Ne.app NeANT
The Ne.app NeANT User module of the NeANT distribution.
0.printf.cpp
Go to the documentation of this file.
1
29// tell Compaq C++ we need ENOMEM (defined by POSIX
30// but not in the compiler's pure C++ libc headers)
31#undef __PURE_CNAME
32
33#include <rw_environ.h> // for rw_putenv()
34#include <rw_printf.h>
35#include <rw_process.h> // for rw_pid_t
36#include <rw_value.h> // for UserClass
37
38#include <bitset> // for bitset
39#include <ios> // for ios::iostate, ios::openmode, ios::seekdir
40#include <string> // for string
41#include <locale> // for locale::all, ...
42
43#include <assert.h> // for assert()
44#include <ctype.h> // for isdigit()
45#include <errno.h> // for EXXX, errno
46#include <limits.h> // for INT_MAX, ...
47#include <locale.h> // for LC_ALL, ...
48#include <signal.h> // for SIGABRT, ...
49#include <stdio.h> // for printf(), ...
50#include <stdlib.h> // for free(), size_t
51#include <string.h> // for strcpy()
52#include <stdarg.h> // for va_arg, ...
53#include <time.h> // for struct tm
54#include <wchar.h> // for WEOF
55
56
57// disable tests for function name in "%{lF}"
58#define _RWSTD_NO_SPRINTFA_FUNNAME
59
60
62int ntests; // number of tests performed
63int nfailures; // number of failures
64
65
66static void
67do_test (int line, // line number of the test case
68 const char *fmt, // format string
69 const char *expect, // expected output or 0 on error
70 char *result) // actual result (0 on error)
71{
72 static char nullstr[] = "null";
73 ++ntests;
74
75 const char* q_fmt = "\"\"";
76
77 if (0 == fmt) {
78 fmt = nullstr;
79 q_fmt = "()";
80 }
81
82 if (result && expect) {
83
84 const int cmp = memcmp (expect, result, strlen (expect) + 1);
85
86 if (cmp) {
87 ++nfailures;
88 fprintf (stderr,
89 "# Assertion failed on line %d: "
90 "rw_sprintf(%c%s%c, ...) == \"%s\", got \"%s\"\n",
91 line, q_fmt [0], fmt, q_fmt [1], expect, result);
92 }
93 }
94 else if (result || expect) {
95 ++nfailures;
96
97 const char* q_expect = "\"\"";
98 const char* q_result = "\"\"";
99
100 if (0 == expect) {
101 expect = nullstr;
102 q_expect = "()";
103 }
104
105 if (0 == result) {
106 result = nullstr;
107 q_result = "()";
108 }
109
110 fprintf (stderr, "# Assertion failed on line %d: "
111 "rw_printf(%c%s%c, ...) == %c%s%c got %c%s%c\n",
112 line, q_fmt [0], fmt, q_fmt [1],
113 q_expect [0], expect, q_expect [1],
114 q_result [0], result, q_result [1]);
115 }
116 else /* if (!result && !expect) */ {
117 _RWSTD_ASSERT (!result && !expect);
118 }
119
120 if (result && result != nullstr)
121 free (result);
122}
123
124
125#undef TEST
126#define TEST(fmt, a1, a2, a3, expect) \
127 do_test (__LINE__, fmt, expect, rw_sprintfa (fmt, a1, a2, a3))
128
129#undef TEST_SPEC
130#define TEST_SPEC(pfx, a1, a2, a3, expect) \
131 { \
132 ++ntests; \
133 char fmt [64]; \
134 sprintf (fmt, "%s%c", pfx, spec); \
135 char* const s0 = rw_sprintfa (fmt, a1, a2, a3); \
136 char buf [256]; \
137 /* non-const variable below avoids warnings about */ \
138 /* controlling expression being constant */ \
139 const char* /* const */ expect_var = (expect); \
140 if (expect_var) \
141 strcpy (buf, expect_var ? expect_var : ""); \
142 else \
143 sprintf (buf, fmt, a1, a2, a3); \
144 const int result = memcmp (buf, s0, strlen (buf) + 1); \
145 if (result) { \
146 ++nfailures; \
147 fprintf (stderr, \
148 "# Assertion failed on line %d: " \
149 "rw_printf(\"%s\", %ld, %ld, %ld) " \
150 "== \"%s\", got \"%s\"\n", \
151 __LINE__, fmt, \
152 (long)a1, (long)a2, (long)a3, buf, s0); \
153 } \
154 free (s0); \
155 } (void)0 /* require semicolon after macro invocation */
156
157
159// returns an invalid or misaligned address (when 1 < size)
160const void* bad_address (size_t size)
161{
162 const char *addr;
163
164 if (1 < size) {
165 static const char buf [] = "0123456789abcdef";
166
167 addr = buf;
168 while (0 == ((size_t)addr & (size - 1)))
169 ++addr;
170 }
171 else {
172
173#ifndef _RWSTD_OS_HP_UX
174 // the first page is usually unmapped
175 addr = (char*)32;
176#else
177 // the first page on HP-UX is readable, this should give
178 // an invalid (inaccessible) address both on IPF and PA
179 addr = (char*)(0 - size_t (32));
180#endif // _RWSTD_OS_HP_UX
181
182 }
183
184 return addr;
185}
186
187// returns the expected string corresponding to an invalid
188// or misaligned address
189const char* format_bad_address (const void *ptr, bool valid)
190{
191 static char buf [80];
192
193#if 4 == _RWSTD_PTR_SIZE
194 sprintf (buf, "(%s address %#010" _RWSTD_PRIz "x)",
195 valid ? "misaligned" : "invalid", (size_t)ptr);
196#elif 8 == _RWSTD_PTR_SIZE
197 sprintf (buf, "(%s address %#018" _RWSTD_PRIz "x)",
198 valid ? "misaligned" : "invalid", (size_t)ptr);
199#else
200 sprintf (buf, "(%s address %#0" _RWSTD_PRIz "x)",
201 valid ? "misaligned" : "invalid", (size_t)ptr);
202#endif
203
204 return buf;
205}
206
207
209static void
210test_percent ()
211{
213 printf ("%s\n", "\"%\": percent sign");
214
215 TEST ("%", 0, 0, 0, "%");
216 TEST ("%%", 0, 0, 0, "%");
217 TEST ("%% ", 0, 0, 0, "% ");
218 TEST (" %% ", 0, 0, 0, " % ");
219 TEST ("%%%", 0, 0, 0, "%%");
220 TEST ("%% %", 0, 0, 0, "% %");
221 TEST (" %", 0, 0, 0, " %");
222 TEST (" %", 0, 0, 0, " %");
223 TEST ("%%%%", 0, 0, 0, "%%");
224 TEST ("%% %%", 0, 0, 0, "% %");
225 TEST ("%% %% %", 0, 0, 0, "% % %");
226 TEST ("%% %% ", 0, 0, 0, "% % ");
227 TEST (" %%%% ", 0, 0, 0, " %% ");
228 TEST ("%%%%%%%%", 0, 0, 0, "%%%%");
229}
230
231
233static void
234test_character ()
235{
237 printf ("%s\n", "\"%c\": character formatting");
238
239 const char spec = 'c';
240
241 TEST_SPEC ("%", '\0', 0, 0, "\0");
242 TEST_SPEC ("%", '\a', 0, 0, "\a");
243 TEST_SPEC ("%", '\n', 0, 0, "\n");
244 TEST_SPEC ("%", '\r', 0, 0, "\r");
245 TEST_SPEC ("%", '\t', 0, 0, "\t");
246 TEST_SPEC ("%", '0', 0, 0, "0");
247 TEST_SPEC ("%", '1', 0, 0, "1");
248 TEST_SPEC ("%", 'A', 0, 0, "A");
249 TEST_SPEC ("%", 'Z', 0, 0, "Z");
250 TEST_SPEC ("%", '\xff', 0, 0, "\xff");
251
252 // exercise right justification
253 TEST_SPEC ("%0", 'v', 0, 0, "v");
254 TEST_SPEC ("%1", 'w', 0, 0, "w");
255 TEST_SPEC ("%2", 'x', 0, 0, " x");
256 TEST_SPEC ("%3", 'y', 0, 0, " y");
257 TEST_SPEC ("%4", 'z', 0, 0, " z");
258
259 TEST_SPEC ("%*", 0, '0', 0, "0");
260 TEST_SPEC ("%*", 1, '1', 0, "1");
261 TEST_SPEC ("%*", 2, '2', 0, " 2");
262 TEST_SPEC ("%*", 3, '3', 0, " 3");
263 TEST_SPEC ("%*", 4, '4', 0, " 4");
264
265 // exercise left justification
266 TEST_SPEC ("%-0", 'V', 0, 0, "V");
267 TEST_SPEC ("%-1", 'W', 0, 0, "W");
268 TEST_SPEC ("%-2", 'X', 0, 0, "X ");
269 TEST_SPEC ("%-3", 'Y', 0, 0, "Y ");
270 TEST_SPEC ("%-4", 'Z', 0, 0, "Z ");
271
272 TEST_SPEC ("%-*", 0, '0', 0, "0");
273 TEST_SPEC ("%-*", 1, '1', 0, "1");
274 TEST_SPEC ("%-*", 2, '2', 0, "2 ");
275 TEST_SPEC ("%-*", 3, '3', 0, "3 ");
276 TEST_SPEC ("%-*", 4, '4', 0, "4 ");
277
278 // 7.19.6.1, p5 of ISO/IEC 9899:1999:
279 // A negative field width argument is taken as a - flag
280 // followed by a positive field width.
281
282 TEST_SPEC ("%*", -1, '1', 0, "1");
283 TEST_SPEC ("%*", -2, '2', 0, "2 ");
284 TEST_SPEC ("%*", -3, '3', 0, "3 ");
285 TEST_SPEC ("%*", -4, '4', 0, "4 ");
286 TEST_SPEC ("%-*", -5, '5', 0, "5 ");
287
288 TEST_SPEC ("%#", 'a', 0, 0, "'a'");
289
291 printf ("%s\n", "extension: \"%{c}\": escaped character");
292
293 TEST ("%{c}", '\0', 0, 0, "\\0");
294 TEST ("%{c}", '\2', 0, 0, "\\x02");
295 TEST ("%{c}", '\a', 0, 0, "\\a");
296 TEST ("%{c}", '\n', 0, 0, "\\n");
297 TEST ("%{c}", '\r', 0, 0, "\\r");
298 TEST ("%{c}", '\t', 0, 0, "\\t");
299 TEST ("%{c}", '0', 0, 0, "0");
300 TEST ("%{c}", '2', 0, 0, "2");
301 TEST ("%{c}", 'A', 0, 0, "A");
302 TEST ("%{c}", 'Z', 0, 0, "Z");
303 TEST ("%{c}", '\xff', 0, 0, "\\xff");
304
306 printf ("%s\n", "extension: \"%{#c}\": quoted escaped character");
307 TEST ("%{#c}", '\0', 0, 0, "'\\0'");
308 TEST ("%{#c}", '\3', 0, 0, "'\\x03'");
309 TEST ("%{#c}", '\a', 0, 0, "'\\a'");
310 TEST ("%{#c}", '\n', 0, 0, "'\\n'");
311 TEST ("%{#c}", '\r', 0, 0, "'\\r'");
312 TEST ("%{#c}", '\t', 0, 0, "'\\t'");
313 TEST ("%{#c}", '0', 0, 0, "'0'");
314 TEST ("%{#c}", '3', 0, 0, "'3'");
315 TEST ("%{#c}", 'A', 0, 0, "'A'");
316 TEST ("%{#c}", 'Z', 0, 0, "'Z'");
317 TEST ("%{#c}", '\xff', 0, 0, "'\\xff'");
318
320 printf ("%s\n", "\"%lc\": wide character");
321
322 TEST_SPEC ("%", L'\0', 0, 0, "\0");
323 TEST_SPEC ("%", L'\a', 0, 0, "\a");
324 TEST_SPEC ("%", L'\n', 0, 0, "\n");
325 TEST_SPEC ("%", L'\r', 0, 0, "\r");
326 TEST_SPEC ("%", L'\t', 0, 0, "\t");
327 TEST_SPEC ("%", L'0', 0, 0, "0");
328 TEST_SPEC ("%", L'1', 0, 0, "1");
329 TEST_SPEC ("%", L'A', 0, 0, "A");
330 TEST_SPEC ("%", L'Z', 0, 0, "Z");
331
333 printf ("%s\n", "extension: \"%{lc}\": escaped wide character");
334
335 TEST ("%{lc}", L'\0', 0, 0, "\\0");
336 TEST ("%{lc}", L'\4', 0, 0, "\\x04");
337 TEST ("%{lc}", L'\a', 0, 0, "\\a");
338 TEST ("%{lc}", L'\n', 0, 0, "\\n");
339 TEST ("%{lc}", L'\r', 0, 0, "\\r");
340 TEST ("%{lc}", L'\t', 0, 0, "\\t");
341 TEST ("%{lc}", L'0', 0, 0, "0");
342 TEST ("%{lc}", L'1', 0, 0, "1");
343 TEST ("%{lc}", L'A', 0, 0, "A");
344 TEST ("%{lc}", L'Z', 0, 0, "Z");
345 TEST ("%{lc}", L'\xff', 0, 0, "\\xff");
346 TEST ("%{lc}", WEOF, 0, 0, "EOF");
347
349 printf ("%s\n", "extension: \"%{#lc}\": quoted escaped wide character");
350
351 TEST ("%{#lc}", L'\0', 0, 0, "'\\0'");
352 TEST ("%{#lc}", L'\5', 0, 0, "'\\x05'");
353 TEST ("%{#lc}", L'\a', 0, 0, "'\\a'");
354 TEST ("%{#lc}", L'\n', 0, 0, "'\\n'");
355 TEST ("%{#lc}", L'\r', 0, 0, "'\\r'");
356 TEST ("%{#lc}", L'\t', 0, 0, "'\\t'");
357 TEST ("%{#lc}", L'0', 0, 0, "'0'");
358 TEST ("%{#lc}", L'1', 0, 0, "'1'");
359 TEST ("%{#lc}", L'A', 0, 0, "'A'");
360 TEST ("%{#lc}", L'Z', 0, 0, "'Z'");
361 TEST ("%{#lc}", L'\xff', 0, 0, "'\\xff'");
362 TEST ("%{#lc}", WEOF, 0, 0, "EOF");
363}
364
365
367static void
369{
371 printf ("%s\n", "\"%s\": character string");
372
373 TEST ("", "", 0, 0, "");
374 TEST ("%s", "", 0, 0, "");
375 TEST ("%s", "a", 0, 0, "a");
376 TEST ("%s", "ab", 0, 0, "ab");
377 TEST ("%s", "abc", 0, 0, "abc");
378 TEST ("%s", "abcd", 0, 0, "abcd");
379 TEST ("%s", "abcde", 0, 0, "abcde");
380 TEST ("%s", "abcdef", 0, 0, "abcdef");
381
382 TEST ("|%1s|", "xyz", 0, 0, "|xyz|");
383 TEST ("|%2s|", "xyz", 0, 0, "|xyz|");
384 TEST ("|%3s|", "xyz", 0, 0, "|xyz|");
385 TEST ("|%4s|", "xyz", 0, 0, "| xyz|");
386 TEST ("|%5s|", "xyz", 0, 0, "| xyz|");
387 TEST ("|%6s|", "xyz", 0, 0, "| xyz|");
388
389 TEST ("|%-1s|", "xyz", 0, 0, "|xyz|");
390 TEST ("|%-2s|", "xyz", 0, 0, "|xyz|");
391 TEST ("|%-3s|", "xyz", 0, 0, "|xyz|");
392 TEST ("|%-4s|", "xyz", 0, 0, "|xyz |");
393 TEST ("|%-5s|", "xyz", 0, 0, "|xyz |");
394 TEST ("|%-6s|", "xyz", 0, 0, "|xyz |");
395
396 TEST ("|%+1s|", "xyz", 0, 0, "|xyz|");
397 TEST ("|%+2s|", "xyz", 0, 0, "|xyz|");
398 TEST ("|%+3s|", "xyz", 0, 0, "|xyz|");
399 TEST ("|%+4s|", "xyz", 0, 0, "| xyz|");
400 TEST ("|%+5s|", "xyz", 0, 0, "| xyz|");
401 TEST ("|%+6s|", "xyz", 0, 0, "| xyz|");
402
403 TEST ("|%1.0s|", "xyz", 0, 0, "| |");
404 TEST ("|%2.1s|", "xyz", 0, 0, "| x|");
405 TEST ("|%3.2s|", "xyz", 0, 0, "| xy|");
406 TEST ("|%4.3s|", "xyz", 0, 0, "| xyz|");
407 TEST ("|%5.4s|", "xyz", 0, 0, "| xyz|");
408 TEST ("|%6.5s|", "xyz", 0, 0, "| xyz|");
409
410 TEST ("|%*.*s|", 7, 2, "xyz", "| xy|");
411 TEST ("|%*.*s|", -8, 1, "xyz", "|x |");
412
413 TEST ("%s%s", "A", "BC", 0, "ABC");
414 TEST ("1%s2%s3", "A", "BC", 0, "1A2BC3");
415 TEST ("%s%s%s", "A", "BC", "DEF", "ABCDEF");
416 TEST ("1%s2%s3%s4", "A", "BC", "DEF", "1A2BC3DEF4");
417
418 TEST ("%s", 0, 0, 0, "(null)");
419
420 const void* addr = bad_address (0);
421 TEST ("%s", addr, 0, 0, format_bad_address (addr, false));
422
423#ifndef _RWSTD_NO_WCHAR_T
424
426 printf ("%s\n", "\"%ls\": wide character string");
427
428 TEST ("%ls", 0, 0, 0, "(null)");
429
430 addr = bad_address (0);
431 TEST ("%ls", addr, 0, 0, format_bad_address (addr, false));
432
433 addr = bad_address (sizeof (wchar_t));
434 TEST ("%ls", addr, 0, 0, format_bad_address (addr, true));
435
436 fprintf (stderr, "Warning: %s\n", "\"%ls\" not exercised");
437
438#endif // _RWSTD_NO_WCHAR_T
439
441 printf ("%s\n", "extension: \"%{#s}\": quoted character string");
442
443 TEST ("%{#s}", "", 0, 0, "\"\"");
444 TEST ("%{#s}", "\0", 0, 0, "\"\"");
445 TEST ("%{#s}", "\1", 0, 0, "\"\\x01\"");
446 TEST ("%{#s}", "\a", 0, 0, "\"\\a\"");
447 TEST ("%{#s}", "\n", 0, 0, "\"\\n\"");
448 TEST ("%{#s}", "\r", 0, 0, "\"\\r\"");
449 TEST ("%{#s}", "\t", 0, 0, "\"\\t\"");
450 TEST ("%{#s}", "\v", 0, 0, "\"\\v\"");
451 TEST ("%{#s}", "a", 0, 0, "\"a\"");
452 TEST ("%{#s}", "ab", 0, 0, "\"ab\"");
453 TEST ("%{#s}", "abc", 0, 0, "\"abc\"");
454 TEST ("%{#s}", "a\ac", 0, 0, "\"a\\ac\"");
455 TEST ("%{#s}", "a\"c", 0, 0, "\"a\\\"c\"");
456
457 // embedded NULs
458 TEST ("%{#1s}", "\0", 0, 0, "\"\\0\"");
459 TEST ("%{#2s}", "\0", 0, 0, "\"\\0\\0\"");
460 TEST ("%{#2s}", "a\0", 0, 0, "\"a\\0\"");
461 TEST ("%{#2s}", "\0a", 0, 0, "\"\\0a\"");
462 TEST ("%{#3s}", "\0\0\0", 0, 0, "\"\\0\\0\\0\"");
463 TEST ("%{#3s}", "\0a\0", 0, 0, "\"\\0a\\0\"");
464 TEST ("%{#3s}", "\0\0a", 0, 0, "\"\\0\\0a\"");
465
466 TEST ("%{#*s}", 0, "\0\0\0v", 0, "\"\"");
467 TEST ("%{#*s}", 1, "\0\0\0w", 0, "\"\\0\"");
468 TEST ("%{#*s}", 2, "\0\0\0x", 0, "\"\\0\\0\"");
469 TEST ("%{#*s}", 3, "\0\0\0y", 0, "\"\\0\\0\\0\"");
470 TEST ("%{#*s}", 4, "\0\0\0z", 0, "\"\\0\\0\\0z\"");
471 TEST ("%{#*s}", 5, "\0\0\0z", 0, "\"\\0\\0\\0z\\0\"");
472
473#ifndef _RWSTD_NO_WCHAR_T
474
476 printf ("%s\n", "extension: \"%{#ls}\": quoted wide character string");
477
478 TEST ("%{#ls}", L"", 0, 0, "\"\"");
479 TEST ("%{#ls}", L"\1", 0, 0, "\"\\x01\"");
480 TEST ("%{#ls}", L"\a", 0, 0, "\"\\a\"");
481 TEST ("%{#ls}", L"\n", 0, 0, "\"\\n\"");
482 TEST ("%{#ls}", L"\r", 0, 0, "\"\\r\"");
483 TEST ("%{#ls}", L"\t", 0, 0, "\"\\t\"");
484 TEST ("%{#ls}", L"\v", 0, 0, "\"\\v\"");
485 TEST ("%{#ls}", L"a", 0, 0, "\"a\"");
486 TEST ("%{#ls}", L"ab", 0, 0, "\"ab\"");
487 TEST ("%{#ls}", L"abc", 0, 0, "\"abc\"");
488 TEST ("%{#ls}", L"a\ac", 0, 0, "\"a\\ac\"");
489 TEST ("%{#ls}", L"a\"c", 0, 0, "\"a\\\"c\"");
490 TEST ("%{#ls}", L"\x100", 0, 0, "\"\\x100\"");
491
492 // embedded NULs
493 TEST ("%{#1ls}", L"\0", 0, 0, "\"\\0\"");
494 TEST ("%{#2ls}", L"\0", 0, 0, "\"\\0\\0\"");
495 TEST ("%{#2ls}", L"a\0", 0, 0, "\"a\\0\"");
496 TEST ("%{#2ls}", L"\0a", 0, 0, "\"\\0a\"");
497 TEST ("%{#3ls}", L"\0\0\0", 0, 0, "\"\\0\\0\\0\"");
498 TEST ("%{#3ls}", L"\0a\0", 0, 0, "\"\\0a\\0\"");
499 TEST ("%{#3ls}", L"\0\0a", 0, 0, "\"\\0\\0a\"");
500
501 TEST ("%{#*ls}", 0, L"\0\0\0v", 0, "\"\"");
502 TEST ("%{#*ls}", 1, L"\0\0\0w", 0, "\"\\0\"");
503 TEST ("%{#*ls}", 2, L"\0\0\0x", 0, "\"\\0\\0\"");
504 TEST ("%{#*ls}", 3, L"\0\0\0y", 0, "\"\\0\\0\\0\"");
505 TEST ("%{#*ls}", 4, L"\0\0\0z", 0, "\"\\0\\0\\0z\"");
506 TEST ("%{#*ls}", 5, L"\0\0\0z", 0, "\"\\0\\0\\0z\\0\"");
507
508 addr = bad_address (0);
509 TEST ("%{#ls}", addr, 0, 0, format_bad_address (addr, false));
510
511 addr = bad_address (sizeof (wchar_t));
512 TEST ("%{#ls}", addr, 0, 0, format_bad_address (addr, true));
513
514#endif // _RWSTD_NO_WCHAR_T
515
516}
517
518
520static void
521test_chararray ()
522{
524 printf ("%s\n", "extension: \"%{Ac}\": quoted character array");
525
526 // exercise the formatting of arrays of characters of arbitrary width
527 // (i.e., single-byte narrow, 2-byte, 4-byte (usually wchar_t's), and
528 // 8-byte characters
529 TEST ("%{Ac}", 0, 0, 0, "(null)");
530 TEST ("%{Ac}", "", 0, 0, "\"\"");
531 TEST ("%{Ac}", "a", 0, 0, "\"a\"");
532 TEST ("%{Ac}", "ab", 0, 0, "\"ab\"");
533 TEST ("%{Ac}", "abc", 0, 0, "\"abc\"");
534
535 TEST ("%{1Ac}", 0, 0, 0, "(null)");
536 TEST ("%{1Ac}", "", 0, 0, "\"\"");
537 TEST ("%{1Ac}", "a", 0, 0, "\"a\"");
538 TEST ("%{1Ac}", "ab", 0, 0, "\"ab\"");
539 TEST ("%{1Ac}", "abc", 0, 0, "\"abc\"");
540
541 // +---- width: character width in bytes
542 // | +-- precision: number of elements in array
543 // | |
544 // v v
545 TEST ("%{1.0Ac}", 0, 0, 0, "(null)");
546 TEST ("%{1.0Ac}", "", 0, 0, "\"\"");
547 TEST ("%{1.1Ac}", "", 0, 0, "\"\\0\"");
548
549 TEST ("%{1.0Ac}", "a", 0, 0, "\"\"");
550 TEST ("%{1.1Ac}", "a", 0, 0, "\"a\"");
551 TEST ("%{1.2Ac}", "a", 0, 0, "\"a\\0\"");
552
553 TEST ("%{1.0Ac}", "ab", 0, 0, "\"\"");
554 TEST ("%{1.1Ac}", "ab", 0, 0, "\"a\"");
555 TEST ("%{1.2Ac}", "ab", 0, 0, "\"ab\"");
556 TEST ("%{1.3Ac}", "ab", 0, 0, "\"ab\\0\"");
557
558 TEST ("%{1.*Ac}", 7, "ab\0cdef", 0, "\"ab\\0cdef\"");
559 TEST ("%{*.7Ac}", 1, "abc\0def", 0, "\"abc\\0def\"");
560 TEST ("%{*.*Ac}", 1, 7, "abcd\0ef", "\"abcd\\0ef\"");
561
562#ifndef _RWSTD_NO_WCHAR_T
563 const unsigned wchar_size = sizeof (wchar_t);
564#else // if defined (_RWSTD_NO_WCHAR_T)
565 const unsigned wchar_size = 0;
566#endif // _RWSTD_NO_WCHAR_T
567
568 if (2 == wchar_size) {
569 TEST ("%{2Ac}", 0, 0, 0, "(null)");
570 TEST ("%{2Ac}", L"", 0, 0, "L\"\"");
571 TEST ("%{2Ac}", L"a", 0, 0, "L\"a\"");
572 TEST ("%{2Ac}", L"ab", 0, 0, "L\"ab\"");
573 TEST ("%{2Ac}", L"abc", 0, 0, "L\"abc\"");
574
575 TEST ("%{2.0Ac}", L"", 0, 0, "L\"\"");
576 TEST ("%{2.1Ac}", L"", 0, 0, "L\"\\0\"");
577
578 TEST ("%{2.0Ac}", L"a", 0, 0, "L\"\"");
579 TEST ("%{2.1Ac}", L"a", 0, 0, "L\"a\"");
580 TEST ("%{2.2Ac}", L"a", 0, 0, "L\"a\\0\"");
581
582 TEST ("%{2.0Ac}", L"ab", 0, 0, "L\"\"");
583 TEST ("%{2.1Ac}", L"ab", 0, 0, "L\"a\"");
584 TEST ("%{2.2Ac}", L"ab", 0, 0, "L\"ab\"");
585 TEST ("%{2.3Ac}", L"ab", 0, 0, "L\"ab\\0\"");
586
587 TEST ("%{2.0Ac}", L"abc", 0, 0, "L\"\"");
588 TEST ("%{2.1Ac}", L"abc", 0, 0, "L\"a\"");
589 TEST ("%{2.2Ac}", L"abc", 0, 0, "L\"ab\"");
590 TEST ("%{2.3Ac}", L"abc", 0, 0, "L\"abc\"");
591 TEST ("%{2.4Ac}", L"abc", 0, 0, "L\"abc\\0\"");
592
593 TEST ("%{2.*Ac}", 7, L"ab\0cdef", 0, "L\"ab\\0cdef\"");
594 TEST ("%{*.7Ac}", 2, L"abc\0def", 0, "L\"abc\\0def\"");
595 TEST ("%{*.*Ac}", 2, 7, L"abcd\0ef", "L\"abcd\\0ef\"");
596 }
597
598 if (sizeof (short) != wchar_size) {
599 const short s_ [] = { '\0' };
600 const short s_a [] = { 'a', '\0' };
601 const short s_ab [] = { 'a', 'b', '\0' };
602 const short s_abc [] = { 'a', 'b', 'c', '\0' };
603
604 TEST ("%{2Ac}", 0, 0, 0, "(null)");
605 TEST ("%{2Ac}", s_, 0, 0, "\"\"");
606 TEST ("%{2Ac}", s_a, 0, 0, "\"a\"");
607 TEST ("%{2Ac}", s_ab, 0, 0, "\"ab\"");
608 TEST ("%{2Ac}", s_abc, 0, 0, "\"abc\"");
609 }
610
611 if (4 == wchar_size) {
612 TEST ("%{4Ac}", 0, 0, 0, "(null)");
613 TEST ("%{4Ac}", L"", 0, 0, "L\"\"");
614 TEST ("%{4Ac}", L"a", 0, 0, "L\"a\"");
615 TEST ("%{4Ac}", L"ab", 0, 0, "L\"ab\"");
616 TEST ("%{4Ac}", L"abc", 0, 0, "L\"abc\"");
617
618 TEST ("%{4.0Ac}", L"", 0, 0, "L\"\"");
619 TEST ("%{4.1Ac}", L"", 0, 0, "L\"\\0\"");
620
621 TEST ("%{4.0Ac}", L"a", 0, 0, "L\"\"");
622 TEST ("%{4.1Ac}", L"a", 0, 0, "L\"a\"");
623 TEST ("%{4.2Ac}", L"a", 0, 0, "L\"a\\0\"");
624
625 TEST ("%{4.0Ac}", L"ab", 0, 0, "L\"\"");
626 TEST ("%{4.1Ac}", L"ab", 0, 0, "L\"a\"");
627 TEST ("%{4.2Ac}", L"ab", 0, 0, "L\"ab\"");
628 TEST ("%{4.3Ac}", L"ab", 0, 0, "L\"ab\\0\"");
629
630 TEST ("%{4.0Ac}", L"abc", 0, 0, "L\"\"");
631 TEST ("%{4.1Ac}", L"abc", 0, 0, "L\"a\"");
632 TEST ("%{4.2Ac}", L"abc", 0, 0, "L\"ab\"");
633 TEST ("%{4.3Ac}", L"abc", 0, 0, "L\"abc\"");
634 TEST ("%{4.4Ac}", L"abc", 0, 0, "L\"abc\\0\"");
635
636 TEST ("%{4.*Ac}", 7, L"ab\0cdef", 0, "L\"ab\\0cdef\"");
637 TEST ("%{*.7Ac}", 4, L"abc\0def", 0, "L\"abc\\0def\"");
638 TEST ("%{*.*Ac}", 4, 7, L"abcd\0ef", "L\"abcd\\0ef\"");
639 }
640}
641
642
644static const char**
645mkargv (const char *arg0 = 0,
646 const char *arg1 = 0,
647 const char *arg2 = 0,
648 const char *arg3 = 0,
649 const char *arg4 = 0,
650 const char *arg5 = 0,
651 const char *arg6 = 0,
652 const char *arg7 = 0,
653 const char *arg8 = 0,
654 const char *arg9 = 0)
655{
656 static const char* argv [10];
657
658 argv [0] = arg0;
659 argv [1] = arg1;
660 argv [2] = arg2;
661 argv [3] = arg3;
662 argv [4] = arg4;
663 argv [5] = arg5;
664 argv [6] = arg6;
665 argv [7] = arg7;
666 argv [8] = arg8;
667 argv [9] = arg9;
668
669 return argv;
670}
671
672
673static void
674test_stringarray ()
675{
677 printf ("%s\n", "extension: \"%{As}\": array of character strings");
678
679#undef ARG
680#define ARG mkargv
681
682 TEST ("%{As}", 0, 0, 0, "(null)");
683 TEST ("%{As}", ARG ("a"), 0, 0, "a");
684 TEST ("%{As}", ARG ("a", "bc"), 0, 0, "a,bc");
685 TEST ("%{As}", ARG ("a", "bc", "def"), 0, 0, "a,bc,def");
686 TEST ("%{As}", ARG ("a", "bc", "def", "ghij"), 0, 0, "a,bc,def,ghij");
687
688 TEST ("%{#As}", 0, 0, 0, "(null)");
689 TEST ("%{#As}", ARG ("abcd"), 0, 0, "\"abcd\"");
690 TEST ("%{#As}", ARG ("abcd", "efg"), 0, 0, "\"abcd\",\"efg\"");
691 TEST ("%{#As}", ARG ("abcd", "efg", "hi"), 0, 0, "\"abcd\",\"efg\",\"hi\"");
692
693 TEST ("%{ As}", 0, 0, 0, "(null)");
694 TEST ("%{ As}", ARG ("a"), 0, 0, "a");
695 TEST ("%{ As}", ARG ("a", "bc"), 0, 0, "a bc");
696 TEST ("%{ As}", ARG ("a", "bc", "def"), 0, 0, "a bc def");
697 TEST ("%{ As}", ARG ("a", "bc", "def", "ghij"), 0, 0, "a bc def ghij");
698
699 TEST ("%{ #As}", 0, 0, 0, "(null)");
700 TEST ("%{ #As}", ARG ("abc"), 0, 0, "\"abc\"");
701 TEST ("%{ #As}", ARG ("abc", "efg"), 0, 0, "\"abc\" \"efg\"");
702 TEST ("%{ #As}", ARG ("abc", "efg", "hi"), 0, 0, "\"abc\" \"efg\" \"hi\"");
703}
704
705
707static void
708test_basic_string ()
709{
711 printf ("%s\n", "extension: \"%{S}\": std::string");
712
713 std::string str;
714
715#undef S
716#define S(s) &(str = std::string (s, sizeof s - 1))
717
718 TEST ("%{S}", 0, 0, 0, "(null)");
719 TEST ("%{S}", S (""), 0, 0, "");
720 TEST ("%{S}", S ("a"), 0, 0, "a");
721 TEST ("%{S}", S ("ab"), 0, 0, "ab");
722 TEST ("%{S}", S ("abc"), 0, 0, "abc");
723
724 TEST ("%{#S}", S ("\a\n\r\t\v"), 0, 0, "\"\\a\\n\\r\\t\\v\"");
725
726 TEST ("%{#S}", S ("\0bc"), 0, 0, "\"\\0bc\"");
727 TEST ("%{#S}", S ("a\0c"), 0, 0, "\"a\\0c\"");
728 TEST ("%{#S}", S ("ab\0"), 0, 0, "\"ab\\0\"");
729 TEST ("%{#S}", S ("a\0\0"), 0, 0, "\"a\\0\\0\"");
730 TEST ("%{#S}", S ("\0\0\0"), 0, 0, "\"\\0\\0\\0\"");
731
733 printf ("%s\n", "extension: \"%{lS}\": std::wstring");
734
735#ifndef _RWSTD_NO_WCHAR_T
736
737 std::wstring wstr;
738
739# undef WS
740# define WS(ws) \
741 &(wstr = std::wstring (L ## ws, sizeof L ## ws / sizeof (wchar_t) - 1))
742
743 TEST ("%{lS}", 0, 0, 0, "(null)");
744 TEST ("%{lS}", WS (""), 0, 0, "");
745 TEST ("%{lS}", WS ("a"), 0, 0, "a");
746 TEST ("%{lS}", WS ("ab"), 0, 0, "ab");
747 TEST ("%{lS}", WS ("abc"), 0, 0, "abc");
748
749 TEST ("%{#lS}", WS ("\a\n\r\t\v"), 0, 0, "\"\\a\\n\\r\\t\\v\"");
750
751 TEST ("%{#lS}", WS ("\0bc"), 0, 0, "\"\\0bc\"");
752 TEST ("%{#lS}", WS ("a\0c"), 0, 0, "\"a\\0c\"");
753 TEST ("%{#lS}", WS ("ab\0"), 0, 0, "\"ab\\0\"");
754 TEST ("%{#lS}", WS ("a\0\0"), 0, 0, "\"a\\0\\0\"");
755 TEST ("%{#lS}", WS ("\0\0\0"), 0, 0, "\"\\0\\0\\0\"");
756
757#else // if defined (_RWSTD_NO_WCHAR_T)
758
759 fprintf (stderr, "Warning: %s\n", "\"%{lS}\" not exercised: "
760 "_RWSTD_NO_WCHAR_T #defined");
761
762#endif // _RWSTD_NO_WCHAR_T
763
765 printf ("%s\n", "extension: \"%{#*S}\": std::basic_string<charT> with "
766 "sizeof (charT)");
767
768 TEST ("%{#1S}", 0, 0, 0, "(null)");
769 TEST ("%{#1S}", S ("\0bc"), 0, 0, "\"\\0bc\"");
770 TEST ("%{#1S}", S ("a\0c"), 0, 0, "\"a\\0c\"");
771 TEST ("%{#1S}", S ("ab\0"), 0, 0, "\"ab\\0\"");
772 TEST ("%{#1S}", S ("a\0\0"), 0, 0, "\"a\\0\\0\"");
773 TEST ("%{#1S}", S ("\0\0\0"), 0, 0, "\"\\0\\0\\0\"");
774
775#if 2 == _RWSTD_WCHAR_SIZE
776
777 TEST ("%{#2S}", 0, 0, 0, "(null)");
778 TEST ("%{#2S}", WS (""), 0, 0, "L\"\"");
779 TEST ("%{#2S}", WS ("a"), 0, 0, "L\"a\"");
780 TEST ("%{#2S}", WS ("ab"), 0, 0, "L\"ab\"");
781 TEST ("%{#2S}", WS ("abc"), 0, 0, "L\"abc\"");
782
783 TEST ("%{#2S}", WS ("\0bc"), 0, 0, "L\"\\0bc\"");
784 TEST ("%{#2S}", WS ("a\0c"), 0, 0, "L\"a\\0c\"");
785 TEST ("%{#2S}", WS ("ab\0"), 0, 0, "L\"ab\\0\"");
786 TEST ("%{#2S}", WS ("a\0\0"), 0, 0, "L\"a\\0\\0\"");
787 TEST ("%{#2S}", WS ("\0\0\0"), 0, 0, "L\"\\0\\0\\0\"");
788
789#elif 4 == _RWSTD_WCHAR_SIZE
790
791 TEST ("%{#4S}", 0, 0, 0, "(null)");
792 TEST ("%{#4S}", WS (""), 0, 0, "L\"\"");
793 TEST ("%{#4S}", WS ("a"), 0, 0, "L\"a\"");
794 TEST ("%{#4S}", WS ("ab"), 0, 0, "L\"ab\"");
795 TEST ("%{#4S}", WS ("abc"), 0, 0, "L\"abc\"");
796
797 TEST ("%{#4S}", WS ("\0bc"), 0, 0, "L\"\\0bc\"");
798 TEST ("%{#4S}", WS ("a\0c"), 0, 0, "L\"a\\0c\"");
799 TEST ("%{#4S}", WS ("ab\0"), 0, 0, "L\"ab\\0\"");
800 TEST ("%{#4S}", WS ("a\0\0"), 0, 0, "L\"a\\0\\0\"");
801 TEST ("%{#4S}", WS ("\0\0\0"), 0, 0, "L\"\\0\\0\\0\"");
802
803#endif // _RWSTD_WCHAR_SIZE
804
805}
806
807
809static void
810test_ios_bitmasks ()
811{
813 printf ("%s\n", "extension: \"%{Is}\": std::ios_base::iostate");
814
815 const int bad = std::ios_base::badbit;
816 const int eof = std::ios_base::eofbit;
817 const int fail = std::ios_base::failbit;
818
819 TEST ("[%{Is}]", 0, 0, 0, "[goodbit]");
820 TEST ("[%{Is}]", bad, 0, 0, "[badbit]");
821 TEST ("[%{Is}]", eof, 0, 0, "[eofbit]");
822 TEST ("[%{Is}]", fail, 0, 0, "[failbit]");
823
824 TEST ("[%{#Is}]", 0, 0, 0, "[std::ios::goodbit]");
825 TEST ("[%{#Is}]", bad, 0, 0, "[std::ios::badbit]");
826 TEST ("[%{#Is}]", eof, 0, 0, "[std::ios::eofbit]");
827 TEST ("[%{#Is}]", fail, 0, 0, "[std::ios::failbit]");
828
829 TEST ("[%{Is}]", bad | eof, 0, 0, "[badbit | eofbit]");
830 TEST ("[%{Is}]", bad | fail, 0, 0, "[badbit | failbit]");
831 TEST ("[%{Is}]", eof | fail, 0, 0, "[eofbit | failbit]");
832 TEST ("[%{Is}]", bad | eof | fail, 0, 0, "[badbit | eofbit | failbit]");
833
835 printf ("%s\n", "extension: \"%{Io}\": std::ios_base::opemode");
836
837 const int in = std::ios_base::in;
838 const int out = std::ios_base::out;
839 const int ate = std::ios_base::ate;
840
841 TEST ("[%{Io}]", 0, 0, 0, "[openmode(0)]");
842 TEST ("[%{Io}]", in, 0, 0, "[in]");
843 TEST ("[%{Io}]", out, 0, 0, "[out]");
844 TEST ("[%{Io}]", ate, 0, 0, "[ate]");
845 TEST ("[%{Io}]", in | out, 0, 0, "[in | out]");
846 TEST ("[%{Io}]", in | ate, 0, 0, "[in | ate]");
847 TEST ("[%{Io}]", in | out | ate, 0, 0, "[in | out | ate]");
848 TEST ("[%{Io}]", out | ate, 0, 0, "[out | ate]");
849
850 TEST ("[%{#Io}]", 0, 0, 0, "[std::ios::openmode(0)]");
851 TEST ("[%{#Io}]", in, 0, 0, "[std::ios::in]");
852 TEST ("[%{#Io}]", out, 0, 0, "[std::ios::out]");
853 TEST ("[%{#Io}]", ate, 0, 0, "[std::ios::ate]");
854 TEST ("[%{#Io}]", in | out, 0, 0, "[std::ios::in | std::ios::out]");
855 TEST ("[%{#Io}]", in | ate, 0, 0, "[std::ios::in | std::ios::ate]");
856 TEST ("[%{#Io}]", in | out | ate, 0, 0,
857 "[std::ios::in | std::ios::out | std::ios::ate]");
858 TEST ("[%{#Io}]", out | ate, 0, 0, "[std::ios::out | std::ios::ate]");
859
861 printf ("%s\n", "extension: \"%{Iw}\": std::ios_base::seekdir");
862
863 TEST ("[%{Iw}]", std::ios::beg, 0, 0, "[beg]");
864 TEST ("[%{Iw}]", std::ios::cur, 0, 0, "[cur]");
865 TEST ("[%{Iw}]", std::ios::end, 0, 0, "[end]");
866
867 TEST ("[%{#Iw}]", std::ios::beg, 0, 0, "[std::ios::beg]");
868 TEST ("[%{#Iw}]", std::ios::cur, 0, 0, "[std::ios::cur]");
869 TEST ("[%{#Iw}]", std::ios::end, 0, 0, "[std::ios::end]");
870
872 printf ("%s\n", "extension: \"%{If}\": std::ios_base::fmtflags");
873
874#define BASE(n) ((n) << _RWSTD_IOS_BASEOFF)
875
876 TEST ("[%{If}]", 0, 0, 0, "[fmtflags(0)]");
877 TEST ("[%{If}]", std::ios::adjustfield, 0, 0, "[adjustfield]");
878 TEST ("[%{If}]", std::ios::basefield, 0, 0, "[basefield]");
879 TEST ("[%{If}]", std::ios::boolalpha, 0, 0, "[boolalpha]");
880 TEST ("[%{If}]", std::ios::dec, 0, 0, "[dec]");
881 TEST ("[%{If}]", std::ios::fixed, 0, 0, "[fixed]");
882 TEST ("[%{If}]", std::ios::hex, 0, 0, "[hex]");
883 TEST ("[%{If}]", std::ios::internal, 0, 0, "[internal]");
884 TEST ("[%{If}]", std::ios::left, 0, 0, "[left]");
885 TEST ("[%{If}]", std::ios::oct, 0, 0, "[oct]");
886 TEST ("[%{If}]", std::ios::right, 0, 0, "[right]");
887 TEST ("[%{If}]", std::ios::scientific, 0, 0, "[scientific]");
888 TEST ("[%{If}]", std::ios::showbase, 0, 0, "[showbase]");
889 TEST ("[%{If}]", std::ios::showpoint, 0, 0, "[showpoint]");
890 TEST ("[%{If}]", std::ios::showpos, 0, 0, "[showpos]");
891 TEST ("[%{If}]", std::ios::skipws, 0, 0, "[skipws]");
892 TEST ("[%{If}]", std::ios::unitbuf, 0, 0, "[unitbuf]");
893 TEST ("[%{If}]", std::ios::uppercase, 0, 0, "[uppercase]");
894#ifndef _RWSTD_NO_EXT_BIN_IO
895 TEST ("[%{If}]", std::ios::bin, 0, 0, "[bin]");
896#endif // _RWSTD_NO_EXT_BIN_IO
897#ifndef _RWSTD_NO_EXT_REENTRANT_IO
898 TEST ("[%{If}]", std::ios::nolock, 0, 0, "[nolock]");
899 TEST ("[%{If}]", std::ios::nolockbuf, 0, 0, "[nolockbuf]");
900#endif // _RWSTD_NO_EXT_REENTRANT_IO
901
902 TEST ("[%{If}]", BASE (1), 0, 0, "[fmtflags(0) | base(1)]");
903 TEST ("[%{If}]", BASE (2), 0, 0, "[fmtflags(0) | base(2)]");
904 TEST ("[%{If}]", BASE (3), 0, 0, "[fmtflags(0) | base(3)]");
905 TEST ("[%{If}]", BASE (4), 0, 0, "[fmtflags(0) | base(4)]");
906 TEST ("[%{If}]", BASE (5), 0, 0, "[fmtflags(0) | base(5)]");
907 TEST ("[%{If}]", BASE (6), 0, 0, "[fmtflags(0) | base(6)]");
908 TEST ("[%{If}]", BASE (7), 0, 0, "[fmtflags(0) | base(7)]");
909 TEST ("[%{If}]", BASE (8), 0, 0, "[fmtflags(0)]");
910 TEST ("[%{If}]", BASE (9), 0, 0, "[fmtflags(0) | base(9)]");
911 TEST ("[%{If}]", BASE (10), 0, 0, "[fmtflags(0)]");
912 TEST ("[%{If}]", BASE (11), 0, 0, "[fmtflags(0) | base(11)]");
913 TEST ("[%{If}]", BASE (12), 0, 0, "[fmtflags(0) | base(12)]");
914 TEST ("[%{If}]", BASE (13), 0, 0, "[fmtflags(0) | base(13)]");
915 TEST ("[%{If}]", BASE (14), 0, 0, "[fmtflags(0) | base(14)]");
916 TEST ("[%{If}]", BASE (15), 0, 0, "[fmtflags(0) | base(15)]");
917 TEST ("[%{If}]", BASE (16), 0, 0, "[fmtflags(0)]");
918 TEST ("[%{If}]", BASE (17), 0, 0, "[fmtflags(0) | base(17)]");
919 TEST ("[%{If}]", BASE (18), 0, 0, "[fmtflags(0) | base(18)]");
920 TEST ("[%{If}]", BASE (19), 0, 0, "[fmtflags(0) | base(19)]");
921 TEST ("[%{If}]", BASE (20), 0, 0, "[fmtflags(0) | base(20)]");
922 TEST ("[%{If}]", BASE (21), 0, 0, "[fmtflags(0) | base(21)]");
923 TEST ("[%{If}]", BASE (22), 0, 0, "[fmtflags(0) | base(22)]");
924 TEST ("[%{If}]", BASE (23), 0, 0, "[fmtflags(0) | base(23)]");
925 TEST ("[%{If}]", BASE (24), 0, 0, "[fmtflags(0) | base(24)]");
926 TEST ("[%{If}]", BASE (25), 0, 0, "[fmtflags(0) | base(25)]");
927 TEST ("[%{If}]", BASE (26), 0, 0, "[fmtflags(0) | base(26)]");
928 TEST ("[%{If}]", BASE (27), 0, 0, "[fmtflags(0) | base(27)]");
929 TEST ("[%{If}]", BASE (28), 0, 0, "[fmtflags(0) | base(28)]");
930 TEST ("[%{If}]", BASE (29), 0, 0, "[fmtflags(0) | base(29)]");
931 TEST ("[%{If}]", BASE (30), 0, 0, "[fmtflags(0) | base(30)]");
932 TEST ("[%{If}]", BASE (31), 0, 0, "[fmtflags(0) | base(31)]");
933 TEST ("[%{If}]", BASE (32), 0, 0, "[fmtflags(0) | base(32)]");
934 TEST ("[%{If}]", BASE (33), 0, 0, "[fmtflags(0) | base(33)]");
935 TEST ("[%{If}]", BASE (34), 0, 0, "[fmtflags(0) | base(34)]");
936 TEST ("[%{If}]", BASE (35), 0, 0, "[fmtflags(0) | base(35)]");
937 TEST ("[%{If}]", BASE (36), 0, 0, "[fmtflags(0) | base(36)]");
938
939 TEST ("[%{#If}]", 0, 0, 0, "[std::ios::fmtflags(0)]");
940 TEST ("[%{#If}]", std::ios::adjustfield, 0, 0, "[std::ios::adjustfield]");
941 TEST ("[%{#If}]", std::ios::basefield, 0, 0, "[std::ios::basefield]");
942 TEST ("[%{#If}]", std::ios::boolalpha, 0, 0, "[std::ios::boolalpha]");
943 TEST ("[%{#If}]", std::ios::dec, 0, 0, "[std::ios::dec]");
944 TEST ("[%{#If}]", std::ios::fixed, 0, 0, "[std::ios::fixed]");
945 TEST ("[%{#If}]", std::ios::hex, 0, 0, "[std::ios::hex]");
946 TEST ("[%{#If}]", std::ios::internal, 0, 0, "[std::ios::internal]");
947 TEST ("[%{#If}]", std::ios::left, 0, 0, "[std::ios::left]");
948 TEST ("[%{#If}]", std::ios::oct, 0, 0, "[std::ios::oct]");
949 TEST ("[%{#If}]", std::ios::right, 0, 0, "[std::ios::right]");
950 TEST ("[%{#If}]", std::ios::scientific, 0, 0, "[std::ios::scientific]");
951 TEST ("[%{#If}]", std::ios::showbase, 0, 0, "[std::ios::showbase]");
952 TEST ("[%{#If}]", std::ios::showpoint, 0, 0, "[std::ios::showpoint]");
953 TEST ("[%{#If}]", std::ios::showpos, 0, 0, "[std::ios::showpos]");
954 TEST ("[%{#If}]", std::ios::skipws, 0, 0, "[std::ios::skipws]");
955 TEST ("[%{#If}]", std::ios::unitbuf, 0, 0, "[std::ios::unitbuf]");
956 TEST ("[%{#If}]", std::ios::uppercase, 0, 0, "[std::ios::uppercase]");
957#ifndef _RWSTD_NO_EXT_BIN_IO
958 TEST ("[%{#If}]", std::ios::bin, 0, 0, "[std::ios::bin]");
959#endif // _RWSTD_NO_EXT_BIN_IO
960#ifndef _RWSTD_NO_EXT_REENTRANT_IO
961 TEST ("[%{#If}]", std::ios::nolock, 0, 0, "[std::ios::nolock]");
962 TEST ("[%{#If}]", std::ios::nolockbuf, 0, 0, "[std::ios::nolockbuf]");
963#endif // _RWSTD_NO_EXT_REENTRANT_IO
964
965 TEST ("[%{#If}]", BASE (1), 0, 0,
966 "[std::ios::fmtflags(0) | std::ios::base(1)]");
967 TEST ("[%{#If}]", BASE (2), 0, 0,
968 "[std::ios::fmtflags(0) | std::ios::base(2)]");
969 TEST ("[%{#If}]", BASE (3), 0, 0,
970 "[std::ios::fmtflags(0) | std::ios::base(3)]");
971 TEST ("[%{#If}]", BASE (4), 0, 0,
972 "[std::ios::fmtflags(0) | std::ios::base(4)]");
973 TEST ("[%{#If}]", BASE (5), 0, 0,
974 "[std::ios::fmtflags(0) | std::ios::base(5)]");
975 TEST ("[%{#If}]", BASE (6), 0, 0,
976 "[std::ios::fmtflags(0) | std::ios::base(6)]");
977 TEST ("[%{#If}]", BASE (7), 0, 0,
978 "[std::ios::fmtflags(0) | std::ios::base(7)]");
979 TEST ("[%{#If}]", BASE (8), 0, 0,
980 "[std::ios::fmtflags(0)]");
981 TEST ("[%{#If}]", BASE (9), 0, 0,
982 "[std::ios::fmtflags(0) | std::ios::base(9)]");
983 TEST ("[%{#If}]", BASE (10), 0, 0,
984 "[std::ios::fmtflags(0)]");
985 TEST ("[%{#If}]", BASE (11), 0, 0,
986 "[std::ios::fmtflags(0) | std::ios::base(11)]");
987 TEST ("[%{#If}]", BASE (12), 0, 0,
988 "[std::ios::fmtflags(0) | std::ios::base(12)]");
989 TEST ("[%{#If}]", BASE (13), 0, 0,
990 "[std::ios::fmtflags(0) | std::ios::base(13)]");
991 TEST ("[%{#If}]", BASE (14), 0, 0,
992 "[std::ios::fmtflags(0) | std::ios::base(14)]");
993 TEST ("[%{#If}]", BASE (15), 0, 0,
994 "[std::ios::fmtflags(0) | std::ios::base(15)]");
995 TEST ("[%{#If}]", BASE (16), 0, 0,
996 "[std::ios::fmtflags(0)]");
997 TEST ("[%{#If}]", BASE (17), 0, 0,
998 "[std::ios::fmtflags(0) | std::ios::base(17)]");
999 TEST ("[%{#If}]", BASE (18), 0, 0,
1000 "[std::ios::fmtflags(0) | std::ios::base(18)]");
1001 TEST ("[%{#If}]", BASE (19), 0, 0,
1002 "[std::ios::fmtflags(0) | std::ios::base(19)]");
1003 TEST ("[%{#If}]", BASE (20), 0, 0,
1004 "[std::ios::fmtflags(0) | std::ios::base(20)]");
1005 TEST ("[%{#If}]", BASE (21), 0, 0,
1006 "[std::ios::fmtflags(0) | std::ios::base(21)]");
1007 TEST ("[%{#If}]", BASE (22), 0, 0,
1008 "[std::ios::fmtflags(0) | std::ios::base(22)]");
1009 TEST ("[%{#If}]", BASE (23), 0, 0,
1010 "[std::ios::fmtflags(0) | std::ios::base(23)]");
1011 TEST ("[%{#If}]", BASE (24), 0, 0,
1012 "[std::ios::fmtflags(0) | std::ios::base(24)]");
1013 TEST ("[%{#If}]", BASE (25), 0, 0,
1014 "[std::ios::fmtflags(0) | std::ios::base(25)]");
1015 TEST ("[%{#If}]", BASE (26), 0, 0,
1016 "[std::ios::fmtflags(0) | std::ios::base(26)]");
1017 TEST ("[%{#If}]", BASE (27), 0, 0,
1018 "[std::ios::fmtflags(0) | std::ios::base(27)]");
1019 TEST ("[%{#If}]", BASE (28), 0, 0,
1020 "[std::ios::fmtflags(0) | std::ios::base(28)]");
1021 TEST ("[%{#If}]", BASE (29), 0, 0,
1022 "[std::ios::fmtflags(0) | std::ios::base(29)]");
1023 TEST ("[%{#If}]", BASE (30), 0, 0,
1024 "[std::ios::fmtflags(0) | std::ios::base(30)]");
1025 TEST ("[%{#If}]", BASE (31), 0, 0,
1026 "[std::ios::fmtflags(0) | std::ios::base(31)]");
1027 TEST ("[%{#If}]", BASE (32), 0, 0,
1028 "[std::ios::fmtflags(0) | std::ios::base(32)]");
1029 TEST ("[%{#If}]", BASE (33), 0, 0,
1030 "[std::ios::fmtflags(0) | std::ios::base(33)]");
1031 TEST ("[%{#If}]", BASE (34), 0, 0,
1032 "[std::ios::fmtflags(0) | std::ios::base(34)]");
1033 TEST ("[%{#If}]", BASE (35), 0, 0,
1034 "[std::ios::fmtflags(0) | std::ios::base(35)]");
1035 TEST ("[%{#If}]", BASE (36), 0, 0,
1036 "[std::ios::fmtflags(0) | std::ios::base(36)]");
1037
1039 printf ("%s\n", "extension: \"%{Ie}\": std::ios_base::event");
1040
1041 TEST ("[%{Ie}]", std::ios::erase_event, 0, 0, "[erase_event]");
1042 TEST ("[%{Ie}]", std::ios::imbue_event, 0, 0, "[imbue_event]");
1043 TEST ("[%{Ie}]", std::ios::copyfmt_event, 0, 0, "[copyfmt_event]");
1044 TEST ("[%{Ie}]", 3, 0, 0, "[event(3)]");
1045 TEST ("[%{Ie}]", 10, 0, 0, "[event(10)]");
1046
1047 TEST ("[%{#Ie}]", std::ios::erase_event, 0, 0,
1048 "[std::ios::erase_event]");
1049 TEST ("[%{#Ie}]", std::ios::imbue_event, 0, 0,
1050 "[std::ios::imbue_event]");
1051 TEST ("[%{#Ie}]", std::ios::copyfmt_event, 0, 0,
1052 "[std::ios::copyfmt_event]");
1053 TEST ("[%{#Ie}]", 3, 0, 0,
1054 "[std::ios::event(3)]");
1055 TEST ("[%{#Ie}]", 10, 0, 0,
1056 "[std::ios::event(10)]");
1057}
1058
1059
1061static void
1062test_locale_category ()
1063{
1065 printf ("%s\n", "extension: \"%{Lc}\": locale category");
1066
1067 TEST ("[%{Lc}]", LC_ALL, 0, 0, "[LC_ALL]");
1068 TEST ("[%{Lc}]", LC_COLLATE, 0, 0, "[LC_COLLATE]");
1069 TEST ("[%{Lc}]", LC_CTYPE, 0, 0, "[LC_CTYPE]");
1070 TEST ("[%{Lc}]", LC_MONETARY, 0, 0, "[LC_MONETARY]");
1071 TEST ("[%{Lc}]", LC_NUMERIC, 0, 0, "[LC_NUMERIC]");
1072 TEST ("[%{Lc}]", LC_TIME, 0, 0, "[LC_TIME]");
1073#ifdef LC_MESSAGES
1074 TEST ("[%{Lc}]", LC_MESSAGES, 0, 0, "[LC_MESSAGES]");
1075#endif // LC_MESSAGES
1076
1077 TEST ("[%{Lc}]", std::locale::all, 0, 0, "[all]");
1078 TEST ("[%{Lc}]", std::locale::none, 0, 0, "[none]");
1079 TEST ("[%{Lc}]", std::locale::collate, 0, 0, "[collate]");
1080 TEST ("[%{Lc}]", std::locale::ctype, 0, 0, "[ctype]");
1081 TEST ("[%{Lc}]", std::locale::monetary, 0, 0, "[monetary]");
1082 TEST ("[%{Lc}]", std::locale::numeric, 0, 0, "[numeric]");
1083 TEST ("[%{Lc}]", std::locale::messages, 0, 0, "[messages]");
1084 TEST ("[%{Lc}]", std::locale::time, 0, 0, "[time]");
1085
1086 TEST ("[%{#Lc}]", LC_ALL, 0, 0, "[LC_ALL]");
1087 TEST ("[%{#Lc}]", LC_COLLATE, 0, 0, "[LC_COLLATE]");
1088 TEST ("[%{#Lc}]", LC_CTYPE, 0, 0, "[LC_CTYPE]");
1089 TEST ("[%{#Lc}]", LC_MONETARY, 0, 0, "[LC_MONETARY]");
1090 TEST ("[%{#Lc}]", LC_NUMERIC, 0, 0, "[LC_NUMERIC]");
1091 TEST ("[%{#Lc}]", LC_TIME, 0, 0, "[LC_TIME]");
1092#ifdef LC_MESSAGES
1093 TEST ("[%{#Lc}]", LC_MESSAGES, 0, 0, "[LC_MESSAGES]");
1094#endif // LC_MESSAGES
1095
1096 TEST ("[%{#Lc}]", std::locale::all, 0, 0, "[std::locale::all]");
1097 TEST ("[%{#Lc}]", std::locale::none, 0, 0, "[std::locale::none]");
1098 TEST ("[%{#Lc}]", std::locale::collate, 0, 0, "[std::locale::collate]");
1099 TEST ("[%{#Lc}]", std::locale::ctype, 0, 0, "[std::locale::ctype]");
1100 TEST ("[%{#Lc}]", std::locale::monetary, 0, 0, "[std::locale::monetary]");
1101 TEST ("[%{#Lc}]", std::locale::numeric, 0, 0, "[std::locale::numeric]");
1102 TEST ("[%{#Lc}]", std::locale::messages, 0, 0, "[std::locale::messages]");
1103 TEST ("[%{#Lc}]", std::locale::time, 0, 0, "[std::locale::time]");
1104}
1105
1106
1108static void
1109test_ctype_mask ()
1110{
1112 printf ("%s\n", "extension: \"%{LC}\": std::ctype_base::mask");
1113
1114 const int Alpha = std::ctype_base::alpha;
1115 const int Alnum = std::ctype_base::alnum;
1116 const int Cntrl = std::ctype_base::cntrl;
1117 const int Digit = std::ctype_base::digit;
1118 const int Graph = std::ctype_base::graph;
1119 const int Lower = std::ctype_base::lower;
1120 const int Print = std::ctype_base::print;
1121 const int Punct = std::ctype_base::punct;
1122 const int Space = std::ctype_base::space;
1123 const int Xdigit = std::ctype_base::xdigit;
1124
1125 TEST ("[%{LC}]", Alpha, 0, 0, "[alpha]");
1126 TEST ("[%{LC}]", Alnum, 0, 0, "[alnum]");
1127 TEST ("[%{LC}]", Cntrl, 0, 0, "[cntrl]");
1128 TEST ("[%{LC}]", Digit, 0, 0, "[digit]");
1129 TEST ("[%{LC}]", Graph, 0, 0, "[graph]");
1130 TEST ("[%{LC}]", Lower, 0, 0, "[lower]");
1131 TEST ("[%{LC}]", Print, 0, 0, "[print]");
1132 TEST ("[%{LC}]", Punct, 0, 0, "[punct]");
1133 TEST ("[%{LC}]", Space, 0, 0, "[space]");
1134 TEST ("[%{LC}]", Xdigit, 0, 0, "[xdigit]");
1135
1136 TEST ("[%{#LC}]", Alpha, 0, 0, "[std::ctype_base::alpha]");
1137 TEST ("[%{#LC}]", Alnum, 0, 0, "[std::ctype_base::alnum]");
1138 TEST ("[%{#LC}]", Cntrl, 0, 0, "[std::ctype_base::cntrl]");
1139 TEST ("[%{#LC}]", Digit, 0, 0, "[std::ctype_base::digit]");
1140 TEST ("[%{#LC}]", Graph, 0, 0, "[std::ctype_base::graph]");
1141 TEST ("[%{#LC}]", Lower, 0, 0, "[std::ctype_base::lower]");
1142 TEST ("[%{#LC}]", Print, 0, 0, "[std::ctype_base::print]");
1143 TEST ("[%{#LC}]", Punct, 0, 0, "[std::ctype_base::punct]");
1144 TEST ("[%{#LC}]", Space, 0, 0, "[std::ctype_base::space]");
1145 TEST ("[%{#LC}]", Xdigit, 0, 0, "[std::ctype_base::xdigit]");
1146
1147 TEST ("[%{LC}]", Alpha | Cntrl, 0, 0, "[alpha | cntrl]");
1148 TEST ("[%{LC}]", Cntrl | Digit, 0, 0, "[cntrl | digit]");
1149 TEST ("[%{LC}]", Digit | Graph, 0, 0, "[digit | graph]");
1150 TEST ("[%{LC}]", Graph | Lower, 0, 0, "[graph | lower]");
1151 TEST ("[%{LC}]", Lower | Print, 0, 0, "[lower | print]");
1152 TEST ("[%{LC}]", Print | Punct, 0, 0, "[print | punct]");
1153 TEST ("[%{LC}]", Punct | Space, 0, 0, "[punct | space]");
1154}
1155
1156
1159static const char*
1160mkbitset (const char *str)
1161{
1162 static char bitset [32];
1163
1164 memset (bitset, 0, sizeof bitset);
1165
1166 char *pbyte = bitset;
1167
1168 for (const char *pc = str; *pc; ++pc) {
1169
1170 const size_t bitno = size_t (pc - str);
1171
1172 if ((bitno & 15) == 8)
1173 ++pbyte;
1174
1175 const size_t binx = bitno & 7;
1176
1177 if ('0' == *pc)
1178 *pbyte &= ~(1 << binx);
1179 else if ('1' == *pc)
1180 *pbyte |= 1 << binx;
1181 else
1182 RW_ASSERT (!"logic error: bit must be '0' or '1'");
1183
1184 RW_ASSERT (size_t (pbyte - bitset) < sizeof bitset);
1185 }
1186
1187 return bitset;
1188}
1189
1190
1191static void
1192test_bitset ()
1193{
1195 printf ("%s\n", "extension: \"%{b}\": bitset");
1196
1197#define BS(str) mkbitset (str)
1198
1199 TEST ("%{b}", 0, 0, 0, "(null)");
1200 TEST ("%{.1b}", BS ("1"), 0, 0, "1");
1201 TEST ("%{.2b}", BS ("1"), 0, 0, "10");
1202 TEST ("%{.3b}", BS ("1"), 0, 0, "100");
1203 TEST ("%{.3b}", BS ("101"), 0, 0, "101");
1204 TEST ("%{.8b}", BS ("11111111"), 0, 0, "11111111");
1205 TEST ("%{.16b}", BS ("0000000000000000"), 0, 0, "0000000000000000");
1206 TEST ("%{.16b}", BS ("0000000000000001"), 0, 0, "0000000000000001");
1207 TEST ("%{.16b}", BS ("0000000000000010"), 0, 0, "0000000000000010");
1208 TEST ("%{.16b}", BS ("0000000000000100"), 0, 0, "0000000000000100");
1209 TEST ("%{.16b}", BS ("0000000000001000"), 0, 0, "0000000000001000");
1210 TEST ("%{.16b}", BS ("0000000000010000"), 0, 0, "0000000000010000");
1211 TEST ("%{.16b}", BS ("0000000000100000"), 0, 0, "0000000000100000");
1212 TEST ("%{.16b}", BS ("0000000001000000"), 0, 0, "0000000001000000");
1213 TEST ("%{.16b}", BS ("0000000010000000"), 0, 0, "0000000010000000");
1214 TEST ("%{.16b}", BS ("0000000100000000"), 0, 0, "0000000100000000");
1215 TEST ("%{.16b}", BS ("0000001000000000"), 0, 0, "0000001000000000");
1216 TEST ("%{.16b}", BS ("0000010000000000"), 0, 0, "0000010000000000");
1217 TEST ("%{.16b}", BS ("0000100000000000"), 0, 0, "0000100000000000");
1218 TEST ("%{.16b}", BS ("0001000000000000"), 0, 0, "0001000000000000");
1219 TEST ("%{.16b}", BS ("0010000000000000"), 0, 0, "0010000000000000");
1220 TEST ("%{.16b}", BS ("0100000000000000"), 0, 0, "0100000000000000");
1221 TEST ("%{.16b}", BS ("1000000000000000"), 0, 0, "1000000000000000");
1222}
1223
1224
1226static void
1227test_dec (char spec)
1228{
1229 const bool sgn = 'u' != spec;
1230
1231 // "%d", "%i" ////////////////////////////////////////////////////
1232 printf ("\"%%%c\": %ssigned integer\n", spec, sgn ? "" : "un");
1233
1234 TEST_SPEC ("%", 0, 0, 0, "0");
1235 TEST_SPEC ("%", 1, 0, 0, "1");
1236 TEST_SPEC ("%", 2, 0, 0, "2");
1237 TEST_SPEC ("%", 3, 0, 0, "3");
1238
1239 TEST_SPEC ("%", -1, 0, 0, sgn ? "-1" : "4294967295");
1240 TEST_SPEC ("%", -2, 0, 0, sgn ? "-2" : "4294967294");
1241 TEST_SPEC ("%", -3, 0, 0, sgn ? "-3" : "4294967293");
1242
1243 TEST_SPEC ("%+", 4, 0, 0, sgn ? "+4" : "4");
1244 TEST_SPEC ("%+", 5, 0, 0, sgn ? "+5" : "5");
1245 TEST_SPEC ("%+", 6, 0, 0, sgn ? "+6" : "6");
1246 TEST_SPEC ("%+", -4, 0, 0, sgn ? "-4" : "4294967292");
1247 TEST_SPEC ("%+", -5, 0, 0, sgn ? "-5" : "4294967291");
1248 TEST_SPEC ("%+", -6, 0, 0, sgn ? "-6" : "4294967290");
1249
1250 TEST_SPEC ("%", 123, 0, 0, "123");
1251 TEST_SPEC ("%", 2345, 0, 0, "2345");
1252 TEST_SPEC ("%", 34567, 0, 0, "34567");
1253
1254 TEST_SPEC ("%", -124, 0, 0, sgn ? "-124" : "4294967172");
1255 TEST_SPEC ("%", -2346, 0, 0, sgn ? "-2346" : "4294964950");
1256 TEST_SPEC ("%", -34568, 0, 0, sgn ? "-34568" : "4294932728");
1257
1258 TEST_SPEC ("%", INT_MIN, 0, 0, 0);
1259 TEST_SPEC ("%", INT_MAX, 0, 0, 0);
1260
1261 // exercise right justification
1262 TEST_SPEC ("%0", 3140, 0, 0, "3140");
1263 TEST_SPEC ("%1", 3141, 0, 0, "3141");
1264 TEST_SPEC ("%2", 3142, 0, 0, "3142");
1265 TEST_SPEC ("%3", 3143, 0, 0, "3143");
1266 TEST_SPEC ("%4", 3144, 0, 0, "3144");
1267 TEST_SPEC ("%5", 3145, 0, 0, " 3145");
1268 TEST_SPEC ("%6", 3146, 0, 0, " 3146");
1269 TEST_SPEC ("%7", 3147, 0, 0, " 3147");
1270 TEST_SPEC ("%+8", 3148, 0, 0, sgn ? " +3148" : " 3148");
1271 TEST_SPEC ("%9", -3149, 0, 0, sgn ? " -3149" : "4294964147");
1272
1273 // exercise left justification
1274 TEST_SPEC ("%-0", 4140, 0, 0, "4140");
1275 TEST_SPEC ("%-1", 4141, 0, 0, "4141");
1276 TEST_SPEC ("%-2", 4142, 0, 0, "4142");
1277 TEST_SPEC ("%-3", 4143, 0, 0, "4143");
1278 TEST_SPEC ("%-4", 4144, 0, 0, "4144");
1279 TEST_SPEC ("%-5", 4145, 0, 0, "4145 ");
1280 TEST_SPEC ("%-6", 4146, 0, 0, "4146 ");
1281 TEST_SPEC ("%-7", 4147, 0, 0, "4147 ");
1282 TEST_SPEC ("%-8", -4148, 0, 0, sgn ? "-4148 " : "4294963148");
1283 TEST_SPEC ("%+-9", 4149, 0, 0, sgn ? "+4149 " : "4149 ");
1284
1285 // exercise precision
1286 TEST_SPEC ("%.0", 5670, 0, 0, "5670");
1287 TEST_SPEC ("%.1", 5671, 0, 0, "5671");
1288 TEST_SPEC ("%.2", 5672, 0, 0, "5672");
1289 TEST_SPEC ("%.3", 5673, 0, 0, "5673");
1290 TEST_SPEC ("%.4", 5674, 0, 0, "5674");
1291 TEST_SPEC ("%.5", 5675, 0, 0, "05675");
1292 TEST_SPEC ("%.6", 5676, 0, 0, "005676");
1293 TEST_SPEC ("%.7", 5677, 0, 0, "0005677");
1294 TEST_SPEC ("%.8", -5678, 0, 0, sgn ? "-00005678" : "4294961618");
1295 TEST_SPEC ("%+.9", 5679, 0, 0, sgn ? "+000005679" : "000005679");
1296
1297 // exercise justification with precision
1298 TEST_SPEC ("%3.0", 30, 0, 0, " 30");
1299 TEST_SPEC ("%3.1", 31, 0, 0, " 31");
1300 TEST_SPEC ("%3.2", 32, 0, 0, " 32");
1301 TEST_SPEC ("%3.3", 33, 0, 0, "033");
1302 TEST_SPEC ("%3.4", 34, 0, 0, "0034");
1303 TEST_SPEC ("%3.5", 35, 0, 0, "00035");
1304 TEST_SPEC ("%4.5", 45, 0, 0, "00045");
1305 TEST_SPEC ("%5.5", 55, 0, 0, "00055");
1306 TEST_SPEC ("%6.5", 65, 0, 0, " 00065");
1307 TEST_SPEC ("%7.5", 75, 0, 0, " 00075");
1308 TEST_SPEC ("%8.5", 85, 0, 0, " 00085");
1309 TEST_SPEC ("%9.5", 95, 0, 0, " 00095");
1310 TEST_SPEC ("%9.6", -96, 0, 0, sgn ? " -000096" : "4294967200");
1311 TEST_SPEC ("%+9.7", 97, 0, 0, sgn ? " +0000097" : " 0000097");
1312 TEST_SPEC ("%+-9.8", 98, 0, 0, sgn ? "+00000098" : "00000098 ");
1313 TEST_SPEC ("%-+9.9", 99, 0, 0, sgn ? "+000000099" : "000000099");
1314
1315 // exercise edge cases
1316
1317 // 7.19.6.1 of ISO/IEC 9899:1999:
1318 // The result of converting a zero value with a precision
1319 // of zero is no characters.
1320 TEST_SPEC ("%.0", 0, 0, 0, "");
1321 TEST_SPEC ("%1.0", 0, 0, 0, " ");
1322 TEST_SPEC ("%2.0", 0, 0, 0, " ");
1323 TEST_SPEC ("%+3.0", 0, 0, 0, " ");
1324 TEST_SPEC ("%-4.0", 0, 0, 0, " ");
1325
1326 // 7.19.6.1, p5 of ISO/IEC 9899:1999:
1327 // A negative field width argument is taken as
1328 // a - flag followed by a positive field width.
1329 // A negative precision argument is taken as
1330 // if the precision were omitted.
1331
1332 TEST_SPEC ("%*", 0, 0, 0, "0");
1333 TEST_SPEC ("%*", 1, 1, 0, "1");
1334 TEST_SPEC ("%*", 2, 2, 0, " 2");
1335 TEST_SPEC ("%*", 3, 3, 0, " 3");
1336 TEST_SPEC ("%*", -4, -4, 0, sgn ? "-4 " : "4294967292");
1337 TEST_SPEC ("%-*", 5, 5, 0, "5 ");
1338 TEST_SPEC ("%-*", -6, -6, 0, sgn ? "-6 " : "4294967290");
1339
1340 TEST_SPEC ("%*.*", 0, 0, 0, "");
1341 TEST_SPEC ("%*.*", 1, 0, 0, " ");
1342 TEST_SPEC ("%*.*", 2, 0, 0, " ");
1343 TEST_SPEC ("%*.*", 2, 0, 1, " 1");
1344 TEST_SPEC ("%*.*", 2, 1, 2, " 2");
1345 TEST_SPEC ("%*.*", 2, 2, 2, "02");
1346 TEST_SPEC ("%*.*", -3, 2, 3, "03 ");
1347 TEST_SPEC ("%-*.*", -4, 2, -4, sgn ? "-04 " : "4294967292");
1348 TEST_SPEC ("%-*.*", -4, -2, -4, sgn ? "-4 " : "4294967292");
1349
1350 // "%hhd", "%hhi", ///////////////////////////////////////////////
1351 printf ("\"%%hh%c\": %ssigned char\n", spec, sgn ? "" : "un");
1352
1353 TEST_SPEC ("%hh", '\0', 0, 0, "0");
1354 TEST_SPEC ("%hh", '\1', 0, 0, "1");
1355 TEST_SPEC ("%hh", '\2', 0, 0, "2");
1356 TEST_SPEC ("%hh", '\x7f', 0, 0, "127");
1357
1358 TEST_SPEC ("%hh", '\x80', 0, 0, sgn ? "-128" : "128");
1359 TEST_SPEC ("%hh", '\xff', 0, 0, sgn ? "-1" : "255");
1360
1361 // "%hd", "%hi" //////////////////////////////////////////////////
1362 printf ("\"%%h%c\": %ssigned short\n", spec, sgn ? "" : "un");
1363
1364 TEST_SPEC ("%h", short (0), 0, 0, "0");
1365 TEST_SPEC ("%h", short (1), 0, 0, "1");
1366 TEST_SPEC ("%h", short (2), 0, 0, "2");
1367
1368 TEST_SPEC ("%h", SHRT_MIN, 0, 0, 0);
1369 TEST_SPEC ("%h", SHRT_MAX, 0, 0, 0);
1370
1371 // "%ld", "%li" //////////////////////////////////////////////////
1372 printf ("\"%%l%c\": signed long\n", spec);
1373
1374 TEST_SPEC ("%l", 0L, 0, 0, "0");
1375 TEST_SPEC ("%l", 1L, 0, 0, "1");
1376 TEST_SPEC ("%l", 2L, 0, 0, "2");
1377 TEST_SPEC ("%l", LONG_MAX, 0, 0, 0);
1378
1379 TEST_SPEC ("%l", -1L, 0, 0, 0);
1380 TEST_SPEC ("%l", -2L, 0, 0, 0);
1381 TEST_SPEC ("%l", LONG_MIN, 0, 0, 0);
1382
1383#ifndef _RWSTD_NO_LONG_LONG
1384
1385 // "%lld", "%lli" ////////////////////////////////////////////////
1386 printf ("\"%%ll%c\": signed long long\n", spec);
1387
1388 const _RWSTD_LONG_LONG llong_min = _RWSTD_LLONG_MIN;
1389 const _RWSTD_LONG_LONG llong_max = _RWSTD_LLONG_MAX;
1390
1391 TEST_SPEC ("%ll", 0LL, 0, 0, "0");
1392 TEST_SPEC ("%ll", 1LL, 0, 0, "1");
1393 TEST_SPEC ("%ll", 12LL, 0, 0, "12");
1394 TEST_SPEC ("%ll", 123LL, 0, 0, "123");
1395 TEST_SPEC ("%ll", 1234LL, 0, 0, "1234");
1396 TEST_SPEC ("%ll", 12345LL, 0, 0, "12345");
1397 TEST_SPEC ("%ll", 123456LL, 0, 0, "123456");
1398 TEST_SPEC ("%ll", 1234567LL, 0, 0, "1234567");
1399 TEST_SPEC ("%ll", 12345678LL, 0, 0, "12345678");
1400 TEST_SPEC ("%ll", 123456789LL, 0, 0, "123456789");
1401
1402# if 4 == _RWSTD_LLONG_SIZE
1403
1404 // FIXME: exercise 32-bit negative long long
1405
1406 fprintf (stderr, "Warning: %s\n", "\"%lld\" not exercised "
1407 "with negative values for %u-bit long long",
1408 sizeof (RWSTD_LONG_LONG) * CHAR_BIT);
1409
1410# elif 8 == _RWSTD_LLONG_SIZE
1411
1412 TEST_SPEC ("%ll", -1LL, 0, 0, sgn ? "-1" : "18446744073709551615");
1413 TEST_SPEC ("%ll", -2LL, 0, 0, sgn ? "-2" : "18446744073709551614");
1414 TEST_SPEC ("%ll", -3LL, 0, 0, sgn ? "-3" : "18446744073709551613");
1415
1416 TEST_SPEC ("%ll", llong_min, 0, 0,
1417 sgn ? "-9223372036854775808" : "9223372036854775808");
1418 TEST_SPEC ("%ll", llong_min + 1, 0, 0,
1419 sgn ? "-9223372036854775807" : "9223372036854775809");
1420 TEST_SPEC ("%ll", llong_min + 2, 0, 0,
1421 sgn ? "-9223372036854775806" : "9223372036854775810");
1422
1423 TEST_SPEC ("%ll", llong_max, 0, 0, "9223372036854775807");
1424 TEST_SPEC ("%ll", llong_max - 1, 0, 0, "9223372036854775806");
1425
1426# endif
1427
1428#else // if defined (_RWSTD_NO_LONG_LONG)
1429
1430 fprintf (stderr, "Warning: %s\n", "\"%lld\" not exercised");
1431
1432#endif // _RWSTD_NO_LONG_LONG
1433}
1434
1435
1437static void
1438test_oct ()
1439{
1440 printf ("%s\n", "\"%o\": octal integer");
1441
1442 TEST ("%o", 0, 0, 0, "0");
1443 TEST ("%o", 1, 0, 0, "1");
1444 TEST ("%o", 2, 0, 0, "2");
1445 TEST ("%o", 3, 0, 0, "3");
1446 TEST ("%o", 4, 0, 0, "4");
1447 TEST ("%o", 5, 0, 0, "5");
1448 TEST ("%o", 6, 0, 0, "6");
1449 TEST ("%o", 7, 0, 0, "7");
1450 TEST ("%o", 8, 0, 0, "10");
1451 TEST ("%o", 9, 0, 0, "11");
1452 TEST ("%o", 10, 0, 0, "12");
1453
1454 TEST ("%#o", 11, 0, 0, "013");
1455}
1456
1457
1459static void
1460test_hex (char spec)
1461{
1462 printf ("\"%%%c\": hexadecimal integer\n", spec);
1463
1464 // exercise by comparing against libc sprintf()
1465 TEST_SPEC ("%", 0, 0, 0, 0);
1466 TEST_SPEC ("%", 1, 0, 0, 0);
1467 TEST_SPEC ("%", 2, 0, 0, 0);
1468 TEST_SPEC ("%", 3, 0, 0, 0);
1469 TEST_SPEC ("%", 9, 0, 0, 0);
1470 TEST_SPEC ("%", 10, 0, 0, 0);
1471 TEST_SPEC ("%", 11, 0, 0, 0);
1472 TEST_SPEC ("%", 12, 0, 0, 0);
1473 TEST_SPEC ("%", 13, 0, 0, 0);
1474 TEST_SPEC ("%", 14, 0, 0, 0);
1475 TEST_SPEC ("%", 15, 0, 0, 0);
1476 TEST_SPEC ("%", 123, 0, 0, 0);
1477 TEST_SPEC ("%", 234, 0, 0, 0);
1478 TEST_SPEC ("%", 345, 0, 0, 0);
1479 TEST_SPEC ("%", -1, 0, 0, 0);
1480 TEST_SPEC ("%", -2, 0, 0, 0);
1481 TEST_SPEC ("%", -3, 0, 0, 0);
1482 TEST_SPEC ("%", -4, 0, 0, 0);
1483
1484 TEST_SPEC ("%+", 0, 0, 0, 0);
1485 TEST_SPEC ("%+", 1, 0, 0, 0);
1486 TEST_SPEC ("%+", 2, 0, 0, 0);
1487 TEST_SPEC ("%+", 3, 0, 0, 0);
1488 TEST_SPEC ("%+", 4, 0, 0, 0);
1489 TEST_SPEC ("%+", 5, 0, 0, 0);
1490 TEST_SPEC ("%+", 6, 0, 0, 0);
1491 TEST_SPEC ("%+", 15, 0, 0, 0);
1492 TEST_SPEC ("%+", 16, 0, 0, 0);
1493
1494 TEST_SPEC ("%+", -1, 0, 0, 0);
1495 TEST_SPEC ("%+", -2, 0, 0, 0);
1496 TEST_SPEC ("%+", -3, 0, 0, 0);
1497 TEST_SPEC ("%+", -4, 0, 0, 0);
1498 TEST_SPEC ("%+", -5, 0, 0, 0);
1499 TEST_SPEC ("%+", -6, 0, 0, 0);
1500 TEST_SPEC ("%+", -15, 0, 0, 0);
1501 TEST_SPEC ("%+", -16, 0, 0, 0);
1502
1503 TEST_SPEC ("%#", 0, 0, 0, "0");
1504 TEST_SPEC ("%#", 1, 0, 0, 0);
1505 TEST_SPEC ("%#", 20, 0, 0, 0);
1506 TEST_SPEC ("%#", -30, 0, 0, 0);
1507
1508 TEST_SPEC ("%0", 0, 0, 0, "0");
1509 TEST_SPEC ("%0", 2, 0, 0, 0);
1510 TEST_SPEC ("%0", 21, 0, 0, 0);
1511 TEST_SPEC ("%0", -32, 0, 0, 0);
1512
1513 // exercise right justification
1514 TEST_SPEC ("%0", 1000, 0, 0, 0);
1515 TEST_SPEC ("%1", 1001, 0, 0, 0);
1516 TEST_SPEC ("%2", 1002, 0, 0, 0);
1517 TEST_SPEC ("%3", 1003, 0, 0, 0);
1518 TEST_SPEC ("%4", 1004, 0, 0, 0);
1519 TEST_SPEC ("%5", 1005, 0, 0, 0);
1520 TEST_SPEC ("%6", 1006, 0, 0, 0);
1521 TEST_SPEC ("%7", 1007, 0, 0, 0);
1522 TEST_SPEC ("%8", 1008, 0, 0, 0);
1523 TEST_SPEC ("%9", 1009, 0, 0, 0);
1524 TEST_SPEC ("%10", 1010, 0, 0, 0);
1525
1526 TEST_SPEC ("%11", -1011, 0, 0, 0);
1527 TEST_SPEC ("%12", -1012, 0, 0, 0);
1528 TEST_SPEC ("%13", -1013, 0, 0, 0);
1529 TEST_SPEC ("%14", -1014, 0, 0, 0);
1530 TEST_SPEC ("%15", -1015, 0, 0, 0);
1531 TEST_SPEC ("%16", -1016, 0, 0, 0);
1532 TEST_SPEC ("%17", -1017, 0, 0, 0);
1533 TEST_SPEC ("%18", -1018, 0, 0, 0);
1534 TEST_SPEC ("%19", -1019, 0, 0, 0);
1535 TEST_SPEC ("%20", -1020, 0, 0, 0);
1536
1537 // exercise left justification
1538 TEST_SPEC ("%-0", 2000, 0, 0, 0);
1539 TEST_SPEC ("%-1", 2001, 0, 0, 0);
1540 TEST_SPEC ("%-2", 2002, 0, 0, 0);
1541 TEST_SPEC ("%-3", 2003, 0, 0, 0);
1542 TEST_SPEC ("%-4", 2004, 0, 0, 0);
1543 TEST_SPEC ("%-5", 2005, 0, 0, 0);
1544 TEST_SPEC ("%-6", 2006, 0, 0, 0);
1545 TEST_SPEC ("%-7", 2007, 0, 0, 0);
1546 TEST_SPEC ("%-8", 2008, 0, 0, 0);
1547 TEST_SPEC ("%-9", 2009, 0, 0, 0);
1548 TEST_SPEC ("%-10", 2010, 0, 0, 0);
1549
1550 TEST_SPEC ("%-11", -2011, 0, 0, 0);
1551 TEST_SPEC ("%-12", -2012, 0, 0, 0);
1552 TEST_SPEC ("%-13", -2013, 0, 0, 0);
1553 TEST_SPEC ("%-14", -2014, 0, 0, 0);
1554 TEST_SPEC ("%-15", -2015, 0, 0, 0);
1555 TEST_SPEC ("%-16", -2016, 0, 0, 0);
1556 TEST_SPEC ("%-17", -2017, 0, 0, 0);
1557 TEST_SPEC ("%-18", -2018, 0, 0, 0);
1558 TEST_SPEC ("%-19", -2019, 0, 0, 0);
1559 TEST_SPEC ("%-20", -2020, 0, 0, 0);
1560
1561 // exercise precision
1562 TEST_SPEC ("%.0", 3000, 0, 0, 0);
1563 TEST_SPEC ("%.1", 3001, 0, 0, 0);
1564 TEST_SPEC ("%.2", 3002, 0, 0, 0);
1565 TEST_SPEC ("%.3", 3003, 0, 0, 0);
1566 TEST_SPEC ("%.4", 3004, 0, 0, 0);
1567 TEST_SPEC ("%.5", 3005, 0, 0, 0);
1568 TEST_SPEC ("%.6", 3006, 0, 0, 0);
1569 TEST_SPEC ("%.7", 3007, 0, 0, 0);
1570 TEST_SPEC ("%.8", 3008, 0, 0, 0);
1571 TEST_SPEC ("%.9", 3009, 0, 0, 0);
1572 TEST_SPEC ("%.10", 3010, 0, 0, 0);
1573
1574 TEST_SPEC ("%+.0", 4000, 0, 0, 0);
1575 TEST_SPEC ("%+.1", 4001, 0, 0, 0);
1576 TEST_SPEC ("%+.2", 4002, 0, 0, 0);
1577 TEST_SPEC ("%+.3", 4003, 0, 0, 0);
1578 TEST_SPEC ("%+.4", 4004, 0, 0, 0);
1579 TEST_SPEC ("%+.5", 4005, 0, 0, 0);
1580 TEST_SPEC ("%+.6", 4006, 0, 0, 0);
1581 TEST_SPEC ("%+.7", 4007, 0, 0, 0);
1582 TEST_SPEC ("%+.8", 4008, 0, 0, 0);
1583 TEST_SPEC ("%+.9", 4009, 0, 0, 0);
1584 TEST_SPEC ("%+.10", 4010, 0, 0, 0);
1585
1586 // exercise justification with precision
1587 TEST_SPEC ("%+-.0", 5000, 0, 0, 0);
1588 TEST_SPEC ("%+-.1", 5001, 0, 0, 0);
1589 TEST_SPEC ("%+-.2", 5002, 0, 0, 0);
1590 TEST_SPEC ("%+-.3", 5003, 0, 0, 0);
1591 TEST_SPEC ("%+-.4", 5004, 0, 0, 0);
1592 TEST_SPEC ("%+-.5", 5005, 0, 0, 0);
1593 TEST_SPEC ("%+-.6", 5006, 0, 0, 0);
1594 TEST_SPEC ("%+-.7", 5007, 0, 0, 0);
1595 TEST_SPEC ("%+-.8", 5008, 0, 0, 0);
1596 TEST_SPEC ("%+-.9", 5009, 0, 0, 0);
1597 TEST_SPEC ("%+-.10", 5010, 0, 0, 0);
1598
1599 TEST_SPEC ("%-+.0", 5020, 0, 0, 0);
1600 TEST_SPEC ("%-+.1", 5021, 0, 0, 0);
1601 TEST_SPEC ("%-+.2", 5022, 0, 0, 0);
1602 TEST_SPEC ("%-+.3", 5023, 0, 0, 0);
1603 TEST_SPEC ("%-+.4", 5024, 0, 0, 0);
1604 TEST_SPEC ("%-+.5", 5025, 0, 0, 0);
1605 TEST_SPEC ("%-+.6", 5026, 0, 0, 0);
1606 TEST_SPEC ("%-+.7", 5027, 0, 0, 0);
1607 TEST_SPEC ("%-+.8", 5028, 0, 0, 0);
1608 TEST_SPEC ("%-+.9", 5029, 0, 0, 0);
1609 TEST_SPEC ("%-+.10", 5020, 0, 0, 0);
1610
1611 // exercise edge cases
1612
1613 // 7.19.6.1 of ISO/IEC 9899:1999:
1614 // The result of converting a zero value with a precision
1615 // of zero is no characters.
1616 TEST_SPEC ("%.0", 0, 0, 0, "");
1617 TEST_SPEC ("%1.0", 0, 0, 0, " ");
1618 TEST_SPEC ("%2.0", 0, 0, 0, " ");
1619 TEST_SPEC ("%+3.0", 0, 0, 0, " ");
1620 TEST_SPEC ("%-4.0", 0, 0, 0, " ");
1621
1622 // 7.19.6.1, p5 of ISO/IEC 9899:1999:
1623 // A negative field width argument is taken as
1624 // a - flag followed by a positive field width.
1625 // A negative precision argument is taken as
1626 // if the precision were omitted.
1627
1628 TEST_SPEC ("%*", 0, 0, 0, 0);
1629 TEST_SPEC ("%*", 1, 1, 0, 0);
1630 TEST_SPEC ("%*", 2, 2, 0, 0);
1631 TEST_SPEC ("%*", 3, 3, 0, 0);
1632 TEST_SPEC ("%*", -4, -4, 0, 0);
1633 TEST_SPEC ("%-*", 5, 5, 0, 0);
1634 TEST_SPEC ("%-*", -6, -6, 0, 0);
1635
1636 TEST_SPEC ("%*.*", 0, 0, 0, 0);
1637 TEST_SPEC ("%*.*", 1, 0, 0, 0);
1638 TEST_SPEC ("%*.*", 2, 0, 0, 0);
1639 TEST_SPEC ("%*.*", 2, 0, 1, 0);
1640 TEST_SPEC ("%*.*", 2, 1, 2, 0);
1641 TEST_SPEC ("%*.*", 2, 2, 2, 0);
1642 TEST_SPEC ("%*.*", -3, 2, 3, 0);
1643 TEST_SPEC ("%-*.*", -4, 2, -4, 0);
1644 TEST_SPEC ("%-*.*", -4, -2, -4, 0);
1645
1646 // "%hhx", "%hhx", ///////////////////////////////////////////////
1647 printf ("\"%%hh%c\": hexadecimal char\n", spec);
1648
1649 TEST_SPEC ("%hh", '\0', 0, 0, "0");
1650 TEST_SPEC ("%hh", '\1', 0, 0, "1");
1651 TEST_SPEC ("%hh", '\2', 0, 0, "2");
1652 TEST_SPEC ("%hh", '\x7f', 0, 0, ('x' == spec ? "7f" : "7F"));
1653 TEST_SPEC ("%hh", '\x80', 0, 0, "80");
1654 TEST_SPEC ("%hh", '\xff', 0, 0, ('x' == spec ? "ff" : "FF"));
1655
1656 TEST_SPEC ("%#hh", '\0', 0, 0, "0");
1657 TEST_SPEC ("%#hh", '\1', 0, 0, ('x' == spec ? "0x1" : "0X1"));
1658 TEST_SPEC ("%#hh", '\2', 0, 0, ('x' == spec ? "0x2" : "0X2"));
1659 TEST_SPEC ("%#hh", '\x7f', 0, 0, ('x' == spec ? "0x7f" : "0X7F"));
1660 TEST_SPEC ("%#hh", '\x80', 0, 0, ('x' == spec ? "0x80" : "0X80"));
1661 TEST_SPEC ("%#hh", '\xff', 0, 0, ('x' == spec ? "0xff" : "0XFF"));
1662
1663 // "%hx", "%hhX" /////////////////////////////////////////////////
1664 printf ("\"%%h%c\": hexadecimal short\n", spec);
1665
1666 TEST_SPEC ("%h", short (0), 0, 0, "0");
1667 TEST_SPEC ("%h", short (1), 0, 0, "1");
1668 TEST_SPEC ("%h", short (2), 0, 0, "2");
1669
1670 TEST_SPEC ("%h", SHRT_MIN, 0, 0, 0);
1671 TEST_SPEC ("%h", SHRT_MAX, 0, 0, 0);
1672}
1673
1674
1676static void
1677test_bool ()
1678{
1679 printf ("%s\n", "extension: \"%b\": bool");
1680
1681 TEST ("%b", false, 0, 0, "false");
1682 TEST ("%b", true, 0, 0, "true");
1683
1684 TEST ("%b", '\0', 0, 0, "false");
1685 TEST ("%b", '\x01', 0, 0, "true");
1686 TEST ("%b", '\x80', 0, 0, "true");
1687 TEST ("%b", '\xff', 0, 0, "true");
1688
1689 TEST ("%b", 0, 0, 0, "false");
1690 TEST ("%b", -1, 0, 0, "true");
1691 TEST ("%b", +1, 0, 0, "true");
1692 TEST ("%b", -2, 0, 0, "true");
1693 TEST ("%b", +2, 0, 0, "true");
1694}
1695
1696
1698static void
1699test_integer ()
1700{
1701 test_dec ('d');
1702 test_dec ('i');
1703 test_dec ('u');
1704
1705 test_oct ();
1706
1707 test_hex ('x');
1708 test_hex ('X');
1709
1710 test_bool ();
1711}
1712
1713
1715void* make_array (int width, // element width in bytes
1716 int a0 = 0, int a1 = 0, int a2 = 0, int a3 = 0,
1717 int a4 = 0, int a5 = 0, int a6 = 0, int a7 = 0,
1718 int a8 = 0, int a9 = 0, int a10 = 0, int a11 = 0,
1719 int a12 = 0, int a13 = 0, int a14 = 0, int a15 = 0)
1720{
1721 RW_ASSERT (8 == width || 4 == width || 2 == width || 1 == width);
1722
1723#ifdef _RWSTD_INT64_T
1724 typedef _RWSTD_UINT64_T ui64_t;
1725 typedef _RWSTD_INT64_T i64_t;
1726#else
1727 typedef _RWSTD_UINT32_T ui64_t;
1728 typedef _RWSTD_INT32_T i64_t;
1729#endif
1730 typedef _RWSTD_UINT32_T ui32_t;
1731 typedef _RWSTD_INT32_T i32_t;
1732 typedef _RWSTD_INT16_T ui16_t;
1733 typedef _RWSTD_INT16_T i16_t;
1734 typedef _RWSTD_INT8_T ui8_t;
1735 typedef _RWSTD_INT8_T i8_t;
1736
1737 static union {
1738 i64_t i64;
1739 i32_t i32;
1740 i16_t i16;
1741 i8_t i8;
1742 } array [17];
1743
1744 union {
1745 i64_t* pi64;
1746 i32_t* pi32;
1747 i16_t* pi16;
1748 i8_t* pi8;
1749 } ptr = { &array [0].i64 };
1750
1751#define ADD_ELEMENT(n) \
1752 switch (width) { \
1753 case 8 /* bytes */: *ptr.pi64++ = i64_t (a##n); break; \
1754 case 4 /* bytes */: *ptr.pi32++ = i32_t (a##n); break; \
1755 case 2 /* bytes */: *ptr.pi16++ = i16_t (a##n); break; \
1756 case 1 /* byte */: *ptr.pi8++ = i8_t (a##n); break; \
1757 } (void)0
1758
1759 ADD_ELEMENT ( 0); ADD_ELEMENT ( 1); ADD_ELEMENT ( 2); ADD_ELEMENT ( 3);
1760 ADD_ELEMENT ( 4); ADD_ELEMENT ( 5); ADD_ELEMENT ( 6); ADD_ELEMENT ( 7);
1761 ADD_ELEMENT ( 8); ADD_ELEMENT ( 9); ADD_ELEMENT (10); ADD_ELEMENT (11);
1762 ADD_ELEMENT (12); ADD_ELEMENT (13); ADD_ELEMENT (14); ADD_ELEMENT (15);
1763
1764 // zero-terminate
1765 const int a16 = 0;
1766 ADD_ELEMENT (16);
1767
1768 return array;
1769}
1770
1771static void
1772test_intarray ()
1773{
1775 printf ("%s\n", "extension: \"%{Ao}\": array of octal integers");
1776
1777#define AR make_array
1778
1779 // null 1, 2, 4, and 8-byte integer arrays
1780 TEST ("%{1Ao}", 0, 0, 0, "(null)");
1781 TEST ("%{2Ao}", 0, 0, 0, "(null)");
1782 TEST ("%{4Ao}", 0, 0, 0, "(null)");
1783
1784#ifdef _RWSTD_INT64_T
1785 TEST ("%{8Ao}", 0, 0, 0, "(null)");
1786#endif // _RWSTD_INT64_T
1787
1788 // 2-byte integer arrays
1789 TEST ("%{2Ao}", AR (2, 0), 0, 0, "");
1790 TEST ("%{2Ao}", AR (2, 1, 2), 0, 0, "1,2");
1791 TEST ("%{2Ao}", AR (2, 2, 3, 4), 0, 0, "2,3,4");
1792 TEST ("%{2Ao}", AR (2, 3, 4, 5, 6), 0, 0, "3,4,5,6");
1793 TEST ("%{2Ao}", AR (2, 4, 5, 6, 7, 8), 0, 0, "4,5,6,7,10");
1794
1795 TEST ("%{*Ao}", 2, AR (2, 4, 5, 6, 7, 8), 0, "4,5,6,7,10");
1796 TEST ("%{*.*Ao}", 2, 2, AR (2, 4, 0, 6, 0, 8), "4,0");
1797 TEST ("%{*.*Ao}", 2, 3, AR (2, 4, 0, 6, 0, 8), "4,0,6");
1798 TEST ("%{*.*Ao}", 2, 4, AR (2, 4, 0, 6, 0, 8), "4,0,6,0");
1799 TEST ("%{*.*Ao}", 2, 5, AR (2, 4, 0, 6, 0, 8), "4,0,6,0,10");
1800
1801 // the pound flag alone has no affect on the '0' prefix
1802 TEST ("%{#2Ao}", AR (2, 5, 6, 7, 8, 9), 0, 0, "5,6,7,10,11");
1803 // zero and pound flags add the '0' prefix
1804 TEST ("%{0#2Ao}", AR (2, 6, 7, 8, 9, 10), 0, 0, "06,07,010,011,012");
1805
1806 _RWSTD_INT8_T array8 [] = {
1807 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
1808 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0 /* terminate */
1809 };
1810
1811 _RWSTD_INT16_T array16 [] = {
1812 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
1813 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0 /* terminate */
1814 };
1815
1816 _RWSTD_INT32_T array32 [] = {
1817 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
1818 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0 /* terminate */
1819 };
1820
1821#ifdef _RWSTD_INT64_T
1822
1823 _RWSTD_INT64_T array64 [] = {
1824 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
1825 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0 /* terminate */
1826 };
1827
1828 // set array element at index inx to value val
1829# define SET_ELEM(inx, val) \
1830 RW_ASSERT (unsigned (inx) < array_size); \
1831 array8 [inx] = val; array16 [inx] = val; \
1832 array32 [inx] = val; array64 [inx] = val; \
1833 array_str [inx * 2] = '0' + val
1834
1835#else // if !defined (_RWSTD_INT64_T)
1836
1837 // set array element at index inx to value val
1838# define SET_ELEM(inx, val) \
1839 RW_ASSERT (unsigned (inx) < array_size); \
1840 array8 [inx] = val; array16 [inx] = val; \
1841 array32 [inx] = val; \
1842 array_str [inx * 2] = '0' + val
1843
1844#endif // _RWSTD_INT64_T
1845
1846 const unsigned array_size = sizeof array16 / sizeof *array16;
1847
1848 char array_str [2 * array_size] = {
1849 "1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,"
1850 "1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1"
1851 };
1852
1853 TEST ("%{1Ao}", array8, 0, 0, array_str);
1854 TEST ("%{#1Ao}", array8, 0, 0, "{ 1 <repeats 32 times> }");
1855
1856 TEST ("%{2Ao}", array16, 0, 0, array_str);
1857 TEST ("%{#2Ao}", array16, 0, 0, "{ 1 <repeats 32 times> }");
1858
1859 TEST ("%{4Ao}", array32, 0, 0, array_str);
1860 TEST ("%{#4Ao}", array32, 0, 0, "{ 1 <repeats 32 times> }");
1861
1862 SET_ELEM (1, 2);
1863
1864 TEST ("%{2Ao}", array16, 0, 0, array_str);
1865 TEST ("%{#2Ao}", array16, 0, 0, "{ 1,2,1 <repeats 30 times> }");
1866
1867 SET_ELEM ( 1, 1);
1868 SET_ELEM (30, 2);
1869
1870 TEST ("%{2Ao}", array16, 0, 0, array_str);
1871 TEST ("%{#2Ao}", array16, 0, 0, "{ 1 <repeats 30 times>,2,1 }");
1872
1873 SET_ELEM (30, 1);
1874 SET_ELEM (31, 2);
1875
1876 TEST ("%{2Ao}", array16, 0, 0, array_str);
1877 TEST ("%{#2Ao}", array16, 0, 0, "{ 1 <repeats 31 times>,2 }");
1878
1880 printf ("%s\n", "extension: \"%{Ad}\": array of decimal integers");
1881
1882 TEST ("%{4Ad}", AR (4, 0), 0, 0, "");
1883 TEST ("%{4Ad}", AR (4, 20, 31), 0, 0, "20,31");
1884 TEST ("%{4Ad}", AR (4, 21, 32, 43), 0, 0, "21,32,43");
1885 TEST ("%{4Ad}", AR (4, 22, 33, 44, 55), 0, 0, "22,33,44,55");
1886 TEST ("%{4Ad}", AR (4, 23, 34, 45, 56, 67), 0, 0, "23,34,45,56,67");
1887
1889 printf ("%s\n", "extension: \"%{Ax}\": array of hexadecimal integers");
1890
1891 TEST ("%{4Ax}", AR (4, 0), 0, 0, "");
1892 TEST ("%{4Ax}", AR (4, 0xa, 0xb), 0, 0, "a,b");
1893 TEST ("%{4Ax}", AR (4, 0xb, 0xc, 0xd), 0, 0, "b,c,d");
1894 TEST ("%{4Ax}", AR (4, 0xc, 0xd, 0xe, 0xf), 0, 0, "c,d,e,f");
1895 TEST ("%{4Ax}", AR (4, 0xc9, 0xda, 0xeb, 0xfc), 0, 0, "c9,da,eb,fc");
1896
1897 TEST ("%{#4Ax}", AR (4, 0xd, 0xe, 0xa, 0xd), 0, 0, "d,e,a,d");
1898 TEST ("%{0#4Ax}", AR (4, 0xb, 0xe, 0xe, 0xf), 0, 0, "0xb,0xe,0xe,0xf");
1899}
1900
1901
1903static void
1905{
1907 printf ("%s\n", "\"%e\": scientific floating point notation");
1908
1909 // double formatting
1910 TEST ("%e", 0.0, 0, 0, "0.000000e+00");
1911 TEST ("%e", 1.0, 0, 0, "1.000000e+00");
1912 TEST ("%e", -1.0, 0, 0, "-1.000000e+00");
1913 TEST ("%e", 10.0, 0, 0, "1.000000e+01");
1914 TEST ("%e", -10.0, 0, 0, "-1.000000e+01");
1915 TEST ("%e", 10.1, 0, 0, "1.010000e+01");
1916 TEST ("%e", -10.1, 0, 0, "-1.010000e+01");
1917
1918 // long double formatting
1919 TEST ("%Le", 0.0L, 0, 0, "0.000000e+00");
1920 TEST ("%Le", 1.0L, 0, 0, "1.000000e+00");
1921 TEST ("%Le", -1.0L, 0, 0, "-1.000000e+00");
1922 TEST ("%Le", 10.0L, 0, 0, "1.000000e+01");
1923 TEST ("%Le", -10.0L, 0, 0, "-1.000000e+01");
1924 TEST ("%Le", 10.1L, 0, 0, "1.010000e+01");
1925 TEST ("%Le", -10.1L, 0, 0, "-1.010000e+01");
1926
1927 TEST ("%Le", 1.1e+01L, 0, 0, "1.100000e+01");
1928 TEST ("%Le", 1.2e+10L, 0, 0, "1.200000e+10");
1929 TEST ("%Le", 1.3e+12L, 0, 0, "1.300000e+12");
1930
1931#if 100 < _RWSTD_LDBL_MAX_10_EXP
1932
1933 // especially exercise the correct number of zeros in the exponent
1934 // to verify that the function corrects MSVC's screwed up formatting
1935 // without messing it up even more than it is (see PR #27946)
1936 TEST ("%Le", 1.4e+100L, 0, 0, "1.400000e+100");
1937 TEST ("%Le", 1.5e+120L, 0, 0, "1.500000e+120");
1938 TEST ("%Le", 1.6e+123L, 0, 0, "1.600000e+123");
1939#endif
1940
1941#if 1000 < _RWSTD_LDBL_MAX_10_EXP
1942 TEST ("%Le", 1.7e+1000L, 0, 0, "1.700000e+1000");
1943 TEST ("%Le", 1.8e+1200L, 0, 0, "1.800000e+1200");
1944 TEST ("%Le", 1.9e+1230L, 0, 0, "1.900000e+1230");
1945 TEST ("%Le", 2.0e+1234L, 0, 0, "2.000000e+1234");
1946#endif
1947
1949 printf ("%s\n", "\"%E\": scientific floating point notation");
1950
1951 fprintf (stderr, "Warning: %s\n", "\"%E\" not exercised");
1952
1954 printf ("%s\n", "\"%f\": fixed floating point notation");
1955
1956 fprintf (stderr, "Warning: %s\n", "\"%f\" not exercised");
1957
1959 printf ("%s\n", "\"%F\": fixed floating point notation");
1960
1961 fprintf (stderr, "Warning: %s\n", "\"%F\" not exercised");
1962
1964 printf ("%s\n", "\"%g\": value-dependent floating point notation");
1965
1966 fprintf (stderr, "Warning: %s\n", "\"%g\" not exercised");
1967
1969 printf ("%s\n", "\"%G\": value-dependent floating point notation");
1970
1971 fprintf (stderr, "Warning: %s\n", "\"%G\" not exercised");
1972}
1973
1974
1976static void
1977test_pointer ()
1978{
1979 printf ("%s\n", "\"%p\": void pointer");
1980
1981 const char spec = 'p';
1982
1983#if 4 == _RWSTD_PTR_SIZE
1984
1985 TEST_SPEC ("%", (void*)0, 0, 0, "00000000");
1986 TEST_SPEC ("%", (void*)1, 0, 0, "00000001");
1987 TEST_SPEC ("%", (void*)0xffffffff, 0, 0, "ffffffff");
1988
1989 TEST_SPEC ("%#", (void*)0, 0, 0, "0x00000000");
1990 TEST_SPEC ("%#", (void*)0x123, 0, 0, "0x00000123");
1991 TEST_SPEC ("%#", (void*)0xffffffff, 0, 0, "0xffffffff");
1992
1993#elif 8 == _RWSTD_PTR_SIZE
1994
1995 TEST_SPEC ("%", (void*)0, 0, 0, "0000000000000000");
1996 TEST_SPEC ("%", (void*)1, 0, 0, "0000000000000001");
1997 TEST_SPEC ("%", (void*)0xffffffff, 0, 0, "00000000ffffffff");
1998
1999 TEST_SPEC ("%#", (void*)0, 0, 0, "0x0000000000000000");
2000 TEST_SPEC ("%#", (void*)0x123, 0, 0, "0x0000000000000123");
2001 TEST_SPEC ("%#", (void*)0xffffffff, 0, 0, "0x00000000ffffffff");
2002
2003#endif
2004}
2005
2006
2008extern "C" int test_function (int i)
2009{
2010 return i ? i + test_function (-1) : 0;
2011}
2012
2013
2014static void
2015test_funptr ()
2016{
2017 printf ("%s\n", "extension: \"%{f}\": function pointer");
2018
2019 typedef void (*funptr_t)();
2020
2021#if 4 == _RWSTD_PTR_SIZE
2022
2023 TEST ("%{f}", (funptr_t)0, 0, 0, "00000000");
2024 TEST ("%{f}", (funptr_t)1, 0, 0, "00000001");
2025 TEST ("%{f}", (funptr_t)0xffffffff, 0, 0, "ffffffff");
2026
2027 TEST ("%{#f}", (funptr_t)0, 0, 0, "0x00000000");
2028 TEST ("%{#f}", (funptr_t)0x123, 0, 0, "0x00000123");
2029 TEST ("%{#f}", (funptr_t)0xffffffff, 0, 0, "0xffffffff");
2030
2031# ifndef _RWSTD_NO_SPRINTFA_FUNNAME
2032
2033 char output [64];
2034 void* funaddr = (void*)&test_function;
2035 sprintf (output, "%#x=test_function+0", funaddr);
2036
2037 TEST ("%{lf}", (funptr_t)&test_function, 0, 0, output);
2038
2039 funaddr = (char*)funaddr + 4;
2040 sprintf (output, "%#x=test_function+4", funaddr);
2041
2042 TEST ("%{lf}", (funptr_t)funaddr, 0, 0, output);
2043
2044# endif // _RWSTD_NO_SPRINTFA_FUNNAME
2045
2046#elif 8 == _RWSTD_PTR_SIZE
2047
2048 TEST ("%{f}", (funptr_t)0, 0, 0, "0000000000000000");
2049 TEST ("%{f}", (funptr_t)1, 0, 0, "0000000000000001");
2050 TEST ("%{f}", (funptr_t)0xffffffff, 0, 0, "00000000ffffffff");
2051
2052 TEST ("%{#f}", (funptr_t)0, 0, 0, "0x0000000000000000");
2053 TEST ("%{#f}", (funptr_t)0x123, 0, 0, "0x0000000000000123");
2054 TEST ("%{#f}", (funptr_t)0xffffffff, 0, 0, "0x00000000ffffffff");
2055
2056# ifndef _RWSTD_NO_SPRINTFA_FUNNAME
2057
2058 char output [64];
2059 sprintf (output, "%#x=test_function+0", (void*)&test_function);
2060
2061 TEST ("%{lf}", (funptr_t)&test_function, 0, 0, output);
2062
2063 sprintf (output, "%#x=test_function+0", (char*)&test_function + 32);
2064 TEST ("%{lf}", (funptr_t)((char*)&test_funptr + 32), 0, 0, output);
2065
2066# endif // _RWSTD_NO_SPRINTFA_FUNNAME
2067
2068#endif
2069}
2070
2071
2073static void
2074test_memptr ()
2075{
2076 printf ("%s\n", "extension: \"%{M}\": member pointer");
2077
2078 struct MyClass { };
2079 typedef void (MyClass::*memptr_t)();
2080
2081 union {
2082 memptr_t mptr;
2083 long lval [sizeof (memptr_t) / sizeof (long) + 1];
2084 } uval;
2085
2086 if (sizeof (memptr_t) <= sizeof (long)) {
2087
2088#if 4 == _RWSTD_LONG_SIZE
2089
2090 uval.lval [0] = 0UL;
2091 TEST ("%{M}", uval.mptr, 0, 0, "00000000");
2092 TEST ("%{#M}", uval.mptr, 0, 0, "0x00000000");
2093
2094 uval.lval [0] = 1UL;
2095 TEST ("%{M}", uval.mptr, 0, 0, "00000001");
2096 TEST ("%{#M}", uval.mptr, 0, 0, "0x00000001");
2097
2098 uval.lval [0] = 0xffffffffUL;
2099 TEST ("%{M}", uval.mptr, 0, 0, "ffffffff");
2100 TEST ("%{#M}", uval.mptr, 0, 0, "0xffffffff");
2101
2102#elif 8 == _RWSTD_LONG_SIZE
2103
2104 uval.lval [0] = 0UL;
2105 TEST ("%{M}", uval.mptr, 0, 0, "0000000000000000");
2106 TEST ("%{#M}", uval.mptr, 0, 0, "0x0000000000000000");
2107
2108 uval.lval [0] = 1UL;
2109 TEST ("%{M}", uval.mptr, 0, 0, "0000000000000001");
2110 TEST ("%{#M}", uval.mptr, 0, 0, "0x0000000000000001");
2111
2112 uval.lval [0] = 0xffffffffUL;
2113 TEST ("%{M}", uval.mptr, 0, 0, "00000000ffffffff");
2114 TEST ("%{#M}", uval.mptr, 0, 0, "0x00000000ffffffff");
2115
2116#else
2117
2118 fprintf (stderr, "Warning: %s\n", "\"%{M}\" not exercised");
2119
2120#endif
2121
2122 }
2123 else if (sizeof (memptr_t) == 2 * sizeof (long)) {
2124
2125 static const union {
2126 unsigned int ival;
2127 unsigned char bytes [sizeof (int)];
2128 } u = { 1U };
2129
2130 static size_t big_endian = size_t (0 == u.bytes [0]);
2131
2132 const size_t lo_inx = size_t (big_endian);
2133 const size_t hi_inx = size_t (1 - big_endian);
2134
2135#if 4 == _RWSTD_LONG_SIZE
2136
2137 uval.lval [hi_inx] = 0UL;
2138
2139 uval.lval [lo_inx] = 0UL;
2140 TEST ("%{M}", uval.mptr, 0, 0, "0000000000000000");
2141 TEST ("%{#M}", uval.mptr, 0, 0, "0x0000000000000000");
2142
2143 uval.lval [lo_inx] = 1UL;
2144 TEST ("%{M}", uval.mptr, 0, 0, "0000000000000001");
2145 TEST ("%{#M}", uval.mptr, 0, 0, "0x0000000000000001");
2146
2147 uval.lval [lo_inx] = 0xffffffffUL;
2148 TEST ("%{M}", uval.mptr, 0, 0, "00000000ffffffff");
2149 TEST ("%{#M}", uval.mptr, 0, 0, "0x00000000ffffffff");
2150
2151 uval.lval [hi_inx] = 0xdeadbeefUL;
2152
2153 uval.lval [lo_inx] = 0UL;
2154 TEST ("%{M}", uval.mptr, 0, 0, "deadbeef00000000");
2155 TEST ("%{#M}", uval.mptr, 0, 0, "0xdeadbeef00000000");
2156
2157 uval.lval [lo_inx] = 0x1aUL;
2158 TEST ("%{M}", uval.mptr, 0, 0, "deadbeef0000001a");
2159 TEST ("%{#M}", uval.mptr, 0, 0, "0xdeadbeef0000001a");
2160
2161 uval.lval [lo_inx] = 0x0fff1fffUL;
2162 TEST ("%{M}", uval.mptr, 0, 0, "deadbeef0fff1fff");
2163 TEST ("%{#M}", uval.mptr, 0, 0, "0xdeadbeef0fff1fff");
2164
2165#elif 8 == _RWSTD_LONG_SIZE
2166
2167 uval.lval [hi_inx] = 0UL;
2168
2169 uval.lval [lo_inx] = 0UL;
2170 TEST ("%{M}", uval.mptr, 0, 0, "00000000000000000000000000000000");
2171 TEST ("%{#M}", uval.mptr, 0, 0, "0x00000000000000000000000000000000");
2172
2173 uval.lval [lo_inx] = 1UL;
2174 TEST ("%{M}", uval.mptr, 0, 0, "00000000000000000000000000000001");
2175 TEST ("%{#M}", uval.mptr, 0, 0, "0x00000000000000000000000000000001");
2176
2177 uval.lval [lo_inx] = 0xffffffffUL;
2178 TEST ("%{M}", uval.mptr, 0, 0, "000000000000000000000000ffffffff");
2179 TEST ("%{#M}", uval.mptr, 0, 0, "0x000000000000000000000000ffffffff");
2180
2181 uval.lval [hi_inx] = 0x0123456789abcdefUL;
2182
2183 uval.lval [lo_inx] = 0UL;
2184 TEST ("%{M}", uval.mptr, 0, 0, "0123456789abcdef0000000000000000");
2185 TEST ("%{#M}", uval.mptr, 0, 0, "0x0123456789abcdef0000000000000000");
2186
2187 uval.lval [lo_inx] = 0x1aUL;
2188 TEST ("%{M}", uval.mptr, 0, 0, "0123456789abcdef000000000000001a");
2189 TEST ("%{#M}", uval.mptr, 0, 0, "0x0123456789abcdef000000000000001a");
2190
2191 uval.lval [lo_inx] = 0x0fff1fffUL;
2192 TEST ("%{M}", uval.mptr, 0, 0, "0123456789abcdef000000000fff1fff");
2193 TEST ("%{#M}", uval.mptr, 0, 0, "0x0123456789abcdef000000000fff1fff");
2194
2195#else
2196
2197 fprintf (stderr, "Warning: %s\n", "\"%{M}\" not exercised");
2198
2199#endif
2200
2201 }
2202}
2203
2204
2206static void
2207test_width_specific_int ()
2208{
2209 printf ("%s\n", "extension: \"%{I8d}\": 8-bit decimal integers");
2210
2211 TEST ("%{I8d}", 0, 0, 0, "0");
2212 TEST ("%{I8d}", 1, 0, 0, "1");
2213 TEST ("%{I8d}", 2, 0, 0, "2");
2214 TEST ("%{I8d}", 3, 0, 0, "3");
2215 TEST ("%{I8d}", 127, 0, 0, "127");
2216 TEST ("%{I8d}", 128, 0, 0, "-128");
2217 TEST ("%{I8d}", 255, 0, 0, "-1");
2218 TEST ("%{I8d}", 256, 0, 0, "0");
2219 TEST ("%{I8d}", -1, 0, 0, "-1");
2220 TEST ("%{I8d}", -128, 0, 0, "-128");
2221
2222 printf ("%s\n", "extension: \"%{I8o}\": 8-bit octal integers");
2223
2224 TEST ("%{I8o}", 0, 0, 0, "0");
2225 TEST ("%{I8o}", 1, 0, 0, "1");
2226 TEST ("%{I8o}", 2, 0, 0, "2");
2227 TEST ("%{I8o}", 3, 0, 0, "3");
2228 TEST ("%{I8o}", 4, 0, 0, "4");
2229 TEST ("%{I8o}", 5, 0, 0, "5");
2230 TEST ("%{I8o}", 6, 0, 0, "6");
2231 TEST ("%{I8o}", 7, 0, 0, "7");
2232 TEST ("%{I8o}", 8, 0, 0, "10");
2233 TEST ("%{I8o}", 127, 0, 0, "177");
2234 TEST ("%{I8o}", 128, 0, 0, "200");
2235 TEST ("%{I8o}", 255, 0, 0, "377");
2236 TEST ("%{I8o}", 256, 0, 0, "0");
2237
2238 printf ("%s\n", "extension: \"%{I8x}\": 8-bit hexadecimal integers");
2239
2240 TEST ("%{I8x}", 0, 0, 0, "0");
2241 TEST ("%{I8x}", 1, 0, 0, "1");
2242 TEST ("%{I8x}", 2, 0, 0, "2");
2243 TEST ("%{I8x}", 9, 0, 0, "9");
2244 TEST ("%{I8x}", 10, 0, 0, "a");
2245 TEST ("%{I8x}", 15, 0, 0, "f");
2246 TEST ("%{I8x}", 16, 0, 0, "10");
2247 TEST ("%{I8x}", 127, 0, 0, "7f");
2248 TEST ("%{I8x}", 128, 0, 0, "80");
2249 TEST ("%{I8x}", 255, 0, 0, "ff");
2250 TEST ("%{I8x}", 256, 0, 0, "0");
2251
2252 printf ("%s\n", "extension: \"%{I16d}\": 16-bit decimal integers");
2253
2254 TEST ("%{I16d}", 0, 0, 0, "0");
2255 TEST ("%{I16d}", 1, 0, 0, "1");
2256 TEST ("%{I16d}", 2, 0, 0, "2");
2257 TEST ("%{I16d}", 3, 0, 0, "3");
2258 TEST ("%{I16d}", 127, 0, 0, "127");
2259 TEST ("%{I16d}", 128, 0, 0, "128");
2260 TEST ("%{I16d}", 32767, 0, 0, "32767");
2261 TEST ("%{I16d}", 32768, 0, 0, "-32768");
2262 TEST ("%{I16d}", 65535, 0, 0, "-1");
2263 TEST ("%{I16d}", 65536, 0, 0, "0");
2264 TEST ("%{I16d}", -1, 0, 0, "-1");
2265 TEST ("%{I16d}", -32768, 0, 0, "-32768");
2266
2267 printf ("%s\n", "extension: \"%{I32d}\": 32-bit decimal integers");
2268
2269 TEST ("%{I32d}", 0, 0, 0, "0");
2270 TEST ("%{I32d}", 1, 0, 0, "1");
2271 TEST ("%{I32d}", 2, 0, 0, "2");
2272 TEST ("%{I32d}", 3, 0, 0, "3");
2273 TEST ("%{I32d}", 32767, 0, 0, "32767");
2274 TEST ("%{I32d}", 32768, 0, 0, "32768");
2275 TEST ("%{I32d}", 2147483647, 0, 0, "2147483647");
2276 TEST ("%{I32d}", 2147483648UL, 0, 0, "-2147483648");
2277
2278 printf ("%s\n", "extension: \"%{I64d}\": 64-bit decimal integers");
2279
2280#ifndef _RWSTD_NO_LONG_LONG
2281
2282 TEST ("%{I64d}", 0LL, 0, 0, "0");
2283 TEST ("%{I64d}", 1LL, 0, 0, "1");
2284 TEST ("%{I64d}", 2LL, 0, 0, "2");
2285 TEST ("%{I64d}", 3LL, 0, 0, "3");
2286 TEST ("%{I64d}", 32767LL, 0, 0, "32767");
2287 TEST ("%{I64d}", 32768LL, 0, 0, "32768");
2288 TEST ("%{I64d}", 2147483647LL, 0, 0, "2147483647");
2289 TEST ("%{I64d}", 2147483648LL, 0, 0, "2147483648");
2290
2291#else // if defined (_RWSTD_NO_LONG_LONG)
2292
2293 fprintf (stderr, "Warning: %s\n", "\"%{I64d}\" not exercised "
2294 "(no long long support)");
2295
2296#endif // _RWSTD_NO_LONG_LONG
2297}
2298
2299
2301static void
2302test_envvar ()
2303{
2304 printf ("%s\n", "extension: \"%{$string}\": environment variable");
2305
2306 rw_putenv ("FOO=bar");
2307 TEST ("[%{$FOO}]", 0, 0, 0, "[bar]");
2308 TEST ("[%{$*}]", "FOO", 0, 0, "[bar]");
2309 TEST ("[%{$*}][%1$s]", "FOO", 0, 0, "[bar][bar]");
2310
2311 // +--------------------+-------------+-------------+-------------+
2312 // | | parameter | parameter | parameter |
2313 // | +-------------+-------------+-------------+
2314 // | |Set, Not Null| Set, Null | Unset |
2315 // +--------------------+-------------+-------------+-------------+
2316 // | ${parameter:-word} | parameter | word | word |
2317 // | ${parameter-word} | parameter | null | word |
2318 // | ${parameter:=word} | parameter | assign word | assign word |
2319 // | ${parameter=word} | parameter | null | assign word |
2320 // | ${parameter:?word} | parameter | error | error |
2321 // | ${parameter?word} | parameter | null | error |
2322 // | ${parameter:+word} | word | null | null |
2323 // | ${parameter+word} | word | word | null |
2324 // +--------------------+-------------+-------------+-------------+
2325
2326 rw_putenv ("NOT_NULL=FOO");
2327 rw_putenv ("NULL="); // define to null (empty string)
2328 rw_putenv ("UNSET"); // undefine if defined
2329
2330 // ":-" use parameter if not null, otherwise word
2331 TEST ("[%{$NOT_NULL:-word}]", 0, 0, 0, "[FOO]");
2332 TEST ("[%{$NULL:-word}]", 0, 0, 0, "[word]");
2333 TEST ("[%{$UNSET:-word}]", 0, 0, 0, "[word]");
2334
2335 // "-" use parameter if not null, word when unset, otherwise null
2336 TEST ("[%{$NOT_NULL-word}]", 0, 0, 0, "[FOO]");
2337 TEST ("[%{$NULL-word}]", 0, 0, 0, "[]");
2338 TEST ("[%{$UNSET-word}]", 0, 0, 0, "[word]");
2339
2340 // ":=" use parameter if not null, otherwise assign word
2341 TEST ("[%{$NOT_NULL:=word}]", 0, 0, 0, "[FOO]");
2342 TEST ("[%{$NULL:=word}]", 0, 0, 0, "[word]");
2343 TEST ("[%{$NULL}]", 0, 0, 0, "[word]");
2344 TEST ("[%{$UNSET:=word}]", 0, 0, 0, "[word]");
2345 TEST ("[%{$UNSET}]", 0, 0, 0, "[word]");
2346
2347 // restore variables assigned above
2348 rw_putenv ("NULL=");
2349 rw_putenv ("UNSET");
2350
2351 // "=" use parameter if not null, assign word when unset, otherwise null
2352 TEST ("[%{$NOT_NULL=word}]", 0, 0, 0, "[FOO]");
2353 TEST ("[%{$NULL=word}]", 0, 0, 0, "[]");
2354 TEST ("[%{$UNSET=word}]", 0, 0, 0, "[word]");
2355 TEST ("[%{$UNSET}]", 0, 0, 0, "[word]");
2356
2357 // restore variables assigned above
2358 rw_putenv ("NULL=");
2359 rw_putenv ("UNSET");
2360
2361 // ":?" use parameter if not null, otherwise error
2362 TEST ("[%{$NOT_NULL:?word}]", 0, 0, 0, "[FOO]");
2363 TEST ("[%{$NULL:?word}]", 0, 0, 0, "[%{$NULL:?word}]");
2364 TEST ("[%{$UNSET:?word}]", 0, 0, 0, "[%{$UNSET:?word}]");
2365
2366 // "?" use parameter if not null, null when unset, otherwise error
2367 TEST ("[%{$NOT_NULL?word}]", 0, 0, 0, "[FOO]");
2368 TEST ("[%{$NULL?word}]", 0, 0, 0, "[]");
2369 TEST ("[%{$UNSET?word}]", 0, 0, 0, "[%{$UNSET?word}]");
2370
2371 // ":+" use word if parameter is not null, otherwise null
2372 TEST ("[%{$NOT_NULL:+word}]", 0, 0, 0, "[word]");
2373 TEST ("[%{$NULL:+word}]", 0, 0, 0, "[]");
2374 TEST ("[%{$UNSET:+word}]", 0, 0, 0, "[]");
2375
2376 // "+" use word if parameter is set, otherwise null
2377 TEST ("[%{$NOT_NULL+word}]", 0, 0, 0, "[word]");
2378 TEST ("[%{$NULL+word}]", 0, 0, 0, "[word]");
2379 TEST ("[%{$UNSET+word}]", 0, 0, 0, "[]");
2380
2382
2383 rw_putenv ("NOT_NULL=bar");
2384 rw_putenv ("NULL="); // define to null (empty string)
2385 rw_putenv ("UNSET"); // undefine if defined
2386
2387 TEST ("[%{$*:-WORD}]", "NOT_NULL", 0, 0, "[bar]");
2388 TEST ("[%{$*:-WORD}]", "NULL", 0, 0, "[WORD]");
2389 TEST ("[%{$*:-WORD}]", "UNSET", 0, 0, "[WORD]");
2390
2391 TEST ("[%{$*-WORD}]", "NOT_NULL", 0, 0, "[bar]");
2392 TEST ("[%{$*-WORD}]", "NULL", 0, 0, "[]");
2393 TEST ("[%{$*-WORD}]", "UNSET", 0, 0, "[WORD]");
2394
2395 TEST ("[%{$*:=WORD}]", "NOT_NULL", 0, 0, "[bar]");
2396 TEST ("[%{$*:=WORD}]", "NULL", 0, 0, "[WORD]");
2397 TEST ("[%{$*}]", "NULL", 0, 0, "[WORD]");
2398 TEST ("[%{$*:=WORD}]", "UNSET", 0, 0, "[WORD]");
2399 TEST ("[%{$*}]", "UNSET", 0, 0, "[WORD]");
2400
2401 // restore variables assigned above
2402 rw_putenv ("NULL=");
2403 rw_putenv ("UNSET");
2404
2405 TEST ("[%{$*=WORD}]", "NOT_NULL", 0, 0, "[bar]");
2406 TEST ("[%{$*=WORD}]", "NULL", 0, 0, "[]");
2407 TEST ("[%{$*=WORD}]", "UNSET", 0, 0, "[WORD]");
2408 TEST ("[%{$*}]", "UNSET", 0, 0, "[WORD]");
2409
2410 // restore variables assigned above
2411 rw_putenv ("NULL=");
2412 rw_putenv ("UNSET");
2413
2414 TEST ("[%{$*:?WORD}]", "NOT_NULL", 0, 0, "[bar]");
2415 TEST ("[%{$*:?WORD}]", "NULL", 0, 0, "[%{$*:?WORD}]");
2416 TEST ("[%{$*:?WORD}]", "UNSET", 0, 0, "[%{$*:?WORD}]");
2417
2418 TEST ("[%{$*?WORD}]", "NOT_NULL", 0, 0, "[bar]");
2419 TEST ("[%{$*?WORD}]", "NULL", 0, 0, "[]");
2420 TEST ("[%{$*?WORD}]", "UNSET", 0, 0, "[%{$*?WORD}]");
2421
2422 TEST ("[%{$*:+WORD}]", "NOT_NULL", 0, 0, "[WORD]");
2423 TEST ("[%{$*:+WORD}]", "NULL", 0, 0, "[]");
2424 TEST ("[%{$*:+WORD}]", "UNSET", 0, 0, "[]");
2425
2426 TEST ("[%{$*+WORD}]", "NOT_NULL", 0, 0, "[WORD]");
2427 TEST ("[%{$*+WORD}]", "NULL", 0, 0, "[WORD]");
2428 TEST ("[%{$*+WORD}]", "UNSET", 0, 0, "[]");
2429
2431
2432 TEST ("[%{$*:-*}]", "NOT_NULL", "WORD", 0, "[bar]");
2433 TEST ("[%{$*:-*}]", "NULL", "WORD", 0, "[WORD]");
2434 TEST ("[%{$*:-*}]", "UNSET", "WORD", 0, "[WORD]");
2435
2436 TEST ("[%{$*-*}]", "NOT_NULL", "WORD", 0, "[bar]");
2437 TEST ("[%{$*-*}]", "NULL", "WORD", 0, "[]");
2438 TEST ("[%{$*-*}]", "UNSET", "WORD", 0, "[WORD]");
2439
2440 TEST ("[%{$*:=*}]", "NOT_NULL", "WORD", 0, "[bar]");
2441 TEST ("[%{$*:=*}]", "NULL", "WORD", 0, "[WORD]");
2442 TEST ("[%{$*}]", "NULL", 0, 0, "[WORD]");
2443 TEST ("[%{$*:=*}]", "UNSET", "WORD", 0, "[WORD]");
2444 TEST ("[%{$*}]", "UNSET", 0, 0, "[WORD]");
2445
2446 // restore variables assigned above
2447 rw_putenv ("NULL=");
2448 rw_putenv ("UNSET");
2449
2450 TEST ("[%{$*=*}]", "NOT_NULL", "WORD", 0, "[bar]");
2451 TEST ("[%{$*=*}]", "NULL", "WORD", 0, "[]");
2452 TEST ("[%{$*=*}]", "UNSET", "WORD", 0, "[WORD]");
2453 TEST ("[%{$*}]", "UNSET", 0, 0, "[WORD]");
2454
2455 // restore variables assigned above
2456 rw_putenv ("NULL=");
2457 rw_putenv ("UNSET");
2458
2459 TEST ("[%{$*:?*}]", "NOT_NULL", "WORD", 0, "[bar]");
2460 TEST ("[%{$*:?*}]", "NULL", "WORD", 0, "[%{$*:?*}]");
2461 TEST ("[%{$*:?*}]", "UNSET", "WORD", 0, "[%{$*:?*}]");
2462
2463 TEST ("[%{$*?*}]", "NOT_NULL", "WORD", 0, "[bar]");
2464 TEST ("[%{$*?*}]", "NULL", "WORD", 0, "[]");
2465 TEST ("[%{$*?*}]", "UNSET", "WORD", 0, "[%{$*?*}]");
2466
2467 TEST ("[%{$*:+*}]", "NOT_NULL", "WORD", 0, "[WORD]");
2468 TEST ("[%{$*:+*}]", "NULL", "WORD", 0, "[]");
2469 TEST ("[%{$*:+*}]", "UNSET", "WORD", 0, "[]");
2470
2471 TEST ("[%{$*+*}]", "NOT_NULL", "WORD", 0, "[WORD]");
2472 TEST ("[%{$*+*}]", "NULL", "WORD", 0, "[WORD]");
2473 TEST ("[%{$*+*}]", "UNSET", "WORD", 0, "[]");
2474
2476
2477 // exercise unconditional assignment
2478 TEST ("[%{$*!:*}]", "NOT_NULL", "WORD1", 0, "[WORD1]");
2479 TEST ("[%{$*!:*}]", "NULL", "WORD2", 0, "[WORD2]");
2480 TEST ("[%{$*!:*}]", "UNSET", "WORD3", 0, "[WORD3]");
2481
2482 TEST ("[%{$*!:*}]", "NOT_NULL", "WORD4", 0, "[WORD4]");
2483 TEST ("[%{$*!:*}]", "NULL", "WORD5", 0, "[WORD5]");
2484 TEST ("[%{$*!:*}]", "UNSET", "WORD6", 0, "[WORD6]");
2485
2487
2488 // exercise assignment of a formatted string
2489 TEST ("[%{$FOO!:@}, %{$FOO}]", "%s", "bar", 0, "[bar, bar]");
2490}
2491
2492
2494static void
2495test_errno ()
2496{
2498 printf ("%s\n", "extension: \"%m\": strerror(errno)");
2499
2500 for (int i = 0; i != 256; ++i) {
2501
2502 char expect [256];
2503
2504 // be prepared to deal with non-conforming implementations
2505 // of strerror() (such as IRIX) that return a null pointer
2506 const char* const str = strerror (i);
2507 strcpy (expect, str ? str : "(null)");
2508
2509 errno = i;
2510
2511 char *result = rw_sprintfa ("%m");
2512
2513 if (strcmp (result, expect)) {
2514 fprintf (stderr,
2515 "rw_sprintfa(\"%%m\") == \"%s\", got \"%s\" for "
2516 "errno=%d", expect, result, i);
2517 }
2518
2519 free (result);
2520 }
2521
2523 printf ("%s\n", "extension: \"%{#m}\": errno");
2524
2525 int count = 0;
2526
2527 errno = 0;
2528 TEST ("%{#m}", 0, 0, 0, "E#0");
2529
2530 errno = 0;
2531 TEST ("%{#*m}", 0, 0, 0, "E#0");
2532
2533#ifdef EDOM
2534
2535 ++count;
2536
2537 errno = EDOM;
2538 TEST ("%{#m}", 0, 0, 0, "EDOM");
2539
2540 errno = 0;
2541 TEST ("%{#*m}", EDOM, 0, 0, "EDOM");
2542
2543#endif // EDOM
2544
2545#ifdef ERANGE
2546
2547 ++count;
2548
2549 errno = ERANGE;
2550 TEST ("%{#m}", 0, 0, 0, "ERANGE");
2551
2552 errno = 0;
2553 TEST ("%{#*m}", ERANGE, 0, 0, "ERANGE");
2554
2555#endif // ERANGE
2556
2557#ifdef EILSEQ
2558
2559 ++count;
2560
2561 errno = EILSEQ;
2562 TEST ("%{#m}", 0, 0, 0, "EILSEQ");
2563
2564 errno = 0;
2565 TEST ("%{#*m}", EILSEQ, 0, 0, "EILSEQ");
2566
2567#endif // EILSEQ
2568
2569 if (0 == count)
2570 fprintf (stderr, "%s\n", "%{#m}: could not test");
2571
2572 errno = 0;
2573}
2574
2575
2577static void
2578test_signal ()
2579{
2581 printf ("%s\n", "extension: \"%K\": signal name");
2582
2583 TEST ("%{K}", SIGABRT, 0, 0, "SIGABRT");
2584 TEST ("%{K}", SIGFPE, 0, 0, "SIGFPE");
2585 TEST ("%{K}", SIGILL, 0, 0, "SIGILL");
2586 TEST ("%{K}", SIGINT, 0, 0, "SIGINT");
2587 TEST ("%{K}", SIGSEGV, 0, 0, "SIGSEGV");
2588 TEST ("%{K}", SIGTERM, 0, 0, "SIGTERM");
2589 TEST ("%{K}", 12345, 0, 0, "SIG#12345");
2590
2591 TEST ("[%{10K}]", SIGABRT, 0, 0, "[ SIGABRT]");
2592 TEST ("[%{+10K}]", SIGFPE, 0, 0, "[ SIGFPE]");
2593 TEST ("[%{-10K}]", SIGILL, 0, 0, "[SIGILL ]");
2594 TEST ("[%{.3K}]", SIGINT, 0, 0, "[SIG]");
2595 TEST ("[%{10.3K}]", SIGSEGV, 0, 0, "[ SIG]");
2596 TEST ("[%{+10.3K}]", SIGTERM, 0, 0, "[ SIG]");
2597 TEST ("[%{-10.3K}]", 12345, 0, 0, "[SIG ]");
2598}
2599
2600
2602static void
2603test_pid ()
2604{
2606 printf ("%s\n", "extension: \"%P\": rw_pid_t");
2607
2608 const rw_pid_t pid = 12345;
2609
2610 TEST ("%{P}", pid, 0, 0, "12345");
2611
2612 TEST ("[%{10P}]", pid, 0, 0, "[ 12345]");
2613 TEST ("[%{+10P}]", pid, 0, 0, "[ 12345]");
2614 TEST ("[%{-10P}]", pid, 0, 0, "[12345 ]");
2615 TEST ("[%{.3P}]", pid, 0, 0, "[12345]");
2616 TEST ("[%{10.3P}]", pid, 0, 0, "[ 12345]");
2617 TEST ("[%{+10.3P}]", pid, 0, 0, "[ 12345]");
2618 TEST ("[%{-10.3P}]", pid, 0, 0, "[12345 ]");
2619}
2620
2621
2623static const tm*
2624make_tm (int sec = 0, // [0,60]
2625 int min = 0, // [0,59]
2626 int hour = 0, // [0,23]
2627 int mday = 1, // [1,31]
2628 int mon = 0, // [0,11]
2629 int year = 0, // Gregorian year - 1900
2630 int wday = 0, // [0,6]; 0 = Sunday
2631 int yday = 0, // [0,365]
2632 int isdst = 0, // < 0, 0, > 0
2633 long gmtoff = 0, // offset from GMT in seconds,
2634 const char *zone = 0) // timezone name
2635{
2636 static tm tmp = tm ();
2637
2638 if (sec < 0) {
2639 // get the current local time
2640 time_t t = time (0);
2641 tm *tmb = localtime (&t);
2642 return tmb ? tmb : &tmp;
2643 }
2644 else if (INT_MAX == sec) {
2645 // return 0 to exercise extensions
2646 return 0;
2647 }
2648
2649 // use arguments to initialize struct
2650 tmp.tm_sec = sec;
2651 tmp.tm_min = min;
2652 tmp.tm_hour = hour;
2653 tmp.tm_mday = mday;
2654 tmp.tm_mon = mon;
2655 tmp.tm_year = year;
2656 tmp.tm_wday = wday;
2657 tmp.tm_yday = yday;
2658 tmp.tm_isdst = isdst;
2659
2660#if defined (__linux__) && defined (_RWSTD_NO_PURE_C_HEADERS)
2661
2662 // support for glibc extension:
2663
2664 // GNU glibc uses gmtoff and zone instead of timezone and
2665 // tzname when computing/formatting time zone information
2666 //
2667 // http://www.gnu.org/manual/glibc-2.2.3/html_node/libc_425.html#SEC434
2668
2669# ifndef __USE_BSD
2670
2671 tmp.tm_gmtoff = gmtoff;
2672 tmp.tm_zone = zone;
2673
2674# else // if defined (__USE_BSD)
2675
2676 tmp.tm_gmtoff = gmtoff;
2677 tmp.tm_zone = zone;
2678
2679# endif // __USE_BSD
2680
2681#else
2682
2683 _RWSTD_UNUSED (gmtoff);
2684 _RWSTD_UNUSED (zone);
2685
2686#endif // __linux__ && _RWSTD_NO_PURE_C_HEADERS
2687
2688 return &tmp;
2689}
2690
2691
2692static void
2693test_tm ()
2694{
2696 printf ("%s\n", "extension: \"%{t}\": struct tm");
2697
2698#define TM make_tm
2699
2700 TEST ("%{t}", 0, 0, 0, "(null)");
2701
2702 const void* addr = bad_address (0);
2703 TEST ("%{t}", addr, 0, 0, format_bad_address (addr, false));
2704
2705 addr = bad_address (sizeof (int));
2706 TEST ("%{t}", addr, 0, 0, format_bad_address (addr, true));
2707
2708 // exercise human readable format
2709 TEST ("%{t}", TM (), 0, 0, "Sun Jan 1 00:00:00 1900");
2710 TEST ("%{t}", TM (1), 0, 0, "Sun Jan 1 00:00:01 1900");
2711 TEST ("%{t}", TM (2, 3), 0, 0, "Sun Jan 1 00:03:02 1900");
2712 TEST ("%{t}", TM (3, 4, 5), 0, 0, "Sun Jan 1 05:04:03 1900");
2713 TEST ("%{t}", TM (4, 5, 6, 7), 0, 0, "Sun Jan 7 06:05:04 1900");
2714 TEST ("%{t}", TM (5, 6, 7, 8, 9), 0, 0, "Sun Oct 8 07:06:05 1900");
2715 TEST ("%{t}", TM (6, 7, 8, 9, 10, 11), 0, 0, "Sun Nov 9 08:07:06 1911");
2716
2717 TEST ("%{t}", TM (7, 7, 8, 1, 1, 12, 1), 0, 0, "Mon Feb 1 08:07:07 1912");
2718 TEST ("%{t}", TM (8, 7, 8, 2, 2, 23, 2), 0, 0, "Tue Mar 2 08:07:08 1923");
2719 TEST ("%{t}", TM (9, 7, 8, 3, 3, 34, 3), 0, 0, "Wed Apr 3 08:07:09 1934");
2720 TEST ("%{t}", TM (0, 7, 8, 4, 4, 45, 4), 0, 0, "Thu May 4 08:07:00 1945");
2721 TEST ("%{t}", TM (1, 7, 8, 5, 5, 56, 5), 0, 0, "Fri Jun 5 08:07:01 1956");
2722 TEST ("%{t}", TM (2, 7, 8, 6, 6, -1, 6), 0, 0, "Sat Jul 6 08:07:02 1899");
2723 TEST ("%{t}", TM (3, 7, 8, 7, 7, -1899), 0, 0, "Sun Aug 7 08:07:03 1");
2724 TEST ("%{t}", TM (3, 7, 8, 7, 7, -1900), 0, 0, "Sun Aug 7 08:07:03 1 BC");
2725 TEST ("%{t}", TM (3, 7, 8, 7, 7, -1901), 0, 0, "Sun Aug 7 08:07:03 2 BC");
2726
2727 TEST ("%{t}", TM (56, 34, 12, 1, 0, 0, 0, 0, 1), 0, 0,
2728 "Sun Jan 1 12:34:56 DST 1900");
2729
2731 printf ("%s\n", "extension: \"%{#t}\": verbose struct tm");
2732
2733 // exercise verbose struct tm format (members with 0 value omitted)
2734 TEST ("%{#t}", TM (), 0, 0, "{ tm_mday=1 }");
2735 TEST ("%{#t}", TM (60), 0, 0, "{ tm_sec=60, tm_mday=1 }");
2736 TEST ("%{#t}", TM ( 0, 59), 0, 0, "{ tm_min=59, tm_mday=1 }");
2737 TEST ("%{#t}", TM ( 0, 0, 23), 0, 0, "{ tm_hour=23, tm_mday=1 }");
2738 TEST ("%{#t}", TM ( 0, 0, 0, 2), 0, 0, "{ tm_mday=2 }");
2739 TEST ("%{#t}", TM ( 0, 0, 0, 3, 1), 0, 0, "{ tm_mday=3, tm_mon=1 Feb }");
2740
2741 // exercise invalid values of tm members (verbose format implied)
2742 TEST ("%{t}", TM (61), 0, 0, "{ tm_sec=61 [0,60], tm_mday=1 }");
2743 TEST ("%{t}", TM ( 0, 60), 0, 0, "{ tm_min=60 [0,59], tm_mday=1 }");
2744 TEST ("%{t}", TM ( 0, 0, 24), 0, 0, "{ tm_hour=24 [0,23], tm_mday=1 }");
2745
2746 TEST ("%{t}", TM ( 0, 0, 0, 0), 0, 0, "{ tm_mday=0 [1,31] }");
2747 TEST ("%{t}", TM ( 0, 0, 0, 32), 0, 0, "{ tm_mday=32 [1,31] }");
2748
2749 TEST ("%{t}", TM ( 0, 0, 0, 1, 12), 0, 0,
2750 "{ tm_mday=1, tm_mon=12 [0,11] }");
2751 TEST ("%{t}", TM (0, 0, 0, 1, 0, 0, -1), 0, 0,
2752 "{ tm_mday=1, tm_wday=-1 [0,6] }");
2753 TEST ("%{t}", TM (0, 0, 0, 1, 0, 0, 0, 366), 0, 0,
2754 "{ tm_mday=1, tm_yday=366 [0,365] }");
2755
2756#if 4 == _RWSTD_INT_SIZE
2757
2758 // exercise integer overflow in tm_year arithmetic
2759 TEST ("%{t}", TM (0, 0, 0, 1, 0, INT_MAX), 0, 0,
2760 "{ tm_mday=1, tm_year=2147483647 [-2147483648,2147481747] }");
2761
2762#elif 8 == _RWSTD_INT_SIZE
2763
2764 TEST ("%{t}", TM (0, 0, 0, 1, 0, INT_MAX), 0, 0,
2765 "{ tm_mday=1, tm_year=9223372036854775807 "
2766 "[-9223372036854775808,9223372036854773907] }");
2767
2768#endif // _RWSTD_INT_SIZE
2769}
2770
2771
2773static void
2774test_paramno ()
2775{
2777 printf ("%s\n", "extension: \"%<paramno>$\": positional parameters");
2778
2779 TEST ("%c %1$c", 'a', 0, 0, "a a");
2780 TEST ("%c %1$c %1$c", 'b', 0, 0, "b b b");
2781 TEST ("%c %1$c %c %2$c", 'c', 'd', 0, "c c d d");
2782 TEST ("%c %c %1$c %1$c", 'e', 'f', 0, "e f e e");
2783
2784 TEST ("%s %1$s", "b", 0, 0, "b b");
2785 TEST ("%s %1$s", "cd", 0, 0, "cd cd");
2786
2787 TEST ("[%s|%1$1s]", "xyz", 0, 0, "[xyz|xyz]");
2788 TEST ("[%s|%1$2s]", "xyz", 0, 0, "[xyz|xyz]");
2789 TEST ("[%s|%1$3s]", "xyz", 0, 0, "[xyz|xyz]");
2790 TEST ("[%s|%1$4s]", "xyz", 0, 0, "[xyz| xyz]");
2791 TEST ("[%s|%1$5s]", "xyz", 0, 0, "[xyz| xyz]");
2792 TEST ("[%s|%1$6s]", "xyz", 0, 0, "[xyz| xyz]");
2793
2794 TEST ("[%s|%1$-1s]", "xyz", 0, 0, "[xyz|xyz]");
2795 TEST ("[%s|%1$-2s]", "xyz", 0, 0, "[xyz|xyz]");
2796 TEST ("[%s|%1$-3s]", "xyz", 0, 0, "[xyz|xyz]");
2797 TEST ("[%s|%1$-4s]", "xyz", 0, 0, "[xyz|xyz ]");
2798 TEST ("[%s|%1$-5s]", "xyz", 0, 0, "[xyz|xyz ]");
2799 TEST ("[%s|%1$-6s]", "xyz", 0, 0, "[xyz|xyz ]");
2800
2801 TEST ("[%s|%1$+1s]", "xyz", 0, 0, "[xyz|xyz]");
2802 TEST ("[%s|%1$+2s]", "xyz", 0, 0, "[xyz|xyz]");
2803 TEST ("[%s|%1$+3s]", "xyz", 0, 0, "[xyz|xyz]");
2804 TEST ("[%s|%1$+4s]", "xyz", 0, 0, "[xyz| xyz]");
2805 TEST ("[%s|%1$+5s]", "xyz", 0, 0, "[xyz| xyz]");
2806 TEST ("[%s|%1$+6s]", "xyz", 0, 0, "[xyz| xyz]");
2807
2808 TEST ("[%s|%1$1.1s]", "xyz", 0, 0, "[xyz|x]");
2809 TEST ("[%s|%1$2.2s]", "xyz", 0, 0, "[xyz|xy]");
2810 TEST ("[%s|%1$3.3s]", "xyz", 0, 0, "[xyz|xyz]");
2811 TEST ("[%s|%1$4.1s]", "xyz", 0, 0, "[xyz| x]");
2812 TEST ("[%s|%1$5.2s]", "xyz", 0, 0, "[xyz| xy]");
2813 TEST ("[%s|%1$6.3s]", "xyz", 0, 0, "[xyz| xyz]");
2814
2815 TEST ("[%s|%1$6.3s]", "xyz", 0, 0, "[xyz| xyz]");
2816
2817 TEST ("[foo=%s, bar=%s|foo=%1$s, bar=%2$s]",
2818 "abc", "def", 0,
2819 "[foo=abc, bar=def|foo=abc, bar=def]");
2820
2821 TEST ("%i %1$i", 1, 0, 0, "1 1");
2822 TEST ("%i %1$i", 1, 0, 0, "1 1");
2823}
2824
2825
2827static void
2828test_conditional ()
2829{
2831 printf ("%s\n", "extension: \"%{?}\", \"%{:}\", \"%{;}\": conditional");
2832
2833 TEST ("%{?}%{;}", 0, 0, 0, "");
2834 TEST ("%{?}%{;}", 1, 0, 0, "");
2835
2836 TEST ("%{?}a%{;}", 0, 0, 0, "");
2837 TEST ("%{?}b%{;}", 1, 0, 0, "b");
2838
2839 TEST ("a%{?}b%{;}", 0, 0, 0, "a");
2840 TEST ("a%{?}b%{;}", 1, 0, 0, "ab");
2841
2842 TEST ("a%{?}%{;}b", 0, 0, 0, "ab");
2843 TEST ("a%{?}%{;}b", 1, 0, 0, "ab");
2844
2845 TEST ("a%{?}b%{;}c", 0, 0, 0, "ac");
2846 TEST ("a%{?}b%{;}c", 1, 0, 0, "abc");
2847
2848 TEST ("%{?}%{:}%{;}", 0, 0, 0, "");
2849 TEST ("%{?}%{:}%{;}", 1, 0, 0, "");
2850
2851 TEST ("%{?}a%{:}b%{;}", 0, 0, 0, "b");
2852 TEST ("%{?}a%{:}b%{;}", 1, 0, 0, "a");
2853
2854 TEST ("a%{?}b%{:}c%{;}", 0, 0, 0, "ac");
2855 TEST ("a%{?}b%{:}c%{;}", 1, 0, 0, "ab");
2856
2857 TEST ("a%{?}b%{:}c%{;}d", 0, 0, 0, "acd");
2858 TEST ("a%{?}b%{:}c%{;}d", 1, 0, 0, "abd");
2859
2860 TEST ("a%{?}bc%{:}d%{;}", 0, 0, 0, "ad");
2861 TEST ("a%{?}bc%{:}d%{;}", 1, 0, 0, "abc");
2862
2863 TEST ("a%{?}bc%{:}d%{;}e", 0, 0, 0, "ade");
2864 TEST ("a%{?}bc%{:}d%{;}e", 1, 0, 0, "abce");
2865
2866 TEST ("a%{?}bc%{:}de%{;}", 0, 0, 0, "ade");
2867 TEST ("a%{?}bc%{:}de%{;}", 1, 0, 0, "abc");
2868
2869 TEST ("a%{?}bc%{:}de%{;}f", 0, 0, 0, "adef");
2870 TEST ("a%{?}bc%{:}de%{;}f", 1, 0, 0, "abcf");
2871
2872 // exercise nested confitionals
2873 TEST ("x%{?}0%{?}1%{;}2%{;}y", 0, 0, 0, "xy");
2874 TEST ("x%{?}0%{?}1%{;}2%{;}y", 0, 1, 0, "xy");
2875 TEST ("x%{?}0%{?}1%{;}2%{;}y", 1, 0, 0, "x02y");
2876 TEST ("x%{?}0%{?}1%{;}2%{;}y", 1, 1, 0, "x012y");
2877
2878 TEST ("x%{?}0%{?}1%{:}2%{;}3%{;}y", 0, 0, 0, "xy");
2879 TEST ("x%{?}0%{?}1%{:}2%{;}3%{;}y", 0, 1, 0, "xy");
2880 TEST ("x%{?}0%{?}1%{:}2%{;}3%{;}y", 1, 0, 0, "x023y");
2881 TEST ("x%{?}0%{?}1%{:}2%{;}3%{;}y", 1, 1, 0, "x013y");
2882
2883 TEST ("x%{?}0%{?}1%{:}2%{;}3%{:}4%{;}y", 0, 0, 0, "x4y");
2884 TEST ("x%{?}0%{?}1%{:}2%{;}3%{:}4%{;}y", 0, 1, 0, "x4y");
2885 TEST ("x%{?}0%{?}1%{:}2%{;}3%{:}4%{;}y", 1, 0, 0, "x023y");
2886 TEST ("x%{?}0%{?}1%{:}2%{;}3%{:}4%{;}y", 1, 1, 0, "x013y");
2887
2888 const char cond3[] = {
2889 "0"
2890 "%{?}" // if ($1) {
2891 "1"
2892 "%{?}" // if ($2) {
2893 "2"
2894 "%{?}" // if ($3) {
2895 "3"
2896 "%{:}" // } else /* if (!$3) */ {
2897 "4"
2898 "%{;}" // } // $3
2899 "5"
2900 "%{:}" // } else /* if (!$2) */{
2901 "6"
2902 "%{;}" // } // $2
2903 "7"
2904 "%{:}" // } else /* if (!$1) */ {
2905 "8"
2906 "%{;}" // } // $1
2907 "9"
2908 };
2909
2910 TEST (cond3, 0, 0, 0, "089");
2911 TEST (cond3, 0, 0, 1, "089");
2912 TEST (cond3, 0, 1, 0, "089");
2913 TEST (cond3, 0, 1, 1, "089");
2914 TEST (cond3, 1, 0, 0, "01679");
2915 TEST (cond3, 1, 0, 1, "01679");
2916 TEST (cond3, 1, 1, 0, "0124579");
2917 TEST (cond3, 1, 1, 1, "0123579");
2918
2919 // exercise conditionals with positional parameters
2920 TEST ("A%{?}B%{:}C%{;}%1$d", 0, 0, 0, "AC0");
2921 TEST ("A%{?}B%{:}C%{;}%1$d", 1, 0, 0, "AB1");
2922 TEST ("A%{?}B%{:}C%{;}%1$d", 2, 0, 0, "AB2");
2923 TEST ("A%{?}B%{:}C%{;}%1$d", -1, 0, 0, "AB-1");
2924}
2925
2926
2928// directive syntax:
2929// "X=" [ '#' ] [ '+' ] [ '*' | <n> ] [ '.' [ '*' | '@' | <n> ] ]
2930// where
2931// '#' causes UserClass::id_ to be included in output
2932// ignored for UserPOD
2933// '+' forces UserClass::data_.val_ or UserPOD::data_.val to be
2934// formatted as an integer (otherwise it is formatted as an
2935// (optionally escaped) character '*' or <n> is the number
2936// of elements in the sequence (the first occurrence)
2937// '*', <n> is the offset of the cursor within the sequence
2938// (where the cursor is a pair of pointy brackets
2939// surrounding the element, e.g., >123<)
2940// '@' is the pointer to the element to be surrended by the
2941// pair of pointy brackets
2942// first rw_snprintfa's variable argument of int type should be
2943// sizeof(UserClass) or sizeof(UserPOD)
2944
2945#undef TEST
2946#define TEST(fmt, a1, a2, a3, expect) \
2947 do_test (__LINE__, fmt, expect, rw_sprintfa (fmt, cwidth, a1, a2, a3))
2948
2949static void
2950test_userclass_format ()
2951{
2952 UserClass* const x = UserClass::from_char ("abcdef");
2953 static const int cwidth = sizeof (*x);
2954
2955 TEST ("[%{X=*}]", 0, x, 0, "[]");
2956 TEST ("[%{X=*}]", 1, x, 0, "[a]");
2957 TEST ("[%{X=*}]", 2, x, 0, "[ab]");
2958 TEST ("[%{X=*}]", 3, x, 0, "[abc]");
2959 TEST ("[%{X=*}]", 4, x, 0, "[abcd]");
2960 TEST ("[%{X=*}]", 5, x, 0, "[abcde]");
2961 TEST ("[%{X=*}]", 6, x, 0, "[abcdef]");
2962
2963
2964 TEST ("[%{X=#*}]", 0, x, 0, "[]");
2965 TEST ("[%{X=#*}]", 1, x, 0, "[1:a]");
2966 TEST ("[%{X=#*}]", 2, x, 0, "[1:a2:b]");
2967 TEST ("[%{X=#*}]", 3, x, 0, "[1:a2:b3:c]");
2968 TEST ("[%{X=#*}]", 4, x, 0, "[1:a2:b3:c4:d]");
2969 TEST ("[%{X=#*}]", 5, x, 0, "[1:a2:b3:c4:d5:e]");
2970 TEST ("[%{X=#*}]", 6, x, 0, "[1:a2:b3:c4:d5:e6:f]");
2971
2972
2973 TEST ("[%{X=+*}]", 0, x, 0, "[]");
2974 TEST ("[%{X=+*}]", 1, x, 0, "[97]");
2975 TEST ("[%{X=+*}]", 2, x, 0, "[97,98]");
2976 TEST ("[%{X=+*}]", 3, x, 0, "[97,98,99]");
2977 TEST ("[%{X=+*}]", 4, x, 0, "[97,98,99,100]");
2978 TEST ("[%{X=+*}]", 5, x, 0, "[97,98,99,100,101]");
2979 TEST ("[%{X=+*}]", 6, x, 0, "[97,98,99,100,101,102]");
2980
2981
2982 TEST ("[%{X=*.0}]", 0, x, 0, "[]");
2983
2984 TEST ("[%{X=*.0}]", 1, x, 0, "[>a<]");
2985
2986 TEST ("[%{X=*.*}]", 2, 0, x, "[>a<b]");
2987 TEST ("[%{X=*.1}]", 2, x, 0, "[a>b<]");
2988
2989 TEST ("[%{X=*.0}]", 3, x, 0, "[>a<bc]");
2990 TEST ("[%{X=*.*}]", 3, 1, x, "[a>b<c]");
2991 TEST ("[%{X=*.*}]", 3, 2, x, "[ab>c<]");
2992
2993 TEST ("[%{X=*.*}]", 4, 0, x, "[>a<bcd]");
2994 TEST ("[%{X=*.*}]", 4, 1, x, "[a>b<cd]");
2995 TEST ("[%{X=*.*}]", 4, 2, x, "[ab>c<d]");
2996 TEST ("[%{X=*.*}]", 4, 3, x, "[abc>d<]");
2997
2998 TEST ("[%{X=*.@}]", 4, x + 3, x, "[abc>d<]");
2999 TEST ("[%{X=*.@}]", 4, x + 2, x, "[ab>c<d]");
3000 TEST ("[%{X=*.@}]", 4, x + 1, x, "[a>b<cd]");
3001 TEST ("[%{X=*.@}]", 4, x + 0, x, "[>a<bcd]");
3002
3003 TEST ("[%{X=#5.*}]", 0, x, 0, "[>1:a<2:b3:c4:d5:e]");
3004 TEST ("[%{X=#5.*}]", 1, x, 0, "[1:a>2:b<3:c4:d5:e]");
3005 TEST ("[%{X=#5.*}]", 2, x, 0, "[1:a2:b>3:c<4:d5:e]");
3006 TEST ("[%{X=#5.*}]", 3, x, 0, "[1:a2:b3:c>4:d<5:e]");
3007 TEST ("[%{X=#5.*}]", 4, x, 0, "[1:a2:b3:c4:d>5:e<]");
3008
3009
3010 TEST ("[%{X=+*.0}]", 0, x, 0, "[]");
3011
3012 TEST ("[%{X=+*.0}]", 1, x, 0, "[>97<]");
3013
3014 TEST ("[%{X=+*.*}]", 2, 0, x, "[>97<,98]");
3015 TEST ("[%{X=+*.1}]", 2, x, 0, "[97,>98<]");
3016
3017 TEST ("[%{X=+*.0}]", 3, x, 0, "[>97<,98,99]");
3018 TEST ("[%{X=+*.*}]", 3, 1, x, "[97,>98<,99]");
3019 TEST ("[%{X=+*.*}]", 3, 2, x, "[97,98,>99<]");
3020
3021 TEST ("[%{X=+*.*}]", 4, 0, x, "[>97<,98,99,100]");
3022 TEST ("[%{X=+*.*}]", 4, 1, x, "[97,>98<,99,100]");
3023 TEST ("[%{X=+*.*}]", 4, 2, x, "[97,98,>99<,100]");
3024 TEST ("[%{X=+*.*}]", 4, 3, x, "[97,98,99,>100<]");
3025
3026 TEST ("[%{X=+*.@}]", 4, x + 3, x, "[97,98,99,>100<]");
3027 TEST ("[%{X=+*.@}]", 4, x + 2, x, "[97,98,>99<,100]");
3028 TEST ("[%{X=+*.@}]", 4, x + 1, x, "[97,>98<,99,100]");
3029 TEST ("[%{X=+*.@}]", 4, x + 0, x, "[>97<,98,99,100]");
3030
3031 TEST ("[%{X=+#5.*}]", 0, x, 0, "[>1:97<,2:98,3:99,4:100,5:101]");
3032 TEST ("[%{X=+#5.*}]", 1, x, 0, "[1:97,>2:98<,3:99,4:100,5:101]");
3033 TEST ("[%{X=+#5.*}]", 2, x, 0, "[1:97,2:98,>3:99<,4:100,5:101]");
3034 TEST ("[%{X=+#5.*}]", 3, x, 0, "[1:97,2:98,3:99,>4:100<,5:101]");
3035 TEST ("[%{X=+#5.*}]", 4, x, 0, "[1:97,2:98,3:99,4:100,>5:101<]");
3036
3037 delete[] x;
3038}
3039
3040static void
3041test_userpod_format ()
3042{
3043 UserPOD* const x = UserPOD::from_char ("abcdef");
3044 static const int cwidth = sizeof (*x);
3045
3046 TEST ("[%{X=*}]", 0, x, 0, "[]");
3047 TEST ("[%{X=*}]", 1, x, 0, "[a]");
3048 TEST ("[%{X=*}]", 2, x, 0, "[ab]");
3049 TEST ("[%{X=*}]", 3, x, 0, "[abc]");
3050 TEST ("[%{X=*}]", 4, x, 0, "[abcd]");
3051 TEST ("[%{X=*}]", 5, x, 0, "[abcde]");
3052 TEST ("[%{X=*}]", 6, x, 0, "[abcdef]");
3053
3054
3055 TEST ("[%{X=#*}]", 0, x, 0, "[]");
3056 TEST ("[%{X=#*}]", 1, x, 0, "[a]");
3057 TEST ("[%{X=#*}]", 2, x, 0, "[ab]");
3058 TEST ("[%{X=#*}]", 3, x, 0, "[abc]");
3059 TEST ("[%{X=#*}]", 4, x, 0, "[abcd]");
3060 TEST ("[%{X=#*}]", 5, x, 0, "[abcde]");
3061 TEST ("[%{X=#*}]", 6, x, 0, "[abcdef]");
3062
3063
3064 TEST ("[%{X=+*}]", 0, x, 0, "[]");
3065 TEST ("[%{X=+*}]", 1, x, 0, "[97]");
3066 TEST ("[%{X=+*}]", 2, x, 0, "[97,98]");
3067 TEST ("[%{X=+*}]", 3, x, 0, "[97,98,99]");
3068 TEST ("[%{X=+*}]", 4, x, 0, "[97,98,99,100]");
3069 TEST ("[%{X=+*}]", 5, x, 0, "[97,98,99,100,101]");
3070 TEST ("[%{X=+*}]", 6, x, 0, "[97,98,99,100,101,102]");
3071
3072
3073 TEST ("[%{X=*.0}]", 0, x, 0, "[]");
3074
3075 TEST ("[%{X=*.0}]", 1, x, 0, "[>a<]");
3076
3077 TEST ("[%{X=*.*}]", 2, 0, x, "[>a<b]");
3078 TEST ("[%{X=*.1}]", 2, x, 0, "[a>b<]");
3079
3080 TEST ("[%{X=*.0}]", 3, x, 0, "[>a<bc]");
3081 TEST ("[%{X=*.*}]", 3, 1, x, "[a>b<c]");
3082 TEST ("[%{X=*.*}]", 3, 2, x, "[ab>c<]");
3083
3084 TEST ("[%{X=*.*}]", 4, 0, x, "[>a<bcd]");
3085 TEST ("[%{X=*.*}]", 4, 1, x, "[a>b<cd]");
3086 TEST ("[%{X=*.*}]", 4, 2, x, "[ab>c<d]");
3087 TEST ("[%{X=*.*}]", 4, 3, x, "[abc>d<]");
3088
3089 TEST ("[%{X=*.@}]", 4, x + 3, x, "[abc>d<]");
3090 TEST ("[%{X=*.@}]", 4, x + 2, x, "[ab>c<d]");
3091 TEST ("[%{X=*.@}]", 4, x + 1, x, "[a>b<cd]");
3092 TEST ("[%{X=*.@}]", 4, x + 0, x, "[>a<bcd]");
3093
3094 TEST ("[%{X=#5.*}]", 0, x, 0, "[>a<bcde]");
3095 TEST ("[%{X=#5.*}]", 1, x, 0, "[a>b<cde]");
3096 TEST ("[%{X=#5.*}]", 2, x, 0, "[ab>c<de]");
3097 TEST ("[%{X=#5.*}]", 3, x, 0, "[abc>d<e]");
3098 TEST ("[%{X=#5.*}]", 4, x, 0, "[abcd>e<]");
3099
3100
3101 TEST ("[%{X=+*.0}]", 0, x, 0, "[]");
3102
3103 TEST ("[%{X=+*.0}]", 1, x, 0, "[>97<]");
3104
3105 TEST ("[%{X=+*.*}]", 2, 0, x, "[>97<,98]");
3106 TEST ("[%{X=+*.1}]", 2, x, 0, "[97,>98<]");
3107
3108 TEST ("[%{X=+*.0}]", 3, x, 0, "[>97<,98,99]");
3109 TEST ("[%{X=+*.*}]", 3, 1, x, "[97,>98<,99]");
3110 TEST ("[%{X=+*.*}]", 3, 2, x, "[97,98,>99<]");
3111
3112 TEST ("[%{X=+*.*}]", 4, 0, x, "[>97<,98,99,100]");
3113 TEST ("[%{X=+*.*}]", 4, 1, x, "[97,>98<,99,100]");
3114 TEST ("[%{X=+*.*}]", 4, 2, x, "[97,98,>99<,100]");
3115 TEST ("[%{X=+*.*}]", 4, 3, x, "[97,98,99,>100<]");
3116
3117 TEST ("[%{X=+*.@}]", 4, x + 3, x, "[97,98,99,>100<]");
3118 TEST ("[%{X=+*.@}]", 4, x + 2, x, "[97,98,>99<,100]");
3119 TEST ("[%{X=+*.@}]", 4, x + 1, x, "[97,>98<,99,100]");
3120 TEST ("[%{X=+*.@}]", 4, x + 0, x, "[>97<,98,99,100]");
3121
3122 TEST ("[%{X=+#5.*}]", 0, x, 0, "[>97<,98,99,100,101]");
3123 TEST ("[%{X=+#5.*}]", 1, x, 0, "[97,>98<,99,100,101]");
3124 TEST ("[%{X=+#5.*}]", 2, x, 0, "[97,98,>99<,100,101]");
3125 TEST ("[%{X=+#5.*}]", 3, x, 0, "[97,98,99,>100<,101]");
3126 TEST ("[%{X=+#5.*}]", 4, x, 0, "[97,98,99,100,>101<]");
3127
3128 delete[] x;
3129}
3130
3131
3133#undef TEST
3134#define TEST(fmt, a1, a2, a3, expect) \
3135 do_test (__LINE__, fmt, expect, rw_sprintfa (fmt, a1, a2, a3))
3136
3137static int
3138user_fun_va (const char *fun_name, // name of calling function
3139 char **pbuf, // pointer to a buffer
3140 size_t *pbufsize, // pointer to buffer size
3141 const char *fmt, // format string
3142 va_list va) // argument list
3143{
3144 if (0 == pbuf) {
3145 fprintf (stderr, "pbuf: unexpected null argument #1");
3146 ++nfailures;
3147 return -1;
3148 }
3149
3150 if (0 == pbufsize) {
3151 fprintf (stderr, "pbufsize: unexpected null argument #2");
3152 ++nfailures;
3153 return -1;
3154 }
3155
3156 if (0 == fmt) {
3157 fprintf (stderr, "fmt: unexpected null argument #3");
3158 ++nfailures;
3159 return -1;
3160 }
3161
3162 if ( 0 == strcmp ("!", fmt)
3163 || 0 == strcmp ("+!", fmt)
3164 || 0 == strcmp ("-!", fmt)) {
3165 // special value indicating to the caller that we're
3166 // returning control to it and letting it to handle
3167 // the directive to set/push/pop a user-defined
3168 // formatting function
3169 return _RWSTD_INT_MIN;
3170 }
3171
3172 const size_t funlen = strlen (fun_name);
3173
3174 int arg = -1;
3175
3176 if (isdigit (*fmt)) {
3177 // process positional parameter
3178 char* end = 0;
3179 arg = int (strtol (fmt, &end, 10));
3180 if ('$' != *end)
3181 arg = -1;
3182 else if (memcmp (fun_name, end + 1, funlen) || ':' != end [funlen + 1])
3183 arg = _RWSTD_INT_MIN;
3184 }
3185 else if (memcmp (fun_name, fmt, funlen) || ':' != fmt [funlen])
3186 arg = _RWSTD_INT_MIN;
3187
3188 if (_RWSTD_INT_MIN == arg) {
3189 // if the format directive (beyond the positional parameter, if
3190 // present) doesn't match the name of the user-defined function,
3191 // return to the caller for further processing
3192 return arg;
3193 }
3194
3195 if (-1 < arg) {
3196 // extract the address of the positional argument from the list
3197 // (assume its type is int for simplicity -- there is no easy way
3198 // to verify compatibility with the actual type of the argument
3199 // without having access to the argument's original directive)
3200 const int* const parg = va_arg (va, int*);
3201
3202 RW_ASSERT (0 != parg);
3203
3204 arg = *parg;
3205 }
3206 else {
3207 // extract the address of the caller's variable argument list
3208 va_list *pva = va_arg (va, va_list*);
3209
3210 RW_ASSERT (0 != pva);
3211
3212 // extract an integer value from rw_snprintfa's variable argument
3213 // list pass through to us by the caller
3214 arg = va_arg (*pva, int);
3215
3216 // extract the address where to store the extracted argument
3217 int* const pparam = va_arg (va, int*);
3218
3219 RW_ASSERT (0 != pparam);
3220
3221 // store the extracted argument
3222 *pparam = arg;
3223 }
3224
3225 // compute the length of the buffer formatted so far
3226 const size_t buflen_0 = *pbuf ? strlen (*pbuf) : 0;
3227
3228 // invoke rw_asnprintf() recursively to format our arguments
3229 // and append the result to the end of the buffer; pass the
3230 // value returned from rw_asnprintf() (i.e., the number of
3231 // bytes appended) back to the caller
3232 const int n = rw_asnprintf (pbuf, pbufsize,
3233 "%{+}<%s:'%s',%d>", fun_name, fmt, arg);
3234
3235 // compute the new length of the buffer
3236 const size_t buflen_1 = *pbuf ? strlen (*pbuf) : 0;
3237
3238 // assert that the function really appended as many characters
3239 // as it said it did (assumes no NULs embedded in the output)
3240 // and that it didn't write past the end of the buffer
3241 RW_ASSERT (n < 0 || buflen_1 == buflen_0 + n);
3242 RW_ASSERT (buflen_1 < *pbufsize);
3243
3244 return n;
3245}
3246
3247
3248static int
3249user_fun_f (char **pbuf, size_t *pbufsize, const char *fmt, ...)
3250{
3251 va_list va;
3252 va_start (va, fmt);
3253
3254 const int result = user_fun_va ("f", pbuf, pbufsize, fmt, va);
3255
3256 va_end (va);
3257
3258 return result;
3259}
3260
3261static int
3262user_fun_g (char **pbuf, size_t *pbufsize, const char *fmt, ...)
3263{
3264 va_list va;
3265 va_start (va, fmt);
3266
3267 const int result = user_fun_va ("g", pbuf, pbufsize, fmt, va);
3268
3269 va_end (va);
3270
3271 return result;
3272}
3273
3274
3275static void
3276test_user_defined_formatting ()
3277{
3279 printf ("%s\n", "extension: \"%{!}\" user-defined formatting function");
3280
3281 // set the user-defined function that overrides the default
3282 TEST ("%{!}", &user_fun_f, 0, 0, "");
3283 TEST ("%{d}", 0, 0, 0, "0");
3284 TEST ("%{f:d}", 0, 0, 0, "<f:'f:d',0>");
3285 TEST ("%{x}", 10, 0, 0, "a");
3286 TEST ("%{f:foo}", 1, 0, 0, "<f:'f:foo',1>");
3287 TEST ("%{f:bar}", -1, 0, 0, "<f:'f:bar',-1>");
3288
3289 // exercise positional parameters
3290 TEST ("%d%{1$f:foo}", 11, 0, 0, "11<f:'1$f:foo',11>");
3291 TEST ("%{f:d}%{1$f:bar}", 12, 0, 0, "<f:'f:d',12><f:'1$f:bar',12>");
3292 TEST ("%i%{1$f:foo}%{1$f:bar}", 13, 0, 0,
3293 "13<f:'1$f:foo',13><f:'1$f:bar',13>");
3294
3295 // push another user-defined function on the stack
3296 TEST ("%{+!}", &user_fun_g, 0, 0, "");
3297 TEST ("%{f:x}", 0, 0, 0, "<f:'f:x',0>");
3298 TEST ("%{g:y}", 1, 0, 0, "<g:'g:y',1>");
3299 TEST ("%{i}", 2, 0, 0, "2");
3300 TEST ("%{f:a}%b%{g:c}", 3, 4, 5, "<f:'f:a',3>true<g:'g:c',5>");
3301
3302 // disable all user-defined processing
3303 TEST ("%{!}", 0, 0, 0, "");
3304 TEST ("%{d}", 3, 0, 0, "3");
3305 TEST ("%{i}", -5, 0, 0, "-5");
3306
3307 // pop the top of the stack and re-enable user-defined processing
3308 TEST ("%{-!}", 0, 0, 0, "");
3309 TEST ("%{f:x}", 1, 0, 0, "<f:'f:x',1>");
3310 TEST ("%{f:y}", 2, 0, 0, "<f:'f:y',2>");
3311
3312 // reset the user-defined formatting function
3313 TEST ("%{!}", 0, 0, 0, "");
3314 TEST ("%{d}", 123, 0, 0, "123");
3315}
3316
3317
3319static void
3320test_bufsize ()
3321{
3323 printf ("%s\n", "extension: \"%{N}\" buffer size");
3324
3325 TEST ("%{0}foo", 0, 0, 0, 0);
3326 TEST ("%{1}foo", 0, 0, 0, 0);
3327 TEST ("%{2}foo", 0, 0, 0, 0);
3328 TEST ("%{3}foo", 0, 0, 0, 0);
3329 TEST ("%{4}foo", 0, 0, 0, "foo");
3330 TEST ("%{10}foobar", 0, 0, 0, "foobar");
3331
3332 TEST ("%{*}bar", 0, 0, 0, 0);
3333 TEST ("%{*}bar", 1, 0, 0, 0);
3334 TEST ("%{*}bar", 2, 0, 0, 0);
3335 TEST ("%{*}bar", 3, 0, 0, 0);
3336 TEST ("%{*}bar", 4, 0, 0, "bar");
3337}
3338
3339
3341static void
3342test_nested_format ()
3343{
3345 printf ("%s\n", "extension: \"%{@}\" nested format directive");
3346
3347 TEST ("%{@}", "", 0, 0, "");
3348 TEST ("%{@}", "a", 0, 0, "a");
3349 TEST ("%{@}", "ab", 0, 0, "ab");
3350 TEST ("%{@}", "abc", 0, 0, "abc");
3351 TEST ("%{@}", "%d", 0, 0, "0");
3352 TEST ("%{@}", "%d", 1, 0, "1");
3353 TEST ("%{@}", "%d", 12, 0, "12");
3354 TEST ("%{@}", "%s", "x", 0, "x");
3355 TEST ("%{@}", "%s", "xy", 0, "xy");
3356 TEST ("%{@}", "%s", "xyz", 0, "xyz");
3357 TEST ("x%{@}", "%s", "yz", 0, "xyz");
3358 TEST ("%{@}z", "%s", "xy", 0, "xyz");
3359 TEST ("x%{@}z", "%s", "y", 0, "xyz");
3360
3361 TEST ("ABC%{@}F", "D%{@}E", "", 0, "ABCDEF");
3362 TEST ("ABC%{@}GH", "D%{@}F", "e", 0, "ABCDeFGH");
3363 TEST ("ABC%{@}HIJ", "D%{@}G", "ef", 0, "ABCDefGHIJ");
3364 TEST ("ABC%{@}IJKL", "D%{@}H", "efg", 0, "ABCDefgHIJKL");
3365
3366 TEST ("AB%{@}MN", "CD%{@}KL", "EF%{@}IJ", "gh", "ABCDEFghIJKLMN");
3367
3368 TEST ("A%{@}C%{@}E%{@}G", "B", "D", "F", "ABCDEFG");
3369 TEST ("A%{@}C%{@}E", "%s", "B", "D", "ABCDE");
3370 TEST ("A%{@}C%{@}E", "B", "%s", "D", "ABCDE");
3371
3372 TEST ("ABC%sGHI%{@}XYZ", "DEF", "%s%1$s", "JKL", "ABCDEFGHIJKLJKLXYZ");
3373
3374 // exercise arrays
3375
3376 TEST ("%{.0@}", "%i", 0, 0, "");
3377 TEST ("%{.1@}", "%i", 1, 0, "1");
3378 TEST ("%{.2@}", "%i", 2, 3, "23");
3379
3380 TEST ("%{ .0@}", "%i", 3, 0, "");
3381 TEST ("%{ .1@}", "%i", 4, 5, "4");
3382 TEST ("%{ .2@}", "%i", 5, 6, "5 6");
3383 TEST ("[ %{.2@}]", "%i ", 6, 7, "[ 6 7 ]");
3384
3385 const int ia[] = { 9, 8, 7, 6, 5, 4, 3, 2, 1, 0 };
3386
3387 //
3388 // +---- (width: ???)
3389 // | +-- precision: number of elements in array
3390 // | |
3391 // v v
3392 TEST ("%{.0A@}", "%i", ia, 0, "");
3393 TEST ("%{.1A@}", "%i", ia, 0, "9");
3394 TEST ("%{.2A@}", "%i", ia, 0, "98");
3395 TEST ("%{.3A@}", "%i", ia, 0, "987");
3396 TEST ("%{.4A@}", "%i", ia, 0, "9876");
3397 TEST ("%{.5A@}", "%i", ia, 0, "98765");
3398 TEST ("%{.6A@}", "%i", ia, 0, "987654");
3399 TEST ("%{.7A@}", "%i", ia, 0, "9876543");
3400 TEST ("%{.8A@}", "%i", ia, 0, "98765432");
3401 TEST ("%{.9A@}", "%i", ia, 0, "987654321");
3402 TEST ("%{.*A@}", 10, "%i", ia, "9876543210");
3403 TEST ("[%{ .*A@}]", 9, "%i", ia, "[9 8 7 6 5 4 3 2 1]");
3404 TEST ("[%{ .*A@}]", 8, "%i", ia, "[9 8 7 6 5 4 3 2]");
3405 TEST ("[%{ .*A@}]", 7, "%i", ia, "[9 8 7 6 5 4 3]");
3406 TEST ("[%{ .*A@}]", 6, "%i", ia, "[9 8 7 6 5 4]");
3407 TEST ("[%{ .*A@}]", 5, "%i", ia, "[9 8 7 6 5]");
3408 TEST ("[%{ .*A@}]", 4, "%i", ia, "[9 8 7 6]");
3409 TEST ("[%{ .*A@}]", 3, "%i", ia, "[9 8 7]");
3410 TEST ("[%{ .*A@}]", 2, "%i", ia, "[9 8]");
3411 TEST ("[%{ .*A@}]", 1, "%i", ia, "[9]");
3412 TEST ("[%{ .*A@}]", 0, "%i", ia, "[]");
3413
3414 static const struct {
3415 size_t i; const char *s;
3416 } sa[] = {
3417 { 1, "foo" }, { 2, "bar" }, { 3, "foobar" }
3418 };
3419
3420 // members must be packed with no padding
3421 RW_ASSERT (sizeof *sa == sizeof sa->i + sizeof sa->s);
3422
3423 TEST ("{%{ .*A@}}", // array of nested directives
3424 3, // three elements
3425 "(%zu, %#s)", // descrcibes structure
3426 sa, // array argument
3427 "{(1, \"foo\") (2, \"bar\") (3, \"foobar\")}");
3428}
3429
3430
3432static void
3433test_malformed_directives ()
3434{
3436 printf ("%s\n", "malformed directives");
3437
3438 TEST ((char*)0, 0, 0, 0, "(null)");
3439 TEST ("%{", 0, 0, 0, "%{");
3440 TEST ("%{%", 0, 0, 0, "%{%");
3441 TEST ("%{%{", 0, 0, 0, "%{%{");
3442 TEST ("%{}", 0, 0, 0, "%{}");
3443}
3444
3445
3447static void
3448stress_bufsize ()
3449{
3450 // exercise the ability to format into a fixed size buffer
3451 // and correctly report buffer overlow errors via ENOMEM
3452
3454 static const char str[] = "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ";
3455
3456 char buf [sizeof str] = "";
3457
3458 for (unsigned size = 0; size != sizeof str - 1; ++size) {
3459 for (unsigned len = 0; len != sizeof str - 1; ++len) {
3460
3461 errno = 0;
3462
3463 const char* const s = str + sizeof str - 1 - len;
3464
3465 // format a substring of s len characters long
3466 // into a buffer size characters wide
3467 const char* const res =
3468 rw_snprintfa (buf, size, "%{*}%s", size, s);
3469
3470 const int error = errno;
3471
3472 if (size <= len) {
3473 // verify that the function returns 0 and sets errno
3474 // to ENOMEM when the provided buffer is not big enough
3475 assert (0 == res);
3476 assert (ENOMEM == error);
3477 }
3478 else {
3479 // verify that the function returns the address
3480 // of the provided buffer on success and that
3481 // the contents of the buffer match the argument
3482 assert (res == buf);
3483 assert (0 == error);
3484 assert (0 == strcmp (s, buf));
3485 }
3486 }
3487 }
3488}
3489
3490
3492int main ()
3493{
3494 test_percent ();
3495
3496 test_character ();
3497 test_string ();
3498 test_chararray ();
3499 test_stringarray ();
3500
3501 test_integer ();
3502 test_intarray ();
3503
3504 test_floating ();
3505 test_pointer ();
3506
3507 test_envvar ();
3508 test_funptr ();
3509 test_memptr ();
3510 test_errno ();
3511 test_signal ();
3512 test_pid ();
3513
3514 test_basic_string ();
3515
3516 test_ios_bitmasks ();
3517
3518 test_locale_category ();
3519
3520 test_ctype_mask ();
3521
3522 test_bitset ();
3523
3524 test_tm ();
3525
3526 test_paramno ();
3527
3528 test_width_specific_int ();
3529
3530 test_conditional ();
3531
3532 // must be exercised before user-defined formatting
3533 test_userclass_format ();
3534 test_userpod_format ();
3535
3536 test_user_defined_formatting ();
3537
3538 test_bufsize ();
3539
3540 test_nested_format ();
3541
3542 test_malformed_directives ();
3543
3545 if (nfailures) {
3546 fprintf (stderr, "\nFailed %d out of %d assertions.\n",
3547 nfailures, ntests);
3548 return 1;
3549 }
3550
3552 // close stderr to prevent the tested function from spitting out
3553 // thousands of error messages in the stress test below
3554 fclose (stderr);
3555
3556 stress_bufsize ();
3557
3558 printf ("\nPassed all %d assertions.\n", ntests);
3559
3560 return 0;
3561}
int ival
int fail
const char * format_bad_address(const void *ptr, bool valid)
Definition 0.printf.cpp:189
#define WS(ws)
#define BASE(n)
#define ARG
const void * bad_address(size_t size)
Definition 0.printf.cpp:160
int ntests
Definition 0.printf.cpp:62
#define SET_ELEM(inx, val)
#define BS(str)
#define TEST(fmt, a1, a2, a3, expect)
Definition 0.printf.cpp:126
#define AR
#define TEST_SPEC(pfx, a1, a2, a3, expect)
Definition 0.printf.cpp:130
int test_function(int i)
int nfailures
Definition 0.printf.cpp:63
void * make_array(int width, int a0=0, int a1=0, int a2=0, int a3=0, int a4=0, int a5=0, int a6=0, int a7=0, int a8=0, int a9=0, int a10=0, int a11=0, int a12=0, int a13=0, int a14=0, int a15=0)
#define TM
int main()
#define ADD_ELEMENT(n)
void count(T, T, const U &,...)
#define i
Definition 17.names.cpp:126
#define t
Definition 17.names.cpp:136
#define u
Definition 17.names.cpp:137
#define cmp
Definition 17.names.cpp:458
#define s_
Definition 17.names.cpp:189
#define line
Definition 17.names.cpp:490
#define res
Definition 17.names.cpp:531
#define ptr
Definition 17.names.cpp:525
#define sec
Definition 17.names.cpp:539
#define x
Definition 17.names.cpp:140
#define array
Definition 17.names.cpp:447
#define buf
Definition 17.names.cpp:452
#define a2
Definition 17.names.cpp:251
#define a1
Definition 17.names.cpp:225
#define addr
Definition 17.names.cpp:446
#define tmp
Definition 17.names.cpp:553
#define s
#define len
Definition 17.names.cpp:488
#define n
Definition 17.names.cpp:130
volatile int result
#define EDOM
#define EILSEQ
std::Nested::test_tm test_tm
void test_string(const char *charTname, const std::collate< charT > &co, const char *str1, const char *str2, int expected_val)
bool cond3(std::ctype_base::mask, char, const char *)
#define LL(number)
void test_errno(CharType ctype, const char *cname, IterType itype, const char *iname, numT)
void do_test(int line, const char *src, std::size_t resoff, ForwardIterator dummy_iter, const T *, const char *predname)
void test_floating(CharT *, Traits *, FloatingType *, const char *cname, const char *tname, const char *fname, const char *fmt)
void test_bool(CharT *, Traits *, const char *cname, const char *tname)
const int end
const int out
const int ate
const int in
IMPORT_C SInt32 printf(const Char *,...)
#define ERANGE
@ big_endian
Definition INFINITY.cpp:70
#define assert(expr)
Definition _cassert.h:40
#define LC_CTYPE
#define LC_NUMERIC
#define LC_MONETARY
#define LC_ALL
#define LC_TIME
#define LC_COLLATE
#define _RWSTD_LONG_LONG
unsigned short wchar_t
#define SIGINT
#define SIGILL
#define SIGTERM
#define SIGFPE
#define SIGABRT
#define SIGSEGV
#define va_arg(va, T)
#define va_end(ignore)
#define va_start(va, name)
#define stderr
#define WEOF
#define _RWSTD_UNUSED(arg)
Definition _defs.h:972
#define _RWSTD_ASSERT(ignore)
Definition _defs.h:1108
A TOML array.
Definition array.hpp:258
const char * str
Definition exec.cpp:170
void(DummyStruct::* memptr_t)() const
Definition fmt_defs.h:54
void(* funptr_t)()
#define SHRT_MAX
Definition limits.h:64
#define INT_MIN
Definition limits.h:80
#define CHAR_BIT
Definition limits.h:40
#define LONG_MAX
Definition limits.h:88
#define INT_MAX
Definition limits.h:76
#define SHRT_MIN
Definition limits.h:68
#define LONG_MIN
Definition limits.h:92
#define ENOMEM
Definition memattr.cpp:78
@ error
throw a parse_error exception in case of a tag
UChar bytes[sizeof(int)]
Definition printf.cpp:83
_TEST_EXPORT int rw_putenv(const char *, int=-1)
Definition environ.cpp:69
_TEST_EXPORT char * rw_snprintfa(char *buf, _RWSTD_SIZE_T bufsize, const char *fmt,...)
_TEST_EXPORT char * rw_sprintfa(const char *fmt,...)
Definition printf.cpp:3258
_TEST_EXPORT int rw_asnprintf(char **pbuf, _RWSTD_SIZE_T *pbufsize, const char *fmt,...)
_RWSTD_SSIZE_T rw_pid_t
Definition rw_process.h:33
#define RW_ASSERT(expr)
#define _RWSTD_PRIz
#define LC_MESSAGES
Definition time_put.cpp:60
static UserClass from_char(char c)
Definition rw_value.h:221
static UserPOD from_char(char c)
Definition rw_value.h:49
A local time-of-day.
int arg
Definition locale.cpp:2806
#define min(a, b)