Hi,
I guess that the implementation of strtoull is slightly wrong.
The current function prototype is:
unsigned long
strtoull(const char *nptr, char **endptr, int base)
But (IMHO) it should be:
unsigned long long
strtoull(const char *nptr, char **endptr, int base)
A patch is attached. This patch tries to determine the macro that
defines the maximum value for an unsigned long long and the
corresponding type. It tests for the existance of several macros and
optionally falls back to an unsigned long (you might want to remove this
"feature" - don't know if it's useful). The header file
<internal/file.h> is added to make it compilable without warning. I
changed both strtoull.c files but it seems that neither of them is
compiled/used, therefore I added strtoull.o to the lib/crt/makefile.
The existance of the sources below lib/crtdll/ is very confusing because
these sources arent't compiled at all. What's the cause to keep them in
the repository?
BTW: Where's the definition of strtoll? Is it required? Or was my work
useless at all?
Regards,
Mark
Index: lib/crt/stdlib/strtoull.c
===================================================================
--- lib/crt/stdlib/strtoull.c (revision 14631)
+++ lib/crt/stdlib/strtoull.c (working copy)
@@ -4,21 +4,49 @@
#include <ctype.h>
#include <errno.h>
#include <stdlib.h>
-//#include <msvcrt/unconst.h>
+/* #include <msvcrt/unconst.h> */
+/* required to get prototype for __set_errno() */
+#include <internal/file.h>
+
+#if defined(LONG_LONG_MAX)
+/* GCC-style constant */
+#define ROS_LLONG_MAX LONG_LONG_MAX
+#define ROS_ULLONG_MAX ULONG_LONG_MAX
+typedef long long ros_ll;
+typedef unsigned long long ros_ull;
+#elif defined(_I64_MAX)
+/* MSVC-style constant */
+#define ROS_LLONG_MAX _I64_MAX
+#define ROS_ULLONG_MAX _UI64_MAX
+typedef __int64 ros_ll;
+typedef unsigned __int64 ros_ull;
+#elif defined(LLONG_MAX)
+/* C9x-style constant */
+#define ROS_LLONG_MAX LLONG_MAX
+#define ROS_ULLONG_MAX ULLONG_MAX
+#include <stdint.h>
+typedef int64_t ros_ll;
+typedef uint64_t ros_ull;
+#else
+#define ROS_LLONG_MAX LONG_MAX
+#define ROS_ULLONG_MAX ULONG_MAX
+typedef long ros_ll;
+typedef unsigned long ros_ull;
+#endif
+
/*
* Convert a string to an unsigned long integer.
*
* Ignores `locale' stuff. Assumes that the upper and lower case
* alphabets and digits are each contiguous.
*/
-unsigned long
+ros_ull
strtoull(const char *nptr, char **endptr, int base)
{
const char *s = nptr;
- unsigned long acc;
+ ros_ull acc, cutoff;
int c;
- unsigned long cutoff;
int neg = 0, any, cutlim;
/*
@@ -43,8 +71,8 @@
}
if (base == 0)
base = c == '0' ? 8 : 10;
- cutoff = (unsigned long)ULONG_MAX / base;
- cutlim = (unsigned long)ULONG_MAX % base;
+ cutoff = (ros_ull)ROS_ULLONG_MAX / base;
+ cutlim = (int) ((ros_ull)ROS_ULLONG_MAX % base);
for (acc = 0, any = 0;; c = *s++)
{
if (isdigit(c))
@@ -65,7 +93,7 @@
}
if (any < 0)
{
- acc = ULONG_MAX;
+ acc = ROS_ULLONG_MAX;
__set_errno ( ERANGE );
}
else if (neg)
Index: lib/crt/makefile
===================================================================
--- lib/crt/makefile (revision 14631)
+++ lib/crt/makefile (working copy)
@@ -369,6 +369,7 @@
stdlib/strtod.o \
stdlib/strtol.o \
stdlib/strtoul.o \
+ stdlib/strtoull.o \
stdlib/swab.o \
stdlib/wcstod.o \
stdlib/wcstol.o \
Index: lib/crtdll/stdlib/strtoull.c
===================================================================
--- lib/crtdll/stdlib/strtoull.c (revision 14631)
+++ lib/crtdll/stdlib/strtoull.c (working copy)
@@ -4,21 +4,46 @@
#include <msvcrt/ctype.h>
#include <msvcrt/errno.h>
#include <msvcrt/stdlib.h>
-//#include <msvcrt/unconst.h>
+/* #include <msvcrt/unconst.h> */
+#if defined(LONG_LONG_MAX)
+/* GCC-style constant */
+#define ROS_LLONG_MAX LONG_LONG_MAX
+#define ROS_ULLONG_MAX ULONG_LONG_MAX
+typedef long long ros_ll;
+typedef unsigned long long ros_ull;
+#elif defined(_I64_MAX)
+/* MSVC-style constant */
+#define ROS_LLONG_MAX _I64_MAX
+#define ROS_ULLONG_MAX _UI64_MAX
+typedef __int64 ros_ll;
+typedef unsigned __int64 ros_ull;
+#elif defined(LLONG_MAX)
+/* C9x-style constant */
+#define ROS_LLONG_MAX LLONG_MAX
+#define ROS_ULLONG_MAX ULLONG_MAX
+#include <stdint.h>
+typedef int64_t ros_ll;
+typedef uint64_t ros_ull;
+#else
+#define ROS_LLONG_MAX LONG_MAX
+#define ROS_ULLONG_MAX ULONG_MAX
+typedef long ros_ll;
+typedef unsigned long ros_ull;
+#endif
+
/*
* Convert a string to an unsigned long integer.
*
* Ignores `locale' stuff. Assumes that the upper and lower case
* alphabets and digits are each contiguous.
*/
-unsigned long
+ros_ull
strtoull(const char *nptr, char **endptr, int base)
{
const char *s = nptr;
- unsigned long acc;
+ ros_ull acc, cutoff;
int c;
- unsigned long cutoff;
int neg = 0, any, cutlim;
/*
@@ -43,8 +68,8 @@
}
if (base == 0)
base = c == '0' ? 8 : 10;
- cutoff = (unsigned long)ULONG_MAX / base;
- cutlim = (unsigned long)ULONG_MAX % base;
+ cutoff = (ros_ull)ROS_ULLONG_MAX / base;
+ cutlim = (int) ((ros_ull)ROS_ULLONG_MAX % base);
for (acc = 0, any = 0;; c = *s++)
{
if (isdigit(c))
@@ -65,7 +90,7 @@
}
if (any < 0)
{
- acc = ULONG_MAX;
+ acc = ROS_ULLONG_MAX;
errno = ERANGE;
}
else if (neg)