:pserver:cvsanon@mok.lvcm.com:/CVS/ReactOS reactos
[reactos.git] / lib / crtdll / stdlib / strtoll.c
1 /* Copyright (C) 1996 DJ Delorie, see COPYING.DJ for details */
2 /* Copyright (C) 1994 DJ Delorie, see COPYING.DJ for details */
3 #include <limits.h>
4 #include <crtdll/ctype.h>
5 #include <crtdll/errno.h>
6 #include <crtdll/stdlib.h>
7 //#include <crtdll/unconst.h>
8
9 /* constants used in Solaris */
10 #define LLONG_MIN       -9223372036854775807L-1L
11 #define LLONG_MAX       9223372036854775807L
12 #define ULLONG_MAX      18446744073709551615UL
13
14 long
15 strtoll(const char *nptr, char **endptr, int base)
16 {
17   const char *s = nptr;
18   unsigned long acc;
19   int c;
20   unsigned long cutoff;
21   int neg = 0, any, cutlim;
22
23   /*
24    * See strtol for comments as to the logic used.
25    */
26   do {
27     c = *s++;
28   } while (isspace(c));
29   if (c == '-')
30   {
31     neg = 1;
32     c = *s++;
33   }
34   else if (c == '+')
35     c = *s++;
36   if ((base == 0 || base == 16) &&
37       c == '0' && (*s == 'x' || *s == 'X'))
38   {
39     c = s[1];
40     s += 2;
41     base = 16;
42   }
43   if (base == 0)
44     base = c == '0' ? 8 : 10;
45
46 /* to prevent overflow, we take max-1 and add 1 after division */
47   cutoff = neg ? -(LLONG_MIN+1) : LLONG_MAX-1;
48   cutlim = cutoff % base;
49   cutoff /= base;
50   if (++cutlim == base)
51   {
52     cutlim = 0;
53     cutoff++;
54   }
55   for (acc = 0, any = 0;; c = *s++)
56   {
57     if (isdigit(c))
58       c -= '0';
59     else if (isalpha(c))
60       c -= isupper(c) ? 'A' - 10 : 'a' - 10;
61     else
62       break;
63     if (c >= base)
64       break;
65     if (any < 0 || acc > cutoff || (acc == cutoff && c > cutlim))
66       any = -1;
67     else
68     {
69       any = 1;
70       acc *= base;
71       acc += c;
72     }
73   }
74   if (any < 0)
75   {
76     acc = neg ? LLONG_MIN : LLONG_MAX;
77     errno = ERANGE;
78   }
79   else if (neg)
80     acc *= -1;
81   if (endptr != 0)
82     *endptr = any ? (char *)s - 1 : (char *)nptr;
83   return acc;
84 }