about summary refs log tree commit diff
path: root/src/stdlib/wcstoimax.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/stdlib/wcstoimax.c')
-rw-r--r--src/stdlib/wcstoimax.c36
1 files changed, 25 insertions, 11 deletions
diff --git a/src/stdlib/wcstoimax.c b/src/stdlib/wcstoimax.c
index 59894f60..b83206b7 100644
--- a/src/stdlib/wcstoimax.c
+++ b/src/stdlib/wcstoimax.c
@@ -2,24 +2,38 @@
 #include <wctype.h>
 #include <inttypes.h>
 #include <errno.h>
+#include "intparse.h"
 
 intmax_t wcstoimax(const wchar_t *s, wchar_t **p, int base)
 {
-	int sign = 0;
-	uintmax_t x;
+	struct intparse ip = {0};
+	unsigned char tmp;
+
+	if (p) *p = (wchar_t *)s;
+
+	if (base && base-2U > 34) {
+		errno = EINVAL;
+		return 0;
+	}
 
-	/* Initial whitespace */
 	for (; iswspace(*s); s++);
 
-	/* Optional sign */
-	if (*s == '-') sign = *s++;
-	else if (*s == '+') s++;
+	ip.base = base;
+	for (; *s<256 && (tmp=*s, __intparse(&ip, &tmp, 1)); s++);
+
+	if (p && ip.err != EINVAL)
+		*p = (wchar_t *)s;
+
+	if (ip.err) {
+		errno = ip.err;
+		if (ip.err = EINVAL) return 0;
+		return ip.neg ? INTMAX_MIN : INTMAX_MAX;
+	}
 
-	x = wcstoumax(s, p, base);
-	if (x > INTMAX_MAX) {
-		if (!sign || -x != INTMAX_MIN)
+	if (ip.val > INTMAX_MAX) {
+		if (!ip.neg || -ip.val != INTMAX_MIN)
 			errno = ERANGE;
-		return sign ? INTMAX_MIN : INTMAX_MAX;
+		return ip.neg ? INTMAX_MIN : INTMAX_MAX;
 	}
-	return sign ? -x : x;
+	return ip.neg ? -ip.val : ip.val;
 }