summaryrefslogtreecommitdiff
path: root/lib
diff options
context:
space:
mode:
Diffstat (limited to 'lib')
-rw-r--r--lib/Makefile.in55
-rw-r--r--lib/_Noreturn.h43
-rw-r--r--lib/acl-errno-valid.c4
-rw-r--r--lib/acl-internal.c18
-rw-r--r--lib/acl-internal.h26
-rw-r--r--lib/acl.h4
-rw-r--r--lib/acl_entries.c10
-rw-r--r--lib/af_alg.h115
-rw-r--r--lib/alloca.in.h33
-rw-r--r--lib/allocator.c17
-rw-r--r--lib/allocator.h18
-rw-r--r--lib/arg-nonnull.h12
-rw-r--r--lib/at-func.c6
-rw-r--r--lib/attribute.h226
-rw-r--r--lib/binary-io.c32
-rw-r--r--lib/binary-io.h36
-rw-r--r--lib/byteswap.in.h16
-rw-r--r--lib/c++defs.h37
-rw-r--r--lib/c-ctype.c18
-rw-r--r--lib/c-ctype.h22
-rw-r--r--lib/c-strcase.h18
-rw-r--r--lib/c-strcasecmp.c20
-rw-r--r--lib/c-strncasecmp.c20
-rw-r--r--lib/canonicalize-lgpl.c472
-rw-r--r--lib/careadlinkat.c176
-rw-r--r--lib/careadlinkat.h20
-rw-r--r--lib/cdefs.h707
-rw-r--r--lib/cloexec.c20
-rw-r--r--lib/cloexec.h20
-rw-r--r--lib/close-stream.c4
-rw-r--r--lib/close-stream.h18
-rw-r--r--lib/copy-file-range.c67
-rw-r--r--lib/count-leading-zeros.c18
-rw-r--r--lib/count-leading-zeros.h29
-rw-r--r--lib/count-one-bits.c18
-rw-r--r--lib/count-one-bits.h110
-rw-r--r--lib/count-trailing-zeros.c18
-rw-r--r--lib/count-trailing-zeros.h29
-rw-r--r--lib/diffseq.h136
-rw-r--r--lib/dirent.in.h152
-rw-r--r--lib/dirfd.c16
-rw-r--r--lib/dosname.h53
-rw-r--r--lib/dtoastr.c17
-rw-r--r--lib/dtotimespec.c14
-rw-r--r--lib/dup2.c118
-rw-r--r--lib/dynarray.h284
-rw-r--r--lib/eloop-threshold.h83
-rw-r--r--lib/errno.in.h22
-rw-r--r--lib/euidaccess.c36
-rw-r--r--lib/execinfo.c18
-rw-r--r--lib/execinfo.in.h10
-rw-r--r--lib/explicit_bzero.c48
-rw-r--r--lib/faccessat.c67
-rw-r--r--lib/fchmodat.c142
-rw-r--r--lib/fcntl.c579
-rw-r--r--lib/fcntl.in.h107
-rw-r--r--lib/fdatasync.c27
-rw-r--r--lib/fdopendir.c4
-rw-r--r--lib/file-has-acl.c502
-rw-r--r--lib/filemode.c18
-rw-r--r--lib/filemode.h4
-rw-r--r--lib/filename.h112
-rw-r--r--lib/filevercmp.c209
-rw-r--r--lib/filevercmp.h86
-rw-r--r--lib/fingerprint.c66
-rw-r--r--lib/fingerprint.h28
-rw-r--r--lib/flexmember.h35
-rw-r--r--lib/fpending.c15
-rw-r--r--lib/fpending.h4
-rw-r--r--lib/free.c53
-rw-r--r--lib/fstatat.c25
-rw-r--r--lib/fsusage.c72
-rw-r--r--lib/fsusage.h16
-rw-r--r--lib/fsync.c20
-rw-r--r--lib/ftoastr.c33
-rw-r--r--lib/ftoastr.h11
-rw-r--r--lib/futimens.c37
-rw-r--r--lib/get-permissions.c104
-rw-r--r--lib/getdtablesize.c18
-rw-r--r--lib/getgroups.c28
-rw-r--r--lib/getloadavg.c176
-rw-r--r--lib/getopt-cdefs.in.h25
-rw-r--r--lib/getopt-core.h10
-rw-r--r--lib/getopt-ext.h10
-rw-r--r--lib/getopt-pfx-core.h31
-rw-r--r--lib/getopt-pfx-ext.h23
-rw-r--r--lib/getopt.c16
-rw-r--r--lib/getopt.in.h22
-rw-r--r--lib/getopt1.c10
-rw-r--r--lib/getopt_int.h10
-rw-r--r--lib/getrandom.c191
-rw-r--r--lib/gettext.h38
-rw-r--r--lib/gettime.c47
-rw-r--r--lib/gettimeofday.c57
-rw-r--r--lib/gnulib.mk.in2654
-rw-r--r--lib/group-member.c25
-rw-r--r--lib/idx.h134
-rw-r--r--lib/ieee754.in.h222
-rw-r--r--lib/ignore-value.h21
-rw-r--r--lib/intprops-internal.h392
-rw-r--r--lib/intprops.h276
-rw-r--r--lib/inttypes.in.h526
-rw-r--r--lib/lchmod.c94
-rw-r--r--lib/libc-config.h202
-rw-r--r--lib/limits.in.h101
-rw-r--r--lib/localtime-buffer.c58
-rw-r--r--lib/localtime-buffer.h27
-rw-r--r--lib/lstat.c61
-rw-r--r--lib/malloc.c51
-rw-r--r--lib/malloc/dynarray-skeleton.c528
-rw-r--r--lib/malloc/dynarray.h178
-rw-r--r--lib/malloc/dynarray_at_failure.c40
-rw-r--r--lib/malloc/dynarray_emplace_enlarge.c77
-rw-r--r--lib/malloc/dynarray_finalize.c66
-rw-r--r--lib/malloc/dynarray_resize.c68
-rw-r--r--lib/malloc/dynarray_resize_clear.c39
-rw-r--r--lib/malloc/scratch_buffer.h151
-rw-r--r--lib/malloc/scratch_buffer_dupfree.c41
-rw-r--r--lib/malloc/scratch_buffer_grow.c56
-rw-r--r--lib/malloc/scratch_buffer_grow_preserve.c67
-rw-r--r--lib/malloc/scratch_buffer_set_array_size.c64
-rw-r--r--lib/md5-stream.c141
-rw-r--r--lib/md5.c118
-rw-r--r--lib/md5.h46
-rw-r--r--lib/memmem.c71
-rw-r--r--lib/mempcpy.c33
-rw-r--r--lib/memrchr.c18
-rw-r--r--lib/mini-gmp-gnulib.c48
-rw-r--r--lib/mini-gmp.c4619
-rw-r--r--lib/mini-gmp.h310
-rw-r--r--lib/minmax.h18
-rw-r--r--lib/mkostemp.c16
-rw-r--r--lib/mktime-internal.h76
-rw-r--r--lib/mktime.c608
-rw-r--r--lib/nanosleep.c195
-rw-r--r--lib/nproc.c404
-rw-r--r--lib/nproc.h46
-rw-r--r--lib/nstrftime.c399
-rw-r--r--lib/open.c63
-rw-r--r--lib/openat-priv.h4
-rw-r--r--lib/openat-proc.c9
-rw-r--r--lib/openat.h26
-rw-r--r--lib/pathmax.h83
-rw-r--r--lib/pipe2.c27
-rw-r--r--lib/pselect.c22
-rw-r--r--lib/pthread_sigmask.c16
-rw-r--r--lib/putenv.c194
-rw-r--r--lib/qcopy-acl.c4
-rw-r--r--lib/rawmemchr.c125
-rw-r--r--lib/rawmemchr.valgrind28
-rw-r--r--lib/readlink.c66
-rw-r--r--lib/readlinkat.c56
-rw-r--r--lib/realloc.c63
-rw-r--r--lib/regcomp.c3788
-rw-r--r--lib/regex.c84
-rw-r--r--lib/regex.h699
-rw-r--r--lib/regex_internal.c1711
-rw-r--r--lib/regex_internal.h835
-rw-r--r--lib/regexec.c4221
-rw-r--r--lib/root-uid.h20
-rw-r--r--lib/save-cwd.c2
-rw-r--r--lib/save-cwd.h6
-rw-r--r--lib/scratch_buffer.h127
-rw-r--r--lib/set-permissions.c274
-rw-r--r--lib/sha1.c117
-rw-r--r--lib/sha1.h45
-rw-r--r--lib/sha256.c198
-rw-r--r--lib/sha256.h54
-rw-r--r--lib/sha512.c193
-rw-r--r--lib/sha512.h54
-rw-r--r--lib/sig2str.c21
-rw-r--r--lib/sig2str.h4
-rw-r--r--lib/sigdescr_np.c376
-rw-r--r--lib/signal.in.h62
-rw-r--r--lib/stat-time.c18
-rw-r--r--lib/stat-time.h73
-rw-r--r--lib/stdalign.in.h48
-rw-r--r--lib/stdckdint.in.h37
-rw-r--r--lib/stddef.in.h75
-rw-r--r--lib/stdint.in.h102
-rw-r--r--lib/stdio-impl.h100
-rw-r--r--lib/stdio.in.h732
-rw-r--r--lib/stdlib.in.h722
-rw-r--r--lib/stpcpy.c16
-rw-r--r--lib/str-two-way.h452
-rw-r--r--lib/strftime.h25
-rw-r--r--lib/string.in.h391
-rw-r--r--lib/strnlen.c30
-rw-r--r--lib/strtoimax.c38
-rw-r--r--lib/strtol.c86
-rw-r--r--lib/strtoll.c16
-rw-r--r--lib/symlink.c22
-rw-r--r--lib/sys_random.in.h98
-rw-r--r--lib/sys_select.in.h50
-rw-r--r--lib/sys_stat.in.h262
-rw-r--r--lib/sys_time.in.h26
-rw-r--r--lib/sys_types.in.h33
-rw-r--r--lib/tempname.c390
-rw-r--r--lib/tempname.h25
-rw-r--r--lib/time-internal.h20
-rw-r--r--lib/time.in.h172
-rw-r--r--lib/time_r.c18
-rw-r--r--lib/time_rz.c114
-rw-r--r--lib/timegm.c64
-rw-r--r--lib/timespec-add.c30
-rw-r--r--lib/timespec-sub.c30
-rw-r--r--lib/timespec.c18
-rw-r--r--lib/timespec.h76
-rw-r--r--lib/u64.c18
-rw-r--r--lib/u64.h16
-rw-r--r--lib/unistd.c18
-rw-r--r--lib/unistd.in.h885
-rw-r--r--lib/unlocked-io.h30
-rw-r--r--lib/utimens.c56
-rw-r--r--lib/utimens.h16
-rw-r--r--lib/utimensat.c217
-rw-r--r--lib/verify.h161
-rw-r--r--lib/vla.h30
-rw-r--r--lib/warn-on-use.h122
-rw-r--r--lib/xalloc-oversized.h55
220 files changed, 33598 insertions, 6124 deletions
diff --git a/lib/Makefile.in b/lib/Makefile.in
index 1f5b154f355..8b950136241 100644
--- a/lib/Makefile.in
+++ b/lib/Makefile.in
@@ -1,6 +1,6 @@
### @configure_input@
-# Copyright 2017 Free Software Foundation, Inc.
+# Copyright 2017-2022 Free Software Foundation, Inc.
# This file is part of GNU Emacs.
@@ -29,26 +29,9 @@ top_srcdir = @top_srcdir@
all:
.PHONY: all
-# 'make' verbosity.
-AM_V_AR = $(am__v_AR_@AM_V@)
-am__v_AR_ = $(am__v_AR_@AM_DEFAULT_V@)
-am__v_AR_0 = @echo " AR " $@;
-am__v_AR_1 =
+-include ${top_builddir}/src/verbose.mk
-AM_V_CC = $(am__v_CC_@AM_V@)
-am__v_CC_ = $(am__v_CC_@AM_DEFAULT_V@)
-am__v_CC_0 = @echo " CC " $@;
-am__v_CC_1 =
-
-AM_V_GEN = $(am__v_GEN_@AM_V@)
-am__v_GEN_ = $(am__v_GEN_@AM_DEFAULT_V@)
-am__v_GEN_0 = @echo " GEN " $@;
-am__v_GEN_1 =
-
-AM_V_at = $(am__v_at_@AM_V@)
-am__v_at_ = $(am__v_at_@AM_DEFAULT_V@)
-am__v_at_0 = @
-am__v_at_1 =
+HAVE_NATIVE_COMP = @HAVE_NATIVE_COMP@
ALL_CFLAGS= \
$(C_SWITCH_SYSTEM) $(C_SWITCH_MACHINE) $(DEPFLAGS) \
@@ -56,6 +39,10 @@ ALL_CFLAGS= \
-I. -I../src -I$(srcdir) -I$(srcdir)/../src \
$(if $(patsubst e-%,,$(notdir $<)),,-Demacs)
+ifeq ($(HAVE_NATIVE_COMP),yes)
+ALL_CFLAGS += -DGL_COMPILE_CRYPTO_STREAM
+endif
+
SYSTEM_TYPE = @SYSTEM_TYPE@
ifeq ($(SYSTEM_TYPE),windows-nt)
include $(srcdir)/../nt/gnulib-cfg.mk
@@ -77,29 +64,37 @@ endif
../config.status: $(top_srcdir)/configure.ac $(top_srcdir)/m4/*.m4
$(MAKE) -C .. $(notdir $@)
Makefile: ../config.status $(srcdir)/Makefile.in
- $(MAKE) -C .. src/$@
+ $(MAKE) -C .. lib/$@
+
+# Object modules that need not be built for Emacs.
+# Emacs does not need e-regex.o (it has its own regex-emacs.c),
+# and building it would just waste time.
+# Emacs also doesn't need the dynarray-related files in malloc/ and
+# the replacement 'free'.
+not_emacs_OBJECTS = regex.o malloc/%.o free.o
-libgnu_a_OBJECTS = $(gl_LIBOBJS) \
+libgnu_a_OBJECTS = fingerprint.o $(gl_LIBOBJS) \
$(patsubst %.c,%.o,$(filter %.c,$(libgnu_a_SOURCES)))
-libegnu_a_OBJECTS = $(patsubst %.o,e-%.o,$(libgnu_a_OBJECTS))
+for_emacs_OBJECTS = $(filter-out $(not_emacs_OBJECTS),$(libgnu_a_OBJECTS))
+libegnu_a_OBJECTS = $(patsubst %.o,e-%.o,$(for_emacs_OBJECTS))
$(libegnu_a_OBJECTS) $(libgnu_a_OBJECTS): $(BUILT_SOURCES)
.c.o:
- $(AM_V_CC)$(CC) -c $(CPPFLAGS) $(ALL_CFLAGS) $<
+ $(AM_V_CC)$(CC) -c $(CPPFLAGS) $(ALL_CFLAGS) -o $@ $<
e-%.o: %.c
$(AM_V_CC)$(CC) -c $(CPPFLAGS) $(ALL_CFLAGS) -Demacs -o $@ $<
all: libgnu.a $(if $(HYBRID_MALLOC),libegnu.a)
libgnu.a: $(libgnu_a_OBJECTS)
- $(AM_V_at)rm -f $@
- $(AM_V_AR)$(AR) $(ARFLAGS) $@ $(libgnu_a_OBJECTS)
+ $(AM_V_AR)rm -f $@
+ $(AM_V_at)$(AR) $(ARFLAGS) $@ $(libgnu_a_OBJECTS)
$(AM_V_at)$(RANLIB) $@
libegnu.a: $(libegnu_a_OBJECTS)
- $(AM_V_at)rm -f $@
- $(AM_V_AR)$(AR) $(ARFLAGS) $@ $(libegnu_a_OBJECTS)
+ $(AM_V_AR)rm -f $@
+ $(AM_V_at)$(AR) $(ARFLAGS) $@ $(libegnu_a_OBJECTS)
$(AM_V_at)$(RANLIB) $@
ETAGS = ../lib-src/etags$(EXEEXT)
@@ -112,7 +107,7 @@ TAGS: $(ETAGS) $(tagsfiles)
.PHONY: $(ETAGS) tags
clean:
- rm -f *.[ao] *-t \#* $(DEPDIR)/*
+ rm -f ./*.[ao] ./*/*.o ./*-t \#* $(DEPDIR)/*.d $(DEPDIR)/*/*.d
mostlyclean: clean
rm -f $(filter-out %-t,$(MOSTLYCLEANFILES))
distclean bootstrap-clean: mostlyclean
@@ -120,6 +115,8 @@ distclean bootstrap-clean: mostlyclean
rm -fr $(DEPDIR)
maintainer-clean: distclean
rm -f TAGS gnulib.mk
+ -rmdir malloc sys 2>/dev/null || true
+
.PHONY: mostlyclean clean distclean bootstrap-clean maintainer-clean
# Tell versions [3.59,3.63) of GNU make to not export all variables.
diff --git a/lib/_Noreturn.h b/lib/_Noreturn.h
index c44ad89b7c0..e914627a887 100644
--- a/lib/_Noreturn.h
+++ b/lib/_Noreturn.h
@@ -1,8 +1,43 @@
-#if !defined _Noreturn && __STDC_VERSION__ < 201112
-# if (3 <= __GNUC__ || (__GNUC__ == 2 && 8 <= __GNUC_MINOR__) \
- || 0x5110 <= __SUNPRO_C)
+/* A C macro for declaring that a function does not return.
+ Copyright (C) 2011-2022 Free Software Foundation, Inc.
+
+ This program is free software: you can redistribute it and/or modify it
+ under the terms of the GNU Lesser General Public License as published
+ by the Free Software Foundation; either version 2 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
+ Lesser General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public License
+ along with this program. If not, see <https://www.gnu.org/licenses/>. */
+
+#ifndef _Noreturn
+# 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 ((!defined __cplusplus || defined __clang__) \
+ && (201112 <= (defined __STDC_VERSION__ ? __STDC_VERSION__ : 0) \
+ || (!defined __STRICT_ANSI__ \
+ && (4 < __GNUC__ + (7 <= __GNUC_MINOR__) \
+ || (defined __apple_build_version__ \
+ ? 6000000 <= __apple_build_version__ \
+ : 3 < __clang_major__ + (5 <= __clang_minor__))))))
+ /* _Noreturn works as-is. */
+# elif (2 < __GNUC__ + (8 <= __GNUC_MINOR__) || defined __clang__ \
+ || 0x5110 <= __SUNPRO_C)
# define _Noreturn __attribute__ ((__noreturn__))
-# elif 1200 <= _MSC_VER
+# elif 1200 <= (defined _MSC_VER ? _MSC_VER : 0)
# define _Noreturn __declspec (noreturn)
# else
# define _Noreturn
diff --git a/lib/acl-errno-valid.c b/lib/acl-errno-valid.c
index 1e96974dd12..a364e413256 100644
--- a/lib/acl-errno-valid.c
+++ b/lib/acl-errno-valid.c
@@ -1,10 +1,10 @@
/* Test whether ACLs are well supported on this system.
- Copyright 2013-2017 Free Software Foundation, Inc.
+ Copyright 2013-2022 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
+ 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,
diff --git a/lib/acl-internal.c b/lib/acl-internal.c
index 63e6b6b997c..be244c67a2a 100644
--- a/lib/acl-internal.c
+++ b/lib/acl-internal.c
@@ -1,10 +1,10 @@
/* Test whether a file has a nontrivial ACL. -*- coding: utf-8 -*-
- Copyright (C) 2002-2003, 2005-2017 Free Software Foundation, Inc.
+ Copyright (C) 2002-2003, 2005-2022 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
+ 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,
@@ -23,7 +23,7 @@
#include "acl-internal.h"
-#if USE_ACL && HAVE_ACL_GET_FILE
+#if USE_ACL && HAVE_ACL_GET_FILE /* Linux, FreeBSD, Mac OS X, IRIX, Tru64, Cygwin >= 2.5 */
# if HAVE_ACL_TYPE_EXTENDED /* Mac OS X */
@@ -37,7 +37,7 @@ acl_extended_nontrivial (acl_t acl)
return (acl_entries (acl) > 0);
}
-# else /* Linux, FreeBSD, IRIX, Tru64 */
+# else /* Linux, FreeBSD, IRIX, Tru64, Cygwin >= 2.5 */
/* ACL is an ACL, from a file, stored as type ACL_TYPE_ACCESS.
Return 1 if the given ACL is non-trivial.
@@ -51,7 +51,7 @@ acl_access_nontrivial (acl_t acl)
at least, allowing us to write
return (3 < acl_entries (acl));
but the following code is more robust. */
-# if HAVE_ACL_FIRST_ENTRY /* Linux, FreeBSD */
+# if HAVE_ACL_FIRST_ENTRY /* Linux, FreeBSD, Cygwin >= 2.5 */
acl_entry_t ace;
int got_one;
@@ -124,7 +124,7 @@ acl_default_nontrivial (acl_t acl)
# endif
-#elif USE_ACL && HAVE_FACL && defined GETACL /* Solaris, Cygwin, not HP-UX */
+#elif USE_ACL && HAVE_FACL && defined GETACL /* Solaris, Cygwin < 2.5, not HP-UX */
/* Test an ACL retrieved with GETACL.
Return 1 if the given ACL, consisting of COUNT entries, is non-trivial.
@@ -355,7 +355,7 @@ acl_nontrivial (int count, struct acl_entry *entries)
struct acl_entry *ace = &entries[i];
if (ace->uid != ACL_NSUSER && ace->gid != ACL_NSGROUP)
- return 1;
+ return 1;
}
return 0;
}
@@ -479,7 +479,7 @@ void
free_permission_context (struct permission_context *ctx)
{
#if USE_ACL
-# if HAVE_ACL_GET_FILE /* Linux, FreeBSD, Mac OS X, IRIX, Tru64 */
+# if HAVE_ACL_GET_FILE /* Linux, FreeBSD, Mac OS X, IRIX, Tru64, Cygwin >= 2.5 */
if (ctx->acl)
acl_free (ctx->acl);
# if !HAVE_ACL_TYPE_EXTENDED
@@ -487,7 +487,7 @@ free_permission_context (struct permission_context *ctx)
acl_free (ctx->default_acl);
# endif
-# elif defined GETACL /* Solaris, Cygwin */
+# elif defined GETACL /* Solaris, Cygwin < 2.5 */
free (ctx->entries);
# ifdef ACE_GETACL
free (ctx->ace_entries);
diff --git a/lib/acl-internal.h b/lib/acl-internal.h
index ebd24217bb6..93533762dd0 100644
--- a/lib/acl-internal.h
+++ b/lib/acl-internal.h
@@ -1,10 +1,10 @@
/* Internal implementation of access control lists. -*- coding: utf-8 -*-
- Copyright (C) 2002-2003, 2005-2017 Free Software Foundation, Inc.
+ Copyright (C) 2002-2003, 2005-2022 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
+ 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,
@@ -30,7 +30,8 @@
# define GETACLCNT ACL_CNT
#endif
-/* On Linux, additional ACL related API is available in <acl/libacl.h>. */
+/* On Linux and Cygwin >= 2.5, additional ACL related API is available in
+ <acl/libacl.h>. */
#ifdef HAVE_ACL_LIBACL_H
# include <acl/libacl.h>
#endif
@@ -72,7 +73,7 @@ _GL_INLINE_HEADER_BEGIN
# if HAVE_ACL_GET_FILE
/* POSIX 1003.1e (draft 17 -- abandoned) specific version. */
-/* Linux, FreeBSD, Mac OS X, IRIX, Tru64 */
+/* Linux, FreeBSD, Mac OS X, IRIX, Tru64, Cygwin >= 2.5 */
# ifndef MIN_ACL_ENTRIES
# define MIN_ACL_ENTRIES 4
@@ -122,7 +123,10 @@ rpl_acl_set_fd (int fd, acl_t acl)
# endif
/* Linux-specific */
-# ifndef HAVE_ACL_EXTENDED_FILE
+/* Cygwin >= 2.5 implements this function, but it returns 1 for all
+ directories, thus is unusable. */
+# if !defined HAVE_ACL_EXTENDED_FILE || defined __CYGWIN__
+# undef HAVE_ACL_EXTENDED_FILE
# define HAVE_ACL_EXTENDED_FILE false
# define acl_extended_file(name) (-1)
# endif
@@ -163,7 +167,7 @@ extern int acl_access_nontrivial (acl_t);
extern int acl_default_nontrivial (acl_t);
# endif
-# elif HAVE_FACL && defined GETACL /* Solaris, Cygwin, not HP-UX */
+# elif HAVE_FACL && defined GETACL /* Solaris, Cygwin < 2.5, not HP-UX */
/* Set to 0 if a file's mode is stored independently from the ACL. */
# if defined __CYGWIN__ /* Cygwin */
@@ -256,14 +260,14 @@ extern int acl_nontrivial (int count, struct acl *entries);
struct permission_context {
mode_t mode;
#if USE_ACL
-# if HAVE_ACL_GET_FILE /* Linux, FreeBSD, Mac OS X, IRIX, Tru64 */
+# if HAVE_ACL_GET_FILE /* Linux, FreeBSD, Mac OS X, IRIX, Tru64, Cygwin >= 2.5 */
acl_t acl;
# if !HAVE_ACL_TYPE_EXTENDED
acl_t default_acl;
# endif
bool acls_not_supported;
-# elif defined GETACL /* Solaris, Cygwin */
+# elif defined GETACL /* Solaris, Cygwin < 2.5 */
int count;
aclent_t *entries;
# ifdef ACE_GETACL
@@ -293,10 +297,6 @@ struct permission_context {
int get_permissions (const char *, int, mode_t, struct permission_context *);
int set_permissions (struct permission_context *, const char *, int);
-void free_permission_context (struct permission_context *)
-#if ! (defined USE_ACL && (HAVE_ACL_GET_FILE || defined GETACL))
- _GL_ATTRIBUTE_CONST
-#endif
- ;
+void free_permission_context (struct permission_context *);
_GL_INLINE_HEADER_END
diff --git a/lib/acl.h b/lib/acl.h
index d3b048022e3..f4d0df80618 100644
--- a/lib/acl.h
+++ b/lib/acl.h
@@ -1,10 +1,10 @@
/* acl.c - access control lists
- Copyright (C) 2002, 2008-2017 Free Software Foundation, Inc.
+ Copyright (C) 2002, 2008-2022 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
+ 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,
diff --git a/lib/acl_entries.c b/lib/acl_entries.c
index c7efaefd52f..677de23e0cb 100644
--- a/lib/acl_entries.c
+++ b/lib/acl_entries.c
@@ -1,10 +1,10 @@
/* Return the number of entries in an ACL.
- Copyright (C) 2002-2003, 2005-2017 Free Software Foundation, Inc.
+ Copyright (C) 2002-2003, 2005-2022 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
+ 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,
@@ -22,7 +22,7 @@
#include "acl-internal.h"
/* This file assumes POSIX-draft like ACLs
- (Linux, FreeBSD, Mac OS X, IRIX, Tru64). */
+ (Linux, FreeBSD, Mac OS X, IRIX, Tru64, Cygwin >= 2.5). */
/* Return the number of entries in ACL.
Return -1 and set errno upon failure to determine it. */
@@ -34,7 +34,7 @@ acl_entries (acl_t acl)
if (acl != NULL)
{
-#if HAVE_ACL_FIRST_ENTRY /* Linux, FreeBSD, Mac OS X */
+#if HAVE_ACL_FIRST_ENTRY /* Linux, FreeBSD, Mac OS X, Cygwin >= 2.5 */
# if HAVE_ACL_TYPE_EXTENDED /* Mac OS X */
/* acl_get_entry returns 0 when it successfully fetches an entry,
and -1/EINVAL at the end. */
@@ -45,7 +45,7 @@ acl_entries (acl_t acl)
got_one >= 0;
got_one = acl_get_entry (acl, ACL_NEXT_ENTRY, &ace))
count++;
-# else /* Linux, FreeBSD */
+# else /* Linux, FreeBSD, Cygwin >= 2.5 */
/* acl_get_entry returns 1 when it successfully fetches an entry,
and 0 at the end. */
acl_entry_t ace;
diff --git a/lib/af_alg.h b/lib/af_alg.h
new file mode 100644
index 00000000000..ddd6568b8e3
--- /dev/null
+++ b/lib/af_alg.h
@@ -0,0 +1,115 @@
+/* af_alg.h - Compute message digests from file streams and buffers.
+ Copyright (C) 2018-2022 Free Software Foundation, Inc.
+
+ This file is free software: you can redistribute it and/or modify
+ it under the terms of the GNU Lesser General Public License as
+ published by the Free Software Foundation; either version 2.1 of the
+ License, or (at your option) any later version.
+
+ This file 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 Lesser General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public License
+ along with this program. If not, see <https://www.gnu.org/licenses/>. */
+
+/* Written by Matteo Croce <mcroce@redhat.com>, 2018.
+ Documentation by Bruno Haible <bruno@clisp.org>, 2018. */
+
+/* Declare specific functions for computing message digests
+ using the Linux kernel crypto API, if available. This kernel API gives
+ access to specialized crypto instructions (that would also be available
+ in user space) or to crypto devices (not directly available in user space).
+
+ For a more complete set of facilities that use the Linux kernel crypto API,
+ look at libkcapi. */
+
+#ifndef AF_ALG_H
+# define AF_ALG_H 1
+
+# include <stdio.h>
+# include <errno.h>
+
+# ifdef __cplusplus
+extern "C" {
+# endif
+
+# if USE_LINUX_CRYPTO_API
+
+/* Compute a message digest of a memory region.
+
+ The memory region starts at BUFFER and is LEN bytes long.
+
+ ALG is the message digest algorithm; see the file /proc/crypto.
+
+ RESBLOCK points to a block of HASHLEN bytes, for the result.
+ HASHLEN must be the length of the message digest, in bytes, in particular:
+
+ alg | hashlen
+ -------+--------
+ md5 | 16
+ sha1 | 20
+ sha224 | 28
+ sha256 | 32
+ sha384 | 48
+ sha512 | 64
+
+ If successful, fill RESBLOCK and return 0.
+ Upon failure, return a negated error number. */
+int
+afalg_buffer (const char *buffer, size_t len, const char *alg,
+ void *resblock, ssize_t hashlen);
+
+/* Compute a message digest of data read from STREAM.
+
+ STREAM is an open file stream. The last operation on STREAM should
+ not be 'ungetc', and if STREAM is also open for writing it should
+ have been fflushed since its last write. Read from the current
+ position to the end of STREAM. Handle regular files efficiently.
+
+ ALG is the message digest algorithm; see the file /proc/crypto.
+
+ RESBLOCK points to a block of HASHLEN bytes, for the result.
+ HASHLEN must be the length of the message digest, in bytes, in particular:
+
+ alg | hashlen
+ -------+--------
+ md5 | 16
+ sha1 | 20
+ sha224 | 28
+ sha256 | 32
+ sha384 | 48
+ sha512 | 64
+
+ If successful, fill RESBLOCK and return 0.
+ Upon failure, return a negated error number.
+ Unless returning 0 or -EIO, restore STREAM's file position so that
+ the caller can fall back on some other method. */
+int
+afalg_stream (FILE *stream, const char *alg,
+ void *resblock, ssize_t hashlen);
+
+# else
+
+static inline int
+afalg_buffer (const char *buffer, size_t len, const char *alg,
+ void *resblock, ssize_t hashlen)
+{
+ return -EAFNOSUPPORT;
+}
+
+static inline int
+afalg_stream (FILE *stream, const char *alg,
+ void *resblock, ssize_t hashlen)
+{
+ return -EAFNOSUPPORT;
+}
+
+# endif
+
+# ifdef __cplusplus
+}
+# endif
+
+#endif /* AF_ALG_H */
diff --git a/lib/alloca.in.h b/lib/alloca.in.h
index 1881e74f5dc..e2b146138d7 100644
--- a/lib/alloca.in.h
+++ b/lib/alloca.in.h
@@ -1,22 +1,20 @@
/* Memory allocation on the stack.
- Copyright (C) 1995, 1999, 2001-2004, 2006-2017 Free Software Foundation,
+ Copyright (C) 1995, 1999, 2001-2004, 2006-2022 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 file is free software: you can redistribute it and/or modify
+ it under the terms of the GNU Lesser General Public License as
+ published by the Free Software Foundation; either version 2.1 of the
+ License, or (at your option) any later version.
- This program is distributed in the hope that it will be useful,
+ This file is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- General Public License for more details.
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU Lesser General Public License for more details.
- You should have received a copy of the GNU General Public
- License along with this program; if not, see
- <https://www.gnu.org/licenses/>.
- */
+ You should have received a copy of the GNU Lesser General Public License
+ along with this program. If not, see <https://www.gnu.org/licenses/>. */
/* Avoid using the symbol _ALLOCA_H here, as Bison assumes _ALLOCA_H
means there is a real alloca function. */
@@ -35,7 +33,16 @@
*/
#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 needed. */
+# if defined __GNUC__ && (defined _WIN32 && ! defined __CYGWIN__) && @HAVE_ALLOCA_H@
+# include_next <alloca.h>
+# endif
+#endif
+#ifndef alloca
+# if defined __GNUC__ || (__clang_major__ >= 4)
# define alloca __builtin_alloca
# elif defined _AIX
# define alloca __alloca
diff --git a/lib/allocator.c b/lib/allocator.c
index 2c1a3da03aa..42c891805d1 100644
--- a/lib/allocator.c
+++ b/lib/allocator.c
@@ -1,3 +1,20 @@
+/* Memory allocators such as malloc+free.
+
+ Copyright (C) 2011-2022 Free Software Foundation, Inc.
+
+ This file is free software: you can redistribute it and/or modify
+ it under the terms of the GNU Lesser General Public License as
+ published by the Free Software Foundation; either version 2.1 of the
+ License, or (at your option) any later version.
+
+ This file 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 Lesser General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public License
+ along with this program. If not, see <https://www.gnu.org/licenses/>. */
+
#define _GL_USE_STDLIB_ALLOC 1
#include <config.h>
#include "allocator.h"
diff --git a/lib/allocator.h b/lib/allocator.h
index 8f79d7435c3..3e698ced83a 100644
--- a/lib/allocator.h
+++ b/lib/allocator.h
@@ -1,18 +1,18 @@
/* Memory allocators such as malloc+free.
- Copyright (C) 2011-2017 Free Software Foundation, Inc.
+ Copyright (C) 2011-2022 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 file is free software: you can redistribute it and/or modify
+ it under the terms of the GNU Lesser General Public License as
+ published by the Free Software Foundation; either version 2.1 of the
+ License, or (at your option) any later version.
- This program is distributed in the hope that it will be useful,
+ This file 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.
+ GNU Lesser General Public License for more details.
- You should have received a copy of the GNU General Public License
+ You should have received a copy of the GNU Lesser General Public License
along with this program. If not, see <https://www.gnu.org/licenses/>. */
/* Written by Paul Eggert. */
@@ -29,7 +29,7 @@ struct allocator
/* Do not use GCC attributes such as __attribute__ ((malloc)) with
the function types pointed at by these members, because these
attributes do not work with pointers to functions. See
- <https://lists.gnu.org/archive/html/bug-gnulib/2011-04/msg00007.html>. */
+ <https://lists.gnu.org/r/bug-gnulib/2011-04/msg00007.html>. */
/* Call ALLOCATE to allocate memory, like 'malloc'. On failure ALLOCATE
should return NULL, though not necessarily set errno. When given
diff --git a/lib/arg-nonnull.h b/lib/arg-nonnull.h
index 61ee0712747..e4513efe955 100644
--- a/lib/arg-nonnull.h
+++ b/lib/arg-nonnull.h
@@ -1,24 +1,24 @@
/* A C macro for declaring that specific arguments must not be NULL.
- Copyright (C) 2009-2017 Free Software Foundation, Inc.
+ Copyright (C) 2009-2022 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
+ under the terms of the GNU Lesser General Public License as published
+ by the Free Software Foundation; either version 2 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.
+ Lesser General Public License for more details.
- You should have received a copy of the GNU General Public License
+ You should have received a copy of the GNU Lesser General Public License
along with this program. If not, see <https://www.gnu.org/licenses/>. */
/* _GL_ARG_NONNULL((n,...,m)) tells the compiler and static analyzer tools
that the values passed as arguments n, ..., m must be non-NULL pointers.
n = 1 stands for the first argument, n = 2 for the second argument etc. */
#ifndef _GL_ARG_NONNULL
-# if (__GNUC__ == 3 && __GNUC_MINOR__ >= 3) || __GNUC__ > 3
+# if __GNUC__ > 3 || (__GNUC__ == 3 && __GNUC_MINOR__ >= 3) || defined __clang__
# define _GL_ARG_NONNULL(params) __attribute__ ((__nonnull__ params))
# else
# define _GL_ARG_NONNULL(params)
diff --git a/lib/at-func.c b/lib/at-func.c
index 2a3e375e9a2..afcc819beb0 100644
--- a/lib/at-func.c
+++ b/lib/at-func.c
@@ -1,9 +1,9 @@
/* Define at-style functions like fstatat, unlinkat, fchownat, etc.
- Copyright (C) 2006, 2009-2017 Free Software Foundation, Inc.
+ Copyright (C) 2006, 2009-2022 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
+ 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,
@@ -16,7 +16,7 @@
/* written by Jim Meyering */
-#include "dosname.h" /* solely for definition of IS_ABSOLUTE_FILE_NAME */
+#include "filename.h" /* solely for definition of IS_ABSOLUTE_FILE_NAME */
#ifdef GNULIB_SUPPORT_ONLY_AT_FDCWD
# include <errno.h>
diff --git a/lib/attribute.h b/lib/attribute.h
new file mode 100644
index 00000000000..378d4f0a80e
--- /dev/null
+++ b/lib/attribute.h
@@ -0,0 +1,226 @@
+/* ATTRIBUTE_* macros for using attributes in GCC and similar compilers
+
+ Copyright 2020-2022 Free Software Foundation, Inc.
+
+ This file is free software: you can redistribute it and/or modify
+ it under the terms of the GNU Lesser General Public License as
+ published by the Free Software Foundation; either version 2.1 of the
+ License, or (at your option) any later version.
+
+ This file 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 Lesser General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public License
+ along with this program. If not, see <https://www.gnu.org/licenses/>. */
+
+/* Written by Paul Eggert. */
+
+/* Provide public ATTRIBUTE_* names for the private _GL_ATTRIBUTE_*
+ macros used within Gnulib. */
+
+/* These attributes can be placed in two ways:
+ - At the start of a declaration (i.e. even before storage-class
+ specifiers!); then they apply to all entities that are declared
+ by the declaration.
+ - Immediately after the name of an entity being declared by the
+ declaration; then they apply to that entity only. */
+
+#ifndef _GL_ATTRIBUTE_H
+#define _GL_ATTRIBUTE_H
+
+
+/* This file defines two types of attributes:
+ * C2x standard attributes. These have macro names that do not begin with
+ 'ATTRIBUTE_'.
+ * Selected GCC attributes; see:
+ https://gcc.gnu.org/onlinedocs/gcc/Common-Function-Attributes.html
+ https://gcc.gnu.org/onlinedocs/gcc/Common-Variable-Attributes.html
+ https://gcc.gnu.org/onlinedocs/gcc/Common-Type-Attributes.html
+ These names begin with 'ATTRIBUTE_' to avoid name clashes. */
+
+
+/* =============== Attributes for specific kinds of functions =============== */
+
+/* Attributes for functions that should not be used. */
+
+/* Warn if the entity is used. */
+/* Applies to:
+ - function, variable,
+ - struct, union, struct/union member,
+ - enumeration, enumeration item,
+ - typedef,
+ in C++ also: namespace, class, template specialization. */
+#define DEPRECATED _GL_ATTRIBUTE_DEPRECATED
+
+/* If a function call is not optimized way, warn with MSG. */
+/* Applies to: functions. */
+#define ATTRIBUTE_WARNING(msg) _GL_ATTRIBUTE_WARNING (msg)
+
+/* If a function call is not optimized way, report an error with MSG. */
+/* Applies to: functions. */
+#define ATTRIBUTE_ERROR(msg) _GL_ATTRIBUTE_ERROR (msg)
+
+
+/* Attributes for memory-allocating functions. */
+
+/* The function returns a pointer to freshly allocated memory. */
+/* Applies to: functions. */
+#define ATTRIBUTE_MALLOC _GL_ATTRIBUTE_MALLOC
+
+/* ATTRIBUTE_ALLOC_SIZE ((N)) - The Nth argument of the function
+ is the size of the returned memory block.
+ ATTRIBUTE_ALLOC_SIZE ((M, N)) - Multiply the Mth and Nth arguments
+ to determine the size of the returned memory block. */
+/* Applies to: function, pointer to function, function types. */
+#define ATTRIBUTE_ALLOC_SIZE(args) _GL_ATTRIBUTE_ALLOC_SIZE (args)
+
+/* ATTRIBUTE_DEALLOC (F, I) declares that the function returns pointers
+ that can be freed by passing them as the Ith argument to the
+ function F.
+ ATTRIBUTE_DEALLOC_FREE declares that the function returns pointers that
+ can be freed via 'free'; it can be used only after declaring 'free'. */
+/* Applies to: functions. Cannot be used on inline functions. */
+#define ATTRIBUTE_DEALLOC(f, i) _GL_ATTRIBUTE_DEALLOC(f, i)
+#define ATTRIBUTE_DEALLOC_FREE _GL_ATTRIBUTE_DEALLOC_FREE
+
+/* Attributes for variadic functions. */
+
+/* The variadic function expects a trailing NULL argument.
+ ATTRIBUTE_SENTINEL () - The last argument is NULL (requires C99).
+ ATTRIBUTE_SENTINEL ((N)) - The (N+1)st argument from the end is NULL. */
+/* Applies to: functions. */
+#define ATTRIBUTE_SENTINEL(pos) _GL_ATTRIBUTE_SENTINEL (pos)
+
+
+/* ================== Attributes for compiler diagnostics ================== */
+
+/* Attributes that help the compiler diagnose programmer mistakes.
+ Some of them may also help for some compiler optimizations. */
+
+/* ATTRIBUTE_FORMAT ((ARCHETYPE, STRING-INDEX, FIRST-TO-CHECK)) -
+ The STRING-INDEXth function argument is a format string of style
+ ARCHETYPE, which is one of:
+ printf, gnu_printf
+ scanf, gnu_scanf,
+ strftime, gnu_strftime,
+ strfmon,
+ or the same thing prefixed and suffixed with '__'.
+ If FIRST-TO-CHECK is not 0, arguments starting at FIRST-TO_CHECK
+ are suitable for the format string. */
+/* Applies to: functions. */
+#define ATTRIBUTE_FORMAT(spec) _GL_ATTRIBUTE_FORMAT (spec)
+
+/* ATTRIBUTE_NONNULL ((N1, N2,...)) - Arguments N1, N2,... must not be NULL.
+ ATTRIBUTE_NONNULL () - All pointer arguments must not be null. */
+/* Applies to: functions. */
+#define ATTRIBUTE_NONNULL(args) _GL_ATTRIBUTE_NONNULL (args)
+
+/* The function's return value is a non-NULL pointer. */
+/* Applies to: functions. */
+#define ATTRIBUTE_RETURNS_NONNULL _GL_ATTRIBUTE_RETURNS_NONNULL
+
+/* Warn if the caller does not use the return value,
+ unless the caller uses something like ignore_value. */
+/* Applies to: function, enumeration, class. */
+#define NODISCARD _GL_ATTRIBUTE_NODISCARD
+
+
+/* Attributes that disable false alarms when the compiler diagnoses
+ programmer "mistakes". */
+
+/* Do not warn if the entity is not used. */
+/* Applies to:
+ - function, variable,
+ - struct, union, struct/union member,
+ - enumeration, enumeration item,
+ - typedef,
+ in C++ also: class. */
+#define MAYBE_UNUSED _GL_ATTRIBUTE_MAYBE_UNUSED
+
+/* The contents of a character array is not meant to be NUL-terminated. */
+/* Applies to: struct/union members and variables that are arrays of element
+ type '[[un]signed] char'. */
+#define ATTRIBUTE_NONSTRING _GL_ATTRIBUTE_NONSTRING
+
+/* Do not warn if control flow falls through to the immediately
+ following 'case' or 'default' label. */
+/* Applies to: Empty statement (;), inside a 'switch' statement. */
+#define FALLTHROUGH _GL_ATTRIBUTE_FALLTHROUGH
+
+
+/* ================== Attributes for debugging information ================== */
+
+/* Attributes regarding debugging information emitted by the compiler. */
+
+/* Omit the function from stack traces when debugging. */
+/* Applies to: function. */
+#define ATTRIBUTE_ARTIFICIAL _GL_ATTRIBUTE_ARTIFICIAL
+
+/* Make the entity visible to debuggers etc., even with '-fwhole-program'. */
+/* Applies to: functions, variables. */
+#define ATTRIBUTE_EXTERNALLY_VISIBLE _GL_ATTRIBUTE_EXTERNALLY_VISIBLE
+
+
+/* ========== Attributes that mainly direct compiler optimizations ========== */
+
+/* The function does not throw exceptions. */
+/* Applies to: functions. */
+#define ATTRIBUTE_NOTHROW _GL_ATTRIBUTE_NOTHROW
+
+/* Do not inline the function. */
+/* Applies to: functions. */
+#define ATTRIBUTE_NOINLINE _GL_ATTRIBUTE_NOINLINE
+
+/* Always inline the function, and report an error if the compiler
+ cannot inline. */
+/* Applies to: function. */
+#define ATTRIBUTE_ALWAYS_INLINE _GL_ATTRIBUTE_ALWAYS_INLINE
+
+/* It is OK for a compiler to omit duplicate calls with the same arguments.
+ This attribute is safe for a function that neither depends on
+ nor affects observable state, and always returns exactly once -
+ e.g., does not loop forever, and does not call longjmp.
+ (This attribute is stricter than ATTRIBUTE_PURE.) */
+/* Applies to: functions. */
+#define ATTRIBUTE_CONST _GL_ATTRIBUTE_CONST
+
+/* It is OK for a compiler to omit duplicate calls with the same
+ arguments if observable state is not changed between calls.
+ This attribute is safe for a function that does not affect
+ observable state, and always returns exactly once.
+ (This attribute is looser than ATTRIBUTE_CONST.) */
+/* Applies to: functions. */
+#define ATTRIBUTE_PURE _GL_ATTRIBUTE_PURE
+
+/* The function is rarely executed. */
+/* Applies to: functions. */
+#define ATTRIBUTE_COLD _GL_ATTRIBUTE_COLD
+
+/* If called from some other compilation unit, the function executes
+ code from that unit only by return or by exception handling,
+ letting the compiler optimize that unit more aggressively. */
+/* Applies to: functions. */
+#define ATTRIBUTE_LEAF _GL_ATTRIBUTE_LEAF
+
+/* For struct members: The member has the smallest possible alignment.
+ For struct, union, class: All members have the smallest possible alignment,
+ minimizing the memory required. */
+/* Applies to: struct members, struct, union,
+ in C++ also: class. */
+#define ATTRIBUTE_PACKED _GL_ATTRIBUTE_PACKED
+
+
+/* ================ Attributes that make invalid code valid ================ */
+
+/* Attributes that prevent fatal compiler optimizations for code that is not
+ fully ISO C compliant. */
+
+/* Pointers to the type may point to the same storage as pointers to
+ other types, thus disabling strict aliasing optimization. */
+/* Applies to: types. */
+#define ATTRIBUTE_MAY_ALIAS _GL_ATTRIBUTE_MAY_ALIAS
+
+
+#endif /* _GL_ATTRIBUTE_H */
diff --git a/lib/binary-io.c b/lib/binary-io.c
index 2cee469781c..ea407fd74f7 100644
--- a/lib/binary-io.c
+++ b/lib/binary-io.c
@@ -1,17 +1,17 @@
/* Binary mode I/O.
- Copyright 2017 Free Software Foundation, Inc.
+ Copyright 2017-2022 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 file is free software: you can redistribute it and/or modify
+ it under the terms of the GNU Lesser General Public License as
+ published by the Free Software Foundation; either version 2.1 of the
+ License, or (at your option) any later version.
- This program is distributed in the hope that it will be useful,
+ This file 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.
+ GNU Lesser General Public License for more details.
- You should have received a copy of the GNU General Public License
+ You should have received a copy of the GNU Lesser General Public License
along with this program. If not, see <https://www.gnu.org/licenses/>. */
#include <config.h>
@@ -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 75adb33c918..5b7661e2331 100644
--- a/lib/binary-io.h
+++ b/lib/binary-io.h
@@ -1,17 +1,17 @@
/* Binary mode I/O.
- Copyright (C) 2001, 2003, 2005, 2008-2017 Free Software Foundation, Inc.
+ Copyright (C) 2001, 2003, 2005, 2008-2022 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 file is free software: you can redistribute it and/or modify
+ it under the terms of the GNU Lesser General Public License as
+ published by the Free Software Foundation; either version 2.1 of the
+ License, or (at your option) any later version.
- This program is distributed in the hope that it will be useful,
+ This file 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.
+ GNU Lesser General Public License for more details.
- You should have received a copy of the GNU General Public License
+ You should have received a copy of the GNU Lesser General Public License
along with this program. If not, see <https://www.gnu.org/licenses/>. */
#ifndef _BINARY_H
@@ -47,33 +47,27 @@ _GL_INLINE_HEADER_BEGIN
/* Use a function rather than a macro, to avoid gcc warnings
"warning: statement with no effect". */
BINARY_IO_INLINE int
-__gl_setmode (int fd, int mode)
+__gl_setmode (_GL_UNUSED int fd, _GL_UNUSED int mode)
{
- (void) fd;
- (void) mode;
return O_BINARY;
}
#endif
-#if defined __DJGPP__ || defined __EMX__
-extern int __gl_setmode_check (int);
-#else
-BINARY_IO_INLINE int
-__gl_setmode_check (int fd) { 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
+ its old 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/byteswap.in.h b/lib/byteswap.in.h
index 32385a289c6..f4746d39954 100644
--- a/lib/byteswap.in.h
+++ b/lib/byteswap.in.h
@@ -1,18 +1,18 @@
/* byteswap.h - Byte swapping
- Copyright (C) 2005, 2007, 2009-2017 Free Software Foundation, Inc.
+ Copyright (C) 2005, 2007, 2009-2022 Free Software Foundation, Inc.
Written by Oskar Liljeblad <oskar@osk.mine.nu>, 2005.
- 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 file is free software: you can redistribute it and/or modify
+ it under the terms of the GNU Lesser General Public License as
+ published by the Free Software Foundation; either version 2.1 of the
+ License, or (at your option) any later version.
- This program is distributed in the hope that it will be useful,
+ This file 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.
+ GNU Lesser General Public License for more details.
- You should have received a copy of the GNU General Public License
+ You should have received a copy of the GNU Lesser General Public License
along with this program. If not, see <https://www.gnu.org/licenses/>. */
#ifndef _GL_BYTESWAP_H
diff --git a/lib/c++defs.h b/lib/c++defs.h
index 09dcd3e0687..ad181558fbd 100644
--- a/lib/c++defs.h
+++ b/lib/c++defs.h
@@ -1,17 +1,17 @@
/* C++ compatible function declaration macros.
- Copyright (C) 2010-2017 Free Software Foundation, Inc.
+ Copyright (C) 2010-2022 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
+ under the terms of the GNU Lesser General Public License as published
+ by the Free Software Foundation; either version 2 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.
+ Lesser General Public License for more details.
- You should have received a copy of the GNU General Public License
+ You should have received a copy of the GNU Lesser General Public License
along with this program. If not, see <https://www.gnu.org/licenses/>. */
#ifndef _GL_CXXDEFS_H
@@ -146,6 +146,16 @@
_GL_EXTERN_C int _gl_cxxalias_dummy
#endif
+/* _GL_CXXALIAS_MDA (func, rettype, parameters);
+ is to be used when func is a Microsoft deprecated alias, on native Windows.
+ It declares a C++ alias called GNULIB_NAMESPACE::func
+ that redirects to _func, if GNULIB_NAMESPACE is defined.
+ Example:
+ _GL_CXXALIAS_MDA (open, int, (const char *filename, int flags, ...));
+ */
+#define _GL_CXXALIAS_MDA(func,rettype,parameters) \
+ _GL_CXXALIAS_RPL_1 (func, _##func, rettype, parameters)
+
/* _GL_CXXALIAS_RPL_CAST_1 (func, rpl_func, rettype, parameters);
is like _GL_CXXALIAS_RPL_1 (func, rpl_func, rettype, parameters);
except that the C function rpl_func may have a slightly different
@@ -171,6 +181,14 @@
_GL_EXTERN_C int _gl_cxxalias_dummy
#endif
+/* _GL_CXXALIAS_MDA_CAST (func, rettype, parameters);
+ is like _GL_CXXALIAS_MDA (func, rettype, parameters);
+ except that the C function func may have a slightly different declaration.
+ A cast is used to silence the "invalid conversion" error that would
+ otherwise occur. */
+#define _GL_CXXALIAS_MDA_CAST(func,rettype,parameters) \
+ _GL_CXXALIAS_RPL_CAST_1 (func, _##func, rettype, parameters)
+
/* _GL_CXXALIAS_SYS (func, rettype, parameters);
declares a C++ alias called GNULIB_NAMESPACE::func
that redirects to the system provided function func, if GNULIB_NAMESPACE
@@ -268,7 +286,7 @@
_GL_CXXALIASWARN_2 (func, namespace)
/* To work around GCC bug <https://gcc.gnu.org/bugzilla/show_bug.cgi?id=43881>,
we enable the warning only when not optimizing. */
-# if !__OPTIMIZE__
+# if !(defined __GNUC__ && !defined __clang__ && __OPTIMIZE__)
# define _GL_CXXALIASWARN_2(func,namespace) \
_GL_WARN_ON_USE (func, \
"The symbol ::" #func " refers to the system function. " \
@@ -296,14 +314,11 @@
_GL_CXXALIASWARN1_2 (func, rettype, parameters_and_attributes, namespace)
/* To work around GCC bug <https://gcc.gnu.org/bugzilla/show_bug.cgi?id=43881>,
we enable the warning only when not optimizing. */
-# if !__OPTIMIZE__
+# if !(defined __GNUC__ && !defined __clang__ && __OPTIMIZE__)
# define _GL_CXXALIASWARN1_2(func,rettype,parameters_and_attributes,namespace) \
- _GL_WARN_ON_USE_CXX (func, rettype, parameters_and_attributes, \
+ _GL_WARN_ON_USE_CXX (func, rettype, rettype, parameters_and_attributes, \
"The symbol ::" #func " refers to the system function. " \
"Use " #namespace "::" #func " instead.")
-# elif __GNUC__ >= 3 && GNULIB_STRICT_CHECKING
-# define _GL_CXXALIASWARN1_2(func,rettype,parameters_and_attributes,namespace) \
- extern __typeof__ (func) func
# else
# define _GL_CXXALIASWARN1_2(func,rettype,parameters_and_attributes,namespace) \
_GL_EXTERN_C int _gl_cxxalias_dummy
diff --git a/lib/c-ctype.c b/lib/c-ctype.c
index 5d9d4d87a61..a247514cd62 100644
--- a/lib/c-ctype.c
+++ b/lib/c-ctype.c
@@ -1,3 +1,21 @@
+/* Character handling in C locale.
+
+ Copyright (C) 2003-2022 Free Software Foundation, Inc.
+
+ This file is free software: you can redistribute it and/or modify
+ it under the terms of the GNU Lesser General Public License as
+ published by the Free Software Foundation; either version 2.1 of the
+ License, or (at your option) any later version.
+
+ This file 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 Lesser General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public License
+ along with this program. If not, see <https://www.gnu.org/licenses/>. */
+
#include <config.h>
+
#define C_CTYPE_INLINE _GL_EXTERN_INLINE
#include "c-ctype.h"
diff --git a/lib/c-ctype.h b/lib/c-ctype.h
index 9ad3c18d471..1a4f603898f 100644
--- a/lib/c-ctype.h
+++ b/lib/c-ctype.h
@@ -5,20 +5,20 @@
<ctype.h> functions' behaviour depends on the current locale set via
setlocale.
- Copyright (C) 2000-2003, 2006, 2008-2017 Free Software Foundation, Inc.
+ Copyright (C) 2000-2003, 2006, 2008-2022 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 file is free software: you can redistribute it and/or modify
+ it under the terms of the GNU Lesser General Public License as
+ published by the Free Software Foundation; either version 2.1 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.
+ This file 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 Lesser General Public License for more details.
-You should have received a copy of the GNU General Public License
-along with this program; if not, see <https://www.gnu.org/licenses/>. */
+ You should have received a copy of the GNU Lesser General Public License
+ along with this program. If not, see <https://www.gnu.org/licenses/>. */
#ifndef C_CTYPE_H
#define C_CTYPE_H
diff --git a/lib/c-strcase.h b/lib/c-strcase.h
index 220d21d34ec..3e874b5ea3a 100644
--- a/lib/c-strcase.h
+++ b/lib/c-strcase.h
@@ -1,19 +1,19 @@
/* Case-insensitive string comparison functions in C locale.
- Copyright (C) 1995-1996, 2001, 2003, 2005, 2009-2017 Free Software
+ Copyright (C) 1995-1996, 2001, 2003, 2005, 2009-2022 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 file is free software: you can redistribute it and/or modify
+ it under the terms of the GNU Lesser General Public License as
+ published by the Free Software Foundation; either version 2.1 of the
+ License, or (at your option) any later version.
- This program is distributed in the hope that it will be useful,
+ This file 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.
+ GNU Lesser General Public License for more details.
- You should have received a copy of the GNU General Public License
- along with this program; if not, see <https://www.gnu.org/licenses/>. */
+ You should have received a copy of the GNU Lesser General Public License
+ along with this program. If not, see <https://www.gnu.org/licenses/>. */
#ifndef C_STRCASE_H
#define C_STRCASE_H
diff --git a/lib/c-strcasecmp.c b/lib/c-strcasecmp.c
index b2880a2e6c7..87b993cb2fe 100644
--- a/lib/c-strcasecmp.c
+++ b/lib/c-strcasecmp.c
@@ -1,18 +1,18 @@
/* c-strcasecmp.c -- case insensitive string comparator in C locale
- Copyright (C) 1998-1999, 2005-2006, 2009-2017 Free Software Foundation, Inc.
+ Copyright (C) 1998-1999, 2005-2006, 2009-2022 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 file is free software: you can redistribute it and/or modify
+ it under the terms of the GNU Lesser General Public License as
+ published by the Free Software Foundation; either version 2.1 of the
+ License, or (at your option) any later version.
- This program is distributed in the hope that it will be useful,
+ This file 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.
+ GNU Lesser General Public License for more details.
- You should have received a copy of the GNU General Public License
- along with this program; if not, see <https://www.gnu.org/licenses/>. */
+ You should have received a copy of the GNU Lesser General Public License
+ along with this program. If not, see <https://www.gnu.org/licenses/>. */
#include <config.h>
@@ -52,5 +52,5 @@ c_strcasecmp (const char *s1, const char *s2)
/* On machines where 'char' and 'int' are types of the same size, the
difference of two 'unsigned char' values - including the sign bit -
doesn't fit in an 'int'. */
- return (c1 > c2 ? 1 : c1 < c2 ? -1 : 0);
+ return _GL_CMP (c1, c2);
}
diff --git a/lib/c-strncasecmp.c b/lib/c-strncasecmp.c
index 982e17915bc..5a5d30b6e5e 100644
--- a/lib/c-strncasecmp.c
+++ b/lib/c-strncasecmp.c
@@ -1,18 +1,18 @@
/* c-strncasecmp.c -- case insensitive string comparator in C locale
- Copyright (C) 1998-1999, 2005-2006, 2009-2017 Free Software Foundation, Inc.
+ Copyright (C) 1998-1999, 2005-2006, 2009-2022 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 file is free software: you can redistribute it and/or modify
+ it under the terms of the GNU Lesser General Public License as
+ published by the Free Software Foundation; either version 2.1 of the
+ License, or (at your option) any later version.
- This program is distributed in the hope that it will be useful,
+ This file 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.
+ GNU Lesser General Public License for more details.
- You should have received a copy of the GNU General Public License
- along with this program; if not, see <https://www.gnu.org/licenses/>. */
+ You should have received a copy of the GNU Lesser General Public License
+ along with this program. If not, see <https://www.gnu.org/licenses/>. */
#include <config.h>
@@ -52,5 +52,5 @@ c_strncasecmp (const char *s1, const char *s2, size_t n)
/* On machines where 'char' and 'int' are types of the same size, the
difference of two 'unsigned char' values - including the sign bit -
doesn't fit in an 'int'. */
- return (c1 > c2 ? 1 : c1 < c2 ? -1 : 0);
+ return _GL_CMP (c1, c2);
}
diff --git a/lib/canonicalize-lgpl.c b/lib/canonicalize-lgpl.c
new file mode 100644
index 00000000000..a7fa7feb62e
--- /dev/null
+++ b/lib/canonicalize-lgpl.c
@@ -0,0 +1,472 @@
+/* Return the canonical absolute name of a given file.
+ Copyright (C) 1996-2022 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 Lesser General Public
+ License as published by the Free Software Foundation; either
+ version 2.1 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
+ Lesser General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public
+ License along with the GNU C Library; if not, see
+ <https://www.gnu.org/licenses/>. */
+
+#ifndef _LIBC
+/* Don't use __attribute__ __nonnull__ in this compilation unit. Otherwise gcc
+ optimizes away the name == NULL test below. */
+# define _GL_ARG_NONNULL(params)
+
+# include <libc-config.h>
+#endif
+
+/* Specification. */
+#include <stdlib.h>
+
+#include <errno.h>
+#include <fcntl.h>
+#include <limits.h>
+#include <stdbool.h>
+#include <string.h>
+#include <sys/stat.h>
+#include <unistd.h>
+
+#include <eloop-threshold.h>
+#include <filename.h>
+#include <idx.h>
+#include <intprops.h>
+#include <scratch_buffer.h>
+
+#ifdef _LIBC
+# include <shlib-compat.h>
+# define GCC_LINT 1
+# define _GL_ATTRIBUTE_PURE __attribute__ ((__pure__))
+#else
+# define __canonicalize_file_name canonicalize_file_name
+# define __realpath realpath
+# include "pathmax.h"
+# define __faccessat faccessat
+# if defined _WIN32 && !defined __CYGWIN__
+# define __getcwd _getcwd
+# elif HAVE_GETCWD
+# if IN_RELOCWRAPPER
+ /* When building the relocatable program wrapper, use the system's getcwd
+ function, not the gnulib override, otherwise we would get a link error.
+ */
+# undef getcwd
+# endif
+# if defined VMS && !defined getcwd
+ /* We want the directory in Unix syntax, not in VMS syntax.
+ The gnulib override of 'getcwd' takes 2 arguments; the original VMS
+ 'getcwd' takes 3 arguments. */
+# define __getcwd(buf, max) getcwd (buf, max, 0)
+# else
+# define __getcwd getcwd
+# endif
+# else
+# define __getcwd(buf, max) getwd (buf)
+# endif
+# define __mempcpy mempcpy
+# define __pathconf pathconf
+# define __rawmemchr rawmemchr
+# define __readlink readlink
+# if IN_RELOCWRAPPER
+ /* When building the relocatable program wrapper, use the system's memmove
+ function, not the gnulib override, otherwise we would get a link error.
+ */
+# undef memmove
+# endif
+#endif
+
+/* Suppress bogus GCC -Wmaybe-uninitialized warnings. */
+#if defined GCC_LINT || defined lint
+# define IF_LINT(Code) Code
+#else
+# define IF_LINT(Code) /* empty */
+#endif
+
+#ifndef DOUBLE_SLASH_IS_DISTINCT_ROOT
+# define DOUBLE_SLASH_IS_DISTINCT_ROOT false
+#endif
+
+#if defined _LIBC || !FUNC_REALPATH_WORKS
+
+/* Return true if FILE's existence can be shown, false (setting errno)
+ otherwise. Follow symbolic links. */
+static bool
+file_accessible (char const *file)
+{
+# if defined _LIBC || HAVE_FACCESSAT
+ return __faccessat (AT_FDCWD, file, F_OK, AT_EACCESS) == 0;
+# else
+ struct stat st;
+ return stat (file, &st) == 0 || errno == EOVERFLOW;
+# endif
+}
+
+/* True if concatenating END as a suffix to a file name means that the
+ code needs to check that the file name is that of a searchable
+ directory, since the canonicalize_filename_mode_stk code won't
+ check this later anyway when it checks an ordinary file name
+ component within END. END must either be empty, or start with a
+ slash. */
+
+static bool _GL_ATTRIBUTE_PURE
+suffix_requires_dir_check (char const *end)
+{
+ /* If END does not start with a slash, the suffix is OK. */
+ while (ISSLASH (*end))
+ {
+ /* Two or more slashes act like a single slash. */
+ do
+ end++;
+ while (ISSLASH (*end));
+
+ switch (*end++)
+ {
+ default: return false; /* An ordinary file name component is OK. */
+ case '\0': return true; /* Trailing "/" is trouble. */
+ case '.': break; /* Possibly "." or "..". */
+ }
+ /* Trailing "/.", or "/.." even if not trailing, is trouble. */
+ if (!*end || (*end == '.' && (!end[1] || ISSLASH (end[1]))))
+ return true;
+ }
+
+ return false;
+}
+
+/* Append this to a file name to test whether it is a searchable directory.
+ On POSIX platforms "/" suffices, but "/./" is sometimes needed on
+ macOS 10.13 <https://bugs.gnu.org/30350>, and should also work on
+ platforms like AIX 7.2 that need at least "/.". */
+
+# if defined _LIBC || defined LSTAT_FOLLOWS_SLASHED_SYMLINK
+static char const dir_suffix[] = "/";
+# else
+static char const dir_suffix[] = "/./";
+# endif
+
+/* Return true if DIR is a searchable dir, false (setting errno) otherwise.
+ DIREND points to the NUL byte at the end of the DIR string.
+ Store garbage into DIREND[0 .. strlen (dir_suffix)]. */
+
+static bool
+dir_check (char *dir, char *dirend)
+{
+ strcpy (dirend, dir_suffix);
+ return file_accessible (dir);
+}
+
+static idx_t
+get_path_max (void)
+{
+# ifdef PATH_MAX
+ long int path_max = PATH_MAX;
+# else
+ /* The caller invoked realpath with a null RESOLVED, even though
+ PATH_MAX is not defined as a constant. The glibc manual says
+ programs should not do this, and POSIX says the behavior is undefined.
+ Historically, glibc here used the result of pathconf, or 1024 if that
+ failed; stay consistent with this (dubious) historical practice. */
+ int err = errno;
+ long int path_max = __pathconf ("/", _PC_PATH_MAX);
+ __set_errno (err);
+# endif
+ return path_max < 0 ? 1024 : path_max <= IDX_MAX ? path_max : IDX_MAX;
+}
+
+/* Act like __realpath (see below), with an additional argument
+ rname_buf that can be used as temporary storage.
+
+ If GCC_LINT is defined, do not inline this function with GCC 10.1
+ and later, to avoid creating a pointer to the stack that GCC
+ -Wreturn-local-addr incorrectly complains about. See:
+ https://gcc.gnu.org/bugzilla/show_bug.cgi?id=93644
+ Although the noinline attribute can hurt performance a bit, no better way
+ to pacify GCC is known; even an explicit #pragma does not pacify GCC.
+ When the GCC bug is fixed this workaround should be limited to the
+ broken GCC versions. */
+# if __GNUC_PREREQ (10, 1)
+# if defined GCC_LINT || defined lint
+__attribute__ ((__noinline__))
+# elif __OPTIMIZE__ && !__NO_INLINE__
+# define GCC_BOGUS_WRETURN_LOCAL_ADDR
+# endif
+# endif
+static char *
+realpath_stk (const char *name, char *resolved,
+ struct scratch_buffer *rname_buf)
+{
+ char *dest;
+ char const *start;
+ char const *end;
+ int num_links = 0;
+
+ if (name == NULL)
+ {
+ /* As per Single Unix Specification V2 we must return an error if
+ either parameter is a null pointer. We extend this to allow
+ the RESOLVED parameter to be NULL in case the we are expected to
+ allocate the room for the return value. */
+ __set_errno (EINVAL);
+ return NULL;
+ }
+
+ if (name[0] == '\0')
+ {
+ /* As per Single Unix Specification V2 we must return an error if
+ the name argument points to an empty string. */
+ __set_errno (ENOENT);
+ return NULL;
+ }
+
+ struct scratch_buffer extra_buffer, link_buffer;
+ scratch_buffer_init (&extra_buffer);
+ scratch_buffer_init (&link_buffer);
+ scratch_buffer_init (rname_buf);
+ char *rname_on_stack = rname_buf->data;
+ char *rname = rname_on_stack;
+ bool end_in_extra_buffer = false;
+ bool failed = true;
+
+ /* This is always zero for Posix hosts, but can be 2 for MS-Windows
+ and MS-DOS X:/foo/bar file names. */
+ idx_t prefix_len = FILE_SYSTEM_PREFIX_LEN (name);
+
+ if (!IS_ABSOLUTE_FILE_NAME (name))
+ {
+ while (!__getcwd (rname, rname_buf->length))
+ {
+ if (errno != ERANGE)
+ {
+ dest = rname;
+ goto error;
+ }
+ if (!scratch_buffer_grow (rname_buf))
+ goto error_nomem;
+ rname = rname_buf->data;
+ }
+ dest = __rawmemchr (rname, '\0');
+ start = name;
+ prefix_len = FILE_SYSTEM_PREFIX_LEN (rname);
+ }
+ else
+ {
+ dest = __mempcpy (rname, name, prefix_len);
+ *dest++ = '/';
+ if (DOUBLE_SLASH_IS_DISTINCT_ROOT)
+ {
+ if (prefix_len == 0 /* implies ISSLASH (name[0]) */
+ && ISSLASH (name[1]) && !ISSLASH (name[2]))
+ *dest++ = '/';
+ *dest = '\0';
+ }
+ start = name + prefix_len;
+ }
+
+ for ( ; *start; start = end)
+ {
+ /* Skip sequence of multiple file name separators. */
+ while (ISSLASH (*start))
+ ++start;
+
+ /* Find end of component. */
+ for (end = start; *end && !ISSLASH (*end); ++end)
+ /* Nothing. */;
+
+ /* Length of this file name component; it can be zero if a file
+ name ends in '/'. */
+ idx_t startlen = end - start;
+
+ if (startlen == 0)
+ break;
+ else if (startlen == 1 && start[0] == '.')
+ /* nothing */;
+ else if (startlen == 2 && start[0] == '.' && start[1] == '.')
+ {
+ /* Back up to previous component, ignore if at root already. */
+ if (dest > rname + prefix_len + 1)
+ for (--dest; dest > rname && !ISSLASH (dest[-1]); --dest)
+ continue;
+ if (DOUBLE_SLASH_IS_DISTINCT_ROOT
+ && dest == rname + 1 && !prefix_len
+ && ISSLASH (*dest) && !ISSLASH (dest[1]))
+ dest++;
+ }
+ else
+ {
+ if (!ISSLASH (dest[-1]))
+ *dest++ = '/';
+
+ while (rname + rname_buf->length - dest
+ < startlen + sizeof dir_suffix)
+ {
+ idx_t dest_offset = dest - rname;
+ if (!scratch_buffer_grow_preserve (rname_buf))
+ goto error_nomem;
+ rname = rname_buf->data;
+ dest = rname + dest_offset;
+ }
+
+ dest = __mempcpy (dest, start, startlen);
+ *dest = '\0';
+
+ char *buf;
+ ssize_t n;
+ while (true)
+ {
+ buf = link_buffer.data;
+ idx_t bufsize = link_buffer.length;
+ n = __readlink (rname, buf, bufsize - 1);
+ if (n < bufsize - 1)
+ break;
+ if (!scratch_buffer_grow (&link_buffer))
+ goto error_nomem;
+ }
+ if (0 <= n)
+ {
+ if (++num_links > __eloop_threshold ())
+ {
+ __set_errno (ELOOP);
+ goto error;
+ }
+
+ buf[n] = '\0';
+
+ char *extra_buf = extra_buffer.data;
+ idx_t end_idx IF_LINT (= 0);
+ if (end_in_extra_buffer)
+ end_idx = end - extra_buf;
+ size_t len = strlen (end);
+ if (INT_ADD_OVERFLOW (len, n))
+ {
+ __set_errno (ENOMEM);
+ goto error_nomem;
+ }
+ while (extra_buffer.length <= len + n)
+ {
+ if (!scratch_buffer_grow_preserve (&extra_buffer))
+ goto error_nomem;
+ extra_buf = extra_buffer.data;
+ }
+ if (end_in_extra_buffer)
+ end = extra_buf + end_idx;
+
+ /* Careful here, end may be a pointer into extra_buf... */
+ memmove (&extra_buf[n], end, len + 1);
+ name = end = memcpy (extra_buf, buf, n);
+ end_in_extra_buffer = true;
+
+ if (IS_ABSOLUTE_FILE_NAME (buf))
+ {
+ idx_t pfxlen = FILE_SYSTEM_PREFIX_LEN (buf);
+
+ dest = __mempcpy (rname, buf, pfxlen);
+ *dest++ = '/'; /* It's an absolute symlink */
+ if (DOUBLE_SLASH_IS_DISTINCT_ROOT)
+ {
+ if (ISSLASH (buf[1]) && !ISSLASH (buf[2]) && !pfxlen)
+ *dest++ = '/';
+ *dest = '\0';
+ }
+ /* Install the new prefix to be in effect hereafter. */
+ prefix_len = pfxlen;
+ }
+ else
+ {
+ /* Back up to previous component, ignore if at root
+ already: */
+ if (dest > rname + prefix_len + 1)
+ for (--dest; dest > rname && !ISSLASH (dest[-1]); --dest)
+ continue;
+ if (DOUBLE_SLASH_IS_DISTINCT_ROOT && dest == rname + 1
+ && ISSLASH (*dest) && !ISSLASH (dest[1]) && !prefix_len)
+ dest++;
+ }
+ }
+ else if (! (suffix_requires_dir_check (end)
+ ? dir_check (rname, dest)
+ : errno == EINVAL))
+ goto error;
+ }
+ }
+ if (dest > rname + prefix_len + 1 && ISSLASH (dest[-1]))
+ --dest;
+ if (DOUBLE_SLASH_IS_DISTINCT_ROOT && dest == rname + 1 && !prefix_len
+ && ISSLASH (*dest) && !ISSLASH (dest[1]))
+ dest++;
+ failed = false;
+
+error:
+ *dest++ = '\0';
+ if (resolved != NULL && dest - rname <= get_path_max ())
+ rname = strcpy (resolved, rname);
+
+error_nomem:
+ scratch_buffer_free (&extra_buffer);
+ scratch_buffer_free (&link_buffer);
+
+ if (failed || rname == resolved)
+ {
+ scratch_buffer_free (rname_buf);
+ return failed ? NULL : resolved;
+ }
+
+ return scratch_buffer_dupfree (rname_buf, dest - rname);
+}
+
+/* Return the canonical absolute name of file NAME. A canonical name
+ does not contain any ".", ".." components nor any repeated file name
+ separators ('/') or symlinks. All file name components must exist. If
+ RESOLVED is null, the result is malloc'd; otherwise, if the
+ canonical name is PATH_MAX chars or more, returns null with 'errno'
+ set to ENAMETOOLONG; if the name fits in fewer than PATH_MAX chars,
+ returns the name in RESOLVED. If the name cannot be resolved and
+ RESOLVED is non-NULL, it contains the name of the first component
+ that cannot be resolved. If the name can be resolved, RESOLVED
+ holds the same value as the value returned. */
+
+char *
+__realpath (const char *name, char *resolved)
+{
+ #ifdef GCC_BOGUS_WRETURN_LOCAL_ADDR
+ #warning "GCC might issue a bogus -Wreturn-local-addr warning here."
+ #warning "See <https://gcc.gnu.org/bugzilla/show_bug.cgi?id=93644>."
+ #endif
+ struct scratch_buffer rname_buffer;
+ return realpath_stk (name, resolved, &rname_buffer);
+}
+libc_hidden_def (__realpath)
+versioned_symbol (libc, __realpath, realpath, GLIBC_2_3);
+
+#endif /* defined _LIBC || !FUNC_REALPATH_WORKS */
+
+
+#if SHLIB_COMPAT(libc, GLIBC_2_0, GLIBC_2_3)
+char *
+attribute_compat_text_section
+__old_realpath (const char *name, char *resolved)
+{
+ if (resolved == NULL)
+ {
+ __set_errno (EINVAL);
+ return NULL;
+ }
+
+ return __realpath (name, resolved);
+}
+compat_symbol (libc, __old_realpath, realpath, GLIBC_2_0);
+#endif
+
+
+char *
+__canonicalize_file_name (const char *name)
+{
+ return __realpath (name, NULL);
+}
+weak_alias (__canonicalize_file_name, canonicalize_file_name)
diff --git a/lib/careadlinkat.c b/lib/careadlinkat.c
index e2af54f0984..6ddc35f798b 100644
--- a/lib/careadlinkat.c
+++ b/lib/careadlinkat.c
@@ -1,19 +1,19 @@
/* Read symbolic links into a buffer without size limitation, relative to fd.
- Copyright (C) 2001, 2003-2004, 2007, 2009-2017 Free Software Foundation,
+ Copyright (C) 2001, 2003-2004, 2007, 2009-2022 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 file is free software: you can redistribute it and/or modify
+ it under the terms of the GNU Lesser General Public License as
+ published by the Free Software Foundation; either version 2.1 of the
+ License, or (at your option) any later version.
- This program is distributed in the hope that it will be useful,
+ This file 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.
+ GNU Lesser General Public License for more details.
- You should have received a copy of the GNU General Public License
+ You should have received a copy of the GNU Lesser General Public License
along with this program. If not, see <https://www.gnu.org/licenses/>. */
/* Written by Paul Eggert, Bruno Haible, and Jim Meyering. */
@@ -22,6 +22,9 @@
#include "careadlinkat.h"
+#include "idx.h"
+#include "minmax.h"
+
#include <errno.h>
#include <limits.h>
#include <string.h>
@@ -38,78 +41,62 @@
#include "allocator.h"
-/* Assuming the current directory is FD, get the symbolic link value
- of FILENAME as a null-terminated string and put it into a buffer.
- If FD is AT_FDCWD, FILENAME is interpreted relative to the current
- working directory, as in openat.
-
- If the link is small enough to fit into BUFFER put it there.
- BUFFER's size is BUFFER_SIZE, and BUFFER can be null
- if BUFFER_SIZE is zero.
-
- If the link is not small, put it into a dynamically allocated
- buffer managed by ALLOC. It is the caller's responsibility to free
- the returned value if it is nonnull and is not BUFFER. A null
- ALLOC stands for the standard allocator.
-
- The PREADLINKAT function specifies how to read links. It operates
- like POSIX readlinkat()
- <http://pubs.opengroup.org/onlinepubs/9699919799/functions/readlink.html>
- but can assume that its first argument is the same as FD.
-
- If successful, return the buffer address; otherwise return NULL and
- set errno. */
-
-char *
-careadlinkat (int fd, char const *filename,
+enum { STACK_BUF_SIZE = 1024 };
+
+/* Act like careadlinkat (see below), with an additional argument
+ STACK_BUF that can be used as temporary storage.
+
+ If GCC_LINT is defined, do not inline this function with GCC 10.1
+ and later, to avoid creating a pointer to the stack that GCC
+ -Wreturn-local-addr incorrectly complains about. See:
+ https://gcc.gnu.org/bugzilla/show_bug.cgi?id=93644
+ Although the noinline attribute can hurt performance a bit, no better way
+ to pacify GCC is known; even an explicit #pragma does not pacify GCC.
+ When the GCC bug is fixed this workaround should be limited to the
+ broken GCC versions. */
+#if _GL_GNUC_PREREQ (10, 1)
+# if defined GCC_LINT || defined lint
+__attribute__ ((__noinline__))
+# elif __OPTIMIZE__ && !__NO_INLINE__
+# define GCC_BOGUS_WRETURN_LOCAL_ADDR
+# endif
+#endif
+static char *
+readlink_stk (int fd, char const *filename,
char *buffer, size_t buffer_size,
struct allocator const *alloc,
- ssize_t (*preadlinkat) (int, char const *, char *, size_t))
+ ssize_t (*preadlinkat) (int, char const *, char *, size_t),
+ char stack_buf[STACK_BUF_SIZE])
{
- char *buf;
- size_t buf_size;
- size_t buf_size_max =
- SSIZE_MAX < SIZE_MAX ? (size_t) SSIZE_MAX + 1 : SIZE_MAX;
- char stack_buf[1024];
-
if (! alloc)
alloc = &stdlib_allocator;
- if (! buffer_size)
+ if (!buffer)
{
- /* Allocate the initial buffer on the stack. This way, in the
- common case of a symlink of small size, we get away with a
- single small malloc() instead of a big malloc() followed by a
- shrinking realloc(). */
buffer = stack_buf;
- buffer_size = sizeof stack_buf;
+ buffer_size = STACK_BUF_SIZE;
}
- buf = buffer;
- buf_size = buffer_size;
+ char *buf = buffer;
+ idx_t buf_size_max = MIN (IDX_MAX, MIN (SSIZE_MAX, SIZE_MAX));
+ idx_t buf_size = MIN (buffer_size, buf_size_max);
- do
+ while (buf)
{
/* Attempt to read the link into the current buffer. */
- ssize_t link_length = preadlinkat (fd, filename, buf, buf_size);
- size_t link_size;
+ idx_t link_length = preadlinkat (fd, filename, buf, buf_size);
if (link_length < 0)
{
- /* On AIX 5L v5.3 and HP-UX 11i v2 04/09, readlink returns -1
- with errno == ERANGE if the buffer is too small. */
- int readlinkat_errno = errno;
- if (readlinkat_errno != ERANGE)
+ if (buf != buffer)
{
- if (buf != buffer)
- {
- alloc->free (buf);
- errno = readlinkat_errno;
- }
- return NULL;
+ int readlinkat_errno = errno;
+ alloc->free (buf);
+ errno = readlinkat_errno;
}
+ return NULL;
}
- link_size = link_length;
+ idx_t link_size = link_length;
if (link_size < buf_size)
{
@@ -117,19 +104,19 @@ careadlinkat (int fd, char const *filename,
if (buf == stack_buf)
{
- char *b = (char *) alloc->allocate (link_size);
+ char *b = alloc->allocate (link_size);
buf_size = link_size;
if (! b)
break;
- memcpy (b, buf, link_size);
- buf = b;
+ return memcpy (b, buf, link_size);
}
- else if (link_size < buf_size && buf != buffer && alloc->reallocate)
+
+ if (link_size < buf_size && buf != buffer && alloc->reallocate)
{
/* Shrink BUF before returning it. */
- char *b = (char *) alloc->reallocate (buf, link_size);
+ char *b = alloc->reallocate (buf, link_size);
if (b)
- buf = b;
+ return b;
}
return buf;
@@ -138,23 +125,60 @@ careadlinkat (int fd, char const *filename,
if (buf != buffer)
alloc->free (buf);
- if (buf_size <= buf_size_max / 2)
- buf_size *= 2;
- else if (buf_size < buf_size_max)
- buf_size = buf_size_max;
- else if (buf_size_max < SIZE_MAX)
+ if (buf_size_max / 2 <= buf_size)
{
errno = ENAMETOOLONG;
return NULL;
}
- else
- break;
- buf = (char *) alloc->allocate (buf_size);
+
+ buf_size = 2 * buf_size + 1;
+ buf = alloc->allocate (buf_size);
}
- while (buf);
if (alloc->die)
alloc->die (buf_size);
errno = ENOMEM;
return NULL;
}
+
+
+/* Assuming the current directory is FD, get the symbolic link value
+ of FILENAME as a null-terminated string and put it into a buffer.
+ If FD is AT_FDCWD, FILENAME is interpreted relative to the current
+ working directory, as in openat.
+
+ If the link is small enough to fit into BUFFER put it there.
+ BUFFER's size is BUFFER_SIZE, and BUFFER can be null
+ if BUFFER_SIZE is zero.
+
+ If the link is not small, put it into a dynamically allocated
+ buffer managed by ALLOC. It is the caller's responsibility to free
+ the returned value if it is nonnull and is not BUFFER. A null
+ ALLOC stands for the standard allocator.
+
+ The PREADLINKAT function specifies how to read links. It operates
+ like POSIX readlinkat()
+ <https://pubs.opengroup.org/onlinepubs/9699919799/functions/readlink.html>
+ but can assume that its first argument is the same as FD.
+
+ If successful, return the buffer address; otherwise return NULL and
+ set errno. */
+
+char *
+careadlinkat (int fd, char const *filename,
+ char *buffer, size_t buffer_size,
+ struct allocator const *alloc,
+ ssize_t (*preadlinkat) (int, char const *, char *, size_t))
+{
+ /* Allocate the initial buffer on the stack. This way, in the
+ common case of a symlink of small size, we get away with a
+ single small malloc instead of a big malloc followed by a
+ shrinking realloc. */
+ #ifdef GCC_BOGUS_WRETURN_LOCAL_ADDR
+ #warning "GCC might issue a bogus -Wreturn-local-addr warning here."
+ #warning "See <https://gcc.gnu.org/bugzilla/show_bug.cgi?id=93644>."
+ #endif
+ char stack_buf[STACK_BUF_SIZE];
+ return readlink_stk (fd, filename, buffer, buffer_size, alloc,
+ preadlinkat, stack_buf);
+}
diff --git a/lib/careadlinkat.h b/lib/careadlinkat.h
index d436c691eaa..2b559b2cd4c 100644
--- a/lib/careadlinkat.h
+++ b/lib/careadlinkat.h
@@ -1,18 +1,18 @@
/* Read symbolic links into a buffer without size limitation, relative to fd.
- Copyright (C) 2011-2017 Free Software Foundation, Inc.
+ Copyright (C) 2011-2022 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 file is free software: you can redistribute it and/or modify
+ it under the terms of the GNU Lesser General Public License as
+ published by the Free Software Foundation; either version 2.1 of the
+ License, or (at your option) any later version.
- This program is distributed in the hope that it will be useful,
+ This file 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.
+ GNU Lesser General Public License for more details.
- You should have received a copy of the GNU General Public License
+ You should have received a copy of the GNU Lesser General Public License
along with this program. If not, see <https://www.gnu.org/licenses/>. */
/* Written by Paul Eggert, Bruno Haible, and Jim Meyering. */
@@ -40,14 +40,14 @@ struct allocator;
The PREADLINKAT function specifies how to read links. It operates
like POSIX readlinkat()
- <http://pubs.opengroup.org/onlinepubs/9699919799/functions/readlink.html>
+ <https://pubs.opengroup.org/onlinepubs/9699919799/functions/readlink.html>
but can assume that its first argument is the same as FD.
If successful, return the buffer address; otherwise return NULL and
set errno. */
char *careadlinkat (int fd, char const *filename,
- char *buffer, size_t buffer_size,
+ char *restrict buffer, size_t buffer_size,
struct allocator const *alloc,
ssize_t (*preadlinkat) (int, char const *,
char *, size_t));
diff --git a/lib/cdefs.h b/lib/cdefs.h
new file mode 100644
index 00000000000..7b8ed5b344b
--- /dev/null
+++ b/lib/cdefs.h
@@ -0,0 +1,707 @@
+/* Copyright (C) 1992-2022 Free Software Foundation, Inc.
+ Copyright The GNU Toolchain Authors.
+ 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 Lesser General Public
+ License as published by the Free Software Foundation; either
+ version 2.1 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
+ Lesser General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public
+ License along with the GNU C Library; if not, see
+ <https://www.gnu.org/licenses/>. */
+
+#ifndef _SYS_CDEFS_H
+#define _SYS_CDEFS_H 1
+
+/* We are almost always included from features.h. */
+#ifndef _FEATURES_H
+# include <features.h>
+#endif
+
+/* The GNU libc does not support any K&R compilers or the traditional mode
+ of ISO C compilers anymore. Check for some of the combinations not
+ supported anymore. */
+#if defined __GNUC__ && !defined __STDC__
+# error "You need a ISO C conforming compiler to use the glibc headers"
+#endif
+
+/* Some user header file might have defined this before. */
+#undef __P
+#undef __PMT
+
+/* Compilers that lack __has_attribute may object to
+ #if defined __has_attribute && __has_attribute (...)
+ even though they do not need to evaluate the right-hand side of the &&.
+ Similarly for __has_builtin, etc. */
+#if (defined __has_attribute \
+ && (!defined __clang_minor__ \
+ || (defined __apple_build_version__ \
+ ? 6000000 <= __apple_build_version__ \
+ : 3 < __clang_major__ + (5 <= __clang_minor__))))
+# define __glibc_has_attribute(attr) __has_attribute (attr)
+#else
+# define __glibc_has_attribute(attr) 0
+#endif
+#ifdef __has_builtin
+# define __glibc_has_builtin(name) __has_builtin (name)
+#else
+# define __glibc_has_builtin(name) 0
+#endif
+#ifdef __has_extension
+# define __glibc_has_extension(ext) __has_extension (ext)
+#else
+# define __glibc_has_extension(ext) 0
+#endif
+
+#if defined __GNUC__ || defined __clang__
+
+/* All functions, except those with callbacks or those that
+ synchronize memory, are leaf functions. */
+# if __GNUC_PREREQ (4, 6) && !defined _LIBC
+# define __LEAF , __leaf__
+# define __LEAF_ATTR __attribute__ ((__leaf__))
+# else
+# define __LEAF
+# define __LEAF_ATTR
+# endif
+
+/* GCC can always grok prototypes. For C++ programs we add throw()
+ to help it optimize the function calls. But this only works with
+ gcc 2.8.x and egcs. For gcc 3.4 and up we even mark C functions
+ as non-throwing using a function attribute since programs can use
+ the -fexceptions options for C code as well. */
+# if !defined __cplusplus \
+ && (__GNUC_PREREQ (3, 4) || __glibc_has_attribute (__nothrow__))
+# define __THROW __attribute__ ((__nothrow__ __LEAF))
+# define __THROWNL __attribute__ ((__nothrow__))
+# define __NTH(fct) __attribute__ ((__nothrow__ __LEAF)) fct
+# define __NTHNL(fct) __attribute__ ((__nothrow__)) fct
+# else
+# if defined __cplusplus && (__GNUC_PREREQ (2,8) || __clang_major >= 4)
+# if __cplusplus >= 201103L
+# define __THROW noexcept (true)
+# else
+# define __THROW throw ()
+# endif
+# define __THROWNL __THROW
+# define __NTH(fct) __LEAF_ATTR fct __THROW
+# define __NTHNL(fct) fct __THROW
+# else
+# define __THROW
+# define __THROWNL
+# define __NTH(fct) fct
+# define __NTHNL(fct) fct
+# endif
+# endif
+
+#else /* Not GCC or clang. */
+
+# if (defined __cplusplus \
+ || (defined __STDC_VERSION__ && __STDC_VERSION__ >= 199901L))
+# define __inline inline
+# else
+# define __inline /* No inline functions. */
+# endif
+
+# define __THROW
+# define __THROWNL
+# define __NTH(fct) fct
+
+#endif /* GCC || clang. */
+
+/* These two macros are not used in glibc anymore. They are kept here
+ only because some other projects expect the macros to be defined. */
+#define __P(args) args
+#define __PMT(args) args
+
+/* For these things, GCC behaves the ANSI way normally,
+ and the non-ANSI way under -traditional. */
+
+#define __CONCAT(x,y) x ## y
+#define __STRING(x) #x
+
+/* This is not a typedef so `const __ptr_t' does the right thing. */
+#define __ptr_t void *
+
+
+/* C++ needs to know that types and declarations are C, not C++. */
+#ifdef __cplusplus
+# define __BEGIN_DECLS extern "C" {
+# define __END_DECLS }
+#else
+# define __BEGIN_DECLS
+# define __END_DECLS
+#endif
+
+
+/* Fortify support. */
+#define __bos(ptr) __builtin_object_size (ptr, __USE_FORTIFY_LEVEL > 1)
+#define __bos0(ptr) __builtin_object_size (ptr, 0)
+
+/* Use __builtin_dynamic_object_size at _FORTIFY_SOURCE=3 when available. */
+#if __USE_FORTIFY_LEVEL == 3 && (__glibc_clang_prereq (9, 0) \
+ || __GNUC_PREREQ (12, 0))
+# define __glibc_objsize0(__o) __builtin_dynamic_object_size (__o, 0)
+# define __glibc_objsize(__o) __builtin_dynamic_object_size (__o, 1)
+#else
+# define __glibc_objsize0(__o) __bos0 (__o)
+# define __glibc_objsize(__o) __bos (__o)
+#endif
+
+/* Compile time conditions to choose between the regular, _chk and _chk_warn
+ variants. These conditions should get evaluated to constant and optimized
+ away. */
+
+#define __glibc_safe_len_cond(__l, __s, __osz) ((__l) <= (__osz) / (__s))
+#define __glibc_unsigned_or_positive(__l) \
+ ((__typeof (__l)) 0 < (__typeof (__l)) -1 \
+ || (__builtin_constant_p (__l) && (__l) > 0))
+
+/* Length is known to be safe at compile time if the __L * __S <= __OBJSZ
+ condition can be folded to a constant and if it is true, or unknown (-1) */
+#define __glibc_safe_or_unknown_len(__l, __s, __osz) \
+ ((__osz) == (__SIZE_TYPE__) -1 \
+ || (__glibc_unsigned_or_positive (__l) \
+ && __builtin_constant_p (__glibc_safe_len_cond ((__SIZE_TYPE__) (__l), \
+ (__s), (__osz))) \
+ && __glibc_safe_len_cond ((__SIZE_TYPE__) (__l), (__s), (__osz))))
+
+/* Conversely, we know at compile time that the length is unsafe if the
+ __L * __S <= __OBJSZ condition can be folded to a constant and if it is
+ false. */
+#define __glibc_unsafe_len(__l, __s, __osz) \
+ (__glibc_unsigned_or_positive (__l) \
+ && __builtin_constant_p (__glibc_safe_len_cond ((__SIZE_TYPE__) (__l), \
+ __s, __osz)) \
+ && !__glibc_safe_len_cond ((__SIZE_TYPE__) (__l), __s, __osz))
+
+/* Fortify function f. __f_alias, __f_chk and __f_chk_warn must be
+ declared. */
+
+#define __glibc_fortify(f, __l, __s, __osz, ...) \
+ (__glibc_safe_or_unknown_len (__l, __s, __osz) \
+ ? __ ## f ## _alias (__VA_ARGS__) \
+ : (__glibc_unsafe_len (__l, __s, __osz) \
+ ? __ ## f ## _chk_warn (__VA_ARGS__, __osz) \
+ : __ ## f ## _chk (__VA_ARGS__, __osz))) \
+
+/* Fortify function f, where object size argument passed to f is the number of
+ elements and not total size. */
+
+#define __glibc_fortify_n(f, __l, __s, __osz, ...) \
+ (__glibc_safe_or_unknown_len (__l, __s, __osz) \
+ ? __ ## f ## _alias (__VA_ARGS__) \
+ : (__glibc_unsafe_len (__l, __s, __osz) \
+ ? __ ## f ## _chk_warn (__VA_ARGS__, (__osz) / (__s)) \
+ : __ ## f ## _chk (__VA_ARGS__, (__osz) / (__s)))) \
+
+#if __GNUC_PREREQ (4,3)
+# define __warnattr(msg) __attribute__((__warning__ (msg)))
+# define __errordecl(name, msg) \
+ extern void name (void) __attribute__((__error__ (msg)))
+#else
+# define __warnattr(msg)
+# define __errordecl(name, msg) extern void name (void)
+#endif
+
+/* Support for flexible arrays.
+ Headers that should use flexible arrays only if they're "real"
+ (e.g. only if they won't affect sizeof()) should test
+ #if __glibc_c99_flexarr_available. */
+#if defined __STDC_VERSION__ && __STDC_VERSION__ >= 199901L && !defined __HP_cc
+# define __flexarr []
+# define __glibc_c99_flexarr_available 1
+#elif __GNUC_PREREQ (2,97) || defined __clang__
+/* GCC 2.97 and clang support C99 flexible array members as an extension,
+ even when in C89 mode or compiling C++ (any version). */
+# define __flexarr []
+# define __glibc_c99_flexarr_available 1
+#elif defined __GNUC__
+/* Pre-2.97 GCC did not support C99 flexible arrays but did have
+ an equivalent extension with slightly different notation. */
+# define __flexarr [0]
+# define __glibc_c99_flexarr_available 1
+#else
+/* Some other non-C99 compiler. Approximate with [1]. */
+# define __flexarr [1]
+# define __glibc_c99_flexarr_available 0
+#endif
+
+
+/* __asm__ ("xyz") is used throughout the headers to rename functions
+ at the assembly language level. This is wrapped by the __REDIRECT
+ macro, in order to support compilers that can do this some other
+ way. When compilers don't support asm-names at all, we have to do
+ preprocessor tricks instead (which don't have exactly the right
+ semantics, but it's the best we can do).
+
+ Example:
+ int __REDIRECT(setpgrp, (__pid_t pid, __pid_t pgrp), setpgid); */
+
+#if (defined __GNUC__ && __GNUC__ >= 2) || (__clang_major__ >= 4)
+
+# define __REDIRECT(name, proto, alias) name proto __asm__ (__ASMNAME (#alias))
+# ifdef __cplusplus
+# define __REDIRECT_NTH(name, proto, alias) \
+ name proto __THROW __asm__ (__ASMNAME (#alias))
+# define __REDIRECT_NTHNL(name, proto, alias) \
+ name proto __THROWNL __asm__ (__ASMNAME (#alias))
+# else
+# define __REDIRECT_NTH(name, proto, alias) \
+ name proto __asm__ (__ASMNAME (#alias)) __THROW
+# define __REDIRECT_NTHNL(name, proto, alias) \
+ name proto __asm__ (__ASMNAME (#alias)) __THROWNL
+# endif
+# define __ASMNAME(cname) __ASMNAME2 (__USER_LABEL_PREFIX__, cname)
+# define __ASMNAME2(prefix, cname) __STRING (prefix) cname
+
+/*
+#elif __SOME_OTHER_COMPILER__
+
+# define __REDIRECT(name, proto, alias) name proto; \
+ _Pragma("let " #name " = " #alias)
+*/
+#endif
+
+/* GCC and clang have various useful declarations that can be made with
+ the '__attribute__' syntax. All of the ways we use this do fine if
+ they are omitted for compilers that don't understand it. */
+#if !(defined __GNUC__ || defined __clang__)
+# define __attribute__(xyz) /* Ignore */
+#endif
+
+/* At some point during the gcc 2.96 development the `malloc' attribute
+ for functions was introduced. We don't want to use it unconditionally
+ (although this would be possible) since it generates warnings. */
+#if __GNUC_PREREQ (2,96) || __glibc_has_attribute (__malloc__)
+# define __attribute_malloc__ __attribute__ ((__malloc__))
+#else
+# define __attribute_malloc__ /* Ignore */
+#endif
+
+/* Tell the compiler which arguments to an allocation function
+ indicate the size of the allocation. */
+#if __GNUC_PREREQ (4, 3)
+# define __attribute_alloc_size__(params) \
+ __attribute__ ((__alloc_size__ params))
+#else
+# define __attribute_alloc_size__(params) /* Ignore. */
+#endif
+
+/* Tell the compiler which argument to an allocation function
+ indicates the alignment of the allocation. */
+#if __GNUC_PREREQ (4, 9) || __glibc_has_attribute (__alloc_align__)
+# define __attribute_alloc_align__(param) \
+ __attribute__ ((__alloc_align__ param))
+#else
+# define __attribute_alloc_align__(param) /* Ignore. */
+#endif
+
+/* At some point during the gcc 2.96 development the `pure' attribute
+ for functions was introduced. We don't want to use it unconditionally
+ (although this would be possible) since it generates warnings. */
+#if __GNUC_PREREQ (2,96) || __glibc_has_attribute (__pure__)
+# define __attribute_pure__ __attribute__ ((__pure__))
+#else
+# define __attribute_pure__ /* Ignore */
+#endif
+
+/* This declaration tells the compiler that the value is constant. */
+#if __GNUC_PREREQ (2,5) || __glibc_has_attribute (__const__)
+# define __attribute_const__ __attribute__ ((__const__))
+#else
+# define __attribute_const__ /* Ignore */
+#endif
+
+#if __GNUC_PREREQ (2,7) || __glibc_has_attribute (__unused__)
+# define __attribute_maybe_unused__ __attribute__ ((__unused__))
+#else
+# define __attribute_maybe_unused__ /* Ignore */
+#endif
+
+/* At some point during the gcc 3.1 development the `used' attribute
+ for functions was introduced. We don't want to use it unconditionally
+ (although this would be possible) since it generates warnings. */
+#if __GNUC_PREREQ (3,1) || __glibc_has_attribute (__used__)
+# define __attribute_used__ __attribute__ ((__used__))
+# define __attribute_noinline__ __attribute__ ((__noinline__))
+#else
+# define __attribute_used__ __attribute__ ((__unused__))
+# define __attribute_noinline__ /* Ignore */
+#endif
+
+/* Since version 3.2, gcc allows marking deprecated functions. */
+#if __GNUC_PREREQ (3,2) || __glibc_has_attribute (__deprecated__)
+# define __attribute_deprecated__ __attribute__ ((__deprecated__))
+#else
+# define __attribute_deprecated__ /* Ignore */
+#endif
+
+/* Since version 4.5, gcc also allows one to specify the message printed
+ when a deprecated function is used. clang claims to be gcc 4.2, but
+ may also support this feature. */
+#if __GNUC_PREREQ (4,5) \
+ || __glibc_has_extension (__attribute_deprecated_with_message__)
+# define __attribute_deprecated_msg__(msg) \
+ __attribute__ ((__deprecated__ (msg)))
+#else
+# define __attribute_deprecated_msg__(msg) __attribute_deprecated__
+#endif
+
+/* At some point during the gcc 2.8 development the `format_arg' attribute
+ for functions was introduced. We don't want to use it unconditionally
+ (although this would be possible) since it generates warnings.
+ If several `format_arg' attributes are given for the same function, in
+ gcc-3.0 and older, all but the last one are ignored. In newer gccs,
+ all designated arguments are considered. */
+#if __GNUC_PREREQ (2,8) || __glibc_has_attribute (__format_arg__)
+# define __attribute_format_arg__(x) __attribute__ ((__format_arg__ (x)))
+#else
+# define __attribute_format_arg__(x) /* Ignore */
+#endif
+
+/* At some point during the gcc 2.97 development the `strfmon' format
+ attribute for functions was introduced. We don't want to use it
+ unconditionally (although this would be possible) since it
+ generates warnings. */
+#if __GNUC_PREREQ (2,97) || __glibc_has_attribute (__format__)
+# define __attribute_format_strfmon__(a,b) \
+ __attribute__ ((__format__ (__strfmon__, a, b)))
+#else
+# define __attribute_format_strfmon__(a,b) /* Ignore */
+#endif
+
+/* The nonnull function attribute marks pointer parameters that
+ must not be NULL. This has the name __nonnull in glibc,
+ and __attribute_nonnull__ in files shared with Gnulib to avoid
+ collision with a different __nonnull in DragonFlyBSD 5.9. */
+#ifndef __attribute_nonnull__
+# if __GNUC_PREREQ (3,3) || __glibc_has_attribute (__nonnull__)
+# define __attribute_nonnull__(params) __attribute__ ((__nonnull__ params))
+# else
+# define __attribute_nonnull__(params)
+# endif
+#endif
+#ifndef __nonnull
+# define __nonnull(params) __attribute_nonnull__ (params)
+#endif
+
+/* The returns_nonnull function attribute marks the return type of the function
+ as always being non-null. */
+#ifndef __returns_nonnull
+# if __GNUC_PREREQ (4, 9) || __glibc_has_attribute (__returns_nonnull__)
+# define __returns_nonnull __attribute__ ((__returns_nonnull__))
+# else
+# define __returns_nonnull
+# endif
+#endif
+
+/* If fortification mode, we warn about unused results of certain
+ function calls which can lead to problems. */
+#if __GNUC_PREREQ (3,4) || __glibc_has_attribute (__warn_unused_result__)
+# define __attribute_warn_unused_result__ \
+ __attribute__ ((__warn_unused_result__))
+# if defined __USE_FORTIFY_LEVEL && __USE_FORTIFY_LEVEL > 0
+# define __wur __attribute_warn_unused_result__
+# endif
+#else
+# define __attribute_warn_unused_result__ /* empty */
+#endif
+#ifndef __wur
+# define __wur /* Ignore */
+#endif
+
+/* Forces a function to be always inlined. */
+#if __GNUC_PREREQ (3,2) || __glibc_has_attribute (__always_inline__)
+/* The Linux kernel defines __always_inline in stddef.h (283d7573), and
+ it conflicts with this definition. Therefore undefine it first to
+ allow either header to be included first. */
+# undef __always_inline
+# define __always_inline __inline __attribute__ ((__always_inline__))
+#else
+# undef __always_inline
+# define __always_inline __inline
+#endif
+
+/* Associate error messages with the source location of the call site rather
+ than with the source location inside the function. */
+#if __GNUC_PREREQ (4,3) || __glibc_has_attribute (__artificial__)
+# define __attribute_artificial__ __attribute__ ((__artificial__))
+#else
+# define __attribute_artificial__ /* Ignore */
+#endif
+
+/* GCC 4.3 and above with -std=c99 or -std=gnu99 implements ISO C99
+ inline semantics, unless -fgnu89-inline is used. Using __GNUC_STDC_INLINE__
+ or __GNUC_GNU_INLINE is not a good enough check for gcc because gcc versions
+ older than 4.3 may define these macros and still not guarantee GNU inlining
+ semantics.
+
+ clang++ identifies itself as gcc-4.2, but has support for GNU inlining
+ 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__ \
+ || defined __GNUC_GNU_INLINE__)))
+# if defined __GNUC_STDC_INLINE__ || defined __cplusplus
+# define __extern_inline extern __inline __attribute__ ((__gnu_inline__))
+# define __extern_always_inline \
+ extern __always_inline __attribute__ ((__gnu_inline__))
+# else
+# define __extern_inline extern __inline
+# define __extern_always_inline extern __always_inline
+# endif
+#endif
+
+#ifdef __extern_always_inline
+# define __fortify_function __extern_always_inline __attribute_artificial__
+#endif
+
+/* GCC 4.3 and above allow passing all anonymous arguments of an
+ __extern_always_inline function to some other vararg function. */
+#if __GNUC_PREREQ (4,3)
+# define __va_arg_pack() __builtin_va_arg_pack ()
+# define __va_arg_pack_len() __builtin_va_arg_pack_len ()
+#endif
+
+/* It is possible to compile containing GCC extensions even if GCC is
+ run in pedantic mode if the uses are carefully marked using the
+ `__extension__' keyword. But this is not generally available before
+ version 2.8. */
+#if !(__GNUC_PREREQ (2,8) || defined __clang__)
+# define __extension__ /* Ignore */
+#endif
+
+/* __restrict is known in EGCS 1.2 and above, and in clang.
+ It works also in C++ mode (outside of arrays), but only when spelled
+ as '__restrict', not 'restrict'. */
+#if !(__GNUC_PREREQ (2,92) || __clang_major__ >= 3)
+# if defined __STDC_VERSION__ && __STDC_VERSION__ >= 199901L
+# define __restrict restrict
+# else
+# define __restrict /* Ignore */
+# endif
+#endif
+
+/* ISO C99 also allows to declare arrays as non-overlapping. The syntax is
+ array_name[restrict]
+ GCC 3.1 and clang support this.
+ This syntax is not usable in C++ mode. */
+#if (__GNUC_PREREQ (3,1) || __clang_major__ >= 3) && !defined __cplusplus
+# define __restrict_arr __restrict
+#else
+# ifdef __GNUC__
+# define __restrict_arr /* Not supported in old GCC. */
+# else
+# if defined __STDC_VERSION__ && __STDC_VERSION__ >= 199901L
+# define __restrict_arr restrict
+# else
+/* Some other non-C99 compiler. */
+# define __restrict_arr /* Not supported. */
+# endif
+# endif
+#endif
+
+#if (__GNUC__ >= 3) || __glibc_has_builtin (__builtin_expect)
+# define __glibc_unlikely(cond) __builtin_expect ((cond), 0)
+# define __glibc_likely(cond) __builtin_expect ((cond), 1)
+#else
+# define __glibc_unlikely(cond) (cond)
+# define __glibc_likely(cond) (cond)
+#endif
+
+#if (!defined _Noreturn \
+ && (defined __STDC_VERSION__ ? __STDC_VERSION__ : 0) < 201112 \
+ && !(__GNUC_PREREQ (4,7) \
+ || (3 < __clang_major__ + (5 <= __clang_minor__))))
+# if __GNUC_PREREQ (2,8)
+# define _Noreturn __attribute__ ((__noreturn__))
+# else
+# define _Noreturn
+# endif
+#endif
+
+#if __GNUC_PREREQ (8, 0)
+/* Describes a char array whose address can safely be passed as the first
+ argument to strncpy and strncat, as the char array is not necessarily
+ a NUL-terminated string. */
+# define __attribute_nonstring__ __attribute__ ((__nonstring__))
+#else
+# define __attribute_nonstring__
+#endif
+
+/* Undefine (also defined in libc-symbols.h). */
+#undef __attribute_copy__
+#if __GNUC_PREREQ (9, 0)
+/* Copies attributes from the declaration or type referenced by
+ the argument. */
+# define __attribute_copy__(arg) __attribute__ ((__copy__ (arg)))
+#else
+# define __attribute_copy__(arg)
+#endif
+
+#if (!defined _Static_assert && !defined __cplusplus \
+ && (defined __STDC_VERSION__ ? __STDC_VERSION__ : 0) < 201112 \
+ && (!(__GNUC_PREREQ (4, 6) || __clang_major__ >= 4) \
+ || defined __STRICT_ANSI__))
+# define _Static_assert(expr, diagnostic) \
+ extern int (*__Static_assert_function (void)) \
+ [!!sizeof (struct { int __error_if_negative: (expr) ? 2 : -1; })]
+#endif
+
+/* Gnulib avoids including these, as they don't work on non-glibc or
+ older glibc platforms. */
+#ifndef __GNULIB_CDEFS
+# include <bits/wordsize.h>
+# include <bits/long-double.h>
+#endif
+
+#if __LDOUBLE_REDIRECTS_TO_FLOAT128_ABI == 1
+# ifdef __REDIRECT
+
+/* Alias name defined automatically. */
+# define __LDBL_REDIR(name, proto) ... unused__ldbl_redir
+# define __LDBL_REDIR_DECL(name) \
+ extern __typeof (name) name __asm (__ASMNAME ("__" #name "ieee128"));
+
+/* Alias name defined automatically, with leading underscores. */
+# define __LDBL_REDIR2_DECL(name) \
+ extern __typeof (__##name) __##name \
+ __asm (__ASMNAME ("__" #name "ieee128"));
+
+/* Alias name defined manually. */
+# define __LDBL_REDIR1(name, proto, alias) ... unused__ldbl_redir1
+# define __LDBL_REDIR1_DECL(name, alias) \
+ extern __typeof (name) name __asm (__ASMNAME (#alias));
+
+# define __LDBL_REDIR1_NTH(name, proto, alias) \
+ __REDIRECT_NTH (name, proto, alias)
+# define __REDIRECT_NTH_LDBL(name, proto, alias) \
+ __LDBL_REDIR1_NTH (name, proto, __##alias##ieee128)
+
+/* Unused. */
+# define __REDIRECT_LDBL(name, proto, alias) ... unused__redirect_ldbl
+# define __LDBL_REDIR_NTH(name, proto) ... unused__ldbl_redir_nth
+
+# else
+_Static_assert (0, "IEEE 128-bits long double requires redirection on this platform");
+# endif
+#elif defined __LONG_DOUBLE_MATH_OPTIONAL && defined __NO_LONG_DOUBLE_MATH
+# define __LDBL_COMPAT 1
+# ifdef __REDIRECT
+# define __LDBL_REDIR1(name, proto, alias) __REDIRECT (name, proto, alias)
+# define __LDBL_REDIR(name, proto) \
+ __LDBL_REDIR1 (name, proto, __nldbl_##name)
+# define __LDBL_REDIR1_NTH(name, proto, alias) __REDIRECT_NTH (name, proto, alias)
+# define __LDBL_REDIR_NTH(name, proto) \
+ __LDBL_REDIR1_NTH (name, proto, __nldbl_##name)
+# define __LDBL_REDIR2_DECL(name) \
+ extern __typeof (__##name) __##name __asm (__ASMNAME ("__nldbl___" #name));
+# define __LDBL_REDIR1_DECL(name, alias) \
+ extern __typeof (name) name __asm (__ASMNAME (#alias));
+# define __LDBL_REDIR_DECL(name) \
+ extern __typeof (name) name __asm (__ASMNAME ("__nldbl_" #name));
+# define __REDIRECT_LDBL(name, proto, alias) \
+ __LDBL_REDIR1 (name, proto, __nldbl_##alias)
+# define __REDIRECT_NTH_LDBL(name, proto, alias) \
+ __LDBL_REDIR1_NTH (name, proto, __nldbl_##alias)
+# endif
+#endif
+#if (!defined __LDBL_COMPAT && __LDOUBLE_REDIRECTS_TO_FLOAT128_ABI == 0) \
+ || !defined __REDIRECT
+# define __LDBL_REDIR1(name, proto, alias) name proto
+# define __LDBL_REDIR(name, proto) name proto
+# define __LDBL_REDIR1_NTH(name, proto, alias) name proto __THROW
+# define __LDBL_REDIR_NTH(name, proto) name proto __THROW
+# define __LDBL_REDIR2_DECL(name)
+# define __LDBL_REDIR_DECL(name)
+# ifdef __REDIRECT
+# define __REDIRECT_LDBL(name, proto, alias) __REDIRECT (name, proto, alias)
+# define __REDIRECT_NTH_LDBL(name, proto, alias) \
+ __REDIRECT_NTH (name, proto, alias)
+# endif
+#endif
+
+/* __glibc_macro_warning (MESSAGE) issues warning MESSAGE. This is
+ intended for use in preprocessor macros.
+
+ Note: MESSAGE must be a _single_ string; concatenation of string
+ literals is not supported. */
+#if __GNUC_PREREQ (4,8) || __glibc_clang_prereq (3,5)
+# define __glibc_macro_warning1(message) _Pragma (#message)
+# define __glibc_macro_warning(message) \
+ __glibc_macro_warning1 (GCC warning message)
+#else
+# define __glibc_macro_warning(msg)
+#endif
+
+/* Generic selection (ISO C11) is a C-only feature, available in GCC
+ since version 4.9. Previous versions do not provide generic
+ selection, even though they might set __STDC_VERSION__ to 201112L,
+ when in -std=c11 mode. Thus, we must check for !defined __GNUC__
+ when testing __STDC_VERSION__ for generic selection support.
+ On the other hand, Clang also defines __GNUC__, so a clang-specific
+ check is required to enable the use of generic selection. */
+#if !defined __cplusplus \
+ && (__GNUC_PREREQ (4, 9) \
+ || __glibc_has_extension (c_generic_selections) \
+ || (!defined __GNUC__ && defined __STDC_VERSION__ \
+ && __STDC_VERSION__ >= 201112L))
+# define __HAVE_GENERIC_SELECTION 1
+#else
+# define __HAVE_GENERIC_SELECTION 0
+#endif
+
+#if __GNUC_PREREQ (10, 0)
+/* Designates a 1-based positional argument ref-index of pointer type
+ that can be used to access size-index elements of the pointed-to
+ array according to access mode, or at least one element when
+ size-index is not provided:
+ access (access-mode, <ref-index> [, <size-index>]) */
+# define __attr_access(x) __attribute__ ((__access__ x))
+/* For _FORTIFY_SOURCE == 3 we use __builtin_dynamic_object_size, which may
+ use the access attribute to get object sizes from function definition
+ arguments, so we can't use them on functions we fortify. Drop the object
+ size hints for such functions. */
+# if __USE_FORTIFY_LEVEL == 3
+# define __fortified_attr_access(a, o, s) __attribute__ ((__access__ (a, o)))
+# else
+# define __fortified_attr_access(a, o, s) __attr_access ((a, o, s))
+# endif
+# if __GNUC_PREREQ (11, 0)
+# define __attr_access_none(argno) __attribute__ ((__access__ (__none__, argno)))
+# else
+# define __attr_access_none(argno)
+# endif
+#else
+# define __fortified_attr_access(a, o, s)
+# define __attr_access(x)
+# define __attr_access_none(argno)
+#endif
+
+#if __GNUC_PREREQ (11, 0)
+/* Designates dealloc as a function to call to deallocate objects
+ allocated by the declared function. */
+# define __attr_dealloc(dealloc, argno) \
+ __attribute__ ((__malloc__ (dealloc, argno)))
+# define __attr_dealloc_free __attr_dealloc (__builtin_free, 1)
+#else
+# define __attr_dealloc(dealloc, argno)
+# define __attr_dealloc_free
+#endif
+
+/* Specify that a function such as setjmp or vfork may return
+ twice. */
+#if __GNUC_PREREQ (4, 1)
+# define __attribute_returns_twice__ __attribute__ ((__returns_twice__))
+#else
+# define __attribute_returns_twice__ /* Ignore. */
+#endif
+
+#endif /* sys/cdefs.h */
diff --git a/lib/cloexec.c b/lib/cloexec.c
index 2b67a0102e7..812be01a06c 100644
--- a/lib/cloexec.c
+++ b/lib/cloexec.c
@@ -1,21 +1,21 @@
/* cloexec.c - set or clear the close-on-exec descriptor flag
- Copyright (C) 1991, 2004-2006, 2009-2017 Free Software Foundation, Inc.
+ Copyright (C) 1991, 2004-2006, 2009-2022 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 file is free software: you can redistribute it and/or modify
+ it under the terms of the GNU Lesser General Public License as
+ published by the Free Software Foundation; either version 2.1 of the
+ License, or (at your option) any later version.
- This program is distributed in the hope that it will be useful,
+ This file 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.
+ GNU Lesser General Public License for more details.
- You should have received a copy of the GNU General Public License
- along with this program. If not, see <https://www.gnu.org/licenses/>.
+ You should have received a copy of the GNU Lesser General Public License
+ along with this program. If not, see <https://www.gnu.org/licenses/>. */
- The code is taken from glibc/manual/llio.texi */
+/* The code is taken from glibc/manual/llio.texi */
#include <config.h>
diff --git a/lib/cloexec.h b/lib/cloexec.h
index d937a406817..7a22d775327 100644
--- a/lib/cloexec.h
+++ b/lib/cloexec.h
@@ -1,21 +1,19 @@
/* cloexec.c - set or clear the close-on-exec descriptor flag
- Copyright (C) 2004, 2009-2017 Free Software Foundation, Inc.
+ Copyright (C) 2004, 2009-2022 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 file is free software: you can redistribute it and/or modify
+ it under the terms of the GNU Lesser General Public License as
+ published by the Free Software Foundation; either version 2.1 of the
+ License, or (at your option) any later version.
- This program is distributed in the hope that it will be useful,
+ This file 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.
+ GNU Lesser General Public License for more details.
- You should have received a copy of the GNU General Public License
- along with this program. If not, see <https://www.gnu.org/licenses/>.
-
-*/
+ You should have received a copy of the GNU Lesser General Public License
+ along with this program. If not, see <https://www.gnu.org/licenses/>. */
#include <stdbool.h>
diff --git a/lib/close-stream.c b/lib/close-stream.c
index 19707626fa2..9b0e97b271d 100644
--- a/lib/close-stream.c
+++ b/lib/close-stream.c
@@ -1,10 +1,10 @@
/* Close a stream, with nicer error checking than fclose's.
- Copyright (C) 1998-2002, 2004, 2006-2017 Free Software Foundation, Inc.
+ Copyright (C) 1998-2002, 2004, 2006-2022 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
+ 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,
diff --git a/lib/close-stream.h b/lib/close-stream.h
index be3d4196b06..2b4c8ed8f5b 100644
--- a/lib/close-stream.h
+++ b/lib/close-stream.h
@@ -1,2 +1,20 @@
+/* Close a stream, with nicer error checking than fclose's.
+
+ Copyright (C) 2006-2022 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 the Free Software Foundation, either version 3 of the License,
+ or (at your option) any later version.
+
+ This file is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program. If not, see <https://www.gnu.org/licenses/>. */
+
#include <stdio.h>
+
int close_stream (FILE *stream);
diff --git a/lib/copy-file-range.c b/lib/copy-file-range.c
new file mode 100644
index 00000000000..1ec7f4de67c
--- /dev/null
+++ b/lib/copy-file-range.c
@@ -0,0 +1,67 @@
+/* Stub for copy_file_range
+ Copyright 2019-2022 Free Software Foundation, Inc.
+
+ This file is free software: you can redistribute it and/or modify
+ it under the terms of the GNU Lesser General Public License as
+ published by the Free Software Foundation; either version 2.1 of the
+ License, or (at your option) any later version.
+
+ This file 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 Lesser General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public License
+ along with this program. If not, see <https://www.gnu.org/licenses/>. */
+
+#include <config.h>
+
+#include <unistd.h>
+
+#include <errno.h>
+
+#if defined __linux__ && HAVE_COPY_FILE_RANGE
+# include <sys/utsname.h>
+#endif
+
+ssize_t
+copy_file_range (int infd, off_t *pinoff,
+ int outfd, off_t *poutoff,
+ size_t length, unsigned int flags)
+{
+#undef copy_file_range
+
+#if defined __linux__ && HAVE_COPY_FILE_RANGE
+ /* The implementation of copy_file_range (which first appeared in
+ Linux kernel release 4.5) had many issues before release 5.3
+ <https://lwn.net/Articles/789527/>, so fail with ENOSYS for Linux
+ kernels 5.2 and earlier.
+
+ This workaround, and the configure-time check for Linux, can be
+ removed when such kernels (released March 2016 through September
+ 2019) are no longer a consideration. As of January 2021, the
+ furthest-future planned kernel EOL is December 2024 for kernel
+ release 4.19. */
+
+ static signed char ok;
+
+ if (! ok)
+ {
+ struct utsname name;
+ uname (&name);
+ char *p = name.release;
+ ok = ((p[1] != '.' || '5' < p[0]
+ || (p[0] == '5' && (p[3] != '.' || '2' < p[2])))
+ ? 1 : -1);
+ }
+
+ if (0 < ok)
+ return copy_file_range (infd, pinoff, outfd, poutoff, length, flags);
+#endif
+
+ /* There is little need to emulate copy_file_range with read+write,
+ since programs that use copy_file_range must fall back on
+ read+write anyway. */
+ errno = ENOSYS;
+ return -1;
+}
diff --git a/lib/count-leading-zeros.c b/lib/count-leading-zeros.c
index d0c0704f582..8eb1d2c1005 100644
--- a/lib/count-leading-zeros.c
+++ b/lib/count-leading-zeros.c
@@ -1,3 +1,21 @@
+/* Count the number of leading 0 bits in a word.
+
+ Copyright (C) 2012-2022 Free Software Foundation, Inc.
+
+ This file is free software: you can redistribute it and/or modify
+ it under the terms of the GNU Lesser General Public License as
+ published by the Free Software Foundation; either version 2.1 of the
+ License, or (at your option) any later version.
+
+ This file 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 Lesser General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public License
+ along with this program. If not, see <https://www.gnu.org/licenses/>. */
+
#include <config.h>
+
#define COUNT_LEADING_ZEROS_INLINE _GL_EXTERN_INLINE
#include "count-leading-zeros.h"
diff --git a/lib/count-leading-zeros.h b/lib/count-leading-zeros.h
index c8b3dc05110..354641af0a2 100644
--- a/lib/count-leading-zeros.h
+++ b/lib/count-leading-zeros.h
@@ -1,17 +1,17 @@
/* count-leading-zeros.h -- counts the number of leading 0 bits in a word.
- Copyright (C) 2012-2017 Free Software Foundation, Inc.
+ Copyright (C) 2012-2022 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 file is free software: you can redistribute it and/or modify
+ it under the terms of the GNU Lesser General Public License as
+ published by the Free Software Foundation; either version 2.1 of the
+ License, or (at your option) any later version.
- This program is distributed in the hope that it will be useful,
+ This file 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.
+ GNU Lesser General Public License for more details.
- You should have received a copy of the GNU General Public License
+ You should have received a copy of the GNU Lesser General Public License
along with this program. If not, see <https://www.gnu.org/licenses/>. */
/* Written by Eric Blake. */
@@ -30,11 +30,16 @@ _GL_INLINE_HEADER_BEGIN
# define COUNT_LEADING_ZEROS_INLINE _GL_INLINE
#endif
+#ifdef __cplusplus
+extern "C" {
+#endif
+
/* Assuming the GCC builtin is BUILTIN and the MSC builtin is MSC_BUILTIN,
expand to code that computes the number of leading zeros of the local
variable 'x' of type TYPE (an unsigned integer type) and return it
from the current function. */
-#if __GNUC__ > 3 || (__GNUC__ == 3 && __GNUC_MINOR__ >= 4)
+#if __GNUC__ > 3 || (__GNUC__ == 3 && __GNUC_MINOR__ >= 4) \
+ || (__clang_major__ >= 4)
# define COUNT_LEADING_ZEROS(BUILTIN, MSC_BUILTIN, TYPE) \
return x ? BUILTIN (x) : CHAR_BIT * sizeof x;
#elif _MSC_VER
@@ -71,7 +76,7 @@ COUNT_LEADING_ZEROS_INLINE int
count_leading_zeros_32 (unsigned int x)
{
/* <https://github.com/gibsjose/BitHacks>
- <http://www.fit.vutbr.cz/~ibarina/pub/bithacks.pdf> */
+ <https://www.fit.vutbr.cz/~ibarina/pub/bithacks.pdf> */
static const char de_Bruijn_lookup[32] = {
31, 22, 30, 21, 18, 10, 29, 2, 20, 17, 15, 13, 9, 6, 28, 1,
23, 19, 11, 3, 16, 14, 7, 24, 12, 4, 8, 25, 5, 26, 27, 0
@@ -100,7 +105,6 @@ count_leading_zeros_l (unsigned long int x)
COUNT_LEADING_ZEROS (__builtin_clzl, _BitScanReverse, unsigned long int);
}
-#if HAVE_UNSIGNED_LONG_LONG_INT
/* Compute and return the number of leading zeros in X. */
COUNT_LEADING_ZEROS_INLINE int
count_leading_zeros_ll (unsigned long long int x)
@@ -108,6 +112,9 @@ count_leading_zeros_ll (unsigned long long int x)
COUNT_LEADING_ZEROS (__builtin_clzll, _BitScanReverse64,
unsigned long long int);
}
+
+#ifdef __cplusplus
+}
#endif
_GL_INLINE_HEADER_END
diff --git a/lib/count-one-bits.c b/lib/count-one-bits.c
index 66341d77cda..67a61dad61e 100644
--- a/lib/count-one-bits.c
+++ b/lib/count-one-bits.c
@@ -1,4 +1,22 @@
+/* Count the number of 1-bits in a word.
+
+ Copyright (C) 2012-2022 Free Software Foundation, Inc.
+
+ This file is free software: you can redistribute it and/or modify
+ it under the terms of the GNU Lesser General Public License as
+ published by the Free Software Foundation; either version 2.1 of the
+ License, or (at your option) any later version.
+
+ This file 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 Lesser General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public License
+ along with this program. If not, see <https://www.gnu.org/licenses/>. */
+
#include <config.h>
+
#define COUNT_ONE_BITS_INLINE _GL_EXTERN_INLINE
#include "count-one-bits.h"
diff --git a/lib/count-one-bits.h b/lib/count-one-bits.h
index 1576b08481b..7d24c45a0d3 100644
--- a/lib/count-one-bits.h
+++ b/lib/count-one-bits.h
@@ -1,17 +1,17 @@
/* count-one-bits.h -- counts the number of 1-bits in a word.
- Copyright (C) 2007-2017 Free Software Foundation, Inc.
+ Copyright (C) 2007-2022 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 file is free software: you can redistribute it and/or modify
+ it under the terms of the GNU Lesser General Public License as
+ published by the Free Software Foundation; either version 2.1 of the
+ License, or (at your option) any later version.
- This program is distributed in the hope that it will be useful,
+ This file 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.
+ GNU Lesser General Public License for more details.
- You should have received a copy of the GNU General Public License
+ You should have received a copy of the GNU Lesser General Public License
along with this program. If not, see <https://www.gnu.org/licenses/>. */
/* Written by Ben Pfaff. */
@@ -30,29 +30,18 @@ _GL_INLINE_HEADER_BEGIN
# define COUNT_ONE_BITS_INLINE _GL_INLINE
#endif
-/* Expand to code that computes the number of 1-bits of the local
- variable 'x' of type TYPE (an unsigned integer type) and return it
- from the current function. */
-#define COUNT_ONE_BITS_GENERIC(TYPE) \
- do \
- { \
- int count = 0; \
- int bits; \
- for (bits = 0; bits < sizeof (TYPE) * CHAR_BIT; bits += 32) \
- { \
- count += count_one_bits_32 (x); \
- x = x >> 31 >> 1; \
- } \
- return count; \
- } \
- while (0)
+#ifdef __cplusplus
+extern "C" {
+#endif
-/* Assuming the GCC builtin is BUILTIN and the MSC builtin is MSC_BUILTIN,
+/* Assuming the GCC builtin is GCC_BUILTIN and the MSC builtin is MSC_BUILTIN,
expand to code that computes the number of 1-bits of the local
variable 'x' of type TYPE (an unsigned integer type) and return it
from the current function. */
-#if __GNUC__ > 3 || (__GNUC__ == 3 && __GNUC_MINOR__ >= 4)
-# define COUNT_ONE_BITS(BUILTIN, MSC_BUILTIN, TYPE) return BUILTIN (x)
+#if (__GNUC__ > 3 || (__GNUC__ == 3 && __GNUC_MINOR__ >= 4)) \
+ || (__clang_major__ >= 4)
+# define COUNT_ONE_BITS(GCC_BUILTIN, MSC_BUILTIN, TYPE) \
+ return GCC_BUILTIN (x)
#else
/* Compute and return the number of 1-bits set in the least
@@ -67,14 +56,46 @@ count_one_bits_32 (unsigned int x)
return (x >> 8) + (x & 0x00ff);
}
+/* Expand to code that computes the number of 1-bits of the local
+ variable 'x' of type TYPE (an unsigned integer type) and return it
+ from the current function. */
+# define COUNT_ONE_BITS_GENERIC(TYPE) \
+ do \
+ { \
+ int count = 0; \
+ int bits; \
+ for (bits = 0; bits < sizeof (TYPE) * CHAR_BIT; bits += 32) \
+ { \
+ count += count_one_bits_32 (x); \
+ x = x >> 31 >> 1; \
+ } \
+ return count; \
+ } \
+ while (0)
+
# if 1500 <= _MSC_VER && (defined _M_IX86 || defined _M_X64)
/* While gcc falls back to its own generic code if the machine
on which it's running doesn't support popcount, with Microsoft's
compiler we need to detect and fallback ourselves. */
-# pragma intrinsic __cpuid
-# pragma intrinsic __popcnt
-# pragma intrinsic __popcnt64
+
+# if 0
+# include <intrin.h>
+# else
+ /* Don't pollute the namespace with too many MSVC intrinsics. */
+# pragma intrinsic (__cpuid)
+# pragma intrinsic (__popcnt)
+# if defined _M_X64
+# pragma intrinsic (__popcnt64)
+# endif
+# endif
+
+# if !defined _M_X64
+static inline __popcnt64 (unsigned long long x)
+{
+ return __popcnt ((unsigned int) (x >> 32)) + __popcnt ((unsigned int) x);
+}
+# endif
/* Return nonzero if popcount is supported. */
@@ -86,25 +107,30 @@ popcount_supported (void)
{
if (popcount_support < 0)
{
+ /* Do as described in
+ <https://docs.microsoft.com/en-us/cpp/intrinsics/popcnt16-popcnt-popcnt64> */
int cpu_info[4];
__cpuid (cpu_info, 1);
- popcount_support = (cpu_info[2] >> 23) & 1; /* See MSDN. */
+ popcount_support = (cpu_info[2] >> 23) & 1;
}
return popcount_support;
}
-# define COUNT_ONE_BITS(BUILTIN, MSC_BUILTIN, TYPE) \
- do \
- { \
- if (popcount_supported ()) \
- return MSC_BUILTIN (x); \
- else \
- COUNT_ONE_BITS_GENERIC (TYPE); \
- } \
+# define COUNT_ONE_BITS(GCC_BUILTIN, MSC_BUILTIN, TYPE) \
+ do \
+ { \
+ if (popcount_supported ()) \
+ return MSC_BUILTIN (x); \
+ else \
+ COUNT_ONE_BITS_GENERIC (TYPE); \
+ } \
while (0)
+
# else
-# define COUNT_ONE_BITS(BUILTIN, MSC_BUILTIN, TYPE) \
+
+# define COUNT_ONE_BITS(GCC_BUILTIN, MSC_BUILTIN, TYPE) \
COUNT_ONE_BITS_GENERIC (TYPE)
+
# endif
#endif
@@ -122,13 +148,15 @@ count_one_bits_l (unsigned long int x)
COUNT_ONE_BITS (__builtin_popcountl, __popcnt, unsigned long int);
}
-#if HAVE_UNSIGNED_LONG_LONG_INT
/* Compute and return the number of 1-bits set in X. */
COUNT_ONE_BITS_INLINE int
count_one_bits_ll (unsigned long long int x)
{
COUNT_ONE_BITS (__builtin_popcountll, __popcnt64, unsigned long long int);
}
+
+#ifdef __cplusplus
+}
#endif
_GL_INLINE_HEADER_END
diff --git a/lib/count-trailing-zeros.c b/lib/count-trailing-zeros.c
index f3da8867428..143dcda55d1 100644
--- a/lib/count-trailing-zeros.c
+++ b/lib/count-trailing-zeros.c
@@ -1,3 +1,21 @@
+/* Count the number of trailing 0 bits in a word.
+
+ Copyright 2013-2022 Free Software Foundation, Inc.
+
+ This file is free software: you can redistribute it and/or modify
+ it under the terms of the GNU Lesser General Public License as
+ published by the Free Software Foundation; either version 2.1 of the
+ License, or (at your option) any later version.
+
+ This file 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 Lesser General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public License
+ along with this program. If not, see <https://www.gnu.org/licenses/>. */
+
#include <config.h>
+
#define COUNT_TRAILING_ZEROS_INLINE _GL_EXTERN_INLINE
#include "count-trailing-zeros.h"
diff --git a/lib/count-trailing-zeros.h b/lib/count-trailing-zeros.h
index 9f9f07f5a0d..9a989a43245 100644
--- a/lib/count-trailing-zeros.h
+++ b/lib/count-trailing-zeros.h
@@ -1,17 +1,17 @@
/* count-trailing-zeros.h -- counts the number of trailing 0 bits in a word.
- Copyright 2013-2017 Free Software Foundation, Inc.
+ Copyright 2013-2022 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 file is free software: you can redistribute it and/or modify
+ it under the terms of the GNU Lesser General Public License as
+ published by the Free Software Foundation; either version 2.1 of the
+ License, or (at your option) any later version.
- This program is distributed in the hope that it will be useful,
+ This file 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.
+ GNU Lesser General Public License for more details.
- You should have received a copy of the GNU General Public License
+ You should have received a copy of the GNU Lesser General Public License
along with this program. If not, see <https://www.gnu.org/licenses/>. */
/* Written by Paul Eggert. */
@@ -30,11 +30,16 @@ _GL_INLINE_HEADER_BEGIN
# define COUNT_TRAILING_ZEROS_INLINE _GL_INLINE
#endif
+#ifdef __cplusplus
+extern "C" {
+#endif
+
/* Assuming the GCC builtin is BUILTIN and the MSC builtin is MSC_BUILTIN,
expand to code that computes the number of trailing zeros of the local
variable 'x' of type TYPE (an unsigned integer type) and return it
from the current function. */
-#if __GNUC__ > 3 || (__GNUC__ == 3 && __GNUC_MINOR__ >= 4)
+#if __GNUC__ > 3 || (__GNUC__ == 3 && __GNUC_MINOR__ >= 4) \
+ || (__clang_major__ >= 4)
# define COUNT_TRAILING_ZEROS(BUILTIN, MSC_BUILTIN, TYPE) \
return x ? BUILTIN (x) : CHAR_BIT * sizeof x;
#elif _MSC_VER
@@ -69,7 +74,7 @@ COUNT_TRAILING_ZEROS_INLINE int
count_trailing_zeros_32 (unsigned int x)
{
/* <https://github.com/gibsjose/BitHacks>
- <http://www.fit.vutbr.cz/~ibarina/pub/bithacks.pdf> */
+ <https://www.fit.vutbr.cz/~ibarina/pub/bithacks.pdf> */
static const char de_Bruijn_lookup[32] = {
0, 1, 28, 2, 29, 14, 24, 3, 30, 22, 20, 15, 25, 17, 4, 8,
31, 27, 13, 23, 21, 19, 16, 7, 26, 12, 18, 6, 11, 5, 10, 9
@@ -92,7 +97,6 @@ count_trailing_zeros_l (unsigned long int x)
COUNT_TRAILING_ZEROS (__builtin_ctzl, _BitScanForward, unsigned long int);
}
-#if HAVE_UNSIGNED_LONG_LONG_INT
/* Compute and return the number of trailing zeros in X. */
COUNT_TRAILING_ZEROS_INLINE int
count_trailing_zeros_ll (unsigned long long int x)
@@ -100,6 +104,9 @@ count_trailing_zeros_ll (unsigned long long int x)
COUNT_TRAILING_ZEROS (__builtin_ctzll, _BitScanForward64,
unsigned long long int);
}
+
+#ifdef __cplusplus
+}
#endif
_GL_INLINE_HEADER_END
diff --git a/lib/diffseq.h b/lib/diffseq.h
index b6f9f6f9d19..0f76ea1d5ad 100644
--- a/lib/diffseq.h
+++ b/lib/diffseq.h
@@ -1,11 +1,11 @@
/* Analyze differences between two vectors.
- Copyright (C) 1988-1989, 1992-1995, 2001-2004, 2006-2017 Free Software
+ Copyright (C) 1988-1989, 1992-1995, 2001-2004, 2006-2022 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
+ 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,
@@ -28,13 +28,13 @@
The basic algorithm is described in:
"An O(ND) Difference Algorithm and its Variations", Eugene W. Myers,
Algorithmica Vol. 1, 1986, pp. 251-266,
- <http://dx.doi.org/10.1007/BF01840446>.
+ <https://doi.org/10.1007/BF01840446>.
See especially section 4.2, which describes the variation used below.
The basic algorithm was independently discovered as described in:
"Algorithms for Approximate String Matching", Esko Ukkonen,
Information and Control Vol. 64, 1985, pp. 100-118,
- <http://dx.doi.org/10.1016/S0019-9958(85)80046-2>.
+ <https://doi.org/10.1016/S0019-9958(85)80046-2>.
Unless the 'find_minimal' flag is set, this code uses the TOO_EXPENSIVE
heuristic, by Paul Eggert, to limit the cost to O(N**1.5 log N)
@@ -51,10 +51,14 @@
EXTRA_CONTEXT_FIELDS Declarations of fields for 'struct context'.
NOTE_DELETE(ctxt, xoff) Record the removal of the object xvec[xoff].
NOTE_INSERT(ctxt, yoff) Record the insertion of the object yvec[yoff].
+ NOTE_ORDERED (Optional) A boolean expression saying that
+ NOTE_DELETE and NOTE_INSERT calls must be
+ issued in offset order.
EARLY_ABORT(ctxt) (Optional) A boolean expression that triggers an
early abort of the computation.
USE_HEURISTIC (Optional) Define if you want to support the
heuristic for large vectors.
+
It is also possible to use this file with abstract arrays. In this case,
xvec and yvec are not represented in memory. They only exist conceptually.
In this case, the list of defines above is amended as follows:
@@ -63,6 +67,7 @@
XVECREF_YVECREF_EQUAL(ctxt, xoff, yoff)
A three-argument macro: References xvec[xoff] and
yvec[yoff] and tests these elements for equality.
+
Before including this file, you also need to include:
#include <limits.h>
#include <stdbool.h>
@@ -78,6 +83,10 @@
# define EARLY_ABORT(ctxt) false
#endif
+#ifndef NOTE_ORDERED
+# define NOTE_ORDERED false
+#endif
+
/* Use this to suppress gcc's "...may be used before initialized" warnings.
Beware: The Code argument must not contain commas. */
#ifndef IF_LINT
@@ -88,15 +97,6 @@
# endif
#endif
-/* As above, but when Code must contain one comma. */
-#ifndef IF_LINT2
-# if defined GCC_LINT || defined lint
-# define IF_LINT2(Code1, Code2) Code1, Code2
-# else
-# define IF_LINT2(Code1, Code2) /* empty */
-# endif
-#endif
-
/*
* Context of comparison operation.
*/
@@ -468,49 +468,89 @@ compareseq (OFFSET xoff, OFFSET xlim, OFFSET yoff, OFFSET ylim,
#define XREF_YREF_EQUAL(x,y) XVECREF_YVECREF_EQUAL (ctxt, x, y)
#endif
- /* Slide down the bottom initial diagonal. */
- while (xoff < xlim && yoff < ylim && XREF_YREF_EQUAL (xoff, yoff))
+ while (true)
{
- xoff++;
- yoff++;
- }
+ /* Slide down the bottom initial diagonal. */
+ while (xoff < xlim && yoff < ylim && XREF_YREF_EQUAL (xoff, yoff))
+ {
+ xoff++;
+ yoff++;
+ }
- /* Slide up the top initial diagonal. */
- while (xoff < xlim && yoff < ylim && XREF_YREF_EQUAL (xlim - 1, ylim - 1))
- {
- xlim--;
- ylim--;
- }
+ /* Slide up the top initial diagonal. */
+ while (xoff < xlim && yoff < ylim && XREF_YREF_EQUAL (xlim - 1, ylim - 1))
+ {
+ xlim--;
+ ylim--;
+ }
- /* Handle simple cases. */
- if (xoff == xlim)
- while (yoff < ylim)
- {
- NOTE_INSERT (ctxt, yoff);
- if (EARLY_ABORT (ctxt))
- return true;
- yoff++;
- }
- else if (yoff == ylim)
- while (xoff < xlim)
- {
- NOTE_DELETE (ctxt, xoff);
- if (EARLY_ABORT (ctxt))
- return true;
- xoff++;
- }
- else
- {
- struct partition part IF_LINT2 (= { .xmid = 0, .ymid = 0 });
+ /* Handle simple cases. */
+ if (xoff == xlim)
+ {
+ while (yoff < ylim)
+ {
+ NOTE_INSERT (ctxt, yoff);
+ if (EARLY_ABORT (ctxt))
+ return true;
+ yoff++;
+ }
+ break;
+ }
+ if (yoff == ylim)
+ {
+ while (xoff < xlim)
+ {
+ NOTE_DELETE (ctxt, xoff);
+ if (EARLY_ABORT (ctxt))
+ return true;
+ xoff++;
+ }
+ break;
+ }
+
+ struct partition part;
/* Find a point of correspondence in the middle of the vectors. */
diag (xoff, xlim, yoff, ylim, find_minimal, &part, ctxt);
/* Use the partitions to split this problem into subproblems. */
- if (compareseq (xoff, part.xmid, yoff, part.ymid, part.lo_minimal, ctxt))
- return true;
- if (compareseq (part.xmid, xlim, part.ymid, ylim, part.hi_minimal, ctxt))
- return true;
+ OFFSET xoff1, xlim1, yoff1, ylim1, xoff2, xlim2, yoff2, ylim2;
+ bool find_minimal1, find_minimal2;
+ if (!NOTE_ORDERED
+ && ((xlim + ylim) - (part.xmid + part.ymid)
+ < (part.xmid + part.ymid) - (xoff + yoff)))
+ {
+ /* The second problem is smaller and the caller doesn't
+ care about order, so do the second problem first to
+ lessen recursion. */
+ xoff1 = part.xmid; xlim1 = xlim;
+ yoff1 = part.ymid; ylim1 = ylim;
+ find_minimal1 = part.hi_minimal;
+
+ xoff2 = xoff; xlim2 = part.xmid;
+ yoff2 = yoff; ylim2 = part.ymid;
+ find_minimal2 = part.lo_minimal;
+ }
+ else
+ {
+ xoff1 = xoff; xlim1 = part.xmid;
+ yoff1 = yoff; ylim1 = part.ymid;
+ find_minimal1 = part.lo_minimal;
+
+ xoff2 = part.xmid; xlim2 = xlim;
+ yoff2 = part.ymid; ylim2 = ylim;
+ find_minimal2 = part.hi_minimal;
+ }
+
+ /* Recurse to do one subproblem. */
+ bool early = compareseq (xoff1, xlim1, yoff1, ylim1, find_minimal1, ctxt);
+ if (early)
+ return early;
+
+ /* Iterate to do the other subproblem. */
+ xoff = xoff2; xlim = xlim2;
+ yoff = yoff2; ylim = ylim2;
+ find_minimal = find_minimal2;
}
return false;
diff --git a/lib/dirent.in.h b/lib/dirent.in.h
index 5b235731e04..f28288d1acc 100644
--- a/lib/dirent.in.h
+++ b/lib/dirent.in.h
@@ -1,17 +1,17 @@
/* A GNU-like <dirent.h>.
- Copyright (C) 2006-2017 Free Software Foundation, Inc.
+ Copyright (C) 2006-2022 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 file is free software: you can redistribute it and/or modify
+ it under the terms of the GNU Lesser General Public License as
+ published by the Free Software Foundation; either version 2.1 of the
+ License, or (at your option) any later version.
- This program is distributed in the hope that it will be useful,
+ This file 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.
+ GNU Lesser General Public License for more details.
- You should have received a copy of the GNU General Public License
+ You should have received a copy of the GNU Lesser General Public License
along with this program. If not, see <https://www.gnu.org/licenses/>. */
#ifndef _@GUARD_PREFIX@_DIRENT_H
@@ -55,12 +55,36 @@ typedef struct gl_directory DIR;
# endif
#endif
+/* _GL_ATTRIBUTE_DEALLOC (F, I) declares that the function returns pointers
+ that can be freed by passing them as the Ith argument to the
+ function F. */
+#ifndef _GL_ATTRIBUTE_DEALLOC
+# if __GNUC__ >= 11
+# define _GL_ATTRIBUTE_DEALLOC(f, i) __attribute__ ((__malloc__ (f, i)))
+# else
+# define _GL_ATTRIBUTE_DEALLOC(f, i)
+# endif
+#endif
+
+/* _GL_ATTRIBUTE_MALLOC declares that the function returns a pointer to freshly
+ allocated memory. */
+/* Applies to: functions. */
+#ifndef _GL_ATTRIBUTE_MALLOC
+# if __GNUC__ >= 3 || defined __clang__
+# define _GL_ATTRIBUTE_MALLOC __attribute__ ((__malloc__))
+# else
+# define _GL_ATTRIBUTE_MALLOC
+# endif
+#endif
+
/* The __attribute__ feature is available in gcc versions 2.5 and later.
The attribute __pure__ was added in gcc 2.96. */
-#if __GNUC__ > 2 || (__GNUC__ == 2 && __GNUC_MINOR__ >= 96)
-# define _GL_ATTRIBUTE_PURE __attribute__ ((__pure__))
-#else
-# define _GL_ATTRIBUTE_PURE /* empty */
+#ifndef _GL_ATTRIBUTE_PURE
+# if __GNUC__ > 2 || (__GNUC__ == 2 && __GNUC_MINOR__ >= 96) || defined __clang__
+# define _GL_ATTRIBUTE_PURE __attribute__ ((__pure__))
+# else
+# define _GL_ATTRIBUTE_PURE /* empty */
+# endif
#endif
/* The definitions of _GL_FUNCDECL_RPL etc. are copied here. */
@@ -72,6 +96,30 @@ typedef struct gl_directory DIR;
/* Declare overridden functions. */
+#if @GNULIB_CLOSEDIR@
+# if @REPLACE_CLOSEDIR@
+# if !(defined __cplusplus && defined GNULIB_NAMESPACE)
+# undef closedir
+# define closedir rpl_closedir
+# define GNULIB_defined_closedir 1
+# endif
+_GL_FUNCDECL_RPL (closedir, int, (DIR *dirp) _GL_ARG_NONNULL ((1)));
+_GL_CXXALIAS_RPL (closedir, int, (DIR *dirp));
+# else
+# if !@HAVE_CLOSEDIR@
+_GL_FUNCDECL_SYS (closedir, int, (DIR *dirp) _GL_ARG_NONNULL ((1)));
+# endif
+_GL_CXXALIAS_SYS (closedir, int, (DIR *dirp));
+# endif
+_GL_CXXALIASWARN (closedir);
+#elif defined GNULIB_POSIXCHECK
+# undef closedir
+# if HAVE_RAW_DECL_CLOSEDIR
+_GL_WARN_ON_USE (closedir, "closedir is not portable - "
+ "use gnulib module closedir for portability");
+# endif
+#endif
+
#if @GNULIB_OPENDIR@
# if @REPLACE_OPENDIR@
# if !(defined __cplusplus && defined GNULIB_NAMESPACE)
@@ -79,20 +127,36 @@ typedef struct gl_directory DIR;
# define opendir rpl_opendir
# define GNULIB_defined_opendir 1
# endif
-_GL_FUNCDECL_RPL (opendir, DIR *, (const char *dir_name) _GL_ARG_NONNULL ((1)));
+_GL_FUNCDECL_RPL (opendir, DIR *,
+ (const char *dir_name)
+ _GL_ARG_NONNULL ((1))
+ _GL_ATTRIBUTE_MALLOC _GL_ATTRIBUTE_DEALLOC (closedir, 1));
_GL_CXXALIAS_RPL (opendir, DIR *, (const char *dir_name));
# else
-# if !@HAVE_OPENDIR@
-_GL_FUNCDECL_SYS (opendir, DIR *, (const char *dir_name) _GL_ARG_NONNULL ((1)));
+# if !@HAVE_OPENDIR@ || __GNUC__ >= 11
+_GL_FUNCDECL_SYS (opendir, DIR *,
+ (const char *dir_name)
+ _GL_ARG_NONNULL ((1))
+ _GL_ATTRIBUTE_MALLOC _GL_ATTRIBUTE_DEALLOC (closedir, 1));
# endif
_GL_CXXALIAS_SYS (opendir, DIR *, (const char *dir_name));
# endif
_GL_CXXALIASWARN (opendir);
-#elif defined GNULIB_POSIXCHECK
-# undef opendir
-# if HAVE_RAW_DECL_OPENDIR
+#else
+# if @GNULIB_CLOSEDIR@ && __GNUC__ >= 11 && !defined opendir
+/* For -Wmismatched-dealloc: Associate opendir with closedir or
+ rpl_closedir. */
+_GL_FUNCDECL_SYS (opendir, DIR *,
+ (const char *dir_name)
+ _GL_ARG_NONNULL ((1))
+ _GL_ATTRIBUTE_MALLOC _GL_ATTRIBUTE_DEALLOC (closedir, 1));
+# endif
+# if defined GNULIB_POSIXCHECK
+# undef opendir
+# if HAVE_RAW_DECL_OPENDIR
_GL_WARN_ON_USE (opendir, "opendir is not portable - "
"use gnulib module opendir for portability");
+# endif
# endif
#endif
@@ -124,35 +188,12 @@ _GL_WARN_ON_USE (rewinddir, "rewinddir is not portable - "
# endif
#endif
-#if @GNULIB_CLOSEDIR@
-# if @REPLACE_CLOSEDIR@
-# if !(defined __cplusplus && defined GNULIB_NAMESPACE)
-# undef closedir
-# define closedir rpl_closedir
-# define GNULIB_defined_closedir 1
-# endif
-_GL_FUNCDECL_RPL (closedir, int, (DIR *dirp) _GL_ARG_NONNULL ((1)));
-_GL_CXXALIAS_RPL (closedir, int, (DIR *dirp));
-# else
-# if !@HAVE_CLOSEDIR@
-_GL_FUNCDECL_SYS (closedir, int, (DIR *dirp) _GL_ARG_NONNULL ((1)));
-# endif
-_GL_CXXALIAS_SYS (closedir, int, (DIR *dirp));
-# endif
-_GL_CXXALIASWARN (closedir);
-#elif defined GNULIB_POSIXCHECK
-# undef closedir
-# if HAVE_RAW_DECL_CLOSEDIR
-_GL_WARN_ON_USE (closedir, "closedir is not portable - "
- "use gnulib module closedir for portability");
-# endif
-#endif
-
#if @GNULIB_DIRFD@
/* Return the file descriptor associated with the given directory stream,
or -1 if none exists. */
# if @REPLACE_DIRFD@
-# if !(defined __cplusplus && defined GNULIB_NAMESPACE)
+/* On kLIBC, dirfd() is a macro that does not work. Undefine it. */
+# if !(defined __cplusplus && defined GNULIB_NAMESPACE) || defined dirfd
# undef dirfd
# define dirfd rpl_dirfd
# endif
@@ -197,20 +238,33 @@ _GL_WARN_ON_USE (dirfd, "dirfd is unportable - "
# undef fdopendir
# define fdopendir rpl_fdopendir
# endif
-_GL_FUNCDECL_RPL (fdopendir, DIR *, (int fd));
+_GL_FUNCDECL_RPL (fdopendir, DIR *,
+ (int fd)
+ _GL_ATTRIBUTE_MALLOC _GL_ATTRIBUTE_DEALLOC (closedir, 1));
_GL_CXXALIAS_RPL (fdopendir, DIR *, (int fd));
# else
-# if !@HAVE_FDOPENDIR@ || !@HAVE_DECL_FDOPENDIR@
-_GL_FUNCDECL_SYS (fdopendir, DIR *, (int fd));
+# if !@HAVE_FDOPENDIR@ || !@HAVE_DECL_FDOPENDIR@ || __GNUC__ >= 11
+_GL_FUNCDECL_SYS (fdopendir, DIR *,
+ (int fd)
+ _GL_ATTRIBUTE_MALLOC _GL_ATTRIBUTE_DEALLOC (closedir, 1));
# endif
_GL_CXXALIAS_SYS (fdopendir, DIR *, (int fd));
# endif
_GL_CXXALIASWARN (fdopendir);
-#elif defined GNULIB_POSIXCHECK
-# undef fdopendir
-# if HAVE_RAW_DECL_FDOPENDIR
+#else
+# if @GNULIB_CLOSEDIR@ && __GNUC__ >= 11 && !defined fdopendir
+/* For -Wmismatched-dealloc: Associate fdopendir with closedir or
+ rpl_closedir. */
+_GL_FUNCDECL_SYS (fdopendir, DIR *,
+ (int fd)
+ _GL_ATTRIBUTE_MALLOC _GL_ATTRIBUTE_DEALLOC (closedir, 1));
+# endif
+# if defined GNULIB_POSIXCHECK
+# undef fdopendir
+# if HAVE_RAW_DECL_FDOPENDIR
_GL_WARN_ON_USE (fdopendir, "fdopendir is unportable - "
"use gnulib module fdopendir for portability");
+# endif
# endif
#endif
diff --git a/lib/dirfd.c b/lib/dirfd.c
index 7e38fabdac2..4104683fbf0 100644
--- a/lib/dirfd.c
+++ b/lib/dirfd.c
@@ -1,18 +1,18 @@
/* dirfd.c -- return the file descriptor associated with an open DIR*
- Copyright (C) 2001, 2006, 2008-2017 Free Software Foundation, Inc.
+ Copyright (C) 2001, 2006, 2008-2022 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 file is free software: you can redistribute it and/or modify
+ it under the terms of the GNU Lesser General Public License as
+ published by the Free Software Foundation; either version 2.1 of the
+ License, or (at your option) any later version.
- This program is distributed in the hope that it will be useful,
+ This file 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.
+ GNU Lesser General Public License for more details.
- You should have received a copy of the GNU General Public License
+ You should have received a copy of the GNU Lesser General Public License
along with this program. If not, see <https://www.gnu.org/licenses/>. */
/* Written by Jim Meyering. */
diff --git a/lib/dosname.h b/lib/dosname.h
deleted file mode 100644
index 255d57e4d6b..00000000000
--- a/lib/dosname.h
+++ /dev/null
@@ -1,53 +0,0 @@
-/* File names on MS-DOS/Windows systems.
-
- Copyright (C) 2000-2001, 2004-2006, 2009-2017 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/>.
-
- From Paul Eggert and Jim Meyering. */
-
-#ifndef _DOSNAME_H
-#define _DOSNAME_H
-
-#if (defined _WIN32 || defined __WIN32__ || \
- defined __MSDOS__ || defined __CYGWIN__ || \
- defined __EMX__ || defined __DJGPP__)
- /* This internal macro assumes ASCII, but all hosts that support drive
- letters use ASCII. */
-# define _IS_DRIVE_LETTER(C) (((unsigned int) (C) | ('a' - 'A')) - 'a' \
- <= 'z' - 'a')
-# define FILE_SYSTEM_PREFIX_LEN(Filename) \
- (_IS_DRIVE_LETTER ((Filename)[0]) && (Filename)[1] == ':' ? 2 : 0)
-# ifndef __CYGWIN__
-# define FILE_SYSTEM_DRIVE_PREFIX_CAN_BE_RELATIVE 1
-# endif
-# define ISSLASH(C) ((C) == '/' || (C) == '\\')
-#else
-# define FILE_SYSTEM_PREFIX_LEN(Filename) 0
-# define ISSLASH(C) ((C) == '/')
-#endif
-
-#ifndef FILE_SYSTEM_DRIVE_PREFIX_CAN_BE_RELATIVE
-# define FILE_SYSTEM_DRIVE_PREFIX_CAN_BE_RELATIVE 0
-#endif
-
-#if FILE_SYSTEM_DRIVE_PREFIX_CAN_BE_RELATIVE
-# define IS_ABSOLUTE_FILE_NAME(F) ISSLASH ((F)[FILE_SYSTEM_PREFIX_LEN (F)])
-# else
-# define IS_ABSOLUTE_FILE_NAME(F) \
- (ISSLASH ((F)[0]) || FILE_SYSTEM_PREFIX_LEN (F) != 0)
-#endif
-#define IS_RELATIVE_FILE_NAME(F) (! IS_ABSOLUTE_FILE_NAME (F))
-
-#endif /* DOSNAME_H_ */
diff --git a/lib/dtoastr.c b/lib/dtoastr.c
index aed181d66b1..71af14c9df4 100644
--- a/lib/dtoastr.c
+++ b/lib/dtoastr.c
@@ -1,2 +1,19 @@
+/* Convert 'double' to accurate string.
+
+ Copyright (C) 2010-2022 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 the Free Software Foundation, either version 3 of the License,
+ or (at your option) any later version.
+
+ This file 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/>. */
+
#define LENGTH 2
#include "ftoastr.c"
diff --git a/lib/dtotimespec.c b/lib/dtotimespec.c
index 8f2e8150c9b..b62a8bd6cfc 100644
--- a/lib/dtotimespec.c
+++ b/lib/dtotimespec.c
@@ -1,10 +1,10 @@
/* Convert double to timespec.
- Copyright (C) 2011-2017 Free Software Foundation, Inc.
+ Copyright (C) 2011-2022 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
+ 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,
@@ -32,20 +32,20 @@ dtotimespec (double sec)
if (! (TYPE_MINIMUM (time_t) < sec))
return make_timespec (TYPE_MINIMUM (time_t), 0);
else if (! (sec < 1.0 + TYPE_MAXIMUM (time_t)))
- return make_timespec (TYPE_MAXIMUM (time_t), TIMESPEC_RESOLUTION - 1);
+ return make_timespec (TYPE_MAXIMUM (time_t), TIMESPEC_HZ - 1);
else
{
time_t s = sec;
- double frac = TIMESPEC_RESOLUTION * (sec - s);
+ double frac = TIMESPEC_HZ * (sec - s);
long ns = frac;
ns += ns < frac;
- s += ns / TIMESPEC_RESOLUTION;
- ns %= TIMESPEC_RESOLUTION;
+ s += ns / TIMESPEC_HZ;
+ ns %= TIMESPEC_HZ;
if (ns < 0)
{
s--;
- ns += TIMESPEC_RESOLUTION;
+ ns += TIMESPEC_HZ;
}
return make_timespec (s, ns);
diff --git a/lib/dup2.c b/lib/dup2.c
index 85c1a44401a..1c766ab38ec 100644
--- a/lib/dup2.c
+++ b/lib/dup2.c
@@ -1,18 +1,18 @@
/* Duplicate an open file descriptor to a specified file descriptor.
- Copyright (C) 1999, 2004-2007, 2009-2017 Free Software Foundation, Inc.
+ Copyright (C) 1999, 2004-2007, 2009-2022 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 file is free software: you can redistribute it and/or modify
+ it under the terms of the GNU Lesser General Public License as
+ published by the Free Software Foundation; either version 2.1 of the
+ License, or (at your option) any later version.
- This program is distributed in the hope that it will be useful,
+ This file 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.
+ GNU Lesser General Public License for more details.
- You should have received a copy of the GNU General Public License
+ You should have received a copy of the GNU Lesser General Public License
along with this program. If not, see <https://www.gnu.org/licenses/>. */
/* written by Paul Eggert */
@@ -25,28 +25,26 @@
#include <errno.h>
#include <fcntl.h>
-#if HAVE_DUP2
+#undef dup2
-# undef dup2
-
-# if (defined _WIN32 || defined __WIN32__) && ! defined __CYGWIN__
+#if defined _WIN32 && ! defined __CYGWIN__
/* Get declarations of the native Windows API functions. */
-# define WIN32_LEAN_AND_MEAN
-# include <windows.h>
+# define WIN32_LEAN_AND_MEAN
+# include <windows.h>
-# if HAVE_MSVC_INVALID_PARAMETER_HANDLER
-# include "msvc-inval.h"
-# endif
+# if HAVE_MSVC_INVALID_PARAMETER_HANDLER
+# include "msvc-inval.h"
+# endif
/* Get _get_osfhandle. */
-# if GNULIB_MSVC_NOTHROW
-# include "msvc-nothrow.h"
-# else
-# include <io.h>
-# endif
+# if GNULIB_MSVC_NOTHROW
+# include "msvc-nothrow.h"
+# else
+# include <io.h>
+# endif
-# if HAVE_MSVC_INVALID_PARAMETER_HANDLER
+# if HAVE_MSVC_INVALID_PARAMETER_HANDLER
static int
dup2_nothrow (int fd, int desired_fd)
{
@@ -54,7 +52,7 @@ dup2_nothrow (int fd, int desired_fd)
TRY_MSVC_INVAL
{
- result = dup2 (fd, desired_fd);
+ result = _dup2 (fd, desired_fd);
}
CATCH_MSVC_INVAL
{
@@ -65,9 +63,9 @@ dup2_nothrow (int fd, int desired_fd)
return result;
}
-# else
-# define dup2_nothrow dup2
-# endif
+# else
+# define dup2_nothrow _dup2
+# endif
static int
ms_windows_dup2 (int fd, int desired_fd)
@@ -103,11 +101,11 @@ ms_windows_dup2 (int fd, int desired_fd)
return result;
}
-# define dup2 ms_windows_dup2
+# define dup2 ms_windows_dup2
-# elif defined __KLIBC__
+#elif defined __KLIBC__
-# include <InnoTekLIBC/backend.h>
+# include <InnoTekLIBC/backend.h>
static int
klibc_dup2dirfd (int fd, int desired_fd)
@@ -155,81 +153,37 @@ klibc_dup2 (int fd, int desired_fd)
return dupfd;
}
-# define dup2 klibc_dup2
-# endif
+# define dup2 klibc_dup2
+#endif
int
rpl_dup2 (int fd, int desired_fd)
{
int result;
-# ifdef F_GETFL
+#ifdef F_GETFL
/* On Linux kernels 2.6.26-2.6.29, dup2 (fd, fd) returns -EBADF.
On Cygwin 1.5.x, dup2 (1, 1) returns 0.
On Cygwin 1.7.17, dup2 (1, -1) dumps core.
On Cygwin 1.7.25, dup2 (1, 256) can dump core.
On Haiku, dup2 (fd, fd) mistakenly clears FD_CLOEXEC. */
-# if HAVE_SETDTABLESIZE
+# if HAVE_SETDTABLESIZE
setdtablesize (desired_fd + 1);
-# endif
+# endif
if (desired_fd < 0)
fd = desired_fd;
if (fd == desired_fd)
return fcntl (fd, F_GETFL) == -1 ? -1 : fd;
-# endif
+#endif
result = dup2 (fd, desired_fd);
/* Correct an errno value on FreeBSD 6.1 and Cygwin 1.5.x. */
if (result == -1 && errno == EMFILE)
errno = EBADF;
-# if REPLACE_FCHDIR
+#if REPLACE_FCHDIR
if (fd != desired_fd && result != -1)
result = _gl_register_dup (fd, result);
-# endif
- return result;
-}
-
-#else /* !HAVE_DUP2 */
-
-/* On older platforms, dup2 did not exist. */
-
-# ifndef F_DUPFD
-static int
-dupfd (int fd, int desired_fd)
-{
- int duplicated_fd = dup (fd);
- if (duplicated_fd < 0 || duplicated_fd == desired_fd)
- return duplicated_fd;
- else
- {
- int r = dupfd (fd, desired_fd);
- int e = errno;
- close (duplicated_fd);
- errno = e;
- return r;
- }
-}
-# endif
-
-int
-dup2 (int fd, int desired_fd)
-{
- int result = fcntl (fd, F_GETFL) < 0 ? -1 : fd;
- if (result == -1 || fd == desired_fd)
- return result;
- close (desired_fd);
-# ifdef F_DUPFD
- result = fcntl (fd, F_DUPFD, desired_fd);
-# if REPLACE_FCHDIR
- if (0 <= result)
- result = _gl_register_dup (fd, result);
-# endif
-# else
- result = dupfd (fd, desired_fd);
-# endif
- if (result == -1 && (errno == EMFILE || errno == EINVAL))
- errno = EBADF;
+#endif
return result;
}
-#endif /* !HAVE_DUP2 */
diff --git a/lib/dynarray.h b/lib/dynarray.h
new file mode 100644
index 00000000000..ca6439d3adc
--- /dev/null
+++ b/lib/dynarray.h
@@ -0,0 +1,284 @@
+/* Type-safe arrays which grow dynamically.
+ Copyright 2021-2022 Free Software Foundation, Inc.
+
+ This file is free software: you can redistribute it and/or modify
+ it under the terms of the GNU Lesser General Public License as
+ published by the Free Software Foundation; either version 2.1 of the
+ License, or (at your option) any later version.
+
+ This file 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 Lesser General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public License
+ along with this program. If not, see <https://www.gnu.org/licenses/>. */
+
+/* Written by Paul Eggert and Bruno Haible, 2021. */
+
+#ifndef _GL_DYNARRAY_H
+#define _GL_DYNARRAY_H
+
+/* Before including this file, you need to define:
+
+ DYNARRAY_STRUCT
+ The struct tag of dynamic array to be defined.
+
+ DYNARRAY_ELEMENT
+ The type name of the element type. Elements are copied
+ as if by memcpy, and can change address as the dynamic
+ array grows.
+
+ DYNARRAY_PREFIX
+ The prefix of the functions which are defined.
+
+ The following parameters are optional:
+
+ DYNARRAY_ELEMENT_FREE
+ DYNARRAY_ELEMENT_FREE (E) is evaluated to deallocate the
+ contents of elements. E is of type DYNARRAY_ELEMENT *.
+
+ DYNARRAY_ELEMENT_INIT
+ DYNARRAY_ELEMENT_INIT (E) is evaluated to initialize a new
+ element. E is of type DYNARRAY_ELEMENT *.
+ If DYNARRAY_ELEMENT_FREE but not DYNARRAY_ELEMENT_INIT is
+ defined, new elements are automatically zero-initialized.
+ Otherwise, new elements have undefined contents.
+
+ DYNARRAY_INITIAL_SIZE
+ The size of the statically allocated array (default:
+ at least 2, more elements if they fit into 128 bytes).
+ Must be a preprocessor constant. If DYNARRAY_INITIAL_SIZE is 0,
+ there is no statically allocated array at, and all non-empty
+ arrays are heap-allocated.
+
+ DYNARRAY_FINAL_TYPE
+ The name of the type which holds the final array. If not
+ defined, is PREFIX##finalize not provided. DYNARRAY_FINAL_TYPE
+ must be a struct type, with members of type DYNARRAY_ELEMENT and
+ size_t at the start (in this order).
+
+ These macros are undefined after this header file has been
+ included.
+
+ The following types are provided (their members are private to the
+ dynarray implementation):
+
+ struct DYNARRAY_STRUCT
+
+ The following functions are provided:
+ */
+
+/* Initialize a dynamic array object. This must be called before any
+ use of the object. */
+#if 0
+static void
+ DYNARRAY_PREFIX##init (struct DYNARRAY_STRUCT *list);
+#endif
+
+/* Deallocate the dynamic array and its elements. */
+#if 0
+static void
+ DYNARRAY_PREFIX##free (struct DYNARRAY_STRUCT *list);
+#endif
+
+/* Return true if the dynamic array is in an error state. */
+#if 0
+static bool
+ DYNARRAY_PREFIX##has_failed (const struct DYNARRAY_STRUCT *list);
+#endif
+
+/* Mark the dynamic array as failed. All elements are deallocated as
+ a side effect. */
+#if 0
+static void
+ DYNARRAY_PREFIX##mark_failed (struct DYNARRAY_STRUCT *list);
+#endif
+
+/* Return the number of elements which have been added to the dynamic
+ array. */
+#if 0
+static size_t
+ DYNARRAY_PREFIX##size (const struct DYNARRAY_STRUCT *list);
+#endif
+
+/* Return a pointer to the first array element, if any. For a
+ zero-length array, the pointer can be NULL even though the dynamic
+ array has not entered the failure state. */
+#if 0
+static DYNARRAY_ELEMENT *
+ DYNARRAY_PREFIX##begin (const struct DYNARRAY_STRUCT *list);
+#endif
+
+/* Return a pointer one element past the last array element. For a
+ zero-length array, the pointer can be NULL even though the dynamic
+ array has not entered the failure state. */
+#if 0
+static DYNARRAY_ELEMENT *
+ DYNARRAY_PREFIX##end (const struct DYNARRAY_STRUCT *list);
+#endif
+
+/* Return a pointer to the array element at INDEX. Terminate the
+ process if INDEX is out of bounds. */
+#if 0
+static DYNARRAY_ELEMENT *
+ DYNARRAY_PREFIX##at (struct DYNARRAY_STRUCT *list, size_t index);
+#endif
+
+/* Add ITEM at the end of the array, enlarging it by one element.
+ Mark *LIST as failed if the dynamic array allocation size cannot be
+ increased. */
+#if 0
+static void
+ DYNARRAY_PREFIX##add (struct DYNARRAY_STRUCT *list,
+ DYNARRAY_ELEMENT item);
+#endif
+
+/* Allocate a place for a new element in *LIST and return a pointer to
+ it. The pointer can be NULL if the dynamic array cannot be
+ enlarged due to a memory allocation failure. */
+#if 0
+static DYNARRAY_ELEMENT *
+ DYNARRAY_PREFIX##emplace (struct DYNARRAY_STRUCT *list);
+#endif
+
+/* Change the size of *LIST to SIZE. If SIZE is larger than the
+ existing size, new elements are added (which can be initialized).
+ Otherwise, the list is truncated, and elements are freed. Return
+ false on memory allocation failure (and mark *LIST as failed). */
+#if 0
+static bool
+ DYNARRAY_PREFIX##resize (struct DYNARRAY_STRUCT *list, size_t size);
+#endif
+
+/* Remove the last element of LIST if it is present. */
+#if 0
+static void
+ DYNARRAY_PREFIX##remove_last (struct DYNARRAY_STRUCT *list);
+#endif
+
+/* Remove all elements from the list. The elements are freed, but the
+ list itself is not. */
+#if 0
+static void
+ DYNARRAY_PREFIX##clear (struct DYNARRAY_STRUCT *list);
+#endif
+
+#if defined DYNARRAY_FINAL_TYPE
+/* Transfer the dynamic array to a permanent location at *RESULT.
+ Returns true on success on false on allocation failure. In either
+ case, *LIST is re-initialized and can be reused. A NULL pointer is
+ stored in *RESULT if LIST refers to an empty list. On success, the
+ pointer in *RESULT is heap-allocated and must be deallocated using
+ free. */
+#if 0
+static bool
+ DYNARRAY_PREFIX##finalize (struct DYNARRAY_STRUCT *list,
+ DYNARRAY_FINAL_TYPE *result);
+#endif
+#else /* !defined DYNARRAY_FINAL_TYPE */
+/* Transfer the dynamic array to a heap-allocated array and return a
+ pointer to it. The pointer is NULL if memory allocation fails, or
+ if the array is empty, so this function should be used only for
+ arrays which are known not be empty (usually because they always
+ have a sentinel at the end). If LENGTHP is not NULL, the array
+ length is written to *LENGTHP. *LIST is re-initialized and can be
+ reused. */
+#if 0
+static DYNARRAY_ELEMENT *
+ DYNARRAY_PREFIX##finalize (struct DYNARRAY_STRUCT *list,
+ size_t *lengthp);
+#endif
+#endif
+
+/* A minimal example which provides a growing list of integers can be
+ defined like this:
+
+ struct int_array
+ {
+ // Pointer to result array followed by its length,
+ // as required by DYNARRAY_FINAL_TYPE.
+ int *array;
+ size_t length;
+ };
+
+ #define DYNARRAY_STRUCT dynarray_int
+ #define DYNARRAY_ELEMENT int
+ #define DYNARRAY_PREFIX dynarray_int_
+ #define DYNARRAY_FINAL_TYPE struct int_array
+ #include <malloc/dynarray-skeleton.c>
+
+ To create a three-element array with elements 1, 2, 3, use this
+ code:
+
+ struct dynarray_int dyn;
+ dynarray_int_init (&dyn);
+ for (int i = 1; i <= 3; ++i)
+ {
+ int *place = dynarray_int_emplace (&dyn);
+ assert (place != NULL);
+ *place = i;
+ }
+ struct int_array result;
+ bool ok = dynarray_int_finalize (&dyn, &result);
+ assert (ok);
+ assert (result.length == 3);
+ assert (result.array[0] == 1);
+ assert (result.array[1] == 2);
+ assert (result.array[2] == 3);
+ free (result.array);
+
+ If the elements contain resources which must be freed, define
+ DYNARRAY_ELEMENT_FREE appropriately, like this:
+
+ struct str_array
+ {
+ char **array;
+ size_t length;
+ };
+
+ #define DYNARRAY_STRUCT dynarray_str
+ #define DYNARRAY_ELEMENT char *
+ #define DYNARRAY_ELEMENT_FREE(ptr) free (*ptr)
+ #define DYNARRAY_PREFIX dynarray_str_
+ #define DYNARRAY_FINAL_TYPE struct str_array
+ #include <malloc/dynarray-skeleton.c>
+ */
+
+
+/* The implementation is imported from glibc. */
+
+/* Avoid possible conflicts with symbols exported by the GNU libc. */
+#define __libc_dynarray_at_failure gl_dynarray_at_failure
+#define __libc_dynarray_emplace_enlarge gl_dynarray_emplace_enlarge
+#define __libc_dynarray_finalize gl_dynarray_finalize
+#define __libc_dynarray_resize_clear gl_dynarray_resize_clear
+#define __libc_dynarray_resize gl_dynarray_resize
+
+#if defined DYNARRAY_STRUCT || defined DYNARRAY_ELEMENT || defined DYNARRAY_PREFIX
+
+# ifndef _GL_LIKELY
+/* Rely on __builtin_expect, as provided by the module 'builtin-expect'. */
+# define _GL_LIKELY(cond) __builtin_expect ((cond), 1)
+# define _GL_UNLIKELY(cond) __builtin_expect ((cond), 0)
+# endif
+
+/* Define auxiliary structs and declare auxiliary functions, common to all
+ instantiations of dynarray. */
+# include <malloc/dynarray.gl.h>
+
+/* Define the instantiation, specified through
+ DYNARRAY_STRUCT
+ DYNARRAY_ELEMENT
+ DYNARRAY_PREFIX
+ etc. */
+# include <malloc/dynarray-skeleton.gl.h>
+
+#else
+
+/* This file is being included from one of the malloc/dynarray_*.c files. */
+# include <malloc/dynarray.h>
+
+#endif
+
+#endif /* _GL_DYNARRAY_H */
diff --git a/lib/eloop-threshold.h b/lib/eloop-threshold.h
new file mode 100644
index 00000000000..8b314571198
--- /dev/null
+++ b/lib/eloop-threshold.h
@@ -0,0 +1,83 @@
+/* Threshold at which to diagnose ELOOP. Generic version.
+ Copyright (C) 2012-2022 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 Lesser General Public
+ License as published by the Free Software Foundation; either
+ version 2.1 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
+ Lesser General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public
+ License along with the GNU C Library; if not, see
+ <https://www.gnu.org/licenses/>. */
+
+#ifndef _ELOOP_THRESHOLD_H
+#define _ELOOP_THRESHOLD_H 1
+
+#include <limits.h>
+#ifdef _LIBC
+# include <sys/param.h>
+# define _GL_ATTRIBUTE_CONST __attribute__ ((const))
+#else
+# include <unistd.h>
+# include "minmax.h"
+# define __sysconf sysconf
+# if (!defined SYMLOOP_MAX \
+ && ! (defined _SC_SYMLOOP_MAX && defined _POSIX_SYMLOOP_MAX))
+# define SYMLOOP_MAX 8
+# endif
+#endif
+
+/* POSIX specifies SYMLOOP_MAX as the "Maximum number of symbolic
+ links that can be reliably traversed in the resolution of a
+ pathname in the absence of a loop." This makes it a minimum that
+ we should certainly accept. But it leaves open the possibility
+ that more might sometimes work--just not "reliably".
+
+ For example, Linux implements a complex policy whereby there is a
+ small limit on the number of direct symlink traversals (a symlink
+ to a symlink to a symlink), but larger limit on the total number of
+ symlink traversals overall. Hence the SYMLOOP_MAX number should be
+ the small one, but the limit library functions enforce on users
+ should be the larger one.
+
+ So, we use the larger of the reported SYMLOOP_MAX (if any) and our
+ own constant MIN_ELOOP_THRESHOLD, below. This constant should be
+ large enough that it never rules out a file name and directory tree
+ that the underlying system (i.e. calls to 'open' et al) would
+ resolve successfully. It should be small enough that actual loops
+ are detected without a huge number of iterations. */
+
+#ifndef MIN_ELOOP_THRESHOLD
+# define MIN_ELOOP_THRESHOLD 40
+#endif
+
+/* Return the maximum number of symlink traversals to permit
+ before diagnosing ELOOP. */
+static inline unsigned int _GL_ATTRIBUTE_CONST
+__eloop_threshold (void)
+{
+#ifdef SYMLOOP_MAX
+ const int symloop_max = SYMLOOP_MAX;
+#else
+ /* The function is marked 'const' even though we use memory and
+ call a function, because sysconf is required to return the
+ same value in every call and so it must always be safe to
+ call __eloop_threshold exactly once and reuse the value. */
+ static long int sysconf_symloop_max;
+ if (sysconf_symloop_max == 0)
+ sysconf_symloop_max = __sysconf (_SC_SYMLOOP_MAX);
+ const unsigned int symloop_max = (sysconf_symloop_max <= 0
+ ? _POSIX_SYMLOOP_MAX
+ : sysconf_symloop_max);
+#endif
+
+ return MAX (symloop_max, MIN_ELOOP_THRESHOLD);
+}
+
+#endif /* eloop-threshold.h */
diff --git a/lib/errno.in.h b/lib/errno.in.h
index aaf5fecd73b..3ec18456940 100644
--- a/lib/errno.in.h
+++ b/lib/errno.in.h
@@ -1,19 +1,19 @@
/* A POSIX-like <errno.h>.
- Copyright (C) 2008-2017 Free Software Foundation, Inc.
+ Copyright (C) 2008-2022 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 file is free software: you can redistribute it and/or modify
+ it under the terms of the GNU Lesser General Public License as
+ published by the Free Software Foundation; either version 2.1 of the
+ License, or (at your option) any later version.
- This program is distributed in the hope that it will be useful,
+ This file 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.
+ GNU Lesser General Public License for more details.
- You should have received a copy of the GNU General Public License
- along with this program; if not, see <https://www.gnu.org/licenses/>. */
+ You should have received a copy of the GNU Lesser General Public License
+ along with this program. If not, see <https://www.gnu.org/licenses/>. */
#ifndef _@GUARD_PREFIX@_ERRNO_H
@@ -30,7 +30,7 @@
/* On native Windows platforms, many macros are not defined. */
-# if (defined _WIN32 || defined __WIN32__) && ! defined __CYGWIN__
+# if defined _WIN32 && ! defined __CYGWIN__
/* These are the same values as defined by MSVC 10, for interoperability. */
@@ -248,7 +248,7 @@
interoperability. */
# define EOWNERDEAD 58
# define ENOTRECOVERABLE 59
-# elif (defined _WIN32 || defined __WIN32__) && ! defined __CYGWIN__
+# elif defined _WIN32 && ! defined __CYGWIN__
/* We have a conflict here: pthreads-win32 defines these values
differently than MSVC 10. It's hairy to decide which one to use. */
# if defined __MINGW32__ && !defined USE_WINDOWS_THREADS
diff --git a/lib/euidaccess.c b/lib/euidaccess.c
index 298c4459477..97388c73bbb 100644
--- a/lib/euidaccess.c
+++ b/lib/euidaccess.c
@@ -1,21 +1,21 @@
/* euidaccess -- check if effective user id can access file
- Copyright (C) 1990-1991, 1995, 1998, 2000, 2003-2006, 2008-2017 Free
+ Copyright (C) 1990-1991, 1995, 1998, 2000, 2003-2006, 2008-2022 Free
Software Foundation, Inc.
This file is part of the GNU C Library.
- This program is free software: you can redistribute it and/or modify
- it under the terms of the GNU General Public License as published by
- the Free Software Foundation; either version 3 of the License, or
- (at your option) any later version.
+ This file is free software: you can redistribute it and/or modify
+ it under the terms of the GNU Lesser General Public License as
+ published by the Free Software Foundation; either version 2.1 of the
+ License, or (at your option) any later version.
- This program is distributed in the hope that it will be useful,
+ This file 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.
+ GNU Lesser General Public License for more details.
- You should have received a copy of the GNU General Public License
+ You should have received a copy of the GNU Lesser General Public License
along with this program. If not, see <https://www.gnu.org/licenses/>. */
/* Written by David MacKenzie and Torbjorn Granlund.
@@ -29,8 +29,11 @@
#include <sys/types.h>
#include <sys/stat.h>
#include <unistd.h>
-
-#include "root-uid.h"
+#if defined _WIN32 && ! defined __CYGWIN__
+# include <io.h>
+#else
+# include "root-uid.h"
+#endif
#if HAVE_LIBGEN_H
# include <libgen.h>
@@ -84,7 +87,9 @@ euidaccess (const char *file, int mode)
return accessx (file, mode, ACC_SELF);
#elif HAVE_EACCESS /* FreeBSD */
return eaccess (file, mode);
-#else /* Mac OS X, NetBSD, OpenBSD, HP-UX, Solaris, Cygwin, mingw, BeOS */
+#elif defined _WIN32 && ! defined __CYGWIN__ /* mingw */
+ return _access (file, mode);
+#else /* Mac OS X, NetBSD, OpenBSD, HP-UX, Solaris, Cygwin, BeOS */
uid_t uid = getuid ();
gid_t gid = getgid ();
@@ -102,7 +107,10 @@ euidaccess (const char *file, int mode)
safe. */
if (mode == F_OK)
- return stat (file, &stats);
+ {
+ int result = stat (file, &stats);
+ return result != 0 && errno == EOVERFLOW ? 0 : result;
+ }
else
{
int result;
@@ -137,8 +145,8 @@ euidaccess (const char *file, int mode)
/* If we are not set-uid or set-gid, access does the same. */
return access (file, mode);
- if (stat (file, &stats) != 0)
- return -1;
+ if (stat (file, &stats) == -1)
+ return mode == F_OK && errno == EOVERFLOW ? 0 : -1;
/* The super-user can read and write any file, and execute any file
that anyone can execute. */
diff --git a/lib/execinfo.c b/lib/execinfo.c
index 0bcd9f078ba..4320b16c63d 100644
--- a/lib/execinfo.c
+++ b/lib/execinfo.c
@@ -1,3 +1,21 @@
+/* Information about executables.
+
+ Copyright (C) 2012-2022 Free Software Foundation, Inc.
+
+ This file is free software: you can redistribute it and/or modify
+ it under the terms of the GNU Lesser General Public License as
+ published by the Free Software Foundation; either version 2.1 of the
+ License, or (at your option) any later version.
+
+ This file 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 Lesser General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public License
+ along with this program. If not, see <https://www.gnu.org/licenses/>. */
+
#include <config.h>
+
#define _GL_EXECINFO_INLINE _GL_EXTERN_INLINE
#include "execinfo.h"
diff --git a/lib/execinfo.in.h b/lib/execinfo.in.h
index f2269269c53..03c551a87b3 100644
--- a/lib/execinfo.in.h
+++ b/lib/execinfo.in.h
@@ -1,18 +1,18 @@
/* Information about executables.
- Copyright (C) 2012-2017 Free Software Foundation, Inc.
+ Copyright (C) 2012-2022 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
+ it under the terms of the GNU Lesser General Public License as published by
+ the Free Software Foundation; either version 2.1 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.
+ GNU Lesser General Public License for more details.
- You should have received a copy of the GNU General Public License
+ You should have received a copy of the GNU Lesser General Public License
along with this program. If not, see <https://www.gnu.org/licenses/>. */
/* Written by Paul Eggert. */
diff --git a/lib/explicit_bzero.c b/lib/explicit_bzero.c
index 09093467769..ad0bfd170ca 100644
--- a/lib/explicit_bzero.c
+++ b/lib/explicit_bzero.c
@@ -1,18 +1,18 @@
/* Erasure of sensitive data, generic implementation.
- Copyright (C) 2016-2017 Free Software Foundation, Inc.
+ Copyright (C) 2016-2022 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
+ modify it under the terms of the GNU Lesser General Public
License as published by the Free Software Foundation; either
- version 3 of the License, or (at your option) any later version.
+ version 2.1 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.
+ Lesser General Public License for more details.
- You should have received a copy of the GNU General Public
+ You should have received a copy of the GNU Lesser General Public
License along with the GNU C Library; if not, see
<https://www.gnu.org/licenses/>. */
@@ -25,24 +25,50 @@
# include <config.h>
#endif
+/* memset_s need this define */
+#if HAVE_MEMSET_S
+# define __STDC_WANT_LIB_EXT1__ 1
+#endif
+
#include <string.h>
+#if defined _WIN32 && !defined __CYGWIN__
+# define WIN32_LEAN_AND_MEAN
+# include <windows.h>
+#endif
+
+#if _LIBC
/* glibc-internal users use __explicit_bzero_chk, and explicit_bzero
redirects to that. */
-#undef explicit_bzero
+# undef explicit_bzero
+#endif
/* Set LEN bytes of S to 0. The compiler will not delete a call to
this function, even if S is dead after the call. */
void
explicit_bzero (void *s, size_t len)
{
-#ifdef HAVE_EXPLICIT_MEMSET
- explicit_memset (s, 0, len);
-#else
+#if defined _WIN32 && !defined __CYGWIN__
+ (void) SecureZeroMemory (s, len);
+#elif HAVE_EXPLICIT_MEMSET
+ explicit_memset (s, '\0', len);
+#elif HAVE_MEMSET_S
+ (void) memset_s (s, len, '\0', len);
+#elif defined __GNUC__ && !defined __clang__
memset (s, '\0', len);
-# ifdef __GNUC__
/* Compiler barrier. */
asm volatile ("" ::: "memory");
-# endif
+#elif defined __clang__
+ memset (s, '\0', len);
+ /* Compiler barrier. */
+ /* With asm ("" ::: "memory") LLVM analyzes uses of 's' and finds that the
+ whole thing is dead and eliminates it. Use 'g' to work around this
+ problem. See <https://bugs.llvm.org/show_bug.cgi?id=15495#c11>. */
+ __asm__ volatile ("" : : "g"(s) : "memory");
+#else
+ /* Invoke memset through a volatile function pointer. This defeats compiler
+ optimizations. */
+ void * (* const volatile volatile_memset) (void *, int, size_t) = memset;
+ (void) volatile_memset (s, '\0', len);
#endif
}
diff --git a/lib/faccessat.c b/lib/faccessat.c
index 6cf9c99df20..c1737d03a10 100644
--- a/lib/faccessat.c
+++ b/lib/faccessat.c
@@ -1,9 +1,9 @@
/* Check the access rights of a file relative to an open directory.
- Copyright (C) 2009-2017 Free Software Foundation, Inc.
+ Copyright (C) 2009-2022 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
+ 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,
@@ -16,10 +16,34 @@
/* written by Eric Blake */
+/* If the user's config.h happens to include <unistd.h>, let it include only
+ the system's <unistd.h> here, so that orig_faccessat doesn't recurse to
+ rpl_faccessat. */
+#define _GL_INCLUDING_UNISTD_H
#include <config.h>
+/* Specification. */
#include <unistd.h>
+
+#include <errno.h>
#include <fcntl.h>
+#include <stdlib.h>
+#include <string.h>
+#include <sys/stat.h>
+#undef _GL_INCLUDING_UNISTD_H
+
+#if HAVE_FACCESSAT
+static int
+orig_faccessat (int fd, char const *name, int mode, int flag)
+{
+ return faccessat (fd, name, mode, flag);
+}
+#endif
+
+/* Write "unistd.h" here, not <unistd.h>, otherwise OSF/1 5.1 DTK cc
+ eliminates this include because of the preliminary #include <unistd.h>
+ above. */
+#include "unistd.h"
#ifndef HAVE_ACCESS
/* Mingw lacks access, but it also lacks real vs. effective ids, so
@@ -28,6 +52,29 @@
# define access euidaccess
#endif
+#if HAVE_FACCESSAT
+
+int
+rpl_faccessat (int fd, char const *file, int mode, int flag)
+{
+ int result = orig_faccessat (fd, file, mode, flag);
+
+ if (result == 0 && file[strlen (file) - 1] == '/')
+ {
+ struct stat st;
+ result = fstatat (fd, file, &st, 0);
+ if (result == 0 && !S_ISDIR (st.st_mode))
+ {
+ errno = ENOTDIR;
+ return -1;
+ }
+ }
+
+ return result;
+}
+
+#else /* !HAVE_FACCESSAT */
+
/* Invoke access or euidaccess on file, FILE, using mode MODE, in the directory
open on descriptor FD. If possible, do it without changing the
working directory. Otherwise, resort to using save_cwd/fchdir, then
@@ -36,10 +83,12 @@
Note that this implementation only supports AT_EACCESS, although some
native versions also support AT_SYMLINK_NOFOLLOW. */
-#define AT_FUNC_NAME faccessat
-#define AT_FUNC_F1 euidaccess
-#define AT_FUNC_F2 access
-#define AT_FUNC_USE_F1_COND AT_EACCESS
-#define AT_FUNC_POST_FILE_PARAM_DECLS , int mode, int flag
-#define AT_FUNC_POST_FILE_ARGS , mode
-#include "at-func.c"
+# define AT_FUNC_NAME faccessat
+# define AT_FUNC_F1 euidaccess
+# define AT_FUNC_F2 access
+# define AT_FUNC_USE_F1_COND AT_EACCESS
+# define AT_FUNC_POST_FILE_PARAM_DECLS , int mode, int flag
+# define AT_FUNC_POST_FILE_ARGS , mode
+# include "at-func.c"
+
+#endif
diff --git a/lib/fchmodat.c b/lib/fchmodat.c
new file mode 100644
index 00000000000..164e2c4a95f
--- /dev/null
+++ b/lib/fchmodat.c
@@ -0,0 +1,142 @@
+/* Change the protections of file relative to an open directory.
+ Copyright (C) 2006, 2009-2022 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 Jim Meyering and Paul Eggert */
+
+/* If the user's config.h happens to include <sys/stat.h>, let it include only
+ the system's <sys/stat.h> here, so that orig_fchmodat doesn't recurse to
+ rpl_fchmodat. */
+#define __need_system_sys_stat_h
+#include <config.h>
+
+/* Specification. */
+#include <sys/stat.h>
+#undef __need_system_sys_stat_h
+
+#if HAVE_FCHMODAT
+static int
+orig_fchmodat (int dir, char const *file, mode_t mode, int flags)
+{
+ return fchmodat (dir, file, mode, flags);
+}
+#endif
+
+#include <errno.h>
+#include <fcntl.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <unistd.h>
+
+#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"
+#else
+# include <sys/stat.h>
+#endif
+
+#include <intprops.h>
+
+/* Invoke chmod or lchmod on FILE, using mode MODE, in the directory
+ open on descriptor FD. If possible, do it without changing the
+ working directory. Otherwise, resort to using save_cwd/fchdir,
+ then (chmod|lchmod)/restore_cwd. If either the save_cwd or the
+ restore_cwd fails, then give a diagnostic and exit nonzero.
+ Note that an attempt to use a FLAG value of AT_SYMLINK_NOFOLLOW
+ on a system without lchmod support causes this function to fail. */
+
+#if HAVE_FCHMODAT
+int
+fchmodat (int dir, char const *file, mode_t mode, int flags)
+{
+# if HAVE_NEARLY_WORKING_FCHMODAT
+ /* Correct the trailing slash handling. */
+ size_t len = strlen (file);
+ if (len && file[len - 1] == '/')
+ {
+ struct stat st;
+ if (fstatat (dir, file, &st, flags & AT_SYMLINK_NOFOLLOW) < 0)
+ return -1;
+ if (!S_ISDIR (st.st_mode))
+ {
+ errno = ENOTDIR;
+ return -1;
+ }
+ }
+# endif
+
+# if NEED_FCHMODAT_NONSYMLINK_FIX
+ if (flags == AT_SYMLINK_NOFOLLOW)
+ {
+# if HAVE_READLINKAT
+ char readlink_buf[1];
+
+# ifdef O_PATH
+ /* Open a file descriptor with O_NOFOLLOW, to make sure we don't
+ follow symbolic links, if /proc is mounted. O_PATH is used to
+ avoid a failure if the file is not readable.
+ Cf. <https://sourceware.org/bugzilla/show_bug.cgi?id=14578> */
+ int fd = openat (dir, file, O_PATH | O_NOFOLLOW | O_CLOEXEC);
+ if (fd < 0)
+ return fd;
+
+ int err;
+ if (0 <= readlinkat (fd, "", readlink_buf, sizeof readlink_buf))
+ err = EOPNOTSUPP;
+ else if (errno == EINVAL)
+ {
+ static char const fmt[] = "/proc/self/fd/%d";
+ char buf[sizeof fmt - sizeof "%d" + INT_BUFSIZE_BOUND (int)];
+ sprintf (buf, fmt, fd);
+ err = chmod (buf, mode) == 0 ? 0 : errno == ENOENT ? -1 : errno;
+ }
+ else
+ err = errno == ENOENT ? -1 : errno;
+
+ close (fd);
+
+ errno = err;
+ if (0 <= err)
+ return err == 0 ? 0 : -1;
+# endif
+
+ /* O_PATH + /proc is not supported. */
+
+ if (0 <= readlinkat (dir, file, readlink_buf, sizeof readlink_buf))
+ {
+ errno = EOPNOTSUPP;
+ return -1;
+ }
+# endif
+
+ /* Fall back on orig_fchmodat with no flags, despite a possible race. */
+ flags = 0;
+ }
+# endif
+
+ return orig_fchmodat (dir, file, mode, flags);
+}
+#else
+# define AT_FUNC_NAME fchmodat
+# define AT_FUNC_F1 lchmod
+# define AT_FUNC_F2 chmod
+# define AT_FUNC_USE_F1_COND AT_SYMLINK_NOFOLLOW
+# define AT_FUNC_POST_FILE_PARAM_DECLS , mode_t mode, int flag
+# define AT_FUNC_POST_FILE_ARGS , mode
+# include "at-func.c"
+#endif
diff --git a/lib/fcntl.c b/lib/fcntl.c
index 91efd12c2ba..f9753c4035f 100644
--- a/lib/fcntl.c
+++ b/lib/fcntl.c
@@ -1,18 +1,18 @@
/* Provide file descriptor control.
- Copyright (C) 2009-2017 Free Software Foundation, Inc.
+ Copyright (C) 2009-2022 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 file is free software: you can redistribute it and/or modify
+ it under the terms of the GNU Lesser General Public License as
+ published by the Free Software Foundation; either version 2.1 of the
+ License, or (at your option) any later version.
- This program is distributed in the hope that it will be useful,
+ This file 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.
+ GNU Lesser General Public License for more details.
- You should have received a copy of the GNU General Public License
+ You should have received a copy of the GNU Lesser General Public License
along with this program. If not, see <https://www.gnu.org/licenses/>. */
/* Written by Eric Blake <ebb9@byu.net>. */
@@ -25,14 +25,15 @@
#include <errno.h>
#include <limits.h>
#include <stdarg.h>
+#include <stdlib.h>
#include <unistd.h>
-#if !HAVE_FCNTL
-# define rpl_fcntl fcntl
+#ifdef __KLIBC__
+# define INCL_DOS
+# include <os2.h>
#endif
-#undef fcntl
-#if (defined _WIN32 || defined __WIN32__) && ! defined __CYGWIN__
+#if defined _WIN32 && ! defined __CYGWIN__
/* Get declarations of the native Windows API functions. */
# define WIN32_LEAN_AND_MEAN
# include <windows.h>
@@ -69,14 +70,14 @@ dupfd (int oldfd, int newfd, int flags)
return -1;
}
if (old_handle == INVALID_HANDLE_VALUE
- || (mode = setmode (oldfd, O_BINARY)) == -1)
+ || (mode = _setmode (oldfd, O_BINARY)) == -1)
{
/* oldfd is not open, or is an unassigned standard file
descriptor. */
errno = EBADF;
return -1;
}
- setmode (oldfd, mode);
+ _setmode (oldfd, mode);
flags |= mode;
for (;;)
@@ -166,93 +167,18 @@ dupfd (int oldfd, int newfd, int flags)
}
#endif /* W32 */
+/* Forward declarations, because we '#undef fcntl' in the middle of this
+ compilation unit. */
+/* Our implementation of fcntl (fd, F_DUPFD, target). */
+static int rpl_fcntl_DUPFD (int fd, int target);
+/* Our implementation of fcntl (fd, F_DUPFD_CLOEXEC, target). */
+static int rpl_fcntl_DUPFD_CLOEXEC (int fd, int target);
#ifdef __KLIBC__
-
-# define INCL_DOS
-# include <os2.h>
-
-static int
-klibc_fcntl (int fd, int action, /* arg */...)
-{
- va_list arg_ptr;
- int arg;
- struct stat sbuf;
- int result = -1;
-
- va_start (arg_ptr, action);
- arg = va_arg (arg_ptr, int);
- result = fcntl (fd, action, arg);
- /* EPERM for F_DUPFD, ENOTSUP for others */
- if (result == -1 && (errno == EPERM || errno == ENOTSUP)
- && !fstat (fd, &sbuf) && S_ISDIR (sbuf.st_mode))
- {
- ULONG ulMode;
-
- switch (action)
- {
- case F_DUPFD:
- /* Find available fd */
- while (fcntl (arg, F_GETFL) != -1 || errno != EBADF)
- arg++;
-
- result = dup2 (fd, arg);
- break;
-
- /* Using underlying APIs is right ? */
- case F_GETFD:
- if (DosQueryFHState (fd, &ulMode))
- break;
-
- result = (ulMode & OPEN_FLAGS_NOINHERIT) ? FD_CLOEXEC : 0;
- break;
-
- case F_SETFD:
- if (arg & ~FD_CLOEXEC)
- break;
-
- if (DosQueryFHState (fd, &ulMode))
- break;
-
- if (arg & FD_CLOEXEC)
- ulMode |= OPEN_FLAGS_NOINHERIT;
- else
- ulMode &= ~OPEN_FLAGS_NOINHERIT;
-
- /* Filter supported flags. */
- ulMode &= (OPEN_FLAGS_WRITE_THROUGH | OPEN_FLAGS_FAIL_ON_ERROR
- | OPEN_FLAGS_NO_CACHE | OPEN_FLAGS_NOINHERIT);
-
- if (DosSetFHState (fd, ulMode))
- break;
-
- result = 0;
- break;
-
- case F_GETFL:
- result = 0;
- break;
-
- case F_SETFL:
- if (arg != 0)
- break;
-
- result = 0;
- break;
-
- default :
- errno = EINVAL;
- break;
- }
- }
-
- va_end (arg_ptr);
-
- return result;
-}
-
-# define fcntl klibc_fcntl
+/* Adds support for fcntl on directories. */
+static int klibc_fcntl (int fd, int action, /* arg */...);
#endif
+
/* Perform the specified ACTION on the file descriptor FD, possibly
using the argument ARG further described below. This replacement
handles the following actions, and forwards all others on to the
@@ -273,110 +199,35 @@ klibc_fcntl (int fd, int action, /* arg */...)
return -1 and set errno. */
int
-rpl_fcntl (int fd, int action, /* arg */...)
+fcntl (int fd, int action, /* arg */...)
+#undef fcntl
+#ifdef __KLIBC__
+# define fcntl klibc_fcntl
+#endif
{
va_list arg;
int result = -1;
va_start (arg, action);
switch (action)
{
-
-#if !HAVE_FCNTL
case F_DUPFD:
{
int target = va_arg (arg, int);
- result = dupfd (fd, target, 0);
+ result = rpl_fcntl_DUPFD (fd, target);
break;
}
-#elif FCNTL_DUPFD_BUGGY || REPLACE_FCHDIR
- case F_DUPFD:
- {
- int target = va_arg (arg, int);
- /* Detect invalid target; needed for cygwin 1.5.x. */
- if (target < 0 || getdtablesize () <= target)
- errno = EINVAL;
- else
- {
- /* Haiku alpha 2 loses fd flags on original. */
- int flags = fcntl (fd, F_GETFD);
- if (flags < 0)
- {
- result = -1;
- break;
- }
- result = fcntl (fd, action, target);
- if (0 <= result && fcntl (fd, F_SETFD, flags) == -1)
- {
- int saved_errno = errno;
- close (result);
- result = -1;
- errno = saved_errno;
- }
-# if REPLACE_FCHDIR
- if (0 <= result)
- result = _gl_register_dup (fd, result);
-# endif
- }
- break;
- } /* F_DUPFD */
-#endif /* FCNTL_DUPFD_BUGGY || REPLACE_FCHDIR */
case F_DUPFD_CLOEXEC:
{
int target = va_arg (arg, int);
-
-#if !HAVE_FCNTL
- result = dupfd (fd, target, O_CLOEXEC);
- break;
-#else /* HAVE_FCNTL */
- /* Try the system call first, if the headers claim it exists
- (that is, if GNULIB_defined_F_DUPFD_CLOEXEC is 0), since we
- may be running with a glibc that has the macro but with an
- older kernel that does not support it. Cache the
- information on whether the system call really works, but
- avoid caching failure if the corresponding F_DUPFD fails
- for any reason. 0 = unknown, 1 = yes, -1 = no. */
- static int have_dupfd_cloexec = GNULIB_defined_F_DUPFD_CLOEXEC ? -1 : 0;
- if (0 <= have_dupfd_cloexec)
- {
- result = fcntl (fd, action, target);
- if (0 <= result || errno != EINVAL)
- {
- have_dupfd_cloexec = 1;
-# if REPLACE_FCHDIR
- if (0 <= result)
- result = _gl_register_dup (fd, result);
-# endif
- }
- else
- {
- result = rpl_fcntl (fd, F_DUPFD, target);
- if (result < 0)
- break;
- have_dupfd_cloexec = -1;
- }
- }
- else
- result = rpl_fcntl (fd, F_DUPFD, target);
- if (0 <= result && have_dupfd_cloexec == -1)
- {
- int flags = fcntl (result, F_GETFD);
- if (flags < 0 || fcntl (result, F_SETFD, flags | FD_CLOEXEC) == -1)
- {
- int saved_errno = errno;
- close (result);
- errno = saved_errno;
- result = -1;
- }
- }
+ result = rpl_fcntl_DUPFD_CLOEXEC (fd, target);
break;
-#endif /* HAVE_FCNTL */
- } /* F_DUPFD_CLOEXEC */
+ }
#if !HAVE_FCNTL
case F_GETFD:
{
-# if (defined _WIN32 || defined __WIN32__) && ! defined __CYGWIN__
+# if defined _WIN32 && ! defined __CYGWIN__
HANDLE handle = (HANDLE) _get_osfhandle (fd);
DWORD flags;
if (handle == INVALID_HANDLE_VALUE
@@ -405,8 +256,183 @@ rpl_fcntl (int fd, int action, /* arg */...)
default:
{
#if HAVE_FCNTL
- void *p = va_arg (arg, void *);
- result = fcntl (fd, action, p);
+ switch (action)
+ {
+ #ifdef F_BARRIERFSYNC /* macOS */
+ case F_BARRIERFSYNC:
+ #endif
+ #ifdef F_CHKCLEAN /* macOS */
+ case F_CHKCLEAN:
+ #endif
+ #ifdef F_CLOSEM /* NetBSD, HP-UX */
+ case F_CLOSEM:
+ #endif
+ #ifdef F_FLUSH_DATA /* macOS */
+ case F_FLUSH_DATA:
+ #endif
+ #ifdef F_FREEZE_FS /* macOS */
+ case F_FREEZE_FS:
+ #endif
+ #ifdef F_FULLFSYNC /* macOS */
+ case F_FULLFSYNC:
+ #endif
+ #ifdef F_GETCONFINED /* macOS */
+ case F_GETCONFINED:
+ #endif
+ #ifdef F_GETDEFAULTPROTLEVEL /* macOS */
+ case F_GETDEFAULTPROTLEVEL:
+ #endif
+ #ifdef F_GETFD /* POSIX */
+ case F_GETFD:
+ #endif
+ #ifdef F_GETFL /* POSIX */
+ case F_GETFL:
+ #endif
+ #ifdef F_GETLEASE /* Linux */
+ case F_GETLEASE:
+ #endif
+ #ifdef F_GETNOSIGPIPE /* macOS */
+ case F_GETNOSIGPIPE:
+ #endif
+ #ifdef F_GETOWN /* POSIX */
+ case F_GETOWN:
+ #endif
+ #ifdef F_GETPIPE_SZ /* Linux */
+ case F_GETPIPE_SZ:
+ #endif
+ #ifdef F_GETPROTECTIONCLASS /* macOS */
+ case F_GETPROTECTIONCLASS:
+ #endif
+ #ifdef F_GETPROTECTIONLEVEL /* macOS */
+ case F_GETPROTECTIONLEVEL:
+ #endif
+ #ifdef F_GET_SEALS /* Linux */
+ case F_GET_SEALS:
+ #endif
+ #ifdef F_GETSIG /* Linux */
+ case F_GETSIG:
+ #endif
+ #ifdef F_MAXFD /* NetBSD */
+ case F_MAXFD:
+ #endif
+ #ifdef F_RECYCLE /* macOS */
+ case F_RECYCLE:
+ #endif
+ #ifdef F_SETFIFOENH /* HP-UX */
+ case F_SETFIFOENH:
+ #endif
+ #ifdef F_THAW_FS /* macOS */
+ case F_THAW_FS:
+ #endif
+ /* These actions take no argument. */
+ result = fcntl (fd, action);
+ break;
+
+ #ifdef F_ADD_SEALS /* Linux */
+ case F_ADD_SEALS:
+ #endif
+ #ifdef F_BADFD /* Solaris */
+ case F_BADFD:
+ #endif
+ #ifdef F_CHECK_OPENEVT /* macOS */
+ case F_CHECK_OPENEVT:
+ #endif
+ #ifdef F_DUP2FD /* FreeBSD, AIX, Solaris */
+ case F_DUP2FD:
+ #endif
+ #ifdef F_DUP2FD_CLOEXEC /* FreeBSD, Solaris */
+ case F_DUP2FD_CLOEXEC:
+ #endif
+ #ifdef F_DUP2FD_CLOFORK /* Solaris */
+ case F_DUP2FD_CLOFORK:
+ #endif
+ #ifdef F_DUPFD /* POSIX */
+ case F_DUPFD:
+ #endif
+ #ifdef F_DUPFD_CLOEXEC /* POSIX */
+ case F_DUPFD_CLOEXEC:
+ #endif
+ #ifdef F_DUPFD_CLOFORK /* Solaris */
+ case F_DUPFD_CLOFORK:
+ #endif
+ #ifdef F_GETXFL /* Solaris */
+ case F_GETXFL:
+ #endif
+ #ifdef F_GLOBAL_NOCACHE /* macOS */
+ case F_GLOBAL_NOCACHE:
+ #endif
+ #ifdef F_MAKECOMPRESSED /* macOS */
+ case F_MAKECOMPRESSED:
+ #endif
+ #ifdef F_MOVEDATAEXTENTS /* macOS */
+ case F_MOVEDATAEXTENTS:
+ #endif
+ #ifdef F_NOCACHE /* macOS */
+ case F_NOCACHE:
+ #endif
+ #ifdef F_NODIRECT /* macOS */
+ case F_NODIRECT:
+ #endif
+ #ifdef F_NOTIFY /* Linux */
+ case F_NOTIFY:
+ #endif
+ #ifdef F_OPLKACK /* IRIX */
+ case F_OPLKACK:
+ #endif
+ #ifdef F_OPLKREG /* IRIX */
+ case F_OPLKREG:
+ #endif
+ #ifdef F_RDAHEAD /* macOS */
+ case F_RDAHEAD:
+ #endif
+ #ifdef F_SETBACKINGSTORE /* macOS */
+ case F_SETBACKINGSTORE:
+ #endif
+ #ifdef F_SETCONFINED /* macOS */
+ case F_SETCONFINED:
+ #endif
+ #ifdef F_SETFD /* POSIX */
+ case F_SETFD:
+ #endif
+ #ifdef F_SETFL /* POSIX */
+ case F_SETFL:
+ #endif
+ #ifdef F_SETLEASE /* Linux */
+ case F_SETLEASE:
+ #endif
+ #ifdef F_SETNOSIGPIPE /* macOS */
+ case F_SETNOSIGPIPE:
+ #endif
+ #ifdef F_SETOWN /* POSIX */
+ case F_SETOWN:
+ #endif
+ #ifdef F_SETPIPE_SZ /* Linux */
+ case F_SETPIPE_SZ:
+ #endif
+ #ifdef F_SETPROTECTIONCLASS /* macOS */
+ case F_SETPROTECTIONCLASS:
+ #endif
+ #ifdef F_SETSIG /* Linux */
+ case F_SETSIG:
+ #endif
+ #ifdef F_SINGLE_WRITER /* macOS */
+ case F_SINGLE_WRITER:
+ #endif
+ /* These actions take an 'int' argument. */
+ {
+ int x = va_arg (arg, int);
+ result = fcntl (fd, action, x);
+ }
+ break;
+
+ default:
+ /* Other actions take a pointer argument. */
+ {
+ void *p = va_arg (arg, void *);
+ result = fcntl (fd, action, p);
+ }
+ break;
+ }
#else
errno = EINVAL;
#endif
@@ -416,3 +442,188 @@ rpl_fcntl (int fd, int action, /* arg */...)
va_end (arg);
return result;
}
+
+static int
+rpl_fcntl_DUPFD (int fd, int target)
+{
+ int result;
+#if !HAVE_FCNTL
+ result = dupfd (fd, target, 0);
+#elif FCNTL_DUPFD_BUGGY || REPLACE_FCHDIR
+ /* Detect invalid target; needed for cygwin 1.5.x. */
+ if (target < 0 || getdtablesize () <= target)
+ {
+ result = -1;
+ errno = EINVAL;
+ }
+ else
+ {
+ /* Haiku alpha 2 loses fd flags on original. */
+ int flags = fcntl (fd, F_GETFD);
+ if (flags < 0)
+ result = -1;
+ else
+ {
+ result = fcntl (fd, F_DUPFD, target);
+ if (0 <= result && fcntl (fd, F_SETFD, flags) == -1)
+ {
+ int saved_errno = errno;
+ close (result);
+ result = -1;
+ errno = saved_errno;
+ }
+# if REPLACE_FCHDIR
+ if (0 <= result)
+ result = _gl_register_dup (fd, result);
+# endif
+ }
+ }
+#else
+ result = fcntl (fd, F_DUPFD, target);
+#endif
+ return result;
+}
+
+static int
+rpl_fcntl_DUPFD_CLOEXEC (int fd, int target)
+{
+ int result;
+#if !HAVE_FCNTL
+ result = dupfd (fd, target, O_CLOEXEC);
+#else /* HAVE_FCNTL */
+# if defined __NetBSD__ || defined __HAIKU__
+ /* On NetBSD 9.0, the system fcntl (fd, F_DUPFD_CLOEXEC, target)
+ has only the same effect as fcntl (fd, F_DUPFD, target). */
+ /* On Haiku, the system fcntl (fd, F_DUPFD_CLOEXEC, target) sets
+ the FD_CLOEXEC flag on fd, not on target. Therefore avoid the
+ system fcntl in this case. */
+# define have_dupfd_cloexec -1
+# else
+ /* Try the system call first, if the headers claim it exists
+ (that is, if GNULIB_defined_F_DUPFD_CLOEXEC is 0), since we
+ may be running with a glibc that has the macro but with an
+ older kernel that does not support it. Cache the
+ information on whether the system call really works, but
+ avoid caching failure if the corresponding F_DUPFD fails
+ for any reason. 0 = unknown, 1 = yes, -1 = no. */
+ static int have_dupfd_cloexec = GNULIB_defined_F_DUPFD_CLOEXEC ? -1 : 0;
+ if (0 <= have_dupfd_cloexec)
+ {
+ result = fcntl (fd, F_DUPFD_CLOEXEC, target);
+ if (0 <= result || errno != EINVAL)
+ {
+ have_dupfd_cloexec = 1;
+# if REPLACE_FCHDIR
+ if (0 <= result)
+ result = _gl_register_dup (fd, result);
+# endif
+ }
+ else
+ {
+ result = rpl_fcntl_DUPFD (fd, target);
+ if (result >= 0)
+ have_dupfd_cloexec = -1;
+ }
+ }
+ else
+# endif
+ result = rpl_fcntl_DUPFD (fd, target);
+ if (0 <= result && have_dupfd_cloexec == -1)
+ {
+ int flags = fcntl (result, F_GETFD);
+ if (flags < 0 || fcntl (result, F_SETFD, flags | FD_CLOEXEC) == -1)
+ {
+ int saved_errno = errno;
+ close (result);
+ errno = saved_errno;
+ result = -1;
+ }
+ }
+#endif /* HAVE_FCNTL */
+ return result;
+}
+
+#undef fcntl
+
+#ifdef __KLIBC__
+
+static int
+klibc_fcntl (int fd, int action, /* arg */...)
+{
+ va_list arg_ptr;
+ int arg;
+ struct stat sbuf;
+ int result;
+
+ va_start (arg_ptr, action);
+ arg = va_arg (arg_ptr, int);
+ result = fcntl (fd, action, arg);
+ /* EPERM for F_DUPFD, ENOTSUP for others */
+ if (result == -1 && (errno == EPERM || errno == ENOTSUP)
+ && !fstat (fd, &sbuf) && S_ISDIR (sbuf.st_mode))
+ {
+ ULONG ulMode;
+
+ switch (action)
+ {
+ case F_DUPFD:
+ /* Find available fd */
+ while (fcntl (arg, F_GETFL) != -1 || errno != EBADF)
+ arg++;
+
+ result = dup2 (fd, arg);
+ break;
+
+ /* Using underlying APIs is right ? */
+ case F_GETFD:
+ if (DosQueryFHState (fd, &ulMode))
+ break;
+
+ result = (ulMode & OPEN_FLAGS_NOINHERIT) ? FD_CLOEXEC : 0;
+ break;
+
+ case F_SETFD:
+ if (arg & ~FD_CLOEXEC)
+ break;
+
+ if (DosQueryFHState (fd, &ulMode))
+ break;
+
+ if (arg & FD_CLOEXEC)
+ ulMode |= OPEN_FLAGS_NOINHERIT;
+ else
+ ulMode &= ~OPEN_FLAGS_NOINHERIT;
+
+ /* Filter supported flags. */
+ ulMode &= (OPEN_FLAGS_WRITE_THROUGH | OPEN_FLAGS_FAIL_ON_ERROR
+ | OPEN_FLAGS_NO_CACHE | OPEN_FLAGS_NOINHERIT);
+
+ if (DosSetFHState (fd, ulMode))
+ break;
+
+ result = 0;
+ break;
+
+ case F_GETFL:
+ result = 0;
+ break;
+
+ case F_SETFL:
+ if (arg != 0)
+ break;
+
+ result = 0;
+ break;
+
+ default:
+ errno = EINVAL;
+ break;
+ }
+ }
+
+ va_end (arg_ptr);
+
+ return result;
+}
+
+#endif
diff --git a/lib/fcntl.in.h b/lib/fcntl.in.h
index 00b270c958d..9270ced8973 100644
--- a/lib/fcntl.in.h
+++ b/lib/fcntl.in.h
@@ -1,18 +1,18 @@
/* Like <fcntl.h>, but with non-working flags defined to 0.
- Copyright (C) 2006-2017 Free Software Foundation, Inc.
+ Copyright (C) 2006-2022 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 file is free software: you can redistribute it and/or modify
+ it under the terms of the GNU Lesser General Public License as
+ published by the Free Software Foundation; either version 2.1 of the
+ License, or (at your option) any later version.
- This program is distributed in the hope that it will be useful,
+ This file 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.
+ GNU Lesser General Public License for more details.
- You should have received a copy of the GNU General Public License
+ You should have received a copy of the GNU Lesser General Public License
along with this program. If not, see <https://www.gnu.org/licenses/>. */
/* written by Paul Eggert */
@@ -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 __WIN32__) && ! defined __CYGWIN__)
-# include <io.h>
-#endif
-
/* The definitions of _GL_FUNCDECL_RPL etc. are copied here. */
@@ -82,6 +88,47 @@
/* 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));
+# elif defined _WIN32 && !defined __CYGWIN__
+# if !(defined __cplusplus && defined GNULIB_NAMESPACE)
+# undef creat
+# define creat _creat
+# endif
+_GL_CXXALIAS_MDA (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");
+#elif @GNULIB_MDA_CREAT@
+/* On native Windows, map 'creat' to '_creat', so that -loldnames is not
+ required. In C++ with GNULIB_NAMESPACE, avoid differences between
+ platforms by defining GNULIB_NAMESPACE::creat always. */
+# if defined _WIN32 && !defined __CYGWIN__
+# if !(defined __cplusplus && defined GNULIB_NAMESPACE)
+# undef creat
+# define creat _creat
+# endif
+/* Need to cast, because in mingw the last argument is 'int mode'. */
+_GL_CXXALIAS_MDA_CAST (creat, int, (const char *filename, mode_t mode));
+# else
+_GL_CXXALIAS_SYS (creat, int, (const char *filename, mode_t mode));
+# endif
+_GL_CXXALIASWARN (creat);
+#endif
+
#if @GNULIB_FCNTL@
# if @REPLACE_FCNTL@
# if !(defined __cplusplus && defined GNULIB_NAMESPACE)
@@ -90,9 +137,15 @@
# endif
_GL_FUNCDECL_RPL (fcntl, int, (int fd, int action, ...));
_GL_CXXALIAS_RPL (fcntl, int, (int fd, int action, ...));
+# if !GNULIB_defined_rpl_fcntl
+# define GNULIB_defined_rpl_fcntl 1
+# endif
# else
# if !@HAVE_FCNTL@
_GL_FUNCDECL_SYS (fcntl, int, (int fd, int action, ...));
+# if !GNULIB_defined_fcntl
+# define GNULIB_defined_fcntl 1
+# endif
# endif
_GL_CXXALIAS_SYS (fcntl, int, (int fd, int action, ...));
# endif
@@ -114,6 +167,12 @@ _GL_WARN_ON_USE (fcntl, "fcntl is not always POSIX compliant - "
_GL_FUNCDECL_RPL (open, int, (const char *filename, int flags, ...)
_GL_ARG_NONNULL ((1)));
_GL_CXXALIAS_RPL (open, int, (const char *filename, int flags, ...));
+# elif defined _WIN32 && !defined __CYGWIN__
+# if !(defined __cplusplus && defined GNULIB_NAMESPACE)
+# undef open
+# define open _open
+# endif
+_GL_CXXALIAS_MDA (open, int, (const char *filename, int flags, ...));
# else
_GL_CXXALIAS_SYS (open, int, (const char *filename, int flags, ...));
# endif
@@ -127,6 +186,22 @@ _GL_CXXALIASWARN (open);
/* Assume open is always declared. */
_GL_WARN_ON_USE (open, "open is not always POSIX compliant - "
"use gnulib module open for portability");
+#elif @GNULIB_MDA_OPEN@
+/* On native Windows, map 'open' to '_open', so that -loldnames is not
+ required. In C++ with GNULIB_NAMESPACE, avoid differences between
+ platforms by defining GNULIB_NAMESPACE::open always. */
+# if defined _WIN32 && !defined __CYGWIN__
+# if !(defined __cplusplus && defined GNULIB_NAMESPACE)
+# undef open
+# define open _open
+# endif
+_GL_CXXALIAS_MDA (open, int, (const char *filename, int flags, ...));
+# else
+_GL_CXXALIAS_SYS (open, int, (const char *filename, int flags, ...));
+# endif
+# if !defined __hpux
+_GL_CXXALIASWARN (open);
+# endif
#endif
#if @GNULIB_OPENAT@
@@ -360,6 +435,10 @@ _GL_WARN_ON_USE (openat, "openat is not portable - "
# define AT_EACCESS 4
#endif
+/* Ignore this flag if not supported. */
+#ifndef AT_NO_AUTOMOUNT
+# define AT_NO_AUTOMOUNT 0
+#endif
#endif /* _@GUARD_PREFIX@_FCNTL_H */
#endif /* _@GUARD_PREFIX@_FCNTL_H */
diff --git a/lib/fdatasync.c b/lib/fdatasync.c
deleted file mode 100644
index 25fd74049fb..00000000000
--- a/lib/fdatasync.c
+++ /dev/null
@@ -1,27 +0,0 @@
-/* Emulate fdatasync on platforms that lack it.
-
- Copyright (C) 2011-2017 Free Software Foundation, Inc.
-
- This library is free software; you can redistribute it and/or
- modify it under the terms of the GNU General Public
- License as published by the Free Software Foundation; either
- version 3 of the License, or (at your option) any later version.
-
- This 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 this program. If not, see <https://www.gnu.org/licenses/>. */
-
-#include <config.h>
-#include <unistd.h>
-
-int
-fdatasync (int fd)
-{
- /* This does more work than strictly necessary, but is the best we
- can do portably. */
- return fsync (fd);
-}
diff --git a/lib/fdopendir.c b/lib/fdopendir.c
index 7f72258598d..c2b0e1ed347 100644
--- a/lib/fdopendir.c
+++ b/lib/fdopendir.c
@@ -1,9 +1,9 @@
/* provide a replacement fdopendir function
- Copyright (C) 2004-2017 Free Software Foundation, Inc.
+ Copyright (C) 2004-2022 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
+ 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,
diff --git a/lib/file-has-acl.c b/lib/file-has-acl.c
new file mode 100644
index 00000000000..e02f0626ad3
--- /dev/null
+++ b/lib/file-has-acl.c
@@ -0,0 +1,502 @@
+/* Test whether a file has a nontrivial ACL. -*- coding: utf-8 -*-
+
+ Copyright (C) 2002-2003, 2005-2022 Free Software Foundation, Inc.
+
+ This program is free software: you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation, either version 3 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program. If not, see <https://www.gnu.org/licenses/>.
+
+ Written by Paul Eggert, Andreas Grünbacher, and Bruno Haible. */
+
+/* Without this pragma, gcc 4.7.0 20120126 may suggest that the
+ file_has_acl function might be candidate for attribute 'const' */
+#if (__GNUC__ == 4 && 6 <= __GNUC_MINOR__) || 4 < __GNUC__
+# pragma GCC diagnostic ignored "-Wsuggest-attribute=const"
+#endif
+
+#include <config.h>
+
+#include "acl.h"
+
+#include "acl-internal.h"
+
+#if GETXATTR_WITH_POSIX_ACLS
+# include <sys/xattr.h>
+# include <linux/xattr.h>
+#endif
+
+/* Return 1 if NAME has a nontrivial access control list,
+ 0 if ACLs are not supported, or if NAME has no or only a base ACL,
+ and -1 (setting errno) on error. Note callers can determine
+ if ACLs are not supported as errno is set in that case also.
+ SB must be set to the stat buffer of NAME,
+ obtained through stat() or lstat(). */
+
+int
+file_has_acl (char const *name, struct stat const *sb)
+{
+#if USE_ACL
+ if (! S_ISLNK (sb->st_mode))
+ {
+
+# if GETXATTR_WITH_POSIX_ACLS
+
+ ssize_t ret;
+
+ ret = getxattr (name, XATTR_NAME_POSIX_ACL_ACCESS, NULL, 0);
+ if (ret < 0 && errno == ENODATA)
+ ret = 0;
+ else if (ret > 0)
+ return 1;
+
+ if (ret == 0 && S_ISDIR (sb->st_mode))
+ {
+ ret = getxattr (name, XATTR_NAME_POSIX_ACL_DEFAULT, NULL, 0);
+ if (ret < 0 && errno == ENODATA)
+ ret = 0;
+ else if (ret > 0)
+ return 1;
+ }
+
+ if (ret < 0)
+ return - acl_errno_valid (errno);
+ return ret;
+
+# elif HAVE_ACL_GET_FILE
+
+ /* POSIX 1003.1e (draft 17 -- abandoned) specific version. */
+ /* Linux, FreeBSD, Mac OS X, IRIX, Tru64, Cygwin >= 2.5 */
+ int ret;
+
+ if (HAVE_ACL_EXTENDED_FILE) /* Linux */
+ {
+ /* On Linux, acl_extended_file is an optimized function: It only
+ makes two calls to getxattr(), one for ACL_TYPE_ACCESS, one for
+ ACL_TYPE_DEFAULT. */
+ ret = acl_extended_file (name);
+ }
+ else /* FreeBSD, Mac OS X, IRIX, Tru64, Cygwin >= 2.5 */
+ {
+# if HAVE_ACL_TYPE_EXTENDED /* Mac OS X */
+ /* On Mac OS X, acl_get_file (name, ACL_TYPE_ACCESS)
+ and acl_get_file (name, ACL_TYPE_DEFAULT)
+ always return NULL / EINVAL. There is no point in making
+ these two useless calls. The real ACL is retrieved through
+ acl_get_file (name, ACL_TYPE_EXTENDED). */
+ acl_t acl = acl_get_file (name, ACL_TYPE_EXTENDED);
+ if (acl)
+ {
+ ret = acl_extended_nontrivial (acl);
+ acl_free (acl);
+ }
+ else
+ ret = -1;
+# else /* FreeBSD, IRIX, Tru64, Cygwin >= 2.5 */
+ acl_t acl = acl_get_file (name, ACL_TYPE_ACCESS);
+ if (acl)
+ {
+ int saved_errno;
+
+ ret = acl_access_nontrivial (acl);
+ saved_errno = errno;
+ acl_free (acl);
+ errno = saved_errno;
+# if HAVE_ACL_FREE_TEXT /* Tru64 */
+ /* On OSF/1, acl_get_file (name, ACL_TYPE_DEFAULT) always
+ returns NULL with errno not set. There is no point in
+ making this call. */
+# else /* FreeBSD, IRIX, Cygwin >= 2.5 */
+ /* On Linux, FreeBSD, IRIX, acl_get_file (name, ACL_TYPE_ACCESS)
+ and acl_get_file (name, ACL_TYPE_DEFAULT) on a directory
+ either both succeed or both fail; it depends on the
+ file system. Therefore there is no point in making the second
+ call if the first one already failed. */
+ if (ret == 0 && S_ISDIR (sb->st_mode))
+ {
+ acl = acl_get_file (name, ACL_TYPE_DEFAULT);
+ if (acl)
+ {
+# ifdef __CYGWIN__ /* Cygwin >= 2.5 */
+ ret = acl_access_nontrivial (acl);
+ saved_errno = errno;
+ acl_free (acl);
+ errno = saved_errno;
+# else
+ ret = (0 < acl_entries (acl));
+ acl_free (acl);
+# endif
+ }
+ else
+ ret = -1;
+ }
+# endif
+ }
+ else
+ ret = -1;
+# endif
+ }
+ if (ret < 0)
+ return - acl_errno_valid (errno);
+ return ret;
+
+# elif HAVE_FACL && defined GETACL /* Solaris, Cygwin < 2.5, not HP-UX */
+
+# if defined ACL_NO_TRIVIAL
+
+ /* Solaris 10 (newer version), which has additional API declared in
+ <sys/acl.h> (acl_t) and implemented in libsec (acl_set, acl_trivial,
+ acl_fromtext, ...). */
+ return acl_trivial (name);
+
+# else /* Solaris, Cygwin, general case */
+
+ /* Solaris 2.5 through Solaris 10, Cygwin, and contemporaneous versions
+ of Unixware. The acl() call returns the access and default ACL both
+ at once. */
+ {
+ /* Initially, try to read the entries into a stack-allocated buffer.
+ Use malloc if it does not fit. */
+ enum
+ {
+ alloc_init = 4000 / sizeof (aclent_t), /* >= 3 */
+ alloc_max = MIN (INT_MAX, SIZE_MAX / sizeof (aclent_t))
+ };
+ aclent_t buf[alloc_init];
+ size_t alloc = alloc_init;
+ aclent_t *entries = buf;
+ aclent_t *malloced = NULL;
+ int count;
+
+ for (;;)
+ {
+ count = acl (name, GETACL, alloc, entries);
+ if (count < 0 && errno == ENOSPC)
+ {
+ /* Increase the size of the buffer. */
+ free (malloced);
+ if (alloc > alloc_max / 2)
+ {
+ errno = ENOMEM;
+ return -1;
+ }
+ alloc = 2 * alloc; /* <= alloc_max */
+ entries = malloced =
+ (aclent_t *) malloc (alloc * sizeof (aclent_t));
+ if (entries == NULL)
+ {
+ errno = ENOMEM;
+ return -1;
+ }
+ continue;
+ }
+ break;
+ }
+ if (count < 0)
+ {
+ if (errno == ENOSYS || errno == ENOTSUP)
+ ;
+ else
+ {
+ free (malloced);
+ return -1;
+ }
+ }
+ else if (count == 0)
+ ;
+ else
+ {
+ /* Don't use MIN_ACL_ENTRIES: It's set to 4 on Cygwin, but Cygwin
+ returns only 3 entries for files with no ACL. But this is safe:
+ If there are more than 4 entries, there cannot be only the
+ "user::", "group::", "other:", and "mask:" entries. */
+ if (count > 4)
+ {
+ free (malloced);
+ return 1;
+ }
+
+ if (acl_nontrivial (count, entries))
+ {
+ free (malloced);
+ return 1;
+ }
+ }
+ free (malloced);
+ }
+
+# ifdef ACE_GETACL
+ /* Solaris also has a different variant of ACLs, used in ZFS and NFSv4
+ file systems (whereas the other ones are used in UFS file systems). */
+ {
+ /* Initially, try to read the entries into a stack-allocated buffer.
+ Use malloc if it does not fit. */
+ enum
+ {
+ alloc_init = 4000 / sizeof (ace_t), /* >= 3 */
+ alloc_max = MIN (INT_MAX, SIZE_MAX / sizeof (ace_t))
+ };
+ ace_t buf[alloc_init];
+ size_t alloc = alloc_init;
+ ace_t *entries = buf;
+ ace_t *malloced = NULL;
+ int count;
+
+ for (;;)
+ {
+ count = acl (name, ACE_GETACL, alloc, entries);
+ if (count < 0 && errno == ENOSPC)
+ {
+ /* Increase the size of the buffer. */
+ free (malloced);
+ if (alloc > alloc_max / 2)
+ {
+ errno = ENOMEM;
+ return -1;
+ }
+ alloc = 2 * alloc; /* <= alloc_max */
+ entries = malloced = (ace_t *) malloc (alloc * sizeof (ace_t));
+ if (entries == NULL)
+ {
+ errno = ENOMEM;
+ return -1;
+ }
+ continue;
+ }
+ break;
+ }
+ if (count < 0)
+ {
+ if (errno == ENOSYS || errno == EINVAL)
+ ;
+ else
+ {
+ free (malloced);
+ return -1;
+ }
+ }
+ else if (count == 0)
+ ;
+ else
+ {
+ /* In the old (original Solaris 10) convention:
+ If there are more than 3 entries, there cannot be only the
+ ACE_OWNER, ACE_GROUP, ACE_OTHER entries.
+ In the newer Solaris 10 and Solaris 11 convention:
+ If there are more than 6 entries, there cannot be only the
+ ACE_OWNER, ACE_GROUP, ACE_EVERYONE entries, each once with
+ NEW_ACE_ACCESS_ALLOWED_ACE_TYPE and once with
+ NEW_ACE_ACCESS_DENIED_ACE_TYPE. */
+ if (count > 6)
+ {
+ free (malloced);
+ return 1;
+ }
+
+ if (acl_ace_nontrivial (count, entries))
+ {
+ free (malloced);
+ return 1;
+ }
+ }
+ free (malloced);
+ }
+# endif
+
+ return 0;
+# endif
+
+# elif HAVE_GETACL /* HP-UX */
+
+ {
+ struct acl_entry entries[NACLENTRIES];
+ int count;
+
+ count = getacl (name, NACLENTRIES, entries);
+
+ if (count < 0)
+ {
+ /* ENOSYS is seen on newer HP-UX versions.
+ EOPNOTSUPP is typically seen on NFS mounts.
+ ENOTSUP was seen on Quantum StorNext file systems (cvfs). */
+ if (errno == ENOSYS || errno == EOPNOTSUPP || errno == ENOTSUP)
+ ;
+ else
+ return -1;
+ }
+ else if (count == 0)
+ return 0;
+ else /* count > 0 */
+ {
+ if (count > NACLENTRIES)
+ /* If NACLENTRIES cannot be trusted, use dynamic memory
+ allocation. */
+ abort ();
+
+ /* If there are more than 3 entries, there cannot be only the
+ (uid,%), (%,gid), (%,%) entries. */
+ if (count > 3)
+ return 1;
+
+ {
+ struct stat statbuf;
+
+ if (stat (name, &statbuf) == -1 && errno != EOVERFLOW)
+ return -1;
+
+ return acl_nontrivial (count, entries);
+ }
+ }
+ }
+
+# if HAVE_ACLV_H /* HP-UX >= 11.11 */
+
+ {
+ struct acl entries[NACLVENTRIES];
+ int count;
+
+ count = acl ((char *) name, ACL_GET, NACLVENTRIES, entries);
+
+ if (count < 0)
+ {
+ /* EOPNOTSUPP is seen on NFS in HP-UX 11.11, 11.23.
+ EINVAL is seen on NFS in HP-UX 11.31. */
+ if (errno == ENOSYS || errno == EOPNOTSUPP || errno == EINVAL)
+ ;
+ else
+ return -1;
+ }
+ else if (count == 0)
+ return 0;
+ else /* count > 0 */
+ {
+ if (count > NACLVENTRIES)
+ /* If NACLVENTRIES cannot be trusted, use dynamic memory
+ allocation. */
+ abort ();
+
+ /* If there are more than 4 entries, there cannot be only the
+ four base ACL entries. */
+ if (count > 4)
+ return 1;
+
+ return aclv_nontrivial (count, entries);
+ }
+ }
+
+# endif
+
+# elif HAVE_ACLX_GET && defined ACL_AIX_WIP /* AIX */
+
+ acl_type_t type;
+ char aclbuf[1024];
+ void *acl = aclbuf;
+ size_t aclsize = sizeof (aclbuf);
+ mode_t mode;
+
+ for (;;)
+ {
+ /* The docs say that type being 0 is equivalent to ACL_ANY, but it
+ is not true, in AIX 5.3. */
+ type.u64 = ACL_ANY;
+ if (aclx_get (name, 0, &type, aclbuf, &aclsize, &mode) >= 0)
+ break;
+ if (errno == ENOSYS)
+ return 0;
+ if (errno != ENOSPC)
+ {
+ if (acl != aclbuf)
+ free (acl);
+ return -1;
+ }
+ aclsize = 2 * aclsize;
+ if (acl != aclbuf)
+ free (acl);
+ acl = malloc (aclsize);
+ if (acl == NULL)
+ {
+ errno = ENOMEM;
+ return -1;
+ }
+ }
+
+ if (type.u64 == ACL_AIXC)
+ {
+ int result = acl_nontrivial ((struct acl *) acl);
+ if (acl != aclbuf)
+ free (acl);
+ return result;
+ }
+ else if (type.u64 == ACL_NFS4)
+ {
+ int result = acl_nfs4_nontrivial ((nfs4_acl_int_t *) acl);
+ if (acl != aclbuf)
+ free (acl);
+ return result;
+ }
+ else
+ {
+ /* A newer type of ACL has been introduced in the system.
+ We should better support it. */
+ if (acl != aclbuf)
+ free (acl);
+ errno = EINVAL;
+ return -1;
+ }
+
+# elif HAVE_STATACL /* older AIX */
+
+ union { struct acl a; char room[4096]; } u;
+
+ if (statacl ((char *) name, STX_NORMAL, &u.a, sizeof (u)) < 0)
+ return -1;
+
+ return acl_nontrivial (&u.a);
+
+# elif HAVE_ACLSORT /* NonStop Kernel */
+
+ {
+ struct acl entries[NACLENTRIES];
+ int count;
+
+ count = acl ((char *) name, ACL_GET, NACLENTRIES, entries);
+
+ if (count < 0)
+ {
+ if (errno == ENOSYS || errno == ENOTSUP)
+ ;
+ else
+ return -1;
+ }
+ else if (count == 0)
+ return 0;
+ else /* count > 0 */
+ {
+ if (count > NACLENTRIES)
+ /* If NACLENTRIES cannot be trusted, use dynamic memory
+ allocation. */
+ abort ();
+
+ /* If there are more than 4 entries, there cannot be only the
+ four base ACL entries. */
+ if (count > 4)
+ return 1;
+
+ return acl_nontrivial (count, entries);
+ }
+ }
+
+# endif
+ }
+#endif
+
+ return 0;
+}
diff --git a/lib/filemode.c b/lib/filemode.c
index c6cf1f3196c..a8cbea844c8 100644
--- a/lib/filemode.c
+++ b/lib/filemode.c
@@ -1,11 +1,11 @@
/* filemode.c -- make a string describing file modes
- Copyright (C) 1985, 1990, 1993, 1998-2000, 2004, 2006, 2009-2017 Free
+ Copyright (C) 1985, 1990, 1993, 1998-2000, 2004, 2006, 2009-2022 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
+ 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,
@@ -20,17 +20,6 @@
#include "filemode.h"
-/* The following is for Cray DMF (Data Migration Facility), which is a
- HSM file system. A migrated file has a 'st_dm_mode' that is
- different from the normal 'st_mode', so any tests for migrated
- files should use the former. */
-#if HAVE_ST_DM_MODE
-# define IS_MIGRATED_FILE(statp) \
- (S_ISOFD (statp->st_dm_mode) || S_ISOFL (statp->st_dm_mode))
-#else
-# define IS_MIGRATED_FILE(statp) 0
-#endif
-
#if ! HAVE_DECL_STRMODE
/* Return a character indicating the type of file described by
@@ -126,7 +115,6 @@ strmode (mode_t mode, char *str)
for files whose type cannot be determined solely from st_mode:
'F' semaphore
- 'M' migrated file (Cray DMF)
'Q' message queue
'S' shared memory object
'T' typed memory object
@@ -169,8 +157,6 @@ filemodestring (struct stat const *statp, char *str)
if (S_TYPEISSEM (statp))
str[0] = 'F';
- else if (IS_MIGRATED_FILE (statp))
- str[0] = 'M';
else if (S_TYPEISMQ (statp))
str[0] = 'Q';
else if (S_TYPEISSHM (statp))
diff --git a/lib/filemode.h b/lib/filemode.h
index 809bf7eb0fb..bf38181cdcd 100644
--- a/lib/filemode.h
+++ b/lib/filemode.h
@@ -1,11 +1,11 @@
/* Make a string describing file modes.
- Copyright (C) 1998-1999, 2003, 2006, 2009-2017 Free Software Foundation,
+ Copyright (C) 1998-1999, 2003, 2006, 2009-2022 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
+ 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,
diff --git a/lib/filename.h b/lib/filename.h
new file mode 100644
index 00000000000..ab77ca2df91
--- /dev/null
+++ b/lib/filename.h
@@ -0,0 +1,112 @@
+/* Basic filename support macros.
+ Copyright (C) 2001-2022 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 Lesser General Public
+ License as published by the Free Software Foundation; either
+ version 2.1 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
+ Lesser General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public
+ License along with the GNU C Library; if not, see
+ <https://www.gnu.org/licenses/>. */
+
+/* From Paul Eggert and Jim Meyering. */
+
+#ifndef _FILENAME_H
+#define _FILENAME_H
+
+#include <string.h>
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+
+/* Filename support.
+ ISSLASH(C) tests whether C is a directory separator
+ character.
+ HAS_DEVICE(Filename) tests whether Filename contains a device
+ specification.
+ FILE_SYSTEM_PREFIX_LEN(Filename) length of the device specification
+ at the beginning of Filename,
+ index of the part consisting of
+ alternating components and slashes.
+ FILE_SYSTEM_DRIVE_PREFIX_CAN_BE_RELATIVE
+ 1 when a non-empty device specification
+ can be followed by an empty or relative
+ part,
+ 0 when a non-empty device specification
+ must be followed by a slash,
+ 0 when device specification don't exist.
+ IS_ABSOLUTE_FILE_NAME(Filename)
+ tests whether Filename is independent of
+ any notion of "current directory".
+ IS_RELATIVE_FILE_NAME(Filename)
+ tests whether Filename may be concatenated
+ to a directory filename.
+ Note: On native Windows, OS/2, DOS, "c:" is neither an absolute nor a
+ relative file name!
+ IS_FILE_NAME_WITH_DIR(Filename) tests whether Filename contains a device
+ or directory specification.
+ */
+#if defined _WIN32 || defined __CYGWIN__ \
+ || defined __EMX__ || defined __MSDOS__ || defined __DJGPP__
+ /* Native Windows, Cygwin, OS/2, DOS */
+# define ISSLASH(C) ((C) == '/' || (C) == '\\')
+ /* Internal macro: Tests whether a character is a drive letter. */
+# define _IS_DRIVE_LETTER(C) \
+ (((C) >= 'A' && (C) <= 'Z') || ((C) >= 'a' && (C) <= 'z'))
+ /* Help the compiler optimizing it. This assumes ASCII. */
+# undef _IS_DRIVE_LETTER
+# define _IS_DRIVE_LETTER(C) \
+ (((unsigned int) (C) | ('a' - 'A')) - 'a' <= 'z' - 'a')
+# define HAS_DEVICE(Filename) \
+ (_IS_DRIVE_LETTER ((Filename)[0]) && (Filename)[1] == ':')
+# define FILE_SYSTEM_PREFIX_LEN(Filename) (HAS_DEVICE (Filename) ? 2 : 0)
+# ifdef __CYGWIN__
+# define FILE_SYSTEM_DRIVE_PREFIX_CAN_BE_RELATIVE 0
+# else
+ /* On native Windows, OS/2, DOS, the system has the notion of a
+ "current directory" on each drive. */
+# define FILE_SYSTEM_DRIVE_PREFIX_CAN_BE_RELATIVE 1
+# endif
+# if FILE_SYSTEM_DRIVE_PREFIX_CAN_BE_RELATIVE
+# define IS_ABSOLUTE_FILE_NAME(Filename) \
+ ISSLASH ((Filename)[FILE_SYSTEM_PREFIX_LEN (Filename)])
+# else
+# define IS_ABSOLUTE_FILE_NAME(Filename) \
+ (ISSLASH ((Filename)[0]) || HAS_DEVICE (Filename))
+# endif
+# define IS_RELATIVE_FILE_NAME(Filename) \
+ (! (ISSLASH ((Filename)[0]) || HAS_DEVICE (Filename)))
+# define IS_FILE_NAME_WITH_DIR(Filename) \
+ (strchr ((Filename), '/') != NULL || strchr ((Filename), '\\') != NULL \
+ || HAS_DEVICE (Filename))
+#else
+ /* Unix */
+# define ISSLASH(C) ((C) == '/')
+# define HAS_DEVICE(Filename) ((void) (Filename), 0)
+# define FILE_SYSTEM_PREFIX_LEN(Filename) ((void) (Filename), 0)
+# define FILE_SYSTEM_DRIVE_PREFIX_CAN_BE_RELATIVE 0
+# define IS_ABSOLUTE_FILE_NAME(Filename) ISSLASH ((Filename)[0])
+# define IS_RELATIVE_FILE_NAME(Filename) (! ISSLASH ((Filename)[0]))
+# define IS_FILE_NAME_WITH_DIR(Filename) (strchr ((Filename), '/') != NULL)
+#endif
+
+/* Deprecated macros. For backward compatibility with old users of the
+ 'filename' module. */
+#define IS_ABSOLUTE_PATH IS_ABSOLUTE_FILE_NAME
+#define IS_PATH_WITH_DIR IS_FILE_NAME_WITH_DIR
+
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* _FILENAME_H */
diff --git a/lib/filevercmp.c b/lib/filevercmp.c
index 4026097b38e..7e54793e613 100644
--- a/lib/filevercmp.c
+++ b/lib/filevercmp.c
@@ -1,78 +1,88 @@
-/*
+/* Compare file names containing version numbers.
+
Copyright (C) 1995 Ian Jackson <iwj10@cus.cam.ac.uk>
Copyright (C) 2001 Anthony Towns <aj@azure.humbug.org.au>
- Copyright (C) 2008-2017 Free Software Foundation, Inc.
+ Copyright (C) 2008-2022 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 file is free software: you can redistribute it and/or modify
+ it under the terms of the GNU Lesser 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,
+ This file 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.
+ GNU Lesser General Public License for more details.
- You should have received a copy of the GNU General Public License
- along with this program. If not, see <https://www.gnu.org/licenses/>. */
+ You should have received a copy of the GNU Lesser General Public License
+ along with this program. If not, see <https://www.gnu.org/licenses/>. */
#include <config.h>
#include "filevercmp.h"
-#include <sys/types.h>
-#include <stdlib.h>
#include <stdbool.h>
-#include <string.h>
#include <c-ctype.h>
#include <limits.h>
-
-/* Match a file suffix defined by this regular expression:
- /(\.[A-Za-z~][A-Za-z0-9~]*)*$/
- Scan the string *STR and return a pointer to the matching suffix, or
- NULL if not found. Upon return, *STR points to terminating NUL. */
-static const char *
-match_suffix (const char **str)
+#include <idx.h>
+#include <verify.h>
+
+/* Return the length of a prefix of S that corresponds to the suffix
+ defined by this extended regular expression in the C locale:
+ (\.[A-Za-z~][A-Za-z0-9~]*)*$
+ Use the longest suffix matching this regular expression,
+ except do not use all of S as a suffix if S is nonempty.
+ If *LEN is -1, S is a string; set *LEN to S's length.
+ Otherwise, *LEN should be nonnegative, S is a char array,
+ and *LEN does not change. */
+static idx_t
+file_prefixlen (char const *s, ptrdiff_t *len)
{
- const char *match = NULL;
- bool read_alpha = false;
- while (**str)
+ size_t n = *len; /* SIZE_MAX if N == -1. */
+ idx_t prefixlen = 0;
+
+ for (idx_t i = 0; ; )
{
- if (read_alpha)
- {
- read_alpha = false;
- if (!c_isalpha (**str) && '~' != **str)
- match = NULL;
- }
- else if ('.' == **str)
+ if (*len < 0 ? !s[i] : i == n)
{
- read_alpha = true;
- if (!match)
- match = *str;
+ *len = i;
+ return prefixlen;
}
- else if (!c_isalnum (**str) && '~' != **str)
- match = NULL;
- (*str)++;
+
+ i++;
+ prefixlen = i;
+ while (i + 1 < n && s[i] == '.' && (c_isalpha (s[i + 1])
+ || s[i + 1] == '~'))
+ for (i += 2; i < n && (c_isalnum (s[i]) || s[i] == '~'); i++)
+ continue;
}
- return match;
}
-/* verrevcmp helper function */
+/* Return a version sort comparison value for S's byte at position POS.
+ S has length LEN. If POS == LEN, sort before all non-'~' bytes. */
+
static int
-order (unsigned char c)
+order (char const *s, idx_t pos, idx_t len)
{
+ if (pos == len)
+ return -1;
+
+ unsigned char c = s[pos];
if (c_isdigit (c))
return 0;
else if (c_isalpha (c))
return c;
else if (c == '~')
- return -1;
+ return -2;
else
- return (int) c + UCHAR_MAX + 1;
+ {
+ verify (UCHAR_MAX <= (INT_MAX - 1 - 2) / 2);
+ return c + UCHAR_MAX + 1;
+ }
}
/* slightly modified verrevcmp function from dpkg
- S1, S2 - compared string
- S1_LEN, S2_LEN - length of strings to be scanned
+ S1, S2 - compared char array
+ S1_LEN, S2_LEN - length of arrays to be scanned
This implements the algorithm for comparison of version strings
specified by Debian and now widely adopted. The detailed
@@ -81,37 +91,38 @@ order (unsigned char c)
implements that from s5.6.12 of Debian Policy v3.8.0.1
https://www.debian.org/doc/debian-policy/ch-controlfields.html#s-f-Version */
static int _GL_ATTRIBUTE_PURE
-verrevcmp (const char *s1, size_t s1_len, const char *s2, size_t s2_len)
+verrevcmp (const char *s1, idx_t s1_len, const char *s2, idx_t s2_len)
{
- size_t s1_pos = 0;
- size_t s2_pos = 0;
+ idx_t s1_pos = 0;
+ idx_t s2_pos = 0;
while (s1_pos < s1_len || s2_pos < s2_len)
{
int first_diff = 0;
while ((s1_pos < s1_len && !c_isdigit (s1[s1_pos]))
|| (s2_pos < s2_len && !c_isdigit (s2[s2_pos])))
{
- int s1_c = (s1_pos == s1_len) ? 0 : order (s1[s1_pos]);
- int s2_c = (s2_pos == s2_len) ? 0 : order (s2[s2_pos]);
+ int s1_c = order (s1, s1_pos, s1_len);
+ int s2_c = order (s2, s2_pos, s2_len);
if (s1_c != s2_c)
return s1_c - s2_c;
s1_pos++;
s2_pos++;
}
- while (s1[s1_pos] == '0')
+ while (s1_pos < s1_len && s1[s1_pos] == '0')
s1_pos++;
- while (s2[s2_pos] == '0')
+ while (s2_pos < s2_len && s2[s2_pos] == '0')
s2_pos++;
- while (c_isdigit (s1[s1_pos]) && c_isdigit (s2[s2_pos]))
+ while (s1_pos < s1_len && s2_pos < s2_len
+ && c_isdigit (s1[s1_pos]) && c_isdigit (s2[s2_pos]))
{
if (!first_diff)
first_diff = s1[s1_pos] - s2[s2_pos];
s1_pos++;
s2_pos++;
}
- if (c_isdigit (s1[s1_pos]))
+ if (s1_pos < s1_len && c_isdigit (s1[s1_pos]))
return 1;
- if (c_isdigit (s2[s2_pos]))
+ if (s2_pos < s2_len && c_isdigit (s2[s2_pos]))
return -1;
if (first_diff)
return first_diff;
@@ -124,58 +135,56 @@ verrevcmp (const char *s1, size_t s1_len, const char *s2, size_t s2_len)
int
filevercmp (const char *s1, const char *s2)
{
- const char *s1_pos;
- const char *s2_pos;
- const char *s1_suffix, *s2_suffix;
- size_t s1_len, s2_len;
- int result;
-
- /* easy comparison to see if strings are identical */
- int simple_cmp = strcmp (s1, s2);
- if (simple_cmp == 0)
- return 0;
+ return filenvercmp (s1, -1, s2, -1);
+}
- /* special handle for "", "." and ".." */
- if (!*s1)
- return -1;
- if (!*s2)
- return 1;
- if (0 == strcmp (".", s1))
- return -1;
- if (0 == strcmp (".", s2))
- return 1;
- if (0 == strcmp ("..", s1))
- return -1;
- if (0 == strcmp ("..", s2))
+/* Compare versions A (of length ALEN) and B (of length BLEN).
+ See filevercmp.h for function description. */
+int
+filenvercmp (char const *a, ptrdiff_t alen, char const *b, ptrdiff_t blen)
+{
+ /* Special case for empty versions. */
+ bool aempty = alen < 0 ? !a[0] : !alen;
+ bool bempty = blen < 0 ? !b[0] : !blen;
+ if (aempty)
+ return -!bempty;
+ if (bempty)
return 1;
- /* special handle for other hidden files */
- if (*s1 == '.' && *s2 != '.')
- return -1;
- if (*s1 != '.' && *s2 == '.')
- return 1;
- if (*s1 == '.' && *s2 == '.')
+ /* Special cases for leading ".": "." sorts first, then "..", then
+ other names with leading ".", then other names. */
+ if (a[0] == '.')
{
- s1++;
- s2++;
- }
+ if (b[0] != '.')
+ return -1;
- /* "cut" file suffixes */
- s1_pos = s1;
- s2_pos = s2;
- s1_suffix = match_suffix (&s1_pos);
- s2_suffix = match_suffix (&s2_pos);
- s1_len = (s1_suffix ? s1_suffix : s1_pos) - s1;
- s2_len = (s2_suffix ? s2_suffix : s2_pos) - s2;
-
- /* restore file suffixes if strings are identical after "cut" */
- if ((s1_suffix || s2_suffix) && (s1_len == s2_len)
- && 0 == strncmp (s1, s2, s1_len))
- {
- s1_len = s1_pos - s1;
- s2_len = s2_pos - s2;
+ bool adot = alen < 0 ? !a[1] : alen == 1;
+ bool bdot = blen < 0 ? !b[1] : blen == 1;
+ if (adot)
+ return -!bdot;
+ if (bdot)
+ return 1;
+
+ bool adotdot = a[1] == '.' && (alen < 0 ? !a[2] : alen == 2);
+ bool bdotdot = b[1] == '.' && (blen < 0 ? !b[2] : blen == 2);
+ if (adotdot)
+ return -!bdotdot;
+ if (bdotdot)
+ return 1;
}
+ else if (b[0] == '.')
+ return 1;
+
+ /* Cut file suffixes. */
+ idx_t aprefixlen = file_prefixlen (a, &alen);
+ idx_t bprefixlen = file_prefixlen (b, &blen);
+
+ /* If both suffixes are empty, a second pass would return the same thing. */
+ bool one_pass_only = aprefixlen == alen && bprefixlen == blen;
+
+ int result = verrevcmp (a, aprefixlen, b, bprefixlen);
- result = verrevcmp (s1, s1_len, s2, s2_len);
- return result == 0 ? simple_cmp : result;
+ /* Return the initial result if nonzero, or if no second pass is needed.
+ Otherwise, restore the suffixes and try again. */
+ return result || one_pass_only ? result : verrevcmp (a, alen, b, blen);
}
diff --git a/lib/filevercmp.h b/lib/filevercmp.h
index 25cc6f624cd..57949760b25 100644
--- a/lib/filevercmp.h
+++ b/lib/filevercmp.h
@@ -1,42 +1,78 @@
-/*
+/* Compare file names containing version numbers.
+
Copyright (C) 1995 Ian Jackson <iwj10@cus.cam.ac.uk>
Copyright (C) 2001 Anthony Towns <aj@azure.humbug.org.au>
- Copyright (C) 2008-2017 Free Software Foundation, Inc.
+ Copyright (C) 2008-2022 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 file is free software: you can redistribute it and/or modify
+ it under the terms of the GNU Lesser 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,
+ This file 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.
+ GNU Lesser General Public License for more details.
- You should have received a copy of the GNU General Public License
- along with this program. If not, see <https://www.gnu.org/licenses/>. */
+ You should have received a copy of the GNU Lesser General Public License
+ along with this program. If not, see <https://www.gnu.org/licenses/>. */
#ifndef FILEVERCMP_H
#define FILEVERCMP_H
-/* Compare version strings:
+#include <stddef.h>
+
+/* Compare strings A and B as file names containing version numbers,
+ and return an integer that is negative, zero, or positive depending
+ on whether A compares less than, equal to, or greater than B.
+
+ Use the following version sort algorithm:
+
+ 1. Compare the strings' maximal-length non-digit prefixes lexically.
+ If there is a difference return that difference.
+ Otherwise discard the prefixes and continue with the next step.
+
+ 2. Compare the strings' maximal-length digit prefixes, using
+ numeric comparison of the numbers represented by each prefix.
+ (Treat an empty prefix as zero; this can happen only at string end.)
+ If there is a difference, return that difference.
+ Otherwise discard the prefixes and continue with the next step.
+
+ 3. If both strings are empty, return 0. Otherwise continue with step 1.
+
+ In version sort, lexical comparison is left to right, byte by byte,
+ using the byte's numeric value (0-255), except that:
+
+ 1. ASCII letters sort before other bytes.
+ 2. A tilde sorts before anything, even an empty string.
+
+ In addition to the version sort rules, the following strings have
+ special priority and sort before all other strings (listed in order):
- This function compares strings S1 and S2:
- 1) By PREFIX in the same way as strcmp.
- 2) Then by VERSION (most similarly to version compare of Debian's dpkg).
- Leading zeros in version numbers are ignored.
- 3) If both (PREFIX and VERSION) are equal, strcmp function is used for
- comparison. So this function can return 0 if (and only if) strings S1
- and S2 are identical.
+ 1. The empty string.
+ 2. ".".
+ 3. "..".
+ 4. Strings starting with "." sort before other strings.
- It returns number >0 for S1 > S2, 0 for S1 == S2 and number <0 for S1 < S2.
+ Before comparing two strings where both begin with non-".",
+ or where both begin with "." but neither is "." or "..",
+ suffixes matching the C-locale extended regular expression
+ (\.[A-Za-z~][A-Za-z0-9~]*)*$ are removed and the strings compared
+ without them, using version sort without special priority;
+ if they do not compare equal, this comparison result is used and
+ the suffixes are effectively ignored. Otherwise, the entire
+ strings are compared using version sort. When removing a suffix
+ from a nonempty string, remove the maximal-length suffix such that
+ the remaining string is nonempty.
- This function compares strings, in a way that if VER1 and VER2 are version
- numbers and PREFIX and SUFFIX (SUFFIX defined as (\.[A-Za-z~][A-Za-z0-9~]*)*)
- are strings then VER1 < VER2 implies filevercmp (PREFIX VER1 SUFFIX,
- PREFIX VER2 SUFFIX) < 0.
+ This function is intended to be a replacement for strverscmp. */
+int filevercmp (char const *a, char const *b) _GL_ATTRIBUTE_PURE;
- This function is intended to be a replacement for strverscmp. */
-int filevercmp (const char *s1, const char *s2) _GL_ATTRIBUTE_PURE;
+/* Like filevercmp, except compare the byte arrays A (of length ALEN)
+ and B (of length BLEN) so that A and B can contain '\0', which
+ sorts just before '\1'. But if ALEN is -1 treat A as a string
+ terminated by '\0', and similarly for BLEN. */
+int filenvercmp (char const *a, ptrdiff_t alen, char const *b, ptrdiff_t blen)
+ _GL_ATTRIBUTE_PURE;
#endif /* FILEVERCMP_H */
diff --git a/lib/fingerprint.c b/lib/fingerprint.c
new file mode 100644
index 00000000000..e450d317d72
--- /dev/null
+++ b/lib/fingerprint.c
@@ -0,0 +1,66 @@
+/* Placeholder fingerprint for Emacs
+
+Copyright 2019-2022 Free Software Foundation, Inc.
+
+This file is part of GNU Emacs.
+
+GNU Emacs 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.
+
+GNU Emacs 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 GNU Emacs. If not, see <https://www.gnu.org/licenses/>. */
+
+#include <config.h>
+
+#include "fingerprint.h"
+
+/* This random fingerprint was generated by the shell command:
+
+ shuf -i 0-255 -n 32 -r | awk '{printf " 0x%.02X,\n", $0}'
+
+ In the final Emacs executable, this random fingerprint is replaced
+ by a fingerprint of the temporary Emacs executable that was built
+ along the way. */
+
+volatile unsigned char fingerprint[] =
+ {
+ 0xDE,
+ 0x86,
+ 0xBB,
+ 0x99,
+ 0xFF,
+ 0xF5,
+ 0x46,
+ 0x9A,
+ 0x9E,
+ 0x3F,
+ 0x9F,
+ 0x5D,
+ 0x9A,
+ 0xDF,
+ 0xF0,
+ 0x91,
+ 0xBD,
+ 0xCD,
+ 0xC1,
+ 0xE8,
+ 0x0C,
+ 0x16,
+ 0x1E,
+ 0xAF,
+ 0xB8,
+ 0x6C,
+ 0xE2,
+ 0x2B,
+ 0xB1,
+ 0x24,
+ 0xCE,
+ 0xB0,
+ };
diff --git a/lib/fingerprint.h b/lib/fingerprint.h
new file mode 100644
index 00000000000..d683d0a37a0
--- /dev/null
+++ b/lib/fingerprint.h
@@ -0,0 +1,28 @@
+/* Header file for the Emacs build fingerprint.
+
+Copyright (C) 2016, 2018-2022 Free Software Foundation, Inc.
+
+This file is part of GNU Emacs.
+
+GNU Emacs 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.
+
+GNU Emacs 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 GNU Emacs. If not, see <https://www.gnu.org/licenses/>. */
+
+#ifndef EMACS_FINGERPRINT_H
+#define EMACS_FINGERPRINT_H
+
+/* We generate fingerprint.c and fingerprint.o from all the sources in
+ Emacs. This way, we have a unique value that we can use to pair
+ data files (like a dump file) with a specific build of Emacs. */
+extern volatile unsigned char fingerprint[32];
+
+#endif
diff --git a/lib/flexmember.h b/lib/flexmember.h
index 7e4f95d3c89..1545639f754 100644
--- a/lib/flexmember.h
+++ b/lib/flexmember.h
@@ -1,20 +1,20 @@
/* Sizes of structs with flexible array members.
- Copyright 2016-2017 Free Software Foundation, Inc.
+ Copyright 2016-2022 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
+ modify it under the terms of the GNU Lesser General Public
License as published by the Free Software Foundation; either
- version 3 of the License, or (at your option) any later version.
+ version 2.1 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.
+ Lesser General Public License for more details.
- You should have received a copy of the GNU General Public
+ You should have received a copy of the GNU Lesser General Public
License along with the GNU C Library; if not, see
<https://www.gnu.org/licenses/>.
@@ -33,11 +33,26 @@
# define FLEXALIGNOF(type) _Alignof (type)
#endif
-/* 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.
- This is not simply sizeof (TYPE) + N, since it may require
- alignment on unusually picky C11 platforms, and
- FLEXIBLE_ARRAY_MEMBER may be 1 on pre-C11 platforms.
+/* 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) \
diff --git a/lib/fpending.c b/lib/fpending.c
index 5811a4a7475..6408cff4647 100644
--- a/lib/fpending.c
+++ b/lib/fpending.c
@@ -1,10 +1,10 @@
/* fpending.c -- return the number of pending output bytes on a stream
- Copyright (C) 2000, 2004, 2006-2007, 2009-2017 Free Software Foundation,
+ Copyright (C) 2000, 2004, 2006-2007, 2009-2022 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
+ 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,
@@ -24,6 +24,10 @@
#include "stdio-impl.h"
+/* This file is not used on systems that already have the __fpending function,
+ namely glibc >= 2.2, Solaris >= 7, UnixWare >= 7.1.4.MP4, Cygwin >= 1.7.34,
+ Android API >= 23. */
+
/* Return the number of pending (aka buffered, unflushed)
bytes on the stream, FP, that is open for writing. */
size_t
@@ -32,16 +36,17 @@ __fpending (FILE *fp)
/* Most systems provide FILE as a struct and the necessary bitmask in
<stdio.h>, because they need it for implementing getc() and putc() as
fast macros. */
-#if defined _IO_ftrylockfile || __GNU_LIBRARY__ == 1 /* GNU libc, BeOS, Haiku, Linux libc5 */
+#if defined _IO_EOF_SEEN || defined _IO_ftrylockfile || __GNU_LIBRARY__ == 1
+ /* GNU libc, BeOS, Haiku, Linux libc5 */
return fp->_IO_write_ptr - fp->_IO_write_base;
#elif defined __sferror || defined __DragonFly__ || defined __ANDROID__
- /* FreeBSD, NetBSD, OpenBSD, DragonFly, Mac OS X, Cygwin, Minix 3, Android */
+ /* FreeBSD, NetBSD, OpenBSD, DragonFly, Mac OS X, Cygwin < 1.7.34, Minix 3, Android */
return fp->_p - fp->_bf._base;
#elif defined __EMX__ /* emx+gcc */
return fp->_ptr - fp->_buffer;
#elif defined __minix /* Minix */
return fp_->_ptr - fp_->_buf;
-#elif defined _IOERR /* AIX, HP-UX, IRIX, OSF/1, Solaris, OpenServer, mingw, MSVC, NonStop Kernel, OpenVMS */
+#elif defined _IOERR /* AIX, HP-UX, IRIX, OSF/1, Solaris, OpenServer, UnixWare, mingw, MSVC, NonStop Kernel, OpenVMS */
return (fp_->_ptr ? fp_->_ptr - fp_->_base : 0);
#elif defined __UCLIBC__ /* uClibc */
return (fp->__modeflags & __FLAG_WRITING ? fp->__bufpos - fp->__bufstart : 0);
diff --git a/lib/fpending.h b/lib/fpending.h
index 73c7d795c18..43542c5b8ad 100644
--- a/lib/fpending.h
+++ b/lib/fpending.h
@@ -1,11 +1,11 @@
/* Declare __fpending.
- Copyright (C) 2000, 2003, 2005-2006, 2009-2017 Free Software Foundation,
+ Copyright (C) 2000, 2003, 2005-2006, 2009-2022 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
+ 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,
diff --git a/lib/free.c b/lib/free.c
new file mode 100644
index 00000000000..86ebe6c6300
--- /dev/null
+++ b/lib/free.c
@@ -0,0 +1,53 @@
+/* Make free() preserve errno.
+
+ Copyright (C) 2003, 2006, 2009-2022 Free Software Foundation, Inc.
+
+ This file is free software: you can redistribute it and/or modify
+ it under the terms of the GNU Lesser General Public License as
+ published by the Free Software Foundation; either version 2.1 of the
+ License, or (at your option) any later version.
+
+ This file 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 Lesser General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public License
+ along with this program. If not, see <https://www.gnu.org/licenses/>. */
+
+/* written by Paul Eggert */
+
+#include <config.h>
+
+/* Specification. */
+#include <stdlib.h>
+
+/* A function definition is only needed if HAVE_FREE_POSIX is not defined. */
+#if !HAVE_FREE_POSIX
+
+# include <errno.h>
+
+void
+rpl_free (void *p)
+# undef free
+{
+# if defined __GNUC__ && !defined __clang__
+ /* An invalid GCC optimization
+ <https://gcc.gnu.org/bugzilla/show_bug.cgi?id=98396>
+ would optimize away the assignments in the code below, when link-time
+ optimization (LTO) is enabled. Make the code more complicated, so that
+ GCC does not grok how to optimize it. */
+ int err[2];
+ err[0] = errno;
+ err[1] = errno;
+ errno = 0;
+ free (p);
+ errno = err[errno == 0];
+# else
+ int err = errno;
+ free (p);
+ errno = err;
+# endif
+}
+
+#endif
diff --git a/lib/fstatat.c b/lib/fstatat.c
index 67e48d95d71..6e8344964bc 100644
--- a/lib/fstatat.c
+++ b/lib/fstatat.c
@@ -1,10 +1,10 @@
/* Work around an fstatat bug on Solaris 9.
- Copyright (C) 2006, 2009-2017 Free Software Foundation, Inc.
+ Copyright (C) 2006, 2009-2022 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
+ 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,
@@ -28,7 +28,7 @@
#include <sys/stat.h>
#undef __need_system_sys_stat_h
-#if HAVE_FSTATAT
+#if HAVE_FSTATAT && HAVE_WORKING_FSTATAT_ZERO_FLAG
static int
orig_fstatat (int fd, char const *filename, struct stat *buf, int flags)
{
@@ -36,13 +36,20 @@ orig_fstatat (int fd, char const *filename, struct stat *buf, int flags)
}
#endif
+#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"
#include <errno.h>
#include <fcntl.h>
+#include <stdlib.h>
#include <string.h>
#if HAVE_FSTATAT && HAVE_WORKING_FSTATAT_ZERO_FLAG
@@ -51,6 +58,12 @@ orig_fstatat (int fd, char const *filename, struct stat *buf, int flags)
# define LSTAT_FOLLOWS_SLASHED_SYMLINK 0
# endif
+static int
+normal_fstatat (int fd, char const *file, struct stat *st, int flag)
+{
+ return stat_time_normalize (orig_fstatat (fd, file, st, flag), st);
+}
+
/* fstatat should always follow symbolic links that end in /, but on
Solaris 9 it doesn't if AT_SYMLINK_NOFOLLOW is specified.
Likewise, trailing slash on a non-directory should be an error.
@@ -63,7 +76,7 @@ orig_fstatat (int fd, char const *filename, struct stat *buf, int flags)
int
rpl_fstatat (int fd, char const *file, struct stat *st, int flag)
{
- int result = orig_fstatat (fd, file, st, flag);
+ int result = normal_fstatat (fd, file, st, flag);
size_t len;
if (LSTAT_FOLLOWS_SLASHED_SYMLINK || result != 0)
@@ -79,7 +92,7 @@ rpl_fstatat (int fd, char const *file, struct stat *st, int flag)
errno = ENOTDIR;
return -1;
}
- result = orig_fstatat (fd, file, st, flag & ~AT_SYMLINK_NOFOLLOW);
+ result = normal_fstatat (fd, file, st, flag & ~AT_SYMLINK_NOFOLLOW);
}
/* Fix stat behavior. */
if (result == 0 && !S_ISDIR (st->st_mode) && file[len - 1] == '/')
diff --git a/lib/fsusage.c b/lib/fsusage.c
index b670c0c43a1..18f790f6e7b 100644
--- a/lib/fsusage.c
+++ b/lib/fsusage.c
@@ -1,19 +1,19 @@
/* fsusage.c -- return space usage of mounted file systems
- Copyright (C) 1991-1992, 1996, 1998-1999, 2002-2006, 2009-2017 Free Software
+ Copyright (C) 1991-1992, 1996, 1998-1999, 2002-2006, 2009-2022 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 file is free software: you can redistribute it and/or modify
+ it under the terms of the GNU Lesser 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,
+ This file 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.
+ GNU Lesser General Public License for more details.
- You should have received a copy of the GNU General Public License
+ You should have received a copy of the GNU Lesser General Public License
along with this program. If not, see <https://www.gnu.org/licenses/>. */
#include <config.h>
@@ -46,9 +46,6 @@
# if HAVE_SYS_STATFS_H
# include <sys/statfs.h>
# endif
-# if HAVE_DUSTAT_H /* AIX PS/2 */
-# include <sys/dustat.h>
-# endif
#endif
/* Many space usage primitives use all 1 bits to denote a value that is
@@ -151,21 +148,6 @@ get_fs_usage (char const *file, char const *disk, struct fs_usage *fsp)
? PROPAGATE_ALL_ONES (fsd.f_frsize)
: PROPAGATE_ALL_ONES (fsd.f_bsize));
-#elif defined STAT_STATFS2_FS_DATA /* Ultrix */
-
- struct fs_data fsd;
-
- if (statfs (file, &fsd) != 1)
- return -1;
-
- fsp->fsu_blocksize = 1024;
- fsp->fsu_blocks = PROPAGATE_ALL_ONES (fsd.fd_req.btot);
- fsp->fsu_bfree = PROPAGATE_ALL_ONES (fsd.fd_req.bfree);
- fsp->fsu_bavail = PROPAGATE_TOP_BIT (fsd.fd_req.bfreen);
- fsp->fsu_bavail_top_bit_set = EXTRACT_TOP_BIT (fsd.fd_req.bfreen) != 0;
- fsp->fsu_files = PROPAGATE_ALL_ONES (fsd.fd_req.gtot);
- fsp->fsu_ffree = PROPAGATE_ALL_ONES (fsd.fd_req.gfree);
-
#elif defined STAT_STATFS3_OSF1 /* OSF/1 */
struct statfs fsd;
@@ -219,12 +201,7 @@ get_fs_usage (char const *file, char const *disk, struct fs_usage *fsp)
fsp->fsu_blocksize = PROPAGATE_ALL_ONES (fsd.f_fsize);
-#elif defined STAT_STATFS4 /* SVR3, Dynix, old Irix, old AIX, \
- Dolphin */
-
-# if !_AIX && !defined _SEQUENT_ && !defined DOLPHIN
-# define f_bavail f_bfree
-# endif
+#elif defined STAT_STATFS4 /* SVR3, old Irix */
struct statfs fsd;
@@ -234,11 +211,7 @@ get_fs_usage (char const *file, char const *disk, struct fs_usage *fsp)
/* Empirically, the block counts on most SVR3 and SVR3-derived
systems seem to always be in terms of 512-byte blocks,
no matter what value f_bsize has. */
-# if _AIX || defined _CRAY
- fsp->fsu_blocksize = PROPAGATE_ALL_ONES (fsd.f_bsize);
-# else
fsp->fsu_blocksize = 512;
-# endif
#endif
@@ -258,30 +231,3 @@ get_fs_usage (char const *file, char const *disk, struct fs_usage *fsp)
(void) disk; /* avoid argument-unused warning */
return 0;
}
-
-#if defined _AIX && defined _I386
-/* AIX PS/2 does not supply statfs. */
-
-int
-statfs (char *file, struct statfs *fsb)
-{
- struct stat stats;
- struct dustat fsd;
-
- if (stat (file, &stats) != 0)
- return -1;
- if (dustat (stats.st_dev, 0, &fsd, sizeof (fsd)))
- return -1;
- fsb->f_type = 0;
- fsb->f_bsize = fsd.du_bsize;
- fsb->f_blocks = fsd.du_fsize - fsd.du_isize;
- fsb->f_bfree = fsd.du_tfree;
- fsb->f_bavail = fsd.du_tfree;
- fsb->f_files = (fsd.du_isize - 2) * fsd.du_inopb;
- fsb->f_ffree = fsd.du_tinode;
- fsb->f_fsid.val[0] = fsd.du_site;
- fsb->f_fsid.val[1] = fsd.du_pckno;
- return 0;
-}
-
-#endif /* _AIX && _I386 */
diff --git a/lib/fsusage.h b/lib/fsusage.h
index f78edc6a0cb..0443d19f922 100644
--- a/lib/fsusage.h
+++ b/lib/fsusage.h
@@ -1,19 +1,19 @@
/* fsusage.h -- declarations for file system space usage info
- Copyright (C) 1991-1992, 1997, 2003-2006, 2009-2017 Free Software
+ Copyright (C) 1991-1992, 1997, 2003-2006, 2009-2022 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 file is free software: you can redistribute it and/or modify
+ it under the terms of the GNU Lesser 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,
+ This file 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.
+ GNU Lesser General Public License for more details.
- You should have received a copy of the GNU General Public License
+ You should have received a copy of the GNU Lesser General Public License
along with this program. If not, see <https://www.gnu.org/licenses/>. */
/* Space usage statistics for a file system. Blocks are 512-byte. */
diff --git a/lib/fsync.c b/lib/fsync.c
index c25f1db6575..9b561ab96ee 100644
--- a/lib/fsync.c
+++ b/lib/fsync.c
@@ -7,25 +7,25 @@
Written by Richard W.M. Jones <rjones.at.redhat.com>
- Copyright (C) 2008-2017 Free Software Foundation, Inc.
+ Copyright (C) 2008-2022 Free Software Foundation, Inc.
- This library is free software; you can redistribute it and/or
- modify it under the terms of the GNU General Public
- License as published by the Free Software Foundation; either
- version 3 of the License, or (at your option) any later version.
+ This file is free software: you can redistribute it and/or modify
+ it under the terms of the GNU Lesser General Public License as
+ published by the Free Software Foundation; either version 2.1 of the
+ License, or (at your option) any later version.
- This library is distributed in the hope that it will be useful,
+ This file is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- General Public License for more details.
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU Lesser General Public License for more details.
- You should have received a copy of the GNU General Public License
+ You should have received a copy of the GNU Lesser General Public License
along with this program. If not, see <https://www.gnu.org/licenses/>. */
#include <config.h>
#include <unistd.h>
-#if (defined _WIN32 || defined __WIN32__) && ! defined __CYGWIN__
+#if defined _WIN32 && ! defined __CYGWIN__
/* FlushFileBuffers */
# define WIN32_LEAN_AND_MEAN
diff --git a/lib/ftoastr.c b/lib/ftoastr.c
index bcc79f03673..91057529221 100644
--- a/lib/ftoastr.c
+++ b/lib/ftoastr.c
@@ -1,10 +1,10 @@
/* floating point to accurate string
- Copyright (C) 2010-2017 Free Software Foundation, Inc.
+ Copyright (C) 2010-2022 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
+ 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,
@@ -33,22 +33,28 @@
#include <stdio.h>
#include <stdlib.h>
+#ifdef C_LOCALE
+# include "c-snprintf.h"
+# include "c-strtod.h"
+# define PREFIX(name) c_ ## name
+#else
+# define PREFIX(name) name
+#endif
+
#if LENGTH == 3
# define FLOAT long double
# define FLOAT_DIG LDBL_DIG
# define FLOAT_MIN LDBL_MIN
# define FLOAT_PREC_BOUND _GL_LDBL_PREC_BOUND
-# define FTOASTR ldtoastr
+# define FTOASTR PREFIX (ldtoastr)
# define PROMOTED_FLOAT long double
-# if HAVE_C99_STRTOLD
-# define STRTOF strtold
-# endif
+# define STRTOF PREFIX (strtold)
#elif LENGTH == 2
# define FLOAT double
# define FLOAT_DIG DBL_DIG
# define FLOAT_MIN DBL_MIN
# define FLOAT_PREC_BOUND _GL_DBL_PREC_BOUND
-# define FTOASTR dtoastr
+# define FTOASTR PREFIX (dtoastr)
# define PROMOTED_FLOAT double
#else
# define LENGTH 1
@@ -56,24 +62,27 @@
# define FLOAT_DIG FLT_DIG
# define FLOAT_MIN FLT_MIN
# define FLOAT_PREC_BOUND _GL_FLT_PREC_BOUND
-# define FTOASTR ftoastr
+# define FTOASTR PREFIX (ftoastr)
# define PROMOTED_FLOAT double
# if HAVE_STRTOF
# define STRTOF strtof
# endif
#endif
-/* On pre-C99 hosts, approximate strtof and strtold with strtod. This
+/* On pre-C99 hosts, approximate strtof with strtod. This
may generate one or two extra digits, but that's better than not
working at all. */
#ifndef STRTOF
-# define STRTOF strtod
+# define STRTOF PREFIX (strtod)
#endif
/* On hosts where it's not known that snprintf works, use sprintf to
implement the subset needed here. Typically BUFSIZE is big enough
and there's little or no performance hit. */
-#if ! GNULIB_SNPRINTF
+#ifdef C_LOCALE
+# undef snprintf
+# define snprintf c_snprintf
+#elif ! GNULIB_SNPRINTF
# undef snprintf
# define snprintf ftoastr_snprintf
static int
@@ -107,7 +116,7 @@ FTOASTR (char *buf, size_t bufsize, int flags, int width, FLOAT x)
Andrysco M, Jhala R, Lerner S. Printing floating-point numbers:
a faster, always correct method. ACM SIGPLAN notices - POPL '16.
- 2016;51(1):555-67 <http://dx.doi.org/10.1145/2914770.2837654>; draft at
+ 2016;51(1):555-67 <https://doi.org/10.1145/2914770.2837654>; draft at
<https://cseweb.ucsd.edu/~lerner/papers/fp-printing-popl16.pdf>. */
PROMOTED_FLOAT promoted_x = x;
diff --git a/lib/ftoastr.h b/lib/ftoastr.h
index f73712c9415..bac32a387e2 100644
--- a/lib/ftoastr.h
+++ b/lib/ftoastr.h
@@ -1,10 +1,10 @@
/* floating point to accurate string
- Copyright (C) 2010-2017 Free Software Foundation, Inc.
+ Copyright (C) 2010-2022 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
+ 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,
@@ -18,6 +18,7 @@
/* Written by Paul Eggert. */
#ifndef _GL_FTOASTR_H
+#define _GL_FTOASTR_H
#include "intprops.h"
#include <float.h>
@@ -48,6 +49,12 @@ int ftoastr (char *buf, size_t bufsize, int flags, int width, float x);
int dtoastr (char *buf, size_t bufsize, int flags, int width, double x);
int ldtoastr (char *buf, size_t bufsize, int flags, int width, long double x);
+/* The last two functions except that the formatting takes place in
+ the C locale. */
+int c_dtoastr (char *buf, size_t bufsize, int flags, int width, double x);
+int c_ldtoastr (char *buf, size_t bufsize, int flags, int width, long double x);
+
+
/* Flag values for ftoastr etc. These can be ORed together. */
enum
{
diff --git a/lib/futimens.c b/lib/futimens.c
new file mode 100644
index 00000000000..bc3e41a9439
--- /dev/null
+++ b/lib/futimens.c
@@ -0,0 +1,37 @@
+/* Set the access and modification time of an open fd.
+ Copyright (C) 2009-2022 Free Software Foundation, Inc.
+
+ This file is free software: you can redistribute it and/or modify
+ it under the terms of the GNU Lesser General Public License as
+ published by the Free Software Foundation, either version 3 of the
+ License, or (at your option) any later version.
+
+ This file 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 Lesser General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public License
+ along with this program. If not, see <https://www.gnu.org/licenses/>. */
+
+/* written by Eric Blake */
+
+#include <config.h>
+
+#include <sys/stat.h>
+
+#include "utimens.h"
+
+/* Set the access and modification timestamps of FD to be
+ TIMESPEC[0] and TIMESPEC[1], respectively.
+ Fail with ENOSYS on systems without futimes (or equivalent).
+ If TIMESPEC is null, set the timestamps to the current time.
+ Return 0 on success, -1 (setting errno) on failure. */
+int
+futimens (int fd, struct timespec const times[2])
+{
+ /* fdutimens also works around bugs in native futimens, when running
+ with glibc compiled against newer headers but on a Linux kernel
+ older than 2.6.32. */
+ return fdutimens (fd, NULL, times);
+}
diff --git a/lib/get-permissions.c b/lib/get-permissions.c
index c54d71c1c56..ff79adae72f 100644
--- a/lib/get-permissions.c
+++ b/lib/get-permissions.c
@@ -1,10 +1,10 @@
/* Get permissions of a file. -*- coding: utf-8 -*-
- Copyright (C) 2002-2003, 2005-2017 Free Software Foundation, Inc.
+ Copyright (C) 2002-2003, 2005-2022 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
+ 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,
@@ -31,16 +31,16 @@
int
get_permissions (const char *name, int desc, mode_t mode,
- struct permission_context *ctx)
+ struct permission_context *ctx)
{
memset (ctx, 0, sizeof *ctx);
ctx->mode = mode;
#if USE_ACL && HAVE_ACL_GET_FILE
/* POSIX 1003.1e (draft 17 -- abandoned) specific version. */
- /* Linux, FreeBSD, Mac OS X, IRIX, Tru64 */
+ /* Linux, FreeBSD, Mac OS X, IRIX, Tru64, Cygwin >= 2.5 */
# if !HAVE_ACL_TYPE_EXTENDED
- /* Linux, FreeBSD, IRIX, Tru64 */
+ /* Linux, FreeBSD, IRIX, Tru64, Cygwin >= 2.5 */
if (HAVE_ACL_GET_FD && desc != -1)
ctx->acl = acl_get_fd (desc);
@@ -57,16 +57,16 @@ get_permissions (const char *name, int desc, mode_t mode,
{
ctx->default_acl = acl_get_file (name, ACL_TYPE_DEFAULT);
if (ctx->default_acl == NULL)
- return -1;
+ return -1;
}
-# if HAVE_ACL_TYPE_NFS4 /* FreeBSD */
+# if HAVE_ACL_TYPE_NFS4 /* FreeBSD */
/* TODO (see set_permissions). */
-# endif
+# endif
-# else /* HAVE_ACL_TYPE_EXTENDED */
+# else /* HAVE_ACL_TYPE_EXTENDED */
/* Mac OS X */
/* On Mac OS X, acl_get_file (name, ACL_TYPE_ACCESS)
@@ -108,23 +108,23 @@ 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 (;;)
{
int ret;
if (desc != -1)
- ret = facl (desc, ACE_GETACLCNT, 0, NULL);
+ ret = facl (desc, ACE_GETACLCNT, 0, NULL);
else
- ret = acl (name, ACE_GETACLCNT, 0, NULL);
+ ret = acl (name, ACE_GETACLCNT, 0, NULL);
if (ret < 0)
- {
- if (errno == ENOSYS || errno == EINVAL)
- ret = 0;
- else
- return -1;
- }
+ {
+ if (errno == ENOSYS || errno == EINVAL)
+ ret = 0;
+ else
+ return -1;
+ }
ctx->ace_count = ret;
if (ctx->ace_count == 0)
@@ -138,15 +138,15 @@ get_permissions (const char *name, int desc, mode_t mode,
}
if (desc != -1)
- ret = facl (desc, ACE_GETACL, ctx->ace_count, ctx->ace_entries);
+ ret = facl (desc, ACE_GETACL, ctx->ace_count, ctx->ace_entries);
else
- ret = acl (name, ACE_GETACL, ctx->ace_count, ctx->ace_entries);
+ ret = acl (name, ACE_GETACL, ctx->ace_count, ctx->ace_entries);
if (ret < 0)
{
if (errno == ENOSYS || errno == EINVAL)
{
- free (ctx->ace_entries);
- ctx->ace_entries = NULL;
+ free (ctx->ace_entries);
+ ctx->ace_entries = NULL;
ctx->ace_count = 0;
break;
}
@@ -154,10 +154,10 @@ get_permissions (const char *name, int desc, mode_t mode,
return -1;
}
if (ret <= ctx->ace_count)
- {
- ctx->ace_count = ret;
- break;
- }
+ {
+ ctx->ace_count = ret;
+ break;
+ }
/* Huh? The number of ACL entries has increased since the last call.
Repeat. */
free (ctx->ace_entries);
@@ -170,20 +170,20 @@ get_permissions (const char *name, int desc, mode_t mode,
int ret;
if (desc != -1)
- ret = facl (desc, GETACLCNT, 0, NULL);
+ ret = facl (desc, GETACLCNT, 0, NULL);
else
- ret = acl (name, GETACLCNT, 0, NULL);
+ ret = acl (name, GETACLCNT, 0, NULL);
if (ret < 0)
- {
- if (errno == ENOSYS || errno == ENOTSUP || errno == EOPNOTSUPP)
- ret = 0;
- else
- return -1;
- }
+ {
+ if (errno == ENOSYS || errno == ENOTSUP || errno == EOPNOTSUPP)
+ ret = 0;
+ else
+ return -1;
+ }
ctx->count = ret;
if (ctx->count == 0)
- break;
+ break;
ctx->entries = (aclent_t *) malloc (ctx->count * sizeof (aclent_t));
if (ctx->entries == NULL)
@@ -193,26 +193,26 @@ get_permissions (const char *name, int desc, mode_t mode,
}
if (desc != -1)
- ret = facl (desc, GETACL, ctx->count, ctx->entries);
+ ret = facl (desc, GETACL, ctx->count, ctx->entries);
else
- ret = acl (name, GETACL, ctx->count, ctx->entries);
+ ret = acl (name, GETACL, ctx->count, ctx->entries);
if (ret < 0)
- {
- if (errno == ENOSYS || errno == ENOTSUP || errno == EOPNOTSUPP)
- {
- free (ctx->entries);
- ctx->entries = NULL;
- ctx->count = 0;
- break;
- }
- else
- return -1;
- }
+ {
+ if (errno == ENOSYS || errno == ENOTSUP || errno == EOPNOTSUPP)
+ {
+ free (ctx->entries);
+ ctx->entries = NULL;
+ ctx->count = 0;
+ break;
+ }
+ else
+ return -1;
+ }
if (ret <= ctx->count)
- {
- ctx->count = ret;
- break;
- }
+ {
+ ctx->count = ret;
+ break;
+ }
/* Huh? The number of ACL entries has increased since the last call.
Repeat. */
free (ctx->entries);
diff --git a/lib/getdtablesize.c b/lib/getdtablesize.c
index d0a5ecaf5d6..793e0f8894e 100644
--- a/lib/getdtablesize.c
+++ b/lib/getdtablesize.c
@@ -1,18 +1,18 @@
/* getdtablesize() function: Return maximum possible file descriptor value + 1.
- Copyright (C) 2008-2017 Free Software Foundation, Inc.
+ Copyright (C) 2008-2022 Free Software Foundation, Inc.
Written by Bruno Haible <bruno@clisp.org>, 2008.
- 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 file is free software: you can redistribute it and/or modify
+ it under the terms of the GNU Lesser General Public License as
+ published by the Free Software Foundation; either version 2.1 of the
+ License, or (at your option) any later version.
- This program is distributed in the hope that it will be useful,
+ This file 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.
+ GNU Lesser General Public License for more details.
- You should have received a copy of the GNU General Public License
+ You should have received a copy of the GNU Lesser General Public License
along with this program. If not, see <https://www.gnu.org/licenses/>. */
#include <config.h>
@@ -20,7 +20,7 @@
/* Specification. */
#include <unistd.h>
-#if (defined _WIN32 || defined __WIN32__) && ! defined __CYGWIN__
+#if defined _WIN32 && ! defined __CYGWIN__
# include <stdio.h>
diff --git a/lib/getgroups.c b/lib/getgroups.c
index 52473a5a230..f7abd726671 100644
--- a/lib/getgroups.c
+++ b/lib/getgroups.c
@@ -1,18 +1,18 @@
/* provide consistent interface to getgroups for systems that don't allow N==0
- Copyright (C) 1996, 1999, 2003, 2006-2017 Free Software Foundation, Inc.
+ Copyright (C) 1996, 1999, 2003, 2006-2022 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 file is free software: you can redistribute it and/or modify
+ it under the terms of the GNU Lesser General Public License as
+ published by the Free Software Foundation; either version 2.1 of the
+ License, or (at your option) any later version.
- This program is distributed in the hope that it will be useful,
+ This file 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.
+ GNU Lesser General Public License for more details.
- You should have received a copy of the GNU General Public License
+ You should have received a copy of the GNU Lesser General Public License
along with this program. If not, see <https://www.gnu.org/licenses/>. */
/* written by Jim Meyering */
@@ -30,7 +30,7 @@
/* Provide a stub that fails with ENOSYS, since there is no group
information available on mingw. */
int
-getgroups (int n _GL_UNUSED, GETGROUPS_T *groups _GL_UNUSED)
+getgroups (_GL_UNUSED int n, _GL_UNUSED GETGROUPS_T *groups)
{
errno = ENOSYS;
return -1;
@@ -58,8 +58,8 @@ int posix_getgroups (int, gid_t []) __asm ("_getgroups");
# define getgroups posix_getgroups
# endif
-/* On at least Ultrix 4.3 and NextStep 3.2, getgroups (0, NULL) always
- fails. On other systems, it returns the number of supplemental
+/* On at least NeXTstep 3.2, getgroups (0, NULL) always fails.
+ On other systems, it returns the number of supplemental
groups for the process. This function handles that special case
and lets the system-provided function handle all others. However,
it can fail with ENOMEM if memory is tight. It is unspecified
@@ -70,7 +70,6 @@ rpl_getgroups (int n, gid_t *group)
{
int n_groups;
GETGROUPS_T *gbuf;
- int saved_errno;
if (n < 0)
{
@@ -99,9 +98,7 @@ rpl_getgroups (int n, gid_t *group)
while (n--)
group[n] = gbuf[n];
}
- saved_errno = errno;
free (gbuf);
- errno = saved_errno;
return result;
}
@@ -121,10 +118,7 @@ rpl_getgroups (int n, gid_t *group)
n *= 2;
}
- saved_errno = errno;
free (gbuf);
- errno = saved_errno;
-
return n_groups;
}
diff --git a/lib/getloadavg.c b/lib/getloadavg.c
index 5f2dfabb6fd..37e82808671 100644
--- a/lib/getloadavg.c
+++ b/lib/getloadavg.c
@@ -1,6 +1,6 @@
/* Get the system load averages.
- Copyright (C) 1985-1989, 1991-1995, 1997, 1999-2000, 2003-2017 Free Software
+ Copyright (C) 1985-1989, 1991-1995, 1997, 1999-2000, 2003-2022 Free Software
Foundation, Inc.
NOTE: The canonical source of this file is maintained with gnulib.
@@ -8,7 +8,7 @@
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
+ 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,
@@ -47,29 +47,25 @@
N_NAME_POINTER The nlist n_name element is a pointer,
not an array.
HAVE_STRUCT_NLIST_N_UN_N_NAME 'n_un.n_name' is member of 'struct nlist'.
- LINUX_LDAV_FILE [__linux__, __CYGWIN__]: File containing
- load averages.
+ LINUX_LDAV_FILE [__linux__, __ANDROID__, __CYGWIN__]: File
+ containing load averages.
Specific system predefines this file uses, aside from setting
default values if not emacs:
apollo
BSD Real BSD, not just BSD-like.
- convex
DGUX
eunice UNIX emulator under VMS.
hpux
__MSDOS__ No-op for MSDOS.
NeXT
sgi
- sequent Sequent Dynix 3.x.x (BSD)
- _SEQUENT_ Sequent DYNIX/ptx 1.x.x (SYSV)
- sony_news NEWS-OS (works at least for 4.1C)
UMAX
UMAX4_3
VMS
- WINDOWS32 No-op for Windows95/NT.
- __linux__ Linux: assumes /proc file system mounted.
+ _WIN32 Native Windows (possibly also defined on Cygwin)
+ __linux__, __ANDROID__ Linux: assumes /proc file system mounted.
Support from Michael K. Johnson.
__CYGWIN__ Cygwin emulates linux /proc/loadavg.
__NetBSD__ NetBSD: assumes /kern file system mounted.
@@ -97,9 +93,8 @@
# include "intprops.h"
-# if !defined (BSD) && defined (ultrix)
-/* Ultrix behaves like BSD on Vaxen. */
-# define BSD
+# if defined _WIN32 && ! defined __CYGWIN__ && ! defined WINDOWS32
+# define WINDOWS32
# endif
# ifdef NeXT
@@ -141,10 +136,6 @@
# define MORE_BSD
# endif
-# if defined (ultrix) && defined (mips)
-# define decstation
-# endif
-
# if defined (__SVR4) && !defined (SVR4)
# define SVR4
# endif
@@ -168,13 +159,6 @@
# include <sys/table.h>
# endif
-/* UTek's /bin/cc on the 4300 has no architecture specific cpp define by
- default, but _MACH_IND_SYS_TYPES is defined in <sys/types.h>. Combine
- that with a couple of other things and we'll have a unique match. */
-# if !defined (tek4300) && defined (unix) && defined (m68k) && defined (mc68000) && defined (mc68020) && defined (_MACH_IND_SYS_TYPES)
-# define tek4300 /* Define by emacs, but not by other users. */
-# endif
-
/* VAX C can't handle multi-line #ifs, or lines longer than 256 chars. */
# ifndef LOAD_AVE_TYPE
@@ -187,14 +171,6 @@
# define LOAD_AVE_TYPE long
# endif
-# ifdef decstation
-# define LOAD_AVE_TYPE long
-# endif
-
-# ifdef _SEQUENT_
-# define LOAD_AVE_TYPE long
-# endif
-
# ifdef sgi
# define LOAD_AVE_TYPE long
# endif
@@ -203,41 +179,14 @@
# define LOAD_AVE_TYPE long
# endif
-# ifdef sony_news
-# define LOAD_AVE_TYPE long
-# endif
-
-# ifdef sequent
-# define LOAD_AVE_TYPE long
-# endif
-
# ifdef OSF_ALPHA
# define LOAD_AVE_TYPE long
# endif
-# if defined (ardent) && defined (titan)
-# define LOAD_AVE_TYPE long
-# endif
-
-# ifdef tek4300
-# define LOAD_AVE_TYPE long
-# endif
-
-# if defined (alliant) && defined (i860) /* Alliant FX/2800 */
-# define LOAD_AVE_TYPE long
-# endif
-
# if defined _AIX && ! defined HAVE_LIBPERFSTAT
# define LOAD_AVE_TYPE long
# endif
-# ifdef convex
-# define LOAD_AVE_TYPE double
-# ifndef LDAV_CVT
-# define LDAV_CVT(n) (n)
-# endif
-# endif
-
# endif /* No LOAD_AVE_TYPE. */
# ifdef OSF_ALPHA
@@ -247,13 +196,6 @@
# define FSCALE 1024.0
# endif
-# if defined (alliant) && defined (i860) /* Alliant FX/2800 */
-/* <sys/param.h> defines an incorrect value for FSCALE on an
- Alliant FX/2800 Concentrix 2.2, according to ghazi@noc.rutgers.edu. */
-# undef FSCALE
-# define FSCALE 100.0
-# endif
-
# ifndef FSCALE
@@ -263,25 +205,17 @@
# define FSCALE 2048.0
# endif
-# if defined (MIPS) || defined (SVR4) || defined (decstation)
+# if defined (MIPS) || defined (SVR4)
# define FSCALE 256
# endif
-# if defined (sgi) || defined (sequent)
+# if defined (sgi)
/* Sometimes both MIPS and sgi are defined, so FSCALE was just defined
above under #ifdef MIPS. But we want the sgi value. */
# undef FSCALE
# define FSCALE 1000.0
# endif
-# if defined (ardent) && defined (titan)
-# define FSCALE 65536.0
-# endif
-
-# ifdef tek4300
-# define FSCALE 100.0
-# endif
-
# if defined _AIX && !defined HAVE_LIBPERFSTAT
# define FSCALE 65536.0
# endif
@@ -303,28 +237,22 @@
# endif
-# if !defined (KERNEL_FILE) && defined (sequent)
-# define KERNEL_FILE "/dynix"
-# endif
-
# if !defined (KERNEL_FILE) && defined (hpux)
# define KERNEL_FILE "/hp-ux"
# endif
-# if !defined (KERNEL_FILE) && (defined (_SEQUENT_) || defined (MIPS) || defined (SVR4) || defined (ISC) || defined (sgi) || (defined (ardent) && defined (titan)))
+# if !defined (KERNEL_FILE) && (defined (MIPS) || defined (SVR4) || defined (ISC) || defined (sgi))
# define KERNEL_FILE "/unix"
# endif
-# if !defined (LDAV_SYMBOL) && defined (alliant)
-# define LDAV_SYMBOL "_Loadavg"
-# endif
-
-# if !defined (LDAV_SYMBOL) && ((defined (hpux) && !defined (hp9000s300)) || defined (_SEQUENT_) || defined (SVR4) || defined (ISC) || defined (sgi) || (defined (ardent) && defined (titan)) || (defined (_AIX) && !defined(HAVE_LIBPERFSTAT)))
+# if !defined (LDAV_SYMBOL) && (defined (hpux) || defined (SVR4) || defined (ISC) || defined (sgi) || (defined (_AIX) && !defined(HAVE_LIBPERFSTAT)))
# define LDAV_SYMBOL "avenrun"
# endif
-# include <unistd.h>
+# ifdef HAVE_UNISTD_H
+# include <unistd.h>
+# endif
/* LOAD_AVE_TYPE should only get defined if we're going to use the
nlist method. */
@@ -335,7 +263,7 @@
# ifdef LOAD_AVE_TYPE
# ifndef __VMS
-# ifndef __linux__
+# if !(defined __linux__ || defined __ANDROID__)
# ifndef NLIST_STRUCT
# include <a.out.h>
# else /* NLIST_STRUCT */
@@ -358,7 +286,7 @@
# ifndef LDAV_SYMBOL
# define LDAV_SYMBOL "_avenrun"
# endif /* LDAV_SYMBOL */
-# endif /* __linux__ */
+# endif /* __linux__ || __ANDROID__ */
# else /* __VMS */
@@ -431,7 +359,8 @@
# include <sys/dg_sys_info.h>
# endif
-# if (defined __linux__ || defined __CYGWIN__ || defined SUNOS_5 \
+# if (defined __linux__ || defined __ANDROID__ \
+ || defined __CYGWIN__ || defined SUNOS_5 \
|| (defined LOAD_AVE_TYPE && ! defined __VMS))
# include <fcntl.h>
# endif
@@ -460,7 +389,7 @@ static bool getloadavg_initialized;
/* Offset in kmem to seek to read load average, or 0 means invalid. */
static long offset;
-# if ! defined __VMS && ! defined sgi && ! defined __linux__
+# if ! defined __VMS && ! defined sgi && ! (defined __linux__ || defined __ANDROID__)
static struct nlist name_list[2];
# endif
@@ -495,17 +424,17 @@ getloadavg (double loadavg[], int nelem)
int saved_errno;
kc = kstat_open ();
- if (kc == 0)
+ if (kc == NULL)
return -1;
ksp = kstat_lookup (kc, "unix", 0, "system_misc");
- if (ksp == 0)
+ if (ksp == NULL)
return -1;
if (kstat_read (kc, ksp, 0) == -1)
return -1;
kn = kstat_data_lookup (ksp, "avenrun_1min");
- if (kn == 0)
+ if (kn == NULL)
{
/* Return -1 if no load average information is available. */
nelem = 0;
@@ -518,14 +447,14 @@ getloadavg (double loadavg[], int nelem)
if (nelem >= 2)
{
kn = kstat_data_lookup (ksp, "avenrun_5min");
- if (kn != 0)
+ if (kn != NULL)
{
loadavg[elem++] = (double) kn->value.ul / FSCALE;
if (nelem >= 3)
{
kn = kstat_data_lookup (ksp, "avenrun_15min");
- if (kn != 0)
+ if (kn != NULL)
loadavg[elem++] = (double) kn->value.ul / FSCALE;
}
}
@@ -570,8 +499,8 @@ getloadavg (double loadavg[], int nelem)
}
# endif
-# if !defined (LDAV_DONE) && (defined (__linux__) || defined (__CYGWIN__))
- /* Linux without glibc, Cygwin */
+# if !defined (LDAV_DONE) && (defined __linux__ || defined __ANDROID__ || defined __CYGWIN__)
+ /* Linux without glibc, Android, Cygwin */
# define LDAV_DONE
# undef LOAD_AVE_TYPE
@@ -583,7 +512,7 @@ getloadavg (double loadavg[], int nelem)
char const *ptr = ldavgbuf;
int fd, count, saved_errno;
- fd = open (LINUX_LDAV_FILE, O_RDONLY);
+ fd = open (LINUX_LDAV_FILE, O_RDONLY | O_CLOEXEC);
if (fd == -1)
return -1;
count = read (fd, ldavgbuf, sizeof ldavgbuf - 1);
@@ -621,12 +550,12 @@ getloadavg (double loadavg[], int nelem)
for (ptr++; '0' <= *ptr && *ptr <= '9'; ptr++)
numerator = 10 * numerator + (*ptr - '0'), denominator *= 10;
- loadavg[elem++] = numerator / denominator;
+ loadavg[elem] = numerator / denominator;
}
return elem;
-# endif /* __linux__ || __CYGWIN__ */
+# endif /* __linux__ || __ANDROID__ || __CYGWIN__ */
# if !defined (LDAV_DONE) && defined (__NetBSD__) /* NetBSD < 0.9 */
# define LDAV_DONE
@@ -638,15 +567,22 @@ getloadavg (double loadavg[], int nelem)
unsigned long int load_ave[3], scale;
int count;
- FILE *fp;
-
- fp = fopen (NETBSD_LDAV_FILE, "r");
- if (fp == NULL)
- return -1;
- count = fscanf (fp, "%lu %lu %lu %lu\n",
+ char readbuf[4 * INT_BUFSIZE_BOUND (unsigned long int) + 1];
+ int fd = open (NETBSD_LDAV_FILE, O_RDONLY | O_CLOEXEC);
+ if (fd < 0)
+ return fd;
+ int nread = read (fd, readbuf, sizeof readbuf - 1);
+ int err = errno;
+ close (fd);
+ if (nread < 0)
+ {
+ errno = err;
+ return -1;
+ }
+ readbuf[nread] = '\0';
+ count = sscanf (readbuf, "%lu %lu %lu %lu\n",
&load_ave[0], &load_ave[1], &load_ave[2],
&scale);
- (void) fclose (fp);
if (count != 4)
{
errno = ENOTSUP;
@@ -915,7 +851,7 @@ getloadavg (double loadavg[], int nelem)
# ifndef SUNOS_5
if (
-# if !(defined (_AIX) && !defined (ps2))
+# if !defined (_AIX)
nlist (KERNEL_FILE, name_list)
# else /* _AIX */
knlist (name_list, 1, sizeof (name_list[0]))
@@ -940,33 +876,17 @@ getloadavg (double loadavg[], int nelem)
if (!getloadavg_initialized)
{
# ifndef SUNOS_5
- /* Set the channel to close on exec, so it does not
- litter any child's descriptor table. */
-# ifndef O_CLOEXEC
-# define O_CLOEXEC 0
-# endif
int fd = open ("/dev/kmem", O_RDONLY | O_CLOEXEC);
if (0 <= fd)
{
-# if F_DUPFD_CLOEXEC
- if (fd <= STDERR_FILENO)
- {
- int fd1 = fcntl (fd, F_DUPFD_CLOEXEC, STDERR_FILENO + 1);
- close (fd);
- fd = fd1;
- }
-# endif
- if (0 <= fd)
- {
- channel = fd;
- getloadavg_initialized = true;
- }
+ channel = fd;
+ getloadavg_initialized = true;
}
# else /* SUNOS_5 */
/* We pass 0 for the kernel, corefile, and swapfile names
to use the currently running kernel. */
kd = kvm_open (0, 0, 0, O_RDONLY, 0);
- if (kd != 0)
+ if (kd != NULL)
{
/* nlist the currently running kernel. */
kvm_nlist (kd, name_list);
diff --git a/lib/getopt-cdefs.in.h b/lib/getopt-cdefs.in.h
index 21d847b8c3d..b6dd913caf9 100644
--- a/lib/getopt-cdefs.in.h
+++ b/lib/getopt-cdefs.in.h
@@ -1,22 +1,21 @@
/* getopt-on-non-glibc compatibility macros.
- Copyright (C) 1989-2017 Free Software Foundation, Inc.
+ Copyright (C) 1989-2022 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.
- gnulib 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 file is free software: you can redistribute it and/or modify
+ it under the terms of the GNU Lesser General Public License as
+ published by the Free Software Foundation; either version 2.1 of the
+ License, or (at your option) any later version.
- gnulib 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.
+ This file 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 Lesser General Public License for more details.
- You should have received a copy of the GNU General Public
- License along with gnulib; if not, see
- <https://www.gnu.org/licenses/>. */
+ You should have received a copy of the GNU Lesser General Public License
+ along with this program. If not, see <https://www.gnu.org/licenses/>. */
#ifndef _GETOPT_CDEFS_H
#define _GETOPT_CDEFS_H 1
@@ -57,7 +56,7 @@
#endif
#ifndef __THROW
-# if defined __cplusplus && __GNUC_PREREQ (2,8)
+# if defined __cplusplus && (__GNUC_PREREQ (2,8) || __clang_major__ >= 4)
# define __THROW throw ()
# else
# define __THROW
diff --git a/lib/getopt-core.h b/lib/getopt-core.h
index ec0734c7230..1c40ecc833f 100644
--- a/lib/getopt-core.h
+++ b/lib/getopt-core.h
@@ -1,19 +1,19 @@
/* Declarations for getopt (basic, portable features only).
- Copyright (C) 1989-2017 Free Software Foundation, Inc.
+ Copyright (C) 1989-2022 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.
The GNU C Library is free software; you can redistribute it and/or
- modify it under the terms of the GNU General Public
+ modify it under the terms of the GNU Lesser General Public
License as published by the Free Software Foundation; either
- version 3 of the License, or (at your option) any later version.
+ version 2.1 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.
+ Lesser General Public License for more details.
- You should have received a copy of the GNU General Public
+ You should have received a copy of the GNU Lesser General Public
License along with the GNU C Library; if not, see
<https://www.gnu.org/licenses/>. */
diff --git a/lib/getopt-ext.h b/lib/getopt-ext.h
index 4cdbfb0e7a5..d661fcc5548 100644
--- a/lib/getopt-ext.h
+++ b/lib/getopt-ext.h
@@ -1,19 +1,19 @@
/* Declarations for getopt (GNU extensions).
- Copyright (C) 1989-2017 Free Software Foundation, Inc.
+ Copyright (C) 1989-2022 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.
The GNU C Library is free software; you can redistribute it and/or
- modify it under the terms of the GNU General Public
+ modify it under the terms of the GNU Lesser General Public
License as published by the Free Software Foundation; either
- version 3 of the License, or (at your option) any later version.
+ version 2.1 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.
+ Lesser General Public License for more details.
- You should have received a copy of the GNU General Public
+ You should have received a copy of the GNU Lesser General Public
License along with the GNU C Library; if not, see
<https://www.gnu.org/licenses/>. */
diff --git a/lib/getopt-pfx-core.h b/lib/getopt-pfx-core.h
index 2ede4bbffef..3eead0e04e8 100644
--- a/lib/getopt-pfx-core.h
+++ b/lib/getopt-pfx-core.h
@@ -1,22 +1,21 @@
/* getopt (basic, portable features) gnulib wrapper header.
- Copyright (C) 1989-2017 Free Software Foundation, Inc.
+ Copyright (C) 1989-2022 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.
- gnulib 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 file is free software: you can redistribute it and/or modify
+ it under the terms of the GNU Lesser General Public License as
+ published by the Free Software Foundation; either version 2.1 of the
+ License, or (at your option) any later version.
- gnulib 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.
+ This file 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 Lesser General Public License for more details.
- You should have received a copy of the GNU General Public
- License along with gnulib; if not, see
- <https://www.gnu.org/licenses/>. */
+ You should have received a copy of the GNU Lesser General Public License
+ along with this program. If not, see <https://www.gnu.org/licenses/>. */
#ifndef _GETOPT_PFX_CORE_H
#define _GETOPT_PFX_CORE_H 1
@@ -48,6 +47,14 @@
# define optind __GETOPT_ID (optind)
# define optopt __GETOPT_ID (optopt)
+/* Work around a a problem on macOS, which declares getopt with a
+ trailing __DARWIN_ALIAS(getopt) that would expand to something like
+ __asm("_" "rpl_getopt" "$UNIX2003") were it not for the following
+ hack to suppress the macOS declaration <https://bugs.gnu.org/40205>. */
+# ifdef __APPLE__
+# define _GETOPT
+# endif
+
/* The system's getopt.h may have already included getopt-core.h to
declare the unprefixed identifiers. Undef _GETOPT_CORE_H so that
getopt-core.h declares them with prefixes. */
diff --git a/lib/getopt-pfx-ext.h b/lib/getopt-pfx-ext.h
index 16d9634e8c9..85a6cb5db3d 100644
--- a/lib/getopt-pfx-ext.h
+++ b/lib/getopt-pfx-ext.h
@@ -1,22 +1,21 @@
/* getopt (GNU extensions) gnulib wrapper header.
- Copyright (C) 1989-2017 Free Software Foundation, Inc.
+ Copyright (C) 1989-2022 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.
- gnulib 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 file is free software: you can redistribute it and/or modify
+ it under the terms of the GNU Lesser General Public License as
+ published by the Free Software Foundation; either version 2.1 of the
+ License, or (at your option) any later version.
- gnulib 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.
+ This file 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 Lesser General Public License for more details.
- You should have received a copy of the GNU General Public
- License along with gnulib; if not, see
- <https://www.gnu.org/licenses/>. */
+ You should have received a copy of the GNU Lesser General Public License
+ along with this program. If not, see <https://www.gnu.org/licenses/>. */
#ifndef _GETOPT_PFX_EXT_H
#define _GETOPT_PFX_EXT_H 1
diff --git a/lib/getopt.c b/lib/getopt.c
index b0cc35bfb1b..128dc7fcf54 100644
--- a/lib/getopt.c
+++ b/lib/getopt.c
@@ -1,19 +1,19 @@
/* Getopt for GNU.
- Copyright (C) 1987-2017 Free Software Foundation, Inc.
+ Copyright (C) 1987-2022 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.
The GNU C Library is free software; you can redistribute it and/or
- modify it under the terms of the GNU General Public
+ modify it under the terms of the GNU Lesser General Public
License as published by the Free Software Foundation; either
- version 3 of the License, or (at your option) any later version.
+ version 2.1 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.
+ Lesser General Public License for more details.
- You should have received a copy of the GNU General Public
+ You should have received a copy of the GNU Lesser General Public
License along with the GNU C Library; if not, see
<https://www.gnu.org/licenses/>. */
@@ -46,7 +46,7 @@
/* When used standalone, flockfile and funlockfile might not be
available. */
# if (!defined _POSIX_THREAD_SAFE_FUNCTIONS \
- || ((defined _WIN32 || defined __WIN32__) && ! defined __CYGWIN__))
+ || (defined _WIN32 && ! defined __CYGWIN__))
# define flockfile(fp) /* nop */
# define funlockfile(fp) /* nop */
# endif
@@ -378,8 +378,8 @@ process_long_option (int argc, char **argv, const char *optstring,
/* Initialize internal data upon the first call to getopt. */
static const char *
-_getopt_initialize (int argc _GL_UNUSED,
- char **argv _GL_UNUSED, const char *optstring,
+_getopt_initialize (_GL_UNUSED int argc,
+ _GL_UNUSED char **argv, const char *optstring,
struct _getopt_data *d, int posixly_correct)
{
/* Start processing options with ARGV-element 1 (since ARGV-element 0
diff --git a/lib/getopt.in.h b/lib/getopt.in.h
index 908f84166af..9bc50ee2be5 100644
--- a/lib/getopt.in.h
+++ b/lib/getopt.in.h
@@ -1,22 +1,22 @@
/* Declarations for getopt.
- Copyright (C) 1989-2017 Free Software Foundation, Inc.
+ Copyright (C) 1989-2022 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
this file.
- gnulib 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 file is free software: you can redistribute it and/or modify
+ it under the terms of the GNU Lesser General Public License as
+ published by the Free Software Foundation; either version 2.1 of the
+ License, or (at your option) any later version.
- gnulib 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.
+ This file 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 Lesser General Public License for more details.
- You should have received a copy of the GNU General Public
- License along with gnulib; if not, see <https://www.gnu.org/licenses/>. */
+ You should have received a copy of the GNU Lesser General Public License
+ along with this program. If not, see <https://www.gnu.org/licenses/>. */
#ifndef _@GUARD_PREFIX@_GETOPT_H
diff --git a/lib/getopt1.c b/lib/getopt1.c
index d689f4ce67a..990eee1b64f 100644
--- a/lib/getopt1.c
+++ b/lib/getopt1.c
@@ -1,19 +1,19 @@
/* getopt_long and getopt_long_only entry points for GNU getopt.
- Copyright (C) 1987-2017 Free Software Foundation, Inc.
+ Copyright (C) 1987-2022 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.
The GNU C Library is free software; you can redistribute it and/or
- modify it under the terms of the GNU General Public
+ modify it under the terms of the GNU Lesser General Public
License as published by the Free Software Foundation; either
- version 3 of the License, or (at your option) any later version.
+ version 2.1 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.
+ Lesser General Public License for more details.
- You should have received a copy of the GNU General Public
+ You should have received a copy of the GNU Lesser General Public
License along with the GNU C Library; if not, see
<https://www.gnu.org/licenses/>. */
diff --git a/lib/getopt_int.h b/lib/getopt_int.h
index e33856ce9b9..ccdbb973a51 100644
--- a/lib/getopt_int.h
+++ b/lib/getopt_int.h
@@ -1,19 +1,19 @@
/* Internal declarations for getopt.
- Copyright (C) 1989-2017 Free Software Foundation, Inc.
+ Copyright (C) 1989-2022 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.
The GNU C Library is free software; you can redistribute it and/or
- modify it under the terms of the GNU General Public
+ modify it under the terms of the GNU Lesser General Public
License as published by the Free Software Foundation; either
- version 3 of the License, or (at your option) any later version.
+ version 2.1 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.
+ Lesser General Public License for more details.
- You should have received a copy of the GNU General Public
+ You should have received a copy of the GNU Lesser General Public
License along with the GNU C Library; if not, see
<https://www.gnu.org/licenses/>. */
diff --git a/lib/getrandom.c b/lib/getrandom.c
new file mode 100644
index 00000000000..e1468730933
--- /dev/null
+++ b/lib/getrandom.c
@@ -0,0 +1,191 @@
+/* Obtain a series of random bytes.
+
+ Copyright 2020-2022 Free Software Foundation, Inc.
+
+ This file is free software: you can redistribute it and/or modify
+ it under the terms of the GNU Lesser General Public License as
+ published by the Free Software Foundation; either version 2.1 of the
+ License, or (at your option) any later version.
+
+ This file 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 Lesser General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public License
+ along with this program. If not, see <https://www.gnu.org/licenses/>. */
+
+/* Written by Paul Eggert. */
+
+#include <config.h>
+
+#include <sys/random.h>
+
+#include <errno.h>
+#include <fcntl.h>
+#include <stdbool.h>
+#include <unistd.h>
+
+#if defined _WIN32 && ! defined __CYGWIN__
+# define WIN32_LEAN_AND_MEAN
+# include <windows.h>
+# if HAVE_BCRYPT_H
+# include <bcrypt.h>
+# else
+# define NTSTATUS LONG
+typedef void * BCRYPT_ALG_HANDLE;
+# define BCRYPT_USE_SYSTEM_PREFERRED_RNG 0x00000002
+# if HAVE_LIB_BCRYPT
+extern NTSTATUS WINAPI BCryptGenRandom (BCRYPT_ALG_HANDLE, UCHAR *, ULONG, ULONG);
+# endif
+# endif
+# if !HAVE_LIB_BCRYPT
+# include <wincrypt.h>
+# ifndef CRYPT_VERIFY_CONTEXT
+# define CRYPT_VERIFY_CONTEXT 0xF0000000
+# endif
+# endif
+#endif
+
+#include "minmax.h"
+
+#if defined _WIN32 && ! defined __CYGWIN__
+
+/* Don't assume that UNICODE is not defined. */
+# undef LoadLibrary
+# define LoadLibrary LoadLibraryA
+# undef CryptAcquireContext
+# define CryptAcquireContext CryptAcquireContextA
+
+# if !HAVE_LIB_BCRYPT
+
+/* Avoid warnings from gcc -Wcast-function-type. */
+# define GetProcAddress \
+ (void *) GetProcAddress
+
+/* BCryptGenRandom with the BCRYPT_USE_SYSTEM_PREFERRED_RNG flag works only
+ starting with Windows 7. */
+typedef NTSTATUS (WINAPI * BCryptGenRandomFuncType) (BCRYPT_ALG_HANDLE, UCHAR *, ULONG, ULONG);
+static BCryptGenRandomFuncType BCryptGenRandomFunc = NULL;
+static BOOL initialized = FALSE;
+
+static void
+initialize (void)
+{
+ HMODULE bcrypt = LoadLibrary ("bcrypt.dll");
+ if (bcrypt != NULL)
+ {
+ BCryptGenRandomFunc =
+ (BCryptGenRandomFuncType) GetProcAddress (bcrypt, "BCryptGenRandom");
+ }
+ initialized = TRUE;
+}
+
+# else
+
+# define BCryptGenRandomFunc BCryptGenRandom
+
+# endif
+
+#else
+/* These devices exist on all platforms except native Windows. */
+
+/* Name of a device through which the kernel returns high quality random
+ numbers, from an entropy pool. When the pool is empty, the call blocks
+ until entropy sources have added enough bits of entropy. */
+# ifndef NAME_OF_RANDOM_DEVICE
+# define NAME_OF_RANDOM_DEVICE "/dev/random"
+# endif
+
+/* Name of a device through which the kernel returns random or pseudo-random
+ numbers. It uses an entropy pool, but, in order to avoid blocking, adds
+ bits generated by a pseudo-random number generator, as needed. */
+# ifndef NAME_OF_NONCE_DEVICE
+# define NAME_OF_NONCE_DEVICE "/dev/urandom"
+# endif
+
+#endif
+
+/* Set BUFFER (of size LENGTH) to random bytes under the control of FLAGS.
+ Return the number of bytes written (> 0).
+ Upon error, return -1 and set errno. */
+ssize_t
+getrandom (void *buffer, size_t length, unsigned int flags)
+#undef getrandom
+{
+#if defined _WIN32 && ! defined __CYGWIN__
+ /* BCryptGenRandom, defined in <bcrypt.h>
+ <https://docs.microsoft.com/en-us/windows/win32/api/bcrypt/nf-bcrypt-bcryptgenrandom>
+ with the BCRYPT_USE_SYSTEM_PREFERRED_RNG flag
+ works in Windows 7 and newer. */
+ static int bcrypt_not_working /* = 0 */;
+ if (!bcrypt_not_working)
+ {
+# if !HAVE_LIB_BCRYPT
+ if (!initialized)
+ initialize ();
+# endif
+ if (BCryptGenRandomFunc != NULL
+ && BCryptGenRandomFunc (NULL, buffer, length,
+ BCRYPT_USE_SYSTEM_PREFERRED_RNG)
+ == 0 /*STATUS_SUCCESS*/)
+ return length;
+ bcrypt_not_working = 1;
+ }
+# if !HAVE_LIB_BCRYPT
+ /* CryptGenRandom, defined in <wincrypt.h>
+ <https://docs.microsoft.com/en-us/windows/win32/api/wincrypt/nf-wincrypt-cryptgenrandom>
+ works in older releases as well, but is now deprecated.
+ CryptAcquireContext, defined in <wincrypt.h>
+ <https://docs.microsoft.com/en-us/windows/win32/api/wincrypt/nf-wincrypt-cryptacquirecontexta> */
+ {
+ static int crypt_initialized /* = 0 */;
+ static HCRYPTPROV provider;
+ if (!crypt_initialized)
+ {
+ if (CryptAcquireContext (&provider, NULL, NULL, PROV_RSA_FULL,
+ CRYPT_VERIFY_CONTEXT))
+ crypt_initialized = 1;
+ else
+ crypt_initialized = -1;
+ }
+ if (crypt_initialized >= 0)
+ {
+ if (!CryptGenRandom (provider, length, buffer))
+ {
+ errno = EIO;
+ return -1;
+ }
+ return length;
+ }
+ }
+# endif
+ errno = ENOSYS;
+ return -1;
+#elif HAVE_GETRANDOM
+ return getrandom (buffer, length, flags);
+#else
+ static int randfd[2] = { -1, -1 };
+ bool devrandom = (flags & GRND_RANDOM) != 0;
+ int fd = randfd[devrandom];
+
+ if (fd < 0)
+ {
+ static char const randdevice[][MAX (sizeof NAME_OF_NONCE_DEVICE,
+ sizeof NAME_OF_RANDOM_DEVICE)]
+ = { NAME_OF_NONCE_DEVICE, NAME_OF_RANDOM_DEVICE };
+ int oflags = (O_RDONLY + O_CLOEXEC
+ + (flags & GRND_NONBLOCK ? O_NONBLOCK : 0));
+ fd = open (randdevice[devrandom], oflags);
+ if (fd < 0)
+ {
+ if (errno == ENOENT || errno == ENOTDIR)
+ errno = ENOSYS;
+ return -1;
+ }
+ randfd[devrandom] = fd;
+ }
+
+ return read (fd, buffer, length);
+#endif
+}
diff --git a/lib/gettext.h b/lib/gettext.h
index f6150be6523..b3577a043f8 100644
--- a/lib/gettext.h
+++ b/lib/gettext.h
@@ -1,19 +1,19 @@
/* Convenience header for conditional use of GNU <libintl.h>.
- Copyright (C) 1995-1998, 2000-2002, 2004-2006, 2009-2017 Free Software
+ Copyright (C) 1995-1998, 2000-2002, 2004-2006, 2009-2022 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 file is free software: you can redistribute it and/or modify
+ it under the terms of the GNU Lesser General Public License as
+ published by the Free Software Foundation; either version 2.1 of the
+ License, or (at your option) any later version.
- This program is distributed in the hope that it will be useful,
+ This file 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.
+ GNU Lesser General Public License for more details.
- You should have received a copy of the GNU General Public License along
- with this program; if not, see <https://www.gnu.org/licenses/>. */
+ You should have received a copy of the GNU Lesser General Public License
+ along with this program. If not, see <https://www.gnu.org/licenses/>. */
#ifndef _LIBGETTEXT_H
#define _LIBGETTEXT_H 1
@@ -138,7 +138,7 @@
#define dcnpgettext(Domainname, Msgctxt, Msgid, MsgidPlural, N, Category) \
npgettext_aux (Domainname, Msgctxt GETTEXT_CONTEXT_GLUE Msgid, Msgid, MsgidPlural, N, Category)
-#ifdef __GNUC__
+#if defined __GNUC__ || defined __clang__
__inline
#else
#ifdef __cplusplus
@@ -157,7 +157,7 @@ pgettext_aux (const char *domain,
return translation;
}
-#ifdef __GNUC__
+#if defined __GNUC__ || defined __clang__
__inline
#else
#ifdef __cplusplus
@@ -184,9 +184,15 @@ npgettext_aux (const char *domain,
#include <string.h>
-#if (((__GNUC__ >= 3 || __GNUG__ >= 2) && !defined __STRICT_ANSI__) \
- /* || __STDC_VERSION__ == 199901L
- || (__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 \
+ && defined __STDC_VERSION__ && 199901L <= __STDC_VERSION__ \
+ && !defined __STDC_NO_VLA__)
# define _LIBGETTEXT_HAVE_VARIABLE_SIZE_ARRAYS 1
#else
# define _LIBGETTEXT_HAVE_VARIABLE_SIZE_ARRAYS 0
@@ -201,7 +207,7 @@ npgettext_aux (const char *domain,
#define dpgettext_expr(Domainname, Msgctxt, Msgid) \
dcpgettext_expr (Domainname, Msgctxt, Msgid, LC_MESSAGES)
-#ifdef __GNUC__
+#if defined __GNUC__ || defined __clang__
__inline
#else
#ifdef __cplusplus
@@ -248,7 +254,7 @@ dcpgettext_expr (const char *domain,
#define dnpgettext_expr(Domainname, Msgctxt, Msgid, MsgidPlural, N) \
dcnpgettext_expr (Domainname, Msgctxt, Msgid, MsgidPlural, N, LC_MESSAGES)
-#ifdef __GNUC__
+#if defined __GNUC__ || defined __clang__
__inline
#else
#ifdef __cplusplus
diff --git a/lib/gettime.c b/lib/gettime.c
index e5af26c9902..541af18bbfa 100644
--- a/lib/gettime.c
+++ b/lib/gettime.c
@@ -1,18 +1,18 @@
/* gettime -- get the system clock
- Copyright (C) 2002, 2004-2007, 2009-2017 Free Software Foundation, Inc.
+ Copyright (C) 2002, 2004-2007, 2009-2022 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 file is free software: you can redistribute it and/or modify
+ it under the terms of the GNU Lesser 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,
+ This file 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.
+ GNU Lesser General Public License for more details.
- You should have received a copy of the GNU General Public License
+ You should have received a copy of the GNU Lesser General Public License
along with this program. If not, see <https://www.gnu.org/licenses/>. */
/* Written by Paul Eggert. */
@@ -28,21 +28,24 @@
void
gettime (struct timespec *ts)
{
-#if HAVE_NANOTIME
- nanotime (ts);
+#if defined CLOCK_REALTIME && HAVE_CLOCK_GETTIME
+ clock_gettime (CLOCK_REALTIME, ts);
+#elif defined HAVE_TIMESPEC_GET
+ timespec_get (ts, TIME_UTC);
#else
+ struct timeval tv;
+ gettimeofday (&tv, NULL);
+ ts->tv_sec = tv.tv_sec;
+ ts->tv_nsec = tv.tv_usec * 1000;
+#endif
+}
-# if defined CLOCK_REALTIME && HAVE_CLOCK_GETTIME
- if (clock_gettime (CLOCK_REALTIME, ts) == 0)
- return;
-# endif
-
- {
- struct timeval tv;
- gettimeofday (&tv, NULL);
- ts->tv_sec = tv.tv_sec;
- ts->tv_nsec = tv.tv_usec * 1000;
- }
+/* Return the current system time as a struct timespec. */
-#endif
+struct timespec
+current_timespec (void)
+{
+ struct timespec ts;
+ gettime (&ts);
+ return ts;
}
diff --git a/lib/gettimeofday.c b/lib/gettimeofday.c
index a11b1830c4c..36c7920afe6 100644
--- a/lib/gettimeofday.c
+++ b/lib/gettimeofday.c
@@ -1,19 +1,19 @@
/* Provide gettimeofday for systems that don't have it or for which it's broken.
- Copyright (C) 2001-2003, 2005-2007, 2009-2017 Free Software Foundation, Inc.
+ Copyright (C) 2001-2003, 2005-2007, 2009-2022 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 file is free software: you can redistribute it and/or modify
+ it under the terms of the GNU Lesser General Public License as
+ published by the Free Software Foundation; either version 2.1 of the
+ License, or (at your option) any later version.
- This program is distributed in the hope that it will be useful,
+ This file 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.
+ GNU Lesser General Public License for more details.
- You should have received a copy of the GNU General Public License
- along with this program; if not, see <https://www.gnu.org/licenses/>. */
+ You should have received a copy of the GNU Lesser General Public License
+ along with this program. If not, see <https://www.gnu.org/licenses/>. */
/* written by Jim Meyering */
@@ -24,15 +24,23 @@
#include <time.h>
-#if (defined _WIN32 || defined __WIN32__) && ! defined __CYGWIN__
+#if defined _WIN32 && ! defined __CYGWIN__
# define WINDOWS_NATIVE
# include <windows.h>
#endif
-#include "localtime-buffer.h"
-
#ifdef WINDOWS_NATIVE
+/* Don't assume that UNICODE is not defined. */
+# undef LoadLibrary
+# define LoadLibrary LoadLibraryA
+
+# if !(_WIN32_WINNT >= _WIN32_WINNT_WIN8)
+
+/* Avoid warnings from gcc -Wcast-function-type. */
+# define GetProcAddress \
+ (void *) GetProcAddress
+
/* GetSystemTimePreciseAsFileTime was introduced only in Windows 8. */
typedef void (WINAPI * GetSystemTimePreciseAsFileTimeFuncType) (FILETIME *lpTime);
static GetSystemTimePreciseAsFileTimeFuncType GetSystemTimePreciseAsFileTimeFunc = NULL;
@@ -45,11 +53,17 @@ initialize (void)
if (kernel32 != NULL)
{
GetSystemTimePreciseAsFileTimeFunc =
- (GetSystemTimePreciseAsFileTimeFuncType) GetProcAddress (kernel32, "GetSystemTimePreciseAsFileTime");
+ (GetSystemTimePreciseAsFileTimeFuncType) GetProcAddress (kernel32, "GetSystemTimePreciseAsFileTime");
}
initialized = TRUE;
}
+# else
+
+# define GetSystemTimePreciseAsFileTimeFunc GetSystemTimePreciseAsFileTime
+
+# endif
+
#endif
/* This is a wrapper for gettimeofday. It is used only on systems
@@ -68,10 +82,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
@@ -80,15 +94,17 @@ gettimeofday (struct timeval *restrict tv, void *restrict tz)
<http://www.windowstimestamp.com/description>. */
FILETIME current_time;
+# if !(_WIN32_WINNT >= _WIN32_WINNT_WIN8)
if (!initialized)
initialize ();
+# endif
if (GetSystemTimePreciseAsFileTimeFunc != NULL)
GetSystemTimePreciseAsFileTimeFunc (&current_time);
else
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;
@@ -105,11 +121,6 @@ gettimeofday (struct timeval *restrict tv, void *restrict tz)
#else
# if HAVE_GETTIMEOFDAY
-# if GETTIMEOFDAY_CLOBBERS_LOCALTIME
- /* Save and restore the contents of the buffer used for localtime's
- result around the call to gettimeofday. */
- struct tm save = *localtime_buffer_addr;
-# endif
# if defined timeval /* 'struct timeval' overridden by gnulib? */
# undef timeval
@@ -124,10 +135,6 @@ gettimeofday (struct timeval *restrict tv, void *restrict tz)
int result = gettimeofday (tv, (struct timezone *) tz);
# endif
-# if GETTIMEOFDAY_CLOBBERS_LOCALTIME
- *localtime_buffer_addr = save;
-# endif
-
return result;
# else
diff --git a/lib/gnulib.mk.in b/lib/gnulib.mk.in
index e9358a6855d..5bb78740d6a 100644
--- a/lib/gnulib.mk.in
+++ b/lib/gnulib.mk.in
@@ -1,10 +1,9 @@
## DO NOT EDIT! GENERATED AUTOMATICALLY!
-## Process this file with automake to produce Makefile.in.
-# Copyright (C) 2002-2017 Free Software Foundation, Inc.
+# Copyright (C) 2002-2022 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
-# the Free Software Foundation; either version 3 of the License, or
+# the Free Software Foundation, either version 3 of the License, or
# (at your option) any later version.
#
# This file is distributed in the hope that it will be useful,
@@ -21,7 +20,154 @@
# the same distribution terms as the rest of that program.
#
# Generated by gnulib-tool.
-# Reproduce by: gnulib-tool --import --lib=libgnu --source-base=lib --m4-base=m4 --doc-base=doc --tests-base=tests --aux-dir=build-aux --avoid=close --avoid=dup --avoid=fchdir --avoid=fstat --avoid=malloc-posix --avoid=msvc-inval --avoid=msvc-nothrow --avoid=openat-die --avoid=opendir --avoid=raise --avoid=save-cwd --avoid=select --avoid=setenv --avoid=sigprocmask --avoid=stat --avoid=stdarg --avoid=stdbool --avoid=threadlib --avoid=tzset --avoid=unsetenv --avoid=utime --avoid=utime-h --gnu-make --makefile-name=gnulib.mk.in --conditional-dependencies --no-libtool --macro-prefix=gl --no-vc-files alloca-opt binary-io byteswap c-ctype c-strcase careadlinkat close-stream count-leading-zeros count-one-bits count-trailing-zeros crypto/md5 crypto/sha1 crypto/sha256 crypto/sha512 d-type diffseq dtoastr dtotimespec dup2 environ execinfo explicit_bzero faccessat fcntl fcntl-h fdatasync fdopendir filemode filevercmp flexmember fstatat fsusage fsync getloadavg getopt-gnu gettime gettimeofday gitlog-to-changelog ignore-value intprops largefile lstat manywarnings memrchr minmax mkostemp mktime nstrftime pipe2 pselect pthread_sigmask putenv qcopy-acl readlink readlinkat sig2str socklen stat-time std-gnu11 stdalign stddef stdio stpcpy strtoimax symlink sys_stat sys_time tempname time time_r time_rz timegm timer-time timespec-add timespec-sub unlocked-io update-copyright utimens vla warnings
+# Reproduce by:
+# gnulib-tool --import \
+# --lib=libgnu \
+# --source-base=lib \
+# --m4-base=m4 \
+# --doc-base=doc \
+# --tests-base=tests \
+# --aux-dir=build-aux \
+# --gnu-make \
+# --makefile-name=gnulib.mk.in \
+# --conditional-dependencies \
+# --no-libtool \
+# --macro-prefix=gl \
+# --no-vc-files \
+# --avoid=btowc \
+# --avoid=chmod \
+# --avoid=close \
+# --avoid=crypto/af_alg \
+# --avoid=dup \
+# --avoid=fchdir \
+# --avoid=fstat \
+# --avoid=langinfo \
+# --avoid=lock \
+# --avoid=mbrtowc \
+# --avoid=mbsinit \
+# --avoid=memchr \
+# --avoid=mkdir \
+# --avoid=msvc-inval \
+# --avoid=msvc-nothrow \
+# --avoid=nl_langinfo \
+# --avoid=openat-die \
+# --avoid=opendir \
+# --avoid=pthread-h \
+# --avoid=raise \
+# --avoid=save-cwd \
+# --avoid=select \
+# --avoid=setenv \
+# --avoid=sigprocmask \
+# --avoid=stat \
+# --avoid=stdarg \
+# --avoid=stdbool \
+# --avoid=threadlib \
+# --avoid=tzset \
+# --avoid=unsetenv \
+# --avoid=utime \
+# --avoid=utime-h \
+# --avoid=wchar \
+# --avoid=wcrtomb \
+# --avoid=wctype-h \
+# alloca-opt \
+# binary-io \
+# byteswap \
+# c-ctype \
+# c-strcase \
+# canonicalize-lgpl \
+# careadlinkat \
+# close-stream \
+# copy-file-range \
+# count-leading-zeros \
+# count-one-bits \
+# count-trailing-zeros \
+# crypto/md5 \
+# crypto/md5-buffer \
+# crypto/sha1-buffer \
+# crypto/sha256-buffer \
+# crypto/sha512-buffer \
+# d-type \
+# diffseq \
+# double-slash-root \
+# dtoastr \
+# dtotimespec \
+# dup2 \
+# environ \
+# execinfo \
+# explicit_bzero \
+# faccessat \
+# fchmodat \
+# fcntl \
+# fcntl-h \
+# fdopendir \
+# file-has-acl \
+# filemode \
+# filename \
+# filevercmp \
+# flexmember \
+# fpieee \
+# free-posix \
+# fstatat \
+# fsusage \
+# fsync \
+# futimens \
+# getloadavg \
+# getopt-gnu \
+# getrandom \
+# gettime \
+# gettimeofday \
+# gitlog-to-changelog \
+# ieee754-h \
+# ignore-value \
+# intprops \
+# largefile \
+# libgmp \
+# lstat \
+# manywarnings \
+# memmem-simple \
+# mempcpy \
+# memrchr \
+# minmax \
+# mkostemp \
+# mktime \
+# nanosleep \
+# nproc \
+# nstrftime \
+# pathmax \
+# pipe2 \
+# pselect \
+# pthread_sigmask \
+# qcopy-acl \
+# readlink \
+# readlinkat \
+# regex \
+# sig2str \
+# sigdescr_np \
+# socklen \
+# stat-time \
+# std-gnu11 \
+# stdalign \
+# stddef \
+# stdio \
+# stpcpy \
+# strnlen \
+# strtoimax \
+# symlink \
+# sys_stat \
+# sys_time \
+# tempname \
+# time \
+# time_r \
+# time_rz \
+# timegm \
+# timer-time \
+# timespec-add \
+# timespec-sub \
+# unlocked-io \
+# update-copyright \
+# utimensat \
+# vla \
+# warnings
MOSTLYCLEANFILES += core *.stackdump
@@ -30,9 +176,7 @@ ALLOCA = @ALLOCA@
ALLOCA_H = @ALLOCA_H@
ALSA_CFLAGS = @ALSA_CFLAGS@
ALSA_LIBS = @ALSA_LIBS@
-AM_DEFAULT_V = @AM_DEFAULT_V@
AM_DEFAULT_VERBOSITY = @AM_DEFAULT_VERBOSITY@
-AM_V = @AM_V@
APPLE_UNIVERSAL_BUILD = @APPLE_UNIVERSAL_BUILD@
AR = @AR@
ARFLAGS = @ARFLAGS@
@@ -44,14 +188,19 @@ BITSIZEOF_SIZE_T = @BITSIZEOF_SIZE_T@
BITSIZEOF_WCHAR_T = @BITSIZEOF_WCHAR_T@
BITSIZEOF_WINT_T = @BITSIZEOF_WINT_T@
BLESSMAIL_TARGET = @BLESSMAIL_TARGET@
+BREW = @BREW@
BUILD_DETAILS = @BUILD_DETAILS@
BYTESWAP_H = @BYTESWAP_H@
CAIRO_CFLAGS = @CAIRO_CFLAGS@
CAIRO_LIBS = @CAIRO_LIBS@
-CANNOT_DUMP = @CANNOT_DUMP@
+CAIRO_XCB_CFLAGS = @CAIRO_XCB_CFLAGS@
+CAIRO_XCB_LIBS = @CAIRO_XCB_LIBS@
+CAIRO_XLIB_CFLAGS = @CAIRO_XLIB_CFLAGS@
+CAIRO_XLIB_LIBS = @CAIRO_XLIB_LIBS@
CC = @CC@
CFLAGS = @CFLAGS@
CFLAGS_SOUND = @CFLAGS_SOUND@
+CHECK_STRUCTS = @CHECK_STRUCTS@
CLIENTRES = @CLIENTRES@
CLIENTW = @CLIENTW@
CM_OBJ = @CM_OBJ@
@@ -59,6 +208,8 @@ COM_ERRLIB = @COM_ERRLIB@
CPP = @CPP@
CPPFLAGS = @CPPFLAGS@
CRYPTOLIB = @CRYPTOLIB@
+CXX = @CXX@
+CXXFLAGS = @CXXFLAGS@
CYGWIN_OBJ = @CYGWIN_OBJ@
C_SWITCH_MACHINE = @C_SWITCH_MACHINE@
C_SWITCH_SYSTEM = @C_SWITCH_SYSTEM@
@@ -69,6 +220,8 @@ DBUS_OBJ = @DBUS_OBJ@
DEFS = @DEFS@
DESLIB = @DESLIB@
DOCMISC_W32 = @DOCMISC_W32@
+DUMPING = @DUMPING@
+DYNLIB_OBJ = @DYNLIB_OBJ@
ECHO_C = @ECHO_C@
ECHO_N = @ECHO_N@
ECHO_T = @ECHO_T@
@@ -99,241 +252,376 @@ GETOPT_CDEFS_H = @GETOPT_CDEFS_H@
GETOPT_H = @GETOPT_H@
GFILENOTIFY_CFLAGS = @GFILENOTIFY_CFLAGS@
GFILENOTIFY_LIBS = @GFILENOTIFY_LIBS@
-GL_COND_LIBTOOL = @GL_COND_LIBTOOL@
-GL_GENERATE_ALLOCA_H = @GL_GENERATE_ALLOCA_H@
-GL_GENERATE_BYTESWAP_H = @GL_GENERATE_BYTESWAP_H@
-GL_GENERATE_ERRNO_H = @GL_GENERATE_ERRNO_H@
-GL_GENERATE_EXECINFO_H = @GL_GENERATE_EXECINFO_H@
-GL_GENERATE_LIMITS_H = @GL_GENERATE_LIMITS_H@
-GL_GENERATE_STDALIGN_H = @GL_GENERATE_STDALIGN_H@
-GL_GENERATE_STDDEF_H = @GL_GENERATE_STDDEF_H@
-GL_GENERATE_STDINT_H = @GL_GENERATE_STDINT_H@
+GL_CFLAG_ALLOW_WARNINGS = @GL_CFLAG_ALLOW_WARNINGS@
+GL_CFLAG_GNULIB_WARNINGS = @GL_CFLAG_GNULIB_WARNINGS@
+GL_COND_LIBTOOL_CONDITION = @GL_COND_LIBTOOL_CONDITION@
+GL_COND_OBJ_CANONICALIZE_LGPL_CONDITION = @GL_COND_OBJ_CANONICALIZE_LGPL_CONDITION@
+GL_COND_OBJ_COPY_FILE_RANGE_CONDITION = @GL_COND_OBJ_COPY_FILE_RANGE_CONDITION@
+GL_COND_OBJ_DIRFD_CONDITION = @GL_COND_OBJ_DIRFD_CONDITION@
+GL_COND_OBJ_DUP2_CONDITION = @GL_COND_OBJ_DUP2_CONDITION@
+GL_COND_OBJ_EUIDACCESS_CONDITION = @GL_COND_OBJ_EUIDACCESS_CONDITION@
+GL_COND_OBJ_EXECINFO_CONDITION = @GL_COND_OBJ_EXECINFO_CONDITION@
+GL_COND_OBJ_EXPLICIT_BZERO_CONDITION = @GL_COND_OBJ_EXPLICIT_BZERO_CONDITION@
+GL_COND_OBJ_FACCESSAT_CONDITION = @GL_COND_OBJ_FACCESSAT_CONDITION@
+GL_COND_OBJ_FCHMODAT_CONDITION = @GL_COND_OBJ_FCHMODAT_CONDITION@
+GL_COND_OBJ_FCNTL_CONDITION = @GL_COND_OBJ_FCNTL_CONDITION@
+GL_COND_OBJ_FDOPENDIR_CONDITION = @GL_COND_OBJ_FDOPENDIR_CONDITION@
+GL_COND_OBJ_FPENDING_CONDITION = @GL_COND_OBJ_FPENDING_CONDITION@
+GL_COND_OBJ_FREE_CONDITION = @GL_COND_OBJ_FREE_CONDITION@
+GL_COND_OBJ_FSTATAT_CONDITION = @GL_COND_OBJ_FSTATAT_CONDITION@
+GL_COND_OBJ_FSUSAGE_CONDITION = @GL_COND_OBJ_FSUSAGE_CONDITION@
+GL_COND_OBJ_FSYNC_CONDITION = @GL_COND_OBJ_FSYNC_CONDITION@
+GL_COND_OBJ_FUTIMENS_CONDITION = @GL_COND_OBJ_FUTIMENS_CONDITION@
+GL_COND_OBJ_GETDTABLESIZE_CONDITION = @GL_COND_OBJ_GETDTABLESIZE_CONDITION@
+GL_COND_OBJ_GETGROUPS_CONDITION = @GL_COND_OBJ_GETGROUPS_CONDITION@
+GL_COND_OBJ_GETLOADAVG_CONDITION = @GL_COND_OBJ_GETLOADAVG_CONDITION@
+GL_COND_OBJ_GETOPT_CONDITION = @GL_COND_OBJ_GETOPT_CONDITION@
+GL_COND_OBJ_GETRANDOM_CONDITION = @GL_COND_OBJ_GETRANDOM_CONDITION@
+GL_COND_OBJ_GETTIMEOFDAY_CONDITION = @GL_COND_OBJ_GETTIMEOFDAY_CONDITION@
+GL_COND_OBJ_GROUP_MEMBER_CONDITION = @GL_COND_OBJ_GROUP_MEMBER_CONDITION@
+GL_COND_OBJ_LCHMOD_CONDITION = @GL_COND_OBJ_LCHMOD_CONDITION@
+GL_COND_OBJ_LSTAT_CONDITION = @GL_COND_OBJ_LSTAT_CONDITION@
+GL_COND_OBJ_MEMPCPY_CONDITION = @GL_COND_OBJ_MEMPCPY_CONDITION@
+GL_COND_OBJ_MEMRCHR_CONDITION = @GL_COND_OBJ_MEMRCHR_CONDITION@
+GL_COND_OBJ_MINI_GMP_GNULIB_CONDITION = @GL_COND_OBJ_MINI_GMP_GNULIB_CONDITION@
+GL_COND_OBJ_MKOSTEMP_CONDITION = @GL_COND_OBJ_MKOSTEMP_CONDITION@
+GL_COND_OBJ_NANOSLEEP_CONDITION = @GL_COND_OBJ_NANOSLEEP_CONDITION@
+GL_COND_OBJ_OPEN_CONDITION = @GL_COND_OBJ_OPEN_CONDITION@
+GL_COND_OBJ_PSELECT_CONDITION = @GL_COND_OBJ_PSELECT_CONDITION@
+GL_COND_OBJ_PTHREAD_SIGMASK_CONDITION = @GL_COND_OBJ_PTHREAD_SIGMASK_CONDITION@
+GL_COND_OBJ_RAWMEMCHR_CONDITION = @GL_COND_OBJ_RAWMEMCHR_CONDITION@
+GL_COND_OBJ_READLINKAT_CONDITION = @GL_COND_OBJ_READLINKAT_CONDITION@
+GL_COND_OBJ_READLINK_CONDITION = @GL_COND_OBJ_READLINK_CONDITION@
+GL_COND_OBJ_REGEX_CONDITION = @GL_COND_OBJ_REGEX_CONDITION@
+GL_COND_OBJ_SIG2STR_CONDITION = @GL_COND_OBJ_SIG2STR_CONDITION@
+GL_COND_OBJ_SIGDESCR_NP_CONDITION = @GL_COND_OBJ_SIGDESCR_NP_CONDITION@
+GL_COND_OBJ_STDIO_READ_CONDITION = @GL_COND_OBJ_STDIO_READ_CONDITION@
+GL_COND_OBJ_STDIO_WRITE_CONDITION = @GL_COND_OBJ_STDIO_WRITE_CONDITION@
+GL_COND_OBJ_STPCPY_CONDITION = @GL_COND_OBJ_STPCPY_CONDITION@
+GL_COND_OBJ_STRNLEN_CONDITION = @GL_COND_OBJ_STRNLEN_CONDITION@
+GL_COND_OBJ_STRTOIMAX_CONDITION = @GL_COND_OBJ_STRTOIMAX_CONDITION@
+GL_COND_OBJ_STRTOLL_CONDITION = @GL_COND_OBJ_STRTOLL_CONDITION@
+GL_COND_OBJ_SYMLINK_CONDITION = @GL_COND_OBJ_SYMLINK_CONDITION@
+GL_COND_OBJ_TIMEGM_CONDITION = @GL_COND_OBJ_TIMEGM_CONDITION@
+GL_COND_OBJ_TIME_RZ_CONDITION = @GL_COND_OBJ_TIME_RZ_CONDITION@
+GL_COND_OBJ_TIME_R_CONDITION = @GL_COND_OBJ_TIME_R_CONDITION@
+GL_COND_OBJ_UTIMENSAT_CONDITION = @GL_COND_OBJ_UTIMENSAT_CONDITION@
+GL_GENERATE_ALLOCA_H_CONDITION = @GL_GENERATE_ALLOCA_H_CONDITION@
+GL_GENERATE_BYTESWAP_H_CONDITION = @GL_GENERATE_BYTESWAP_H_CONDITION@
+GL_GENERATE_ERRNO_H_CONDITION = @GL_GENERATE_ERRNO_H_CONDITION@
+GL_GENERATE_EXECINFO_H_CONDITION = @GL_GENERATE_EXECINFO_H_CONDITION@
+GL_GENERATE_GETOPT_CDEFS_H_CONDITION = @GL_GENERATE_GETOPT_CDEFS_H_CONDITION@
+GL_GENERATE_GETOPT_H_CONDITION = @GL_GENERATE_GETOPT_H_CONDITION@
+GL_GENERATE_GMP_GMP_H_CONDITION = @GL_GENERATE_GMP_GMP_H_CONDITION@
+GL_GENERATE_GMP_H_CONDITION = @GL_GENERATE_GMP_H_CONDITION@
+GL_GENERATE_IEEE754_H_CONDITION = @GL_GENERATE_IEEE754_H_CONDITION@
+GL_GENERATE_LIMITS_H_CONDITION = @GL_GENERATE_LIMITS_H_CONDITION@
+GL_GENERATE_MINI_GMP_H_CONDITION = @GL_GENERATE_MINI_GMP_H_CONDITION@
+GL_GENERATE_STDALIGN_H_CONDITION = @GL_GENERATE_STDALIGN_H_CONDITION@
+GL_GENERATE_STDCKDINT_H_CONDITION = @GL_GENERATE_STDCKDINT_H_CONDITION@
+GL_GENERATE_STDDEF_H_CONDITION = @GL_GENERATE_STDDEF_H_CONDITION@
+GL_GENERATE_STDINT_H_CONDITION = @GL_GENERATE_STDINT_H_CONDITION@
+GL_GNULIB_ACCESS = @GL_GNULIB_ACCESS@
+GL_GNULIB_ALIGNED_ALLOC = @GL_GNULIB_ALIGNED_ALLOC@
+GL_GNULIB_ALPHASORT = @GL_GNULIB_ALPHASORT@
+GL_GNULIB_ATOLL = @GL_GNULIB_ATOLL@
+GL_GNULIB_CALLOC_GNU = @GL_GNULIB_CALLOC_GNU@
+GL_GNULIB_CALLOC_POSIX = @GL_GNULIB_CALLOC_POSIX@
+GL_GNULIB_CANONICALIZE_FILE_NAME = @GL_GNULIB_CANONICALIZE_FILE_NAME@
+GL_GNULIB_CHDIR = @GL_GNULIB_CHDIR@
+GL_GNULIB_CHMOD = @GL_GNULIB_CHMOD@
+GL_GNULIB_CHOWN = @GL_GNULIB_CHOWN@
+GL_GNULIB_CLOSE = @GL_GNULIB_CLOSE@
+GL_GNULIB_CLOSEDIR = @GL_GNULIB_CLOSEDIR@
+GL_GNULIB_COPY_FILE_RANGE = @GL_GNULIB_COPY_FILE_RANGE@
+GL_GNULIB_CREAT = @GL_GNULIB_CREAT@
+GL_GNULIB_CTIME = @GL_GNULIB_CTIME@
+GL_GNULIB_DIRFD = @GL_GNULIB_DIRFD@
+GL_GNULIB_DPRINTF = @GL_GNULIB_DPRINTF@
+GL_GNULIB_DUP = @GL_GNULIB_DUP@
+GL_GNULIB_DUP2 = @GL_GNULIB_DUP2@
+GL_GNULIB_DUP3 = @GL_GNULIB_DUP3@
+GL_GNULIB_ENVIRON = @GL_GNULIB_ENVIRON@
+GL_GNULIB_EUIDACCESS = @GL_GNULIB_EUIDACCESS@
+GL_GNULIB_EXECL = @GL_GNULIB_EXECL@
+GL_GNULIB_EXECLE = @GL_GNULIB_EXECLE@
+GL_GNULIB_EXECLP = @GL_GNULIB_EXECLP@
+GL_GNULIB_EXECV = @GL_GNULIB_EXECV@
+GL_GNULIB_EXECVE = @GL_GNULIB_EXECVE@
+GL_GNULIB_EXECVP = @GL_GNULIB_EXECVP@
+GL_GNULIB_EXECVPE = @GL_GNULIB_EXECVPE@
+GL_GNULIB_EXPLICIT_BZERO = @GL_GNULIB_EXPLICIT_BZERO@
+GL_GNULIB_FACCESSAT = @GL_GNULIB_FACCESSAT@
+GL_GNULIB_FCHDIR = @GL_GNULIB_FCHDIR@
+GL_GNULIB_FCHMODAT = @GL_GNULIB_FCHMODAT@
+GL_GNULIB_FCHOWNAT = @GL_GNULIB_FCHOWNAT@
+GL_GNULIB_FCLOSE = @GL_GNULIB_FCLOSE@
+GL_GNULIB_FCNTL = @GL_GNULIB_FCNTL@
+GL_GNULIB_FDATASYNC = @GL_GNULIB_FDATASYNC@
+GL_GNULIB_FDOPEN = @GL_GNULIB_FDOPEN@
+GL_GNULIB_FDOPENDIR = @GL_GNULIB_FDOPENDIR@
+GL_GNULIB_FFLUSH = @GL_GNULIB_FFLUSH@
+GL_GNULIB_FFSL = @GL_GNULIB_FFSL@
+GL_GNULIB_FFSLL = @GL_GNULIB_FFSLL@
+GL_GNULIB_FGETC = @GL_GNULIB_FGETC@
+GL_GNULIB_FGETS = @GL_GNULIB_FGETS@
+GL_GNULIB_FOPEN = @GL_GNULIB_FOPEN@
+GL_GNULIB_FOPEN_GNU = @GL_GNULIB_FOPEN_GNU@
+GL_GNULIB_FPRINTF = @GL_GNULIB_FPRINTF@
+GL_GNULIB_FPRINTF_POSIX = @GL_GNULIB_FPRINTF_POSIX@
+GL_GNULIB_FPURGE = @GL_GNULIB_FPURGE@
+GL_GNULIB_FPUTC = @GL_GNULIB_FPUTC@
+GL_GNULIB_FPUTS = @GL_GNULIB_FPUTS@
+GL_GNULIB_FREAD = @GL_GNULIB_FREAD@
+GL_GNULIB_FREE_POSIX = @GL_GNULIB_FREE_POSIX@
+GL_GNULIB_FREOPEN = @GL_GNULIB_FREOPEN@
+GL_GNULIB_FSCANF = @GL_GNULIB_FSCANF@
+GL_GNULIB_FSEEK = @GL_GNULIB_FSEEK@
+GL_GNULIB_FSEEKO = @GL_GNULIB_FSEEKO@
+GL_GNULIB_FSTAT = @GL_GNULIB_FSTAT@
+GL_GNULIB_FSTATAT = @GL_GNULIB_FSTATAT@
+GL_GNULIB_FSYNC = @GL_GNULIB_FSYNC@
+GL_GNULIB_FTELL = @GL_GNULIB_FTELL@
+GL_GNULIB_FTELLO = @GL_GNULIB_FTELLO@
+GL_GNULIB_FTRUNCATE = @GL_GNULIB_FTRUNCATE@
+GL_GNULIB_FUTIMENS = @GL_GNULIB_FUTIMENS@
+GL_GNULIB_FWRITE = @GL_GNULIB_FWRITE@
+GL_GNULIB_GETC = @GL_GNULIB_GETC@
+GL_GNULIB_GETCHAR = @GL_GNULIB_GETCHAR@
+GL_GNULIB_GETCWD = @GL_GNULIB_GETCWD@
+GL_GNULIB_GETDELIM = @GL_GNULIB_GETDELIM@
+GL_GNULIB_GETDOMAINNAME = @GL_GNULIB_GETDOMAINNAME@
+GL_GNULIB_GETDTABLESIZE = @GL_GNULIB_GETDTABLESIZE@
+GL_GNULIB_GETENTROPY = @GL_GNULIB_GETENTROPY@
+GL_GNULIB_GETGROUPS = @GL_GNULIB_GETGROUPS@
+GL_GNULIB_GETHOSTNAME = @GL_GNULIB_GETHOSTNAME@
+GL_GNULIB_GETLINE = @GL_GNULIB_GETLINE@
+GL_GNULIB_GETLOADAVG = @GL_GNULIB_GETLOADAVG@
+GL_GNULIB_GETLOGIN = @GL_GNULIB_GETLOGIN@
+GL_GNULIB_GETLOGIN_R = @GL_GNULIB_GETLOGIN_R@
+GL_GNULIB_GETOPT_POSIX = @GL_GNULIB_GETOPT_POSIX@
+GL_GNULIB_GETPAGESIZE = @GL_GNULIB_GETPAGESIZE@
+GL_GNULIB_GETPASS = @GL_GNULIB_GETPASS@
+GL_GNULIB_GETPASS_GNU = @GL_GNULIB_GETPASS_GNU@
+GL_GNULIB_GETRANDOM = @GL_GNULIB_GETRANDOM@
+GL_GNULIB_GETSUBOPT = @GL_GNULIB_GETSUBOPT@
+GL_GNULIB_GETTIMEOFDAY = @GL_GNULIB_GETTIMEOFDAY@
+GL_GNULIB_GETUMASK = @GL_GNULIB_GETUMASK@
+GL_GNULIB_GETUSERSHELL = @GL_GNULIB_GETUSERSHELL@
+GL_GNULIB_GRANTPT = @GL_GNULIB_GRANTPT@
+GL_GNULIB_GROUP_MEMBER = @GL_GNULIB_GROUP_MEMBER@
+GL_GNULIB_IMAXABS = @GL_GNULIB_IMAXABS@
+GL_GNULIB_IMAXDIV = @GL_GNULIB_IMAXDIV@
+GL_GNULIB_ISATTY = @GL_GNULIB_ISATTY@
+GL_GNULIB_LCHMOD = @GL_GNULIB_LCHMOD@
+GL_GNULIB_LCHOWN = @GL_GNULIB_LCHOWN@
+GL_GNULIB_LINK = @GL_GNULIB_LINK@
+GL_GNULIB_LINKAT = @GL_GNULIB_LINKAT@
+GL_GNULIB_LOCALTIME = @GL_GNULIB_LOCALTIME@
+GL_GNULIB_LSEEK = @GL_GNULIB_LSEEK@
+GL_GNULIB_LSTAT = @GL_GNULIB_LSTAT@
+GL_GNULIB_MALLOC_GNU = @GL_GNULIB_MALLOC_GNU@
+GL_GNULIB_MALLOC_POSIX = @GL_GNULIB_MALLOC_POSIX@
+GL_GNULIB_MBSCASECMP = @GL_GNULIB_MBSCASECMP@
+GL_GNULIB_MBSCASESTR = @GL_GNULIB_MBSCASESTR@
+GL_GNULIB_MBSCHR = @GL_GNULIB_MBSCHR@
+GL_GNULIB_MBSCSPN = @GL_GNULIB_MBSCSPN@
+GL_GNULIB_MBSLEN = @GL_GNULIB_MBSLEN@
+GL_GNULIB_MBSNCASECMP = @GL_GNULIB_MBSNCASECMP@
+GL_GNULIB_MBSNLEN = @GL_GNULIB_MBSNLEN@
+GL_GNULIB_MBSPBRK = @GL_GNULIB_MBSPBRK@
+GL_GNULIB_MBSPCASECMP = @GL_GNULIB_MBSPCASECMP@
+GL_GNULIB_MBSRCHR = @GL_GNULIB_MBSRCHR@
+GL_GNULIB_MBSSEP = @GL_GNULIB_MBSSEP@
+GL_GNULIB_MBSSPN = @GL_GNULIB_MBSSPN@
+GL_GNULIB_MBSSTR = @GL_GNULIB_MBSSTR@
+GL_GNULIB_MBSTOK_R = @GL_GNULIB_MBSTOK_R@
+GL_GNULIB_MBTOWC = @GL_GNULIB_MBTOWC@
+GL_GNULIB_MDA_ACCESS = @GL_GNULIB_MDA_ACCESS@
+GL_GNULIB_MDA_CHDIR = @GL_GNULIB_MDA_CHDIR@
+GL_GNULIB_MDA_CHMOD = @GL_GNULIB_MDA_CHMOD@
+GL_GNULIB_MDA_CLOSE = @GL_GNULIB_MDA_CLOSE@
+GL_GNULIB_MDA_CREAT = @GL_GNULIB_MDA_CREAT@
+GL_GNULIB_MDA_DUP = @GL_GNULIB_MDA_DUP@
+GL_GNULIB_MDA_DUP2 = @GL_GNULIB_MDA_DUP2@
+GL_GNULIB_MDA_ECVT = @GL_GNULIB_MDA_ECVT@
+GL_GNULIB_MDA_EXECL = @GL_GNULIB_MDA_EXECL@
+GL_GNULIB_MDA_EXECLE = @GL_GNULIB_MDA_EXECLE@
+GL_GNULIB_MDA_EXECLP = @GL_GNULIB_MDA_EXECLP@
+GL_GNULIB_MDA_EXECV = @GL_GNULIB_MDA_EXECV@
+GL_GNULIB_MDA_EXECVE = @GL_GNULIB_MDA_EXECVE@
+GL_GNULIB_MDA_EXECVP = @GL_GNULIB_MDA_EXECVP@
+GL_GNULIB_MDA_EXECVPE = @GL_GNULIB_MDA_EXECVPE@
+GL_GNULIB_MDA_FCLOSEALL = @GL_GNULIB_MDA_FCLOSEALL@
+GL_GNULIB_MDA_FCVT = @GL_GNULIB_MDA_FCVT@
+GL_GNULIB_MDA_FDOPEN = @GL_GNULIB_MDA_FDOPEN@
+GL_GNULIB_MDA_FILENO = @GL_GNULIB_MDA_FILENO@
+GL_GNULIB_MDA_GCVT = @GL_GNULIB_MDA_GCVT@
+GL_GNULIB_MDA_GETCWD = @GL_GNULIB_MDA_GETCWD@
+GL_GNULIB_MDA_GETPID = @GL_GNULIB_MDA_GETPID@
+GL_GNULIB_MDA_GETW = @GL_GNULIB_MDA_GETW@
+GL_GNULIB_MDA_ISATTY = @GL_GNULIB_MDA_ISATTY@
+GL_GNULIB_MDA_LSEEK = @GL_GNULIB_MDA_LSEEK@
+GL_GNULIB_MDA_MEMCCPY = @GL_GNULIB_MDA_MEMCCPY@
+GL_GNULIB_MDA_MKDIR = @GL_GNULIB_MDA_MKDIR@
+GL_GNULIB_MDA_MKTEMP = @GL_GNULIB_MDA_MKTEMP@
+GL_GNULIB_MDA_OPEN = @GL_GNULIB_MDA_OPEN@
+GL_GNULIB_MDA_PUTENV = @GL_GNULIB_MDA_PUTENV@
+GL_GNULIB_MDA_PUTW = @GL_GNULIB_MDA_PUTW@
+GL_GNULIB_MDA_READ = @GL_GNULIB_MDA_READ@
+GL_GNULIB_MDA_RMDIR = @GL_GNULIB_MDA_RMDIR@
+GL_GNULIB_MDA_STRDUP = @GL_GNULIB_MDA_STRDUP@
+GL_GNULIB_MDA_SWAB = @GL_GNULIB_MDA_SWAB@
+GL_GNULIB_MDA_TEMPNAM = @GL_GNULIB_MDA_TEMPNAM@
+GL_GNULIB_MDA_TZSET = @GL_GNULIB_MDA_TZSET@
+GL_GNULIB_MDA_UMASK = @GL_GNULIB_MDA_UMASK@
+GL_GNULIB_MDA_UNLINK = @GL_GNULIB_MDA_UNLINK@
+GL_GNULIB_MDA_WRITE = @GL_GNULIB_MDA_WRITE@
+GL_GNULIB_MEMCHR = @GL_GNULIB_MEMCHR@
+GL_GNULIB_MEMMEM = @GL_GNULIB_MEMMEM@
+GL_GNULIB_MEMPCPY = @GL_GNULIB_MEMPCPY@
+GL_GNULIB_MEMRCHR = @GL_GNULIB_MEMRCHR@
+GL_GNULIB_MKDIR = @GL_GNULIB_MKDIR@
+GL_GNULIB_MKDIRAT = @GL_GNULIB_MKDIRAT@
+GL_GNULIB_MKDTEMP = @GL_GNULIB_MKDTEMP@
+GL_GNULIB_MKFIFO = @GL_GNULIB_MKFIFO@
+GL_GNULIB_MKFIFOAT = @GL_GNULIB_MKFIFOAT@
+GL_GNULIB_MKNOD = @GL_GNULIB_MKNOD@
+GL_GNULIB_MKNODAT = @GL_GNULIB_MKNODAT@
+GL_GNULIB_MKOSTEMP = @GL_GNULIB_MKOSTEMP@
+GL_GNULIB_MKOSTEMPS = @GL_GNULIB_MKOSTEMPS@
+GL_GNULIB_MKSTEMP = @GL_GNULIB_MKSTEMP@
+GL_GNULIB_MKSTEMPS = @GL_GNULIB_MKSTEMPS@
+GL_GNULIB_MKTIME = @GL_GNULIB_MKTIME@
+GL_GNULIB_NANOSLEEP = @GL_GNULIB_NANOSLEEP@
+GL_GNULIB_NONBLOCKING = @GL_GNULIB_NONBLOCKING@
+GL_GNULIB_OBSTACK_PRINTF = @GL_GNULIB_OBSTACK_PRINTF@
+GL_GNULIB_OBSTACK_PRINTF_POSIX = @GL_GNULIB_OBSTACK_PRINTF_POSIX@
+GL_GNULIB_OPEN = @GL_GNULIB_OPEN@
+GL_GNULIB_OPENAT = @GL_GNULIB_OPENAT@
+GL_GNULIB_OPENDIR = @GL_GNULIB_OPENDIR@
+GL_GNULIB_OVERRIDES_STRUCT_STAT = @GL_GNULIB_OVERRIDES_STRUCT_STAT@
+GL_GNULIB_PCLOSE = @GL_GNULIB_PCLOSE@
+GL_GNULIB_PERROR = @GL_GNULIB_PERROR@
+GL_GNULIB_PIPE = @GL_GNULIB_PIPE@
+GL_GNULIB_PIPE2 = @GL_GNULIB_PIPE2@
+GL_GNULIB_POPEN = @GL_GNULIB_POPEN@
+GL_GNULIB_POSIX_MEMALIGN = @GL_GNULIB_POSIX_MEMALIGN@
+GL_GNULIB_POSIX_OPENPT = @GL_GNULIB_POSIX_OPENPT@
+GL_GNULIB_PREAD = @GL_GNULIB_PREAD@
+GL_GNULIB_PRINTF = @GL_GNULIB_PRINTF@
+GL_GNULIB_PRINTF_POSIX = @GL_GNULIB_PRINTF_POSIX@
+GL_GNULIB_PSELECT = @GL_GNULIB_PSELECT@
+GL_GNULIB_PTHREAD_SIGMASK = @GL_GNULIB_PTHREAD_SIGMASK@
+GL_GNULIB_PTSNAME = @GL_GNULIB_PTSNAME@
+GL_GNULIB_PTSNAME_R = @GL_GNULIB_PTSNAME_R@
+GL_GNULIB_PUTC = @GL_GNULIB_PUTC@
+GL_GNULIB_PUTCHAR = @GL_GNULIB_PUTCHAR@
+GL_GNULIB_PUTENV = @GL_GNULIB_PUTENV@
+GL_GNULIB_PUTS = @GL_GNULIB_PUTS@
+GL_GNULIB_PWRITE = @GL_GNULIB_PWRITE@
+GL_GNULIB_QSORT_R = @GL_GNULIB_QSORT_R@
+GL_GNULIB_RAISE = @GL_GNULIB_RAISE@
+GL_GNULIB_RANDOM = @GL_GNULIB_RANDOM@
+GL_GNULIB_RANDOM_R = @GL_GNULIB_RANDOM_R@
+GL_GNULIB_RAWMEMCHR = @GL_GNULIB_RAWMEMCHR@
+GL_GNULIB_READ = @GL_GNULIB_READ@
+GL_GNULIB_READDIR = @GL_GNULIB_READDIR@
+GL_GNULIB_READLINK = @GL_GNULIB_READLINK@
+GL_GNULIB_READLINKAT = @GL_GNULIB_READLINKAT@
+GL_GNULIB_REALLOCARRAY = @GL_GNULIB_REALLOCARRAY@
+GL_GNULIB_REALLOC_GNU = @GL_GNULIB_REALLOC_GNU@
+GL_GNULIB_REALLOC_POSIX = @GL_GNULIB_REALLOC_POSIX@
+GL_GNULIB_REALPATH = @GL_GNULIB_REALPATH@
+GL_GNULIB_REMOVE = @GL_GNULIB_REMOVE@
+GL_GNULIB_RENAME = @GL_GNULIB_RENAME@
+GL_GNULIB_RENAMEAT = @GL_GNULIB_RENAMEAT@
+GL_GNULIB_REWINDDIR = @GL_GNULIB_REWINDDIR@
+GL_GNULIB_RMDIR = @GL_GNULIB_RMDIR@
+GL_GNULIB_RPMATCH = @GL_GNULIB_RPMATCH@
+GL_GNULIB_SCANDIR = @GL_GNULIB_SCANDIR@
+GL_GNULIB_SCANF = @GL_GNULIB_SCANF@
+GL_GNULIB_SECURE_GETENV = @GL_GNULIB_SECURE_GETENV@
+GL_GNULIB_SELECT = @GL_GNULIB_SELECT@
+GL_GNULIB_SETENV = @GL_GNULIB_SETENV@
+GL_GNULIB_SETHOSTNAME = @GL_GNULIB_SETHOSTNAME@
+GL_GNULIB_SIGABBREV_NP = @GL_GNULIB_SIGABBREV_NP@
+GL_GNULIB_SIGACTION = @GL_GNULIB_SIGACTION@
+GL_GNULIB_SIGDESCR_NP = @GL_GNULIB_SIGDESCR_NP@
+GL_GNULIB_SIGNAL_H_SIGPIPE = @GL_GNULIB_SIGNAL_H_SIGPIPE@
+GL_GNULIB_SIGPROCMASK = @GL_GNULIB_SIGPROCMASK@
+GL_GNULIB_SLEEP = @GL_GNULIB_SLEEP@
+GL_GNULIB_SNPRINTF = @GL_GNULIB_SNPRINTF@
+GL_GNULIB_SPRINTF_POSIX = @GL_GNULIB_SPRINTF_POSIX@
+GL_GNULIB_STAT = @GL_GNULIB_STAT@
+GL_GNULIB_STDIO_H_NONBLOCKING = @GL_GNULIB_STDIO_H_NONBLOCKING@
+GL_GNULIB_STDIO_H_SIGPIPE = @GL_GNULIB_STDIO_H_SIGPIPE@
+GL_GNULIB_STPCPY = @GL_GNULIB_STPCPY@
+GL_GNULIB_STPNCPY = @GL_GNULIB_STPNCPY@
+GL_GNULIB_STRCASESTR = @GL_GNULIB_STRCASESTR@
+GL_GNULIB_STRCHRNUL = @GL_GNULIB_STRCHRNUL@
+GL_GNULIB_STRDUP = @GL_GNULIB_STRDUP@
+GL_GNULIB_STRERROR = @GL_GNULIB_STRERROR@
+GL_GNULIB_STRERRORNAME_NP = @GL_GNULIB_STRERRORNAME_NP@
+GL_GNULIB_STRERROR_R = @GL_GNULIB_STRERROR_R@
+GL_GNULIB_STRFTIME = @GL_GNULIB_STRFTIME@
+GL_GNULIB_STRNCAT = @GL_GNULIB_STRNCAT@
+GL_GNULIB_STRNDUP = @GL_GNULIB_STRNDUP@
+GL_GNULIB_STRNLEN = @GL_GNULIB_STRNLEN@
+GL_GNULIB_STRPBRK = @GL_GNULIB_STRPBRK@
+GL_GNULIB_STRPTIME = @GL_GNULIB_STRPTIME@
+GL_GNULIB_STRSEP = @GL_GNULIB_STRSEP@
+GL_GNULIB_STRSIGNAL = @GL_GNULIB_STRSIGNAL@
+GL_GNULIB_STRSTR = @GL_GNULIB_STRSTR@
+GL_GNULIB_STRTOD = @GL_GNULIB_STRTOD@
+GL_GNULIB_STRTOIMAX = @GL_GNULIB_STRTOIMAX@
+GL_GNULIB_STRTOK_R = @GL_GNULIB_STRTOK_R@
+GL_GNULIB_STRTOL = @GL_GNULIB_STRTOL@
+GL_GNULIB_STRTOLD = @GL_GNULIB_STRTOLD@
+GL_GNULIB_STRTOLL = @GL_GNULIB_STRTOLL@
+GL_GNULIB_STRTOUL = @GL_GNULIB_STRTOUL@
+GL_GNULIB_STRTOULL = @GL_GNULIB_STRTOULL@
+GL_GNULIB_STRTOUMAX = @GL_GNULIB_STRTOUMAX@
+GL_GNULIB_STRVERSCMP = @GL_GNULIB_STRVERSCMP@
+GL_GNULIB_SYMLINK = @GL_GNULIB_SYMLINK@
+GL_GNULIB_SYMLINKAT = @GL_GNULIB_SYMLINKAT@
+GL_GNULIB_SYSTEM_POSIX = @GL_GNULIB_SYSTEM_POSIX@
+GL_GNULIB_TIMEGM = @GL_GNULIB_TIMEGM@
+GL_GNULIB_TIMESPEC_GET = @GL_GNULIB_TIMESPEC_GET@
+GL_GNULIB_TIMESPEC_GETRES = @GL_GNULIB_TIMESPEC_GETRES@
+GL_GNULIB_TIME_R = @GL_GNULIB_TIME_R@
+GL_GNULIB_TIME_RZ = @GL_GNULIB_TIME_RZ@
+GL_GNULIB_TMPFILE = @GL_GNULIB_TMPFILE@
+GL_GNULIB_TRUNCATE = @GL_GNULIB_TRUNCATE@
+GL_GNULIB_TTYNAME_R = @GL_GNULIB_TTYNAME_R@
+GL_GNULIB_TZSET = @GL_GNULIB_TZSET@
+GL_GNULIB_UNISTD_H_GETOPT = @GL_GNULIB_UNISTD_H_GETOPT@
+GL_GNULIB_UNISTD_H_NONBLOCKING = @GL_GNULIB_UNISTD_H_NONBLOCKING@
+GL_GNULIB_UNISTD_H_SIGPIPE = @GL_GNULIB_UNISTD_H_SIGPIPE@
+GL_GNULIB_UNLINK = @GL_GNULIB_UNLINK@
+GL_GNULIB_UNLINKAT = @GL_GNULIB_UNLINKAT@
+GL_GNULIB_UNLOCKPT = @GL_GNULIB_UNLOCKPT@
+GL_GNULIB_UNSETENV = @GL_GNULIB_UNSETENV@
+GL_GNULIB_USLEEP = @GL_GNULIB_USLEEP@
+GL_GNULIB_UTIMENSAT = @GL_GNULIB_UTIMENSAT@
+GL_GNULIB_VASPRINTF = @GL_GNULIB_VASPRINTF@
+GL_GNULIB_VDPRINTF = @GL_GNULIB_VDPRINTF@
+GL_GNULIB_VFPRINTF = @GL_GNULIB_VFPRINTF@
+GL_GNULIB_VFPRINTF_POSIX = @GL_GNULIB_VFPRINTF_POSIX@
+GL_GNULIB_VFSCANF = @GL_GNULIB_VFSCANF@
+GL_GNULIB_VPRINTF = @GL_GNULIB_VPRINTF@
+GL_GNULIB_VPRINTF_POSIX = @GL_GNULIB_VPRINTF_POSIX@
+GL_GNULIB_VSCANF = @GL_GNULIB_VSCANF@
+GL_GNULIB_VSNPRINTF = @GL_GNULIB_VSNPRINTF@
+GL_GNULIB_VSPRINTF_POSIX = @GL_GNULIB_VSPRINTF_POSIX@
+GL_GNULIB_WCTOMB = @GL_GNULIB_WCTOMB@
+GL_GNULIB_WRITE = @GL_GNULIB_WRITE@
+GL_GNULIB__EXIT = @GL_GNULIB__EXIT@
GMALLOC_OBJ = @GMALLOC_OBJ@
-GNULIB_ALPHASORT = @GNULIB_ALPHASORT@
-GNULIB_ATOLL = @GNULIB_ATOLL@
-GNULIB_CALLOC_POSIX = @GNULIB_CALLOC_POSIX@
-GNULIB_CANONICALIZE_FILE_NAME = @GNULIB_CANONICALIZE_FILE_NAME@
-GNULIB_CHDIR = @GNULIB_CHDIR@
-GNULIB_CHOWN = @GNULIB_CHOWN@
-GNULIB_CLOSE = @GNULIB_CLOSE@
-GNULIB_CLOSEDIR = @GNULIB_CLOSEDIR@
-GNULIB_CTIME = @GNULIB_CTIME@
-GNULIB_DIRFD = @GNULIB_DIRFD@
-GNULIB_DPRINTF = @GNULIB_DPRINTF@
-GNULIB_DUP = @GNULIB_DUP@
-GNULIB_DUP2 = @GNULIB_DUP2@
-GNULIB_DUP3 = @GNULIB_DUP3@
-GNULIB_ENVIRON = @GNULIB_ENVIRON@
-GNULIB_EUIDACCESS = @GNULIB_EUIDACCESS@
-GNULIB_EXPLICIT_BZERO = @GNULIB_EXPLICIT_BZERO@
-GNULIB_FACCESSAT = @GNULIB_FACCESSAT@
-GNULIB_FCHDIR = @GNULIB_FCHDIR@
-GNULIB_FCHMODAT = @GNULIB_FCHMODAT@
-GNULIB_FCHOWNAT = @GNULIB_FCHOWNAT@
-GNULIB_FCLOSE = @GNULIB_FCLOSE@
-GNULIB_FCNTL = @GNULIB_FCNTL@
-GNULIB_FDATASYNC = @GNULIB_FDATASYNC@
-GNULIB_FDOPEN = @GNULIB_FDOPEN@
-GNULIB_FDOPENDIR = @GNULIB_FDOPENDIR@
-GNULIB_FFLUSH = @GNULIB_FFLUSH@
-GNULIB_FFSL = @GNULIB_FFSL@
-GNULIB_FFSLL = @GNULIB_FFSLL@
-GNULIB_FGETC = @GNULIB_FGETC@
-GNULIB_FGETS = @GNULIB_FGETS@
-GNULIB_FOPEN = @GNULIB_FOPEN@
-GNULIB_FPRINTF = @GNULIB_FPRINTF@
-GNULIB_FPRINTF_POSIX = @GNULIB_FPRINTF_POSIX@
-GNULIB_FPURGE = @GNULIB_FPURGE@
-GNULIB_FPUTC = @GNULIB_FPUTC@
-GNULIB_FPUTS = @GNULIB_FPUTS@
-GNULIB_FREAD = @GNULIB_FREAD@
-GNULIB_FREOPEN = @GNULIB_FREOPEN@
-GNULIB_FSCANF = @GNULIB_FSCANF@
-GNULIB_FSEEK = @GNULIB_FSEEK@
-GNULIB_FSEEKO = @GNULIB_FSEEKO@
-GNULIB_FSTAT = @GNULIB_FSTAT@
-GNULIB_FSTATAT = @GNULIB_FSTATAT@
-GNULIB_FSYNC = @GNULIB_FSYNC@
-GNULIB_FTELL = @GNULIB_FTELL@
-GNULIB_FTELLO = @GNULIB_FTELLO@
-GNULIB_FTRUNCATE = @GNULIB_FTRUNCATE@
-GNULIB_FUTIMENS = @GNULIB_FUTIMENS@
-GNULIB_FWRITE = @GNULIB_FWRITE@
-GNULIB_GETC = @GNULIB_GETC@
-GNULIB_GETCHAR = @GNULIB_GETCHAR@
-GNULIB_GETCWD = @GNULIB_GETCWD@
-GNULIB_GETDELIM = @GNULIB_GETDELIM@
-GNULIB_GETDOMAINNAME = @GNULIB_GETDOMAINNAME@
-GNULIB_GETDTABLESIZE = @GNULIB_GETDTABLESIZE@
-GNULIB_GETGROUPS = @GNULIB_GETGROUPS@
-GNULIB_GETHOSTNAME = @GNULIB_GETHOSTNAME@
-GNULIB_GETLINE = @GNULIB_GETLINE@
-GNULIB_GETLOADAVG = @GNULIB_GETLOADAVG@
-GNULIB_GETLOGIN = @GNULIB_GETLOGIN@
-GNULIB_GETLOGIN_R = @GNULIB_GETLOGIN_R@
-GNULIB_GETPAGESIZE = @GNULIB_GETPAGESIZE@
-GNULIB_GETSUBOPT = @GNULIB_GETSUBOPT@
+GMP_H = @GMP_H@
+GNULIBHEADERS_OVERRIDE_WINT_T = @GNULIBHEADERS_OVERRIDE_WINT_T@
GNULIB_GETTIMEOFDAY = @GNULIB_GETTIMEOFDAY@
-GNULIB_GETUSERSHELL = @GNULIB_GETUSERSHELL@
-GNULIB_GL_UNISTD_H_GETOPT = @GNULIB_GL_UNISTD_H_GETOPT@
-GNULIB_GRANTPT = @GNULIB_GRANTPT@
-GNULIB_GROUP_MEMBER = @GNULIB_GROUP_MEMBER@
-GNULIB_IMAXABS = @GNULIB_IMAXABS@
-GNULIB_IMAXDIV = @GNULIB_IMAXDIV@
-GNULIB_ISATTY = @GNULIB_ISATTY@
-GNULIB_LCHMOD = @GNULIB_LCHMOD@
-GNULIB_LCHOWN = @GNULIB_LCHOWN@
-GNULIB_LINK = @GNULIB_LINK@
-GNULIB_LINKAT = @GNULIB_LINKAT@
-GNULIB_LOCALTIME = @GNULIB_LOCALTIME@
-GNULIB_LSEEK = @GNULIB_LSEEK@
-GNULIB_LSTAT = @GNULIB_LSTAT@
-GNULIB_MALLOC_POSIX = @GNULIB_MALLOC_POSIX@
-GNULIB_MBSCASECMP = @GNULIB_MBSCASECMP@
-GNULIB_MBSCASESTR = @GNULIB_MBSCASESTR@
-GNULIB_MBSCHR = @GNULIB_MBSCHR@
-GNULIB_MBSCSPN = @GNULIB_MBSCSPN@
-GNULIB_MBSLEN = @GNULIB_MBSLEN@
-GNULIB_MBSNCASECMP = @GNULIB_MBSNCASECMP@
-GNULIB_MBSNLEN = @GNULIB_MBSNLEN@
-GNULIB_MBSPBRK = @GNULIB_MBSPBRK@
-GNULIB_MBSPCASECMP = @GNULIB_MBSPCASECMP@
-GNULIB_MBSRCHR = @GNULIB_MBSRCHR@
-GNULIB_MBSSEP = @GNULIB_MBSSEP@
-GNULIB_MBSSPN = @GNULIB_MBSSPN@
-GNULIB_MBSSTR = @GNULIB_MBSSTR@
-GNULIB_MBSTOK_R = @GNULIB_MBSTOK_R@
-GNULIB_MBTOWC = @GNULIB_MBTOWC@
-GNULIB_MEMCHR = @GNULIB_MEMCHR@
-GNULIB_MEMMEM = @GNULIB_MEMMEM@
-GNULIB_MEMPCPY = @GNULIB_MEMPCPY@
-GNULIB_MEMRCHR = @GNULIB_MEMRCHR@
-GNULIB_MKDIRAT = @GNULIB_MKDIRAT@
-GNULIB_MKDTEMP = @GNULIB_MKDTEMP@
-GNULIB_MKFIFO = @GNULIB_MKFIFO@
-GNULIB_MKFIFOAT = @GNULIB_MKFIFOAT@
-GNULIB_MKNOD = @GNULIB_MKNOD@
-GNULIB_MKNODAT = @GNULIB_MKNODAT@
-GNULIB_MKOSTEMP = @GNULIB_MKOSTEMP@
-GNULIB_MKOSTEMPS = @GNULIB_MKOSTEMPS@
-GNULIB_MKSTEMP = @GNULIB_MKSTEMP@
-GNULIB_MKSTEMPS = @GNULIB_MKSTEMPS@
-GNULIB_MKTIME = @GNULIB_MKTIME@
-GNULIB_NANOSLEEP = @GNULIB_NANOSLEEP@
-GNULIB_NONBLOCKING = @GNULIB_NONBLOCKING@
-GNULIB_OBSTACK_PRINTF = @GNULIB_OBSTACK_PRINTF@
-GNULIB_OBSTACK_PRINTF_POSIX = @GNULIB_OBSTACK_PRINTF_POSIX@
-GNULIB_OPEN = @GNULIB_OPEN@
-GNULIB_OPENAT = @GNULIB_OPENAT@
-GNULIB_OPENDIR = @GNULIB_OPENDIR@
-GNULIB_OVERRIDES_STRUCT_STAT = @GNULIB_OVERRIDES_STRUCT_STAT@
-GNULIB_OVERRIDES_WINT_T = @GNULIB_OVERRIDES_WINT_T@
-GNULIB_PCLOSE = @GNULIB_PCLOSE@
-GNULIB_PERROR = @GNULIB_PERROR@
-GNULIB_PIPE = @GNULIB_PIPE@
-GNULIB_PIPE2 = @GNULIB_PIPE2@
-GNULIB_POPEN = @GNULIB_POPEN@
-GNULIB_POSIX_OPENPT = @GNULIB_POSIX_OPENPT@
-GNULIB_PREAD = @GNULIB_PREAD@
-GNULIB_PRINTF = @GNULIB_PRINTF@
-GNULIB_PRINTF_POSIX = @GNULIB_PRINTF_POSIX@
-GNULIB_PSELECT = @GNULIB_PSELECT@
-GNULIB_PTHREAD_SIGMASK = @GNULIB_PTHREAD_SIGMASK@
-GNULIB_PTSNAME = @GNULIB_PTSNAME@
-GNULIB_PTSNAME_R = @GNULIB_PTSNAME_R@
-GNULIB_PUTC = @GNULIB_PUTC@
-GNULIB_PUTCHAR = @GNULIB_PUTCHAR@
-GNULIB_PUTENV = @GNULIB_PUTENV@
-GNULIB_PUTS = @GNULIB_PUTS@
-GNULIB_PWRITE = @GNULIB_PWRITE@
-GNULIB_QSORT_R = @GNULIB_QSORT_R@
-GNULIB_RAISE = @GNULIB_RAISE@
-GNULIB_RANDOM = @GNULIB_RANDOM@
-GNULIB_RANDOM_R = @GNULIB_RANDOM_R@
-GNULIB_RAWMEMCHR = @GNULIB_RAWMEMCHR@
-GNULIB_READ = @GNULIB_READ@
-GNULIB_READDIR = @GNULIB_READDIR@
-GNULIB_READLINK = @GNULIB_READLINK@
-GNULIB_READLINKAT = @GNULIB_READLINKAT@
-GNULIB_REALLOCARRAY = @GNULIB_REALLOCARRAY@
-GNULIB_REALLOC_POSIX = @GNULIB_REALLOC_POSIX@
-GNULIB_REALPATH = @GNULIB_REALPATH@
-GNULIB_REMOVE = @GNULIB_REMOVE@
-GNULIB_RENAME = @GNULIB_RENAME@
-GNULIB_RENAMEAT = @GNULIB_RENAMEAT@
-GNULIB_REWINDDIR = @GNULIB_REWINDDIR@
-GNULIB_RMDIR = @GNULIB_RMDIR@
-GNULIB_RPMATCH = @GNULIB_RPMATCH@
-GNULIB_SCANDIR = @GNULIB_SCANDIR@
-GNULIB_SCANF = @GNULIB_SCANF@
-GNULIB_SECURE_GETENV = @GNULIB_SECURE_GETENV@
-GNULIB_SELECT = @GNULIB_SELECT@
-GNULIB_SETENV = @GNULIB_SETENV@
-GNULIB_SETHOSTNAME = @GNULIB_SETHOSTNAME@
-GNULIB_SIGACTION = @GNULIB_SIGACTION@
-GNULIB_SIGNAL_H_SIGPIPE = @GNULIB_SIGNAL_H_SIGPIPE@
-GNULIB_SIGPROCMASK = @GNULIB_SIGPROCMASK@
-GNULIB_SLEEP = @GNULIB_SLEEP@
-GNULIB_SNPRINTF = @GNULIB_SNPRINTF@
-GNULIB_SPRINTF_POSIX = @GNULIB_SPRINTF_POSIX@
-GNULIB_STAT = @GNULIB_STAT@
-GNULIB_STDIO_H_NONBLOCKING = @GNULIB_STDIO_H_NONBLOCKING@
-GNULIB_STDIO_H_SIGPIPE = @GNULIB_STDIO_H_SIGPIPE@
-GNULIB_STPCPY = @GNULIB_STPCPY@
-GNULIB_STPNCPY = @GNULIB_STPNCPY@
-GNULIB_STRCASESTR = @GNULIB_STRCASESTR@
-GNULIB_STRCHRNUL = @GNULIB_STRCHRNUL@
-GNULIB_STRDUP = @GNULIB_STRDUP@
-GNULIB_STRERROR = @GNULIB_STRERROR@
-GNULIB_STRERROR_R = @GNULIB_STRERROR_R@
-GNULIB_STRFTIME = @GNULIB_STRFTIME@
-GNULIB_STRNCAT = @GNULIB_STRNCAT@
-GNULIB_STRNDUP = @GNULIB_STRNDUP@
-GNULIB_STRNLEN = @GNULIB_STRNLEN@
-GNULIB_STRPBRK = @GNULIB_STRPBRK@
-GNULIB_STRPTIME = @GNULIB_STRPTIME@
-GNULIB_STRSEP = @GNULIB_STRSEP@
-GNULIB_STRSIGNAL = @GNULIB_STRSIGNAL@
-GNULIB_STRSTR = @GNULIB_STRSTR@
-GNULIB_STRTOD = @GNULIB_STRTOD@
-GNULIB_STRTOIMAX = @GNULIB_STRTOIMAX@
-GNULIB_STRTOK_R = @GNULIB_STRTOK_R@
-GNULIB_STRTOLL = @GNULIB_STRTOLL@
-GNULIB_STRTOULL = @GNULIB_STRTOULL@
-GNULIB_STRTOUMAX = @GNULIB_STRTOUMAX@
-GNULIB_STRVERSCMP = @GNULIB_STRVERSCMP@
-GNULIB_SYMLINK = @GNULIB_SYMLINK@
-GNULIB_SYMLINKAT = @GNULIB_SYMLINKAT@
-GNULIB_SYSTEM_POSIX = @GNULIB_SYSTEM_POSIX@
-GNULIB_TIMEGM = @GNULIB_TIMEGM@
-GNULIB_TIME_R = @GNULIB_TIME_R@
-GNULIB_TIME_RZ = @GNULIB_TIME_RZ@
-GNULIB_TMPFILE = @GNULIB_TMPFILE@
-GNULIB_TRUNCATE = @GNULIB_TRUNCATE@
-GNULIB_TTYNAME_R = @GNULIB_TTYNAME_R@
-GNULIB_TZSET = @GNULIB_TZSET@
-GNULIB_UNISTD_H_NONBLOCKING = @GNULIB_UNISTD_H_NONBLOCKING@
-GNULIB_UNISTD_H_SIGPIPE = @GNULIB_UNISTD_H_SIGPIPE@
-GNULIB_UNLINK = @GNULIB_UNLINK@
-GNULIB_UNLINKAT = @GNULIB_UNLINKAT@
-GNULIB_UNLOCKPT = @GNULIB_UNLOCKPT@
-GNULIB_UNSETENV = @GNULIB_UNSETENV@
-GNULIB_USLEEP = @GNULIB_USLEEP@
-GNULIB_UTIMENSAT = @GNULIB_UTIMENSAT@
-GNULIB_VASPRINTF = @GNULIB_VASPRINTF@
-GNULIB_VDPRINTF = @GNULIB_VDPRINTF@
-GNULIB_VFPRINTF = @GNULIB_VFPRINTF@
-GNULIB_VFPRINTF_POSIX = @GNULIB_VFPRINTF_POSIX@
-GNULIB_VFSCANF = @GNULIB_VFSCANF@
-GNULIB_VPRINTF = @GNULIB_VPRINTF@
-GNULIB_VPRINTF_POSIX = @GNULIB_VPRINTF_POSIX@
-GNULIB_VSCANF = @GNULIB_VSCANF@
-GNULIB_VSNPRINTF = @GNULIB_VSNPRINTF@
-GNULIB_VSPRINTF_POSIX = @GNULIB_VSPRINTF_POSIX@
GNULIB_WARN_CFLAGS = @GNULIB_WARN_CFLAGS@
-GNULIB_WCTOMB = @GNULIB_WCTOMB@
-GNULIB_WRITE = @GNULIB_WRITE@
-GNULIB__EXIT = @GNULIB__EXIT@
GNUSTEP_CFLAGS = @GNUSTEP_CFLAGS@
GNU_OBJC_CFLAGS = @GNU_OBJC_CFLAGS@
GOBJECT_CFLAGS = @GOBJECT_CFLAGS@
@@ -345,20 +633,35 @@ GTK_CFLAGS = @GTK_CFLAGS@
GTK_LIBS = @GTK_LIBS@
GTK_OBJ = @GTK_OBJ@
GZIP_PROG = @GZIP_PROG@
+HAIKU_CFLAGS = @HAIKU_CFLAGS@
+HAIKU_CXX_OBJ = @HAIKU_CXX_OBJ@
+HAIKU_LIBS = @HAIKU_LIBS@
+HAIKU_OBJ = @HAIKU_OBJ@
+HARFBUZZ_CFLAGS = @HARFBUZZ_CFLAGS@
+HARFBUZZ_LIBS = @HARFBUZZ_LIBS@
+HAVE_ALIGNED_ALLOC = @HAVE_ALIGNED_ALLOC@
+HAVE_ALLOCA_H = @HAVE_ALLOCA_H@
HAVE_ALPHASORT = @HAVE_ALPHASORT@
HAVE_ATOLL = @HAVE_ATOLL@
+HAVE_BE_APP = @HAVE_BE_APP@
HAVE_C99_STDINT_H = @HAVE_C99_STDINT_H@
HAVE_CANONICALIZE_FILE_NAME = @HAVE_CANONICALIZE_FILE_NAME@
HAVE_CHOWN = @HAVE_CHOWN@
HAVE_CLOSEDIR = @HAVE_CLOSEDIR@
+HAVE_COPY_FILE_RANGE = @HAVE_COPY_FILE_RANGE@
HAVE_DECL_DIRFD = @HAVE_DECL_DIRFD@
+HAVE_DECL_ECVT = @HAVE_DECL_ECVT@
HAVE_DECL_ENVIRON = @HAVE_DECL_ENVIRON@
+HAVE_DECL_EXECVPE = @HAVE_DECL_EXECVPE@
HAVE_DECL_FCHDIR = @HAVE_DECL_FCHDIR@
+HAVE_DECL_FCLOSEALL = @HAVE_DECL_FCLOSEALL@
+HAVE_DECL_FCVT = @HAVE_DECL_FCVT@
HAVE_DECL_FDATASYNC = @HAVE_DECL_FDATASYNC@
HAVE_DECL_FDOPENDIR = @HAVE_DECL_FDOPENDIR@
HAVE_DECL_FPURGE = @HAVE_DECL_FPURGE@
HAVE_DECL_FSEEKO = @HAVE_DECL_FSEEKO@
HAVE_DECL_FTELLO = @HAVE_DECL_FTELLO@
+HAVE_DECL_GCVT = @HAVE_DECL_GCVT@
HAVE_DECL_GETDELIM = @HAVE_DECL_GETDELIM@
HAVE_DECL_GETDOMAINNAME = @HAVE_DECL_GETDOMAINNAME@
HAVE_DECL_GETLINE = @HAVE_DECL_GETLINE@
@@ -374,6 +677,7 @@ HAVE_DECL_LOCALTIME_R = @HAVE_DECL_LOCALTIME_R@
HAVE_DECL_MEMMEM = @HAVE_DECL_MEMMEM@
HAVE_DECL_MEMRCHR = @HAVE_DECL_MEMRCHR@
HAVE_DECL_OBSTACK_PRINTF = @HAVE_DECL_OBSTACK_PRINTF@
+HAVE_DECL_POSIX_SPAWN_SETSID = @HAVE_DECL_POSIX_SPAWN_SETSID@
HAVE_DECL_SETENV = @HAVE_DECL_SETENV@
HAVE_DECL_SETHOSTNAME = @HAVE_DECL_SETHOSTNAME@
HAVE_DECL_SETSTATE = @HAVE_DECL_SETSTATE@
@@ -386,14 +690,15 @@ HAVE_DECL_STRSIGNAL = @HAVE_DECL_STRSIGNAL@
HAVE_DECL_STRTOIMAX = @HAVE_DECL_STRTOIMAX@
HAVE_DECL_STRTOK_R = @HAVE_DECL_STRTOK_R@
HAVE_DECL_STRTOUMAX = @HAVE_DECL_STRTOUMAX@
+HAVE_DECL_TRUNCATE = @HAVE_DECL_TRUNCATE@
HAVE_DECL_TTYNAME_R = @HAVE_DECL_TTYNAME_R@
HAVE_DECL_UNSETENV = @HAVE_DECL_UNSETENV@
HAVE_DECL_VSNPRINTF = @HAVE_DECL_VSNPRINTF@
HAVE_DIRENT_H = @HAVE_DIRENT_H@
HAVE_DPRINTF = @HAVE_DPRINTF@
-HAVE_DUP2 = @HAVE_DUP2@
HAVE_DUP3 = @HAVE_DUP3@
HAVE_EUIDACCESS = @HAVE_EUIDACCESS@
+HAVE_EXECVPE = @HAVE_EXECVPE@
HAVE_EXPLICIT_BZERO = @HAVE_EXPLICIT_BZERO@
HAVE_FACCESSAT = @HAVE_FACCESSAT@
HAVE_FCHDIR = @HAVE_FCHDIR@
@@ -411,26 +716,34 @@ HAVE_FTELLO = @HAVE_FTELLO@
HAVE_FTRUNCATE = @HAVE_FTRUNCATE@
HAVE_FUTIMENS = @HAVE_FUTIMENS@
HAVE_GETDTABLESIZE = @HAVE_GETDTABLESIZE@
+HAVE_GETENTROPY = @HAVE_GETENTROPY@
HAVE_GETGROUPS = @HAVE_GETGROUPS@
HAVE_GETHOSTNAME = @HAVE_GETHOSTNAME@
HAVE_GETLOGIN = @HAVE_GETLOGIN@
HAVE_GETOPT_H = @HAVE_GETOPT_H@
HAVE_GETPAGESIZE = @HAVE_GETPAGESIZE@
+HAVE_GETPASS = @HAVE_GETPASS@
+HAVE_GETRANDOM = @HAVE_GETRANDOM@
HAVE_GETSUBOPT = @HAVE_GETSUBOPT@
HAVE_GETTIMEOFDAY = @HAVE_GETTIMEOFDAY@
+HAVE_GETUMASK = @HAVE_GETUMASK@
HAVE_GRANTPT = @HAVE_GRANTPT@
HAVE_GROUP_MEMBER = @HAVE_GROUP_MEMBER@
+HAVE_GSETTINGS = @HAVE_GSETTINGS@
+HAVE_IMAXDIV_T = @HAVE_IMAXDIV_T@
+HAVE_INITSTATE = @HAVE_INITSTATE@
HAVE_INTTYPES_H = @HAVE_INTTYPES_H@
HAVE_LCHMOD = @HAVE_LCHMOD@
HAVE_LCHOWN = @HAVE_LCHOWN@
+HAVE_LIBGMP = @HAVE_LIBGMP@
+HAVE_LIBSECCOMP = @HAVE_LIBSECCOMP@
HAVE_LINK = @HAVE_LINK@
HAVE_LINKAT = @HAVE_LINKAT@
-HAVE_LONG_LONG_INT = @HAVE_LONG_LONG_INT@
HAVE_LSTAT = @HAVE_LSTAT@
-HAVE_MAKEINFO = @HAVE_MAKEINFO@
+HAVE_MACPORTS = @HAVE_MACPORTS@
HAVE_MAX_ALIGN_T = @HAVE_MAX_ALIGN_T@
HAVE_MBSLEN = @HAVE_MBSLEN@
-HAVE_MEMCHR = @HAVE_MEMCHR@
+HAVE_MBTOWC = @HAVE_MBTOWC@
HAVE_MEMPCPY = @HAVE_MEMPCPY@
HAVE_MKDIRAT = @HAVE_MKDIRAT@
HAVE_MKDTEMP = @HAVE_MKDTEMP@
@@ -444,15 +757,23 @@ HAVE_MKSTEMP = @HAVE_MKSTEMP@
HAVE_MKSTEMPS = @HAVE_MKSTEMPS@
HAVE_MODULES = @HAVE_MODULES@
HAVE_NANOSLEEP = @HAVE_NANOSLEEP@
+HAVE_NATIVE_COMP = @HAVE_NATIVE_COMP@
HAVE_OPENAT = @HAVE_OPENAT@
HAVE_OPENDIR = @HAVE_OPENDIR@
HAVE_OS_H = @HAVE_OS_H@
HAVE_PCLOSE = @HAVE_PCLOSE@
+HAVE_PDUMPER = @HAVE_PDUMPER@
+HAVE_PGTK = @HAVE_PGTK@
HAVE_PIPE = @HAVE_PIPE@
HAVE_PIPE2 = @HAVE_PIPE2@
HAVE_POPEN = @HAVE_POPEN@
+HAVE_POSIX_MEMALIGN = @HAVE_POSIX_MEMALIGN@
HAVE_POSIX_OPENPT = @HAVE_POSIX_OPENPT@
HAVE_POSIX_SIGNALBLOCKING = @HAVE_POSIX_SIGNALBLOCKING@
+HAVE_POSIX_SPAWN = @HAVE_POSIX_SPAWN@
+HAVE_POSIX_SPAWNATTR_SETFLAGS = @HAVE_POSIX_SPAWNATTR_SETFLAGS@
+HAVE_POSIX_SPAWN_FILE_ACTIONS_ADDCHDIR = @HAVE_POSIX_SPAWN_FILE_ACTIONS_ADDCHDIR@
+HAVE_POSIX_SPAWN_FILE_ACTIONS_ADDCHDIR_NP = @HAVE_POSIX_SPAWN_FILE_ACTIONS_ADDCHDIR_NP@
HAVE_PREAD = @HAVE_PREAD@
HAVE_PSELECT = @HAVE_PSELECT@
HAVE_PTHREAD_SIGMASK = @HAVE_PTHREAD_SIGMASK@
@@ -474,10 +795,14 @@ HAVE_RENAMEAT = @HAVE_RENAMEAT@
HAVE_REWINDDIR = @HAVE_REWINDDIR@
HAVE_RPMATCH = @HAVE_RPMATCH@
HAVE_SCANDIR = @HAVE_SCANDIR@
+HAVE_SECCOMP = @HAVE_SECCOMP@
HAVE_SECURE_GETENV = @HAVE_SECURE_GETENV@
HAVE_SETENV = @HAVE_SETENV@
HAVE_SETHOSTNAME = @HAVE_SETHOSTNAME@
+HAVE_SETSTATE = @HAVE_SETSTATE@
+HAVE_SIGABBREV_NP = @HAVE_SIGABBREV_NP@
HAVE_SIGACTION = @HAVE_SIGACTION@
+HAVE_SIGDESCR_NP = @HAVE_SIGDESCR_NP@
HAVE_SIGHANDLER_T = @HAVE_SIGHANDLER_T@
HAVE_SIGINFO_T = @HAVE_SIGINFO_T@
HAVE_SIGNED_SIG_ATOMIC_T = @HAVE_SIGNED_SIG_ATOMIC_T@
@@ -485,16 +810,21 @@ HAVE_SIGNED_WCHAR_T = @HAVE_SIGNED_WCHAR_T@
HAVE_SIGNED_WINT_T = @HAVE_SIGNED_WINT_T@
HAVE_SIGSET_T = @HAVE_SIGSET_T@
HAVE_SLEEP = @HAVE_SLEEP@
+HAVE_SPAWN_H = @HAVE_SPAWN_H@
HAVE_STDINT_H = @HAVE_STDINT_H@
HAVE_STPCPY = @HAVE_STPCPY@
HAVE_STPNCPY = @HAVE_STPNCPY@
HAVE_STRCASESTR = @HAVE_STRCASESTR@
HAVE_STRCHRNUL = @HAVE_STRCHRNUL@
+HAVE_STRERRORNAME_NP = @HAVE_STRERRORNAME_NP@
HAVE_STRPBRK = @HAVE_STRPBRK@
HAVE_STRPTIME = @HAVE_STRPTIME@
HAVE_STRSEP = @HAVE_STRSEP@
HAVE_STRTOD = @HAVE_STRTOD@
+HAVE_STRTOL = @HAVE_STRTOL@
+HAVE_STRTOLD = @HAVE_STRTOLD@
HAVE_STRTOLL = @HAVE_STRTOLL@
+HAVE_STRTOUL = @HAVE_STRTOUL@
HAVE_STRTOULL = @HAVE_STRTOULL@
HAVE_STRUCT_RANDOM_DATA = @HAVE_STRUCT_RANDOM_DATA@
HAVE_STRUCT_SIGACTION_SA_SIGACTION = @HAVE_STRUCT_SIGACTION_SA_SIGACTION@
@@ -507,18 +837,18 @@ HAVE_SYS_CDEFS_H = @HAVE_SYS_CDEFS_H@
HAVE_SYS_INTTYPES_H = @HAVE_SYS_INTTYPES_H@
HAVE_SYS_LOADAVG_H = @HAVE_SYS_LOADAVG_H@
HAVE_SYS_PARAM_H = @HAVE_SYS_PARAM_H@
+HAVE_SYS_RANDOM_H = @HAVE_SYS_RANDOM_H@
HAVE_SYS_SELECT_H = @HAVE_SYS_SELECT_H@
HAVE_SYS_TIME_H = @HAVE_SYS_TIME_H@
HAVE_SYS_TYPES_H = @HAVE_SYS_TYPES_H@
HAVE_TIMEGM = @HAVE_TIMEGM@
+HAVE_TIMESPEC_GET = @HAVE_TIMESPEC_GET@
+HAVE_TIMESPEC_GETRES = @HAVE_TIMESPEC_GETRES@
HAVE_TIMEZONE_T = @HAVE_TIMEZONE_T@
-HAVE_TRUNCATE = @HAVE_TRUNCATE@
HAVE_TYPE_VOLATILE_SIG_ATOMIC_T = @HAVE_TYPE_VOLATILE_SIG_ATOMIC_T@
-HAVE_TZSET = @HAVE_TZSET@
HAVE_UNISTD_H = @HAVE_UNISTD_H@
HAVE_UNLINKAT = @HAVE_UNLINKAT@
HAVE_UNLOCKPT = @HAVE_UNLOCKPT@
-HAVE_UNSIGNED_LONG_LONG_INT = @HAVE_UNSIGNED_LONG_LONG_INT@
HAVE_USLEEP = @HAVE_USLEEP@
HAVE_UTIMENSAT = @HAVE_UTIMENSAT@
HAVE_VASPRINTF = @HAVE_VASPRINTF@
@@ -529,6 +859,7 @@ HAVE_WINSOCK2_H = @HAVE_WINSOCK2_H@
HAVE_XSERVER = @HAVE_XSERVER@
HAVE__EXIT = @HAVE__EXIT@
HYBRID_MALLOC = @HYBRID_MALLOC@
+IEEE754_H = @IEEE754_H@
IMAGEMAGICK_CFLAGS = @IMAGEMAGICK_CFLAGS@
IMAGEMAGICK_LIBS = @IMAGEMAGICK_LIBS@
INCLUDE_NEXT = @INCLUDE_NEXT@
@@ -540,16 +871,24 @@ INSTALL_PROGRAM = @INSTALL_PROGRAM@
INSTALL_SCRIPT = @INSTALL_SCRIPT@
INT32_MAX_LT_INTMAX_MAX = @INT32_MAX_LT_INTMAX_MAX@
INT64_MAX_EQ_LONG_MAX = @INT64_MAX_EQ_LONG_MAX@
+JSON_CFLAGS = @JSON_CFLAGS@
+JSON_LIBS = @JSON_LIBS@
+JSON_OBJ = @JSON_OBJ@
KQUEUE_CFLAGS = @KQUEUE_CFLAGS@
KQUEUE_LIBS = @KQUEUE_LIBS@
KRB4LIB = @KRB4LIB@
KRB5LIB = @KRB5LIB@
+LCMS2_CFLAGS = @LCMS2_CFLAGS@
+LCMS2_LIBS = @LCMS2_LIBS@
LDFLAGS = @LDFLAGS@
LD_SWITCH_SYSTEM = @LD_SWITCH_SYSTEM@
LD_SWITCH_SYSTEM_TEMACS = @LD_SWITCH_SYSTEM_TEMACS@
LD_SWITCH_X_SITE = @LD_SWITCH_X_SITE@
LD_SWITCH_X_SITE_RPATH = @LD_SWITCH_X_SITE_RPATH@
+LIBGCCJIT_CFLAGS = @LIBGCCJIT_CFLAGS@
+LIBGCCJIT_LIBS = @LIBGCCJIT_LIBS@
LIBGIF = @LIBGIF@
+LIBGMP = @LIBGMP@
LIBGNUTLS_CFLAGS = @LIBGNUTLS_CFLAGS@
LIBGNUTLS_LIBS = @LIBGNUTLS_LIBS@
LIBGNU_LIBDEPS = @LIBGNU_LIBDEPS@
@@ -558,7 +897,6 @@ LIBGPM = @LIBGPM@
LIBHESIOD = @LIBHESIOD@
LIBINTL = @LIBINTL@
LIBJPEG = @LIBJPEG@
-LIBLCMS2 = @LIBLCMS2@
LIBMODULES = @LIBMODULES@
LIBOBJS = @LIBOBJS@
LIBOTF_CFLAGS = @LIBOTF_CFLAGS@
@@ -566,6 +904,8 @@ LIBOTF_LIBS = @LIBOTF_LIBS@
LIBPNG = @LIBPNG@
LIBRESOLV = @LIBRESOLV@
LIBS = @LIBS@
+LIBSECCOMP_CFLAGS = @LIBSECCOMP_CFLAGS@
+LIBSECCOMP_LIBS = @LIBSECCOMP_LIBS@
LIBSELINUX_LIBS = @LIBSELINUX_LIBS@
LIBSOUND = @LIBSOUND@
LIBSYSTEMD_CFLAGS = @LIBSYSTEMD_CFLAGS@
@@ -590,14 +930,17 @@ LIB_ACL = @LIB_ACL@
LIB_CLOCK_GETTIME = @LIB_CLOCK_GETTIME@
LIB_EACCESS = @LIB_EACCESS@
LIB_EXECINFO = @LIB_EXECINFO@
-LIB_FDATASYNC = @LIB_FDATASYNC@
+LIB_GETRANDOM = @LIB_GETRANDOM@
+LIB_HAS_ACL = @LIB_HAS_ACL@
LIB_MATH = @LIB_MATH@
+LIB_NANOSLEEP = @LIB_NANOSLEEP@
LIB_PTHREAD = @LIB_PTHREAD@
LIB_PTHREAD_SIGMASK = @LIB_PTHREAD_SIGMASK@
LIB_TIMER_TIME = @LIB_TIMER_TIME@
LIB_WSOCK32 = @LIB_WSOCK32@
LIMITS_H = @LIMITS_H@
LN_S_FILEONLY = @LN_S_FILEONLY@
+LTLIBGMP = @LTLIBGMP@
LTLIBINTL = @LTLIBINTL@
LTLIBOBJS = @LTLIBOBJS@
M17N_FLT_CFLAGS = @M17N_FLT_CFLAGS@
@@ -606,6 +949,7 @@ MAKEINFO = @MAKEINFO@
MAKE_PROG = @MAKE_PROG@
MKDIR_P = @MKDIR_P@
MODULES_OBJ = @MODULES_OBJ@
+MODULES_SECONDARY_SUFFIX = @MODULES_SECONDARY_SUFFIX@
MODULES_SUFFIX = @MODULES_SUFFIX@
NEXT_AS_FIRST_DIRECTIVE_DIRENT_H = @NEXT_AS_FIRST_DIRECTIVE_DIRENT_H@
NEXT_AS_FIRST_DIRECTIVE_ERRNO_H = @NEXT_AS_FIRST_DIRECTIVE_ERRNO_H@
@@ -619,6 +963,7 @@ NEXT_AS_FIRST_DIRECTIVE_STDINT_H = @NEXT_AS_FIRST_DIRECTIVE_STDINT_H@
NEXT_AS_FIRST_DIRECTIVE_STDIO_H = @NEXT_AS_FIRST_DIRECTIVE_STDIO_H@
NEXT_AS_FIRST_DIRECTIVE_STDLIB_H = @NEXT_AS_FIRST_DIRECTIVE_STDLIB_H@
NEXT_AS_FIRST_DIRECTIVE_STRING_H = @NEXT_AS_FIRST_DIRECTIVE_STRING_H@
+NEXT_AS_FIRST_DIRECTIVE_SYS_RANDOM_H = @NEXT_AS_FIRST_DIRECTIVE_SYS_RANDOM_H@
NEXT_AS_FIRST_DIRECTIVE_SYS_SELECT_H = @NEXT_AS_FIRST_DIRECTIVE_SYS_SELECT_H@
NEXT_AS_FIRST_DIRECTIVE_SYS_STAT_H = @NEXT_AS_FIRST_DIRECTIVE_SYS_STAT_H@
NEXT_AS_FIRST_DIRECTIVE_SYS_TIME_H = @NEXT_AS_FIRST_DIRECTIVE_SYS_TIME_H@
@@ -637,6 +982,7 @@ NEXT_STDINT_H = @NEXT_STDINT_H@
NEXT_STDIO_H = @NEXT_STDIO_H@
NEXT_STDLIB_H = @NEXT_STDLIB_H@
NEXT_STRING_H = @NEXT_STRING_H@
+NEXT_SYS_RANDOM_H = @NEXT_SYS_RANDOM_H@
NEXT_SYS_SELECT_H = @NEXT_SYS_SELECT_H@
NEXT_SYS_STAT_H = @NEXT_SYS_STAT_H@
NEXT_SYS_TIME_H = @NEXT_SYS_TIME_H@
@@ -664,40 +1010,60 @@ PATH_SEPARATOR = @PATH_SEPARATOR@
PAXCTL = @PAXCTL@
PAXCTL_dumped = @PAXCTL_dumped@
PAXCTL_notdumped = @PAXCTL_notdumped@
+PGTK_LIBS = @PGTK_LIBS@
+PGTK_OBJ = @PGTK_OBJ@
PKG_CONFIG = @PKG_CONFIG@
PKG_CONFIG_LIBDIR = @PKG_CONFIG_LIBDIR@
PKG_CONFIG_PATH = @PKG_CONFIG_PATH@
PNG_CFLAGS = @PNG_CFLAGS@
+PNG_LIBS = @PNG_LIBS@
POST_ALLOC_OBJ = @POST_ALLOC_OBJ@
PRAGMA_COLUMNS = @PRAGMA_COLUMNS@
PRAGMA_SYSTEM_HEADER = @PRAGMA_SYSTEM_HEADER@
PRE_ALLOC_OBJ = @PRE_ALLOC_OBJ@
PRIPTR_PREFIX = @PRIPTR_PREFIX@
-PRI_MACROS_BROKEN = @PRI_MACROS_BROKEN@
PROFILING_CFLAGS = @PROFILING_CFLAGS@
PTHREAD_H_DEFINES_STRUCT_TIMESPEC = @PTHREAD_H_DEFINES_STRUCT_TIMESPEC@
PTRDIFF_T_SUFFIX = @PTRDIFF_T_SUFFIX@
RALLOC_OBJ = @RALLOC_OBJ@
RANLIB = @RANLIB@
-REPLACE_CALLOC = @REPLACE_CALLOC@
+REPLACE_ACCESS = @REPLACE_ACCESS@
+REPLACE_ALIGNED_ALLOC = @REPLACE_ALIGNED_ALLOC@
+REPLACE_CALLOC_FOR_CALLOC_GNU = @REPLACE_CALLOC_FOR_CALLOC_GNU@
+REPLACE_CALLOC_FOR_CALLOC_POSIX = @REPLACE_CALLOC_FOR_CALLOC_POSIX@
REPLACE_CANONICALIZE_FILE_NAME = @REPLACE_CANONICALIZE_FILE_NAME@
+REPLACE_CHMOD = @REPLACE_CHMOD@
REPLACE_CHOWN = @REPLACE_CHOWN@
REPLACE_CLOSE = @REPLACE_CLOSE@
REPLACE_CLOSEDIR = @REPLACE_CLOSEDIR@
+REPLACE_COPY_FILE_RANGE = @REPLACE_COPY_FILE_RANGE@
+REPLACE_CREAT = @REPLACE_CREAT@
REPLACE_CTIME = @REPLACE_CTIME@
REPLACE_DIRFD = @REPLACE_DIRFD@
REPLACE_DPRINTF = @REPLACE_DPRINTF@
REPLACE_DUP = @REPLACE_DUP@
REPLACE_DUP2 = @REPLACE_DUP2@
+REPLACE_EXECL = @REPLACE_EXECL@
+REPLACE_EXECLE = @REPLACE_EXECLE@
+REPLACE_EXECLP = @REPLACE_EXECLP@
+REPLACE_EXECV = @REPLACE_EXECV@
+REPLACE_EXECVE = @REPLACE_EXECVE@
+REPLACE_EXECVP = @REPLACE_EXECVP@
+REPLACE_EXECVPE = @REPLACE_EXECVPE@
+REPLACE_FACCESSAT = @REPLACE_FACCESSAT@
+REPLACE_FCHMODAT = @REPLACE_FCHMODAT@
REPLACE_FCHOWNAT = @REPLACE_FCHOWNAT@
REPLACE_FCLOSE = @REPLACE_FCLOSE@
REPLACE_FCNTL = @REPLACE_FCNTL@
REPLACE_FDOPEN = @REPLACE_FDOPEN@
REPLACE_FDOPENDIR = @REPLACE_FDOPENDIR@
REPLACE_FFLUSH = @REPLACE_FFLUSH@
+REPLACE_FFSLL = @REPLACE_FFSLL@
REPLACE_FOPEN = @REPLACE_FOPEN@
+REPLACE_FOPEN_FOR_FOPEN_GNU = @REPLACE_FOPEN_FOR_FOPEN_GNU@
REPLACE_FPRINTF = @REPLACE_FPRINTF@
REPLACE_FPURGE = @REPLACE_FPURGE@
+REPLACE_FREE = @REPLACE_FREE@
REPLACE_FREOPEN = @REPLACE_FREOPEN@
REPLACE_FSEEK = @REPLACE_FSEEK@
REPLACE_FSEEKO = @REPLACE_FSEEKO@
@@ -715,8 +1081,12 @@ REPLACE_GETGROUPS = @REPLACE_GETGROUPS@
REPLACE_GETLINE = @REPLACE_GETLINE@
REPLACE_GETLOGIN_R = @REPLACE_GETLOGIN_R@
REPLACE_GETPAGESIZE = @REPLACE_GETPAGESIZE@
+REPLACE_GETPASS = @REPLACE_GETPASS@
+REPLACE_GETPASS_FOR_GETPASS_GNU = @REPLACE_GETPASS_FOR_GETPASS_GNU@
+REPLACE_GETRANDOM = @REPLACE_GETRANDOM@
REPLACE_GETTIMEOFDAY = @REPLACE_GETTIMEOFDAY@
REPLACE_GMTIME = @REPLACE_GMTIME@
+REPLACE_INITSTATE = @REPLACE_INITSTATE@
REPLACE_ISATTY = @REPLACE_ISATTY@
REPLACE_LCHOWN = @REPLACE_LCHOWN@
REPLACE_LINK = @REPLACE_LINK@
@@ -725,13 +1095,16 @@ REPLACE_LOCALTIME = @REPLACE_LOCALTIME@
REPLACE_LOCALTIME_R = @REPLACE_LOCALTIME_R@
REPLACE_LSEEK = @REPLACE_LSEEK@
REPLACE_LSTAT = @REPLACE_LSTAT@
-REPLACE_MALLOC = @REPLACE_MALLOC@
+REPLACE_MALLOC_FOR_MALLOC_GNU = @REPLACE_MALLOC_FOR_MALLOC_GNU@
+REPLACE_MALLOC_FOR_MALLOC_POSIX = @REPLACE_MALLOC_FOR_MALLOC_POSIX@
REPLACE_MBTOWC = @REPLACE_MBTOWC@
REPLACE_MEMCHR = @REPLACE_MEMCHR@
REPLACE_MEMMEM = @REPLACE_MEMMEM@
REPLACE_MKDIR = @REPLACE_MKDIR@
REPLACE_MKFIFO = @REPLACE_MKFIFO@
+REPLACE_MKFIFOAT = @REPLACE_MKFIFOAT@
REPLACE_MKNOD = @REPLACE_MKNOD@
+REPLACE_MKNODAT = @REPLACE_MKNODAT@
REPLACE_MKSTEMP = @REPLACE_MKSTEMP@
REPLACE_MKTIME = @REPLACE_MKTIME@
REPLACE_NANOSLEEP = @REPLACE_NANOSLEEP@
@@ -742,6 +1115,7 @@ REPLACE_OPENAT = @REPLACE_OPENAT@
REPLACE_OPENDIR = @REPLACE_OPENDIR@
REPLACE_PERROR = @REPLACE_PERROR@
REPLACE_POPEN = @REPLACE_POPEN@
+REPLACE_POSIX_MEMALIGN = @REPLACE_POSIX_MEMALIGN@
REPLACE_PREAD = @REPLACE_PREAD@
REPLACE_PRINTF = @REPLACE_PRINTF@
REPLACE_PSELECT = @REPLACE_PSELECT@
@@ -752,11 +1126,14 @@ REPLACE_PUTENV = @REPLACE_PUTENV@
REPLACE_PWRITE = @REPLACE_PWRITE@
REPLACE_QSORT_R = @REPLACE_QSORT_R@
REPLACE_RAISE = @REPLACE_RAISE@
+REPLACE_RANDOM = @REPLACE_RANDOM@
REPLACE_RANDOM_R = @REPLACE_RANDOM_R@
REPLACE_READ = @REPLACE_READ@
REPLACE_READLINK = @REPLACE_READLINK@
REPLACE_READLINKAT = @REPLACE_READLINKAT@
-REPLACE_REALLOC = @REPLACE_REALLOC@
+REPLACE_REALLOCARRAY = @REPLACE_REALLOCARRAY@
+REPLACE_REALLOC_FOR_REALLOC_GNU = @REPLACE_REALLOC_FOR_REALLOC_GNU@
+REPLACE_REALLOC_FOR_REALLOC_POSIX = @REPLACE_REALLOC_FOR_REALLOC_POSIX@
REPLACE_REALPATH = @REPLACE_REALPATH@
REPLACE_REMOVE = @REPLACE_REMOVE@
REPLACE_RENAME = @REPLACE_RENAME@
@@ -764,6 +1141,7 @@ REPLACE_RENAMEAT = @REPLACE_RENAMEAT@
REPLACE_RMDIR = @REPLACE_RMDIR@
REPLACE_SELECT = @REPLACE_SELECT@
REPLACE_SETENV = @REPLACE_SETENV@
+REPLACE_SETSTATE = @REPLACE_SETSTATE@
REPLACE_SLEEP = @REPLACE_SLEEP@
REPLACE_SNPRINTF = @REPLACE_SNPRINTF@
REPLACE_SPRINTF = @REPLACE_SPRINTF@
@@ -775,6 +1153,7 @@ REPLACE_STRCASESTR = @REPLACE_STRCASESTR@
REPLACE_STRCHRNUL = @REPLACE_STRCHRNUL@
REPLACE_STRDUP = @REPLACE_STRDUP@
REPLACE_STRERROR = @REPLACE_STRERROR@
+REPLACE_STRERRORNAME_NP = @REPLACE_STRERRORNAME_NP@
REPLACE_STRERROR_R = @REPLACE_STRERROR_R@
REPLACE_STRFTIME = @REPLACE_STRFTIME@
REPLACE_STRNCAT = @REPLACE_STRNCAT@
@@ -785,6 +1164,11 @@ REPLACE_STRSTR = @REPLACE_STRSTR@
REPLACE_STRTOD = @REPLACE_STRTOD@
REPLACE_STRTOIMAX = @REPLACE_STRTOIMAX@
REPLACE_STRTOK_R = @REPLACE_STRTOK_R@
+REPLACE_STRTOL = @REPLACE_STRTOL@
+REPLACE_STRTOLD = @REPLACE_STRTOLD@
+REPLACE_STRTOLL = @REPLACE_STRTOLL@
+REPLACE_STRTOUL = @REPLACE_STRTOUL@
+REPLACE_STRTOULL = @REPLACE_STRTOULL@
REPLACE_STRTOUMAX = @REPLACE_STRTOUMAX@
REPLACE_STRUCT_TIMEVAL = @REPLACE_STRUCT_TIMEVAL@
REPLACE_SYMLINK = @REPLACE_SYMLINK@
@@ -815,8 +1199,12 @@ SETTINGS_CFLAGS = @SETTINGS_CFLAGS@
SETTINGS_LIBS = @SETTINGS_LIBS@
SHELL = @SHELL@
SIG_ATOMIC_T_SUFFIX = @SIG_ATOMIC_T_SUFFIX@
+SIZEOF_LONG = @SIZEOF_LONG@
SIZE_T_SUFFIX = @SIZE_T_SUFFIX@
+SMALL_JA_DIC = @SMALL_JA_DIC@
+SQLITE3_LIBS = @SQLITE3_LIBS@
STDALIGN_H = @STDALIGN_H@
+STDCKDINT_H = @STDCKDINT_H@
STDDEF_H = @STDDEF_H@
STDINT_H = @STDINT_H@
SUBDIR_MAKEFILES_IN = @SUBDIR_MAKEFILES_IN@
@@ -824,15 +1212,18 @@ SYSTEM_TYPE = @SYSTEM_TYPE@
SYS_TIME_H_DEFINES_STRUCT_TIMESPEC = @SYS_TIME_H_DEFINES_STRUCT_TIMESPEC@
TERMCAP_OBJ = @TERMCAP_OBJ@
TIME_H_DEFINES_STRUCT_TIMESPEC = @TIME_H_DEFINES_STRUCT_TIMESPEC@
+TIME_H_DEFINES_TIME_UTC = @TIME_H_DEFINES_TIME_UTC@
TOOLKIT_LIBW = @TOOLKIT_LIBW@
UINT32_MAX_LT_UINTMAX_MAX = @UINT32_MAX_LT_UINTMAX_MAX@
UINT64_MAX_EQ_ULONG_MAX = @UINT64_MAX_EQ_ULONG_MAX@
UNDEFINE_STRTOK_R = @UNDEFINE_STRTOK_R@
UNEXEC_OBJ = @UNEXEC_OBJ@
UNISTD_H_DEFINES_STRUCT_TIMESPEC = @UNISTD_H_DEFINES_STRUCT_TIMESPEC@
+UNISTD_H_HAVE_SYS_RANDOM_H = @UNISTD_H_HAVE_SYS_RANDOM_H@
UNISTD_H_HAVE_WINSOCK2_H = @UNISTD_H_HAVE_WINSOCK2_H@
UNISTD_H_HAVE_WINSOCK2_H_AND_USE_SOCKETS = @UNISTD_H_HAVE_WINSOCK2_H_AND_USE_SOCKETS@
USE_ACL = @USE_ACL@
+USE_STARTUP_NOTIFICATION = @USE_STARTUP_NOTIFICATION@
VMLIMIT_OBJ = @VMLIMIT_OBJ@
W32_LIBS = @W32_LIBS@
W32_OBJ = @W32_OBJ@
@@ -841,6 +1232,8 @@ WARN_CFLAGS = @WARN_CFLAGS@
WCHAR_T_SUFFIX = @WCHAR_T_SUFFIX@
WEBKIT_CFLAGS = @WEBKIT_CFLAGS@
WEBKIT_LIBS = @WEBKIT_LIBS@
+WEBP_CFLAGS = @WEBP_CFLAGS@
+WEBP_LIBS = @WEBP_LIBS@
WERROR_CFLAGS = @WERROR_CFLAGS@
WIDGET_OBJ = @WIDGET_OBJ@
WINDOWS_64_BIT_OFF_T = @WINDOWS_64_BIT_OFF_T@
@@ -852,6 +1245,8 @@ WINDRES = @WINDRES@
WINT_T_SUFFIX = @WINT_T_SUFFIX@
XARGS_LIMIT = @XARGS_LIMIT@
XCB_LIBS = @XCB_LIBS@
+XCOMPOSITE_CFLAGS = @XCOMPOSITE_CFLAGS@
+XCOMPOSITE_LIBS = @XCOMPOSITE_LIBS@
XCRUN = @XCRUN@
XDBE_CFLAGS = @XDBE_CFLAGS@
XDBE_LIBS = @XDBE_LIBS@
@@ -862,14 +1257,22 @@ XFT_LIBS = @XFT_LIBS@
XGSELOBJ = @XGSELOBJ@
XINERAMA_CFLAGS = @XINERAMA_CFLAGS@
XINERAMA_LIBS = @XINERAMA_LIBS@
+XINPUT_CFLAGS = @XINPUT_CFLAGS@
+XINPUT_LIBS = @XINPUT_LIBS@
XMENU_OBJ = @XMENU_OBJ@
XMKMF = @XMKMF@
XOBJ = @XOBJ@
XRANDR_CFLAGS = @XRANDR_CFLAGS@
XRANDR_LIBS = @XRANDR_LIBS@
+XRENDER_LIBS = @XRENDER_LIBS@
+XSHAPE_CFLAGS = @XSHAPE_CFLAGS@
+XSHAPE_LIBS = @XSHAPE_LIBS@
+XSYNC_CFLAGS = @XSYNC_CFLAGS@
+XSYNC_LIBS = @XSYNC_LIBS@
XWIDGETS_OBJ = @XWIDGETS_OBJ@
X_TOOLKIT_TYPE = @X_TOOLKIT_TYPE@
ac_ct_CC = @ac_ct_CC@
+ac_ct_CXX = @ac_ct_CXX@
ac_ct_OBJC = @ac_ct_OBJC@
archlibdir = @archlibdir@
bindir = @bindir@
@@ -889,33 +1292,46 @@ datadir = @datadir@
datarootdir = @datarootdir@
docdir = @docdir@
dvidir = @dvidir@
+emacs_major_version = @emacs_major_version@
etcdir = @etcdir@
etcdocdir = @etcdocdir@
exec_prefix = @exec_prefix@
gamedir = @gamedir@
gamegroup = @gamegroup@
gameuser = @gameuser@
-gl_GNULIB_ENABLED_03e0aaad4cb89ca757653bd367a6ccb7 = @gl_GNULIB_ENABLED_03e0aaad4cb89ca757653bd367a6ccb7@
-gl_GNULIB_ENABLED_2049e887c7e5308faad27b3f894bb8c9 = @gl_GNULIB_ENABLED_2049e887c7e5308faad27b3f894bb8c9@
-gl_GNULIB_ENABLED_260941c0e5dc67ec9e87d1fb321c300b = @gl_GNULIB_ENABLED_260941c0e5dc67ec9e87d1fb321c300b@
-gl_GNULIB_ENABLED_5264294aa0a5557541b53c8c741f7f31 = @gl_GNULIB_ENABLED_5264294aa0a5557541b53c8c741f7f31@
-gl_GNULIB_ENABLED_6099e9737f757db36c47fa9d9f02e88c = @gl_GNULIB_ENABLED_6099e9737f757db36c47fa9d9f02e88c@
-gl_GNULIB_ENABLED_682e609604ccaac6be382e4ee3a4eaec = @gl_GNULIB_ENABLED_682e609604ccaac6be382e4ee3a4eaec@
-gl_GNULIB_ENABLED_a9786850e999ae65a836a6041e8e5ed1 = @gl_GNULIB_ENABLED_a9786850e999ae65a836a6041e8e5ed1@
-gl_GNULIB_ENABLED_be453cec5eecf5731a274f2de7f2db36 = @gl_GNULIB_ENABLED_be453cec5eecf5731a274f2de7f2db36@
-gl_GNULIB_ENABLED_cloexec = @gl_GNULIB_ENABLED_cloexec@
-gl_GNULIB_ENABLED_dirfd = @gl_GNULIB_ENABLED_dirfd@
-gl_GNULIB_ENABLED_dosname = @gl_GNULIB_ENABLED_dosname@
-gl_GNULIB_ENABLED_euidaccess = @gl_GNULIB_ENABLED_euidaccess@
-gl_GNULIB_ENABLED_getdtablesize = @gl_GNULIB_ENABLED_getdtablesize@
-gl_GNULIB_ENABLED_getgroups = @gl_GNULIB_ENABLED_getgroups@
-gl_GNULIB_ENABLED_open = @gl_GNULIB_ENABLED_open@
-gl_GNULIB_ENABLED_strtoll = @gl_GNULIB_ENABLED_strtoll@
+gl_GNULIB_ENABLED_03e0aaad4cb89ca757653bd367a6ccb7_CONDITION = @gl_GNULIB_ENABLED_03e0aaad4cb89ca757653bd367a6ccb7_CONDITION@
+gl_GNULIB_ENABLED_260941c0e5dc67ec9e87d1fb321c300b_CONDITION = @gl_GNULIB_ENABLED_260941c0e5dc67ec9e87d1fb321c300b_CONDITION@
+gl_GNULIB_ENABLED_5264294aa0a5557541b53c8c741f7f31_CONDITION = @gl_GNULIB_ENABLED_5264294aa0a5557541b53c8c741f7f31_CONDITION@
+gl_GNULIB_ENABLED_6099e9737f757db36c47fa9d9f02e88c_CONDITION = @gl_GNULIB_ENABLED_6099e9737f757db36c47fa9d9f02e88c_CONDITION@
+gl_GNULIB_ENABLED_61bcaca76b3e6f9ae55d57a1c3193bc4_CONDITION = @gl_GNULIB_ENABLED_61bcaca76b3e6f9ae55d57a1c3193bc4_CONDITION@
+gl_GNULIB_ENABLED_682e609604ccaac6be382e4ee3a4eaec_CONDITION = @gl_GNULIB_ENABLED_682e609604ccaac6be382e4ee3a4eaec_CONDITION@
+gl_GNULIB_ENABLED_925677f0343de64b89a9f0c790b4104c_CONDITION = @gl_GNULIB_ENABLED_925677f0343de64b89a9f0c790b4104c_CONDITION@
+gl_GNULIB_ENABLED_a9786850e999ae65a836a6041e8e5ed1_CONDITION = @gl_GNULIB_ENABLED_a9786850e999ae65a836a6041e8e5ed1_CONDITION@
+gl_GNULIB_ENABLED_be453cec5eecf5731a274f2de7f2db36_CONDITION = @gl_GNULIB_ENABLED_be453cec5eecf5731a274f2de7f2db36_CONDITION@
+gl_GNULIB_ENABLED_cloexec_CONDITION = @gl_GNULIB_ENABLED_cloexec_CONDITION@
+gl_GNULIB_ENABLED_d3b2383720ee0e541357aa2aac598e2b_CONDITION = @gl_GNULIB_ENABLED_d3b2383720ee0e541357aa2aac598e2b_CONDITION@
+gl_GNULIB_ENABLED_dirfd_CONDITION = @gl_GNULIB_ENABLED_dirfd_CONDITION@
+gl_GNULIB_ENABLED_dynarray_CONDITION = @gl_GNULIB_ENABLED_dynarray_CONDITION@
+gl_GNULIB_ENABLED_e80bf6f757095d2e5fc94dafb8f8fc8b_CONDITION = @gl_GNULIB_ENABLED_e80bf6f757095d2e5fc94dafb8f8fc8b_CONDITION@
+gl_GNULIB_ENABLED_ef455225c00f5049c808c2eda3e76866_CONDITION = @gl_GNULIB_ENABLED_ef455225c00f5049c808c2eda3e76866_CONDITION@
+gl_GNULIB_ENABLED_euidaccess_CONDITION = @gl_GNULIB_ENABLED_euidaccess_CONDITION@
+gl_GNULIB_ENABLED_getdtablesize_CONDITION = @gl_GNULIB_ENABLED_getdtablesize_CONDITION@
+gl_GNULIB_ENABLED_getgroups_CONDITION = @gl_GNULIB_ENABLED_getgroups_CONDITION@
+gl_GNULIB_ENABLED_lchmod_CONDITION = @gl_GNULIB_ENABLED_lchmod_CONDITION@
+gl_GNULIB_ENABLED_open_CONDITION = @gl_GNULIB_ENABLED_open_CONDITION@
+gl_GNULIB_ENABLED_rawmemchr_CONDITION = @gl_GNULIB_ENABLED_rawmemchr_CONDITION@
+gl_GNULIB_ENABLED_scratch_buffer_CONDITION = @gl_GNULIB_ENABLED_scratch_buffer_CONDITION@
+gl_GNULIB_ENABLED_stdckdint_CONDITION = @gl_GNULIB_ENABLED_stdckdint_CONDITION@
+gl_GNULIB_ENABLED_strtoll_CONDITION = @gl_GNULIB_ENABLED_strtoll_CONDITION@
+gl_GNULIB_ENABLED_utimens_CONDITION = @gl_GNULIB_ENABLED_utimens_CONDITION@
+gl_LIBOBJDEPS = @gl_LIBOBJDEPS@
gl_LIBOBJS = @gl_LIBOBJS@
gl_LTLIBOBJS = @gl_LTLIBOBJS@
+gltests_LIBOBJDEPS = @gltests_LIBOBJDEPS@
gltests_LIBOBJS = @gltests_LIBOBJS@
gltests_LTLIBOBJS = @gltests_LTLIBOBJS@
gltests_WITNESS = @gltests_WITNESS@
+gsettingsschemadir = @gsettingsschemadir@
host = @host@
host_alias = @host_alias@
host_cpu = @host_cpu@
@@ -928,6 +1344,7 @@ libdir = @libdir@
libexecdir = @libexecdir@
liblockfile = @liblockfile@
lispdir = @lispdir@
+lispdirrel = @lispdirrel@
lisppath = @lisppath@
localedir = @localedir@
locallisppath = @locallisppath@
@@ -935,6 +1352,8 @@ localstatedir = @localstatedir@
mandir = @mandir@
ns_appbindir = @ns_appbindir@
ns_appdir = @ns_appdir@
+ns_applibdir = @ns_applibdir@
+ns_applibexecdir = @ns_applibexecdir@
ns_appresdir = @ns_appresdir@
ns_appsrc = @ns_appsrc@
ns_check_file = @ns_check_file@
@@ -944,6 +1363,7 @@ pdfdir = @pdfdir@
prefix = @prefix@
program_transform_name = @program_transform_name@
psdir = @psdir@
+runstatedir = @runstatedir@
sbindir = @sbindir@
sharedstatedir = @sharedstatedir@
srcdir = @srcdir@
@@ -958,6 +1378,7 @@ x_default_search_path = @x_default_search_path@
noinst_LIBRARIES += libgnu.a
libgnu_a_SOURCES =
+libgnu_a_CFLAGS = $(AM_CFLAGS) $(GL_CFLAG_GNULIB_WARNINGS)
libgnu_a_LIBADD = $(gl_LIBOBJS)
libgnu_a_DEPENDENCIES = $(gl_LIBOBJS)
EXTRA_libgnu_a_SOURCES =
@@ -968,7 +1389,7 @@ ifeq (,$(OMIT_GNULIB_MODULE_absolute-header))
# 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 = (__GNUC__ || 60000000 <= __DECC_VER)
+HAVE_INCLUDE_NEXT = (__GNUC__ || __clang__ || 60000000 <= __DECC_VER)
endif
## end gnulib module absolute-header
@@ -992,13 +1413,12 @@ BUILT_SOURCES += $(ALLOCA_H)
# We need the following in order to create <alloca.h> when the system
# doesn't have one that works with the given compiler.
-ifneq (,$(GL_GENERATE_ALLOCA_H))
+ifneq (,$(GL_GENERATE_ALLOCA_H_CONDITION))
alloca.h: alloca.in.h $(top_builddir)/config.status
- $(AM_V_GEN)rm -f $@-t $@ && \
- { echo '/* DO NOT EDIT! GENERATED AUTOMATICALLY! */'; \
- cat $(srcdir)/alloca.in.h; \
- } > $@-t && \
- mv -f $@-t $@
+ $(gl_V_at)$(SED_HEADER_STDOUT) \
+ -e 's|@''HAVE_ALLOCA_H''@|$(HAVE_ALLOCA_H)|g' \
+ $(srcdir)/alloca.in.h > $@-t
+ $(AM_V_at)mv $@-t $@
else
alloca.h: $(top_builddir)/config.status
rm -f $@
@@ -1023,15 +1443,21 @@ endif
## begin gnulib module at-internal
ifeq (,$(OMIT_GNULIB_MODULE_at-internal))
-ifneq (,$(gl_GNULIB_ENABLED_260941c0e5dc67ec9e87d1fb321c300b))
+ifneq (,$(gl_GNULIB_ENABLED_260941c0e5dc67ec9e87d1fb321c300b_CONDITION))
+libgnu_a_SOURCES += openat-priv.h openat-proc.c
endif
-EXTRA_DIST += openat-priv.h openat-proc.c
+endif
+## end gnulib module at-internal
+
+## begin gnulib module attribute
+ifeq (,$(OMIT_GNULIB_MODULE_attribute))
-EXTRA_libgnu_a_SOURCES += openat-proc.c
+
+EXTRA_DIST += attribute.h
endif
-## end gnulib module at-internal
+## end gnulib module attribute
## begin gnulib module binary-io
ifeq (,$(OMIT_GNULIB_MODULE_binary-io))
@@ -1048,13 +1474,10 @@ BUILT_SOURCES += $(BYTESWAP_H)
# We need the following in order to create <byteswap.h> when the system
# doesn't have one.
-ifneq (,$(GL_GENERATE_BYTESWAP_H))
+ifneq (,$(GL_GENERATE_BYTESWAP_H_CONDITION))
byteswap.h: byteswap.in.h $(top_builddir)/config.status
- $(AM_V_GEN)rm -f $@-t $@ && \
- { echo '/* DO NOT EDIT! GENERATED AUTOMATICALLY! */'; \
- cat $(srcdir)/byteswap.in.h; \
- } > $@-t && \
- mv -f $@-t $@
+ $(gl_V_at)$(SED_HEADER_TO_AT_t) $(srcdir)/byteswap.in.h
+ $(AM_V_at)mv $@-t $@
else
byteswap.h: $(top_builddir)/config.status
rm -f $@
@@ -1082,6 +1505,16 @@ libgnu_a_SOURCES += c-strcase.h c-strcasecmp.c c-strncasecmp.c
endif
## end gnulib module c-strcase
+## begin gnulib module canonicalize-lgpl
+ifeq (,$(OMIT_GNULIB_MODULE_canonicalize-lgpl))
+
+ifneq (,$(GL_COND_OBJ_CANONICALIZE_LGPL_CONDITION))
+libgnu_a_SOURCES += canonicalize-lgpl.c
+endif
+
+endif
+## end gnulib module canonicalize-lgpl
+
## begin gnulib module careadlinkat
ifeq (,$(OMIT_GNULIB_MODULE_careadlinkat))
@@ -1095,7 +1528,7 @@ endif
## begin gnulib module cloexec
ifeq (,$(OMIT_GNULIB_MODULE_cloexec))
-ifneq (,$(gl_GNULIB_ENABLED_cloexec))
+ifneq (,$(gl_GNULIB_ENABLED_cloexec_CONDITION))
libgnu_a_SOURCES += cloexec.c
endif
@@ -1114,6 +1547,16 @@ EXTRA_DIST += close-stream.h
endif
## end gnulib module close-stream
+## begin gnulib module copy-file-range
+ifeq (,$(OMIT_GNULIB_MODULE_copy-file-range))
+
+ifneq (,$(GL_COND_OBJ_COPY_FILE_RANGE_CONDITION))
+libgnu_a_SOURCES += copy-file-range.c
+endif
+
+endif
+## end gnulib module copy-file-range
+
## begin gnulib module count-leading-zeros
ifeq (,$(OMIT_GNULIB_MODULE_count-leading-zeros))
@@ -1147,42 +1590,50 @@ endif
## begin gnulib module crypto/md5
ifeq (,$(OMIT_GNULIB_MODULE_crypto/md5))
+libgnu_a_SOURCES += md5-stream.c
+
+endif
+## end gnulib module crypto/md5
+
+## begin gnulib module crypto/md5-buffer
+ifeq (,$(OMIT_GNULIB_MODULE_crypto/md5-buffer))
+
libgnu_a_SOURCES += md5.c
EXTRA_DIST += gl_openssl.h md5.h
endif
-## end gnulib module crypto/md5
+## end gnulib module crypto/md5-buffer
-## begin gnulib module crypto/sha1
-ifeq (,$(OMIT_GNULIB_MODULE_crypto/sha1))
+## begin gnulib module crypto/sha1-buffer
+ifeq (,$(OMIT_GNULIB_MODULE_crypto/sha1-buffer))
libgnu_a_SOURCES += sha1.c
EXTRA_DIST += gl_openssl.h sha1.h
endif
-## end gnulib module crypto/sha1
+## end gnulib module crypto/sha1-buffer
-## begin gnulib module crypto/sha256
-ifeq (,$(OMIT_GNULIB_MODULE_crypto/sha256))
+## begin gnulib module crypto/sha256-buffer
+ifeq (,$(OMIT_GNULIB_MODULE_crypto/sha256-buffer))
libgnu_a_SOURCES += sha256.c
EXTRA_DIST += gl_openssl.h sha256.h
endif
-## end gnulib module crypto/sha256
+## end gnulib module crypto/sha256-buffer
-## begin gnulib module crypto/sha512
-ifeq (,$(OMIT_GNULIB_MODULE_crypto/sha512))
+## begin gnulib module crypto/sha512-buffer
+ifeq (,$(OMIT_GNULIB_MODULE_crypto/sha512-buffer))
libgnu_a_SOURCES += sha512.c
EXTRA_DIST += gl_openssl.h sha512.h
endif
-## end gnulib module crypto/sha512
+## end gnulib module crypto/sha512-buffer
## begin gnulib module diffseq
ifeq (,$(OMIT_GNULIB_MODULE_diffseq))
@@ -1200,22 +1651,21 @@ BUILT_SOURCES += dirent.h
# We need the following in order to create <dirent.h> when the system
# doesn't have one that works with the given compiler.
dirent.h: dirent.in.h $(top_builddir)/config.status $(CXXDEFS_H) $(ARG_NONNULL_H) $(WARN_ON_USE_H)
- $(AM_V_GEN)rm -f $@-t $@ && \
- { echo '/* DO NOT EDIT! GENERATED AUTOMATICALLY! */'; \
- sed -e 's|@''GUARD_PREFIX''@|GL|g' \
+ $(gl_V_at)$(SED_HEADER_STDOUT) \
+ -e 's|@''GUARD_PREFIX''@|GL|g' \
-e 's|@''HAVE_DIRENT_H''@|$(HAVE_DIRENT_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_DIRENT_H''@|$(NEXT_DIRENT_H)|g' \
- -e 's/@''GNULIB_OPENDIR''@/$(GNULIB_OPENDIR)/g' \
- -e 's/@''GNULIB_READDIR''@/$(GNULIB_READDIR)/g' \
- -e 's/@''GNULIB_REWINDDIR''@/$(GNULIB_REWINDDIR)/g' \
- -e 's/@''GNULIB_CLOSEDIR''@/$(GNULIB_CLOSEDIR)/g' \
- -e 's/@''GNULIB_DIRFD''@/$(GNULIB_DIRFD)/g' \
- -e 's/@''GNULIB_FDOPENDIR''@/$(GNULIB_FDOPENDIR)/g' \
- -e 's/@''GNULIB_SCANDIR''@/$(GNULIB_SCANDIR)/g' \
- -e 's/@''GNULIB_ALPHASORT''@/$(GNULIB_ALPHASORT)/g' \
+ -e 's/@''GNULIB_OPENDIR''@/$(GL_GNULIB_OPENDIR)/g' \
+ -e 's/@''GNULIB_READDIR''@/$(GL_GNULIB_READDIR)/g' \
+ -e 's/@''GNULIB_REWINDDIR''@/$(GL_GNULIB_REWINDDIR)/g' \
+ -e 's/@''GNULIB_CLOSEDIR''@/$(GL_GNULIB_CLOSEDIR)/g' \
+ -e 's/@''GNULIB_DIRFD''@/$(GL_GNULIB_DIRFD)/g' \
+ -e 's/@''GNULIB_FDOPENDIR''@/$(GL_GNULIB_FDOPENDIR)/g' \
+ -e 's/@''GNULIB_SCANDIR''@/$(GL_GNULIB_SCANDIR)/g' \
+ -e 's/@''GNULIB_ALPHASORT''@/$(GL_GNULIB_ALPHASORT)/g' \
-e 's/@''HAVE_OPENDIR''@/$(HAVE_OPENDIR)/g' \
-e 's/@''HAVE_READDIR''@/$(HAVE_READDIR)/g' \
-e 's/@''HAVE_REWINDDIR''@/$(HAVE_REWINDDIR)/g' \
@@ -1232,9 +1682,8 @@ dirent.h: dirent.in.h $(top_builddir)/config.status $(CXXDEFS_H) $(ARG_NONNULL_H
-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)' \
- < $(srcdir)/dirent.in.h; \
- } > $@-t && \
- mv $@-t $@
+ $(srcdir)/dirent.in.h > $@-t
+ $(AM_V_at)mv $@-t $@
MOSTLYCLEANFILES += dirent.h dirent.h-t
EXTRA_DIST += dirent.in.h
@@ -1245,26 +1694,14 @@ endif
## begin gnulib module dirfd
ifeq (,$(OMIT_GNULIB_MODULE_dirfd))
-ifneq (,$(gl_GNULIB_ENABLED_dirfd))
-
+ifneq (,$(gl_GNULIB_ENABLED_dirfd_CONDITION))
+ifneq (,$(GL_COND_OBJ_DIRFD_CONDITION))
+libgnu_a_SOURCES += dirfd.c
endif
-EXTRA_DIST += dirfd.c
-
-EXTRA_libgnu_a_SOURCES += dirfd.c
endif
-## end gnulib module dirfd
-
-## begin gnulib module dosname
-ifeq (,$(OMIT_GNULIB_MODULE_dosname))
-
-ifneq (,$(gl_GNULIB_ENABLED_dosname))
-
endif
-EXTRA_DIST += dosname.h
-
-endif
-## end gnulib module dosname
+## end gnulib module dirfd
## begin gnulib module dtoastr
ifeq (,$(OMIT_GNULIB_MODULE_dtoastr))
@@ -1289,13 +1726,60 @@ endif
## begin gnulib module dup2
ifeq (,$(OMIT_GNULIB_MODULE_dup2))
+ifneq (,$(GL_COND_OBJ_DUP2_CONDITION))
+libgnu_a_SOURCES += dup2.c
+endif
+
+endif
+## end gnulib module dup2
+
+## begin gnulib module dynarray
+ifeq (,$(OMIT_GNULIB_MODULE_dynarray))
+
+ifneq (,$(gl_GNULIB_ENABLED_dynarray_CONDITION))
+BUILT_SOURCES += malloc/dynarray.gl.h malloc/dynarray-skeleton.gl.h
-EXTRA_DIST += dup2.c
+malloc/dynarray.gl.h: malloc/dynarray.h
+ $(AM_V_GEN)$(MKDIR_P) 'malloc'
+ $(AM_V_at)$(SED_HEADER_STDOUT) \
+ -e '/libc_hidden_proto/d' \
+ $(srcdir)/malloc/dynarray.h > $@-t
+ $(AM_V_at)mv $@-t $@
+MOSTLYCLEANFILES += malloc/dynarray.gl.h malloc/dynarray.gl.h-t
-EXTRA_libgnu_a_SOURCES += dup2.c
+malloc/dynarray-skeleton.gl.h: malloc/dynarray-skeleton.c
+ $(AM_V_GEN)$(MKDIR_P) 'malloc'
+ $(AM_V_at)$(SED_HEADER_STDOUT) \
+ -e 's|<malloc/dynarray\.h>|<malloc/dynarray.gl.h>|g' \
+ -e 's|__attribute_maybe_unused__|_GL_ATTRIBUTE_MAYBE_UNUSED|g' \
+ -e 's|__attribute_nonnull__|_GL_ATTRIBUTE_NONNULL|g' \
+ -e 's|__attribute_warn_unused_result__|_GL_ATTRIBUTE_NODISCARD|g' \
+ -e 's|__glibc_likely|_GL_LIKELY|g' \
+ -e 's|__glibc_unlikely|_GL_UNLIKELY|g' \
+ $(srcdir)/malloc/dynarray-skeleton.c > $@-t
+ $(AM_V_at)mv $@-t $@
+MOSTLYCLEANFILES += malloc/dynarray-skeleton.gl.h malloc/dynarray-skeleton.gl.h-t
+
+libgnu_a_SOURCES += malloc/dynarray_at_failure.c malloc/dynarray_emplace_enlarge.c malloc/dynarray_finalize.c malloc/dynarray_resize.c malloc/dynarray_resize_clear.c
endif
-## end gnulib module dup2
+EXTRA_DIST += dynarray.h malloc/dynarray-skeleton.c malloc/dynarray.h
+
+EXTRA_libgnu_a_SOURCES += malloc/dynarray-skeleton.c
+
+endif
+## end gnulib module dynarray
+
+## begin gnulib module eloop-threshold
+ifeq (,$(OMIT_GNULIB_MODULE_eloop-threshold))
+
+ifneq (,$(gl_GNULIB_ENABLED_925677f0343de64b89a9f0c790b4104c_CONDITION))
+
+endif
+EXTRA_DIST += eloop-threshold.h
+
+endif
+## end gnulib module eloop-threshold
## begin gnulib module errno
ifeq (,$(OMIT_GNULIB_MODULE_errno))
@@ -1304,11 +1788,10 @@ BUILT_SOURCES += $(ERRNO_H)
# We need the following in order to create <errno.h> when the system
# doesn't have one that is POSIX compliant.
-ifneq (,$(GL_GENERATE_ERRNO_H))
+ifneq (,$(GL_GENERATE_ERRNO_H_CONDITION))
errno.h: errno.in.h $(top_builddir)/config.status
- $(AM_V_GEN)rm -f $@-t $@ && \
- { echo '/* DO NOT EDIT! GENERATED AUTOMATICALLY! */' && \
- sed -e 's|@''GUARD_PREFIX''@|GL|g' \
+ $(gl_V_at)$(SED_HEADER_STDOUT) \
+ -e 's|@''GUARD_PREFIX''@|GL|g' \
-e 's|@''INCLUDE_NEXT''@|$(INCLUDE_NEXT)|g' \
-e 's|@''PRAGMA_SYSTEM_HEADER''@|@PRAGMA_SYSTEM_HEADER@|g' \
-e 's|@''PRAGMA_COLUMNS''@|@PRAGMA_COLUMNS@|g' \
@@ -1319,9 +1802,8 @@ errno.h: errno.in.h $(top_builddir)/config.status
-e 's|@''ENOLINK_VALUE''@|$(ENOLINK_VALUE)|g' \
-e 's|@''EOVERFLOW_HIDDEN''@|$(EOVERFLOW_HIDDEN)|g' \
-e 's|@''EOVERFLOW_VALUE''@|$(EOVERFLOW_VALUE)|g' \
- < $(srcdir)/errno.in.h; \
- } > $@-t && \
- mv $@-t $@
+ $(srcdir)/errno.in.h > $@-t
+ $(AM_V_at)mv $@-t $@
else
errno.h: $(top_builddir)/config.status
rm -f $@
@@ -1336,14 +1818,13 @@ endif
## begin gnulib module euidaccess
ifeq (,$(OMIT_GNULIB_MODULE_euidaccess))
-ifneq (,$(gl_GNULIB_ENABLED_euidaccess))
-
+ifneq (,$(gl_GNULIB_ENABLED_euidaccess_CONDITION))
+ifneq (,$(GL_COND_OBJ_EUIDACCESS_CONDITION))
+libgnu_a_SOURCES += euidaccess.c
endif
-EXTRA_DIST += euidaccess.c
-
-EXTRA_libgnu_a_SOURCES += euidaccess.c
endif
+endif
## end gnulib module euidaccess
## begin gnulib module execinfo
@@ -1353,22 +1834,21 @@ BUILT_SOURCES += $(EXECINFO_H)
# We need the following in order to create <execinfo.h> when the system
# doesn't have one that works.
-ifneq (,$(GL_GENERATE_EXECINFO_H))
+ifneq (,$(GL_GENERATE_EXECINFO_H_CONDITION))
execinfo.h: execinfo.in.h $(top_builddir)/config.status
- $(AM_V_GEN)rm -f $@-t $@ && \
- { echo '/* DO NOT EDIT! GENERATED AUTOMATICALLY! */'; \
- cat $(srcdir)/execinfo.in.h; \
- } > $@-t && \
- mv $@-t $@
+ $(gl_V_at)$(SED_HEADER_TO_AT_t) $(srcdir)/execinfo.in.h
+ $(AM_V_at)mv $@-t $@
else
execinfo.h: $(top_builddir)/config.status
rm -f $@
endif
MOSTLYCLEANFILES += execinfo.h execinfo.h-t
-EXTRA_DIST += execinfo.c execinfo.in.h
+ifneq (,$(GL_COND_OBJ_EXECINFO_CONDITION))
+libgnu_a_SOURCES += execinfo.c
+endif
-EXTRA_libgnu_a_SOURCES += execinfo.c
+EXTRA_DIST += execinfo.in.h
endif
## end gnulib module execinfo
@@ -1376,10 +1856,9 @@ endif
## begin gnulib module explicit_bzero
ifeq (,$(OMIT_GNULIB_MODULE_explicit_bzero))
-
-EXTRA_DIST += explicit_bzero.c
-
-EXTRA_libgnu_a_SOURCES += explicit_bzero.c
+ifneq (,$(GL_COND_OBJ_EXPLICIT_BZERO_CONDITION))
+libgnu_a_SOURCES += explicit_bzero.c
+endif
endif
## end gnulib module explicit_bzero
@@ -1387,21 +1866,37 @@ endif
## begin gnulib module faccessat
ifeq (,$(OMIT_GNULIB_MODULE_faccessat))
+ifneq (,$(GL_COND_OBJ_FACCESSAT_CONDITION))
+libgnu_a_SOURCES += faccessat.c
+endif
-EXTRA_DIST += at-func.c faccessat.c
+EXTRA_DIST += at-func.c
-EXTRA_libgnu_a_SOURCES += at-func.c faccessat.c
+EXTRA_libgnu_a_SOURCES += at-func.c
endif
## end gnulib module faccessat
-## begin gnulib module fcntl
-ifeq (,$(OMIT_GNULIB_MODULE_fcntl))
+## begin gnulib module fchmodat
+ifeq (,$(OMIT_GNULIB_MODULE_fchmodat))
+
+ifneq (,$(GL_COND_OBJ_FCHMODAT_CONDITION))
+libgnu_a_SOURCES += fchmodat.c
+endif
+EXTRA_DIST += at-func.c
-EXTRA_DIST += fcntl.c
+EXTRA_libgnu_a_SOURCES += at-func.c
+
+endif
+## end gnulib module fchmodat
+
+## begin gnulib module fcntl
+ifeq (,$(OMIT_GNULIB_MODULE_fcntl))
-EXTRA_libgnu_a_SOURCES += fcntl.c
+ifneq (,$(GL_COND_OBJ_FCNTL_CONDITION))
+libgnu_a_SOURCES += fcntl.c
+endif
endif
## end gnulib module fcntl
@@ -1414,28 +1909,30 @@ BUILT_SOURCES += fcntl.h
# We need the following in order to create <fcntl.h> when the system
# doesn't have one that works with the given compiler.
fcntl.h: fcntl.in.h $(top_builddir)/config.status $(CXXDEFS_H) $(ARG_NONNULL_H) $(WARN_ON_USE_H)
- $(AM_V_GEN)rm -f $@-t $@ && \
- { echo '/* DO NOT EDIT! GENERATED AUTOMATICALLY! */'; \
- sed -e 's|@''GUARD_PREFIX''@|GL|g' \
+ $(gl_V_at)$(SED_HEADER_STDOUT) \
+ -e 's|@''GUARD_PREFIX''@|GL|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_FCNTL_H''@|$(NEXT_FCNTL_H)|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/@''GNULIB_CREAT''@/$(GL_GNULIB_CREAT)/g' \
+ -e 's/@''GNULIB_FCNTL''@/$(GL_GNULIB_FCNTL)/g' \
+ -e 's/@''GNULIB_NONBLOCKING''@/$(GL_GNULIB_NONBLOCKING)/g' \
+ -e 's/@''GNULIB_OPEN''@/$(GL_GNULIB_OPEN)/g' \
+ -e 's/@''GNULIB_OPENAT''@/$(GL_GNULIB_OPENAT)/g' \
+ -e 's/@''GNULIB_MDA_CREAT''@/$(GL_GNULIB_MDA_CREAT)/g' \
+ -e 's/@''GNULIB_MDA_OPEN''@/$(GL_GNULIB_MDA_OPEN)/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' \
-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)' \
- < $(srcdir)/fcntl.in.h; \
- } > $@-t && \
- mv $@-t $@
+ $(srcdir)/fcntl.in.h > $@-t
+ $(AM_V_at)mv $@-t $@
MOSTLYCLEANFILES += fcntl.h fcntl.h-t
EXTRA_DIST += fcntl.in.h
@@ -1443,27 +1940,25 @@ EXTRA_DIST += fcntl.in.h
endif
## end gnulib module fcntl-h
-## begin gnulib module fdatasync
-ifeq (,$(OMIT_GNULIB_MODULE_fdatasync))
-
-
-EXTRA_DIST += fdatasync.c
-
-EXTRA_libgnu_a_SOURCES += fdatasync.c
+## begin gnulib module fdopendir
+ifeq (,$(OMIT_GNULIB_MODULE_fdopendir))
+ifneq (,$(GL_COND_OBJ_FDOPENDIR_CONDITION))
+libgnu_a_SOURCES += fdopendir.c
endif
-## end gnulib module fdatasync
-## begin gnulib module fdopendir
-ifeq (,$(OMIT_GNULIB_MODULE_fdopendir))
+endif
+## end gnulib module fdopendir
+## begin gnulib module file-has-acl
+ifeq (,$(OMIT_GNULIB_MODULE_file-has-acl))
-EXTRA_DIST += fdopendir.c
+libgnu_a_SOURCES += file-has-acl.c
-EXTRA_libgnu_a_SOURCES += fdopendir.c
+EXTRA_DIST += acl-internal.h
endif
-## end gnulib module fdopendir
+## end gnulib module file-has-acl
## begin gnulib module filemode
ifeq (,$(OMIT_GNULIB_MODULE_filemode))
@@ -1475,6 +1970,15 @@ EXTRA_DIST += filemode.h
endif
## end gnulib module filemode
+## begin gnulib module filename
+ifeq (,$(OMIT_GNULIB_MODULE_filename))
+
+
+EXTRA_DIST += filename.h
+
+endif
+## end gnulib module filename
+
## begin gnulib module filevercmp
ifeq (,$(OMIT_GNULIB_MODULE_filevercmp))
@@ -1497,21 +2001,35 @@ endif
## begin gnulib module fpending
ifeq (,$(OMIT_GNULIB_MODULE_fpending))
+ifneq (,$(GL_COND_OBJ_FPENDING_CONDITION))
+libgnu_a_SOURCES += fpending.c
+endif
-EXTRA_DIST += fpending.c fpending.h stdio-impl.h
-
-EXTRA_libgnu_a_SOURCES += fpending.c
+EXTRA_DIST += fpending.h stdio-impl.h
endif
## end gnulib module fpending
+## begin gnulib module free-posix
+ifeq (,$(OMIT_GNULIB_MODULE_free-posix))
+
+ifneq (,$(GL_COND_OBJ_FREE_CONDITION))
+libgnu_a_SOURCES += free.c
+endif
+
+endif
+## end gnulib module free-posix
+
## begin gnulib module fstatat
ifeq (,$(OMIT_GNULIB_MODULE_fstatat))
+ifneq (,$(GL_COND_OBJ_FSTATAT_CONDITION))
+libgnu_a_SOURCES += fstatat.c
+endif
-EXTRA_DIST += at-func.c fstatat.c
+EXTRA_DIST += at-func.c
-EXTRA_libgnu_a_SOURCES += at-func.c fstatat.c
+EXTRA_libgnu_a_SOURCES += at-func.c
endif
## end gnulib module fstatat
@@ -1519,10 +2037,11 @@ endif
## begin gnulib module fsusage
ifeq (,$(OMIT_GNULIB_MODULE_fsusage))
+ifneq (,$(GL_COND_OBJ_FSUSAGE_CONDITION))
+libgnu_a_SOURCES += fsusage.c
+endif
-EXTRA_DIST += fsusage.c fsusage.h
-
-EXTRA_libgnu_a_SOURCES += fsusage.c
+EXTRA_DIST += fsusage.h
endif
## end gnulib module fsusage
@@ -1530,47 +2049,74 @@ endif
## begin gnulib module fsync
ifeq (,$(OMIT_GNULIB_MODULE_fsync))
+ifneq (,$(GL_COND_OBJ_FSYNC_CONDITION))
+libgnu_a_SOURCES += fsync.c
+endif
-EXTRA_DIST += fsync.c
+endif
+## end gnulib module fsync
-EXTRA_libgnu_a_SOURCES += fsync.c
+## begin gnulib module futimens
+ifeq (,$(OMIT_GNULIB_MODULE_futimens))
+ifneq (,$(GL_COND_OBJ_FUTIMENS_CONDITION))
+libgnu_a_SOURCES += futimens.c
endif
-## end gnulib module fsync
-## begin gnulib module getdtablesize
-ifeq (,$(OMIT_GNULIB_MODULE_getdtablesize))
+endif
+## end gnulib module futimens
+
+## begin gnulib module gen-header
+ifeq (,$(OMIT_GNULIB_MODULE_gen-header))
+
+# In 'sed', replace the pattern space with a "DO NOT EDIT" comment.
+SED_HEADER_NOEDIT = s,.*,/* DO NOT EDIT! GENERATED AUTOMATICALLY! */,
-ifneq (,$(gl_GNULIB_ENABLED_getdtablesize))
+# '$(SED_HEADER_STDOUT) -e "..."' runs 'sed' but first outputs "DO NOT EDIT".
+SED_HEADER_STDOUT = sed -e 1h -e '1$(SED_HEADER_NOEDIT)' -e 1G
+
+# '$(SED_HEADER_TO_AT_t) FILE' copies FILE to $@-t, prepending a leading
+# "DO_NOT_EDIT". Although this could be done more simply via:
+# SED_HEADER_TO_AT_t = $(SED_HEADER_STDOUT) > $@-t
+# the -n and 'w' avoid a fork+exec, at least when GNU Make is used.
+SED_HEADER_TO_AT_t = $(SED_HEADER_STDOUT) -n -e 'w $@-t'
+
+# Use $(gl_V_at) instead of $(AM_V_GEN) or $(AM_V_at) on a line that
+gl_V_at = $(AM_V_GEN)
endif
-EXTRA_DIST += getdtablesize.c
+## end gnulib module gen-header
-EXTRA_libgnu_a_SOURCES += getdtablesize.c
+## begin gnulib module getdtablesize
+ifeq (,$(OMIT_GNULIB_MODULE_getdtablesize))
+
+ifneq (,$(gl_GNULIB_ENABLED_getdtablesize_CONDITION))
+ifneq (,$(GL_COND_OBJ_GETDTABLESIZE_CONDITION))
+libgnu_a_SOURCES += getdtablesize.c
+endif
endif
+endif
## end gnulib module getdtablesize
## begin gnulib module getgroups
ifeq (,$(OMIT_GNULIB_MODULE_getgroups))
-ifneq (,$(gl_GNULIB_ENABLED_getgroups))
-
+ifneq (,$(gl_GNULIB_ENABLED_getgroups_CONDITION))
+ifneq (,$(GL_COND_OBJ_GETGROUPS_CONDITION))
+libgnu_a_SOURCES += getgroups.c
endif
-EXTRA_DIST += getgroups.c
-
-EXTRA_libgnu_a_SOURCES += getgroups.c
endif
+endif
## end gnulib module getgroups
## begin gnulib module getloadavg
ifeq (,$(OMIT_GNULIB_MODULE_getloadavg))
-
-EXTRA_DIST += getloadavg.c
-
-EXTRA_libgnu_a_SOURCES += getloadavg.c
+ifneq (,$(GL_COND_OBJ_GETLOADAVG_CONDITION))
+libgnu_a_SOURCES += getloadavg.c
+endif
endif
## end gnulib module getloadavg
@@ -1582,41 +2128,59 @@ BUILT_SOURCES += $(GETOPT_H) $(GETOPT_CDEFS_H)
# We need the following in order to create <getopt.h> when the system
# doesn't have one that works with the given compiler.
-getopt.h: getopt.in.h $(top_builddir)/config.status
- $(AM_V_GEN)rm -f $@-t $@ && \
- { echo '/* DO NOT EDIT! GENERATED AUTOMATICALLY! */'; \
- sed -e 's|@''GUARD_PREFIX''@|GL|g' \
+ifneq (,$(GL_GENERATE_GETOPT_H_CONDITION))
+getopt.h: getopt.in.h $(top_builddir)/config.status $(ARG_NONNULL_H)
+ $(gl_V_at)$(SED_HEADER_STDOUT) \
+ -e 's|@''GUARD_PREFIX''@|GL|g' \
-e 's|@''HAVE_GETOPT_H''@|$(HAVE_GETOPT_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_GETOPT_H''@|$(NEXT_GETOPT_H)|g' \
-e '/definition of _GL_ARG_NONNULL/r $(ARG_NONNULL_H)' \
- < $(srcdir)/getopt.in.h; \
- } > $@-t && \
- mv -f $@-t $@
+ $(srcdir)/getopt.in.h > $@-t
+ $(AM_V_at)mv $@-t $@
+else
+getopt.h: $(top_builddir)/config.status
+ rm -f $@
+endif
+ifneq (,$(GL_GENERATE_GETOPT_CDEFS_H_CONDITION))
getopt-cdefs.h: getopt-cdefs.in.h $(top_builddir)/config.status
- $(AM_V_GEN)rm -f $@-t $@ && \
- { echo '/* DO NOT EDIT! GENERATED AUTOMATICALLY! */'; \
- sed -e 's|@''HAVE_SYS_CDEFS_H''@|$(HAVE_SYS_CDEFS_H)|g' \
- < $(srcdir)/getopt-cdefs.in.h; \
- } > $@-t && \
- mv -f $@-t $@
+ $(AM_V_GEN)$(SED_HEADER_STDOUT) \
+ -e 's|@''HAVE_SYS_CDEFS_H''@|$(HAVE_SYS_CDEFS_H)|g' \
+ $(srcdir)/getopt-cdefs.in.h > $@-t
+ $(AM_V_at)mv $@-t $@
+else
+getopt-cdefs.h: $(top_builddir)/config.status
+ rm -f $@
+endif
MOSTLYCLEANFILES += getopt.h getopt.h-t getopt-cdefs.h getopt-cdefs.h-t
-EXTRA_DIST += getopt-cdefs.in.h getopt-core.h getopt-ext.h getopt-pfx-core.h getopt-pfx-ext.h getopt.c getopt.in.h getopt1.c getopt_int.h
+ifneq (,$(GL_COND_OBJ_GETOPT_CONDITION))
+libgnu_a_SOURCES += getopt.c getopt1.c
+endif
-EXTRA_libgnu_a_SOURCES += getopt.c getopt1.c
+EXTRA_DIST += getopt-cdefs.in.h getopt-core.h getopt-ext.h getopt-pfx-core.h getopt-pfx-ext.h getopt.in.h getopt_int.h
endif
## end gnulib module getopt-posix
+## begin gnulib module getrandom
+ifeq (,$(OMIT_GNULIB_MODULE_getrandom))
+
+ifneq (,$(GL_COND_OBJ_GETRANDOM_CONDITION))
+libgnu_a_SOURCES += getrandom.c
+endif
+
+endif
+## end gnulib module getrandom
+
## begin gnulib module gettext-h
ifeq (,$(OMIT_GNULIB_MODULE_gettext-h))
-ifneq (,$(gl_GNULIB_ENABLED_be453cec5eecf5731a274f2de7f2db36))
+ifneq (,$(gl_GNULIB_ENABLED_be453cec5eecf5731a274f2de7f2db36_CONDITION))
libgnu_a_SOURCES += gettext.h
endif
@@ -1634,10 +2198,9 @@ endif
## begin gnulib module gettimeofday
ifeq (,$(OMIT_GNULIB_MODULE_gettimeofday))
-
-EXTRA_DIST += gettimeofday.c
-
-EXTRA_libgnu_a_SOURCES += gettimeofday.c
+ifneq (,$(GL_COND_OBJ_GETTIMEOFDAY_CONDITION))
+libgnu_a_SOURCES += gettimeofday.c
+endif
endif
## end gnulib module gettimeofday
@@ -1654,15 +2217,46 @@ endif
## begin gnulib module group-member
ifeq (,$(OMIT_GNULIB_MODULE_group-member))
-ifneq (,$(gl_GNULIB_ENABLED_a9786850e999ae65a836a6041e8e5ed1))
+ifneq (,$(gl_GNULIB_ENABLED_a9786850e999ae65a836a6041e8e5ed1_CONDITION))
+ifneq (,$(GL_COND_OBJ_GROUP_MEMBER_CONDITION))
+libgnu_a_SOURCES += group-member.c
+endif
+
+endif
+endif
+## end gnulib module group-member
+
+## begin gnulib module idx
+ifeq (,$(OMIT_GNULIB_MODULE_idx))
+
+libgnu_a_SOURCES += idx.h
endif
-EXTRA_DIST += group-member.c
+## end gnulib module idx
+
+## begin gnulib module ieee754-h
+ifeq (,$(OMIT_GNULIB_MODULE_ieee754-h))
-EXTRA_libgnu_a_SOURCES += group-member.c
+BUILT_SOURCES += $(IEEE754_H)
+# We need the following in order to create <ieee754.h> when the system
+# doesn't have one that works with the given compiler.
+ifneq (,$(GL_GENERATE_IEEE754_H_CONDITION))
+ieee754.h: ieee754.in.h $(top_builddir)/config.status
+ $(gl_V_at)$(SED_HEADER_STDOUT) \
+ -e 's/ifndef _GL_GNULIB_HEADER/if 0/g' \
+ $(srcdir)/ieee754.in.h > $@-t
+ $(AM_V_at)mv $@-t $@
+else
+ieee754.h: $(top_builddir)/config.status
+ rm -f $@
endif
-## end gnulib module group-member
+MOSTLYCLEANFILES += ieee754.h ieee754.h-t
+
+EXTRA_DIST += ieee754.in.h
+
+endif
+## end gnulib module ieee754-h
## begin gnulib module ignore-value
ifeq (,$(OMIT_GNULIB_MODULE_ignore-value))
@@ -1677,7 +2271,7 @@ endif
ifeq (,$(OMIT_GNULIB_MODULE_intprops))
-EXTRA_DIST += intprops.h
+EXTRA_DIST += intprops-internal.h intprops.h
endif
## end gnulib module intprops
@@ -1690,26 +2284,23 @@ BUILT_SOURCES += 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.
inttypes.h: 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' \
+ $(gl_V_at)$(SED_HEADER_STDOUT) \
+ -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/@''HAVE_LONG_LONG_INT''@/$(HAVE_LONG_LONG_INT)/g' \
- -e 's/@''HAVE_UNSIGNED_LONG_LONG_INT''@/$(HAVE_UNSIGNED_LONG_LONG_INT)/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/@''GNULIB_IMAXABS''@/$(GL_GNULIB_IMAXABS)/g' \
+ -e 's/@''GNULIB_IMAXDIV''@/$(GL_GNULIB_IMAXDIV)/g' \
+ -e 's/@''GNULIB_STRTOIMAX''@/$(GL_GNULIB_STRTOIMAX)/g' \
+ -e 's/@''GNULIB_STRTOUMAX''@/$(GL_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' \
@@ -1719,9 +2310,8 @@ inttypes.h: inttypes.in.h $(top_builddir)/config.status $(CXXDEFS_H) $(WARN_ON_U
-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)' \
- < $(srcdir)/inttypes.in.h; \
- } > $@-t && \
- mv $@-t $@
+ $(srcdir)/inttypes.in.h > $@-t
+ $(AM_V_at)mv $@-t $@
MOSTLYCLEANFILES += inttypes.h inttypes.h-t
EXTRA_DIST += inttypes.in.h
@@ -1729,6 +2319,62 @@ EXTRA_DIST += inttypes.in.h
endif
## end gnulib module inttypes-incomplete
+## begin gnulib module lchmod
+ifeq (,$(OMIT_GNULIB_MODULE_lchmod))
+
+ifneq (,$(gl_GNULIB_ENABLED_lchmod_CONDITION))
+ifneq (,$(GL_COND_OBJ_LCHMOD_CONDITION))
+libgnu_a_SOURCES += lchmod.c
+endif
+
+endif
+endif
+## end gnulib module lchmod
+
+## begin gnulib module libc-config
+ifeq (,$(OMIT_GNULIB_MODULE_libc-config))
+
+
+EXTRA_DIST += cdefs.h libc-config.h
+
+endif
+## end gnulib module libc-config
+
+## begin gnulib module libgmp
+ifeq (,$(OMIT_GNULIB_MODULE_libgmp))
+
+BUILT_SOURCES += $(GMP_H)
+
+ifneq (,$(GL_GENERATE_GMP_H_CONDITION))
+ifneq (,$(GL_GENERATE_MINI_GMP_H_CONDITION))
+# Build gmp.h as a wrapper for mini-gmp.h when using mini-gmp.
+gmp.h: $(top_builddir)/config.status
+ echo '#include "mini-gmp.h"' > $@-t
+ mv $@-t $@
+endif
+ifneq (,$(GL_GENERATE_GMP_GMP_H_CONDITION))
+# Build gmp.h as a wrapper for gmp/gmp.h.
+gmp.h: $(top_builddir)/config.status
+ echo '#include <gmp/gmp.h>' > $@-t
+ mv $@-t $@
+endif
+else
+gmp.h: $(top_builddir)/config.status
+ rm -f $@
+endif
+MOSTLYCLEANFILES += gmp.h gmp.h-t
+
+ifneq (,$(GL_COND_OBJ_MINI_GMP_GNULIB_CONDITION))
+libgnu_a_SOURCES += mini-gmp-gnulib.c
+endif
+
+EXTRA_DIST += mini-gmp.c mini-gmp.h
+
+EXTRA_libgnu_a_SOURCES += mini-gmp.c
+
+endif
+## end gnulib module libgmp
+
## begin gnulib module limits-h
ifeq (,$(OMIT_GNULIB_MODULE_limits-h))
@@ -1736,18 +2382,16 @@ BUILT_SOURCES += $(LIMITS_H)
# We need the following in order to create <limits.h> when the system
# doesn't have one that is compatible with GNU.
-ifneq (,$(GL_GENERATE_LIMITS_H))
+ifneq (,$(GL_GENERATE_LIMITS_H_CONDITION))
limits.h: limits.in.h $(top_builddir)/config.status
- $(AM_V_GEN)rm -f $@-t $@ && \
- { echo '/* DO NOT EDIT! GENERATED AUTOMATICALLY! */' && \
- sed -e 's|@''GUARD_PREFIX''@|GL|g' \
+ $(gl_V_at)$(SED_HEADER_STDOUT) \
+ -e 's|@''GUARD_PREFIX''@|GL|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_LIMITS_H''@|$(NEXT_LIMITS_H)|g' \
- < $(srcdir)/limits.in.h; \
- } > $@-t && \
- mv $@-t $@
+ $(srcdir)/limits.in.h > $@-t
+ $(AM_V_at)mv $@-t $@
else
limits.h: $(top_builddir)/config.status
rm -f $@
@@ -1759,37 +2403,69 @@ EXTRA_DIST += limits.in.h
endif
## end gnulib module limits-h
-## begin gnulib module localtime-buffer
-ifeq (,$(OMIT_GNULIB_MODULE_localtime-buffer))
+## begin gnulib module lstat
+ifeq (,$(OMIT_GNULIB_MODULE_lstat))
-ifneq (,$(gl_GNULIB_ENABLED_2049e887c7e5308faad27b3f894bb8c9))
+ifneq (,$(GL_COND_OBJ_LSTAT_CONDITION))
+libgnu_a_SOURCES += lstat.c
+endif
endif
-EXTRA_DIST += localtime-buffer.c localtime-buffer.h
+## end gnulib module lstat
-EXTRA_libgnu_a_SOURCES += localtime-buffer.c
+## begin gnulib module malloc-gnu
+ifeq (,$(OMIT_GNULIB_MODULE_malloc-gnu))
+
+ifneq (,$(gl_GNULIB_ENABLED_e80bf6f757095d2e5fc94dafb8f8fc8b_CONDITION))
endif
-## end gnulib module localtime-buffer
+EXTRA_DIST += malloc.c
-## begin gnulib module lstat
-ifeq (,$(OMIT_GNULIB_MODULE_lstat))
+EXTRA_libgnu_a_SOURCES += malloc.c
+endif
+## end gnulib module malloc-gnu
-EXTRA_DIST += lstat.c
+## begin gnulib module malloc-posix
+ifeq (,$(OMIT_GNULIB_MODULE_malloc-posix))
-EXTRA_libgnu_a_SOURCES += lstat.c
+ifneq (,$(gl_GNULIB_ENABLED_ef455225c00f5049c808c2eda3e76866_CONDITION))
endif
-## end gnulib module lstat
+EXTRA_DIST += malloc.c
+
+EXTRA_libgnu_a_SOURCES += malloc.c
+
+endif
+## end gnulib module malloc-posix
+
+## begin gnulib module memmem-simple
+ifeq (,$(OMIT_GNULIB_MODULE_memmem-simple))
-## begin gnulib module memrchr
-ifeq (,$(OMIT_GNULIB_MODULE_memrchr))
+EXTRA_DIST += memmem.c str-two-way.h
+
+EXTRA_libgnu_a_SOURCES += memmem.c
+
+endif
+## end gnulib module memmem-simple
+
+## begin gnulib module mempcpy
+ifeq (,$(OMIT_GNULIB_MODULE_mempcpy))
+
+ifneq (,$(GL_COND_OBJ_MEMPCPY_CONDITION))
+libgnu_a_SOURCES += mempcpy.c
+endif
+
+endif
+## end gnulib module mempcpy
-EXTRA_DIST += memrchr.c
+## begin gnulib module memrchr
+ifeq (,$(OMIT_GNULIB_MODULE_memrchr))
-EXTRA_libgnu_a_SOURCES += memrchr.c
+ifneq (,$(GL_COND_OBJ_MEMRCHR_CONDITION))
+libgnu_a_SOURCES += memrchr.c
+endif
endif
## end gnulib module memrchr
@@ -1805,10 +2481,9 @@ endif
## begin gnulib module mkostemp
ifeq (,$(OMIT_GNULIB_MODULE_mkostemp))
-
-EXTRA_DIST += mkostemp.c
-
-EXTRA_libgnu_a_SOURCES += mkostemp.c
+ifneq (,$(GL_COND_OBJ_MKOSTEMP_CONDITION))
+libgnu_a_SOURCES += mkostemp.c
+endif
endif
## end gnulib module mkostemp
@@ -1827,7 +2502,7 @@ endif
## begin gnulib module mktime-internal
ifeq (,$(OMIT_GNULIB_MODULE_mktime-internal))
-ifneq (,$(gl_GNULIB_ENABLED_5264294aa0a5557541b53c8c741f7f31))
+ifneq (,$(gl_GNULIB_ENABLED_5264294aa0a5557541b53c8c741f7f31_CONDITION))
endif
EXTRA_DIST += mktime-internal.h mktime.c
@@ -1837,6 +2512,26 @@ EXTRA_libgnu_a_SOURCES += mktime.c
endif
## end gnulib module mktime-internal
+## begin gnulib module nanosleep
+ifeq (,$(OMIT_GNULIB_MODULE_nanosleep))
+
+ifneq (,$(GL_COND_OBJ_NANOSLEEP_CONDITION))
+libgnu_a_SOURCES += nanosleep.c
+endif
+
+endif
+## end gnulib module nanosleep
+
+## begin gnulib module nproc
+ifeq (,$(OMIT_GNULIB_MODULE_nproc))
+
+libgnu_a_SOURCES += nproc.c
+
+EXTRA_DIST += nproc.h
+
+endif
+## end gnulib module nproc
+
## begin gnulib module nstrftime
ifeq (,$(OMIT_GNULIB_MODULE_nstrftime))
@@ -1850,20 +2545,19 @@ endif
## begin gnulib module open
ifeq (,$(OMIT_GNULIB_MODULE_open))
-ifneq (,$(gl_GNULIB_ENABLED_open))
-
+ifneq (,$(gl_GNULIB_ENABLED_open_CONDITION))
+ifneq (,$(GL_COND_OBJ_OPEN_CONDITION))
+libgnu_a_SOURCES += open.c
endif
-EXTRA_DIST += open.c
-
-EXTRA_libgnu_a_SOURCES += open.c
endif
+endif
## end gnulib module open
## begin gnulib module openat-h
ifeq (,$(OMIT_GNULIB_MODULE_openat-h))
-ifneq (,$(gl_GNULIB_ENABLED_03e0aaad4cb89ca757653bd367a6ccb7))
+ifneq (,$(gl_GNULIB_ENABLED_03e0aaad4cb89ca757653bd367a6ccb7_CONDITION))
endif
EXTRA_DIST += openat.h
@@ -1871,6 +2565,15 @@ EXTRA_DIST += openat.h
endif
## end gnulib module openat-h
+## begin gnulib module pathmax
+ifeq (,$(OMIT_GNULIB_MODULE_pathmax))
+
+
+EXTRA_DIST += pathmax.h
+
+endif
+## end gnulib module pathmax
+
## begin gnulib module pipe2
ifeq (,$(OMIT_GNULIB_MODULE_pipe2))
@@ -1882,10 +2585,9 @@ endif
## begin gnulib module pselect
ifeq (,$(OMIT_GNULIB_MODULE_pselect))
-
-EXTRA_DIST += pselect.c
-
-EXTRA_libgnu_a_SOURCES += pselect.c
+ifneq (,$(GL_COND_OBJ_PSELECT_CONDITION))
+libgnu_a_SOURCES += pselect.c
+endif
endif
## end gnulib module pselect
@@ -1893,40 +2595,41 @@ endif
## begin gnulib module pthread_sigmask
ifeq (,$(OMIT_GNULIB_MODULE_pthread_sigmask))
-
-EXTRA_DIST += pthread_sigmask.c
-
-EXTRA_libgnu_a_SOURCES += pthread_sigmask.c
+ifneq (,$(GL_COND_OBJ_PTHREAD_SIGMASK_CONDITION))
+libgnu_a_SOURCES += pthread_sigmask.c
+endif
endif
## end gnulib module pthread_sigmask
-## begin gnulib module putenv
-ifeq (,$(OMIT_GNULIB_MODULE_putenv))
+## begin gnulib module qcopy-acl
+ifeq (,$(OMIT_GNULIB_MODULE_qcopy-acl))
+libgnu_a_SOURCES += qcopy-acl.c
-EXTRA_DIST += putenv.c
+endif
+## end gnulib module qcopy-acl
-EXTRA_libgnu_a_SOURCES += putenv.c
+## begin gnulib module rawmemchr
+ifeq (,$(OMIT_GNULIB_MODULE_rawmemchr))
+ifneq (,$(gl_GNULIB_ENABLED_rawmemchr_CONDITION))
+ifneq (,$(GL_COND_OBJ_RAWMEMCHR_CONDITION))
+libgnu_a_SOURCES += rawmemchr.c
endif
-## end gnulib module putenv
-
-## begin gnulib module qcopy-acl
-ifeq (,$(OMIT_GNULIB_MODULE_qcopy-acl))
-libgnu_a_SOURCES += qcopy-acl.c
+endif
+EXTRA_DIST += rawmemchr.valgrind
endif
-## end gnulib module qcopy-acl
+## end gnulib module rawmemchr
## begin gnulib module readlink
ifeq (,$(OMIT_GNULIB_MODULE_readlink))
-
-EXTRA_DIST += readlink.c
-
-EXTRA_libgnu_a_SOURCES += readlink.c
+ifneq (,$(GL_COND_OBJ_READLINK_CONDITION))
+libgnu_a_SOURCES += readlink.c
+endif
endif
## end gnulib module readlink
@@ -1934,18 +2637,61 @@ endif
## begin gnulib module readlinkat
ifeq (,$(OMIT_GNULIB_MODULE_readlinkat))
+ifneq (,$(GL_COND_OBJ_READLINKAT_CONDITION))
+libgnu_a_SOURCES += readlinkat.c
+endif
-EXTRA_DIST += at-func.c readlinkat.c
+EXTRA_DIST += at-func.c
-EXTRA_libgnu_a_SOURCES += at-func.c readlinkat.c
+EXTRA_libgnu_a_SOURCES += at-func.c
endif
## end gnulib module readlinkat
+## begin gnulib module realloc-gnu
+ifeq (,$(OMIT_GNULIB_MODULE_realloc-gnu))
+
+ifneq (,$(gl_GNULIB_ENABLED_d3b2383720ee0e541357aa2aac598e2b_CONDITION))
+
+endif
+EXTRA_DIST += realloc.c
+
+EXTRA_libgnu_a_SOURCES += realloc.c
+
+endif
+## end gnulib module realloc-gnu
+
+## begin gnulib module realloc-posix
+ifeq (,$(OMIT_GNULIB_MODULE_realloc-posix))
+
+ifneq (,$(gl_GNULIB_ENABLED_61bcaca76b3e6f9ae55d57a1c3193bc4_CONDITION))
+
+endif
+EXTRA_DIST += realloc.c
+
+EXTRA_libgnu_a_SOURCES += realloc.c
+
+endif
+## end gnulib module realloc-posix
+
+## begin gnulib module regex
+ifeq (,$(OMIT_GNULIB_MODULE_regex))
+
+ifneq (,$(GL_COND_OBJ_REGEX_CONDITION))
+libgnu_a_SOURCES += regex.c
+endif
+
+EXTRA_DIST += regcomp.c regex.h regex_internal.c regex_internal.h regexec.c
+
+EXTRA_libgnu_a_SOURCES += regcomp.c regex_internal.c regexec.c
+
+endif
+## end gnulib module regex
+
## begin gnulib module root-uid
ifeq (,$(OMIT_GNULIB_MODULE_root-uid))
-ifneq (,$(gl_GNULIB_ENABLED_6099e9737f757db36c47fa9d9f02e88c))
+ifneq (,$(gl_GNULIB_ENABLED_6099e9737f757db36c47fa9d9f02e88c_CONDITION))
endif
EXTRA_DIST += root-uid.h
@@ -1953,17 +2699,53 @@ EXTRA_DIST += root-uid.h
endif
## end gnulib module root-uid
+## begin gnulib module scratch_buffer
+ifeq (,$(OMIT_GNULIB_MODULE_scratch_buffer))
+
+ifneq (,$(gl_GNULIB_ENABLED_scratch_buffer_CONDITION))
+BUILT_SOURCES += malloc/scratch_buffer.gl.h
+
+malloc/scratch_buffer.gl.h: malloc/scratch_buffer.h
+ $(AM_V_GEN)$(MKDIR_P) 'malloc'
+ $(AM_V_at)$(SED_HEADER_STDOUT) \
+ -e 's|__always_inline|inline _GL_ATTRIBUTE_ALWAYS_INLINE|g' \
+ -e 's|__glibc_likely|_GL_LIKELY|g' \
+ -e 's|__glibc_unlikely|_GL_UNLIKELY|g' \
+ -e '/libc_hidden_proto/d' \
+ $(srcdir)/malloc/scratch_buffer.h > $@-t
+ $(AM_V_at)mv $@-t $@
+MOSTLYCLEANFILES += malloc/scratch_buffer.gl.h malloc/scratch_buffer.gl.h-t
+
+libgnu_a_SOURCES += malloc/scratch_buffer_dupfree.c malloc/scratch_buffer_grow.c malloc/scratch_buffer_grow_preserve.c malloc/scratch_buffer_set_array_size.c
+
+endif
+EXTRA_DIST += malloc/scratch_buffer.h scratch_buffer.h
+
+endif
+## end gnulib module scratch_buffer
+
## begin gnulib module sig2str
ifeq (,$(OMIT_GNULIB_MODULE_sig2str))
+ifneq (,$(GL_COND_OBJ_SIG2STR_CONDITION))
+libgnu_a_SOURCES += sig2str.c
+endif
-EXTRA_DIST += sig2str.c sig2str.h
-
-EXTRA_libgnu_a_SOURCES += sig2str.c
+EXTRA_DIST += sig2str.h
endif
## end gnulib module sig2str
+## begin gnulib module sigdescr_np
+ifeq (,$(OMIT_GNULIB_MODULE_sigdescr_np))
+
+ifneq (,$(GL_COND_OBJ_SIGDESCR_NP_CONDITION))
+libgnu_a_SOURCES += sigdescr_np.c
+endif
+
+endif
+## end gnulib module sigdescr_np
+
## begin gnulib module signal-h
ifeq (,$(OMIT_GNULIB_MODULE_signal-h))
@@ -1972,18 +2754,17 @@ BUILT_SOURCES += signal.h
# We need the following in order to create <signal.h> when the system
# doesn't have a complete one.
signal.h: signal.in.h $(top_builddir)/config.status $(CXXDEFS_H) $(ARG_NONNULL_H) $(WARN_ON_USE_H)
- $(AM_V_GEN)rm -f $@-t $@ && \
- { echo '/* DO NOT EDIT! GENERATED AUTOMATICALLY! */' && \
- sed -e 's|@''GUARD_PREFIX''@|GL|g' \
+ $(gl_V_at)$(SED_HEADER_STDOUT) \
+ -e 's|@''GUARD_PREFIX''@|GL|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_SIGNAL_H''@|$(NEXT_SIGNAL_H)|g' \
- -e 's|@''GNULIB_PTHREAD_SIGMASK''@|$(GNULIB_PTHREAD_SIGMASK)|g' \
- -e 's|@''GNULIB_RAISE''@|$(GNULIB_RAISE)|g' \
- -e 's/@''GNULIB_SIGNAL_H_SIGPIPE''@/$(GNULIB_SIGNAL_H_SIGPIPE)/g' \
- -e 's/@''GNULIB_SIGPROCMASK''@/$(GNULIB_SIGPROCMASK)/g' \
- -e 's/@''GNULIB_SIGACTION''@/$(GNULIB_SIGACTION)/g' \
+ -e 's/@''GNULIB_PTHREAD_SIGMASK''@/$(GL_GNULIB_PTHREAD_SIGMASK)/g' \
+ -e 's/@''GNULIB_RAISE''@/$(GL_GNULIB_RAISE)/g' \
+ -e 's/@''GNULIB_SIGNAL_H_SIGPIPE''@/$(GL_GNULIB_SIGNAL_H_SIGPIPE)/g' \
+ -e 's/@''GNULIB_SIGPROCMASK''@/$(GL_GNULIB_SIGPROCMASK)/g' \
+ -e 's/@''GNULIB_SIGACTION''@/$(GL_GNULIB_SIGACTION)/g' \
-e 's|@''HAVE_POSIX_SIGNALBLOCKING''@|$(HAVE_POSIX_SIGNALBLOCKING)|g' \
-e 's|@''HAVE_PTHREAD_SIGMASK''@|$(HAVE_PTHREAD_SIGMASK)|g' \
-e 's|@''HAVE_RAISE''@|$(HAVE_RAISE)|g' \
@@ -1998,9 +2779,8 @@ signal.h: signal.in.h $(top_builddir)/config.status $(CXXDEFS_H) $(ARG_NONNULL_H
-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)' \
- < $(srcdir)/signal.in.h; \
- } > $@-t && \
- mv $@-t $@
+ $(srcdir)/signal.in.h > $@-t
+ $(AM_V_at)mv $@-t $@
MOSTLYCLEANFILES += signal.h signal.h-t
EXTRA_DIST += signal.in.h
@@ -2081,13 +2861,10 @@ BUILT_SOURCES += $(STDALIGN_H)
# We need the following in order to create <stdalign.h> when the system
# doesn't have one that works.
-ifneq (,$(GL_GENERATE_STDALIGN_H))
+ifneq (,$(GL_GENERATE_STDALIGN_H_CONDITION))
stdalign.h: stdalign.in.h $(top_builddir)/config.status
- $(AM_V_GEN)rm -f $@-t $@ && \
- { echo '/* DO NOT EDIT! GENERATED AUTOMATICALLY! */'; \
- cat $(srcdir)/stdalign.in.h; \
- } > $@-t && \
- mv $@-t $@
+ $(gl_V_at)$(SED_HEADER_TO_AT_t) $(srcdir)/stdalign.in.h
+ $(AM_V_at)mv $@-t $@
else
stdalign.h: $(top_builddir)/config.status
rm -f $@
@@ -2099,6 +2876,31 @@ EXTRA_DIST += stdalign.in.h
endif
## end gnulib module stdalign
+## begin gnulib module stdckdint
+ifeq (,$(OMIT_GNULIB_MODULE_stdckdint))
+
+ifneq (,$(gl_GNULIB_ENABLED_stdckdint_CONDITION))
+BUILT_SOURCES += $(STDCKDINT_H)
+
+# We need the following in order to create <stdckdint.h> when the system
+# doesn't have one that works with the given compiler.
+ifneq (,$(GL_GENERATE_STDCKDINT_H_CONDITION))
+stdckdint.h: stdckdint.in.h $(top_builddir)/config.status
+ $(gl_V_at)$(SED_HEADER_STDOUT) \
+ $(srcdir)/stdckdint.in.h > $@-t
+ $(AM_V_at)mv $@-t $@
+else
+stdckdint.h: $(top_builddir)/config.status
+ rm -f $@
+endif
+MOSTLYCLEANFILES += stdckdint.h stdckdint.h-t
+
+endif
+EXTRA_DIST += intprops-internal.h stdckdint.in.h
+
+endif
+## end gnulib module stdckdint
+
## begin gnulib module stddef
ifeq (,$(OMIT_GNULIB_MODULE_stddef))
@@ -2106,11 +2908,10 @@ BUILT_SOURCES += $(STDDEF_H)
# We need the following in order to create <stddef.h> when the system
# doesn't have one that works with the given compiler.
-ifneq (,$(GL_GENERATE_STDDEF_H))
+ifneq (,$(GL_GENERATE_STDDEF_H_CONDITION))
stddef.h: stddef.in.h $(top_builddir)/config.status
- $(AM_V_GEN)rm -f $@-t $@ && \
- { echo '/* DO NOT EDIT! GENERATED AUTOMATICALLY! */' && \
- sed -e 's|@''GUARD_PREFIX''@|GL|g' \
+ $(gl_V_at)$(SED_HEADER_STDOUT) \
+ -e 's|@''GUARD_PREFIX''@|GL|g' \
-e 's|@''INCLUDE_NEXT''@|$(INCLUDE_NEXT)|g' \
-e 's|@''PRAGMA_SYSTEM_HEADER''@|@PRAGMA_SYSTEM_HEADER@|g' \
-e 's|@''PRAGMA_COLUMNS''@|@PRAGMA_COLUMNS@|g' \
@@ -2118,9 +2919,8 @@ stddef.h: stddef.in.h $(top_builddir)/config.status
-e 's|@''HAVE_MAX_ALIGN_T''@|$(HAVE_MAX_ALIGN_T)|g' \
-e 's|@''HAVE_WCHAR_T''@|$(HAVE_WCHAR_T)|g' \
-e 's|@''REPLACE_NULL''@|$(REPLACE_NULL)|g' \
- < $(srcdir)/stddef.in.h; \
- } > $@-t && \
- mv $@-t $@
+ $(srcdir)/stddef.in.h > $@-t
+ $(AM_V_at)mv $@-t $@
else
stddef.h: $(top_builddir)/config.status
rm -f $@
@@ -2139,11 +2939,10 @@ BUILT_SOURCES += $(STDINT_H)
# We need the following in order to create <stdint.h> when the system
# doesn't have one that works with the given compiler.
-ifneq (,$(GL_GENERATE_STDINT_H))
+ifneq (,$(GL_GENERATE_STDINT_H_CONDITION))
stdint.h: stdint.in.h $(top_builddir)/config.status
- $(AM_V_GEN)rm -f $@-t $@ && \
- { echo '/* DO NOT EDIT! GENERATED AUTOMATICALLY! */'; \
- sed -e 's|@''GUARD_PREFIX''@|GL|g' \
+ $(gl_V_at)$(SED_HEADER_STDOUT) \
+ -e 's|@''GUARD_PREFIX''@|GL|g' \
-e 's/@''HAVE_STDINT_H''@/$(HAVE_STDINT_H)/g' \
-e 's|@''INCLUDE_NEXT''@|$(INCLUDE_NEXT)|g' \
-e 's|@''PRAGMA_SYSTEM_HEADER''@|@PRAGMA_SYSTEM_HEADER@|g' \
@@ -2155,8 +2954,6 @@ stdint.h: 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' \
@@ -2171,10 +2968,9 @@ stdint.h: stdint.in.h $(top_builddir)/config.status
-e 's/@''BITSIZEOF_WINT_T''@/$(BITSIZEOF_WINT_T)/g' \
-e 's/@''HAVE_SIGNED_WINT_T''@/$(HAVE_SIGNED_WINT_T)/g' \
-e 's/@''WINT_T_SUFFIX''@/$(WINT_T_SUFFIX)/g' \
- -e 's/@''GNULIB_OVERRIDES_WINT_T''@/$(GNULIB_OVERRIDES_WINT_T)/g' \
- < $(srcdir)/stdint.in.h; \
- } > $@-t && \
- mv $@-t $@
+ -e 's/@''GNULIBHEADERS_OVERRIDE_WINT_T''@/$(GNULIBHEADERS_OVERRIDE_WINT_T)/g' \
+ $(srcdir)/stdint.in.h > $@-t
+ $(AM_V_at)mv $@-t $@
else
stdint.h: $(top_builddir)/config.status
rm -f $@
@@ -2194,68 +2990,75 @@ BUILT_SOURCES += stdio.h
# We need the following in order to create <stdio.h> when the system
# doesn't have one that works with the given compiler.
stdio.h: stdio.in.h $(top_builddir)/config.status $(CXXDEFS_H) $(ARG_NONNULL_H) $(WARN_ON_USE_H)
- $(AM_V_GEN)rm -f $@-t $@ && \
- { echo '/* DO NOT EDIT! GENERATED AUTOMATICALLY! */' && \
- sed -e 's|@''GUARD_PREFIX''@|GL|g' \
+ $(gl_V_at)$(SED_HEADER_STDOUT) \
+ -e 's|@''GUARD_PREFIX''@|GL|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_STDIO_H''@|$(NEXT_STDIO_H)|g' \
- -e 's/@''GNULIB_DPRINTF''@/$(GNULIB_DPRINTF)/g' \
- -e 's/@''GNULIB_FCLOSE''@/$(GNULIB_FCLOSE)/g' \
- -e 's/@''GNULIB_FDOPEN''@/$(GNULIB_FDOPEN)/g' \
- -e 's/@''GNULIB_FFLUSH''@/$(GNULIB_FFLUSH)/g' \
- -e 's/@''GNULIB_FGETC''@/$(GNULIB_FGETC)/g' \
- -e 's/@''GNULIB_FGETS''@/$(GNULIB_FGETS)/g' \
- -e 's/@''GNULIB_FOPEN''@/$(GNULIB_FOPEN)/g' \
- -e 's/@''GNULIB_FPRINTF''@/$(GNULIB_FPRINTF)/g' \
- -e 's/@''GNULIB_FPRINTF_POSIX''@/$(GNULIB_FPRINTF_POSIX)/g' \
- -e 's/@''GNULIB_FPURGE''@/$(GNULIB_FPURGE)/g' \
- -e 's/@''GNULIB_FPUTC''@/$(GNULIB_FPUTC)/g' \
- -e 's/@''GNULIB_FPUTS''@/$(GNULIB_FPUTS)/g' \
- -e 's/@''GNULIB_FREAD''@/$(GNULIB_FREAD)/g' \
- -e 's/@''GNULIB_FREOPEN''@/$(GNULIB_FREOPEN)/g' \
- -e 's/@''GNULIB_FSCANF''@/$(GNULIB_FSCANF)/g' \
- -e 's/@''GNULIB_FSEEK''@/$(GNULIB_FSEEK)/g' \
- -e 's/@''GNULIB_FSEEKO''@/$(GNULIB_FSEEKO)/g' \
- -e 's/@''GNULIB_FTELL''@/$(GNULIB_FTELL)/g' \
- -e 's/@''GNULIB_FTELLO''@/$(GNULIB_FTELLO)/g' \
- -e 's/@''GNULIB_FWRITE''@/$(GNULIB_FWRITE)/g' \
- -e 's/@''GNULIB_GETC''@/$(GNULIB_GETC)/g' \
- -e 's/@''GNULIB_GETCHAR''@/$(GNULIB_GETCHAR)/g' \
- -e 's/@''GNULIB_GETDELIM''@/$(GNULIB_GETDELIM)/g' \
- -e 's/@''GNULIB_GETLINE''@/$(GNULIB_GETLINE)/g' \
- -e 's/@''GNULIB_OBSTACK_PRINTF''@/$(GNULIB_OBSTACK_PRINTF)/g' \
- -e 's/@''GNULIB_OBSTACK_PRINTF_POSIX''@/$(GNULIB_OBSTACK_PRINTF_POSIX)/g' \
- -e 's/@''GNULIB_PCLOSE''@/$(GNULIB_PCLOSE)/g' \
- -e 's/@''GNULIB_PERROR''@/$(GNULIB_PERROR)/g' \
- -e 's/@''GNULIB_POPEN''@/$(GNULIB_POPEN)/g' \
- -e 's/@''GNULIB_PRINTF''@/$(GNULIB_PRINTF)/g' \
- -e 's/@''GNULIB_PRINTF_POSIX''@/$(GNULIB_PRINTF_POSIX)/g' \
- -e 's/@''GNULIB_PUTC''@/$(GNULIB_PUTC)/g' \
- -e 's/@''GNULIB_PUTCHAR''@/$(GNULIB_PUTCHAR)/g' \
- -e 's/@''GNULIB_PUTS''@/$(GNULIB_PUTS)/g' \
- -e 's/@''GNULIB_REMOVE''@/$(GNULIB_REMOVE)/g' \
- -e 's/@''GNULIB_RENAME''@/$(GNULIB_RENAME)/g' \
- -e 's/@''GNULIB_RENAMEAT''@/$(GNULIB_RENAMEAT)/g' \
- -e 's/@''GNULIB_SCANF''@/$(GNULIB_SCANF)/g' \
- -e 's/@''GNULIB_SNPRINTF''@/$(GNULIB_SNPRINTF)/g' \
- -e 's/@''GNULIB_SPRINTF_POSIX''@/$(GNULIB_SPRINTF_POSIX)/g' \
- -e 's/@''GNULIB_STDIO_H_NONBLOCKING''@/$(GNULIB_STDIO_H_NONBLOCKING)/g' \
- -e 's/@''GNULIB_STDIO_H_SIGPIPE''@/$(GNULIB_STDIO_H_SIGPIPE)/g' \
- -e 's/@''GNULIB_TMPFILE''@/$(GNULIB_TMPFILE)/g' \
- -e 's/@''GNULIB_VASPRINTF''@/$(GNULIB_VASPRINTF)/g' \
- -e 's/@''GNULIB_VDPRINTF''@/$(GNULIB_VDPRINTF)/g' \
- -e 's/@''GNULIB_VFPRINTF''@/$(GNULIB_VFPRINTF)/g' \
- -e 's/@''GNULIB_VFPRINTF_POSIX''@/$(GNULIB_VFPRINTF_POSIX)/g' \
- -e 's/@''GNULIB_VFSCANF''@/$(GNULIB_VFSCANF)/g' \
- -e 's/@''GNULIB_VSCANF''@/$(GNULIB_VSCANF)/g' \
- -e 's/@''GNULIB_VPRINTF''@/$(GNULIB_VPRINTF)/g' \
- -e 's/@''GNULIB_VPRINTF_POSIX''@/$(GNULIB_VPRINTF_POSIX)/g' \
- -e 's/@''GNULIB_VSNPRINTF''@/$(GNULIB_VSNPRINTF)/g' \
- -e 's/@''GNULIB_VSPRINTF_POSIX''@/$(GNULIB_VSPRINTF_POSIX)/g' \
+ -e 's/@''GNULIB_DPRINTF''@/$(GL_GNULIB_DPRINTF)/g' \
+ -e 's/@''GNULIB_FCLOSE''@/$(GL_GNULIB_FCLOSE)/g' \
+ -e 's/@''GNULIB_FDOPEN''@/$(GL_GNULIB_FDOPEN)/g' \
+ -e 's/@''GNULIB_FFLUSH''@/$(GL_GNULIB_FFLUSH)/g' \
+ -e 's/@''GNULIB_FGETC''@/$(GL_GNULIB_FGETC)/g' \
+ -e 's/@''GNULIB_FGETS''@/$(GL_GNULIB_FGETS)/g' \
+ -e 's/@''GNULIB_FOPEN''@/$(GL_GNULIB_FOPEN)/g' \
+ -e 's/@''GNULIB_FOPEN_GNU''@/$(GL_GNULIB_FOPEN_GNU)/g' \
+ -e 's/@''GNULIB_FPRINTF''@/$(GL_GNULIB_FPRINTF)/g' \
+ -e 's/@''GNULIB_FPRINTF_POSIX''@/$(GL_GNULIB_FPRINTF_POSIX)/g' \
+ -e 's/@''GNULIB_FPURGE''@/$(GL_GNULIB_FPURGE)/g' \
+ -e 's/@''GNULIB_FPUTC''@/$(GL_GNULIB_FPUTC)/g' \
+ -e 's/@''GNULIB_FPUTS''@/$(GL_GNULIB_FPUTS)/g' \
+ -e 's/@''GNULIB_FREAD''@/$(GL_GNULIB_FREAD)/g' \
+ -e 's/@''GNULIB_FREOPEN''@/$(GL_GNULIB_FREOPEN)/g' \
+ -e 's/@''GNULIB_FSCANF''@/$(GL_GNULIB_FSCANF)/g' \
+ -e 's/@''GNULIB_FSEEK''@/$(GL_GNULIB_FSEEK)/g' \
+ -e 's/@''GNULIB_FSEEKO''@/$(GL_GNULIB_FSEEKO)/g' \
+ -e 's/@''GNULIB_FTELL''@/$(GL_GNULIB_FTELL)/g' \
+ -e 's/@''GNULIB_FTELLO''@/$(GL_GNULIB_FTELLO)/g' \
+ -e 's/@''GNULIB_FWRITE''@/$(GL_GNULIB_FWRITE)/g' \
+ -e 's/@''GNULIB_GETC''@/$(GL_GNULIB_GETC)/g' \
+ -e 's/@''GNULIB_GETCHAR''@/$(GL_GNULIB_GETCHAR)/g' \
+ -e 's/@''GNULIB_GETDELIM''@/$(GL_GNULIB_GETDELIM)/g' \
+ -e 's/@''GNULIB_GETLINE''@/$(GL_GNULIB_GETLINE)/g' \
+ -e 's/@''GNULIB_OBSTACK_PRINTF''@/$(GL_GNULIB_OBSTACK_PRINTF)/g' \
+ -e 's/@''GNULIB_OBSTACK_PRINTF_POSIX''@/$(GL_GNULIB_OBSTACK_PRINTF_POSIX)/g' \
+ -e 's/@''GNULIB_PCLOSE''@/$(GL_GNULIB_PCLOSE)/g' \
+ -e 's/@''GNULIB_PERROR''@/$(GL_GNULIB_PERROR)/g' \
+ -e 's/@''GNULIB_POPEN''@/$(GL_GNULIB_POPEN)/g' \
+ -e 's/@''GNULIB_PRINTF''@/$(GL_GNULIB_PRINTF)/g' \
+ -e 's/@''GNULIB_PRINTF_POSIX''@/$(GL_GNULIB_PRINTF_POSIX)/g' \
+ -e 's/@''GNULIB_PUTC''@/$(GL_GNULIB_PUTC)/g' \
+ -e 's/@''GNULIB_PUTCHAR''@/$(GL_GNULIB_PUTCHAR)/g' \
+ -e 's/@''GNULIB_PUTS''@/$(GL_GNULIB_PUTS)/g' \
+ -e 's/@''GNULIB_REMOVE''@/$(GL_GNULIB_REMOVE)/g' \
+ -e 's/@''GNULIB_RENAME''@/$(GL_GNULIB_RENAME)/g' \
+ -e 's/@''GNULIB_RENAMEAT''@/$(GL_GNULIB_RENAMEAT)/g' \
+ -e 's/@''GNULIB_SCANF''@/$(GL_GNULIB_SCANF)/g' \
+ -e 's/@''GNULIB_SNPRINTF''@/$(GL_GNULIB_SNPRINTF)/g' \
+ -e 's/@''GNULIB_SPRINTF_POSIX''@/$(GL_GNULIB_SPRINTF_POSIX)/g' \
+ -e 's/@''GNULIB_STDIO_H_NONBLOCKING''@/$(GL_GNULIB_STDIO_H_NONBLOCKING)/g' \
+ -e 's/@''GNULIB_STDIO_H_SIGPIPE''@/$(GL_GNULIB_STDIO_H_SIGPIPE)/g' \
+ -e 's/@''GNULIB_TMPFILE''@/$(GL_GNULIB_TMPFILE)/g' \
+ -e 's/@''GNULIB_VASPRINTF''@/$(GL_GNULIB_VASPRINTF)/g' \
+ -e 's/@''GNULIB_VDPRINTF''@/$(GL_GNULIB_VDPRINTF)/g' \
+ -e 's/@''GNULIB_VFPRINTF''@/$(GL_GNULIB_VFPRINTF)/g' \
+ -e 's/@''GNULIB_VFPRINTF_POSIX''@/$(GL_GNULIB_VFPRINTF_POSIX)/g' \
+ -e 's/@''GNULIB_VFSCANF''@/$(GL_GNULIB_VFSCANF)/g' \
+ -e 's/@''GNULIB_VSCANF''@/$(GL_GNULIB_VSCANF)/g' \
+ -e 's/@''GNULIB_VPRINTF''@/$(GL_GNULIB_VPRINTF)/g' \
+ -e 's/@''GNULIB_VPRINTF_POSIX''@/$(GL_GNULIB_VPRINTF_POSIX)/g' \
+ -e 's/@''GNULIB_VSNPRINTF''@/$(GL_GNULIB_VSNPRINTF)/g' \
+ -e 's/@''GNULIB_VSPRINTF_POSIX''@/$(GL_GNULIB_VSPRINTF_POSIX)/g' \
+ -e 's/@''GNULIB_MDA_FCLOSEALL''@/$(GL_GNULIB_MDA_FCLOSEALL)/g' \
+ -e 's/@''GNULIB_MDA_FDOPEN''@/$(GL_GNULIB_MDA_FDOPEN)/g' \
+ -e 's/@''GNULIB_MDA_FILENO''@/$(GL_GNULIB_MDA_FILENO)/g' \
+ -e 's/@''GNULIB_MDA_GETW''@/$(GL_GNULIB_MDA_GETW)/g' \
+ -e 's/@''GNULIB_MDA_PUTW''@/$(GL_GNULIB_MDA_PUTW)/g' \
+ -e 's/@''GNULIB_MDA_TEMPNAM''@/$(GL_GNULIB_MDA_TEMPNAM)/g' \
< $(srcdir)/stdio.in.h | \
- sed -e 's|@''HAVE_DECL_FPURGE''@|$(HAVE_DECL_FPURGE)|g' \
+ sed -e 's|@''HAVE_DECL_FCLOSEALL''@|$(HAVE_DECL_FCLOSEALL)|g' \
+ -e 's|@''HAVE_DECL_FPURGE''@|$(HAVE_DECL_FPURGE)|g' \
-e 's|@''HAVE_DECL_FSEEKO''@|$(HAVE_DECL_FSEEKO)|g' \
-e 's|@''HAVE_DECL_FTELLO''@|$(HAVE_DECL_FTELLO)|g' \
-e 's|@''HAVE_DECL_GETDELIM''@|$(HAVE_DECL_GETDELIM)|g' \
@@ -2276,6 +3079,7 @@ stdio.h: stdio.in.h $(top_builddir)/config.status $(CXXDEFS_H) $(ARG_NONNULL_H)
-e 's|@''REPLACE_FDOPEN''@|$(REPLACE_FDOPEN)|g' \
-e 's|@''REPLACE_FFLUSH''@|$(REPLACE_FFLUSH)|g' \
-e 's|@''REPLACE_FOPEN''@|$(REPLACE_FOPEN)|g' \
+ -e 's|@''REPLACE_FOPEN_FOR_FOPEN_GNU''@|$(REPLACE_FOPEN_FOR_FOPEN_GNU)|g' \
-e 's|@''REPLACE_FPRINTF''@|$(REPLACE_FPRINTF)|g' \
-e 's|@''REPLACE_FPURGE''@|$(REPLACE_FPURGE)|g' \
-e 's|@''REPLACE_FREOPEN''@|$(REPLACE_FREOPEN)|g' \
@@ -2306,11 +3110,18 @@ stdio.h: stdio.in.h $(top_builddir)/config.status $(CXXDEFS_H) $(ARG_NONNULL_H)
-e 's|@''ASM_SYMBOL_PREFIX''@|$(ASM_SYMBOL_PREFIX)|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)'; \
- } > $@-t && \
- mv $@-t $@
+ -e '/definition of _GL_WARN_ON_USE/r $(WARN_ON_USE_H)' \
+ > $@-t
+ $(AM_V_at)mv $@-t $@
MOSTLYCLEANFILES += stdio.h stdio.h-t
+ifneq (,$(GL_COND_OBJ_STDIO_READ_CONDITION))
+libgnu_a_SOURCES += stdio-read.c
+endif
+ifneq (,$(GL_COND_OBJ_STDIO_WRITE_CONDITION))
+libgnu_a_SOURCES += stdio-write.c
+endif
+
EXTRA_DIST += stdio.in.h
endif
@@ -2325,60 +3136,80 @@ BUILT_SOURCES += stdlib.h
# doesn't have one that works with the given compiler.
stdlib.h: stdlib.in.h $(top_builddir)/config.status $(CXXDEFS_H) \
$(_NORETURN_H) $(ARG_NONNULL_H) $(WARN_ON_USE_H)
- $(AM_V_GEN)rm -f $@-t $@ && \
- { echo '/* DO NOT EDIT! GENERATED AUTOMATICALLY! */' && \
- sed -e 's|@''GUARD_PREFIX''@|GL|g' \
+ $(gl_V_at)$(SED_HEADER_STDOUT) \
+ -e 's|@''GUARD_PREFIX''@|GL|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_STDLIB_H''@|$(NEXT_STDLIB_H)|g' \
- -e 's/@''GNULIB__EXIT''@/$(GNULIB__EXIT)/g' \
- -e 's/@''GNULIB_ATOLL''@/$(GNULIB_ATOLL)/g' \
- -e 's/@''GNULIB_CALLOC_POSIX''@/$(GNULIB_CALLOC_POSIX)/g' \
- -e 's/@''GNULIB_CANONICALIZE_FILE_NAME''@/$(GNULIB_CANONICALIZE_FILE_NAME)/g' \
- -e 's/@''GNULIB_GETLOADAVG''@/$(GNULIB_GETLOADAVG)/g' \
- -e 's/@''GNULIB_GETSUBOPT''@/$(GNULIB_GETSUBOPT)/g' \
- -e 's/@''GNULIB_GRANTPT''@/$(GNULIB_GRANTPT)/g' \
- -e 's/@''GNULIB_MALLOC_POSIX''@/$(GNULIB_MALLOC_POSIX)/g' \
- -e 's/@''GNULIB_MBTOWC''@/$(GNULIB_MBTOWC)/g' \
- -e 's/@''GNULIB_MKDTEMP''@/$(GNULIB_MKDTEMP)/g' \
- -e 's/@''GNULIB_MKOSTEMP''@/$(GNULIB_MKOSTEMP)/g' \
- -e 's/@''GNULIB_MKOSTEMPS''@/$(GNULIB_MKOSTEMPS)/g' \
- -e 's/@''GNULIB_MKSTEMP''@/$(GNULIB_MKSTEMP)/g' \
- -e 's/@''GNULIB_MKSTEMPS''@/$(GNULIB_MKSTEMPS)/g' \
- -e 's/@''GNULIB_POSIX_OPENPT''@/$(GNULIB_POSIX_OPENPT)/g' \
- -e 's/@''GNULIB_PTSNAME''@/$(GNULIB_PTSNAME)/g' \
- -e 's/@''GNULIB_PTSNAME_R''@/$(GNULIB_PTSNAME_R)/g' \
- -e 's/@''GNULIB_PUTENV''@/$(GNULIB_PUTENV)/g' \
- -e 's/@''GNULIB_QSORT_R''@/$(GNULIB_QSORT_R)/g' \
- -e 's/@''GNULIB_RANDOM''@/$(GNULIB_RANDOM)/g' \
- -e 's/@''GNULIB_RANDOM_R''@/$(GNULIB_RANDOM_R)/g' \
- -e 's/@''GNULIB_REALLOC_POSIX''@/$(GNULIB_REALLOC_POSIX)/g' \
- -e 's/@''GNULIB_REALLOCARRAY''@/$(GNULIB_REALLOCARRAY)/g' \
- -e 's/@''GNULIB_REALPATH''@/$(GNULIB_REALPATH)/g' \
- -e 's/@''GNULIB_RPMATCH''@/$(GNULIB_RPMATCH)/g' \
- -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_STRTOLL''@/$(GNULIB_STRTOLL)/g' \
- -e 's/@''GNULIB_STRTOULL''@/$(GNULIB_STRTOULL)/g' \
- -e 's/@''GNULIB_SYSTEM_POSIX''@/$(GNULIB_SYSTEM_POSIX)/g' \
- -e 's/@''GNULIB_UNLOCKPT''@/$(GNULIB_UNLOCKPT)/g' \
- -e 's/@''GNULIB_UNSETENV''@/$(GNULIB_UNSETENV)/g' \
- -e 's/@''GNULIB_WCTOMB''@/$(GNULIB_WCTOMB)/g' \
+ -e 's/@''GNULIB__EXIT''@/$(GL_GNULIB__EXIT)/g' \
+ -e 's/@''GNULIB_ALIGNED_ALLOC''@/$(GL_GNULIB_ALIGNED_ALLOC)/g' \
+ -e 's/@''GNULIB_ATOLL''@/$(GL_GNULIB_ATOLL)/g' \
+ -e 's/@''GNULIB_CALLOC_GNU''@/$(GL_GNULIB_CALLOC_GNU)/g' \
+ -e 's/@''GNULIB_CALLOC_POSIX''@/$(GL_GNULIB_CALLOC_POSIX)/g' \
+ -e 's/@''GNULIB_CANONICALIZE_FILE_NAME''@/$(GL_GNULIB_CANONICALIZE_FILE_NAME)/g' \
+ -e 's/@''GNULIB_FREE_POSIX''@/$(GL_GNULIB_FREE_POSIX)/g' \
+ -e 's/@''GNULIB_GETLOADAVG''@/$(GL_GNULIB_GETLOADAVG)/g' \
+ -e 's/@''GNULIB_GETSUBOPT''@/$(GL_GNULIB_GETSUBOPT)/g' \
+ -e 's/@''GNULIB_GRANTPT''@/$(GL_GNULIB_GRANTPT)/g' \
+ -e 's/@''GNULIB_MALLOC_GNU''@/$(GL_GNULIB_MALLOC_GNU)/g' \
+ -e 's/@''GNULIB_MALLOC_POSIX''@/$(GL_GNULIB_MALLOC_POSIX)/g' \
+ -e 's/@''GNULIB_MBTOWC''@/$(GL_GNULIB_MBTOWC)/g' \
+ -e 's/@''GNULIB_MKDTEMP''@/$(GL_GNULIB_MKDTEMP)/g' \
+ -e 's/@''GNULIB_MKOSTEMP''@/$(GL_GNULIB_MKOSTEMP)/g' \
+ -e 's/@''GNULIB_MKOSTEMPS''@/$(GL_GNULIB_MKOSTEMPS)/g' \
+ -e 's/@''GNULIB_MKSTEMP''@/$(GL_GNULIB_MKSTEMP)/g' \
+ -e 's/@''GNULIB_MKSTEMPS''@/$(GL_GNULIB_MKSTEMPS)/g' \
+ -e 's/@''GNULIB_POSIX_MEMALIGN''@/$(GL_GNULIB_POSIX_MEMALIGN)/g' \
+ -e 's/@''GNULIB_POSIX_OPENPT''@/$(GL_GNULIB_POSIX_OPENPT)/g' \
+ -e 's/@''GNULIB_PTSNAME''@/$(GL_GNULIB_PTSNAME)/g' \
+ -e 's/@''GNULIB_PTSNAME_R''@/$(GL_GNULIB_PTSNAME_R)/g' \
+ -e 's/@''GNULIB_PUTENV''@/$(GL_GNULIB_PUTENV)/g' \
+ -e 's/@''GNULIB_QSORT_R''@/$(GL_GNULIB_QSORT_R)/g' \
+ -e 's/@''GNULIB_RANDOM''@/$(GL_GNULIB_RANDOM)/g' \
+ -e 's/@''GNULIB_RANDOM_R''@/$(GL_GNULIB_RANDOM_R)/g' \
+ -e 's/@''GNULIB_REALLOC_GNU''@/$(GL_GNULIB_REALLOC_GNU)/g' \
+ -e 's/@''GNULIB_REALLOC_POSIX''@/$(GL_GNULIB_REALLOC_POSIX)/g' \
+ -e 's/@''GNULIB_REALLOCARRAY''@/$(GL_GNULIB_REALLOCARRAY)/g' \
+ -e 's/@''GNULIB_REALPATH''@/$(GL_GNULIB_REALPATH)/g' \
+ -e 's/@''GNULIB_RPMATCH''@/$(GL_GNULIB_RPMATCH)/g' \
+ -e 's/@''GNULIB_SECURE_GETENV''@/$(GL_GNULIB_SECURE_GETENV)/g' \
+ -e 's/@''GNULIB_SETENV''@/$(GL_GNULIB_SETENV)/g' \
+ -e 's/@''GNULIB_STRTOD''@/$(GL_GNULIB_STRTOD)/g' \
+ -e 's/@''GNULIB_STRTOL''@/$(GL_GNULIB_STRTOL)/g' \
+ -e 's/@''GNULIB_STRTOLD''@/$(GL_GNULIB_STRTOLD)/g' \
+ -e 's/@''GNULIB_STRTOLL''@/$(GL_GNULIB_STRTOLL)/g' \
+ -e 's/@''GNULIB_STRTOUL''@/$(GL_GNULIB_STRTOUL)/g' \
+ -e 's/@''GNULIB_STRTOULL''@/$(GL_GNULIB_STRTOULL)/g' \
+ -e 's/@''GNULIB_SYSTEM_POSIX''@/$(GL_GNULIB_SYSTEM_POSIX)/g' \
+ -e 's/@''GNULIB_UNLOCKPT''@/$(GL_GNULIB_UNLOCKPT)/g' \
+ -e 's/@''GNULIB_UNSETENV''@/$(GL_GNULIB_UNSETENV)/g' \
+ -e 's/@''GNULIB_WCTOMB''@/$(GL_GNULIB_WCTOMB)/g' \
+ -e 's/@''GNULIB_MDA_ECVT''@/$(GL_GNULIB_MDA_ECVT)/g' \
+ -e 's/@''GNULIB_MDA_FCVT''@/$(GL_GNULIB_MDA_FCVT)/g' \
+ -e 's/@''GNULIB_MDA_GCVT''@/$(GL_GNULIB_MDA_GCVT)/g' \
+ -e 's/@''GNULIB_MDA_MKTEMP''@/$(GL_GNULIB_MDA_MKTEMP)/g' \
+ -e 's/@''GNULIB_MDA_PUTENV''@/$(GL_GNULIB_MDA_PUTENV)/g' \
< $(srcdir)/stdlib.in.h | \
sed -e 's|@''HAVE__EXIT''@|$(HAVE__EXIT)|g' \
+ -e 's|@''HAVE_ALIGNED_ALLOC''@|$(HAVE_ALIGNED_ALLOC)|g' \
-e 's|@''HAVE_ATOLL''@|$(HAVE_ATOLL)|g' \
-e 's|@''HAVE_CANONICALIZE_FILE_NAME''@|$(HAVE_CANONICALIZE_FILE_NAME)|g' \
+ -e 's|@''HAVE_DECL_ECVT''@|$(HAVE_DECL_ECVT)|g' \
+ -e 's|@''HAVE_DECL_FCVT''@|$(HAVE_DECL_FCVT)|g' \
+ -e 's|@''HAVE_DECL_GCVT''@|$(HAVE_DECL_GCVT)|g' \
-e 's|@''HAVE_DECL_GETLOADAVG''@|$(HAVE_DECL_GETLOADAVG)|g' \
-e 's|@''HAVE_GETSUBOPT''@|$(HAVE_GETSUBOPT)|g' \
-e 's|@''HAVE_GRANTPT''@|$(HAVE_GRANTPT)|g' \
+ -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' \
-e 's|@''HAVE_MKSTEMP''@|$(HAVE_MKSTEMP)|g' \
-e 's|@''HAVE_MKSTEMPS''@|$(HAVE_MKSTEMPS)|g' \
+ -e 's|@''HAVE_POSIX_MEMALIGN''@|$(HAVE_POSIX_MEMALIGN)|g' \
-e 's|@''HAVE_POSIX_OPENPT''@|$(HAVE_POSIX_OPENPT)|g' \
-e 's|@''HAVE_PTSNAME''@|$(HAVE_PTSNAME)|g' \
-e 's|@''HAVE_PTSNAME_R''@|$(HAVE_PTSNAME_R)|g' \
@@ -2391,36 +3222,55 @@ stdlib.h: 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_STRTOL''@|$(HAVE_STRTOL)|g' \
+ -e 's|@''HAVE_STRTOLD''@|$(HAVE_STRTOLD)|g' \
-e 's|@''HAVE_STRTOLL''@|$(HAVE_STRTOLL)|g' \
+ -e 's|@''HAVE_STRTOUL''@|$(HAVE_STRTOUL)|g' \
-e 's|@''HAVE_STRTOULL''@|$(HAVE_STRTOULL)|g' \
-e 's|@''HAVE_STRUCT_RANDOM_DATA''@|$(HAVE_STRUCT_RANDOM_DATA)|g' \
-e 's|@''HAVE_SYS_LOADAVG_H''@|$(HAVE_SYS_LOADAVG_H)|g' \
-e 's|@''HAVE_UNLOCKPT''@|$(HAVE_UNLOCKPT)|g' \
-e 's|@''HAVE_DECL_UNSETENV''@|$(HAVE_DECL_UNSETENV)|g' \
- -e 's|@''REPLACE_CALLOC''@|$(REPLACE_CALLOC)|g' \
+ -e 's|@''REPLACE_ALIGNED_ALLOC''@|$(REPLACE_ALIGNED_ALLOC)|g' \
+ -e 's|@''REPLACE_CALLOC_FOR_CALLOC_GNU''@|$(REPLACE_CALLOC_FOR_CALLOC_GNU)|g' \
+ -e 's|@''REPLACE_CALLOC_FOR_CALLOC_POSIX''@|$(REPLACE_CALLOC_FOR_CALLOC_POSIX)|g' \
-e 's|@''REPLACE_CANONICALIZE_FILE_NAME''@|$(REPLACE_CANONICALIZE_FILE_NAME)|g' \
- -e 's|@''REPLACE_MALLOC''@|$(REPLACE_MALLOC)|g' \
+ -e 's|@''REPLACE_FREE''@|$(REPLACE_FREE)|g' \
+ -e 's|@''REPLACE_INITSTATE''@|$(REPLACE_INITSTATE)|g' \
+ -e 's|@''REPLACE_MALLOC_FOR_MALLOC_GNU''@|$(REPLACE_MALLOC_FOR_MALLOC_GNU)|g' \
+ -e 's|@''REPLACE_MALLOC_FOR_MALLOC_POSIX''@|$(REPLACE_MALLOC_FOR_MALLOC_POSIX)|g' \
-e 's|@''REPLACE_MBTOWC''@|$(REPLACE_MBTOWC)|g' \
-e 's|@''REPLACE_MKSTEMP''@|$(REPLACE_MKSTEMP)|g' \
+ -e 's|@''REPLACE_POSIX_MEMALIGN''@|$(REPLACE_POSIX_MEMALIGN)|g' \
-e 's|@''REPLACE_PTSNAME''@|$(REPLACE_PTSNAME)|g' \
-e 's|@''REPLACE_PTSNAME_R''@|$(REPLACE_PTSNAME_R)|g' \
-e 's|@''REPLACE_PUTENV''@|$(REPLACE_PUTENV)|g' \
-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_REALLOC_FOR_REALLOC_GNU''@|$(REPLACE_REALLOC_FOR_REALLOC_GNU)|g' \
+ -e 's|@''REPLACE_REALLOC_FOR_REALLOC_POSIX''@|$(REPLACE_REALLOC_FOR_REALLOC_POSIX)|g' \
+ -e 's|@''REPLACE_REALLOCARRAY''@|$(REPLACE_REALLOCARRAY)|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_STRTOL''@|$(REPLACE_STRTOL)|g' \
+ -e 's|@''REPLACE_STRTOLD''@|$(REPLACE_STRTOLD)|g' \
+ -e 's|@''REPLACE_STRTOLL''@|$(REPLACE_STRTOLL)|g' \
+ -e 's|@''REPLACE_STRTOUL''@|$(REPLACE_STRTOUL)|g' \
+ -e 's|@''REPLACE_STRTOULL''@|$(REPLACE_STRTOULL)|g' \
-e 's|@''REPLACE_UNSETENV''@|$(REPLACE_UNSETENV)|g' \
-e 's|@''REPLACE_WCTOMB''@|$(REPLACE_WCTOMB)|g' \
-e '/definitions of _GL_FUNCDECL_RPL/r $(CXXDEFS_H)' \
-e '/definition of _Noreturn/r $(_NORETURN_H)' \
-e '/definition of _GL_ARG_NONNULL/r $(ARG_NONNULL_H)' \
- -e '/definition of _GL_WARN_ON_USE/r $(WARN_ON_USE_H)'; \
- } > $@-t && \
- mv $@-t $@
+ -e '/definition of _GL_WARN_ON_USE/r $(WARN_ON_USE_H)' \
+ > $@-t
+ $(AM_V_at)mv $@-t $@
MOSTLYCLEANFILES += stdlib.h stdlib.h-t
EXTRA_DIST += stdlib.in.h
@@ -2431,10 +3281,9 @@ endif
## begin gnulib module stpcpy
ifeq (,$(OMIT_GNULIB_MODULE_stpcpy))
-
-EXTRA_DIST += stpcpy.c
-
-EXTRA_libgnu_a_SOURCES += stpcpy.c
+ifneq (,$(GL_COND_OBJ_STPCPY_CONDITION))
+libgnu_a_SOURCES += stpcpy.c
+endif
endif
## end gnulib module stpcpy
@@ -2447,57 +3296,61 @@ BUILT_SOURCES += string.h
# We need the following in order to create <string.h> when the system
# doesn't have one that works with the given compiler.
string.h: string.in.h $(top_builddir)/config.status $(CXXDEFS_H) $(ARG_NONNULL_H) $(WARN_ON_USE_H)
- $(AM_V_GEN)rm -f $@-t $@ && \
- { echo '/* DO NOT EDIT! GENERATED AUTOMATICALLY! */' && \
- sed -e 's|@''GUARD_PREFIX''@|GL|g' \
+ $(gl_V_at)$(SED_HEADER_STDOUT) \
+ -e 's|@''GUARD_PREFIX''@|GL|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_STRING_H''@|$(NEXT_STRING_H)|g' \
- -e 's/@''GNULIB_EXPLICIT_BZERO''@/$(GNULIB_EXPLICIT_BZERO)/g' \
- -e 's/@''GNULIB_FFSL''@/$(GNULIB_FFSL)/g' \
- -e 's/@''GNULIB_FFSLL''@/$(GNULIB_FFSLL)/g' \
- -e 's/@''GNULIB_MBSLEN''@/$(GNULIB_MBSLEN)/g' \
- -e 's/@''GNULIB_MBSNLEN''@/$(GNULIB_MBSNLEN)/g' \
- -e 's/@''GNULIB_MBSCHR''@/$(GNULIB_MBSCHR)/g' \
- -e 's/@''GNULIB_MBSRCHR''@/$(GNULIB_MBSRCHR)/g' \
- -e 's/@''GNULIB_MBSSTR''@/$(GNULIB_MBSSTR)/g' \
- -e 's/@''GNULIB_MBSCASECMP''@/$(GNULIB_MBSCASECMP)/g' \
- -e 's/@''GNULIB_MBSNCASECMP''@/$(GNULIB_MBSNCASECMP)/g' \
- -e 's/@''GNULIB_MBSPCASECMP''@/$(GNULIB_MBSPCASECMP)/g' \
- -e 's/@''GNULIB_MBSCASESTR''@/$(GNULIB_MBSCASESTR)/g' \
- -e 's/@''GNULIB_MBSCSPN''@/$(GNULIB_MBSCSPN)/g' \
- -e 's/@''GNULIB_MBSPBRK''@/$(GNULIB_MBSPBRK)/g' \
- -e 's/@''GNULIB_MBSSPN''@/$(GNULIB_MBSSPN)/g' \
- -e 's/@''GNULIB_MBSSEP''@/$(GNULIB_MBSSEP)/g' \
- -e 's/@''GNULIB_MBSTOK_R''@/$(GNULIB_MBSTOK_R)/g' \
- -e 's/@''GNULIB_MEMCHR''@/$(GNULIB_MEMCHR)/g' \
- -e 's/@''GNULIB_MEMMEM''@/$(GNULIB_MEMMEM)/g' \
- -e 's/@''GNULIB_MEMPCPY''@/$(GNULIB_MEMPCPY)/g' \
- -e 's/@''GNULIB_MEMRCHR''@/$(GNULIB_MEMRCHR)/g' \
- -e 's/@''GNULIB_RAWMEMCHR''@/$(GNULIB_RAWMEMCHR)/g' \
- -e 's/@''GNULIB_STPCPY''@/$(GNULIB_STPCPY)/g' \
- -e 's/@''GNULIB_STPNCPY''@/$(GNULIB_STPNCPY)/g' \
- -e 's/@''GNULIB_STRCHRNUL''@/$(GNULIB_STRCHRNUL)/g' \
- -e 's/@''GNULIB_STRDUP''@/$(GNULIB_STRDUP)/g' \
- -e 's/@''GNULIB_STRNCAT''@/$(GNULIB_STRNCAT)/g' \
- -e 's/@''GNULIB_STRNDUP''@/$(GNULIB_STRNDUP)/g' \
- -e 's/@''GNULIB_STRNLEN''@/$(GNULIB_STRNLEN)/g' \
- -e 's/@''GNULIB_STRPBRK''@/$(GNULIB_STRPBRK)/g' \
- -e 's/@''GNULIB_STRSEP''@/$(GNULIB_STRSEP)/g' \
- -e 's/@''GNULIB_STRSTR''@/$(GNULIB_STRSTR)/g' \
- -e 's/@''GNULIB_STRCASESTR''@/$(GNULIB_STRCASESTR)/g' \
- -e 's/@''GNULIB_STRTOK_R''@/$(GNULIB_STRTOK_R)/g' \
- -e 's/@''GNULIB_STRERROR''@/$(GNULIB_STRERROR)/g' \
- -e 's/@''GNULIB_STRERROR_R''@/$(GNULIB_STRERROR_R)/g' \
- -e 's/@''GNULIB_STRSIGNAL''@/$(GNULIB_STRSIGNAL)/g' \
- -e 's/@''GNULIB_STRVERSCMP''@/$(GNULIB_STRVERSCMP)/g' \
+ -e 's/@''GNULIB_EXPLICIT_BZERO''@/$(GL_GNULIB_EXPLICIT_BZERO)/g' \
+ -e 's/@''GNULIB_FFSL''@/$(GL_GNULIB_FFSL)/g' \
+ -e 's/@''GNULIB_FFSLL''@/$(GL_GNULIB_FFSLL)/g' \
+ -e 's/@''GNULIB_MBSLEN''@/$(GL_GNULIB_MBSLEN)/g' \
+ -e 's/@''GNULIB_MBSNLEN''@/$(GL_GNULIB_MBSNLEN)/g' \
+ -e 's/@''GNULIB_MBSCHR''@/$(GL_GNULIB_MBSCHR)/g' \
+ -e 's/@''GNULIB_MBSRCHR''@/$(GL_GNULIB_MBSRCHR)/g' \
+ -e 's/@''GNULIB_MBSSTR''@/$(GL_GNULIB_MBSSTR)/g' \
+ -e 's/@''GNULIB_MBSCASECMP''@/$(GL_GNULIB_MBSCASECMP)/g' \
+ -e 's/@''GNULIB_MBSNCASECMP''@/$(GL_GNULIB_MBSNCASECMP)/g' \
+ -e 's/@''GNULIB_MBSPCASECMP''@/$(GL_GNULIB_MBSPCASECMP)/g' \
+ -e 's/@''GNULIB_MBSCASESTR''@/$(GL_GNULIB_MBSCASESTR)/g' \
+ -e 's/@''GNULIB_MBSCSPN''@/$(GL_GNULIB_MBSCSPN)/g' \
+ -e 's/@''GNULIB_MBSPBRK''@/$(GL_GNULIB_MBSPBRK)/g' \
+ -e 's/@''GNULIB_MBSSPN''@/$(GL_GNULIB_MBSSPN)/g' \
+ -e 's/@''GNULIB_MBSSEP''@/$(GL_GNULIB_MBSSEP)/g' \
+ -e 's/@''GNULIB_MBSTOK_R''@/$(GL_GNULIB_MBSTOK_R)/g' \
+ -e 's/@''GNULIB_MEMCHR''@/$(GL_GNULIB_MEMCHR)/g' \
+ -e 's/@''GNULIB_MEMMEM''@/$(GL_GNULIB_MEMMEM)/g' \
+ -e 's/@''GNULIB_MEMPCPY''@/$(GL_GNULIB_MEMPCPY)/g' \
+ -e 's/@''GNULIB_MEMRCHR''@/$(GL_GNULIB_MEMRCHR)/g' \
+ -e 's/@''GNULIB_RAWMEMCHR''@/$(GL_GNULIB_RAWMEMCHR)/g' \
+ -e 's/@''GNULIB_STPCPY''@/$(GL_GNULIB_STPCPY)/g' \
+ -e 's/@''GNULIB_STPNCPY''@/$(GL_GNULIB_STPNCPY)/g' \
+ -e 's/@''GNULIB_STRCHRNUL''@/$(GL_GNULIB_STRCHRNUL)/g' \
+ -e 's/@''GNULIB_STRDUP''@/$(GL_GNULIB_STRDUP)/g' \
+ -e 's/@''GNULIB_STRNCAT''@/$(GL_GNULIB_STRNCAT)/g' \
+ -e 's/@''GNULIB_STRNDUP''@/$(GL_GNULIB_STRNDUP)/g' \
+ -e 's/@''GNULIB_STRNLEN''@/$(GL_GNULIB_STRNLEN)/g' \
+ -e 's/@''GNULIB_STRPBRK''@/$(GL_GNULIB_STRPBRK)/g' \
+ -e 's/@''GNULIB_STRSEP''@/$(GL_GNULIB_STRSEP)/g' \
+ -e 's/@''GNULIB_STRSTR''@/$(GL_GNULIB_STRSTR)/g' \
+ -e 's/@''GNULIB_STRCASESTR''@/$(GL_GNULIB_STRCASESTR)/g' \
+ -e 's/@''GNULIB_STRTOK_R''@/$(GL_GNULIB_STRTOK_R)/g' \
+ -e 's/@''GNULIB_STRERROR''@/$(GL_GNULIB_STRERROR)/g' \
+ -e 's/@''GNULIB_STRERROR_R''@/$(GL_GNULIB_STRERROR_R)/g' \
+ -e 's/@''GNULIB_STRERRORNAME_NP''@/$(GL_GNULIB_STRERRORNAME_NP)/g' \
+ -e 's/@''GNULIB_SIGABBREV_NP''@/$(GL_GNULIB_SIGABBREV_NP)/g' \
+ -e 's/@''GNULIB_SIGDESCR_NP''@/$(GL_GNULIB_SIGDESCR_NP)/g' \
+ -e 's/@''GNULIB_STRSIGNAL''@/$(GL_GNULIB_STRSIGNAL)/g' \
+ -e 's/@''GNULIB_STRVERSCMP''@/$(GL_GNULIB_STRVERSCMP)/g' \
+ -e 's/@''GNULIB_MDA_MEMCCPY''@/$(GL_GNULIB_MDA_MEMCCPY)/g' \
+ -e 's/@''GNULIB_MDA_STRDUP''@/$(GL_GNULIB_MDA_STRDUP)/g' \
+ -e 's/@''GNULIB_FREE_POSIX''@/$(GL_GNULIB_FREE_POSIX)/g' \
< $(srcdir)/string.in.h | \
sed -e 's|@''HAVE_EXPLICIT_BZERO''@|$(HAVE_EXPLICIT_BZERO)|g' \
-e 's|@''HAVE_FFSL''@|$(HAVE_FFSL)|g' \
-e 's|@''HAVE_FFSLL''@|$(HAVE_FFSLL)|g' \
-e 's|@''HAVE_MBSLEN''@|$(HAVE_MBSLEN)|g' \
- -e 's|@''HAVE_MEMCHR''@|$(HAVE_MEMCHR)|g' \
-e 's|@''HAVE_DECL_MEMMEM''@|$(HAVE_DECL_MEMMEM)|g' \
-e 's|@''HAVE_MEMPCPY''@|$(HAVE_MEMPCPY)|g' \
-e 's|@''HAVE_DECL_MEMRCHR''@|$(HAVE_DECL_MEMRCHR)|g' \
@@ -2513,10 +3366,15 @@ string.h: string.in.h $(top_builddir)/config.status $(CXXDEFS_H) $(ARG_NONNULL_H
-e 's|@''HAVE_STRCASESTR''@|$(HAVE_STRCASESTR)|g' \
-e 's|@''HAVE_DECL_STRTOK_R''@|$(HAVE_DECL_STRTOK_R)|g' \
-e 's|@''HAVE_DECL_STRERROR_R''@|$(HAVE_DECL_STRERROR_R)|g' \
+ -e 's|@''HAVE_STRERRORNAME_NP''@|$(HAVE_STRERRORNAME_NP)|g' \
+ -e 's|@''HAVE_SIGABBREV_NP''@|$(HAVE_SIGABBREV_NP)|g' \
+ -e 's|@''HAVE_SIGDESCR_NP''@|$(HAVE_SIGDESCR_NP)|g' \
-e 's|@''HAVE_DECL_STRSIGNAL''@|$(HAVE_DECL_STRSIGNAL)|g' \
-e 's|@''HAVE_STRVERSCMP''@|$(HAVE_STRVERSCMP)|g' \
+ -e 's|@''REPLACE_FFSLL''@|$(REPLACE_FFSLL)|g' \
-e 's|@''REPLACE_MEMCHR''@|$(REPLACE_MEMCHR)|g' \
-e 's|@''REPLACE_MEMMEM''@|$(REPLACE_MEMMEM)|g' \
+ -e 's|@''REPLACE_FREE''@|$(REPLACE_FREE)|g' \
-e 's|@''REPLACE_STPNCPY''@|$(REPLACE_STPNCPY)|g' \
-e 's|@''REPLACE_STRCHRNUL''@|$(REPLACE_STRCHRNUL)|g' \
-e 's|@''REPLACE_STRDUP''@|$(REPLACE_STRDUP)|g' \
@@ -2528,14 +3386,14 @@ string.h: string.in.h $(top_builddir)/config.status $(CXXDEFS_H) $(ARG_NONNULL_H
-e 's|@''REPLACE_STRTOK_R''@|$(REPLACE_STRTOK_R)|g' \
-e 's|@''REPLACE_STRERROR''@|$(REPLACE_STRERROR)|g' \
-e 's|@''REPLACE_STRERROR_R''@|$(REPLACE_STRERROR_R)|g' \
+ -e 's|@''REPLACE_STRERRORNAME_NP''@|$(REPLACE_STRERRORNAME_NP)|g' \
-e 's|@''REPLACE_STRSIGNAL''@|$(REPLACE_STRSIGNAL)|g' \
-e 's|@''UNDEFINE_STRTOK_R''@|$(UNDEFINE_STRTOK_R)|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)'; \
- < $(srcdir)/string.in.h; \
- } > $@-t && \
- mv $@-t $@
+ -e '/definition of _GL_WARN_ON_USE/r $(WARN_ON_USE_H)' \
+ > $@-t
+ $(AM_V_at)mv $@-t $@
MOSTLYCLEANFILES += string.h string.h-t
EXTRA_DIST += string.in.h
@@ -2543,13 +3401,22 @@ EXTRA_DIST += string.in.h
endif
## end gnulib module string
-## begin gnulib module strtoimax
-ifeq (,$(OMIT_GNULIB_MODULE_strtoimax))
+## begin gnulib module strnlen
+ifeq (,$(OMIT_GNULIB_MODULE_strnlen))
+ifneq (,$(GL_COND_OBJ_STRNLEN_CONDITION))
+libgnu_a_SOURCES += strnlen.c
+endif
+
+endif
+## end gnulib module strnlen
-EXTRA_DIST += strtoimax.c
+## begin gnulib module strtoimax
+ifeq (,$(OMIT_GNULIB_MODULE_strtoimax))
-EXTRA_libgnu_a_SOURCES += strtoimax.c
+ifneq (,$(GL_COND_OBJ_STRTOIMAX_CONDITION))
+libgnu_a_SOURCES += strtoimax.c
+endif
endif
## end gnulib module strtoimax
@@ -2557,12 +3424,15 @@ endif
## begin gnulib module strtoll
ifeq (,$(OMIT_GNULIB_MODULE_strtoll))
-ifneq (,$(gl_GNULIB_ENABLED_strtoll))
+ifneq (,$(gl_GNULIB_ENABLED_strtoll_CONDITION))
+ifneq (,$(GL_COND_OBJ_STRTOLL_CONDITION))
+libgnu_a_SOURCES += strtoll.c
+endif
endif
-EXTRA_DIST += strtol.c strtoll.c
+EXTRA_DIST += strtol.c
-EXTRA_libgnu_a_SOURCES += strtol.c strtoll.c
+EXTRA_libgnu_a_SOURCES += strtol.c
endif
## end gnulib module strtoll
@@ -2570,13 +3440,44 @@ endif
## begin gnulib module symlink
ifeq (,$(OMIT_GNULIB_MODULE_symlink))
+ifneq (,$(GL_COND_OBJ_SYMLINK_CONDITION))
+libgnu_a_SOURCES += symlink.c
+endif
+
+endif
+## end gnulib module symlink
+
+## begin gnulib module sys_random
+ifeq (,$(OMIT_GNULIB_MODULE_sys_random))
-EXTRA_DIST += symlink.c
+BUILT_SOURCES += sys/random.h
-EXTRA_libgnu_a_SOURCES += symlink.c
+# We need the following in order to create <sys/random.h> when the system
+# doesn't have one.
+sys/random.h: sys_random.in.h $(top_builddir)/config.status $(CXXDEFS_H) $(ARG_NONNULL_H) $(WARN_ON_USE_H)
+ $(AM_V_GEN)$(MKDIR_P) 'sys'
+ $(AM_V_at)$(SED_HEADER_STDOUT) \
+ -e 's|@''GUARD_PREFIX''@|GL|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_SYS_RANDOM_H''@|$(NEXT_SYS_RANDOM_H)|g' \
+ -e 's|@''HAVE_SYS_RANDOM_H''@|$(HAVE_SYS_RANDOM_H)|g' \
+ -e 's/@''GNULIB_GETRANDOM''@/$(GL_GNULIB_GETRANDOM)/g' \
+ -e 's/@''HAVE_GETRANDOM''@/$(HAVE_GETRANDOM)/g' \
+ -e 's/@''REPLACE_GETRANDOM''@/$(REPLACE_GETRANDOM)/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)' \
+ $(srcdir)/sys_random.in.h > $@-t
+ $(AM_V_at)mv $@-t $@
+MOSTLYCLEANFILES += sys/random.h sys/random.h-t
+MOSTLYCLEANDIRS += sys
+
+EXTRA_DIST += sys_random.in.h
endif
-## end gnulib module symlink
+## end gnulib module sys_random
## begin gnulib module sys_select
ifeq (,$(OMIT_GNULIB_MODULE_sys_select))
@@ -2586,26 +3487,24 @@ BUILT_SOURCES += sys/select.h
# We need the following in order to create <sys/select.h> when the system
# doesn't have one that works with the given compiler.
sys/select.h: sys_select.in.h $(top_builddir)/config.status $(CXXDEFS_H) $(WARN_ON_USE_H)
- $(AM_V_at)$(MKDIR_P) sys
- $(AM_V_GEN)rm -f $@-t $@ && \
- { echo '/* DO NOT EDIT! GENERATED AUTOMATICALLY! */'; \
- sed -e 's|@''GUARD_PREFIX''@|GL|g' \
+ $(AM_V_GEN)$(MKDIR_P) 'sys'
+ $(AM_V_at)$(SED_HEADER_STDOUT) \
+ -e 's|@''GUARD_PREFIX''@|GL|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_SYS_SELECT_H''@|$(NEXT_SYS_SELECT_H)|g' \
-e 's|@''HAVE_SYS_SELECT_H''@|$(HAVE_SYS_SELECT_H)|g' \
- -e 's/@''GNULIB_PSELECT''@/$(GNULIB_PSELECT)/g' \
- -e 's/@''GNULIB_SELECT''@/$(GNULIB_SELECT)/g' \
+ -e 's/@''GNULIB_PSELECT''@/$(GL_GNULIB_PSELECT)/g' \
+ -e 's/@''GNULIB_SELECT''@/$(GL_GNULIB_SELECT)/g' \
-e 's|@''HAVE_WINSOCK2_H''@|$(HAVE_WINSOCK2_H)|g' \
-e 's|@''HAVE_PSELECT''@|$(HAVE_PSELECT)|g' \
-e 's|@''REPLACE_PSELECT''@|$(REPLACE_PSELECT)|g' \
-e 's|@''REPLACE_SELECT''@|$(REPLACE_SELECT)|g' \
-e '/definitions of _GL_FUNCDECL_RPL/r $(CXXDEFS_H)' \
-e '/definition of _GL_WARN_ON_USE/r $(WARN_ON_USE_H)' \
- < $(srcdir)/sys_select.in.h; \
- } > $@-t && \
- mv $@-t $@
+ $(srcdir)/sys_select.in.h > $@-t
+ $(AM_V_at)mv $@-t $@
MOSTLYCLEANFILES += sys/select.h sys/select.h-t
MOSTLYCLEANDIRS += sys
@@ -2622,33 +3521,39 @@ BUILT_SOURCES += sys/stat.h
# We need the following in order to create <sys/stat.h> when the system
# has one that is incomplete.
sys/stat.h: sys_stat.in.h $(top_builddir)/config.status $(CXXDEFS_H) $(ARG_NONNULL_H) $(WARN_ON_USE_H)
- $(AM_V_at)$(MKDIR_P) sys
- $(AM_V_GEN)rm -f $@-t $@ && \
- { echo '/* DO NOT EDIT! GENERATED AUTOMATICALLY! */'; \
- sed -e 's|@''GUARD_PREFIX''@|GL|g' \
+ $(AM_V_GEN)$(MKDIR_P) 'sys'
+ $(AM_V_at)$(SED_HEADER_STDOUT) \
+ -e 's|@''GUARD_PREFIX''@|GL|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_SYS_STAT_H''@|$(NEXT_SYS_STAT_H)|g' \
-e 's|@''WINDOWS_64_BIT_ST_SIZE''@|$(WINDOWS_64_BIT_ST_SIZE)|g' \
-e 's|@''WINDOWS_STAT_TIMESPEC''@|$(WINDOWS_STAT_TIMESPEC)|g' \
- -e 's/@''GNULIB_FCHMODAT''@/$(GNULIB_FCHMODAT)/g' \
- -e 's/@''GNULIB_FSTAT''@/$(GNULIB_FSTAT)/g' \
- -e 's/@''GNULIB_FSTATAT''@/$(GNULIB_FSTATAT)/g' \
- -e 's/@''GNULIB_FUTIMENS''@/$(GNULIB_FUTIMENS)/g' \
- -e 's/@''GNULIB_LCHMOD''@/$(GNULIB_LCHMOD)/g' \
- -e 's/@''GNULIB_LSTAT''@/$(GNULIB_LSTAT)/g' \
- -e 's/@''GNULIB_MKDIRAT''@/$(GNULIB_MKDIRAT)/g' \
- -e 's/@''GNULIB_MKFIFO''@/$(GNULIB_MKFIFO)/g' \
- -e 's/@''GNULIB_MKFIFOAT''@/$(GNULIB_MKFIFOAT)/g' \
- -e 's/@''GNULIB_MKNOD''@/$(GNULIB_MKNOD)/g' \
- -e 's/@''GNULIB_MKNODAT''@/$(GNULIB_MKNODAT)/g' \
- -e 's/@''GNULIB_STAT''@/$(GNULIB_STAT)/g' \
- -e 's/@''GNULIB_UTIMENSAT''@/$(GNULIB_UTIMENSAT)/g' \
- -e 's/@''GNULIB_OVERRIDES_STRUCT_STAT''@/$(GNULIB_OVERRIDES_STRUCT_STAT)/g' \
+ -e 's/@''GNULIB_CHMOD''@/$(GL_GNULIB_CHMOD)/g' \
+ -e 's/@''GNULIB_FCHMODAT''@/$(GL_GNULIB_FCHMODAT)/g' \
+ -e 's/@''GNULIB_FSTAT''@/$(GL_GNULIB_FSTAT)/g' \
+ -e 's/@''GNULIB_FSTATAT''@/$(GL_GNULIB_FSTATAT)/g' \
+ -e 's/@''GNULIB_FUTIMENS''@/$(GL_GNULIB_FUTIMENS)/g' \
+ -e 's/@''GNULIB_GETUMASK''@/$(GL_GNULIB_GETUMASK)/g' \
+ -e 's/@''GNULIB_LCHMOD''@/$(GL_GNULIB_LCHMOD)/g' \
+ -e 's/@''GNULIB_LSTAT''@/$(GL_GNULIB_LSTAT)/g' \
+ -e 's/@''GNULIB_MKDIR''@/$(GL_GNULIB_MKDIR)/g' \
+ -e 's/@''GNULIB_MKDIRAT''@/$(GL_GNULIB_MKDIRAT)/g' \
+ -e 's/@''GNULIB_MKFIFO''@/$(GL_GNULIB_MKFIFO)/g' \
+ -e 's/@''GNULIB_MKFIFOAT''@/$(GL_GNULIB_MKFIFOAT)/g' \
+ -e 's/@''GNULIB_MKNOD''@/$(GL_GNULIB_MKNOD)/g' \
+ -e 's/@''GNULIB_MKNODAT''@/$(GL_GNULIB_MKNODAT)/g' \
+ -e 's/@''GNULIB_STAT''@/$(GL_GNULIB_STAT)/g' \
+ -e 's/@''GNULIB_UTIMENSAT''@/$(GL_GNULIB_UTIMENSAT)/g' \
+ -e 's/@''GNULIB_OVERRIDES_STRUCT_STAT''@/$(GL_GNULIB_OVERRIDES_STRUCT_STAT)/g' \
+ -e 's/@''GNULIB_MDA_CHMOD''@/$(GL_GNULIB_MDA_CHMOD)/g' \
+ -e 's/@''GNULIB_MDA_MKDIR''@/$(GL_GNULIB_MDA_MKDIR)/g' \
+ -e 's/@''GNULIB_MDA_UMASK''@/$(GL_GNULIB_MDA_UMASK)/g' \
-e 's|@''HAVE_FCHMODAT''@|$(HAVE_FCHMODAT)|g' \
-e 's|@''HAVE_FSTATAT''@|$(HAVE_FSTATAT)|g' \
-e 's|@''HAVE_FUTIMENS''@|$(HAVE_FUTIMENS)|g' \
+ -e 's|@''HAVE_GETUMASK''@|$(HAVE_GETUMASK)|g' \
-e 's|@''HAVE_LCHMOD''@|$(HAVE_LCHMOD)|g' \
-e 's|@''HAVE_LSTAT''@|$(HAVE_LSTAT)|g' \
-e 's|@''HAVE_MKDIRAT''@|$(HAVE_MKDIRAT)|g' \
@@ -2657,21 +3562,24 @@ sys/stat.h: sys_stat.in.h $(top_builddir)/config.status $(CXXDEFS_H) $(ARG_NONNU
-e 's|@''HAVE_MKNOD''@|$(HAVE_MKNOD)|g' \
-e 's|@''HAVE_MKNODAT''@|$(HAVE_MKNODAT)|g' \
-e 's|@''HAVE_UTIMENSAT''@|$(HAVE_UTIMENSAT)|g' \
+ -e 's|@''REPLACE_CHMOD''@|$(REPLACE_CHMOD)|g' \
+ -e 's|@''REPLACE_FCHMODAT''@|$(REPLACE_FCHMODAT)|g' \
-e 's|@''REPLACE_FSTAT''@|$(REPLACE_FSTAT)|g' \
-e 's|@''REPLACE_FSTATAT''@|$(REPLACE_FSTATAT)|g' \
-e 's|@''REPLACE_FUTIMENS''@|$(REPLACE_FUTIMENS)|g' \
-e 's|@''REPLACE_LSTAT''@|$(REPLACE_LSTAT)|g' \
-e 's|@''REPLACE_MKDIR''@|$(REPLACE_MKDIR)|g' \
-e 's|@''REPLACE_MKFIFO''@|$(REPLACE_MKFIFO)|g' \
+ -e 's|@''REPLACE_MKFIFOAT''@|$(REPLACE_MKFIFOAT)|g' \
-e 's|@''REPLACE_MKNOD''@|$(REPLACE_MKNOD)|g' \
+ -e 's|@''REPLACE_MKNODAT''@|$(REPLACE_MKNODAT)|g' \
-e 's|@''REPLACE_STAT''@|$(REPLACE_STAT)|g' \
-e 's|@''REPLACE_UTIMENSAT''@|$(REPLACE_UTIMENSAT)|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)' \
- < $(srcdir)/sys_stat.in.h; \
- } > $@-t && \
- mv $@-t $@
+ $(srcdir)/sys_stat.in.h > $@-t
+ $(AM_V_at)mv $@-t $@
MOSTLYCLEANFILES += sys/stat.h sys/stat.h-t
MOSTLYCLEANDIRS += sys
@@ -2688,16 +3596,15 @@ BUILT_SOURCES += sys/time.h
# We need the following in order to create <sys/time.h> when the system
# doesn't have one that works with the given compiler.
sys/time.h: sys_time.in.h $(top_builddir)/config.status $(CXXDEFS_H) $(ARG_NONNULL_H) $(WARN_ON_USE_H)
- $(AM_V_at)$(MKDIR_P) sys
- $(AM_V_GEN)rm -f $@-t $@ && \
- { echo '/* DO NOT EDIT! GENERATED AUTOMATICALLY! */'; \
- sed -e 's|@''GUARD_PREFIX''@|GL|g' \
+ $(AM_V_GEN)$(MKDIR_P) 'sys'
+ $(AM_V_at)$(SED_HEADER_STDOUT) \
+ -e 's|@''GUARD_PREFIX''@|GL|g' \
-e 's/@''HAVE_SYS_TIME_H''@/$(HAVE_SYS_TIME_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_SYS_TIME_H''@|$(NEXT_SYS_TIME_H)|g' \
- -e 's/@''GNULIB_GETTIMEOFDAY''@/$(GNULIB_GETTIMEOFDAY)/g' \
+ -e 's/@''GNULIB_GETTIMEOFDAY''@/$(GL_GNULIB_GETTIMEOFDAY)/g' \
-e 's|@''HAVE_WINSOCK2_H''@|$(HAVE_WINSOCK2_H)|g' \
-e 's/@''HAVE_GETTIMEOFDAY''@/$(HAVE_GETTIMEOFDAY)/g' \
-e 's/@''HAVE_STRUCT_TIMEVAL''@/$(HAVE_STRUCT_TIMEVAL)/g' \
@@ -2706,9 +3613,8 @@ sys/time.h: sys_time.in.h $(top_builddir)/config.status $(CXXDEFS_H) $(ARG_NONNU
-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)' \
- < $(srcdir)/sys_time.in.h; \
- } > $@-t && \
- mv $@-t $@
+ $(srcdir)/sys_time.in.h > $@-t
+ $(AM_V_at)mv $@-t $@
MOSTLYCLEANFILES += sys/time.h sys/time.h-t
EXTRA_DIST += sys_time.in.h
@@ -2724,19 +3630,17 @@ BUILT_SOURCES += sys/types.h
# We need the following in order to create <sys/types.h> when the system
# doesn't have one that works with the given compiler.
sys/types.h: sys_types.in.h $(top_builddir)/config.status
- $(AM_V_at)$(MKDIR_P) sys
- $(AM_V_GEN)rm -f $@-t $@ && \
- { echo '/* DO NOT EDIT! GENERATED AUTOMATICALLY! */'; \
- sed -e 's|@''GUARD_PREFIX''@|GL|g' \
+ $(AM_V_GEN)$(MKDIR_P) 'sys'
+ $(AM_V_at)$(SED_HEADER_STDOUT) \
+ -e 's|@''GUARD_PREFIX''@|GL|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_SYS_TYPES_H''@|$(NEXT_SYS_TYPES_H)|g' \
-e 's|@''WINDOWS_64_BIT_OFF_T''@|$(WINDOWS_64_BIT_OFF_T)|g' \
-e 's|@''WINDOWS_STAT_INODES''@|$(WINDOWS_STAT_INODES)|g' \
- < $(srcdir)/sys_types.in.h; \
- } > $@-t && \
- mv $@-t $@
+ $(srcdir)/sys_types.in.h > $@-t
+ $(AM_V_at)mv $@-t $@
MOSTLYCLEANFILES += sys/types.h sys/types.h-t
EXTRA_DIST += sys_types.in.h
@@ -2762,29 +3666,32 @@ BUILT_SOURCES += time.h
# We need the following in order to create <time.h> when the system
# doesn't have one that works with the given compiler.
time.h: time.in.h $(top_builddir)/config.status $(CXXDEFS_H) $(ARG_NONNULL_H) $(WARN_ON_USE_H)
- $(AM_V_GEN)rm -f $@-t $@ && \
- { echo '/* DO NOT EDIT! GENERATED AUTOMATICALLY! */' && \
- sed -e 's|@''GUARD_PREFIX''@|GL|g' \
+ $(gl_V_at)$(SED_HEADER_STDOUT) \
+ -e 's|@''GUARD_PREFIX''@|GL|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_TIME_H''@|$(NEXT_TIME_H)|g' \
- -e 's/@''GNULIB_CTIME''@/$(GNULIB_CTIME)/g' \
- -e 's/@''GNULIB_LOCALTIME''@/$(GNULIB_LOCALTIME)/g' \
- -e 's/@''GNULIB_MKTIME''@/$(GNULIB_MKTIME)/g' \
- -e 's/@''GNULIB_NANOSLEEP''@/$(GNULIB_NANOSLEEP)/g' \
- -e 's/@''GNULIB_STRFTIME''@/$(GNULIB_STRFTIME)/g' \
- -e 's/@''GNULIB_STRPTIME''@/$(GNULIB_STRPTIME)/g' \
- -e 's/@''GNULIB_TIMEGM''@/$(GNULIB_TIMEGM)/g' \
- -e 's/@''GNULIB_TIME_R''@/$(GNULIB_TIME_R)/g' \
- -e 's/@''GNULIB_TIME_RZ''@/$(GNULIB_TIME_RZ)/g' \
- -e 's/@''GNULIB_TZSET''@/$(GNULIB_TZSET)/g' \
+ -e 's/@''GNULIB_CTIME''@/$(GL_GNULIB_CTIME)/g' \
+ -e 's/@''GNULIB_LOCALTIME''@/$(GL_GNULIB_LOCALTIME)/g' \
+ -e 's/@''GNULIB_MKTIME''@/$(GL_GNULIB_MKTIME)/g' \
+ -e 's/@''GNULIB_NANOSLEEP''@/$(GL_GNULIB_NANOSLEEP)/g' \
+ -e 's/@''GNULIB_STRFTIME''@/$(GL_GNULIB_STRFTIME)/g' \
+ -e 's/@''GNULIB_STRPTIME''@/$(GL_GNULIB_STRPTIME)/g' \
+ -e 's/@''GNULIB_TIMEGM''@/$(GL_GNULIB_TIMEGM)/g' \
+ -e 's/@''GNULIB_TIMESPEC_GET''@/$(GL_GNULIB_TIMESPEC_GET)/g' \
+ -e 's/@''GNULIB_TIMESPEC_GETRES''@/$(GL_GNULIB_TIMESPEC_GETRES)/g' \
+ -e 's/@''GNULIB_TIME_R''@/$(GL_GNULIB_TIME_R)/g' \
+ -e 's/@''GNULIB_TIME_RZ''@/$(GL_GNULIB_TIME_RZ)/g' \
+ -e 's/@''GNULIB_TZSET''@/$(GL_GNULIB_TZSET)/g' \
+ -e 's/@''GNULIB_MDA_TZSET''@/$(GL_GNULIB_MDA_TZSET)/g' \
-e 's|@''HAVE_DECL_LOCALTIME_R''@|$(HAVE_DECL_LOCALTIME_R)|g' \
-e 's|@''HAVE_NANOSLEEP''@|$(HAVE_NANOSLEEP)|g' \
-e 's|@''HAVE_STRPTIME''@|$(HAVE_STRPTIME)|g' \
-e 's|@''HAVE_TIMEGM''@|$(HAVE_TIMEGM)|g' \
+ -e 's|@''HAVE_TIMESPEC_GET''@|$(HAVE_TIMESPEC_GET)|g' \
+ -e 's|@''HAVE_TIMESPEC_GETRES''@|$(HAVE_TIMESPEC_GETRES)|g' \
-e 's|@''HAVE_TIMEZONE_T''@|$(HAVE_TIMEZONE_T)|g' \
- -e 's|@''HAVE_TZSET''@|$(HAVE_TZSET)|g' \
-e 's|@''REPLACE_CTIME''@|$(REPLACE_CTIME)|g' \
-e 's|@''REPLACE_GMTIME''@|$(REPLACE_GMTIME)|g' \
-e 's|@''REPLACE_LOCALTIME''@|$(REPLACE_LOCALTIME)|g' \
@@ -2798,12 +3705,12 @@ time.h: time.in.h $(top_builddir)/config.status $(CXXDEFS_H) $(ARG_NONNULL_H) $(
-e 's|@''SYS_TIME_H_DEFINES_STRUCT_TIMESPEC''@|$(SYS_TIME_H_DEFINES_STRUCT_TIMESPEC)|g' \
-e 's|@''TIME_H_DEFINES_STRUCT_TIMESPEC''@|$(TIME_H_DEFINES_STRUCT_TIMESPEC)|g' \
-e 's|@''UNISTD_H_DEFINES_STRUCT_TIMESPEC''@|$(UNISTD_H_DEFINES_STRUCT_TIMESPEC)|g' \
+ -e 's|@''TIME_H_DEFINES_TIME_UTC''@|$(TIME_H_DEFINES_TIME_UTC)|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)' \
- < $(srcdir)/time.in.h; \
- } > $@-t && \
- mv $@-t $@
+ $(srcdir)/time.in.h > $@-t
+ $(AM_V_at)mv $@-t $@
MOSTLYCLEANFILES += time.h time.h-t
EXTRA_DIST += time.in.h
@@ -2814,10 +3721,9 @@ endif
## begin gnulib module time_r
ifeq (,$(OMIT_GNULIB_MODULE_time_r))
-
-EXTRA_DIST += time_r.c
-
-EXTRA_libgnu_a_SOURCES += time_r.c
+ifneq (,$(GL_COND_OBJ_TIME_R_CONDITION))
+libgnu_a_SOURCES += time_r.c
+endif
endif
## end gnulib module time_r
@@ -2825,10 +3731,11 @@ endif
## begin gnulib module time_rz
ifeq (,$(OMIT_GNULIB_MODULE_time_rz))
+ifneq (,$(GL_COND_OBJ_TIME_RZ_CONDITION))
+libgnu_a_SOURCES += time_rz.c
+endif
-EXTRA_DIST += time-internal.h time_rz.c
-
-EXTRA_libgnu_a_SOURCES += time_rz.c
+EXTRA_DIST += time-internal.h
endif
## end gnulib module time_rz
@@ -2836,10 +3743,11 @@ endif
## begin gnulib module timegm
ifeq (,$(OMIT_GNULIB_MODULE_timegm))
+ifneq (,$(GL_COND_OBJ_TIMEGM_CONDITION))
+libgnu_a_SOURCES += timegm.c
+endif
-EXTRA_DIST += mktime-internal.h timegm.c
-
-EXTRA_libgnu_a_SOURCES += timegm.c
+EXTRA_DIST += mktime-internal.h
endif
## end gnulib module timegm
@@ -2889,70 +3797,104 @@ libgnu_a_SOURCES += unistd.c
# We need the following in order to create an empty placeholder for
# <unistd.h> when the system doesn't have one.
unistd.h: unistd.in.h $(top_builddir)/config.status $(CXXDEFS_H) $(ARG_NONNULL_H) $(WARN_ON_USE_H)
- $(AM_V_GEN)rm -f $@-t $@ && \
- { echo '/* DO NOT EDIT! GENERATED AUTOMATICALLY! */'; \
- sed -e 's|@''GUARD_PREFIX''@|GL|g' \
+ $(gl_V_at)$(SED_HEADER_STDOUT) \
+ -e 's|@''GUARD_PREFIX''@|GL|g' \
-e 's|@''HAVE_UNISTD_H''@|$(HAVE_UNISTD_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_UNISTD_H''@|$(NEXT_UNISTD_H)|g' \
-e 's|@''WINDOWS_64_BIT_OFF_T''@|$(WINDOWS_64_BIT_OFF_T)|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_DUP''@/$(GNULIB_DUP)/g' \
- -e 's/@''GNULIB_DUP2''@/$(GNULIB_DUP2)/g' \
- -e 's/@''GNULIB_DUP3''@/$(GNULIB_DUP3)/g' \
- -e 's/@''GNULIB_ENVIRON''@/$(GNULIB_ENVIRON)/g' \
- -e 's/@''GNULIB_EUIDACCESS''@/$(GNULIB_EUIDACCESS)/g' \
- -e 's/@''GNULIB_FACCESSAT''@/$(GNULIB_FACCESSAT)/g' \
- -e 's/@''GNULIB_FCHDIR''@/$(GNULIB_FCHDIR)/g' \
- -e 's/@''GNULIB_FCHOWNAT''@/$(GNULIB_FCHOWNAT)/g' \
- -e 's/@''GNULIB_FDATASYNC''@/$(GNULIB_FDATASYNC)/g' \
- -e 's/@''GNULIB_FSYNC''@/$(GNULIB_FSYNC)/g' \
- -e 's/@''GNULIB_FTRUNCATE''@/$(GNULIB_FTRUNCATE)/g' \
- -e 's/@''GNULIB_GETCWD''@/$(GNULIB_GETCWD)/g' \
- -e 's/@''GNULIB_GETDOMAINNAME''@/$(GNULIB_GETDOMAINNAME)/g' \
- -e 's/@''GNULIB_GETDTABLESIZE''@/$(GNULIB_GETDTABLESIZE)/g' \
- -e 's/@''GNULIB_GETGROUPS''@/$(GNULIB_GETGROUPS)/g' \
- -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_GETPAGESIZE''@/$(GNULIB_GETPAGESIZE)/g' \
- -e 's/@''GNULIB_GETUSERSHELL''@/$(GNULIB_GETUSERSHELL)/g' \
- -e 's/@''GNULIB_GROUP_MEMBER''@/$(GNULIB_GROUP_MEMBER)/g' \
- -e 's/@''GNULIB_ISATTY''@/$(GNULIB_ISATTY)/g' \
- -e 's/@''GNULIB_LCHOWN''@/$(GNULIB_LCHOWN)/g' \
- -e 's/@''GNULIB_LINK''@/$(GNULIB_LINK)/g' \
- -e 's/@''GNULIB_LINKAT''@/$(GNULIB_LINKAT)/g' \
- -e 's/@''GNULIB_LSEEK''@/$(GNULIB_LSEEK)/g' \
- -e 's/@''GNULIB_PIPE''@/$(GNULIB_PIPE)/g' \
- -e 's/@''GNULIB_PIPE2''@/$(GNULIB_PIPE2)/g' \
- -e 's/@''GNULIB_PREAD''@/$(GNULIB_PREAD)/g' \
- -e 's/@''GNULIB_PWRITE''@/$(GNULIB_PWRITE)/g' \
- -e 's/@''GNULIB_READ''@/$(GNULIB_READ)/g' \
- -e 's/@''GNULIB_READLINK''@/$(GNULIB_READLINK)/g' \
- -e 's/@''GNULIB_READLINKAT''@/$(GNULIB_READLINKAT)/g' \
- -e 's/@''GNULIB_RMDIR''@/$(GNULIB_RMDIR)/g' \
- -e 's/@''GNULIB_SETHOSTNAME''@/$(GNULIB_SETHOSTNAME)/g' \
- -e 's/@''GNULIB_SLEEP''@/$(GNULIB_SLEEP)/g' \
- -e 's/@''GNULIB_SYMLINK''@/$(GNULIB_SYMLINK)/g' \
- -e 's/@''GNULIB_SYMLINKAT''@/$(GNULIB_SYMLINKAT)/g' \
- -e 's/@''GNULIB_TRUNCATE''@/$(GNULIB_TRUNCATE)/g' \
- -e 's/@''GNULIB_TTYNAME_R''@/$(GNULIB_TTYNAME_R)/g' \
- -e 's/@''GNULIB_UNISTD_H_GETOPT''@/0$(GNULIB_GL_UNISTD_H_GETOPT)/g' \
- -e 's/@''GNULIB_UNISTD_H_NONBLOCKING''@/$(GNULIB_UNISTD_H_NONBLOCKING)/g' \
- -e 's/@''GNULIB_UNISTD_H_SIGPIPE''@/$(GNULIB_UNISTD_H_SIGPIPE)/g' \
- -e 's/@''GNULIB_UNLINK''@/$(GNULIB_UNLINK)/g' \
- -e 's/@''GNULIB_UNLINKAT''@/$(GNULIB_UNLINKAT)/g' \
- -e 's/@''GNULIB_USLEEP''@/$(GNULIB_USLEEP)/g' \
- -e 's/@''GNULIB_WRITE''@/$(GNULIB_WRITE)/g' \
+ -e 's/@''GNULIB_ACCESS''@/$(GL_GNULIB_ACCESS)/g' \
+ -e 's/@''GNULIB_CHDIR''@/$(GL_GNULIB_CHDIR)/g' \
+ -e 's/@''GNULIB_CHOWN''@/$(GL_GNULIB_CHOWN)/g' \
+ -e 's/@''GNULIB_CLOSE''@/$(GL_GNULIB_CLOSE)/g' \
+ -e 's/@''GNULIB_COPY_FILE_RANGE''@/$(GL_GNULIB_COPY_FILE_RANGE)/g' \
+ -e 's/@''GNULIB_DUP''@/$(GL_GNULIB_DUP)/g' \
+ -e 's/@''GNULIB_DUP2''@/$(GL_GNULIB_DUP2)/g' \
+ -e 's/@''GNULIB_DUP3''@/$(GL_GNULIB_DUP3)/g' \
+ -e 's/@''GNULIB_ENVIRON''@/$(GL_GNULIB_ENVIRON)/g' \
+ -e 's/@''GNULIB_EUIDACCESS''@/$(GL_GNULIB_EUIDACCESS)/g' \
+ -e 's/@''GNULIB_EXECL''@/$(GL_GNULIB_EXECL)/g' \
+ -e 's/@''GNULIB_EXECLE''@/$(GL_GNULIB_EXECLE)/g' \
+ -e 's/@''GNULIB_EXECLP''@/$(GL_GNULIB_EXECLP)/g' \
+ -e 's/@''GNULIB_EXECV''@/$(GL_GNULIB_EXECV)/g' \
+ -e 's/@''GNULIB_EXECVE''@/$(GL_GNULIB_EXECVE)/g' \
+ -e 's/@''GNULIB_EXECVP''@/$(GL_GNULIB_EXECVP)/g' \
+ -e 's/@''GNULIB_EXECVPE''@/$(GL_GNULIB_EXECVPE)/g' \
+ -e 's/@''GNULIB_FACCESSAT''@/$(GL_GNULIB_FACCESSAT)/g' \
+ -e 's/@''GNULIB_FCHDIR''@/$(GL_GNULIB_FCHDIR)/g' \
+ -e 's/@''GNULIB_FCHOWNAT''@/$(GL_GNULIB_FCHOWNAT)/g' \
+ -e 's/@''GNULIB_FDATASYNC''@/$(GL_GNULIB_FDATASYNC)/g' \
+ -e 's/@''GNULIB_FSYNC''@/$(GL_GNULIB_FSYNC)/g' \
+ -e 's/@''GNULIB_FTRUNCATE''@/$(GL_GNULIB_FTRUNCATE)/g' \
+ -e 's/@''GNULIB_GETCWD''@/$(GL_GNULIB_GETCWD)/g' \
+ -e 's/@''GNULIB_GETDOMAINNAME''@/$(GL_GNULIB_GETDOMAINNAME)/g' \
+ -e 's/@''GNULIB_GETDTABLESIZE''@/$(GL_GNULIB_GETDTABLESIZE)/g' \
+ -e 's/@''GNULIB_GETENTROPY''@/$(GL_GNULIB_GETENTROPY)/g' \
+ -e 's/@''GNULIB_GETGROUPS''@/$(GL_GNULIB_GETGROUPS)/g' \
+ -e 's/@''GNULIB_GETHOSTNAME''@/$(GL_GNULIB_GETHOSTNAME)/g' \
+ -e 's/@''GNULIB_GETLOGIN''@/$(GL_GNULIB_GETLOGIN)/g' \
+ -e 's/@''GNULIB_GETLOGIN_R''@/$(GL_GNULIB_GETLOGIN_R)/g' \
+ -e 's/@''GNULIB_GETOPT_POSIX''@/$(GL_GNULIB_GETOPT_POSIX)/g' \
+ -e 's/@''GNULIB_GETPAGESIZE''@/$(GL_GNULIB_GETPAGESIZE)/g' \
+ -e 's/@''GNULIB_GETPASS''@/$(GL_GNULIB_GETPASS)/g' \
+ -e 's/@''GNULIB_GETPASS_GNU''@/$(GL_GNULIB_GETPASS_GNU)/g' \
+ -e 's/@''GNULIB_GETUSERSHELL''@/$(GL_GNULIB_GETUSERSHELL)/g' \
+ -e 's/@''GNULIB_GROUP_MEMBER''@/$(GL_GNULIB_GROUP_MEMBER)/g' \
+ -e 's/@''GNULIB_ISATTY''@/$(GL_GNULIB_ISATTY)/g' \
+ -e 's/@''GNULIB_LCHOWN''@/$(GL_GNULIB_LCHOWN)/g' \
+ -e 's/@''GNULIB_LINK''@/$(GL_GNULIB_LINK)/g' \
+ -e 's/@''GNULIB_LINKAT''@/$(GL_GNULIB_LINKAT)/g' \
+ -e 's/@''GNULIB_LSEEK''@/$(GL_GNULIB_LSEEK)/g' \
+ -e 's/@''GNULIB_PIPE''@/$(GL_GNULIB_PIPE)/g' \
+ -e 's/@''GNULIB_PIPE2''@/$(GL_GNULIB_PIPE2)/g' \
+ -e 's/@''GNULIB_PREAD''@/$(GL_GNULIB_PREAD)/g' \
+ -e 's/@''GNULIB_PWRITE''@/$(GL_GNULIB_PWRITE)/g' \
+ -e 's/@''GNULIB_READ''@/$(GL_GNULIB_READ)/g' \
+ -e 's/@''GNULIB_READLINK''@/$(GL_GNULIB_READLINK)/g' \
+ -e 's/@''GNULIB_READLINKAT''@/$(GL_GNULIB_READLINKAT)/g' \
+ -e 's/@''GNULIB_RMDIR''@/$(GL_GNULIB_RMDIR)/g' \
+ -e 's/@''GNULIB_SETHOSTNAME''@/$(GL_GNULIB_SETHOSTNAME)/g' \
+ -e 's/@''GNULIB_SLEEP''@/$(GL_GNULIB_SLEEP)/g' \
+ -e 's/@''GNULIB_SYMLINK''@/$(GL_GNULIB_SYMLINK)/g' \
+ -e 's/@''GNULIB_SYMLINKAT''@/$(GL_GNULIB_SYMLINKAT)/g' \
+ -e 's/@''GNULIB_TRUNCATE''@/$(GL_GNULIB_TRUNCATE)/g' \
+ -e 's/@''GNULIB_TTYNAME_R''@/$(GL_GNULIB_TTYNAME_R)/g' \
+ -e 's/@''GNULIB_UNISTD_H_GETOPT''@/0$(GL_GNULIB_UNISTD_H_GETOPT)/g' \
+ -e 's/@''GNULIB_UNISTD_H_NONBLOCKING''@/$(GL_GNULIB_UNISTD_H_NONBLOCKING)/g' \
+ -e 's/@''GNULIB_UNISTD_H_SIGPIPE''@/$(GL_GNULIB_UNISTD_H_SIGPIPE)/g' \
+ -e 's/@''GNULIB_UNLINK''@/$(GL_GNULIB_UNLINK)/g' \
+ -e 's/@''GNULIB_UNLINKAT''@/$(GL_GNULIB_UNLINKAT)/g' \
+ -e 's/@''GNULIB_USLEEP''@/$(GL_GNULIB_USLEEP)/g' \
+ -e 's/@''GNULIB_WRITE''@/$(GL_GNULIB_WRITE)/g' \
+ -e 's/@''GNULIB_MDA_ACCESS''@/$(GL_GNULIB_MDA_ACCESS)/g' \
+ -e 's/@''GNULIB_MDA_CHDIR''@/$(GL_GNULIB_MDA_CHDIR)/g' \
+ -e 's/@''GNULIB_MDA_CLOSE''@/$(GL_GNULIB_MDA_CLOSE)/g' \
+ -e 's/@''GNULIB_MDA_DUP''@/$(GL_GNULIB_MDA_DUP)/g' \
+ -e 's/@''GNULIB_MDA_DUP2''@/$(GL_GNULIB_MDA_DUP2)/g' \
+ -e 's/@''GNULIB_MDA_EXECL''@/$(GL_GNULIB_MDA_EXECL)/g' \
+ -e 's/@''GNULIB_MDA_EXECLE''@/$(GL_GNULIB_MDA_EXECLE)/g' \
+ -e 's/@''GNULIB_MDA_EXECLP''@/$(GL_GNULIB_MDA_EXECLP)/g' \
+ -e 's/@''GNULIB_MDA_EXECV''@/$(GL_GNULIB_MDA_EXECV)/g' \
+ -e 's/@''GNULIB_MDA_EXECVE''@/$(GL_GNULIB_MDA_EXECVE)/g' \
+ -e 's/@''GNULIB_MDA_EXECVP''@/$(GL_GNULIB_MDA_EXECVP)/g' \
+ -e 's/@''GNULIB_MDA_EXECVPE''@/$(GL_GNULIB_MDA_EXECVPE)/g' \
+ -e 's/@''GNULIB_MDA_GETCWD''@/$(GL_GNULIB_MDA_GETCWD)/g' \
+ -e 's/@''GNULIB_MDA_GETPID''@/$(GL_GNULIB_MDA_GETPID)/g' \
+ -e 's/@''GNULIB_MDA_ISATTY''@/$(GL_GNULIB_MDA_ISATTY)/g' \
+ -e 's/@''GNULIB_MDA_LSEEK''@/$(GL_GNULIB_MDA_LSEEK)/g' \
+ -e 's/@''GNULIB_MDA_READ''@/$(GL_GNULIB_MDA_READ)/g' \
+ -e 's/@''GNULIB_MDA_RMDIR''@/$(GL_GNULIB_MDA_RMDIR)/g' \
+ -e 's/@''GNULIB_MDA_SWAB''@/$(GL_GNULIB_MDA_SWAB)/g' \
+ -e 's/@''GNULIB_MDA_UNLINK''@/$(GL_GNULIB_MDA_UNLINK)/g' \
+ -e 's/@''GNULIB_MDA_WRITE''@/$(GL_GNULIB_MDA_WRITE)/g' \
< $(srcdir)/unistd.in.h | \
sed -e 's|@''HAVE_CHOWN''@|$(HAVE_CHOWN)|g' \
- -e 's|@''HAVE_DUP2''@|$(HAVE_DUP2)|g' \
+ -e 's|@''HAVE_COPY_FILE_RANGE''@|$(HAVE_COPY_FILE_RANGE)|g' \
-e 's|@''HAVE_DUP3''@|$(HAVE_DUP3)|g' \
-e 's|@''HAVE_EUIDACCESS''@|$(HAVE_EUIDACCESS)|g' \
+ -e 's|@''HAVE_EXECVPE''@|$(HAVE_EXECVPE)|g' \
-e 's|@''HAVE_FACCESSAT''@|$(HAVE_FACCESSAT)|g' \
-e 's|@''HAVE_FCHDIR''@|$(HAVE_FCHDIR)|g' \
-e 's|@''HAVE_FCHOWNAT''@|$(HAVE_FCHOWNAT)|g' \
@@ -2960,9 +3902,11 @@ unistd.h: unistd.in.h $(top_builddir)/config.status $(CXXDEFS_H) $(ARG_NONNULL_H
-e 's|@''HAVE_FSYNC''@|$(HAVE_FSYNC)|g' \
-e 's|@''HAVE_FTRUNCATE''@|$(HAVE_FTRUNCATE)|g' \
-e 's|@''HAVE_GETDTABLESIZE''@|$(HAVE_GETDTABLESIZE)|g' \
+ -e 's|@''HAVE_GETENTROPY''@|$(HAVE_GETENTROPY)|g' \
-e 's|@''HAVE_GETGROUPS''@|$(HAVE_GETGROUPS)|g' \
-e 's|@''HAVE_GETHOSTNAME''@|$(HAVE_GETHOSTNAME)|g' \
-e 's|@''HAVE_GETPAGESIZE''@|$(HAVE_GETPAGESIZE)|g' \
+ -e 's|@''HAVE_GETPASS''@|$(HAVE_GETPASS)|g' \
-e 's|@''HAVE_GROUP_MEMBER''@|$(HAVE_GROUP_MEMBER)|g' \
-e 's|@''HAVE_LCHOWN''@|$(HAVE_LCHOWN)|g' \
-e 's|@''HAVE_LINK''@|$(HAVE_LINK)|g' \
@@ -2977,10 +3921,10 @@ unistd.h: unistd.in.h $(top_builddir)/config.status $(CXXDEFS_H) $(ARG_NONNULL_H
-e 's|@''HAVE_SLEEP''@|$(HAVE_SLEEP)|g' \
-e 's|@''HAVE_SYMLINK''@|$(HAVE_SYMLINK)|g' \
-e 's|@''HAVE_SYMLINKAT''@|$(HAVE_SYMLINKAT)|g' \
- -e 's|@''HAVE_TRUNCATE''@|$(HAVE_TRUNCATE)|g' \
-e 's|@''HAVE_UNLINKAT''@|$(HAVE_UNLINKAT)|g' \
-e 's|@''HAVE_USLEEP''@|$(HAVE_USLEEP)|g' \
-e 's|@''HAVE_DECL_ENVIRON''@|$(HAVE_DECL_ENVIRON)|g' \
+ -e 's|@''HAVE_DECL_EXECVPE''@|$(HAVE_DECL_EXECVPE)|g' \
-e 's|@''HAVE_DECL_FCHDIR''@|$(HAVE_DECL_FCHDIR)|g' \
-e 's|@''HAVE_DECL_FDATASYNC''@|$(HAVE_DECL_FDATASYNC)|g' \
-e 's|@''HAVE_DECL_GETDOMAINNAME''@|$(HAVE_DECL_GETDOMAINNAME)|g' \
@@ -2989,14 +3933,25 @@ unistd.h: unistd.in.h $(top_builddir)/config.status $(CXXDEFS_H) $(ARG_NONNULL_H
-e 's|@''HAVE_DECL_GETPAGESIZE''@|$(HAVE_DECL_GETPAGESIZE)|g' \
-e 's|@''HAVE_DECL_GETUSERSHELL''@|$(HAVE_DECL_GETUSERSHELL)|g' \
-e 's|@''HAVE_DECL_SETHOSTNAME''@|$(HAVE_DECL_SETHOSTNAME)|g' \
+ -e 's|@''HAVE_DECL_TRUNCATE''@|$(HAVE_DECL_TRUNCATE)|g' \
-e 's|@''HAVE_DECL_TTYNAME_R''@|$(HAVE_DECL_TTYNAME_R)|g' \
-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_COPY_FILE_RANGE''@|$(REPLACE_COPY_FILE_RANGE)|g' \
-e 's|@''REPLACE_DUP''@|$(REPLACE_DUP)|g' \
-e 's|@''REPLACE_DUP2''@|$(REPLACE_DUP2)|g' \
+ -e 's|@''REPLACE_EXECL''@|$(REPLACE_EXECL)|g' \
+ -e 's|@''REPLACE_EXECLE''@|$(REPLACE_EXECLE)|g' \
+ -e 's|@''REPLACE_EXECLP''@|$(REPLACE_EXECLP)|g' \
+ -e 's|@''REPLACE_EXECV''@|$(REPLACE_EXECV)|g' \
+ -e 's|@''REPLACE_EXECVE''@|$(REPLACE_EXECVE)|g' \
+ -e 's|@''REPLACE_EXECVP''@|$(REPLACE_EXECVP)|g' \
+ -e 's|@''REPLACE_EXECVPE''@|$(REPLACE_EXECVPE)|g' \
+ -e 's|@''REPLACE_FACCESSAT''@|$(REPLACE_FACCESSAT)|g' \
-e 's|@''REPLACE_FCHOWNAT''@|$(REPLACE_FCHOWNAT)|g' \
-e 's|@''REPLACE_FTRUNCATE''@|$(REPLACE_FTRUNCATE)|g' \
-e 's|@''REPLACE_GETCWD''@|$(REPLACE_GETCWD)|g' \
@@ -3005,6 +3960,8 @@ unistd.h: unistd.in.h $(top_builddir)/config.status $(CXXDEFS_H) $(ARG_NONNULL_H
-e 's|@''REPLACE_GETLOGIN_R''@|$(REPLACE_GETLOGIN_R)|g' \
-e 's|@''REPLACE_GETGROUPS''@|$(REPLACE_GETGROUPS)|g' \
-e 's|@''REPLACE_GETPAGESIZE''@|$(REPLACE_GETPAGESIZE)|g' \
+ -e 's|@''REPLACE_GETPASS''@|$(REPLACE_GETPASS)|g' \
+ -e 's|@''REPLACE_GETPASS_FOR_GETPASS_GNU''@|$(REPLACE_GETPASS_FOR_GETPASS_GNU)|g' \
-e 's|@''REPLACE_ISATTY''@|$(REPLACE_ISATTY)|g' \
-e 's|@''REPLACE_LCHOWN''@|$(REPLACE_LCHOWN)|g' \
-e 's|@''REPLACE_LINK''@|$(REPLACE_LINK)|g' \
@@ -3025,13 +3982,14 @@ unistd.h: unistd.in.h $(top_builddir)/config.status $(CXXDEFS_H) $(ARG_NONNULL_H
-e 's|@''REPLACE_UNLINKAT''@|$(REPLACE_UNLINKAT)|g' \
-e 's|@''REPLACE_USLEEP''@|$(REPLACE_USLEEP)|g' \
-e 's|@''REPLACE_WRITE''@|$(REPLACE_WRITE)|g' \
+ -e 's|@''UNISTD_H_HAVE_SYS_RANDOM_H''@|$(UNISTD_H_HAVE_SYS_RANDOM_H)|g' \
-e 's|@''UNISTD_H_HAVE_WINSOCK2_H''@|$(UNISTD_H_HAVE_WINSOCK2_H)|g' \
-e 's|@''UNISTD_H_HAVE_WINSOCK2_H_AND_USE_SOCKETS''@|$(UNISTD_H_HAVE_WINSOCK2_H_AND_USE_SOCKETS)|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)'; \
- } > $@-t && \
- mv $@-t $@
+ -e '/definition of _GL_WARN_ON_USE/r $(WARN_ON_USE_H)' \
+ > $@-t
+ $(AM_V_at)mv $@-t $@
MOSTLYCLEANFILES += unistd.h unistd.h-t
EXTRA_DIST += unistd.in.h
@@ -3039,14 +3997,14 @@ EXTRA_DIST += unistd.in.h
endif
## end gnulib module unistd
-## begin gnulib module unlocked-io
-ifeq (,$(OMIT_GNULIB_MODULE_unlocked-io))
+## begin gnulib module unlocked-io-internal
+ifeq (,$(OMIT_GNULIB_MODULE_unlocked-io-internal))
EXTRA_DIST += unlocked-io.h
endif
-## end gnulib module unlocked-io
+## end gnulib module unlocked-io-internal
## begin gnulib module update-copyright
ifeq (,$(OMIT_GNULIB_MODULE_update-copyright))
@@ -3060,13 +4018,29 @@ endif
## begin gnulib module utimens
ifeq (,$(OMIT_GNULIB_MODULE_utimens))
+ifneq (,$(gl_GNULIB_ENABLED_utimens_CONDITION))
libgnu_a_SOURCES += utimens.c
+endif
EXTRA_DIST += utimens.h
endif
## end gnulib module utimens
+## begin gnulib module utimensat
+ifeq (,$(OMIT_GNULIB_MODULE_utimensat))
+
+ifneq (,$(GL_COND_OBJ_UTIMENSAT_CONDITION))
+libgnu_a_SOURCES += utimensat.c
+endif
+
+EXTRA_DIST += at-func.c
+
+EXTRA_libgnu_a_SOURCES += at-func.c
+
+endif
+## end gnulib module utimensat
+
## begin gnulib module verify
ifeq (,$(OMIT_GNULIB_MODULE_verify))
@@ -3088,7 +4062,7 @@ endif
## begin gnulib module xalloc-oversized
ifeq (,$(OMIT_GNULIB_MODULE_xalloc-oversized))
-ifneq (,$(gl_GNULIB_ENABLED_682e609604ccaac6be382e4ee3a4eaec))
+ifneq (,$(gl_GNULIB_ENABLED_682e609604ccaac6be382e4ee3a4eaec_CONDITION))
endif
EXTRA_DIST += xalloc-oversized.h
@@ -3104,3 +4078,7 @@ mostlyclean-local: mostlyclean-generic
fi; \
done; \
:
+distclean-local: distclean-gnulib-libobjs
+distclean-gnulib-libobjs:
+ -rm -f @gl_LIBOBJDEPS@
+maintainer-clean-local: distclean-gnulib-libobjs
diff --git a/lib/group-member.c b/lib/group-member.c
index 7c4ce496753..cd43f36f4eb 100644
--- a/lib/group-member.c
+++ b/lib/group-member.c
@@ -1,19 +1,19 @@
/* group-member.c -- determine whether group id is in calling user's group list
- Copyright (C) 1994, 1997-1998, 2003, 2005-2006, 2009-2017 Free Software
+ Copyright (C) 1994, 1997-1998, 2003, 2005-2006, 2009-2022 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 file is free software: you can redistribute it and/or modify
+ it under the terms of the GNU Lesser General Public License as
+ published by the Free Software Foundation; either version 2.1 of the
+ License, or (at your option) any later version.
- This program is distributed in the hope that it will be useful,
+ This file 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.
+ GNU Lesser General Public License for more details.
- You should have received a copy of the GNU General Public License
+ You should have received a copy of the GNU Lesser General Public License
along with this program. If not, see <https://www.gnu.org/licenses/>. */
#include <config.h>
@@ -21,12 +21,11 @@
/* Specification. */
#include <unistd.h>
+#include <stdckdint.h>
#include <stdio.h>
#include <sys/types.h>
#include <stdlib.h>
-#include "xalloc-oversized.h"
-
/* Most processes have no more than this many groups, and for these
processes we can avoid using malloc. */
enum { GROUPBUF_SIZE = 100 };
@@ -53,10 +52,10 @@ get_group_info (struct group_info *gi)
if (n_groups < 0)
{
int n_group_slots = getgroups (0, NULL);
- if (0 <= n_group_slots
- && ! xalloc_oversized (n_group_slots, sizeof *gi->group))
+ size_t nbytes;
+ if (! ckd_mul (&nbytes, n_group_slots, sizeof *gi->group))
{
- gi->group = malloc (n_group_slots * sizeof *gi->group);
+ gi->group = malloc (nbytes);
if (gi->group)
n_groups = getgroups (n_group_slots, gi->group);
}
diff --git a/lib/idx.h b/lib/idx.h
new file mode 100644
index 00000000000..c3669ddaca8
--- /dev/null
+++ b/lib/idx.h
@@ -0,0 +1,134 @@
+/* A type for indices and sizes.
+ Copyright (C) 2020-2022 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 Lesser General Public
+ License as published by the Free Software Foundation; either
+ version 2.1 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
+ Lesser General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public
+ License along with the GNU C Library; if not, see
+ <https://www.gnu.org/licenses/>. */
+
+#ifndef _IDX_H
+#define _IDX_H
+
+/* Get ptrdiff_t. */
+#include <stddef.h>
+
+/* Get PTRDIFF_MAX. */
+#include <stdint.h>
+
+/* The type 'idx_t' holds an (array) index or an (object) size.
+ Its implementation promotes to a signed integer type,
+ which can hold the values
+ 0..2^63-1 (on 64-bit platforms) or
+ 0..2^31-1 (on 32-bit platforms).
+
+ Why a signed integer type?
+
+ * Security: Signed types can be checked for overflow via
+ '-fsanitize=undefined', but unsigned types cannot.
+
+ * Comparisons without surprises: ISO C99 § 6.3.1.8 specifies a few
+ surprising results for comparisons, such as
+
+ (int) -3 < (unsigned long) 7 => false
+ (int) -3 < (unsigned int) 7 => false
+ and on 32-bit machines:
+ (long) -3 < (unsigned int) 7 => false
+
+ This is surprising because the natural comparison order is by
+ value in the realm of infinite-precision signed integers (ℤ).
+
+ The best way to get rid of such surprises is to use signed types
+ for numerical integer values, and use unsigned types only for
+ bit masks and enums.
+
+ Why not use 'size_t' directly?
+
+ * Because 'size_t' is an unsigned type, and a signed type is better.
+ See above.
+
+ Why not use 'ssize_t'?
+
+ * 'ptrdiff_t' is more portable; it is standardized by ISO C
+ whereas 'ssize_t' is standardized only by POSIX.
+
+ * 'ssize_t' is not required to be as wide as 'size_t', and some
+ now-obsolete POSIX platforms had 'size_t' wider than 'ssize_t'.
+
+ * Conversely, some now-obsolete platforms had 'ptrdiff_t' wider
+ than 'size_t', which can be a win and conforms to POSIX.
+
+ Won't this cause a problem with objects larger than PTRDIFF_MAX?
+
+ * Typical modern or large platforms do not allocate such objects,
+ so this is not much of a problem in practice; for example, you
+ can safely write 'idx_t len = strlen (s);'. To port to older
+ small platforms where allocations larger than PTRDIFF_MAX could
+ in theory be a problem, you can use Gnulib's ialloc module, or
+ functions like ximalloc in Gnulib's xalloc module.
+
+ Why not use 'ptrdiff_t' directly?
+
+ * Maintainability: When reading and modifying code, it helps to know that
+ a certain variable cannot have negative values. For example, when you
+ have a loop
+
+ int n = ...;
+ for (int i = 0; i < n; i++) ...
+
+ or
+
+ ptrdiff_t n = ...;
+ for (ptrdiff_t i = 0; i < n; i++) ...
+
+ you have to ask yourself "what if n < 0?". Whereas in
+
+ idx_t n = ...;
+ for (idx_t i = 0; i < n; i++) ...
+
+ you know that this case cannot happen.
+
+ Similarly, when a programmer writes
+
+ idx_t = ptr2 - ptr1;
+
+ there is an implied assertion that ptr1 and ptr2 point into the same
+ object and that ptr1 <= ptr2.
+
+ * Being future-proof: In the future, range types (integers which are
+ constrained to a certain range of values) may be added to C compilers
+ or to the C standard. Several programming languages (Ada, Haskell,
+ Common Lisp, Pascal) already have range types. Such range types may
+ help producing good code and good warnings. The type 'idx_t' could
+ then be typedef'ed to a range type that is signed after promotion. */
+
+/* In the future, idx_t could be typedef'ed to a signed range type.
+ The clang "extended integer types", supported in Clang 11 or newer
+ <https://clang.llvm.org/docs/LanguageExtensions.html#extended-integer-types>,
+ are a special case of range types. However, these types don't support binary
+ operators with plain integer types (e.g. expressions such as x > 1).
+ Therefore, they don't behave like signed types (and not like unsigned types
+ either). So, we cannot use them here. */
+
+/* Use the signed type 'ptrdiff_t'. */
+/* Note: ISO C does not mandate that 'size_t' and 'ptrdiff_t' have the same
+ size, but it is so on all platforms we have seen since 1990. */
+typedef ptrdiff_t idx_t;
+
+/* IDX_MAX is the maximum value of an idx_t. */
+#define IDX_MAX PTRDIFF_MAX
+
+/* So far no need has been found for an IDX_WIDTH macro.
+ Perhaps there should be another macro IDX_VALUE_BITS that does not
+ count the sign bit and is therefore one less than PTRDIFF_WIDTH. */
+
+#endif /* _IDX_H */
diff --git a/lib/ieee754.in.h b/lib/ieee754.in.h
new file mode 100644
index 00000000000..2ca9709bb90
--- /dev/null
+++ b/lib/ieee754.in.h
@@ -0,0 +1,222 @@
+/* Copyright (C) 1992-2022 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 Lesser General Public
+ License as published by the Free Software Foundation; either
+ version 2.1 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
+ Lesser General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public
+ License along with the GNU C Library; if not, see
+ <https://www.gnu.org/licenses/>. */
+
+#ifndef _IEEE754_H
+
+#define _IEEE754_H 1
+
+#ifndef _GL_GNULIB_HEADER
+/* Ordinary glibc usage. */
+# include <features.h>
+# include <endian.h>
+#else
+/* Gnulib usage. */
+# ifndef __BEGIN_DECLS
+# ifdef __cplusplus
+# define __BEGIN_DECLS extern "C" {
+# define __END_DECLS }
+# else
+# define __BEGIN_DECLS
+# define __END_DECLS
+# endif
+# endif
+# ifndef __FLOAT_WORD_ORDER
+# define __LITTLE_ENDIAN 1234
+# define __BIG_ENDIAN 4321
+# ifdef WORDS_BIGENDIAN
+# define __BYTE_ORDER __BIG_ENDIAN
+# else
+# define __BYTE_ORDER __LITTLE_ENDIAN
+# endif
+# define __FLOAT_WORD_ORDER __BYTE_ORDER
+# endif
+#endif
+
+__BEGIN_DECLS
+
+union ieee754_float
+ {
+ float f;
+
+ /* This is the IEEE 754 single-precision format. */
+ struct
+ {
+#if __BYTE_ORDER == __BIG_ENDIAN
+ unsigned int negative:1;
+ unsigned int exponent:8;
+ unsigned int mantissa:23;
+#endif /* Big endian. */
+#if __BYTE_ORDER == __LITTLE_ENDIAN
+ unsigned int mantissa:23;
+ unsigned int exponent:8;
+ unsigned int negative:1;
+#endif /* Little endian. */
+ } ieee;
+
+ /* This format makes it easier to see if a NaN is a signalling NaN. */
+ struct
+ {
+#if __BYTE_ORDER == __BIG_ENDIAN
+ unsigned int negative:1;
+ unsigned int exponent:8;
+ unsigned int quiet_nan:1;
+ unsigned int mantissa:22;
+#endif /* Big endian. */
+#if __BYTE_ORDER == __LITTLE_ENDIAN
+ unsigned int mantissa:22;
+ unsigned int quiet_nan:1;
+ unsigned int exponent:8;
+ unsigned int negative:1;
+#endif /* Little endian. */
+ } ieee_nan;
+ };
+
+#define IEEE754_FLOAT_BIAS 0x7f /* Added to exponent. */
+
+
+union ieee754_double
+ {
+ double d;
+
+ /* This is the IEEE 754 double-precision format. */
+ struct
+ {
+#if __BYTE_ORDER == __BIG_ENDIAN
+ unsigned int negative:1;
+ unsigned int exponent:11;
+ /* Together these comprise the mantissa. */
+ unsigned int mantissa0:20;
+ unsigned int mantissa1:32;
+#endif /* Big endian. */
+#if __BYTE_ORDER == __LITTLE_ENDIAN
+# if __FLOAT_WORD_ORDER == __BIG_ENDIAN
+ unsigned int mantissa0:20;
+ unsigned int exponent:11;
+ unsigned int negative:1;
+ unsigned int mantissa1:32;
+# else
+ /* Together these comprise the mantissa. */
+ unsigned int mantissa1:32;
+ unsigned int mantissa0:20;
+ unsigned int exponent:11;
+ unsigned int negative:1;
+# endif
+#endif /* Little endian. */
+ } ieee;
+
+ /* This format makes it easier to see if a NaN is a signalling NaN. */
+ struct
+ {
+#if __BYTE_ORDER == __BIG_ENDIAN
+ unsigned int negative:1;
+ unsigned int exponent:11;
+ unsigned int quiet_nan:1;
+ /* Together these comprise the mantissa. */
+ unsigned int mantissa0:19;
+ unsigned int mantissa1:32;
+#else
+# if __FLOAT_WORD_ORDER == __BIG_ENDIAN
+ unsigned int mantissa0:19;
+ unsigned int quiet_nan:1;
+ unsigned int exponent:11;
+ unsigned int negative:1;
+ unsigned int mantissa1:32;
+# else
+ /* Together these comprise the mantissa. */
+ unsigned int mantissa1:32;
+ unsigned int mantissa0:19;
+ unsigned int quiet_nan:1;
+ unsigned int exponent:11;
+ unsigned int negative:1;
+# endif
+#endif
+ } ieee_nan;
+ };
+
+#define IEEE754_DOUBLE_BIAS 0x3ff /* Added to exponent. */
+
+
+union ieee854_long_double
+ {
+ long double d;
+
+ /* This is the IEEE 854 double-extended-precision format. */
+ struct
+ {
+#if __BYTE_ORDER == __BIG_ENDIAN
+ unsigned int negative:1;
+ unsigned int exponent:15;
+ unsigned int empty:16;
+ unsigned int mantissa0:32;
+ unsigned int mantissa1:32;
+#endif
+#if __BYTE_ORDER == __LITTLE_ENDIAN
+# if __FLOAT_WORD_ORDER == __BIG_ENDIAN
+ unsigned int exponent:15;
+ unsigned int negative:1;
+ unsigned int empty:16;
+ unsigned int mantissa0:32;
+ unsigned int mantissa1:32;
+# else
+ unsigned int mantissa1:32;
+ unsigned int mantissa0:32;
+ unsigned int exponent:15;
+ unsigned int negative:1;
+ unsigned int empty:16;
+# endif
+#endif
+ } ieee;
+
+ /* This is for NaNs in the IEEE 854 double-extended-precision format. */
+ struct
+ {
+#if __BYTE_ORDER == __BIG_ENDIAN
+ unsigned int negative:1;
+ unsigned int exponent:15;
+ unsigned int empty:16;
+ unsigned int one:1;
+ unsigned int quiet_nan:1;
+ unsigned int mantissa0:30;
+ unsigned int mantissa1:32;
+#endif
+#if __BYTE_ORDER == __LITTLE_ENDIAN
+# if __FLOAT_WORD_ORDER == __BIG_ENDIAN
+ unsigned int exponent:15;
+ unsigned int negative:1;
+ unsigned int empty:16;
+ unsigned int mantissa0:30;
+ unsigned int quiet_nan:1;
+ unsigned int one:1;
+ unsigned int mantissa1:32;
+# else
+ unsigned int mantissa1:32;
+ unsigned int mantissa0:30;
+ unsigned int quiet_nan:1;
+ unsigned int one:1;
+ unsigned int exponent:15;
+ unsigned int negative:1;
+ unsigned int empty:16;
+# endif
+#endif
+ } ieee_nan;
+ };
+
+#define IEEE854_LONG_DOUBLE_BIAS 0x3fff
+
+__END_DECLS
+
+#endif /* ieee754.h */
diff --git a/lib/ignore-value.h b/lib/ignore-value.h
index 8ef3fe782f7..173b63f5379 100644
--- a/lib/ignore-value.h
+++ b/lib/ignore-value.h
@@ -1,18 +1,18 @@
/* ignore a function return without a compiler warning. -*- coding: utf-8 -*-
- Copyright (C) 2008-2017 Free Software Foundation, Inc.
+ Copyright (C) 2008-2022 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 file is free software: you can redistribute it and/or modify
+ it under the terms of the GNU Lesser General Public License as
+ published by the Free Software Foundation; either version 2.1 of the
+ License, or (at your option) any later version.
- This program is distributed in the hope that it will be useful,
+ This file 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.
+ GNU Lesser General Public License for more details.
- You should have received a copy of the GNU General Public License
+ You should have received a copy of the GNU Lesser General Public License
along with this program. If not, see <https://www.gnu.org/licenses/>. */
/* Written by Jim Meyering, Eric Blake and Pádraig Brady. */
@@ -39,8 +39,9 @@
versions 3.4 and newer have __attribute__ ((__warn_unused_result__))
which may cause unwanted diagnostics in that case. Use __typeof__
and __extension__ to work around the problem, if the workaround is
- known to be needed. */
-#if 3 < __GNUC__ + (4 <= __GNUC_MINOR__)
+ known to be needed.
+ The workaround is not needed with clang. */
+#if (3 < __GNUC__ + (4 <= __GNUC_MINOR__)) && !defined __clang__
# define ignore_value(x) \
(__extension__ ({ __typeof__ (x) __x = (x); (void) __x; }))
#else
diff --git a/lib/intprops-internal.h b/lib/intprops-internal.h
new file mode 100644
index 00000000000..f6455f78559
--- /dev/null
+++ b/lib/intprops-internal.h
@@ -0,0 +1,392 @@
+/* intprops-internal.h -- properties of integer types not visible to users
+
+ Copyright (C) 2001-2022 Free Software Foundation, Inc.
+
+ This program is free software: you can redistribute it and/or modify it
+ under the terms of the GNU Lesser General Public License as published
+ by the Free Software Foundation; either version 2.1 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 Lesser General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public License
+ along with this program. If not, see <https://www.gnu.org/licenses/>. */
+
+#ifndef _GL_INTPROPS_INTERNAL_H
+#define _GL_INTPROPS_INTERNAL_H
+
+#include <limits.h>
+
+/* Return a value with the common real type of E and V and the value of V.
+ Do not evaluate E. */
+#define _GL_INT_CONVERT(e, v) ((1 ? 0 : (e)) + (v))
+
+/* Act like _GL_INT_CONVERT (E, -V) but work around a bug in IRIX 6.5 cc; see
+ <https://lists.gnu.org/r/bug-gnulib/2011-05/msg00406.html>. */
+#define _GL_INT_NEGATE_CONVERT(e, v) ((1 ? 0 : (e)) - (v))
+
+/* The extra casts in the following macros work around compiler bugs,
+ e.g., in Cray C 5.0.3.0. */
+
+/* True if the real type T is signed. */
+#define _GL_TYPE_SIGNED(t) (! ((t) 0 < (t) -1))
+
+/* Return 1 if the real expression E, after promotion, has a
+ signed or floating type. Do not evaluate E. */
+#define _GL_EXPR_SIGNED(e) (_GL_INT_NEGATE_CONVERT (e, 1) < 0)
+
+
+/* Minimum and maximum values for integer types and expressions. */
+
+/* The width in bits of the integer type or expression T.
+ Do not evaluate T. T must not be a bit-field expression.
+ Padding bits are not supported; this is checked at compile-time below. */
+#define _GL_TYPE_WIDTH(t) (sizeof (t) * CHAR_BIT)
+
+/* The maximum and minimum values for the type of the expression E,
+ after integer promotion. E is not evaluated. */
+#define _GL_INT_MINIMUM(e) \
+ (_GL_EXPR_SIGNED (e) \
+ ? ~ _GL_SIGNED_INT_MAXIMUM (e) \
+ : _GL_INT_CONVERT (e, 0))
+#define _GL_INT_MAXIMUM(e) \
+ (_GL_EXPR_SIGNED (e) \
+ ? _GL_SIGNED_INT_MAXIMUM (e) \
+ : _GL_INT_NEGATE_CONVERT (e, 1))
+#define _GL_SIGNED_INT_MAXIMUM(e) \
+ (((_GL_INT_CONVERT (e, 1) << (_GL_TYPE_WIDTH (+ (e)) - 2)) - 1) * 2 + 1)
+
+/* Work around OpenVMS incompatibility with C99. */
+#if !defined LLONG_MAX && defined __INT64_MAX
+# define LLONG_MAX __INT64_MAX
+# define LLONG_MIN __INT64_MIN
+#endif
+
+/* This include file assumes that signed types are two's complement without
+ padding bits; the above macros have undefined behavior otherwise.
+ If this is a problem for you, please let us know how to fix it for your host.
+ This assumption is tested by the intprops-tests module. */
+
+/* Does the __typeof__ keyword work? This could be done by
+ 'configure', but for now it's easier to do it by hand. */
+#if (2 <= __GNUC__ \
+ || (4 <= __clang_major__) \
+ || (1210 <= __IBMC__ && defined __IBM__TYPEOF__) \
+ || (0x5110 <= __SUNPRO_C && !__STDC__))
+# define _GL_HAVE___TYPEOF__ 1
+#else
+# define _GL_HAVE___TYPEOF__ 0
+#endif
+
+/* Return 1 if the integer type or expression T might be signed. Return 0
+ if it is definitely unsigned. T must not be a bit-field expression.
+ This macro does not evaluate its argument, and expands to an
+ integer constant expression. */
+#if _GL_HAVE___TYPEOF__
+# define _GL_SIGNED_TYPE_OR_EXPR(t) _GL_TYPE_SIGNED (__typeof__ (t))
+#else
+# define _GL_SIGNED_TYPE_OR_EXPR(t) 1
+#endif
+
+/* Return 1 if - A would overflow in [MIN,MAX] arithmetic.
+ A should not have side effects, and A's type should be an
+ integer with minimum value MIN and maximum MAX. */
+#define _GL_INT_NEGATE_RANGE_OVERFLOW(a, min, max) \
+ ((min) < 0 ? (a) < - (max) : 0 < (a))
+
+/* True if __builtin_add_overflow (A, B, P) and __builtin_sub_overflow
+ (A, B, P) work when P is non-null. */
+#ifdef __EDG__
+/* EDG-based compilers like nvc 22.1 cannot add 64-bit signed to unsigned
+ <https://bugs.gnu.org/53256>. */
+# define _GL_HAS_BUILTIN_ADD_OVERFLOW 0
+#elif defined __has_builtin
+# define _GL_HAS_BUILTIN_ADD_OVERFLOW __has_builtin (__builtin_add_overflow)
+/* __builtin_{add,sub}_overflow exists but is not reliable in GCC 5.x and 6.x,
+ see <https://gcc.gnu.org/bugzilla/show_bug.cgi?id=98269>. */
+#elif 7 <= __GNUC__
+# define _GL_HAS_BUILTIN_ADD_OVERFLOW 1
+#else
+# define _GL_HAS_BUILTIN_ADD_OVERFLOW 0
+#endif
+
+/* True if __builtin_mul_overflow (A, B, P) works when P is non-null. */
+#if defined __clang_major__ && __clang_major__ < 14
+/* 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_sub_overflow_p and __builtin_mul_overflow_p. */
+#ifdef __EDG__
+/* In EDG-based compilers like ICC 2021.3 and earlier,
+ __builtin_add_overflow_p etc. are not treated as integral constant
+ expressions even when all arguments are. */
+# define _GL_HAS_BUILTIN_OVERFLOW_P 0
+#elif defined __has_builtin
+# define _GL_HAS_BUILTIN_OVERFLOW_P __has_builtin (__builtin_mul_overflow_p)
+#else
+# define _GL_HAS_BUILTIN_OVERFLOW_P (7 <= __GNUC__)
+#endif
+
+#if (!defined _GL_STDCKDINT_H && 202311 <= __STDC_VERSION__ \
+ && ! (_GL_HAS_BUILTIN_ADD_OVERFLOW && _GL_HAS_BUILTIN_MUL_OVERFLOW))
+# include <stdckdint.h>
+#endif
+
+/* Store the low-order bits of A + B, A - B, A * B, respectively, into *R.
+ Return 1 if the result overflows. Arguments should not have side
+ effects and A, B and *R can be of any integer type other than char,
+ bool, a bit-precise integer type, or an enumeration type. */
+#if _GL_HAS_BUILTIN_ADD_OVERFLOW
+# define _GL_INT_ADD_WRAPV(a, b, r) __builtin_add_overflow (a, b, r)
+# define _GL_INT_SUBTRACT_WRAPV(a, b, r) __builtin_sub_overflow (a, b, r)
+#elif defined ckd_add && defined ckd_sub && !defined _GL_STDCKDINT_H
+# define _GL_INT_ADD_WRAPV(a, b, r) ckd_add (r, + (a), + (b))
+# define _GL_INT_SUBTRACT_WRAPV(a, b, r) ckd_sub (r, + (a), + (b))
+#else
+# define _GL_INT_ADD_WRAPV(a, b, r) \
+ _GL_INT_OP_WRAPV (a, b, r, +, _GL_INT_ADD_RANGE_OVERFLOW)
+# define _GL_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__)) \
+ && !defined __EDG__)
+# define _GL_INT_MULTIPLY_WRAPV(a, b, r) __builtin_mul_overflow (a, b, r)
+# else
+ /* Work around GCC bug 91450. */
+# define _GL_INT_MULTIPLY_WRAPV(a, b, r) \
+ ((!_GL_SIGNED_TYPE_OR_EXPR (*(r)) && _GL_EXPR_SIGNED (a) && _GL_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
+#elif defined ckd_mul && !defined _GL_STDCKDINT_H
+# define _GL_INT_MULTIPLY_WRAPV(a, b, r) ckd_mul (r, + (a), + (b))
+#else
+# define _GL_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 compilers that
+ lack relevant builtins. */
+#if __GNUC__ || defined __clang__
+# define _GL__GENERIC_BOGUS 1
+#else
+# define _GL__GENERIC_BOGUS 0
+#endif
+
+/* Store the low-order bits of A <op> B into *R, where OP specifies
+ the operation and OVERFLOW the overflow predicate. Return 1 if the
+ result overflows. Arguments should not have side effects,
+ and A, B and *R can be of any integer type other than char, bool, a
+ bit-precise integer type, or an enumeration type. */
+#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), \
+ 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
+/* 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. Arguments should not have side
+ effects, and A, B and *R can be of any integer type other than
+ char, bool, a bit-precise integer type, or an enumeration type. */
+# if _GL_HAVE___TYPEOF__
+# define _GL_INT_OP_WRAPV_SMALLISH(a,b,r,op,overflow,st,smin,smax,ut,umax) \
+ (_GL_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_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_WRAPV_SMALLISH (a, b, r, op, overflow, \
+ short int, SHRT_MIN, SHRT_MAX, \
+ unsigned short int, USHRT_MAX) \
+ : sizeof *(r) == sizeof (int) \
+ ? (_GL_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_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)) \
+ : (_GL_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_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
+
+/* Store the low-order bits of A <op> B into *R, where the operation
+ is given by OP. Use the unsigned type UT for calculation to avoid
+ overflow problems. *R's type is T, with extrema TMIN and TMAX.
+ T can be any signed integer type other than char, bool, a
+ bit-precise integer type, or an enumeration type.
+ Return 1 if the result overflows. */
+#define _GL_INT_OP_CALC(a, b, r, op, overflow, ut, t, tmin, tmax) \
+ (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))
+
+/* Return 1 if the integer expressions A - B and -A would overflow,
+ respectively. Arguments should not have side effects,
+ and can be any signed integer type other than char, bool, a
+ bit-precise integer type, or an enumeration type.
+ These macros are tuned for their last input argument being a constant. */
+
+#if _GL_HAS_BUILTIN_OVERFLOW_P
+# define _GL_INT_NEGATE_OVERFLOW(a) \
+ __builtin_sub_overflow_p (0, a, (__typeof__ (- (a))) 0)
+#else
+# define _GL_INT_NEGATE_OVERFLOW(a) \
+ _GL_INT_NEGATE_RANGE_OVERFLOW (a, _GL_INT_MINIMUM (a), _GL_INT_MAXIMUM (a))
+#endif
+
+/* Return the low-order bits of A <op> B, where the operation is given
+ by OP. Use the unsigned type UT for calculation to avoid undefined
+ behavior on signed integer overflow, and convert the result to type T.
+ UT is at least as wide as T and is no narrower than unsigned int,
+ T is two's complement, and there is no padding or trap representations.
+ Assume that converting UT to T yields the low-order bits, as is
+ done in all known two's-complement C compilers. E.g., see:
+ https://gcc.gnu.org/onlinedocs/gcc/Integers-implementation.html
+
+ According to the C standard, converting UT to T yields an
+ implementation-defined result or signal for values outside T's
+ range. However, code that works around this theoretical problem
+ runs afoul of a compiler bug in Oracle Studio 12.3 x86. See:
+ https://lists.gnu.org/r/bug-gnulib/2017-04/msg00049.html
+ As the compiler bug is real, don't try to work around the
+ theoretical problem. */
+
+#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 not have side effects
+ and can be any integer type other than char, bool,
+ a bit-precise integer type, or an enumeration type.
+ 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) \
+ ? ((_GL_EXPR_SIGNED (_GL_INT_CONVERT (a, (tmin) - (b))) || (b) < (tmin)) \
+ && (a) < (tmin) - (b)) \
+ : (a) <= -1 - (b)) \
+ || ((_GL_EXPR_SIGNED (a) ? 0 <= (a) : (tmax) < (a)) && (tmax) < (a) + (b))) \
+ : (a) < 0 \
+ ? (((tmin) \
+ ? ((_GL_EXPR_SIGNED (_GL_INT_CONVERT (b, (tmin) - (a))) || (a) < (tmin)) \
+ && (b) < (tmin) - (a)) \
+ : (b) <= -1 - (a)) \
+ || ((_GL_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 \
+ ? ((!_GL_EXPR_SIGNED (_GL_INT_CONVERT ((a) - (tmin), b)) && (a) - (tmin) < 0) \
+ || (a) - (tmin) < (b)) \
+ : ((! (_GL_EXPR_SIGNED (_GL_INT_CONVERT (tmax, b)) \
+ && _GL_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 \
+ ? (_GL_EXPR_SIGNED (_GL_INT_CONVERT (tmax, b)) \
+ ? (a) < (tmax) / (b) \
+ : ((_GL_INT_NEGATE_OVERFLOW (b) \
+ ? _GL_INT_CONVERT (b, tmax) >> (_GL_TYPE_WIDTH (+ (b)) - 1) \
+ : (tmax) / -(b)) \
+ <= -1 - (a))) \
+ : _GL_INT_NEGATE_OVERFLOW (_GL_INT_CONVERT (b, tmin)) && (b) == -1 \
+ ? (_GL_EXPR_SIGNED (a) \
+ ? 0 < (a) + (tmin) \
+ : 0 < (a) && -1 - (tmin) < (a) - 1) \
+ : (tmin) / (b) < (a)) \
+ : (b) == 0 \
+ ? 0 \
+ : ((a) < 0 \
+ ? (_GL_INT_NEGATE_OVERFLOW (_GL_INT_CONVERT (a, tmin)) && (a) == -1 \
+ ? (_GL_EXPR_SIGNED (b) ? 0 < (b) + (tmin) : -1 - (tmin) < (b) - 1) \
+ : (tmin) / (a) < (b)) \
+ : (tmax) / (b) < (a)))
+
+#endif /* _GL_INTPROPS_INTERNAL_H */
diff --git a/lib/intprops.h b/lib/intprops.h
index a34e81c7b5e..f182ddc1fe6 100644
--- a/lib/intprops.h
+++ b/lib/intprops.h
@@ -1,33 +1,24 @@
/* intprops.h -- properties of integer types
- Copyright (C) 2001-2017 Free Software Foundation, Inc.
+ Copyright (C) 2001-2022 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
+ under the terms of the GNU Lesser General Public License as published
+ by the Free Software Foundation; either version 2.1 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.
+ GNU Lesser General Public License for more details.
- You should have received a copy of the GNU General Public License
+ You should have received a copy of the GNU Lesser General Public License
along with this program. If not, see <https://www.gnu.org/licenses/>. */
-/* Written by Paul Eggert. */
-
#ifndef _GL_INTPROPS_H
#define _GL_INTPROPS_H
-#include <limits.h>
-
-/* Return a value with the common real type of E and V and the value of V. */
-#define _GL_INT_CONVERT(e, v) (0 * (e) + (v))
-
-/* Act like _GL_INT_CONVERT (E, -V) but work around a bug in IRIX 6.5 cc; see
- <https://lists.gnu.org/archive/html/bug-gnulib/2011-05/msg00406.html>. */
-#define _GL_INT_NEGATE_CONVERT(e, v) (0 * (e) - (v))
+#include "intprops-internal.h"
/* The extra casts in the following macros work around compiler bugs,
e.g., in Cray C 5.0.3.0. */
@@ -37,18 +28,19 @@
#define TYPE_IS_INTEGER(t) ((t) 1.5 == 1)
/* True if the real type T is signed. */
-#define TYPE_SIGNED(t) (! ((t) 0 < (t) -1))
+#define TYPE_SIGNED(t) _GL_TYPE_SIGNED (t)
/* Return 1 if the real expression E, after promotion, has a
- signed or floating type. */
-#define EXPR_SIGNED(e) (_GL_INT_NEGATE_CONVERT (e, 1) < 0)
+ signed or floating type. Do not evaluate E. */
+#define EXPR_SIGNED(e) _GL_EXPR_SIGNED (e)
/* Minimum and maximum values for integer types and expressions. */
/* The width in bits of the integer type or expression T.
+ Do not evaluate T. T must not be a bit-field expression.
Padding bits are not supported; this is checked at compile-time below. */
-#define TYPE_WIDTH(t) (sizeof (t) * CHAR_BIT)
+#define TYPE_WIDTH(t) _GL_TYPE_WIDTH (t)
/* The maximum and minimum values for the integer type T. */
#define TYPE_MINIMUM(t) ((t) ~ TYPE_MAXIMUM (t))
@@ -57,78 +49,37 @@
? (t) -1 \
: ((((t) 1 << (TYPE_WIDTH (t) - 2)) - 1) * 2 + 1)))
-/* The maximum and minimum values for the type of the expression E,
- after integer promotion. E should not have side effects. */
-#define _GL_INT_MINIMUM(e) \
- (EXPR_SIGNED (e) \
- ? ~ _GL_SIGNED_INT_MAXIMUM (e) \
- : _GL_INT_CONVERT (e, 0))
-#define _GL_INT_MAXIMUM(e) \
- (EXPR_SIGNED (e) \
- ? _GL_SIGNED_INT_MAXIMUM (e) \
- : _GL_INT_NEGATE_CONVERT (e, 1))
-#define _GL_SIGNED_INT_MAXIMUM(e) \
- (((_GL_INT_CONVERT (e, 1) << (TYPE_WIDTH ((e) + 0) - 2)) - 1) * 2 + 1)
-
-/* Work around OpenVMS incompatibility with C99. */
-#if !defined LLONG_MAX && defined __INT64_MAX
-# define LLONG_MAX __INT64_MAX
-# define LLONG_MIN __INT64_MIN
-#endif
-
-/* This include file assumes that signed types are two's complement without
- padding bits; the above macros have undefined behavior otherwise.
- If this is a problem for you, please let us know how to fix it for your host.
- This assumption is tested by the intprops-tests module. */
-
-/* Does the __typeof__ keyword work? This could be done by
- 'configure', but for now it's easier to do it by hand. */
-#if (2 <= __GNUC__ \
- || (1210 <= __IBMC__ && defined __IBM__TYPEOF__) \
- || (0x5110 <= __SUNPRO_C && !__STDC__))
-# define _GL_HAVE___TYPEOF__ 1
-#else
-# define _GL_HAVE___TYPEOF__ 0
-#endif
-
-/* Return 1 if the integer type or expression T might be signed. Return 0
- if it is definitely unsigned. This macro does not evaluate its argument,
- and expands to an integer constant expression. */
-#if _GL_HAVE___TYPEOF__
-# define _GL_SIGNED_TYPE_OR_EXPR(t) TYPE_SIGNED (__typeof__ (t))
-#else
-# define _GL_SIGNED_TYPE_OR_EXPR(t) 1
-#endif
-
/* Bound on length of the string representing an unsigned integer
value representable in B bits. log10 (2.0) < 146/485. The
smallest value of B where this bound is not tight is 2621. */
#define INT_BITS_STRLEN_BOUND(b) (((b) * 146 + 484) / 485)
/* Bound on length of the string representing an integer type or expression T.
+ T must not be a bit-field expression.
+
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)) \
+ _GL_SIGNED_TYPE_OR_EXPR (t))
/* Bound on buffer size needed to represent an integer type or expression T,
- including the terminating null. */
+ including the terminating null. T must not be a bit-field expression. */
#define INT_BUFSIZE_BOUND(t) (INT_STRLEN_BOUND (t) + 1)
/* Range overflow checks.
The INT_<op>_RANGE_OVERFLOW macros return 1 if the corresponding C
- operators might not yield numerically correct answers due to
- arithmetic overflow. They do not rely on undefined or
- implementation-defined behavior. Their implementations are simple
- and straightforward, but they are a bit harder to use than the
- INT_<op>_OVERFLOW macros described below.
+ operators overflow arithmetically when given the same arguments.
+ These macros do not rely on undefined or implementation-defined behavior.
+ Although their implementations are simple and straightforward,
+ they are harder to use and may be less efficient than the
+ INT_<op>_WRAPV, INT_<op>_OK, and INT_<op>_OVERFLOW macros described below.
Example usage:
@@ -152,6 +103,9 @@
must have minimum value MIN and maximum MAX. Unsigned types should
use a zero MIN of the proper type.
+ Because all arguments are subject to integer promotions, these
+ macros typically do not work on types narrower than 'int'.
+
These macros are tuned for constant MIN and MAX. For commutative
operations such as A + B, they are also tuned for constant B. */
@@ -172,14 +126,12 @@
/* Return 1 if - A would overflow in [MIN,MAX] arithmetic.
See above for restrictions. */
#define INT_NEGATE_RANGE_OVERFLOW(a, min, max) \
- ((min) < 0 \
- ? (a) < - (max) \
- : 0 < (a))
+ _GL_INT_NEGATE_RANGE_OVERFLOW (a, min, max)
/* Return 1 if A * B would overflow in [MIN,MAX] arithmetic.
See above for restrictions. Avoid && and || as they tickle
bugs in Sun C 5.11 2010/08/13 and other compilers; see
- <https://lists.gnu.org/archive/html/bug-gnulib/2011-05/msg00401.html>. */
+ <https://lists.gnu.org/r/bug-gnulib/2011-05/msg00401.html>. */
#define INT_MULTIPLY_RANGE_OVERFLOW(a, b, min, max) \
((b) < 0 \
? ((a) < 0 \
@@ -218,16 +170,6 @@
? (a) < (min) >> (b) \
: (max) >> (b) < (a))
-/* True if __builtin_add_overflow (A, B, P) works when P is non-null. */
-#if 5 <= __GNUC__ && !defined __ICC
-# define _GL_HAS_BUILTIN_OVERFLOW 1
-#else
-# define _GL_HAS_BUILTIN_OVERFLOW 0
-#endif
-
-/* True if __builtin_add_overflow_p (A, B, C) works. */
-#define _GL_HAS_BUILTIN_OVERFLOW_P (7 <= __GNUC__)
-
/* The _GL*_OVERFLOW macros have the same restrictions as the
*_RANGE_OVERFLOW macros, except that they do not assume that operands
(e.g., A and B) have the same type as MIN and MAX. Instead, they assume
@@ -279,7 +221,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.
@@ -307,9 +251,22 @@
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. For
+ example, in the typical case with 16-bit 'short' and 32-bit 'int',
+ if A, B and *R are all of type 'short' then INT_ADD_OVERFLOW (A, B)
+ returns false because the addition cannot overflow after A and B
+ are converted to 'int', whereas INT_ADD_WRAPV (A, B, R) returns
+ true or false depending on whether the sum fits into 'short'.
- These macros are tuned for their last argument being a constant.
+ These macros are tuned for their last input argument being a constant.
+
+ A, B, and *R should be integers; they need not be the same type,
+ and they need not be all signed or all unsigned.
+ However, none of the integer types should be bit-precise,
+ and *R's type should not be char, bool, or an enumeration type.
Return 1 if the integer expressions A * B, A - B, -A, A * B, A / B,
A % B, and A << B would overflow, respectively. */
@@ -318,12 +275,7 @@
_GL_BINARY_OP_OVERFLOW (a, b, _GL_ADD_OVERFLOW)
#define INT_SUBTRACT_OVERFLOW(a, b) \
_GL_BINARY_OP_OVERFLOW (a, b, _GL_SUBTRACT_OVERFLOW)
-#if _GL_HAS_BUILTIN_OVERFLOW_P
-# define INT_NEGATE_OVERFLOW(a) INT_SUBTRACT_OVERFLOW (0, a)
-#else
-# define INT_NEGATE_OVERFLOW(a) \
- INT_NEGATE_RANGE_OVERFLOW (a, _GL_INT_MINIMUM (a), _GL_INT_MAXIMUM (a))
-#endif
+#define INT_NEGATE_OVERFLOW(a) _GL_INT_NEGATE_OVERFLOW (a)
#define INT_MULTIPLY_OVERFLOW(a, b) \
_GL_BINARY_OP_OVERFLOW (a, b, _GL_MULTIPLY_OVERFLOW)
#define INT_DIVIDE_OVERFLOW(a, b) \
@@ -340,114 +292,44 @@
Arguments should be free of side effects. */
#define _GL_BINARY_OP_OVERFLOW(a, b, op_result_overflow) \
op_result_overflow (a, b, \
- _GL_INT_MINIMUM (0 * (b) + (a)), \
- _GL_INT_MAXIMUM (0 * (b) + (a)))
+ _GL_INT_MINIMUM (_GL_INT_CONVERT (a, b)), \
+ _GL_INT_MAXIMUM (_GL_INT_CONVERT (a, b)))
/* 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)
-
-/* 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. */
-#if __GNUC__
-# define _GL__GENERIC_BOGUS 1
-#else
-# define _GL__GENERIC_BOGUS 0
-#endif
+#define INT_ADD_WRAPV(a, b, r) _GL_INT_ADD_WRAPV (a, b, r)
+#define INT_SUBTRACT_WRAPV(a, b, r) _GL_INT_SUBTRACT_WRAPV (a, b, r)
+#define INT_MULTIPLY_WRAPV(a, b, r) _GL_INT_MULTIPLY_WRAPV (a, b, r)
-/* 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) \
- (_Generic \
- (*(r), \
- signed char: \
- _GL_INT_OP_CALC (a, b, r, op, overflow, unsigned int, \
- signed char, SCHAR_MIN, SCHAR_MAX), \
- short int: \
- _GL_INT_OP_CALC (a, b, r, op, overflow, unsigned int, \
- short int, SHRT_MIN, SHRT_MAX), \
- int: \
- _GL_INT_OP_CALC (a, b, r, op, overflow, unsigned int, \
- int, INT_MIN, INT_MAX), \
- long int: \
- _GL_INT_OP_CALC (a, b, r, op, overflow, unsigned long int, \
- long int, LONG_MIN, LONG_MAX), \
- long long int: \
- _GL_INT_OP_CALC (a, b, r, op, overflow, unsigned long long int, \
- long long int, LLONG_MIN, LLONG_MAX)))
-#else
-# define _GL_INT_OP_WRAPV(a, b, r, op, builtin, overflow) \
- (sizeof *(r) == sizeof (signed char) \
- ? _GL_INT_OP_CALC (a, b, r, op, overflow, unsigned int, \
- signed char, SCHAR_MIN, SCHAR_MAX) \
- : sizeof *(r) == sizeof (short int) \
- ? _GL_INT_OP_CALC (a, b, r, op, overflow, unsigned int, \
- short int, SHRT_MIN, SHRT_MAX) \
- : sizeof *(r) == sizeof (int) \
- ? _GL_INT_OP_CALC (a, b, r, op, overflow, unsigned int, \
- int, INT_MIN, INT_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))
-# 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)
-# endif
-#endif
+/* The following macros compute A + B, A - B, and A * B, respectively.
+ If no overflow occurs, they set *R to the result and return 1;
+ otherwise, they return 0 and may modify *R.
+
+ Example usage:
+
+ long int result;
+ if (INT_ADD_OK (a, b, &result))
+ printf ("result is %ld\n", result);
+ else
+ printf ("overflow\n");
+
+ A, B, and *R should be integers; they need not be the same type,
+ and they need not be all signed or all unsigned.
+ However, none of the integer types should be bit-precise,
+ and *R's type should not be char, bool, or an enumeration type.
+
+ These macros work correctly on all known practical hosts, and do not rely
+ on undefined behavior due to signed arithmetic overflow.
+
+ These macros are not constant expressions.
+
+ These macros may evaluate their arguments zero or multiple times, so the
+ arguments should not have side effects.
+
+ These macros are tuned for B being a constant. */
-/* Store the low-order bits of A <op> B into *R, where the operation
- is given by OP. Use the unsigned type UT for calculation to avoid
- 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))) \
- ? (*(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))
-
-/* Return the low-order bits of A <op> B, where the operation is given
- by OP. Use the unsigned type UT for calculation to avoid undefined
- behavior on signed integer overflow, and convert the result to type T.
- UT is at least as wide as T and is no narrower than unsigned int,
- T is two's complement, and there is no padding or trap representations.
- Assume that converting UT to T yields the low-order bits, as is
- done in all known two's-complement C compilers. E.g., see:
- https://gcc.gnu.org/onlinedocs/gcc/Integers-implementation.html
-
- According to the C standard, converting UT to T yields an
- implementation-defined result or signal for values outside T's
- range. However, code that works around this theoretical problem
- runs afoul of a compiler bug in Oracle Studio 12.3 x86. See:
- https://lists.gnu.org/archive/html/bug-gnulib/2017-04/msg00049.html
- As the compiler bug is real, don't try to work around the
- theoretical problem. */
-
-#define _GL_INT_OP_WRAPV_VIA_UNSIGNED(a, b, op, ut, t) \
- ((t) ((ut) (a) op (ut) (b)))
+#define INT_ADD_OK(a, b, r) (! INT_ADD_WRAPV (a, b, r))
+#define INT_SUBTRACT_OK(a, b, r) (! INT_SUBTRACT_WRAPV (a, b, r))
+#define INT_MULTIPLY_OK(a, b, r) (! INT_MULTIPLY_WRAPV (a, b, r))
#endif /* _GL_INTPROPS_H */
diff --git a/lib/inttypes.in.h b/lib/inttypes.in.h
index e7357e96acc..853eca087c5 100644
--- a/lib/inttypes.in.h
+++ b/lib/inttypes.in.h
@@ -1,23 +1,23 @@
-/* Copyright (C) 2006-2017 Free Software Foundation, Inc.
+/* Copyright (C) 2006-2022 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 file is free software: you can redistribute it and/or modify
+ it under the terms of the GNU Lesser General Public License as
+ published by the Free Software Foundation; either version 2.1 of the
+ License, or (at your option) any later version.
- This program is distributed in the hope that it will be useful,
+ This file 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.
+ GNU Lesser General Public License for more details.
- You should have received a copy of the GNU General Public License
+ You should have received a copy of the GNU Lesser 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.
- * <http://www.opengroup.org/susv3xbd/inttypes.h.html>
+ * <https://pubs.opengroup.org/onlinepubs/9699919799/basedefs/inttypes.h.html>
*/
#if __GNUC__ >= 3
@@ -38,6 +38,8 @@
# endif
# @INCLUDE_NEXT@ @NEXT_INTTYPES_H@
+
+# define _GL_FINISHED_INCLUDING_SYSTEM_INTTYPES_H
# endif
#endif
@@ -49,15 +51,15 @@
#ifndef __GLIBC__
# include <stdint.h>
#endif
-/* Get CHAR_BIT. */
+/* 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 __WIN32__) && ! defined __CYGWIN__
+#if defined _WIN32 && ! defined __CYGWIN__
# include <stdio.h>
#endif
-#if !(INT_MIN == INT32_MIN && INT_MAX == INT32_MAX)
-# error "This file assumes that 'int' has exactly 32 bits. Please report your platform and compiler to <bug-gnulib@gnu.org>."
+#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. */
@@ -76,110 +78,92 @@
# define _LONG_LONG_FORMAT_PREFIX "ll"
#endif
-#if !defined PRId8 || @PRI_MACROS_BROKEN@
-# undef PRId8
+#if !defined PRId8
# ifdef INT8_MAX
# define PRId8 "d"
# endif
#endif
-#if !defined PRIi8 || @PRI_MACROS_BROKEN@
-# undef PRIi8
+#if !defined PRIi8
# ifdef INT8_MAX
# define PRIi8 "i"
# endif
#endif
-#if !defined PRIo8 || @PRI_MACROS_BROKEN@
-# undef PRIo8
+#if !defined PRIo8
# ifdef UINT8_MAX
# define PRIo8 "o"
# endif
#endif
-#if !defined PRIu8 || @PRI_MACROS_BROKEN@
-# undef PRIu8
+#if !defined PRIu8
# ifdef UINT8_MAX
# define PRIu8 "u"
# endif
#endif
-#if !defined PRIx8 || @PRI_MACROS_BROKEN@
-# undef PRIx8
+#if !defined PRIx8
# ifdef UINT8_MAX
# define PRIx8 "x"
# endif
#endif
-#if !defined PRIX8 || @PRI_MACROS_BROKEN@
-# undef PRIX8
+#if !defined PRIX8
# ifdef UINT8_MAX
# define PRIX8 "X"
# endif
#endif
-#if !defined PRId16 || @PRI_MACROS_BROKEN@
-# undef PRId16
+#if !defined PRId16
# ifdef INT16_MAX
# define PRId16 "d"
# endif
#endif
-#if !defined PRIi16 || @PRI_MACROS_BROKEN@
-# undef PRIi16
+#if !defined PRIi16
# ifdef INT16_MAX
# define PRIi16 "i"
# endif
#endif
-#if !defined PRIo16 || @PRI_MACROS_BROKEN@
-# undef PRIo16
+#if !defined PRIo16
# ifdef UINT16_MAX
# define PRIo16 "o"
# endif
#endif
-#if !defined PRIu16 || @PRI_MACROS_BROKEN@
-# undef PRIu16
+#if !defined PRIu16
# ifdef UINT16_MAX
# define PRIu16 "u"
# endif
#endif
-#if !defined PRIx16 || @PRI_MACROS_BROKEN@
-# undef PRIx16
+#if !defined PRIx16
# ifdef UINT16_MAX
# define PRIx16 "x"
# endif
#endif
-#if !defined PRIX16 || @PRI_MACROS_BROKEN@
-# undef PRIX16
+#if !defined PRIX16
# ifdef UINT16_MAX
# define PRIX16 "X"
# endif
#endif
-#if !defined PRId32 || @PRI_MACROS_BROKEN@
-# undef PRId32
+#if !defined PRId32
# ifdef INT32_MAX
# define PRId32 "d"
# endif
#endif
-#if !defined PRIi32 || @PRI_MACROS_BROKEN@
-# undef PRIi32
+#if !defined PRIi32
# ifdef INT32_MAX
# define PRIi32 "i"
# endif
#endif
-#if !defined PRIo32 || @PRI_MACROS_BROKEN@
-# undef PRIo32
+#if !defined PRIo32
# ifdef UINT32_MAX
# define PRIo32 "o"
# endif
#endif
-#if !defined PRIu32 || @PRI_MACROS_BROKEN@
-# undef PRIu32
+#if !defined PRIu32
# ifdef UINT32_MAX
# define PRIu32 "u"
# endif
#endif
-#if !defined PRIx32 || @PRI_MACROS_BROKEN@
-# undef PRIx32
+#if !defined PRIx32
# ifdef UINT32_MAX
# define PRIx32 "x"
# endif
#endif
-#if !defined PRIX32 || @PRI_MACROS_BROKEN@
-# undef PRIX32
+#if !defined PRIX32
# ifdef UINT32_MAX
# define PRIX32 "X"
# endif
@@ -189,15 +173,13 @@
# define _PRI64_PREFIX "l"
# elif defined _MSC_VER || defined __MINGW32__
# define _PRI64_PREFIX "I64"
-# elif @HAVE_LONG_LONG_INT@ && LONG_MAX >> 30 == 1
+# elif LONG_MAX >> 30 == 1
# define _PRI64_PREFIX _LONG_LONG_FORMAT_PREFIX
# endif
-# if !defined PRId64 || @PRI_MACROS_BROKEN@
-# undef PRId64
+# if !defined PRId64
# define PRId64 _PRI64_PREFIX "d"
# endif
-# if !defined PRIi64 || @PRI_MACROS_BROKEN@
-# undef PRIi64
+# if !defined PRIi64
# define PRIi64 _PRI64_PREFIX "i"
# endif
#endif
@@ -206,266 +188,220 @@
# define _PRIu64_PREFIX "l"
# elif defined _MSC_VER || defined __MINGW32__
# define _PRIu64_PREFIX "I64"
-# elif @HAVE_UNSIGNED_LONG_LONG_INT@ && ULONG_MAX >> 31 == 1
+# elif ULONG_MAX >> 31 == 1
# define _PRIu64_PREFIX _LONG_LONG_FORMAT_PREFIX
# endif
-# if !defined PRIo64 || @PRI_MACROS_BROKEN@
-# undef PRIo64
+# if !defined PRIo64
# define PRIo64 _PRIu64_PREFIX "o"
# endif
-# if !defined PRIu64 || @PRI_MACROS_BROKEN@
-# undef PRIu64
+# if !defined PRIu64
# define PRIu64 _PRIu64_PREFIX "u"
# endif
-# if !defined PRIx64 || @PRI_MACROS_BROKEN@
-# undef PRIx64
+# if !defined PRIx64
# define PRIx64 _PRIu64_PREFIX "x"
# endif
-# if !defined PRIX64 || @PRI_MACROS_BROKEN@
-# undef PRIX64
+# if !defined PRIX64
# define PRIX64 _PRIu64_PREFIX "X"
# endif
#endif
-#if !defined PRIdLEAST8 || @PRI_MACROS_BROKEN@
-# undef PRIdLEAST8
+#if !defined PRIdLEAST8
# define PRIdLEAST8 "d"
#endif
-#if !defined PRIiLEAST8 || @PRI_MACROS_BROKEN@
-# undef PRIiLEAST8
+#if !defined PRIiLEAST8
# define PRIiLEAST8 "i"
#endif
-#if !defined PRIoLEAST8 || @PRI_MACROS_BROKEN@
-# undef PRIoLEAST8
+#if !defined PRIoLEAST8
# define PRIoLEAST8 "o"
#endif
-#if !defined PRIuLEAST8 || @PRI_MACROS_BROKEN@
-# undef PRIuLEAST8
+#if !defined PRIuLEAST8
# define PRIuLEAST8 "u"
#endif
-#if !defined PRIxLEAST8 || @PRI_MACROS_BROKEN@
-# undef PRIxLEAST8
+#if !defined PRIxLEAST8
# define PRIxLEAST8 "x"
#endif
-#if !defined PRIXLEAST8 || @PRI_MACROS_BROKEN@
-# undef PRIXLEAST8
+#if !defined PRIXLEAST8
# define PRIXLEAST8 "X"
#endif
-#if !defined PRIdLEAST16 || @PRI_MACROS_BROKEN@
-# undef PRIdLEAST16
+#if !defined PRIdLEAST16
# define PRIdLEAST16 "d"
#endif
-#if !defined PRIiLEAST16 || @PRI_MACROS_BROKEN@
-# undef PRIiLEAST16
+#if !defined PRIiLEAST16
# define PRIiLEAST16 "i"
#endif
-#if !defined PRIoLEAST16 || @PRI_MACROS_BROKEN@
-# undef PRIoLEAST16
+#if !defined PRIoLEAST16
# define PRIoLEAST16 "o"
#endif
-#if !defined PRIuLEAST16 || @PRI_MACROS_BROKEN@
-# undef PRIuLEAST16
+#if !defined PRIuLEAST16
# define PRIuLEAST16 "u"
#endif
-#if !defined PRIxLEAST16 || @PRI_MACROS_BROKEN@
-# undef PRIxLEAST16
+#if !defined PRIxLEAST16
# define PRIxLEAST16 "x"
#endif
-#if !defined PRIXLEAST16 || @PRI_MACROS_BROKEN@
-# undef PRIXLEAST16
+#if !defined PRIXLEAST16
# define PRIXLEAST16 "X"
#endif
-#if !defined PRIdLEAST32 || @PRI_MACROS_BROKEN@
-# undef PRIdLEAST32
+#if !defined PRIdLEAST32
# define PRIdLEAST32 "d"
#endif
-#if !defined PRIiLEAST32 || @PRI_MACROS_BROKEN@
-# undef PRIiLEAST32
+#if !defined PRIiLEAST32
# define PRIiLEAST32 "i"
#endif
-#if !defined PRIoLEAST32 || @PRI_MACROS_BROKEN@
-# undef PRIoLEAST32
+#if !defined PRIoLEAST32
# define PRIoLEAST32 "o"
#endif
-#if !defined PRIuLEAST32 || @PRI_MACROS_BROKEN@
-# undef PRIuLEAST32
+#if !defined PRIuLEAST32
# define PRIuLEAST32 "u"
#endif
-#if !defined PRIxLEAST32 || @PRI_MACROS_BROKEN@
-# undef PRIxLEAST32
+#if !defined PRIxLEAST32
# define PRIxLEAST32 "x"
#endif
-#if !defined PRIXLEAST32 || @PRI_MACROS_BROKEN@
-# undef PRIXLEAST32
+#if !defined PRIXLEAST32
# define PRIXLEAST32 "X"
#endif
#ifdef INT64_MAX
-# if !defined PRIdLEAST64 || @PRI_MACROS_BROKEN@
-# undef PRIdLEAST64
+# if !defined PRIdLEAST64
# define PRIdLEAST64 PRId64
# endif
-# if !defined PRIiLEAST64 || @PRI_MACROS_BROKEN@
-# undef PRIiLEAST64
+# if !defined PRIiLEAST64
# define PRIiLEAST64 PRIi64
# endif
#endif
#ifdef UINT64_MAX
-# if !defined PRIoLEAST64 || @PRI_MACROS_BROKEN@
-# undef PRIoLEAST64
+# if !defined PRIoLEAST64
# define PRIoLEAST64 PRIo64
# endif
-# if !defined PRIuLEAST64 || @PRI_MACROS_BROKEN@
-# undef PRIuLEAST64
+# if !defined PRIuLEAST64
# define PRIuLEAST64 PRIu64
# endif
-# if !defined PRIxLEAST64 || @PRI_MACROS_BROKEN@
-# undef PRIxLEAST64
+# if !defined PRIxLEAST64
# define PRIxLEAST64 PRIx64
# endif
-# if !defined PRIXLEAST64 || @PRI_MACROS_BROKEN@
-# undef PRIXLEAST64
+# if !defined PRIXLEAST64
# define PRIXLEAST64 PRIX64
# endif
#endif
-#if !defined PRIdFAST8 || @PRI_MACROS_BROKEN@
-# undef PRIdFAST8
+#if !defined 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 !defined 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 !defined 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 !defined 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 !defined 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 !defined 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 !defined 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 !defined 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 !defined 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 !defined 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 !defined 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 !defined 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 !defined 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 !defined 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 !defined 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 !defined 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 !defined 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 !defined PRIXFAST32
# if UINT_FAST32_MAX > UINT32_MAX
# define PRIXFAST32 PRIX64
# else
@@ -473,76 +409,64 @@
# endif
#endif
#ifdef INT64_MAX
-# if !defined PRIdFAST64 || @PRI_MACROS_BROKEN@
-# undef PRIdFAST64
+# if !defined PRIdFAST64
# define PRIdFAST64 PRId64
# endif
-# if !defined PRIiFAST64 || @PRI_MACROS_BROKEN@
-# undef PRIiFAST64
+# if !defined PRIiFAST64
# define PRIiFAST64 PRIi64
# endif
#endif
#ifdef UINT64_MAX
-# if !defined PRIoFAST64 || @PRI_MACROS_BROKEN@
-# undef PRIoFAST64
+# if !defined PRIoFAST64
# define PRIoFAST64 PRIo64
# endif
-# if !defined PRIuFAST64 || @PRI_MACROS_BROKEN@
-# undef PRIuFAST64
+# if !defined PRIuFAST64
# define PRIuFAST64 PRIu64
# endif
-# if !defined PRIxFAST64 || @PRI_MACROS_BROKEN@
-# undef PRIxFAST64
+# if !defined PRIxFAST64
# define PRIxFAST64 PRIx64
# endif
-# if !defined PRIXFAST64 || @PRI_MACROS_BROKEN@
-# undef PRIXFAST64
+# if !defined PRIXFAST64
# define PRIXFAST64 PRIX64
# endif
#endif
-#if !defined PRIdMAX || @PRI_MACROS_BROKEN@
-# undef PRIdMAX
+#if !defined 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 !defined 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 !defined 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 !defined 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 !defined 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 !defined PRIXMAX
# if @UINT32_MAX_LT_UINTMAX_MAX@
# define PRIXMAX PRIX64
# else
@@ -550,129 +474,108 @@
# endif
#endif
-#if !defined PRIdPTR || @PRI_MACROS_BROKEN@
-# undef PRIdPTR
+#if !defined PRIdPTR
# ifdef INTPTR_MAX
# define PRIdPTR @PRIPTR_PREFIX@ "d"
# endif
#endif
-#if !defined PRIiPTR || @PRI_MACROS_BROKEN@
-# undef PRIiPTR
+#if !defined PRIiPTR
# ifdef INTPTR_MAX
# define PRIiPTR @PRIPTR_PREFIX@ "i"
# endif
#endif
-#if !defined PRIoPTR || @PRI_MACROS_BROKEN@
-# undef PRIoPTR
+#if !defined PRIoPTR
# ifdef UINTPTR_MAX
# define PRIoPTR @PRIPTR_PREFIX@ "o"
# endif
#endif
-#if !defined PRIuPTR || @PRI_MACROS_BROKEN@
-# undef PRIuPTR
+#if !defined PRIuPTR
# ifdef UINTPTR_MAX
# define PRIuPTR @PRIPTR_PREFIX@ "u"
# endif
#endif
-#if !defined PRIxPTR || @PRI_MACROS_BROKEN@
-# undef PRIxPTR
+#if !defined PRIxPTR
# ifdef UINTPTR_MAX
# define PRIxPTR @PRIPTR_PREFIX@ "x"
# endif
#endif
-#if !defined PRIXPTR || @PRI_MACROS_BROKEN@
-# undef PRIXPTR
+#if !defined PRIXPTR
# ifdef UINTPTR_MAX
# define PRIXPTR @PRIPTR_PREFIX@ "X"
# endif
#endif
-#if !defined SCNd8 || @PRI_MACROS_BROKEN@
-# undef SCNd8
+#if !defined SCNd8
# ifdef INT8_MAX
# define SCNd8 "hhd"
# endif
#endif
-#if !defined SCNi8 || @PRI_MACROS_BROKEN@
-# undef SCNi8
+#if !defined SCNi8
# ifdef INT8_MAX
# define SCNi8 "hhi"
# endif
#endif
-#if !defined SCNo8 || @PRI_MACROS_BROKEN@
-# undef SCNo8
+#if !defined SCNo8
# ifdef UINT8_MAX
# define SCNo8 "hho"
# endif
#endif
-#if !defined SCNu8 || @PRI_MACROS_BROKEN@
-# undef SCNu8
+#if !defined SCNu8
# ifdef UINT8_MAX
# define SCNu8 "hhu"
# endif
#endif
-#if !defined SCNx8 || @PRI_MACROS_BROKEN@
-# undef SCNx8
+#if !defined SCNx8
# ifdef UINT8_MAX
# define SCNx8 "hhx"
# endif
#endif
-#if !defined SCNd16 || @PRI_MACROS_BROKEN@
-# undef SCNd16
+#if !defined SCNd16
# ifdef INT16_MAX
# define SCNd16 "hd"
# endif
#endif
-#if !defined SCNi16 || @PRI_MACROS_BROKEN@
-# undef SCNi16
+#if !defined SCNi16
# ifdef INT16_MAX
# define SCNi16 "hi"
# endif
#endif
-#if !defined SCNo16 || @PRI_MACROS_BROKEN@
-# undef SCNo16
+#if !defined SCNo16
# ifdef UINT16_MAX
# define SCNo16 "ho"
# endif
#endif
-#if !defined SCNu16 || @PRI_MACROS_BROKEN@
-# undef SCNu16
+#if !defined SCNu16
# ifdef UINT16_MAX
# define SCNu16 "hu"
# endif
#endif
-#if !defined SCNx16 || @PRI_MACROS_BROKEN@
-# undef SCNx16
+#if !defined SCNx16
# ifdef UINT16_MAX
# define SCNx16 "hx"
# endif
#endif
-#if !defined SCNd32 || @PRI_MACROS_BROKEN@
-# undef SCNd32
+#if !defined SCNd32
# ifdef INT32_MAX
# define SCNd32 "d"
# endif
#endif
-#if !defined SCNi32 || @PRI_MACROS_BROKEN@
-# undef SCNi32
+#if !defined SCNi32
# ifdef INT32_MAX
# define SCNi32 "i"
# endif
#endif
-#if !defined SCNo32 || @PRI_MACROS_BROKEN@
-# undef SCNo32
+#if !defined SCNo32
# ifdef UINT32_MAX
# define SCNo32 "o"
# endif
#endif
-#if !defined SCNu32 || @PRI_MACROS_BROKEN@
-# undef SCNu32
+#if !defined SCNu32
# ifdef UINT32_MAX
# define SCNu32 "u"
# endif
#endif
-#if !defined SCNx32 || @PRI_MACROS_BROKEN@
-# undef SCNx32
+#if !defined SCNx32
# ifdef UINT32_MAX
# define SCNx32 "x"
# endif
@@ -682,15 +585,13 @@
# define _SCN64_PREFIX "l"
# elif defined _MSC_VER || defined __MINGW32__
# define _SCN64_PREFIX "I64"
-# elif @HAVE_LONG_LONG_INT@ && LONG_MAX >> 30 == 1
+# elif LONG_MAX >> 30 == 1
# define _SCN64_PREFIX _LONG_LONG_FORMAT_PREFIX
# endif
-# if !defined SCNd64 || @PRI_MACROS_BROKEN@
-# undef SCNd64
+# if !defined SCNd64
# define SCNd64 _SCN64_PREFIX "d"
# endif
-# if !defined SCNi64 || @PRI_MACROS_BROKEN@
-# undef SCNi64
+# if !defined SCNi64
# define SCNi64 _SCN64_PREFIX "i"
# endif
#endif
@@ -699,110 +600,86 @@
# define _SCNu64_PREFIX "l"
# elif defined _MSC_VER || defined __MINGW32__
# define _SCNu64_PREFIX "I64"
-# elif @HAVE_UNSIGNED_LONG_LONG_INT@ && ULONG_MAX >> 31 == 1
+# elif ULONG_MAX >> 31 == 1
# define _SCNu64_PREFIX _LONG_LONG_FORMAT_PREFIX
# endif
-# if !defined SCNo64 || @PRI_MACROS_BROKEN@
-# undef SCNo64
+# if !defined SCNo64
# define SCNo64 _SCNu64_PREFIX "o"
# endif
-# if !defined SCNu64 || @PRI_MACROS_BROKEN@
-# undef SCNu64
+# if !defined SCNu64
# define SCNu64 _SCNu64_PREFIX "u"
# endif
-# if !defined SCNx64 || @PRI_MACROS_BROKEN@
-# undef SCNx64
+# if !defined SCNx64
# define SCNx64 _SCNu64_PREFIX "x"
# endif
#endif
-#if !defined SCNdLEAST8 || @PRI_MACROS_BROKEN@
-# undef SCNdLEAST8
+#if !defined SCNdLEAST8
# define SCNdLEAST8 "hhd"
#endif
-#if !defined SCNiLEAST8 || @PRI_MACROS_BROKEN@
-# undef SCNiLEAST8
+#if !defined SCNiLEAST8
# define SCNiLEAST8 "hhi"
#endif
-#if !defined SCNoLEAST8 || @PRI_MACROS_BROKEN@
-# undef SCNoLEAST8
+#if !defined SCNoLEAST8
# define SCNoLEAST8 "hho"
#endif
-#if !defined SCNuLEAST8 || @PRI_MACROS_BROKEN@
-# undef SCNuLEAST8
+#if !defined SCNuLEAST8
# define SCNuLEAST8 "hhu"
#endif
-#if !defined SCNxLEAST8 || @PRI_MACROS_BROKEN@
-# undef SCNxLEAST8
+#if !defined SCNxLEAST8
# define SCNxLEAST8 "hhx"
#endif
-#if !defined SCNdLEAST16 || @PRI_MACROS_BROKEN@
-# undef SCNdLEAST16
+#if !defined SCNdLEAST16
# define SCNdLEAST16 "hd"
#endif
-#if !defined SCNiLEAST16 || @PRI_MACROS_BROKEN@
-# undef SCNiLEAST16
+#if !defined SCNiLEAST16
# define SCNiLEAST16 "hi"
#endif
-#if !defined SCNoLEAST16 || @PRI_MACROS_BROKEN@
-# undef SCNoLEAST16
+#if !defined SCNoLEAST16
# define SCNoLEAST16 "ho"
#endif
-#if !defined SCNuLEAST16 || @PRI_MACROS_BROKEN@
-# undef SCNuLEAST16
+#if !defined SCNuLEAST16
# define SCNuLEAST16 "hu"
#endif
-#if !defined SCNxLEAST16 || @PRI_MACROS_BROKEN@
-# undef SCNxLEAST16
+#if !defined SCNxLEAST16
# define SCNxLEAST16 "hx"
#endif
-#if !defined SCNdLEAST32 || @PRI_MACROS_BROKEN@
-# undef SCNdLEAST32
+#if !defined SCNdLEAST32
# define SCNdLEAST32 "d"
#endif
-#if !defined SCNiLEAST32 || @PRI_MACROS_BROKEN@
-# undef SCNiLEAST32
+#if !defined SCNiLEAST32
# define SCNiLEAST32 "i"
#endif
-#if !defined SCNoLEAST32 || @PRI_MACROS_BROKEN@
-# undef SCNoLEAST32
+#if !defined SCNoLEAST32
# define SCNoLEAST32 "o"
#endif
-#if !defined SCNuLEAST32 || @PRI_MACROS_BROKEN@
-# undef SCNuLEAST32
+#if !defined SCNuLEAST32
# define SCNuLEAST32 "u"
#endif
-#if !defined SCNxLEAST32 || @PRI_MACROS_BROKEN@
-# undef SCNxLEAST32
+#if !defined SCNxLEAST32
# define SCNxLEAST32 "x"
#endif
#ifdef INT64_MAX
-# if !defined SCNdLEAST64 || @PRI_MACROS_BROKEN@
-# undef SCNdLEAST64
+# if !defined SCNdLEAST64
# define SCNdLEAST64 SCNd64
# endif
-# if !defined SCNiLEAST64 || @PRI_MACROS_BROKEN@
-# undef SCNiLEAST64
+# if !defined SCNiLEAST64
# define SCNiLEAST64 SCNi64
# endif
#endif
#ifdef UINT64_MAX
-# if !defined SCNoLEAST64 || @PRI_MACROS_BROKEN@
-# undef SCNoLEAST64
+# if !defined SCNoLEAST64
# define SCNoLEAST64 SCNo64
# endif
-# if !defined SCNuLEAST64 || @PRI_MACROS_BROKEN@
-# undef SCNuLEAST64
+# if !defined SCNuLEAST64
# define SCNuLEAST64 SCNu64
# endif
-# if !defined SCNxLEAST64 || @PRI_MACROS_BROKEN@
-# undef SCNxLEAST64
+# if !defined SCNxLEAST64
# define SCNxLEAST64 SCNx64
# endif
#endif
-#if !defined SCNdFAST8 || @PRI_MACROS_BROKEN@
-# undef SCNdFAST8
+#if !defined SCNdFAST8
# if INT_FAST8_MAX > INT32_MAX
# define SCNdFAST8 SCNd64
# elif INT_FAST8_MAX == 0x7fff
@@ -813,8 +690,7 @@
# define SCNdFAST8 "d"
# endif
#endif
-#if !defined SCNiFAST8 || @PRI_MACROS_BROKEN@
-# undef SCNiFAST8
+#if !defined SCNiFAST8
# if INT_FAST8_MAX > INT32_MAX
# define SCNiFAST8 SCNi64
# elif INT_FAST8_MAX == 0x7fff
@@ -825,8 +701,7 @@
# define SCNiFAST8 "i"
# endif
#endif
-#if !defined SCNoFAST8 || @PRI_MACROS_BROKEN@
-# undef SCNoFAST8
+#if !defined SCNoFAST8
# if UINT_FAST8_MAX > UINT32_MAX
# define SCNoFAST8 SCNo64
# elif UINT_FAST8_MAX == 0xffff
@@ -837,8 +712,7 @@
# define SCNoFAST8 "o"
# endif
#endif
-#if !defined SCNuFAST8 || @PRI_MACROS_BROKEN@
-# undef SCNuFAST8
+#if !defined SCNuFAST8
# if UINT_FAST8_MAX > UINT32_MAX
# define SCNuFAST8 SCNu64
# elif UINT_FAST8_MAX == 0xffff
@@ -849,8 +723,7 @@
# define SCNuFAST8 "u"
# endif
#endif
-#if !defined SCNxFAST8 || @PRI_MACROS_BROKEN@
-# undef SCNxFAST8
+#if !defined SCNxFAST8
# if UINT_FAST8_MAX > UINT32_MAX
# define SCNxFAST8 SCNx64
# elif UINT_FAST8_MAX == 0xffff
@@ -861,8 +734,7 @@
# define SCNxFAST8 "x"
# endif
#endif
-#if !defined SCNdFAST16 || @PRI_MACROS_BROKEN@
-# undef SCNdFAST16
+#if !defined SCNdFAST16
# if INT_FAST16_MAX > INT32_MAX
# define SCNdFAST16 SCNd64
# elif INT_FAST16_MAX == 0x7fff
@@ -871,8 +743,7 @@
# define SCNdFAST16 "d"
# endif
#endif
-#if !defined SCNiFAST16 || @PRI_MACROS_BROKEN@
-# undef SCNiFAST16
+#if !defined SCNiFAST16
# if INT_FAST16_MAX > INT32_MAX
# define SCNiFAST16 SCNi64
# elif INT_FAST16_MAX == 0x7fff
@@ -881,8 +752,7 @@
# define SCNiFAST16 "i"
# endif
#endif
-#if !defined SCNoFAST16 || @PRI_MACROS_BROKEN@
-# undef SCNoFAST16
+#if !defined SCNoFAST16
# if UINT_FAST16_MAX > UINT32_MAX
# define SCNoFAST16 SCNo64
# elif UINT_FAST16_MAX == 0xffff
@@ -891,8 +761,7 @@
# define SCNoFAST16 "o"
# endif
#endif
-#if !defined SCNuFAST16 || @PRI_MACROS_BROKEN@
-# undef SCNuFAST16
+#if !defined SCNuFAST16
# if UINT_FAST16_MAX > UINT32_MAX
# define SCNuFAST16 SCNu64
# elif UINT_FAST16_MAX == 0xffff
@@ -901,8 +770,7 @@
# define SCNuFAST16 "u"
# endif
#endif
-#if !defined SCNxFAST16 || @PRI_MACROS_BROKEN@
-# undef SCNxFAST16
+#if !defined SCNxFAST16
# if UINT_FAST16_MAX > UINT32_MAX
# define SCNxFAST16 SCNx64
# elif UINT_FAST16_MAX == 0xffff
@@ -911,40 +779,35 @@
# define SCNxFAST16 "x"
# endif
#endif
-#if !defined SCNdFAST32 || @PRI_MACROS_BROKEN@
-# undef SCNdFAST32
+#if !defined 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 !defined 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 !defined 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 !defined 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 !defined SCNxFAST32
# if UINT_FAST32_MAX > UINT32_MAX
# define SCNxFAST32 SCNx64
# else
@@ -952,64 +815,54 @@
# endif
#endif
#ifdef INT64_MAX
-# if !defined SCNdFAST64 || @PRI_MACROS_BROKEN@
-# undef SCNdFAST64
+# if !defined SCNdFAST64
# define SCNdFAST64 SCNd64
# endif
-# if !defined SCNiFAST64 || @PRI_MACROS_BROKEN@
-# undef SCNiFAST64
+# if !defined SCNiFAST64
# define SCNiFAST64 SCNi64
# endif
#endif
#ifdef UINT64_MAX
-# if !defined SCNoFAST64 || @PRI_MACROS_BROKEN@
-# undef SCNoFAST64
+# if !defined SCNoFAST64
# define SCNoFAST64 SCNo64
# endif
-# if !defined SCNuFAST64 || @PRI_MACROS_BROKEN@
-# undef SCNuFAST64
+# if !defined SCNuFAST64
# define SCNuFAST64 SCNu64
# endif
-# if !defined SCNxFAST64 || @PRI_MACROS_BROKEN@
-# undef SCNxFAST64
+# if !defined SCNxFAST64
# define SCNxFAST64 SCNx64
# endif
#endif
-#if !defined SCNdMAX || @PRI_MACROS_BROKEN@
-# undef SCNdMAX
+#if !defined 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 !defined 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 !defined 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 !defined 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 !defined SCNxMAX
# if @UINT32_MAX_LT_UINTMAX_MAX@
# define SCNxMAX SCNx64
# else
@@ -1017,32 +870,27 @@
# endif
#endif
-#if !defined SCNdPTR || @PRI_MACROS_BROKEN@
-# undef SCNdPTR
+#if !defined SCNdPTR
# ifdef INTPTR_MAX
# define SCNdPTR @PRIPTR_PREFIX@ "d"
# endif
#endif
-#if !defined SCNiPTR || @PRI_MACROS_BROKEN@
-# undef SCNiPTR
+#if !defined SCNiPTR
# ifdef INTPTR_MAX
# define SCNiPTR @PRIPTR_PREFIX@ "i"
# endif
#endif
-#if !defined SCNoPTR || @PRI_MACROS_BROKEN@
-# undef SCNoPTR
+#if !defined SCNoPTR
# ifdef UINTPTR_MAX
# define SCNoPTR @PRIPTR_PREFIX@ "o"
# endif
#endif
-#if !defined SCNuPTR || @PRI_MACROS_BROKEN@
-# undef SCNuPTR
+#if !defined SCNuPTR
# ifdef UINTPTR_MAX
# define SCNuPTR @PRIPTR_PREFIX@ "u"
# endif
#endif
-#if !defined SCNxPTR || @PRI_MACROS_BROKEN@
-# undef SCNxPTR
+#if !defined SCNxPTR
# ifdef UINTPTR_MAX
# define SCNxPTR @PRIPTR_PREFIX@ "x"
# endif
@@ -1067,11 +915,13 @@ _GL_WARN_ON_USE (imaxabs, "imaxabs is unportable - "
#endif
#if @GNULIB_IMAXDIV@
-# if !@HAVE_DECL_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
@@ -1089,15 +939,19 @@ _GL_WARN_ON_USE (imaxdiv, "imaxdiv is unportable - "
# 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));
+ (const char *restrict, char **restrict, int)
+ _GL_ARG_NONNULL ((1)));
+_GL_CXXALIAS_RPL (strtoimax, intmax_t,
+ (const char *restrict, char **restrict, int));
# else
# if !@HAVE_DECL_STRTOIMAX@
# undef strtoimax
_GL_FUNCDECL_SYS (strtoimax, intmax_t,
- (const char *, char **, int) _GL_ARG_NONNULL ((1)));
+ (const char *restrict, char **restrict, int)
+ _GL_ARG_NONNULL ((1)));
# endif
-_GL_CXXALIAS_SYS (strtoimax, intmax_t, (const char *, char **, int));
+_GL_CXXALIAS_SYS (strtoimax, intmax_t,
+ (const char *restrict, char **restrict, int));
# endif
_GL_CXXALIASWARN (strtoimax);
#elif defined GNULIB_POSIXCHECK
@@ -1115,15 +969,19 @@ _GL_WARN_ON_USE (strtoimax, "strtoimax is unportable - "
# 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));
+ (const char *restrict, char **restrict, int)
+ _GL_ARG_NONNULL ((1)));
+_GL_CXXALIAS_RPL (strtoumax, uintmax_t,
+ (const char *restrict, char **restrict, int));
# else
# if !@HAVE_DECL_STRTOUMAX@
# undef strtoumax
_GL_FUNCDECL_SYS (strtoumax, uintmax_t,
- (const char *, char **, int) _GL_ARG_NONNULL ((1)));
+ (const char *restrict, char **restrict, int)
+ _GL_ARG_NONNULL ((1)));
# endif
-_GL_CXXALIAS_SYS (strtoumax, uintmax_t, (const char *, char **, int));
+_GL_CXXALIAS_SYS (strtoumax, uintmax_t,
+ (const char *restrict, char **restrict, int));
# endif
_GL_CXXALIASWARN (strtoumax);
#elif defined GNULIB_POSIXCHECK
diff --git a/lib/lchmod.c b/lib/lchmod.c
new file mode 100644
index 00000000000..8410a2d835f
--- /dev/null
+++ b/lib/lchmod.c
@@ -0,0 +1,94 @@
+/* Implement lchmod on platforms where it does not work correctly.
+
+ Copyright 2020-2022 Free Software Foundation, Inc.
+
+ This program is free software: you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation, either version 3 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program. If not, see <https://www.gnu.org/licenses/>. */
+
+/* written by Paul Eggert */
+
+#include <config.h>
+
+/* Specification. */
+#include <sys/stat.h>
+
+#include <errno.h>
+#include <fcntl.h>
+#include <stdio.h>
+#include <string.h>
+#include <unistd.h>
+
+#include <intprops.h>
+
+/* Work like chmod, except when FILE is a symbolic link.
+ In that case, on systems where permissions on symbolic links are unsupported
+ (such as Linux), set errno to EOPNOTSUPP and return -1. */
+
+int
+lchmod (char const *file, mode_t mode)
+{
+ char readlink_buf[1];
+
+#ifdef O_PATH
+ /* Open a file descriptor with O_NOFOLLOW, to make sure we don't
+ follow symbolic links, if /proc is mounted. O_PATH is used to
+ avoid a failure if the file is not readable.
+ Cf. <https://sourceware.org/bugzilla/show_bug.cgi?id=14578> */
+ int fd = open (file, O_PATH | O_NOFOLLOW | O_CLOEXEC);
+ if (fd < 0)
+ return fd;
+
+ int err;
+ if (0 <= readlinkat (fd, "", readlink_buf, sizeof readlink_buf))
+ err = EOPNOTSUPP;
+ else if (errno == EINVAL)
+ {
+ static char const fmt[] = "/proc/self/fd/%d";
+ char buf[sizeof fmt - sizeof "%d" + INT_BUFSIZE_BOUND (int)];
+ sprintf (buf, fmt, fd);
+ err = chmod (buf, mode) == 0 ? 0 : errno == ENOENT ? -1 : errno;
+ }
+ else
+ err = errno == ENOENT ? -1 : errno;
+
+ close (fd);
+
+ errno = err;
+ if (0 <= err)
+ return err == 0 ? 0 : -1;
+#endif
+
+ size_t len = strlen (file);
+ if (len && file[len - 1] == '/')
+ {
+ struct stat st;
+ if (lstat (file, &st) < 0)
+ return -1;
+ if (!S_ISDIR (st.st_mode))
+ {
+ errno = ENOTDIR;
+ return -1;
+ }
+ }
+
+ /* O_PATH + /proc is not supported. */
+
+ if (0 <= readlink (file, readlink_buf, sizeof readlink_buf))
+ {
+ errno = EOPNOTSUPP;
+ return -1;
+ }
+
+ /* Fall back on chmod, despite a possible race. */
+ return chmod (file, mode);
+}
diff --git a/lib/libc-config.h b/lib/libc-config.h
new file mode 100644
index 00000000000..a56665b1ce3
--- /dev/null
+++ b/lib/libc-config.h
@@ -0,0 +1,202 @@
+/* System definitions for code taken from the GNU C Library
+
+ Copyright 2017-2022 Free Software Foundation, Inc.
+
+ This program is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Lesser General Public
+ License as published by the Free Software Foundation; either
+ version 2.1 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
+ Lesser General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public
+ License along with this program; if not, see
+ <https://www.gnu.org/licenses/>. */
+
+/* Written by Paul Eggert. */
+
+/* This is intended to be a good-enough substitute for glibc system
+ macros like those defined in <sys/cdefs.h>, so that Gnulib code
+ shared with glibc can do this as the first #include:
+
+ #ifndef _LIBC
+ # include <libc-config.h>
+ #endif
+
+ When compiled as part of glibc this is a no-op; when compiled as
+ part of Gnulib this includes Gnulib's <config.h> and defines macros
+ that glibc library code would normally assume.
+
+ Note: This header file MUST NOT be included by public header files
+ of Gnulib. */
+
+#include <config.h>
+
+/* On glibc this includes <features.h> and <sys/cdefs.h> and #defines
+ _FEATURES_H, __WORDSIZE, and __set_errno. On FreeBSD 11 and
+ DragonFlyBSD 5.9 it includes <sys/cdefs.h> which defines __nonnull.
+ Elsewhere it is harmless. */
+#include <errno.h>
+
+/* From glibc <errno.h>. */
+#ifndef __set_errno
+# define __set_errno(val) (errno = (val))
+#endif
+
+/* From glibc <features.h>. */
+
+#ifndef __GNUC_PREREQ
+# if defined __GNUC__ && defined __GNUC_MINOR__
+# define __GNUC_PREREQ(maj, min) ((maj) < __GNUC__ + ((min) <= __GNUC_MINOR__))
+# else
+# define __GNUC_PREREQ(maj, min) 0
+# endif
+#endif
+
+#ifndef __glibc_clang_prereq
+# if defined __clang_major__ && defined __clang_minor__
+# ifdef __apple_build_version__
+/* Apple for some reason renumbers __clang_major__ and __clang_minor__.
+ Gnulib code uses only __glibc_clang_prereq (3, 5); map it to
+ 6000000 <= __apple_build_version__. Support for other calls to
+ __glibc_clang_prereq can be added here as needed. */
+# define __glibc_clang_prereq(maj, min) \
+ ((maj) == 3 && (min) == 5 ? 6000000 <= __apple_build_version__ : 0)
+# else
+# define __glibc_clang_prereq(maj, min) \
+ ((maj) < __clang_major__ + ((min) <= __clang_minor__))
+# endif
+# else
+# define __glibc_clang_prereq(maj, min) 0
+# endif
+#endif
+
+#ifndef __attribute_nonnull__
+/* <sys/cdefs.h> either does not exist, or is too old for Gnulib.
+ Prepare to include <cdefs.h>, which is Gnulib's version of a
+ more-recent glibc <sys/cdefs.h>. */
+
+/* Define _FEATURES_H so that <cdefs.h> does not include <features.h>. */
+# ifndef _FEATURES_H
+# define _FEATURES_H 1
+# endif
+/* Define __GNULIB_CDEFS so that <cdefs.h> does not attempt to include
+ nonexistent files. */
+# define __GNULIB_CDEFS
+/* Undef the macros unconditionally defined by our copy of glibc
+ <sys/cdefs.h>, so that they do not clash with any system-defined
+ versions. */
+# undef _SYS_CDEFS_H
+# undef __ASMNAME
+# undef __ASMNAME2
+# undef __BEGIN_DECLS
+# undef __CONCAT
+# undef __END_DECLS
+# undef __HAVE_GENERIC_SELECTION
+# undef __LDBL_COMPAT
+# undef __LDBL_REDIR
+# undef __LDBL_REDIR1
+# undef __LDBL_REDIR1_DECL
+# undef __LDBL_REDIR1_NTH
+# undef __LDBL_REDIR2_DECL
+# undef __LDBL_REDIR_DECL
+# undef __LDBL_REDIR_NTH
+# undef __LEAF
+# undef __LEAF_ATTR
+# undef __NTH
+# undef __NTHNL
+# undef __REDIRECT
+# undef __REDIRECT_LDBL
+# undef __REDIRECT_NTH
+# undef __REDIRECT_NTHNL
+# undef __REDIRECT_NTH_LDBL
+# undef __STRING
+# undef __THROW
+# undef __THROWNL
+# undef __attr_access
+# undef __attr_access_none
+# undef __attr_dealloc
+# undef __attr_dealloc_free
+# undef __attribute__
+# undef __attribute_alloc_align__
+# undef __attribute_alloc_size__
+# undef __attribute_artificial__
+# undef __attribute_const__
+# undef __attribute_deprecated__
+# undef __attribute_deprecated_msg__
+# undef __attribute_format_arg__
+# undef __attribute_format_strfmon__
+# undef __attribute_malloc__
+# undef __attribute_maybe_unused__
+# undef __attribute_noinline__
+# undef __attribute_nonstring__
+# undef __attribute_pure__
+# undef __attribute_returns_twice__
+# undef __attribute_used__
+# undef __attribute_warn_unused_result__
+# undef __bos
+# undef __bos0
+# undef __errordecl
+# undef __extension__
+# undef __extern_always_inline
+# undef __extern_inline
+# undef __flexarr
+# undef __fortified_attr_access
+# undef __fortify_function
+# undef __glibc_c99_flexarr_available
+# undef __glibc_fortify
+# undef __glibc_fortify_n
+# undef __glibc_has_attribute
+# undef __glibc_has_builtin
+# undef __glibc_has_extension
+# undef __glibc_likely
+# undef __glibc_macro_warning
+# undef __glibc_macro_warning1
+# undef __glibc_objsize
+# undef __glibc_objsize0
+# undef __glibc_safe_len_cond
+# undef __glibc_safe_or_unknown_len
+# undef __glibc_unlikely
+# undef __glibc_unsafe_len
+# undef __glibc_unsigned_or_positive
+# undef __inline
+# undef __ptr_t
+# undef __restrict
+# undef __restrict_arr
+# undef __va_arg_pack
+# undef __va_arg_pack_len
+# undef __warnattr
+# undef __wur
+
+/* Include our copy of glibc <sys/cdefs.h>. */
+# include <cdefs.h>
+
+/* <cdefs.h> __inline is too pessimistic for non-GCC. */
+# undef __inline
+# ifndef HAVE___INLINE
+# if 199901 <= __STDC_VERSION__ || defined inline
+# define __inline inline
+# else
+# define __inline
+# endif
+# endif
+
+#endif /* defined __glibc_likely */
+
+
+/* A substitute for glibc <libc-symbols.h>, good enough for Gnulib. */
+#define attribute_hidden
+#define libc_hidden_proto(name)
+#define libc_hidden_def(name)
+#define libc_hidden_weak(name)
+#define libc_hidden_ver(local, name)
+#define strong_alias(name, aliasname)
+#define weak_alias(name, aliasname)
+
+/* A substitute for glibc <shlib-compat.h>, good enough for Gnulib. */
+#define SHLIB_COMPAT(lib, introduced, obsoleted) 0
+#define compat_symbol(lib, local, symbol, version) extern int dummy
+#define versioned_symbol(lib, local, symbol, version) extern int dummy
diff --git a/lib/limits.in.h b/lib/limits.in.h
index 78dcf31037e..b77bf75c5fe 100644
--- a/lib/limits.in.h
+++ b/lib/limits.in.h
@@ -1,42 +1,75 @@
/* A GNU-like <limits.h>.
- Copyright 2016-2017 Free Software Foundation, Inc.
+ Copyright 2016-2022 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 file is free software: you can redistribute it and/or modify
+ it under the terms of the GNU Lesser General Public License as
+ published by the Free Software Foundation; either version 2.1 of the
+ License, or (at your option) any later version.
- This program is distributed in the hope that it will be useful,
+ This file 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.
+ GNU Lesser 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 _@GUARD_PREFIX@_LIMITS_H
+ You should have received a copy of the GNU Lesser General Public License
+ along with this program. If not, see <https://www.gnu.org/licenses/>. */
#if __GNUC__ >= 3
@PRAGMA_SYSTEM_HEADER@
#endif
@PRAGMA_COLUMNS@
-/* The include_next requires a split double-inclusion guard. */
+#if defined _GL_ALREADY_INCLUDING_LIMITS_H
+/* Special invocation convention:
+ On Haiku/x86_64, we have a sequence of nested includes
+ <limits.h> -> <syslimits.h> -> <limits.h>.
+ In this situation, LONG_MAX and INT_MAX are not yet defined,
+ therefore we should not attempt to define LONG_BIT. */
+
#@INCLUDE_NEXT@ @NEXT_LIMITS_H@
+#else
+/* Normal invocation convention. */
+
+#ifndef _@GUARD_PREFIX@_LIMITS_H
+
+# define _GL_ALREADY_INCLUDING_LIMITS_H
+
+/* The include_next requires a split double-inclusion guard. */
+# @INCLUDE_NEXT@ @NEXT_LIMITS_H@
+
+# undef _GL_ALREADY_INCLUDING_LIMITS_H
+
#ifndef _@GUARD_PREFIX@_LIMITS_H
#define _@GUARD_PREFIX@_LIMITS_H
-/* For HP-UX 11.31. */
-#if defined LONG_LONG_MIN && !defined LLONG_MIN
-# define LLONG_MIN LONG_LONG_MIN
+#ifndef LLONG_MIN
+# if defined LONG_LONG_MIN /* HP-UX 11.31 */
+# define LLONG_MIN LONG_LONG_MIN
+# elif defined LONGLONG_MIN /* IRIX 6.5 */
+# define LLONG_MIN LONGLONG_MIN
+# elif defined __GNUC__
+# define LLONG_MIN (- __LONG_LONG_MAX__ - 1LL)
+# endif
#endif
-#if defined LONG_LONG_MAX && !defined LLONG_MAX
-# define LLONG_MAX LONG_LONG_MAX
+#ifndef LLONG_MAX
+# if defined LONG_LONG_MAX /* HP-UX 11.31 */
+# define LLONG_MAX LONG_LONG_MAX
+# elif defined LONGLONG_MAX /* IRIX 6.5 */
+# define LLONG_MAX LONGLONG_MAX
+# elif defined __GNUC__
+# define LLONG_MAX __LONG_LONG_MAX__
+# endif
#endif
-#if defined ULONG_LONG_MAX && !defined ULLONG_MAX
-# define ULLONG_MAX ULONG_LONG_MAX
+#ifndef ULLONG_MAX
+# if defined ULONG_LONG_MAX /* HP-UX 11.31 */
+# define ULLONG_MAX ULONG_LONG_MAX
+# elif defined ULONGLONG_MAX /* IRIX 6.5 */
+# define ULLONG_MAX ULONGLONG_MAX
+# elif defined __GNUC__
+# define ULLONG_MAX (__LONG_LONG_MAX__ * 2ULL + 1ULL)
+# endif
#endif
/* The number of usable bits in an unsigned or signed integer type
@@ -53,10 +86,24 @@
#define _GL_COB8(n) (_GL_COB4 ((n) >> 4) + _GL_COB4 (n))
#define _GL_COB4(n) (!!((n) & 8) + !!((n) & 4) + !!((n) & 2) + !!((n) & 1))
-/* Macros specified by ISO/IEC TS 18661-1:2014. */
+#ifndef WORD_BIT
+/* Assume 'int' is 32 bits wide. */
+# define WORD_BIT 32
+#endif
+#ifndef LONG_BIT
+/* Assume 'long' is 32 or 64 bits wide. */
+# if LONG_MAX == INT_MAX
+# define LONG_BIT 32
+# else
+# define LONG_BIT 64
+# endif
+#endif
+
+/* Macros specified by C2x and by ISO/IEC TS 18661-1:2014. */
#if (! defined ULLONG_WIDTH \
- && (defined _GNU_SOURCE || defined __STDC_WANT_IEC_60559_BFP_EXT__))
+ && (defined _GNU_SOURCE || defined __STDC_WANT_IEC_60559_BFP_EXT__ \
+ || (defined __STDC_VERSION__ && 201710 < __STDC_VERSION__)))
# define CHAR_WIDTH _GL_INTEGER_WIDTH (CHAR_MIN, CHAR_MAX)
# define SCHAR_WIDTH _GL_INTEGER_WIDTH (SCHAR_MIN, SCHAR_MAX)
# define UCHAR_WIDTH _GL_INTEGER_WIDTH (0, UCHAR_MAX)
@@ -68,7 +115,17 @@
# define ULONG_WIDTH _GL_INTEGER_WIDTH (0, ULONG_MAX)
# define LLONG_WIDTH _GL_INTEGER_WIDTH (LLONG_MIN, LLONG_MAX)
# define ULLONG_WIDTH _GL_INTEGER_WIDTH (0, ULLONG_MAX)
-#endif /* !ULLONG_WIDTH && (_GNU_SOURCE || __STDC_WANT_IEC_60559_BFP_EXT__) */
+#endif
+
+/* Macros specified by C2x. */
+
+#if (! defined BOOL_WIDTH \
+ && (defined _GNU_SOURCE \
+ || (defined __STDC_VERSION__ && 201710 < __STDC_VERSION__)))
+# define BOOL_MAX 1
+# define BOOL_WIDTH 1
+#endif
#endif /* _@GUARD_PREFIX@_LIMITS_H */
#endif /* _@GUARD_PREFIX@_LIMITS_H */
+#endif
diff --git a/lib/localtime-buffer.c b/lib/localtime-buffer.c
deleted file mode 100644
index c96c577ac1f..00000000000
--- a/lib/localtime-buffer.c
+++ /dev/null
@@ -1,58 +0,0 @@
-/* Provide access to the last buffer returned by localtime() or gmtime().
-
- Copyright (C) 2001-2003, 2005-2007, 2009-2017 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 Jim Meyering */
-
-#include <config.h>
-
-/* Specification. */
-#include "localtime-buffer.h"
-
-#if GETTIMEOFDAY_CLOBBERS_LOCALTIME || TZSET_CLOBBERS_LOCALTIME
-
-static struct tm tm_zero_buffer;
-struct tm *localtime_buffer_addr = &tm_zero_buffer;
-
-/* This is a wrapper for localtime.
-
- On the first call, record the address of the static buffer that
- localtime uses for its result. */
-
-struct tm *
-rpl_localtime (time_t const *timep)
-{
- struct tm *tm = localtime (timep);
-
- if (localtime_buffer_addr == &tm_zero_buffer)
- localtime_buffer_addr = tm;
-
- return tm;
-}
-
-/* Same as above, since gmtime and localtime use the same buffer. */
-struct tm *
-rpl_gmtime (time_t const *timep)
-{
- struct tm *tm = gmtime (timep);
-
- if (localtime_buffer_addr == &tm_zero_buffer)
- localtime_buffer_addr = tm;
-
- return tm;
-}
-
-#endif
diff --git a/lib/localtime-buffer.h b/lib/localtime-buffer.h
deleted file mode 100644
index 0a0389da073..00000000000
--- a/lib/localtime-buffer.h
+++ /dev/null
@@ -1,27 +0,0 @@
-/* Provide access to the last buffer returned by localtime() or gmtime().
-
- Copyright (C) 2001-2003, 2005-2007, 2009-2017 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 Jim Meyering */
-
-#include <time.h>
-
-#if GETTIMEOFDAY_CLOBBERS_LOCALTIME || TZSET_CLOBBERS_LOCALTIME
-
-/* The address of the last buffer returned by localtime() or gmtime(). */
-extern struct tm *localtime_buffer_addr;
-
-#endif
diff --git a/lib/lstat.c b/lib/lstat.c
index c721a4e641c..472bfbceb93 100644
--- a/lib/lstat.c
+++ b/lib/lstat.c
@@ -1,18 +1,18 @@
/* Work around a bug of lstat on some systems
- Copyright (C) 1997-2006, 2008-2017 Free Software Foundation, Inc.
+ Copyright (C) 1997-2006, 2008-2022 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 file is free software: you can redistribute it and/or modify
+ it under the terms of the GNU Lesser General Public License as
+ published by the Free Software Foundation; either version 2.1 of the
+ License, or (at your option) any later version.
- This program is distributed in the hope that it will be useful,
+ This file 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.
+ GNU Lesser General Public License for more details.
- You should have received a copy of the GNU General Public License
+ You should have received a copy of the GNU Lesser General Public License
along with this program. If not, see <https://www.gnu.org/licenses/>. */
/* written by Jim Meyering */
@@ -42,10 +42,16 @@ 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"
# include <string.h>
# include <errno.h>
@@ -66,32 +72,33 @@ orig_lstat (const char *filename, struct stat *buf)
int
rpl_lstat (const char *file, struct stat *sbuf)
{
- size_t len;
- int lstat_result = orig_lstat (file, sbuf);
-
- if (lstat_result != 0)
- return lstat_result;
+ int result = orig_lstat (file, sbuf);
/* This replacement file can blindly check against '/' rather than
using the ISSLASH macro, because all platforms with '\\' either
lack symlinks (mingw) or have working lstat (cygwin) and thus do
not compile this file. 0 len should have already been filtered
out above, with a failure return of ENOENT. */
- len = strlen (file);
- if (file[len - 1] != '/' || S_ISDIR (sbuf->st_mode))
- return 0;
-
- /* At this point, a trailing slash is only permitted on
- symlink-to-dir; but it should have found information on the
- directory, not the symlink. Call stat() to get info about the
- link's referent. Our replacement stat guarantees valid results,
- even if the symlink is not pointing to a directory. */
- if (!S_ISLNK (sbuf->st_mode))
+ if (result == 0)
{
- errno = ENOTDIR;
- return -1;
+ if (S_ISDIR (sbuf->st_mode) || file[strlen (file) - 1] != '/')
+ result = stat_time_normalize (result, sbuf);
+ else
+ {
+ /* At this point, a trailing slash is permitted only on
+ symlink-to-dir; but it should have found information on the
+ directory, not the symlink. Call 'stat' to get info about the
+ link's referent. Our replacement stat guarantees valid results,
+ even if the symlink is not pointing to a directory. */
+ if (!S_ISLNK (sbuf->st_mode))
+ {
+ errno = ENOTDIR;
+ return -1;
+ }
+ result = stat (file, sbuf);
+ }
}
- return stat (file, sbuf);
+ return result;
}
#endif /* HAVE_LSTAT */
diff --git a/lib/malloc.c b/lib/malloc.c
new file mode 100644
index 00000000000..f334dd6e96d
--- /dev/null
+++ b/lib/malloc.c
@@ -0,0 +1,51 @@
+/* malloc() function that is glibc compatible.
+
+ Copyright (C) 1997-1998, 2006-2007, 2009-2022 Free Software Foundation, Inc.
+
+ This file is free software: you can redistribute it and/or modify
+ it under the terms of the GNU Lesser General Public License as
+ published by the Free Software Foundation; either version 2.1 of the
+ License, or (at your option) any later version.
+
+ This file 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 Lesser General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public License
+ along with this program. If not, see <https://www.gnu.org/licenses/>. */
+
+/* written by Jim Meyering and Bruno Haible */
+
+#define _GL_USE_STDLIB_ALLOC 1
+#include <config.h>
+
+#include <stdlib.h>
+
+#include <errno.h>
+
+#include "xalloc-oversized.h"
+
+/* Allocate an N-byte block of memory from the heap, even if N is 0. */
+
+void *
+rpl_malloc (size_t n)
+{
+ if (n == 0)
+ n = 1;
+
+ if (xalloc_oversized (n, 1))
+ {
+ errno = ENOMEM;
+ return NULL;
+ }
+
+ void *result = malloc (n);
+
+#if !HAVE_MALLOC_POSIX
+ if (result == NULL)
+ errno = ENOMEM;
+#endif
+
+ return result;
+}
diff --git a/lib/malloc/dynarray-skeleton.c b/lib/malloc/dynarray-skeleton.c
new file mode 100644
index 00000000000..bad548a498c
--- /dev/null
+++ b/lib/malloc/dynarray-skeleton.c
@@ -0,0 +1,528 @@
+/* Type-safe arrays which grow dynamically.
+ Copyright (C) 2017-2022 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 Lesser General Public
+ License as published by the Free Software Foundation; either
+ version 2.1 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
+ Lesser General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public
+ License along with the GNU C Library; if not, see
+ <https://www.gnu.org/licenses/>. */
+
+/* Pre-processor macros which act as parameters:
+
+ DYNARRAY_STRUCT
+ The struct tag of dynamic array to be defined.
+ DYNARRAY_ELEMENT
+ The type name of the element type. Elements are copied
+ as if by memcpy, and can change address as the dynamic
+ array grows.
+ DYNARRAY_PREFIX
+ The prefix of the functions which are defined.
+
+ The following parameters are optional:
+
+ DYNARRAY_ELEMENT_FREE
+ DYNARRAY_ELEMENT_FREE (E) is evaluated to deallocate the
+ contents of elements. E is of type DYNARRAY_ELEMENT *.
+ DYNARRAY_ELEMENT_INIT
+ DYNARRAY_ELEMENT_INIT (E) is evaluated to initialize a new
+ element. E is of type DYNARRAY_ELEMENT *.
+ If DYNARRAY_ELEMENT_FREE but not DYNARRAY_ELEMENT_INIT is
+ defined, new elements are automatically zero-initialized.
+ Otherwise, new elements have undefined contents.
+ DYNARRAY_INITIAL_SIZE
+ The size of the statically allocated array (default:
+ at least 2, more elements if they fit into 128 bytes).
+ Must be a preprocessor constant. If DYNARRAY_INITIAL_SIZE is 0,
+ there is no statically allocated array at, and all non-empty
+ arrays are heap-allocated.
+ DYNARRAY_FINAL_TYPE
+ The name of the type which holds the final array. If not
+ defined, is PREFIX##finalize not provided. DYNARRAY_FINAL_TYPE
+ must be a struct type, with members of type DYNARRAY_ELEMENT and
+ size_t at the start (in this order).
+
+ These macros are undefined after this header file has been
+ included.
+
+ The following types are provided (their members are private to the
+ dynarray implementation):
+
+ struct DYNARRAY_STRUCT
+
+ The following functions are provided:
+
+ void DYNARRAY_PREFIX##init (struct DYNARRAY_STRUCT *);
+ void DYNARRAY_PREFIX##free (struct DYNARRAY_STRUCT *);
+ bool DYNARRAY_PREFIX##has_failed (const struct DYNARRAY_STRUCT *);
+ void DYNARRAY_PREFIX##mark_failed (struct DYNARRAY_STRUCT *);
+ size_t DYNARRAY_PREFIX##size (const struct DYNARRAY_STRUCT *);
+ DYNARRAY_ELEMENT *DYNARRAY_PREFIX##begin (const struct DYNARRAY_STRUCT *);
+ DYNARRAY_ELEMENT *DYNARRAY_PREFIX##end (const struct DYNARRAY_STRUCT *);
+ DYNARRAY_ELEMENT *DYNARRAY_PREFIX##at (struct DYNARRAY_STRUCT *, size_t);
+ void DYNARRAY_PREFIX##add (struct DYNARRAY_STRUCT *, DYNARRAY_ELEMENT);
+ DYNARRAY_ELEMENT *DYNARRAY_PREFIX##emplace (struct DYNARRAY_STRUCT *);
+ bool DYNARRAY_PREFIX##resize (struct DYNARRAY_STRUCT *, size_t);
+ void DYNARRAY_PREFIX##remove_last (struct DYNARRAY_STRUCT *);
+ void DYNARRAY_PREFIX##clear (struct DYNARRAY_STRUCT *);
+
+ The following functions are provided are provided if the
+ prerequisites are met:
+
+ bool DYNARRAY_PREFIX##finalize (struct DYNARRAY_STRUCT *,
+ DYNARRAY_FINAL_TYPE *);
+ (if DYNARRAY_FINAL_TYPE is defined)
+ DYNARRAY_ELEMENT *DYNARRAY_PREFIX##finalize (struct DYNARRAY_STRUCT *,
+ size_t *);
+ (if DYNARRAY_FINAL_TYPE is not defined)
+*/
+
+#include <malloc/dynarray.h>
+
+#include <errno.h>
+#include <stdlib.h>
+#include <string.h>
+
+#ifndef DYNARRAY_STRUCT
+# error "DYNARRAY_STRUCT must be defined"
+#endif
+
+#ifndef DYNARRAY_ELEMENT
+# error "DYNARRAY_ELEMENT must be defined"
+#endif
+
+#ifndef DYNARRAY_PREFIX
+# error "DYNARRAY_PREFIX must be defined"
+#endif
+
+#ifdef DYNARRAY_INITIAL_SIZE
+# if DYNARRAY_INITIAL_SIZE < 0
+# error "DYNARRAY_INITIAL_SIZE must be non-negative"
+# endif
+# if DYNARRAY_INITIAL_SIZE > 0
+# define DYNARRAY_HAVE_SCRATCH 1
+# else
+# define DYNARRAY_HAVE_SCRATCH 0
+# endif
+#else
+/* Provide a reasonable default which limits the size of
+ DYNARRAY_STRUCT. */
+# define DYNARRAY_INITIAL_SIZE \
+ (sizeof (DYNARRAY_ELEMENT) > 64 ? 2 : 128 / sizeof (DYNARRAY_ELEMENT))
+# define DYNARRAY_HAVE_SCRATCH 1
+#endif
+
+/* Public type definitions. */
+
+/* All fields of this struct are private to the implementation. */
+struct DYNARRAY_STRUCT
+{
+ union
+ {
+ struct dynarray_header dynarray_abstract;
+ struct
+ {
+ /* These fields must match struct dynarray_header. */
+ size_t used;
+ size_t allocated;
+ DYNARRAY_ELEMENT *array;
+ } dynarray_header;
+ } u;
+
+#if DYNARRAY_HAVE_SCRATCH
+ /* Initial inline allocation. */
+ DYNARRAY_ELEMENT scratch[DYNARRAY_INITIAL_SIZE];
+#endif
+};
+
+/* Internal use only: Helper macros. */
+
+/* Ensure macro-expansion of DYNARRAY_PREFIX. */
+#define DYNARRAY_CONCAT0(prefix, name) prefix##name
+#define DYNARRAY_CONCAT1(prefix, name) DYNARRAY_CONCAT0(prefix, name)
+#define DYNARRAY_NAME(name) DYNARRAY_CONCAT1(DYNARRAY_PREFIX, name)
+
+/* Use DYNARRAY_FREE instead of DYNARRAY_NAME (free),
+ so that Gnulib does not change 'free' to 'rpl_free'. */
+#define DYNARRAY_FREE DYNARRAY_CONCAT1 (DYNARRAY_NAME (f), ree)
+
+/* Address of the scratch buffer if any. */
+#if DYNARRAY_HAVE_SCRATCH
+# define DYNARRAY_SCRATCH(list) (list)->scratch
+#else
+# define DYNARRAY_SCRATCH(list) NULL
+#endif
+
+/* Internal use only: Helper functions. */
+
+/* Internal function. Call DYNARRAY_ELEMENT_FREE with the array
+ elements. Name mangling needed due to the DYNARRAY_ELEMENT_FREE
+ macro expansion. */
+static inline void
+DYNARRAY_NAME (free__elements__) (DYNARRAY_ELEMENT *__dynarray_array,
+ size_t __dynarray_used)
+{
+#ifdef DYNARRAY_ELEMENT_FREE
+ for (size_t __dynarray_i = 0; __dynarray_i < __dynarray_used; ++__dynarray_i)
+ DYNARRAY_ELEMENT_FREE (&__dynarray_array[__dynarray_i]);
+#endif /* DYNARRAY_ELEMENT_FREE */
+}
+
+/* Internal function. Free the non-scratch array allocation. */
+static inline void
+DYNARRAY_NAME (free__array__) (struct DYNARRAY_STRUCT *list)
+{
+#if DYNARRAY_HAVE_SCRATCH
+ if (list->u.dynarray_header.array != list->scratch)
+ free (list->u.dynarray_header.array);
+#else
+ free (list->u.dynarray_header.array);
+#endif
+}
+
+/* Public functions. */
+
+/* Initialize a dynamic array object. This must be called before any
+ use of the object. */
+__attribute_nonnull__ ((1))
+static void
+DYNARRAY_NAME (init) (struct DYNARRAY_STRUCT *list)
+{
+ list->u.dynarray_header.used = 0;
+ list->u.dynarray_header.allocated = DYNARRAY_INITIAL_SIZE;
+ list->u.dynarray_header.array = DYNARRAY_SCRATCH (list);
+}
+
+/* Deallocate the dynamic array and its elements. */
+__attribute_maybe_unused__ __attribute_nonnull__ ((1))
+static void
+DYNARRAY_FREE (struct DYNARRAY_STRUCT *list)
+{
+ DYNARRAY_NAME (free__elements__)
+ (list->u.dynarray_header.array, list->u.dynarray_header.used);
+ DYNARRAY_NAME (free__array__) (list);
+ DYNARRAY_NAME (init) (list);
+}
+
+/* Return true if the dynamic array is in an error state. */
+__attribute_nonnull__ ((1))
+static inline bool
+DYNARRAY_NAME (has_failed) (const struct DYNARRAY_STRUCT *list)
+{
+ return list->u.dynarray_header.allocated == __dynarray_error_marker ();
+}
+
+/* Mark the dynamic array as failed. All elements are deallocated as
+ a side effect. */
+__attribute_nonnull__ ((1))
+static void
+DYNARRAY_NAME (mark_failed) (struct DYNARRAY_STRUCT *list)
+{
+ DYNARRAY_NAME (free__elements__)
+ (list->u.dynarray_header.array, list->u.dynarray_header.used);
+ DYNARRAY_NAME (free__array__) (list);
+ list->u.dynarray_header.array = DYNARRAY_SCRATCH (list);
+ list->u.dynarray_header.used = 0;
+ list->u.dynarray_header.allocated = __dynarray_error_marker ();
+}
+
+/* Return the number of elements which have been added to the dynamic
+ array. */
+__attribute_nonnull__ ((1))
+static inline size_t
+DYNARRAY_NAME (size) (const struct DYNARRAY_STRUCT *list)
+{
+ return list->u.dynarray_header.used;
+}
+
+/* Return a pointer to the array element at INDEX. Terminate the
+ process if INDEX is out of bounds. */
+__attribute_nonnull__ ((1))
+static inline DYNARRAY_ELEMENT *
+DYNARRAY_NAME (at) (struct DYNARRAY_STRUCT *list, size_t index)
+{
+ if (__glibc_unlikely (index >= DYNARRAY_NAME (size) (list)))
+ __libc_dynarray_at_failure (DYNARRAY_NAME (size) (list), index);
+ return list->u.dynarray_header.array + index;
+}
+
+/* Return a pointer to the first array element, if any. For a
+ zero-length array, the pointer can be NULL even though the dynamic
+ array has not entered the failure state. */
+__attribute_nonnull__ ((1))
+static inline DYNARRAY_ELEMENT *
+DYNARRAY_NAME (begin) (struct DYNARRAY_STRUCT *list)
+{
+ return list->u.dynarray_header.array;
+}
+
+/* Return a pointer one element past the last array element. For a
+ zero-length array, the pointer can be NULL even though the dynamic
+ array has not entered the failure state. */
+__attribute_nonnull__ ((1))
+static inline DYNARRAY_ELEMENT *
+DYNARRAY_NAME (end) (struct DYNARRAY_STRUCT *list)
+{
+ return list->u.dynarray_header.array + list->u.dynarray_header.used;
+}
+
+/* Internal function. Slow path for the add function below. */
+static void
+DYNARRAY_NAME (add__) (struct DYNARRAY_STRUCT *list, DYNARRAY_ELEMENT item)
+{
+ if (__glibc_unlikely
+ (!__libc_dynarray_emplace_enlarge (&list->u.dynarray_abstract,
+ DYNARRAY_SCRATCH (list),
+ sizeof (DYNARRAY_ELEMENT))))
+ {
+ DYNARRAY_NAME (mark_failed) (list);
+ return;
+ }
+
+ /* Copy the new element and increase the array length. */
+ list->u.dynarray_header.array[list->u.dynarray_header.used++] = item;
+}
+
+/* Add ITEM at the end of the array, enlarging it by one element.
+ Mark *LIST as failed if the dynamic array allocation size cannot be
+ increased. */
+__attribute_nonnull__ ((1))
+static inline void
+DYNARRAY_NAME (add) (struct DYNARRAY_STRUCT *list, DYNARRAY_ELEMENT item)
+{
+ /* Do nothing in case of previous error. */
+ if (DYNARRAY_NAME (has_failed) (list))
+ return;
+
+ /* Enlarge the array if necessary. */
+ if (__glibc_unlikely (list->u.dynarray_header.used
+ == list->u.dynarray_header.allocated))
+ {
+ DYNARRAY_NAME (add__) (list, item);
+ return;
+ }
+
+ /* Copy the new element and increase the array length. */
+ list->u.dynarray_header.array[list->u.dynarray_header.used++] = item;
+}
+
+/* Internal function. Building block for the emplace functions below.
+ Assumes space for one more element in *LIST. */
+static inline DYNARRAY_ELEMENT *
+DYNARRAY_NAME (emplace__tail__) (struct DYNARRAY_STRUCT *list)
+{
+ DYNARRAY_ELEMENT *result
+ = &list->u.dynarray_header.array[list->u.dynarray_header.used];
+ ++list->u.dynarray_header.used;
+#if defined (DYNARRAY_ELEMENT_INIT)
+ DYNARRAY_ELEMENT_INIT (result);
+#elif defined (DYNARRAY_ELEMENT_FREE)
+ memset (result, 0, sizeof (*result));
+#endif
+ return result;
+}
+
+/* Internal function. Slow path for the emplace function below. */
+static DYNARRAY_ELEMENT *
+DYNARRAY_NAME (emplace__) (struct DYNARRAY_STRUCT *list)
+{
+ if (__glibc_unlikely
+ (!__libc_dynarray_emplace_enlarge (&list->u.dynarray_abstract,
+ DYNARRAY_SCRATCH (list),
+ sizeof (DYNARRAY_ELEMENT))))
+ {
+ DYNARRAY_NAME (mark_failed) (list);
+ return NULL;
+ }
+ return DYNARRAY_NAME (emplace__tail__) (list);
+}
+
+/* Allocate a place for a new element in *LIST and return a pointer to
+ it. The pointer can be NULL if the dynamic array cannot be
+ enlarged due to a memory allocation failure. */
+__attribute_maybe_unused__ __attribute_warn_unused_result__
+__attribute_nonnull__ ((1))
+static
+/* Avoid inlining with the larger initialization code. */
+#if !(defined (DYNARRAY_ELEMENT_INIT) || defined (DYNARRAY_ELEMENT_FREE))
+inline
+#endif
+DYNARRAY_ELEMENT *
+DYNARRAY_NAME (emplace) (struct DYNARRAY_STRUCT *list)
+{
+ /* Do nothing in case of previous error. */
+ if (DYNARRAY_NAME (has_failed) (list))
+ return NULL;
+
+ /* Enlarge the array if necessary. */
+ if (__glibc_unlikely (list->u.dynarray_header.used
+ == list->u.dynarray_header.allocated))
+ return (DYNARRAY_NAME (emplace__) (list));
+ return DYNARRAY_NAME (emplace__tail__) (list);
+}
+
+/* Change the size of *LIST to SIZE. If SIZE is larger than the
+ existing size, new elements are added (which can be initialized).
+ Otherwise, the list is truncated, and elements are freed. Return
+ false on memory allocation failure (and mark *LIST as failed). */
+__attribute_maybe_unused__ __attribute_nonnull__ ((1))
+static bool
+DYNARRAY_NAME (resize) (struct DYNARRAY_STRUCT *list, size_t size)
+{
+ if (size > list->u.dynarray_header.used)
+ {
+ bool ok;
+#if defined (DYNARRAY_ELEMENT_INIT)
+ /* The new elements have to be initialized. */
+ size_t old_size = list->u.dynarray_header.used;
+ ok = __libc_dynarray_resize (&list->u.dynarray_abstract,
+ size, DYNARRAY_SCRATCH (list),
+ sizeof (DYNARRAY_ELEMENT));
+ if (ok)
+ for (size_t i = old_size; i < size; ++i)
+ {
+ DYNARRAY_ELEMENT_INIT (&list->u.dynarray_header.array[i]);
+ }
+#elif defined (DYNARRAY_ELEMENT_FREE)
+ /* Zero initialization is needed so that the elements can be
+ safely freed. */
+ ok = __libc_dynarray_resize_clear
+ (&list->u.dynarray_abstract, size,
+ DYNARRAY_SCRATCH (list), sizeof (DYNARRAY_ELEMENT));
+#else
+ ok = __libc_dynarray_resize (&list->u.dynarray_abstract,
+ size, DYNARRAY_SCRATCH (list),
+ sizeof (DYNARRAY_ELEMENT));
+#endif
+ if (__glibc_unlikely (!ok))
+ DYNARRAY_NAME (mark_failed) (list);
+ return ok;
+ }
+ else
+ {
+ /* The list has shrunk in size. Free the removed elements. */
+ DYNARRAY_NAME (free__elements__)
+ (list->u.dynarray_header.array + size,
+ list->u.dynarray_header.used - size);
+ list->u.dynarray_header.used = size;
+ return true;
+ }
+}
+
+/* Remove the last element of LIST if it is present. */
+__attribute_maybe_unused__ __attribute_nonnull__ ((1))
+static void
+DYNARRAY_NAME (remove_last) (struct DYNARRAY_STRUCT *list)
+{
+ /* used > 0 implies that the array is the non-failed state. */
+ if (list->u.dynarray_header.used > 0)
+ {
+ size_t new_length = list->u.dynarray_header.used - 1;
+#ifdef DYNARRAY_ELEMENT_FREE
+ DYNARRAY_ELEMENT_FREE (&list->u.dynarray_header.array[new_length]);
+#endif
+ list->u.dynarray_header.used = new_length;
+ }
+}
+
+/* Remove all elements from the list. The elements are freed, but the
+ list itself is not. */
+__attribute_maybe_unused__ __attribute_nonnull__ ((1))
+static void
+DYNARRAY_NAME (clear) (struct DYNARRAY_STRUCT *list)
+{
+ /* free__elements__ does nothing if the list is in the failed
+ state. */
+ DYNARRAY_NAME (free__elements__)
+ (list->u.dynarray_header.array, list->u.dynarray_header.used);
+ list->u.dynarray_header.used = 0;
+}
+
+#ifdef DYNARRAY_FINAL_TYPE
+/* Transfer the dynamic array to a permanent location at *RESULT.
+ Returns true on success on false on allocation failure. In either
+ case, *LIST is re-initialized and can be reused. A NULL pointer is
+ stored in *RESULT if LIST refers to an empty list. On success, the
+ pointer in *RESULT is heap-allocated and must be deallocated using
+ free. */
+__attribute_maybe_unused__ __attribute_warn_unused_result__
+__attribute_nonnull__ ((1, 2))
+static bool
+DYNARRAY_NAME (finalize) (struct DYNARRAY_STRUCT *list,
+ DYNARRAY_FINAL_TYPE *result)
+{
+ struct dynarray_finalize_result res;
+ if (__libc_dynarray_finalize (&list->u.dynarray_abstract,
+ DYNARRAY_SCRATCH (list),
+ sizeof (DYNARRAY_ELEMENT), &res))
+ {
+ /* On success, the result owns all the data. */
+ DYNARRAY_NAME (init) (list);
+ *result = (DYNARRAY_FINAL_TYPE) { res.array, res.length };
+ return true;
+ }
+ else
+ {
+ /* On error, we need to free all data. */
+ DYNARRAY_FREE (list);
+ errno = ENOMEM;
+ return false;
+ }
+}
+#else /* !DYNARRAY_FINAL_TYPE */
+/* Transfer the dynamic array to a heap-allocated array and return a
+ pointer to it. The pointer is NULL if memory allocation fails, or
+ if the array is empty, so this function should be used only for
+ arrays which are known not be empty (usually because they always
+ have a sentinel at the end). If LENGTHP is not NULL, the array
+ length is written to *LENGTHP. *LIST is re-initialized and can be
+ reused. */
+__attribute_maybe_unused__ __attribute_warn_unused_result__
+__attribute_nonnull__ ((1))
+static DYNARRAY_ELEMENT *
+DYNARRAY_NAME (finalize) (struct DYNARRAY_STRUCT *list, size_t *lengthp)
+{
+ struct dynarray_finalize_result res;
+ if (__libc_dynarray_finalize (&list->u.dynarray_abstract,
+ DYNARRAY_SCRATCH (list),
+ sizeof (DYNARRAY_ELEMENT), &res))
+ {
+ /* On success, the result owns all the data. */
+ DYNARRAY_NAME (init) (list);
+ if (lengthp != NULL)
+ *lengthp = res.length;
+ return res.array;
+ }
+ else
+ {
+ /* On error, we need to free all data. */
+ DYNARRAY_FREE (list);
+ errno = ENOMEM;
+ return NULL;
+ }
+}
+#endif /* !DYNARRAY_FINAL_TYPE */
+
+/* Undo macro definitions. */
+
+#undef DYNARRAY_CONCAT0
+#undef DYNARRAY_CONCAT1
+#undef DYNARRAY_NAME
+#undef DYNARRAY_SCRATCH
+#undef DYNARRAY_HAVE_SCRATCH
+
+#undef DYNARRAY_STRUCT
+#undef DYNARRAY_ELEMENT
+#undef DYNARRAY_PREFIX
+#undef DYNARRAY_ELEMENT_FREE
+#undef DYNARRAY_ELEMENT_INIT
+#undef DYNARRAY_INITIAL_SIZE
+#undef DYNARRAY_FINAL_TYPE
diff --git a/lib/malloc/dynarray.h b/lib/malloc/dynarray.h
new file mode 100644
index 00000000000..f16fd950df6
--- /dev/null
+++ b/lib/malloc/dynarray.h
@@ -0,0 +1,178 @@
+/* Type-safe arrays which grow dynamically. Shared definitions.
+ Copyright (C) 2017-2022 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 Lesser General Public
+ License as published by the Free Software Foundation; either
+ version 2.1 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
+ Lesser General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public
+ License along with the GNU C Library; if not, see
+ <https://www.gnu.org/licenses/>. */
+
+/* To use the dynarray facility, you need to include
+ <malloc/dynarray-skeleton.c> and define the parameter macros
+ documented in that file.
+
+ A minimal example which provides a growing list of integers can be
+ defined like this:
+
+ struct int_array
+ {
+ // Pointer to result array followed by its length,
+ // as required by DYNARRAY_FINAL_TYPE.
+ int *array;
+ size_t length;
+ };
+
+ #define DYNARRAY_STRUCT dynarray_int
+ #define DYNARRAY_ELEMENT int
+ #define DYNARRAY_PREFIX dynarray_int_
+ #define DYNARRAY_FINAL_TYPE struct int_array
+ #include <malloc/dynarray-skeleton.c>
+
+ To create a three-element array with elements 1, 2, 3, use this
+ code:
+
+ struct dynarray_int dyn;
+ dynarray_int_init (&dyn);
+ for (int i = 1; i <= 3; ++i)
+ {
+ int *place = dynarray_int_emplace (&dyn);
+ assert (place != NULL);
+ *place = i;
+ }
+ struct int_array result;
+ bool ok = dynarray_int_finalize (&dyn, &result);
+ assert (ok);
+ assert (result.length == 3);
+ assert (result.array[0] == 1);
+ assert (result.array[1] == 2);
+ assert (result.array[2] == 3);
+ free (result.array);
+
+ If the elements contain resources which must be freed, define
+ DYNARRAY_ELEMENT_FREE appropriately, like this:
+
+ struct str_array
+ {
+ char **array;
+ size_t length;
+ };
+
+ #define DYNARRAY_STRUCT dynarray_str
+ #define DYNARRAY_ELEMENT char *
+ #define DYNARRAY_ELEMENT_FREE(ptr) free (*ptr)
+ #define DYNARRAY_PREFIX dynarray_str_
+ #define DYNARRAY_FINAL_TYPE struct str_array
+ #include <malloc/dynarray-skeleton.c>
+
+ Compared to scratch buffers, dynamic arrays have the following
+ features:
+
+ - They have an element type, and are not just an untyped buffer of
+ bytes.
+
+ - When growing, previously stored elements are preserved. (It is
+ expected that scratch_buffer_grow_preserve and
+ scratch_buffer_set_array_size eventually go away because all
+ current users are moved to dynamic arrays.)
+
+ - Scratch buffers have a more aggressive growth policy because
+ growing them typically means a retry of an operation (across an
+ NSS service module boundary), which is expensive.
+
+ - For the same reason, scratch buffers have a much larger initial
+ stack allocation. */
+
+#ifndef _DYNARRAY_H
+#define _DYNARRAY_H
+
+#include <stdbool.h>
+#include <stddef.h>
+#include <string.h>
+
+struct dynarray_header
+{
+ size_t used;
+ size_t allocated;
+ void *array;
+};
+
+/* Marker used in the allocated member to indicate that an error was
+ encountered. */
+static inline size_t
+__dynarray_error_marker (void)
+{
+ return -1;
+}
+
+/* Internal function. See the has_failed function in
+ dynarray-skeleton.c. */
+static inline bool
+__dynarray_error (struct dynarray_header *list)
+{
+ return list->allocated == __dynarray_error_marker ();
+}
+
+/* Internal function. Enlarge the dynamically allocated area of the
+ array to make room for one more element. SCRATCH is a pointer to
+ the scratch area (which is not heap-allocated and must not be
+ freed). ELEMENT_SIZE is the size, in bytes, of one element.
+ Return false on failure, true on success. */
+bool __libc_dynarray_emplace_enlarge (struct dynarray_header *,
+ void *scratch, size_t element_size);
+
+/* Internal function. Enlarge the dynamically allocated area of the
+ array to make room for at least SIZE elements (which must be larger
+ than the existing used part of the dynamic array). SCRATCH is a
+ pointer to the scratch area (which is not heap-allocated and must
+ not be freed). ELEMENT_SIZE is the size, in bytes, of one element.
+ Return false on failure, true on success. */
+bool __libc_dynarray_resize (struct dynarray_header *, size_t size,
+ void *scratch, size_t element_size);
+
+/* Internal function. Like __libc_dynarray_resize, but clear the new
+ part of the dynamic array. */
+bool __libc_dynarray_resize_clear (struct dynarray_header *, size_t size,
+ void *scratch, size_t element_size);
+
+/* Internal type. */
+struct dynarray_finalize_result
+{
+ void *array;
+ size_t length;
+};
+
+/* Internal function. Copy the dynamically-allocated area to an
+ explicitly-sized heap allocation. SCRATCH is a pointer to the
+ embedded scratch space. ELEMENT_SIZE is the size, in bytes, of the
+ element type. On success, true is returned, and pointer and length
+ are written to *RESULT. On failure, false is returned. The caller
+ has to take care of some of the memory management; this function is
+ expected to be called from dynarray-skeleton.c. */
+bool __libc_dynarray_finalize (struct dynarray_header *list, void *scratch,
+ size_t element_size,
+ struct dynarray_finalize_result *result);
+
+
+/* Internal function. Terminate the process after an index error.
+ SIZE is the number of elements of the dynamic array. INDEX is the
+ lookup index which triggered the failure. */
+_Noreturn void __libc_dynarray_at_failure (size_t size, size_t index);
+
+#ifndef _ISOMAC
+libc_hidden_proto (__libc_dynarray_emplace_enlarge)
+libc_hidden_proto (__libc_dynarray_resize)
+libc_hidden_proto (__libc_dynarray_resize_clear)
+libc_hidden_proto (__libc_dynarray_finalize)
+libc_hidden_proto (__libc_dynarray_at_failure)
+#endif
+
+#endif /* _DYNARRAY_H */
diff --git a/lib/malloc/dynarray_at_failure.c b/lib/malloc/dynarray_at_failure.c
new file mode 100644
index 00000000000..062ab7062bd
--- /dev/null
+++ b/lib/malloc/dynarray_at_failure.c
@@ -0,0 +1,40 @@
+/* Report an dynamic array index out of bounds condition.
+ Copyright (C) 2017-2022 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 Lesser General Public
+ License as published by the Free Software Foundation; either
+ version 2.1 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
+ Lesser General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public
+ License along with the GNU C Library; if not, see
+ <https://www.gnu.org/licenses/>. */
+
+#ifndef _LIBC
+# include <libc-config.h>
+# include <stdlib.h>
+#endif
+
+#include <dynarray.h>
+#include <stdio.h>
+
+void
+__libc_dynarray_at_failure (size_t size, size_t index)
+{
+#ifdef _LIBC
+ char buf[200];
+ __snprintf (buf, sizeof (buf), "Fatal glibc error: "
+ "array index %zu not less than array length %zu\n",
+ index, size);
+ __libc_fatal (buf);
+#else
+ abort ();
+#endif
+}
+libc_hidden_def (__libc_dynarray_at_failure)
diff --git a/lib/malloc/dynarray_emplace_enlarge.c b/lib/malloc/dynarray_emplace_enlarge.c
new file mode 100644
index 00000000000..0cff2e7055a
--- /dev/null
+++ b/lib/malloc/dynarray_emplace_enlarge.c
@@ -0,0 +1,77 @@
+/* Increase the size of a dynamic array in preparation of an emplace operation.
+ Copyright (C) 2017-2022 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 Lesser General Public
+ License as published by the Free Software Foundation; either
+ version 2.1 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
+ Lesser General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public
+ License along with the GNU C Library; if not, see
+ <https://www.gnu.org/licenses/>. */
+
+#ifndef _LIBC
+# include <libc-config.h>
+#endif
+
+#include <dynarray.h>
+#include <errno.h>
+#include <intprops.h>
+#include <stdlib.h>
+#include <string.h>
+
+bool
+__libc_dynarray_emplace_enlarge (struct dynarray_header *list,
+ void *scratch, size_t element_size)
+{
+ size_t new_allocated;
+ if (list->allocated == 0)
+ {
+ /* No scratch buffer provided. Choose a reasonable default
+ size. */
+ if (element_size < 4)
+ new_allocated = 16;
+ else if (element_size < 8)
+ new_allocated = 8;
+ else
+ new_allocated = 4;
+ }
+ else
+ /* Increase the allocated size, using an exponential growth
+ policy. */
+ {
+ new_allocated = list->allocated + list->allocated / 2 + 1;
+ if (new_allocated <= list->allocated)
+ {
+ /* Overflow. */
+ __set_errno (ENOMEM);
+ return false;
+ }
+ }
+
+ size_t new_size;
+ if (INT_MULTIPLY_WRAPV (new_allocated, element_size, &new_size))
+ return false;
+ void *new_array;
+ if (list->array == scratch)
+ {
+ /* The previous array was not heap-allocated. */
+ new_array = malloc (new_size);
+ if (new_array != NULL && list->array != NULL)
+ memcpy (new_array, list->array, list->used * element_size);
+ }
+ else
+ new_array = realloc (list->array, new_size);
+ if (new_array == NULL)
+ return false;
+ list->array = new_array;
+ list->allocated = new_allocated;
+ return true;
+}
+libc_hidden_def (__libc_dynarray_emplace_enlarge)
diff --git a/lib/malloc/dynarray_finalize.c b/lib/malloc/dynarray_finalize.c
new file mode 100644
index 00000000000..3f360c3aa85
--- /dev/null
+++ b/lib/malloc/dynarray_finalize.c
@@ -0,0 +1,66 @@
+/* Copy the dynamically-allocated area to an explicitly-sized heap allocation.
+ Copyright (C) 2017-2022 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 Lesser General Public
+ License as published by the Free Software Foundation; either
+ version 2.1 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
+ Lesser General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public
+ License along with the GNU C Library; if not, see
+ <https://www.gnu.org/licenses/>. */
+
+#ifndef _LIBC
+# include <libc-config.h>
+#endif
+
+#include <dynarray.h>
+#include <stdlib.h>
+#include <string.h>
+
+bool
+__libc_dynarray_finalize (struct dynarray_header *list,
+ void *scratch, size_t element_size,
+ struct dynarray_finalize_result *result)
+{
+ if (__dynarray_error (list))
+ /* The caller will reported the deferred error. */
+ return false;
+
+ size_t used = list->used;
+
+ /* Empty list. */
+ if (used == 0)
+ {
+ /* An empty list could still be backed by a heap-allocated
+ array. Free it if necessary. */
+ if (list->array != scratch)
+ free (list->array);
+ *result = (struct dynarray_finalize_result) { NULL, 0 };
+ return true;
+ }
+
+ size_t allocation_size = used * element_size;
+ void *heap_array = malloc (allocation_size);
+ if (heap_array != NULL)
+ {
+ /* The new array takes ownership of the strings. */
+ if (list->array != NULL)
+ memcpy (heap_array, list->array, allocation_size);
+ if (list->array != scratch)
+ free (list->array);
+ *result = (struct dynarray_finalize_result)
+ { .array = heap_array, .length = used };
+ return true;
+ }
+ else
+ /* The caller will perform the freeing operation. */
+ return false;
+}
+libc_hidden_def (__libc_dynarray_finalize)
diff --git a/lib/malloc/dynarray_resize.c b/lib/malloc/dynarray_resize.c
new file mode 100644
index 00000000000..8d1922e5c7f
--- /dev/null
+++ b/lib/malloc/dynarray_resize.c
@@ -0,0 +1,68 @@
+/* Increase the size of a dynamic array.
+ Copyright (C) 2017-2022 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 Lesser General Public
+ License as published by the Free Software Foundation; either
+ version 2.1 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
+ Lesser General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public
+ License along with the GNU C Library; if not, see
+ <https://www.gnu.org/licenses/>. */
+
+#ifndef _LIBC
+# include <libc-config.h>
+#endif
+
+#include <dynarray.h>
+#include <errno.h>
+#include <intprops.h>
+#include <stdlib.h>
+#include <string.h>
+
+bool
+__libc_dynarray_resize (struct dynarray_header *list, size_t size,
+ void *scratch, size_t element_size)
+{
+ /* The existing allocation provides sufficient room. */
+ if (size <= list->allocated)
+ {
+ list->used = size;
+ return true;
+ }
+
+ /* Otherwise, use size as the new allocation size. The caller is
+ expected to provide the final size of the array, so there is no
+ over-allocation here. */
+
+ size_t new_size_bytes;
+ if (INT_MULTIPLY_WRAPV (size, element_size, &new_size_bytes))
+ {
+ /* Overflow. */
+ __set_errno (ENOMEM);
+ return false;
+ }
+ void *new_array;
+ if (list->array == scratch)
+ {
+ /* The previous array was not heap-allocated. */
+ new_array = malloc (new_size_bytes);
+ if (new_array != NULL && list->array != NULL)
+ memcpy (new_array, list->array, list->used * element_size);
+ }
+ else
+ new_array = realloc (list->array, new_size_bytes);
+ if (new_array == NULL)
+ return false;
+ list->array = new_array;
+ list->allocated = size;
+ list->used = size;
+ return true;
+}
+libc_hidden_def (__libc_dynarray_resize)
diff --git a/lib/malloc/dynarray_resize_clear.c b/lib/malloc/dynarray_resize_clear.c
new file mode 100644
index 00000000000..8cf1b0d0268
--- /dev/null
+++ b/lib/malloc/dynarray_resize_clear.c
@@ -0,0 +1,39 @@
+/* Increase the size of a dynamic array and clear the new part.
+ Copyright (C) 2017-2022 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 Lesser General Public
+ License as published by the Free Software Foundation; either
+ version 2.1 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
+ Lesser General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public
+ License along with the GNU C Library; if not, see
+ <https://www.gnu.org/licenses/>. */
+
+#ifndef _LIBC
+# include <libc-config.h>
+#endif
+
+#include <dynarray.h>
+#include <string.h>
+
+bool
+__libc_dynarray_resize_clear (struct dynarray_header *list, size_t size,
+ void *scratch, size_t element_size)
+{
+ size_t old_size = list->used;
+ if (!__libc_dynarray_resize (list, size, scratch, element_size))
+ return false;
+ /* __libc_dynarray_resize already checked for overflow. */
+ char *array = list->array;
+ memset (array + (old_size * element_size), 0,
+ (size - old_size) * element_size);
+ return true;
+}
+libc_hidden_def (__libc_dynarray_resize_clear)
diff --git a/lib/malloc/scratch_buffer.h b/lib/malloc/scratch_buffer.h
new file mode 100644
index 00000000000..e4c5c8a85da
--- /dev/null
+++ b/lib/malloc/scratch_buffer.h
@@ -0,0 +1,151 @@
+/* Variable-sized buffer with on-stack default allocation.
+ Copyright (C) 2015-2022 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 Lesser General Public
+ License as published by the Free Software Foundation; either
+ version 2.1 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
+ Lesser General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public
+ License along with the GNU C Library; if not, see
+ <https://www.gnu.org/licenses/>. */
+
+#ifndef _SCRATCH_BUFFER_H
+#define _SCRATCH_BUFFER_H
+
+/* Scratch buffers with a default stack allocation and fallback to
+ heap allocation. It is expected that this function is used in this
+ way:
+
+ struct scratch_buffer tmpbuf;
+ scratch_buffer_init (&tmpbuf);
+
+ while (!function_that_uses_buffer (tmpbuf.data, tmpbuf.length))
+ if (!scratch_buffer_grow (&tmpbuf))
+ return -1;
+
+ scratch_buffer_free (&tmpbuf);
+ return 0;
+
+ The allocation functions (scratch_buffer_grow,
+ scratch_buffer_grow_preserve, scratch_buffer_set_array_size) make
+ sure that the heap allocation, if any, is freed, so that the code
+ above does not have a memory leak. The buffer still remains in a
+ state that can be deallocated using scratch_buffer_free, so a loop
+ like this is valid as well:
+
+ struct scratch_buffer tmpbuf;
+ scratch_buffer_init (&tmpbuf);
+
+ while (!function_that_uses_buffer (tmpbuf.data, tmpbuf.length))
+ if (!scratch_buffer_grow (&tmpbuf))
+ break;
+
+ scratch_buffer_free (&tmpbuf);
+
+ scratch_buffer_grow and scratch_buffer_grow_preserve are guaranteed
+ to grow the buffer by at least 512 bytes. This means that when
+ using the scratch buffer as a backing store for a non-character
+ array whose element size, in bytes, is 512 or smaller, the scratch
+ buffer only has to grow once to make room for at least one more
+ element.
+*/
+
+#include <stdbool.h>
+#include <stddef.h>
+#include <stdlib.h>
+
+/* Scratch buffer. Must be initialized with scratch_buffer_init
+ before its use. */
+struct scratch_buffer {
+ void *data; /* Pointer to the beginning of the scratch area. */
+ size_t length; /* Allocated space at the data pointer, in bytes. */
+ union { max_align_t __align; char __c[1024]; } __space;
+};
+
+/* Initializes *BUFFER so that BUFFER->data points to BUFFER->__space
+ and BUFFER->length reflects the available space. */
+static inline void
+scratch_buffer_init (struct scratch_buffer *buffer)
+{
+ buffer->data = buffer->__space.__c;
+ buffer->length = sizeof (buffer->__space);
+}
+
+/* Deallocates *BUFFER (if it was heap-allocated). */
+static inline void
+scratch_buffer_free (struct scratch_buffer *buffer)
+{
+ if (buffer->data != buffer->__space.__c)
+ free (buffer->data);
+}
+
+/* Grow *BUFFER by some arbitrary amount. The buffer contents is NOT
+ preserved. Return true on success, false on allocation failure (in
+ which case the old buffer is freed). On success, the new buffer is
+ larger than the previous size. On failure, *BUFFER is deallocated,
+ but remains in a free-able state, and errno is set. */
+bool __libc_scratch_buffer_grow (struct scratch_buffer *buffer);
+libc_hidden_proto (__libc_scratch_buffer_grow)
+
+/* Alias for __libc_scratch_buffer_grow. */
+static __always_inline bool
+scratch_buffer_grow (struct scratch_buffer *buffer)
+{
+ return __glibc_likely (__libc_scratch_buffer_grow (buffer));
+}
+
+/* Like __libc_scratch_buffer_grow, but preserve the old buffer
+ contents on success, as a prefix of the new buffer. */
+bool __libc_scratch_buffer_grow_preserve (struct scratch_buffer *buffer);
+libc_hidden_proto (__libc_scratch_buffer_grow_preserve)
+
+/* Alias for __libc_scratch_buffer_grow_preserve. */
+static __always_inline bool
+scratch_buffer_grow_preserve (struct scratch_buffer *buffer)
+{
+ return __glibc_likely (__libc_scratch_buffer_grow_preserve (buffer));
+}
+
+/* Grow *BUFFER so that it can store at least NELEM elements of SIZE
+ bytes. The buffer contents are NOT preserved. Both NELEM and SIZE
+ can be zero. Return true on success, false on allocation failure
+ (in which case the old buffer is freed, but *BUFFER remains in a
+ free-able state, and errno is set). It is unspecified whether this
+ function can reduce the array size. */
+bool __libc_scratch_buffer_set_array_size (struct scratch_buffer *buffer,
+ size_t nelem, size_t size);
+libc_hidden_proto (__libc_scratch_buffer_set_array_size)
+
+/* Alias for __libc_scratch_set_array_size. */
+static __always_inline bool
+scratch_buffer_set_array_size (struct scratch_buffer *buffer,
+ size_t nelem, size_t size)
+{
+ return __glibc_likely (__libc_scratch_buffer_set_array_size
+ (buffer, nelem, size));
+}
+
+/* Return a copy of *BUFFER's first SIZE bytes as a heap-allocated block,
+ deallocating *BUFFER if it was heap-allocated. SIZE must be at
+ most *BUFFER's size. Return NULL (setting errno) on memory
+ exhaustion. */
+void *__libc_scratch_buffer_dupfree (struct scratch_buffer *buffer,
+ size_t size);
+libc_hidden_proto (__libc_scratch_buffer_dupfree)
+
+/* Alias for __libc_scratch_dupfree. */
+static __always_inline void *
+scratch_buffer_dupfree (struct scratch_buffer *buffer, size_t size)
+{
+ void *r = __libc_scratch_buffer_dupfree (buffer, size);
+ return __glibc_likely (r != NULL) ? r : NULL;
+}
+
+#endif /* _SCRATCH_BUFFER_H */
diff --git a/lib/malloc/scratch_buffer_dupfree.c b/lib/malloc/scratch_buffer_dupfree.c
new file mode 100644
index 00000000000..eb3b95c1b1c
--- /dev/null
+++ b/lib/malloc/scratch_buffer_dupfree.c
@@ -0,0 +1,41 @@
+/* Variable-sized buffer with on-stack default allocation.
+ Copyright (C) 2020-2022 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 Lesser General Public
+ License as published by the Free Software Foundation; either
+ version 2.1 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
+ Lesser General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public
+ License along with the GNU C Library; if not, see
+ <https://www.gnu.org/licenses/>. */
+
+#ifndef _LIBC
+# include <libc-config.h>
+#endif
+
+#include <scratch_buffer.h>
+#include <string.h>
+
+void *
+__libc_scratch_buffer_dupfree (struct scratch_buffer *buffer, size_t size)
+{
+ void *data = buffer->data;
+ if (data == buffer->__space.__c)
+ {
+ void *copy = malloc (size);
+ return copy != NULL ? memcpy (copy, data, size) : NULL;
+ }
+ else
+ {
+ void *copy = realloc (data, size);
+ return copy != NULL ? copy : data;
+ }
+}
+libc_hidden_def (__libc_scratch_buffer_dupfree)
diff --git a/lib/malloc/scratch_buffer_grow.c b/lib/malloc/scratch_buffer_grow.c
new file mode 100644
index 00000000000..9a5e4dbb1eb
--- /dev/null
+++ b/lib/malloc/scratch_buffer_grow.c
@@ -0,0 +1,56 @@
+/* Variable-sized buffer with on-stack default allocation.
+ Copyright (C) 2015-2022 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 Lesser General Public
+ License as published by the Free Software Foundation; either
+ version 2.1 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
+ Lesser General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public
+ License along with the GNU C Library; if not, see
+ <https://www.gnu.org/licenses/>. */
+
+#ifndef _LIBC
+# include <libc-config.h>
+#endif
+
+#include <scratch_buffer.h>
+#include <errno.h>
+
+bool
+__libc_scratch_buffer_grow (struct scratch_buffer *buffer)
+{
+ void *new_ptr;
+ size_t new_length = buffer->length * 2;
+
+ /* Discard old buffer. */
+ scratch_buffer_free (buffer);
+
+ /* Check for overflow. */
+ if (__glibc_likely (new_length >= buffer->length))
+ new_ptr = malloc (new_length);
+ else
+ {
+ __set_errno (ENOMEM);
+ new_ptr = NULL;
+ }
+
+ if (__glibc_unlikely (new_ptr == NULL))
+ {
+ /* Buffer must remain valid to free. */
+ scratch_buffer_init (buffer);
+ return false;
+ }
+
+ /* Install new heap-based buffer. */
+ buffer->data = new_ptr;
+ buffer->length = new_length;
+ return true;
+}
+libc_hidden_def (__libc_scratch_buffer_grow)
diff --git a/lib/malloc/scratch_buffer_grow_preserve.c b/lib/malloc/scratch_buffer_grow_preserve.c
new file mode 100644
index 00000000000..3fe5a0720ec
--- /dev/null
+++ b/lib/malloc/scratch_buffer_grow_preserve.c
@@ -0,0 +1,67 @@
+/* Variable-sized buffer with on-stack default allocation.
+ Copyright (C) 2015-2022 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 Lesser General Public
+ License as published by the Free Software Foundation; either
+ version 2.1 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
+ Lesser General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public
+ License along with the GNU C Library; if not, see
+ <https://www.gnu.org/licenses/>. */
+
+#ifndef _LIBC
+# include <libc-config.h>
+#endif
+
+#include <scratch_buffer.h>
+#include <errno.h>
+#include <string.h>
+
+bool
+__libc_scratch_buffer_grow_preserve (struct scratch_buffer *buffer)
+{
+ size_t new_length = 2 * buffer->length;
+ void *new_ptr;
+
+ if (buffer->data == buffer->__space.__c)
+ {
+ /* Move buffer to the heap. No overflow is possible because
+ buffer->length describes a small buffer on the stack. */
+ new_ptr = malloc (new_length);
+ if (new_ptr == NULL)
+ return false;
+ memcpy (new_ptr, buffer->__space.__c, buffer->length);
+ }
+ else
+ {
+ /* Buffer was already on the heap. Check for overflow. */
+ if (__glibc_likely (new_length >= buffer->length))
+ new_ptr = realloc (buffer->data, new_length);
+ else
+ {
+ __set_errno (ENOMEM);
+ new_ptr = NULL;
+ }
+
+ if (__glibc_unlikely (new_ptr == NULL))
+ {
+ /* Deallocate, but buffer must remain valid to free. */
+ free (buffer->data);
+ scratch_buffer_init (buffer);
+ return false;
+ }
+ }
+
+ /* Install new heap-based buffer. */
+ buffer->data = new_ptr;
+ buffer->length = new_length;
+ return true;
+}
+libc_hidden_def (__libc_scratch_buffer_grow_preserve)
diff --git a/lib/malloc/scratch_buffer_set_array_size.c b/lib/malloc/scratch_buffer_set_array_size.c
new file mode 100644
index 00000000000..89c37a950e9
--- /dev/null
+++ b/lib/malloc/scratch_buffer_set_array_size.c
@@ -0,0 +1,64 @@
+/* Variable-sized buffer with on-stack default allocation.
+ Copyright (C) 2015-2022 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 Lesser General Public
+ License as published by the Free Software Foundation; either
+ version 2.1 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
+ Lesser General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public
+ License along with the GNU C Library; if not, see
+ <https://www.gnu.org/licenses/>. */
+
+#ifndef _LIBC
+# include <libc-config.h>
+#endif
+
+#include <scratch_buffer.h>
+#include <errno.h>
+#include <limits.h>
+
+bool
+__libc_scratch_buffer_set_array_size (struct scratch_buffer *buffer,
+ size_t nelem, size_t size)
+{
+ size_t new_length = nelem * size;
+
+ /* Avoid overflow check if both values are small. */
+ if ((nelem | size) >> (sizeof (size_t) * CHAR_BIT / 2) != 0
+ && nelem != 0 && size != new_length / nelem)
+ {
+ /* Overflow. Discard the old buffer, but it must remain valid
+ to free. */
+ scratch_buffer_free (buffer);
+ scratch_buffer_init (buffer);
+ __set_errno (ENOMEM);
+ return false;
+ }
+
+ if (new_length <= buffer->length)
+ return true;
+
+ /* Discard old buffer. */
+ scratch_buffer_free (buffer);
+
+ char *new_ptr = malloc (new_length);
+ if (new_ptr == NULL)
+ {
+ /* Buffer must remain valid to free. */
+ scratch_buffer_init (buffer);
+ return false;
+ }
+
+ /* Install new heap-based buffer. */
+ buffer->data = new_ptr;
+ buffer->length = new_length;
+ return true;
+}
+libc_hidden_def (__libc_scratch_buffer_set_array_size)
diff --git a/lib/md5-stream.c b/lib/md5-stream.c
new file mode 100644
index 00000000000..07c639fd360
--- /dev/null
+++ b/lib/md5-stream.c
@@ -0,0 +1,141 @@
+/* Functions to compute MD5 message digest of files or memory blocks.
+ according to the definition of MD5 in RFC 1321 from April 1992.
+ Copyright (C) 1995-1997, 1999-2001, 2005-2006, 2008-2022 Free Software
+ Foundation, Inc.
+ This file is part of the GNU C Library.
+
+ This file is free software: you can redistribute it and/or modify
+ it under the terms of the GNU Lesser General Public License as
+ published by the Free Software Foundation; either version 2.1 of the
+ License, or (at your option) any later version.
+
+ This file 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 Lesser General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public License
+ along with this program. If not, see <https://www.gnu.org/licenses/>. */
+
+/* Written by Ulrich Drepper <drepper@gnu.ai.mit.edu>, 1995. */
+
+#include <config.h>
+
+/* Specification. */
+#if HAVE_OPENSSL_MD5
+# define GL_OPENSSL_INLINE _GL_EXTERN_INLINE
+#endif
+#include "md5.h"
+
+#include <stdlib.h>
+
+#if USE_UNLOCKED_IO
+# include "unlocked-io.h"
+#endif
+
+#include "af_alg.h"
+
+#ifdef _LIBC
+# include <endian.h>
+# if __BYTE_ORDER == __BIG_ENDIAN
+# define WORDS_BIGENDIAN 1
+# endif
+/* We need to keep the namespace clean so define the MD5 function
+ protected using leading __ . */
+# define md5_init_ctx __md5_init_ctx
+# define md5_process_block __md5_process_block
+# define md5_process_bytes __md5_process_bytes
+# define md5_finish_ctx __md5_finish_ctx
+# define md5_stream __md5_stream
+#endif
+
+#define BLOCKSIZE 32768
+#if BLOCKSIZE % 64 != 0
+# error "invalid BLOCKSIZE"
+#endif
+
+/* Compute MD5 message digest for bytes read from STREAM. The
+ resulting message digest number will be written into the 16 bytes
+ beginning at RESBLOCK. */
+int
+md5_stream (FILE *stream, void *resblock)
+{
+ switch (afalg_stream (stream, "md5", resblock, MD5_DIGEST_SIZE))
+ {
+ case 0: return 0;
+ case -EIO: return 1;
+ }
+
+ char *buffer = malloc (BLOCKSIZE + 72);
+ if (!buffer)
+ return 1;
+
+ struct md5_ctx ctx;
+ md5_init_ctx (&ctx);
+ size_t sum;
+
+ /* Iterate over full file contents. */
+ while (1)
+ {
+ /* We read the file in blocks of BLOCKSIZE bytes. One call of the
+ computation function processes the whole buffer so that with the
+ next round of the loop another block can be read. */
+ size_t n;
+ sum = 0;
+
+ /* Read block. Take care for partial reads. */
+ while (1)
+ {
+ /* Either process a partial fread() from this loop,
+ or the fread() in afalg_stream may have gotten EOF.
+ We need to avoid a subsequent fread() as EOF may
+ not be sticky. For details of such systems, see:
+ https://sourceware.org/bugzilla/show_bug.cgi?id=1190 */
+ if (feof (stream))
+ goto process_partial_block;
+
+ n = fread (buffer + sum, 1, BLOCKSIZE - sum, stream);
+
+ sum += n;
+
+ if (sum == BLOCKSIZE)
+ break;
+
+ if (n == 0)
+ {
+ /* Check for the error flag IFF N == 0, so that we don't
+ exit the loop after a partial read due to e.g., EAGAIN
+ or EWOULDBLOCK. */
+ if (ferror (stream))
+ {
+ free (buffer);
+ return 1;
+ }
+ goto process_partial_block;
+ }
+ }
+
+ /* Process buffer with BLOCKSIZE bytes. Note that
+ BLOCKSIZE % 64 == 0
+ */
+ md5_process_block (buffer, BLOCKSIZE, &ctx);
+ }
+
+process_partial_block:
+
+ /* Process any remaining bytes. */
+ if (sum > 0)
+ md5_process_bytes (buffer, sum, &ctx);
+
+ /* Construct result in desired memory. */
+ md5_finish_ctx (&ctx, resblock);
+ free (buffer);
+ return 0;
+}
+
+/*
+ * Hey Emacs!
+ * Local Variables:
+ * coding: utf-8
+ * End:
+ */
diff --git a/lib/md5.c b/lib/md5.c
index e16da5990f3..57489ed74c5 100644
--- a/lib/md5.c
+++ b/lib/md5.c
@@ -1,26 +1,27 @@
/* Functions to compute MD5 message digest of files or memory blocks.
according to the definition of MD5 in RFC 1321 from April 1992.
- Copyright (C) 1995-1997, 1999-2001, 2005-2006, 2008-2017 Free Software
+ Copyright (C) 1995-1997, 1999-2001, 2005-2006, 2008-2022 Free Software
Foundation, Inc.
This file is part of the GNU C Library.
- This program is free software; you can redistribute it and/or modify it
- under the terms of the GNU General Public License as published by the
- Free Software Foundation; either version 3, or (at your option) any
- later version.
+ This file is free software: you can redistribute it and/or modify
+ it under the terms of the GNU Lesser General Public License as
+ published by the Free Software Foundation; either version 2.1 of the
+ License, or (at your option) any later version.
- This program is distributed in the hope that it will be useful,
+ This file 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.
+ GNU Lesser General Public License for more details.
- You should have received a copy of the GNU General Public License
- along with this program; if not, see <https://www.gnu.org/licenses/>. */
+ You should have received a copy of the GNU Lesser General Public License
+ along with this program. If not, see <https://www.gnu.org/licenses/>. */
/* Written by Ulrich Drepper <drepper@gnu.ai.mit.edu>, 1995. */
#include <config.h>
+/* Specification. */
#if HAVE_OPENSSL_MD5
# define GL_OPENSSL_INLINE _GL_EXTERN_INLINE
#endif
@@ -28,14 +29,9 @@
#include <stdalign.h>
#include <stdint.h>
-#include <stdlib.h>
#include <string.h>
#include <sys/types.h>
-#if USE_UNLOCKED_IO
-# include "unlocked-io.h"
-#endif
-
#ifdef _LIBC
# include <endian.h>
# if __BYTE_ORDER == __BIG_ENDIAN
@@ -48,23 +44,18 @@
# define md5_process_bytes __md5_process_bytes
# define md5_finish_ctx __md5_finish_ctx
# define md5_read_ctx __md5_read_ctx
-# define md5_stream __md5_stream
# define md5_buffer __md5_buffer
#endif
+#include <byteswap.h>
#ifdef WORDS_BIGENDIAN
-# define SWAP(n) \
- (((n) << 24) | (((n) & 0xff00) << 8) | (((n) >> 8) & 0xff00) | ((n) >> 24))
+# define SWAP(n) bswap_32 (n)
#else
# define SWAP(n) (n)
#endif
-#define BLOCKSIZE 32768
-#if BLOCKSIZE % 64 != 0
-# error "invalid BLOCKSIZE"
-#endif
-
#if ! HAVE_OPENSSL_MD5
+
/* This array contains the bytes used to pad the buffer to the next
64-byte boundary. (RFC 1321, 3.1: Step 1) */
static const unsigned char fillbuf[64] = { 0x80, 0 /* , 0, 0, ... */ };
@@ -132,82 +123,7 @@ md5_finish_ctx (struct md5_ctx *ctx, void *resbuf)
return md5_read_ctx (ctx, resbuf);
}
-#endif
-
-/* Compute MD5 message digest for bytes read from STREAM. The
- resulting message digest number will be written into the 16 bytes
- beginning at RESBLOCK. */
-int
-md5_stream (FILE *stream, void *resblock)
-{
- struct md5_ctx ctx;
- size_t sum;
- char *buffer = malloc (BLOCKSIZE + 72);
- if (!buffer)
- return 1;
-
- /* Initialize the computation context. */
- md5_init_ctx (&ctx);
-
- /* Iterate over full file contents. */
- while (1)
- {
- /* We read the file in blocks of BLOCKSIZE bytes. One call of the
- computation function processes the whole buffer so that with the
- next round of the loop another block can be read. */
- size_t n;
- sum = 0;
-
- /* Read block. Take care for partial reads. */
- while (1)
- {
- n = fread (buffer + sum, 1, BLOCKSIZE - sum, stream);
-
- sum += n;
-
- if (sum == BLOCKSIZE)
- break;
-
- if (n == 0)
- {
- /* Check for the error flag IFF N == 0, so that we don't
- exit the loop after a partial read due to e.g., EAGAIN
- or EWOULDBLOCK. */
- if (ferror (stream))
- {
- free (buffer);
- return 1;
- }
- goto process_partial_block;
- }
-
- /* We've read at least one byte, so ignore errors. But always
- check for EOF, since feof may be true even though N > 0.
- Otherwise, we could end up calling fread after EOF. */
- if (feof (stream))
- goto process_partial_block;
- }
-
- /* Process buffer with BLOCKSIZE bytes. Note that
- BLOCKSIZE % 64 == 0
- */
- md5_process_block (buffer, BLOCKSIZE, &ctx);
- }
-
-process_partial_block:
-
- /* Process any remaining bytes. */
- if (sum > 0)
- md5_process_bytes (buffer, sum, &ctx);
-
- /* Construct result in desired memory. */
- md5_finish_ctx (&ctx, resblock);
- free (buffer);
- return 0;
-}
-
-#if ! HAVE_OPENSSL_MD5
/* Compute MD5 message digest for LEN bytes beginning at BUFFER. The
result is always in little endian byte order, so that a byte-wise
output yields to the wanted ASCII representation of the message
@@ -468,4 +384,12 @@ md5_process_block (const void *buffer, size_t len, struct md5_ctx *ctx)
ctx->C = C;
ctx->D = D;
}
+
#endif
+
+/*
+ * Hey Emacs!
+ * Local Variables:
+ * coding: utf-8
+ * End:
+ */
diff --git a/lib/md5.h b/lib/md5.h
index 8b94bfcf0e0..611c230b817 100644
--- a/lib/md5.h
+++ b/lib/md5.h
@@ -1,21 +1,21 @@
/* Declaration of functions and data types used for MD5 sum computing
library functions.
- Copyright (C) 1995-1997, 1999-2001, 2004-2006, 2008-2017 Free Software
+ Copyright (C) 1995-1997, 1999-2001, 2004-2006, 2008-2022 Free Software
Foundation, Inc.
This file is part of the GNU C Library.
- This program is free software; you can redistribute it and/or modify it
- under the terms of the GNU General Public License as published by the
- Free Software Foundation; either version 3, or (at your option) any
- later version.
+ This file is free software: you can redistribute it and/or modify
+ it under the terms of the GNU Lesser General Public License as
+ published by the Free Software Foundation; either version 2.1 of the
+ License, or (at your option) any later version.
- This program is distributed in the hope that it will be useful,
+ This file 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.
+ GNU Lesser General Public License for more details.
- You should have received a copy of the GNU General Public License
- along with this program; if not, see <https://www.gnu.org/licenses/>. */
+ You should have received a copy of the GNU Lesser General Public License
+ along with this program. If not, see <https://www.gnu.org/licenses/>. */
#ifndef _MD5_H
#define _MD5_H 1
@@ -24,6 +24,9 @@
#include <stdint.h>
# if HAVE_OPENSSL_MD5
+# ifndef OPENSSL_API_COMPAT
+# define OPENSSL_API_COMPAT 0x10101000L /* FIXME: Use OpenSSL 1.1+ API. */
+# endif
# include <openssl/md5.h>
# endif
@@ -40,7 +43,7 @@
#endif
#ifndef __THROW
-# if defined __cplusplus && __GNUC_PREREQ (2,8)
+# if defined __cplusplus && (__GNUC_PREREQ (2,8) || __clang_major__ >= 4)
# define __THROW throw ()
# else
# define __THROW
@@ -105,13 +108,15 @@ extern void __md5_process_bytes (const void *buffer, size_t len,
in first 16 bytes following RESBUF. The result is always in little
endian byte order, so that a byte-wise output yields to the wanted
ASCII representation of the message digest. */
-extern void *__md5_finish_ctx (struct md5_ctx *ctx, void *resbuf) __THROW;
+extern void *__md5_finish_ctx (struct md5_ctx *ctx, void *restrict resbuf)
+ __THROW;
/* Put result from CTX in first 16 bytes following RESBUF. The result is
always in little endian byte order, so that a byte-wise output yields
to the wanted ASCII representation of the message digest. */
-extern void *__md5_read_ctx (const struct md5_ctx *ctx, void *resbuf) __THROW;
+extern void *__md5_read_ctx (const struct md5_ctx *ctx, void *restrict resbuf)
+ __THROW;
/* Compute MD5 message digest for LEN bytes beginning at BUFFER. The
@@ -119,11 +124,15 @@ extern void *__md5_read_ctx (const struct md5_ctx *ctx, void *resbuf) __THROW;
output yields to the wanted ASCII representation of the message
digest. */
extern void *__md5_buffer (const char *buffer, size_t len,
- void *resblock) __THROW;
+ void *restrict resblock) __THROW;
# endif
-/* Compute MD5 message digest for bytes read from STREAM. The
- resulting message digest number will be written into the 16 bytes
+
+/* Compute MD5 message digest for bytes read from STREAM.
+ STREAM is an open file stream. Regular files are handled more efficiently.
+ The contents of STREAM from its current position to its end will be read.
+ The case that the last operation on STREAM was an 'ungetc' is not supported.
+ The resulting message digest number will be written into the 16 bytes
beginning at RESBLOCK. */
extern int __md5_stream (FILE *stream, void *resblock) __THROW;
@@ -133,3 +142,10 @@ extern int __md5_stream (FILE *stream, void *resblock) __THROW;
# endif
#endif /* md5.h */
+
+/*
+ * Hey Emacs!
+ * Local Variables:
+ * coding: utf-8
+ * End:
+ */
diff --git a/lib/memmem.c b/lib/memmem.c
new file mode 100644
index 00000000000..5701052d48b
--- /dev/null
+++ b/lib/memmem.c
@@ -0,0 +1,71 @@
+/* Copyright (C) 1991-1994, 1996-1998, 2000, 2004, 2007-2022 Free Software
+ Foundation, Inc.
+ This file is part of the GNU C Library.
+
+ This file is free software: you can redistribute it and/or modify
+ it under the terms of the GNU Lesser General Public License as
+ published by the Free Software Foundation; either version 2.1 of the
+ License, or (at your option) any later version.
+
+ This file 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 Lesser General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public License
+ along with this program. If not, see <https://www.gnu.org/licenses/>. */
+
+/* This particular implementation was written by Eric Blake, 2008. */
+
+#ifndef _LIBC
+# include <config.h>
+#endif
+
+/* Specification of memmem. */
+#include <string.h>
+
+#define RETURN_TYPE void *
+#define AVAILABLE(h, h_l, j, n_l) ((j) <= (h_l) - (n_l))
+#include "str-two-way.h"
+
+/* Return the first occurrence of NEEDLE in HAYSTACK. Return HAYSTACK
+ if NEEDLE_LEN is 0, otherwise NULL if NEEDLE is not found in
+ HAYSTACK. */
+void *
+memmem (const void *haystack_start, size_t haystack_len,
+ const void *needle_start, size_t needle_len)
+{
+ /* Abstract memory is considered to be an array of 'unsigned char' values,
+ not an array of 'char' values. See ISO C 99 section 6.2.6.1. */
+ const unsigned char *haystack = (const unsigned char *) haystack_start;
+ const unsigned char *needle = (const unsigned char *) needle_start;
+
+ if (needle_len == 0)
+ /* The first occurrence of the empty string is deemed to occur at
+ the beginning of the string. */
+ return (void *) haystack;
+
+ /* Sanity check, otherwise the loop might search through the whole
+ memory. */
+ if (__builtin_expect (haystack_len < needle_len, 0))
+ return NULL;
+
+ /* Use optimizations in memchr when possible, to reduce the search
+ size of haystack using a linear algorithm with a smaller
+ coefficient. However, avoid memchr for long needles, since we
+ can often achieve sublinear performance. */
+ if (needle_len < LONG_NEEDLE_THRESHOLD)
+ {
+ haystack = memchr (haystack, *needle, haystack_len);
+ if (!haystack || __builtin_expect (needle_len == 1, 0))
+ return (void *) haystack;
+ haystack_len -= haystack - (const unsigned char *) haystack_start;
+ if (haystack_len < needle_len)
+ return NULL;
+ return two_way_short_needle (haystack, haystack_len, needle, needle_len);
+ }
+ else
+ return two_way_long_needle (haystack, haystack_len, needle, needle_len);
+}
+
+#undef LONG_NEEDLE_THRESHOLD
diff --git a/lib/mempcpy.c b/lib/mempcpy.c
new file mode 100644
index 00000000000..9aae418ef29
--- /dev/null
+++ b/lib/mempcpy.c
@@ -0,0 +1,33 @@
+/* Copy memory area and return pointer after last written byte.
+ Copyright (C) 2003, 2007, 2009-2022 Free Software Foundation, Inc.
+
+ This file is free software: you can redistribute it and/or modify
+ it under the terms of the GNU Lesser General Public License as
+ published by the Free Software Foundation; either version 2.1 of the
+ License, or (at your option) any later version.
+
+ This file 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 Lesser General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public License
+ along with this program. If not, see <https://www.gnu.org/licenses/>. */
+
+#include <config.h>
+
+/* Specification. */
+#include <string.h>
+
+/* A function definition is only needed if HAVE_MEMPCPY is not defined. */
+#if !HAVE_MEMPCPY
+
+/* Copy N bytes of SRC to DEST, return pointer to bytes after the
+ last written byte. */
+void *
+mempcpy (void *dest, const void *src, size_t n)
+{
+ return (char *) memcpy (dest, src, n) + n;
+}
+
+#endif
diff --git a/lib/memrchr.c b/lib/memrchr.c
index 29e56984cb1..90fdb86f1f1 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-2017 Free Software
+ Copyright (C) 1991, 1993, 1996-1997, 1999-2000, 2003-2022 Free Software
Foundation, Inc.
Based on strlen implementation by Torbjorn Granlund (tege@sics.se),
@@ -9,17 +9,17 @@
adaptation to memchr suggested by Dick Karpinski (dick@cca.ucsf.edu),
and implemented by Roland McGrath (roland@ai.mit.edu).
- 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 file is free software: you can redistribute it and/or modify
+ it under the terms of the GNU Lesser 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,
+ This file 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.
+ GNU Lesser General Public License for more details.
- You should have received a copy of the GNU General Public License
+ You should have received a copy of the GNU Lesser General Public License
along with this program. If not, see <https://www.gnu.org/licenses/>. */
#if defined _LIBC
@@ -68,7 +68,7 @@ __memrchr (void const *s, int c_in, size_t n)
if (*--char_ptr == c)
return (void *) char_ptr;
- longword_ptr = (const longword *) char_ptr;
+ longword_ptr = (const void *) char_ptr;
/* All these elucidatory comments refer to 4-byte longwords,
but the theory applies equally well to any size longwords. */
diff --git a/lib/mini-gmp-gnulib.c b/lib/mini-gmp-gnulib.c
new file mode 100644
index 00000000000..7d09c80e9e9
--- /dev/null
+++ b/lib/mini-gmp-gnulib.c
@@ -0,0 +1,48 @@
+/* Tailor mini-gmp.c for Gnulib-using applications.
+
+ Copyright 2018-2022 Free Software Foundation, Inc.
+
+ This file is free software.
+ It is dual-licensed under "the GNU LGPLv3+ or the GNU GPLv2+".
+ You can redistribute it and/or modify it under either
+ - the terms of the GNU Lesser General Public License as published
+ by the Free Software Foundation, either version 3, or (at your
+ option) any later version, or
+ - the terms of the GNU General Public License as published by the
+ Free Software Foundation; either version 2, or (at your option)
+ any later version, or
+ - the same dual license "the GNU LGPLv3+ or the GNU GPLv2+".
+
+ This file 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
+ Lesser General Public License and the GNU General Public License
+ for more details.
+
+ You should have received a copy of the GNU Lesser General Public
+ License and of the GNU General Public License along with this
+ program. If not, see <https://www.gnu.org/licenses/>. */
+
+#include <config.h>
+
+#include <stddef.h>
+#include <stdio.h>
+
+#include "mini-gmp.h"
+
+/* Pacify GCC -Wsuggest-attribute=const, pure, malloc. */
+#if 4 < __GNUC__ + (6 <= __GNUC_MINOR__)
+# pragma GCC diagnostic ignored "-Wsuggest-attribute=const"
+# pragma GCC diagnostic ignored "-Wsuggest-attribute=pure"
+#endif
+#if 8 <= __GNUC__
+# pragma GCC diagnostic ignored "-Wsuggest-attribute=malloc"
+#endif
+
+/* Pacify GCC -Wunused-variable for variables used only in 'assert' calls. */
+#if (defined NDEBUG \
+ && (4 < __GNUC__ + (6 <= __GNUC_MINOR__) || defined __clang__))
+# pragma GCC diagnostic ignored "-Wunused-variable"
+#endif
+
+#include "mini-gmp.c"
diff --git a/lib/mini-gmp.c b/lib/mini-gmp.c
new file mode 100644
index 00000000000..95f067f82d6
--- /dev/null
+++ b/lib/mini-gmp.c
@@ -0,0 +1,4619 @@
+/* mini-gmp, a minimalistic implementation of a GNU GMP subset.
+
+ Contributed to the GNU project by Niels Möller
+
+Copyright 1991-1997, 1999-2021 Free Software Foundation, Inc.
+
+This file is part of the GNU MP Library.
+
+The GNU MP Library is free software; you can redistribute it and/or modify
+it under the terms of either:
+
+ * the GNU Lesser General Public License as published by the Free
+ Software Foundation; either version 3 of the License, or (at your
+ option) any later version.
+
+or
+
+ * the GNU General Public License as published by the Free Software
+ Foundation; either version 2 of the License, or (at your option) any
+ later version.
+
+or both in parallel, as here.
+
+The GNU MP 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 copies of the GNU General Public License and the
+GNU Lesser General Public License along with the GNU MP Library. If not,
+see https://www.gnu.org/licenses/. */
+
+/* NOTE: All functions in this file which are not declared in
+ mini-gmp.h are internal, and are not intended to be compatible
+ with GMP or with future versions of mini-gmp. */
+
+/* Much of the material copied from GMP files, including: gmp-impl.h,
+ longlong.h, mpn/generic/add_n.c, mpn/generic/addmul_1.c,
+ mpn/generic/lshift.c, mpn/generic/mul_1.c,
+ mpn/generic/mul_basecase.c, mpn/generic/rshift.c,
+ mpn/generic/sbpi1_div_qr.c, mpn/generic/sub_n.c,
+ mpn/generic/submul_1.c. */
+
+#include <assert.h>
+#include <ctype.h>
+#include <limits.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
+#include "mini-gmp.h"
+
+#if !defined(MINI_GMP_DONT_USE_FLOAT_H)
+#include <float.h>
+#endif
+
+
+/* Macros */
+#define GMP_LIMB_BITS (sizeof(mp_limb_t) * CHAR_BIT)
+
+#define GMP_LIMB_MAX ((mp_limb_t) ~ (mp_limb_t) 0)
+#define GMP_LIMB_HIGHBIT ((mp_limb_t) 1 << (GMP_LIMB_BITS - 1))
+
+#define GMP_HLIMB_BIT ((mp_limb_t) 1 << (GMP_LIMB_BITS / 2))
+#define GMP_LLIMB_MASK (GMP_HLIMB_BIT - 1)
+
+#define GMP_ULONG_BITS (sizeof(unsigned long) * CHAR_BIT)
+#define GMP_ULONG_HIGHBIT ((unsigned long) 1 << (GMP_ULONG_BITS - 1))
+
+#define GMP_ABS(x) ((x) >= 0 ? (x) : -(x))
+#define GMP_NEG_CAST(T,x) (-((T)((x) + 1) - 1))
+
+#define GMP_MIN(a, b) ((a) < (b) ? (a) : (b))
+#define GMP_MAX(a, b) ((a) > (b) ? (a) : (b))
+
+#define GMP_CMP(a,b) (((a) > (b)) - ((a) < (b)))
+
+#if defined(DBL_MANT_DIG) && FLT_RADIX == 2
+#define GMP_DBL_MANT_BITS DBL_MANT_DIG
+#else
+#define GMP_DBL_MANT_BITS (53)
+#endif
+
+/* Return non-zero if xp,xsize and yp,ysize overlap.
+ If xp+xsize<=yp there's no overlap, or if yp+ysize<=xp there's no
+ overlap. If both these are false, there's an overlap. */
+#define GMP_MPN_OVERLAP_P(xp, xsize, yp, ysize) \
+ ((xp) + (xsize) > (yp) && (yp) + (ysize) > (xp))
+
+#define gmp_assert_nocarry(x) do { \
+ mp_limb_t __cy = (x); \
+ assert (__cy == 0); \
+ (void) (__cy); \
+ } while (0)
+
+#define gmp_clz(count, x) do { \
+ mp_limb_t __clz_x = (x); \
+ unsigned __clz_c = 0; \
+ int LOCAL_SHIFT_BITS = 8; \
+ if (GMP_LIMB_BITS > LOCAL_SHIFT_BITS) \
+ for (; \
+ (__clz_x & ((mp_limb_t) 0xff << (GMP_LIMB_BITS - 8))) == 0; \
+ __clz_c += 8) \
+ { __clz_x <<= LOCAL_SHIFT_BITS; } \
+ for (; (__clz_x & GMP_LIMB_HIGHBIT) == 0; __clz_c++) \
+ __clz_x <<= 1; \
+ (count) = __clz_c; \
+ } while (0)
+
+#define gmp_ctz(count, x) do { \
+ mp_limb_t __ctz_x = (x); \
+ unsigned __ctz_c = 0; \
+ gmp_clz (__ctz_c, __ctz_x & - __ctz_x); \
+ (count) = GMP_LIMB_BITS - 1 - __ctz_c; \
+ } while (0)
+
+#define gmp_add_ssaaaa(sh, sl, ah, al, bh, bl) \
+ do { \
+ mp_limb_t __x; \
+ __x = (al) + (bl); \
+ (sh) = (ah) + (bh) + (__x < (al)); \
+ (sl) = __x; \
+ } while (0)
+
+#define gmp_sub_ddmmss(sh, sl, ah, al, bh, bl) \
+ do { \
+ mp_limb_t __x; \
+ __x = (al) - (bl); \
+ (sh) = (ah) - (bh) - ((al) < (bl)); \
+ (sl) = __x; \
+ } while (0)
+
+#define gmp_umul_ppmm(w1, w0, u, v) \
+ do { \
+ int LOCAL_GMP_LIMB_BITS = GMP_LIMB_BITS; \
+ if (sizeof(unsigned int) * CHAR_BIT >= 2 * GMP_LIMB_BITS) \
+ { \
+ unsigned int __ww = (unsigned int) (u) * (v); \
+ w0 = (mp_limb_t) __ww; \
+ w1 = (mp_limb_t) (__ww >> LOCAL_GMP_LIMB_BITS); \
+ } \
+ else if (GMP_ULONG_BITS >= 2 * GMP_LIMB_BITS) \
+ { \
+ unsigned long int __ww = (unsigned long int) (u) * (v); \
+ w0 = (mp_limb_t) __ww; \
+ w1 = (mp_limb_t) (__ww >> LOCAL_GMP_LIMB_BITS); \
+ } \
+ else { \
+ mp_limb_t __x0, __x1, __x2, __x3; \
+ unsigned __ul, __vl, __uh, __vh; \
+ mp_limb_t __u = (u), __v = (v); \
+ assert (sizeof (unsigned) * 2 >= sizeof (mp_limb_t)); \
+ \
+ __ul = __u & GMP_LLIMB_MASK; \
+ __uh = __u >> (GMP_LIMB_BITS / 2); \
+ __vl = __v & GMP_LLIMB_MASK; \
+ __vh = __v >> (GMP_LIMB_BITS / 2); \
+ \
+ __x0 = (mp_limb_t) __ul * __vl; \
+ __x1 = (mp_limb_t) __ul * __vh; \
+ __x2 = (mp_limb_t) __uh * __vl; \
+ __x3 = (mp_limb_t) __uh * __vh; \
+ \
+ __x1 += __x0 >> (GMP_LIMB_BITS / 2);/* this can't give carry */ \
+ __x1 += __x2; /* but this indeed can */ \
+ if (__x1 < __x2) /* did we get it? */ \
+ __x3 += GMP_HLIMB_BIT; /* yes, add it in the proper pos. */ \
+ \
+ (w1) = __x3 + (__x1 >> (GMP_LIMB_BITS / 2)); \
+ (w0) = (__x1 << (GMP_LIMB_BITS / 2)) + (__x0 & GMP_LLIMB_MASK); \
+ } \
+ } while (0)
+
+#define gmp_udiv_qrnnd_preinv(q, r, nh, nl, d, di) \
+ do { \
+ mp_limb_t _qh, _ql, _r, _mask; \
+ gmp_umul_ppmm (_qh, _ql, (nh), (di)); \
+ gmp_add_ssaaaa (_qh, _ql, _qh, _ql, (nh) + 1, (nl)); \
+ _r = (nl) - _qh * (d); \
+ _mask = -(mp_limb_t) (_r > _ql); /* both > and >= are OK */ \
+ _qh += _mask; \
+ _r += _mask & (d); \
+ if (_r >= (d)) \
+ { \
+ _r -= (d); \
+ _qh++; \
+ } \
+ \
+ (r) = _r; \
+ (q) = _qh; \
+ } while (0)
+
+#define gmp_udiv_qr_3by2(q, r1, r0, n2, n1, n0, d1, d0, dinv) \
+ do { \
+ mp_limb_t _q0, _t1, _t0, _mask; \
+ gmp_umul_ppmm ((q), _q0, (n2), (dinv)); \
+ gmp_add_ssaaaa ((q), _q0, (q), _q0, (n2), (n1)); \
+ \
+ /* Compute the two most significant limbs of n - q'd */ \
+ (r1) = (n1) - (d1) * (q); \
+ gmp_sub_ddmmss ((r1), (r0), (r1), (n0), (d1), (d0)); \
+ gmp_umul_ppmm (_t1, _t0, (d0), (q)); \
+ gmp_sub_ddmmss ((r1), (r0), (r1), (r0), _t1, _t0); \
+ (q)++; \
+ \
+ /* Conditionally adjust q and the remainders */ \
+ _mask = - (mp_limb_t) ((r1) >= _q0); \
+ (q) += _mask; \
+ gmp_add_ssaaaa ((r1), (r0), (r1), (r0), _mask & (d1), _mask & (d0)); \
+ if ((r1) >= (d1)) \
+ { \
+ if ((r1) > (d1) || (r0) >= (d0)) \
+ { \
+ (q)++; \
+ gmp_sub_ddmmss ((r1), (r0), (r1), (r0), (d1), (d0)); \
+ } \
+ } \
+ } while (0)
+
+/* Swap macros. */
+#define MP_LIMB_T_SWAP(x, y) \
+ do { \
+ mp_limb_t __mp_limb_t_swap__tmp = (x); \
+ (x) = (y); \
+ (y) = __mp_limb_t_swap__tmp; \
+ } while (0)
+#define MP_SIZE_T_SWAP(x, y) \
+ do { \
+ mp_size_t __mp_size_t_swap__tmp = (x); \
+ (x) = (y); \
+ (y) = __mp_size_t_swap__tmp; \
+ } while (0)
+#define MP_BITCNT_T_SWAP(x,y) \
+ do { \
+ mp_bitcnt_t __mp_bitcnt_t_swap__tmp = (x); \
+ (x) = (y); \
+ (y) = __mp_bitcnt_t_swap__tmp; \
+ } while (0)
+#define MP_PTR_SWAP(x, y) \
+ do { \
+ mp_ptr __mp_ptr_swap__tmp = (x); \
+ (x) = (y); \
+ (y) = __mp_ptr_swap__tmp; \
+ } while (0)
+#define MP_SRCPTR_SWAP(x, y) \
+ do { \
+ mp_srcptr __mp_srcptr_swap__tmp = (x); \
+ (x) = (y); \
+ (y) = __mp_srcptr_swap__tmp; \
+ } while (0)
+
+#define MPN_PTR_SWAP(xp,xs, yp,ys) \
+ do { \
+ MP_PTR_SWAP (xp, yp); \
+ MP_SIZE_T_SWAP (xs, ys); \
+ } while(0)
+#define MPN_SRCPTR_SWAP(xp,xs, yp,ys) \
+ do { \
+ MP_SRCPTR_SWAP (xp, yp); \
+ MP_SIZE_T_SWAP (xs, ys); \
+ } while(0)
+
+#define MPZ_PTR_SWAP(x, y) \
+ do { \
+ mpz_ptr __mpz_ptr_swap__tmp = (x); \
+ (x) = (y); \
+ (y) = __mpz_ptr_swap__tmp; \
+ } while (0)
+#define MPZ_SRCPTR_SWAP(x, y) \
+ do { \
+ mpz_srcptr __mpz_srcptr_swap__tmp = (x); \
+ (x) = (y); \
+ (y) = __mpz_srcptr_swap__tmp; \
+ } while (0)
+
+const int mp_bits_per_limb = GMP_LIMB_BITS;
+
+
+/* Memory allocation and other helper functions. */
+static void
+gmp_die (const char *msg)
+{
+ fprintf (stderr, "%s\n", msg);
+ abort();
+}
+
+static void *
+gmp_default_alloc (size_t size)
+{
+ void *p;
+
+ assert (size > 0);
+
+ p = malloc (size);
+ if (!p)
+ gmp_die("gmp_default_alloc: Virtual memory exhausted.");
+
+ return p;
+}
+
+static void *
+gmp_default_realloc (void *old, size_t unused_old_size, size_t new_size)
+{
+ void * p;
+
+ p = realloc (old, new_size);
+
+ if (!p)
+ gmp_die("gmp_default_realloc: Virtual memory exhausted.");
+
+ return p;
+}
+
+static void
+gmp_default_free (void *p, size_t unused_size)
+{
+ free (p);
+}
+
+static void * (*gmp_allocate_func) (size_t) = gmp_default_alloc;
+static void * (*gmp_reallocate_func) (void *, size_t, size_t) = gmp_default_realloc;
+static void (*gmp_free_func) (void *, size_t) = gmp_default_free;
+
+void
+mp_get_memory_functions (void *(**alloc_func) (size_t),
+ void *(**realloc_func) (void *, size_t, size_t),
+ void (**free_func) (void *, size_t))
+{
+ if (alloc_func)
+ *alloc_func = gmp_allocate_func;
+
+ if (realloc_func)
+ *realloc_func = gmp_reallocate_func;
+
+ if (free_func)
+ *free_func = gmp_free_func;
+}
+
+void
+mp_set_memory_functions (void *(*alloc_func) (size_t),
+ void *(*realloc_func) (void *, size_t, size_t),
+ void (*free_func) (void *, size_t))
+{
+ if (!alloc_func)
+ alloc_func = gmp_default_alloc;
+ if (!realloc_func)
+ realloc_func = gmp_default_realloc;
+ if (!free_func)
+ free_func = gmp_default_free;
+
+ gmp_allocate_func = alloc_func;
+ gmp_reallocate_func = realloc_func;
+ gmp_free_func = free_func;
+}
+
+#define gmp_alloc(size) ((*gmp_allocate_func)((size)))
+#define gmp_free(p, size) ((*gmp_free_func) ((p), (size)))
+#define gmp_realloc(ptr, old_size, size) ((*gmp_reallocate_func)(ptr, old_size, size))
+
+static mp_ptr
+gmp_alloc_limbs (mp_size_t size)
+{
+ return (mp_ptr) gmp_alloc (size * sizeof (mp_limb_t));
+}
+
+static mp_ptr
+gmp_realloc_limbs (mp_ptr old, mp_size_t old_size, mp_size_t size)
+{
+ assert (size > 0);
+ return (mp_ptr) gmp_realloc (old, old_size * sizeof (mp_limb_t), size * sizeof (mp_limb_t));
+}
+
+static void
+gmp_free_limbs (mp_ptr old, mp_size_t size)
+{
+ gmp_free (old, size * sizeof (mp_limb_t));
+}
+
+
+/* MPN interface */
+
+void
+mpn_copyi (mp_ptr d, mp_srcptr s, mp_size_t n)
+{
+ mp_size_t i;
+ for (i = 0; i < n; i++)
+ d[i] = s[i];
+}
+
+void
+mpn_copyd (mp_ptr d, mp_srcptr s, mp_size_t n)
+{
+ while (--n >= 0)
+ d[n] = s[n];
+}
+
+int
+mpn_cmp (mp_srcptr ap, mp_srcptr bp, mp_size_t n)
+{
+ while (--n >= 0)
+ {
+ if (ap[n] != bp[n])
+ return ap[n] > bp[n] ? 1 : -1;
+ }
+ return 0;
+}
+
+static int
+mpn_cmp4 (mp_srcptr ap, mp_size_t an, mp_srcptr bp, mp_size_t bn)
+{
+ if (an != bn)
+ return an < bn ? -1 : 1;
+ else
+ return mpn_cmp (ap, bp, an);
+}
+
+static mp_size_t
+mpn_normalized_size (mp_srcptr xp, mp_size_t n)
+{
+ while (n > 0 && xp[n-1] == 0)
+ --n;
+ return n;
+}
+
+int
+mpn_zero_p(mp_srcptr rp, mp_size_t n)
+{
+ return mpn_normalized_size (rp, n) == 0;
+}
+
+void
+mpn_zero (mp_ptr rp, mp_size_t n)
+{
+ while (--n >= 0)
+ rp[n] = 0;
+}
+
+mp_limb_t
+mpn_add_1 (mp_ptr rp, mp_srcptr ap, mp_size_t n, mp_limb_t b)
+{
+ mp_size_t i;
+
+ assert (n > 0);
+ i = 0;
+ do
+ {
+ mp_limb_t r = ap[i] + b;
+ /* Carry out */
+ b = (r < b);
+ rp[i] = r;
+ }
+ while (++i < n);
+
+ return b;
+}
+
+mp_limb_t
+mpn_add_n (mp_ptr rp, mp_srcptr ap, mp_srcptr bp, mp_size_t n)
+{
+ mp_size_t i;
+ mp_limb_t cy;
+
+ for (i = 0, cy = 0; i < n; i++)
+ {
+ mp_limb_t a, b, r;
+ a = ap[i]; b = bp[i];
+ r = a + cy;
+ cy = (r < cy);
+ r += b;
+ cy += (r < b);
+ rp[i] = r;
+ }
+ return cy;
+}
+
+mp_limb_t
+mpn_add (mp_ptr rp, mp_srcptr ap, mp_size_t an, mp_srcptr bp, mp_size_t bn)
+{
+ mp_limb_t cy;
+
+ assert (an >= bn);
+
+ cy = mpn_add_n (rp, ap, bp, bn);
+ if (an > bn)
+ cy = mpn_add_1 (rp + bn, ap + bn, an - bn, cy);
+ return cy;
+}
+
+mp_limb_t
+mpn_sub_1 (mp_ptr rp, mp_srcptr ap, mp_size_t n, mp_limb_t b)
+{
+ mp_size_t i;
+
+ assert (n > 0);
+
+ i = 0;
+ do
+ {
+ mp_limb_t a = ap[i];
+ /* Carry out */
+ mp_limb_t cy = a < b;
+ rp[i] = a - b;
+ b = cy;
+ }
+ while (++i < n);
+
+ return b;
+}
+
+mp_limb_t
+mpn_sub_n (mp_ptr rp, mp_srcptr ap, mp_srcptr bp, mp_size_t n)
+{
+ mp_size_t i;
+ mp_limb_t cy;
+
+ for (i = 0, cy = 0; i < n; i++)
+ {
+ mp_limb_t a, b;
+ a = ap[i]; b = bp[i];
+ b += cy;
+ cy = (b < cy);
+ cy += (a < b);
+ rp[i] = a - b;
+ }
+ return cy;
+}
+
+mp_limb_t
+mpn_sub (mp_ptr rp, mp_srcptr ap, mp_size_t an, mp_srcptr bp, mp_size_t bn)
+{
+ mp_limb_t cy;
+
+ assert (an >= bn);
+
+ cy = mpn_sub_n (rp, ap, bp, bn);
+ if (an > bn)
+ cy = mpn_sub_1 (rp + bn, ap + bn, an - bn, cy);
+ return cy;
+}
+
+mp_limb_t
+mpn_mul_1 (mp_ptr rp, mp_srcptr up, mp_size_t n, mp_limb_t vl)
+{
+ mp_limb_t ul, cl, hpl, lpl;
+
+ assert (n >= 1);
+
+ cl = 0;
+ do
+ {
+ ul = *up++;
+ gmp_umul_ppmm (hpl, lpl, ul, vl);
+
+ lpl += cl;
+ cl = (lpl < cl) + hpl;
+
+ *rp++ = lpl;
+ }
+ while (--n != 0);
+
+ return cl;
+}
+
+mp_limb_t
+mpn_addmul_1 (mp_ptr rp, mp_srcptr up, mp_size_t n, mp_limb_t vl)
+{
+ mp_limb_t ul, cl, hpl, lpl, rl;
+
+ assert (n >= 1);
+
+ cl = 0;
+ do
+ {
+ ul = *up++;
+ gmp_umul_ppmm (hpl, lpl, ul, vl);
+
+ lpl += cl;
+ cl = (lpl < cl) + hpl;
+
+ rl = *rp;
+ lpl = rl + lpl;
+ cl += lpl < rl;
+ *rp++ = lpl;
+ }
+ while (--n != 0);
+
+ return cl;
+}
+
+mp_limb_t
+mpn_submul_1 (mp_ptr rp, mp_srcptr up, mp_size_t n, mp_limb_t vl)
+{
+ mp_limb_t ul, cl, hpl, lpl, rl;
+
+ assert (n >= 1);
+
+ cl = 0;
+ do
+ {
+ ul = *up++;
+ gmp_umul_ppmm (hpl, lpl, ul, vl);
+
+ lpl += cl;
+ cl = (lpl < cl) + hpl;
+
+ rl = *rp;
+ lpl = rl - lpl;
+ cl += lpl > rl;
+ *rp++ = lpl;
+ }
+ while (--n != 0);
+
+ return cl;
+}
+
+mp_limb_t
+mpn_mul (mp_ptr rp, mp_srcptr up, mp_size_t un, mp_srcptr vp, mp_size_t vn)
+{
+ assert (un >= vn);
+ assert (vn >= 1);
+ assert (!GMP_MPN_OVERLAP_P(rp, un + vn, up, un));
+ assert (!GMP_MPN_OVERLAP_P(rp, un + vn, vp, vn));
+
+ /* We first multiply by the low order limb. This result can be
+ stored, not added, to rp. We also avoid a loop for zeroing this
+ way. */
+
+ rp[un] = mpn_mul_1 (rp, up, un, vp[0]);
+
+ /* Now accumulate the product of up[] and the next higher limb from
+ vp[]. */
+
+ while (--vn >= 1)
+ {
+ rp += 1, vp += 1;
+ rp[un] = mpn_addmul_1 (rp, up, un, vp[0]);
+ }
+ return rp[un];
+}
+
+void
+mpn_mul_n (mp_ptr rp, mp_srcptr ap, mp_srcptr bp, mp_size_t n)
+{
+ mpn_mul (rp, ap, n, bp, n);
+}
+
+void
+mpn_sqr (mp_ptr rp, mp_srcptr ap, mp_size_t n)
+{
+ mpn_mul (rp, ap, n, ap, n);
+}
+
+mp_limb_t
+mpn_lshift (mp_ptr rp, mp_srcptr up, mp_size_t n, unsigned int cnt)
+{
+ mp_limb_t high_limb, low_limb;
+ unsigned int tnc;
+ mp_limb_t retval;
+
+ assert (n >= 1);
+ assert (cnt >= 1);
+ assert (cnt < GMP_LIMB_BITS);
+
+ up += n;
+ rp += n;
+
+ tnc = GMP_LIMB_BITS - cnt;
+ low_limb = *--up;
+ retval = low_limb >> tnc;
+ high_limb = (low_limb << cnt);
+
+ while (--n != 0)
+ {
+ low_limb = *--up;
+ *--rp = high_limb | (low_limb >> tnc);
+ high_limb = (low_limb << cnt);
+ }
+ *--rp = high_limb;
+
+ return retval;
+}
+
+mp_limb_t
+mpn_rshift (mp_ptr rp, mp_srcptr up, mp_size_t n, unsigned int cnt)
+{
+ mp_limb_t high_limb, low_limb;
+ unsigned int tnc;
+ mp_limb_t retval;
+
+ assert (n >= 1);
+ assert (cnt >= 1);
+ assert (cnt < GMP_LIMB_BITS);
+
+ tnc = GMP_LIMB_BITS - cnt;
+ high_limb = *up++;
+ retval = (high_limb << tnc);
+ low_limb = high_limb >> cnt;
+
+ while (--n != 0)
+ {
+ high_limb = *up++;
+ *rp++ = low_limb | (high_limb << tnc);
+ low_limb = high_limb >> cnt;
+ }
+ *rp = low_limb;
+
+ return retval;
+}
+
+static mp_bitcnt_t
+mpn_common_scan (mp_limb_t limb, mp_size_t i, mp_srcptr up, mp_size_t un,
+ mp_limb_t ux)
+{
+ unsigned cnt;
+
+ assert (ux == 0 || ux == GMP_LIMB_MAX);
+ assert (0 <= i && i <= un );
+
+ while (limb == 0)
+ {
+ i++;
+ if (i == un)
+ return (ux == 0 ? ~(mp_bitcnt_t) 0 : un * GMP_LIMB_BITS);
+ limb = ux ^ up[i];
+ }
+ gmp_ctz (cnt, limb);
+ return (mp_bitcnt_t) i * GMP_LIMB_BITS + cnt;
+}
+
+mp_bitcnt_t
+mpn_scan1 (mp_srcptr ptr, mp_bitcnt_t bit)
+{
+ mp_size_t i;
+ i = bit / GMP_LIMB_BITS;
+
+ return mpn_common_scan ( ptr[i] & (GMP_LIMB_MAX << (bit % GMP_LIMB_BITS)),
+ i, ptr, i, 0);
+}
+
+mp_bitcnt_t
+mpn_scan0 (mp_srcptr ptr, mp_bitcnt_t bit)
+{
+ mp_size_t i;
+ i = bit / GMP_LIMB_BITS;
+
+ return mpn_common_scan (~ptr[i] & (GMP_LIMB_MAX << (bit % GMP_LIMB_BITS)),
+ i, ptr, i, GMP_LIMB_MAX);
+}
+
+void
+mpn_com (mp_ptr rp, mp_srcptr up, mp_size_t n)
+{
+ while (--n >= 0)
+ *rp++ = ~ *up++;
+}
+
+mp_limb_t
+mpn_neg (mp_ptr rp, mp_srcptr up, mp_size_t n)
+{
+ while (*up == 0)
+ {
+ *rp = 0;
+ if (!--n)
+ return 0;
+ ++up; ++rp;
+ }
+ *rp = - *up;
+ mpn_com (++rp, ++up, --n);
+ return 1;
+}
+
+
+/* MPN division interface. */
+
+/* The 3/2 inverse is defined as
+
+ m = floor( (B^3-1) / (B u1 + u0)) - B
+*/
+mp_limb_t
+mpn_invert_3by2 (mp_limb_t u1, mp_limb_t u0)
+{
+ mp_limb_t r, m;
+
+ {
+ mp_limb_t p, ql;
+ unsigned ul, uh, qh;
+
+ assert (sizeof (unsigned) * 2 >= sizeof (mp_limb_t));
+ /* For notation, let b denote the half-limb base, so that B = b^2.
+ Split u1 = b uh + ul. */
+ ul = u1 & GMP_LLIMB_MASK;
+ uh = u1 >> (GMP_LIMB_BITS / 2);
+
+ /* Approximation of the high half of quotient. Differs from the 2/1
+ inverse of the half limb uh, since we have already subtracted
+ u0. */
+ qh = (u1 ^ GMP_LIMB_MAX) / uh;
+
+ /* Adjust to get a half-limb 3/2 inverse, i.e., we want
+
+ qh' = floor( (b^3 - 1) / u) - b = floor ((b^3 - b u - 1) / u
+ = floor( (b (~u) + b-1) / u),
+
+ and the remainder
+
+ r = b (~u) + b-1 - qh (b uh + ul)
+ = b (~u - qh uh) + b-1 - qh ul
+
+ Subtraction of qh ul may underflow, which implies adjustments.
+ But by normalization, 2 u >= B > qh ul, so we need to adjust by
+ at most 2.
+ */
+
+ r = ((~u1 - (mp_limb_t) qh * uh) << (GMP_LIMB_BITS / 2)) | GMP_LLIMB_MASK;
+
+ p = (mp_limb_t) qh * ul;
+ /* Adjustment steps taken from udiv_qrnnd_c */
+ if (r < p)
+ {
+ qh--;
+ r += u1;
+ if (r >= u1) /* i.e. we didn't get carry when adding to r */
+ if (r < p)
+ {
+ qh--;
+ r += u1;
+ }
+ }
+ r -= p;
+
+ /* Low half of the quotient is
+
+ ql = floor ( (b r + b-1) / u1).
+
+ This is a 3/2 division (on half-limbs), for which qh is a
+ suitable inverse. */
+
+ p = (r >> (GMP_LIMB_BITS / 2)) * qh + r;
+ /* Unlike full-limb 3/2, we can add 1 without overflow. For this to
+ work, it is essential that ql is a full mp_limb_t. */
+ ql = (p >> (GMP_LIMB_BITS / 2)) + 1;
+
+ /* By the 3/2 trick, we don't need the high half limb. */
+ r = (r << (GMP_LIMB_BITS / 2)) + GMP_LLIMB_MASK - ql * u1;
+
+ if (r >= (GMP_LIMB_MAX & (p << (GMP_LIMB_BITS / 2))))
+ {
+ ql--;
+ r += u1;
+ }
+ m = ((mp_limb_t) qh << (GMP_LIMB_BITS / 2)) + ql;
+ if (r >= u1)
+ {
+ m++;
+ r -= u1;
+ }
+ }
+
+ /* Now m is the 2/1 inverse of u1. If u0 > 0, adjust it to become a
+ 3/2 inverse. */
+ if (u0 > 0)
+ {
+ mp_limb_t th, tl;
+ r = ~r;
+ r += u0;
+ if (r < u0)
+ {
+ m--;
+ if (r >= u1)
+ {
+ m--;
+ r -= u1;
+ }
+ r -= u1;
+ }
+ gmp_umul_ppmm (th, tl, u0, m);
+ r += th;
+ if (r < th)
+ {
+ m--;
+ m -= ((r > u1) | ((r == u1) & (tl > u0)));
+ }
+ }
+
+ return m;
+}
+
+struct gmp_div_inverse
+{
+ /* Normalization shift count. */
+ unsigned shift;
+ /* Normalized divisor (d0 unused for mpn_div_qr_1) */
+ mp_limb_t d1, d0;
+ /* Inverse, for 2/1 or 3/2. */
+ mp_limb_t di;
+};
+
+static void
+mpn_div_qr_1_invert (struct gmp_div_inverse *inv, mp_limb_t d)
+{
+ unsigned shift;
+
+ assert (d > 0);
+ gmp_clz (shift, d);
+ inv->shift = shift;
+ inv->d1 = d << shift;
+ inv->di = mpn_invert_limb (inv->d1);
+}
+
+static void
+mpn_div_qr_2_invert (struct gmp_div_inverse *inv,
+ mp_limb_t d1, mp_limb_t d0)
+{
+ unsigned shift;
+
+ assert (d1 > 0);
+ gmp_clz (shift, d1);
+ inv->shift = shift;
+ if (shift > 0)
+ {
+ d1 = (d1 << shift) | (d0 >> (GMP_LIMB_BITS - shift));
+ d0 <<= shift;
+ }
+ inv->d1 = d1;
+ inv->d0 = d0;
+ inv->di = mpn_invert_3by2 (d1, d0);
+}
+
+static void
+mpn_div_qr_invert (struct gmp_div_inverse *inv,
+ mp_srcptr dp, mp_size_t dn)
+{
+ assert (dn > 0);
+
+ if (dn == 1)
+ mpn_div_qr_1_invert (inv, dp[0]);
+ else if (dn == 2)
+ mpn_div_qr_2_invert (inv, dp[1], dp[0]);
+ else
+ {
+ unsigned shift;
+ mp_limb_t d1, d0;
+
+ d1 = dp[dn-1];
+ d0 = dp[dn-2];
+ assert (d1 > 0);
+ gmp_clz (shift, d1);
+ inv->shift = shift;
+ if (shift > 0)
+ {
+ d1 = (d1 << shift) | (d0 >> (GMP_LIMB_BITS - shift));
+ d0 = (d0 << shift) | (dp[dn-3] >> (GMP_LIMB_BITS - shift));
+ }
+ inv->d1 = d1;
+ inv->d0 = d0;
+ inv->di = mpn_invert_3by2 (d1, d0);
+ }
+}
+
+/* Not matching current public gmp interface, rather corresponding to
+ the sbpi1_div_* functions. */
+static mp_limb_t
+mpn_div_qr_1_preinv (mp_ptr qp, mp_srcptr np, mp_size_t nn,
+ const struct gmp_div_inverse *inv)
+{
+ mp_limb_t d, di;
+ mp_limb_t r;
+ mp_ptr tp = NULL;
+ mp_size_t tn = 0;
+
+ if (inv->shift > 0)
+ {
+ /* Shift, reusing qp area if possible. In-place shift if qp == np. */
+ tp = qp;
+ if (!tp)
+ {
+ tn = nn;
+ tp = gmp_alloc_limbs (tn);
+ }
+ r = mpn_lshift (tp, np, nn, inv->shift);
+ np = tp;
+ }
+ else
+ r = 0;
+
+ d = inv->d1;
+ di = inv->di;
+ while (--nn >= 0)
+ {
+ mp_limb_t q;
+
+ gmp_udiv_qrnnd_preinv (q, r, r, np[nn], d, di);
+ if (qp)
+ qp[nn] = q;
+ }
+ if (tn)
+ gmp_free_limbs (tp, tn);
+
+ return r >> inv->shift;
+}
+
+static void
+mpn_div_qr_2_preinv (mp_ptr qp, mp_ptr np, mp_size_t nn,
+ const struct gmp_div_inverse *inv)
+{
+ unsigned shift;
+ mp_size_t i;
+ mp_limb_t d1, d0, di, r1, r0;
+
+ assert (nn >= 2);
+ shift = inv->shift;
+ d1 = inv->d1;
+ d0 = inv->d0;
+ di = inv->di;
+
+ if (shift > 0)
+ r1 = mpn_lshift (np, np, nn, shift);
+ else
+ r1 = 0;
+
+ r0 = np[nn - 1];
+
+ i = nn - 2;
+ do
+ {
+ mp_limb_t n0, q;
+ n0 = np[i];
+ gmp_udiv_qr_3by2 (q, r1, r0, r1, r0, n0, d1, d0, di);
+
+ if (qp)
+ qp[i] = q;
+ }
+ while (--i >= 0);
+
+ if (shift > 0)
+ {
+ assert ((r0 & (GMP_LIMB_MAX >> (GMP_LIMB_BITS - shift))) == 0);
+ r0 = (r0 >> shift) | (r1 << (GMP_LIMB_BITS - shift));
+ r1 >>= shift;
+ }
+
+ np[1] = r1;
+ np[0] = r0;
+}
+
+static void
+mpn_div_qr_pi1 (mp_ptr qp,
+ mp_ptr np, mp_size_t nn, mp_limb_t n1,
+ mp_srcptr dp, mp_size_t dn,
+ mp_limb_t dinv)
+{
+ mp_size_t i;
+
+ mp_limb_t d1, d0;
+ mp_limb_t cy, cy1;
+ mp_limb_t q;
+
+ assert (dn > 2);
+ assert (nn >= dn);
+
+ d1 = dp[dn - 1];
+ d0 = dp[dn - 2];
+
+ assert ((d1 & GMP_LIMB_HIGHBIT) != 0);
+ /* Iteration variable is the index of the q limb.
+ *
+ * We divide <n1, np[dn-1+i], np[dn-2+i], np[dn-3+i],..., np[i]>
+ * by <d1, d0, dp[dn-3], ..., dp[0] >
+ */
+
+ i = nn - dn;
+ do
+ {
+ mp_limb_t n0 = np[dn-1+i];
+
+ if (n1 == d1 && n0 == d0)
+ {
+ q = GMP_LIMB_MAX;
+ mpn_submul_1 (np+i, dp, dn, q);
+ n1 = np[dn-1+i]; /* update n1, last loop's value will now be invalid */
+ }
+ else
+ {
+ gmp_udiv_qr_3by2 (q, n1, n0, n1, n0, np[dn-2+i], d1, d0, dinv);
+
+ cy = mpn_submul_1 (np + i, dp, dn-2, q);
+
+ cy1 = n0 < cy;
+ n0 = n0 - cy;
+ cy = n1 < cy1;
+ n1 = n1 - cy1;
+ np[dn-2+i] = n0;
+
+ if (cy != 0)
+ {
+ n1 += d1 + mpn_add_n (np + i, np + i, dp, dn - 1);
+ q--;
+ }
+ }
+
+ if (qp)
+ qp[i] = q;
+ }
+ while (--i >= 0);
+
+ np[dn - 1] = n1;
+}
+
+static void
+mpn_div_qr_preinv (mp_ptr qp, mp_ptr np, mp_size_t nn,
+ mp_srcptr dp, mp_size_t dn,
+ const struct gmp_div_inverse *inv)
+{
+ assert (dn > 0);
+ assert (nn >= dn);
+
+ if (dn == 1)
+ np[0] = mpn_div_qr_1_preinv (qp, np, nn, inv);
+ else if (dn == 2)
+ mpn_div_qr_2_preinv (qp, np, nn, inv);
+ else
+ {
+ mp_limb_t nh;
+ unsigned shift;
+
+ assert (inv->d1 == dp[dn-1]);
+ assert (inv->d0 == dp[dn-2]);
+ assert ((inv->d1 & GMP_LIMB_HIGHBIT) != 0);
+
+ shift = inv->shift;
+ if (shift > 0)
+ nh = mpn_lshift (np, np, nn, shift);
+ else
+ nh = 0;
+
+ mpn_div_qr_pi1 (qp, np, nn, nh, dp, dn, inv->di);
+
+ if (shift > 0)
+ gmp_assert_nocarry (mpn_rshift (np, np, dn, shift));
+ }
+}
+
+static void
+mpn_div_qr (mp_ptr qp, mp_ptr np, mp_size_t nn, mp_srcptr dp, mp_size_t dn)
+{
+ struct gmp_div_inverse inv;
+ mp_ptr tp = NULL;
+
+ assert (dn > 0);
+ assert (nn >= dn);
+
+ mpn_div_qr_invert (&inv, dp, dn);
+ if (dn > 2 && inv.shift > 0)
+ {
+ tp = gmp_alloc_limbs (dn);
+ gmp_assert_nocarry (mpn_lshift (tp, dp, dn, inv.shift));
+ dp = tp;
+ }
+ mpn_div_qr_preinv (qp, np, nn, dp, dn, &inv);
+ if (tp)
+ gmp_free_limbs (tp, dn);
+}
+
+
+/* MPN base conversion. */
+static unsigned
+mpn_base_power_of_two_p (unsigned b)
+{
+ switch (b)
+ {
+ case 2: return 1;
+ case 4: return 2;
+ case 8: return 3;
+ case 16: return 4;
+ case 32: return 5;
+ case 64: return 6;
+ case 128: return 7;
+ case 256: return 8;
+ default: return 0;
+ }
+}
+
+struct mpn_base_info
+{
+ /* bb is the largest power of the base which fits in one limb, and
+ exp is the corresponding exponent. */
+ unsigned exp;
+ mp_limb_t bb;
+};
+
+static void
+mpn_get_base_info (struct mpn_base_info *info, mp_limb_t b)
+{
+ mp_limb_t m;
+ mp_limb_t p;
+ unsigned exp;
+
+ m = GMP_LIMB_MAX / b;
+ for (exp = 1, p = b; p <= m; exp++)
+ p *= b;
+
+ info->exp = exp;
+ info->bb = p;
+}
+
+static mp_bitcnt_t
+mpn_limb_size_in_base_2 (mp_limb_t u)
+{
+ unsigned shift;
+
+ assert (u > 0);
+ gmp_clz (shift, u);
+ return GMP_LIMB_BITS - shift;
+}
+
+static size_t
+mpn_get_str_bits (unsigned char *sp, unsigned bits, mp_srcptr up, mp_size_t un)
+{
+ unsigned char mask;
+ size_t sn, j;
+ mp_size_t i;
+ unsigned shift;
+
+ sn = ((un - 1) * GMP_LIMB_BITS + mpn_limb_size_in_base_2 (up[un-1])
+ + bits - 1) / bits;
+
+ mask = (1U << bits) - 1;
+
+ for (i = 0, j = sn, shift = 0; j-- > 0;)
+ {
+ unsigned char digit = up[i] >> shift;
+
+ shift += bits;
+
+ if (shift >= GMP_LIMB_BITS && ++i < un)
+ {
+ shift -= GMP_LIMB_BITS;
+ digit |= up[i] << (bits - shift);
+ }
+ sp[j] = digit & mask;
+ }
+ return sn;
+}
+
+/* We generate digits from the least significant end, and reverse at
+ the end. */
+static size_t
+mpn_limb_get_str (unsigned char *sp, mp_limb_t w,
+ const struct gmp_div_inverse *binv)
+{
+ mp_size_t i;
+ for (i = 0; w > 0; i++)
+ {
+ mp_limb_t h, l, r;
+
+ h = w >> (GMP_LIMB_BITS - binv->shift);
+ l = w << binv->shift;
+
+ gmp_udiv_qrnnd_preinv (w, r, h, l, binv->d1, binv->di);
+ assert ((r & (GMP_LIMB_MAX >> (GMP_LIMB_BITS - binv->shift))) == 0);
+ r >>= binv->shift;
+
+ sp[i] = r;
+ }
+ return i;
+}
+
+static size_t
+mpn_get_str_other (unsigned char *sp,
+ int base, const struct mpn_base_info *info,
+ mp_ptr up, mp_size_t un)
+{
+ struct gmp_div_inverse binv;
+ size_t sn;
+ size_t i;
+
+ mpn_div_qr_1_invert (&binv, base);
+
+ sn = 0;
+
+ if (un > 1)
+ {
+ struct gmp_div_inverse bbinv;
+ mpn_div_qr_1_invert (&bbinv, info->bb);
+
+ do
+ {
+ mp_limb_t w;
+ size_t done;
+ w = mpn_div_qr_1_preinv (up, up, un, &bbinv);
+ un -= (up[un-1] == 0);
+ done = mpn_limb_get_str (sp + sn, w, &binv);
+
+ for (sn += done; done < info->exp; done++)
+ sp[sn++] = 0;
+ }
+ while (un > 1);
+ }
+ sn += mpn_limb_get_str (sp + sn, up[0], &binv);
+
+ /* Reverse order */
+ for (i = 0; 2*i + 1 < sn; i++)
+ {
+ unsigned char t = sp[i];
+ sp[i] = sp[sn - i - 1];
+ sp[sn - i - 1] = t;
+ }
+
+ return sn;
+}
+
+size_t
+mpn_get_str (unsigned char *sp, int base, mp_ptr up, mp_size_t un)
+{
+ unsigned bits;
+
+ assert (un > 0);
+ assert (up[un-1] > 0);
+
+ bits = mpn_base_power_of_two_p (base);
+ if (bits)
+ return mpn_get_str_bits (sp, bits, up, un);
+ else
+ {
+ struct mpn_base_info info;
+
+ mpn_get_base_info (&info, base);
+ return mpn_get_str_other (sp, base, &info, up, un);
+ }
+}
+
+static mp_size_t
+mpn_set_str_bits (mp_ptr rp, const unsigned char *sp, size_t sn,
+ unsigned bits)
+{
+ mp_size_t rn;
+ mp_limb_t limb;
+ unsigned shift;
+
+ for (limb = 0, rn = 0, shift = 0; sn-- > 0; )
+ {
+ limb |= (mp_limb_t) sp[sn] << shift;
+ shift += bits;
+ if (shift >= GMP_LIMB_BITS)
+ {
+ shift -= GMP_LIMB_BITS;
+ rp[rn++] = limb;
+ /* Next line is correct also if shift == 0,
+ bits == 8, and mp_limb_t == unsigned char. */
+ limb = (unsigned int) sp[sn] >> (bits - shift);
+ }
+ }
+ if (limb != 0)
+ rp[rn++] = limb;
+ else
+ rn = mpn_normalized_size (rp, rn);
+ return rn;
+}
+
+/* Result is usually normalized, except for all-zero input, in which
+ case a single zero limb is written at *RP, and 1 is returned. */
+static mp_size_t
+mpn_set_str_other (mp_ptr rp, const unsigned char *sp, size_t sn,
+ mp_limb_t b, const struct mpn_base_info *info)
+{
+ mp_size_t rn;
+ mp_limb_t w;
+ unsigned k;
+ size_t j;
+
+ assert (sn > 0);
+
+ k = 1 + (sn - 1) % info->exp;
+
+ j = 0;
+ w = sp[j++];
+ while (--k != 0)
+ w = w * b + sp[j++];
+
+ rp[0] = w;
+
+ for (rn = 1; j < sn;)
+ {
+ mp_limb_t cy;
+
+ w = sp[j++];
+ for (k = 1; k < info->exp; k++)
+ w = w * b + sp[j++];
+
+ cy = mpn_mul_1 (rp, rp, rn, info->bb);
+ cy += mpn_add_1 (rp, rp, rn, w);
+ if (cy > 0)
+ rp[rn++] = cy;
+ }
+ assert (j == sn);
+
+ return rn;
+}
+
+mp_size_t
+mpn_set_str (mp_ptr rp, const unsigned char *sp, size_t sn, int base)
+{
+ unsigned bits;
+
+ if (sn == 0)
+ return 0;
+
+ bits = mpn_base_power_of_two_p (base);
+ if (bits)
+ return mpn_set_str_bits (rp, sp, sn, bits);
+ else
+ {
+ struct mpn_base_info info;
+
+ mpn_get_base_info (&info, base);
+ return mpn_set_str_other (rp, sp, sn, base, &info);
+ }
+}
+
+
+/* MPZ interface */
+void
+mpz_init (mpz_t r)
+{
+ static const mp_limb_t dummy_limb = GMP_LIMB_MAX & 0xc1a0;
+
+ r->_mp_alloc = 0;
+ r->_mp_size = 0;
+ r->_mp_d = (mp_ptr) &dummy_limb;
+}
+
+/* The utility of this function is a bit limited, since many functions
+ assigns the result variable using mpz_swap. */
+void
+mpz_init2 (mpz_t r, mp_bitcnt_t bits)
+{
+ mp_size_t rn;
+
+ bits -= (bits != 0); /* Round down, except if 0 */
+ rn = 1 + bits / GMP_LIMB_BITS;
+
+ r->_mp_alloc = rn;
+ r->_mp_size = 0;
+ r->_mp_d = gmp_alloc_limbs (rn);
+}
+
+void
+mpz_clear (mpz_t r)
+{
+ if (r->_mp_alloc)
+ gmp_free_limbs (r->_mp_d, r->_mp_alloc);
+}
+
+static mp_ptr
+mpz_realloc (mpz_t r, mp_size_t size)
+{
+ size = GMP_MAX (size, 1);
+
+ if (r->_mp_alloc)
+ r->_mp_d = gmp_realloc_limbs (r->_mp_d, r->_mp_alloc, size);
+ else
+ r->_mp_d = gmp_alloc_limbs (size);
+ r->_mp_alloc = size;
+
+ if (GMP_ABS (r->_mp_size) > size)
+ r->_mp_size = 0;
+
+ return r->_mp_d;
+}
+
+/* Realloc for an mpz_t WHAT if it has less than NEEDED limbs. */
+#define MPZ_REALLOC(z,n) ((n) > (z)->_mp_alloc \
+ ? mpz_realloc(z,n) \
+ : (z)->_mp_d)
+
+/* MPZ assignment and basic conversions. */
+void
+mpz_set_si (mpz_t r, signed long int x)
+{
+ if (x >= 0)
+ mpz_set_ui (r, x);
+ else /* (x < 0) */
+ if (GMP_LIMB_BITS < GMP_ULONG_BITS)
+ {
+ mpz_set_ui (r, GMP_NEG_CAST (unsigned long int, x));
+ mpz_neg (r, r);
+ }
+ else
+ {
+ r->_mp_size = -1;
+ MPZ_REALLOC (r, 1)[0] = GMP_NEG_CAST (unsigned long int, x);
+ }
+}
+
+void
+mpz_set_ui (mpz_t r, unsigned long int x)
+{
+ if (x > 0)
+ {
+ r->_mp_size = 1;
+ MPZ_REALLOC (r, 1)[0] = x;
+ if (GMP_LIMB_BITS < GMP_ULONG_BITS)
+ {
+ int LOCAL_GMP_LIMB_BITS = GMP_LIMB_BITS;
+ while (x >>= LOCAL_GMP_LIMB_BITS)
+ {
+ ++ r->_mp_size;
+ MPZ_REALLOC (r, r->_mp_size)[r->_mp_size - 1] = x;
+ }
+ }
+ }
+ else
+ r->_mp_size = 0;
+}
+
+void
+mpz_set (mpz_t r, const mpz_t x)
+{
+ /* Allow the NOP r == x */
+ if (r != x)
+ {
+ mp_size_t n;
+ mp_ptr rp;
+
+ n = GMP_ABS (x->_mp_size);
+ rp = MPZ_REALLOC (r, n);
+
+ mpn_copyi (rp, x->_mp_d, n);
+ r->_mp_size = x->_mp_size;
+ }
+}
+
+void
+mpz_init_set_si (mpz_t r, signed long int x)
+{
+ mpz_init (r);
+ mpz_set_si (r, x);
+}
+
+void
+mpz_init_set_ui (mpz_t r, unsigned long int x)
+{
+ mpz_init (r);
+ mpz_set_ui (r, x);
+}
+
+void
+mpz_init_set (mpz_t r, const mpz_t x)
+{
+ mpz_init (r);
+ mpz_set (r, x);
+}
+
+int
+mpz_fits_slong_p (const mpz_t u)
+{
+ return mpz_cmp_si (u, LONG_MAX) <= 0 && mpz_cmp_si (u, LONG_MIN) >= 0;
+}
+
+static int
+mpn_absfits_ulong_p (mp_srcptr up, mp_size_t un)
+{
+ int ulongsize = GMP_ULONG_BITS / GMP_LIMB_BITS;
+ mp_limb_t ulongrem = 0;
+
+ if (GMP_ULONG_BITS % GMP_LIMB_BITS != 0)
+ ulongrem = (mp_limb_t) (ULONG_MAX >> GMP_LIMB_BITS * ulongsize) + 1;
+
+ return un <= ulongsize || (up[ulongsize] < ulongrem && un == ulongsize + 1);
+}
+
+int
+mpz_fits_ulong_p (const mpz_t u)
+{
+ mp_size_t us = u->_mp_size;
+
+ return us >= 0 && mpn_absfits_ulong_p (u->_mp_d, us);
+}
+
+int
+mpz_fits_sint_p (const mpz_t u)
+{
+ return mpz_cmp_si (u, INT_MAX) <= 0 && mpz_cmp_si (u, INT_MIN) >= 0;
+}
+
+int
+mpz_fits_uint_p (const mpz_t u)
+{
+ return u->_mp_size >= 0 && mpz_cmpabs_ui (u, UINT_MAX) <= 0;
+}
+
+int
+mpz_fits_sshort_p (const mpz_t u)
+{
+ return mpz_cmp_si (u, SHRT_MAX) <= 0 && mpz_cmp_si (u, SHRT_MIN) >= 0;
+}
+
+int
+mpz_fits_ushort_p (const mpz_t u)
+{
+ return u->_mp_size >= 0 && mpz_cmpabs_ui (u, USHRT_MAX) <= 0;
+}
+
+long int
+mpz_get_si (const mpz_t u)
+{
+ unsigned long r = mpz_get_ui (u);
+ unsigned long c = -LONG_MAX - LONG_MIN;
+
+ if (u->_mp_size < 0)
+ /* This expression is necessary to properly handle -LONG_MIN */
+ return -(long) c - (long) ((r - c) & LONG_MAX);
+ else
+ return (long) (r & LONG_MAX);
+}
+
+unsigned long int
+mpz_get_ui (const mpz_t u)
+{
+ if (GMP_LIMB_BITS < GMP_ULONG_BITS)
+ {
+ int LOCAL_GMP_LIMB_BITS = GMP_LIMB_BITS;
+ unsigned long r = 0;
+ mp_size_t n = GMP_ABS (u->_mp_size);
+ n = GMP_MIN (n, 1 + (mp_size_t) (GMP_ULONG_BITS - 1) / GMP_LIMB_BITS);
+ while (--n >= 0)
+ r = (r << LOCAL_GMP_LIMB_BITS) + u->_mp_d[n];
+ return r;
+ }
+
+ return u->_mp_size == 0 ? 0 : u->_mp_d[0];
+}
+
+size_t
+mpz_size (const mpz_t u)
+{
+ return GMP_ABS (u->_mp_size);
+}
+
+mp_limb_t
+mpz_getlimbn (const mpz_t u, mp_size_t n)
+{
+ if (n >= 0 && n < GMP_ABS (u->_mp_size))
+ return u->_mp_d[n];
+ else
+ return 0;
+}
+
+void
+mpz_realloc2 (mpz_t x, mp_bitcnt_t n)
+{
+ mpz_realloc (x, 1 + (n - (n != 0)) / GMP_LIMB_BITS);
+}
+
+mp_srcptr
+mpz_limbs_read (mpz_srcptr x)
+{
+ return x->_mp_d;
+}
+
+mp_ptr
+mpz_limbs_modify (mpz_t x, mp_size_t n)
+{
+ assert (n > 0);
+ return MPZ_REALLOC (x, n);
+}
+
+mp_ptr
+mpz_limbs_write (mpz_t x, mp_size_t n)
+{
+ return mpz_limbs_modify (x, n);
+}
+
+void
+mpz_limbs_finish (mpz_t x, mp_size_t xs)
+{
+ mp_size_t xn;
+ xn = mpn_normalized_size (x->_mp_d, GMP_ABS (xs));
+ x->_mp_size = xs < 0 ? -xn : xn;
+}
+
+static mpz_srcptr
+mpz_roinit_normal_n (mpz_t x, mp_srcptr xp, mp_size_t xs)
+{
+ x->_mp_alloc = 0;
+ x->_mp_d = (mp_ptr) xp;
+ x->_mp_size = xs;
+ return x;
+}
+
+mpz_srcptr
+mpz_roinit_n (mpz_t x, mp_srcptr xp, mp_size_t xs)
+{
+ mpz_roinit_normal_n (x, xp, xs);
+ mpz_limbs_finish (x, xs);
+ return x;
+}
+
+
+/* Conversions and comparison to double. */
+void
+mpz_set_d (mpz_t r, double x)
+{
+ int sign;
+ mp_ptr rp;
+ mp_size_t rn, i;
+ double B;
+ double Bi;
+ mp_limb_t f;
+
+ /* x != x is true when x is a NaN, and x == x * 0.5 is true when x is
+ zero or infinity. */
+ if (x != x || x == x * 0.5)
+ {
+ r->_mp_size = 0;
+ return;
+ }
+
+ sign = x < 0.0 ;
+ if (sign)
+ x = - x;
+
+ if (x < 1.0)
+ {
+ r->_mp_size = 0;
+ return;
+ }
+ B = 4.0 * (double) (GMP_LIMB_HIGHBIT >> 1);
+ Bi = 1.0 / B;
+ for (rn = 1; x >= B; rn++)
+ x *= Bi;
+
+ rp = MPZ_REALLOC (r, rn);
+
+ f = (mp_limb_t) x;
+ x -= f;
+ assert (x < 1.0);
+ i = rn-1;
+ rp[i] = f;
+ while (--i >= 0)
+ {
+ x = B * x;
+ f = (mp_limb_t) x;
+ x -= f;
+ assert (x < 1.0);
+ rp[i] = f;
+ }
+
+ r->_mp_size = sign ? - rn : rn;
+}
+
+void
+mpz_init_set_d (mpz_t r, double x)
+{
+ mpz_init (r);
+ mpz_set_d (r, x);
+}
+
+double
+mpz_get_d (const mpz_t u)
+{
+ int m;
+ mp_limb_t l;
+ mp_size_t un;
+ double x;
+ double B = 4.0 * (double) (GMP_LIMB_HIGHBIT >> 1);
+
+ un = GMP_ABS (u->_mp_size);
+
+ if (un == 0)
+ return 0.0;
+
+ l = u->_mp_d[--un];
+ gmp_clz (m, l);
+ m = m + GMP_DBL_MANT_BITS - GMP_LIMB_BITS;
+ if (m < 0)
+ l &= GMP_LIMB_MAX << -m;
+
+ for (x = l; --un >= 0;)
+ {
+ x = B*x;
+ if (m > 0) {
+ l = u->_mp_d[un];
+ m -= GMP_LIMB_BITS;
+ if (m < 0)
+ l &= GMP_LIMB_MAX << -m;
+ x += l;
+ }
+ }
+
+ if (u->_mp_size < 0)
+ x = -x;
+
+ return x;
+}
+
+int
+mpz_cmpabs_d (const mpz_t x, double d)
+{
+ mp_size_t xn;
+ double B, Bi;
+ mp_size_t i;
+
+ xn = x->_mp_size;
+ d = GMP_ABS (d);
+
+ if (xn != 0)
+ {
+ xn = GMP_ABS (xn);
+
+ B = 4.0 * (double) (GMP_LIMB_HIGHBIT >> 1);
+ Bi = 1.0 / B;
+
+ /* Scale d so it can be compared with the top limb. */
+ for (i = 1; i < xn; i++)
+ d *= Bi;
+
+ if (d >= B)
+ return -1;
+
+ /* Compare floor(d) to top limb, subtract and cancel when equal. */
+ for (i = xn; i-- > 0;)
+ {
+ mp_limb_t f, xl;
+
+ f = (mp_limb_t) d;
+ xl = x->_mp_d[i];
+ if (xl > f)
+ return 1;
+ else if (xl < f)
+ return -1;
+ d = B * (d - f);
+ }
+ }
+ return - (d > 0.0);
+}
+
+int
+mpz_cmp_d (const mpz_t x, double d)
+{
+ if (x->_mp_size < 0)
+ {
+ if (d >= 0.0)
+ return -1;
+ else
+ return -mpz_cmpabs_d (x, d);
+ }
+ else
+ {
+ if (d < 0.0)
+ return 1;
+ else
+ return mpz_cmpabs_d (x, d);
+ }
+}
+
+
+/* MPZ comparisons and the like. */
+int
+mpz_sgn (const mpz_t u)
+{
+ return GMP_CMP (u->_mp_size, 0);
+}
+
+int
+mpz_cmp_si (const mpz_t u, long v)
+{
+ mp_size_t usize = u->_mp_size;
+
+ if (v >= 0)
+ return mpz_cmp_ui (u, v);
+ else if (usize >= 0)
+ return 1;
+ else
+ return - mpz_cmpabs_ui (u, GMP_NEG_CAST (unsigned long int, v));
+}
+
+int
+mpz_cmp_ui (const mpz_t u, unsigned long v)
+{
+ mp_size_t usize = u->_mp_size;
+
+ if (usize < 0)
+ return -1;
+ else
+ return mpz_cmpabs_ui (u, v);
+}
+
+int
+mpz_cmp (const mpz_t a, const mpz_t b)
+{
+ mp_size_t asize = a->_mp_size;
+ mp_size_t bsize = b->_mp_size;
+
+ if (asize != bsize)
+ return (asize < bsize) ? -1 : 1;
+ else if (asize >= 0)
+ return mpn_cmp (a->_mp_d, b->_mp_d, asize);
+ else
+ return mpn_cmp (b->_mp_d, a->_mp_d, -asize);
+}
+
+int
+mpz_cmpabs_ui (const mpz_t u, unsigned long v)
+{
+ mp_size_t un = GMP_ABS (u->_mp_size);
+
+ if (! mpn_absfits_ulong_p (u->_mp_d, un))
+ return 1;
+ else
+ {
+ unsigned long uu = mpz_get_ui (u);
+ return GMP_CMP(uu, v);
+ }
+}
+
+int
+mpz_cmpabs (const mpz_t u, const mpz_t v)
+{
+ return mpn_cmp4 (u->_mp_d, GMP_ABS (u->_mp_size),
+ v->_mp_d, GMP_ABS (v->_mp_size));
+}
+
+void
+mpz_abs (mpz_t r, const mpz_t u)
+{
+ mpz_set (r, u);
+ r->_mp_size = GMP_ABS (r->_mp_size);
+}
+
+void
+mpz_neg (mpz_t r, const mpz_t u)
+{
+ mpz_set (r, u);
+ r->_mp_size = -r->_mp_size;
+}
+
+void
+mpz_swap (mpz_t u, mpz_t v)
+{
+ MP_SIZE_T_SWAP (u->_mp_alloc, v->_mp_alloc);
+ MPN_PTR_SWAP (u->_mp_d, u->_mp_size, v->_mp_d, v->_mp_size);
+}
+
+
+/* MPZ addition and subtraction */
+
+
+void
+mpz_add_ui (mpz_t r, const mpz_t a, unsigned long b)
+{
+ mpz_t bb;
+ mpz_init_set_ui (bb, b);
+ mpz_add (r, a, bb);
+ mpz_clear (bb);
+}
+
+void
+mpz_sub_ui (mpz_t r, const mpz_t a, unsigned long b)
+{
+ mpz_ui_sub (r, b, a);
+ mpz_neg (r, r);
+}
+
+void
+mpz_ui_sub (mpz_t r, unsigned long a, const mpz_t b)
+{
+ mpz_neg (r, b);
+ mpz_add_ui (r, r, a);
+}
+
+static mp_size_t
+mpz_abs_add (mpz_t r, const mpz_t a, const mpz_t b)
+{
+ mp_size_t an = GMP_ABS (a->_mp_size);
+ mp_size_t bn = GMP_ABS (b->_mp_size);
+ mp_ptr rp;
+ mp_limb_t cy;
+
+ if (an < bn)
+ {
+ MPZ_SRCPTR_SWAP (a, b);
+ MP_SIZE_T_SWAP (an, bn);
+ }
+
+ rp = MPZ_REALLOC (r, an + 1);
+ cy = mpn_add (rp, a->_mp_d, an, b->_mp_d, bn);
+
+ rp[an] = cy;
+
+ return an + cy;
+}
+
+static mp_size_t
+mpz_abs_sub (mpz_t r, const mpz_t a, const mpz_t b)
+{
+ mp_size_t an = GMP_ABS (a->_mp_size);
+ mp_size_t bn = GMP_ABS (b->_mp_size);
+ int cmp;
+ mp_ptr rp;
+
+ cmp = mpn_cmp4 (a->_mp_d, an, b->_mp_d, bn);
+ if (cmp > 0)
+ {
+ rp = MPZ_REALLOC (r, an);
+ gmp_assert_nocarry (mpn_sub (rp, a->_mp_d, an, b->_mp_d, bn));
+ return mpn_normalized_size (rp, an);
+ }
+ else if (cmp < 0)
+ {
+ rp = MPZ_REALLOC (r, bn);
+ gmp_assert_nocarry (mpn_sub (rp, b->_mp_d, bn, a->_mp_d, an));
+ return -mpn_normalized_size (rp, bn);
+ }
+ else
+ return 0;
+}
+
+void
+mpz_add (mpz_t r, const mpz_t a, const mpz_t b)
+{
+ mp_size_t rn;
+
+ if ( (a->_mp_size ^ b->_mp_size) >= 0)
+ rn = mpz_abs_add (r, a, b);
+ else
+ rn = mpz_abs_sub (r, a, b);
+
+ r->_mp_size = a->_mp_size >= 0 ? rn : - rn;
+}
+
+void
+mpz_sub (mpz_t r, const mpz_t a, const mpz_t b)
+{
+ mp_size_t rn;
+
+ if ( (a->_mp_size ^ b->_mp_size) >= 0)
+ rn = mpz_abs_sub (r, a, b);
+ else
+ rn = mpz_abs_add (r, a, b);
+
+ r->_mp_size = a->_mp_size >= 0 ? rn : - rn;
+}
+
+
+/* MPZ multiplication */
+void
+mpz_mul_si (mpz_t r, const mpz_t u, long int v)
+{
+ if (v < 0)
+ {
+ mpz_mul_ui (r, u, GMP_NEG_CAST (unsigned long int, v));
+ mpz_neg (r, r);
+ }
+ else
+ mpz_mul_ui (r, u, v);
+}
+
+void
+mpz_mul_ui (mpz_t r, const mpz_t u, unsigned long int v)
+{
+ mpz_t vv;
+ mpz_init_set_ui (vv, v);
+ mpz_mul (r, u, vv);
+ mpz_clear (vv);
+ return;
+}
+
+void
+mpz_mul (mpz_t r, const mpz_t u, const mpz_t v)
+{
+ int sign;
+ mp_size_t un, vn, rn;
+ mpz_t t;
+ mp_ptr tp;
+
+ un = u->_mp_size;
+ vn = v->_mp_size;
+
+ if (un == 0 || vn == 0)
+ {
+ r->_mp_size = 0;
+ return;
+ }
+
+ sign = (un ^ vn) < 0;
+
+ un = GMP_ABS (un);
+ vn = GMP_ABS (vn);
+
+ mpz_init2 (t, (un + vn) * GMP_LIMB_BITS);
+
+ tp = t->_mp_d;
+ if (un >= vn)
+ mpn_mul (tp, u->_mp_d, un, v->_mp_d, vn);
+ else
+ mpn_mul (tp, v->_mp_d, vn, u->_mp_d, un);
+
+ rn = un + vn;
+ rn -= tp[rn-1] == 0;
+
+ t->_mp_size = sign ? - rn : rn;
+ mpz_swap (r, t);
+ mpz_clear (t);
+}
+
+void
+mpz_mul_2exp (mpz_t r, const mpz_t u, mp_bitcnt_t bits)
+{
+ mp_size_t un, rn;
+ mp_size_t limbs;
+ unsigned shift;
+ mp_ptr rp;
+
+ un = GMP_ABS (u->_mp_size);
+ if (un == 0)
+ {
+ r->_mp_size = 0;
+ return;
+ }
+
+ limbs = bits / GMP_LIMB_BITS;
+ shift = bits % GMP_LIMB_BITS;
+
+ rn = un + limbs + (shift > 0);
+ rp = MPZ_REALLOC (r, rn);
+ if (shift > 0)
+ {
+ mp_limb_t cy = mpn_lshift (rp + limbs, u->_mp_d, un, shift);
+ rp[rn-1] = cy;
+ rn -= (cy == 0);
+ }
+ else
+ mpn_copyd (rp + limbs, u->_mp_d, un);
+
+ mpn_zero (rp, limbs);
+
+ r->_mp_size = (u->_mp_size < 0) ? - rn : rn;
+}
+
+void
+mpz_addmul_ui (mpz_t r, const mpz_t u, unsigned long int v)
+{
+ mpz_t t;
+ mpz_init_set_ui (t, v);
+ mpz_mul (t, u, t);
+ mpz_add (r, r, t);
+ mpz_clear (t);
+}
+
+void
+mpz_submul_ui (mpz_t r, const mpz_t u, unsigned long int v)
+{
+ mpz_t t;
+ mpz_init_set_ui (t, v);
+ mpz_mul (t, u, t);
+ mpz_sub (r, r, t);
+ mpz_clear (t);
+}
+
+void
+mpz_addmul (mpz_t r, const mpz_t u, const mpz_t v)
+{
+ mpz_t t;
+ mpz_init (t);
+ mpz_mul (t, u, v);
+ mpz_add (r, r, t);
+ mpz_clear (t);
+}
+
+void
+mpz_submul (mpz_t r, const mpz_t u, const mpz_t v)
+{
+ mpz_t t;
+ mpz_init (t);
+ mpz_mul (t, u, v);
+ mpz_sub (r, r, t);
+ mpz_clear (t);
+}
+
+
+/* MPZ division */
+enum mpz_div_round_mode { GMP_DIV_FLOOR, GMP_DIV_CEIL, GMP_DIV_TRUNC };
+
+/* Allows q or r to be zero. Returns 1 iff remainder is non-zero. */
+static int
+mpz_div_qr (mpz_t q, mpz_t r,
+ const mpz_t n, const mpz_t d, enum mpz_div_round_mode mode)
+{
+ mp_size_t ns, ds, nn, dn, qs;
+ ns = n->_mp_size;
+ ds = d->_mp_size;
+
+ if (ds == 0)
+ gmp_die("mpz_div_qr: Divide by zero.");
+
+ if (ns == 0)
+ {
+ if (q)
+ q->_mp_size = 0;
+ if (r)
+ r->_mp_size = 0;
+ return 0;
+ }
+
+ nn = GMP_ABS (ns);
+ dn = GMP_ABS (ds);
+
+ qs = ds ^ ns;
+
+ if (nn < dn)
+ {
+ if (mode == GMP_DIV_CEIL && qs >= 0)
+ {
+ /* q = 1, r = n - d */
+ if (r)
+ mpz_sub (r, n, d);
+ if (q)
+ mpz_set_ui (q, 1);
+ }
+ else if (mode == GMP_DIV_FLOOR && qs < 0)
+ {
+ /* q = -1, r = n + d */
+ if (r)
+ mpz_add (r, n, d);
+ if (q)
+ mpz_set_si (q, -1);
+ }
+ else
+ {
+ /* q = 0, r = d */
+ if (r)
+ mpz_set (r, n);
+ if (q)
+ q->_mp_size = 0;
+ }
+ return 1;
+ }
+ else
+ {
+ mp_ptr np, qp;
+ mp_size_t qn, rn;
+ mpz_t tq, tr;
+
+ mpz_init_set (tr, n);
+ np = tr->_mp_d;
+
+ qn = nn - dn + 1;
+
+ if (q)
+ {
+ mpz_init2 (tq, qn * GMP_LIMB_BITS);
+ qp = tq->_mp_d;
+ }
+ else
+ qp = NULL;
+
+ mpn_div_qr (qp, np, nn, d->_mp_d, dn);
+
+ if (qp)
+ {
+ qn -= (qp[qn-1] == 0);
+
+ tq->_mp_size = qs < 0 ? -qn : qn;
+ }
+ rn = mpn_normalized_size (np, dn);
+ tr->_mp_size = ns < 0 ? - rn : rn;
+
+ if (mode == GMP_DIV_FLOOR && qs < 0 && rn != 0)
+ {
+ if (q)
+ mpz_sub_ui (tq, tq, 1);
+ if (r)
+ mpz_add (tr, tr, d);
+ }
+ else if (mode == GMP_DIV_CEIL && qs >= 0 && rn != 0)
+ {
+ if (q)
+ mpz_add_ui (tq, tq, 1);
+ if (r)
+ mpz_sub (tr, tr, d);
+ }
+
+ if (q)
+ {
+ mpz_swap (tq, q);
+ mpz_clear (tq);
+ }
+ if (r)
+ mpz_swap (tr, r);
+
+ mpz_clear (tr);
+
+ return rn != 0;
+ }
+}
+
+void
+mpz_cdiv_qr (mpz_t q, mpz_t r, const mpz_t n, const mpz_t d)
+{
+ mpz_div_qr (q, r, n, d, GMP_DIV_CEIL);
+}
+
+void
+mpz_fdiv_qr (mpz_t q, mpz_t r, const mpz_t n, const mpz_t d)
+{
+ mpz_div_qr (q, r, n, d, GMP_DIV_FLOOR);
+}
+
+void
+mpz_tdiv_qr (mpz_t q, mpz_t r, const mpz_t n, const mpz_t d)
+{
+ mpz_div_qr (q, r, n, d, GMP_DIV_TRUNC);
+}
+
+void
+mpz_cdiv_q (mpz_t q, const mpz_t n, const mpz_t d)
+{
+ mpz_div_qr (q, NULL, n, d, GMP_DIV_CEIL);
+}
+
+void
+mpz_fdiv_q (mpz_t q, const mpz_t n, const mpz_t d)
+{
+ mpz_div_qr (q, NULL, n, d, GMP_DIV_FLOOR);
+}
+
+void
+mpz_tdiv_q (mpz_t q, const mpz_t n, const mpz_t d)
+{
+ mpz_div_qr (q, NULL, n, d, GMP_DIV_TRUNC);
+}
+
+void
+mpz_cdiv_r (mpz_t r, const mpz_t n, const mpz_t d)
+{
+ mpz_div_qr (NULL, r, n, d, GMP_DIV_CEIL);
+}
+
+void
+mpz_fdiv_r (mpz_t r, const mpz_t n, const mpz_t d)
+{
+ mpz_div_qr (NULL, r, n, d, GMP_DIV_FLOOR);
+}
+
+void
+mpz_tdiv_r (mpz_t r, const mpz_t n, const mpz_t d)
+{
+ mpz_div_qr (NULL, r, n, d, GMP_DIV_TRUNC);
+}
+
+void
+mpz_mod (mpz_t r, const mpz_t n, const mpz_t d)
+{
+ mpz_div_qr (NULL, r, n, d, d->_mp_size >= 0 ? GMP_DIV_FLOOR : GMP_DIV_CEIL);
+}
+
+static void
+mpz_div_q_2exp (mpz_t q, const mpz_t u, mp_bitcnt_t bit_index,
+ enum mpz_div_round_mode mode)
+{
+ mp_size_t un, qn;
+ mp_size_t limb_cnt;
+ mp_ptr qp;
+ int adjust;
+
+ un = u->_mp_size;
+ if (un == 0)
+ {
+ q->_mp_size = 0;
+ return;
+ }
+ limb_cnt = bit_index / GMP_LIMB_BITS;
+ qn = GMP_ABS (un) - limb_cnt;
+ bit_index %= GMP_LIMB_BITS;
+
+ if (mode == ((un > 0) ? GMP_DIV_CEIL : GMP_DIV_FLOOR)) /* un != 0 here. */
+ /* Note: Below, the final indexing at limb_cnt is valid because at
+ that point we have qn > 0. */
+ adjust = (qn <= 0
+ || !mpn_zero_p (u->_mp_d, limb_cnt)
+ || (u->_mp_d[limb_cnt]
+ & (((mp_limb_t) 1 << bit_index) - 1)));
+ else
+ adjust = 0;
+
+ if (qn <= 0)
+ qn = 0;
+ else
+ {
+ qp = MPZ_REALLOC (q, qn);
+
+ if (bit_index != 0)
+ {
+ mpn_rshift (qp, u->_mp_d + limb_cnt, qn, bit_index);
+ qn -= qp[qn - 1] == 0;
+ }
+ else
+ {
+ mpn_copyi (qp, u->_mp_d + limb_cnt, qn);
+ }
+ }
+
+ q->_mp_size = qn;
+
+ if (adjust)
+ mpz_add_ui (q, q, 1);
+ if (un < 0)
+ mpz_neg (q, q);
+}
+
+static void
+mpz_div_r_2exp (mpz_t r, const mpz_t u, mp_bitcnt_t bit_index,
+ enum mpz_div_round_mode mode)
+{
+ mp_size_t us, un, rn;
+ mp_ptr rp;
+ mp_limb_t mask;
+
+ us = u->_mp_size;
+ if (us == 0 || bit_index == 0)
+ {
+ r->_mp_size = 0;
+ return;
+ }
+ rn = (bit_index + GMP_LIMB_BITS - 1) / GMP_LIMB_BITS;
+ assert (rn > 0);
+
+ rp = MPZ_REALLOC (r, rn);
+ un = GMP_ABS (us);
+
+ mask = GMP_LIMB_MAX >> (rn * GMP_LIMB_BITS - bit_index);
+
+ if (rn > un)
+ {
+ /* Quotient (with truncation) is zero, and remainder is
+ non-zero */
+ if (mode == ((us > 0) ? GMP_DIV_CEIL : GMP_DIV_FLOOR)) /* us != 0 here. */
+ {
+ /* Have to negate and sign extend. */
+ mp_size_t i;
+
+ gmp_assert_nocarry (! mpn_neg (rp, u->_mp_d, un));
+ for (i = un; i < rn - 1; i++)
+ rp[i] = GMP_LIMB_MAX;
+
+ rp[rn-1] = mask;
+ us = -us;
+ }
+ else
+ {
+ /* Just copy */
+ if (r != u)
+ mpn_copyi (rp, u->_mp_d, un);
+
+ rn = un;
+ }
+ }
+ else
+ {
+ if (r != u)
+ mpn_copyi (rp, u->_mp_d, rn - 1);
+
+ rp[rn-1] = u->_mp_d[rn-1] & mask;
+
+ if (mode == ((us > 0) ? GMP_DIV_CEIL : GMP_DIV_FLOOR)) /* us != 0 here. */
+ {
+ /* If r != 0, compute 2^{bit_count} - r. */
+ mpn_neg (rp, rp, rn);
+
+ rp[rn-1] &= mask;
+
+ /* us is not used for anything else, so we can modify it
+ here to indicate flipped sign. */
+ us = -us;
+ }
+ }
+ rn = mpn_normalized_size (rp, rn);
+ r->_mp_size = us < 0 ? -rn : rn;
+}
+
+void
+mpz_cdiv_q_2exp (mpz_t r, const mpz_t u, mp_bitcnt_t cnt)
+{
+ mpz_div_q_2exp (r, u, cnt, GMP_DIV_CEIL);
+}
+
+void
+mpz_fdiv_q_2exp (mpz_t r, const mpz_t u, mp_bitcnt_t cnt)
+{
+ mpz_div_q_2exp (r, u, cnt, GMP_DIV_FLOOR);
+}
+
+void
+mpz_tdiv_q_2exp (mpz_t r, const mpz_t u, mp_bitcnt_t cnt)
+{
+ mpz_div_q_2exp (r, u, cnt, GMP_DIV_TRUNC);
+}
+
+void
+mpz_cdiv_r_2exp (mpz_t r, const mpz_t u, mp_bitcnt_t cnt)
+{
+ mpz_div_r_2exp (r, u, cnt, GMP_DIV_CEIL);
+}
+
+void
+mpz_fdiv_r_2exp (mpz_t r, const mpz_t u, mp_bitcnt_t cnt)
+{
+ mpz_div_r_2exp (r, u, cnt, GMP_DIV_FLOOR);
+}
+
+void
+mpz_tdiv_r_2exp (mpz_t r, const mpz_t u, mp_bitcnt_t cnt)
+{
+ mpz_div_r_2exp (r, u, cnt, GMP_DIV_TRUNC);
+}
+
+void
+mpz_divexact (mpz_t q, const mpz_t n, const mpz_t d)
+{
+ gmp_assert_nocarry (mpz_div_qr (q, NULL, n, d, GMP_DIV_TRUNC));
+}
+
+int
+mpz_divisible_p (const mpz_t n, const mpz_t d)
+{
+ return mpz_div_qr (NULL, NULL, n, d, GMP_DIV_TRUNC) == 0;
+}
+
+int
+mpz_congruent_p (const mpz_t a, const mpz_t b, const mpz_t m)
+{
+ mpz_t t;
+ int res;
+
+ /* a == b (mod 0) iff a == b */
+ if (mpz_sgn (m) == 0)
+ return (mpz_cmp (a, b) == 0);
+
+ mpz_init (t);
+ mpz_sub (t, a, b);
+ res = mpz_divisible_p (t, m);
+ mpz_clear (t);
+
+ return res;
+}
+
+static unsigned long
+mpz_div_qr_ui (mpz_t q, mpz_t r,
+ const mpz_t n, unsigned long d, enum mpz_div_round_mode mode)
+{
+ unsigned long ret;
+ mpz_t rr, dd;
+
+ mpz_init (rr);
+ mpz_init_set_ui (dd, d);
+ mpz_div_qr (q, rr, n, dd, mode);
+ mpz_clear (dd);
+ ret = mpz_get_ui (rr);
+
+ if (r)
+ mpz_swap (r, rr);
+ mpz_clear (rr);
+
+ return ret;
+}
+
+unsigned long
+mpz_cdiv_qr_ui (mpz_t q, mpz_t r, const mpz_t n, unsigned long d)
+{
+ return mpz_div_qr_ui (q, r, n, d, GMP_DIV_CEIL);
+}
+
+unsigned long
+mpz_fdiv_qr_ui (mpz_t q, mpz_t r, const mpz_t n, unsigned long d)
+{
+ return mpz_div_qr_ui (q, r, n, d, GMP_DIV_FLOOR);
+}
+
+unsigned long
+mpz_tdiv_qr_ui (mpz_t q, mpz_t r, const mpz_t n, unsigned long d)
+{
+ return mpz_div_qr_ui (q, r, n, d, GMP_DIV_TRUNC);
+}
+
+unsigned long
+mpz_cdiv_q_ui (mpz_t q, const mpz_t n, unsigned long d)
+{
+ return mpz_div_qr_ui (q, NULL, n, d, GMP_DIV_CEIL);
+}
+
+unsigned long
+mpz_fdiv_q_ui (mpz_t q, const mpz_t n, unsigned long d)
+{
+ return mpz_div_qr_ui (q, NULL, n, d, GMP_DIV_FLOOR);
+}
+
+unsigned long
+mpz_tdiv_q_ui (mpz_t q, const mpz_t n, unsigned long d)
+{
+ return mpz_div_qr_ui (q, NULL, n, d, GMP_DIV_TRUNC);
+}
+
+unsigned long
+mpz_cdiv_r_ui (mpz_t r, const mpz_t n, unsigned long d)
+{
+ return mpz_div_qr_ui (NULL, r, n, d, GMP_DIV_CEIL);
+}
+unsigned long
+mpz_fdiv_r_ui (mpz_t r, const mpz_t n, unsigned long d)
+{
+ return mpz_div_qr_ui (NULL, r, n, d, GMP_DIV_FLOOR);
+}
+unsigned long
+mpz_tdiv_r_ui (mpz_t r, const mpz_t n, unsigned long d)
+{
+ return mpz_div_qr_ui (NULL, r, n, d, GMP_DIV_TRUNC);
+}
+
+unsigned long
+mpz_cdiv_ui (const mpz_t n, unsigned long d)
+{
+ return mpz_div_qr_ui (NULL, NULL, n, d, GMP_DIV_CEIL);
+}
+
+unsigned long
+mpz_fdiv_ui (const mpz_t n, unsigned long d)
+{
+ return mpz_div_qr_ui (NULL, NULL, n, d, GMP_DIV_FLOOR);
+}
+
+unsigned long
+mpz_tdiv_ui (const mpz_t n, unsigned long d)
+{
+ return mpz_div_qr_ui (NULL, NULL, n, d, GMP_DIV_TRUNC);
+}
+
+unsigned long
+mpz_mod_ui (mpz_t r, const mpz_t n, unsigned long d)
+{
+ return mpz_div_qr_ui (NULL, r, n, d, GMP_DIV_FLOOR);
+}
+
+void
+mpz_divexact_ui (mpz_t q, const mpz_t n, unsigned long d)
+{
+ gmp_assert_nocarry (mpz_div_qr_ui (q, NULL, n, d, GMP_DIV_TRUNC));
+}
+
+int
+mpz_divisible_ui_p (const mpz_t n, unsigned long d)
+{
+ return mpz_div_qr_ui (NULL, NULL, n, d, GMP_DIV_TRUNC) == 0;
+}
+
+
+/* GCD */
+static mp_limb_t
+mpn_gcd_11 (mp_limb_t u, mp_limb_t v)
+{
+ unsigned shift;
+
+ assert ( (u | v) > 0);
+
+ if (u == 0)
+ return v;
+ else if (v == 0)
+ return u;
+
+ gmp_ctz (shift, u | v);
+
+ u >>= shift;
+ v >>= shift;
+
+ if ( (u & 1) == 0)
+ MP_LIMB_T_SWAP (u, v);
+
+ while ( (v & 1) == 0)
+ v >>= 1;
+
+ while (u != v)
+ {
+ if (u > v)
+ {
+ u -= v;
+ do
+ u >>= 1;
+ while ( (u & 1) == 0);
+ }
+ else
+ {
+ v -= u;
+ do
+ v >>= 1;
+ while ( (v & 1) == 0);
+ }
+ }
+ return u << shift;
+}
+
+unsigned long
+mpz_gcd_ui (mpz_t g, const mpz_t u, unsigned long v)
+{
+ mpz_t t;
+ mpz_init_set_ui(t, v);
+ mpz_gcd (t, u, t);
+ if (v > 0)
+ v = mpz_get_ui (t);
+
+ if (g)
+ mpz_swap (t, g);
+
+ mpz_clear (t);
+
+ return v;
+}
+
+static mp_bitcnt_t
+mpz_make_odd (mpz_t r)
+{
+ mp_bitcnt_t shift;
+
+ assert (r->_mp_size > 0);
+ /* Count trailing zeros, equivalent to mpn_scan1, because we know that there is a 1 */
+ shift = mpn_scan1 (r->_mp_d, 0);
+ mpz_tdiv_q_2exp (r, r, shift);
+
+ return shift;
+}
+
+void
+mpz_gcd (mpz_t g, const mpz_t u, const mpz_t v)
+{
+ mpz_t tu, tv;
+ mp_bitcnt_t uz, vz, gz;
+
+ if (u->_mp_size == 0)
+ {
+ mpz_abs (g, v);
+ return;
+ }
+ if (v->_mp_size == 0)
+ {
+ mpz_abs (g, u);
+ return;
+ }
+
+ mpz_init (tu);
+ mpz_init (tv);
+
+ mpz_abs (tu, u);
+ uz = mpz_make_odd (tu);
+ mpz_abs (tv, v);
+ vz = mpz_make_odd (tv);
+ gz = GMP_MIN (uz, vz);
+
+ if (tu->_mp_size < tv->_mp_size)
+ mpz_swap (tu, tv);
+
+ mpz_tdiv_r (tu, tu, tv);
+ if (tu->_mp_size == 0)
+ {
+ mpz_swap (g, tv);
+ }
+ else
+ for (;;)
+ {
+ int c;
+
+ mpz_make_odd (tu);
+ c = mpz_cmp (tu, tv);
+ if (c == 0)
+ {
+ mpz_swap (g, tu);
+ break;
+ }
+ if (c < 0)
+ mpz_swap (tu, tv);
+
+ if (tv->_mp_size == 1)
+ {
+ mp_limb_t *gp;
+
+ mpz_tdiv_r (tu, tu, tv);
+ gp = MPZ_REALLOC (g, 1); /* gp = mpz_limbs_modify (g, 1); */
+ *gp = mpn_gcd_11 (tu->_mp_d[0], tv->_mp_d[0]);
+
+ g->_mp_size = *gp != 0; /* mpz_limbs_finish (g, 1); */
+ break;
+ }
+ mpz_sub (tu, tu, tv);
+ }
+ mpz_clear (tu);
+ mpz_clear (tv);
+ mpz_mul_2exp (g, g, gz);
+}
+
+void
+mpz_gcdext (mpz_t g, mpz_t s, mpz_t t, const mpz_t u, const mpz_t v)
+{
+ mpz_t tu, tv, s0, s1, t0, t1;
+ mp_bitcnt_t uz, vz, gz;
+ mp_bitcnt_t power;
+
+ if (u->_mp_size == 0)
+ {
+ /* g = 0 u + sgn(v) v */
+ signed long sign = mpz_sgn (v);
+ mpz_abs (g, v);
+ if (s)
+ s->_mp_size = 0;
+ if (t)
+ mpz_set_si (t, sign);
+ return;
+ }
+
+ if (v->_mp_size == 0)
+ {
+ /* g = sgn(u) u + 0 v */
+ signed long sign = mpz_sgn (u);
+ mpz_abs (g, u);
+ if (s)
+ mpz_set_si (s, sign);
+ if (t)
+ t->_mp_size = 0;
+ return;
+ }
+
+ mpz_init (tu);
+ mpz_init (tv);
+ mpz_init (s0);
+ mpz_init (s1);
+ mpz_init (t0);
+ mpz_init (t1);
+
+ mpz_abs (tu, u);
+ uz = mpz_make_odd (tu);
+ mpz_abs (tv, v);
+ vz = mpz_make_odd (tv);
+ gz = GMP_MIN (uz, vz);
+
+ uz -= gz;
+ vz -= gz;
+
+ /* Cofactors corresponding to odd gcd. gz handled later. */
+ if (tu->_mp_size < tv->_mp_size)
+ {
+ mpz_swap (tu, tv);
+ MPZ_SRCPTR_SWAP (u, v);
+ MPZ_PTR_SWAP (s, t);
+ MP_BITCNT_T_SWAP (uz, vz);
+ }
+
+ /* Maintain
+ *
+ * u = t0 tu + t1 tv
+ * v = s0 tu + s1 tv
+ *
+ * where u and v denote the inputs with common factors of two
+ * eliminated, and det (s0, t0; s1, t1) = 2^p. Then
+ *
+ * 2^p tu = s1 u - t1 v
+ * 2^p tv = -s0 u + t0 v
+ */
+
+ /* After initial division, tu = q tv + tu', we have
+ *
+ * u = 2^uz (tu' + q tv)
+ * v = 2^vz tv
+ *
+ * or
+ *
+ * t0 = 2^uz, t1 = 2^uz q
+ * s0 = 0, s1 = 2^vz
+ */
+
+ mpz_tdiv_qr (t1, tu, tu, tv);
+ mpz_mul_2exp (t1, t1, uz);
+
+ mpz_setbit (s1, vz);
+ power = uz + vz;
+
+ if (tu->_mp_size > 0)
+ {
+ mp_bitcnt_t shift;
+ shift = mpz_make_odd (tu);
+ mpz_setbit (t0, uz + shift);
+ power += shift;
+
+ for (;;)
+ {
+ int c;
+ c = mpz_cmp (tu, tv);
+ if (c == 0)
+ break;
+
+ if (c < 0)
+ {
+ /* tv = tv' + tu
+ *
+ * u = t0 tu + t1 (tv' + tu) = (t0 + t1) tu + t1 tv'
+ * v = s0 tu + s1 (tv' + tu) = (s0 + s1) tu + s1 tv' */
+
+ mpz_sub (tv, tv, tu);
+ mpz_add (t0, t0, t1);
+ mpz_add (s0, s0, s1);
+
+ shift = mpz_make_odd (tv);
+ mpz_mul_2exp (t1, t1, shift);
+ mpz_mul_2exp (s1, s1, shift);
+ }
+ else
+ {
+ mpz_sub (tu, tu, tv);
+ mpz_add (t1, t0, t1);
+ mpz_add (s1, s0, s1);
+
+ shift = mpz_make_odd (tu);
+ mpz_mul_2exp (t0, t0, shift);
+ mpz_mul_2exp (s0, s0, shift);
+ }
+ power += shift;
+ }
+ }
+ else
+ mpz_setbit (t0, uz);
+
+ /* Now tv = odd part of gcd, and -s0 and t0 are corresponding
+ cofactors. */
+
+ mpz_mul_2exp (tv, tv, gz);
+ mpz_neg (s0, s0);
+
+ /* 2^p g = s0 u + t0 v. Eliminate one factor of two at a time. To
+ adjust cofactors, we need u / g and v / g */
+
+ mpz_divexact (s1, v, tv);
+ mpz_abs (s1, s1);
+ mpz_divexact (t1, u, tv);
+ mpz_abs (t1, t1);
+
+ while (power-- > 0)
+ {
+ /* s0 u + t0 v = (s0 - v/g) u - (t0 + u/g) v */
+ if (mpz_odd_p (s0) || mpz_odd_p (t0))
+ {
+ mpz_sub (s0, s0, s1);
+ mpz_add (t0, t0, t1);
+ }
+ assert (mpz_even_p (t0) && mpz_even_p (s0));
+ mpz_tdiv_q_2exp (s0, s0, 1);
+ mpz_tdiv_q_2exp (t0, t0, 1);
+ }
+
+ /* Arrange so that |s| < |u| / 2g */
+ mpz_add (s1, s0, s1);
+ if (mpz_cmpabs (s0, s1) > 0)
+ {
+ mpz_swap (s0, s1);
+ mpz_sub (t0, t0, t1);
+ }
+ if (u->_mp_size < 0)
+ mpz_neg (s0, s0);
+ if (v->_mp_size < 0)
+ mpz_neg (t0, t0);
+
+ mpz_swap (g, tv);
+ if (s)
+ mpz_swap (s, s0);
+ if (t)
+ mpz_swap (t, t0);
+
+ mpz_clear (tu);
+ mpz_clear (tv);
+ mpz_clear (s0);
+ mpz_clear (s1);
+ mpz_clear (t0);
+ mpz_clear (t1);
+}
+
+void
+mpz_lcm (mpz_t r, const mpz_t u, const mpz_t v)
+{
+ mpz_t g;
+
+ if (u->_mp_size == 0 || v->_mp_size == 0)
+ {
+ r->_mp_size = 0;
+ return;
+ }
+
+ mpz_init (g);
+
+ mpz_gcd (g, u, v);
+ mpz_divexact (g, u, g);
+ mpz_mul (r, g, v);
+
+ mpz_clear (g);
+ mpz_abs (r, r);
+}
+
+void
+mpz_lcm_ui (mpz_t r, const mpz_t u, unsigned long v)
+{
+ if (v == 0 || u->_mp_size == 0)
+ {
+ r->_mp_size = 0;
+ return;
+ }
+
+ v /= mpz_gcd_ui (NULL, u, v);
+ mpz_mul_ui (r, u, v);
+
+ mpz_abs (r, r);
+}
+
+int
+mpz_invert (mpz_t r, const mpz_t u, const mpz_t m)
+{
+ mpz_t g, tr;
+ int invertible;
+
+ if (u->_mp_size == 0 || mpz_cmpabs_ui (m, 1) <= 0)
+ return 0;
+
+ mpz_init (g);
+ mpz_init (tr);
+
+ mpz_gcdext (g, tr, NULL, u, m);
+ invertible = (mpz_cmp_ui (g, 1) == 0);
+
+ if (invertible)
+ {
+ if (tr->_mp_size < 0)
+ {
+ if (m->_mp_size >= 0)
+ mpz_add (tr, tr, m);
+ else
+ mpz_sub (tr, tr, m);
+ }
+ mpz_swap (r, tr);
+ }
+
+ mpz_clear (g);
+ mpz_clear (tr);
+ return invertible;
+}
+
+
+/* Higher level operations (sqrt, pow and root) */
+
+void
+mpz_pow_ui (mpz_t r, const mpz_t b, unsigned long e)
+{
+ unsigned long bit;
+ mpz_t tr;
+ mpz_init_set_ui (tr, 1);
+
+ bit = GMP_ULONG_HIGHBIT;
+ do
+ {
+ mpz_mul (tr, tr, tr);
+ if (e & bit)
+ mpz_mul (tr, tr, b);
+ bit >>= 1;
+ }
+ while (bit > 0);
+
+ mpz_swap (r, tr);
+ mpz_clear (tr);
+}
+
+void
+mpz_ui_pow_ui (mpz_t r, unsigned long blimb, unsigned long e)
+{
+ mpz_t b;
+
+ mpz_init_set_ui (b, blimb);
+ mpz_pow_ui (r, b, e);
+ mpz_clear (b);
+}
+
+void
+mpz_powm (mpz_t r, const mpz_t b, const mpz_t e, const mpz_t m)
+{
+ mpz_t tr;
+ mpz_t base;
+ mp_size_t en, mn;
+ mp_srcptr mp;
+ struct gmp_div_inverse minv;
+ unsigned shift;
+ mp_ptr tp = NULL;
+
+ en = GMP_ABS (e->_mp_size);
+ mn = GMP_ABS (m->_mp_size);
+ if (mn == 0)
+ gmp_die ("mpz_powm: Zero modulo.");
+
+ if (en == 0)
+ {
+ mpz_set_ui (r, 1);
+ return;
+ }
+
+ mp = m->_mp_d;
+ mpn_div_qr_invert (&minv, mp, mn);
+ shift = minv.shift;
+
+ if (shift > 0)
+ {
+ /* To avoid shifts, we do all our reductions, except the final
+ one, using a *normalized* m. */
+ minv.shift = 0;
+
+ tp = gmp_alloc_limbs (mn);
+ gmp_assert_nocarry (mpn_lshift (tp, mp, mn, shift));
+ mp = tp;
+ }
+
+ mpz_init (base);
+
+ if (e->_mp_size < 0)
+ {
+ if (!mpz_invert (base, b, m))
+ gmp_die ("mpz_powm: Negative exponent and non-invertible base.");
+ }
+ else
+ {
+ mp_size_t bn;
+ mpz_abs (base, b);
+
+ bn = base->_mp_size;
+ if (bn >= mn)
+ {
+ mpn_div_qr_preinv (NULL, base->_mp_d, base->_mp_size, mp, mn, &minv);
+ bn = mn;
+ }
+
+ /* We have reduced the absolute value. Now take care of the
+ sign. Note that we get zero represented non-canonically as
+ m. */
+ if (b->_mp_size < 0)
+ {
+ mp_ptr bp = MPZ_REALLOC (base, mn);
+ gmp_assert_nocarry (mpn_sub (bp, mp, mn, bp, bn));
+ bn = mn;
+ }
+ base->_mp_size = mpn_normalized_size (base->_mp_d, bn);
+ }
+ mpz_init_set_ui (tr, 1);
+
+ while (--en >= 0)
+ {
+ mp_limb_t w = e->_mp_d[en];
+ mp_limb_t bit;
+
+ bit = GMP_LIMB_HIGHBIT;
+ do
+ {
+ mpz_mul (tr, tr, tr);
+ if (w & bit)
+ mpz_mul (tr, tr, base);
+ if (tr->_mp_size > mn)
+ {
+ mpn_div_qr_preinv (NULL, tr->_mp_d, tr->_mp_size, mp, mn, &minv);
+ tr->_mp_size = mpn_normalized_size (tr->_mp_d, mn);
+ }
+ bit >>= 1;
+ }
+ while (bit > 0);
+ }
+
+ /* Final reduction */
+ if (tr->_mp_size >= mn)
+ {
+ minv.shift = shift;
+ mpn_div_qr_preinv (NULL, tr->_mp_d, tr->_mp_size, mp, mn, &minv);
+ tr->_mp_size = mpn_normalized_size (tr->_mp_d, mn);
+ }
+ if (tp)
+ gmp_free_limbs (tp, mn);
+
+ mpz_swap (r, tr);
+ mpz_clear (tr);
+ mpz_clear (base);
+}
+
+void
+mpz_powm_ui (mpz_t r, const mpz_t b, unsigned long elimb, const mpz_t m)
+{
+ mpz_t e;
+
+ mpz_init_set_ui (e, elimb);
+ mpz_powm (r, b, e, m);
+ mpz_clear (e);
+}
+
+/* x=trunc(y^(1/z)), r=y-x^z */
+void
+mpz_rootrem (mpz_t x, mpz_t r, const mpz_t y, unsigned long z)
+{
+ int sgn;
+ mp_bitcnt_t bc;
+ mpz_t t, u;
+
+ sgn = y->_mp_size < 0;
+ if ((~z & sgn) != 0)
+ gmp_die ("mpz_rootrem: Negative argument, with even root.");
+ if (z == 0)
+ gmp_die ("mpz_rootrem: Zeroth root.");
+
+ if (mpz_cmpabs_ui (y, 1) <= 0) {
+ if (x)
+ mpz_set (x, y);
+ if (r)
+ r->_mp_size = 0;
+ return;
+ }
+
+ mpz_init (u);
+ mpz_init (t);
+ bc = (mpz_sizeinbase (y, 2) - 1) / z + 1;
+ mpz_setbit (t, bc);
+
+ if (z == 2) /* simplify sqrt loop: z-1 == 1 */
+ do {
+ mpz_swap (u, t); /* u = x */
+ mpz_tdiv_q (t, y, u); /* t = y/x */
+ mpz_add (t, t, u); /* t = y/x + x */
+ mpz_tdiv_q_2exp (t, t, 1); /* x'= (y/x + x)/2 */
+ } while (mpz_cmpabs (t, u) < 0); /* |x'| < |x| */
+ else /* z != 2 */ {
+ mpz_t v;
+
+ mpz_init (v);
+ if (sgn)
+ mpz_neg (t, t);
+
+ do {
+ mpz_swap (u, t); /* u = x */
+ mpz_pow_ui (t, u, z - 1); /* t = x^(z-1) */
+ mpz_tdiv_q (t, y, t); /* t = y/x^(z-1) */
+ mpz_mul_ui (v, u, z - 1); /* v = x*(z-1) */
+ mpz_add (t, t, v); /* t = y/x^(z-1) + x*(z-1) */
+ mpz_tdiv_q_ui (t, t, z); /* x'=(y/x^(z-1) + x*(z-1))/z */
+ } while (mpz_cmpabs (t, u) < 0); /* |x'| < |x| */
+
+ mpz_clear (v);
+ }
+
+ if (r) {
+ mpz_pow_ui (t, u, z);
+ mpz_sub (r, y, t);
+ }
+ if (x)
+ mpz_swap (x, u);
+ mpz_clear (u);
+ mpz_clear (t);
+}
+
+int
+mpz_root (mpz_t x, const mpz_t y, unsigned long z)
+{
+ int res;
+ mpz_t r;
+
+ mpz_init (r);
+ mpz_rootrem (x, r, y, z);
+ res = r->_mp_size == 0;
+ mpz_clear (r);
+
+ return res;
+}
+
+/* Compute s = floor(sqrt(u)) and r = u - s^2. Allows r == NULL */
+void
+mpz_sqrtrem (mpz_t s, mpz_t r, const mpz_t u)
+{
+ mpz_rootrem (s, r, u, 2);
+}
+
+void
+mpz_sqrt (mpz_t s, const mpz_t u)
+{
+ mpz_rootrem (s, NULL, u, 2);
+}
+
+int
+mpz_perfect_square_p (const mpz_t u)
+{
+ if (u->_mp_size <= 0)
+ return (u->_mp_size == 0);
+ else
+ return mpz_root (NULL, u, 2);
+}
+
+int
+mpn_perfect_square_p (mp_srcptr p, mp_size_t n)
+{
+ mpz_t t;
+
+ assert (n > 0);
+ assert (p [n-1] != 0);
+ return mpz_root (NULL, mpz_roinit_normal_n (t, p, n), 2);
+}
+
+mp_size_t
+mpn_sqrtrem (mp_ptr sp, mp_ptr rp, mp_srcptr p, mp_size_t n)
+{
+ mpz_t s, r, u;
+ mp_size_t res;
+
+ assert (n > 0);
+ assert (p [n-1] != 0);
+
+ mpz_init (r);
+ mpz_init (s);
+ mpz_rootrem (s, r, mpz_roinit_normal_n (u, p, n), 2);
+
+ assert (s->_mp_size == (n+1)/2);
+ mpn_copyd (sp, s->_mp_d, s->_mp_size);
+ mpz_clear (s);
+ res = r->_mp_size;
+ if (rp)
+ mpn_copyd (rp, r->_mp_d, res);
+ mpz_clear (r);
+ return res;
+}
+
+/* Combinatorics */
+
+void
+mpz_mfac_uiui (mpz_t x, unsigned long n, unsigned long m)
+{
+ mpz_set_ui (x, n + (n == 0));
+ if (m + 1 < 2) return;
+ while (n > m + 1)
+ mpz_mul_ui (x, x, n -= m);
+}
+
+void
+mpz_2fac_ui (mpz_t x, unsigned long n)
+{
+ mpz_mfac_uiui (x, n, 2);
+}
+
+void
+mpz_fac_ui (mpz_t x, unsigned long n)
+{
+ mpz_mfac_uiui (x, n, 1);
+}
+
+void
+mpz_bin_uiui (mpz_t r, unsigned long n, unsigned long k)
+{
+ mpz_t t;
+
+ mpz_set_ui (r, k <= n);
+
+ if (k > (n >> 1))
+ k = (k <= n) ? n - k : 0;
+
+ mpz_init (t);
+ mpz_fac_ui (t, k);
+
+ for (; k > 0; --k)
+ mpz_mul_ui (r, r, n--);
+
+ mpz_divexact (r, r, t);
+ mpz_clear (t);
+}
+
+
+/* Primality testing */
+
+/* Computes Kronecker (a/b) with odd b, a!=0 and GCD(a,b) = 1 */
+/* Adapted from JACOBI_BASE_METHOD==4 in mpn/generic/jacbase.c */
+static int
+gmp_jacobi_coprime (mp_limb_t a, mp_limb_t b)
+{
+ int c, bit = 0;
+
+ assert (b & 1);
+ assert (a != 0);
+ /* assert (mpn_gcd_11 (a, b) == 1); */
+
+ /* Below, we represent a and b shifted right so that the least
+ significant one bit is implicit. */
+ b >>= 1;
+
+ gmp_ctz(c, a);
+ a >>= 1;
+
+ for (;;)
+ {
+ a >>= c;
+ /* (2/b) = -1 if b = 3 or 5 mod 8 */
+ bit ^= c & (b ^ (b >> 1));
+ if (a < b)
+ {
+ if (a == 0)
+ return bit & 1 ? -1 : 1;
+ bit ^= a & b;
+ a = b - a;
+ b -= a;
+ }
+ else
+ {
+ a -= b;
+ assert (a != 0);
+ }
+
+ gmp_ctz(c, a);
+ ++c;
+ }
+}
+
+static void
+gmp_lucas_step_k_2k (mpz_t V, mpz_t Qk, const mpz_t n)
+{
+ mpz_mod (Qk, Qk, n);
+ /* V_{2k} <- V_k ^ 2 - 2Q^k */
+ mpz_mul (V, V, V);
+ mpz_submul_ui (V, Qk, 2);
+ mpz_tdiv_r (V, V, n);
+ /* Q^{2k} = (Q^k)^2 */
+ mpz_mul (Qk, Qk, Qk);
+}
+
+/* Computes V_k, Q^k (mod n) for the Lucas' sequence */
+/* with P=1, Q=Q; k = (n>>b0)|1. */
+/* Requires an odd n > 4; b0 > 0; -2*Q must not overflow a long */
+/* Returns (U_k == 0) and sets V=V_k and Qk=Q^k. */
+static int
+gmp_lucas_mod (mpz_t V, mpz_t Qk, long Q,
+ mp_bitcnt_t b0, const mpz_t n)
+{
+ mp_bitcnt_t bs;
+ mpz_t U;
+ int res;
+
+ assert (b0 > 0);
+ assert (Q <= - (LONG_MIN / 2));
+ assert (Q >= - (LONG_MAX / 2));
+ assert (mpz_cmp_ui (n, 4) > 0);
+ assert (mpz_odd_p (n));
+
+ mpz_init_set_ui (U, 1); /* U1 = 1 */
+ mpz_set_ui (V, 1); /* V1 = 1 */
+ mpz_set_si (Qk, Q);
+
+ for (bs = mpz_sizeinbase (n, 2) - 1; --bs >= b0;)
+ {
+ /* U_{2k} <- U_k * V_k */
+ mpz_mul (U, U, V);
+ /* V_{2k} <- V_k ^ 2 - 2Q^k */
+ /* Q^{2k} = (Q^k)^2 */
+ gmp_lucas_step_k_2k (V, Qk, n);
+
+ /* A step k->k+1 is performed if the bit in $n$ is 1 */
+ /* mpz_tstbit(n,bs) or the bit is 0 in $n$ but */
+ /* should be 1 in $n+1$ (bs == b0) */
+ if (b0 == bs || mpz_tstbit (n, bs))
+ {
+ /* Q^{k+1} <- Q^k * Q */
+ mpz_mul_si (Qk, Qk, Q);
+ /* U_{k+1} <- (U_k + V_k) / 2 */
+ mpz_swap (U, V); /* Keep in V the old value of U_k */
+ mpz_add (U, U, V);
+ /* We have to compute U/2, so we need an even value, */
+ /* equivalent (mod n) */
+ if (mpz_odd_p (U))
+ mpz_add (U, U, n);
+ mpz_tdiv_q_2exp (U, U, 1);
+ /* V_{k+1} <-(D*U_k + V_k) / 2 =
+ U_{k+1} + (D-1)/2*U_k = U_{k+1} - 2Q*U_k */
+ mpz_mul_si (V, V, -2*Q);
+ mpz_add (V, U, V);
+ mpz_tdiv_r (V, V, n);
+ }
+ mpz_tdiv_r (U, U, n);
+ }
+
+ res = U->_mp_size == 0;
+ mpz_clear (U);
+ return res;
+}
+
+/* Performs strong Lucas' test on x, with parameters suggested */
+/* for the BPSW test. Qk is only passed to recycle a variable. */
+/* Requires GCD (x,6) = 1.*/
+static int
+gmp_stronglucas (const mpz_t x, mpz_t Qk)
+{
+ mp_bitcnt_t b0;
+ mpz_t V, n;
+ mp_limb_t maxD, D; /* The absolute value is stored. */
+ long Q;
+ mp_limb_t tl;
+
+ /* Test on the absolute value. */
+ mpz_roinit_normal_n (n, x->_mp_d, GMP_ABS (x->_mp_size));
+
+ assert (mpz_odd_p (n));
+ /* assert (mpz_gcd_ui (NULL, n, 6) == 1); */
+ if (mpz_root (Qk, n, 2))
+ return 0; /* A square is composite. */
+
+ /* Check Ds up to square root (in case, n is prime)
+ or avoid overflows */
+ maxD = (Qk->_mp_size == 1) ? Qk->_mp_d [0] - 1 : GMP_LIMB_MAX;
+
+ D = 3;
+ /* Search a D such that (D/n) = -1 in the sequence 5,-7,9,-11,.. */
+ /* For those Ds we have (D/n) = (n/|D|) */
+ do
+ {
+ if (D >= maxD)
+ return 1 + (D != GMP_LIMB_MAX); /* (1 + ! ~ D) */
+ D += 2;
+ tl = mpz_tdiv_ui (n, D);
+ if (tl == 0)
+ return 0;
+ }
+ while (gmp_jacobi_coprime (tl, D) == 1);
+
+ mpz_init (V);
+
+ /* n-(D/n) = n+1 = d*2^{b0}, with d = (n>>b0) | 1 */
+ b0 = mpn_common_scan (~ n->_mp_d[0], 0, n->_mp_d, n->_mp_size, GMP_LIMB_MAX);
+ /* b0 = mpz_scan0 (n, 0); */
+
+ /* D= P^2 - 4Q; P = 1; Q = (1-D)/4 */
+ Q = (D & 2) ? (long) (D >> 2) + 1 : -(long) (D >> 2);
+
+ if (! gmp_lucas_mod (V, Qk, Q, b0, n)) /* If Ud != 0 */
+ while (V->_mp_size != 0 && --b0 != 0) /* while Vk != 0 */
+ /* V <- V ^ 2 - 2Q^k */
+ /* Q^{2k} = (Q^k)^2 */
+ gmp_lucas_step_k_2k (V, Qk, n);
+
+ mpz_clear (V);
+ return (b0 != 0);
+}
+
+static int
+gmp_millerrabin (const mpz_t n, const mpz_t nm1, mpz_t y,
+ const mpz_t q, mp_bitcnt_t k)
+{
+ assert (k > 0);
+
+ /* Caller must initialize y to the base. */
+ mpz_powm (y, y, q, n);
+
+ if (mpz_cmp_ui (y, 1) == 0 || mpz_cmp (y, nm1) == 0)
+ return 1;
+
+ while (--k > 0)
+ {
+ mpz_powm_ui (y, y, 2, n);
+ if (mpz_cmp (y, nm1) == 0)
+ return 1;
+ }
+ return 0;
+}
+
+/* This product is 0xc0cfd797, and fits in 32 bits. */
+#define GMP_PRIME_PRODUCT \
+ (3UL*5UL*7UL*11UL*13UL*17UL*19UL*23UL*29UL)
+
+/* Bit (p+1)/2 is set, for each odd prime <= 61 */
+#define GMP_PRIME_MASK 0xc96996dcUL
+
+int
+mpz_probab_prime_p (const mpz_t n, int reps)
+{
+ mpz_t nm1;
+ mpz_t q;
+ mpz_t y;
+ mp_bitcnt_t k;
+ int is_prime;
+ int j;
+
+ /* Note that we use the absolute value of n only, for compatibility
+ with the real GMP. */
+ if (mpz_even_p (n))
+ return (mpz_cmpabs_ui (n, 2) == 0) ? 2 : 0;
+
+ /* Above test excludes n == 0 */
+ assert (n->_mp_size != 0);
+
+ if (mpz_cmpabs_ui (n, 64) < 0)
+ return (GMP_PRIME_MASK >> (n->_mp_d[0] >> 1)) & 2;
+
+ if (mpz_gcd_ui (NULL, n, GMP_PRIME_PRODUCT) != 1)
+ return 0;
+
+ /* All prime factors are >= 31. */
+ if (mpz_cmpabs_ui (n, 31*31) < 0)
+ return 2;
+
+ mpz_init (nm1);
+ mpz_init (q);
+
+ /* Find q and k, where q is odd and n = 1 + 2**k * q. */
+ mpz_abs (nm1, n);
+ nm1->_mp_d[0] -= 1;
+ /* Count trailing zeros, equivalent to mpn_scan1, because we know that there is a 1 */
+ k = mpn_scan1 (nm1->_mp_d, 0);
+ mpz_tdiv_q_2exp (q, nm1, k);
+
+ /* BPSW test */
+ mpz_init_set_ui (y, 2);
+ is_prime = gmp_millerrabin (n, nm1, y, q, k) && gmp_stronglucas (n, y);
+ reps -= 24; /* skip the first 24 repetitions */
+
+ /* Use Miller-Rabin, with a deterministic sequence of bases, a[j] =
+ j^2 + j + 41 using Euler's polynomial. We potentially stop early,
+ if a[j] >= n - 1. Since n >= 31*31, this can happen only if reps >
+ 30 (a[30] == 971 > 31*31 == 961). */
+
+ for (j = 0; is_prime & (j < reps); j++)
+ {
+ mpz_set_ui (y, (unsigned long) j*j+j+41);
+ if (mpz_cmp (y, nm1) >= 0)
+ {
+ /* Don't try any further bases. This "early" break does not affect
+ the result for any reasonable reps value (<=5000 was tested) */
+ assert (j >= 30);
+ break;
+ }
+ is_prime = gmp_millerrabin (n, nm1, y, q, k);
+ }
+ mpz_clear (nm1);
+ mpz_clear (q);
+ mpz_clear (y);
+
+ return is_prime;
+}
+
+
+/* Logical operations and bit manipulation. */
+
+/* Numbers are treated as if represented in two's complement (and
+ infinitely sign extended). For a negative values we get the two's
+ complement from -x = ~x + 1, where ~ is bitwise complement.
+ Negation transforms
+
+ xxxx10...0
+
+ into
+
+ yyyy10...0
+
+ where yyyy is the bitwise complement of xxxx. So least significant
+ bits, up to and including the first one bit, are unchanged, and
+ the more significant bits are all complemented.
+
+ To change a bit from zero to one in a negative number, subtract the
+ corresponding power of two from the absolute value. This can never
+ underflow. To change a bit from one to zero, add the corresponding
+ power of two, and this might overflow. E.g., if x = -001111, the
+ two's complement is 110001. Clearing the least significant bit, we
+ get two's complement 110000, and -010000. */
+
+int
+mpz_tstbit (const mpz_t d, mp_bitcnt_t bit_index)
+{
+ mp_size_t limb_index;
+ unsigned shift;
+ mp_size_t ds;
+ mp_size_t dn;
+ mp_limb_t w;
+ int bit;
+
+ ds = d->_mp_size;
+ dn = GMP_ABS (ds);
+ limb_index = bit_index / GMP_LIMB_BITS;
+ if (limb_index >= dn)
+ return ds < 0;
+
+ shift = bit_index % GMP_LIMB_BITS;
+ w = d->_mp_d[limb_index];
+ bit = (w >> shift) & 1;
+
+ if (ds < 0)
+ {
+ /* d < 0. Check if any of the bits below is set: If so, our bit
+ must be complemented. */
+ if (shift > 0 && (mp_limb_t) (w << (GMP_LIMB_BITS - shift)) > 0)
+ return bit ^ 1;
+ while (--limb_index >= 0)
+ if (d->_mp_d[limb_index] > 0)
+ return bit ^ 1;
+ }
+ return bit;
+}
+
+static void
+mpz_abs_add_bit (mpz_t d, mp_bitcnt_t bit_index)
+{
+ mp_size_t dn, limb_index;
+ mp_limb_t bit;
+ mp_ptr dp;
+
+ dn = GMP_ABS (d->_mp_size);
+
+ limb_index = bit_index / GMP_LIMB_BITS;
+ bit = (mp_limb_t) 1 << (bit_index % GMP_LIMB_BITS);
+
+ if (limb_index >= dn)
+ {
+ mp_size_t i;
+ /* The bit should be set outside of the end of the number.
+ We have to increase the size of the number. */
+ dp = MPZ_REALLOC (d, limb_index + 1);
+
+ dp[limb_index] = bit;
+ for (i = dn; i < limb_index; i++)
+ dp[i] = 0;
+ dn = limb_index + 1;
+ }
+ else
+ {
+ mp_limb_t cy;
+
+ dp = d->_mp_d;
+
+ cy = mpn_add_1 (dp + limb_index, dp + limb_index, dn - limb_index, bit);
+ if (cy > 0)
+ {
+ dp = MPZ_REALLOC (d, dn + 1);
+ dp[dn++] = cy;
+ }
+ }
+
+ d->_mp_size = (d->_mp_size < 0) ? - dn : dn;
+}
+
+static void
+mpz_abs_sub_bit (mpz_t d, mp_bitcnt_t bit_index)
+{
+ mp_size_t dn, limb_index;
+ mp_ptr dp;
+ mp_limb_t bit;
+
+ dn = GMP_ABS (d->_mp_size);
+ dp = d->_mp_d;
+
+ limb_index = bit_index / GMP_LIMB_BITS;
+ bit = (mp_limb_t) 1 << (bit_index % GMP_LIMB_BITS);
+
+ assert (limb_index < dn);
+
+ gmp_assert_nocarry (mpn_sub_1 (dp + limb_index, dp + limb_index,
+ dn - limb_index, bit));
+ dn = mpn_normalized_size (dp, dn);
+ d->_mp_size = (d->_mp_size < 0) ? - dn : dn;
+}
+
+void
+mpz_setbit (mpz_t d, mp_bitcnt_t bit_index)
+{
+ if (!mpz_tstbit (d, bit_index))
+ {
+ if (d->_mp_size >= 0)
+ mpz_abs_add_bit (d, bit_index);
+ else
+ mpz_abs_sub_bit (d, bit_index);
+ }
+}
+
+void
+mpz_clrbit (mpz_t d, mp_bitcnt_t bit_index)
+{
+ if (mpz_tstbit (d, bit_index))
+ {
+ if (d->_mp_size >= 0)
+ mpz_abs_sub_bit (d, bit_index);
+ else
+ mpz_abs_add_bit (d, bit_index);
+ }
+}
+
+void
+mpz_combit (mpz_t d, mp_bitcnt_t bit_index)
+{
+ if (mpz_tstbit (d, bit_index) ^ (d->_mp_size < 0))
+ mpz_abs_sub_bit (d, bit_index);
+ else
+ mpz_abs_add_bit (d, bit_index);
+}
+
+void
+mpz_com (mpz_t r, const mpz_t u)
+{
+ mpz_add_ui (r, u, 1);
+ mpz_neg (r, r);
+}
+
+void
+mpz_and (mpz_t r, const mpz_t u, const mpz_t v)
+{
+ mp_size_t un, vn, rn, i;
+ mp_ptr up, vp, rp;
+
+ mp_limb_t ux, vx, rx;
+ mp_limb_t uc, vc, rc;
+ mp_limb_t ul, vl, rl;
+
+ un = GMP_ABS (u->_mp_size);
+ vn = GMP_ABS (v->_mp_size);
+ if (un < vn)
+ {
+ MPZ_SRCPTR_SWAP (u, v);
+ MP_SIZE_T_SWAP (un, vn);
+ }
+ if (vn == 0)
+ {
+ r->_mp_size = 0;
+ return;
+ }
+
+ uc = u->_mp_size < 0;
+ vc = v->_mp_size < 0;
+ rc = uc & vc;
+
+ ux = -uc;
+ vx = -vc;
+ rx = -rc;
+
+ /* If the smaller input is positive, higher limbs don't matter. */
+ rn = vx ? un : vn;
+
+ rp = MPZ_REALLOC (r, rn + (mp_size_t) rc);
+
+ up = u->_mp_d;
+ vp = v->_mp_d;
+
+ i = 0;
+ do
+ {
+ ul = (up[i] ^ ux) + uc;
+ uc = ul < uc;
+
+ vl = (vp[i] ^ vx) + vc;
+ vc = vl < vc;
+
+ rl = ( (ul & vl) ^ rx) + rc;
+ rc = rl < rc;
+ rp[i] = rl;
+ }
+ while (++i < vn);
+ assert (vc == 0);
+
+ for (; i < rn; i++)
+ {
+ ul = (up[i] ^ ux) + uc;
+ uc = ul < uc;
+
+ rl = ( (ul & vx) ^ rx) + rc;
+ rc = rl < rc;
+ rp[i] = rl;
+ }
+ if (rc)
+ rp[rn++] = rc;
+ else
+ rn = mpn_normalized_size (rp, rn);
+
+ r->_mp_size = rx ? -rn : rn;
+}
+
+void
+mpz_ior (mpz_t r, const mpz_t u, const mpz_t v)
+{
+ mp_size_t un, vn, rn, i;
+ mp_ptr up, vp, rp;
+
+ mp_limb_t ux, vx, rx;
+ mp_limb_t uc, vc, rc;
+ mp_limb_t ul, vl, rl;
+
+ un = GMP_ABS (u->_mp_size);
+ vn = GMP_ABS (v->_mp_size);
+ if (un < vn)
+ {
+ MPZ_SRCPTR_SWAP (u, v);
+ MP_SIZE_T_SWAP (un, vn);
+ }
+ if (vn == 0)
+ {
+ mpz_set (r, u);
+ return;
+ }
+
+ uc = u->_mp_size < 0;
+ vc = v->_mp_size < 0;
+ rc = uc | vc;
+
+ ux = -uc;
+ vx = -vc;
+ rx = -rc;
+
+ /* If the smaller input is negative, by sign extension higher limbs
+ don't matter. */
+ rn = vx ? vn : un;
+
+ rp = MPZ_REALLOC (r, rn + (mp_size_t) rc);
+
+ up = u->_mp_d;
+ vp = v->_mp_d;
+
+ i = 0;
+ do
+ {
+ ul = (up[i] ^ ux) + uc;
+ uc = ul < uc;
+
+ vl = (vp[i] ^ vx) + vc;
+ vc = vl < vc;
+
+ rl = ( (ul | vl) ^ rx) + rc;
+ rc = rl < rc;
+ rp[i] = rl;
+ }
+ while (++i < vn);
+ assert (vc == 0);
+
+ for (; i < rn; i++)
+ {
+ ul = (up[i] ^ ux) + uc;
+ uc = ul < uc;
+
+ rl = ( (ul | vx) ^ rx) + rc;
+ rc = rl < rc;
+ rp[i] = rl;
+ }
+ if (rc)
+ rp[rn++] = rc;
+ else
+ rn = mpn_normalized_size (rp, rn);
+
+ r->_mp_size = rx ? -rn : rn;
+}
+
+void
+mpz_xor (mpz_t r, const mpz_t u, const mpz_t v)
+{
+ mp_size_t un, vn, i;
+ mp_ptr up, vp, rp;
+
+ mp_limb_t ux, vx, rx;
+ mp_limb_t uc, vc, rc;
+ mp_limb_t ul, vl, rl;
+
+ un = GMP_ABS (u->_mp_size);
+ vn = GMP_ABS (v->_mp_size);
+ if (un < vn)
+ {
+ MPZ_SRCPTR_SWAP (u, v);
+ MP_SIZE_T_SWAP (un, vn);
+ }
+ if (vn == 0)
+ {
+ mpz_set (r, u);
+ return;
+ }
+
+ uc = u->_mp_size < 0;
+ vc = v->_mp_size < 0;
+ rc = uc ^ vc;
+
+ ux = -uc;
+ vx = -vc;
+ rx = -rc;
+
+ rp = MPZ_REALLOC (r, un + (mp_size_t) rc);
+
+ up = u->_mp_d;
+ vp = v->_mp_d;
+
+ i = 0;
+ do
+ {
+ ul = (up[i] ^ ux) + uc;
+ uc = ul < uc;
+
+ vl = (vp[i] ^ vx) + vc;
+ vc = vl < vc;
+
+ rl = (ul ^ vl ^ rx) + rc;
+ rc = rl < rc;
+ rp[i] = rl;
+ }
+ while (++i < vn);
+ assert (vc == 0);
+
+ for (; i < un; i++)
+ {
+ ul = (up[i] ^ ux) + uc;
+ uc = ul < uc;
+
+ rl = (ul ^ ux) + rc;
+ rc = rl < rc;
+ rp[i] = rl;
+ }
+ if (rc)
+ rp[un++] = rc;
+ else
+ un = mpn_normalized_size (rp, un);
+
+ r->_mp_size = rx ? -un : un;
+}
+
+static unsigned
+gmp_popcount_limb (mp_limb_t x)
+{
+ unsigned c;
+
+ /* Do 16 bits at a time, to avoid limb-sized constants. */
+ int LOCAL_SHIFT_BITS = 16;
+ for (c = 0; x > 0;)
+ {
+ unsigned w = x - ((x >> 1) & 0x5555);
+ w = ((w >> 2) & 0x3333) + (w & 0x3333);
+ w = (w >> 4) + w;
+ w = ((w >> 8) & 0x000f) + (w & 0x000f);
+ c += w;
+ if (GMP_LIMB_BITS > LOCAL_SHIFT_BITS)
+ x >>= LOCAL_SHIFT_BITS;
+ else
+ x = 0;
+ }
+ return c;
+}
+
+mp_bitcnt_t
+mpn_popcount (mp_srcptr p, mp_size_t n)
+{
+ mp_size_t i;
+ mp_bitcnt_t c;
+
+ for (c = 0, i = 0; i < n; i++)
+ c += gmp_popcount_limb (p[i]);
+
+ return c;
+}
+
+mp_bitcnt_t
+mpz_popcount (const mpz_t u)
+{
+ mp_size_t un;
+
+ un = u->_mp_size;
+
+ if (un < 0)
+ return ~(mp_bitcnt_t) 0;
+
+ return mpn_popcount (u->_mp_d, un);
+}
+
+mp_bitcnt_t
+mpz_hamdist (const mpz_t u, const mpz_t v)
+{
+ mp_size_t un, vn, i;
+ mp_limb_t uc, vc, ul, vl, comp;
+ mp_srcptr up, vp;
+ mp_bitcnt_t c;
+
+ un = u->_mp_size;
+ vn = v->_mp_size;
+
+ if ( (un ^ vn) < 0)
+ return ~(mp_bitcnt_t) 0;
+
+ comp = - (uc = vc = (un < 0));
+ if (uc)
+ {
+ assert (vn < 0);
+ un = -un;
+ vn = -vn;
+ }
+
+ up = u->_mp_d;
+ vp = v->_mp_d;
+
+ if (un < vn)
+ MPN_SRCPTR_SWAP (up, un, vp, vn);
+
+ for (i = 0, c = 0; i < vn; i++)
+ {
+ ul = (up[i] ^ comp) + uc;
+ uc = ul < uc;
+
+ vl = (vp[i] ^ comp) + vc;
+ vc = vl < vc;
+
+ c += gmp_popcount_limb (ul ^ vl);
+ }
+ assert (vc == 0);
+
+ for (; i < un; i++)
+ {
+ ul = (up[i] ^ comp) + uc;
+ uc = ul < uc;
+
+ c += gmp_popcount_limb (ul ^ comp);
+ }
+
+ return c;
+}
+
+mp_bitcnt_t
+mpz_scan1 (const mpz_t u, mp_bitcnt_t starting_bit)
+{
+ mp_ptr up;
+ mp_size_t us, un, i;
+ mp_limb_t limb, ux;
+
+ us = u->_mp_size;
+ un = GMP_ABS (us);
+ i = starting_bit / GMP_LIMB_BITS;
+
+ /* Past the end there's no 1 bits for u>=0, or an immediate 1 bit
+ for u<0. Notice this test picks up any u==0 too. */
+ if (i >= un)
+ return (us >= 0 ? ~(mp_bitcnt_t) 0 : starting_bit);
+
+ up = u->_mp_d;
+ ux = 0;
+ limb = up[i];
+
+ if (starting_bit != 0)
+ {
+ if (us < 0)
+ {
+ ux = mpn_zero_p (up, i);
+ limb = ~ limb + ux;
+ ux = - (mp_limb_t) (limb >= ux);
+ }
+
+ /* Mask to 0 all bits before starting_bit, thus ignoring them. */
+ limb &= GMP_LIMB_MAX << (starting_bit % GMP_LIMB_BITS);
+ }
+
+ return mpn_common_scan (limb, i, up, un, ux);
+}
+
+mp_bitcnt_t
+mpz_scan0 (const mpz_t u, mp_bitcnt_t starting_bit)
+{
+ mp_ptr up;
+ mp_size_t us, un, i;
+ mp_limb_t limb, ux;
+
+ us = u->_mp_size;
+ ux = - (mp_limb_t) (us >= 0);
+ un = GMP_ABS (us);
+ i = starting_bit / GMP_LIMB_BITS;
+
+ /* When past end, there's an immediate 0 bit for u>=0, or no 0 bits for
+ u<0. Notice this test picks up all cases of u==0 too. */
+ if (i >= un)
+ return (ux ? starting_bit : ~(mp_bitcnt_t) 0);
+
+ up = u->_mp_d;
+ limb = up[i] ^ ux;
+
+ if (ux == 0)
+ limb -= mpn_zero_p (up, i); /* limb = ~(~limb + zero_p) */
+
+ /* Mask all bits before starting_bit, thus ignoring them. */
+ limb &= GMP_LIMB_MAX << (starting_bit % GMP_LIMB_BITS);
+
+ return mpn_common_scan (limb, i, up, un, ux);
+}
+
+
+/* MPZ base conversion. */
+
+size_t
+mpz_sizeinbase (const mpz_t u, int base)
+{
+ mp_size_t un, tn;
+ mp_srcptr up;
+ mp_ptr tp;
+ mp_bitcnt_t bits;
+ struct gmp_div_inverse bi;
+ size_t ndigits;
+
+ assert (base >= 2);
+ assert (base <= 62);
+
+ un = GMP_ABS (u->_mp_size);
+ if (un == 0)
+ return 1;
+
+ up = u->_mp_d;
+
+ bits = (un - 1) * GMP_LIMB_BITS + mpn_limb_size_in_base_2 (up[un-1]);
+ switch (base)
+ {
+ case 2:
+ return bits;
+ case 4:
+ return (bits + 1) / 2;
+ case 8:
+ return (bits + 2) / 3;
+ case 16:
+ return (bits + 3) / 4;
+ case 32:
+ return (bits + 4) / 5;
+ /* FIXME: Do something more clever for the common case of base
+ 10. */
+ }
+
+ tp = gmp_alloc_limbs (un);
+ mpn_copyi (tp, up, un);
+ mpn_div_qr_1_invert (&bi, base);
+
+ tn = un;
+ ndigits = 0;
+ do
+ {
+ ndigits++;
+ mpn_div_qr_1_preinv (tp, tp, tn, &bi);
+ tn -= (tp[tn-1] == 0);
+ }
+ while (tn > 0);
+
+ gmp_free_limbs (tp, un);
+ return ndigits;
+}
+
+char *
+mpz_get_str (char *sp, int base, const mpz_t u)
+{
+ unsigned bits;
+ const char *digits;
+ mp_size_t un;
+ size_t i, sn, osn;
+
+ digits = "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz";
+ if (base > 1)
+ {
+ if (base <= 36)
+ digits = "0123456789abcdefghijklmnopqrstuvwxyz";
+ else if (base > 62)
+ return NULL;
+ }
+ else if (base >= -1)
+ base = 10;
+ else
+ {
+ base = -base;
+ if (base > 36)
+ return NULL;
+ }
+
+ sn = 1 + mpz_sizeinbase (u, base);
+ if (!sp)
+ {
+ osn = 1 + sn;
+ sp = (char *) gmp_alloc (osn);
+ }
+ else
+ osn = 0;
+ un = GMP_ABS (u->_mp_size);
+
+ if (un == 0)
+ {
+ sp[0] = '0';
+ sn = 1;
+ goto ret;
+ }
+
+ i = 0;
+
+ if (u->_mp_size < 0)
+ sp[i++] = '-';
+
+ bits = mpn_base_power_of_two_p (base);
+
+ if (bits)
+ /* Not modified in this case. */
+ sn = i + mpn_get_str_bits ((unsigned char *) sp + i, bits, u->_mp_d, un);
+ else
+ {
+ struct mpn_base_info info;
+ mp_ptr tp;
+
+ mpn_get_base_info (&info, base);
+ tp = gmp_alloc_limbs (un);
+ mpn_copyi (tp, u->_mp_d, un);
+
+ sn = i + mpn_get_str_other ((unsigned char *) sp + i, base, &info, tp, un);
+ gmp_free_limbs (tp, un);
+ }
+
+ for (; i < sn; i++)
+ sp[i] = digits[(unsigned char) sp[i]];
+
+ret:
+ sp[sn] = '\0';
+ if (osn && osn != sn + 1)
+ sp = (char*) gmp_realloc (sp, osn, sn + 1);
+ return sp;
+}
+
+int
+mpz_set_str (mpz_t r, const char *sp, int base)
+{
+ unsigned bits, value_of_a;
+ mp_size_t rn, alloc;
+ mp_ptr rp;
+ size_t dn, sn;
+ int sign;
+ unsigned char *dp;
+
+ assert (base == 0 || (base >= 2 && base <= 62));
+
+ while (isspace( (unsigned char) *sp))
+ sp++;
+
+ sign = (*sp == '-');
+ sp += sign;
+
+ if (base == 0)
+ {
+ if (sp[0] == '0')
+ {
+ if (sp[1] == 'x' || sp[1] == 'X')
+ {
+ base = 16;
+ sp += 2;
+ }
+ else if (sp[1] == 'b' || sp[1] == 'B')
+ {
+ base = 2;
+ sp += 2;
+ }
+ else
+ base = 8;
+ }
+ else
+ base = 10;
+ }
+
+ if (!*sp)
+ {
+ r->_mp_size = 0;
+ return -1;
+ }
+ sn = strlen(sp);
+ dp = (unsigned char *) gmp_alloc (sn);
+
+ value_of_a = (base > 36) ? 36 : 10;
+ for (dn = 0; *sp; sp++)
+ {
+ unsigned digit;
+
+ if (isspace ((unsigned char) *sp))
+ continue;
+ else if (*sp >= '0' && *sp <= '9')
+ digit = *sp - '0';
+ else if (*sp >= 'a' && *sp <= 'z')
+ digit = *sp - 'a' + value_of_a;
+ else if (*sp >= 'A' && *sp <= 'Z')
+ digit = *sp - 'A' + 10;
+ else
+ digit = base; /* fail */
+
+ if (digit >= (unsigned) base)
+ {
+ gmp_free (dp, sn);
+ r->_mp_size = 0;
+ return -1;
+ }
+
+ dp[dn++] = digit;
+ }
+
+ if (!dn)
+ {
+ gmp_free (dp, sn);
+ r->_mp_size = 0;
+ return -1;
+ }
+ bits = mpn_base_power_of_two_p (base);
+
+ if (bits > 0)
+ {
+ alloc = (dn * bits + GMP_LIMB_BITS - 1) / GMP_LIMB_BITS;
+ rp = MPZ_REALLOC (r, alloc);
+ rn = mpn_set_str_bits (rp, dp, dn, bits);
+ }
+ else
+ {
+ struct mpn_base_info info;
+ mpn_get_base_info (&info, base);
+ alloc = (dn + info.exp - 1) / info.exp;
+ rp = MPZ_REALLOC (r, alloc);
+ rn = mpn_set_str_other (rp, dp, dn, base, &info);
+ /* Normalization, needed for all-zero input. */
+ assert (rn > 0);
+ rn -= rp[rn-1] == 0;
+ }
+ assert (rn <= alloc);
+ gmp_free (dp, sn);
+
+ r->_mp_size = sign ? - rn : rn;
+
+ return 0;
+}
+
+int
+mpz_init_set_str (mpz_t r, const char *sp, int base)
+{
+ mpz_init (r);
+ return mpz_set_str (r, sp, base);
+}
+
+size_t
+mpz_out_str (FILE *stream, int base, const mpz_t x)
+{
+ char *str;
+ size_t len, n;
+
+ str = mpz_get_str (NULL, base, x);
+ if (!str)
+ return 0;
+ len = strlen (str);
+ n = fwrite (str, 1, len, stream);
+ gmp_free (str, len + 1);
+ return n;
+}
+
+
+static int
+gmp_detect_endian (void)
+{
+ static const int i = 2;
+ const unsigned char *p = (const unsigned char *) &i;
+ return 1 - *p;
+}
+
+/* Import and export. Does not support nails. */
+void
+mpz_import (mpz_t r, size_t count, int order, size_t size, int endian,
+ size_t nails, const void *src)
+{
+ const unsigned char *p;
+ ptrdiff_t word_step;
+ mp_ptr rp;
+ mp_size_t rn;
+
+ /* The current (partial) limb. */
+ mp_limb_t limb;
+ /* The number of bytes already copied to this limb (starting from
+ the low end). */
+ size_t bytes;
+ /* The index where the limb should be stored, when completed. */
+ mp_size_t i;
+
+ if (nails != 0)
+ gmp_die ("mpz_import: Nails not supported.");
+
+ assert (order == 1 || order == -1);
+ assert (endian >= -1 && endian <= 1);
+
+ if (endian == 0)
+ endian = gmp_detect_endian ();
+
+ p = (unsigned char *) src;
+
+ word_step = (order != endian) ? 2 * size : 0;
+
+ /* Process bytes from the least significant end, so point p at the
+ least significant word. */
+ if (order == 1)
+ {
+ p += size * (count - 1);
+ word_step = - word_step;
+ }
+
+ /* And at least significant byte of that word. */
+ if (endian == 1)
+ p += (size - 1);
+
+ rn = (size * count + sizeof(mp_limb_t) - 1) / sizeof(mp_limb_t);
+ rp = MPZ_REALLOC (r, rn);
+
+ for (limb = 0, bytes = 0, i = 0; count > 0; count--, p += word_step)
+ {
+ size_t j;
+ for (j = 0; j < size; j++, p -= (ptrdiff_t) endian)
+ {
+ limb |= (mp_limb_t) *p << (bytes++ * CHAR_BIT);
+ if (bytes == sizeof(mp_limb_t))
+ {
+ rp[i++] = limb;
+ bytes = 0;
+ limb = 0;
+ }
+ }
+ }
+ assert (i + (bytes > 0) == rn);
+ if (limb != 0)
+ rp[i++] = limb;
+ else
+ i = mpn_normalized_size (rp, i);
+
+ r->_mp_size = i;
+}
+
+void *
+mpz_export (void *r, size_t *countp, int order, size_t size, int endian,
+ size_t nails, const mpz_t u)
+{
+ size_t count;
+ mp_size_t un;
+
+ if (nails != 0)
+ gmp_die ("mpz_export: Nails not supported.");
+
+ assert (order == 1 || order == -1);
+ assert (endian >= -1 && endian <= 1);
+ assert (size > 0 || u->_mp_size == 0);
+
+ un = u->_mp_size;
+ count = 0;
+ if (un != 0)
+ {
+ size_t k;
+ unsigned char *p;
+ ptrdiff_t word_step;
+ /* The current (partial) limb. */
+ mp_limb_t limb;
+ /* The number of bytes left to do in this limb. */
+ size_t bytes;
+ /* The index where the limb was read. */
+ mp_size_t i;
+
+ un = GMP_ABS (un);
+
+ /* Count bytes in top limb. */
+ limb = u->_mp_d[un-1];
+ assert (limb != 0);
+
+ k = (GMP_LIMB_BITS <= CHAR_BIT);
+ if (!k)
+ {
+ do {
+ int LOCAL_CHAR_BIT = CHAR_BIT;
+ k++; limb >>= LOCAL_CHAR_BIT;
+ } while (limb != 0);
+ }
+ /* else limb = 0; */
+
+ count = (k + (un-1) * sizeof (mp_limb_t) + size - 1) / size;
+
+ if (!r)
+ r = gmp_alloc (count * size);
+
+ if (endian == 0)
+ endian = gmp_detect_endian ();
+
+ p = (unsigned char *) r;
+
+ word_step = (order != endian) ? 2 * size : 0;
+
+ /* Process bytes from the least significant end, so point p at the
+ least significant word. */
+ if (order == 1)
+ {
+ p += size * (count - 1);
+ word_step = - word_step;
+ }
+
+ /* And at least significant byte of that word. */
+ if (endian == 1)
+ p += (size - 1);
+
+ for (bytes = 0, i = 0, k = 0; k < count; k++, p += word_step)
+ {
+ size_t j;
+ for (j = 0; j < size; ++j, p -= (ptrdiff_t) endian)
+ {
+ if (sizeof (mp_limb_t) == 1)
+ {
+ if (i < un)
+ *p = u->_mp_d[i++];
+ else
+ *p = 0;
+ }
+ else
+ {
+ int LOCAL_CHAR_BIT = CHAR_BIT;
+ if (bytes == 0)
+ {
+ if (i < un)
+ limb = u->_mp_d[i++];
+ bytes = sizeof (mp_limb_t);
+ }
+ *p = limb;
+ limb >>= LOCAL_CHAR_BIT;
+ bytes--;
+ }
+ }
+ }
+ assert (i == un);
+ assert (k == count);
+ }
+
+ if (countp)
+ *countp = count;
+
+ return r;
+}
diff --git a/lib/mini-gmp.h b/lib/mini-gmp.h
new file mode 100644
index 00000000000..59c24cf5111
--- /dev/null
+++ b/lib/mini-gmp.h
@@ -0,0 +1,310 @@
+/* mini-gmp, a minimalistic implementation of a GNU GMP subset.
+
+Copyright 2011-2015, 2017, 2019-2021 Free Software Foundation, Inc.
+
+This file is part of the GNU MP Library.
+
+The GNU MP Library is free software; you can redistribute it and/or modify
+it under the terms of either:
+
+ * the GNU Lesser General Public License as published by the Free
+ Software Foundation; either version 3 of the License, or (at your
+ option) any later version.
+
+or
+
+ * the GNU General Public License as published by the Free Software
+ Foundation; either version 2 of the License, or (at your option) any
+ later version.
+
+or both in parallel, as here.
+
+The GNU MP 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 copies of the GNU General Public License and the
+GNU Lesser General Public License along with the GNU MP Library. If not,
+see https://www.gnu.org/licenses/. */
+
+/* About mini-gmp: This is a minimal implementation of a subset of the
+ GMP interface. It is intended for inclusion into applications which
+ have modest bignums needs, as a fallback when the real GMP library
+ is not installed.
+
+ This file defines the public interface. */
+
+#ifndef __MINI_GMP_H__
+#define __MINI_GMP_H__
+
+/* For size_t */
+#include <stddef.h>
+
+#if defined (__cplusplus)
+extern "C" {
+#endif
+
+void mp_set_memory_functions (void *(*) (size_t),
+ void *(*) (void *, size_t, size_t),
+ void (*) (void *, size_t));
+
+void mp_get_memory_functions (void *(**) (size_t),
+ void *(**) (void *, size_t, size_t),
+ void (**) (void *, size_t));
+
+#ifndef MINI_GMP_LIMB_TYPE
+#define MINI_GMP_LIMB_TYPE long
+#endif
+
+typedef unsigned MINI_GMP_LIMB_TYPE mp_limb_t;
+typedef long mp_size_t;
+typedef unsigned long mp_bitcnt_t;
+
+typedef mp_limb_t *mp_ptr;
+typedef const mp_limb_t *mp_srcptr;
+
+typedef struct
+{
+ int _mp_alloc; /* Number of *limbs* allocated and pointed
+ to by the _mp_d field. */
+ int _mp_size; /* abs(_mp_size) is the number of limbs the
+ last field points to. If _mp_size is
+ negative this is a negative number. */
+ mp_limb_t *_mp_d; /* Pointer to the limbs. */
+} __mpz_struct;
+
+typedef __mpz_struct mpz_t[1];
+
+typedef __mpz_struct *mpz_ptr;
+typedef const __mpz_struct *mpz_srcptr;
+
+extern const int mp_bits_per_limb;
+
+void mpn_copyi (mp_ptr, mp_srcptr, mp_size_t);
+void mpn_copyd (mp_ptr, mp_srcptr, mp_size_t);
+void mpn_zero (mp_ptr, mp_size_t);
+
+int mpn_cmp (mp_srcptr, mp_srcptr, mp_size_t);
+int mpn_zero_p (mp_srcptr, mp_size_t);
+
+mp_limb_t mpn_add_1 (mp_ptr, mp_srcptr, mp_size_t, mp_limb_t);
+mp_limb_t mpn_add_n (mp_ptr, mp_srcptr, mp_srcptr, mp_size_t);
+mp_limb_t mpn_add (mp_ptr, mp_srcptr, mp_size_t, mp_srcptr, mp_size_t);
+
+mp_limb_t mpn_sub_1 (mp_ptr, mp_srcptr, mp_size_t, mp_limb_t);
+mp_limb_t mpn_sub_n (mp_ptr, mp_srcptr, mp_srcptr, mp_size_t);
+mp_limb_t mpn_sub (mp_ptr, mp_srcptr, mp_size_t, mp_srcptr, mp_size_t);
+
+mp_limb_t mpn_mul_1 (mp_ptr, mp_srcptr, mp_size_t, mp_limb_t);
+mp_limb_t mpn_addmul_1 (mp_ptr, mp_srcptr, mp_size_t, mp_limb_t);
+mp_limb_t mpn_submul_1 (mp_ptr, mp_srcptr, mp_size_t, mp_limb_t);
+
+mp_limb_t mpn_mul (mp_ptr, mp_srcptr, mp_size_t, mp_srcptr, mp_size_t);
+void mpn_mul_n (mp_ptr, mp_srcptr, mp_srcptr, mp_size_t);
+void mpn_sqr (mp_ptr, mp_srcptr, mp_size_t);
+int mpn_perfect_square_p (mp_srcptr, mp_size_t);
+mp_size_t mpn_sqrtrem (mp_ptr, mp_ptr, mp_srcptr, mp_size_t);
+
+mp_limb_t mpn_lshift (mp_ptr, mp_srcptr, mp_size_t, unsigned int);
+mp_limb_t mpn_rshift (mp_ptr, mp_srcptr, mp_size_t, unsigned int);
+
+mp_bitcnt_t mpn_scan0 (mp_srcptr, mp_bitcnt_t);
+mp_bitcnt_t mpn_scan1 (mp_srcptr, mp_bitcnt_t);
+
+void mpn_com (mp_ptr, mp_srcptr, mp_size_t);
+mp_limb_t mpn_neg (mp_ptr, mp_srcptr, mp_size_t);
+
+mp_bitcnt_t mpn_popcount (mp_srcptr, mp_size_t);
+
+mp_limb_t mpn_invert_3by2 (mp_limb_t, mp_limb_t);
+#define mpn_invert_limb(x) mpn_invert_3by2 ((x), 0)
+
+size_t mpn_get_str (unsigned char *, int, mp_ptr, mp_size_t);
+mp_size_t mpn_set_str (mp_ptr, const unsigned char *, size_t, int);
+
+void mpz_init (mpz_t);
+void mpz_init2 (mpz_t, mp_bitcnt_t);
+void mpz_clear (mpz_t);
+
+#define mpz_odd_p(z) (((z)->_mp_size != 0) & (int) (z)->_mp_d[0])
+#define mpz_even_p(z) (! mpz_odd_p (z))
+
+int mpz_sgn (const mpz_t);
+int mpz_cmp_si (const mpz_t, long);
+int mpz_cmp_ui (const mpz_t, unsigned long);
+int mpz_cmp (const mpz_t, const mpz_t);
+int mpz_cmpabs_ui (const mpz_t, unsigned long);
+int mpz_cmpabs (const mpz_t, const mpz_t);
+int mpz_cmp_d (const mpz_t, double);
+int mpz_cmpabs_d (const mpz_t, double);
+
+void mpz_abs (mpz_t, const mpz_t);
+void mpz_neg (mpz_t, const mpz_t);
+void mpz_swap (mpz_t, mpz_t);
+
+void mpz_add_ui (mpz_t, const mpz_t, unsigned long);
+void mpz_add (mpz_t, const mpz_t, const mpz_t);
+void mpz_sub_ui (mpz_t, const mpz_t, unsigned long);
+void mpz_ui_sub (mpz_t, unsigned long, const mpz_t);
+void mpz_sub (mpz_t, const mpz_t, const mpz_t);
+
+void mpz_mul_si (mpz_t, const mpz_t, long int);
+void mpz_mul_ui (mpz_t, const mpz_t, unsigned long int);
+void mpz_mul (mpz_t, const mpz_t, const mpz_t);
+void mpz_mul_2exp (mpz_t, const mpz_t, mp_bitcnt_t);
+void mpz_addmul_ui (mpz_t, const mpz_t, unsigned long int);
+void mpz_addmul (mpz_t, const mpz_t, const mpz_t);
+void mpz_submul_ui (mpz_t, const mpz_t, unsigned long int);
+void mpz_submul (mpz_t, const mpz_t, const mpz_t);
+
+void mpz_cdiv_qr (mpz_t, mpz_t, const mpz_t, const mpz_t);
+void mpz_fdiv_qr (mpz_t, mpz_t, const mpz_t, const mpz_t);
+void mpz_tdiv_qr (mpz_t, mpz_t, const mpz_t, const mpz_t);
+void mpz_cdiv_q (mpz_t, const mpz_t, const mpz_t);
+void mpz_fdiv_q (mpz_t, const mpz_t, const mpz_t);
+void mpz_tdiv_q (mpz_t, const mpz_t, const mpz_t);
+void mpz_cdiv_r (mpz_t, const mpz_t, const mpz_t);
+void mpz_fdiv_r (mpz_t, const mpz_t, const mpz_t);
+void mpz_tdiv_r (mpz_t, const mpz_t, const mpz_t);
+
+void mpz_cdiv_q_2exp (mpz_t, const mpz_t, mp_bitcnt_t);
+void mpz_fdiv_q_2exp (mpz_t, const mpz_t, mp_bitcnt_t);
+void mpz_tdiv_q_2exp (mpz_t, const mpz_t, mp_bitcnt_t);
+void mpz_cdiv_r_2exp (mpz_t, const mpz_t, mp_bitcnt_t);
+void mpz_fdiv_r_2exp (mpz_t, const mpz_t, mp_bitcnt_t);
+void mpz_tdiv_r_2exp (mpz_t, const mpz_t, mp_bitcnt_t);
+
+void mpz_mod (mpz_t, const mpz_t, const mpz_t);
+
+void mpz_divexact (mpz_t, const mpz_t, const mpz_t);
+
+int mpz_divisible_p (const mpz_t, const mpz_t);
+int mpz_congruent_p (const mpz_t, const mpz_t, const mpz_t);
+
+unsigned long mpz_cdiv_qr_ui (mpz_t, mpz_t, const mpz_t, unsigned long);
+unsigned long mpz_fdiv_qr_ui (mpz_t, mpz_t, const mpz_t, unsigned long);
+unsigned long mpz_tdiv_qr_ui (mpz_t, mpz_t, const mpz_t, unsigned long);
+unsigned long mpz_cdiv_q_ui (mpz_t, const mpz_t, unsigned long);
+unsigned long mpz_fdiv_q_ui (mpz_t, const mpz_t, unsigned long);
+unsigned long mpz_tdiv_q_ui (mpz_t, const mpz_t, unsigned long);
+unsigned long mpz_cdiv_r_ui (mpz_t, const mpz_t, unsigned long);
+unsigned long mpz_fdiv_r_ui (mpz_t, const mpz_t, unsigned long);
+unsigned long mpz_tdiv_r_ui (mpz_t, const mpz_t, unsigned long);
+unsigned long mpz_cdiv_ui (const mpz_t, unsigned long);
+unsigned long mpz_fdiv_ui (const mpz_t, unsigned long);
+unsigned long mpz_tdiv_ui (const mpz_t, unsigned long);
+
+unsigned long mpz_mod_ui (mpz_t, const mpz_t, unsigned long);
+
+void mpz_divexact_ui (mpz_t, const mpz_t, unsigned long);
+
+int mpz_divisible_ui_p (const mpz_t, unsigned long);
+
+unsigned long mpz_gcd_ui (mpz_t, const mpz_t, unsigned long);
+void mpz_gcd (mpz_t, const mpz_t, const mpz_t);
+void mpz_gcdext (mpz_t, mpz_t, mpz_t, const mpz_t, const mpz_t);
+void mpz_lcm_ui (mpz_t, const mpz_t, unsigned long);
+void mpz_lcm (mpz_t, const mpz_t, const mpz_t);
+int mpz_invert (mpz_t, const mpz_t, const mpz_t);
+
+void mpz_sqrtrem (mpz_t, mpz_t, const mpz_t);
+void mpz_sqrt (mpz_t, const mpz_t);
+int mpz_perfect_square_p (const mpz_t);
+
+void mpz_pow_ui (mpz_t, const mpz_t, unsigned long);
+void mpz_ui_pow_ui (mpz_t, unsigned long, unsigned long);
+void mpz_powm (mpz_t, const mpz_t, const mpz_t, const mpz_t);
+void mpz_powm_ui (mpz_t, const mpz_t, unsigned long, const mpz_t);
+
+void mpz_rootrem (mpz_t, mpz_t, const mpz_t, unsigned long);
+int mpz_root (mpz_t, const mpz_t, unsigned long);
+
+void mpz_fac_ui (mpz_t, unsigned long);
+void mpz_2fac_ui (mpz_t, unsigned long);
+void mpz_mfac_uiui (mpz_t, unsigned long, unsigned long);
+void mpz_bin_uiui (mpz_t, unsigned long, unsigned long);
+
+int mpz_probab_prime_p (const mpz_t, int);
+
+int mpz_tstbit (const mpz_t, mp_bitcnt_t);
+void mpz_setbit (mpz_t, mp_bitcnt_t);
+void mpz_clrbit (mpz_t, mp_bitcnt_t);
+void mpz_combit (mpz_t, mp_bitcnt_t);
+
+void mpz_com (mpz_t, const mpz_t);
+void mpz_and (mpz_t, const mpz_t, const mpz_t);
+void mpz_ior (mpz_t, const mpz_t, const mpz_t);
+void mpz_xor (mpz_t, const mpz_t, const mpz_t);
+
+mp_bitcnt_t mpz_popcount (const mpz_t);
+mp_bitcnt_t mpz_hamdist (const mpz_t, const mpz_t);
+mp_bitcnt_t mpz_scan0 (const mpz_t, mp_bitcnt_t);
+mp_bitcnt_t mpz_scan1 (const mpz_t, mp_bitcnt_t);
+
+int mpz_fits_slong_p (const mpz_t);
+int mpz_fits_ulong_p (const mpz_t);
+int mpz_fits_sint_p (const mpz_t);
+int mpz_fits_uint_p (const mpz_t);
+int mpz_fits_sshort_p (const mpz_t);
+int mpz_fits_ushort_p (const mpz_t);
+long int mpz_get_si (const mpz_t);
+unsigned long int mpz_get_ui (const mpz_t);
+double mpz_get_d (const mpz_t);
+size_t mpz_size (const mpz_t);
+mp_limb_t mpz_getlimbn (const mpz_t, mp_size_t);
+
+void mpz_realloc2 (mpz_t, mp_bitcnt_t);
+mp_srcptr mpz_limbs_read (mpz_srcptr);
+mp_ptr mpz_limbs_modify (mpz_t, mp_size_t);
+mp_ptr mpz_limbs_write (mpz_t, mp_size_t);
+void mpz_limbs_finish (mpz_t, mp_size_t);
+mpz_srcptr mpz_roinit_n (mpz_t, mp_srcptr, mp_size_t);
+
+#define MPZ_ROINIT_N(xp, xs) {{0, (xs),(xp) }}
+
+void mpz_set_si (mpz_t, signed long int);
+void mpz_set_ui (mpz_t, unsigned long int);
+void mpz_set (mpz_t, const mpz_t);
+void mpz_set_d (mpz_t, double);
+
+void mpz_init_set_si (mpz_t, signed long int);
+void mpz_init_set_ui (mpz_t, unsigned long int);
+void mpz_init_set (mpz_t, const mpz_t);
+void mpz_init_set_d (mpz_t, double);
+
+size_t mpz_sizeinbase (const mpz_t, int);
+char *mpz_get_str (char *, int, const mpz_t);
+int mpz_set_str (mpz_t, const char *, int);
+int mpz_init_set_str (mpz_t, const char *, int);
+
+/* This long list taken from gmp.h. */
+/* For reference, "defined(EOF)" cannot be used here. In g++ 2.95.4,
+ <iostream> defines EOF but not FILE. */
+#if defined (FILE) \
+ || defined (H_STDIO) \
+ || defined (_H_STDIO) /* AIX */ \
+ || defined (_STDIO_H) /* glibc, Sun, SCO */ \
+ || defined (_STDIO_H_) /* BSD, OSF */ \
+ || defined (__STDIO_H) /* Borland */ \
+ || defined (__STDIO_H__) /* IRIX */ \
+ || defined (_STDIO_INCLUDED) /* HPUX */ \
+ || defined (__dj_include_stdio_h_) /* DJGPP */ \
+ || defined (_FILE_DEFINED) /* Microsoft */ \
+ || defined (__STDIO__) /* Apple MPW MrC */ \
+ || defined (_MSL_STDIO_H) /* Metrowerks */ \
+ || defined (_STDIO_H_INCLUDED) /* QNX4 */ \
+ || defined (_ISO_STDIO_ISO_H) /* Sun C++ */ \
+ || defined (__STDIO_LOADED) /* VMS */ \
+ || defined (_STDIO) /* HPE NonStop */ \
+ || defined (__DEFINED_FILE) /* musl */
+size_t mpz_out_str (FILE *, int, const mpz_t);
+#endif
+
+void mpz_import (mpz_t, size_t, int, size_t, int, size_t, const void *);
+void *mpz_export (void *, size_t *, int, size_t, int, size_t, const mpz_t);
+
+#if defined (__cplusplus)
+}
+#endif
+#endif /* __MINI_GMP_H__ */
diff --git a/lib/minmax.h b/lib/minmax.h
index bbf14163c1b..b4b1345bbce 100644
--- a/lib/minmax.h
+++ b/lib/minmax.h
@@ -1,19 +1,19 @@
/* MIN, MAX macros.
- Copyright (C) 1995, 1998, 2001, 2003, 2005, 2009-2017 Free Software
+ Copyright (C) 1995, 1998, 2001, 2003, 2005, 2009-2022 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 file is free software: you can redistribute it and/or modify
+ it under the terms of the GNU Lesser General Public License as
+ published by the Free Software Foundation; either version 2.1 of the
+ License, or (at your option) any later version.
- This program is distributed in the hope that it will be useful,
+ This file 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.
+ GNU Lesser General Public License for more details.
- You should have received a copy of the GNU General Public License
- along with this program; if not, see <https://www.gnu.org/licenses/>. */
+ You should have received a copy of the GNU Lesser General Public License
+ along with this program. If not, see <https://www.gnu.org/licenses/>. */
#ifndef _MINMAX_H
#define _MINMAX_H
diff --git a/lib/mkostemp.c b/lib/mkostemp.c
index f1ce93babea..eae289aff94 100644
--- a/lib/mkostemp.c
+++ b/lib/mkostemp.c
@@ -1,18 +1,18 @@
-/* Copyright (C) 1998-1999, 2001, 2005-2007, 2009-2017 Free Software
+/* Copyright (C) 1998-1999, 2001, 2005-2007, 2009-2022 Free Software
Foundation, Inc.
This file is derived from the one in the GNU C Library.
- This program is free software: you can redistribute it and/or modify
- it under the terms of the GNU General Public License as published by
- the Free Software Foundation; either version 3 of the License, or
- (at your option) any later version.
+ This file is free software: you can redistribute it and/or modify
+ it under the terms of the GNU Lesser General Public License as
+ published by the Free Software Foundation; either version 2.1 of the
+ License, or (at your option) any later version.
- This program is distributed in the hope that it will be useful,
+ This file 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.
+ GNU Lesser General Public License for more details.
- You should have received a copy of the GNU General Public License
+ You should have received a copy of the GNU Lesser General Public License
along with this program. If not, see <https://www.gnu.org/licenses/>. */
#if !_LIBC
diff --git a/lib/mktime-internal.h b/lib/mktime-internal.h
index 00e58abdd6c..170764eabc8 100644
--- a/lib/mktime-internal.h
+++ b/lib/mktime-internal.h
@@ -1,37 +1,79 @@
-/* mktime variant that also uses an offset guess
+/* Internals of mktime and related functions
+ Copyright 2016-2022 Free Software Foundation, Inc.
+ This file is part of the GNU C Library.
+ Contributed by Paul Eggert <eggert@cs.ucla.edu>.
- Copyright 2016-2017 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
+ The GNU C Library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Lesser General Public
License as published by the Free Software Foundation; either
- version 3 of the License, or (at your option) any later version.
+ version 2.1 of the License, or (at your option) any later version.
- This program is distributed in the hope that it will be useful,
+ The GNU C Library is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- General Public License for more details.
+ Lesser 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
+ You should have received a copy of the GNU Lesser General Public
+ License along with the GNU C Library; if not, see
<https://www.gnu.org/licenses/>. */
-#include <time.h>
+#ifndef _LIBC
+# include <time.h>
+#endif
/* mktime_offset_t is a signed type wide enough to hold a UTC offset
in seconds, and used as part of the type of the offset-guess
- argument to mktime_internal. Use time_t on platforms where time_t
+ argument to mktime_internal. In Glibc, it is always long int.
+ When in Gnulib, use time_t on platforms where time_t
is signed, to be compatible with platforms like BeOS that export
this implementation detail of mktime. On platforms where time_t is
unsigned, GNU and POSIX code can assume 'int' is at least 32 bits
which is wide enough for a UTC offset. */
-
-#if TIME_T_IS_SIGNED
+#ifdef _LIBC
+typedef long int mktime_offset_t;
+#elif defined TIME_T_IS_SIGNED
typedef time_t mktime_offset_t;
#else
typedef int mktime_offset_t;
#endif
-time_t mktime_internal (struct tm *,
- struct tm * (*) (time_t const *, struct tm *),
- mktime_offset_t *);
+/* The source code uses identifiers like __time64_t for glibc
+ timestamps that can contain 64-bit values even when time_t is only
+ 32 bits. These are just macros for the ordinary identifiers unless
+ compiling within glibc when time_t is 32 bits. */
+#if ! (defined _LIBC && __TIMESIZE != 64)
+# undef __time64_t
+# define __time64_t time_t
+# define __gmtime64_r __gmtime_r
+# define __localtime64_r __localtime_r
+# define __mktime64 mktime
+# define __timegm64 timegm
+#endif
+
+#ifndef _LIBC
+
+/* Although glibc source code uses leading underscores, Gnulib wants
+ ordinary names.
+
+ Portable standalone applications should supply a <time.h> that
+ declares a POSIX-compliant localtime_r, for the benefit of older
+ implementations that lack localtime_r or have a nonstandard one.
+ Similarly for gmtime_r. See the gnulib time_r module for one way
+ to implement this. */
+
+# undef __gmtime_r
+# undef __localtime_r
+# define __gmtime_r gmtime_r
+# define __localtime_r localtime_r
+
+# define __mktime_internal mktime_internal
+
+#endif
+
+/* Subroutine of mktime. Return the time_t representation of TP and
+ normalize TP, given that a struct tm * maps to a time_t as performed
+ by FUNC. Record next guess for localtime-gmtime offset in *OFFSET. */
+extern __time64_t __mktime_internal (struct tm *tp,
+ struct tm *(*func) (__time64_t const *,
+ struct tm *),
+ mktime_offset_t *offset) attribute_hidden;
diff --git a/lib/mktime.c b/lib/mktime.c
index dd7f0a3ab34..7dc9d67ef9d 100644
--- a/lib/mktime.c
+++ b/lib/mktime.c
@@ -1,43 +1,37 @@
/* Convert a 'struct tm' to a time_t value.
- Copyright (C) 1993-2017 Free Software Foundation, Inc.
+ Copyright (C) 1993-2022 Free Software Foundation, Inc.
This file is part of the GNU C Library.
Contributed by Paul Eggert <eggert@twinsun.com>.
The GNU C Library is free software; you can redistribute it and/or
- modify it under the terms of the GNU General Public
+ modify it under the terms of the GNU Lesser General Public
License as published by the Free Software Foundation; either
- version 3 of the License, or (at your option) any later version.
+ version 2.1 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.
+ Lesser General Public License for more details.
- You should have received a copy of the GNU General Public
+ You should have received a copy of the GNU Lesser General Public
License along with the GNU C Library; if not, see
<https://www.gnu.org/licenses/>. */
-/* Define this to 1 to have a standalone program to test this implementation of
- mktime. */
-#ifndef DEBUG_MKTIME
-# define DEBUG_MKTIME 0
-#endif
-
/* The following macros influence what gets defined when this file is compiled:
Macro/expression Which gnulib module This compilation unit
should define
+ _LIBC (glibc proper) mktime
+
NEED_MKTIME_WORKING mktime rpl_mktime
|| NEED_MKTIME_WINDOWS
NEED_MKTIME_INTERNAL mktime-internal mktime_internal
-
- DEBUG_MKTIME (defined manually) my_mktime, main
*/
-#if !defined _LIBC && !DEBUG_MKTIME
-# include <config.h>
+#ifndef _LIBC
+# include <libc-config.h>
#endif
/* Assume that leap seconds are possible, unless told otherwise.
@@ -49,47 +43,87 @@
#include <time.h>
+#include <errno.h>
#include <limits.h>
#include <stdbool.h>
+#include <stdlib.h>
+#include <string.h>
#include <intprops.h>
#include <verify.h>
-#if DEBUG_MKTIME
-# include <stdio.h>
-# include <stdlib.h>
-# include <string.h>
-/* Make it work even if the system's libc has its own mktime routine. */
-# undef mktime
-# define mktime my_mktime
+#ifndef NEED_MKTIME_INTERNAL
+# define NEED_MKTIME_INTERNAL 0
#endif
+#ifndef NEED_MKTIME_WINDOWS
+# define NEED_MKTIME_WINDOWS 0
+#endif
+#ifndef NEED_MKTIME_WORKING
+# define NEED_MKTIME_WORKING 0
+#endif
+
+#include "mktime-internal.h"
-#if NEED_MKTIME_WINDOWS /* on native Windows */
-# include <stdlib.h>
-# include <string.h>
+#if !defined _LIBC && (NEED_MKTIME_WORKING || NEED_MKTIME_WINDOWS)
+static void
+my_tzset (void)
+{
+# if NEED_MKTIME_WINDOWS
+ /* Rectify the value of the environment variable TZ.
+ There are four possible kinds of such values:
+ - Traditional US time zone names, e.g. "PST8PDT". Syntax: see
+ <https://docs.microsoft.com/en-us/cpp/c-runtime-library/reference/tzset>
+ - Time zone names based on geography, that contain one or more
+ slashes, e.g. "Europe/Moscow".
+ - Time zone names based on geography, without slashes, e.g.
+ "Singapore".
+ - Time zone names that contain explicit DST rules. Syntax: see
+ <https://pubs.opengroup.org/onlinepubs/9699919799/basedefs/V1_chap08.html#tag_08_03>
+ The Microsoft CRT understands only the first kind. It produces incorrect
+ results if the value of TZ is of the other kinds.
+ But in a Cygwin environment, /etc/profile.d/tzset.sh sets TZ to a value
+ of the second kind for most geographies, or of the first kind in a few
+ other geographies. If it is of the second kind, neutralize it. For the
+ Microsoft CRT, an absent or empty TZ means the time zone that the user
+ has set in the Windows Control Panel.
+ If the value of TZ is of the third or fourth kind -- Cygwin programs
+ understand these syntaxes as well --, it does not matter whether we
+ neutralize it or not, since these values occur only when a Cygwin user
+ has set TZ explicitly; this case is 1. rare and 2. under the user's
+ responsibility. */
+ const char *tz = getenv ("TZ");
+ if (tz != NULL && strchr (tz, '/') != NULL)
+ _putenv ("TZ=");
+# else
+ tzset ();
+# endif
+}
+# undef __tzset
+# define __tzset() my_tzset ()
#endif
-#if NEED_MKTIME_WORKING || NEED_MKTIME_INTERNAL || DEBUG_MKTIME
+#if defined _LIBC || NEED_MKTIME_WORKING || NEED_MKTIME_INTERNAL
/* A signed type that can represent an integer number of years
- multiplied by three times the number of seconds in a year. It is
+ multiplied by four times the number of seconds in a year. It is
needed when converting a tm_year value times the number of seconds
- in a year. The factor of three comes because these products need
+ in a year. The factor of four comes because these products need
to be subtracted from each other, and sometimes with an offset
- added to them, without worrying about overflow.
+ added to them, and then with another timestamp added, without
+ worrying about overflow.
- Much of the code uses long_int to represent time_t values, to
- lessen the hassle of dealing with platforms where time_t is
+ Much of the code uses long_int to represent __time64_t values, to
+ lessen the hassle of dealing with platforms where __time64_t is
unsigned, and because long_int should suffice to represent all
- time_t values that mktime can generate even on platforms where
- time_t is excessively wide. */
+ __time64_t values that mktime can generate even on platforms where
+ __time64_t is wider than the int components of struct tm. */
-#if INT_MAX <= LONG_MAX / 3 / 366 / 24 / 60 / 60
+#if INT_MAX <= LONG_MAX / 4 / 366 / 24 / 60 / 60
typedef long int long_int;
#else
typedef long long int long_int;
#endif
-verify (INT_MAX <= TYPE_MAXIMUM (long_int) / 3 / 366 / 24 / 60 / 60);
+verify (INT_MAX <= TYPE_MAXIMUM (long_int) / 4 / 366 / 24 / 60 / 60);
/* Shift A right by B bits portably, by dividing A by 2**B and
truncating towards minus infinity. B should be in the range 0 <= B
@@ -107,19 +141,18 @@ shr (long_int a, int b)
long_int one = 1;
return (-one >> 1 == -1
? a >> b
- : a / (one << b) - (a % (one << b) < 0));
+ : (a + (a < 0)) / (one << b) - (a < 0));
}
-/* Bounds for the intersection of time_t and long_int. */
+/* Bounds for the intersection of __time64_t and long_int. */
static long_int const mktime_min
- = ((TYPE_SIGNED (time_t) && TYPE_MINIMUM (time_t) < TYPE_MINIMUM (long_int))
- ? TYPE_MINIMUM (long_int) : TYPE_MINIMUM (time_t));
+ = ((TYPE_SIGNED (__time64_t)
+ && TYPE_MINIMUM (__time64_t) < TYPE_MINIMUM (long_int))
+ ? TYPE_MINIMUM (long_int) : TYPE_MINIMUM (__time64_t));
static long_int const mktime_max
- = (TYPE_MAXIMUM (long_int) < TYPE_MAXIMUM (time_t)
- ? TYPE_MAXIMUM (long_int) : TYPE_MAXIMUM (time_t));
-
-verify (TYPE_IS_INTEGER (time_t));
+ = (TYPE_MAXIMUM (long_int) < TYPE_MAXIMUM (__time64_t)
+ ? TYPE_MAXIMUM (long_int) : TYPE_MAXIMUM (__time64_t));
#define EPOCH_YEAR 1970
#define TM_YEAR_BASE 1900
@@ -150,19 +183,6 @@ const unsigned short int __mon_yday[2][13] =
};
-#ifdef _LIBC
-typedef time_t mktime_offset_t;
-#else
-/* Portable standalone applications should supply a <time.h> that
- declares a POSIX-compliant localtime_r, for the benefit of older
- implementations that lack localtime_r or have a nonstandard one.
- See the gnulib time_r module for one way to implement this. */
-# undef __localtime_r
-# define __localtime_r localtime_r
-# define __mktime_internal mktime_internal
-# include "mktime-internal.h"
-#endif
-
/* Do the values A and B differ according to the rules for tm_isdst?
A and B differ if one is zero and the other positive. */
static bool
@@ -176,9 +196,10 @@ isdst_differ (int a, int b)
were not adjusted between the timestamps.
The YEAR values uses the same numbering as TP->tm_year. Values
- need not be in the usual range. However, YEAR1 must not overflow
- when multiplied by three times the number of seconds in a year, and
- likewise for YDAY1 and three times the number of seconds in a day. */
+ need not be in the usual range. However, YEAR1 - YEAR0 must not
+ overflow even when multiplied by three times the number of seconds
+ in a year, and likewise for YDAY1 - YDAY0 and three times the
+ number of seconds in a day. */
static long_int
ydhms_diff (long_int year1, long_int yday1, int hour1, int min1, int sec1,
@@ -190,8 +211,8 @@ ydhms_diff (long_int year1, long_int yday1, int hour1, int min1, int sec1,
Take care to avoid integer overflow here. */
int a4 = shr (year1, 2) + shr (TM_YEAR_BASE, 2) - ! (year1 & 3);
int b4 = shr (year0, 2) + shr (TM_YEAR_BASE, 2) - ! (year0 & 3);
- int a100 = a4 / 25 - (a4 % 25 < 0);
- int b100 = b4 / 25 - (b4 % 25 < 0);
+ int a100 = (a4 + (a4 < 0)) / 25 - (a4 < 0);
+ int b100 = (b4 + (b4 < 0)) / 25 - (b4 < 0);
int a400 = shr (a100, 2);
int b400 = shr (b100, 2);
int intervening_leap_days = (a4 - b4) - (a100 - b100) + (a400 - b400);
@@ -213,109 +234,94 @@ long_int_avg (long_int a, long_int b)
return shr (a, 1) + shr (b, 1) + ((a | b) & 1);
}
-/* Return a time_t value corresponding to (YEAR-YDAY HOUR:MIN:SEC),
- assuming that T corresponds to *TP and that no clock adjustments
- occurred between *TP and the desired time.
- Although T and the returned value are of type long_int,
- they represent time_t values and must be in time_t range.
- If TP is null, return a value not equal to T; this avoids false matches.
+/* Return a long_int value corresponding to (YEAR-YDAY HOUR:MIN:SEC)
+ minus *TP seconds, assuming no clock adjustments occurred between
+ the two timestamps.
+
YEAR and YDAY must not be so large that multiplying them by three times the
number of seconds in a year (or day, respectively) would overflow long_int.
- If the returned value would be out of range, yield the minimal or
- maximal in-range value, except do not yield a value equal to T. */
+ *TP should be in the usual range. */
static long_int
-guess_time_tm (long_int year, long_int yday, int hour, int min, int sec,
- long_int t, const struct tm *tp)
+tm_diff (long_int year, long_int yday, int hour, int min, int sec,
+ struct tm const *tp)
{
- if (tp)
- {
- long_int result;
- long_int d = ydhms_diff (year, yday, hour, min, sec,
- tp->tm_year, tp->tm_yday,
- tp->tm_hour, tp->tm_min, tp->tm_sec);
- if (! INT_ADD_WRAPV (t, d, &result))
- return result;
- }
-
- /* Overflow occurred one way or another. Return the nearest result
- that is actually in range, except don't report a zero difference
- if the actual difference is nonzero, as that would cause a false
- match; and don't oscillate between two values, as that would
- confuse the spring-forward gap detector. */
- return (t < long_int_avg (mktime_min, mktime_max)
- ? (t <= mktime_min + 1 ? t + 1 : mktime_min)
- : (mktime_max - 1 <= t ? t - 1 : mktime_max));
+ return ydhms_diff (year, yday, hour, min, sec,
+ tp->tm_year, tp->tm_yday,
+ tp->tm_hour, tp->tm_min, tp->tm_sec);
}
/* Use CONVERT to convert T to a struct tm value in *TM. T must be in
- range for time_t. Return TM if successful, NULL if T is out of
- range for CONVERT. */
+ range for __time64_t. Return TM if successful, NULL (setting errno) on
+ failure. */
static struct tm *
-convert_time (struct tm *(*convert) (const time_t *, struct tm *),
+convert_time (struct tm *(*convert) (const __time64_t *, struct tm *),
long_int t, struct tm *tm)
{
- time_t x = t;
+ __time64_t x = t;
return convert (&x, tm);
}
/* Use CONVERT to convert *T to a broken down time in *TP.
If *T is out of range for conversion, adjust it so that
it is the nearest in-range value and then convert that.
- A value is in range if it fits in both time_t and long_int. */
+ A value is in range if it fits in both __time64_t and long_int.
+ Return TP on success, NULL (setting errno) on failure. */
static struct tm *
-ranged_convert (struct tm *(*convert) (const time_t *, struct tm *),
+ranged_convert (struct tm *(*convert) (const __time64_t *, struct tm *),
long_int *t, struct tm *tp)
{
- struct tm *r;
- if (*t < mktime_min)
- *t = mktime_min;
- else if (mktime_max < *t)
- *t = mktime_max;
- r = convert_time (convert, *t, tp);
-
- if (!r && *t)
+ long_int t1 = (*t < mktime_min ? mktime_min
+ : *t <= mktime_max ? *t : mktime_max);
+ struct tm *r = convert_time (convert, t1, tp);
+ if (r)
{
- long_int bad = *t;
- long_int ok = 0;
+ *t = t1;
+ return r;
+ }
+ if (errno != EOVERFLOW)
+ return NULL;
- /* BAD is a known unconvertible value, and OK is a known good one.
- Use binary search to narrow the range between BAD and OK until
- they differ by 1. */
- while (true)
- {
- long_int mid = long_int_avg (ok, bad);
- if (mid != ok && mid != bad)
- break;
- r = convert_time (convert, mid, tp);
- if (r)
- ok = mid;
- else
- bad = mid;
- }
+ long_int bad = t1;
+ long_int ok = 0;
+ struct tm oktm; oktm.tm_sec = -1;
- if (!r && ok)
- {
- /* The last conversion attempt failed;
- revert to the most recent successful attempt. */
- r = convert_time (convert, ok, tp);
- }
+ /* BAD is a known out-of-range value, and OK is a known in-range one.
+ Use binary search to narrow the range between BAD and OK until
+ they differ by 1. */
+ while (true)
+ {
+ long_int mid = long_int_avg (ok, bad);
+ if (mid == ok || mid == bad)
+ break;
+ if (convert_time (convert, mid, tp))
+ ok = mid, oktm = *tp;
+ else if (errno != EOVERFLOW)
+ return NULL;
+ else
+ bad = mid;
}
- return r;
+ if (oktm.tm_sec < 0)
+ return NULL;
+ *t = ok;
+ *tp = oktm;
+ return tp;
}
-/* Convert *TP to a time_t value, inverting
+
+/* Convert *TP to a __time64_t value, inverting
the monotonic and mostly-unit-linear conversion function CONVERT.
Use *OFFSET to keep track of a guess at the offset of the result,
compared to what the result would be for UTC without leap seconds.
If *OFFSET's guess is correct, only one CONVERT call is needed.
+ If successful, set *TP to the canonicalized struct tm;
+ otherwise leave *TP alone, return ((time_t) -1) and set errno.
This function is external because it is used also by timegm.c. */
-time_t
+__time64_t
__mktime_internal (struct tm *tp,
- struct tm *(*convert) (const time_t *, struct tm *),
+ struct tm *(*convert) (const __time64_t *, struct tm *),
mktime_offset_t *offset)
{
- long_int t, gt, t0, t1, t2, dt;
struct tm tm;
/* The maximum number of probes (calls to CONVERT) should be enough
@@ -335,7 +341,7 @@ __mktime_internal (struct tm *tp,
int isdst = tp->tm_isdst;
/* 1 if the previous probe was DST. */
- int dst2;
+ int dst2 = 0;
/* Ensure that mon is in range, and set year accordingly. */
int mon_remainder = mon % 12;
@@ -355,6 +361,7 @@ __mktime_internal (struct tm *tp,
long_int lmday = mday;
long_int yday = mon_yday + lmday;
+ mktime_offset_t off = *offset;
int negative_offset_guess;
int sec_requested = sec;
@@ -362,7 +369,7 @@ __mktime_internal (struct tm *tp,
if (LEAP_SECONDS_POSSIBLE)
{
/* Handle out-of-range seconds specially,
- since ydhms_tm_diff assumes every minute has 60 seconds. */
+ since ydhms_diff assumes every minute has 60 seconds. */
if (sec < 0)
sec = 0;
if (59 < sec)
@@ -372,34 +379,47 @@ __mktime_internal (struct tm *tp,
/* Invert CONVERT by probing. First assume the same offset as last
time. */
- INT_SUBTRACT_WRAPV (0, *offset, &negative_offset_guess);
- t0 = ydhms_diff (year, yday, hour, min, sec,
- EPOCH_YEAR - TM_YEAR_BASE, 0, 0, 0, negative_offset_guess);
+ INT_SUBTRACT_WRAPV (0, off, &negative_offset_guess);
+ long_int t0 = ydhms_diff (year, yday, hour, min, sec,
+ EPOCH_YEAR - TM_YEAR_BASE, 0, 0, 0,
+ negative_offset_guess);
+ long_int t = t0, t1 = t0, t2 = t0;
/* Repeatedly use the error to improve the guess. */
- for (t = t1 = t2 = t0, dst2 = 0;
- (gt = guess_time_tm (year, yday, hour, min, sec, t,
- ranged_convert (convert, &t, &tm)),
- t != gt);
- t1 = t2, t2 = t, t = gt, dst2 = tm.tm_isdst != 0)
- if (t == t1 && t != t2
- && (tm.tm_isdst < 0
- || (isdst < 0
- ? dst2 <= (tm.tm_isdst != 0)
- : (isdst != 0) != (tm.tm_isdst != 0))))
- /* We can't possibly find a match, as we are oscillating
- between two values. The requested time probably falls
- within a spring-forward gap of size GT - T. Follow the common
- practice in this case, which is to return a time that is GT - T
- away from the requested time, preferring a time whose
- tm_isdst differs from the requested value. (If no tm_isdst
- was requested and only one of the two values has a nonzero
- tm_isdst, prefer that value.) In practice, this is more
- useful than returning -1. */
- goto offset_found;
- else if (--remaining_probes == 0)
- return -1;
+ while (true)
+ {
+ if (! ranged_convert (convert, &t, &tm))
+ return -1;
+ long_int dt = tm_diff (year, yday, hour, min, sec, &tm);
+ if (dt == 0)
+ break;
+
+ if (t == t1 && t != t2
+ && (tm.tm_isdst < 0
+ || (isdst < 0
+ ? dst2 <= (tm.tm_isdst != 0)
+ : (isdst != 0) != (tm.tm_isdst != 0))))
+ /* We can't possibly find a match, as we are oscillating
+ between two values. The requested time probably falls
+ within a spring-forward gap of size DT. Follow the common
+ practice in this case, which is to return a time that is DT
+ away from the requested time, preferring a time whose
+ tm_isdst differs from the requested value. (If no tm_isdst
+ was requested and only one of the two values has a nonzero
+ tm_isdst, prefer that value.) In practice, this is more
+ useful than returning -1. */
+ goto offset_found;
+
+ remaining_probes--;
+ if (remaining_probes == 0)
+ {
+ __set_errno (EOVERFLOW);
+ return -1;
+ }
+
+ t1 = t2, t2 = t, t += dt, dst2 = tm.tm_isdst != 0;
+ }
/* We have a match. Check whether tm.tm_isdst has the requested
value, if any. */
@@ -409,8 +429,13 @@ __mktime_internal (struct tm *tp,
time with the right value, and use its UTC offset.
Heuristic: probe the adjacent timestamps in both directions,
- looking for the desired isdst. This should work for all real
- time zone histories in the tz database. */
+ looking for the desired isdst. If none is found within a
+ reasonable duration bound, assume a one-hour DST difference.
+ This should work for all real time zone histories in the tz
+ database. */
+
+ /* +1 if we wanted standard time but got DST, -1 if the reverse. */
+ int dst_difference = (isdst == 0) - (tm.tm_isdst == 0);
/* Distance between probes when looking for a DST boundary. In
tzdata2003a, the shortest period of DST is 601200 seconds
@@ -421,12 +446,14 @@ __mktime_internal (struct tm *tp,
periods when probing. */
int stride = 601200;
- /* The longest period of DST in tzdata2003a is 536454000 seconds
- (e.g., America/Jujuy starting 1946-10-01 01:00). The longest
- period of non-DST is much longer, but it makes no real sense
- to search for more than a year of non-DST, so use the DST
- max. */
- int duration_max = 536454000;
+ /* In TZDB 2021e, the longest period of DST (or of non-DST), in
+ which the DST (or adjacent DST) difference is not one hour,
+ is 457243209 seconds: e.g., America/Cambridge_Bay with leap
+ seconds, starting 1965-10-31 00:00 in a switch from
+ double-daylight time (-05) to standard time (-07), and
+ continuing to 1980-04-27 02:00 in a switch from standard time
+ (-07) to daylight time (-06). */
+ int duration_max = 457243209;
/* Search in both directions, so the maximum distance is half
the duration; add the stride to avoid off-by-1 problems. */
@@ -441,25 +468,43 @@ __mktime_internal (struct tm *tp,
if (! INT_ADD_WRAPV (t, delta * direction, &ot))
{
struct tm otm;
- ranged_convert (convert, &ot, &otm);
+ if (! ranged_convert (convert, &ot, &otm))
+ return -1;
if (! isdst_differ (isdst, otm.tm_isdst))
{
/* We found the desired tm_isdst.
Extrapolate back to the desired time. */
- t = guess_time_tm (year, yday, hour, min, sec, ot, &otm);
- ranged_convert (convert, &t, &tm);
- goto offset_found;
+ long_int gt = ot + tm_diff (year, yday, hour, min, sec,
+ &otm);
+ if (mktime_min <= gt && gt <= mktime_max)
+ {
+ if (convert_time (convert, gt, &tm))
+ {
+ t = gt;
+ goto offset_found;
+ }
+ if (errno != EOVERFLOW)
+ return -1;
+ }
}
}
}
+
+ /* No unusual DST offset was found nearby. Assume one-hour DST. */
+ t += 60 * 60 * dst_difference;
+ if (mktime_min <= t && t <= mktime_max && convert_time (convert, t, &tm))
+ goto offset_found;
+
+ __set_errno (EOVERFLOW);
+ return -1;
}
offset_found:
/* Set *OFFSET to the low-order bits of T - T0 - NEGATIVE_OFFSET_GUESS.
This is just a heuristic to speed up the next mktime call, and
correctness is unaffected if integer overflow occurs here. */
- INT_SUBTRACT_WRAPV (t, t0, &dt);
- INT_SUBTRACT_WRAPV (dt, negative_offset_guess, offset);
+ INT_SUBTRACT_WRAPV (t, t0, offset);
+ INT_SUBTRACT_WRAPV (*offset, negative_offset_guess, offset);
if (LEAP_SECONDS_POSSIBLE && sec_requested != tm.tm_sec)
{
@@ -469,8 +514,12 @@ __mktime_internal (struct tm *tp,
sec_adjustment -= sec;
sec_adjustment += sec_requested;
if (INT_ADD_WRAPV (t, sec_adjustment, &t)
- || ! (mktime_min <= t && t <= mktime_max)
- || ! convert_time (convert, t, &tm))
+ || ! (mktime_min <= t && t <= mktime_max))
+ {
+ __set_errno (EOVERFLOW);
+ return -1;
+ }
+ if (! convert_time (convert, t, &tm))
return -1;
}
@@ -478,213 +527,52 @@ __mktime_internal (struct tm *tp,
return t;
}
-#endif /* NEED_MKTIME_WORKING || NEED_MKTIME_INTERNAL || DEBUG_MKTIME */
+#endif /* _LIBC || NEED_MKTIME_WORKING || NEED_MKTIME_INTERNAL */
-#if NEED_MKTIME_WORKING || NEED_MKTIME_WINDOWS || DEBUG_MKTIME
-
-# if NEED_MKTIME_WORKING || DEBUG_MKTIME
-static mktime_offset_t localtime_offset;
-# endif
+#if defined _LIBC || NEED_MKTIME_WORKING || NEED_MKTIME_WINDOWS
-/* Convert *TP to a time_t value. */
-time_t
-mktime (struct tm *tp)
+/* Convert *TP to a __time64_t value. */
+__time64_t
+__mktime64 (struct tm *tp)
{
-# if NEED_MKTIME_WINDOWS
- /* Rectify the value of the environment variable TZ.
- There are four possible kinds of such values:
- - Traditional US time zone names, e.g. "PST8PDT". Syntax: see
- <https://msdn.microsoft.com/en-us/library/90s5c885.aspx>
- - Time zone names based on geography, that contain one or more
- slashes, e.g. "Europe/Moscow".
- - Time zone names based on geography, without slashes, e.g.
- "Singapore".
- - Time zone names that contain explicit DST rules. Syntax: see
- <http://pubs.opengroup.org/onlinepubs/9699919799/basedefs/V1_chap08.html#tag_08_03>
- The Microsoft CRT understands only the first kind. It produces incorrect
- results if the value of TZ is of the other kinds.
- But in a Cygwin environment, /etc/profile.d/tzset.sh sets TZ to a value
- of the second kind for most geographies, or of the first kind in a few
- other geographies. If it is of the second kind, neutralize it. For the
- Microsoft CRT, an absent or empty TZ means the time zone that the user
- has set in the Windows Control Panel.
- If the value of TZ is of the third or fourth kind -- Cygwin programs
- understand these syntaxes as well --, it does not matter whether we
- neutralize it or not, since these values occur only when a Cygwin user
- has set TZ explicitly; this case is 1. rare and 2. under the user's
- responsibility. */
- const char *tz = getenv ("TZ");
- if (tz != NULL && strchr (tz, '/') != NULL)
- _putenv ("TZ=");
-# endif
-
-# if NEED_MKTIME_WORKING || DEBUG_MKTIME
-# ifdef _LIBC
/* POSIX.1 8.1.1 requires that whenever mktime() is called, the
time zone names contained in the external variable 'tzname' shall
be set as if the tzset() function had been called. */
__tzset ();
-# elif HAVE_TZSET
- tzset ();
-# endif
- return __mktime_internal (tp, __localtime_r, &localtime_offset);
+# if defined _LIBC || NEED_MKTIME_WORKING
+ static mktime_offset_t localtime_offset;
+ return __mktime_internal (tp, __localtime64_r, &localtime_offset);
# else
# undef mktime
return mktime (tp);
# endif
}
+#endif /* _LIBC || NEED_MKTIME_WORKING || NEED_MKTIME_WINDOWS */
-#endif /* NEED_MKTIME_WORKING || NEED_MKTIME_WINDOWS || DEBUG_MKTIME */
-
-#ifdef weak_alias
-weak_alias (mktime, timelocal)
-#endif
-
-#ifdef _LIBC
-libc_hidden_def (mktime)
-libc_hidden_weak (timelocal)
-#endif
-
-#if DEBUG_MKTIME
+#if defined _LIBC && __TIMESIZE != 64
-static int
-not_equal_tm (const struct tm *a, const struct tm *b)
-{
- return ((a->tm_sec ^ b->tm_sec)
- | (a->tm_min ^ b->tm_min)
- | (a->tm_hour ^ b->tm_hour)
- | (a->tm_mday ^ b->tm_mday)
- | (a->tm_mon ^ b->tm_mon)
- | (a->tm_year ^ b->tm_year)
- | (a->tm_yday ^ b->tm_yday)
- | isdst_differ (a->tm_isdst, b->tm_isdst));
-}
+libc_hidden_def (__mktime64)
-static void
-print_tm (const struct tm *tp)
-{
- if (tp)
- printf ("%04d-%02d-%02d %02d:%02d:%02d yday %03d wday %d isdst %d",
- tp->tm_year + TM_YEAR_BASE, tp->tm_mon + 1, tp->tm_mday,
- tp->tm_hour, tp->tm_min, tp->tm_sec,
- tp->tm_yday, tp->tm_wday, tp->tm_isdst);
- else
- printf ("0");
-}
-
-static int
-check_result (time_t tk, struct tm tmk, time_t tl, const struct tm *lt)
-{
- if (tk != tl || !lt || not_equal_tm (&tmk, lt))
- {
- printf ("mktime (");
- print_tm (lt);
- printf (")\nyields (");
- print_tm (&tmk);
- printf (") == %ld, should be %ld\n", (long int) tk, (long int) tl);
- return 1;
- }
-
- return 0;
-}
-
-int
-main (int argc, char **argv)
+time_t
+mktime (struct tm *tp)
{
- int status = 0;
- struct tm tm, tmk, tml;
- struct tm *lt;
- time_t tk, tl, tl1;
- char trailer;
-
- /* Sanity check, plus call tzset. */
- tl = 0;
- if (! localtime (&tl))
+ struct tm tm = *tp;
+ __time64_t t = __mktime64 (&tm);
+ if (in_time_t_range (t))
{
- printf ("localtime (0) fails\n");
- status = 1;
+ *tp = tm;
+ return t;
}
-
- if ((argc == 3 || argc == 4)
- && (sscanf (argv[1], "%d-%d-%d%c",
- &tm.tm_year, &tm.tm_mon, &tm.tm_mday, &trailer)
- == 3)
- && (sscanf (argv[2], "%d:%d:%d%c",
- &tm.tm_hour, &tm.tm_min, &tm.tm_sec, &trailer)
- == 3))
- {
- tm.tm_year -= TM_YEAR_BASE;
- tm.tm_mon--;
- tm.tm_isdst = argc == 3 ? -1 : atoi (argv[3]);
- tmk = tm;
- tl = mktime (&tmk);
- lt = localtime_r (&tl, &tml);
- printf ("mktime returns %ld == ", (long int) tl);
- print_tm (&tmk);
- printf ("\n");
- status = check_result (tl, tmk, tl, lt);
- }
- else if (argc == 4 || (argc == 5 && strcmp (argv[4], "-") == 0))
+ else
{
- time_t from = atol (argv[1]);
- time_t by = atol (argv[2]);
- time_t to = atol (argv[3]);
-
- if (argc == 4)
- for (tl = from; by < 0 ? to <= tl : tl <= to; tl = tl1)
- {
- lt = localtime_r (&tl, &tml);
- if (lt)
- {
- tmk = tml;
- tk = mktime (&tmk);
- status |= check_result (tk, tmk, tl, &tml);
- }
- else
- {
- printf ("localtime_r (%ld) yields 0\n", (long int) tl);
- status = 1;
- }
- tl1 = tl + by;
- if ((tl1 < tl) != (by < 0))
- break;
- }
- else
- for (tl = from; by < 0 ? to <= tl : tl <= to; tl = tl1)
- {
- /* Null benchmark. */
- lt = localtime_r (&tl, &tml);
- if (lt)
- {
- tmk = tml;
- tk = tl;
- status |= check_result (tk, tmk, tl, &tml);
- }
- else
- {
- printf ("localtime_r (%ld) yields 0\n", (long int) tl);
- status = 1;
- }
- tl1 = tl + by;
- if ((tl1 < tl) != (by < 0))
- break;
- }
+ __set_errno (EOVERFLOW);
+ return -1;
}
- else
- printf ("Usage:\
-\t%s YYYY-MM-DD HH:MM:SS [ISDST] # Test given time.\n\
-\t%s FROM BY TO # Test values FROM, FROM+BY, ..., TO.\n\
-\t%s FROM BY TO - # Do not test those values (for benchmark).\n",
- argv[0], argv[0], argv[0]);
-
- return status;
}
-#endif /* DEBUG_MKTIME */
-
-/*
-Local Variables:
-compile-command: "gcc -DDEBUG_MKTIME -I. -Wall -W -O2 -g mktime.c -o mktime"
-End:
-*/
+#endif
+
+weak_alias (mktime, timelocal)
+libc_hidden_def (mktime)
+libc_hidden_weak (timelocal)
diff --git a/lib/nanosleep.c b/lib/nanosleep.c
new file mode 100644
index 00000000000..446794edc0b
--- /dev/null
+++ b/lib/nanosleep.c
@@ -0,0 +1,195 @@
+/* Provide a replacement for the POSIX nanosleep function.
+
+ Copyright (C) 1999-2000, 2002, 2004-2022 Free Software Foundation, Inc.
+
+ This file is free software: you can redistribute it and/or modify
+ it under the terms of the GNU Lesser General Public License as
+ published by the Free Software Foundation; either version 2.1 of the
+ License, or (at your option) any later version.
+
+ This file 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 Lesser General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public License
+ along with this program. If not, see <https://www.gnu.org/licenses/>. */
+
+/* written by Jim Meyering
+ and Bruno Haible for the native Windows part */
+
+#include <config.h>
+
+#include <time.h>
+
+#include "intprops.h"
+#include "verify.h"
+
+#include <stdbool.h>
+#include <stdio.h>
+#include <sys/types.h>
+#include <sys/select.h>
+#include <signal.h>
+
+#include <errno.h>
+
+#include <unistd.h>
+
+
+enum { BILLION = 1000 * 1000 * 1000 };
+
+#if HAVE_BUG_BIG_NANOSLEEP
+
+int
+nanosleep (const struct timespec *requested_delay,
+ struct timespec *remaining_delay)
+# undef nanosleep
+{
+ /* nanosleep mishandles large sleeps due to internal overflow problems.
+ The worst known case of this is Linux 2.6.9 with glibc 2.3.4, which
+ can't sleep more than 24.85 days (2^31 milliseconds). Similarly,
+ cygwin 1.5.x, which can't sleep more than 49.7 days (2^32 milliseconds).
+ Solve this by breaking the sleep up into smaller chunks. */
+
+ if (requested_delay->tv_nsec < 0 || BILLION <= requested_delay->tv_nsec)
+ {
+ errno = EINVAL;
+ return -1;
+ }
+
+ {
+ /* Verify that time_t is large enough. */
+ verify (TYPE_MAXIMUM (time_t) / 24 / 24 / 60 / 60);
+ const time_t limit = 24 * 24 * 60 * 60;
+ time_t seconds = requested_delay->tv_sec;
+ struct timespec intermediate;
+ intermediate.tv_nsec = requested_delay->tv_nsec;
+
+ while (limit < seconds)
+ {
+ int result;
+ intermediate.tv_sec = limit;
+ result = nanosleep (&intermediate, remaining_delay);
+ seconds -= limit;
+ if (result)
+ {
+ if (remaining_delay)
+ remaining_delay->tv_sec += seconds;
+ return result;
+ }
+ intermediate.tv_nsec = 0;
+ }
+ intermediate.tv_sec = seconds;
+ return nanosleep (&intermediate, remaining_delay);
+ }
+}
+
+#elif defined _WIN32 && ! defined __CYGWIN__
+/* Native Windows platforms. */
+
+# define WIN32_LEAN_AND_MEAN
+# include <windows.h>
+
+/* The Windows API function Sleep() has a resolution of about 15 ms and takes
+ at least 5 ms to execute. We use this function for longer time periods.
+ Additionally, we use busy-looping over short time periods, to get a
+ resolution of about 0.01 ms. In order to measure such short timespans,
+ we use the QueryPerformanceCounter() function. */
+
+int
+nanosleep (const struct timespec *requested_delay,
+ struct timespec *remaining_delay)
+{
+ static bool initialized;
+ /* Number of performance counter increments per nanosecond,
+ or zero if it could not be determined. */
+ static double ticks_per_nanosecond;
+
+ if (requested_delay->tv_nsec < 0 || BILLION <= requested_delay->tv_nsec)
+ {
+ errno = EINVAL;
+ return -1;
+ }
+
+ /* For requested delays of one second or more, 15ms resolution is
+ sufficient. */
+ if (requested_delay->tv_sec == 0)
+ {
+ if (!initialized)
+ {
+ /* Initialize ticks_per_nanosecond. */
+ LARGE_INTEGER ticks_per_second;
+
+ if (QueryPerformanceFrequency (&ticks_per_second))
+ ticks_per_nanosecond =
+ (double) ticks_per_second.QuadPart / 1000000000.0;
+
+ initialized = true;
+ }
+ if (ticks_per_nanosecond)
+ {
+ /* QueryPerformanceFrequency worked. We can use
+ QueryPerformanceCounter. Use a combination of Sleep and
+ busy-looping. */
+ /* Number of milliseconds to pass to the Sleep function.
+ Since Sleep can take up to 8 ms less or 8 ms more than requested
+ (or maybe more if the system is loaded), we subtract 10 ms. */
+ int sleep_millis = (int) requested_delay->tv_nsec / 1000000 - 10;
+ /* Determine how many ticks to delay. */
+ LONGLONG wait_ticks = requested_delay->tv_nsec * ticks_per_nanosecond;
+ /* Start. */
+ LARGE_INTEGER counter_before;
+ if (QueryPerformanceCounter (&counter_before))
+ {
+ /* Wait until the performance counter has reached this value.
+ We don't need to worry about overflow, because the performance
+ counter is reset at reboot, and with a frequency of 3.6E6
+ ticks per second 63 bits suffice for over 80000 years. */
+ LONGLONG wait_until = counter_before.QuadPart + wait_ticks;
+ /* Use Sleep for the longest part. */
+ if (sleep_millis > 0)
+ Sleep (sleep_millis);
+ /* Busy-loop for the rest. */
+ for (;;)
+ {
+ LARGE_INTEGER counter_after;
+ if (!QueryPerformanceCounter (&counter_after))
+ /* QueryPerformanceCounter failed, but succeeded earlier.
+ Should not happen. */
+ break;
+ if (counter_after.QuadPart >= wait_until)
+ /* The requested time has elapsed. */
+ break;
+ }
+ goto done;
+ }
+ }
+ }
+ /* Implementation for long delays and as fallback. */
+ Sleep (requested_delay->tv_sec * 1000 + requested_delay->tv_nsec / 1000000);
+
+ done:
+ /* Sleep is not interruptible. So there is no remaining delay. */
+ if (remaining_delay != NULL)
+ {
+ remaining_delay->tv_sec = 0;
+ remaining_delay->tv_nsec = 0;
+ }
+ return 0;
+}
+
+#else
+/* Other platforms lacking nanosleep.
+ It's not clear whether these are still practical porting targets.
+ For now, just fall back on pselect. */
+
+/* Suspend execution for at least *REQUESTED_DELAY seconds. The
+ *REMAINING_DELAY part isn't implemented yet. */
+
+int
+nanosleep (const struct timespec *requested_delay,
+ struct timespec *remaining_delay)
+{
+ return pselect (0, NULL, NULL, NULL, requested_delay, NULL);
+}
+#endif
diff --git a/lib/nproc.c b/lib/nproc.c
new file mode 100644
index 00000000000..378d3ff3fc6
--- /dev/null
+++ b/lib/nproc.c
@@ -0,0 +1,404 @@
+/* Detect the number of processors.
+
+ Copyright (C) 2009-2022 Free Software Foundation, Inc.
+
+ This file is free software: you can redistribute it and/or modify
+ it under the terms of the GNU Lesser General Public License as
+ published by the Free Software Foundation; either version 2.1 of the
+ License, or (at your option) any later version.
+
+ This file 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 Lesser General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public License
+ along with this program. If not, see <https://www.gnu.org/licenses/>. */
+
+/* Written by Glen Lenker and Bruno Haible. */
+
+#include <config.h>
+#include "nproc.h"
+
+#include <limits.h>
+#include <stdlib.h>
+#include <unistd.h>
+
+#if HAVE_PTHREAD_GETAFFINITY_NP && 0
+# include <pthread.h>
+# include <sched.h>
+#endif
+#if HAVE_SCHED_GETAFFINITY_LIKE_GLIBC || HAVE_SCHED_GETAFFINITY_NP
+# include <sched.h>
+#endif
+
+#include <sys/types.h>
+
+#if HAVE_SYS_PSTAT_H
+# include <sys/pstat.h>
+#endif
+
+#if HAVE_SYS_SYSMP_H
+# include <sys/sysmp.h>
+#endif
+
+#if HAVE_SYS_PARAM_H
+# include <sys/param.h>
+#endif
+
+#if HAVE_SYS_SYSCTL_H && ! defined __GLIBC__
+# include <sys/sysctl.h>
+#endif
+
+#if defined _WIN32 && ! defined __CYGWIN__
+# define WIN32_LEAN_AND_MEAN
+# include <windows.h>
+#endif
+
+#include "c-ctype.h"
+
+#include "minmax.h"
+
+#define ARRAY_SIZE(a) (sizeof (a) / sizeof ((a)[0]))
+
+/* Return the number of processors available to the current process, based
+ on a modern system call that returns the "affinity" between the current
+ process and each CPU. Return 0 if unknown or if such a system call does
+ not exist. */
+static unsigned long
+num_processors_via_affinity_mask (void)
+{
+ /* glibc >= 2.3.3 with NPTL and NetBSD 5 have pthread_getaffinity_np,
+ but with different APIs. Also it requires linking with -lpthread.
+ Therefore this code is not enabled.
+ glibc >= 2.3.4 has sched_getaffinity whereas NetBSD 5 has
+ sched_getaffinity_np. */
+#if HAVE_PTHREAD_GETAFFINITY_NP && defined __GLIBC__ && 0
+ {
+ cpu_set_t set;
+
+ if (pthread_getaffinity_np (pthread_self (), sizeof (set), &set) == 0)
+ {
+ unsigned long count;
+
+# ifdef CPU_COUNT
+ /* glibc >= 2.6 has the CPU_COUNT macro. */
+ count = CPU_COUNT (&set);
+# else
+ size_t i;
+
+ count = 0;
+ for (i = 0; i < CPU_SETSIZE; i++)
+ if (CPU_ISSET (i, &set))
+ count++;
+# endif
+ if (count > 0)
+ return count;
+ }
+ }
+#elif HAVE_PTHREAD_GETAFFINITY_NP && defined __NetBSD__ && 0
+ {
+ cpuset_t *set;
+
+ set = cpuset_create ();
+ if (set != NULL)
+ {
+ unsigned long count = 0;
+
+ if (pthread_getaffinity_np (pthread_self (), cpuset_size (set), set)
+ == 0)
+ {
+ cpuid_t i;
+
+ for (i = 0;; i++)
+ {
+ int ret = cpuset_isset (i, set);
+ if (ret < 0)
+ break;
+ if (ret > 0)
+ count++;
+ }
+ }
+ cpuset_destroy (set);
+ if (count > 0)
+ return count;
+ }
+ }
+#elif HAVE_SCHED_GETAFFINITY_LIKE_GLIBC /* glibc >= 2.3.4 */
+ {
+ cpu_set_t set;
+
+ if (sched_getaffinity (0, sizeof (set), &set) == 0)
+ {
+ unsigned long count;
+
+# ifdef CPU_COUNT
+ /* glibc >= 2.6 has the CPU_COUNT macro. */
+ count = CPU_COUNT (&set);
+# else
+ size_t i;
+
+ count = 0;
+ for (i = 0; i < CPU_SETSIZE; i++)
+ if (CPU_ISSET (i, &set))
+ count++;
+# endif
+ if (count > 0)
+ return count;
+ }
+ }
+#elif HAVE_SCHED_GETAFFINITY_NP /* NetBSD >= 5 */
+ {
+ cpuset_t *set;
+
+ set = cpuset_create ();
+ if (set != NULL)
+ {
+ unsigned long count = 0;
+
+ if (sched_getaffinity_np (getpid (), cpuset_size (set), set) == 0)
+ {
+ cpuid_t i;
+
+ for (i = 0;; i++)
+ {
+ int ret = cpuset_isset (i, set);
+ if (ret < 0)
+ break;
+ if (ret > 0)
+ count++;
+ }
+ }
+ cpuset_destroy (set);
+ if (count > 0)
+ return count;
+ }
+ }
+#endif
+
+#if defined _WIN32 && ! defined __CYGWIN__
+ { /* This works on native Windows platforms. */
+ DWORD_PTR process_mask;
+ DWORD_PTR system_mask;
+
+ if (GetProcessAffinityMask (GetCurrentProcess (),
+ &process_mask, &system_mask))
+ {
+ DWORD_PTR mask = process_mask;
+ unsigned long count = 0;
+
+ for (; mask != 0; mask = mask >> 1)
+ if (mask & 1)
+ count++;
+ if (count > 0)
+ return count;
+ }
+ }
+#endif
+
+ return 0;
+}
+
+
+/* Return the total number of processors. Here QUERY must be one of
+ NPROC_ALL, NPROC_CURRENT. The result is guaranteed to be at least 1. */
+static unsigned long int
+num_processors_ignoring_omp (enum nproc_query query)
+{
+ /* On systems with a modern affinity mask system call, we have
+ sysconf (_SC_NPROCESSORS_CONF)
+ >= sysconf (_SC_NPROCESSORS_ONLN)
+ >= num_processors_via_affinity_mask ()
+ The first number is the number of CPUs configured in the system.
+ The second number is the number of CPUs available to the scheduler.
+ The third number is the number of CPUs available to the current process.
+
+ Note! On Linux systems with glibc, the first and second number come from
+ the /sys and /proc file systems (see
+ glibc/sysdeps/unix/sysv/linux/getsysstats.c).
+ In some situations these file systems are not mounted, and the sysconf call
+ returns 1 or 2 (<https://sourceware.org/bugzilla/show_bug.cgi?id=21542>),
+ which does not reflect the reality. */
+
+ if (query == NPROC_CURRENT)
+ {
+ /* Try the modern affinity mask system call. */
+ {
+ unsigned long nprocs = num_processors_via_affinity_mask ();
+
+ if (nprocs > 0)
+ return nprocs;
+ }
+
+#if defined _SC_NPROCESSORS_ONLN
+ { /* This works on glibc, Mac OS X 10.5, FreeBSD, AIX, OSF/1, Solaris,
+ Cygwin, Haiku. */
+ long int nprocs = sysconf (_SC_NPROCESSORS_ONLN);
+ if (nprocs > 0)
+ return nprocs;
+ }
+#endif
+ }
+ else /* query == NPROC_ALL */
+ {
+#if defined _SC_NPROCESSORS_CONF
+ { /* This works on glibc, Mac OS X 10.5, FreeBSD, AIX, OSF/1, Solaris,
+ Cygwin, Haiku. */
+ long int nprocs = sysconf (_SC_NPROCESSORS_CONF);
+
+# if __GLIBC__ >= 2 && defined __linux__
+ /* On Linux systems with glibc, this information comes from the /sys and
+ /proc file systems (see glibc/sysdeps/unix/sysv/linux/getsysstats.c).
+ In some situations these file systems are not mounted, and the
+ sysconf call returns 1 or 2. But we wish to guarantee that
+ num_processors (NPROC_ALL) >= num_processors (NPROC_CURRENT). */
+ if (nprocs == 1 || nprocs == 2)
+ {
+ unsigned long nprocs_current = num_processors_via_affinity_mask ();
+
+ if (/* nprocs_current > 0 && */ nprocs_current > nprocs)
+ nprocs = nprocs_current;
+ }
+# endif
+
+ if (nprocs > 0)
+ return nprocs;
+ }
+#endif
+ }
+
+#if HAVE_PSTAT_GETDYNAMIC
+ { /* This works on HP-UX. */
+ struct pst_dynamic psd;
+ if (pstat_getdynamic (&psd, sizeof psd, 1, 0) >= 0)
+ {
+ /* The field psd_proc_cnt contains the number of active processors.
+ In newer releases of HP-UX 11, the field psd_max_proc_cnt includes
+ deactivated processors. */
+ if (query == NPROC_CURRENT)
+ {
+ if (psd.psd_proc_cnt > 0)
+ return psd.psd_proc_cnt;
+ }
+ else
+ {
+ if (psd.psd_max_proc_cnt > 0)
+ return psd.psd_max_proc_cnt;
+ }
+ }
+ }
+#endif
+
+#if HAVE_SYSMP && defined MP_NAPROCS && defined MP_NPROCS
+ { /* This works on IRIX. */
+ /* MP_NPROCS yields the number of installed processors.
+ MP_NAPROCS yields the number of processors available to unprivileged
+ processes. */
+ int nprocs =
+ sysmp (query == NPROC_CURRENT && getuid () != 0
+ ? MP_NAPROCS
+ : MP_NPROCS);
+ if (nprocs > 0)
+ return nprocs;
+ }
+#endif
+
+ /* Finally, as fallback, use the APIs that don't distinguish between
+ NPROC_CURRENT and NPROC_ALL. */
+
+#if HAVE_SYSCTL && ! defined __GLIBC__ && defined HW_NCPU
+ { /* This works on macOS, FreeBSD, NetBSD, OpenBSD.
+ macOS 10.14 does not allow mib to be const. */
+ int nprocs;
+ size_t len = sizeof (nprocs);
+ static int mib[][2] = {
+# ifdef HW_NCPUONLINE
+ { CTL_HW, HW_NCPUONLINE },
+# endif
+ { CTL_HW, HW_NCPU }
+ };
+ for (int i = 0; i < ARRAY_SIZE (mib); i++)
+ {
+ if (sysctl (mib[i], ARRAY_SIZE (mib[i]), &nprocs, &len, NULL, 0) == 0
+ && len == sizeof (nprocs)
+ && 0 < nprocs)
+ return nprocs;
+ }
+ }
+#endif
+
+#if defined _WIN32 && ! defined __CYGWIN__
+ { /* This works on native Windows platforms. */
+ SYSTEM_INFO system_info;
+ GetSystemInfo (&system_info);
+ if (0 < system_info.dwNumberOfProcessors)
+ return system_info.dwNumberOfProcessors;
+ }
+#endif
+
+ return 1;
+}
+
+/* Parse OMP environment variables without dependence on OMP.
+ Return 0 for invalid values. */
+static unsigned long int
+parse_omp_threads (char const* threads)
+{
+ unsigned long int ret = 0;
+
+ if (threads == NULL)
+ return ret;
+
+ /* The OpenMP spec says that the value assigned to the environment variables
+ "may have leading and trailing white space". */
+ while (*threads != '\0' && c_isspace (*threads))
+ threads++;
+
+ /* Convert it from positive decimal to 'unsigned long'. */
+ if (c_isdigit (*threads))
+ {
+ char *endptr = NULL;
+ unsigned long int value = strtoul (threads, &endptr, 10);
+
+ if (endptr != NULL)
+ {
+ while (*endptr != '\0' && c_isspace (*endptr))
+ endptr++;
+ if (*endptr == '\0')
+ return value;
+ /* Also accept the first value in a nesting level,
+ since we can't determine the nesting level from env vars. */
+ else if (*endptr == ',')
+ return value;
+ }
+ }
+
+ return ret;
+}
+
+unsigned long int
+num_processors (enum nproc_query query)
+{
+ unsigned long int omp_env_limit = ULONG_MAX;
+
+ if (query == NPROC_CURRENT_OVERRIDABLE)
+ {
+ unsigned long int omp_env_threads;
+ /* Honor the OpenMP environment variables, recognized also by all
+ programs that are based on OpenMP. */
+ omp_env_threads = parse_omp_threads (getenv ("OMP_NUM_THREADS"));
+ omp_env_limit = parse_omp_threads (getenv ("OMP_THREAD_LIMIT"));
+ if (! omp_env_limit)
+ omp_env_limit = ULONG_MAX;
+
+ if (omp_env_threads)
+ return MIN (omp_env_threads, omp_env_limit);
+
+ query = NPROC_CURRENT;
+ }
+ /* Here query is one of NPROC_ALL, NPROC_CURRENT. */
+ {
+ unsigned long nprocs = num_processors_ignoring_omp (query);
+ return MIN (nprocs, omp_env_limit);
+ }
+}
diff --git a/lib/nproc.h b/lib/nproc.h
new file mode 100644
index 00000000000..505351d95f4
--- /dev/null
+++ b/lib/nproc.h
@@ -0,0 +1,46 @@
+/* Detect the number of processors.
+
+ Copyright (C) 2009-2022 Free Software Foundation, Inc.
+
+ This file is free software: you can redistribute it and/or modify
+ it under the terms of the GNU Lesser General Public License as
+ published by the Free Software Foundation; either version 2.1 of the
+ License, or (at your option) any later version.
+
+ This file 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 Lesser General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public License
+ along with this program. If not, see <https://www.gnu.org/licenses/>. */
+
+/* Written by Glen Lenker and Bruno Haible. */
+
+/* Allow the use in C++ code. */
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/* A "processor" in this context means a thread execution unit, that is either
+ - an execution core in a (possibly multi-core) chip, in a (possibly multi-
+ chip) module, in a single computer, or
+ - a thread execution unit inside a core
+ (hyper-threading, see <https://en.wikipedia.org/wiki/Hyper-threading>).
+ Which of the two definitions is used, is unspecified. */
+
+enum nproc_query
+{
+ NPROC_ALL, /* total number of processors */
+ NPROC_CURRENT, /* processors available to the current process */
+ NPROC_CURRENT_OVERRIDABLE /* likewise, but overridable through the
+ OMP_NUM_THREADS environment variable */
+};
+
+/* Return the total number of processors. The result is guaranteed to
+ be at least 1. */
+extern unsigned long int num_processors (enum nproc_query query);
+
+#ifdef __cplusplus
+}
+#endif /* C++ */
diff --git a/lib/nstrftime.c b/lib/nstrftime.c
index 8795cd729d7..c1dd5542478 100644
--- a/lib/nstrftime.c
+++ b/lib/nstrftime.c
@@ -1,30 +1,28 @@
-/* Copyright (C) 1991-2017 Free Software Foundation, Inc.
+/* Copyright (C) 1991-2022 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.
+ This file is free software: you can redistribute it and/or modify
+ it under the terms of the GNU Lesser 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,
+ This file is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- General Public License for more details.
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU Lesser 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/>. */
+ You should have received a copy of the GNU Lesser General Public License
+ along with this program. If not, see <https://www.gnu.org/licenses/>. */
#ifdef _LIBC
# define USE_IN_EXTENDED_LOCALE_MODEL 1
# define HAVE_STRUCT_ERA_ENTRY 1
# define HAVE_TM_GMTOFF 1
-# define HAVE_TM_ZONE 1
+# define HAVE_STRUCT_TM_TM_ZONE 1
# define HAVE_TZNAME 1
-# define HAVE_TZSET 1
# include "../locale/localeinfo.h"
#else
-# include <config.h>
+# include <libc-config.h>
# if FPRINTFTIME
# include "fprintftime.h"
# else
@@ -34,6 +32,7 @@
#endif
#include <ctype.h>
+#include <errno.h>
#include <time.h>
#if HAVE_TZNAME && !HAVE_DECL_TZNAME
@@ -68,13 +67,8 @@ extern char *tzname[];
#include <string.h>
#include <stdbool.h>
-#ifndef FALLTHROUGH
-# if __GNUC__ < 7
-# define FALLTHROUGH ((void) 0)
-# else
-# define FALLTHROUGH __attribute__ ((__fallthrough__))
-# endif
-#endif
+#include "attribute.h"
+#include <intprops.h>
#ifdef COMPILE_WIDE
# include <endian.h>
@@ -91,6 +85,7 @@ extern char *tzname[];
# define UCHAR_T unsigned char
# define L_(Str) Str
# define NLW(Sym) Sym
+# define ABALTMON_1 _NL_ABALTMON_1
# define MEMCPY(d, s, n) memcpy (d, s, n)
# define STRLEN(s) strlen (s)
@@ -110,14 +105,7 @@ extern char *tzname[];
#define SHR(a, b) \
(-1 >> 1 == -1 \
? (a) >> (b) \
- : (a) / (1 << (b)) - ((a) % (1 << (b)) < 0))
-
-/* Bound on length of the string representing an integer type or expression T.
- Subtract 1 for the sign bit if t is signed; log10 (2.0) < 146/485;
- add 1 for integer division truncation; add 1 more for a minus sign
- if needed. */
-#define INT_STRLEN_BOUND(t) \
- ((sizeof (t) * CHAR_BIT - 1) * 146 / 485 + 2)
+ : ((a) + ((a) < 0)) / (1 << (b)) - ((a) < 0))
#define TM_YEAR_BASE 1900
@@ -166,20 +154,24 @@ extern char *tzname[];
# define advance(P, N) ((P) += (N))
#endif
-#define add(n, f) \
+#define add(n, f) width_add (width, n, f)
+#define width_add(width, n, f) \
do \
{ \
size_t _n = (n); \
- size_t _w = (width < 0 ? 0 : width); \
+ size_t _w = pad == L_('-') || width < 0 ? 0 : width; \
size_t _incr = _n < _w ? _w : _n; \
if (_incr >= maxsize - i) \
- return 0; \
+ { \
+ errno = ERANGE; \
+ return 0; \
+ } \
if (p) \
{ \
- if (digits == 0 && _n < _w) \
+ if (_n < _w) \
{ \
- size_t _delta = width - _n; \
- if (pad == L_('0')) \
+ size_t _delta = _w - _n; \
+ if (pad == L_('0') || pad == L_('+')) \
memset_zero (p, _delta); \
else \
memset_space (p, _delta); \
@@ -190,15 +182,17 @@ extern char *tzname[];
i += _incr; \
} while (0)
+#define add1(c) width_add1 (width, c)
#if FPRINTFTIME
-# define add1(C) add (1, fputc (C, p))
+# define width_add1(width, c) width_add (width, 1, fputc (c, p))
#else
-# define add1(C) add (1, *p = C)
+# define width_add1(width, c) width_add (width, 1, *p = c)
#endif
+#define cpy(n, s) width_cpy (width, n, s)
#if FPRINTFTIME
-# define cpy(n, s) \
- add ((n), \
+# define width_cpy(width, n, s) \
+ width_add (width, n, \
do \
{ \
if (to_lowcase) \
@@ -218,8 +212,8 @@ extern char *tzname[];
while (0) \
)
#else
-# define cpy(n, s) \
- add ((n), \
+# define width_cpy(width, n, s) \
+ width_add (width, n, \
if (to_lowcase) \
memcpy_lowcase (p, (s), _n LOCALE_ARG); \
else if (to_uppcase) \
@@ -255,7 +249,7 @@ extern char *tzname[];
# undef _NL_CURRENT
# define _NL_CURRENT(category, item) \
(current->values[_NL_ITEM_INDEX (item)].string)
-# define LOCALE_PARAM , __locale_t loc
+# define LOCALE_PARAM , locale_t loc
# define LOCALE_ARG , loc
# define HELPER_LOCALE_ARG , current
#else
@@ -349,8 +343,8 @@ tm_diff (const struct tm *a, const struct tm *b)
but it's OK to assume that A and B are close to each other. */
int a4 = SHR (a->tm_year, 2) + SHR (TM_YEAR_BASE, 2) - ! (a->tm_year & 3);
int b4 = SHR (b->tm_year, 2) + SHR (TM_YEAR_BASE, 2) - ! (b->tm_year & 3);
- int a100 = a4 / 25 - (a4 % 25 < 0);
- int b100 = b4 / 25 - (b4 % 25 < 0);
+ int a100 = (a4 + (a4 < 0)) / 25 - (a4 < 0);
+ int b100 = (b4 + (b4 < 0)) / 25 - (b4 < 0);
int a400 = SHR (a100, 2);
int b400 = SHR (b100, 2);
int intervening_leap_days = (a4 - b4) - (a100 - b100) + (a400 - b400);
@@ -373,10 +367,7 @@ tm_diff (const struct tm *a, const struct tm *b)
#define ISO_WEEK1_WDAY 4 /* Thursday */
#define YDAY_MINIMUM (-366)
static int iso_week_days (int, int);
-#ifdef __GNUC__
-__inline__
-#endif
-static int
+static __inline int
iso_week_days (int yday, int wday)
{
/* Add enough to the first operand of % to make it nonnegative. */
@@ -397,7 +388,6 @@ iso_week_days (int yday, int wday)
#endif
#ifdef my_strftime
-# undef HAVE_TZSET
# define extra_args , tz, ns
# define extra_args_spec , timezone_t tz, int ns
#else
@@ -417,7 +407,7 @@ iso_week_days (int yday, int wday)
static size_t __strftime_internal (STREAM_OR_CHAR_T *, STRFTIME_ARG (size_t)
const CHAR_T *, const struct tm *,
- bool, bool *
+ bool, int, int, bool *
extra_args_spec LOCALE_PARAM);
/* Write information from TP into S according to the format
@@ -432,20 +422,20 @@ my_strftime (STREAM_OR_CHAR_T *s, STRFTIME_ARG (size_t maxsize)
const struct tm *tp extra_args_spec LOCALE_PARAM)
{
bool tzset_called = false;
- return __strftime_internal (s, STRFTIME_ARG (maxsize) format, tp,
- false, &tzset_called extra_args LOCALE_ARG);
+ return __strftime_internal (s, STRFTIME_ARG (maxsize) format, tp, false,
+ 0, -1, &tzset_called extra_args LOCALE_ARG);
}
-#if defined _LIBC && ! FPRINTFTIME
libc_hidden_def (my_strftime)
-#endif
-/* Just like my_strftime, above, but with two more parameters.
- UPCASE indicate that the result should be converted to upper case,
- and *TZSET_CALLED indicates whether tzset has been called here. */
+/* Just like my_strftime, above, but with more parameters.
+ UPCASE indicates that the result should be converted to upper case.
+ YR_SPEC and WIDTH specify the padding and width for the year.
+ *TZSET_CALLED indicates whether tzset has been called here. */
static size_t
__strftime_internal (STREAM_OR_CHAR_T *s, STRFTIME_ARG (size_t maxsize)
const CHAR_T *format,
- const struct tm *tp, bool upcase, bool *tzset_called
+ const struct tm *tp, bool upcase,
+ int yr_spec, int width, bool *tzset_called
extra_args_spec LOCALE_PARAM)
{
#if defined _LIBC && defined USE_IN_EXTENDED_LOCALE_MODEL
@@ -455,6 +445,7 @@ __strftime_internal (STREAM_OR_CHAR_T *s, STRFTIME_ARG (size_t maxsize)
size_t maxsize = (size_t) -1;
#endif
+ int saved_errno = errno;
int hour12 = tp->tm_hour;
#ifdef _NL_CURRENT
/* We cannot make the following values variables since we must delay
@@ -475,12 +466,19 @@ __strftime_internal (STREAM_OR_CHAR_T *s, STRFTIME_ARG (size_t maxsize)
# define f_month \
((const CHAR_T *) (tp->tm_mon < 0 || tp->tm_mon > 11 \
? "?" : _NL_CURRENT (LC_TIME, NLW(MON_1) + tp->tm_mon)))
+# define a_altmonth \
+ ((const CHAR_T *) (tp->tm_mon < 0 || tp->tm_mon > 11 \
+ ? "?" : _NL_CURRENT (LC_TIME, NLW(ABALTMON_1) + tp->tm_mon)))
+# define f_altmonth \
+ ((const CHAR_T *) (tp->tm_mon < 0 || tp->tm_mon > 11 \
+ ? "?" : _NL_CURRENT (LC_TIME, NLW(ALTMON_1) + tp->tm_mon)))
# define ampm \
((const CHAR_T *) _NL_CURRENT (LC_TIME, tp->tm_hour > 11 \
? NLW(PM_STR) : NLW(AM_STR)))
# define aw_len STRLEN (a_wkday)
# define am_len STRLEN (a_month)
+# define aam_len STRLEN (a_altmonth)
# define ap_len STRLEN (ampm)
#endif
#if HAVE_TZNAME
@@ -494,17 +492,8 @@ __strftime_internal (STREAM_OR_CHAR_T *s, STRFTIME_ARG (size_t maxsize)
const char *format_end = NULL;
#endif
-#if ! defined _LIBC && ! HAVE_RUN_TZSET_TEST
- /* Solaris 2.5.x and 2.6 tzset sometimes modify the storage returned
- by localtime. On such systems, we must either use the tzset and
- localtime wrappers to work around the bug (which sets
- HAVE_RUN_TZSET_TEST) or make a copy of the structure. */
- struct tm copy = *tp;
- tp = &copy;
-#endif
-
zone = NULL;
-#if HAVE_TM_ZONE
+#if HAVE_STRUCT_TM_TM_ZONE
/* The POSIX test suite assumes that setting
the environment variable TZ to a new value before calling strftime()
will influence the result (the %Z format) even if the information in
@@ -521,7 +510,7 @@ __strftime_internal (STREAM_OR_CHAR_T *s, STRFTIME_ARG (size_t maxsize)
}
else
{
-# if !HAVE_TM_ZONE
+# if !HAVE_STRUCT_TM_TM_ZONE
/* Infer the zone name from *TZ instead of from TZNAME. */
tzname_vec = tz->tzname_copy;
# endif
@@ -531,7 +520,7 @@ __strftime_internal (STREAM_OR_CHAR_T *s, STRFTIME_ARG (size_t maxsize)
{
/* POSIX.1 requires that local time zone information be used as
though strftime called tzset. */
-# if HAVE_TZSET
+# ifndef my_strftime
if (!*tzset_called)
{
tzset ();
@@ -550,9 +539,9 @@ __strftime_internal (STREAM_OR_CHAR_T *s, STRFTIME_ARG (size_t maxsize)
if (hour12 == 0)
hour12 = 12;
- for (f = format; *f != '\0'; ++f)
+ for (f = format; *f != '\0'; width = -1, f++)
{
- int pad = 0; /* Padding for number ('-', '_', or 0). */
+ int pad = 0; /* Padding for number ('_', '-', '+', '0', or 0). */
int modifier; /* Field modifier ('E', 'O', or 0). */
int digits = 0; /* Max digits for numeric format. */
int number_value; /* Numeric value to be printed. */
@@ -561,19 +550,18 @@ __strftime_internal (STREAM_OR_CHAR_T *s, STRFTIME_ARG (size_t maxsize)
bool always_output_a_sign; /* +/- should always be output. */
int tz_colon_mask; /* Bitmask of where ':' should appear. */
const CHAR_T *subfmt;
- CHAR_T sign_char;
CHAR_T *bufp;
CHAR_T buf[1
+ 2 /* for the two colons in a %::z or %:::z time zone */
+ (sizeof (int) < sizeof (time_t)
? INT_STRLEN_BOUND (time_t)
: INT_STRLEN_BOUND (int))];
- int width = -1;
bool to_lowcase = false;
bool to_uppcase = upcase;
size_t colons;
bool change_case = false;
int format_char;
+ int subwidth;
#if DO_MULTIBYTE && !defined COMPILE_WIDE
switch (*f)
@@ -663,6 +651,8 @@ __strftime_internal (STREAM_OR_CHAR_T *s, STRFTIME_ARG (size_t maxsize)
#endif /* ! DO_MULTIBYTE */
+ char const *percent = f;
+
/* Check for flags that can modify a format. */
while (1)
{
@@ -671,6 +661,7 @@ __strftime_internal (STREAM_OR_CHAR_T *s, STRFTIME_ARG (size_t maxsize)
/* This influences the number formats. */
case L_('_'):
case L_('-'):
+ case L_('+'):
case L_('0'):
pad = *f;
continue;
@@ -689,21 +680,14 @@ __strftime_internal (STREAM_OR_CHAR_T *s, STRFTIME_ARG (size_t maxsize)
break;
}
- /* As a GNU extension we allow the field width to be specified. */
if (ISDIGIT (*f))
{
width = 0;
do
{
- if (width > INT_MAX / 10
- || (width == INT_MAX / 10 && *f - L_('0') > INT_MAX % 10))
- /* Avoid overflow. */
+ if (INT_MULTIPLY_WRAPV (width, 10, &width)
+ || INT_ADD_WRAPV (width, *f - L_('0'), &width))
width = INT_MAX;
- else
- {
- width *= 10;
- width += *f - L_('0');
- }
++f;
}
while (ISDIGIT (*f));
@@ -735,12 +719,16 @@ __strftime_internal (STREAM_OR_CHAR_T *s, STRFTIME_ARG (size_t maxsize)
} \
while (0)
#define DO_SIGNED_NUMBER(d, negative, v) \
+ DO_MAYBE_SIGNED_NUMBER (d, negative, v, do_signed_number)
+#define DO_YEARISH(d, negative, v) \
+ DO_MAYBE_SIGNED_NUMBER (d, negative, v, do_yearish)
+#define DO_MAYBE_SIGNED_NUMBER(d, negative, v, label) \
do \
{ \
digits = d; \
negative_number = negative; \
u_number_value = v; \
- goto do_signed_number; \
+ goto label; \
} \
while (0)
@@ -766,8 +754,8 @@ __strftime_internal (STREAM_OR_CHAR_T *s, STRFTIME_ARG (size_t maxsize)
while (0)
case L_('%'):
- if (modifier != 0)
- goto bad_format;
+ if (f - 1 != percent)
+ goto bad_percent;
add1 (*f);
break;
@@ -808,17 +796,20 @@ __strftime_internal (STREAM_OR_CHAR_T *s, STRFTIME_ARG (size_t maxsize)
to_uppcase = true;
to_lowcase = false;
}
- if (modifier != 0)
+ if (modifier == L_('E'))
goto bad_format;
#ifdef _NL_CURRENT
- cpy (am_len, a_month);
+ if (modifier == L_('O'))
+ cpy (aam_len, a_altmonth);
+ else
+ cpy (am_len, a_month);
break;
#else
goto underlying_strftime;
#endif
case L_('B'):
- if (modifier != 0)
+ if (modifier == L_('E'))
goto bad_format;
if (change_case)
{
@@ -826,7 +817,10 @@ __strftime_internal (STREAM_OR_CHAR_T *s, STRFTIME_ARG (size_t maxsize)
to_lowcase = false;
}
#ifdef _NL_CURRENT
- cpy (STRLEN (f_month), f_month);
+ if (modifier == L_('O'))
+ cpy (STRLEN (f_altmonth), f_altmonth);
+ else
+ cpy (STRLEN (f_month), f_month);
break;
#else
goto underlying_strftime;
@@ -836,7 +830,7 @@ __strftime_internal (STREAM_OR_CHAR_T *s, STRFTIME_ARG (size_t maxsize)
if (modifier == L_('O'))
goto bad_format;
#ifdef _NL_CURRENT
- if (! (modifier == 'E'
+ if (! (modifier == L_('E')
&& (*(subfmt =
(const CHAR_T *) _NL_CURRENT (LC_TIME,
NLW(ERA_D_T_FMT)))
@@ -847,15 +841,17 @@ __strftime_internal (STREAM_OR_CHAR_T *s, STRFTIME_ARG (size_t maxsize)
#endif
subformat:
+ subwidth = -1;
+ subformat_width:
{
size_t len = __strftime_internal (NULL, STRFTIME_ARG ((size_t) -1)
- subfmt,
- tp, to_uppcase, tzset_called
+ subfmt, tp, to_uppcase,
+ pad, subwidth, tzset_called
extra_args LOCALE_ARG);
add (len, __strftime_internal (p,
STRFTIME_ARG (maxsize - i)
- subfmt,
- tp, to_uppcase, tzset_called
+ subfmt, tp, to_uppcase,
+ pad, subwidth, tzset_called
extra_args LOCALE_ARG));
}
break;
@@ -914,9 +910,11 @@ __strftime_internal (STREAM_OR_CHAR_T *s, STRFTIME_ARG (size_t maxsize)
}
{
- int century = tp->tm_year / 100 + TM_YEAR_BASE / 100;
- century -= tp->tm_year % 100 < 0 && 0 < century;
- DO_SIGNED_NUMBER (2, tp->tm_year < - TM_YEAR_BASE, century);
+ bool negative_year = tp->tm_year < - TM_YEAR_BASE;
+ bool zero_thru_1899 = !negative_year & (tp->tm_year < 0);
+ int century = ((tp->tm_year - 99 * zero_thru_1899) / 100
+ + TM_YEAR_BASE / 100);
+ DO_YEARISH (2, negative_year, century);
}
case L_('x'):
@@ -925,7 +923,7 @@ __strftime_internal (STREAM_OR_CHAR_T *s, STRFTIME_ARG (size_t maxsize)
#ifdef _NL_CURRENT
if (! (modifier == L_('E')
&& (*(subfmt =
- (const CHAR_T *)_NL_CURRENT (LC_TIME, NLW(ERA_D_FMT)))
+ (const CHAR_T *) _NL_CURRENT (LC_TIME, NLW(ERA_D_FMT)))
!= L_('\0'))))
subfmt = (const CHAR_T *) _NL_CURRENT (LC_TIME, NLW(D_FMT));
goto subformat;
@@ -957,9 +955,17 @@ __strftime_internal (STREAM_OR_CHAR_T *s, STRFTIME_ARG (size_t maxsize)
always_output_a_sign = true;
goto do_number_body;
+ do_yearish:
+ if (pad == 0)
+ pad = yr_spec;
+ always_output_a_sign
+ = (pad == L_('+')
+ && ((digits == 2 ? 99 : 9999) < u_number_value
+ || digits < width));
+ goto do_maybe_signed_number;
+
do_number_spacepad:
- /* Force '_' flag unless overridden by '0' or '-' flag. */
- if (pad != L_('0') && pad != L_('-'))
+ if (pad == 0)
pad = L_('_');
do_number:
@@ -969,6 +975,8 @@ __strftime_internal (STREAM_OR_CHAR_T *s, STRFTIME_ARG (size_t maxsize)
do_signed_number:
always_output_a_sign = false;
+
+ do_maybe_signed_number:
tz_colon_mask = 0;
do_number_body:
@@ -1015,66 +1023,52 @@ __strftime_internal (STREAM_OR_CHAR_T *s, STRFTIME_ARG (size_t maxsize)
while (u_number_value != 0 || tz_colon_mask != 0);
do_number_sign_and_padding:
- if (digits < width)
- digits = width;
-
- sign_char = (negative_number ? L_('-')
- : always_output_a_sign ? L_('+')
- : 0);
-
- if (pad == L_('-'))
- {
- if (sign_char)
- add1 (sign_char);
- }
- else
- {
- int padding = digits - (buf + (sizeof (buf) / sizeof (buf[0]))
- - bufp) - !!sign_char;
-
- if (padding > 0)
- {
- if (pad == L_('_'))
- {
- if ((size_t) padding >= maxsize - i)
- return 0;
-
- if (p)
- memset_space (p, padding);
- i += padding;
- width = width > padding ? width - padding : 0;
- if (sign_char)
- add1 (sign_char);
- }
- else
- {
- if ((size_t) digits >= maxsize - i)
- return 0;
+ if (pad == 0)
+ pad = L_('0');
+ if (width < 0)
+ width = digits;
- if (sign_char)
- add1 (sign_char);
-
- if (p)
- memset_zero (p, padding);
- i += padding;
- width = 0;
- }
- }
- else
- {
- if (sign_char)
- add1 (sign_char);
- }
- }
+ {
+ CHAR_T sign_char = (negative_number ? L_('-')
+ : always_output_a_sign ? L_('+')
+ : 0);
+ int numlen = buf + sizeof buf / sizeof buf[0] - bufp;
+ int shortage = width - !!sign_char - numlen;
+ int padding = pad == L_('-') || shortage <= 0 ? 0 : shortage;
+
+ if (sign_char)
+ {
+ if (pad == L_('_'))
+ {
+ if (p)
+ memset_space (p, padding);
+ i += padding;
+ width -= padding;
+ }
+ width_add1 (0, sign_char);
+ width--;
+ }
- cpy (buf + sizeof (buf) / sizeof (buf[0]) - bufp, bufp);
+ cpy (numlen, bufp);
+ }
break;
case L_('F'):
if (modifier != 0)
goto bad_format;
+ if (pad == 0 && width < 0)
+ {
+ pad = L_('+');
+ subwidth = 4;
+ }
+ else
+ {
+ subwidth = width - 6;
+ if (subwidth < 0)
+ subwidth = 0;
+ }
subfmt = L_("%Y-%m-%d");
- goto subformat;
+ goto subformat_width;
case L_('H'):
if (modifier == L_('E'))
@@ -1122,19 +1116,21 @@ __strftime_internal (STREAM_OR_CHAR_T *s, STRFTIME_ARG (size_t maxsize)
case L_('N'): /* GNU extension. */
if (modifier == L_('E'))
goto bad_format;
-
- number_value = ns;
- if (width == -1)
- width = 9;
- else
- {
- /* Take an explicit width less than 9 as a precision. */
- int j;
- for (j = width; j < 9; j++)
- number_value /= 10;
- }
-
- DO_NUMBER (width, number_value);
+ {
+ int n = ns, ns_digits = 9;
+ if (width <= 0)
+ width = ns_digits;
+ int ndigs = ns_digits;
+ while (width < ndigs || (1 < ndigs && n % 10 == 0))
+ ndigs--, n /= 10;
+ for (int j = ndigs; 0 < j; j--)
+ buf[j - 1] = n % 10 + L_('0'), n /= 10;
+ if (!pad)
+ pad = L_('0');
+ width_cpy (0, ndigs, buf);
+ width_add (width - ndigs, 0, (void) 0);
+ }
+ break;
#endif
case L_('n'):
@@ -1162,7 +1158,6 @@ __strftime_internal (STREAM_OR_CHAR_T *s, STRFTIME_ARG (size_t maxsize)
case L_('q'): /* GNU extension. */
DO_SIGNED_NUMBER (1, false, ((tp->tm_mon * 11) >> 5) + 1);
- break;
case L_('R'):
subfmt = L_("%H:%M");
@@ -1191,7 +1186,13 @@ __strftime_internal (STREAM_OR_CHAR_T *s, STRFTIME_ARG (size_t maxsize)
time_t t;
ltm = *tp;
+ ltm.tm_yday = -1;
t = mktime_z (tz, &ltm);
+ if (ltm.tm_yday < 0)
+ {
+ errno = EOVERFLOW;
+ return 0;
+ }
/* Generate string value for T using time_t arithmetic;
this works even if sizeof (long) < sizeof (time_t). */
@@ -1283,17 +1284,18 @@ __strftime_internal (STREAM_OR_CHAR_T *s, STRFTIME_ARG (size_t maxsize)
case L_('g'):
{
int yy = (tp->tm_year % 100 + year_adjust) % 100;
- DO_NUMBER (2, (0 <= yy
- ? yy
- : tp->tm_year < -TM_YEAR_BASE - year_adjust
- ? -yy
- : yy + 100));
+ DO_YEARISH (2, false,
+ (0 <= yy
+ ? yy
+ : tp->tm_year < -TM_YEAR_BASE - year_adjust
+ ? -yy
+ : yy + 100));
}
case L_('G'):
- DO_SIGNED_NUMBER (4, tp->tm_year < -TM_YEAR_BASE - year_adjust,
- (tp->tm_year + (unsigned int) TM_YEAR_BASE
- + year_adjust));
+ DO_YEARISH (4, tp->tm_year < -TM_YEAR_BASE - year_adjust,
+ (tp->tm_year + (unsigned int) TM_YEAR_BASE
+ + year_adjust));
default:
DO_NUMBER (2, days / 7 + 1);
@@ -1313,7 +1315,7 @@ __strftime_internal (STREAM_OR_CHAR_T *s, STRFTIME_ARG (size_t maxsize)
DO_NUMBER (1, tp->tm_wday);
case L_('Y'):
- if (modifier == 'E')
+ if (modifier == L_('E'))
{
#if HAVE_STRUCT_ERA_ENTRY
struct era_entry *era = _nl_get_era_entry (tp HELPER_LOCALE_ARG);
@@ -1324,6 +1326,8 @@ __strftime_internal (STREAM_OR_CHAR_T *s, STRFTIME_ARG (size_t maxsize)
# else
subfmt = era->era_format;
# endif
+ if (pad == 0)
+ pad = yr_spec;
goto subformat;
}
#else
@@ -1333,8 +1337,8 @@ __strftime_internal (STREAM_OR_CHAR_T *s, STRFTIME_ARG (size_t maxsize)
if (modifier == L_('O'))
goto bad_format;
- DO_SIGNED_NUMBER (4, tp->tm_year < -TM_YEAR_BASE,
- tp->tm_year + (unsigned int) TM_YEAR_BASE);
+ DO_YEARISH (4, tp->tm_year < -TM_YEAR_BASE,
+ tp->tm_year + (unsigned int) TM_YEAR_BASE);
case L_('y'):
if (modifier == L_('E'))
@@ -1344,7 +1348,9 @@ __strftime_internal (STREAM_OR_CHAR_T *s, STRFTIME_ARG (size_t maxsize)
if (era)
{
int delta = tp->tm_year - era->start_date[0];
- DO_NUMBER (1, (era->offset
+ if (pad == 0)
+ pad = yr_spec;
+ DO_NUMBER (2, (era->offset
+ delta * era->absolute_direction));
}
#else
@@ -1356,7 +1362,7 @@ __strftime_internal (STREAM_OR_CHAR_T *s, STRFTIME_ARG (size_t maxsize)
int yy = tp->tm_year % 100;
if (yy < 0)
yy = tp->tm_year < - TM_YEAR_BASE ? -yy : yy + 100;
- DO_NUMBER (2, yy);
+ DO_YEARISH (2, false, yy);
}
case L_('Z'):
@@ -1415,7 +1421,7 @@ __strftime_internal (STREAM_OR_CHAR_T *s, STRFTIME_ARG (size_t maxsize)
/* POSIX.1 requires that local time zone information be used as
though strftime called tzset. */
-# if HAVE_TZSET
+# ifndef my_strftime
if (!*tzset_called)
{
tzset ();
@@ -1424,28 +1430,10 @@ __strftime_internal (STREAM_OR_CHAR_T *s, STRFTIME_ARG (size_t maxsize)
# endif
ltm = *tp;
+ ltm.tm_wday = -1;
lt = mktime_z (tz, &ltm);
-
- if (lt == (time_t) -1)
- {
- /* mktime returns -1 for errors, but -1 is also a
- valid time_t value. Check whether an error really
- occurred. */
- struct tm tm;
-
- if (! localtime_rz (tz, &lt, &tm)
- || ((ltm.tm_sec ^ tm.tm_sec)
- | (ltm.tm_min ^ tm.tm_min)
- | (ltm.tm_hour ^ tm.tm_hour)
- | (ltm.tm_mday ^ tm.tm_mday)
- | (ltm.tm_mon ^ tm.tm_mon)
- | (ltm.tm_year ^ tm.tm_year)))
- break;
- }
-
- if (! localtime_rz (0, &lt, &gtm))
+ if (ltm.tm_wday < 0 || ! localtime_rz (0, &lt, &gtm))
break;
-
diff = tm_diff (&ltm, &gtm);
}
#endif
@@ -1480,6 +1468,7 @@ __strftime_internal (STREAM_OR_CHAR_T *s, STRFTIME_ARG (size_t maxsize)
}
case L_('\0'): /* GNU extension: % at end of format. */
+ bad_percent:
--f;
FALLTHROUGH;
default:
@@ -1487,12 +1476,7 @@ __strftime_internal (STREAM_OR_CHAR_T *s, STRFTIME_ARG (size_t maxsize)
since this is most likely the right thing to do if a
multibyte string has been misparsed. */
bad_format:
- {
- int flen;
- for (flen = 1; f[1 - flen] != L_('%'); flen++)
- continue;
- cpy (flen, &f[1 - flen]);
- }
+ cpy (f - percent + 1, percent);
break;
}
}
@@ -1502,5 +1486,6 @@ __strftime_internal (STREAM_OR_CHAR_T *s, STRFTIME_ARG (size_t maxsize)
*p = L_('\0');
#endif
+ errno = saved_errno;
return i;
}
diff --git a/lib/open.c b/lib/open.c
index b5452b56afd..170bff108e3 100644
--- a/lib/open.c
+++ b/lib/open.c
@@ -1,17 +1,17 @@
/* Open a descriptor to a file.
- Copyright (C) 2007-2017 Free Software Foundation, Inc.
+ Copyright (C) 2007-2022 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 file is free software: you can redistribute it and/or modify
+ it under the terms of the GNU Lesser General Public License as
+ published by the Free Software Foundation; either version 2.1 of the
+ License, or (at your option) any later version.
- This program is distributed in the hope that it will be useful,
+ This file 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.
+ GNU Lesser General Public License for more details.
- You should have received a copy of the GNU General Public License
+ You should have received a copy of the GNU Lesser General Public License
along with this program. If not, see <https://www.gnu.org/licenses/>. */
/* Written by Bruno Haible <bruno@clisp.org>, 2007. */
@@ -30,7 +30,11 @@
static int
orig_open (const char *filename, int flags, mode_t mode)
{
+#if defined _WIN32 && !defined __CYGWIN__
+ return _open (filename, flags, mode);
+#else
return open (filename, flags, mode);
+#endif
}
/* Specification. */
@@ -86,34 +90,33 @@ open (const char *filename, int flags, ...)
flags &= ~O_NONBLOCK;
#endif
-#if (defined _WIN32 || defined __WIN32__) && ! defined __CYGWIN__
+#if defined _WIN32 && ! defined __CYGWIN__
if (strcmp (filename, "/dev/null") == 0)
filename = "NUL";
#endif
#if OPEN_TRAILING_SLASH_BUG
- /* If the filename ends in a slash and one of O_CREAT, O_WRONLY, O_RDWR
- is specified, then fail.
- Rationale: POSIX <http://www.opengroup.org/susv3/basedefs/xbd_chap04.html>
- says that
- "A pathname that contains at least one non-slash character and that
- ends with one or more trailing slashes shall be resolved as if a
- single dot character ( '.' ) were appended to the pathname."
- and
- "The special filename dot shall refer to the directory specified by
- its predecessor."
+ /* Fail if one of O_CREAT, O_WRONLY, O_RDWR is specified and the filename
+ ends in a slash, as POSIX says such a filename must name a directory
+ <https://pubs.opengroup.org/onlinepubs/9699919799/basedefs/V1_chap04.html#tag_04_13>:
+ "A pathname that contains at least one non-<slash> character and that
+ ends with one or more trailing <slash> characters shall not be resolved
+ successfully unless the last pathname component before the trailing
+ <slash> characters names an existing directory"
If the named file already exists as a directory, then
- if O_CREAT is specified, open() must fail because of the semantics
of O_CREAT,
- if O_WRONLY or O_RDWR is specified, open() must fail because POSIX
- <http://www.opengroup.org/susv3/functions/open.html> says that it
- fails with errno = EISDIR in this case.
+ <https://pubs.opengroup.org/onlinepubs/9699919799/functions/open.html>
+ says that it fails with errno = EISDIR in this case.
If the named file does not exist or does not name a directory, then
- if O_CREAT is specified, open() must fail since open() cannot create
directories,
- if O_WRONLY or O_RDWR is specified, open() must fail because the
file does not contain a '.' directory. */
- if (flags & (O_CREAT | O_WRONLY | O_RDWR))
+ if ((flags & O_CREAT)
+ || (flags & O_ACCMODE) == O_RDWR
+ || (flags & O_ACCMODE) == O_WRONLY)
{
size_t len = strlen (filename);
if (len > 0 && filename[len - 1] == '/')
@@ -125,7 +128,7 @@ open (const char *filename, int flags, ...)
#endif
fd = orig_open (filename,
- flags & ~(have_cloexec <= 0 ? O_CLOEXEC : 0), mode);
+ flags & ~(have_cloexec < 0 ? O_CLOEXEC : 0), mode);
if (flags & O_CLOEXEC)
{
@@ -171,14 +174,12 @@ open (const char *filename, int flags, ...)
#if OPEN_TRAILING_SLASH_BUG
/* If the filename ends in a slash and fd does not refer to a directory,
then fail.
- Rationale: POSIX <http://www.opengroup.org/susv3/basedefs/xbd_chap04.html>
- says that
- "A pathname that contains at least one non-slash character and that
- ends with one or more trailing slashes shall be resolved as if a
- single dot character ( '.' ) were appended to the pathname."
- and
- "The special filename dot shall refer to the directory specified by
- its predecessor."
+ Rationale: POSIX says such a filename must name a directory
+ <https://pubs.opengroup.org/onlinepubs/9699919799/basedefs/V1_chap04.html#tag_04_13>:
+ "A pathname that contains at least one non-<slash> character and that
+ ends with one or more trailing <slash> characters shall not be resolved
+ successfully unless the last pathname component before the trailing
+ <slash> characters names an existing directory"
If the named file without the slash is not a directory, open() must fail
with ENOTDIR. */
if (fd >= 0)
diff --git a/lib/openat-priv.h b/lib/openat-priv.h
index b5a411b944b..5d60810709d 100644
--- a/lib/openat-priv.h
+++ b/lib/openat-priv.h
@@ -1,10 +1,10 @@
/* Internals for openat-like functions.
- Copyright (C) 2005-2006, 2009-2017 Free Software Foundation, Inc.
+ Copyright (C) 2005-2006, 2009-2022 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
+ 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,
diff --git a/lib/openat-proc.c b/lib/openat-proc.c
index 6d2b598c8b2..3bacf7dbd13 100644
--- a/lib/openat-proc.c
+++ b/lib/openat-proc.c
@@ -1,10 +1,10 @@
/* Create /proc/self/fd-related names for subfiles of open directories.
- Copyright (C) 2006, 2009-2017 Free Software Foundation, Inc.
+ Copyright (C) 2006, 2009-2022 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
+ 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,
@@ -73,8 +73,9 @@ openat_proc_name (char buf[OPENAT_BUFFER_SIZE], int fd, char const *file)
problem is exhibited on code that built on Solaris 8 and
running on Solaris 10. */
- int proc_self_fd = open ("/proc/self/fd",
- O_SEARCH | O_DIRECTORY | O_NOCTTY | O_NONBLOCK);
+ int proc_self_fd =
+ open ("/proc/self/fd",
+ O_SEARCH | O_DIRECTORY | O_NOCTTY | O_NONBLOCK | O_CLOEXEC);
if (proc_self_fd < 0)
proc_status = -1;
else
diff --git a/lib/openat.h b/lib/openat.h
index 1c4f64a32ed..56919ef8dc4 100644
--- a/lib/openat.h
+++ b/lib/openat.h
@@ -1,9 +1,9 @@
/* provide a replacement openat function
- Copyright (C) 2004-2006, 2008-2017 Free Software Foundation, Inc.
+ Copyright (C) 2004-2006, 2008-2022 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
+ 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,
@@ -52,19 +52,19 @@ _Noreturn void openat_save_fail (int);
slightly more readable than it would be with
fchownat (..., 0) or fchownat (..., AT_SYMLINK_NOFOLLOW). */
-#if GNULIB_FCHOWNAT
+#if GNULIB_CHOWNAT
-# ifndef FCHOWNAT_INLINE
-# define FCHOWNAT_INLINE _GL_INLINE
+# ifndef CHOWNAT_INLINE
+# define CHOWNAT_INLINE _GL_INLINE
# endif
-FCHOWNAT_INLINE int
+CHOWNAT_INLINE int
chownat (int fd, char const *file, uid_t owner, gid_t group)
{
return fchownat (fd, file, owner, group, 0);
}
-FCHOWNAT_INLINE int
+CHOWNAT_INLINE int
lchownat (int fd, char const *file, uid_t owner, gid_t group)
{
return fchownat (fd, file, owner, group, AT_SYMLINK_NOFOLLOW);
@@ -72,19 +72,19 @@ lchownat (int fd, char const *file, uid_t owner, gid_t group)
#endif
-#if GNULIB_FCHMODAT
+#if GNULIB_CHMODAT
-# ifndef FCHMODAT_INLINE
-# define FCHMODAT_INLINE _GL_INLINE
+# ifndef CHMODAT_INLINE
+# define CHMODAT_INLINE _GL_INLINE
# endif
-FCHMODAT_INLINE int
+CHMODAT_INLINE int
chmodat (int fd, char const *file, mode_t mode)
{
return fchmodat (fd, file, mode, 0);
}
-FCHMODAT_INLINE int
+CHMODAT_INLINE int
lchmodat (int fd, char const *file, mode_t mode)
{
return fchmodat (fd, file, mode, AT_SYMLINK_NOFOLLOW);
@@ -98,12 +98,14 @@ lchmodat (int fd, char const *file, mode_t mode)
# define STATAT_INLINE _GL_INLINE
# endif
+_GL_ATTRIBUTE_DEPRECATED
STATAT_INLINE int
statat (int fd, char const *name, struct stat *st)
{
return fstatat (fd, name, st, 0);
}
+_GL_ATTRIBUTE_DEPRECATED
STATAT_INLINE int
lstatat (int fd, char const *name, struct stat *st)
{
diff --git a/lib/pathmax.h b/lib/pathmax.h
new file mode 100644
index 00000000000..19b93d7eab1
--- /dev/null
+++ b/lib/pathmax.h
@@ -0,0 +1,83 @@
+/* Define PATH_MAX somehow. Requires sys/types.h.
+ Copyright (C) 1992, 1999, 2001, 2003, 2005, 2009-2022 Free Software
+ Foundation, Inc.
+
+ This file is free software: you can redistribute it and/or modify
+ it under the terms of the GNU Lesser General Public License as
+ published by the Free Software Foundation; either version 2.1 of the
+ License, or (at your option) any later version.
+
+ This file 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 Lesser General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public License
+ along with this program. If not, see <https://www.gnu.org/licenses/>. */
+
+#ifndef _PATHMAX_H
+# define _PATHMAX_H
+
+/* POSIX:2008 defines PATH_MAX to be the maximum number of bytes in a filename,
+ including the terminating NUL byte.
+ <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.
+
+ This file does *not* define PATH_MAX always. Programs that use this file
+ can handle the GNU/Hurd case in several ways:
+ - Either with a package-wide handling, or with a per-file handling,
+ - Either through a
+ #ifdef PATH_MAX
+ or through a fallback like
+ #ifndef PATH_MAX
+ # define PATH_MAX 8192
+ #endif
+ or through a fallback like
+ #ifndef PATH_MAX
+ # define PATH_MAX pathconf ("/", _PC_PATH_MAX)
+ #endif
+ */
+
+# include <unistd.h>
+
+# include <limits.h>
+
+# ifndef _POSIX_PATH_MAX
+# define _POSIX_PATH_MAX 256
+# endif
+
+/* Don't include sys/param.h if it already has been. */
+# if defined HAVE_SYS_PARAM_H && !defined PATH_MAX && !defined MAXPATHLEN
+# include <sys/param.h>
+# endif
+
+# if !defined PATH_MAX && defined MAXPATHLEN
+# define PATH_MAX MAXPATHLEN
+# endif
+
+# ifdef __hpux
+/* On HP-UX, PATH_MAX designates the maximum number of bytes in a filename,
+ *not* including the terminating NUL byte, and is set to 1023.
+ Additionally, when _XOPEN_SOURCE is defined to 500 or more, PATH_MAX is
+ not defined at all any more. */
+# undef PATH_MAX
+# define PATH_MAX 1024
+# endif
+
+# if defined _WIN32 && ! defined __CYGWIN__
+/* The page "Naming Files, Paths, and Namespaces" on msdn.microsoft.com,
+ section "Maximum Path Length Limitation",
+ <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
+ - FILENAME_MAX in <stdio.h>,
+ - _MAX_PATH in <stdlib.h>,
+ - MAX_PATH in <windef.h>.
+ Undefine the original value, because mingw's <limits.h> gets it wrong. */
+# undef PATH_MAX
+# define PATH_MAX 260
+# endif
+
+#endif /* _PATHMAX_H */
diff --git a/lib/pipe2.c b/lib/pipe2.c
index 741cee99ff6..400aff001a2 100644
--- a/lib/pipe2.c
+++ b/lib/pipe2.c
@@ -1,18 +1,18 @@
/* Create a pipe, with specific opening flags.
- Copyright (C) 2009-2017 Free Software Foundation, Inc.
+ Copyright (C) 2009-2022 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 file is free software: you can redistribute it and/or modify
+ it under the terms of the GNU Lesser General Public License as
+ published by the Free Software Foundation; either version 2.1 of the
+ License, or (at your option) any later version.
- This program is distributed in the hope that it will be useful,
+ This file 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.
+ GNU Lesser General Public License for more details.
- You should have received a copy of the GNU General Public License along
- with this program; if not, see <https://www.gnu.org/licenses/>. */
+ You should have received a copy of the GNU Lesser General Public License
+ along with this program. If not, see <https://www.gnu.org/licenses/>. */
#include <config.h>
@@ -29,7 +29,7 @@
# include "nonblocking.h"
#endif
-#if (defined _WIN32 || defined __WIN32__) && ! defined __CYGWIN__
+#if defined _WIN32 && ! defined __CYGWIN__
/* Native Windows API. */
# include <io.h>
@@ -73,7 +73,7 @@ pipe2 (int fd[2], int flags)
return -1;
}
-#if (defined _WIN32 || defined __WIN32__) && ! defined __CYGWIN__
+#if defined _WIN32 && ! defined __CYGWIN__
/* Native Windows API. */
if (_pipe (fd, 4096, flags & ~O_NONBLOCK) < 0)
@@ -107,7 +107,7 @@ pipe2 (int fd[2], int flags)
if (pipe (fd) < 0)
return -1;
- /* POSIX <http://www.opengroup.org/onlinepubs/9699919799/functions/pipe.html>
+ /* POSIX <https://pubs.opengroup.org/onlinepubs/9699919799/functions/pipe.html>
says that initially, the O_NONBLOCK and FD_CLOEXEC flags are cleared on
both fd[0] and fd[1]. */
@@ -152,8 +152,7 @@ pipe2 (int fd[2], int flags)
#endif
-#if GNULIB_defined_O_NONBLOCK || \
- !((defined _WIN32 || defined __WIN32__) && ! defined __CYGWIN__)
+#if GNULIB_defined_O_NONBLOCK || !(defined _WIN32 && ! defined __CYGWIN__)
fail:
{
int saved_errno = errno;
diff --git a/lib/pselect.c b/lib/pselect.c
index 2ea7c45307c..a1eca0c6a26 100644
--- a/lib/pselect.c
+++ b/lib/pselect.c
@@ -1,21 +1,21 @@
/* pselect - synchronous I/O multiplexing
- Copyright 2011-2017 Free Software Foundation, Inc.
+ Copyright 2011-2022 Free Software Foundation, Inc.
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, or (at your option)
- any later version.
+ This file is free software: you can redistribute it and/or modify
+ it under the terms of the GNU Lesser General Public License as
+ published by the Free Software Foundation; either version 2.1 of the
+ License, or (at your option) any later version.
- This program is distributed in the hope that it will be useful,
+ This file 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.
+ GNU Lesser General Public License for more details.
- You should have received a copy of the GNU General Public License along
- with this program; if not, see <https://www.gnu.org/licenses/>. */
+ You should have received a copy of the GNU Lesser General Public License
+ along with this program. If not, see <https://www.gnu.org/licenses/>. */
/* written by Paul Eggert */
@@ -83,9 +83,9 @@ pselect (int nfds, fd_set *restrict rfds,
int
rpl_pselect (int nfds, fd_set *restrict rfds,
- fd_set *restrict wfds, fd_set *restrict xfds,
+ fd_set *restrict wfds, fd_set *restrict xfds,
struct timespec const *restrict timeout,
- sigset_t const *restrict sigmask)
+ sigset_t const *restrict sigmask)
{
int i;
diff --git a/lib/pthread_sigmask.c b/lib/pthread_sigmask.c
index 9ccf89b51fb..cd4eb807325 100644
--- a/lib/pthread_sigmask.c
+++ b/lib/pthread_sigmask.c
@@ -1,17 +1,17 @@
/* POSIX compatible signal blocking for threads.
- Copyright (C) 2011-2017 Free Software Foundation, Inc.
+ Copyright (C) 2011-2022 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 file is free software: you can redistribute it and/or modify
+ it under the terms of the GNU Lesser General Public License as
+ published by the Free Software Foundation; either version 2.1 of the
+ License, or (at your option) any later version.
- This program is distributed in the hope that it will be useful,
+ This file 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.
+ GNU Lesser General Public License for more details.
- You should have received a copy of the GNU General Public License
+ You should have received a copy of the GNU Lesser General Public License
along with this program. If not, see <https://www.gnu.org/licenses/>. */
#include <config.h>
diff --git a/lib/putenv.c b/lib/putenv.c
deleted file mode 100644
index 7831864478e..00000000000
--- a/lib/putenv.c
+++ /dev/null
@@ -1,194 +0,0 @@
-/* Copyright (C) 1991, 1994, 1997-1998, 2000, 2003-2017 Free Software
- Foundation, Inc.
-
- NOTE: The canonical source of this file is maintained with the GNU C
- Library. Bugs can be reported to bug-glibc@prep.ai.mit.edu.
-
- 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 any
- later version.
-
- This program is distributed in the hope that it will be useful,
- but WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- GNU General Public License for more details.
-
- You should have received a copy of the GNU General Public License
- along with this program. If not, see <https://www.gnu.org/licenses/>. */
-
-#include <config.h>
-
-/* Specification. */
-#include <stdlib.h>
-
-#include <stddef.h>
-
-/* Include errno.h *after* sys/types.h to work around header problems
- on AIX 3.2.5. */
-#include <errno.h>
-#ifndef __set_errno
-# define __set_errno(ev) ((errno) = (ev))
-#endif
-
-#include <string.h>
-#include <unistd.h>
-
-#if (defined _WIN32 || defined __WIN32__) && ! defined __CYGWIN__
-# define WIN32_LEAN_AND_MEAN
-# include <windows.h>
-#endif
-
-#if _LIBC
-# if HAVE_GNU_LD
-# define environ __environ
-# else
-extern char **environ;
-# endif
-#endif
-
-#if _LIBC
-/* This lock protects against simultaneous modifications of 'environ'. */
-# include <bits/libc-lock.h>
-__libc_lock_define_initialized (static, envlock)
-# define LOCK __libc_lock_lock (envlock)
-# define UNLOCK __libc_lock_unlock (envlock)
-#else
-# define LOCK
-# define UNLOCK
-#endif
-
-static int
-_unsetenv (const char *name)
-{
- size_t len;
-#if !HAVE_DECL__PUTENV
- char **ep;
-#endif
-
- if (name == NULL || *name == '\0' || strchr (name, '=') != NULL)
- {
- __set_errno (EINVAL);
- return -1;
- }
-
- len = strlen (name);
-
-#if HAVE_DECL__PUTENV
- {
- int putenv_result, putenv_errno;
- char *name_ = malloc (len + 2);
- memcpy (name_, name, len);
- name_[len] = '=';
- name_[len + 1] = 0;
- putenv_result = _putenv (name_);
- putenv_errno = errno;
- free (name_);
- __set_errno (putenv_errno);
- return putenv_result;
- }
-#else
-
- LOCK;
-
- ep = environ;
- while (*ep != NULL)
- if (!strncmp (*ep, name, len) && (*ep)[len] == '=')
- {
- /* Found it. Remove this pointer by moving later ones back. */
- char **dp = ep;
-
- do
- dp[0] = dp[1];
- while (*dp++);
- /* Continue the loop in case NAME appears again. */
- }
- else
- ++ep;
-
- UNLOCK;
-
- return 0;
-#endif
-}
-
-
-/* Put STRING, which is of the form "NAME=VALUE", in the environment.
- If STRING contains no '=', then remove STRING from the environment. */
-int
-putenv (char *string)
-{
- const char *name_end = strchr (string, '=');
- char **ep;
-
- if (name_end == NULL)
- {
- /* Remove the variable from the environment. */
- return _unsetenv (string);
- }
-
-#if HAVE_DECL__PUTENV
- /* Rely on _putenv to allocate the new environment. If other
- parts of the application use _putenv, the !HAVE_DECL__PUTENV code
- would fight over who owns the environ vector, causing a crash. */
- if (name_end[1])
- return _putenv (string);
- else
- {
- /* _putenv ("NAME=") unsets NAME, so invoke _putenv ("NAME= ")
- to allocate the environ vector and then replace the new
- entry with "NAME=". */
- int putenv_result, putenv_errno;
- char *name_x = malloc (name_end - string + sizeof "= ");
- if (!name_x)
- return -1;
- memcpy (name_x, string, name_end - string + 1);
- name_x[name_end - string + 1] = ' ';
- name_x[name_end - string + 2] = 0;
- putenv_result = _putenv (name_x);
- putenv_errno = errno;
- for (ep = environ; *ep; ep++)
- if (strcmp (*ep, name_x) == 0)
- {
- *ep = string;
- break;
- }
-# if (defined _WIN32 || defined __WIN32__) && ! defined __CYGWIN__
- if (putenv_result == 0)
- {
- /* _putenv propagated "NAME= " into the subprocess environment;
- fix that by calling SetEnvironmentVariable directly. */
- name_x[name_end - string] = 0;
- putenv_result = SetEnvironmentVariable (name_x, "") ? 0 : -1;
- putenv_errno = ENOMEM; /* ENOMEM is the only way to fail. */
- }
-# endif
- free (name_x);
- __set_errno (putenv_errno);
- return putenv_result;
- }
-#else
- for (ep = environ; *ep; ep++)
- if (strncmp (*ep, string, name_end - string) == 0
- && (*ep)[name_end - string] == '=')
- break;
-
- if (*ep)
- *ep = string;
- else
- {
- static char **last_environ = NULL;
- size_t size = ep - environ;
- char **new_environ = malloc ((size + 2) * sizeof *new_environ);
- if (! new_environ)
- return -1;
- new_environ[0] = string;
- memcpy (new_environ + 1, environ, (size + 1) * sizeof *new_environ);
- free (last_environ);
- last_environ = new_environ;
- environ = new_environ;
- }
-
- return 0;
-#endif
-}
diff --git a/lib/qcopy-acl.c b/lib/qcopy-acl.c
index 003cb42b7db..37fb179260d 100644
--- a/lib/qcopy-acl.c
+++ b/lib/qcopy-acl.c
@@ -1,10 +1,10 @@
/* Copy access control list from one file to another. -*- coding: utf-8 -*-
- Copyright (C) 2002-2003, 2005-2017 Free Software Foundation, Inc.
+ Copyright (C) 2002-2003, 2005-2022 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
+ 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,
diff --git a/lib/rawmemchr.c b/lib/rawmemchr.c
new file mode 100644
index 00000000000..ea68c1bfc6a
--- /dev/null
+++ b/lib/rawmemchr.c
@@ -0,0 +1,125 @@
+/* Searching in a string.
+ Copyright (C) 2008-2022 Free Software Foundation, Inc.
+
+ This file is free software: you can redistribute it and/or modify
+ it under the terms of the GNU Lesser General Public License as
+ published by the Free Software Foundation; either version 2.1 of the
+ License, or (at your option) any later version.
+
+ This file 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 Lesser General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public License
+ along with this program. If not, see <https://www.gnu.org/licenses/>. */
+
+#include <config.h>
+
+/* Specification. */
+#include <string.h>
+
+/* A function definition is only needed if HAVE_RAWMEMCHR is not defined. */
+#if !HAVE_RAWMEMCHR
+
+# include <limits.h>
+# include <stdalign.h>
+# include <stdint.h>
+
+# include "verify.h"
+
+/* Find the first occurrence of C in S. */
+void *
+rawmemchr (const void *s, int c_in)
+{
+ /* Change this typedef to experiment with performance. */
+ typedef uintptr_t longword;
+ /* If you change the "uintptr_t", you should change UINTPTR_WIDTH to match.
+ This verifies that the type does not have padding bits. */
+ verify (UINTPTR_WIDTH == UCHAR_WIDTH * sizeof (longword));
+
+ const unsigned char *char_ptr;
+ unsigned char c = c_in;
+
+ /* Handle the first few bytes by reading one byte at a time.
+ Do this until CHAR_PTR is aligned on a longword boundary. */
+ for (char_ptr = (const unsigned char *) s;
+ (uintptr_t) char_ptr % alignof (longword) != 0;
+ ++char_ptr)
+ if (*char_ptr == c)
+ return (void *) char_ptr;
+
+ longword const *longword_ptr = s = char_ptr;
+
+ /* Compute auxiliary longword values:
+ repeated_one is a value which has a 1 in every byte.
+ repeated_c has c in every byte. */
+ longword repeated_one = (longword) -1 / UCHAR_MAX;
+ longword repeated_c = repeated_one * c;
+ longword repeated_hibit = repeated_one * (UCHAR_MAX / 2 + 1);
+
+ /* Instead of the traditional loop which tests each byte, we will
+ test a longword at a time. The tricky part is testing if any of
+ the bytes in the longword in question are equal to
+ c. We first use an xor with repeated_c. This reduces the task
+ to testing whether any of the bytes in longword1 is zero.
+
+ (The following comments assume 8-bit bytes, as POSIX requires;
+ the code's use of UCHAR_MAX should work even if bytes have more
+ than 8 bits.)
+
+ We compute tmp =
+ ((longword1 - repeated_one) & ~longword1) & (repeated_one * 0x80).
+ That is, we perform the following operations:
+ 1. Subtract repeated_one.
+ 2. & ~longword1.
+ 3. & a mask consisting of 0x80 in every byte.
+ Consider what happens in each byte:
+ - If a byte of longword1 is zero, step 1 and 2 transform it into 0xff,
+ and step 3 transforms it into 0x80. A carry can also be propagated
+ to more significant bytes.
+ - If a byte of longword1 is nonzero, let its lowest 1 bit be at
+ position k (0 <= k <= 7); so the lowest k bits are 0. After step 1,
+ the byte ends in a single bit of value 0 and k bits of value 1.
+ After step 2, the result is just k bits of value 1: 2^k - 1. After
+ step 3, the result is 0. And no carry is produced.
+ So, if longword1 has only non-zero bytes, tmp is zero.
+ Whereas if longword1 has a zero byte, call j the position of the least
+ significant zero byte. Then the result has a zero at positions 0, ...,
+ j-1 and a 0x80 at position j. We cannot predict the result at the more
+ significant bytes (positions j+1..3), but it does not matter since we
+ already have a non-zero bit at position 8*j+7.
+
+ The test whether any byte in longword1 is zero is equivalent
+ to testing whether tmp is nonzero.
+
+ This test can read beyond the end of a string, depending on where
+ C_IN is encountered. However, this is considered safe since the
+ initialization phase ensured that the read will be aligned,
+ therefore, the read will not cross page boundaries and will not
+ cause a fault. */
+
+ while (1)
+ {
+ longword longword1 = *longword_ptr ^ repeated_c;
+
+ if ((((longword1 - repeated_one) & ~longword1) & repeated_hibit) != 0)
+ break;
+ longword_ptr++;
+ }
+
+ char_ptr = s = longword_ptr;
+
+ /* At this point, we know that one of the sizeof (longword) bytes
+ starting at char_ptr is == c. If we knew endianness, we
+ could determine the first such byte without any further memory
+ accesses, just by looking at the tmp result from the last loop
+ iteration. However, the following simple and portable code does
+ not attempt this potential optimization. */
+
+ while (*char_ptr != c)
+ char_ptr++;
+ return (void *) char_ptr;
+}
+
+#endif
diff --git a/lib/rawmemchr.valgrind b/lib/rawmemchr.valgrind
new file mode 100644
index 00000000000..64cf86c8429
--- /dev/null
+++ b/lib/rawmemchr.valgrind
@@ -0,0 +1,28 @@
+# Suppress a valgrind message about use of uninitialized memory in rawmemchr().
+
+# Copyright (C) 2008-2022 Free Software Foundation, Inc.
+#
+# This file is free software: you can redistribute it and/or modify
+# it under the terms of the GNU Lesser General Public License as
+# published by the Free Software Foundation; either version 2.1 of the
+# License, or (at your option) any later version.
+#
+# This file 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 Lesser General Public License for more details.
+#
+# You should have received a copy of the GNU Lesser General Public License
+# along with this program. If not, see <https://www.gnu.org/licenses/>.
+
+# This use is OK because it provides only a speedup.
+{
+ rawmemchr-value4
+ Memcheck:Value4
+ fun:rawmemchr
+}
+{
+ rawmemchr-value8
+ Memcheck:Value8
+ fun:rawmemchr
+}
diff --git a/lib/readlink.c b/lib/readlink.c
index cd9604b224c..ed03cc8ded1 100644
--- a/lib/readlink.c
+++ b/lib/readlink.c
@@ -1,17 +1,17 @@
-/* Stub for readlink().
- Copyright (C) 2003-2007, 2009-2017 Free Software Foundation, Inc.
+/* Read the contents of a symbolic link.
+ Copyright (C) 2003-2007, 2009-2022 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 file is free software: you can redistribute it and/or modify
+ it under the terms of the GNU Lesser General Public License as
+ published by the Free Software Foundation; either version 2.1 of the
+ License, or (at your option) any later version.
- This program is distributed in the hope that it will be useful,
+ This file 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.
+ GNU Lesser General Public License for more details.
- You should have received a copy of the GNU General Public License
+ You should have received a copy of the GNU Lesser General Public License
along with this program. If not, see <https://www.gnu.org/licenses/>. */
#include <config.h>
@@ -29,15 +29,15 @@
such as DJGPP 2.03 and mingw32. */
ssize_t
-readlink (const char *name, char *buf _GL_UNUSED,
- size_t bufsize _GL_UNUSED)
+readlink (char const *file, _GL_UNUSED char *buf,
+ _GL_UNUSED size_t bufsize)
{
struct stat statbuf;
/* In general we should use lstat() here, not stat(). But on platforms
without symbolic links, lstat() - if it exists - would be equivalent to
stat(), therefore we can use stat(). This saves us a configure check. */
- if (stat (name, &statbuf) >= 0)
+ if (stat (file, &statbuf) >= 0)
errno = EINVAL;
return -1;
}
@@ -51,24 +51,54 @@ readlink (const char *name, char *buf _GL_UNUSED,
for Solaris 9. */
ssize_t
-rpl_readlink (const char *name, char *buf, size_t bufsize)
+rpl_readlink (char const *file, char *buf, size_t bufsize)
{
# if READLINK_TRAILING_SLASH_BUG
- size_t len = strlen (name);
- if (len && name[len - 1] == '/')
+ size_t file_len = strlen (file);
+ if (file_len && file[file_len - 1] == '/')
{
- /* Even if name without the slash is a symlink to a directory,
+ /* Even if FILE without the slash is a symlink to a directory,
both lstat() and stat() must resolve the trailing slash to
the directory rather than the symlink. We can therefore
safely use stat() to distinguish between EINVAL and
ENOTDIR/ENOENT, avoiding extra overhead of rpl_lstat(). */
struct stat st;
- if (stat (name, &st) == 0)
+ if (stat (file, &st) == 0 || errno == EOVERFLOW)
errno = EINVAL;
return -1;
}
# endif /* READLINK_TRAILING_SLASH_BUG */
- return readlink (name, buf, bufsize);
+
+ ssize_t r = readlink (file, buf, bufsize);
+
+# if READLINK_TRUNCATE_BUG
+ if (r < 0 && errno == ERANGE)
+ {
+ /* Try again with a bigger buffer. This is just for test cases;
+ real code invariably discards short reads. */
+ char stackbuf[4032];
+ r = readlink (file, stackbuf, sizeof stackbuf);
+ if (r < 0)
+ {
+ if (errno == ERANGE)
+ {
+ /* Clear the buffer, which is good enough for real code.
+ Thankfully, no test cases try short reads of enormous
+ symlinks and what would be the point anyway? */
+ r = bufsize;
+ memset (buf, 0, r);
+ }
+ }
+ else
+ {
+ if (bufsize < r)
+ r = bufsize;
+ memcpy (buf, stackbuf, r);
+ }
+ }
+# endif
+
+ return r;
}
#endif /* HAVE_READLINK */
diff --git a/lib/readlinkat.c b/lib/readlinkat.c
index c9880e1c704..ab45e140b59 100644
--- a/lib/readlinkat.c
+++ b/lib/readlinkat.c
@@ -1,9 +1,9 @@
/* Read a symlink relative to an open directory.
- Copyright (C) 2009-2017 Free Software Foundation, Inc.
+ Copyright (C) 2009-2022 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
+ 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,
@@ -18,17 +18,21 @@
#include <config.h>
-#include <errno.h>
+/* Specification. */
#include <unistd.h>
+
+#include <errno.h>
+#include <stdlib.h>
#include <string.h>
#include <sys/stat.h>
#if HAVE_READLINKAT
+# undef fstatat
# undef readlinkat
ssize_t
-rpl_readlinkat (int fd, char const *file, char *buf, size_t len)
+rpl_readlinkat (int fd, char const *file, char *buf, size_t bufsize)
{
# if READLINK_TRAILING_SLASH_BUG
size_t file_len = strlen (file);
@@ -37,15 +41,45 @@ rpl_readlinkat (int fd, char const *file, char *buf, size_t len)
/* Even if FILE without the slash is a symlink to a directory,
both lstat() and stat() must resolve the trailing slash to
the directory rather than the symlink. We can therefore
- safely use stat() to distinguish between EINVAL and
- ENOTDIR/ENOENT, avoiding extra overhead of rpl_lstat(). */
+ safely use fstatat(..., 0) to distinguish between EINVAL and
+ ENOTDIR/ENOENT, avoiding extra overhead of rpl_fstatat(). */
struct stat st;
- if (stat (file, &st) == 0)
+ if (fstatat (fd, file, &st, 0) == 0 || errno == EOVERFLOW)
errno = EINVAL;
return -1;
}
# endif /* READLINK_TRAILING_SLASH_BUG */
- return readlinkat (fd, file, buf, len);
+
+ ssize_t r = readlinkat (fd, file, buf, bufsize);
+
+# if READLINK_TRUNCATE_BUG
+ if (r < 0 && errno == ERANGE)
+ {
+ /* Try again with a bigger buffer. This is just for test cases;
+ real code invariably discards short reads. */
+ char stackbuf[4032];
+ r = readlinkat (fd, file, stackbuf, sizeof stackbuf);
+ if (r < 0)
+ {
+ if (errno == ERANGE)
+ {
+ /* Clear the buffer, which is good enough for real code.
+ Thankfully, no test cases try short reads of enormous
+ symlinks and what would be the point anyway? */
+ r = bufsize;
+ memset (buf, 0, r);
+ }
+ }
+ else
+ {
+ if (bufsize < r)
+ r = bufsize;
+ memcpy (buf, stackbuf, r);
+ }
+ }
+# endif
+
+ return r;
}
#else
@@ -58,7 +92,7 @@ rpl_readlinkat (int fd, char const *file, char *buf, size_t len)
readlinkat worthless since readlink does not guarantee a
NUL-terminated buffer. Assume this was a bug in POSIX. */
-/* Read the contents of symlink FILE into buffer BUF of size LEN, in the
+/* Read the contents of symlink FILE into buffer BUF of size BUFSIZE, in the
directory open on descriptor FD. If possible, do it without changing
the working directory. Otherwise, resort to using save_cwd/fchdir,
then readlink/restore_cwd. If either the save_cwd or the restore_cwd
@@ -66,8 +100,8 @@ rpl_readlinkat (int fd, char const *file, char *buf, size_t len)
# define AT_FUNC_NAME readlinkat
# define AT_FUNC_F1 readlink
-# define AT_FUNC_POST_FILE_PARAM_DECLS , char *buf, size_t len
-# define AT_FUNC_POST_FILE_ARGS , buf, len
+# define AT_FUNC_POST_FILE_PARAM_DECLS , char *buf, size_t bufsize
+# define AT_FUNC_POST_FILE_ARGS , buf, bufsize
# define AT_FUNC_RESULT ssize_t
# include "at-func.c"
# undef AT_FUNC_NAME
diff --git a/lib/realloc.c b/lib/realloc.c
new file mode 100644
index 00000000000..c8783815761
--- /dev/null
+++ b/lib/realloc.c
@@ -0,0 +1,63 @@
+/* realloc() function that is glibc compatible.
+
+ Copyright (C) 1997, 2003-2004, 2006-2007, 2009-2022 Free Software
+ Foundation, Inc.
+
+ This file is free software: you can redistribute it and/or modify
+ it under the terms of the GNU Lesser General Public License as
+ published by the Free Software Foundation; either version 2.1 of the
+ License, or (at your option) any later version.
+
+ This file 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 Lesser General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public License
+ along with this program. If not, see <https://www.gnu.org/licenses/>. */
+
+/* written by Jim Meyering and Bruno Haible */
+
+#include <config.h>
+
+#include <stdlib.h>
+
+#include <errno.h>
+
+#include "xalloc-oversized.h"
+
+/* Call the system's realloc below. This file does not define
+ _GL_USE_STDLIB_ALLOC because it needs Gnulib's malloc if present. */
+#undef realloc
+
+/* Change the size of an allocated block of memory P to N bytes,
+ with error checking. If P is NULL, use malloc. Otherwise if N is zero,
+ free P and return NULL. */
+
+void *
+rpl_realloc (void *p, size_t n)
+{
+ if (p == NULL)
+ return malloc (n);
+
+ if (n == 0)
+ {
+ free (p);
+ return NULL;
+ }
+
+ if (xalloc_oversized (n, 1))
+ {
+ errno = ENOMEM;
+ return NULL;
+ }
+
+ void *result = realloc (p, n);
+
+#if !HAVE_MALLOC_POSIX
+ if (result == NULL)
+ errno = ENOMEM;
+#endif
+
+ return result;
+}
diff --git a/lib/regcomp.c b/lib/regcomp.c
new file mode 100644
index 00000000000..122c3de58c3
--- /dev/null
+++ b/lib/regcomp.c
@@ -0,0 +1,3788 @@
+/* Extended regular expression matching and search library.
+ Copyright (C) 2002-2022 Free Software Foundation, Inc.
+ This file is part of the GNU C Library.
+ Contributed by Isamu Hasegawa <isamu@yamato.ibm.com>.
+
+ The GNU C Library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Lesser General Public
+ License as published by the Free Software Foundation; either
+ version 2.1 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
+ Lesser General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public
+ License along with the GNU C Library; if not, see
+ <https://www.gnu.org/licenses/>. */
+
+#ifdef _LIBC
+# include <locale/weight.h>
+#endif
+
+static reg_errcode_t re_compile_internal (regex_t *preg, const char * pattern,
+ size_t length, reg_syntax_t syntax);
+static void re_compile_fastmap_iter (regex_t *bufp,
+ const re_dfastate_t *init_state,
+ char *fastmap);
+static reg_errcode_t init_dfa (re_dfa_t *dfa, size_t pat_len);
+static void free_charset (re_charset_t *cset);
+static void free_workarea_compile (regex_t *preg);
+static reg_errcode_t create_initial_state (re_dfa_t *dfa);
+static void optimize_utf8 (re_dfa_t *dfa);
+static reg_errcode_t analyze (regex_t *preg);
+static reg_errcode_t preorder (bin_tree_t *root,
+ reg_errcode_t (fn (void *, bin_tree_t *)),
+ void *extra);
+static reg_errcode_t postorder (bin_tree_t *root,
+ reg_errcode_t (fn (void *, bin_tree_t *)),
+ void *extra);
+static reg_errcode_t optimize_subexps (void *extra, bin_tree_t *node);
+static reg_errcode_t lower_subexps (void *extra, bin_tree_t *node);
+static bin_tree_t *lower_subexp (reg_errcode_t *err, regex_t *preg,
+ bin_tree_t *node);
+static reg_errcode_t calc_first (void *extra, bin_tree_t *node);
+static reg_errcode_t calc_next (void *extra, bin_tree_t *node);
+static reg_errcode_t link_nfa_nodes (void *extra, bin_tree_t *node);
+static Idx duplicate_node (re_dfa_t *dfa, Idx org_idx, unsigned int constraint);
+static Idx search_duplicated_node (const re_dfa_t *dfa, Idx org_node,
+ unsigned int constraint);
+static reg_errcode_t calc_eclosure (re_dfa_t *dfa);
+static reg_errcode_t calc_eclosure_iter (re_node_set *new_set, re_dfa_t *dfa,
+ Idx node, bool root);
+static reg_errcode_t calc_inveclosure (re_dfa_t *dfa);
+static Idx fetch_number (re_string_t *input, re_token_t *token,
+ reg_syntax_t syntax);
+static int peek_token (re_token_t *token, re_string_t *input,
+ reg_syntax_t syntax);
+static bin_tree_t *parse (re_string_t *regexp, regex_t *preg,
+ reg_syntax_t syntax, reg_errcode_t *err);
+static bin_tree_t *parse_reg_exp (re_string_t *regexp, regex_t *preg,
+ re_token_t *token, reg_syntax_t syntax,
+ Idx nest, reg_errcode_t *err);
+static bin_tree_t *parse_branch (re_string_t *regexp, regex_t *preg,
+ re_token_t *token, reg_syntax_t syntax,
+ Idx nest, reg_errcode_t *err);
+static bin_tree_t *parse_expression (re_string_t *regexp, regex_t *preg,
+ re_token_t *token, reg_syntax_t syntax,
+ Idx nest, reg_errcode_t *err);
+static bin_tree_t *parse_sub_exp (re_string_t *regexp, regex_t *preg,
+ re_token_t *token, reg_syntax_t syntax,
+ Idx nest, reg_errcode_t *err);
+static bin_tree_t *parse_dup_op (bin_tree_t *dup_elem, re_string_t *regexp,
+ re_dfa_t *dfa, re_token_t *token,
+ reg_syntax_t syntax, reg_errcode_t *err);
+static bin_tree_t *parse_bracket_exp (re_string_t *regexp, re_dfa_t *dfa,
+ re_token_t *token, reg_syntax_t syntax,
+ reg_errcode_t *err);
+static reg_errcode_t parse_bracket_element (bracket_elem_t *elem,
+ re_string_t *regexp,
+ re_token_t *token, int token_len,
+ re_dfa_t *dfa,
+ reg_syntax_t syntax,
+ bool accept_hyphen);
+static reg_errcode_t parse_bracket_symbol (bracket_elem_t *elem,
+ re_string_t *regexp,
+ re_token_t *token);
+static reg_errcode_t build_equiv_class (bitset_t sbcset,
+ re_charset_t *mbcset,
+ Idx *equiv_class_alloc,
+ const unsigned char *name);
+static reg_errcode_t build_charclass (RE_TRANSLATE_TYPE trans,
+ bitset_t sbcset,
+ re_charset_t *mbcset,
+ Idx *char_class_alloc,
+ const char *class_name,
+ reg_syntax_t syntax);
+static bin_tree_t *build_charclass_op (re_dfa_t *dfa,
+ RE_TRANSLATE_TYPE trans,
+ const char *class_name,
+ const char *extra,
+ bool non_match, reg_errcode_t *err);
+static bin_tree_t *create_tree (re_dfa_t *dfa,
+ bin_tree_t *left, bin_tree_t *right,
+ re_token_type_t type);
+static bin_tree_t *create_token_tree (re_dfa_t *dfa,
+ bin_tree_t *left, bin_tree_t *right,
+ const re_token_t *token);
+static bin_tree_t *duplicate_tree (const bin_tree_t *src, re_dfa_t *dfa);
+static void free_token (re_token_t *node);
+static reg_errcode_t free_tree (void *extra, bin_tree_t *node);
+static reg_errcode_t mark_opt_subexp (void *extra, bin_tree_t *node);
+
+/* This table gives an error message for each of the error codes listed
+ in regex.h. Obviously the order here has to be same as there.
+ POSIX doesn't require that we do anything for REG_NOERROR,
+ but why not be nice? */
+
+static const char __re_error_msgid[] =
+ {
+#define REG_NOERROR_IDX 0
+ gettext_noop ("Success") /* REG_NOERROR */
+ "\0"
+#define REG_NOMATCH_IDX (REG_NOERROR_IDX + sizeof "Success")
+ gettext_noop ("No match") /* REG_NOMATCH */
+ "\0"
+#define REG_BADPAT_IDX (REG_NOMATCH_IDX + sizeof "No match")
+ gettext_noop ("Invalid regular expression") /* REG_BADPAT */
+ "\0"
+#define REG_ECOLLATE_IDX (REG_BADPAT_IDX + sizeof "Invalid regular expression")
+ gettext_noop ("Invalid collation character") /* REG_ECOLLATE */
+ "\0"
+#define REG_ECTYPE_IDX (REG_ECOLLATE_IDX + sizeof "Invalid collation character")
+ gettext_noop ("Invalid character class name") /* REG_ECTYPE */
+ "\0"
+#define REG_EESCAPE_IDX (REG_ECTYPE_IDX + sizeof "Invalid character class name")
+ gettext_noop ("Trailing backslash") /* REG_EESCAPE */
+ "\0"
+#define REG_ESUBREG_IDX (REG_EESCAPE_IDX + sizeof "Trailing backslash")
+ gettext_noop ("Invalid back reference") /* REG_ESUBREG */
+ "\0"
+#define REG_EBRACK_IDX (REG_ESUBREG_IDX + sizeof "Invalid back reference")
+ gettext_noop ("Unmatched [, [^, [:, [., or [=") /* REG_EBRACK */
+ "\0"
+#define REG_EPAREN_IDX (REG_EBRACK_IDX + sizeof "Unmatched [, [^, [:, [., or [=")
+ gettext_noop ("Unmatched ( or \\(") /* REG_EPAREN */
+ "\0"
+#define REG_EBRACE_IDX (REG_EPAREN_IDX + sizeof "Unmatched ( or \\(")
+ gettext_noop ("Unmatched \\{") /* REG_EBRACE */
+ "\0"
+#define REG_BADBR_IDX (REG_EBRACE_IDX + sizeof "Unmatched \\{")
+ gettext_noop ("Invalid content of \\{\\}") /* REG_BADBR */
+ "\0"
+#define REG_ERANGE_IDX (REG_BADBR_IDX + sizeof "Invalid content of \\{\\}")
+ gettext_noop ("Invalid range end") /* REG_ERANGE */
+ "\0"
+#define REG_ESPACE_IDX (REG_ERANGE_IDX + sizeof "Invalid range end")
+ gettext_noop ("Memory exhausted") /* REG_ESPACE */
+ "\0"
+#define REG_BADRPT_IDX (REG_ESPACE_IDX + sizeof "Memory exhausted")
+ gettext_noop ("Invalid preceding regular expression") /* REG_BADRPT */
+ "\0"
+#define REG_EEND_IDX (REG_BADRPT_IDX + sizeof "Invalid preceding regular expression")
+ gettext_noop ("Premature end of regular expression") /* REG_EEND */
+ "\0"
+#define REG_ESIZE_IDX (REG_EEND_IDX + sizeof "Premature end of regular expression")
+ gettext_noop ("Regular expression too big") /* REG_ESIZE */
+ "\0"
+#define REG_ERPAREN_IDX (REG_ESIZE_IDX + sizeof "Regular expression too big")
+ gettext_noop ("Unmatched ) or \\)") /* REG_ERPAREN */
+ };
+
+static const size_t __re_error_msgid_idx[] =
+ {
+ REG_NOERROR_IDX,
+ REG_NOMATCH_IDX,
+ REG_BADPAT_IDX,
+ REG_ECOLLATE_IDX,
+ REG_ECTYPE_IDX,
+ REG_EESCAPE_IDX,
+ REG_ESUBREG_IDX,
+ REG_EBRACK_IDX,
+ REG_EPAREN_IDX,
+ REG_EBRACE_IDX,
+ REG_BADBR_IDX,
+ REG_ERANGE_IDX,
+ REG_ESPACE_IDX,
+ REG_BADRPT_IDX,
+ REG_EEND_IDX,
+ REG_ESIZE_IDX,
+ REG_ERPAREN_IDX
+ };
+
+/* Entry points for GNU code. */
+
+/* re_compile_pattern is the GNU regular expression compiler: it
+ compiles PATTERN (of length LENGTH) and puts the result in BUFP.
+ Returns 0 if the pattern was valid, otherwise an error string.
+
+ Assumes the 'allocated' (and perhaps 'buffer') and 'translate' fields
+ are set in BUFP on entry. */
+
+const char *
+re_compile_pattern (const char *pattern, size_t length,
+ struct re_pattern_buffer *bufp)
+{
+ reg_errcode_t ret;
+
+ /* And GNU code determines whether or not to get register information
+ by passing null for the REGS argument to re_match, etc., not by
+ setting no_sub, unless RE_NO_SUB is set. */
+ bufp->no_sub = !!(re_syntax_options & RE_NO_SUB);
+
+ /* Match anchors at newline. */
+ bufp->newline_anchor = 1;
+
+ ret = re_compile_internal (bufp, pattern, length, re_syntax_options);
+
+ if (!ret)
+ return NULL;
+ return gettext (__re_error_msgid + __re_error_msgid_idx[(int) ret]);
+}
+weak_alias (__re_compile_pattern, re_compile_pattern)
+
+/* Set by 're_set_syntax' to the current regexp syntax to recognize. Can
+ also be assigned to arbitrarily: each pattern buffer stores its own
+ syntax, so it can be changed between regex compilations. */
+/* This has no initializer because initialized variables in Emacs
+ become read-only after dumping. */
+reg_syntax_t re_syntax_options;
+
+
+/* Specify the precise syntax of regexps for compilation. This provides
+ for compatibility for various utilities which historically have
+ different, incompatible syntaxes.
+
+ The argument SYNTAX is a bit mask comprised of the various bits
+ defined in regex.h. We return the old syntax. */
+
+reg_syntax_t
+re_set_syntax (reg_syntax_t syntax)
+{
+ reg_syntax_t ret = re_syntax_options;
+
+ re_syntax_options = syntax;
+ return ret;
+}
+weak_alias (__re_set_syntax, re_set_syntax)
+
+int
+re_compile_fastmap (struct re_pattern_buffer *bufp)
+{
+ re_dfa_t *dfa = bufp->buffer;
+ char *fastmap = bufp->fastmap;
+
+ memset (fastmap, '\0', sizeof (char) * SBC_MAX);
+ re_compile_fastmap_iter (bufp, dfa->init_state, fastmap);
+ if (dfa->init_state != dfa->init_state_word)
+ re_compile_fastmap_iter (bufp, dfa->init_state_word, fastmap);
+ if (dfa->init_state != dfa->init_state_nl)
+ re_compile_fastmap_iter (bufp, dfa->init_state_nl, fastmap);
+ if (dfa->init_state != dfa->init_state_begbuf)
+ re_compile_fastmap_iter (bufp, dfa->init_state_begbuf, fastmap);
+ bufp->fastmap_accurate = 1;
+ return 0;
+}
+weak_alias (__re_compile_fastmap, re_compile_fastmap)
+
+static __always_inline void
+re_set_fastmap (char *fastmap, bool icase, int ch)
+{
+ fastmap[ch] = 1;
+ if (icase)
+ fastmap[tolower (ch)] = 1;
+}
+
+/* Helper function for re_compile_fastmap.
+ Compile fastmap for the initial_state INIT_STATE. */
+
+static void
+re_compile_fastmap_iter (regex_t *bufp, const re_dfastate_t *init_state,
+ char *fastmap)
+{
+ re_dfa_t *dfa = bufp->buffer;
+ Idx node_cnt;
+ bool icase = (dfa->mb_cur_max == 1 && (bufp->syntax & RE_ICASE));
+ for (node_cnt = 0; node_cnt < init_state->nodes.nelem; ++node_cnt)
+ {
+ Idx node = init_state->nodes.elems[node_cnt];
+ re_token_type_t type = dfa->nodes[node].type;
+
+ if (type == CHARACTER)
+ {
+ re_set_fastmap (fastmap, icase, dfa->nodes[node].opr.c);
+ if ((bufp->syntax & RE_ICASE) && dfa->mb_cur_max > 1)
+ {
+ unsigned char buf[MB_LEN_MAX];
+ unsigned char *p;
+ wchar_t wc;
+ mbstate_t state;
+
+ p = buf;
+ *p++ = dfa->nodes[node].opr.c;
+ while (++node < dfa->nodes_len
+ && dfa->nodes[node].type == CHARACTER
+ && dfa->nodes[node].mb_partial)
+ *p++ = dfa->nodes[node].opr.c;
+ memset (&state, '\0', sizeof (state));
+ if (__mbrtowc (&wc, (const char *) buf, p - buf,
+ &state) == p - buf
+ && (__wcrtomb ((char *) buf, __towlower (wc), &state)
+ != (size_t) -1))
+ re_set_fastmap (fastmap, false, buf[0]);
+ }
+ }
+ else if (type == SIMPLE_BRACKET)
+ {
+ int i, ch;
+ for (i = 0, ch = 0; i < BITSET_WORDS; ++i)
+ {
+ int j;
+ bitset_word_t w = dfa->nodes[node].opr.sbcset[i];
+ for (j = 0; j < BITSET_WORD_BITS; ++j, ++ch)
+ if (w & ((bitset_word_t) 1 << j))
+ re_set_fastmap (fastmap, icase, ch);
+ }
+ }
+ else if (type == COMPLEX_BRACKET)
+ {
+ re_charset_t *cset = dfa->nodes[node].opr.mbcset;
+ Idx i;
+
+#ifdef _LIBC
+ /* See if we have to try all bytes which start multiple collation
+ elements.
+ e.g. In da_DK, we want to catch 'a' since "aa" is a valid
+ collation element, and don't catch 'b' since 'b' is
+ the only collation element which starts from 'b' (and
+ it is caught by SIMPLE_BRACKET). */
+ if (_NL_CURRENT_WORD (LC_COLLATE, _NL_COLLATE_NRULES) != 0
+ && (cset->ncoll_syms || cset->nranges))
+ {
+ const int32_t *table = (const int32_t *)
+ _NL_CURRENT (LC_COLLATE, _NL_COLLATE_TABLEMB);
+ for (i = 0; i < SBC_MAX; ++i)
+ if (table[i] < 0)
+ re_set_fastmap (fastmap, icase, i);
+ }
+#endif /* _LIBC */
+
+ /* See if we have to start the match at all multibyte characters,
+ i.e. where we would not find an invalid sequence. This only
+ applies to multibyte character sets; for single byte character
+ sets, the SIMPLE_BRACKET again suffices. */
+ if (dfa->mb_cur_max > 1
+ && (cset->nchar_classes || cset->non_match || cset->nranges
+#ifdef _LIBC
+ || cset->nequiv_classes
+#endif /* _LIBC */
+ ))
+ {
+ unsigned char c = 0;
+ do
+ {
+ mbstate_t mbs;
+ memset (&mbs, 0, sizeof (mbs));
+ if (__mbrtowc (NULL, (char *) &c, 1, &mbs) == (size_t) -2)
+ re_set_fastmap (fastmap, false, (int) c);
+ }
+ while (++c != 0);
+ }
+
+ else
+ {
+ /* ... Else catch all bytes which can start the mbchars. */
+ for (i = 0; i < cset->nmbchars; ++i)
+ {
+ char buf[256];
+ mbstate_t state;
+ memset (&state, '\0', sizeof (state));
+ if (__wcrtomb (buf, cset->mbchars[i], &state) != (size_t) -1)
+ re_set_fastmap (fastmap, icase, *(unsigned char *) buf);
+ if ((bufp->syntax & RE_ICASE) && dfa->mb_cur_max > 1)
+ {
+ if (__wcrtomb (buf, __towlower (cset->mbchars[i]), &state)
+ != (size_t) -1)
+ re_set_fastmap (fastmap, false, *(unsigned char *) buf);
+ }
+ }
+ }
+ }
+ else if (type == OP_PERIOD || type == OP_UTF8_PERIOD || type == END_OF_RE)
+ {
+ memset (fastmap, '\1', sizeof (char) * SBC_MAX);
+ if (type == END_OF_RE)
+ bufp->can_be_null = 1;
+ return;
+ }
+ }
+}
+
+/* Entry point for POSIX code. */
+/* regcomp takes a regular expression as a string and compiles it.
+
+ PREG is a regex_t *. We do not expect any fields to be initialized,
+ since POSIX says we shouldn't. Thus, we set
+
+ 'buffer' to the compiled pattern;
+ 'used' to the length of the compiled pattern;
+ 'syntax' to RE_SYNTAX_POSIX_EXTENDED if the
+ REG_EXTENDED bit in CFLAGS is set; otherwise, to
+ RE_SYNTAX_POSIX_BASIC;
+ 'newline_anchor' to REG_NEWLINE being set in CFLAGS;
+ 'fastmap' to an allocated space for the fastmap;
+ 'fastmap_accurate' to zero;
+ 're_nsub' to the number of subexpressions in PATTERN.
+
+ PATTERN is the address of the pattern string.
+
+ CFLAGS is a series of bits which affect compilation.
+
+ If REG_EXTENDED is set, we use POSIX extended syntax; otherwise, we
+ use POSIX basic syntax.
+
+ If REG_NEWLINE is set, then . and [^...] don't match newline.
+ Also, regexec will try a match beginning after every newline.
+
+ If REG_ICASE is set, then we considers upper- and lowercase
+ versions of letters to be equivalent when matching.
+
+ If REG_NOSUB is set, then when PREG is passed to regexec, that
+ routine will report only success or failure, and nothing about the
+ registers.
+
+ It returns 0 if it succeeds, nonzero if it doesn't. (See regex.h for
+ the return codes and their meanings.) */
+
+int
+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
+ : RE_SYNTAX_POSIX_BASIC);
+
+ preg->buffer = NULL;
+ preg->allocated = 0;
+ preg->used = 0;
+
+ /* Try to allocate space for the fastmap. */
+ preg->fastmap = re_malloc (char, SBC_MAX);
+ if (__glibc_unlikely (preg->fastmap == NULL))
+ return REG_ESPACE;
+
+ syntax |= (cflags & REG_ICASE) ? RE_ICASE : 0;
+
+ /* If REG_NEWLINE is set, newlines are treated differently. */
+ if (cflags & REG_NEWLINE)
+ { /* REG_NEWLINE implies neither . nor [^...] match newline. */
+ syntax &= ~RE_DOT_NEWLINE;
+ syntax |= RE_HAT_LISTS_NOT_NEWLINE;
+ /* It also changes the matching behavior. */
+ preg->newline_anchor = 1;
+ }
+ else
+ preg->newline_anchor = 0;
+ preg->no_sub = !!(cflags & REG_NOSUB);
+ preg->translate = NULL;
+
+ ret = re_compile_internal (preg, pattern, strlen (pattern), syntax);
+
+ /* POSIX doesn't distinguish between an unmatched open-group and an
+ unmatched close-group: both are REG_EPAREN. */
+ if (ret == REG_ERPAREN)
+ ret = REG_EPAREN;
+
+ /* We have already checked preg->fastmap != NULL. */
+ if (__glibc_likely (ret == REG_NOERROR))
+ /* Compute the fastmap now, since regexec cannot modify the pattern
+ buffer. This function never fails in this implementation. */
+ (void) re_compile_fastmap (preg);
+ else
+ {
+ /* Some error occurred while compiling the expression. */
+ re_free (preg->fastmap);
+ preg->fastmap = NULL;
+ }
+
+ return (int) ret;
+}
+libc_hidden_def (__regcomp)
+weak_alias (__regcomp, regcomp)
+
+/* 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,
+ size_t errbuf_size)
+{
+ const char *msg;
+ size_t msg_size;
+ int nerrcodes = sizeof __re_error_msgid_idx / sizeof __re_error_msgid_idx[0];
+
+ if (__glibc_unlikely (errcode < 0 || errcode >= nerrcodes))
+ /* Only error codes returned by the rest of the code should be passed
+ to this routine. If we are given anything else, or if other regex
+ code generates an invalid error code, then the program has a bug.
+ Dump core so we can fix it. */
+ abort ();
+
+ msg = gettext (__re_error_msgid + __re_error_msgid_idx[errcode]);
+
+ msg_size = strlen (msg) + 1; /* Includes the null. */
+
+ if (__glibc_likely (errbuf_size != 0))
+ {
+ size_t cpy_size = msg_size;
+ if (__glibc_unlikely (msg_size > errbuf_size))
+ {
+ cpy_size = errbuf_size - 1;
+ errbuf[cpy_size] = '\0';
+ }
+ memcpy (errbuf, msg, cpy_size);
+ }
+
+ return msg_size;
+}
+weak_alias (__regerror, regerror)
+
+
+/* This static array is used for the map to single-byte characters when
+ UTF-8 is used. Otherwise we would allocate memory just to initialize
+ it the same all the time. UTF-8 is the preferred encoding so this is
+ a worthwhile optimization. */
+static const bitset_t utf8_sb_map =
+{
+ /* Set the first 128 bits. */
+#if (defined __GNUC__ || __clang_major__ >= 4) && !defined __STRICT_ANSI__
+ [0 ... 0x80 / BITSET_WORD_BITS - 1] = BITSET_WORD_MAX
+#else
+# if 4 * BITSET_WORD_BITS < ASCII_CHARS
+# error "bitset_word_t is narrower than 32 bits"
+# elif 3 * BITSET_WORD_BITS < ASCII_CHARS
+ BITSET_WORD_MAX, BITSET_WORD_MAX, BITSET_WORD_MAX,
+# elif 2 * BITSET_WORD_BITS < ASCII_CHARS
+ BITSET_WORD_MAX, BITSET_WORD_MAX,
+# elif 1 * BITSET_WORD_BITS < ASCII_CHARS
+ BITSET_WORD_MAX,
+# endif
+ (BITSET_WORD_MAX
+ >> (SBC_MAX % BITSET_WORD_BITS == 0
+ ? 0
+ : BITSET_WORD_BITS - SBC_MAX % BITSET_WORD_BITS))
+#endif
+};
+
+
+static void
+free_dfa_content (re_dfa_t *dfa)
+{
+ Idx i, j;
+
+ if (dfa->nodes)
+ for (i = 0; i < dfa->nodes_len; ++i)
+ free_token (dfa->nodes + i);
+ re_free (dfa->nexts);
+ for (i = 0; i < dfa->nodes_len; ++i)
+ {
+ if (dfa->eclosures != NULL)
+ re_node_set_free (dfa->eclosures + i);
+ if (dfa->inveclosures != NULL)
+ re_node_set_free (dfa->inveclosures + i);
+ if (dfa->edests != NULL)
+ re_node_set_free (dfa->edests + i);
+ }
+ re_free (dfa->edests);
+ re_free (dfa->eclosures);
+ re_free (dfa->inveclosures);
+ re_free (dfa->nodes);
+
+ if (dfa->state_table)
+ for (i = 0; i <= dfa->state_hash_mask; ++i)
+ {
+ struct re_state_table_entry *entry = dfa->state_table + i;
+ for (j = 0; j < entry->num; ++j)
+ {
+ re_dfastate_t *state = entry->array[j];
+ free_state (state);
+ }
+ re_free (entry->array);
+ }
+ re_free (dfa->state_table);
+ if (dfa->sb_char != utf8_sb_map)
+ re_free (dfa->sb_char);
+ re_free (dfa->subexp_map);
+#ifdef DEBUG
+ re_free (dfa->re_str);
+#endif
+
+ re_free (dfa);
+}
+
+
+/* Free dynamically allocated space used by PREG. */
+
+void
+regfree (regex_t *preg)
+{
+ re_dfa_t *dfa = preg->buffer;
+ if (__glibc_likely (dfa != NULL))
+ {
+ lock_fini (dfa->lock);
+ free_dfa_content (dfa);
+ }
+ preg->buffer = NULL;
+ preg->allocated = 0;
+
+ re_free (preg->fastmap);
+ preg->fastmap = NULL;
+
+ re_free (preg->translate);
+ preg->translate = NULL;
+}
+libc_hidden_def (__regfree)
+weak_alias (__regfree, regfree)
+
+/* Entry points compatible with 4.2 BSD regex library. We don't define
+ them unless specifically requested. */
+
+#if defined _REGEX_RE_COMP || defined _LIBC
+
+/* BSD has one and only one pattern buffer. */
+static struct re_pattern_buffer re_comp_buf;
+
+char *
+# ifdef _LIBC
+/* Make these definitions weak in libc, so POSIX programs can redefine
+ these names if they don't use our functions, and still use
+ regcomp/regexec above without link errors. */
+weak_function
+# endif
+re_comp (const char *s)
+{
+ reg_errcode_t ret;
+ char *fastmap;
+
+ if (!s)
+ {
+ if (!re_comp_buf.buffer)
+ return gettext ("No previous regular expression");
+ return 0;
+ }
+
+ if (re_comp_buf.buffer)
+ {
+ fastmap = re_comp_buf.fastmap;
+ re_comp_buf.fastmap = NULL;
+ __regfree (&re_comp_buf);
+ memset (&re_comp_buf, '\0', sizeof (re_comp_buf));
+ re_comp_buf.fastmap = fastmap;
+ }
+
+ if (re_comp_buf.fastmap == NULL)
+ {
+ re_comp_buf.fastmap = re_malloc (char, SBC_MAX);
+ if (re_comp_buf.fastmap == NULL)
+ return (char *) gettext (__re_error_msgid
+ + __re_error_msgid_idx[(int) REG_ESPACE]);
+ }
+
+ /* Since 're_exec' always passes NULL for the 'regs' argument, we
+ don't need to initialize the pattern buffer fields which affect it. */
+
+ /* Match anchors at newlines. */
+ re_comp_buf.newline_anchor = 1;
+
+ ret = re_compile_internal (&re_comp_buf, s, strlen (s), re_syntax_options);
+
+ if (!ret)
+ return NULL;
+
+ /* Yes, we're discarding 'const' here if !HAVE_LIBINTL. */
+ return (char *) gettext (__re_error_msgid + __re_error_msgid_idx[(int) ret]);
+}
+
+#ifdef _LIBC
+libc_freeres_fn (free_mem)
+{
+ __regfree (&re_comp_buf);
+}
+#endif
+
+#endif /* _REGEX_RE_COMP */
+
+/* Internal entry point.
+ Compile the regular expression PATTERN, whose length is LENGTH.
+ SYNTAX indicate regular expression's syntax. */
+
+static reg_errcode_t
+re_compile_internal (regex_t *preg, const char * pattern, size_t length,
+ reg_syntax_t syntax)
+{
+ reg_errcode_t err = REG_NOERROR;
+ re_dfa_t *dfa;
+ re_string_t regexp;
+
+ /* Initialize the pattern buffer. */
+ preg->fastmap_accurate = 0;
+ preg->syntax = syntax;
+ preg->not_bol = preg->not_eol = 0;
+ preg->used = 0;
+ preg->re_nsub = 0;
+ preg->can_be_null = 0;
+ preg->regs_allocated = REGS_UNALLOCATED;
+
+ /* Initialize the dfa. */
+ dfa = preg->buffer;
+ if (__glibc_unlikely (preg->allocated < sizeof (re_dfa_t)))
+ {
+ /* If zero allocated, but buffer is non-null, try to realloc
+ enough space. This loses if buffer's address is bogus, but
+ that is the user's responsibility. If ->buffer is NULL this
+ is a simple allocation. */
+ dfa = re_realloc (preg->buffer, re_dfa_t, 1);
+ if (dfa == NULL)
+ return REG_ESPACE;
+ preg->allocated = sizeof (re_dfa_t);
+ preg->buffer = dfa;
+ }
+ preg->used = sizeof (re_dfa_t);
+
+ err = init_dfa (dfa, length);
+ if (__glibc_unlikely (err == REG_NOERROR && lock_init (dfa->lock) != 0))
+ err = REG_ESPACE;
+ if (__glibc_unlikely (err != REG_NOERROR))
+ {
+ free_dfa_content (dfa);
+ preg->buffer = NULL;
+ preg->allocated = 0;
+ return err;
+ }
+#ifdef DEBUG
+ /* Note: length+1 will not overflow since it is checked in init_dfa. */
+ dfa->re_str = re_malloc (char, length + 1);
+ strncpy (dfa->re_str, pattern, length + 1);
+#endif
+
+ err = re_string_construct (&regexp, pattern, length, preg->translate,
+ (syntax & RE_ICASE) != 0, dfa);
+ if (__glibc_unlikely (err != REG_NOERROR))
+ {
+ re_compile_internal_free_return:
+ free_workarea_compile (preg);
+ re_string_destruct (&regexp);
+ lock_fini (dfa->lock);
+ free_dfa_content (dfa);
+ preg->buffer = NULL;
+ preg->allocated = 0;
+ return err;
+ }
+
+ /* Parse the regular expression, and build a structure tree. */
+ preg->re_nsub = 0;
+ dfa->str_tree = parse (&regexp, preg, syntax, &err);
+ if (__glibc_unlikely (dfa->str_tree == NULL))
+ goto re_compile_internal_free_return;
+
+ /* Analyze the tree and create the nfa. */
+ err = analyze (preg);
+ if (__glibc_unlikely (err != REG_NOERROR))
+ goto re_compile_internal_free_return;
+
+ /* If possible, do searching in single byte encoding to speed things up. */
+ if (dfa->is_utf8 && !(syntax & RE_ICASE) && preg->translate == NULL)
+ optimize_utf8 (dfa);
+
+ /* Then create the initial state of the dfa. */
+ err = create_initial_state (dfa);
+
+ /* Release work areas. */
+ free_workarea_compile (preg);
+ re_string_destruct (&regexp);
+
+ if (__glibc_unlikely (err != REG_NOERROR))
+ {
+ lock_fini (dfa->lock);
+ free_dfa_content (dfa);
+ preg->buffer = NULL;
+ preg->allocated = 0;
+ }
+
+ return err;
+}
+
+/* Initialize DFA. We use the length of the regular expression PAT_LEN
+ as the initial length of some arrays. */
+
+static reg_errcode_t
+init_dfa (re_dfa_t *dfa, size_t pat_len)
+{
+ __re_size_t table_size;
+#ifndef _LIBC
+ const char *codeset_name;
+#endif
+ size_t max_i18n_object_size = MAX (sizeof (wchar_t), sizeof (wctype_t));
+ size_t max_object_size =
+ MAX (sizeof (struct re_state_table_entry),
+ MAX (sizeof (re_token_t),
+ MAX (sizeof (re_node_set),
+ MAX (sizeof (regmatch_t),
+ max_i18n_object_size))));
+
+ memset (dfa, '\0', sizeof (re_dfa_t));
+
+ /* Force allocation of str_tree_storage the first time. */
+ dfa->str_tree_storage_idx = BIN_TREE_STORAGE_SIZE;
+
+ /* Avoid overflows. The extra "/ 2" is for the table_size doubling
+ calculation below, and for similar doubling calculations
+ elsewhere. And it's <= rather than <, because some of the
+ doubling calculations add 1 afterwards. */
+ if (__glibc_unlikely (MIN (IDX_MAX, SIZE_MAX / max_object_size) / 2
+ <= pat_len))
+ return REG_ESPACE;
+
+ dfa->nodes_alloc = pat_len + 1;
+ dfa->nodes = re_malloc (re_token_t, dfa->nodes_alloc);
+
+ /* table_size = 2 ^ ceil(log pat_len) */
+ for (table_size = 1; ; table_size <<= 1)
+ if (table_size > pat_len)
+ break;
+
+ dfa->state_table = calloc (sizeof (struct re_state_table_entry), table_size);
+ dfa->state_hash_mask = table_size - 1;
+
+ dfa->mb_cur_max = MB_CUR_MAX;
+#ifdef _LIBC
+ if (dfa->mb_cur_max == 6
+ && strcmp (_NL_CURRENT (LC_CTYPE, _NL_CTYPE_CODESET_NAME), "UTF-8") == 0)
+ dfa->is_utf8 = 1;
+ dfa->map_notascii = (_NL_CURRENT_WORD (LC_CTYPE, _NL_CTYPE_MAP_TO_NONASCII)
+ != 0);
+#else
+ codeset_name = nl_langinfo (CODESET);
+ if ((codeset_name[0] == 'U' || codeset_name[0] == 'u')
+ && (codeset_name[1] == 'T' || codeset_name[1] == 't')
+ && (codeset_name[2] == 'F' || codeset_name[2] == 'f')
+ && strcmp (codeset_name + 3 + (codeset_name[3] == '-'), "8") == 0)
+ dfa->is_utf8 = 1;
+
+ /* We check exhaustively in the loop below if this charset is a
+ superset of ASCII. */
+ dfa->map_notascii = 0;
+#endif
+
+ if (dfa->mb_cur_max > 1)
+ {
+ if (dfa->is_utf8)
+ dfa->sb_char = (re_bitset_ptr_t) utf8_sb_map;
+ else
+ {
+ int i, j, ch;
+
+ dfa->sb_char = (re_bitset_ptr_t) calloc (sizeof (bitset_t), 1);
+ if (__glibc_unlikely (dfa->sb_char == NULL))
+ return REG_ESPACE;
+
+ /* Set the bits corresponding to single byte chars. */
+ for (i = 0, ch = 0; i < BITSET_WORDS; ++i)
+ for (j = 0; j < BITSET_WORD_BITS; ++j, ++ch)
+ {
+ wint_t wch = __btowc (ch);
+ if (wch != WEOF)
+ dfa->sb_char[i] |= (bitset_word_t) 1 << j;
+#ifndef _LIBC
+ if (isascii (ch) && wch != ch)
+ dfa->map_notascii = 1;
+#endif
+ }
+ }
+ }
+
+ if (__glibc_unlikely (dfa->nodes == NULL || dfa->state_table == NULL))
+ return REG_ESPACE;
+ return REG_NOERROR;
+}
+
+/* Initialize WORD_CHAR table, which indicate which character is
+ "word". In this case "word" means that it is the word construction
+ character used by some operators like "\<", "\>", etc. */
+
+static void
+init_word_char (re_dfa_t *dfa)
+{
+ int i = 0;
+ int j;
+ int ch = 0;
+ dfa->word_ops_used = 1;
+ if (__glibc_likely (dfa->map_notascii == 0))
+ {
+ bitset_word_t bits0 = 0x00000000;
+ bitset_word_t bits1 = 0x03ff0000;
+ bitset_word_t bits2 = 0x87fffffe;
+ bitset_word_t bits3 = 0x07fffffe;
+ if (BITSET_WORD_BITS == 64)
+ {
+ /* Pacify gcc -Woverflow on 32-bit platformns. */
+ dfa->word_char[0] = bits1 << 31 << 1 | bits0;
+ dfa->word_char[1] = bits3 << 31 << 1 | bits2;
+ i = 2;
+ }
+ else if (BITSET_WORD_BITS == 32)
+ {
+ dfa->word_char[0] = bits0;
+ dfa->word_char[1] = bits1;
+ dfa->word_char[2] = bits2;
+ dfa->word_char[3] = bits3;
+ i = 4;
+ }
+ else
+ goto general_case;
+ ch = 128;
+
+ if (__glibc_likely (dfa->is_utf8))
+ {
+ memset (&dfa->word_char[i], '\0', (SBC_MAX - ch) / 8);
+ return;
+ }
+ }
+
+ general_case:
+ for (; i < BITSET_WORDS; ++i)
+ for (j = 0; j < BITSET_WORD_BITS; ++j, ++ch)
+ if (isalnum (ch) || ch == '_')
+ dfa->word_char[i] |= (bitset_word_t) 1 << j;
+}
+
+/* Free the work area which are only used while compiling. */
+
+static void
+free_workarea_compile (regex_t *preg)
+{
+ re_dfa_t *dfa = preg->buffer;
+ bin_tree_storage_t *storage, *next;
+ for (storage = dfa->str_tree_storage; storage; storage = next)
+ {
+ next = storage->next;
+ re_free (storage);
+ }
+ dfa->str_tree_storage = NULL;
+ dfa->str_tree_storage_idx = BIN_TREE_STORAGE_SIZE;
+ dfa->str_tree = NULL;
+ re_free (dfa->org_indices);
+ dfa->org_indices = NULL;
+}
+
+/* Create initial states for all contexts. */
+
+static reg_errcode_t
+create_initial_state (re_dfa_t *dfa)
+{
+ Idx first, i;
+ reg_errcode_t err;
+ re_node_set init_nodes;
+
+ /* Initial states have the epsilon closure of the node which is
+ the first node of the regular expression. */
+ first = dfa->str_tree->first->node_idx;
+ dfa->init_node = first;
+ err = re_node_set_init_copy (&init_nodes, dfa->eclosures + first);
+ if (__glibc_unlikely (err != REG_NOERROR))
+ return err;
+
+ /* The back-references which are in initial states can epsilon transit,
+ since in this case all of the subexpressions can be null.
+ Then we add epsilon closures of the nodes which are the next nodes of
+ the back-references. */
+ if (dfa->nbackref > 0)
+ for (i = 0; i < init_nodes.nelem; ++i)
+ {
+ Idx node_idx = init_nodes.elems[i];
+ re_token_type_t type = dfa->nodes[node_idx].type;
+
+ Idx clexp_idx;
+ if (type != OP_BACK_REF)
+ continue;
+ for (clexp_idx = 0; clexp_idx < init_nodes.nelem; ++clexp_idx)
+ {
+ re_token_t *clexp_node;
+ clexp_node = dfa->nodes + init_nodes.elems[clexp_idx];
+ if (clexp_node->type == OP_CLOSE_SUBEXP
+ && clexp_node->opr.idx == dfa->nodes[node_idx].opr.idx)
+ break;
+ }
+ if (clexp_idx == init_nodes.nelem)
+ continue;
+
+ if (type == OP_BACK_REF)
+ {
+ Idx dest_idx = dfa->edests[node_idx].elems[0];
+ if (!re_node_set_contains (&init_nodes, dest_idx))
+ {
+ reg_errcode_t merge_err
+ = re_node_set_merge (&init_nodes, dfa->eclosures + dest_idx);
+ if (merge_err != REG_NOERROR)
+ return merge_err;
+ i = 0;
+ }
+ }
+ }
+
+ /* It must be the first time to invoke acquire_state. */
+ dfa->init_state = re_acquire_state_context (&err, dfa, &init_nodes, 0);
+ /* We don't check ERR here, since the initial state must not be NULL. */
+ if (__glibc_unlikely (dfa->init_state == NULL))
+ return err;
+ if (dfa->init_state->has_constraint)
+ {
+ dfa->init_state_word = re_acquire_state_context (&err, dfa, &init_nodes,
+ CONTEXT_WORD);
+ dfa->init_state_nl = re_acquire_state_context (&err, dfa, &init_nodes,
+ CONTEXT_NEWLINE);
+ dfa->init_state_begbuf = re_acquire_state_context (&err, dfa,
+ &init_nodes,
+ CONTEXT_NEWLINE
+ | CONTEXT_BEGBUF);
+ if (__glibc_unlikely (dfa->init_state_word == NULL
+ || dfa->init_state_nl == NULL
+ || dfa->init_state_begbuf == NULL))
+ return err;
+ }
+ else
+ dfa->init_state_word = dfa->init_state_nl
+ = dfa->init_state_begbuf = dfa->init_state;
+
+ re_node_set_free (&init_nodes);
+ return REG_NOERROR;
+}
+
+/* If it is possible to do searching in single byte encoding instead of UTF-8
+ to speed things up, set dfa->mb_cur_max to 1, clear is_utf8 and change
+ DFA nodes where needed. */
+
+static void
+optimize_utf8 (re_dfa_t *dfa)
+{
+ Idx node;
+ int i;
+ bool mb_chars = false;
+ bool has_period = false;
+
+ for (node = 0; node < dfa->nodes_len; ++node)
+ switch (dfa->nodes[node].type)
+ {
+ case CHARACTER:
+ if (dfa->nodes[node].opr.c >= ASCII_CHARS)
+ mb_chars = true;
+ break;
+ case ANCHOR:
+ switch (dfa->nodes[node].opr.ctx_type)
+ {
+ case LINE_FIRST:
+ case LINE_LAST:
+ case BUF_FIRST:
+ case BUF_LAST:
+ break;
+ default:
+ /* Word anchors etc. cannot be handled. It's okay to test
+ opr.ctx_type since constraints (for all DFA nodes) are
+ created by ORing one or more opr.ctx_type values. */
+ return;
+ }
+ break;
+ case OP_PERIOD:
+ has_period = true;
+ break;
+ case OP_BACK_REF:
+ case OP_ALT:
+ case END_OF_RE:
+ case OP_DUP_ASTERISK:
+ case OP_OPEN_SUBEXP:
+ case OP_CLOSE_SUBEXP:
+ break;
+ case COMPLEX_BRACKET:
+ return;
+ case SIMPLE_BRACKET:
+ /* Just double check. */
+ {
+ int rshift = (ASCII_CHARS % BITSET_WORD_BITS == 0
+ ? 0
+ : BITSET_WORD_BITS - ASCII_CHARS % BITSET_WORD_BITS);
+ for (i = ASCII_CHARS / BITSET_WORD_BITS; i < BITSET_WORDS; ++i)
+ {
+ if (dfa->nodes[node].opr.sbcset[i] >> rshift != 0)
+ return;
+ rshift = 0;
+ }
+ }
+ break;
+ default:
+ abort ();
+ }
+
+ if (mb_chars || has_period)
+ for (node = 0; node < dfa->nodes_len; ++node)
+ {
+ if (dfa->nodes[node].type == CHARACTER
+ && dfa->nodes[node].opr.c >= ASCII_CHARS)
+ dfa->nodes[node].mb_partial = 0;
+ else if (dfa->nodes[node].type == OP_PERIOD)
+ dfa->nodes[node].type = OP_UTF8_PERIOD;
+ }
+
+ /* The search can be in single byte locale. */
+ dfa->mb_cur_max = 1;
+ dfa->is_utf8 = 0;
+ dfa->has_mb_node = dfa->nbackref > 0 || has_period;
+}
+
+/* Analyze the structure tree, and calculate "first", "next", "edest",
+ "eclosure", and "inveclosure". */
+
+static reg_errcode_t
+analyze (regex_t *preg)
+{
+ re_dfa_t *dfa = preg->buffer;
+ reg_errcode_t ret;
+
+ /* Allocate arrays. */
+ dfa->nexts = re_malloc (Idx, dfa->nodes_alloc);
+ dfa->org_indices = re_malloc (Idx, dfa->nodes_alloc);
+ dfa->edests = re_malloc (re_node_set, dfa->nodes_alloc);
+ dfa->eclosures = re_malloc (re_node_set, dfa->nodes_alloc);
+ if (__glibc_unlikely (dfa->nexts == NULL || dfa->org_indices == NULL
+ || dfa->edests == NULL || dfa->eclosures == NULL))
+ return REG_ESPACE;
+
+ dfa->subexp_map = re_malloc (Idx, preg->re_nsub);
+ if (dfa->subexp_map != NULL)
+ {
+ Idx i;
+ for (i = 0; i < preg->re_nsub; i++)
+ dfa->subexp_map[i] = i;
+ preorder (dfa->str_tree, optimize_subexps, dfa);
+ for (i = 0; i < preg->re_nsub; i++)
+ if (dfa->subexp_map[i] != i)
+ break;
+ if (i == preg->re_nsub)
+ {
+ re_free (dfa->subexp_map);
+ dfa->subexp_map = NULL;
+ }
+ }
+
+ ret = postorder (dfa->str_tree, lower_subexps, preg);
+ if (__glibc_unlikely (ret != REG_NOERROR))
+ return ret;
+ ret = postorder (dfa->str_tree, calc_first, dfa);
+ if (__glibc_unlikely (ret != REG_NOERROR))
+ return ret;
+ preorder (dfa->str_tree, calc_next, dfa);
+ ret = preorder (dfa->str_tree, link_nfa_nodes, dfa);
+ if (__glibc_unlikely (ret != REG_NOERROR))
+ return ret;
+ ret = calc_eclosure (dfa);
+ if (__glibc_unlikely (ret != REG_NOERROR))
+ return ret;
+
+ /* We only need this during the prune_impossible_nodes pass in regexec.c;
+ skip it if p_i_n will not run, as calc_inveclosure can be quadratic. */
+ if ((!preg->no_sub && preg->re_nsub > 0 && dfa->has_plural_match)
+ || dfa->nbackref)
+ {
+ dfa->inveclosures = re_malloc (re_node_set, dfa->nodes_len);
+ if (__glibc_unlikely (dfa->inveclosures == NULL))
+ return REG_ESPACE;
+ ret = calc_inveclosure (dfa);
+ }
+
+ return ret;
+}
+
+/* Our parse trees are very unbalanced, so we cannot use a stack to
+ implement parse tree visits. Instead, we use parent pointers and
+ some hairy code in these two functions. */
+static reg_errcode_t
+postorder (bin_tree_t *root, reg_errcode_t (fn (void *, bin_tree_t *)),
+ void *extra)
+{
+ bin_tree_t *node, *prev;
+
+ for (node = root; ; )
+ {
+ /* Descend down the tree, preferably to the left (or to the right
+ if that's the only child). */
+ while (node->left || node->right)
+ if (node->left)
+ node = node->left;
+ else
+ node = node->right;
+
+ do
+ {
+ reg_errcode_t err = fn (extra, node);
+ if (__glibc_unlikely (err != REG_NOERROR))
+ return err;
+ if (node->parent == NULL)
+ return REG_NOERROR;
+ prev = node;
+ node = node->parent;
+ }
+ /* Go up while we have a node that is reached from the right. */
+ while (node->right == prev || node->right == NULL);
+ node = node->right;
+ }
+}
+
+static reg_errcode_t
+preorder (bin_tree_t *root, reg_errcode_t (fn (void *, bin_tree_t *)),
+ void *extra)
+{
+ bin_tree_t *node;
+
+ for (node = root; ; )
+ {
+ reg_errcode_t err = fn (extra, node);
+ if (__glibc_unlikely (err != REG_NOERROR))
+ return err;
+
+ /* Go to the left node, or up and to the right. */
+ if (node->left)
+ node = node->left;
+ else
+ {
+ bin_tree_t *prev = NULL;
+ while (node->right == prev || node->right == NULL)
+ {
+ prev = node;
+ node = node->parent;
+ if (!node)
+ return REG_NOERROR;
+ }
+ node = node->right;
+ }
+ }
+}
+
+/* Optimization pass: if a SUBEXP is entirely contained, strip it and tell
+ re_search_internal to map the inner one's opr.idx to this one's. Adjust
+ backreferences as well. Requires a preorder visit. */
+static reg_errcode_t
+optimize_subexps (void *extra, bin_tree_t *node)
+{
+ re_dfa_t *dfa = (re_dfa_t *) extra;
+
+ if (node->token.type == OP_BACK_REF && dfa->subexp_map)
+ {
+ int idx = node->token.opr.idx;
+ node->token.opr.idx = dfa->subexp_map[idx];
+ dfa->used_bkref_map |= 1 << node->token.opr.idx;
+ }
+
+ else if (node->token.type == SUBEXP
+ && node->left && node->left->token.type == SUBEXP)
+ {
+ Idx other_idx = node->left->token.opr.idx;
+
+ node->left = node->left->left;
+ if (node->left)
+ node->left->parent = node;
+
+ dfa->subexp_map[other_idx] = dfa->subexp_map[node->token.opr.idx];
+ if (other_idx < BITSET_WORD_BITS)
+ dfa->used_bkref_map &= ~((bitset_word_t) 1 << other_idx);
+ }
+
+ return REG_NOERROR;
+}
+
+/* Lowering pass: Turn each SUBEXP node into the appropriate concatenation
+ of OP_OPEN_SUBEXP, the body of the SUBEXP (if any) and OP_CLOSE_SUBEXP. */
+static reg_errcode_t
+lower_subexps (void *extra, bin_tree_t *node)
+{
+ regex_t *preg = (regex_t *) extra;
+ reg_errcode_t err = REG_NOERROR;
+
+ if (node->left && node->left->token.type == SUBEXP)
+ {
+ node->left = lower_subexp (&err, preg, node->left);
+ if (node->left)
+ node->left->parent = node;
+ }
+ if (node->right && node->right->token.type == SUBEXP)
+ {
+ node->right = lower_subexp (&err, preg, node->right);
+ if (node->right)
+ node->right->parent = node;
+ }
+
+ return err;
+}
+
+static bin_tree_t *
+lower_subexp (reg_errcode_t *err, regex_t *preg, bin_tree_t *node)
+{
+ re_dfa_t *dfa = preg->buffer;
+ bin_tree_t *body = node->left;
+ bin_tree_t *op, *cls, *tree1, *tree;
+
+ if (preg->no_sub
+ /* We do not optimize empty subexpressions, because otherwise we may
+ have bad CONCAT nodes with NULL children. This is obviously not
+ very common, so we do not lose much. An example that triggers
+ this case is the sed "script" /\(\)/x. */
+ && node->left != NULL
+ && (node->token.opr.idx >= BITSET_WORD_BITS
+ || !(dfa->used_bkref_map
+ & ((bitset_word_t) 1 << node->token.opr.idx))))
+ return node->left;
+
+ /* Convert the SUBEXP node to the concatenation of an
+ OP_OPEN_SUBEXP, the contents, and an OP_CLOSE_SUBEXP. */
+ op = create_tree (dfa, NULL, NULL, OP_OPEN_SUBEXP);
+ cls = create_tree (dfa, NULL, NULL, OP_CLOSE_SUBEXP);
+ tree1 = body ? create_tree (dfa, body, cls, CONCAT) : cls;
+ tree = create_tree (dfa, op, tree1, CONCAT);
+ if (__glibc_unlikely (tree == NULL || tree1 == NULL
+ || op == NULL || cls == NULL))
+ {
+ *err = REG_ESPACE;
+ return NULL;
+ }
+
+ op->token.opr.idx = cls->token.opr.idx = node->token.opr.idx;
+ op->token.opt_subexp = cls->token.opt_subexp = node->token.opt_subexp;
+ return tree;
+}
+
+/* Pass 1 in building the NFA: compute FIRST and create unlinked automaton
+ nodes. Requires a postorder visit. */
+static reg_errcode_t
+calc_first (void *extra, bin_tree_t *node)
+{
+ re_dfa_t *dfa = (re_dfa_t *) extra;
+ if (node->token.type == CONCAT)
+ {
+ node->first = node->left->first;
+ node->node_idx = node->left->node_idx;
+ }
+ else
+ {
+ node->first = node;
+ node->node_idx = re_dfa_add_node (dfa, node->token);
+ if (__glibc_unlikely (node->node_idx == -1))
+ return REG_ESPACE;
+ if (node->token.type == ANCHOR)
+ dfa->nodes[node->node_idx].constraint = node->token.opr.ctx_type;
+ }
+ return REG_NOERROR;
+}
+
+/* Pass 2: compute NEXT on the tree. Preorder visit. */
+static reg_errcode_t
+calc_next (void *extra, bin_tree_t *node)
+{
+ switch (node->token.type)
+ {
+ case OP_DUP_ASTERISK:
+ node->left->next = node;
+ break;
+ case CONCAT:
+ node->left->next = node->right->first;
+ node->right->next = node->next;
+ break;
+ default:
+ if (node->left)
+ node->left->next = node->next;
+ if (node->right)
+ node->right->next = node->next;
+ break;
+ }
+ return REG_NOERROR;
+}
+
+/* Pass 3: link all DFA nodes to their NEXT node (any order will do). */
+static reg_errcode_t
+link_nfa_nodes (void *extra, bin_tree_t *node)
+{
+ re_dfa_t *dfa = (re_dfa_t *) extra;
+ Idx idx = node->node_idx;
+ reg_errcode_t err = REG_NOERROR;
+
+ switch (node->token.type)
+ {
+ case CONCAT:
+ break;
+
+ case END_OF_RE:
+ DEBUG_ASSERT (node->next == NULL);
+ break;
+
+ case OP_DUP_ASTERISK:
+ case OP_ALT:
+ {
+ Idx left, right;
+ dfa->has_plural_match = 1;
+ if (node->left != NULL)
+ left = node->left->first->node_idx;
+ else
+ left = node->next->node_idx;
+ if (node->right != NULL)
+ right = node->right->first->node_idx;
+ else
+ right = node->next->node_idx;
+ DEBUG_ASSERT (left > -1);
+ DEBUG_ASSERT (right > -1);
+ err = re_node_set_init_2 (dfa->edests + idx, left, right);
+ }
+ break;
+
+ case ANCHOR:
+ case OP_OPEN_SUBEXP:
+ case OP_CLOSE_SUBEXP:
+ err = re_node_set_init_1 (dfa->edests + idx, node->next->node_idx);
+ break;
+
+ case OP_BACK_REF:
+ dfa->nexts[idx] = node->next->node_idx;
+ if (node->token.type == OP_BACK_REF)
+ err = re_node_set_init_1 (dfa->edests + idx, dfa->nexts[idx]);
+ break;
+
+ default:
+ DEBUG_ASSERT (!IS_EPSILON_NODE (node->token.type));
+ dfa->nexts[idx] = node->next->node_idx;
+ break;
+ }
+
+ return err;
+}
+
+/* Duplicate the epsilon closure of the node ROOT_NODE.
+ Note that duplicated nodes have constraint INIT_CONSTRAINT in addition
+ to their own constraint. */
+
+static reg_errcode_t
+duplicate_node_closure (re_dfa_t *dfa, Idx top_org_node, Idx top_clone_node,
+ Idx root_node, unsigned int init_constraint)
+{
+ Idx org_node, clone_node;
+ bool ok;
+ unsigned int constraint = init_constraint;
+ for (org_node = top_org_node, clone_node = top_clone_node;;)
+ {
+ Idx org_dest, clone_dest;
+ if (dfa->nodes[org_node].type == OP_BACK_REF)
+ {
+ /* If the back reference epsilon-transit, its destination must
+ also have the constraint. Then duplicate the epsilon closure
+ of the destination of the back reference, and store it in
+ edests of the back reference. */
+ org_dest = dfa->nexts[org_node];
+ re_node_set_empty (dfa->edests + clone_node);
+ clone_dest = duplicate_node (dfa, org_dest, constraint);
+ if (__glibc_unlikely (clone_dest == -1))
+ return REG_ESPACE;
+ dfa->nexts[clone_node] = dfa->nexts[org_node];
+ ok = re_node_set_insert (dfa->edests + clone_node, clone_dest);
+ if (__glibc_unlikely (! ok))
+ return REG_ESPACE;
+ }
+ else if (dfa->edests[org_node].nelem == 0)
+ {
+ /* In case of the node can't epsilon-transit, don't duplicate the
+ destination and store the original destination as the
+ destination of the node. */
+ dfa->nexts[clone_node] = dfa->nexts[org_node];
+ break;
+ }
+ else if (dfa->edests[org_node].nelem == 1)
+ {
+ /* In case of the node can epsilon-transit, and it has only one
+ destination. */
+ org_dest = dfa->edests[org_node].elems[0];
+ re_node_set_empty (dfa->edests + clone_node);
+ /* If the node is root_node itself, it means the epsilon closure
+ has a loop. Then tie it to the destination of the root_node. */
+ if (org_node == root_node && clone_node != org_node)
+ {
+ ok = re_node_set_insert (dfa->edests + clone_node, org_dest);
+ if (__glibc_unlikely (! ok))
+ return REG_ESPACE;
+ break;
+ }
+ /* In case the node has another constraint, append it. */
+ constraint |= dfa->nodes[org_node].constraint;
+ clone_dest = duplicate_node (dfa, org_dest, constraint);
+ if (__glibc_unlikely (clone_dest == -1))
+ return REG_ESPACE;
+ ok = re_node_set_insert (dfa->edests + clone_node, clone_dest);
+ if (__glibc_unlikely (! ok))
+ return REG_ESPACE;
+ }
+ else /* dfa->edests[org_node].nelem == 2 */
+ {
+ /* In case of the node can epsilon-transit, and it has two
+ destinations. In the bin_tree_t and DFA, that's '|' and '*'. */
+ org_dest = dfa->edests[org_node].elems[0];
+ re_node_set_empty (dfa->edests + clone_node);
+ /* Search for a duplicated node which satisfies the constraint. */
+ clone_dest = search_duplicated_node (dfa, org_dest, constraint);
+ if (clone_dest == -1)
+ {
+ /* There is no such duplicated node, create a new one. */
+ reg_errcode_t err;
+ clone_dest = duplicate_node (dfa, org_dest, constraint);
+ if (__glibc_unlikely (clone_dest == -1))
+ return REG_ESPACE;
+ ok = re_node_set_insert (dfa->edests + clone_node, clone_dest);
+ if (__glibc_unlikely (! ok))
+ return REG_ESPACE;
+ err = duplicate_node_closure (dfa, org_dest, clone_dest,
+ root_node, constraint);
+ if (__glibc_unlikely (err != REG_NOERROR))
+ return err;
+ }
+ else
+ {
+ /* There is a duplicated node which satisfies the constraint,
+ use it to avoid infinite loop. */
+ ok = re_node_set_insert (dfa->edests + clone_node, clone_dest);
+ if (__glibc_unlikely (! ok))
+ return REG_ESPACE;
+ }
+
+ org_dest = dfa->edests[org_node].elems[1];
+ clone_dest = duplicate_node (dfa, org_dest, constraint);
+ if (__glibc_unlikely (clone_dest == -1))
+ return REG_ESPACE;
+ ok = re_node_set_insert (dfa->edests + clone_node, clone_dest);
+ if (__glibc_unlikely (! ok))
+ return REG_ESPACE;
+ }
+ org_node = org_dest;
+ clone_node = clone_dest;
+ }
+ return REG_NOERROR;
+}
+
+/* Search for a node which is duplicated from the node ORG_NODE, and
+ satisfies the constraint CONSTRAINT. */
+
+static Idx
+search_duplicated_node (const re_dfa_t *dfa, Idx org_node,
+ unsigned int constraint)
+{
+ Idx idx;
+ for (idx = dfa->nodes_len - 1; dfa->nodes[idx].duplicated && idx > 0; --idx)
+ {
+ if (org_node == dfa->org_indices[idx]
+ && constraint == dfa->nodes[idx].constraint)
+ return idx; /* Found. */
+ }
+ return -1; /* Not found. */
+}
+
+/* Duplicate the node whose index is ORG_IDX and set the constraint CONSTRAINT.
+ Return the index of the new node, or -1 if insufficient storage is
+ available. */
+
+static Idx
+duplicate_node (re_dfa_t *dfa, Idx org_idx, unsigned int constraint)
+{
+ Idx dup_idx = re_dfa_add_node (dfa, dfa->nodes[org_idx]);
+ if (__glibc_likely (dup_idx != -1))
+ {
+ dfa->nodes[dup_idx].constraint = constraint;
+ dfa->nodes[dup_idx].constraint |= dfa->nodes[org_idx].constraint;
+ dfa->nodes[dup_idx].duplicated = 1;
+
+ /* Store the index of the original node. */
+ dfa->org_indices[dup_idx] = org_idx;
+ }
+ return dup_idx;
+}
+
+static reg_errcode_t
+calc_inveclosure (re_dfa_t *dfa)
+{
+ Idx src, idx;
+ bool ok;
+ for (idx = 0; idx < dfa->nodes_len; ++idx)
+ re_node_set_init_empty (dfa->inveclosures + idx);
+
+ for (src = 0; src < dfa->nodes_len; ++src)
+ {
+ Idx *elems = dfa->eclosures[src].elems;
+ for (idx = 0; idx < dfa->eclosures[src].nelem; ++idx)
+ {
+ ok = re_node_set_insert_last (dfa->inveclosures + elems[idx], src);
+ if (__glibc_unlikely (! ok))
+ return REG_ESPACE;
+ }
+ }
+
+ return REG_NOERROR;
+}
+
+/* Calculate "eclosure" for all the node in DFA. */
+
+static reg_errcode_t
+calc_eclosure (re_dfa_t *dfa)
+{
+ Idx node_idx;
+ bool incomplete;
+ DEBUG_ASSERT (dfa->nodes_len > 0);
+ incomplete = false;
+ /* For each nodes, calculate epsilon closure. */
+ for (node_idx = 0; ; ++node_idx)
+ {
+ reg_errcode_t err;
+ re_node_set eclosure_elem;
+ if (node_idx == dfa->nodes_len)
+ {
+ if (!incomplete)
+ break;
+ incomplete = false;
+ node_idx = 0;
+ }
+
+ DEBUG_ASSERT (dfa->eclosures[node_idx].nelem != -1);
+
+ /* If we have already calculated, skip it. */
+ if (dfa->eclosures[node_idx].nelem != 0)
+ continue;
+ /* Calculate epsilon closure of 'node_idx'. */
+ err = calc_eclosure_iter (&eclosure_elem, dfa, node_idx, true);
+ if (__glibc_unlikely (err != REG_NOERROR))
+ return err;
+
+ if (dfa->eclosures[node_idx].nelem == 0)
+ {
+ incomplete = true;
+ re_node_set_free (&eclosure_elem);
+ }
+ }
+ return REG_NOERROR;
+}
+
+/* Calculate epsilon closure of NODE. */
+
+static reg_errcode_t
+calc_eclosure_iter (re_node_set *new_set, re_dfa_t *dfa, Idx node, bool root)
+{
+ reg_errcode_t err;
+ Idx i;
+ re_node_set eclosure;
+ bool incomplete = false;
+ err = re_node_set_alloc (&eclosure, dfa->edests[node].nelem + 1);
+ if (__glibc_unlikely (err != REG_NOERROR))
+ return err;
+
+ /* An epsilon closure includes itself. */
+ eclosure.elems[eclosure.nelem++] = node;
+
+ /* This indicates that we are calculating this node now.
+ We reference this value to avoid infinite loop. */
+ dfa->eclosures[node].nelem = -1;
+
+ /* If the current node has constraints, duplicate all nodes
+ since they must inherit the constraints. */
+ if (dfa->nodes[node].constraint
+ && dfa->edests[node].nelem
+ && !dfa->nodes[dfa->edests[node].elems[0]].duplicated)
+ {
+ err = duplicate_node_closure (dfa, node, node, node,
+ dfa->nodes[node].constraint);
+ if (__glibc_unlikely (err != REG_NOERROR))
+ return err;
+ }
+
+ /* Expand each epsilon destination nodes. */
+ if (IS_EPSILON_NODE(dfa->nodes[node].type))
+ for (i = 0; i < dfa->edests[node].nelem; ++i)
+ {
+ re_node_set eclosure_elem;
+ Idx edest = dfa->edests[node].elems[i];
+ /* If calculating the epsilon closure of 'edest' is in progress,
+ return intermediate result. */
+ if (dfa->eclosures[edest].nelem == -1)
+ {
+ incomplete = true;
+ continue;
+ }
+ /* If we haven't calculated the epsilon closure of 'edest' yet,
+ calculate now. Otherwise use calculated epsilon closure. */
+ if (dfa->eclosures[edest].nelem == 0)
+ {
+ err = calc_eclosure_iter (&eclosure_elem, dfa, edest, false);
+ if (__glibc_unlikely (err != REG_NOERROR))
+ return err;
+ }
+ else
+ eclosure_elem = dfa->eclosures[edest];
+ /* Merge the epsilon closure of 'edest'. */
+ err = re_node_set_merge (&eclosure, &eclosure_elem);
+ if (__glibc_unlikely (err != REG_NOERROR))
+ return err;
+ /* If the epsilon closure of 'edest' is incomplete,
+ the epsilon closure of this node is also incomplete. */
+ if (dfa->eclosures[edest].nelem == 0)
+ {
+ incomplete = true;
+ re_node_set_free (&eclosure_elem);
+ }
+ }
+
+ if (incomplete && !root)
+ dfa->eclosures[node].nelem = 0;
+ else
+ dfa->eclosures[node] = eclosure;
+ *new_set = eclosure;
+ return REG_NOERROR;
+}
+
+/* Functions for token which are used in the parser. */
+
+/* Fetch a token from INPUT.
+ We must not use this function inside bracket expressions. */
+
+static void
+fetch_token (re_token_t *result, re_string_t *input, reg_syntax_t syntax)
+{
+ re_string_skip_bytes (input, peek_token (result, input, syntax));
+}
+
+/* Peek a token from INPUT, and return the length of the token.
+ We must not use this function inside bracket expressions. */
+
+static int
+peek_token (re_token_t *token, re_string_t *input, reg_syntax_t syntax)
+{
+ unsigned char c;
+
+ if (re_string_eoi (input))
+ {
+ token->type = END_OF_RE;
+ return 0;
+ }
+
+ c = re_string_peek_byte (input, 0);
+ token->opr.c = c;
+
+ token->word_char = 0;
+ token->mb_partial = 0;
+ if (input->mb_cur_max > 1
+ && !re_string_first_byte (input, re_string_cur_idx (input)))
+ {
+ token->type = CHARACTER;
+ token->mb_partial = 1;
+ return 1;
+ }
+ if (c == '\\')
+ {
+ unsigned char c2;
+ if (re_string_cur_idx (input) + 1 >= re_string_length (input))
+ {
+ token->type = BACK_SLASH;
+ return 1;
+ }
+
+ c2 = re_string_peek_byte_case (input, 1);
+ token->opr.c = c2;
+ token->type = CHARACTER;
+ if (input->mb_cur_max > 1)
+ {
+ wint_t wc = re_string_wchar_at (input,
+ re_string_cur_idx (input) + 1);
+ token->word_char = IS_WIDE_WORD_CHAR (wc) != 0;
+ }
+ else
+ token->word_char = IS_WORD_CHAR (c2) != 0;
+
+ switch (c2)
+ {
+ case '|':
+ if (!(syntax & RE_LIMITED_OPS) && !(syntax & RE_NO_BK_VBAR))
+ token->type = OP_ALT;
+ break;
+ case '1': case '2': case '3': case '4': case '5':
+ case '6': case '7': case '8': case '9':
+ if (!(syntax & RE_NO_BK_REFS))
+ {
+ token->type = OP_BACK_REF;
+ token->opr.idx = c2 - '1';
+ }
+ break;
+ case '<':
+ if (!(syntax & RE_NO_GNU_OPS))
+ {
+ token->type = ANCHOR;
+ token->opr.ctx_type = WORD_FIRST;
+ }
+ break;
+ case '>':
+ if (!(syntax & RE_NO_GNU_OPS))
+ {
+ token->type = ANCHOR;
+ token->opr.ctx_type = WORD_LAST;
+ }
+ break;
+ case 'b':
+ if (!(syntax & RE_NO_GNU_OPS))
+ {
+ token->type = ANCHOR;
+ token->opr.ctx_type = WORD_DELIM;
+ }
+ break;
+ case 'B':
+ if (!(syntax & RE_NO_GNU_OPS))
+ {
+ token->type = ANCHOR;
+ token->opr.ctx_type = NOT_WORD_DELIM;
+ }
+ break;
+ case 'w':
+ if (!(syntax & RE_NO_GNU_OPS))
+ token->type = OP_WORD;
+ break;
+ case 'W':
+ if (!(syntax & RE_NO_GNU_OPS))
+ token->type = OP_NOTWORD;
+ break;
+ case 's':
+ if (!(syntax & RE_NO_GNU_OPS))
+ token->type = OP_SPACE;
+ break;
+ case 'S':
+ if (!(syntax & RE_NO_GNU_OPS))
+ token->type = OP_NOTSPACE;
+ break;
+ case '`':
+ if (!(syntax & RE_NO_GNU_OPS))
+ {
+ token->type = ANCHOR;
+ token->opr.ctx_type = BUF_FIRST;
+ }
+ break;
+ case '\'':
+ if (!(syntax & RE_NO_GNU_OPS))
+ {
+ token->type = ANCHOR;
+ token->opr.ctx_type = BUF_LAST;
+ }
+ break;
+ case '(':
+ if (!(syntax & RE_NO_BK_PARENS))
+ token->type = OP_OPEN_SUBEXP;
+ break;
+ case ')':
+ if (!(syntax & RE_NO_BK_PARENS))
+ token->type = OP_CLOSE_SUBEXP;
+ break;
+ case '+':
+ if (!(syntax & RE_LIMITED_OPS) && (syntax & RE_BK_PLUS_QM))
+ token->type = OP_DUP_PLUS;
+ break;
+ case '?':
+ if (!(syntax & RE_LIMITED_OPS) && (syntax & RE_BK_PLUS_QM))
+ token->type = OP_DUP_QUESTION;
+ break;
+ case '{':
+ if ((syntax & RE_INTERVALS) && (!(syntax & RE_NO_BK_BRACES)))
+ token->type = OP_OPEN_DUP_NUM;
+ break;
+ case '}':
+ if ((syntax & RE_INTERVALS) && (!(syntax & RE_NO_BK_BRACES)))
+ token->type = OP_CLOSE_DUP_NUM;
+ break;
+ default:
+ break;
+ }
+ return 2;
+ }
+
+ token->type = CHARACTER;
+ if (input->mb_cur_max > 1)
+ {
+ wint_t wc = re_string_wchar_at (input, re_string_cur_idx (input));
+ token->word_char = IS_WIDE_WORD_CHAR (wc) != 0;
+ }
+ else
+ token->word_char = IS_WORD_CHAR (token->opr.c);
+
+ switch (c)
+ {
+ case '\n':
+ if (syntax & RE_NEWLINE_ALT)
+ token->type = OP_ALT;
+ break;
+ case '|':
+ if (!(syntax & RE_LIMITED_OPS) && (syntax & RE_NO_BK_VBAR))
+ token->type = OP_ALT;
+ break;
+ case '*':
+ token->type = OP_DUP_ASTERISK;
+ break;
+ case '+':
+ if (!(syntax & RE_LIMITED_OPS) && !(syntax & RE_BK_PLUS_QM))
+ token->type = OP_DUP_PLUS;
+ break;
+ case '?':
+ if (!(syntax & RE_LIMITED_OPS) && !(syntax & RE_BK_PLUS_QM))
+ token->type = OP_DUP_QUESTION;
+ break;
+ case '{':
+ if ((syntax & RE_INTERVALS) && (syntax & RE_NO_BK_BRACES))
+ token->type = OP_OPEN_DUP_NUM;
+ break;
+ case '}':
+ if ((syntax & RE_INTERVALS) && (syntax & RE_NO_BK_BRACES))
+ token->type = OP_CLOSE_DUP_NUM;
+ break;
+ case '(':
+ if (syntax & RE_NO_BK_PARENS)
+ token->type = OP_OPEN_SUBEXP;
+ break;
+ case ')':
+ if (syntax & RE_NO_BK_PARENS)
+ token->type = OP_CLOSE_SUBEXP;
+ break;
+ case '[':
+ token->type = OP_OPEN_BRACKET;
+ break;
+ case '.':
+ token->type = OP_PERIOD;
+ break;
+ case '^':
+ 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')
+ break;
+ }
+ token->type = ANCHOR;
+ token->opr.ctx_type = LINE_FIRST;
+ break;
+ case '$':
+ 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);
+ peek_token (&next, input, syntax);
+ re_string_skip_bytes (input, -1);
+ if (next.type != OP_ALT && next.type != OP_CLOSE_SUBEXP)
+ break;
+ }
+ token->type = ANCHOR;
+ token->opr.ctx_type = LINE_LAST;
+ break;
+ default:
+ break;
+ }
+ return 1;
+}
+
+/* Peek a token from INPUT, and return the length of the token.
+ We must not use this function out of bracket expressions. */
+
+static int
+peek_token_bracket (re_token_t *token, re_string_t *input, reg_syntax_t syntax)
+{
+ unsigned char c;
+ if (re_string_eoi (input))
+ {
+ token->type = END_OF_RE;
+ return 0;
+ }
+ c = re_string_peek_byte (input, 0);
+ token->opr.c = c;
+
+ if (input->mb_cur_max > 1
+ && !re_string_first_byte (input, re_string_cur_idx (input)))
+ {
+ token->type = CHARACTER;
+ return 1;
+ }
+
+ if (c == '\\' && (syntax & RE_BACKSLASH_ESCAPE_IN_LISTS)
+ && re_string_cur_idx (input) + 1 < re_string_length (input))
+ {
+ /* In this case, '\' escape a character. */
+ unsigned char c2;
+ re_string_skip_bytes (input, 1);
+ c2 = re_string_peek_byte (input, 0);
+ token->opr.c = c2;
+ token->type = CHARACTER;
+ return 1;
+ }
+ if (c == '[') /* '[' is a special char in a bracket exps. */
+ {
+ unsigned char c2;
+ int token_len;
+ if (re_string_cur_idx (input) + 1 < re_string_length (input))
+ c2 = re_string_peek_byte (input, 1);
+ else
+ c2 = 0;
+ token->opr.c = c2;
+ token_len = 2;
+ switch (c2)
+ {
+ case '.':
+ token->type = OP_OPEN_COLL_ELEM;
+ break;
+
+ case '=':
+ token->type = OP_OPEN_EQUIV_CLASS;
+ break;
+
+ case ':':
+ if (syntax & RE_CHAR_CLASSES)
+ {
+ token->type = OP_OPEN_CHAR_CLASS;
+ break;
+ }
+ FALLTHROUGH;
+ default:
+ token->type = CHARACTER;
+ token->opr.c = c;
+ token_len = 1;
+ break;
+ }
+ return token_len;
+ }
+ switch (c)
+ {
+ case ']':
+ token->type = OP_CLOSE_BRACKET;
+ break;
+ case '^':
+ token->type = OP_NON_MATCH_LIST;
+ break;
+ case '-':
+ /* In V7 Unix grep and Unix awk and mawk, [...---...]
+ (3 adjacent minus signs) stands for a single minus sign.
+ Support that without breaking anything else. */
+ if (! (re_string_cur_idx (input) + 2 < re_string_length (input)
+ && re_string_peek_byte (input, 1) == '-'
+ && re_string_peek_byte (input, 2) == '-'))
+ {
+ token->type = OP_CHARSET_RANGE;
+ break;
+ }
+ re_string_skip_bytes (input, 2);
+ FALLTHROUGH;
+ default:
+ token->type = CHARACTER;
+ }
+ return 1;
+}
+
+/* Functions for parser. */
+
+/* Entry point of the parser.
+ Parse the regular expression REGEXP and return the structure tree.
+ If an error occurs, ERR is set by error code, and return NULL.
+ This function build the following tree, from regular expression <reg_exp>:
+ CAT
+ / \
+ / \
+ <reg_exp> EOR
+
+ CAT means concatenation.
+ EOR means end of regular expression. */
+
+static bin_tree_t *
+parse (re_string_t *regexp, regex_t *preg, reg_syntax_t syntax,
+ reg_errcode_t *err)
+{
+ re_dfa_t *dfa = preg->buffer;
+ bin_tree_t *tree, *eor, *root;
+ re_token_t current_token;
+ dfa->syntax = syntax;
+ fetch_token (&current_token, regexp, syntax | RE_CARET_ANCHORS_HERE);
+ tree = parse_reg_exp (regexp, preg, &current_token, syntax, 0, err);
+ if (__glibc_unlikely (*err != REG_NOERROR && tree == NULL))
+ return NULL;
+ eor = create_tree (dfa, NULL, NULL, END_OF_RE);
+ if (tree != NULL)
+ root = create_tree (dfa, tree, eor, CONCAT);
+ else
+ root = eor;
+ if (__glibc_unlikely (eor == NULL || root == NULL))
+ {
+ *err = REG_ESPACE;
+ return NULL;
+ }
+ return root;
+}
+
+/* This function build the following tree, from regular expression
+ <branch1>|<branch2>:
+ ALT
+ / \
+ / \
+ <branch1> <branch2>
+
+ ALT means alternative, which represents the operator '|'. */
+
+static bin_tree_t *
+parse_reg_exp (re_string_t *regexp, regex_t *preg, re_token_t *token,
+ reg_syntax_t syntax, Idx nest, reg_errcode_t *err)
+{
+ re_dfa_t *dfa = preg->buffer;
+ bin_tree_t *tree, *branch = NULL;
+ bitset_word_t initial_bkref_map = dfa->completed_bkref_map;
+ tree = parse_branch (regexp, preg, token, syntax, nest, err);
+ if (__glibc_unlikely (*err != REG_NOERROR && tree == NULL))
+ return NULL;
+
+ while (token->type == OP_ALT)
+ {
+ fetch_token (token, regexp, syntax | RE_CARET_ANCHORS_HERE);
+ if (token->type != OP_ALT && token->type != END_OF_RE
+ && (nest == 0 || token->type != OP_CLOSE_SUBEXP))
+ {
+ bitset_word_t accumulated_bkref_map = dfa->completed_bkref_map;
+ dfa->completed_bkref_map = initial_bkref_map;
+ branch = parse_branch (regexp, preg, token, syntax, nest, err);
+ if (__glibc_unlikely (*err != REG_NOERROR && branch == NULL))
+ {
+ if (tree != NULL)
+ postorder (tree, free_tree, NULL);
+ return NULL;
+ }
+ dfa->completed_bkref_map |= accumulated_bkref_map;
+ }
+ else
+ branch = NULL;
+ tree = create_tree (dfa, tree, branch, OP_ALT);
+ if (__glibc_unlikely (tree == NULL))
+ {
+ *err = REG_ESPACE;
+ return NULL;
+ }
+ }
+ return tree;
+}
+
+/* This function build the following tree, from regular expression
+ <exp1><exp2>:
+ CAT
+ / \
+ / \
+ <exp1> <exp2>
+
+ CAT means concatenation. */
+
+static bin_tree_t *
+parse_branch (re_string_t *regexp, regex_t *preg, re_token_t *token,
+ reg_syntax_t syntax, Idx nest, reg_errcode_t *err)
+{
+ bin_tree_t *tree, *expr;
+ re_dfa_t *dfa = preg->buffer;
+ tree = parse_expression (regexp, preg, token, syntax, nest, err);
+ if (__glibc_unlikely (*err != REG_NOERROR && tree == NULL))
+ return NULL;
+
+ while (token->type != OP_ALT && token->type != END_OF_RE
+ && (nest == 0 || token->type != OP_CLOSE_SUBEXP))
+ {
+ expr = parse_expression (regexp, preg, token, syntax, nest, err);
+ if (__glibc_unlikely (*err != REG_NOERROR && expr == NULL))
+ {
+ if (tree != NULL)
+ postorder (tree, free_tree, NULL);
+ return NULL;
+ }
+ if (tree != NULL && expr != NULL)
+ {
+ bin_tree_t *newtree = create_tree (dfa, tree, expr, CONCAT);
+ if (newtree == NULL)
+ {
+ postorder (expr, free_tree, NULL);
+ postorder (tree, free_tree, NULL);
+ *err = REG_ESPACE;
+ return NULL;
+ }
+ tree = newtree;
+ }
+ else if (tree == NULL)
+ tree = expr;
+ /* Otherwise expr == NULL, we don't need to create new tree. */
+ }
+ return tree;
+}
+
+/* This function build the following tree, from regular expression a*:
+ *
+ |
+ a
+*/
+
+static bin_tree_t *
+parse_expression (re_string_t *regexp, regex_t *preg, re_token_t *token,
+ reg_syntax_t syntax, Idx nest, reg_errcode_t *err)
+{
+ re_dfa_t *dfa = preg->buffer;
+ bin_tree_t *tree;
+ switch (token->type)
+ {
+ case CHARACTER:
+ tree = create_token_tree (dfa, NULL, NULL, token);
+ if (__glibc_unlikely (tree == NULL))
+ {
+ *err = REG_ESPACE;
+ return NULL;
+ }
+ if (dfa->mb_cur_max > 1)
+ {
+ while (!re_string_eoi (regexp)
+ && !re_string_first_byte (regexp, re_string_cur_idx (regexp)))
+ {
+ bin_tree_t *mbc_remain;
+ fetch_token (token, regexp, syntax);
+ mbc_remain = create_token_tree (dfa, NULL, NULL, token);
+ tree = create_tree (dfa, tree, mbc_remain, CONCAT);
+ if (__glibc_unlikely (mbc_remain == NULL || tree == NULL))
+ {
+ *err = REG_ESPACE;
+ return NULL;
+ }
+ }
+ }
+ break;
+
+ case OP_OPEN_SUBEXP:
+ tree = parse_sub_exp (regexp, preg, token, syntax, nest + 1, err);
+ if (__glibc_unlikely (*err != REG_NOERROR && tree == NULL))
+ return NULL;
+ break;
+
+ case OP_OPEN_BRACKET:
+ tree = parse_bracket_exp (regexp, dfa, token, syntax, err);
+ if (__glibc_unlikely (*err != REG_NOERROR && tree == NULL))
+ return NULL;
+ break;
+
+ case OP_BACK_REF:
+ if (!__glibc_likely (dfa->completed_bkref_map & (1 << token->opr.idx)))
+ {
+ *err = REG_ESUBREG;
+ return NULL;
+ }
+ dfa->used_bkref_map |= 1 << token->opr.idx;
+ tree = create_token_tree (dfa, NULL, NULL, token);
+ if (__glibc_unlikely (tree == NULL))
+ {
+ *err = REG_ESPACE;
+ return NULL;
+ }
+ ++dfa->nbackref;
+ dfa->has_mb_node = 1;
+ break;
+
+ case OP_OPEN_DUP_NUM:
+ if (syntax & RE_CONTEXT_INVALID_DUP)
+ {
+ *err = REG_BADRPT;
+ return NULL;
+ }
+ FALLTHROUGH;
+ case OP_DUP_ASTERISK:
+ case OP_DUP_PLUS:
+ case OP_DUP_QUESTION:
+ if (syntax & RE_CONTEXT_INVALID_OPS)
+ {
+ *err = REG_BADRPT;
+ return NULL;
+ }
+ else if (syntax & RE_CONTEXT_INDEP_OPS)
+ {
+ fetch_token (token, regexp, syntax);
+ return parse_expression (regexp, preg, token, syntax, nest, err);
+ }
+ FALLTHROUGH;
+ case OP_CLOSE_SUBEXP:
+ if ((token->type == OP_CLOSE_SUBEXP)
+ && !(syntax & RE_UNMATCHED_RIGHT_PAREN_ORD))
+ {
+ *err = REG_ERPAREN;
+ return NULL;
+ }
+ FALLTHROUGH;
+ case OP_CLOSE_DUP_NUM:
+ /* We treat it as a normal character. */
+
+ /* Then we can these characters as normal characters. */
+ token->type = CHARACTER;
+ /* mb_partial and word_char bits should be initialized already
+ by peek_token. */
+ tree = create_token_tree (dfa, NULL, NULL, token);
+ if (__glibc_unlikely (tree == NULL))
+ {
+ *err = REG_ESPACE;
+ return NULL;
+ }
+ break;
+
+ case ANCHOR:
+ if ((token->opr.ctx_type
+ & (WORD_DELIM | NOT_WORD_DELIM | WORD_FIRST | WORD_LAST))
+ && dfa->word_ops_used == 0)
+ init_word_char (dfa);
+ if (token->opr.ctx_type == WORD_DELIM
+ || token->opr.ctx_type == NOT_WORD_DELIM)
+ {
+ bin_tree_t *tree_first, *tree_last;
+ if (token->opr.ctx_type == WORD_DELIM)
+ {
+ token->opr.ctx_type = WORD_FIRST;
+ tree_first = create_token_tree (dfa, NULL, NULL, token);
+ token->opr.ctx_type = WORD_LAST;
+ }
+ else
+ {
+ token->opr.ctx_type = INSIDE_WORD;
+ tree_first = create_token_tree (dfa, NULL, NULL, token);
+ token->opr.ctx_type = INSIDE_NOTWORD;
+ }
+ tree_last = create_token_tree (dfa, NULL, NULL, token);
+ tree = create_tree (dfa, tree_first, tree_last, OP_ALT);
+ if (__glibc_unlikely (tree_first == NULL || tree_last == NULL
+ || tree == NULL))
+ {
+ *err = REG_ESPACE;
+ return NULL;
+ }
+ }
+ else
+ {
+ tree = create_token_tree (dfa, NULL, NULL, token);
+ if (__glibc_unlikely (tree == NULL))
+ {
+ *err = REG_ESPACE;
+ return NULL;
+ }
+ }
+ /* We must return here, since ANCHORs can't be followed
+ by repetition operators.
+ eg. RE"^*" is invalid or "<ANCHOR(^)><CHAR(*)>",
+ it must not be "<ANCHOR(^)><REPEAT(*)>". */
+ fetch_token (token, regexp, syntax);
+ return tree;
+
+ case OP_PERIOD:
+ tree = create_token_tree (dfa, NULL, NULL, token);
+ if (__glibc_unlikely (tree == NULL))
+ {
+ *err = REG_ESPACE;
+ return NULL;
+ }
+ if (dfa->mb_cur_max > 1)
+ dfa->has_mb_node = 1;
+ break;
+
+ case OP_WORD:
+ case OP_NOTWORD:
+ tree = build_charclass_op (dfa, regexp->trans,
+ "alnum",
+ "_",
+ token->type == OP_NOTWORD, err);
+ if (__glibc_unlikely (*err != REG_NOERROR && tree == NULL))
+ return NULL;
+ break;
+
+ case OP_SPACE:
+ case OP_NOTSPACE:
+ tree = build_charclass_op (dfa, regexp->trans,
+ "space",
+ "",
+ token->type == OP_NOTSPACE, err);
+ if (__glibc_unlikely (*err != REG_NOERROR && tree == NULL))
+ return NULL;
+ break;
+
+ case OP_ALT:
+ case END_OF_RE:
+ return NULL;
+
+ case BACK_SLASH:
+ *err = REG_EESCAPE;
+ return NULL;
+
+ default:
+ /* Must not happen? */
+ DEBUG_ASSERT (false);
+ return NULL;
+ }
+ fetch_token (token, regexp, syntax);
+
+ while (token->type == OP_DUP_ASTERISK || token->type == OP_DUP_PLUS
+ || token->type == OP_DUP_QUESTION || token->type == OP_OPEN_DUP_NUM)
+ {
+ bin_tree_t *dup_tree = parse_dup_op (tree, regexp, dfa, token,
+ syntax, err);
+ if (__glibc_unlikely (*err != REG_NOERROR && dup_tree == NULL))
+ {
+ if (tree != NULL)
+ postorder (tree, free_tree, NULL);
+ return NULL;
+ }
+ tree = dup_tree;
+ /* In BRE consecutive duplications are not allowed. */
+ if ((syntax & RE_CONTEXT_INVALID_DUP)
+ && (token->type == OP_DUP_ASTERISK
+ || token->type == OP_OPEN_DUP_NUM))
+ {
+ if (tree != NULL)
+ postorder (tree, free_tree, NULL);
+ *err = REG_BADRPT;
+ return NULL;
+ }
+ }
+
+ return tree;
+}
+
+/* This function build the following tree, from regular expression
+ (<reg_exp>):
+ SUBEXP
+ |
+ <reg_exp>
+*/
+
+static bin_tree_t *
+parse_sub_exp (re_string_t *regexp, regex_t *preg, re_token_t *token,
+ reg_syntax_t syntax, Idx nest, reg_errcode_t *err)
+{
+ re_dfa_t *dfa = preg->buffer;
+ bin_tree_t *tree;
+ size_t cur_nsub;
+ cur_nsub = preg->re_nsub++;
+
+ fetch_token (token, regexp, syntax | RE_CARET_ANCHORS_HERE);
+
+ /* The subexpression may be a null string. */
+ if (token->type == OP_CLOSE_SUBEXP)
+ tree = NULL;
+ else
+ {
+ tree = parse_reg_exp (regexp, preg, token, syntax, nest, err);
+ if (__glibc_unlikely (*err == REG_NOERROR
+ && token->type != OP_CLOSE_SUBEXP))
+ {
+ if (tree != NULL)
+ postorder (tree, free_tree, NULL);
+ *err = REG_EPAREN;
+ }
+ if (__glibc_unlikely (*err != REG_NOERROR))
+ return NULL;
+ }
+
+ if (cur_nsub <= '9' - '1')
+ dfa->completed_bkref_map |= 1 << cur_nsub;
+
+ tree = create_tree (dfa, tree, NULL, SUBEXP);
+ if (__glibc_unlikely (tree == NULL))
+ {
+ *err = REG_ESPACE;
+ return NULL;
+ }
+ tree->token.opr.idx = cur_nsub;
+ return tree;
+}
+
+/* This function parse repetition operators like "*", "+", "{1,3}" etc. */
+
+static bin_tree_t *
+parse_dup_op (bin_tree_t *elem, re_string_t *regexp, re_dfa_t *dfa,
+ re_token_t *token, reg_syntax_t syntax, reg_errcode_t *err)
+{
+ bin_tree_t *tree = NULL, *old_tree = NULL;
+ Idx i, start, end, start_idx = re_string_cur_idx (regexp);
+ re_token_t start_token = *token;
+
+ if (token->type == OP_OPEN_DUP_NUM)
+ {
+ end = 0;
+ start = fetch_number (regexp, token, syntax);
+ if (start == -1)
+ {
+ if (token->type == CHARACTER && token->opr.c == ',')
+ start = 0; /* We treat "{,m}" as "{0,m}". */
+ else
+ {
+ *err = REG_BADBR; /* <re>{} is invalid. */
+ return NULL;
+ }
+ }
+ if (__glibc_likely (start != -2))
+ {
+ /* We treat "{n}" as "{n,n}". */
+ end = ((token->type == OP_CLOSE_DUP_NUM) ? start
+ : ((token->type == CHARACTER && token->opr.c == ',')
+ ? fetch_number (regexp, token, syntax) : -2));
+ }
+ if (__glibc_unlikely (start == -2 || end == -2))
+ {
+ /* Invalid sequence. */
+ if (__glibc_unlikely (!(syntax & RE_INVALID_INTERVAL_ORD)))
+ {
+ if (token->type == END_OF_RE)
+ *err = REG_EBRACE;
+ else
+ *err = REG_BADBR;
+
+ return NULL;
+ }
+
+ /* If the syntax bit is set, rollback. */
+ re_string_set_index (regexp, start_idx);
+ *token = start_token;
+ token->type = CHARACTER;
+ /* mb_partial and word_char bits should be already initialized by
+ peek_token. */
+ return elem;
+ }
+
+ if (__glibc_unlikely ((end != -1 && start > end)
+ || token->type != OP_CLOSE_DUP_NUM))
+ {
+ /* First number greater than second. */
+ *err = REG_BADBR;
+ return NULL;
+ }
+
+ if (__glibc_unlikely (RE_DUP_MAX < (end == -1 ? start : end)))
+ {
+ *err = REG_ESIZE;
+ return NULL;
+ }
+ }
+ else
+ {
+ start = (token->type == OP_DUP_PLUS) ? 1 : 0;
+ end = (token->type == OP_DUP_QUESTION) ? 1 : -1;
+ }
+
+ fetch_token (token, regexp, syntax);
+
+ if (__glibc_unlikely (elem == NULL))
+ return NULL;
+ if (__glibc_unlikely (start == 0 && end == 0))
+ {
+ postorder (elem, free_tree, NULL);
+ return NULL;
+ }
+
+ /* Extract "<re>{n,m}" to "<re><re>...<re><re>{0,<m-n>}". */
+ if (__glibc_unlikely (start > 0))
+ {
+ tree = elem;
+ for (i = 2; i <= start; ++i)
+ {
+ elem = duplicate_tree (elem, dfa);
+ tree = create_tree (dfa, tree, elem, CONCAT);
+ if (__glibc_unlikely (elem == NULL || tree == NULL))
+ goto parse_dup_op_espace;
+ }
+
+ if (start == end)
+ return tree;
+
+ /* Duplicate ELEM before it is marked optional. */
+ elem = duplicate_tree (elem, dfa);
+ if (__glibc_unlikely (elem == NULL))
+ goto parse_dup_op_espace;
+ old_tree = tree;
+ }
+ else
+ old_tree = NULL;
+
+ if (elem->token.type == SUBEXP)
+ {
+ uintptr_t subidx = elem->token.opr.idx;
+ postorder (elem, mark_opt_subexp, (void *) subidx);
+ }
+
+ tree = create_tree (dfa, elem, NULL,
+ (end == -1 ? OP_DUP_ASTERISK : OP_ALT));
+ if (__glibc_unlikely (tree == NULL))
+ goto parse_dup_op_espace;
+
+ /* This loop is actually executed only when end != -1,
+ to rewrite <re>{0,n} as (<re>(<re>...<re>?)?)?... We have
+ already created the start+1-th copy. */
+ if (TYPE_SIGNED (Idx) || end != -1)
+ for (i = start + 2; i <= end; ++i)
+ {
+ elem = duplicate_tree (elem, dfa);
+ tree = create_tree (dfa, tree, elem, CONCAT);
+ if (__glibc_unlikely (elem == NULL || tree == NULL))
+ goto parse_dup_op_espace;
+
+ tree = create_tree (dfa, tree, NULL, OP_ALT);
+ if (__glibc_unlikely (tree == NULL))
+ goto parse_dup_op_espace;
+ }
+
+ if (old_tree)
+ tree = create_tree (dfa, old_tree, tree, CONCAT);
+
+ return tree;
+
+ parse_dup_op_espace:
+ *err = REG_ESPACE;
+ return NULL;
+}
+
+/* Size of the names for collating symbol/equivalence_class/character_class.
+ I'm not sure, but maybe enough. */
+#define BRACKET_NAME_BUF_SIZE 32
+
+#ifndef _LIBC
+
+/* Convert the byte B to the corresponding wide character. In a
+ unibyte locale, treat B as itself. In a multibyte locale, return
+ WEOF if B is an encoding error. */
+static wint_t
+parse_byte (unsigned char b, re_dfa_t const *dfa)
+{
+ return dfa->mb_cur_max > 1 ? __btowc (b) : b;
+}
+
+/* Local function for parse_bracket_exp used in _LIBC environment.
+ Build the range expression which starts from START_ELEM, and ends
+ at END_ELEM. The result are written to MBCSET and SBCSET.
+ RANGE_ALLOC is the allocated size of mbcset->range_starts, and
+ mbcset->range_ends, is a pointer argument since we may
+ update it. */
+
+static reg_errcode_t
+build_range_exp (bitset_t sbcset, re_charset_t *mbcset, Idx *range_alloc,
+ bracket_elem_t *start_elem, bracket_elem_t *end_elem,
+ re_dfa_t *dfa, reg_syntax_t syntax, uint_fast32_t nrules,
+ const unsigned char *collseqmb, const char *collseqwc,
+ int_fast32_t table_size, const void *symb_table,
+ const unsigned char *extra)
+{
+ /* Equivalence Classes and Character Classes can't be a range start/end. */
+ if (__glibc_unlikely (start_elem->type == EQUIV_CLASS
+ || start_elem->type == CHAR_CLASS
+ || end_elem->type == EQUIV_CLASS
+ || end_elem->type == CHAR_CLASS))
+ return REG_ERANGE;
+
+ /* We can handle no multi character collating elements without libc
+ support. */
+ if (__glibc_unlikely ((start_elem->type == COLL_SYM
+ && strlen ((char *) start_elem->opr.name) > 1)
+ || (end_elem->type == COLL_SYM
+ && strlen ((char *) end_elem->opr.name) > 1)))
+ return REG_ECOLLATE;
+
+ unsigned int
+ start_ch = ((start_elem->type == SB_CHAR) ? start_elem->opr.ch
+ : ((start_elem->type == COLL_SYM) ? start_elem->opr.name[0]
+ : 0)),
+ end_ch = ((end_elem->type == SB_CHAR) ? end_elem->opr.ch
+ : ((end_elem->type == COLL_SYM) ? end_elem->opr.name[0]
+ : 0));
+ wint_t
+ start_wc = ((start_elem->type == SB_CHAR || start_elem->type == COLL_SYM)
+ ? parse_byte (start_ch, dfa) : start_elem->opr.wch),
+ end_wc = ((end_elem->type == SB_CHAR || end_elem->type == COLL_SYM)
+ ? parse_byte (end_ch, dfa) : end_elem->opr.wch);
+
+ if (start_wc == WEOF || end_wc == WEOF)
+ return REG_ECOLLATE;
+ else if (__glibc_unlikely ((syntax & RE_NO_EMPTY_RANGES)
+ && start_wc > end_wc))
+ return REG_ERANGE;
+
+ /* Got valid collation sequence values, add them as a new entry.
+ However, for !_LIBC we have no collation elements: if the
+ character set is single byte, the single byte character set
+ that we build below suffices. parse_bracket_exp passes
+ no MBCSET if dfa->mb_cur_max == 1. */
+ if (dfa->mb_cur_max > 1)
+ {
+ /* Check the space of the arrays. */
+ if (__glibc_unlikely (*range_alloc == mbcset->nranges))
+ {
+ /* There is not enough space, need realloc. */
+ wchar_t *new_array_start, *new_array_end;
+ Idx new_nranges;
+
+ /* +1 in case of mbcset->nranges is 0. */
+ new_nranges = 2 * mbcset->nranges + 1;
+ /* Use realloc since mbcset->range_starts and mbcset->range_ends
+ are NULL if *range_alloc == 0. */
+ new_array_start = re_realloc (mbcset->range_starts, wchar_t,
+ new_nranges);
+ new_array_end = re_realloc (mbcset->range_ends, wchar_t,
+ new_nranges);
+
+ if (__glibc_unlikely (new_array_start == NULL
+ || new_array_end == NULL))
+ {
+ re_free (new_array_start);
+ re_free (new_array_end);
+ return REG_ESPACE;
+ }
+
+ mbcset->range_starts = new_array_start;
+ mbcset->range_ends = new_array_end;
+ *range_alloc = new_nranges;
+ }
+
+ mbcset->range_starts[mbcset->nranges] = start_wc;
+ mbcset->range_ends[mbcset->nranges++] = end_wc;
+ }
+
+ /* Build the table for single byte characters. */
+ for (wchar_t wc = 0; wc < SBC_MAX; ++wc)
+ {
+ if (start_wc <= wc && wc <= end_wc)
+ bitset_set (sbcset, wc);
+ }
+
+ return REG_NOERROR;
+}
+#endif /* not _LIBC */
+
+#ifndef _LIBC
+/* Helper function for parse_bracket_exp only used in case of NOT _LIBC.
+ Build the collating element which is represented by NAME.
+ The result are written to MBCSET and SBCSET.
+ COLL_SYM_ALLOC is the allocated size of mbcset->coll_sym, is a
+ pointer argument since we may update it. */
+
+static reg_errcode_t
+build_collating_symbol (bitset_t sbcset, re_charset_t *mbcset,
+ Idx *coll_sym_alloc, const unsigned char *name,
+ uint_fast32_t nrules, int_fast32_t table_size,
+ const void *symb_table, const unsigned char *extra)
+{
+ size_t name_len = strlen ((const char *) name);
+ if (__glibc_unlikely (name_len != 1))
+ return REG_ECOLLATE;
+ else
+ {
+ bitset_set (sbcset, name[0]);
+ return REG_NOERROR;
+ }
+}
+#endif /* not _LIBC */
+
+#ifdef _LIBC
+/* Local function for parse_bracket_exp used in _LIBC environment.
+ Seek the collating symbol entry corresponding to NAME.
+ Return the index of the symbol in the SYMB_TABLE,
+ or -1 if not found. */
+
+static __always_inline int32_t
+seek_collating_symbol_entry (const unsigned char *name, size_t name_len,
+ const int32_t *symb_table,
+ int_fast32_t table_size,
+ const unsigned char *extra)
+{
+ int_fast32_t elem;
+
+ for (elem = 0; elem < table_size; elem++)
+ if (symb_table[2 * elem] != 0)
+ {
+ int32_t idx = symb_table[2 * elem + 1];
+ /* Skip the name of collating element name. */
+ idx += 1 + extra[idx];
+ if (/* Compare the length of the name. */
+ name_len == extra[idx]
+ /* Compare the name. */
+ && memcmp (name, &extra[idx + 1], name_len) == 0)
+ /* Yep, this is the entry. */
+ return elem;
+ }
+ return -1;
+}
+
+/* Local function for parse_bracket_exp used in _LIBC environment.
+ Look up the collation sequence value of BR_ELEM.
+ Return the value if succeeded, UINT_MAX otherwise. */
+
+static __always_inline unsigned int
+lookup_collation_sequence_value (bracket_elem_t *br_elem, uint32_t nrules,
+ const unsigned char *collseqmb,
+ const char *collseqwc,
+ int_fast32_t table_size,
+ const int32_t *symb_table,
+ const unsigned char *extra)
+{
+ if (br_elem->type == SB_CHAR)
+ {
+ /* if (MB_CUR_MAX == 1) */
+ if (nrules == 0)
+ return collseqmb[br_elem->opr.ch];
+ else
+ {
+ wint_t wc = __btowc (br_elem->opr.ch);
+ return __collseq_table_lookup (collseqwc, wc);
+ }
+ }
+ else if (br_elem->type == MB_CHAR)
+ {
+ if (nrules != 0)
+ return __collseq_table_lookup (collseqwc, br_elem->opr.wch);
+ }
+ else if (br_elem->type == COLL_SYM)
+ {
+ size_t sym_name_len = strlen ((char *) br_elem->opr.name);
+ if (nrules != 0)
+ {
+ int32_t elem, idx;
+ elem = seek_collating_symbol_entry (br_elem->opr.name,
+ sym_name_len,
+ symb_table, table_size,
+ extra);
+ if (elem != -1)
+ {
+ /* We found the entry. */
+ idx = symb_table[2 * elem + 1];
+ /* Skip the name of collating element name. */
+ idx += 1 + extra[idx];
+ /* Skip the byte sequence of the collating element. */
+ idx += 1 + extra[idx];
+ /* Adjust for the alignment. */
+ idx = (idx + 3) & ~3;
+ /* Skip the multibyte collation sequence value. */
+ idx += sizeof (unsigned int);
+ /* Skip the wide char sequence of the collating element. */
+ idx += sizeof (unsigned int) *
+ (1 + *(unsigned int *) (extra + idx));
+ /* Return the collation sequence value. */
+ return *(unsigned int *) (extra + idx);
+ }
+ else if (sym_name_len == 1)
+ {
+ /* No valid character. Match it as a single byte
+ character. */
+ return collseqmb[br_elem->opr.name[0]];
+ }
+ }
+ else if (sym_name_len == 1)
+ return collseqmb[br_elem->opr.name[0]];
+ }
+ return UINT_MAX;
+}
+
+/* Local function for parse_bracket_exp used in _LIBC environment.
+ Build the range expression which starts from START_ELEM, and ends
+ at END_ELEM. The result are written to MBCSET and SBCSET.
+ RANGE_ALLOC is the allocated size of mbcset->range_starts, and
+ mbcset->range_ends, is a pointer argument since we may
+ update it. */
+
+static __always_inline reg_errcode_t
+build_range_exp (bitset_t sbcset, re_charset_t *mbcset, Idx *range_alloc,
+ bracket_elem_t *start_elem, bracket_elem_t *end_elem,
+ re_dfa_t *dfa, reg_syntax_t syntax, uint32_t nrules,
+ const unsigned char *collseqmb, const char *collseqwc,
+ int_fast32_t table_size, const int32_t *symb_table,
+ const unsigned char *extra)
+{
+ unsigned int ch;
+ uint32_t start_collseq;
+ uint32_t end_collseq;
+
+ /* Equivalence Classes and Character Classes can't be a range
+ start/end. */
+ if (__glibc_unlikely (start_elem->type == EQUIV_CLASS
+ || start_elem->type == CHAR_CLASS
+ || end_elem->type == EQUIV_CLASS
+ || end_elem->type == CHAR_CLASS))
+ return REG_ERANGE;
+
+ /* FIXME: Implement rational ranges here, too. */
+ start_collseq = lookup_collation_sequence_value (start_elem, nrules, collseqmb, collseqwc,
+ table_size, symb_table, extra);
+ end_collseq = lookup_collation_sequence_value (end_elem, nrules, collseqmb, collseqwc,
+ table_size, symb_table, extra);
+ /* Check start/end collation sequence values. */
+ if (__glibc_unlikely (start_collseq == UINT_MAX
+ || end_collseq == UINT_MAX))
+ return REG_ECOLLATE;
+ if (__glibc_unlikely ((syntax & RE_NO_EMPTY_RANGES)
+ && start_collseq > end_collseq))
+ return REG_ERANGE;
+
+ /* Got valid collation sequence values, add them as a new entry.
+ However, if we have no collation elements, and the character set
+ is single byte, the single byte character set that we
+ build below suffices. */
+ if (nrules > 0 || dfa->mb_cur_max > 1)
+ {
+ /* Check the space of the arrays. */
+ if (__glibc_unlikely (*range_alloc == mbcset->nranges))
+ {
+ /* There is not enough space, need realloc. */
+ uint32_t *new_array_start;
+ uint32_t *new_array_end;
+ int new_nranges;
+
+ /* +1 in case of mbcset->nranges is 0. */
+ new_nranges = 2 * mbcset->nranges + 1;
+ new_array_start = re_realloc (mbcset->range_starts, uint32_t,
+ new_nranges);
+ new_array_end = re_realloc (mbcset->range_ends, uint32_t,
+ new_nranges);
+
+ if (__glibc_unlikely (new_array_start == NULL
+ || new_array_end == NULL))
+ return REG_ESPACE;
+
+ mbcset->range_starts = new_array_start;
+ mbcset->range_ends = new_array_end;
+ *range_alloc = new_nranges;
+ }
+
+ mbcset->range_starts[mbcset->nranges] = start_collseq;
+ mbcset->range_ends[mbcset->nranges++] = end_collseq;
+ }
+
+ /* Build the table for single byte characters. */
+ for (ch = 0; ch < SBC_MAX; ch++)
+ {
+ uint32_t ch_collseq;
+ /* if (MB_CUR_MAX == 1) */
+ if (nrules == 0)
+ ch_collseq = collseqmb[ch];
+ else
+ ch_collseq = __collseq_table_lookup (collseqwc, __btowc (ch));
+ if (start_collseq <= ch_collseq && ch_collseq <= end_collseq)
+ bitset_set (sbcset, ch);
+ }
+ return REG_NOERROR;
+}
+
+/* Local function for parse_bracket_exp used in _LIBC environment.
+ Build the collating element which is represented by NAME.
+ The result are written to MBCSET and SBCSET.
+ COLL_SYM_ALLOC is the allocated size of mbcset->coll_sym, is a
+ pointer argument since we may update it. */
+
+static __always_inline reg_errcode_t
+build_collating_symbol (bitset_t sbcset, re_charset_t *mbcset,
+ Idx *coll_sym_alloc, const unsigned char *name,
+ uint_fast32_t nrules, int_fast32_t table_size,
+ const int32_t *symb_table, const unsigned char *extra)
+{
+ int32_t elem, idx;
+ size_t name_len = strlen ((const char *) name);
+ if (nrules != 0)
+ {
+ elem = seek_collating_symbol_entry (name, name_len, symb_table,
+ table_size, extra);
+ if (elem != -1)
+ {
+ /* We found the entry. */
+ idx = symb_table[2 * elem + 1];
+ /* Skip the name of collating element name. */
+ idx += 1 + extra[idx];
+ }
+ else if (name_len == 1)
+ {
+ /* No valid character, treat it as a normal
+ character. */
+ bitset_set (sbcset, name[0]);
+ return REG_NOERROR;
+ }
+ else
+ return REG_ECOLLATE;
+
+ /* Got valid collation sequence, add it as a new entry. */
+ /* Check the space of the arrays. */
+ if (__glibc_unlikely (*coll_sym_alloc == mbcset->ncoll_syms))
+ {
+ /* Not enough, realloc it. */
+ /* +1 in case of mbcset->ncoll_syms is 0. */
+ int new_coll_sym_alloc = 2 * mbcset->ncoll_syms + 1;
+ /* Use realloc since mbcset->coll_syms is NULL
+ if *alloc == 0. */
+ int32_t *new_coll_syms = re_realloc (mbcset->coll_syms, int32_t,
+ new_coll_sym_alloc);
+ if (__glibc_unlikely (new_coll_syms == NULL))
+ return REG_ESPACE;
+ mbcset->coll_syms = new_coll_syms;
+ *coll_sym_alloc = new_coll_sym_alloc;
+ }
+ mbcset->coll_syms[mbcset->ncoll_syms++] = idx;
+ return REG_NOERROR;
+ }
+ else
+ {
+ if (__glibc_unlikely (name_len != 1))
+ return REG_ECOLLATE;
+ else
+ {
+ bitset_set (sbcset, name[0]);
+ return REG_NOERROR;
+ }
+ }
+}
+#endif /* _LIBC */
+
+/* This function parse bracket expression like "[abc]", "[a-c]",
+ "[[.a-a.]]" etc. */
+
+static bin_tree_t *
+parse_bracket_exp (re_string_t *regexp, re_dfa_t *dfa, re_token_t *token,
+ reg_syntax_t syntax, reg_errcode_t *err)
+{
+ const unsigned char *collseqmb = NULL;
+ const char *collseqwc = NULL;
+ uint_fast32_t nrules = 0;
+ int_fast32_t table_size = 0;
+ const void *symb_table = NULL;
+ const unsigned char *extra = NULL;
+
+ re_token_t br_token;
+ re_bitset_ptr_t sbcset;
+ re_charset_t *mbcset;
+ Idx coll_sym_alloc = 0, range_alloc = 0, mbchar_alloc = 0;
+ Idx equiv_class_alloc = 0, char_class_alloc = 0;
+ bool non_match = false;
+ bin_tree_t *work_tree;
+ int token_len;
+ bool first_round = true;
+#ifdef _LIBC
+ collseqmb = (const unsigned char *)
+ _NL_CURRENT (LC_COLLATE, _NL_COLLATE_COLLSEQMB);
+ nrules = _NL_CURRENT_WORD (LC_COLLATE, _NL_COLLATE_NRULES);
+ if (nrules)
+ {
+ /*
+ if (MB_CUR_MAX > 1)
+ */
+ collseqwc = _NL_CURRENT (LC_COLLATE, _NL_COLLATE_COLLSEQWC);
+ table_size = _NL_CURRENT_WORD (LC_COLLATE, _NL_COLLATE_SYMB_HASH_SIZEMB);
+ symb_table = _NL_CURRENT (LC_COLLATE, _NL_COLLATE_SYMB_TABLEMB);
+ extra = (const unsigned char *) _NL_CURRENT (LC_COLLATE,
+ _NL_COLLATE_SYMB_EXTRAMB);
+ }
+#endif
+ sbcset = (re_bitset_ptr_t) calloc (sizeof (bitset_t), 1);
+ mbcset = (re_charset_t *) calloc (sizeof (re_charset_t), 1);
+ if (__glibc_unlikely (sbcset == NULL || mbcset == NULL))
+ {
+ re_free (sbcset);
+ re_free (mbcset);
+ *err = REG_ESPACE;
+ return NULL;
+ }
+
+ token_len = peek_token_bracket (token, regexp, syntax);
+ if (__glibc_unlikely (token->type == END_OF_RE))
+ {
+ *err = REG_BADPAT;
+ goto parse_bracket_exp_free_return;
+ }
+ if (token->type == OP_NON_MATCH_LIST)
+ {
+ mbcset->non_match = 1;
+ non_match = true;
+ if (syntax & RE_HAT_LISTS_NOT_NEWLINE)
+ bitset_set (sbcset, '\n');
+ re_string_skip_bytes (regexp, token_len); /* Skip a token. */
+ token_len = peek_token_bracket (token, regexp, syntax);
+ if (__glibc_unlikely (token->type == END_OF_RE))
+ {
+ *err = REG_BADPAT;
+ goto parse_bracket_exp_free_return;
+ }
+ }
+
+ /* We treat the first ']' as a normal character. */
+ if (token->type == OP_CLOSE_BRACKET)
+ token->type = CHARACTER;
+
+ while (1)
+ {
+ bracket_elem_t start_elem, end_elem;
+ unsigned char start_name_buf[BRACKET_NAME_BUF_SIZE];
+ unsigned char end_name_buf[BRACKET_NAME_BUF_SIZE];
+ reg_errcode_t ret;
+ int token_len2 = 0;
+ bool is_range_exp = false;
+ re_token_t token2;
+
+ start_elem.opr.name = start_name_buf;
+ start_elem.type = COLL_SYM;
+ ret = parse_bracket_element (&start_elem, regexp, token, token_len, dfa,
+ syntax, first_round);
+ if (__glibc_unlikely (ret != REG_NOERROR))
+ {
+ *err = ret;
+ goto parse_bracket_exp_free_return;
+ }
+ first_round = false;
+
+ /* Get information about the next token. We need it in any case. */
+ token_len = peek_token_bracket (token, regexp, syntax);
+
+ /* Do not check for ranges if we know they are not allowed. */
+ if (start_elem.type != CHAR_CLASS && start_elem.type != EQUIV_CLASS)
+ {
+ if (__glibc_unlikely (token->type == END_OF_RE))
+ {
+ *err = REG_EBRACK;
+ goto parse_bracket_exp_free_return;
+ }
+ if (token->type == OP_CHARSET_RANGE)
+ {
+ re_string_skip_bytes (regexp, token_len); /* Skip '-'. */
+ token_len2 = peek_token_bracket (&token2, regexp, syntax);
+ if (__glibc_unlikely (token2.type == END_OF_RE))
+ {
+ *err = REG_EBRACK;
+ goto parse_bracket_exp_free_return;
+ }
+ if (token2.type == OP_CLOSE_BRACKET)
+ {
+ /* We treat the last '-' as a normal character. */
+ re_string_skip_bytes (regexp, -token_len);
+ token->type = CHARACTER;
+ }
+ else
+ is_range_exp = true;
+ }
+ }
+
+ if (is_range_exp == true)
+ {
+ end_elem.opr.name = end_name_buf;
+ end_elem.type = COLL_SYM;
+ ret = parse_bracket_element (&end_elem, regexp, &token2, token_len2,
+ dfa, syntax, true);
+ if (__glibc_unlikely (ret != REG_NOERROR))
+ {
+ *err = ret;
+ goto parse_bracket_exp_free_return;
+ }
+
+ token_len = peek_token_bracket (token, regexp, syntax);
+
+ *err = build_range_exp (sbcset, mbcset, &range_alloc,
+ &start_elem, &end_elem,
+ dfa, syntax, nrules, collseqmb, collseqwc,
+ table_size, symb_table, extra);
+ if (__glibc_unlikely (*err != REG_NOERROR))
+ goto parse_bracket_exp_free_return;
+ }
+ else
+ {
+ switch (start_elem.type)
+ {
+ case SB_CHAR:
+ bitset_set (sbcset, start_elem.opr.ch);
+ break;
+ case MB_CHAR:
+ /* Check whether the array has enough space. */
+ if (__glibc_unlikely (mbchar_alloc == mbcset->nmbchars))
+ {
+ wchar_t *new_mbchars;
+ /* Not enough, realloc it. */
+ /* +1 in case of mbcset->nmbchars is 0. */
+ mbchar_alloc = 2 * mbcset->nmbchars + 1;
+ /* Use realloc since array is NULL if *alloc == 0. */
+ new_mbchars = re_realloc (mbcset->mbchars, wchar_t,
+ mbchar_alloc);
+ if (__glibc_unlikely (new_mbchars == NULL))
+ goto parse_bracket_exp_espace;
+ mbcset->mbchars = new_mbchars;
+ }
+ mbcset->mbchars[mbcset->nmbchars++] = start_elem.opr.wch;
+ break;
+ case EQUIV_CLASS:
+ *err = build_equiv_class (sbcset,
+ mbcset, &equiv_class_alloc,
+ start_elem.opr.name);
+ if (__glibc_unlikely (*err != REG_NOERROR))
+ goto parse_bracket_exp_free_return;
+ break;
+ case COLL_SYM:
+ *err = build_collating_symbol (sbcset,
+ mbcset, &coll_sym_alloc,
+ start_elem.opr.name,
+ nrules, table_size, symb_table, extra);
+ if (__glibc_unlikely (*err != REG_NOERROR))
+ goto parse_bracket_exp_free_return;
+ break;
+ case CHAR_CLASS:
+ *err = build_charclass (regexp->trans, sbcset,
+ mbcset, &char_class_alloc,
+ (const char *) start_elem.opr.name,
+ syntax);
+ if (__glibc_unlikely (*err != REG_NOERROR))
+ goto parse_bracket_exp_free_return;
+ break;
+ default:
+ DEBUG_ASSERT (false);
+ break;
+ }
+ }
+ if (__glibc_unlikely (token->type == END_OF_RE))
+ {
+ *err = REG_EBRACK;
+ goto parse_bracket_exp_free_return;
+ }
+ if (token->type == OP_CLOSE_BRACKET)
+ break;
+ }
+
+ re_string_skip_bytes (regexp, token_len); /* Skip a token. */
+
+ /* If it is non-matching list. */
+ if (non_match)
+ bitset_not (sbcset);
+
+ /* Ensure only single byte characters are set. */
+ if (dfa->mb_cur_max > 1)
+ bitset_mask (sbcset, dfa->sb_char);
+
+ if (mbcset->nmbchars || mbcset->ncoll_syms || mbcset->nequiv_classes
+ || mbcset->nranges || (dfa->mb_cur_max > 1 && (mbcset->nchar_classes
+ || mbcset->non_match)))
+ {
+ bin_tree_t *mbc_tree;
+ int sbc_idx;
+ /* Build a tree for complex bracket. */
+ dfa->has_mb_node = 1;
+ br_token.type = COMPLEX_BRACKET;
+ br_token.opr.mbcset = mbcset;
+ mbc_tree = create_token_tree (dfa, NULL, NULL, &br_token);
+ if (__glibc_unlikely (mbc_tree == NULL))
+ goto parse_bracket_exp_espace;
+ for (sbc_idx = 0; sbc_idx < BITSET_WORDS; ++sbc_idx)
+ if (sbcset[sbc_idx])
+ break;
+ /* If there are no bits set in sbcset, there is no point
+ of having both SIMPLE_BRACKET and COMPLEX_BRACKET. */
+ if (sbc_idx < BITSET_WORDS)
+ {
+ /* Build a tree for simple bracket. */
+ br_token.type = SIMPLE_BRACKET;
+ br_token.opr.sbcset = sbcset;
+ work_tree = create_token_tree (dfa, NULL, NULL, &br_token);
+ if (__glibc_unlikely (work_tree == NULL))
+ goto parse_bracket_exp_espace;
+
+ /* Then join them by ALT node. */
+ work_tree = create_tree (dfa, work_tree, mbc_tree, OP_ALT);
+ if (__glibc_unlikely (work_tree == NULL))
+ goto parse_bracket_exp_espace;
+ }
+ else
+ {
+ re_free (sbcset);
+ work_tree = mbc_tree;
+ }
+ }
+ else
+ {
+ free_charset (mbcset);
+ /* Build a tree for simple bracket. */
+ br_token.type = SIMPLE_BRACKET;
+ br_token.opr.sbcset = sbcset;
+ work_tree = create_token_tree (dfa, NULL, NULL, &br_token);
+ if (__glibc_unlikely (work_tree == NULL))
+ goto parse_bracket_exp_espace;
+ }
+ return work_tree;
+
+ parse_bracket_exp_espace:
+ *err = REG_ESPACE;
+ parse_bracket_exp_free_return:
+ re_free (sbcset);
+ free_charset (mbcset);
+ return NULL;
+}
+
+/* Parse an element in the bracket expression. */
+
+static reg_errcode_t
+parse_bracket_element (bracket_elem_t *elem, re_string_t *regexp,
+ re_token_t *token, int token_len, re_dfa_t *dfa,
+ reg_syntax_t syntax, bool accept_hyphen)
+{
+ int cur_char_size;
+ cur_char_size = re_string_char_size_at (regexp, re_string_cur_idx (regexp));
+ if (cur_char_size > 1)
+ {
+ elem->type = MB_CHAR;
+ elem->opr.wch = re_string_wchar_at (regexp, re_string_cur_idx (regexp));
+ re_string_skip_bytes (regexp, cur_char_size);
+ return REG_NOERROR;
+ }
+ re_string_skip_bytes (regexp, token_len); /* Skip a token. */
+ if (token->type == OP_OPEN_COLL_ELEM || token->type == OP_OPEN_CHAR_CLASS
+ || token->type == OP_OPEN_EQUIV_CLASS)
+ return parse_bracket_symbol (elem, regexp, token);
+ if (__glibc_unlikely (token->type == OP_CHARSET_RANGE) && !accept_hyphen)
+ {
+ /* A '-' must only appear as anything but a range indicator before
+ the closing bracket. Everything else is an error. */
+ re_token_t token2;
+ (void) peek_token_bracket (&token2, regexp, syntax);
+ if (token2.type != OP_CLOSE_BRACKET)
+ /* The actual error value is not standardized since this whole
+ case is undefined. But ERANGE makes good sense. */
+ return REG_ERANGE;
+ }
+ elem->type = SB_CHAR;
+ elem->opr.ch = token->opr.c;
+ return REG_NOERROR;
+}
+
+/* Parse a bracket symbol in the bracket expression. Bracket symbols are
+ such as [:<character_class>:], [.<collating_element>.], and
+ [=<equivalent_class>=]. */
+
+static reg_errcode_t
+parse_bracket_symbol (bracket_elem_t *elem, re_string_t *regexp,
+ re_token_t *token)
+{
+ unsigned char ch, delim = token->opr.c;
+ int i = 0;
+ if (re_string_eoi(regexp))
+ return REG_EBRACK;
+ for (;; ++i)
+ {
+ if (i >= BRACKET_NAME_BUF_SIZE)
+ return REG_EBRACK;
+ if (token->type == OP_OPEN_CHAR_CLASS)
+ ch = re_string_fetch_byte_case (regexp);
+ else
+ ch = re_string_fetch_byte (regexp);
+ if (re_string_eoi(regexp))
+ return REG_EBRACK;
+ if (ch == delim && re_string_peek_byte (regexp, 0) == ']')
+ break;
+ elem->opr.name[i] = ch;
+ }
+ re_string_skip_bytes (regexp, 1);
+ elem->opr.name[i] = '\0';
+ switch (token->type)
+ {
+ case OP_OPEN_COLL_ELEM:
+ elem->type = COLL_SYM;
+ break;
+ case OP_OPEN_EQUIV_CLASS:
+ elem->type = EQUIV_CLASS;
+ break;
+ case OP_OPEN_CHAR_CLASS:
+ elem->type = CHAR_CLASS;
+ break;
+ default:
+ break;
+ }
+ return REG_NOERROR;
+}
+
+ /* Helper function for parse_bracket_exp.
+ Build the equivalence class which is represented by NAME.
+ The result are written to MBCSET and SBCSET.
+ EQUIV_CLASS_ALLOC is the allocated size of mbcset->equiv_classes,
+ is a pointer argument since we may update it. */
+
+static reg_errcode_t
+build_equiv_class (bitset_t sbcset, re_charset_t *mbcset,
+ Idx *equiv_class_alloc, const unsigned char *name)
+{
+#ifdef _LIBC
+ uint32_t nrules = _NL_CURRENT_WORD (LC_COLLATE, _NL_COLLATE_NRULES);
+ if (nrules != 0)
+ {
+ const int32_t *table, *indirect;
+ const unsigned char *weights, *extra, *cp;
+ unsigned char char_buf[2];
+ int32_t idx1, idx2;
+ unsigned int ch;
+ size_t len;
+ /* Calculate the index for equivalence class. */
+ cp = name;
+ table = (const int32_t *) _NL_CURRENT (LC_COLLATE, _NL_COLLATE_TABLEMB);
+ weights = (const unsigned char *) _NL_CURRENT (LC_COLLATE,
+ _NL_COLLATE_WEIGHTMB);
+ extra = (const unsigned char *) _NL_CURRENT (LC_COLLATE,
+ _NL_COLLATE_EXTRAMB);
+ indirect = (const int32_t *) _NL_CURRENT (LC_COLLATE,
+ _NL_COLLATE_INDIRECTMB);
+ idx1 = findidx (table, indirect, extra, &cp, -1);
+ if (__glibc_unlikely (idx1 == 0 || *cp != '\0'))
+ /* This isn't a valid character. */
+ return REG_ECOLLATE;
+
+ /* Build single byte matching table for this equivalence class. */
+ len = weights[idx1 & 0xffffff];
+ for (ch = 0; ch < SBC_MAX; ++ch)
+ {
+ char_buf[0] = ch;
+ cp = char_buf;
+ idx2 = findidx (table, indirect, extra, &cp, 1);
+/*
+ idx2 = table[ch];
+*/
+ if (idx2 == 0)
+ /* This isn't a valid character. */
+ continue;
+ /* Compare only if the length matches and the collation rule
+ index is the same. */
+ if (len == weights[idx2 & 0xffffff] && (idx1 >> 24) == (idx2 >> 24)
+ && memcmp (weights + (idx1 & 0xffffff) + 1,
+ weights + (idx2 & 0xffffff) + 1, len) == 0)
+ bitset_set (sbcset, ch);
+ }
+ /* Check whether the array has enough space. */
+ if (__glibc_unlikely (*equiv_class_alloc == mbcset->nequiv_classes))
+ {
+ /* Not enough, realloc it. */
+ /* +1 in case of mbcset->nequiv_classes is 0. */
+ Idx new_equiv_class_alloc = 2 * mbcset->nequiv_classes + 1;
+ /* Use realloc since the array is NULL if *alloc == 0. */
+ int32_t *new_equiv_classes = re_realloc (mbcset->equiv_classes,
+ int32_t,
+ new_equiv_class_alloc);
+ if (__glibc_unlikely (new_equiv_classes == NULL))
+ return REG_ESPACE;
+ mbcset->equiv_classes = new_equiv_classes;
+ *equiv_class_alloc = new_equiv_class_alloc;
+ }
+ mbcset->equiv_classes[mbcset->nequiv_classes++] = idx1;
+ }
+ else
+#endif /* _LIBC */
+ {
+ if (__glibc_unlikely (strlen ((const char *) name) != 1))
+ return REG_ECOLLATE;
+ bitset_set (sbcset, *name);
+ }
+ return REG_NOERROR;
+}
+
+ /* Helper function for parse_bracket_exp.
+ Build the character class which is represented by NAME.
+ The result are written to MBCSET and SBCSET.
+ CHAR_CLASS_ALLOC is the allocated size of mbcset->char_classes,
+ is a pointer argument since we may update it. */
+
+static reg_errcode_t
+build_charclass (RE_TRANSLATE_TYPE trans, bitset_t sbcset,
+ re_charset_t *mbcset, Idx *char_class_alloc,
+ const char *class_name, reg_syntax_t syntax)
+{
+ int i;
+ const char *name = class_name;
+
+ /* In case of REG_ICASE "upper" and "lower" match the both of
+ upper and lower cases. */
+ if ((syntax & RE_ICASE)
+ && (strcmp (name, "upper") == 0 || strcmp (name, "lower") == 0))
+ name = "alpha";
+
+ /* Check the space of the arrays. */
+ if (__glibc_unlikely (*char_class_alloc == mbcset->nchar_classes))
+ {
+ /* Not enough, realloc it. */
+ /* +1 in case of mbcset->nchar_classes is 0. */
+ Idx new_char_class_alloc = 2 * mbcset->nchar_classes + 1;
+ /* Use realloc since array is NULL if *alloc == 0. */
+ wctype_t *new_char_classes = re_realloc (mbcset->char_classes, wctype_t,
+ new_char_class_alloc);
+ if (__glibc_unlikely (new_char_classes == NULL))
+ return REG_ESPACE;
+ mbcset->char_classes = new_char_classes;
+ *char_class_alloc = new_char_class_alloc;
+ }
+ mbcset->char_classes[mbcset->nchar_classes++] = __wctype (name);
+
+#define BUILD_CHARCLASS_LOOP(ctype_func) \
+ do { \
+ if (__glibc_unlikely (trans != NULL)) \
+ { \
+ for (i = 0; i < SBC_MAX; ++i) \
+ if (ctype_func (i)) \
+ bitset_set (sbcset, trans[i]); \
+ } \
+ else \
+ { \
+ for (i = 0; i < SBC_MAX; ++i) \
+ if (ctype_func (i)) \
+ bitset_set (sbcset, i); \
+ } \
+ } while (0)
+
+ if (strcmp (name, "alnum") == 0)
+ BUILD_CHARCLASS_LOOP (isalnum);
+ else if (strcmp (name, "cntrl") == 0)
+ BUILD_CHARCLASS_LOOP (iscntrl);
+ else if (strcmp (name, "lower") == 0)
+ BUILD_CHARCLASS_LOOP (islower);
+ else if (strcmp (name, "space") == 0)
+ BUILD_CHARCLASS_LOOP (isspace);
+ else if (strcmp (name, "alpha") == 0)
+ BUILD_CHARCLASS_LOOP (isalpha);
+ else if (strcmp (name, "digit") == 0)
+ BUILD_CHARCLASS_LOOP (isdigit);
+ else if (strcmp (name, "print") == 0)
+ BUILD_CHARCLASS_LOOP (isprint);
+ else if (strcmp (name, "upper") == 0)
+ BUILD_CHARCLASS_LOOP (isupper);
+ else if (strcmp (name, "blank") == 0)
+ BUILD_CHARCLASS_LOOP (isblank);
+ else if (strcmp (name, "graph") == 0)
+ BUILD_CHARCLASS_LOOP (isgraph);
+ else if (strcmp (name, "punct") == 0)
+ BUILD_CHARCLASS_LOOP (ispunct);
+ else if (strcmp (name, "xdigit") == 0)
+ BUILD_CHARCLASS_LOOP (isxdigit);
+ else
+ return REG_ECTYPE;
+
+ return REG_NOERROR;
+}
+
+static bin_tree_t *
+build_charclass_op (re_dfa_t *dfa, RE_TRANSLATE_TYPE trans,
+ const char *class_name,
+ const char *extra, bool non_match,
+ reg_errcode_t *err)
+{
+ re_bitset_ptr_t sbcset;
+ re_charset_t *mbcset;
+ Idx alloc = 0;
+ reg_errcode_t ret;
+ bin_tree_t *tree;
+
+ sbcset = (re_bitset_ptr_t) calloc (sizeof (bitset_t), 1);
+ if (__glibc_unlikely (sbcset == NULL))
+ {
+ *err = REG_ESPACE;
+ return NULL;
+ }
+ mbcset = (re_charset_t *) calloc (sizeof (re_charset_t), 1);
+ if (__glibc_unlikely (mbcset == NULL))
+ {
+ re_free (sbcset);
+ *err = REG_ESPACE;
+ return NULL;
+ }
+ mbcset->non_match = non_match;
+
+ /* We don't care the syntax in this case. */
+ ret = build_charclass (trans, sbcset, mbcset, &alloc, class_name, 0);
+
+ if (__glibc_unlikely (ret != REG_NOERROR))
+ {
+ re_free (sbcset);
+ free_charset (mbcset);
+ *err = ret;
+ return NULL;
+ }
+ /* \w match '_' also. */
+ for (; *extra; extra++)
+ bitset_set (sbcset, *extra);
+
+ /* If it is non-matching list. */
+ if (non_match)
+ bitset_not (sbcset);
+
+ /* Ensure only single byte characters are set. */
+ if (dfa->mb_cur_max > 1)
+ bitset_mask (sbcset, dfa->sb_char);
+
+ /* Build a tree for simple bracket. */
+ 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;
+
+ if (dfa->mb_cur_max > 1)
+ {
+ bin_tree_t *mbc_tree;
+ /* Build a tree for complex bracket. */
+ br_token.type = COMPLEX_BRACKET;
+ br_token.opr.mbcset = mbcset;
+ dfa->has_mb_node = 1;
+ mbc_tree = create_token_tree (dfa, NULL, NULL, &br_token);
+ if (__glibc_unlikely (mbc_tree == NULL))
+ goto build_word_op_espace;
+ /* Then join them by ALT node. */
+ tree = create_tree (dfa, tree, mbc_tree, OP_ALT);
+ if (__glibc_likely (mbc_tree != NULL))
+ return tree;
+ }
+ else
+ {
+ free_charset (mbcset);
+ return tree;
+ }
+
+ build_word_op_espace:
+ re_free (sbcset);
+ free_charset (mbcset);
+ *err = REG_ESPACE;
+ return NULL;
+}
+
+/* This is intended for the expressions like "a{1,3}".
+ Fetch a number from 'input', and return the number.
+ Return -1 if the number field is empty like "{,1}".
+ Return RE_DUP_MAX + 1 if the number field is too large.
+ Return -2 if an error occurred. */
+
+static Idx
+fetch_number (re_string_t *input, re_token_t *token, reg_syntax_t syntax)
+{
+ Idx num = -1;
+ unsigned char c;
+ while (1)
+ {
+ fetch_token (token, input, syntax);
+ c = token->opr.c;
+ if (__glibc_unlikely (token->type == END_OF_RE))
+ return -2;
+ if (token->type == OP_CLOSE_DUP_NUM || c == ',')
+ break;
+ num = ((token->type != CHARACTER || c < '0' || '9' < c || num == -2)
+ ? -2
+ : num == -1
+ ? c - '0'
+ : MIN (RE_DUP_MAX + 1, num * 10 + c - '0'));
+ }
+ return num;
+}
+
+static void
+free_charset (re_charset_t *cset)
+{
+ re_free (cset->mbchars);
+#ifdef _LIBC
+ re_free (cset->coll_syms);
+ re_free (cset->equiv_classes);
+#endif
+ re_free (cset->range_starts);
+ re_free (cset->range_ends);
+ re_free (cset->char_classes);
+ re_free (cset);
+}
+
+/* Functions for binary tree operation. */
+
+/* Create a tree node. */
+
+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 = { .type = type };
+ return create_token_tree (dfa, left, right, &t);
+}
+
+static bin_tree_t *
+create_token_tree (re_dfa_t *dfa, bin_tree_t *left, bin_tree_t *right,
+ const re_token_t *token)
+{
+ bin_tree_t *tree;
+ if (__glibc_unlikely (dfa->str_tree_storage_idx == BIN_TREE_STORAGE_SIZE))
+ {
+ bin_tree_storage_t *storage = re_malloc (bin_tree_storage_t, 1);
+
+ if (storage == NULL)
+ return NULL;
+ storage->next = dfa->str_tree_storage;
+ dfa->str_tree_storage = storage;
+ dfa->str_tree_storage_idx = 0;
+ }
+ tree = &dfa->str_tree_storage->data[dfa->str_tree_storage_idx++];
+
+ tree->parent = NULL;
+ tree->left = left;
+ tree->right = right;
+ tree->token = *token;
+ tree->token.duplicated = 0;
+ tree->token.opt_subexp = 0;
+ tree->first = NULL;
+ tree->next = NULL;
+ tree->node_idx = -1;
+
+ if (left != NULL)
+ left->parent = tree;
+ if (right != NULL)
+ right->parent = tree;
+ return tree;
+}
+
+/* Mark the tree SRC as an optional subexpression.
+ To be called from preorder or postorder. */
+
+static reg_errcode_t
+mark_opt_subexp (void *extra, bin_tree_t *node)
+{
+ Idx idx = (uintptr_t) extra;
+ if (node->token.type == SUBEXP && node->token.opr.idx == idx)
+ node->token.opt_subexp = 1;
+
+ return REG_NOERROR;
+}
+
+/* Free the allocated memory inside NODE. */
+
+static void
+free_token (re_token_t *node)
+{
+ if (node->type == COMPLEX_BRACKET && node->duplicated == 0)
+ free_charset (node->opr.mbcset);
+ else if (node->type == SIMPLE_BRACKET && node->duplicated == 0)
+ re_free (node->opr.sbcset);
+}
+
+/* Worker function for tree walking. Free the allocated memory inside NODE
+ and its children. */
+
+static reg_errcode_t
+free_tree (void *extra, bin_tree_t *node)
+{
+ free_token (&node->token);
+ return REG_NOERROR;
+}
+
+
+/* Duplicate the node SRC, and return new node. This is a preorder
+ visit similar to the one implemented by the generic visitor, but
+ we need more infrastructure to maintain two parallel trees --- so,
+ it's easier to duplicate. */
+
+static bin_tree_t *
+duplicate_tree (const bin_tree_t *root, re_dfa_t *dfa)
+{
+ const bin_tree_t *node;
+ bin_tree_t *dup_root;
+ bin_tree_t **p_new = &dup_root, *dup_node = root->parent;
+
+ for (node = root; ; )
+ {
+ /* Create a new tree and link it back to the current parent. */
+ *p_new = create_token_tree (dfa, NULL, NULL, &node->token);
+ if (*p_new == NULL)
+ return NULL;
+ (*p_new)->parent = dup_node;
+ (*p_new)->token.duplicated = 1;
+ dup_node = *p_new;
+
+ /* Go to the left node, or up and to the right. */
+ if (node->left)
+ {
+ node = node->left;
+ p_new = &dup_node->left;
+ }
+ else
+ {
+ const bin_tree_t *prev = NULL;
+ while (node->right == prev || node->right == NULL)
+ {
+ prev = node;
+ node = node->parent;
+ dup_node = dup_node->parent;
+ if (!node)
+ return dup_root;
+ }
+ node = node->right;
+ p_new = &dup_node->right;
+ }
+ }
+}
diff --git a/lib/regex.c b/lib/regex.c
new file mode 100644
index 00000000000..ff1176782e4
--- /dev/null
+++ b/lib/regex.c
@@ -0,0 +1,84 @@
+/* Extended regular expression matching and search library.
+ Copyright (C) 2002-2022 Free Software Foundation, Inc.
+ This file is part of the GNU C Library.
+ Contributed by Isamu Hasegawa <isamu@yamato.ibm.com>.
+
+ The GNU C Library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Lesser General Public
+ License as published by the Free Software Foundation; either
+ version 2.1 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
+ Lesser General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public
+ License along with the GNU C Library; if not, see
+ <https://www.gnu.org/licenses/>. */
+
+#define __STDC_WANT_IEC_60559_BFP_EXT__
+
+#ifndef _LIBC
+# include <libc-config.h>
+
+# if __GNUC_PREREQ (4, 6)
+# pragma GCC diagnostic ignored "-Wsuggest-attribute=pure"
+# pragma GCC diagnostic ignored "-Wvla"
+# endif
+# if __GNUC_PREREQ (4, 3)
+# pragma GCC diagnostic ignored "-Wold-style-definition"
+# pragma GCC diagnostic ignored "-Wtype-limits"
+# endif
+#endif
+
+/* Make sure no one compiles this code with a C++ compiler. */
+#if defined __cplusplus && defined _LIBC
+# error "This is C code, use a C compiler"
+#endif
+
+#ifdef _LIBC
+/* We have to keep the namespace clean. */
+# define regfree(preg) __regfree (preg)
+# define regexec(pr, st, nm, pm, ef) __regexec (pr, st, nm, pm, ef)
+# define regcomp(preg, pattern, cflags) __regcomp (preg, pattern, cflags)
+# define regerror(errcode, preg, errbuf, errbuf_size) \
+ __regerror(errcode, preg, errbuf, errbuf_size)
+# define re_set_registers(bu, re, nu, st, en) \
+ __re_set_registers (bu, re, nu, st, en)
+# define re_match_2(bufp, string1, size1, string2, size2, pos, regs, stop) \
+ __re_match_2 (bufp, string1, size1, string2, size2, pos, regs, stop)
+# define re_match(bufp, string, size, pos, regs) \
+ __re_match (bufp, string, size, pos, regs)
+# define re_search(bufp, string, size, startpos, range, regs) \
+ __re_search (bufp, string, size, startpos, range, regs)
+# define re_compile_pattern(pattern, length, bufp) \
+ __re_compile_pattern (pattern, length, bufp)
+# define re_set_syntax(syntax) __re_set_syntax (syntax)
+# define re_search_2(bufp, st1, s1, st2, s2, startpos, range, regs, stop) \
+ __re_search_2 (bufp, st1, s1, st2, s2, startpos, range, regs, stop)
+# define re_compile_fastmap(bufp) __re_compile_fastmap (bufp)
+
+# include "../locale/localeinfo.h"
+#endif
+
+/* On some systems, limits.h sets RE_DUP_MAX to a lower value than
+ GNU regex allows. Include it before <regex.h>, which correctly
+ #undefs RE_DUP_MAX and sets it to the right value. */
+#include <limits.h>
+
+#include <regex.h>
+#include "regex_internal.h"
+
+#include "regex_internal.c"
+#include "regcomp.c"
+#include "regexec.c"
+
+/* Binary backward compatibility. */
+#if _LIBC
+# include <shlib-compat.h>
+# if SHLIB_COMPAT (libc, GLIBC_2_0, GLIBC_2_3)
+link_warning (re_max_failures, "the 're_max_failures' variable is obsolete and will go away.")
+int re_max_failures = 2000;
+# endif
+#endif
diff --git a/lib/regex.h b/lib/regex.h
new file mode 100644
index 00000000000..a7e0bd02757
--- /dev/null
+++ b/lib/regex.h
@@ -0,0 +1,699 @@
+/* Definitions for data structures and routines for the regular
+ expression library.
+ Copyright (C) 1985, 1989-2022 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 Lesser General Public
+ License as published by the Free Software Foundation; either
+ version 2.1 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
+ Lesser General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public
+ License along with the GNU C Library; if not, see
+ <https://www.gnu.org/licenses/>. */
+
+#ifndef _REGEX_H
+#define _REGEX_H 1
+
+#include <sys/types.h>
+
+/* Allow the use in C++ code. */
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/* Define __USE_GNU to declare GNU extensions that violate the
+ POSIX name space rules. */
+#ifdef _GNU_SOURCE
+# define __USE_GNU 1
+#endif
+
+#ifdef _REGEX_LARGE_OFFSETS
+
+/* Use types and values that are wide enough to represent signed and
+ unsigned byte offsets in memory. This currently works only when
+ the regex code is used outside of the GNU C library; it is not yet
+ supported within glibc itself, and glibc users should not define
+ _REGEX_LARGE_OFFSETS. */
+
+/* The type of object sizes. */
+typedef size_t __re_size_t;
+
+/* The type of object sizes, in places where the traditional code
+ uses unsigned long int. */
+typedef size_t __re_long_size_t;
+
+#else
+
+/* The traditional GNU regex implementation mishandles strings longer
+ than INT_MAX. */
+typedef unsigned int __re_size_t;
+typedef unsigned long int __re_long_size_t;
+
+#endif
+
+/* The following two types have to be signed and unsigned integer type
+ wide enough to hold a value of a pointer. For most ANSI compilers
+ ptrdiff_t and size_t should be likely OK. Still size of these two
+ types is 2 for Microsoft C. Ugh... */
+typedef long int s_reg_t;
+typedef unsigned long int active_reg_t;
+
+/* The following bits are used to determine the regexp syntax we
+ recognize. The set/not-set meanings are chosen so that Emacs syntax
+ remains the value 0. The bits are given in alphabetical order, and
+ the definitions shifted by one from the previous bit; thus, when we
+ add or remove a bit, only one other definition need change. */
+typedef unsigned long int reg_syntax_t;
+
+#ifdef __USE_GNU
+/* If this bit is not set, then \ inside a bracket expression is literal.
+ If set, then such a \ quotes the following character. */
+# define RE_BACKSLASH_ESCAPE_IN_LISTS ((unsigned long int) 1)
+
+/* If this bit is not set, then + and ? are operators, and \+ and \? are
+ literals.
+ If set, then \+ and \? are operators and + and ? are literals. */
+# define RE_BK_PLUS_QM (RE_BACKSLASH_ESCAPE_IN_LISTS << 1)
+
+/* If this bit is set, then character classes are supported. They are:
+ [:alpha:], [:upper:], [:lower:], [:digit:], [:alnum:], [:xdigit:],
+ [:space:], [:print:], [:punct:], [:graph:], and [:cntrl:].
+ If not set, then character classes are not supported. */
+# define RE_CHAR_CLASSES (RE_BK_PLUS_QM << 1)
+
+/* If this bit is set, then ^ and $ are always anchors (outside bracket
+ expressions, of course).
+ If this bit is not set, then it depends:
+ ^ is an anchor if it is at the beginning of a regular
+ expression or after an open-group or an alternation operator;
+ $ is an anchor if it is at the end of a regular expression, or
+ before a close-group or an alternation operator.
+
+ This bit could be (re)combined with RE_CONTEXT_INDEP_OPS, because
+ POSIX draft 11.2 says that * etc. in leading positions is undefined.
+ We already implemented a previous draft which made those constructs
+ invalid, though, so we haven't changed the code back. */
+# define RE_CONTEXT_INDEP_ANCHORS (RE_CHAR_CLASSES << 1)
+
+/* If this bit is set, then special characters are always special
+ regardless of where they are in the pattern.
+ If this bit is not set, then special characters are special only in
+ some contexts; otherwise they are ordinary. Specifically,
+ * + ? and intervals are only special when not after the beginning,
+ open-group, or alternation operator. */
+# define RE_CONTEXT_INDEP_OPS (RE_CONTEXT_INDEP_ANCHORS << 1)
+
+/* If this bit is set, then *, +, ?, and { cannot be first in an re or
+ immediately after an alternation or begin-group operator. */
+# define RE_CONTEXT_INVALID_OPS (RE_CONTEXT_INDEP_OPS << 1)
+
+/* If this bit is set, then . matches newline.
+ If not set, then it doesn't. */
+# define RE_DOT_NEWLINE (RE_CONTEXT_INVALID_OPS << 1)
+
+/* If this bit is set, then . doesn't match NUL.
+ If not set, then it does. */
+# define RE_DOT_NOT_NULL (RE_DOT_NEWLINE << 1)
+
+/* If this bit is set, nonmatching lists [^...] do not match newline.
+ If not set, they do. */
+# define RE_HAT_LISTS_NOT_NEWLINE (RE_DOT_NOT_NULL << 1)
+
+/* If this bit is set, either \{...\} or {...} defines an
+ interval, depending on RE_NO_BK_BRACES.
+ If not set, \{, \}, {, and } are literals. */
+# define RE_INTERVALS (RE_HAT_LISTS_NOT_NEWLINE << 1)
+
+/* If this bit is set, +, ? and | aren't recognized as operators.
+ If not set, they are. */
+# define RE_LIMITED_OPS (RE_INTERVALS << 1)
+
+/* If this bit is set, newline is an alternation operator.
+ If not set, newline is literal. */
+# define RE_NEWLINE_ALT (RE_LIMITED_OPS << 1)
+
+/* If this bit is set, then '{...}' defines an interval, and \{ and \}
+ are literals.
+ If not set, then '\{...\}' defines an interval. */
+# define RE_NO_BK_BRACES (RE_NEWLINE_ALT << 1)
+
+/* If this bit is set, (...) defines a group, and \( and \) are literals.
+ If not set, \(...\) defines a group, and ( and ) are literals. */
+# define RE_NO_BK_PARENS (RE_NO_BK_BRACES << 1)
+
+/* If this bit is set, then \<digit> matches <digit>.
+ If not set, then \<digit> is a back-reference. */
+# define RE_NO_BK_REFS (RE_NO_BK_PARENS << 1)
+
+/* If this bit is set, then | is an alternation operator, and \| is literal.
+ If not set, then \| is an alternation operator, and | is literal. */
+# define RE_NO_BK_VBAR (RE_NO_BK_REFS << 1)
+
+/* If this bit is set, then an ending range point collating higher
+ than the starting range point, as in [z-a], is invalid.
+ If not set, then when ending range point collates higher than the
+ starting range point, the range is ignored. */
+# define RE_NO_EMPTY_RANGES (RE_NO_BK_VBAR << 1)
+
+/* If this bit is set, then an unmatched ) is ordinary.
+ If not set, then an unmatched ) is invalid. */
+# define RE_UNMATCHED_RIGHT_PAREN_ORD (RE_NO_EMPTY_RANGES << 1)
+
+/* If this bit is set, succeed as soon as we match the whole pattern,
+ without further backtracking. */
+# define RE_NO_POSIX_BACKTRACKING (RE_UNMATCHED_RIGHT_PAREN_ORD << 1)
+
+/* If this bit is set, do not process the GNU regex operators.
+ If not set, then the GNU regex operators are recognized. */
+# define RE_NO_GNU_OPS (RE_NO_POSIX_BACKTRACKING << 1)
+
+/* If this bit is set, turn on internal regex debugging.
+ If not set, and debugging was on, turn it off.
+ This only works if regex.c is compiled -DDEBUG.
+ We define this bit always, so that all that's needed to turn on
+ debugging is to recompile regex.c; the calling code can always have
+ this bit set, and it won't affect anything in the normal case. */
+# define RE_DEBUG (RE_NO_GNU_OPS << 1)
+
+/* If this bit is set, a syntactically invalid interval is treated as
+ a string of ordinary characters. For example, the ERE 'a{1' is
+ treated as 'a\{1'. */
+# define RE_INVALID_INTERVAL_ORD (RE_DEBUG << 1)
+
+/* If this bit is set, then ignore case when matching.
+ If not set, then case is significant. */
+# define RE_ICASE (RE_INVALID_INTERVAL_ORD << 1)
+
+/* This bit is used internally like RE_CONTEXT_INDEP_ANCHORS but only
+ for ^, because it is difficult to scan the regex backwards to find
+ whether ^ should be special. */
+# define RE_CARET_ANCHORS_HERE (RE_ICASE << 1)
+
+/* If this bit is set, then \{ cannot be first in a regex or
+ immediately after an alternation, open-group or \} operator. */
+# define RE_CONTEXT_INVALID_DUP (RE_CARET_ANCHORS_HERE << 1)
+
+/* If this bit is set, then no_sub will be set to 1 during
+ re_compile_pattern. */
+# define RE_NO_SUB (RE_CONTEXT_INVALID_DUP << 1)
+#endif
+
+/* This global variable defines the particular regexp syntax to use (for
+ some interfaces). When a regexp is compiled, the syntax used is
+ stored in the pattern buffer, so changing this does not affect
+ already-compiled regexps. */
+extern reg_syntax_t re_syntax_options;
+
+#ifdef __USE_GNU
+/* Define combinations of the above bits for the standard possibilities.
+ (The [[[ comments delimit what gets put into the Texinfo file, so
+ don't delete them!) */
+/* [[[begin syntaxes]]] */
+# define RE_SYNTAX_EMACS 0
+
+# define RE_SYNTAX_AWK \
+ (RE_BACKSLASH_ESCAPE_IN_LISTS | RE_DOT_NOT_NULL \
+ | RE_NO_BK_PARENS | RE_NO_BK_REFS \
+ | RE_NO_BK_VBAR | RE_NO_EMPTY_RANGES \
+ | RE_DOT_NEWLINE | RE_CONTEXT_INDEP_ANCHORS \
+ | RE_CHAR_CLASSES \
+ | RE_UNMATCHED_RIGHT_PAREN_ORD | RE_NO_GNU_OPS)
+
+# define RE_SYNTAX_GNU_AWK \
+ ((RE_SYNTAX_POSIX_EXTENDED | RE_BACKSLASH_ESCAPE_IN_LISTS \
+ | RE_INVALID_INTERVAL_ORD) \
+ & ~(RE_DOT_NOT_NULL | RE_CONTEXT_INDEP_OPS \
+ | RE_CONTEXT_INVALID_OPS ))
+
+# define RE_SYNTAX_POSIX_AWK \
+ (RE_SYNTAX_POSIX_EXTENDED | RE_BACKSLASH_ESCAPE_IN_LISTS \
+ | RE_INTERVALS | RE_NO_GNU_OPS \
+ | RE_INVALID_INTERVAL_ORD)
+
+# define RE_SYNTAX_GREP \
+ ((RE_SYNTAX_POSIX_BASIC | RE_NEWLINE_ALT) \
+ & ~(RE_CONTEXT_INVALID_DUP | RE_DOT_NOT_NULL))
+
+# define RE_SYNTAX_EGREP \
+ ((RE_SYNTAX_POSIX_EXTENDED | RE_INVALID_INTERVAL_ORD | RE_NEWLINE_ALT) \
+ & ~(RE_CONTEXT_INVALID_OPS | RE_DOT_NOT_NULL))
+
+/* POSIX grep -E behavior is no longer incompatible with GNU. */
+# define RE_SYNTAX_POSIX_EGREP \
+ RE_SYNTAX_EGREP
+
+/* P1003.2/D11.2, section 4.20.7.1, lines 5078ff. */
+# define RE_SYNTAX_ED RE_SYNTAX_POSIX_BASIC
+
+# define RE_SYNTAX_SED RE_SYNTAX_POSIX_BASIC
+
+/* Syntax bits common to both basic and extended POSIX regex syntax. */
+# define _RE_SYNTAX_POSIX_COMMON \
+ (RE_CHAR_CLASSES | RE_DOT_NEWLINE | RE_DOT_NOT_NULL \
+ | RE_INTERVALS | RE_NO_EMPTY_RANGES)
+
+# define RE_SYNTAX_POSIX_BASIC \
+ (_RE_SYNTAX_POSIX_COMMON | RE_BK_PLUS_QM | RE_CONTEXT_INVALID_DUP)
+
+/* Differs from ..._POSIX_BASIC only in that RE_BK_PLUS_QM becomes
+ RE_LIMITED_OPS, i.e., \? \+ \| are not recognized. Actually, this
+ isn't minimal, since other operators, such as \`, aren't disabled. */
+# define RE_SYNTAX_POSIX_MINIMAL_BASIC \
+ (_RE_SYNTAX_POSIX_COMMON | RE_LIMITED_OPS)
+
+# define RE_SYNTAX_POSIX_EXTENDED \
+ (_RE_SYNTAX_POSIX_COMMON | RE_CONTEXT_INDEP_ANCHORS \
+ | RE_CONTEXT_INDEP_OPS | RE_NO_BK_BRACES \
+ | RE_NO_BK_PARENS | RE_NO_BK_VBAR \
+ | RE_CONTEXT_INVALID_OPS | RE_UNMATCHED_RIGHT_PAREN_ORD)
+
+/* Differs from ..._POSIX_EXTENDED in that RE_CONTEXT_INDEP_OPS is
+ removed and RE_NO_BK_REFS is added. */
+# define RE_SYNTAX_POSIX_MINIMAL_EXTENDED \
+ (_RE_SYNTAX_POSIX_COMMON | RE_CONTEXT_INDEP_ANCHORS \
+ | RE_CONTEXT_INVALID_OPS | RE_NO_BK_BRACES \
+ | RE_NO_BK_PARENS | RE_NO_BK_REFS \
+ | RE_NO_BK_VBAR | RE_UNMATCHED_RIGHT_PAREN_ORD)
+/* [[[end syntaxes]]] */
+
+/* Maximum number of duplicates an interval can allow. POSIX-conforming
+ systems might define this in <limits.h>, but we want our
+ value, so remove any previous define. */
+# ifdef _REGEX_INCLUDE_LIMITS_H
+# include <limits.h>
+# endif
+# ifdef RE_DUP_MAX
+# undef RE_DUP_MAX
+# endif
+
+/* RE_DUP_MAX is 2**15 - 1 because an earlier implementation stored
+ the counter as a 2-byte signed integer. This is no longer true, so
+ RE_DUP_MAX could be increased to (INT_MAX / 10 - 1), or to
+ ((SIZE_MAX - 9) / 10) if _REGEX_LARGE_OFFSETS is defined.
+ However, there would be a huge performance problem if someone
+ actually used a pattern like a\{214748363\}, so RE_DUP_MAX retains
+ its historical value. */
+# define RE_DUP_MAX (0x7fff)
+#endif
+
+
+/* POSIX 'cflags' bits (i.e., information for 'regcomp'). */
+
+/* If this bit is set, then use extended regular expression syntax.
+ If not set, then use basic regular expression syntax. */
+#define REG_EXTENDED 1
+
+/* If this bit is set, then ignore case when matching.
+ If not set, then case is significant. */
+#define REG_ICASE (1 << 1)
+
+/* If this bit is set, then anchors do not match at newline
+ characters in the string.
+ If not set, then anchors do match at newlines. */
+#define REG_NEWLINE (1 << 2)
+
+/* If this bit is set, then report only success or fail in regexec.
+ If not set, then returns differ between not matching and errors. */
+#define REG_NOSUB (1 << 3)
+
+
+/* POSIX 'eflags' bits (i.e., information for regexec). */
+
+/* If this bit is set, then the beginning-of-line operator doesn't match
+ the beginning of the string (presumably because it's not the
+ beginning of a line).
+ If not set, then the beginning-of-line operator does match the
+ beginning of the string. */
+#define REG_NOTBOL 1
+
+/* Like REG_NOTBOL, except for the end-of-line. */
+#define REG_NOTEOL (1 << 1)
+
+/* Use PMATCH[0] to delimit the start and end of the search in the
+ buffer. */
+#define REG_STARTEND (1 << 2)
+
+
+/* If any error codes are removed, changed, or added, update the
+ '__re_error_msgid' table in regcomp.c. */
+
+typedef enum
+{
+ _REG_ENOSYS = -1, /* This will never happen for this implementation. */
+ _REG_NOERROR = 0, /* Success. */
+ _REG_NOMATCH, /* Didn't find a match (for regexec). */
+
+ /* POSIX regcomp return error codes. (In the order listed in the
+ standard.) */
+ _REG_BADPAT, /* Invalid pattern. */
+ _REG_ECOLLATE, /* Invalid collating element. */
+ _REG_ECTYPE, /* Invalid character class name. */
+ _REG_EESCAPE, /* Trailing backslash. */
+ _REG_ESUBREG, /* Invalid back reference. */
+ _REG_EBRACK, /* Unmatched left bracket. */
+ _REG_EPAREN, /* Parenthesis imbalance. */
+ _REG_EBRACE, /* Unmatched \{. */
+ _REG_BADBR, /* Invalid contents of \{\}. */
+ _REG_ERANGE, /* Invalid range end. */
+ _REG_ESPACE, /* Ran out of memory. */
+ _REG_BADRPT, /* No preceding re for repetition op. */
+
+ /* Error codes we've added. */
+ _REG_EEND, /* Premature end. */
+ _REG_ESIZE, /* Too large (e.g., repeat count too large). */
+ _REG_ERPAREN /* Unmatched ) or \); not returned from regcomp. */
+} reg_errcode_t;
+
+#if defined _XOPEN_SOURCE || defined __USE_XOPEN2K
+# define REG_ENOSYS _REG_ENOSYS
+#endif
+#define REG_NOERROR _REG_NOERROR
+#define REG_NOMATCH _REG_NOMATCH
+#define REG_BADPAT _REG_BADPAT
+#define REG_ECOLLATE _REG_ECOLLATE
+#define REG_ECTYPE _REG_ECTYPE
+#define REG_EESCAPE _REG_EESCAPE
+#define REG_ESUBREG _REG_ESUBREG
+#define REG_EBRACK _REG_EBRACK
+#define REG_EPAREN _REG_EPAREN
+#define REG_EBRACE _REG_EBRACE
+#define REG_BADBR _REG_BADBR
+#define REG_ERANGE _REG_ERANGE
+#define REG_ESPACE _REG_ESPACE
+#define REG_BADRPT _REG_BADRPT
+#define REG_EEND _REG_EEND
+#define REG_ESIZE _REG_ESIZE
+#define REG_ERPAREN _REG_ERPAREN
+
+/* This data structure represents a compiled pattern. Before calling
+ the pattern compiler, the fields 'buffer', 'allocated', 'fastmap',
+ and 'translate' can be set. After the pattern has been compiled,
+ the fields 're_nsub', 'not_bol' and 'not_eol' are available. All
+ other fields are private to the regex routines. */
+
+#ifndef RE_TRANSLATE_TYPE
+# define __RE_TRANSLATE_TYPE unsigned char *
+# ifdef __USE_GNU
+# define RE_TRANSLATE_TYPE __RE_TRANSLATE_TYPE
+# endif
+#endif
+
+#ifdef __USE_GNU
+# define __REPB_PREFIX(name) name
+#else
+# define __REPB_PREFIX(name) __##name
+#endif
+
+struct re_pattern_buffer
+{
+ /* Space that holds the compiled pattern. The type
+ 'struct re_dfa_t' is private and is not declared here. */
+ struct re_dfa_t *__REPB_PREFIX(buffer);
+
+ /* Number of bytes to which 'buffer' points. */
+ __re_long_size_t __REPB_PREFIX(allocated);
+
+ /* Number of bytes actually used in 'buffer'. */
+ __re_long_size_t __REPB_PREFIX(used);
+
+ /* Syntax setting with which the pattern was compiled. */
+ reg_syntax_t __REPB_PREFIX(syntax);
+
+ /* Pointer to a fastmap, if any, otherwise zero. re_search uses the
+ fastmap, if there is one, to skip over impossible starting points
+ for matches. */
+ char *__REPB_PREFIX(fastmap);
+
+ /* Either a translate table to apply to all characters before
+ comparing them, or zero for no translation. The translation is
+ applied to a pattern when it is compiled and to a string when it
+ is matched. */
+ __RE_TRANSLATE_TYPE __REPB_PREFIX(translate);
+
+ /* Number of subexpressions found by the compiler. */
+ size_t re_nsub;
+
+ /* Zero if this pattern cannot match the empty string, one else.
+ Well, in truth it's used only in 're_search_2', to see whether or
+ not we should use the fastmap, so we don't set this absolutely
+ perfectly; see 're_compile_fastmap' (the "duplicate" case). */
+ unsigned __REPB_PREFIX(can_be_null) : 1;
+
+ /* If REGS_UNALLOCATED, allocate space in the 'regs' structure
+ for 'max (RE_NREGS, re_nsub + 1)' groups.
+ If REGS_REALLOCATE, reallocate space if necessary.
+ If REGS_FIXED, use what's there. */
+#ifdef __USE_GNU
+# define REGS_UNALLOCATED 0
+# define REGS_REALLOCATE 1
+# define REGS_FIXED 2
+#endif
+ unsigned __REPB_PREFIX(regs_allocated) : 2;
+
+ /* Set to zero when 're_compile_pattern' compiles a pattern; set to
+ one by 're_compile_fastmap' if it updates the fastmap. */
+ unsigned __REPB_PREFIX(fastmap_accurate) : 1;
+
+ /* If set, 're_match_2' does not return information about
+ subexpressions. */
+ unsigned __REPB_PREFIX(no_sub) : 1;
+
+ /* If set, a beginning-of-line anchor doesn't match at the beginning
+ of the string. */
+ unsigned __REPB_PREFIX(not_bol) : 1;
+
+ /* Similarly for an end-of-line anchor. */
+ unsigned __REPB_PREFIX(not_eol) : 1;
+
+ /* If true, an anchor at a newline matches. */
+ unsigned __REPB_PREFIX(newline_anchor) : 1;
+};
+
+typedef struct re_pattern_buffer regex_t;
+
+/* Type for byte offsets within the string. POSIX mandates this. */
+#ifdef _REGEX_LARGE_OFFSETS
+/* POSIX 1003.1-2008 requires that regoff_t be at least as wide as
+ ptrdiff_t and ssize_t. We don't know of any hosts where ptrdiff_t
+ is wider than ssize_t, so ssize_t is safe. ptrdiff_t is not
+ visible here, so use ssize_t. */
+typedef ssize_t regoff_t;
+#else
+/* The traditional GNU regex implementation mishandles strings longer
+ than INT_MAX. */
+typedef int regoff_t;
+#endif
+
+
+#ifdef __USE_GNU
+/* This is the structure we store register match data in. See
+ regex.texinfo for a full description of what registers match. */
+struct re_registers
+{
+ __re_size_t num_regs;
+ regoff_t *start;
+ regoff_t *end;
+};
+
+
+/* If 'regs_allocated' is REGS_UNALLOCATED in the pattern buffer,
+ 're_match_2' returns information about at least this many registers
+ the first time a 'regs' structure is passed. */
+# ifndef RE_NREGS
+# define RE_NREGS 30
+# endif
+#endif
+
+
+/* POSIX specification for registers. Aside from the different names than
+ 're_registers', POSIX uses an array of structures, instead of a
+ structure of arrays. */
+typedef struct
+{
+ regoff_t rm_so; /* Byte offset from string's start to substring's start. */
+ regoff_t rm_eo; /* Byte offset from string's start to substring's end. */
+} regmatch_t;
+
+/* Declarations for routines. */
+
+#ifndef _REGEX_NELTS
+# if (defined __STDC_VERSION__ && 199901L <= __STDC_VERSION__ \
+ && !defined __STDC_NO_VLA__)
+# define _REGEX_NELTS(n) n
+# else
+# define _REGEX_NELTS(n)
+# endif
+#endif
+
+#if defined __GNUC__ && 4 < __GNUC__ + (6 <= __GNUC_MINOR__)
+# pragma GCC diagnostic push
+# pragma GCC diagnostic ignored "-Wvla"
+#endif
+
+#ifndef _Attr_access_
+# ifdef __attr_access
+# define _Attr_access_(arg) __attr_access (arg)
+# elif defined __GNUC__ && 10 <= __GNUC__
+# define _Attr_access_(x) __attribute__ ((__access__ x))
+# else
+# define _Attr_access_(x)
+# endif
+#endif
+
+#ifdef __USE_GNU
+/* Sets the current default syntax to SYNTAX, and return the old syntax.
+ You can also simply assign to the 're_syntax_options' variable. */
+extern reg_syntax_t re_set_syntax (reg_syntax_t __syntax);
+
+/* Compile the regular expression PATTERN, with length LENGTH
+ and syntax given by the global 're_syntax_options', into the buffer
+ BUFFER. Return NULL if successful, and an error string if not.
+
+ To free the allocated storage, you must call 'regfree' on BUFFER.
+ Note that the translate table must either have been initialized by
+ 'regcomp', with a malloc'ed value, or set to NULL before calling
+ 'regfree'. */
+extern const char *re_compile_pattern (const char *__pattern, size_t __length,
+ struct re_pattern_buffer *__buffer)
+ _Attr_access_ ((__read_only__, 1, 2));
+
+
+/* Compile a fastmap for the compiled pattern in BUFFER; used to
+ accelerate searches. Return 0 if successful and -2 if was an
+ internal error. */
+extern int re_compile_fastmap (struct re_pattern_buffer *__buffer);
+
+
+/* Search in the string STRING (with length LENGTH) for the pattern
+ compiled into BUFFER. Start searching at position START, for RANGE
+ characters. Return the starting position of the match, -1 for no
+ match, or -2 for an internal error. Also return register
+ information in REGS (if REGS and BUFFER->no_sub are nonzero). */
+extern regoff_t re_search (struct re_pattern_buffer *__buffer,
+ const char *__String, regoff_t __length,
+ regoff_t __start, regoff_t __range,
+ struct re_registers *__regs)
+ _Attr_access_ ((__read_only__, 2, 3));
+
+
+/* Like 're_search', but search in the concatenation of STRING1 and
+ STRING2. Also, stop searching at index START + STOP. */
+extern regoff_t re_search_2 (struct re_pattern_buffer *__buffer,
+ const char *__string1, regoff_t __length1,
+ const char *__string2, regoff_t __length2,
+ regoff_t __start, regoff_t __range,
+ struct re_registers *__regs,
+ regoff_t __stop)
+ _Attr_access_ ((__read_only__, 2, 3))
+ _Attr_access_ ((__read_only__, 4, 5));
+
+
+/* Like 're_search', but return how many characters in STRING the regexp
+ in BUFFER matched, starting at position START. */
+extern regoff_t re_match (struct re_pattern_buffer *__buffer,
+ const char *__String, regoff_t __length,
+ regoff_t __start, struct re_registers *__regs)
+ _Attr_access_ ((__read_only__, 2, 3));
+
+
+/* Relates to 're_match' as 're_search_2' relates to 're_search'. */
+extern regoff_t re_match_2 (struct re_pattern_buffer *__buffer,
+ const char *__string1, regoff_t __length1,
+ const char *__string2, regoff_t __length2,
+ regoff_t __start, struct re_registers *__regs,
+ regoff_t __stop)
+ _Attr_access_ ((__read_only__, 2, 3))
+ _Attr_access_ ((__read_only__, 4, 5));
+
+
+/* Set REGS to hold NUM_REGS registers, storing them in STARTS and
+ ENDS. Subsequent matches using BUFFER and REGS will use this memory
+ for recording register information. STARTS and ENDS must be
+ allocated with malloc, and must each be at least 'NUM_REGS * sizeof
+ (regoff_t)' bytes long.
+
+ If NUM_REGS == 0, then subsequent matches should allocate their own
+ register data.
+
+ Unless this function is called, the first search or match using
+ BUFFER will allocate its own register data, without
+ freeing the old data. */
+extern void re_set_registers (struct re_pattern_buffer *__buffer,
+ struct re_registers *__regs,
+ __re_size_t __num_regs,
+ regoff_t *__starts, regoff_t *__ends);
+#endif /* Use GNU */
+
+#if defined _REGEX_RE_COMP || (defined _LIBC && defined __USE_MISC)
+/* 4.2 bsd compatibility. */
+extern char *re_comp (const char *);
+extern int re_exec (const char *);
+#endif
+
+/* For plain 'restrict', use glibc's __restrict if defined.
+ Otherwise, GCC 2.95 and later have "__restrict"; C99 compilers have
+ "restrict", and "configure" may have defined "restrict".
+ Other compilers use __restrict, __restrict__, and _Restrict, and
+ 'configure' might #define 'restrict' to those words, so pick a
+ different name. */
+#ifndef _Restrict_
+# if defined __restrict \
+ || 2 < __GNUC__ + (95 <= __GNUC_MINOR__) \
+ || __clang_major__ >= 3
+# define _Restrict_ __restrict
+# elif 199901L <= __STDC_VERSION__ || defined restrict
+# define _Restrict_ restrict
+# else
+# define _Restrict_
+# endif
+#endif
+/* For the ISO C99 syntax
+ array_name[restrict]
+ use glibc's __restrict_arr if available.
+ Otherwise, GCC 3.1 and clang support this syntax (but not in C++ mode).
+ Other ISO C99 compilers support it as well. */
+#ifndef _Restrict_arr_
+# ifdef __restrict_arr
+# define _Restrict_arr_ __restrict_arr
+# elif ((199901L <= __STDC_VERSION__ \
+ || 3 < __GNUC__ + (1 <= __GNUC_MINOR__) \
+ || __clang_major__ >= 3) \
+ && !defined __cplusplus)
+# define _Restrict_arr_ _Restrict_
+# else
+# define _Restrict_arr_
+# endif
+#endif
+
+/* POSIX compatibility. */
+extern int regcomp (regex_t *_Restrict_ __preg,
+ const char *_Restrict_ __pattern,
+ int __cflags);
+
+extern int regexec (const regex_t *_Restrict_ __preg,
+ const char *_Restrict_ __String, size_t __nmatch,
+ regmatch_t __pmatch[_Restrict_arr_
+ _REGEX_NELTS (__nmatch)],
+ int __eflags);
+
+extern size_t regerror (int __errcode, const regex_t *_Restrict_ __preg,
+ char *_Restrict_ __errbuf, size_t __errbuf_size)
+ _Attr_access_ ((__write_only__, 3, 4));
+
+extern void regfree (regex_t *__preg);
+
+#if defined __GNUC__ && 4 < __GNUC__ + (6 <= __GNUC_MINOR__)
+# pragma GCC diagnostic pop
+#endif
+
+#ifdef __cplusplus
+}
+#endif /* C++ */
+
+#endif /* regex.h */
diff --git a/lib/regex_internal.c b/lib/regex_internal.c
new file mode 100644
index 00000000000..0e6919f3400
--- /dev/null
+++ b/lib/regex_internal.c
@@ -0,0 +1,1711 @@
+/* Extended regular expression matching and search library.
+ Copyright (C) 2002-2022 Free Software Foundation, Inc.
+ This file is part of the GNU C Library.
+ Contributed by Isamu Hasegawa <isamu@yamato.ibm.com>.
+
+ The GNU C Library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Lesser General Public
+ License as published by the Free Software Foundation; either
+ version 2.1 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
+ Lesser General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public
+ License along with the GNU C Library; if not, see
+ <https://www.gnu.org/licenses/>. */
+
+static void re_string_construct_common (const char *str, Idx len,
+ re_string_t *pstr,
+ RE_TRANSLATE_TYPE trans, bool icase,
+ const re_dfa_t *dfa);
+static re_dfastate_t *create_ci_newstate (const re_dfa_t *dfa,
+ const re_node_set *nodes,
+ re_hashval_t hash);
+static re_dfastate_t *create_cd_newstate (const re_dfa_t *dfa,
+ const re_node_set *nodes,
+ unsigned int context,
+ re_hashval_t hash);
+static reg_errcode_t re_string_realloc_buffers (re_string_t *pstr,
+ Idx new_buf_len);
+static void build_wcs_buffer (re_string_t *pstr);
+static reg_errcode_t build_wcs_upper_buffer (re_string_t *pstr);
+static void build_upper_buffer (re_string_t *pstr);
+static void re_string_translate_buffer (re_string_t *pstr);
+static unsigned int re_string_context_at (const re_string_t *input, Idx idx,
+ int eflags) __attribute__ ((pure));
+
+/* Functions for string operation. */
+
+/* This function allocate the buffers. It is necessary to call
+ re_string_reconstruct before using the object. */
+
+static reg_errcode_t
+__attribute_warn_unused_result__
+re_string_allocate (re_string_t *pstr, const char *str, Idx len, Idx init_len,
+ RE_TRANSLATE_TYPE trans, bool icase, const re_dfa_t *dfa)
+{
+ reg_errcode_t ret;
+ Idx init_buf_len;
+
+ /* Ensure at least one character fits into the buffers. */
+ if (init_len < dfa->mb_cur_max)
+ init_len = dfa->mb_cur_max;
+ init_buf_len = (len + 1 < init_len) ? len + 1: init_len;
+ re_string_construct_common (str, len, pstr, trans, icase, dfa);
+
+ ret = re_string_realloc_buffers (pstr, init_buf_len);
+ if (__glibc_unlikely (ret != REG_NOERROR))
+ return ret;
+
+ pstr->word_char = dfa->word_char;
+ pstr->word_ops_used = dfa->word_ops_used;
+ pstr->mbs = pstr->mbs_allocated ? pstr->mbs : (unsigned char *) str;
+ pstr->valid_len = (pstr->mbs_allocated || dfa->mb_cur_max > 1) ? 0 : len;
+ pstr->valid_raw_len = pstr->valid_len;
+ return REG_NOERROR;
+}
+
+/* This function allocate the buffers, and initialize them. */
+
+static reg_errcode_t
+__attribute_warn_unused_result__
+re_string_construct (re_string_t *pstr, const char *str, Idx len,
+ RE_TRANSLATE_TYPE trans, bool icase, const re_dfa_t *dfa)
+{
+ reg_errcode_t ret;
+ memset (pstr, '\0', sizeof (re_string_t));
+ re_string_construct_common (str, len, pstr, trans, icase, dfa);
+
+ if (len > 0)
+ {
+ ret = re_string_realloc_buffers (pstr, len + 1);
+ if (__glibc_unlikely (ret != REG_NOERROR))
+ return ret;
+ }
+ pstr->mbs = pstr->mbs_allocated ? pstr->mbs : (unsigned char *) str;
+
+ if (icase)
+ {
+ if (dfa->mb_cur_max > 1)
+ {
+ while (1)
+ {
+ ret = build_wcs_upper_buffer (pstr);
+ if (__glibc_unlikely (ret != REG_NOERROR))
+ return ret;
+ if (pstr->valid_raw_len >= len)
+ break;
+ if (pstr->bufs_len > pstr->valid_len + dfa->mb_cur_max)
+ break;
+ ret = re_string_realloc_buffers (pstr, pstr->bufs_len * 2);
+ if (__glibc_unlikely (ret != REG_NOERROR))
+ return ret;
+ }
+ }
+ else
+ build_upper_buffer (pstr);
+ }
+ else
+ {
+ if (dfa->mb_cur_max > 1)
+ build_wcs_buffer (pstr);
+ else
+ {
+ if (trans != NULL)
+ re_string_translate_buffer (pstr);
+ else
+ {
+ pstr->valid_len = pstr->bufs_len;
+ pstr->valid_raw_len = pstr->bufs_len;
+ }
+ }
+ }
+
+ return REG_NOERROR;
+}
+
+/* Helper functions for re_string_allocate, and re_string_construct. */
+
+static reg_errcode_t
+__attribute_warn_unused_result__
+re_string_realloc_buffers (re_string_t *pstr, Idx new_buf_len)
+{
+ if (pstr->mb_cur_max > 1)
+ {
+ wint_t *new_wcs;
+
+ /* Avoid overflow in realloc. */
+ const size_t max_object_size = MAX (sizeof (wint_t), sizeof (Idx));
+ if (__glibc_unlikely (MIN (IDX_MAX, SIZE_MAX / max_object_size)
+ < new_buf_len))
+ return REG_ESPACE;
+
+ new_wcs = re_realloc (pstr->wcs, wint_t, new_buf_len);
+ if (__glibc_unlikely (new_wcs == NULL))
+ return REG_ESPACE;
+ pstr->wcs = new_wcs;
+ if (pstr->offsets != NULL)
+ {
+ Idx *new_offsets = re_realloc (pstr->offsets, Idx, new_buf_len);
+ if (__glibc_unlikely (new_offsets == NULL))
+ return REG_ESPACE;
+ pstr->offsets = new_offsets;
+ }
+ }
+ if (pstr->mbs_allocated)
+ {
+ unsigned char *new_mbs = re_realloc (pstr->mbs, unsigned char,
+ new_buf_len);
+ if (__glibc_unlikely (new_mbs == NULL))
+ return REG_ESPACE;
+ pstr->mbs = new_mbs;
+ }
+ pstr->bufs_len = new_buf_len;
+ return REG_NOERROR;
+}
+
+
+static void
+re_string_construct_common (const char *str, Idx len, re_string_t *pstr,
+ RE_TRANSLATE_TYPE trans, bool icase,
+ const re_dfa_t *dfa)
+{
+ pstr->raw_mbs = (const unsigned char *) str;
+ pstr->len = len;
+ pstr->raw_len = len;
+ pstr->trans = trans;
+ pstr->icase = icase;
+ pstr->mbs_allocated = (trans != NULL || icase);
+ pstr->mb_cur_max = dfa->mb_cur_max;
+ pstr->is_utf8 = dfa->is_utf8;
+ pstr->map_notascii = dfa->map_notascii;
+ pstr->stop = pstr->len;
+ pstr->raw_stop = pstr->stop;
+}
+
+
+/* Build wide character buffer PSTR->WCS.
+ If the byte sequence of the string are:
+ <mb1>(0), <mb1>(1), <mb2>(0), <mb2>(1), <sb3>
+ Then wide character buffer will be:
+ <wc1> , WEOF , <wc2> , WEOF , <wc3>
+ We use WEOF for padding, they indicate that the position isn't
+ a first byte of a multibyte character.
+
+ Note that this function assumes PSTR->VALID_LEN elements are already
+ built and starts from PSTR->VALID_LEN. */
+
+static void
+build_wcs_buffer (re_string_t *pstr)
+{
+#ifdef _LIBC
+ unsigned char buf[MB_LEN_MAX];
+ DEBUG_ASSERT (MB_LEN_MAX >= pstr->mb_cur_max);
+#else
+ unsigned char buf[64];
+#endif
+ mbstate_t prev_st;
+ Idx byte_idx, end_idx, remain_len;
+ size_t mbclen;
+
+ /* Build the buffers from pstr->valid_len to either pstr->len or
+ pstr->bufs_len. */
+ end_idx = (pstr->bufs_len > pstr->len) ? pstr->len : pstr->bufs_len;
+ for (byte_idx = pstr->valid_len; byte_idx < end_idx;)
+ {
+ wchar_t wc;
+ const char *p;
+
+ remain_len = end_idx - byte_idx;
+ prev_st = pstr->cur_state;
+ /* Apply the translation if we need. */
+ if (__glibc_unlikely (pstr->trans != NULL))
+ {
+ int i, ch;
+
+ for (i = 0; i < pstr->mb_cur_max && i < remain_len; ++i)
+ {
+ ch = pstr->raw_mbs [pstr->raw_mbs_idx + byte_idx + i];
+ buf[i] = pstr->mbs[byte_idx + i] = pstr->trans[ch];
+ }
+ p = (const char *) buf;
+ }
+ else
+ p = (const char *) pstr->raw_mbs + pstr->raw_mbs_idx + byte_idx;
+ mbclen = __mbrtowc (&wc, p, remain_len, &pstr->cur_state);
+ if (__glibc_unlikely (mbclen == (size_t) -1 || mbclen == 0
+ || (mbclen == (size_t) -2
+ && pstr->bufs_len >= pstr->len)))
+ {
+ /* We treat these cases as a singlebyte character. */
+ mbclen = 1;
+ wc = (wchar_t) pstr->raw_mbs[pstr->raw_mbs_idx + byte_idx];
+ if (__glibc_unlikely (pstr->trans != NULL))
+ wc = pstr->trans[wc];
+ pstr->cur_state = prev_st;
+ }
+ else if (__glibc_unlikely (mbclen == (size_t) -2))
+ {
+ /* The buffer doesn't have enough space, finish to build. */
+ pstr->cur_state = prev_st;
+ break;
+ }
+
+ /* Write wide character and padding. */
+ pstr->wcs[byte_idx++] = wc;
+ /* Write paddings. */
+ for (remain_len = byte_idx + mbclen - 1; byte_idx < remain_len ;)
+ pstr->wcs[byte_idx++] = WEOF;
+ }
+ pstr->valid_len = byte_idx;
+ pstr->valid_raw_len = byte_idx;
+}
+
+/* Build wide character buffer PSTR->WCS like build_wcs_buffer,
+ but for REG_ICASE. */
+
+static reg_errcode_t
+__attribute_warn_unused_result__
+build_wcs_upper_buffer (re_string_t *pstr)
+{
+ mbstate_t prev_st;
+ Idx src_idx, byte_idx, end_idx, remain_len;
+ size_t mbclen;
+#ifdef _LIBC
+ char buf[MB_LEN_MAX];
+ DEBUG_ASSERT (pstr->mb_cur_max <= MB_LEN_MAX);
+#else
+ char buf[64];
+#endif
+
+ byte_idx = pstr->valid_len;
+ end_idx = (pstr->bufs_len > pstr->len) ? pstr->len : pstr->bufs_len;
+
+ /* The following optimization assumes that ASCII characters can be
+ mapped to wide characters with a simple cast. */
+ if (! pstr->map_notascii && pstr->trans == NULL && !pstr->offsets_needed)
+ {
+ while (byte_idx < end_idx)
+ {
+ wchar_t wc;
+ unsigned char ch = pstr->raw_mbs[pstr->raw_mbs_idx + byte_idx];
+
+ if (isascii (ch) && mbsinit (&pstr->cur_state))
+ {
+ /* The next step uses the assumption that wchar_t is encoded
+ ASCII-safe: all ASCII values can be converted like this. */
+ wchar_t wcu = __towupper (ch);
+ if (isascii (wcu))
+ {
+ pstr->mbs[byte_idx] = wcu;
+ pstr->wcs[byte_idx] = wcu;
+ byte_idx++;
+ continue;
+ }
+ }
+
+ remain_len = end_idx - byte_idx;
+ prev_st = pstr->cur_state;
+ mbclen = __mbrtowc (&wc,
+ ((const char *) pstr->raw_mbs + pstr->raw_mbs_idx
+ + byte_idx), remain_len, &pstr->cur_state);
+ if (__glibc_likely (0 < mbclen && mbclen < (size_t) -2))
+ {
+ wchar_t wcu = __towupper (wc);
+ if (wcu != wc)
+ {
+ size_t mbcdlen;
+
+ mbcdlen = __wcrtomb (buf, wcu, &prev_st);
+ if (__glibc_likely (mbclen == mbcdlen))
+ memcpy (pstr->mbs + byte_idx, buf, mbclen);
+ else
+ {
+ src_idx = byte_idx;
+ goto offsets_needed;
+ }
+ }
+ else
+ memcpy (pstr->mbs + byte_idx,
+ pstr->raw_mbs + pstr->raw_mbs_idx + byte_idx, mbclen);
+ pstr->wcs[byte_idx++] = wcu;
+ /* Write paddings. */
+ for (remain_len = byte_idx + mbclen - 1; byte_idx < remain_len ;)
+ pstr->wcs[byte_idx++] = WEOF;
+ }
+ else if (mbclen == (size_t) -1 || mbclen == 0
+ || (mbclen == (size_t) -2 && pstr->bufs_len >= pstr->len))
+ {
+ /* It is an invalid character, an incomplete character
+ at the end of the string, or '\0'. Just use the byte. */
+ pstr->mbs[byte_idx] = ch;
+ /* And also cast it to wide char. */
+ pstr->wcs[byte_idx++] = (wchar_t) ch;
+ if (__glibc_unlikely (mbclen == (size_t) -1))
+ pstr->cur_state = prev_st;
+ }
+ else
+ {
+ /* The buffer doesn't have enough space, finish to build. */
+ pstr->cur_state = prev_st;
+ break;
+ }
+ }
+ pstr->valid_len = byte_idx;
+ pstr->valid_raw_len = byte_idx;
+ return REG_NOERROR;
+ }
+ else
+ for (src_idx = pstr->valid_raw_len; byte_idx < end_idx;)
+ {
+ wchar_t wc;
+ const char *p;
+ offsets_needed:
+ remain_len = end_idx - byte_idx;
+ prev_st = pstr->cur_state;
+ if (__glibc_unlikely (pstr->trans != NULL))
+ {
+ int i, ch;
+
+ for (i = 0; i < pstr->mb_cur_max && i < remain_len; ++i)
+ {
+ ch = pstr->raw_mbs [pstr->raw_mbs_idx + src_idx + i];
+ buf[i] = pstr->trans[ch];
+ }
+ p = (const char *) buf;
+ }
+ else
+ p = (const char *) pstr->raw_mbs + pstr->raw_mbs_idx + src_idx;
+ mbclen = __mbrtowc (&wc, p, remain_len, &pstr->cur_state);
+ if (__glibc_likely (0 < mbclen && mbclen < (size_t) -2))
+ {
+ wchar_t wcu = __towupper (wc);
+ if (wcu != wc)
+ {
+ size_t mbcdlen;
+
+ mbcdlen = __wcrtomb ((char *) buf, wcu, &prev_st);
+ if (__glibc_likely (mbclen == mbcdlen))
+ memcpy (pstr->mbs + byte_idx, buf, mbclen);
+ else if (mbcdlen != (size_t) -1)
+ {
+ size_t i;
+
+ if (byte_idx + mbcdlen > pstr->bufs_len)
+ {
+ pstr->cur_state = prev_st;
+ break;
+ }
+
+ if (pstr->offsets == NULL)
+ {
+ pstr->offsets = re_malloc (Idx, pstr->bufs_len);
+
+ if (pstr->offsets == NULL)
+ return REG_ESPACE;
+ }
+ if (!pstr->offsets_needed)
+ {
+ for (i = 0; i < (size_t) byte_idx; ++i)
+ pstr->offsets[i] = i;
+ pstr->offsets_needed = 1;
+ }
+
+ memcpy (pstr->mbs + byte_idx, buf, mbcdlen);
+ pstr->wcs[byte_idx] = wcu;
+ pstr->offsets[byte_idx] = src_idx;
+ for (i = 1; i < mbcdlen; ++i)
+ {
+ pstr->offsets[byte_idx + i]
+ = src_idx + (i < mbclen ? i : mbclen - 1);
+ pstr->wcs[byte_idx + i] = WEOF;
+ }
+ pstr->len += mbcdlen - mbclen;
+ if (pstr->raw_stop > src_idx)
+ pstr->stop += mbcdlen - mbclen;
+ end_idx = (pstr->bufs_len > pstr->len)
+ ? pstr->len : pstr->bufs_len;
+ byte_idx += mbcdlen;
+ src_idx += mbclen;
+ continue;
+ }
+ else
+ memcpy (pstr->mbs + byte_idx, p, mbclen);
+ }
+ else
+ memcpy (pstr->mbs + byte_idx, p, mbclen);
+
+ if (__glibc_unlikely (pstr->offsets_needed != 0))
+ {
+ size_t i;
+ for (i = 0; i < mbclen; ++i)
+ pstr->offsets[byte_idx + i] = src_idx + i;
+ }
+ src_idx += mbclen;
+
+ pstr->wcs[byte_idx++] = wcu;
+ /* Write paddings. */
+ for (remain_len = byte_idx + mbclen - 1; byte_idx < remain_len ;)
+ pstr->wcs[byte_idx++] = WEOF;
+ }
+ else if (mbclen == (size_t) -1 || mbclen == 0
+ || (mbclen == (size_t) -2 && pstr->bufs_len >= pstr->len))
+ {
+ /* It is an invalid character or '\0'. Just use the byte. */
+ int ch = pstr->raw_mbs[pstr->raw_mbs_idx + src_idx];
+
+ if (__glibc_unlikely (pstr->trans != NULL))
+ ch = pstr->trans [ch];
+ pstr->mbs[byte_idx] = ch;
+
+ if (__glibc_unlikely (pstr->offsets_needed != 0))
+ pstr->offsets[byte_idx] = src_idx;
+ ++src_idx;
+
+ /* And also cast it to wide char. */
+ pstr->wcs[byte_idx++] = (wchar_t) ch;
+ if (__glibc_unlikely (mbclen == (size_t) -1))
+ pstr->cur_state = prev_st;
+ }
+ else
+ {
+ /* The buffer doesn't have enough space, finish to build. */
+ pstr->cur_state = prev_st;
+ break;
+ }
+ }
+ pstr->valid_len = byte_idx;
+ pstr->valid_raw_len = src_idx;
+ return REG_NOERROR;
+}
+
+/* Skip characters until the index becomes greater than NEW_RAW_IDX.
+ Return the index. */
+
+static Idx
+re_string_skip_chars (re_string_t *pstr, Idx new_raw_idx, wint_t *last_wc)
+{
+ mbstate_t prev_st;
+ Idx rawbuf_idx;
+ size_t mbclen;
+ wint_t wc = WEOF;
+
+ /* Skip the characters which are not necessary to check. */
+ for (rawbuf_idx = pstr->raw_mbs_idx + pstr->valid_raw_len;
+ rawbuf_idx < new_raw_idx;)
+ {
+ wchar_t wc2;
+ Idx remain_len = pstr->raw_len - rawbuf_idx;
+ prev_st = pstr->cur_state;
+ mbclen = __mbrtowc (&wc2, (const char *) pstr->raw_mbs + rawbuf_idx,
+ remain_len, &pstr->cur_state);
+ if (__glibc_unlikely (mbclen == (size_t) -2 || mbclen == (size_t) -1
+ || mbclen == 0))
+ {
+ /* We treat these cases as a single byte character. */
+ if (mbclen == 0 || remain_len == 0)
+ wc = L'\0';
+ else
+ wc = *(unsigned char *) (pstr->raw_mbs + rawbuf_idx);
+ mbclen = 1;
+ pstr->cur_state = prev_st;
+ }
+ else
+ wc = wc2;
+ /* Then proceed the next character. */
+ rawbuf_idx += mbclen;
+ }
+ *last_wc = wc;
+ return rawbuf_idx;
+}
+
+/* Build the buffer PSTR->MBS, and apply the translation if we need.
+ This function is used in case of REG_ICASE. */
+
+static void
+build_upper_buffer (re_string_t *pstr)
+{
+ Idx char_idx, end_idx;
+ end_idx = (pstr->bufs_len > pstr->len) ? pstr->len : pstr->bufs_len;
+
+ for (char_idx = pstr->valid_len; char_idx < end_idx; ++char_idx)
+ {
+ int ch = pstr->raw_mbs[pstr->raw_mbs_idx + char_idx];
+ if (__glibc_unlikely (pstr->trans != NULL))
+ ch = pstr->trans[ch];
+ pstr->mbs[char_idx] = toupper (ch);
+ }
+ pstr->valid_len = char_idx;
+ pstr->valid_raw_len = char_idx;
+}
+
+/* Apply TRANS to the buffer in PSTR. */
+
+static void
+re_string_translate_buffer (re_string_t *pstr)
+{
+ Idx buf_idx, end_idx;
+ end_idx = (pstr->bufs_len > pstr->len) ? pstr->len : pstr->bufs_len;
+
+ for (buf_idx = pstr->valid_len; buf_idx < end_idx; ++buf_idx)
+ {
+ int ch = pstr->raw_mbs[pstr->raw_mbs_idx + buf_idx];
+ pstr->mbs[buf_idx] = pstr->trans[ch];
+ }
+
+ pstr->valid_len = buf_idx;
+ pstr->valid_raw_len = buf_idx;
+}
+
+/* This function re-construct the buffers.
+ Concretely, convert to wide character in case of pstr->mb_cur_max > 1,
+ convert to upper case in case of REG_ICASE, apply translation. */
+
+static reg_errcode_t
+__attribute_warn_unused_result__
+re_string_reconstruct (re_string_t *pstr, Idx idx, int eflags)
+{
+ Idx offset;
+
+ if (__glibc_unlikely (pstr->raw_mbs_idx <= idx))
+ offset = idx - pstr->raw_mbs_idx;
+ else
+ {
+ /* Reset buffer. */
+ if (pstr->mb_cur_max > 1)
+ memset (&pstr->cur_state, '\0', sizeof (mbstate_t));
+ pstr->len = pstr->raw_len;
+ pstr->stop = pstr->raw_stop;
+ pstr->valid_len = 0;
+ pstr->raw_mbs_idx = 0;
+ pstr->valid_raw_len = 0;
+ pstr->offsets_needed = 0;
+ pstr->tip_context = ((eflags & REG_NOTBOL) ? CONTEXT_BEGBUF
+ : CONTEXT_NEWLINE | CONTEXT_BEGBUF);
+ if (!pstr->mbs_allocated)
+ pstr->mbs = (unsigned char *) pstr->raw_mbs;
+ offset = idx;
+ }
+
+ if (__glibc_likely (offset != 0))
+ {
+ /* Should the already checked characters be kept? */
+ if (__glibc_likely (offset < pstr->valid_raw_len))
+ {
+ /* Yes, move them to the front of the buffer. */
+ if (__glibc_unlikely (pstr->offsets_needed))
+ {
+ Idx low = 0, high = pstr->valid_len, mid;
+ do
+ {
+ mid = (high + low) / 2;
+ if (pstr->offsets[mid] > offset)
+ high = mid;
+ else if (pstr->offsets[mid] < offset)
+ low = mid + 1;
+ else
+ break;
+ }
+ while (low < high);
+ if (pstr->offsets[mid] < offset)
+ ++mid;
+ pstr->tip_context = re_string_context_at (pstr, mid - 1,
+ eflags);
+ /* This can be quite complicated, so handle specially
+ only the common and easy case where the character with
+ different length representation of lower and upper
+ case is present at or after offset. */
+ if (pstr->valid_len > offset
+ && mid == offset && pstr->offsets[mid] == offset)
+ {
+ memmove (pstr->wcs, pstr->wcs + offset,
+ (pstr->valid_len - offset) * sizeof (wint_t));
+ memmove (pstr->mbs, pstr->mbs + offset, pstr->valid_len - offset);
+ pstr->valid_len -= offset;
+ pstr->valid_raw_len -= offset;
+ for (low = 0; low < pstr->valid_len; low++)
+ pstr->offsets[low] = pstr->offsets[low + offset] - offset;
+ }
+ else
+ {
+ /* Otherwise, just find out how long the partial multibyte
+ character at offset is and fill it with WEOF/255. */
+ pstr->len = pstr->raw_len - idx + offset;
+ pstr->stop = pstr->raw_stop - idx + offset;
+ pstr->offsets_needed = 0;
+ while (mid > 0 && pstr->offsets[mid - 1] == offset)
+ --mid;
+ while (mid < pstr->valid_len)
+ if (pstr->wcs[mid] != WEOF)
+ break;
+ else
+ ++mid;
+ if (mid == pstr->valid_len)
+ pstr->valid_len = 0;
+ else
+ {
+ pstr->valid_len = pstr->offsets[mid] - offset;
+ if (pstr->valid_len)
+ {
+ for (low = 0; low < pstr->valid_len; ++low)
+ pstr->wcs[low] = WEOF;
+ memset (pstr->mbs, 255, pstr->valid_len);
+ }
+ }
+ pstr->valid_raw_len = pstr->valid_len;
+ }
+ }
+ else
+ {
+ pstr->tip_context = re_string_context_at (pstr, offset - 1,
+ eflags);
+ if (pstr->mb_cur_max > 1)
+ memmove (pstr->wcs, pstr->wcs + offset,
+ (pstr->valid_len - offset) * sizeof (wint_t));
+ if (__glibc_unlikely (pstr->mbs_allocated))
+ memmove (pstr->mbs, pstr->mbs + offset,
+ pstr->valid_len - offset);
+ pstr->valid_len -= offset;
+ pstr->valid_raw_len -= offset;
+ DEBUG_ASSERT (pstr->valid_len > 0);
+ }
+ }
+ else
+ {
+ /* No, skip all characters until IDX. */
+ Idx prev_valid_len = pstr->valid_len;
+
+ if (__glibc_unlikely (pstr->offsets_needed))
+ {
+ pstr->len = pstr->raw_len - idx + offset;
+ pstr->stop = pstr->raw_stop - idx + offset;
+ pstr->offsets_needed = 0;
+ }
+ pstr->valid_len = 0;
+ if (pstr->mb_cur_max > 1)
+ {
+ Idx wcs_idx;
+ wint_t wc = WEOF;
+
+ if (pstr->is_utf8)
+ {
+ const unsigned char *raw, *p, *end;
+
+ /* Special case UTF-8. Multi-byte chars start with any
+ byte other than 0x80 - 0xbf. */
+ raw = pstr->raw_mbs + pstr->raw_mbs_idx;
+ end = raw + (offset - pstr->mb_cur_max);
+ if (end < pstr->raw_mbs)
+ end = pstr->raw_mbs;
+ p = raw + offset - 1;
+#ifdef _LIBC
+ /* We know the wchar_t encoding is UCS4, so for the simple
+ case, ASCII characters, skip the conversion step. */
+ if (isascii (*p) && __glibc_likely (pstr->trans == NULL))
+ {
+ memset (&pstr->cur_state, '\0', sizeof (mbstate_t));
+ /* pstr->valid_len = 0; */
+ wc = (wchar_t) *p;
+ }
+ else
+#endif
+ for (; p >= end; --p)
+ if ((*p & 0xc0) != 0x80)
+ {
+ mbstate_t cur_state;
+ wchar_t wc2;
+ Idx mlen = raw + pstr->len - p;
+ unsigned char buf[6];
+ size_t mbclen;
+
+ const unsigned char *pp = p;
+ if (__glibc_unlikely (pstr->trans != NULL))
+ {
+ int i = mlen < 6 ? mlen : 6;
+ while (--i >= 0)
+ buf[i] = pstr->trans[p[i]];
+ pp = buf;
+ }
+ /* XXX Don't use mbrtowc, we know which conversion
+ to use (UTF-8 -> UCS4). */
+ memset (&cur_state, 0, sizeof (cur_state));
+ mbclen = __mbrtowc (&wc2, (const char *) pp, mlen,
+ &cur_state);
+ if (raw + offset - p <= mbclen
+ && mbclen < (size_t) -2)
+ {
+ memset (&pstr->cur_state, '\0',
+ sizeof (mbstate_t));
+ pstr->valid_len = mbclen - (raw + offset - p);
+ wc = wc2;
+ }
+ break;
+ }
+ }
+
+ if (wc == WEOF)
+ pstr->valid_len = re_string_skip_chars (pstr, idx, &wc) - idx;
+ if (wc == WEOF)
+ pstr->tip_context
+ = re_string_context_at (pstr, prev_valid_len - 1, eflags);
+ else
+ pstr->tip_context = ((__glibc_unlikely (pstr->word_ops_used != 0)
+ && IS_WIDE_WORD_CHAR (wc))
+ ? CONTEXT_WORD
+ : ((IS_WIDE_NEWLINE (wc)
+ && pstr->newline_anchor)
+ ? CONTEXT_NEWLINE : 0));
+ if (__glibc_unlikely (pstr->valid_len))
+ {
+ for (wcs_idx = 0; wcs_idx < pstr->valid_len; ++wcs_idx)
+ pstr->wcs[wcs_idx] = WEOF;
+ if (pstr->mbs_allocated)
+ memset (pstr->mbs, 255, pstr->valid_len);
+ }
+ pstr->valid_raw_len = pstr->valid_len;
+ }
+ else
+ {
+ int c = pstr->raw_mbs[pstr->raw_mbs_idx + offset - 1];
+ pstr->valid_raw_len = 0;
+ if (pstr->trans)
+ c = pstr->trans[c];
+ pstr->tip_context = (bitset_contain (pstr->word_char, c)
+ ? CONTEXT_WORD
+ : ((IS_NEWLINE (c) && pstr->newline_anchor)
+ ? CONTEXT_NEWLINE : 0));
+ }
+ }
+ if (!__glibc_unlikely (pstr->mbs_allocated))
+ pstr->mbs += offset;
+ }
+ pstr->raw_mbs_idx = idx;
+ pstr->len -= offset;
+ pstr->stop -= offset;
+
+ /* Then build the buffers. */
+ if (pstr->mb_cur_max > 1)
+ {
+ if (pstr->icase)
+ {
+ reg_errcode_t ret = build_wcs_upper_buffer (pstr);
+ if (__glibc_unlikely (ret != REG_NOERROR))
+ return ret;
+ }
+ else
+ build_wcs_buffer (pstr);
+ }
+ else
+ if (__glibc_unlikely (pstr->mbs_allocated))
+ {
+ if (pstr->icase)
+ build_upper_buffer (pstr);
+ else if (pstr->trans != NULL)
+ re_string_translate_buffer (pstr);
+ }
+ else
+ pstr->valid_len = pstr->len;
+
+ pstr->cur_idx = 0;
+ return REG_NOERROR;
+}
+
+static unsigned char
+__attribute__ ((pure))
+re_string_peek_byte_case (const re_string_t *pstr, Idx idx)
+{
+ int ch;
+ Idx off;
+
+ /* Handle the common (easiest) cases first. */
+ if (__glibc_likely (!pstr->mbs_allocated))
+ return re_string_peek_byte (pstr, idx);
+
+ if (pstr->mb_cur_max > 1
+ && ! re_string_is_single_byte_char (pstr, pstr->cur_idx + idx))
+ return re_string_peek_byte (pstr, idx);
+
+ off = pstr->cur_idx + idx;
+ if (pstr->offsets_needed)
+ off = pstr->offsets[off];
+
+ ch = pstr->raw_mbs[pstr->raw_mbs_idx + off];
+
+ /* Ensure that e.g. for tr_TR.UTF-8 BACKSLASH DOTLESS SMALL LETTER I
+ this function returns CAPITAL LETTER I instead of first byte of
+ DOTLESS SMALL LETTER I. The latter would confuse the parser,
+ since peek_byte_case doesn't advance cur_idx in any way. */
+ if (pstr->offsets_needed && !isascii (ch))
+ return re_string_peek_byte (pstr, idx);
+
+ return ch;
+}
+
+static unsigned char
+re_string_fetch_byte_case (re_string_t *pstr)
+{
+ if (__glibc_likely (!pstr->mbs_allocated))
+ return re_string_fetch_byte (pstr);
+
+ if (pstr->offsets_needed)
+ {
+ Idx off;
+ int ch;
+
+ /* For tr_TR.UTF-8 [[:islower:]] there is
+ [[: CAPITAL LETTER I WITH DOT lower:]] in mbs. Skip
+ in that case the whole multi-byte character and return
+ the original letter. On the other side, with
+ [[: DOTLESS SMALL LETTER I return [[:I, as doing
+ anything else would complicate things too much. */
+
+ if (!re_string_first_byte (pstr, pstr->cur_idx))
+ return re_string_fetch_byte (pstr);
+
+ off = pstr->offsets[pstr->cur_idx];
+ ch = pstr->raw_mbs[pstr->raw_mbs_idx + off];
+
+ if (! isascii (ch))
+ return re_string_fetch_byte (pstr);
+
+ re_string_skip_bytes (pstr,
+ re_string_char_size_at (pstr, pstr->cur_idx));
+ return ch;
+ }
+
+ return pstr->raw_mbs[pstr->raw_mbs_idx + pstr->cur_idx++];
+}
+
+static void
+re_string_destruct (re_string_t *pstr)
+{
+ re_free (pstr->wcs);
+ re_free (pstr->offsets);
+ if (pstr->mbs_allocated)
+ re_free (pstr->mbs);
+}
+
+/* Return the context at IDX in INPUT. */
+
+static unsigned int
+re_string_context_at (const re_string_t *input, Idx idx, int eflags)
+{
+ int c;
+ if (__glibc_unlikely (idx < 0))
+ /* In this case, we use the value stored in input->tip_context,
+ since we can't know the character in input->mbs[-1] here. */
+ return input->tip_context;
+ if (__glibc_unlikely (idx == input->len))
+ return ((eflags & REG_NOTEOL) ? CONTEXT_ENDBUF
+ : CONTEXT_NEWLINE | CONTEXT_ENDBUF);
+ if (input->mb_cur_max > 1)
+ {
+ wint_t wc;
+ Idx wc_idx = idx;
+ while(input->wcs[wc_idx] == WEOF)
+ {
+ DEBUG_ASSERT (wc_idx >= 0);
+ --wc_idx;
+ if (wc_idx < 0)
+ return input->tip_context;
+ }
+ wc = input->wcs[wc_idx];
+ if (__glibc_unlikely (input->word_ops_used != 0)
+ && IS_WIDE_WORD_CHAR (wc))
+ return CONTEXT_WORD;
+ return (IS_WIDE_NEWLINE (wc) && input->newline_anchor
+ ? CONTEXT_NEWLINE : 0);
+ }
+ else
+ {
+ c = re_string_byte_at (input, idx);
+ if (bitset_contain (input->word_char, c))
+ return CONTEXT_WORD;
+ return IS_NEWLINE (c) && input->newline_anchor ? CONTEXT_NEWLINE : 0;
+ }
+}
+
+/* Functions for set operation. */
+
+static reg_errcode_t
+__attribute_warn_unused_result__
+re_node_set_alloc (re_node_set *set, Idx size)
+{
+ set->alloc = size;
+ set->nelem = 0;
+ set->elems = re_malloc (Idx, size);
+ if (__glibc_unlikely (set->elems == NULL)
+ && (MALLOC_0_IS_NONNULL || size != 0))
+ return REG_ESPACE;
+ return REG_NOERROR;
+}
+
+static reg_errcode_t
+__attribute_warn_unused_result__
+re_node_set_init_1 (re_node_set *set, Idx elem)
+{
+ set->alloc = 1;
+ set->nelem = 1;
+ set->elems = re_malloc (Idx, 1);
+ if (__glibc_unlikely (set->elems == NULL))
+ {
+ set->alloc = set->nelem = 0;
+ return REG_ESPACE;
+ }
+ set->elems[0] = elem;
+ return REG_NOERROR;
+}
+
+static reg_errcode_t
+__attribute_warn_unused_result__
+re_node_set_init_2 (re_node_set *set, Idx elem1, Idx elem2)
+{
+ set->alloc = 2;
+ set->elems = re_malloc (Idx, 2);
+ if (__glibc_unlikely (set->elems == NULL))
+ return REG_ESPACE;
+ if (elem1 == elem2)
+ {
+ set->nelem = 1;
+ set->elems[0] = elem1;
+ }
+ else
+ {
+ set->nelem = 2;
+ if (elem1 < elem2)
+ {
+ set->elems[0] = elem1;
+ set->elems[1] = elem2;
+ }
+ else
+ {
+ set->elems[0] = elem2;
+ set->elems[1] = elem1;
+ }
+ }
+ return REG_NOERROR;
+}
+
+static reg_errcode_t
+__attribute_warn_unused_result__
+re_node_set_init_copy (re_node_set *dest, const re_node_set *src)
+{
+ dest->nelem = src->nelem;
+ if (src->nelem > 0)
+ {
+ dest->alloc = dest->nelem;
+ dest->elems = re_malloc (Idx, dest->alloc);
+ if (__glibc_unlikely (dest->elems == NULL))
+ {
+ dest->alloc = dest->nelem = 0;
+ return REG_ESPACE;
+ }
+ memcpy (dest->elems, src->elems, src->nelem * sizeof (Idx));
+ }
+ else
+ re_node_set_init_empty (dest);
+ return REG_NOERROR;
+}
+
+/* Calculate the intersection of the sets SRC1 and SRC2. And merge it to
+ DEST. Return value indicate the error code or REG_NOERROR if succeeded.
+ Note: We assume dest->elems is NULL, when dest->alloc is 0. */
+
+static reg_errcode_t
+__attribute_warn_unused_result__
+re_node_set_add_intersect (re_node_set *dest, const re_node_set *src1,
+ const re_node_set *src2)
+{
+ Idx i1, i2, is, id, delta, sbase;
+ if (src1->nelem == 0 || src2->nelem == 0)
+ return REG_NOERROR;
+
+ /* We need dest->nelem + 2 * elems_in_intersection; this is a
+ conservative estimate. */
+ if (src1->nelem + src2->nelem + dest->nelem > dest->alloc)
+ {
+ Idx new_alloc = src1->nelem + src2->nelem + dest->alloc;
+ Idx *new_elems = re_realloc (dest->elems, Idx, new_alloc);
+ if (__glibc_unlikely (new_elems == NULL))
+ return REG_ESPACE;
+ dest->elems = new_elems;
+ dest->alloc = new_alloc;
+ }
+
+ /* Find the items in the intersection of SRC1 and SRC2, and copy
+ into the top of DEST those that are not already in DEST itself. */
+ sbase = dest->nelem + src1->nelem + src2->nelem;
+ i1 = src1->nelem - 1;
+ i2 = src2->nelem - 1;
+ id = dest->nelem - 1;
+ for (;;)
+ {
+ if (src1->elems[i1] == src2->elems[i2])
+ {
+ /* Try to find the item in DEST. Maybe we could binary search? */
+ while (id >= 0 && dest->elems[id] > src1->elems[i1])
+ --id;
+
+ if (id < 0 || dest->elems[id] != src1->elems[i1])
+ dest->elems[--sbase] = src1->elems[i1];
+
+ if (--i1 < 0 || --i2 < 0)
+ break;
+ }
+
+ /* Lower the highest of the two items. */
+ else if (src1->elems[i1] < src2->elems[i2])
+ {
+ if (--i2 < 0)
+ break;
+ }
+ else
+ {
+ if (--i1 < 0)
+ break;
+ }
+ }
+
+ id = dest->nelem - 1;
+ is = dest->nelem + src1->nelem + src2->nelem - 1;
+ delta = is - sbase + 1;
+
+ /* Now copy. When DELTA becomes zero, the remaining
+ DEST elements are already in place; this is more or
+ less the same loop that is in re_node_set_merge. */
+ dest->nelem += delta;
+ if (delta > 0 && id >= 0)
+ for (;;)
+ {
+ if (dest->elems[is] > dest->elems[id])
+ {
+ /* Copy from the top. */
+ dest->elems[id + delta--] = dest->elems[is--];
+ if (delta == 0)
+ break;
+ }
+ else
+ {
+ /* Slide from the bottom. */
+ dest->elems[id + delta] = dest->elems[id];
+ if (--id < 0)
+ break;
+ }
+ }
+
+ /* Copy remaining SRC elements. */
+ memcpy (dest->elems, dest->elems + sbase, delta * sizeof (Idx));
+
+ return REG_NOERROR;
+}
+
+/* Calculate the union set of the sets SRC1 and SRC2. And store it to
+ DEST. Return value indicate the error code or REG_NOERROR if succeeded. */
+
+static reg_errcode_t
+__attribute_warn_unused_result__
+re_node_set_init_union (re_node_set *dest, const re_node_set *src1,
+ const re_node_set *src2)
+{
+ Idx i1, i2, id;
+ if (src1 != NULL && src1->nelem > 0 && src2 != NULL && src2->nelem > 0)
+ {
+ dest->alloc = src1->nelem + src2->nelem;
+ dest->elems = re_malloc (Idx, dest->alloc);
+ if (__glibc_unlikely (dest->elems == NULL))
+ return REG_ESPACE;
+ }
+ else
+ {
+ if (src1 != NULL && src1->nelem > 0)
+ return re_node_set_init_copy (dest, src1);
+ else if (src2 != NULL && src2->nelem > 0)
+ return re_node_set_init_copy (dest, src2);
+ else
+ re_node_set_init_empty (dest);
+ return REG_NOERROR;
+ }
+ for (i1 = i2 = id = 0 ; i1 < src1->nelem && i2 < src2->nelem ;)
+ {
+ if (src1->elems[i1] > src2->elems[i2])
+ {
+ dest->elems[id++] = src2->elems[i2++];
+ continue;
+ }
+ if (src1->elems[i1] == src2->elems[i2])
+ ++i2;
+ dest->elems[id++] = src1->elems[i1++];
+ }
+ if (i1 < src1->nelem)
+ {
+ memcpy (dest->elems + id, src1->elems + i1,
+ (src1->nelem - i1) * sizeof (Idx));
+ id += src1->nelem - i1;
+ }
+ else if (i2 < src2->nelem)
+ {
+ memcpy (dest->elems + id, src2->elems + i2,
+ (src2->nelem - i2) * sizeof (Idx));
+ id += src2->nelem - i2;
+ }
+ dest->nelem = id;
+ return REG_NOERROR;
+}
+
+/* Calculate the union set of the sets DEST and SRC. And store it to
+ DEST. Return value indicate the error code or REG_NOERROR if succeeded. */
+
+static reg_errcode_t
+__attribute_warn_unused_result__
+re_node_set_merge (re_node_set *dest, const re_node_set *src)
+{
+ Idx is, id, sbase, delta;
+ if (src == NULL || src->nelem == 0)
+ return REG_NOERROR;
+ if (dest->alloc < 2 * src->nelem + dest->nelem)
+ {
+ Idx new_alloc = 2 * (src->nelem + dest->alloc);
+ Idx *new_buffer = re_realloc (dest->elems, Idx, new_alloc);
+ if (__glibc_unlikely (new_buffer == NULL))
+ return REG_ESPACE;
+ dest->elems = new_buffer;
+ dest->alloc = new_alloc;
+ }
+
+ if (__glibc_unlikely (dest->nelem == 0))
+ {
+ /* Although we already guaranteed above that dest->alloc != 0 and
+ therefore dest->elems != NULL, add a debug assertion to pacify
+ GCC 11.2.1's -fanalyzer. */
+ DEBUG_ASSERT (dest->elems);
+ dest->nelem = src->nelem;
+ memcpy (dest->elems, src->elems, src->nelem * sizeof (Idx));
+ return REG_NOERROR;
+ }
+
+ /* Copy into the top of DEST the items of SRC that are not
+ found in DEST. Maybe we could binary search in DEST? */
+ for (sbase = dest->nelem + 2 * src->nelem,
+ is = src->nelem - 1, id = dest->nelem - 1; is >= 0 && id >= 0; )
+ {
+ if (dest->elems[id] == src->elems[is])
+ is--, id--;
+ else if (dest->elems[id] < src->elems[is])
+ dest->elems[--sbase] = src->elems[is--];
+ else /* if (dest->elems[id] > src->elems[is]) */
+ --id;
+ }
+
+ if (is >= 0)
+ {
+ /* If DEST is exhausted, the remaining items of SRC must be unique. */
+ sbase -= is + 1;
+ memcpy (dest->elems + sbase, src->elems, (is + 1) * sizeof (Idx));
+ }
+
+ id = dest->nelem - 1;
+ is = dest->nelem + 2 * src->nelem - 1;
+ delta = is - sbase + 1;
+ if (delta == 0)
+ return REG_NOERROR;
+
+ /* Now copy. When DELTA becomes zero, the remaining
+ DEST elements are already in place. */
+ dest->nelem += delta;
+ for (;;)
+ {
+ if (dest->elems[is] > dest->elems[id])
+ {
+ /* Copy from the top. */
+ dest->elems[id + delta--] = dest->elems[is--];
+ if (delta == 0)
+ break;
+ }
+ else
+ {
+ /* Slide from the bottom. */
+ dest->elems[id + delta] = dest->elems[id];
+ if (--id < 0)
+ {
+ /* Copy remaining SRC elements. */
+ memcpy (dest->elems, dest->elems + sbase,
+ delta * sizeof (Idx));
+ break;
+ }
+ }
+ }
+
+ return REG_NOERROR;
+}
+
+/* Insert the new element ELEM to the re_node_set* SET.
+ SET should not already have ELEM.
+ Return true if successful. */
+
+static bool
+__attribute_warn_unused_result__
+re_node_set_insert (re_node_set *set, Idx elem)
+{
+ Idx idx;
+ /* In case the set is empty. */
+ if (set->alloc == 0)
+ return __glibc_likely (re_node_set_init_1 (set, elem) == REG_NOERROR);
+
+ if (__glibc_unlikely (set->nelem) == 0)
+ {
+ /* Although we already guaranteed above that set->alloc != 0 and
+ therefore set->elems != NULL, add a debug assertion to pacify
+ GCC 11.2 -fanalyzer. */
+ DEBUG_ASSERT (set->elems);
+ set->elems[0] = elem;
+ ++set->nelem;
+ return true;
+ }
+
+ /* Realloc if we need. */
+ if (set->alloc == set->nelem)
+ {
+ Idx *new_elems;
+ set->alloc = set->alloc * 2;
+ new_elems = re_realloc (set->elems, Idx, set->alloc);
+ if (__glibc_unlikely (new_elems == NULL))
+ return false;
+ set->elems = new_elems;
+ }
+
+ /* Move the elements which follows the new element. Test the
+ first element separately to skip a check in the inner loop. */
+ if (elem < set->elems[0])
+ {
+ for (idx = set->nelem; idx > 0; idx--)
+ set->elems[idx] = set->elems[idx - 1];
+ }
+ else
+ {
+ for (idx = set->nelem; set->elems[idx - 1] > elem; idx--)
+ set->elems[idx] = set->elems[idx - 1];
+ DEBUG_ASSERT (set->elems[idx - 1] < elem);
+ }
+
+ /* Insert the new element. */
+ set->elems[idx] = elem;
+ ++set->nelem;
+ return true;
+}
+
+/* Insert the new element ELEM to the re_node_set* SET.
+ SET should not already have any element greater than or equal to ELEM.
+ Return true if successful. */
+
+static bool
+__attribute_warn_unused_result__
+re_node_set_insert_last (re_node_set *set, Idx elem)
+{
+ /* Realloc if we need. */
+ if (set->alloc == set->nelem)
+ {
+ Idx *new_elems;
+ set->alloc = (set->alloc + 1) * 2;
+ new_elems = re_realloc (set->elems, Idx, set->alloc);
+ if (__glibc_unlikely (new_elems == NULL))
+ return false;
+ set->elems = new_elems;
+ }
+
+ /* Insert the new element. */
+ set->elems[set->nelem++] = elem;
+ return true;
+}
+
+/* Compare two node sets SET1 and SET2.
+ Return true if SET1 and SET2 are equivalent. */
+
+static bool
+__attribute__ ((pure))
+re_node_set_compare (const re_node_set *set1, const re_node_set *set2)
+{
+ Idx i;
+ if (set1 == NULL || set2 == NULL || set1->nelem != set2->nelem)
+ return false;
+ for (i = set1->nelem ; --i >= 0 ; )
+ if (set1->elems[i] != set2->elems[i])
+ return false;
+ return true;
+}
+
+/* Return (idx + 1) if SET contains the element ELEM, return 0 otherwise. */
+
+static Idx
+__attribute__ ((pure))
+re_node_set_contains (const re_node_set *set, Idx elem)
+{
+ __re_size_t idx, right, mid;
+ if (set->nelem <= 0)
+ return 0;
+
+ /* Binary search the element. */
+ idx = 0;
+ right = set->nelem - 1;
+ while (idx < right)
+ {
+ mid = (idx + right) / 2;
+ if (set->elems[mid] < elem)
+ idx = mid + 1;
+ else
+ right = mid;
+ }
+ return set->elems[idx] == elem ? idx + 1 : 0;
+}
+
+static void
+re_node_set_remove_at (re_node_set *set, Idx idx)
+{
+ if (idx < 0 || idx >= set->nelem)
+ return;
+ --set->nelem;
+ for (; idx < set->nelem; idx++)
+ set->elems[idx] = set->elems[idx + 1];
+}
+
+
+/* Add the token TOKEN to dfa->nodes, and return the index of the token.
+ Or return -1 if an error occurred. */
+
+static Idx
+re_dfa_add_node (re_dfa_t *dfa, re_token_t token)
+{
+ if (__glibc_unlikely (dfa->nodes_len >= dfa->nodes_alloc))
+ {
+ size_t new_nodes_alloc = dfa->nodes_alloc * 2;
+ Idx *new_nexts, *new_indices;
+ re_node_set *new_edests, *new_eclosures;
+ re_token_t *new_nodes;
+
+ /* Avoid overflows in realloc. */
+ const size_t max_object_size = MAX (sizeof (re_token_t),
+ MAX (sizeof (re_node_set),
+ sizeof (Idx)));
+ if (__glibc_unlikely (MIN (IDX_MAX, SIZE_MAX / max_object_size)
+ < new_nodes_alloc))
+ return -1;
+
+ new_nodes = re_realloc (dfa->nodes, re_token_t, new_nodes_alloc);
+ if (__glibc_unlikely (new_nodes == NULL))
+ return -1;
+ dfa->nodes = new_nodes;
+ dfa->nodes_alloc = new_nodes_alloc;
+ new_nexts = re_realloc (dfa->nexts, Idx, new_nodes_alloc);
+ if (new_nexts != NULL)
+ dfa->nexts = new_nexts;
+ new_indices = re_realloc (dfa->org_indices, Idx, new_nodes_alloc);
+ if (new_indices != NULL)
+ dfa->org_indices = new_indices;
+ new_edests = re_realloc (dfa->edests, re_node_set, new_nodes_alloc);
+ if (new_edests != NULL)
+ dfa->edests = new_edests;
+ new_eclosures = re_realloc (dfa->eclosures, re_node_set, new_nodes_alloc);
+ if (new_eclosures != NULL)
+ dfa->eclosures = new_eclosures;
+ if (__glibc_unlikely (new_nexts == NULL || new_indices == NULL
+ || new_edests == NULL || new_eclosures == NULL))
+ return -1;
+ }
+ dfa->nodes[dfa->nodes_len] = token;
+ dfa->nodes[dfa->nodes_len].constraint = 0;
+ dfa->nodes[dfa->nodes_len].accept_mb =
+ ((token.type == OP_PERIOD && dfa->mb_cur_max > 1)
+ || token.type == COMPLEX_BRACKET);
+ dfa->nexts[dfa->nodes_len] = -1;
+ re_node_set_init_empty (dfa->edests + dfa->nodes_len);
+ re_node_set_init_empty (dfa->eclosures + dfa->nodes_len);
+ return dfa->nodes_len++;
+}
+
+static re_hashval_t
+calc_state_hash (const re_node_set *nodes, unsigned int context)
+{
+ re_hashval_t hash = nodes->nelem + context;
+ Idx i;
+ for (i = 0 ; i < nodes->nelem ; i++)
+ hash += nodes->elems[i];
+ return hash;
+}
+
+/* Search for the state whose node_set is equivalent to NODES.
+ Return the pointer to the state, if we found it in the DFA.
+ Otherwise create the new one and return it. In case of an error
+ return NULL and set the error code in ERR.
+ Note: - We assume NULL as the invalid state, then it is possible that
+ return value is NULL and ERR is REG_NOERROR.
+ - We never return non-NULL value in case of any errors, it is for
+ optimization. */
+
+static re_dfastate_t *
+__attribute_warn_unused_result__
+re_acquire_state (reg_errcode_t *err, const re_dfa_t *dfa,
+ const re_node_set *nodes)
+{
+ re_hashval_t hash;
+ re_dfastate_t *new_state;
+ struct re_state_table_entry *spot;
+ Idx i;
+#if defined GCC_LINT || defined lint
+ /* Suppress bogus uninitialized-variable warnings. */
+ *err = REG_NOERROR;
+#endif
+ if (__glibc_unlikely (nodes->nelem == 0))
+ {
+ *err = REG_NOERROR;
+ return NULL;
+ }
+ hash = calc_state_hash (nodes, 0);
+ spot = dfa->state_table + (hash & dfa->state_hash_mask);
+
+ for (i = 0 ; i < spot->num ; i++)
+ {
+ re_dfastate_t *state = spot->array[i];
+ if (hash != state->hash)
+ continue;
+ if (re_node_set_compare (&state->nodes, nodes))
+ return state;
+ }
+
+ /* There are no appropriate state in the dfa, create the new one. */
+ new_state = create_ci_newstate (dfa, nodes, hash);
+ if (__glibc_unlikely (new_state == NULL))
+ *err = REG_ESPACE;
+
+ return new_state;
+}
+
+/* Search for the state whose node_set is equivalent to NODES and
+ whose context is equivalent to CONTEXT.
+ Return the pointer to the state, if we found it in the DFA.
+ Otherwise create the new one and return it. In case of an error
+ return NULL and set the error code in ERR.
+ Note: - We assume NULL as the invalid state, then it is possible that
+ return value is NULL and ERR is REG_NOERROR.
+ - We never return non-NULL value in case of any errors, it is for
+ optimization. */
+
+static re_dfastate_t *
+__attribute_warn_unused_result__
+re_acquire_state_context (reg_errcode_t *err, const re_dfa_t *dfa,
+ const re_node_set *nodes, unsigned int context)
+{
+ re_hashval_t hash;
+ re_dfastate_t *new_state;
+ struct re_state_table_entry *spot;
+ Idx i;
+#if defined GCC_LINT || defined lint
+ /* Suppress bogus uninitialized-variable warnings. */
+ *err = REG_NOERROR;
+#endif
+ if (nodes->nelem == 0)
+ {
+ *err = REG_NOERROR;
+ return NULL;
+ }
+ hash = calc_state_hash (nodes, context);
+ spot = dfa->state_table + (hash & dfa->state_hash_mask);
+
+ for (i = 0 ; i < spot->num ; i++)
+ {
+ re_dfastate_t *state = spot->array[i];
+ if (state->hash == hash
+ && state->context == context
+ && re_node_set_compare (state->entrance_nodes, nodes))
+ return state;
+ }
+ /* There are no appropriate state in 'dfa', create the new one. */
+ new_state = create_cd_newstate (dfa, nodes, context, hash);
+ if (__glibc_unlikely (new_state == NULL))
+ *err = REG_ESPACE;
+
+ return new_state;
+}
+
+/* Finish initialization of the new state NEWSTATE, and using its hash value
+ HASH put in the appropriate bucket of DFA's state table. Return value
+ indicates the error code if failed. */
+
+static reg_errcode_t
+__attribute_warn_unused_result__
+register_state (const re_dfa_t *dfa, re_dfastate_t *newstate,
+ re_hashval_t hash)
+{
+ struct re_state_table_entry *spot;
+ reg_errcode_t err;
+ Idx i;
+
+ newstate->hash = hash;
+ err = re_node_set_alloc (&newstate->non_eps_nodes, newstate->nodes.nelem);
+ if (__glibc_unlikely (err != REG_NOERROR))
+ return REG_ESPACE;
+ for (i = 0; i < newstate->nodes.nelem; i++)
+ {
+ Idx elem = newstate->nodes.elems[i];
+ if (!IS_EPSILON_NODE (dfa->nodes[elem].type))
+ if (! re_node_set_insert_last (&newstate->non_eps_nodes, elem))
+ return REG_ESPACE;
+ }
+
+ spot = dfa->state_table + (hash & dfa->state_hash_mask);
+ if (__glibc_unlikely (spot->alloc <= spot->num))
+ {
+ Idx new_alloc = 2 * spot->num + 2;
+ re_dfastate_t **new_array = re_realloc (spot->array, re_dfastate_t *,
+ new_alloc);
+ if (__glibc_unlikely (new_array == NULL))
+ return REG_ESPACE;
+ spot->array = new_array;
+ spot->alloc = new_alloc;
+ }
+ spot->array[spot->num++] = newstate;
+ return REG_NOERROR;
+}
+
+static void
+free_state (re_dfastate_t *state)
+{
+ re_node_set_free (&state->non_eps_nodes);
+ re_node_set_free (&state->inveclosure);
+ if (state->entrance_nodes != &state->nodes)
+ {
+ re_node_set_free (state->entrance_nodes);
+ re_free (state->entrance_nodes);
+ }
+ re_node_set_free (&state->nodes);
+ re_free (state->word_trtable);
+ re_free (state->trtable);
+ re_free (state);
+}
+
+/* Create the new state which is independent of contexts.
+ Return the new state if succeeded, otherwise return NULL. */
+
+static re_dfastate_t *
+__attribute_warn_unused_result__
+create_ci_newstate (const re_dfa_t *dfa, const re_node_set *nodes,
+ re_hashval_t hash)
+{
+ Idx i;
+ reg_errcode_t err;
+ re_dfastate_t *newstate;
+
+ newstate = (re_dfastate_t *) calloc (sizeof (re_dfastate_t), 1);
+ if (__glibc_unlikely (newstate == NULL))
+ return NULL;
+ err = re_node_set_init_copy (&newstate->nodes, nodes);
+ if (__glibc_unlikely (err != REG_NOERROR))
+ {
+ re_free (newstate);
+ return NULL;
+ }
+
+ newstate->entrance_nodes = &newstate->nodes;
+ for (i = 0 ; i < nodes->nelem ; i++)
+ {
+ re_token_t *node = dfa->nodes + nodes->elems[i];
+ re_token_type_t type = node->type;
+ if (type == CHARACTER && !node->constraint)
+ continue;
+ newstate->accept_mb |= node->accept_mb;
+
+ /* If the state has the halt node, the state is a halt state. */
+ if (type == END_OF_RE)
+ newstate->halt = 1;
+ else if (type == OP_BACK_REF)
+ newstate->has_backref = 1;
+ else if (type == ANCHOR || node->constraint)
+ newstate->has_constraint = 1;
+ }
+ err = register_state (dfa, newstate, hash);
+ if (__glibc_unlikely (err != REG_NOERROR))
+ {
+ free_state (newstate);
+ newstate = NULL;
+ }
+ return newstate;
+}
+
+/* Create the new state which is depend on the context CONTEXT.
+ Return the new state if succeeded, otherwise return NULL. */
+
+static re_dfastate_t *
+__attribute_warn_unused_result__
+create_cd_newstate (const re_dfa_t *dfa, const re_node_set *nodes,
+ unsigned int context, re_hashval_t hash)
+{
+ Idx i, nctx_nodes = 0;
+ reg_errcode_t err;
+ re_dfastate_t *newstate;
+
+ newstate = (re_dfastate_t *) calloc (sizeof (re_dfastate_t), 1);
+ if (__glibc_unlikely (newstate == NULL))
+ return NULL;
+ err = re_node_set_init_copy (&newstate->nodes, nodes);
+ if (__glibc_unlikely (err != REG_NOERROR))
+ {
+ re_free (newstate);
+ return NULL;
+ }
+
+ newstate->context = context;
+ newstate->entrance_nodes = &newstate->nodes;
+
+ for (i = 0 ; i < nodes->nelem ; i++)
+ {
+ re_token_t *node = dfa->nodes + nodes->elems[i];
+ re_token_type_t type = node->type;
+ unsigned int constraint = node->constraint;
+
+ if (type == CHARACTER && !constraint)
+ continue;
+ newstate->accept_mb |= node->accept_mb;
+
+ /* If the state has the halt node, the state is a halt state. */
+ if (type == END_OF_RE)
+ newstate->halt = 1;
+ else if (type == OP_BACK_REF)
+ newstate->has_backref = 1;
+
+ if (constraint)
+ {
+ if (newstate->entrance_nodes == &newstate->nodes)
+ {
+ 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)
+ {
+ free_state (newstate);
+ return NULL;
+ }
+ nctx_nodes = 0;
+ newstate->has_constraint = 1;
+ }
+
+ if (NOT_SATISFY_PREV_CONSTRAINT (constraint,context))
+ {
+ re_node_set_remove_at (&newstate->nodes, i - nctx_nodes);
+ ++nctx_nodes;
+ }
+ }
+ }
+ err = register_state (dfa, newstate, hash);
+ if (__glibc_unlikely (err != REG_NOERROR))
+ {
+ free_state (newstate);
+ newstate = NULL;
+ }
+ return newstate;
+}
diff --git a/lib/regex_internal.h b/lib/regex_internal.h
new file mode 100644
index 00000000000..57a455b1f43
--- /dev/null
+++ b/lib/regex_internal.h
@@ -0,0 +1,835 @@
+/* Extended regular expression matching and search library.
+ Copyright (C) 2002-2022 Free Software Foundation, Inc.
+ This file is part of the GNU C Library.
+ Contributed by Isamu Hasegawa <isamu@yamato.ibm.com>.
+
+ The GNU C Library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Lesser General Public
+ License as published by the Free Software Foundation; either
+ version 2.1 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
+ Lesser General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public
+ License along with the GNU C Library; if not, see
+ <https://www.gnu.org/licenses/>. */
+
+#ifndef _REGEX_INTERNAL_H
+#define _REGEX_INTERNAL_H 1
+
+#include <ctype.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
+#include <langinfo.h>
+#include <locale.h>
+#include <wchar.h>
+#include <wctype.h>
+#include <stdbool.h>
+#include <stdint.h>
+
+#ifndef _LIBC
+# include <dynarray.h>
+#endif
+
+#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>
+# define lock_define(name) __libc_lock_define (, name)
+# define lock_init(lock) (__libc_lock_init (lock), 0)
+# define lock_fini(lock) ((void) 0)
+# define lock_lock(lock) __libc_lock_lock (lock)
+# define lock_unlock(lock) __libc_lock_unlock (lock)
+#elif defined GNULIB_LOCK && !defined GNULIB_REGEX_SINGLE_THREAD
+# include "glthread/lock.h"
+# 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))
+# define lock_unlock(lock) glthread_lock_unlock (&(lock))
+#elif defined GNULIB_PTHREAD && !defined GNULIB_REGEX_SINGLE_THREAD
+# include <pthread.h>
+# define lock_define(name) pthread_mutex_t name;
+# define lock_init(lock) pthread_mutex_init (&(lock), 0)
+# define lock_fini(lock) pthread_mutex_destroy (&(lock))
+# define lock_lock(lock) pthread_mutex_lock (&(lock))
+# define lock_unlock(lock) pthread_mutex_unlock (&(lock))
+#else
+# define lock_define(name)
+# define lock_init(lock) 0
+# define lock_fini(lock) ((void) 0)
+ /* The 'dfa' avoids an "unused variable 'dfa'" warning from GCC. */
+# define lock_lock(lock) ((void) dfa)
+# define lock_unlock(lock) ((void) 0)
+#endif
+
+/* In case that the system doesn't have isblank(). */
+#if !defined _LIBC && ! (defined isblank || (HAVE_ISBLANK && HAVE_DECL_ISBLANK))
+# define isblank(ch) ((ch) == ' ' || (ch) == '\t')
+#endif
+
+/* regex code assumes isascii has its usual numeric meaning,
+ even if the portable character set uses EBCDIC encoding,
+ and even if wint_t is wider than int. */
+#ifndef _LIBC
+# undef isascii
+# define isascii(c) (((c) & ~0x7f) == 0)
+#endif
+
+#ifdef _LIBC
+# ifndef _RE_DEFINE_LOCALE_FUNCTIONS
+# define _RE_DEFINE_LOCALE_FUNCTIONS 1
+# include <locale/localeinfo.h>
+# include <locale/coll-lookup.h>
+# endif
+#endif
+
+/* This is for other GNU distributions with internationalized messages. */
+#if (HAVE_LIBINTL_H && ENABLE_NLS) || defined _LIBC
+# include <libintl.h>
+# ifdef _LIBC
+# undef gettext
+# define gettext(msgid) \
+ __dcgettext (_libc_intl_domainname, msgid, LC_MESSAGES)
+# endif
+#else
+# undef gettext
+# define gettext(msgid) (msgid)
+#endif
+
+#ifndef gettext_noop
+/* This define is so xgettext can find the internationalizable
+ strings. */
+# define gettext_noop(String) String
+#endif
+
+/* Number of ASCII characters. */
+#define ASCII_CHARS 0x80
+
+/* Number of single byte characters. */
+#define SBC_MAX (UCHAR_MAX + 1)
+
+#define COLL_ELEM_LEN_MAX 8
+
+/* The character which represents newline. */
+#define NEWLINE_CHAR '\n'
+#define WIDE_NEWLINE_CHAR L'\n'
+
+/* Rename to standard API for using out of glibc. */
+#ifndef _LIBC
+# undef __wctype
+# undef __iswalnum
+# undef __iswctype
+# undef __towlower
+# undef __towupper
+# define __wctype wctype
+# define __iswalnum iswalnum
+# define __iswctype iswctype
+# define __towlower towlower
+# define __towupper towupper
+# define __btowc btowc
+# define __mbrtowc mbrtowc
+# define __wcrtomb wcrtomb
+# define __regfree regfree
+#endif /* not _LIBC */
+
+/* Types related to integers. Unless protected by #ifdef _LIBC, the
+ regex code should avoid exact-width types like int32_t and uint64_t
+ as some non-GCC platforms lack them, an issue when this code is
+ used in Gnulib. */
+
+#ifndef SSIZE_MAX
+# define SSIZE_MAX ((ssize_t) (SIZE_MAX / 2))
+#endif
+#ifndef ULONG_WIDTH
+# define ULONG_WIDTH REGEX_UINTEGER_WIDTH (ULONG_MAX)
+/* The number of usable bits in an unsigned integer type with maximum
+ value MAX, as an int expression suitable in #if. Cover all known
+ practical hosts. This implementation exploits the fact that MAX is
+ 1 less than a power of 2, and merely counts the number of 1 bits in
+ MAX; "COBn" means "count the number of 1 bits in the low-order n bits". */
+# define REGEX_UINTEGER_WIDTH(max) REGEX_COB128 (max)
+# define REGEX_COB128(n) (REGEX_COB64 ((n) >> 31 >> 31 >> 2) + REGEX_COB64 (n))
+# define REGEX_COB64(n) (REGEX_COB32 ((n) >> 31 >> 1) + REGEX_COB32 (n))
+# define REGEX_COB32(n) (REGEX_COB16 ((n) >> 16) + REGEX_COB16 (n))
+# define REGEX_COB16(n) (REGEX_COB8 ((n) >> 8) + REGEX_COB8 (n))
+# define REGEX_COB8(n) (REGEX_COB4 ((n) >> 4) + REGEX_COB4 (n))
+# define REGEX_COB4(n) (!!((n) & 8) + !!((n) & 4) + !!((n) & 2) + ((n) & 1))
+# if ULONG_MAX / 2 + 1 != 1ul << (ULONG_WIDTH - 1)
+# error "ULONG_MAX out of range"
+# endif
+#endif
+
+/* The type of indexes into strings. This is signed, not size_t,
+ since the API requires indexes to fit in regoff_t anyway, and using
+ signed integers makes the code a bit smaller and presumably faster.
+ The traditional GNU regex implementation uses int for indexes.
+ The POSIX-compatible implementation uses a possibly-wider type.
+ The name 'Idx' is three letters to minimize the hassle of
+ reindenting a lot of regex code that formerly used 'int'. */
+typedef regoff_t Idx;
+#ifdef _REGEX_LARGE_OFFSETS
+# define IDX_MAX SSIZE_MAX
+#else
+# define IDX_MAX INT_MAX
+#endif
+
+/* A hash value, suitable for computing hash tables. */
+typedef __re_size_t re_hashval_t;
+
+/* An integer used to represent a set of bits. It must be unsigned,
+ and must be at least as wide as unsigned int. */
+typedef unsigned long int bitset_word_t;
+/* All bits set in a bitset_word_t. */
+#define BITSET_WORD_MAX ULONG_MAX
+/* Number of bits in a bitset_word_t. */
+#define BITSET_WORD_BITS ULONG_WIDTH
+
+/* Number of bitset_word_t values in a bitset_t. */
+#define BITSET_WORDS ((SBC_MAX + BITSET_WORD_BITS - 1) / BITSET_WORD_BITS)
+
+typedef bitset_word_t bitset_t[BITSET_WORDS];
+typedef bitset_word_t *re_bitset_ptr_t;
+typedef const bitset_word_t *re_const_bitset_ptr_t;
+
+#define PREV_WORD_CONSTRAINT 0x0001
+#define PREV_NOTWORD_CONSTRAINT 0x0002
+#define NEXT_WORD_CONSTRAINT 0x0004
+#define NEXT_NOTWORD_CONSTRAINT 0x0008
+#define PREV_NEWLINE_CONSTRAINT 0x0010
+#define NEXT_NEWLINE_CONSTRAINT 0x0020
+#define PREV_BEGBUF_CONSTRAINT 0x0040
+#define NEXT_ENDBUF_CONSTRAINT 0x0080
+#define WORD_DELIM_CONSTRAINT 0x0100
+#define NOT_WORD_DELIM_CONSTRAINT 0x0200
+
+typedef enum
+{
+ INSIDE_WORD = PREV_WORD_CONSTRAINT | NEXT_WORD_CONSTRAINT,
+ WORD_FIRST = PREV_NOTWORD_CONSTRAINT | NEXT_WORD_CONSTRAINT,
+ WORD_LAST = PREV_WORD_CONSTRAINT | NEXT_NOTWORD_CONSTRAINT,
+ INSIDE_NOTWORD = PREV_NOTWORD_CONSTRAINT | NEXT_NOTWORD_CONSTRAINT,
+ LINE_FIRST = PREV_NEWLINE_CONSTRAINT,
+ LINE_LAST = NEXT_NEWLINE_CONSTRAINT,
+ BUF_FIRST = PREV_BEGBUF_CONSTRAINT,
+ BUF_LAST = NEXT_ENDBUF_CONSTRAINT,
+ WORD_DELIM = WORD_DELIM_CONSTRAINT,
+ NOT_WORD_DELIM = NOT_WORD_DELIM_CONSTRAINT
+} re_context_type;
+
+typedef struct
+{
+ Idx alloc;
+ Idx nelem;
+ Idx *elems;
+} re_node_set;
+
+typedef enum
+{
+ NON_TYPE = 0,
+
+ /* Node type, These are used by token, node, tree. */
+ CHARACTER = 1,
+ END_OF_RE = 2,
+ SIMPLE_BRACKET = 3,
+ OP_BACK_REF = 4,
+ OP_PERIOD = 5,
+ COMPLEX_BRACKET = 6,
+ OP_UTF8_PERIOD = 7,
+
+ /* We define EPSILON_BIT as a macro so that OP_OPEN_SUBEXP is used
+ when the debugger shows values of this enum type. */
+#define EPSILON_BIT 8
+ OP_OPEN_SUBEXP = EPSILON_BIT | 0,
+ OP_CLOSE_SUBEXP = EPSILON_BIT | 1,
+ OP_ALT = EPSILON_BIT | 2,
+ OP_DUP_ASTERISK = EPSILON_BIT | 3,
+ ANCHOR = EPSILON_BIT | 4,
+
+ /* Tree type, these are used only by tree. */
+ CONCAT = 16,
+ SUBEXP = 17,
+
+ /* Token type, these are used only by token. */
+ OP_DUP_PLUS = 18,
+ OP_DUP_QUESTION,
+ OP_OPEN_BRACKET,
+ OP_CLOSE_BRACKET,
+ OP_CHARSET_RANGE,
+ OP_OPEN_DUP_NUM,
+ OP_CLOSE_DUP_NUM,
+ OP_NON_MATCH_LIST,
+ OP_OPEN_COLL_ELEM,
+ OP_CLOSE_COLL_ELEM,
+ OP_OPEN_EQUIV_CLASS,
+ OP_CLOSE_EQUIV_CLASS,
+ OP_OPEN_CHAR_CLASS,
+ OP_CLOSE_CHAR_CLASS,
+ OP_WORD,
+ OP_NOTWORD,
+ OP_SPACE,
+ OP_NOTSPACE,
+ BACK_SLASH
+
+} re_token_type_t;
+
+typedef struct
+{
+ /* Multibyte characters. */
+ wchar_t *mbchars;
+
+#ifdef _LIBC
+ /* Collating symbols. */
+ int32_t *coll_syms;
+#endif
+
+#ifdef _LIBC
+ /* Equivalence classes. */
+ int32_t *equiv_classes;
+#endif
+
+ /* Range expressions. */
+#ifdef _LIBC
+ uint32_t *range_starts;
+ uint32_t *range_ends;
+#else
+ wchar_t *range_starts;
+ wchar_t *range_ends;
+#endif
+
+ /* Character classes. */
+ wctype_t *char_classes;
+
+ /* If this character set is the non-matching list. */
+ unsigned int non_match : 1;
+
+ /* # of multibyte characters. */
+ Idx nmbchars;
+
+ /* # of collating symbols. */
+ Idx ncoll_syms;
+
+ /* # of equivalence classes. */
+ Idx nequiv_classes;
+
+ /* # of range expressions. */
+ Idx nranges;
+
+ /* # of character classes. */
+ Idx nchar_classes;
+} re_charset_t;
+
+typedef struct
+{
+ union
+ {
+ unsigned char c; /* for CHARACTER */
+ re_bitset_ptr_t sbcset; /* for SIMPLE_BRACKET */
+ re_charset_t *mbcset; /* for COMPLEX_BRACKET */
+ Idx idx; /* for BACK_REF */
+ re_context_type ctx_type; /* for ANCHOR */
+ } opr;
+#if (__GNUC__ >= 2 || defined __clang__) && !defined __STRICT_ANSI__
+ re_token_type_t type : 8;
+#else
+ re_token_type_t type;
+#endif
+ unsigned int constraint : 10; /* context constraint */
+ unsigned int duplicated : 1;
+ unsigned int opt_subexp : 1;
+ unsigned int accept_mb : 1;
+ /* These 2 bits can be moved into the union if needed (e.g. if running out
+ of bits; move opr.c to opr.c.c and move the flags to opr.c.flags). */
+ unsigned int mb_partial : 1;
+ unsigned int word_char : 1;
+} re_token_t;
+
+#define IS_EPSILON_NODE(type) ((type) & EPSILON_BIT)
+
+struct re_string_t
+{
+ /* Indicate the raw buffer which is the original string passed as an
+ argument of regexec(), re_search(), etc.. */
+ const unsigned char *raw_mbs;
+ /* Store the multibyte string. In case of "case insensitive mode" like
+ REG_ICASE, upper cases of the string are stored, otherwise MBS points
+ the same address that RAW_MBS points. */
+ unsigned char *mbs;
+ /* Store the wide character string which is corresponding to MBS. */
+ wint_t *wcs;
+ Idx *offsets;
+ mbstate_t cur_state;
+ /* Index in RAW_MBS. Each character mbs[i] corresponds to
+ raw_mbs[raw_mbs_idx + i]. */
+ Idx raw_mbs_idx;
+ /* The length of the valid characters in the buffers. */
+ Idx valid_len;
+ /* The corresponding number of bytes in raw_mbs array. */
+ Idx valid_raw_len;
+ /* The length of the buffers MBS and WCS. */
+ Idx bufs_len;
+ /* The index in MBS, which is updated by re_string_fetch_byte. */
+ Idx cur_idx;
+ /* length of RAW_MBS array. */
+ Idx raw_len;
+ /* This is RAW_LEN - RAW_MBS_IDX + VALID_LEN - VALID_RAW_LEN. */
+ Idx len;
+ /* End of the buffer may be shorter than its length in the cases such
+ as re_match_2, re_search_2. Then, we use STOP for end of the buffer
+ instead of LEN. */
+ Idx raw_stop;
+ /* This is RAW_STOP - RAW_MBS_IDX adjusted through OFFSETS. */
+ Idx stop;
+
+ /* The context of mbs[0]. We store the context independently, since
+ the context of mbs[0] may be different from raw_mbs[0], which is
+ the beginning of the input string. */
+ unsigned int tip_context;
+ /* The translation passed as a part of an argument of re_compile_pattern. */
+ RE_TRANSLATE_TYPE trans;
+ /* Copy of re_dfa_t's word_char. */
+ re_const_bitset_ptr_t word_char;
+ /* true if REG_ICASE. */
+ unsigned char icase;
+ unsigned char is_utf8;
+ unsigned char map_notascii;
+ unsigned char mbs_allocated;
+ unsigned char offsets_needed;
+ unsigned char newline_anchor;
+ unsigned char word_ops_used;
+ int mb_cur_max;
+};
+typedef struct re_string_t re_string_t;
+
+
+struct re_dfa_t;
+typedef struct re_dfa_t re_dfa_t;
+
+#ifndef _LIBC
+# define IS_IN(libc) false
+#endif
+
+#define re_string_peek_byte(pstr, offset) \
+ ((pstr)->mbs[(pstr)->cur_idx + offset])
+#define re_string_fetch_byte(pstr) \
+ ((pstr)->mbs[(pstr)->cur_idx++])
+#define re_string_first_byte(pstr, idx) \
+ ((idx) == (pstr)->valid_len || (pstr)->wcs[idx] != WEOF)
+#define re_string_is_single_byte_char(pstr, idx) \
+ ((pstr)->wcs[idx] != WEOF && ((pstr)->valid_len == (idx) + 1 \
+ || (pstr)->wcs[(idx) + 1] != WEOF))
+#define re_string_eoi(pstr) ((pstr)->stop <= (pstr)->cur_idx)
+#define re_string_cur_idx(pstr) ((pstr)->cur_idx)
+#define re_string_get_buffer(pstr) ((pstr)->mbs)
+#define re_string_length(pstr) ((pstr)->len)
+#define re_string_byte_at(pstr,idx) ((pstr)->mbs[idx])
+#define re_string_skip_bytes(pstr,idx) ((pstr)->cur_idx += (idx))
+#define re_string_set_index(pstr,idx) ((pstr)->cur_idx = (idx))
+
+#ifdef _LIBC
+# define MALLOC_0_IS_NONNULL 1
+#elif !defined MALLOC_0_IS_NONNULL
+# define MALLOC_0_IS_NONNULL 0
+#endif
+
+#ifndef MAX
+# define MAX(a,b) ((a) < (b) ? (b) : (a))
+#endif
+#ifndef MIN
+# define MIN(a,b) ((a) < (b) ? (a) : (b))
+#endif
+
+#define re_malloc(t,n) ((t *) malloc ((n) * sizeof (t)))
+#define re_realloc(p,t,n) ((t *) realloc (p, (n) * sizeof (t)))
+#define re_free(p) free (p)
+
+struct bin_tree_t
+{
+ struct bin_tree_t *parent;
+ struct bin_tree_t *left;
+ struct bin_tree_t *right;
+ struct bin_tree_t *first;
+ struct bin_tree_t *next;
+
+ re_token_t token;
+
+ /* 'node_idx' is the index in dfa->nodes, if 'type' == 0.
+ Otherwise 'type' indicate the type of this node. */
+ Idx node_idx;
+};
+typedef struct bin_tree_t bin_tree_t;
+
+#define BIN_TREE_STORAGE_SIZE \
+ ((1024 - sizeof (void *)) / sizeof (bin_tree_t))
+
+struct bin_tree_storage_t
+{
+ struct bin_tree_storage_t *next;
+ bin_tree_t data[BIN_TREE_STORAGE_SIZE];
+};
+typedef struct bin_tree_storage_t bin_tree_storage_t;
+
+#define CONTEXT_WORD 1
+#define CONTEXT_NEWLINE (CONTEXT_WORD << 1)
+#define CONTEXT_BEGBUF (CONTEXT_NEWLINE << 1)
+#define CONTEXT_ENDBUF (CONTEXT_BEGBUF << 1)
+
+#define IS_WORD_CONTEXT(c) ((c) & CONTEXT_WORD)
+#define IS_NEWLINE_CONTEXT(c) ((c) & CONTEXT_NEWLINE)
+#define IS_BEGBUF_CONTEXT(c) ((c) & CONTEXT_BEGBUF)
+#define IS_ENDBUF_CONTEXT(c) ((c) & CONTEXT_ENDBUF)
+#define IS_ORDINARY_CONTEXT(c) ((c) == 0)
+
+#define IS_WORD_CHAR(ch) (isalnum (ch) || (ch) == '_')
+#define IS_NEWLINE(ch) ((ch) == NEWLINE_CHAR)
+#define IS_WIDE_WORD_CHAR(ch) (__iswalnum (ch) || (ch) == L'_')
+#define IS_WIDE_NEWLINE(ch) ((ch) == WIDE_NEWLINE_CHAR)
+
+#define NOT_SATISFY_PREV_CONSTRAINT(constraint,context) \
+ ((((constraint) & PREV_WORD_CONSTRAINT) && !IS_WORD_CONTEXT (context)) \
+ || ((constraint & PREV_NOTWORD_CONSTRAINT) && IS_WORD_CONTEXT (context)) \
+ || ((constraint & PREV_NEWLINE_CONSTRAINT) && !IS_NEWLINE_CONTEXT (context))\
+ || ((constraint & PREV_BEGBUF_CONSTRAINT) && !IS_BEGBUF_CONTEXT (context)))
+
+#define NOT_SATISFY_NEXT_CONSTRAINT(constraint,context) \
+ ((((constraint) & NEXT_WORD_CONSTRAINT) && !IS_WORD_CONTEXT (context)) \
+ || (((constraint) & NEXT_NOTWORD_CONSTRAINT) && IS_WORD_CONTEXT (context)) \
+ || (((constraint) & NEXT_NEWLINE_CONSTRAINT) && !IS_NEWLINE_CONTEXT (context)) \
+ || (((constraint) & NEXT_ENDBUF_CONSTRAINT) && !IS_ENDBUF_CONTEXT (context)))
+
+struct re_dfastate_t
+{
+ re_hashval_t hash;
+ re_node_set nodes;
+ re_node_set non_eps_nodes;
+ re_node_set inveclosure;
+ re_node_set *entrance_nodes;
+ struct re_dfastate_t **trtable, **word_trtable;
+ unsigned int context : 4;
+ unsigned int halt : 1;
+ /* If this state can accept "multi byte".
+ Note that we refer to multibyte characters, and multi character
+ collating elements as "multi byte". */
+ unsigned int accept_mb : 1;
+ /* If this state has backreference node(s). */
+ unsigned int has_backref : 1;
+ unsigned int has_constraint : 1;
+};
+typedef struct re_dfastate_t re_dfastate_t;
+
+struct re_state_table_entry
+{
+ Idx num;
+ Idx alloc;
+ re_dfastate_t **array;
+};
+
+/* Array type used in re_sub_match_last_t and re_sub_match_top_t. */
+
+typedef struct
+{
+ Idx next_idx;
+ Idx alloc;
+ re_dfastate_t **array;
+} state_array_t;
+
+/* Store information about the node NODE whose type is OP_CLOSE_SUBEXP. */
+
+typedef struct
+{
+ Idx node;
+ Idx str_idx; /* The position NODE match at. */
+ state_array_t path;
+} re_sub_match_last_t;
+
+/* Store information about the node NODE whose type is OP_OPEN_SUBEXP.
+ And information about the node, whose type is OP_CLOSE_SUBEXP,
+ corresponding to NODE is stored in LASTS. */
+
+typedef struct
+{
+ Idx str_idx;
+ Idx node;
+ state_array_t *path;
+ Idx alasts; /* Allocation size of LASTS. */
+ Idx nlasts; /* The number of LASTS. */
+ re_sub_match_last_t **lasts;
+} re_sub_match_top_t;
+
+struct re_backref_cache_entry
+{
+ Idx node;
+ Idx str_idx;
+ Idx subexp_from;
+ Idx subexp_to;
+ bitset_word_t eps_reachable_subexps_map;
+ char more;
+};
+
+typedef struct
+{
+ /* The string object corresponding to the input string. */
+ re_string_t input;
+ const re_dfa_t *const dfa;
+ /* EFLAGS of the argument of regexec. */
+ int eflags;
+ /* Where the matching ends. */
+ Idx match_last;
+ Idx last_node;
+ /* The state log used by the matcher. */
+ re_dfastate_t **state_log;
+ Idx state_log_top;
+ /* Back reference cache. */
+ Idx nbkref_ents;
+ Idx abkref_ents;
+ struct re_backref_cache_entry *bkref_ents;
+ int max_mb_elem_len;
+ Idx nsub_tops;
+ Idx asub_tops;
+ re_sub_match_top_t **sub_tops;
+} re_match_context_t;
+
+typedef struct
+{
+ re_dfastate_t **sifted_states;
+ re_dfastate_t **limited_states;
+ Idx last_node;
+ Idx last_str_idx;
+ re_node_set limits;
+} re_sift_context_t;
+
+struct re_fail_stack_ent_t
+{
+ Idx idx;
+ Idx node;
+ regmatch_t *regs;
+ re_node_set eps_via_nodes;
+};
+
+struct re_fail_stack_t
+{
+ Idx num;
+ Idx alloc;
+ struct re_fail_stack_ent_t *stack;
+};
+
+struct re_dfa_t
+{
+ re_token_t *nodes;
+ size_t nodes_alloc;
+ size_t nodes_len;
+ Idx *nexts;
+ Idx *org_indices;
+ re_node_set *edests;
+ re_node_set *eclosures;
+ re_node_set *inveclosures;
+ struct re_state_table_entry *state_table;
+ re_dfastate_t *init_state;
+ re_dfastate_t *init_state_word;
+ re_dfastate_t *init_state_nl;
+ re_dfastate_t *init_state_begbuf;
+ bin_tree_t *str_tree;
+ bin_tree_storage_t *str_tree_storage;
+ re_bitset_ptr_t sb_char;
+ int str_tree_storage_idx;
+
+ /* number of subexpressions 're_nsub' is in regex_t. */
+ re_hashval_t state_hash_mask;
+ Idx init_node;
+ Idx nbackref; /* The number of backreference in this dfa. */
+
+ /* Bitmap expressing which backreference is used. */
+ bitset_word_t used_bkref_map;
+ bitset_word_t completed_bkref_map;
+
+ unsigned int has_plural_match : 1;
+ /* If this dfa has "multibyte node", which is a backreference or
+ a node which can accept multibyte character or multi character
+ collating element. */
+ unsigned int has_mb_node : 1;
+ unsigned int is_utf8 : 1;
+ unsigned int map_notascii : 1;
+ unsigned int word_ops_used : 1;
+ int mb_cur_max;
+ bitset_t word_char;
+ reg_syntax_t syntax;
+ Idx *subexp_map;
+#ifdef DEBUG
+ char* re_str;
+#endif
+ lock_define (lock)
+};
+
+#define re_node_set_init_empty(set) memset (set, '\0', sizeof (re_node_set))
+#define re_node_set_remove(set,id) \
+ (re_node_set_remove_at (set, re_node_set_contains (set, id) - 1))
+#define re_node_set_empty(p) ((p)->nelem = 0)
+#define re_node_set_free(set) re_free ((set)->elems)
+
+
+typedef enum
+{
+ SB_CHAR,
+ MB_CHAR,
+ EQUIV_CLASS,
+ COLL_SYM,
+ CHAR_CLASS
+} bracket_elem_type;
+
+typedef struct
+{
+ bracket_elem_type type;
+ union
+ {
+ unsigned char ch;
+ unsigned char *name;
+ wchar_t wch;
+ } opr;
+} bracket_elem_t;
+
+
+/* Functions for bitset_t operation. */
+
+static inline void
+bitset_set (bitset_t set, Idx i)
+{
+ set[i / BITSET_WORD_BITS] |= (bitset_word_t) 1 << i % BITSET_WORD_BITS;
+}
+
+static inline void
+bitset_clear (bitset_t set, Idx i)
+{
+ set[i / BITSET_WORD_BITS] &= ~ ((bitset_word_t) 1 << i % BITSET_WORD_BITS);
+}
+
+static inline bool
+bitset_contain (const bitset_t set, Idx i)
+{
+ return (set[i / BITSET_WORD_BITS] >> i % BITSET_WORD_BITS) & 1;
+}
+
+static inline void
+bitset_empty (bitset_t set)
+{
+ memset (set, '\0', sizeof (bitset_t));
+}
+
+static inline void
+bitset_set_all (bitset_t set)
+{
+ memset (set, -1, sizeof (bitset_word_t) * (SBC_MAX / BITSET_WORD_BITS));
+ if (SBC_MAX % BITSET_WORD_BITS != 0)
+ set[BITSET_WORDS - 1] =
+ ((bitset_word_t) 1 << SBC_MAX % BITSET_WORD_BITS) - 1;
+}
+
+static inline void
+bitset_copy (bitset_t dest, const bitset_t src)
+{
+ memcpy (dest, src, sizeof (bitset_t));
+}
+
+static inline void
+bitset_not (bitset_t set)
+{
+ int bitset_i;
+ for (bitset_i = 0; bitset_i < SBC_MAX / BITSET_WORD_BITS; ++bitset_i)
+ set[bitset_i] = ~set[bitset_i];
+ if (SBC_MAX % BITSET_WORD_BITS != 0)
+ set[BITSET_WORDS - 1] =
+ ((((bitset_word_t) 1 << SBC_MAX % BITSET_WORD_BITS) - 1)
+ & ~set[BITSET_WORDS - 1]);
+}
+
+static inline void
+bitset_merge (bitset_t dest, const bitset_t src)
+{
+ int bitset_i;
+ for (bitset_i = 0; bitset_i < BITSET_WORDS; ++bitset_i)
+ dest[bitset_i] |= src[bitset_i];
+}
+
+static inline void
+bitset_mask (bitset_t dest, const bitset_t src)
+{
+ int bitset_i;
+ for (bitset_i = 0; bitset_i < BITSET_WORDS; ++bitset_i)
+ dest[bitset_i] &= src[bitset_i];
+}
+
+/* Functions for re_string. */
+static int
+__attribute__ ((pure, unused))
+re_string_char_size_at (const re_string_t *pstr, Idx idx)
+{
+ int byte_idx;
+ if (pstr->mb_cur_max == 1)
+ return 1;
+ for (byte_idx = 1; idx + byte_idx < pstr->valid_len; ++byte_idx)
+ if (pstr->wcs[idx + byte_idx] != WEOF)
+ break;
+ return byte_idx;
+}
+
+static wint_t
+__attribute__ ((pure, unused))
+re_string_wchar_at (const re_string_t *pstr, Idx idx)
+{
+ if (pstr->mb_cur_max == 1)
+ return (wint_t) pstr->mbs[idx];
+ return (wint_t) pstr->wcs[idx];
+}
+
+#ifdef _LIBC
+# include <locale/weight.h>
+#endif
+
+static int
+__attribute__ ((pure, unused))
+re_string_elem_size_at (const re_string_t *pstr, Idx idx)
+{
+#ifdef _LIBC
+ const unsigned char *p, *extra;
+ const int32_t *table, *indirect;
+ uint_fast32_t nrules = _NL_CURRENT_WORD (LC_COLLATE, _NL_COLLATE_NRULES);
+
+ if (nrules != 0)
+ {
+ table = (const int32_t *) _NL_CURRENT (LC_COLLATE, _NL_COLLATE_TABLEMB);
+ extra = (const unsigned char *)
+ _NL_CURRENT (LC_COLLATE, _NL_COLLATE_EXTRAMB);
+ indirect = (const int32_t *) _NL_CURRENT (LC_COLLATE,
+ _NL_COLLATE_INDIRECTMB);
+ p = pstr->mbs + idx;
+ findidx (table, indirect, extra, &p, pstr->len - idx);
+ return p - pstr->mbs - idx;
+ }
+#endif /* _LIBC */
+
+ return 1;
+}
+
+#ifdef _LIBC
+# if __GNUC__ >= 7
+# define FALLTHROUGH __attribute__ ((__fallthrough__))
+# else
+# define FALLTHROUGH ((void) 0)
+# endif
+#else
+# include "attribute.h"
+#endif
+
+#endif /* _REGEX_INTERNAL_H */
diff --git a/lib/regexec.c b/lib/regexec.c
new file mode 100644
index 00000000000..521cb028415
--- /dev/null
+++ b/lib/regexec.c
@@ -0,0 +1,4221 @@
+/* Extended regular expression matching and search library.
+ Copyright (C) 2002-2022 Free Software Foundation, Inc.
+ This file is part of the GNU C Library.
+ Contributed by Isamu Hasegawa <isamu@yamato.ibm.com>.
+
+ The GNU C Library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Lesser General Public
+ License as published by the Free Software Foundation; either
+ version 2.1 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
+ Lesser General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public
+ License along with the GNU C Library; if not, see
+ <https://www.gnu.org/licenses/>. */
+
+static reg_errcode_t match_ctx_init (re_match_context_t *cache, int eflags,
+ Idx n);
+static void match_ctx_clean (re_match_context_t *mctx);
+static void match_ctx_free (re_match_context_t *cache);
+static reg_errcode_t match_ctx_add_entry (re_match_context_t *cache, Idx node,
+ Idx str_idx, Idx from, Idx to);
+static Idx search_cur_bkref_entry (const re_match_context_t *mctx, Idx str_idx);
+static reg_errcode_t match_ctx_add_subtop (re_match_context_t *mctx, Idx node,
+ Idx str_idx);
+static re_sub_match_last_t * match_ctx_add_sublast (re_sub_match_top_t *subtop,
+ Idx node, Idx str_idx);
+static void sift_ctx_init (re_sift_context_t *sctx, re_dfastate_t **sifted_sts,
+ re_dfastate_t **limited_sts, Idx last_node,
+ Idx last_str_idx);
+static reg_errcode_t re_search_internal (const regex_t *preg,
+ const char *string, Idx length,
+ Idx start, Idx last_start, Idx stop,
+ size_t nmatch, regmatch_t pmatch[],
+ int eflags);
+static regoff_t re_search_2_stub (struct re_pattern_buffer *bufp,
+ const char *string1, Idx length1,
+ const char *string2, Idx length2,
+ Idx start, regoff_t range,
+ struct re_registers *regs,
+ Idx stop, bool ret_len);
+static regoff_t re_search_stub (struct re_pattern_buffer *bufp,
+ const char *string, Idx length, Idx start,
+ regoff_t range, Idx stop,
+ struct re_registers *regs,
+ bool ret_len);
+static unsigned re_copy_regs (struct re_registers *regs, regmatch_t *pmatch,
+ Idx nregs, int regs_allocated);
+static reg_errcode_t prune_impossible_nodes (re_match_context_t *mctx);
+static Idx check_matching (re_match_context_t *mctx, bool fl_longest_match,
+ Idx *p_match_first);
+static Idx check_halt_state_context (const re_match_context_t *mctx,
+ const re_dfastate_t *state, Idx idx);
+static void update_regs (const re_dfa_t *dfa, regmatch_t *pmatch,
+ regmatch_t *prev_idx_match, Idx cur_node,
+ Idx cur_idx, Idx nmatch);
+static reg_errcode_t push_fail_stack (struct re_fail_stack_t *fs,
+ Idx str_idx, Idx dest_node, Idx nregs,
+ regmatch_t *regs, regmatch_t *prevregs,
+ re_node_set *eps_via_nodes);
+static reg_errcode_t set_regs (const regex_t *preg,
+ const re_match_context_t *mctx,
+ size_t nmatch, regmatch_t *pmatch,
+ bool fl_backtrack);
+static reg_errcode_t free_fail_stack_return (struct re_fail_stack_t *fs);
+
+static int sift_states_iter_mb (const re_match_context_t *mctx,
+ re_sift_context_t *sctx,
+ Idx node_idx, Idx str_idx, Idx max_str_idx);
+static reg_errcode_t sift_states_backward (const re_match_context_t *mctx,
+ re_sift_context_t *sctx);
+static reg_errcode_t build_sifted_states (const re_match_context_t *mctx,
+ re_sift_context_t *sctx, Idx str_idx,
+ re_node_set *cur_dest);
+static reg_errcode_t update_cur_sifted_state (const re_match_context_t *mctx,
+ re_sift_context_t *sctx,
+ Idx str_idx,
+ re_node_set *dest_nodes);
+static reg_errcode_t add_epsilon_src_nodes (const re_dfa_t *dfa,
+ re_node_set *dest_nodes,
+ const re_node_set *candidates);
+static bool check_dst_limits (const re_match_context_t *mctx,
+ const re_node_set *limits,
+ Idx dst_node, Idx dst_idx, Idx src_node,
+ Idx src_idx);
+static int check_dst_limits_calc_pos_1 (const re_match_context_t *mctx,
+ int boundaries, Idx subexp_idx,
+ Idx from_node, Idx bkref_idx);
+static int check_dst_limits_calc_pos (const re_match_context_t *mctx,
+ Idx limit, Idx subexp_idx,
+ Idx node, Idx str_idx,
+ Idx bkref_idx);
+static reg_errcode_t check_subexp_limits (const re_dfa_t *dfa,
+ re_node_set *dest_nodes,
+ const re_node_set *candidates,
+ re_node_set *limits,
+ struct re_backref_cache_entry *bkref_ents,
+ Idx str_idx);
+static reg_errcode_t sift_states_bkref (const re_match_context_t *mctx,
+ re_sift_context_t *sctx,
+ Idx str_idx, const re_node_set *candidates);
+static reg_errcode_t merge_state_array (const re_dfa_t *dfa,
+ re_dfastate_t **dst,
+ re_dfastate_t **src, Idx num);
+static re_dfastate_t *find_recover_state (reg_errcode_t *err,
+ re_match_context_t *mctx);
+static re_dfastate_t *transit_state (reg_errcode_t *err,
+ re_match_context_t *mctx,
+ re_dfastate_t *state);
+static re_dfastate_t *merge_state_with_log (reg_errcode_t *err,
+ re_match_context_t *mctx,
+ re_dfastate_t *next_state);
+static reg_errcode_t check_subexp_matching_top (re_match_context_t *mctx,
+ re_node_set *cur_nodes,
+ Idx str_idx);
+#if 0
+static re_dfastate_t *transit_state_sb (reg_errcode_t *err,
+ re_match_context_t *mctx,
+ re_dfastate_t *pstate);
+#endif
+static reg_errcode_t transit_state_mb (re_match_context_t *mctx,
+ re_dfastate_t *pstate);
+static reg_errcode_t transit_state_bkref (re_match_context_t *mctx,
+ const re_node_set *nodes);
+static reg_errcode_t get_subexp (re_match_context_t *mctx,
+ Idx bkref_node, Idx bkref_str_idx);
+static reg_errcode_t get_subexp_sub (re_match_context_t *mctx,
+ const re_sub_match_top_t *sub_top,
+ re_sub_match_last_t *sub_last,
+ Idx bkref_node, Idx bkref_str);
+static Idx find_subexp_node (const re_dfa_t *dfa, const re_node_set *nodes,
+ Idx subexp_idx, int type);
+static reg_errcode_t check_arrival (re_match_context_t *mctx,
+ state_array_t *path, Idx top_node,
+ Idx top_str, Idx last_node, Idx last_str,
+ int type);
+static reg_errcode_t check_arrival_add_next_nodes (re_match_context_t *mctx,
+ Idx str_idx,
+ re_node_set *cur_nodes,
+ re_node_set *next_nodes);
+static reg_errcode_t check_arrival_expand_ecl (const re_dfa_t *dfa,
+ re_node_set *cur_nodes,
+ Idx ex_subexp, int type);
+static reg_errcode_t check_arrival_expand_ecl_sub (const re_dfa_t *dfa,
+ re_node_set *dst_nodes,
+ Idx target, Idx ex_subexp,
+ int type);
+static reg_errcode_t expand_bkref_cache (re_match_context_t *mctx,
+ re_node_set *cur_nodes, Idx cur_str,
+ Idx subexp_num, int type);
+static bool build_trtable (const re_dfa_t *dfa, re_dfastate_t *state);
+static int check_node_accept_bytes (const re_dfa_t *dfa, Idx node_idx,
+ const re_string_t *input, Idx idx);
+#ifdef _LIBC
+static unsigned int find_collation_sequence_value (const unsigned char *mbs,
+ size_t name_len);
+#endif
+static Idx group_nodes_into_DFAstates (const re_dfa_t *dfa,
+ const re_dfastate_t *state,
+ re_node_set *states_node,
+ bitset_t *states_ch);
+static bool check_node_accept (const re_match_context_t *mctx,
+ const re_token_t *node, Idx idx);
+static reg_errcode_t extend_buffers (re_match_context_t *mctx, int min_len);
+
+/* Entry point for POSIX code. */
+
+/* regexec searches for a given pattern, specified by PREG, in the
+ string STRING.
+
+ If NMATCH is zero or REG_NOSUB was set in the cflags argument to
+ 'regcomp', we ignore PMATCH. Otherwise, we assume PMATCH has at
+ least NMATCH elements, and we set them to the offsets of the
+ corresponding matched substrings.
+
+ EFLAGS specifies "execution flags" which affect matching: if
+ REG_NOTBOL is set, then ^ does not match at the beginning of the
+ string; if REG_NOTEOL is set, then $ does not match at the end.
+
+ Return 0 if a match is found, REG_NOMATCH if not, REG_BADPAT if
+ EFLAGS is invalid. */
+
+int
+regexec (const regex_t *__restrict preg, const char *__restrict string,
+ size_t nmatch, regmatch_t pmatch[_REGEX_NELTS (nmatch)], int eflags)
+{
+ reg_errcode_t err;
+ Idx start, length;
+ re_dfa_t *dfa = preg->buffer;
+
+ if (eflags & ~(REG_NOTBOL | REG_NOTEOL | REG_STARTEND))
+ return REG_BADPAT;
+
+ if (eflags & REG_STARTEND)
+ {
+ start = pmatch[0].rm_so;
+ length = pmatch[0].rm_eo;
+ }
+ else
+ {
+ start = 0;
+ length = strlen (string);
+ }
+
+ lock_lock (dfa->lock);
+ if (preg->no_sub)
+ err = re_search_internal (preg, string, length, start, length,
+ length, 0, NULL, eflags);
+ else
+ err = re_search_internal (preg, string, length, start, length,
+ length, nmatch, pmatch, eflags);
+ lock_unlock (dfa->lock);
+ return err != REG_NOERROR;
+}
+
+#ifdef _LIBC
+libc_hidden_def (__regexec)
+
+# include <shlib-compat.h>
+versioned_symbol (libc, __regexec, regexec, GLIBC_2_3_4);
+
+# if SHLIB_COMPAT (libc, GLIBC_2_0, GLIBC_2_3_4)
+__typeof__ (__regexec) __compat_regexec;
+
+int
+attribute_compat_text_section
+__compat_regexec (const regex_t *__restrict preg,
+ const char *__restrict string, size_t nmatch,
+ regmatch_t pmatch[_REGEX_NELTS (nmatch)], int eflags)
+{
+ return regexec (preg, string, nmatch, pmatch,
+ eflags & (REG_NOTBOL | REG_NOTEOL));
+}
+compat_symbol (libc, __compat_regexec, regexec, GLIBC_2_0);
+# endif
+#endif
+
+/* Entry points for GNU code. */
+
+/* re_match, re_search, re_match_2, re_search_2
+
+ The former two functions operate on STRING with length LENGTH,
+ while the later two operate on concatenation of STRING1 and STRING2
+ with lengths LENGTH1 and LENGTH2, respectively.
+
+ re_match() matches the compiled pattern in BUFP against the string,
+ starting at index START.
+
+ re_search() first tries matching at index START, then it tries to match
+ starting from index START + 1, and so on. The last start position tried
+ is START + RANGE. (Thus RANGE = 0 forces re_search to operate the same
+ way as re_match().)
+
+ The parameter STOP of re_{match,search}_2 specifies that no match exceeding
+ the first STOP characters of the concatenation of the strings should be
+ concerned.
+
+ If REGS is not NULL, and BUFP->no_sub is not set, the offsets of the match
+ and all groups is stored in REGS. (For the "_2" variants, the offsets are
+ computed relative to the concatenation, not relative to the individual
+ strings.)
+
+ On success, re_match* functions return the length of the match, re_search*
+ return the position of the start of the match. They return -1 on
+ match failure, -2 on error. */
+
+regoff_t
+re_match (struct re_pattern_buffer *bufp, const char *string, Idx length,
+ Idx start, struct re_registers *regs)
+{
+ return re_search_stub (bufp, string, length, start, 0, length, regs, true);
+}
+#ifdef _LIBC
+weak_alias (__re_match, re_match)
+#endif
+
+regoff_t
+re_search (struct re_pattern_buffer *bufp, const char *string, Idx length,
+ Idx start, regoff_t range, struct re_registers *regs)
+{
+ return re_search_stub (bufp, string, length, start, range, length, regs,
+ false);
+}
+#ifdef _LIBC
+weak_alias (__re_search, re_search)
+#endif
+
+regoff_t
+re_match_2 (struct re_pattern_buffer *bufp, const char *string1, Idx length1,
+ const char *string2, Idx length2, Idx start,
+ struct re_registers *regs, Idx stop)
+{
+ return re_search_2_stub (bufp, string1, length1, string2, length2,
+ start, 0, regs, stop, true);
+}
+#ifdef _LIBC
+weak_alias (__re_match_2, re_match_2)
+#endif
+
+regoff_t
+re_search_2 (struct re_pattern_buffer *bufp, const char *string1, Idx length1,
+ const char *string2, Idx length2, Idx start, regoff_t range,
+ struct re_registers *regs, Idx stop)
+{
+ return re_search_2_stub (bufp, string1, length1, string2, length2,
+ start, range, regs, stop, false);
+}
+#ifdef _LIBC
+weak_alias (__re_search_2, re_search_2)
+#endif
+
+static regoff_t
+re_search_2_stub (struct re_pattern_buffer *bufp, const char *string1,
+ Idx length1, const char *string2, Idx length2, Idx start,
+ regoff_t range, struct re_registers *regs,
+ Idx stop, bool ret_len)
+{
+ const char *str;
+ regoff_t rval;
+ Idx len;
+ char *s = NULL;
+
+ if (__glibc_unlikely ((length1 < 0 || length2 < 0 || stop < 0
+ || INT_ADD_WRAPV (length1, length2, &len))))
+ return -2;
+
+ /* Concatenate the strings. */
+ if (length2 > 0)
+ if (length1 > 0)
+ {
+ s = re_malloc (char, len);
+
+ if (__glibc_unlikely (s == NULL))
+ return -2;
+#ifdef _LIBC
+ memcpy (__mempcpy (s, string1, length1), string2, length2);
+#else
+ memcpy (s, string1, length1);
+ memcpy (s + length1, string2, length2);
+#endif
+ str = s;
+ }
+ else
+ str = string2;
+ else
+ str = string1;
+
+ rval = re_search_stub (bufp, str, len, start, range, stop, regs,
+ ret_len);
+ re_free (s);
+ return rval;
+}
+
+/* The parameters have the same meaning as those of re_search.
+ Additional parameters:
+ If RET_LEN is true the length of the match is returned (re_match style);
+ otherwise the position of the match is returned. */
+
+static regoff_t
+re_search_stub (struct re_pattern_buffer *bufp, const char *string, Idx length,
+ Idx start, regoff_t range, Idx stop, struct re_registers *regs,
+ bool ret_len)
+{
+ reg_errcode_t result;
+ regmatch_t *pmatch;
+ Idx nregs;
+ regoff_t rval;
+ int eflags = 0;
+ re_dfa_t *dfa = bufp->buffer;
+ Idx last_start = start + range;
+
+ /* Check for out-of-range. */
+ if (__glibc_unlikely (start < 0 || start > length))
+ return -1;
+ if (__glibc_unlikely (length < last_start
+ || (0 <= range && last_start < start)))
+ last_start = length;
+ else if (__glibc_unlikely (last_start < 0
+ || (range < 0 && start <= last_start)))
+ last_start = 0;
+
+ lock_lock (dfa->lock);
+
+ eflags |= (bufp->not_bol) ? REG_NOTBOL : 0;
+ eflags |= (bufp->not_eol) ? REG_NOTEOL : 0;
+
+ /* Compile fastmap if we haven't yet. */
+ if (start < last_start && bufp->fastmap != NULL && !bufp->fastmap_accurate)
+ re_compile_fastmap (bufp);
+
+ if (__glibc_unlikely (bufp->no_sub))
+ regs = NULL;
+
+ /* We need at least 1 register. */
+ if (regs == NULL)
+ nregs = 1;
+ else if (__glibc_unlikely (bufp->regs_allocated == REGS_FIXED
+ && regs->num_regs <= bufp->re_nsub))
+ {
+ nregs = regs->num_regs;
+ if (__glibc_unlikely (nregs < 1))
+ {
+ /* Nothing can be copied to regs. */
+ regs = NULL;
+ nregs = 1;
+ }
+ }
+ else
+ nregs = bufp->re_nsub + 1;
+ pmatch = re_malloc (regmatch_t, nregs);
+ if (__glibc_unlikely (pmatch == NULL))
+ {
+ rval = -2;
+ goto out;
+ }
+
+ result = re_search_internal (bufp, string, length, start, last_start, stop,
+ nregs, pmatch, eflags);
+
+ rval = 0;
+
+ /* I hope we needn't fill their regs with -1's when no match was found. */
+ if (result != REG_NOERROR)
+ rval = result == REG_NOMATCH ? -1 : -2;
+ else if (regs != NULL)
+ {
+ /* If caller wants register contents data back, copy them. */
+ bufp->regs_allocated = re_copy_regs (regs, pmatch, nregs,
+ bufp->regs_allocated);
+ if (__glibc_unlikely (bufp->regs_allocated == REGS_UNALLOCATED))
+ rval = -2;
+ }
+
+ if (__glibc_likely (rval == 0))
+ {
+ if (ret_len)
+ {
+ DEBUG_ASSERT (pmatch[0].rm_so == start);
+ rval = pmatch[0].rm_eo - start;
+ }
+ else
+ rval = pmatch[0].rm_so;
+ }
+ re_free (pmatch);
+ out:
+ lock_unlock (dfa->lock);
+ return rval;
+}
+
+static unsigned
+re_copy_regs (struct re_registers *regs, regmatch_t *pmatch, Idx nregs,
+ int regs_allocated)
+{
+ int rval = REGS_REALLOCATE;
+ Idx i;
+ Idx need_regs = nregs + 1;
+ /* We need one extra element beyond 'num_regs' for the '-1' marker GNU code
+ uses. */
+
+ /* Have the register data arrays been allocated? */
+ if (regs_allocated == REGS_UNALLOCATED)
+ { /* No. So allocate them with malloc. */
+ regs->start = re_malloc (regoff_t, need_regs);
+ if (__glibc_unlikely (regs->start == NULL))
+ return REGS_UNALLOCATED;
+ regs->end = re_malloc (regoff_t, need_regs);
+ if (__glibc_unlikely (regs->end == NULL))
+ {
+ re_free (regs->start);
+ return REGS_UNALLOCATED;
+ }
+ regs->num_regs = need_regs;
+ }
+ else if (regs_allocated == REGS_REALLOCATE)
+ { /* Yes. If we need more elements than were already
+ allocated, reallocate them. If we need fewer, just
+ leave it alone. */
+ if (__glibc_unlikely (need_regs > regs->num_regs))
+ {
+ regoff_t *new_start = re_realloc (regs->start, regoff_t, need_regs);
+ regoff_t *new_end;
+ if (__glibc_unlikely (new_start == NULL))
+ return REGS_UNALLOCATED;
+ new_end = re_realloc (regs->end, regoff_t, need_regs);
+ if (__glibc_unlikely (new_end == NULL))
+ {
+ re_free (new_start);
+ return REGS_UNALLOCATED;
+ }
+ regs->start = new_start;
+ regs->end = new_end;
+ regs->num_regs = need_regs;
+ }
+ }
+ else
+ {
+ DEBUG_ASSERT (regs_allocated == REGS_FIXED);
+ /* This function may not be called with REGS_FIXED and nregs too big. */
+ DEBUG_ASSERT (nregs <= regs->num_regs);
+ rval = REGS_FIXED;
+ }
+
+ /* Copy the regs. */
+ for (i = 0; i < nregs; ++i)
+ {
+ regs->start[i] = pmatch[i].rm_so;
+ regs->end[i] = pmatch[i].rm_eo;
+ }
+ for ( ; i < regs->num_regs; ++i)
+ regs->start[i] = regs->end[i] = -1;
+
+ return rval;
+}
+
+/* Set REGS to hold NUM_REGS registers, storing them in STARTS and
+ ENDS. Subsequent matches using PATTERN_BUFFER and REGS will use
+ this memory for recording register information. STARTS and ENDS
+ must be allocated using the malloc library routine, and must each
+ be at least NUM_REGS * sizeof (regoff_t) bytes long.
+
+ If NUM_REGS == 0, then subsequent matches should allocate their own
+ register data.
+
+ Unless this function is called, the first search or match using
+ PATTERN_BUFFER will allocate its own register data, without
+ freeing the old data. */
+
+void
+re_set_registers (struct re_pattern_buffer *bufp, struct re_registers *regs,
+ __re_size_t num_regs, regoff_t *starts, regoff_t *ends)
+{
+ if (num_regs)
+ {
+ bufp->regs_allocated = REGS_REALLOCATE;
+ regs->num_regs = num_regs;
+ regs->start = starts;
+ regs->end = ends;
+ }
+ else
+ {
+ bufp->regs_allocated = REGS_UNALLOCATED;
+ regs->num_regs = 0;
+ regs->start = regs->end = NULL;
+ }
+}
+#ifdef _LIBC
+weak_alias (__re_set_registers, re_set_registers)
+#endif
+
+/* Entry points compatible with 4.2 BSD regex library. We don't define
+ them unless specifically requested. */
+
+#if defined _REGEX_RE_COMP || defined _LIBC
+int
+# ifdef _LIBC
+weak_function
+# endif
+re_exec (const char *s)
+{
+ return 0 == regexec (&re_comp_buf, s, 0, NULL, 0);
+}
+#endif /* _REGEX_RE_COMP */
+
+/* Internal entry point. */
+
+/* Searches for a compiled pattern PREG in the string STRING, whose
+ length is LENGTH. NMATCH, PMATCH, and EFLAGS have the same
+ meaning as with regexec. LAST_START is START + RANGE, where
+ START and RANGE have the same meaning as with re_search.
+ Return REG_NOERROR if we find a match, and REG_NOMATCH if not,
+ otherwise return the error code.
+ Note: We assume front end functions already check ranges.
+ (0 <= LAST_START && LAST_START <= LENGTH) */
+
+static reg_errcode_t
+__attribute_warn_unused_result__
+re_search_internal (const regex_t *preg, const char *string, Idx length,
+ Idx start, Idx last_start, Idx stop, size_t nmatch,
+ regmatch_t pmatch[], int eflags)
+{
+ reg_errcode_t err;
+ const re_dfa_t *dfa = preg->buffer;
+ Idx left_lim, right_lim;
+ int incr;
+ bool fl_longest_match;
+ int match_kind;
+ Idx match_first;
+ Idx match_last = -1;
+ Idx extra_nmatch;
+ bool sb;
+ int ch;
+ re_match_context_t mctx = { .dfa = dfa };
+ char *fastmap = ((preg->fastmap != NULL && preg->fastmap_accurate
+ && start != last_start && !preg->can_be_null)
+ ? preg->fastmap : NULL);
+ RE_TRANSLATE_TYPE t = preg->translate;
+
+ extra_nmatch = (nmatch > preg->re_nsub) ? nmatch - (preg->re_nsub + 1) : 0;
+ nmatch -= extra_nmatch;
+
+ /* Check if the DFA haven't been compiled. */
+ if (__glibc_unlikely (preg->used == 0 || dfa->init_state == NULL
+ || dfa->init_state_word == NULL
+ || dfa->init_state_nl == NULL
+ || dfa->init_state_begbuf == NULL))
+ return REG_NOMATCH;
+
+ /* We assume front-end functions already check them. */
+ 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,
+ we'll never use init_state_nl, so do not check it. */
+ if (dfa->init_state->nodes.nelem == 0
+ && dfa->init_state_word->nodes.nelem == 0
+ && (dfa->init_state_nl->nodes.nelem == 0
+ || !preg->newline_anchor))
+ {
+ if (start != 0 && last_start != 0)
+ return REG_NOMATCH;
+ start = last_start = 0;
+ }
+
+ /* We must check the longest matching, if nmatch > 0. */
+ fl_longest_match = (nmatch != 0 || dfa->nbackref);
+
+ err = re_string_allocate (&mctx.input, string, length, dfa->nodes_len + 1,
+ preg->translate, (preg->syntax & RE_ICASE) != 0,
+ dfa);
+ if (__glibc_unlikely (err != REG_NOERROR))
+ goto free_return;
+ mctx.input.stop = stop;
+ mctx.input.raw_stop = stop;
+ mctx.input.newline_anchor = preg->newline_anchor;
+
+ err = match_ctx_init (&mctx, eflags, dfa->nbackref * 2);
+ if (__glibc_unlikely (err != REG_NOERROR))
+ goto free_return;
+
+ /* We will log all the DFA states through which the dfa pass,
+ if nmatch > 1, or this dfa has "multibyte node", which is a
+ back-reference or a node which can accept multibyte character or
+ multi character collating element. */
+ if (nmatch > 1 || dfa->has_mb_node)
+ {
+ /* Avoid overflow. */
+ if (__glibc_unlikely ((MIN (IDX_MAX, SIZE_MAX / sizeof (re_dfastate_t *))
+ <= mctx.input.bufs_len)))
+ {
+ err = REG_ESPACE;
+ goto free_return;
+ }
+
+ mctx.state_log = re_malloc (re_dfastate_t *, mctx.input.bufs_len + 1);
+ if (__glibc_unlikely (mctx.state_log == NULL))
+ {
+ err = REG_ESPACE;
+ goto free_return;
+ }
+ }
+
+ match_first = start;
+ mctx.input.tip_context = (eflags & REG_NOTBOL) ? CONTEXT_BEGBUF
+ : CONTEXT_NEWLINE | CONTEXT_BEGBUF;
+
+ /* Check incrementally whether the input string matches. */
+ incr = (last_start < start) ? -1 : 1;
+ left_lim = (last_start < start) ? last_start : start;
+ right_lim = (last_start < start) ? start : last_start;
+ sb = dfa->mb_cur_max == 1;
+ match_kind =
+ (fastmap
+ ? ((sb || !(preg->syntax & RE_ICASE || t) ? 4 : 0)
+ | (start <= last_start ? 2 : 0)
+ | (t != NULL ? 1 : 0))
+ : 8);
+
+ for (;; match_first += incr)
+ {
+ err = REG_NOMATCH;
+ if (match_first < left_lim || right_lim < match_first)
+ goto free_return;
+
+ /* Advance as rapidly as possible through the string, until we
+ find a plausible place to start matching. This may be done
+ with varying efficiency, so there are various possibilities:
+ only the most common of them are specialized, in order to
+ save on code size. We use a switch statement for speed. */
+ switch (match_kind)
+ {
+ case 8:
+ /* No fastmap. */
+ break;
+
+ case 7:
+ /* Fastmap with single-byte translation, match forward. */
+ while (__glibc_likely (match_first < right_lim)
+ && !fastmap[t[(unsigned char) string[match_first]]])
+ ++match_first;
+ goto forward_match_found_start_or_reached_end;
+
+ case 6:
+ /* Fastmap without translation, match forward. */
+ while (__glibc_likely (match_first < right_lim)
+ && !fastmap[(unsigned char) string[match_first]])
+ ++match_first;
+
+ forward_match_found_start_or_reached_end:
+ if (__glibc_unlikely (match_first == right_lim))
+ {
+ ch = match_first >= length
+ ? 0 : (unsigned char) string[match_first];
+ if (!fastmap[t ? t[ch] : ch])
+ goto free_return;
+ }
+ break;
+
+ case 4:
+ case 5:
+ /* Fastmap without multi-byte translation, match backwards. */
+ while (match_first >= left_lim)
+ {
+ ch = match_first >= length
+ ? 0 : (unsigned char) string[match_first];
+ if (fastmap[t ? t[ch] : ch])
+ break;
+ --match_first;
+ }
+ if (match_first < left_lim)
+ goto free_return;
+ break;
+
+ default:
+ /* In this case, we can't determine easily the current byte,
+ since it might be a component byte of a multibyte
+ character. Then we use the constructed buffer instead. */
+ for (;;)
+ {
+ /* If MATCH_FIRST is out of the valid range, reconstruct the
+ buffers. */
+ __re_size_t offset = match_first - mctx.input.raw_mbs_idx;
+ if (__glibc_unlikely (offset
+ >= (__re_size_t) mctx.input.valid_raw_len))
+ {
+ err = re_string_reconstruct (&mctx.input, match_first,
+ eflags);
+ if (__glibc_unlikely (err != REG_NOERROR))
+ goto free_return;
+
+ offset = match_first - mctx.input.raw_mbs_idx;
+ }
+ /* Use buffer byte if OFFSET is in buffer, otherwise '\0'. */
+ ch = (offset < mctx.input.valid_len
+ ? re_string_byte_at (&mctx.input, offset) : 0);
+ if (fastmap[ch])
+ break;
+ match_first += incr;
+ if (match_first < left_lim || match_first > right_lim)
+ {
+ err = REG_NOMATCH;
+ goto free_return;
+ }
+ }
+ break;
+ }
+
+ /* Reconstruct the buffers so that the matcher can assume that
+ the matching starts from the beginning of the buffer. */
+ err = re_string_reconstruct (&mctx.input, match_first, eflags);
+ if (__glibc_unlikely (err != REG_NOERROR))
+ goto free_return;
+
+ /* Don't consider this char as a possible match start if it part,
+ yet isn't the head, of a multibyte character. */
+ if (!sb && !re_string_first_byte (&mctx.input, 0))
+ continue;
+
+ /* It seems to be appropriate one, then use the matcher. */
+ /* We assume that the matching starts from 0. */
+ mctx.state_log_top = mctx.nbkref_ents = mctx.max_mb_elem_len = 0;
+ match_last = check_matching (&mctx, fl_longest_match,
+ start <= last_start ? &match_first : NULL);
+ if (match_last != -1)
+ {
+ if (__glibc_unlikely (match_last == -2))
+ {
+ err = REG_ESPACE;
+ goto free_return;
+ }
+ else
+ {
+ mctx.match_last = match_last;
+ if ((!preg->no_sub && nmatch > 1) || dfa->nbackref)
+ {
+ re_dfastate_t *pstate = mctx.state_log[match_last];
+ mctx.last_node = check_halt_state_context (&mctx, pstate,
+ match_last);
+ }
+ if ((!preg->no_sub && nmatch > 1 && dfa->has_plural_match)
+ || dfa->nbackref)
+ {
+ err = prune_impossible_nodes (&mctx);
+ if (err == REG_NOERROR)
+ break;
+ if (__glibc_unlikely (err != REG_NOMATCH))
+ goto free_return;
+ match_last = -1;
+ }
+ else
+ break; /* We found a match. */
+ }
+ }
+
+ match_ctx_clean (&mctx);
+ }
+
+ DEBUG_ASSERT (match_last != -1);
+ DEBUG_ASSERT (err == REG_NOERROR);
+
+ /* Set pmatch[] if we need. */
+ if (nmatch > 0)
+ {
+ Idx reg_idx;
+
+ /* Initialize registers. */
+ for (reg_idx = 1; reg_idx < nmatch; ++reg_idx)
+ pmatch[reg_idx].rm_so = pmatch[reg_idx].rm_eo = -1;
+
+ /* Set the points where matching start/end. */
+ pmatch[0].rm_so = 0;
+ pmatch[0].rm_eo = mctx.match_last;
+ /* FIXME: This function should fail if mctx.match_last exceeds
+ the maximum possible regoff_t value. We need a new error
+ code REG_OVERFLOW. */
+
+ if (!preg->no_sub && nmatch > 1)
+ {
+ err = set_regs (preg, &mctx, nmatch, pmatch,
+ dfa->has_plural_match && dfa->nbackref > 0);
+ if (__glibc_unlikely (err != REG_NOERROR))
+ goto free_return;
+ }
+
+ /* At last, add the offset to each register, since we slid
+ the buffers so that we could assume that the matching starts
+ from 0. */
+ for (reg_idx = 0; reg_idx < nmatch; ++reg_idx)
+ if (pmatch[reg_idx].rm_so != -1)
+ {
+ if (__glibc_unlikely (mctx.input.offsets_needed != 0))
+ {
+ pmatch[reg_idx].rm_so =
+ (pmatch[reg_idx].rm_so == mctx.input.valid_len
+ ? mctx.input.valid_raw_len
+ : mctx.input.offsets[pmatch[reg_idx].rm_so]);
+ pmatch[reg_idx].rm_eo =
+ (pmatch[reg_idx].rm_eo == mctx.input.valid_len
+ ? mctx.input.valid_raw_len
+ : mctx.input.offsets[pmatch[reg_idx].rm_eo]);
+ }
+ pmatch[reg_idx].rm_so += match_first;
+ pmatch[reg_idx].rm_eo += match_first;
+ }
+ for (reg_idx = 0; reg_idx < extra_nmatch; ++reg_idx)
+ {
+ pmatch[nmatch + reg_idx].rm_so = -1;
+ pmatch[nmatch + reg_idx].rm_eo = -1;
+ }
+
+ if (dfa->subexp_map)
+ for (reg_idx = 0; reg_idx + 1 < nmatch; reg_idx++)
+ if (dfa->subexp_map[reg_idx] != reg_idx)
+ {
+ pmatch[reg_idx + 1].rm_so
+ = pmatch[dfa->subexp_map[reg_idx] + 1].rm_so;
+ pmatch[reg_idx + 1].rm_eo
+ = pmatch[dfa->subexp_map[reg_idx] + 1].rm_eo;
+ }
+ }
+
+ free_return:
+ re_free (mctx.state_log);
+ if (dfa->nbackref)
+ match_ctx_free (&mctx);
+ re_string_destruct (&mctx.input);
+ return err;
+}
+
+static reg_errcode_t
+__attribute_warn_unused_result__
+prune_impossible_nodes (re_match_context_t *mctx)
+{
+ const re_dfa_t *const dfa = mctx->dfa;
+ Idx halt_node, match_last;
+ reg_errcode_t ret;
+ re_dfastate_t **sifted_states;
+ re_dfastate_t **lim_states = NULL;
+ re_sift_context_t sctx;
+ DEBUG_ASSERT (mctx->state_log != NULL);
+ match_last = mctx->match_last;
+ halt_node = mctx->last_node;
+
+ /* Avoid overflow. */
+ if (__glibc_unlikely (MIN (IDX_MAX, SIZE_MAX / sizeof (re_dfastate_t *))
+ <= match_last))
+ return REG_ESPACE;
+
+ sifted_states = re_malloc (re_dfastate_t *, match_last + 1);
+ if (__glibc_unlikely (sifted_states == NULL))
+ {
+ ret = REG_ESPACE;
+ goto free_return;
+ }
+ if (dfa->nbackref)
+ {
+ lim_states = re_malloc (re_dfastate_t *, match_last + 1);
+ if (__glibc_unlikely (lim_states == NULL))
+ {
+ ret = REG_ESPACE;
+ goto free_return;
+ }
+ while (1)
+ {
+ memset (lim_states, '\0',
+ sizeof (re_dfastate_t *) * (match_last + 1));
+ sift_ctx_init (&sctx, sifted_states, lim_states, halt_node,
+ match_last);
+ ret = sift_states_backward (mctx, &sctx);
+ re_node_set_free (&sctx.limits);
+ if (__glibc_unlikely (ret != REG_NOERROR))
+ goto free_return;
+ if (sifted_states[0] != NULL || lim_states[0] != NULL)
+ break;
+ do
+ {
+ --match_last;
+ if (match_last < 0)
+ {
+ ret = REG_NOMATCH;
+ goto free_return;
+ }
+ } while (mctx->state_log[match_last] == NULL
+ || !mctx->state_log[match_last]->halt);
+ halt_node = check_halt_state_context (mctx,
+ mctx->state_log[match_last],
+ match_last);
+ }
+ ret = merge_state_array (dfa, sifted_states, lim_states,
+ match_last + 1);
+ re_free (lim_states);
+ lim_states = NULL;
+ if (__glibc_unlikely (ret != REG_NOERROR))
+ goto free_return;
+ }
+ else
+ {
+ sift_ctx_init (&sctx, sifted_states, lim_states, halt_node, match_last);
+ ret = sift_states_backward (mctx, &sctx);
+ re_node_set_free (&sctx.limits);
+ if (__glibc_unlikely (ret != REG_NOERROR))
+ goto free_return;
+ if (sifted_states[0] == NULL)
+ {
+ ret = REG_NOMATCH;
+ goto free_return;
+ }
+ }
+ re_free (mctx->state_log);
+ mctx->state_log = sifted_states;
+ sifted_states = NULL;
+ mctx->last_node = halt_node;
+ mctx->match_last = match_last;
+ ret = REG_NOERROR;
+ free_return:
+ re_free (sifted_states);
+ re_free (lim_states);
+ return ret;
+}
+
+/* Acquire an initial state and return it.
+ We must select appropriate initial state depending on the context,
+ since initial states may have constraints like "\<", "^", etc.. */
+
+static __always_inline re_dfastate_t *
+acquire_init_state_context (reg_errcode_t *err, const re_match_context_t *mctx,
+ Idx idx)
+{
+ const re_dfa_t *const dfa = mctx->dfa;
+ if (dfa->init_state->has_constraint)
+ {
+ unsigned int context;
+ context = re_string_context_at (&mctx->input, idx - 1, mctx->eflags);
+ if (IS_WORD_CONTEXT (context))
+ return dfa->init_state_word;
+ else if (IS_ORDINARY_CONTEXT (context))
+ return dfa->init_state;
+ else if (IS_BEGBUF_CONTEXT (context) && IS_NEWLINE_CONTEXT (context))
+ return dfa->init_state_begbuf;
+ else if (IS_NEWLINE_CONTEXT (context))
+ return dfa->init_state_nl;
+ else if (IS_BEGBUF_CONTEXT (context))
+ {
+ /* It is relatively rare case, then calculate on demand. */
+ return re_acquire_state_context (err, dfa,
+ dfa->init_state->entrance_nodes,
+ context);
+ }
+ else
+ /* Must not happen? */
+ return dfa->init_state;
+ }
+ else
+ return dfa->init_state;
+}
+
+/* Check whether the regular expression match input string INPUT or not,
+ and return the index where the matching end. Return -1 if
+ there is no match, and return -2 in case of an error.
+ FL_LONGEST_MATCH means we want the POSIX longest matching.
+ If P_MATCH_FIRST is not NULL, and the match fails, it is set to the
+ next place where we may want to try matching.
+ Note that the matcher assumes that the matching starts from the current
+ index of the buffer. */
+
+static Idx
+__attribute_warn_unused_result__
+check_matching (re_match_context_t *mctx, bool fl_longest_match,
+ Idx *p_match_first)
+{
+ const re_dfa_t *const dfa = mctx->dfa;
+ reg_errcode_t err;
+ Idx match = 0;
+ Idx match_last = -1;
+ Idx cur_str_idx = re_string_cur_idx (&mctx->input);
+ re_dfastate_t *cur_state;
+ bool at_init_state = p_match_first != NULL;
+ Idx next_start_idx = cur_str_idx;
+
+ err = REG_NOERROR;
+ cur_state = acquire_init_state_context (&err, mctx, cur_str_idx);
+ /* An initial state must not be NULL (invalid). */
+ if (__glibc_unlikely (cur_state == NULL))
+ {
+ DEBUG_ASSERT (err == REG_ESPACE);
+ return -2;
+ }
+
+ if (mctx->state_log != NULL)
+ {
+ mctx->state_log[cur_str_idx] = cur_state;
+
+ /* Check OP_OPEN_SUBEXP in the initial state in case that we use them
+ later. E.g. Processing back references. */
+ if (__glibc_unlikely (dfa->nbackref))
+ {
+ at_init_state = false;
+ err = check_subexp_matching_top (mctx, &cur_state->nodes, 0);
+ if (__glibc_unlikely (err != REG_NOERROR))
+ return err;
+
+ if (cur_state->has_backref)
+ {
+ err = transit_state_bkref (mctx, &cur_state->nodes);
+ if (__glibc_unlikely (err != REG_NOERROR))
+ return err;
+ }
+ }
+ }
+
+ /* If the RE accepts NULL string. */
+ if (__glibc_unlikely (cur_state->halt))
+ {
+ if (!cur_state->has_constraint
+ || check_halt_state_context (mctx, cur_state, cur_str_idx))
+ {
+ if (!fl_longest_match)
+ return cur_str_idx;
+ else
+ {
+ match_last = cur_str_idx;
+ match = 1;
+ }
+ }
+ }
+
+ while (!re_string_eoi (&mctx->input))
+ {
+ re_dfastate_t *old_state = cur_state;
+ Idx next_char_idx = re_string_cur_idx (&mctx->input) + 1;
+
+ if ((__glibc_unlikely (next_char_idx >= mctx->input.bufs_len)
+ && mctx->input.bufs_len < mctx->input.len)
+ || (__glibc_unlikely (next_char_idx >= mctx->input.valid_len)
+ && mctx->input.valid_len < mctx->input.len))
+ {
+ err = extend_buffers (mctx, next_char_idx + 1);
+ if (__glibc_unlikely (err != REG_NOERROR))
+ {
+ DEBUG_ASSERT (err == REG_ESPACE);
+ return -2;
+ }
+ }
+
+ cur_state = transit_state (&err, mctx, cur_state);
+ if (mctx->state_log != NULL)
+ cur_state = merge_state_with_log (&err, mctx, cur_state);
+
+ if (cur_state == NULL)
+ {
+ /* Reached the invalid state or an error. Try to recover a valid
+ state using the state log, if available and if we have not
+ already found a valid (even if not the longest) match. */
+ if (__glibc_unlikely (err != REG_NOERROR))
+ return -2;
+
+ if (mctx->state_log == NULL
+ || (match && !fl_longest_match)
+ || (cur_state = find_recover_state (&err, mctx)) == NULL)
+ break;
+ }
+
+ if (__glibc_unlikely (at_init_state))
+ {
+ if (old_state == cur_state)
+ next_start_idx = next_char_idx;
+ else
+ at_init_state = false;
+ }
+
+ if (cur_state->halt)
+ {
+ /* Reached a halt state.
+ Check the halt state can satisfy the current context. */
+ if (!cur_state->has_constraint
+ || check_halt_state_context (mctx, cur_state,
+ re_string_cur_idx (&mctx->input)))
+ {
+ /* We found an appropriate halt state. */
+ match_last = re_string_cur_idx (&mctx->input);
+ match = 1;
+
+ /* We found a match, do not modify match_first below. */
+ p_match_first = NULL;
+ if (!fl_longest_match)
+ break;
+ }
+ }
+ }
+
+ if (p_match_first)
+ *p_match_first += next_start_idx;
+
+ return match_last;
+}
+
+/* Check NODE match the current context. */
+
+static bool
+check_halt_node_context (const re_dfa_t *dfa, Idx node, unsigned int context)
+{
+ re_token_type_t type = dfa->nodes[node].type;
+ unsigned int constraint = dfa->nodes[node].constraint;
+ if (type != END_OF_RE)
+ return false;
+ if (!constraint)
+ return true;
+ if (NOT_SATISFY_NEXT_CONSTRAINT (constraint, context))
+ return false;
+ return true;
+}
+
+/* Check the halt state STATE match the current context.
+ Return 0 if not match, if the node, STATE has, is a halt node and
+ match the context, return the node. */
+
+static Idx
+check_halt_state_context (const re_match_context_t *mctx,
+ const re_dfastate_t *state, Idx idx)
+{
+ Idx i;
+ unsigned int context;
+ 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))
+ return state->nodes.elems[i];
+ return 0;
+}
+
+/* Compute the next node to which "NFA" transit from NODE("NFA" is a NFA
+ corresponding to the DFA).
+ Return the destination node, and update EPS_VIA_NODES;
+ return -1 on match failure, -2 on error. */
+
+static Idx
+proceed_next_node (const re_match_context_t *mctx, Idx nregs, regmatch_t *regs,
+ regmatch_t *prevregs,
+ Idx *pidx, Idx node, re_node_set *eps_via_nodes,
+ struct re_fail_stack_t *fs)
+{
+ const re_dfa_t *const dfa = mctx->dfa;
+ if (IS_EPSILON_NODE (dfa->nodes[node].type))
+ {
+ re_node_set *cur_nodes = &mctx->state_log[*pidx]->nodes;
+ re_node_set *edests = &dfa->edests[node];
+
+ if (! re_node_set_contains (eps_via_nodes, node))
+ {
+ bool ok = re_node_set_insert (eps_via_nodes, node);
+ if (__glibc_unlikely (! ok))
+ return -2;
+ }
+
+ /* Pick a valid destination, or return -1 if none is found. */
+ Idx dest_node = -1;
+ for (Idx i = 0; i < edests->nelem; i++)
+ {
+ Idx candidate = edests->elems[i];
+ if (!re_node_set_contains (cur_nodes, candidate))
+ continue;
+ if (dest_node == -1)
+ dest_node = candidate;
+
+ else
+ {
+ /* In order to avoid infinite loop like "(a*)*", return the second
+ epsilon-transition if the first was already considered. */
+ if (re_node_set_contains (eps_via_nodes, dest_node))
+ return candidate;
+
+ /* Otherwise, push the second epsilon-transition on the fail stack. */
+ else if (fs != NULL
+ && push_fail_stack (fs, *pidx, candidate, nregs, regs,
+ prevregs, eps_via_nodes))
+ return -2;
+
+ /* We know we are going to exit. */
+ break;
+ }
+ }
+ return dest_node;
+ }
+ else
+ {
+ Idx naccepted = 0;
+ re_token_type_t type = dfa->nodes[node].type;
+
+ if (dfa->nodes[node].accept_mb)
+ naccepted = check_node_accept_bytes (dfa, node, &mctx->input, *pidx);
+ else if (type == OP_BACK_REF)
+ {
+ Idx subexp_idx = dfa->nodes[node].opr.idx + 1;
+ if (subexp_idx < nregs)
+ naccepted = regs[subexp_idx].rm_eo - regs[subexp_idx].rm_so;
+ if (fs != NULL)
+ {
+ 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 (mctx->input.valid_len - *pidx < naccepted
+ || (memcmp (buf + regs[subexp_idx].rm_so, buf + *pidx,
+ naccepted)
+ != 0))
+ return -1;
+ }
+ }
+
+ if (naccepted == 0)
+ {
+ Idx dest_node;
+ bool ok = re_node_set_insert (eps_via_nodes, node);
+ if (__glibc_unlikely (! ok))
+ return -2;
+ dest_node = dfa->edests[node].elems[0];
+ if (re_node_set_contains (&mctx->state_log[*pidx]->nodes,
+ dest_node))
+ return dest_node;
+ }
+ }
+
+ if (naccepted != 0
+ || check_node_accept (mctx, dfa->nodes + node, *pidx))
+ {
+ Idx dest_node = dfa->nexts[node];
+ *pidx = (naccepted == 0) ? *pidx + 1 : *pidx + naccepted;
+ if (fs && (*pidx > mctx->match_last || mctx->state_log[*pidx] == NULL
+ || !re_node_set_contains (&mctx->state_log[*pidx]->nodes,
+ dest_node)))
+ return -1;
+ re_node_set_empty (eps_via_nodes);
+ return dest_node;
+ }
+ }
+ return -1;
+}
+
+static reg_errcode_t
+__attribute_warn_unused_result__
+push_fail_stack (struct re_fail_stack_t *fs, Idx str_idx, Idx dest_node,
+ Idx nregs, regmatch_t *regs, regmatch_t *prevregs,
+ re_node_set *eps_via_nodes)
+{
+ reg_errcode_t err;
+ Idx num = fs->num;
+ if (num == fs->alloc)
+ {
+ struct re_fail_stack_ent_t *new_array;
+ new_array = re_realloc (fs->stack, struct re_fail_stack_ent_t,
+ fs->alloc * 2);
+ if (new_array == NULL)
+ return REG_ESPACE;
+ fs->alloc *= 2;
+ fs->stack = new_array;
+ }
+ fs->stack[num].idx = str_idx;
+ fs->stack[num].node = dest_node;
+ fs->stack[num].regs = re_malloc (regmatch_t, 2 * nregs);
+ if (fs->stack[num].regs == NULL)
+ return REG_ESPACE;
+ fs->num = num + 1;
+ memcpy (fs->stack[num].regs, regs, sizeof (regmatch_t) * nregs);
+ memcpy (fs->stack[num].regs + nregs, prevregs, sizeof (regmatch_t) * nregs);
+ err = re_node_set_init_copy (&fs->stack[num].eps_via_nodes, eps_via_nodes);
+ return err;
+}
+
+static Idx
+pop_fail_stack (struct re_fail_stack_t *fs, Idx *pidx, Idx nregs,
+ regmatch_t *regs, regmatch_t *prevregs,
+ re_node_set *eps_via_nodes)
+{
+ if (fs == NULL || fs->num == 0)
+ return -1;
+ Idx num = --fs->num;
+ *pidx = fs->stack[num].idx;
+ memcpy (regs, fs->stack[num].regs, sizeof (regmatch_t) * nregs);
+ memcpy (prevregs, fs->stack[num].regs + nregs, sizeof (regmatch_t) * nregs);
+ re_node_set_free (eps_via_nodes);
+ re_free (fs->stack[num].regs);
+ *eps_via_nodes = fs->stack[num].eps_via_nodes;
+ DEBUG_ASSERT (0 <= fs->stack[num].node);
+ return fs->stack[num].node;
+}
+
+
+#define DYNARRAY_STRUCT regmatch_list
+#define DYNARRAY_ELEMENT regmatch_t
+#define DYNARRAY_PREFIX regmatch_list_
+#include <malloc/dynarray-skeleton.c>
+
+/* Set the positions where the subexpressions are starts/ends to registers
+ PMATCH.
+ Note: We assume that pmatch[0] is already set, and
+ pmatch[i].rm_so == pmatch[i].rm_eo == -1 for 0 < i < nmatch. */
+
+static reg_errcode_t
+__attribute_warn_unused_result__
+set_regs (const regex_t *preg, const re_match_context_t *mctx, size_t nmatch,
+ regmatch_t *pmatch, bool fl_backtrack)
+{
+ const re_dfa_t *dfa = preg->buffer;
+ Idx idx, cur_node;
+ re_node_set eps_via_nodes;
+ struct re_fail_stack_t *fs;
+ struct re_fail_stack_t fs_body = { 0, 2, NULL };
+ struct regmatch_list prev_match;
+ regmatch_list_init (&prev_match);
+
+ DEBUG_ASSERT (nmatch > 1);
+ DEBUG_ASSERT (mctx->state_log != NULL);
+ if (fl_backtrack)
+ {
+ fs = &fs_body;
+ fs->stack = re_malloc (struct re_fail_stack_ent_t, fs->alloc);
+ if (fs->stack == NULL)
+ return REG_ESPACE;
+ }
+ else
+ fs = NULL;
+
+ cur_node = dfa->init_node;
+ re_node_set_init_empty (&eps_via_nodes);
+
+ if (!regmatch_list_resize (&prev_match, nmatch))
+ {
+ regmatch_list_free (&prev_match);
+ free_fail_stack_return (fs);
+ return REG_ESPACE;
+ }
+ regmatch_t *prev_idx_match = regmatch_list_begin (&prev_match);
+ memcpy (prev_idx_match, pmatch, sizeof (regmatch_t) * nmatch);
+
+ for (idx = pmatch[0].rm_so; idx <= pmatch[0].rm_eo ;)
+ {
+ update_regs (dfa, pmatch, prev_idx_match, cur_node, idx, nmatch);
+
+ if ((idx == pmatch[0].rm_eo && cur_node == mctx->last_node)
+ || (fs && re_node_set_contains (&eps_via_nodes, cur_node)))
+ {
+ Idx reg_idx;
+ cur_node = -1;
+ if (fs)
+ {
+ for (reg_idx = 0; reg_idx < nmatch; ++reg_idx)
+ if (pmatch[reg_idx].rm_so > -1 && pmatch[reg_idx].rm_eo == -1)
+ {
+ cur_node = pop_fail_stack (fs, &idx, nmatch, pmatch,
+ prev_idx_match, &eps_via_nodes);
+ break;
+ }
+ }
+ if (cur_node < 0)
+ {
+ re_node_set_free (&eps_via_nodes);
+ regmatch_list_free (&prev_match);
+ return free_fail_stack_return (fs);
+ }
+ }
+
+ /* Proceed to next node. */
+ cur_node = proceed_next_node (mctx, nmatch, pmatch, prev_idx_match,
+ &idx, cur_node,
+ &eps_via_nodes, fs);
+
+ if (__glibc_unlikely (cur_node < 0))
+ {
+ if (__glibc_unlikely (cur_node == -2))
+ {
+ re_node_set_free (&eps_via_nodes);
+ regmatch_list_free (&prev_match);
+ free_fail_stack_return (fs);
+ return REG_ESPACE;
+ }
+ cur_node = pop_fail_stack (fs, &idx, nmatch, pmatch,
+ prev_idx_match, &eps_via_nodes);
+ if (cur_node < 0)
+ {
+ re_node_set_free (&eps_via_nodes);
+ regmatch_list_free (&prev_match);
+ free_fail_stack_return (fs);
+ return REG_NOMATCH;
+ }
+ }
+ }
+ re_node_set_free (&eps_via_nodes);
+ regmatch_list_free (&prev_match);
+ return free_fail_stack_return (fs);
+}
+
+static reg_errcode_t
+free_fail_stack_return (struct re_fail_stack_t *fs)
+{
+ if (fs)
+ {
+ Idx fs_idx;
+ for (fs_idx = 0; fs_idx < fs->num; ++fs_idx)
+ {
+ re_node_set_free (&fs->stack[fs_idx].eps_via_nodes);
+ re_free (fs->stack[fs_idx].regs);
+ }
+ re_free (fs->stack);
+ }
+ return REG_NOERROR;
+}
+
+static void
+update_regs (const re_dfa_t *dfa, regmatch_t *pmatch,
+ regmatch_t *prev_idx_match, Idx cur_node, Idx cur_idx, Idx nmatch)
+{
+ int type = dfa->nodes[cur_node].type;
+ if (type == OP_OPEN_SUBEXP)
+ {
+ Idx reg_num = dfa->nodes[cur_node].opr.idx + 1;
+
+ /* We are at the first node of this sub expression. */
+ if (reg_num < nmatch)
+ {
+ pmatch[reg_num].rm_so = cur_idx;
+ pmatch[reg_num].rm_eo = -1;
+ }
+ }
+ else if (type == OP_CLOSE_SUBEXP)
+ {
+ /* We are at the last node of this sub expression. */
+ Idx reg_num = dfa->nodes[cur_node].opr.idx + 1;
+ if (reg_num < nmatch)
+ {
+ if (pmatch[reg_num].rm_so < cur_idx)
+ {
+ pmatch[reg_num].rm_eo = cur_idx;
+ /* This is a non-empty match or we are not inside an optional
+ subexpression. Accept this right away. */
+ memcpy (prev_idx_match, pmatch, sizeof (regmatch_t) * nmatch);
+ }
+ else
+ {
+ if (dfa->nodes[cur_node].opt_subexp
+ && prev_idx_match[reg_num].rm_so != -1)
+ /* We transited through an empty match for an optional
+ subexpression, like (a?)*, and this is not the subexp's
+ first match. Copy back the old content of the registers
+ so that matches of an inner subexpression are undone as
+ well, like in ((a?))*. */
+ memcpy (pmatch, prev_idx_match, sizeof (regmatch_t) * nmatch);
+ else
+ /* We completed a subexpression, but it may be part of
+ an optional one, so do not update PREV_IDX_MATCH. */
+ pmatch[reg_num].rm_eo = cur_idx;
+ }
+ }
+ }
+}
+
+/* This function checks the STATE_LOG from the SCTX->last_str_idx to 0
+ and sift the nodes in each states according to the following rules.
+ Updated state_log will be wrote to STATE_LOG.
+
+ Rules: We throw away the Node 'a' in the STATE_LOG[STR_IDX] if...
+ 1. When STR_IDX == MATCH_LAST(the last index in the state_log):
+ If 'a' isn't the LAST_NODE and 'a' can't epsilon transit to
+ the LAST_NODE, we throw away the node 'a'.
+ 2. When 0 <= STR_IDX < MATCH_LAST and 'a' accepts
+ string 's' and transit to 'b':
+ i. If 'b' isn't in the STATE_LOG[STR_IDX+strlen('s')], we throw
+ away the node 'a'.
+ ii. If 'b' is in the STATE_LOG[STR_IDX+strlen('s')] but 'b' is
+ thrown away, we throw away the node 'a'.
+ 3. When 0 <= STR_IDX < MATCH_LAST and 'a' epsilon transit to 'b':
+ i. If 'b' isn't in the STATE_LOG[STR_IDX], we throw away the
+ node 'a'.
+ ii. If 'b' is in the STATE_LOG[STR_IDX] but 'b' is thrown away,
+ we throw away the node 'a'. */
+
+#define STATE_NODE_CONTAINS(state,node) \
+ ((state) != NULL && re_node_set_contains (&(state)->nodes, node))
+
+static reg_errcode_t
+sift_states_backward (const re_match_context_t *mctx, re_sift_context_t *sctx)
+{
+ reg_errcode_t err;
+ int null_cnt = 0;
+ Idx str_idx = sctx->last_str_idx;
+ re_node_set cur_dest;
+
+ 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. */
+ err = re_node_set_init_1 (&cur_dest, sctx->last_node);
+ if (__glibc_unlikely (err != REG_NOERROR))
+ return err;
+ err = update_cur_sifted_state (mctx, sctx, str_idx, &cur_dest);
+ if (__glibc_unlikely (err != REG_NOERROR))
+ goto free_return;
+
+ /* Then check each states in the state_log. */
+ while (str_idx > 0)
+ {
+ /* Update counters. */
+ null_cnt = (sctx->sifted_states[str_idx] == NULL) ? null_cnt + 1 : 0;
+ if (null_cnt > mctx->max_mb_elem_len)
+ {
+ memset (sctx->sifted_states, '\0',
+ sizeof (re_dfastate_t *) * str_idx);
+ re_node_set_free (&cur_dest);
+ return REG_NOERROR;
+ }
+ re_node_set_empty (&cur_dest);
+ --str_idx;
+
+ if (mctx->state_log[str_idx])
+ {
+ err = build_sifted_states (mctx, sctx, str_idx, &cur_dest);
+ if (__glibc_unlikely (err != REG_NOERROR))
+ goto free_return;
+ }
+
+ /* Add all the nodes which satisfy the following conditions:
+ - It can epsilon transit to a node in CUR_DEST.
+ - It is in CUR_SRC.
+ And update state_log. */
+ err = update_cur_sifted_state (mctx, sctx, str_idx, &cur_dest);
+ if (__glibc_unlikely (err != REG_NOERROR))
+ goto free_return;
+ }
+ err = REG_NOERROR;
+ free_return:
+ re_node_set_free (&cur_dest);
+ return err;
+}
+
+static reg_errcode_t
+__attribute_warn_unused_result__
+build_sifted_states (const re_match_context_t *mctx, re_sift_context_t *sctx,
+ Idx str_idx, re_node_set *cur_dest)
+{
+ const re_dfa_t *const dfa = mctx->dfa;
+ const re_node_set *cur_src = &mctx->state_log[str_idx]->non_eps_nodes;
+ Idx i;
+
+ /* Then build the next sifted state.
+ We build the next sifted state on 'cur_dest', and update
+ 'sifted_states[str_idx]' with 'cur_dest'.
+ Note:
+ 'cur_dest' is the sifted state from 'state_log[str_idx + 1]'.
+ 'cur_src' points the node_set of the old 'state_log[str_idx]'
+ (with the epsilon nodes pre-filtered out). */
+ for (i = 0; i < cur_src->nelem; i++)
+ {
+ Idx prev_node = cur_src->elems[i];
+ int naccepted = 0;
+ bool ok;
+ DEBUG_ASSERT (!IS_EPSILON_NODE (dfa->nodes[prev_node].type));
+
+ /* If the node may accept "multi byte". */
+ if (dfa->nodes[prev_node].accept_mb)
+ naccepted = sift_states_iter_mb (mctx, sctx, prev_node,
+ str_idx, sctx->last_str_idx);
+
+ /* We don't check backreferences here.
+ See update_cur_sifted_state(). */
+ if (!naccepted
+ && check_node_accept (mctx, dfa->nodes + prev_node, str_idx)
+ && STATE_NODE_CONTAINS (sctx->sifted_states[str_idx + 1],
+ dfa->nexts[prev_node]))
+ naccepted = 1;
+
+ if (naccepted == 0)
+ continue;
+
+ if (sctx->limits.nelem)
+ {
+ Idx to_idx = str_idx + naccepted;
+ if (check_dst_limits (mctx, &sctx->limits,
+ dfa->nexts[prev_node], to_idx,
+ prev_node, str_idx))
+ continue;
+ }
+ ok = re_node_set_insert (cur_dest, prev_node);
+ if (__glibc_unlikely (! ok))
+ return REG_ESPACE;
+ }
+
+ return REG_NOERROR;
+}
+
+/* Helper functions. */
+
+static reg_errcode_t
+clean_state_log_if_needed (re_match_context_t *mctx, Idx next_state_log_idx)
+{
+ Idx top = mctx->state_log_top;
+
+ if ((next_state_log_idx >= mctx->input.bufs_len
+ && mctx->input.bufs_len < mctx->input.len)
+ || (next_state_log_idx >= mctx->input.valid_len
+ && mctx->input.valid_len < mctx->input.len))
+ {
+ reg_errcode_t err;
+ err = extend_buffers (mctx, next_state_log_idx + 1);
+ if (__glibc_unlikely (err != REG_NOERROR))
+ return err;
+ }
+
+ if (top < next_state_log_idx)
+ {
+ DEBUG_ASSERT (mctx->state_log != NULL);
+ memset (mctx->state_log + top + 1, '\0',
+ sizeof (re_dfastate_t *) * (next_state_log_idx - top));
+ mctx->state_log_top = next_state_log_idx;
+ }
+ return REG_NOERROR;
+}
+
+static reg_errcode_t
+merge_state_array (const re_dfa_t *dfa, re_dfastate_t **dst,
+ re_dfastate_t **src, Idx num)
+{
+ Idx st_idx;
+ reg_errcode_t err;
+ for (st_idx = 0; st_idx < num; ++st_idx)
+ {
+ if (dst[st_idx] == NULL)
+ dst[st_idx] = src[st_idx];
+ else if (src[st_idx] != NULL)
+ {
+ re_node_set merged_set;
+ err = re_node_set_init_union (&merged_set, &dst[st_idx]->nodes,
+ &src[st_idx]->nodes);
+ if (__glibc_unlikely (err != REG_NOERROR))
+ return err;
+ dst[st_idx] = re_acquire_state (&err, dfa, &merged_set);
+ re_node_set_free (&merged_set);
+ if (__glibc_unlikely (err != REG_NOERROR))
+ return err;
+ }
+ }
+ return REG_NOERROR;
+}
+
+static reg_errcode_t
+update_cur_sifted_state (const re_match_context_t *mctx,
+ re_sift_context_t *sctx, Idx str_idx,
+ re_node_set *dest_nodes)
+{
+ const re_dfa_t *const dfa = mctx->dfa;
+ reg_errcode_t err = REG_NOERROR;
+ const re_node_set *candidates;
+ candidates = ((mctx->state_log[str_idx] == NULL) ? NULL
+ : &mctx->state_log[str_idx]->nodes);
+
+ if (dest_nodes->nelem == 0)
+ sctx->sifted_states[str_idx] = NULL;
+ else
+ {
+ if (candidates)
+ {
+ /* At first, add the nodes which can epsilon transit to a node in
+ DEST_NODE. */
+ err = add_epsilon_src_nodes (dfa, dest_nodes, candidates);
+ if (__glibc_unlikely (err != REG_NOERROR))
+ return err;
+
+ /* Then, check the limitations in the current sift_context. */
+ if (sctx->limits.nelem)
+ {
+ err = check_subexp_limits (dfa, dest_nodes, candidates, &sctx->limits,
+ mctx->bkref_ents, str_idx);
+ if (__glibc_unlikely (err != REG_NOERROR))
+ return err;
+ }
+ }
+
+ sctx->sifted_states[str_idx] = re_acquire_state (&err, dfa, dest_nodes);
+ if (__glibc_unlikely (err != REG_NOERROR))
+ return err;
+ }
+
+ if (candidates && mctx->state_log[str_idx]->has_backref)
+ {
+ err = sift_states_bkref (mctx, sctx, str_idx, candidates);
+ if (__glibc_unlikely (err != REG_NOERROR))
+ return err;
+ }
+ return REG_NOERROR;
+}
+
+static reg_errcode_t
+__attribute_warn_unused_result__
+add_epsilon_src_nodes (const re_dfa_t *dfa, re_node_set *dest_nodes,
+ const re_node_set *candidates)
+{
+ reg_errcode_t err = REG_NOERROR;
+ Idx i;
+
+ re_dfastate_t *state = re_acquire_state (&err, dfa, dest_nodes);
+ if (__glibc_unlikely (err != REG_NOERROR))
+ return err;
+
+ if (!state->inveclosure.alloc)
+ {
+ err = re_node_set_alloc (&state->inveclosure, dest_nodes->nelem);
+ if (__glibc_unlikely (err != REG_NOERROR))
+ return REG_ESPACE;
+ for (i = 0; i < dest_nodes->nelem; i++)
+ {
+ err = re_node_set_merge (&state->inveclosure,
+ dfa->inveclosures + dest_nodes->elems[i]);
+ if (__glibc_unlikely (err != REG_NOERROR))
+ return REG_ESPACE;
+ }
+ }
+ return re_node_set_add_intersect (dest_nodes, candidates,
+ &state->inveclosure);
+}
+
+static reg_errcode_t
+sub_epsilon_src_nodes (const re_dfa_t *dfa, Idx node, re_node_set *dest_nodes,
+ const re_node_set *candidates)
+{
+ Idx ecl_idx;
+ reg_errcode_t err;
+ re_node_set *inv_eclosure = dfa->inveclosures + node;
+ re_node_set except_nodes;
+ re_node_set_init_empty (&except_nodes);
+ for (ecl_idx = 0; ecl_idx < inv_eclosure->nelem; ++ecl_idx)
+ {
+ Idx cur_node = inv_eclosure->elems[ecl_idx];
+ if (cur_node == node)
+ continue;
+ if (IS_EPSILON_NODE (dfa->nodes[cur_node].type))
+ {
+ Idx edst1 = dfa->edests[cur_node].elems[0];
+ Idx edst2 = ((dfa->edests[cur_node].nelem > 1)
+ ? dfa->edests[cur_node].elems[1] : -1);
+ if ((!re_node_set_contains (inv_eclosure, edst1)
+ && re_node_set_contains (dest_nodes, edst1))
+ || (edst2 > 0
+ && !re_node_set_contains (inv_eclosure, edst2)
+ && re_node_set_contains (dest_nodes, edst2)))
+ {
+ err = re_node_set_add_intersect (&except_nodes, candidates,
+ dfa->inveclosures + cur_node);
+ if (__glibc_unlikely (err != REG_NOERROR))
+ {
+ re_node_set_free (&except_nodes);
+ return err;
+ }
+ }
+ }
+ }
+ for (ecl_idx = 0; ecl_idx < inv_eclosure->nelem; ++ecl_idx)
+ {
+ Idx cur_node = inv_eclosure->elems[ecl_idx];
+ if (!re_node_set_contains (&except_nodes, cur_node))
+ {
+ Idx idx = re_node_set_contains (dest_nodes, cur_node) - 1;
+ re_node_set_remove_at (dest_nodes, idx);
+ }
+ }
+ re_node_set_free (&except_nodes);
+ return REG_NOERROR;
+}
+
+static bool
+check_dst_limits (const re_match_context_t *mctx, const re_node_set *limits,
+ Idx dst_node, Idx dst_idx, Idx src_node, Idx src_idx)
+{
+ const re_dfa_t *const dfa = mctx->dfa;
+ Idx lim_idx, src_pos, dst_pos;
+
+ Idx dst_bkref_idx = search_cur_bkref_entry (mctx, dst_idx);
+ Idx src_bkref_idx = search_cur_bkref_entry (mctx, src_idx);
+ for (lim_idx = 0; lim_idx < limits->nelem; ++lim_idx)
+ {
+ Idx subexp_idx;
+ struct re_backref_cache_entry *ent;
+ ent = mctx->bkref_ents + limits->elems[lim_idx];
+ subexp_idx = dfa->nodes[ent->node].opr.idx;
+
+ dst_pos = check_dst_limits_calc_pos (mctx, limits->elems[lim_idx],
+ subexp_idx, dst_node, dst_idx,
+ dst_bkref_idx);
+ src_pos = check_dst_limits_calc_pos (mctx, limits->elems[lim_idx],
+ subexp_idx, src_node, src_idx,
+ src_bkref_idx);
+
+ /* In case of:
+ <src> <dst> ( <subexp> )
+ ( <subexp> ) <src> <dst>
+ ( <subexp1> <src> <subexp2> <dst> <subexp3> ) */
+ if (src_pos == dst_pos)
+ continue; /* This is unrelated limitation. */
+ else
+ return true;
+ }
+ return false;
+}
+
+static int
+check_dst_limits_calc_pos_1 (const re_match_context_t *mctx, int boundaries,
+ Idx subexp_idx, Idx from_node, Idx bkref_idx)
+{
+ const re_dfa_t *const dfa = mctx->dfa;
+ const re_node_set *eclosures = dfa->eclosures + from_node;
+ Idx node_idx;
+
+ /* Else, we are on the boundary: examine the nodes on the epsilon
+ closure. */
+ for (node_idx = 0; node_idx < eclosures->nelem; ++node_idx)
+ {
+ Idx node = eclosures->elems[node_idx];
+ switch (dfa->nodes[node].type)
+ {
+ case OP_BACK_REF:
+ if (bkref_idx != -1)
+ {
+ struct re_backref_cache_entry *ent = mctx->bkref_ents + bkref_idx;
+ do
+ {
+ Idx dst;
+ int cpos;
+
+ if (ent->node != node)
+ continue;
+
+ if (subexp_idx < BITSET_WORD_BITS
+ && !(ent->eps_reachable_subexps_map
+ & ((bitset_word_t) 1 << subexp_idx)))
+ continue;
+
+ /* Recurse trying to reach the OP_OPEN_SUBEXP and
+ OP_CLOSE_SUBEXP cases below. But, if the
+ destination node is the same node as the source
+ node, don't recurse because it would cause an
+ infinite loop: a regex that exhibits this behavior
+ is ()\1*\1* */
+ dst = dfa->edests[node].elems[0];
+ if (dst == from_node)
+ {
+ if (boundaries & 1)
+ return -1;
+ else /* if (boundaries & 2) */
+ return 0;
+ }
+
+ cpos =
+ check_dst_limits_calc_pos_1 (mctx, boundaries, subexp_idx,
+ dst, bkref_idx);
+ if (cpos == -1 /* && (boundaries & 1) */)
+ return -1;
+ if (cpos == 0 && (boundaries & 2))
+ return 0;
+
+ if (subexp_idx < BITSET_WORD_BITS)
+ ent->eps_reachable_subexps_map
+ &= ~((bitset_word_t) 1 << subexp_idx);
+ }
+ while (ent++->more);
+ }
+ break;
+
+ case OP_OPEN_SUBEXP:
+ if ((boundaries & 1) && subexp_idx == dfa->nodes[node].opr.idx)
+ return -1;
+ break;
+
+ case OP_CLOSE_SUBEXP:
+ if ((boundaries & 2) && subexp_idx == dfa->nodes[node].opr.idx)
+ return 0;
+ break;
+
+ default:
+ break;
+ }
+ }
+
+ return (boundaries & 2) ? 1 : 0;
+}
+
+static int
+check_dst_limits_calc_pos (const re_match_context_t *mctx, Idx limit,
+ Idx subexp_idx, Idx from_node, Idx str_idx,
+ Idx bkref_idx)
+{
+ struct re_backref_cache_entry *lim = mctx->bkref_ents + limit;
+ int boundaries;
+
+ /* If we are outside the range of the subexpression, return -1 or 1. */
+ if (str_idx < lim->subexp_from)
+ return -1;
+
+ if (lim->subexp_to < str_idx)
+ return 1;
+
+ /* If we are within the subexpression, return 0. */
+ boundaries = (str_idx == lim->subexp_from);
+ boundaries |= (str_idx == lim->subexp_to) << 1;
+ if (boundaries == 0)
+ return 0;
+
+ /* Else, examine epsilon closure. */
+ return check_dst_limits_calc_pos_1 (mctx, boundaries, subexp_idx,
+ from_node, bkref_idx);
+}
+
+/* Check the limitations of sub expressions LIMITS, and remove the nodes
+ which are against limitations from DEST_NODES. */
+
+static reg_errcode_t
+check_subexp_limits (const re_dfa_t *dfa, re_node_set *dest_nodes,
+ const re_node_set *candidates, re_node_set *limits,
+ struct re_backref_cache_entry *bkref_ents, Idx str_idx)
+{
+ reg_errcode_t err;
+ Idx node_idx, lim_idx;
+
+ for (lim_idx = 0; lim_idx < limits->nelem; ++lim_idx)
+ {
+ Idx subexp_idx;
+ struct re_backref_cache_entry *ent;
+ ent = bkref_ents + limits->elems[lim_idx];
+
+ if (str_idx <= ent->subexp_from || ent->str_idx < str_idx)
+ continue; /* This is unrelated limitation. */
+
+ subexp_idx = dfa->nodes[ent->node].opr.idx;
+ if (ent->subexp_to == str_idx)
+ {
+ Idx ops_node = -1;
+ Idx cls_node = -1;
+ for (node_idx = 0; node_idx < dest_nodes->nelem; ++node_idx)
+ {
+ Idx node = dest_nodes->elems[node_idx];
+ re_token_type_t type = dfa->nodes[node].type;
+ if (type == OP_OPEN_SUBEXP
+ && subexp_idx == dfa->nodes[node].opr.idx)
+ ops_node = node;
+ else if (type == OP_CLOSE_SUBEXP
+ && subexp_idx == dfa->nodes[node].opr.idx)
+ cls_node = node;
+ }
+
+ /* Check the limitation of the open subexpression. */
+ /* Note that (ent->subexp_to = str_idx != ent->subexp_from). */
+ if (ops_node >= 0)
+ {
+ err = sub_epsilon_src_nodes (dfa, ops_node, dest_nodes,
+ candidates);
+ if (__glibc_unlikely (err != REG_NOERROR))
+ return err;
+ }
+
+ /* Check the limitation of the close subexpression. */
+ if (cls_node >= 0)
+ for (node_idx = 0; node_idx < dest_nodes->nelem; ++node_idx)
+ {
+ Idx node = dest_nodes->elems[node_idx];
+ if (!re_node_set_contains (dfa->inveclosures + node,
+ cls_node)
+ && !re_node_set_contains (dfa->eclosures + node,
+ cls_node))
+ {
+ /* It is against this limitation.
+ Remove it form the current sifted state. */
+ err = sub_epsilon_src_nodes (dfa, node, dest_nodes,
+ candidates);
+ if (__glibc_unlikely (err != REG_NOERROR))
+ return err;
+ --node_idx;
+ }
+ }
+ }
+ else /* (ent->subexp_to != str_idx) */
+ {
+ for (node_idx = 0; node_idx < dest_nodes->nelem; ++node_idx)
+ {
+ Idx node = dest_nodes->elems[node_idx];
+ re_token_type_t type = dfa->nodes[node].type;
+ if (type == OP_CLOSE_SUBEXP || type == OP_OPEN_SUBEXP)
+ {
+ if (subexp_idx != dfa->nodes[node].opr.idx)
+ continue;
+ /* It is against this limitation.
+ Remove it form the current sifted state. */
+ err = sub_epsilon_src_nodes (dfa, node, dest_nodes,
+ candidates);
+ if (__glibc_unlikely (err != REG_NOERROR))
+ return err;
+ }
+ }
+ }
+ }
+ return REG_NOERROR;
+}
+
+static reg_errcode_t
+__attribute_warn_unused_result__
+sift_states_bkref (const re_match_context_t *mctx, re_sift_context_t *sctx,
+ Idx str_idx, const re_node_set *candidates)
+{
+ const re_dfa_t *const dfa = mctx->dfa;
+ reg_errcode_t err;
+ Idx node_idx, node;
+ re_sift_context_t local_sctx;
+ Idx first_idx = search_cur_bkref_entry (mctx, str_idx);
+
+ if (first_idx == -1)
+ return REG_NOERROR;
+
+ local_sctx.sifted_states = NULL; /* Mark that it hasn't been initialized. */
+
+ for (node_idx = 0; node_idx < candidates->nelem; ++node_idx)
+ {
+ Idx enabled_idx;
+ re_token_type_t type;
+ struct re_backref_cache_entry *entry;
+ node = candidates->elems[node_idx];
+ type = dfa->nodes[node].type;
+ /* Avoid infinite loop for the REs like "()\1+". */
+ if (node == sctx->last_node && str_idx == sctx->last_str_idx)
+ continue;
+ if (type != OP_BACK_REF)
+ continue;
+
+ entry = mctx->bkref_ents + first_idx;
+ enabled_idx = first_idx;
+ do
+ {
+ Idx subexp_len;
+ Idx to_idx;
+ Idx dst_node;
+ bool ok;
+ re_dfastate_t *cur_state;
+
+ if (entry->node != node)
+ continue;
+ subexp_len = entry->subexp_to - entry->subexp_from;
+ to_idx = str_idx + subexp_len;
+ dst_node = (subexp_len ? dfa->nexts[node]
+ : dfa->edests[node].elems[0]);
+
+ if (to_idx > sctx->last_str_idx
+ || sctx->sifted_states[to_idx] == NULL
+ || !STATE_NODE_CONTAINS (sctx->sifted_states[to_idx], dst_node)
+ || check_dst_limits (mctx, &sctx->limits, node,
+ str_idx, dst_node, to_idx))
+ continue;
+
+ if (local_sctx.sifted_states == NULL)
+ {
+ local_sctx = *sctx;
+ err = re_node_set_init_copy (&local_sctx.limits, &sctx->limits);
+ if (__glibc_unlikely (err != REG_NOERROR))
+ goto free_return;
+ }
+ local_sctx.last_node = node;
+ local_sctx.last_str_idx = str_idx;
+ ok = re_node_set_insert (&local_sctx.limits, enabled_idx);
+ if (__glibc_unlikely (! ok))
+ {
+ err = REG_ESPACE;
+ goto free_return;
+ }
+ cur_state = local_sctx.sifted_states[str_idx];
+ err = sift_states_backward (mctx, &local_sctx);
+ if (__glibc_unlikely (err != REG_NOERROR))
+ goto free_return;
+ if (sctx->limited_states != NULL)
+ {
+ err = merge_state_array (dfa, sctx->limited_states,
+ local_sctx.sifted_states,
+ str_idx + 1);
+ if (__glibc_unlikely (err != REG_NOERROR))
+ goto free_return;
+ }
+ local_sctx.sifted_states[str_idx] = cur_state;
+ re_node_set_remove (&local_sctx.limits, enabled_idx);
+
+ /* mctx->bkref_ents may have changed, reload the pointer. */
+ entry = mctx->bkref_ents + enabled_idx;
+ }
+ while (enabled_idx++, entry++->more);
+ }
+ err = REG_NOERROR;
+ free_return:
+ if (local_sctx.sifted_states != NULL)
+ {
+ re_node_set_free (&local_sctx.limits);
+ }
+
+ return err;
+}
+
+
+static int
+sift_states_iter_mb (const re_match_context_t *mctx, re_sift_context_t *sctx,
+ Idx node_idx, Idx str_idx, Idx max_str_idx)
+{
+ const re_dfa_t *const dfa = mctx->dfa;
+ 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]))
+ /* The node can't accept the "multi byte", or the
+ destination was already thrown away, then the node
+ couldn't accept the current input "multi byte". */
+ naccepted = 0;
+ /* Otherwise, it is sure that the node could accept
+ 'naccepted' bytes input. */
+ return naccepted;
+}
+
+/* Functions for state transition. */
+
+/* Return the next state to which the current state STATE will transit by
+ accepting the current input byte, and update STATE_LOG if necessary.
+ Return NULL on failure.
+ If STATE can accept a multibyte char/collating element/back reference
+ update the destination of STATE_LOG. */
+
+static re_dfastate_t *
+__attribute_warn_unused_result__
+transit_state (reg_errcode_t *err, re_match_context_t *mctx,
+ re_dfastate_t *state)
+{
+ re_dfastate_t **trtable;
+ unsigned char ch;
+
+ /* If the current state can accept multibyte. */
+ if (__glibc_unlikely (state->accept_mb))
+ {
+ *err = transit_state_mb (mctx, state);
+ if (__glibc_unlikely (*err != REG_NOERROR))
+ return NULL;
+ }
+
+ /* Then decide the next state with the single byte. */
+#if 0
+ if (0)
+ /* don't use transition table */
+ return transit_state_sb (err, mctx, state);
+#endif
+
+ /* Use transition table */
+ ch = re_string_fetch_byte (&mctx->input);
+ for (;;)
+ {
+ trtable = state->trtable;
+ if (__glibc_likely (trtable != NULL))
+ return trtable[ch];
+
+ trtable = state->word_trtable;
+ if (__glibc_likely (trtable != NULL))
+ {
+ unsigned int context;
+ context
+ = re_string_context_at (&mctx->input,
+ re_string_cur_idx (&mctx->input) - 1,
+ mctx->eflags);
+ if (IS_WORD_CONTEXT (context))
+ return trtable[ch + SBC_MAX];
+ else
+ return trtable[ch];
+ }
+
+ if (!build_trtable (mctx->dfa, state))
+ {
+ *err = REG_ESPACE;
+ return NULL;
+ }
+
+ /* Retry, we now have a transition table. */
+ }
+}
+
+/* Update the state_log if we need */
+static re_dfastate_t *
+merge_state_with_log (reg_errcode_t *err, re_match_context_t *mctx,
+ re_dfastate_t *next_state)
+{
+ const re_dfa_t *const dfa = mctx->dfa;
+ Idx cur_idx = re_string_cur_idx (&mctx->input);
+
+ if (cur_idx > mctx->state_log_top)
+ {
+ mctx->state_log[cur_idx] = next_state;
+ mctx->state_log_top = cur_idx;
+ }
+ else if (mctx->state_log[cur_idx] == 0)
+ {
+ mctx->state_log[cur_idx] = next_state;
+ }
+ else
+ {
+ re_dfastate_t *pstate;
+ unsigned int context;
+ re_node_set next_nodes, *log_nodes, *table_nodes = NULL;
+ /* If (state_log[cur_idx] != 0), it implies that cur_idx is
+ the destination of a multibyte char/collating element/
+ back reference. Then the next state is the union set of
+ these destinations and the results of the transition table. */
+ pstate = mctx->state_log[cur_idx];
+ log_nodes = pstate->entrance_nodes;
+ if (next_state != NULL)
+ {
+ table_nodes = next_state->entrance_nodes;
+ *err = re_node_set_init_union (&next_nodes, table_nodes,
+ log_nodes);
+ if (__glibc_unlikely (*err != REG_NOERROR))
+ return NULL;
+ }
+ else
+ next_nodes = *log_nodes;
+ /* Note: We already add the nodes of the initial state,
+ then we don't need to add them here. */
+
+ context = re_string_context_at (&mctx->input,
+ re_string_cur_idx (&mctx->input) - 1,
+ mctx->eflags);
+ next_state = mctx->state_log[cur_idx]
+ = re_acquire_state_context (err, dfa, &next_nodes, context);
+ /* We don't need to check errors here, since the return value of
+ this function is next_state and ERR is already set. */
+
+ if (table_nodes != NULL)
+ re_node_set_free (&next_nodes);
+ }
+
+ if (__glibc_unlikely (dfa->nbackref) && next_state != NULL)
+ {
+ /* Check OP_OPEN_SUBEXP in the current state in case that we use them
+ later. We must check them here, since the back references in the
+ next state might use them. */
+ *err = check_subexp_matching_top (mctx, &next_state->nodes,
+ cur_idx);
+ if (__glibc_unlikely (*err != REG_NOERROR))
+ return NULL;
+
+ /* If the next state has back references. */
+ if (next_state->has_backref)
+ {
+ *err = transit_state_bkref (mctx, &next_state->nodes);
+ if (__glibc_unlikely (*err != REG_NOERROR))
+ return NULL;
+ next_state = mctx->state_log[cur_idx];
+ }
+ }
+
+ return next_state;
+}
+
+/* Skip bytes in the input that correspond to part of a
+ multi-byte match, then look in the log for a state
+ from which to restart matching. */
+static re_dfastate_t *
+find_recover_state (reg_errcode_t *err, re_match_context_t *mctx)
+{
+ re_dfastate_t *cur_state;
+ do
+ {
+ Idx max = mctx->state_log_top;
+ Idx cur_str_idx = re_string_cur_idx (&mctx->input);
+
+ do
+ {
+ if (++cur_str_idx > max)
+ return NULL;
+ re_string_skip_bytes (&mctx->input, 1);
+ }
+ while (mctx->state_log[cur_str_idx] == NULL);
+
+ cur_state = merge_state_with_log (err, mctx, NULL);
+ }
+ while (*err == REG_NOERROR && cur_state == NULL);
+ return cur_state;
+}
+
+/* Helper functions for transit_state. */
+
+/* From the node set CUR_NODES, pick up the nodes whose types are
+ OP_OPEN_SUBEXP and which have corresponding back references in the regular
+ expression. And register them to use them later for evaluating the
+ corresponding back references. */
+
+static reg_errcode_t
+check_subexp_matching_top (re_match_context_t *mctx, re_node_set *cur_nodes,
+ Idx str_idx)
+{
+ const re_dfa_t *const dfa = mctx->dfa;
+ Idx node_idx;
+ reg_errcode_t err;
+
+ /* TODO: This isn't efficient.
+ Because there might be more than one nodes whose types are
+ OP_OPEN_SUBEXP and whose index is SUBEXP_IDX, we must check all
+ nodes.
+ E.g. RE: (a){2} */
+ for (node_idx = 0; node_idx < cur_nodes->nelem; ++node_idx)
+ {
+ Idx node = cur_nodes->elems[node_idx];
+ if (dfa->nodes[node].type == OP_OPEN_SUBEXP
+ && dfa->nodes[node].opr.idx < BITSET_WORD_BITS
+ && (dfa->used_bkref_map
+ & ((bitset_word_t) 1 << dfa->nodes[node].opr.idx)))
+ {
+ err = match_ctx_add_subtop (mctx, node, str_idx);
+ if (__glibc_unlikely (err != REG_NOERROR))
+ return err;
+ }
+ }
+ return REG_NOERROR;
+}
+
+#if 0
+/* Return the next state to which the current state STATE will transit by
+ accepting the current input byte. Return NULL on failure. */
+
+static re_dfastate_t *
+transit_state_sb (reg_errcode_t *err, re_match_context_t *mctx,
+ re_dfastate_t *state)
+{
+ const re_dfa_t *const dfa = mctx->dfa;
+ re_node_set next_nodes;
+ re_dfastate_t *next_state;
+ Idx node_cnt, cur_str_idx = re_string_cur_idx (&mctx->input);
+ unsigned int context;
+
+ *err = re_node_set_alloc (&next_nodes, state->nodes.nelem + 1);
+ if (__glibc_unlikely (*err != REG_NOERROR))
+ return NULL;
+ for (node_cnt = 0; node_cnt < state->nodes.nelem; ++node_cnt)
+ {
+ Idx cur_node = state->nodes.elems[node_cnt];
+ if (check_node_accept (mctx, dfa->nodes + cur_node, cur_str_idx))
+ {
+ *err = re_node_set_merge (&next_nodes,
+ dfa->eclosures + dfa->nexts[cur_node]);
+ if (__glibc_unlikely (*err != REG_NOERROR))
+ {
+ re_node_set_free (&next_nodes);
+ return NULL;
+ }
+ }
+ }
+ context = re_string_context_at (&mctx->input, cur_str_idx, mctx->eflags);
+ next_state = re_acquire_state_context (err, dfa, &next_nodes, context);
+ /* We don't need to check errors here, since the return value of
+ this function is next_state and ERR is already set. */
+
+ re_node_set_free (&next_nodes);
+ re_string_skip_bytes (&mctx->input, 1);
+ return next_state;
+}
+#endif
+
+static reg_errcode_t
+transit_state_mb (re_match_context_t *mctx, re_dfastate_t *pstate)
+{
+ const re_dfa_t *const dfa = mctx->dfa;
+ reg_errcode_t err;
+ Idx i;
+
+ for (i = 0; i < pstate->nodes.nelem; ++i)
+ {
+ re_node_set dest_nodes, *new_nodes;
+ Idx cur_node_idx = pstate->nodes.elems[i];
+ int naccepted;
+ Idx dest_idx;
+ unsigned int context;
+ re_dfastate_t *dest_state;
+
+ if (!dfa->nodes[cur_node_idx].accept_mb)
+ continue;
+
+ if (dfa->nodes[cur_node_idx].constraint)
+ {
+ context = re_string_context_at (&mctx->input,
+ re_string_cur_idx (&mctx->input),
+ mctx->eflags);
+ if (NOT_SATISFY_NEXT_CONSTRAINT (dfa->nodes[cur_node_idx].constraint,
+ context))
+ continue;
+ }
+
+ /* How many bytes the node can accept? */
+ naccepted = check_node_accept_bytes (dfa, cur_node_idx, &mctx->input,
+ re_string_cur_idx (&mctx->input));
+ if (naccepted == 0)
+ continue;
+
+ /* The node can accepts 'naccepted' bytes. */
+ dest_idx = re_string_cur_idx (&mctx->input) + naccepted;
+ mctx->max_mb_elem_len = ((mctx->max_mb_elem_len < naccepted) ? naccepted
+ : mctx->max_mb_elem_len);
+ err = clean_state_log_if_needed (mctx, dest_idx);
+ if (__glibc_unlikely (err != REG_NOERROR))
+ return err;
+ DEBUG_ASSERT (dfa->nexts[cur_node_idx] != -1);
+ new_nodes = dfa->eclosures + dfa->nexts[cur_node_idx];
+
+ dest_state = mctx->state_log[dest_idx];
+ if (dest_state == NULL)
+ dest_nodes = *new_nodes;
+ else
+ {
+ err = re_node_set_init_union (&dest_nodes,
+ dest_state->entrance_nodes, new_nodes);
+ if (__glibc_unlikely (err != REG_NOERROR))
+ return err;
+ }
+ context = re_string_context_at (&mctx->input, dest_idx - 1,
+ mctx->eflags);
+ mctx->state_log[dest_idx]
+ = re_acquire_state_context (&err, dfa, &dest_nodes, context);
+ if (dest_state != NULL)
+ re_node_set_free (&dest_nodes);
+ if (__glibc_unlikely (mctx->state_log[dest_idx] == NULL
+ && err != REG_NOERROR))
+ return err;
+ }
+ return REG_NOERROR;
+}
+
+static reg_errcode_t
+transit_state_bkref (re_match_context_t *mctx, const re_node_set *nodes)
+{
+ const re_dfa_t *const dfa = mctx->dfa;
+ reg_errcode_t err;
+ Idx i;
+ Idx cur_str_idx = re_string_cur_idx (&mctx->input);
+
+ for (i = 0; i < nodes->nelem; ++i)
+ {
+ Idx dest_str_idx, prev_nelem, bkc_idx;
+ Idx node_idx = nodes->elems[i];
+ unsigned int context;
+ const re_token_t *node = dfa->nodes + node_idx;
+ re_node_set *new_dest_nodes;
+
+ /* Check whether 'node' is a backreference or not. */
+ if (node->type != OP_BACK_REF)
+ continue;
+
+ if (node->constraint)
+ {
+ context = re_string_context_at (&mctx->input, cur_str_idx,
+ mctx->eflags);
+ if (NOT_SATISFY_NEXT_CONSTRAINT (node->constraint, context))
+ continue;
+ }
+
+ /* 'node' is a backreference.
+ Check the substring which the substring matched. */
+ bkc_idx = mctx->nbkref_ents;
+ err = get_subexp (mctx, node_idx, cur_str_idx);
+ if (__glibc_unlikely (err != REG_NOERROR))
+ goto free_return;
+
+ /* And add the epsilon closures (which is 'new_dest_nodes') of
+ the backreference to appropriate state_log. */
+ DEBUG_ASSERT (dfa->nexts[node_idx] != -1);
+ for (; bkc_idx < mctx->nbkref_ents; ++bkc_idx)
+ {
+ Idx subexp_len;
+ re_dfastate_t *dest_state;
+ struct re_backref_cache_entry *bkref_ent;
+ bkref_ent = mctx->bkref_ents + bkc_idx;
+ if (bkref_ent->node != node_idx || bkref_ent->str_idx != cur_str_idx)
+ continue;
+ subexp_len = bkref_ent->subexp_to - bkref_ent->subexp_from;
+ new_dest_nodes = (subexp_len == 0
+ ? dfa->eclosures + dfa->edests[node_idx].elems[0]
+ : dfa->eclosures + dfa->nexts[node_idx]);
+ dest_str_idx = (cur_str_idx + bkref_ent->subexp_to
+ - bkref_ent->subexp_from);
+ context = re_string_context_at (&mctx->input, dest_str_idx - 1,
+ mctx->eflags);
+ dest_state = mctx->state_log[dest_str_idx];
+ prev_nelem = ((mctx->state_log[cur_str_idx] == NULL) ? 0
+ : mctx->state_log[cur_str_idx]->nodes.nelem);
+ /* Add 'new_dest_node' to state_log. */
+ if (dest_state == NULL)
+ {
+ mctx->state_log[dest_str_idx]
+ = re_acquire_state_context (&err, dfa, new_dest_nodes,
+ context);
+ if (__glibc_unlikely (mctx->state_log[dest_str_idx] == NULL
+ && err != REG_NOERROR))
+ goto free_return;
+ }
+ else
+ {
+ re_node_set dest_nodes;
+ err = re_node_set_init_union (&dest_nodes,
+ dest_state->entrance_nodes,
+ new_dest_nodes);
+ if (__glibc_unlikely (err != REG_NOERROR))
+ {
+ re_node_set_free (&dest_nodes);
+ goto free_return;
+ }
+ mctx->state_log[dest_str_idx]
+ = re_acquire_state_context (&err, dfa, &dest_nodes, context);
+ re_node_set_free (&dest_nodes);
+ if (__glibc_unlikely (mctx->state_log[dest_str_idx] == NULL
+ && err != REG_NOERROR))
+ goto free_return;
+ }
+ /* We need to check recursively if the backreference can epsilon
+ transit. */
+ if (subexp_len == 0
+ && mctx->state_log[cur_str_idx]->nodes.nelem > prev_nelem)
+ {
+ err = check_subexp_matching_top (mctx, new_dest_nodes,
+ cur_str_idx);
+ if (__glibc_unlikely (err != REG_NOERROR))
+ goto free_return;
+ err = transit_state_bkref (mctx, new_dest_nodes);
+ if (__glibc_unlikely (err != REG_NOERROR))
+ goto free_return;
+ }
+ }
+ }
+ err = REG_NOERROR;
+ free_return:
+ return err;
+}
+
+/* Enumerate all the candidates which the backreference BKREF_NODE can match
+ at BKREF_STR_IDX, and register them by match_ctx_add_entry().
+ Note that we might collect inappropriate candidates here.
+ However, the cost of checking them strictly here is too high, then we
+ delay these checking for prune_impossible_nodes(). */
+
+static reg_errcode_t
+__attribute_warn_unused_result__
+get_subexp (re_match_context_t *mctx, Idx bkref_node, Idx bkref_str_idx)
+{
+ const re_dfa_t *const dfa = mctx->dfa;
+ Idx subexp_num, sub_top_idx;
+ const char *buf = (const char *) re_string_get_buffer (&mctx->input);
+ /* Return if we have already checked BKREF_NODE at BKREF_STR_IDX. */
+ Idx cache_idx = search_cur_bkref_entry (mctx, bkref_str_idx);
+ if (cache_idx != -1)
+ {
+ const struct re_backref_cache_entry *entry
+ = mctx->bkref_ents + cache_idx;
+ do
+ if (entry->node == bkref_node)
+ return REG_NOERROR; /* We already checked it. */
+ while (entry++->more);
+ }
+
+ subexp_num = dfa->nodes[bkref_node].opr.idx;
+
+ /* For each sub expression */
+ for (sub_top_idx = 0; sub_top_idx < mctx->nsub_tops; ++sub_top_idx)
+ {
+ reg_errcode_t err;
+ re_sub_match_top_t *sub_top = mctx->sub_tops[sub_top_idx];
+ re_sub_match_last_t *sub_last;
+ Idx sub_last_idx, sl_str, bkref_str_off;
+
+ if (dfa->nodes[sub_top->node].opr.idx != subexp_num)
+ continue; /* It isn't related. */
+
+ sl_str = sub_top->str_idx;
+ bkref_str_off = bkref_str_idx;
+ /* At first, check the last node of sub expressions we already
+ evaluated. */
+ for (sub_last_idx = 0; sub_last_idx < sub_top->nlasts; ++sub_last_idx)
+ {
+ regoff_t sl_str_diff;
+ sub_last = sub_top->lasts[sub_last_idx];
+ sl_str_diff = sub_last->str_idx - sl_str;
+ /* The matched string by the sub expression match with the substring
+ at the back reference? */
+ if (sl_str_diff > 0)
+ {
+ if (__glibc_unlikely (bkref_str_off + sl_str_diff
+ > mctx->input.valid_len))
+ {
+ /* Not enough chars for a successful match. */
+ if (bkref_str_off + sl_str_diff > mctx->input.len)
+ break;
+
+ err = clean_state_log_if_needed (mctx,
+ bkref_str_off
+ + sl_str_diff);
+ if (__glibc_unlikely (err != REG_NOERROR))
+ return err;
+ buf = (const char *) re_string_get_buffer (&mctx->input);
+ }
+ if (memcmp (buf + bkref_str_off, buf + sl_str, sl_str_diff) != 0)
+ /* We don't need to search this sub expression any more. */
+ break;
+ }
+ bkref_str_off += sl_str_diff;
+ sl_str += sl_str_diff;
+ err = get_subexp_sub (mctx, sub_top, sub_last, bkref_node,
+ bkref_str_idx);
+
+ /* Reload buf, since the preceding call might have reallocated
+ the buffer. */
+ buf = (const char *) re_string_get_buffer (&mctx->input);
+
+ if (err == REG_NOMATCH)
+ continue;
+ if (__glibc_unlikely (err != REG_NOERROR))
+ return err;
+ }
+
+ if (sub_last_idx < sub_top->nlasts)
+ continue;
+ if (sub_last_idx > 0)
+ ++sl_str;
+ /* Then, search for the other last nodes of the sub expression. */
+ for (; sl_str <= bkref_str_idx; ++sl_str)
+ {
+ Idx cls_node;
+ regoff_t sl_str_off;
+ const re_node_set *nodes;
+ sl_str_off = sl_str - sub_top->str_idx;
+ /* The matched string by the sub expression match with the substring
+ at the back reference? */
+ if (sl_str_off > 0)
+ {
+ if (__glibc_unlikely (bkref_str_off >= mctx->input.valid_len))
+ {
+ /* If we are at the end of the input, we cannot match. */
+ if (bkref_str_off >= mctx->input.len)
+ break;
+
+ err = extend_buffers (mctx, bkref_str_off + 1);
+ if (__glibc_unlikely (err != REG_NOERROR))
+ return err;
+
+ buf = (const char *) re_string_get_buffer (&mctx->input);
+ }
+ if (buf [bkref_str_off++] != buf[sl_str - 1])
+ break; /* We don't need to search this sub expression
+ any more. */
+ }
+ if (mctx->state_log[sl_str] == NULL)
+ continue;
+ /* Does this state have a ')' of the sub expression? */
+ nodes = &mctx->state_log[sl_str]->nodes;
+ cls_node = find_subexp_node (dfa, nodes, subexp_num,
+ OP_CLOSE_SUBEXP);
+ if (cls_node == -1)
+ continue; /* No. */
+ if (sub_top->path == NULL)
+ {
+ sub_top->path = calloc (sizeof (state_array_t),
+ sl_str - sub_top->str_idx + 1);
+ if (sub_top->path == NULL)
+ return REG_ESPACE;
+ }
+ /* Can the OP_OPEN_SUBEXP node arrive the OP_CLOSE_SUBEXP node
+ in the current context? */
+ err = check_arrival (mctx, sub_top->path, sub_top->node,
+ sub_top->str_idx, cls_node, sl_str,
+ OP_CLOSE_SUBEXP);
+ if (err == REG_NOMATCH)
+ continue;
+ if (__glibc_unlikely (err != REG_NOERROR))
+ return err;
+ sub_last = match_ctx_add_sublast (sub_top, cls_node, sl_str);
+ if (__glibc_unlikely (sub_last == NULL))
+ return REG_ESPACE;
+ err = get_subexp_sub (mctx, sub_top, sub_last, bkref_node,
+ bkref_str_idx);
+ buf = (const char *) re_string_get_buffer (&mctx->input);
+ if (err == REG_NOMATCH)
+ continue;
+ if (__glibc_unlikely (err != REG_NOERROR))
+ return err;
+ }
+ }
+ return REG_NOERROR;
+}
+
+/* Helper functions for get_subexp(). */
+
+/* Check SUB_LAST can arrive to the back reference BKREF_NODE at BKREF_STR.
+ If it can arrive, register the sub expression expressed with SUB_TOP
+ and SUB_LAST. */
+
+static reg_errcode_t
+get_subexp_sub (re_match_context_t *mctx, const re_sub_match_top_t *sub_top,
+ re_sub_match_last_t *sub_last, Idx bkref_node, Idx bkref_str)
+{
+ reg_errcode_t err;
+ Idx to_idx;
+ /* Can the subexpression arrive the back reference? */
+ err = check_arrival (mctx, &sub_last->path, sub_last->node,
+ sub_last->str_idx, bkref_node, bkref_str,
+ OP_OPEN_SUBEXP);
+ if (err != REG_NOERROR)
+ return err;
+ err = match_ctx_add_entry (mctx, bkref_node, bkref_str, sub_top->str_idx,
+ sub_last->str_idx);
+ if (__glibc_unlikely (err != REG_NOERROR))
+ return err;
+ to_idx = bkref_str + sub_last->str_idx - sub_top->str_idx;
+ return clean_state_log_if_needed (mctx, to_idx);
+}
+
+/* Find the first node which is '(' or ')' and whose index is SUBEXP_IDX.
+ Search '(' if FL_OPEN, or search ')' otherwise.
+ TODO: This function isn't efficient...
+ Because there might be more than one nodes whose types are
+ OP_OPEN_SUBEXP and whose index is SUBEXP_IDX, we must check all
+ nodes.
+ E.g. RE: (a){2} */
+
+static Idx
+find_subexp_node (const re_dfa_t *dfa, const re_node_set *nodes,
+ Idx subexp_idx, int type)
+{
+ Idx cls_idx;
+ for (cls_idx = 0; cls_idx < nodes->nelem; ++cls_idx)
+ {
+ Idx cls_node = nodes->elems[cls_idx];
+ const re_token_t *node = dfa->nodes + cls_node;
+ if (node->type == type
+ && node->opr.idx == subexp_idx)
+ return cls_node;
+ }
+ return -1;
+}
+
+/* Check whether the node TOP_NODE at TOP_STR can arrive to the node
+ LAST_NODE at LAST_STR. We record the path onto PATH since it will be
+ heavily reused.
+ Return REG_NOERROR if it can arrive, REG_NOMATCH if it cannot,
+ REG_ESPACE if memory is exhausted. */
+
+static reg_errcode_t
+__attribute_warn_unused_result__
+check_arrival (re_match_context_t *mctx, state_array_t *path, Idx top_node,
+ Idx top_str, Idx last_node, Idx last_str, int type)
+{
+ const re_dfa_t *const dfa = mctx->dfa;
+ reg_errcode_t err = REG_NOERROR;
+ Idx subexp_num, backup_cur_idx, str_idx, null_cnt;
+ re_dfastate_t *cur_state = NULL;
+ re_node_set *cur_nodes, next_nodes;
+ re_dfastate_t **backup_state_log;
+ unsigned int context;
+
+ subexp_num = dfa->nodes[top_node].opr.idx;
+ /* Extend the buffer if we need. */
+ if (__glibc_unlikely (path->alloc < last_str + mctx->max_mb_elem_len + 1))
+ {
+ re_dfastate_t **new_array;
+ Idx old_alloc = path->alloc;
+ Idx incr_alloc = last_str + mctx->max_mb_elem_len + 1;
+ Idx new_alloc;
+ if (__glibc_unlikely (IDX_MAX - old_alloc < incr_alloc))
+ return REG_ESPACE;
+ new_alloc = old_alloc + incr_alloc;
+ if (__glibc_unlikely (SIZE_MAX / sizeof (re_dfastate_t *) < new_alloc))
+ return REG_ESPACE;
+ new_array = re_realloc (path->array, re_dfastate_t *, new_alloc);
+ if (__glibc_unlikely (new_array == NULL))
+ return REG_ESPACE;
+ path->array = new_array;
+ path->alloc = new_alloc;
+ memset (new_array + old_alloc, '\0',
+ sizeof (re_dfastate_t *) * (path->alloc - old_alloc));
+ }
+
+ str_idx = path->next_idx ? path->next_idx : top_str;
+
+ /* Temporary modify MCTX. */
+ backup_state_log = mctx->state_log;
+ backup_cur_idx = mctx->input.cur_idx;
+ mctx->state_log = path->array;
+ mctx->input.cur_idx = str_idx;
+
+ /* Setup initial node set. */
+ context = re_string_context_at (&mctx->input, str_idx - 1, mctx->eflags);
+ if (str_idx == top_str)
+ {
+ err = re_node_set_init_1 (&next_nodes, top_node);
+ if (__glibc_unlikely (err != REG_NOERROR))
+ return err;
+ err = check_arrival_expand_ecl (dfa, &next_nodes, subexp_num, type);
+ if (__glibc_unlikely (err != REG_NOERROR))
+ {
+ re_node_set_free (&next_nodes);
+ return err;
+ }
+ }
+ else
+ {
+ cur_state = mctx->state_log[str_idx];
+ if (cur_state && cur_state->has_backref)
+ {
+ err = re_node_set_init_copy (&next_nodes, &cur_state->nodes);
+ if (__glibc_unlikely (err != REG_NOERROR))
+ return err;
+ }
+ else
+ re_node_set_init_empty (&next_nodes);
+ }
+ if (str_idx == top_str || (cur_state && cur_state->has_backref))
+ {
+ if (next_nodes.nelem)
+ {
+ err = expand_bkref_cache (mctx, &next_nodes, str_idx,
+ subexp_num, type);
+ if (__glibc_unlikely (err != REG_NOERROR))
+ {
+ re_node_set_free (&next_nodes);
+ return err;
+ }
+ }
+ cur_state = re_acquire_state_context (&err, dfa, &next_nodes, context);
+ if (__glibc_unlikely (cur_state == NULL && err != REG_NOERROR))
+ {
+ re_node_set_free (&next_nodes);
+ return err;
+ }
+ mctx->state_log[str_idx] = cur_state;
+ }
+
+ for (null_cnt = 0; str_idx < last_str && null_cnt <= mctx->max_mb_elem_len;)
+ {
+ re_node_set_empty (&next_nodes);
+ if (mctx->state_log[str_idx + 1])
+ {
+ err = re_node_set_merge (&next_nodes,
+ &mctx->state_log[str_idx + 1]->nodes);
+ if (__glibc_unlikely (err != REG_NOERROR))
+ {
+ re_node_set_free (&next_nodes);
+ return err;
+ }
+ }
+ if (cur_state)
+ {
+ err = check_arrival_add_next_nodes (mctx, str_idx,
+ &cur_state->non_eps_nodes,
+ &next_nodes);
+ if (__glibc_unlikely (err != REG_NOERROR))
+ {
+ re_node_set_free (&next_nodes);
+ return err;
+ }
+ }
+ ++str_idx;
+ if (next_nodes.nelem)
+ {
+ err = check_arrival_expand_ecl (dfa, &next_nodes, subexp_num, type);
+ if (__glibc_unlikely (err != REG_NOERROR))
+ {
+ re_node_set_free (&next_nodes);
+ return err;
+ }
+ err = expand_bkref_cache (mctx, &next_nodes, str_idx,
+ subexp_num, type);
+ if (__glibc_unlikely (err != REG_NOERROR))
+ {
+ re_node_set_free (&next_nodes);
+ return err;
+ }
+ }
+ context = re_string_context_at (&mctx->input, str_idx - 1, mctx->eflags);
+ cur_state = re_acquire_state_context (&err, dfa, &next_nodes, context);
+ if (__glibc_unlikely (cur_state == NULL && err != REG_NOERROR))
+ {
+ re_node_set_free (&next_nodes);
+ return err;
+ }
+ mctx->state_log[str_idx] = cur_state;
+ null_cnt = cur_state == NULL ? null_cnt + 1 : 0;
+ }
+ re_node_set_free (&next_nodes);
+ cur_nodes = (mctx->state_log[last_str] == NULL ? NULL
+ : &mctx->state_log[last_str]->nodes);
+ path->next_idx = str_idx;
+
+ /* Fix MCTX. */
+ mctx->state_log = backup_state_log;
+ mctx->input.cur_idx = backup_cur_idx;
+
+ /* Then check the current node set has the node LAST_NODE. */
+ if (cur_nodes != NULL && re_node_set_contains (cur_nodes, last_node))
+ return REG_NOERROR;
+
+ return REG_NOMATCH;
+}
+
+/* Helper functions for check_arrival. */
+
+/* Calculate the destination nodes of CUR_NODES at STR_IDX, and append them
+ to NEXT_NODES.
+ TODO: This function is similar to the functions transit_state*(),
+ however this function has many additional works.
+ Can't we unify them? */
+
+static reg_errcode_t
+__attribute_warn_unused_result__
+check_arrival_add_next_nodes (re_match_context_t *mctx, Idx str_idx,
+ re_node_set *cur_nodes, re_node_set *next_nodes)
+{
+ const re_dfa_t *const dfa = mctx->dfa;
+ bool ok;
+ Idx cur_idx;
+ reg_errcode_t err = REG_NOERROR;
+ re_node_set union_set;
+ re_node_set_init_empty (&union_set);
+ for (cur_idx = 0; cur_idx < cur_nodes->nelem; ++cur_idx)
+ {
+ int naccepted = 0;
+ Idx cur_node = cur_nodes->elems[cur_idx];
+ DEBUG_ASSERT (!IS_EPSILON_NODE (dfa->nodes[cur_node].type));
+
+ /* If the node may accept "multi byte". */
+ if (dfa->nodes[cur_node].accept_mb)
+ {
+ naccepted = check_node_accept_bytes (dfa, cur_node, &mctx->input,
+ str_idx);
+ if (naccepted > 1)
+ {
+ re_dfastate_t *dest_state;
+ Idx next_node = dfa->nexts[cur_node];
+ Idx next_idx = str_idx + naccepted;
+ dest_state = mctx->state_log[next_idx];
+ re_node_set_empty (&union_set);
+ if (dest_state)
+ {
+ err = re_node_set_merge (&union_set, &dest_state->nodes);
+ if (__glibc_unlikely (err != REG_NOERROR))
+ {
+ re_node_set_free (&union_set);
+ return err;
+ }
+ }
+ ok = re_node_set_insert (&union_set, next_node);
+ if (__glibc_unlikely (! ok))
+ {
+ re_node_set_free (&union_set);
+ return REG_ESPACE;
+ }
+ mctx->state_log[next_idx] = re_acquire_state (&err, dfa,
+ &union_set);
+ if (__glibc_unlikely (mctx->state_log[next_idx] == NULL
+ && err != REG_NOERROR))
+ {
+ re_node_set_free (&union_set);
+ return err;
+ }
+ }
+ }
+
+ if (naccepted
+ || check_node_accept (mctx, dfa->nodes + cur_node, str_idx))
+ {
+ ok = re_node_set_insert (next_nodes, dfa->nexts[cur_node]);
+ if (__glibc_unlikely (! ok))
+ {
+ re_node_set_free (&union_set);
+ return REG_ESPACE;
+ }
+ }
+ }
+ re_node_set_free (&union_set);
+ return REG_NOERROR;
+}
+
+/* For all the nodes in CUR_NODES, add the epsilon closures of them to
+ CUR_NODES, however exclude the nodes which are:
+ - inside the sub expression whose number is EX_SUBEXP, if FL_OPEN.
+ - out of the sub expression whose number is EX_SUBEXP, if !FL_OPEN.
+*/
+
+static reg_errcode_t
+check_arrival_expand_ecl (const re_dfa_t *dfa, re_node_set *cur_nodes,
+ Idx ex_subexp, int type)
+{
+ reg_errcode_t err;
+ Idx idx, outside_node;
+ re_node_set new_nodes;
+ DEBUG_ASSERT (cur_nodes->nelem);
+ err = re_node_set_alloc (&new_nodes, cur_nodes->nelem);
+ if (__glibc_unlikely (err != REG_NOERROR))
+ return err;
+ /* Create a new node set NEW_NODES with the nodes which are epsilon
+ closures of the node in CUR_NODES. */
+
+ for (idx = 0; idx < cur_nodes->nelem; ++idx)
+ {
+ Idx cur_node = cur_nodes->elems[idx];
+ const re_node_set *eclosure = dfa->eclosures + cur_node;
+ outside_node = find_subexp_node (dfa, eclosure, ex_subexp, type);
+ if (outside_node == -1)
+ {
+ /* There are no problematic nodes, just merge them. */
+ err = re_node_set_merge (&new_nodes, eclosure);
+ if (__glibc_unlikely (err != REG_NOERROR))
+ {
+ re_node_set_free (&new_nodes);
+ return err;
+ }
+ }
+ else
+ {
+ /* There are problematic nodes, re-calculate incrementally. */
+ err = check_arrival_expand_ecl_sub (dfa, &new_nodes, cur_node,
+ ex_subexp, type);
+ if (__glibc_unlikely (err != REG_NOERROR))
+ {
+ re_node_set_free (&new_nodes);
+ return err;
+ }
+ }
+ }
+ re_node_set_free (cur_nodes);
+ *cur_nodes = new_nodes;
+ return REG_NOERROR;
+}
+
+/* Helper function for check_arrival_expand_ecl.
+ Check incrementally the epsilon closure of TARGET, and if it isn't
+ problematic append it to DST_NODES. */
+
+static reg_errcode_t
+__attribute_warn_unused_result__
+check_arrival_expand_ecl_sub (const re_dfa_t *dfa, re_node_set *dst_nodes,
+ Idx target, Idx ex_subexp, int type)
+{
+ Idx cur_node;
+ for (cur_node = target; !re_node_set_contains (dst_nodes, cur_node);)
+ {
+ bool ok;
+
+ if (dfa->nodes[cur_node].type == type
+ && dfa->nodes[cur_node].opr.idx == ex_subexp)
+ {
+ if (type == OP_CLOSE_SUBEXP)
+ {
+ ok = re_node_set_insert (dst_nodes, cur_node);
+ if (__glibc_unlikely (! ok))
+ return REG_ESPACE;
+ }
+ break;
+ }
+ ok = re_node_set_insert (dst_nodes, cur_node);
+ if (__glibc_unlikely (! ok))
+ return REG_ESPACE;
+ if (dfa->edests[cur_node].nelem == 0)
+ break;
+ if (dfa->edests[cur_node].nelem == 2)
+ {
+ reg_errcode_t err;
+ err = check_arrival_expand_ecl_sub (dfa, dst_nodes,
+ dfa->edests[cur_node].elems[1],
+ ex_subexp, type);
+ if (__glibc_unlikely (err != REG_NOERROR))
+ return err;
+ }
+ cur_node = dfa->edests[cur_node].elems[0];
+ }
+ return REG_NOERROR;
+}
+
+
+/* For all the back references in the current state, calculate the
+ destination of the back references by the appropriate entry
+ in MCTX->BKREF_ENTS. */
+
+static reg_errcode_t
+__attribute_warn_unused_result__
+expand_bkref_cache (re_match_context_t *mctx, re_node_set *cur_nodes,
+ Idx cur_str, Idx subexp_num, int type)
+{
+ const re_dfa_t *const dfa = mctx->dfa;
+ reg_errcode_t err;
+ Idx cache_idx_start = search_cur_bkref_entry (mctx, cur_str);
+ struct re_backref_cache_entry *ent;
+
+ if (cache_idx_start == -1)
+ return REG_NOERROR;
+
+ restart:
+ ent = mctx->bkref_ents + cache_idx_start;
+ do
+ {
+ Idx to_idx, next_node;
+
+ /* Is this entry ENT is appropriate? */
+ if (!re_node_set_contains (cur_nodes, ent->node))
+ continue; /* No. */
+
+ to_idx = cur_str + ent->subexp_to - ent->subexp_from;
+ /* Calculate the destination of the back reference, and append it
+ to MCTX->STATE_LOG. */
+ if (to_idx == cur_str)
+ {
+ /* The backreference did epsilon transit, we must re-check all the
+ node in the current state. */
+ re_node_set new_dests;
+ reg_errcode_t err2, err3;
+ next_node = dfa->edests[ent->node].elems[0];
+ if (re_node_set_contains (cur_nodes, next_node))
+ continue;
+ err = re_node_set_init_1 (&new_dests, next_node);
+ err2 = check_arrival_expand_ecl (dfa, &new_dests, subexp_num, type);
+ err3 = re_node_set_merge (cur_nodes, &new_dests);
+ re_node_set_free (&new_dests);
+ if (__glibc_unlikely (err != REG_NOERROR || err2 != REG_NOERROR
+ || err3 != REG_NOERROR))
+ {
+ err = (err != REG_NOERROR ? err
+ : (err2 != REG_NOERROR ? err2 : err3));
+ return err;
+ }
+ /* TODO: It is still inefficient... */
+ goto restart;
+ }
+ else
+ {
+ re_node_set union_set;
+ next_node = dfa->nexts[ent->node];
+ if (mctx->state_log[to_idx])
+ {
+ bool ok;
+ if (re_node_set_contains (&mctx->state_log[to_idx]->nodes,
+ next_node))
+ continue;
+ err = re_node_set_init_copy (&union_set,
+ &mctx->state_log[to_idx]->nodes);
+ ok = re_node_set_insert (&union_set, next_node);
+ if (__glibc_unlikely (err != REG_NOERROR || ! ok))
+ {
+ re_node_set_free (&union_set);
+ err = err != REG_NOERROR ? err : REG_ESPACE;
+ return err;
+ }
+ }
+ else
+ {
+ err = re_node_set_init_1 (&union_set, next_node);
+ if (__glibc_unlikely (err != REG_NOERROR))
+ return err;
+ }
+ mctx->state_log[to_idx] = re_acquire_state (&err, dfa, &union_set);
+ re_node_set_free (&union_set);
+ if (__glibc_unlikely (mctx->state_log[to_idx] == NULL
+ && err != REG_NOERROR))
+ return err;
+ }
+ }
+ while (ent++->more);
+ return REG_NOERROR;
+}
+
+/* Build transition table for the state.
+ Return true if successful. */
+
+static bool __attribute_noinline__
+build_trtable (const re_dfa_t *dfa, re_dfastate_t *state)
+{
+ reg_errcode_t err;
+ Idx i, j;
+ int ch;
+ bool need_word_trtable = false;
+ bitset_word_t elem, mask;
+ Idx ndests; /* Number of the destination states from 'state'. */
+ re_dfastate_t **trtable;
+ re_dfastate_t *dest_states[SBC_MAX];
+ re_dfastate_t *dest_states_word[SBC_MAX];
+ re_dfastate_t *dest_states_nl[SBC_MAX];
+ re_node_set follows;
+ bitset_t acceptable;
+
+ /* We build DFA states which corresponds to the destination nodes
+ from 'state'. 'dests_node[i]' represents the nodes which i-th
+ destination state contains, and 'dests_ch[i]' represents the
+ characters which i-th destination state accepts. */
+ re_node_set dests_node[SBC_MAX];
+ bitset_t dests_ch[SBC_MAX];
+
+ /* Initialize transition table. */
+ state->word_trtable = state->trtable = NULL;
+
+ /* At first, group all nodes belonging to 'state' into several
+ destinations. */
+ ndests = group_nodes_into_DFAstates (dfa, state, dests_node, dests_ch);
+ if (__glibc_unlikely (ndests <= 0))
+ {
+ /* Return false in case of an error, true otherwise. */
+ if (ndests == 0)
+ {
+ state->trtable = (re_dfastate_t **)
+ calloc (sizeof (re_dfastate_t *), SBC_MAX);
+ if (__glibc_unlikely (state->trtable == NULL))
+ return false;
+ return true;
+ }
+ return false;
+ }
+
+ err = re_node_set_alloc (&follows, ndests + 1);
+ if (__glibc_unlikely (err != REG_NOERROR))
+ {
+ out_free:
+ re_node_set_free (&follows);
+ for (i = 0; i < ndests; ++i)
+ re_node_set_free (dests_node + i);
+ return false;
+ }
+
+ bitset_empty (acceptable);
+
+ /* Then build the states for all destinations. */
+ for (i = 0; i < ndests; ++i)
+ {
+ Idx next_node;
+ re_node_set_empty (&follows);
+ /* Merge the follows of this destination states. */
+ for (j = 0; j < dests_node[i].nelem; ++j)
+ {
+ next_node = dfa->nexts[dests_node[i].elems[j]];
+ if (next_node != -1)
+ {
+ err = re_node_set_merge (&follows, dfa->eclosures + next_node);
+ if (__glibc_unlikely (err != REG_NOERROR))
+ goto out_free;
+ }
+ }
+ dest_states[i] = re_acquire_state_context (&err, dfa, &follows, 0);
+ if (__glibc_unlikely (dest_states[i] == NULL && err != REG_NOERROR))
+ goto out_free;
+ /* If the new state has context constraint,
+ build appropriate states for these contexts. */
+ if (dest_states[i]->has_constraint)
+ {
+ dest_states_word[i] = re_acquire_state_context (&err, dfa, &follows,
+ CONTEXT_WORD);
+ if (__glibc_unlikely (dest_states_word[i] == NULL
+ && err != REG_NOERROR))
+ goto out_free;
+
+ if (dest_states[i] != dest_states_word[i] && dfa->mb_cur_max > 1)
+ need_word_trtable = true;
+
+ dest_states_nl[i] = re_acquire_state_context (&err, dfa, &follows,
+ CONTEXT_NEWLINE);
+ if (__glibc_unlikely (dest_states_nl[i] == NULL && err != REG_NOERROR))
+ goto out_free;
+ }
+ else
+ {
+ dest_states_word[i] = dest_states[i];
+ dest_states_nl[i] = dest_states[i];
+ }
+ bitset_merge (acceptable, dests_ch[i]);
+ }
+
+ if (!__glibc_unlikely (need_word_trtable))
+ {
+ /* We don't care about whether the following character is a word
+ character, or we are in a single-byte character set so we can
+ discern by looking at the character code: allocate a
+ 256-entry transition table. */
+ trtable = state->trtable =
+ (re_dfastate_t **) calloc (sizeof (re_dfastate_t *), SBC_MAX);
+ if (__glibc_unlikely (trtable == NULL))
+ goto out_free;
+
+ /* For all characters ch...: */
+ for (i = 0; i < BITSET_WORDS; ++i)
+ for (ch = i * BITSET_WORD_BITS, elem = acceptable[i], mask = 1;
+ elem;
+ mask <<= 1, elem >>= 1, ++ch)
+ if (__glibc_unlikely (elem & 1))
+ {
+ /* There must be exactly one destination which accepts
+ character ch. See group_nodes_into_DFAstates. */
+ for (j = 0; (dests_ch[j][i] & mask) == 0; ++j)
+ ;
+
+ /* j-th destination accepts the word character ch. */
+ if (dfa->word_char[i] & mask)
+ trtable[ch] = dest_states_word[j];
+ else
+ trtable[ch] = dest_states[j];
+ }
+ }
+ else
+ {
+ /* We care about whether the following character is a word
+ character, and we are in a multi-byte character set: discern
+ by looking at the character code: build two 256-entry
+ transition tables, one starting at trtable[0] and one
+ starting at trtable[SBC_MAX]. */
+ trtable = state->word_trtable =
+ (re_dfastate_t **) calloc (sizeof (re_dfastate_t *), 2 * SBC_MAX);
+ if (__glibc_unlikely (trtable == NULL))
+ goto out_free;
+
+ /* For all characters ch...: */
+ for (i = 0; i < BITSET_WORDS; ++i)
+ for (ch = i * BITSET_WORD_BITS, elem = acceptable[i], mask = 1;
+ elem;
+ mask <<= 1, elem >>= 1, ++ch)
+ if (__glibc_unlikely (elem & 1))
+ {
+ /* There must be exactly one destination which accepts
+ character ch. See group_nodes_into_DFAstates. */
+ for (j = 0; (dests_ch[j][i] & mask) == 0; ++j)
+ ;
+
+ /* j-th destination accepts the word character ch. */
+ trtable[ch] = dest_states[j];
+ trtable[ch + SBC_MAX] = dest_states_word[j];
+ }
+ }
+
+ /* new line */
+ if (bitset_contain (acceptable, NEWLINE_CHAR))
+ {
+ /* The current state accepts newline character. */
+ for (j = 0; j < ndests; ++j)
+ if (bitset_contain (dests_ch[j], NEWLINE_CHAR))
+ {
+ /* k-th destination accepts newline character. */
+ trtable[NEWLINE_CHAR] = dest_states_nl[j];
+ if (need_word_trtable)
+ trtable[NEWLINE_CHAR + SBC_MAX] = dest_states_nl[j];
+ /* There must be only one destination which accepts
+ newline. See group_nodes_into_DFAstates. */
+ break;
+ }
+ }
+
+ re_node_set_free (&follows);
+ for (i = 0; i < ndests; ++i)
+ re_node_set_free (dests_node + i);
+ return true;
+}
+
+/* Group all nodes belonging to STATE into several destinations.
+ Then for all destinations, set the nodes belonging to the destination
+ to DESTS_NODE[i] and set the characters accepted by the destination
+ to DEST_CH[i]. Return the number of destinations if successful,
+ -1 on internal error. */
+
+static Idx
+group_nodes_into_DFAstates (const re_dfa_t *dfa, const re_dfastate_t *state,
+ re_node_set *dests_node, bitset_t *dests_ch)
+{
+ reg_errcode_t err;
+ bool ok;
+ Idx i, j, k;
+ Idx ndests; /* Number of the destinations from 'state'. */
+ bitset_t accepts; /* Characters a node can accept. */
+ const re_node_set *cur_nodes = &state->nodes;
+ bitset_empty (accepts);
+ ndests = 0;
+
+ /* For all the nodes belonging to 'state', */
+ for (i = 0; i < cur_nodes->nelem; ++i)
+ {
+ re_token_t *node = &dfa->nodes[cur_nodes->elems[i]];
+ re_token_type_t type = node->type;
+ unsigned int constraint = node->constraint;
+
+ /* Enumerate all single byte character this node can accept. */
+ if (type == CHARACTER)
+ bitset_set (accepts, node->opr.c);
+ else if (type == SIMPLE_BRACKET)
+ {
+ bitset_merge (accepts, node->opr.sbcset);
+ }
+ else if (type == OP_PERIOD)
+ {
+ if (dfa->mb_cur_max > 1)
+ bitset_merge (accepts, dfa->sb_char);
+ else
+ bitset_set_all (accepts);
+ if (!(dfa->syntax & RE_DOT_NEWLINE))
+ bitset_clear (accepts, '\n');
+ if (dfa->syntax & RE_DOT_NOT_NULL)
+ bitset_clear (accepts, '\0');
+ }
+ else if (type == OP_UTF8_PERIOD)
+ {
+ if (ASCII_CHARS % BITSET_WORD_BITS == 0)
+ memset (accepts, -1, ASCII_CHARS / CHAR_BIT);
+ else
+ bitset_merge (accepts, utf8_sb_map);
+ if (!(dfa->syntax & RE_DOT_NEWLINE))
+ bitset_clear (accepts, '\n');
+ if (dfa->syntax & RE_DOT_NOT_NULL)
+ bitset_clear (accepts, '\0');
+ }
+ else
+ continue;
+
+ /* Check the 'accepts' and sift the characters which are not
+ match it the context. */
+ if (constraint)
+ {
+ if (constraint & NEXT_NEWLINE_CONSTRAINT)
+ {
+ bool accepts_newline = bitset_contain (accepts, NEWLINE_CHAR);
+ bitset_empty (accepts);
+ if (accepts_newline)
+ bitset_set (accepts, NEWLINE_CHAR);
+ else
+ continue;
+ }
+ if (constraint & NEXT_ENDBUF_CONSTRAINT)
+ {
+ bitset_empty (accepts);
+ continue;
+ }
+
+ if (constraint & NEXT_WORD_CONSTRAINT)
+ {
+ bitset_word_t any_set = 0;
+ if (type == CHARACTER && !node->word_char)
+ {
+ bitset_empty (accepts);
+ continue;
+ }
+ if (dfa->mb_cur_max > 1)
+ for (j = 0; j < BITSET_WORDS; ++j)
+ any_set |= (accepts[j] &= (dfa->word_char[j] | ~dfa->sb_char[j]));
+ else
+ for (j = 0; j < BITSET_WORDS; ++j)
+ any_set |= (accepts[j] &= dfa->word_char[j]);
+ if (!any_set)
+ continue;
+ }
+ if (constraint & NEXT_NOTWORD_CONSTRAINT)
+ {
+ bitset_word_t any_set = 0;
+ if (type == CHARACTER && node->word_char)
+ {
+ bitset_empty (accepts);
+ continue;
+ }
+ if (dfa->mb_cur_max > 1)
+ for (j = 0; j < BITSET_WORDS; ++j)
+ any_set |= (accepts[j] &= ~(dfa->word_char[j] & dfa->sb_char[j]));
+ else
+ for (j = 0; j < BITSET_WORDS; ++j)
+ any_set |= (accepts[j] &= ~dfa->word_char[j]);
+ if (!any_set)
+ continue;
+ }
+ }
+
+ /* Then divide 'accepts' into DFA states, or create a new
+ state. Above, we make sure that accepts is not empty. */
+ for (j = 0; j < ndests; ++j)
+ {
+ bitset_t intersec; /* Intersection sets, see below. */
+ bitset_t remains;
+ /* Flags, see below. */
+ bitset_word_t has_intersec, not_subset, not_consumed;
+
+ /* Optimization, skip if this state doesn't accept the character. */
+ if (type == CHARACTER && !bitset_contain (dests_ch[j], node->opr.c))
+ continue;
+
+ /* Enumerate the intersection set of this state and 'accepts'. */
+ has_intersec = 0;
+ for (k = 0; k < BITSET_WORDS; ++k)
+ has_intersec |= intersec[k] = accepts[k] & dests_ch[j][k];
+ /* And skip if the intersection set is empty. */
+ if (!has_intersec)
+ continue;
+
+ /* Then check if this state is a subset of 'accepts'. */
+ not_subset = not_consumed = 0;
+ for (k = 0; k < BITSET_WORDS; ++k)
+ {
+ not_subset |= remains[k] = ~accepts[k] & dests_ch[j][k];
+ not_consumed |= accepts[k] = accepts[k] & ~dests_ch[j][k];
+ }
+
+ /* If this state isn't a subset of 'accepts', create a
+ new group state, which has the 'remains'. */
+ if (not_subset)
+ {
+ bitset_copy (dests_ch[ndests], remains);
+ bitset_copy (dests_ch[j], intersec);
+ err = re_node_set_init_copy (dests_node + ndests, &dests_node[j]);
+ if (__glibc_unlikely (err != REG_NOERROR))
+ goto error_return;
+ ++ndests;
+ }
+
+ /* Put the position in the current group. */
+ ok = re_node_set_insert (&dests_node[j], cur_nodes->elems[i]);
+ if (__glibc_unlikely (! ok))
+ goto error_return;
+
+ /* If all characters are consumed, go to next node. */
+ if (!not_consumed)
+ break;
+ }
+ /* Some characters remain, create a new group. */
+ if (j == ndests)
+ {
+ bitset_copy (dests_ch[ndests], accepts);
+ err = re_node_set_init_1 (dests_node + ndests, cur_nodes->elems[i]);
+ if (__glibc_unlikely (err != REG_NOERROR))
+ goto error_return;
+ ++ndests;
+ bitset_empty (accepts);
+ }
+ }
+ assume (ndests <= SBC_MAX);
+ return ndests;
+ error_return:
+ for (j = 0; j < ndests; ++j)
+ re_node_set_free (dests_node + j);
+ return -1;
+}
+
+/* Check how many bytes the node 'dfa->nodes[node_idx]' accepts.
+ Return the number of the bytes the node accepts.
+ STR_IDX is the current index of the input string.
+
+ This function handles the nodes which can accept one character, or
+ one collating element like '.', '[a-z]', opposite to the other nodes
+ can only accept one byte. */
+
+#ifdef _LIBC
+# include <locale/weight.h>
+#endif
+
+static int
+check_node_accept_bytes (const re_dfa_t *dfa, Idx node_idx,
+ const re_string_t *input, Idx str_idx)
+{
+ const re_token_t *node = dfa->nodes + node_idx;
+ int char_len, elem_len;
+ Idx i;
+
+ if (__glibc_unlikely (node->type == OP_UTF8_PERIOD))
+ {
+ unsigned char c = re_string_byte_at (input, str_idx), d;
+ if (__glibc_likely (c < 0xc2))
+ return 0;
+
+ if (str_idx + 2 > input->len)
+ return 0;
+
+ d = re_string_byte_at (input, str_idx + 1);
+ if (c < 0xe0)
+ return (d < 0x80 || d > 0xbf) ? 0 : 2;
+ else if (c < 0xf0)
+ {
+ char_len = 3;
+ if (c == 0xe0 && d < 0xa0)
+ return 0;
+ }
+ else if (c < 0xf8)
+ {
+ char_len = 4;
+ if (c == 0xf0 && d < 0x90)
+ return 0;
+ }
+ else if (c < 0xfc)
+ {
+ char_len = 5;
+ if (c == 0xf8 && d < 0x88)
+ return 0;
+ }
+ else if (c < 0xfe)
+ {
+ char_len = 6;
+ if (c == 0xfc && d < 0x84)
+ return 0;
+ }
+ else
+ return 0;
+
+ if (str_idx + char_len > input->len)
+ return 0;
+
+ for (i = 1; i < char_len; ++i)
+ {
+ d = re_string_byte_at (input, str_idx + i);
+ if (d < 0x80 || d > 0xbf)
+ return 0;
+ }
+ return char_len;
+ }
+
+ char_len = re_string_char_size_at (input, str_idx);
+ if (node->type == OP_PERIOD)
+ {
+ if (char_len <= 1)
+ return 0;
+ /* 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'))
+ return 0;
+ return char_len;
+ }
+
+ elem_len = re_string_elem_size_at (input, str_idx);
+ if ((elem_len <= 1 && char_len <= 1) || char_len == 0)
+ return 0;
+
+ if (node->type == COMPLEX_BRACKET)
+ {
+ const re_charset_t *cset = node->opr.mbcset;
+#ifdef _LIBC
+ const unsigned char *pin
+ = ((const unsigned char *) re_string_get_buffer (input) + str_idx);
+ Idx j;
+ uint32_t nrules;
+#endif
+ int match_len = 0;
+ wchar_t wc = ((cset->nranges || cset->nchar_classes || cset->nmbchars)
+ ? re_string_wchar_at (input, str_idx) : 0);
+
+ /* match with multibyte character? */
+ for (i = 0; i < cset->nmbchars; ++i)
+ if (wc == cset->mbchars[i])
+ {
+ match_len = char_len;
+ goto check_node_accept_bytes_match;
+ }
+ /* match with character_class? */
+ for (i = 0; i < cset->nchar_classes; ++i)
+ {
+ wctype_t wt = cset->char_classes[i];
+ if (__iswctype (wc, wt))
+ {
+ match_len = char_len;
+ goto check_node_accept_bytes_match;
+ }
+ }
+
+#ifdef _LIBC
+ nrules = _NL_CURRENT_WORD (LC_COLLATE, _NL_COLLATE_NRULES);
+ if (nrules != 0)
+ {
+ unsigned int in_collseq = 0;
+ const int32_t *table, *indirect;
+ const unsigned char *weights, *extra;
+ const char *collseqwc;
+
+ /* match with collating_symbol? */
+ if (cset->ncoll_syms)
+ extra = (const unsigned char *)
+ _NL_CURRENT (LC_COLLATE, _NL_COLLATE_SYMB_EXTRAMB);
+ for (i = 0; i < cset->ncoll_syms; ++i)
+ {
+ const unsigned char *coll_sym = extra + cset->coll_syms[i];
+ /* Compare the length of input collating element and
+ the length of current collating element. */
+ if (*coll_sym != elem_len)
+ continue;
+ /* Compare each bytes. */
+ for (j = 0; j < *coll_sym; j++)
+ if (pin[j] != coll_sym[1 + j])
+ break;
+ if (j == *coll_sym)
+ {
+ /* Match if every bytes is equal. */
+ match_len = j;
+ goto check_node_accept_bytes_match;
+ }
+ }
+
+ if (cset->nranges)
+ {
+ if (elem_len <= char_len)
+ {
+ collseqwc = _NL_CURRENT (LC_COLLATE, _NL_COLLATE_COLLSEQWC);
+ in_collseq = __collseq_table_lookup (collseqwc, wc);
+ }
+ else
+ in_collseq = find_collation_sequence_value (pin, elem_len);
+ }
+ /* match with range expression? */
+ /* FIXME: Implement rational ranges here, too. */
+ for (i = 0; i < cset->nranges; ++i)
+ if (cset->range_starts[i] <= in_collseq
+ && in_collseq <= cset->range_ends[i])
+ {
+ match_len = elem_len;
+ goto check_node_accept_bytes_match;
+ }
+
+ /* match with equivalence_class? */
+ if (cset->nequiv_classes)
+ {
+ const unsigned char *cp = pin;
+ table = (const int32_t *)
+ _NL_CURRENT (LC_COLLATE, _NL_COLLATE_TABLEMB);
+ weights = (const unsigned char *)
+ _NL_CURRENT (LC_COLLATE, _NL_COLLATE_WEIGHTMB);
+ extra = (const unsigned char *)
+ _NL_CURRENT (LC_COLLATE, _NL_COLLATE_EXTRAMB);
+ indirect = (const int32_t *)
+ _NL_CURRENT (LC_COLLATE, _NL_COLLATE_INDIRECTMB);
+ int32_t idx = findidx (table, indirect, extra, &cp, elem_len);
+ int32_t rule = idx >> 24;
+ idx &= 0xffffff;
+ if (idx > 0)
+ {
+ size_t weight_len = weights[idx];
+ for (i = 0; i < cset->nequiv_classes; ++i)
+ {
+ int32_t equiv_class_idx = cset->equiv_classes[i];
+ int32_t equiv_class_rule = equiv_class_idx >> 24;
+ equiv_class_idx &= 0xffffff;
+ if (weights[equiv_class_idx] == weight_len
+ && equiv_class_rule == rule
+ && memcmp (weights + idx + 1,
+ weights + equiv_class_idx + 1,
+ weight_len) == 0)
+ {
+ match_len = elem_len;
+ goto check_node_accept_bytes_match;
+ }
+ }
+ }
+ }
+ }
+ else
+#endif /* _LIBC */
+ {
+ /* match with range expression? */
+ for (i = 0; i < cset->nranges; ++i)
+ {
+ if (cset->range_starts[i] <= wc && wc <= cset->range_ends[i])
+ {
+ match_len = char_len;
+ goto check_node_accept_bytes_match;
+ }
+ }
+ }
+ check_node_accept_bytes_match:
+ if (!cset->non_match)
+ return match_len;
+ else
+ {
+ if (match_len > 0)
+ return 0;
+ else
+ return (elem_len > char_len) ? elem_len : char_len;
+ }
+ }
+ return 0;
+}
+
+#ifdef _LIBC
+static unsigned int
+find_collation_sequence_value (const unsigned char *mbs, size_t mbs_len)
+{
+ uint32_t nrules = _NL_CURRENT_WORD (LC_COLLATE, _NL_COLLATE_NRULES);
+ if (nrules == 0)
+ {
+ if (mbs_len == 1)
+ {
+ /* No valid character. Match it as a single byte character. */
+ const unsigned char *collseq = (const unsigned char *)
+ _NL_CURRENT (LC_COLLATE, _NL_COLLATE_COLLSEQMB);
+ return collseq[mbs[0]];
+ }
+ return UINT_MAX;
+ }
+ else
+ {
+ int32_t idx;
+ const unsigned char *extra = (const unsigned char *)
+ _NL_CURRENT (LC_COLLATE, _NL_COLLATE_SYMB_EXTRAMB);
+ int32_t extrasize = (const unsigned char *)
+ _NL_CURRENT (LC_COLLATE, _NL_COLLATE_SYMB_EXTRAMB + 1) - extra;
+
+ for (idx = 0; idx < extrasize;)
+ {
+ int mbs_cnt;
+ bool found = false;
+ int32_t elem_mbs_len;
+ /* Skip the name of collating element name. */
+ idx = idx + extra[idx] + 1;
+ elem_mbs_len = extra[idx++];
+ if (mbs_len == elem_mbs_len)
+ {
+ for (mbs_cnt = 0; mbs_cnt < elem_mbs_len; ++mbs_cnt)
+ if (extra[idx + mbs_cnt] != mbs[mbs_cnt])
+ break;
+ if (mbs_cnt == elem_mbs_len)
+ /* Found the entry. */
+ found = true;
+ }
+ /* Skip the byte sequence of the collating element. */
+ idx += elem_mbs_len;
+ /* Adjust for the alignment. */
+ idx = (idx + 3) & ~3;
+ /* Skip the collation sequence value. */
+ idx += sizeof (uint32_t);
+ /* Skip the wide char sequence of the collating element. */
+ idx = idx + sizeof (uint32_t) * (*(int32_t *) (extra + idx) + 1);
+ /* If we found the entry, return the sequence value. */
+ if (found)
+ return *(uint32_t *) (extra + idx);
+ /* Skip the collation sequence value. */
+ idx += sizeof (uint32_t);
+ }
+ return UINT_MAX;
+ }
+}
+#endif /* _LIBC */
+
+/* Check whether the node accepts the byte which is IDX-th
+ byte of the INPUT. */
+
+static bool
+check_node_accept (const re_match_context_t *mctx, const re_token_t *node,
+ Idx idx)
+{
+ unsigned char ch;
+ ch = re_string_byte_at (&mctx->input, idx);
+ switch (node->type)
+ {
+ case CHARACTER:
+ if (node->opr.c != ch)
+ return false;
+ break;
+
+ case SIMPLE_BRACKET:
+ if (!bitset_contain (node->opr.sbcset, ch))
+ return false;
+ break;
+
+ case OP_UTF8_PERIOD:
+ if (ch >= ASCII_CHARS)
+ return false;
+ FALLTHROUGH;
+ case OP_PERIOD:
+ if ((ch == '\n' && !(mctx->dfa->syntax & RE_DOT_NEWLINE))
+ || (ch == '\0' && (mctx->dfa->syntax & RE_DOT_NOT_NULL)))
+ return false;
+ break;
+
+ default:
+ return false;
+ }
+
+ if (node->constraint)
+ {
+ /* The node has constraints. Check whether the current context
+ satisfies the constraints. */
+ unsigned int context = re_string_context_at (&mctx->input, idx,
+ mctx->eflags);
+ if (NOT_SATISFY_NEXT_CONSTRAINT (node->constraint, context))
+ return false;
+ }
+
+ return true;
+}
+
+/* Extend the buffers, if the buffers have run out. */
+
+static reg_errcode_t
+__attribute_warn_unused_result__
+extend_buffers (re_match_context_t *mctx, int min_len)
+{
+ reg_errcode_t ret;
+ re_string_t *pstr = &mctx->input;
+
+ /* Avoid overflow. */
+ if (__glibc_unlikely (MIN (IDX_MAX, SIZE_MAX / sizeof (re_dfastate_t *)) / 2
+ <= pstr->bufs_len))
+ return REG_ESPACE;
+
+ /* Double the lengths of the buffers, but allocate at least MIN_LEN. */
+ ret = re_string_realloc_buffers (pstr,
+ MAX (min_len,
+ MIN (pstr->len, pstr->bufs_len * 2)));
+ if (__glibc_unlikely (ret != REG_NOERROR))
+ return ret;
+
+ if (mctx->state_log != NULL)
+ {
+ /* And double the length of state_log. */
+ /* XXX We have no indication of the size of this buffer. If this
+ allocation fail we have no indication that the state_log array
+ does not have the right size. */
+ re_dfastate_t **new_array = re_realloc (mctx->state_log, re_dfastate_t *,
+ pstr->bufs_len + 1);
+ if (__glibc_unlikely (new_array == NULL))
+ return REG_ESPACE;
+ mctx->state_log = new_array;
+ }
+
+ /* Then reconstruct the buffers. */
+ if (pstr->icase)
+ {
+ if (pstr->mb_cur_max > 1)
+ {
+ ret = build_wcs_upper_buffer (pstr);
+ if (__glibc_unlikely (ret != REG_NOERROR))
+ return ret;
+ }
+ else
+ build_upper_buffer (pstr);
+ }
+ else
+ {
+ if (pstr->mb_cur_max > 1)
+ build_wcs_buffer (pstr);
+ else
+ {
+ if (pstr->trans != NULL)
+ re_string_translate_buffer (pstr);
+ }
+ }
+ return REG_NOERROR;
+}
+
+
+/* Functions for matching context. */
+
+/* Initialize MCTX. */
+
+static reg_errcode_t
+__attribute_warn_unused_result__
+match_ctx_init (re_match_context_t *mctx, int eflags, Idx n)
+{
+ mctx->eflags = eflags;
+ mctx->match_last = -1;
+ if (n > 0)
+ {
+ /* Avoid overflow. */
+ size_t max_object_size =
+ MAX (sizeof (struct re_backref_cache_entry),
+ sizeof (re_sub_match_top_t *));
+ if (__glibc_unlikely (MIN (IDX_MAX, SIZE_MAX / max_object_size) < n))
+ return REG_ESPACE;
+
+ mctx->bkref_ents = re_malloc (struct re_backref_cache_entry, n);
+ mctx->sub_tops = re_malloc (re_sub_match_top_t *, n);
+ if (__glibc_unlikely (mctx->bkref_ents == NULL || mctx->sub_tops == NULL))
+ return REG_ESPACE;
+ }
+ /* Already zero-ed by the caller.
+ else
+ mctx->bkref_ents = NULL;
+ mctx->nbkref_ents = 0;
+ mctx->nsub_tops = 0; */
+ mctx->abkref_ents = n;
+ mctx->max_mb_elem_len = 1;
+ mctx->asub_tops = n;
+ return REG_NOERROR;
+}
+
+/* Clean the entries which depend on the current input in MCTX.
+ This function must be invoked when the matcher changes the start index
+ of the input, or changes the input string. */
+
+static void
+match_ctx_clean (re_match_context_t *mctx)
+{
+ Idx st_idx;
+ for (st_idx = 0; st_idx < mctx->nsub_tops; ++st_idx)
+ {
+ Idx sl_idx;
+ re_sub_match_top_t *top = mctx->sub_tops[st_idx];
+ for (sl_idx = 0; sl_idx < top->nlasts; ++sl_idx)
+ {
+ re_sub_match_last_t *last = top->lasts[sl_idx];
+ re_free (last->path.array);
+ re_free (last);
+ }
+ re_free (top->lasts);
+ if (top->path)
+ {
+ re_free (top->path->array);
+ re_free (top->path);
+ }
+ re_free (top);
+ }
+
+ mctx->nsub_tops = 0;
+ mctx->nbkref_ents = 0;
+}
+
+/* Free all the memory associated with MCTX. */
+
+static void
+match_ctx_free (re_match_context_t *mctx)
+{
+ /* First, free all the memory associated with MCTX->SUB_TOPS. */
+ match_ctx_clean (mctx);
+ re_free (mctx->sub_tops);
+ re_free (mctx->bkref_ents);
+}
+
+/* Add a new backreference entry to MCTX.
+ Note that we assume that caller never call this function with duplicate
+ entry, and call with STR_IDX which isn't smaller than any existing entry.
+*/
+
+static reg_errcode_t
+__attribute_warn_unused_result__
+match_ctx_add_entry (re_match_context_t *mctx, Idx node, Idx str_idx, Idx from,
+ Idx to)
+{
+ if (mctx->nbkref_ents >= mctx->abkref_ents)
+ {
+ struct re_backref_cache_entry* new_entry;
+ new_entry = re_realloc (mctx->bkref_ents, struct re_backref_cache_entry,
+ mctx->abkref_ents * 2);
+ if (__glibc_unlikely (new_entry == NULL))
+ {
+ re_free (mctx->bkref_ents);
+ return REG_ESPACE;
+ }
+ mctx->bkref_ents = new_entry;
+ memset (mctx->bkref_ents + mctx->nbkref_ents, '\0',
+ sizeof (struct re_backref_cache_entry) * mctx->abkref_ents);
+ mctx->abkref_ents *= 2;
+ }
+ if (mctx->nbkref_ents > 0
+ && mctx->bkref_ents[mctx->nbkref_ents - 1].str_idx == str_idx)
+ mctx->bkref_ents[mctx->nbkref_ents - 1].more = 1;
+
+ mctx->bkref_ents[mctx->nbkref_ents].node = node;
+ mctx->bkref_ents[mctx->nbkref_ents].str_idx = str_idx;
+ mctx->bkref_ents[mctx->nbkref_ents].subexp_from = from;
+ mctx->bkref_ents[mctx->nbkref_ents].subexp_to = to;
+
+ /* This is a cache that saves negative results of check_dst_limits_calc_pos.
+ If bit N is clear, means that this entry won't epsilon-transition to
+ an OP_OPEN_SUBEXP or OP_CLOSE_SUBEXP for the N+1-th subexpression. If
+ it is set, check_dst_limits_calc_pos_1 will recurse and try to find one
+ such node.
+
+ A backreference does not epsilon-transition unless it is empty, so set
+ to all zeros if FROM != TO. */
+ mctx->bkref_ents[mctx->nbkref_ents].eps_reachable_subexps_map
+ = (from == to ? -1 : 0);
+
+ mctx->bkref_ents[mctx->nbkref_ents++].more = 0;
+ if (mctx->max_mb_elem_len < to - from)
+ mctx->max_mb_elem_len = to - from;
+ return REG_NOERROR;
+}
+
+/* Return the first entry with the same str_idx, or -1 if none is
+ found. Note that MCTX->BKREF_ENTS is already sorted by MCTX->STR_IDX. */
+
+static Idx
+search_cur_bkref_entry (const re_match_context_t *mctx, Idx str_idx)
+{
+ Idx left, right, mid, last;
+ last = right = mctx->nbkref_ents;
+ for (left = 0; left < right;)
+ {
+ mid = (left + right) / 2;
+ if (mctx->bkref_ents[mid].str_idx < str_idx)
+ left = mid + 1;
+ else
+ right = mid;
+ }
+ if (left < last && mctx->bkref_ents[left].str_idx == str_idx)
+ return left;
+ else
+ return -1;
+}
+
+/* Register the node NODE, whose type is OP_OPEN_SUBEXP, and which matches
+ at STR_IDX. */
+
+static reg_errcode_t
+__attribute_warn_unused_result__
+match_ctx_add_subtop (re_match_context_t *mctx, Idx node, Idx str_idx)
+{
+ 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;
+ re_sub_match_top_t **new_array = re_realloc (mctx->sub_tops,
+ re_sub_match_top_t *,
+ new_asub_tops);
+ if (__glibc_unlikely (new_array == NULL))
+ return REG_ESPACE;
+ mctx->sub_tops = new_array;
+ mctx->asub_tops = new_asub_tops;
+ }
+ mctx->sub_tops[mctx->nsub_tops] = calloc (1, sizeof (re_sub_match_top_t));
+ if (__glibc_unlikely (mctx->sub_tops[mctx->nsub_tops] == NULL))
+ return REG_ESPACE;
+ mctx->sub_tops[mctx->nsub_tops]->node = node;
+ mctx->sub_tops[mctx->nsub_tops++]->str_idx = str_idx;
+ return REG_NOERROR;
+}
+
+/* Register the node NODE, whose type is OP_CLOSE_SUBEXP, and which matches
+ at STR_IDX, whose corresponding OP_OPEN_SUBEXP is SUB_TOP.
+ Return the new entry if successful, NULL if memory is exhausted. */
+
+static re_sub_match_last_t *
+match_ctx_add_sublast (re_sub_match_top_t *subtop, Idx node, Idx str_idx)
+{
+ re_sub_match_last_t *new_entry;
+ if (__glibc_unlikely (subtop->nlasts == subtop->alasts))
+ {
+ Idx new_alasts = 2 * subtop->alasts + 1;
+ re_sub_match_last_t **new_array = re_realloc (subtop->lasts,
+ re_sub_match_last_t *,
+ new_alasts);
+ if (__glibc_unlikely (new_array == NULL))
+ return NULL;
+ subtop->lasts = new_array;
+ subtop->alasts = new_alasts;
+ }
+ new_entry = calloc (1, sizeof (re_sub_match_last_t));
+ if (__glibc_likely (new_entry != NULL))
+ {
+ subtop->lasts[subtop->nlasts] = new_entry;
+ new_entry->node = node;
+ new_entry->str_idx = str_idx;
+ ++subtop->nlasts;
+ }
+ return new_entry;
+}
+
+static void
+sift_ctx_init (re_sift_context_t *sctx, re_dfastate_t **sifted_sts,
+ re_dfastate_t **limited_sts, Idx last_node, Idx last_str_idx)
+{
+ sctx->sifted_states = sifted_sts;
+ sctx->limited_states = limited_sts;
+ sctx->last_node = last_node;
+ sctx->last_str_idx = last_str_idx;
+ re_node_set_init_empty (&sctx->limits);
+}
diff --git a/lib/root-uid.h b/lib/root-uid.h
index 4aa9dfe24f0..b3274e39aaa 100644
--- a/lib/root-uid.h
+++ b/lib/root-uid.h
@@ -1,21 +1,21 @@
/* The user ID that always has appropriate privileges in the POSIX sense.
- Copyright 2012-2017 Free Software Foundation, Inc.
+ Copyright 2012-2022 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 file is free software: you can redistribute it and/or modify
+ it under the terms of the GNU Lesser General Public License as
+ published by the Free Software Foundation; either version 2.1 of the
+ License, or (at your option) any later version.
- This program is distributed in the hope that it will be useful,
+ This file 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.
+ GNU Lesser General Public License for more details.
- You should have received a copy of the GNU General Public License
- along with this program. If not, see <https://www.gnu.org/licenses/>.
+ You should have received a copy of the GNU Lesser General Public License
+ along with this program. If not, see <https://www.gnu.org/licenses/>. */
- Written by Paul Eggert. */
+/* Written by Paul Eggert. */
#ifndef ROOT_UID_H_
#define ROOT_UID_H_
diff --git a/lib/save-cwd.c b/lib/save-cwd.c
index fbd944bb722..ecaef8974a0 100644
--- a/lib/save-cwd.c
+++ b/lib/save-cwd.c
@@ -1,6 +1,6 @@
/* save-cwd.c -- Save and restore current working directory.
- Copyright (C) 1995, 1997-1998, 2003-2006, 2009-2017 Free Software
+ Copyright (C) 1995, 1997-1998, 2003-2006, 2009-2022 Free Software
Foundation, Inc.
This program is free software: you can redistribute it and/or modify
diff --git a/lib/save-cwd.h b/lib/save-cwd.h
index 577bc35dc07..90e8a0747ce 100644
--- a/lib/save-cwd.h
+++ b/lib/save-cwd.h
@@ -1,11 +1,11 @@
/* Save and restore current working directory.
- Copyright (C) 1995, 1997-1998, 2003, 2009-2017 Free Software
- Foundation, Inc.
+ Copyright (C) 1995, 1997-1998, 2003, 2009-2022 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
+ 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,
diff --git a/lib/scratch_buffer.h b/lib/scratch_buffer.h
new file mode 100644
index 00000000000..f4fe5e8d344
--- /dev/null
+++ b/lib/scratch_buffer.h
@@ -0,0 +1,127 @@
+/* Variable-sized buffer with on-stack default allocation.
+ Copyright (C) 2017-2022 Free Software Foundation, Inc.
+
+ This file is free software: you can redistribute it and/or modify
+ it under the terms of the GNU Lesser General Public License as
+ published by the Free Software Foundation; either version 2.1 of the
+ License, or (at your option) any later version.
+
+ This file 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 Lesser General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public License
+ along with this program. If not, see <https://www.gnu.org/licenses/>. */
+
+/* Written by Paul Eggert, 2017. */
+
+#ifndef _GL_SCRATCH_BUFFER_H
+#define _GL_SCRATCH_BUFFER_H
+
+/* Scratch buffers with a default stack allocation and fallback to
+ heap allocation. It is expected that this function is used in this
+ way:
+
+ struct scratch_buffer tmpbuf;
+ scratch_buffer_init (&tmpbuf);
+
+ while (!function_that_uses_buffer (tmpbuf.data, tmpbuf.length))
+ if (!scratch_buffer_grow (&tmpbuf))
+ return -1;
+
+ scratch_buffer_free (&tmpbuf);
+ return 0;
+
+ The allocation functions (scratch_buffer_grow,
+ scratch_buffer_grow_preserve, scratch_buffer_set_array_size) make
+ sure that the heap allocation, if any, is freed, so that the code
+ above does not have a memory leak. The buffer still remains in a
+ state that can be deallocated using scratch_buffer_free, so a loop
+ like this is valid as well:
+
+ struct scratch_buffer tmpbuf;
+ scratch_buffer_init (&tmpbuf);
+
+ while (!function_that_uses_buffer (tmpbuf.data, tmpbuf.length))
+ if (!scratch_buffer_grow (&tmpbuf))
+ break;
+
+ scratch_buffer_free (&tmpbuf);
+
+ scratch_buffer_grow and scratch_buffer_grow_preserve are guaranteed
+ to grow the buffer by at least 512 bytes. This means that when
+ using the scratch buffer as a backing store for a non-character
+ array whose element size, in bytes, is 512 or smaller, the scratch
+ buffer only has to grow once to make room for at least one more
+ element.
+*/
+
+/* Scratch buffer. Must be initialized with scratch_buffer_init
+ before its use. */
+struct scratch_buffer;
+
+/* Initializes *BUFFER so that BUFFER->data points to BUFFER->__space
+ and BUFFER->length reflects the available space. */
+#if 0
+extern void scratch_buffer_init (struct scratch_buffer *buffer);
+#endif
+
+/* Deallocates *BUFFER (if it was heap-allocated). */
+#if 0
+extern void scratch_buffer_free (struct scratch_buffer *buffer);
+#endif
+
+/* Grow *BUFFER by some arbitrary amount. The buffer contents is NOT
+ preserved. Return true on success, false on allocation failure (in
+ which case the old buffer is freed). On success, the new buffer is
+ larger than the previous size. On failure, *BUFFER is deallocated,
+ but remains in a free-able state, and errno is set. */
+#if 0
+extern bool scratch_buffer_grow (struct scratch_buffer *buffer);
+#endif
+
+/* Like scratch_buffer_grow, but preserve the old buffer
+ contents on success, as a prefix of the new buffer. */
+#if 0
+extern bool scratch_buffer_grow_preserve (struct scratch_buffer *buffer);
+#endif
+
+/* Grow *BUFFER so that it can store at least NELEM elements of SIZE
+ bytes. The buffer contents are NOT preserved. Both NELEM and SIZE
+ can be zero. Return true on success, false on allocation failure
+ (in which case the old buffer is freed, but *BUFFER remains in a
+ free-able state, and errno is set). It is unspecified whether this
+ function can reduce the array size. */
+#if 0
+extern bool scratch_buffer_set_array_size (struct scratch_buffer *buffer,
+ size_t nelem, size_t size);
+#endif
+
+/* Return a copy of *BUFFER's first SIZE bytes as a heap-allocated block,
+ deallocating *BUFFER if it was heap-allocated. SIZE must be at
+ most *BUFFER's size. Return NULL (setting errno) on memory
+ exhaustion. */
+#if 0
+extern void *scratch_buffer_dupfree (struct scratch_buffer *buffer,
+ size_t size);
+#endif
+
+
+/* The implementation is imported from glibc. */
+
+/* Avoid possible conflicts with symbols exported by the GNU libc. */
+#define __libc_scratch_buffer_dupfree gl_scratch_buffer_dupfree
+#define __libc_scratch_buffer_grow gl_scratch_buffer_grow
+#define __libc_scratch_buffer_grow_preserve gl_scratch_buffer_grow_preserve
+#define __libc_scratch_buffer_set_array_size gl_scratch_buffer_set_array_size
+
+#ifndef _GL_LIKELY
+/* Rely on __builtin_expect, as provided by the module 'builtin-expect'. */
+# define _GL_LIKELY(cond) __builtin_expect ((cond), 1)
+# define _GL_UNLIKELY(cond) __builtin_expect ((cond), 0)
+#endif
+
+#include <malloc/scratch_buffer.gl.h>
+
+#endif /* _GL_SCRATCH_BUFFER_H */
diff --git a/lib/set-permissions.c b/lib/set-permissions.c
index b30841fca40..c1a4b82a0d0 100644
--- a/lib/set-permissions.c
+++ b/lib/set-permissions.c
@@ -1,10 +1,10 @@
/* Set permissions of a file. -*- coding: utf-8 -*-
- Copyright (C) 2002-2003, 2005-2017 Free Software Foundation, Inc.
+ Copyright (C) 2002-2003, 2005-2022 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
+ 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,
@@ -24,7 +24,7 @@
#include "acl-internal.h"
#if USE_ACL
-# if ! defined HAVE_ACL_FROM_MODE && defined HAVE_ACL_FROM_TEXT /* FreeBSD, IRIX, Tru64 */
+# if ! defined HAVE_ACL_FROM_MODE && defined HAVE_ACL_FROM_TEXT /* FreeBSD, IRIX, Tru64, Cygwin >= 2.5 */
# if HAVE_ACL_GET_FILE && !HAVE_ACL_TYPE_EXTENDED
static acl_t
@@ -32,7 +32,7 @@ acl_from_mode (mode_t mode)
{
# if HAVE_ACL_FREE_TEXT /* Tru64 */
char acl_text[] = "u::---,g::---,o::---,";
-# else /* FreeBSD, IRIX */
+# else /* FreeBSD, IRIX, Cygwin >= 2.5 */
char acl_text[] = "u::---,g::---,o::---";
# endif
@@ -51,7 +51,7 @@ acl_from_mode (mode_t mode)
# endif
# endif
-# if HAVE_FACL && defined GETACL /* Solaris, Cygwin, not HP-UX */
+# if HAVE_FACL && defined GETACL /* Solaris, Cygwin < 2.5, not HP-UX */
static int
set_acls_from_mode (const char *name, int desc, mode_t mode, bool *must_chmod)
{
@@ -229,14 +229,14 @@ set_acls_from_mode (const char *name, int desc, mode_t mode, bool *must_chmod)
if (ret < 0 && errno != EINVAL && errno != ENOTSUP)
{
if (errno == ENOSYS)
- {
- *must_chmod = true;
- return 0;
- }
+ {
+ *must_chmod = true;
+ return 0;
+ }
return -1;
}
if (ret == 0)
- return 0;
+ return 0;
}
# endif
@@ -256,18 +256,18 @@ set_acls_from_mode (const char *name, int desc, mode_t mode, bool *must_chmod)
if (desc != -1)
ret = facl (desc, SETACL,
- sizeof (entries) / sizeof (aclent_t), entries);
+ sizeof (entries) / sizeof (aclent_t), entries);
else
ret = acl (name, SETACL,
- sizeof (entries) / sizeof (aclent_t), entries);
+ sizeof (entries) / sizeof (aclent_t), entries);
if (ret < 0)
{
- if (errno == ENOSYS || errno == EOPNOTSUPP)
- {
- *must_chmod = true;
- return 0;
- }
- return -1;
+ if (errno == ENOSYS || errno == EOPNOTSUPP)
+ {
+ *must_chmod = true;
+ return 0;
+ }
+ return -1;
}
return 0;
}
@@ -483,15 +483,15 @@ context_acl_from_mode (struct permission_context *ctx)
static int
set_acls (struct permission_context *ctx, const char *name, int desc,
- int from_mode, bool *must_chmod, bool *acls_set)
+ int from_mode, bool *must_chmod, bool *acls_set)
{
int ret = 0;
# if HAVE_ACL_GET_FILE
/* POSIX 1003.1e (draft 17 -- abandoned) specific version. */
- /* Linux, FreeBSD, Mac OS X, IRIX, Tru64 */
+ /* Linux, FreeBSD, Mac OS X, IRIX, Tru64, Cygwin >= 2.5 */
# if !HAVE_ACL_TYPE_EXTENDED
- /* Linux, FreeBSD, IRIX, Tru64 */
+ /* Linux, FreeBSD, IRIX, Tru64, Cygwin >= 2.5 */
# ifndef HAVE_ACL_FROM_TEXT
# error Must have acl_from_text (see POSIX 1003.1e draft 17).
@@ -503,53 +503,53 @@ set_acls (struct permission_context *ctx, const char *name, int desc,
if (! ctx->acls_not_supported)
{
if (ret == 0 && from_mode)
- {
- if (ctx->acl)
- acl_free (ctx->acl);
- ctx->acl = acl_from_mode (ctx->mode);
- if (ctx->acl == NULL)
- ret = -1;
- }
+ {
+ if (ctx->acl)
+ acl_free (ctx->acl);
+ ctx->acl = acl_from_mode (ctx->mode);
+ if (ctx->acl == NULL)
+ ret = -1;
+ }
if (ret == 0 && ctx->acl)
- {
- if (HAVE_ACL_SET_FD && desc != -1)
- ret = acl_set_fd (desc, ctx->acl);
- else
- ret = acl_set_file (name, ACL_TYPE_ACCESS, ctx->acl);
- if (ret != 0)
- {
- if (! acl_errno_valid (errno))
- {
- ctx->acls_not_supported = true;
- if (from_mode || acl_access_nontrivial (ctx->acl) == 0)
- ret = 0;
- }
- }
- else
- {
- *acls_set = true;
- if (S_ISDIR(ctx->mode))
- {
- if (! from_mode && ctx->default_acl &&
- acl_default_nontrivial (ctx->default_acl))
- ret = acl_set_file (name, ACL_TYPE_DEFAULT,
- ctx->default_acl);
- else
- ret = acl_delete_def_file (name);
- }
- }
- }
+ {
+ if (HAVE_ACL_SET_FD && desc != -1)
+ ret = acl_set_fd (desc, ctx->acl);
+ else
+ ret = acl_set_file (name, ACL_TYPE_ACCESS, ctx->acl);
+ if (ret != 0)
+ {
+ if (! acl_errno_valid (errno))
+ {
+ ctx->acls_not_supported = true;
+ if (from_mode || acl_access_nontrivial (ctx->acl) == 0)
+ ret = 0;
+ }
+ }
+ else
+ {
+ *acls_set = true;
+ if (S_ISDIR(ctx->mode))
+ {
+ if (! from_mode && ctx->default_acl &&
+ acl_default_nontrivial (ctx->default_acl))
+ ret = acl_set_file (name, ACL_TYPE_DEFAULT,
+ ctx->default_acl);
+ else
+ ret = acl_delete_def_file (name);
+ }
+ }
+ }
}
-# if HAVE_ACL_TYPE_NFS4 /* FreeBSD */
+# if HAVE_ACL_TYPE_NFS4 /* FreeBSD */
/* File systems either support POSIX ACLs (for example, ufs) or NFS4 ACLs
(for example, zfs). */
/* TODO: Implement setting ACLs once get_permissions() reads them. */
-# endif
+# endif
# else /* HAVE_ACL_TYPE_EXTENDED */
/* Mac OS X */
@@ -573,38 +573,38 @@ set_acls (struct permission_context *ctx, const char *name, int desc,
/* Remove ACLs if the file has ACLs. */
if (HAVE_ACL_GET_FD && desc != -1)
- acl = acl_get_fd (desc);
+ acl = acl_get_fd (desc);
else
- acl = acl_get_file (name, ACL_TYPE_EXTENDED);
+ acl = acl_get_file (name, ACL_TYPE_EXTENDED);
if (acl)
- {
- acl_free (acl);
-
- acl = acl_init (0);
- if (acl)
- {
- if (HAVE_ACL_SET_FD && desc != -1)
- ret = acl_set_fd (desc, acl);
- else
- ret = acl_set_file (name, ACL_TYPE_EXTENDED, acl);
- acl_free (acl);
- }
- else
- ret = -1;
- }
+ {
+ acl_free (acl);
+
+ acl = acl_init (0);
+ if (acl)
+ {
+ if (HAVE_ACL_SET_FD && desc != -1)
+ ret = acl_set_fd (desc, acl);
+ else
+ ret = acl_set_file (name, ACL_TYPE_EXTENDED, acl);
+ acl_free (acl);
+ }
+ else
+ ret = -1;
+ }
}
else
{
if (HAVE_ACL_SET_FD && desc != -1)
- ret = acl_set_fd (desc, ctx->acl);
+ ret = acl_set_fd (desc, ctx->acl);
else
- ret = acl_set_file (name, ACL_TYPE_EXTENDED, ctx->acl);
+ ret = acl_set_file (name, ACL_TYPE_EXTENDED, ctx->acl);
if (ret != 0)
- {
- if (! acl_errno_valid (errno)
- && ! acl_extended_nontrivial (ctx->acl))
- ret = 0;
- }
+ {
+ if (! acl_errno_valid (errno)
+ && ! acl_extended_nontrivial (ctx->acl))
+ ret = 0;
+ }
}
*acls_set = true;
@@ -626,34 +626,34 @@ set_acls (struct permission_context *ctx, const char *name, int desc,
if (ret == 0 && ctx->count)
{
if (desc != -1)
- ret = facl (desc, SETACL, ctx->count, ctx->entries);
+ ret = facl (desc, SETACL, ctx->count, ctx->entries);
else
- ret = acl (name, SETACL, ctx->count, ctx->entries);
+ ret = acl (name, SETACL, ctx->count, ctx->entries);
if (ret < 0)
- {
- if ((errno == ENOSYS || errno == EOPNOTSUPP || errno == EINVAL)
- && acl_nontrivial (ctx->count, ctx->entries) == 0)
- ret = 0;
- }
+ {
+ if ((errno == ENOSYS || errno == EOPNOTSUPP || errno == EINVAL)
+ && acl_nontrivial (ctx->count, ctx->entries) == 0)
+ ret = 0;
+ }
else
- *acls_set = true;
+ *acls_set = true;
}
# ifdef ACE_GETACL
if (ret == 0 && ctx->ace_count)
{
if (desc != -1)
- ret = facl (desc, ACE_SETACL, ctx->ace_count, ctx->ace_entries);
+ ret = facl (desc, ACE_SETACL, ctx->ace_count, ctx->ace_entries);
else
- ret = acl (name, ACE_SETACL, ctx->ace_count, ctx->ace_entries);
+ ret = acl (name, ACE_SETACL, ctx->ace_count, ctx->ace_entries);
if (ret < 0)
- {
- if ((errno == ENOSYS || errno == EINVAL || errno == ENOTSUP)
- && acl_ace_nontrivial (ctx->ace_count, ctx->ace_entries) == 0)
- ret = 0;
- }
+ {
+ if ((errno == ENOSYS || errno == EINVAL || errno == ENOTSUP)
+ && acl_ace_nontrivial (ctx->ace_count, ctx->ace_entries) == 0)
+ ret = 0;
+ }
else
- *acls_set = true;
+ *acls_set = true;
}
# endif
@@ -665,17 +665,17 @@ set_acls (struct permission_context *ctx, const char *name, int desc,
if (ret == 0 && ctx->count > 0)
{
if (desc != -1)
- ret = fsetacl (desc, ctx->count, ctx->entries);
+ ret = fsetacl (desc, ctx->count, ctx->entries);
else
- ret = setacl (name, ctx->count, ctx->entries);
+ ret = setacl (name, ctx->count, ctx->entries);
if (ret < 0)
- {
- if ((errno == ENOSYS || errno == EOPNOTSUPP || errno == ENOTSUP)
- && (from_mode || !acl_nontrivial (ctx->count, ctx->entries)))
- ret = 0;
- }
+ {
+ if ((errno == ENOSYS || errno == EOPNOTSUPP || errno == ENOTSUP)
+ && (from_mode || !acl_nontrivial (ctx->count, ctx->entries)))
+ ret = 0;
+ }
else
- *acls_set = true;
+ *acls_set = true;
}
# if HAVE_ACLV_H
@@ -686,13 +686,13 @@ set_acls (struct permission_context *ctx, const char *name, int desc,
{
ret = acl ((char *) name, ACL_SET, ctx->aclv_count, ctx->aclv_entries);
if (ret < 0)
- {
- if ((errno == ENOSYS || errno == EOPNOTSUPP || errno == EINVAL)
- && (from_mode || !aclv_nontrivial (ctx->aclv_count, ctx->aclv_entries)))
- ret = 0;
- }
+ {
+ if ((errno == ENOSYS || errno == EOPNOTSUPP || errno == EINVAL)
+ && (from_mode || !aclv_nontrivial (ctx->aclv_count, ctx->aclv_entries)))
+ ret = 0;
+ }
else
- *acls_set = true;
+ *acls_set = true;
}
# endif
@@ -711,16 +711,16 @@ set_acls (struct permission_context *ctx, const char *name, int desc,
if (ret == 0 && ctx->have_u)
{
if (desc != -1)
- ret = fchacl (desc, &ctx->u.a, ctx->u.a.acl_len);
+ ret = fchacl (desc, &ctx->u.a, ctx->u.a.acl_len);
else
- ret = chacl ((char *) name, &ctx->u.a, ctx->u.a.acl_len);
+ ret = chacl ((char *) name, &ctx->u.a, ctx->u.a.acl_len);
if (ret < 0)
- {
- if (errno == ENOSYS && from_mode)
- ret = 0;
- }
+ {
+ if (errno == ENOSYS && from_mode)
+ ret = 0;
+ }
else
- *acls_set = true;
+ *acls_set = true;
}
# elif HAVE_ACLSORT /* NonStop Kernel */
@@ -732,12 +732,12 @@ set_acls (struct permission_context *ctx, const char *name, int desc,
{
ret = acl ((char *) name, ACL_SET, ctx->count, ctx->entries);
if (ret != 0)
- {
- if (!acl_nontrivial (ctx->count, ctx->entries))
- ret = 0;
- }
+ {
+ if (!acl_nontrivial (ctx->count, ctx->entries))
+ ret = 0;
+ }
else
- *acls_set = true;
+ *acls_set = true;
}
# else /* No ACLs */
@@ -775,7 +775,7 @@ chmod_or_fchmod (const char *name, int desc, mode_t mode)
int
set_permissions (struct permission_context *ctx, const char *name, int desc)
{
- bool acls_set _GL_UNUSED = false;
+ _GL_UNUSED bool acls_set = false;
bool early_chmod;
bool must_chmod = false;
int ret = 0;
@@ -805,7 +805,7 @@ set_permissions (struct permission_context *ctx, const char *name, int desc)
{
ret = chmod_or_fchmod (name, desc, ctx->mode);
if (ret != 0)
- return -1;
+ return -1;
}
#if USE_ACL
@@ -815,18 +815,18 @@ set_permissions (struct permission_context *ctx, const char *name, int desc)
int saved_errno = ret ? errno : 0;
/* If we can't set an acl which we expect to be able to set, try setting
- the permissions to ctx->mode. Due to possible inherited permissions,
- we cannot simply chmod. */
+ the permissions to ctx->mode. Due to possible inherited permissions,
+ we cannot simply chmod. */
ret = set_acls (ctx, name, desc, true, &must_chmod, &acls_set);
if (! acls_set)
- must_chmod = true;
+ must_chmod = true;
if (saved_errno)
- {
- errno = saved_errno;
- ret = -1;
- }
+ {
+ errno = saved_errno;
+ ret = -1;
+ }
}
#endif
@@ -837,10 +837,10 @@ set_permissions (struct permission_context *ctx, const char *name, int desc)
ret = chmod_or_fchmod (name, desc, ctx->mode);
if (saved_errno)
- {
- errno = saved_errno;
- ret = -1;
- }
+ {
+ errno = saved_errno;
+ ret = -1;
+ }
}
return ret;
diff --git a/lib/sha1.c b/lib/sha1.c
index ca3eabc45e7..79e50ba0b03 100644
--- a/lib/sha1.c
+++ b/lib/sha1.c
@@ -1,20 +1,20 @@
/* sha1.c - Functions to compute SHA1 message digest of files or
memory blocks according to the NIST specification FIPS-180-1.
- Copyright (C) 2000-2001, 2003-2006, 2008-2017 Free Software Foundation, Inc.
+ Copyright (C) 2000-2001, 2003-2006, 2008-2022 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 file is free software: you can redistribute it and/or modify
+ it under the terms of the GNU Lesser General Public License as
+ published by the Free Software Foundation; either version 2.1 of the
+ License, or (at your option) any later version.
- This program is distributed in the hope that it will be useful,
+ This file 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.
+ GNU Lesser General Public License for more details.
- You should have received a copy of the GNU General Public License
- along with this program; if not, see <https://www.gnu.org/licenses/>. */
+ You should have received a copy of the GNU Lesser General Public License
+ along with this program. If not, see <https://www.gnu.org/licenses/>. */
/* Written by Scott G. Miller
Credits:
@@ -23,6 +23,7 @@
#include <config.h>
+/* Specification. */
#if HAVE_OPENSSL_SHA1
# define GL_OPENSSL_INLINE _GL_EXTERN_INLINE
#endif
@@ -30,26 +31,17 @@
#include <stdalign.h>
#include <stdint.h>
-#include <stdlib.h>
#include <string.h>
-#if USE_UNLOCKED_IO
-# include "unlocked-io.h"
-#endif
-
+#include <byteswap.h>
#ifdef WORDS_BIGENDIAN
# define SWAP(n) (n)
#else
-# define SWAP(n) \
- (((n) << 24) | (((n) & 0xff00) << 8) | (((n) >> 8) & 0xff00) | ((n) >> 24))
-#endif
-
-#define BLOCKSIZE 32768
-#if BLOCKSIZE % 64 != 0
-# error "invalid BLOCKSIZE"
+# define SWAP(n) bswap_32 (n)
#endif
#if ! HAVE_OPENSSL_SHA1
+
/* This array contains the bytes used to pad the buffer to the next
64-byte boundary. (RFC 1321, 3.1: Step 1) */
static const unsigned char fillbuf[64] = { 0x80, 0 /* , 0, 0, ... */ };
@@ -120,82 +112,7 @@ sha1_finish_ctx (struct sha1_ctx *ctx, void *resbuf)
return sha1_read_ctx (ctx, resbuf);
}
-#endif
-
-/* Compute SHA1 message digest for bytes read from STREAM. The
- resulting message digest number will be written into the 16 bytes
- beginning at RESBLOCK. */
-int
-sha1_stream (FILE *stream, void *resblock)
-{
- struct sha1_ctx ctx;
- size_t sum;
-
- char *buffer = malloc (BLOCKSIZE + 72);
- if (!buffer)
- return 1;
-
- /* Initialize the computation context. */
- sha1_init_ctx (&ctx);
-
- /* Iterate over full file contents. */
- while (1)
- {
- /* We read the file in blocks of BLOCKSIZE bytes. One call of the
- computation function processes the whole buffer so that with the
- next round of the loop another block can be read. */
- size_t n;
- sum = 0;
-
- /* Read block. Take care for partial reads. */
- while (1)
- {
- n = fread (buffer + sum, 1, BLOCKSIZE - sum, stream);
-
- sum += n;
-
- if (sum == BLOCKSIZE)
- break;
-
- if (n == 0)
- {
- /* Check for the error flag IFF N == 0, so that we don't
- exit the loop after a partial read due to e.g., EAGAIN
- or EWOULDBLOCK. */
- if (ferror (stream))
- {
- free (buffer);
- return 1;
- }
- goto process_partial_block;
- }
-
- /* We've read at least one byte, so ignore errors. But always
- check for EOF, since feof may be true even though N > 0.
- Otherwise, we could end up calling fread after EOF. */
- if (feof (stream))
- goto process_partial_block;
- }
-
- /* Process buffer with BLOCKSIZE bytes. Note that
- BLOCKSIZE % 64 == 0
- */
- sha1_process_block (buffer, BLOCKSIZE, &ctx);
- }
-
- process_partial_block:;
-
- /* Process any remaining bytes. */
- if (sum > 0)
- sha1_process_bytes (buffer, sum, &ctx);
-
- /* Construct result in desired memory. */
- sha1_finish_ctx (&ctx, resblock);
- free (buffer);
- return 0;
-}
-#if ! HAVE_OPENSSL_SHA1
/* Compute SHA1 message digest for LEN bytes beginning at BUFFER. The
result is always in little endian byte order, so that a byte-wise
output yields to the wanted ASCII representation of the message
@@ -433,4 +350,12 @@ sha1_process_block (const void *buffer, size_t len, struct sha1_ctx *ctx)
e = ctx->E += e;
}
}
+
#endif
+
+/*
+ * Hey Emacs!
+ * Local Variables:
+ * coding: utf-8
+ * End:
+ */
diff --git a/lib/sha1.h b/lib/sha1.h
index dd48889fa4c..bc3470a508d 100644
--- a/lib/sha1.h
+++ b/lib/sha1.h
@@ -1,20 +1,20 @@
/* Declarations of functions and data types used for SHA1 sum
library functions.
- Copyright (C) 2000-2001, 2003, 2005-2006, 2008-2017 Free Software
+ Copyright (C) 2000-2001, 2003, 2005-2006, 2008-2022 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 file is free software: you can redistribute it and/or modify
+ it under the terms of the GNU Lesser General Public License as
+ published by the Free Software Foundation; either version 2.1 of the
+ License, or (at your option) any later version.
- This program is distributed in the hope that it will be useful,
+ This file 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.
+ GNU Lesser General Public License for more details.
- You should have received a copy of the GNU General Public License
- along with this program; if not, see <https://www.gnu.org/licenses/>. */
+ You should have received a copy of the GNU Lesser General Public License
+ along with this program. If not, see <https://www.gnu.org/licenses/>. */
#ifndef SHA1_H
# define SHA1_H 1
@@ -23,6 +23,9 @@
# include <stdint.h>
# if HAVE_OPENSSL_SHA1
+# ifndef OPENSSL_API_COMPAT
+# define OPENSSL_API_COMPAT 0x10101000L /* FIXME: Use OpenSSL 1.1+ API. */
+# endif
# include <openssl/sha.h>
# endif
@@ -30,7 +33,7 @@
extern "C" {
# endif
-#define SHA1_DIGEST_SIZE 20
+# define SHA1_DIGEST_SIZE 20
# if HAVE_OPENSSL_SHA1
# define GL_OPENSSL_NAME 1
@@ -71,24 +74,29 @@ extern void sha1_process_bytes (const void *buffer, size_t len,
in first 20 bytes following RESBUF. The result is always in little
endian byte order, so that a byte-wise output yields to the wanted
ASCII representation of the message digest. */
-extern void *sha1_finish_ctx (struct sha1_ctx *ctx, void *resbuf);
+extern void *sha1_finish_ctx (struct sha1_ctx *ctx, void *restrict resbuf);
/* Put result from CTX in first 20 bytes following RESBUF. The result is
always in little endian byte order, so that a byte-wise output yields
to the wanted ASCII representation of the message digest. */
-extern void *sha1_read_ctx (const struct sha1_ctx *ctx, void *resbuf);
+extern void *sha1_read_ctx (const struct sha1_ctx *ctx, void *restrict resbuf);
/* Compute SHA1 message digest for LEN bytes beginning at BUFFER. The
result is always in little endian byte order, so that a byte-wise
output yields to the wanted ASCII representation of the message
digest. */
-extern void *sha1_buffer (const char *buffer, size_t len, void *resblock);
+extern void *sha1_buffer (const char *buffer, size_t len,
+ void *restrict resblock);
# endif
-/* Compute SHA1 message digest for bytes read from STREAM. The
- resulting message digest number will be written into the 20 bytes
+
+/* Compute SHA1 message digest for bytes read from STREAM.
+ STREAM is an open file stream. Regular files are handled more efficiently.
+ The contents of STREAM from its current position to its end will be read.
+ The case that the last operation on STREAM was an 'ungetc' is not supported.
+ The resulting message digest number will be written into the 20 bytes
beginning at RESBLOCK. */
extern int sha1_stream (FILE *stream, void *resblock);
@@ -98,3 +106,10 @@ extern int sha1_stream (FILE *stream, void *resblock);
# endif
#endif
+
+/*
+ * Hey Emacs!
+ * Local Variables:
+ * coding: utf-8
+ * End:
+ */
diff --git a/lib/sha256.c b/lib/sha256.c
index 449a9b7b712..c9ca618c67e 100644
--- a/lib/sha256.c
+++ b/lib/sha256.c
@@ -1,19 +1,19 @@
/* sha256.c - Functions to compute SHA256 and SHA224 message digest of files or
memory blocks according to the NIST specification FIPS-180-2.
- Copyright (C) 2005-2006, 2008-2017 Free Software Foundation, Inc.
+ Copyright (C) 2005-2006, 2008-2022 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 file is free software: you can redistribute it and/or modify
+ it under the terms of the GNU Lesser General Public License as
+ published by the Free Software Foundation; either version 2.1 of the
+ License, or (at your option) any later version.
- This program is distributed in the hope that it will be useful,
+ This file 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.
+ GNU Lesser General Public License for more details.
- You should have received a copy of the GNU General Public License
+ You should have received a copy of the GNU Lesser General Public License
along with this program. If not, see <https://www.gnu.org/licenses/>. */
/* Written by David Madore, considerably copypasting from
@@ -22,6 +22,7 @@
#include <config.h>
+/* Specification. */
#if HAVE_OPENSSL_SHA256
# define GL_OPENSSL_INLINE _GL_EXTERN_INLINE
#endif
@@ -29,26 +30,17 @@
#include <stdalign.h>
#include <stdint.h>
-#include <stdlib.h>
#include <string.h>
-#if USE_UNLOCKED_IO
-# include "unlocked-io.h"
-#endif
-
+#include <byteswap.h>
#ifdef WORDS_BIGENDIAN
# define SWAP(n) (n)
#else
-# define SWAP(n) \
- (((n) << 24) | (((n) & 0xff00) << 8) | (((n) >> 8) & 0xff00) | ((n) >> 24))
-#endif
-
-#define BLOCKSIZE 32768
-#if BLOCKSIZE % 64 != 0
-# error "invalid BLOCKSIZE"
+# define SWAP(n) bswap_32 (n)
#endif
#if ! HAVE_OPENSSL_SHA256
+
/* This array contains the bytes used to pad the buffer to the next
64-byte boundary. */
static const unsigned char fillbuf[64] = { 0x80, 0 /* , 0, 0, ... */ };
@@ -91,17 +83,17 @@ sha224_init_ctx (struct sha256_ctx *ctx)
ctx->buflen = 0;
}
-/* Copy the value from v into the memory location pointed to by *cp,
- If your architecture allows unaligned access this is equivalent to
- * (uint32_t *) cp = v */
+/* Copy the value from v into the memory location pointed to by *CP,
+ If your architecture allows unaligned access, this is equivalent to
+ * (__typeof__ (v) *) cp = v */
static void
set_uint32 (char *cp, uint32_t v)
{
memcpy (cp, &v, sizeof v);
}
-/* Put result from CTX in first 32 bytes following RESBUF. The result
- must be in little endian byte order. */
+/* Put result from CTX in first 32 bytes following RESBUF.
+ The result must be in little endian byte order. */
void *
sha256_read_ctx (const struct sha256_ctx *ctx, void *resbuf)
{
@@ -167,154 +159,8 @@ sha224_finish_ctx (struct sha256_ctx *ctx, void *resbuf)
sha256_conclude_ctx (ctx);
return sha224_read_ctx (ctx, resbuf);
}
-#endif
-
-/* Compute SHA256 message digest for bytes read from STREAM. The
- resulting message digest number will be written into the 32 bytes
- beginning at RESBLOCK. */
-int
-sha256_stream (FILE *stream, void *resblock)
-{
- struct sha256_ctx ctx;
- size_t sum;
-
- char *buffer = malloc (BLOCKSIZE + 72);
- if (!buffer)
- return 1;
-
- /* Initialize the computation context. */
- sha256_init_ctx (&ctx);
-
- /* Iterate over full file contents. */
- while (1)
- {
- /* We read the file in blocks of BLOCKSIZE bytes. One call of the
- computation function processes the whole buffer so that with the
- next round of the loop another block can be read. */
- size_t n;
- sum = 0;
-
- /* Read block. Take care for partial reads. */
- while (1)
- {
- n = fread (buffer + sum, 1, BLOCKSIZE - sum, stream);
-
- sum += n;
-
- if (sum == BLOCKSIZE)
- break;
-
- if (n == 0)
- {
- /* Check for the error flag IFF N == 0, so that we don't
- exit the loop after a partial read due to e.g., EAGAIN
- or EWOULDBLOCK. */
- if (ferror (stream))
- {
- free (buffer);
- return 1;
- }
- goto process_partial_block;
- }
-
- /* We've read at least one byte, so ignore errors. But always
- check for EOF, since feof may be true even though N > 0.
- Otherwise, we could end up calling fread after EOF. */
- if (feof (stream))
- goto process_partial_block;
- }
-
- /* Process buffer with BLOCKSIZE bytes. Note that
- BLOCKSIZE % 64 == 0
- */
- sha256_process_block (buffer, BLOCKSIZE, &ctx);
- }
-
- process_partial_block:;
-
- /* Process any remaining bytes. */
- if (sum > 0)
- sha256_process_bytes (buffer, sum, &ctx);
-
- /* Construct result in desired memory. */
- sha256_finish_ctx (&ctx, resblock);
- free (buffer);
- return 0;
-}
-
-/* FIXME: Avoid code duplication */
-int
-sha224_stream (FILE *stream, void *resblock)
-{
- struct sha256_ctx ctx;
- size_t sum;
-
- char *buffer = malloc (BLOCKSIZE + 72);
- if (!buffer)
- return 1;
-
- /* Initialize the computation context. */
- sha224_init_ctx (&ctx);
-
- /* Iterate over full file contents. */
- while (1)
- {
- /* We read the file in blocks of BLOCKSIZE bytes. One call of the
- computation function processes the whole buffer so that with the
- next round of the loop another block can be read. */
- size_t n;
- sum = 0;
-
- /* Read block. Take care for partial reads. */
- while (1)
- {
- n = fread (buffer + sum, 1, BLOCKSIZE - sum, stream);
-
- sum += n;
-
- if (sum == BLOCKSIZE)
- break;
-
- if (n == 0)
- {
- /* Check for the error flag IFF N == 0, so that we don't
- exit the loop after a partial read due to e.g., EAGAIN
- or EWOULDBLOCK. */
- if (ferror (stream))
- {
- free (buffer);
- return 1;
- }
- goto process_partial_block;
- }
-
- /* We've read at least one byte, so ignore errors. But always
- check for EOF, since feof may be true even though N > 0.
- Otherwise, we could end up calling fread after EOF. */
- if (feof (stream))
- goto process_partial_block;
- }
-
- /* Process buffer with BLOCKSIZE bytes. Note that
- BLOCKSIZE % 64 == 0
- */
- sha256_process_block (buffer, BLOCKSIZE, &ctx);
- }
-
- process_partial_block:;
-
- /* Process any remaining bytes. */
- if (sum > 0)
- sha256_process_bytes (buffer, sum, &ctx);
-
- /* Construct result in desired memory. */
- sha224_finish_ctx (&ctx, resblock);
- free (buffer);
- return 0;
-}
-#if ! HAVE_OPENSSL_SHA256
-/* Compute SHA512 message digest for LEN bytes beginning at BUFFER. The
+/* Compute SHA256 message digest for LEN bytes beginning at BUFFER. The
result is always in little endian byte order, so that a byte-wise
output yields to the wanted ASCII representation of the message
digest. */
@@ -576,4 +422,12 @@ sha256_process_block (const void *buffer, size_t len, struct sha256_ctx *ctx)
h = ctx->state[7] += h;
}
}
+
#endif
+
+/*
+ * Hey Emacs!
+ * Local Variables:
+ * coding: utf-8
+ * End:
+ */
diff --git a/lib/sha256.h b/lib/sha256.h
index b998aa4b634..533173a59e8 100644
--- a/lib/sha256.h
+++ b/lib/sha256.h
@@ -1,18 +1,18 @@
/* Declarations of functions and data types used for SHA256 and SHA224 sum
library functions.
- Copyright (C) 2005-2006, 2008-2017 Free Software Foundation, Inc.
+ Copyright (C) 2005-2006, 2008-2022 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 file is free software: you can redistribute it and/or modify
+ it under the terms of the GNU Lesser General Public License as
+ published by the Free Software Foundation; either version 2.1 of the
+ License, or (at your option) any later version.
- This program is distributed in the hope that it will be useful,
+ This file 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.
+ GNU Lesser General Public License for more details.
- You should have received a copy of the GNU General Public License
+ You should have received a copy of the GNU Lesser General Public License
along with this program. If not, see <https://www.gnu.org/licenses/>. */
#ifndef SHA256_H
@@ -22,6 +22,9 @@
# include <stdint.h>
# if HAVE_OPENSSL_SHA256
+# ifndef OPENSSL_API_COMPAT
+# define OPENSSL_API_COMPAT 0x10101000L /* FIXME: Use OpenSSL 1.1+ API. */
+# endif
# include <openssl/sha.h>
# endif
@@ -70,27 +73,35 @@ extern void sha256_process_bytes (const void *buffer, size_t len,
in first 32 (28) bytes following RESBUF. The result is always in little
endian byte order, so that a byte-wise output yields to the wanted
ASCII representation of the message digest. */
-extern void *sha256_finish_ctx (struct sha256_ctx *ctx, void *resbuf);
-extern void *sha224_finish_ctx (struct sha256_ctx *ctx, void *resbuf);
+extern void *sha256_finish_ctx (struct sha256_ctx *ctx, void *restrict resbuf);
+extern void *sha224_finish_ctx (struct sha256_ctx *ctx, void *restrict resbuf);
/* Put result from CTX in first 32 (28) bytes following RESBUF. The result is
always in little endian byte order, so that a byte-wise output yields
to the wanted ASCII representation of the message digest. */
-extern void *sha256_read_ctx (const struct sha256_ctx *ctx, void *resbuf);
-extern void *sha224_read_ctx (const struct sha256_ctx *ctx, void *resbuf);
+extern void *sha256_read_ctx (const struct sha256_ctx *ctx,
+ void *restrict resbuf);
+extern void *sha224_read_ctx (const struct sha256_ctx *ctx,
+ void *restrict resbuf);
-/* Compute SHA256 (SHA224) message digest for LEN bytes beginning at BUFFER. The
- result is always in little endian byte order, so that a byte-wise
+/* Compute SHA256 (SHA224) message digest for LEN bytes beginning at BUFFER.
+ The result is always in little endian byte order, so that a byte-wise
output yields to the wanted ASCII representation of the message
digest. */
-extern void *sha256_buffer (const char *buffer, size_t len, void *resblock);
-extern void *sha224_buffer (const char *buffer, size_t len, void *resblock);
+extern void *sha256_buffer (const char *buffer, size_t len,
+ void *restrict resblock);
+extern void *sha224_buffer (const char *buffer, size_t len,
+ void *restrict resblock);
# endif
-/* Compute SHA256 (SHA224) message digest for bytes read from STREAM. The
- resulting message digest number will be written into the 32 (28) bytes
+
+/* Compute SHA256 (SHA224) message digest for bytes read from STREAM.
+ STREAM is an open file stream. Regular files are handled more efficiently.
+ The contents of STREAM from its current position to its end will be read.
+ The case that the last operation on STREAM was an 'ungetc' is not supported.
+ The resulting message digest number will be written into the 32 (28) bytes
beginning at RESBLOCK. */
extern int sha256_stream (FILE *stream, void *resblock);
extern int sha224_stream (FILE *stream, void *resblock);
@@ -101,3 +112,10 @@ extern int sha224_stream (FILE *stream, void *resblock);
# endif
#endif
+
+/*
+ * Hey Emacs!
+ * Local Variables:
+ * coding: utf-8
+ * End:
+ */
diff --git a/lib/sha512.c b/lib/sha512.c
index e666231148e..6776bb464d8 100644
--- a/lib/sha512.c
+++ b/lib/sha512.c
@@ -1,19 +1,19 @@
/* sha512.c - Functions to compute SHA512 and SHA384 message digest of files or
memory blocks according to the NIST specification FIPS-180-2.
- Copyright (C) 2005-2006, 2008-2017 Free Software Foundation, Inc.
+ Copyright (C) 2005-2006, 2008-2022 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 file is free software: you can redistribute it and/or modify
+ it under the terms of the GNU Lesser General Public License as
+ published by the Free Software Foundation; either version 2.1 of the
+ License, or (at your option) any later version.
- This program is distributed in the hope that it will be useful,
+ This file 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.
+ GNU Lesser General Public License for more details.
- You should have received a copy of the GNU General Public License
+ You should have received a copy of the GNU Lesser General Public License
along with this program. If not, see <https://www.gnu.org/licenses/>. */
/* Written by David Madore, considerably copypasting from
@@ -22,6 +22,7 @@
#include <config.h>
+/* Specification. */
#if HAVE_OPENSSL_SHA512
# define GL_OPENSSL_INLINE _GL_EXTERN_INLINE
#endif
@@ -29,33 +30,17 @@
#include <stdalign.h>
#include <stdint.h>
-#include <stdlib.h>
#include <string.h>
-#if USE_UNLOCKED_IO
-# include "unlocked-io.h"
-#endif
-
+#include <byteswap.h>
#ifdef WORDS_BIGENDIAN
# define SWAP(n) (n)
#else
-# define SWAP(n) \
- u64or (u64or (u64or (u64shl (n, 56), \
- u64shl (u64and (n, u64lo (0x0000ff00)), 40)), \
- u64or (u64shl (u64and (n, u64lo (0x00ff0000)), 24), \
- u64shl (u64and (n, u64lo (0xff000000)), 8))), \
- u64or (u64or (u64and (u64shr (n, 8), u64lo (0xff000000)), \
- u64and (u64shr (n, 24), u64lo (0x00ff0000))), \
- u64or (u64and (u64shr (n, 40), u64lo (0x0000ff00)), \
- u64shr (n, 56))))
-#endif
-
-#define BLOCKSIZE 32768
-#if BLOCKSIZE % 128 != 0
-# error "invalid BLOCKSIZE"
+# define SWAP(n) bswap_64 (n)
#endif
#if ! HAVE_OPENSSL_SHA512
+
/* This array contains the bytes used to pad the buffer to the next
128-byte boundary. */
static const unsigned char fillbuf[128] = { 0x80, 0 /* , 0, 0, ... */ };
@@ -175,153 +160,7 @@ sha384_finish_ctx (struct sha512_ctx *ctx, void *resbuf)
sha512_conclude_ctx (ctx);
return sha384_read_ctx (ctx, resbuf);
}
-#endif
-
-/* Compute SHA512 message digest for bytes read from STREAM. The
- resulting message digest number will be written into the 64 bytes
- beginning at RESBLOCK. */
-int
-sha512_stream (FILE *stream, void *resblock)
-{
- struct sha512_ctx ctx;
- size_t sum;
-
- char *buffer = malloc (BLOCKSIZE + 72);
- if (!buffer)
- return 1;
-
- /* Initialize the computation context. */
- sha512_init_ctx (&ctx);
-
- /* Iterate over full file contents. */
- while (1)
- {
- /* We read the file in blocks of BLOCKSIZE bytes. One call of the
- computation function processes the whole buffer so that with the
- next round of the loop another block can be read. */
- size_t n;
- sum = 0;
-
- /* Read block. Take care for partial reads. */
- while (1)
- {
- n = fread (buffer + sum, 1, BLOCKSIZE - sum, stream);
-
- sum += n;
-
- if (sum == BLOCKSIZE)
- break;
-
- if (n == 0)
- {
- /* Check for the error flag IFF N == 0, so that we don't
- exit the loop after a partial read due to e.g., EAGAIN
- or EWOULDBLOCK. */
- if (ferror (stream))
- {
- free (buffer);
- return 1;
- }
- goto process_partial_block;
- }
-
- /* We've read at least one byte, so ignore errors. But always
- check for EOF, since feof may be true even though N > 0.
- Otherwise, we could end up calling fread after EOF. */
- if (feof (stream))
- goto process_partial_block;
- }
-
- /* Process buffer with BLOCKSIZE bytes. Note that
- BLOCKSIZE % 128 == 0
- */
- sha512_process_block (buffer, BLOCKSIZE, &ctx);
- }
-
- process_partial_block:;
-
- /* Process any remaining bytes. */
- if (sum > 0)
- sha512_process_bytes (buffer, sum, &ctx);
-
- /* Construct result in desired memory. */
- sha512_finish_ctx (&ctx, resblock);
- free (buffer);
- return 0;
-}
-
-/* FIXME: Avoid code duplication */
-int
-sha384_stream (FILE *stream, void *resblock)
-{
- struct sha512_ctx ctx;
- size_t sum;
-
- char *buffer = malloc (BLOCKSIZE + 72);
- if (!buffer)
- return 1;
-
- /* Initialize the computation context. */
- sha384_init_ctx (&ctx);
-
- /* Iterate over full file contents. */
- while (1)
- {
- /* We read the file in blocks of BLOCKSIZE bytes. One call of the
- computation function processes the whole buffer so that with the
- next round of the loop another block can be read. */
- size_t n;
- sum = 0;
-
- /* Read block. Take care for partial reads. */
- while (1)
- {
- n = fread (buffer + sum, 1, BLOCKSIZE - sum, stream);
-
- sum += n;
-
- if (sum == BLOCKSIZE)
- break;
-
- if (n == 0)
- {
- /* Check for the error flag IFF N == 0, so that we don't
- exit the loop after a partial read due to e.g., EAGAIN
- or EWOULDBLOCK. */
- if (ferror (stream))
- {
- free (buffer);
- return 1;
- }
- goto process_partial_block;
- }
-
- /* We've read at least one byte, so ignore errors. But always
- check for EOF, since feof may be true even though N > 0.
- Otherwise, we could end up calling fread after EOF. */
- if (feof (stream))
- goto process_partial_block;
- }
-
- /* Process buffer with BLOCKSIZE bytes. Note that
- BLOCKSIZE % 128 == 0
- */
- sha512_process_block (buffer, BLOCKSIZE, &ctx);
- }
-
- process_partial_block:;
-
- /* Process any remaining bytes. */
- if (sum > 0)
- sha512_process_bytes (buffer, sum, &ctx);
-
- /* Construct result in desired memory. */
- sha384_finish_ctx (&ctx, resblock);
- free (buffer);
- return 0;
-}
-#if ! HAVE_OPENSSL_SHA512
/* Compute SHA512 message digest for LEN bytes beginning at BUFFER. The
result is always in little endian byte order, so that a byte-wise
output yields to the wanted ASCII representation of the message
@@ -628,4 +467,12 @@ sha512_process_block (const void *buffer, size_t len, struct sha512_ctx *ctx)
h = ctx->state[7] = u64plus (ctx->state[7], h);
}
}
+
#endif
+
+/*
+ * Hey Emacs!
+ * Local Variables:
+ * coding: utf-8
+ * End:
+ */
diff --git a/lib/sha512.h b/lib/sha512.h
index 70a3f9ad6cb..1eb18702278 100644
--- a/lib/sha512.h
+++ b/lib/sha512.h
@@ -1,18 +1,18 @@
/* Declarations of functions and data types used for SHA512 and SHA384 sum
library functions.
- Copyright (C) 2005-2006, 2008-2017 Free Software Foundation, Inc.
+ Copyright (C) 2005-2006, 2008-2022 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 file is free software: you can redistribute it and/or modify
+ it under the terms of the GNU Lesser General Public License as
+ published by the Free Software Foundation; either version 2.1 of the
+ License, or (at your option) any later version.
- This program is distributed in the hope that it will be useful,
+ This file 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.
+ GNU Lesser General Public License for more details.
- You should have received a copy of the GNU General Public License
+ You should have received a copy of the GNU Lesser General Public License
along with this program. If not, see <https://www.gnu.org/licenses/>. */
#ifndef SHA512_H
@@ -22,6 +22,9 @@
# include "u64.h"
# if HAVE_OPENSSL_SHA512
+# ifndef OPENSSL_API_COMPAT
+# define OPENSSL_API_COMPAT 0x10101000L /* FIXME: Use OpenSSL 1.1+ API. */
+# endif
# include <openssl/sha.h>
# endif
@@ -70,8 +73,8 @@ extern void sha512_process_bytes (const void *buffer, size_t len,
in first 64 (48) bytes following RESBUF. The result is always in little
endian byte order, so that a byte-wise output yields to the wanted
ASCII representation of the message digest. */
-extern void *sha512_finish_ctx (struct sha512_ctx *ctx, void *resbuf);
-extern void *sha384_finish_ctx (struct sha512_ctx *ctx, void *resbuf);
+extern void *sha512_finish_ctx (struct sha512_ctx *ctx, void *restrict resbuf);
+extern void *sha384_finish_ctx (struct sha512_ctx *ctx, void *restrict resbuf);
/* Put result from CTX in first 64 (48) bytes following RESBUF. The result is
@@ -80,20 +83,28 @@ extern void *sha384_finish_ctx (struct sha512_ctx *ctx, void *resbuf);
IMPORTANT: On some systems it is required that RESBUF is correctly
aligned for a 32 bits value. */
-extern void *sha512_read_ctx (const struct sha512_ctx *ctx, void *resbuf);
-extern void *sha384_read_ctx (const struct sha512_ctx *ctx, void *resbuf);
+extern void *sha512_read_ctx (const struct sha512_ctx *ctx,
+ void *restrict resbuf);
+extern void *sha384_read_ctx (const struct sha512_ctx *ctx,
+ void *restrict resbuf);
-/* Compute SHA512 (SHA384) message digest for LEN bytes beginning at BUFFER. The
- result is always in little endian byte order, so that a byte-wise
+/* Compute SHA512 (SHA384) message digest for LEN bytes beginning at BUFFER.
+ The result is always in little endian byte order, so that a byte-wise
output yields to the wanted ASCII representation of the message
digest. */
-extern void *sha512_buffer (const char *buffer, size_t len, void *resblock);
-extern void *sha384_buffer (const char *buffer, size_t len, void *resblock);
+extern void *sha512_buffer (const char *buffer, size_t len,
+ void *restrict resblock);
+extern void *sha384_buffer (const char *buffer, size_t len,
+ void *restrict resblock);
# endif
-/* Compute SHA512 (SHA384) message digest for bytes read from STREAM. The
- resulting message digest number will be written into the 64 (48) bytes
+
+/* Compute SHA512 (SHA384) message digest for bytes read from STREAM.
+ STREAM is an open file stream. Regular files are handled more efficiently.
+ The contents of STREAM from its current position to its end will be read.
+ The case that the last operation on STREAM was an 'ungetc' is not supported.
+ The resulting message digest number will be written into the 64 (48) bytes
beginning at RESBLOCK. */
extern int sha512_stream (FILE *stream, void *resblock);
extern int sha384_stream (FILE *stream, void *resblock);
@@ -104,3 +115,10 @@ extern int sha384_stream (FILE *stream, void *resblock);
# endif
#endif
+
+/*
+ * Hey Emacs!
+ * Local Variables:
+ * coding: utf-8
+ * End:
+ */
diff --git a/lib/sig2str.c b/lib/sig2str.c
index a3ed970063e..8e2fc0c0754 100644
--- a/lib/sig2str.c
+++ b/lib/sig2str.c
@@ -1,10 +1,10 @@
/* sig2str.c -- convert between signal names and numbers
- Copyright (C) 2002, 2004, 2006, 2009-2017 Free Software Foundation, Inc.
+ Copyright (C) 2002, 2004, 2006, 2009-2022 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
+ 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,
@@ -189,6 +189,11 @@ static struct numname { int num; char const name[8]; } numname_table[] =
NUMNAME (STKFLT),
#endif
+ /* AIX 7. */
+#ifdef SIGCPUFAIL
+ NUMNAME (CPUFAIL),
+#endif
+
/* AIX 5L. */
#ifdef SIGDANGER
NUMNAME (DANGER),
@@ -229,7 +234,12 @@ static struct numname { int num; char const name[8]; } numname_table[] =
NUMNAME (WINDOW), /* Older name for SIGWINCH. */
#endif
- /* BeOS */
+ /* OpenBSD. */
+#ifdef SIGTHR
+ NUMNAME (THR),
+#endif
+
+ /* BeOS, Haiku */
#ifdef SIGKILLTHR
NUMNAME (KILLTHR),
#endif
@@ -239,6 +249,11 @@ static struct numname { int num; char const name[8]; } numname_table[] =
NUMNAME (DIL),
#endif
+ /* native Windows */
+#ifdef SIGBREAK
+ NUMNAME (BREAK),
+#endif
+
/* Korn shell and Bash, of uncertain vintage. */
{ 0, "EXIT" }
};
diff --git a/lib/sig2str.h b/lib/sig2str.h
index 4e43ea404c1..a45af7f9686 100644
--- a/lib/sig2str.h
+++ b/lib/sig2str.h
@@ -1,10 +1,10 @@
/* sig2str.h -- convert between signal names and numbers
- Copyright (C) 2002, 2005, 2009-2017 Free Software Foundation, Inc.
+ Copyright (C) 2002, 2005, 2009-2022 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
+ 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,
diff --git a/lib/sigdescr_np.c b/lib/sigdescr_np.c
new file mode 100644
index 00000000000..652bc8d75b4
--- /dev/null
+++ b/lib/sigdescr_np.c
@@ -0,0 +1,376 @@
+/* English descriptions of signals.
+ Copyright (C) 2020-2022 Free Software Foundation, Inc.
+
+ This file is free software: you can redistribute it and/or modify
+ it under the terms of the GNU Lesser General Public License as
+ published by the Free Software Foundation; either version 2.1 of the
+ License, or (at your option) any later version.
+
+ This file 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 Lesser General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public License
+ along with this program. If not, see <https://www.gnu.org/licenses/>. */
+
+/* Written by Bruno Haible <bruno@clisp.org>, 2020. */
+
+#include <config.h>
+
+/* Specification. */
+#include <string.h>
+
+#include <signal.h>
+
+const char *
+sigdescr_np (int sig)
+{
+ /* Note: Some platforms (glibc, FreeBSD, NetBSD, OpenBSD, AIX, IRIX, Haiku,
+ Android) have an array 'sys_siglist'. (On AIX, you need to declare it
+ yourself, and it has fewer than NSIG elements.) Its contents varies
+ depending on the OS.
+ On other OSes, you can invoke strsignal (sig) in the C locale.
+ In the code below, we show the differences.
+ You can see how cryptic some of these strings are. We try to pick more
+ understandable wordings. */
+
+ switch (sig)
+ {
+ /* Signals specified by ISO C. */
+ case SIGABRT:
+ /* glibc: "Aborted". *BSD: "Abort trap". Solaris: "Abort". */
+ return "Aborted";
+ case SIGFPE:
+ /* glibc, *BSD: "Floating point exception". Solaris: "Arithmetic exception".
+ The latter is more correct, because of integer division by 0 or -1. */
+ return "Arithmetic exception";
+ case SIGILL:
+ return "Illegal instruction";
+ case SIGINT:
+ return "Interrupt";
+ case SIGSEGV:
+ return "Segmentation fault";
+ case SIGTERM:
+ return "Terminated";
+
+ /* Signals specified by POSIX.
+ <https://pubs.opengroup.org/onlinepubs/9699919799/basedefs/signal.h.html> */
+ #if defined SIGALRM
+ case SIGALRM:
+ return "Alarm clock";
+ #endif
+ #if defined SIGBUS
+ case SIGBUS:
+ return "Bus error";
+ #endif
+ #if defined SIGCHLD
+ case SIGCHLD:
+ /* glibc, *BSD: "Child exited". Solaris: "Child status changed". */
+ return "Child stopped or exited";
+ #endif
+ #if defined SIGCONT
+ case SIGCONT:
+ return "Continued";
+ #endif
+ #if defined SIGHUP
+ case SIGHUP:
+ return "Hangup";
+ #endif
+ #if defined SIGKILL
+ case SIGKILL:
+ return "Killed";
+ #endif
+ #if defined SIGPIPE
+ case SIGPIPE:
+ return "Broken pipe";
+ #endif
+ #if defined SIGQUIT
+ case SIGQUIT:
+ return "Quit";
+ #endif
+ #if defined SIGSTOP
+ case SIGSTOP:
+ /* glibc, Solaris: "Stopped (signal)". *BSD: "Suspended (signal)". */
+ return "Stopped (signal)";
+ #endif
+ #if defined SIGTSTP
+ case SIGTSTP:
+ /* glibc: "Stopped". *BSD: "Suspended". Solaris: "Stopped (user)". */
+ return "Stopped";
+ #endif
+ #if defined SIGTTIN
+ case SIGTTIN:
+ return "Stopped (tty input)";
+ #endif
+ #if defined SIGTTOU
+ case SIGTTOU:
+ return "Stopped (tty output)";
+ #endif
+ #if defined SIGUSR1
+ case SIGUSR1:
+ /* glibc, *BSD: "User defined signal 1". Solaris: "User signal 1". */
+ return "User defined signal 1";
+ #endif
+ #if defined SIGUSR2
+ case SIGUSR2:
+ /* glibc, *BSD: "User defined signal 2". Solaris: "User signal 2". */
+ return "User defined signal 2";
+ #endif
+ #if defined SIGPOLL
+ case SIGPOLL:
+ /* glibc: "I/O possible". Solaris: "Pollable event". */
+ return "I/O possible";
+ #endif
+ #if defined SIGPROF
+ case SIGPROF:
+ return "Profiling timer expired";
+ #endif
+ #if defined SIGSYS
+ case SIGSYS:
+ return "Bad system call";
+ #endif
+ #if defined SIGTRAP
+ case SIGTRAP:
+ /* glibc, Solaris: "Trace/breakpoint trap". *BSD: "Trace/BPT trap". */
+ return "Trace/breakpoint trap";
+ #endif
+ #if defined SIGURG
+ case SIGURG:
+ /* glibc, *BSD: "Urgent I/O condition". Solaris: "Urgent socket condition". */
+ return "Urgent I/O condition";
+ #endif
+ #if defined SIGVTALRM
+ case SIGVTALRM:
+ return "Virtual timer expired";
+ #endif
+ #if defined SIGXCPU
+ case SIGXCPU:
+ /* glibc, *BSD: "CPU time limit exceeded". Solaris: "Cpu limit exceeded". */
+ return "CPU time limit exceeded";
+ #endif
+ #if defined SIGXFSZ
+ case SIGXFSZ:
+ return "File size limit exceeded";
+ #endif
+
+ /* Other signals on other systems. */
+ /* native Windows */
+ #if defined SIGBREAK
+ case SIGBREAK:
+ return "Ctrl-Break";
+ #endif
+ /* IRIX */
+ #if defined SIGCKPT
+ case SIGCKPT:
+ return "Checkpoint"; /* See man 1 cpr, man 3C atcheckpoint */
+ #endif
+ /* Linux, IRIX, Cygwin */
+ #if defined SIGCLD && SIGCLD != SIGCHLD
+ case SIGCLD:
+ return "Child stopped or exited";
+ #endif
+ /* AIX */
+ #if defined SIGCPUFAIL
+ case SIGCPUFAIL:
+ /* AIX: "CPU failure predicted". */
+ return "CPU going down"; /* See man bindprocessor */
+ #endif
+ /* AIX */
+ #if defined SIGDANGER
+ case SIGDANGER:
+ /* AIX: "Paging space low". */
+ return "Swap space nearly exhausted";
+ #endif
+ /* Mac OS X, FreeBSD, NetBSD, OpenBSD, Minix, AIX, IRIX, Cygwin, mingw */
+ #if defined SIGEMT
+ case SIGEMT:
+ /* glibc/Hurd, *BSD: "EMT trap". Solaris: "Emulation trap". */
+ return "Instruction emulation needed";
+ #endif
+ /* Mac OS X, FreeBSD, NetBSD, OpenBSD, Minix */
+ #if defined SIGINFO && SIGINFO != SIGPWR
+ case SIGINFO:
+ return "Information request";
+ #endif
+ /* Linux, Mac OS X, FreeBSD, NetBSD, OpenBSD, Minix, AIX, IRIX, Cygwin */
+ #if defined SIGIO && SIGIO != SIGPOLL
+ case SIGIO:
+ return "I/O possible";
+ #endif
+ /* Linux, IRIX, Cygwin, mingw */
+ #if defined SIGIOT && SIGIOT != SIGABRT
+ case SIGIOT:
+ return "IOT instruction"; /* a PDP-11 instruction */
+ #endif
+ /* AIX */
+ #if defined SIGKAP
+ case SIGKAP:
+ /* Process must issue a KSKAPACK ioctl, or will be killed in 30 seconds. */
+ /* AIX: "Monitor mode granted". */
+ return "Keep Alive Poll";
+ #endif
+ /* Haiku */
+ #if defined SIGKILLTHR
+ case SIGKILLTHR:
+ return "Kill thread";
+ #endif
+ /* Minix */
+ #if defined SIGKMEM
+ case SIGKMEM:
+ return "Kernel memory request";
+ #endif
+ /* Minix */
+ #if defined SIGKMESS
+ case SIGKMESS:
+ return "Kernel message";
+ #endif
+ /* Minix */
+ #if defined SIGKSIG
+ case SIGKSIG:
+ return "Kernel signal";
+ #endif
+ /* Minix */
+ #if defined SIGKSIGSM
+ case SIGKSIGSM:
+ return "Kernel signal for signal manager";
+ #endif
+ /* FreeBSD */
+ #if defined SIGLIBRT
+ case SIGLIBRT:
+ return "Real-time library interrupt";
+ #endif
+ /* Cygwin */
+ #if defined SIGLOST && SIGLOST != SIGABRT && SIGLOST != SIGPWR
+ case SIGLOST:
+ /* Solaris: "Resource lost". */
+ return "File lock lost";
+ #endif
+ /* AIX */
+ #if defined SIGMIGRATE
+ case SIGMIGRATE:
+ return "Process migration";
+ #endif
+ /* AIX */
+ #if defined SIGMSG
+ case SIGMSG:
+ /* AIX: "Input device data". */
+ return "Message in the ring";
+ #endif
+ /* ACM */
+ #if defined SIGPLAN
+ case SIGPLAN:
+ return "Programming language anomaly";
+ #endif
+ /* AIX */
+ #if defined SIGPRE
+ case SIGPRE:
+ return "Programmed exception";
+ #endif
+ /* IRIX */
+ #if defined SIGPTINTR
+ case SIGPTINTR:
+ return "Pthread interrupt";
+ #endif
+ /* IRIX */
+ #if defined SIGPTRESCHED
+ case SIGPTRESCHED:
+ return "Pthread rescheduling";
+ #endif
+ /* Linux, NetBSD, Minix, AIX, IRIX, Cygwin */
+ #if defined SIGPWR
+ case SIGPWR:
+ /* glibc: "Power failure". NetBSD: "Power fail/restart". */
+ return "Power failure";
+ #endif
+ /* AIX */
+ #if defined SIGRECONFIG
+ case SIGRECONFIG:
+ return "Dynamic logical partitioning changed";
+ #endif
+ /* AIX */
+ #if defined SIGRECOVERY
+ case SIGRECOVERY:
+ return "Kernel recovery";
+ #endif
+ /* IRIX */
+ #if defined SIGRESTART
+ case SIGRESTART:
+ return "Checkpoint restart"; /* See man 1 cpr, man 3C atrestart */
+ #endif
+ /* AIX */
+ #if defined SIGRETRACT
+ case SIGRETRACT:
+ /* AIX: "Monitor mode retracted". */
+ return "Retracting Keep Alive Poll";
+ #endif
+ /* AIX */
+ #if defined SIGSAK
+ case SIGSAK:
+ /* AIX: "Secure attention". */
+ return "Secure Attention Key";
+ #endif
+ /* ACM */
+ #if defined SIGSAM
+ case SIGSAM:
+ return "Symbolic computation failed";
+ #endif
+ /* Minix */
+ #if defined SIGSNDELAY
+ case SIGSNDELAY:
+ return "Done sending message";
+ #endif
+ /* AIX */
+ #if defined SIGSOUND
+ case SIGSOUND:
+ /* AIX: "Sound completed". */
+ return "Sound configuration changed";
+ #endif
+ /* Linux */
+ #if defined SIGSTKFLT
+ case SIGSTKFLT:
+ return "Stack fault";
+ #endif
+ /* AIX */
+ #if defined SIGSYSERROR
+ case SIGSYSERROR:
+ return "Kernel error";
+ #endif
+ /* AIX */
+ #if defined SIGTALRM
+ case SIGTALRM:
+ return "Thread alarm clock";
+ #endif
+ /* FreeBSD, OpenBSD */
+ #if defined SIGTHR
+ case SIGTHR:
+ /* OpenBSD: "Thread AST". */
+ return "Thread library interrupt";
+ #endif
+ /* IRIX */
+ #if defined SIGUME
+ case SIGUME:
+ return "Uncorrectable memory error";
+ #endif
+ /* AIX */
+ #if defined SIGVIRT
+ case SIGVIRT:
+ return "Virtual time alarm clock";
+ #endif
+ /* AIX */
+ #if defined SIGWAITING
+ case SIGWAITING:
+ /* AIX: "No runnable lwp". */
+ return "Thread waiting";
+ #endif
+ /* Linux, Mac OS X, FreeBSD, NetBSD, OpenBSD, Minix, AIX, IRIX, Cygwin, Haiku */
+ #if defined SIGWINCH
+ case SIGWINCH:
+ /* glibc: "Window changed". *BSD: "Window size changed" or "Window size changes". */
+ return "Window size changed";
+ #endif
+
+ default:
+ return NULL;
+ }
+}
diff --git a/lib/signal.in.h b/lib/signal.in.h
index 9c32b14962f..640b5022f5f 100644
--- a/lib/signal.in.h
+++ b/lib/signal.in.h
@@ -1,18 +1,18 @@
/* A GNU-like <signal.h>.
- Copyright (C) 2006-2017 Free Software Foundation, Inc.
+ Copyright (C) 2006-2022 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 file is free software: you can redistribute it and/or modify
+ it under the terms of the GNU Lesser General Public License as
+ published by the Free Software Foundation; either version 2.1 of the
+ License, or (at your option) any later version.
- This program is distributed in the hope that it will be useful,
+ This file 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.
+ GNU Lesser General Public License for more details.
- You should have received a copy of the GNU General Public License
+ You should have received a copy of the GNU Lesser General Public License
along with this program. If not, see <https://www.gnu.org/licenses/>. */
#if __GNUC__ >= 3
@@ -55,13 +55,13 @@
#ifndef _@GUARD_PREFIX@_SIGNAL_H
#define _@GUARD_PREFIX@_SIGNAL_H
-/* Mac OS X 10.3, FreeBSD 6.4, OpenBSD 3.8, OSF/1 4.0, Solaris 2.6, Android
- declare pthread_sigmask in <pthread.h>, not in <signal.h>.
+/* Mac OS X 10.3, FreeBSD 6.4, OpenBSD 3.8, OSF/1 4.0, Solaris 2.6, Android,
+ OS/2 kLIBC declare pthread_sigmask in <pthread.h>, not in <signal.h>.
But avoid namespace pollution on glibc systems.*/
#if (@GNULIB_PTHREAD_SIGMASK@ || defined GNULIB_POSIXCHECK) \
&& ((defined __APPLE__ && defined __MACH__) \
|| defined __FreeBSD__ || defined __OpenBSD__ || defined __osf__ \
- || defined __sun || defined __ANDROID__) \
+ || defined __sun || defined __ANDROID__ || defined __KLIBC__) \
&& ! defined __GLIBC__
# include <pthread.h>
#endif
@@ -133,18 +133,28 @@ typedef void (*sighandler_t) (int);
# define pthread_sigmask rpl_pthread_sigmask
# endif
_GL_FUNCDECL_RPL (pthread_sigmask, int,
- (int how, const sigset_t *new_mask, sigset_t *old_mask));
+ (int how,
+ const sigset_t *restrict new_mask,
+ sigset_t *restrict old_mask));
_GL_CXXALIAS_RPL (pthread_sigmask, int,
- (int how, const sigset_t *new_mask, sigset_t *old_mask));
+ (int how,
+ const sigset_t *restrict new_mask,
+ sigset_t *restrict old_mask));
# else
-# if !@HAVE_PTHREAD_SIGMASK@
+# if !(@HAVE_PTHREAD_SIGMASK@ || defined pthread_sigmask)
_GL_FUNCDECL_SYS (pthread_sigmask, int,
- (int how, const sigset_t *new_mask, sigset_t *old_mask));
+ (int how,
+ const sigset_t *restrict new_mask,
+ sigset_t *restrict old_mask));
# endif
_GL_CXXALIAS_SYS (pthread_sigmask, int,
- (int how, const sigset_t *new_mask, sigset_t *old_mask));
+ (int how,
+ const sigset_t *restrict new_mask,
+ sigset_t *restrict old_mask));
# endif
+# if __GLIBC__ >= 2
_GL_CXXALIASWARN (pthread_sigmask);
+# endif
#elif defined GNULIB_POSIXCHECK
# undef pthread_sigmask
# if HAVE_RAW_DECL_PTHREAD_SIGMASK
@@ -168,7 +178,9 @@ _GL_FUNCDECL_SYS (raise, int, (int sig));
# endif
_GL_CXXALIAS_SYS (raise, int, (int sig));
# endif
+# if __GLIBC__ >= 2
_GL_CXXALIASWARN (raise);
+# endif
#elif defined GNULIB_POSIXCHECK
# undef raise
/* Assume raise is always declared. */
@@ -200,7 +212,7 @@ typedef int verify_NSIG_constraint[NSIG <= 32 ? 1 : -1];
/* When also using extern inline, suppress the use of static inline in
standard headers of problematic Apple configurations, as Libc at
least through Libc-825.26 (2013-04-09) mishandles it; see, e.g.,
- <https://lists.gnu.org/archive/html/bug-gnulib/2012-12/msg00023.html>.
+ <https://lists.gnu.org/r/bug-gnulib/2012-12/msg00023.html>.
Perhaps Apple will fix this some day. */
#if (defined _GL_EXTERN_INLINE_IN_USE && defined __APPLE__ \
&& (defined __i386__ || defined __x86_64__))
@@ -291,10 +303,14 @@ _GL_CXXALIASWARN (sigpending);
# define SIG_SETMASK 1 /* blocked_set = *set; */
# define SIG_UNBLOCK 2 /* blocked_set = blocked_set & ~*set; */
_GL_FUNCDECL_SYS (sigprocmask, int,
- (int operation, const sigset_t *set, sigset_t *old_set));
+ (int operation,
+ const sigset_t *restrict set,
+ sigset_t *restrict old_set));
# endif
_GL_CXXALIAS_SYS (sigprocmask, int,
- (int operation, const sigset_t *set, sigset_t *old_set));
+ (int operation,
+ const sigset_t *restrict set,
+ sigset_t *restrict old_set));
_GL_CXXALIASWARN (sigprocmask);
/* Install the handler FUNC for signal SIG, and return the previous
@@ -318,10 +334,18 @@ _GL_FUNCDECL_RPL (signal, _gl_function_taking_int_returning_void_t,
_GL_CXXALIAS_RPL (signal, _gl_function_taking_int_returning_void_t,
(int sig, _gl_function_taking_int_returning_void_t func));
# else
+/* On OpenBSD, the declaration of 'signal' may not be present at this point,
+ because it occurs in <sys/signal.h>, not <signal.h> directly. */
+# if defined __OpenBSD__
+_GL_FUNCDECL_SYS (signal, _gl_function_taking_int_returning_void_t,
+ (int sig, _gl_function_taking_int_returning_void_t func));
+# endif
_GL_CXXALIAS_SYS (signal, _gl_function_taking_int_returning_void_t,
(int sig, _gl_function_taking_int_returning_void_t func));
# endif
+# if __GLIBC__ >= 2
_GL_CXXALIASWARN (signal);
+# endif
# if !@HAVE_POSIX_SIGNALBLOCKING@ && GNULIB_defined_SIGPIPE
/* Raise signal SIGPIPE. */
diff --git a/lib/stat-time.c b/lib/stat-time.c
index 81b83ddb4fe..3d48a2b5b0e 100644
--- a/lib/stat-time.c
+++ b/lib/stat-time.c
@@ -1,3 +1,21 @@
+/* stat-related time functions.
+
+ Copyright (C) 2012-2022 Free Software Foundation, Inc.
+
+ This file is free software: you can redistribute it and/or modify
+ it under the terms of the GNU Lesser General Public License as
+ published by the Free Software Foundation; either version 2.1 of the
+ License, or (at your option) any later version.
+
+ This file 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 Lesser General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public License
+ along with this program. If not, see <https://www.gnu.org/licenses/>. */
+
#include <config.h>
+
#define _GL_STAT_TIME_INLINE _GL_EXTERN_INLINE
#include "stat-time.h"
diff --git a/lib/stat-time.h b/lib/stat-time.h
index 47a3bf8f21e..6b0088e3285 100644
--- a/lib/stat-time.h
+++ b/lib/stat-time.h
@@ -1,18 +1,18 @@
/* stat-related time functions.
- Copyright (C) 2005, 2007, 2009-2017 Free Software Foundation, Inc.
+ Copyright (C) 2005, 2007, 2009-2022 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 file is free software: you can redistribute it and/or modify
+ it under the terms of the GNU Lesser General Public License as
+ published by the Free Software Foundation; either version 2.1 of the
+ License, or (at your option) any later version.
- This program is distributed in the hope that it will be useful,
+ This file 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.
+ GNU Lesser General Public License for more details.
- You should have received a copy of the GNU General Public License
+ You should have received a copy of the GNU Lesser General Public License
along with this program. If not, see <https://www.gnu.org/licenses/>. */
/* Written by Paul Eggert. */
@@ -20,6 +20,10 @@
#ifndef STAT_TIME_H
#define STAT_TIME_H 1
+#include "intprops.h"
+
+#include <errno.h>
+#include <stddef.h>
#include <sys/stat.h>
#include <time.h>
@@ -98,15 +102,13 @@ get_stat_mtime_ns (struct stat const *st)
/* Return the nanosecond component of *ST's birth time. */
_GL_STAT_TIME_INLINE long int _GL_ATTRIBUTE_PURE
-get_stat_birthtime_ns (struct stat const *st)
+get_stat_birthtime_ns (_GL_UNUSED struct stat const *st)
{
# if defined HAVE_STRUCT_STAT_ST_BIRTHTIMESPEC_TV_NSEC
return STAT_TIMESPEC (st, st_birthtim).tv_nsec;
# elif defined HAVE_STRUCT_STAT_ST_BIRTHTIMENSEC
return STAT_TIMESPEC_NS (st, st_birthtim);
# else
- /* Avoid a "parameter unused" warning. */
- (void) st;
return 0;
# endif
}
@@ -156,7 +158,7 @@ get_stat_mtime (struct stat const *st)
/* Return *ST's birth time, if available; otherwise return a value
with tv_sec and tv_nsec both equal to -1. */
_GL_STAT_TIME_INLINE struct timespec _GL_ATTRIBUTE_PURE
-get_stat_birthtime (struct stat const *st)
+get_stat_birthtime (_GL_UNUSED struct stat const *st)
{
struct timespec t;
@@ -166,10 +168,10 @@ get_stat_birthtime (struct stat const *st)
#elif defined HAVE_STRUCT_STAT_ST_BIRTHTIMENSEC
t.tv_sec = st->st_birthtime;
t.tv_nsec = st->st_birthtimensec;
-#elif (defined _WIN32 || defined __WIN32__) && ! defined __CYGWIN__
+#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
@@ -180,8 +182,6 @@ get_stat_birthtime (struct stat const *st)
/* Birth time is not supported. */
t.tv_sec = -1;
t.tv_nsec = -1;
- /* Avoid a "parameter unused" warning. */
- (void) st;
#endif
#if (defined HAVE_STRUCT_STAT_ST_BIRTHTIMESPEC_TV_NSEC \
@@ -202,6 +202,47 @@ get_stat_birthtime (struct stat const *st)
return t;
}
+/* If a stat-like function returned RESULT, normalize the timestamps
+ in *ST, in case this platform suffers from the Solaris 11 bug where
+ tv_nsec might be negative. Return the adjusted RESULT, setting
+ errno to EOVERFLOW if normalization overflowed. This function
+ is intended to be private to this .h file. */
+_GL_STAT_TIME_INLINE int
+stat_time_normalize (int result, _GL_UNUSED struct stat *st)
+{
+#if defined __sun && defined STAT_TIMESPEC
+ if (result == 0)
+ {
+ long int timespec_hz = 1000000000;
+ short int const ts_off[] = { offsetof (struct stat, st_atim),
+ offsetof (struct stat, st_mtim),
+ offsetof (struct stat, st_ctim) };
+ int i;
+ for (i = 0; i < sizeof ts_off / sizeof *ts_off; i++)
+ {
+ struct timespec *ts = (struct timespec *) ((char *) st + ts_off[i]);
+ long int q = ts->tv_nsec / timespec_hz;
+ long int r = ts->tv_nsec % timespec_hz;
+ if (r < 0)
+ {
+ r += timespec_hz;
+ q--;
+ }
+ ts->tv_nsec = r;
+ /* Overflow is possible, as Solaris 11 stat can yield
+ tv_sec == TYPE_MINIMUM (time_t) && tv_nsec == -1000000000.
+ INT_ADD_WRAPV is OK, since time_t is signed on Solaris. */
+ if (INT_ADD_WRAPV (q, ts->tv_sec, &ts->tv_sec))
+ {
+ errno = EOVERFLOW;
+ return -1;
+ }
+ }
+ }
+#endif
+ return result;
+}
+
#ifdef __cplusplus
}
#endif
diff --git a/lib/stdalign.in.h b/lib/stdalign.in.h
index 68e889e053c..3b117df11fe 100644
--- a/lib/stdalign.in.h
+++ b/lib/stdalign.in.h
@@ -1,19 +1,19 @@
/* A substitute for ISO C11 <stdalign.h>.
- Copyright 2011-2017 Free Software Foundation, Inc.
+ Copyright 2011-2022 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 file is free software: you can redistribute it and/or modify
+ it under the terms of the GNU Lesser General Public License as
+ published by the Free Software Foundation; either version 2.1 of the
+ License, or (at your option) any later version.
- This program is distributed in the hope that it will be useful,
+ This file 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.
+ GNU Lesser General Public License for more details.
- You should have received a copy of the GNU General Public License
- along with this program; if not, see <https://www.gnu.org/licenses/>. */
+ You should have received a copy of the GNU Lesser General Public License
+ along with this program. If not, see <https://www.gnu.org/licenses/>. */
/* Written by Paul Eggert and Bruno Haible. */
@@ -34,11 +34,12 @@
requirement of a structure member (i.e., slot or field) that is of
type TYPE, as an integer constant expression.
- This differs from GCC's __alignof__ operator, which can yield a
- better-performing alignment for an object of that type. For
- example, on x86 with GCC, __alignof__ (double) and __alignof__
- (long long) are 8, whereas alignof (double) and alignof (long long)
- are 4 unless the option '-malign-double' is used.
+ This differs from GCC's and clang's __alignof__ operator, which can
+ yield a better-performing alignment for an object of that type. For
+ example, on x86 with GCC and on Linux/x86 with clang,
+ __alignof__ (double) and __alignof__ (long long) are 8, whereas
+ alignof (double) and alignof (long long) are 4 unless the option
+ '-malign-double' is used.
The result cannot be used as a value for an 'enum' constant, if you
want to be portable to HP-UX 10.20 cc and AIX 3.2.5 xlc.
@@ -53,9 +54,12 @@
#undef _Alignof
/* GCC releases before GCC 4.9 had a bug in _Alignof. See GCC bug 52023
- <https://gcc.gnu.org/bugzilla/show_bug.cgi?id=52023>. */
+ <https://gcc.gnu.org/bugzilla/show_bug.cgi?id=52023>.
+ clang versions < 8.0.0 have the same bug. */
#if (!defined __STDC_VERSION__ || __STDC_VERSION__ < 201112 \
- || (defined __GNUC__ && __GNUC__ < 4 + (__GNUC_MINOR__ < 9)))
+ || (defined __GNUC__ && __GNUC__ < 4 + (__GNUC_MINOR__ < 9) \
+ && !defined __clang__) \
+ || (defined __clang__ && __clang_major__ < 8))
# ifdef __cplusplus
# if 201103 <= __cplusplus
# define _Alignof(type) alignof (type)
@@ -100,11 +104,13 @@
#if !defined __STDC_VERSION__ || __STDC_VERSION__ < 201112
# if defined __cplusplus && 201103 <= __cplusplus
# define _Alignas(a) alignas (a)
-# elif ((defined __APPLE__ && defined __MACH__ \
- ? 4 < __GNUC__ + (1 <= __GNUC_MINOR__) \
- : __GNUC__) \
- || (__ia64 && (61200 <= __HP_cc || 61200 <= __HP_aCC)) \
- || __ICC || 0x590 <= __SUNPRO_C || 0x0600 <= __xlC__)
+# elif (!defined __attribute__ \
+ && ((defined __APPLE__ && defined __MACH__ \
+ ? 4 < __GNUC__ + (1 <= __GNUC_MINOR__) \
+ : __GNUC__ && !defined __ibmxl__) \
+ || (4 <= __clang_major__) \
+ || (__ia64 && (61200 <= __HP_cc || 61200 <= __HP_aCC)) \
+ || __ICC || 0x590 <= __SUNPRO_C || 0x0600 <= __xlC__))
# define _Alignas(a) __attribute__ ((__aligned__ (a)))
# elif 1300 <= _MSC_VER
# define _Alignas(a) __declspec (align (a))
diff --git a/lib/stdckdint.in.h b/lib/stdckdint.in.h
new file mode 100644
index 00000000000..90fa62e5966
--- /dev/null
+++ b/lib/stdckdint.in.h
@@ -0,0 +1,37 @@
+/* stdckdint.h -- checked integer arithmetic
+
+ Copyright 2022 Free Software Foundation, Inc.
+
+ This program is free software: you can redistribute it and/or modify it
+ under the terms of the GNU Lesser General Public License as published
+ by the Free Software Foundation; either version 2.1 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 Lesser General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public License
+ along with this program. If not, see <https://www.gnu.org/licenses/>. */
+
+#ifndef _GL_STDCKDINT_H
+#define _GL_STDCKDINT_H
+
+#include "intprops-internal.h"
+
+#include <stdbool.h>
+
+/* Store into *R the low-order bits of A + B, A - B, A * B, respectively.
+ Return 1 if the result overflows, 0 otherwise.
+ A, B, and *R can have any integer type other than char, bool, a
+ bit-precise integer type, or an enumeration type.
+
+ These are like the standard macros introduced in C23, except that
+ arguments should not have side effects. */
+
+#define ckd_add(r, a, b) ((bool) _GL_INT_ADD_WRAPV (a, b, r))
+#define ckd_sub(r, a, b) ((bool) _GL_INT_SUBTRACT_WRAPV (a, b, r))
+#define ckd_mul(r, a, b) ((bool) _GL_INT_MULTIPLY_WRAPV (a, b, r))
+
+#endif /* _GL_STDCKDINT_H */
diff --git a/lib/stddef.in.h b/lib/stddef.in.h
index 758ccf63386..5c9a747d7d2 100644
--- a/lib/stddef.in.h
+++ b/lib/stddef.in.h
@@ -1,25 +1,25 @@
/* A substitute for POSIX 2008 <stddef.h>, for platforms that have issues.
- Copyright (C) 2009-2017 Free Software Foundation, Inc.
+ Copyright (C) 2009-2022 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 file is free software: you can redistribute it and/or modify
+ it under the terms of the GNU Lesser General Public License as
+ published by the Free Software Foundation; either version 2.1 of the
+ License, or (at your option) any later version.
- This program is distributed in the hope that it will be useful,
+ This file 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.
+ GNU Lesser General Public License for more details.
- You should have received a copy of the GNU General Public License
- along with this program; if not, see <https://www.gnu.org/licenses/>. */
+ You should have received a copy of the GNU Lesser General Public License
+ along with this program. If not, see <https://www.gnu.org/licenses/>. */
/* Written by Eric Blake. */
/*
* 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
@@ -42,6 +42,13 @@
# define _GL_STDDEF_WINT_T
# endif
# @INCLUDE_NEXT@ @NEXT_STDDEF_H@
+ /* On TinyCC, make sure that the macros that indicate the special invocation
+ convention get undefined. */
+# undef __need_wchar_t
+# undef __need_size_t
+# undef __need_ptrdiff_t
+# undef __need_NULL
+# undef __need_wint_t
# endif
#else
@@ -49,6 +56,23 @@
# ifndef _@GUARD_PREFIX@_STDDEF_H
+/* On AIX 7.2, with xlc in 64-bit mode, <stddef.h> defines max_align_t to a
+ type with alignment 4, but 'long' has alignment 8. */
+# if defined _AIX && defined __LP64__
+# if !GNULIB_defined_max_align_t
+# ifdef _MAX_ALIGN_T
+/* /usr/include/stddef.h has already defined max_align_t. Override it. */
+typedef long rpl_max_align_t;
+# define max_align_t rpl_max_align_t
+# else
+/* Prevent /usr/include/stddef.h from defining max_align_t. */
+typedef long max_align_t;
+# define _MAX_ALIGN_T
+# endif
+# define GNULIB_defined_max_align_t 1
+# endif
+# endif
+
/* The include_next requires a split double-inclusion guard. */
# @INCLUDE_NEXT@ @NEXT_STDDEF_H@
@@ -83,20 +107,28 @@
/* 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).
+ Similarly on OS/2 kLIBC. */
+#if (defined _MSC_VER || (defined __KLIBC__ && !defined __LIBCN__)) \
+ && defined __cplusplus
+# include <cstddef>
+#else
+# if ! (@HAVE_MAX_ALIGN_T@ || (defined _GCC_MAX_ALIGN_T && !defined __clang__))
+# 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
+# if defined __GNUC__ || (__clang_major__ >= 4)
+# 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 +136,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 df8b37d3d49..eaa7874f539 100644
--- a/lib/stdint.in.h
+++ b/lib/stdint.in.h
@@ -1,23 +1,23 @@
-/* Copyright (C) 2001-2002, 2004-2017 Free Software Foundation, Inc.
+/* Copyright (C) 2001-2002, 2004-2022 Free Software Foundation, Inc.
Written by Paul Eggert, Bruno Haible, Sam Steingold, Peter Burwood.
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, or (at your option)
- any later version.
+ This file is free software: you can redistribute it and/or modify
+ it under the terms of the GNU Lesser General Public License as
+ published by the Free Software Foundation; either version 2.1 of the
+ License, or (at your option) any later version.
- This program is distributed in the hope that it will be useful,
+ This file 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.
+ GNU Lesser General Public License for more details.
- You should have received a copy of the GNU General Public License
- along with this program; if not, see <https://www.gnu.org/licenses/>. */
+ You should have received a copy of the GNU Lesser General Public License
+ along with this program. If not, see <https://www.gnu.org/licenses/>. */
/*
* 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
@@ -85,7 +85,7 @@
/* Override WINT_MIN and WINT_MAX if gnulib's <wchar.h> or <wctype.h> overrides
wint_t. */
-#if @GNULIB_OVERRIDES_WINT_T@
+#if @GNULIBHEADERS_OVERRIDE_WINT_T@
# undef WINT_MIN
# undef WINT_MAX
# define WINT_MIN 0x0U
@@ -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,25 @@ 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 WSL-5.4.1 <stdint.h> needs its own 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__)
+# 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 +332,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 +346,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 +494,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 */
@@ -564,11 +579,6 @@ typedef int _verify_intmax_size[sizeof (intmax_t) == sizeof (uintmax_t)
<wchar.h> -> <stdio.h> -> <getopt.h> -> <stdlib.h>, and the latter includes
<stdint.h> and assumes its types are already defined. */
# if @HAVE_WCHAR_H@ && ! (defined WCHAR_MIN && defined WCHAR_MAX)
- /* BSD/OS 4.0.1 has a bug: <stddef.h>, <stdio.h> and <time.h> must be
- included before <wchar.h>. */
-# include <stddef.h>
-# include <stdio.h>
-# include <time.h>
# define _GL_JUST_INCLUDE_SYSTEM_WCHAR_H
# include <wchar.h>
# undef _GL_JUST_INCLUDE_SYSTEM_WCHAR_H
@@ -586,17 +596,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 !@GNULIBHEADERS_OVERRIDE_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 +641,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 +665,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 8960333687e..ed32e6981ac 100644
--- a/lib/stdio-impl.h
+++ b/lib/stdio-impl.h
@@ -1,23 +1,34 @@
/* Implementation details of FILE streams.
- Copyright (C) 2007-2008, 2010-2017 Free Software Foundation, Inc.
+ Copyright (C) 2007-2008, 2010-2022 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 file is free software: you can redistribute it and/or modify
+ it under the terms of the GNU Lesser General Public License as
+ published by the Free Software Foundation; either version 2.1 of the
+ License, or (at your option) any later version.
- This program is distributed in the hope that it will be useful,
+ This file 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.
+ GNU Lesser General Public License for more details.
- You should have received a copy of the GNU General Public License
+ You should have received a copy of the GNU Lesser General Public License
along with this program. If not, see <https://www.gnu.org/licenses/>. */
/* Many stdio implementations have the same logic and therefore can share
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_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_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. */
@@ -54,25 +65,84 @@
# define _flags pub._flags
# 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,
+ see <https://android.googlesource.com/platform/bionic.git/+/e78392637d5086384a5631ddfdfa8d7ec8326ee3/libc/stdio/fileext.h>
+ and <https://android.googlesource.com/platform/bionic.git/+/e78392637d5086384a5631ddfdfa8d7ec8326ee3/libc/stdio/local.h>.
+ After this commit, the innards of FILE are hidden. */
+# define fp_ ((struct { unsigned char *_p; \
+ int _r; \
+ int _w; \
+ _gl_flags_file_t _flags; \
+ _gl_flags_file_t _file; \
+ struct { unsigned char *_base; size_t _size; } _bf; \
+ int _lbfsize; \
+ void *_cookie; \
+ void *_close; \
+ void *_read; \
+ void *_seek; \
+ void *_write; \
+ struct { unsigned char *_base; size_t _size; } _ext; \
+ unsigned char *_up; \
+ int _ur; \
+ unsigned char _ubuf[3]; \
+ unsigned char _nbuf[1]; \
+ struct { unsigned char *_base; size_t _size; } _lb; \
+ int _blksize; \
+ fpos_t _offset; \
+ /* More fields, not relevant here. */ \
+ } *) fp)
# else
# define fp_ fp
# endif
-# if (defined __NetBSD__ && __NetBSD_Version__ >= 105270000) || defined __OpenBSD__ || defined __minix || defined __ANDROID__ /* NetBSD >= 1.5ZA, OpenBSD, Minix 3, Android */
+# if (defined __NetBSD__ && __NetBSD_Version__ >= 105270000) || defined __OpenBSD__ || defined __minix /* NetBSD >= 1.5ZA, OpenBSD, Minix 3 */
/* See <http://cvsweb.netbsd.org/bsdweb.cgi/src/lib/libc/stdio/fileext.h?rev=HEAD&content-type=text/x-cvsweb-markup>
- and <https://cvsweb.openbsd.org/cgi-bin/cvsweb/src/lib/libc/stdio/fileext.h?rev=HEAD&content-type=text/x-cvsweb-markup> */
+ and <https://cvsweb.openbsd.org/cgi-bin/cvsweb/src/lib/libc/stdio/fileext.h?rev=HEAD&content-type=text/x-cvsweb-markup>
+ and <https://github.com/Stichting-MINIX-Research-Foundation/minix/blob/master/lib/libc/stdio/fileext.h> */
struct __sfileext
{
struct __sbuf _ub; /* ungetc buffer */
/* More fields, not relevant here. */
};
# define fp_ub ((struct __sfileext *) fp->_ext._base)->_ub
-# else /* FreeBSD, NetBSD <= 1.5Z, DragonFly, Mac OS X, Cygwin, Android */
+# elif defined __ANDROID__ /* Android */
+ struct __sfileext
+ {
+ struct { unsigned char *_base; size_t _size; } _ub; /* ungetc buffer */
+ /* More fields, not relevant here. */
+ };
+# define fp_ub ((struct __sfileext *) fp_->_ext._base)->_ub
+# else /* FreeBSD, NetBSD <= 1.5Z, DragonFly, Mac OS X, Cygwin */
# define fp_ub fp_->_ub
# endif
# define HASUB(fp) (fp_ub._base != NULL)
+# if defined __ANDROID__ /* Android */
+ /* Needed after this commit from 2016-01-25
+ <https://android.googlesource.com/platform/bionic.git/+/e70e0e9267d069bf56a5078c99307e08a7280de7> */
+# ifndef __SEOF
+# define __SLBF 1
+# define __SNBF 2
+# define __SRD 4
+# define __SWR 8
+# define __SRW 0x10
+# define __SEOF 0x20
+# define __SERR 0x40
+# endif
+# ifndef __SOFF
+# define __SOFF 0x1000
+# endif
+# endif
+
#endif
@@ -81,7 +151,7 @@
#ifdef __TANDEM /* NonStop Kernel */
# ifndef _IOERR
/* These values were determined by the program 'stdioext-flags' at
- <https://lists.gnu.org/archive/html/bug-gnulib/2010-12/msg00165.html>. */
+ <https://lists.gnu.org/r/bug-gnulib/2010-12/msg00165.html>. */
# define _IOERR 0x40
# define _IOREAD 0x80
# define _IOWRT 0x4
@@ -105,14 +175,14 @@
# define fp_ fp
# endif
-# if defined _SCO_DS /* OpenServer */
+# if defined _SCO_DS || (defined __SCO_VERSION__ || defined __sysv5__) /* OpenServer 5, OpenServer 6, UnixWare 7 */
# define _cnt __cnt
# define _ptr __ptr
# define _base __base
# define _flag __flag
# endif
-#elif (defined _WIN32 || defined __WIN32__) && ! defined __CYGWIN__ /* newer Windows with MSVC */
+#elif defined _WIN32 && ! defined __CYGWIN__ /* newer Windows with MSVC */
/* <stdio.h> does not define the innards of FILE any more. */
# define WINDOWS_OPAQUE_FILE
@@ -132,7 +202,7 @@ struct _gl_real_FILE
# define fp_ ((struct _gl_real_FILE *) fp)
/* These values were determined by a program similar to the one at
- <https://lists.gnu.org/archive/html/bug-gnulib/2010-12/msg00165.html>. */
+ <https://lists.gnu.org/r/bug-gnulib/2010-12/msg00165.html>. */
# define _IOREAD 0x1
# define _IOWRT 0x2
# define _IORW 0x4
diff --git a/lib/stdio.in.h b/lib/stdio.in.h
index 066e08eba9a..7b36dac2f52 100644
--- a/lib/stdio.in.h
+++ b/lib/stdio.in.h
@@ -1,19 +1,19 @@
/* A GNU-like <stdio.h>.
- Copyright (C) 2004, 2007-2017 Free Software Foundation, Inc.
+ Copyright (C) 2004, 2007-2022 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 file is free software: you can redistribute it and/or modify
+ it under the terms of the GNU Lesser General Public License as
+ published by the Free Software Foundation; either version 2.1 of the
+ License, or (at your option) any later version.
- This program is distributed in the hope that it will be useful,
+ This file 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.
+ GNU Lesser General Public License for more details.
- You should have received a copy of the GNU General Public License
- along with this program; if not, see <https://www.gnu.org/licenses/>. */
+ You should have received a copy of the GNU Lesser General Public License
+ along with this program. If not, see <https://www.gnu.org/licenses/>. */
#if __GNUC__ >= 3
@PRAGMA_SYSTEM_HEADER@
@@ -56,41 +56,103 @@
May also define off_t to a 64-bit type on native Windows. */
#include <sys/types.h>
+/* Solaris 10 and NetBSD 7.0 declare renameat in <unistd.h>, not in <stdio.h>. */
+/* But in any case avoid namespace pollution on glibc systems. */
+#if (@GNULIB_RENAMEAT@ || defined GNULIB_POSIXCHECK) && (defined __sun || defined __NetBSD__) \
+ && ! defined __GLIBC__
+# 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. */
+#if (@GNULIB_PERROR@ || defined GNULIB_POSIXCHECK) \
+ && (defined _WIN32 && ! defined __CYGWIN__) \
+ && ! defined __GLIBC__
+# include <stdlib.h>
+#endif
+
+/* MSVC declares 'remove' in <io.h>, not in <stdio.h>. We must include
+ it before we #define remove rpl_remove. */
+/* MSVC declares 'rename' in <io.h>, not in <stdio.h>. We must include
+ it before we #define rename rpl_rename. */
+/* But in any case avoid namespace pollution on glibc systems. */
+#if (@GNULIB_REMOVE@ || @GNULIB_RENAME@ || defined GNULIB_POSIXCHECK) \
+ && (defined _WIN32 && ! defined __CYGWIN__) \
+ && ! defined __GLIBC__
+# include <io.h>
+#endif
+
+
+/* _GL_ATTRIBUTE_DEALLOC (F, I) declares that the function returns pointers
+ that can be freed by passing them as the Ith argument to the
+ function F. */
+#ifndef _GL_ATTRIBUTE_DEALLOC
+# if __GNUC__ >= 11
+# define _GL_ATTRIBUTE_DEALLOC(f, i) __attribute__ ((__malloc__ (f, i)))
+# else
+# define _GL_ATTRIBUTE_DEALLOC(f, i)
+# endif
+#endif
+
/* The __attribute__ feature is available in gcc versions 2.5 and later.
The __-protected variants of the attributes 'format' and 'printf' are
accepted by gcc versions 2.6.4 (effectively 2.7) and later.
We enable _GL_ATTRIBUTE_FORMAT only if these are supported too, because
gnulib and libintl do '#define printf __printf__' when they override
the 'printf' function. */
-#if __GNUC__ > 2 || (__GNUC__ == 2 && __GNUC_MINOR__ >= 7)
-# define _GL_ATTRIBUTE_FORMAT(spec) __attribute__ ((__format__ spec))
+#ifndef _GL_ATTRIBUTE_FORMAT
+# if __GNUC__ > 2 || (__GNUC__ == 2 && __GNUC_MINOR__ >= 7) || defined __clang__
+# define _GL_ATTRIBUTE_FORMAT(spec) __attribute__ ((__format__ spec))
+# else
+# define _GL_ATTRIBUTE_FORMAT(spec) /* empty */
+# endif
+#endif
+
+/* An __attribute__ __format__ specifier for a function that takes a format
+ string and arguments, where the format string directives are the ones
+ standardized by ISO C99 and POSIX.
+ _GL_ATTRIBUTE_SPEC_PRINTF_STANDARD */
+/* __gnu_printf__ is supported in GCC >= 4.4. */
+#if __GNUC__ > 4 || (__GNUC__ == 4 && __GNUC_MINOR__ >= 4)
+# define _GL_ATTRIBUTE_SPEC_PRINTF_STANDARD __gnu_printf__
#else
-# define _GL_ATTRIBUTE_FORMAT(spec) /* empty */
+# define _GL_ATTRIBUTE_SPEC_PRINTF_STANDARD __printf__
#endif
-/* _GL_ATTRIBUTE_FORMAT_PRINTF
+/* An __attribute__ __format__ specifier for a function that takes a format
+ string and arguments, where the format string directives are the ones of the
+ system printf(), rather than the ones standardized by ISO C99 and POSIX.
+ _GL_ATTRIBUTE_SPEC_PRINTF_SYSTEM */
+/* On mingw, Gnulib sets __USE_MINGW_ANSI_STDIO in order to get closer to
+ the standards. The macro GNULIB_PRINTF_ATTRIBUTE_FLAVOR_GNU indicates
+ whether this change is effective. On older mingw, it is not. */
+#if GNULIB_PRINTF_ATTRIBUTE_FLAVOR_GNU
+# define _GL_ATTRIBUTE_SPEC_PRINTF_SYSTEM _GL_ATTRIBUTE_SPEC_PRINTF_STANDARD
+#else
+# define _GL_ATTRIBUTE_SPEC_PRINTF_SYSTEM __printf__
+#endif
+
+/* _GL_ATTRIBUTE_FORMAT_PRINTF_STANDARD
indicates to GCC that the function takes a format string and arguments,
where the format string directives are the ones standardized by ISO C99
and POSIX. */
-#if __GNUC__ > 4 || (__GNUC__ == 4 && __GNUC_MINOR__ >= 4)
-# define _GL_ATTRIBUTE_FORMAT_PRINTF(formatstring_parameter, first_argument) \
- _GL_ATTRIBUTE_FORMAT ((__gnu_printf__, formatstring_parameter, first_argument))
-#else
-# define _GL_ATTRIBUTE_FORMAT_PRINTF(formatstring_parameter, first_argument) \
- _GL_ATTRIBUTE_FORMAT ((__printf__, formatstring_parameter, first_argument))
-#endif
+#define _GL_ATTRIBUTE_FORMAT_PRINTF_STANDARD(formatstring_parameter, first_argument) \
+ _GL_ATTRIBUTE_FORMAT ((_GL_ATTRIBUTE_SPEC_PRINTF_STANDARD, formatstring_parameter, first_argument))
-/* _GL_ATTRIBUTE_FORMAT_PRINTF_SYSTEM is like _GL_ATTRIBUTE_FORMAT_PRINTF,
+/* _GL_ATTRIBUTE_FORMAT_PRINTF_SYSTEM is like _GL_ATTRIBUTE_FORMAT_PRINTF_STANDARD,
except that it indicates to GCC that the supported format string directives
are the ones of the system printf(), rather than the ones standardized by
ISO C99 and POSIX. */
-#if GNULIB_PRINTF_ATTRIBUTE_FLAVOR_GNU
-# define _GL_ATTRIBUTE_FORMAT_PRINTF_SYSTEM(formatstring_parameter, first_argument) \
- _GL_ATTRIBUTE_FORMAT_PRINTF (formatstring_parameter, first_argument)
-#else
-# define _GL_ATTRIBUTE_FORMAT_PRINTF_SYSTEM(formatstring_parameter, first_argument) \
- _GL_ATTRIBUTE_FORMAT ((__printf__, formatstring_parameter, first_argument))
-#endif
+#define _GL_ATTRIBUTE_FORMAT_PRINTF_SYSTEM(formatstring_parameter, first_argument) \
+ _GL_ATTRIBUTE_FORMAT ((_GL_ATTRIBUTE_SPEC_PRINTF_SYSTEM, formatstring_parameter, first_argument))
/* _GL_ATTRIBUTE_FORMAT_SCANF
indicates to GCC that the function takes a format string and arguments,
@@ -111,34 +173,6 @@
#define _GL_ATTRIBUTE_FORMAT_SCANF_SYSTEM(formatstring_parameter, first_argument) \
_GL_ATTRIBUTE_FORMAT ((__scanf__, formatstring_parameter, first_argument))
-/* Solaris 10 and NetBSD 7.0 declare renameat in <unistd.h>, not in <stdio.h>. */
-/* But in any case avoid namespace pollution on glibc systems. */
-#if (@GNULIB_RENAMEAT@ || defined GNULIB_POSIXCHECK) && (defined __sun || defined __NetBSD__) \
- && ! defined __GLIBC__
-# include <unistd.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. */
-#if (@GNULIB_PERROR@ || defined GNULIB_POSIXCHECK) \
- && ((defined _WIN32 || defined __WIN32__) && ! defined __CYGWIN__) \
- && ! defined __GLIBC__
-# include <stdlib.h>
-#endif
-
-/* MSVC declares 'remove' in <io.h>, not in <stdio.h>. We must include
- it before we #define remove rpl_remove. */
-/* MSVC declares 'rename' in <io.h>, not in <stdio.h>. We must include
- it before we #define rename rpl_rename. */
-/* But in any case avoid namespace pollution on glibc systems. */
-#if (@GNULIB_REMOVE@ || @GNULIB_RENAME@ || defined GNULIB_POSIXCHECK) \
- && ((defined _WIN32 || defined __WIN32__) && ! defined __CYGWIN__) \
- && ! defined __GLIBC__
-# include <io.h>
-#endif
-
-
/* The definitions of _GL_FUNCDECL_RPL etc. are copied here. */
/* The definition of _GL_ARG_NONNULL is copied here. */
@@ -152,7 +186,7 @@
/* When also using extern inline, suppress the use of static inline in
standard headers of problematic Apple configurations, as Libc at
least through Libc-825.26 (2013-04-09) mishandles it; see, e.g.,
- <https://lists.gnu.org/archive/html/bug-gnulib/2012-12/msg00023.html>.
+ <https://lists.gnu.org/r/bug-gnulib/2012-12/msg00023.html>.
Perhaps Apple will fix this some day. */
#if (defined _GL_EXTERN_INLINE_IN_USE && defined __APPLE__ \
&& defined __GNUC__ && defined __STDC__)
@@ -164,17 +198,17 @@
# if !(defined __cplusplus && defined GNULIB_NAMESPACE)
# define dprintf rpl_dprintf
# endif
-_GL_FUNCDECL_RPL (dprintf, int, (int fd, const char *format, ...)
- _GL_ATTRIBUTE_FORMAT_PRINTF (2, 3)
+_GL_FUNCDECL_RPL (dprintf, int, (int fd, const char *restrict format, ...)
+ _GL_ATTRIBUTE_FORMAT_PRINTF_STANDARD (2, 3)
_GL_ARG_NONNULL ((2)));
-_GL_CXXALIAS_RPL (dprintf, int, (int fd, const char *format, ...));
+_GL_CXXALIAS_RPL (dprintf, int, (int fd, const char *restrict format, ...));
# else
# if !@HAVE_DPRINTF@
-_GL_FUNCDECL_SYS (dprintf, int, (int fd, const char *format, ...)
- _GL_ATTRIBUTE_FORMAT_PRINTF (2, 3)
+_GL_FUNCDECL_SYS (dprintf, int, (int fd, const char *restrict format, ...)
+ _GL_ATTRIBUTE_FORMAT_PRINTF_STANDARD (2, 3)
_GL_ARG_NONNULL ((2)));
# endif
-_GL_CXXALIAS_SYS (dprintf, int, (int fd, const char *format, ...));
+_GL_CXXALIAS_SYS (dprintf, int, (int fd, const char *restrict format, ...));
# endif
_GL_CXXALIASWARN (dprintf);
#elif defined GNULIB_POSIXCHECK
@@ -196,7 +230,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. */
@@ -204,24 +240,84 @@ _GL_WARN_ON_USE (fclose, "fclose is not always POSIX compliant - "
"use gnulib module fclose for portable POSIX compliance");
#endif
+#if @GNULIB_MDA_FCLOSEALL@
+/* On native Windows, map 'fcloseall' to '_fcloseall', so that -loldnames is
+ not required. In C++ with GNULIB_NAMESPACE, avoid differences between
+ platforms by defining GNULIB_NAMESPACE::fcloseall on all platforms that have
+ it. */
+# if defined _WIN32 && !defined __CYGWIN__
+# if !(defined __cplusplus && defined GNULIB_NAMESPACE)
+# undef fcloseall
+# define fcloseall _fcloseall
+# endif
+_GL_CXXALIAS_MDA (fcloseall, int, (void));
+# else
+# if @HAVE_DECL_FCLOSEALL@
+# if defined __FreeBSD__ || defined __DragonFly__
+_GL_CXXALIAS_SYS (fcloseall, void, (void));
+# else
+_GL_CXXALIAS_SYS (fcloseall, int, (void));
+# endif
+# endif
+# endif
+# if (defined _WIN32 && !defined __CYGWIN__) || @HAVE_DECL_FCLOSEALL@
+_GL_CXXALIASWARN (fcloseall);
+# endif
+#endif
+
#if @GNULIB_FDOPEN@
# if @REPLACE_FDOPEN@
# if !(defined __cplusplus && defined GNULIB_NAMESPACE)
# undef fdopen
# define fdopen rpl_fdopen
# endif
-_GL_FUNCDECL_RPL (fdopen, FILE *, (int fd, const char *mode)
- _GL_ARG_NONNULL ((2)));
+_GL_FUNCDECL_RPL (fdopen, FILE *,
+ (int fd, const char *mode)
+ _GL_ARG_NONNULL ((2)) _GL_ATTRIBUTE_DEALLOC (fclose, 1));
_GL_CXXALIAS_RPL (fdopen, FILE *, (int fd, const char *mode));
+# elif defined _WIN32 && !defined __CYGWIN__
+# if !(defined __cplusplus && defined GNULIB_NAMESPACE)
+# undef fdopen
+# define fdopen _fdopen
+# endif
+_GL_CXXALIAS_MDA (fdopen, FILE *, (int fd, const char *mode));
# else
+# if __GNUC__ >= 11
+/* For -Wmismatched-dealloc: Associate fdopen with fclose or rpl_fclose. */
+_GL_FUNCDECL_SYS (fdopen, FILE *,
+ (int fd, const char *mode)
+ _GL_ARG_NONNULL ((2)) _GL_ATTRIBUTE_DEALLOC (fclose, 1));
+# endif
_GL_CXXALIAS_SYS (fdopen, FILE *, (int fd, const char *mode));
# endif
_GL_CXXALIASWARN (fdopen);
-#elif defined GNULIB_POSIXCHECK
-# undef fdopen
+#else
+# if @GNULIB_FCLOSE@ && __GNUC__ >= 11 && !defined fdopen
+/* For -Wmismatched-dealloc: Associate fdopen with fclose or rpl_fclose. */
+_GL_FUNCDECL_SYS (fdopen, FILE *,
+ (int fd, const char *mode)
+ _GL_ARG_NONNULL ((2)) _GL_ATTRIBUTE_DEALLOC (fclose, 1));
+# endif
+# if defined GNULIB_POSIXCHECK
+# undef fdopen
/* Assume fdopen is always declared. */
_GL_WARN_ON_USE (fdopen, "fdopen on native Windows platforms is not POSIX compliant - "
"use gnulib module fdopen for portability");
+# elif @GNULIB_MDA_FDOPEN@
+/* On native Windows, map 'fdopen' to '_fdopen', so that -loldnames is not
+ required. In C++ with GNULIB_NAMESPACE, avoid differences between
+ platforms by defining GNULIB_NAMESPACE::fdopen always. */
+# if defined _WIN32 && !defined __CYGWIN__
+# if !(defined __cplusplus && defined GNULIB_NAMESPACE)
+# undef fdopen
+# define fdopen _fdopen
+# endif
+_GL_CXXALIAS_MDA (fdopen, FILE *, (int fd, const char *mode));
+# else
+_GL_CXXALIAS_SYS (fdopen, FILE *, (int fd, const char *mode));
+# endif
+_GL_CXXALIASWARN (fdopen);
+# endif
#endif
#if @GNULIB_FFLUSH@
@@ -240,7 +336,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 +357,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@
@@ -268,33 +368,74 @@ _GL_CXXALIASWARN (fgetc);
# undef fgets
# define fgets rpl_fgets
# endif
-_GL_FUNCDECL_RPL (fgets, char *, (char *s, int n, FILE *stream)
- _GL_ARG_NONNULL ((1, 3)));
-_GL_CXXALIAS_RPL (fgets, char *, (char *s, int n, FILE *stream));
+_GL_FUNCDECL_RPL (fgets, char *,
+ (char *restrict s, int n, FILE *restrict stream)
+ _GL_ARG_NONNULL ((1, 3)));
+_GL_CXXALIAS_RPL (fgets, char *,
+ (char *restrict s, int n, FILE *restrict stream));
# else
-_GL_CXXALIAS_SYS (fgets, char *, (char *s, int n, FILE *stream));
+_GL_CXXALIAS_SYS (fgets, char *,
+ (char *restrict s, int n, FILE *restrict stream));
# endif
+# if __GLIBC__ >= 2
_GL_CXXALIASWARN (fgets);
+# endif
+#endif
+
+#if @GNULIB_MDA_FILENO@
+/* On native Windows, map 'fileno' to '_fileno', so that -loldnames is not
+ required. In C++ with GNULIB_NAMESPACE, avoid differences between
+ platforms by defining GNULIB_NAMESPACE::fileno always. */
+# if defined _WIN32 && !defined __CYGWIN__
+# if !(defined __cplusplus && defined GNULIB_NAMESPACE)
+# undef fileno
+# define fileno _fileno
+# endif
+_GL_CXXALIAS_MDA (fileno, int, (FILE *restrict stream));
+# else
+_GL_CXXALIAS_SYS (fileno, int, (FILE *restrict stream));
+# endif
+_GL_CXXALIASWARN (fileno);
#endif
#if @GNULIB_FOPEN@
-# if @REPLACE_FOPEN@
+# if (@GNULIB_FOPEN@ && @REPLACE_FOPEN@) \
+ || (@GNULIB_FOPEN_GNU@ && @REPLACE_FOPEN_FOR_FOPEN_GNU@)
# if !(defined __cplusplus && defined GNULIB_NAMESPACE)
# undef fopen
# define fopen rpl_fopen
# endif
-_GL_FUNCDECL_RPL (fopen, FILE *, (const char *filename, const char *mode)
- _GL_ARG_NONNULL ((1, 2)));
-_GL_CXXALIAS_RPL (fopen, FILE *, (const char *filename, const char *mode));
+_GL_FUNCDECL_RPL (fopen, FILE *,
+ (const char *restrict filename, const char *restrict mode)
+ _GL_ARG_NONNULL ((1, 2)) _GL_ATTRIBUTE_DEALLOC (fclose, 1));
+_GL_CXXALIAS_RPL (fopen, FILE *,
+ (const char *restrict filename, const char *restrict mode));
# else
-_GL_CXXALIAS_SYS (fopen, FILE *, (const char *filename, const char *mode));
+# if __GNUC__ >= 11
+/* For -Wmismatched-dealloc: Associate fopen with fclose or rpl_fclose. */
+_GL_FUNCDECL_SYS (fopen, FILE *,
+ (const char *restrict filename, const char *restrict mode)
+ _GL_ARG_NONNULL ((1, 2)) _GL_ATTRIBUTE_DEALLOC (fclose, 1));
+# endif
+_GL_CXXALIAS_SYS (fopen, FILE *,
+ (const char *restrict filename, const char *restrict mode));
# endif
+# if __GLIBC__ >= 2
_GL_CXXALIASWARN (fopen);
-#elif defined GNULIB_POSIXCHECK
-# undef fopen
+# endif
+#else
+# if @GNULIB_FCLOSE@ && __GNUC__ >= 11 && !defined fopen
+/* For -Wmismatched-dealloc: Associate fopen with fclose or rpl_fclose. */
+_GL_FUNCDECL_SYS (fopen, FILE *,
+ (const char *restrict filename, const char *restrict mode)
+ _GL_ARG_NONNULL ((1, 2)) _GL_ATTRIBUTE_DEALLOC (fclose, 1));
+# endif
+# if defined GNULIB_POSIXCHECK
+# undef fopen
/* Assume fopen is always declared. */
_GL_WARN_ON_USE (fopen, "fopen on native Windows platforms is not POSIX compliant - "
"use gnulib module fopen for portability");
+# endif
#endif
#if @GNULIB_FPRINTF_POSIX@ || @GNULIB_FPRINTF@
@@ -305,19 +446,25 @@ _GL_WARN_ON_USE (fopen, "fopen on native Windows platforms is not POSIX complian
# endif
# define GNULIB_overrides_fprintf 1
# if @GNULIB_FPRINTF_POSIX@ || @GNULIB_VFPRINTF_POSIX@
-_GL_FUNCDECL_RPL (fprintf, int, (FILE *fp, const char *format, ...)
- _GL_ATTRIBUTE_FORMAT_PRINTF (2, 3)
- _GL_ARG_NONNULL ((1, 2)));
+_GL_FUNCDECL_RPL (fprintf, int,
+ (FILE *restrict fp, const char *restrict format, ...)
+ _GL_ATTRIBUTE_FORMAT_PRINTF_STANDARD (2, 3)
+ _GL_ARG_NONNULL ((1, 2)));
# else
-_GL_FUNCDECL_RPL (fprintf, int, (FILE *fp, const char *format, ...)
- _GL_ATTRIBUTE_FORMAT_PRINTF_SYSTEM (2, 3)
- _GL_ARG_NONNULL ((1, 2)));
+_GL_FUNCDECL_RPL (fprintf, int,
+ (FILE *restrict fp, const char *restrict format, ...)
+ _GL_ATTRIBUTE_FORMAT_PRINTF_SYSTEM (2, 3)
+ _GL_ARG_NONNULL ((1, 2)));
# endif
-_GL_CXXALIAS_RPL (fprintf, int, (FILE *fp, const char *format, ...));
+_GL_CXXALIAS_RPL (fprintf, int,
+ (FILE *restrict fp, const char *restrict format, ...));
# else
-_GL_CXXALIAS_SYS (fprintf, int, (FILE *fp, const char *format, ...));
+_GL_CXXALIAS_SYS (fprintf, int,
+ (FILE *restrict fp, const char *restrict format, ...));
# endif
+# if __GLIBC__ >= 2
_GL_CXXALIASWARN (fprintf);
+# endif
#endif
#if !@GNULIB_FPRINTF_POSIX@ && defined GNULIB_POSIXCHECK
# if !GNULIB_overrides_fprintf
@@ -368,7 +515,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@
@@ -377,13 +526,18 @@ _GL_CXXALIASWARN (fputc);
# undef fputs
# define fputs rpl_fputs
# endif
-_GL_FUNCDECL_RPL (fputs, int, (const char *string, FILE *stream)
- _GL_ARG_NONNULL ((1, 2)));
-_GL_CXXALIAS_RPL (fputs, int, (const char *string, FILE *stream));
+_GL_FUNCDECL_RPL (fputs, int,
+ (const char *restrict string, FILE *restrict stream)
+ _GL_ARG_NONNULL ((1, 2)));
+_GL_CXXALIAS_RPL (fputs, int,
+ (const char *restrict string, FILE *restrict stream));
# else
-_GL_CXXALIAS_SYS (fputs, int, (const char *string, FILE *stream));
+_GL_CXXALIAS_SYS (fputs, int,
+ (const char *restrict string, FILE *restrict stream));
# endif
+# if __GLIBC__ >= 2
_GL_CXXALIASWARN (fputs);
+# endif
#endif
#if @GNULIB_FREAD@
@@ -392,13 +546,21 @@ _GL_CXXALIASWARN (fputs);
# undef fread
# define fread rpl_fread
# endif
-_GL_FUNCDECL_RPL (fread, size_t, (void *ptr, size_t s, size_t n, FILE *stream)
- _GL_ARG_NONNULL ((4)));
-_GL_CXXALIAS_RPL (fread, size_t, (void *ptr, size_t s, size_t n, FILE *stream));
+_GL_FUNCDECL_RPL (fread, size_t,
+ (void *restrict ptr, size_t s, size_t n,
+ FILE *restrict stream)
+ _GL_ARG_NONNULL ((4)));
+_GL_CXXALIAS_RPL (fread, size_t,
+ (void *restrict ptr, size_t s, size_t n,
+ FILE *restrict stream));
# else
-_GL_CXXALIAS_SYS (fread, size_t, (void *ptr, size_t s, size_t n, FILE *stream));
+_GL_CXXALIAS_SYS (fread, size_t,
+ (void *restrict ptr, size_t s, size_t n,
+ FILE *restrict stream));
# endif
+# if __GLIBC__ >= 2
_GL_CXXALIASWARN (fread);
+# endif
#endif
#if @GNULIB_FREOPEN@
@@ -408,15 +570,20 @@ _GL_CXXALIASWARN (fread);
# define freopen rpl_freopen
# endif
_GL_FUNCDECL_RPL (freopen, FILE *,
- (const char *filename, const char *mode, FILE *stream)
+ (const char *restrict filename, const char *restrict mode,
+ FILE *restrict stream)
_GL_ARG_NONNULL ((2, 3)));
_GL_CXXALIAS_RPL (freopen, FILE *,
- (const char *filename, const char *mode, FILE *stream));
+ (const char *restrict filename, const char *restrict mode,
+ FILE *restrict stream));
# else
_GL_CXXALIAS_SYS (freopen, FILE *,
- (const char *filename, const char *mode, FILE *stream));
+ (const char *restrict filename, const char *restrict mode,
+ FILE *restrict stream));
# endif
+# if __GLIBC__ >= 2
_GL_CXXALIASWARN (freopen);
+# endif
#elif defined GNULIB_POSIXCHECK
# undef freopen
/* Assume freopen is always declared. */
@@ -431,14 +598,19 @@ _GL_WARN_ON_USE (freopen,
# undef fscanf
# define fscanf rpl_fscanf
# endif
-_GL_FUNCDECL_RPL (fscanf, int, (FILE *stream, const char *format, ...)
- _GL_ATTRIBUTE_FORMAT_SCANF_SYSTEM (2, 3)
- _GL_ARG_NONNULL ((1, 2)));
-_GL_CXXALIAS_RPL (fscanf, int, (FILE *stream, const char *format, ...));
+_GL_FUNCDECL_RPL (fscanf, int,
+ (FILE *restrict stream, const char *restrict format, ...)
+ _GL_ATTRIBUTE_FORMAT_SCANF_SYSTEM (2, 3)
+ _GL_ARG_NONNULL ((1, 2)));
+_GL_CXXALIAS_RPL (fscanf, int,
+ (FILE *restrict stream, const char *restrict format, ...));
# else
-_GL_CXXALIAS_SYS (fscanf, int, (FILE *stream, const char *format, ...));
+_GL_CXXALIAS_SYS (fscanf, int,
+ (FILE *restrict stream, const char *restrict format, ...));
# endif
+# if __GLIBC__ >= 2
_GL_CXXALIASWARN (fscanf);
+# endif
#endif
@@ -489,7 +661,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 +726,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@
@@ -601,13 +777,16 @@ _GL_WARN_ON_USE (ftell, "ftell cannot handle files larger than 4 GB "
# define fwrite rpl_fwrite
# endif
_GL_FUNCDECL_RPL (fwrite, size_t,
- (const void *ptr, size_t s, size_t n, FILE *stream)
+ (const void *restrict ptr, size_t s, size_t n,
+ FILE *restrict stream)
_GL_ARG_NONNULL ((1, 4)));
_GL_CXXALIAS_RPL (fwrite, size_t,
- (const void *ptr, size_t s, size_t n, FILE *stream));
+ (const void *restrict ptr, size_t s, size_t n,
+ FILE *restrict stream));
# else
_GL_CXXALIAS_SYS (fwrite, size_t,
- (const void *ptr, size_t s, size_t n, FILE *stream));
+ (const void *restrict ptr, size_t s, size_t n,
+ FILE *restrict stream));
/* Work around bug 11959 when fortifying glibc 2.4 through 2.15
<https://sourceware.org/bugzilla/show_bug.cgi?id=11959>,
@@ -632,7 +811,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 +827,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 +843,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@
@@ -676,22 +861,26 @@ _GL_CXXALIASWARN (getchar);
# define getdelim rpl_getdelim
# endif
_GL_FUNCDECL_RPL (getdelim, ssize_t,
- (char **lineptr, size_t *linesize, int delimiter,
- FILE *stream)
+ (char **restrict lineptr, size_t *restrict linesize,
+ int delimiter,
+ FILE *restrict stream)
_GL_ARG_NONNULL ((1, 2, 4)));
_GL_CXXALIAS_RPL (getdelim, ssize_t,
- (char **lineptr, size_t *linesize, int delimiter,
- FILE *stream));
+ (char **restrict lineptr, size_t *restrict linesize,
+ int delimiter,
+ FILE *restrict stream));
# else
# if !@HAVE_DECL_GETDELIM@
_GL_FUNCDECL_SYS (getdelim, ssize_t,
- (char **lineptr, size_t *linesize, int delimiter,
- FILE *stream)
+ (char **restrict lineptr, size_t *restrict linesize,
+ int delimiter,
+ FILE *restrict stream)
_GL_ARG_NONNULL ((1, 2, 4)));
# endif
_GL_CXXALIAS_SYS (getdelim, ssize_t,
- (char **lineptr, size_t *linesize, int delimiter,
- FILE *stream));
+ (char **restrict lineptr, size_t *restrict linesize,
+ int delimiter,
+ FILE *restrict stream));
# endif
_GL_CXXALIASWARN (getdelim);
#elif defined GNULIB_POSIXCHECK
@@ -715,18 +904,22 @@ _GL_WARN_ON_USE (getdelim, "getdelim is unportable - "
# define getline rpl_getline
# endif
_GL_FUNCDECL_RPL (getline, ssize_t,
- (char **lineptr, size_t *linesize, FILE *stream)
+ (char **restrict lineptr, size_t *restrict linesize,
+ FILE *restrict stream)
_GL_ARG_NONNULL ((1, 2, 3)));
_GL_CXXALIAS_RPL (getline, ssize_t,
- (char **lineptr, size_t *linesize, FILE *stream));
+ (char **restrict lineptr, size_t *restrict linesize,
+ FILE *restrict stream));
# else
# if !@HAVE_DECL_GETLINE@
_GL_FUNCDECL_SYS (getline, ssize_t,
- (char **lineptr, size_t *linesize, FILE *stream)
+ (char **restrict lineptr, size_t *restrict linesize,
+ FILE *restrict stream)
_GL_ARG_NONNULL ((1, 2, 3)));
# endif
_GL_CXXALIAS_SYS (getline, ssize_t,
- (char **lineptr, size_t *linesize, FILE *stream));
+ (char **restrict lineptr, size_t *restrict linesize,
+ FILE *restrict stream));
# endif
# if @HAVE_DECL_GETLINE@
_GL_CXXALIASWARN (getline);
@@ -747,6 +940,22 @@ _GL_WARN_ON_USE (getline, "getline is unportable - "
_GL_WARN_ON_USE (gets, "gets is a security hole - use fgets instead");
#endif
+#if @GNULIB_MDA_GETW@
+/* On native Windows, map 'getw' to '_getw', so that -loldnames is not
+ required. In C++ with GNULIB_NAMESPACE, avoid differences between
+ platforms by defining GNULIB_NAMESPACE::getw always. */
+# if defined _WIN32 && !defined __CYGWIN__
+# if !(defined __cplusplus && defined GNULIB_NAMESPACE)
+# undef getw
+# define getw _getw
+# endif
+_GL_CXXALIAS_MDA (getw, int, (FILE *restrict stream));
+# else
+_GL_CXXALIAS_SYS (getw, int, (FILE *restrict stream));
+# endif
+_GL_CXXALIASWARN (getw);
+#endif
+
#if @GNULIB_OBSTACK_PRINTF@ || @GNULIB_OBSTACK_PRINTF_POSIX@
struct obstack;
/* Grow an obstack with formatted output. Return the number of
@@ -760,7 +969,7 @@ struct obstack;
# endif
_GL_FUNCDECL_RPL (obstack_printf, int,
(struct obstack *obs, const char *format, ...)
- _GL_ATTRIBUTE_FORMAT_PRINTF (2, 3)
+ _GL_ATTRIBUTE_FORMAT_PRINTF_STANDARD (2, 3)
_GL_ARG_NONNULL ((1, 2)));
_GL_CXXALIAS_RPL (obstack_printf, int,
(struct obstack *obs, const char *format, ...));
@@ -768,7 +977,7 @@ _GL_CXXALIAS_RPL (obstack_printf, int,
# if !@HAVE_DECL_OBSTACK_PRINTF@
_GL_FUNCDECL_SYS (obstack_printf, int,
(struct obstack *obs, const char *format, ...)
- _GL_ATTRIBUTE_FORMAT_PRINTF (2, 3)
+ _GL_ATTRIBUTE_FORMAT_PRINTF_STANDARD (2, 3)
_GL_ARG_NONNULL ((1, 2)));
# endif
_GL_CXXALIAS_SYS (obstack_printf, int,
@@ -781,7 +990,7 @@ _GL_CXXALIASWARN (obstack_printf);
# endif
_GL_FUNCDECL_RPL (obstack_vprintf, int,
(struct obstack *obs, const char *format, va_list args)
- _GL_ATTRIBUTE_FORMAT_PRINTF (2, 0)
+ _GL_ATTRIBUTE_FORMAT_PRINTF_STANDARD (2, 0)
_GL_ARG_NONNULL ((1, 2)));
_GL_CXXALIAS_RPL (obstack_vprintf, int,
(struct obstack *obs, const char *format, va_list args));
@@ -789,7 +998,7 @@ _GL_CXXALIAS_RPL (obstack_vprintf, int,
# if !@HAVE_DECL_OBSTACK_PRINTF@
_GL_FUNCDECL_SYS (obstack_vprintf, int,
(struct obstack *obs, const char *format, va_list args)
- _GL_ATTRIBUTE_FORMAT_PRINTF (2, 0)
+ _GL_ATTRIBUTE_FORMAT_PRINTF_STANDARD (2, 0)
_GL_ARG_NONNULL ((1, 2)));
# endif
_GL_CXXALIAS_SYS (obstack_vprintf, int,
@@ -825,7 +1034,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. */
@@ -839,43 +1050,53 @@ _GL_WARN_ON_USE (perror, "perror is not always POSIX compliant - "
# undef popen
# define popen rpl_popen
# endif
-_GL_FUNCDECL_RPL (popen, FILE *, (const char *cmd, const char *mode)
- _GL_ARG_NONNULL ((1, 2)));
+_GL_FUNCDECL_RPL (popen, FILE *,
+ (const char *cmd, const char *mode)
+ _GL_ARG_NONNULL ((1, 2)) _GL_ATTRIBUTE_DEALLOC (pclose, 1));
_GL_CXXALIAS_RPL (popen, FILE *, (const char *cmd, const char *mode));
# else
-# if !@HAVE_POPEN@
-_GL_FUNCDECL_SYS (popen, FILE *, (const char *cmd, const char *mode)
- _GL_ARG_NONNULL ((1, 2)));
+# if !@HAVE_POPEN@ || __GNUC__ >= 11
+_GL_FUNCDECL_SYS (popen, FILE *,
+ (const char *cmd, const char *mode)
+ _GL_ARG_NONNULL ((1, 2)) _GL_ATTRIBUTE_DEALLOC (pclose, 1));
# endif
_GL_CXXALIAS_SYS (popen, FILE *, (const char *cmd, const char *mode));
# endif
_GL_CXXALIASWARN (popen);
-#elif defined GNULIB_POSIXCHECK
-# undef popen
-# if HAVE_RAW_DECL_POPEN
+#else
+# if @GNULIB_PCLOSE@ && __GNUC__ >= 11 && !defined popen
+/* For -Wmismatched-dealloc: Associate popen with pclose or rpl_pclose. */
+_GL_FUNCDECL_SYS (popen, FILE *,
+ (const char *cmd, const char *mode)
+ _GL_ARG_NONNULL ((1, 2)) _GL_ATTRIBUTE_DEALLOC (pclose, 1));
+# endif
+# if defined GNULIB_POSIXCHECK
+# undef popen
+# if HAVE_RAW_DECL_POPEN
_GL_WARN_ON_USE (popen, "popen is buggy on some platforms - "
"use gnulib module popen or pipe for more portability");
+# endif
# endif
#endif
#if @GNULIB_PRINTF_POSIX@ || @GNULIB_PRINTF@
# if (@GNULIB_PRINTF_POSIX@ && @REPLACE_PRINTF@) \
|| (@GNULIB_PRINTF@ && @REPLACE_STDIO_WRITE_FUNCS@ && (@GNULIB_STDIO_H_NONBLOCKING@ || @GNULIB_STDIO_H_SIGPIPE@))
-# if defined __GNUC__
+# if defined __GNUC__ || defined __clang__
# if !(defined __cplusplus && defined GNULIB_NAMESPACE)
/* Don't break __attribute__((format(printf,M,N))). */
# define printf __printf__
# endif
# if @GNULIB_PRINTF_POSIX@ || @GNULIB_VFPRINTF_POSIX@
_GL_FUNCDECL_RPL_1 (__printf__, int,
- (const char *format, ...)
+ (const char *restrict format, ...)
__asm__ (@ASM_SYMBOL_PREFIX@
_GL_STDIO_MACROEXPAND_AND_STRINGIZE(rpl_printf))
- _GL_ATTRIBUTE_FORMAT_PRINTF (1, 2)
+ _GL_ATTRIBUTE_FORMAT_PRINTF_STANDARD (1, 2)
_GL_ARG_NONNULL ((1)));
# else
_GL_FUNCDECL_RPL_1 (__printf__, int,
- (const char *format, ...)
+ (const char *restrict format, ...)
__asm__ (@ASM_SYMBOL_PREFIX@
_GL_STDIO_MACROEXPAND_AND_STRINGIZE(rpl_printf))
_GL_ATTRIBUTE_FORMAT_PRINTF_SYSTEM (1, 2)
@@ -887,16 +1108,18 @@ _GL_CXXALIAS_RPL_1 (printf, __printf__, int, (const char *format, ...));
# define printf rpl_printf
# endif
_GL_FUNCDECL_RPL (printf, int,
- (const char *format, ...)
- _GL_ATTRIBUTE_FORMAT_PRINTF (1, 2)
+ (const char *restrict format, ...)
+ _GL_ATTRIBUTE_FORMAT_PRINTF_STANDARD (1, 2)
_GL_ARG_NONNULL ((1)));
-_GL_CXXALIAS_RPL (printf, int, (const char *format, ...));
+_GL_CXXALIAS_RPL (printf, int, (const char *restrict format, ...));
# endif
# define GNULIB_overrides_printf 1
# else
-_GL_CXXALIAS_SYS (printf, int, (const char *format, ...));
+_GL_CXXALIAS_SYS (printf, int, (const char *restrict format, ...));
# endif
+# if __GLIBC__ >= 2
_GL_CXXALIASWARN (printf);
+# endif
#endif
#if !@GNULIB_PRINTF_POSIX@ && defined GNULIB_POSIXCHECK
# if !GNULIB_overrides_printf
@@ -919,7 +1142,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 +1158,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 +1174,25 @@ _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_MDA_PUTW@
+/* On native Windows, map 'putw' to '_putw', so that -loldnames is not
+ required. In C++ with GNULIB_NAMESPACE, avoid differences between
+ platforms by defining GNULIB_NAMESPACE::putw always. */
+# if defined _WIN32 && !defined __CYGWIN__
+# if !(defined __cplusplus && defined GNULIB_NAMESPACE)
+# undef putw
+# define putw _putw
+# endif
+_GL_CXXALIAS_MDA (putw, int, (int w, FILE *restrict stream));
+# else
+_GL_CXXALIAS_SYS (putw, int, (int w, FILE *restrict stream));
+# endif
+_GL_CXXALIASWARN (putw);
#endif
#if @GNULIB_REMOVE@
@@ -961,7 +1206,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 +1231,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. */
@@ -1023,33 +1272,35 @@ _GL_WARN_ON_USE (renameat, "renameat is not portable - "
#if @GNULIB_SCANF@
# if @REPLACE_STDIO_READ_FUNCS@ && @GNULIB_STDIO_H_NONBLOCKING@
-# if defined __GNUC__
+# if defined __GNUC__ || defined __clang__
# if !(defined __cplusplus && defined GNULIB_NAMESPACE)
# undef scanf
/* Don't break __attribute__((format(scanf,M,N))). */
# define scanf __scanf__
# endif
_GL_FUNCDECL_RPL_1 (__scanf__, int,
- (const char *format, ...)
+ (const char *restrict format, ...)
__asm__ (@ASM_SYMBOL_PREFIX@
_GL_STDIO_MACROEXPAND_AND_STRINGIZE(rpl_scanf))
_GL_ATTRIBUTE_FORMAT_SCANF_SYSTEM (1, 2)
_GL_ARG_NONNULL ((1)));
-_GL_CXXALIAS_RPL_1 (scanf, __scanf__, int, (const char *format, ...));
+_GL_CXXALIAS_RPL_1 (scanf, __scanf__, int, (const char *restrict format, ...));
# else
# if !(defined __cplusplus && defined GNULIB_NAMESPACE)
# undef scanf
# define scanf rpl_scanf
# endif
-_GL_FUNCDECL_RPL (scanf, int, (const char *format, ...)
+_GL_FUNCDECL_RPL (scanf, int, (const char *restrict format, ...)
_GL_ATTRIBUTE_FORMAT_SCANF_SYSTEM (1, 2)
_GL_ARG_NONNULL ((1)));
-_GL_CXXALIAS_RPL (scanf, int, (const char *format, ...));
+_GL_CXXALIAS_RPL (scanf, int, (const char *restrict format, ...));
# endif
# else
-_GL_CXXALIAS_SYS (scanf, int, (const char *format, ...));
+_GL_CXXALIAS_SYS (scanf, int, (const char *restrict format, ...));
# endif
+# if __GLIBC__ >= 2
_GL_CXXALIASWARN (scanf);
+# endif
#endif
#if @GNULIB_SNPRINTF@
@@ -1057,23 +1308,30 @@ _GL_CXXALIASWARN (scanf);
# if !(defined __cplusplus && defined GNULIB_NAMESPACE)
# define snprintf rpl_snprintf
# endif
+# define GNULIB_overrides_snprintf 1
_GL_FUNCDECL_RPL (snprintf, int,
- (char *str, size_t size, const char *format, ...)
- _GL_ATTRIBUTE_FORMAT_PRINTF (3, 4)
+ (char *restrict str, size_t size,
+ const char *restrict format, ...)
+ _GL_ATTRIBUTE_FORMAT_PRINTF_STANDARD (3, 4)
_GL_ARG_NONNULL ((3)));
_GL_CXXALIAS_RPL (snprintf, int,
- (char *str, size_t size, const char *format, ...));
+ (char *restrict str, size_t size,
+ const char *restrict format, ...));
# else
# if !@HAVE_DECL_SNPRINTF@
_GL_FUNCDECL_SYS (snprintf, int,
- (char *str, size_t size, const char *format, ...)
- _GL_ATTRIBUTE_FORMAT_PRINTF (3, 4)
+ (char *restrict str, size_t size,
+ const char *restrict format, ...)
+ _GL_ATTRIBUTE_FORMAT_PRINTF_STANDARD (3, 4)
_GL_ARG_NONNULL ((3)));
# endif
_GL_CXXALIAS_SYS (snprintf, int,
- (char *str, size_t size, const char *format, ...));
+ (char *restrict str, size_t size,
+ const char *restrict format, ...));
# endif
+# if __GLIBC__ >= 2
_GL_CXXALIASWARN (snprintf);
+# endif
#elif defined GNULIB_POSIXCHECK
# undef snprintf
# if HAVE_RAW_DECL_SNPRINTF
@@ -1096,14 +1354,20 @@ _GL_WARN_ON_USE (snprintf, "snprintf is unportable - "
# if !(defined __cplusplus && defined GNULIB_NAMESPACE)
# define sprintf rpl_sprintf
# endif
-_GL_FUNCDECL_RPL (sprintf, int, (char *str, const char *format, ...)
- _GL_ATTRIBUTE_FORMAT_PRINTF (2, 3)
- _GL_ARG_NONNULL ((1, 2)));
-_GL_CXXALIAS_RPL (sprintf, int, (char *str, const char *format, ...));
+# define GNULIB_overrides_sprintf 1
+_GL_FUNCDECL_RPL (sprintf, int,
+ (char *restrict str, const char *restrict format, ...)
+ _GL_ATTRIBUTE_FORMAT_PRINTF_STANDARD (2, 3)
+ _GL_ARG_NONNULL ((1, 2)));
+_GL_CXXALIAS_RPL (sprintf, int,
+ (char *restrict str, const char *restrict format, ...));
# else
-_GL_CXXALIAS_SYS (sprintf, int, (char *str, const char *format, ...));
+_GL_CXXALIAS_SYS (sprintf, int,
+ (char *restrict str, const char *restrict format, ...));
# endif
+# if __GLIBC__ >= 2
_GL_CXXALIASWARN (sprintf);
+# endif
#elif defined GNULIB_POSIXCHECK
# undef sprintf
/* Assume sprintf is always declared. */
@@ -1112,22 +1376,53 @@ _GL_WARN_ON_USE (sprintf, "sprintf is not always POSIX compliant - "
"POSIX compliance");
#endif
+#if @GNULIB_MDA_TEMPNAM@
+/* On native Windows, map 'tempnam' to '_tempnam', so that -loldnames is not
+ required. In C++ with GNULIB_NAMESPACE, avoid differences between
+ platforms by defining GNULIB_NAMESPACE::tempnam always. */
+# if defined _WIN32 && !defined __CYGWIN__
+# if !(defined __cplusplus && defined GNULIB_NAMESPACE)
+# undef tempnam
+# define tempnam _tempnam
+# endif
+_GL_CXXALIAS_MDA (tempnam, char *, (const char *dir, const char *prefix));
+# else
+_GL_CXXALIAS_SYS (tempnam, char *, (const char *dir, const char *prefix));
+# endif
+_GL_CXXALIASWARN (tempnam);
+#endif
+
#if @GNULIB_TMPFILE@
# if @REPLACE_TMPFILE@
# if !(defined __cplusplus && defined GNULIB_NAMESPACE)
# define tmpfile rpl_tmpfile
# endif
-_GL_FUNCDECL_RPL (tmpfile, FILE *, (void));
+_GL_FUNCDECL_RPL (tmpfile, FILE *, (void)
+ _GL_ATTRIBUTE_DEALLOC (fclose, 1));
_GL_CXXALIAS_RPL (tmpfile, FILE *, (void));
# else
+# if __GNUC__ >= 11
+/* For -Wmismatched-dealloc: Associate tmpfile with fclose or rpl_fclose. */
+_GL_FUNCDECL_SYS (tmpfile, FILE *, (void)
+ _GL_ATTRIBUTE_DEALLOC (fclose, 1));
+# endif
_GL_CXXALIAS_SYS (tmpfile, FILE *, (void));
# endif
+# if __GLIBC__ >= 2
_GL_CXXALIASWARN (tmpfile);
-#elif defined GNULIB_POSIXCHECK
-# undef tmpfile
-# if HAVE_RAW_DECL_TMPFILE
+# endif
+#else
+# if @GNULIB_FCLOSE@ && __GNUC__ >= 11 && !defined tmpfile
+/* For -Wmismatched-dealloc: Associate tmpfile with fclose or rpl_fclose. */
+_GL_FUNCDECL_SYS (tmpfile, FILE *, (void)
+ _GL_ATTRIBUTE_DEALLOC (fclose, 1));
+# endif
+# if defined GNULIB_POSIXCHECK
+# undef tmpfile
+# if HAVE_RAW_DECL_TMPFILE
_GL_WARN_ON_USE (tmpfile, "tmpfile is not usable on mingw - "
"use gnulib module tmpfile for portability");
+# endif
# endif
#endif
@@ -1140,9 +1435,10 @@ _GL_WARN_ON_USE (tmpfile, "tmpfile is not usable on mingw - "
# if !(defined __cplusplus && defined GNULIB_NAMESPACE)
# define asprintf rpl_asprintf
# endif
+# define GNULIB_overrides_asprintf
_GL_FUNCDECL_RPL (asprintf, int,
(char **result, const char *format, ...)
- _GL_ATTRIBUTE_FORMAT_PRINTF (2, 3)
+ _GL_ATTRIBUTE_FORMAT_PRINTF_STANDARD (2, 3)
_GL_ARG_NONNULL ((1, 2)));
_GL_CXXALIAS_RPL (asprintf, int,
(char **result, const char *format, ...));
@@ -1150,7 +1446,7 @@ _GL_CXXALIAS_RPL (asprintf, int,
# if !@HAVE_VASPRINTF@
_GL_FUNCDECL_SYS (asprintf, int,
(char **result, const char *format, ...)
- _GL_ATTRIBUTE_FORMAT_PRINTF (2, 3)
+ _GL_ATTRIBUTE_FORMAT_PRINTF_STANDARD (2, 3)
_GL_ARG_NONNULL ((1, 2)));
# endif
_GL_CXXALIAS_SYS (asprintf, int,
@@ -1161,9 +1457,10 @@ _GL_CXXALIASWARN (asprintf);
# if !(defined __cplusplus && defined GNULIB_NAMESPACE)
# define vasprintf rpl_vasprintf
# endif
+# define GNULIB_overrides_vasprintf 1
_GL_FUNCDECL_RPL (vasprintf, int,
(char **result, const char *format, va_list args)
- _GL_ATTRIBUTE_FORMAT_PRINTF (2, 0)
+ _GL_ATTRIBUTE_FORMAT_PRINTF_STANDARD (2, 0)
_GL_ARG_NONNULL ((1, 2)));
_GL_CXXALIAS_RPL (vasprintf, int,
(char **result, const char *format, va_list args));
@@ -1171,7 +1468,7 @@ _GL_CXXALIAS_RPL (vasprintf, int,
# if !@HAVE_VASPRINTF@
_GL_FUNCDECL_SYS (vasprintf, int,
(char **result, const char *format, va_list args)
- _GL_ATTRIBUTE_FORMAT_PRINTF (2, 0)
+ _GL_ATTRIBUTE_FORMAT_PRINTF_STANDARD (2, 0)
_GL_ARG_NONNULL ((1, 2)));
# endif
_GL_CXXALIAS_SYS (vasprintf, int,
@@ -1185,22 +1482,27 @@ _GL_CXXALIASWARN (vasprintf);
# if !(defined __cplusplus && defined GNULIB_NAMESPACE)
# define vdprintf rpl_vdprintf
# endif
-_GL_FUNCDECL_RPL (vdprintf, int, (int fd, const char *format, va_list args)
- _GL_ATTRIBUTE_FORMAT_PRINTF (2, 0)
- _GL_ARG_NONNULL ((2)));
-_GL_CXXALIAS_RPL (vdprintf, int, (int fd, const char *format, va_list args));
+_GL_FUNCDECL_RPL (vdprintf, int,
+ (int fd, const char *restrict format, va_list args)
+ _GL_ATTRIBUTE_FORMAT_PRINTF_STANDARD (2, 0)
+ _GL_ARG_NONNULL ((2)));
+_GL_CXXALIAS_RPL (vdprintf, int,
+ (int fd, const char *restrict format, va_list args));
# else
# if !@HAVE_VDPRINTF@
-_GL_FUNCDECL_SYS (vdprintf, int, (int fd, const char *format, va_list args)
- _GL_ATTRIBUTE_FORMAT_PRINTF (2, 0)
- _GL_ARG_NONNULL ((2)));
+_GL_FUNCDECL_SYS (vdprintf, int,
+ (int fd, const char *restrict format, va_list args)
+ _GL_ATTRIBUTE_FORMAT_PRINTF_STANDARD (2, 0)
+ _GL_ARG_NONNULL ((2)));
# endif
/* Need to cast, because on Solaris, the third parameter will likely be
__va_list args. */
_GL_CXXALIAS_SYS_CAST (vdprintf, int,
- (int fd, const char *format, va_list args));
+ (int fd, const char *restrict format, va_list args));
# endif
+# if __GLIBC__ >= 2
_GL_CXXALIASWARN (vdprintf);
+# endif
#elif defined GNULIB_POSIXCHECK
# undef vdprintf
# if HAVE_RAW_DECL_VDPRINTF
@@ -1217,23 +1519,32 @@ _GL_WARN_ON_USE (vdprintf, "vdprintf is unportable - "
# endif
# define GNULIB_overrides_vfprintf 1
# if @GNULIB_VFPRINTF_POSIX@
-_GL_FUNCDECL_RPL (vfprintf, int, (FILE *fp, const char *format, va_list args)
- _GL_ATTRIBUTE_FORMAT_PRINTF (2, 0)
- _GL_ARG_NONNULL ((1, 2)));
+_GL_FUNCDECL_RPL (vfprintf, int,
+ (FILE *restrict fp,
+ const char *restrict format, va_list args)
+ _GL_ATTRIBUTE_FORMAT_PRINTF_STANDARD (2, 0)
+ _GL_ARG_NONNULL ((1, 2)));
# else
-_GL_FUNCDECL_RPL (vfprintf, int, (FILE *fp, const char *format, va_list args)
- _GL_ATTRIBUTE_FORMAT_PRINTF_SYSTEM (2, 0)
- _GL_ARG_NONNULL ((1, 2)));
+_GL_FUNCDECL_RPL (vfprintf, int,
+ (FILE *restrict fp,
+ const char *restrict format, va_list args)
+ _GL_ATTRIBUTE_FORMAT_PRINTF_SYSTEM (2, 0)
+ _GL_ARG_NONNULL ((1, 2)));
# endif
-_GL_CXXALIAS_RPL (vfprintf, int, (FILE *fp, const char *format, va_list args));
+_GL_CXXALIAS_RPL (vfprintf, int,
+ (FILE *restrict fp,
+ const char *restrict format, va_list args));
# else
/* Need to cast, because on Solaris, the third parameter is
__va_list args
and GCC's fixincludes did not change this to __gnuc_va_list. */
_GL_CXXALIAS_SYS_CAST (vfprintf, int,
- (FILE *fp, const char *format, va_list args));
+ (FILE *restrict fp,
+ const char *restrict format, va_list args));
# endif
+# if __GLIBC__ >= 2
_GL_CXXALIASWARN (vfprintf);
+# endif
#endif
#if !@GNULIB_VFPRINTF_POSIX@ && defined GNULIB_POSIXCHECK
# if !GNULIB_overrides_vfprintf
@@ -1252,16 +1563,21 @@ _GL_WARN_ON_USE (vfprintf, "vfprintf is not always POSIX compliant - "
# define vfscanf rpl_vfscanf
# endif
_GL_FUNCDECL_RPL (vfscanf, int,
- (FILE *stream, const char *format, va_list args)
+ (FILE *restrict stream,
+ const char *restrict format, va_list args)
_GL_ATTRIBUTE_FORMAT_SCANF_SYSTEM (2, 0)
_GL_ARG_NONNULL ((1, 2)));
_GL_CXXALIAS_RPL (vfscanf, int,
- (FILE *stream, const char *format, va_list args));
+ (FILE *restrict stream,
+ const char *restrict format, va_list args));
# else
_GL_CXXALIAS_SYS (vfscanf, int,
- (FILE *stream, const char *format, va_list args));
+ (FILE *restrict stream,
+ const char *restrict format, va_list args));
# endif
+# if __GLIBC__ >= 2
_GL_CXXALIASWARN (vfscanf);
+# endif
#endif
#if @GNULIB_VPRINTF_POSIX@ || @GNULIB_VPRINTF@
@@ -1272,22 +1588,25 @@ _GL_CXXALIASWARN (vfscanf);
# endif
# define GNULIB_overrides_vprintf 1
# if @GNULIB_VPRINTF_POSIX@ || @GNULIB_VFPRINTF_POSIX@
-_GL_FUNCDECL_RPL (vprintf, int, (const char *format, va_list args)
- _GL_ATTRIBUTE_FORMAT_PRINTF (1, 0)
+_GL_FUNCDECL_RPL (vprintf, int, (const char *restrict format, va_list args)
+ _GL_ATTRIBUTE_FORMAT_PRINTF_STANDARD (1, 0)
_GL_ARG_NONNULL ((1)));
# else
-_GL_FUNCDECL_RPL (vprintf, int, (const char *format, va_list args)
+_GL_FUNCDECL_RPL (vprintf, int, (const char *restrict format, va_list args)
_GL_ATTRIBUTE_FORMAT_PRINTF_SYSTEM (1, 0)
_GL_ARG_NONNULL ((1)));
# endif
-_GL_CXXALIAS_RPL (vprintf, int, (const char *format, va_list args));
+_GL_CXXALIAS_RPL (vprintf, int, (const char *restrict format, va_list args));
# else
/* Need to cast, because on Solaris, the second parameter is
__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));
+_GL_CXXALIAS_SYS_CAST (vprintf, int,
+ (const char *restrict format, va_list args));
# endif
+# if __GLIBC__ >= 2
_GL_CXXALIASWARN (vprintf);
+# endif
#endif
#if !@GNULIB_VPRINTF_POSIX@ && defined GNULIB_POSIXCHECK
# if !GNULIB_overrides_vprintf
@@ -1305,14 +1624,16 @@ _GL_WARN_ON_USE (vprintf, "vprintf is not always POSIX compliant - "
# undef vscanf
# define vscanf rpl_vscanf
# endif
-_GL_FUNCDECL_RPL (vscanf, int, (const char *format, va_list args)
+_GL_FUNCDECL_RPL (vscanf, int, (const char *restrict format, va_list args)
_GL_ATTRIBUTE_FORMAT_SCANF_SYSTEM (1, 0)
_GL_ARG_NONNULL ((1)));
-_GL_CXXALIAS_RPL (vscanf, int, (const char *format, va_list args));
+_GL_CXXALIAS_RPL (vscanf, int, (const char *restrict format, va_list args));
# else
-_GL_CXXALIAS_SYS (vscanf, int, (const char *format, va_list args));
+_GL_CXXALIAS_SYS (vscanf, int, (const char *restrict format, va_list args));
# endif
+# if __GLIBC__ >= 2
_GL_CXXALIASWARN (vscanf);
+# endif
#endif
#if @GNULIB_VSNPRINTF@
@@ -1320,23 +1641,30 @@ _GL_CXXALIASWARN (vscanf);
# if !(defined __cplusplus && defined GNULIB_NAMESPACE)
# define vsnprintf rpl_vsnprintf
# endif
+# define GNULIB_overrides_vsnprintf 1
_GL_FUNCDECL_RPL (vsnprintf, int,
- (char *str, size_t size, const char *format, va_list args)
- _GL_ATTRIBUTE_FORMAT_PRINTF (3, 0)
+ (char *restrict str, size_t size,
+ const char *restrict format, va_list args)
+ _GL_ATTRIBUTE_FORMAT_PRINTF_STANDARD (3, 0)
_GL_ARG_NONNULL ((3)));
_GL_CXXALIAS_RPL (vsnprintf, int,
- (char *str, size_t size, const char *format, va_list args));
+ (char *restrict str, size_t size,
+ const char *restrict format, va_list args));
# else
# if !@HAVE_DECL_VSNPRINTF@
_GL_FUNCDECL_SYS (vsnprintf, int,
- (char *str, size_t size, const char *format, va_list args)
- _GL_ATTRIBUTE_FORMAT_PRINTF (3, 0)
+ (char *restrict str, size_t size,
+ const char *restrict format, va_list args)
+ _GL_ATTRIBUTE_FORMAT_PRINTF_STANDARD (3, 0)
_GL_ARG_NONNULL ((3)));
# endif
_GL_CXXALIAS_SYS (vsnprintf, int,
- (char *str, size_t size, const char *format, va_list args));
+ (char *restrict str, size_t size,
+ const char *restrict format, va_list args));
# endif
+# if __GLIBC__ >= 2
_GL_CXXALIASWARN (vsnprintf);
+# endif
#elif defined GNULIB_POSIXCHECK
# undef vsnprintf
# if HAVE_RAW_DECL_VSNPRINTF
@@ -1350,20 +1678,26 @@ _GL_WARN_ON_USE (vsnprintf, "vsnprintf is unportable - "
# if !(defined __cplusplus && defined GNULIB_NAMESPACE)
# define vsprintf rpl_vsprintf
# endif
+# define GNULIB_overrides_vsprintf 1
_GL_FUNCDECL_RPL (vsprintf, int,
- (char *str, const char *format, va_list args)
- _GL_ATTRIBUTE_FORMAT_PRINTF (2, 0)
+ (char *restrict str,
+ const char *restrict format, va_list args)
+ _GL_ATTRIBUTE_FORMAT_PRINTF_STANDARD (2, 0)
_GL_ARG_NONNULL ((1, 2)));
_GL_CXXALIAS_RPL (vsprintf, int,
- (char *str, const char *format, va_list args));
+ (char *restrict str,
+ const char *restrict format, va_list args));
# else
/* Need to cast, because on Solaris, the third parameter is
__va_list args
and GCC's fixincludes did not change this to __gnuc_va_list. */
_GL_CXXALIAS_SYS_CAST (vsprintf, int,
- (char *str, const char *format, va_list args));
+ (char *restrict str,
+ const char *restrict 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 d5fa02b57ab..a86643c3ca3 100644
--- a/lib/stdlib.in.h
+++ b/lib/stdlib.in.h
@@ -1,18 +1,18 @@
/* A GNU-like <stdlib.h>.
- Copyright (C) 1995, 2001-2004, 2006-2017 Free Software Foundation, Inc.
+ Copyright (C) 1995, 2001-2004, 2006-2022 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 file is free software: you can redistribute it and/or modify
+ it under the terms of the GNU Lesser General Public License as
+ published by the Free Software Foundation; either version 2.1 of the
+ License, or (at your option) any later version.
- This program is distributed in the hope that it will be useful,
+ This file 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.
+ GNU Lesser General Public License for more details.
- You should have received a copy of the GNU General Public License
+ You should have received a copy of the GNU Lesser General Public License
along with this program. If not, see <https://www.gnu.org/licenses/>. */
#if __GNUC__ >= 3
@@ -47,11 +47,14 @@
/* Solaris declares getloadavg() in <sys/loadavg.h>. */
#if (@GNULIB_GETLOADAVG@ || defined GNULIB_POSIXCHECK) && @HAVE_SYS_LOADAVG_H@
+/* OpenIndiana has a bug: <sys/time.h> must be included before
+ <sys/loadavg.h>. */
+# include <sys/time.h>
# include <sys/loadavg.h>
#endif
-/* Native Windows platforms declare mktemp() in <io.h>. */
-#if 0 && ((defined _WIN32 || defined __WIN32__) && ! defined __CYGWIN__)
+/* Native Windows platforms declare _mktemp() in <io.h>. */
+#if defined _WIN32 && !defined __CYGWIN__
# include <io.h>
#endif
@@ -87,20 +90,52 @@ struct random_data
# endif
#endif
-#if (@GNULIB_MKSTEMP@ || @GNULIB_MKSTEMPS@ || @GNULIB_GETSUBOPT@ || defined GNULIB_POSIXCHECK) && ! defined __GLIBC__ && !((defined _WIN32 || defined __WIN32__) && ! defined __CYGWIN__)
+#if (@GNULIB_MKSTEMP@ || @GNULIB_MKSTEMPS@ || @GNULIB_MKOSTEMP@ || @GNULIB_MKOSTEMPS@ || @GNULIB_GETSUBOPT@ || defined GNULIB_POSIXCHECK) && ! defined __GLIBC__ && !(defined _WIN32 && ! defined __CYGWIN__)
/* On Mac OS X 10.3, only <unistd.h> declares mkstemp. */
/* On Mac OS X 10.5, only <unistd.h> declares mkstemps. */
+/* On Mac OS X 10.13, only <unistd.h> declares mkostemp and mkostemps. */
/* On Cygwin 1.7.1, only <unistd.h> declares getsubopt. */
/* But avoid namespace pollution on glibc systems and native Windows. */
# include <unistd.h>
#endif
+/* _GL_ATTRIBUTE_DEALLOC (F, I) declares that the function returns pointers
+ that can be freed by passing them as the Ith argument to the
+ function F. */
+#ifndef _GL_ATTRIBUTE_DEALLOC
+# if __GNUC__ >= 11
+# define _GL_ATTRIBUTE_DEALLOC(f, i) __attribute__ ((__malloc__ (f, i)))
+# else
+# define _GL_ATTRIBUTE_DEALLOC(f, i)
+# endif
+#endif
+
+/* _GL_ATTRIBUTE_DEALLOC_FREE declares that the function returns pointers that
+ can be freed via 'free'; it can be used only after declaring 'free'. */
+/* Applies to: functions. Cannot be used on inline functions. */
+#ifndef _GL_ATTRIBUTE_DEALLOC_FREE
+# define _GL_ATTRIBUTE_DEALLOC_FREE _GL_ATTRIBUTE_DEALLOC (free, 1)
+#endif
+
+/* _GL_ATTRIBUTE_MALLOC declares that the function returns a pointer to freshly
+ allocated memory. */
+/* Applies to: functions. */
+#ifndef _GL_ATTRIBUTE_MALLOC
+# if __GNUC__ >= 3 || defined __clang__
+# define _GL_ATTRIBUTE_MALLOC __attribute__ ((__malloc__))
+# else
+# define _GL_ATTRIBUTE_MALLOC
+# endif
+#endif
+
/* The __attribute__ feature is available in gcc versions 2.5 and later.
The attribute __pure__ was added in gcc 2.96. */
-#if __GNUC__ > 2 || (__GNUC__ == 2 && __GNUC_MINOR__ >= 96)
-# define _GL_ATTRIBUTE_PURE __attribute__ ((__pure__))
-#else
-# define _GL_ATTRIBUTE_PURE /* empty */
+#ifndef _GL_ATTRIBUTE_PURE
+# if __GNUC__ > 2 || (__GNUC__ == 2 && __GNUC_MINOR__ >= 96) || defined __clang__
+# define _GL_ATTRIBUTE_PURE __attribute__ ((__pure__))
+# else
+# define _GL_ATTRIBUTE_PURE /* empty */
+# endif
#endif
/* The definition of _Noreturn is copied here. */
@@ -143,6 +178,73 @@ _GL_WARN_ON_USE (_Exit, "_Exit is unportable - "
#endif
+#if @GNULIB_FREE_POSIX@
+# if @REPLACE_FREE@
+# if !(defined __cplusplus && defined GNULIB_NAMESPACE)
+# undef free
+# define free rpl_free
+# endif
+# if defined __cplusplus && (__GLIBC__ + (__GLIBC_MINOR__ >= 14) > 2)
+_GL_FUNCDECL_RPL (free, void, (void *ptr) throw ());
+# else
+_GL_FUNCDECL_RPL (free, void, (void *ptr));
+# endif
+_GL_CXXALIAS_RPL (free, void, (void *ptr));
+# else
+_GL_CXXALIAS_SYS (free, void, (void *ptr));
+# endif
+# if __GLIBC__ >= 2
+_GL_CXXALIASWARN (free);
+# endif
+#elif defined GNULIB_POSIXCHECK
+# undef free
+/* Assume free is always declared. */
+_GL_WARN_ON_USE (free, "free is not future POSIX compliant everywhere - "
+ "use gnulib module free for portability");
+#endif
+
+
+/* Allocate memory with indefinite extent and specified alignment. */
+#if @GNULIB_ALIGNED_ALLOC@
+# if @REPLACE_ALIGNED_ALLOC@
+# if !(defined __cplusplus && defined GNULIB_NAMESPACE)
+# undef aligned_alloc
+# define aligned_alloc rpl_aligned_alloc
+# endif
+_GL_FUNCDECL_RPL (aligned_alloc, void *,
+ (size_t alignment, size_t size)
+ _GL_ATTRIBUTE_MALLOC _GL_ATTRIBUTE_DEALLOC_FREE);
+_GL_CXXALIAS_RPL (aligned_alloc, void *, (size_t alignment, size_t size));
+# else
+# if @HAVE_ALIGNED_ALLOC@
+# if __GNUC__ >= 11
+/* For -Wmismatched-dealloc: Associate aligned_alloc with free or rpl_free. */
+_GL_FUNCDECL_SYS (aligned_alloc, void *,
+ (size_t alignment, size_t size)
+ _GL_ATTRIBUTE_MALLOC _GL_ATTRIBUTE_DEALLOC_FREE);
+# endif
+_GL_CXXALIAS_SYS (aligned_alloc, void *, (size_t alignment, size_t size));
+# endif
+# endif
+# if @HAVE_ALIGNED_ALLOC@
+_GL_CXXALIASWARN (aligned_alloc);
+# endif
+#else
+# if @GNULIB_FREE_POSIX@ && __GNUC__ >= 11 && !defined aligned_alloc
+/* For -Wmismatched-dealloc: Associate aligned_alloc with free or rpl_free. */
+_GL_FUNCDECL_SYS (aligned_alloc, void *,
+ (size_t alignment, size_t size)
+ _GL_ATTRIBUTE_MALLOC _GL_ATTRIBUTE_DEALLOC_FREE);
+# endif
+# if defined GNULIB_POSIXCHECK
+# undef aligned_alloc
+# if HAVE_RAW_DECL_ALIGNED_ALLOC
+_GL_WARN_ON_USE (aligned_alloc, "aligned_alloc is not portable - "
+ "use gnulib module aligned_alloc for portability");
+# endif
+# endif
+#endif
+
#if @GNULIB_ATOLL@
/* Parse a signed decimal integer.
Returns the value of the integer. Errors are not detected. */
@@ -162,22 +264,41 @@ _GL_WARN_ON_USE (atoll, "atoll is unportable - "
#endif
#if @GNULIB_CALLOC_POSIX@
-# if @REPLACE_CALLOC@
+# if (@GNULIB_CALLOC_POSIX@ && @REPLACE_CALLOC_FOR_CALLOC_POSIX@) \
+ || (@GNULIB_CALLOC_GNU@ && @REPLACE_CALLOC_FOR_CALLOC_GNU@)
# if !(defined __cplusplus && defined GNULIB_NAMESPACE)
# undef calloc
# define calloc rpl_calloc
# endif
-_GL_FUNCDECL_RPL (calloc, void *, (size_t nmemb, size_t size));
+_GL_FUNCDECL_RPL (calloc, void *,
+ (size_t nmemb, size_t size)
+ _GL_ATTRIBUTE_MALLOC _GL_ATTRIBUTE_DEALLOC_FREE);
_GL_CXXALIAS_RPL (calloc, void *, (size_t nmemb, size_t size));
# else
+# if __GNUC__ >= 11
+/* For -Wmismatched-dealloc: Associate calloc with free or rpl_free. */
+_GL_FUNCDECL_SYS (calloc, void *,
+ (size_t nmemb, size_t size)
+ _GL_ATTRIBUTE_MALLOC _GL_ATTRIBUTE_DEALLOC_FREE);
+# endif
_GL_CXXALIAS_SYS (calloc, void *, (size_t nmemb, size_t size));
# endif
+# if __GLIBC__ >= 2
_GL_CXXALIASWARN (calloc);
-#elif defined GNULIB_POSIXCHECK
-# undef calloc
+# endif
+#else
+# if @GNULIB_FREE_POSIX@ && __GNUC__ >= 11 && !defined calloc
+/* For -Wmismatched-dealloc: Associate calloc with free or rpl_free. */
+_GL_FUNCDECL_SYS (calloc, void *,
+ (size_t nmemb, size_t size)
+ _GL_ATTRIBUTE_MALLOC _GL_ATTRIBUTE_DEALLOC_FREE);
+# endif
+# if defined GNULIB_POSIXCHECK
+# undef calloc
/* Assume calloc is always declared. */
_GL_WARN_ON_USE (calloc, "calloc is not POSIX compliant everywhere - "
"use gnulib module calloc-posix for portability");
+# endif
#endif
#if @GNULIB_CANONICALIZE_FILE_NAME@
@@ -185,23 +306,108 @@ _GL_WARN_ON_USE (calloc, "calloc is not POSIX compliant everywhere - "
# if !(defined __cplusplus && defined GNULIB_NAMESPACE)
# define canonicalize_file_name rpl_canonicalize_file_name
# endif
-_GL_FUNCDECL_RPL (canonicalize_file_name, char *, (const char *name)
- _GL_ARG_NONNULL ((1)));
+_GL_FUNCDECL_RPL (canonicalize_file_name, char *,
+ (const char *name)
+ _GL_ARG_NONNULL ((1))
+ _GL_ATTRIBUTE_MALLOC _GL_ATTRIBUTE_DEALLOC_FREE);
_GL_CXXALIAS_RPL (canonicalize_file_name, char *, (const char *name));
# else
-# if !@HAVE_CANONICALIZE_FILE_NAME@
-_GL_FUNCDECL_SYS (canonicalize_file_name, char *, (const char *name)
- _GL_ARG_NONNULL ((1)));
+# if !@HAVE_CANONICALIZE_FILE_NAME@ || __GNUC__ >= 11
+_GL_FUNCDECL_SYS (canonicalize_file_name, char *,
+ (const char *name)
+ _GL_ARG_NONNULL ((1))
+ _GL_ATTRIBUTE_MALLOC _GL_ATTRIBUTE_DEALLOC_FREE);
# 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
-# if HAVE_RAW_DECL_CANONICALIZE_FILE_NAME
+#else
+# if @GNULIB_FREE_POSIX@ && __GNUC__ >= 11 && !defined canonicalize_file_name
+/* For -Wmismatched-dealloc: Associate canonicalize_file_name with free or
+ rpl_free. */
+_GL_FUNCDECL_SYS (canonicalize_file_name, char *,
+ (const char *name)
+ _GL_ARG_NONNULL ((1))
+ _GL_ATTRIBUTE_MALLOC _GL_ATTRIBUTE_DEALLOC_FREE);
+# endif
+# if defined GNULIB_POSIXCHECK
+# undef canonicalize_file_name
+# if HAVE_RAW_DECL_CANONICALIZE_FILE_NAME
_GL_WARN_ON_USE (canonicalize_file_name,
"canonicalize_file_name is unportable - "
"use gnulib module canonicalize-lgpl for portability");
+# endif
+# endif
+#endif
+
+#if @GNULIB_MDA_ECVT@
+/* On native Windows, map 'ecvt' to '_ecvt', so that -loldnames is not
+ required. In C++ with GNULIB_NAMESPACE, avoid differences between
+ platforms by defining GNULIB_NAMESPACE::ecvt on all platforms that have
+ it. */
+# if defined _WIN32 && !defined __CYGWIN__
+# if !(defined __cplusplus && defined GNULIB_NAMESPACE)
+# undef ecvt
+# define ecvt _ecvt
+# endif
+_GL_CXXALIAS_MDA (ecvt, char *,
+ (double number, int ndigits, int *decptp, int *signp));
+# else
+# if @HAVE_DECL_ECVT@
+_GL_CXXALIAS_SYS (ecvt, char *,
+ (double number, int ndigits, int *decptp, int *signp));
+# endif
+# endif
+# if (defined _WIN32 && !defined __CYGWIN__) || @HAVE_DECL_ECVT@
+_GL_CXXALIASWARN (ecvt);
+# endif
+#endif
+
+#if @GNULIB_MDA_FCVT@
+/* On native Windows, map 'fcvt' to '_fcvt', so that -loldnames is not
+ required. In C++ with GNULIB_NAMESPACE, avoid differences between
+ platforms by defining GNULIB_NAMESPACE::fcvt on all platforms that have
+ it. */
+# if defined _WIN32 && !defined __CYGWIN__
+# if !(defined __cplusplus && defined GNULIB_NAMESPACE)
+# undef fcvt
+# define fcvt _fcvt
+# endif
+_GL_CXXALIAS_MDA (fcvt, char *,
+ (double number, int ndigits, int *decptp, int *signp));
+# else
+# if @HAVE_DECL_FCVT@
+_GL_CXXALIAS_SYS (fcvt, char *,
+ (double number, int ndigits, int *decptp, int *signp));
+# endif
+# endif
+# if (defined _WIN32 && !defined __CYGWIN__) || @HAVE_DECL_FCVT@
+_GL_CXXALIASWARN (fcvt);
+# endif
+#endif
+
+#if @GNULIB_MDA_GCVT@
+/* On native Windows, map 'gcvt' to '_gcvt', so that -loldnames is not
+ required. In C++ with GNULIB_NAMESPACE, avoid differences between
+ platforms by defining GNULIB_NAMESPACE::gcvt on all platforms that have
+ it. */
+# if defined _WIN32 && !defined __CYGWIN__
+# if !(defined __cplusplus && defined GNULIB_NAMESPACE)
+# undef gcvt
+# define gcvt _gcvt
+# endif
+_GL_CXXALIAS_MDA (gcvt, char *, (double number, int ndigits, char *buf));
+# else
+# if @HAVE_DECL_GCVT@
+_GL_CXXALIAS_SYS (gcvt, char *, (double number, int ndigits, char *buf));
+# endif
+# endif
+# if (defined _WIN32 && !defined __CYGWIN__) || @HAVE_DECL_GCVT@
+_GL_CXXALIASWARN (gcvt);
# endif
#endif
@@ -234,8 +440,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)
@@ -273,23 +479,42 @@ _GL_WARN_ON_USE (grantpt, "grantpt is not portable - "
by never specifying a zero size), so it does not need malloc or
realloc to be redefined. */
#if @GNULIB_MALLOC_POSIX@
-# if @REPLACE_MALLOC@
+# if (@GNULIB_MALLOC_POSIX@ && @REPLACE_MALLOC_FOR_MALLOC_POSIX@) \
+ || (@GNULIB_MALLOC_GNU@ && @REPLACE_MALLOC_FOR_MALLOC_GNU@)
# if !((defined __cplusplus && defined GNULIB_NAMESPACE) \
|| _GL_USE_STDLIB_ALLOC)
# undef malloc
# define malloc rpl_malloc
# endif
-_GL_FUNCDECL_RPL (malloc, void *, (size_t size));
+_GL_FUNCDECL_RPL (malloc, void *,
+ (size_t size)
+ _GL_ATTRIBUTE_MALLOC _GL_ATTRIBUTE_DEALLOC_FREE);
_GL_CXXALIAS_RPL (malloc, void *, (size_t size));
# else
+# if __GNUC__ >= 11
+/* For -Wmismatched-dealloc: Associate malloc with free or rpl_free. */
+_GL_FUNCDECL_SYS (malloc, void *,
+ (size_t size)
+ _GL_ATTRIBUTE_MALLOC _GL_ATTRIBUTE_DEALLOC_FREE);
+# endif
_GL_CXXALIAS_SYS (malloc, void *, (size_t size));
# endif
+# if __GLIBC__ >= 2
_GL_CXXALIASWARN (malloc);
-#elif defined GNULIB_POSIXCHECK && !_GL_USE_STDLIB_ALLOC
-# undef malloc
+# endif
+#else
+# if @GNULIB_FREE_POSIX@ && __GNUC__ >= 11 && !defined malloc
+/* For -Wmismatched-dealloc: Associate malloc with free or rpl_free. */
+_GL_FUNCDECL_SYS (malloc, void *,
+ (size_t size)
+ _GL_ATTRIBUTE_MALLOC _GL_ATTRIBUTE_DEALLOC_FREE);
+# endif
+# if defined GNULIB_POSIXCHECK && !_GL_USE_STDLIB_ALLOC
+# undef malloc
/* Assume malloc is always declared. */
_GL_WARN_ON_USE (malloc, "malloc is not POSIX compliant everywhere - "
"use gnulib module malloc-posix for portability");
+# endif
#endif
/* Convert a multibyte character to a wide character. */
@@ -299,12 +524,27 @@ _GL_WARN_ON_USE (malloc, "malloc is not POSIX compliant everywhere - "
# undef mbtowc
# define mbtowc rpl_mbtowc
# endif
-_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));
+_GL_FUNCDECL_RPL (mbtowc, int,
+ (wchar_t *restrict pwc, const char *restrict s, size_t n));
+_GL_CXXALIAS_RPL (mbtowc, int,
+ (wchar_t *restrict pwc, const char *restrict s, size_t n));
# else
-_GL_CXXALIAS_SYS (mbtowc, int, (wchar_t *pwc, const char *s, size_t n));
+# if !@HAVE_MBTOWC@
+_GL_FUNCDECL_SYS (mbtowc, int,
+ (wchar_t *restrict pwc, const char *restrict s, size_t n));
+# endif
+_GL_CXXALIAS_SYS (mbtowc, int,
+ (wchar_t *restrict pwc, const char *restrict 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@
@@ -439,6 +679,51 @@ _GL_WARN_ON_USE (mkstemps, "mkstemps is unportable - "
# endif
#endif
+#if @GNULIB_MDA_MKTEMP@
+/* On native Windows, map 'mktemp' to '_mktemp', so that -loldnames is not
+ required. In C++ with GNULIB_NAMESPACE, avoid differences between
+ platforms by defining GNULIB_NAMESPACE::mktemp always. */
+# if defined _WIN32 && !defined __CYGWIN__
+# if !(defined __cplusplus && defined GNULIB_NAMESPACE)
+# undef mktemp
+# define mktemp _mktemp
+# endif
+_GL_CXXALIAS_MDA (mktemp, char *, (char * /*template*/));
+# else
+_GL_CXXALIAS_SYS (mktemp, char *, (char * /*template*/));
+# endif
+_GL_CXXALIASWARN (mktemp);
+#endif
+
+/* Allocate memory with indefinite extent and specified alignment. */
+#if @GNULIB_POSIX_MEMALIGN@
+# if @REPLACE_POSIX_MEMALIGN@
+# if !(defined __cplusplus && defined GNULIB_NAMESPACE)
+# undef posix_memalign
+# define posix_memalign rpl_posix_memalign
+# endif
+_GL_FUNCDECL_RPL (posix_memalign, int,
+ (void **memptr, size_t alignment, size_t size)
+ _GL_ARG_NONNULL ((1)));
+_GL_CXXALIAS_RPL (posix_memalign, int,
+ (void **memptr, size_t alignment, size_t size));
+# else
+# if @HAVE_POSIX_MEMALIGN@
+_GL_CXXALIAS_SYS (posix_memalign, int,
+ (void **memptr, size_t alignment, size_t size));
+# endif
+# endif
+# if @HAVE_POSIX_MEMALIGN@
+_GL_CXXALIASWARN (posix_memalign);
+# endif
+#elif defined GNULIB_POSIXCHECK
+# undef posix_memalign
+# if HAVE_RAW_DECL_POSIX_MEMALIGN
+_GL_WARN_ON_USE (posix_memalign, "posix_memalign is not portable - "
+ "use gnulib module posix_memalign for portability");
+# endif
+#endif
+
#if @GNULIB_POSIX_OPENPT@
/* Return an FD open to the master side of a pseudo-terminal. Flags should
include O_RDWR, and may also include O_NOCTTY. */
@@ -497,6 +782,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
@@ -514,6 +802,28 @@ _GL_WARN_ON_USE (ptsname_r, "ptsname_r is not portable - "
# endif
_GL_FUNCDECL_RPL (putenv, int, (char *string) _GL_ARG_NONNULL ((1)));
_GL_CXXALIAS_RPL (putenv, int, (char *string));
+# elif defined _WIN32 && !defined __CYGWIN__
+# if !(defined __cplusplus && defined GNULIB_NAMESPACE)
+# undef putenv
+# define putenv _putenv
+# endif
+_GL_CXXALIAS_MDA (putenv, int, (char *string));
+# else
+_GL_CXXALIAS_SYS (putenv, int, (char *string));
+# endif
+_GL_CXXALIASWARN (putenv);
+#elif @GNULIB_MDA_PUTENV@
+/* On native Windows, map 'putenv' to '_putenv', so that -loldnames is not
+ required. In C++ with GNULIB_NAMESPACE, avoid differences between
+ platforms by defining GNULIB_NAMESPACE::putenv always. */
+# if defined _WIN32 && !defined __CYGWIN__
+# if !(defined __cplusplus && defined GNULIB_NAMESPACE)
+# undef putenv
+# define putenv _putenv
+# endif
+/* Need to cast, because on mingw, the parameter is either
+ 'const char *string' or 'char *string'. */
+_GL_CXXALIAS_MDA_CAST (putenv, int, (char *string));
# else
_GL_CXXALIAS_SYS (putenv, int, (char *string));
# endif
@@ -524,29 +834,35 @@ _GL_CXXALIASWARN (putenv);
/* Sort an array of NMEMB elements, starting at address BASE, each element
occupying SIZE bytes, in ascending order according to the comparison
function COMPARE. */
+# ifdef __cplusplus
+extern "C" {
+# endif
+# if !GNULIB_defined_qsort_r_fn_types
+typedef int (*_gl_qsort_r_compar_fn) (void const *, void const *, void *);
+# define GNULIB_defined_qsort_r_fn_types 1
+# endif
+# ifdef __cplusplus
+}
+# endif
# if @REPLACE_QSORT_R@
# if !(defined __cplusplus && defined GNULIB_NAMESPACE)
# undef qsort_r
# define qsort_r rpl_qsort_r
# endif
_GL_FUNCDECL_RPL (qsort_r, void, (void *base, size_t nmemb, size_t size,
- int (*compare) (void const *, void const *,
- void *),
+ _gl_qsort_r_compar_fn compare,
void *arg) _GL_ARG_NONNULL ((1, 4)));
_GL_CXXALIAS_RPL (qsort_r, void, (void *base, size_t nmemb, size_t size,
- int (*compare) (void const *, void const *,
- void *),
+ _gl_qsort_r_compar_fn compare,
void *arg));
# else
# if !@HAVE_QSORT_R@
_GL_FUNCDECL_SYS (qsort_r, void, (void *base, size_t nmemb, size_t size,
- int (*compare) (void const *, void const *,
- void *),
+ _gl_qsort_r_compar_fn compare,
void *arg) _GL_ARG_NONNULL ((1, 4)));
# endif
_GL_CXXALIAS_SYS (qsort_r, void, (void *base, size_t nmemb, size_t size,
- int (*compare) (void const *, void const *,
- void *),
+ _gl_qsort_r_compar_fn compare,
void *arg));
# endif
_GL_CXXALIASWARN (qsort_r);
@@ -569,10 +885,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
@@ -583,10 +910,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
@@ -597,31 +935,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
@@ -702,9 +1065,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
@@ -732,8 +1097,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
@@ -746,33 +1113,60 @@ _GL_WARN_ON_USE (setstate_r, "setstate_r is unportable - "
#if @GNULIB_REALLOC_POSIX@
-# if @REPLACE_REALLOC@
+# if (@GNULIB_REALLOC_POSIX@ && @REPLACE_REALLOC_FOR_REALLOC_POSIX@) \
+ || (@GNULIB_REALLOC_GNU@ && @REPLACE_REALLOC_FOR_REALLOC_GNU@)
# if !((defined __cplusplus && defined GNULIB_NAMESPACE) \
|| _GL_USE_STDLIB_ALLOC)
# undef realloc
# define realloc rpl_realloc
# endif
-_GL_FUNCDECL_RPL (realloc, void *, (void *ptr, size_t size));
+_GL_FUNCDECL_RPL (realloc, void *, (void *ptr, size_t size)
+ _GL_ATTRIBUTE_DEALLOC_FREE);
_GL_CXXALIAS_RPL (realloc, void *, (void *ptr, size_t size));
# else
+# if __GNUC__ >= 11
+/* For -Wmismatched-dealloc: Associate realloc with free or rpl_free. */
+_GL_FUNCDECL_SYS (realloc, void *, (void *ptr, size_t size)
+ _GL_ATTRIBUTE_DEALLOC_FREE);
+# endif
_GL_CXXALIAS_SYS (realloc, void *, (void *ptr, size_t size));
# endif
+# if __GLIBC__ >= 2
_GL_CXXALIASWARN (realloc);
-#elif defined GNULIB_POSIXCHECK && !_GL_USE_STDLIB_ALLOC
-# undef realloc
+# endif
+#else
+# if @GNULIB_FREE_POSIX@ && __GNUC__ >= 11 && !defined realloc
+/* For -Wmismatched-dealloc: Associate realloc with free or rpl_free. */
+_GL_FUNCDECL_SYS (realloc, void *, (void *ptr, size_t size)
+ _GL_ATTRIBUTE_DEALLOC_FREE);
+# endif
+# if defined GNULIB_POSIXCHECK && !_GL_USE_STDLIB_ALLOC
+# undef realloc
/* Assume realloc is always declared. */
_GL_WARN_ON_USE (realloc, "realloc is not POSIX compliant everywhere - "
"use gnulib module realloc-posix for portability");
+# endif
#endif
#if @GNULIB_REALLOCARRAY@
-# if ! @HAVE_REALLOCARRAY@
+# if @REPLACE_REALLOCARRAY@
+# if !(defined __cplusplus && defined GNULIB_NAMESPACE)
+# undef reallocarray
+# define reallocarray rpl_reallocarray
+# endif
+_GL_FUNCDECL_RPL (reallocarray, void *,
+ (void *ptr, size_t nmemb, size_t size));
+_GL_CXXALIAS_RPL (reallocarray, void *,
+ (void *ptr, size_t nmemb, size_t size));
+# else
+# if ! @HAVE_REALLOCARRAY@
_GL_FUNCDECL_SYS (reallocarray, void *,
(void *ptr, size_t nmemb, size_t size));
-# endif
+# endif
_GL_CXXALIAS_SYS (reallocarray, void *,
(void *ptr, size_t nmemb, size_t size));
+# endif
_GL_CXXALIASWARN (reallocarray);
#elif defined GNULIB_POSIXCHECK
# undef reallocarray
@@ -787,15 +1181,19 @@ _GL_WARN_ON_USE (reallocarray, "reallocarray is not portable - "
# if !(defined __cplusplus && defined GNULIB_NAMESPACE)
# define realpath rpl_realpath
# endif
-_GL_FUNCDECL_RPL (realpath, char *, (const char *name, char *resolved)
- _GL_ARG_NONNULL ((1)));
-_GL_CXXALIAS_RPL (realpath, char *, (const char *name, char *resolved));
+_GL_FUNCDECL_RPL (realpath, char *,
+ (const char *restrict name, char *restrict resolved)
+ _GL_ARG_NONNULL ((1)));
+_GL_CXXALIAS_RPL (realpath, char *,
+ (const char *restrict name, char *restrict resolved));
# else
# if !@HAVE_REALPATH@
-_GL_FUNCDECL_SYS (realpath, char *, (const char *name, char *resolved)
- _GL_ARG_NONNULL ((1)));
+_GL_FUNCDECL_SYS (realpath, char *,
+ (const char *restrict name, char *restrict resolved)
+ _GL_ARG_NONNULL ((1)));
# endif
-_GL_CXXALIAS_SYS (realpath, char *, (const char *name, char *resolved));
+_GL_CXXALIAS_SYS (realpath, char *,
+ (const char *restrict name, char *restrict resolved));
# endif
_GL_CXXALIASWARN (realpath);
#elif defined GNULIB_POSIXCHECK
@@ -877,17 +1275,24 @@ _GL_WARN_ON_USE (setenv, "setenv is unportable - "
# if !(defined __cplusplus && defined GNULIB_NAMESPACE)
# define strtod rpl_strtod
# endif
-_GL_FUNCDECL_RPL (strtod, double, (const char *str, char **endp)
- _GL_ARG_NONNULL ((1)));
-_GL_CXXALIAS_RPL (strtod, double, (const char *str, char **endp));
+# define GNULIB_defined_strtod_function 1
+_GL_FUNCDECL_RPL (strtod, double,
+ (const char *restrict str, char **restrict endp)
+ _GL_ARG_NONNULL ((1)));
+_GL_CXXALIAS_RPL (strtod, double,
+ (const char *restrict str, char **restrict endp));
# else
# if !@HAVE_STRTOD@
-_GL_FUNCDECL_SYS (strtod, double, (const char *str, char **endp)
- _GL_ARG_NONNULL ((1)));
+_GL_FUNCDECL_SYS (strtod, double,
+ (const char *restrict str, char **restrict endp)
+ _GL_ARG_NONNULL ((1)));
# endif
-_GL_CXXALIAS_SYS (strtod, double, (const char *str, char **endp));
+_GL_CXXALIAS_SYS (strtod, double,
+ (const char *restrict str, char **restrict endp));
# endif
+# if __GLIBC__ >= 2
_GL_CXXALIASWARN (strtod);
+# endif
#elif defined GNULIB_POSIXCHECK
# undef strtod
# if HAVE_RAW_DECL_STRTOD
@@ -896,6 +1301,77 @@ _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 *restrict str, char **restrict endp)
+ _GL_ARG_NONNULL ((1)));
+_GL_CXXALIAS_RPL (strtold, long double,
+ (const char *restrict str, char **restrict endp));
+# else
+# if !@HAVE_STRTOLD@
+_GL_FUNCDECL_SYS (strtold, long double,
+ (const char *restrict str, char **restrict endp)
+ _GL_ARG_NONNULL ((1)));
+# endif
+_GL_CXXALIAS_SYS (strtold, long double,
+ (const char *restrict str, char **restrict 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_STRTOL@
+/* 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,
+ it may be decimal or octal (with prefix "0") or hexadecimal (with prefix
+ "0x").
+ If ENDPTR is not NULL, the address of the first byte after the integer is
+ stored in *ENDPTR.
+ Upon overflow, the return value is LONG_MAX or LONG_MIN, and errno is set
+ to ERANGE. */
+# if @REPLACE_STRTOL@
+# if !(defined __cplusplus && defined GNULIB_NAMESPACE)
+# define strtol rpl_strtol
+# endif
+# define GNULIB_defined_strtol_function 1
+_GL_FUNCDECL_RPL (strtol, long,
+ (const char *restrict string, char **restrict endptr,
+ int base)
+ _GL_ARG_NONNULL ((1)));
+_GL_CXXALIAS_RPL (strtol, long,
+ (const char *restrict string, char **restrict endptr,
+ int base));
+# else
+# if !@HAVE_STRTOL@
+_GL_FUNCDECL_SYS (strtol, long,
+ (const char *restrict string, char **restrict endptr,
+ int base)
+ _GL_ARG_NONNULL ((1)));
+# endif
+_GL_CXXALIAS_SYS (strtol, long,
+ (const char *restrict string, char **restrict endptr,
+ int base));
+# endif
+_GL_CXXALIASWARN (strtol);
+#elif defined GNULIB_POSIXCHECK
+# undef strtol
+# if HAVE_RAW_DECL_STRTOL
+_GL_WARN_ON_USE (strtol, "strtol is unportable - "
+ "use gnulib module strtol 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,
@@ -905,13 +1381,29 @@ _GL_WARN_ON_USE (strtod, "strtod is unportable - "
stored in *ENDPTR.
Upon overflow, the return value is LLONG_MAX or LLONG_MIN, and errno is set
to ERANGE. */
-# if !@HAVE_STRTOLL@
+# if @REPLACE_STRTOLL@
+# if !(defined __cplusplus && defined GNULIB_NAMESPACE)
+# define strtoll rpl_strtoll
+# endif
+# define GNULIB_defined_strtoll_function 1
+_GL_FUNCDECL_RPL (strtoll, long long,
+ (const char *restrict string, char **restrict endptr,
+ int base)
+ _GL_ARG_NONNULL ((1)));
+_GL_CXXALIAS_RPL (strtoll, long long,
+ (const char *restrict string, char **restrict endptr,
+ int base));
+# else
+# if !@HAVE_STRTOLL@
_GL_FUNCDECL_SYS (strtoll, long long,
- (const char *string, char **endptr, int base)
+ (const char *restrict string, char **restrict endptr,
+ int base)
_GL_ARG_NONNULL ((1)));
-# endif
+# endif
_GL_CXXALIAS_SYS (strtoll, long long,
- (const char *string, char **endptr, int base));
+ (const char *restrict string, char **restrict endptr,
+ int base));
+# endif
_GL_CXXALIASWARN (strtoll);
#elif defined GNULIB_POSIXCHECK
# undef strtoll
@@ -921,6 +1413,46 @@ _GL_WARN_ON_USE (strtoll, "strtoll is unportable - "
# endif
#endif
+#if @GNULIB_STRTOUL@
+/* Parse an unsigned integer whose textual representation starts at STRING.
+ The integer is expected to be in base BASE (2 <= BASE <= 36); if BASE == 0,
+ it may be decimal or octal (with prefix "0") or hexadecimal (with prefix
+ "0x").
+ If ENDPTR is not NULL, the address of the first byte after the integer is
+ stored in *ENDPTR.
+ Upon overflow, the return value is ULONG_MAX, and errno is set to ERANGE. */
+# if @REPLACE_STRTOUL@
+# if !(defined __cplusplus && defined GNULIB_NAMESPACE)
+# define strtoul rpl_strtoul
+# endif
+# define GNULIB_defined_strtoul_function 1
+_GL_FUNCDECL_RPL (strtoul, unsigned long,
+ (const char *restrict string, char **restrict endptr,
+ int base)
+ _GL_ARG_NONNULL ((1)));
+_GL_CXXALIAS_RPL (strtoul, unsigned long,
+ (const char *restrict string, char **restrict endptr,
+ int base));
+# else
+# if !@HAVE_STRTOUL@
+_GL_FUNCDECL_SYS (strtoul, unsigned long,
+ (const char *restrict string, char **restrict endptr,
+ int base)
+ _GL_ARG_NONNULL ((1)));
+# endif
+_GL_CXXALIAS_SYS (strtoul, unsigned long,
+ (const char *restrict string, char **restrict endptr,
+ int base));
+# endif
+_GL_CXXALIASWARN (strtoul);
+#elif defined GNULIB_POSIXCHECK
+# undef strtoul
+# if HAVE_RAW_DECL_STRTOUL
+_GL_WARN_ON_USE (strtoul, "strtoul is unportable - "
+ "use gnulib module strtoul for portability");
+# endif
+#endif
+
#if @GNULIB_STRTOULL@
/* Parse an unsigned integer whose textual representation starts at STRING.
The integer is expected to be in base BASE (2 <= BASE <= 36); if BASE == 0,
@@ -930,13 +1462,29 @@ _GL_WARN_ON_USE (strtoll, "strtoll is unportable - "
stored in *ENDPTR.
Upon overflow, the return value is ULLONG_MAX, and errno is set to
ERANGE. */
-# if !@HAVE_STRTOULL@
+# if @REPLACE_STRTOULL@
+# if !(defined __cplusplus && defined GNULIB_NAMESPACE)
+# define strtoull rpl_strtoull
+# endif
+# define GNULIB_defined_strtoull_function 1
+_GL_FUNCDECL_RPL (strtoull, unsigned long long,
+ (const char *restrict string, char **restrict endptr,
+ int base)
+ _GL_ARG_NONNULL ((1)));
+_GL_CXXALIAS_RPL (strtoull, unsigned long long,
+ (const char *restrict string, char **restrict endptr,
+ int base));
+# else
+# if !@HAVE_STRTOULL@
_GL_FUNCDECL_SYS (strtoull, unsigned long long,
- (const char *string, char **endptr, int base)
+ (const char *restrict string, char **restrict endptr,
+ int base)
_GL_ARG_NONNULL ((1)));
-# endif
+# endif
_GL_CXXALIAS_SYS (strtoull, unsigned long long,
- (const char *string, char **endptr, int base));
+ (const char *restrict string, char **restrict endptr,
+ int base));
+# endif
_GL_CXXALIASWARN (strtoull);
#elif defined GNULIB_POSIXCHECK
# undef strtoull
@@ -1000,7 +1548,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/stpcpy.c b/lib/stpcpy.c
index 079599db868..434f84ae765 100644
--- a/lib/stpcpy.c
+++ b/lib/stpcpy.c
@@ -1,21 +1,21 @@
/* stpcpy.c -- copy a string and return pointer to end of new string
- Copyright (C) 1992, 1995, 1997-1998, 2006, 2009-2017 Free Software
+ Copyright (C) 1992, 1995, 1997-1998, 2006, 2009-2022 Free Software
Foundation, Inc.
NOTE: The canonical source of this file is maintained with the GNU C Library.
Bugs can be reported to bug-glibc@prep.ai.mit.edu.
- 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 any
- later version.
+ This file is free software: you can redistribute it and/or modify
+ it under the terms of the GNU Lesser General Public License as
+ published by the Free Software Foundation; either version 2.1 of the
+ License, or (at your option) any later version.
- This program is distributed in the hope that it will be useful,
+ This file 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.
+ GNU Lesser General Public License for more details.
- You should have received a copy of the GNU General Public License
+ You should have received a copy of the GNU Lesser General Public License
along with this program. If not, see <https://www.gnu.org/licenses/>. */
#include <config.h>
diff --git a/lib/str-two-way.h b/lib/str-two-way.h
new file mode 100644
index 00000000000..b00017c0b4b
--- /dev/null
+++ b/lib/str-two-way.h
@@ -0,0 +1,452 @@
+/* Byte-wise substring search, using the Two-Way algorithm.
+ Copyright (C) 2008-2022 Free Software Foundation, Inc.
+ This file is part of the GNU C Library.
+ Written by Eric Blake <ebb9@byu.net>, 2008.
+
+ This file is free software: you can redistribute it and/or modify
+ it under the terms of the GNU Lesser General Public License as
+ published by the Free Software Foundation; either version 2.1 of the
+ License, or (at your option) any later version.
+
+ This file 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 Lesser General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public License
+ along with this program. If not, see <https://www.gnu.org/licenses/>. */
+
+/* Before including this file, you need to include <config.h> and
+ <string.h>, and define:
+ RETURN_TYPE A macro that expands to the return type.
+ AVAILABLE(h, h_l, j, n_l)
+ A macro that returns nonzero if there are
+ at least N_L bytes left starting at H[J].
+ H is 'unsigned char *', H_L, J, and N_L
+ are 'size_t'; H_L is an lvalue. For
+ NUL-terminated searches, H_L can be
+ modified each iteration to avoid having
+ to compute the end of H up front.
+
+ For case-insensitivity, you may optionally define:
+ CMP_FUNC(p1, p2, l) A macro that returns 0 iff the first L
+ characters of P1 and P2 are equal.
+ CANON_ELEMENT(c) A macro that canonicalizes an element right after
+ it has been fetched from one of the two strings.
+ The argument is an 'unsigned char'; the result
+ must be an 'unsigned char' as well.
+
+ This file undefines the macros documented above, and defines
+ LONG_NEEDLE_THRESHOLD.
+*/
+
+#include <limits.h>
+#include <stdint.h>
+
+/* We use the Two-Way string matching algorithm (also known as
+ Chrochemore-Perrin), which guarantees linear complexity with
+ constant space. Additionally, for long needles, we also use a bad
+ character shift table similar to the Boyer-Moore algorithm to
+ achieve improved (potentially sub-linear) performance.
+
+ See https://www-igm.univ-mlv.fr/~lecroq/string/node26.html#SECTION00260,
+ https://en.wikipedia.org/wiki/Boyer-Moore_string_search_algorithm,
+ https://citeseerx.ist.psu.edu/viewdoc/download?doi=10.1.1.34.6641&rep=rep1&type=pdf
+*/
+
+/* Point at which computing a bad-byte shift table is likely to be
+ worthwhile. Small needles should not compute a table, since it
+ adds (1 << CHAR_BIT) + NEEDLE_LEN computations of preparation for a
+ speedup no greater than a factor of NEEDLE_LEN. The larger the
+ needle, the better the potential performance gain. On the other
+ hand, on non-POSIX systems with CHAR_BIT larger than eight, the
+ memory required for the table is prohibitive. */
+#if CHAR_BIT < 10
+# define LONG_NEEDLE_THRESHOLD 32U
+#else
+# define LONG_NEEDLE_THRESHOLD SIZE_MAX
+#endif
+
+#ifndef MAX
+# define MAX(a, b) ((a < b) ? (b) : (a))
+#endif
+
+#ifndef CANON_ELEMENT
+# define CANON_ELEMENT(c) c
+#endif
+#ifndef CMP_FUNC
+# define CMP_FUNC memcmp
+#endif
+
+/* Perform a critical factorization of NEEDLE, of length NEEDLE_LEN.
+ Return the index of the first byte in the right half, and set
+ *PERIOD to the global period of the right half.
+
+ The global period of a string is the smallest index (possibly its
+ length) at which all remaining bytes in the string are repetitions
+ of the prefix (the last repetition may be a subset of the prefix).
+
+ When NEEDLE is factored into two halves, a local period is the
+ length of the smallest word that shares a suffix with the left half
+ and shares a prefix with the right half. All factorizations of a
+ non-empty NEEDLE have a local period of at least 1 and no greater
+ than NEEDLE_LEN.
+
+ A critical factorization has the property that the local period
+ equals the global period. All strings have at least one critical
+ factorization with the left half smaller than the global period.
+ And while some strings have more than one critical factorization,
+ it is provable that with an ordered alphabet, at least one of the
+ critical factorizations corresponds to a maximal suffix.
+
+ Given an ordered alphabet, a critical factorization can be computed
+ in linear time, with 2 * NEEDLE_LEN comparisons, by computing the
+ shorter of two ordered maximal suffixes. The ordered maximal
+ suffixes are determined by lexicographic comparison while tracking
+ periodicity. */
+static size_t
+critical_factorization (const unsigned char *needle, size_t needle_len,
+ size_t *period)
+{
+ /* Index of last byte of left half, or SIZE_MAX. */
+ size_t max_suffix, max_suffix_rev;
+ size_t j; /* Index into NEEDLE for current candidate suffix. */
+ size_t k; /* Offset into current period. */
+ size_t p; /* Intermediate period. */
+ unsigned char a, b; /* Current comparison bytes. */
+
+ /* Special case NEEDLE_LEN of 1 or 2 (all callers already filtered
+ out 0-length needles. */
+ if (needle_len < 3)
+ {
+ *period = 1;
+ return needle_len - 1;
+ }
+
+ /* Invariants:
+ 0 <= j < NEEDLE_LEN - 1
+ -1 <= max_suffix{,_rev} < j (treating SIZE_MAX as if it were signed)
+ min(max_suffix, max_suffix_rev) < global period of NEEDLE
+ 1 <= p <= global period of NEEDLE
+ p == global period of the substring NEEDLE[max_suffix{,_rev}+1...j]
+ 1 <= k <= p
+ */
+
+ /* Perform lexicographic search. */
+ max_suffix = SIZE_MAX;
+ j = 0;
+ k = p = 1;
+ while (j + k < needle_len)
+ {
+ a = CANON_ELEMENT (needle[j + k]);
+ b = CANON_ELEMENT (needle[max_suffix + k]);
+ if (a < b)
+ {
+ /* Suffix is smaller, period is entire prefix so far. */
+ j += k;
+ k = 1;
+ p = j - max_suffix;
+ }
+ else if (a == b)
+ {
+ /* Advance through repetition of the current period. */
+ if (k != p)
+ ++k;
+ else
+ {
+ j += p;
+ k = 1;
+ }
+ }
+ else /* b < a */
+ {
+ /* Suffix is larger, start over from current location. */
+ max_suffix = j++;
+ k = p = 1;
+ }
+ }
+ *period = p;
+
+ /* Perform reverse lexicographic search. */
+ max_suffix_rev = SIZE_MAX;
+ j = 0;
+ k = p = 1;
+ while (j + k < needle_len)
+ {
+ a = CANON_ELEMENT (needle[j + k]);
+ b = CANON_ELEMENT (needle[max_suffix_rev + k]);
+ if (b < a)
+ {
+ /* Suffix is smaller, period is entire prefix so far. */
+ j += k;
+ k = 1;
+ p = j - max_suffix_rev;
+ }
+ else if (a == b)
+ {
+ /* Advance through repetition of the current period. */
+ if (k != p)
+ ++k;
+ else
+ {
+ j += p;
+ k = 1;
+ }
+ }
+ else /* a < b */
+ {
+ /* Suffix is larger, start over from current location. */
+ max_suffix_rev = j++;
+ k = p = 1;
+ }
+ }
+
+ /* Choose the shorter suffix. Return the index of the first byte of
+ the right half, rather than the last byte of the left half.
+
+ For some examples, 'banana' has two critical factorizations, both
+ exposed by the two lexicographic extreme suffixes of 'anana' and
+ 'nana', where both suffixes have a period of 2. On the other
+ hand, with 'aab' and 'bba', both strings have a single critical
+ factorization of the last byte, with the suffix having a period
+ of 1. While the maximal lexicographic suffix of 'aab' is 'b',
+ the maximal lexicographic suffix of 'bba' is 'ba', which is not a
+ critical factorization. Conversely, the maximal reverse
+ lexicographic suffix of 'a' works for 'bba', but not 'ab' for
+ 'aab'. The shorter suffix of the two will always be a critical
+ factorization. */
+ if (max_suffix_rev + 1 < max_suffix + 1)
+ return max_suffix + 1;
+ *period = p;
+ return max_suffix_rev + 1;
+}
+
+/* Return the first location of non-empty NEEDLE within HAYSTACK, or
+ NULL. HAYSTACK_LEN is the minimum known length of HAYSTACK. This
+ method is optimized for NEEDLE_LEN < LONG_NEEDLE_THRESHOLD.
+ Performance is guaranteed to be linear, with an initialization cost
+ of 2 * NEEDLE_LEN comparisons.
+
+ If AVAILABLE does not modify HAYSTACK_LEN (as in memmem), then at
+ most 2 * HAYSTACK_LEN - NEEDLE_LEN comparisons occur in searching.
+ If AVAILABLE modifies HAYSTACK_LEN (as in strstr), then at most 3 *
+ HAYSTACK_LEN - NEEDLE_LEN comparisons occur in searching. */
+static RETURN_TYPE _GL_ATTRIBUTE_PURE
+two_way_short_needle (const unsigned char *haystack, size_t haystack_len,
+ const unsigned char *needle, size_t needle_len)
+{
+ size_t i; /* Index into current byte of NEEDLE. */
+ size_t j; /* Index into current window of HAYSTACK. */
+ size_t period; /* The period of the right half of needle. */
+ size_t suffix; /* The index of the right half of needle. */
+
+ /* Factor the needle into two halves, such that the left half is
+ smaller than the global period, and the right half is
+ periodic (with a period as large as NEEDLE_LEN - suffix). */
+ suffix = critical_factorization (needle, needle_len, &period);
+
+ /* Perform the search. Each iteration compares the right half
+ first. */
+ if (CMP_FUNC (needle, needle + period, suffix) == 0)
+ {
+ /* Entire needle is periodic; a mismatch in the left half can
+ only advance by the period, so use memory to avoid rescanning
+ known occurrences of the period in the right half. */
+ size_t memory = 0;
+ j = 0;
+ while (AVAILABLE (haystack, haystack_len, j, needle_len))
+ {
+ /* Scan for matches in right half. */
+ i = MAX (suffix, memory);
+ while (i < needle_len && (CANON_ELEMENT (needle[i])
+ == CANON_ELEMENT (haystack[i + j])))
+ ++i;
+ if (needle_len <= i)
+ {
+ /* Scan for matches in left half. */
+ i = suffix - 1;
+ while (memory < i + 1 && (CANON_ELEMENT (needle[i])
+ == CANON_ELEMENT (haystack[i + j])))
+ --i;
+ if (i + 1 < memory + 1)
+ return (RETURN_TYPE) (haystack + j);
+ /* No match, so remember how many repetitions of period
+ on the right half were scanned. */
+ j += period;
+ memory = needle_len - period;
+ }
+ else
+ {
+ j += i - suffix + 1;
+ memory = 0;
+ }
+ }
+ }
+ else
+ {
+ /* The two halves of needle are distinct; no extra memory is
+ required, and any mismatch results in a maximal shift. */
+ period = MAX (suffix, needle_len - suffix) + 1;
+ j = 0;
+ while (AVAILABLE (haystack, haystack_len, j, needle_len))
+ {
+ /* Scan for matches in right half. */
+ i = suffix;
+ while (i < needle_len && (CANON_ELEMENT (needle[i])
+ == CANON_ELEMENT (haystack[i + j])))
+ ++i;
+ if (needle_len <= i)
+ {
+ /* Scan for matches in left half. */
+ i = suffix - 1;
+ while (i != SIZE_MAX && (CANON_ELEMENT (needle[i])
+ == CANON_ELEMENT (haystack[i + j])))
+ --i;
+ if (i == SIZE_MAX)
+ return (RETURN_TYPE) (haystack + j);
+ j += period;
+ }
+ else
+ j += i - suffix + 1;
+ }
+ }
+ return NULL;
+}
+
+/* Return the first location of non-empty NEEDLE within HAYSTACK, or
+ NULL. HAYSTACK_LEN is the minimum known length of HAYSTACK. This
+ method is optimized for LONG_NEEDLE_THRESHOLD <= NEEDLE_LEN.
+ Performance is guaranteed to be linear, with an initialization cost
+ of 3 * NEEDLE_LEN + (1 << CHAR_BIT) operations.
+
+ If AVAILABLE does not modify HAYSTACK_LEN (as in memmem), then at
+ most 2 * HAYSTACK_LEN - NEEDLE_LEN comparisons occur in searching,
+ and sublinear performance O(HAYSTACK_LEN / NEEDLE_LEN) is possible.
+ If AVAILABLE modifies HAYSTACK_LEN (as in strstr), then at most 3 *
+ HAYSTACK_LEN - NEEDLE_LEN comparisons occur in searching, and
+ sublinear performance is not possible. */
+static RETURN_TYPE _GL_ATTRIBUTE_PURE
+two_way_long_needle (const unsigned char *haystack, size_t haystack_len,
+ const unsigned char *needle, size_t needle_len)
+{
+ size_t i; /* Index into current byte of NEEDLE. */
+ size_t j; /* Index into current window of HAYSTACK. */
+ size_t period; /* The period of the right half of needle. */
+ size_t suffix; /* The index of the right half of needle. */
+ size_t shift_table[1U << CHAR_BIT]; /* See below. */
+
+ /* Factor the needle into two halves, such that the left half is
+ smaller than the global period, and the right half is
+ periodic (with a period as large as NEEDLE_LEN - suffix). */
+ suffix = critical_factorization (needle, needle_len, &period);
+
+ /* Populate shift_table. For each possible byte value c,
+ shift_table[c] is the distance from the last occurrence of c to
+ the end of NEEDLE, or NEEDLE_LEN if c is absent from the NEEDLE.
+ shift_table[NEEDLE[NEEDLE_LEN - 1]] contains the only 0. */
+ for (i = 0; i < 1U << CHAR_BIT; i++)
+ shift_table[i] = needle_len;
+ for (i = 0; i < needle_len; i++)
+ shift_table[CANON_ELEMENT (needle[i])] = needle_len - i - 1;
+
+ /* Perform the search. Each iteration compares the right half
+ first. */
+ if (CMP_FUNC (needle, needle + period, suffix) == 0)
+ {
+ /* Entire needle is periodic; a mismatch in the left half can
+ only advance by the period, so use memory to avoid rescanning
+ known occurrences of the period in the right half. */
+ size_t memory = 0;
+ size_t shift;
+ j = 0;
+ while (AVAILABLE (haystack, haystack_len, j, needle_len))
+ {
+ /* Check the last byte first; if it does not match, then
+ shift to the next possible match location. */
+ shift = shift_table[CANON_ELEMENT (haystack[j + needle_len - 1])];
+ if (0 < shift)
+ {
+ if (memory && shift < period)
+ {
+ /* Since needle is periodic, but the last period has
+ a byte out of place, there can be no match until
+ after the mismatch. */
+ shift = needle_len - period;
+ }
+ memory = 0;
+ j += shift;
+ continue;
+ }
+ /* Scan for matches in right half. The last byte has
+ already been matched, by virtue of the shift table. */
+ i = MAX (suffix, memory);
+ while (i < needle_len - 1 && (CANON_ELEMENT (needle[i])
+ == CANON_ELEMENT (haystack[i + j])))
+ ++i;
+ if (needle_len - 1 <= i)
+ {
+ /* Scan for matches in left half. */
+ i = suffix - 1;
+ while (memory < i + 1 && (CANON_ELEMENT (needle[i])
+ == CANON_ELEMENT (haystack[i + j])))
+ --i;
+ if (i + 1 < memory + 1)
+ return (RETURN_TYPE) (haystack + j);
+ /* No match, so remember how many repetitions of period
+ on the right half were scanned. */
+ j += period;
+ memory = needle_len - period;
+ }
+ else
+ {
+ j += i - suffix + 1;
+ memory = 0;
+ }
+ }
+ }
+ else
+ {
+ /* The two halves of needle are distinct; no extra memory is
+ required, and any mismatch results in a maximal shift. */
+ size_t shift;
+ period = MAX (suffix, needle_len - suffix) + 1;
+ j = 0;
+ while (AVAILABLE (haystack, haystack_len, j, needle_len))
+ {
+ /* Check the last byte first; if it does not match, then
+ shift to the next possible match location. */
+ shift = shift_table[CANON_ELEMENT (haystack[j + needle_len - 1])];
+ if (0 < shift)
+ {
+ j += shift;
+ continue;
+ }
+ /* Scan for matches in right half. The last byte has
+ already been matched, by virtue of the shift table. */
+ i = suffix;
+ while (i < needle_len - 1 && (CANON_ELEMENT (needle[i])
+ == CANON_ELEMENT (haystack[i + j])))
+ ++i;
+ if (needle_len - 1 <= i)
+ {
+ /* Scan for matches in left half. */
+ i = suffix - 1;
+ while (i != SIZE_MAX && (CANON_ELEMENT (needle[i])
+ == CANON_ELEMENT (haystack[i + j])))
+ --i;
+ if (i == SIZE_MAX)
+ return (RETURN_TYPE) (haystack + j);
+ j += period;
+ }
+ else
+ j += i - suffix + 1;
+ }
+ }
+ return NULL;
+}
+
+#undef AVAILABLE
+#undef CANON_ELEMENT
+#undef CMP_FUNC
+#undef MAX
+#undef RETURN_TYPE
diff --git a/lib/strftime.h b/lib/strftime.h
index 9d91e5139cd..a9847084f01 100644
--- a/lib/strftime.h
+++ b/lib/strftime.h
@@ -1,18 +1,18 @@
/* declarations for strftime.c
- Copyright (C) 2002, 2004, 2008-2017 Free Software Foundation, Inc.
+ Copyright (C) 2002, 2004, 2008-2022 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 file is free software: you can redistribute it and/or modify
+ it under the terms of the GNU Lesser 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,
+ This file 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.
+ GNU Lesser General Public License for more details.
- You should have received a copy of the GNU General Public License
+ You should have received a copy of the GNU Lesser General Public License
along with this program. If not, see <https://www.gnu.org/licenses/>. */
#include <time.h>
@@ -24,8 +24,13 @@ extern "C" {
/* Just like strftime, but with two more arguments:
POSIX requires that strftime use the local timezone information.
Use the timezone __TZ instead. Use __NS as the number of
- nanoseconds in the %N directive. */
-size_t nstrftime (char *, size_t, char const *, struct tm const *,
+ nanoseconds in the %N directive.
+
+ On error, set errno and return 0. Otherwise, return the number of
+ bytes generated (not counting the trailing NUL), preserving errno
+ if the number is 0. This errno behavior is in draft POSIX 202x
+ plus some requested changes to POSIX. */
+size_t nstrftime (char *restrict, size_t, char const *, struct tm const *,
timezone_t __tz, int __ns);
#ifdef __cplusplus
diff --git a/lib/string.in.h b/lib/string.in.h
index 0e0e0c51f5e..3996da9fcb5 100644
--- a/lib/string.in.h
+++ b/lib/string.in.h
@@ -1,19 +1,19 @@
/* A GNU-like <string.h>.
- Copyright (C) 1995-1996, 2001-2017 Free Software Foundation, Inc.
+ Copyright (C) 1995-1996, 2001-2022 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 file is free software: you can redistribute it and/or modify
+ it under the terms of the GNU Lesser General Public License as
+ published by the Free Software Foundation; either version 2.1 of the
+ License, or (at your option) any later version.
- This program is distributed in the hope that it will be useful,
+ This file 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.
+ GNU Lesser General Public License for more details.
- You should have received a copy of the GNU General Public License
- along with this program; if not, see <https://www.gnu.org/licenses/>. */
+ You should have received a copy of the GNU Lesser General Public License
+ along with this program. If not, see <https://www.gnu.org/licenses/>. */
#if __GNUC__ >= 3
@PRAGMA_SYSTEM_HEADER@
@@ -52,14 +52,6 @@
# include <wchar.h>
#endif
-/* The __attribute__ feature is available in gcc versions 2.5 and later.
- The attribute __pure__ was added in gcc 2.96. */
-#if __GNUC__ > 2 || (__GNUC__ == 2 && __GNUC_MINOR__ >= 96)
-# define _GL_ATTRIBUTE_PURE __attribute__ ((__pure__))
-#else
-# define _GL_ATTRIBUTE_PURE /* empty */
-#endif
-
/* NetBSD 5.0 declares strsignal in <unistd.h>, not in <string.h>. */
/* But in any case avoid namespace pollution on glibc systems. */
#if (@GNULIB_STRSIGNAL@ || defined GNULIB_POSIXCHECK) && defined __NetBSD__ \
@@ -67,12 +59,98 @@
# include <unistd.h>
#endif
+/* AIX 7.2 declares ffsl and ffsll in <strings.h>, not in <string.h>. */
+/* But in any case avoid namespace pollution on glibc systems. */
+#if ((@GNULIB_FFSL@ || @GNULIB_FFSLL@ || defined GNULIB_POSIXCHECK) \
+ && defined _AIX) \
+ && ! defined __GLIBC__
+# include <strings.h>
+#endif
+
+/* _GL_ATTRIBUTE_DEALLOC (F, I) declares that the function returns pointers
+ that can be freed by passing them as the Ith argument to the
+ function F. */
+#ifndef _GL_ATTRIBUTE_DEALLOC
+# if __GNUC__ >= 11
+# define _GL_ATTRIBUTE_DEALLOC(f, i) __attribute__ ((__malloc__ (f, i)))
+# else
+# define _GL_ATTRIBUTE_DEALLOC(f, i)
+# endif
+#endif
+
+/* _GL_ATTRIBUTE_DEALLOC_FREE declares that the function returns pointers that
+ can be freed via 'free'; it can be used only after declaring 'free'. */
+/* Applies to: functions. Cannot be used on inline functions. */
+#ifndef _GL_ATTRIBUTE_DEALLOC_FREE
+# define _GL_ATTRIBUTE_DEALLOC_FREE _GL_ATTRIBUTE_DEALLOC (free, 1)
+#endif
+
+/* _GL_ATTRIBUTE_MALLOC declares that the function returns a pointer to freshly
+ allocated memory. */
+/* Applies to: functions. */
+#ifndef _GL_ATTRIBUTE_MALLOC
+# if __GNUC__ >= 3 || defined __clang__
+# define _GL_ATTRIBUTE_MALLOC __attribute__ ((__malloc__))
+# else
+# define _GL_ATTRIBUTE_MALLOC
+# endif
+#endif
+
+/* The __attribute__ feature is available in gcc versions 2.5 and later.
+ The attribute __pure__ was added in gcc 2.96. */
+#ifndef _GL_ATTRIBUTE_PURE
+# if __GNUC__ > 2 || (__GNUC__ == 2 && __GNUC_MINOR__ >= 96) || defined __clang__
+# define _GL_ATTRIBUTE_PURE __attribute__ ((__pure__))
+# else
+# define _GL_ATTRIBUTE_PURE /* empty */
+# endif
+#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. */
+/* Make _GL_ATTRIBUTE_DEALLOC_FREE work, even though <stdlib.h> may not have
+ been included yet. */
+#if @GNULIB_FREE_POSIX@
+# if (@REPLACE_FREE@ && !defined free \
+ && !(defined __cplusplus && defined GNULIB_NAMESPACE))
+/* We can't do '#define free rpl_free' here. */
+_GL_EXTERN_C void rpl_free (void *);
+# undef _GL_ATTRIBUTE_DEALLOC_FREE
+# define _GL_ATTRIBUTE_DEALLOC_FREE _GL_ATTRIBUTE_DEALLOC (rpl_free, 1)
+# else
+# if defined _MSC_VER && !defined free
+_GL_EXTERN_C
+# if defined _DLL
+ __declspec (dllimport)
+# endif
+ void __cdecl free (void *);
+# else
+# if defined __cplusplus && (__GLIBC__ + (__GLIBC_MINOR__ >= 14) > 2)
+_GL_EXTERN_C void free (void *) throw ();
+# else
+_GL_EXTERN_C void free (void *);
+# endif
+# endif
+# endif
+#else
+# if defined _MSC_VER && !defined free
+_GL_EXTERN_C
+# if defined _DLL
+ __declspec (dllimport)
+# endif
+ void __cdecl free (void *);
+# else
+# if defined __cplusplus && (__GLIBC__ + (__GLIBC_MINOR__ >= 14) > 2)
+_GL_EXTERN_C void free (void *) throw ();
+# else
+_GL_EXTERN_C void free (void *);
+# endif
+# endif
+#endif
/* Clear a block of memory. The compiler will not delete a call to
this function, even if the block is dead after the call. */
@@ -108,10 +186,18 @@ _GL_WARN_ON_USE (ffsl, "ffsl is not portable - use the ffsl module");
/* Find the index of the least-significant set bit. */
#if @GNULIB_FFSLL@
-# if !@HAVE_FFSLL@
+# if @REPLACE_FFSLL@
+# if !(defined __cplusplus && defined GNULIB_NAMESPACE)
+# define ffsll rpl_ffsll
+# endif
+_GL_FUNCDECL_RPL (ffsll, int, (long long int i));
+_GL_CXXALIAS_RPL (ffsll, int, (long long int i));
+# else
+# if !@HAVE_FFSLL@
_GL_FUNCDECL_SYS (ffsll, int, (long long int i));
-# endif
+# endif
_GL_CXXALIAS_SYS (ffsll, int, (long long int i));
+# endif
_GL_CXXALIASWARN (ffsll);
#elif defined GNULIB_POSIXCHECK
# undef ffsll
@@ -121,10 +207,30 @@ _GL_WARN_ON_USE (ffsll, "ffsll is not portable - use the ffsll module");
#endif
+#if @GNULIB_MDA_MEMCCPY@
+/* On native Windows, map 'memccpy' to '_memccpy', so that -loldnames is not
+ required. In C++ with GNULIB_NAMESPACE, avoid differences between
+ platforms by defining GNULIB_NAMESPACE::memccpy always. */
+# if defined _WIN32 && !defined __CYGWIN__
+# if !(defined __cplusplus && defined GNULIB_NAMESPACE)
+# undef memccpy
+# define memccpy _memccpy
+# endif
+_GL_CXXALIAS_MDA (memccpy, void *,
+ (void *dest, const void *src, int c, size_t n));
+# else
+_GL_CXXALIAS_SYS (memccpy, void *,
+ (void *dest, const void *src, int c, size_t n));
+# endif
+_GL_CXXALIASWARN (memccpy);
+#endif
+
+
/* Return the first instance of C within N bytes of S, or NULL. */
#if @GNULIB_MEMCHR@
# if @REPLACE_MEMCHR@
# if !(defined __cplusplus && defined GNULIB_NAMESPACE)
+# undef memchr
# define memchr rpl_memchr
# endif
_GL_FUNCDECL_RPL (memchr, void *, (void const *__s, int __c, size_t __n)
@@ -132,11 +238,6 @@ _GL_FUNCDECL_RPL (memchr, void *, (void const *__s, int __c, size_t __n)
_GL_ARG_NONNULL ((1)));
_GL_CXXALIAS_RPL (memchr, void *, (void const *__s, int __c, size_t __n));
# else
-# if ! @HAVE_MEMCHR@
-_GL_FUNCDECL_SYS (memchr, void *, (void const *__s, int __c, size_t __n)
- _GL_ATTRIBUTE_PURE
- _GL_ARG_NONNULL ((1)));
-# endif
/* On some systems, this function is defined as an overloaded function:
extern "C" { const void * std::memchr (const void *, int, size_t); }
extern "C++" { void * std::memchr (void *, int, size_t); } */
@@ -145,11 +246,12 @@ _GL_CXXALIAS_SYS_CAST2 (memchr,
void const *, (void const *__s, int __c, size_t __n));
# endif
# if ((__GLIBC__ == 2 && __GLIBC_MINOR__ >= 10) && !defined __UCLIBC__) \
- && (__GNUC__ > 4 || (__GNUC__ == 4 && __GNUC_MINOR__ >= 4))
-_GL_CXXALIASWARN1 (memchr, void *, (void *__s, int __c, size_t __n));
+ && (__GNUC__ > 4 || (__GNUC__ == 4 && __GNUC_MINOR__ >= 4) \
+ || defined __clang__)
+_GL_CXXALIASWARN1 (memchr, void *, (void *__s, int __c, size_t __n) throw ());
_GL_CXXALIASWARN1 (memchr, void const *,
- (void const *__s, int __c, size_t __n));
-# else
+ (void const *__s, int __c, size_t __n) throw ());
+# elif __GLIBC__ >= 2
_GL_CXXALIASWARN (memchr);
# endif
#elif defined GNULIB_POSIXCHECK
@@ -230,9 +332,10 @@ _GL_CXXALIAS_SYS_CAST2 (memrchr,
void *, (void const *, int, size_t),
void const *, (void const *, int, size_t));
# if ((__GLIBC__ == 2 && __GLIBC_MINOR__ >= 10) && !defined __UCLIBC__) \
- && (__GNUC__ > 4 || (__GNUC__ == 4 && __GNUC_MINOR__ >= 4))
-_GL_CXXALIASWARN1 (memrchr, void *, (void *, int, size_t));
-_GL_CXXALIASWARN1 (memrchr, void const *, (void const *, int, size_t));
+ && (__GNUC__ > 4 || (__GNUC__ == 4 && __GNUC_MINOR__ >= 4) \
+ || defined __clang__)
+_GL_CXXALIASWARN1 (memrchr, void *, (void *, int, size_t) throw ());
+_GL_CXXALIASWARN1 (memrchr, void const *, (void const *, int, size_t) throw ());
# else
_GL_CXXALIASWARN (memrchr);
# endif
@@ -260,9 +363,11 @@ _GL_CXXALIAS_SYS_CAST2 (rawmemchr,
void *, (void const *__s, int __c_in),
void const *, (void const *__s, int __c_in));
# if ((__GLIBC__ == 2 && __GLIBC_MINOR__ >= 10) && !defined __UCLIBC__) \
- && (__GNUC__ > 4 || (__GNUC__ == 4 && __GNUC_MINOR__ >= 4))
-_GL_CXXALIASWARN1 (rawmemchr, void *, (void *__s, int __c_in));
-_GL_CXXALIASWARN1 (rawmemchr, void const *, (void const *__s, int __c_in));
+ && (__GNUC__ > 4 || (__GNUC__ == 4 && __GNUC_MINOR__ >= 4) \
+ || defined __clang__)
+_GL_CXXALIASWARN1 (rawmemchr, void *, (void *__s, int __c_in) throw ());
+_GL_CXXALIASWARN1 (rawmemchr, void const *,
+ (void const *__s, int __c_in) throw ());
# else
_GL_CXXALIASWARN (rawmemchr);
# endif
@@ -332,9 +437,11 @@ _GL_WARN_ON_USE (stpncpy, "stpncpy is unportable - "
GB18030 and the character to be searched is a digit. */
# undef strchr
/* Assume strchr is always declared. */
-_GL_WARN_ON_USE (strchr, "strchr cannot work correctly on character strings "
- "in some multibyte locales - "
- "use mbschr if you care about internationalization");
+_GL_WARN_ON_USE_CXX (strchr,
+ const char *, char *, (const char *, int),
+ "strchr cannot work correctly on character strings "
+ "in some multibyte locales - "
+ "use mbschr if you care about internationalization");
#endif
/* Find the first occurrence of C in S or the final NUL byte. */
@@ -362,9 +469,11 @@ _GL_CXXALIAS_SYS_CAST2 (strchrnul,
char const *, (char const *__s, int __c_in));
# endif
# if ((__GLIBC__ == 2 && __GLIBC_MINOR__ >= 10) && !defined __UCLIBC__) \
- && (__GNUC__ > 4 || (__GNUC__ == 4 && __GNUC_MINOR__ >= 4))
-_GL_CXXALIASWARN1 (strchrnul, char *, (char *__s, int __c_in));
-_GL_CXXALIASWARN1 (strchrnul, char const *, (char const *__s, int __c_in));
+ && (__GNUC__ > 4 || (__GNUC__ == 4 && __GNUC_MINOR__ >= 4) \
+ || defined __clang__)
+_GL_CXXALIASWARN1 (strchrnul, char *, (char *__s, int __c_in) throw ());
+_GL_CXXALIASWARN1 (strchrnul, char const *,
+ (char const *__s, int __c_in) throw ());
# else
_GL_CXXALIASWARN (strchrnul);
# endif
@@ -383,24 +492,62 @@ _GL_WARN_ON_USE (strchrnul, "strchrnul is unportable - "
# undef strdup
# define strdup rpl_strdup
# endif
-_GL_FUNCDECL_RPL (strdup, char *, (char const *__s) _GL_ARG_NONNULL ((1)));
+_GL_FUNCDECL_RPL (strdup, char *,
+ (char const *__s)
+ _GL_ARG_NONNULL ((1))
+ _GL_ATTRIBUTE_MALLOC _GL_ATTRIBUTE_DEALLOC_FREE);
_GL_CXXALIAS_RPL (strdup, char *, (char const *__s));
+# elif defined _WIN32 && !defined __CYGWIN__
+# if !(defined __cplusplus && defined GNULIB_NAMESPACE)
+# undef strdup
+# define strdup _strdup
+# endif
+_GL_CXXALIAS_MDA (strdup, char *, (char const *__s));
# else
# if defined __cplusplus && defined GNULIB_NAMESPACE && defined strdup
/* strdup exists as a function and as a macro. Get rid of the macro. */
# undef strdup
# endif
-# if !(@HAVE_DECL_STRDUP@ || defined strdup)
-_GL_FUNCDECL_SYS (strdup, char *, (char const *__s) _GL_ARG_NONNULL ((1)));
+# if (!@HAVE_DECL_STRDUP@ || __GNUC__ >= 11) && !defined strdup
+_GL_FUNCDECL_SYS (strdup, char *,
+ (char const *__s)
+ _GL_ARG_NONNULL ((1))
+ _GL_ATTRIBUTE_MALLOC _GL_ATTRIBUTE_DEALLOC_FREE);
# endif
_GL_CXXALIAS_SYS (strdup, char *, (char const *__s));
# endif
_GL_CXXALIASWARN (strdup);
-#elif defined GNULIB_POSIXCHECK
-# undef strdup
-# if HAVE_RAW_DECL_STRDUP
+#else
+# if __GNUC__ >= 11 && !defined strdup
+/* For -Wmismatched-dealloc: Associate strdup with free or rpl_free. */
+_GL_FUNCDECL_SYS (strdup, char *,
+ (char const *__s)
+ _GL_ARG_NONNULL ((1))
+ _GL_ATTRIBUTE_MALLOC _GL_ATTRIBUTE_DEALLOC_FREE);
+# endif
+# if defined GNULIB_POSIXCHECK
+# undef strdup
+# if HAVE_RAW_DECL_STRDUP
_GL_WARN_ON_USE (strdup, "strdup is unportable - "
"use gnulib module strdup for portability");
+# endif
+# elif @GNULIB_MDA_STRDUP@
+/* On native Windows, map 'creat' to '_creat', so that -loldnames is not
+ required. In C++ with GNULIB_NAMESPACE, avoid differences between
+ platforms by defining GNULIB_NAMESPACE::strdup always. */
+# if defined _WIN32 && !defined __CYGWIN__
+# if !(defined __cplusplus && defined GNULIB_NAMESPACE)
+# undef strdup
+# define strdup _strdup
+# endif
+_GL_CXXALIAS_MDA (strdup, char *, (char const *__s));
+# else
+# if defined __cplusplus && defined GNULIB_NAMESPACE && defined strdup
+# undef strdup
+# endif
+_GL_CXXALIAS_SYS (strdup, char *, (char const *__s));
+# endif
+_GL_CXXALIASWARN (strdup);
# endif
#endif
@@ -411,13 +558,18 @@ _GL_WARN_ON_USE (strdup, "strdup is unportable - "
# undef strncat
# define strncat rpl_strncat
# endif
-_GL_FUNCDECL_RPL (strncat, char *, (char *dest, const char *src, size_t n)
- _GL_ARG_NONNULL ((1, 2)));
-_GL_CXXALIAS_RPL (strncat, char *, (char *dest, const char *src, size_t n));
+_GL_FUNCDECL_RPL (strncat, char *,
+ (char *restrict dest, const char *restrict src, size_t n)
+ _GL_ARG_NONNULL ((1, 2)));
+_GL_CXXALIAS_RPL (strncat, char *,
+ (char *restrict dest, const char *restrict src, size_t n));
# else
-_GL_CXXALIAS_SYS (strncat, char *, (char *dest, const char *src, size_t n));
+_GL_CXXALIAS_SYS (strncat, char *,
+ (char *restrict dest, const char *restrict src, size_t n));
# endif
+# if __GLIBC__ >= 2
_GL_CXXALIASWARN (strncat);
+# endif
#elif defined GNULIB_POSIXCHECK
# undef strncat
# if HAVE_RAW_DECL_STRNCAT
@@ -433,22 +585,35 @@ _GL_WARN_ON_USE (strncat, "strncat is unportable - "
# undef strndup
# define strndup rpl_strndup
# endif
-_GL_FUNCDECL_RPL (strndup, char *, (char const *__s, size_t __n)
- _GL_ARG_NONNULL ((1)));
+_GL_FUNCDECL_RPL (strndup, char *,
+ (char const *__s, size_t __n)
+ _GL_ARG_NONNULL ((1))
+ _GL_ATTRIBUTE_MALLOC _GL_ATTRIBUTE_DEALLOC_FREE);
_GL_CXXALIAS_RPL (strndup, char *, (char const *__s, size_t __n));
# else
-# if ! @HAVE_DECL_STRNDUP@
-_GL_FUNCDECL_SYS (strndup, char *, (char const *__s, size_t __n)
- _GL_ARG_NONNULL ((1)));
+# if !@HAVE_DECL_STRNDUP@ || (__GNUC__ >= 11 && !defined strndup)
+_GL_FUNCDECL_SYS (strndup, char *,
+ (char const *__s, size_t __n)
+ _GL_ARG_NONNULL ((1))
+ _GL_ATTRIBUTE_MALLOC _GL_ATTRIBUTE_DEALLOC_FREE);
# endif
_GL_CXXALIAS_SYS (strndup, char *, (char const *__s, size_t __n));
# endif
_GL_CXXALIASWARN (strndup);
-#elif defined GNULIB_POSIXCHECK
-# undef strndup
-# if HAVE_RAW_DECL_STRNDUP
+#else
+# if __GNUC__ >= 11 && !defined strndup
+/* For -Wmismatched-dealloc: Associate strndup with free or rpl_free. */
+_GL_FUNCDECL_SYS (strndup, char *,
+ (char const *__s, size_t __n)
+ _GL_ARG_NONNULL ((1))
+ _GL_ATTRIBUTE_MALLOC _GL_ATTRIBUTE_DEALLOC_FREE);
+# endif
+# if defined GNULIB_POSIXCHECK
+# undef strndup
+# if HAVE_RAW_DECL_STRNDUP
_GL_WARN_ON_USE (strndup, "strndup is unportable - "
"use gnulib module strndup for portability");
+# endif
# endif
#endif
@@ -508,11 +673,12 @@ _GL_CXXALIAS_SYS_CAST2 (strpbrk,
char *, (char const *__s, char const *__accept),
const char *, (char const *__s, char const *__accept));
# if ((__GLIBC__ == 2 && __GLIBC_MINOR__ >= 10) && !defined __UCLIBC__) \
- && (__GNUC__ > 4 || (__GNUC__ == 4 && __GNUC_MINOR__ >= 4))
-_GL_CXXALIASWARN1 (strpbrk, char *, (char *__s, char const *__accept));
+ && (__GNUC__ > 4 || (__GNUC__ == 4 && __GNUC_MINOR__ >= 4) \
+ || defined __clang__)
+_GL_CXXALIASWARN1 (strpbrk, char *, (char *__s, char const *__accept) throw ());
_GL_CXXALIASWARN1 (strpbrk, char const *,
- (char const *__s, char const *__accept));
-# else
+ (char const *__s, char const *__accept) throw ());
+# elif __GLIBC__ >= 2
_GL_CXXALIASWARN (strpbrk);
# endif
# if defined GNULIB_POSIXCHECK
@@ -521,15 +687,19 @@ _GL_CXXALIASWARN (strpbrk);
locale encoding is GB18030 and one of the characters to be searched is a
digit. */
# undef strpbrk
-_GL_WARN_ON_USE (strpbrk, "strpbrk cannot work correctly on character strings "
- "in multibyte locales - "
- "use mbspbrk if you care about internationalization");
+_GL_WARN_ON_USE_CXX (strpbrk,
+ const char *, char *, (const char *, const char *),
+ "strpbrk cannot work correctly on character strings "
+ "in multibyte locales - "
+ "use mbspbrk if you care about internationalization");
# endif
#elif defined GNULIB_POSIXCHECK
# undef strpbrk
# if HAVE_RAW_DECL_STRPBRK
-_GL_WARN_ON_USE (strpbrk, "strpbrk is unportable - "
- "use gnulib module strpbrk for portability");
+_GL_WARN_ON_USE_CXX (strpbrk,
+ const char *, char *, (const char *, const char *),
+ "strpbrk is unportable - "
+ "use gnulib module strpbrk for portability");
# endif
#endif
@@ -548,9 +718,11 @@ _GL_WARN_ON_USE (strspn, "strspn cannot work correctly on character strings "
GB18030 and the character to be searched is a digit. */
# undef strrchr
/* Assume strrchr is always declared. */
-_GL_WARN_ON_USE (strrchr, "strrchr cannot work correctly on character strings "
- "in some multibyte locales - "
- "use mbsrchr if you care about internationalization");
+_GL_WARN_ON_USE_CXX (strrchr,
+ const char *, char *, (const char *, int),
+ "strrchr cannot work correctly on character strings "
+ "in some multibyte locales - "
+ "use mbsrchr if you care about internationalization");
#endif
/* Search the next delimiter (char listed in DELIM) starting at *STRINGP.
@@ -610,11 +782,13 @@ _GL_CXXALIAS_SYS_CAST2 (strstr,
const char *, (const char *haystack, const char *needle));
# endif
# if ((__GLIBC__ == 2 && __GLIBC_MINOR__ >= 10) && !defined __UCLIBC__) \
- && (__GNUC__ > 4 || (__GNUC__ == 4 && __GNUC_MINOR__ >= 4))
-_GL_CXXALIASWARN1 (strstr, char *, (char *haystack, const char *needle));
+ && (__GNUC__ > 4 || (__GNUC__ == 4 && __GNUC_MINOR__ >= 4) \
+ || defined __clang__)
+_GL_CXXALIASWARN1 (strstr, char *,
+ (char *haystack, const char *needle) throw ());
_GL_CXXALIASWARN1 (strstr, const char *,
- (const char *haystack, const char *needle));
-# else
+ (const char *haystack, const char *needle) throw ());
+# elif __GLIBC__ >= 2
_GL_CXXALIASWARN (strstr);
# endif
#elif defined GNULIB_POSIXCHECK
@@ -659,10 +833,12 @@ _GL_CXXALIAS_SYS_CAST2 (strcasestr,
const char *, (const char *haystack, const char *needle));
# endif
# if ((__GLIBC__ == 2 && __GLIBC_MINOR__ >= 10) && !defined __UCLIBC__) \
- && (__GNUC__ > 4 || (__GNUC__ == 4 && __GNUC_MINOR__ >= 4))
-_GL_CXXALIASWARN1 (strcasestr, char *, (char *haystack, const char *needle));
+ && (__GNUC__ > 4 || (__GNUC__ == 4 && __GNUC_MINOR__ >= 4) \
+ || defined __clang__)
+_GL_CXXALIASWARN1 (strcasestr, char *,
+ (char *haystack, const char *needle) throw ());
_GL_CXXALIASWARN1 (strcasestr, const char *,
- (const char *haystack, const char *needle));
+ (const char *haystack, const char *needle) throw ());
# else
_GL_CXXALIASWARN (strcasestr);
# endif
@@ -693,7 +869,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.
@@ -964,7 +1140,8 @@ _GL_EXTERN_C char * mbssep (char **stringp, const char *delim)
Caveat: The identity of the delimiting character is lost.
See also mbssep(). */
-_GL_EXTERN_C char * mbstok_r (char *string, const char *delim, char **save_ptr)
+_GL_EXTERN_C char * mbstok_r (char *restrict string, const char *delim,
+ char **save_ptr)
_GL_ARG_NONNULL ((2, 3));
#endif
@@ -980,7 +1157,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. */
@@ -1017,6 +1196,60 @@ _GL_WARN_ON_USE (strerror_r, "strerror_r is unportable - "
# endif
#endif
+/* Return the name of the system error code ERRNUM. */
+#if @GNULIB_STRERRORNAME_NP@
+# if @REPLACE_STRERRORNAME_NP@
+# if !(defined __cplusplus && defined GNULIB_NAMESPACE)
+# undef strerrorname_np
+# define strerrorname_np rpl_strerrorname_np
+# endif
+_GL_FUNCDECL_RPL (strerrorname_np, const char *, (int errnum));
+_GL_CXXALIAS_RPL (strerrorname_np, const char *, (int errnum));
+# else
+# if !@HAVE_STRERRORNAME_NP@
+_GL_FUNCDECL_SYS (strerrorname_np, const char *, (int errnum));
+# endif
+_GL_CXXALIAS_SYS (strerrorname_np, const char *, (int errnum));
+# endif
+_GL_CXXALIASWARN (strerrorname_np);
+#elif defined GNULIB_POSIXCHECK
+# undef strerrorname_np
+# if HAVE_RAW_DECL_STRERRORNAME_NP
+_GL_WARN_ON_USE (strerrorname_np, "strerrorname_np is unportable - "
+ "use gnulib module strerrorname_np for portability");
+# endif
+#endif
+
+/* Return an abbreviation string for the signal number SIG. */
+#if @GNULIB_SIGABBREV_NP@
+# if ! @HAVE_SIGABBREV_NP@
+_GL_FUNCDECL_SYS (sigabbrev_np, const char *, (int sig));
+# endif
+_GL_CXXALIAS_SYS (sigabbrev_np, const char *, (int sig));
+_GL_CXXALIASWARN (sigabbrev_np);
+#elif defined GNULIB_POSIXCHECK
+# undef sigabbrev_np
+# if HAVE_RAW_DECL_SIGABBREV_NP
+_GL_WARN_ON_USE (sigabbrev_np, "sigabbrev_np is unportable - "
+ "use gnulib module sigabbrev_np for portability");
+# endif
+#endif
+
+/* Return an English description string for the signal number SIG. */
+#if @GNULIB_SIGDESCR_NP@
+# if ! @HAVE_SIGDESCR_NP@
+_GL_FUNCDECL_SYS (sigdescr_np, const char *, (int sig));
+# endif
+_GL_CXXALIAS_SYS (sigdescr_np, const char *, (int sig));
+_GL_CXXALIASWARN (sigdescr_np);
+#elif defined GNULIB_POSIXCHECK
+# undef sigdescr_np
+# if HAVE_RAW_DECL_SIGDESCR_NP
+_GL_WARN_ON_USE (sigdescr_np, "sigdescr_np is unportable - "
+ "use gnulib module sigdescr_np for portability");
+# endif
+#endif
+
#if @GNULIB_STRSIGNAL@
# if @REPLACE_STRSIGNAL@
# if !(defined __cplusplus && defined GNULIB_NAMESPACE)
diff --git a/lib/strnlen.c b/lib/strnlen.c
new file mode 100644
index 00000000000..c8fc69c6a9c
--- /dev/null
+++ b/lib/strnlen.c
@@ -0,0 +1,30 @@
+/* Find the length of STRING, but scan at most MAXLEN characters.
+ Copyright (C) 2005-2007, 2009-2022 Free Software Foundation, Inc.
+ Written by Simon Josefsson.
+
+ This file is free software: you can redistribute it and/or modify
+ it under the terms of the GNU Lesser General Public License as
+ published by the Free Software Foundation; either version 2.1 of the
+ License, or (at your option) any later version.
+
+ This file 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 Lesser General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public License
+ along with this program. If not, see <https://www.gnu.org/licenses/>. */
+
+#include <config.h>
+
+#include <string.h>
+
+/* Find the length of STRING, but scan at most MAXLEN characters.
+ If no '\0' terminator is found in that many characters, return MAXLEN. */
+
+size_t
+strnlen (const char *string, size_t maxlen)
+{
+ const char *end = memchr (string, '\0', maxlen);
+ return end ? (size_t) (end - string) : maxlen;
+}
diff --git a/lib/strtoimax.c b/lib/strtoimax.c
index f7d46f040d7..cad12d0d9be 100644
--- a/lib/strtoimax.c
+++ b/lib/strtoimax.c
@@ -1,19 +1,19 @@
/* Convert string representation of a number into an intmax_t value.
- Copyright (C) 1999, 2001-2004, 2006, 2009-2017 Free Software Foundation,
+ Copyright (C) 1999, 2001-2004, 2006, 2009-2022 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 file is free software: you can redistribute it and/or modify
+ it under the terms of the GNU Lesser 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,
+ This file 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.
+ GNU Lesser General Public License for more details.
- You should have received a copy of the GNU General Public License
+ You should have received a copy of the GNU Lesser General Public License
along with this program. If not, see <https://www.gnu.org/licenses/>. */
/* Written by Paul Eggert. */
@@ -28,36 +28,30 @@
#include "verify.h"
#ifdef UNSIGNED
-# if HAVE_UNSIGNED_LONG_LONG_INT
-# ifndef HAVE_DECL_STRTOULL
+# ifndef HAVE_DECL_STRTOULL
"this configure-time declaration test was not run"
-# endif
-# if !HAVE_DECL_STRTOULL
+# endif
+# if !HAVE_DECL_STRTOULL
unsigned long long int strtoull (char const *, char **, int);
-# endif
# endif
#else
-# if HAVE_LONG_LONG_INT
-# ifndef HAVE_DECL_STRTOLL
+# ifndef HAVE_DECL_STRTOLL
"this configure-time declaration test was not run"
-# endif
-# if !HAVE_DECL_STRTOLL
+# endif
+# if !HAVE_DECL_STRTOLL
long long int strtoll (char const *, char **, int);
-# endif
# endif
#endif
#ifdef UNSIGNED
-# define Have_long_long HAVE_UNSIGNED_LONG_LONG_INT
# define Int uintmax_t
# define Strtoimax strtoumax
# define Strtol strtoul
# define Strtoll strtoull
# define Unsigned unsigned
#else
-# define Have_long_long HAVE_LONG_LONG_INT
# define Int intmax_t
# define Strtoimax strtoimax
# define Strtol strtol
@@ -68,15 +62,11 @@ long long int strtoll (char const *, char **, int);
Int
Strtoimax (char const *ptr, char **endptr, int base)
{
-#if Have_long_long
verify (sizeof (Int) == sizeof (Unsigned long int)
|| sizeof (Int) == sizeof (Unsigned long long int));
if (sizeof (Int) != sizeof (Unsigned long int))
return Strtoll (ptr, endptr, base);
-#else
- verify (sizeof (Int) == sizeof (Unsigned long int));
-#endif
return Strtol (ptr, endptr, base);
}
diff --git a/lib/strtol.c b/lib/strtol.c
index 1ef88700fca..6c2e9333abc 100644
--- a/lib/strtol.c
+++ b/lib/strtol.c
@@ -1,22 +1,22 @@
/* Convert string representation of a number into an integer value.
- Copyright (C) 1991-1992, 1994-1999, 2003, 2005-2007, 2009-2017 Free Software
+ Copyright (C) 1991-1992, 1994-1999, 2003, 2005-2007, 2009-2022 Free Software
Foundation, Inc.
NOTE: The canonical source of this file is maintained with the GNU C
Library. Bugs can be reported to bug-glibc@gnu.org.
- 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 any
- later version.
+ This file is free software: you can redistribute it and/or modify
+ it under the terms of the GNU Lesser 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,
+ This file 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.
+ GNU Lesser General Public License for more details.
- You should have received a copy of the GNU General Public License
+ You should have received a copy of the GNU Lesser General Public License
along with this program. If not, see <https://www.gnu.org/licenses/>. */
#ifdef _LIBC
@@ -51,6 +51,7 @@
/* Determine the name. */
#ifdef USE_IN_EXTENDED_LOCALE_MODEL
+# undef strtol
# if UNSIGNED
# ifdef USE_WIDE_CHAR
# ifdef QUAD
@@ -82,6 +83,7 @@
# endif
#else
# if UNSIGNED
+# undef strtol
# ifdef USE_WIDE_CHAR
# ifdef QUAD
# define strtol wcstoull
@@ -97,6 +99,7 @@
# endif
# else
# ifdef USE_WIDE_CHAR
+# undef strtol
# ifdef QUAD
# define strtol wcstoll
# else
@@ -104,6 +107,7 @@
# endif
# else
# ifdef QUAD
+# undef strtol
# define strtol strtoll
# endif
# endif
@@ -117,35 +121,6 @@
# define STRTOL_LONG_MIN LLONG_MIN
# define STRTOL_LONG_MAX LLONG_MAX
# define STRTOL_ULONG_MAX ULLONG_MAX
-
-/* The extra casts in the following macros work around compiler bugs,
- e.g., in Cray C 5.0.3.0. */
-
-/* True if the arithmetic type T is signed. */
-# define TYPE_SIGNED(t) (! ((t) 0 < (t) -1))
-
-/* Minimum and maximum values for integer types.
- These macros have undefined behavior for signed types that either
- have padding bits or do not use two's complement. If this is a
- problem for you, please let us know how to fix it for your host. */
-
-/* The maximum and minimum values for the integer type T. */
-# define TYPE_MINIMUM(t) ((t) ~ TYPE_MAXIMUM (t))
-# define TYPE_MAXIMUM(t) \
- ((t) (! TYPE_SIGNED (t) \
- ? (t) -1 \
- : ((((t) 1 << (sizeof (t) * CHAR_BIT - 2)) - 1) * 2 + 1)))
-
-# ifndef ULLONG_MAX
-# define ULLONG_MAX TYPE_MAXIMUM (unsigned long long)
-# endif
-# ifndef LLONG_MAX
-# define LLONG_MAX TYPE_MAXIMUM (long long int)
-# endif
-# ifndef LLONG_MIN
-# define LLONG_MIN TYPE_MINIMUM (long long int)
-# endif
-
# if __GNUC__ == 2 && __GNUC_MINOR__ < 7
/* Work around gcc bug with using this constant. */
static const unsigned long long int maxquad = ULLONG_MAX;
@@ -160,6 +135,12 @@
#endif
+#ifdef USE_NUMBER_GROUPING
+# define GROUP_PARAM_PROTO , int group
+#else
+# define GROUP_PARAM_PROTO
+#endif
+
/* We use this code also for the extended locale handling where the
function gets as an additional argument the locale which has to be
used. To access the values we have to redefine the _NL_CURRENT
@@ -195,19 +176,23 @@
# define UCHAR_TYPE unsigned char
# define STRING_TYPE char
# ifdef USE_IN_EXTENDED_LOCALE_MODEL
-# define ISSPACE(Ch) __isspace_l ((Ch), loc)
-# define ISALPHA(Ch) __isalpha_l ((Ch), loc)
-# define TOUPPER(Ch) __toupper_l ((Ch), loc)
+# define ISSPACE(Ch) __isspace_l ((unsigned char) (Ch), loc)
+# define ISALPHA(Ch) __isalpha_l ((unsigned char) (Ch), loc)
+# define TOUPPER(Ch) __toupper_l ((unsigned char) (Ch), loc)
# else
-# define ISSPACE(Ch) isspace (Ch)
-# define ISALPHA(Ch) isalpha (Ch)
-# define TOUPPER(Ch) toupper (Ch)
+# define ISSPACE(Ch) isspace ((unsigned char) (Ch))
+# define ISALPHA(Ch) isalpha ((unsigned char) (Ch))
+# define TOUPPER(Ch) toupper ((unsigned char) (Ch))
# endif
#endif
-#define INTERNAL(X) INTERNAL1(X)
-#define INTERNAL1(X) __##X##_internal
-#define WEAKNAME(X) WEAKNAME1(X)
+#ifdef USE_NUMBER_GROUPING
+# define INTERNAL(X) INTERNAL1(X)
+# define INTERNAL1(X) __##X##_internal
+# define WEAKNAME(X) WEAKNAME1(X)
+#else
+# define INTERNAL(X) X
+#endif
#ifdef USE_NUMBER_GROUPING
/* This file defines a function to check for correct grouping. */
@@ -225,7 +210,7 @@
INT
INTERNAL (strtol) (const STRING_TYPE *nptr, STRING_TYPE **endptr,
- int base, int group LOCALE_PARAM_PROTO)
+ int base GROUP_PARAM_PROTO LOCALE_PARAM_PROTO)
{
int negative;
register unsigned LONG int cutoff;
@@ -408,15 +393,16 @@ noconv:
return 0L;
}
+#ifdef USE_NUMBER_GROUPING
/* External user entry point. */
-
INT
-#ifdef weak_function
+# ifdef weak_function
weak_function
-#endif
+# endif
strtol (const STRING_TYPE *nptr, STRING_TYPE **endptr,
int base LOCALE_PARAM_PROTO)
{
return INTERNAL (strtol) (nptr, endptr, base, 0 LOCALE_PARAM);
}
+#endif
diff --git a/lib/strtoll.c b/lib/strtoll.c
index f6952f3cd23..acea42ee003 100644
--- a/lib/strtoll.c
+++ b/lib/strtoll.c
@@ -1,19 +1,19 @@
/* Function to parse a 'long long int' from text.
- Copyright (C) 1995-1997, 1999, 2001, 2009-2017 Free Software Foundation,
+ Copyright (C) 1995-1997, 1999, 2001, 2009-2022 Free Software Foundation,
Inc.
This file is part of the GNU C Library.
- This program is free software: you can redistribute it and/or modify
- it under the terms of the GNU General Public License as published by
- the Free Software Foundation; either version 3 of the License, or
- (at your option) any later version.
+ This file is free software: you can redistribute it and/or modify
+ it under the terms of the GNU Lesser 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,
+ This file 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.
+ GNU Lesser General Public License for more details.
- You should have received a copy of the GNU General Public License
+ You should have received a copy of the GNU Lesser General Public License
along with this program. If not, see <https://www.gnu.org/licenses/>. */
#define QUAD 1
diff --git a/lib/symlink.c b/lib/symlink.c
index 427f1f5f00c..26310af7b12 100644
--- a/lib/symlink.c
+++ b/lib/symlink.c
@@ -1,17 +1,17 @@
/* Stub for symlink().
- Copyright (C) 2009-2017 Free Software Foundation, Inc.
+ Copyright (C) 2009-2022 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 file is free software: you can redistribute it and/or modify
+ it under the terms of the GNU Lesser 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,
+ This file 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.
+ GNU Lesser General Public License for more details.
- You should have received a copy of the GNU General Public License
+ You should have received a copy of the GNU Lesser General Public License
along with this program. If not, see <https://www.gnu.org/licenses/>. */
#include <config.h>
@@ -36,7 +36,7 @@ rpl_symlink (char const *contents, char const *name)
if (len && name[len - 1] == '/')
{
struct stat st;
- if (lstat (name, &st) == 0)
+ if (lstat (name, &st) == 0 || errno == EOVERFLOW)
errno = EEXIST;
return -1;
}
@@ -47,8 +47,8 @@ rpl_symlink (char const *contents, char const *name)
/* The system does not support symlinks. */
int
-symlink (char const *contents _GL_UNUSED,
- char const *name _GL_UNUSED)
+symlink (_GL_UNUSED char const *contents,
+ _GL_UNUSED char const *name)
{
errno = ENOSYS;
return -1;
diff --git a/lib/sys_random.in.h b/lib/sys_random.in.h
new file mode 100644
index 00000000000..e730e6139f8
--- /dev/null
+++ b/lib/sys_random.in.h
@@ -0,0 +1,98 @@
+/* Substitute for <sys/random.h>.
+ Copyright (C) 2020-2022 Free Software Foundation, Inc.
+
+ This file is free software: you can redistribute it and/or modify
+ it under the terms of the GNU Lesser General Public License as
+ published by the Free Software Foundation; either version 2.1 of the
+ License, or (at your option) any later version.
+
+ This file 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 Lesser General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public License
+ along with this program. If not, see <https://www.gnu.org/licenses/>. */
+
+# if __GNUC__ >= 3
+@PRAGMA_SYSTEM_HEADER@
+# endif
+@PRAGMA_COLUMNS@
+
+#ifndef _@GUARD_PREFIX@_SYS_RANDOM_H
+
+#if @HAVE_SYS_RANDOM_H@
+
+/* On uClibc < 1.0.35, <sys/random.h> assumes prior inclusion of <stddef.h>.
+ Do not use __UCLIBC__ here, as it might not be defined yet.
+ But avoid namespace pollution on glibc systems. */
+# ifndef __GLIBC__
+# include <stddef.h>
+# endif
+/* On Mac OS X 10.5, <sys/random.h> assumes prior inclusion of <sys/types.h>.
+ On Max OS X 10.13, <sys/random.h> assumes prior inclusion of a file that
+ includes <Availability.h>, such as <stdlib.h> or <unistd.h>. */
+# if defined __APPLE__ && defined __MACH__ /* Mac OS X */
+# include <sys/types.h>
+# include <stdlib.h>
+# endif
+
+/* The include_next requires a split double-inclusion guard. */
+# @INCLUDE_NEXT@ @NEXT_SYS_RANDOM_H@
+
+#endif
+
+#ifndef _@GUARD_PREFIX@_SYS_RANDOM_H
+#define _@GUARD_PREFIX@_SYS_RANDOM_H
+
+#include <sys/types.h>
+
+/* Define the GRND_* constants. */
+#ifndef GRND_NONBLOCK
+# define GRND_NONBLOCK 1
+# define GRND_RANDOM 2
+#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. */
+
+
+/* Declare overridden functions. */
+
+
+#if @GNULIB_GETRANDOM@
+/* Fill a buffer with random bytes. */
+# if @REPLACE_GETRANDOM@
+# if !(defined __cplusplus && defined GNULIB_NAMESPACE)
+# undef getrandom
+# define getrandom rpl_getrandom
+# endif
+_GL_FUNCDECL_RPL (getrandom, ssize_t,
+ (void *buffer, size_t length, unsigned int flags)
+ _GL_ARG_NONNULL ((1)));
+_GL_CXXALIAS_RPL (getrandom, ssize_t,
+ (void *buffer, size_t length, unsigned int flags));
+# else
+# if !@HAVE_GETRANDOM@
+_GL_FUNCDECL_SYS (getrandom, ssize_t,
+ (void *buffer, size_t length, unsigned int flags)
+ _GL_ARG_NONNULL ((1)));
+# endif
+_GL_CXXALIAS_SYS (getrandom, ssize_t,
+ (void *buffer, size_t length, unsigned int flags));
+# endif
+_GL_CXXALIASWARN (getrandom);
+#elif defined GNULIB_POSIXCHECK
+# undef getrandom
+# if HAVE_RAW_DECL_GETRANDOM
+_GL_WARN_ON_USE (getrandom, "getrandom is unportable - "
+ "use gnulib module getrandom for portability");
+# endif
+#endif
+
+
+#endif /* _@GUARD_PREFIX@_SYS_RANDOM_H */
+#endif /* _@GUARD_PREFIX@_SYS_RANDOM_H */
diff --git a/lib/sys_select.in.h b/lib/sys_select.in.h
index 3bda2122277..2bd0e0f79a8 100644
--- a/lib/sys_select.in.h
+++ b/lib/sys_select.in.h
@@ -1,18 +1,18 @@
/* Substitute for <sys/select.h>.
- Copyright (C) 2007-2017 Free Software Foundation, Inc.
+ Copyright (C) 2007-2022 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 file is free software: you can redistribute it and/or modify
+ it under the terms of the GNU Lesser General Public License as
+ published by the Free Software Foundation; either version 2.1 of the
+ License, or (at your option) any later version.
- This program is distributed in the hope that it will be useful,
+ This file 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.
+ GNU Lesser General Public License for more details.
- You should have received a copy of the GNU General Public License
- along with this program; if not, see <https://www.gnu.org/licenses/>. */
+ You should have received a copy of the GNU Lesser General Public License
+ along with this program. If not, see <https://www.gnu.org/licenses/>. */
# if __GNUC__ >= 3
@PRAGMA_SYSTEM_HEADER@
@@ -21,7 +21,7 @@
/* On OSF/1 and Solaris 2.6, <sys/types.h> and <sys/time.h>
both include <sys/select.h>.
- On Cygwin, <sys/time.h> includes <sys/select.h>.
+ On Cygwin and OpenBSD, <sys/time.h> includes <sys/select.h>.
Simply delegate to the system's header in this case. */
#if (@HAVE_SYS_SELECT_H@ \
&& !defined _GL_SYS_SELECT_H_REDIRECT_FROM_SYS_TYPES_H \
@@ -39,6 +39,7 @@
|| (!defined _GL_SYS_SELECT_H_REDIRECT_FROM_SYS_TIME_H \
&& ((defined __osf__ && defined _SYS_TIME_H_ \
&& defined _OSF_SOURCE) \
+ || (defined __OpenBSD__ && defined _SYS_TIME_H_) \
|| (defined __sun && defined _SYS_TIME_H \
&& (! (defined _XOPEN_SOURCE \
|| defined _POSIX_C_SOURCE) \
@@ -103,9 +104,16 @@
/* Get definition of 'sigset_t'.
But avoid namespace pollution on glibc systems and "unknown type
name" problems on Cygwin.
+ On OS/2 kLIBC, sigset_t is defined in <sys/select.h>, too. In addition,
+ if <sys/param.h> is included, <types.h> -> <sys/types.h> -> <sys/select.h>
+ are included. Then <signal.h> -> <pthread.h> are included by GNULIB. By the
+ way, <pthread.h> requires PAGE_SIZE defined in <sys/param.h>. However,
+ <sys/param.h> has not been processed, yet. As a result, 'PAGE_SIZE'
+ undeclared error occurs in <pthread.h>.
Do this after the include_next (for the sake of OpenBSD 5.0) but before
the split double-inclusion guard (for the sake of Solaris). */
-#if !((defined __GLIBC__ || defined __CYGWIN__) && !defined __UCLIBC__)
+#if !((defined __GLIBC__ || defined __CYGWIN__ || defined __KLIBC__) \
+ && !defined __UCLIBC__)
# include <signal.h>
#endif
@@ -177,14 +185,14 @@ rpl_fd_isset (SOCKET fd, fd_set * set)
# if !(defined __cplusplus && defined GNULIB_NAMESPACE)
# undef close
# define close close_used_without_including_unistd_h
-# else
+# elif !defined __clang__
_GL_WARN_ON_USE (close,
"close() used without including <unistd.h>");
# endif
# if !(defined __cplusplus && defined GNULIB_NAMESPACE)
# undef gethostname
# define gethostname gethostname_used_without_including_unistd_h
-# else
+# elif !defined __clang__
_GL_WARN_ON_USE (gethostname,
"gethostname() used without including <unistd.h>");
# endif
@@ -219,7 +227,7 @@ rpl_fd_isset (SOCKET fd, fd_set * set)
# define setsockopt setsockopt_used_without_including_sys_socket_h
# undef shutdown
# define shutdown shutdown_used_without_including_sys_socket_h
-# else
+# elif !defined __clang__
_GL_WARN_ON_USE (socket,
"socket() used without including <sys/socket.h>");
_GL_WARN_ON_USE (connect,
@@ -271,9 +279,13 @@ _GL_FUNCDECL_SYS (pselect, int,
(int, fd_set *restrict, fd_set *restrict, fd_set *restrict,
struct timespec const *restrict, const sigset_t *restrict));
# endif
-_GL_CXXALIAS_SYS (pselect, int,
- (int, fd_set *restrict, fd_set *restrict, fd_set *restrict,
- struct timespec const *restrict, const sigset_t *restrict));
+/* Need to cast, because on AIX 7, the second, third, fourth argument may be
+ void *restrict, void *restrict, void *restrict. */
+_GL_CXXALIAS_SYS_CAST (pselect, int,
+ (int,
+ fd_set *restrict, fd_set *restrict, fd_set *restrict,
+ struct timespec const *restrict,
+ const sigset_t *restrict));
# endif
_GL_CXXALIASWARN (pselect);
#elif defined GNULIB_POSIXCHECK
@@ -295,11 +307,11 @@ _GL_FUNCDECL_RPL (select, int,
struct timeval *restrict));
_GL_CXXALIAS_RPL (select, int,
(int, fd_set *restrict, fd_set *restrict, fd_set *restrict,
- struct timeval *restrict));
+ timeval *restrict));
# else
_GL_CXXALIAS_SYS (select, int,
(int, fd_set *restrict, fd_set *restrict, fd_set *restrict,
- struct timeval *restrict));
+ timeval *restrict));
# endif
_GL_CXXALIASWARN (select);
#elif @HAVE_WINSOCK2_H@
diff --git a/lib/sys_stat.in.h b/lib/sys_stat.in.h
index f0919e90d5c..714c3cb189e 100644
--- a/lib/sys_stat.in.h
+++ b/lib/sys_stat.in.h
@@ -1,18 +1,18 @@
/* Provide a more complete sys/stat.h header file.
- Copyright (C) 2005-2017 Free Software Foundation, Inc.
+ Copyright (C) 2005-2022 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 file is free software: you can redistribute it and/or modify
+ it under the terms of the GNU Lesser General Public License as
+ published by the Free Software Foundation; either version 2.1 of the
+ License, or (at your option) any later version.
- This program is distributed in the hope that it will be useful,
+ This file 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.
+ GNU Lesser General Public License for more details.
- You should have received a copy of the GNU General Public License
- along with this program; if not, see <https://www.gnu.org/licenses/>. */
+ You should have received a copy of the GNU Lesser General Public License
+ along with this program. If not, see <https://www.gnu.org/licenses/>. */
/* Written by Eric Blake, Paul Eggert, and Jim Meyering. */
@@ -54,16 +54,23 @@
/* 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>. */
-#if (defined _WIN32 || defined __WIN32__) && ! defined __CYGWIN__
+ 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 */
#endif
/* Native Windows platforms declare umask() in <io.h>. */
-#if 0 && ((defined _WIN32 || defined __WIN32__) && ! defined __CYGWIN__)
+#if 0 && (defined _WIN32 && ! defined __CYGWIN__)
# include <io.h>
#endif
@@ -368,11 +375,11 @@ struct stat
# define S_IRWXO (S_IROTH | S_IWOTH | S_IXOTH)
#endif
-/* S_IXUGO is a common extension to POSIX. */
+/* Although S_IXUGO and S_IRWXUGO are not specified by POSIX and are
+ not implemented in GNU/Linux, some Gnulib-using apps use the macros. */
#if !S_IXUGO
# define S_IXUGO (S_IXUSR | S_IXGRP | S_IXOTH)
#endif
-
#ifndef S_IRWXUGO
# define S_IRWXUGO (S_IRWXU | S_IRWXG | S_IRWXO)
#endif
@@ -384,14 +391,70 @@ struct stat
#endif
+#if @GNULIB_CHMOD@
+# if @REPLACE_CHMOD@
+# if !(defined __cplusplus && defined GNULIB_NAMESPACE)
+# undef chmod
+# define chmod rpl_chmod
+# endif
+_GL_FUNCDECL_RPL (chmod, int, (const char *filename, mode_t mode)
+ _GL_ARG_NONNULL ((1)));
+_GL_CXXALIAS_RPL (chmod, int, (const char *filename, mode_t mode));
+# elif defined _WIN32 && !defined __CYGWIN__
+# if !(defined __cplusplus && defined GNULIB_NAMESPACE)
+# undef chmod
+# define chmod _chmod
+# endif
+/* Need to cast, because in mingw the last argument is 'int mode'. */
+_GL_CXXALIAS_MDA_CAST (chmod, int, (const char *filename, mode_t mode));
+# else
+_GL_CXXALIAS_SYS (chmod, int, (const char *filename, mode_t mode));
+# endif
+_GL_CXXALIASWARN (chmod);
+#elif defined GNULIB_POSIXCHECK
+# undef chmod
+# if HAVE_RAW_DECL_CHMOD
+_GL_WARN_ON_USE (chmod, "chmod has portability problems - "
+ "use gnulib module chmod for portability");
+# endif
+#elif @GNULIB_MDA_CHMOD@
+/* On native Windows, map 'chmod' to '_chmod', so that -loldnames is not
+ required. In C++ with GNULIB_NAMESPACE, avoid differences between
+ platforms by defining GNULIB_NAMESPACE::chmod always. */
+# if defined _WIN32 && !defined __CYGWIN__
+# if !(defined __cplusplus && defined GNULIB_NAMESPACE)
+# undef chmod
+# define chmod _chmod
+# endif
+/* Need to cast, because in mingw the last argument is 'int mode'. */
+_GL_CXXALIAS_MDA_CAST (chmod, int, (const char *filename, mode_t mode));
+# else
+_GL_CXXALIAS_SYS (chmod, int, (const char *filename, mode_t mode));
+# endif
+_GL_CXXALIASWARN (chmod);
+#endif
+
+
#if @GNULIB_FCHMODAT@
-# if !@HAVE_FCHMODAT@
+# if @REPLACE_FCHMODAT@
+# if !(defined __cplusplus && defined GNULIB_NAMESPACE)
+# undef fchmodat
+# define fchmodat rpl_fchmodat
+# endif
+_GL_FUNCDECL_RPL (fchmodat, int,
+ (int fd, char const *file, mode_t mode, int flag)
+ _GL_ARG_NONNULL ((2)));
+_GL_CXXALIAS_RPL (fchmodat, int,
+ (int fd, char const *file, mode_t mode, int flag));
+# else
+# if !@HAVE_FCHMODAT@
_GL_FUNCDECL_SYS (fchmodat, int,
(int fd, char const *file, mode_t mode, int flag)
_GL_ARG_NONNULL ((2)));
-# endif
+# endif
_GL_CXXALIAS_SYS (fchmodat, int,
(int fd, char const *file, mode_t mode, int flag));
+# endif
_GL_CXXALIASWARN (fchmodat);
#elif defined GNULIB_POSIXCHECK
# undef fchmodat
@@ -413,7 +476,9 @@ _GL_CXXALIAS_RPL (fstat, int, (int fd, struct stat *buf));
# else
_GL_CXXALIAS_SYS (fstat, int, (int fd, struct stat *buf));
# endif
+# if __GLIBC__ >= 2
_GL_CXXALIASWARN (fstat);
+# endif
#elif @GNULIB_OVERRIDES_STRUCT_STAT@
# undef fstat
# define fstat fstat_used_without_requesting_gnulib_module_fstat
@@ -436,18 +501,22 @@ _GL_WARN_ON_USE (fstat, "fstat has portability problems - "
# define fstatat rpl_fstatat
# endif
_GL_FUNCDECL_RPL (fstatat, int,
- (int fd, char const *name, struct stat *st, int flags)
+ (int fd, char const *restrict name, struct stat *restrict st,
+ int flags)
_GL_ARG_NONNULL ((2, 3)));
_GL_CXXALIAS_RPL (fstatat, int,
- (int fd, char const *name, struct stat *st, int flags));
+ (int fd, char const *restrict name, struct stat *restrict st,
+ int flags));
# else
# if !@HAVE_FSTATAT@
_GL_FUNCDECL_SYS (fstatat, int,
- (int fd, char const *name, struct stat *st, int flags)
+ (int fd, char const *restrict name, struct stat *restrict st,
+ int flags)
_GL_ARG_NONNULL ((2, 3)));
# endif
_GL_CXXALIAS_SYS (fstatat, int,
- (int fd, char const *name, struct stat *st, int flags));
+ (int fd, char const *restrict name, struct stat *restrict st,
+ int flags));
# endif
_GL_CXXALIASWARN (fstatat);
#elif @GNULIB_OVERRIDES_STRUCT_STAT@
@@ -492,34 +561,32 @@ _GL_WARN_ON_USE (futimens, "futimens is not portable - "
#endif
+#if @GNULIB_GETUMASK@
+# if !@HAVE_GETUMASK@
+_GL_FUNCDECL_SYS (getumask, mode_t, (void));
+# endif
+_GL_CXXALIAS_SYS (getumask, mode_t, (void));
+# if @HAVE_GETUMASK@
+_GL_CXXALIASWARN (getumask);
+# endif
+#elif defined GNULIB_POSIXCHECK
+# undef getumask
+# if HAVE_RAW_DECL_GETUMASK
+_GL_WARN_ON_USE (getumask, "getumask is not portable - "
+ "use gnulib module getumask for portability");
+# endif
+#endif
+
+
#if @GNULIB_LCHMOD@
/* Change the mode of FILENAME to MODE, without dereferencing it if FILENAME
denotes a symbolic link. */
-# if !@HAVE_LCHMOD@
-/* The lchmod replacement follows symbolic links. Callers should take
- this into account; lchmod should be applied only to arguments that
- are known to not be symbolic links. On hosts that lack lchmod,
- this can lead to race conditions between the check and the
- invocation of lchmod, but we know of no workarounds that are
- reliable in general. You might try requesting support for lchmod
- from your operating system supplier. */
-# if !(defined __cplusplus && defined GNULIB_NAMESPACE)
-# define lchmod chmod
-# endif
-/* Need to cast, because on mingw, the second parameter of chmod is
- int mode. */
-_GL_CXXALIAS_RPL_CAST_1 (lchmod, chmod, int,
- (const char *filename, mode_t mode));
-# else
-# if 0 /* assume already declared */
+# if !@HAVE_LCHMOD@ || defined __hpux
_GL_FUNCDECL_SYS (lchmod, int, (const char *filename, mode_t mode)
_GL_ARG_NONNULL ((1)));
-# endif
-_GL_CXXALIAS_SYS (lchmod, int, (const char *filename, mode_t mode));
# endif
-# if @HAVE_LCHMOD@
+_GL_CXXALIAS_SYS (lchmod, int, (const char *filename, mode_t mode));
_GL_CXXALIASWARN (lchmod);
-# endif
#elif defined GNULIB_POSIXCHECK
# undef lchmod
# if HAVE_RAW_DECL_LCHMOD
@@ -536,17 +603,21 @@ _GL_WARN_ON_USE (lchmod, "lchmod is unportable - "
# if !(defined __cplusplus && defined GNULIB_NAMESPACE)
# define lstat stat
# endif
-_GL_CXXALIAS_RPL_1 (lstat, stat, int, (const char *name, struct stat *buf));
+_GL_CXXALIAS_RPL_1 (lstat, stat, int,
+ (const char *restrict name, struct stat *restrict buf));
# elif @REPLACE_LSTAT@
# if !(defined __cplusplus && defined GNULIB_NAMESPACE)
# undef lstat
# define lstat rpl_lstat
# endif
-_GL_FUNCDECL_RPL (lstat, int, (const char *name, struct stat *buf)
- _GL_ARG_NONNULL ((1, 2)));
-_GL_CXXALIAS_RPL (lstat, int, (const char *name, struct stat *buf));
+_GL_FUNCDECL_RPL (lstat, int,
+ (const char *restrict name, struct stat *restrict buf)
+ _GL_ARG_NONNULL ((1, 2)));
+_GL_CXXALIAS_RPL (lstat, int,
+ (const char *restrict name, struct stat *restrict buf));
# else
-_GL_CXXALIAS_SYS (lstat, int, (const char *name, struct stat *buf));
+_GL_CXXALIAS_SYS (lstat, int,
+ (const char *restrict name, struct stat *restrict buf));
# endif
# if @HAVE_LSTAT@
_GL_CXXALIASWARN (lstat);
@@ -563,21 +634,20 @@ _GL_WARN_ON_USE (lstat, "lstat is unportable - "
#endif
-#if @REPLACE_MKDIR@
-# if !(defined __cplusplus && defined GNULIB_NAMESPACE)
-# undef mkdir
-# define mkdir rpl_mkdir
-# endif
+#if @GNULIB_MKDIR@
+# if @REPLACE_MKDIR@
+# if !(defined __cplusplus && defined GNULIB_NAMESPACE)
+# undef mkdir
+# define mkdir rpl_mkdir
+# endif
_GL_FUNCDECL_RPL (mkdir, int, (char const *name, mode_t mode)
- _GL_ARG_NONNULL ((1)));
+ _GL_ARG_NONNULL ((1)));
_GL_CXXALIAS_RPL (mkdir, int, (char const *name, mode_t mode));
-#else
+# elif defined _WIN32 && !defined __CYGWIN__
/* mingw's _mkdir() function has 1 argument, but we pass 2 arguments.
Additionally, it declares _mkdir (and depending on compile flags, an
alias mkdir), only in the nonstandard includes <direct.h> and <io.h>,
which are included above. */
-# if (defined _WIN32 || defined __WIN32__) && ! defined __CYGWIN__
-
# if !GNULIB_defined_rpl_mkdir
static int
rpl_mkdir (char const *name, mode_t mode)
@@ -586,16 +656,44 @@ rpl_mkdir (char const *name, mode_t mode)
}
# define GNULIB_defined_rpl_mkdir 1
# endif
-
# if !(defined __cplusplus && defined GNULIB_NAMESPACE)
+# undef mkdir
# define mkdir rpl_mkdir
# endif
_GL_CXXALIAS_RPL (mkdir, int, (char const *name, mode_t mode));
# else
_GL_CXXALIAS_SYS (mkdir, int, (char const *name, mode_t mode));
# endif
-#endif
_GL_CXXALIASWARN (mkdir);
+#elif defined GNULIB_POSIXCHECK
+# undef mkdir
+# if HAVE_RAW_DECL_MKDIR
+_GL_WARN_ON_USE (mkdir, "mkdir does not always support two parameters - "
+ "use gnulib module mkdir for portability");
+# endif
+#elif @GNULIB_MDA_MKDIR@
+/* On native Windows, map 'mkdir' to '_mkdir', so that -loldnames is not
+ required. In C++ with GNULIB_NAMESPACE, avoid differences between
+ platforms by defining GNULIB_NAMESPACE::mkdir always. */
+# if defined _WIN32 && !defined __CYGWIN__
+# if !GNULIB_defined_rpl_mkdir
+static int
+rpl_mkdir (char const *name, mode_t mode)
+{
+ return _mkdir (name);
+}
+# define GNULIB_defined_rpl_mkdir 1
+# endif
+# if !(defined __cplusplus && defined GNULIB_NAMESPACE)
+# undef mkdir
+# define mkdir rpl_mkdir
+# endif
+_GL_CXXALIAS_RPL (mkdir, int, (char const *name, mode_t mode));
+# else
+_GL_CXXALIAS_SYS (mkdir, int, (char const *name, mode_t mode));
+# endif
+_GL_CXXALIASWARN (mkdir);
+#endif
#if @GNULIB_MKDIRAT@
@@ -641,11 +739,21 @@ _GL_WARN_ON_USE (mkfifo, "mkfifo is not portable - "
#if @GNULIB_MKFIFOAT@
-# if !@HAVE_MKFIFOAT@
+# if @REPLACE_MKFIFOAT@
+# if !(defined __cplusplus && defined GNULIB_NAMESPACE)
+# undef mkfifoat
+# define mkfifoat rpl_mkfifoat
+# endif
+_GL_FUNCDECL_RPL (mkfifoat, int, (int fd, char const *file, mode_t mode)
+ _GL_ARG_NONNULL ((2)));
+_GL_CXXALIAS_RPL (mkfifoat, int, (int fd, char const *file, mode_t mode));
+# else
+# if !@HAVE_MKFIFOAT@
_GL_FUNCDECL_SYS (mkfifoat, int, (int fd, char const *file, mode_t mode)
_GL_ARG_NONNULL ((2)));
-# endif
+# endif
_GL_CXXALIAS_SYS (mkfifoat, int, (int fd, char const *file, mode_t mode));
+# endif
_GL_CXXALIASWARN (mkfifoat);
#elif defined GNULIB_POSIXCHECK
# undef mkfifoat
@@ -684,13 +792,25 @@ _GL_WARN_ON_USE (mknod, "mknod is not portable - "
#if @GNULIB_MKNODAT@
-# if !@HAVE_MKNODAT@
+# if @REPLACE_MKNODAT@
+# if !(defined __cplusplus && defined GNULIB_NAMESPACE)
+# undef mknodat
+# define mknodat rpl_mknodat
+# endif
+_GL_FUNCDECL_RPL (mknodat, int,
+ (int fd, char const *file, mode_t mode, dev_t dev)
+ _GL_ARG_NONNULL ((2)));
+_GL_CXXALIAS_RPL (mknodat, int,
+ (int fd, char const *file, mode_t mode, dev_t dev));
+# else
+# if !@HAVE_MKNODAT@
_GL_FUNCDECL_SYS (mknodat, int,
(int fd, char const *file, mode_t mode, dev_t dev)
_GL_ARG_NONNULL ((2)));
-# endif
+# endif
_GL_CXXALIAS_SYS (mknodat, int,
(int fd, char const *file, mode_t mode, dev_t dev));
+# endif
_GL_CXXALIASWARN (mknodat);
#elif defined GNULIB_POSIXCHECK
# undef mknodat
@@ -759,7 +879,7 @@ _GL_WARN_ON_USE (mknodat, "mknodat is not portable - "
# define stat(name, st) rpl_stat (name, st)
# endif /* !_LARGE_FILES */
# endif /* !@GNULIB_OVERRIDES_STRUCT_STAT@ */
-_GL_EXTERN_C int stat (const char *name, struct stat *buf)
+_GL_EXTERN_C int stat (const char *restrict name, struct stat *restrict buf)
_GL_ARG_NONNULL ((1, 2));
# endif
#elif @GNULIB_OVERRIDES_STRUCT_STAT@
@@ -775,6 +895,24 @@ _GL_WARN_ON_USE (stat, "stat is unportable - "
#endif
+#if @GNULIB_MDA_UMASK@
+/* On native Windows, map 'umask' to '_umask', so that -loldnames is not
+ required. In C++ with GNULIB_NAMESPACE, avoid differences between
+ platforms by defining GNULIB_NAMESPACE::umask always. */
+# if defined _WIN32 && !defined __CYGWIN__
+# if !(defined __cplusplus && defined GNULIB_NAMESPACE)
+# undef umask
+# define umask _umask
+# endif
+/* Need to cast, because in mingw the last argument is 'int mode'. */
+_GL_CXXALIAS_MDA_CAST (umask, mode_t, (mode_t mask));
+# else
+_GL_CXXALIAS_SYS (umask, mode_t, (mode_t mask));
+# endif
+_GL_CXXALIASWARN (umask);
+#endif
+
+
#if @GNULIB_UTIMENSAT@
/* Use the rpl_ prefix also on Solaris <= 9, because on Solaris 9 our utimensat
implementation relies on futimesat, which on Solaris 10 makes an invocation
diff --git a/lib/sys_time.in.h b/lib/sys_time.in.h
index 8a3c87d11d8..87db1a88745 100644
--- a/lib/sys_time.in.h
+++ b/lib/sys_time.in.h
@@ -1,19 +1,19 @@
/* Provide a more complete sys/time.h.
- Copyright (C) 2007-2017 Free Software Foundation, Inc.
+ Copyright (C) 2007-2022 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 file is free software: you can redistribute it and/or modify
+ it under the terms of the GNU Lesser General Public License as
+ published by the Free Software Foundation; either version 2.1 of the
+ License, or (at your option) any later version.
- This program is distributed in the hope that it will be useful,
+ This file 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.
+ GNU Lesser General Public License for more details.
- You should have received a copy of the GNU General Public License
- along with this program; if not, see <https://www.gnu.org/licenses/>. */
+ You should have received a copy of the GNU Lesser General Public License
+ along with this program. If not, see <https://www.gnu.org/licenses/>. */
/* Written by Paul Eggert. */
@@ -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
@@ -131,7 +135,7 @@ _GL_WARN_ON_USE (gettimeofday, "gettimeofday is unportable - "
# if !(defined __cplusplus && defined GNULIB_NAMESPACE)
# undef close
# define close close_used_without_including_unistd_h
-# else
+# elif !defined __clang__
_GL_WARN_ON_USE (close,
"close() used without including <unistd.h>");
# endif
diff --git a/lib/sys_types.in.h b/lib/sys_types.in.h
index b0d6132a163..698e88d6326 100644
--- a/lib/sys_types.in.h
+++ b/lib/sys_types.in.h
@@ -1,25 +1,36 @@
/* Provide a more complete sys/types.h.
- Copyright (C) 2011-2017 Free Software Foundation, Inc.
+ Copyright (C) 2011-2022 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 file is free software: you can redistribute it and/or modify
+ it under the terms of the GNU Lesser General Public License as
+ published by the Free Software Foundation; either version 2.1 of the
+ License, or (at your option) any later version.
- This program is distributed in the hope that it will be useful,
+ This file 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.
+ GNU Lesser General Public License for more details.
- You should have received a copy of the GNU General Public License
- along with this program; if not, see <https://www.gnu.org/licenses/>. */
+ You should have received a copy of the GNU Lesser General Public License
+ along with this program. If not, see <https://www.gnu.org/licenses/>. */
#if __GNUC__ >= 3
@PRAGMA_SYSTEM_HEADER@
#endif
@PRAGMA_COLUMNS@
+#if defined _WIN32 && !defined __CYGWIN__ \
+ && (defined __need_off_t || defined __need___off64_t \
+ || defined __need_ssize_t || defined __need_time_t)
+
+/* Special invocation convention inside mingw header files. */
+
+#@INCLUDE_NEXT@ @NEXT_SYS_TYPES_H@
+
+#else
+/* Normal invocation convention. */
+
#ifndef _@GUARD_PREFIX@_SYS_TYPES_H
/* The include_next requires a split double-inclusion guard. */
@@ -86,10 +97,10 @@ typedef unsigned long long int rpl_ino_t;
/* MSVC 9 defines size_t in <stddef.h>, not in <sys/types.h>. */
/* But avoid namespace pollution on glibc systems. */
-#if ((defined _WIN32 || defined __WIN32__) && ! defined __CYGWIN__) \
- && ! defined __GLIBC__
+#if (defined _WIN32 && ! defined __CYGWIN__) && ! defined __GLIBC__
# include <stddef.h>
#endif
#endif /* _@GUARD_PREFIX@_SYS_TYPES_H */
#endif /* _@GUARD_PREFIX@_SYS_TYPES_H */
+#endif /* __need_XXX */
diff --git a/lib/tempname.c b/lib/tempname.c
index 2e3f95f3fb1..11b4796b34b 100644
--- a/lib/tempname.c
+++ b/lib/tempname.c
@@ -1,39 +1,29 @@
-/* tempname.c - generate the name of a temporary file.
+/* Copyright (C) 1991-2022 Free Software Foundation, Inc.
+ This file is part of the GNU C Library.
- Copyright (C) 1991-2003, 2005-2007, 2009-2017 Free Software Foundation, Inc.
+ The GNU C Library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Lesser General Public
+ License as published by the Free Software Foundation; either
+ version 2.1 of the License, or (at your option) any later version.
- 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,
+ 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 this program. If not, see <https://www.gnu.org/licenses/>. */
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Lesser General Public License for more details.
-/* Extracted from glibc sysdeps/posix/tempname.c. See also tmpdir.c. */
+ You should have received a copy of the GNU Lesser General Public
+ License along with the GNU C Library; if not, see
+ <https://www.gnu.org/licenses/>. */
#if !_LIBC
-# include <config.h>
+# include <libc-config.h>
# include "tempname.h"
#endif
-#include <sys/types.h>
-#include <assert.h>
-
+#include <stdbool.h>
#include <errno.h>
-#ifndef __set_errno
-# define __set_errno(Val) errno = (Val)
-#endif
#include <stdio.h>
-#ifndef P_tmpdir
-# define P_tmpdir "/tmp"
-#endif
#ifndef TMP_MAX
# define TMP_MAX 238328
#endif
@@ -47,143 +37,161 @@
# error report this to bug-gnulib@gnu.org
#endif
-#include <stddef.h>
#include <stdlib.h>
#include <string.h>
#include <fcntl.h>
-#include <sys/time.h>
#include <stdint.h>
-#include <unistd.h>
-
+#include <sys/random.h>
#include <sys/stat.h>
+#include <time.h>
#if _LIBC
-# define struct_stat64 struct stat64
+# define struct_stat64 struct __stat64_t64
#else
# define struct_stat64 struct stat
-# define __try_tempname try_tempname
# define __gen_tempname gen_tempname
-# define __getpid getpid
-# define __gettimeofday gettimeofday
# define __mkdir mkdir
# define __open open
-# define __lxstat64(version, file, buf) lstat (file, buf)
+# define __lstat64_time64(file, buf) lstat (file, buf)
+# define __getrandom getrandom
+# define __clock_gettime64 clock_gettime
+# define __timespec64 timespec
#endif
-#ifdef _LIBC
-# include <hp-timing.h>
-# if HP_TIMING_AVAIL
-# define RANDOM_BITS(Var) \
- if (__builtin_expect (value == UINT64_C (0), 0)) \
- { \
- /* If this is the first time this function is used initialize \
- the variable we accumulate the value in to some somewhat \
- random value. If we'd not do this programs at startup time \
- might have a reduced set of possible names, at least on slow \
- machines. */ \
- struct timeval tv; \
- __gettimeofday (&tv, NULL); \
- value = ((uint64_t) tv.tv_usec << 16) ^ tv.tv_sec; \
- } \
- HP_TIMING_NOW (Var)
-# endif
-#endif
+/* Use getrandom if it works, falling back on a 64-bit linear
+ congruential generator that starts with Var's value
+ mixed in with a clock's low-order bits if available. */
+typedef uint_fast64_t random_value;
+#define RANDOM_VALUE_MAX UINT_FAST64_MAX
+#define BASE_62_DIGITS 10 /* 62**10 < UINT_FAST64_MAX */
+#define BASE_62_POWER (62LL * 62 * 62 * 62 * 62 * 62 * 62 * 62 * 62 * 62)
-/* Use the widest available unsigned type if uint64_t is not
- available. The algorithm below extracts a number less than 62**6
- (approximately 2**35.725) from uint64_t, so ancient hosts where
- uintmax_t is only 32 bits lose about 3.725 bits of randomness,
- which is better than not having mkstemp at all. */
-#if !defined UINT64_MAX && !defined uint64_t
-# define uint64_t uintmax_t
-#endif
+/* Return the result of mixing the entropy from R and S.
+ Assume that R and S are not particularly random,
+ and that the result should look randomish to an untrained eye. */
-#if _LIBC
-/* Return nonzero if DIR is an existent directory. */
-static int
-direxists (const char *dir)
+static random_value
+mix_random_values (random_value r, random_value s)
{
- struct_stat64 buf;
- return __xstat64 (_STAT_VER, dir, &buf) == 0 && S_ISDIR (buf.st_mode);
+ /* As this code is used only when high-quality randomness is neither
+ available nor necessary, there is no need for fancier polynomials
+ such as those in the Linux kernel's 'random' driver. */
+ return (2862933555777941757 * r + 3037000493) ^ s;
}
-/* Path search algorithm, for tmpnam, tmpfile, etc. If DIR is
- non-null and exists, uses it; otherwise uses the first of $TMPDIR,
- P_tmpdir, /tmp that exists. Copies into TMPL a template suitable
- for use with mk[s]temp. Will fail (-1) if DIR is non-null and
- doesn't exist, none of the searched dirs exists, or there's not
- enough space in TMPL. */
-int
-__path_search (char *tmpl, size_t tmpl_len, const char *dir, const char *pfx,
- int try_tmpdir)
+/* Set *R to a random value.
+ Return true if *R is set to high-quality value taken from getrandom.
+ Otherwise return false, falling back to a low-quality *R that might
+ depend on S.
+
+ This function returns false only when getrandom fails.
+ On GNU systems this should happen only early in the boot process,
+ when the fallback should be good enough for programs using tempname
+ because any attacker likely has root privileges already. */
+
+static bool
+random_bits (random_value *r, random_value s)
{
- const char *d;
- size_t dlen, plen;
+ /* Without GRND_NONBLOCK it can be blocked for minutes on some systems. */
+ if (__getrandom (r, sizeof *r, GRND_NONBLOCK) == sizeof *r)
+ return true;
- if (!pfx || !pfx[0])
- {
- pfx = "file";
- plen = 4;
- }
- else
- {
- plen = strlen (pfx);
- if (plen > 5)
- plen = 5;
- }
+ /* If getrandom did not work, use ersatz entropy based on low-order
+ clock bits. On GNU systems getrandom should fail only
+ early in booting, when ersatz should be good enough.
+ Do not use ASLR-based entropy, as that would leak ASLR info into
+ the resulting file name which is typically public.
- if (try_tmpdir)
- {
- d = __secure_getenv ("TMPDIR");
- if (d != NULL && direxists (d))
- dir = d;
- else if (dir != NULL && direxists (dir))
- /* nothing */ ;
- else
- dir = NULL;
- }
- if (dir == NULL)
- {
- if (direxists (P_tmpdir))
- dir = P_tmpdir;
- else if (strcmp (P_tmpdir, "/tmp") != 0 && direxists ("/tmp"))
- dir = "/tmp";
- else
- {
- __set_errno (ENOENT);
- return -1;
- }
- }
+ Of course we are in a state of sin here. */
- dlen = strlen (dir);
- while (dlen > 1 && dir[dlen - 1] == '/')
- dlen--; /* remove trailing slashes */
+ random_value v = s;
- /* check we have room for "${dir}/${pfx}XXXXXX\0" */
- if (tmpl_len < dlen + 1 + plen + 6 + 1)
- {
- __set_errno (EINVAL);
- return -1;
- }
+#if _LIBC || (defined CLOCK_REALTIME && HAVE_CLOCK_GETTIME)
+ struct __timespec64 tv;
+ __clock_gettime64 (CLOCK_REALTIME, &tv);
+ v = mix_random_values (v, tv.tv_sec);
+ v = mix_random_values (v, tv.tv_nsec);
+#endif
- sprintf (tmpl, "%.*s/%.*sXXXXXX", (int) dlen, dir, (int) plen, pfx);
- return 0;
+ *r = mix_random_values (v, clock ());
+ return false;
+}
+
+#if _LIBC
+static int try_tempname_len (char *, int, void *, int (*) (char *, void *),
+ size_t);
+#endif
+
+static int
+try_file (char *tmpl, void *flags)
+{
+ int *openflags = flags;
+ return __open (tmpl,
+ (*openflags & ~O_ACCMODE)
+ | O_RDWR | O_CREAT | O_EXCL, S_IRUSR | S_IWUSR);
+}
+
+static int
+try_dir (char *tmpl, _GL_UNUSED void *flags)
+{
+ return __mkdir (tmpl, S_IRUSR | S_IWUSR | S_IXUSR);
+}
+
+static int
+try_nocreate (char *tmpl, _GL_UNUSED void *flags)
+{
+ struct_stat64 st;
+
+ if (__lstat64_time64 (tmpl, &st) == 0 || errno == EOVERFLOW)
+ __set_errno (EEXIST);
+ return errno == ENOENT ? 0 : -1;
}
-#endif /* _LIBC */
/* These are the characters used in temporary file names. */
static const char letters[] =
"abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789";
+/* Generate a temporary file name based on TMPL. TMPL must match the
+ rules for mk[s]temp (i.e., end in at least X_SUFFIX_LEN "X"s,
+ possibly with a suffix).
+ The name constructed does not exist at the time of the call to
+ this function. TMPL is overwritten with the result.
+
+ KIND may be one of:
+ __GT_NOCREATE: simply verify that the name does not exist
+ at the time of the call.
+ __GT_FILE: create the file using open(O_CREAT|O_EXCL)
+ and return a read-write fd. The file is mode 0600.
+ __GT_DIR: create a directory, which will be mode 0700.
+
+ */
+#ifdef _LIBC
+static
+#endif
int
-__try_tempname (char *tmpl, int suffixlen, void *args,
- int (*tryfunc) (char *, void *))
+gen_tempname_len (char *tmpl, int suffixlen, int flags, int kind,
+ size_t x_suffix_len)
{
- int len;
+ static int (*const tryfunc[]) (char *, void *) =
+ {
+ [__GT_FILE] = try_file,
+ [__GT_DIR] = try_dir,
+ [__GT_NOCREATE] = try_nocreate
+ };
+ return try_tempname_len (tmpl, suffixlen, &flags, tryfunc[kind],
+ x_suffix_len);
+}
+
+#ifdef _LIBC
+static
+#endif
+int
+try_tempname_len (char *tmpl, int suffixlen, void *args,
+ int (*tryfunc) (char *, void *), size_t x_suffix_len)
+{
+ size_t len;
char *XXXXXX;
- static uint64_t value;
- uint64_t random_time_bits;
unsigned int count;
int fd = -1;
int save_errno = errno;
@@ -193,7 +201,8 @@ __try_tempname (char *tmpl, int suffixlen, void *args,
can exist for a given template is 62**6. It should never be
necessary to try all of these combinations. Instead if a reasonable
number of names is tried (we define reasonable as 62**3) fail to
- give the system administrator the chance to remove the problems. */
+ give the system administrator the chance to remove the problems.
+ This value requires that X_SUFFIX_LEN be at least 3. */
#define ATTEMPTS_MIN (62 * 62 * 62)
/* The number of times to attempt to generate a temporary file. To
@@ -204,44 +213,48 @@ __try_tempname (char *tmpl, int suffixlen, void *args,
unsigned int attempts = ATTEMPTS_MIN;
#endif
+ /* A random variable. */
+ random_value v = 0;
+
+ /* A value derived from the random variable, and how many random
+ base-62 digits can currently be extracted from VDIGBUF. */
+ random_value vdigbuf;
+ int vdigits = 0;
+
+ /* Least biased value for V. If V is less than this, V can generate
+ BASE_62_DIGITS unbiased digits. Otherwise the digits are biased. */
+ random_value const biased_min
+ = RANDOM_VALUE_MAX - RANDOM_VALUE_MAX % BASE_62_POWER;
+
len = strlen (tmpl);
- if (len < 6 + suffixlen || memcmp (&tmpl[len - 6 - suffixlen], "XXXXXX", 6))
+ if (len < x_suffix_len + suffixlen
+ || strspn (&tmpl[len - x_suffix_len - suffixlen], "X") < x_suffix_len)
{
__set_errno (EINVAL);
return -1;
}
/* This is where the Xs start. */
- XXXXXX = &tmpl[len - 6 - suffixlen];
+ XXXXXX = &tmpl[len - x_suffix_len - suffixlen];
- /* Get some more or less random data. */
-#ifdef RANDOM_BITS
- RANDOM_BITS (random_time_bits);
-#else
- {
- struct timeval tv;
- __gettimeofday (&tv, NULL);
- random_time_bits = ((uint64_t) tv.tv_usec << 16) ^ tv.tv_sec;
- }
-#endif
- value += random_time_bits ^ __getpid ();
-
- for (count = 0; count < attempts; value += 7777, ++count)
+ for (count = 0; count < attempts; ++count)
{
- uint64_t v = value;
-
- /* Fill in the random bits. */
- XXXXXX[0] = letters[v % 62];
- v /= 62;
- XXXXXX[1] = letters[v % 62];
- v /= 62;
- XXXXXX[2] = letters[v % 62];
- v /= 62;
- XXXXXX[3] = letters[v % 62];
- v /= 62;
- XXXXXX[4] = letters[v % 62];
- v /= 62;
- XXXXXX[5] = letters[v % 62];
+ for (size_t i = 0; i < x_suffix_len; i++)
+ {
+ if (vdigits == 0)
+ {
+ /* Worry about bias only if the bits are high quality. */
+ while (random_bits (&v, v) && biased_min <= v)
+ continue;
+
+ vdigbuf = v;
+ vdigits = BASE_62_DIGITS;
+ }
+
+ XXXXXX[i] = letters[vdigbuf % 62];
+ vdigbuf /= 62;
+ vdigits--;
+ }
fd = tryfunc (tmpl, args);
if (fd >= 0)
@@ -258,66 +271,17 @@ __try_tempname (char *tmpl, int suffixlen, void *args,
return -1;
}
-static int
-try_file (char *tmpl, void *flags)
-{
- int *openflags = flags;
- return __open (tmpl,
- (*openflags & ~O_ACCMODE)
- | O_RDWR | O_CREAT | O_EXCL, S_IRUSR | S_IWUSR);
-}
-
-static int
-try_dir (char *tmpl, void *flags _GL_UNUSED)
-{
- return __mkdir (tmpl, S_IRUSR | S_IWUSR | S_IXUSR);
-}
-
-static int
-try_nocreate (char *tmpl, void *flags _GL_UNUSED)
+int
+__gen_tempname (char *tmpl, int suffixlen, int flags, int kind)
{
- struct_stat64 st;
-
- if (__lxstat64 (_STAT_VER, tmpl, &st) == 0 || errno == EOVERFLOW)
- __set_errno (EEXIST);
- return errno == ENOENT ? 0 : -1;
+ return gen_tempname_len (tmpl, suffixlen, flags, kind, 6);
}
-/* Generate a temporary file name based on TMPL. TMPL must match the
- rules for mk[s]temp (i.e. end in "XXXXXX", possibly with a suffix).
- The name constructed does not exist at the time of the call to
- __gen_tempname. TMPL is overwritten with the result.
-
- KIND may be one of:
- __GT_NOCREATE: simply verify that the name does not exist
- at the time of the call.
- __GT_FILE: create the file using open(O_CREAT|O_EXCL)
- and return a read-write fd. The file is mode 0600.
- __GT_DIR: create a directory, which will be mode 0700.
-
- We use a clever algorithm to get hard-to-predict names. */
+#if !_LIBC
int
-__gen_tempname (char *tmpl, int suffixlen, int flags, int kind)
+try_tempname (char *tmpl, int suffixlen, void *args,
+ int (*tryfunc) (char *, void *))
{
- int (*tryfunc) (char *, void *);
-
- switch (kind)
- {
- case __GT_FILE:
- tryfunc = try_file;
- break;
-
- case __GT_DIR:
- tryfunc = try_dir;
- break;
-
- case __GT_NOCREATE:
- tryfunc = try_nocreate;
- break;
-
- default:
- assert (! "invalid KIND in __gen_tempname");
- abort ();
- }
- return __try_tempname (tmpl, suffixlen, &flags, tryfunc);
+ return try_tempname_len (tmpl, suffixlen, args, tryfunc, 6);
}
+#endif
diff --git a/lib/tempname.h b/lib/tempname.h
index 245c8161abe..5e3c5e15500 100644
--- a/lib/tempname.h
+++ b/lib/tempname.h
@@ -1,18 +1,18 @@
/* Create a temporary file or directory.
- Copyright (C) 2006, 2009-2017 Free Software Foundation, Inc.
+ Copyright (C) 2006, 2009-2022 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 file is free software: you can redistribute it and/or modify
+ it under the terms of the GNU Lesser General Public License as
+ published by the Free Software Foundation; either version 2.1 of the
+ License, or (at your option) any later version.
- This program is distributed in the hope that it will be useful,
+ This file 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.
+ GNU Lesser General Public License for more details.
- You should have received a copy of the GNU General Public License
+ You should have received a copy of the GNU Lesser General Public License
along with this program. If not, see <https://www.gnu.org/licenses/>. */
/* header written by Eric Blake */
@@ -48,8 +48,11 @@ extern "C" {
and return a read-write fd. The file is mode 0600.
GT_DIR: create a directory, which will be mode 0700.
- We use a clever algorithm to get hard-to-predict names. */
+ */
extern int gen_tempname (char *tmpl, int suffixlen, int flags, int kind);
+/* Similar, except X_SUFFIX_LEN gives the number of Xs. */
+extern int gen_tempname_len (char *tmpl, int suffixlen, int flags, int kind,
+ size_t x_suffix_len);
/* Similar to gen_tempname, but TRYFUNC is called for each temporary
name to try. If TRYFUNC returns a non-negative number, TRY_GEN_TEMPNAME
@@ -57,6 +60,10 @@ extern int gen_tempname (char *tmpl, int suffixlen, int flags, int kind);
name is tried, or else TRY_GEN_TEMPNAME returns -1. */
extern int try_tempname (char *tmpl, int suffixlen, void *args,
int (*tryfunc) (char *, void *));
+/* Similar, except X_SUFFIX_LEN gives the number of Xs. */
+extern int try_tempname_len (char *tmpl, int suffixlen, void *args,
+ int (*tryfunc) (char *, void *),
+ size_t x_suffix_len);
#ifdef __cplusplus
}
diff --git a/lib/time-internal.h b/lib/time-internal.h
index 8caf11d8746..c8a2a8ce6bc 100644
--- a/lib/time-internal.h
+++ b/lib/time-internal.h
@@ -1,19 +1,19 @@
/* Time internal interface
- Copyright 2015-2017 Free Software Foundation, Inc.
+ Copyright 2015-2022 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 file is free software: you can redistribute it and/or modify
+ it under the terms of the GNU Lesser 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,
+ This file 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.
+ GNU Lesser General Public License for more details.
- You should have received a copy of the GNU General Public License along
- with this program; if not, see <https://www.gnu.org/licenses/>. */
+ You should have received a copy of the GNU Lesser General Public License
+ along with this program. If not, see <https://www.gnu.org/licenses/>. */
/* Written by Paul Eggert. */
@@ -24,7 +24,7 @@ struct tm_zone
members are zero. */
struct tm_zone *next;
-#if HAVE_TZNAME && !HAVE_TM_ZONE
+#if HAVE_TZNAME && !HAVE_STRUCT_TM_TM_ZONE
/* Copies of recent strings taken from tzname[0] and tzname[1].
The copies are in ABBRS, so that they survive tzset. Null if unknown. */
char *tzname_copy[2];
diff --git a/lib/time.in.h b/lib/time.in.h
index d210fbf80b1..6d4c7719636 100644
--- a/lib/time.in.h
+++ b/lib/time.in.h
@@ -1,19 +1,19 @@
/* A more-standard <time.h>.
- Copyright (C) 2007-2017 Free Software Foundation, Inc.
+ Copyright (C) 2007-2022 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 file is free software: you can redistribute it and/or modify
+ it under the terms of the GNU Lesser General Public License as
+ published by the Free Software Foundation; either version 2.1 of the
+ License, or (at your option) any later version.
- This program is distributed in the hope that it will be useful,
+ This file 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.
+ GNU Lesser General Public License for more details.
- You should have received a copy of the GNU General Public License
- along with this program; if not, see <https://www.gnu.org/licenses/>. */
+ You should have received a copy of the GNU Lesser General Public License
+ along with this program. If not, see <https://www.gnu.org/licenses/>. */
#if __GNUC__ >= 3
@PRAGMA_SYSTEM_HEADER@
@@ -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. */
@@ -48,7 +54,7 @@
/* The definition of _GL_WARN_ON_USE is copied here. */
-/* Some systems don't define struct timespec (e.g., AIX 4.1, Ultrix 4.3).
+/* Some systems don't define struct timespec (e.g., AIX 4.1).
Or they define it with the wrong member names or define it in <sys/time.h>
(e.g., FreeBSD circa 1997). Stock Mingw prior to 3.0 does not define it,
but the pthreads-win32 library defines it in <pthread.h>. */
@@ -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. */
@@ -95,9 +101,39 @@ struct __time_t_must_be_integral {
# define GNULIB_defined_struct_time_t_must_be_integral 1
# endif
+/* Define TIME_UTC, a positive integer constant used for timespec_get(). */
+# if ! @TIME_H_DEFINES_TIME_UTC@
+# if !GNULIB_defined_TIME_UTC
+# define TIME_UTC 1
+# define GNULIB_defined_TIME_UTC 1
+# endif
+# endif
+
+/* Set *TS to the current time, and return BASE.
+ Upon failure, return 0. */
+# if @GNULIB_TIMESPEC_GET@
+# if ! @HAVE_TIMESPEC_GET@
+_GL_FUNCDECL_SYS (timespec_get, int, (struct timespec *ts, int base)
+ _GL_ARG_NONNULL ((1)));
+# endif
+_GL_CXXALIAS_SYS (timespec_get, int, (struct timespec *ts, int base));
+_GL_CXXALIASWARN (timespec_get);
+# endif
+
+/* Set *TS to the current time resolution, and return BASE.
+ Upon failure, return 0. */
+# if @GNULIB_TIMESPEC_GETRES@
+# if ! @HAVE_TIMESPEC_GETRES@
+_GL_FUNCDECL_SYS (timespec_getres, int, (struct timespec *ts, int base)
+ _GL_ARG_NONNULL ((1)));
+# endif
+_GL_CXXALIAS_SYS (timespec_getres, int, (struct timespec *ts, int base));
+_GL_CXXALIASWARN (timespec_getres);
+# endif
+
/* 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)
@@ -129,10 +165,27 @@ _GL_CXXALIASWARN (nanosleep);
# endif
_GL_FUNCDECL_RPL (tzset, void, (void));
_GL_CXXALIAS_RPL (tzset, void, (void));
+# elif defined _WIN32 && !defined __CYGWIN__
+# if !(defined __cplusplus && defined GNULIB_NAMESPACE)
+# undef tzset
+# define tzset _tzset
+# endif
+_GL_CXXALIAS_MDA (tzset, void, (void));
# else
-# if ! @HAVE_TZSET@
-_GL_FUNCDECL_SYS (tzset, void, (void));
+_GL_CXXALIAS_SYS (tzset, void, (void));
+# endif
+_GL_CXXALIASWARN (tzset);
+# elif @GNULIB_MDA_TZSET@
+/* On native Windows, map 'tzset' to '_tzset', so that -loldnames is not
+ required. In C++ with GNULIB_NAMESPACE, avoid differences between
+ platforms by defining GNULIB_NAMESPACE::tzset always. */
+# if defined _WIN32 && !defined __CYGWIN__
+# if !(defined __cplusplus && defined GNULIB_NAMESPACE)
+# undef tzset
+# define tzset _tzset
# endif
+_GL_CXXALIAS_MDA (tzset, void, (void));
+# else
_GL_CXXALIAS_SYS (tzset, void, (void));
# endif
_GL_CXXALIASWARN (tzset);
@@ -149,12 +202,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 +258,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)
@@ -212,12 +267,14 @@ _GL_CXXALIASWARN (gmtime_r);
# define localtime rpl_localtime
# endif
_GL_FUNCDECL_RPL (localtime, struct tm *, (time_t const *__timer)
- _GL_ARG_NONNULL ((1)));
+ _GL_ARG_NONNULL ((1)));
_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 +294,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 +309,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,45 +321,90 @@ _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)
# define strftime rpl_strftime
# endif
-_GL_FUNCDECL_RPL (strftime, size_t, (char *__buf, size_t __bufsize,
- const char *__fmt, const struct tm *__tp)
- _GL_ARG_NONNULL ((1, 3, 4)));
-_GL_CXXALIAS_RPL (strftime, size_t, (char *__buf, size_t __bufsize,
- const char *__fmt, const struct tm *__tp));
+_GL_FUNCDECL_RPL (strftime, size_t,
+ (char *restrict __buf, size_t __bufsize,
+ const char *restrict __fmt, const struct tm *restrict __tp)
+ _GL_ARG_NONNULL ((1, 3, 4)));
+_GL_CXXALIAS_RPL (strftime, size_t,
+ (char *restrict __buf, size_t __bufsize,
+ const char *restrict __fmt, const struct tm *restrict __tp));
# else
-_GL_CXXALIAS_SYS (strftime, size_t, (char *__buf, size_t __bufsize,
- const char *__fmt, const struct tm *__tp));
+_GL_CXXALIAS_SYS (strftime, size_t,
+ (char *restrict __buf, size_t __bufsize,
+ const char *restrict __fmt, const struct tm *restrict __tp));
# endif
+# if __GLIBC__ >= 2
_GL_CXXALIASWARN (strftime);
+# endif
# endif
# if defined _GNU_SOURCE && @GNULIB_TIME_RZ@ && ! @HAVE_TIMEZONE_T@
+/* Functions that use a first-class time zone data type, instead of
+ relying on an implicit global time zone.
+ Inspired by NetBSD. */
+
+/* Represents a time zone.
+ (timezone_t) NULL stands for UTC. */
typedef struct tm_zone *timezone_t;
+
+/* tzalloc (name)
+ Returns a time zone object for the given time zone NAME. This object
+ represents the time zone that other functions would use it the TZ
+ environment variable was set to NAME.
+ If NAME is NULL, the result represents the time zone that other functions
+ would use it the TZ environment variable was unset.
+ May return NULL if NAME is invalid (this is platform dependent) or
+ upon memory allocation failure. */
_GL_FUNCDECL_SYS (tzalloc, timezone_t, (char const *__name));
_GL_CXXALIAS_SYS (tzalloc, timezone_t, (char const *__name));
+
+/* tzfree (tz)
+ Frees a time zone object.
+ The argument must have been returned by tzalloc(). */
_GL_FUNCDECL_SYS (tzfree, void, (timezone_t __tz));
_GL_CXXALIAS_SYS (tzfree, void, (timezone_t __tz));
+
+/* localtime_rz (tz, &t, &result)
+ Converts an absolute time T to a broken-down time RESULT, assuming the
+ time zone TZ.
+ This function is like 'localtime_r', but relies on the argument TZ instead
+ of an implicit global time zone. */
_GL_FUNCDECL_SYS (localtime_rz, struct tm *,
(timezone_t __tz, time_t const *restrict __timer,
struct tm *restrict __result) _GL_ARG_NONNULL ((2, 3)));
_GL_CXXALIAS_SYS (localtime_rz, struct tm *,
(timezone_t __tz, time_t const *restrict __timer,
struct tm *restrict __result));
+
+/* mktime_z (tz, &tm)
+ Normalizes the broken-down time TM and converts it to an absolute time,
+ assuming the time zone TZ. Returns the absolute time.
+ This function is like 'mktime', but relies on the argument TZ instead
+ of an implicit global time zone. */
_GL_FUNCDECL_SYS (mktime_z, time_t,
- (timezone_t __tz, struct tm *restrict __result)
+ (timezone_t __tz, struct tm *restrict __tm)
_GL_ARG_NONNULL ((2)));
_GL_CXXALIAS_SYS (mktime_z, time_t,
- (timezone_t __tz, struct tm *restrict __result));
+ (timezone_t __tz, struct tm *restrict __tm));
+
+/* Time zone abbreviation strings (returned by 'localtime_rz' or 'mktime_z'
+ in the 'tm_zone' member of 'struct tm') are valid as long as
+ - the 'struct tm' argument is not destroyed or overwritten,
+ and
+ - the 'timezone_t' argument is not freed through tzfree(). */
+
# endif
/* Convert TM to a time_t value, assuming UTC. */
@@ -333,17 +435,17 @@ _GL_WARN_ON_USE (asctime, "asctime can overrun buffers in some cases - "
# endif
# if defined GNULIB_POSIXCHECK
# undef asctime_r
-_GL_WARN_ON_USE (asctime, "asctime_r can overrun buffers in some cases - "
+_GL_WARN_ON_USE (asctime_r, "asctime_r can overrun buffers in some cases - "
"better use strftime (or even sprintf) instead");
# endif
# if defined GNULIB_POSIXCHECK
# undef ctime
-_GL_WARN_ON_USE (asctime, "ctime can overrun buffers in some cases - "
+_GL_WARN_ON_USE (ctime, "ctime can overrun buffers in some cases - "
"better use strftime (or even sprintf) instead");
# endif
# if defined GNULIB_POSIXCHECK
# undef ctime_r
-_GL_WARN_ON_USE (asctime, "ctime_r can overrun buffers in some cases - "
+_GL_WARN_ON_USE (ctime_r, "ctime_r can overrun buffers in some cases - "
"better use strftime (or even sprintf) instead");
# endif
diff --git a/lib/time_r.c b/lib/time_r.c
index 8cf8329fe5d..d4b22755451 100644
--- a/lib/time_r.c
+++ b/lib/time_r.c
@@ -1,19 +1,19 @@
/* Reentrant time functions like localtime_r.
- Copyright (C) 2003, 2006-2007, 2010-2017 Free Software Foundation, Inc.
+ Copyright (C) 2003, 2006-2007, 2010-2022 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 file is free software: you can redistribute it and/or modify
+ it under the terms of the GNU Lesser General Public License as
+ published by the Free Software Foundation; either version 2.1 of the
+ License, or (at your option) any later version.
- This program is distributed in the hope that it will be useful,
+ This file 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.
+ GNU Lesser General Public License for more details.
- You should have received a copy of the GNU General Public License along
- with this program; if not, see <https://www.gnu.org/licenses/>. */
+ You should have received a copy of the GNU Lesser General Public License
+ along with this program. If not, see <https://www.gnu.org/licenses/>. */
/* Written by Paul Eggert. */
diff --git a/lib/time_rz.c b/lib/time_rz.c
index ad02edb23cb..1a91d3778e7 100644
--- a/lib/time_rz.c
+++ b/lib/time_rz.c
@@ -1,19 +1,19 @@
/* Time zone functions such as tzalloc and localtime_rz
- Copyright 2015-2017 Free Software Foundation, Inc.
+ Copyright 2015-2022 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 file is free software: you can redistribute it and/or modify
+ it under the terms of the GNU Lesser 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,
+ This file 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.
+ GNU Lesser General Public License for more details.
- You should have received a copy of the GNU General Public License along
- with this program; if not, see <https://www.gnu.org/licenses/>. */
+ You should have received a copy of the GNU Lesser General Public License
+ along with this program. If not, see <https://www.gnu.org/licenses/>. */
/* Written by Paul Eggert. */
@@ -27,19 +27,15 @@
#include <time.h>
#include <errno.h>
-#include <limits.h>
#include <stdbool.h>
#include <stddef.h>
#include <stdlib.h>
#include <string.h>
#include "flexmember.h"
+#include "idx.h"
#include "time-internal.h"
-#ifndef SIZE_MAX
-# define SIZE_MAX ((size_t) -1)
-#endif
-
/* The approximate size to use for small allocation requests. This is
the largest "small" request for the GNU C library malloc. */
enum { DEFAULT_MXFAST = 64 * sizeof (size_t) / 4 };
@@ -54,31 +50,6 @@ enum { ABBR_SIZE_MIN = DEFAULT_MXFAST - offsetof (struct tm_zone, abbrs) };
matters; the pointer is never dereferenced. */
static timezone_t const local_tz = (timezone_t) 1;
-#if HAVE_TM_ZONE || HAVE_TZNAME
-
-/* Return true if the values A and B differ according to the rules for
- tm_isdst: A and B differ if one is zero and the other positive. */
-static bool
-isdst_differ (int a, int b)
-{
- return !a != !b && 0 <= a && 0 <= b;
-}
-
-/* Return true if A and B are equal. */
-static int
-equal_tm (const struct tm *a, const struct tm *b)
-{
- return ! ((a->tm_sec ^ b->tm_sec)
- | (a->tm_min ^ b->tm_min)
- | (a->tm_hour ^ b->tm_hour)
- | (a->tm_mday ^ b->tm_mday)
- | (a->tm_mon ^ b->tm_mon)
- | (a->tm_year ^ b->tm_year)
- | isdst_differ (a->tm_isdst, b->tm_isdst));
-}
-
-#endif
-
/* Copy to ABBRS the abbreviation at ABBR with size ABBR_SIZE (this
includes its trailing null byte). Append an extra null byte to
mark the end of ABBRS. */
@@ -100,7 +71,7 @@ tzalloc (char const *name)
if (tz)
{
tz->next = NULL;
-#if HAVE_TZNAME && !HAVE_TM_ZONE
+#if HAVE_TZNAME && !HAVE_STRUCT_TM_TM_ZONE
tz->tzname_copy[0] = tz->tzname_copy[1] = NULL;
#endif
tz->tz_is_set = !!name;
@@ -112,13 +83,13 @@ tzalloc (char const *name)
}
/* Save into TZ any nontrivial time zone abbreviation used by TM, and
- update *TM (if HAVE_TM_ZONE) or *TZ (if !HAVE_TM_ZONE &&
- HAVE_TZNAME) if they use the abbreviation. Return true if
- successful, false (setting errno) otherwise. */
+ update *TM (if HAVE_STRUCT_TM_TM_ZONE) or *TZ (if
+ !HAVE_STRUCT_TM_TM_ZONE && HAVE_TZNAME) if they use the abbreviation.
+ Return true if successful, false (setting errno) otherwise. */
static bool
save_abbr (timezone_t tz, struct tm *tm)
{
-#if HAVE_TM_ZONE || HAVE_TZNAME
+#if HAVE_STRUCT_TM_TM_ZONE || HAVE_TZNAME
char const *zone = NULL;
char *zone_copy = (char *) "";
@@ -126,7 +97,7 @@ save_abbr (timezone_t tz, struct tm *tm)
int tzname_index = -1;
# endif
-# if HAVE_TM_ZONE
+# if HAVE_STRUCT_TM_TM_ZONE
zone = tm->tm_zone;
# endif
@@ -150,14 +121,8 @@ save_abbr (timezone_t tz, struct tm *tm)
{
if (! (*zone_copy || (zone_copy == tz->abbrs && tz->tz_is_set)))
{
- size_t zone_size = strlen (zone) + 1;
- size_t zone_used = zone_copy - tz->abbrs;
- if (SIZE_MAX - zone_used < zone_size)
- {
- errno = ENOMEM;
- return false;
- }
- if (zone_used + zone_size < ABBR_SIZE_MIN)
+ idx_t zone_size = strlen (zone) + 1;
+ if (zone_size < tz->abbrs + ABBR_SIZE_MIN - zone_copy)
extend_abbrs (zone_copy, zone, zone_size);
else
{
@@ -180,7 +145,7 @@ save_abbr (timezone_t tz, struct tm *tm)
}
/* Replace the zone name so that its lifetime matches that of TZ. */
-# if HAVE_TM_ZONE
+# if HAVE_STRUCT_TM_TM_ZONE
tm->tm_zone = zone_copy;
# else
if (0 <= tzname_index)
@@ -286,6 +251,21 @@ revert_tz (timezone_t tz)
struct tm *
localtime_rz (timezone_t tz, time_t const *t, struct tm *tm)
{
+#ifdef HAVE_LOCALTIME_INFLOOP_BUG
+ /* The -67768038400665599 comes from:
+ https://lists.gnu.org/r/bug-gnulib/2017-07/msg00142.html
+ On affected platforms the greatest POSIX-compatible time_t value
+ that could return nonnull is 67768036191766798 (when
+ TZ="XXX24:59:59" it resolves to the year 2**31 - 1 + 1900, on
+ 12-31 at 23:59:59), so test for that too while we're in the
+ neighborhood. */
+ if (! (-67768038400665599 <= *t && *t <= 67768036191766798))
+ {
+ errno = EOVERFLOW;
+ return NULL;
+ }
+#endif
+
if (!tz)
return gmtime_r (t, tm);
else
@@ -312,17 +292,25 @@ mktime_z (timezone_t tz, struct tm *tm)
timezone_t old_tz = set_tz (tz);
if (old_tz)
{
- time_t t = mktime (tm);
-#if HAVE_TM_ZONE || HAVE_TZNAME
- time_t badtime = -1;
struct tm tm_1;
- if ((t != badtime
- || (localtime_r (&t, &tm_1) && equal_tm (tm, &tm_1)))
- && !save_abbr (tz, tm))
- t = badtime;
+ tm_1.tm_sec = tm->tm_sec;
+ tm_1.tm_min = tm->tm_min;
+ tm_1.tm_hour = tm->tm_hour;
+ tm_1.tm_mday = tm->tm_mday;
+ tm_1.tm_mon = tm->tm_mon;
+ tm_1.tm_year = tm->tm_year;
+ tm_1.tm_yday = -1;
+ tm_1.tm_isdst = tm->tm_isdst;
+ time_t t = mktime (&tm_1);
+ bool ok = 0 <= tm_1.tm_yday;
+#if HAVE_STRUCT_TM_TM_ZONE || HAVE_TZNAME
+ ok = ok && save_abbr (tz, &tm_1);
#endif
- if (revert_tz (old_tz))
- return t;
+ if (revert_tz (old_tz) && ok)
+ {
+ *tm = tm_1;
+ return t;
+ }
}
return -1;
}
diff --git a/lib/timegm.c b/lib/timegm.c
index 1cabf648264..a1b19efc392 100644
--- a/lib/timegm.c
+++ b/lib/timegm.c
@@ -1,40 +1,58 @@
/* Convert UTC calendar time to simple time. Like mktime but assumes UTC.
- Copyright (C) 1994, 1997, 2003-2004, 2006-2007, 2009-2017 Free Software
- Foundation, Inc. This file is part of the GNU C Library.
+ Copyright (C) 1994-2022 Free Software Foundation, Inc.
+ This file is part of the GNU C Library.
- This program is free software; you can redistribute it and/or modify
- it under the terms of the GNU General Public License as published by
- the Free Software Foundation; either version 3, or (at your option)
- any later version.
+ The GNU C Library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Lesser General Public
+ License as published by the Free Software Foundation; either
+ version 2.1 of the License, or (at your option) any later version.
- This program is distributed in the hope that it will be useful,
+ The GNU C Library is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- GNU General Public License for more details.
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Lesser General Public License for more details.
- You should have received a copy of the GNU General Public License
- along with this program; if not, see <https://www.gnu.org/licenses/>. */
+ You should have received a copy of the GNU Lesser General Public
+ License along with the GNU C Library; if not, see
+ <https://www.gnu.org/licenses/>. */
#ifndef _LIBC
-# include <config.h>
+# include <libc-config.h>
#endif
#include <time.h>
+#include <errno.h>
-#ifdef _LIBC
-typedef time_t mktime_offset_t;
-#else
-# undef __gmtime_r
-# define __gmtime_r gmtime_r
-# define __mktime_internal mktime_internal
-# include "mktime-internal.h"
-#endif
+#include "mktime-internal.h"
-time_t
-timegm (struct tm *tmp)
+__time64_t
+__timegm64 (struct tm *tmp)
{
static mktime_offset_t gmtime_offset;
tmp->tm_isdst = 0;
- return __mktime_internal (tmp, __gmtime_r, &gmtime_offset);
+ return __mktime_internal (tmp, __gmtime64_r, &gmtime_offset);
+}
+
+#if defined _LIBC && __TIMESIZE != 64
+
+libc_hidden_def (__timegm64)
+
+time_t
+timegm (struct tm *tmp)
+{
+ struct tm tm = *tmp;
+ __time64_t t = __timegm64 (&tm);
+ if (in_time_t_range (t))
+ {
+ *tmp = tm;
+ return t;
+ }
+ else
+ {
+ __set_errno (EOVERFLOW);
+ return -1;
+ }
}
+
+#endif
diff --git a/lib/timespec-add.c b/lib/timespec-add.c
index faa45829445..0f270e5bc8c 100644
--- a/lib/timespec-add.c
+++ b/lib/timespec-add.c
@@ -1,10 +1,10 @@
/* Add two struct timespec values.
- Copyright (C) 2011-2017 Free Software Foundation, Inc.
+ Copyright (C) 2011-2022 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
+ 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,
@@ -18,7 +18,7 @@
/* Written by Paul Eggert. */
/* Return the sum of two timespec values A and B. On overflow, return
- an extremal value. This assumes 0 <= tv_nsec < TIMESPEC_RESOLUTION. */
+ an extremal value. This assumes 0 <= tv_nsec < TIMESPEC_HZ. */
#include <config.h>
#include "timespec.h"
@@ -31,39 +31,33 @@ timespec_add (struct timespec a, struct timespec b)
time_t rs = a.tv_sec;
time_t bs = b.tv_sec;
int ns = a.tv_nsec + b.tv_nsec;
- int nsd = ns - TIMESPEC_RESOLUTION;
+ int nsd = ns - TIMESPEC_HZ;
int rns = ns;
- time_t tmin = TYPE_MINIMUM (time_t);
- time_t tmax = TYPE_MAXIMUM (time_t);
if (0 <= nsd)
{
rns = nsd;
- if (bs < tmax)
- bs++;
+ time_t bs1;
+ if (!INT_ADD_WRAPV (bs, 1, &bs1))
+ bs = bs1;
else if (rs < 0)
rs++;
else
goto high_overflow;
}
- /* INT_ADD_WRAPV is not appropriate since time_t might be unsigned.
- In theory time_t might be narrower than int, so plain
- INT_ADD_OVERFLOW does not suffice. */
- if (! INT_ADD_OVERFLOW (rs, bs) && tmin <= rs + bs && rs + bs <= tmax)
- rs += bs;
- else
+ if (INT_ADD_WRAPV (rs, bs, &rs))
{
- if (rs < 0)
+ if (bs < 0)
{
- rs = tmin;
+ rs = TYPE_MINIMUM (time_t);
rns = 0;
}
else
{
high_overflow:
- rs = tmax;
- rns = TIMESPEC_RESOLUTION - 1;
+ rs = TYPE_MAXIMUM (time_t);
+ rns = TIMESPEC_HZ - 1;
}
}
diff --git a/lib/timespec-sub.c b/lib/timespec-sub.c
index 3872f1bc2db..36747833e39 100644
--- a/lib/timespec-sub.c
+++ b/lib/timespec-sub.c
@@ -1,10 +1,10 @@
/* Subtract two struct timespec values.
- Copyright (C) 2011-2017 Free Software Foundation, Inc.
+ Copyright (C) 2011-2022 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
+ 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,
@@ -19,7 +19,7 @@
/* Return the difference between two timespec values A and B. On
overflow, return an extremal value. This assumes 0 <= tv_nsec <
- TIMESPEC_RESOLUTION. */
+ TIMESPEC_HZ. */
#include <config.h>
#include "timespec.h"
@@ -33,37 +33,31 @@ timespec_sub (struct timespec a, struct timespec b)
time_t bs = b.tv_sec;
int ns = a.tv_nsec - b.tv_nsec;
int rns = ns;
- time_t tmin = TYPE_MINIMUM (time_t);
- time_t tmax = TYPE_MAXIMUM (time_t);
if (ns < 0)
{
- rns = ns + TIMESPEC_RESOLUTION;
- if (bs < tmax)
- bs++;
+ rns = ns + TIMESPEC_HZ;
+ time_t bs1;
+ if (!INT_ADD_WRAPV (bs, 1, &bs1))
+ bs = bs1;
else if (- TYPE_SIGNED (time_t) < rs)
rs--;
else
goto low_overflow;
}
- /* INT_SUBTRACT_WRAPV is not appropriate since time_t might be unsigned.
- In theory time_t might be narrower than int, so plain
- INT_SUBTRACT_OVERFLOW does not suffice. */
- if (! INT_SUBTRACT_OVERFLOW (rs, bs) && tmin <= rs - bs && rs - bs <= tmax)
- rs -= bs;
- else
+ if (INT_SUBTRACT_WRAPV (rs, bs, &rs))
{
- if (rs < 0)
+ if (0 < bs)
{
low_overflow:
- rs = tmin;
+ rs = TYPE_MINIMUM (time_t);
rns = 0;
}
else
{
- rs = tmax;
- rns = TIMESPEC_RESOLUTION - 1;
+ rs = TYPE_MAXIMUM (time_t);
+ rns = TIMESPEC_HZ - 1;
}
}
diff --git a/lib/timespec.c b/lib/timespec.c
index 2b6098ed7bd..9d136cb803b 100644
--- a/lib/timespec.c
+++ b/lib/timespec.c
@@ -1,3 +1,21 @@
+/* Inline functions for <timespec.h>.
+
+ Copyright (C) 2012-2022 Free Software Foundation, Inc.
+
+ This file is free software: you can redistribute it and/or modify
+ it under the terms of the GNU Lesser General Public License as
+ published by the Free Software Foundation, either version 3 of the
+ License, or (at your option) any later version.
+
+ This file 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 Lesser General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public License
+ along with this program. If not, see <https://www.gnu.org/licenses/>. */
+
#include <config.h>
+
#define _GL_TIMESPEC_INLINE _GL_EXTERN_INLINE
#include "timespec.h"
diff --git a/lib/timespec.h b/lib/timespec.h
index 3831301578e..9e358289a2a 100644
--- a/lib/timespec.h
+++ b/lib/timespec.h
@@ -1,25 +1,25 @@
/* timespec -- System time interface
- Copyright (C) 2000, 2002, 2004-2005, 2007, 2009-2017 Free Software
+ Copyright (C) 2000, 2002, 2004-2005, 2007, 2009-2022 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 file is free software: you can redistribute it and/or modify
+ it under the terms of the GNU Lesser 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,
+ This file 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.
+ GNU Lesser General Public License for more details.
- You should have received a copy of the GNU General Public License
+ You should have received a copy of the GNU Lesser General Public License
along with this program. If not, see <https://www.gnu.org/licenses/>. */
#if ! defined TIMESPEC_H
-# define TIMESPEC_H
+#define TIMESPEC_H
-# include <time.h>
+#include <time.h>
#ifndef _GL_INLINE_HEADER_BEGIN
#error "Please include config.h first."
@@ -33,11 +33,19 @@ _GL_INLINE_HEADER_BEGIN
extern "C" {
#endif
-/* Resolution of timespec timestamps (in units per second), and log
- base 10 of the resolution. */
+#include "arg-nonnull.h"
-enum { TIMESPEC_RESOLUTION = 1000000000 };
-enum { LOG10_TIMESPEC_RESOLUTION = 9 };
+/* Inverse resolution of timespec timestamps (in units per second),
+ and log base 10 of the inverse resolution. */
+
+enum { TIMESPEC_HZ = 1000000000 };
+enum { LOG10_TIMESPEC_HZ = 9 };
+
+/* Obsolescent names for backward compatibility.
+ They are misnomers, because TIMESPEC_RESOLUTION is not a resolution. */
+
+enum { TIMESPEC_RESOLUTION = TIMESPEC_HZ };
+enum { LOG10_TIMESPEC_RESOLUTION = LOG10_TIMESPEC_HZ };
/* Return a timespec with seconds S and nanoseconds NS. */
@@ -50,40 +58,12 @@ make_timespec (time_t s, long int ns)
return r;
}
-/* Return negative, zero, positive if A < B, A == B, A > B, respectively.
-
- For each timestamp T, this code assumes that either:
-
- * T.tv_nsec is in the range 0..999999999; or
- * T.tv_sec corresponds to a valid leap second on a host that supports
- leap seconds, and T.tv_nsec is in the range 1000000000..1999999999; or
- * T.tv_sec is the minimum time_t value and T.tv_nsec is -1; or
- T.tv_sec is the maximum time_t value and T.tv_nsec is 2000000000.
- This allows for special struct timespec values that are less or
- greater than all possible valid timestamps.
-
- In all these cases, it is safe to subtract two tv_nsec values and
- convert the result to integer without worrying about overflow on
- any platform of interest to the GNU project, since all such
- platforms have 32-bit int or wider.
-
- Replacing "(int) (a.tv_nsec - b.tv_nsec)" with something like
- "a.tv_nsec < b.tv_nsec ? -1 : a.tv_nsec > b.tv_nsec" would cause
- this function to work in some cases where the above assumption is
- violated, but not in all cases (e.g., a.tv_sec==1, a.tv_nsec==-2,
- b.tv_sec==0, b.tv_nsec==999999999) and is arguably not worth the
- extra instructions. Using a subtraction has the advantage of
- detecting some invalid cases on platforms that detect integer
- overflow.
-
- The (int) cast avoids a gcc -Wconversion warning. */
+/* Return negative, zero, positive if A < B, A == B, A > B, respectively. */
_GL_TIMESPEC_INLINE int _GL_ATTRIBUTE_PURE
timespec_cmp (struct timespec a, struct timespec b)
{
- return (a.tv_sec < b.tv_sec ? -1
- : a.tv_sec > b.tv_sec ? 1
- : (int) (a.tv_nsec - b.tv_nsec));
+ return 2 * _GL_CMP (a.tv_sec, b.tv_sec) + _GL_CMP (a.tv_nsec, b.tv_nsec);
}
/* Return -1, 0, 1, depending on the sign of A. A.tv_nsec must be
@@ -91,7 +71,7 @@ timespec_cmp (struct timespec a, struct timespec b)
_GL_TIMESPEC_INLINE int _GL_ATTRIBUTE_PURE
timespec_sign (struct timespec a)
{
- return a.tv_sec < 0 ? -1 : a.tv_sec || a.tv_nsec;
+ return _GL_CMP (a.tv_sec, 0) + (!a.tv_sec & !!a.tv_nsec);
}
struct timespec timespec_add (struct timespec, struct timespec)
@@ -108,8 +88,10 @@ timespectod (struct timespec a)
return a.tv_sec + a.tv_nsec / 1e9;
}
-void gettime (struct timespec *);
-int settime (struct timespec const *);
+long int gettime_res (void);
+struct timespec current_timespec (void);
+void gettime (struct timespec *) _GL_ARG_NONNULL ((1));
+int settime (struct timespec const *) _GL_ARG_NONNULL ((1));
#ifdef __cplusplus
}
diff --git a/lib/u64.c b/lib/u64.c
index 1e3854ddcd7..0eefeae801b 100644
--- a/lib/u64.c
+++ b/lib/u64.c
@@ -1,4 +1,22 @@
+/* uint64_t-like operations that work even on hosts lacking uint64_t
+
+ Copyright (C) 2012-2022 Free Software Foundation, Inc.
+
+ This file is free software: you can redistribute it and/or modify
+ it under the terms of the GNU Lesser General Public License as
+ published by the Free Software Foundation; either version 2.1 of the
+ License, or (at your option) any later version.
+
+ This file 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 Lesser General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public License
+ along with this program. If not, see <https://www.gnu.org/licenses/>. */
+
#include <config.h>
+
#define _GL_U64_INLINE _GL_EXTERN_INLINE
#include "u64.h"
typedef int dummy;
diff --git a/lib/u64.h b/lib/u64.h
index f56cc382339..1908e7c3896 100644
--- a/lib/u64.h
+++ b/lib/u64.h
@@ -1,18 +1,18 @@
/* uint64_t-like operations that work even on hosts lacking uint64_t
- Copyright (C) 2006, 2009-2017 Free Software Foundation, Inc.
+ Copyright (C) 2006, 2009-2022 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 file is free software: you can redistribute it and/or modify
+ it under the terms of the GNU Lesser General Public License as
+ published by the Free Software Foundation; either version 2.1 of the
+ License, or (at your option) any later version.
- This program is distributed in the hope that it will be useful,
+ This file 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.
+ GNU Lesser General Public License for more details.
- You should have received a copy of the GNU General Public License
+ You should have received a copy of the GNU Lesser General Public License
along with this program. If not, see <https://www.gnu.org/licenses/>. */
/* Written by Paul Eggert. */
diff --git a/lib/unistd.c b/lib/unistd.c
index 72bad1c0527..95978e6ad0a 100644
--- a/lib/unistd.c
+++ b/lib/unistd.c
@@ -1,4 +1,22 @@
+/* Inline functions for <unistd.h>.
+
+ Copyright (C) 2012-2022 Free Software Foundation, Inc.
+
+ This file is free software: you can redistribute it and/or modify
+ it under the terms of the GNU Lesser General Public License as
+ published by the Free Software Foundation; either version 2.1 of the
+ License, or (at your option) any later version.
+
+ This file 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 Lesser General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public License
+ along with this program. If not, see <https://www.gnu.org/licenses/>. */
+
#include <config.h>
+
#define _GL_UNISTD_INLINE _GL_EXTERN_INLINE
#include "unistd.h"
typedef int dummy;
diff --git a/lib/unistd.in.h b/lib/unistd.in.h
index c1dd07ff8cd..57df09ecdf4 100644
--- a/lib/unistd.in.h
+++ b/lib/unistd.in.h
@@ -1,18 +1,18 @@
/* Substitute for and wrapper around <unistd.h>.
- Copyright (C) 2003-2017 Free Software Foundation, Inc.
+ Copyright (C) 2003-2022 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 file is free software: you can redistribute it and/or modify
+ it under the terms of the GNU Lesser General Public License as
+ published by the Free Software Foundation; either version 2.1 of the
+ License, or (at your option) any later version.
- This program is distributed in the hope that it will be useful,
+ This file 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.
+ GNU Lesser General Public License for more details.
- You should have received a copy of the GNU General Public License
- along with this program; if not, see <https://www.gnu.org/licenses/>. */
+ You should have received a copy of the GNU Lesser General Public License
+ along with this program. If not, see <https://www.gnu.org/licenses/>. */
#ifndef _@GUARD_PREFIX@_UNISTD_H
@@ -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
@@ -61,16 +64,18 @@
/* But avoid namespace pollution on glibc systems. */
#if (!(defined SEEK_CUR && defined SEEK_END && defined SEEK_SET) \
|| ((@GNULIB_UNLINK@ || defined GNULIB_POSIXCHECK) \
- && ((defined _WIN32 || defined __WIN32__) && ! defined __CYGWIN__)) \
+ && (defined _WIN32 && ! defined __CYGWIN__)) \
|| ((@GNULIB_SYMLINKAT@ || defined GNULIB_POSIXCHECK) \
&& defined __CYGWIN__)) \
&& ! defined __GLIBC__
# 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
@@ -88,20 +93,18 @@
# undef __need_system_stdlib_h
#endif
-/* Native Windows platforms declare chdir, getcwd, rmdir in
+/* Native Windows platforms declare _chdir, _getcwd, _rmdir in
<io.h> and/or <direct.h>, not in <unistd.h>.
- They also declare access(), chmod(), close(), dup(), dup2(), isatty(),
- lseek(), read(), unlink(), write() in <io.h>. */
-#if ((@GNULIB_CHDIR@ || @GNULIB_GETCWD@ || @GNULIB_RMDIR@ \
- || defined GNULIB_POSIXCHECK) \
- && ((defined _WIN32 || defined __WIN32__) && ! defined __CYGWIN__))
-# include <io.h> /* mingw32, mingw64 */
-# include <direct.h> /* mingw64, MSVC 9 */
-#elif (@GNULIB_CLOSE@ || @GNULIB_DUP@ || @GNULIB_DUP2@ || @GNULIB_ISATTY@ \
- || @GNULIB_LSEEK@ || @GNULIB_READ@ || @GNULIB_UNLINK@ || @GNULIB_WRITE@ \
- || defined GNULIB_POSIXCHECK) \
- && ((defined _WIN32 || defined __WIN32__) && ! defined __CYGWIN__)
+ They also declare _access(), _chmod(), _close(), _dup(), _dup2(), _isatty(),
+ _lseek(), _read(), _unlink(), _write() in <io.h>. */
+#if defined _WIN32 && !defined __CYGWIN__
# include <io.h>
+# include <direct.h>
+#endif
+
+/* Native Windows platforms declare _execl*, _execv* in <process.h>. */
+#if defined _WIN32 && !defined __CYGWIN__
+# include <process.h>
#endif
/* AIX and OSF/1 5.1 declare getdomainname in <netdb.h>, not in <unistd.h>.
@@ -113,20 +116,29 @@
# 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>
+/* Mac OS X 10.13, Solaris 11.4, and Android 9.0 declare getentropy in
+ <sys/random.h>, not in <unistd.h>. */
+/* But avoid namespace pollution on glibc systems. */
+#if (@GNULIB_GETENTROPY@ || defined GNULIB_POSIXCHECK) \
+ && ((defined __APPLE__ && defined __MACH__) || defined __sun \
+ || defined __ANDROID__) \
+ && @UNISTD_H_HAVE_SYS_RANDOM_H@ \
+ && !defined __GLIBC__
+# include <sys/random.h>
#endif
-#if (@GNULIB_READ@ || @GNULIB_WRITE@ \
- || @GNULIB_READLINK@ || @GNULIB_READLINKAT@ \
- || @GNULIB_PREAD@ || @GNULIB_PWRITE@ || defined GNULIB_POSIXCHECK)
-/* Get ssize_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
+/* MSVC defines off_t in <sys/types.h>.
+ May also define off_t to a 64-bit type on native Windows. */
+/* Get off_t, ssize_t, mode_t. */
+#include <sys/types.h>
+
/* The definitions of _GL_FUNCDECL_RPL etc. are copied here. */
/* The definition of _GL_ARG_NONNULL is copied here. */
@@ -134,9 +146,8 @@
/* The definition of _GL_WARN_ON_USE is copied here. */
-/* Get getopt(), optarg, optind, opterr, optopt.
- But avoid namespace pollution on glibc systems. */
-#if @GNULIB_UNISTD_H_GETOPT@ && !defined __GLIBC__ && !defined _GL_SYSTEM_GETOPT
+/* Get getopt(), optarg, optind, opterr, optopt. */
+#if @GNULIB_GETOPT_POSIX@ && @GNULIB_UNISTD_H_GETOPT@ && !defined _GL_SYSTEM_GETOPT
# include <getopt-cdefs.h>
# include <getopt-pfx-core.h>
#endif
@@ -248,15 +259,61 @@ _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));
+# elif defined _WIN32 && !defined __CYGWIN__
+# if !(defined __cplusplus && defined GNULIB_NAMESPACE)
+# undef access
+# define access _access
+# endif
+_GL_CXXALIAS_MDA (access, int, (const char *file, int mode));
+# else
+_GL_CXXALIAS_SYS (access, int, (const char *file, int mode));
+# endif
+_GL_CXXALIASWARN (access);
+#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
+#elif @GNULIB_MDA_ACCESS@
+/* On native Windows, map 'access' to '_access', so that -loldnames is not
+ required. In C++ with GNULIB_NAMESPACE, avoid differences between
+ platforms by defining GNULIB_NAMESPACE::access always. */
+# if defined _WIN32 && !defined __CYGWIN__
+# if !(defined __cplusplus && defined GNULIB_NAMESPACE)
+# undef access
+# define access _access
+# endif
+_GL_CXXALIAS_MDA (access, int, (const char *file, int mode));
+# else
+_GL_CXXALIAS_SYS (access, int, (const char *file, int mode));
+# endif
+_GL_CXXALIASWARN (access);
#endif
#if @GNULIB_CHDIR@
+# if defined _WIN32 && !defined __CYGWIN__
+# if !(defined __cplusplus && defined GNULIB_NAMESPACE)
+# undef chdir
+# define chdir _chdir
+# endif
+_GL_CXXALIAS_MDA (chdir, int, (const char *file));
+# else
_GL_CXXALIAS_SYS (chdir, int, (const char *file) _GL_ARG_NONNULL ((1)));
+# endif
_GL_CXXALIASWARN (chdir);
#elif defined GNULIB_POSIXCHECK
# undef chdir
@@ -264,6 +321,20 @@ _GL_CXXALIASWARN (chdir);
_GL_WARN_ON_USE (chown, "chdir is not always in <unistd.h> - "
"use gnulib module chdir for portability");
# endif
+#elif @GNULIB_MDA_CHDIR@
+/* On native Windows, map 'chdir' to '_chdir', so that -loldnames is not
+ required. In C++ with GNULIB_NAMESPACE, avoid differences between
+ platforms by defining GNULIB_NAMESPACE::chdir always. */
+# if defined _WIN32 && !defined __CYGWIN__
+# if !(defined __cplusplus && defined GNULIB_NAMESPACE)
+# undef chdir
+# define chdir _chdir
+# endif
+_GL_CXXALIAS_MDA (chdir, int, (const char *file));
+# else
+_GL_CXXALIAS_SYS (chdir, int, (const char *file) _GL_ARG_NONNULL ((1)));
+# endif
+_GL_CXXALIASWARN (chdir);
#endif
@@ -272,7 +343,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
@@ -308,6 +379,12 @@ _GL_WARN_ON_USE (chown, "chown fails to follow symlinks on some systems and "
# endif
_GL_FUNCDECL_RPL (close, int, (int fd));
_GL_CXXALIAS_RPL (close, int, (int fd));
+# elif defined _WIN32 && !defined __CYGWIN__
+# if !(defined __cplusplus && defined GNULIB_NAMESPACE)
+# undef close
+# define close _close
+# endif
+_GL_CXXALIAS_MDA (close, int, (int fd));
# else
_GL_CXXALIAS_SYS (close, int, (int fd));
# endif
@@ -320,6 +397,53 @@ _GL_CXXALIASWARN (close);
/* Assume close is always declared. */
_GL_WARN_ON_USE (close, "close does not portably work on sockets - "
"use gnulib module close for portability");
+#elif @GNULIB_MDA_CLOSE@
+/* On native Windows, map 'close' to '_close', so that -loldnames is not
+ required. In C++ with GNULIB_NAMESPACE, avoid differences between
+ platforms by defining GNULIB_NAMESPACE::close always. */
+# if defined _WIN32 && !defined __CYGWIN__
+# if !(defined __cplusplus && defined GNULIB_NAMESPACE)
+# undef close
+# define close _close
+# endif
+_GL_CXXALIAS_MDA (close, int, (int fd));
+# else
+_GL_CXXALIAS_SYS (close, int, (int fd));
+# endif
+_GL_CXXALIASWARN (close);
+#endif
+
+
+#if @GNULIB_COPY_FILE_RANGE@
+# if @REPLACE_COPY_FILE_RANGE@
+# if !(defined __cplusplus && defined GNULIB_NAMESPACE)
+# undef copy_file_range
+# define copy_file_range rpl_copy_file_range
+# endif
+_GL_FUNCDECL_RPL (copy_file_range, ssize_t, (int ifd, off_t *ipos,
+ int ofd, off_t *opos,
+ size_t len, unsigned flags));
+_GL_CXXALIAS_RPL (copy_file_range, ssize_t, (int ifd, off_t *ipos,
+ int ofd, off_t *opos,
+ size_t len, unsigned flags));
+# else
+# 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));
+# endif
+_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
+# undef copy_file_range
+# if HAVE_RAW_DECL_COPY_FILE_RANGE
+_GL_WARN_ON_USE (copy_file_range,
+ "copy_file_range is unportable - "
+ "use gnulib module copy_file_range for portability");
+# endif
#endif
@@ -330,6 +454,12 @@ _GL_WARN_ON_USE (close, "close does not portably work on sockets - "
# endif
_GL_FUNCDECL_RPL (dup, int, (int oldfd));
_GL_CXXALIAS_RPL (dup, int, (int oldfd));
+# elif defined _WIN32 && !defined __CYGWIN__
+# if !(defined __cplusplus && defined GNULIB_NAMESPACE)
+# undef dup
+# define dup _dup
+# endif
+_GL_CXXALIAS_MDA (dup, int, (int oldfd));
# else
_GL_CXXALIAS_SYS (dup, int, (int oldfd));
# endif
@@ -340,6 +470,20 @@ _GL_CXXALIASWARN (dup);
_GL_WARN_ON_USE (dup, "dup is unportable - "
"use gnulib module dup for portability");
# endif
+#elif @GNULIB_MDA_DUP@
+/* On native Windows, map 'dup' to '_dup', so that -loldnames is not
+ required. In C++ with GNULIB_NAMESPACE, avoid differences between
+ platforms by defining GNULIB_NAMESPACE::dup always. */
+# if defined _WIN32 && !defined __CYGWIN__
+# if !(defined __cplusplus && defined GNULIB_NAMESPACE)
+# undef dup
+# define dup _dup
+# endif
+_GL_CXXALIAS_MDA (dup, int, (int oldfd));
+# else
+_GL_CXXALIAS_SYS (dup, int, (int oldfd));
+# endif
+_GL_CXXALIASWARN (dup);
#endif
@@ -348,17 +492,20 @@ _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
# endif
_GL_FUNCDECL_RPL (dup2, int, (int oldfd, int newfd));
_GL_CXXALIAS_RPL (dup2, int, (int oldfd, int newfd));
-# else
-# if !@HAVE_DUP2@
-_GL_FUNCDECL_SYS (dup2, int, (int oldfd, int newfd));
+# elif defined _WIN32 && !defined __CYGWIN__
+# if !(defined __cplusplus && defined GNULIB_NAMESPACE)
+# undef dup2
+# define dup2 _dup2
# endif
+_GL_CXXALIAS_MDA (dup2, int, (int oldfd, int newfd));
+# else
_GL_CXXALIAS_SYS (dup2, int, (int oldfd, int newfd));
# endif
_GL_CXXALIASWARN (dup2);
@@ -368,6 +515,20 @@ _GL_CXXALIASWARN (dup2);
_GL_WARN_ON_USE (dup2, "dup2 is unportable - "
"use gnulib module dup2 for portability");
# endif
+#elif @GNULIB_MDA_DUP2@
+/* On native Windows, map 'dup2' to '_dup2', so that -loldnames is not
+ required. In C++ with GNULIB_NAMESPACE, avoid differences between
+ platforms by defining GNULIB_NAMESPACE::dup2 always. */
+# if defined _WIN32 && !defined __CYGWIN__
+# if !(defined __cplusplus && defined GNULIB_NAMESPACE)
+# undef dup2
+# define dup2 _dup2
+# endif
+_GL_CXXALIAS_MDA (dup2, int, (int oldfd, int newfd));
+# else
+_GL_CXXALIAS_SYS (dup2, int, (int oldfd, int newfd));
+# endif
+_GL_CXXALIASWARN (dup2);
#endif
@@ -401,6 +562,13 @@ _GL_WARN_ON_USE (dup3, "dup3 is unportable - "
#if @GNULIB_ENVIRON@
+# if defined __CYGWIN__ && !defined __i386__
+/* The 'environ' variable is defined in a DLL. Therefore its declaration needs
+ the '__declspec(dllimport)' attribute, but the system's <unistd.h> lacks it.
+ This leads to a link error on 64-bit Cygwin when the option
+ -Wl,--disable-auto-import is in use. */
+_GL_EXTERN_C __declspec(dllimport) char **environ;
+# endif
# if !@HAVE_DECL_ENVIRON@
/* Set of environment variables and values. An array of strings of the form
"VARIABLE=VALUE", terminated with a NULL. */
@@ -426,12 +594,12 @@ extern char **environ;
#elif defined GNULIB_POSIXCHECK
# if HAVE_RAW_DECL_ENVIRON
_GL_UNISTD_INLINE char ***
+_GL_WARN_ON_USE_ATTRIBUTE ("environ is unportable - "
+ "use gnulib module environ for portability")
rpl_environ (void)
{
return &environ;
}
-_GL_WARN_ON_USE (rpl_environ, "environ is unportable - "
- "use gnulib module environ for portability");
# undef environ
# define environ (*rpl_environ ())
# endif
@@ -461,14 +629,302 @@ _GL_WARN_ON_USE (euidaccess, "euidaccess is unportable - "
#endif
+#if @GNULIB_EXECL@
+# if @REPLACE_EXECL@
+# if !(defined __cplusplus && defined GNULIB_NAMESPACE)
+# undef execl
+# define execl rpl_execl
+# endif
+_GL_FUNCDECL_RPL (execl, int, (const char *program, const char *arg, ...)
+ _GL_ARG_NONNULL ((1)));
+_GL_CXXALIAS_RPL (execl, int, (const char *program, const char *arg, ...));
+# else
+_GL_CXXALIAS_SYS (execl, int, (const char *program, const char *arg, ...));
+# endif
+_GL_CXXALIASWARN (execl);
+#elif defined GNULIB_POSIXCHECK
+# undef execl
+# if HAVE_RAW_DECL_EXECL
+_GL_WARN_ON_USE (execl, "execl behaves very differently on mingw - "
+ "use gnulib module execl for portability");
+# endif
+#elif @GNULIB_MDA_EXECL@
+/* On native Windows, map 'execl' to '_execl', so that -loldnames is not
+ required. In C++ with GNULIB_NAMESPACE, avoid differences between
+ platforms by defining GNULIB_NAMESPACE::execl always. */
+# if defined _WIN32 && !defined __CYGWIN__
+# if !(defined __cplusplus && defined GNULIB_NAMESPACE)
+# undef execl
+# define execl _execl
+# endif
+_GL_CXXALIAS_MDA (execl, intptr_t, (const char *program, const char *arg, ...));
+# else
+_GL_CXXALIAS_SYS (execl, int, (const char *program, const char *arg, ...));
+# endif
+_GL_CXXALIASWARN (execl);
+#endif
+
+#if @GNULIB_EXECLE@
+# if @REPLACE_EXECLE@
+# if !(defined __cplusplus && defined GNULIB_NAMESPACE)
+# undef execle
+# define execle rpl_execle
+# endif
+_GL_FUNCDECL_RPL (execle, int, (const char *program, const char *arg, ...)
+ _GL_ARG_NONNULL ((1)));
+_GL_CXXALIAS_RPL (execle, int, (const char *program, const char *arg, ...));
+# else
+_GL_CXXALIAS_SYS (execle, int, (const char *program, const char *arg, ...));
+# endif
+_GL_CXXALIASWARN (execle);
+#elif defined GNULIB_POSIXCHECK
+# undef execle
+# if HAVE_RAW_DECL_EXECLE
+_GL_WARN_ON_USE (execle, "execle behaves very differently on mingw - "
+ "use gnulib module execle for portability");
+# endif
+#elif @GNULIB_MDA_EXECLE@
+/* On native Windows, map 'execle' to '_execle', so that -loldnames is not
+ required. In C++ with GNULIB_NAMESPACE, avoid differences between
+ platforms by defining GNULIB_NAMESPACE::execle always. */
+# if defined _WIN32 && !defined __CYGWIN__
+# if !(defined __cplusplus && defined GNULIB_NAMESPACE)
+# undef execle
+# define execle _execle
+# endif
+_GL_CXXALIAS_MDA (execle, intptr_t,
+ (const char *program, const char *arg, ...));
+# else
+_GL_CXXALIAS_SYS (execle, int, (const char *program, const char *arg, ...));
+# endif
+_GL_CXXALIASWARN (execle);
+#endif
+
+#if @GNULIB_EXECLP@
+# if @REPLACE_EXECLP@
+# if !(defined __cplusplus && defined GNULIB_NAMESPACE)
+# undef execlp
+# define execlp rpl_execlp
+# endif
+_GL_FUNCDECL_RPL (execlp, int, (const char *program, const char *arg, ...)
+ _GL_ARG_NONNULL ((1)));
+_GL_CXXALIAS_RPL (execlp, int, (const char *program, const char *arg, ...));
+# else
+_GL_CXXALIAS_SYS (execlp, int, (const char *program, const char *arg, ...));
+# endif
+_GL_CXXALIASWARN (execlp);
+#elif defined GNULIB_POSIXCHECK
+# undef execlp
+# if HAVE_RAW_DECL_EXECLP
+_GL_WARN_ON_USE (execlp, "execlp behaves very differently on mingw - "
+ "use gnulib module execlp for portability");
+# endif
+#elif @GNULIB_MDA_EXECLP@
+/* On native Windows, map 'execlp' to '_execlp', so that -loldnames is not
+ required. In C++ with GNULIB_NAMESPACE, avoid differences between
+ platforms by defining GNULIB_NAMESPACE::execlp always. */
+# if defined _WIN32 && !defined __CYGWIN__
+# if !(defined __cplusplus && defined GNULIB_NAMESPACE)
+# undef execlp
+# define execlp _execlp
+# endif
+_GL_CXXALIAS_MDA (execlp, intptr_t,
+ (const char *program, const char *arg, ...));
+# else
+_GL_CXXALIAS_SYS (execlp, int, (const char *program, const char *arg, ...));
+# endif
+_GL_CXXALIASWARN (execlp);
+#endif
+
+
+#if @GNULIB_EXECV@
+# if @REPLACE_EXECV@
+# if !(defined __cplusplus && defined GNULIB_NAMESPACE)
+# undef execv
+# define execv rpl_execv
+# endif
+_GL_FUNCDECL_RPL (execv, int, (const char *program, char * const *argv)
+ _GL_ARG_NONNULL ((1, 2)));
+_GL_CXXALIAS_RPL (execv, int, (const char *program, char * const *argv));
+# else
+_GL_CXXALIAS_SYS (execv, int, (const char *program, char * const *argv));
+# endif
+_GL_CXXALIASWARN (execv);
+#elif defined GNULIB_POSIXCHECK
+# undef execv
+# if HAVE_RAW_DECL_EXECV
+_GL_WARN_ON_USE (execv, "execv behaves very differently on mingw - "
+ "use gnulib module execv for portability");
+# endif
+#elif @GNULIB_MDA_EXECV@
+/* On native Windows, map 'execv' to '_execv', so that -loldnames is not
+ required. In C++ with GNULIB_NAMESPACE, avoid differences between
+ platforms by defining GNULIB_NAMESPACE::execv always. */
+# if defined _WIN32 && !defined __CYGWIN__
+# if !(defined __cplusplus && defined GNULIB_NAMESPACE)
+# undef execv
+# define execv _execv
+# endif
+_GL_CXXALIAS_MDA_CAST (execv, intptr_t,
+ (const char *program, char * const *argv));
+# else
+_GL_CXXALIAS_SYS (execv, int, (const char *program, char * const *argv));
+# endif
+_GL_CXXALIASWARN (execv);
+#endif
+
+#if @GNULIB_EXECVE@
+# if @REPLACE_EXECVE@
+# if !(defined __cplusplus && defined GNULIB_NAMESPACE)
+# undef execve
+# define execve rpl_execve
+# endif
+_GL_FUNCDECL_RPL (execve, int,
+ (const char *program, char * const *argv, char * const *env)
+ _GL_ARG_NONNULL ((1, 2)));
+_GL_CXXALIAS_RPL (execve, int,
+ (const char *program, char * const *argv, char * const *env));
+# else
+_GL_CXXALIAS_SYS (execve, int,
+ (const char *program, char * const *argv, char * const *env));
+# endif
+_GL_CXXALIASWARN (execve);
+#elif defined GNULIB_POSIXCHECK
+# undef execve
+# if HAVE_RAW_DECL_EXECVE
+_GL_WARN_ON_USE (execve, "execve behaves very differently on mingw - "
+ "use gnulib module execve for portability");
+# endif
+#elif @GNULIB_MDA_EXECVE@
+/* On native Windows, map 'execve' to '_execve', so that -loldnames is not
+ required. In C++ with GNULIB_NAMESPACE, avoid differences between
+ platforms by defining GNULIB_NAMESPACE::execve always. */
+# if defined _WIN32 && !defined __CYGWIN__
+# if !(defined __cplusplus && defined GNULIB_NAMESPACE)
+# undef execve
+# define execve _execve
+# endif
+_GL_CXXALIAS_MDA_CAST (execve, intptr_t,
+ (const char *program, char * const *argv,
+ char * const *env));
+# else
+_GL_CXXALIAS_SYS (execve, int,
+ (const char *program, char * const *argv, char * const *env));
+# endif
+_GL_CXXALIASWARN (execve);
+#endif
+
+#if @GNULIB_EXECVP@
+# if @REPLACE_EXECVP@
+# if !(defined __cplusplus && defined GNULIB_NAMESPACE)
+# undef execvp
+# define execvp rpl_execvp
+# endif
+_GL_FUNCDECL_RPL (execvp, int, (const char *program, char * const *argv)
+ _GL_ARG_NONNULL ((1, 2)));
+_GL_CXXALIAS_RPL (execvp, int, (const char *program, char * const *argv));
+# else
+_GL_CXXALIAS_SYS (execvp, int, (const char *program, char * const *argv));
+# endif
+_GL_CXXALIASWARN (execvp);
+#elif defined GNULIB_POSIXCHECK
+# undef execvp
+# if HAVE_RAW_DECL_EXECVP
+_GL_WARN_ON_USE (execvp, "execvp behaves very differently on mingw - "
+ "use gnulib module execvp for portability");
+# endif
+#elif @GNULIB_MDA_EXECVP@
+/* On native Windows, map 'execvp' to '_execvp', so that -loldnames is not
+ required. In C++ with GNULIB_NAMESPACE, avoid differences between
+ platforms by defining GNULIB_NAMESPACE::execvp always. */
+# if defined _WIN32 && !defined __CYGWIN__
+# if !(defined __cplusplus && defined GNULIB_NAMESPACE)
+# undef execvp
+# define execvp _execvp
+# endif
+_GL_CXXALIAS_MDA_CAST (execvp, intptr_t,
+ (const char *program, char * const *argv));
+# else
+_GL_CXXALIAS_SYS (execvp, int, (const char *program, char * const *argv));
+# endif
+_GL_CXXALIASWARN (execvp);
+#endif
+
+#if @GNULIB_EXECVPE@
+# if @REPLACE_EXECVPE@
+# if !(defined __cplusplus && defined GNULIB_NAMESPACE)
+# undef execvpe
+# define execvpe rpl_execvpe
+# endif
+_GL_FUNCDECL_RPL (execvpe, int,
+ (const char *program, char * const *argv, char * const *env)
+ _GL_ARG_NONNULL ((1, 2)));
+_GL_CXXALIAS_RPL (execvpe, int,
+ (const char *program, char * const *argv, char * const *env));
+# else
+# if !@HAVE_DECL_EXECVPE@
+_GL_FUNCDECL_SYS (execvpe, int,
+ (const char *program, char * const *argv, char * const *env)
+ _GL_ARG_NONNULL ((1, 2)));
+# endif
+_GL_CXXALIAS_SYS (execvpe, int,
+ (const char *program, char * const *argv, char * const *env));
+# endif
+_GL_CXXALIASWARN (execvpe);
+#elif defined GNULIB_POSIXCHECK
+# undef execvpe
+# if HAVE_RAW_DECL_EXECVPE
+_GL_WARN_ON_USE (execvpe, "execvpe behaves very differently on mingw - "
+ "use gnulib module execvpe for portability");
+# endif
+#elif @GNULIB_MDA_EXECVPE@
+/* On native Windows, map 'execvpe' to '_execvpe', so that -loldnames is not
+ required. In C++ with GNULIB_NAMESPACE, avoid differences between
+ platforms by defining GNULIB_NAMESPACE::execvpe on all platforms that have
+ it. */
+# if defined _WIN32 && !defined __CYGWIN__
+# if !(defined __cplusplus && defined GNULIB_NAMESPACE)
+# undef execvpe
+# define execvpe _execvpe
+# endif
+_GL_CXXALIAS_MDA_CAST (execvpe, intptr_t,
+ (const char *program, char * const *argv,
+ char * const *env));
+# elif @HAVE_EXECVPE@
+# if !@HAVE_DECL_EXECVPE@
+_GL_FUNCDECL_SYS (execvpe, int,
+ (const char *program, char * const *argv, char * const *env)
+ _GL_ARG_NONNULL ((1, 2)));
+# endif
+_GL_CXXALIAS_SYS (execvpe, int,
+ (const char *program, char * const *argv, char * const *env));
+# endif
+# if (defined _WIN32 && !defined __CYGWIN__) || @HAVE_EXECVPE@
+_GL_CXXALIASWARN (execvpe);
+# endif
+#endif
+
+
#if @GNULIB_FACCESSAT@
-# if !@HAVE_FACCESSAT@
+# if @REPLACE_FACCESSAT@
+# if !(defined __cplusplus && defined GNULIB_NAMESPACE)
+# undef faccessat
+# define faccessat rpl_faccessat
+# endif
+_GL_FUNCDECL_RPL (faccessat, int,
+ (int fd, char const *name, int mode, int flag)
+ _GL_ARG_NONNULL ((2)));
+_GL_CXXALIAS_RPL (faccessat, int,
+ (int fd, char const *name, int mode, int flag));
+# else
+# if !@HAVE_FACCESSAT@
_GL_FUNCDECL_SYS (faccessat, int,
(int fd, char const *file, int mode, int flag)
_GL_ARG_NONNULL ((2)));
-# endif
+# endif
_GL_CXXALIAS_SYS (faccessat, int,
(int fd, char const *file, int mode, int flag));
+# endif
_GL_CXXALIASWARN (faccessat);
#elif defined GNULIB_POSIXCHECK
# undef faccessat
@@ -484,7 +940,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*/));
@@ -536,7 +992,7 @@ _GL_CXXALIASWARN (fchownat);
# undef fchownat
# if HAVE_RAW_DECL_FCHOWNAT
_GL_WARN_ON_USE (fchownat, "fchownat is not portable - "
- "use gnulib module openat for portability");
+ "use gnulib module fchownat for portability");
# endif
#endif
@@ -545,7 +1001,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
@@ -564,7 +1020,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
@@ -583,7 +1039,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
@@ -613,7 +1069,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
@@ -624,6 +1080,12 @@ _GL_WARN_ON_USE (ftruncate, "ftruncate is unportable - "
# endif
_GL_FUNCDECL_RPL (getcwd, char *, (char *buf, size_t size));
_GL_CXXALIAS_RPL (getcwd, char *, (char *buf, size_t size));
+# elif defined _WIN32 && !defined __CYGWIN__
+# if !(defined __cplusplus && defined GNULIB_NAMESPACE)
+# undef getcwd
+# define getcwd _getcwd
+# endif
+_GL_CXXALIAS_MDA (getcwd, char *, (char *buf, size_t size));
# else
/* Need to cast, because on mingw, the second parameter is
int size. */
@@ -636,6 +1098,22 @@ _GL_CXXALIASWARN (getcwd);
_GL_WARN_ON_USE (getcwd, "getcwd is unportable - "
"use gnulib module getcwd for portability");
# endif
+#elif @GNULIB_MDA_GETCWD@
+/* On native Windows, map 'getcwd' to '_getcwd', so that -loldnames is not
+ required. In C++ with GNULIB_NAMESPACE, avoid differences between
+ platforms by defining GNULIB_NAMESPACE::getcwd always. */
+# if defined _WIN32 && !defined __CYGWIN__
+# if !(defined __cplusplus && defined GNULIB_NAMESPACE)
+# undef getcwd
+# define getcwd _getcwd
+# endif
+/* Need to cast, because on mingw, the second parameter is either
+ 'int size' or 'size_t size'. */
+_GL_CXXALIAS_MDA_CAST (getcwd, char *, (char *buf, size_t size));
+# else
+_GL_CXXALIAS_SYS_CAST (getcwd, char *, (char *buf, size_t size));
+# endif
+_GL_CXXALIASWARN (getcwd);
#endif
@@ -689,7 +1167,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
@@ -701,6 +1181,22 @@ _GL_WARN_ON_USE (getdtablesize, "getdtablesize is unportable - "
#endif
+#if @GNULIB_GETENTROPY@
+/* Fill a buffer with random bytes. */
+# if !@HAVE_GETENTROPY@
+_GL_FUNCDECL_SYS (getentropy, int, (void *buffer, size_t length));
+# endif
+_GL_CXXALIAS_SYS (getentropy, int, (void *buffer, size_t length));
+_GL_CXXALIASWARN (getentropy);
+#elif defined GNULIB_POSIXCHECK
+# undef getentropy
+# if HAVE_RAW_DECL_GETENTROPY
+_GL_WARN_ON_USE (getentropy, "getentropy is unportable - "
+ "use gnulib module getentropy for portability");
+# endif
+#endif
+
+
#if @GNULIB_GETGROUPS@
/* Return the supplemental groups that the current process belongs to.
It is unspecified whether the effective group id is in the list.
@@ -773,7 +1269,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:
@@ -802,7 +1298,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:
@@ -843,6 +1339,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. */
@@ -917,6 +1418,54 @@ _GL_WARN_ON_USE (getpagesize, "getpagesize is unportable - "
#endif
+#if @GNULIB_GETPASS@
+/* Function getpass() from module 'getpass':
+ Read a password from /dev/tty or stdin.
+ Function getpass() from module 'getpass-gnu':
+ Read a password of arbitrary length from /dev/tty or stdin. */
+# if (@GNULIB_GETPASS@ && @REPLACE_GETPASS@) \
+ || (@GNULIB_GETPASS_GNU@ && @REPLACE_GETPASS_FOR_GETPASS_GNU@)
+# if !(defined __cplusplus && defined GNULIB_NAMESPACE)
+# undef getpass
+# define getpass rpl_getpass
+# endif
+_GL_FUNCDECL_RPL (getpass, char *, (const char *prompt)
+ _GL_ARG_NONNULL ((1)));
+_GL_CXXALIAS_RPL (getpass, char *, (const char *prompt));
+# else
+# if !@HAVE_GETPASS@
+_GL_FUNCDECL_SYS (getpass, char *, (const char *prompt)
+ _GL_ARG_NONNULL ((1)));
+# endif
+_GL_CXXALIAS_SYS (getpass, char *, (const char *prompt));
+# endif
+_GL_CXXALIASWARN (getpass);
+#elif defined GNULIB_POSIXCHECK
+# undef getpass
+# if HAVE_RAW_DECL_GETPASS
+_GL_WARN_ON_USE (getpass, "getpass is unportable - "
+ "use gnulib module getpass or getpass-gnu for portability");
+# endif
+#endif
+
+
+#if @GNULIB_MDA_GETPID@
+/* On native Windows, map 'getpid' to '_getpid', so that -loldnames is not
+ required. In C++ with GNULIB_NAMESPACE, avoid differences between
+ platforms by defining GNULIB_NAMESPACE::getpid always. */
+# if defined _WIN32 && !defined __CYGWIN__
+# if !(defined __cplusplus && defined GNULIB_NAMESPACE)
+# undef getpid
+# define getpid _getpid
+# endif
+_GL_CXXALIAS_MDA (getpid, int, (void));
+# else
+_GL_CXXALIAS_SYS (getpid, pid_t, (void));
+# endif
+_GL_CXXALIASWARN (getpid);
+#endif
+
+
#if @GNULIB_GETUSERSHELL@
/* Return the next valid login shell on the system, or NULL when the end of
the list has been reached. */
@@ -987,8 +1536,15 @@ _GL_WARN_ON_USE (group_member, "group_member is unportable - "
# undef isatty
# define isatty rpl_isatty
# endif
+# define GNULIB_defined_isatty 1
_GL_FUNCDECL_RPL (isatty, int, (int fd));
_GL_CXXALIAS_RPL (isatty, int, (int fd));
+# elif defined _WIN32 && !defined __CYGWIN__
+# if !(defined __cplusplus && defined GNULIB_NAMESPACE)
+# undef isatty
+# define isatty _isatty
+# endif
+_GL_CXXALIAS_MDA (isatty, int, (int fd));
# else
_GL_CXXALIAS_SYS (isatty, int, (int fd));
# endif
@@ -999,6 +1555,20 @@ _GL_CXXALIASWARN (isatty);
_GL_WARN_ON_USE (isatty, "isatty has portability problems on native Windows - "
"use gnulib module isatty for portability");
# endif
+#elif @GNULIB_MDA_ISATTY@
+/* On native Windows, map 'isatty' to '_isatty', so that -loldnames is not
+ required. In C++ with GNULIB_NAMESPACE, avoid differences between
+ platforms by defining GNULIB_NAMESPACE::isatty always. */
+# if defined _WIN32 && !defined __CYGWIN__
+# if !(defined __cplusplus && defined GNULIB_NAMESPACE)
+# undef isatty
+# define isatty _isatty
+# endif
+_GL_CXXALIAS_MDA (isatty, int, (int fd));
+# else
+_GL_CXXALIAS_SYS (isatty, int, (int fd));
+# endif
+_GL_CXXALIASWARN (isatty);
#endif
@@ -1007,7 +1577,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
@@ -1037,7 +1607,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
@@ -1103,13 +1673,19 @@ _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
# endif
_GL_FUNCDECL_RPL (lseek, off_t, (int fd, off_t offset, int whence));
_GL_CXXALIAS_RPL (lseek, off_t, (int fd, off_t offset, int whence));
+# elif defined _WIN32 && !defined __CYGWIN__
+# if !(defined __cplusplus && defined GNULIB_NAMESPACE)
+# undef lseek
+# define lseek _lseek
+# endif
+_GL_CXXALIAS_MDA (lseek, off_t, (int fd, off_t offset, int whence));
# else
_GL_CXXALIAS_SYS (lseek, off_t, (int fd, off_t offset, int whence));
# endif
@@ -1120,6 +1696,20 @@ _GL_CXXALIASWARN (lseek);
_GL_WARN_ON_USE (lseek, "lseek does not fail with ESPIPE on pipes on some "
"systems - use gnulib module lseek for portability");
# endif
+#elif @GNULIB_MDA_LSEEK@
+/* On native Windows, map 'lseek' to '_lseek', so that -loldnames is not
+ required. In C++ with GNULIB_NAMESPACE, avoid differences between
+ platforms by defining GNULIB_NAMESPACE::lseek always. */
+# if defined _WIN32 && !defined __CYGWIN__
+# if !(defined __cplusplus && defined GNULIB_NAMESPACE)
+# undef lseek
+# define lseek _lseek
+# endif
+_GL_CXXALIAS_MDA (lseek, long, (int fd, long offset, int whence));
+# else
+_GL_CXXALIAS_SYS (lseek, off_t, (int fd, off_t offset, int whence));
+# endif
+_GL_CXXALIASWARN (lseek);
#endif
@@ -1175,7 +1765,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
@@ -1210,7 +1800,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
@@ -1243,7 +1833,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
@@ -1252,11 +1842,32 @@ _GL_WARN_ON_USE (pwrite, "pwrite is unportable - "
_GL_FUNCDECL_RPL (read, ssize_t, (int fd, void *buf, size_t count)
_GL_ARG_NONNULL ((2)));
_GL_CXXALIAS_RPL (read, ssize_t, (int fd, void *buf, size_t count));
+# elif defined _WIN32 && !defined __CYGWIN__
+# if !(defined __cplusplus && defined GNULIB_NAMESPACE)
+# undef read
+# define read _read
+# endif
+_GL_CXXALIAS_MDA (read, ssize_t, (int fd, void *buf, size_t count));
# else
-/* Need to cast, because on mingw, the third parameter is
- unsigned int count
- and the return type is 'int'. */
-_GL_CXXALIAS_SYS_CAST (read, ssize_t, (int fd, void *buf, size_t count));
+_GL_CXXALIAS_SYS (read, ssize_t, (int fd, void *buf, size_t count));
+# endif
+_GL_CXXALIASWARN (read);
+#elif @GNULIB_MDA_READ@
+/* On native Windows, map 'read' to '_read', so that -loldnames is not
+ required. In C++ with GNULIB_NAMESPACE, avoid differences between
+ platforms by defining GNULIB_NAMESPACE::read always. */
+# if defined _WIN32 && !defined __CYGWIN__
+# if !(defined __cplusplus && defined GNULIB_NAMESPACE)
+# undef read
+# define read _read
+# endif
+# ifdef __MINGW32__
+_GL_CXXALIAS_MDA (read, int, (int fd, void *buf, unsigned int count));
+# else
+_GL_CXXALIAS_MDA (read, ssize_t, (int fd, void *buf, unsigned int count));
+# endif
+# else
+_GL_CXXALIAS_SYS (read, ssize_t, (int fd, void *buf, size_t count));
# endif
_GL_CXXALIASWARN (read);
#endif
@@ -1267,24 +1878,28 @@ _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
# endif
_GL_FUNCDECL_RPL (readlink, ssize_t,
- (const char *file, char *buf, size_t bufsize)
+ (const char *restrict file,
+ char *restrict buf, size_t bufsize)
_GL_ARG_NONNULL ((1, 2)));
_GL_CXXALIAS_RPL (readlink, ssize_t,
- (const char *file, char *buf, size_t bufsize));
+ (const char *restrict file,
+ char *restrict buf, size_t bufsize));
# else
# if !@HAVE_READLINK@
_GL_FUNCDECL_SYS (readlink, ssize_t,
- (const char *file, char *buf, size_t bufsize)
+ (const char *restrict file,
+ char *restrict buf, size_t bufsize)
_GL_ARG_NONNULL ((1, 2)));
# endif
_GL_CXXALIAS_SYS (readlink, ssize_t,
- (const char *file, char *buf, size_t bufsize));
+ (const char *restrict file,
+ char *restrict buf, size_t bufsize));
# endif
_GL_CXXALIASWARN (readlink);
#elif defined GNULIB_POSIXCHECK
@@ -1302,18 +1917,22 @@ _GL_WARN_ON_USE (readlink, "readlink is unportable - "
# define readlinkat rpl_readlinkat
# endif
_GL_FUNCDECL_RPL (readlinkat, ssize_t,
- (int fd, char const *file, char *buf, size_t len)
+ (int fd, char const *restrict file,
+ char *restrict buf, size_t len)
_GL_ARG_NONNULL ((2, 3)));
_GL_CXXALIAS_RPL (readlinkat, ssize_t,
- (int fd, char const *file, char *buf, size_t len));
+ (int fd, char const *restrict file,
+ char *restrict buf, size_t len));
# else
# if !@HAVE_READLINKAT@
_GL_FUNCDECL_SYS (readlinkat, ssize_t,
- (int fd, char const *file, char *buf, size_t len)
+ (int fd, char const *restrict file,
+ char *restrict buf, size_t len)
_GL_ARG_NONNULL ((2, 3)));
# endif
_GL_CXXALIAS_SYS (readlinkat, ssize_t,
- (int fd, char const *file, char *buf, size_t len));
+ (int fd, char const *restrict file,
+ char *restrict buf, size_t len));
# endif
_GL_CXXALIASWARN (readlinkat);
#elif defined GNULIB_POSIXCHECK
@@ -1333,6 +1952,12 @@ _GL_WARN_ON_USE (readlinkat, "readlinkat is not portable - "
# endif
_GL_FUNCDECL_RPL (rmdir, int, (char const *name) _GL_ARG_NONNULL ((1)));
_GL_CXXALIAS_RPL (rmdir, int, (char const *name));
+# elif defined _WIN32 && !defined __CYGWIN__
+# if !(defined __cplusplus && defined GNULIB_NAMESPACE)
+# undef rmdir
+# define rmdir _rmdir
+# endif
+_GL_CXXALIAS_MDA (rmdir, int, (char const *name));
# else
_GL_CXXALIAS_SYS (rmdir, int, (char const *name));
# endif
@@ -1343,6 +1968,20 @@ _GL_CXXALIASWARN (rmdir);
_GL_WARN_ON_USE (rmdir, "rmdir is unportable - "
"use gnulib module rmdir for portability");
# endif
+#elif @GNULIB_MDA_RMDIR@
+/* On native Windows, map 'rmdir' to '_rmdir', so that -loldnames is not
+ required. In C++ with GNULIB_NAMESPACE, avoid differences between
+ platforms by defining GNULIB_NAMESPACE::rmdir always. */
+# if defined _WIN32 && !defined __CYGWIN__
+# if !(defined __cplusplus && defined GNULIB_NAMESPACE)
+# undef rmdir
+# define rmdir _rmdir
+# endif
+_GL_CXXALIAS_MDA (rmdir, int, (char const *name));
+# else
+_GL_CXXALIAS_SYS (rmdir, int, (char const *name));
+# endif
+_GL_CXXALIASWARN (rmdir);
#endif
@@ -1377,7 +2016,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
@@ -1401,6 +2040,31 @@ _GL_WARN_ON_USE (sleep, "sleep is unportable - "
#endif
+#if @GNULIB_MDA_SWAB@
+/* On native Windows, map 'swab' to '_swab', so that -loldnames is not
+ required. In C++ with GNULIB_NAMESPACE, avoid differences between
+ platforms by defining GNULIB_NAMESPACE::swab always. */
+# if defined _WIN32 && !defined __CYGWIN__
+# if !(defined __cplusplus && defined GNULIB_NAMESPACE)
+# undef swab
+# define swab _swab
+# endif
+/* Need to cast, because in old mingw the arguments are
+ (const char *from, char *to, size_t n). */
+_GL_CXXALIAS_MDA_CAST (swab, void, (char *from, char *to, int n));
+# else
+# if defined __hpux /* HP-UX */
+_GL_CXXALIAS_SYS (swab, void, (const char *from, char *to, int n));
+# elif defined __sun && !defined _XPG4 /* Solaris */
+_GL_CXXALIAS_SYS (swab, void, (const char *from, char *to, ssize_t n));
+# else
+_GL_CXXALIAS_SYS (swab, void, (const void *from, void *to, ssize_t n));
+# endif
+# endif
+_GL_CXXALIASWARN (swab);
+#endif
+
+
#if @GNULIB_SYMLINK@
# if @REPLACE_SYMLINK@
# if !(defined __cplusplus && defined GNULIB_NAMESPACE)
@@ -1461,7 +2125,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
@@ -1471,7 +2135,7 @@ _GL_FUNCDECL_RPL (truncate, int, (const char *filename, off_t length)
_GL_ARG_NONNULL ((1)));
_GL_CXXALIAS_RPL (truncate, int, (const char *filename, off_t length));
# else
-# if !@HAVE_TRUNCATE@
+# if !@HAVE_DECL_TRUNCATE@
_GL_FUNCDECL_SYS (truncate, int, (const char *filename, off_t length)
_GL_ARG_NONNULL ((1)));
# endif
@@ -1525,6 +2189,12 @@ _GL_WARN_ON_USE (ttyname_r, "ttyname_r is not portable - "
# endif
_GL_FUNCDECL_RPL (unlink, int, (char const *file) _GL_ARG_NONNULL ((1)));
_GL_CXXALIAS_RPL (unlink, int, (char const *file));
+# elif defined _WIN32 && !defined __CYGWIN__
+# if !(defined __cplusplus && defined GNULIB_NAMESPACE)
+# undef unlink
+# define unlink _unlink
+# endif
+_GL_CXXALIAS_MDA (unlink, int, (char const *file));
# else
_GL_CXXALIAS_SYS (unlink, int, (char const *file));
# endif
@@ -1535,6 +2205,20 @@ _GL_CXXALIASWARN (unlink);
_GL_WARN_ON_USE (unlink, "unlink is not portable - "
"use gnulib module unlink for portability");
# endif
+#elif @GNULIB_MDA_UNLINK@
+/* On native Windows, map 'unlink' to '_unlink', so that -loldnames is not
+ required. In C++ with GNULIB_NAMESPACE, avoid differences between
+ platforms by defining GNULIB_NAMESPACE::unlink always. */
+# if defined _WIN32 && !defined __CYGWIN__
+# if !(defined __cplusplus && defined GNULIB_NAMESPACE)
+# undef unlink
+# define unlink _unlink
+# endif
+_GL_CXXALIAS_MDA (unlink, int, (char const *file));
+# else
+_GL_CXXALIAS_SYS (unlink, int, (char const *file));
+# endif
+_GL_CXXALIASWARN (unlink);
#endif
@@ -1559,7 +2243,7 @@ _GL_CXXALIASWARN (unlinkat);
# undef unlinkat
# if HAVE_RAW_DECL_UNLINKAT
_GL_WARN_ON_USE (unlinkat, "unlinkat is not portable - "
- "use gnulib module openat for portability");
+ "use gnulib module unlinkat for portability");
# endif
#endif
@@ -1568,7 +2252,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
@@ -1580,7 +2264,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
@@ -1595,7 +2281,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
@@ -1604,11 +2290,32 @@ _GL_WARN_ON_USE (usleep, "usleep is unportable - "
_GL_FUNCDECL_RPL (write, ssize_t, (int fd, const void *buf, size_t count)
_GL_ARG_NONNULL ((2)));
_GL_CXXALIAS_RPL (write, ssize_t, (int fd, const void *buf, size_t count));
+# elif defined _WIN32 && !defined __CYGWIN__
+# if !(defined __cplusplus && defined GNULIB_NAMESPACE)
+# undef write
+# define write _write
+# endif
+_GL_CXXALIAS_MDA (write, ssize_t, (int fd, const void *buf, size_t count));
+# else
+_GL_CXXALIAS_SYS (write, ssize_t, (int fd, const void *buf, size_t count));
+# endif
+_GL_CXXALIASWARN (write);
+#elif @GNULIB_MDA_WRITE@
+/* On native Windows, map 'write' to '_write', so that -loldnames is not
+ required. In C++ with GNULIB_NAMESPACE, avoid differences between
+ platforms by defining GNULIB_NAMESPACE::write always. */
+# if defined _WIN32 && !defined __CYGWIN__
+# if !(defined __cplusplus && defined GNULIB_NAMESPACE)
+# undef write
+# define write _write
+# endif
+# ifdef __MINGW32__
+_GL_CXXALIAS_MDA (write, int, (int fd, const void *buf, unsigned int count));
+# else
+_GL_CXXALIAS_MDA (write, ssize_t, (int fd, const void *buf, unsigned int count));
+# endif
# else
-/* Need to cast, because on mingw, the third parameter is
- unsigned int count
- and the return type is 'int'. */
-_GL_CXXALIAS_SYS_CAST (write, ssize_t, (int fd, const void *buf, size_t count));
+_GL_CXXALIAS_SYS (write, ssize_t, (int fd, const void *buf, size_t count));
# endif
_GL_CXXALIASWARN (write);
#endif
diff --git a/lib/unlocked-io.h b/lib/unlocked-io.h
index be5d2b5d847..7461d740959 100644
--- a/lib/unlocked-io.h
+++ b/lib/unlocked-io.h
@@ -1,10 +1,10 @@
/* Prefer faster, non-thread-safe stdio functions if available.
- Copyright (C) 2001-2004, 2009-2017 Free Software Foundation, Inc.
+ Copyright (C) 2001-2004, 2009-2022 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
+ 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,
@@ -33,91 +33,91 @@
# include <stdio.h>
-# if HAVE_DECL_CLEARERR_UNLOCKED
+# if HAVE_DECL_CLEARERR_UNLOCKED || defined clearerr_unlocked
# undef clearerr
# define clearerr(x) clearerr_unlocked (x)
# else
# define clearerr_unlocked(x) clearerr (x)
# endif
-# if HAVE_DECL_FEOF_UNLOCKED
+# if HAVE_DECL_FEOF_UNLOCKED || defined feof_unlocked
# undef feof
# define feof(x) feof_unlocked (x)
# else
# define feof_unlocked(x) feof (x)
# endif
-# if HAVE_DECL_FERROR_UNLOCKED
+# if HAVE_DECL_FERROR_UNLOCKED || defined ferror_unlocked
# undef ferror
# define ferror(x) ferror_unlocked (x)
# else
# define ferror_unlocked(x) ferror (x)
# endif
-# if HAVE_DECL_FFLUSH_UNLOCKED
+# if HAVE_DECL_FFLUSH_UNLOCKED || defined fflush_unlocked
# undef fflush
# define fflush(x) fflush_unlocked (x)
# else
# define fflush_unlocked(x) fflush (x)
# endif
-# if HAVE_DECL_FGETS_UNLOCKED
+# if HAVE_DECL_FGETS_UNLOCKED || defined fgets_unlocked
# undef fgets
# define fgets(x,y,z) fgets_unlocked (x,y,z)
# else
# define fgets_unlocked(x,y,z) fgets (x,y,z)
# endif
-# if HAVE_DECL_FPUTC_UNLOCKED
+# if HAVE_DECL_FPUTC_UNLOCKED || defined fputc_unlocked
# undef fputc
# define fputc(x,y) fputc_unlocked (x,y)
# else
# define fputc_unlocked(x,y) fputc (x,y)
# endif
-# if HAVE_DECL_FPUTS_UNLOCKED
+# if HAVE_DECL_FPUTS_UNLOCKED || defined fputs_unlocked
# undef fputs
# define fputs(x,y) fputs_unlocked (x,y)
# else
# define fputs_unlocked(x,y) fputs (x,y)
# endif
-# if HAVE_DECL_FREAD_UNLOCKED
+# if HAVE_DECL_FREAD_UNLOCKED || defined fread_unlocked
# undef fread
# define fread(w,x,y,z) fread_unlocked (w,x,y,z)
# else
# define fread_unlocked(w,x,y,z) fread (w,x,y,z)
# endif
-# if HAVE_DECL_FWRITE_UNLOCKED
+# if HAVE_DECL_FWRITE_UNLOCKED || defined fwrite_unlocked
# undef fwrite
# define fwrite(w,x,y,z) fwrite_unlocked (w,x,y,z)
# else
# define fwrite_unlocked(w,x,y,z) fwrite (w,x,y,z)
# endif
-# if HAVE_DECL_GETC_UNLOCKED
+# if HAVE_DECL_GETC_UNLOCKED || defined get_unlocked
# undef getc
# define getc(x) getc_unlocked (x)
# else
# define getc_unlocked(x) getc (x)
# endif
-# if HAVE_DECL_GETCHAR_UNLOCKED
+# if HAVE_DECL_GETCHAR_UNLOCKED || defined getchar_unlocked
# undef getchar
# define getchar() getchar_unlocked ()
# else
# define getchar_unlocked() getchar ()
# endif
-# if HAVE_DECL_PUTC_UNLOCKED
+# if HAVE_DECL_PUTC_UNLOCKED || defined putc_unlocked
# undef putc
# define putc(x,y) putc_unlocked (x,y)
# else
# define putc_unlocked(x,y) putc (x,y)
# endif
-# if HAVE_DECL_PUTCHAR_UNLOCKED
+# if HAVE_DECL_PUTCHAR_UNLOCKED || defined putchar_unlocked
# undef putchar
# define putchar(x) putchar_unlocked (x)
# else
diff --git a/lib/utimens.c b/lib/utimens.c
index 55545e8ce9b..2fa12518507 100644
--- a/lib/utimens.c
+++ b/lib/utimens.c
@@ -1,18 +1,18 @@
/* Set file access and modification times.
- Copyright (C) 2003-2017 Free Software Foundation, Inc.
+ Copyright (C) 2003-2022 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 any
- later version.
+ This file is free software: you can redistribute it and/or modify
+ it under the terms of the GNU Lesser 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,
+ This file 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.
+ GNU Lesser General Public License for more details.
- You should have received a copy of the GNU General Public License
+ You should have received a copy of the GNU Lesser General Public License
along with this program. If not, see <https://www.gnu.org/licenses/>. */
/* Written by Paul Eggert. */
@@ -27,6 +27,7 @@
#include <errno.h>
#include <fcntl.h>
#include <stdbool.h>
+#include <string.h>
#include <sys/stat.h>
#include <sys/time.h>
#include <unistd.h>
@@ -39,8 +40,7 @@
GNU Emacs, which arranges for this in some other way and which
defines WIN32_LEAN_AND_MEAN itself. */
-#if ((defined _WIN32 || defined __WIN32__) \
- && ! defined __CYGWIN__ && ! defined EMACS_CONFIGURATION)
+#if defined _WIN32 && ! defined __CYGWIN__ && ! defined EMACS_CONFIGURATION
# define USE_SETFILETIME
# define WIN32_LEAN_AND_MEAN
# include <windows.h>
@@ -53,7 +53,9 @@
/* Avoid recursion with rpl_futimens or rpl_utimensat. */
#undef futimens
-#undef utimensat
+#if !HAVE_NEARLY_WORKING_UTIMENSAT
+# undef utimensat
+#endif
/* Solaris 9 mistakenly succeeds when given a non-directory with a
trailing slash. Force the use of rpl_stat for a fix. */
@@ -92,11 +94,11 @@ validate_timespec (struct timespec timespec[2])
if ((timespec[0].tv_nsec != UTIME_NOW
&& timespec[0].tv_nsec != UTIME_OMIT
&& ! (0 <= timespec[0].tv_nsec
- && timespec[0].tv_nsec < TIMESPEC_RESOLUTION))
+ && timespec[0].tv_nsec < TIMESPEC_HZ))
|| (timespec[1].tv_nsec != UTIME_NOW
&& timespec[1].tv_nsec != UTIME_OMIT
&& ! (0 <= timespec[1].tv_nsec
- && timespec[1].tv_nsec < TIMESPEC_RESOLUTION)))
+ && timespec[1].tv_nsec < TIMESPEC_HZ)))
{
errno = EINVAL;
return -1;
@@ -124,14 +126,14 @@ validate_timespec (struct timespec timespec[2])
return result + (utime_omit_count == 1);
}
-/* Normalize any UTIME_NOW or UTIME_OMIT values in *TS, using stat
- buffer STATBUF to obtain the current timestamps of the file. If
+/* Normalize any UTIME_NOW or UTIME_OMIT values in (*TS)[0] and (*TS)[1],
+ using STATBUF to obtain the current timestamps of the file. If
both times are UTIME_NOW, set *TS to NULL (as this can avoid some
permissions issues). If both times are UTIME_OMIT, return true
(nothing further beyond the prior collection of STATBUF is
necessary); otherwise return false. */
static bool
-update_timespec (struct stat const *statbuf, struct timespec *ts[2])
+update_timespec (struct stat const *statbuf, struct timespec **ts)
{
struct timespec *timespec = *ts;
if (timespec[0].tv_nsec == UTIME_OMIT
@@ -247,6 +249,20 @@ fdutimens (int fd, char const *file, struct timespec const timespec[2])
# if HAVE_UTIMENSAT
if (fd < 0)
{
+# if defined __APPLE__ && defined __MACH__
+ size_t len = strlen (file);
+ if (len > 0 && file[len - 1] == '/')
+ {
+ struct stat statbuf;
+ if (stat (file, &statbuf) < 0)
+ return -1;
+ if (!S_ISDIR (statbuf.st_mode))
+ {
+ errno = ENOTDIR;
+ return -1;
+ }
+ }
+# endif
result = utimensat (AT_FDCWD, file, ts, 0);
# ifdef __linux__
/* Work around a kernel bug:
@@ -289,8 +305,8 @@ fdutimens (int fd, char const *file, struct timespec const timespec[2])
#ifdef USE_SETFILETIME
/* On native Windows, use SetFileTime(). See
- <https://msdn.microsoft.com/en-us/library/ms724933.aspx>
- <https://msdn.microsoft.com/en-us/library/ms724284.aspx> */
+ <https://docs.microsoft.com/en-us/windows/desktop/api/fileapi/nf-fileapi-setfiletime>
+ <https://docs.microsoft.com/en-us/windows/desktop/api/minwinbase/ns-minwinbase-filetime> */
if (0 <= fd)
{
HANDLE handle;
@@ -308,10 +324,10 @@ fdutimens (int fd, char const *file, struct timespec const timespec[2])
if (ts == NULL || ts[0].tv_nsec == UTIME_NOW || ts[1].tv_nsec == UTIME_NOW)
{
/* GetSystemTimeAsFileTime
- <https://msdn.microsoft.com/en-us/library/ms724397.aspx>.
+ <https://docs.microsoft.com/en-us/windows/desktop/api/sysinfoapi/nf-sysinfoapi-getsystemtimeasfiletime>.
It would be overkill to use
GetSystemTimePreciseAsFileTime
- <https://msdn.microsoft.com/en-us/library/hh706895.aspx>. */
+ <https://docs.microsoft.com/en-us/windows/desktop/api/sysinfoapi/nf-sysinfoapi-getsystemtimepreciseasfiletime>. */
GetSystemTimeAsFileTime (&current_time);
}
diff --git a/lib/utimens.h b/lib/utimens.h
index f1dd9884dc1..2ccc06e5ed6 100644
--- a/lib/utimens.h
+++ b/lib/utimens.h
@@ -1,18 +1,18 @@
/* Set file access and modification times.
- Copyright 2012-2017 Free Software Foundation, Inc.
+ Copyright 2012-2022 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 any
- later version.
+ This file is free software: you can redistribute it and/or modify
+ it under the terms of the GNU Lesser 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,
+ This file 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.
+ GNU Lesser General Public License for more details.
- You should have received a copy of the GNU General Public License
+ You should have received a copy of the GNU Lesser General Public License
along with this program. If not, see <https://www.gnu.org/licenses/>. */
/* Written by Paul Eggert. */
diff --git a/lib/utimensat.c b/lib/utimensat.c
new file mode 100644
index 00000000000..f81b0c790ef
--- /dev/null
+++ b/lib/utimensat.c
@@ -0,0 +1,217 @@
+/* Set the access and modification time of a file relative to directory fd.
+ Copyright (C) 2009-2022 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 Eric Blake */
+
+#include <config.h>
+
+/* Specification. */
+#include <sys/stat.h>
+
+#include <errno.h>
+#include <fcntl.h>
+#include <stdlib.h>
+#include <string.h>
+#include <sys/stat.h>
+
+#include "stat-time.h"
+#include "timespec.h"
+#include "utimens.h"
+
+#if HAVE_NEARLY_WORKING_UTIMENSAT
+
+/* Use the original utimensat(), but correct the trailing slash handling. */
+int
+rpl_utimensat (int fd, char const *file, struct timespec const times[2],
+ int flag)
+# undef utimensat
+{
+ size_t len = strlen (file);
+ if (len && file[len - 1] == '/')
+ {
+ struct stat st;
+ if (fstatat (fd, file, &st, flag & AT_SYMLINK_NOFOLLOW) < 0)
+ return -1;
+ if (!S_ISDIR (st.st_mode))
+ {
+ errno = ENOTDIR;
+ return -1;
+ }
+ }
+
+ return utimensat (fd, file, times, flag);
+}
+
+#else
+
+# if HAVE_UTIMENSAT
+
+/* If we have a native utimensat, but are compiling this file, then
+ utimensat was defined to rpl_utimensat by our replacement
+ sys/stat.h. We assume the native version might fail with ENOSYS,
+ or succeed without properly affecting ctime (as is the case when
+ using newer glibc but older Linux kernel). In this scenario,
+ rpl_utimensat checks whether the native version is usable, and
+ local_utimensat provides the fallback manipulation. */
+
+static int local_utimensat (int, char const *, struct timespec const[2], int);
+# define AT_FUNC_NAME local_utimensat
+
+/* Like utimensat, but work around native bugs. */
+
+int
+rpl_utimensat (int fd, char const *file, struct timespec const times[2],
+ int flag)
+# undef utimensat
+{
+# if defined __linux__ || defined __sun
+ struct timespec ts[2];
+# endif
+
+ /* See comments in utimens.c for details. */
+ static int utimensat_works_really; /* 0 = unknown, 1 = yes, -1 = no. */
+ if (0 <= utimensat_works_really)
+ {
+ int result;
+# if defined __linux__ || defined __sun
+ struct stat st;
+ /* As recently as Linux kernel 2.6.32 (Dec 2009), several file
+ systems (xfs, ntfs-3g) have bugs with a single UTIME_OMIT,
+ but work if both times are either explicitly specified or
+ UTIME_NOW. Work around it with a preparatory [l]stat prior
+ to calling utimensat; fortunately, there is not much timing
+ impact due to the extra syscall even on file systems where
+ UTIME_OMIT would have worked.
+
+ The same bug occurs in Solaris 11.1 (Apr 2013).
+
+ FIXME: Simplify this in 2024, when these file system bugs are
+ no longer common on Gnulib target platforms. */
+ if (times && (times[0].tv_nsec == UTIME_OMIT
+ || times[1].tv_nsec == UTIME_OMIT))
+ {
+ if (fstatat (fd, file, &st, flag))
+ return -1;
+ if (times[0].tv_nsec == UTIME_OMIT && times[1].tv_nsec == UTIME_OMIT)
+ return 0;
+ if (times[0].tv_nsec == UTIME_OMIT)
+ ts[0] = get_stat_atime (&st);
+ else
+ ts[0] = times[0];
+ if (times[1].tv_nsec == UTIME_OMIT)
+ ts[1] = get_stat_mtime (&st);
+ else
+ ts[1] = times[1];
+ times = ts;
+ }
+# ifdef __hppa__
+ /* Linux kernel 2.6.22.19 on hppa does not reject invalid tv_nsec
+ values. */
+ else if (times
+ && ((times[0].tv_nsec != UTIME_NOW
+ && ! (0 <= times[0].tv_nsec
+ && times[0].tv_nsec < TIMESPEC_HZ))
+ || (times[1].tv_nsec != UTIME_NOW
+ && ! (0 <= times[1].tv_nsec
+ && times[1].tv_nsec < TIMESPEC_HZ))))
+ {
+ errno = EINVAL;
+ return -1;
+ }
+# endif
+# endif
+# if defined __APPLE__ && defined __MACH__
+ /* macOS 10.13 does not reject invalid tv_nsec values either. */
+ if (times
+ && ((times[0].tv_nsec != UTIME_OMIT
+ && times[0].tv_nsec != UTIME_NOW
+ && ! (0 <= times[0].tv_nsec
+ && times[0].tv_nsec < TIMESPEC_HZ))
+ || (times[1].tv_nsec != UTIME_OMIT
+ && times[1].tv_nsec != UTIME_NOW
+ && ! (0 <= times[1].tv_nsec
+ && times[1].tv_nsec < TIMESPEC_HZ))))
+ {
+ errno = EINVAL;
+ return -1;
+ }
+ size_t len = strlen (file);
+ if (len > 0 && file[len - 1] == '/')
+ {
+ struct stat statbuf;
+ if (fstatat (fd, file, &statbuf, 0) < 0)
+ return -1;
+ if (!S_ISDIR (statbuf.st_mode))
+ {
+ errno = ENOTDIR;
+ return -1;
+ }
+ }
+# endif
+ result = utimensat (fd, file, times, flag);
+ /* Linux kernel 2.6.25 has a bug where it returns EINVAL for
+ UTIME_NOW or UTIME_OMIT with non-zero tv_sec, which
+ local_utimensat works around. Meanwhile, EINVAL for a bad
+ flag is indeterminate whether the native utimensat works, but
+ local_utimensat will also reject it. */
+ if (result == -1 && errno == EINVAL && (flag & ~AT_SYMLINK_NOFOLLOW))
+ return result;
+ if (result == 0 || (errno != ENOSYS && errno != EINVAL))
+ {
+ utimensat_works_really = 1;
+ return result;
+ }
+ }
+ /* No point in trying openat/futimens, since on Linux, futimens is
+ implemented with the same syscall as utimensat. Only avoid the
+ native utimensat due to an ENOSYS failure; an EINVAL error was
+ data-dependent, and the next caller may pass valid data. */
+ if (0 <= utimensat_works_really && errno == ENOSYS)
+ utimensat_works_really = -1;
+ return local_utimensat (fd, file, times, flag);
+}
+
+# else /* !HAVE_UTIMENSAT */
+
+# define AT_FUNC_NAME utimensat
+
+# endif /* !HAVE_UTIMENSAT */
+
+/* Set the access and modification timestamps of FILE to be
+ TIMESPEC[0] and TIMESPEC[1], respectively; relative to directory
+ FD. If flag is AT_SYMLINK_NOFOLLOW, change the times of a symlink,
+ or fail with ENOSYS if not possible. If TIMESPEC is null, set the
+ timestamps to the current time. If possible, do it without
+ changing the working directory. Otherwise, resort to using
+ save_cwd/fchdir, then utimens/restore_cwd. If either the save_cwd
+ or the restore_cwd fails, then give a diagnostic and exit nonzero.
+ Return 0 on success, -1 (setting errno) on failure. */
+
+/* AT_FUNC_NAME is now utimensat or local_utimensat. */
+# define AT_FUNC_F1 lutimens
+# define AT_FUNC_F2 utimens
+# define AT_FUNC_USE_F1_COND AT_SYMLINK_NOFOLLOW
+# define AT_FUNC_POST_FILE_PARAM_DECLS , struct timespec const ts[2], int flag
+# define AT_FUNC_POST_FILE_ARGS , ts
+# include "at-func.c"
+# undef AT_FUNC_NAME
+# undef AT_FUNC_F1
+# undef AT_FUNC_F2
+# undef AT_FUNC_USE_F1_COND
+# undef AT_FUNC_POST_FILE_PARAM_DECLS
+# undef AT_FUNC_POST_FILE_ARGS
+
+#endif /* !HAVE_NEARLY_WORKING_UTIMENSAT */
diff --git a/lib/verify.h b/lib/verify.h
index e0b48613374..47b6ee661b3 100644
--- a/lib/verify.h
+++ b/lib/verify.h
@@ -1,18 +1,18 @@
/* Compile-time assert-like macros.
- Copyright (C) 2005-2006, 2009-2017 Free Software Foundation, Inc.
+ Copyright (C) 2005-2006, 2009-2022 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 file is free software: you can redistribute it and/or modify
+ it under the terms of the GNU Lesser General Public License as
+ published by the Free Software Foundation; either version 2.1 of the
+ License, or (at your option) any later version.
- This program is distributed in the hope that it will be useful,
+ This file 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.
+ GNU Lesser General Public License for more details.
- You should have received a copy of the GNU General Public License
+ You should have received a copy of the GNU Lesser General Public License
along with this program. If not, see <https://www.gnu.org/licenses/>. */
/* Written by Paul Eggert, Bruno Haible, and Jim Meyering. */
@@ -21,31 +21,32 @@
#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 by clang 4+.
- 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. This is supported by GCC 9.1+.
- 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__) || 5 <= __clang_major__)))
+# define _GL_HAVE__STATIC_ASSERT 1
+# endif
+# if (202000L <= __STDC_VERSION__ \
+ || (!defined __STRICT_ANSI__ && 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 +144,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 +198,66 @@ 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 200410 <= __cpp_static_assert
+# define _GL_VERIFY(R, DIAGNOSTIC, ...) static_assert (R, DIAGNOSTIC)
+#elif 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)]
+# if 4 < __GNUC__ + (6 <= __GNUC_MINOR__)
+# pragma GCC diagnostic ignored "-Wnested-externs"
+# endif
#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 __cpp_static_assert < 201411 && !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,37 +265,55 @@ 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 (...)")
+# define verify(R) _GL_VERIFY (R, "verify (" #R ")", -)
#endif
-#ifndef __has_builtin
-# define __has_builtin(x) 0
-#endif
+/* Assume that R always holds. Behavior is undefined if R is false,
+ fails to evaluate, or has side effects.
+
+ 'assume (R)' is a directive from the programmer telling the
+ compiler that R is true so the compiler needn't generate code to
+ test R. This is why 'assume' is in verify.h: it's related to
+ static checking (in this case, static checking done by the
+ programmer), not dynamic checking.
+
+ 'assume (R)' can affect compilation of all the code, not just code
+ that happens to be executed after the assume (R) is "executed".
+ For example, if the code mistakenly does 'assert (R); assume (R);'
+ the compiler is entitled to optimize away the 'assert (R)'.
-/* 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. */
+ 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__))
+ Avoid Clang's __builtin_assume, as it breaks GNU Emacs master
+ as of 2020-08-23T21:09:49Z!eggert@cs.ucla.edu; see
+ <https://bugs.gnu.org/43152#71>. It's not known whether this breakage
+ is a Clang bug or an Emacs bug; play it safe for now. */
+
+#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 202311L <= __STDC_VERSION__
+# include <stddef.h>
+# define assume(R) ((R) ? (void) 0 : unreachable ())
+#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. */
+ if 'assume' silences warnings with GCC 3.4 through GCC 4.4.7 (2012). */
# define assume(R) ((R) ? (void) 0 : __builtin_trap ())
#else
-# define assume(R) ((void) (0 && (R)))
+ /* Some older tools grok NOTREACHED, e.g., Oracle Studio 12.6 (2017). */
+# define assume(R) ((R) ? (void) 0 : /*NOTREACHED*/ (void) 0)
#endif
/* @assert.h omit end@ */
diff --git a/lib/vla.h b/lib/vla.h
index 59de9a6bcd6..ce02428f53a 100644
--- a/lib/vla.h
+++ b/lib/vla.h
@@ -1,10 +1,10 @@
/* vla.h - variable length arrays
- Copyright 2014-2017 Free Software Foundation, Inc.
+ Copyright 2014-2022 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
+ 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,
@@ -17,6 +17,20 @@
Written by Paul Eggert. */
+/* The VLA_ELEMS macro does not allocate variable-length arrays (VLAs),
+ so it does not have the security or performance issues commonly
+ associated with VLAs. VLA_ELEMS is for exploiting a C11 feature
+ where a function can start like this:
+
+ double scan_array (int n, double v[static n])
+
+ to require a caller to pass a vector V with at least N elements;
+ this allows better static checking and performance in some cases.
+ In C11 this feature means that V is a VLA, so the feature is
+ supported only if __STDC_NO_VLA__ is defined, and for compatibility
+ to platforms that do not support VLAs, VLA_ELEMS (n) expands to
+ nothing when __STDC_NO_VLA__ is not defined. */
+
/* A function's argument must point to an array with at least N elements.
Example: 'int main (int argc, char *argv[VLA_ELEMS (argc)]);'. */
@@ -25,3 +39,15 @@
#else
# define VLA_ELEMS(n) static n
#endif
+
+/* Although C99 requires support for variable-length arrays (VLAs),
+ some C compilers never supported VLAs and VLAs are optional in C11.
+ VLAs are controversial because their allocation may be unintended
+ or awkward to support, and large VLAs might cause security or
+ performance problems. GCC can diagnose the use of VLAs via the
+ -Wvla and -Wvla-larger-than warnings options, and defining the
+ macro GNULIB_NO_VLA disables the allocation of VLAs in Gnulib code.
+
+ The VLA_ELEMS macro is unaffected by GNULIB_NO_VLA, since it does
+ not allocate VLAs. Programs that use VLA_ELEMS should be compiled
+ with 'gcc -Wvla-larger-than' instead of with 'gcc -Wvla'. */
diff --git a/lib/warn-on-use.h b/lib/warn-on-use.h
index cae8c3eec5c..94f5b9201ed 100644
--- a/lib/warn-on-use.h
+++ b/lib/warn-on-use.h
@@ -1,17 +1,17 @@
/* A C macro for emitting warnings if a function is used.
- Copyright (C) 2010-2017 Free Software Foundation, Inc.
+ Copyright (C) 2010-2022 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
+ under the terms of the GNU Lesser General Public License as published
+ by the Free Software Foundation; either version 2 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.
+ Lesser General Public License for more details.
- You should have received a copy of the GNU General Public License
+ You should have received a copy of the GNU Lesser General Public License
along with this program. If not, see <https://www.gnu.org/licenses/>. */
/* _GL_WARN_ON_USE (function, "literal string") issues a declaration
@@ -20,23 +20,32 @@
supported by the compiler. If the compiler does not support this
feature, the macro expands to an unused extern declaration.
- This macro is useful for marking a function as a potential
+ _GL_WARN_ON_USE_ATTRIBUTE ("literal string") expands to the
+ attribute used in _GL_WARN_ON_USE. If the compiler does not support
+ this feature, it expands to empty.
+
+ These macros are useful for marking a function as a potential
portability trap, with the intent that "literal string" include
instructions on the replacement function that should be used
- instead. However, one of the reasons that a function is a
- portability trap is if it has the wrong signature. Declaring
- FUNCTION with a different signature in C is a compilation error, so
- this macro must use the same type as any existing declaration so
- that programs that avoid the problematic FUNCTION do not fail to
- compile merely because they included a header that poisoned the
- function. But this implies that _GL_WARN_ON_USE is only safe to
- use if FUNCTION is known to already have a declaration. Use of
- this macro implies that there must not be any other macro hiding
- the declaration of FUNCTION; but undefining FUNCTION first is part
- of the poisoning process anyway (although for symbols that are
- provided only via a macro, the result is a compilation error rather
- than a warning containing "literal string"). Also note that in
- C++, it is only safe to use if FUNCTION has no overloads.
+ instead.
+ _GL_WARN_ON_USE is for functions with 'extern' linkage.
+ _GL_WARN_ON_USE_ATTRIBUTE is for functions with 'static' or 'inline'
+ linkage.
+
+ However, one of the reasons that a function is a portability trap is
+ if it has the wrong signature. Declaring FUNCTION with a different
+ signature in C is a compilation error, so this macro must use the
+ same type as any existing declaration so that programs that avoid
+ the problematic FUNCTION do not fail to compile merely because they
+ included a header that poisoned the function. But this implies that
+ _GL_WARN_ON_USE is only safe to use if FUNCTION is known to already
+ have a declaration. Use of this macro implies that there must not
+ be any other macro hiding the declaration of FUNCTION; but
+ undefining FUNCTION first is part of the poisoning process anyway
+ (although for symbols that are provided only via a macro, the result
+ is a compilation error rather than a warning containing
+ "literal string"). Also note that in C++, it is only safe to use if
+ FUNCTION has no overloads.
For an example, it is possible to poison 'getline' by:
- adding a call to gl_WARN_ON_USE_PREPARE([[#include <stdio.h>]],
@@ -54,47 +63,78 @@
(less common usage, like &environ, will cause a compilation error
rather than issue the nice warning, but the end result of informing
the developer about their portability problem is still achieved):
- #if HAVE_RAW_DECL_ENVIRON
- static char ***rpl_environ (void) { return &environ; }
- _GL_WARN_ON_USE (rpl_environ, "environ is not always properly declared");
- # undef environ
- # define environ (*rpl_environ ())
- #endif
+ #if HAVE_RAW_DECL_ENVIRON
+ static char ***
+ rpl_environ (void) { return &environ; }
+ _GL_WARN_ON_USE (rpl_environ, "environ is not always properly declared");
+ # undef environ
+ # define environ (*rpl_environ ())
+ #endif
+ or better (avoiding contradictory use of 'static' and 'extern'):
+ #if HAVE_RAW_DECL_ENVIRON
+ static char ***
+ _GL_WARN_ON_USE_ATTRIBUTE ("environ is not always properly declared")
+ rpl_environ (void) { return &environ; }
+ # undef environ
+ # define environ (*rpl_environ ())
+ #endif
*/
#ifndef _GL_WARN_ON_USE
# if 4 < __GNUC__ || (__GNUC__ == 4 && 3 <= __GNUC_MINOR__)
/* A compiler attribute is available in gcc versions 4.3.0 and later. */
# define _GL_WARN_ON_USE(function, message) \
-extern __typeof__ (function) function __attribute__ ((__warning__ (message)))
+_GL_WARN_EXTERN_C __typeof__ (function) function __attribute__ ((__warning__ (message)))
+# define _GL_WARN_ON_USE_ATTRIBUTE(message) \
+ __attribute__ ((__warning__ (message)))
+# elif __clang_major__ >= 4
+/* Another compiler attribute is available in clang. */
+# define _GL_WARN_ON_USE(function, message) \
+_GL_WARN_EXTERN_C __typeof__ (function) function \
+ __attribute__ ((__diagnose_if__ (1, message, "warning")))
+# define _GL_WARN_ON_USE_ATTRIBUTE(message) \
+ __attribute__ ((__diagnose_if__ (1, message, "warning")))
# elif __GNUC__ >= 3 && GNULIB_STRICT_CHECKING
/* Verify the existence of the function. */
# define _GL_WARN_ON_USE(function, message) \
-extern __typeof__ (function) function
+_GL_WARN_EXTERN_C __typeof__ (function) function
+# define _GL_WARN_ON_USE_ATTRIBUTE(message)
# else /* Unsupported. */
# define _GL_WARN_ON_USE(function, message) \
_GL_WARN_EXTERN_C int _gl_warn_on_use
+# define _GL_WARN_ON_USE_ATTRIBUTE(message)
# endif
#endif
-/* _GL_WARN_ON_USE_CXX (function, rettype, parameters_and_attributes, "string")
- is like _GL_WARN_ON_USE (function, "string"), except that the function is
- declared with the given prototype, consisting of return type, parameters,
- and attributes.
+/* _GL_WARN_ON_USE_CXX (function, rettype_gcc, rettype_clang, parameters_and_attributes, "message")
+ is like _GL_WARN_ON_USE (function, "message"), except that in C++ mode the
+ function is declared with the given prototype, consisting of return type,
+ parameters, and attributes.
This variant is useful for overloaded functions in C++. _GL_WARN_ON_USE does
not work in this case. */
#ifndef _GL_WARN_ON_USE_CXX
-# if 4 < __GNUC__ || (__GNUC__ == 4 && 3 <= __GNUC_MINOR__)
-# define _GL_WARN_ON_USE_CXX(function,rettype,parameters_and_attributes,msg) \
-extern rettype function parameters_and_attributes \
- __attribute__ ((__warning__ (msg)))
-# elif __GNUC__ >= 3 && GNULIB_STRICT_CHECKING
+# if !defined __cplusplus
+# define _GL_WARN_ON_USE_CXX(function,rettype_gcc,rettype_clang,parameters_and_attributes,msg) \
+ _GL_WARN_ON_USE (function, msg)
+# else
+# if 4 < __GNUC__ || (__GNUC__ == 4 && 3 <= __GNUC_MINOR__)
+/* A compiler attribute is available in gcc versions 4.3.0 and later. */
+# define _GL_WARN_ON_USE_CXX(function,rettype_gcc,rettype_clang,parameters_and_attributes,msg) \
+extern rettype_gcc function parameters_and_attributes \
+ __attribute__ ((__warning__ (msg)))
+# elif __clang_major__ >= 4
+/* Another compiler attribute is available in clang. */
+# define _GL_WARN_ON_USE_CXX(function,rettype_gcc,rettype_clang,parameters_and_attributes,msg) \
+extern rettype_clang function parameters_and_attributes \
+ __attribute__ ((__diagnose_if__ (1, msg, "warning")))
+# elif __GNUC__ >= 3 && GNULIB_STRICT_CHECKING
/* Verify the existence of the function. */
-# define _GL_WARN_ON_USE_CXX(function,rettype,parameters_and_attributes,msg) \
-extern rettype function parameters_and_attributes
-# else /* Unsupported. */
-# define _GL_WARN_ON_USE_CXX(function,rettype,parameters_and_attributes,msg) \
+# define _GL_WARN_ON_USE_CXX(function,rettype_gcc,rettype_clang,parameters_and_attributes,msg) \
+extern rettype_gcc function parameters_and_attributes
+# else /* Unsupported. */
+# define _GL_WARN_ON_USE_CXX(function,rettype_gcc,rettype_clang,parameters_and_attributes,msg) \
_GL_WARN_EXTERN_C int _gl_warn_on_use
+# endif
# endif
#endif
diff --git a/lib/xalloc-oversized.h b/lib/xalloc-oversized.h
index ae4fbc77f98..aefa6fd8049 100644
--- a/lib/xalloc-oversized.h
+++ b/lib/xalloc-oversized.h
@@ -1,18 +1,18 @@
/* xalloc-oversized.h -- memory allocation size checking
- Copyright (C) 1990-2000, 2003-2004, 2006-2017 Free Software Foundation, Inc.
+ Copyright (C) 1990-2000, 2003-2004, 2006-2022 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 file is free software: you can redistribute it and/or modify
+ it under the terms of the GNU Lesser General Public License as
+ published by the Free Software Foundation; either version 2.1 of the
+ License, or (at your option) any later version.
- This program is distributed in the hope that it will be useful,
+ This file 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.
+ GNU Lesser General Public License for more details.
- You should have received a copy of the GNU General Public License
+ You should have received a copy of the GNU Lesser General Public License
along with this program. If not, see <https://www.gnu.org/licenses/>. */
#ifndef XALLOC_OVERSIZED_H_
@@ -21,34 +21,39 @@
#include <stddef.h>
#include <stdint.h>
-/* True if N * S would overflow in a size_t calculation,
- or would generate a value larger than PTRDIFF_MAX.
+/* True if N * S does not fit into both ptrdiff_t and size_t.
+ N and S should be nonnegative and free of side effects.
This expands to a constant expression if N and S are both constants.
- By gnulib convention, SIZE_MAX represents overflow in size
+ By gnulib convention, SIZE_MAX represents overflow in size_t
calculations, so the conservative size_t-based dividend to use here
is SIZE_MAX - 1. */
#define __xalloc_oversized(n, s) \
- ((size_t) (PTRDIFF_MAX < SIZE_MAX ? PTRDIFF_MAX : SIZE_MAX - 1) / (s) < (n))
+ ((s) != 0 \
+ && ((size_t) (PTRDIFF_MAX < SIZE_MAX ? PTRDIFF_MAX : SIZE_MAX - 1) / (s) \
+ < (n)))
-#if PTRDIFF_MAX < SIZE_MAX
-typedef ptrdiff_t __xalloc_count_type;
-#else
-typedef size_t __xalloc_count_type;
-#endif
+/* Return 1 if and only if an array of N objects, each of size S,
+ cannot exist reliably because its total size in bytes would exceed
+ MIN (PTRDIFF_MAX, SIZE_MAX - 1).
+
+ N and S should be nonnegative and free of side effects.
-/* Return 1 if an array of N objects, each of size S, cannot exist
- reliably due to size or ptrdiff_t arithmetic overflow. S must be
- positive and N must be nonnegative. This is a macro, not a
- function, so that it works correctly even when SIZE_MAX < N. */
+ Warning: (xalloc_oversized (N, S) ? NULL : malloc (N * S)) can
+ misbehave if N and S are both narrower than ptrdiff_t and size_t,
+ and can be rewritten as (xalloc_oversized (N, S) ? NULL
+ : malloc (N * (size_t) S)).
-#if 7 <= __GNUC__
+ This is a macro, not a function, so that it works even if an
+ argument exceeds MAX (PTRDIFF_MAX, SIZE_MAX). */
+#if 7 <= __GNUC__ && !defined __clang__ && PTRDIFF_MAX < SIZE_MAX
# define xalloc_oversized(n, s) \
- __builtin_mul_overflow_p (n, s, (__xalloc_count_type) 1)
-#elif 5 <= __GNUC__ && !defined __ICC && !__STRICT_ANSI__
+ __builtin_mul_overflow_p (n, s, (ptrdiff_t) 1)
+#elif (5 <= __GNUC__ && !defined __ICC && !__STRICT_ANSI__ \
+ && PTRDIFF_MAX < SIZE_MAX)
# define xalloc_oversized(n, s) \
(__builtin_constant_p (n) && __builtin_constant_p (s) \
? __xalloc_oversized (n, s) \
- : ({ __xalloc_count_type __xalloc_count; \
+ : ({ ptrdiff_t __xalloc_count; \
__builtin_mul_overflow (n, s, &__xalloc_count); }))
/* Other compilers use integer division; this may be slower but is