diff options
Diffstat (limited to 'lib/libc/stdlib')
| -rw-r--r-- | lib/libc/stdlib/Makefile.inc | 87 | ||||
| -rw-r--r-- | lib/libc/stdlib/Symbol.map | 2 | ||||
| -rw-r--r-- | lib/libc/stdlib/getopt.3 | 49 | ||||
| -rw-r--r-- | lib/libc/stdlib/strtonum.3 | 74 | ||||
| -rw-r--r-- | lib/libc/stdlib/strtonum.c | 27 | ||||
| -rw-r--r-- | lib/libc/stdlib/tdestroy.c | 66 | ||||
| -rw-r--r-- | lib/libc/stdlib/tsearch.3 | 25 |
7 files changed, 276 insertions, 54 deletions
diff --git a/lib/libc/stdlib/Makefile.inc b/lib/libc/stdlib/Makefile.inc index b878a7625e9f..c2107fdaeaae 100644 --- a/lib/libc/stdlib/Makefile.inc +++ b/lib/libc/stdlib/Makefile.inc @@ -1,19 +1,76 @@ # machine-independent stdlib sources .PATH: ${LIBC_SRCTOP}/${LIBC_ARCH}/stdlib ${LIBC_SRCTOP}/stdlib -MISRCS+=C99_Exit.c a64l.c abort.c abs.c atexit.c atof.c atoi.c atol.c atoll.c \ - bsearch.c bsearch_b.c \ - cxa_thread_atexit.c cxa_thread_atexit_impl.c \ - div.c exit.c getenv.c getopt.c getopt_long.c \ - getsubopt.c hcreate.c hcreate_r.c hdestroy_r.c heapsort.c heapsort_b.c \ - hsearch_r.c imaxabs.c imaxdiv.c \ - insque.c l64a.c labs.c ldiv.c llabs.c lldiv.c lsearch.c memalignment.c \ - merge.c mergesort_b.c ptsname.c qsort.c qsort_r.c qsort_r_compat.c \ - qsort_s.c quick_exit.c radixsort.c rand.c \ - random.c reallocarray.c reallocf.c realpath.c recallocarray.c remque.c \ - set_constraint_handler_s.c strfmon.c strtoimax.c \ - strtol.c strtold.c strtoll.c strtoq.c strtoul.c strtonum.c strtoull.c \ - strtoumax.c strtouq.c system.c tdelete.c tfind.c tsearch.c twalk.c +MISRCS+= \ + C99_Exit.c \ + a64l.c \ + abort.c \ + abs.c \ + atexit.c \ + atof.c \ + atoi.c \ + atol.c \ + atoll.c \ + bsearch.c \ + bsearch_b.c \ + cxa_thread_atexit.c \ + cxa_thread_atexit_impl.c \ + div.c \ + exit.c \ + getenv.c \ + getopt.c \ + getopt_long.c \ + getsubopt.c \ + hcreate.c \ + hcreate_r.c \ + hdestroy_r.c \ + heapsort.c \ + heapsort_b.c \ + hsearch_r.c \ + imaxabs.c \ + imaxdiv.c \ + insque.c \ + l64a.c \ + labs.c \ + ldiv.c \ + llabs.c \ + lldiv.c \ + lsearch.c \ + memalignment.c \ + merge.c \ + mergesort_b.c \ + ptsname.c \ + qsort.c \ + qsort_r.c \ + qsort_r_compat.c \ + qsort_s.c \ + quick_exit.c \ + radixsort.c \ + rand.c \ + random.c \ + reallocarray.c \ + reallocf.c \ + realpath.c \ + recallocarray.c \ + remque.c \ + set_constraint_handler_s.c \ + strfmon.c \ + strtoimax.c \ + strtol.c \ + strtold.c \ + strtoll.c \ + strtoq.c \ + strtoul.c \ + strtonum.c \ + strtoull.c \ + strtoumax.c \ + strtouq.c \ + system.c \ + tdelete.c \ + tdestroy.c \ + tfind.c \ + tsearch.c \ + twalk.c CFLAGS.qsort.c+= -Wsign-compare @@ -85,9 +142,11 @@ MLINKS+=strtod.3 strtof.3 \ MLINKS+=strtol.3 strtoll.3 \ strtol.3 strtoq.3 \ strtol.3 strtoimax.3 +MLINKS+=strtonum.3 strtonumx.3 MLINKS+=strtoul.3 strtoull.3 \ strtoul.3 strtouq.3 \ strtoul.3 strtoumax.3 MLINKS+=tsearch.3 tdelete.3 \ tsearch.3 tfind.3 \ - tsearch.3 twalk.3 + tsearch.3 twalk.3 \ + tsearch.3 tdestroy.3 diff --git a/lib/libc/stdlib/Symbol.map b/lib/libc/stdlib/Symbol.map index 8b7e97c3cbdc..373006b4a388 100644 --- a/lib/libc/stdlib/Symbol.map +++ b/lib/libc/stdlib/Symbol.map @@ -134,6 +134,8 @@ FBSD_1.8 { FBSD_1.9 { memalignment; recallocarray; + strtonumx; + tdestroy; }; FBSDprivate_1.0 { diff --git a/lib/libc/stdlib/getopt.3 b/lib/libc/stdlib/getopt.3 index a5b5bff9d1a7..1b40f6dfea7e 100644 --- a/lib/libc/stdlib/getopt.3 +++ b/lib/libc/stdlib/getopt.3 @@ -27,7 +27,7 @@ .\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF .\" SUCH DAMAGE. .\" -.Dd June 5, 2014 +.Dd December 14, 2025 .Dt GETOPT 3 .Os .Sh NAME @@ -60,30 +60,49 @@ if it has been specified in the string of accepted option characters, The option string .Fa optstring may contain the following elements: individual characters, and -characters followed by a colon to indicate an option argument -is to follow. -If an individual character is followed by two colons, then the -option argument is optional; +characters followed by a colon +.Pq Ql \&: +to indicate an option argument is to follow. +If an individual character is followed by two colons +.Pq Ql \&:\&: , +then the option argument is optional; .Va optarg is set to the rest of the current -.Va argv +.Fa argv word, or .Dv NULL if there were no more characters in the current word. -This is a -.Tn GNU -extension. +This is an extension not covered by POSIX. +.Pp For example, an option string .Li \&"x" recognizes an option -.Dq Fl x , -and an option string +.Dq Fl x . +.Pp +An option string .Li \&"x:" -recognizes an option and argument -.Dq Fl x Ar argument . +recognizes an option with an argument, both +.Dq Fl x Ns Ar arg\^ , +and +.Dq Fl x Ar arg\^ . It does not matter to .Fn getopt -if a following argument has leading white space. +if the option's argument is a separate word or not. +.Pp +An option string +.Li \&"x::" +recognizes the option both without an argument +.Dq Fl x , +and with an argument +.Dq Fl x Ns Ar arg\^ . +In the latter case the argument must be part of the same +.Fa argv +word. +The +.Dq Fl x +and +.Dq Ar arg\^ +must not be separated by a whitespace on the command line. .Pp On return from .Fn getopt , @@ -267,7 +286,7 @@ Care should be taken not to use as the first character in .Fa optstring to avoid a semantic conflict with -.Tn GNU +GNU .Fn getopt , which assigns different meaning to an .Fa optstring diff --git a/lib/libc/stdlib/strtonum.3 b/lib/libc/stdlib/strtonum.3 index 2650d147e7cc..7e6111a6ff71 100644 --- a/lib/libc/stdlib/strtonum.3 +++ b/lib/libc/stdlib/strtonum.3 @@ -1,4 +1,5 @@ .\" Copyright (c) 2004 Ted Unangst +.\" Copyright 2023 Oxide Computer Company .\" .\" Permission to use, copy, modify, and distribute this software for any .\" purpose with or without fee is hereby granted, provided that the above @@ -14,11 +15,12 @@ .\" .\" $OpenBSD: strtonum.3,v 1.13 2006/04/25 05:15:42 tedu Exp $ .\" -.Dd April 29, 2004 +.Dd January 15, 2026 .Dt STRTONUM 3 .Os .Sh NAME -.Nm strtonum +.Nm strtonum , +.Nm strtonumx .Nd "reliably convert string value to an integer" .Sh SYNOPSIS .In stdlib.h @@ -29,26 +31,33 @@ .Fa "long long maxval" .Fa "const char **errstr" .Fc +.Ft long long +.Fo strtonumx +.Fa "const char *nptr" +.Fa "long long minval" +.Fa "long long maxval" +.Fa "const char **errstr" +.Fa "int base" +.Fc .Sh DESCRIPTION The .Fn strtonum -function converts the string in +and +.Fn strtonumx +functions convert the string in .Fa nptr to a .Vt "long long" value. -The -.Fn strtonum -function was designed to facilitate safe, robust programming -and overcome the shortcomings of the +These functions were designed to facilitate safe, robust programming and +overcome the shortcomings of the .Xr atoi 3 and .Xr strtol 3 family of interfaces. .Pp The string may begin with an arbitrary amount of whitespace -(as determined by -.Xr isspace 3 ) +.Pq as determined by Xr isspace 3 followed by a single optional .Ql + or @@ -57,7 +66,10 @@ sign. .Pp The remainder of the string is converted to a .Vt "long long" -value according to base 10. +value according to base 10 +.Pq for Fn strtonum +or the provided base +.Pq for Fn strtonumx . .Pp The value obtained is then checked against the provided .Fa minval @@ -68,13 +80,30 @@ If .Fa errstr is non-null, .Fn strtonum -stores an error string in +and +.Fn strtonumx +store an error string in .Fa *errstr indicating the failure. +.Pp +For +.Fn strtonumx +the value of +.Ar base +is interpreted in the same way as described in +.Xr strtoll 3 . +In particular, if the value of +.Ar base +is 0, then the expected form of +.Ar nptr +is that of a decimal constant, octal constant or hexadecimal constant, any of +which may be preceded by a + or - sign. .Sh RETURN VALUES The .Fn strtonum -function returns the result of the conversion, +and +.Fn strtonumx +functions return the result of the conversion, unless the value would exceed the provided bounds or is invalid. On error, 0 is returned, .Va errno @@ -90,6 +119,8 @@ a successful return of 0 from an error. .Sh EXAMPLES Using .Fn strtonum +and +.Fn strtonumx correctly is meant to be simpler than the alternative functions. .Bd -literal -offset indent int iterations; @@ -107,7 +138,10 @@ The above example will guarantee that the value of iterations is between .It Bq Er ERANGE The given string was out of range. .It Bq Er EINVAL -The given string did not consist solely of digit characters. +The given string did not consist solely of digit characters +.Pq for Fn strtonum , +or characters which are valid in the given base +.Pq for Fn strtonumx . .It Bq Er EINVAL The supplied .Fa minval @@ -120,12 +154,15 @@ If an error occurs, will be set to one of the following strings: .Pp .Bl -tag -width ".Li too large" -compact -.It Li "too large" +.It Qq too large The result was larger than the provided maximum value. -.It Li "too small" +.It Qq too small The result was smaller than the provided minimum value. -.It Li invalid -The string did not consist solely of digit characters. +.It Qq invalid +The string did not consist solely of characters valid in the specified base +.Pq or base 10 for Fn strtonum . +.It Qq unparsable; invalid base specified +The specified base was outside the permitted range. .El .Sh SEE ALSO .Xr atof 3 , @@ -152,3 +189,6 @@ The .Fn strtonum function first appeared in .Ox 3.6 . +The +.Fn strtonumx +function first appeared in illumos in 2023. diff --git a/lib/libc/stdlib/strtonum.c b/lib/libc/stdlib/strtonum.c index 0d0715bf39c1..44c27d6af3ad 100644 --- a/lib/libc/stdlib/strtonum.c +++ b/lib/libc/stdlib/strtonum.c @@ -2,6 +2,8 @@ * Copyright (c) 2004 Ted Unangst and Todd Miller * All rights reserved. * + * Copyright 2023 Oxide Computer Company + * * Permission to use, copy, modify, and distribute this software for any * purpose with or without fee is hereby granted, provided that the above * copyright notice and this permission notice appear in all copies. @@ -24,10 +26,13 @@ #define INVALID 1 #define TOOSMALL 2 #define TOOLARGE 3 +#define BADBASE 4 + +#define MBASE ('z' - 'a' + 1 + 10) long long -strtonum(const char *numstr, long long minval, long long maxval, - const char **errstrp) +strtonumx(const char *numstr, long long minval, long long maxval, + const char **errstrp, int base) { long long ll = 0; int error = 0; @@ -35,20 +40,23 @@ strtonum(const char *numstr, long long minval, long long maxval, struct errval { const char *errstr; int err; - } ev[4] = { + } ev[5] = { { NULL, 0 }, { "invalid", EINVAL }, { "too small", ERANGE }, { "too large", ERANGE }, + { "unparsable; invalid base specified", EINVAL }, }; ev[0].err = errno; errno = 0; if (minval > maxval) { error = INVALID; + } else if (base < 0 || base > MBASE || base == 1) { + error = BADBASE; } else { - ll = strtoll(numstr, &ep, 10); - if (errno == EINVAL || numstr == ep || *ep != '\0') + ll = strtoll(numstr, &ep, base); + if (numstr == ep || *ep != '\0') error = INVALID; else if ((ll == LLONG_MIN && errno == ERANGE) || ll < minval) error = TOOSMALL; @@ -58,8 +66,15 @@ strtonum(const char *numstr, long long minval, long long maxval, if (errstrp != NULL) *errstrp = ev[error].errstr; errno = ev[error].err; - if (error) + if (error != 0) ll = 0; return (ll); } + +long long +strtonum(const char *numstr, long long minval, long long maxval, + const char **errstrp) +{ + return (strtonumx(numstr, minval, maxval, errstrp, 10)); +} diff --git a/lib/libc/stdlib/tdestroy.c b/lib/libc/stdlib/tdestroy.c new file mode 100644 index 000000000000..2aeb02228e46 --- /dev/null +++ b/lib/libc/stdlib/tdestroy.c @@ -0,0 +1,66 @@ +/* + * Copyright 2025 The FreeBSD Foundation + * + * SPDX-License-Identifier: BSD-2-Clause + * + * This software was developed by Konstantin Belousov <kib@FreeBSD.org> + * under sponsorship from the FreeBSD Foundation. + */ + +#define _SEARCH_PRIVATE +#include <search.h> +#include <stdlib.h> + +static void +nul_node_free(void *node __unused) +{ +} + +void +tdestroy(void *rootp, void (*node_free)(void *)) +{ + posix_tnode *back, *curr, **front; + + if (rootp == NULL) + return; + if (node_free == NULL) + node_free = nul_node_free; + + back = rootp; + front = &back; + + for (;;) { + /* + * The sequence of nodes from back to just before *front linked + * by llink have been found to have non-NULL rlink. + * + * Extend *front to (*front)->llink, deleting *front from the + * sequence if it has a NULL rlink. + */ + curr = *front; + if (curr->rlink != NULL) + front = &curr->llink; + else { + *front = curr->llink; + node_free(curr->key); + free(curr); + } + if (*front != NULL) + continue; + if (back == NULL) + break; + + /* + * The sequence cannot be extended because *front is NULL. Make + * the rlink of the back node the new *front, the llink of the + * back node the new back, and free the old back node. + */ + curr = back; + back = curr->llink; + if (back == NULL) + front = &back; + *front = curr->rlink; + node_free(curr->key); + free(curr); + } +} diff --git a/lib/libc/stdlib/tsearch.3 b/lib/libc/stdlib/tsearch.3 index edee01cafc52..f412c37a4ef0 100644 --- a/lib/libc/stdlib/tsearch.3 +++ b/lib/libc/stdlib/tsearch.3 @@ -36,6 +36,7 @@ .In search.h .Ft void * .Fn tdelete "const void * restrict key" "posix_tnode ** restrict rootp" "int (*compar) (const void *, const void *)" +.Fn tdestroy "posix_tnode *root" "(void (*node_free)(void *)" .Ft posix_tnode * .Fn tfind "const void *key" "posix_tnode * const *rootp" "int (*compar) (const void *, const void *)" .Ft posix_tnode * @@ -45,6 +46,7 @@ .Sh DESCRIPTION The .Fn tdelete , +.Fn tdestroy , .Fn tfind , .Fn tsearch , and @@ -95,6 +97,13 @@ If the node to be deleted is the root of the binary search tree, will be adjusted. .Pp The +.Fn tdestroy +function destroys the whole search tree, freeing all allocated nodes. +If tree keys need special handling on free, the +.Fa node_free +function can be provided, which is called on each key. +.Pp +The .Fn twalk function walks the binary search tree rooted in @@ -128,7 +137,9 @@ is NULL or the datum cannot be found. .Pp The .Fn twalk -function returns no value. +and +.Fn tdestroy +functions return no value. .Sh EXAMPLES This example uses .Fn tsearch @@ -184,6 +195,7 @@ main(void) tdelete(four, &root, comp); twalk(root, printwalk); + tdestroy(root, NULL); return 0; } .Ed @@ -192,8 +204,17 @@ main(void) .Xr hsearch 3 , .Xr lsearch 3 .Sh STANDARDS -These functions conform to +These +.Fn tdelete , +.Fn tfind , +.Fn tsearch , +and +.Fn twalk +functions conform to .St -p1003.1-2008 . +The +.Fn tdestroy +function is the glibc extension. .Pp The .Fa posix_tnode |
