Ne.app NeANT
The Ne.app NeANT User module of the NeANT distribution.
22.locale.time.get.cpp
Go to the documentation of this file.
1
29#include <locale>
30#include <sstream> // for stringstream
31
32#include <climits> // for INT_{MIN,MAX}
33#include <clocale> // for LC_ALL
34#include <cstdio> // for fprintf()
35#include <cstdlib> // for getenv()
36#include <cstring> // for memcmp(), strlen()
37#include <ctime> // for struct tm
38
39#include <rw_driver.h> // for rw_test()
40#include <rw_file.h> // for rw_nextfd()
41#include <rw_locale.h> // for rw_locale_query()
42#include <rw_printf.h> // for rw_snprintf()
43
44
46template <class charT>
47void do_test (int lineno, charT, const char *cname,
48 std::tm val, const char *pat, int consumed,
49 const char *fmt, int flags, int err_expect = -1)
50{
51 std::basic_ostringstream<charT> ostrm;
52
53 typedef std::istreambuf_iterator<charT> InIter;
54 typedef std::ostreambuf_iterator<charT> OutIter;
55
56 const std::time_get<charT, InIter> &tg =
57 std::use_facet<std::time_get<charT, InIter> >(ostrm.getloc ());
58
59 const std::time_put<charT, OutIter> &tp =
60 std::use_facet<std::time_put<charT, OutIter> >(ostrm.getloc ());
61
62 ostrm.flags (std::ios_base::fmtflags (flags));
63
64 charT wpatbuf [256];
65 for (std::size_t j = 0; !!(wpatbuf [j] = pat [j]); ++j);
66
67 const charT *wpat = wpatbuf;
68 const charT *wpatend = wpat + std::char_traits<charT>::length (wpat);
69
70 // format string
71 OutIter it (ostrm);
72 tp.put (it, ostrm, charT (' '), &val, wpat, wpatend);
73
74 // working around dumb compilers such as MSVC 6.0 that
75 // do not zero initialize POD structs when using tm()
76 static std::tm zero_tm;
77 std::tm x = zero_tm;
78
79 std::basic_istringstream<charT> istrm (ostrm.str ());
80
81 istrm.flags (std::ios_base::fmtflags (flags));
82
83 std::ios_base::iostate err = std::ios_base::goodbit;
84
85 const char *fname = 0;
86
87 InIter ibeg = InIter (istrm);
88 InIter iend;
89
90 _TRY {
91 if ( '\0' == fmt [1]
92 || ('E' == fmt [0] || ('O' == fmt [0] && '\0' == fmt [2]))) {
93
94 // single-character format strings "a", "b", "x", "X", and "Y"
95 // exercise the standard time_get interface, i.e., get_weekday(),
96 // get_monthname(), and get_year()
97
98 // other single or two character format strings, e.g., "Ec" or "Ex"
99 // exercise the single character extension (format specifier and
100 // an optional modifier)
101
102 switch (*fmt) {
103 case 'a':
104 fname = "get_weekday";
105 iend = tg.get_weekday (ibeg, iend, istrm, err, &x);
106 break;
107
108 case 'b':
109 fname = "get_monthname";
110 iend = tg.get_monthname (ibeg, iend, istrm, err, &x);
111 break;
112
113 case 'x':
114 fname = "get_date";
115 iend = tg.get_date (ibeg, iend, istrm, err, &x);
116 break;
117
118 case 'X':
119 fname = "get_time";
120 iend = tg.get_time (ibeg, iend, istrm, err, &x);
121 break;
122
123 case 'Y':
124 fname = "get_year";
125 iend = tg.get_year (ibeg, iend, istrm, err, &x);
126 break;
127
128 default:
129 fname = "get";
130 if ('E' == fmt [0] || 'O' == fmt [0])
131 iend = tg.get (ibeg, iend, istrm, err, &x,
132 fmt [1], fmt [0]);
133 else
134 iend = tg.get (ibeg, iend, istrm, err, &x, *fmt);
135 break;
136 }
137 }
138 else {
139 // multi-character format strings exercise the pattern
140 // extensions to time_get, ala strptime()
141
142 charT fmtstr [256];
143 charT *end;
144
145 const char *pfmt = fmt;
146 for (end = fmtstr; *pfmt; *end++ = *pfmt++);
147
148 fname = "get";
149 iend = tg.get (ibeg, iend, istrm, err, &x, fmtstr, end);
150 }
151 }
152 _CATCH (...) {
153 rw_error (0, 0, lineno,
154 "line %d. time_get<%s>::%s (%{*Ac}, ..., \"%s\") "
155 "unexpectedly threw an exception",
156 __LINE__, cname, fname,
157 int (sizeof (charT)), ostrm.str ().data (), fmt);
158
159 return;
160 }
161
162 int extracted = -1 == consumed ? -1
163 : int (istrm.rdbuf ()->pubseekoff (0, std::ios::cur, std::ios::in));
164
165 if (extracted == -1)
166 consumed = -1;
167
168 int success =
169 extracted == consumed && (-1 == err_expect || err == err_expect);
170
171 rw_assert (success, __FILE__, lineno,
172 "line %d. time_get<%s>::%s (%{*Ac}, ..., \"%s\") "
173 "ate %d, expected %d, rdstate() == %{Is}, got %{Is}",
174 __LINE__, cname, fname,
175 int (sizeof (charT)), ostrm.str ().data (), fmt,
176 extracted, consumed, err_expect, err);
177
178 success = 0 == std::memcmp (&x, &val, sizeof x);
179
180 rw_assert (success, __FILE__, lineno,
181 "line %d. time_get<%s>::%s (%{*Ac}, ..., \"%s\") got %{t}, "
182 "expected %{t}, flags = %{If}, locale (%s)",
183 __LINE__, cname, fname,
184 int (sizeof (charT)), ostrm.str ().data (), fmt, &x,
185 &val, flags, std::locale ().name ().data ());
186}
187
188
189
191std::tm mktm (int sec = 0, int min = 0, int hour = 0,
192 int mday = 0, int mon = 0, int year = 0,
193 int wday = 0, int yday = 0, int isdst = 0)
194{
195 std::tm tmp = std::tm ();
196
197 if (sec < 0) {
198 // get the current local time
199 std::time_t t = std::time (0);
200 std::tm *ptm = std::localtime (&t);
201 return ptm ? *ptm : tmp;
202 }
203
204 // use arguments to initialize struct
205 tmp.tm_sec = sec; // seconds after the minute [0, 60]
206 tmp.tm_min = min; // minutes after the hour [0, 59]
207 tmp.tm_hour = hour; // hours since midnight [0, 23]
208 tmp.tm_mday = mday; // day of the month [1, 31]
209 tmp.tm_mon = mon; // months since January [0, 11]
210 tmp.tm_year = year; // years since 1900
211 tmp.tm_wday = wday; // days since Sunday [0, 6]
212 tmp.tm_yday = yday; // days since January 1 [0, 365]
213 tmp.tm_isdst = isdst; // Daylight Saving Time flag
214
215 return tmp;
216}
217
218
219// for convenience
220#define Boolalpha std::ios_base::boolalpha
221#define Dec std::ios_base::dec
222#define Fixed std::ios_base::fixed
223#define Hex std::ios_base::hex
224#define Internal std::ios_base::internal
225#define Left std::ios_base::left
226#define Oct std::ios_base::oct
227#define Right std::ios_base::right
228#define Scientific std::ios_base::scientific
229#define Showbase std::ios_base::showbase
230#define Showpoint std::ios_base::showpoint
231#define Showpos std::ios_base::showpos
232#define Skipws std::ios_base::skipws
233#define Unitbuf std::ios_base::unitbuf
234#define Uppercase std::ios_base::uppercase
235#define Bin std::ios_base::bin
236#define Adjustfield std::ios_base::adjustfield
237#define Basefield std::ios_base::basefield
238#define Floatfield std::ios_base::floatfield
239#define Nolock std::ios_base::nolock
240#define Nolockbuf std::ios_base::nolockbuf
241
242// capitalize to prevent EDG eccp from expanding the macros
243// in .cc files when implicit inclusion is used (causes errors
244// in constructs such as traits_type::eof ())
245#define Bad std::ios_base::badbit
246#define Eof std::ios_base::eofbit
247#define Fail std::ios_base::failbit
248#define Good std::ios_base::goodbit
249
250
251#define T __LINE__, charT (), cname, mktm
252#define TEST do_test
253
254#define FUNCTION(fun) \
255 rw_info (0, 0, __LINE__, \
256 "std::time_get<%s>::%s() in locale (\"%s\")", \
257 cname, fun, std::locale ().name ().c_str ())
258
259#define STEP(desc) rw_info (0, 0, __LINE__, "%s", desc)
260
261
262template <class charT>
263void test_posix (charT, const char *cname)
264{
265 // set the global locale object
266 std::locale::global (std::locale ("C"));
267
268 // exercise abbreviated weekday names (time_get::get_weekday())
269 FUNCTION ("get_weekday");
270
271 TEST (T (0, 0, 0, 0, 0, 0, 0), "%a", -1, "a", 0, Eof);
272 TEST (T (0, 0, 0, 0, 0, 0, 1), "%a", -1, "a", 0, Eof);
273 TEST (T (0, 0, 0, 0, 0, 0, 2), "%a", -1, "a", 0, Eof);
274 TEST (T (0, 0, 0, 0, 0, 0, 3), "%a", -1, "a", 0, Eof);
275 TEST (T (0, 0, 0, 0, 0, 0, 4), "%a", -1, "a", 0, Eof);
276 TEST (T (0, 0, 0, 0, 0, 0, 5), "%a", -1, "a", 0, Eof);
277 TEST (T (0, 0, 0, 0, 0, 0, 6), "%a", -1, "a", 0, Eof);
278
279 // comparison is case insensitive
280 TEST (T (0, 0, 0, 0, 0, 0, 0), "Sun", 3, "a", 0, Eof);
281 TEST (T (0, 0, 0, 0, 0, 0, 0), "SUN", 3, "a", 0, Eof);
282 TEST (T (0, 0, 0, 0, 0, 0, 0), "sun", 3, "a", 0, Eof);
283 TEST (T (0, 0, 0, 0, 0, 0, 1), "Mon", 3, "a", 0, Eof);
284 TEST (T (0, 0, 0, 0, 0, 0, 2), "Tue", 3, "a", 0, Eof);
285 TEST (T (0, 0, 0, 0, 0, 0, 3), "Wed", 3, "a", 0, Eof);
286 TEST (T (0, 0, 0, 0, 0, 0, 4), "Thu", 3, "a", 0, Eof);
287 TEST (T (0, 0, 0, 0, 0, 0, 5), "Fri", 3, "a", 0, Eof);
288 TEST (T (0, 0, 0, 0, 0, 0, 6), "Sat", 3, "a", 0, Eof);
289
290 // abbreviation followed by a letter other than the one
291 // that follows in a full name is acepted
292 TEST (T (0, 0, 0, 0, 0, 0, 0), "suna", 3, "a", 0, Good);
293 TEST (T (0, 0, 0, 0, 0, 0, 1), "monb", 3, "a", 0, Good);
294 TEST (T (0, 0, 0, 0, 0, 0, 2), "tuec", 3, "a", 0, Good);
295 TEST (T (0, 0, 0, 0, 0, 0, 3), "wedd", 3, "a", 0, Good);
296 TEST (T (0, 0, 0, 0, 0, 0, 4), "thue", 3, "a", 0, Good);
297 TEST (T (0, 0, 0, 0, 0, 0, 5), "frif", 3, "a", 0, Good);
298 TEST (T (0, 0, 0, 0, 0, 0, 6), "satg", 3, "a", 0, Good);
299
300 // exercise failure on invalid input including incomplete
301 // full names (other than valid cases exercised above)
302 TEST (T (0, 0, 0, 0, 0, 0, 0), " Sun", 0, "a", 0, Fail);
303 TEST (T (0, 0, 0, 0, 0, 0, 0), "Mond", 4, "a", 0, Eof | Fail);
304 TEST (T (0, 0, 0, 0, 0, 0, 0), "Tuesd", 5, "a", 0, Eof | Fail);
305 TEST (T (0, 0, 0, 0, 0, 0, 0), "Wednesd", 7, "a", 0, Eof | Fail);
306 TEST (T (0, 0, 0, 0, 0, 0, 0), "Thursda.", 7, "a", 0, Fail);
307 TEST (T (0, 0, 0, 0, 0, 0, 0), "Fridax", 5, "a", 0, Fail);
308 TEST (T (0, 0, 0, 0, 0, 0, 0), "6Saturday", 0, "a", 0, Fail);
309
310 // exercise full weekday names
311 TEST (T (0, 0, 0, 0, 0, 0, 0), "%A", -1, "a", 0, -1);
312 TEST (T (0, 0, 0, 0, 0, 0, 1), "%A", -1, "a", 0, -1);
313 TEST (T (0, 0, 0, 0, 0, 0, 2), "%A", -1, "a", 0, -1);
314 TEST (T (0, 0, 0, 0, 0, 0, 3), "%A", -1, "a", 0, -1);
315 TEST (T (0, 0, 0, 0, 0, 0, 4), "%A", -1, "a", 0, -1);
316 TEST (T (0, 0, 0, 0, 0, 0, 5), "%A", -1, "a", 0, -1);
317 TEST (T (0, 0, 0, 0, 0, 0, 6), "%A", -1, "a", 0, -1);
318
319 // comparison is case insensitive
320 TEST (T (0, 0, 0, 0, 0, 0, 0), "Sunday", 6, "a", 0, Good);
321 TEST (T (0, 0, 0, 0, 0, 0, 0), "SUNDAY", 6, "a", 0, Good);
322 TEST (T (0, 0, 0, 0, 0, 0, 0), "sunday", 6, "a", 0, Good);
323 TEST (T (0, 0, 0, 0, 0, 0, 1), "Monday", 6, "a", 0, Good);
324 TEST (T (0, 0, 0, 0, 0, 0, 2), "Tuesday", 7, "a", 0, Good);
325 TEST (T (0, 0, 0, 0, 0, 0, 3), "Wednesday", 9, "a", 0, Good);
326 TEST (T (0, 0, 0, 0, 0, 0, 4), "Thursday", 8, "a", 0, Good);
327 TEST (T (0, 0, 0, 0, 0, 0, 5), "Friday", 6, "a", 0, Good);
328 TEST (T (0, 0, 0, 0, 0, 0, 6), "Saturday", 8, "a", 0, Good);
329
330 TEST (T (0, 0, 0, 0, 0, 0, 0), "Sunday ", 6, "a", 0, Good);
331 TEST (T (0, 0, 0, 0, 0, 0, 1), "Monday 0", 6, "a", 0, Good);
332 TEST (T (0, 0, 0, 0, 0, 0, 2), "Tuesdayy", 7, "a", 0, Good);
333 TEST (T (0, 0, 0, 0, 0, 0, 3), "Wednesday.", 9, "a", 0, Good);
334 TEST (T (0, 0, 0, 0, 0, 0, 4), "Thursday,", 8, "a", 0, Good);
335 TEST (T (0, 0, 0, 0, 0, 0, 5), "Friday/", 6, "a", 0, Good);
336 TEST (T (0, 0, 0, 0, 0, 0, 6), "Saturday:", 8, "a", 0, Good);
337
338 // exercise abbreviated month names (time_get::get_monthname())
339 FUNCTION ("get_monthname");
340 TEST (T (0, 0, 0, 0, 0), "%b", -1, "b", 0, -1);
341 TEST (T (0, 0, 0, 0, 1), "%b", -1, "b", 0, -1);
342 TEST (T (0, 0, 0, 0, 2), "%b", -1, "b", 0, -1);
343 TEST (T (0, 0, 0, 0, 3), "%b", -1, "b", 0, -1);
344 TEST (T (0, 0, 0, 0, 4), "%b", -1, "b", 0, -1);
345 TEST (T (0, 0, 0, 0, 5), "%b", -1, "b", 0, -1);
346 TEST (T (0, 0, 0, 0, 6), "%b", -1, "b", 0, -1);
347 TEST (T (0, 0, 0, 0, 7), "%b", -1, "b", 0, -1);
348 TEST (T (0, 0, 0, 0, 8), "%b", -1, "b", 0, -1);
349 TEST (T (0, 0, 0, 0, 9), "%b", -1, "b", 0, -1);
350 TEST (T (0, 0, 0, 0, 10), "%b", -1, "b", 0, -1);
351 TEST (T (0, 0, 0, 0, 11), "%b", -1, "b", 0, -1);
352
353 TEST (T (0, 0, 0, 0, 0), "Jan", 3, "b", 0, Eof);
354 TEST (T (0, 0, 0, 0, 1), "Feb", 3, "b", 0, Eof);
355 TEST (T (0, 0, 0, 0, 2), "Mar", 3, "b", 0, Eof);
356 TEST (T (0, 0, 0, 0, 3), "Apr", 3, "b", 0, Eof);
357 TEST (T (0, 0, 0, 0, 4), "May", 3, "b", 0, Good);
358 TEST (T (0, 0, 0, 0, 5), "Jun", 3, "b", 0, Eof);
359 TEST (T (0, 0, 0, 0, 6), "Jul", 3, "b", 0, Eof);
360 TEST (T (0, 0, 0, 0, 7), "Aug", 3, "b", 0, Eof);
361 TEST (T (0, 0, 0, 0, 8), "Sep", 3, "b", 0, Eof);
362 TEST (T (0, 0, 0, 0, 9), "Oct", 3, "b", 0, Eof);
363 TEST (T (0, 0, 0, 0, 10), "Nov", 3, "b", 0, Eof);
364 TEST (T (0, 0, 0, 0, 11), "Dec", 3, "b", 0, Eof);
365
366 // exercise invalid abbreviated month names
367 TEST (T (0, 0, 0, 0, 0), "J", 1, "b", 0, Eof | Fail);
368 TEST (T (0, 0, 0, 0, 0), "J ", 1, "b", 0, Fail);
369 TEST (T (0, 0, 0, 0, 0), "Ja", 2, "b", 0, Eof | Fail);
370 TEST (T (0, 0, 0, 0, 0), "Ju", 2, "b", 0, Eof | Fail);
371
372 // exercise full month names
373 TEST (T (0, 0, 0, 0, 0), "%B", -1, "b", 0, -1);
374 TEST (T (0, 0, 0, 0, 1), "%B", -1, "b", 0, -1);
375 TEST (T (0, 0, 0, 0, 2), "%B", -1, "b", 0, -1);
376 TEST (T (0, 0, 0, 0, 3), "%B", -1, "b", 0, -1);
377 TEST (T (0, 0, 0, 0, 4), "%B", -1, "b", 0, -1);
378 TEST (T (0, 0, 0, 0, 5), "%B", -1, "b", 0, -1);
379 TEST (T (0, 0, 0, 0, 6), "%B", -1, "b", 0, -1);
380 TEST (T (0, 0, 0, 0, 7), "%B", -1, "b", 0, -1);
381 TEST (T (0, 0, 0, 0, 8), "%B", -1, "b", 0, -1);
382 TEST (T (0, 0, 0, 0, 9), "%B", -1, "b", 0, -1);
383 TEST (T (0, 0, 0, 0, 10), "%B", -1, "b", 0, -1);
384 TEST (T (0, 0, 0, 0, 11), "%B", -1, "b", 0, -1);
385
386 TEST (T (0, 0, 0, 0, 0), "January", 7, "b", 0, Good);
387 TEST (T (0, 0, 0, 0, 0), "January ", 7, "b", 0, Good);
388 TEST (T (0, 0, 0, 0, 1), "February", 8, "b", 0, Good);
389 TEST (T (0, 0, 0, 0, 2), "March", 5, "b", 0, Good);
390 TEST (T (0, 0, 0, 0, 2), "Marchh", 5, "b", 0, Good);
391 TEST (T (0, 0, 0, 0, 3), "April", 5, "b", 0, Good);
392 TEST (T (0, 0, 0, 0, 4), "May", 3, "b", 0, Good);
393 TEST (T (0, 0, 0, 0, 5), "June", 4, "b", 0, Good);
394 TEST (T (0, 0, 0, 0, 6), "July", 4, "b", 0, Good);
395 TEST (T (0, 0, 0, 0, 6), "Jull", 3, "b", 0, Good);
396 TEST (T (0, 0, 0, 0, 7), "August", 6, "b", 0, Good);
397 TEST (T (0, 0, 0, 0, 8), "September", 9, "b", 0, Good);
398 TEST (T (0, 0, 0, 0, 9), "October", 7, "b", 0, Good);
399 TEST (T (0, 0, 0, 0, 10), "November", 8, "b", 0, Good);
400 TEST (T (0, 0, 0, 0, 11), "December", 8, "b", 0, Good);
401
402 // exercise invalid full month names
403 TEST (T (0, 0, 0, 0, 0), "Januar", 6, "b", 0, Eof | Fail);
404 TEST (T (0, 0, 0, 0, 0), "Februar", 7, "b", 0, Eof | Fail);
405 TEST (T (0, 0, 0, 0, 0), " March", 0, "b", 0, Fail);
406 TEST (T (0, 0, 0, 0, 0), "apri/", 4, "b", 0, Fail);
407 TEST (T (0, 0, 0, 0, 0), "/MAY", 0, "b", 0, Fail);
408 TEST (T (0, 0, 0, 0, 0), ":Jun", 0, "b", 0, Fail);
409 TEST (T (0, 0, 0, 0, 0), "Ju ", 2, "b", 0, Fail);
410
411 // exercise date (time_get::get_date())
412 FUNCTION ("get_date");
413 TEST (T (0, 0, 0, 1, 0, 100), "%x", 8, "x", 0, Eof);
414 TEST (T (0, 0, 0, 2, 1, 111), "%x", 8, "x", 0, Eof);
415 TEST (T (0, 0, 0, 3, 2, 122), "%x", 8, "x", 0, Eof);
416 TEST (T (0, 0, 0, 4, 3, 133), "%x", 8, "x", 0, Eof);
417 TEST (T (0, 0, 0, 5, 4, 144), "%x", 8, "x", 0, Eof);
418 TEST (T (0, 0, 0, 6, 5, 155), "%x", 8, "x", 0, Eof);
419 TEST (T (0, 0, 0, 7, 6, 166), "%x", 8, "x", 0, Eof);
420 TEST (T (0, 0, 0, 8, 7, 168), "%x", 8, "x", 0, Eof);
421 TEST (T (0, 0, 0, 9, 8, 69), "%x", 8, "x", 0, Eof);
422 TEST (T (0, 0, 0, 10, 9, 99), "%x", 8, "x", 0, Eof);
423
424 TEST (T (0, 0, 0, 11, 5, 155), "06/11/55", 8, "x", 0, Eof);
425 TEST (T (0, 0, 0, 12, 6, 167), "07/12/67", 8, "x", 0, Eof);
426 TEST (T (0, 0, 0, 23, 7, 78), "08/23/78", 8, "x", 0, Eof);
427 TEST (T (0, 0, 0, 31, 11, 89), "12/31/89", 8, "x", 0, Eof);
428
429 // exercise time (time_get::get_time())
430 FUNCTION ("get_time");
431 TEST (T ( 0, 0, 0), "%X", 8, "X", 0, Eof);
432 TEST (T ( 1, 59, 11), "%X", 8, "X", 0, Eof);
433 TEST (T (12, 48, 10), "%X", 8, "X", 0, Eof);
434 TEST (T (23, 37, 9), "%X", 8, "X", 0, Eof);
435 TEST (T (34, 26, 8), "%X", 8, "X", 0, Eof);
436 TEST (T (45, 15, 7), "%X", 8, "X", 0, Eof);
437 TEST (T (56, 4, 6), "%X", 8, "X", 0, Eof);
438
439 TEST (T ( 0, 0, 0), "00:00:00", 8, "X", 0, Eof);
440 TEST (T (60, 9, 23), "23:09:60", 8, "X", 0, Eof);
441 TEST (T (59, 18, 22), "22:18:59", 8, "X", 0, Eof);
442 TEST (T (58, 27, 21), "21:27:58", 8, "X", 0, Eof);
443 TEST (T (57, 36, 20), "20:36:57", 8, "X", 0, Eof);
444 TEST (T (56, 45, 19), "19:45:56", 8, "X", 0, Eof);
445 TEST (T (55, 54, 18), "18:54:55", 8, "X", 0, Eof);
446
447 // exercise year (time_get::get_year())
448 FUNCTION ("get_year");
449 TEST (T (0, 0, 0, 0, 0, -1900), "0", 1, "Y", 0, Eof);
450 TEST (T (0, 0, 0, 0, 0, -1900), "00", 2, "Y", 0, Eof);
451 TEST (T (0, 0, 0, 0, 0, -1899), "001", 3, "Y", 0, Eof);
452 TEST (T (0, 0, 0, 0, 0, -124), "1776", 4, "Y", 0, Eof);
453 TEST (T (0, 0, 0, 0, 0, 0), "1900", 4, "Y", 0, Eof);
454 TEST (T (0, 0, 0, 0, 0, 1), "1901", 4, "Y", 0, Eof);
455 TEST (T (0, 0, 0, 0, 0, 99), "1999", 4, "Y", 0, Eof);
456 TEST (T (0, 0, 0, 0, 0, 102), "2002", 4, "Y", 0, Eof);
457 TEST (T (0, 0, 0, 0, 0, 98099), "99999", 5, "Y", 0, Eof);
458
459 FUNCTION ("get");
460
461 // exercise extensions implementing complete IEEE Std 1003.1-2001 support
462 // http://www.opengroup.org/onlinepubs/007904975/functions/strptime.html
463
464 // capital format specifier (other than "X") implies the
465 // testing of std::time_get<>::get (..., char, char)
466
467 // %a The day of the week, using the locale's weekday names;
468 // either the abbreviated or full name may be specified.
469 // %A Equivalent to %a.
470 STEP ("%a, %A: the day of the week");
471 TEST (T (0, 0, 0, 0, 0, 0, 0), "Sun", 3, "A", 0, Eof);
472 TEST (T (0, 0, 0, 0, 0, 0, 1), "Mon", 3, "A", 0, Eof);
473 TEST (T (0, 0, 0, 0, 0, 0, 2), "Tue", 3, "A", 0, Eof);
474 TEST (T (0, 0, 0, 0, 0, 0, 3), "Wed", 3, "A", 0, Eof);
475 TEST (T (0, 0, 0, 0, 0, 0, 4), "Thu", 3, "A", 0, Eof);
476 TEST (T (0, 0, 0, 0, 0, 0, 5), "Fri", 3, "A", 0, Eof);
477 TEST (T (0, 0, 0, 0, 0, 0, 6), "Sat", 3, "A", 0, Eof);
478
479 TEST (T (0, 0, 0, 0, 0, 0, 0), "Sunday", 6, "A", 0, Good);
480 TEST (T (0, 0, 0, 0, 0, 0, 1), "Monday", 6, "A", 0, Good);
481 TEST (T (0, 0, 0, 0, 0, 0, 2), "Tuesday", 7, "A", 0, Good);
482 TEST (T (0, 0, 0, 0, 0, 0, 3), "Wednesday", 9, "A", 0, Good);
483 TEST (T (0, 0, 0, 0, 0, 0, 4), "Thursday", 8, "A", 0, Good);
484 TEST (T (0, 0, 0, 0, 0, 0, 5), "Friday", 6, "A", 0, Good);
485 TEST (T (0, 0, 0, 0, 0, 0, 6), "Saturday", 8, "A", 0, Good);
486
487 // %b The month, using the locale's month names;
488 // either the abbreviated or full name may be specified.
489 // %B Equivalent to %b.
490 STEP ("%b, %B: the month");
491 TEST (T (0, 0, 0, 0, 0), "January", 7, "B", 0, Good);
492 TEST (T (0, 0, 0, 0, 1), "February", 8, "B", 0, Good);
493 TEST (T (0, 0, 0, 0, 2), "March", 5, "B", 0, Good);
494 TEST (T (0, 0, 0, 0, 3), "April", 5, "B", 0, Good);
495 TEST (T (0, 0, 0, 0, 4), "May", 3, "B", 0, Good);
496 TEST (T (0, 0, 0, 0, 5), "June", 4, "B", 0, Good);
497 TEST (T (0, 0, 0, 0, 6), "July", 4, "B", 0, Good);
498 TEST (T (0, 0, 0, 0, 7), "August", 6, "B", 0, Good);
499 TEST (T (0, 0, 0, 0, 8), "September", 9, "B", 0, Good);
500 TEST (T (0, 0, 0, 0, 9), "October", 7, "B", 0, Good);
501 TEST (T (0, 0, 0, 0, 10), "November", 8, "B", 0, Good);
502 TEST (T (0, 0, 0, 0, 11), "December", 8, "B", 0, Good);
503
504 // %c Replaced by the locale's appropriate date and time representation.
505 STEP ("%c: date and time representation");
506 rw_warn (0, 0, __LINE__, "%%c not being exercised");
507
508
509 // %C: The century number [00,99]; leading zeros are permitted
510 // but not required.
511 STEP ("%C: the century number");
512 TEST (T (0, 0, 0, 0, 0, -1900), "0", 1, "C", 0, Eof);
513 TEST (T (0, 0, 0, 0, 0, -1800), "1", 1, "C", 0, Eof);
514 TEST (T (0, 0, 0, 0, 0, -1700), "2", 1, "C", 0, Eof);
515 TEST (T (0, 0, 0, 0, 0, -1600), "3", 1, "C", 0, Eof);
516 TEST (T (0, 0, 0, 0, 0, -1500), "04", 2, "C", 0, Eof);
517 TEST (T (0, 0, 0, 0, 0, 0), "19", 2, "C", 0, Eof);
518 TEST (T (0, 0, 0, 0, 0, 100), "20", 2, "C", 0, Eof);
519 TEST (T (0, 0, 0, 0, 0, 200), "21", 2, "C", 0, Eof);
520 TEST (T (0, 0, 0, 0, 0, 1300), "32", 2, "C", 0, Eof);
521 TEST (T (0, 0, 0, 0, 0, 8000), "99", 2, "C", 0, Eof);
522 TEST (T (0, 0, 0, 0, 0, 0), "100", 3, "C", 0, Eof | Fail);
523
524 // %d The day of the month [01,31]; leading zeros are permitted but not
525 // required.
526 STEP ("%d: day of the month");
527 TEST (T (0, 0, 0, 1), "1", 1, "d", 0, Eof);
528 TEST (T (0, 0, 0, 2), "02", 2, "d", 0, Eof);
529 TEST (T (0, 0, 0, 28), "28", 2, "d", 0, Eof);
530 TEST (T (0, 0, 0, 29), "29", 2, "d", 0, Eof);
531 TEST (T (0, 0, 0, 30), "030", 3, "d", 0, Eof);
532 TEST (T (0, 0, 0, 31), "0031", 4, "d", 0, Eof);
533 TEST (T (0, 0, 0, 0), "0", 1, "d", 0, Eof | Fail);
534 // leading whitespace not allowed
535 TEST (T (0, 0, 0, 0), " 3", 0, "d", 0, Fail);
536 TEST (T (0, 0, 0, 0), "32", 2, "d", 0, Eof | Fail);
537
538 // %D The date as %m/%d/%y.
539 STEP ("%D: the date as %m/%d/%y");
540 TEST (T (0, 0, 0, 14, 3, 102), "4/14/2", 6, "D", 0, Eof);
541 TEST (T (0, 0, 0, 14, 3, 102), "04/14/02", 8, "D", 0, Eof);
542 TEST (T (0, 0, 0, 14, 3, 102), "04/14/002", 9, "D", 0, Eof);
543 TEST (T (0, 0, 0, 0, 0, 0), "0/1/2002", 1, "D", 0, Fail);
544 TEST (T (0, 0, 0, 0, 0, 0), "4/0/2002", 3, "D", 0, Fail);
545 TEST (T (0, 0, 0, 0, 0, 0), "4/32/2002", 4, "D", 0, Fail);
546
547 // %e Equivalent to %d; leading zeros are permitted but not required.
548 STEP ("%e: equivalent to %d");
549 TEST (T (0, 0, 0, 1), "01", 2, "e", 0, Eof);
550 TEST (T (0, 0, 0, 9), "9", 1, "e", 0, Eof);
551 TEST (T (0, 0, 0, 31), "31", 2, "e", 0, Eof);
552 TEST (T (0, 0, 0, 0), "0", 1, "e", 0, Eof | Fail);
553 // leading whitespace not allowed
554 TEST (T (0, 0, 0, 0), " 2", 0, "e", 0, Fail);
555 TEST (T (0, 0, 0, 0), "99", 2, "e", 0, Eof | Fail);
556
557 // %h Equivalent to %b.
558 STEP ("%h: equivalent to %b");
559 TEST (T (0, 0, 0, 0, 0), "Jan", 3, "h", 0, Eof);
560 TEST (T (0, 0, 0, 0, 1), "February", 8, "h", 0, Good);
561 TEST (T (0, 0, 0, 0, 2), "Mar", 3, "h", 0, Eof);
562 TEST (T (0, 0, 0, 0, 3), "April", 5, "h", 0, Good);
563 TEST (T (0, 0, 0, 0, 4), "May", 3, "h", 0, Good);
564 TEST (T (0, 0, 0, 0, 5), "June", 4, "h", 0, Good);
565 TEST (T (0, 0, 0, 0, 6), "Jul", 3, "h", 0, Eof);
566 TEST (T (0, 0, 0, 0, 7), "August", 6, "h", 0, Good);
567 TEST (T (0, 0, 0, 0, 8), "Sep", 3, "h", 0, Eof);
568 TEST (T (0, 0, 0, 0, 9), "October", 7, "h", 0, Good);
569 TEST (T (0, 0, 0, 0, 10), "Nov", 3, "h", 0, Eof);
570 TEST (T (0, 0, 0, 0, 11), "December", 8, "h", 0, Good);
571
572 // %H The hour (24-hour clock) [00,23]; leading zeros are permitted
573 // but not required.
574 STEP ("%H: the hour (24-hour clock)");
575 TEST (T (0, 0, 0), "0", 1, "H", 0, Eof);
576 TEST (T (0, 0, 0), "00", 2, "H", 0, Eof);
577 TEST (T (0, 0, 0), "000", 3, "H", 0, Eof);
578 TEST (T (0, 0, 1), "1", 1, "H", 0, Eof);
579 TEST (T (0, 0, 2), "2", 1, "H", 0, Eof);
580 TEST (T (0, 0, 3), "3", 1, "H", 0, Eof);
581 TEST (T (0, 0, 11), "11", 2, "H", 0, Eof);
582 TEST (T (0, 0, 12), "12", 2, "H", 0, Eof);
583 TEST (T (0, 0, 13), "13", 2, "H", 0, Eof);
584 TEST (T (0, 0, 23), "23", 2, "H", 0, Eof);
585 TEST (T (0, 0, 23), "023", 3, "H", 0, Eof);
586 TEST (T (0, 0, 0), "024", 3, "H", 0, Eof | Fail);
587 TEST (T (0, 0, 0), "987", 3, "H", 0, Eof | Fail);
588
589 // %I The hour (12-hour clock) [01,12]; leading zeros are permitted
590 // but not required.
591 STEP ("%I: the hour (12-hour clock)");
592 TEST (T (0, 0, 0), "1", 1, "I", 0, Eof);
593 TEST (T (0, 0, 1), "2", 1, "I", 0, Eof);
594 TEST (T (0, 0, 2), "3", 1, "I", 0, Eof);
595 TEST (T (0, 0, 3), "4", 1, "I", 0, Eof);
596 TEST (T (0, 0, 4), "5", 1, "I", 0, Eof);
597 TEST (T (0, 0, 5), "6", 1, "I", 0, Eof);
598 TEST (T (0, 0, 6), "7", 1, "I", 0, Eof);
599 TEST (T (0, 0, 7), "8", 1, "I", 0, Eof);
600 TEST (T (0, 0, 8), "9", 1, "I", 0, Eof);
601 TEST (T (0, 0, 9), "10", 2, "I", 0, Eof);
602 TEST (T (0, 0, 10), "11", 2, "I", 0, Eof);
603 TEST (T (0, 0, 11), "12", 2, "I", 0, Eof);
604 TEST (T (0, 0, 0), "13", 2, "I", 0, Eof | Fail);
605 TEST (T (0, 0, 0), "013", 3, "I", 0, Eof | Fail);
606 TEST (T (0, 0, 0), "123", 3, "I", 0, Eof | Fail);
607 TEST (T (0, 0, 0), "0", 1, "I", 0, Eof | Fail);
608
609 // %j The day number of the year [001,366]; leading zeros are permitted
610 // but not required.
611 TEST (T (0, 0, 0, 0, 0, 0, 0, 0), "1", 1, "j", 0, Eof);
612 TEST (T (0, 0, 0, 0, 0, 0, 0, 1), "2", 1, "j", 0, Eof);
613 TEST (T (0, 0, 0, 0, 0, 0, 0, 2), "03", 2, "j", 0, Eof);
614 TEST (T (0, 0, 0, 0, 0, 0, 0, 9), "10", 2, "j", 0, Eof);
615 TEST (T (0, 0, 0, 0, 0, 0, 0, 364), "365", 3, "j", 0, Eof);
616 TEST (T (0, 0, 0, 0, 0, 0, 0, 365), "366", 3, "j", 0, Eof);
617 TEST (T (0, 0, 0, 0, 0, 0, 0, 0), "0", 1, "j", 0, Eof | Fail);
618 TEST (T (0, 0, 0, 0, 0, 0, 0, 0), "367", 3, "j", 0, Eof | Fail);
619
620#ifdef __GLIBC__
621
622 STEP ("%k: equivalent to %H (GNU glibc extension)");
623
624 TEST (T (0, 0, 0), "0", 1, "k", 0, Eof);
625 TEST (T (0, 0, 1), "1", 1, "k", 0, Eof);
626 TEST (T (0, 0, 9), "9", 1, "k", 0, Eof);
627 TEST (T (0, 0, 10), "10", 2, "k", 0, Eof);
628 TEST (T (0, 0, 11), "11", 2, "k", 0, Eof);
629 TEST (T (0, 0, 12), "12", 2, "k", 0, Eof);
630 TEST (T (0, 0, 13), "13", 2, "k", 0, Eof);
631 TEST (T (0, 0, 23), "23", 2, "k", 0, Eof);
632 TEST (T (0, 0, 23), "023", 3, "k", 0, Eof);
633 TEST (T (0, 0, 0), "024", 3, "k", 0, Eof | Fail);
634 TEST (T (0, 0, 0), "987", 3, "k", 0, Eof | Fail);
635
636#endif // __GLIBC__
637
638 // %m The month number [01,12]; leading zeros are permitted
639 // but not required.
640 STEP ("%m: the month number");
641 TEST (T (0, 0, 0, 0, 0, 0), "1", 1, "m", 0, Eof);
642 TEST (T (0, 0, 0, 0, 1, 0), "2", 1, "m", 0, Eof);
643 TEST (T (0, 0, 0, 0, 2, 0), "3", 1, "m", 0, Eof);
644 TEST (T (0, 0, 0, 0, 3, 0), "4", 1, "m", 0, Eof);
645 TEST (T (0, 0, 0, 0, 4, 0), "5", 1, "m", 0, Eof);
646 TEST (T (0, 0, 0, 0, 5, 0), "6", 1, "m", 0, Eof);
647 TEST (T (0, 0, 0, 0, 6, 0), "7", 1, "m", 0, Eof);
648 TEST (T (0, 0, 0, 0, 7, 0), "8", 1, "m", 0, Eof);
649 TEST (T (0, 0, 0, 0, 8, 0), "9", 1, "m", 0, Eof);
650 TEST (T (0, 0, 0, 0, 9, 0), "10", 2, "m", 0, Eof);
651 TEST (T (0, 0, 0, 0, 10, 0), "11", 2, "m", 0, Eof);
652 TEST (T (0, 0, 0, 0, 11, 0), "12", 2, "m", 0, Eof);
653 TEST (T (0, 0, 0, 0, 0, 0), "01", 2, "m", 0, Eof);
654 TEST (T (0, 0, 0, 0, 1, 0), "02", 2, "m", 0, Eof);
655 TEST (T (0, 0, 0, 0, 0, 0), "0", 1, "m", 0, Eof | Fail);
656 TEST (T (0, 0, 0, 0, 0, 0), "13", 2, "m", 0, Eof | Fail);
657
658 // %M The minute [00,59]; leading zeros are permitted but not required.
659 STEP ("%M: the minute");
660 TEST (T (0, 0), "0", 1, "M", 0, Eof);
661 TEST (T (0, 0), "00", 2, "M", 0, Eof);
662 TEST (T (0, 0), "000", 3, "M", 0, Eof);
663 TEST (T (0, 1), "1", 1, "M", 0, Eof);
664 TEST (T (0, 2), "2", 1, "M", 0, Eof);
665 TEST (T (0, 19), "19", 2, "M", 0, Eof);
666 TEST (T (0, 29), "29", 2, "M", 0, Eof);
667 TEST (T (0, 59), "59", 2, "M", 0, Eof);
668 TEST (T (0, 0), "60", 2, "M", 0, Eof | Fail);
669
670 // %n Any white space.
671 STEP ("%n: any whitespace");
672 TEST (T (), "", 0, "n", 0, Eof);
673 TEST (T (), " ", 1, "n", 0, Eof);
674 TEST (T (), " ", 2, "n", 0, Eof);
675 TEST (T (), " ", 3, "n", 0, Eof);
676 TEST (T (), "\n ", 2, "n", 0, Eof);
677 TEST (T (), " \t", 2, "n", 0, Eof);
678 TEST (T (), "\n\t", 2, "n", 0, Eof);
679 TEST (T (), ".", 0, "n", 0, Good);
680 TEST (T (), " 1", 1, "n", 0, Good);
681 TEST (T (), "\t 2", 2, "n", 0, Good);
682
683 // %p The locale's equivalent of a.m or p.m.
684 STEP ("%p: the equivalent of AM/PM");
685 TEST (T (0, 0, 1), "AM", 2, "p", 0, Good);
686 TEST (T (0, 0, 13), "PM", 2, "p", 0, Good);
687 TEST (T (0, 0, 0), "", 0, "p", 0, Eof | Fail);
688 TEST (T (0, 0, 0), "A", 1, "p", 0, Eof | Fail);
689 TEST (T (0, 0, 0), "P", 1, "p", 0, Eof | Fail);
690 TEST (T (0, 0, 0), "M", 0, "p", 0, Fail);
691 TEST (T (0, 0, 0), "A ", 1, "p", 0, Fail);
692 TEST (T (0, 0, 0), "P ", 1, "p", 0, Fail);
693
694 // %r 12-hour clock time using the AM/PM notation if t_fmt_ampm is
695 // not an empty string in the LC_TIME portion of the current locale;
696 // in the POSIX locale, this shall be equivalent to %I:%M:%S %p.
697 STEP ("%r: 12-hour clock time using the AM/PM notation");
698 rw_warn (0, 0, __LINE__, "%%r not being exercised");
699
700
701 // %R The time as %H:%M.
702 STEP ("%R: the time as %H:%M");
703 TEST (T (0, 0, 0), "0:0", 3, "R", 0, Eof);
704 TEST (T (0, 1, 0), "0:1", 3, "R", 0, Eof);
705 TEST (T (0, 2, 0), "0:02", 4, "R", 0, Eof);
706 TEST (T (0, 59, 0), "0:59", 4, "R", 0, Eof);
707 TEST (T (0, 48, 1), "1:48", 4, "R", 0, Eof);
708 TEST (T (0, 37, 11), "11:37", 5, "R", 0, Eof);
709 TEST (T (0, 26, 19), "19:26", 5, "R", 0, Eof);
710 TEST (T (0, 15, 22), "22:15", 5, "R", 0, Eof);
711 TEST (T (0, 4, 23), "23:04", 5, "R", 0, Eof);
712 TEST (T (0, 3, 23), "23:03:00", 5, "R", 0, Good);
713 TEST (T (0, 2, 23), "23:2:01", 4, "R", 0, Good);
714 TEST (T (0, 0, 0), "23:60", 5, "R", 0, Eof | Fail);
715 TEST (T (0, 0, 0), "24:00", 2, "R", 0, Fail);
716
717 // %S The seconds [00,60]; leading zeros are permitted but not required.
718 STEP ("%S: the seconds");
719 TEST (T ( 0), "0", 1, "S", 0, Eof);
720 TEST (T ( 1), "01", 2, "S", 0, Eof);
721 TEST (T ( 2), "002", 3, "S", 0, Eof);
722 TEST (T (13), "13", 2, "S", 0, Eof);
723 TEST (T (24), "24", 2, "S", 0, Eof);
724 TEST (T (34), "34", 2, "S", 0, Eof);
725 TEST (T (45), "45", 2, "S", 0, Eof);
726 TEST (T (56), "56", 2, "S", 0, Eof);
727 TEST (T (60), "60", 2, "S", 0, Eof);
728 TEST (T ( 0), "61", 2, "S", 0, Eof | Fail);
729
730 // %t Any white space.
731 STEP ("%t: any whitespace");
732 TEST (T (), "\t", 1, "t", 0, Eof);
733 TEST (T (), " ", 1, "t", 0, Eof);
734 TEST (T (), " ", 2, "t", 0, Eof);
735 TEST (T (), "\n ", 2, "t", 0, Eof);
736
737 // %T The time as %H:%M:%S.
738 STEP ("%T: the time as %H:%M:%S");
739 TEST (T ( 0, 0, 0), "0:0:00", 6, "T", 0, Eof);
740 TEST (T ( 1, 1, 0), "0:1:1", 5, "T", 0, Eof);
741 TEST (T ( 2, 2, 0), "0:02:2", 6, "T", 0, Eof);
742 TEST (T ( 3, 59, 0), "0:59:3", 6, "T", 0, Eof);
743 TEST (T ( 4, 48, 1), "1:48:04", 7, "T", 0, Eof);
744 TEST (T ( 5, 37, 11), "11:37:5", 7, "T", 0, Eof);
745 TEST (T ( 6, 26, 19), "19:26:006", 9, "T", 0, Eof);
746 TEST (T ( 7, 15, 22), "22:015:7", 8, "T", 0, Eof);
747 TEST (T ( 8, 4, 23), "023:004:8", 9, "T", 0, Eof);
748 TEST (T (60, 59, 23), "023:59:60", 9, "T", 0, Eof);
749 TEST (T ( 0, 0, 0), "23:59:61", 8, "T", 0, Eof | Fail);
750 TEST (T ( 0, 0, 0), "0:0:62", 6, "T", 0, Eof | Fail);
751 TEST (T ( 0, 0, 0), "0:0", 3, "T", 0, Eof | Fail);
752 TEST (T ( 0, 0, 0), "999", 3, "T", 0, Eof | Fail);
753
754 // %U The week number of the year (Sunday as the first day of the week)
755 // as a decimal number [00,53]; leading zeros are permitted but not
756 // required.
757 STEP ("%U: the Sunday-based week of the year");
758 rw_warn (0, 0, __LINE__, "%%U not being exercised");
759
760 // %w The weekday as a decimal number [0,6], with 0 representing
761 // Sunday; leading zeros are permitted but not required.
762 STEP ("%w: the Sunday-based weekday as a decimal number");
763 TEST (T (0, 0, 0, 0, 0, 0, 0), "0", 1, "w", 0, Eof);
764 TEST (T (0, 0, 0, 0, 0, 0, 0), "00", 2, "w", 0, Eof);
765 TEST (T (0, 0, 0, 0, 0, 0, 1), "1", 1, "w", 0, Eof);
766 TEST (T (0, 0, 0, 0, 0, 0, 1), "01", 2, "w", 0, Eof);
767 TEST (T (0, 0, 0, 0, 0, 0, 2), "2", 1, "w", 0, Eof);
768 TEST (T (0, 0, 0, 0, 0, 0, 3), "3", 1, "w", 0, Eof);
769 TEST (T (0, 0, 0, 0, 0, 0, 4), "4", 1, "w", 0, Eof);
770 TEST (T (0, 0, 0, 0, 0, 0, 5), "5", 1, "w", 0, Eof);
771 TEST (T (0, 0, 0, 0, 0, 0, 6), "6", 1, "w", 0, Eof);
772 TEST (T (0, 0, 0, 0, 0, 0, 0), "7", 1, "w", 0, Eof | Fail);
773
774 // %W The week number of the year (Monday as the first day of the
775 // week) as a decimal number [00,53]; leading zeros are permitted
776 // but not required.
777 STEP ("%W: the Monday-based week of the year");
778 rw_warn (0, 0, __LINE__, "%%W not being exercised");
779
780 // %x The date, using the locale's date format.
781 STEP ("%x: the date");
782 TEST (T (0, 0, 0, 25, 6, 67), "7/25/1967", 9, "%x", 0, Eof);
783
784 // %X The time, using the locale's time format.
785 STEP ("%X: the time");
786 TEST (T (12, 34, 5), "5:34:12", 7, "%X", 0, Eof);
787 TEST (T (23, 45, 6), " 6:45:23", 8, " %X", 0, Eof);
788
789 // %y The year within century. When a century is not otherwise
790 // specified, values in the range [69,99] shall refer to years 1969
791 // to 1999 inclusive, and values in the range [00,68] shall refer
792 // to years 2000 to 2068 inclusive; leading zeros shall be permitted
793 // but shall not be required.
794 // Note: It is expected that in a future version of
795 // IEEE Std 1003.1-2001 the default century inferred from a
796 // 2-digit year will change. (This would apply to all commands
797 // accepting a 2-digit year as input.)
798 STEP ("%y: the year within century");
799 TEST (T (0, 0, 0, 0, 0, 100), "0", 1, "%y", 0, Eof);
800 TEST (T (0, 0, 0, 0, 0, 100), "00", 2, "%y", 0, Eof);
801 TEST (T (0, 0, 0, 0, 0, 101), "1", 1, "%y", 0, Eof);
802 TEST (T (0, 0, 0, 0, 0, 102), "2", 1, "%y", 0, Eof);
803 TEST (T (0, 0, 0, 0, 0, 103), "03", 2, "%y", 0, Eof);
804 TEST (T (0, 0, 0, 0, 0, 168), "68", 2, "%y", 0, Eof);
805 TEST (T (0, 0, 0, 0, 0, 69), "69", 2, "%y", 0, Eof);
806 TEST (T (0, 0, 0, 0, 0, 99), "99", 2, "%y", 0, Eof);
807 TEST (T (0, 0, 0, 0, 0, -1800), "100", 3, "%y", 0, Eof);
808 TEST (T (0, 0, 0, 0, 0, 102), "2002", 4, "%y", 0, Eof);
809
810 // %Y The year, including the century (for example, 1988).
811 STEP ("%Y: the year, including the century");
812 TEST (T (0, 0, 0, 0, 0, -1900), "0", 1, "%Y", 0, Eof);
813 TEST (T (0, 0, 0, 0, 0, -1900), " 0", 2, " %Y", 0, Eof);
814 TEST (T (0, 0, 0, 0, 0, 99), "\t1999", 5, " %Y", 0, Eof);
815
816 STEP ("invalid pattern");
817 TEST (T (0), "0", 0, "E", 0, Fail);
818 TEST (T (0), "0", 0, "i", 0, Fail);
819 TEST (T (0), "0", 0, "J", 0, Fail);
820 TEST (T (0), "0", 0, "N", 0, Fail);
821 TEST (T (0), "0", 0, "P", 0, Fail);
822 TEST (T (0), "0", 0, "s", 0, Fail);
823 TEST (T (0), "0", 0, "u", 0, Fail);
824 TEST (T (0), "0", 0, "z", 0, Fail);
825 TEST (T (0), "0", 0, "Z", 0, Fail);
826
827
828 // %Ec The locale's alternative date and time representation.
829 // %EC The name of the base year (period) in the locale's alternative
830 // representation.
831 // %Ex The locale's alternative date representation.
832 // %EX The locale's alternative time representation.
833 // %Ey The offset from %EC (year only) in the locale's alternative
834 // representation.
835 // %EY The full alternative year representation.
836 // %Od The day of the month using the locale's alternative numeric
837 // symbols; leading zeros are permitted but not required.
838 // %Oe Equivalent to %Od.
839 // %OH The hour (24-hour clock) using the locale's alternative numeric
840 // symbols.
841 // %OI The hour (12-hour clock) using the locale's alternative numeric
842 // symbols.
843 // %Om The month using the locale's alternative numeric symbols.
844 // %OM The minutes using the locale's alternative numeric symbols.
845 // %OS The seconds using the locale's alternative numeric symbols.
846 // %OU The week number of the year (Sunday as the first day of the week)
847 // using the locale's alternative numeric symbols.
848 // %Ow The number of the weekday (Sunday=0) using the locale's
849 // alternative numeric symbols.
850 // %OW The week number of the year (Monday as the first day of the
851 // week) using the locale's alternative numeric symbols.
852 // %Oy The year (offset from %C ) using the locale's alternative numeric
853 // symbols.
854 rw_warn (0, 0, __LINE__, "E modifier not being exercised");
855 rw_warn (0, 0, __LINE__, "O modifier not being exercised");
856
857 // exercise pattern strings containing multiple format specifiers
858 TEST (T (0, 0, 0, 0, 0, 0, 0), "Sun Jan", 7, "%a %b", 0, Eof);
859 TEST (T (0, 0, 0, 0, 1, 0, 1), "Mon Feb", 8, "%a %b", 0, Eof);
860 TEST (T (0, 0, 0, 0, 2, 0, 2), "Tue%nMar", 7, "%a %b", 0, Eof);
861 TEST (T (0, 0, 0, 0, 3, 0, 3), "Wed%t Apr", 8, "%a %b", 0, Eof);
862 TEST (T (0, 0, 0, 0, 2, 0, 5), "Friday March", 12, "%a %b", 0, Good);
863}
864
865
868template <class charT>
869void test_english (charT, const char *cname, const char *locname)
870{
871 _TRY {
872 // set the global locale object to the german locale
873 std::locale::global (std::locale (locname));
874 }
875 _CATCH (...) {
876 rw_error (0, 0, __LINE__,
877 "locale(%#s) unexpectedly threw an exception", locname);
878
879 return;
880 }
881
882 // exercise abbreviated weekday names
883 FUNCTION ("get_weekday");
884 TEST (T (0, 0, 0, 0, 0, 0, 0), "Sun", 3, "a", 0, Eof);
885 TEST (T (0, 0, 0, 0, 0, 0, 1), "Mon", 3, "a", 0, Eof);
886 TEST (T (0, 0, 0, 0, 0, 0, 2), "Tue", 3, "a", 0, Eof);
887 TEST (T (0, 0, 0, 0, 0, 0, 3), "Wed", 3, "a", 0, Eof);
888 TEST (T (0, 0, 0, 0, 0, 0, 4), "Thu", 3, "a", 0, Eof);
889 TEST (T (0, 0, 0, 0, 0, 0, 5), "Fri", 3, "a", 0, Eof);
890 TEST (T (0, 0, 0, 0, 0, 0, 6), "Sat", 3, "a", 0, Eof);
891
892 // exercise full weekday names
893 TEST (T (0, 0, 0, 0, 0, 0, 0), "Sunday", 6, "a", 0, Good);
894 TEST (T (0, 0, 0, 0, 0, 0, 1), "Monday", 6, "a", 0, Good);
895 TEST (T (0, 0, 0, 0, 0, 0, 2), "Tuesday", 7, "a", 0, Good);
896 TEST (T (0, 0, 0, 0, 0, 0, 3), "Wednesday", 9, "a", 0, Good);
897 TEST (T (0, 0, 0, 0, 0, 0, 4), "Thursday", 8, "a", 0, Good);
898 TEST (T (0, 0, 0, 0, 0, 0, 5), "Friday", 6, "a", 0, Good);
899 TEST (T (0, 0, 0, 0, 0, 0, 6), "Saturday", 8, "a", 0, Good);
900
901 // exercise full month names
902 FUNCTION ("get_monthname");
903 TEST (T (0, 0, 0, 0, 0), "%B", -1, "b", 0, -1);
904 TEST (T (0, 0, 0, 0, 1), "%B", -1, "b", 0, -1);
905 TEST (T (0, 0, 0, 0, 2), "%B", -1, "b", 0, -1);
906 TEST (T (0, 0, 0, 0, 3), "%B", -1, "b", 0, -1);
907 TEST (T (0, 0, 0, 0, 4), "%B", -1, "b", 0, -1);
908 TEST (T (0, 0, 0, 0, 5), "%B", -1, "b", 0, -1);
909 TEST (T (0, 0, 0, 0, 6), "%B", -1, "b", 0, -1);
910 TEST (T (0, 0, 0, 0, 7), "%B", -1, "b", 0, -1);
911 TEST (T (0, 0, 0, 0, 8), "%B", -1, "b", 0, -1);
912 TEST (T (0, 0, 0, 0, 9), "%B", -1, "b", 0, -1);
913 TEST (T (0, 0, 0, 0, 10), "%B", -1, "b", 0, -1);
914 TEST (T (0, 0, 0, 0, 11), "%B", -1, "b", 0, -1);
915
916 // exercise date (time_get::get_date())
917 FUNCTION ("get_date");
918 TEST (T (0, 0, 0, 1, 0, 100), "%x", 8, "x", 0, Eof);
919
920 // exercise time (time_get::get_time())
921 FUNCTION ("get_time");
922
923 int len;
924
925 {
926 // determine whether "%X" is equivalent to "%I:%M:%S %p"
927 // (e.g., HP-UX or Linux) or to "%I:%M:%S" (e.g., Compaq
928 // Tru64 UNIX)
929 char buf [32];
930 const std::tm tmb = mktm (0, 0, 1);
931 len = int (std::strftime (buf, sizeof buf, "%X", &tmb));
932 }
933
934 const int hour = 11 == len ? 12 : 0;
935
936 TEST (T ( 0, 0, 0), "%X", len, "X", 0, 11 == len ? Good : Eof);
937 TEST (T ( 0, 0, 1), "%X", len, "X", 0, 11 == len ? Good : Eof);
938 TEST (T ( 0, 0, 11), "%X", len, "X", 0, 11 == len ? Good : Eof);
939 TEST (T ( 0, 0, 12), "%X", len, "X", 0, 11 == len ? Good : Eof);
940 TEST (T ( 0, 0, 13), "%X", len, "X", 0, 11 == len ? Good : Eof);
941 TEST (T ( 0, 0, 23), "%X", len, "X", 0, 11 == len ? Good : Eof);
942
943 TEST (T ( 0, 0, 12 - hour), "12:00:00 AM", len, "X", 0, Good);
944 TEST (T ( 0, 0, 1), "01:00:00 AM", len, "X", 0, Good);
945 TEST (T ( 0, 0, 2), "02:00:00 AM", len, "X", 0, Good);
946 TEST (T ( 0, 0, 3), "03:00:00 AM", len, "X", 0, Good);
947 TEST (T ( 0, 0, 4), "04:00:00 AM", len, "X", 0, Good);
948 TEST (T ( 0, 0, 5), "05:00:00 AM", len, "X", 0, Good);
949 TEST (T ( 0, 0, 6), "06:00:00 AM", len, "X", 0, Good);
950 TEST (T ( 0, 0, 7), "07:00:00 AM", len, "X", 0, Good);
951 TEST (T ( 0, 0, 8), "08:00:00 AM", len, "X", 0, Good);
952 TEST (T ( 0, 0, 9), "09:00:00 AM", len, "X", 0, Good);
953 TEST (T ( 0, 0, 10), "10:00:00 AM", len, "X", 0, Good);
954 TEST (T ( 0, 0, 11), "11:00:00 AM", len, "X", 0, Good);
955
956 TEST (T ( 0, 0, 12), "12:00:00 PM", len, "X", 0, Good);
957 TEST (T ( 0, 0, hour + 1), "01:00:00 PM", len, "X", 0, Good);
958 TEST (T ( 0, 0, hour + 2), "02:00:00 PM", len, "X", 0, Good);
959 TEST (T ( 0, 0, hour + 3), "03:00:00 PM", len, "X", 0, Good);
960 TEST (T ( 0, 0, hour + 4), "04:00:00 PM", len, "X", 0, Good);
961 TEST (T ( 0, 0, hour + 5), "05:00:00 PM", len, "X", 0, Good);
962 TEST (T ( 0, 0, hour + 6), "06:00:00 PM", len, "X", 0, Good);
963 TEST (T ( 0, 0, hour + 7), "07:00:00 PM", len, "X", 0, Good);
964 TEST (T ( 0, 0, hour + 8), "08:00:00 PM", len, "X", 0, Good);
965 TEST (T ( 0, 0, hour + 9), "09:00:00 PM", len, "X", 0, Good);
966 TEST (T ( 0, 0, hour + 10), "10:00:00 PM", len, "X", 0, Good);
967 TEST (T ( 0, 0, hour + 11), "11:00:00 PM", len, "X", 0, Good);
968
969 TEST (T (60, 9, hour + 11), "11:09:60 PM", len, "X", 0, Good);
970}
971
972
975template <class charT>
976void test_german (charT, const char *cname, const char *locname)
977{
978 _TRY {
979 // set the global locale object to the german locale
980 std::locale::global (std::locale (locname));
981 }
982 _CATCH (...) {
983 rw_error (0, 0, __LINE__,
984 "locale(%#s) unexpectedly threw an exception", locname);
985
986 return;
987 }
988
989 // exercise abbreviated weekday names
990 // these may be { So, Mo, Di, Mi, Do, Sa } (e.g., Compaq Tru64 UNIX)
991 // or { Son, Mon, Die, Mit, Don, Sam } (e.g., Linux, SunOS, or Win32)
992 FUNCTION ("get_weekday");
993 TEST (T (0, 0, 0, 0, 0, 0, 0), "%a", -1, "a", 0, Eof);
994 TEST (T (0, 0, 0, 0, 0, 0, 1), "%a", -1, "a", 0, Eof);
995 TEST (T (0, 0, 0, 0, 0, 0, 2), "%a", -1, "a", 0, Eof);
996 TEST (T (0, 0, 0, 0, 0, 0, 3), "%a", -1, "a", 0, Eof);
997 TEST (T (0, 0, 0, 0, 0, 0, 4), "%a", -1, "a", 0, Eof);
998 TEST (T (0, 0, 0, 0, 0, 0, 5), "%a", -1, "a", 0, Eof);
999 TEST (T (0, 0, 0, 0, 0, 0, 6), "%a", -1, "a", 0, Eof);
1000
1001 // exercise full weekday names
1002 TEST (T (0, 0, 0, 0, 0, 0, 0), "Sonntag", 7, "a", 0, Good);
1003 TEST (T (0, 0, 0, 0, 0, 0, 1), "Montag", 6, "a", 0, Good);
1004 TEST (T (0, 0, 0, 0, 0, 0, 2), "Dienstag", 8, "a", 0, Good);
1005 TEST (T (0, 0, 0, 0, 0, 0, 3), "Mittwoch", 8, "a", 0, Good);
1006 TEST (T (0, 0, 0, 0, 0, 0, 4), "Donnerstag", 10, "a", 0, Good);
1007 TEST (T (0, 0, 0, 0, 0, 0, 5), "Freitag", 7, "a", 0, Good);
1008 TEST (T (0, 0, 0, 0, 0, 0, 6), "Samstag", 7, "a", 0, Good);
1009
1010 // exercise full month names
1011 FUNCTION ("get_monthname");
1012 TEST (T (0, 0, 0, 0, 0), "%B", -1, "b", 0, -1);
1013 TEST (T (0, 0, 0, 0, 1), "%B", -1, "b", 0, -1);
1014 TEST (T (0, 0, 0, 0, 2), "%B", -1, "b", 0, -1);
1015 TEST (T (0, 0, 0, 0, 3), "%B", -1, "b", 0, -1);
1016 TEST (T (0, 0, 0, 0, 4), "%B", -1, "b", 0, -1);
1017 TEST (T (0, 0, 0, 0, 5), "%B", -1, "b", 0, -1);
1018 TEST (T (0, 0, 0, 0, 6), "%B", -1, "b", 0, -1);
1019 TEST (T (0, 0, 0, 0, 7), "%B", -1, "b", 0, -1);
1020 TEST (T (0, 0, 0, 0, 8), "%B", -1, "b", 0, -1);
1021 TEST (T (0, 0, 0, 0, 9), "%B", -1, "b", 0, -1);
1022 TEST (T (0, 0, 0, 0, 10), "%B", -1, "b", 0, -1);
1023 TEST (T (0, 0, 0, 0, 11), "%B", -1, "b", 0, -1);
1024}
1025
1026
1029template <class charT>
1030void test_danish (charT, const char *cname, const char *locname)
1031{
1032 _TRY {
1033 // set the global locale object to the german locale
1034 std::locale::global (std::locale (locname));
1035 }
1036 _CATCH (...) {
1037 rw_error (0, 0, __LINE__,
1038 "locale(%#s) unexpectedly threw an exception", locname);
1039
1040 return;
1041 }
1042
1043 // exercise abbreviated weekday names
1044 FUNCTION ("get_weekday");
1045 TEST (T (0, 0, 0, 0, 0, 0, 0), "%a", 3, "a", 0, Eof);
1046 TEST (T (0, 0, 0, 0, 0, 0, 1), "%a", 3, "a", 0, Eof);
1047 TEST (T (0, 0, 0, 0, 0, 0, 2), "%a", 3, "a", 0, Eof);
1048 TEST (T (0, 0, 0, 0, 0, 0, 3), "%a", 3, "a", 0, Eof);
1049 TEST (T (0, 0, 0, 0, 0, 0, 4), "%a", 3, "a", 0, Eof);
1050 TEST (T (0, 0, 0, 0, 0, 0, 5), "%a", 3, "a", 0, Eof);
1051 TEST (T (0, 0, 0, 0, 0, 0, 6), "%a", 3, "a", 0, Eof);
1052
1053 // avoid using <s><o/><n> or <s><o/><n><d><a><g> since it
1054 // contains the non-ASCII character <o/> (o with a slash)
1055 TEST (T (0, 0, 0, 0, 0, 0, 1), "man", 3, "a", 0, Eof);
1056 TEST (T (0, 0, 0, 0, 0, 0, 2), "tir", 3, "a", 0, Eof);
1057 TEST (T (0, 0, 0, 0, 0, 0, 3), "ons", 3, "a", 0, Eof);
1058 TEST (T (0, 0, 0, 0, 0, 0, 4), "tor", 3, "a", 0, Eof);
1059 TEST (T (0, 0, 0, 0, 0, 0, 5), "fre", 3, "a", 0, Eof);
1060
1061 TEST (T (0, 0, 0, 0, 0, 0, 1), "mandag", 6, "a", 0, Good);
1062 TEST (T (0, 0, 0, 0, 0, 0, 2), "tirsdag", 7, "a", 0, Good);
1063 TEST (T (0, 0, 0, 0, 0, 0, 3), "onsdag", 6, "a", 0, Good);
1064 TEST (T (0, 0, 0, 0, 0, 0, 4), "torsdag", 7, "a", 0, Good);
1065 TEST (T (0, 0, 0, 0, 0, 0, 5), "fredag", 6, "a", 0, Good);
1066
1067 // exercise full month names
1068 FUNCTION ("get_monthname");
1069 TEST (T (0, 0, 0, 0, 0), "%B", -1, "b", 0, -1);
1070 TEST (T (0, 0, 0, 0, 1), "%B", -1, "b", 0, -1);
1071 TEST (T (0, 0, 0, 0, 2), "%B", -1, "b", 0, -1);
1072 TEST (T (0, 0, 0, 0, 3), "%B", -1, "b", 0, -1);
1073 TEST (T (0, 0, 0, 0, 4), "%B", -1, "b", 0, -1);
1074 TEST (T (0, 0, 0, 0, 5), "%B", -1, "b", 0, -1);
1075 TEST (T (0, 0, 0, 0, 6), "%B", -1, "b", 0, -1);
1076 TEST (T (0, 0, 0, 0, 7), "%B", -1, "b", 0, -1);
1077 TEST (T (0, 0, 0, 0, 8), "%B", -1, "b", 0, -1);
1078 TEST (T (0, 0, 0, 0, 9), "%B", -1, "b", 0, -1);
1079 TEST (T (0, 0, 0, 0, 10), "%B", -1, "b", 0, -1);
1080 TEST (T (0, 0, 0, 0, 11), "%B", -1, "b", 0, -1);
1081}
1082
1083
1087{
1088 const char* abday [7]; // %a abbreviated day name
1089 const char* day [7]; // %A full day name
1090 const char* abmon [12]; // %b abbreviated month name
1091 const char* mon [12]; // %B full month name
1092 const char* am_pm [2]; // %p AM/PM designator
1093 const char* d_t_fmt; // %c date and time
1094 const char* d_fmt; // %x date
1095 const char* t_fmt; // %X time
1096 const char* t_fmt_ampm; // %r time with the AM/PM designaror
1097 const char* era_d_t_fmt; // %Ec alternative date and time
1098 const char* era_d_fmt; // %EX alternative date
1099 const char* era_t_fmt; // %Ex alternative time
1100 const char* const* alt_digits; // alternative numeric symbols
1101
1102 struct era_data {
1104 int start_day; // [1..31]
1105 int start_mon; // [0..11]
1107 int end_day; // [1..31]
1108 int end_mon; // [0..11]
1109 int end_year; // INT_MIN, [0..9999], INT_MAX
1110 const char *name;
1111 const char *format;
1112 };
1113
1115};
1116
1117
1118// the root of the locale directory (RWSTD_LOCALE_ROOT)
1119// set in main() instead of here to avoid Solaris 7 putenv() bug (PR #30017)
1120static const char*
1122
1123
1124static const char*
1125make_LC_TIME (const time_data *td)
1126{
1127 static char locnamebuf [1024];
1128
1129 if (*locnamebuf)
1130 return locnamebuf;
1131
1132 // create a temporary locale definition file
1133 char srcfname [1024];
1134 if (rw_snprintf (srcfname, sizeof srcfname, "%s%c%s",
1135 locale_root, _RWSTD_PATH_SEP, "LC_TIME.src") < 0)
1136 return 0;
1137
1138 std::FILE *fout = std::fopen (srcfname, "w");
1139 rw_fatal (0 != fout, 0, __LINE__,
1140 "fopen(%#s, \"w\") failed: %{#m} - %m", srcfname);
1141
1142 // rw_fatal() doesn't return on failure
1143 RW_ASSERT (0 != fout);
1144
1145 std::fprintf (fout, "LC_TIME\n");
1146
1147 unsigned i;
1148
1149 std::fprintf (fout, "abday ");
1150
1151 for (i = 0; i != sizeof td->abday / sizeof *td->abday; ++i) {
1152 std::fprintf (fout, "\"");
1153 pcs_write (fout, td->abday [i]);
1154 std::fprintf (fout, "\"%c", i < 6 ? ';' : '\n');
1155 }
1156
1157 std::fprintf (fout, "day ");
1158
1159 for (i = 0; i != sizeof td->day / sizeof *td->day; ++i) {
1160 std::fprintf (fout, "\"");
1161 pcs_write (fout, td->day [i]);
1162 std::fprintf (fout, "\"%c", i < 6 ? ';' : '\n');
1163 }
1164
1165 std::fprintf (fout, "abmon ");
1166
1167 for (i = 0; i != sizeof td->abmon / sizeof *td->abmon; ++i) {
1168 std::fprintf (fout, "\"");
1169 pcs_write (fout, td->abmon [i]);
1170 std::fprintf (fout, "\"%c", i < 11 ? ';' : '\n');
1171 }
1172
1173 std::fprintf (fout, "mon ");
1174
1175 for (i = 0; i != sizeof td->mon / sizeof *td->mon; ++i) {
1176 std::fprintf (fout, "\"");
1177 pcs_write (fout, td->mon [i]);
1178 std::fprintf (fout, "\"%c", i < 11 ? ';' : '\n');
1179 }
1180
1181 std::fprintf (fout, "am_pm ");
1182
1183 for (i = 0; i != sizeof td->am_pm / sizeof *td->am_pm; ++i) {
1184 std::fprintf (fout, "\"");
1185 pcs_write (fout, td->am_pm [i]);
1186 std::fprintf (fout, "\"%c", i < 1 ? ';' : '\n');
1187 }
1188
1189 // write out d_t_fmt, d_fmt, t_fmt, etc.
1190 // preface each line with a comment giving
1191 // the specification in a human-readable format
1192 std::fprintf (fout, "\n# d_t_fmt \"%s\"\nd_t_fmt \"",
1193 td->d_t_fmt);
1194 pcs_write (fout, td->d_t_fmt);
1195
1196 std::fprintf (fout, "\"\n\n# d_fmt \"%s\"\nd_fmt \"",
1197 td->d_fmt);
1198 pcs_write (fout, td->d_fmt);
1199
1200 std::fprintf (fout, "\"\n\n# t_fmt \"%s\"\nt_fmt \"",
1201 td->t_fmt);
1202 pcs_write (fout, td->t_fmt);
1203
1204 std::fprintf (fout, "\"\n\n# t_fmt_ampm \"%s\"\nt_fmt_ampm \"",
1205 td->t_fmt_ampm);
1206 pcs_write (fout, td->t_fmt_ampm);
1207
1208 std::fprintf (fout, "\"\n\n# era_d_t_fmt \"%s\"\nera_d_t_fmt \"",
1209 td->era_d_t_fmt);
1210 pcs_write (fout, td->era_d_t_fmt);
1211
1212 std::fprintf (fout, "\"\n\n# era_d_fmt \"%s\"\nera_d_fmt \"",
1213 td->era_d_fmt);
1214 pcs_write (fout, td->era_d_fmt);
1215
1216 std::fprintf (fout, "\"\n\n# era_t_fmt \"%s\"\nera_t_fmt \"",
1217 td->era_t_fmt);
1218 pcs_write (fout, td->era_t_fmt);
1219
1220 std::fprintf (fout, "\"\nalt_digits ");
1221
1222 for (i = 0; td->alt_digits [i]; ++i) {
1223 std::fprintf (fout, "\"");
1224 pcs_write (fout, td->alt_digits [i]);
1225 std::fprintf (fout, "\"%c", td->alt_digits [i + 1] ? ';' : '\n');
1226 }
1227
1228 std::fprintf (fout, "\n\nera ");
1229
1230 for (i = 0; INT_MIN != td->era [i].offset; ++i) {
1231
1232 char segment [256];
1233
1234 std::sprintf (segment, "%c:%d:%04d/%02d/%02d:",
1235 td->era [i].offset < 0 ? '-' : '+',
1236 td->era [i].offset < 0 ? -td->era [i].offset
1237 : td->era [i].offset,
1238 td->era [i].start_year + 1900,
1239 td->era [i].start_mon + 1,
1240 td->era [i].start_day);
1241
1242 const char *end_date = 0;
1243
1244 if (INT_MIN == td->era [i].end_year)
1245 end_date = "-*"; // beginning of time
1246 else if (INT_MAX == td->era [i].end_year)
1247 end_date = "+*"; // end of time
1248
1249 if (end_date) {
1250 std::sprintf (segment + std::strlen (segment), "%s:%s:%s",
1251 end_date, td->era [i].name, td->era [i].format);
1252 }
1253 else {
1254 std::sprintf (segment + std::strlen (segment),
1255 "%04d/%02d/%02d:%s:%s",
1256 td->era [i].end_year + 1900,
1257 td->era [i].end_mon + 1,
1258 td->era [i].end_day,
1259 td->era [i].name,
1260 td->era [i].format);
1261 }
1262
1263 std::fprintf (fout, "\"");
1264 pcs_write (fout, segment);
1265 std::fprintf (fout, "\"%c",
1266 INT_MIN == td->era [i + 1].offset ? '\n' : ';');
1267 }
1268
1269 std::fprintf (fout, "\nEND LC_TIME\n");
1270
1271 std::fclose (fout);
1272
1273 // create a temporary character map file
1274 char cmfname [1024];
1275 if (rw_snprintf (cmfname, sizeof cmfname, "%s%c%s",
1276 locale_root, _RWSTD_PATH_SEP, "LC_TIME.cm") < 0)
1277 return 0;
1278
1279 fout = std::fopen (cmfname, "w");
1280 rw_fatal (0 != fout, 0, __LINE__,
1281 "fopen(%#s, \"w\") failed: %{#m} - %m", cmfname);
1282
1283 // rw_fatal() doesn't return on failure
1284 RW_ASSERT (0 != fout);
1285
1286 pcs_write (fout, 0);
1287
1288 std::fclose (fout);
1289
1290 // process the locale definition file and the character map
1291 const char* const locname =
1292 rw_localedef ("-w ", srcfname, cmfname, "test-locale");
1293
1294 if (locname && (std::strlen(locname) < sizeof locnamebuf))
1295 std::strcpy (locnamebuf, locname);
1296
1297 return locname;
1298}
1299
1300
1301static const char*
1302make_LC_TIME ()
1303{
1304 const char* const alt_digits[] = {
1305 "", "1st", "2nd", "3rd", "4th",
1306 "5th", "6th", "7th", "8th", "9th",
1307 "10th", "11th", "12th", "13th", "14th",
1308 "15th", "16th", "17th", "18th", "19th",
1309 "20th", "21st", "22nd", "23rd", "24th",
1310 "25th", "26th", "27th", "28th", "29th",
1311 "30th", "31st", 0 // sentinel
1312 };
1313
1314 const time_data::era_data era[] = {
1315 // some entries copied and modified from HP-UX 11.11 ja_JP.utf8
1316 //
1317 // # 1990-01-02 and onward: "Heisei%EyNen" (1990 is Heisei 2 Nen.)
1318 // # 1990-01-01 to 1990-01-02: "%C" (no era specified)
1319 // # 1989-01-08 to 1989-12-31: "HeiseiGannen"
1320 // # 1927-01-01 to 1989-01-07: "Showa%EyNen" (1927 is Showa 2 Nen.)
1321 // # 1927-01-01 and prior: "foo"
1322 // era "+:2:1990/01/02:+*:<U????><U????>:%EC%Ey<U????>";
1323 // "+:1:1989/01/08:1989/12/31:<U????>:%EC<U????><U????>";
1324 // "+:2:1927/01/01:1989/01/07:<U????><U????>:%EC%Ey<U????>";
1325 // "-:7:1926/12/31:-*:foo:bar%EC%Ey"
1326
1327 // 7|2 |1 | |2 starting year in an era
1328 // <<<|>>>>>>>>>|>>>>>>>>>|.|>>> direction in which years increase
1329 // ^ ^ ^ ^
1330 // | | | |
1331 // | | | +-> Jan 2, 1990 (Heisei %Ey Nen)
1332 // | | +-> Dec 31, 1989 (%C)
1333 // | +-> Jan 7, 1989 (Heisei Gannen)
1334 // +-> Jan 1, 1927 (Showa %Ey Nen)
1335 // +-< Dec 31, 1926 (foobar %Ey)
1336
1337 { 2, 2, 0, 90, 0, 0, INT_MAX, "Heisei", "%EC %Ey Nen" },
1338 { 1, 8, 0, 89, 31, 11, 89, "Heisei", "%EC Gannen" },
1339 { 2, 1, 0, 27, 7, 0, 89, "Showa", "%EC %Ey Nen" },
1340 { -7, 31, 11, 26, 0, 0, INT_MIN, "bar", "foo%EC %Ey" },
1341 { INT_MIN /* sentinel entry */, 0, 0, 0, 0, 0, 0, 0, 0 }
1342 };
1343
1344 const time_data td = {
1345 // %a
1346 { "[Sun]", "[Mon]", "[Tue]", "[Wed]", "[Thu]", "[Fri]", "[Sat]" },
1347
1348 // %A
1349 {
1350 "[Sunday]", "[Monday]", "[Tuesday]", "[Wednesday]", "[Thursday]",
1351 "[Friday]", "[Saturday]"
1352 },
1353
1354 // %b
1355 {
1356 "[Jan]", "[Feb]", "[Mar]", "[Apr]", "[May]", "[Jun]",
1357 "[Jul]", "[Aug]", "[Sep]", "[Oct]", "[Nov]", "[Dec]",
1358 },
1359
1360 // %B
1361 {
1362 "[January]", "[February]", "[March]", "[April]", "[May]", "[June]",
1363 "[July]", "[August]", "[September]", "[October]", "[November]",
1364 "[December]",
1365 },
1366
1367 { "[A.M.]", "[P.M.]" }, // %p
1368
1369 "[[%a][%b][%d][%H][%M][%S][%y]]", // %c
1370 "[[%3m][%.4d][%4.3y]]", // %x
1371 "[[%3H][%.4M][%4.3S]]", // %X
1372 "[[%I][%M][%S][%p]]", // %r
1373 "[[%A][%B][%Od][%H][%M][%S][%Y]]", // %Ec
1374 "%Ow weekday, %OU week, %Oy year", // %Ex
1375 "%OH hour, %OM minute, %OS second", // %EX
1376
1377 alt_digits, era
1378 };
1379
1380 const char* const locname = make_LC_TIME (&td);
1381
1382 return locname;
1383}
1384
1385
1388template <class charT>
1389void test_user (charT, const char *cname, const char *locname)
1390{
1391 const char* const envar = std::getenv (LOCALE_ROOT_ENVAR);
1392
1393 rw_info (0, 0, __LINE__,
1394 "std::time_get<%s>, in locale(\"%s\") "
1395 "created from a generated LC_TIME file; "
1396 LOCALE_ROOT_ENVAR "=%s",
1397 cname, locname, envar);
1398
1399 // construct a locale object from the binary database
1400 std::locale loc;
1401
1402 _TRY {
1403 loc = std::locale (loc, locname, std::locale::time);
1404 }
1405 _CATCH (...) {
1406 rw_error (0, 0, __LINE__,
1407 "locale (locale (), \"%s\", locale::time) "
1408 "unexpectedly threw an exception", locname);
1409 return;
1410 }
1411
1412 // set the global locale (used by the test function)
1413 std::locale::global (loc);
1414
1415
1416 // %Ec: The locale's alternative date and time representation.
1417 STEP ("%Ec: alternative date and time representation");
1418 TEST (T (0, 0, 0, 1, 0, 0, 0),
1419 // "[[%A][%B][%Od][%H][%M][%S][%Y]]"
1420 "[[[Sunday]][[January]][1st][00][00][00][1900]]", 46,
1421 "%Ec", 0, Good);
1422
1423 TEST (T (5, 4, 3, 2, 1, 1, 1),
1424 "[[[monday]][[february]][2nd][03][04][05][1901]]", 47,
1425 "%Ec", 0, Good);
1426
1427 TEST (T (60, 59, 23, 31, 2, -1898, 2),
1428 // %Y requires a four digit year, 02 is not treated as 2002
1429 "[[[TUE]][[MAR]][31st][23][59][60][02]]", 38,
1430 "%Ec", 0, Good);
1431
1432 // %EC: The name of the base year (period) in the locale's
1433 // alternative representation.
1434
1435 // %Ex: The locale's alternative date representation.
1436 STEP ("%Ex: alternative date representation");
1437 rw_warn (0, 0, __LINE__, "%%Ex not being exercised");
1438
1439 // verify that facet computes the remaining tm members from
1440 // the supplied data
1441 //TEST (T (0, 0, 0, 21, 4, 2002, 2, 141),
1442 // // "%Ow weekday, %OU week, %Oy year"
1443 // "2nd weekday, 21st week, 2nd year", 32,
1444 // // i.e., May 21, 2002
1445 // "%Ex", 0, Good);
1446
1447 // %EX: The locale's alternative time representation.
1448 STEP ("%EX: alternative time representation");
1449 // verify that 0 is correctly parsed if alternative numeric
1450 // symbols are expected and the symbol for zero is empty
1451 TEST (T (0, 1, 2),
1452 // "%OH hour, %OM minute, %OS second"
1453 "2nd hour, 1st minute, 0 second", 30,
1454 "%EX", 0, Good);
1455
1456 TEST (T (21, 22, 23),
1457 // "%OH hour, %OM minute, %OS second"
1458 "23rd hour, 22nd minute, 21st second", 35,
1459 "%EX", 0, Good);
1460
1461 // %Ey: The offset from %EC (year only) in the locale's
1462 // alternative representation.
1463 STEP ("%Ey: offset from %EC in alternative representation.");
1464 rw_warn (0, 0, __LINE__, "%%Ey not being exercised");
1465
1466 // %EY: The full alternative year representation.
1467 STEP ("%EY: the full alternative year representation");
1468 rw_warn (0, 0, __LINE__, "%%EY not being exercised");
1469
1470 // %Od: The day of the month using the locale's alternative
1471 // numeric symbols; leading zeros are permitted but not required.
1472 STEP ("%Od: the day of the month using alternative numeric symbols");
1473 TEST (T (0, 0, 0, 1), "1st", 3, "%Od", 0, Good);
1474 TEST (T (0, 0, 0, 2), "2nd", 3, "%Od", 0, Good);
1475 TEST (T (0, 0, 0, 11), "11th", 4, "%Od", 0, Good);
1476 TEST (T (0, 0, 0, 21), "21st", 4, "%Od", 0, Good);
1477 TEST (T (0, 0, 0, 30), "30th", 4, "%Od", 0, Good);
1478 TEST (T (0, 0, 0, 31), "31st", 4, "%Od", 0, Good);
1479 TEST (T (0, 0, 0, 0), "32", 2, "%Od", 0, Eof | Fail);
1480
1481 // %Oe: Equivalent to %Od.
1482 STEP ("%Oe: equivalent to %Od");
1483 TEST (T (0, 0, 0, 3), "3rd", 3, "%Oe", 0, Good);
1484 TEST (T (0, 0, 0, 4), "4th", 3, "%Oe", 0, Good);
1485 TEST (T (0, 0, 0, 9), "9th", 3, "%Oe", 0, Good);
1486 TEST (T (0, 0, 0, 10), "10th", 4, "%Oe", 0, Good);
1487 TEST (T (0, 0, 0, 0), "32nd", 2, "%Oe", 0, Fail);
1488 TEST (T (0, 0, 0, 0), "33", 2, "%Oe", 0, Eof | Fail);
1489
1490 // %OH: The hour (24-hour clock) using the locale's alternative
1491 // numeric symbols.
1492 STEP ("%OH: the hour (24-hour clock) using alternative numeric symbols");
1493 TEST (T (0, 0, 0), "0", 1, "%OH", 0, Eof);
1494 TEST (T (0, 0, 0), "00", 2, "%OH", 0, Eof);
1495 TEST (T (0, 0, 1), "1st", 3, "%OH", 0, Good);
1496 TEST (T (0, 0, 2), "2nd", 3, "%OH", 0, Good);
1497 TEST (T (0, 0, 11), "11th", 4, "%OH", 0, Good);
1498 TEST (T (0, 0, 12), "12th", 4, "%OH", 0, Good);
1499 TEST (T (0, 0, 13), "13th", 4, "%OH", 0, Good);
1500 TEST (T (0, 0, 23), "23rd", 4, "%OH", 0, Good);
1501
1502 // %OI: The hour (12-hour clock) using the locale's alternative
1503 // numeric symbols.
1504 STEP ("%OI: the hour (12-hour clock) using alternative numeric symbols");
1505 TEST (T (0, 0, 0), "0", 1, "%OI", 0, Eof);
1506 TEST (T (0, 0, 0), "000", 3, "%OI", 0, Eof);
1507 TEST (T (0, 0, 3), "3rd", 3, "%OI", 0, Good);
1508 TEST (T (0, 0, 11), "11th", 4, "%OI", 0, Good);
1509 TEST (T (0, 0, 12), "12th", 4, "%OI", 0, Good);
1510 TEST (T (0, 0, 0), "13th", 4, "%OI", 0, Fail);
1511 TEST (T (0, 0, 0), "14", 2, "%OI", 0, Eof | Fail);
1512
1513 // %Om: The month using the locale's alternative numeric symbols.
1514 STEP ("%Om: the month using alternative numeric symbols");
1515 TEST (T (0, 0, 0, 0, 0), "1st", 3, "%Om", 0, Good);
1516 TEST (T (0, 0, 0, 0, 1), "2nd", 3, "%Om", 0, Good);
1517 TEST (T (0, 0, 0, 0, 2), "3rd", 3, "%Om", 0, Good);
1518 TEST (T (0, 0, 0, 0, 3), "4th", 3, "%Om", 0, Good);
1519 TEST (T (0, 0, 0, 0, 4), "5th", 3, "%Om", 0, Good);
1520 TEST (T (0, 0, 0, 0, 5), "6th", 3, "%Om", 0, Good);
1521 TEST (T (0, 0, 0, 0, 6), "7th", 3, "%Om", 0, Good);
1522 TEST (T (0, 0, 0, 0, 7), "8th", 3, "%Om", 0, Good);
1523 TEST (T (0, 0, 0, 0, 8), "9th", 3, "%Om", 0, Good);
1524 TEST (T (0, 0, 0, 0, 9), "10th", 4, "%Om", 0, Good);
1525 TEST (T (0, 0, 0, 0, 10), "11th", 4, "%Om", 0, Good);
1526 TEST (T (0, 0, 0, 0, 11), "12th", 4, "%Om", 0, Good);
1527 TEST (T (0, 0, 0, 0, 0), "13th", 4, "%Om", 0, Fail);
1528 TEST (T (0, 0, 0, 0, 0), "0", 1, "%Om", 0, Eof | Fail);
1529 TEST (T (0, 0, 0, 0, 0), "00", 2, "%Om", 0, Eof | Fail);
1530 TEST (T (0, 0, 0, 0, 0), "01", 2, "%Om", 0, Eof | Fail);
1531
1532 // %OM: The minutes using the locale's alternative numeric symbols.
1533 STEP ("%OM: the minutes using alternative numeric symbols");
1534 TEST (T (0, 0), "0", 1, "%OM", 0, Eof);
1535 TEST (T (0, 1), "1st", 3, "%OM", 0, Good);
1536 TEST (T (0, 2), "2nd", 3, "%OM", 0, Good);
1537 TEST (T (0, 3), "3rd", 3, "%OM", 0, Good);
1538 TEST (T (0, 4), "4th", 3, "%OM", 0, Good);
1539 TEST (T (0, 29), "29th", 4, "%OM", 0, Good);
1540 TEST (T (0, 30), "30th", 4, "%OM", 0, Good);
1541 TEST (T (0, 31), "31st", 4, "%OM", 0, Good);
1542 TEST (T (0, 32), "32", 2, "%OM", 0, Eof);
1543 TEST (T (0, 0), "60", 2, "%OM", 0, Eof | Fail);
1544 TEST (T (0, 0), "2", 1, "%OM", 0, Eof | Fail);
1545
1546 // %OS: The seconds using the locale's alternative numeric symbols.
1547 STEP ("%OS: the seconds using alternative numeric symbols");
1548 TEST (T ( 0), "0", 1, "%OS", 0, Eof);
1549 TEST (T ( 1), "1st", 3, "%OS", 0, Good);
1550 TEST (T ( 2), "2nd", 3, "%OS", 0, Good);
1551 TEST (T ( 3), "3rd", 3, "%OS", 0, Good);
1552 TEST (T ( 4), "4th", 3, "%OS", 0, Good);
1553 TEST (T (29), "29th", 4, "%OS", 0, Good);
1554 TEST (T (30), "30th", 4, "%OS", 0, Good);
1555 TEST (T (31), "31st", 4, "%OS", 0, Good);
1556 TEST (T (32), "32", 2, "%OS", 0, Eof);
1557 TEST (T (59), "059", 3, "%OS", 0, Eof);
1558 TEST (T (60), "0060", 4, "%OS", 0, Eof);
1559 TEST (T ( 0), "61", 2, "%OS", 0, Eof | Fail);
1560 TEST (T ( 0), "21", 2, "%OS", 0, Eof | Fail);
1561
1562 // %OU: The week number of the year (Sunday as the first day of the week)
1563 // using the locale's alternative numeric symbols.
1564 STEP ("%OU: the Sunday-based week using alternative numeric symbols");
1565 rw_warn (0, 0, __LINE__, "%%OU not being exercised");
1566
1567 // %Ow: The number of the weekday (Sunday=0) using the locale's
1568 // alternative numeric symbols.
1569 STEP ("%Ow: Sunday-based weekday using alternative numeric symbols");
1570 TEST (T (0, 0, 0, 0, 0, 0, 0), "0", 1, "%Ow", 0, Eof);
1571 TEST (T (0, 0, 0, 0, 0, 0, 1), "1st", 3, "%Ow", 0, Good);
1572 TEST (T (0, 0, 0, 0, 0, 0, 2), "2nd", 3, "%Ow", 0, Good);
1573 TEST (T (0, 0, 0, 0, 0, 0, 6), "6th", 3, "%Ow", 0, Good);
1574 TEST (T (0, 0, 0, 0, 0, 0, 0), "7th", 3, "%Ow", 0, Fail);
1575 TEST (T (0, 0, 0, 0, 0, 0, 0), "8", 1, "%Ow", 0, Eof | Fail);
1576
1577 // %OW: The week number of the year (Monday as the first day of the week)
1578 // using the locale's alternative numeric symbols.
1579 STEP ("%OW: the Monday-based week using alternative numeric symbols");
1580 rw_warn (0, 0, __LINE__, "%%OW not being exercised");
1581
1582 // %Oy: The year (offset from %C ) using the locale's alternative
1583 // numeric symbols.
1584 STEP ("%Oy: year offset from %C using alternative numeric symbols");
1585 rw_warn (0, 0, __LINE__, "%%Oy not being exercised");
1586}
1587
1588
1590static int
1591run_test (int, char**)
1592{
1593 // set up RWSTD_LOCALE_ROOT and other environment variables
1594 // here as opposed to at program startup to work around a
1595 // SunOS 5.7 bug in putenv() (PR ##30017)
1597
1598 // store the next available file descriptor
1599 // in order to detect file descriptor leaks
1600 const int fd0 = rw_nextfd (0);
1601
1602 test_posix (char (), "char");
1603
1604 const char *locname;
1605
1606 const char en[] = "en-*-*-*";
1607 const char de[] = "de-*-*-*";
1608 const char da[] = "da-*-*-*";
1609
1610 int nnamed = 0;
1611
1612 // try to find and exercise the english locale
1613 if ((locname = rw_locale_query (LC_ALL, en, 1)) && *locname) {
1614 test_english (char (), "char", locname);
1615 ++nnamed;
1616 }
1617
1618 // try to find and exercise the german locale
1619 if ((locname = rw_locale_query (LC_ALL, de, 1)) && *locname) {
1620 test_german (char (), "char", locname);
1621 ++nnamed;
1622 }
1623
1624 // try to find and exercise the danish locale
1625 if ((locname = rw_locale_query (LC_ALL, da, 1)) && *locname) {
1626 test_danish (char (), "char", locname);
1627 ++nnamed;
1628 }
1629
1631 // exercise the time_get facets with a user-defined locale
1632 std::locale::global (std::locale ("C"));
1633
1634 // create a LC_TIME database based on user-defined data
1635 locname = make_LC_TIME ();
1636
1637 if (!locname) {
1638 rw_error (0, 0, __LINE__, "failed to generate LC_TIME locale data");
1639 return 0;
1640 }
1641
1642 test_user (char (), "char", locname);
1643
1644#ifndef _RWSTD_NO_WCHAR_T
1645
1646 test_posix (wchar_t (), "wchar_t");
1647
1648 test_user (wchar_t (), "wchar_t", locname);
1649
1650#endif // _RWSTD_NO_WCHAR_T
1651
1652 // reset the gloab locale to free up resources (such as file
1653 // descriptors used by time_get_byname to map locale databases)
1654 std::locale::global (std::locale ("C"));
1655
1656 const int fd1 = rw_nextfd (0);
1657
1658 rw_assert (0 == fd1 - fd0, 0, __LINE__,
1659 "%d file descriptor leaks detected", fd1 - fd0);
1660
1661 rw_assert (0 != nnamed, 0, __LINE__,
1662 "time_get not exercised in named locales");
1663
1664 return 0;
1665}
1666
1667
1669int main (int argc, char *argv[])
1670{
1671 return rw_test (argc, argv, __FILE__,
1672 "lib.locale.time.get",
1673 0 /* no comment */,
1674 run_test,
1675 "",
1676 0);
1677}
#define i
Definition 17.names.cpp:126
#define t
Definition 17.names.cpp:136
#define ostrm
Definition 17.names.cpp:512
#define loc
Definition 17.names.cpp:492
#define sec
Definition 17.names.cpp:539
#define x
Definition 17.names.cpp:140
#define istrm
Definition 17.names.cpp:486
#define lineno
Definition 17.names.cpp:491
#define buf
Definition 17.names.cpp:452
#define j
Definition 17.names.cpp:127
#define offset
Definition 17.names.cpp:508
#define charT
Definition 17.names.cpp:456
#define tmp
Definition 17.names.cpp:553
#define len
Definition 17.names.cpp:488
#define val
Definition 17.names.cpp:570
const char * locale_root
#define flags
#define T
std::tm mktm(int sec=0, int min=0, int hour=0, int mday=0, int mon=0, int year=0, int wday=0, int yday=0, int isdst=0)
void test_german(charT, const char *cname, const char *locname)
void test_posix(charT, const char *cname)
void test_english(charT, const char *cname, const char *locname)
#define FUNCTION(fun)
#define Fail
#define TEST
#define Good
void test_danish(charT, const char *cname, const char *locname)
void test_user(charT, const char *cname, const char *locname)
#define Eof
#define STEP(desc)
void do_test(int line, const char *src, std::size_t resoff, ForwardIterator dummy_iter, const T *, const char *predname)
void run_test(const ForwardIterator &dummy, T *, Predicate *pred)
const int end
#define main
#define LC_ALL
#define _RWSTD_PATH_SEP
Definition _config.h:297
#define _TRY
Definition _defs.h:850
#define _CATCH(ex)
Definition _defs.h:851
#define INT_MIN
Definition limits.h:80
#define INT_MAX
Definition limits.h:76
_TEST_EXPORT int rw_test(int argc, char *argv[], const char *filename, const char *clause, const char *comment, int(*testfun)(int, char **), const char *optspec,...)
_TEST_EXPORT int rw_info(int, const char *, int, const char *,...)
Definition driver.cpp:1681
_TEST_EXPORT int rw_fatal(int expr, const char *filename, int line, const char *fmtspec,...)
Definition driver.cpp:1596
_TEST_EXPORT int rw_assert(int, const char *, int, const char *,...)
Definition driver.cpp:1630
_TEST_EXPORT int rw_error(int, const char *, int, const char *,...)
Definition driver.cpp:1613
_TEST_EXPORT int rw_warn(int, const char *, int, const char *,...)
Definition driver.cpp:1647
_TEST_EXPORT void pcs_write(void *, const char *)
Definition file.cpp:89
_TEST_EXPORT int rw_nextfd(int *)
Definition file.cpp:478
#define LOCALE_ROOT_ENVAR
Definition rw_locale.h:57
_TEST_EXPORT const char * rw_set_locale_root()
Definition locale.cpp:324
_TEST_EXPORT const char * rw_localedef(const char *, const char *, const char *, const char *)
Definition locale.cpp:154
_TEST_EXPORT char * rw_locale_query(int=_UNUSED_CAT, const char *=0, _RWSTD_SIZE_T=0)
_TEST_EXPORT int rw_snprintf(char *, _RWSTD_SIZE_T, const char *,...)
#define RW_ASSERT(expr)
const era_data * era
const char * t_fmt_ampm
const char * am_pm[2]
const char *const * alt_digits
const char * abday[7]
const char * abmon[12]
const char * d_fmt
const char * era_t_fmt
const char * era_d_fmt
const char * era_d_t_fmt
const char * day[7]
const char * mon[12]
const char * d_t_fmt
const char * t_fmt
#define min(a, b)