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> 2021-02-10 Érico Nogueira <ericonr@disroot.org>
* configure.ac: Bumped version to 1.4.0. * configure.ac: Bumped version to 1.4.0.

View file

@ -7,8 +7,5 @@ libc {
# a* # a*
argp_error; argp_failure; argp_help; argp_parse; argp_state_help; argp_error; argp_failure; argp_help; argp_parse; argp_state_help;
argp_usage; 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. /* 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. This file is part of the GNU C Library.
Written by Miles Bader <miles@gnu.ai.mit.edu>. Written by Miles Bader <miles@gnu.ai.mit.edu>.

View file

@ -1,5 +1,5 @@
/* Default definition for ARGP_ERR_EXIT_STATUS /* 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. This file is part of the GNU C Library.
Written by Miles Bader <miles@gnu.ai.mit.edu>. Written by Miles Bader <miles@gnu.ai.mit.edu>.

View file

@ -1,5 +1,5 @@
/* Word-wrapping and line-truncating streams /* 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. This file is part of the GNU C Library.
Written by Miles Bader <miles@gnu.ai.mit.edu>. Written by Miles Bader <miles@gnu.ai.mit.edu>.

View file

@ -1,5 +1,5 @@
/* Word-wrapping and line-truncating streams. /* 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. This file is part of the GNU C Library.
Written by Miles Bader <miles@gnu.ai.mit.edu>. Written by Miles Bader <miles@gnu.ai.mit.edu>.

View file

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

View file

@ -1,5 +1,5 @@
/* Name frobnication for compiling argp outside of glibc /* 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. This file is part of the GNU C Library.
Written by Miles Bader <miles@gnu.ai.mit.edu>. Written by Miles Bader <miles@gnu.ai.mit.edu>.

View file

@ -1,5 +1,5 @@
/* Default definition for ARGP_PROGRAM_VERSION. /* 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. This file is part of the GNU C Library.
Written by Miles Bader <miles@gnu.ai.mit.edu>. Written by Miles Bader <miles@gnu.ai.mit.edu>.

View file

@ -1,5 +1,5 @@
/* Default definition for ARGP_PROGRAM_VERSION_HOOK. /* 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. This file is part of the GNU C Library.
Written by Miles Bader <miles@gnu.ai.mit.edu>. Written by Miles Bader <miles@gnu.ai.mit.edu>.

View file

@ -1,5 +1,5 @@
/* Test program for argp argument parser /* 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. This file is part of the GNU C Library.
Written by Miles Bader <miles@gnu.ai.mit.edu>. 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 Process this file with autoconf to produce a configure script.
dnl This configure.ac is only for building a standalone argp library. dnl This configure.ac is only for building a standalone argp library.
AC_PREREQ(2.54) AC_PREREQ([2.71])
AC_INIT(argp-ba.c) AC_INIT
AM_INIT_AUTOMAKE(argp, standalone-1.4.0) AC_CONFIG_SRCDIR([argp-ba.c])
AM_INIT_AUTOMAKE(argp, standalone-1.6.0)
AM_CONFIG_HEADER(config.h) AM_CONFIG_HEADER(config.h)
# GNU libc defaults to supplying the ISO C library functions only. The # GNU libc defaults to supplying the ISO C library functions only. The
# _GNU_SOURCE define enables these extensions, in particular we want # _GNU_SOURCE define enables these extensions, in particular we want
# errno.h to declare program_invocation_name. Enable it on all # errno.h to declare program_invocation_name. Enable it on all
# systems; no problems have been reported with it so far. # systems; no problems have been reported with it so far.
AC_GNU_SOURCE AC_USE_SYSTEM_EXTENSIONS
# Checks for programs. # Checks for programs.
AC_PROG_CC AC_PROG_CC
@ -19,13 +20,21 @@ AC_PROG_RANLIB
AM_PROG_CC_STDC AM_PROG_CC_STDC
if test "x$am_cv_prog_cc_stdc" = xno ; then 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 fi
# Checks for libraries. # Checks for libraries.
# Checks for header files. # 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) AC_CHECK_HEADERS(limits.h malloc.h unistd.h libintl.h)
# Checks for typedefs, structures, and compiler characteristics. # Checks for typedefs, structures, and compiler characteristics.
@ -49,9 +58,7 @@ AC_DEFUN([ARGP_CHECK_FUNC],
AH_TEMPLATE(AS_TR_CPP(HAVE_[]ac_func), AH_TEMPLATE(AS_TR_CPP(HAVE_[]ac_func),
[Define to 1 if you have the `]ac_func[' function.]) [Define to 1 if you have the `]ac_func[' function.])
AC_CACHE_CHECK([for $2], ac_var, AC_CACHE_CHECK([for $2], ac_var,
[AC_TRY_LINK([$1], [$2], [AC_LINK_IFELSE([AC_LANG_PROGRAM([[$1]], [[$2]])],[AS_VAR_SET(ac_var, yes)],[AS_VAR_SET(ac_var, no)])])
[AS_VAR_SET(ac_var, yes)],
[AS_VAR_SET(ac_var, no)])])
if test AS_VAR_GET(ac_var) = yes ; then if test AS_VAR_GET(ac_var) = yes ; then
ifelse([$3],, ifelse([$3],,
[AC_DEFINE_UNQUOTED(AS_TR_CPP(HAVE_[]ac_func))], [AC_DEFINE_UNQUOTED(AS_TR_CPP(HAVE_[]ac_func))],
@ -93,4 +100,5 @@ fi
CPPFLAGS="$CPPFLAGS -I$srcdir" 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> The GNU C Library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* This file is hereby placed in the public domain. 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> #include <string.h>
void * #undef mempcpy
mempcpy (void *to, const void *from, size_t size) #undef __mempcpy
{
memcpy(to, from, size);
return (char *) to + size;
}
#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> The GNU C Library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* This file is hereby placed in the public domain. 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 The GNU C Library is distributed in the hope that it will be useful,
* like strchr, but returns a pointer to the NUL character, not a NULL but WITHOUT ANY WARRANTY; without even the implied warranty of
* pointer, if the character isn't found. */ 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; /* Align pointer to sizeof op_t. */
while (*p && (*p != c)) uintptr_t s_int = (uintptr_t) str;
p++; 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> The GNU C Library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* This file is hereby placed in the public domain. License as published by the Free Software Foundation; either
*/ version 2.1 of the License, or (at your option) any later version.
The GNU C Library is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
Lesser General Public License for more details.
You should have received a copy of the GNU Lesser General Public
License along with the GNU C Library; if not, see
<https://www.gnu.org/licenses/>. */
#ifdef HAVE_CONFIG_H
# include "config.h"
#endif
#include <stdio.h>
#include <sys/types.h>
#if 1 || defined STDC_HEADERS
# include <stdlib.h> # include <stdlib.h>
# include <string.h> # include <string.h>
#else
char *malloc ();
#endif
#undef __strndup
#undef strndup
#ifndef weak_alias
# define __strndup strndup
#endif
char * char *
strndup (const char *s, size_t size) __strndup (const char *s, size_t n)
{ {
char *r; size_t len = __strnlen (s, n);
char *end = memchr(s, 0, size); char *new = (char *) malloc (len + 1);
if (end) if (new == NULL)
/* Length + 1 */ return NULL;
size = end - s + 1;
r = malloc(size); new[len] = '\0';
return (char *) memcpy (new, s, len);
if (size)
{
memcpy(r, s, size-1);
r[size-1] = '\0';
}
return r;
} }
#ifdef libc_hidden_def
libc_hidden_def (__strndup)
#endif
#ifdef weak_alias
weak_alias (__strndup, strndup)
#endif