os/ossrv/stdcpp/tsrc/Stdcpp_test/stdcxx/testengine/src/driver.cpp
author sl
Tue, 10 Jun 2014 14:32:02 +0200
changeset 1 260cb5ec6c19
permissions -rw-r--r--
Update contrib.
sl@0
     1
/************************************************************************
sl@0
     2
 *
sl@0
     3
 * driver.cpp - definitions of the test driver
sl@0
     4
 *
sl@0
     5
 * $Id: driver.cpp 290009 2005-09-18 23:28:26Z sebor $
sl@0
     6
 *
sl@0
     7
 ************************************************************************
sl@0
     8
 *
sl@0
     9
 * Copyright (c) 1994-2005 Quovadx,  Inc., acting through its  Rogue Wave
sl@0
    10
 * Software division. Licensed under the Apache License, Version 2.0 (the
sl@0
    11
 * "License");  you may  not use this file except  in compliance with the
sl@0
    12
 * License.    You    may   obtain   a   copy   of    the   License    at
sl@0
    13
 * http://www.apache.org/licenses/LICENSE-2.0.    Unless   required    by
sl@0
    14
 * applicable law  or agreed to  in writing,  software  distributed under
sl@0
    15
 * the License is distributed on an "AS IS" BASIS,  WITHOUT WARRANTIES OR
sl@0
    16
 * CONDITIONS OF  ANY KIND, either  express or implied.  See  the License
sl@0
    17
 * for the specific language governing permissions  and limitations under
sl@0
    18
 * the License.
sl@0
    19
 *
sl@0
    20
 **************************************************************************/
sl@0
    21
sl@0
    22
// expand _TEST_EXPORT macros
sl@0
    23
#define _RWSTD_TEST_SRC
sl@0
    24
sl@0
    25
#include "opt_diags.h"
sl@0
    26
#include "opt_lines.h"
sl@0
    27
#include "opt_trace.h"
sl@0
    28
#include "opt_types.h"
sl@0
    29
sl@0
    30
#include <cmdopt.h>    // for rw_setopts()
sl@0
    31
#include <printf.h>    // for rw_snprintfa()
sl@0
    32
sl@0
    33
#include <assert.h>    // for assert
sl@0
    34
#include <setjmp.h>    // for longjmp, setjmp, ...
sl@0
    35
#include <stdarg.h>    // for va_list
sl@0
    36
#include <stdio.h>     // for fileno, fprintf
sl@0
    37
#include <stdlib.h>    // for free
sl@0
    38
#include <string.h>    // for strchr, strcpy
sl@0
    39
#include"std_log_result.h"
sl@0
    40
#define LOG_FILENAME_LINE __FILE__, __LINE__
sl@0
    41
#if !defined (_WIN32) && !defined (_WIN64)
sl@0
    42
#  include <unistd.h>    // for isatty
sl@0
    43
sl@0
    44
// declare fileno in case it's not declared (for strict ANSI conformance)
sl@0
    45
extern "C" {
sl@0
    46
sl@0
    47
IMPORT_C int (fileno)(FILE*) _LIBC_THROWS ();
sl@0
    48
sl@0
    49
}   // extern "C"
sl@0
    50
sl@0
    51
#else
sl@0
    52
   // no isatty on Windoze
sl@0
    53
#  define _RWSTD_NO_ISATTY
sl@0
    54
#endif   // _WIN{32,64}
sl@0
    55
sl@0
    56
// expand _TEST_EXPORT macros
sl@0
    57
#define _RWSTD_TEST_SRC
sl@0
    58
#include <driver.h>
sl@0
    59
sl@0
    60
/************************************************************************/
sl@0
    61
sl@0
    62
#define RW_TEST_STRSTR(x)   #x
sl@0
    63
#define RW_TEST_STR(x)      RW_TEST_STRSTR(x)
sl@0
    64
sl@0
    65
#ifndef RW_TEST_COMPILER
sl@0
    66
#  if defined (__DECCXX__)
sl@0
    67
#    define RW_TEST_COMPILER "Compaq C++, __DECCXX__ = " \
sl@0
    68
            RW_TEST_STR (__DECCXX__)
sl@0
    69
#  elif defined (__INTEL_COMPILER)
sl@0
    70
#    if defined (__EDG_VERSION__)
sl@0
    71
#      define RW_TEST_ICC_EDG_VER \
sl@0
    72
              ", __EDG_VERSION__ = "  RW_TEST_STR (__EDG_VERSION__)
sl@0
    73
#    else
sl@0
    74
#      define RW_TEST_ICC_EDG_VER ""
sl@0
    75
#    endif
sl@0
    76
#    if defined (_MSC_VER)
sl@0
    77
#      define RW_TEST_COMPILER "Intel C++, __INTEL_COMPILER = " \
sl@0
    78
              RW_TEST_STR (__INTEL_COMPILER) ", _MSC_VER = " \
sl@0
    79
              RW_TEST_STR (_MSC_VER) \
sl@0
    80
              RW_TEST_ICC_EDG_VER
sl@0
    81
#    elif defined (__INTEL_COMPILER_BUILD_DATE)
sl@0
    82
#      define RW_TEST_COMPILER "Intel C++, __INTEL_COMPILER = " \
sl@0
    83
              RW_TEST_STR (__INTEL_COMPILER) \
sl@0
    84
              ", __INTEL_COMPILER_BUILD_DATE = " \
sl@0
    85
              RW_TEST_STR (__INTEL_COMPILER_BUILD_DATE) \
sl@0
    86
              RW_TEST_ICC_EDG_VER
sl@0
    87
#    else
sl@0
    88
#      define RW_TEST_COMPILER "Intel C++, __INTEL_COMPILER = " \
sl@0
    89
              RW_TEST_STR (__INTEL_COMPILER) \
sl@0
    90
              RW_TEST_ICC_EDG_VER
sl@0
    91
#    endif
sl@0
    92
#  elif defined (__GNUC__)
sl@0
    93
#    if defined (__VERSION__)
sl@0
    94
#      define RW_TEST_GCC_VER ", __VERSION__ = \"" __VERSION__ "\""
sl@0
    95
#    else
sl@0
    96
#      define RW_TEST_GCC_VER ""
sl@0
    97
#    endif
sl@0
    98
#    if defined (__GNUC_PATCHLEVEL__)
sl@0
    99
#      define RW_TEST_COMPILER "gcc "            \
sl@0
   100
              RW_TEST_STR (__GNUC__) "."         \
sl@0
   101
              RW_TEST_STR (__GNUC_MINOR__) "."   \
sl@0
   102
              RW_TEST_STR (__GNUC_PATCHLEVEL__)  \
sl@0
   103
              RW_TEST_GCC_VER
sl@0
   104
#    else
sl@0
   105
#      define RW_TEST_COMPILER "gcc " \
sl@0
   106
              RW_TEST_STR (__GNUC__) "." RW_TEST_STR (__GNUC_MINOR__) 
sl@0
   107
              RW_TEST_GCC_VER
sl@0
   108
#    endif
sl@0
   109
#  elif defined (_COMPILER_VERSION) && defined (__sgi)
sl@0
   110
#    define RW_TEST_COMPILER "SGI MIPSpro, _COMPILER_VERSION = " \
sl@0
   111
            RW_TEST_STR (_COMPILER_VERSION)
sl@0
   112
#  elif defined (__INTEL_COMPILER)
sl@0
   113
#    if defined (_MSC_VER)
sl@0
   114
#      define RW_TEST_COMPILER "Intel C++, __INTEL_COMPILER = " \
sl@0
   115
              RW_TEST_STR (__INTEL_COMPILER) ", _MSC_VER = " \
sl@0
   116
              RW_TEST_STR (_MSC_VER)
sl@0
   117
#    else
sl@0
   118
#      define RW_TEST_COMPILER "Intel C++, __INTEL_COMPILER = " \
sl@0
   119
              RW_TEST_STR (__INTEL_COMPILER)
sl@0
   120
#    endif
sl@0
   121
#  elif defined (__EDG__)
sl@0
   122
#    define RW_TEST_COMPILER "EDG eccp, __EDG_VERSION__ = " \
sl@0
   123
            RW_TEST_STR (__EDG_VERSION__)
sl@0
   124
#  elif defined (__HP_aCC)
sl@0
   125
#    define RW_TEST_COMPILER "HP aCC, __HP_aCC = " \
sl@0
   126
            RW_TEST_STR (__HP_aCC)
sl@0
   127
#  elif defined (__IBMCPP__)
sl@0
   128
#    define RW_TEST_COMPILER "IBM VisualAge C++, __IBMCPP__ = " \
sl@0
   129
            RW_TEST_STR (__IBMCPP__)
sl@0
   130
#  elif defined (_MSC_VER)
sl@0
   131
#    define RW_TEST_COMPILER "MSVC, _MSC_VER = " \
sl@0
   132
            RW_TEST_STR (_MSC_VER)
sl@0
   133
#  elif defined (__SUNPRO_CC)
sl@0
   134
#    define RW_TEST_COMPILER "SunPro, __SUNPRO_CC = " \
sl@0
   135
            RW_TEST_STR (__SUNPRO_CC)
sl@0
   136
#  else
sl@0
   137
#    define RW_TEST_COMPILER "unknown"
sl@0
   138
#  endif
sl@0
   139
#endif
sl@0
   140
sl@0
   141
#ifndef RW_TEST_LIBSTD
sl@0
   142
#  ifdef _RWSTD_VER
sl@0
   143
#    define RW_TEST_LIBSTD "Rogue Wave C++ Standard Library, " \
sl@0
   144
            "_RWSTD_VER = " RW_TEST_STR (_RWSTD_VER)
sl@0
   145
#  elif defined (__GLIBCXX__)
sl@0
   146
#    define RW_TEST_LIBSTD "GNU C++ Standard Library, " \
sl@0
   147
            "__GLIBCXX__ = " \
sl@0
   148
            RW_TEST_STR (__GLIBCXX__)
sl@0
   149
#  elif defined (_STLPORT_VERSION)
sl@0
   150
     // check for STLport before SGI STL since STLport,
sl@0
   151
     // being derived from SGI STL, #defines both macros
sl@0
   152
#    define RW_TEST_LIBSTD "STLport, " \
sl@0
   153
            "_STLPORT_VERSION = " \
sl@0
   154
            RW_TEST_STR (_STLPORT_VERSION)
sl@0
   155
#  elif defined (__SGI_STL)
sl@0
   156
#    define RW_TEST_LIBSTD "SGI STL, " \
sl@0
   157
            "__SGI_STL = " \
sl@0
   158
            RW_TEST_STR (__SGI_STL)
sl@0
   159
#  elif defined (_YVALS)
sl@0
   160
     // is there a better way to identify the Dinkumware
sl@0
   161
     // implementation? does it have a version macro?
sl@0
   162
#    define RW_TEST_LIBSTD "Dinkum C++ Standard Library"
sl@0
   163
#  endif
sl@0
   164
#endif   // RW_TEST_LIBSTD
sl@0
   165
sl@0
   166
#ifndef RW_TEST_HARDWARE
sl@0
   167
#  if defined (__alpha__) || defined (__alpha)
sl@0
   168
#    define RW_TEST_ARCH "alpha"
sl@0
   169
#  elif defined (__amd64__) || defined (__amd64)
sl@0
   170
#    if defined (__LP64__) || defined (_LP64)
sl@0
   171
#      define RW_TEST_ARCH "amd64/LP64"
sl@0
   172
#    else
sl@0
   173
#      define RW_TEST_ARCH "amd64/ILP32"
sl@0
   174
#    endif
sl@0
   175
#  elif defined (_PA_RISC2_0)
sl@0
   176
#    define RW_TEST_ARCH "pa-risc 2.0"
sl@0
   177
#  elif defined (_PA_RISC1_0)
sl@0
   178
#    define RW_TEST_ARCH "pa-risc 1.0"
sl@0
   179
#  elif defined (__hppa)
sl@0
   180
#    define RW_TEST_ARCH "pa-risc"
sl@0
   181
#  elif defined (__pentiumpro__) || defined (__pentiumpro)
sl@0
   182
#    define RW_TEST_ARCH "pentiumpro"
sl@0
   183
#  elif defined (__pentium__) || defined (__pentium)
sl@0
   184
#    define RW_TEST_ARCH "pentium"
sl@0
   185
#  elif defined (__i486__) || defined (__i486)
sl@0
   186
#    define RW_TEST_ARCH "i486"
sl@0
   187
#  elif defined (__i386__) || defined (__i386)
sl@0
   188
#    define RW_TEST_ARCH "i386"
sl@0
   189
#  elif defined (__i586__) || defined (__i586)
sl@0
   190
#    define RW_TEST_ARCH "i586"
sl@0
   191
#  elif defined (__ia64)
sl@0
   192
#    define RW_TEST_ARCH "ia64"
sl@0
   193
#  elif defined (__mips)
sl@0
   194
#    define RW_TEST_ARCH "mips"
sl@0
   195
#  elif defined (__sparcv9)
sl@0
   196
#    define RW_TEST_ARCH "sparc-v9"
sl@0
   197
#  elif defined (__sparcv8)
sl@0
   198
#    define RW_TEST_ARCH "sparc-v8"
sl@0
   199
#  elif defined (__sparc)
sl@0
   200
#    define RW_TEST_ARCH "sparc"
sl@0
   201
#  elif defined (_POWER)
sl@0
   202
#    if defined (_ARCH_PWR5)
sl@0
   203
#      define RW_TEST_ARCH "power-5"
sl@0
   204
#    elif defined (_ARCH_PWR4)
sl@0
   205
#      define RW_TEST_ARCH "power-4"
sl@0
   206
#    elif defined (_ARCH_PWR3)
sl@0
   207
#      define RW_TEST_ARCH "power-3"
sl@0
   208
#    elif defined (_ARCH_604)
sl@0
   209
#      define RW_TEST_ARCH "powerpc-604"
sl@0
   210
#    elif defined (_ARCH_603)
sl@0
   211
#      define RW_TEST_ARCH "powerpc-603"
sl@0
   212
#    elif defined (_ARCH_602)
sl@0
   213
#      define RW_TEST_ARCH "powerpc-602"
sl@0
   214
#    elif defined (_ARCH_601)
sl@0
   215
#      define RW_TEST_ARCH "powerpc-601"
sl@0
   216
#    elif defined (_ARCH_403)
sl@0
   217
#      define RW_TEST_ARCH "powerpc-403"
sl@0
   218
#    elif defined (_ARCH_PPC64)
sl@0
   219
#      define RW_TEST_ARCH "powerpc/LP64"
sl@0
   220
#    else
sl@0
   221
#      define RW_TEST_ARCH "powerpc"
sl@0
   222
#    endif
sl@0
   223
#  elif defined (_WIN64)
sl@0
   224
#    define RW_TEST_ARCH "ia64"
sl@0
   225
#  elif defined (_WIN32)
sl@0
   226
#    define RW_TEST_ARCH "i86"
sl@0
   227
#  elif defined (__x86_64__) || defined (__x86_64)
sl@0
   228
#    if defined (__LP64__) || defined (_LP64)
sl@0
   229
#      define RW_TEST_ARCH "x86_64/LP64"
sl@0
   230
#    else
sl@0
   231
#      define RW_TEST_ARCH "x86_64/ILP32"
sl@0
   232
#    endif
sl@0
   233
#  else
sl@0
   234
#    define RW_TEST_ARCH "unknown"
sl@0
   235
#  endif
sl@0
   236
sl@0
   237
sl@0
   238
#  if defined (_AIX54)
sl@0
   239
#    define RW_TEST_OS "aix-5.4 (or better)"
sl@0
   240
#  elif defined (_AIX53)
sl@0
   241
#    define RW_TEST_OS "aix-5.3"
sl@0
   242
#  elif defined (_AIX52)
sl@0
   243
#    define RW_TEST_OS "aix-5.2"
sl@0
   244
#  elif defined (_AIX51)
sl@0
   245
#    define RW_TEST_OS "aix-5.1"
sl@0
   246
#  elif defined (_AIX50)
sl@0
   247
#    define RW_TEST_OS "aix-5.0"
sl@0
   248
#  elif defined (_AIX43)
sl@0
   249
#    define RW_TEST_OS "aix-4.3"
sl@0
   250
#  elif defined (_AIX41)
sl@0
   251
#    define RW_TEST_OS "aix-4.1"
sl@0
   252
#  elif defined (_AIX32)
sl@0
   253
#    define RW_TEST_OS "aix-3.2"
sl@0
   254
#  elif defined (_AIX)
sl@0
   255
#    define RW_TEST_OS "aix"
sl@0
   256
#  elif defined (__hpux)
sl@0
   257
#    define RW_TEST_OS "hp-ux"
sl@0
   258
#  elif defined (__osf__)
sl@0
   259
#    define RW_TEST_OS "tru64-unix"
sl@0
   260
#  elif defined (__sgi) && defined (__mips)
sl@0
   261
#    define RW_TEST_OS "irix"
sl@0
   262
#  elif defined (__linux__) || defined (__linux)
sl@0
   263
sl@0
   264
     // get Linux release string (UTS_RELEASE)
sl@0
   265
#    include <linux/version.h>
sl@0
   266
sl@0
   267
#    ifndef UTS_RELEASE
sl@0
   268
#      define UTS_RELEASE "(unknown release)"
sl@0
   269
#    endif   // UTS_RELEASE
sl@0
   270
sl@0
   271
#    if defined (__ELF__)
sl@0
   272
#      define LINUX_TYPE "linux-elf"
sl@0
   273
#    else
sl@0
   274
#      define LINUX_TYPE "linux"
sl@0
   275
#    endif
sl@0
   276
sl@0
   277
#    define RW_TEST_OS LINUX_TYPE " "     \
sl@0
   278
            UTS_RELEASE " with glibc "    \
sl@0
   279
            RW_TEST_STR (__GLIBC__) "."   \
sl@0
   280
            RW_TEST_STR (__GLIBC_MINOR__)
sl@0
   281
sl@0
   282
#  elif defined (__SunOS_5_10)
sl@0
   283
#    define RW_TEST_OS "sunos-5.10"
sl@0
   284
#  elif defined (__SunOS_5_9)
sl@0
   285
#    define RW_TEST_OS "sunos-5.9"
sl@0
   286
#  elif defined (__SunOS_5_8)
sl@0
   287
#    define RW_TEST_OS "sunos-5.8"
sl@0
   288
#  elif defined (__SunOS_5_7)
sl@0
   289
#    define RW_TEST_OS "sunos-5.7"
sl@0
   290
#  elif defined (__SunOS_5_6)
sl@0
   291
#    define RW_TEST_OS "sunos-5.6"
sl@0
   292
#  elif defined (__sun__)
sl@0
   293
#    define RW_TEST_OS "sunos"
sl@0
   294
#  elif defined (_WIN64)
sl@0
   295
#    define RW_TEST_OS "win64"
sl@0
   296
#  elif defined (_WIN32)
sl@0
   297
#    define RW_TEST_OS "win32"
sl@0
   298
#  else
sl@0
   299
#    define RW_TEST_OS "unknown"
sl@0
   300
#  endif
sl@0
   301
sl@0
   302
#  define RW_TEST_HARDWARE RW_TEST_ARCH " running " RW_TEST_OS
sl@0
   303
#else
sl@0
   304
#  define RW_TEST_HARDWARE "unknown"
sl@0
   305
#endif
sl@0
   306
sl@0
   307
/************************************************************************/
sl@0
   308
sl@0
   309
// defined in printf.cpp but not declared in printf.h
sl@0
   310
_TEST_EXPORT int
sl@0
   311
rw_vasnprintf (char**, size_t*, const char*, va_list);
sl@0
   312
sl@0
   313
/************************************************************************/
sl@0
   314
sl@0
   315
// array to store the number of each type of diagnostic
sl@0
   316
static int
sl@0
   317
ndiags [N_DIAG_TYPES][2] /* = { { total, active }, ... }*/;
sl@0
   318
sl@0
   319
static FILE *ftestout;
sl@0
   320
sl@0
   321
static jmp_buf test_env;
sl@0
   322
sl@0
   323
// set to 1 after the driver has been initialized
sl@0
   324
static int driver_initialized = 0;
sl@0
   325
sl@0
   326
// set to 1 after the driver has finished running
sl@0
   327
static int driver_finished = 0;
sl@0
   328
sl@0
   329
#if 0   // disabled
sl@0
   330
// %S: severity
sl@0
   331
// %M: diagnostic
sl@0
   332
// %m: diagnostic if not empty
sl@0
   333
// %F: file name
sl@0
   334
// %f: file name if not empty
sl@0
   335
// %C: clause
sl@0
   336
// %c: clause if not empty
sl@0
   337
// %L: line number
sl@0
   338
// %l: line number if valid
sl@0
   339
// %T: text
sl@0
   340
// %t: text if not empty
sl@0
   341
static char diag_pattern [80];
sl@0
   342
#endif
sl@0
   343
sl@0
   344
// option: use CSV format (comma separated values)
sl@0
   345
static int _rw_opt_csv = 0;
sl@0
   346
sl@0
   347
static char clause_id [80];
sl@0
   348
sl@0
   349
/************************************************************************/
sl@0
   350
sl@0
   351
#define CHECK_INIT(init, func)   _rw_check_init (init, __LINE__, func)
sl@0
   352
sl@0
   353
static inline void
sl@0
   354
_rw_check_init (bool init, int line, const char *func)
sl@0
   355
{
sl@0
   356
    if (init && !driver_initialized) {
sl@0
   357
        fprintf (stderr, "%s:%d: %s: test driver already initialized\n",
sl@0
   358
                 __FILE__, line, func);
sl@0
   359
     std_log(LOG_FILENAME_LINE,"%s:%d: %s: test driver already initialized\n",
sl@0
   360
                 __FILE__, line, func);                 
sl@0
   361
        abort ();
sl@0
   362
    }
sl@0
   363
sl@0
   364
    if (!init && driver_initialized) {
sl@0
   365
        fprintf (stderr, "%s:%d: %s: test driver not initialized yet\n",
sl@0
   366
                 __FILE__, line, func);
sl@0
   367
      std_log(LOG_FILENAME_LINE,"%s:%d: %s: test driver not initialized yet\n",
sl@0
   368
                 __FILE__, line, func);                  
sl@0
   369
        abort ();
sl@0
   370
    }
sl@0
   371
sl@0
   372
    if (driver_finished) {
sl@0
   373
        fprintf (stderr, "%s:%d: %s: test finished, cannot call\n",
sl@0
   374
                 __FILE__, line, func);
sl@0
   375
     std_log(LOG_FILENAME_LINE,"%s:%d: %s: test finished, cannot call\n",
sl@0
   376
                 __FILE__, line, func);                 
sl@0
   377
    }
sl@0
   378
}
sl@0
   379
sl@0
   380
/************************************************************************/
sl@0
   381
sl@0
   382
static int
sl@0
   383
_rw_opt_brief (int argc, char *argv[])
sl@0
   384
{
sl@0
   385
    static int opt_brief;
sl@0
   386
sl@0
   387
    if (0 == argc) {
sl@0
   388
        // query mode: return the value of the option
sl@0
   389
        return opt_brief;
sl@0
   390
    }
sl@0
   391
sl@0
   392
    if (1 == argc && argv && 0 == argv [0]) {
sl@0
   393
        // help mode: set argv[0] to the text of the help message
sl@0
   394
sl@0
   395
        static const char helpstr[] = {
sl@0
   396
            "Enables brief mode.\n"
sl@0
   397
        };
sl@0
   398
sl@0
   399
        argv [0] = _RWSTD_CONST_CAST (char*, helpstr);
sl@0
   400
sl@0
   401
        return 0;
sl@0
   402
    }
sl@0
   403
sl@0
   404
    // set mode: enable the option
sl@0
   405
    opt_brief = 1;
sl@0
   406
sl@0
   407
    return 0;
sl@0
   408
}
sl@0
   409
sl@0
   410
/************************************************************************/
sl@0
   411
sl@0
   412
static int
sl@0
   413
_rw_opt_quiet (int argc, char *argv[])
sl@0
   414
{
sl@0
   415
    static int opt_quiet;
sl@0
   416
sl@0
   417
    if (0 == argc) {
sl@0
   418
        // query mode: return the value of the option
sl@0
   419
        return opt_quiet;
sl@0
   420
    }
sl@0
   421
sl@0
   422
    if (1 == argc && argv && 0 == argv [0]) {
sl@0
   423
        // help mode: set argv[0] to the text of the help message
sl@0
   424
sl@0
   425
        static const char helpstr[] = {
sl@0
   426
            "Enables quiet mode.\n"
sl@0
   427
            "In quiet mode only diagnostics with severity 7 and above are "
sl@0
   428
            "issued."
sl@0
   429
        };
sl@0
   430
sl@0
   431
        argv [0] = _RWSTD_CONST_CAST (char*, helpstr);
sl@0
   432
sl@0
   433
        return 0;
sl@0
   434
    }
sl@0
   435
sl@0
   436
    // set mode: enable the option
sl@0
   437
    _rw_diag_mask = ~((1 << 7) | (1 << 8) | (1 << 9));
sl@0
   438
    opt_quiet     = 1;
sl@0
   439
sl@0
   440
    return 0;
sl@0
   441
}
sl@0
   442
sl@0
   443
/************************************************************************/
sl@0
   444
sl@0
   445
static int
sl@0
   446
_rw_opt_verbose (int argc, char *argv[])
sl@0
   447
{
sl@0
   448
    static int opt_verbose;
sl@0
   449
sl@0
   450
    if (0 == argc) {
sl@0
   451
        // query mode: return the value of the option
sl@0
   452
        return opt_verbose;
sl@0
   453
    }
sl@0
   454
sl@0
   455
    if (1 == argc && argv && 0 == argv [0]) {
sl@0
   456
        // help mode: set argv[0] to the text of the help message
sl@0
   457
sl@0
   458
        static const char helpstr[] = {
sl@0
   459
            "Enables verbose mode.\n"
sl@0
   460
        };
sl@0
   461
sl@0
   462
        argv [0] = _RWSTD_CONST_CAST (char*, helpstr);
sl@0
   463
sl@0
   464
        return 0;
sl@0
   465
    }
sl@0
   466
sl@0
   467
    // set mode: enable the option
sl@0
   468
    opt_verbose = 1;
sl@0
   469
sl@0
   470
    return 0;
sl@0
   471
}
sl@0
   472
sl@0
   473
/************************************************************************/
sl@0
   474
sl@0
   475
static int
sl@0
   476
_rw_setopt_csv (int argc, char *argv[])
sl@0
   477
{
sl@0
   478
    if (1 == argc && argv && 0 == argv [0]) {
sl@0
   479
        static const char helpstr[] = {
sl@0
   480
            "Enables CSV (comma separated values) mode.\n"
sl@0
   481
        };
sl@0
   482
sl@0
   483
        argv [0] = _RWSTD_CONST_CAST (char*, helpstr);
sl@0
   484
sl@0
   485
        return 0;
sl@0
   486
    }
sl@0
   487
sl@0
   488
    _rw_opt_csv = 1;
sl@0
   489
    return 0;
sl@0
   490
}
sl@0
   491
sl@0
   492
/************************************************************************/
sl@0
   493
sl@0
   494
static int
sl@0
   495
_rw_opt_compat (int argc, char *argv[])
sl@0
   496
{
sl@0
   497
    static int opt_compat;
sl@0
   498
sl@0
   499
    if (0 == argc) {
sl@0
   500
        // query mode: return the value of the option
sl@0
   501
        return opt_compat;
sl@0
   502
    }
sl@0
   503
sl@0
   504
    if (1 == argc && argv && 0 == argv [0]) {
sl@0
   505
        // help mode: set argv[0] to the text of the help message
sl@0
   506
sl@0
   507
        static const char helpstr[] = {
sl@0
   508
            "Enables RWTest-format compatibility mode.\n"
sl@0
   509
        };
sl@0
   510
sl@0
   511
        argv [0] = _RWSTD_CONST_CAST (char*, helpstr);
sl@0
   512
sl@0
   513
        return 0;
sl@0
   514
    }
sl@0
   515
sl@0
   516
    // set mode: enable the option
sl@0
   517
    opt_compat = 1;
sl@0
   518
sl@0
   519
    return 0;
sl@0
   520
}
sl@0
   521
sl@0
   522
/************************************************************************/
sl@0
   523
sl@0
   524
static int
sl@0
   525
_rw_opt_no_stdout (int argc, char *argv[])
sl@0
   526
{
sl@0
   527
    static int opt_no_stdout;
sl@0
   528
sl@0
   529
    if (0 == argc) {
sl@0
   530
        // query mode: return the value of the option
sl@0
   531
        return opt_no_stdout;
sl@0
   532
    }
sl@0
   533
sl@0
   534
    if (1 == argc && argv && 0 == argv [0]) {
sl@0
   535
        // help mode: set argv[0] to the text of the help message
sl@0
   536
sl@0
   537
        static const char helpstr[] = {
sl@0
   538
            "Prevents the program from using stdandard output for diagnostic\n"
sl@0
   539
            "messages. Instead, the driver will create a log file with a name\n"
sl@0
   540
            "obtained from the from the basename of the program source file,\n"
sl@0
   541
            "usually obtained by passing the value of the __FILE__ macro to\n"
sl@0
   542
            "the driver, with the .out extension. If successful, the driver\n"
sl@0
   543
            "will write all diagnostic messages issued by the program to this\n"
sl@0
   544
            "file. Otherwise, the driver exits with an error.\n"
sl@0
   545
        };
sl@0
   546
sl@0
   547
        argv [0] = _RWSTD_CONST_CAST (char*, helpstr);
sl@0
   548
sl@0
   549
        return 0;
sl@0
   550
    }
sl@0
   551
    
sl@0
   552
    // set mode: enable the option
sl@0
   553
    opt_no_stdout = 1;
sl@0
   554
sl@0
   555
    return 0;
sl@0
   556
}
sl@0
   557
sl@0
   558
/************************************************************************/
sl@0
   559
sl@0
   560
static int
sl@0
   561
_rw_setopt_output_file (int argc, char *argv[])
sl@0
   562
{
sl@0
   563
    if (1 == argc && argv && 0 == argv [0]) {
sl@0
   564
        static const char helpstr[] = {
sl@0
   565
            "Specifies the name of the output file to be used by the program\n"
sl@0
   566
            "for diagnostic messages. Unless this option is specified, the\n"
sl@0
   567
            "program will issue all diagnostic messages to the standard output."
sl@0
   568
            "\nDriver diagnostics are always directed to stderr.\n"
sl@0
   569
        };
sl@0
   570
sl@0
   571
        argv [0] = _RWSTD_CONST_CAST (char*, helpstr);
sl@0
   572
sl@0
   573
        return 0;
sl@0
   574
    }
sl@0
   575
sl@0
   576
    const char *file_name = 0;
sl@0
   577
sl@0
   578
    if ('-' == argv [0][0] && 'O' == argv [0][1] || 'o' == argv [0][1]) {
sl@0
   579
        file_name = argv [0] + 2;
sl@0
   580
    }
sl@0
   581
    else if (1 < argc && '-' != argv [1][0]) {
sl@0
   582
        file_name = argv [1];
sl@0
   583
    }
sl@0
   584
sl@0
   585
    if (file_name) {
sl@0
   586
sl@0
   587
        FILE* const f = fopen (file_name, "w");
sl@0
   588
sl@0
   589
        if (f) {
sl@0
   590
            if (ftestout && ftestout != stderr)
sl@0
   591
                fclose (ftestout);
sl@0
   592
sl@0
   593
            ftestout = f;
sl@0
   594
        }
sl@0
   595
    }
sl@0
   596
sl@0
   597
    // return 0 on success, any non-zero value on failure
sl@0
   598
    return !(ftestout != 0);
sl@0
   599
}
sl@0
   600
sl@0
   601
/************************************************************************/
sl@0
   602
sl@0
   603
_TEST_EXPORT int
sl@0
   604
rw_vsetopts (const char *opts, va_list va);
sl@0
   605
sl@0
   606
/************************************************************************/
sl@0
   607
sl@0
   608
static int
sl@0
   609
_rw_use_color ()
sl@0
   610
{
sl@0
   611
#ifndef _RWSTD_NO_ISATTY
sl@0
   612
sl@0
   613
    // is output sent to a terminal?
sl@0
   614
    // if so, assume a vt100 compatible terminal for now
sl@0
   615
    static const int tty = isatty (fileno (ftestout));
sl@0
   616
sl@0
   617
#else   // if defined (_RWSTD_NO_ISATTY)
sl@0
   618
sl@0
   619
    // FIXME: deal with a missing isatty() and Windows
sl@0
   620
    static const int tty = 0;
sl@0
   621
sl@0
   622
#endif   // _RWSTD_NO_ISATTY
sl@0
   623
sl@0
   624
    return 0 != tty;
sl@0
   625
}
sl@0
   626
sl@0
   627
/************************************************************************/
sl@0
   628
sl@0
   629
_TEST_EXPORT int
sl@0
   630
rw_vtest (int argc, char **argv,
sl@0
   631
          const char *file_name,
sl@0
   632
          const char *clause,
sl@0
   633
          const char *comment,
sl@0
   634
          int (*fun)(int, char**),
sl@0
   635
          const char *optstr,
sl@0
   636
          va_list     va)
sl@0
   637
{
sl@0
   638
    CHECK_INIT (false, "rw_vtest()");
sl@0
   639
sl@0
   640
    driver_initialized = 1;
sl@0
   641
sl@0
   642
    if (optstr && 0 > rw_vsetopts (optstr, va)) {
sl@0
   643
        fprintf (stderr, "%s:%d: rw_setopts() failed\n", __FILE__, __LINE__);
sl@0
   644
        std_log(LOG_FILENAME_LINE,"%s:%d: rw_setopts() failed\n", __FILE__, __LINE__);
sl@0
   645
        return 1;
sl@0
   646
    }
sl@0
   647
sl@0
   648
    const int nopts =
sl@0
   649
        rw_setopts ("|-no-stdout "
sl@0
   650
                    "|-diags= "      // argument required
sl@0
   651
                    "|-trace "
sl@0
   652
                    "|-severity= "   // argument required
sl@0
   653
                    "|-csv "
sl@0
   654
                    "|-compat "
sl@0
   655
                    "o|-output:"     // argument optional
sl@0
   656
                    "b|-brief "
sl@0
   657
                    "q|-quiet "
sl@0
   658
                    "v|-verbose",
sl@0
   659
                    _rw_opt_no_stdout,
sl@0
   660
                    _rw_setopt_diags,
sl@0
   661
                    _rw_setopt_trace,
sl@0
   662
                    _rw_setopt_trace_mask,
sl@0
   663
                    _rw_setopt_csv,
sl@0
   664
                    _rw_opt_compat,
sl@0
   665
                    _rw_setopt_output_file,
sl@0
   666
                    _rw_opt_brief,
sl@0
   667
                    _rw_opt_quiet,
sl@0
   668
                    _rw_opt_verbose,
sl@0
   669
                    0);
sl@0
   670
sl@0
   671
    if (3 > nopts) {
sl@0
   672
        fprintf (stderr, "%s:%d: rw_setopts() failed\n", __FILE__, __LINE__);
sl@0
   673
        std_log(LOG_FILENAME_LINE,"%s:%d: rw_setopts() failed\n", __FILE__, __LINE__);
sl@0
   674
        abort ();
sl@0
   675
        return 1;
sl@0
   676
    }
sl@0
   677
sl@0
   678
#ifndef _RWSTD_USE_CONFIG
sl@0
   679
sl@0
   680
    // enable RWTest-format compatibility mode
sl@0
   681
    _rw_opt_compat (1, 0);
sl@0
   682
sl@0
   683
    // disable output to stdout
sl@0
   684
    _rw_opt_no_stdout (1, 0);
sl@0
   685
sl@0
   686
#endif   // _RWSTD_USE_CONFIG
sl@0
   687
sl@0
   688
    _rw_setopts_types ();
sl@0
   689
sl@0
   690
    _rw_setopts_lines ();
sl@0
   691
sl@0
   692
    int status = rw_runopts (argc, argv);
sl@0
   693
sl@0
   694
    if (status)
sl@0
   695
        return status;
sl@0
   696
sl@0
   697
    if (0 == ftestout) {
sl@0
   698
sl@0
   699
        if (_rw_opt_no_stdout (0, 0) && file_name) {
sl@0
   700
            char fname [256] = "C:\\";
sl@0
   701
            
sl@0
   702
            char* temp_ret = strchr (file_name, '/');
sl@0
   703
            
sl@0
   704
            if(temp_ret != NULL)
sl@0
   705
            {    
sl@0
   706
             const char* const slash = strrchr (file_name, '/');
sl@0
   707
sl@0
   708
             strcat (fname, slash ? slash + 1 : file_name);
sl@0
   709
            }
sl@0
   710
            else
sl@0
   711
            {    
sl@0
   712
             const char* const slash = strrchr (file_name, _RWSTD_PATH_SEP);
sl@0
   713
sl@0
   714
             strcat (fname, slash ? slash + 1 : file_name);
sl@0
   715
            }
sl@0
   716
            
sl@0
   717
            char* const dot = strchr (fname, '.');
sl@0
   718
            if (dot)
sl@0
   719
                strcpy (dot, ".out");
sl@0
   720
            else
sl@0
   721
                strcat (fname, ".out");
sl@0
   722
sl@0
   723
            ftestout = fopen (fname, "w");
sl@0
   724
        }
sl@0
   725
        else
sl@0
   726
            ftestout = stdout;
sl@0
   727
    }
sl@0
   728
sl@0
   729
    if (clause)
sl@0
   730
        strcpy (clause_id, clause);
sl@0
   731
sl@0
   732
    const char begin_fmt[] = {
sl@0
   733
        "\n"
sl@0
   734
        "# COMPILER: %s\n"
sl@0
   735
        "# ENVIRONMENT: %s\n"
sl@0
   736
        "# FILE: %s\n"
sl@0
   737
        "# COMPILED: %s, %s\n"
sl@0
   738
        "# COMMENT: %s\n"
sl@0
   739
        "######################################################"
sl@0
   740
    };
sl@0
   741
sl@0
   742
    const char* const fname = strrchr (file_name, _RWSTD_PATH_SEP);
sl@0
   743
sl@0
   744
    rw_info (0, 0, 0,
sl@0
   745
             begin_fmt,
sl@0
   746
             RW_TEST_COMPILER, RW_TEST_HARDWARE,
sl@0
   747
             fname ? fname + 1 : file_name,
sl@0
   748
             __DATE__, __TIME__,
sl@0
   749
             comment ? comment : "");
sl@0
   750
sl@0
   751
    status = setjmp (test_env);
sl@0
   752
sl@0
   753
    if (0 == status) {
sl@0
   754
        // environment set, execute the callback function
sl@0
   755
        status = fun (argc, argv);
sl@0
   756
    }
sl@0
   757
    else {
sl@0
   758
        // fatal test error (via a call to rw_fatal())
sl@0
   759
    }
sl@0
   760
sl@0
   761
    driver_finished = 1;
sl@0
   762
sl@0
   763
    static const char tblrow[] =
sl@0
   764
        "+-----------------------+--------+--------+--------+";
sl@0
   765
sl@0
   766
    fprintf (ftestout,
sl@0
   767
             "# %s\n"
sl@0
   768
             "# | DIAGNOSTIC            | ACTIVE |  TOTAL |INACTIVE|\n"
sl@0
   769
             "# %s\n",
sl@0
   770
             tblrow, tblrow);
sl@0
   771
sl@0
   772
    int nlines = 0;
sl@0
   773
sl@0
   774
    for (int i = 0; i != N_DIAG_TYPES; ++i) {
sl@0
   775
        if (ndiags [i][0] || !(_rw_diag_mask & (1 << diag_trace))) {
sl@0
   776
sl@0
   777
            // print out details for any non-zero totals
sl@0
   778
            // or for all totals when debugging or tracing
sl@0
   779
            // is enabled
sl@0
   780
sl@0
   781
            ++nlines;
sl@0
   782
sl@0
   783
            const long num = (ndiags [i][0] - ndiags [i][1]) * 100L;
sl@0
   784
            const long den = ndiags [i][0];
sl@0
   785
sl@0
   786
            const long pct = den ? num / den : 0;
sl@0
   787
sl@0
   788
            const char* pfx = "";
sl@0
   789
            const char* sfx = "";
sl@0
   790
sl@0
   791
            static int use_color = _rw_use_color ();
sl@0
   792
sl@0
   793
            if (use_color) {
sl@0
   794
                pfx = ndiags [i][1] ? diag_msgs [i].esc_pfx : "";
sl@0
   795
                sfx = ndiags [i][1] ? diag_msgs [i].esc_sfx : "";
sl@0
   796
            }
sl@0
   797
sl@0
   798
            fprintf (ftestout,
sl@0
   799
                     "# | (S%d) %-*s |%s %6d %s| %6d | %5ld%% |\n",
sl@0
   800
                     i, int (sizeof diag_msgs [i].code), diag_msgs [i].code,
sl@0
   801
                     pfx, ndiags [i][1], sfx, ndiags [i][0], pct);
sl@0
   802
        }
sl@0
   803
    }
sl@0
   804
sl@0
   805
    if (0 == nlines)
sl@0
   806
        fprintf (ftestout, "# no diagnostics\n");
sl@0
   807
sl@0
   808
    fprintf (ftestout, "# %s\n", tblrow);
sl@0
   809
sl@0
   810
    if (_rw_opt_compat (0, 0)) {
sl@0
   811
sl@0
   812
        // TO DO: get rid of this
sl@0
   813
sl@0
   814
        // RWTest compatibility format
sl@0
   815
sl@0
   816
        fprintf (ftestout,
sl@0
   817
                 "######################################################\n"
sl@0
   818
                 "## Warnings = %d\n"
sl@0
   819
                 "## Assertions = %d\n"
sl@0
   820
                 "## FailedAssertions = %d\n",
sl@0
   821
                 ndiags [diag_warn][1] + ndiags [diag_xwarn][1],
sl@0
   822
                 ndiags [diag_assert][0],
sl@0
   823
                 ndiags [diag_assert][1] + ndiags [diag_xassert][1]);
sl@0
   824
    }
sl@0
   825
sl@0
   826
    fclose (ftestout);
sl@0
   827
    ftestout = 0;
sl@0
   828
sl@0
   829
    return status;
sl@0
   830
}
sl@0
   831
sl@0
   832
/************************************************************************/
sl@0
   833
sl@0
   834
_TEST_EXPORT int
sl@0
   835
rw_test (int argc, char **argv,
sl@0
   836
         const char *fname,
sl@0
   837
         const char *clause,
sl@0
   838
         const char *comment,
sl@0
   839
         int (*testfun)(int, char**),
sl@0
   840
         const char *optstr,
sl@0
   841
         ...)
sl@0
   842
{
sl@0
   843
    CHECK_INIT (false, "rw_test()");
sl@0
   844
sl@0
   845
    va_list va;
sl@0
   846
    va_start (va, optstr);
sl@0
   847
sl@0
   848
    const int status =
sl@0
   849
        rw_vtest (argc, argv, fname, clause, comment, testfun, optstr, va);
sl@0
   850
sl@0
   851
    va_end (va);
sl@0
   852
sl@0
   853
    return status;
sl@0
   854
}
sl@0
   855
sl@0
   856
/************************************************************************/
sl@0
   857
sl@0
   858
// escape every occurrence of the double quote character in the string
sl@0
   859
// pointed to by buf by prepending to it the escape character specified
sl@0
   860
// by the last acrgument
sl@0
   861
// returns the new buffer if the size of the existing buffer isn't
sl@0
   862
// sufficient and sets *pbufsize to the size of the newly allocated
sl@0
   863
// buffer, otherwise the original value of buf and leaves *pbufsize
sl@0
   864
// unchanged
sl@0
   865
static char*
sl@0
   866
_rw_escape (char *buf, size_t bufsize, char esc)
sl@0
   867
{
sl@0
   868
    // handle null buffer
sl@0
   869
    if (0 == buf)
sl@0
   870
        return buf;
sl@0
   871
sl@0
   872
    // count the number of embedded quotes
sl@0
   873
    char *quote = buf;
sl@0
   874
    size_t nquotes = 0;
sl@0
   875
    
sl@0
   876
    #ifdef __ARMCC__
sl@0
   877
    #pragma diag_suppress 1293
sl@0
   878
    #endif
sl@0
   879
    while ((quote = strchr (quote, '"'))) {
sl@0
   880
        ++nquotes;
sl@0
   881
        ++quote;
sl@0
   882
    }
sl@0
   883
    
sl@0
   884
sl@0
   885
    // no quotes found, return the original buffer
sl@0
   886
    if (0 == nquotes)
sl@0
   887
        return buf;
sl@0
   888
sl@0
   889
    // conpute the size of the buffer that will be needed to escape
sl@0
   890
    // all the double quotes
sl@0
   891
    size_t newbufsize = strlen (buf) + nquotes + 1;
sl@0
   892
sl@0
   893
    char *newbuf = 0;
sl@0
   894
sl@0
   895
    if (0 /* newbufsize <= bufsize */) {
sl@0
   896
        // FIXME: escape embedded quotes in place w/o reallocation
sl@0
   897
        _RWSTD_UNUSED (bufsize);
sl@0
   898
    }
sl@0
   899
    else {
sl@0
   900
        newbuf = (char*)malloc (newbufsize);
sl@0
   901
        if (0 == newbuf) {
sl@0
   902
            return 0;
sl@0
   903
        }
sl@0
   904
sl@0
   905
        // set the next pointer to the beginning of the new buffer
sl@0
   906
        // as the destination where to copy the string argument
sl@0
   907
        char *next = newbuf;
sl@0
   908
sl@0
   909
        // set quote to initially point to the beginning of
sl@0
   910
        // the source buffer and then just past the last quote
sl@0
   911
        quote = buf;
sl@0
   912
sl@0
   913
        for (char *q = buf; ; ++q) {
sl@0
   914
sl@0
   915
            // look for the next (or first) quote
sl@0
   916
            q = strchr (q, '"');
sl@0
   917
sl@0
   918
            // compute the number of characters, excluding the quote
sl@0
   919
            // to copy to the destination buffer
sl@0
   920
            const size_t nchars = q ? size_t (q - quote) : strlen (quote);
sl@0
   921
sl@0
   922
            memcpy (next, quote, nchars);
sl@0
   923
sl@0
   924
            if (q) {
sl@0
   925
                // append the escape character to the destination buffer
sl@0
   926
                next [nchars] = esc;
sl@0
   927
sl@0
   928
                // append the quote from the source string
sl@0
   929
                next [nchars + 1] = '"';
sl@0
   930
sl@0
   931
                // advance the destination pointer past the quote
sl@0
   932
                next += nchars + 2;
sl@0
   933
sl@0
   934
                // advance the source pointer past the embedded quote
sl@0
   935
                quote = q + 1;
sl@0
   936
            }
sl@0
   937
            else {
sl@0
   938
                // NUL-terminate the destination buffer
sl@0
   939
                *next = '\0';
sl@0
   940
                break;
sl@0
   941
            }
sl@0
   942
        }
sl@0
   943
    }
sl@0
   944
sl@0
   945
    return newbuf;
sl@0
   946
}
sl@0
   947
sl@0
   948
/************************************************************************/
sl@0
   949
sl@0
   950
static void
sl@0
   951
_rw_vissue_diag (diag_t diag, int severity, const char *file, int line,
sl@0
   952
                 const char *fmt, va_list va)
sl@0
   953
{
sl@0
   954
    CHECK_INIT (true, "_rw_vissue_diag()");
sl@0
   955
sl@0
   956
    if (0 == fmt)
sl@0
   957
        fmt = "";
sl@0
   958
sl@0
   959
    static char fmterr[] = "*** formatting error ***";
sl@0
   960
sl@0
   961
    char *usrbuf = 0;
sl@0
   962
    const int nchars = rw_vasnprintf (&usrbuf, 0, fmt, va);
sl@0
   963
sl@0
   964
    if (nchars < 0 || 0 == usrbuf)
sl@0
   965
        usrbuf = fmterr;
sl@0
   966
sl@0
   967
    // compute the number of newline characters in the text
sl@0
   968
    int nlines = 0;
sl@0
   969
    
sl@0
   970
    #ifdef __ARMCC__
sl@0
   971
    #pragma diag_suppress 1293
sl@0
   972
    #endif
sl@0
   973
    for (const char *nl = usrbuf; (nl = strchr (nl, '\n')); ++nl)
sl@0
   974
        ++nlines;
sl@0
   975
    
sl@0
   976
sl@0
   977
    static const int use_color = _rw_use_color ();
sl@0
   978
sl@0
   979
    const char* const diagstr[] = {
sl@0
   980
        use_color ? diag_msgs [severity].esc_pfx : "",
sl@0
   981
        *diag_msgs [severity].code ? diag_msgs [severity].code : "UNKNOWN",
sl@0
   982
        use_color  ? diag_msgs [severity].esc_sfx : "",
sl@0
   983
        _rw_opt_verbose (0, 0) && *diag_msgs [severity].desc ?
sl@0
   984
        diag_msgs [severity].desc : 0
sl@0
   985
    };
sl@0
   986
sl@0
   987
    const char* const traced_diag =
sl@0
   988
        0 == severity && diag_msgs [diag].code ? diag_msgs [diag].code : 0;
sl@0
   989
sl@0
   990
    const char* const slash = file ? strrchr (file, _RWSTD_PATH_SEP) : 0;
sl@0
   991
    if (slash)
sl@0
   992
        file = slash + 1;
sl@0
   993
sl@0
   994
    char *mybuf = 0;
sl@0
   995
sl@0
   996
    if (_rw_opt_csv) {
sl@0
   997
sl@0
   998
        // format all fields as comma separated values (CSV):
sl@0
   999
        // -- a field containing the quote character, the comma,
sl@0
  1000
        //    or the newline or linefeed character must be enclosed
sl@0
  1001
        //    in a pair of double quotes
sl@0
  1002
        // -- every occurrence of the double quote character in a field
sl@0
  1003
        //    must be escaped by prepening another double quote character
sl@0
  1004
        //    to it
sl@0
  1005
sl@0
  1006
        // escape all double quotes by prepending the double
sl@0
  1007
        // quote character to each according to the CSV format
sl@0
  1008
        char* const newbuf = _rw_escape (usrbuf, 0, '"');
sl@0
  1009
        if (newbuf != usrbuf) {
sl@0
  1010
            free (usrbuf);
sl@0
  1011
            usrbuf = newbuf;
sl@0
  1012
        }
sl@0
  1013
sl@0
  1014
        mybuf =
sl@0
  1015
            rw_sprintfa ("%d, "                      // severity
sl@0
  1016
                         "\"%s%s"                    // diagnostic
sl@0
  1017
                         "%{?}_%s%{;}%s\", "         // traced diagnostic
sl@0
  1018
                         "\"%s\", "                  // clause
sl@0
  1019
                         "\"%s\", "                  // file
sl@0
  1020
                         "%d, "                      // line
sl@0
  1021
                         "\"%s\"",                   // user text
sl@0
  1022
                         severity,
sl@0
  1023
                         diagstr [0], diagstr [1],
sl@0
  1024
                         0 != traced_diag, traced_diag, diagstr [2],
sl@0
  1025
                         clause_id,
sl@0
  1026
                         0 != file ? file : "",
sl@0
  1027
                         line,
sl@0
  1028
                         usrbuf);
sl@0
  1029
    }
sl@0
  1030
    else {
sl@0
  1031
sl@0
  1032
        nlines += 2 + ('\0' != *clause_id) + (0 != file) + (0 < line);
sl@0
  1033
sl@0
  1034
        mybuf =
sl@0
  1035
            rw_sprintfa ("# %s"                      // escape prefix
sl@0
  1036
                         "%s"                        // diagnostic
sl@0
  1037
                         "%{?}_%s%{;}"               // traced diagnostic
sl@0
  1038
                         "%s "                       // escape suffix
sl@0
  1039
                         "(S%d)"                     // severity
sl@0
  1040
                         "%{?}, %s%{;} "             // description
sl@0
  1041
                         "(%d lines):\n"             // number of lines
sl@0
  1042
                         "# TEXT: %s\n"              // user text
sl@0
  1043
                         "%{?}# CLAUSE: %s\n%{;}"    // clause if not empty
sl@0
  1044
                         "%{?}# FILE: %s\n%{;}"      // file if not null
sl@0
  1045
                         "%{?}# LINE: %d\n%{;}",     // line if positive
sl@0
  1046
                         diagstr [0],
sl@0
  1047
                         diagstr [1],
sl@0
  1048
                         0 != traced_diag, traced_diag,
sl@0
  1049
                         diagstr [2],
sl@0
  1050
                         severity,
sl@0
  1051
                         0 != diagstr [3], diagstr [3],
sl@0
  1052
                         nlines,
sl@0
  1053
                         usrbuf,
sl@0
  1054
                         '\0' != *clause_id, clause_id,
sl@0
  1055
                         0 != file, file,
sl@0
  1056
                         0 < line, line);
sl@0
  1057
    }
sl@0
  1058
#if 0   // disabled
sl@0
  1059
    else {
sl@0
  1060
sl@0
  1061
        mybuf =
sl@0
  1062
            rw_sprintfa ("# %s%s"                 // diagnostic
sl@0
  1063
                         "%{?}_%s%{;}%s "         // traced diagnostic
sl@0
  1064
                         "(S%d): "                // severity
sl@0
  1065
                         "%{?}[%s] %{;}"          // clause if not empty
sl@0
  1066
                         "%{?}(%d lines): %{;}"   // number of lines if > 1
sl@0
  1067
                         "%{?}%s:"                // if (file) then file
sl@0
  1068
                         "%{?}%d:%{;} "           //   if (0 < line) line
sl@0
  1069
                         "%{:}"                   // else
sl@0
  1070
                         "%{?}line %d: %{;}"      //   if (0 < line) line
sl@0
  1071
                         "%{;}"                   // endif
sl@0
  1072
                         "%s",                    // user text
sl@0
  1073
                         diagstr [0], diagstr [1],
sl@0
  1074
                         0 != traced_diag, traced_diag, diagstr [2],
sl@0
  1075
                         severity,
sl@0
  1076
                         '\0' != *clause_id, clause_id,
sl@0
  1077
                         1 < nlines, nlines,
sl@0
  1078
                         0 != file, file,
sl@0
  1079
                         0 < line, line,
sl@0
  1080
                         0 < line, line,
sl@0
  1081
                         usrbuf);
sl@0
  1082
    }
sl@0
  1083
#endif   // 0/1
sl@0
  1084
sl@0
  1085
    fprintf (ftestout, "%s\n", mybuf);
sl@0
  1086
sl@0
  1087
    if (mybuf != fmterr)
sl@0
  1088
        free (mybuf);
sl@0
  1089
sl@0
  1090
    if (usrbuf != fmterr)
sl@0
  1091
        free (usrbuf);
sl@0
  1092
}
sl@0
  1093
sl@0
  1094
/************************************************************************/
sl@0
  1095
sl@0
  1096
static void
sl@0
  1097
_rw_vdiag (diag_t diag, int severity, const char *file, int line,
sl@0
  1098
           const char *fmt, va_list va)
sl@0
  1099
{
sl@0
  1100
    CHECK_INIT (true, "_rw_vdiag()");
sl@0
  1101
sl@0
  1102
    // check if the diagnostic is expected
sl@0
  1103
    const int expected = 0 != _rw_expected (line);
sl@0
  1104
sl@0
  1105
    if (expected) {
sl@0
  1106
        if (severity) {
sl@0
  1107
            // if the diagnostic is expected to be active,
sl@0
  1108
            // adjust its type and severity
sl@0
  1109
            if (diag_assert == diag)
sl@0
  1110
                diag = diag_xassert;
sl@0
  1111
            else if (diag_warn == diag)
sl@0
  1112
                diag = diag_xwarn;
sl@0
  1113
sl@0
  1114
            severity = diag * severity;
sl@0
  1115
        }
sl@0
  1116
        else {
sl@0
  1117
            // if the diagnostic is expected to be active but isn't,
sl@0
  1118
            // adjust its type to an unexpectdly inactive one
sl@0
  1119
            if (diag_assert == diag || diag_warn == diag)
sl@0
  1120
                diag = diag_expect;
sl@0
  1121
sl@0
  1122
            severity = diag;
sl@0
  1123
        }
sl@0
  1124
    }
sl@0
  1125
    else if (diag) {
sl@0
  1126
        // normalize the severity
sl@0
  1127
        severity = diag * severity;
sl@0
  1128
    }
sl@0
  1129
sl@0
  1130
    if (severity < 0)
sl@0
  1131
        severity = 0;
sl@0
  1132
    else if (N_DIAG_TYPES <= severity)
sl@0
  1133
        severity = N_DIAG_TYPES - 1;
sl@0
  1134
sl@0
  1135
    // increment the diagnostic counter
sl@0
  1136
    ++ndiags [diag][0];
sl@0
  1137
sl@0
  1138
    if (severity) {
sl@0
  1139
sl@0
  1140
        ++ndiags [diag][1];
sl@0
  1141
    }
sl@0
  1142
sl@0
  1143
    const int sevbit = (1 << severity);
sl@0
  1144
sl@0
  1145
    if (0 == (sevbit & _rw_diag_mask)) {
sl@0
  1146
        // issue the diagnostic
sl@0
  1147
        _rw_vissue_diag (diag, severity, file, line, fmt, va);
sl@0
  1148
    }
sl@0
  1149
sl@0
  1150
    if (diag_fatal == diag && severity) {
sl@0
  1151
        // fatal error, terminate test
sl@0
  1152
        longjmp (test_env, severity);
sl@0
  1153
    }
sl@0
  1154
}
sl@0
  1155
sl@0
  1156
/************************************************************************/
sl@0
  1157
sl@0
  1158
_TEST_EXPORT int
sl@0
  1159
rw_fatal (int success, const char *file, int line, const char *fmt, ...)
sl@0
  1160
{
sl@0
  1161
    CHECK_INIT (true, "rw_fatal()");
sl@0
  1162
sl@0
  1163
    va_list va;
sl@0
  1164
    va_start (va, fmt);
sl@0
  1165
sl@0
  1166
    _rw_vdiag (diag_fatal, 0 == success, file, line, fmt, va);
sl@0
  1167
sl@0
  1168
    va_end (va);
sl@0
  1169
sl@0
  1170
    return success;
sl@0
  1171
}
sl@0
  1172
sl@0
  1173
/************************************************************************/
sl@0
  1174
sl@0
  1175
_TEST_EXPORT int
sl@0
  1176
rw_error (int success, const char *file, int line, const char *fmt, ...)
sl@0
  1177
{
sl@0
  1178
    CHECK_INIT (true, "rw_error()");
sl@0
  1179
sl@0
  1180
    va_list va;
sl@0
  1181
    va_start (va, fmt);
sl@0
  1182
sl@0
  1183
    _rw_vdiag (diag_error, 0 == success, file, line, fmt, va);
sl@0
  1184
sl@0
  1185
    va_end (va);
sl@0
  1186
sl@0
  1187
    return success;
sl@0
  1188
}
sl@0
  1189
sl@0
  1190
/************************************************************************/
sl@0
  1191
sl@0
  1192
_TEST_EXPORT int
sl@0
  1193
rw_assert (int success, const char *file, int line, const char *fmt, ...)
sl@0
  1194
{
sl@0
  1195
    CHECK_INIT (true, "rw_assert()");
sl@0
  1196
sl@0
  1197
    va_list va;
sl@0
  1198
    va_start (va, fmt);
sl@0
  1199
sl@0
  1200
    _rw_vdiag (diag_assert, 0 == success, file, line, fmt, va);
sl@0
  1201
sl@0
  1202
    va_end (va);
sl@0
  1203
sl@0
  1204
    return success;
sl@0
  1205
}
sl@0
  1206
sl@0
  1207
/************************************************************************/
sl@0
  1208
sl@0
  1209
_TEST_EXPORT int
sl@0
  1210
rw_warn (int success, const char *file, int line, const char *fmt, ...)
sl@0
  1211
{
sl@0
  1212
    CHECK_INIT (true, "rw_warn()");
sl@0
  1213
sl@0
  1214
    va_list va;
sl@0
  1215
    va_start (va, fmt);
sl@0
  1216
sl@0
  1217
    _rw_vdiag (diag_warn, 0 == success, file, line, fmt, va);
sl@0
  1218
sl@0
  1219
    va_end (va);
sl@0
  1220
sl@0
  1221
    return success;
sl@0
  1222
}
sl@0
  1223
sl@0
  1224
/************************************************************************/
sl@0
  1225
sl@0
  1226
_TEST_EXPORT int
sl@0
  1227
rw_note (int success, const char *file, int line, const char *fmt, ...)
sl@0
  1228
{
sl@0
  1229
    CHECK_INIT (true, "rw_note()");
sl@0
  1230
sl@0
  1231
    va_list va;
sl@0
  1232
    va_start (va, fmt);
sl@0
  1233
sl@0
  1234
    _rw_vdiag (diag_note, 0 == success, file, line, fmt, va);
sl@0
  1235
sl@0
  1236
    va_end (va);
sl@0
  1237
sl@0
  1238
    return success;
sl@0
  1239
}
sl@0
  1240
sl@0
  1241
/************************************************************************/
sl@0
  1242
sl@0
  1243
_TEST_EXPORT int
sl@0
  1244
rw_info (int success, const char *file, int line, const char *fmt, ...)
sl@0
  1245
{
sl@0
  1246
    CHECK_INIT (true, "rw_info()");
sl@0
  1247
sl@0
  1248
    va_list va;
sl@0
  1249
    va_start (va, fmt);
sl@0
  1250
sl@0
  1251
    _rw_vdiag (diag_info, 0 == success, file, line, fmt, va);
sl@0
  1252
sl@0
  1253
    va_end (va);
sl@0
  1254
sl@0
  1255
    return success;
sl@0
  1256
}