This is the mail archive of the newlib@sourceware.org mailing list for the newlib project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]
Other format: [Raw text]

Re: [PATCH] gethex doesn't cope with multibyte decimalpoints


Corinna Vinschen wrote:
Hi,

AFAICS, there's a bug in gethex().  The function assumes that the
decimalpoint is a single char.  This is incorrect for multibyte
charsets.  Actually the decimalpoint var should be a multibyte char and
comparisons in the code should always compare the entire string, isn't
it?  I attached a patch.  Note especially the change of the while loop
which now has to step forward instead of backward since backward
stepping screws up multibyte comparisons.


This isn't going to work unfortunately. The decimal point location (decpt) is calculated by adding 1 to the string pointer s which in the multibyte case is wrong. This value is used to figure out the exponent to adjust the result by (see the calculation of e). Changing to reading left to right makes the calculation of the result wrong if the number of hex digits is larger than 8. For example, if you have 10 hex digits, you want the bottom 8 to form one long integer and the top 2 digits by themselves not the other way around.

I believe the right answer is to assume that the decimal point is a single multibyte character. With that, convert the string to wchar first and the decimal point to a wchar, then do all the processing the same after that (looking for the wchar decimal point). A check may be necessary to ensure that no wchar is > 256 before checking in the hexdig table. I believe this would make the algorithm work for either case.
Corinna


* libc/stdlib/gdtoa-gethex.c (gethex): Allow multibyte decimal point. Fix compiler warnings due to different signedness of pointer types.


Index: libc/stdlib/gdtoa-gethex.c
===================================================================
RCS file: /cvs/src/src/newlib/libc/stdlib/gdtoa-gethex.c,v
retrieving revision 1.1
diff -u -p -r1.1 gdtoa-gethex.c
--- libc/stdlib/gdtoa-gethex.c 22 Jun 2006 17:59:52 -0000 1.1
+++ libc/stdlib/gdtoa-gethex.c 6 Feb 2009 13:53:12 -0000
@@ -152,10 +152,12 @@ _DEFUN(gethex, (ptr, sp, fpi, exp, bp, s
__ULong L, lostbits, *x;
Long e, e1;
#ifdef USE_LOCALE
- unsigned char decimalpoint = *localeconv()->decimal_point;
+ unsigned char *decimalpoint = (unsigned char *)
+ localeconv()->decimal_point;
#else
-#define decimalpoint '.'
+#define decimalpoint "."
#endif
+ size_t dplen = strlen ((char *) decimalpoint);
if (!hexdig['0'])
hexdig_init();
@@ -170,7 +172,7 @@ _DEFUN(gethex, (ptr, sp, fpi, exp, bp, s
e = 0;
if (!hexdig[*s]) {
zret = 1;
- if (*s != decimalpoint)
+ if (!strncmp ((char *) s, (char *) decimalpoint, dplen))
goto pcheck;
decpt = ++s;
if (!hexdig[*s])
@@ -184,7 +186,7 @@ _DEFUN(gethex, (ptr, sp, fpi, exp, bp, s
}
while(hexdig[*s])
s++;
- if (*s == decimalpoint && !decpt) {
+ if (!strncmp ((char *) s, (char *) decimalpoint, dplen) && !decpt) {
decpt = ++s;
while(hexdig[*s])
s++;
@@ -225,15 +227,17 @@ _DEFUN(gethex, (ptr, sp, fpi, exp, bp, s
x = b->_x;
n = 0;
L = 0;
- while(s1 > s0) {
- if (*--s1 == decimalpoint)
+ while (s0 < s1) {
+ if (!strncmp ((char *) s0, (char *) decimalpoint, dplen)) {
+ s0 += dplen;
continue;
+ }
if (n == 32) {
*x++ = L;
L = 0;
n = 0;
}
- L |= (hexdig[*s1] & 0x0f) << n;
+ L = (L << 4) | (hexdig[*s0++] & 0x0f);
n += 4;
}
*x++ = L;




Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]