[patch] *scanf: Allow language-dependent radix character
Corinna Vinschen
vinschen@redhat.com
Wed Dec 18 14:54:00 GMT 2013
On Dec 17 18:24, Jeff Johnston wrote:
> In addition to any else's comments, one issue I would note is that the value of
> BUF, which is used as the size of buf for floating point, assumes a single character decimal point.
> I believe that should be incremented by MB_LEN_MAX in the MB case to compensate for the decimal point.
Oh, hum. The current definition for BUF in the FLOATING_POINT case is:
#if ((MAXEXP+MAXFRACT+3) > MB_LEN_MAX)
# define BUF (MAXEXP+MAXFRACT+3) /* 3 = sign + decimal point + NUL */
#else
# define BUF MB_LEN_MAX
#endif
Keeping everything else as is and just handling the decimal point with
MB_LEN_MAX, I'd get:
#if ((MAXEXP+MAXFRACT+MB_LEN_MAX+2) > MB_LEN_MAX /* Always true */
# define BUF (MAXEXP+MAXFRACT+MB_LEN_MAX+2)
#else
...
So I guess I can reduce that to just
#define BUF (MAXEXP+MAXFRACT+MB_LEN_MAX+2) /* decimal point + sign + NUL */
In the non-MB case, MB_LEN_MAX is 1 anyway so it's equivalent to the old
definition.
> A minor issue is that _ungetc_r can possibly fail and there is no check.
None of the other ungetc calls check for errors. The problem is, what
do you do *if* ungetc errors? It's an undefined case, so you probably
can only hope for the best.
Revised patch attached.
Thanks,
Corinna
* vfscanf.c (BUF): Change definition to take multibyte decimal point
into account.
(__SVFSCANF_R): Handle radix char language-dependent
per POSIX.
(__SVFWSCANF_R): Ditto.
Index: libc/stdio/vfscanf.c
===================================================================
RCS file: /cvs/src/src/newlib/libc/stdio/vfscanf.c,v
retrieving revision 1.54
diff -u -p -r1.54 vfscanf.c
--- libc/stdio/vfscanf.c 29 Apr 2013 21:06:23 -0000 1.54
+++ libc/stdio/vfscanf.c 18 Dec 2013 09:43:17 -0000
@@ -162,6 +162,7 @@ Supporting OS subroutines required:
#ifdef FLOATING_POINT
#include <math.h>
#include <float.h>
+#include <locale.h>
/* Currently a test is made to see if long double processing is warranted.
This could be changed in the future should the _ldtoa_r code be
@@ -174,11 +175,7 @@ extern _LONG_DOUBLE _strtold _PARAMS((ch
#include "floatio.h"
-#if ((MAXEXP+MAXFRACT+3) > MB_LEN_MAX)
-# define BUF (MAXEXP+MAXFRACT+3) /* 3 = sign + decimal point + NUL */
-#else
-# define BUF MB_LEN_MAX
-#endif
+#define BUF (MAXEXP+MAXFRACT+MB_LEN_MAX+2) /* decimal point + sign + NUL */
/* An upper bound for how long a long prints in decimal. 4 / 13 approximates
log (2). Add one char for roundoff compensation and one for the sign. */
@@ -1288,6 +1285,10 @@ _DEFUN(__SVFSCANF_R, (rptr, fp, fmt0, ap
unsigned width_left = 0;
char nancount = 0;
char infcount = 0;
+ const char *decpt = _localeconv_r (rptr)->decimal_point;
+#ifdef _MB_CAPABLE
+ int decptpos = 0;
+#endif
#ifdef hardway
if (width == 0 || width > sizeof (buf) - 1)
#else
@@ -1416,14 +1417,6 @@ _DEFUN(__SVFSCANF_R, (rptr, fp, fmt0, ap
goto fok;
}
break;
- case '.':
- if (flags & DPTOK)
- {
- flags &= ~(SIGNOK | DPTOK);
- leading_zeroes = zeroes;
- goto fok;
- }
- break;
case 'e':
case 'E':
/* no exponent without some digits */
@@ -1442,6 +1435,53 @@ _DEFUN(__SVFSCANF_R, (rptr, fp, fmt0, ap
goto fok;
}
break;
+ default:
+#ifndef _MB_CAPABLE
+ if ((unsigned char) c == (unsigned char) decpt[0]
+ && (flags & DPTOK))
+ {
+ flags &= ~(SIGNOK | DPTOK);
+ leading_zeroes = zeroes;
+ goto fok;
+ }
+ break;
+#else
+ if (flags & DPTOK)
+ {
+ while ((unsigned char) c
+ == (unsigned char) decpt[decptpos])
+ {
+ if (decpt[++decptpos] == '\0')
+ {
+ /* We read the complete decpt seq. */
+ flags &= ~(SIGNOK | DPTOK);
+ leading_zeroes = zeroes;
+ p = stpncpy (p, decpt, decptpos);
+ decptpos = 0;
+ goto fskip;
+ }
+ ++nread;
+ if (--fp->_r > 0)
+ fp->_p++;
+ else if (__srefill_r (rptr, fp))
+ break; /* EOF */
+ c = *fp->_p;
+ }
+ if (decptpos > 0)
+ {
+ /* We read part of a multibyte decimal point,
+ but the rest is invalid or we're at EOF,
+ so back off. */
+ while (decptpos-- > 0)
+ {
+ _ungetc_r (rptr, (unsigned char) decpt[decptpos],
+ fp);
+ --nread;
+ }
+ }
+ }
+ break;
+#endif
}
break;
fok:
Index: libc/stdio/vfwscanf.c
===================================================================
RCS file: /cvs/src/src/newlib/libc/stdio/vfwscanf.c,v
retrieving revision 1.5
diff -u -p -r1.5 vfwscanf.c
--- libc/stdio/vfwscanf.c 26 Nov 2013 17:21:00 -0000 1.5
+++ libc/stdio/vfwscanf.c 18 Dec 2013 09:43:17 -0000
@@ -161,6 +161,9 @@ C99, POSIX-1.2008
#ifdef FLOATING_POINT
#include <math.h>
#include <float.h>
+#ifdef __HAVE_LOCALE_INFO_EXTENDED__
+#include "../locale/lnumeric.h"
+#endif
/* Currently a test is made to see if long double processing is warranted.
This could be changed in the future should the _ldtoa_r code be
@@ -414,6 +417,7 @@ _DEFUN(__SVFWSCANF_R, (rptr, fp, fmt0, a
float *flp;
_LONG_DOUBLE *ldp;
double *dp;
+ wchar_t decpt;
#endif
long *lp;
#ifndef _NO_LONGLONG
@@ -440,6 +444,27 @@ _DEFUN(__SVFWSCANF_R, (rptr, fp, fmt0, a
# define GET_ARG(n, ap, type) (va_arg (ap, type))
#endif
+#ifdef FLOATING_POINT
+#ifdef _MB_CAPABLE
+#ifdef __HAVE_LOCALE_INFO_EXTENDED__
+ decpt = *__get_current_numeric_locale ()->wdecimal_point;
+#else
+ {
+ size_t nconv;
+
+ memset (&state, '\0', sizeof (state));
+ nconv = _mbrtowc_r (data, &decpt,
+ _localeconv_r (data)->decimal_point,
+ MB_CUR_MAX, &state);
+ if (nconv == (size_t) -1 || nconv == (size_t) -2)
+ decpt = L'.';
+ }
+#endif /* !__HAVE_LOCALE_INFO_EXTENDED__ */
+#else
+ decpt = (wchar_t) *_localeconv_r (data)->decimal_point;
+#endif /* !_MB_CAPABLE */
+#endif /* FLOATING_POINT */
+
_newlib_flockfile_start (fp);
ORIENT (fp, 1);
@@ -1271,14 +1296,6 @@ _DEFUN(__SVFWSCANF_R, (rptr, fp, fmt0, a
goto fok;
}
break;
- case L'.':
- if (flags & DPTOK)
- {
- flags &= ~(SIGNOK | DPTOK);
- leading_zeroes = zeroes;
- goto fok;
- }
- break;
case L'e':
case L'E':
/* no exponent without some digits */
@@ -1297,6 +1314,14 @@ _DEFUN(__SVFWSCANF_R, (rptr, fp, fmt0, a
goto fok;
}
break;
+ default:
+ if ((wchar_t) c == decpt && (flags & DPTOK))
+ {
+ flags &= ~(SIGNOK | DPTOK);
+ leading_zeroes = zeroes;
+ goto fok;
+ }
+ break;
}
if (c != WEOF)
_ungetwc_r (rptr, c, fp);
--
Corinna Vinschen
Cygwin Maintainer
Red Hat
-------------- next part --------------
A non-text attachment was scrubbed...
Name: not available
Type: application/pgp-signature
Size: 836 bytes
Desc: not available
URL: <http://sourceware.org/pipermail/newlib/attachments/20131218/bf1c0162/attachment.sig>
More information about the Newlib
mailing list