aboutsummaryrefslogtreecommitdiff
path: root/lib/libc/stdlib
diff options
context:
space:
mode:
Diffstat (limited to 'lib/libc/stdlib')
-rw-r--r--lib/libc/stdlib/Makefile.inc6
-rw-r--r--lib/libc/stdlib/bsearch.32
-rw-r--r--lib/libc/stdlib/exit.c2
-rw-r--r--lib/libc/stdlib/getopt.3164
-rw-r--r--lib/libc/stdlib/getopt.c44
-rw-r--r--lib/libc/stdlib/rand48.33
-rw-r--r--lib/libc/stdlib/random.32
-rw-r--r--lib/libc/stdlib/realloc.32
-rw-r--r--lib/libc/stdlib/setenv.c3
-rw-r--r--lib/libc/stdlib/strtol.c2
-rw-r--r--lib/libc/stdlib/strtoq.c136
-rw-r--r--lib/libc/stdlib/strtoul.c2
-rw-r--r--lib/libc/stdlib/strtouq.c114
13 files changed, 403 insertions, 79 deletions
diff --git a/lib/libc/stdlib/Makefile.inc b/lib/libc/stdlib/Makefile.inc
index 972887fbd82a..0bd1a90ab56a 100644
--- a/lib/libc/stdlib/Makefile.inc
+++ b/lib/libc/stdlib/Makefile.inc
@@ -3,17 +3,17 @@
# stdlib sources
.PATH: ${.CURDIR}/${MACHINE}/stdlib ${.CURDIR}/stdlib
-SRCS+= abort.c atexit.c atoi.c atol.c bsearch.c calloc.c div.c exit.c \
+SRCS+= abort.c atexit.c atoi.c atol.c bsearch.c calloc.c exit.c \
getenv.c getopt.c heapsort.c malloc.c multibyte.c \
putenv.c qsort.c radixsort.c rand.c random.c setenv.c strtod.c \
strtol.c strtoul.c system.c \
_rand48.c drand48.c erand48.c jrand48.c lcong48.c lrand48.c \
- mrand48.c nrand48.c seed48.c srand48.c
+ mrand48.c nrand48.c seed48.c srand48.c strtoq.c strtouq.c
.if (${MACHINE} == "hp300")
SRCS+= abs.s div.c labs.c ldiv.c atof.c
.elif (${MACHINE} == "i386")
-SRCS+= abs.s div.s labs.s ldiv.s atof.c
+SRCS+= abs.S div.S labs.S ldiv.S atof.c
.elif (${MACHINE} == "tahoe")
SRCS+= abs.s div.c labs.c ldiv.c atof.c
.elif (${MACHINE} == "vax")
diff --git a/lib/libc/stdlib/bsearch.3 b/lib/libc/stdlib/bsearch.3
index 35c5a426f522..b1de330f2429 100644
--- a/lib/libc/stdlib/bsearch.3
+++ b/lib/libc/stdlib/bsearch.3
@@ -50,7 +50,7 @@ The
.Fn bsearch
function searches an array of
.Fa nmemb
-objects, the inital member of which is
+objects, the initial member of which is
pointed to by
.Fa base ,
for a member that matches the object pointed to by
diff --git a/lib/libc/stdlib/exit.c b/lib/libc/stdlib/exit.c
index 0d3c72520f46..50c872afe529 100644
--- a/lib/libc/stdlib/exit.c
+++ b/lib/libc/stdlib/exit.c
@@ -57,4 +57,6 @@ exit(status)
if (__cleanup)
(*__cleanup)();
_exit(status);
+ /* We'll never get here; this just surpresses a warning. */
+ while(1) { ; }
}
diff --git a/lib/libc/stdlib/getopt.3 b/lib/libc/stdlib/getopt.3
index c21a0a725faf..c028465b992f 100644
--- a/lib/libc/stdlib/getopt.3
+++ b/lib/libc/stdlib/getopt.3
@@ -29,7 +29,8 @@
.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
.\" SUCH DAMAGE.
.\"
-.\" @(#)getopt.3 6.16 (Berkeley) 4/19/91
+.\" from: @(#)getopt.3 6.16 (Berkeley) 4/19/91
+.\" $Id: getopt.3,v 1.2 1993/11/23 00:08:36 jtc Exp $
.\"
.Dd April 19, 1991
.Dt GETOPT 3
@@ -38,12 +39,13 @@
.Nm getopt
.Nd get option letter from argv
.Sh SYNOPSIS
-.Fd #include <stdlib.h>
-.Vt extern char *optarg
-.Vt extern int optind
-.Vt extern int opterr
+.Fd #include <unistd.h>
.Ft int
.Fn getopt "int argc" "char * const *argv" "const char *optstring"
+.Vt extern char *optarg;
+.Vt extern int optind;
+.Vt extern int opterr;
+.Vt extern int optopt;
.Sh DESCRIPTION
The
.Fn getopt
@@ -93,68 +95,137 @@ evaluation.
The
.Fn getopt
function
-returns an
-.Dv EOF
-when the argument list is exhausted, or a non-recognized
-option is encountered.
+returns \-1
+when the argument list is exhausted.
The interpretation of options in the argument list may be cancelled
by the option
.Ql --
(double dash) which causes
.Fn getopt
-to signal the end of argument processing and return an
-.Dv EOF .
+to signal the end of argument processing and return \-1.
When all options have been processed (i.e., up to the first non-option
argument),
.Fn getopt
-returns
-.Dv EOF .
+returns \-1.
.Sh DIAGNOSTICS
-If the
+If the
.Fn getopt
-function encounters a character not found in the string
-.Va optarg
-or detects
-a missing option argument
-it writes error message
-.Ql ?
-to the
-.Em stderr .
-Setting
+function encounters an option character that is not contained in
+.Fa optstring ,
+it returns a question mark
+.Pq ?
+character.
+If it detects a missing option argument, it returns a colon
+.Pq \:
+character if the first character of
+.Fa optstring
+is a colon, otherwise it returns a question mark.
+In either case, a diagnostic message is written to
+.Em stderr
+unless the application has set
.Va opterr
-to a zero will disable these error messages.
+to zero or the first character of
+.Fa optstring
+is a colon.
.Sh EXAMPLE
+.\" The following example comes from section E.9.7 of the IEEE 1003.2-90
+.\" standard (POSIX.2).
+The following code fragment shows how one might process the arguments for
+a utility that can take the mutually exclusive options
+.Em a
+and
+.Em b
+and the options
+.Em f
+and
+.Em o ,
+both of which require arguments:
+.Pp
.Bd -literal -compact
-extern char *optarg;
-extern int optind;
-int bflag, ch, fd;
+#include <unistd.h>
-bflag = 0;
-while ((ch = getopt(argc, argv, "bf:")) != EOF)
- switch(ch) {
- case 'b':
- bflag = 1;
- break;
- case 'f':
- if ((fd = open(optarg, O_RDONLY, 0)) < 0) {
- (void)fprintf(stderr,
- "myname: unable to read file %s.\en", optarg);
- exit(1) ;
+int
+main (argc, argv)
+ int argc;
+ char *argv[];
+{
+ int c, bflg, aflg, errflg = 0;
+ char *ifile, *ofile;
+ extern char *optarg;
+ extern int optind, optopt;
+
+ . . .
+
+ while ((c = getopt(argc, argv, ":abf:o:")) != -1) {
+ switch(ch) {
+ case 'a':
+ if (bflg)
+ errflg = 1;
+ else
+ aflg = 1;
+ break;
+ case 'b':
+ if (aflg)
+ errflg = 1;
+ else
+ bflg = 1;
+ break;
+ case 'f':
+ ifile = optarg;
+ break;
+ case 'o':
+ ofile = optarg;
+ break;
+ case ':': /* -f or -o without option-arg */
+ fprintf (stderr,
+ "Option -%c requires an option-argument\\n",
+ optopt);
+ errflg = 1;
+ break;
+ case '?':
+ fprintf (stderr,
+ "Unrecognized option: -%c\\n",
+ optopt);
+ errflg = 1;
+ break;
}
- break;
- case '?':
- default:
- usage();
+ }
+
+ if (errflg) {
+ fprintf (stderr, "usage: . . .\\n");
+ exit (2);
+ }
+
+ argc -= optind;
+ argv += optind;
+
+ . . .
+
}
-argc -= optind;
-argv += optind;
.Ed
+.Sh STANDARDS
+The
+.Fn getopt
+function conforms to
+.St -p1003.2-92 .
.Sh HISTORY
The
.Fn getopt
function appeared
.Bx 4.3 .
.Sh BUGS
+The
+.Fn getopt
+function was once specified to return
+.Dv EOF
+instead of \-1.
+This was changed by
+.St -p1003.2-92
+to decouple
+.Fn getopt
+from
+.Pa <stdio.h> .
+.Pp
Option arguments are allowed to begin with
.Dq Li \- ;
this is reasonable but
@@ -177,8 +248,7 @@ It is provided for backward compatibility
.Em only .
By default, a single dash causes
.Fn getopt
-to return
-.Dv EOF .
+to returns \-1.
This is, we believe, compatible with System V.
.Pp
It is also possible to handle digits as option letters.
@@ -195,7 +265,7 @@ The following code fragment works fairly well.
int length;
char *p;
-while ((c = getopt(argc, argv, "0123456789")) != EOF)
+while ((c = getopt(argc, argv, "0123456789")) != -1)
switch (c) {
case '0': case '1': case '2': case '3': case '4':
case '5': case '6': case '7': case '8': case '9':
diff --git a/lib/libc/stdlib/getopt.c b/lib/libc/stdlib/getopt.c
index 7126cc1da95a..7d1d9802156f 100644
--- a/lib/libc/stdlib/getopt.c
+++ b/lib/libc/stdlib/getopt.c
@@ -32,7 +32,8 @@
*/
#if defined(LIBC_SCCS) && !defined(lint)
-static char sccsid[] = "@(#)getopt.c 4.13 (Berkeley) 2/23/91";
+/*static char *sccsid = "from: @(#)getopt.c 4.13 (Berkeley) 2/23/91";*/
+static char *rcsid = "$Id: getopt.c,v 1.2 1993/11/23 00:08:37 jtc Exp $";
#endif /* LIBC_SCCS and not lint */
#include <stdio.h>
@@ -42,11 +43,12 @@ static char sccsid[] = "@(#)getopt.c 4.13 (Berkeley) 2/23/91";
/*
* get option letter from argument vector
*/
-int opterr = 1, /* if error message should be printed */
- optind = 1, /* index into parent argv vector */
- optopt; /* character checked for validity */
+int opterr = 1; /* if error message should be printed */
+int optind = 1; /* index into parent argv vector */
+int optopt; /* character checked for validity */
char *optarg; /* argument associated with option */
+#define NOOPT (int)':' /* No option */
#define BADCH (int)'?'
#define EMSG ""
@@ -63,26 +65,27 @@ getopt(nargc, nargv, ostr)
if (!*place) { /* update scanning pointer */
if (optind >= nargc || *(place = nargv[optind]) != '-') {
place = EMSG;
- return(EOF);
+ return(-1);
}
if (place[1] && *++place == '-') { /* found "--" */
++optind;
place = EMSG;
- return(EOF);
+ return(-1);
}
- } /* option letter okay? */
+ }
+ /* option letter okay? */
if ((optopt = (int)*place++) == (int)':' ||
- !(oli = index(ostr, optopt))) {
+ !(oli = strchr(ostr, optopt))) {
/*
* if the user didn't specify '-' as an option,
- * assume it means EOF.
+ * assume it means -1.
*/
if (optopt == (int)'-')
- return(EOF);
+ return(-1);
if (!*place)
++optind;
- if (opterr) {
- if (!(p = rindex(*nargv, '/')))
+ if (opterr && *ostr != ':') {
+ if (!(p = strrchr(*nargv, '/')))
p = *nargv;
else
++p;
@@ -91,25 +94,26 @@ getopt(nargc, nargv, ostr)
}
return(BADCH);
}
+
if (*++oli != ':') { /* don't need argument */
optarg = NULL;
if (!*place)
++optind;
- }
- else { /* need an argument */
+ } else { /* need an argument */
if (*place) /* no white space */
optarg = place;
else if (nargc <= ++optind) { /* no arg */
place = EMSG;
- if (!(p = rindex(*nargv, '/')))
- p = *nargv;
- else
- ++p;
- if (opterr)
+ if (opterr && *ostr != ':') {
+ if (!(p = strrchr(*nargv, '/')))
+ p = *nargv;
+ else
+ ++p;
(void)fprintf(stderr,
"%s: option requires an argument -- %c\n",
p, optopt);
- return(BADCH);
+ }
+ return((*ostr == ':') ? NOOPT : BADCH);
}
else /* white space */
optarg = nargv[optind];
diff --git a/lib/libc/stdlib/rand48.3 b/lib/libc/stdlib/rand48.3
index fead60db46e2..176303dcf795 100644
--- a/lib/libc/stdlib/rand48.3
+++ b/lib/libc/stdlib/rand48.3
@@ -158,6 +158,3 @@ Martin Birgmeier
.Sh SEE ALSO
.Xr rand 3 ,
.Xr random 3 .
-============================== cut here ==============================
-
-
diff --git a/lib/libc/stdlib/random.3 b/lib/libc/stdlib/random.3
index 872983cd9e86..17a31b2aae45 100644
--- a/lib/libc/stdlib/random.3
+++ b/lib/libc/stdlib/random.3
@@ -41,7 +41,7 @@
.Nm setstate
.Nd better random number generator; routines for changing generators
.Sh SYNOPSIS
-.Fd #include <stdlib>
+.Fd #include <stdlib.h>
.Ft long
.Fn random void
.Ft void
diff --git a/lib/libc/stdlib/realloc.3 b/lib/libc/stdlib/realloc.3
index ee3e64018fc7..ba2ccc9180fb 100644
--- a/lib/libc/stdlib/realloc.3
+++ b/lib/libc/stdlib/realloc.3
@@ -72,7 +72,7 @@ by a call to the
or
.Fn realloc
function, unpredictable and usually detrimental
-behaviour will occur.
+behavior will occur.
If the space cannot be allocated, the object
pointed to by
.Fa ptr
diff --git a/lib/libc/stdlib/setenv.c b/lib/libc/stdlib/setenv.c
index 14efac37b37c..9cade228c687 100644
--- a/lib/libc/stdlib/setenv.c
+++ b/lib/libc/stdlib/setenv.c
@@ -39,6 +39,8 @@ static char sccsid[] = "@(#)setenv.c 5.6 (Berkeley) 6/4/91";
#include <stdlib.h>
#include <string.h>
+extern char *_findenv();
+
/*
* setenv --
* Set the value of the environmental variable "name" to be
@@ -53,7 +55,6 @@ setenv(name, value, rewrite)
static int alloced; /* if allocated space before */
register char *C;
int l_value, offset;
- char *_findenv();
if (*value == '=') /* no `=' in value */
++value;
diff --git a/lib/libc/stdlib/strtol.c b/lib/libc/stdlib/strtol.c
index 000d87647af6..1c1d5c96ee9a 100644
--- a/lib/libc/stdlib/strtol.c
+++ b/lib/libc/stdlib/strtol.c
@@ -124,6 +124,6 @@ strtol(nptr, endptr, base)
} else if (neg)
acc = -acc;
if (endptr != 0)
- *endptr = any ? s - 1 : (char *)nptr;
+ *endptr = any ? (char *)s - 1 : (char *)nptr;
return (acc);
}
diff --git a/lib/libc/stdlib/strtoq.c b/lib/libc/stdlib/strtoq.c
new file mode 100644
index 000000000000..af02765d6c98
--- /dev/null
+++ b/lib/libc/stdlib/strtoq.c
@@ -0,0 +1,136 @@
+/*-
+ * Copyright (c) 1992 The Regents of the University of California.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ * must display the following acknowledgement:
+ * This product includes software developed by the University of
+ * California, Berkeley and its contributors.
+ * 4. Neither the name of the University nor the names of its contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#if defined(LIBC_SCCS) && !defined(lint)
+static char sccsid[] = "@(#)strtoq.c 5.1 (Berkeley) 6/26/92";
+#endif /* LIBC_SCCS and not lint */
+
+#include <sys/types.h>
+
+#include <limits.h>
+#include <errno.h>
+#include <ctype.h>
+#include <stdlib.h>
+
+/*
+ * Convert a string to a quad integer.
+ *
+ * Ignores `locale' stuff. Assumes that the upper and lower case
+ * alphabets and digits are each contiguous.
+ */
+quad_t
+strtoq(nptr, endptr, base)
+ const char *nptr;
+ char **endptr;
+ register int base;
+{
+ register const char *s;
+ register u_quad_t acc;
+ register int c;
+ register u_quad_t qbase, cutoff;
+ register int neg, any, cutlim;
+
+ /*
+ * Skip white space and pick up leading +/- sign if any.
+ * If base is 0, allow 0x for hex and 0 for octal, else
+ * assume decimal; if base is already 16, allow 0x.
+ */
+ s = nptr;
+ do {
+ c = *s++;
+ } while (isspace(c));
+ if (c == '-') {
+ neg = 1;
+ c = *s++;
+ } else {
+ neg = 0;
+ if (c == '+')
+ c = *s++;
+ }
+ if ((base == 0 || base == 16) &&
+ c == '0' && (*s == 'x' || *s == 'X')) {
+ c = s[1];
+ s += 2;
+ base = 16;
+ }
+ if (base == 0)
+ base = c == '0' ? 8 : 10;
+
+ /*
+ * Compute the cutoff value between legal numbers and illegal
+ * numbers. That is the largest legal value, divided by the
+ * base. An input number that is greater than this value, if
+ * followed by a legal input character, is too big. One that
+ * is equal to this value may be valid or not; the limit
+ * between valid and invalid numbers is then based on the last
+ * digit. For instance, if the range for quads is
+ * [-9223372036854775808..9223372036854775807] and the input base
+ * is 10, cutoff will be set to 922337203685477580 and cutlim to
+ * either 7 (neg==0) or 8 (neg==1), meaning that if we have
+ * accumulated a value > 922337203685477580, or equal but the
+ * next digit is > 7 (or 8), the number is too big, and we will
+ * return a range error.
+ *
+ * Set any if any `digits' consumed; make it negative to indicate
+ * overflow.
+ */
+ qbase = (unsigned)base;
+ cutoff = neg ? -(u_quad_t)QUAD_MIN : QUAD_MAX;
+ cutlim = cutoff % qbase;
+ cutoff /= qbase;
+ for (acc = 0, any = 0;; c = *s++) {
+ if (isdigit(c))
+ c -= '0';
+ else if (isalpha(c))
+ c -= isupper(c) ? 'A' - 10 : 'a' - 10;
+ else
+ break;
+ if (c >= base)
+ break;
+ if (any < 0 || acc > cutoff || acc == cutoff && c > cutlim)
+ any = -1;
+ else {
+ any = 1;
+ acc *= qbase;
+ acc += c;
+ }
+ }
+ if (any < 0) {
+ acc = neg ? QUAD_MIN : QUAD_MAX;
+ errno = ERANGE;
+ } else if (neg)
+ acc = -acc;
+ if (endptr != 0)
+ *endptr = any ? (char *)s - 1 : (char *)nptr;
+ return (acc);
+}
diff --git a/lib/libc/stdlib/strtoul.c b/lib/libc/stdlib/strtoul.c
index ed8c1080ba6e..284c182ef71c 100644
--- a/lib/libc/stdlib/strtoul.c
+++ b/lib/libc/stdlib/strtoul.c
@@ -102,6 +102,6 @@ strtoul(nptr, endptr, base)
} else if (neg)
acc = -acc;
if (endptr != 0)
- *endptr = any ? s - 1 : (char *)nptr;
+ *endptr = any ? (char *)s - 1 : (char *)nptr;
return (acc);
}
diff --git a/lib/libc/stdlib/strtouq.c b/lib/libc/stdlib/strtouq.c
new file mode 100644
index 000000000000..14e37e07f324
--- /dev/null
+++ b/lib/libc/stdlib/strtouq.c
@@ -0,0 +1,114 @@
+/*-
+ * Copyright (c) 1992 The Regents of the University of California.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ * must display the following acknowledgement:
+ * This product includes software developed by the University of
+ * California, Berkeley and its contributors.
+ * 4. Neither the name of the University nor the names of its contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#if defined(LIBC_SCCS) && !defined(lint)
+static char sccsid[] = "@(#)strtouq.c 5.1 (Berkeley) 6/26/92";
+#endif /* LIBC_SCCS and not lint */
+
+#include <sys/types.h>
+
+#include <limits.h>
+#include <errno.h>
+#include <ctype.h>
+#include <stdlib.h>
+
+/*
+ * Convert a string to an unsigned quad integer.
+ *
+ * Ignores `locale' stuff. Assumes that the upper and lower case
+ * alphabets and digits are each contiguous.
+ */
+u_quad_t
+strtouq(nptr, endptr, base)
+ const char *nptr;
+ char **endptr;
+ register int base;
+{
+ register const char *s = nptr;
+ register u_quad_t acc;
+ register int c;
+ register u_quad_t qbase, cutoff;
+ register int neg, any, cutlim;
+
+ /*
+ * See strtoq for comments as to the logic used.
+ */
+ s = nptr;
+ do {
+ c = *s++;
+ } while (isspace(c));
+ if (c == '-') {
+ neg = 1;
+ c = *s++;
+ } else {
+ neg = 0;
+ if (c == '+')
+ c = *s++;
+ }
+ if ((base == 0 || base == 16) &&
+ c == '0' && (*s == 'x' || *s == 'X')) {
+ c = s[1];
+ s += 2;
+ base = 16;
+ }
+ if (base == 0)
+ base = c == '0' ? 8 : 10;
+ qbase = (unsigned)base;
+ cutoff = (u_quad_t)UQUAD_MAX / qbase;
+ cutlim = (u_quad_t)UQUAD_MAX % qbase;
+ for (acc = 0, any = 0;; c = *s++) {
+ if (isdigit(c))
+ c -= '0';
+ else if (isalpha(c))
+ c -= isupper(c) ? 'A' - 10 : 'a' - 10;
+ else
+ break;
+ if (c >= base)
+ break;
+ if (any < 0 || acc > cutoff || acc == cutoff && c > cutlim)
+ any = -1;
+ else {
+ any = 1;
+ acc *= qbase;
+ acc += c;
+ }
+ }
+ if (any < 0) {
+ acc = UQUAD_MAX;
+ errno = ERANGE;
+ } else if (neg)
+ acc = -acc;
+ if (endptr != 0)
+ *endptr = any ? (char *)s - 1 : (char *)nptr;
+ return (acc);
+}