Ne.app NeANT
The Ne.app NeANT User module of the NeANT distribution.
driver.cpp
Go to the documentation of this file.
1
29// expand _TEST_EXPORT macros
30#define _RWSTD_TEST_SRC
31
32#include "opt_diags.h"
33#include "opt_lines.h"
34#include "opt_trace.h"
35#include "opt_types.h"
36
37#include <rw_cmdopt.h> // for rw_setopts()
38#include <rw_printf.h> // for rw_snprintfa()
39
40#include <assert.h> // for assert
41#include <ctype.h> // for islower(), isupper()
42#include <setjmp.h> // for longjmp, setjmp, ...
43#include <stdarg.h> // for va_list
44#include <stdio.h> // for fileno
45#include <stdlib.h> // for free, _set_invalid_parameter_handler()
46#include <string.h> // for strchr, strcpy
47
48#ifdef _WIN32
49# include <windows.h> // for SetErrorMode()
50#endif // _WIN32
51
52#ifdef _MSC_VER
53# include <crtdbg.h> // for _CrtSetReportMode(), _CrtSetDbgFlag()
54#endif // _MSC_VER
55
56#ifndef _WIN32
57# include <unistd.h> // for isatty()
58# include <sys/resource.h> // for setlimit()
59
60# ifndef RLIM_SAVED_CUR
61# define RLIM_SAVED_CUR RLIM_INFINITY
62# endif // RLIM_SAVED_CUR
63
64# ifndef RLIM_SAVED_MAX
65# define RLIM_SAVED_MAX RLIM_INFINITY
66# endif // RLIM_SAVED_MAX
67
68// declare fileno in case it's not declared (for strict ANSI conformance)
69extern "C" {
70
72
73} // extern "C"
74
75#else // if Windows
76 // no isatty on Windoze
77# define _RWSTD_NO_ISATTY
78#endif // _WIN32
79
80// expand _TEST_EXPORT macros
81#define _RWSTD_TEST_SRC
82#include <rw_driver.h>
83
84
86#define RW_TEST_STRSTR(x) #x
87#define RW_TEST_STR(x) RW_TEST_STRSTR(x)
88
89#ifndef RW_TEST_COMPILER
90# if defined (__DECCXX__)
91# define RW_TEST_COMPILER "Compaq C++, __DECCXX__ = " \
92 RW_TEST_STR (__DECCXX__)
93# elif defined (__INTEL_COMPILER)
94# if defined (__EDG_VERSION__)
95# define RW_TEST_ICC_EDG_VER \
96 ", __EDG_VERSION__ = " RW_TEST_STR (__EDG_VERSION__)
97# else
98# define RW_TEST_ICC_EDG_VER ""
99# endif
100# if defined (_MSC_VER)
101# define RW_TEST_COMPILER "Intel C++, __INTEL_COMPILER = " \
102 RW_TEST_STR (__INTEL_COMPILER) ", _MSC_VER = " \
103 RW_TEST_STR (_MSC_VER) \
104 RW_TEST_ICC_EDG_VER
105# elif defined (__INTEL_COMPILER_BUILD_DATE)
106# define RW_TEST_COMPILER "Intel C++, __INTEL_COMPILER = " \
107 RW_TEST_STR (__INTEL_COMPILER) \
108 ", __INTEL_COMPILER_BUILD_DATE = " \
109 RW_TEST_STR (__INTEL_COMPILER_BUILD_DATE) \
110 RW_TEST_ICC_EDG_VER
111# else
112# define RW_TEST_COMPILER "Intel C++, __INTEL_COMPILER = " \
113 RW_TEST_STR (__INTEL_COMPILER) \
114 RW_TEST_ICC_EDG_VER
115# endif
116# elif defined (__GNUC__)
117# if defined (__VERSION__)
118# define RW_TEST_GCC_VER ", __VERSION__ = \"" __VERSION__ "\""
119# else
120# define RW_TEST_GCC_VER ""
121# endif
122# if defined (__GNUC_PATCHLEVEL__)
123# define RW_TEST_COMPILER "gcc " \
124 RW_TEST_STR (__GNUC__) "." \
125 RW_TEST_STR (__GNUC_MINOR__) "." \
126 RW_TEST_STR (__GNUC_PATCHLEVEL__) \
127 RW_TEST_GCC_VER
128# else
129# define RW_TEST_COMPILER "gcc " \
130 RW_TEST_STR (__GNUC__) "." RW_TEST_STR (__GNUC_MINOR__)
131 RW_TEST_GCC_VER
132# endif
133# elif defined (_COMPILER_VERSION) && defined (__sgi)
134# define RW_TEST_COMPILER "SGI MIPSpro, _COMPILER_VERSION = " \
135 RW_TEST_STR (_COMPILER_VERSION)
136# elif defined (__INTEL_COMPILER)
137# if defined (_MSC_VER)
138# define RW_TEST_COMPILER "Intel C++, __INTEL_COMPILER = " \
139 RW_TEST_STR (__INTEL_COMPILER) ", _MSC_VER = " \
140 RW_TEST_STR (_MSC_VER)
141# else
142# define RW_TEST_COMPILER "Intel C++, __INTEL_COMPILER = " \
143 RW_TEST_STR (__INTEL_COMPILER)
144# endif
145# elif defined (__HP_aCC)
146# if defined (__EDG_VERSION__)
147# define RW_TEST_ACC_EDG_VER \
148 ", __EDG_VERSION__ = " RW_TEST_STR (__EDG_VERSION__)
149# else
150# define RW_TEST_ACC_EDG_VER ""
151# endif
152# define RW_TEST_COMPILER "HP aCC, __HP_aCC = " \
153 RW_TEST_STR (__HP_aCC) \
154 RW_TEST_ACC_EDG_VER
155# elif defined (__IBMCPP__)
156# define RW_TEST_COMPILER "IBM VisualAge C++, __IBMCPP__ = " \
157 RW_TEST_STR (__IBMCPP__)
158# elif defined (_MSC_VER)
159# define RW_TEST_COMPILER "MSVC, _MSC_VER = " \
160 RW_TEST_STR (_MSC_VER)
161# elif defined (__SUNPRO_CC)
162# define RW_TEST_COMPILER "SunPro, __SUNPRO_CC = " \
163 RW_TEST_STR (__SUNPRO_CC)
164# elif defined (__EDG__)
165 // handle the vanilla EDG eccp last to avoid overriding
166 // the real compiler's macro (compilers such as Intel C++
167 // and HP aCC use eccp for their C++ front end)
168# define RW_TEST_COMPILER "EDG eccp, __EDG_VERSION__ = " \
169 RW_TEST_STR (__EDG_VERSION__)
170# else
171# define RW_TEST_COMPILER "unknown"
172# endif
173#endif
174
175#ifndef RW_TEST_LIBSTD
176# ifdef _RWSTD_VER
177# define RW_TEST_LIBSTD "Rogue Wave C++ Standard Library, " \
178 "_RWSTD_VER = " RW_TEST_STR (_RWSTD_VER)
179# elif defined (__GLIBCXX__)
180# define RW_TEST_LIBSTD "GNU C++ Standard Library, " \
181 "__GLIBCXX__ = " \
182 RW_TEST_STR (__GLIBCXX__)
183# elif defined (_STLPORT_VERSION)
184 // check for STLport before SGI STL since STLport,
185 // being derived from SGI STL, #defines both macros
186# define RW_TEST_LIBSTD "STLport, " \
187 "_STLPORT_VERSION = " \
188 RW_TEST_STR (_STLPORT_VERSION)
189# elif defined (__SGI_STL)
190# define RW_TEST_LIBSTD "SGI STL, " \
191 "__SGI_STL = " \
192 RW_TEST_STR (__SGI_STL)
193# elif defined (_YVALS)
194 // is there a better way to identify the Dinkumware
195 // implementation? does it have a version macro?
196# define RW_TEST_LIBSTD "Dinkum C++ Standard Library"
197# endif
198#endif // RW_TEST_LIBSTD
199
200#ifndef RW_TEST_HARDWARE
201# if defined (__alpha__) || defined (__alpha)
202# define RW_TEST_ARCH "alpha"
203# elif defined (__x86_64__) || defined (__x86_64)
204# if defined (__LP64__) || defined (_LP64)
205# define RW_TEST_ARCH "x86_64/LP64"
206# else
207# define RW_TEST_ARCH "x86_64/ILP32"
208# endif
209# elif defined (__amd64__) || defined (__amd64)
210# if defined (__LP64__) || defined (_LP64)
211# define RW_TEST_ARCH "amd64/LP64"
212# else
213# define RW_TEST_ARCH "amd64/ILP32"
214# endif
215# elif defined (_PA_RISC2_0)
216# define RW_TEST_ARCH "pa-risc 2.0"
217# elif defined (_PA_RISC1_0)
218# define RW_TEST_ARCH "pa-risc 1.0"
219# elif defined (__hppa)
220# define RW_TEST_ARCH "pa-risc"
221# elif defined (__pentiumpro__) || defined (__pentiumpro)
222# define RW_TEST_ARCH "pentiumpro"
223# elif defined (__pentium__) || defined (__pentium)
224# define RW_TEST_ARCH "pentium"
225# elif defined (__i486__) || defined (__i486)
226# define RW_TEST_ARCH "i486"
227# elif defined (__i386__) || defined (__i386)
228# define RW_TEST_ARCH "i386"
229# elif defined (__i586__) || defined (__i586)
230# define RW_TEST_ARCH "i586"
231# elif defined (__ia64)
232# define RW_TEST_ARCH "ia64"
233# elif defined (__mips)
234# define RW_TEST_ARCH "mips"
235# elif defined (__sparcv9)
236# define RW_TEST_ARCH "sparc-v9"
237# elif defined (__sparcv8)
238# define RW_TEST_ARCH "sparc-v8"
239# elif defined (__sparc)
240# define RW_TEST_ARCH "sparc"
241# elif defined (_POWER)
242# if defined (_ARCH_PWR5)
243# define RW_TEST_ARCH "power-5"
244# elif defined (_ARCH_PWR4)
245# define RW_TEST_ARCH "power-4"
246# elif defined (_ARCH_PWR3)
247# define RW_TEST_ARCH "power-3"
248# elif defined (_ARCH_604)
249# define RW_TEST_ARCH "powerpc-604"
250# elif defined (_ARCH_603)
251# define RW_TEST_ARCH "powerpc-603"
252# elif defined (_ARCH_602)
253# define RW_TEST_ARCH "powerpc-602"
254# elif defined (_ARCH_601)
255# define RW_TEST_ARCH "powerpc-601"
256# elif defined (_ARCH_403)
257# define RW_TEST_ARCH "powerpc-403"
258# elif defined (_ARCH_PPC64)
259# define RW_TEST_ARCH "powerpc/LP64"
260# else
261# define RW_TEST_ARCH "powerpc"
262# endif
263# elif defined (_WIN64)
264# define RW_TEST_ARCH "ia64"
265# elif defined (_WIN32)
266# define RW_TEST_ARCH "i86"
267# else
268# define RW_TEST_ARCH "unknown"
269# endif
270
271
272# if defined (_AIX54)
273# define RW_TEST_OS "aix-5.4 (or better)"
274# elif defined (_AIX53)
275# define RW_TEST_OS "aix-5.3"
276# elif defined (_AIX52)
277# define RW_TEST_OS "aix-5.2"
278# elif defined (_AIX51)
279# define RW_TEST_OS "aix-5.1"
280# elif defined (_AIX50)
281# define RW_TEST_OS "aix-5.0"
282# elif defined (_AIX43)
283# define RW_TEST_OS "aix-4.3"
284# elif defined (_AIX41)
285# define RW_TEST_OS "aix-4.1"
286# elif defined (_AIX32)
287# define RW_TEST_OS "aix-3.2"
288# elif defined (_AIX)
289# define RW_TEST_OS "aix"
290# elif defined (__hpux)
291# define RW_TEST_OS "hp-ux"
292# elif defined (__osf__)
293# define RW_TEST_OS "tru64-unix"
294# elif defined (__sgi) && defined (__mips)
295# define RW_TEST_OS "irix"
296# elif defined (__linux__) || defined (__linux)
297# if defined (__ELF__)
298# define LINUX_TYPE "linux-elf"
299# else
300# define LINUX_TYPE "linux"
301# endif
302
303# define RW_TEST_OS LINUX_TYPE " (" \
304 _RWSTD_LINUX_RELEASE ") with glibc " \
305 RW_TEST_STR (__GLIBC__) "." \
306 RW_TEST_STR (__GLIBC_MINOR__)
307
308# elif defined (__SunOS_5_11)
309# define RW_TEST_OS "sunos-5.11"
310# elif defined (__SunOS_5_10)
311# define RW_TEST_OS "sunos-5.10"
312# elif defined (__SunOS_5_9)
313# define RW_TEST_OS "sunos-5.9"
314# elif defined (__SunOS_5_8)
315# define RW_TEST_OS "sunos-5.8"
316# elif defined (__SunOS_5_7)
317# define RW_TEST_OS "sunos-5.7"
318# elif defined (__SunOS_5_6)
319# define RW_TEST_OS "sunos-5.6"
320# elif defined (__sun__)
321# define RW_TEST_OS "sunos"
322# elif defined (_WIN64)
323# define RW_TEST_OS "win64"
324# elif defined (_WIN32)
325# define RW_TEST_OS "win32"
326# else
327# define RW_TEST_OS "unknown"
328# endif
329
330# define RW_TEST_HARDWARE RW_TEST_ARCH " running " RW_TEST_OS
331#else
332# define RW_TEST_HARDWARE "unknown"
333#endif
334
335
337// defined in printf.cpp but not declared in printf.h
338_TEST_EXPORT int
339rw_vasnprintf (char**, size_t*, const char*, va_list);
340
341
343// array to store the number of each type of diagnostic
344static int
345ndiags [N_DIAG_TYPES][2] /* = { { total, active }, ... }*/;
346
347static rw_file *_rw_ftestout;
348
349static jmp_buf test_env;
350
351// set to 1 after the driver has been initialized
352static int _rw_driver_init = 0;
353
354// set to 1 after the driver has finished running
355static int _rw_driver_done = 0;
356
357#if 0 // disabled
358// %S: severity
359// %M: diagnostic
360// %m: diagnostic if not empty
361// %F: file name
362// %f: file name if not empty
363// %C: clause
364// %c: clause if not empty
365// %L: line number
366// %l: line number if valid
367// %T: text
368// %t: text if not empty
369static char diag_pattern [80];
370#endif
371
372// option: use CSV format (comma separated values)
373static int _rw_opt_csv = 0;
374
375static char clause_id [80];
376
377
379#define CHECK_INIT(init, func) _rw_check_init (init, __LINE__, func)
380
381static inline void
382_rw_check_init (int expect_init, int line, const char *func)
383{
384 if (expect_init) {
385 // driver is expected to be initialized
386 if (!_rw_driver_init) {
388 "%s:%d: %s: error: test driver not initialized yet\n",
389 __FILE__, line, func);
390
391 abort ();
392 }
393 }
394 else if (_rw_driver_init) {
395 // driver is NOT expected to be initialized
397 "%s:%d: %s: error: test driver already initialized\n",
398 __FILE__, line, func);
399
400 abort ();
401 }
402
403 if (_rw_driver_done) {
404 // driver is NOT expected to be done at this point
406 "%s:%d: %s: warning: test finished, cannot call\n",
407 __FILE__, line, func);
408 }
409}
410
411
413static int
414_rw_opt_brief (int argc, char *argv[])
415{
416 static int opt_brief;
417
418 if (0 == argc) {
419 // query mode: return the value of the option
420 return opt_brief;
421 }
422
423 if (1 == argc && argv && 0 == argv [0]) {
424 // help mode: set argv[0] to the text of the help message
425
426 static const char helpstr[] = {
427 "Enables brief mode.\n"
428 };
429
430 argv [0] = _RWSTD_CONST_CAST (char*, helpstr);
431
432 return 0;
433 }
434
435 // set mode: enable the option
436 opt_brief = 1;
437
438 return 0;
439}
440
441
443static int
444_rw_opt_quiet (int argc, char *argv[])
445{
446 static int opt_quiet;
447
448 if (0 == argc) {
449 // query mode: return the value of the option
450 return opt_quiet;
451 }
452
453 if (1 == argc && argv && 0 == argv [0]) {
454 // help mode: set argv[0] to the text of the help message
455
456 static const char helpstr[] = {
457 "Enables quiet mode.\n"
458 "In quiet mode only diagnostics with severity 7 and above are "
459 "issued."
460 };
461
462 argv [0] = _RWSTD_CONST_CAST (char*, helpstr);
463
464 return 0;
465 }
466
467 // set mode: enable the option
468 _rw_diag_mask = ~((1 << 7) | (1 << 8) | (1 << 9));
469 opt_quiet = 1;
470
471 return 0;
472}
473
474
476static int
477_rw_opt_verbose (int argc, char *argv[])
478{
479 static int opt_verbose;
480
481 if (0 == argc) {
482 // query mode: return the value of the option
483 return opt_verbose;
484 }
485
486 if (1 == argc && argv && 0 == argv [0]) {
487 // help mode: set argv[0] to the text of the help message
488
489 static const char helpstr[] = {
490 "Enables verbose mode.\n"
491 };
492
493 argv [0] = _RWSTD_CONST_CAST (char*, helpstr);
494
495 return 0;
496 }
497
498 // set mode: enable the option
499 opt_verbose = 1;
500
501 return 0;
502}
503
504
506static int
507_rw_setopt_csv (int argc, char *argv[])
508{
509 if (1 == argc && argv && 0 == argv [0]) {
510 static const char helpstr[] = {
511 "Enables CSV (comma separated values) mode.\n"
512 };
513
514 argv [0] = _RWSTD_CONST_CAST (char*, helpstr);
515
516 return 0;
517 }
518
519 _rw_opt_csv = 1;
520 return 0;
521}
522
523
525static int
526_rw_opt_compat (int argc, char *argv[])
527{
528 static int opt_compat;
529
530 if (0 == argc) {
531 // query mode: return the value of the option
532 return opt_compat;
533 }
534
535 if (1 == argc && argv && 0 == argv [0]) {
536 // help mode: set argv[0] to the text of the help message
537
538 static const char helpstr[] = {
539 "Enables RWTest-format compatibility mode.\n"
540 };
541
542 argv [0] = _RWSTD_CONST_CAST (char*, helpstr);
543
544 return 0;
545 }
546
547 // set mode: enable the option
548 opt_compat = 1;
549
550 return 0;
551}
552
553
555static int
556_rw_opt_no_stdout (int argc, char *argv[])
557{
558 static int opt_no_stdout;
559
560 if (0 == argc) {
561 // query mode: return the value of the option
562 return opt_no_stdout;
563 }
564
565 if (1 == argc && argv && 0 == argv [0]) {
566 // help mode: set argv[0] to the text of the help message
567
568 static const char helpstr[] = {
569 "Prevents the program from using stdandard output for diagnostic\n"
570 "messages. Instead, the driver will create a log file with a name\n"
571 "obtained from the from the basename of the program source file,\n"
572 "usually obtained by passing the value of the __FILE__ macro to\n"
573 "the driver, with the .out extension. If successful, the driver\n"
574 "will write all diagnostic messages issued by the program to this\n"
575 "file. Otherwise, the driver exits with an error.\n"
576 };
577
578 argv [0] = _RWSTD_CONST_CAST (char*, helpstr);
579
580 return 0;
581 }
582
583 // set mode: enable the option
584 opt_no_stdout = 1;
585
586 return 0;
587}
588
589
591static int
592_rw_setopt_output_file (int argc, char *argv[])
593{
594 if (1 == argc && argv && 0 == argv [0]) {
595 static const char helpstr[] = {
596 "Specifies the name of the output file to be used by the program\n"
597 "for diagnostic messages. Unless this option is specified, the\n"
598 "program will issue all diagnostic messages to the standard output."
599 "\nDriver diagnostics are always directed to stderr.\n"
600 };
601
602 argv [0] = _RWSTD_CONST_CAST (char*, helpstr);
603
604 return 0;
605 }
606
607 const char *file_name = 0;
608
609 if ('-' == argv [0][0] && ('O' == argv [0][1] || 'o' == argv [0][1])
610 && argv [0][2]) {
611 file_name = argv [0] + 2;
612 }
613 else if (1 < argc && '-' != argv [1][0]) {
614 file_name = argv [1];
615 }
616
617 if (file_name) {
618 if (file_name[0] != '-' || file_name[1] != '\0') {
619 FILE* const f = fopen (file_name, "w");
620
621 if (f) {
622 if (_rw_ftestout && _rw_ftestout != rw_stdout)
623 fclose ((FILE*)(void*)_rw_ftestout);
624
625 _rw_ftestout = (rw_file*)(void*)f;
626 }
627 }
628 else
629 _rw_ftestout = (rw_file*)(void*)stdout;
630 }
631
632 // return 0 on success, any non-zero value on failure
633 return !(_rw_ftestout != 0);
634}
635
636
638_TEST_EXPORT int
639rw_vsetopts (const char *opts, va_list va);
640
641
643static int
644_rw_use_color ()
645{
646#ifndef _RWSTD_NO_ISATTY
647
648 // is output sent to a terminal?
649 // if so, assume a vt100 compatible terminal for now
650 static const int tty = _rw_ftestout ?
651 isatty (fileno ((FILE*)(void*)_rw_ftestout)) : 0;
652
653#else // if defined (_RWSTD_NO_ISATTY)
654
655 // FIXME: deal with a missing isatty() and Windows
656 static const int tty = 0;
657
658#endif // _RWSTD_NO_ISATTY
659
660 return 0 != tty;
661}
662
663
665static int
666_rw_setopt_ulimit (int argc, char **argv)
667{
668 if (1 == argc && argv && 0 == argv [0]) {
669 static const char helpstr[] = {
670 "Sets limits on one or more system resources.\n"
671 "The syntax of <arg> is as follows:\n"
672 "<arg> ::= <limit-list>\n"
673 "<limit-list> ::= <limit> [, <limit-list> ]\n"
674 "<limit> ::= <resource> : <number>\n"
675 "<resource> ::= core | cpu | data | fsize | nofile | stack | as\n"
676 " ::= CORE | CPU | DATA | FSIZE | NOFILE | STACK | AS\n"
677 " ::= Core | Cpu | Data | Fsize | Nofile | Stack | As\n"
678 "Names in all lowercase letters set the soft limit, those in all\n"
679 "uppercase set the hard limit, names in mixed case will cause \n"
680 "both limits to attempt to be set.\n"
681 };
682
683 argv [0] = _RWSTD_CONST_CAST (char*, helpstr);
684
685 return 0;
686 }
687
688 RW_ASSERT (0 != argv);
689
690#if defined (RLIMIT_CORE) || defined (RLIMIT_CPU) || defined (RLIMIT_DATA)
691
692 static const struct {
693 const char* name; // name to set only the soft limit
694 const char* caps; // name to set only the hard limit
695 const char* mixd; // name to set both limits
696 int resource;
697 } limits[] = {
698
699#ifdef RLIMIT_CORE
700 { "core", "CORE", "Core", RLIMIT_CORE },
701#endif // RLIMIT_CORE
702#ifdef RLIMIT_CPU
703 { "cpu", "CPU", "Cpu", RLIMIT_CPU },
704#endif // RLIMIT_CPU
705#ifdef RLIMIT_DATA
706 { "data", "DATA", "Data", RLIMIT_DATA },
707#endif // RLIMIT_DATA
708#ifdef RLIMIT_FSIZE
709 { "fsize", "FSIZE", "Fsize", RLIMIT_FSIZE },
710#endif // RLIMIT_FSIZE
711#ifdef RLIMIT_NOFILE
712 { "nofile", "NOFILE", "Nofile", RLIMIT_NOFILE },
713#endif // RLIMIT_NOFILE
714#ifdef RLIMIT_STACK
715 { "stack", "STACK", "Stack", RLIMIT_STACK },
716#endif // RLIMIT_STACK
717#ifdef RLIMIT_AS
718 { "as", "AS", "As", RLIMIT_AS },
719#endif // RLIMIT_AS
720 { 0, 0, 0, 0 }
721 };
722
723 const char* arg = strchr (argv [0], '=');
724
725 while (arg && *arg) {
726
727 ++arg;
728
729 const size_t arglen = strlen (arg);
730
731 for (size_t i = 0; limits [i].name; ++i) {
732 const size_t limit_len = strlen (limits [i].name);
733
734 if ( limit_len < arglen
735 && ( 0 == memcmp (limits [i].name, arg, limit_len)
736 || 0 == memcmp (limits [i].caps, arg, limit_len)
737 || 0 == memcmp (limits [i].mixd, arg, limit_len))
738 && ':' == arg [limit_len]) {
739
740 // determine whether the hard limit and/or
741 // the soft limit should be set
742 const bool hard = isupper (arg [0]);
743 const bool soft = islower (arg [1]);
744
745 arg += limit_len + 1;
746
747 char *end;
748 const long lim = strtol (arg, &end, 10);
749
750 arg = end;
751
752 if ('\0' != *arg && ',' != *arg)
753 break;
754
755 rlimit rlim;
756 memset (&rlim, 0, sizeof rlim);
757
758 rlim.rlim_cur = soft ? lim : RLIM_SAVED_CUR;
759 rlim.rlim_max = hard ? lim : RLIM_SAVED_MAX;
760
761 const int result = setrlimit (limits [i].resource, &rlim);
762
763 if (result) {
765 "setrlimit(RLIMIT_%s, { .rlim_cur=%ld, "
766 ".rlim_max=%ld }) error: %m\n",
767 limits [i].caps, rlim.rlim_cur, rlim.rlim_max);
768 }
769
770 break;
771 }
772 }
773
774 if ('\0' != *arg && ',' != *arg) {
776 "%s: parse error at \"%s\"\n", argv [0], arg);
777 return 1;
778 }
779 }
780
781#else // if !defined (RLIMIT_XXX)
782
783 rw_fprintf (rw_stderr, "warning: --ulimit: ignoring unimplemented "
784 "option: %s\n", argv [0]);
785
786#endif // defined (RLIMIT_XXX)
787
788 return 0;
789
790}
791
792
793
795static int
796_rw_setopt_compat_error (int argc, char **argv, char opt)
797{
798 if (1 == argc && argv && 0 == argv [0]) {
799 static const char helpstr[] = {
800 "Compatibility-mode option\n"
801 };
802
803 argv [0] = _RWSTD_CONST_CAST (char*, helpstr);
804
805 return 0;
806 }
807
808 rw_fprintf (rw_stderr, "error: -%c: option available only "
809 "in compatibility mode\n", opt);
810 return 1;
811}
812
813static int
814_rw_setopt_compat_warn (int argc, char **argv, char opt)
815{
816 if (1 == argc && argv && 0 == argv [0]) {
817 return _rw_setopt_compat_error (argc, argv, opt);
818 }
819
821 "warning: -%c: ignoring unimplemented compatibility "
822 "mode option\n", opt);
823 return 0;
824}
825
826
827static int
828_rw_setopt_compat_append (int argc, char **argv)
829{
830 if (_rw_opt_compat (0, 0))
831 return _rw_setopt_compat_warn (argc, argv, 'A');
832
833 return _rw_setopt_compat_error (argc, argv, 'A');
834}
835
836
837static int
838_rw_setopt_compat_compiler (int argc, char **argv)
839{
840 if (_rw_opt_compat (0, 0))
841 return _rw_setopt_compat_warn (argc, argv, 'C');
842
843 return _rw_setopt_compat_error (argc, argv, 'C');
844}
845
846
847static int
848_rw_setopt_compat_dir (int argc, char **argv)
849{
850 if (_rw_opt_compat (0, 0))
851 return _rw_setopt_compat_warn (argc, argv, 'D');
852
853 return _rw_setopt_compat_error (argc, argv, 'D');
854}
855
856
857static int
858_rw_setopt_compat_debug_file (int argc, char **argv)
859{
860 if (_rw_opt_compat (0, 0))
861 return _rw_setopt_compat_warn (argc, argv, 'G');
862
863 return _rw_setopt_compat_error (argc, argv, 'G');
864}
865
866
867static int
868_rw_setopt_compat_alarm (int argc, char **argv)
869{
870 if (_rw_opt_compat (0, 0))
871 return _rw_setopt_compat_warn (argc, argv, 'L');
872
873 return _rw_setopt_compat_error (argc, argv, 'L');
874}
875
876
877static int
878_rw_setopt_compat_machine (int argc, char **argv)
879{
880 if (_rw_opt_compat (0, 0))
881 return _rw_setopt_compat_warn (argc, argv, 'M');
882
883 return _rw_setopt_compat_error (argc, argv, 'M');
884}
885
886
887static int
888_rw_setopt_compat_output_file (int argc, char **argv)
889{
890 if (_rw_opt_compat (0, 0))
891 return _rw_setopt_output_file (argc, argv);
892
893 return _rw_setopt_compat_error (argc, argv, 'O');
894}
895
896
897static int
898_rw_setopts_compat ()
899{
900 const int nopts =
901 rw_setopts ("A " // append output
902 "C: " // compiler
903 "D: " // directory
904 "G: " // debug file
905 "L: " // alarm
906 "M: " // machine
907 "O: ", // output file
908 _rw_setopt_compat_append,
909 _rw_setopt_compat_compiler,
910 _rw_setopt_compat_dir,
911 _rw_setopt_compat_debug_file,
912 _rw_setopt_compat_alarm,
913 _rw_setopt_compat_machine,
914 _rw_setopt_compat_output_file,
915 0 /* detect missing handlers */);
916
917 if (7 > nopts) {
919 "%s:%d: rw_setopts() failed\n", __FILE__, __LINE__);
920 abort ();
921 return 1;
922 }
923
924 return 0;
925}
926
927
928#ifdef _WIN32
929
930# if defined (_MSC_VER) && _MSC_VER >= 1400
931
932static void
933_rw_invalid_parameter (const wchar_t* /*expression*/,
934 const wchar_t* /*function*/,
935 const wchar_t* /*file*/,
936 unsigned int /*line*/,
937 uintptr_t /*pReserved*/)
938{
939 // empty handler - ignore invalid parameter validation
940}
941
942# endif // MSVC 8.0 and later
943
944static int
945_rw_opt_no_popups (int argc, char *argv[])
946{
947 static int opt_no_popups;
948
949 if (0 == argc) {
950 // query mode: return the value of the option
951 return opt_no_popups;
952 }
953
954 if (1 == argc && argv && 0 == argv [0]) {
955 // help mode: set argv[0] to the text of the help message
956
957 static const char helpstr[] = {
958 "Prevents the program from using message box popup window's for\n"
959 "error messages.\n"
960 };
961
962 argv [0] = _RWSTD_CONST_CAST (char*, helpstr);
963
964 return 0;
965 }
966
967 // set mode: enable the option
968 opt_no_popups = 1;
969
970 SetErrorMode (SEM_FAILCRITICALERRORS | SEM_NOGPFAULTERRORBOX);
971
972# ifdef _MSC_VER
973# if _MSC_VER >= 1400
974 _set_invalid_parameter_handler (_rw_invalid_parameter);
975# endif // MSVC 8.0 and later
976
977 _CrtSetReportMode (_CRT_WARN, _CRTDBG_MODE_FILE | _CRTDBG_MODE_DEBUG);
978 _CrtSetReportFile (_CRT_WARN, _CRTDBG_FILE_STDERR);
979 _CrtSetReportMode (_CRT_ERROR, _CRTDBG_MODE_FILE | _CRTDBG_MODE_DEBUG);
980 _CrtSetReportFile (_CRT_ERROR, _CRTDBG_FILE_STDERR);
981 _CrtSetReportMode (_CRT_ASSERT, _CRTDBG_MODE_FILE | _CRTDBG_MODE_DEBUG);
982 _CrtSetReportFile (_CRT_ASSERT, _CRTDBG_FILE_STDERR);
983# endif // _MSC_VER
984
985 return 0;
986}
987
988#endif // _WIN32
989
990
991#if defined (_MSC_VER) && defined (_DEBUG)
992
993static int
994_rw_opt_debug_heap (int argc, char *argv[])
995{
996 static int opt_debug_heap;
997
998 if (0 == argc) {
999 // query mode: return the value of the option
1000 return opt_debug_heap;
1001 }
1002
1003 if (1 == argc && argv && 0 == argv [0]) {
1004 // help mode: set argv[0] to the text of the help message
1005
1006 static const char helpstr[] = {
1007 "Enables the heap consistency checking on every memory allocation\n"
1008 "and deallocation request.\n"
1009 };
1010
1011 argv [0] = _RWSTD_CONST_CAST (char*, helpstr);
1012
1013 return 0;
1014 }
1015
1016 // set mode: enable the option
1017 opt_debug_heap = 1;
1018
1019 _CrtSetDbgFlag ( _CRTDBG_ALLOC_MEM_DF
1020 | _CRTDBG_CHECK_ALWAYS_DF
1021 | _CRTDBG_LEAK_CHECK_DF);
1022
1023 return 0;
1024}
1025
1026#endif // _MSC_VER && _DEBUG
1027
1028
1029#ifdef _WIN32
1030
1031static int
1032_rw_setopts_windows ()
1033{
1034 int nopts =
1035 rw_setopts ("|-no-popups ",
1036 _rw_opt_no_popups,
1037 0 /* detect missing handlers */);
1038
1039 if (1 > nopts) {
1041 "%s:%d: rw_setopts() failed\n", __FILE__, __LINE__);
1042 abort ();
1043 return 1;
1044 }
1045
1046# if defined (_MSC_VER) && defined (_DEBUG)
1047
1048 nopts =
1049 rw_setopts ("|-debug-heap ",
1050 _rw_opt_debug_heap,
1051 0 /* detect missing handlers */);
1052
1053 if (1 > nopts) {
1055 "%s:%d: rw_setopts() failed\n", __FILE__, __LINE__);
1056 abort ();
1057 return 1;
1058 }
1059
1060# endif // _MSC_VER && _DEBUG
1061
1062 return 0;
1063}
1064
1065#endif // _WIN32
1066
1067
1069_TEST_EXPORT int
1070rw_vtest (int argc, char **argv,
1071 const char *file_name,
1072 const char *clause,
1073 const char *comment,
1074 int (*fun)(int, char**),
1075 const char *optstr,
1076 va_list va)
1077{
1078 CHECK_INIT (false, "rw_vtest()");
1079
1080 // set the default test output to stdout
1081 RW_ASSERT (0 == _rw_ftestout);
1082 RW_ASSERT (0 != rw_stdout);
1083
1084 _rw_ftestout = rw_stdout;
1085
1086 _rw_driver_init = 1;
1087
1088 if (optstr && 0 > rw_vsetopts (optstr, va)) {
1090 "%s:%d: rw_setopts() failed\n", __FILE__, __LINE__);
1091 return 1;
1092 }
1093
1094 const int nopts =
1095 rw_setopts ("|-no-stdout "
1096 "|-diags= " // argument required
1097 "|-trace "
1098 "|-severity= " // argument required
1099 "|-csv "
1100 "|-compat "
1101 "|-ulimit= " // argument required
1102 "o|-output:" // argument optional
1103 "b|-brief "
1104 "q|-quiet "
1105 "v|-verbose",
1106 _rw_opt_no_stdout,
1110 _rw_setopt_csv,
1111 _rw_opt_compat,
1112 _rw_setopt_ulimit,
1113 _rw_setopt_output_file,
1114 _rw_opt_brief,
1115 _rw_opt_quiet,
1116 _rw_opt_verbose,
1117 0);
1118
1119 if (3 > nopts) {
1121 "%s:%d: rw_setopts() failed\n", __FILE__, __LINE__);
1122 abort ();
1123 return 1;
1124 }
1125
1126 _rw_setopts_compat ();
1127
1129
1131
1132#ifdef _WIN32
1133 _rw_setopts_windows ();
1134#endif // _WIN32
1135
1136 int status = rw_runopts (argc, argv);
1137
1138 if (status)
1139 return status;
1140
1141 if (rw_stdout == _rw_ftestout) {
1142
1143 if (_rw_opt_no_stdout (0, 0) && file_name) {
1144 char fname [256];
1145
1146 const char* const slash = strrchr (file_name, _RWSTD_PATH_SEP);
1147 strcpy (fname, slash ? slash + 1 : file_name);
1148
1149 char* const dot = strchr (fname, '.');
1150 if (dot)
1151 strcpy (dot, ".out");
1152 else
1153 strcat (fname, ".out");
1154
1155 _rw_ftestout = (rw_file*)(void*)fopen (fname, "w");
1156 }
1157 else
1158 _rw_ftestout = rw_stdout;
1159 }
1160
1161 if (clause)
1162 strcpy (clause_id, clause);
1163
1164 static const char thick_line[] = {
1165 "############################################################"
1166 };
1167
1168 static const char begin_fmt[] = {
1169 "\n"
1170 "# COMPILER: %s\n"
1171 "# ENVIRONMENT: %s\n"
1172 "# FILE: %s\n"
1173 "# COMPILED: %s, %s\n"
1174 "# COMMENT: %s\n"
1175 "%s\n"
1176 };
1177
1178 // allow file_name to be null
1179 const char* const fname =
1180 file_name ? strrchr (file_name, _RWSTD_PATH_SEP) : 0;
1181
1182 rw_info (0, 0, 0,
1183 begin_fmt,
1185 fname ? fname + 1 : file_name,
1186 __DATE__, __TIME__,
1187 comment ? comment : "",
1188 thick_line);
1189
1190 status = setjmp (test_env);
1191
1192 if (0 == status) {
1193 // environment set, execute the callback function
1194 status = fun (argc, argv);
1195 }
1196 else {
1197 // fatal test error (via a call to rw_fatal())
1198 }
1199
1200 _rw_driver_done = 1;
1201
1202 static const char tblrow[] =
1203 "+-----------------------+----------+----------+----------+";
1204
1205 rw_fprintf (_rw_ftestout,
1206 "# %s\n"
1207 "# | DIAGNOSTIC | ACTIVE | TOTAL | INACTIVE |\n"
1208 "# %s\n",
1209 tblrow, tblrow);
1210
1211 int nlines = 0;
1212
1213 for (int i = 0; i != N_DIAG_TYPES; ++i) {
1214 if (ndiags [i][0] || !(_rw_diag_mask & (1 << diag_trace))) {
1215
1216 // print out details for any non-zero totals
1217 // or for all totals when debugging or tracing
1218 // is enabled
1219
1220 ++nlines;
1221
1222 const long inactive = ndiags [i][0] - ndiags [i][1];
1223 const long total = long (ndiags [i][0]);
1224
1225 const long pct = total ? long ((inactive * 100.0) / total) : 0;
1226
1227 const char* pfx = "";
1228 const char* sfx = "";
1229
1230 static int use_color = _rw_use_color ();
1231
1232 if (use_color) {
1233 pfx = ndiags [i][1] ? diag_msgs [i].esc_pfx : "";
1234 sfx = ndiags [i][1] ? diag_msgs [i].esc_sfx : "";
1235 }
1236
1237 rw_fprintf (_rw_ftestout,
1238 "# | (S%d) %-*s |%s %8d %s| %8d | %7ld%% |\n",
1239 i, int (sizeof diag_msgs [i].code),
1240 diag_msgs [i].code,
1241 pfx, ndiags [i][1], sfx, ndiags [i][0], pct);
1242 }
1243 }
1244
1245 if (0 == nlines)
1246 rw_fprintf (_rw_ftestout, "# no diagnostics\n");
1247
1248 rw_fprintf (_rw_ftestout, "# %s\n", tblrow);
1249
1250 if (_rw_opt_compat (0, 0)) {
1251
1252 // TO DO: get rid of this
1253
1254 // RWTest compatibility format
1255
1256 rw_fprintf (_rw_ftestout,
1257 "%s\n"
1258 "## Warnings = %d\n"
1259 "## Assertions = %d\n"
1260 "## FailedAssertions = %d\n",
1261 thick_line,
1262 ndiags [diag_warn][1] + ndiags [diag_xwarn][1],
1263 ndiags [diag_assert][0],
1264 ndiags [diag_assert][1] + ndiags [diag_xassert][1]);
1265 }
1266
1267 if (_rw_ftestout && _rw_ftestout != rw_stdout) {
1268 fclose ((FILE*)(void*)_rw_ftestout);
1269 _rw_ftestout = 0;
1270 }
1271
1272 return status;
1273}
1274
1275
1277_TEST_EXPORT int
1278rw_test (int argc, char **argv,
1279 const char *fname,
1280 const char *clause,
1281 const char *comment,
1282 int (*testfun)(int, char**),
1283 const char *optstr,
1284 ...)
1285{
1286 CHECK_INIT (false, "rw_test()");
1287
1288 va_list va;
1289 va_start (va, optstr);
1290
1291 const int status =
1292 rw_vtest (argc, argv, fname, clause, comment, testfun, optstr, va);
1293
1294 va_end (va);
1295
1296 return status;
1297}
1298
1299
1301// escape every occurrence of the double quote character in the string
1302// pointed to by buf by prepending to it the escape character specified
1303// by the last acrgument
1304// returns the new buffer if the size of the existing buffer isn't
1305// sufficient and sets *pbufsize to the size of the newly allocated
1306// buffer, otherwise the original value of buf and leaves *pbufsize
1307// unchanged
1308static char*
1309_rw_escape (char *buf, size_t bufsize, char esc)
1310{
1311 // handle null buffer
1312 if (0 == buf)
1313 return buf;
1314
1315 // count the number of embedded quotes
1316 char *quote = buf;
1317 size_t nquotes = 0;
1318 while ((quote = strchr (quote, '"'))) {
1319 ++nquotes;
1320 ++quote;
1321 }
1322
1323 // no quotes found, return the original buffer
1324 if (0 == nquotes)
1325 return buf;
1326
1327 // conpute the size of the buffer that will be needed to escape
1328 // all the double quotes
1329 size_t newbufsize = strlen (buf) + nquotes + 1;
1330
1331 char *newbuf = 0;
1332
1333 if (0 /* newbufsize <= bufsize */) {
1334 // FIXME: escape embedded quotes in place w/o reallocation
1335 _RWSTD_UNUSED (bufsize);
1336 }
1337 else {
1338 newbuf = (char*)malloc (newbufsize);
1339 if (0 == newbuf) {
1340 return 0;
1341 }
1342
1343 // set the next pointer to the beginning of the new buffer
1344 // as the destination where to copy the string argument
1345 char *next = newbuf;
1346
1347 // set quote to initially point to the beginning of
1348 // the source buffer and then just past the last quote
1349 quote = buf;
1350
1351 for (char *q = buf; ; ++q) {
1352
1353 // look for the next (or first) quote
1354 q = strchr (q, '"');
1355
1356 // compute the number of characters, excluding the quote
1357 // to copy to the destination buffer
1358 const size_t nchars = q ? size_t (q - quote) : strlen (quote);
1359
1360 memcpy (next, quote, nchars);
1361
1362 if (q) {
1363 // append the escape character to the destination buffer
1364 next [nchars] = esc;
1365
1366 // append the quote from the source string
1367 next [nchars + 1] = '"';
1368
1369 // advance the destination pointer past the quote
1370 next += nchars + 2;
1371
1372 // advance the source pointer past the embedded quote
1373 quote = q + 1;
1374 }
1375 else {
1376 // NUL-terminate the destination buffer
1377 *next = '\0';
1378 break;
1379 }
1380 }
1381 }
1382
1383 return newbuf;
1384}
1385
1386
1388static void
1389_rw_vissue_diag (diag_t diag, int severity, const char *file, int line,
1390 const char *fmt, va_list va)
1391{
1392 CHECK_INIT (true, "_rw_vissue_diag()");
1393
1394 if (0 == fmt)
1395 fmt = "";
1396
1397 static char fmterr[] = "*** formatting error ***";
1398
1399 char *usrbuf = 0;
1400 const int nchars = rw_vasnprintf (&usrbuf, 0, fmt, va);
1401
1402 if (nchars < 0 || 0 == usrbuf)
1403 usrbuf = fmterr;
1404
1405 // compute the number of newline characters in the text
1406 int nlines = 0;
1407 for (const char *nl = usrbuf; (nl = strchr (nl, '\n')); ++nl)
1408 ++nlines;
1409
1410 static const int use_color = _rw_use_color ();
1411
1412 const char* const diagstr[] = {
1413 use_color ? diag_msgs [severity].esc_pfx : "",
1414 *diag_msgs [severity].code ? diag_msgs [severity].code : "UNKNOWN",
1415 use_color ? diag_msgs [severity].esc_sfx : "",
1416 _rw_opt_verbose (0, 0) && *diag_msgs [severity].desc ?
1417 diag_msgs [severity].desc : 0
1418 };
1419
1420 const char* const traced_diag =
1421 0 == severity && diag_msgs [diag].code ? diag_msgs [diag].code : 0;
1422
1423 const char* const slash = file ? strrchr (file, _RWSTD_PATH_SEP) : 0;
1424 if (slash)
1425 file = slash + 1;
1426
1427 char *mybuf = 0;
1428
1429 if (_rw_opt_csv) {
1430
1431 // format all fields as comma separated values (CSV):
1432 // -- a field containing the quote character, the comma,
1433 // or the newline or linefeed character must be enclosed
1434 // in a pair of double quotes
1435 // -- every occurrence of the double quote character in a field
1436 // must be escaped by prepening another double quote character
1437 // to it
1438
1439 // escape all double quotes by prepending the double
1440 // quote character to each according to the CSV format
1441 char* const newbuf = _rw_escape (usrbuf, 0, '"');
1442 if (newbuf != usrbuf) {
1443 free (usrbuf);
1444 usrbuf = newbuf;
1445 }
1446
1447 mybuf =
1448 rw_sprintfa ("%d, " // severity
1449 "\"%s%s" // diagnostic
1450 "%{?}_%s%{;}%s\", " // traced diagnostic
1451 "\"%s\", " // clause
1452 "\"%s\", " // file
1453 "%d, " // line
1454 "\"%s\"", // user text
1455 severity,
1456 diagstr [0], diagstr [1],
1457 0 != traced_diag, traced_diag, diagstr [2],
1458 clause_id,
1459 0 != file ? file : "",
1460 line,
1461 usrbuf);
1462 }
1463 else {
1464
1465 nlines += 2 + ('\0' != *clause_id) + (0 != file) + (0 < line);
1466
1467 mybuf =
1468 rw_sprintfa ("# %s" // escape prefix
1469 "%s" // diagnostic
1470 "%{?}_%s%{;}" // traced diagnostic
1471 "%s " // escape suffix
1472 "(S%d)" // severity
1473 "%{?}, %s%{;} " // description
1474 "(%d lines):\n" // number of lines
1475 "# TEXT: %s\n" // user text
1476 "%{?}# CLAUSE: %s\n%{;}" // clause if not empty
1477 "%{?}# FILE: %s\n%{;}" // file if not null
1478 "%{?}# LINE: %d\n%{;}", // line if positive
1479 diagstr [0],
1480 diagstr [1],
1481 0 != traced_diag, traced_diag,
1482 diagstr [2],
1483 severity,
1484 0 != diagstr [3], diagstr [3],
1485 nlines,
1486 usrbuf,
1487 '\0' != *clause_id, clause_id,
1488 0 != file, file,
1489 0 < line, line);
1490 }
1491#if 0 // disabled
1492 else {
1493
1494 mybuf =
1495 rw_sprintfa ("# %s%s" // diagnostic
1496 "%{?}_%s%{;}%s " // traced diagnostic
1497 "(S%d): " // severity
1498 "%{?}[%s] %{;}" // clause if not empty
1499 "%{?}(%d lines): %{;}" // number of lines if > 1
1500 "%{?}%s:" // if (file) then file
1501 "%{?}%d:%{;} " // if (0 < line) line
1502 "%{:}" // else
1503 "%{?}line %d: %{;}" // if (0 < line) line
1504 "%{;}" // endif
1505 "%s", // user text
1506 diagstr [0], diagstr [1],
1507 0 != traced_diag, traced_diag, diagstr [2],
1508 severity,
1509 '\0' != *clause_id, clause_id,
1510 1 < nlines, nlines,
1511 0 != file, file,
1512 0 < line, line,
1513 0 < line, line,
1514 usrbuf);
1515 }
1516#endif // 0/1
1517
1518 rw_fprintf (_rw_ftestout, "%s\n", mybuf);
1519
1520 if (mybuf != fmterr)
1521 free (mybuf);
1522
1523 if (usrbuf != fmterr)
1524 free (usrbuf);
1525}
1526
1527
1529static void
1530_rw_vdiag (diag_t diag, int severity, const char *file, int line,
1531 const char *fmt, va_list va)
1532{
1533 // ignore this diagnostic if it's present in _rw_diag_ignore
1534 if (_rw_diag_ignore & (1 << diag))
1535 return;
1536
1537 CHECK_INIT (true, "_rw_vdiag()");
1538
1539 // check if the diagnostic is expected
1540 const int expected = 0 != _rw_expected (line);
1541
1542 if (expected) {
1543 if (severity) {
1544 // if the diagnostic is expected to be active,
1545 // adjust its type and severity
1546 if (diag_assert == diag)
1547 diag = diag_xassert;
1548 else if (diag_warn == diag)
1549 diag = diag_xwarn;
1550
1551 severity = diag * severity;
1552 }
1553 else {
1554 // if the diagnostic is expected to be active but isn't,
1555 // adjust its type to an unexpectdly inactive one
1556 if (diag_assert == diag || diag_warn == diag)
1557 diag = diag_expect;
1558
1559 severity = diag;
1560 }
1561 }
1562 else if (diag) {
1563 // normalize the severity
1564 severity = diag * severity;
1565 }
1566
1567 if (severity < 0)
1568 severity = 0;
1569 else if (N_DIAG_TYPES <= severity)
1570 severity = N_DIAG_TYPES - 1;
1571
1572 // increment the diagnostic counter
1573 ++ndiags [diag][0];
1574
1575 if (severity) {
1576
1577 ++ndiags [diag][1];
1578 }
1579
1580 const int sevbit = (1 << severity);
1581
1582 if (0 == (sevbit & _rw_diag_mask)) {
1583 // issue the diagnostic
1584 _rw_vissue_diag (diag, severity, file, line, fmt, va);
1585 }
1586
1587 if (diag_fatal == diag && severity) {
1588 // fatal error, terminate test
1589 longjmp (test_env, severity);
1590 }
1591}
1592
1593
1595_TEST_EXPORT int
1596rw_fatal (int success, const char *file, int line, const char *fmt, ...)
1597{
1598 CHECK_INIT (true, "rw_fatal()");
1599
1600 va_list va;
1601 va_start (va, fmt);
1602
1603 _rw_vdiag (diag_fatal, 0 == success, file, line, fmt, va);
1604
1605 va_end (va);
1606
1607 return success;
1608}
1609
1610
1612_TEST_EXPORT int
1613rw_error (int success, const char *file, int line, const char *fmt, ...)
1614{
1615 CHECK_INIT (true, "rw_error()");
1616
1617 va_list va;
1618 va_start (va, fmt);
1619
1620 _rw_vdiag (diag_error, 0 == success, file, line, fmt, va);
1621
1622 va_end (va);
1623
1624 return success;
1625}
1626
1627
1629_TEST_EXPORT int
1630rw_assert (int success, const char *file, int line, const char *fmt, ...)
1631{
1632 CHECK_INIT (true, "rw_assert()");
1633
1634 va_list va;
1635 va_start (va, fmt);
1636
1637 _rw_vdiag (diag_assert, 0 == success, file, line, fmt, va);
1638
1639 va_end (va);
1640
1641 return success;
1642}
1643
1644
1646_TEST_EXPORT int
1647rw_warn (int success, const char *file, int line, const char *fmt, ...)
1648{
1649 CHECK_INIT (true, "rw_warn()");
1650
1651 va_list va;
1652 va_start (va, fmt);
1653
1654 _rw_vdiag (diag_warn, 0 == success, file, line, fmt, va);
1655
1656 va_end (va);
1657
1658 return success;
1659}
1660
1661
1663_TEST_EXPORT int
1664rw_note (int success, const char *file, int line, const char *fmt, ...)
1665{
1666 CHECK_INIT (true, "rw_note()");
1667
1668 va_list va;
1669 va_start (va, fmt);
1670
1671 _rw_vdiag (diag_note, 0 == success, file, line, fmt, va);
1672
1673 va_end (va);
1674
1675 return success;
1676}
1677
1678
1680_TEST_EXPORT int
1681rw_info (int success, const char *file, int line, const char *fmt, ...)
1682{
1683 CHECK_INIT (true, "rw_info()");
1684
1685 va_list va;
1686 va_start (va, fmt);
1687
1688 _rw_vdiag (diag_info, 0 == success, file, line, fmt, va);
1689
1690 va_end (va);
1691
1692 return success;
1693}
1694
1695
1697_TEST_EXPORT bool
1698rw_enable (int (*fun) (int, const char*, int, const char*, ...), bool enable)
1699{
1700 diag_t diag;
1701
1702 if (&rw_fatal == fun)
1703 diag = diag_fatal;
1704 else if (&rw_error == fun)
1705 diag = diag_error;
1706 else if (&rw_assert == fun)
1707 diag = diag_assert;
1708 else if (&rw_warn == fun)
1709 diag = diag_warn;
1710 else if (&rw_note == fun)
1711 diag = diag_note;
1712 else if (&rw_info == fun)
1713 diag = diag_info;
1714 else {
1715 RW_ASSERT (!"Invalid function in rw_enable");
1716 return false;
1717 }
1718
1719 const bool enabled = 0 == (_rw_diag_ignore & (1 << diag));
1720
1721 // if (enable)
1722 // _rw_diag_ignore &= ~(1 << diag);
1723 // else
1724 // _rw_diag_ignore |= 1 << diag;
1725 _rw_diag_ignore ^= ((enable - 1) ^ _rw_diag_ignore) & (1 << diag);
1726
1727 return enabled;
1728}
#define i
Definition 17.names.cpp:126
#define nchars
Definition 17.names.cpp:502
#define q
Definition 17.names.cpp:133
#define fun
Definition 17.names.cpp:471
#define line
Definition 17.names.cpp:490
#define f
Definition 17.names.cpp:119
#define buf
Definition 17.names.cpp:452
volatile int result
void testfun(std::ios_base::event ev, std::ios_base &iosobj, int index)
const int end
#define _RWSTD_PATH_SEP
Definition _config.h:297
#define _RWSTD_DLLIMPORT
Definition _config.h:391
#define setjmp
Definition _csetjmp.h:52
#define va_end(ignore)
#define va_start(va, name)
#define stdout
#define FILE
#define _RWSTD_UNUSED(arg)
Definition _defs.h:972
#define _LIBC_THROWS()
Definition _defs.h:1152
#define _RWSTD_CONST_CAST(T, x)
Definition _defs.h:536
const char * name
Definition codecvt1.cpp:72
_TEST_EXPORT int rw_assert(int success, const char *file, int line, const char *fmt,...)
Definition driver.cpp:1630
_TEST_EXPORT int rw_error(int success, const char *file, int line, const char *fmt,...)
Definition driver.cpp:1613
_TEST_EXPORT int rw_vsetopts(const char *opts, va_list va)
Definition cmdopt.cpp:450
_RWSTD_DLLIMPORT int() fileno(FILE *) _LIBC_THROWS()
_TEST_EXPORT int rw_warn(int success, const char *file, int line, const char *fmt,...)
Definition driver.cpp:1647
_TEST_EXPORT bool rw_enable(int(*fun)(int, const char *, int, const char *,...), bool enable)
Definition driver.cpp:1698
_TEST_EXPORT int rw_fatal(int success, const char *file, int line, const char *fmt,...)
Definition driver.cpp:1596
#define CHECK_INIT(init, func)
Definition driver.cpp:379
_TEST_EXPORT int rw_test(int argc, char **argv, const char *fname, const char *clause, const char *comment, int(*testfun)(int, char **), const char *optstr,...)
Definition driver.cpp:1278
#define RW_TEST_COMPILER
Definition driver.cpp:171
_TEST_EXPORT int rw_note(int success, const char *file, int line, const char *fmt,...)
Definition driver.cpp:1664
_TEST_EXPORT int rw_vtest(int argc, char **argv, const char *file_name, const char *clause, const char *comment, int(*fun)(int, char **), const char *optstr, va_list va)
Definition driver.cpp:1070
#define RLIM_SAVED_CUR
Definition driver.cpp:61
_TEST_EXPORT int rw_info(int success, const char *file, int line, const char *fmt,...)
Definition driver.cpp:1681
#define RLIM_SAVED_MAX
Definition driver.cpp:65
#define RW_TEST_HARDWARE
Definition driver.cpp:330
_TEST_EXPORT int rw_vasnprintf(char **, size_t *, const char *, va_list)
Definition printf.cpp:946
int _rw_setopt_diags(int argc, char *argv[])
esc_text_t diag_msgs[]
Definition opt_diags.cpp:74
diag_t
Definition opt_diags.h:36
@ diag_info
Definition opt_diags.h:38
@ diag_xassert
Definition opt_diags.h:43
@ diag_expect
Definition opt_diags.h:40
@ diag_xwarn
Definition opt_diags.h:41
@ diag_assert
Definition opt_diags.h:44
@ diag_warn
Definition opt_diags.h:42
@ diag_error
Definition opt_diags.h:45
@ diag_note
Definition opt_diags.h:39
@ diag_fatal
Definition opt_diags.h:46
@ N_DIAG_TYPES
Definition opt_diags.h:48
@ diag_trace
Definition opt_diags.h:37
int _rw_setopts_lines()
int _rw_expected(int line)
int _rw_diag_mask
Definition opt_trace.cpp:41
int _rw_setopt_trace_mask(int argc, char *argv[])
Definition opt_trace.cpp:48
int _rw_setopt_trace(int argc, char *argv[])
int _rw_diag_ignore
Definition opt_trace.cpp:44
int _rw_setopts_types()
Definition opt_types.cpp:96
_TEST_EXPORT int rw_setopts(const char *optspec,...)
Definition cmdopt.cpp:652
_TEST_EXPORT int rw_runopts(int argc, char *argv[])
Definition cmdopt.cpp:875
_TEST_EXPORT rw_file *const rw_stderr
Definition printf.cpp:3348
_TEST_EXPORT char * rw_sprintfa(const char *fmt,...)
Definition printf.cpp:3258
_TEST_EXPORT int rw_fprintf(rw_file *, const char *,...)
Definition printf.cpp:3397
_TEST_EXPORT rw_file *const rw_stdout
Definition printf.cpp:3345
#define _TEST_EXPORT
Definition rw_testdefs.h:55
#define RW_ASSERT(expr)
char esc_pfx[40]
Definition opt_diags.h:54
char desc[80]
Definition opt_diags.h:57
char esc_sfx[40]
Definition opt_diags.h:55
char code[16]
Definition opt_diags.h:56
int arg
Definition locale.cpp:2806