Update to glibc 2.38
This commit is contained in:
parent
e5fe9ad9e8
commit
d00c5ab37f
15 changed files with 432 additions and 215 deletions
|
@ -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.
|
||||||
|
|
3
Versions
3
Versions
|
@ -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;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -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>.
|
||||||
|
|
||||||
|
|
|
@ -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>.
|
||||||
|
|
||||||
|
|
|
@ -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>.
|
||||||
|
|
||||||
|
|
|
@ -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>.
|
||||||
|
|
||||||
|
|
410
argp-help.c
410
argp-help.c
|
@ -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. */
|
||||||
cl1 = cl1->parent;
|
if (cl1->depth > cl2->depth)
|
||||||
while (cl2->depth > cl1->depth)
|
{
|
||||||
cl2 = cl2->parent;
|
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
|
return 1;
|
||||||
a common parent; these can be directly compared. */
|
}
|
||||||
while (cl1->parent != cl2->parent)
|
else if (cl1->depth < cl2->depth)
|
||||||
cl1 = cl1->parent, cl2 = cl2->parent;
|
{
|
||||||
|
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
|
/* 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);
|
||||||
|
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);
|
cmp = (long1 != NULL) - (long2 != NULL);
|
||||||
int short2 = hol_entry_first_short (entry2);
|
if (cmp != 0)
|
||||||
int doc1 = odoc (entry1->opt);
|
return cmp;
|
||||||
int doc2 = odoc (entry2->opt);
|
|
||||||
const char *long1 = hol_entry_first_long (entry1);
|
|
||||||
const char *long2 = hol_entry_first_long (entry2);
|
|
||||||
|
|
||||||
if (doc1)
|
if (long1 != NULL)
|
||||||
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. */
|
|
||||||
{
|
{
|
||||||
char first1 = short1 ? short1 : long1 ? *long1 : 0;
|
cmp = __strcasecmp (long1, long2);
|
||||||
char first2 = short2 ? short2 : long2 ? *long2 : 0;
|
if (cmp != 0)
|
||||||
#ifdef _tolower
|
return cmp;
|
||||||
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;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
else
|
|
||||||
/* Within the same cluster, but not the same group, so just compare
|
/* We're out of comparison criteria. At this point, if ENTRY1 != ENTRY2,
|
||||||
groups. */
|
the order of these entries will be unpredictable. */
|
||||||
return group_cmp (group1, group2, 0);
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Version of hol_entry_cmp with correct signature for qsort. */
|
/* 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
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -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>.
|
||||||
|
|
||||||
|
|
|
@ -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>.
|
||||||
|
|
||||||
|
|
|
@ -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>.
|
||||||
|
|
||||||
|
|
|
@ -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>.
|
||||||
|
|
||||||
|
|
28
configure.ac
28
configure.ac
|
@ -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
|
||||||
|
|
47
mempcpy.c
47
mempcpy.c
|
@ -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)
|
||||||
|
|
65
strchrnul.c
65
strchrnul.c
|
@ -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
|
||||||
|
|
71
strndup.c
71
strndup.c
|
@ -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.
|
||||||
|
|
||||||
#include <stdlib.h>
|
The GNU C Library is distributed in the hope that it will be useful,
|
||||||
#include <string.h>
|
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 *
|
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
|
||||||
|
|
Loading…
Reference in a new issue