- const char *s = nptr;
- unsigned long acc;
- int c;
- unsigned long cutoff;
- int neg = 0, any, cutlim;
-
- /*
- * See strtol for comments as to the logic used.
- */
- do {
- c = *s++;
- } while (isspace(c));
- if (c == '-')
- {
- neg = 1;
- c = *s++;
- }
- else if (c == '+')
- c = *s++;
- if ((base == 0 || base == 16) &&
- c == '0' && (*s == 'x' || *s == 'X'))
- {
- c = s[1];
- s += 2;
- base = 16;
- }
- if (base == 0)
- base = c == '0' ? 8 : 10;
- cutoff = (unsigned long)ULONG_MAX / (unsigned long)base;
- cutlim = (unsigned long)ULONG_MAX % (unsigned long)base;
- for (acc = 0, any = 0;; c = *s++)
- {
- if (isdigit(c))
- c -= '0';
- else if (isalpha(c))
- c -= isupper(c) ? 'A' - 10 : '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;
+ BOOL negative = FALSE;
+ __int64 ret = 0;
+
+#ifndef _LIBCNT_
+ TRACE("(%s %p %d %p)\n", debugstr_a(nptr), endptr, base, locale);
+#endif
+
+ if (!MSVCRT_CHECK_PMT(nptr != NULL)) return 0;
+ if (!MSVCRT_CHECK_PMT(base == 0 || base >= 2)) return 0;
+ if (!MSVCRT_CHECK_PMT(base <= 36)) return 0;
+
+ while(isspace(*nptr)) nptr++;
+
+ if(*nptr == '-') {
+ negative = TRUE;
+ nptr++;
+ } else if(*nptr == '+')
+ nptr++;
+
+ if((base==0 || base==16) && *nptr=='0' && tolower(*(nptr+1))=='x') {
+ base = 16;
+ nptr += 2;
+ }
+
+ if(base == 0) {
+ if(*nptr=='0')
+ base = 8;
+ else
+ base = 10;
+ }
+
+ while(*nptr) {
+ char cur = tolower(*nptr);
+ int v;
+
+ if(isdigit(cur)) {
+ if(cur >= '0'+base)
+ break;
+ v = cur-'0';
+ } else {
+ if(cur<'a' || cur>='a'+base-10)
+ break;
+ v = cur-'a'+10;
+ }
+
+ if(negative)
+ v = -v;
+
+ nptr++;
+
+ if(!negative && (ret>_I64_MAX/base || ret*base>_I64_MAX-v)) {
+ ret = _I64_MAX;
+#ifndef _LIBCNT_
+ *_errno() = ERANGE;
+#endif
+ } else if(negative && (ret<_I64_MIN/base || ret*base<_I64_MIN-v)) {
+ ret = _I64_MIN;
+#ifndef _LIBCNT_
+ *_errno() = ERANGE;
+#endif
+ } else
+ ret = ret*base + v;