aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorBenjamin Kosnik <bkoz@gcc.gnu.org>2001-12-05 22:07:36 +0000
committerBenjamin Kosnik <bkoz@gcc.gnu.org>2001-12-05 22:07:36 +0000
commit0228de0c4f91cb2cc0381f2f2c403caab6e7d82e (patch)
tree434f9b1969290c6575921690cf5ef445f97d33ae
parent0df47f6610ae1ad8b7b3372da8bff6e59230b901 (diff)
downloadgcc-0228de0c4f91cb2cc0381f2f2c403caab6e7d82e.zip
gcc-0228de0c4f91cb2cc0381f2f2c403caab6e7d82e.tar.gz
gcc-0228de0c4f91cb2cc0381f2f2c403caab6e7d82e.tar.bz2
[multiple changes]
2001-12-05 Benjamin Kosnik <bkoz@redhat.com> DR/282 * include/bits/locale_facets.tcc (num_put::_M_widen_float): Add grouping to floating point types. * testsuite/27_io/ostream_inserter_arith.cc (test02): Add test. 2001-12-04 Paolo Carlini <pcarlini@unitus.it> libstdc++/4402 * testsuite/27_io/ostream_inserter_arith.cc (test02): add testcase from the PR. * include/bits/locale_facets.tcc (num_put::_M_convert_float): Deal properly with long ios_base::fixed floats. (num_put::_M_widen_float): use __len in __builtin_alloca call. From-SVN: r47696
-rw-r--r--libstdc++-v3/ChangeLog17
-rw-r--r--libstdc++-v3/include/bits/locale_facets.tcc66
-rw-r--r--libstdc++-v3/testsuite/27_io/ostream_inserter_arith.cc23
3 files changed, 96 insertions, 10 deletions
diff --git a/libstdc++-v3/ChangeLog b/libstdc++-v3/ChangeLog
index 84f842f..08d0eb8 100644
--- a/libstdc++-v3/ChangeLog
+++ b/libstdc++-v3/ChangeLog
@@ -1,3 +1,20 @@
+2001-12-05 Benjamin Kosnik <bkoz@redhat.com>
+
+ DR/282
+ * include/bits/locale_facets.tcc (num_put::_M_widen_float): Add
+ grouping to floating point types.
+ * testsuite/27_io/ostream_inserter_arith.cc (test02): Add test.
+
+2001-12-04 Paolo Carlini <pcarlini@unitus.it>
+
+ libstdc++/4402
+ * testsuite/27_io/ostream_inserter_arith.cc (test02): add testcase
+ from the PR.
+ * include/bits/locale_facets.tcc (num_put::_M_convert_float):
+ Deal properly with long ios_base::fixed floats.
+ (num_put::_M_widen_float): use
+ __len in __builtin_alloca call.
+
2001-12-04 Benjamin Kosnik <bkoz@redhat.com>
* src/Makefile.am (sources): Add ext-inst.cc.
diff --git a/libstdc++-v3/include/bits/locale_facets.tcc b/libstdc++-v3/include/bits/locale_facets.tcc
index 835a0ae..95cbee5 100644
--- a/libstdc++-v3/include/bits/locale_facets.tcc
+++ b/libstdc++-v3/include/bits/locale_facets.tcc
@@ -711,15 +711,23 @@ namespace std
_M_convert_float(_OutIter __s, ios_base& __io, _CharT __fill, char __mod,
_ValueT __v) const
{
- const streamsize __max_prec = numeric_limits<_ValueT>::digits10;
+ const int __max_digits = numeric_limits<_ValueT>::digits10;
streamsize __prec = __io.precision();
// Protect against sprintf() buffer overflows.
- if (__prec > __max_prec)
- __prec = __max_prec;
+ if (__prec > static_cast<streamsize>(__max_digits))
+ __prec = static_cast<streamsize>(__max_digits);
// Long enough for the max format spec.
char __fbuf[16];
- char __cs[64];
+
+ // Consider the possibility of long ios_base::fixed outputs
+ const bool __fixed = __io.flags() & ios_base::fixed;
+ const int __max_exp = numeric_limits<_ValueT>::max_exponent10;
+ // XXX Why + 4? Why * 4? What's going on? Who's on first?
+ const int __cs_size = __fixed ? __max_exp + __max_digits + 4
+ : __max_digits * 4;
+ char* __cs = static_cast<char*>(__builtin_alloca(__cs_size));
+
int __len;
// [22.2.2.2.2] Stage 1, numeric conversion to character.
if (_S_format_float(__io, __fbuf, __mod, __prec))
@@ -757,14 +765,47 @@ namespace std
// numpunct.decimal_point() values for '.' and adding grouping.
const locale __loc = __io.getloc();
const ctype<_CharT>& __ctype = use_facet<ctype<_CharT> >(__loc);
- _CharT* __ws = static_cast<_CharT*>(__builtin_alloca(sizeof(_CharT) * 64));
+ _CharT* __ws = static_cast<_CharT*>(__builtin_alloca(sizeof(_CharT)
+ * __len));
+ // Grouping can add (almost) as many separators as the number of
+ // digits, but no more.
+ _CharT* __ws2 = static_cast<_CharT*>(__builtin_alloca(sizeof(_CharT)
+ * __len * 2));
__ctype.widen(__cs, __cs + __len, __ws);
- const numpunct<_CharT>& __np = use_facet<numpunct<_CharT> >(__loc);
// Replace decimal point.
const _CharT* __p;
+ const numpunct<_CharT>& __np = use_facet<numpunct<_CharT> >(__loc);
if (__p = char_traits<_CharT>::find(__ws, __len, __ctype.widen('.')))
__ws[__p - __ws] = __np.decimal_point();
+
+#ifdef _GLIBCPP_RESOLVE_LIB_DEFECTS
+//282. What types does numpunct grouping refer to?
+ // Add grouping, if necessary.
+ const string __grouping = __np.grouping();
+ ios_base::fmtflags __basefield = __io.flags() & ios_base::basefield;
+ if (__grouping.size())
+ {
+ _CharT* __p2;
+ int __declen = __p ? __p - __ws : __len;
+ __p2 = __add_grouping(__ws2, __np.thousands_sep(),
+ __grouping.c_str(),
+ __grouping.c_str() + __grouping.size(),
+ __ws, __ws + __declen);
+ int __newlen = __p2 - __ws2;
+
+ // Tack on decimal part.
+ if (__p)
+ {
+ char_traits<_CharT>::copy(__p2, __p, __len - __declen);
+ __newlen += __len - __declen;
+ }
+
+ // Switch strings, establish correct new length.
+ __ws = __ws2;
+ __len = __newlen;
+ }
+#endif
return _M_insert(__s, __io, __fill, __ws, __len);
}
@@ -778,13 +819,17 @@ namespace std
// numpunct.decimal_point() values for '.' and adding grouping.
const locale __loc = __io.getloc();
const ctype<_CharT>& __ctype = use_facet<ctype<_CharT> >(__loc);
- _CharT* __ws = static_cast<_CharT*>(__builtin_alloca(sizeof(_CharT) * 64));
- _CharT* __ws2 = static_cast<_CharT*>(__builtin_alloca(sizeof(_CharT) * 64));
+ _CharT* __ws = static_cast<_CharT*>(__builtin_alloca(sizeof(_CharT)
+ * __len));
+ // Grouping can add (almost) as many separators as the number of
+ // digits, but no more.
+ _CharT* __ws2 = static_cast<_CharT*>(__builtin_alloca(sizeof(_CharT)
+ * __len * 2));
__ctype.widen(__cs, __cs + __len, __ws);
// Add grouping, if necessary.
const numpunct<_CharT>& __np = use_facet<numpunct<_CharT> >(__loc);
- string __grouping = __np.grouping();
+ const string __grouping = __np.grouping();
ios_base::fmtflags __basefield = __io.flags() & ios_base::basefield;
bool __dec = __basefield != ios_base::oct
&& __basefield != ios_base::hex;
@@ -810,8 +855,9 @@ namespace std
int __len) const
{
// [22.2.2.2.2] Stage 3.
- _CharT* __ws2 = static_cast<_CharT*>(__builtin_alloca(sizeof(_CharT) * 64));
streamsize __w = __io.width();
+ _CharT* __ws2 = static_cast<_CharT*>(__builtin_alloca(sizeof(_CharT)
+ * __w));
if (__w > static_cast<streamsize>(__len))
{
__pad(__io, __fill, __ws2, __ws, __w, __len, true);
diff --git a/libstdc++-v3/testsuite/27_io/ostream_inserter_arith.cc b/libstdc++-v3/testsuite/27_io/ostream_inserter_arith.cc
index 2e57922..580730b 100644
--- a/libstdc++-v3/testsuite/27_io/ostream_inserter_arith.cc
+++ b/libstdc++-v3/testsuite/27_io/ostream_inserter_arith.cc
@@ -272,6 +272,29 @@ test02()
#endif
VERIFY(os && os.str() == largebuf);
+ // Make sure we can output a long float in fixed format
+ // without seg-faulting (libstdc++/4402)
+ double val2 = 3.5e230;
+
+ ostringstream os2;
+ os2.precision(3);
+ os2.setf(ios::fixed);
+ os2 << val2;
+
+ sprintf(largebuf, "%.*f", 3, val2);
+#ifdef TEST_NUMPUT_VERBOSE
+ cout << "expect: " << largebuf << endl;
+ cout << "result: " << os2.str() << endl;
+#endif
+ VERIFY(os2 && os2.str() == largebuf);
+
+ // Check it can be done in a locale with grouping on.
+ locale loc2("de_DE");
+ os2.imbue(loc2);
+ os2 << fixed << setprecision(3) << val2 << endl;
+ os2 << endl;
+ os2 << fixed << setprecision(1) << val2 << endl;
+
return 0;
}