* vfscanf.c (BUF): Change definition to take multibyte decimal point

into account.
	(__SVFSCANF_R): Handle radix char language-dependent
	per POSIX.
	(__SVFWSCANF_R): Ditto.
This commit is contained in:
Corinna Vinschen 2013-12-18 19:23:33 +00:00
parent 5730605d55
commit 576b7804d6
3 changed files with 94 additions and 21 deletions

View File

@ -1,3 +1,11 @@
2013-12-18 Corinna Vinschen <vinschen@redhat.com>
* vfscanf.c (BUF): Change definition to take multibyte decimal point
into account.
(__SVFSCANF_R): Handle radix char language-dependent
per POSIX.
(__SVFWSCANF_R): Ditto.
2013-12-10 Jeff Johnston <jjohnstn@redhat.com>
* acconfig.h: Add _HAVE_CC_INHIBIT_LOOP_TO_LIBCALL.

View File

@ -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((char *s, char **sptr));
#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:

View File

@ -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, ap),
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, ap),
# 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, ap),
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, ap),
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);