1*03a78d15Sespie // 2001-09-09 Benjamin Kosnik  <bkoz@redhat.com>
2*03a78d15Sespie 
3*03a78d15Sespie // Copyright (C) 2001, 2002 Free Software Foundation
4*03a78d15Sespie //
5*03a78d15Sespie // This file is part of the GNU ISO C++ Library.  This library is free
6*03a78d15Sespie // software; you can redistribute it and/or modify it under the
7*03a78d15Sespie // terms of the GNU General Public License as published by the
8*03a78d15Sespie // Free Software Foundation; either version 2, or (at your option)
9*03a78d15Sespie // any later version.
10*03a78d15Sespie 
11*03a78d15Sespie // This library is distributed in the hope that it will be useful,
12*03a78d15Sespie // but WITHOUT ANY WARRANTY; without even the implied warranty of
13*03a78d15Sespie // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14*03a78d15Sespie // GNU General Public License for more details.
15*03a78d15Sespie 
16*03a78d15Sespie // You should have received a copy of the GNU General Public License along
17*03a78d15Sespie // with this library; see the file COPYING.  If not, write to the Free
18*03a78d15Sespie // Software Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307,
19*03a78d15Sespie // USA.
20*03a78d15Sespie 
21*03a78d15Sespie // 22.2.6.2.1 money_put members
22*03a78d15Sespie 
23*03a78d15Sespie #include <locale>
24*03a78d15Sespie #include <sstream>
25*03a78d15Sespie #include <testsuite_hooks.h>
26*03a78d15Sespie 
27*03a78d15Sespie // XXX This test is not working for non-glibc locale models.
28*03a78d15Sespie // { dg-do run { xfail *-*-* } }
29*03a78d15Sespie 
30*03a78d15Sespie #ifdef _GLIBCPP_USE_WCHAR_T
31*03a78d15Sespie // test string version
test01()32*03a78d15Sespie void test01()
33*03a78d15Sespie {
34*03a78d15Sespie   using namespace std;
35*03a78d15Sespie   typedef money_base::part part;
36*03a78d15Sespie   typedef money_base::pattern pattern;
37*03a78d15Sespie   typedef ostreambuf_iterator<wchar_t> iterator_type;
38*03a78d15Sespie 
39*03a78d15Sespie   bool test = true;
40*03a78d15Sespie 
41*03a78d15Sespie   // basic construction
42*03a78d15Sespie   locale loc_c = locale::classic();
43*03a78d15Sespie   locale loc_hk("en_HK");
44*03a78d15Sespie   locale loc_fr("fr_FR@euro");
45*03a78d15Sespie   locale loc_de("de_DE@euro");
46*03a78d15Sespie   VERIFY( loc_c != loc_de );
47*03a78d15Sespie   VERIFY( loc_hk != loc_fr );
48*03a78d15Sespie   VERIFY( loc_hk != loc_de );
49*03a78d15Sespie   VERIFY( loc_de != loc_fr );
50*03a78d15Sespie 
51*03a78d15Sespie   // cache the moneypunct facets
52*03a78d15Sespie   typedef moneypunct<wchar_t, true> __money_true;
53*03a78d15Sespie   typedef moneypunct<wchar_t, false> __money_false;
54*03a78d15Sespie   const __money_true& monpunct_c_t = use_facet<__money_true>(loc_c);
55*03a78d15Sespie   const __money_true& monpunct_de_t = use_facet<__money_true>(loc_de);
56*03a78d15Sespie   const __money_false& monpunct_c_f = use_facet<__money_false>(loc_c);
57*03a78d15Sespie   const __money_false& monpunct_de_f = use_facet<__money_false>(loc_de);
58*03a78d15Sespie   const __money_true& monpunct_hk_t = use_facet<__money_true>(loc_hk);
59*03a78d15Sespie   const __money_false& monpunct_hk_f = use_facet<__money_false>(loc_hk);
60*03a78d15Sespie 
61*03a78d15Sespie   // sanity check the data is correct.
62*03a78d15Sespie   const wstring empty;
63*03a78d15Sespie 
64*03a78d15Sespie   // total EPA budget FY 2002
65*03a78d15Sespie   const wstring digits1(L"720000000000");
66*03a78d15Sespie 
67*03a78d15Sespie   // est. cost, national missile "defense", expressed as a loss in USD 2001
68*03a78d15Sespie   const wstring digits2(L"-10000000000000");
69*03a78d15Sespie 
70*03a78d15Sespie   // not valid input
71*03a78d15Sespie   const wstring digits3(L"-A");
72*03a78d15Sespie 
73*03a78d15Sespie   // input less than frac_digits
74*03a78d15Sespie   const wstring digits4(L"-1");
75*03a78d15Sespie 
76*03a78d15Sespie   wostringstream oss;
77*03a78d15Sespie   oss.imbue(loc_de);
78*03a78d15Sespie   // cache the money_put facet
79*03a78d15Sespie   const money_put<wchar_t>& mon_put = use_facet<money_put<wchar_t> >(oss.getloc());
80*03a78d15Sespie 
81*03a78d15Sespie 
82*03a78d15Sespie   iterator_type os_it01 = mon_put.put(oss.rdbuf(), true, oss, ' ', digits1);
83*03a78d15Sespie   wstring result1 = oss.str();
84*03a78d15Sespie   VERIFY( result1 == L"7.200.000.000,00 ");
85*03a78d15Sespie 
86*03a78d15Sespie   oss.str(empty);
87*03a78d15Sespie   iterator_type os_it02 = mon_put.put(oss.rdbuf(), false, oss, ' ', digits1);
88*03a78d15Sespie   wstring result2 = oss.str();
89*03a78d15Sespie   VERIFY( result2 == L"7.200.000.000,00 ");
90*03a78d15Sespie 
91*03a78d15Sespie   // intl and non-intl versions should be the same.
92*03a78d15Sespie   VERIFY( result1 == result2 );
93*03a78d15Sespie 
94*03a78d15Sespie   // now try with showbase, to get currency symbol in format
95*03a78d15Sespie   oss.setf(ios_base::showbase);
96*03a78d15Sespie 
97*03a78d15Sespie   oss.str(empty);
98*03a78d15Sespie   iterator_type os_it03 = mon_put.put(oss.rdbuf(), true, oss, ' ', digits1);
99*03a78d15Sespie   wstring result3 = oss.str();
100*03a78d15Sespie   VERIFY( result3 == L"7.200.000.000,00 EUR ");
101*03a78d15Sespie 
102*03a78d15Sespie   oss.str(empty);
103*03a78d15Sespie   iterator_type os_it04 = mon_put.put(oss.rdbuf(), false, oss, ' ', digits1);
104*03a78d15Sespie   wstring result4 = oss.str();
105*03a78d15Sespie   VERIFY( result4 == L"7.200.000.000,00 \x20ac");
106*03a78d15Sespie 
107*03a78d15Sespie   // intl and non-intl versions should be different.
108*03a78d15Sespie   VERIFY( result3 != result4 );
109*03a78d15Sespie   VERIFY( result3 != result1 );
110*03a78d15Sespie   VERIFY( result4 != result2 );
111*03a78d15Sespie 
112*03a78d15Sespie   // test sign of more than one digit, say hong kong.
113*03a78d15Sespie   oss.imbue(loc_hk);
114*03a78d15Sespie   oss.str(empty);
115*03a78d15Sespie   iterator_type os_it05 = mon_put.put(oss.rdbuf(), false, oss, ' ', digits1);
116*03a78d15Sespie   wstring result5 = oss.str();
117*03a78d15Sespie   VERIFY( result5 == L"HK$7,200,000,000.00");
118*03a78d15Sespie 
119*03a78d15Sespie   oss.str(empty);
120*03a78d15Sespie   iterator_type os_it06 = mon_put.put(oss.rdbuf(), true, oss, ' ', digits2);
121*03a78d15Sespie   wstring result6 = oss.str();
122*03a78d15Sespie   VERIFY( result6 == L"(HKD 100,000,000,000.00)");
123*03a78d15Sespie 
124*03a78d15Sespie   // test one-digit formats without zero padding
125*03a78d15Sespie   oss.imbue(loc_c);
126*03a78d15Sespie   oss.str(empty);
127*03a78d15Sespie   iterator_type os_it07 = mon_put.put(oss.rdbuf(), true, oss, ' ', digits4);
128*03a78d15Sespie   wstring result7 = oss.str();
129*03a78d15Sespie   VERIFY( result7 == L"1");
130*03a78d15Sespie 
131*03a78d15Sespie   // test one-digit formats with zero padding, zero frac widths
132*03a78d15Sespie   oss.imbue(loc_hk);
133*03a78d15Sespie   oss.str(empty);
134*03a78d15Sespie   iterator_type os_it08 = mon_put.put(oss.rdbuf(), true, oss, ' ', digits4);
135*03a78d15Sespie   wstring result8 = oss.str();
136*03a78d15Sespie   VERIFY( result8 == L"(HKD .01)");
137*03a78d15Sespie 
138*03a78d15Sespie   oss.unsetf(ios_base::showbase);
139*03a78d15Sespie 
140*03a78d15Sespie   // test bunk input
141*03a78d15Sespie   oss.str(empty);
142*03a78d15Sespie   iterator_type os_it09 = mon_put.put(oss.rdbuf(), true, oss, ' ', digits3);
143*03a78d15Sespie   wstring result9 = oss.str();
144*03a78d15Sespie   VERIFY( result9 == L"");
145*03a78d15Sespie 
146*03a78d15Sespie   // test io.width() > length
147*03a78d15Sespie   // test various fill strategies
148*03a78d15Sespie   oss.imbue(loc_de);
149*03a78d15Sespie 
150*03a78d15Sespie   oss.str(empty);
151*03a78d15Sespie   oss.width(20);
152*03a78d15Sespie   iterator_type os_it10 = mon_put.put(oss.rdbuf(), true, oss, '*', digits4);
153*03a78d15Sespie   wstring result10 = oss.str();
154*03a78d15Sespie   VERIFY( result10 == L"***************-,01*");
155*03a78d15Sespie 
156*03a78d15Sespie   oss.str(empty);
157*03a78d15Sespie   oss.width(20);
158*03a78d15Sespie   oss.setf(ios_base::internal);
159*03a78d15Sespie   iterator_type os_it11 = mon_put.put(oss.rdbuf(), true, oss, '*', digits4);
160*03a78d15Sespie   wstring result11 = oss.str();
161*03a78d15Sespie   VERIFY( result11 == L"-,01****************");
162*03a78d15Sespie }
163*03a78d15Sespie 
164*03a78d15Sespie // test double/wstring versions
test02()165*03a78d15Sespie void test02()
166*03a78d15Sespie {
167*03a78d15Sespie   using namespace std;
168*03a78d15Sespie   typedef money_base::part part;
169*03a78d15Sespie   typedef money_base::pattern pattern;
170*03a78d15Sespie   typedef ostreambuf_iterator<wchar_t> iterator_type;
171*03a78d15Sespie 
172*03a78d15Sespie   bool test = true;
173*03a78d15Sespie 
174*03a78d15Sespie   // basic construction
175*03a78d15Sespie   locale loc_c = locale::classic();
176*03a78d15Sespie   locale loc_hk("en_HK");
177*03a78d15Sespie   locale loc_fr("fr_FR@euro");
178*03a78d15Sespie   locale loc_de("de_DE@euro");
179*03a78d15Sespie   VERIFY( loc_c != loc_de );
180*03a78d15Sespie   VERIFY( loc_hk != loc_fr );
181*03a78d15Sespie   VERIFY( loc_hk != loc_de );
182*03a78d15Sespie   VERIFY( loc_de != loc_fr );
183*03a78d15Sespie 
184*03a78d15Sespie   // cache the moneypunct facets
185*03a78d15Sespie   typedef moneypunct<wchar_t, true> __money_true;
186*03a78d15Sespie   typedef moneypunct<wchar_t, false> __money_false;
187*03a78d15Sespie   const __money_true& monpunct_c_t = use_facet<__money_true>(loc_c);
188*03a78d15Sespie   const __money_true& monpunct_de_t = use_facet<__money_true>(loc_de);
189*03a78d15Sespie   const __money_false& monpunct_c_f = use_facet<__money_false>(loc_c);
190*03a78d15Sespie   const __money_false& monpunct_de_f = use_facet<__money_false>(loc_de);
191*03a78d15Sespie   const __money_true& monpunct_hk_t = use_facet<__money_true>(loc_hk);
192*03a78d15Sespie   const __money_false& monpunct_hk_f = use_facet<__money_false>(loc_hk);
193*03a78d15Sespie 
194*03a78d15Sespie   // sanity check the data is correct.
195*03a78d15Sespie   const wstring empty;
196*03a78d15Sespie 
197*03a78d15Sespie   // total EPA budget FY 2002
198*03a78d15Sespie   const long double  digits1 = 720000000000.0;
199*03a78d15Sespie 
200*03a78d15Sespie   // est. cost, national missile "defense", expressed as a loss in USD 2001
201*03a78d15Sespie   const long double digits2 = -10000000000000.0;
202*03a78d15Sespie 
203*03a78d15Sespie   // input less than frac_digits
204*03a78d15Sespie   const long double digits4 = -1.0;
205*03a78d15Sespie 
206*03a78d15Sespie 
207*03a78d15Sespie   wostringstream oss;
208*03a78d15Sespie   oss.imbue(loc_de);
209*03a78d15Sespie   // cache the money_put facet
210*03a78d15Sespie   const money_put<wchar_t>& mon_put = use_facet<money_put<wchar_t> >(oss.getloc());
211*03a78d15Sespie 
212*03a78d15Sespie 
213*03a78d15Sespie   iterator_type os_it01 = mon_put.put(oss.rdbuf(), true, oss, ' ', digits1);
214*03a78d15Sespie   wstring result1 = oss.str();
215*03a78d15Sespie   VERIFY( result1 == L"7.200.000.000,00 ");
216*03a78d15Sespie 
217*03a78d15Sespie   oss.str(empty);
218*03a78d15Sespie   iterator_type os_it02 = mon_put.put(oss.rdbuf(), false, oss, ' ', digits1);
219*03a78d15Sespie   wstring result2 = oss.str();
220*03a78d15Sespie   VERIFY( result2 == L"7.200.000.000,00 ");
221*03a78d15Sespie 
222*03a78d15Sespie   // intl and non-intl versions should be the same.
223*03a78d15Sespie   VERIFY( result1 == result2 );
224*03a78d15Sespie 
225*03a78d15Sespie   // now try with showbase, to get currency symbol in format
226*03a78d15Sespie   oss.setf(ios_base::showbase);
227*03a78d15Sespie 
228*03a78d15Sespie   oss.str(empty);
229*03a78d15Sespie   iterator_type os_it03 = mon_put.put(oss.rdbuf(), true, oss, ' ', digits1);
230*03a78d15Sespie   wstring result3 = oss.str();
231*03a78d15Sespie   VERIFY( result3 == L"7.200.000.000,00 EUR ");
232*03a78d15Sespie 
233*03a78d15Sespie   oss.str(empty);
234*03a78d15Sespie   iterator_type os_it04 = mon_put.put(oss.rdbuf(), false, oss, ' ', digits1);
235*03a78d15Sespie   wstring result4 = oss.str();
236*03a78d15Sespie   VERIFY( result4 == L"7.200.000.000,00 \x20ac");
237*03a78d15Sespie 
238*03a78d15Sespie   // intl and non-intl versions should be different.
239*03a78d15Sespie   VERIFY( result3 != result4 );
240*03a78d15Sespie   VERIFY( result3 != result1 );
241*03a78d15Sespie   VERIFY( result4 != result2 );
242*03a78d15Sespie }
243*03a78d15Sespie 
test03()244*03a78d15Sespie void test03()
245*03a78d15Sespie {
246*03a78d15Sespie   using namespace std;
247*03a78d15Sespie   bool test = true;
248*03a78d15Sespie 
249*03a78d15Sespie   // Check money_put works with other iterators besides streambuf
250*03a78d15Sespie   // output iterators. (As long as output_iterator requirements are met.)
251*03a78d15Sespie   typedef wstring::iterator iter_type;
252*03a78d15Sespie   typedef money_put<wchar_t, iter_type> mon_put_type;
253*03a78d15Sespie   const ios_base::iostate goodbit = ios_base::goodbit;
254*03a78d15Sespie   const ios_base::iostate eofbit = ios_base::eofbit;
255*03a78d15Sespie   ios_base::iostate err = goodbit;
256*03a78d15Sespie   const locale loc_c = locale::classic();
257*03a78d15Sespie   // woman, art, thief (stole the blues)
258*03a78d15Sespie   const wstring str(L"1943 Janis Joplin");
259*03a78d15Sespie   const long double ld = 1943.0;
260*03a78d15Sespie   const wstring x(str.size(), 'x'); // have to have allocated string!
261*03a78d15Sespie   wstring res;
262*03a78d15Sespie 
263*03a78d15Sespie   wostringstream oss;
264*03a78d15Sespie   oss.imbue(locale(loc_c, new mon_put_type));
265*03a78d15Sespie 
266*03a78d15Sespie   // Iterator advanced, state, output.
267*03a78d15Sespie   const mon_put_type& mp = use_facet<mon_put_type>(oss.getloc());
268*03a78d15Sespie 
269*03a78d15Sespie   // 01 string
270*03a78d15Sespie   res = x;
271*03a78d15Sespie   iter_type ret1 = mp.put(res.begin(), false, oss, ' ', str);
272*03a78d15Sespie   wstring sanity1(res.begin(), ret1);
273*03a78d15Sespie   VERIFY( err == goodbit );
274*03a78d15Sespie   VERIFY( res == L"1943xxxxxxxxxxxxx" );
275*03a78d15Sespie   VERIFY( sanity1 == L"1943" );
276*03a78d15Sespie 
277*03a78d15Sespie   // 02 long double
278*03a78d15Sespie   res = x;
279*03a78d15Sespie   iter_type ret2 = mp.put(res.begin(), false, oss, ' ', ld);
280*03a78d15Sespie   wstring sanity2(res.begin(), ret2);
281*03a78d15Sespie   VERIFY( err == goodbit );
282*03a78d15Sespie   VERIFY( res == L"1943xxxxxxxxxxxxx" );
283*03a78d15Sespie   VERIFY( sanity2 == L"1943" );
284*03a78d15Sespie }
285*03a78d15Sespie 
286*03a78d15Sespie // libstdc++/5280
test04()287*03a78d15Sespie void test04()
288*03a78d15Sespie {
289*03a78d15Sespie #ifdef _GLIBCPP_HAVE_SETENV
290*03a78d15Sespie   // Set the global locale to non-"C".
291*03a78d15Sespie   std::locale loc_de("de_DE@euro");
292*03a78d15Sespie   std::locale::global(loc_de);
293*03a78d15Sespie 
294*03a78d15Sespie   // Set LANG environment variable to de_DE@euro.
295*03a78d15Sespie   const char* oldLANG = getenv("LANG");
296*03a78d15Sespie   if (!setenv("LANG", "de_DE@euro", 1))
297*03a78d15Sespie     {
298*03a78d15Sespie       test01();
299*03a78d15Sespie       test02();
300*03a78d15Sespie       test03();
301*03a78d15Sespie       setenv("LANG", oldLANG ? oldLANG : "", 1);
302*03a78d15Sespie     }
303*03a78d15Sespie #endif
304*03a78d15Sespie }
305*03a78d15Sespie 
306*03a78d15Sespie struct My_money_io : public std::moneypunct<wchar_t,false>
307*03a78d15Sespie {
do_decimal_pointMy_money_io308*03a78d15Sespie   char_type do_decimal_point() const { return L'.'; }
do_thousands_sepMy_money_io309*03a78d15Sespie   char_type do_thousands_sep() const { return L','; }
do_groupingMy_money_io310*03a78d15Sespie   std::string do_grouping() const { return "\003"; }
311*03a78d15Sespie 
do_negative_signMy_money_io312*03a78d15Sespie   std::wstring do_negative_sign() const { return L"()"; }
313*03a78d15Sespie 
do_frac_digitsMy_money_io314*03a78d15Sespie   int do_frac_digits() const { return 2; }
315*03a78d15Sespie 
do_neg_formatMy_money_io316*03a78d15Sespie   pattern do_neg_format() const
317*03a78d15Sespie   {
318*03a78d15Sespie     pattern pat = { { symbol, space, sign, value } };
319*03a78d15Sespie     return pat;
320*03a78d15Sespie   }
321*03a78d15Sespie };
322*03a78d15Sespie 
323*03a78d15Sespie // libstdc++/5708
test05()324*03a78d15Sespie void test05()
325*03a78d15Sespie {
326*03a78d15Sespie   using namespace std;
327*03a78d15Sespie   typedef ostreambuf_iterator<wchar_t> OutIt;
328*03a78d15Sespie 
329*03a78d15Sespie   locale loc(locale::classic(), new My_money_io);
330*03a78d15Sespie 
331*03a78d15Sespie   bool intl = false;
332*03a78d15Sespie 
333*03a78d15Sespie   wstring val(L"-123456");
334*03a78d15Sespie   const money_put<wchar_t,OutIt>& mp  =
335*03a78d15Sespie     use_facet<money_put<wchar_t, OutIt> >(loc);
336*03a78d15Sespie 
337*03a78d15Sespie   wostringstream fmt;
338*03a78d15Sespie   fmt.imbue(loc);
339*03a78d15Sespie   OutIt out(fmt);
340*03a78d15Sespie   mp.put(out,intl,fmt,L'*',val);
341*03a78d15Sespie   VERIFY( fmt.str() == L"*(1,234.56)" );
342*03a78d15Sespie }
343*03a78d15Sespie 
344*03a78d15Sespie struct My_money_io_2 : public std::moneypunct<wchar_t,false>
345*03a78d15Sespie {
do_thousands_sepMy_money_io_2346*03a78d15Sespie   char_type do_thousands_sep() const { return L','; }
do_groupingMy_money_io_2347*03a78d15Sespie   std::string do_grouping() const { return "\001"; }
348*03a78d15Sespie };
349*03a78d15Sespie 
350*03a78d15Sespie // Make sure we can output a very big amount of money (with grouping too).
test06()351*03a78d15Sespie void test06()
352*03a78d15Sespie {
353*03a78d15Sespie   using namespace std;
354*03a78d15Sespie   typedef ostreambuf_iterator<wchar_t> OutIt;
355*03a78d15Sespie 
356*03a78d15Sespie   locale loc(locale::classic(), new My_money_io_2);
357*03a78d15Sespie 
358*03a78d15Sespie   bool intl = false;
359*03a78d15Sespie 
360*03a78d15Sespie   long double val = 1.0e50L;
361*03a78d15Sespie   const money_put<wchar_t,OutIt>& mp  =
362*03a78d15Sespie     use_facet<money_put<wchar_t, OutIt> >(loc);
363*03a78d15Sespie 
364*03a78d15Sespie   wostringstream fmt;
365*03a78d15Sespie   fmt.imbue(loc);
366*03a78d15Sespie   OutIt out(fmt);
367*03a78d15Sespie   mp.put(out,intl,fmt,'*',val);
368*03a78d15Sespie   VERIFY( fmt );
369*03a78d15Sespie }
370*03a78d15Sespie 
371*03a78d15Sespie // http://gcc.gnu.org/ml/libstdc++/2002-05/msg00038.html
test07()372*03a78d15Sespie void test07()
373*03a78d15Sespie {
374*03a78d15Sespie   bool test = true;
375*03a78d15Sespie 
376*03a78d15Sespie   const char* tentLANG = std::setlocale(LC_ALL, "ja_JP.eucjp");
377*03a78d15Sespie   if (tentLANG != NULL)
378*03a78d15Sespie     {
379*03a78d15Sespie       std::string preLANG = tentLANG;
380*03a78d15Sespie       test01();
381*03a78d15Sespie       test02();
382*03a78d15Sespie       test03();
383*03a78d15Sespie       test05();
384*03a78d15Sespie       test06();
385*03a78d15Sespie       std::string postLANG = std::setlocale(LC_ALL, NULL);
386*03a78d15Sespie       VERIFY( preLANG == postLANG );
387*03a78d15Sespie     }
388*03a78d15Sespie }
389*03a78d15Sespie #endif
390*03a78d15Sespie 
main()391*03a78d15Sespie int main()
392*03a78d15Sespie {
393*03a78d15Sespie #ifdef _GLIBCPP_USE_WCHAR_T
394*03a78d15Sespie   test01();
395*03a78d15Sespie   test02();
396*03a78d15Sespie   test03();
397*03a78d15Sespie   test04();
398*03a78d15Sespie   test05();
399*03a78d15Sespie   test06();
400*03a78d15Sespie   test07();
401*03a78d15Sespie #endif
402*03a78d15Sespie   return 0;
403*03a78d15Sespie }
404