1/* Copyright (C) 1991 Free Software Foundation, Inc. 2This file is part of the GNU C Library. 3 4The GNU C Library is free software; you can redistribute it and/or 5modify it under the terms of the GNU Library General Public License as 6published by the Free Software Foundation; either version 2 of the 7License, or (at your option) any later version. 8 9The GNU C Library is distributed in the hope that it will be useful, 10but WITHOUT ANY WARRANTY; without even the implied warranty of 11MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 12Library General Public License for more details. 13 14You should have received a copy of the GNU Library General Public 15License along with the GNU C Library; see the file COPYING.LIB. If 16not, write to the Free Software Foundation, Inc., 59 Temple Place - 17Suite 330, Boston, MA 02111-1307, USA. 18 19This file was modified slightly by Ian Lance Taylor, May 1992, for 20Taylor UUCP. */ 21 22#include "uucp.h" 23 24#include <ctype.h> 25#include <errno.h> 26 27#if HAVE_LIMITS_H 28#include <limits.h> 29#else 30#define ULONG_MAX 4294967295 31#define LONG_MIN (- LONG_MAX - 1) 32#define LONG_MAX 2147483647 33#endif 34 35#ifndef UNSIGNED 36#define UNSIGNED 0 37#endif 38 39/* Convert NPTR to an `unsigned long int' or `long int' in base BASE. 40 If BASE is 0 the base is determined by the presence of a leading 41 zero, indicating octal or a leading "0x" or "0X", indicating hexadecimal. 42 If BASE is < 2 or > 36, it is reset to 10. 43 If ENDPTR is not NULL, a pointer to the character after the last 44 one converted is stored in *ENDPTR. */ 45#if UNSIGNED 46unsigned long int 47#define strtol strtoul 48#else 49long int 50#endif 51strtol (nptr, endptr, base) 52 const char *nptr; 53 char **endptr; 54 int base; 55{ 56 int negative; 57 register unsigned long int cutoff; 58 register unsigned int cutlim; 59 register unsigned long int i; 60 register const char *s; 61 register unsigned int c; 62 const char *save; 63 int overflow; 64 65 if (base < 0 || base == 1 || base > 36) 66 base = 10; 67 68 s = nptr; 69 70 /* Skip white space. */ 71 while (isspace(BUCHAR (*s))) 72 ++s; 73 if (*s == '\0') 74 goto noconv; 75 76 /* Check for a sign. */ 77 if (*s == '-') 78 { 79 negative = 1; 80 ++s; 81 } 82 else if (*s == '+') 83 { 84 negative = 0; 85 ++s; 86 } 87 else 88 negative = 0; 89 90 if (base == 16 91 && s[0] == '0' 92 && (s[1] == 'x' || s[1] == 'X')) 93 s += 2; 94 95 /* If BASE is zero, figure it out ourselves. */ 96 if (base == 0) 97 if (*s == '0') 98 { 99 if (s[1] == 'x' || s[1] == 'X') 100 { 101 s += 2; 102 base = 16; 103 } 104 else 105 base = 8; 106 } 107 else 108 base = 10; 109 110 /* Save the pointer so we can check later if anything happened. */ 111 save = s; 112 113 cutoff = ULONG_MAX / (unsigned long int) base; 114 cutlim = ULONG_MAX % (unsigned long int) base; 115 116 overflow = 0; 117 i = 0; 118 for (c = BUCHAR (*s); c != '\0'; c = BUCHAR (*++s)) 119 { 120 if (isdigit(c)) 121 c -= '0'; 122 else if (islower(c)) 123 c = c - 'a' + 10; 124 else if (isupper(c)) 125 c = c - 'A' + 10; 126 else 127 break; 128 if (c >= base) 129 break; 130 /* Check for overflow. */ 131 if (i > cutoff || (i == cutoff && c > cutlim)) 132 overflow = 1; 133 else 134 { 135 i *= (unsigned long int) base; 136 i += c; 137 } 138 } 139 140 /* Check if anything actually happened. */ 141 if (s == save) 142 goto noconv; 143 144 /* Store in ENDPTR the address of one character 145 past the last character we converted. */ 146 if (endptr != NULL) 147 *endptr = (char *) s; 148 149#if !UNSIGNED 150 /* Check for a value that is within the range of 151 `unsigned long int', but outside the range of `long int'. */ 152 if (i > (negative ? 153 - (unsigned long int) LONG_MIN : (unsigned long int) LONG_MAX)) 154 overflow = 1; 155#endif 156 157 if (overflow) 158 { 159 errno = ERANGE; 160#if UNSIGNED 161 return ULONG_MAX; 162#else 163 return negative ? LONG_MIN : LONG_MAX; 164#endif 165 } 166 167 /* Return the result of the appropriate sign. */ 168 return (negative ? - i : i); 169 170 noconv: 171 /* There was no number to convert. */ 172 if (endptr != NULL) 173 *endptr = (char *) nptr; 174 return 0L; 175} 176