Update to glibc 2.38

This commit is contained in:
Daryl Ronningen 2023-12-08 00:32:25 -08:00
parent e5fe9ad9e8
commit d00c5ab37f
Signed by: Daryl Ronningen
GPG key ID: FD23F0C934A5EC6B
15 changed files with 432 additions and 215 deletions

View file

@ -1,3 +1,8 @@
2023-12-08 Daryl Ronningen <relms@relms.dev>
* Updated argp to glibc 2.38
* configure.ac: Bumped version to 1.6.0.
2021-02-10 Érico Nogueira <ericonr@disroot.org>
* configure.ac: Bumped version to 1.4.0.

View file

@ -7,8 +7,5 @@ libc {
# a*
argp_error; argp_failure; argp_help; argp_parse; argp_state_help;
argp_usage;
# kludge for recursive argp callers that know the magic.
_argp_unlock_xxx;
}
}

View file

@ -1,5 +1,5 @@
/* Default definition for ARGP_PROGRAM_BUG_ADDRESS.
Copyright (C) 1996-2021 Free Software Foundation, Inc.
Copyright (C) 1996-2023 Free Software Foundation, Inc.
This file is part of the GNU C Library.
Written by Miles Bader <miles@gnu.ai.mit.edu>.

View file

@ -1,5 +1,5 @@
/* Default definition for ARGP_ERR_EXIT_STATUS
Copyright (C) 1997-2021 Free Software Foundation, Inc.
Copyright (C) 1997-2023 Free Software Foundation, Inc.
This file is part of the GNU C Library.
Written by Miles Bader <miles@gnu.ai.mit.edu>.

View file

@ -1,5 +1,5 @@
/* Word-wrapping and line-truncating streams
Copyright (C) 1997-2021 Free Software Foundation, Inc.
Copyright (C) 1997-2023 Free Software Foundation, Inc.
This file is part of the GNU C Library.
Written by Miles Bader <miles@gnu.ai.mit.edu>.

View file

@ -1,5 +1,5 @@
/* Word-wrapping and line-truncating streams.
Copyright (C) 1997-2021 Free Software Foundation, Inc.
Copyright (C) 1997-2023 Free Software Foundation, Inc.
This file is part of the GNU C Library.
Written by Miles Bader <miles@gnu.ai.mit.edu>.

View file

@ -1,5 +1,5 @@
/* Hierarchial argument parsing help output
Copyright (C) 1995-2021 Free Software Foundation, Inc.
Copyright (C) 1995-2023 Free Software Foundation, Inc.
This file is part of the GNU C Library.
Written by Miles Bader <miles@gnu.ai.mit.edu>.
@ -68,8 +68,17 @@ char *alloca ();
# endif
#endif
/* can't use macro due to double evaluation */
static char * dgettext_safe(const char *d, const char *m) { return m ? dgettext(d, m) : NULL; }
#if !0
# if HAVE_STRERROR_R
# if !HAVE_DECL_STRERROR_R
char *strerror_r (int errnum, char *buf, size_t buflen);
# endif
# else
# if !HAVE_DECL_STRERROR
char *strerror (int errnum);
# endif
# endif
#endif
#include <argp.h>
#include <argp-fmtstream.h>
@ -79,6 +88,8 @@ static char * dgettext_safe(const char *d, const char *m) { return m ? dgettext(
# define SIZE_MAX ((size_t) -1)
#endif
/* ========================================================================== */
/* User-selectable (using an environment variable) formatting parameters.
These may be specified in an environment variable called `ARGP_HELP_FMT',
@ -158,7 +169,7 @@ fill_in_uparams (const struct argp_state *state)
{
const char *var = getenv ("ARGP_HELP_FMT");
#define SKIPWS(p) do { while (isspace (*p)) p++; } while (0);
#define SKIPWS(p) do { while (isspace ((unsigned char) *p)) p++; } while (0);
if (var)
/* Parse var. */
@ -166,14 +177,14 @@ fill_in_uparams (const struct argp_state *state)
{
SKIPWS (var);
if (isalpha (*var))
if (isalpha ((unsigned char) *var))
{
size_t var_len;
const struct uparam_name *un;
int unspec = 0, val = 0;
const char *arg = var;
while (isalnum (*arg) || *arg == '-' || *arg == '_')
while (isalnum ((unsigned char) *arg) || *arg == '-' || *arg == '_')
arg++;
var_len = arg - var;
@ -198,11 +209,11 @@ fill_in_uparams (const struct argp_state *state)
else
val = 1;
}
else if (isdigit (*arg))
else if (isdigit ((unsigned char) *arg))
{
val = atoi (arg);
while (isdigit (*arg))
arg++;
char *ep;
val = strtol (arg, &ep, 10);
arg = ep;
SKIPWS (arg);
}
@ -245,6 +256,8 @@ fill_in_uparams (const struct argp_state *state)
}
}
/* ========================================================================== */
/* Returns true if OPT hasn't been marked invisible. Visibility only affects
whether OPT is displayed or used in sorting, not option shadowing. */
#define ovisible(opt) (! ((opt)->flags & OPTION_HIDDEN))
@ -337,6 +350,9 @@ find_char (char ch, char *beg, char *end)
return 0;
}
/* -------------------------------------------------------------------------- */
/* Data structure: HOL = Help Option List */
struct hol_cluster; /* fwd decl */
struct hol_entry
@ -355,11 +371,11 @@ struct hol_entry
char *short_options;
/* Entries are sorted by their group first, in the order:
1, 2, ..., n, 0, -m, ..., -2, -1
0, 1, 2, ..., n, -m, ..., -2, -1
and then alphabetically within each group. The default is 0. */
int group;
/* The cluster of options this entry belongs to, or 0 if none. */
/* The cluster of options this entry belongs to, or NULL if none. */
struct hol_cluster *cluster;
/* The argp from which this option came. */
@ -381,7 +397,7 @@ struct hol_cluster
same depth (clusters always follow options in the same group). */
int group;
/* The cluster to which this cluster belongs, or 0 if it's at the base
/* The cluster to which this cluster belongs, or NULL if it's at the base
level. */
struct hol_cluster *parent;
@ -414,7 +430,7 @@ struct hol
};
/* Create a struct hol from the options in ARGP. CLUSTER is the
hol_cluster in which these entries occur, or 0, if at the root. */
hol_cluster in which these entries occur, or NULL if at the root. */
static struct hol *
make_hol (const struct argp *argp, struct hol_cluster *cluster)
{
@ -532,6 +548,9 @@ hol_free (struct hol *hol)
free (hol);
}
/* Iterate across the short_options of the given ENTRY. Call FUNC for each.
Stop when such a call returns a non-zero value, and return this value.
If all FUNC invocations returned 0, return 0. */
static int
hol_entry_short_iterate (const struct hol_entry *entry,
int (*func)(const struct argp_option *opt,
@ -557,6 +576,9 @@ hol_entry_short_iterate (const struct hol_entry *entry,
return val;
}
/* Iterate across the long options of the given ENTRY. Call FUNC for each.
Stop when such a call returns a non-zero value, and return this value.
If all FUNC invocations returned 0, return 0. */
static inline int
__attribute__ ((always_inline))
hol_entry_long_iterate (const struct hol_entry *entry,
@ -581,7 +603,7 @@ hol_entry_long_iterate (const struct hol_entry *entry,
return val;
}
/* Iterator that returns true for the first short option. */
/* A filter that returns true for the first short option of a given ENTRY. */
static inline int
until_short (const struct argp_option *opt, const struct argp_option *real,
const char *domain, void *cookie)
@ -597,7 +619,7 @@ hol_entry_first_short (const struct hol_entry *entry)
entry->argp->argp_domain, 0);
}
/* Returns the first valid long option in ENTRY, or 0 if there is none. */
/* Returns the first valid long option in ENTRY, or NULL if there is none. */
static const char *
hol_entry_first_long (const struct hol_entry *entry)
{
@ -609,7 +631,7 @@ hol_entry_first_long (const struct hol_entry *entry)
return 0;
}
/* Returns the entry in HOL with the long option name NAME, or 0 if there is
/* Returns the entry in HOL with the long option name NAME, or NULL if there is
none. */
static struct hol_entry *
hol_find_entry (struct hol *hol, const char *name)
@ -644,37 +666,93 @@ hol_set_group (struct hol *hol, const char *name, int group)
entry->group = group;
}
/* Order by group: 0, 1, 2, ..., n, -m, ..., -2, -1.
EQ is what to return if GROUP1 and GROUP2 are the same. */
/* -------------------------------------------------------------------------- */
/* Sorting the entries in a HOL. */
/* Order by group: 0, 1, 2, ..., n, -m, ..., -2, -1. */
static int
group_cmp (int group1, int group2, int eq)
group_cmp (int group1, int group2)
{
if (group1 == group2)
return eq;
else if ((group1 < 0 && group2 < 0) || (group1 >= 0 && group2 >= 0))
if ((group1 < 0 && group2 < 0) || (group1 >= 0 && group2 >= 0))
return group1 - group2;
else
/* Return > 0 if group1 < 0 <= group2.
Return < 0 if group2 < 0 <= group1. */
return group2 - group1;
}
/* Compare clusters CL1 & CL2 by the order that they should appear in
/* Compare clusters CL1 and CL2 by the order that they should appear in
output. Assume CL1 and CL2 have the same parent. */
static int
hol_sibling_cluster_cmp (const struct hol_cluster *cl1,
const struct hol_cluster *cl2)
{
/* Compare by group first. */
int cmp = group_cmp (cl1->group, cl2->group);
if (cmp != 0)
return cmp;
/* Within a group, compare by index within the group. */
return cl2->index - cl1->index;
}
/* Compare clusters CL1 and CL2 by the order that they should appear in
output. Assume CL1 and CL2 are at the same depth. */
static int
hol_cousin_cluster_cmp (const struct hol_cluster *cl1,
const struct hol_cluster *cl2)
{
if (cl1->parent == cl2->parent)
return hol_sibling_cluster_cmp (cl1, cl2);
else
{
/* Compare the parent clusters first. */
int cmp = hol_cousin_cluster_cmp (cl1->parent, cl2->parent);
if (cmp != 0)
return cmp;
/* Next, compare by group. */
cmp = group_cmp (cl1->group, cl2->group);
if (cmp != 0)
return cmp;
/* Next, within a group, compare by index within the group. */
return cl2->index - cl1->index;
}
}
/* Compare clusters CL1 and CL2 by the order that they should appear in
output. */
static int
hol_cluster_cmp (const struct hol_cluster *cl1, const struct hol_cluster *cl2)
{
/* If one cluster is deeper than the other, use its ancestor at the same
level, so that finding the common ancestor is straightforward. */
while (cl1->depth > cl2->depth)
cl1 = cl1->parent;
while (cl2->depth > cl1->depth)
cl2 = cl2->parent;
level. Then, go by the rule that entries that are not in a sub-cluster
come before entries in a sub-cluster. */
if (cl1->depth > cl2->depth)
{
do
cl1 = cl1->parent;
while (cl1->depth > cl2->depth);
int cmp = hol_cousin_cluster_cmp (cl1, cl2);
if (cmp != 0)
return cmp;
/* Now reduce both clusters to their ancestors at the point where both have
a common parent; these can be directly compared. */
while (cl1->parent != cl2->parent)
cl1 = cl1->parent, cl2 = cl2->parent;
return 1;
}
else if (cl1->depth < cl2->depth)
{
do
cl2 = cl2->parent;
while (cl1->depth < cl2->depth);
int cmp = hol_cousin_cluster_cmp (cl1, cl2);
if (cmp != 0)
return cmp;
return group_cmp (cl1->group, cl2->group, cl2->index - cl1->index);
return -1;
}
else
return hol_cousin_cluster_cmp (cl1, cl2);
}
/* Return the ancestor of CL that's just below the root (i.e., has a parent
@ -687,17 +765,7 @@ hol_cluster_base (struct hol_cluster *cl)
return cl;
}
/* Return true if CL1 is a child of CL2. */
static int
hol_cluster_is_child (const struct hol_cluster *cl1,
const struct hol_cluster *cl2)
{
while (cl1 && cl1 != cl2)
cl1 = cl1->parent;
return cl1 == cl2;
}
/* Given the name of a OPTION_DOC option, modifies NAME to start at the tail
/* Given the name of an OPTION_DOC option, modifies *NAME to start at the tail
that should be used for comparisons, and returns true iff it should be
treated as a non-option. */
static int
@ -705,92 +773,129 @@ canon_doc_option (const char **name)
{
int non_opt;
/* Skip initial whitespace. */
while (isspace (**name))
while (isspace ((unsigned char) **name))
(*name)++;
/* Decide whether this looks like an option (leading `-') or not. */
/* Decide whether this looks like an option (leading '-') or not. */
non_opt = (**name != '-');
/* Skip until part of name used for sorting. */
while (**name && !isalnum (**name))
while (**name && !isalnum ((unsigned char) **name))
(*name)++;
return non_opt;
}
/* Order ENTRY1 & ENTRY2 by the order which they should appear in a help
listing. */
/* Order ENTRY1 and ENTRY2 by the order which they should appear in a help
listing.
This function implements a total order, that is:
- if cmp (entry1, entry2) < 0 and cmp (entry2, entry3) < 0,
then cmp (entry1, entry3) < 0.
- if cmp (entry1, entry2) < 0 and cmp (entry2, entry3) == 0,
then cmp (entry1, entry3) < 0.
- if cmp (entry1, entry2) == 0 and cmp (entry2, entry3) < 0,
then cmp (entry1, entry3) < 0.
- if cmp (entry1, entry2) == 0 and cmp (entry2, entry3) == 0,
then cmp (entry1, entry3) == 0. */
static int
hol_entry_cmp (const struct hol_entry *entry1,
const struct hol_entry *entry2)
{
/* The group numbers by which the entries should be ordered; if either is
in a cluster, then this is just the group within the cluster. */
int group1 = entry1->group, group2 = entry2->group;
/* First, compare the group numbers. For entries within a cluster, what
matters is the group number of the base cluster in which the entry
resides. */
int group1 = (entry1->cluster
? hol_cluster_base (entry1->cluster)->group
: entry1->group);
int group2 = (entry2->cluster
? hol_cluster_base (entry2->cluster)->group
: entry2->group);
int cmp = group_cmp (group1, group2);
if (cmp != 0)
return cmp;
if (entry1->cluster != entry2->cluster)
/* The group numbers are the same. */
/* Entries that are not in a cluster come before entries in a cluster. */
cmp = (entry1->cluster != NULL) - (entry2->cluster != NULL);
if (cmp != 0)
return cmp;
/* Compare the clusters. */
if (entry1->cluster != NULL)
{
/* The entries are not within the same cluster, so we can't compare them
directly, we have to use the appropriate clustering level too. */
if (! entry1->cluster)
/* ENTRY1 is at the `base level', not in a cluster, so we have to
compare it's group number with that of the base cluster in which
ENTRY2 resides. Note that if they're in the same group, the
clustered option always comes last. */
return group_cmp (group1, hol_cluster_base (entry2->cluster)->group, -1);
else if (! entry2->cluster)
/* Likewise, but ENTRY2's not in a cluster. */
return group_cmp (hol_cluster_base (entry1->cluster)->group, group2, 1);
else
/* Both entries are in clusters, we can just compare the clusters. */
return hol_cluster_cmp (entry1->cluster, entry2->cluster);
cmp = hol_cluster_cmp (entry1->cluster, entry2->cluster);
if (cmp != 0)
return cmp;
}
else if (group1 == group2)
/* The entries are both in the same cluster and group, so compare them
alphabetically. */
/* For entries in the same cluster, compare also the group numbers
within the cluster. */
cmp = group_cmp (entry1->group, entry2->group);
if (cmp != 0)
return cmp;
/* The entries are both in the same group and the same cluster. */
/* 'documentation' options always follow normal options (or documentation
options that *look* like normal options). */
const char *long1 = hol_entry_first_long (entry1);
const char *long2 = hol_entry_first_long (entry2);
int doc1 =
(odoc (entry1->opt) ? long1 != NULL && canon_doc_option (&long1) : 0);
int doc2 =
(odoc (entry2->opt) ? long2 != NULL && canon_doc_option (&long2) : 0);
cmp = doc1 - doc2;
if (cmp != 0)
return cmp;
/* Compare the entries alphabetically. */
/* First, compare the first character of the options.
Put entries without *any* valid options (such as options with
OPTION_HIDDEN set) first. But as they're not displayed, it doesn't
matter where they are. */
int short1 = hol_entry_first_short (entry1);
int short2 = hol_entry_first_short (entry2);
unsigned char first1 = short1 ? short1 : long1 != NULL ? *long1 : 0;
unsigned char first2 = short2 ? short2 : long2 != NULL ? *long2 : 0;
/* Compare ignoring case. */
/* Use tolower, not _tolower, since the latter has undefined behaviour
for characters that are not uppercase letters. */
cmp = tolower (first1) - tolower (first2);
if (cmp != 0)
return cmp;
/* When the options start with the same letter (ignoring case), lower-case
comes first. */
cmp = first2 - first1;
if (cmp != 0)
return cmp;
/* The first character of the options agree. */
/* Put entries with a short option before entries without a short option. */
cmp = (short1 != 0) - (short2 != 0);
if (cmp != 0)
return cmp;
/* Compare entries without a short option by comparing the long option. */
if (short1 == 0)
{
int short1 = hol_entry_first_short (entry1);
int short2 = hol_entry_first_short (entry2);
int doc1 = odoc (entry1->opt);
int doc2 = odoc (entry2->opt);
const char *long1 = hol_entry_first_long (entry1);
const char *long2 = hol_entry_first_long (entry2);
cmp = (long1 != NULL) - (long2 != NULL);
if (cmp != 0)
return cmp;
if (doc1)
doc1 = long1 != NULL && canon_doc_option (&long1);
if (doc2)
doc2 = long2 != NULL && canon_doc_option (&long2);
if (doc1 != doc2)
/* `documentation' options always follow normal options (or
documentation options that *look* like normal options). */
return doc1 - doc2;
else if (!short1 && !short2 && long1 && long2)
/* Only long options. */
return __strcasecmp (long1, long2);
else
/* Compare short/short, long/short, short/long, using the first
character of long options. Entries without *any* valid
options (such as options with OPTION_HIDDEN set) will be put
first, but as they're not displayed, it doesn't matter where
they are. */
if (long1 != NULL)
{
char first1 = short1 ? short1 : long1 ? *long1 : 0;
char first2 = short2 ? short2 : long2 ? *long2 : 0;
#ifdef _tolower
int lower_cmp = _tolower (first1) - _tolower (first2);
#else
int lower_cmp = tolower (first1) - tolower (first2);
#endif
/* Compare ignoring case, except when the options are both the
same letter, in which case lower-case always comes first. */
return lower_cmp ? lower_cmp : first2 - first1;
}
cmp = __strcasecmp (long1, long2);
if (cmp != 0)
return cmp;
}
}
else
/* Within the same cluster, but not the same group, so just compare
groups. */
return group_cmp (group1, group2, 0);
/* We're out of comparison criteria. At this point, if ENTRY1 != ENTRY2,
the order of these entries will be unpredictable. */
return 0;
}
/* Version of hol_entry_cmp with correct signature for qsort. */
/* Variant of hol_entry_cmp with correct signature for qsort. */
static int
hol_entry_qcmp (const void *entry1_v, const void *entry2_v)
{
@ -808,6 +913,9 @@ hol_sort (struct hol *hol)
hol_entry_qcmp);
}
/* -------------------------------------------------------------------------- */
/* Constructing the HOL. */
/* Append MORE to HOL, destroying MORE in the process. Options in HOL shadow
any in MORE with the same name. */
static void
@ -859,7 +967,8 @@ hol_append (struct hol *hol, struct hol *more)
/* Fix up the short options pointers from HOL. */
for (e = entries, left = hol->num_entries; left > 0; e++, left--)
e->short_options += (short_options - hol->short_options);
e->short_options
= short_options + (e->short_options - hol->short_options);
/* Now add the short options from MORE, fixing up its entries
too. */
@ -902,6 +1011,32 @@ hol_append (struct hol *hol, struct hol *more)
hol_free (more);
}
/* Make a HOL containing all levels of options in ARGP. CLUSTER is the
cluster in which ARGP's entries should be clustered, or 0. */
static struct hol *
argp_hol (const struct argp *argp, struct hol_cluster *cluster)
{
const struct argp_child *child = argp->children;
struct hol *hol = make_hol (argp, cluster);
if (child)
while (child->argp)
{
struct hol_cluster *child_cluster =
((child->group || child->header)
/* Put CHILD->argp within its own cluster. */
? hol_add_cluster (hol, child->group, child->header,
child - argp->children, cluster, argp)
/* Just merge it into the parent's cluster. */
: cluster);
hol_append (hol, argp_hol (child->argp, child_cluster)) ;
child++;
}
return hol;
}
/* -------------------------------------------------------------------------- */
/* Printing the HOL. */
/* Inserts enough spaces to make sure STREAM is at column COL. */
static void
indent_to (argp_fmtstream_t stream, unsigned col)
@ -946,7 +1081,7 @@ arg (const struct argp_option *real, const char *req_fmt, const char *opt_fmt,
/* State used during the execution of hol_help. */
struct hol_help_state
{
/* PREV_ENTRY should contain the previous entry printed, or 0. */
/* PREV_ENTRY should contain the previous entry printed, or NULL. */
struct hol_entry *prev_entry;
/* If an entry is in a different group from the previous one, and SEP_GROUPS
@ -999,7 +1134,7 @@ static void
print_header (const char *str, const struct argp *argp,
struct pentry_state *pest)
{
const char *tstr = dgettext_safe (argp->argp_domain, str);
const char *tstr = dgettext (argp->argp_domain, str);
const char *fstr = filter_doc (tstr, ARGP_KEY_HELP_HEADER, argp, pest->state);
if (fstr)
@ -1024,6 +1159,16 @@ print_header (const char *str, const struct argp *argp,
free ((char *) fstr);
}
/* Return true if CL1 is a child of CL2. */
static int
hol_cluster_is_child (const struct hol_cluster *cl1,
const struct hol_cluster *cl2)
{
while (cl1 && cl1 != cl2)
cl1 = cl1->parent;
return cl1 == cl2;
}
/* Inserts a comma if this isn't the first item on the line, and then makes
sure we're at least to column COL. If this *is* the first item on a line,
prints any pending whitespace/headers that should precede this line. Also
@ -1153,7 +1298,7 @@ hol_entry_help (struct hol_entry *entry, const struct argp_state *state,
}
else
{
const char *tstr = real->doc ? dgettext_safe (state == NULL ? NULL
const char *tstr = real->doc ? dgettext (state == NULL ? NULL
: state->root_argp->argp_domain,
real->doc) : 0;
const char *fstr = filter_doc (tstr, real->key, entry->argp, state);
@ -1337,29 +1482,6 @@ hol_usage (struct hol *hol, argp_fmtstream_t stream)
}
}
/* Make a HOL containing all levels of options in ARGP. CLUSTER is the
cluster in which ARGP's entries should be clustered, or 0. */
static struct hol *
argp_hol (const struct argp *argp, struct hol_cluster *cluster)
{
const struct argp_child *child = argp->children;
struct hol *hol = make_hol (argp, cluster);
if (child)
while (child->argp)
{
struct hol_cluster *child_cluster =
((child->group || child->header)
/* Put CHILD->argp within its own cluster. */
? hol_add_cluster (hol, child->group, child->header,
child - argp->children, cluster, argp)
/* Just merge it into the parent's cluster. */
: cluster);
hol_append (hol, argp_hol (child->argp, child_cluster)) ;
child++;
}
return hol;
}
/* Calculate how many different levels with alternative args strings exist in
ARGP. */
static size_t
@ -1390,7 +1512,7 @@ argp_args_usage (const struct argp *argp, const struct argp_state *state,
char *our_level = *levels;
int multiple = 0;
const struct argp_child *child = argp->children;
const char *tdoc = dgettext_safe (argp->argp_domain, argp->args_doc), *nl = 0;
const char *tdoc = dgettext (argp->argp_domain, argp->args_doc), *nl = 0;
const char *fdoc = filter_doc (tdoc, ARGP_KEY_HELP_ARGS_DOC, argp, state);
if (fdoc)
@ -1439,7 +1561,7 @@ argp_args_usage (const struct argp *argp, const struct argp_state *state,
}
/* Print the documentation for ARGP to STREAM; if POST is false, then
everything preceeding a `\v' character in the documentation strings (or
everything preceding a `\v' character in the documentation strings (or
the whole string, for those with none) is printed, otherwise, everything
following the `\v' character (nothing for strings without). Each separate
bit of documentation is separated a blank line, and if PRE_BLANK is true,
@ -1455,7 +1577,7 @@ argp_doc (const struct argp *argp, const struct argp_state *state,
void *input = 0;
int anything = 0;
size_t inp_text_limit = 0;
const char *doc = dgettext_safe (argp->argp_domain, argp->doc);
const char *doc = dgettext (argp->argp_domain, argp->doc);
const struct argp_child *child = argp->children;
if (doc)
@ -1472,7 +1594,7 @@ argp_doc (const struct argp *argp, const struct argp_state *state,
{
if (inp_text_limit)
/* Copy INP_TEXT so that it's nul-terminated. */
inp_text = strndup (inp_text, inp_text_limit);
inp_text = __strndup (inp_text, inp_text_limit);
input = __argp_input (argp, state);
text =
(*argp->help_filter) (post
@ -1856,7 +1978,11 @@ __argp_failure_internal (const struct argp_state *state, int status,
#else
putc_unlocked (':', stream);
putc_unlocked (' ', stream);
# ifdef HAVE_STRERROR_R
fputs (__strerror_r (errnum, buf, sizeof (buf)), stream);
# else
fputs (strerror (errnum), stream);
# endif
#endif
}

View file

@ -1,5 +1,5 @@
/* Name frobnication for compiling argp outside of glibc
Copyright (C) 1997-2021 Free Software Foundation, Inc.
Copyright (C) 1997-2023 Free Software Foundation, Inc.
This file is part of the GNU C Library.
Written by Miles Bader <miles@gnu.ai.mit.edu>.

View file

@ -1,5 +1,5 @@
/* Default definition for ARGP_PROGRAM_VERSION.
Copyright (C) 1996-2021 Free Software Foundation, Inc.
Copyright (C) 1996-2023 Free Software Foundation, Inc.
This file is part of the GNU C Library.
Written by Miles Bader <miles@gnu.ai.mit.edu>.

View file

@ -1,5 +1,5 @@
/* Default definition for ARGP_PROGRAM_VERSION_HOOK.
Copyright (C) 1996-2021 Free Software Foundation, Inc.
Copyright (C) 1996-2023 Free Software Foundation, Inc.
This file is part of the GNU C Library.
Written by Miles Bader <miles@gnu.ai.mit.edu>.

View file

@ -1,5 +1,5 @@
/* Test program for argp argument parser
Copyright (C) 1997-2021 Free Software Foundation, Inc.
Copyright (C) 1997-2023 Free Software Foundation, Inc.
This file is part of the GNU C Library.
Written by Miles Bader <miles@gnu.ai.mit.edu>.

View file

@ -1,16 +1,17 @@
dnl Process this file with autoconf to produce a configure script.
dnl This configure.ac is only for building a standalone argp library.
AC_PREREQ(2.54)
AC_INIT(argp-ba.c)
AM_INIT_AUTOMAKE(argp, standalone-1.4.0)
AC_PREREQ([2.71])
AC_INIT
AC_CONFIG_SRCDIR([argp-ba.c])
AM_INIT_AUTOMAKE(argp, standalone-1.6.0)
AM_CONFIG_HEADER(config.h)
# GNU libc defaults to supplying the ISO C library functions only. The
# _GNU_SOURCE define enables these extensions, in particular we want
# errno.h to declare program_invocation_name. Enable it on all
# systems; no problems have been reported with it so far.
AC_GNU_SOURCE
AC_USE_SYSTEM_EXTENSIONS
# Checks for programs.
AC_PROG_CC
@ -19,13 +20,21 @@ AC_PROG_RANLIB
AM_PROG_CC_STDC
if test "x$am_cv_prog_cc_stdc" = xno ; then
AC_ERROR([the C compiler doesn't handle ANSI-C])
AC_MSG_ERROR(the C compiler doesn't handle ANSI-C)
fi
# Checks for libraries.
# Checks for header files.
AC_HEADER_STDC
m4_warn([obsolete],
[The preprocessor macro `STDC_HEADERS' is obsolete.
Except in unusual embedded environments, you can safely include all
ISO C90 headers unconditionally.])dnl
# Autoupdate added the next two lines to ensure that your configure
# script's behavior did not change. They are probably safe to remove.
AC_CHECK_INCLUDES_DEFAULT
AC_PROG_EGREP
AC_CHECK_HEADERS(limits.h malloc.h unistd.h libintl.h)
# Checks for typedefs, structures, and compiler characteristics.
@ -49,9 +58,7 @@ AC_DEFUN([ARGP_CHECK_FUNC],
AH_TEMPLATE(AS_TR_CPP(HAVE_[]ac_func),
[Define to 1 if you have the `]ac_func[' function.])
AC_CACHE_CHECK([for $2], ac_var,
[AC_TRY_LINK([$1], [$2],
[AS_VAR_SET(ac_var, yes)],
[AS_VAR_SET(ac_var, no)])])
[AC_LINK_IFELSE([AC_LANG_PROGRAM([[$1]], [[$2]])],[AS_VAR_SET(ac_var, yes)],[AS_VAR_SET(ac_var, no)])])
if test AS_VAR_GET(ac_var) = yes ; then
ifelse([$3],,
[AC_DEFINE_UNQUOTED(AS_TR_CPP(HAVE_[]ac_func))],
@ -93,4 +100,5 @@ fi
CPPFLAGS="$CPPFLAGS -I$srcdir"
AC_OUTPUT(Makefile testsuite/Makefile)
AC_CONFIG_FILES([Makefile testsuite/Makefile])
AC_OUTPUT

View file

@ -1,18 +1,39 @@
/* strndup.c
*
*/
/* Copy memory to memory until the specified number of bytes
has been copied, return pointer to following byte.
Overlap is NOT handled correctly.
Copyright (C) 1991-2023 Free Software Foundation, Inc.
This file is part of the GNU C Library.
Contributed by Torbjorn Granlund (tege@sics.se).
/* Written by Niels Möller <nisse@lysator.liu.se>
*
* This file is hereby placed in the public domain.
*/
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 NO_MEMPCPY_STPCPY_REDIRECT
#include <string.h>
void *
mempcpy (void *to, const void *from, size_t size)
{
memcpy(to, from, size);
return (char *) to + size;
}
#undef mempcpy
#undef __mempcpy
#ifndef MEMPCPY
# define MEMPCPY __mempcpy
#endif
void *
MEMPCPY (void *dest, const void *src, size_t len)
{
return memcpy (dest, src, len) + len;
}
libc_hidden_def (__mempcpy)
weak_alias (__mempcpy, mempcpy)
libc_hidden_builtin_def (mempcpy)

View file

@ -1,21 +1,56 @@
/* strchrnul.c
*
*/
/* Copyright (C) 1991-2023 Free Software Foundation, Inc.
This file is part of the GNU C Library.
/* Written by Niels Möller <nisse@lysator.liu.se>
*
* This file is hereby placed in the public domain.
*/
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.
/* FIXME: What is this function supposed to do? My guess is that it is
* like strchr, but returns a pointer to the NUL character, not a NULL
* pointer, if the character isn't found. */
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.
char *strchrnul(const char *s, int c)
You should have received a copy of the GNU Lesser General Public
License along with the GNU C Library; if not, see
<https://www.gnu.org/licenses/>. */
#include <libc-pointer-arith.h>
#include <string-fzb.h>
#include <string-fzc.h>
#include <string-fzi.h>
#include <string-shift.h>
#include <string.h>
#undef __strchrnul
#undef strchrnul
#ifdef STRCHRNUL
# define __strchrnul STRCHRNUL
#endif
/* Find the first occurrence of C in S or the final NUL byte. */
char *
__strchrnul (const char *str, int c_in)
{
const char *p = s;
while (*p && (*p != c))
p++;
/* Align pointer to sizeof op_t. */
uintptr_t s_int = (uintptr_t) str;
const op_t *word_ptr = (const op_t *) PTR_ALIGN_DOWN (str, sizeof (op_t));
return (char *) p;
op_t repeated_c = repeat_bytes (c_in);
op_t word = *word_ptr;
find_t mask = shift_find (find_zero_eq_all (word, repeated_c), s_int);
if (mask != 0)
return (char *) str + index_first (mask);
do
word = *++word_ptr;
while (! has_zero_eq (word, repeated_c));
return (char *) word_ptr + index_first_zero_eq (word, repeated_c);
}
#ifndef STRCHRNUL
libc_hidden_def (__strchrnul)
weak_alias (__strchrnul, strchrnul)
#endif

View file

@ -1,31 +1,56 @@
/* strndup.c
*
*/
/* Copyright (C) 1996-2023 Free Software Foundation, Inc.
This file is part of the GNU C Library.
/* Written by Niels Möller <nisse@lysator.liu.se>
*
* This file is hereby placed in the public domain.
*/
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.
#include <stdlib.h>
#include <string.h>
The GNU C Library is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
Lesser General Public License for more details.
You should have received a copy of the GNU Lesser General Public
License along with the GNU C Library; if not, see
<https://www.gnu.org/licenses/>. */
#ifdef HAVE_CONFIG_H
# include "config.h"
#endif
#include <stdio.h>
#include <sys/types.h>
#if 1 || defined STDC_HEADERS
# include <stdlib.h>
# include <string.h>
#else
char *malloc ();
#endif
#undef __strndup
#undef strndup
#ifndef weak_alias
# define __strndup strndup
#endif
char *
strndup (const char *s, size_t size)
__strndup (const char *s, size_t n)
{
char *r;
char *end = memchr(s, 0, size);
if (end)
/* Length + 1 */
size = end - s + 1;
r = malloc(size);
size_t len = __strnlen (s, n);
char *new = (char *) malloc (len + 1);
if (size)
{
memcpy(r, s, size-1);
r[size-1] = '\0';
}
return r;
if (new == NULL)
return NULL;
new[len] = '\0';
return (char *) memcpy (new, s, len);
}
#ifdef libc_hidden_def
libc_hidden_def (__strndup)
#endif
#ifdef weak_alias
weak_alias (__strndup, strndup)
#endif