+/*----- 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 a 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 int PRINTF_LIKE(5, 6)
+ 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*/);
+