From 0d630c9ee349a87b92c1fe7c1974ae1ef16708d4 Mon Sep 17 00:00:00 2001 From: Eric Kohl Date: Sat, 27 Nov 1999 11:32:43 +0000 Subject: [PATCH] added atoi() and atol() svn path=/trunk/; revision=802 --- reactos/ntoskrnl/rtl/stdlib.c | 74 +++++++++++++++++++++++++++++++++-- 1 file changed, 71 insertions(+), 3 deletions(-) diff --git a/reactos/ntoskrnl/rtl/stdlib.c b/reactos/ntoskrnl/rtl/stdlib.c index 699045f92b9..95c7e838c9f 100644 --- a/reactos/ntoskrnl/rtl/stdlib.c +++ b/reactos/ntoskrnl/rtl/stdlib.c @@ -11,6 +11,7 @@ /* INCLUDES *****************************************************************/ #include +#include #include /* GLOBALS ****************************************************************/ @@ -19,17 +20,84 @@ static unsigned long long next = 0; /* FUNCTIONS ****************************************************************/ -#if 0 int atoi(const char *str) { return (int)atol (str); } + +/* + * NOTE: no error + */ + long atol(const char *str) { - return strtol(str, 0, 10); + const char *s = str; + unsigned long acc; + int c; + unsigned long cutoff; + int neg = 0, any, cutlim; + + /* + * Skip white space and pick up leading +/- sign if any. + */ + do { + c = *s++; + } while (isspace(c)); + if (c == '-') + { + neg = 1; + c = *s++; + } + else if (c == '+') + c = *s++; + + /* + * 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; + cutlim = cutoff % (unsigned long)10; + cutoff /= (unsigned long)10; + for (acc = 0, any = 0;; c = *s++) + { + if (isdigit(c)) + c -= '0'; + else + break; + if (c >= 10) + break; + if (any < 0 || acc > cutoff || (acc == cutoff && c > cutlim)) + any = -1; + else + { + any = 1; + acc *= 10; + acc += c; + } + } + if (any < 0) + { + acc = neg ? LONG_MIN : LONG_MAX; + } + else if (neg) + acc = -acc; + + return acc; } -#endif /*