@@@ fltfmt mess
[mLib] / test / tvec.h
index 3c7884c..2ddaf61 100644 (file)
 #include <stdio.h>
 #include <string.h>
 
-#ifndef MLIB_BUF_H
-#  include "buf.h"
+#ifndef MLIB_ARENA_H
+#  include "arena.h"
 #endif
 
-#ifndef MLIB_CONTROL_H
-#  include "control.h"
+#ifndef MLIB_BUF_H
+#  include "buf.h"
 #endif
 
-#ifndef MLIB_BUF_H
+#ifndef MLIB_DSTR_H
 #  include "dstr.h"
 #endif
 
 #  include "gprintf.h"
 #endif
 
-#ifndef MLIB_LBUF_H
-#  include "lbuf.h"
-#endif
-
 #ifndef MLIB_MACROS_H
 #  include "macros.h"
 #endif
@@ -441,10 +437,11 @@ struct tvec_test {
   const struct tvec_env *env;          /* environment to run test in */
   tvec_testfn *fn;                     /* test function */
 };
-#define TVEC_ENDTESTS { 0, 0, 0, 0 }
 
 /*----- Test state --------------------------------------------------------*/
 
+struct tvec_output;
+
 enum {
   /* Possible test outcomes. */
 
@@ -458,7 +455,7 @@ enum {
 struct tvec_config {
   /* An overall test configuration. */
 
-  const struct tvec_test *tests;       /* the tests to be performed */
+  const struct tvec_test *const *tests;        /* the tests to be performed */
   unsigned nrout, nreg;                        /* number of output/total regs */
   size_t regsz;                                /* size of a register */
 };
@@ -477,6 +474,9 @@ struct tvec_state {
 #define TVSF_XFAIL 0x0100u             /*   test expected to fail */
 #define TVSF_MUFFLE 0x0200u            /*   muffle errors */
 
+  /* Memory allocation.  Read-only for all callers. */
+  arena *a;
+
   /* Test configuration.  Read-only for all callers. */
   struct tvec_config cfg;              /* test configuration */
 
@@ -492,12 +492,16 @@ struct tvec_state {
   /* Test scoreboard.  Available to output formatters. */
   unsigned curr[TVOUT_LIMIT], all[TVOUT_LIMIT], grps[TVOUT_LIMIT];
 
-  /* Output machinery. */
+  /* Output machinery.  Read-only for environments. */
   struct tvec_output *output;          /* output formatter */
 
   /* Input machinery.  Available to type parsers. */
   const char *infile; unsigned lno, test_lno; /* input file name, line */
   FILE *fp;                            /* input file stream */
+
+  /* Adhoc testing state.  Private. */
+  struct tvec_test adhoc_test;
+  const struct tvec_test *adhoc_tests[];
 };
 
 /* @TVEC_REG(tv, vec, i)@
@@ -508,141 +512,6 @@ struct tvec_state {
  */
 #define TVEC_REG(tv, vec, i) TVEC_GREG((tv)->vec, (i), (tv)->cfg.regsz)
 
-/*----- Output formatting -------------------------------------------------*/
-
-struct tvec_output {
-  /* An output formatter. */
-  const struct tvec_outops *ops;       /* pointer to operations */
-};
-
-enum {
-  /* Register output dispositions. */
-
-  TVRD_INPUT,                          /* input-only register */
-  TVRD_OUTPUT,                         /* output-only (input is dead) */
-  TVRD_MATCH,                          /* matching (equal) registers */
-  TVRD_FOUND,                          /* mismatching output register */
-  TVRD_EXPECT,                         /* mismatching input register */
-  TVRD_LIMIT                           /* (number of dispositions) */
-};
-
-#define TVEC_LEVELS(_)                                                 \
-       _(NOTE, "notice", 4)                                            \
-       _(ERR, "ERROR", 8)
-enum {
-#define TVEC_DEFLEVEL(tag, name, val) TVLEV_##tag = val,
-  TVEC_LEVELS(TVEC_DEFLEVEL)
-#undef TVEC_DEFLEVEL
-  TVLEV_LIMIT
-};
-
-/* Benchmarking details. */
-enum {
-  TVBU_OP,                            /* counting operations of some kind */
-  TVBU_BYTE,                           /* counting bytes (@rbuf >= 0@) */
-  TVBU_LIMIT                           /* (number of units) */
-};
-struct bench_timing;    /* include <mLib/bench.h> for the real definition */
-
-struct tvec_outops {
-  /* Output operations. */
-
-  void (*bsession)(struct tvec_output */*o*/, struct tvec_state */*tv*/);
-    /* Begin a test session.  The output driver will probably want to
-     * save @tv@, because this isn't provided to any other methods.
-     */
-
-  int (*esession)(struct tvec_output */*o*/);
-    /* End a session, and return the suggested exit code. */
-
-  void (*bgroup)(struct tvec_output */*o*/);
-    /* Begin a test group.  The test group description is @tv->test@. */
-
-  void (*skipgroup)(struct tvec_output */*o*/,
-                   const char */*excuse*/, va_list */*ap*/);
-    /* The group is being skipped; @excuse@ may be null or a format
-     * string explaining why.  The @egroup@ method will not be called
-     * separately.
-     */
-
-  void (*egroup)(struct tvec_output */*o*/);
-    /* End a test group.  At least one test was attempted or @skipgroup@
-     * would have been called instead.  If @tv->curr[TVOUT_LOSE]@ is nonzero
-     * then the test group as a whole failed; otherwise it passed.
-     */
-
-  void (*btest)(struct tvec_output */*o*/);
-    /* Begin a test case. */
-
-  void (*skip)(struct tvec_output */*o*/,
-              const char */*excuse*/, va_list */*ap*/);
-    /* The test case is being skipped; @excuse@ may be null or a format
-     * string explaining why.  The @etest@ function will still be called (so
-     * this works differently from @skipgroup@ and @egroup@).  A test case
-     * can be skipped at most once, and, if skipped, it cannot fail.
-     */
-
-  void (*fail)(struct tvec_output */*o*/,
-              const char */*detail*/, va_list */*ap*/);
-    /* The test case failed.
-     *
-     * The output driver should preferably report the filename (@infile@) and
-     * line number (@test_lno@, not @lno@) for the failing test.
-     *
-     * The @detail@ may be null or a format string describing detail about
-     * how the failing test was run which can't be determined from the
-     * registers; a @detail@ is usually provided when (and only when) the
-     * test environment potentially invokes the test function more than once.
-     *
-     * A single test case can fail multiple times!
-     */
-
-  void (*dumpreg)(struct tvec_output */*o*/,
-                 unsigned /*disp*/, const union tvec_regval */*rv*/,
-                 const struct tvec_regdef */*rd*/);
-    /* Dump a register.  The `disposition' @disp@ explains what condition the
-     * register is in; see @tvec_dumpreg@ and the @TVRD_...@ codes.  The
-     * register value is at @rv@, and its definition, including its type, at
-     * @rd@.  Note that this function may be called on virtual registers
-     * which aren't in either of the register vectors or mentioned by the
-     * test description.  It may also be called with @rv@ null, indicating
-     * that the register is not live.
-     */
-
-  void (*etest)(struct tvec_output */*o*/, unsigned /*outcome*/);
-    /* The test case concluded with the given @outcome@ (one of the
-     * @TVOUT_...@ codes.
-     */
-
-  void (*bbench)(struct tvec_output */*o*/,
-                const char */*ident*/, unsigned /*unit*/);
-    /* Begin a benchmark.  The @ident@ is a formatted string identifying the
-     * benchmark based on the values of the input registered marked
-     * @TVRF_ID@; the output driver is free to use this or come up with its
-     * own way to identify the test, e.g., by inspecting the register values
-     * for itself.  The @unit@ is one of the @TVBU_...@ constants explaining
-     * what sort of thing is being measured.
-     */
-
-  void (*ebench)(struct tvec_output */*o*/,
-                const char */*ident*/, unsigned /*unit*/,
-                const struct bench_timing */*tm*/);
-    /* End a benchmark.  The @ident@ and @unit@ arguments are as for
-     * @bbench@.  If @tm@ is zero then the measurement failed; otherwise
-     * @tm->n@ counts total number of things (operations or bytes, as
-     * indicated by @unit@) processed in the indicated time.
-     */
-
-  void (*report)(struct tvec_output */*o*/, unsigned /*level*/,
-                const char */*msg*/, va_list */*ap*/);
-    /* Report a message.  The driver should ideally report the filename
-     * (@infile@) and line number (@lno@) prompting the error.
-     */
-
-  void (*destroy)(struct tvec_output */*o*/);
-    /* Release any resources acquired by the driver. */
-};
-
 /*----- Session lifecycle -------------------------------------------------*/
 
 /* --- @tvec_begin@ --- *
@@ -692,11 +561,6 @@ extern int tvec_read(struct tvec_state */*tv*/,
 
 /*----- Command-line interface --------------------------------------------*/
 
-extern const struct tvec_config tvec_adhocconfig;
-  /* A special @struct tvec_config@ to use for programs which perform ad-hoc
-   * testing.
-   */
-
 /* --- @tvec_parseargs@ --- *
  *
  * Arguments:  @int argc@ = number of command-line arguments
@@ -955,496 +819,6 @@ extern PRINTF_LIKE(2, 3)
 extern void tvec_check_v(struct tvec_state */*tv*/,
                         const char */*detail*/, va_list */*ap*/);
 
-/*----- Ad-hoc testing ----------------------------------------------------*/
-
-/* --- @tvec_adhoc@ --- *
- *
- * Arguments:  @struct tvec_state *tv@ = test-vector state
- *             @struct tvec_test *t@ = space for a test definition
- *
- * Returns:    ---
- *
- * Use:                Begin ad-hoc testing, i.e., without reading a file of
- *             test-vector data.
- *
- *             The structure at @t@ will be used to record information about
- *             the tests underway, which would normally come from a static
- *             test definition.  The other functions in this section assume
- *             that @tvec_adhoc@ has been called.
- */
-
-extern void tvec_adhoc(struct tvec_state */*tv*/, struct tvec_test */*t*/);
-
-/* --- @tvec_begingroup@, @TVEC_BEGINGROUP@ --- *
- *
- * Arguments:  @struct tvec_state *tv@ = test-vector state
- *             @const char *name@ = name for this test group
- *             @const char *file@, @unsigned @lno@ = calling file and line
- *
- * Returns:    ---
- *
- * Use:                Begin an ad-hoc test group with the given name.  The @file@
- *             and @lno@ can be anything, but it's usually best if they
- *             refer to the source code performing the test: the macro
- *             @TVEC_BEGINGROUP@ does this automatically.
- */
-
-extern void tvec_begingroup(struct tvec_state */*tv*/, const char */*name*/,
-                           const char */*file*/, unsigned /*lno*/);
-#define TVEC_BEGINGROUP(tv, name)                                      \
-       do tvec_begingroup(tv, name, __FILE__, __LINE__); while (0)
-
-/* --- @tvec_endgroup@ --- *
- *
- * Arguments:  @struct tvec_state *tv@ = test-vector state
- *
- * Returns:    ---
- *
- * Use:                End an ad-hoc test group.  The statistics are updated and the
- *             outcome is reported to the output formatter.
- */
-
-extern void tvec_endgroup(struct tvec_state */*tv*/);
-
-/* --- @TVEC_TESTGROUP@, @TVEC_TESTGROUP_TAG@ --- *
- *
- * Arguments:  @tag@ = label-disambiguation tag
- *             @const struct tvec_state *tv = test-vector state
- *             @const char *name@ = test-group name
- *
- * Returns:    ---
- *
- * Use:                Control-structure macro: @TVEC_TESTGROUP(tv, name) stmt@
- *             establishes a test group with the given @name@ (attributing
- *             it to the source file and lie number), executes @stmt@, and
- *             ends the test group.  If @stmt@ invokes @break@ then the test
- *             group is skipped.  @TVEC_TESTGROUP_TAG@ is the same, with an
- *             additional @tag@ argument for use in higher-level macros.
- */
-
-#define TVEC_TESTGROUP_TAG(tag, tv, name)                              \
-       MC_WRAP(tag##__around,                                          \
-         { TVEC_BEGINGROUP(tv, name); },                               \
-         { tvec_endgroup(tv); },                                       \
-         { if (!((tv)->f&TVSF_SKIP)) tvec_skipgroup(tv, 0);            \
-           tvec_endgroup(tv); })
-#define TVEC_TESTGROUP(tv, name) TVEC_TESTGROUP_TAG(grp, tv, name)
-
-/* --- @tvec_begintest@, @TVEC_BEGINTEST@ --- *
- *
- * Arguments:  @struct tvec_state *tv@ = test-vector state
- *             @const char *file@, @unsigned @lno@ = calling file and line
- *
- * Returns:    ---
- *
- * Use:                Begin an ad-hoc test case.  The @file@ and @lno@ can be
- *             anything, but it's usually best if they refer to the source
- *             code performing the test: the macro @TVEC_BEGINGROUP@ does
- *             this automatically.
- */
-
-extern void tvec_begintest(struct tvec_state */*tv*/,
-                          const char */*file*/, unsigned /*lno*/);
-#define TVEC_BEGINTEST(tv)                                             \
-       do tvec_begintest(tv, __FILE__, __LINE__); while (0)
-
-/* --- @tvec_endtest@ --- *
- *
- * Arguments:  @struct tvec_state *tv@ = test-vector state
- *
- * Returns:    ---
- *
- * Use:                End an ad-hoc test case,  The statistics are updated and the
- *             outcome is reported to the output formatter.
- */
-
-extern void tvec_endtest(struct tvec_state */*tv*/);
-
-/* --- @TVEC_TEST@, @TVEC_TEST_TAG@ --- *
- *
- * Arguments:  @tag@ = label-disambiguation tag
- *             @struct tvec_test *t@ = space for a test definition
- *
- * Returns:    ---
- *
- * Use:                Control-structure macro: @TVEC_TEST(tv) stmt@ begins a test
- *             case, executes @stmt@, and ends the test case.  If @stmt@
- *             invokes @break@ then the test case is skipped.
- *             @TVEC_TEST_TAG@ is the same, with an additional @tag@ argumet
- *             for use in higher-level macros.
- */
-
-#define TVEC_TEST_TAG(tag, tv)                                         \
-       MC_WRAP(tag##__around,                                          \
-         { TVEC_BEGINTEST(tv); },                                      \
-         { tvec_endtest(tv); },                                        \
-         { if ((tv)->f&TVSF_ACTIVE) tvec_skip((tv), 0);                \
-           tvec_endtest(tv); })
-#define TVEC_TEST(tv) TVEC_TEST_TAG(test, tv)
-
-/* --- @tvec_claim@, @tvec_claim_v@, @TVEC_CLAIM@ --- *
- *
- * Arguments:  @struct tvec_state *tv@ = test-vector state
- *             @int ok@ = a flag
- *             @const char *file@, @unsigned @lno@ = calling file and line
- *             @const char *msg@, @va_list *ap@ = message to report on
- *                     failure
- *
- * Returns:    The value @ok@.
- *
- * Use:                Check that a claimed condition holds, as (part of) a test.
- *             If no test case is underway (i.e., if @TVSF_OPEN@ is reset in
- *             @tv->f@), then a new test case is begun and ended.  The
- *             @file@ and @lno@ are passed to the output formatter to be
- *             reported in case of a failure.  If @ok@ is nonzero, then
- *             nothing else happens; so, in particular, if @tvec_claim@
- *             established a new test case, then the test case succeeds.  If
- *             @ok@ is zero, then a failure is reported, quoting @msg@.
- *
- *             The @TVEC_CLAIM@ macro is similar, only it (a) identifies the
- *             file and line number of the call site automatically, and (b)
- *             implicitly quotes the source text of the @ok@ condition in
- *             the failure message.
- */
-
-extern PRINTF_LIKE(5, 6)
-  int tvec_claim(struct tvec_state */*tv*/, int /*ok*/,
-                const char */*file*/, unsigned /*lno*/,
-                const char */*msg*/, ...);
-extern int tvec_claim_v(struct tvec_state */*tv*/, int /*ok*/,
-                       const char */*file*/, unsigned /*lno*/,
-                       const char */*msg*/, va_list */*ap*/);
-#define TVEC_CLAIM(tv, cond)                                           \
-       (tvec_claim(tv, !!(cond), __FILE__, __LINE__, "%s untrue", #cond))
-
-/* --- @tvec_claimeq@ --- *
- *
- * Arguments:  @struct tvec_state *tv@ = test-vector state
- *             @const struct tvec_regty *ty@ = register type
- *             @const union tvec_misc *arg@ = register type argument
- *             @const char *file@, @unsigned @lno@ = calling file and line
- *             @const char *expr@ = the expression to quote on failure
- *
- * Returns:    Nonzero if the input and output values of register 0 are
- *             equal, zero if they differ.
- *
- * Use:                Check that the input and output values of register 0 are
- *             equal (according to the register type @ty@).  As for
- *             @tvec_claim@ above, a test case is automatically begun and
- *             ended if none is already underway.  If the values are
- *             unequal, then @tvec_fail@ is called, quoting @expr@, and the
- *             mismatched values are dumped.
- *
- *             This function is not expected to be called directly, but
- *             through type-specific wrapper functions or macros such as
- *             @TVEC_CLAIMEQ_INT@.
- */
-
-extern int tvec_claimeq(struct tvec_state */*tv*/,
-                       const struct tvec_regty */*ty*/,
-                       const union tvec_misc */*arg*/,
-                       const char */*file*/, unsigned /*lno*/,
-                       const char */*expr*/);
-
-/*----- Benchmarking ------------------------------------------------------*/
-
-struct tvec_benchenv {
-  struct tvec_env _env;                        /* benchmarking is an environment */
-  struct bench_state **bst;            /* benchmark state anchor or null */
-  unsigned long niter;                 /* iterations done per unit */
-  int riter, rbuf;                     /* iterations and buffer registers */
-  const struct tvec_env *env;          /* subordinate environment */
-};
-
-struct tvec_benchctx {
-  const struct tvec_benchenv *be;      /* environment configuration */
-  struct bench_state *bst;             /* benchmark state */
-  double dflt_target;                  /* default time in seconds */
-  unsigned f;                          /* flags */
-#define TVBF_SETTRG 1u                 /*   set `@target' */
-#define TVBF_SETMASK (TVBF_SETTRG))    /*   mask of @TVBF_SET...@ */
-  void *subctx;                                /* subsidiary environment context */
-};
-
-extern struct bench_state *tvec_benchstate;
-
-/* --- Environment implementation --- *
- *
- * The following special variables are supported.
- *
- *   * %|@target|% is the (approximate) number of seconds to run the
- *     benchmark.
- *
- * Unrecognized variables are passed to the subordinate environment, if there
- * is one.  Other events are passed through to the subsidiary environment.
- */
-
-extern tvec_envsetupfn tvec_benchsetup;
-extern tvec_envfindvarfn tvec_benchfindvar;
-extern tvec_envbeforefn tvec_benchbefore;
-extern tvec_envrunfn tvec_benchrun;
-extern tvec_envafterfn tvec_benchafter;
-extern tvec_envteardownfn tvec_benchteardown;
-
-#define TVEC_BENCHENV                                                  \
-  { sizeof(struct tvec_benchctx),                                      \
-    tvec_benchsetup,                                                   \
-    tvec_benchfindvar,                                                 \
-    tvec_benchbefore,                                                  \
-    tvec_benchrun,                                                     \
-    tvec_benchafter,                                                   \
-    tvec_benchteardown }
-#define TVEC_BENCHINIT TVEC_BENCHENV, &tvec_benchstate
-
-/* --- @tvec_benchreport@ --- *
- *
- * Arguments:  @const struct gprintf_ops *gops@ = print operations
- *             @void *go@ = print destination
- *             @unsigned unit@ = the unit being measured (~TVBU_...@)
- *             @unsigned style@ = output style (@TVSF_...@)
- *             @const struct bench_timing *tm@ = the benchmark result
- *
- * Returns:    ---
- *
- * Use:                Formats a report about the benchmark performance.  This
- *             function is intended to be called on by an output @ebench@
- *             function.
- */
-
-extern void tvec_benchreport
-  (const struct gprintf_ops */*gops*/, void */*go*/,
-   unsigned /*unit*/, unsigned /*style*/, const struct bench_timing */*tm*/);
-
-/*----- Remote execution --------------------------------------------------*/
-
-struct tvec_remoteenv;
-
-struct tvec_remotecomms {
-  int infd, outfd;                     /* input and output descriptors */
-  dbuf bout;                           /* output buffer */
-  unsigned char *bin;                  /* input buffer */
-  size_t binoff, binlen, binsz;                /* input offset, length, and size */
-  size_t t;                            /* temporary offset */
-  unsigned f;                          /* flags */
-#define TVRF_BROKEN 0x0001u            /*   communications have failed */
-};
-#define TVEC_REMOTECOMMS_INIT { -1, -1, DBUF_INIT, 0, 0, 0, 0, 0, 0 }
-
-struct tvec_remotectx {
-  struct tvec_state *tv;               /* test vector state */
-  struct tvec_remotecomms rc;          /* communication state */
-  const struct tvec_remoteenv *re;     /* environment configuration */
-  void *subctx;                                /* subenvironment context */
-  struct tvec_vardef vd;               /* temporary variable definition */
-  unsigned ver;                                /* protocol version */
-  pid_t kid;                           /* child process id */
-  int errfd;                           /* child stderr descriptor */
-  lbuf errbuf;                         /* child stderr line buffer */
-  dstr prgwant, progress;              /* progress: wanted/reported */
-  unsigned exwant, exit;               /* exit status wanted/reported */
-#define TVRF_RCNMASK 0x0300u           /*   reconnection behaviour: */
-#define TVRCN_DEMAND 0x0000u           /*     connect on demand */
-#define TVRCN_SKIP 0x0100u             /*     skip unless connected */
-#define TVRCN_FORCE 0x0200u            /*     force reconnection */
-#define TVRF_MUFFLE 0x0400u            /*   muffle child stderr */
-#define TVRF_SETEXIT 0x0800u           /*   set `@exit' */
-#define TVRF_SETPRG 0x1000u            /*   set `@progress' */
-#define TVRF_SETRCN 0x2000u            /*   set `@reconnect' */
-#define TVRF_SETMASK (TVRF_SETEXIT | TVRF_SETPRG | TVRF_SETRCN)
-                                       /*   mask of @TVTF_SET...@ */
-};
-
-typedef int tvec_connectfn(pid_t */*kid_out*/, int */*infd_out*/,
-                          int */*outfd_out*/, int */*errfd_out*/,
-                          struct tvec_state */*tv*/,
-                          const struct tvec_remoteenv */*env*/);
-  /* A connection function.  On entry, @tv@ holds the test-vector state, and
-   * @env@ is the test group's remote environment structure, which will
-   * typically really be some subclass of @struct tvec_remoteenv@ containing
-   * additional parameters for establishing the child process.
-   *
-   * On successful completion, the function stores input and output
-   * descriptors (which need not be distinct) in @*infd_out@ and
-   * @*outfd_out@, and returns zero; if it creates a child process, it should
-   * additionally store the child's process-id in @*kid_out@ and store in
-   * @*errfd_out@ a descriptor from which the child's error output can be
-   * read.  On error, the function should report an appropriate message via
-   * @tvec_error@ and return %$-1$%.
-   */
-
-struct tvec_remoteenv_slots {
-  tvec_connectfn *connect;             /* connection function */
-  const struct tvec_env *env;          /* subsidiary environment */
-  unsigned dflt_reconn;                        /* default reconnection */
-};
-
-struct tvec_remoteenv {
-  struct tvec_env _env;
-  struct tvec_remoteenv_slots r;
-};
-
-struct tvec_remotefork_slots {
-  const struct tvec_test *tests;       /* child tests (or null) */
-};
-
-struct tvec_remotefork {
-  struct tvec_env _env;
-  struct tvec_remoteenv_slots r;
-  struct tvec_remotefork_slots f;
-};
-
-struct tvec_remoteexec_slots {
-  const char *const *args;             /* command line to execute */
-};
-
-struct tvec_remoteexec {
-  struct tvec_env _env;
-  struct tvec_remoteenv_slots r;
-  struct tvec_remoteexec_slots x;
-};
-
-union tvec_remoteenv_subclass_kludge {
-  struct tvec_env _env;
-  struct tvec_remoteenv renv;
-  struct tvec_remotefork fork;
-  struct tvec_remoteexec exec;
-};
-
-/* Exit status.
- *
- * We don't use the conventional encoding returned by the @wait@(2) family of
- * system calls because it's too hard for our flags type to decode.  Instead,
- * we use our own encoding.
- *
- * The exit code or signal number ends up in the `value' field in the low 12
- * bits; bit 12 is set if the value field holds a signal, and it if holds an
- * exit code.  Bits 13--15 hold a code which describes the status of a child
- * process or connection.
- */
-#define TVXF_VALMASK 0x0fffu           /* value (exit code or signal) */
-#define TVXF_SIG 0x1000u               /* value is signal, not exit code */
-#define TVXF_CAUSEMASK 0xe000u         /* mask for cause bits */
-#define TVXST_RUN 0x0000u              /*   still running */
-#define TVXST_EXIT 0x2000u             /*   child exited */
-#define TVXST_KILL 0x4000u             /*   child killed by signal */
-#define TVXST_CONT 0x6000u             /*   child continued (?) */
-#define TVXST_STOP 0x8000u             /*   child stopped (?) */
-#define TVXST_DISCONN 0xa000u          /*   disconnected */
-#define TVXST_UNK 0xc000u              /*   unknown */
-#define TVXST_ERR 0xe000u            /*   local error prevented diagnosis */
-
-/* Remote environment. */
-extern tvec_envsetupfn tvec_remotesetup;
-extern tvec_envfindvarfn tvec_remotefindvar;
-extern tvec_envbeforefn tvec_remotebefore;
-extern tvec_envrunfn tvec_remoterun;
-extern tvec_envafterfn tvec_remoteafter;
-extern tvec_envteardownfn tvec_remoteteardown;
-#define TVEC_REMOTEENV                                                 \
-  { sizeof(struct tvec_remotectx),                                     \
-    tvec_remotesetup,                                                  \
-    tvec_remotefindvar,                                                        \
-    tvec_remotebefore,                                                 \
-    tvec_remoterun,                                                    \
-    tvec_remoteafter,                                                  \
-    tvec_remoteteardown }
-
-/* --- @tvec_setprogress@, @tvec_setprogress_v@ --- *
- *
- * Arguments:  @const char *status@ = progress status token format
- *             @va_list ap@ = argument tail
- *
- * Returns:    ---
- *
- * Use:                Reports the progress of a test execution to the client.
- *
- *             The framework makes use of tokens beginning with %|%|%:
- *
- *               * %|%IDLE|%: during the top-level server code;
- *
- *               * %|%SETUP|%: during the enclosing environment's @before@
- *                 function;
- *
- *               * %|%RUN|%: during the environment's @run@ function, or the
- *                 test function; and
- *
- *               * %|%DONE|%: during the enclosing environment's @after@
- *                 function.
- *
- *             The intent is that a test can use the progress token to check
- *             that a function which is expected to crash does so at the
- *             correct point, so it's expected that more complex test
- *             functions and/or environments will set their own progress
- *             tokens to reflect what's going on.
- */
-
-extern PRINTF_LIKE(1, 2) int tvec_setprogress(const char */*status*/, ...);
-extern int tvec_setprogress_v(const char */*status*/, va_list */*ap*/);
-
-/* --- @tvec_remoteserver@ --- *
- *
- * Arguments:  @int infd@, @int outfd@ = input and output file descriptors
- *             @const struct tvec_config *config@ = test configuration
- *
- * Returns:    Suggested exit code.
- *
- * Use:                Run a test server, reading packets from @infd@ and writing
- *             responses and notifications to @outfd@, and invoking tests as
- *             described by @config@.
- *
- *             This function is not particularly general purpose.  It
- *             expects to `take over' the process, and makes use of private
- *             global variables.
- */
-
-extern int tvec_remoteserver(int /*infd*/, int /*outfd*/,
-                            const struct tvec_config */*config*/);
-
-extern tvec_connectfn tvec_fork, tvec_exec;
-
-#define TVEC_REMOTEFORK(subenv, tests)                                 \
-       TVEC_REMOTEENV, { tvec_fork, subenv }, { tests }
-
-#define TVEC_REMOTEEXEC(subenv, args)                                  \
-       TVEC_REMOTEENV, { tvec_exec, subenv }, { args }
-
-/*----- Timeouts ----------------------------------------------------------*/
-
-struct tvec_timeoutenv {
-  struct tvec_env _env;
-  int timer;                           /* the timer (@ITIMER_...@) */
-  double t;                            /* time to wait (in seconds) */
-  const struct tvec_env *env;          /* subsidiary environment */
-};
-
-struct tvec_timeoutctx {
-  const struct tvec_timeoutenv *te;    /* saved environment description */
-  int timer;                           /* timer code (as overridden) */
-  double t;                            /* time to wait (as overridden) */
-  unsigned f;                          /* flags */
-#define TVTF_SETTMO 1u                 /*   set `@timeout' */
-#define TVTF_SETTMR 2u                 /*   set `@timer' */
-#define TVTF_SETMASK (TVTF_SETTMO | TVTF_SETTMR)
-                                       /*   mask of @TVTF_SET...@ */
-  void *subctx;
-};
-
-extern tvec_envsetupfn tvec_timeoutsetup;
-extern tvec_envfindvarfn tvec_timeoutfindvar;
-extern tvec_envbeforefn tvec_timeoutbefore;
-extern tvec_envrunfn tvec_timeoutrun;
-extern tvec_envafterfn tvec_timeoutafter;
-extern tvec_envteardownfn tvec_timeoutteardown;
-#define TVEC_TIMEOUTENV                                                        \
-       { sizeof(struct tvec_timeoutctx),                               \
-         tvec_timeoutsetup,                                            \
-         tvec_timeoutfindvar,                                          \
-         tvec_timeoutbefore,                                           \
-         tvec_timeoutrun,                                              \
-         tvec_timeoutafter,                                            \
-         tvec_timeoutteardown }
-#define TVEC_TIMEOUTINIT(timer, t) TVEC_TIMEOUTENV, timer, t
-
 /*----- Output functions --------------------------------------------------*/
 
 /* --- @tvec_strlevel@ --- *
@@ -1470,13 +844,24 @@ extern const char *tvec_strlevel(unsigned /*level*/);
  *             @TVLEV_ERR@ or higher force a nonzero exit code.
  */
 
+#define TVEC_LEVELS(_)                                                 \
+       _(INFO, "info", 3)                                              \
+       _(NOTE, "notice", 4)                                            \
+       _(ERR, "ERROR", 8)
+enum {
+#define TVEC_DEFLEVEL(tag, name, val) TVLEV_##tag = val,
+  TVEC_LEVELS(TVEC_DEFLEVEL)
+#undef TVEC_DEFLEVEL
+  TVLEV_LIMIT
+};
+
 extern PRINTF_LIKE(3, 4)
   void tvec_report(struct tvec_state */*tv*/, unsigned /*level*/,
                   const char */*msg*/, ...);
 extern void tvec_report_v(struct tvec_state */*tv*/, unsigned /*level*/,
                          const char */*msg*/, va_list */*ap*/);
 
-/* --- @tvec_error@, @tvec_notice@ --- *
+/* --- @tvec_error@, @tvec_notice@, @tvec_info@ --- *
  *
  * Arguments:  @struct tvec_state *tv@ = test-vector state
  *             @const char *msg@, @va_list ap@ = error message
@@ -1484,17 +869,25 @@ extern void tvec_report_v(struct tvec_state */*tv*/, unsigned /*level*/,
  * Returns:    The @tvec_error@ function returns %$-1$% as a trivial
  *             convenience; @tvec_notice@ does not return a value.
  *
- * Use:                Report an error or a notice.  Errors are distinct from test
+ * Use:                Report a message.  Errors are distinct from test
  *             failures, and indicate that a problem was encountered which
  *             compromised the activity of testing.  Notices are important
  *             information which doesn't fit into any other obvious
- *             category.
+ *             category.  Information is anything else, and is a reasonable
+ *             fallback for writing unstructured information in the absence
+ *             of dedicated support in an output driver.
+ *
+ *             These functions are simple convenience wrappers around
+ *             @tvec_report@.  Use @tvec_report_v@ directly if you have a
+ *             captured @va_list@ of arguments to format.
  */
 
 extern PRINTF_LIKE(2, 3)
   int tvec_error(struct tvec_state */*tv*/, const char */*msg*/, ...);
 extern PRINTF_LIKE(2, 3)
   void tvec_notice(struct tvec_state */*tv*/, const char */*msg*/, ...);
+extern PRINTF_LIKE(2, 3)
+  void tvec_info(struct tvec_state */*tv*/, const char */*msg*/, ...);
 
 /* --- @tvec_unkregerr@ --- *
  *
@@ -1587,7 +980,7 @@ extern struct tvec_output *tvec_tapoutput(FILE */*fp*/);
  *             writing on @fp@.  The policy is subject to change, but
  *             currently the `human' output format is selected if @fp@ is
  *             interactive (i.e., if @isatty(fileno(fp))@ is true), and
- *             otherwise the `tap' format is used.
+ *             otherwise the `machine' format is used.
  */
 
 extern struct tvec_output *tvec_dfltout(FILE */*fp*/);
@@ -1597,18 +990,19 @@ extern struct tvec_output *tvec_dfltout(FILE */*fp*/);
 /* Serialization format.
  *
  * The `candidate register definitions' are those entries @r@ in the @regs@
- * vector whose index @r.i@ is strictly less than @nr@.  The `selected
- * register definitions' are those candidate register definitions @r@ for
- * which the indicated register @rv[r.i]@ has the @TVRF_LIVE@ flag set.  The
- * serialized output begins with a header bitmap: if there are %$n$%
- * candidate register definitions then the header bitmap consists of %$\lceil
- * n/8 \rceil$% bytes.  Bits are ordered starting from the least significant
- * bit of the first byte, end ending at the most significant bit of the final
- * byte.  The bit corresponding to a candidate register definition is set if
- * and only if that register defintion is selected.  The header bitmap is
- * then followed by the serializations of the selected registers -- i.e., for
- * each selected register definition @r@, the serialized value of register
- * @rv[r.i]@ -- simply concatenated together, with no padding or alignment.
+ * vector whose index @r.i@ is strictly less than @nr@ and where
+ * @r.f&mask == want@* .  The `selected register definitions' are those
+ * candidate register definitions @r@ for which the indicated register
+ * @rv[r.i]@ has the @TVRF_LIVE@ flag set.  The serialized output begins with
+ * a header bitmap: if there are %$n$% candidate register definitions then
+ * the header bitmap consists of %$\lceil n/8 \rceil$% bytes.  Bits are
+ * ordered starting from the least significant bit of the first byte, end
+ * ending at the most significant bit of the final byte.  The bit
+ * corresponding to a candidate register definition is set if and only if
+ * that register defintion is selected.  The header bitmap is then followed
+ * by the serializations of the selected registers -- i.e., for each selected
+ * register definition @r@, the serialized value of register @rv[r.i]@ --
+ * simply concatenated together, with no padding or alignment.
  */
 
 /* --- @tvec_serialize@ --- *
@@ -1618,6 +1012,7 @@ extern struct tvec_output *tvec_dfltout(FILE */*fp*/);
  *             @const struct tvec_regdef *regs@ = vector of register
  *                     descriptions, terminated by an entry with a null
  *                     @name@ slot
+ *             @unsigned mask, want@ = flag-based selection
  *             @unsigned nr@ = number of entries in the @rv@ vector
  *             @size_t regsz@ = true size of each element of @rv@
  *
@@ -1632,6 +1027,7 @@ extern struct tvec_output *tvec_dfltout(FILE */*fp*/);
 
 extern int tvec_serialize(const struct tvec_reg */*rv*/, buf */*b*/,
                          const struct tvec_regdef */*regs*/,
+                         unsigned /*mask*/, unsigned /*want*/,
                          unsigned /*nr*/, size_t /*regsz*/);
 
 /* --- @tvec_deserialize@ --- *
@@ -1641,6 +1037,7 @@ extern int tvec_serialize(const struct tvec_reg */*rv*/, buf */*b*/,
  *             @const struct tvec_regdef *regs@ = vector of register
  *                     descriptions, terminated by an entry with a null
  *                     @name@ slot
+ *             @unsigned mask, want@ = flag-based selection
  *             @unsigned nr@ = number of entries in the @rv@ vector
  *             @size_t regsz@ = true size of each element of @rv@
  *
@@ -1655,11 +1052,13 @@ extern int tvec_serialize(const struct tvec_reg */*rv*/, buf */*b*/,
  *             slot, and set the @TVRF_LIVE@ flag on the register.  See
  *             @tvec_serialize@ for a description of the format.
  *
- *             Failure results only from a failing register type handler.
+ *             Failure results only from an input too small for the initial
+ *             bitmap or a failing register type handler.
  */
 
 extern int tvec_deserialize(struct tvec_reg */*rv*/, buf */*b*/,
                            const struct tvec_regdef */*regs*/,
+                           unsigned /*mask*/, unsigned /*want*/,
                            unsigned /*nr*/, size_t /*regsz*/);
 
 /*----- Input utilities ---------------------------------------------------*/
@@ -1803,827 +1202,6 @@ extern int tvec_readword_v(struct tvec_state */*tv*/, dstr */*d*/,
                           const char **/*p_inout*/, const char */*delims*/,
                           const char */*expect*/, va_list */*ap*/);
 
-/*----- Integer types: signed and unsigned --------------------------------*/
-
-/* Integers may be input in decimal, hex, binary, or octal, following
- * approximately usual conventions.
- *
- *   * Signed integers may be preceded with a `+' or `-' sign.
- *
- *   * Decimal integers are just a sequence of decimal digits `0' ... `9'.
- *
- *   * Octal integers are a sequence of digits `0' ... `7', preceded by `0o'
- *     or `0O'.
- *
- *   * Hexadecimal integers are a sequence of digits `0' ... `9', `a'
- *     ... `f', or `A' ... `F', preceded by `0x' or `0X'.
- *
- *   * Radix-B integers are a sequence of digits `0' ... `9', `a' ... `f', or
- *     `A' ... `F', each with value less than B, preceded by `Br' or `BR',
- *     where 0 < B < 36 is expressed in decimal without any leading `0' or
- *     internal underscores `_'.
- *
- *   * A digit sequence may contain internal underscore `_' separators, but
- *     not before or after all of the digits; and two consecutive `_'
- *     characters are not permitted.
- */
-
-extern const struct tvec_regty tvty_int, tvty_uint;
-
-/* The @arg.p@ slot may be null or a pointer to @struct tvec_irange@ or
- * @struct tvec_urange@ as appropriate.  The bounds are inclusive; use, e.g.,
- * @LONG_MAX@ explicitly if one or the other bound is logically inapplicable.
- */
-struct tvec_irange { long min, max; };
-struct tvec_urange { unsigned long min, max; };
-
-/* Bounds corresponding to common integer types. */
-extern const struct tvec_irange
-  tvrange_schar, tvrange_short, tvrange_int, tvrange_long,
-  tvrange_sbyte, tvrange_i16, tvrange_i32;
-extern const struct tvec_urange
-  tvrange_uchar, tvrange_ushort, tvrange_uint, tvrange_ulong, tvrange_size,
-  tvrange_byte, tvrange_u16, tvrange_u32;
-
-/* --- @tvec_claimeq_int@, @TVEC_CLAIMEQ_INT@ --- *
- *
- * Arguments:  @struct tvec_state *tv@ = test-vector state
- *             @long i0, i1@ = two signed integers
- *             @const char *file@, @unsigned @lno@ = calling file and line
- *             @const char *expr@ = the expression to quote on failure
- *
- * Returns:    Nonzero if @i0@ and @i1@ are equal, otherwise zero.
- *
- * Use:                Check that values of @i0@ and @i1@ are equal.  As for
- *             @tvec_claim@ above, a test case is automatically begun and
- *             ended if none is already underway.  If the values are
- *             unequal, then @tvec_fail@ is called, quoting @expr@, and the
- *             mismatched values are dumped: @i0@ is printed as the output
- *             value and @i1@ is printed as the input reference.
- *
- *             The @TVEC_CLAIM_INT@ macro is similar, only it (a) identifies
- *             the file and line number of the call site automatically, and
- *             (b) implicitly quotes the source text of the @i0@ and @i1@
- *             arguments in the failure message.
- */
-
-extern int tvec_claimeq_int(struct tvec_state */*tv*/,
-                           long /*i0*/, long /*i1*/,
-                           const char */*file*/, unsigned /*lno*/,
-                           const char */*expr*/);
-#define TVEC_CLAIMEQ_INT(tv, i0, i1)                                   \
-       (tvec_claimeq_int(tv, i0, i1, __FILE__, __LINE__, #i0 " /= " #i1))
-
-/* --- @tvec_claimeq_uint@, @TVEC_CLAIMEQ_UINT@ --- *
- *
- * Arguments:  @struct tvec_state *tv@ = test-vector state
- *             @unsigned long u0, u1@ = two unsigned integers
- *             @const char *file@, @unsigned @lno@ = calling file and line
- *             @const char *expr@ = the expression to quote on failure
- *
- * Returns:    Nonzero if @u0@ and @u1@ are equal, otherwise zero.
- *
- * Use:                Check that values of @u0@ and @u1@ are equal.  As for
- *             @tvec_claim@ above, a test case is automatically begun and
- *             ended if none is already underway.  If the values are
- *             unequal, then @tvec_fail@ is called, quoting @expr@, and the
- *             mismatched values are dumped: @u0@ is printed as the output
- *             value and @u1@ is printed as the input reference.
- *
- *             The @TVEC_CLAIM_UINT@ macro is similar, only it (a)
- *             identifies the file and line number of the call site
- *             automatically, and (b) implicitly quotes the source text of
- *             the @u0@ and @u1@ arguments in the failure message.
- */
-
-extern int tvec_claimeq_uint(struct tvec_state */*tv*/,
-                           unsigned long /*u0*/, unsigned long /*u1*/,
-                           const char */*file*/, unsigned /*lno*/,
-                           const char */*expr*/);
-#define TVEC_CLAIMEQ_UINT(tv, u0, u1)                                  \
-       (tvec_claimeq_uint(tv, u0, u1, __FILE__, __LINE__, #u0 " /= " #u1))
-
-/*----- Size type ---------------------------------------------------------*/
-
-/* A size is an unsigned integer followed by an optional unit specifier
- * consisting of an SI unit prefix and (optionally) the letter `B'.
- */
-
-extern const struct tvec_regty tvty_size;
-
-/* --- @tvec_claimeq_size@ --- *
- *
- * Arguments:  @struct tvec_state *tv@ = test-vector state
- *             @unsigned long sz0, sz1@ = two sizes
- *             @const char *file@, @unsigned @lno@ = calling file and line
- *             @const char *expr@ = the expression to quote on failure
- *
- * Returns:    Nonzero if @sz0@ and @sz1@ are equal, otherwise zero.
- *
- * Use:                Check that values of @u0@ and @u1@ are equal.  As for
- *             @tvec_claim@ above, a test case is automatically begun and
- *             ended if none is already underway.  If the values are
- *             unequal, then @tvec_fail@ is called, quoting @expr@, and the
- *             mismatched values are dumped: @u0@ is printed as the output
- *             value and @u1@ is printed as the input reference.
- *
- *             The @TVEC_CLAIM_SIZE@ macro is similar, only it (a)
- *             identifies the file and line number of the call site
- *             automatically, and (b) implicitly quotes the source text of
- *             the @u0@ and @u1@ arguments in the failure message.
- */
-
-int tvec_claimeq_size(struct tvec_state *tv,
-                     unsigned long sz0, unsigned long sz1,
-                     const char *file, unsigned lno, const char *expr);
-#define TVEC_CLAIMEQ_UINT(tv, u0, u1)                                  \
-       (tvec_claimeq_uint(tv, u0, u1, __FILE__, __LINE__, #u0 " /= " #u1))
-
-/*----- Floating-point type -----------------------------------------------*/
-
-/* Floating-point values are either NaN (%|#nan|%, if supported by the
- * platform); positive or negative infinity (%|#inf|%, %|+#inf|%, or
- * %|#+inf|% (preferring the last), and %|-#inf|% or %|#-inf|% (preferring
- * the latter), if supported by the platform); or a number in strtod(3)
- * syntax.
- *
- * The comparison rules for floating-point numbers are complex: see
- * @tvec_claimeqish_float@ for details.
- */
-
-extern const struct tvec_regty tvty_float;
-
-struct tvec_floatinfo {
-  /* Details about acceptable floating-point values. */
-
-  unsigned f;                          /* flags (@TVFF_...@ bits) */
-#define TVFF_NOMIN 1u                  /*   ignore @min@ (allow -inf) */
-#define TVFF_NOMAX 2u                  /*   ignore @max@ (allow +inf) */
-#define TVFF_NANOK 4u                  /*   permit NaN */
-#define TVFF_EQMASK 0xf0               /*   how to compare */
-#define TVFF_EXACT 0x00                        /*     must equal exactly */
-#define TVFF_ABSDELTA 0x10             /*     must be within @delta@ */
-#define TVFF_RELDELTA 0x20             /*     diff < @delta@ fraction */
-  double min, max;                     /* smallest/largest value allowed */
-  double delta;                                /* maximum tolerable difference */
-};
-
-extern const struct tvec_floatinfo tvflt_finite, tvflt_nonneg;
-
-/* --- @tvec_claimeqish_float@, @TVEC_CLAIMEQISH_FLOAT@ --- *
- *
- * Arguments:  @struct tvec_state *tv@ = test-vector state
- *             @double f0, f1@ = two floating-point numbers
- *             @unsigned f@ = flags (@TVFF_...@)
- *             @double delta@ = maximum tolerable difference
- *             @const char *file@, @unsigned @lno@ = calling file and line
- *             @const char *expr@ = the expression to quote on failure
- *
- * Returns:    Nonzero if @f0@ and @f1@ are sufficiently close, otherwise
- *             zero.
- *
- * Use:                Check that values of @f0@ and @f1@ are sufficiently close.
- *             As for @tvec_claim@ above, a test case is automatically begun
- *             and ended if none is already underway.  If the values are
- *             too far apart, then @tvec_fail@ is called, quoting @expr@,
- *             and the mismatched values are dumped: @f0@ is printed as the
- *             output value and @f1@ is printed as the input reference.
- *
- *             The details for the comparison are as follows.
- *
- *               * A NaN value matches any other NaN, and nothing else.
- *
- *               * An infinity matches another infinity of the same sign,
- *                 and nothing else.
- *
- *               * If @f&TVFF_EQMASK@ is @TVFF_EXACT@, then any
- *                 representable number matches only itself: in particular,
- *                 positive and negative zero are considered distinct.
- *                 (This allows tests to check that they land on the correct
- *                 side of branch cuts, for example.)
- *
- *               * If @f&TVFF_EQMASK@ is @TVFF_ABSDELTA@, then %$x$% matches
- *                 %$y$% when %$|x - y| < \delta$%.
- *
- *               * If @f&TVFF_EQMASK@ is @TVFF_RELDELTA@, then %$x$% matches
- *                 %$y$% when %$|1 - x/y| < \delta$%.  (Note that this
- *                 criterion is asymmetric.  Write %$x \approx_\delta y$%
- *                 if and only if %$|1 - x/y < \delta$%.  Then, for example,
- *                 if %$y/(1 + \delta) < x < y (1 - \delta)$%, then
- *                 %$x \approx_\delta y$%, but %$y \not\approx_\delta x$%.)
- *
- *             The @TVEC_CLAIM_FLOAT@ macro is similar, only it (a)
- *             identifies the file and line number of the call site
- *             automatically, and (b) implicitly quotes the source text of
- *             the @f0@ and @f1@ arguments (and @delta@) in the failure
- *             message.
- */
-
-extern int tvec_claimeqish_float(struct tvec_state */*tv*/,
-                                double /*f0*/, double /*f1*/,
-                                unsigned /*f*/, double /*delta*/,
-                                const char */*file*/, unsigned /*lno*/,
-                                const char */*expr*/);
-#define TVEC_CLAIMEQISH_FLOAT(tv, f0, f1, f, delta)                    \
-       (tvec_claimeqish_float(tv, f0, f1, f, delta, __FILE__, __LINE__, \
-                              #f0 " /= " #f1 " (+/- " #delta ")"))
-
-/* --- @tvec_claimeq_float@, @TVEC_CLAIMEQ_FLOAT@ --- *
- *
- * Arguments:  @struct tvec_state *tv@ = test-vector state
- *             @double f0, f1@ = two floating-point numbers
- *             @const char *file@, @unsigned @lno@ = calling file and line
- *             @const char *expr@ = the expression to quote on failure
- *
- * Returns:    Nonzero if @f0@ and @u1@ are identical, otherwise zero.
- *
- * Use:                Check that values of @f0@ and @f1@ are identical.  The
- *             function is exactly equivalent to @tvec_claimeqish_float@
- *             with @f == TVFF_EXACT@; the macro is similarly like
- *             @TVEC_CLAIMEQISH_FLOAT@ with @f == TVFF_EXACT@, except that
- *             it doesn't bother to quote a delta.
- */
-
-extern int tvec_claimeq_float(struct tvec_state */*tv*/,
-                             double /*f0*/, double /*f1*/,
-                             const char */*file*/, unsigned /*lno*/,
-                             const char */*expr*/);
-#define TVEC_CLAIMEQ_FLOAT(tv, f0, f1)                                 \
-       (tvec_claimeq_float(tv, f0, f1, __FILE__, __LINE__, #f0 " /= " #f1))
-
-/*----- Durations ---------------------------------------------------------*/
-
-/* A duration measures a time interval in seconds.  The input format consists
- * of a nonnegative decimal floating-point number in @strtod@ format followed
- * by an optional unit specification.
- */
-
-extern const struct tvec_regty tvty_duration;
-
-/* --- @tvec_parsedurunit@ --- *
- *
- * Arguments:  @double *scale_out@ = where to leave the scale
- *             @const char **p_inout@ = input unit string, updated
- *
- * Returns:    Zero on success, %$-1$% on error.
- *
- * Use:                If @*p_inout@ begins with a unit string followed by the end
- *             of the string or some non-alphanumeric character, then store
- *             the corresponding scale factor in @*scale_out@, advance
- *             @*p_inout@ past the unit string, and return zero.  Otherwise,
- *             return %$-1$%.
- */
-
-extern int tvec_parsedurunit(double */*scale_out*/,
-                            const char **/*p_inout*/);
-
-/* --- @tvec_claimeqish_duration@, @TVEC_CLAIMEQISH_DURATION@ --- *
- *
- * Arguments:  @struct tvec_state *tv@ = test-vector state
- *             @double to, t1@ = two durations
- *             @unsigned f@ = flags (@TVFF_...@)
- *             @double delta@ = maximum tolerable difference
- *             @const char *file@, @unsigned @lno@ = calling file and line
- *             @const char *expr@ = the expression to quote on failure
- *
- * Returns:    Nonzero if @t0@ and @t1@ are sufficiently close, otherwise
- *             zero.
- *
- * Use:                Check that values of @t0@ and @t1@ are sufficiently close.
- *             This is essentially the same as @tvec_claimeqish_float@, only
- *             it dumps the values as durations on a mismatch.
- *
- *             The @TVEC_CLAIM_FLOAT@ macro is similar, only it (a)
- *             identifies the file and line number of the call site
- *             automatically, and (b) implicitly quotes the source text of
- *             the @t0@ and @t1@ arguments (and @delta@) in the failure
- *             message.
- */
-
-extern int tvec_claimeqish_duration(struct tvec_state */*tv*/,
-                                   double /*t0*/, double /*t1*/,
-                                   unsigned /*f*/, double /*delta*/,
-                                   const char */*file*/, unsigned /*lno*/,
-                                   const char */*expr*/);
-#define TVEC_CLAIMEQISH_DURATION(tv, t0, t1, f, delta)                 \
-       (tvec_claimeqish_duration(tv, t0, t1, f, delta, __FILE__, __LINE__, \
-                              #t0 " /= " #t1 " (+/- " #delta ")"))
-
-/* --- @tvec_claimeq_duration@, @TVEC_CLAIMEQ_DURATION@ --- *
- *
- * Arguments:  @struct tvec_state *tv@ = test-vector state
- *             @double t0, t1@ = two durations
- *             @const char *file@, @unsigned @lno@ = calling file and line
- *             @const char *expr@ = the expression to quote on failure
- *
- * Returns:    Nonzero if @t0@ and @t1@ are identical, otherwise zero.
- *
- * Use:                Check that values of @t0@ and @t1@ are identical.  The
- *             function is exactly equivalent to @tvec_claimeqish_duration@
- *             with @f == TVFF_EXACT@; the macro is similarly like
- *             @TVEC_CLAIMEQISH_DURATION@ with @f == TVFF_EXACT@, except
- *             that it doesn't bother to quote a delta.
- */
-
-int tvec_claimeq_duration(struct tvec_state */*tv*/,
-                         double /*t0*/, double /*t1*/,
-                         const char */*file*/, unsigned /*lno*/,
-                         const char */*expr*/);
-#define TVEC_CLAIMEQ_DURATION(tv, t0, t1)                                      \
-       (tvec_claimeq_float(tv, t0, t1, __FILE__, __LINE__, #t0 " /= " #t1))
-
-/*----- Enumerated types --------------------------------------------------*/
-
-/* An enumeration describes a set of values of some underlying type, each of
- * which has a symbolic name.  Values outside of the defined set can occur --
- * on output, because of bugs in the tested code, or on input to test
- * handling of unexpected values.
- *
- * There is a distinct enumerated type for each of the branches of
- * @tvec_misc@.  In the following, we write @t@ for the type code, which is
- * @i@ for signed integer, @u@ for unsigned integer, @f@ for floating-point,
- * and @p@ for pointer.
- *
- * On input, an enumerated value may be given by name or as a literal value.
- * For enumerations based on numeric types, the literal values can be written
- * in the same syntax as the underlying values.  For enumerations based on
- * pointers, the only permitted literal is %|#nil|%, which denotes a null
- * pointer.  On output, names are preferred (with the underlying value given
- * in a comment).
- */
-
-#define DEFENUMTY(tag, ty, slot)                                       \
-       extern const struct tvec_regty tvty_##slot##enum;
-TVEC_MISCSLOTS(DEFENUMTY)
-#undef DEFENUMTY
-
-/* A @struct tvec_tassoc@ associates a string tag with a value. */
-#define DEFASSOC(tag_, ty, slot)                                       \
-       struct tvec_##slot##assoc { const char *tag; ty slot; };
-TVEC_MISCSLOTS(DEFASSOC)
-#undef DEFASSOC
-
-#define TVEC_ENDENUM { 0, 0 }
-
-/* Information about an enumerated type. */
-#define DEFINFO(tag, ty, slot)                                         \
-       struct tvec_##slot##enuminfo {                                  \
-         const char *name;             /* type name for diagnostics */ \
-         const struct tvec_##slot##assoc *av; /* name/value mappings */ \
-         EXTRA_##tag##_INFOSLOTS       /* type-specific extra info */  \
-       };
-
-#define EXTRA_INT_INFOSLOTS                                            \
-       const struct tvec_irange *ir;   /* allowed range of raw values */
-
-#define EXTRA_UINT_INFOSLOTS                                           \
-       const struct tvec_urange *ur;   /* allowed range of raw values */
-
-#define EXTRA_FLT_INFOSLOTS                                            \
-       const struct tvec_floatinfo *fi; /* range and matching policy */
-
-#define EXTRA_PTR_INFOSLOTS            /* (nothing) */
-
-TVEC_MISCSLOTS(DEFINFO)
-
-#undef EXTRA_INT_INFOSLOTS
-#undef EXTRA_UINT_INFOSLOTS
-#undef EXTRA_FLT_INFOSLOTS
-#undef EXTRA_PTR_INFOSLOTS
-
-#undef DEFINFO
-
-/* Standard enumerations. */
-extern const struct tvec_ienuminfo tvenum_bool;
-extern const struct tvec_ienuminfo tvenum_cmp;
-
-/* --- @tvec_claimeq_tenum@, @TVEC_CLAIMEQ_TENUM@ --- *
- *
- * Arguments:  @struct tvec_state *tv@ = test-vector state
- *             @const struct tvec_typeenuminfo *ei@ = enumeration type info
- *             @ty t0, t1@ = two values
- *             @const char *file@, @unsigned @lno@ = calling file and line
- *             @const char *expr@ = the expression to quote on failure
- *
- * Returns:    Nonzero if @t0@ and @t1@ are equal, otherwise zero.
- *
- * Use:                Check that values of @t0@ and @t1@ are equal.  As for
- *             @tvec_claim@ above, a test case is automatically begun and
- *             ended if none is already underway.  If the values are
- *             unequal, then @tvec_fail@ is called, quoting @expr@, and the
- *             mismatched values are dumped: @t0@ is printed as the output
- *             value and @t1@ is printed as the input reference.
- *
- *             The @TVEC_CLAIM_TENUM@ macro is similar, only it (a)
- *             identifies the file and line number of the call site
- *             automatically, and (b) implicitly quotes the source text of
- *             the @t0@ and @t1@ arguments in the failure message.
- */
-
-#define DECLCLAIM(tag, ty, slot)                                       \
-       extern int tvec_claimeq_##slot##enum                            \
-         (struct tvec_state */*tv*/,                                   \
-          const struct tvec_##slot##enuminfo */*ei*/,                  \
-          ty /*t0*/, ty /*t1*/,                                        \
-          const char */*file*/, unsigned /*lno*/, const char */*expr*/);
-TVEC_MISCSLOTS(DECLCLAIM)
-#undef DECLCLAIM
-#define TVEC_CLAIMEQ_IENUM(tv, ei, i0, i1)                             \
-       (tvec_claimeq_ienum(tv, ei, i0, i1,                             \
-                           __FILE__, __LINE__, #i0 " /= " #i1))
-#define TVEC_CLAIMEQ_UENUM(tv, ei, u0, u1)                             \
-       (tvec_claimeq_uenum(tv, ei, u0, u1,                             \
-                           __FILE__, __LINE__, #u0 " /= " #u1))
-#define TVEC_CLAIMEQ_FENUM(tv, ei, f0, f1)                             \
-       (tvec_claimeq_fenum(tv, ei, f0, f1,                             \
-                           __FILE__, __LINE__, #f0 " /= " #f1))
-#define TVEC_CLAIMEQ_PENUM(tv, ei, p0, p1)                             \
-       (tvec_claimeq_penum(tv, ei, p0, p1,                             \
-                           __FILE__, __LINE__, #p0 " /= " #p1))
-
-/*----- Flags type --------------------------------------------------------*/
-
-/* A flags value packs a number of fields into a single nonnegative integer.
- * Symbolic names are associated with the possible values of the various
- * fields; more precisely, each name is associated with a value and a
- * covering bitmask.
- *
- * The input syntax is a sequence of items separated by `%|||%' signs.  Each
- * item may be the symbolic name of a field value, or a literal unsigned
- * integer.  The masks associated with the given symbolic names must be
- * disjoint.  The resulting numerical value is simply the bitwise OR of the
- * given values.
- *
- * On output, the table of symbolic names and their associated values and
- * masks is repeatedly scanned, in order, to find disjoint matches -- i.e.,
- * entries whose value matches the target value in the bit positions
- * indicated by the mask, and whose mask doesn't overlap with any previously
- * found matches; the names are then output, separated by `%|||%'.  Any
- * remaining nonzero bits not covered by any of the matching masks are output
- * as a single literal integer, in hex.
- */
-
-extern const struct tvec_regty tvty_flags;
-
-struct tvec_flag {
-  /* Definition of a single flag or bitfield value.
-   *
-   * Each named setting comes with a value @v@ and a mask @m@; the mask
-   * should cover all of the value bits, i.e., @(v&~m) == 0@.
-   */
-
-  const char *tag;                     /* name */
-  unsigned long m, v;                  /* mask and value */
-};
-
-#define TVEC_ENDFLAGS { 0, 0, 0 }
-
-struct tvec_flaginfo {
-  /* Information about a flags type. */
-
-  const char *name;                    /* type name for diagnostics  */
-  const struct tvec_flag *fv;          /* name/mask/value mappings */
-  const struct tvec_urange *range;     /* permitted range for literals */
-};
-
-/* --- @tvec_claimeq_flags@, @TVEC_CLAIMEQ_FLAGS@ --- *
- *
- * Arguments:  @struct tvec_state *tv@ = test-vector state
- *             @const struct tvec_flaginfo *fi@ = flags type info
- *             @unsigned long f0, f1@ = two values
- *             @const char *file@, @unsigned @lno@ = calling file and line
- *             @const char *expr@ = the expression to quote on failure
- *
- * Returns:    Nonzero if @f0@ and @f1@ are equal, otherwise zero.
- *
- * Use:                Check that values of @f0@ and @f1@ are equal.  As for
- *             @tvec_claim@ above, a test case is automatically begun and
- *             ended if none is already underway.  If the values are
- *             unequal, then @tvec_fail@ is called, quoting @expr@, and the
- *             mismatched values are dumped: @f0@ is printed as the output
- *             value and @f1@ is printed as the input reference.
- *
- *             The @TVEC_CLAIM_FLAGS@ macro is similar, only it (a)
- *             identifies the file and line number of the call site
- *             automatically, and (b) implicitly quotes the source text of
- *             the @f0@ and @f1@ arguments in the failure message.
- */
-
-extern int tvec_claimeq_flags(struct tvec_state */*tv*/,
-                             const struct tvec_flaginfo */*fi*/,
-                             unsigned long /*f0*/, unsigned long /*f1*/,
-                             const char */*file*/, unsigned /*lno*/,
-                             const char */*expr*/);
-#define TVEC_CLAIMEQ_FLAGS(tv, fi, f0, f1)                             \
-       (tvec_claimeq_flags(tv, fi, f0, f1,                             \
-                           __FILE__, __LINE__, #f0 " /= " #f1))
-
-/*----- Character type ----------------------------------------------------*/
-
-/* A character value holds a character, as read by @fgetc@.  The special
- * @EOF@ value can also be represented.
- *
- * On input, a character value can be given by symbolic name, with a leading
- * `%|#|%'; or a character or `%|\|%'-escape sequence, optionally in single
- * quotes.
- *
- * The following escape sequences and character names are recognized.
- *
- *   * `%|#eof|%' is the special end-of-file marker.
- *
- *   * `%|#nul|%' is the NUL character, sometimes used to terminate strings.
- *
- *   * `%|bell|%', `%|bel|%', `%|ding|%', or `%|\a|%' is the BEL character
- *     used to ring the terminal bell (or do some other thing to attract the
- *     user's attention).
- *
- *   * %|#backspace|%, %|#bs|%, or %|\b|% is the backspace character, used to
- *     move the cursor backwords by one cell.
- *
- *   * %|#escape|% %|#esc|%, or%|\e|% is the escape character, used to
- *     introduce special terminal commands.
- *
- *   * %|#formfeed|%, %|#ff|%, or %|\f|% is the formfeed character, used to
- *     separate pages of text.
- *
- *   * %|#newline|%, %|#linefeed|%, %|#lf|%, %|#nl|%, or %|\n|% is the
- *     newline character, used to terminate lines of text or advance the
- *     cursor to the next line (perhaps without returning it to the start of
- *     the line).
- *
- *   * %|#return|%, %|#carriage-return|%, %|#cr|%, or %|\r|% is the
- *     carriage-return character, used to return the cursor to the start of
- *     the line.
- *
- *   * %|#tab|%, %|#horizontal-tab|%, %|#ht|%, or %|\t|% is the tab
- *     character, used to advance the cursor to the next tab stop on the
- *     current line.
- *
- *   * %|#vertical-tab|%, %|#vt|%, %|\v|% is the vertical tab character.
- *
- *   * %|#space|%, %|#spc|% is the space character.
- *
- *   * %|#delete|%, %|#del|% is the delete character, used to erase the most
- *     recent character.
- *
- *   * %|\'|% is the single-quote character.
- *
- *   * %|\\|% is the backslash character.
- *
- *   * %|\"|% is the double-quote character.
- *
- *   * %|\NNN|% or %|\{NNN}|% is the character with code NNN in octal.  The
- *     NNN may be up to three digits long.
- *
- *   * %|\xNN|% or %|\x{NN}|% is the character with code NNN in hexadecimal.
- */
-
-extern const struct tvec_regty tvty_char;
-
-/* --- @tvec_claimeq_char@, @TVEC_CLAIMEQ_CHAR@ --- *
- *
- * Arguments:  @struct tvec_state *tv@ = test-vector state
- *             @int ch0, ch1@ = two character codes
- *             @const char *file@, @unsigned @lno@ = calling file and line
- *             @const char *expr@ = the expression to quote on failure
- *
- * Returns:    Nonzero if @ch0@ and @ch1@ are equal, otherwise zero.
- *
- * Use:                Check that values of @ch0@ and @ch1@ are equal.  As for
- *             @tvec_claim@ above, a test case is automatically begun and
- *             ended if none is already underway.  If the values are
- *             unequal, then @tvec_fail@ is called, quoting @expr@, and the
- *             mismatched values are dumped: @ch0@ is printed as the output
- *             value and @ch1@ is printed as the input reference.
- *
- *             The @TVEC_CLAIM_CHAR@ macro is similar, only it (a)
- *             identifies the file and line number of the call site
- *             automatically, and (b) implicitly quotes the source text of
- *             the @ch0@ and @ch1@ arguments in the failure message.
- */
-
-extern int tvec_claimeq_char(struct tvec_state */*tv*/,
-                            int /*ch0*/, int /*ch1*/,
-                            const char */*file*/, unsigned /*lno*/,
-                            const char */*expr*/);
-#define TVEC_CLAIMEQ_CHAR(tv, c0, c1)                                  \
-       (tvec_claimeq_char(tv, c0, c1, __FILE__, __LINE__, #c0 " /= " #c1))
-
-/*----- Text and binary string types --------------------------------------*/
-
-/* A string is a sequence of octets.  Text and binary strings differ
- * primarily in presentation: text strings are shown as raw characters where
- * possible; binary strings are shown as hex dumps with an auxiliary text
- * display.
- *
- * The input format for both kinds of strings is basically the same: a
- * `compound string', consisting of
- *
- *   * single-quoted strings, which are interpreted entirely literally, but
- *     can't contain single quotes or newlines;
- *
- *   * double-quoted strings, in which `%|\|%'-escapes are interpreted as for
- *     characters;
- *
- *   * character names, marked by an initial `%|#|%' sign;
- *
- *   * special tokens marked by an initial `%|!|%' sign; or
- *
- *   * barewords interpreted according to the current coding scheme.
- *
- * The special tokens are
- *
- *   * `%|!bare|%', which causes subsequent sequences of barewords to be
- *     treated as plain text;
- *
- *   * `%|!hex|%', `%|!base32|%', `%|!base64|%', which cause subsequent
- *     barewords to be decoded in the requested manner.
- *
- *   * `%|!repeat|% %$n$% %|{|% %%\textit{string}%% %|}|%', which includes
- *     %$n$% copies of the (compound) string.
- *
- * The only difference between text and binary strings is that the initial
- * coding scheme is %|bare|% for text strings and %|hex|% for binary strings.
- *
- * Either kind of string can contain internal nul characters.  A trailing nul
- * is appended -- beyond the stated input length -- to input strings as a
- * convenience to test functions.  Test functions may include such a nul
- * character on output but this is not checked by the equality test.
- *
- * A @struct tvec_urange@ may be supplied as an argument: the length of the
- * string (in bytes) will be checked against the permitted range.
- */
-
-extern const struct tvec_regty tvty_text, tvty_bytes;
-
-/* --- @tvec_alloctext@, @tvec_allocbytes@ --- *
- *
- * Arguments:  @union tvec_regval *rv@ = register value
- *             @size_t sz@ = required size
- *
- * Returns:    ---
- *
- * Use:                Allocated space in a text or binary string register.  If the
- *             current register size is sufficient, its buffer is left
- *             alone; otherwise, the old buffer, if any, is freed and a
- *             fresh buffer allocated.  These functions are not intended to
- *             be used to adjust a buffer repeatedly, e.g., while building
- *             output incrementally: (a) they will perform badly, and (b)
- *             the old buffer contents are simply discarded if reallocation
- *             is necessary.  Instead, use a @dbuf@ or @dstr@.
- *
- *             The @tvec_alloctext@ function sneakily allocates an extra
- *             byte for a terminating zero.  The @tvec_allocbytes@ function
- *             doesn't do this.
- */
-
-extern void tvec_alloctext(union tvec_regval */*rv*/, size_t /*sz*/);
-extern void tvec_allocbytes(union tvec_regval */*rv*/, size_t /*sz*/);
-
-/* --- @tvec_claimeq_text@, @TVEC_CLAIMEQ_TEXT@ --- *
- *
- * Arguments:  @struct tvec_state *tv@ = test-vector state
- *             @const char *p0@, @size_t sz0@ = first string with length
- *             @const char *p1@, @size_t sz1@ = second string with length
- *             @const char *file@, @unsigned @lno@ = calling file and line
- *             @const char *expr@ = the expression to quote on failure
- *
- * Returns:    Nonzero if the strings at @p0@ and @p1@ are equal, otherwise
- *             zero.
- *
- * Use:                Check that strings at @p0@ and @p1@ are equal.  As for
- *             @tvec_claim@ above, a test case is automatically begun and
- *             ended if none is already underway.  If the values are
- *             unequal, then @tvec_fail@ is called, quoting @expr@, and the
- *             mismatched values are dumped: @p0@ is printed as the output
- *             value and @p1@ is printed as the input reference.
- *
- *             The @TVEC_CLAIM_TEXT@ macro is similar, only it (a)
- *             identifies the file and line number of the call site
- *             automatically, and (b) implicitly quotes the source text of
- *             the @ch0@ and @ch1@ arguments in the failure message.
- */
-
-extern int tvec_claimeq_text(struct tvec_state */*tv*/,
-                            const char */*p0*/, size_t /*sz0*/,
-                            const char */*p1*/, size_t /*sz1*/,
-                            const char */*file*/, unsigned /*lno*/,
-                            const char */*expr*/);
-#define TVEC_CLAIMEQ_TEXT(tv, p0, sz0, p1, sz1)                                \
-       (tvec_claimeq_text(tv, p0, sz0, p1, sz1, __FILE__, __LINE__,    \
-                          #p0 "[" #sz0 "] /= " #p1 "[" #sz1 "]"))
-
-/* --- @tvec_claimeq_textz@, @TVEC_CLAIMEQ_TEXTZ@ --- *
- *
- * Arguments:  @struct tvec_state *tv@ = test-vector state
- *             @const char *p0, *p1@ = two strings to compare
- *             @const char *file@, @unsigned @lno@ = calling file and line
- *             @const char *expr@ = the expression to quote on failure
- *
- * Returns:    Nonzero if the strings at @p0@ and @p1@ are equal, otherwise
- *             zero.
- *
- * Use:                Check that strings at @p0@ and @p1@ are equal, as for
- *             @tvec_claimeq_string@, except that the strings are assumed
- *             null-terminated, so their lengths don't need to be supplied
- *             explicitly.  The macro is similarly like @TVEC_CLAIMEQ_TEXT@.
- */
-
-extern int tvec_claimeq_textz(struct tvec_state */*tv*/,
-                             const char */*p0*/, const char */*p1*/,
-                             const char */*file*/, unsigned /*lno*/,
-                             const char */*expr*/);
-#define TVEC_CLAIMEQ_TEXTZ(tv, p0, p1)                                 \
-       (tvec_claimeq_textz(tv, p0, p1, __FILE__, __LINE__, #p0 " /= " #p1))
-
-/* --- @tvec_claimeq_bytes@, @TVEC_CLAIMEQ_BYTES@ --- *
- *
- * Arguments:  @struct tvec_state *tv@ = test-vector state
- *             @const void *p0@, @size_t sz0@ = first string with length
- *             @const void *p1@, @size_t sz1@ = second string with length
- *             @const char *file@, @unsigned @lno@ = calling file and line
- *             @const char *expr@ = the expression to quote on failure
- *
- * Returns:    Nonzero if the strings at @p0@ and @p1@ are equal, otherwise
- *             zero.
- *
- * Use:                Check that binary strings at @p0@ and @p1@ are equal.  As for
- *             @tvec_claim@ above, a test case is automatically begun and
- *             ended if none is already underway.  If the values are
- *             unequal, then @tvec_fail@ is called, quoting @expr@, and the
- *             mismatched values are dumped: @p0@ is printed as the output
- *             value and @p1@ is printed as the input reference.
- *
- *             The @TVEC_CLAIM_STRING@ macro is similar, only it (a)
- *             identifies the file and line number of the call site
- *             automatically, and (b) implicitly quotes the source text of
- *             the @ch0@ and @ch1@ arguments in the failure message.
- */
-
-extern int tvec_claimeq_bytes(struct tvec_state */*tv*/,
-                              const void */*p0*/, size_t /*sz0*/,
-                              const void */*p1*/, size_t /*sz1*/,
-                              const char */*file*/, unsigned /*lno*/,
-                              const char */*expr*/);
-#define TVEC_CLAIMEQ_BYTES(tv, p0, sz0, p1, sz1)                       \
-       (tvec_claimeq(tv, p0, sz0, p1, sz1, __FILE__, __LINE__,         \
-                     #p0 "[" #sz0 "] /= " #p1 "[" #sz1 "]"))
-
-/*----- Buffer type -------------------------------------------------------*/
-
-/* Buffer registers are primarily used for benchmarking.  Only a buffer's
- * allocation parameters are significant: its contents are ignored on
- * comparison and output, and unspecified on input.
- *
- * The input format gives the buffer's size, and an optional alignment
- * specification, in the form %|SZ [`@' M [`+' A]]|%.  Each of %|SZ|%, %|M|%
- * and %|A|% are sizes, as an integer, optionally suffixed with a unit `kB',
- * `MB', `GB', `TB', `PB', `EB', `ZB', `YB' (with or without the `B')
- * denoting a power of 1024.  The %|SZ|% gives the (effective) buffer size.
- * %|M|% is the `alignment quantum' and %|A|% is the `alignment offset'; both
- * default to zero, but if %|M|% is nonzero then the start of the buffer is
- * aligned such that it is %|A|% more than a multiple of %|M|% bytes.  Note
- * that %|M|% need not be a power of two, though this is common.
- *
- * Units other than `B' are used on output only when the size would be
- * expressed exactly.
- *
- * Buffers are %%\emph{not}%% allocated by default.  In benchmarks, this is
- * best done in a @before@ function.
- *
- * No @claimeq@ functions or macros are provided for buffers because they
- * don't seem very useful.
- */
-
-extern const struct tvec_regty tvty_buffer;
-
-/* --- @tvec_initbuffer@ --- *
- *
- * Arguments:  @union tvec_regval *rv@ = register value
- *             @const union tvec_regval *ref@ = reference buffer
- *             @size_t sz@ = size to allocate
- *
- * Returns:    ---
- *
- * Use:                Initialize the alignment parameters in @rv@ to match @ref@,
- *             and the size to @sz@.
- */
-
-extern void tvec_initbuffer(union tvec_regval */*rv*/,
-                           const union tvec_regval */*ref*/, size_t /*sz*/);
-
-/* --- @tvec_allocbuffer@ --- *
- *
- * Arguments:  @union tvec_regval *rv@ = register value
- *
- * Returns:    ---
- *
- * Use:                Allocate @sz@ bytes to the buffer and fill the space with a
- *             distinctive pattern.
- */
-
-extern void tvec_allocbuffer(union tvec_regval */*rv*/);
-
 /*----- That's all, folks -------------------------------------------------*/
 
 #ifdef __cplusplus