diff options
Diffstat (limited to 'lib')
92 files changed, 7237 insertions, 1061 deletions
diff --git a/lib/_Noreturn.h b/lib/_Noreturn.h index 0d4b9c29e02..394ca3c2aa2 100644 --- a/lib/_Noreturn.h +++ b/lib/_Noreturn.h @@ -28,7 +28,10 @@ # define _Noreturn [[noreturn]] # elif ((!defined __cplusplus || defined __clang__) \ && (201112 <= (defined __STDC_VERSION__ ? __STDC_VERSION__ : 0) \ - || 4 < __GNUC__ + (7 <= __GNUC_MINOR__))) + || 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__) || 0x5110 <= __SUNPRO_C # define _Noreturn __attribute__ ((__noreturn__)) diff --git a/lib/alloca.in.h b/lib/alloca.in.h index 228f9a0a29b..5686b082bbe 100644 --- a/lib/alloca.in.h +++ b/lib/alloca.in.h @@ -1,7 +1,7 @@ /* Memory allocation on the stack. - Copyright (C) 1995, 1999, 2001-2004, 2006-2020 Free Software - Foundation, Inc. + Copyright (C) 1995, 1999, 2001-2004, 2006-2020 Free Software Foundation, + Inc. This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published @@ -35,13 +35,16 @@ */ #ifndef alloca + /* 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 # ifdef __GNUC__ - /* Some version of mingw have an <alloca.h> that causes trouble when - included after 'alloca' gets defined as a macro. As a workaround, include - this <alloca.h> first and define 'alloca' as a macro afterwards. */ -# if (defined _WIN32 && ! defined __CYGWIN__) && @HAVE_ALLOCA_H@ -# include_next <alloca.h> -# endif # define alloca __builtin_alloca # elif defined _AIX # define alloca __alloca diff --git a/lib/at-func.c b/lib/at-func.c index 4a1c909d38e..90022e05787 100644 --- a/lib/at-func.c +++ b/lib/at-func.c @@ -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..2836b99dad0 --- /dev/null +++ b/lib/attribute.h @@ -0,0 +1,215 @@ +/* ATTRIBUTE_* macros for using attributes in GCC and similar compilers + + Copyright 2020 Free Software Foundation, Inc. + + This program is free software: you can redistribute it and/or modify it + under the terms of the GNU General Public License as published + by the Free Software Foundation; either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see <https://www.gnu.org/licenses/>. */ + +/* Written by Paul Eggert. */ + +/* 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) + + +/* Attributes for variadic functions. */ + +/* The variadic function expects a trailing NULL argument. + ATTRIBUTE_SENTINEL () - The last argument is NULL. + 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 + +/* The function does not affect observable state, and always returns a value. + Compilers can omit duplicate calls with the same arguments if + observable state is not changed between calls. (This attribute is + looser than ATTRIBUTE_CONST.) */ +/* Applies to: functions. */ +#define ATTRIBUTE_PURE _GL_ATTRIBUTE_PURE + +/* The function neither depends on nor affects observable state, + and always returns a value. Compilers can omit duplicate calls with + the same arguments. (This attribute is stricter than ATTRIBUTE_PURE.) */ +/* Applies to: functions. */ +#define ATTRIBUTE_CONST _GL_ATTRIBUTE_CONST + +/* 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.h b/lib/binary-io.h index 64223f16fc2..477b4bf4dd3 100644 --- a/lib/binary-io.h +++ b/lib/binary-io.h @@ -1,6 +1,5 @@ /* Binary mode I/O. - Copyright (C) 2001, 2003, 2005, 2008-2020 Free Software Foundation, - Inc. + Copyright (C) 2001, 2003, 2005, 2008-2020 Free Software Foundation, Inc. This program is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by diff --git a/lib/c++defs.h b/lib/c++defs.h index 7a057633883..3e6aaabc9ce 100644 --- a/lib/c++defs.h +++ b/lib/c++defs.h @@ -301,9 +301,6 @@ _GL_WARN_ON_USE_CXX (func, 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.h b/lib/c-ctype.h index 42891bb1683..fbd11b34508 100644 --- a/lib/c-ctype.h +++ b/lib/c-ctype.h @@ -5,8 +5,7 @@ <ctype.h> functions' behaviour depends on the current locale set via setlocale. - Copyright (C) 2000-2003, 2006, 2008-2020 Free Software Foundation, - Inc. + Copyright (C) 2000-2003, 2006, 2008-2020 Free Software Foundation, Inc. This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by diff --git a/lib/c-strcasecmp.c b/lib/c-strcasecmp.c index f660bba73b5..951220f3e29 100644 --- a/lib/c-strcasecmp.c +++ b/lib/c-strcasecmp.c @@ -1,6 +1,5 @@ /* c-strcasecmp.c -- case insensitive string comparator in C locale - Copyright (C) 1998-1999, 2005-2006, 2009-2020 Free Software - Foundation, Inc. + Copyright (C) 1998-1999, 2005-2006, 2009-2020 Free Software Foundation, Inc. This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by diff --git a/lib/c-strncasecmp.c b/lib/c-strncasecmp.c index 89df6915840..9ad49191b7f 100644 --- a/lib/c-strncasecmp.c +++ b/lib/c-strncasecmp.c @@ -1,6 +1,5 @@ /* c-strncasecmp.c -- case insensitive string comparator in C locale - Copyright (C) 1998-1999, 2005-2006, 2009-2020 Free Software - Foundation, Inc. + Copyright (C) 1998-1999, 2005-2006, 2009-2020 Free Software Foundation, Inc. This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by diff --git a/lib/canonicalize-lgpl.c b/lib/canonicalize-lgpl.c index 7d3c710f10f..9f990988393 100644 --- a/lib/canonicalize-lgpl.c +++ b/lib/canonicalize-lgpl.c @@ -51,7 +51,7 @@ # define __realpath realpath # include "pathmax.h" # include "malloca.h" -# include "dosname.h" +# include "filename.h" # if HAVE_GETCWD # if IN_RELOCWRAPPER /* When building the relocatable program wrapper, use the system's getcwd diff --git a/lib/careadlinkat.c b/lib/careadlinkat.c index 197ce8de77f..1aa04363dac 100644 --- a/lib/careadlinkat.c +++ b/lib/careadlinkat.c @@ -1,7 +1,7 @@ /* Read symbolic links into a buffer without size limitation, relative to fd. - Copyright (C) 2001, 2003-2004, 2007, 2009-2020 Free Software - Foundation, Inc. + Copyright (C) 2001, 2003-2004, 2007, 2009-2020 Free Software Foundation, + Inc. This program is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by @@ -72,23 +72,38 @@ careadlinkat (int fd, char const *filename, SSIZE_MAX < SIZE_MAX ? (size_t) SSIZE_MAX + 1 : SIZE_MAX; char stack_buf[1024]; +#if (defined GCC_LINT || defined lint) && _GL_GNUC_PREREQ (10, 1) + /* Pacify preadlinkat without creating a pointer to the stack + that a broken gcc -Wreturn-local-addr would cry wolf about. See: + https://gcc.gnu.org/bugzilla/show_bug.cgi?id=95044 + This workaround differs from the mainline code, but + no other way to pacify GCC 10.1.0 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. */ +# define WORK_AROUND_GCC_BUG_95044 +#endif + if (! alloc) alloc = &stdlib_allocator; - if (! buffer_size) + if (!buffer) { +#ifdef WORK_AROUND_GCC_BUG_95044 + buffer = alloc->allocate (sizeof stack_buf); +#else /* 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; +#endif buffer_size = sizeof stack_buf; } buf = buffer; buf_size = buffer_size; - do + while (buf) { /* Attempt to read the link into the current buffer. */ ssize_t link_length = preadlinkat (fd, filename, buf, buf_size); @@ -117,19 +132,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,8 +153,8 @@ careadlinkat (int fd, char const *filename, if (buf != buffer) alloc->free (buf); - if (buf_size <= buf_size_max / 2) - buf_size *= 2; + if (buf_size < buf_size_max / 2) + buf_size = 2 * buf_size + 1; else if (buf_size < buf_size_max) buf_size = buf_size_max; else if (buf_size_max < SIZE_MAX) @@ -149,9 +164,8 @@ careadlinkat (int fd, char const *filename, } else break; - buf = (char *) alloc->allocate (buf_size); + buf = alloc->allocate (buf_size); } - while (buf); if (alloc->die) alloc->die (buf_size); diff --git a/lib/careadlinkat.h b/lib/careadlinkat.h index 584cfe9ad8e..a4a37b274d0 100644 --- a/lib/careadlinkat.h +++ b/lib/careadlinkat.h @@ -47,7 +47,7 @@ struct allocator; 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/cloexec.c b/lib/cloexec.c index 269e6f25f3b..510be3d57ec 100644 --- a/lib/cloexec.c +++ b/lib/cloexec.c @@ -1,7 +1,6 @@ /* cloexec.c - set or clear the close-on-exec descriptor flag - Copyright (C) 1991, 2004-2006, 2009-2020 Free Software Foundation, - Inc. + Copyright (C) 1991, 2004-2006, 2009-2020 Free Software Foundation, Inc. This program is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by diff --git a/lib/close-stream.c b/lib/close-stream.c index b1d04a53059..04bc8009a57 100644 --- a/lib/close-stream.c +++ b/lib/close-stream.c @@ -1,7 +1,6 @@ /* Close a stream, with nicer error checking than fclose's. - Copyright (C) 1998-2002, 2004, 2006-2020 Free Software Foundation, - Inc. + Copyright (C) 1998-2002, 2004, 2006-2020 Free Software Foundation, Inc. This program is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by diff --git a/lib/count-leading-zeros.h b/lib/count-leading-zeros.h index 2b65cc9eda9..7e88c8cb9d0 100644 --- a/lib/count-leading-zeros.h +++ b/lib/count-leading-zeros.h @@ -30,6 +30,10 @@ _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 @@ -100,7 +104,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 +111,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.h b/lib/count-one-bits.h index 040776f7466..6c5b75708cf 100644 --- a/lib/count-one-bits.h +++ b/lib/count-one-bits.h @@ -30,29 +30,17 @@ _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) +# 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 +55,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 +106,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 +147,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.h b/lib/count-trailing-zeros.h index 15e85708d18..1eb5fb919f4 100644 --- a/lib/count-trailing-zeros.h +++ b/lib/count-trailing-zeros.h @@ -30,6 +30,10 @@ _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 @@ -92,7 +96,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 +103,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 16e06053b43..c89363ac9ee 100644 --- a/lib/diffseq.h +++ b/lib/diffseq.h @@ -1,7 +1,7 @@ /* Analyze differences between two vectors. - Copyright (C) 1988-1989, 1992-1995, 2001-2004, 2006-2020 Free - Software Foundation, Inc. + Copyright (C) 1988-1989, 1992-1995, 2001-2004, 2006-2020 Free Software + Foundation, Inc. This program is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by diff --git a/lib/dirent.in.h b/lib/dirent.in.h index f7c26810158..6fa44f0d28d 100644 --- a/lib/dirent.in.h +++ b/lib/dirent.in.h @@ -57,10 +57,12 @@ typedef struct gl_directory DIR; /* 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) +# define _GL_ATTRIBUTE_PURE __attribute__ ((__pure__)) +# else +# define _GL_ATTRIBUTE_PURE /* empty */ +# endif #endif /* The definitions of _GL_FUNCDECL_RPL etc. are copied here. */ diff --git a/lib/dosname.h b/lib/dosname.h deleted file mode 100644 index 3bb08a5eeec..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-2020 Free Software - Foundation, Inc. - - This program is free software: you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation; either version 3 of the License, or - (at your option) any later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with this program. If not, see <https://www.gnu.org/licenses/>. - - From Paul Eggert and Jim Meyering. */ - -#ifndef _DOSNAME_H -#define _DOSNAME_H - -#if (defined _WIN32 || defined __CYGWIN__ \ - || defined __EMX__ || defined __MSDOS__ || 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/dup2.c b/lib/dup2.c index b5c3a00c740..9bc3951f3d2 100644 --- a/lib/dup2.c +++ b/lib/dup2.c @@ -1,7 +1,6 @@ /* Duplicate an open file descriptor to a specified file descriptor. - Copyright (C) 1999, 2004-2007, 2009-2020 Free Software Foundation, - Inc. + Copyright (C) 1999, 2004-2007, 2009-2020 Free Software Foundation, Inc. This program is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by @@ -26,28 +25,26 @@ #include <errno.h> #include <fcntl.h> -#if HAVE_DUP2 +#undef dup2 -# undef dup2 - -# if 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) { @@ -66,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) @@ -104,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) @@ -156,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/explicit_bzero.c b/lib/explicit_bzero.c index c82771fb1e3..b1f5acb7771 100644 --- a/lib/explicit_bzero.c +++ b/lib/explicit_bzero.c @@ -25,8 +25,18 @@ # 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. */ @@ -38,8 +48,12 @@ void explicit_bzero (void *s, size_t len) { -#ifdef HAVE_EXPLICIT_MEMSET - explicit_memset (s, 0, len); +#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); #else memset (s, '\0', len); # if defined __GNUC__ && !defined __clang__ diff --git a/lib/fchmodat.c b/lib/fchmodat.c new file mode 100644 index 00000000000..8950168608f --- /dev/null +++ b/lib/fchmodat.c @@ -0,0 +1,144 @@ +/* Change the protections of file relative to an open directory. + Copyright (C) 2006, 2009-2020 Free Software Foundation, Inc. + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + 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 <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 NEED_FCHMODAT_NONSYMLINK_FIX + if (flags == AT_SYMLINK_NOFOLLOW) + { + struct stat st; + +# if defined O_PATH && defined AT_EMPTY_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; + + /* Up to Linux 5.3 at least, when FILE refers to a symbolic link, the + chmod call below will change the permissions of the symbolic link + - which is undesired - and on many file systems (ext4, btrfs, jfs, + xfs, ..., but not reiserfs) fail with error EOPNOTSUPP - which is + misleading. Therefore test for a symbolic link explicitly. + Use fstatat because fstat does not work on O_PATH descriptors + before Linux 3.6. */ + if (fstatat (fd, "", &st, AT_EMPTY_PATH) != 0) + { + int stat_errno = errno; + close (fd); + errno = stat_errno; + return -1; + } + if (S_ISLNK (st.st_mode)) + { + close (fd); + errno = EOPNOTSUPP; + return -1; + } + +# if defined __linux__ || defined __ANDROID__ + static char const fmt[] = "/proc/self/fd/%d"; + char buf[sizeof fmt - sizeof "%d" + INT_BUFSIZE_BOUND (int)]; + sprintf (buf, fmt, fd); + int chmod_result = chmod (buf, mode); + int chmod_errno = errno; + close (fd); + if (chmod_result == 0) + return chmod_result; + if (chmod_errno != ENOENT) + { + errno = chmod_errno; + return chmod_result; + } +# endif + /* /proc is not mounted or would not work as in GNU/Linux. */ + +# else + int fstatat_result = fstatat (dir, file, &st, AT_SYMLINK_NOFOLLOW); + if (fstatat_result != 0) + return fstatat_result; + if (S_ISLNK (st.st_mode)) + { + 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.in.h b/lib/fcntl.in.h index b2e1e5130d9..0a21c957baf 100644 --- a/lib/fcntl.in.h +++ b/lib/fcntl.in.h @@ -116,9 +116,15 @@ _GL_WARN_ON_USE (creat, "creat is not always POSIX compliant - " # 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 diff --git a/lib/filemode.h b/lib/filemode.h index 8b8464f220a..f84a491625c 100644 --- a/lib/filemode.h +++ b/lib/filemode.h @@ -1,7 +1,7 @@ /* Make a string describing file modes. - Copyright (C) 1998-1999, 2003, 2006, 2009-2020 Free Software - Foundation, Inc. + Copyright (C) 1998-1999, 2003, 2006, 2009-2020 Free Software Foundation, + Inc. This program is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by diff --git a/lib/filename.h b/lib/filename.h new file mode 100644 index 00000000000..4598fb1d638 --- /dev/null +++ b/lib/filename.h @@ -0,0 +1,110 @@ +/* Basic filename support macros. + Copyright (C) 2001-2004, 2007-2020 Free Software Foundation, Inc. + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + 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 _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/fpending.c b/lib/fpending.c index 4db32eafd6a..802ebcba654 100644 --- a/lib/fpending.c +++ b/lib/fpending.c @@ -1,6 +1,6 @@ /* fpending.c -- return the number of pending output bytes on a stream - Copyright (C) 2000, 2004, 2006-2007, 2009-2020 Free Software - Foundation, Inc. + Copyright (C) 2000, 2004, 2006-2007, 2009-2020 Free Software Foundation, + Inc. This program is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by diff --git a/lib/fpending.h b/lib/fpending.h index 52639379975..a8b8859726d 100644 --- a/lib/fpending.h +++ b/lib/fpending.h @@ -1,7 +1,7 @@ /* Declare __fpending. - Copyright (C) 2000, 2003, 2005-2006, 2009-2020 Free Software - Foundation, Inc. + Copyright (C) 2000, 2003, 2005-2006, 2009-2020 Free Software Foundation, + Inc. This program is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by diff --git a/lib/fsusage.c b/lib/fsusage.c index c0ee4533f9a..81960152d41 100644 --- a/lib/fsusage.c +++ b/lib/fsusage.c @@ -1,7 +1,7 @@ /* fsusage.c -- return space usage of mounted file systems - Copyright (C) 1991-1992, 1996, 1998-1999, 2002-2006, 2009-2020 Free - Software Foundation, Inc. + Copyright (C) 1991-1992, 1996, 1998-1999, 2002-2006, 2009-2020 Free Software + Foundation, Inc. This program is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by diff --git a/lib/ftoastr.c b/lib/ftoastr.c index 7a7d4113c22..47a83152e3f 100644 --- a/lib/ftoastr.c +++ b/lib/ftoastr.c @@ -33,20 +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 -# define STRTOF strtold +# 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 @@ -54,7 +62,7 @@ # 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 @@ -65,13 +73,16 @@ 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 diff --git a/lib/ftoastr.h b/lib/ftoastr.h index d945cc064a7..78b569f3d97 100644 --- a/lib/ftoastr.h +++ b/lib/ftoastr.h @@ -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..83fb27cb6aa --- /dev/null +++ b/lib/futimens.c @@ -0,0 +1,37 @@ +/* Set the access and modification time of an open fd. + Copyright (C) 2009-2020 Free Software Foundation, Inc. + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see <https://www.gnu.org/licenses/>. */ + +/* 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/getgroups.c b/lib/getgroups.c index b1ec68dadf9..4396b4d64b7 100644 --- a/lib/getgroups.c +++ b/lib/getgroups.c @@ -1,7 +1,6 @@ /* provide consistent interface to getgroups for systems that don't allow N==0 - Copyright (C) 1996, 1999, 2003, 2006-2020 Free Software Foundation, - Inc. + Copyright (C) 1996, 1999, 2003, 2006-2020 Free Software Foundation, Inc. This program is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by diff --git a/lib/getloadavg.c b/lib/getloadavg.c index 507017339cc..468e2506709 100644 --- a/lib/getloadavg.c +++ b/lib/getloadavg.c @@ -1,7 +1,7 @@ /* Get the system load averages. - Copyright (C) 1985-1989, 1991-1995, 1997, 1999-2000, 2003-2020 Free - Software Foundation, Inc. + Copyright (C) 1985-1989, 1991-1995, 1997, 1999-2000, 2003-2020 Free Software + Foundation, Inc. NOTE: The canonical source of this file is maintained with gnulib. Bugs can be reported to bug-gnulib@gnu.org. @@ -512,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); @@ -550,7 +550,7 @@ 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; @@ -567,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; @@ -869,27 +876,11 @@ 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 diff --git a/lib/getopt-pfx-core.h b/lib/getopt-pfx-core.h index da0a6d0c3c4..ec545c1b51c 100644 --- a/lib/getopt-pfx-core.h +++ b/lib/getopt-pfx-core.h @@ -48,6 +48,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/getrandom.c b/lib/getrandom.c new file mode 100644 index 00000000000..f8695abf30a --- /dev/null +++ b/lib/getrandom.c @@ -0,0 +1,187 @@ +/* Obtain a series of random bytes. + + Copyright 2020 Free Software Foundation, Inc. + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see <https://www.gnu.org/licenses/>. */ + +/* Written by Paul Eggert. */ + +#include <config.h> + +#include <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) + return fd; + randfd[devrandom] = fd; + } + + return read (fd, buffer, length); +#endif +} diff --git a/lib/gettext.h b/lib/gettext.h index 4c6b5efcc3f..0bd1e13348a 100644 --- a/lib/gettext.h +++ b/lib/gettext.h @@ -1,6 +1,6 @@ /* Convenience header for conditional use of GNU <libintl.h>. - Copyright (C) 1995-1998, 2000-2002, 2004-2006, 2009-2020 Free - Software Foundation, Inc. + Copyright (C) 1995-1998, 2000-2002, 2004-2006, 2009-2020 Free Software + Foundation, Inc. This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by diff --git a/lib/gettime.c b/lib/gettime.c index f212a238a88..f5b8ca53b5f 100644 --- a/lib/gettime.c +++ b/lib/gettime.c @@ -1,7 +1,6 @@ /* gettime -- get the system clock - Copyright (C) 2002, 2004-2007, 2009-2020 Free Software Foundation, - Inc. + Copyright (C) 2002, 2004-2007, 2009-2020 Free Software Foundation, Inc. This program is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by diff --git a/lib/gettimeofday.c b/lib/gettimeofday.c index b5e2c300305..057cebdb163 100644 --- a/lib/gettimeofday.c +++ b/lib/gettimeofday.c @@ -1,7 +1,6 @@ /* Provide gettimeofday for systems that don't have it or for which it's broken. - Copyright (C) 2001-2003, 2005-2007, 2009-2020 Free Software - Foundation, Inc. + Copyright (C) 2001-2003, 2005-2007, 2009-2020 Free Software Foundation, Inc. This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by @@ -34,9 +33,15 @@ #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 +# define GetProcAddress \ + (void *) GetProcAddress /* GetSystemTimePreciseAsFileTime was introduced only in Windows 8. */ typedef void (WINAPI * GetSystemTimePreciseAsFileTimeFuncType) (FILETIME *lpTime); @@ -55,6 +60,12 @@ initialize (void) initialized = TRUE; } +# else + +# define GetSystemTimePreciseAsFileTimeFunc GetSystemTimePreciseAsFileTime + +# endif + #endif /* This is a wrapper for gettimeofday. It is used only on systems @@ -85,8 +96,10 @@ 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 (¤t_time); else diff --git a/lib/gnulib.mk.in b/lib/gnulib.mk.in index 5adea10c18e..68cae8faf74 100644 --- a/lib/gnulib.mk.in +++ b/lib/gnulib.mk.in @@ -86,7 +86,6 @@ # crypto/sha512-buffer \ # d-type \ # diffseq \ -# dosname \ # double-slash-root \ # dtoastr \ # dtotimespec \ @@ -95,18 +94,22 @@ # execinfo \ # explicit_bzero \ # faccessat \ +# fchmodat \ # fcntl \ # fcntl-h \ # fdopendir \ # filemode \ +# filename \ # filevercmp \ # flexmember \ # fpieee \ # fstatat \ # fsusage \ # fsync \ +# futimens \ # getloadavg \ # getopt-gnu \ +# getrandom \ # gettime \ # gettimeofday \ # gitlog-to-changelog \ @@ -114,6 +117,7 @@ # ignore-value \ # intprops \ # largefile \ +# libgmp \ # lstat \ # manywarnings \ # memmem-simple \ @@ -127,7 +131,6 @@ # pipe2 \ # pselect \ # pthread_sigmask \ -# putenv \ # qcopy-acl \ # readlink \ # readlinkat \ @@ -155,7 +158,7 @@ # timespec-sub \ # unlocked-io \ # update-copyright \ -# utimens \ +# utimensat \ # vla \ # warnings @@ -243,14 +246,14 @@ 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_GMP_H = @GL_GENERATE_GMP_H@ GL_GENERATE_IEEE754_H = @GL_GENERATE_IEEE754_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@ GMALLOC_OBJ = @GMALLOC_OBJ@ -GMP_LIB = @GMP_LIB@ -GMP_OBJ = @GMP_OBJ@ +GMP_H = @GMP_H@ GNULIB_ACCESS = @GNULIB_ACCESS@ GNULIB_ALPHASORT = @GNULIB_ALPHASORT@ GNULIB_ATOLL = @GNULIB_ATOLL@ @@ -310,16 +313,20 @@ GNULIB_GETCWD = @GNULIB_GETCWD@ GNULIB_GETDELIM = @GNULIB_GETDELIM@ GNULIB_GETDOMAINNAME = @GNULIB_GETDOMAINNAME@ GNULIB_GETDTABLESIZE = @GNULIB_GETDTABLESIZE@ +GNULIB_GETENTROPY = @GNULIB_GETENTROPY@ 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_GETOPT_POSIX = @GNULIB_GETOPT_POSIX@ GNULIB_GETPAGESIZE = @GNULIB_GETPAGESIZE@ GNULIB_GETPASS = @GNULIB_GETPASS@ +GNULIB_GETRANDOM = @GNULIB_GETRANDOM@ GNULIB_GETSUBOPT = @GNULIB_GETSUBOPT@ GNULIB_GETTIMEOFDAY = @GNULIB_GETTIMEOFDAY@ +GNULIB_GETUMASK = @GNULIB_GETUMASK@ GNULIB_GETUSERSHELL = @GNULIB_GETUSERSHELL@ GNULIB_GL_UNISTD_H_GETOPT = @GNULIB_GL_UNISTD_H_GETOPT@ GNULIB_GRANTPT = @GNULIB_GRANTPT@ @@ -543,7 +550,6 @@ 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_EXPLICIT_BZERO = @HAVE_EXPLICIT_BZERO@ @@ -563,14 +569,17 @@ 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_IMAXDIV_T = @HAVE_IMAXDIV_T@ @@ -580,13 +589,11 @@ HAVE_LCHMOD = @HAVE_LCHMOD@ HAVE_LCHOWN = @HAVE_LCHOWN@ 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_MAX_ALIGN_T = @HAVE_MAX_ALIGN_T@ HAVE_MBSLEN = @HAVE_MBSLEN@ HAVE_MBTOWC = @HAVE_MBTOWC@ -HAVE_MEMCHR = @HAVE_MEMCHR@ HAVE_MEMPCPY = @HAVE_MEMPCPY@ HAVE_MKDIRAT = @HAVE_MKDIRAT@ HAVE_MKDTEMP = @HAVE_MKDTEMP@ @@ -666,6 +673,7 @@ 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@ @@ -676,7 +684,6 @@ 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@ @@ -753,6 +760,8 @@ LIB_ACL = @LIB_ACL@ LIB_CLOCK_GETTIME = @LIB_CLOCK_GETTIME@ LIB_EACCESS = @LIB_EACCESS@ LIB_EXECINFO = @LIB_EXECINFO@ +LIB_GETRANDOM = @LIB_GETRANDOM@ +LIB_GMP = @LIB_GMP@ LIB_MATH = @LIB_MATH@ LIB_PTHREAD = @LIB_PTHREAD@ LIB_PTHREAD_SIGMASK = @LIB_PTHREAD_SIGMASK@ @@ -768,6 +777,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@ @@ -781,6 +791,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@ @@ -799,6 +810,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@ @@ -855,6 +867,7 @@ REPLACE_DPRINTF = @REPLACE_DPRINTF@ REPLACE_DUP = @REPLACE_DUP@ REPLACE_DUP2 = @REPLACE_DUP2@ REPLACE_FACCESSAT = @REPLACE_FACCESSAT@ +REPLACE_FCHMODAT = @REPLACE_FCHMODAT@ REPLACE_FCHOWNAT = @REPLACE_FCHOWNAT@ REPLACE_FCLOSE = @REPLACE_FCLOSE@ REPLACE_FCNTL = @REPLACE_FCNTL@ @@ -882,6 +895,7 @@ REPLACE_GETLINE = @REPLACE_GETLINE@ REPLACE_GETLOGIN_R = @REPLACE_GETLOGIN_R@ REPLACE_GETPAGESIZE = @REPLACE_GETPAGESIZE@ REPLACE_GETPASS = @REPLACE_GETPASS@ +REPLACE_GETRANDOM = @REPLACE_GETRANDOM@ REPLACE_GETTIMEOFDAY = @REPLACE_GETTIMEOFDAY@ REPLACE_GMTIME = @REPLACE_GMTIME@ REPLACE_INITSTATE = @REPLACE_INITSTATE@ @@ -1001,6 +1015,7 @@ 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@ @@ -1070,7 +1085,6 @@ gamegroup = @gamegroup@ gameuser = @gameuser@ gl_GNULIB_ENABLED_03e0aaad4cb89ca757653bd367a6ccb7 = @gl_GNULIB_ENABLED_03e0aaad4cb89ca757653bd367a6ccb7@ gl_GNULIB_ENABLED_2049e887c7e5308faad27b3f894bb8c9 = @gl_GNULIB_ENABLED_2049e887c7e5308faad27b3f894bb8c9@ -gl_GNULIB_ENABLED_21ee726a3540c09237a8e70c0baf7467 = @gl_GNULIB_ENABLED_21ee726a3540c09237a8e70c0baf7467@ gl_GNULIB_ENABLED_260941c0e5dc67ec9e87d1fb321c300b = @gl_GNULIB_ENABLED_260941c0e5dc67ec9e87d1fb321c300b@ gl_GNULIB_ENABLED_5264294aa0a5557541b53c8c741f7f31 = @gl_GNULIB_ENABLED_5264294aa0a5557541b53c8c741f7f31@ gl_GNULIB_ENABLED_6099e9737f757db36c47fa9d9f02e88c = @gl_GNULIB_ENABLED_6099e9737f757db36c47fa9d9f02e88c@ @@ -1082,9 +1096,11 @@ gl_GNULIB_ENABLED_dirfd = @gl_GNULIB_ENABLED_dirfd@ 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_lchmod = @gl_GNULIB_ENABLED_lchmod@ gl_GNULIB_ENABLED_malloca = @gl_GNULIB_ENABLED_malloca@ gl_GNULIB_ENABLED_open = @gl_GNULIB_ENABLED_open@ gl_GNULIB_ENABLED_strtoll = @gl_GNULIB_ENABLED_strtoll@ +gl_GNULIB_ENABLED_utimens = @gl_GNULIB_ENABLED_utimens@ gl_LIBOBJS = @gl_LIBOBJS@ gl_LTLIBOBJS = @gl_LTLIBOBJS@ gltests_LIBOBJS = @gltests_LIBOBJS@ @@ -1198,14 +1214,20 @@ endif ifeq (,$(OMIT_GNULIB_MODULE_at-internal)) ifneq (,$(gl_GNULIB_ENABLED_260941c0e5dc67ec9e87d1fb321c300b)) +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)) @@ -1451,15 +1473,6 @@ EXTRA_libgnu_a_SOURCES += dirfd.c endif ## end gnulib module dirfd -## begin gnulib module dosname -ifeq (,$(OMIT_GNULIB_MODULE_dosname)) - - -EXTRA_DIST += dosname.h - -endif -## end gnulib module dosname - ## begin gnulib module dtoastr ifeq (,$(OMIT_GNULIB_MODULE_dtoastr)) @@ -1589,6 +1602,17 @@ EXTRA_libgnu_a_SOURCES += at-func.c faccessat.c endif ## end gnulib module faccessat +## begin gnulib module fchmodat +ifeq (,$(OMIT_GNULIB_MODULE_fchmodat)) + + +EXTRA_DIST += at-func.c fchmodat.c + +EXTRA_libgnu_a_SOURCES += at-func.c fchmodat.c + +endif +## end gnulib module fchmodat + ## begin gnulib module fcntl ifeq (,$(OMIT_GNULIB_MODULE_fcntl)) @@ -1660,6 +1684,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)) @@ -1723,6 +1756,17 @@ EXTRA_libgnu_a_SOURCES += fsync.c endif ## end gnulib module fsync +## begin gnulib module futimens +ifeq (,$(OMIT_GNULIB_MODULE_futimens)) + + +EXTRA_DIST += futimens.c + +EXTRA_libgnu_a_SOURCES += futimens.c + +endif +## end gnulib module futimens + ## begin gnulib module getdtablesize ifeq (,$(OMIT_GNULIB_MODULE_getdtablesize)) @@ -1798,6 +1842,17 @@ EXTRA_libgnu_a_SOURCES += getopt.c getopt1.c endif ## end gnulib module getopt-posix +## begin gnulib module getrandom +ifeq (,$(OMIT_GNULIB_MODULE_getrandom)) + + +EXTRA_DIST += getrandom.c + +EXTRA_libgnu_a_SOURCES += getrandom.c + +endif +## end gnulib module getrandom + ## begin gnulib module gettext-h ifeq (,$(OMIT_GNULIB_MODULE_gettext-h)) @@ -1910,8 +1965,6 @@ inttypes.h: inttypes.in.h $(top_builddir)/config.status $(CXXDEFS_H) $(WARN_ON_U -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' \ @@ -1941,17 +1994,51 @@ 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)) + +endif +EXTRA_DIST += lchmod.c + +EXTRA_libgnu_a_SOURCES += lchmod.c + +endif +## end gnulib module lchmod + ## begin gnulib module libc-config ifeq (,$(OMIT_GNULIB_MODULE_libc-config)) -ifneq (,$(gl_GNULIB_ENABLED_21ee726a3540c09237a8e70c0baf7467)) -endif 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) + +# Build gmp.h as a wrapper for mini-gmp.h when using mini-gmp. +ifneq (,$(GL_GENERATE_GMP_H)) +gmp.h: $(top_builddir)/config.status + echo '#include "mini-gmp.h"' >$@-t + mv $@-t $@ +else +gmp.h: $(top_builddir)/config.status + rm -f $@ +endif +MOSTLYCLEANFILES += gmp.h gmp.h-t + +EXTRA_DIST += mini-gmp-gnulib.c mini-gmp.c mini-gmp.h + +EXTRA_libgnu_a_SOURCES += mini-gmp-gnulib.c mini-gmp.c + +endif +## end gnulib module libgmp + ## begin gnulib module limits-h ifeq (,$(OMIT_GNULIB_MODULE_limits-h)) @@ -2167,17 +2254,6 @@ EXTRA_libgnu_a_SOURCES += pthread_sigmask.c endif ## end gnulib module pthread_sigmask -## begin gnulib module putenv -ifeq (,$(OMIT_GNULIB_MODULE_putenv)) - - -EXTRA_DIST += putenv.c - -EXTRA_libgnu_a_SOURCES += putenv.c - -endif -## end gnulib module putenv - ## begin gnulib module qcopy-acl ifeq (,$(OMIT_GNULIB_MODULE_qcopy-acl)) @@ -2432,8 +2508,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' \ @@ -2783,7 +2857,6 @@ string.h: string.in.h $(top_builddir)/config.status $(CXXDEFS_H) $(ARG_NONNULL_H -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' \ @@ -2875,6 +2948,40 @@ EXTRA_libgnu_a_SOURCES += symlink.c endif ## end gnulib module symlink +## begin gnulib module sys_random +ifeq (,$(OMIT_GNULIB_MODULE_sys_random)) + +BUILT_SOURCES += sys/random.h + +# 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_at)$(MKDIR_P) sys + $(AM_V_GEN)rm -f $@-t $@ && \ + { echo '/* DO NOT EDIT! GENERATED AUTOMATICALLY! */'; \ + sed -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''@/$(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 && \ + mv -f $@-t $@ +MOSTLYCLEANFILES += sys/random.h sys/random.h-t +MOSTLYCLEANDIRS += sys + +EXTRA_DIST += sys_random.in.h + +endif +## end gnulib module sys_random + ## begin gnulib module sys_select ifeq (,$(OMIT_GNULIB_MODULE_sys_select)) @@ -2933,6 +3040,7 @@ sys/stat.h: sys_stat.in.h $(top_builddir)/config.status $(CXXDEFS_H) $(ARG_NONNU -e 's/@''GNULIB_FSTAT''@/$(GNULIB_FSTAT)/g' \ -e 's/@''GNULIB_FSTATAT''@/$(GNULIB_FSTATAT)/g' \ -e 's/@''GNULIB_FUTIMENS''@/$(GNULIB_FUTIMENS)/g' \ + -e 's/@''GNULIB_GETUMASK''@/$(GNULIB_GETUMASK)/g' \ -e 's/@''GNULIB_LCHMOD''@/$(GNULIB_LCHMOD)/g' \ -e 's/@''GNULIB_LSTAT''@/$(GNULIB_LSTAT)/g' \ -e 's/@''GNULIB_MKDIRAT''@/$(GNULIB_MKDIRAT)/g' \ @@ -2946,6 +3054,7 @@ sys/stat.h: sys_stat.in.h $(top_builddir)/config.status $(CXXDEFS_H) $(ARG_NONNU -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' \ @@ -2954,6 +3063,7 @@ 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_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' \ @@ -3214,10 +3324,12 @@ unistd.h: unistd.in.h $(top_builddir)/config.status $(CXXDEFS_H) $(ARG_NONNULL_H -e 's/@''GNULIB_GETCWD''@/$(GNULIB_GETCWD)/g' \ -e 's/@''GNULIB_GETDOMAINNAME''@/$(GNULIB_GETDOMAINNAME)/g' \ -e 's/@''GNULIB_GETDTABLESIZE''@/$(GNULIB_GETDTABLESIZE)/g' \ + -e 's/@''GNULIB_GETENTROPY''@/$(GNULIB_GETENTROPY)/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_GETOPT_POSIX''@/$(GNULIB_GETOPT_POSIX)/g' \ -e 's/@''GNULIB_GETPAGESIZE''@/$(GNULIB_GETPAGESIZE)/g' \ -e 's/@''GNULIB_GETPASS''@/$(GNULIB_GETPASS)/g' \ -e 's/@''GNULIB_GETUSERSHELL''@/$(GNULIB_GETUSERSHELL)/g' \ @@ -3251,7 +3363,6 @@ unistd.h: unistd.in.h $(top_builddir)/config.status $(CXXDEFS_H) $(ARG_NONNULL_H < $(srcdir)/unistd.in.h | \ sed -e 's|@''HAVE_CHOWN''@|$(HAVE_CHOWN)|g' \ -e 's|@''HAVE_COPY_FILE_RANGE''@|$(HAVE_COPY_FILE_RANGE)|g' \ - -e 's|@''HAVE_DUP2''@|$(HAVE_DUP2)|g' \ -e 's|@''HAVE_DUP3''@|$(HAVE_DUP3)|g' \ -e 's|@''HAVE_EUIDACCESS''@|$(HAVE_EUIDACCESS)|g' \ -e 's|@''HAVE_FACCESSAT''@|$(HAVE_FACCESSAT)|g' \ @@ -3261,6 +3372,7 @@ 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' \ @@ -3330,6 +3442,7 @@ 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)' \ @@ -3365,13 +3478,26 @@ endif ## begin gnulib module utimens ifeq (,$(OMIT_GNULIB_MODULE_utimens)) +ifneq (,$(gl_GNULIB_ENABLED_utimens)) libgnu_a_SOURCES += utimens.c +endif EXTRA_DIST += utimens.h endif ## end gnulib module utimens +## begin gnulib module utimensat +ifeq (,$(OMIT_GNULIB_MODULE_utimensat)) + + +EXTRA_DIST += at-func.c utimensat.c + +EXTRA_libgnu_a_SOURCES += at-func.c utimensat.c + +endif +## end gnulib module utimensat + ## begin gnulib module verify ifeq (,$(OMIT_GNULIB_MODULE_verify)) diff --git a/lib/group-member.c b/lib/group-member.c index 7aa8a453615..6a6fc5605ef 100644 --- a/lib/group-member.c +++ b/lib/group-member.c @@ -1,7 +1,7 @@ /* group-member.c -- determine whether group id is in calling user's group list - Copyright (C) 1994, 1997-1998, 2003, 2005-2006, 2009-2020 Free - Software Foundation, Inc. + Copyright (C) 1994, 1997-1998, 2003, 2005-2006, 2009-2020 Free Software + Foundation, Inc. This program is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by diff --git a/lib/ieee754.in.h b/lib/ieee754.in.h index 01ca648905f..d64bb46e9de 100644 --- a/lib/ieee754.in.h +++ b/lib/ieee754.in.h @@ -67,7 +67,7 @@ union ieee754_float #endif /* Little endian. */ } ieee; - /* This format makes it easier to see if a NaN is a signaling NaN. */ + /* This format makes it easier to see if a NaN is a signalling NaN. */ struct { #if __BYTE_ORDER == __BIG_ENDIAN @@ -118,7 +118,7 @@ union ieee754_double #endif /* Little endian. */ } ieee; - /* This format makes it easier to see if a NaN is a signaling NaN. */ + /* This format makes it easier to see if a NaN is a signalling NaN. */ struct { #if __BYTE_ORDER == __BIG_ENDIAN diff --git a/lib/inttypes.in.h b/lib/inttypes.in.h index da84aff0440..9f04a6ced4a 100644 --- a/lib/inttypes.in.h +++ b/lib/inttypes.in.h @@ -38,6 +38,8 @@ # endif # @INCLUDE_NEXT@ @NEXT_INTTYPES_H@ + +# define _GL_FINISHED_INCLUDING_SYSTEM_INTTYPES_H # endif #endif @@ -189,7 +191,7 @@ # 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@ @@ -206,7 +208,7 @@ # 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@ @@ -682,7 +684,7 @@ # 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@ @@ -699,7 +701,7 @@ # 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@ @@ -1091,15 +1093,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 @@ -1117,15 +1123,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..e1132116234 --- /dev/null +++ b/lib/lchmod.c @@ -0,0 +1,110 @@ +/* Implement lchmod on platforms where it does not work correctly. + + Copyright 2020 Free Software Foundation, Inc. + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see <https://www.gnu.org/licenses/>. */ + +/* written by Paul Eggert */ + +#include <config.h> + +/* Specification. */ +#include <sys/stat.h> + +#include <errno.h> +#include <fcntl.h> +#include <stdio.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> + +/* 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) +{ +#if defined O_PATH && defined AT_EMPTY_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; + + /* Up to Linux 5.3 at least, when FILE refers to a symbolic link, the + chmod call below will change the permissions of the symbolic link + - which is undesired - and on many file systems (ext4, btrfs, jfs, + xfs, ..., but not reiserfs) fail with error EOPNOTSUPP - which is + misleading. Therefore test for a symbolic link explicitly. + Use fstatat because fstat does not work on O_PATH descriptors + before Linux 3.6. */ + struct stat st; + if (fstatat (fd, "", &st, AT_EMPTY_PATH) != 0) + { + int stat_errno = errno; + close (fd); + errno = stat_errno; + return -1; + } + if (S_ISLNK (st.st_mode)) + { + close (fd); + errno = EOPNOTSUPP; + return -1; + } + +# if defined __linux__ || defined __ANDROID__ + static char const fmt[] = "/proc/self/fd/%d"; + char buf[sizeof fmt - sizeof "%d" + INT_BUFSIZE_BOUND (int)]; + sprintf (buf, fmt, fd); + int chmod_result = chmod (buf, mode); + int chmod_errno = errno; + close (fd); + if (chmod_result == 0) + return chmod_result; + if (chmod_errno != ENOENT) + { + errno = chmod_errno; + return chmod_result; + } +# endif + /* /proc is not mounted or would not work as in GNU/Linux. */ + +#elif HAVE_LSTAT + struct stat st; + int lstat_result = lstat (file, &st); + if (lstat_result != 0) + return lstat_result; + if (S_ISLNK (st.st_mode)) + { + errno = EOPNOTSUPP; + return -1; + } +#endif + + /* Fall back on chmod, despite a possible race. */ + return chmod (file, mode); +} diff --git a/lib/libc-config.h b/lib/libc-config.h index aef1f793242..1300c3a2ac8 100644 --- a/lib/libc-config.h +++ b/lib/libc-config.h @@ -55,8 +55,17 @@ #ifndef __glibc_clang_prereq # if defined __clang_major__ && defined __clang_minor__ -# define __glibc_clang_prereq(maj, min) \ - ((maj) < __clang_major__ + ((min) <= __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 @@ -171,4 +180,5 @@ /* A substitute for glibc <shlib-compat.h>, good enough for Gnulib. */ #define SHLIB_COMPAT(lib, introduced, obsoleted) 0 -#define versioned_symbol(lib, local, symbol, version) +#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 90c273fa178..d25c5237060 100644 --- a/lib/limits.in.h +++ b/lib/limits.in.h @@ -15,16 +15,32 @@ 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 - #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 @@ -102,3 +118,4 @@ #endif /* _@GUARD_PREFIX@_LIMITS_H */ #endif /* _@GUARD_PREFIX@_LIMITS_H */ +#endif diff --git a/lib/localtime-buffer.c b/lib/localtime-buffer.c index eb099ff8d84..141849c5461 100644 --- a/lib/localtime-buffer.c +++ b/lib/localtime-buffer.c @@ -1,7 +1,6 @@ /* Provide access to the last buffer returned by localtime() or gmtime(). - Copyright (C) 2001-2003, 2005-2007, 2009-2020 Free Software - Foundation, Inc. + Copyright (C) 2001-2003, 2005-2007, 2009-2020 Free Software Foundation, Inc. This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by diff --git a/lib/localtime-buffer.h b/lib/localtime-buffer.h index 2552cfcffba..3801742f7ba 100644 --- a/lib/localtime-buffer.h +++ b/lib/localtime-buffer.h @@ -1,7 +1,6 @@ /* Provide access to the last buffer returned by localtime() or gmtime(). - Copyright (C) 2001-2003, 2005-2007, 2009-2020 Free Software - Foundation, Inc. + Copyright (C) 2001-2003, 2005-2007, 2009-2020 Free Software Foundation, Inc. This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by diff --git a/lib/malloca.c b/lib/malloca.c index 59bd74d598b..975b166daed 100644 --- a/lib/malloca.c +++ b/lib/malloca.c @@ -1,6 +1,5 @@ /* Safe automatic memory allocation. - Copyright (C) 2003, 2006-2007, 2009-2020 Free Software Foundation, - Inc. + Copyright (C) 2003, 2006-2007, 2009-2020 Free Software Foundation, Inc. Written by Bruno Haible <bruno@clisp.org>, 2003, 2018. This program is free software; you can redistribute it and/or modify diff --git a/lib/malloca.h b/lib/malloca.h index 0d0b713c7bd..cfcd4de4ad8 100644 --- a/lib/malloca.h +++ b/lib/malloca.h @@ -112,14 +112,10 @@ enum among all elementary types. */ sa_alignment_long = sa_alignof (long), sa_alignment_double = sa_alignof (double), -#if HAVE_LONG_LONG_INT sa_alignment_longlong = sa_alignof (long long), -#endif sa_alignment_longdouble = sa_alignof (long double), sa_alignment_max = ((sa_alignment_long - 1) | (sa_alignment_double - 1) -#if HAVE_LONG_LONG_INT | (sa_alignment_longlong - 1) -#endif | (sa_alignment_longdouble - 1) ) + 1 }; diff --git a/lib/md5.c b/lib/md5.c index e0f3032aec0..74cf2c3a0f7 100644 --- a/lib/md5.c +++ b/lib/md5.c @@ -1,7 +1,7 @@ /* 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-2020 Free - Software Foundation, Inc. + Copyright (C) 1995-1997, 1999-2001, 2005-2006, 2008-2020 Free Software + Foundation, Inc. This file is part of the GNU C Library. This program is free software; you can redistribute it and/or modify it diff --git a/lib/md5.h b/lib/md5.h index 7c827b0586a..3c6048242b0 100644 --- a/lib/md5.h +++ b/lib/md5.h @@ -1,7 +1,7 @@ /* Declaration of functions and data types used for MD5 sum computing library functions. - Copyright (C) 1995-1997, 1999-2001, 2004-2006, 2008-2020 Free - Software Foundation, Inc. + Copyright (C) 1995-1997, 1999-2001, 2004-2006, 2008-2020 Free Software + Foundation, Inc. This file is part of the GNU C Library. This program is free software; you can redistribute it and/or modify it @@ -105,13 +105,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,7 +121,7 @@ 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. diff --git a/lib/memmem.c b/lib/memmem.c index 9108f6f697c..6f6574211f8 100644 --- a/lib/memmem.c +++ b/lib/memmem.c @@ -1,5 +1,5 @@ -/* Copyright (C) 1991-1994, 1996-1998, 2000, 2004, 2007-2020 Free - Software Foundation, Inc. +/* Copyright (C) 1991-1994, 1996-1998, 2000, 2004, 2007-2020 Free Software + Foundation, Inc. This file is part of the GNU C Library. This program is free software; you can redistribute it and/or modify diff --git a/lib/memrchr.c b/lib/memrchr.c index b4256edcbb9..7ff32e11338 100644 --- a/lib/memrchr.c +++ b/lib/memrchr.c @@ -1,7 +1,7 @@ /* memrchr -- find the last occurrence of a byte in a memory block - Copyright (C) 1991, 1993, 1996-1997, 1999-2000, 2003-2020 Free - Software Foundation, Inc. + Copyright (C) 1991, 1993, 1996-1997, 1999-2000, 2003-2020 Free Software + Foundation, Inc. Based on strlen implementation by Torbjorn Granlund (tege@sics.se), with help from Dan Sahlin (dan@sics.se) and diff --git a/lib/mini-gmp-gnulib.c b/lib/mini-gmp-gnulib.c new file mode 100644 index 00000000000..5019be5d52a --- /dev/null +++ b/lib/mini-gmp-gnulib.c @@ -0,0 +1,37 @@ +/* Tailor mini-gmp.c for Gnulib-using applications. + + Copyright 2018-2020 Free Software Foundation, Inc. + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see <https://www.gnu.org/licenses/>. */ + +#include <config.h> + +#include <stddef.h> +#include <stdio.h> + +#include "mini-gmp.h" + +/* Pacify GCC -Wsuggest-attribute=const, malloc, pure. */ +#if 4 < __GNUC__ + (6 <= __GNUC_MINOR__) +# pragma GCC diagnostic ignored "-Wsuggest-attribute=const" +# pragma GCC diagnostic ignored "-Wsuggest-attribute=malloc" +# pragma GCC diagnostic ignored "-Wsuggest-attribute=pure" +#endif + +/* Pacify GCC -Wunused-variable for variables used only in 'assert' calls. */ +#if defined NDEBUG && 4 < __GNUC__ + (6 <= __GNUC_MINOR__) +# 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..2e0301b0081 --- /dev/null +++ b/lib/mini-gmp.c @@ -0,0 +1,4615 @@ +/* mini-gmp, a minimalistic implementation of a GNU GMP subset. + + Contributed to the GNU project by Niels Möller + +Copyright 1991-1997, 1999-2020 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 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 3 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 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 + neither with GMP nor 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); \ + } 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); \ + \ + __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; + + /* 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; + size_t j; + unsigned shift; + + for (j = sn, rn = 0, shift = 0; j-- > 0; ) + { + if (shift == 0) + { + rp[rn++] = sp[j]; + shift += bits; + } + else + { + rp[rn-1] |= (mp_limb_t) sp[j] << shift; + shift += bits; + if (shift >= GMP_LIMB_BITS) + { + shift -= GMP_LIMB_BITS; + if (shift > 0) + rp[rn++] = (mp_limb_t) sp[j] >> (bits - shift); + } + } + } + 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_size, v->_mp_size); + MP_SIZE_T_SWAP (u->_mp_alloc, v->_mp_alloc); + MP_PTR_SWAP (u->_mp_d, v->_mp_d); +} + + +/* 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_common_scan (r->_mp_d[0], 0, r->_mp_d, 0, 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 vl = tv->_mp_d[0]; + mp_limb_t ul = mpz_tdiv_ui (tu, vl); + mpz_set_ui (g, mpn_gcd_11 (ul, vl)); + 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_setbit (t0, uz); + 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_mul_2exp (t0, t0, shift); + mpz_mul_2exp (s0, s0, 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; + } + } + + /* 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; + 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); + mpz_setbit (t, mpz_sizeinbase (y, 2) / z + 1); + + 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 = 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; + /* y == 1 means that the previous y was a non-trivial square root + of 1 (mod n). y == 0 means that n is a power of the base. + In either case, n is not prime. */ + if (mpz_cmp_ui (y, 1) <= 0) + return 0; + } + 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; + k = mpz_scan1 (nm1, 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 = 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); + 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_import: 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..c00568c2568 --- /dev/null +++ b/lib/mini-gmp.h @@ -0,0 +1,308 @@ +/* mini-gmp, a minimalistic implementation of a GNU GMP subset. + +Copyright 2011-2015, 2017, 2019 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 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 3 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 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 */ +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/mktime.c b/lib/mktime.c index a13fa27e2bc..92c00b2b14b 100644 --- a/lib/mktime.c +++ b/lib/mktime.c @@ -141,7 +141,7 @@ 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 __time64_t and long_int. */ @@ -211,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); diff --git a/lib/nstrftime.c b/lib/nstrftime.c index 667c7ddc56e..28b539dc2f2 100644 --- a/lib/nstrftime.c +++ b/lib/nstrftime.c @@ -68,16 +68,9 @@ extern char *tzname[]; #include <string.h> #include <stdbool.h> +#include "attribute.h" #include <intprops.h> -#ifndef FALLTHROUGH -# if __GNUC__ < 7 -# define FALLTHROUGH ((void) 0) -# else -# define FALLTHROUGH __attribute__ ((__fallthrough__)) -# endif -#endif - #ifdef COMPILE_WIDE # include <endian.h> # define CHAR_T wchar_t @@ -113,7 +106,7 @@ extern char *tzname[]; #define SHR(a, b) \ (-1 >> 1 == -1 \ ? (a) >> (b) \ - : (a) / (1 << (b)) - ((a) % (1 << (b)) < 0)) + : ((a) + ((a) < 0)) / (1 << (b)) - ((a) < 0)) #define TM_YEAR_BASE 1900 @@ -348,8 +341,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); @@ -927,9 +920,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_YEARISH (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'): @@ -1138,8 +1133,8 @@ __strftime_internal (STREAM_OR_CHAR_T *s, STRFTIME_ARG (size_t maxsize) int ndigs = ns_digits; while (width < ndigs || (1 < ndigs && n % 10 == 0)) ndigs--, n /= 10; - for (int i = ndigs; 0 < i; i--) - buf[i - 1] = n % 10 + L_('0'), 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); diff --git a/lib/open.c b/lib/open.c index 487194f6652..751b42d7dcf 100644 --- a/lib/open.c +++ b/lib/open.c @@ -110,7 +110,9 @@ open (const char *filename, int flags, ...) 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] == '/') @@ -122,7 +124,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) { diff --git a/lib/openat-proc.c b/lib/openat-proc.c index 9111cd3d7ee..b5aaee8b1d3 100644 --- a/lib/openat-proc.c +++ b/lib/openat-proc.c @@ -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 7589150f34f..824ce560e34 100644 --- a/lib/openat.h +++ b/lib/openat.h @@ -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); diff --git a/lib/putenv.c b/lib/putenv.c deleted file mode 100644 index 9e862e63d3d..00000000000 --- a/lib/putenv.c +++ /dev/null @@ -1,194 +0,0 @@ -/* Copyright (C) 1991, 1994, 1997-1998, 2000, 2003-2020 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 __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 __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/regex.c b/lib/regex.c index 6bdd77f50b2..88173bb1052 100644 --- a/lib/regex.c +++ b/lib/regex.c @@ -17,6 +17,8 @@ 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> diff --git a/lib/regex_internal.h b/lib/regex_internal.h index 5c9cbf3b4fe..f6ebfb003e8 100644 --- a/lib/regex_internal.h +++ b/lib/regex_internal.h @@ -141,6 +141,24 @@ #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 @@ -164,36 +182,8 @@ typedef __re_size_t re_hashval_t; 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. For portability to hosts with - padding bits, do not use '(sizeof (bitset_word_t) * CHAR_BIT)'; - instead, deduce it directly from BITSET_WORD_MAX. Avoid - greater-than-32-bit integers and unconditional shifts by more than - 31 bits, as they're not portable. */ -#if BITSET_WORD_MAX == 0xffffffffUL -# define BITSET_WORD_BITS 32 -#elif BITSET_WORD_MAX >> 31 >> 4 == 1 -# define BITSET_WORD_BITS 36 -#elif BITSET_WORD_MAX >> 31 >> 16 == 1 -# define BITSET_WORD_BITS 48 -#elif BITSET_WORD_MAX >> 31 >> 28 == 1 -# define BITSET_WORD_BITS 60 -#elif BITSET_WORD_MAX >> 31 >> 31 >> 1 == 1 -# define BITSET_WORD_BITS 64 -#elif BITSET_WORD_MAX >> 31 >> 31 >> 9 == 1 -# define BITSET_WORD_BITS 72 -#elif BITSET_WORD_MAX >> 31 >> 31 >> 31 >> 31 >> 3 == 1 -# define BITSET_WORD_BITS 128 -#elif BITSET_WORD_MAX >> 31 >> 31 >> 31 >> 31 >> 31 >> 31 >> 31 >> 31 >> 7 == 1 -# define BITSET_WORD_BITS 256 -#elif BITSET_WORD_MAX >> 31 >> 31 >> 31 >> 31 >> 31 >> 31 >> 31 >> 31 >> 7 > 1 -# define BITSET_WORD_BITS 257 /* any value > SBC_MAX will do here */ -# if BITSET_WORD_BITS <= SBC_MAX -# error "Invalid SBC_MAX" -# endif -#else -# error "Add case for new bitset_word_t size" -#endif +/* 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) @@ -601,9 +591,8 @@ struct re_backref_cache_entry Idx str_idx; Idx subexp_from; Idx subexp_to; + bitset_word_t eps_reachable_subexps_map; char more; - char unused; - unsigned short int eps_reachable_subexps_map; }; typedef struct diff --git a/lib/sha1.c b/lib/sha1.c index 68e74ff3f98..bacf29c4051 100644 --- a/lib/sha1.c +++ b/lib/sha1.c @@ -1,8 +1,7 @@ /* 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-2020 Free Software - Foundation, Inc. + Copyright (C) 2000-2001, 2003-2006, 2008-2020 Free Software Foundation, Inc. This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the diff --git a/lib/sha1.h b/lib/sha1.h index 2c9c2d4a5e2..b76788487c3 100644 --- a/lib/sha1.h +++ b/lib/sha1.h @@ -71,20 +71,21 @@ 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. diff --git a/lib/sha256.h b/lib/sha256.h index 1bc61d437c9..750d78a2696 100644 --- a/lib/sha256.h +++ b/lib/sha256.h @@ -70,23 +70,27 @@ 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. diff --git a/lib/sha512.h b/lib/sha512.h index aaf35a5f7d8..21c2f580147 100644 --- a/lib/sha512.h +++ b/lib/sha512.h @@ -70,8 +70,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,16 +80,20 @@ 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. diff --git a/lib/sig2str.c b/lib/sig2str.c index 47c6cfcf95e..905daea2f20 100644 --- a/lib/sig2str.c +++ b/lib/sig2str.c @@ -1,7 +1,6 @@ /* sig2str.c -- convert between signal names and numbers - Copyright (C) 2002, 2004, 2006, 2009-2020 Free Software Foundation, - Inc. + Copyright (C) 2002, 2004, 2006, 2009-2020 Free Software Foundation, Inc. This program is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by diff --git a/lib/signal.in.h b/lib/signal.in.h index 42e1897f1ea..c94b053d6af 100644 --- a/lib/signal.in.h +++ b/lib/signal.in.h @@ -133,16 +133,24 @@ 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@ || 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); @@ -295,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 @@ -322,6 +334,12 @@ _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 diff --git a/lib/stdalign.in.h b/lib/stdalign.in.h index 2f53411e16c..cd786bed2cd 100644 --- a/lib/stdalign.in.h +++ b/lib/stdalign.in.h @@ -102,7 +102,7 @@ # define _Alignas(a) alignas (a) # elif ((defined __APPLE__ && defined __MACH__ \ ? 4 < __GNUC__ + (1 <= __GNUC_MINOR__) \ - : __GNUC__) \ + : __GNUC__ && !defined __ibmxl__) \ || (__ia64 && (61200 <= __HP_cc || 61200 <= __HP_aCC)) \ || __ICC || 0x590 <= __SUNPRO_C || 0x0600 <= __xlC__) # define _Alignas(a) __attribute__ ((__aligned__ (a))) diff --git a/lib/stddef.in.h b/lib/stddef.in.h index e146063c026..2e50a1f01e8 100644 --- a/lib/stddef.in.h +++ b/lib/stddef.in.h @@ -83,20 +83,26 @@ /* Some platforms lack max_align_t. The check for _GCC_MAX_ALIGN_T is a hack in case the configure-time test was done with g++ even though - we are currently compiling with gcc. */ -#if ! (@HAVE_MAX_ALIGN_T@ || defined _GCC_MAX_ALIGN_T) -# if !GNULIB_defined_max_align_t + we are currently compiling with gcc. + On MSVC, max_align_t is defined only in C++ mode, after <cstddef> was + included. Its definition is good since it has an alignment of 8 (on x86 + and x86_64). */ +#if defined _MSC_VER && defined __cplusplus +# include <cstddef> +#else +# if ! (@HAVE_MAX_ALIGN_T@ || defined _GCC_MAX_ALIGN_T) +# if !GNULIB_defined_max_align_t /* On the x86, the maximum storage alignment of double, long, etc. is 4, but GCC's C11 ABI for x86 says that max_align_t has an alignment of 8, and the C11 standard allows this. Work around this problem by using __alignof__ (which returns 8 for double) rather than _Alignof (which returns 4), and align each union member accordingly. */ -# ifdef __GNUC__ -# define _GL_STDDEF_ALIGNAS(type) \ - __attribute__ ((__aligned__ (__alignof__ (type)))) -# else -# define _GL_STDDEF_ALIGNAS(type) /* */ -# endif +# ifdef __GNUC__ +# define _GL_STDDEF_ALIGNAS(type) \ + __attribute__ ((__aligned__ (__alignof__ (type)))) +# else +# define _GL_STDDEF_ALIGNAS(type) /* */ +# endif typedef union { char *__p _GL_STDDEF_ALIGNAS (char *); @@ -104,8 +110,9 @@ typedef union long double __ld _GL_STDDEF_ALIGNAS (long double); long int __i _GL_STDDEF_ALIGNAS (long int); } rpl_max_align_t; -# define max_align_t rpl_max_align_t -# define GNULIB_defined_max_align_t 1 +# define max_align_t rpl_max_align_t +# define GNULIB_defined_max_align_t 1 +# endif # endif #endif diff --git a/lib/stdint.in.h b/lib/stdint.in.h index a83bc45c79c..994c0c777c0 100644 --- a/lib/stdint.in.h +++ b/lib/stdint.in.h @@ -188,7 +188,7 @@ typedef long int gl_int64_t; typedef __int64 gl_int64_t; # define int64_t gl_int64_t # define GL_INT64_T -# elif @HAVE_LONG_LONG_INT@ +# else # undef int64_t typedef long long int gl_int64_t; # define int64_t gl_int64_t @@ -209,7 +209,7 @@ typedef unsigned long int gl_uint64_t; typedef unsigned __int64 gl_uint64_t; # define uint64_t gl_uint64_t # define GL_UINT64_T -# elif @HAVE_UNSIGNED_LONG_LONG_INT@ +# else # undef uint64_t typedef unsigned long long int gl_uint64_t; # define uint64_t gl_uint64_t @@ -333,7 +333,7 @@ typedef unsigned long int gl_uintptr_t; # ifndef INTMAX_MAX # undef INTMAX_C # undef intmax_t -# if @HAVE_LONG_LONG_INT@ && LONG_MAX >> 30 == 1 +# if LONG_MAX >> 30 == 1 typedef long long int gl_intmax_t; # define intmax_t gl_intmax_t # elif defined GL_INT64_T @@ -347,7 +347,7 @@ typedef long int gl_intmax_t; # ifndef UINTMAX_MAX # undef UINTMAX_C # undef uintmax_t -# if @HAVE_UNSIGNED_LONG_LONG_INT@ && ULONG_MAX >> 31 == 1 +# if ULONG_MAX >> 31 == 1 typedef unsigned long long int gl_uintmax_t; # define uintmax_t gl_uintmax_t # elif defined GL_UINT64_T @@ -647,21 +647,21 @@ typedef int _verify_intmax_size[sizeof (intmax_t) == sizeof (uintmax_t) # define INT64_C(x) x##L # elif defined _MSC_VER # define INT64_C(x) x##i64 -# elif @HAVE_LONG_LONG_INT@ +# else # define INT64_C(x) x##LL # endif # if ULONG_MAX >> 31 >> 31 >> 1 == 1 # define UINT64_C(x) x##UL # elif defined _MSC_VER # define UINT64_C(x) x##ui64 -# elif @HAVE_UNSIGNED_LONG_LONG_INT@ +# else # define UINT64_C(x) x##ULL # endif /* 7.18.4.2. Macros for greatest-width integer constants */ # ifndef INTMAX_C -# if @HAVE_LONG_LONG_INT@ && LONG_MAX >> 30 == 1 +# if LONG_MAX >> 30 == 1 # define INTMAX_C(x) x##LL # elif defined GL_INT64_T # define INTMAX_C(x) INT64_C(x) @@ -671,7 +671,7 @@ typedef int _verify_intmax_size[sizeof (intmax_t) == sizeof (uintmax_t) # endif # ifndef UINTMAX_C -# if @HAVE_UNSIGNED_LONG_LONG_INT@ && ULONG_MAX >> 31 == 1 +# if ULONG_MAX >> 31 == 1 # define UINTMAX_C(x) x##ULL # elif defined GL_UINT64_T # define UINTMAX_C(x) UINT64_C(x) diff --git a/lib/stdio.in.h b/lib/stdio.in.h index 6dc526eaab0..6c338dd6c0b 100644 --- a/lib/stdio.in.h +++ b/lib/stdio.in.h @@ -62,10 +62,12 @@ 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)) -#else -# define _GL_ATTRIBUTE_FORMAT(spec) /* empty */ +#ifndef _GL_ATTRIBUTE_FORMAT +# if __GNUC__ > 2 || (__GNUC__ == 2 && __GNUC_MINOR__ >= 7) +# define _GL_ATTRIBUTE_FORMAT(spec) __attribute__ ((__format__ spec)) +# else +# define _GL_ATTRIBUTE_FORMAT(spec) /* empty */ +# endif #endif /* _GL_ATTRIBUTE_FORMAT_PRINTF @@ -171,17 +173,17 @@ # if !(defined __cplusplus && defined GNULIB_NAMESPACE) # define dprintf rpl_dprintf # endif -_GL_FUNCDECL_RPL (dprintf, int, (int fd, const char *format, ...) +_GL_FUNCDECL_RPL (dprintf, int, (int fd, const char *restrict format, ...) _GL_ATTRIBUTE_FORMAT_PRINTF (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_FUNCDECL_SYS (dprintf, int, (int fd, const char *restrict format, ...) _GL_ATTRIBUTE_FORMAT_PRINTF (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 @@ -281,11 +283,14 @@ _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); @@ -298,11 +303,14 @@ _GL_CXXALIASWARN (fgets); # 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_CXXALIAS_RPL (fopen, FILE *, + (const char *restrict filename, const char *restrict mode)); # else -_GL_CXXALIAS_SYS (fopen, FILE *, (const char *filename, const char *mode)); +_GL_CXXALIAS_SYS (fopen, FILE *, + (const char *restrict filename, const char *restrict mode)); # endif # if __GLIBC__ >= 2 _GL_CXXALIASWARN (fopen); @@ -322,17 +330,21 @@ _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 (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); @@ -398,11 +410,14 @@ _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); @@ -415,11 +430,17 @@ _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); @@ -433,13 +454,16 @@ _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); @@ -458,12 +482,15 @@ _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); @@ -634,13 +661,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>, @@ -715,22 +745,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 @@ -754,18 +788,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); @@ -909,14 +947,14 @@ _GL_WARN_ON_USE (popen, "popen is buggy on some platforms - " # 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_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) @@ -928,14 +966,14 @@ _GL_CXXALIAS_RPL_1 (printf, __printf__, int, (const char *format, ...)); # define printf rpl_printf # endif _GL_FUNCDECL_RPL (printf, int, - (const char *format, ...) + (const char *restrict format, ...) _GL_ATTRIBUTE_FORMAT_PRINTF (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); @@ -1083,24 +1121,24 @@ _GL_WARN_ON_USE (renameat, "renameat is not portable - " # 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); @@ -1113,20 +1151,24 @@ _GL_CXXALIASWARN (scanf); # define snprintf rpl_snprintf # endif _GL_FUNCDECL_RPL (snprintf, int, - (char *str, size_t size, const char *format, ...) + (char *restrict str, size_t size, + const char *restrict format, ...) _GL_ATTRIBUTE_FORMAT_PRINTF (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, ...) + (char *restrict str, size_t size, + const char *restrict format, ...) _GL_ATTRIBUTE_FORMAT_PRINTF (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 _GL_CXXALIASWARN (snprintf); #elif defined GNULIB_POSIXCHECK @@ -1151,12 +1193,15 @@ _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, ...)); +_GL_FUNCDECL_RPL (sprintf, int, + (char *restrict str, const char *restrict format, ...) + _GL_ATTRIBUTE_FORMAT_PRINTF (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); @@ -1244,22 +1289,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 (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 (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 @@ -1276,21 +1326,28 @@ _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 (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); @@ -1313,14 +1370,17 @@ _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 _GL_CXXALIASWARN (vfscanf); #endif @@ -1333,20 +1393,21 @@ _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_FUNCDECL_RPL (vprintf, int, (const char *restrict format, va_list args) _GL_ATTRIBUTE_FORMAT_PRINTF (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); @@ -1368,12 +1429,12 @@ _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 _GL_CXXALIASWARN (vscanf); #endif @@ -1384,20 +1445,24 @@ _GL_CXXALIASWARN (vscanf); # define vsnprintf rpl_vsnprintf # endif _GL_FUNCDECL_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) _GL_ATTRIBUTE_FORMAT_PRINTF (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) + (char *restrict str, size_t size, + const char *restrict format, va_list args) _GL_ATTRIBUTE_FORMAT_PRINTF (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 _GL_CXXALIASWARN (vsnprintf); #elif defined GNULIB_POSIXCHECK @@ -1414,17 +1479,20 @@ _GL_WARN_ON_USE (vsnprintf, "vsnprintf is unportable - " # define vsprintf rpl_vsprintf # endif _GL_FUNCDECL_RPL (vsprintf, int, - (char *str, const char *format, va_list args) + (char *restrict str, + const char *restrict format, va_list args) _GL_ATTRIBUTE_FORMAT_PRINTF (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); diff --git a/lib/stdlib.in.h b/lib/stdlib.in.h index 1524277d799..59f9e6c71d1 100644 --- a/lib/stdlib.in.h +++ b/lib/stdlib.in.h @@ -1,7 +1,6 @@ /* A GNU-like <stdlib.h>. - Copyright (C) 1995, 2001-2004, 2006-2020 Free Software Foundation, - Inc. + Copyright (C) 1995, 2001-2004, 2006-2020 Free Software Foundation, Inc. This program is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by @@ -102,10 +101,12 @@ struct random_data /* 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) +# define _GL_ATTRIBUTE_PURE __attribute__ ((__pure__)) +# else +# define _GL_ATTRIBUTE_PURE /* empty */ +# endif #endif /* The definition of _Noreturn is copied here. */ @@ -202,6 +203,10 @@ _GL_FUNCDECL_SYS (canonicalize_file_name, char *, (const char *name) # endif _GL_CXXALIAS_SYS (canonicalize_file_name, char *, (const char *name)); # endif +# ifndef GNULIB_defined_canonicalize_file_name +# define GNULIB_defined_canonicalize_file_name \ + (!@HAVE_CANONICALIZE_FILE_NAME@ || @REPLACE_CANONICALIZE_FILE_NAME@) +# endif _GL_CXXALIASWARN (canonicalize_file_name); #elif defined GNULIB_POSIXCHECK # undef canonicalize_file_name @@ -308,13 +313,17 @@ _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 # if !@HAVE_MBTOWC@ -_GL_FUNCDECL_SYS (mbtowc, int, (wchar_t *pwc, const char *s, size_t n)); +_GL_FUNCDECL_SYS (mbtowc, int, + (wchar_t *restrict pwc, const char *restrict s, size_t n)); # endif -_GL_CXXALIAS_SYS (mbtowc, int, (wchar_t *pwc, const char *s, size_t n)); +_GL_CXXALIAS_SYS (mbtowc, int, + (wchar_t *restrict pwc, const char *restrict s, size_t n)); # endif # if __GLIBC__ >= 2 _GL_CXXALIASWARN (mbtowc); @@ -517,6 +526,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 @@ -600,7 +612,9 @@ _GL_CXXALIAS_RPL (random, long, (void)); # if !@HAVE_RANDOM@ _GL_FUNCDECL_SYS (random, long, (void)); # endif -_GL_CXXALIAS_SYS (random, long, (void)); +/* Need to cast, because on Haiku, the return type is + int. */ +_GL_CXXALIAS_SYS_CAST (random, long, (void)); # endif _GL_CXXALIASWARN (random); #elif defined GNULIB_POSIXCHECK @@ -767,9 +781,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 @@ -797,8 +813,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 @@ -854,15 +872,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 @@ -945,15 +967,19 @@ _GL_WARN_ON_USE (setenv, "setenv is unportable - " # define strtod rpl_strtod # endif # define GNULIB_defined_strtod_function 1 -_GL_FUNCDECL_RPL (strtod, double, (const char *str, char **endp) - _GL_ARG_NONNULL ((1))); -_GL_CXXALIAS_RPL (strtod, double, (const char *str, char **endp)); +_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); @@ -973,15 +999,19 @@ _GL_WARN_ON_USE (strtod, "strtod is unportable - " # define strtold rpl_strtold # endif # define GNULIB_defined_strtold_function 1 -_GL_FUNCDECL_RPL (strtold, long double, (const char *str, char **endp) - _GL_ARG_NONNULL ((1))); -_GL_CXXALIAS_RPL (strtold, long double, (const char *str, char **endp)); +_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 *str, char **endp) - _GL_ARG_NONNULL ((1))); +_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 *str, char **endp)); +_GL_CXXALIAS_SYS (strtold, long double, + (const char *restrict str, char **restrict endp)); # endif _GL_CXXALIASWARN (strtold); #elif defined GNULIB_POSIXCHECK @@ -1003,11 +1033,13 @@ _GL_WARN_ON_USE (strtold, "strtold is unportable - " to ERANGE. */ # 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 _GL_CXXALIAS_SYS (strtoll, long long, - (const char *string, char **endptr, int base)); + (const char *restrict string, char **restrict endptr, + int base)); _GL_CXXALIASWARN (strtoll); #elif defined GNULIB_POSIXCHECK # undef strtoll @@ -1028,11 +1060,13 @@ _GL_WARN_ON_USE (strtoll, "strtoll is unportable - " ERANGE. */ # 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 _GL_CXXALIAS_SYS (strtoull, unsigned long long, - (const char *string, char **endptr, int base)); + (const char *restrict string, char **restrict endptr, + int base)); _GL_CXXALIASWARN (strtoull); #elif defined GNULIB_POSIXCHECK # undef strtoull diff --git a/lib/strftime.h b/lib/strftime.h index 97a062c631d..e8501631573 100644 --- a/lib/strftime.h +++ b/lib/strftime.h @@ -25,7 +25,7 @@ extern "C" { 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 *, +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 2c04e5f4f71..aa9802791ee 100644 --- a/lib/string.in.h +++ b/lib/string.in.h @@ -54,10 +54,12 @@ /* 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) +# define _GL_ATTRIBUTE_PURE __attribute__ ((__pure__)) +# else +# define _GL_ATTRIBUTE_PURE /* empty */ +# endif #endif /* NetBSD 5.0 declares strsignal in <unistd.h>, not in <string.h>. */ @@ -132,11 +134,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); } */ @@ -332,9 +329,10 @@ _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 *, (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. */ @@ -411,11 +409,14 @@ _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); @@ -523,15 +524,17 @@ _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 *, (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 *, (const char *, const char *), + "strpbrk is unportable - " + "use gnulib module strpbrk for portability"); # endif #endif @@ -550,9 +553,10 @@ _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 *, (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. @@ -966,7 +970,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 diff --git a/lib/strtoimax.c b/lib/strtoimax.c index 95f6f3ff11f..a17b2f0a9d7 100644 --- a/lib/strtoimax.c +++ b/lib/strtoimax.c @@ -1,7 +1,7 @@ /* Convert string representation of a number into an intmax_t value. - Copyright (C) 1999, 2001-2004, 2006, 2009-2020 Free Software - Foundation, Inc. + Copyright (C) 1999, 2001-2004, 2006, 2009-2020 Free Software Foundation, + Inc. This program is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by @@ -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 a2e1dee99ee..02aafca44ea 100644 --- a/lib/strtol.c +++ b/lib/strtol.c @@ -1,7 +1,7 @@ /* Convert string representation of a number into an integer value. - Copyright (C) 1991-1992, 1994-1999, 2003, 2005-2007, 2009-2020 Free - Software Foundation, Inc. + Copyright (C) 1991-1992, 1994-1999, 2003, 2005-2007, 2009-2020 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. diff --git a/lib/strtoll.c b/lib/strtoll.c index 0b8e03c025c..3c7e8c002f0 100644 --- a/lib/strtoll.c +++ b/lib/strtoll.c @@ -1,6 +1,6 @@ /* Function to parse a 'long long int' from text. - Copyright (C) 1995-1997, 1999, 2001, 2009-2020 Free Software - Foundation, Inc. + Copyright (C) 1995-1997, 1999, 2001, 2009-2020 Free Software Foundation, + Inc. This file is part of the GNU C Library. This program is free software: you can redistribute it and/or modify diff --git a/lib/sys_random.in.h b/lib/sys_random.in.h new file mode 100644 index 00000000000..f14ac1f5723 --- /dev/null +++ b/lib/sys_random.in.h @@ -0,0 +1,92 @@ +/* Substitute for <sys/random.h>. + Copyright (C) 2020 Free Software Foundation, Inc. + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 3, or (at your option) + any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, see <https://www.gnu.org/licenses/>. */ + +# if __GNUC__ >= 3 +@PRAGMA_SYSTEM_HEADER@ +# endif +@PRAGMA_COLUMNS@ + +#ifndef _@GUARD_PREFIX@_SYS_RANDOM_H + +#if @HAVE_SYS_RANDOM_H@ + +/* 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_stat.in.h b/lib/sys_stat.in.h index c1e3243c1fe..89e167f6d1c 100644 --- a/lib/sys_stat.in.h +++ b/lib/sys_stat.in.h @@ -392,13 +392,25 @@ struct stat #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 @@ -443,18 +455,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@ @@ -499,34 +515,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 @@ -543,17 +557,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); @@ -766,7 +784,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@ diff --git a/lib/tempname.c b/lib/tempname.c index 7c46ad14078..cfb0fc42eca 100644 --- a/lib/tempname.c +++ b/lib/tempname.c @@ -1,25 +1,22 @@ -/* tempname.c - generate the name of a temporary file. +/* Copyright (C) 1991-2020 Free Software Foundation, Inc. + This file is part of the GNU C Library. - Copyright (C) 1991-2003, 2005-2007, 2009-2020 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 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 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 + 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 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 @@ -27,9 +24,6 @@ #include <assert.h> #include <errno.h> -#ifndef __set_errno -# define __set_errno(Val) errno = (Val) -#endif #include <stdio.h> #ifndef P_tmpdir @@ -53,51 +47,39 @@ #include <string.h> #include <fcntl.h> -#include <sys/time.h> #include <stdint.h> -#include <unistd.h> - +#include <sys/random.h> #include <sys/stat.h> #if _LIBC # define struct_stat64 struct stat64 +# define __secure_getenv __libc_secure_getenv #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) #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 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 +# include <random-bits.h> +# define RANDOM_BITS(Var) ((Var) = random_bits ()) +typedef uint32_t random_value; +# define RANDOM_VALUE_MAX UINT32_MAX +# define BASE_62_DIGITS 5 /* 62**5 < UINT32_MAX */ +# define BASE_62_POWER (62 * 62 * 62 * 62 * 62) /* 2**BASE_62_DIGITS */ +#else +/* Use getrandom if it works, falling back on a 64-bit linear + congruential generator that starts with whatever Var's value + happens to be. */ +# define RANDOM_BITS(Var) \ + ((void) (getrandom (&(Var), sizeof (Var), 0) == sizeof (Var) \ + || ((Var) = 2862933555777941757 * (Var) + 3037000493))) +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) #endif #if _LIBC @@ -173,18 +155,80 @@ __path_search (char *tmpl, size_t tmpl_len, const char *dir, const char *pfx, } #endif /* _LIBC */ +#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, void *flags _GL_UNUSED) +{ + return __mkdir (tmpl, S_IRUSR | S_IWUSR | S_IXUSR); +} + +static int +try_nocreate (char *tmpl, void *flags _GL_UNUSED) +{ + struct_stat64 st; + + if (__lxstat64 (_STAT_VER, tmpl, &st) == 0 || errno == EOVERFLOW) + __set_errno (EEXIST); + return errno == ENOENT ? 0 : -1; +} + /* 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. + + We use a clever algorithm to get hard-to-predict names. */ +#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; @@ -194,7 +238,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 @@ -205,44 +250,45 @@ __try_tempname (char *tmpl, int suffixlen, void *args, unsigned int attempts = ATTEMPTS_MIN; #endif + /* A random variable. */ + random_value v; + + /* How many random base-62 digits can currently be extracted from V. */ + int vdigits = 0; + + /* Least unfair value for V. If V is less than this, V can generate + BASE_62_DIGITS digits fairly. Otherwise it might be biased. */ + random_value const unfair_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]; - - /* 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 (); + XXXXXX = &tmpl[len - x_suffix_len - suffixlen]; - 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) + { + do + RANDOM_BITS (v); + while (unfair_min <= v); + + vdigits = BASE_62_DIGITS; + } + + XXXXXX[i] = letters[v % 62]; + v /= 62; + vdigits--; + } fd = tryfunc (tmpl, args); if (fd >= 0) @@ -259,66 +305,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 abb92650827..00dcbe4c93b 100644 --- a/lib/tempname.h +++ b/lib/tempname.h @@ -50,6 +50,9 @@ extern "C" { 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.in.h b/lib/time.in.h index 3f942b704dc..1d11650e77f 100644 --- a/lib/time.in.h +++ b/lib/time.in.h @@ -286,14 +286,17 @@ _GL_CXXALIASWARN (ctime); # 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); diff --git a/lib/time_r.c b/lib/time_r.c index 25068ad7276..e8fca2d5c44 100644 --- a/lib/time_r.c +++ b/lib/time_r.c @@ -1,7 +1,6 @@ /* Reentrant time functions like localtime_r. - Copyright (C) 2003, 2006-2007, 2010-2020 Free Software Foundation, - Inc. + Copyright (C) 2003, 2006-2007, 2010-2020 Free Software Foundation, Inc. This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by diff --git a/lib/unistd.in.h b/lib/unistd.in.h index ddb7c5771ba..a81a14fe873 100644 --- a/lib/unistd.in.h +++ b/lib/unistd.in.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> @@ -118,6 +118,17 @@ # include <netdb.h> #endif +/* 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 + /* 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__ \ @@ -141,7 +152,7 @@ /* Get getopt(), optarg, optind, opterr, optopt. */ -#if @GNULIB_UNISTD_H_GETOPT@ && !defined _GL_SYSTEM_GETOPT +#if @GNULIB_GETOPT_POSIX@ && @GNULIB_UNISTD_H_GETOPT@ && !defined _GL_SYSTEM_GETOPT # include <getopt-cdefs.h> # include <getopt-pfx-core.h> #endif @@ -397,9 +408,6 @@ _GL_WARN_ON_USE (dup, "dup is unportable - " _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)); -# endif _GL_CXXALIAS_SYS (dup2, int, (int oldfd, int newfd)); # endif _GL_CXXALIASWARN (dup2); @@ -763,6 +771,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. @@ -905,6 +929,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. */ @@ -1365,18 +1394,22 @@ _GL_CXXALIASWARN (read); # 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 @@ -1394,18 +1427,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 @@ -1672,7 +1709,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 diff --git a/lib/utimensat.c b/lib/utimensat.c new file mode 100644 index 00000000000..63788d56480 --- /dev/null +++ b/lib/utimensat.c @@ -0,0 +1,160 @@ +/* Set the access and modification time of a file relative to directory fd. + Copyright (C) 2009-2020 Free Software Foundation, Inc. + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see <https://www.gnu.org/licenses/>. */ + +/* written by Eric Blake */ + +#include <config.h> + +/* Specification. */ +#include <sys/stat.h> + +#include <errno.h> +#include <fcntl.h> +#include <stdlib.h> + +#include "stat-time.h" +#include "timespec.h" +#include "utimens.h" + +#if HAVE_UTIMENSAT + +# undef 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) +{ +# 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 + 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 diff --git a/lib/verify.h b/lib/verify.h index d9ab89a570c..f1097612704 100644 --- a/lib/verify.h +++ b/lib/verify.h @@ -277,10 +277,22 @@ template <int w> #endif /* Assume that R always holds. Behavior is undefined if R is false, - fails to evaluate, or has side effects. Although assuming R can - help a compiler generate better code or diagnostics, performance - can suffer if R uses hard-to-optimize features such as function - calls not inlined by the compiler. */ + 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)'. + + 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 _GL_HAS_BUILTIN_UNREACHABLE # define assume(R) ((R) ? (void) 0 : __builtin_unreachable ()) diff --git a/lib/warn-on-use.h b/lib/warn-on-use.h index 1be2cbb9570..23c10fdd122 100644 --- a/lib/warn-on-use.h +++ b/lib/warn-on-use.h @@ -100,23 +100,28 @@ _GL_WARN_EXTERN_C int _gl_warn_on_use #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. + is like _GL_WARN_ON_USE (function, "string"), 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__) +# if !defined __cplusplus # define _GL_WARN_ON_USE_CXX(function,rettype,parameters_and_attributes,msg) \ + _GL_WARN_ON_USE (function, msg) +# else +# 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 +# elif __GNUC__ >= 3 && GNULIB_STRICT_CHECKING /* Verify the existence of the function. */ -# define _GL_WARN_ON_USE_CXX(function,rettype,parameters_and_attributes,msg) \ +# 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) \ +# else /* Unsupported. */ +# define _GL_WARN_ON_USE_CXX(function,rettype,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 6e007b566db..13ee23031a0 100644 --- a/lib/xalloc-oversized.h +++ b/lib/xalloc-oversized.h @@ -1,7 +1,6 @@ /* xalloc-oversized.h -- memory allocation size checking - Copyright (C) 1990-2000, 2003-2004, 2006-2020 Free Software - Foundation, Inc. + Copyright (C) 1990-2000, 2003-2004, 2006-2020 Free Software Foundation, Inc. This program is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by |