1 /* Convert string representation of a number into an integer value. 2 3 Copyright (C) 1991, 1992, 1994, 1995, 1996, 1997, 1998, 1999, 2003, 2005 4 Free Software Foundation, Inc. 5 6 NOTE: The canonical source of this file is maintained with the GNU C 7 Library. Bugs can be reported to bug-glibc@gnu.org. 8 9 This program is free software; you can redistribute it and/or modify it 10 under the terms of the GNU General Public License as published by the 11 Free Software Foundation; either version 2, or (at your option) any 12 later version. 13 14 This program is distributed in the hope that it will be useful, 15 but WITHOUT ANY WARRANTY; without even the implied warranty of 16 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 17 GNU General Public License for more details. 18 19 You should have received a copy of the GNU General Public License 20 along with this program; if not, write to the Free Software Foundation, 21 Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ 22 #include <sys/cdefs.h> 23 __RCSID("$NetBSD: strtol.c,v 1.2 2016/05/17 14:00:09 christos Exp $"); 24 25 26 #ifdef HAVE_CONFIG_H 27 # include <config.h> 28 #endif 29 30 #ifdef _LIBC 31 # define USE_NUMBER_GROUPING 32 #endif 33 34 #include <ctype.h> 35 #include <errno.h> 36 #ifndef errno 37 extern int errno; 38 #endif 39 #ifndef __set_errno 40 # define __set_errno(Val) errno = (Val) 41 #endif 42 43 #include <limits.h> 44 #include <stddef.h> 45 #include <stdlib.h> 46 #include <string.h> 47 48 #ifdef USE_NUMBER_GROUPING 49 # include "../locale/localeinfo.h" 50 #endif 51 52 /* Nonzero if we are defining `strtoul' or `strtoull', operating on 53 unsigned integers. */ 54 #ifndef UNSIGNED 55 # define UNSIGNED 0 56 # define INT LONG int 57 #else 58 # define INT unsigned LONG int 59 #endif 60 61 /* Determine the name. */ 62 #ifdef USE_IN_EXTENDED_LOCALE_MODEL 63 # if UNSIGNED 64 # ifdef USE_WIDE_CHAR 65 # ifdef QUAD 66 # define strtol __wcstoull_l 67 # else 68 # define strtol __wcstoul_l 69 # endif 70 # else 71 # ifdef QUAD 72 # define strtol __strtoull_l 73 # else 74 # define strtol __strtoul_l 75 # endif 76 # endif 77 # else 78 # ifdef USE_WIDE_CHAR 79 # ifdef QUAD 80 # define strtol __wcstoll_l 81 # else 82 # define strtol __wcstol_l 83 # endif 84 # else 85 # ifdef QUAD 86 # define strtol __strtoll_l 87 # else 88 # define strtol __strtol_l 89 # endif 90 # endif 91 # endif 92 #else 93 # if UNSIGNED 94 # ifdef USE_WIDE_CHAR 95 # ifdef QUAD 96 # define strtol wcstoull 97 # else 98 # define strtol wcstoul 99 # endif 100 # else 101 # ifdef QUAD 102 # define strtol strtoull 103 # else 104 # define strtol strtoul 105 # endif 106 # endif 107 # else 108 # ifdef USE_WIDE_CHAR 109 # ifdef QUAD 110 # define strtol wcstoll 111 # else 112 # define strtol wcstol 113 # endif 114 # else 115 # ifdef QUAD 116 # define strtol strtoll 117 # endif 118 # endif 119 # endif 120 #endif 121 122 /* If QUAD is defined, we are defining `strtoll' or `strtoull', 123 operating on `long long int's. */ 124 #ifdef QUAD 125 # define LONG long long 126 # define STRTOL_LONG_MIN LONG_LONG_MIN 127 # define STRTOL_LONG_MAX LONG_LONG_MAX 128 # define STRTOL_ULONG_MAX ULONG_LONG_MAX 129 130 /* The extra casts in the following macros work around compiler bugs, 131 e.g., in Cray C 5.0.3.0. */ 132 133 /* True if negative values of the signed integer type T use two's 134 complement, ones' complement, or signed magnitude representation, 135 respectively. Much GNU code assumes two's complement, but some 136 people like to be portable to all possible C hosts. */ 137 # define TYPE_TWOS_COMPLEMENT(t) ((t) ~ (t) 0 == (t) -1) 138 # define TYPE_ONES_COMPLEMENT(t) ((t) ~ (t) 0 == 0) 139 # define TYPE_SIGNED_MAGNITUDE(t) ((t) ~ (t) 0 < (t) -1) 140 141 /* True if the arithmetic type T is signed. */ 142 # define TYPE_SIGNED(t) (! ((t) 0 < (t) -1)) 143 144 /* The maximum and minimum values for the integer type T. These 145 macros have undefined behavior if T is signed and has padding bits. 146 If this is a problem for you, please let us know how to fix it for 147 your host. */ 148 # define TYPE_MINIMUM(t) \ 149 ((t) (! TYPE_SIGNED (t) \ 150 ? (t) 0 \ 151 : TYPE_SIGNED_MAGNITUDE (t) \ 152 ? ~ (t) 0 \ 153 : ~ (t) 0 << (sizeof (t) * CHAR_BIT - 1))) 154 # define TYPE_MAXIMUM(t) \ 155 ((t) (! TYPE_SIGNED (t) \ 156 ? (t) -1 \ 157 : ~ (~ (t) 0 << (sizeof (t) * CHAR_BIT - 1)))) 158 159 # ifndef ULONG_LONG_MAX 160 # define ULONG_LONG_MAX TYPE_MAXIMUM (unsigned long long) 161 # endif 162 # ifndef LONG_LONG_MAX 163 # define LONG_LONG_MAX TYPE_MAXIMUM (long long int) 164 # endif 165 # ifndef LONG_LONG_MIN 166 # define LONG_LONG_MIN TYPE_MINIMUM (long long int) 167 # endif 168 169 # if __GNUC__ == 2 && __GNUC_MINOR__ < 7 170 /* Work around gcc bug with using this constant. */ 171 static const unsigned long long int maxquad = ULONG_LONG_MAX; 172 # undef STRTOL_ULONG_MAX 173 # define STRTOL_ULONG_MAX maxquad 174 # endif 175 #else 176 # define LONG long 177 # define STRTOL_LONG_MIN LONG_MIN 178 # define STRTOL_LONG_MAX LONG_MAX 179 # define STRTOL_ULONG_MAX ULONG_MAX 180 #endif 181 182 183 /* We use this code also for the extended locale handling where the 184 function gets as an additional argument the locale which has to be 185 used. To access the values we have to redefine the _NL_CURRENT 186 macro. */ 187 #ifdef USE_IN_EXTENDED_LOCALE_MODEL 188 # undef _NL_CURRENT 189 # define _NL_CURRENT(category, item) \ 190 (current->values[_NL_ITEM_INDEX (item)].string) 191 # define LOCALE_PARAM , loc 192 # define LOCALE_PARAM_PROTO , __locale_t loc 193 #else 194 # define LOCALE_PARAM 195 # define LOCALE_PARAM_PROTO 196 #endif 197 198 #if defined _LIBC || defined HAVE_WCHAR_H 199 # include <wchar.h> 200 #endif 201 202 #ifdef USE_WIDE_CHAR 203 # include <wctype.h> 204 # define L_(Ch) L##Ch 205 # define UCHAR_TYPE wint_t 206 # define STRING_TYPE wchar_t 207 # ifdef USE_IN_EXTENDED_LOCALE_MODEL 208 # define ISSPACE(Ch) __iswspace_l ((Ch), loc) 209 # define ISALPHA(Ch) __iswalpha_l ((Ch), loc) 210 # define TOUPPER(Ch) __towupper_l ((Ch), loc) 211 # else 212 # define ISSPACE(Ch) iswspace (Ch) 213 # define ISALPHA(Ch) iswalpha (Ch) 214 # define TOUPPER(Ch) towupper (Ch) 215 # endif 216 #else 217 # if defined STDC_HEADERS || (!defined isascii && !defined HAVE_ISASCII) 218 # define IN_CTYPE_DOMAIN(c) 1 219 # else 220 # define IN_CTYPE_DOMAIN(c) isascii(c) 221 # endif 222 # define L_(Ch) Ch 223 # define UCHAR_TYPE unsigned char 224 # define STRING_TYPE char 225 # ifdef USE_IN_EXTENDED_LOCALE_MODEL 226 # define ISSPACE(Ch) __isspace_l ((Ch), loc) 227 # define ISALPHA(Ch) __isalpha_l ((Ch), loc) 228 # define TOUPPER(Ch) __toupper_l ((Ch), loc) 229 # else 230 # define ISSPACE(Ch) (IN_CTYPE_DOMAIN (Ch) && isspace (Ch)) 231 # define ISALPHA(Ch) (IN_CTYPE_DOMAIN (Ch) && isalpha (Ch)) 232 # define TOUPPER(Ch) (IN_CTYPE_DOMAIN (Ch) ? toupper (Ch) : (Ch)) 233 # endif 234 #endif 235 236 #define INTERNAL(X) INTERNAL1(X) 237 #define INTERNAL1(X) __##X##_internal 238 #define WEAKNAME(X) WEAKNAME1(X) 239 240 #ifdef USE_NUMBER_GROUPING 241 /* This file defines a function to check for correct grouping. */ 242 # include "grouping.h" 243 #endif 244 245 246 247 /* Convert NPTR to an `unsigned long int' or `long int' in base BASE. 248 If BASE is 0 the base is determined by the presence of a leading 249 zero, indicating octal or a leading "0x" or "0X", indicating hexadecimal. 250 If BASE is < 2 or > 36, it is reset to 10. 251 If ENDPTR is not NULL, a pointer to the character after the last 252 one converted is stored in *ENDPTR. */ 253 254 INT 255 INTERNAL (strtol) (const STRING_TYPE *nptr, STRING_TYPE **endptr, 256 int base, int group LOCALE_PARAM_PROTO) 257 { 258 int negative; 259 register unsigned LONG int cutoff; 260 register unsigned int cutlim; 261 register unsigned LONG int i; 262 register const STRING_TYPE *s; 263 register UCHAR_TYPE c; 264 const STRING_TYPE *save, *end; 265 int overflow; 266 267 #ifdef USE_NUMBER_GROUPING 268 # ifdef USE_IN_EXTENDED_LOCALE_MODEL 269 struct locale_data *current = loc->__locales[LC_NUMERIC]; 270 # endif 271 /* The thousands character of the current locale. */ 272 wchar_t thousands = L'\0'; 273 /* The numeric grouping specification of the current locale, 274 in the format described in <locale.h>. */ 275 const char *grouping; 276 277 if (group) 278 { 279 grouping = _NL_CURRENT (LC_NUMERIC, GROUPING); 280 if (*grouping <= 0 || *grouping == CHAR_MAX) 281 grouping = NULL; 282 else 283 { 284 /* Figure out the thousands separator character. */ 285 # if defined _LIBC || defined _HAVE_BTOWC 286 thousands = __btowc (*_NL_CURRENT (LC_NUMERIC, THOUSANDS_SEP)); 287 if (thousands == WEOF) 288 thousands = L'\0'; 289 # endif 290 if (thousands == L'\0') 291 grouping = NULL; 292 } 293 } 294 else 295 grouping = NULL; 296 #endif 297 298 if (base < 0 || base == 1 || base > 36) 299 { 300 __set_errno (EINVAL); 301 return 0; 302 } 303 304 save = s = nptr; 305 306 /* Skip white space. */ 307 while (ISSPACE (*s)) 308 ++s; 309 if (*s == L_('\0')) 310 goto noconv; 311 312 /* Check for a sign. */ 313 if (*s == L_('-')) 314 { 315 negative = 1; 316 ++s; 317 } 318 else if (*s == L_('+')) 319 { 320 negative = 0; 321 ++s; 322 } 323 else 324 negative = 0; 325 326 /* Recognize number prefix and if BASE is zero, figure it out ourselves. */ 327 if (*s == L_('0')) 328 { 329 if ((base == 0 || base == 16) && TOUPPER (s[1]) == L_('X')) 330 { 331 s += 2; 332 base = 16; 333 } 334 else if (base == 0) 335 base = 8; 336 } 337 else if (base == 0) 338 base = 10; 339 340 /* Save the pointer so we can check later if anything happened. */ 341 save = s; 342 343 #ifdef USE_NUMBER_GROUPING 344 if (group) 345 { 346 /* Find the end of the digit string and check its grouping. */ 347 end = s; 348 for (c = *end; c != L_('\0'); c = *++end) 349 if ((wchar_t) c != thousands 350 && ((wchar_t) c < L_('0') || (wchar_t) c > L_('9')) 351 && (!ISALPHA (c) || (int) (TOUPPER (c) - L_('A') + 10) >= base)) 352 break; 353 if (*s == thousands) 354 end = s; 355 else 356 end = correctly_grouped_prefix (s, end, thousands, grouping); 357 } 358 else 359 #endif 360 end = NULL; 361 362 cutoff = STRTOL_ULONG_MAX / (unsigned LONG int) base; 363 cutlim = STRTOL_ULONG_MAX % (unsigned LONG int) base; 364 365 overflow = 0; 366 i = 0; 367 for (c = *s; c != L_('\0'); c = *++s) 368 { 369 if (s == end) 370 break; 371 if (c >= L_('0') && c <= L_('9')) 372 c -= L_('0'); 373 else if (ISALPHA (c)) 374 c = TOUPPER (c) - L_('A') + 10; 375 else 376 break; 377 if ((int) c >= base) 378 break; 379 /* Check for overflow. */ 380 if (i > cutoff || (i == cutoff && c > cutlim)) 381 overflow = 1; 382 else 383 { 384 i *= (unsigned LONG int) base; 385 i += c; 386 } 387 } 388 389 /* Check if anything actually happened. */ 390 if (s == save) 391 goto noconv; 392 393 /* Store in ENDPTR the address of one character 394 past the last character we converted. */ 395 if (endptr != NULL) 396 *endptr = (STRING_TYPE *) s; 397 398 #if !UNSIGNED 399 /* Check for a value that is within the range of 400 `unsigned LONG int', but outside the range of `LONG int'. */ 401 if (overflow == 0 402 && i > (negative 403 ? -((unsigned LONG int) (STRTOL_LONG_MIN + 1)) + 1 404 : (unsigned LONG int) STRTOL_LONG_MAX)) 405 overflow = 1; 406 #endif 407 408 if (overflow) 409 { 410 __set_errno (ERANGE); 411 #if UNSIGNED 412 return STRTOL_ULONG_MAX; 413 #else 414 return negative ? STRTOL_LONG_MIN : STRTOL_LONG_MAX; 415 #endif 416 } 417 418 /* Return the result of the appropriate sign. */ 419 return negative ? -i : i; 420 421 noconv: 422 /* We must handle a special case here: the base is 0 or 16 and the 423 first two characters are '0' and 'x', but the rest are no 424 hexadecimal digits. This is no error case. We return 0 and 425 ENDPTR points to the `x`. */ 426 if (endptr != NULL) 427 { 428 if (save - nptr >= 2 && TOUPPER (save[-1]) == L_('X') 429 && save[-2] == L_('0')) 430 *endptr = (STRING_TYPE *) &save[-1]; 431 else 432 /* There was no number to convert. */ 433 *endptr = (STRING_TYPE *) nptr; 434 } 435 436 return 0L; 437 } 438 439 /* External user entry point. */ 440 441 442 INT 443 #ifdef weak_function 444 weak_function 445 #endif 446 strtol (const STRING_TYPE *nptr, STRING_TYPE **endptr, 447 int base LOCALE_PARAM_PROTO) 448 { 449 return INTERNAL (strtol) (nptr, endptr, base, 0 LOCALE_PARAM); 450 } 451