libstand: Add strtoul().
authorSascha Wildner <saw@online.de>
Mon, 28 Nov 2016 14:47:18 +0000 (15:47 +0100)
committerSascha Wildner <saw@online.de>
Mon, 28 Nov 2016 14:47:18 +0000 (15:47 +0100)
Taken-from: FreeBSD

lib/libstand/Makefile
lib/libstand/stand.h
lib/libstand/strtoul.c [new file with mode: 0644]

index 9ff11a5..f81f585 100644 (file)
@@ -44,8 +44,9 @@ CFLAGS+=      -mno-mmx -mno-3dnow -mno-sse -mno-sse2 -mno-sse3 -msoft-float
 
 # standalone components and stuff we have modified locally
 SRCS+= __main.c assert.c bcd.c bswap.c environment.c getopt.c gets.c \
-       globals.c pager.c printf.c strdup.c strerror.c strtol.c random.c \
-       sbrk.c twiddle.c zalloc.c zalloc_malloc.c
+       globals.c pager.c printf.c random.c \
+       strdup.c strerror.c strtol.c strtoul.c sbrk.c \
+       twiddle.c zalloc.c zalloc_malloc.c
 
 # private (pruned) versions of libc string functions
 SRCS+= strcasecmp.c
index 785aee8..c2fd08c 100644 (file)
@@ -275,6 +275,7 @@ extern u_long       random(void);
 
 /* imports from stdlib, locally modified */
 extern long    strtol(const char *, char **, int);
+extern unsigned long strtoul(const char *, char **, int);
 extern char    *optarg;                        /* getopt(3) external variables */
 extern int     optind, opterr, optopt, optreset;
 extern int     getopt(int, char * const [], const char *);
diff --git a/lib/libstand/strtoul.c b/lib/libstand/strtoul.c
new file mode 100644 (file)
index 0000000..5e2603f
--- /dev/null
@@ -0,0 +1,118 @@
+/*
+ * Copyright (c) 1990, 1993
+ *     The Regents of the University of California.  All rights reserved.
+ *
+ * Copyright (c) 2011 The FreeBSD Foundation
+ * All rights reserved.
+ * Portions of this software were developed by David Chisnall
+ * under sponsorship from the FreeBSD Foundation.
+ *
+ * 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.
+ * 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.
+ *
+ * @(#)strtoul.c       8.1 (Berkeley) 6/4/93
+ * $FreeBSD: head/lib/libstand/strtoul.c 247001 2013-02-19 17:09:23Z kientzle $
+ */
+
+#include "stand.h"
+#include <limits.h>
+
+/*
+ * Convert a string to an unsigned long integer.
+ *
+ * Assumes that the upper and lower case
+ * alphabets and digits are each contiguous.
+ */
+unsigned long
+strtoul(const char * __restrict nptr, char ** __restrict endptr, int base)
+{
+       const char *s;
+       unsigned long acc;
+       char c;
+       unsigned long cutoff;
+       int neg, any, cutlim;
+
+       /*
+        * See strtol for comments as to the logic used.
+        */
+       s = nptr;
+       do {
+               c = *s++;
+       } while (isspace((unsigned char)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') &&
+           ((s[1] >= '0' && s[1] <= '9') ||
+           (s[1] >= 'A' && s[1] <= 'F') ||
+           (s[1] >= 'a' && s[1] <= 'f'))) {
+               c = s[1];
+               s += 2;
+               base = 16;
+       }
+       if (base == 0)
+               base = c == '0' ? 8 : 10;
+       acc = any = 0;
+       if (base < 2 || base > 36)
+               goto noconv;
+
+       cutoff = ULONG_MAX / base;
+       cutlim = ULONG_MAX % base;
+       for ( ; ; c = *s++) {
+               if (c >= '0' && c <= '9')
+                       c -= '0';
+               else if (c >= 'A' && c <= 'Z')
+                       c -= 'A' - 10;
+               else if (c >= 'a' && c <= 'z')
+                       c -= 'a' - 10;
+               else
+                       break;
+               if (c >= base)
+                       break;
+               if (any < 0 || acc > cutoff || (acc == cutoff && c > cutlim))
+                       any = -1;
+               else {
+                       any = 1;
+                       acc *= base;
+                       acc += c;
+               }
+       }
+       if (any < 0) {
+               acc = ULONG_MAX;
+               errno = ERANGE;
+       } else if (!any) {
+noconv:
+               errno = EINVAL;
+       } else if (neg)
+               acc = -acc;
+       if (endptr != NULL)
+               *endptr = (char *)(any ? s - 1 : nptr);
+       return (acc);
+}