diff options
Diffstat (limited to 'main/glib/strtol.c')
-rw-r--r-- | main/glib/strtol.c | 179 |
1 files changed, 93 insertions, 86 deletions
diff --git a/main/glib/strtol.c b/main/glib/strtol.c index 4c3571c..ce18845 100644 --- a/main/glib/strtol.c +++ b/main/glib/strtol.c @@ -1,6 +1,6 @@ /*- * Copyright (c) 1990, 1993 - * The Regents of the University of California. All rights reserved. + * The Regents of the University of California. All rights reserved. * * Copyright (c) 2011 The FreeBSD Foundation * All rights reserved. @@ -50,94 +50,101 @@ __FBSDID("$FreeBSD$"); * alphabets and digits are each contiguous. */ long -strtol(const char * __restrict nptr, char ** __restrict endptr, int base) +strtol(const char *__restrict nptr, char **__restrict endptr, int base) { - const char *s; - unsigned long acc; - char c; - unsigned long cutoff; - int neg, any, cutlim; + const char *s; + unsigned long acc; + char c; + unsigned long cutoff; + int neg, any, cutlim; - /* - * Skip white space and pick up leading +/- sign if any. - * If base is 0, allow 0x for hex and 0 for octal, else - * assume decimal; if base is already 16, allow 0x. - */ - 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; + /* + * Skip white space and pick up leading +/- sign if any. + * If base is 0, allow 0x for hex and 0 for octal, else + * assume decimal; if base is already 16, allow 0x. + */ + 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; + } - /* - * Compute the cutoff value between legal numbers and illegal - * numbers. That is the largest legal value, divided by the - * base. An input number that is greater than this value, if - * followed by a legal input character, is too big. One that - * is equal to this value may be valid or not; the limit - * between valid and invalid numbers is then based on the last - * digit. For instance, if the range for longs is - * [-2147483648..2147483647] and the input base is 10, - * cutoff will be set to 214748364 and cutlim to either - * 7 (neg==0) or 8 (neg==1), meaning that if we have accumulated - * a value > 214748364, or equal but the next digit is > 7 (or 8), - * the number is too big, and we will return a range error. - * - * Set 'any' if any `digits' consumed; make it negative to indicate - * overflow. - */ - cutoff = neg ? (unsigned long)-(LONG_MIN + LONG_MAX) + LONG_MAX - : LONG_MAX; - cutlim = cutoff % base; - cutoff /= 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 = neg ? LONG_MIN : LONG_MAX; - } else if (!any) { - } else if (neg) - acc = -acc; + /* + * Compute the cutoff value between legal numbers and illegal + * numbers. That is the largest legal value, divided by the + * base. An input number that is greater than this value, if + * followed by a legal input character, is too big. One that + * is equal to this value may be valid or not; the limit + * between valid and invalid numbers is then based on the last + * digit. For instance, if the range for longs is + * [-2147483648..2147483647] and the input base is 10, + * cutoff will be set to 214748364 and cutlim to either + * 7 (neg==0) or 8 (neg==1), meaning that if we have accumulated + * a value > 214748364, or equal but the next digit is > 7 (or 8), + * the number is too big, and we will return a range error. + * + * Set 'any' if any `digits' consumed; make it negative to indicate + * overflow. + */ + cutoff = neg ? (unsigned long)-(LONG_MIN + LONG_MAX) + LONG_MAX + : LONG_MAX; + cutlim = cutoff % base; + cutoff /= 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 = neg ? LONG_MIN : LONG_MAX; + } else if(!any) { + } else if(neg) { + acc = -acc; + } noconv: - if (endptr != NULL) - *endptr = (char *)(any ? s - 1 : nptr); - return (acc); + if(endptr != NULL) { + *endptr = (char *)(any ? s - 1 : nptr); + } + return (acc); } |