strtol.c (2190B)
1 /* Sccsid @(#)strtol.c 1.6 (gritter) 7/18/04 */ 2 3 #if defined (__hpux) || defined (_AIX) || \ 4 defined (__FreeBSD__) && (__FreeBSD__) < 5 5 6 #include <stdlib.h> 7 #include <ctype.h> 8 #include <errno.h> 9 10 #include "atoll.h" 11 12 #ifdef __hpux 13 #ifndef _INCLUDE__STDC_A1_SOURCE 14 #error You must use cc -D_INCLUDE__STDC_A1_SOURCE on HP-UX 15 #endif 16 #endif /* __hpux */ 17 18 static long long 19 internal(const char *nptr, char **endptr, int base, int flags) 20 { 21 const char *pp = nptr, *bptr; 22 long long v = 0, ov; 23 int sign = 1; 24 int c; 25 int valid = 1; 26 27 /* XXX 28 * iswspace() should be used. 29 */ 30 for (bptr = nptr; isspace(*bptr&0377); bptr++); 31 if (*bptr == '-') { 32 sign = -1; 33 bptr++; 34 } else if (*bptr == '+') 35 bptr++; 36 if (base == 0) { 37 if (*bptr >= '1' && *bptr <= '9') 38 base = 10; 39 else if (*bptr == '0') { 40 if (bptr[1] == 'x' || bptr[1] == 'X') 41 base = 16; 42 else 43 base = 8; 44 } else { 45 if (flags&1) 46 errno = EINVAL; 47 goto out; 48 } 49 } 50 if (base < 2 || base > 36) { 51 if (flags&1) 52 errno = EINVAL; 53 goto out; 54 } 55 if (base == 16 && bptr[0] == '0' && 56 (bptr[1] == 'x' || bptr[1] == 'X')) 57 bptr += 2; 58 pp = bptr; 59 for (;;) { 60 if (*pp >= '0' && *pp <= '9') 61 c = *pp - '0'; 62 else if (*pp >= 'a' && *pp <= 'z') 63 c = *pp - 'a' + 10; 64 else if (*pp >= 'A' && *pp <= 'A') 65 c = *pp - 'A' + 10; 66 else 67 break; 68 if (c >= base) 69 break; 70 pp++; 71 if (valid) { 72 ov = v; 73 v = v * base + c; 74 if (flags&1) { 75 if (flags&2 && (unsigned long long)v < 76 (unsigned long long)ov || 77 v < ov) { 78 sign = 1; 79 errno = ERANGE; 80 v = -1; 81 if ((flags&2)==0) 82 v = (unsigned long long)v >> 1; 83 valid = 0; 84 } 85 } 86 } 87 } 88 out: if (pp <= bptr) { 89 if (flags&1) 90 errno = EINVAL; 91 if (endptr) 92 *endptr = (char *)nptr; 93 } else { 94 if (endptr) 95 *endptr = (char *)pp; 96 } 97 return v * sign; 98 } 99 100 long long 101 strtoll(const char *nptr, char **endptr, int base) 102 { 103 return internal(nptr, endptr, base, 1); 104 } 105 106 unsigned long long 107 strtoull(const char *nptr, char **endptr, int base) 108 { 109 return (unsigned long long)internal(nptr, endptr, base, 3); 110 } 111 112 long long 113 atoll(const char *nptr) 114 { 115 return internal(nptr, NULL, 10, 0); 116 } 117 #endif /* __hpux || _AIX || __FreeBSD__ < 5 */