1/*- 2 * Copyright (c) 1992, 1993 3 * The Regents of the University of California. All rights reserved. 4 * 5 * Redistribution and use in source and binary forms, with or without 6 * modification, are permitted provided that the following conditions 7 * are met: 8 * 1. Redistributions of source code must retain the above copyright --- 16 unchanged lines hidden (view full) --- 25 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 26 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 27 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 28 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 29 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 30 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 31 * SUCH DAMAGE. 32 * |
33 * $FreeBSD: head/lib/libc/stdlib/strtoimax.c 87494 2001-12-07 16:33:47Z ache $ |
34 */ 35 36#if defined(LIBC_SCCS) && !defined(lint) 37static char sccsid[] = "from @(#)strtol.c 8.1 (Berkeley) 6/4/93"; 38#endif /* LIBC_SCCS and not lint */ 39 40#include <ctype.h> 41#include <errno.h> --- 9 unchanged lines hidden (view full) --- 51intmax_t 52strtoimax(nptr, endptr, base) 53 const char *nptr; 54 char **endptr; 55 int base; 56{ 57 const char *s; 58 uintmax_t acc; |
59 char c; |
60 uintmax_t cutoff; |
61 int neg, any, cutlim; |
62 63 /* 64 * Skip white space and pick up leading +/- sign if any. 65 * If base is 0, allow 0x for hex and 0 for octal, else 66 * assume decimal; if base is already 16, allow 0x. 67 */ 68 s = nptr; 69 do { 70 c = *s++; |
71 } while (isspace((unsigned char)c)); |
72 if (c == '-') { 73 neg = 1; 74 c = *s++; 75 } else { 76 neg = 0; 77 if (c == '+') 78 c = *s++; 79 } --- 27 unchanged lines hidden (view full) --- 107 * Set 'any' if any `digits' consumed; make it negative to indicate 108 * overflow. 109 */ 110 cutoff = neg ? (uintmax_t)-(INTMAX_MIN + INTMAX_MAX) + INTMAX_MAX 111 : INTMAX_MAX; 112 cutlim = cutoff % base; 113 cutoff /= base; 114 for ( ; ; c = *s++) { |
115 if (c >= '0' && c <= '9') 116 c -= '0'; 117 else if (c >= 'A' && c <= 'Z') 118 c -= 'A' - 10; 119 else if (c >= 'a' && c <= 'z') 120 c -= 'a' - 10; |
121 else 122 break; |
123 if (c >= base) |
124 break; |
125 if (any < 0 || acc > cutoff || (acc == cutoff && c > cutlim)) |
126 any = -1; 127 else { 128 any = 1; 129 acc *= base; |
130 acc += c; |
131 } 132 } 133 if (any < 0) { 134 acc = neg ? INTMAX_MIN : INTMAX_MAX; 135 errno = ERANGE; 136 } else if (!any) { 137noconv: 138 errno = EINVAL; 139 } else if (neg) 140 acc = -acc; 141 if (endptr != NULL) 142 *endptr = (char *)(any ? s - 1 : nptr); 143 return (acc); 144} |