Commit 7f1063f8 by Russell Davidson Committed by Benjamin Kosnik

istream_extractor_arith.cc: Patch.


2000-06-19  Russell Davidson  <russell@ehess.cnrs-mrs.fr>

	* testsuite/27_io/istream_extractor_arith.cc: Patch.
	* bits/locale_factets.tcc: Tweak.

From-SVN: r34612
parent aec5061b
2000-06-19 Russell Davidson <russell@ehess.cnrs-mrs.fr>
* testsuite/27_io/istream_extractor_arith.cc: Patch.
* bits/locale_factets.tcc: Tweak.
2000-06-19 Raja R Harinath <harinath@cs.umn.edu> 2000-06-19 Raja R Harinath <harinath@cs.umn.edu>
* src/Makefile.am: change @WERROR@ to $(WERROR) so that this can * src/Makefile.am: change @WERROR@ to $(WERROR) so that this can
......
...@@ -905,9 +905,9 @@ AC_DEFUN(GLIBCPP_CHECK_MATH_SUPPORT, [ ...@@ -905,9 +905,9 @@ AC_DEFUN(GLIBCPP_CHECK_MATH_SUPPORT, [
dnl in libstdc++, which we are building right now. dnl in libstdc++, which we are building right now.
dnl Yet, we need to use the c++ compiler so that __cplusplus is defined. dnl Yet, we need to use the c++ compiler so that __cplusplus is defined.
dnl So, use this. dnl So, use this.
ac_test_CFLAGS="${CFLAGS+set}" # ac_test_CFLAGS="${CFLAGS+set}"
ac_save_CFLAGS="$CFLAGS" # ac_save_CFLAGS="$CFLAGS"
CFLAGS='-x c++' # CFLAGS='-x c++'
dnl Check libm dnl Check libm
AC_CHECK_LIB(m, sin, libm="-lm") AC_CHECK_LIB(m, sin, libm="-lm")
...@@ -937,7 +937,7 @@ AC_DEFUN(GLIBCPP_CHECK_MATH_SUPPORT, [ ...@@ -937,7 +937,7 @@ AC_DEFUN(GLIBCPP_CHECK_MATH_SUPPORT, [
_sincosl _finite _finitef _finitel _fqfinite _fpclass _qfpclass) _sincosl _finite _finitef _finitel _fqfinite _fpclass _qfpclass)
LIBS="$save_LIBS" LIBS="$save_LIBS"
CFLAGS="$ac_save_CFLAGS" # CFLAGS="$ac_save_CFLAGS"
]) ])
......
...@@ -913,13 +913,13 @@ dnl ...@@ -913,13 +913,13 @@ dnl
dnl GLIBCPP_CHECK_MATH_SUPPORT dnl GLIBCPP_CHECK_MATH_SUPPORT
AC_DEFUN(GLIBCPP_CHECK_MATH_SUPPORT, [ AC_DEFUN(GLIBCPP_CHECK_MATH_SUPPORT, [
dnl NB: can't use AC_LANG_CPLUSPLUS here, because g++ tries to link dnl NB: Can't use AC_LANG_CPLUSPLUS here, because g++ tries to link
dnl in libstdc++, which we are building right now. dnl in libstdc++, which we are building right now.
dnl Yet, we need to use the c++ compiler so that __cplusplus is defined. dnl Yet, we need to use the c++ compiler so that __cplusplus is defined.
dnl So, use this. dnl So, use this.
ac_test_CFLAGS="${CFLAGS+set}" # ac_test_CFLAGS="${CFLAGS+set}"
ac_save_CFLAGS="$CFLAGS" # ac_save_CFLAGS="$CFLAGS"
CFLAGS='-x c++' # CFLAGS='-x c++'
dnl Check libm dnl Check libm
AC_CHECK_LIB(m, sin, libm="-lm") AC_CHECK_LIB(m, sin, libm="-lm")
...@@ -949,7 +949,7 @@ AC_DEFUN(GLIBCPP_CHECK_MATH_SUPPORT, [ ...@@ -949,7 +949,7 @@ AC_DEFUN(GLIBCPP_CHECK_MATH_SUPPORT, [
_sincosl _finite _finitef _finitel _fqfinite _fpclass _qfpclass) _sincosl _finite _finitef _finitel _fqfinite _fpclass _qfpclass)
LIBS="$save_LIBS" LIBS="$save_LIBS"
CFLAGS="$ac_save_CFLAGS" # CFLAGS="$ac_save_CFLAGS"
]) ])
......
...@@ -38,6 +38,7 @@ ...@@ -38,6 +38,7 @@
#include <bits/std_vector.h> #include <bits/std_vector.h>
#include <bits/std_memory.h> // For auto_ptr #include <bits/std_memory.h> // For auto_ptr
#include <bits/sbuf_iter.h> // For streambuf_iterators #include <bits/sbuf_iter.h> // For streambuf_iterators
#include <bits/std_cctype.h> // For isspace
namespace std namespace std
{ {
...@@ -297,95 +298,146 @@ namespace std ...@@ -297,95 +298,146 @@ namespace std
{ {
typedef _Format_cache<char> __cache_type; typedef _Format_cache<char> __cache_type;
// Prepare for possible failure
__xtrc[0] = '\0';
// Stage 1: determine a conversion specifier. // Stage 1: determine a conversion specifier.
ios_base::fmtflags __basefield = __io.flags() & ios_base::basefield; ios_base::fmtflags __basefield = __io.flags() & ios_base::basefield;
if (__basefield == ios_base::oct) if (__basefield == ios_base::dec)
__base = 10;
else if (__basefield == ios_base::oct)
__base = 8; __base = 8;
else if (__basefield == ios_base::hex) else if (__basefield == ios_base::hex)
__base = 16; __base = 16;
else else
__base = 0;
// As far as I can tell, bases other than 10 are not available for
// floating point types
if (__fp)
__base = 10; __base = 10;
// Stage 2: extract characters. // Stage 2: extract characters.
__cache_type const* __fmt = __cache_type::_S_get(__io); __cache_type const* __fmt = __cache_type::_S_get(__io);
bool __valid = __beg != __end; bool __valid = __beg != __end;
// Fail quickly if !__valid
if (!__valid)
{
__err |= (ios_base::eofbit | ios_base::failbit);
return;
}
// Acceptable formats for numbers here are based on 22.2.3.1
string __grp; string __grp;
int __sep_pos = 0; int __sep_pos = 0;
int __pos = 0; int __pos = 0;
bool __testdec = false;
bool __testEE = false;
bool __testsign = false;
bool __testEEsign = false;
const char* __lits = __fmt->_S_literals; const char* __lits = __fmt->_S_literals;
char __c = *__beg;
while (__valid && __beg != __end) // Check first for sign
bool __testsign = false;
if ((__c == __lits[__cache_type::_S_minus])
|| (__c == __lits[__cache_type::_S_plus]))
{ {
__valid = false; __xtrc[__pos++] = __c;
char __c = *__beg; ++__beg;
const char* __p = strchr(__fmt->_S_literals, __c); __testsign = true;
// whitespace may follow a sign
while ((__beg != __end) && (isspace(*__beg)))
++__beg;
// NB: strchr returns true for __c == 0x0 // There had better be more to come...
if (__p && __c) if (__beg == __end)
{ {
// Check for sign and accept if appropriate. __xtrc[__pos] = '\0';
if ((__p == &__lits[__cache_type::_S_minus]) __err |= (ios_base::eofbit | ios_base::failbit);
|| (__p == &__lits[__cache_type::_S_plus])) return;
}
}
bool __testzero = false; // Has there been a leading zero?
// Now check if first character is a zero
__c = *__beg;
if (__c == __lits[__cache_type::_S_digits])
{ {
if (__testEE) __testzero = true;
++__beg;
// We have to check for __beg == __end here. If so,
// a plain '0' (possibly with a sign) can be got rid of now
if (__beg == __end)
{ {
if (__testEEsign) __xtrc[__pos++] = __c;
break; __xtrc[__pos] = '\0';
__testEEsign = true; __err |= ios_base::eofbit;
return;
} }
else
// Figure out base for integer types only
// Based on Table 55 of 22.2.2.1.2
if (!__fp && __base != 10 && __base != 8)
{ {
if (__testsign) // Here, __base == 0 or 16
break; __c = *__beg;
__testsign = true; if ((__c == __lits[__cache_type::_S_x])
|| (__c == __lits[__cache_type::_S_X]))
{
++__beg;
__base = 16;
__testzero = false; // "0x" is not a leading zero
} }
else
__base = 8;
} }
// Check for exponential part and accept if appropriate.
else if ((__p == &__lits[__cache_type::_S_ee]) // Remove any more leading zeros
|| (__p == &__lits[__cache_type::_S_Ee])) while (__beg != __end)
{ {
if (!__fp || __testEE || !__testsign) if (*__beg == __lits[__cache_type::_S_digits])
break;
__testEE = true;
}
// Check for hexadecimal base parts.
else if ((__p == &__lits[__cache_type::_S_x])
|| (__p == &__lits[__cache_type::_S_X]))
{ {
if (__base != 16 ++__beg;
&& __xtrc[__pos - 1] != __lits[__cache_type::_S_digits]) __testzero = true;
}
else
break; break;
} }
// Check for appropriate digits. If found, too late for a sign }
else if ((__p >= &__lits[__cache_type::_S_digits] else if (__base == 0) // 1st character is not zero
__base = 10;
// We now seek "units", i.e. digits and thousands separators.
// We may need to know if anything is found here. A leading zero
// (removed by now) would count.
bool __testunits = __testzero;
while (__valid && __beg != __end)
{
__valid = false;
__c = *__beg;
const char* __p = strchr(__fmt->_S_literals, __c);
// NB: strchr returns true for __c == 0x0
if (__p && __c)
{
// Try first for acceptable digit; record it if found
if ((__p >= &__lits[__cache_type::_S_digits]
&& __p < &__lits[__cache_type::_S_digits + __base]) && __p < &__lits[__cache_type::_S_digits + __base])
|| (__p >= &__lits[__cache_type::_S_udigits] || (__p >= &__lits[__cache_type::_S_udigits]
&& __p < &__lits[__cache_type::_S_udigits + __base])) && __p < &__lits[__cache_type::_S_udigits + __base]))
{ {
__testsign = true; __xtrc[__pos++] = __c;
if (__testEE)
__testEEsign = true;
}
// Nothing else will do
else break;
__xtrc[__pos] = __c;
++__pos;
++__sep_pos; ++__sep_pos;
__valid = true; __valid = true;
__testunits = true;
}
} }
else if (__c == __fmt->_M_thousands_sep else if (__c == __fmt->_M_thousands_sep
&& __fmt->_M_use_grouping && !__testdec) && __fmt->_M_use_grouping)
{ {
// NB: Thousands separator at the beginning of a string // NB: Thousands separator at the beginning of a string
// is a no-no, as is two consecutive thousands // is a no-no, as is two consecutive thousands
// separators, as is thousands separator to the right of // separators
// a decimal point. if (__sep_pos)
if (__sep_pos && !__testdec)
{ {
__grp += static_cast<char>(__sep_pos); __grp += static_cast<char>(__sep_pos);
__sep_pos = 0; __sep_pos = 0;
...@@ -394,34 +446,15 @@ namespace std ...@@ -394,34 +446,15 @@ namespace std
else else
__err |= ios_base::failbit; __err |= ios_base::failbit;
} }
else if (__c == __fmt->_M_decimal_point
&& __fp && !__testdec)
{
__xtrc[__pos] = '.';
++__pos;
if (__fmt->_M_use_grouping && !__grp.empty())
{
__grp += static_cast<char>(__sep_pos);
__sep_pos = 0;
}
__testdec = true;
__valid = true;
}
if (__valid) if (__valid)
++__beg; ++__beg;
} }
__xtrc[__pos] = '\0';
if (__beg == __end)
__err |= ios_base::eofbit;
// Digit grouping is checked. If _M_groupings() doesn't // Digit grouping is checked. If _M_groupings() doesn't
// match, then get very very upset, and set failbit. // match, then get very very upset, and set failbit.
if (__fmt->_M_use_grouping && !__grp.empty()) if (__fmt->_M_use_grouping && !__grp.empty())
{ {
// Add the ending grouping if the decimal point hasn't // Add the ending grouping
// already delineated the end of the sequence that grouping
// cares about.
if (!__testdec)
__grp += static_cast<char>(__sep_pos); __grp += static_cast<char>(__sep_pos);
// __grp is parsed L to R // __grp is parsed L to R
...@@ -438,7 +471,7 @@ namespace std ...@@ -438,7 +471,7 @@ namespace std
// numpunct::grouping string exactly, starting at the // numpunct::grouping string exactly, starting at the
// right-most point of the parsed sequence of elements ... // right-most point of the parsed sequence of elements ...
while (__test && __i < __n - 1) while (__test && __i < __n - 1)
for (__j = 0; __test && __j < __len && __i < __n - 1; ++__j, ++__i) for (__j = 0; __test && __j < __len && __i < __n - 1; ++__j,++__i)
__test &= __fmt->_M_grouping[__j] == __grp[__n - __i - 1]; __test &= __fmt->_M_grouping[__j] == __grp[__n - __i - 1];
// ... but the last parsed grouping can be <= numpunct // ... but the last parsed grouping can be <= numpunct
// grouping. // grouping.
...@@ -446,8 +479,114 @@ namespace std ...@@ -446,8 +479,114 @@ namespace std
__test &= __fmt->_M_grouping[__j] >= __grp[__n - __i - 1]; __test &= __fmt->_M_grouping[__j] >= __grp[__n - __i - 1];
if (!__test) if (!__test)
{
__err |= ios_base::failbit; __err |= ios_base::failbit;
__xtrc[__pos] = '\0';
if (__beg == __end)
__err |= ios_base::eofbit;
return;
}
}
// If there was nothing but zeros, put one in the output string
if (__testzero && (__pos == 0 || (__pos == 1 && __testsign)))
__xtrc[__pos++] = __lits[__cache_type::_S_digits];
// That's it for integer types. Remaining code is for floating point
if (__fp && __beg != __end)
{
__c = *__beg;
// Check first for decimal point. There MUST be one if
// __testunits is false.
bool __testdec = false; // Is there a decimal point
// with digits following it?
if (__c == __fmt->_M_decimal_point)
{
__xtrc[__pos++] = '.';
++__beg;
// Now we get any digits after the decimal point
// There MUST be some if __testunits is false.
while (__beg != __end)
{
__c = *__beg;
const char* __p = strchr(__fmt->_S_literals, __c);
if ((__p >= &__lits[__cache_type::_S_digits]
&& __p < &__lits[__cache_type::_S_digits + __base])
|| (__p >= &__lits[__cache_type::_S_udigits]
&& __p < &__lits[__cache_type::_S_udigits + __base]))
{
__xtrc[__pos++] = __c;
++__beg;
__testdec = true;
}
else
break;
}
} }
if (!__testunits && !__testdec) // Ill formed
{
__err |= ios_base::failbit;
__xtrc[__pos] = '\0';
if (__beg == __end)
__err |= ios_base::eofbit;
return;
}
// Now we may find an exponent
if (__beg != __end)
{
__c = *__beg;
if ((__c == __lits[__cache_type::_S_ee])
|| (__c == __lits[__cache_type::_S_Ee]))
{
__xtrc[__pos++] = __c;
++__beg;
// Now there may be a sign
if (__beg != __end)
{
__c = *__beg;
if ((__c == __lits[__cache_type::_S_minus])
|| (__c == __lits[__cache_type::_S_plus]))
{
__xtrc[__pos++] = __c;
++__beg;
// whitespace may follow a sign
while ((__beg != __end) && (isspace(*__beg)))
++__beg;
}
}
// And now there must be some digits
if (__beg == __end)
{
__xtrc[__pos] = '\0';
__err |= (ios_base::eofbit | ios_base::failbit);
return;
}
while (__beg != __end)
{
__c = *__beg;
const char* __p = strchr(__fmt->_S_literals, __c);
if ((__p >= &__lits[__cache_type::_S_digits]
&& __p < &__lits[__cache_type::_S_digits + __base])
|| (__p >= &__lits[__cache_type::_S_udigits]
&& __p < &__lits[__cache_type::_S_udigits + __base]))
{
__xtrc[__pos++] = __c;
++__beg;
}
else
break;
}
}
}
// Finally, that's it for floating point
}
// Finish up
__xtrc[__pos] = '\0';
if (__beg == __end)
__err |= ios_base::eofbit;
} }
// NB: This is an unresolved library defect #17 // NB: This is an unresolved library defect #17
...@@ -1473,8 +1612,3 @@ namespace std ...@@ -1473,8 +1612,3 @@ namespace std
// Local Variables: // Local Variables:
// mode:c++ // mode:c++
// End: // End:
...@@ -4757,9 +4757,9 @@ cross_compiling=$ac_cv_prog_cc_cross ...@@ -4757,9 +4757,9 @@ cross_compiling=$ac_cv_prog_cc_cross
ac_test_CFLAGS="${CFLAGS+set}" # ac_test_CFLAGS="${CFLAGS+set}"
ac_save_CFLAGS="$CFLAGS" # ac_save_CFLAGS="$CFLAGS"
CFLAGS='-x c++' # CFLAGS='-x c++'
echo $ac_n "checking for sin in -lm""... $ac_c" 1>&6 echo $ac_n "checking for sin in -lm""... $ac_c" 1>&6
echo "configure:4766: checking for sin in -lm" >&5 echo "configure:4766: checking for sin in -lm" >&5
...@@ -4990,7 +4990,7 @@ done ...@@ -4990,7 +4990,7 @@ done
LIBS="$save_LIBS" LIBS="$save_LIBS"
CFLAGS="$ac_save_CFLAGS" # CFLAGS="$ac_save_CFLAGS"
for ac_hdr in complex.h for ac_hdr in complex.h
......
...@@ -378,6 +378,110 @@ bool test09() ...@@ -378,6 +378,110 @@ bool test09()
return test; return test;
} }
bool test10() {
std::string str_01("0 00 000 +0 + 0 - 0");
std::stringbuf isbuf_01(str_01);
std::istream is_01(&isbuf_01);
bool test = true;
int n = 365;
is_01 >> n;
test &= n == 0;
n = 364;
is_01 >> n;
test &= n == 0;
n = 363;
is_01 >> n;
test &= n == 0;
n = 362;
is_01 >> n;
test &= n == 0;
n = 361;
is_01 >> n;
test &= n == 0;
n = 360;
is_01 >> n;
test &= n == 0;
test &= is_01.rdstate() == std::ios_base::eofbit;
std::string str_02("0x32 0X33 033 33");
std::stringbuf isbuf_02(str_02);
std::istream is_02(&isbuf_02);
is_02.unsetf(std::ios_base::basefield);
is_02 >> n;
test &= n == 50;
is_02 >> n;
test &= n == 51;
is_02 >> n;
test &= n == 27;
is_02 >> n;
test &= n == 33;
test &= is_02.rdstate() == std::ios_base::eofbit;
std::stringbuf isbuf_03(str_02);
std::istream is_03(&isbuf_03);
char c;
int m;
is_03 >> std::dec >> n >> c >> m;
test &= n == 0;
test &= c == 'x';
test &= m == 32;
is_03 >> std::oct >> m >> c >> n;
test &= m == 0;
test &= c == 'X';
test &= n == 27;
is_03 >> std::dec >> m >> n;
test &= m == 33;
test &= n == 33;
test &= is_03.rdstate() == std::ios_base::eofbit;
std::string str_04("3. 4.5E+ 2a5E-3 .6E1");
std::stringbuf isbuf_04(str_04);
std::istream is_04(&isbuf_04);
double f;
is_04 >> f;
test &= f == 3.0;
is_04 >> f;
test &= f == 450.0;
is_04.ignore();
is_04 >> f;
test &= f == 0.005;
is_04 >> f;
test &= f == 6;
test &= is_03.rdstate() == std::ios_base::eofbit;
std::string str_05("0E20 5Ea E16");
std::stringbuf isbuf_05(str_05);
std::istream is_05(&isbuf_05);
is_05 >> f;
test &= f == 0;
is_05 >> f;
test &= f == 0;
test &= is_05.rdstate() == std::ios_base::failbit;
is_05.clear();
is_05 >> c;
test &= c == 'a';
is_05 >> f;
test &= f == 0;
test &= is_05.rdstate() == std::ios_base::failbit;
is_05.clear();
is_05.ignore();
is_05 >> n;
test &= n == 16;
#ifdef DEBUG_ASSERT
assert(test);
#endif
return test;
}
int main() int main()
{ {
test01(); test01();
...@@ -388,6 +492,7 @@ int main() ...@@ -388,6 +492,7 @@ int main()
test07(); test07();
test08(); test08();
test09(); test09();
test10();
return 0; return 0;
} }
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment