pmt: initial 3.0.2 update

This commit is contained in:
2024-12-14 10:25:23 +03:00
parent 686ef38598
commit 7f8090bb1f
1292 changed files with 500876 additions and 2823 deletions

View File

@@ -0,0 +1,293 @@
/* argmatch.c -- find a match for a string in an array
Copyright (C) 1990, 1998-1999, 2001-2007, 2009-2024 Free Software
Foundation, Inc.
This 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 David MacKenzie <djm@ai.mit.edu>
Modified by Akim Demaille <demaille@inf.enst.fr> */
#include <config.h>
/* Specification. */
#include "argmatch.h"
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#define _(msgid) gettext (msgid)
#include <error.h>
#include "quotearg.h"
#if USE_UNLOCKED_IO
# include "unlocked-io.h"
#endif
/* When reporting an invalid argument, show nonprinting characters
by using the quoting style ARGMATCH_QUOTING_STYLE. Do not use
literal_quoting_style. */
#ifndef ARGMATCH_QUOTING_STYLE
# define ARGMATCH_QUOTING_STYLE locale_quoting_style
#endif
/* Non failing version of argmatch call this function after failing. */
#ifndef ARGMATCH_DIE
# include "exitfail.h"
# define ARGMATCH_DIE exit (exit_failure)
#endif
#ifdef ARGMATCH_DIE_DECL
ARGMATCH_DIE_DECL;
#endif
static void
__argmatch_die (void)
{
ARGMATCH_DIE;
}
/* Used by XARGMATCH. See description in argmatch.h.
Default to __argmatch_die, but allow caller to change this at run-time. */
argmatch_exit_fn argmatch_die = __argmatch_die;
/* If ARG is an unambiguous match for an element of the
NULL-terminated array ARGLIST, return the index in ARGLIST
of the matched element, else -1 if it does not match any element
or -2 if it is ambiguous (is a prefix of more than one element).
If VALLIST is none null, use it to resolve ambiguities limited to
synonyms, i.e., for
"yes", "yop" -> 0
"no", "nope" -> 1
"y" is a valid argument, for 0, and "n" for 1. */
ptrdiff_t
argmatch (const char *arg, const char *const *arglist,
const void *vallist, size_t valsize)
{
size_t i; /* Temporary index in ARGLIST. */
size_t arglen; /* Length of ARG. */
ptrdiff_t matchind = -1; /* Index of first nonexact match. */
bool ambiguous = false; /* If true, multiple nonexact match(es). */
arglen = strlen (arg);
/* Test all elements for either exact match or abbreviated matches. */
for (i = 0; arglist[i]; i++)
{
if (!strncmp (arglist[i], arg, arglen))
{
if (strlen (arglist[i]) == arglen)
/* Exact match found. */
return i;
else if (matchind == -1)
/* First nonexact match found. */
matchind = i;
else
{
/* Second nonexact match found. */
if (vallist == NULL
|| memcmp ((char const *) vallist + valsize * matchind,
(char const *) vallist + valsize * i, valsize))
{
/* There is a real ambiguity, or we could not
disambiguate. */
ambiguous = true;
}
}
}
}
if (ambiguous)
return -2;
else
return matchind;
}
ptrdiff_t
argmatch_exact (const char *arg, const char *const *arglist)
{
size_t i;
/* Test elements for exact match. */
for (i = 0; arglist[i]; i++)
{
if (!strcmp (arglist[i], arg))
return i;
}
return -1;
}
/* Error reporting for argmatch.
CONTEXT is a description of the type of entity that was being matched.
VALUE is the invalid value that was given.
PROBLEM is the return value from argmatch. */
void
argmatch_invalid (const char *context, const char *value, ptrdiff_t problem)
{
char const *format = (problem == -1
? _("invalid argument %s for %s")
: _("ambiguous argument %s for %s"));
error (0, 0, format, quotearg_n_style (0, ARGMATCH_QUOTING_STYLE, value),
quote_n (1, context));
}
/* List the valid arguments for argmatch.
ARGLIST is the same as in argmatch.
VALLIST is a pointer to an array of values.
VALSIZE is the size of the elements of VALLIST */
void
argmatch_valid (const char *const *arglist,
const void *vallist, size_t valsize)
{
size_t i;
const char *last_val = NULL;
/* We try to put synonyms on the same line. The assumption is that
synonyms follow each other */
fputs (_("Valid arguments are:"), stderr);
for (i = 0; arglist[i]; i++)
if ((i == 0)
|| memcmp (last_val, (char const *) vallist + valsize * i, valsize))
{
fprintf (stderr, "\n - %s", quote (arglist[i]));
last_val = (char const *) vallist + valsize * i;
}
else
{
fprintf (stderr, ", %s", quote (arglist[i]));
}
putc ('\n', stderr);
}
/* Never failing versions of the previous functions.
CONTEXT is the context for which argmatch is called (e.g.,
"--version-control", or "$VERSION_CONTROL" etc.). Upon failure,
calls the (supposed never to return) function EXIT_FN. */
ptrdiff_t
__xargmatch_internal (const char *context,
const char *arg, const char *const *arglist,
const void *vallist, size_t valsize,
argmatch_exit_fn exit_fn,
bool allow_abbreviation)
{
ptrdiff_t res;
if (allow_abbreviation)
res = argmatch (arg, arglist, vallist, valsize);
else
res = argmatch_exact (arg, arglist);
if (res >= 0)
/* Success. */
return res;
/* We failed. Explain why. */
argmatch_invalid (context, arg, res);
argmatch_valid (arglist, vallist, valsize);
(*exit_fn) ();
return -1; /* To please the compilers. */
}
/* Look for VALUE in VALLIST, an array of objects of size VALSIZE and
return the first corresponding argument in ARGLIST */
const char *
argmatch_to_argument (const void *value,
const char *const *arglist,
const void *vallist, size_t valsize)
{
size_t i;
for (i = 0; arglist[i]; i++)
if (!memcmp (value, (char const *) vallist + valsize * i, valsize))
return arglist[i];
return NULL;
}
#ifdef TEST
/*
* Based on "getversion.c" by David MacKenzie <djm@gnu.ai.mit.edu>
*/
/* When to make backup files. */
enum backup_type
{
/* Never make backups. */
no_backups,
/* Make simple backups of every file. */
simple_backups,
/* Make numbered backups of files that already have numbered backups,
and simple backups of the others. */
numbered_existing_backups,
/* Make numbered backups of every file. */
numbered_backups
};
/* Two tables describing arguments (keys) and their corresponding
values */
static const char *const backup_args[] =
{
"no", "none", "off",
"simple", "never",
"existing", "nil",
"numbered", "t",
0
};
static const enum backup_type backup_vals[] =
{
no_backups, no_backups, no_backups,
simple_backups, simple_backups,
numbered_existing_backups, numbered_existing_backups,
numbered_backups, numbered_backups
};
int
main (int argc, const char *const *argv)
{
const char *cp;
enum backup_type backup_type = no_backups;
if (argc > 2)
{
fprintf (stderr, "Usage: %s [VERSION_CONTROL]\n", getprogname ());
exit (1);
}
if ((cp = getenv ("VERSION_CONTROL")))
backup_type = XARGMATCH ("$VERSION_CONTROL", cp,
backup_args, backup_vals);
if (argc == 2)
backup_type = XARGMATCH (getprogname (), argv[1],
backup_args, backup_vals);
printf ("The version control is '%s'\n",
ARGMATCH_TO_ARGUMENT (&backup_type, backup_args, backup_vals));
return 0;
}
#endif

View File

@@ -0,0 +1,70 @@
/* basename.c -- return the last element in a file name
Copyright (C) 1990, 1998-2001, 2003-2006, 2009-2024 Free Software
Foundation, Inc.
This file is free software: you can redistribute it and/or modify
it under the terms of the GNU Lesser General Public License as
published by the Free Software Foundation; either version 2.1 of the
License, or (at your option) any later version.
This file is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU Lesser General Public License for more details.
You should have received a copy of the GNU Lesser General Public License
along with this program. If not, see <https://www.gnu.org/licenses/>. */
#include <config.h>
/* Specification. */
#include "basename-lgpl.h"
#include <string.h>
#include "filename.h"
char *
last_component (char const *name)
{
char const *base = name + FILE_SYSTEM_PREFIX_LEN (name);
char const *p;
bool last_was_slash = false;
while (ISSLASH (*base))
base++;
for (p = base; *p; p++)
{
if (ISSLASH (*p))
last_was_slash = true;
else if (last_was_slash)
{
base = p;
last_was_slash = false;
}
}
return (char *) base;
}
size_t
base_len (char const *name)
{
size_t len;
size_t prefix_len = FILE_SYSTEM_PREFIX_LEN (name);
for (len = strlen (name); 1 < len && ISSLASH (name[len - 1]); len--)
continue;
if (DOUBLE_SLASH_IS_DISTINCT_ROOT && len == 1
&& ISSLASH (name[0]) && ISSLASH (name[1]) && ! name[2])
return 2;
if (FILE_SYSTEM_DRIVE_PREFIX_CAN_BE_RELATIVE && prefix_len
&& len == prefix_len && ISSLASH (name[prefix_len]))
return prefix_len + 1;
return len;
}

View File

@@ -0,0 +1,64 @@
/* basename.c -- return the last element in a file name
Copyright (C) 1990, 1998-2001, 2003-2006, 2009-2024 Free Software
Foundation, Inc.
This 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 "dirname.h"
#include <string.h>
#include "xalloc.h"
char *
base_name (char const *name)
{
char const *base = last_component (name);
idx_t length;
int dotslash_len;
if (*base)
{
length = base_len (base);
/* Collapse a sequence of trailing slashes into one. */
length += ISSLASH (base[length]);
/* On systems with drive letters, "a/b:c" must return "./b:c" rather
than "b:c" to avoid confusion with a drive letter. On systems
with pure POSIX semantics, this is not an issue. */
dotslash_len = FILE_SYSTEM_PREFIX_LEN (base) != 0 ? 2 : 0;
}
else
{
/* There is no last component, so NAME is a file system root or
the empty string. */
base = name;
length = base_len (base);
dotslash_len = 0;
}
char *p = ximalloc (dotslash_len + length + 1);
if (dotslash_len)
{
p[0] = '.';
p[1] = '/';
}
/* Finally, copy the basename. */
memcpy (p + dotslash_len, base, length);
p[dotslash_len + length] = '\0';
return p;
}

View File

@@ -0,0 +1,47 @@
/* Convert unibyte character to wide character.
Copyright (C) 2008, 2010-2024 Free Software Foundation, Inc.
Written by Bruno Haible <bruno@clisp.org>, 2008.
This file is free software: you can redistribute it and/or modify
it under the terms of the GNU Lesser General Public License as
published by the Free Software Foundation; either version 2.1 of the
License, or (at your option) any later version.
This file is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU Lesser General Public License for more details.
You should have received a copy of the GNU Lesser General Public License
along with this program. If not, see <https://www.gnu.org/licenses/>. */
#include <config.h>
/* Specification. */
#include <wchar.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
wint_t
btowc (int c)
{
if (c != EOF)
{
char buf[1];
wchar_t wc;
buf[0] = c;
#if HAVE_MBRTOWC
mbstate_t state;
mbszero (&state);
size_t ret = mbrtowc (&wc, buf, 1, &state);
if (!(ret == (size_t)(-1) || ret == (size_t)(-2)))
#else
if (mbtowc (&wc, buf, 1) >= 0)
#endif
return wc;
}
return WEOF;
}

View File

@@ -0,0 +1,21 @@
/* Character handling in C locale.
Copyright (C) 2003-2024 Free Software Foundation, Inc.
This file is free software: you can redistribute it and/or modify
it under the terms of the GNU Lesser General Public License as
published by the Free Software Foundation; either version 2.1 of the
License, or (at your option) any later version.
This file is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU Lesser General Public License for more details.
You should have received a copy of the GNU Lesser General Public License
along with this program. If not, see <https://www.gnu.org/licenses/>. */
#include <config.h>
#define C_CTYPE_INLINE _GL_EXTERN_INLINE
#include "c-ctype.h"

View File

@@ -0,0 +1,56 @@
/* c-strcasecmp.c -- case insensitive string comparator in C locale
Copyright (C) 1998-1999, 2005-2006, 2009-2024 Free Software Foundation, Inc.
This file is free software: you can redistribute it and/or modify
it under the terms of the GNU Lesser General Public License as
published by the Free Software Foundation; either version 2.1 of the
License, or (at your option) any later version.
This file is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU Lesser General Public License for more details.
You should have received a copy of the GNU Lesser General Public License
along with this program. If not, see <https://www.gnu.org/licenses/>. */
#include <config.h>
/* Specification. */
#include "c-strcase.h"
#include <limits.h>
#include "c-ctype.h"
int
c_strcasecmp (const char *s1, const char *s2)
{
register const unsigned char *p1 = (const unsigned char *) s1;
register const unsigned char *p2 = (const unsigned char *) s2;
unsigned char c1, c2;
if (p1 == p2)
return 0;
do
{
c1 = c_tolower (*p1);
c2 = c_tolower (*p2);
if (c1 == '\0')
break;
++p1;
++p2;
}
while (c1 == c2);
if (UCHAR_MAX <= INT_MAX)
return c1 - c2;
else
/* On machines where 'char' and 'int' are types of the same size, the
difference of two 'unsigned char' values - including the sign bit -
doesn't fit in an 'int'. */
return _GL_CMP (c1, c2);
}

View File

@@ -0,0 +1,56 @@
/* c-strncasecmp.c -- case insensitive string comparator in C locale
Copyright (C) 1998-1999, 2005-2006, 2009-2024 Free Software Foundation, Inc.
This file is free software: you can redistribute it and/or modify
it under the terms of the GNU Lesser General Public License as
published by the Free Software Foundation; either version 2.1 of the
License, or (at your option) any later version.
This file is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU Lesser General Public License for more details.
You should have received a copy of the GNU Lesser General Public License
along with this program. If not, see <https://www.gnu.org/licenses/>. */
#include <config.h>
/* Specification. */
#include "c-strcase.h"
#include <limits.h>
#include "c-ctype.h"
int
c_strncasecmp (const char *s1, const char *s2, size_t n)
{
register const unsigned char *p1 = (const unsigned char *) s1;
register const unsigned char *p2 = (const unsigned char *) s2;
unsigned char c1, c2;
if (p1 == p2 || n == 0)
return 0;
do
{
c1 = c_tolower (*p1);
c2 = c_tolower (*p2);
if (--n == 0 || c1 == '\0')
break;
++p1;
++p2;
}
while (c1 == c2);
if (UCHAR_MAX <= INT_MAX)
return c1 - c2;
else
/* On machines where 'char' and 'int' are types of the same size, the
difference of two 'unsigned char' values - including the sign bit -
doesn't fit in an 'int'. */
return _GL_CMP (c1, c2);
}

View File

@@ -0,0 +1,26 @@
/* Test 32-bit wide character for being printable.
Copyright (C) 2020-2024 Free Software Foundation, Inc.
This file is free software: you can redistribute it and/or modify
it under the terms of the GNU Lesser General Public License as
published by the Free Software Foundation; either version 2.1 of the
License, or (at your option) any later version.
This file is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU Lesser General Public License for more details.
You should have received a copy of the GNU Lesser General Public License
along with this program. If not, see <https://www.gnu.org/licenses/>. */
#include <config.h>
#define IN_C32ISPRINT
/* Specification. */
#include <uchar.h>
#define FUNC c32isprint
#define WCHAR_FUNC iswprint
#define UCS_FUNC uc_is_print
#include "c32is-impl.h"

View File

@@ -0,0 +1,469 @@
/* Return the canonical absolute name of a given file.
Copyright (C) 1996-2024 Free Software Foundation, Inc.
This file is part of the GNU C Library.
The GNU C Library is free software; you can redistribute it and/or
modify it under the terms of the GNU Lesser General Public
License as published by the Free Software Foundation; either
version 2.1 of the License, or (at your option) any later version.
The GNU C Library is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
Lesser General Public License for more details.
You should have received a copy of the GNU Lesser General Public
License along with the GNU C Library; if not, see
<https://www.gnu.org/licenses/>. */
#ifndef _LIBC
/* Don't use __attribute__ __nonnull__ in this compilation unit. Otherwise gcc
optimizes away the name == NULL test below. */
# define _GL_ARG_NONNULL(params)
# include <libc-config.h>
#endif
/* Specification. */
#include <stdlib.h>
#include <errno.h>
#include <fcntl.h>
#include <limits.h>
#include <string.h>
#include <sys/stat.h>
#include <unistd.h>
#include <eloop-threshold.h>
#include <filename.h>
#include <idx.h>
#include <intprops.h>
#include <scratch_buffer.h>
#ifdef _LIBC
# include <shlib-compat.h>
# define GCC_LINT 1
# define _GL_ATTRIBUTE_PURE __attribute__ ((__pure__))
#else
# define __canonicalize_file_name canonicalize_file_name
# define __realpath realpath
# define __strdup strdup
# include "pathmax.h"
# define __faccessat faccessat
# if defined _WIN32 && !defined __CYGWIN__
# define __getcwd _getcwd
# elif HAVE_GETCWD
# if IN_RELOCWRAPPER
/* When building the relocatable program wrapper, use the system's getcwd
function, not the gnulib override, otherwise we would get a link error.
*/
# undef getcwd
# endif
# if defined VMS && !defined getcwd
/* We want the directory in Unix syntax, not in VMS syntax.
The gnulib override of 'getcwd' takes 2 arguments; the original VMS
'getcwd' takes 3 arguments. */
# define __getcwd(buf, max) getcwd (buf, max, 0)
# else
# define __getcwd getcwd
# endif
# else
# define __getcwd(buf, max) getwd (buf)
# endif
# define __mempcpy mempcpy
# define __pathconf pathconf
# define __rawmemchr rawmemchr
# define __readlink readlink
# if IN_RELOCWRAPPER
/* When building the relocatable program wrapper, use the system's memmove
function, not the gnulib override, otherwise we would get a link error.
*/
# undef memmove
# endif
#endif
/* Suppress bogus GCC -Wmaybe-uninitialized warnings. */
#if defined GCC_LINT || defined lint
# define IF_LINT(Code) Code
#else
# define IF_LINT(Code) /* empty */
#endif
#ifndef DOUBLE_SLASH_IS_DISTINCT_ROOT
# define DOUBLE_SLASH_IS_DISTINCT_ROOT false
#endif
#if defined _LIBC || !FUNC_REALPATH_WORKS
/* Return true if FILE's existence can be shown, false (setting errno)
otherwise. Follow symbolic links. */
static bool
file_accessible (char const *file)
{
# if defined _LIBC || HAVE_FACCESSAT
return __faccessat (AT_FDCWD, file, F_OK, AT_EACCESS) == 0;
# else
struct stat st;
return stat (file, &st) == 0 || errno == EOVERFLOW;
# endif
}
/* True if concatenating END as a suffix to a file name means that the
code needs to check that the file name is that of a searchable
directory, since the canonicalize_filename_mode_stk code won't
check this later anyway when it checks an ordinary file name
component within END. END must either be empty, or start with a
slash. */
static bool _GL_ATTRIBUTE_PURE
suffix_requires_dir_check (char const *end)
{
/* If END does not start with a slash, the suffix is OK. */
while (ISSLASH (*end))
{
/* Two or more slashes act like a single slash. */
do
end++;
while (ISSLASH (*end));
switch (*end++)
{
default: return false; /* An ordinary file name component is OK. */
case '\0': return true; /* Trailing "/" is trouble. */
case '.': break; /* Possibly "." or "..". */
}
/* Trailing "/.", or "/.." even if not trailing, is trouble. */
if (!*end || (*end == '.' && (!end[1] || ISSLASH (end[1]))))
return true;
}
return false;
}
/* Append this to a file name to test whether it is a searchable directory.
On POSIX platforms "/" suffices, but "/./" is sometimes needed on
macOS 10.13 <https://bugs.gnu.org/30350>, and should also work on
platforms like AIX 7.2 that need at least "/.". */
# if defined _LIBC || defined LSTAT_FOLLOWS_SLASHED_SYMLINK
static char const dir_suffix[] = "/";
# else
static char const dir_suffix[] = "/./";
# endif
/* Return true if DIR is a searchable dir, false (setting errno) otherwise.
DIREND points to the NUL byte at the end of the DIR string.
Store garbage into DIREND[0 .. strlen (dir_suffix)]. */
static bool
dir_check (char *dir, char *dirend)
{
strcpy (dirend, dir_suffix);
return file_accessible (dir);
}
static idx_t
get_path_max (void)
{
# ifdef PATH_MAX
long int path_max = PATH_MAX;
# else
/* The caller invoked realpath with a null RESOLVED, even though
PATH_MAX is not defined as a constant. The glibc manual says
programs should not do this, and POSIX says the behavior is undefined.
Historically, glibc here used the result of pathconf, or 1024 if that
failed; stay consistent with this (dubious) historical practice. */
int err = errno;
long int path_max = __pathconf ("/", _PC_PATH_MAX);
__set_errno (err);
# endif
return path_max < 0 ? 1024 : path_max <= IDX_MAX ? path_max : IDX_MAX;
}
/* Scratch buffers used by realpath_stk and managed by __realpath. */
struct realpath_bufs
{
struct scratch_buffer rname;
struct scratch_buffer extra;
struct scratch_buffer link;
};
static char *
realpath_stk (const char *name, char *resolved, struct realpath_bufs *bufs)
{
char *dest;
char const *start;
char const *end;
int num_links = 0;
if (name == NULL)
{
/* As per Single Unix Specification V2 we must return an error if
either parameter is a null pointer. We extend this to allow
the RESOLVED parameter to be NULL in case the we are expected to
allocate the room for the return value. */
__set_errno (EINVAL);
return NULL;
}
if (name[0] == '\0')
{
/* As per Single Unix Specification V2 we must return an error if
the name argument points to an empty string. */
__set_errno (ENOENT);
return NULL;
}
char *rname = bufs->rname.data;
bool end_in_extra_buffer = false;
bool failed = true;
/* This is always zero for Posix hosts, but can be 2 for MS-Windows
and MS-DOS X:/foo/bar file names. */
idx_t prefix_len = FILE_SYSTEM_PREFIX_LEN (name);
if (!IS_ABSOLUTE_FILE_NAME (name))
{
while (!__getcwd (bufs->rname.data, bufs->rname.length))
{
if (errno != ERANGE)
{
dest = rname;
goto error;
}
if (!scratch_buffer_grow (&bufs->rname))
return NULL;
rname = bufs->rname.data;
}
dest = __rawmemchr (rname, '\0');
start = name;
prefix_len = FILE_SYSTEM_PREFIX_LEN (rname);
}
else
{
dest = __mempcpy (rname, name, prefix_len);
*dest++ = '/';
if (DOUBLE_SLASH_IS_DISTINCT_ROOT)
{
if (prefix_len == 0 /* implies ISSLASH (name[0]) */
&& ISSLASH (name[1]) && !ISSLASH (name[2]))
*dest++ = '/';
*dest = '\0';
}
start = name + prefix_len;
}
for ( ; *start; start = end)
{
/* Skip sequence of multiple file name separators. */
while (ISSLASH (*start))
++start;
/* Find end of component. */
for (end = start; *end && !ISSLASH (*end); ++end)
/* Nothing. */;
/* Length of this file name component; it can be zero if a file
name ends in '/'. */
idx_t startlen = end - start;
if (startlen == 0)
break;
else if (startlen == 1 && start[0] == '.')
/* nothing */;
else if (startlen == 2 && start[0] == '.' && start[1] == '.')
{
/* Back up to previous component, ignore if at root already. */
if (dest > rname + prefix_len + 1)
for (--dest; dest > rname && !ISSLASH (dest[-1]); --dest)
continue;
if (DOUBLE_SLASH_IS_DISTINCT_ROOT
&& dest == rname + 1 && !prefix_len
&& ISSLASH (*dest) && !ISSLASH (dest[1]))
dest++;
}
else
{
if (!ISSLASH (dest[-1]))
*dest++ = '/';
while (rname + bufs->rname.length - dest
< startlen + sizeof dir_suffix)
{
idx_t dest_offset = dest - rname;
if (!scratch_buffer_grow_preserve (&bufs->rname))
return NULL;
rname = bufs->rname.data;
dest = rname + dest_offset;
}
dest = __mempcpy (dest, start, startlen);
*dest = '\0';
char *buf;
ssize_t n;
while (true)
{
buf = bufs->link.data;
idx_t bufsize = bufs->link.length;
n = __readlink (rname, buf, bufsize - 1);
if (n < bufsize - 1)
break;
if (!scratch_buffer_grow (&bufs->link))
return NULL;
}
if (0 <= n)
{
if (++num_links > __eloop_threshold ())
{
__set_errno (ELOOP);
goto error;
}
buf[n] = '\0';
char *extra_buf = bufs->extra.data;
idx_t end_idx IF_LINT (= 0);
if (end_in_extra_buffer)
end_idx = end - extra_buf;
size_t len = strlen (end);
if (INT_ADD_OVERFLOW (len, n))
{
__set_errno (ENOMEM);
return NULL;
}
while (bufs->extra.length <= len + n)
{
if (!scratch_buffer_grow_preserve (&bufs->extra))
return NULL;
extra_buf = bufs->extra.data;
}
if (end_in_extra_buffer)
end = extra_buf + end_idx;
/* Careful here, end may be a pointer into extra_buf... */
memmove (&extra_buf[n], end, len + 1);
name = end = memcpy (extra_buf, buf, n);
end_in_extra_buffer = true;
if (IS_ABSOLUTE_FILE_NAME (buf))
{
idx_t pfxlen = FILE_SYSTEM_PREFIX_LEN (buf);
dest = __mempcpy (rname, buf, pfxlen);
*dest++ = '/'; /* It's an absolute symlink */
if (DOUBLE_SLASH_IS_DISTINCT_ROOT)
{
if (ISSLASH (buf[1]) && !ISSLASH (buf[2]) && !pfxlen)
*dest++ = '/';
*dest = '\0';
}
/* Install the new prefix to be in effect hereafter. */
prefix_len = pfxlen;
}
else
{
/* Back up to previous component, ignore if at root
already: */
if (dest > rname + prefix_len + 1)
for (--dest; dest > rname && !ISSLASH (dest[-1]); --dest)
continue;
if (DOUBLE_SLASH_IS_DISTINCT_ROOT && dest == rname + 1
&& ISSLASH (*dest) && !ISSLASH (dest[1]) && !prefix_len)
dest++;
}
}
else if (! (suffix_requires_dir_check (end)
? dir_check (rname, dest)
: errno == EINVAL))
goto error;
}
}
if (dest > rname + prefix_len + 1 && ISSLASH (dest[-1]))
--dest;
if (DOUBLE_SLASH_IS_DISTINCT_ROOT && dest == rname + 1 && !prefix_len
&& ISSLASH (*dest) && !ISSLASH (dest[1]))
dest++;
failed = false;
error:
*dest++ = '\0';
if (resolved != NULL)
{
/* Copy the full result on success or partial result if failure was due
to the path not existing or not being accessible. */
if ((!failed || errno == ENOENT || errno == EACCES)
&& dest - rname <= get_path_max ())
{
strcpy (resolved, rname);
if (failed)
return NULL;
else
return resolved;
}
if (!failed)
__set_errno (ENAMETOOLONG);
return NULL;
}
else
{
if (failed)
return NULL;
else
return __strdup (bufs->rname.data);
}
}
/* Return the canonical absolute name of file NAME. A canonical name
does not contain any ".", ".." components nor any repeated file name
separators ('/') or symlinks. All file name components must exist. If
RESOLVED is null, the result is malloc'd; otherwise, if the
canonical name is PATH_MAX chars or more, returns null with 'errno'
set to ENAMETOOLONG; if the name fits in fewer than PATH_MAX chars,
returns the name in RESOLVED. If the name cannot be resolved and
RESOLVED is non-NULL, it contains the name of the first component
that cannot be resolved. If the name can be resolved, RESOLVED
holds the same value as the value returned. */
char *
__realpath (const char *name, char *resolved)
{
struct realpath_bufs bufs;
scratch_buffer_init (&bufs.rname);
scratch_buffer_init (&bufs.extra);
scratch_buffer_init (&bufs.link);
char *result = realpath_stk (name, resolved, &bufs);
scratch_buffer_free (&bufs.link);
scratch_buffer_free (&bufs.extra);
scratch_buffer_free (&bufs.rname);
return result;
}
libc_hidden_def (__realpath)
versioned_symbol (libc, __realpath, realpath, GLIBC_2_3);
#endif /* defined _LIBC || !FUNC_REALPATH_WORKS */
#if SHLIB_COMPAT(libc, GLIBC_2_0, GLIBC_2_3)
char *
attribute_compat_text_section
__old_realpath (const char *name, char *resolved)
{
if (resolved == NULL)
{
__set_errno (EINVAL);
return NULL;
}
return __realpath (name, resolved);
}
compat_symbol (libc, __old_realpath, realpath, GLIBC_2_0);
#endif
char *
__canonicalize_file_name (const char *name)
{
return __realpath (name, NULL);
}
weak_alias (__canonicalize_file_name, canonicalize_file_name)

View File

@@ -0,0 +1,83 @@
/* cloexec.c - set or clear the close-on-exec descriptor flag
Copyright (C) 1991, 2004-2006, 2009-2024 Free Software Foundation, Inc.
This file is free software: you can redistribute it and/or modify
it under the terms of the GNU Lesser General Public License as
published by the Free Software Foundation; either version 2.1 of the
License, or (at your option) any later version.
This file is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU Lesser General Public License for more details.
You should have received a copy of the GNU Lesser General Public License
along with this program. If not, see <https://www.gnu.org/licenses/>. */
/* The code is taken from glibc/manual/llio.texi */
#include <config.h>
#include "cloexec.h"
#include <errno.h>
#include <fcntl.h>
#include <unistd.h>
/* Set the 'FD_CLOEXEC' flag of DESC if VALUE is true,
or clear the flag if VALUE is false.
Return 0 on success, or -1 on error with 'errno' set.
Note that on MingW, this function does NOT protect DESC from being
inherited into spawned children. Instead, either use dup_cloexec
followed by closing the original DESC, or use interfaces such as
open or pipe2 that accept flags like O_CLOEXEC to create DESC
non-inheritable in the first place. */
int
set_cloexec_flag (int desc, bool value)
{
#ifdef F_SETFD
int flags = fcntl (desc, F_GETFD, 0);
if (0 <= flags)
{
int newflags = (value ? flags | FD_CLOEXEC : flags & ~FD_CLOEXEC);
if (flags == newflags
|| fcntl (desc, F_SETFD, newflags) != -1)
return 0;
}
return -1;
#else /* !F_SETFD */
/* Use dup2 to reject invalid file descriptors; the cloexec flag
will be unaffected. */
if (desc < 0)
{
errno = EBADF;
return -1;
}
if (dup2 (desc, desc) < 0)
/* errno is EBADF here. */
return -1;
/* There is nothing we can do on this kind of platform. Punt. */
return 0;
#endif /* !F_SETFD */
}
/* Duplicates a file handle FD, while marking the copy to be closed
prior to exec or spawn. Returns -1 and sets errno if FD could not
be duplicated. */
int
dup_cloexec (int fd)
{
return fcntl (fd, F_DUPFD_CLOEXEC, 0);
}

View File

@@ -0,0 +1,77 @@
/* Close a stream, with nicer error checking than fclose's.
Copyright (C) 1998-2002, 2004, 2006-2024 Free Software Foundation, Inc.
This 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 "close-stream.h"
#include <errno.h>
#include "fpending.h"
#if USE_UNLOCKED_IO
# include "unlocked-io.h"
#endif
/* Close STREAM. Return 0 if successful, EOF (setting errno)
otherwise. A failure might set errno to 0 if the error number
cannot be determined.
A failure with errno set to EPIPE may or may not indicate an error
situation worth signaling to the user. See the documentation of the
close_stdout_set_ignore_EPIPE function for details.
If a program writes *anything* to STREAM, that program should close
STREAM and make sure that it succeeds before exiting. Otherwise,
suppose that you go to the extreme of checking the return status
of every function that does an explicit write to STREAM. The last
printf can succeed in writing to the internal stream buffer, and yet
the fclose(STREAM) could still fail (due e.g., to a disk full error)
when it tries to write out that buffered data. Thus, you would be
left with an incomplete output file and the offending program would
exit successfully. Even calling fflush is not always sufficient,
since some file systems (NFS and CODA) buffer written/flushed data
until an actual close call.
Besides, it's wasteful to check the return value from every call
that writes to STREAM -- just let the internal stream state record
the failure. That's what the ferror test is checking below. */
int
close_stream (FILE *stream)
{
const bool some_pending = (__fpending (stream) != 0);
const bool prev_fail = (ferror (stream) != 0);
const bool fclose_fail = (fclose (stream) != 0);
/* Return an error indication if there was a previous failure or if
fclose failed, with one exception: ignore an fclose failure if
there was no previous error, no data remains to be flushed, and
fclose failed with EBADF. That can happen when a program like cp
is invoked like this 'cp a b >&-' (i.e., with standard output
closed) and doesn't generate any output (hence no previous error
and nothing to be flushed). */
if (prev_fail || (fclose_fail && (some_pending || errno != EBADF)))
{
if (! fclose_fail)
errno = 0;
return EOF;
}
return 0;
}

View File

@@ -0,0 +1,135 @@
/* Close standard output and standard error, exiting with a diagnostic on error.
Copyright (C) 1998-2002, 2004, 2006, 2008-2024 Free Software Foundation,
Inc.
This 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 "closeout.h"
#include <errno.h>
#include <stdio.h>
#include <unistd.h>
#include "gettext.h"
#define _(msgid) gettext (msgid)
#include "close-stream.h"
#include <error.h>
#include "exitfail.h"
#include "quotearg.h"
#ifndef __has_feature
# define __has_feature(a) false
#endif
#if defined __SANITIZE_ADDRESS__ || __has_feature (address_sanitizer)
enum { SANITIZE_ADDRESS = true };
#else
enum { SANITIZE_ADDRESS = false };
#endif
static const char *file_name;
/* Set the file name to be reported in the event an error is detected
by close_stdout. */
void
close_stdout_set_file_name (const char *file)
{
file_name = file;
}
static bool ignore_EPIPE /* = false */;
/* Specify the reaction to an EPIPE error during the closing of stdout:
- If ignore = true, it shall be ignored.
- If ignore = false, it shall evoke a diagnostic, along with a nonzero
exit status.
The default is ignore = false.
This setting matters only if the SIGPIPE signal is ignored (i.e. its
handler set to SIG_IGN) or blocked. Only particular programs need to
temporarily ignore SIGPIPE. If SIGPIPE is ignored or blocked because
it was ignored or blocked in the parent process when it created the
child process, it usually is a bug in the parent process: It is bad
practice to have SIGPIPE ignored or blocked while creating a child
process.
EPIPE occurs when writing to a pipe or socket that has no readers now,
when SIGPIPE is ignored or blocked.
The ignore = false setting is suitable for a scenario where it is normally
guaranteed that the pipe writer terminates before the pipe reader. In
this case, an EPIPE is an indication of a premature termination of the
pipe reader and should lead to a diagnostic and a nonzero exit status.
The ignore = true setting is suitable for a scenario where you don't know
ahead of time whether the pipe writer or the pipe reader will terminate
first. In this case, an EPIPE is an indication that the pipe writer can
stop doing useless write() calls; this is what close_stdout does anyway.
EPIPE is part of the normal pipe/socket shutdown protocol in this case,
and should not lead to a diagnostic message. */
void
close_stdout_set_ignore_EPIPE (bool ignore)
{
ignore_EPIPE = ignore;
}
/* Close standard output. On error, issue a diagnostic and _exit
with status 'exit_failure'.
Also close standard error. On error, _exit with status 'exit_failure'.
Since close_stdout is commonly registered via 'atexit', POSIX
and the C standard both say that it should not call 'exit',
because the behavior is undefined if 'exit' is called more than
once. So it calls '_exit' instead of 'exit'. If close_stdout
is registered via atexit before other functions are registered,
the other functions can act before this _exit is invoked.
Applications that use close_stdout should flush any streams
other than stdout and stderr before exiting, since the call to
_exit will bypass other buffer flushing. Applications should
be flushing and closing other streams anyway, to check for I/O
errors. Also, applications should not use tmpfile, since _exit
can bypass the removal of these files.
It's important to detect such failures and exit nonzero because many
tools (most notably 'make' and other build-management systems) depend
on being able to detect failure in other tools via their exit status. */
void
close_stdout (void)
{
if (close_stream (stdout) != 0
&& !(ignore_EPIPE && errno == EPIPE))
{
char const *write_error = _("write error");
if (file_name)
error (0, errno, "%s: %s", quotearg_colon (file_name),
write_error);
else
error (0, errno, "%s", write_error);
_exit (exit_failure);
}
/* Close stderr only if not sanitizing, as sanitizers may report to
stderr after this function returns. */
if (!SANITIZE_ADDRESS && close_stream (stderr) != 0)
_exit (exit_failure);
}

View File

@@ -0,0 +1,86 @@
/* dirname.c -- return all but the last element in a file name
Copyright (C) 1990, 1998, 2000-2001, 2003-2006, 2009-2024 Free Software
Foundation, Inc.
This file is free software: you can redistribute it and/or modify
it under the terms of the GNU Lesser General Public License as
published by the Free Software Foundation; either version 2.1 of the
License, or (at your option) any later version.
This file is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU Lesser General Public License for more details.
You should have received a copy of the GNU Lesser General Public License
along with this program. If not, see <https://www.gnu.org/licenses/>. */
#include <config.h>
#include "dirname.h"
#include <stdlib.h>
#include <string.h>
/* Return the length of the prefix of FILE that will be used by
dir_name. If FILE is in the working directory, this returns zero
even though 'dir_name (FILE)' will return ".". Works properly even
if there are trailing slashes (by effectively ignoring them). */
size_t
dir_len (char const *file)
{
size_t prefix_length = FILE_SYSTEM_PREFIX_LEN (file);
size_t length;
/* Advance prefix_length beyond important leading slashes. */
prefix_length += (prefix_length != 0
? (FILE_SYSTEM_DRIVE_PREFIX_CAN_BE_RELATIVE
&& ISSLASH (file[prefix_length]))
: (ISSLASH (file[0])
? ((DOUBLE_SLASH_IS_DISTINCT_ROOT
&& ISSLASH (file[1]) && ! ISSLASH (file[2])
? 2 : 1))
: 0));
/* Strip the basename and any redundant slashes before it. */
for (length = last_component (file) - file;
prefix_length < length; length--)
if (! ISSLASH (file[length - 1]))
break;
return length;
}
/* In general, we can't use the builtin 'dirname' function if available,
since it has different meanings in different environments.
In some environments the builtin 'dirname' modifies its argument.
Return the leading directories part of FILE, allocated with malloc.
Works properly even if there are trailing slashes (by effectively
ignoring them). Return NULL on failure.
If lstat (FILE) would succeed, then { chdir (dir_name (FILE));
lstat (base_name (FILE)); } will access the same file. Likewise,
if the sequence { chdir (dir_name (FILE));
rename (base_name (FILE), "foo"); } succeeds, you have renamed FILE
to "foo" in the same directory FILE was in. */
char *
mdir_name (char const *file)
{
size_t length = dir_len (file);
bool append_dot = (length == 0
|| (FILE_SYSTEM_DRIVE_PREFIX_CAN_BE_RELATIVE
&& length == FILE_SYSTEM_PREFIX_LEN (file)
&& file[2] != '\0' && ! ISSLASH (file[2])));
char *dir = malloc (length + append_dot + 1);
if (!dir)
return NULL;
memcpy (dir, file, length);
if (append_dot)
dir[length++] = '.';
dir[length] = '\0';
return dir;
}

View File

@@ -0,0 +1,38 @@
/* dirname.c -- return all but the last element in a file name
Copyright (C) 1990, 1998, 2000-2001, 2003-2006, 2009-2024 Free Software
Foundation, Inc.
This 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 "dirname.h"
#include <stdlib.h>
#include <string.h>
#include "xalloc.h"
/* Just like mdir_name (dirname-lgpl.c), except, rather than
returning NULL upon malloc failure, here, we report the
"memory exhausted" condition and exit. */
char *
dir_name (char const *file)
{
char *result = mdir_name (file);
if (!result)
xalloc_die ();
return result;
}

375
jni/parted/libgnulib/lib/error.c Executable file
View File

@@ -0,0 +1,375 @@
/* Error handler for noninteractive utilities
Copyright (C) 1990-2024 Free Software Foundation, Inc.
This file is part of the GNU C Library.
The GNU C Library is free software; you can redistribute it and/or
modify it under the terms of the GNU Lesser General Public
License as published by the Free Software Foundation; either
version 2.1 of the License, or (at your option) any later version.
The GNU C Library is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
Lesser General Public License for more details.
You should have received a copy of the GNU Lesser General Public
License along with the GNU C Library; if not, see
<https://www.gnu.org/licenses/>. */
/* Written by David MacKenzie <djm@gnu.ai.mit.edu>. */
#if !_LIBC
# include <config.h>
# define _GL_NO_INLINE_ERROR
# define __error_internal(status, err, fmt, args, flags) \
verror (status, err, fmt, args)
# define __error_at_line_internal(status, err, file, line, fmt, args, flags) \
verror_at_line (status, err, file, line, fmt, args)
# define error_tail(status, err, fmt, args, flags) \
error_tail (status, err, fmt, args)
#endif
#include <error.h>
#include <stdarg.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#if !_LIBC && ENABLE_NLS
# include "gettext.h"
# define _(msgid) gettext (msgid)
#endif
#ifdef _LIBC
# include <libintl.h>
# include <stdbool.h>
# include <stdint.h>
# include <wchar.h>
# define mbsrtowcs __mbsrtowcs
# define USE_UNLOCKED_IO 0
# define _GL_ATTRIBUTE_FORMAT_PRINTF_STANDARD(a, b)
# define _GL_ARG_NONNULL(a)
#endif
#if USE_UNLOCKED_IO
# include "unlocked-io.h"
#endif
#ifndef _
# define _(String) String
#endif
/* If NULL, error will flush stdout, then print on stderr the program
name, a colon and a space. Otherwise, error will call this
function without parameters instead. */
void (*error_print_progname) (void);
/* This variable is incremented each time 'error' is called. */
unsigned int error_message_count;
#ifdef _LIBC
/* In the GNU C library, there is a predefined variable for this. */
# define program_name program_invocation_name
# include <errno.h>
# include <limits.h>
# include <libio/libioP.h>
/* In GNU libc we want do not want to use the common name 'error' directly.
Instead make it a weak alias. */
extern void __error (int status, int errnum, const char *message, ...)
__attribute__ ((__format__ (__printf__, 3, 4)));
extern void __error_at_line (int status, int errnum, const char *file_name,
unsigned int line_number, const char *message,
...)
__attribute__ ((__format__ (__printf__, 5, 6)));
# define error __error
# define error_at_line __error_at_line
# include <libio/iolibio.h>
# define fflush(s) _IO_fflush (s)
# undef putc
# define putc(c, fp) _IO_putc (c, fp)
# include <libc-lock.h>
#else /* not _LIBC */
# include <fcntl.h>
# include <unistd.h>
# if defined _WIN32 && ! defined __CYGWIN__
/* Get declarations of the native Windows API functions. */
# define WIN32_LEAN_AND_MEAN
# include <windows.h>
/* Get _get_osfhandle. */
# if GNULIB_MSVC_NOTHROW
# include "msvc-nothrow.h"
# else
# include <io.h>
# endif
# endif
/* The gnulib override of fcntl is not needed in this file. */
# undef fcntl
# if !(GNULIB_STRERROR_R_POSIX || HAVE_DECL_STRERROR_R)
# ifndef HAVE_DECL_STRERROR_R
"this configure-time declaration test was not run"
# endif
# if STRERROR_R_CHAR_P
char *strerror_r (int errnum, char *buf, size_t buflen);
# else
int strerror_r (int errnum, char *buf, size_t buflen);
# endif
# endif
# define program_name getprogname ()
# if GNULIB_STRERROR_R_POSIX || HAVE_STRERROR_R || defined strerror_r
# define __strerror_r strerror_r
# endif /* GNULIB_STRERROR_R_POSIX || HAVE_STRERROR_R || defined strerror_r */
# if GNULIB_defined_verror
# undef verror
# endif
# if GNULIB_defined_verror_at_line
# undef verror_at_line
# endif
#endif /* not _LIBC */
#if !_LIBC
/* Return non-zero if FD is open. */
static int
is_open (int fd)
{
# if defined _WIN32 && ! defined __CYGWIN__
/* On native Windows: The initial state of unassigned standard file
descriptors is that they are open but point to an INVALID_HANDLE_VALUE.
There is no fcntl, and the gnulib replacement fcntl does not support
F_GETFL. */
return (HANDLE) _get_osfhandle (fd) != INVALID_HANDLE_VALUE;
# else
# ifndef F_GETFL
# error Please port fcntl to your platform
# endif
return 0 <= fcntl (fd, F_GETFL);
# endif
}
#endif
static void
flush_stdout (void)
{
#if !_LIBC
int stdout_fd;
# if GNULIB_FREOPEN_SAFER
/* Use of gnulib's freopen-safer module normally ensures that
fileno (stdout) == 1
whenever stdout is open. */
stdout_fd = STDOUT_FILENO;
# else
/* POSIX states that fileno (stdout) after fclose is unspecified. But in
practice it is not a problem, because stdout is statically allocated and
the fd of a FILE stream is stored as a field in its allocated memory. */
stdout_fd = fileno (stdout);
# endif
/* POSIX states that fflush (stdout) after fclose is unspecified; it
is safe in glibc, but not on all other platforms. fflush (NULL)
is always defined, but too draconian. */
if (0 <= stdout_fd && is_open (stdout_fd))
#endif
fflush (stdout);
}
static void
print_errno_message (int errnum)
{
char const *s;
#if _LIBC || GNULIB_STRERROR_R_POSIX || defined HAVE_STRERROR_R
char errbuf[1024];
# if _LIBC || (!GNULIB_STRERROR_R_POSIX && STRERROR_R_CHAR_P)
s = __strerror_r (errnum, errbuf, sizeof errbuf);
# else
if (__strerror_r (errnum, errbuf, sizeof errbuf) == 0)
s = errbuf;
else
s = 0;
# endif
#else
s = strerror (errnum);
#endif
#if !_LIBC
if (! s)
s = _("Unknown system error");
#endif
#if _LIBC
__fxprintf (NULL, ": %s", s);
#else
fprintf (stderr, ": %s", s);
#endif
}
static void _GL_ATTRIBUTE_FORMAT_PRINTF_STANDARD (3, 0) _GL_ARG_NONNULL ((3))
error_tail (int status, int errnum, const char *message, va_list args,
unsigned int mode_flags)
{
#if _LIBC
int ret = __vfxprintf (stderr, message, args, mode_flags);
if (ret < 0 && errno == ENOMEM && _IO_fwide (stderr, 0) > 0)
/* Leave a trace in case the heap allocation of the message string
failed. */
fputws_unlocked (L"out of memory\n", stderr);
#else
vfprintf (stderr, message, args);
#endif
++error_message_count;
if (errnum)
print_errno_message (errnum);
#if _LIBC
__fxprintf (NULL, "\n");
#else
putc ('\n', stderr);
#endif
fflush (stderr);
if (status)
exit (status);
}
/* Print the program name and error message MESSAGE, which is a printf-style
format string with optional args.
If ERRNUM is nonzero, print its corresponding system error message.
Exit with status STATUS if it is nonzero. */
void
__error_internal (int status, int errnum, const char *message,
va_list args, unsigned int mode_flags)
{
#if defined _LIBC
/* We do not want this call to be cut short by a thread
cancellation. Therefore disable cancellation for now. */
int state = PTHREAD_CANCEL_ENABLE;
__pthread_setcancelstate (PTHREAD_CANCEL_DISABLE, &state);
#endif
flush_stdout ();
#ifdef _LIBC
_IO_flockfile (stderr);
#endif
if (error_print_progname)
(*error_print_progname) ();
else
{
#if _LIBC
__fxprintf (NULL, "%s: ", program_name);
#else
fprintf (stderr, "%s: ", program_name);
#endif
}
error_tail (status, errnum, message, args, mode_flags);
#ifdef _LIBC
_IO_funlockfile (stderr);
__pthread_setcancelstate (state, NULL);
#endif
}
void
error (int status, int errnum, const char *message, ...)
{
va_list ap;
va_start (ap, message);
__error_internal (status, errnum, message, ap, 0);
va_end (ap);
}
/* Sometimes we want to have at most one error per line. This
variable controls whether this mode is selected or not. */
int error_one_per_line;
void
__error_at_line_internal (int status, int errnum, const char *file_name,
unsigned int line_number, const char *message,
va_list args, unsigned int mode_flags)
{
if (error_one_per_line)
{
static const char *old_file_name;
static unsigned int old_line_number;
if (old_line_number == line_number
&& (file_name == old_file_name
|| (old_file_name != NULL
&& file_name != NULL
&& strcmp (old_file_name, file_name) == 0)))
/* Simply return and print nothing. */
return;
old_file_name = file_name;
old_line_number = line_number;
}
#if defined _LIBC
/* We do not want this call to be cut short by a thread
cancellation. Therefore disable cancellation for now. */
int state = PTHREAD_CANCEL_ENABLE;
__pthread_setcancelstate (PTHREAD_CANCEL_DISABLE, &state);
#endif
flush_stdout ();
#ifdef _LIBC
_IO_flockfile (stderr);
#endif
if (error_print_progname)
(*error_print_progname) ();
else
{
#if _LIBC
__fxprintf (NULL, "%s:", program_name);
#else
fprintf (stderr, "%s:", program_name);
#endif
}
#if _LIBC
__fxprintf (NULL, file_name != NULL ? "%s:%u: " : " ",
file_name, line_number);
#else
fprintf (stderr, file_name != NULL ? "%s:%u: " : " ",
file_name, line_number);
#endif
error_tail (status, errnum, message, args, mode_flags);
#ifdef _LIBC
_IO_funlockfile (stderr);
__pthread_setcancelstate (state, NULL);
#endif
}
void
error_at_line (int status, int errnum, const char *file_name,
unsigned int line_number, const char *message, ...)
{
va_list ap;
va_start (ap, message);
__error_at_line_internal (status, errnum, file_name, line_number,
message, ap, 0);
va_end (ap);
}
#ifdef _LIBC
/* Make the weak alias. */
# undef error
# undef error_at_line
weak_alias (__error, error)
weak_alias (__error_at_line, error_at_line)
#endif

View File

@@ -0,0 +1,24 @@
/* Failure exit status
Copyright (C) 2002-2003, 2005-2007, 2009-2024 Free Software Foundation, Inc.
This file is free software: you can redistribute it and/or modify
it under the terms of the GNU Lesser General Public License as
published by the Free Software Foundation; either version 2.1 of the
License, or (at your option) any later version.
This file is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU Lesser General Public License for more details.
You should have received a copy of the GNU Lesser General Public License
along with this program. If not, see <https://www.gnu.org/licenses/>. */
#include <config.h>
#include "exitfail.h"
#include <stdlib.h>
int volatile exit_failure = EXIT_FAILURE;

629
jni/parted/libgnulib/lib/fcntl.c Executable file
View File

@@ -0,0 +1,629 @@
/* Provide file descriptor control.
Copyright (C) 2009-2024 Free Software Foundation, Inc.
This file is free software: you can redistribute it and/or modify
it under the terms of the GNU Lesser General Public License as
published by the Free Software Foundation; either version 2.1 of the
License, or (at your option) any later version.
This file is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU Lesser General Public License for more details.
You should have received a copy of the GNU Lesser General Public License
along with this program. If not, see <https://www.gnu.org/licenses/>. */
/* Written by Eric Blake <ebb9@byu.net>. */
#include <config.h>
/* Specification. */
#include <fcntl.h>
#include <errno.h>
#include <limits.h>
#include <stdarg.h>
#include <stdlib.h>
#include <unistd.h>
#ifdef __KLIBC__
# define INCL_DOS
# include <os2.h>
#endif
#if defined _WIN32 && ! defined __CYGWIN__
/* Get declarations of the native Windows API functions. */
# define WIN32_LEAN_AND_MEAN
# include <windows.h>
/* Get _get_osfhandle. */
# if GNULIB_MSVC_NOTHROW
# include "msvc-nothrow.h"
# else
# include <io.h>
# endif
/* Upper bound on getdtablesize(). See lib/getdtablesize.c. */
# define OPEN_MAX_MAX 0x10000
/* Duplicate OLDFD into the first available slot of at least NEWFD,
which must be positive, with FLAGS determining whether the duplicate
will be inheritable. */
static int
dupfd (int oldfd, int newfd, int flags)
{
/* Mingw has no way to create an arbitrary fd. Iterate until all
file descriptors less than newfd are filled up. */
HANDLE curr_process = GetCurrentProcess ();
HANDLE old_handle = (HANDLE) _get_osfhandle (oldfd);
unsigned char fds_to_close[OPEN_MAX_MAX / CHAR_BIT];
unsigned int fds_to_close_bound = 0;
int result;
BOOL inherit = flags & O_CLOEXEC ? FALSE : TRUE;
int mode;
if (newfd < 0 || getdtablesize () <= newfd)
{
errno = EINVAL;
return -1;
}
if (old_handle == INVALID_HANDLE_VALUE
|| (mode = _setmode (oldfd, O_BINARY)) == -1)
{
/* oldfd is not open, or is an unassigned standard file
descriptor. */
errno = EBADF;
return -1;
}
_setmode (oldfd, mode);
flags |= mode;
for (;;)
{
HANDLE new_handle;
int duplicated_fd;
unsigned int index;
if (!DuplicateHandle (curr_process, /* SourceProcessHandle */
old_handle, /* SourceHandle */
curr_process, /* TargetProcessHandle */
(PHANDLE) &new_handle, /* TargetHandle */
(DWORD) 0, /* DesiredAccess */
inherit, /* InheritHandle */
DUPLICATE_SAME_ACCESS)) /* Options */
{
switch (GetLastError ())
{
case ERROR_TOO_MANY_OPEN_FILES:
errno = EMFILE;
break;
case ERROR_INVALID_HANDLE:
case ERROR_INVALID_TARGET_HANDLE:
case ERROR_DIRECT_ACCESS_HANDLE:
errno = EBADF;
break;
case ERROR_INVALID_PARAMETER:
case ERROR_INVALID_FUNCTION:
case ERROR_INVALID_ACCESS:
errno = EINVAL;
break;
default:
errno = EACCES;
break;
}
result = -1;
break;
}
duplicated_fd = _open_osfhandle ((intptr_t) new_handle, flags);
if (duplicated_fd < 0)
{
CloseHandle (new_handle);
result = -1;
break;
}
if (newfd <= duplicated_fd)
{
result = duplicated_fd;
break;
}
/* Set the bit duplicated_fd in fds_to_close[]. */
index = (unsigned int) duplicated_fd / CHAR_BIT;
if (fds_to_close_bound <= index)
{
if (sizeof fds_to_close <= index)
/* Need to increase OPEN_MAX_MAX. */
abort ();
memset (fds_to_close + fds_to_close_bound, '\0',
index + 1 - fds_to_close_bound);
fds_to_close_bound = index + 1;
}
fds_to_close[index] |= 1 << ((unsigned int) duplicated_fd % CHAR_BIT);
}
/* Close the previous fds that turned out to be too small. */
{
int saved_errno = errno;
unsigned int duplicated_fd;
for (duplicated_fd = 0;
duplicated_fd < fds_to_close_bound * CHAR_BIT;
duplicated_fd++)
if ((fds_to_close[duplicated_fd / CHAR_BIT]
>> (duplicated_fd % CHAR_BIT))
& 1)
close (duplicated_fd);
errno = saved_errno;
}
# if REPLACE_FCHDIR
if (0 <= result)
result = _gl_register_dup (oldfd, result);
# endif
return result;
}
#endif /* W32 */
/* Forward declarations, because we '#undef fcntl' in the middle of this
compilation unit. */
/* Our implementation of fcntl (fd, F_DUPFD, target). */
static int rpl_fcntl_DUPFD (int fd, int target);
/* Our implementation of fcntl (fd, F_DUPFD_CLOEXEC, target). */
static int rpl_fcntl_DUPFD_CLOEXEC (int fd, int target);
#ifdef __KLIBC__
/* Adds support for fcntl on directories. */
static int klibc_fcntl (int fd, int action, /* arg */...);
#endif
/* Perform the specified ACTION on the file descriptor FD, possibly
using the argument ARG further described below. This replacement
handles the following actions, and forwards all others on to the
native fcntl. An unrecognized ACTION returns -1 with errno set to
EINVAL.
F_DUPFD - duplicate FD, with int ARG being the minimum target fd.
If successful, return the duplicate, which will be inheritable;
otherwise return -1 and set errno.
F_DUPFD_CLOEXEC - duplicate FD, with int ARG being the minimum
target fd. If successful, return the duplicate, which will not be
inheritable; otherwise return -1 and set errno.
F_GETFD - ARG need not be present. If successful, return a
non-negative value containing the descriptor flags of FD (only
FD_CLOEXEC is portable, but other flags may be present); otherwise
return -1 and set errno. */
int
fcntl (int fd, int action, /* arg */...)
#undef fcntl
#ifdef __KLIBC__
# define fcntl klibc_fcntl
#endif
{
va_list arg;
int result = -1;
va_start (arg, action);
switch (action)
{
case F_DUPFD:
{
int target = va_arg (arg, int);
result = rpl_fcntl_DUPFD (fd, target);
break;
}
case F_DUPFD_CLOEXEC:
{
int target = va_arg (arg, int);
result = rpl_fcntl_DUPFD_CLOEXEC (fd, target);
break;
}
#if !HAVE_FCNTL
case F_GETFD:
{
# if defined _WIN32 && ! defined __CYGWIN__
HANDLE handle = (HANDLE) _get_osfhandle (fd);
DWORD flags;
if (handle == INVALID_HANDLE_VALUE
|| GetHandleInformation (handle, &flags) == 0)
errno = EBADF;
else
result = (flags & HANDLE_FLAG_INHERIT) ? 0 : FD_CLOEXEC;
# else /* !W32 */
/* Use dup2 to reject invalid file descriptors. No way to
access this information, so punt. */
if (0 <= dup2 (fd, fd))
result = 0;
# endif /* !W32 */
break;
} /* F_GETFD */
#endif /* !HAVE_FCNTL */
/* Implementing F_SETFD on mingw is not trivial - there is no
API for changing the O_NOINHERIT bit on an fd, and merely
changing the HANDLE_FLAG_INHERIT bit on the underlying handle
can lead to odd state. It may be possible by duplicating the
handle, using _open_osfhandle with the right flags, then
using dup2 to move the duplicate onto the original, but that
is not supported for now. */
default:
{
#if HAVE_FCNTL
switch (action)
{
#ifdef F_BARRIERFSYNC /* macOS */
case F_BARRIERFSYNC:
#endif
#ifdef F_CHKCLEAN /* macOS */
case F_CHKCLEAN:
#endif
#ifdef F_CLOSEM /* NetBSD, HP-UX */
case F_CLOSEM:
#endif
#ifdef F_FLUSH_DATA /* macOS */
case F_FLUSH_DATA:
#endif
#ifdef F_FREEZE_FS /* macOS */
case F_FREEZE_FS:
#endif
#ifdef F_FULLFSYNC /* macOS */
case F_FULLFSYNC:
#endif
#ifdef F_GETCONFINED /* macOS */
case F_GETCONFINED:
#endif
#ifdef F_GETDEFAULTPROTLEVEL /* macOS */
case F_GETDEFAULTPROTLEVEL:
#endif
#ifdef F_GETFD /* POSIX */
case F_GETFD:
#endif
#ifdef F_GETFL /* POSIX */
case F_GETFL:
#endif
#ifdef F_GETLEASE /* Linux */
case F_GETLEASE:
#endif
#ifdef F_GETNOSIGPIPE /* macOS */
case F_GETNOSIGPIPE:
#endif
#ifdef F_GETOWN /* POSIX */
case F_GETOWN:
#endif
#ifdef F_GETPIPE_SZ /* Linux */
case F_GETPIPE_SZ:
#endif
#ifdef F_GETPROTECTIONCLASS /* macOS */
case F_GETPROTECTIONCLASS:
#endif
#ifdef F_GETPROTECTIONLEVEL /* macOS */
case F_GETPROTECTIONLEVEL:
#endif
#ifdef F_GET_SEALS /* Linux */
case F_GET_SEALS:
#endif
#ifdef F_GETSIG /* Linux */
case F_GETSIG:
#endif
#ifdef F_MAXFD /* NetBSD */
case F_MAXFD:
#endif
#ifdef F_RECYCLE /* macOS */
case F_RECYCLE:
#endif
#ifdef F_SETFIFOENH /* HP-UX */
case F_SETFIFOENH:
#endif
#ifdef F_THAW_FS /* macOS */
case F_THAW_FS:
#endif
/* These actions take no argument. */
result = fcntl (fd, action);
break;
#ifdef F_ADD_SEALS /* Linux */
case F_ADD_SEALS:
#endif
#ifdef F_BADFD /* Solaris */
case F_BADFD:
#endif
#ifdef F_CHECK_OPENEVT /* macOS */
case F_CHECK_OPENEVT:
#endif
#ifdef F_DUP2FD /* FreeBSD, AIX, Solaris */
case F_DUP2FD:
#endif
#ifdef F_DUP2FD_CLOEXEC /* FreeBSD, Solaris */
case F_DUP2FD_CLOEXEC:
#endif
#ifdef F_DUP2FD_CLOFORK /* Solaris */
case F_DUP2FD_CLOFORK:
#endif
#ifdef F_DUPFD /* POSIX */
case F_DUPFD:
#endif
#ifdef F_DUPFD_CLOEXEC /* POSIX */
case F_DUPFD_CLOEXEC:
#endif
#ifdef F_DUPFD_CLOFORK /* Solaris */
case F_DUPFD_CLOFORK:
#endif
#ifdef F_GETXFL /* Solaris */
case F_GETXFL:
#endif
#ifdef F_GLOBAL_NOCACHE /* macOS */
case F_GLOBAL_NOCACHE:
#endif
#ifdef F_MAKECOMPRESSED /* macOS */
case F_MAKECOMPRESSED:
#endif
#ifdef F_MOVEDATAEXTENTS /* macOS */
case F_MOVEDATAEXTENTS:
#endif
#ifdef F_NOCACHE /* macOS */
case F_NOCACHE:
#endif
#ifdef F_NODIRECT /* macOS */
case F_NODIRECT:
#endif
#ifdef F_NOTIFY /* Linux */
case F_NOTIFY:
#endif
#ifdef F_OPLKACK /* IRIX */
case F_OPLKACK:
#endif
#ifdef F_OPLKREG /* IRIX */
case F_OPLKREG:
#endif
#ifdef F_RDAHEAD /* macOS */
case F_RDAHEAD:
#endif
#ifdef F_SETBACKINGSTORE /* macOS */
case F_SETBACKINGSTORE:
#endif
#ifdef F_SETCONFINED /* macOS */
case F_SETCONFINED:
#endif
#ifdef F_SETFD /* POSIX */
case F_SETFD:
#endif
#ifdef F_SETFL /* POSIX */
case F_SETFL:
#endif
#ifdef F_SETLEASE /* Linux */
case F_SETLEASE:
#endif
#ifdef F_SETNOSIGPIPE /* macOS */
case F_SETNOSIGPIPE:
#endif
#ifdef F_SETOWN /* POSIX */
case F_SETOWN:
#endif
#ifdef F_SETPIPE_SZ /* Linux */
case F_SETPIPE_SZ:
#endif
#ifdef F_SETPROTECTIONCLASS /* macOS */
case F_SETPROTECTIONCLASS:
#endif
#ifdef F_SETSIG /* Linux */
case F_SETSIG:
#endif
#ifdef F_SINGLE_WRITER /* macOS */
case F_SINGLE_WRITER:
#endif
/* These actions take an 'int' argument. */
{
int x = va_arg (arg, int);
result = fcntl (fd, action, x);
}
break;
default:
/* Other actions take a pointer argument. */
{
void *p = va_arg (arg, void *);
result = fcntl (fd, action, p);
}
break;
}
#else
errno = EINVAL;
#endif
break;
}
}
va_end (arg);
return result;
}
static int
rpl_fcntl_DUPFD (int fd, int target)
{
int result;
#if !HAVE_FCNTL
result = dupfd (fd, target, 0);
#elif FCNTL_DUPFD_BUGGY || REPLACE_FCHDIR
/* Detect invalid target; needed for cygwin 1.5.x. */
if (target < 0 || getdtablesize () <= target)
{
result = -1;
errno = EINVAL;
}
else
{
/* Haiku alpha 2 loses fd flags on original. */
int flags = fcntl (fd, F_GETFD);
if (flags < 0)
result = -1;
else
{
result = fcntl (fd, F_DUPFD, target);
if (0 <= result && fcntl (fd, F_SETFD, flags) == -1)
{
int saved_errno = errno;
close (result);
result = -1;
errno = saved_errno;
}
# if REPLACE_FCHDIR
if (0 <= result)
result = _gl_register_dup (fd, result);
# endif
}
}
#else
result = fcntl (fd, F_DUPFD, target);
#endif
return result;
}
static int
rpl_fcntl_DUPFD_CLOEXEC (int fd, int target)
{
int result;
#if !HAVE_FCNTL
result = dupfd (fd, target, O_CLOEXEC);
#else /* HAVE_FCNTL */
# if defined __NetBSD__ || defined __HAIKU__
/* On NetBSD 9.0, the system fcntl (fd, F_DUPFD_CLOEXEC, target)
has only the same effect as fcntl (fd, F_DUPFD, target). */
/* On Haiku, the system fcntl (fd, F_DUPFD_CLOEXEC, target) sets
the FD_CLOEXEC flag on fd, not on target. Therefore avoid the
system fcntl in this case. */
# define have_dupfd_cloexec -1
# else
/* Try the system call first, if the headers claim it exists
(that is, if GNULIB_defined_F_DUPFD_CLOEXEC is 0), since we
may be running with a glibc that has the macro but with an
older kernel that does not support it. Cache the
information on whether the system call really works, but
avoid caching failure if the corresponding F_DUPFD fails
for any reason. 0 = unknown, 1 = yes, -1 = no. */
static int have_dupfd_cloexec = GNULIB_defined_F_DUPFD_CLOEXEC ? -1 : 0;
if (0 <= have_dupfd_cloexec)
{
result = fcntl (fd, F_DUPFD_CLOEXEC, target);
if (0 <= result || errno != EINVAL)
{
have_dupfd_cloexec = 1;
# if REPLACE_FCHDIR
if (0 <= result)
result = _gl_register_dup (fd, result);
# endif
}
else
{
result = rpl_fcntl_DUPFD (fd, target);
if (result >= 0)
have_dupfd_cloexec = -1;
}
}
else
# endif
result = rpl_fcntl_DUPFD (fd, target);
if (0 <= result && have_dupfd_cloexec == -1)
{
int flags = fcntl (result, F_GETFD);
if (flags < 0 || fcntl (result, F_SETFD, flags | FD_CLOEXEC) == -1)
{
int saved_errno = errno;
close (result);
errno = saved_errno;
result = -1;
}
}
#endif /* HAVE_FCNTL */
return result;
}
#undef fcntl
#ifdef __KLIBC__
static int
klibc_fcntl (int fd, int action, /* arg */...)
{
va_list arg_ptr;
int arg;
struct stat sbuf;
int result;
va_start (arg_ptr, action);
arg = va_arg (arg_ptr, int);
result = fcntl (fd, action, arg);
/* EPERM for F_DUPFD, ENOTSUP for others */
if (result == -1 && (errno == EPERM || errno == ENOTSUP)
&& !fstat (fd, &sbuf) && S_ISDIR (sbuf.st_mode))
{
ULONG ulMode;
switch (action)
{
case F_DUPFD:
/* Find available fd */
while (fcntl (arg, F_GETFL) != -1 || errno != EBADF)
arg++;
result = dup2 (fd, arg);
break;
/* Using underlying APIs is right ? */
case F_GETFD:
if (DosQueryFHState (fd, &ulMode))
break;
result = (ulMode & OPEN_FLAGS_NOINHERIT) ? FD_CLOEXEC : 0;
break;
case F_SETFD:
if (arg & ~FD_CLOEXEC)
break;
if (DosQueryFHState (fd, &ulMode))
break;
if (arg & FD_CLOEXEC)
ulMode |= OPEN_FLAGS_NOINHERIT;
else
ulMode &= ~OPEN_FLAGS_NOINHERIT;
/* Filter supported flags. */
ulMode &= (OPEN_FLAGS_WRITE_THROUGH | OPEN_FLAGS_FAIL_ON_ERROR
| OPEN_FLAGS_NO_CACHE | OPEN_FLAGS_NOINHERIT);
if (DosSetFHState (fd, ulMode))
break;
result = 0;
break;
case F_GETFL:
result = 0;
break;
case F_SETFL:
if (arg != 0)
break;
result = 0;
break;
default:
errno = EINVAL;
break;
}
}
va_end (arg_ptr);
return result;
}
#endif

53
jni/parted/libgnulib/lib/free.c Executable file
View File

@@ -0,0 +1,53 @@
/* Make free() preserve errno.
Copyright (C) 2003, 2006, 2009-2024 Free Software Foundation, Inc.
This file is free software: you can redistribute it and/or modify
it under the terms of the GNU Lesser General Public License as
published by the Free Software Foundation; either version 2.1 of the
License, or (at your option) any later version.
This file is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU Lesser General Public License for more details.
You should have received a copy of the GNU Lesser General Public License
along with this program. If not, see <https://www.gnu.org/licenses/>. */
/* written by Paul Eggert */
#include <config.h>
/* Specification. */
#include <stdlib.h>
/* A function definition is only needed if HAVE_FREE_POSIX is not defined. */
#if !HAVE_FREE_POSIX
# include <errno.h>
void
rpl_free (void *p)
# undef free
{
# if defined __GNUC__ && !defined __clang__
/* An invalid GCC optimization
<https://gcc.gnu.org/bugzilla/show_bug.cgi?id=98396>
would optimize away the assignments in the code below, when link-time
optimization (LTO) is enabled. Make the code more complicated, so that
GCC does not grok how to optimize it. */
int err[2];
err[0] = errno;
err[1] = errno;
errno = 0;
free (p);
errno = err[errno == 0];
# else
int err = errno;
free (p);
errno = err;
# endif
}
#endif

View File

@@ -0,0 +1,124 @@
/* getdtablesize() function: Return maximum possible file descriptor value + 1.
Copyright (C) 2008-2024 Free Software Foundation, Inc.
Written by Bruno Haible <bruno@clisp.org>, 2008.
This file is free software: you can redistribute it and/or modify
it under the terms of the GNU Lesser General Public License as
published by the Free Software Foundation; either version 2.1 of the
License, or (at your option) any later version.
This file is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU Lesser General Public License for more details.
You should have received a copy of the GNU Lesser General Public License
along with this program. If not, see <https://www.gnu.org/licenses/>. */
#include <config.h>
/* Specification. */
#include <unistd.h>
#if defined _WIN32 && ! defined __CYGWIN__
# include <stdio.h>
# if HAVE_MSVC_INVALID_PARAMETER_HANDLER
# include "msvc-inval.h"
# endif
# if HAVE_MSVC_INVALID_PARAMETER_HANDLER
static int
_setmaxstdio_nothrow (int newmax)
{
int result;
TRY_MSVC_INVAL
{
result = _setmaxstdio (newmax);
}
CATCH_MSVC_INVAL
{
result = -1;
}
DONE_MSVC_INVAL;
return result;
}
# else
# define _setmaxstdio_nothrow _setmaxstdio
# endif
/* Cache for the previous getdtablesize () result. Safe to cache because
Windows also lacks setrlimit. */
static int dtablesize;
int
getdtablesize (void)
{
if (dtablesize == 0)
{
/* We are looking for the number N such that the valid file descriptors
are 0..N-1. It can be obtained through a loop as follows:
{
int fd;
for (fd = 3; fd < 65536; fd++)
if (dup2 (0, fd) == -1)
break;
return fd;
}
On Windows XP, the result is 2048.
The drawback of this loop is that it allocates memory for a libc
internal array that is never freed.
The number N can also be obtained as the upper bound for
_getmaxstdio (). _getmaxstdio () returns the maximum number of open
FILE objects. The sanity check in _setmaxstdio reveals the maximum
number of file descriptors. This too allocates memory, but it is
freed when we call _setmaxstdio with the original value. */
int orig_max_stdio = _getmaxstdio ();
unsigned int bound;
for (bound = 0x10000; _setmaxstdio_nothrow (bound) < 0; bound = bound / 2)
;
_setmaxstdio_nothrow (orig_max_stdio);
dtablesize = bound;
}
return dtablesize;
}
#else
# include <limits.h>
# include <sys/resource.h>
# ifndef RLIM_SAVED_CUR
# define RLIM_SAVED_CUR RLIM_INFINITY
# endif
# ifndef RLIM_SAVED_MAX
# define RLIM_SAVED_MAX RLIM_INFINITY
# endif
# ifdef __CYGWIN__
/* Cygwin 1.7.25 auto-increases the RLIMIT_NOFILE soft limit until it
hits the compile-time constant hard limit of 3200. We might as
well just report the hard limit. */
# define rlim_cur rlim_max
# endif
int
getdtablesize (void)
{
struct rlimit lim;
if (getrlimit (RLIMIT_NOFILE, &lim) == 0
&& 0 <= lim.rlim_cur && lim.rlim_cur <= INT_MAX
&& lim.rlim_cur != RLIM_INFINITY
&& lim.rlim_cur != RLIM_SAVED_CUR
&& lim.rlim_cur != RLIM_SAVED_MAX)
return lim.rlim_cur;
return INT_MAX;
}
#endif

View File

@@ -0,0 +1,47 @@
/* hard-locale.c -- Determine whether a locale is hard.
Copyright (C) 1997-1999, 2002-2004, 2006-2007, 2009-2024 Free Software
Foundation, Inc.
This file is free software: you can redistribute it and/or modify
it under the terms of the GNU Lesser General Public License as
published by the Free Software Foundation; either version 2.1 of the
License, or (at your option) any later version.
This file is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU Lesser General Public License for more details.
You should have received a copy of the GNU Lesser General Public License
along with this program. If not, see <https://www.gnu.org/licenses/>. */
#include <config.h>
#include "hard-locale.h"
#include <locale.h>
#include <stdlib.h>
#include <string.h>
bool
hard_locale (int category)
{
char locale[SETLOCALE_NULL_MAX];
if (setlocale_null_r (category, locale, sizeof (locale)))
return false;
if (!(strcmp (locale, "C") == 0 || strcmp (locale, "POSIX") == 0))
return true;
#if defined __ANDROID__
/* On Android 5.0 or newer, it is possible to set a locale that has the same
name as the "C" locale but in fact uses UTF-8 encoding. Cf. test case 2 in
<https://lists.gnu.org/archive/html/bug-gnulib/2023-01/msg00141.html>. */
if (MB_CUR_MAX > 1)
return true;
#endif
return false;
}

View File

@@ -0,0 +1,21 @@
/* malloc with idx_t rather than size_t
Copyright 2021-2024 Free Software Foundation, Inc.
This file is free software: you can redistribute it and/or modify
it under the terms of the GNU Lesser General Public License as
published by the Free Software Foundation; either version 2.1 of the
License, or (at your option) any later version.
This file is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU Lesser General Public License for more details.
You should have received a copy of the GNU Lesser General Public License
along with this program. If not, see <https://www.gnu.org/licenses/>. */
#include <config.h>
#define IALLOC_INLINE _GL_EXTERN_INLINE
#include "ialloc.h"

View File

@@ -0,0 +1,36 @@
/* Test whether a wide character has a given property.
Copyright (C) 2011-2024 Free Software Foundation, Inc.
Written by Bruno Haible <bruno@clisp.org>, 2011.
This file is free software: you can redistribute it and/or modify
it under the terms of the GNU Lesser General Public License as
published by the Free Software Foundation; either version 2.1 of the
License, or (at your option) any later version.
This file is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU Lesser General Public License for more details.
You should have received a copy of the GNU Lesser General Public License
along with this program. If not, see <https://www.gnu.org/licenses/>. */
#include <config.h>
/* Specification. */
#include <wctype.h>
#if GNULIB_defined_wint_t && !GNULIB_defined_wctype_t
int
iswctype (wint_t wc, wctype_t desc)
# undef iswctype
{
return ((wchar_t) wc == wc ? iswctype ((wchar_t) wc, desc) : 0);
}
#else
# include "iswctype-impl.h"
#endif

View File

@@ -0,0 +1,26 @@
/* Test wide character for being a digit.
Copyright (C) 2020-2024 Free Software Foundation, Inc.
This file is free software: you can redistribute it and/or modify
it under the terms of the GNU Lesser General Public License as
published by the Free Software Foundation; either version 2.1 of the
License, or (at your option) any later version.
This file is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU Lesser General Public License for more details.
You should have received a copy of the GNU Lesser General Public License
along with this program. If not, see <https://www.gnu.org/licenses/>. */
#include <config.h>
/* Specification. */
#include <wctype.h>
int
iswdigit (wint_t wc)
{
return wc >= '0' && wc <= '9';
}

View File

@@ -0,0 +1,33 @@
/* Test wide character for being a punctuation or symbol character.
Copyright (C) 2023-2024 Free Software Foundation, Inc.
This file is free software: you can redistribute it and/or modify
it under the terms of the GNU Lesser General Public License as
published by the Free Software Foundation; either version 2.1 of the
License, or (at your option) any later version.
This file is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU Lesser General Public License for more details.
You should have received a copy of the GNU Lesser General Public License
along with this program. If not, see <https://www.gnu.org/licenses/>. */
#include <config.h>
/* Specification. */
#include <wctype.h>
#include <ctype.h>
int
iswpunct (wint_t wc)
#undef iswpunct
{
#if defined __ANDROID__
if ((unsigned int) wc < 128)
return ispunct ((unsigned int) wc);
#endif
return iswpunct (wc);
}

View File

@@ -0,0 +1,33 @@
/* Test wide character for being a hexadecimal digit.
Copyright (C) 2020-2024 Free Software Foundation, Inc.
This file is free software: you can redistribute it and/or modify
it under the terms of the GNU Lesser General Public License as
published by the Free Software Foundation; either version 2.1 of the
License, or (at your option) any later version.
This file is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU Lesser General Public License for more details.
You should have received a copy of the GNU Lesser General Public License
along with this program. If not, see <https://www.gnu.org/licenses/>. */
#include <config.h>
/* Specification. */
#include <wctype.h>
int
iswxdigit (wint_t wc)
{
return ((wc >= '0' && wc <= '9')
#if 'A' == 0x41 && 'a' == 0x61
/* Optimization, assuming ASCII */
|| ((wc & ~0x20) >= 'A' && (wc & ~0x20) <= 'F')
#else
|| (wc >= 'A' && wc <= 'F') || (wc >= 'a' && wc <= 'f')
#endif
);
}

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,139 @@
/* Utility to accept --help and --version options as unobtrusively as possible.
Copyright (C) 1993-1994, 1998-2000, 2002-2006, 2009-2024 Free Software
Foundation, Inc.
This 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. */
#include <config.h>
/* Specification. */
#include "long-options.h"
#include <stdarg.h>
#include <stdio.h>
#include <stdlib.h>
#include <getopt.h>
#include "version-etc.h"
#include "exitfail.h"
static struct option const long_options[] =
{
{"help", no_argument, NULL, 'h'},
{"version", no_argument, NULL, 'v'},
{NULL, 0, NULL, 0}
};
/* Process long options --help and --version, but only if argc == 2.
Be careful not to gobble up "--". */
void
parse_long_options (int argc,
char **argv,
const char *command_name,
const char *package,
const char *version,
void (*usage_func) (int),
/* const char *author1, ...*/ ...)
{
int c;
int saved_opterr;
saved_opterr = opterr;
/* Don't print an error message for unrecognized options. */
opterr = 0;
if (argc == 2
&& (c = getopt_long (argc, argv, "+", long_options, NULL)) != -1)
{
switch (c)
{
case 'h':
(*usage_func) (EXIT_SUCCESS);
break;
case 'v':
{
va_list authors;
va_start (authors, usage_func);
version_etc_va (stdout, command_name, package, version, authors);
exit (EXIT_SUCCESS);
}
default:
/* Don't process any other long-named options. */
break;
}
}
/* Restore previous value. */
opterr = saved_opterr;
/* Reset this to zero so that getopt internals get initialized from
the probably-new parameters when/if getopt is called later. */
optind = 0;
}
/* Process the GNU default long options --help and --version (see also
https://gnu.org/prep/standards/html_node/Command_002dLine-Interfaces.html),
and fail for any other unknown long or short option.
Use with SCAN_ALL=true to scan until "--", or with SCAN_ALL=false to stop
at the first non-option argument (or "--", whichever comes first). */
void
parse_gnu_standard_options_only (int argc,
char **argv,
const char *command_name,
const char *package,
const char *version,
bool scan_all,
void (*usage_func) (int),
/* const char *author1, ...*/ ...)
{
int c;
int saved_opterr = opterr;
/* Print an error message for unrecognized options. */
opterr = 1;
const char *optstring = scan_all ? "" : "+";
if ((c = getopt_long (argc, argv, optstring, long_options, NULL)) != -1)
{
switch (c)
{
case 'h':
(*usage_func) (EXIT_SUCCESS);
break;
case 'v':
{
va_list authors;
va_start (authors, usage_func);
version_etc_va (stdout, command_name, package, version, authors);
exit (EXIT_SUCCESS);
}
default:
(*usage_func) (exit_failure);
break;
}
}
/* Restore previous value. */
opterr = saved_opterr;
}

View File

@@ -0,0 +1,528 @@
/* Type-safe arrays which grow dynamically.
Copyright (C) 2017-2024 Free Software Foundation, Inc.
This file is part of the GNU C Library.
The GNU C Library is free software; you can redistribute it and/or
modify it under the terms of the GNU Lesser General Public
License as published by the Free Software Foundation; either
version 2.1 of the License, or (at your option) any later version.
The GNU C Library is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
Lesser General Public License for more details.
You should have received a copy of the GNU Lesser General Public
License along with the GNU C Library; if not, see
<https://www.gnu.org/licenses/>. */
/* Pre-processor macros which act as parameters:
DYNARRAY_STRUCT
The struct tag of dynamic array to be defined.
DYNARRAY_ELEMENT
The type name of the element type. Elements are copied
as if by memcpy, and can change address as the dynamic
array grows.
DYNARRAY_PREFIX
The prefix of the functions which are defined.
The following parameters are optional:
DYNARRAY_ELEMENT_FREE
DYNARRAY_ELEMENT_FREE (E) is evaluated to deallocate the
contents of elements. E is of type DYNARRAY_ELEMENT *.
DYNARRAY_ELEMENT_INIT
DYNARRAY_ELEMENT_INIT (E) is evaluated to initialize a new
element. E is of type DYNARRAY_ELEMENT *.
If DYNARRAY_ELEMENT_FREE but not DYNARRAY_ELEMENT_INIT is
defined, new elements are automatically zero-initialized.
Otherwise, new elements have undefined contents.
DYNARRAY_INITIAL_SIZE
The size of the statically allocated array (default:
at least 2, more elements if they fit into 128 bytes).
Must be a preprocessor constant. If DYNARRAY_INITIAL_SIZE is 0,
there is no statically allocated array at, and all non-empty
arrays are heap-allocated.
DYNARRAY_FINAL_TYPE
The name of the type which holds the final array. If not
defined, is PREFIX##finalize not provided. DYNARRAY_FINAL_TYPE
must be a struct type, with members of type DYNARRAY_ELEMENT and
size_t at the start (in this order).
These macros are undefined after this header file has been
included.
The following types are provided (their members are private to the
dynarray implementation):
struct DYNARRAY_STRUCT
The following functions are provided:
void DYNARRAY_PREFIX##init (struct DYNARRAY_STRUCT *);
void DYNARRAY_PREFIX##free (struct DYNARRAY_STRUCT *);
bool DYNARRAY_PREFIX##has_failed (const struct DYNARRAY_STRUCT *);
void DYNARRAY_PREFIX##mark_failed (struct DYNARRAY_STRUCT *);
size_t DYNARRAY_PREFIX##size (const struct DYNARRAY_STRUCT *);
DYNARRAY_ELEMENT *DYNARRAY_PREFIX##begin (const struct DYNARRAY_STRUCT *);
DYNARRAY_ELEMENT *DYNARRAY_PREFIX##end (const struct DYNARRAY_STRUCT *);
DYNARRAY_ELEMENT *DYNARRAY_PREFIX##at (struct DYNARRAY_STRUCT *, size_t);
void DYNARRAY_PREFIX##add (struct DYNARRAY_STRUCT *, DYNARRAY_ELEMENT);
DYNARRAY_ELEMENT *DYNARRAY_PREFIX##emplace (struct DYNARRAY_STRUCT *);
bool DYNARRAY_PREFIX##resize (struct DYNARRAY_STRUCT *, size_t);
void DYNARRAY_PREFIX##remove_last (struct DYNARRAY_STRUCT *);
void DYNARRAY_PREFIX##clear (struct DYNARRAY_STRUCT *);
The following functions are provided are provided if the
prerequisites are met:
bool DYNARRAY_PREFIX##finalize (struct DYNARRAY_STRUCT *,
DYNARRAY_FINAL_TYPE *);
(if DYNARRAY_FINAL_TYPE is defined)
DYNARRAY_ELEMENT *DYNARRAY_PREFIX##finalize (struct DYNARRAY_STRUCT *,
size_t *);
(if DYNARRAY_FINAL_TYPE is not defined)
*/
#include <malloc/dynarray.h>
#include <errno.h>
#include <stdlib.h>
#include <string.h>
#ifndef DYNARRAY_STRUCT
# error "DYNARRAY_STRUCT must be defined"
#endif
#ifndef DYNARRAY_ELEMENT
# error "DYNARRAY_ELEMENT must be defined"
#endif
#ifndef DYNARRAY_PREFIX
# error "DYNARRAY_PREFIX must be defined"
#endif
#ifdef DYNARRAY_INITIAL_SIZE
# if DYNARRAY_INITIAL_SIZE < 0
# error "DYNARRAY_INITIAL_SIZE must be non-negative"
# endif
# if DYNARRAY_INITIAL_SIZE > 0
# define DYNARRAY_HAVE_SCRATCH 1
# else
# define DYNARRAY_HAVE_SCRATCH 0
# endif
#else
/* Provide a reasonable default which limits the size of
DYNARRAY_STRUCT. */
# define DYNARRAY_INITIAL_SIZE \
(sizeof (DYNARRAY_ELEMENT) > 64 ? 2 : 128 / sizeof (DYNARRAY_ELEMENT))
# define DYNARRAY_HAVE_SCRATCH 1
#endif
/* Public type definitions. */
/* All fields of this struct are private to the implementation. */
struct DYNARRAY_STRUCT
{
union
{
struct dynarray_header dynarray_abstract;
struct
{
/* These fields must match struct dynarray_header. */
size_t used;
size_t allocated;
DYNARRAY_ELEMENT *array;
} dynarray_header;
} u;
#if DYNARRAY_HAVE_SCRATCH
/* Initial inline allocation. */
DYNARRAY_ELEMENT scratch[DYNARRAY_INITIAL_SIZE];
#endif
};
/* Internal use only: Helper macros. */
/* Ensure macro-expansion of DYNARRAY_PREFIX. */
#define DYNARRAY_CONCAT0(prefix, name) prefix##name
#define DYNARRAY_CONCAT1(prefix, name) DYNARRAY_CONCAT0(prefix, name)
#define DYNARRAY_NAME(name) DYNARRAY_CONCAT1(DYNARRAY_PREFIX, name)
/* Use DYNARRAY_FREE instead of DYNARRAY_NAME (free),
so that Gnulib does not change 'free' to 'rpl_free'. */
#define DYNARRAY_FREE DYNARRAY_CONCAT1 (DYNARRAY_NAME (f), ree)
/* Address of the scratch buffer if any. */
#if DYNARRAY_HAVE_SCRATCH
# define DYNARRAY_SCRATCH(list) (list)->scratch
#else
# define DYNARRAY_SCRATCH(list) NULL
#endif
/* Internal use only: Helper functions. */
/* Internal function. Call DYNARRAY_ELEMENT_FREE with the array
elements. Name mangling needed due to the DYNARRAY_ELEMENT_FREE
macro expansion. */
static inline void
DYNARRAY_NAME (free__elements__) (DYNARRAY_ELEMENT *__dynarray_array,
size_t __dynarray_used)
{
#ifdef DYNARRAY_ELEMENT_FREE
for (size_t __dynarray_i = 0; __dynarray_i < __dynarray_used; ++__dynarray_i)
DYNARRAY_ELEMENT_FREE (&__dynarray_array[__dynarray_i]);
#endif /* DYNARRAY_ELEMENT_FREE */
}
/* Internal function. Free the non-scratch array allocation. */
static inline void
DYNARRAY_NAME (free__array__) (struct DYNARRAY_STRUCT *list)
{
#if DYNARRAY_HAVE_SCRATCH
if (list->u.dynarray_header.array != list->scratch)
free (list->u.dynarray_header.array);
#else
free (list->u.dynarray_header.array);
#endif
}
/* Public functions. */
/* Initialize a dynamic array object. This must be called before any
use of the object. */
__attribute_nonnull__ ((1))
static void
DYNARRAY_NAME (init) (struct DYNARRAY_STRUCT *list)
{
list->u.dynarray_header.used = 0;
list->u.dynarray_header.allocated = DYNARRAY_INITIAL_SIZE;
list->u.dynarray_header.array = DYNARRAY_SCRATCH (list);
}
/* Deallocate the dynamic array and its elements. */
__attribute_maybe_unused__ __attribute_nonnull__ ((1))
static void
DYNARRAY_FREE (struct DYNARRAY_STRUCT *list)
{
DYNARRAY_NAME (free__elements__)
(list->u.dynarray_header.array, list->u.dynarray_header.used);
DYNARRAY_NAME (free__array__) (list);
DYNARRAY_NAME (init) (list);
}
/* Return true if the dynamic array is in an error state. */
__attribute_nonnull__ ((1))
static inline bool
DYNARRAY_NAME (has_failed) (const struct DYNARRAY_STRUCT *list)
{
return list->u.dynarray_header.allocated == __dynarray_error_marker ();
}
/* Mark the dynamic array as failed. All elements are deallocated as
a side effect. */
__attribute_nonnull__ ((1))
static void
DYNARRAY_NAME (mark_failed) (struct DYNARRAY_STRUCT *list)
{
DYNARRAY_NAME (free__elements__)
(list->u.dynarray_header.array, list->u.dynarray_header.used);
DYNARRAY_NAME (free__array__) (list);
list->u.dynarray_header.array = DYNARRAY_SCRATCH (list);
list->u.dynarray_header.used = 0;
list->u.dynarray_header.allocated = __dynarray_error_marker ();
}
/* Return the number of elements which have been added to the dynamic
array. */
__attribute_nonnull__ ((1))
static inline size_t
DYNARRAY_NAME (size) (const struct DYNARRAY_STRUCT *list)
{
return list->u.dynarray_header.used;
}
/* Return a pointer to the array element at INDEX. Terminate the
process if INDEX is out of bounds. */
__attribute_nonnull__ ((1))
static inline DYNARRAY_ELEMENT *
DYNARRAY_NAME (at) (struct DYNARRAY_STRUCT *list, size_t index)
{
if (__glibc_unlikely (index >= DYNARRAY_NAME (size) (list)))
__libc_dynarray_at_failure (DYNARRAY_NAME (size) (list), index);
return list->u.dynarray_header.array + index;
}
/* Return a pointer to the first array element, if any. For a
zero-length array, the pointer can be NULL even though the dynamic
array has not entered the failure state. */
__attribute_nonnull__ ((1))
static inline DYNARRAY_ELEMENT *
DYNARRAY_NAME (begin) (struct DYNARRAY_STRUCT *list)
{
return list->u.dynarray_header.array;
}
/* Return a pointer one element past the last array element. For a
zero-length array, the pointer can be NULL even though the dynamic
array has not entered the failure state. */
__attribute_nonnull__ ((1))
static inline DYNARRAY_ELEMENT *
DYNARRAY_NAME (end) (struct DYNARRAY_STRUCT *list)
{
return list->u.dynarray_header.array + list->u.dynarray_header.used;
}
/* Internal function. Slow path for the add function below. */
static void
DYNARRAY_NAME (add__) (struct DYNARRAY_STRUCT *list, DYNARRAY_ELEMENT item)
{
if (__glibc_unlikely
(!__libc_dynarray_emplace_enlarge (&list->u.dynarray_abstract,
DYNARRAY_SCRATCH (list),
sizeof (DYNARRAY_ELEMENT))))
{
DYNARRAY_NAME (mark_failed) (list);
return;
}
/* Copy the new element and increase the array length. */
list->u.dynarray_header.array[list->u.dynarray_header.used++] = item;
}
/* Add ITEM at the end of the array, enlarging it by one element.
Mark *LIST as failed if the dynamic array allocation size cannot be
increased. */
__attribute_nonnull__ ((1))
static inline void
DYNARRAY_NAME (add) (struct DYNARRAY_STRUCT *list, DYNARRAY_ELEMENT item)
{
/* Do nothing in case of previous error. */
if (DYNARRAY_NAME (has_failed) (list))
return;
/* Enlarge the array if necessary. */
if (__glibc_unlikely (list->u.dynarray_header.used
== list->u.dynarray_header.allocated))
{
DYNARRAY_NAME (add__) (list, item);
return;
}
/* Copy the new element and increase the array length. */
list->u.dynarray_header.array[list->u.dynarray_header.used++] = item;
}
/* Internal function. Building block for the emplace functions below.
Assumes space for one more element in *LIST. */
static inline DYNARRAY_ELEMENT *
DYNARRAY_NAME (emplace__tail__) (struct DYNARRAY_STRUCT *list)
{
DYNARRAY_ELEMENT *result
= &list->u.dynarray_header.array[list->u.dynarray_header.used];
++list->u.dynarray_header.used;
#if defined (DYNARRAY_ELEMENT_INIT)
DYNARRAY_ELEMENT_INIT (result);
#elif defined (DYNARRAY_ELEMENT_FREE)
memset (result, 0, sizeof (*result));
#endif
return result;
}
/* Internal function. Slow path for the emplace function below. */
static DYNARRAY_ELEMENT *
DYNARRAY_NAME (emplace__) (struct DYNARRAY_STRUCT *list)
{
if (__glibc_unlikely
(!__libc_dynarray_emplace_enlarge (&list->u.dynarray_abstract,
DYNARRAY_SCRATCH (list),
sizeof (DYNARRAY_ELEMENT))))
{
DYNARRAY_NAME (mark_failed) (list);
return NULL;
}
return DYNARRAY_NAME (emplace__tail__) (list);
}
/* Allocate a place for a new element in *LIST and return a pointer to
it. The pointer can be NULL if the dynamic array cannot be
enlarged due to a memory allocation failure. */
__attribute_maybe_unused__ __attribute_warn_unused_result__
__attribute_nonnull__ ((1))
static
/* Avoid inlining with the larger initialization code. */
#if !(defined (DYNARRAY_ELEMENT_INIT) || defined (DYNARRAY_ELEMENT_FREE))
inline
#endif
DYNARRAY_ELEMENT *
DYNARRAY_NAME (emplace) (struct DYNARRAY_STRUCT *list)
{
/* Do nothing in case of previous error. */
if (DYNARRAY_NAME (has_failed) (list))
return NULL;
/* Enlarge the array if necessary. */
if (__glibc_unlikely (list->u.dynarray_header.used
== list->u.dynarray_header.allocated))
return (DYNARRAY_NAME (emplace__) (list));
return DYNARRAY_NAME (emplace__tail__) (list);
}
/* Change the size of *LIST to SIZE. If SIZE is larger than the
existing size, new elements are added (which can be initialized).
Otherwise, the list is truncated, and elements are freed. Return
false on memory allocation failure (and mark *LIST as failed). */
__attribute_maybe_unused__ __attribute_nonnull__ ((1))
static bool
DYNARRAY_NAME (resize) (struct DYNARRAY_STRUCT *list, size_t size)
{
if (size > list->u.dynarray_header.used)
{
bool ok;
#if defined (DYNARRAY_ELEMENT_INIT)
/* The new elements have to be initialized. */
size_t old_size = list->u.dynarray_header.used;
ok = __libc_dynarray_resize (&list->u.dynarray_abstract,
size, DYNARRAY_SCRATCH (list),
sizeof (DYNARRAY_ELEMENT));
if (ok)
for (size_t i = old_size; i < size; ++i)
{
DYNARRAY_ELEMENT_INIT (&list->u.dynarray_header.array[i]);
}
#elif defined (DYNARRAY_ELEMENT_FREE)
/* Zero initialization is needed so that the elements can be
safely freed. */
ok = __libc_dynarray_resize_clear
(&list->u.dynarray_abstract, size,
DYNARRAY_SCRATCH (list), sizeof (DYNARRAY_ELEMENT));
#else
ok = __libc_dynarray_resize (&list->u.dynarray_abstract,
size, DYNARRAY_SCRATCH (list),
sizeof (DYNARRAY_ELEMENT));
#endif
if (__glibc_unlikely (!ok))
DYNARRAY_NAME (mark_failed) (list);
return ok;
}
else
{
/* The list has shrunk in size. Free the removed elements. */
DYNARRAY_NAME (free__elements__)
(list->u.dynarray_header.array + size,
list->u.dynarray_header.used - size);
list->u.dynarray_header.used = size;
return true;
}
}
/* Remove the last element of LIST if it is present. */
__attribute_maybe_unused__ __attribute_nonnull__ ((1))
static void
DYNARRAY_NAME (remove_last) (struct DYNARRAY_STRUCT *list)
{
/* used > 0 implies that the array is the non-failed state. */
if (list->u.dynarray_header.used > 0)
{
size_t new_length = list->u.dynarray_header.used - 1;
#ifdef DYNARRAY_ELEMENT_FREE
DYNARRAY_ELEMENT_FREE (&list->u.dynarray_header.array[new_length]);
#endif
list->u.dynarray_header.used = new_length;
}
}
/* Remove all elements from the list. The elements are freed, but the
list itself is not. */
__attribute_maybe_unused__ __attribute_nonnull__ ((1))
static void
DYNARRAY_NAME (clear) (struct DYNARRAY_STRUCT *list)
{
/* free__elements__ does nothing if the list is in the failed
state. */
DYNARRAY_NAME (free__elements__)
(list->u.dynarray_header.array, list->u.dynarray_header.used);
list->u.dynarray_header.used = 0;
}
#ifdef DYNARRAY_FINAL_TYPE
/* Transfer the dynamic array to a permanent location at *RESULT.
Returns true on success on false on allocation failure. In either
case, *LIST is re-initialized and can be reused. A NULL pointer is
stored in *RESULT if LIST refers to an empty list. On success, the
pointer in *RESULT is heap-allocated and must be deallocated using
free. */
__attribute_maybe_unused__ __attribute_warn_unused_result__
__attribute_nonnull__ ((1, 2))
static bool
DYNARRAY_NAME (finalize) (struct DYNARRAY_STRUCT *list,
DYNARRAY_FINAL_TYPE *result)
{
struct dynarray_finalize_result res;
if (__libc_dynarray_finalize (&list->u.dynarray_abstract,
DYNARRAY_SCRATCH (list),
sizeof (DYNARRAY_ELEMENT), &res))
{
/* On success, the result owns all the data. */
DYNARRAY_NAME (init) (list);
*result = (DYNARRAY_FINAL_TYPE) { res.array, res.length };
return true;
}
else
{
/* On error, we need to free all data. */
DYNARRAY_FREE (list);
errno = ENOMEM;
return false;
}
}
#else /* !DYNARRAY_FINAL_TYPE */
/* Transfer the dynamic array to a heap-allocated array and return a
pointer to it. The pointer is NULL if memory allocation fails, or
if the array is empty, so this function should be used only for
arrays which are known not be empty (usually because they always
have a sentinel at the end). If LENGTHP is not NULL, the array
length is written to *LENGTHP. *LIST is re-initialized and can be
reused. */
__attribute_maybe_unused__ __attribute_warn_unused_result__
__attribute_nonnull__ ((1))
static DYNARRAY_ELEMENT *
DYNARRAY_NAME (finalize) (struct DYNARRAY_STRUCT *list, size_t *lengthp)
{
struct dynarray_finalize_result res;
if (__libc_dynarray_finalize (&list->u.dynarray_abstract,
DYNARRAY_SCRATCH (list),
sizeof (DYNARRAY_ELEMENT), &res))
{
/* On success, the result owns all the data. */
DYNARRAY_NAME (init) (list);
if (lengthp != NULL)
*lengthp = res.length;
return res.array;
}
else
{
/* On error, we need to free all data. */
DYNARRAY_FREE (list);
errno = ENOMEM;
return NULL;
}
}
#endif /* !DYNARRAY_FINAL_TYPE */
/* Undo macro definitions. */
#undef DYNARRAY_CONCAT0
#undef DYNARRAY_CONCAT1
#undef DYNARRAY_NAME
#undef DYNARRAY_SCRATCH
#undef DYNARRAY_HAVE_SCRATCH
#undef DYNARRAY_STRUCT
#undef DYNARRAY_ELEMENT
#undef DYNARRAY_PREFIX
#undef DYNARRAY_ELEMENT_FREE
#undef DYNARRAY_ELEMENT_INIT
#undef DYNARRAY_INITIAL_SIZE
#undef DYNARRAY_FINAL_TYPE

View File

@@ -0,0 +1,135 @@
/* Safe automatic memory allocation.
Copyright (C) 2003, 2006-2007, 2009-2024 Free Software Foundation, Inc.
Written by Bruno Haible <bruno@clisp.org>, 2003, 2018.
This file is free software: you can redistribute it and/or modify
it under the terms of the GNU Lesser General Public License as
published by the Free Software Foundation; either version 2.1 of the
License, or (at your option) any later version.
This file is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU Lesser General Public License for more details.
You should have received a copy of the GNU Lesser General Public License
along with this program. If not, see <https://www.gnu.org/licenses/>. */
#define _GL_USE_STDLIB_ALLOC 1
#include <config.h>
/* Specification. */
#include "malloca.h"
#include <stdckdint.h>
#if defined __CHERI_PURE_CAPABILITY__
# include <cheri.h>
#endif
#include "idx.h"
/* The speed critical point in this file is freea() applied to an alloca()
result: it must be fast, to match the speed of alloca(). The speed of
mmalloca() and freea() in the other case are not critical, because they
are only invoked for big memory sizes.
Here we use a bit in the address as an indicator, an idea by Ondřej Bílka.
malloca() can return three types of pointers:
- Pointers ≡ 0 mod 2*sa_alignment_max come from stack allocation.
- Pointers ≡ sa_alignment_max mod 2*sa_alignment_max come from heap
allocation.
- NULL comes from a failed heap allocation. */
#if defined __CHERI_PURE_CAPABILITY__
/* Type for holding the original malloc() result. */
typedef uintptr_t small_t;
#else
/* Type for holding very small pointer differences. */
typedef unsigned char small_t;
/* Verify that it is wide enough. */
static_assert (2 * sa_alignment_max - 1 <= (small_t) -1);
#endif
void *
mmalloca (size_t n)
{
#if HAVE_ALLOCA
/* Allocate one more word, used to determine the address to pass to freea(),
and room for the alignment ≡ sa_alignment_max mod 2*sa_alignment_max. */
uintptr_t alignment2_mask = 2 * sa_alignment_max - 1;
int plus = sizeof (small_t) + alignment2_mask;
idx_t nplus;
if (!ckd_add (&nplus, n, plus) && !xalloc_oversized (nplus, 1))
{
char *mem = (char *) malloc (nplus);
if (mem != NULL)
{
uintptr_t umem = (uintptr_t) mem;
/* The ckd_add avoids signed integer overflow on
theoretical platforms where UINTPTR_MAX <= INT_MAX. */
uintptr_t umemplus;
ckd_add (&umemplus, umem, sizeof (small_t) + sa_alignment_max - 1);
idx_t offset = (umemplus - umemplus % (2 * sa_alignment_max)
+ sa_alignment_max - umem);
void *p = mem + offset;
/* Here p >= mem + sizeof (small_t),
and p <= mem + sizeof (small_t) + 2 * sa_alignment_max - 1
hence p + n <= mem + nplus.
So, the memory range [p, p+n) lies in the allocated memory range
[mem, mem + nplus). */
small_t *sp = p;
# if defined __CHERI_PURE_CAPABILITY__
sp[-1] = umem;
p = (char *) cheri_bounds_set ((char *) p - sizeof (small_t),
sizeof (small_t) + n)
+ sizeof (small_t);
# else
sp[-1] = offset;
# endif
/* p ≡ sa_alignment_max mod 2*sa_alignment_max. */
return p;
}
}
/* Out of memory. */
return NULL;
#else
# if !MALLOC_0_IS_NONNULL
if (n == 0)
n = 1;
# endif
return malloc (n);
#endif
}
#if HAVE_ALLOCA
void
freea (void *p)
{
/* Check argument. */
uintptr_t u = (uintptr_t) p;
if (u & (sa_alignment_max - 1))
{
/* p was not the result of a malloca() call. Invalid argument. */
abort ();
}
/* Determine whether p was a non-NULL pointer returned by mmalloca(). */
if (u & sa_alignment_max)
{
char *cp = p;
small_t *sp = p;
# if defined __CHERI_PURE_CAPABILITY__
void *mem = sp[-1];
# else
void *mem = cp - sp[-1];
# endif
free (mem);
}
}
#endif
/*
* Hey Emacs!
* Local Variables:
* coding: utf-8
* End:
*/

View File

@@ -0,0 +1,288 @@
/* Convert multibyte character to 32-bit wide character.
Copyright (C) 2020-2024 Free Software Foundation, Inc.
This file is free software: you can redistribute it and/or modify
it under the terms of the GNU Lesser General Public License as
published by the Free Software Foundation; either version 2.1 of the
License, or (at your option) any later version.
This file is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU Lesser General Public License for more details.
You should have received a copy of the GNU Lesser General Public License
along with this program. If not, see <https://www.gnu.org/licenses/>. */
/* Written by Bruno Haible <bruno@clisp.org>, 2020. */
#include <config.h>
/* Specification. */
#include <uchar.h>
#include "attribute.h"
#include <errno.h>
#include <stdlib.h>
#if GL_CHAR32_T_IS_UNICODE
# include "lc-charset-unicode.h"
#endif
#if GNULIB_defined_mbstate_t /* AIX, IRIX */
/* Implement mbrtoc32() on top of mbtowc() for the non-UTF-8 locales
and directly for the UTF-8 locales. */
/* Note: On AIX (64-bit) we can implement mbrtoc32 in two equivalent ways:
- in a way that parallels the override of mbrtowc; this is the code branch
here;
- in a way that invokes the overridden mbrtowc; this would be the #else
branch below.
They are equivalent. */
# if AVOID_ANY_THREADS
/* The option '--disable-threads' explicitly requests no locking. */
# elif defined _WIN32 && !defined __CYGWIN__
# define WIN32_LEAN_AND_MEAN /* avoid including junk */
# include <windows.h>
# elif HAVE_PTHREAD_API
# include <pthread.h>
# if HAVE_THREADS_H && HAVE_WEAK_SYMBOLS
# include <threads.h>
# pragma weak thrd_exit
# define c11_threads_in_use() (thrd_exit != NULL)
# else
# define c11_threads_in_use() 0
# endif
# elif HAVE_THREADS_H
# include <threads.h>
# endif
# include "lc-charset-dispatch.h"
# include "mbtowc-lock.h"
static_assert (sizeof (mbstate_t) >= 4);
static char internal_state[4];
size_t
mbrtoc32 (char32_t *pwc, const char *s, size_t n, mbstate_t *ps)
{
# define FITS_IN_CHAR_TYPE(wc) 1
# include "mbrtowc-impl.h"
}
#else /* glibc, macOS, FreeBSD, NetBSD, OpenBSD, HP-UX, Solaris, Cygwin, mingw, MSVC, Minix, Android */
/* Implement mbrtoc32() based on the original mbrtoc32() or on mbrtowc(). */
# include <wchar.h>
# include "localcharset.h"
# include "streq.h"
# if MBRTOC32_IN_C_LOCALE_MAYBE_EILSEQ
# include "hard-locale.h"
# include <locale.h>
# endif
static mbstate_t internal_state;
size_t
mbrtoc32 (char32_t *pwc, const char *s, size_t n, mbstate_t *ps)
# undef mbrtoc32
{
/* It's simpler to handle the case s == NULL upfront, than to worry about
this case later, before every test of pwc and n. */
if (s == NULL)
{
pwc = NULL;
s = "";
n = 1;
}
# if MBRTOC32_EMPTY_INPUT_BUG || _GL_SMALL_WCHAR_T
if (n == 0)
return (size_t) -2;
# endif
if (ps == NULL)
ps = &internal_state;
# if HAVE_WORKING_MBRTOC32 && HAVE_WORKING_C32RTOMB && !MBRTOC32_MULTIBYTE_LOCALE_BUG
/* mbrtoc32() may produce different values for wc than mbrtowc(). Therefore
use mbrtoc32(). */
# if defined _WIN32 && !defined __CYGWIN__
char32_t wc;
size_t ret = mbrtoc32 (&wc, s, n, ps);
if (ret < (size_t) -2 && pwc != NULL)
*pwc = wc;
# else
size_t ret = mbrtoc32 (pwc, s, n, ps);
# endif
# if GNULIB_MBRTOC32_REGULAR
/* Verify that mbrtoc32 is regular. */
if (ret < (size_t) -3 && ! mbsinit (ps))
/* This occurs on glibc 2.36. */
mbszero (ps);
if (ret == (size_t) -3)
abort ();
# endif
# if MBRTOC32_IN_C_LOCALE_MAYBE_EILSEQ
if ((size_t) -2 <= ret && n != 0 && ! hard_locale (LC_CTYPE))
{
if (pwc != NULL)
*pwc = (unsigned char) *s;
return 1;
}
# endif
return ret;
# elif _GL_SMALL_WCHAR_T
/* Special-case all encodings that may produce wide character values
> WCHAR_MAX. */
const char *encoding = locale_charset ();
if (STREQ_OPT (encoding, "UTF-8", 'U', 'T', 'F', '-', '8', 0, 0, 0, 0))
{
/* Special-case the UTF-8 encoding. Assume that the wide-character
encoding in a UTF-8 locale is UCS-2 or, equivalently, UTF-16. */
/* Here n > 0. */
char *pstate = (char *)ps;
size_t nstate = pstate[0];
char buf[4];
const char *p;
size_t m;
int res;
switch (nstate)
{
case 0:
p = s;
m = n;
break;
case 3:
buf[2] = pstate[3];
FALLTHROUGH;
case 2:
buf[1] = pstate[2];
FALLTHROUGH;
case 1:
buf[0] = pstate[1];
p = buf;
m = nstate;
buf[m++] = s[0];
if (n >= 2 && m < 4)
{
buf[m++] = s[1];
if (n >= 3 && m < 4)
buf[m++] = s[2];
}
break;
default:
errno = EINVAL;
return (size_t)(-1);
}
/* Here m > 0. */
{
# define FITS_IN_CHAR_TYPE(wc) 1
# include "mbrtowc-impl-utf8.h"
}
success:
if (nstate >= (res > 0 ? res : 1))
abort ();
res -= nstate;
/* Set *ps to an initial state. */
# if defined _WIN32 && !defined __CYGWIN__
/* Native Windows. */
/* MSVC defines 'mbstate_t' as an 8-byte struct; the first 4 bytes matter.
On mingw, 'mbstate_t' is sometimes defined as 'int', sometimes defined
as an 8-byte struct, of which the first 4 bytes matter. */
*(unsigned int *)pstate = 0;
# elif defined __CYGWIN__
/* Cygwin defines 'mbstate_t' as an 8-byte struct; the first 4 bytes
matter. */
ps->__count = 0;
# else
pstate[0] = 0;
# endif
return res;
incomplete:
{
size_t k = nstate;
/* Here 0 <= k < m < 4. */
pstate[++k] = s[0];
if (k < m)
{
pstate[++k] = s[1];
if (k < m)
pstate[++k] = s[2];
}
if (k != m)
abort ();
}
pstate[0] = m;
return (size_t)(-2);
invalid:
errno = EILSEQ;
/* The conversion state is undefined, says POSIX. */
return (size_t)(-1);
}
else
{
wchar_t wc;
size_t ret = mbrtowc (&wc, s, n, ps);
if (ret < (size_t) -2 && pwc != NULL)
*pwc = wc;
return ret;
}
# else
/* char32_t and wchar_t are equivalent. Use mbrtowc(). */
wchar_t wc;
size_t ret = mbrtowc (&wc, s, n, ps);
# if GNULIB_MBRTOC32_REGULAR
/* Ensure that mbrtoc32 is regular. */
if (ret < (size_t) -2 && ! mbsinit (ps))
/* This occurs on glibc 2.12. */
mbszero (ps);
# endif
# if GL_CHAR32_T_IS_UNICODE && GL_CHAR32_T_VS_WCHAR_T_NEEDS_CONVERSION
if (ret < (size_t) -2 && wc != 0)
{
wc = locale_encoding_to_unicode (wc);
if (wc == 0)
{
ret = (size_t) -1;
errno = EILSEQ;
}
}
# endif
if (ret < (size_t) -2 && pwc != NULL)
*pwc = wc;
return ret;
# endif
}
#endif

View File

@@ -0,0 +1,161 @@
/* Convert multibyte character to wide character.
Copyright (C) 1999-2002, 2005-2024 Free Software Foundation, Inc.
Written by Bruno Haible <bruno@clisp.org>, 2008.
This file is free software: you can redistribute it and/or modify
it under the terms of the GNU Lesser General Public License as
published by the Free Software Foundation; either version 2.1 of the
License, or (at your option) any later version.
This file is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU Lesser General Public License for more details.
You should have received a copy of the GNU Lesser General Public License
along with this program. If not, see <https://www.gnu.org/licenses/>. */
#include <config.h>
/* Specification. */
#include <wchar.h>
#if GNULIB_defined_mbstate_t
/* Implement mbrtowc() on top of mbtowc() for the non-UTF-8 locales
and directly for the UTF-8 locales. */
# include <errno.h>
# include <stdint.h>
# include <stdlib.h>
# if AVOID_ANY_THREADS
/* The option '--disable-threads' explicitly requests no locking. */
# elif defined _WIN32 && !defined __CYGWIN__
# define WIN32_LEAN_AND_MEAN /* avoid including junk */
# include <windows.h>
# elif HAVE_PTHREAD_API
# include <pthread.h>
# if HAVE_THREADS_H && HAVE_WEAK_SYMBOLS
# include <threads.h>
# pragma weak thrd_exit
# define c11_threads_in_use() (thrd_exit != NULL)
# else
# define c11_threads_in_use() 0
# endif
# elif HAVE_THREADS_H
# include <threads.h>
# endif
# include "attribute.h"
# include "lc-charset-dispatch.h"
# include "mbtowc-lock.h"
static_assert (sizeof (mbstate_t) >= 4);
static char internal_state[4];
size_t
mbrtowc (wchar_t *pwc, const char *s, size_t n, mbstate_t *ps)
{
# define FITS_IN_CHAR_TYPE(wc) ((wc) <= WCHAR_MAX)
# include "mbrtowc-impl.h"
}
#else
/* Override the system's mbrtowc() function. */
# if MBRTOWC_IN_C_LOCALE_MAYBE_EILSEQ
# include "hard-locale.h"
# include <locale.h>
# endif
# undef mbrtowc
size_t
rpl_mbrtowc (wchar_t *pwc, const char *s, size_t n, mbstate_t *ps)
{
size_t ret;
wchar_t wc;
# if MBRTOWC_NULL_ARG2_BUG || MBRTOWC_RETVAL_BUG || MBRTOWC_EMPTY_INPUT_BUG
if (s == NULL)
{
pwc = NULL;
s = "";
n = 1;
}
# endif
# if MBRTOWC_EMPTY_INPUT_BUG
if (n == 0)
return (size_t) -2;
# endif
if (! pwc)
pwc = &wc;
# if MBRTOWC_RETVAL_BUG
{
static mbstate_t internal_state;
/* Override mbrtowc's internal state. We cannot call mbsinit() on the
hidden internal state, but we can call it on our variable. */
if (ps == NULL)
ps = &internal_state;
if (!mbsinit (ps))
{
/* Parse the rest of the multibyte character byte for byte. */
size_t count = 0;
for (; n > 0; s++, n--)
{
ret = mbrtowc (&wc, s, 1, ps);
if (ret == (size_t)(-1))
return (size_t)(-1);
count++;
if (ret != (size_t)(-2))
{
/* The multibyte character has been completed. */
*pwc = wc;
return (wc == 0 ? 0 : count);
}
}
return (size_t)(-2);
}
}
# endif
# if MBRTOWC_STORES_INCOMPLETE_BUG
ret = mbrtowc (&wc, s, n, ps);
if (ret < (size_t) -2 && pwc != NULL)
*pwc = wc;
# else
ret = mbrtowc (pwc, s, n, ps);
# endif
# if MBRTOWC_NUL_RETVAL_BUG
if (ret < (size_t) -2 && !*pwc)
return 0;
# endif
# if MBRTOWC_IN_C_LOCALE_MAYBE_EILSEQ
if ((size_t) -2 <= ret && n != 0 && ! hard_locale (LC_CTYPE))
{
unsigned char uc = *s;
*pwc = uc;
return 1;
}
# endif
return ret;
}
#endif

View File

@@ -0,0 +1,23 @@
/* Put an mbstate_t into an initial conversion state.
Copyright (C) 2023-2024 Free Software Foundation, Inc.
This file is free software: you can redistribute it and/or modify
it under the terms of the GNU Lesser General Public License as
published by the Free Software Foundation; either version 2.1 of the
License, or (at your option) any later version.
This file is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU Lesser General Public License for more details.
You should have received a copy of the GNU Lesser General Public License
along with this program. If not, see <https://www.gnu.org/licenses/>. */
/* Written by Bruno Haible <bruno@clisp.org>, 2023. */
#include <config.h>
#define IN_MBSZERO
/* Specification and implementation. */
#include <wchar.h>

View File

@@ -0,0 +1,585 @@
/* nl_langinfo() replacement: query locale dependent information.
Copyright (C) 2007-2024 Free Software Foundation, Inc.
This file is free software: you can redistribute it and/or modify
it under the terms of the GNU Lesser General Public License as
published by the Free Software Foundation; either version 2.1 of the
License, or (at your option) any later version.
This file is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU Lesser General Public License for more details.
You should have received a copy of the GNU Lesser General Public License
along with this program. If not, see <https://www.gnu.org/licenses/>. */
#include <config.h>
/* Specification. */
#include <langinfo.h>
#include <locale.h>
#include <stdlib.h>
#include <string.h>
#if defined _WIN32 && ! defined __CYGWIN__
# define WIN32_LEAN_AND_MEAN /* avoid including junk */
# include <windows.h>
# include <stdio.h>
#endif
#if REPLACE_NL_LANGINFO && !NL_LANGINFO_MTSAFE
# if AVOID_ANY_THREADS
/* The option '--disable-threads' explicitly requests no locking. */
# elif defined _WIN32 && !defined __CYGWIN__
# define WIN32_LEAN_AND_MEAN /* avoid including junk */
# include <windows.h>
# elif HAVE_PTHREAD_API
# include <pthread.h>
# if HAVE_THREADS_H && HAVE_WEAK_SYMBOLS
# include <threads.h>
# pragma weak thrd_exit
# define c11_threads_in_use() (thrd_exit != NULL)
# else
# define c11_threads_in_use() 0
# endif
# elif HAVE_THREADS_H
# include <threads.h>
# endif
#endif
/* nl_langinfo() must be multithread-safe. To achieve this without using
thread-local storage:
1. We use a specific static buffer for each possible argument.
So that different threads can call nl_langinfo with different arguments,
without interfering.
2. We use a simple strcpy or memcpy to fill this static buffer. Filling it
through, for example, strcpy + strcat would not be guaranteed to leave
the buffer's contents intact if another thread is currently accessing
it. If necessary, the contents is first assembled in a stack-allocated
buffer. */
#if !REPLACE_NL_LANGINFO || GNULIB_defined_CODESET
/* Return the codeset of the current locale, if this is easily deducible.
Otherwise, return "". */
static char *
ctype_codeset (void)
{
/* This function is only used on platforms which don't have uselocale().
Therefore we don't need to look at the per-thread locale first, here. */
static char result[2 + 10 + 1];
char buf[2 + 10 + 1];
char locale[SETLOCALE_NULL_MAX];
char *codeset;
size_t codesetlen;
if (setlocale_null_r (LC_CTYPE, locale, sizeof (locale)))
locale[0] = '\0';
codeset = buf;
codeset[0] = '\0';
if (locale[0])
{
/* If the locale name contains an encoding after the dot, return it. */
char *dot = strchr (locale, '.');
if (dot)
{
/* Look for the possible @... trailer and remove it, if any. */
char *codeset_start = dot + 1;
char const *modifier = strchr (codeset_start, '@');
if (! modifier)
codeset = codeset_start;
else
{
codesetlen = modifier - codeset_start;
if (codesetlen < sizeof buf)
{
codeset = memcpy (buf, codeset_start, codesetlen);
codeset[codesetlen] = '\0';
}
}
}
}
# if defined _WIN32 && ! defined __CYGWIN__
/* If setlocale is successful, it returns the number of the
codepage, as a string. Otherwise, fall back on Windows API
GetACP, which returns the locale's codepage as a number (although
this doesn't change according to what the 'setlocale' call specified).
Either way, prepend "CP" to make it a valid codeset name. */
codesetlen = strlen (codeset);
if (0 < codesetlen && codesetlen < sizeof buf - 2)
memmove (buf + 2, codeset, codesetlen + 1);
else
sprintf (buf + 2, "%u", GetACP ());
/* For a locale name such as "French_France.65001", in Windows 10,
setlocale now returns "French_France.utf8" instead. */
if (strcmp (buf + 2, "65001") == 0 || strcmp (buf + 2, "utf8") == 0)
return (char *) "UTF-8";
else
{
memcpy (buf, "CP", 2);
strcpy (result, buf);
return result;
}
# else
strcpy (result, codeset);
return result;
#endif
}
#endif
#if REPLACE_NL_LANGINFO
/* Override nl_langinfo with support for added nl_item values. */
# undef nl_langinfo
/* Without locking, on Solaris 11.3, test-nl_langinfo-mt fails, with message
"thread5 disturbed by threadN!", even when threadN invokes only
nl_langinfo (CODESET);
nl_langinfo (CRNCYSTR);
Similarly on Solaris 10. */
# if !NL_LANGINFO_MTSAFE /* Solaris */
# define ITEMS (MAXSTRMSG + 1)
# define MAX_RESULT_LEN 80
static char *
nl_langinfo_unlocked (nl_item item)
{
static char result[ITEMS][MAX_RESULT_LEN];
/* The result of nl_langinfo is in storage that can be overwritten by
other calls to nl_langinfo. */
char *tmp = nl_langinfo (item);
if (item >= 0 && item < ITEMS && tmp != NULL)
{
size_t tmp_len = strlen (tmp);
if (tmp_len < MAX_RESULT_LEN)
strcpy (result[item], tmp);
else
{
/* Produce a truncated result. Oh well... */
result[item][MAX_RESULT_LEN - 1] = '\0';
memcpy (result[item], tmp, MAX_RESULT_LEN - 1);
}
return result[item];
}
else
return tmp;
}
/* Use a lock, so that no two threads can invoke nl_langinfo_unlocked
at the same time. */
/* Prohibit renaming this symbol. */
# undef gl_get_nl_langinfo_lock
# if AVOID_ANY_THREADS
/* The option '--disable-threads' explicitly requests no locking. */
# define nl_langinfo_with_lock nl_langinfo_unlocked
# elif defined _WIN32 && !defined __CYGWIN__
extern __declspec(dllimport) CRITICAL_SECTION *gl_get_nl_langinfo_lock (void);
static char *
nl_langinfo_with_lock (nl_item item)
{
CRITICAL_SECTION *lock = gl_get_nl_langinfo_lock ();
char *ret;
EnterCriticalSection (lock);
ret = nl_langinfo_unlocked (item);
LeaveCriticalSection (lock);
return ret;
}
# elif HAVE_PTHREAD_API
extern
# if defined _WIN32 || defined __CYGWIN__
__declspec(dllimport)
# endif
pthread_mutex_t *gl_get_nl_langinfo_lock (void);
# if HAVE_WEAK_SYMBOLS /* musl libc, FreeBSD, NetBSD, OpenBSD, Haiku */
/* Avoid the need to link with '-lpthread'. */
# pragma weak pthread_mutex_lock
# pragma weak pthread_mutex_unlock
/* Determine whether libpthread is in use. */
# pragma weak pthread_mutexattr_gettype
/* See the comments in lock.h. */
# define pthread_in_use() \
(pthread_mutexattr_gettype != NULL || c11_threads_in_use ())
# else
# define pthread_in_use() 1
# endif
static char *
nl_langinfo_with_lock (nl_item item)
{
if (pthread_in_use())
{
pthread_mutex_t *lock = gl_get_nl_langinfo_lock ();
char *ret;
if (pthread_mutex_lock (lock))
abort ();
ret = nl_langinfo_unlocked (item);
if (pthread_mutex_unlock (lock))
abort ();
return ret;
}
else
return nl_langinfo_unlocked (item);
}
# elif HAVE_THREADS_H
extern mtx_t *gl_get_nl_langinfo_lock (void);
static char *
nl_langinfo_with_lock (nl_item item)
{
mtx_t *lock = gl_get_nl_langinfo_lock ();
char *ret;
if (mtx_lock (lock) != thrd_success)
abort ();
ret = nl_langinfo_unlocked (item);
if (mtx_unlock (lock) != thrd_success)
abort ();
return ret;
}
# endif
# else
/* On other platforms, no lock is needed. */
# define nl_langinfo_with_lock nl_langinfo
# endif
char *
rpl_nl_langinfo (nl_item item)
{
switch (item)
{
# if GNULIB_defined_CODESET
case CODESET:
return ctype_codeset ();
# endif
# if GNULIB_defined_T_FMT_AMPM
case T_FMT_AMPM:
return (char *) "%I:%M:%S %p";
# endif
# if GNULIB_defined_ALTMON
case ALTMON_1:
case ALTMON_2:
case ALTMON_3:
case ALTMON_4:
case ALTMON_5:
case ALTMON_6:
case ALTMON_7:
case ALTMON_8:
case ALTMON_9:
case ALTMON_10:
case ALTMON_11:
case ALTMON_12:
/* We don't ship the appropriate localizations with gnulib. Therefore,
treat ALTMON_i like MON_i. */
item = item - ALTMON_1 + MON_1;
break;
# endif
# if GNULIB_defined_ERA
case ERA:
/* The format is not standardized. In glibc it is a sequence of strings
of the form "direction:offset:start_date:end_date:era_name:era_format"
with an empty string at the end. */
return (char *) "";
case ERA_D_FMT:
/* The %Ex conversion in strftime behaves like %x if the locale does not
have an alternative time format. */
item = D_FMT;
break;
case ERA_D_T_FMT:
/* The %Ec conversion in strftime behaves like %c if the locale does not
have an alternative time format. */
item = D_T_FMT;
break;
case ERA_T_FMT:
/* The %EX conversion in strftime behaves like %X if the locale does not
have an alternative time format. */
item = T_FMT;
break;
case ALT_DIGITS:
/* The format is not standardized. In glibc it is a sequence of 10
strings, appended in memory. */
return (char *) "\0\0\0\0\0\0\0\0\0\0";
# endif
# if GNULIB_defined_YESEXPR || !FUNC_NL_LANGINFO_YESEXPR_WORKS
case YESEXPR:
return (char *) "^[yY]";
case NOEXPR:
return (char *) "^[nN]";
# endif
default:
break;
}
return nl_langinfo_with_lock (item);
}
#else
/* Provide nl_langinfo from scratch, either for native MS-Windows, or
for old Unix platforms without locales, such as Linux libc5 or
BeOS. */
# include <time.h>
char *
nl_langinfo (nl_item item)
{
char buf[100];
struct tm tmm = { 0 };
switch (item)
{
/* nl_langinfo items of the LC_CTYPE category */
case CODESET:
{
char *codeset = ctype_codeset ();
if (*codeset)
return codeset;
}
# ifdef __BEOS__
return (char *) "UTF-8";
# else
return (char *) "ISO-8859-1";
# endif
/* nl_langinfo items of the LC_NUMERIC category */
case RADIXCHAR:
return localeconv () ->decimal_point;
case THOUSEP:
return localeconv () ->thousands_sep;
# ifdef GROUPING
case GROUPING:
return localeconv () ->grouping;
# endif
/* nl_langinfo items of the LC_TIME category.
TODO: Really use the locale. */
case D_T_FMT:
case ERA_D_T_FMT:
return (char *) "%a %b %e %H:%M:%S %Y";
case D_FMT:
case ERA_D_FMT:
return (char *) "%m/%d/%y";
case T_FMT:
case ERA_T_FMT:
return (char *) "%H:%M:%S";
case T_FMT_AMPM:
return (char *) "%I:%M:%S %p";
case AM_STR:
{
static char result[80];
if (!strftime (buf, sizeof result, "%p", &tmm))
return (char *) "AM";
strcpy (result, buf);
return result;
}
case PM_STR:
{
static char result[80];
tmm.tm_hour = 12;
if (!strftime (buf, sizeof result, "%p", &tmm))
return (char *) "PM";
strcpy (result, buf);
return result;
}
case DAY_1:
case DAY_2:
case DAY_3:
case DAY_4:
case DAY_5:
case DAY_6:
case DAY_7:
{
static char result[7][50];
static char const days[][sizeof "Wednesday"] = {
"Sunday", "Monday", "Tuesday", "Wednesday", "Thursday",
"Friday", "Saturday"
};
tmm.tm_wday = item - DAY_1;
if (!strftime (buf, sizeof result[0], "%A", &tmm))
return (char *) days[item - DAY_1];
strcpy (result[item - DAY_1], buf);
return result[item - DAY_1];
}
case ABDAY_1:
case ABDAY_2:
case ABDAY_3:
case ABDAY_4:
case ABDAY_5:
case ABDAY_6:
case ABDAY_7:
{
static char result[7][30];
static char const abdays[][sizeof "Sun"] = {
"Sun", "Mon", "Tue", "Wed", "Thu", "Fri", "Sat"
};
tmm.tm_wday = item - ABDAY_1;
if (!strftime (buf, sizeof result[0], "%a", &tmm))
return (char *) abdays[item - ABDAY_1];
strcpy (result[item - ABDAY_1], buf);
return result[item - ABDAY_1];
}
{
static char const months[][sizeof "September"] = {
"January", "February", "March", "April", "May", "June", "July",
"August", "September", "October", "November", "December"
};
case MON_1:
case MON_2:
case MON_3:
case MON_4:
case MON_5:
case MON_6:
case MON_7:
case MON_8:
case MON_9:
case MON_10:
case MON_11:
case MON_12:
{
static char result[12][50];
tmm.tm_mon = item - MON_1;
if (!strftime (buf, sizeof result[0], "%B", &tmm))
return (char *) months[item - MON_1];
strcpy (result[item - MON_1], buf);
return result[item - MON_1];
}
case ALTMON_1:
case ALTMON_2:
case ALTMON_3:
case ALTMON_4:
case ALTMON_5:
case ALTMON_6:
case ALTMON_7:
case ALTMON_8:
case ALTMON_9:
case ALTMON_10:
case ALTMON_11:
case ALTMON_12:
{
static char result[12][50];
tmm.tm_mon = item - ALTMON_1;
/* The platforms without nl_langinfo() don't support strftime with
%OB. We don't even need to try. */
#if 0
if (!strftime (buf, sizeof result[0], "%OB", &tmm))
#endif
if (!strftime (buf, sizeof result[0], "%B", &tmm))
return (char *) months[item - ALTMON_1];
strcpy (result[item - ALTMON_1], buf);
return result[item - ALTMON_1];
}
}
case ABMON_1:
case ABMON_2:
case ABMON_3:
case ABMON_4:
case ABMON_5:
case ABMON_6:
case ABMON_7:
case ABMON_8:
case ABMON_9:
case ABMON_10:
case ABMON_11:
case ABMON_12:
{
static char result[12][30];
static char const abmonths[][sizeof "Jan"] = {
"Jan", "Feb", "Mar", "Apr", "May", "Jun", "Jul",
"Aug", "Sep", "Oct", "Nov", "Dec"
};
tmm.tm_mon = item - ABMON_1;
if (!strftime (buf, sizeof result[0], "%b", &tmm))
return (char *) abmonths[item - ABMON_1];
strcpy (result[item - ABMON_1], buf);
return result[item - ABMON_1];
}
case ERA:
return (char *) "";
case ALT_DIGITS:
return (char *) "\0\0\0\0\0\0\0\0\0\0";
/* nl_langinfo items of the LC_MONETARY category. */
case CRNCYSTR:
return localeconv () ->currency_symbol;
# ifdef INT_CURR_SYMBOL
case INT_CURR_SYMBOL:
return localeconv () ->int_curr_symbol;
case MON_DECIMAL_POINT:
return localeconv () ->mon_decimal_point;
case MON_THOUSANDS_SEP:
return localeconv () ->mon_thousands_sep;
case MON_GROUPING:
return localeconv () ->mon_grouping;
case POSITIVE_SIGN:
return localeconv () ->positive_sign;
case NEGATIVE_SIGN:
return localeconv () ->negative_sign;
case FRAC_DIGITS:
return & localeconv () ->frac_digits;
case INT_FRAC_DIGITS:
return & localeconv () ->int_frac_digits;
case P_CS_PRECEDES:
return & localeconv () ->p_cs_precedes;
case N_CS_PRECEDES:
return & localeconv () ->n_cs_precedes;
case P_SEP_BY_SPACE:
return & localeconv () ->p_sep_by_space;
case N_SEP_BY_SPACE:
return & localeconv () ->n_sep_by_space;
case P_SIGN_POSN:
return & localeconv () ->p_sign_posn;
case N_SIGN_POSN:
return & localeconv () ->n_sign_posn;
# endif
/* nl_langinfo items of the LC_MESSAGES category
TODO: Really use the locale. */
case YESEXPR:
return (char *) "^[yY]";
case NOEXPR:
return (char *) "^[nN]";
default:
return (char *) "";
}
}
#endif

View File

@@ -0,0 +1,92 @@
/* Program name management.
Copyright (C) 2001-2003, 2005-2024 Free Software Foundation, Inc.
Written by Bruno Haible <bruno@clisp.org>, 2001.
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <https://www.gnu.org/licenses/>. */
#include <config.h>
/* Specification. */
#undef ENABLE_RELOCATABLE /* avoid defining set_program_name as a macro */
#include "progname.h"
#include <errno.h> /* get program_invocation_name declaration */
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
/* String containing name the program is called with.
To be initialized by main(). */
const char *program_name = NULL;
/* Set program_name, based on argv[0].
argv0 must be a string allocated with indefinite extent, and must not be
modified after this call. */
void
set_program_name (const char *argv0)
{
/* libtool creates a temporary executable whose name is sometimes prefixed
with "lt-" (depends on the platform). It also makes argv[0] absolute.
But the name of the temporary executable is a detail that should not be
visible to the end user and to the test suite.
Remove this "<dirname>/.libs/" or "<dirname>/.libs/lt-" prefix here. */
const char *slash;
const char *base;
/* Sanity check. POSIX requires the invoking process to pass a non-NULL
argv[0]. */
if (argv0 == NULL)
{
/* It's a bug in the invoking program. Help diagnosing it. */
fputs ("A NULL argv[0] was passed through an exec system call.\n",
stderr);
abort ();
}
slash = strrchr (argv0, '/');
base = (slash != NULL ? slash + 1 : argv0);
if (base - argv0 >= 7 && strncmp (base - 7, "/.libs/", 7) == 0)
{
argv0 = base;
if (strncmp (base, "lt-", 3) == 0)
{
argv0 = base + 3;
/* On glibc systems, remove the "lt-" prefix from the variable
program_invocation_short_name. */
#if HAVE_DECL_PROGRAM_INVOCATION_SHORT_NAME
program_invocation_short_name = (char *) argv0;
#endif
}
}
/* But don't strip off a leading <dirname>/ in general, because when the user
runs
/some/hidden/place/bin/cp foo foo
he should get the error message
/some/hidden/place/bin/cp: `foo' and `foo' are the same file
not
cp: `foo' and `foo' are the same file
*/
program_name = argv0;
/* On glibc systems, the error() function comes from libc and uses the
variable program_invocation_name, not program_name. So set this variable
as well. */
#if HAVE_DECL_PROGRAM_INVOCATION_NAME
program_invocation_name = (char *) argv0;
#endif
}

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,135 @@
/* Searching in a string.
Copyright (C) 2008-2024 Free Software Foundation, Inc.
This file is free software: you can redistribute it and/or modify
it under the terms of the GNU Lesser General Public License as
published by the Free Software Foundation; either version 2.1 of the
License, or (at your option) any later version.
This file is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU Lesser General Public License for more details.
You should have received a copy of the GNU Lesser General Public License
along with this program. If not, see <https://www.gnu.org/licenses/>. */
#include <config.h>
/* Specification. */
#include <string.h>
/* A function definition is needed only if HAVE_RAWMEMCHR is not defined. */
#if !HAVE_RAWMEMCHR
# include <limits.h>
# include <stdint.h>
/* Find the first occurrence of C in S. */
void *
rawmemchr (const void *s, int c_in)
{
# ifdef __CHERI_PURE_CAPABILITY__
/* Most architectures let you read an aligned word,
even if the unsigned char array at S ends in the middle of the word.
However CHERI does not, so call memchr
with the underlying object's remaining length.
This cannot return NULL if S points to a C_IN-terminated array.
Use builtins rather than including <cheri.h> which is less stable. */
return memchr (s, c_in, (__builtin_cheri_length_get (s)
- __builtin_cheri_offset_get (s)));
# else
/* You can change this typedef to experiment with performance. */
typedef uintptr_t longword;
/* Verify that the longword type lacks padding bits. */
static_assert (UINTPTR_WIDTH == UCHAR_WIDTH * sizeof (uintptr_t));
const unsigned char *char_ptr;
unsigned char c = c_in;
/* Handle the first few bytes by reading one byte at a time.
Do this until CHAR_PTR is aligned on a natural longword boundary,
as using alignof (longword) might be slower. */
for (char_ptr = (const unsigned char *) s;
(uintptr_t) char_ptr % sizeof (longword) != 0;
++char_ptr)
if (*char_ptr == c)
return (void *) char_ptr;
longword const *longword_ptr = s = char_ptr;
/* Compute auxiliary longword values:
repeated_one is a value which has a 1 in every byte.
repeated_c has c in every byte. */
longword repeated_one = (longword) -1 / UCHAR_MAX;
longword repeated_c = repeated_one * c;
longword repeated_hibit = repeated_one * (UCHAR_MAX / 2 + 1);
/* Instead of the traditional loop which tests each byte, we will
test a longword at a time. The tricky part is testing if any of
the bytes in the longword in question are equal to
c. We first use an xor with repeated_c. This reduces the task
to testing whether any of the bytes in longword1 is zero.
(The following comments assume 8-bit bytes, as POSIX requires;
the code's use of UCHAR_MAX should work even if bytes have more
than 8 bits.)
We compute tmp =
((longword1 - repeated_one) & ~longword1) & (repeated_one * 0x80).
That is, we perform the following operations:
1. Subtract repeated_one.
2. & ~longword1.
3. & a mask consisting of 0x80 in every byte.
Consider what happens in each byte:
- If a byte of longword1 is zero, step 1 and 2 transform it into 0xff,
and step 3 transforms it into 0x80. A carry can also be propagated
to more significant bytes.
- If a byte of longword1 is nonzero, let its lowest 1 bit be at
position k (0 <= k <= 7); so the lowest k bits are 0. After step 1,
the byte ends in a single bit of value 0 and k bits of value 1.
After step 2, the result is just k bits of value 1: 2^k - 1. After
step 3, the result is 0. And no carry is produced.
So, if longword1 has only non-zero bytes, tmp is zero.
Whereas if longword1 has a zero byte, call j the position of the least
significant zero byte. Then the result has a zero at positions 0, ...,
j-1 and a 0x80 at position j. We cannot predict the result at the more
significant bytes (positions j+1..3), but it does not matter since we
already have a non-zero bit at position 8*j+7.
The test whether any byte in longword1 is zero is equivalent
to testing whether tmp is nonzero.
This test can read beyond the end of a string, depending on where
C_IN is encountered. However, this is considered safe since the
initialization phase ensured that the read will be aligned,
therefore, the read will not cross page boundaries and will not
cause a fault. */
while (1)
{
longword longword1 = *longword_ptr ^ repeated_c;
if ((((longword1 - repeated_one) & ~longword1) & repeated_hibit) != 0)
break;
longword_ptr++;
}
char_ptr = s = longword_ptr;
/* At this point, we know that one of the sizeof (longword) bytes
starting at char_ptr is == c. If we knew endianness, we
could determine the first such byte without any further memory
accesses, just by looking at the tmp result from the last loop
iteration. However, the following simple and portable code does
not attempt this potential optimization. */
while (*char_ptr != c)
char_ptr++;
return (void *) char_ptr;
# endif
}
#endif

3788
jni/parted/libgnulib/lib/regcomp.c Executable file

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,80 @@
/* Extended regular expression matching and search library.
Copyright (C) 2002-2024 Free Software Foundation, Inc.
This file is part of the GNU C Library.
Contributed by Isamu Hasegawa <isamu@yamato.ibm.com>.
The GNU C Library is free software; you can redistribute it and/or
modify it under the terms of the GNU Lesser General Public
License as published by the Free Software Foundation; either
version 2.1 of the License, or (at your option) any later version.
The GNU C Library is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
Lesser General Public License for more details.
You should have received a copy of the GNU Lesser General Public
License along with the GNU C Library; if not, see
<https://www.gnu.org/licenses/>. */
#define __STDC_WANT_IEC_60559_BFP_EXT__
#ifndef _LIBC
# include <libc-config.h>
# if __GNUC_PREREQ (4, 6)
# pragma GCC diagnostic ignored "-Wsuggest-attribute=pure"
# pragma GCC diagnostic ignored "-Wvla"
# endif
#endif
/* Make sure no one compiles this code with a C++ compiler. */
#if defined __cplusplus && defined _LIBC
# error "This is C code, use a C compiler"
#endif
#ifdef _LIBC
/* We have to keep the namespace clean. */
# define regfree(preg) __regfree (preg)
# define regexec(pr, st, nm, pm, ef) __regexec (pr, st, nm, pm, ef)
# define regcomp(preg, pattern, cflags) __regcomp (preg, pattern, cflags)
# define regerror(errcode, preg, errbuf, errbuf_size) \
__regerror(errcode, preg, errbuf, errbuf_size)
# define re_set_registers(bu, re, nu, st, en) \
__re_set_registers (bu, re, nu, st, en)
# define re_match_2(bufp, string1, size1, string2, size2, pos, regs, stop) \
__re_match_2 (bufp, string1, size1, string2, size2, pos, regs, stop)
# define re_match(bufp, string, size, pos, regs) \
__re_match (bufp, string, size, pos, regs)
# define re_search(bufp, string, size, startpos, range, regs) \
__re_search (bufp, string, size, startpos, range, regs)
# define re_compile_pattern(pattern, length, bufp) \
__re_compile_pattern (pattern, length, bufp)
# define re_set_syntax(syntax) __re_set_syntax (syntax)
# define re_search_2(bufp, st1, s1, st2, s2, startpos, range, regs, stop) \
__re_search_2 (bufp, st1, s1, st2, s2, startpos, range, regs, stop)
# define re_compile_fastmap(bufp) __re_compile_fastmap (bufp)
# include "../locale/localeinfo.h"
#endif
/* On some systems, limits.h sets RE_DUP_MAX to a lower value than
GNU regex allows. Include it before <regex.h>, which correctly
#undefs RE_DUP_MAX and sets it to the right value. */
#include <limits.h>
#include <regex.h>
#include "regex_internal.h"
#include "regex_internal.c"
#include "regcomp.c"
#include "regexec.c"
/* Binary backward compatibility. */
#if _LIBC
# include <shlib-compat.h>
# if SHLIB_COMPAT (libc, GLIBC_2_0, GLIBC_2_3)
link_warning (re_max_failures, "the 're_max_failures' variable is obsolete and will go away.")
int re_max_failures = 2000;
# endif
#endif

File diff suppressed because it is too large Load Diff

4221
jni/parted/libgnulib/lib/regexec.c Executable file

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,175 @@
/* Determine whether string value is affirmation or negative response
according to current locale's data.
Copyright (C) 1996, 1998, 2000, 2002-2003, 2006-2024 Free Software
Foundation, Inc.
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <https://www.gnu.org/licenses/>. */
#include <config.h>
/* Specification. */
#include <stdlib.h>
#include <stddef.h>
#if ENABLE_NLS
# include <sys/types.h>
# include <limits.h>
# include <string.h>
# if HAVE_LANGINFO_YESEXPR
# include <langinfo.h>
# endif
# include <regex.h>
# include "gettext.h"
# define _(msgid) gettext (msgid)
# define N_(msgid) gettext_noop (msgid)
# if HAVE_LANGINFO_YESEXPR
/* Return the localized regular expression pattern corresponding to
ENGLISH_PATTERN. NL_INDEX can be used with nl_langinfo.
The resulting string may only be used until the next nl_langinfo call. */
static const char *
localized_pattern (const char *english_pattern, nl_item nl_index,
bool posixly_correct)
{
const char *translated_pattern;
/* We prefer to get the patterns from a PO file. It would be possible to
always use nl_langinfo (YESEXPR) instead of _("^[yY]"), and
nl_langinfo (NOEXPR) instead of _("^[nN]"), if we could assume that the
system's locale support is good. But this is not the case e.g. on Cygwin.
The localizations of gnulib.pot are of better quality in general.
Also, if we use locale info from non-free systems that don't have a
'localedef' command, we deprive the users of the freedom to localize
this pattern for their preferred language.
But some programs, such as 'cp', 'mv', 'rm', 'find', 'xargs', are
specified by POSIX to use nl_langinfo (YESEXPR). We implement this
behaviour if POSIXLY_CORRECT is set, for the sake of these programs. */
/* If the user wants strict POSIX compliance, use nl_langinfo. */
if (posixly_correct)
{
translated_pattern = nl_langinfo (nl_index);
/* Check against a broken system return value. */
if (translated_pattern != NULL && translated_pattern[0] != '\0')
return translated_pattern;
}
/* Look in the gnulib message catalog. */
translated_pattern = _(english_pattern);
if (translated_pattern == english_pattern)
{
/* The gnulib message catalog provides no translation.
Try the system's message catalog. */
translated_pattern = nl_langinfo (nl_index);
/* Check against a broken system return value. */
if (translated_pattern != NULL && translated_pattern[0] != '\0')
return translated_pattern;
/* Fall back to English. */
translated_pattern = english_pattern;
}
return translated_pattern;
}
# else
# define localized_pattern(english_pattern,nl_index,posixly_correct) \
_(english_pattern)
# endif
static int
try (const char *response, const char *pattern, char **lastp, regex_t *re)
{
if (*lastp == NULL || strcmp (pattern, *lastp) != 0)
{
char *safe_pattern;
/* The pattern has changed. */
if (*lastp != NULL)
{
/* Free the old compiled pattern. */
regfree (re);
free (*lastp);
*lastp = NULL;
}
/* Put the PATTERN into safe memory before calling regcomp.
(regcomp may call nl_langinfo, overwriting PATTERN's storage. */
safe_pattern = strdup (pattern);
if (safe_pattern == NULL)
return -1;
/* Compile the pattern and cache it for future runs. */
if (regcomp (re, safe_pattern, REG_EXTENDED) != 0)
{
free (safe_pattern);
return -1;
}
*lastp = safe_pattern;
}
/* See if the regular expression matches RESPONSE. */
return regexec (re, response, 0, NULL, 0) == 0;
}
#endif
int
rpmatch (const char *response)
{
#if ENABLE_NLS
/* Match against one of the response patterns, compiling the pattern
first if necessary. */
/* We cache the response patterns and compiled regexps here. */
static char *last_yesexpr, *last_noexpr;
static regex_t cached_yesre, cached_nore;
# if HAVE_LANGINFO_YESEXPR
bool posixly_correct = (getenv ("POSIXLY_CORRECT") != NULL);
# endif
const char *yesexpr, *noexpr;
int result;
/* TRANSLATORS: A regular expression testing for an affirmative answer
(english: "yes"). Testing the first character may be sufficient.
Take care to consider upper and lower case.
To enquire the regular expression that your system uses for this
purpose, you can use the command
locale -k LC_MESSAGES | grep '^yesexpr=' */
yesexpr = localized_pattern (N_("^[yY]"), YESEXPR, posixly_correct);
result = try (response, yesexpr, &last_yesexpr, &cached_yesre);
if (result < 0)
return -1;
if (result)
return 1;
/* TRANSLATORS: A regular expression testing for a negative answer
(english: "no"). Testing the first character may be sufficient.
Take care to consider upper and lower case.
To enquire the regular expression that your system uses for this
purpose, you can use the command
locale -k LC_MESSAGES | grep '^noexpr=' */
noexpr = localized_pattern (N_("^[nN]"), NOEXPR, posixly_correct);
result = try (response, noexpr, &last_noexpr, &cached_nore);
if (result < 0)
return -1;
if (result)
return 0;
return -1;
#else
/* Test against "^[yY]" and "^[nN]", hardcoded to avoid requiring regex */
return (*response == 'y' || *response == 'Y' ? 1
: *response == 'n' || *response == 'N' ? 0 : -1);
#endif
}

View File

@@ -0,0 +1,71 @@
/* An interface to read and write that retries after interrupts.
Copyright (C) 1993-1994, 1998, 2002-2006, 2009-2024 Free Software
Foundation, Inc.
This file is free software: you can redistribute it and/or modify
it under the terms of the GNU Lesser General Public License as
published by the Free Software Foundation; either version 2.1 of the
License, or (at your option) any later version.
This file is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU Lesser General Public License for more details.
You should have received a copy of the GNU Lesser General Public License
along with this program. If not, see <https://www.gnu.org/licenses/>. */
#include <config.h>
/* Specification. */
#ifdef SAFE_WRITE
# include "safe-write.h"
#else
# include "safe-read.h"
#endif
/* Get ssize_t. */
#include <sys/types.h>
#include <unistd.h>
#include <errno.h>
#ifdef EINTR
# define IS_EINTR(x) ((x) == EINTR)
#else
# define IS_EINTR(x) 0
#endif
#include "sys-limits.h"
#ifdef SAFE_WRITE
# define safe_rw safe_write
# define rw write
typedef void const *bufptr;
#else
# define safe_rw safe_read
# define rw read
typedef void *bufptr;
#endif
/* Read(write) up to COUNT bytes at BUF from(to) descriptor FD, retrying if
interrupted. Return the number of bytes read(written), zero for EOF,
or -1 upon error. */
ptrdiff_t
safe_rw (int fd, bufptr buf, idx_t count)
{
for (;;)
{
ssize_t result = rw (fd, buf, count <= (size_t) -1 ? count : (size_t) -1);
if (0 <= result)
return result;
else if (IS_EINTR (errno))
continue;
else if (errno == EINVAL && SYS_BUFSIZE_MAX < count)
count = SYS_BUFSIZE_MAX;
else
return result;
}
}

View File

@@ -0,0 +1,151 @@
/* Return the internal lock used by setlocale_null_r.
Copyright (C) 2019-2024 Free Software Foundation, Inc.
This file is free software: you can redistribute it and/or modify
it under the terms of the GNU Lesser General Public License as
published by the Free Software Foundation; either version 2.1 of the
License, or (at your option) any later version.
This file is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU Lesser General Public License for more details.
You should have received a copy of the GNU Lesser General Public License
along with this program. If not, see <https://www.gnu.org/licenses/>. */
/* Written by Bruno Haible <bruno@clisp.org>, 2019. */
#include <config.h>
/* The option '--disable-threads' explicitly requests no locking. */
/* When it is known that the gl_get_setlocale_null_lock function is defined
by a dependency library, it should not be defined here. */
#if AVOID_ANY_THREADS || OMIT_SETLOCALE_LOCK
/* This declaration is solely to ensure that after preprocessing
this file is never empty. */
typedef int dummy;
#else
/* This file defines the internal lock used by setlocale_null_r.
It is a separate compilation unit, so that only one copy of it is
present when linking statically. */
/* Prohibit renaming this symbol. */
# undef gl_get_setlocale_null_lock
/* Macro for exporting a symbol (function, not variable) defined in this file,
when compiled into a shared library. */
# ifndef SHLIB_EXPORTED
# if HAVE_VISIBILITY
/* Override the effect of the compiler option '-fvisibility=hidden'. */
# define SHLIB_EXPORTED __attribute__((__visibility__("default")))
# elif defined _WIN32 || defined __CYGWIN__
# define SHLIB_EXPORTED __declspec(dllexport)
# else
# define SHLIB_EXPORTED
# endif
# endif
# if defined _WIN32 && !defined __CYGWIN__
# define WIN32_LEAN_AND_MEAN /* avoid including junk */
# include <windows.h>
# include "windows-initguard.h"
/* The return type is a 'CRITICAL_SECTION *', not a 'glwthread_mutex_t *',
because the latter is not guaranteed to be a stable ABI in the future. */
/* Make sure the function gets exported from DLLs. */
SHLIB_EXPORTED CRITICAL_SECTION *gl_get_setlocale_null_lock (void);
static glwthread_initguard_t guard = GLWTHREAD_INITGUARD_INIT;
static CRITICAL_SECTION lock;
/* Returns the internal lock used by setlocale_null_r. */
CRITICAL_SECTION *
gl_get_setlocale_null_lock (void)
{
if (!guard.done)
{
if (InterlockedIncrement (&guard.started) == 0)
{
/* This thread is the first one to need the lock. Initialize it. */
InitializeCriticalSection (&lock);
guard.done = 1;
}
else
{
/* Don't let guard.started grow and wrap around. */
InterlockedDecrement (&guard.started);
/* Yield the CPU while waiting for another thread to finish
initializing this mutex. */
while (!guard.done)
Sleep (0);
}
}
return &lock;
}
# elif HAVE_PTHREAD_API
# include <pthread.h>
static pthread_mutex_t mutex = PTHREAD_MUTEX_INITIALIZER;
/* Make sure the function gets exported from shared libraries. */
SHLIB_EXPORTED pthread_mutex_t *gl_get_setlocale_null_lock (void);
/* Returns the internal lock used by setlocale_null_r. */
pthread_mutex_t *
gl_get_setlocale_null_lock (void)
{
return &mutex;
}
# elif HAVE_THREADS_H
# include <threads.h>
# include <stdlib.h>
static int volatile init_needed = 1;
static once_flag init_once = ONCE_FLAG_INIT;
static mtx_t mutex;
static void
atomic_init (void)
{
if (mtx_init (&mutex, mtx_plain) != thrd_success)
abort ();
init_needed = 0;
}
/* Make sure the function gets exported from shared libraries. */
SHLIB_EXPORTED mtx_t *gl_get_setlocale_null_lock (void);
/* Returns the internal lock used by setlocale_null_r. */
mtx_t *
gl_get_setlocale_null_lock (void)
{
if (init_needed)
call_once (&init_once, atomic_init);
return &mutex;
}
# endif
# if (defined _WIN32 || defined __CYGWIN__) && !defined _MSC_VER
/* Make sure the '__declspec(dllimport)' in setlocale_null.c does not cause
a link failure when no DLLs are involved. */
# if defined _WIN64 || defined _LP64
# define IMP(x) __imp_##x
# else
# define IMP(x) _imp__##x
# endif
void * IMP(gl_get_setlocale_null_lock) = &gl_get_setlocale_null_lock;
# endif
#endif

View File

@@ -0,0 +1,149 @@
/* Query the name of the current global locale, without locking.
Copyright (C) 2019-2024 Free Software Foundation, Inc.
This file is free software: you can redistribute it and/or modify
it under the terms of the GNU Lesser General Public License as
published by the Free Software Foundation; either version 2.1 of the
License, or (at your option) any later version.
This file is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU Lesser General Public License for more details.
You should have received a copy of the GNU Lesser General Public License
along with this program. If not, see <https://www.gnu.org/licenses/>. */
/* Written by Bruno Haible <bruno@clisp.org>, 2019. */
#include <config.h>
/* Specification. */
#include "setlocale_null.h"
#include <errno.h>
#include <locale.h>
#include <string.h>
#if defined _WIN32 && !defined __CYGWIN__
# include <wchar.h>
#endif
/* Use the system's setlocale() function, not the gnulib override, here. */
#undef setlocale
const char *
setlocale_null_unlocked (int category)
{
const char *result = setlocale (category, NULL);
#ifdef __ANDROID__
if (result == NULL)
switch (category)
{
case LC_CTYPE:
case LC_NUMERIC:
case LC_TIME:
case LC_COLLATE:
case LC_MONETARY:
case LC_MESSAGES:
case LC_ALL:
case LC_PAPER:
case LC_NAME:
case LC_ADDRESS:
case LC_TELEPHONE:
case LC_MEASUREMENT:
result = "C";
break;
default:
break;
}
#endif
return result;
}
int
setlocale_null_r_unlocked (int category, char *buf, size_t bufsize)
{
#if defined _WIN32 && !defined __CYGWIN__ && defined _MSC_VER
/* On native Windows, nowadays, the setlocale() implementation is based
on _wsetlocale() and uses malloc() for the result. We are better off
using _wsetlocale() directly. */
const wchar_t *result = _wsetlocale (category, NULL);
if (result == NULL)
{
/* CATEGORY is invalid. */
if (bufsize > 0)
/* Return an empty string in BUF.
This is a convenience for callers that don't want to write explicit
code for handling EINVAL. */
buf[0] = '\0';
return EINVAL;
}
else
{
size_t length = wcslen (result);
if (length < bufsize)
{
size_t i;
/* Convert wchar_t[] -> char[], assuming plain ASCII. */
for (i = 0; i <= length; i++)
buf[i] = result[i];
return 0;
}
else
{
if (bufsize > 0)
{
/* Return a truncated result in BUF.
This is a convenience for callers that don't want to write
explicit code for handling ERANGE. */
size_t i;
/* Convert wchar_t[] -> char[], assuming plain ASCII. */
for (i = 0; i < bufsize; i++)
buf[i] = result[i];
buf[bufsize - 1] = '\0';
}
return ERANGE;
}
}
#else
const char *result = setlocale_null_unlocked (category);
if (result == NULL)
{
/* CATEGORY is invalid. */
if (bufsize > 0)
/* Return an empty string in BUF.
This is a convenience for callers that don't want to write explicit
code for handling EINVAL. */
buf[0] = '\0';
return EINVAL;
}
else
{
size_t length = strlen (result);
if (length < bufsize)
{
memcpy (buf, result, length + 1);
return 0;
}
else
{
if (bufsize > 0)
{
/* Return a truncated result in BUF.
This is a convenience for callers that don't want to write
explicit code for handling ERANGE. */
memcpy (buf, result, bufsize - 1);
buf[bufsize - 1] = '\0';
}
return ERANGE;
}
}
#endif
}

View File

@@ -0,0 +1,299 @@
/* Query the name of the current global locale.
Copyright (C) 2019-2024 Free Software Foundation, Inc.
This file is free software: you can redistribute it and/or modify
it under the terms of the GNU Lesser General Public License as
published by the Free Software Foundation; either version 2.1 of the
License, or (at your option) any later version.
This file is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU Lesser General Public License for more details.
You should have received a copy of the GNU Lesser General Public License
along with this program. If not, see <https://www.gnu.org/licenses/>. */
/* Written by Bruno Haible <bruno@clisp.org>, 2019. */
#include <config.h>
/* Specification. */
#include "setlocale_null.h"
#include <errno.h>
#include <locale.h>
#include <stdlib.h>
#include <string.h>
#if !(SETLOCALE_NULL_ALL_MTSAFE && SETLOCALE_NULL_ONE_MTSAFE)
# if AVOID_ANY_THREADS
/* The option '--disable-threads' explicitly requests no locking. */
# elif defined _WIN32 && !defined __CYGWIN__
# define WIN32_LEAN_AND_MEAN /* avoid including junk */
# include <windows.h>
# elif HAVE_PTHREAD_API
# include <pthread.h>
# if HAVE_THREADS_H && HAVE_WEAK_SYMBOLS
# include <threads.h>
# pragma weak thrd_exit
# define c11_threads_in_use() (thrd_exit != NULL)
# else
# define c11_threads_in_use() 0
# endif
# elif HAVE_THREADS_H
# include <threads.h>
# endif
#endif
#if !(SETLOCALE_NULL_ALL_MTSAFE && SETLOCALE_NULL_ONE_MTSAFE) /* musl libc, macOS, FreeBSD, NetBSD, OpenBSD, AIX, Haiku, Cygwin < 3.4.6 */
/* Use a lock, so that no two threads can invoke setlocale_null_r_unlocked
at the same time. */
/* Prohibit renaming this symbol. */
# undef gl_get_setlocale_null_lock
# if AVOID_ANY_THREADS
/* The option '--disable-threads' explicitly requests no locking. */
# define setlocale_null_r_with_lock setlocale_null_r_unlocked
# elif defined _WIN32 && !defined __CYGWIN__
extern __declspec(dllimport) CRITICAL_SECTION *gl_get_setlocale_null_lock (void);
static int
setlocale_null_r_with_lock (int category, char *buf, size_t bufsize)
{
CRITICAL_SECTION *lock = gl_get_setlocale_null_lock ();
int ret;
EnterCriticalSection (lock);
ret = setlocale_null_r_unlocked (category, buf, bufsize);
LeaveCriticalSection (lock);
return ret;
}
# elif HAVE_PTHREAD_API /* musl libc, macOS, FreeBSD, NetBSD, OpenBSD, AIX, Haiku, Cygwin < 3.4.6 */
extern
# if defined _WIN32 || defined __CYGWIN__
__declspec(dllimport)
# endif
pthread_mutex_t *gl_get_setlocale_null_lock (void);
# if HAVE_WEAK_SYMBOLS /* musl libc, FreeBSD, NetBSD, OpenBSD, Haiku */
/* Avoid the need to link with '-lpthread'. */
# pragma weak pthread_mutex_lock
# pragma weak pthread_mutex_unlock
/* Determine whether libpthread is in use. */
# pragma weak pthread_mutexattr_gettype
/* See the comments in lock.h. */
# define pthread_in_use() \
(pthread_mutexattr_gettype != NULL || c11_threads_in_use ())
# else
# define pthread_in_use() 1
# endif
static int
setlocale_null_r_with_lock (int category, char *buf, size_t bufsize)
{
if (pthread_in_use())
{
pthread_mutex_t *lock = gl_get_setlocale_null_lock ();
int ret;
if (pthread_mutex_lock (lock))
abort ();
ret = setlocale_null_r_unlocked (category, buf, bufsize);
if (pthread_mutex_unlock (lock))
abort ();
return ret;
}
else
return setlocale_null_r_unlocked (category, buf, bufsize);
}
# elif HAVE_THREADS_H
extern mtx_t *gl_get_setlocale_null_lock (void);
static int
setlocale_null_r_with_lock (int category, char *buf, size_t bufsize)
{
mtx_t *lock = gl_get_setlocale_null_lock ();
int ret;
if (mtx_lock (lock) != thrd_success)
abort ();
ret = setlocale_null_r_unlocked (category, buf, bufsize);
if (mtx_unlock (lock) != thrd_success)
abort ();
return ret;
}
# endif
#endif
int
setlocale_null_r (int category, char *buf, size_t bufsize)
{
#if SETLOCALE_NULL_ALL_MTSAFE
# if SETLOCALE_NULL_ONE_MTSAFE
return setlocale_null_r_unlocked (category, buf, bufsize);
# else
if (category == LC_ALL)
return setlocale_null_r_unlocked (category, buf, bufsize);
else
return setlocale_null_r_with_lock (category, buf, bufsize);
# endif
#else
# if SETLOCALE_NULL_ONE_MTSAFE
if (category == LC_ALL)
return setlocale_null_r_with_lock (category, buf, bufsize);
else
return setlocale_null_r_unlocked (category, buf, bufsize);
# else
return setlocale_null_r_with_lock (category, buf, bufsize);
# endif
#endif
}
const char *
setlocale_null (int category)
{
#if SETLOCALE_NULL_ALL_MTSAFE && SETLOCALE_NULL_ONE_MTSAFE
return setlocale_null_unlocked (category);
#else
/* This call must be multithread-safe. To achieve this without using
thread-local storage:
1. We use a specific static buffer for each possible CATEGORY
argument. So that different threads can call setlocale_mtsafe
with different CATEGORY arguments, without interfering.
2. We use a simple strcpy or memcpy to fill this static buffer.
Filling it through, for example, strcpy + strcat would not be
guaranteed to leave the buffer's contents intact if another thread
is currently accessing it. If necessary, the contents is first
assembled in a stack-allocated buffer. */
if (category == LC_ALL)
{
# if SETLOCALE_NULL_ALL_MTSAFE
return setlocale_null_unlocked (LC_ALL);
# else
char buf[SETLOCALE_NULL_ALL_MAX];
static char resultbuf[SETLOCALE_NULL_ALL_MAX];
if (setlocale_null_r (LC_ALL, buf, sizeof (buf)))
return "C";
strcpy (resultbuf, buf);
return resultbuf;
# endif
}
else
{
# if SETLOCALE_NULL_ONE_MTSAFE
return setlocale_null_unlocked (category);
# else
enum
{
LC_CTYPE_INDEX,
LC_NUMERIC_INDEX,
LC_TIME_INDEX,
LC_COLLATE_INDEX,
LC_MONETARY_INDEX,
LC_MESSAGES_INDEX,
# ifdef LC_PAPER
LC_PAPER_INDEX,
# endif
# ifdef LC_NAME
LC_NAME_INDEX,
# endif
# ifdef LC_ADDRESS
LC_ADDRESS_INDEX,
# endif
# ifdef LC_TELEPHONE
LC_TELEPHONE_INDEX,
# endif
# ifdef LC_MEASUREMENT
LC_MEASUREMENT_INDEX,
# endif
# ifdef LC_IDENTIFICATION
LC_IDENTIFICATION_INDEX,
# endif
LC_INDICES_COUNT
}
i;
char buf[SETLOCALE_NULL_MAX];
static char resultbuf[LC_INDICES_COUNT][SETLOCALE_NULL_MAX];
int err;
err = setlocale_null_r (category, buf, sizeof (buf));
if (err == EINVAL)
return NULL;
if (err)
return "C";
switch (category)
{
case LC_CTYPE: i = LC_CTYPE_INDEX; break;
case LC_NUMERIC: i = LC_NUMERIC_INDEX; break;
case LC_TIME: i = LC_TIME_INDEX; break;
case LC_COLLATE: i = LC_COLLATE_INDEX; break;
case LC_MONETARY: i = LC_MONETARY_INDEX; break;
case LC_MESSAGES: i = LC_MESSAGES_INDEX; break;
# ifdef LC_PAPER
case LC_PAPER: i = LC_PAPER_INDEX; break;
# endif
# ifdef LC_NAME
case LC_NAME: i = LC_NAME_INDEX; break;
# endif
# ifdef LC_ADDRESS
case LC_ADDRESS: i = LC_ADDRESS_INDEX; break;
# endif
# ifdef LC_TELEPHONE
case LC_TELEPHONE: i = LC_TELEPHONE_INDEX; break;
# endif
# ifdef LC_MEASUREMENT
case LC_MEASUREMENT: i = LC_MEASUREMENT_INDEX; break;
# endif
# ifdef LC_IDENTIFICATION
case LC_IDENTIFICATION: i = LC_IDENTIFICATION_INDEX; break;
# endif
default:
/* If you get here, a #ifdef LC_xxx is missing. */
abort ();
}
strcpy (resultbuf[i], buf);
return resultbuf[i];
# endif
}
#endif
}

View File

@@ -0,0 +1,21 @@
/* stat-related time functions.
Copyright (C) 2012-2024 Free Software Foundation, Inc.
This file is free software: you can redistribute it and/or modify
it under the terms of the GNU Lesser General Public License as
published by the Free Software Foundation; either version 2.1 of the
License, or (at your option) any later version.
This file is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU Lesser General Public License for more details.
You should have received a copy of the GNU Lesser General Public License
along with this program. If not, see <https://www.gnu.org/licenses/>. */
#include <config.h>
#define _GL_STAT_TIME_INLINE _GL_EXTERN_INLINE
#include "stat-time.h"

View File

@@ -0,0 +1,45 @@
/* stripslash.c -- remove redundant trailing slashes from a file name
Copyright (C) 1990, 2001, 2003-2006, 2009-2024 Free Software Foundation,
Inc.
This file is free software: you can redistribute it and/or modify
it under the terms of the GNU Lesser General Public License as
published by the Free Software Foundation; either version 2.1 of the
License, or (at your option) any later version.
This file is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU Lesser General Public License for more details.
You should have received a copy of the GNU Lesser General Public License
along with this program. If not, see <https://www.gnu.org/licenses/>. */
#include <config.h>
#include "dirname.h"
/* Remove trailing slashes from FILE. Return true if a trailing slash
was removed. This is useful when using file name completion from a
shell that adds a "/" after directory names (such as tcsh and
bash), because on symlinks to directories, several system calls
have different semantics according to whether a trailing slash is
present. */
bool
strip_trailing_slashes (char *file)
{
char *base = last_component (file);
char *base_lim;
bool had_slash;
/* last_component returns "" for file system roots, but we need to turn
"///" into "/". */
if (! *base)
base = file;
base_lim = base + base_len (base);
had_slash = (*base_lim != '\0');
*base_lim = '\0';
return had_slash;
}

View File

@@ -0,0 +1,286 @@
/* Copyright (C) 1991-2024 Free Software Foundation, Inc.
This file is part of the GNU C Library.
The GNU C Library is free software; you can redistribute it and/or
modify it under the terms of the GNU Lesser General Public
License as published by the Free Software Foundation; either
version 2.1 of the License, or (at your option) any later version.
The GNU C Library is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
Lesser General Public License for more details.
You should have received a copy of the GNU Lesser General Public
License along with the GNU C Library; if not, see
<https://www.gnu.org/licenses/>. */
#if !_LIBC
# include <libc-config.h>
# include "tempname.h"
#endif
#include <errno.h>
#include <stdio.h>
#ifndef TMP_MAX
# define TMP_MAX 238328
#endif
#ifndef __GT_FILE
# define __GT_FILE 0
# define __GT_DIR 1
# define __GT_NOCREATE 2
#endif
#if !_LIBC && (GT_FILE != __GT_FILE || GT_DIR != __GT_DIR \
|| GT_NOCREATE != __GT_NOCREATE)
# error report this to bug-gnulib@gnu.org
#endif
#include <stdlib.h>
#include <string.h>
#include <fcntl.h>
#include <stdint.h>
#include <sys/random.h>
#include <sys/stat.h>
#include <time.h>
#if _LIBC
# define struct_stat64 struct __stat64_t64
#else
# define struct_stat64 struct stat
# define __gen_tempname gen_tempname
# define __mkdir mkdir
# define __open open
# define __lstat64_time64(file, buf) lstat (file, buf)
# define __getrandom getrandom
# define __clock_gettime64 clock_gettime
# define __timespec64 timespec
#endif
/* Use getrandom if it works, falling back on a 64-bit linear
congruential generator that starts with Var's value
mixed in with a clock's low-order bits if available. */
typedef uint_fast64_t random_value;
#define RANDOM_VALUE_MAX UINT_FAST64_MAX
#define BASE_62_DIGITS 10 /* 62**10 < UINT_FAST64_MAX */
#define BASE_62_POWER (62LL * 62 * 62 * 62 * 62 * 62 * 62 * 62 * 62 * 62)
/* Return the result of mixing the entropy from R and S.
Assume that R and S are not particularly random,
and that the result should look randomish to an untrained eye. */
static random_value
mix_random_values (random_value r, random_value s)
{
/* As this code is used only when high-quality randomness is neither
available nor necessary, there is no need for fancier polynomials
such as those in the Linux kernel's 'random' driver. */
return (2862933555777941757 * r + 3037000493) ^ s;
}
/* Set *R to a random value.
Return true if *R is set to high-quality value taken from getrandom.
Otherwise return false, falling back to a low-quality *R that might
depend on S.
This function returns false only when getrandom fails.
On GNU systems this should happen only early in the boot process,
when the fallback should be good enough for programs using tempname
because any attacker likely has root privileges already. */
static bool
random_bits (random_value *r, random_value s)
{
/* Without GRND_NONBLOCK it can be blocked for minutes on some systems. */
if (__getrandom (r, sizeof *r, GRND_NONBLOCK) == sizeof *r)
return true;
/* If getrandom did not work, use ersatz entropy based on low-order
clock bits. On GNU systems getrandom should fail only
early in booting, when ersatz should be good enough.
Do not use ASLR-based entropy, as that would leak ASLR info into
the resulting file name which is typically public.
Of course we are in a state of sin here. */
random_value v = s;
#if _LIBC || (defined CLOCK_REALTIME && HAVE_CLOCK_GETTIME)
struct __timespec64 tv;
__clock_gettime64 (CLOCK_REALTIME, &tv);
v = mix_random_values (v, tv.tv_sec);
v = mix_random_values (v, tv.tv_nsec);
#endif
*r = mix_random_values (v, clock ());
return false;
}
#if _LIBC
static int try_tempname_len (char *, int, void *, int (*) (char *, void *),
size_t);
#endif
static int
try_file (char *tmpl, void *flags)
{
int *openflags = flags;
return __open (tmpl,
(*openflags & ~O_ACCMODE)
| O_RDWR | O_CREAT | O_EXCL, S_IRUSR | S_IWUSR);
}
static int
try_dir (char *tmpl, _GL_UNUSED void *flags)
{
return __mkdir (tmpl, S_IRUSR | S_IWUSR | S_IXUSR);
}
static int
try_nocreate (char *tmpl, _GL_UNUSED void *flags)
{
struct_stat64 st;
if (__lstat64_time64 (tmpl, &st) == 0 || errno == EOVERFLOW)
__set_errno (EEXIST);
return errno == ENOENT ? 0 : -1;
}
/* These are the characters used in temporary file names. */
static const char letters[] =
"abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789";
/* Generate a temporary file name based on TMPL. TMPL must match the
rules for mk[s]temp (i.e., end in at least X_SUFFIX_LEN "X"s,
possibly with a suffix).
The name constructed does not exist at the time of the call to
this function. TMPL is overwritten with the result.
KIND may be one of:
__GT_NOCREATE: simply verify that the name does not exist
at the time of the call.
__GT_FILE: create the file using open(O_CREAT|O_EXCL)
and return a read-write fd. The file is mode 0600.
__GT_DIR: create a directory, which will be mode 0700.
*/
#ifdef _LIBC
static
#endif
int
gen_tempname_len (char *tmpl, int suffixlen, int flags, int kind,
size_t x_suffix_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;
unsigned int count;
int fd = -1;
int saved_errno = errno;
/* A lower bound on the number of temporary files to attempt to
generate. The maximum total number of temporary file names that
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.
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
conform to POSIX, this must be no smaller than TMP_MAX. */
#if ATTEMPTS_MIN < TMP_MAX
unsigned int attempts = TMP_MAX;
#else
unsigned int attempts = ATTEMPTS_MIN;
#endif
/* A random variable. */
random_value v = 0;
/* A value derived from the random variable, and how many random
base-62 digits can currently be extracted from VDIGBUF. */
random_value vdigbuf;
int vdigits = 0;
/* Least biased value for V. If V is less than this, V can generate
BASE_62_DIGITS unbiased digits. Otherwise the digits are biased. */
random_value const biased_min
= RANDOM_VALUE_MAX - RANDOM_VALUE_MAX % BASE_62_POWER;
len = strlen (tmpl);
if (len < 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 - x_suffix_len - suffixlen];
for (count = 0; count < attempts; ++count)
{
for (size_t i = 0; i < x_suffix_len; i++)
{
if (vdigits == 0)
{
/* Worry about bias only if the bits are high quality. */
while (random_bits (&v, v) && biased_min <= v)
continue;
vdigbuf = v;
vdigits = BASE_62_DIGITS;
}
XXXXXX[i] = letters[vdigbuf % 62];
vdigbuf /= 62;
vdigits--;
}
fd = tryfunc (tmpl, args);
if (fd >= 0)
{
__set_errno (saved_errno);
return fd;
}
else if (errno != EEXIST)
return -1;
}
/* We got out of the loop because we ran out of combinations to try. */
__set_errno (EEXIST);
return -1;
}
int
__gen_tempname (char *tmpl, int suffixlen, int flags, int kind)
{
return gen_tempname_len (tmpl, suffixlen, flags, kind, 6);
}
#if !_LIBC
int
try_tempname (char *tmpl, int suffixlen, void *args,
int (*tryfunc) (char *, void *))
{
return try_tempname_len (tmpl, suffixlen, args, tryfunc, 6);
}
#endif

View File

@@ -0,0 +1,48 @@
/* Three-level bitmap lookup.
Copyright (C) 2000-2002, 2005-2007, 2009-2024 Free Software Foundation, Inc.
Written by Bruno Haible <bruno@clisp.org>, 2000-2002.
This file is free software: you can redistribute it and/or modify
it under the terms of the GNU Lesser General Public License as
published by the Free Software Foundation; either version 2.1 of the
License, or (at your option) any later version.
This file is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU Lesser General Public License for more details.
You should have received a copy of the GNU Lesser General Public License
along with this program. If not, see <https://www.gnu.org/licenses/>. */
static inline int bitmap_lookup (const void *table, ucs4_t uc);
/* These values are currently hardcoded into gen-uni-tables.c, function
output_predicate(). */
#define header_0 16
#define header_2 9
#define header_3 127
#define header_4 15
static inline int
bitmap_lookup (const void *table, ucs4_t uc)
{
unsigned int index1 = uc >> header_0;
if (index1 < ((const int *) table)[0])
{
int lookup1 = ((const int *) table)[1 + index1];
if (lookup1 >= 0)
{
unsigned int index2 = (uc >> header_2) & header_3;
int lookup2 = ((const short *) table)[lookup1 + index2];
if (lookup2 >= 0)
{
unsigned int index3 = (uc >> 5) & header_4;
unsigned int lookup3 = ((const unsigned int *) table)[lookup2 + index3];
return (lookup3 >> (uc & 0x1f)) & 1;
}
}
}
return 0;
}

View File

@@ -0,0 +1,32 @@
/* ISO C <ctype.h> like properties of Unicode characters.
Copyright (C) 2002, 2006-2007, 2009-2024 Free Software Foundation, Inc.
Written by Bruno Haible <bruno@clisp.org>, 2002.
This file is free software: you can redistribute it and/or modify
it under the terms of the GNU Lesser General Public License as
published by the Free Software Foundation; either version 2.1 of the
License, or (at your option) any later version.
This file is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU Lesser General Public License for more details.
You should have received a copy of the GNU Lesser General Public License
along with this program. If not, see <https://www.gnu.org/licenses/>. */
#include <config.h>
/* Specification. */
#include "unictype.h"
#include "bitmap.h"
/* Define u_is_print table. */
#include "ctype_print.h"
bool
uc_is_print (ucs4_t uc)
{
return bitmap_lookup (&u_is_print, uc);
}

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,30 @@
/* Variable with FSF copyright information, for version-etc.
Copyright (C) 1999-2006, 2009-2024 Free Software Foundation, Inc.
This file is free software: you can redistribute it and/or modify
it under the terms of the GNU Lesser General Public License as
published by the Free Software Foundation, either version 3 of the
License, or (at your option) any later version.
This file is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU Lesser General Public License for more details.
You should have received a copy of the GNU Lesser General Public License
along with this program. If not, see <https://www.gnu.org/licenses/>. */
/* Written by Jim Meyering. */
#include <config.h>
/* Specification. */
#include "version-etc.h"
/* Default copyright goes to the FSF. */
const char version_etc_copyright[] =
/* Do *not* mark this string for translation. %s is a copyright
symbol suitable for this locale, and %d is the copyright
year. */
"Copyright %s %d Free Software Foundation, Inc.";

View File

@@ -0,0 +1,262 @@
/* Print --version and bug-reporting information in a consistent format.
Copyright (C) 1999-2024 Free Software Foundation, Inc.
This file is free software: you can redistribute it and/or modify
it under the terms of the GNU Lesser General Public License as
published by the Free Software Foundation, either version 3 of the
License, or (at your option) any later version.
This file is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU Lesser General Public License for more details.
You should have received a copy of the GNU Lesser General Public License
along with this program. If not, see <https://www.gnu.org/licenses/>. */
/* Written by Jim Meyering. */
#include <config.h>
/* Specification. */
#include "version-etc.h"
#include <stdarg.h>
#include <stdio.h>
#if USE_UNLOCKED_IO
# include "unlocked-io.h"
#endif
#include "gettext.h"
#define _(msgid) gettext (msgid)
/* If you use AM_INIT_AUTOMAKE's no-define option,
PACKAGE is not defined. Use PACKAGE_TARNAME instead. */
#if ! defined PACKAGE && defined PACKAGE_TARNAME
# define PACKAGE PACKAGE_TARNAME
#endif
enum { COPYRIGHT_YEAR = 2024 };
/* The three functions below display the --version information the
standard way.
If COMMAND_NAME is NULL, the PACKAGE is assumed to be the name of
the program. The formats are therefore:
PACKAGE VERSION
or
COMMAND_NAME (PACKAGE) VERSION.
The functions differ in the way they are passed author names. */
/* Display the --version information the standard way.
Author names are given in the array AUTHORS. N_AUTHORS is the
number of elements in the array. */
void
version_etc_arn (FILE *stream,
const char *command_name, const char *package,
const char *version,
const char * const * authors, size_t n_authors)
{
if (command_name)
fprintf (stream, "%s (%s) %s\n", command_name, package, version);
else
fprintf (stream, "%s %s\n", package, version);
#ifdef PACKAGE_PACKAGER
# ifdef PACKAGE_PACKAGER_VERSION
fprintf (stream, _("Packaged by %s (%s)\n"), PACKAGE_PACKAGER,
PACKAGE_PACKAGER_VERSION);
# else
fprintf (stream, _("Packaged by %s\n"), PACKAGE_PACKAGER);
# endif
#endif
/* TRANSLATORS: Translate "(C)" to the copyright symbol
(C-in-a-circle), if this symbol is available in the user's
locale. Otherwise, do not translate "(C)"; leave it as-is. */
fprintf (stream, version_etc_copyright, _("(C)"), COPYRIGHT_YEAR);
fputs ("\n", stream);
/* TRANSLATORS: The %s placeholder is the web address of the GPL license. */
fprintf (stream, _("\
License GPLv3+: GNU GPL version 3 or later <%s>.\n\
This is free software: you are free to change and redistribute it.\n\
There is NO WARRANTY, to the extent permitted by law.\n\
"),
"https://gnu.org/licenses/gpl.html");
fputs ("\n", stream);
switch (n_authors)
{
case 0:
/* No authors are given. The caller should output authorship
info after calling this function. */
break;
case 1:
/* TRANSLATORS: %s denotes an author name. */
fprintf (stream, _("Written by %s.\n"), authors[0]);
break;
case 2:
/* TRANSLATORS: Each %s denotes an author name. */
fprintf (stream, _("Written by %s and %s.\n"), authors[0], authors[1]);
break;
case 3:
/* TRANSLATORS: Each %s denotes an author name. */
fprintf (stream, _("Written by %s, %s, and %s.\n"),
authors[0], authors[1], authors[2]);
break;
case 4:
/* TRANSLATORS: Each %s denotes an author name.
You can use line breaks, estimating that each author name occupies
ca. 16 screen columns and that a screen line has ca. 80 columns. */
fprintf (stream, _("Written by %s, %s, %s,\nand %s.\n"),
authors[0], authors[1], authors[2], authors[3]);
break;
case 5:
/* TRANSLATORS: Each %s denotes an author name.
You can use line breaks, estimating that each author name occupies
ca. 16 screen columns and that a screen line has ca. 80 columns. */
fprintf (stream, _("Written by %s, %s, %s,\n%s, and %s.\n"),
authors[0], authors[1], authors[2], authors[3], authors[4]);
break;
case 6:
/* TRANSLATORS: Each %s denotes an author name.
You can use line breaks, estimating that each author name occupies
ca. 16 screen columns and that a screen line has ca. 80 columns. */
fprintf (stream, _("Written by %s, %s, %s,\n%s, %s, and %s.\n"),
authors[0], authors[1], authors[2], authors[3], authors[4],
authors[5]);
break;
case 7:
/* TRANSLATORS: Each %s denotes an author name.
You can use line breaks, estimating that each author name occupies
ca. 16 screen columns and that a screen line has ca. 80 columns. */
fprintf (stream, _("Written by %s, %s, %s,\n%s, %s, %s, and %s.\n"),
authors[0], authors[1], authors[2], authors[3], authors[4],
authors[5], authors[6]);
break;
case 8:
/* TRANSLATORS: Each %s denotes an author name.
You can use line breaks, estimating that each author name occupies
ca. 16 screen columns and that a screen line has ca. 80 columns. */
fprintf (stream, _("\
Written by %s, %s, %s,\n%s, %s, %s, %s,\nand %s.\n"),
authors[0], authors[1], authors[2], authors[3], authors[4],
authors[5], authors[6], authors[7]);
break;
case 9:
/* TRANSLATORS: Each %s denotes an author name.
You can use line breaks, estimating that each author name occupies
ca. 16 screen columns and that a screen line has ca. 80 columns. */
fprintf (stream, _("\
Written by %s, %s, %s,\n%s, %s, %s, %s,\n%s, and %s.\n"),
authors[0], authors[1], authors[2], authors[3], authors[4],
authors[5], authors[6], authors[7], authors[8]);
break;
default:
/* 10 or more authors. Use an abbreviation, since the human reader
will probably not want to read the entire list anyway. */
/* TRANSLATORS: Each %s denotes an author name.
You can use line breaks, estimating that each author name occupies
ca. 16 screen columns and that a screen line has ca. 80 columns. */
fprintf (stream, _("\
Written by %s, %s, %s,\n%s, %s, %s, %s,\n%s, %s, and others.\n"),
authors[0], authors[1], authors[2], authors[3], authors[4],
authors[5], authors[6], authors[7], authors[8]);
break;
}
}
/* Display the --version information the standard way. See the initial
comment to this module, for more information.
Author names are given in the NULL-terminated array AUTHORS. */
void
version_etc_ar (FILE *stream,
const char *command_name, const char *package,
const char *version, const char * const * authors)
{
size_t n_authors;
for (n_authors = 0; authors[n_authors]; n_authors++)
;
version_etc_arn (stream, command_name, package, version, authors, n_authors);
}
/* Display the --version information the standard way. See the initial
comment to this module, for more information.
Author names are given in the NULL-terminated va_list AUTHORS. */
void
version_etc_va (FILE *stream,
const char *command_name, const char *package,
const char *version, va_list authors)
{
size_t n_authors;
const char *authtab[10];
for (n_authors = 0;
n_authors < 10
&& (authtab[n_authors] = va_arg (authors, const char *)) != NULL;
n_authors++)
;
version_etc_arn (stream, command_name, package, version,
authtab, n_authors);
}
/* Display the --version information the standard way.
If COMMAND_NAME is NULL, the PACKAGE is assumed to be the name of
the program. The formats are therefore:
PACKAGE VERSION
or
COMMAND_NAME (PACKAGE) VERSION.
The authors names are passed as separate arguments, with an additional
NULL argument at the end. */
void
version_etc (FILE *stream,
const char *command_name, const char *package,
const char *version, /* const char *author1, ...*/ ...)
{
va_list authors;
va_start (authors, version);
version_etc_va (stream, command_name, package, version, authors);
va_end (authors);
}
void
emit_bug_reporting_address (void)
{
fputs ("\n", stdout);
/* TRANSLATORS: The placeholder indicates the bug-reporting address
for this package. Please add _another line_ saying
"Report translation bugs to <...>\n" with the address for translation
bugs (typically your translation team's web or email address). */
printf (_("Report bugs to: %s\n"), PACKAGE_BUGREPORT);
#ifdef PACKAGE_PACKAGER_BUG_REPORTS
printf (_("Report %s bugs to: %s\n"), PACKAGE_PACKAGER,
PACKAGE_PACKAGER_BUG_REPORTS);
#endif
#ifdef PACKAGE_URL
printf (_("%s home page: <%s>\n"), PACKAGE_NAME, PACKAGE_URL);
#else
printf (_("%s home page: <%s>\n"),
PACKAGE_NAME, "https://www.gnu.org/software/" PACKAGE "/");
#endif
printf (_("General help using GNU software: <%s>\n"),
"https://www.gnu.org/gethelp/");
}

View File

@@ -0,0 +1,25 @@
/* Get descriptor for a wide character property.
Copyright (C) 2011-2024 Free Software Foundation, Inc.
Written by Bruno Haible <bruno@clisp.org>, 2011.
This file is free software: you can redistribute it and/or modify
it under the terms of the GNU Lesser General Public License as
published by the Free Software Foundation; either version 2.1 of the
License, or (at your option) any later version.
This file is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU Lesser General Public License for more details.
You should have received a copy of the GNU Lesser General Public License
along with this program. If not, see <https://www.gnu.org/licenses/>. */
#include <config.h>
/* Specification. */
#include <wctype.h>
#include <string.h>
#include "wctype-impl.h"

View File

@@ -0,0 +1,41 @@
/* Report a memory allocation failure and exit.
Copyright (C) 1997-2000, 2002-2004, 2006, 2009-2024 Free Software
Foundation, Inc.
This 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 "xalloc.h"
#include <stdlib.h>
#include <error.h>
#include "exitfail.h"
#include "gettext.h"
#define _(msgid) gettext (msgid)
void
xalloc_die (void)
{
error (exit_failure, 0, "%s", _("memory exhausted"));
/* _Noreturn cannot be given to error, since it may return if
its first argument is 0. To help compilers understand the
xalloc_die does not return, call abort. Also, the abort is a
safety feature if exit_failure is 0 (which shouldn't happen). */
abort ();
}

View File

@@ -0,0 +1,340 @@
/* xmalloc.c -- malloc with out of memory checking
Copyright (C) 1990-2000, 2002-2006, 2008-2024 Free Software Foundation, Inc.
This 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>
#define XALLOC_INLINE _GL_EXTERN_INLINE
#include "xalloc.h"
#include "ialloc.h"
#include "minmax.h"
#include <stdckdint.h>
#include <stdlib.h>
#include <stdint.h>
#include <string.h>
static void * _GL_ATTRIBUTE_PURE
check_nonnull (void *p)
{
if (!p)
xalloc_die ();
return p;
}
/* Allocate S bytes of memory dynamically, with error checking. */
void *
xmalloc (size_t s)
{
return check_nonnull (malloc (s));
}
void *
ximalloc (idx_t s)
{
return check_nonnull (imalloc (s));
}
char *
xcharalloc (size_t n)
{
return XNMALLOC (n, char);
}
/* Change the size of an allocated block of memory P to S bytes,
with error checking. */
void *
xrealloc (void *p, size_t s)
{
void *r = realloc (p, s);
if (!r && (!p || s))
xalloc_die ();
return r;
}
void *
xirealloc (void *p, idx_t s)
{
return check_nonnull (irealloc (p, s));
}
/* Change the size of an allocated block of memory P to an array of N
objects each of S bytes, with error checking. */
void *
xreallocarray (void *p, size_t n, size_t s)
{
void *r = reallocarray (p, n, s);
if (!r && (!p || (n && s)))
xalloc_die ();
return r;
}
void *
xireallocarray (void *p, idx_t n, idx_t s)
{
return check_nonnull (ireallocarray (p, n, s));
}
/* Allocate an array of N objects, each with S bytes of memory,
dynamically, with error checking. S must be nonzero. */
void *
xnmalloc (size_t n, size_t s)
{
return xreallocarray (NULL, n, s);
}
void *
xinmalloc (idx_t n, idx_t s)
{
return xireallocarray (NULL, n, s);
}
/* If P is null, allocate a block of at least *PS bytes; otherwise,
reallocate P so that it contains more than *PS bytes. *PS must be
nonzero unless P is null. Set *PS to the new block's size, and
return the pointer to the new block. *PS is never set to zero, and
the returned pointer is never null. */
void *
x2realloc (void *p, size_t *ps)
{
return x2nrealloc (p, ps, 1);
}
/* If P is null, allocate a block of at least *PN such objects;
otherwise, reallocate P so that it contains more than *PN objects
each of S bytes. S must be nonzero. Set *PN to the new number of
objects, and return the pointer to the new block. *PN is never set
to zero, and the returned pointer is never null.
Repeated reallocations are guaranteed to make progress, either by
allocating an initial block with a nonzero size, or by allocating a
larger block.
In the following implementation, nonzero sizes are increased by a
factor of approximately 1.5 so that repeated reallocations have
O(N) overall cost rather than O(N**2) cost, but the
specification for this function does not guarantee that rate.
Here is an example of use:
int *p = NULL;
size_t used = 0;
size_t allocated = 0;
void
append_int (int value)
{
if (used == allocated)
p = x2nrealloc (p, &allocated, sizeof *p);
p[used++] = value;
}
This causes x2nrealloc to allocate a block of some nonzero size the
first time it is called.
To have finer-grained control over the initial size, set *PN to a
nonzero value before calling this function with P == NULL. For
example:
int *p = NULL;
size_t used = 0;
size_t allocated = 0;
size_t allocated1 = 1000;
void
append_int (int value)
{
if (used == allocated)
{
p = x2nrealloc (p, &allocated1, sizeof *p);
allocated = allocated1;
}
p[used++] = value;
}
*/
void *
x2nrealloc (void *p, size_t *pn, size_t s)
{
size_t n = *pn;
if (! p)
{
if (! n)
{
/* The approximate size to use for initial small allocation
requests, when the invoking code specifies an old size of
zero. This is the largest "small" request for the GNU C
library malloc. */
enum { DEFAULT_MXFAST = 64 * sizeof (size_t) / 4 };
n = DEFAULT_MXFAST / s;
n += !n;
}
}
else
{
/* Set N = floor (1.5 * N) + 1 to make progress even if N == 0. */
if (ckd_add (&n, n, (n >> 1) + 1))
xalloc_die ();
}
p = xreallocarray (p, n, s);
*pn = n;
return p;
}
/* Grow PA, which points to an array of *PN items, and return the
location of the reallocated array, updating *PN to reflect its
new size. The new array will contain at least N_INCR_MIN more
items, but will not contain more than N_MAX items total.
S is the size of each item, in bytes.
S and N_INCR_MIN must be positive. *PN must be
nonnegative. If N_MAX is -1, it is treated as if it were
infinity.
If PA is null, then allocate a new array instead of reallocating
the old one.
Thus, to grow an array A without saving its old contents, do
{ free (A); A = xpalloc (NULL, &AITEMS, ...); }. */
void *
xpalloc (void *pa, idx_t *pn, idx_t n_incr_min, ptrdiff_t n_max, idx_t s)
{
idx_t n0 = *pn;
/* The approximate size to use for initial small allocation
requests. This is the largest "small" request for the GNU C
library malloc. */
enum { DEFAULT_MXFAST = 64 * sizeof (size_t) / 4 };
/* If the array is tiny, grow it to about (but no greater than)
DEFAULT_MXFAST bytes. Otherwise, grow it by about 50%.
Adjust the growth according to three constraints: N_INCR_MIN,
N_MAX, and what the C language can represent safely. */
idx_t n;
if (ckd_add (&n, n0, n0 >> 1))
n = IDX_MAX;
if (0 <= n_max && n_max < n)
n = n_max;
/* NBYTES is of a type suitable for holding the count of bytes in an object.
This is typically idx_t, but it should be size_t on (theoretical?)
platforms where SIZE_MAX < IDX_MAX so xpalloc does not pass
values greater than SIZE_MAX to xrealloc. */
#if IDX_MAX <= SIZE_MAX
idx_t nbytes;
#else
size_t nbytes;
#endif
idx_t adjusted_nbytes
= (ckd_mul (&nbytes, n, s)
? MIN (IDX_MAX, SIZE_MAX)
: nbytes < DEFAULT_MXFAST ? DEFAULT_MXFAST : 0);
if (adjusted_nbytes)
{
n = adjusted_nbytes / s;
nbytes = adjusted_nbytes - adjusted_nbytes % s;
}
if (! pa)
*pn = 0;
if (n - n0 < n_incr_min
&& (ckd_add (&n, n0, n_incr_min)
|| (0 <= n_max && n_max < n)
|| ckd_mul (&nbytes, n, s)))
xalloc_die ();
pa = xrealloc (pa, nbytes);
*pn = n;
return pa;
}
/* Allocate S bytes of zeroed memory dynamically, with error checking.
There's no need for xnzalloc (N, S), since it would be equivalent
to xcalloc (N, S). */
void *
xzalloc (size_t s)
{
return xcalloc (s, 1);
}
void *
xizalloc (idx_t s)
{
return xicalloc (s, 1);
}
/* Allocate zeroed memory for N elements of S bytes, with error
checking. S must be nonzero. */
void *
xcalloc (size_t n, size_t s)
{
return check_nonnull (calloc (n, s));
}
void *
xicalloc (idx_t n, idx_t s)
{
return check_nonnull (icalloc (n, s));
}
/* Clone an object P of size S, with error checking. There's no need
for xnmemdup (P, N, S), since xmemdup (P, N * S) works without any
need for an arithmetic overflow check. */
void *
xmemdup (void const *p, size_t s)
{
return memcpy (xmalloc (s), p, s);
}
void *
ximemdup (void const *p, idx_t s)
{
return memcpy (ximalloc (s), p, s);
}
/* Clone an object P of size S, with error checking. Append
a terminating NUL byte. */
char *
ximemdup0 (void const *p, idx_t s)
{
char *result = ximalloc (s + 1);
result[s] = 0;
return memcpy (result, p, s);
}
/* Clone STRING. */
char *
xstrdup (char const *string)
{
return xmemdup (string, strlen (string) + 1);
}

View File

@@ -0,0 +1,236 @@
/* A more useful interface to strtol.
Copyright (C) 1995-1996, 1998-2001, 2003-2007, 2009-2024 Free Software
Foundation, Inc.
This 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. */
#ifndef __strtol
# define __strtol strtol
# define __strtol_t long int
# define __xstrtol xstrtol
# define STRTOL_T_MINIMUM LONG_MIN
# define STRTOL_T_MAXIMUM LONG_MAX
#endif
#include <config.h>
#include "xstrtol.h"
#include <ctype.h>
#include <errno.h>
#include <limits.h>
#include <stdckdint.h>
#include <stdlib.h>
#include <string.h>
#if XSTRTOL_INCLUDE_INTTYPES_H
# include <inttypes.h>
#endif
#include "intprops.h"
static strtol_error
bkm_scale (__strtol_t *x, int scale_factor)
{
__strtol_t scaled;
if (ckd_mul (&scaled, *x, scale_factor))
{
*x = *x < 0 ? TYPE_MINIMUM (__strtol_t) : TYPE_MAXIMUM (__strtol_t);
return LONGINT_OVERFLOW;
}
*x = scaled;
return LONGINT_OK;
}
static strtol_error
bkm_scale_by_power (__strtol_t *x, int base, int power)
{
strtol_error err = LONGINT_OK;
while (power--)
err |= bkm_scale (x, base);
return err;
}
strtol_error
__xstrtol (char const *nptr, char **endptr, int base,
__strtol_t *val, char const *valid_suffixes)
{
char *t_ptr;
char **p = endptr ? endptr : &t_ptr;
if (! TYPE_SIGNED (__strtol_t))
{
char const *q = nptr;
unsigned char ch = *q;
while (isspace (ch))
ch = *++q;
if (ch == '-')
{
*p = (char *) nptr;
return LONGINT_INVALID;
}
}
errno = 0;
__strtol_t tmp = __strtol (nptr, p, base);
strtol_error err = LONGINT_OK;
if (*p == nptr)
{
/* If there is no number but there is a valid suffix, assume the
number is 1. The string is invalid otherwise. */
if (! (valid_suffixes && *nptr && strchr (valid_suffixes, *nptr)))
return LONGINT_INVALID;
tmp = 1;
}
else if (errno != 0)
{
if (errno != ERANGE)
return LONGINT_INVALID;
err = LONGINT_OVERFLOW;
}
/* Let valid_suffixes == NULL mean "allow any suffix". */
/* FIXME: update all callers except the ones that allow suffixes
after the number, changing last parameter NULL to "". */
if (!valid_suffixes)
{
*val = tmp;
return err;
}
if (**p != '\0')
{
int xbase = 1024;
int suffixes = 1;
strtol_error overflow;
if (!strchr (valid_suffixes, **p))
{
*val = tmp;
return err | LONGINT_INVALID_SUFFIX_CHAR;
}
switch (**p)
{
case 'E': case 'G': case 'g': case 'k': case 'K': case 'M': case 'm':
case 'P': case 'Q': case 'R': case 'T': case 't': case 'Y': case 'Z':
/* The "valid suffix" '0' is a special flag meaning that
an optional second suffix is allowed, which can change
the base. A suffix "B" (e.g. "100MB") stands for a power
of 1000, whereas a suffix "iB" (e.g. "100MiB") stands for
a power of 1024. If no suffix (e.g. "100M"), assume
power-of-1024. */
if (strchr (valid_suffixes, '0'))
switch (p[0][1])
{
case 'i':
if (p[0][2] == 'B')
suffixes += 2;
break;
case 'B':
case 'D': /* 'D' is obsolescent */
xbase = 1000;
suffixes++;
break;
}
}
switch (**p)
{
case 'b':
overflow = bkm_scale (&tmp, 512);
break;
case 'B':
/* This obsolescent first suffix is distinct from the 'B'
second suffix above. E.g., 'tar -L 1000B' means change
the tape after writing 1000 KiB of data. */
overflow = bkm_scale (&tmp, 1024);
break;
case 'c':
overflow = LONGINT_OK;
break;
case 'E': /* exa or exbi */
overflow = bkm_scale_by_power (&tmp, xbase, 6);
break;
case 'G': /* giga or gibi */
case 'g': /* 'g' is undocumented; for compatibility only */
overflow = bkm_scale_by_power (&tmp, xbase, 3);
break;
case 'k': /* kilo */
case 'K': /* kibi */
overflow = bkm_scale_by_power (&tmp, xbase, 1);
break;
case 'M': /* mega or mebi */
case 'm': /* 'm' is undocumented; for compatibility only */
overflow = bkm_scale_by_power (&tmp, xbase, 2);
break;
case 'P': /* peta or pebi */
overflow = bkm_scale_by_power (&tmp, xbase, 5);
break;
case 'Q': /* quetta or 2**100 */
overflow = bkm_scale_by_power (&tmp, xbase, 10);
break;
case 'R': /* ronna or 2**90 */
overflow = bkm_scale_by_power (&tmp, xbase, 9);
break;
case 'T': /* tera or tebi */
case 't': /* 't' is undocumented; for compatibility only */
overflow = bkm_scale_by_power (&tmp, xbase, 4);
break;
case 'w':
overflow = bkm_scale (&tmp, 2);
break;
case 'Y': /* yotta or 2**80 */
overflow = bkm_scale_by_power (&tmp, xbase, 8);
break;
case 'Z': /* zetta or 2**70 */
overflow = bkm_scale_by_power (&tmp, xbase, 7);
break;
default:
*val = tmp;
return err | LONGINT_INVALID_SUFFIX_CHAR;
}
err |= overflow;
*p += suffixes;
if (**p)
err |= LONGINT_INVALID_SUFFIX_CHAR;
}
*val = tmp;
return err;
}

View File

@@ -0,0 +1,23 @@
/* Convert string to 'long long', with error checking.
Copyright (C) 2011-2024 Free Software Foundation, Inc.
This file is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published
by the Free Software Foundation, either version 3 of the License,
or (at your option) any later version.
This file is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <https://www.gnu.org/licenses/>. */
#define __strtol strtoll
#define __strtol_t long long int
#define __xstrtol xstrtoll
#define STRTOL_T_MINIMUM LLONG_MIN
#define STRTOL_T_MAXIMUM LLONG_MAX
#include "xstrtol.c"

View File

@@ -0,0 +1,23 @@
/* Convert string to 'unsigned long', with error checking.
Copyright (C) 1994-2024 Free Software Foundation, Inc.
This file is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published
by the Free Software Foundation, either version 3 of the License,
or (at your option) any later version.
This file is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <https://www.gnu.org/licenses/>. */
#define __strtol strtoul
#define __strtol_t unsigned long int
#define __xstrtol xstrtoul
#define STRTOL_T_MINIMUM 0
#define STRTOL_T_MAXIMUM ULONG_MAX
#include "xstrtol.c"

View File

@@ -0,0 +1,23 @@
/* Convert string to 'unsigned long long', with error checking.
Copyright (C) 2010-2024 Free Software Foundation, Inc.
This file is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published
by the Free Software Foundation, either version 3 of the License,
or (at your option) any later version.
This file is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <https://www.gnu.org/licenses/>. */
#define __strtol strtoull
#define __strtol_t unsigned long long int
#define __xstrtol xstrtoull
#define STRTOL_T_MINIMUM 0
#define STRTOL_T_MAXIMUM ULLONG_MAX
#include "xstrtol.c"