From d00c5ab37f7e1db3ed8626c8066258cbdeee6119 Mon Sep 17 00:00:00 2001 From: Daryl Ronningen Date: Fri, 8 Dec 2023 00:32:25 -0800 Subject: [PATCH] Update to glibc 2.38 --- ChangeLog | 5 + Versions | 3 - argp-ba.c | 2 +- argp-eexst.c | 2 +- argp-fmtstream.c | 2 +- argp-fmtstream.h | 2 +- argp-help.c | 410 +++++++++++++++++++++++++++++++---------------- argp-namefrob.h | 2 +- argp-pv.c | 2 +- argp-pvh.c | 2 +- argp-test.c | 2 +- configure.ac | 28 ++-- mempcpy.c | 47 ++++-- strchrnul.c | 65 ++++++-- strndup.c | 73 ++++++--- 15 files changed, 432 insertions(+), 215 deletions(-) diff --git a/ChangeLog b/ChangeLog index 710e3d1..cd821f8 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,8 @@ +2023-12-08 Daryl Ronningen + + * Updated argp to glibc 2.38 + * configure.ac: Bumped version to 1.6.0. + 2021-02-10 Érico Nogueira * configure.ac: Bumped version to 1.4.0. diff --git a/Versions b/Versions index 378320c..bf13642 100644 --- a/Versions +++ b/Versions @@ -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; } } diff --git a/argp-ba.c b/argp-ba.c index c13372d..03e4cdd 100644 --- a/argp-ba.c +++ b/argp-ba.c @@ -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 . diff --git a/argp-eexst.c b/argp-eexst.c index 795e312..d7d4e6e 100644 --- a/argp-eexst.c +++ b/argp-eexst.c @@ -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 . diff --git a/argp-fmtstream.c b/argp-fmtstream.c index 721a253..98edcfc 100644 --- a/argp-fmtstream.c +++ b/argp-fmtstream.c @@ -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 . diff --git a/argp-fmtstream.h b/argp-fmtstream.h index fbd2bf9..5d4bd62 100644 --- a/argp-fmtstream.h +++ b/argp-fmtstream.h @@ -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 . diff --git a/argp-help.c b/argp-help.c index 6f64056..ed74a13 100644 --- a/argp-help.c +++ b/argp-help.c @@ -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 . @@ -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 #include @@ -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 } diff --git a/argp-namefrob.h b/argp-namefrob.h index 4c289b8..dfb6c48 100644 --- a/argp-namefrob.h +++ b/argp-namefrob.h @@ -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 . diff --git a/argp-pv.c b/argp-pv.c index 6ea8ce5..60a49ba 100644 --- a/argp-pv.c +++ b/argp-pv.c @@ -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 . diff --git a/argp-pvh.c b/argp-pvh.c index ac8cf6a..b400220 100644 --- a/argp-pvh.c +++ b/argp-pvh.c @@ -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 . diff --git a/argp-test.c b/argp-test.c index d9c108d..f931475 100644 --- a/argp-test.c +++ b/argp-test.c @@ -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 . diff --git a/configure.ac b/configure.ac index 386215d..09c8d51 100644 --- a/configure.ac +++ b/configure.ac @@ -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 diff --git a/mempcpy.c b/mempcpy.c index 6fa228b..1417d82 100644 --- a/mempcpy.c +++ b/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 - * - * 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 + . */ + +#define NO_MEMPCPY_STPCPY_REDIRECT #include -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) diff --git a/strchrnul.c b/strchrnul.c index af1b4bb..01fa25b 100644 --- a/strchrnul.c +++ b/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 - * - * 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 + . */ + +#include +#include +#include +#include +#include +#include + +#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 diff --git a/strndup.c b/strndup.c index f01065a..c02503d 100644 --- a/strndup.c +++ b/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 - * - * 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 -#include + 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 + . */ + +#ifdef HAVE_CONFIG_H +# include "config.h" +#endif + +#include +#include + +#if 1 || defined STDC_HEADERS +# include +# include +#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