+ * TAP comes from the Perl community, but has spread rather
+ * further. This driver produces TAP version 14, but pretends
+ * to be version 13. The driver produces a TAP `test point' --
+ * i.e., a result reported as `ok' or `not ok' -- for each input
+ * test group. Failure reports and register dumps are produced
+ * as diagnostic messages before the final group result. (TAP
+ * permits structuerd YAML data after the test-point result,
+ * which could be used to report details, but (a) postponing the
+ * details until after the report is inconvenient, and (b) there
+ * is no standardization for the YAML anyway, so in practice
+ * it's no more useful than the unstructured diagnostics.
+ */
+
+extern struct tvec_output *tvec_tapoutput(FILE */*fp*/);
+
+/* --- @tvec_dfltoutput@ --- *
+ *
+ * Arguments: @FILE *fp@ = output file to write on
+ *
+ * Returns: An output formatter.
+ *
+ * Use: Selects and instantiates an output formatter suitable for
+ * 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.
+ */
+
+extern struct tvec_output *tvec_dfltout(FILE */*fp*/);
+
+/*------ Serialization utilities ------------------------------------------*/
+
+/* 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.
+ */
+
+/* --- @tvec_serialize@ --- *
+ *
+ * Arguments: @const struct tvec_reg *rv@ = vector of registers
+ * @buf *b@ = buffer to write on
+ * @const struct tvec_regdef *regs@ = vector of register
+ * descriptions, terminated by an entry with a null
+ * @name@ slot
+ * @unsigned nr@ = number of entries in the @rv@ vector
+ * @size_t regsz@ = true size of each element of @rv@
+ *
+ * Returns: Zero on success, %$-1$% on failure.
+ *
+ * Use: Serialize a collection of register values.
+ *
+ * The serialized output is written to the buffer @b@. Failure
+ * can be caused by running out of buffer space, or a failing
+ * type handler.
+ */
+
+extern int tvec_serialize(const struct tvec_reg */*rv*/, buf */*b*/,
+ const struct tvec_regdef */*regs*/,
+ unsigned /*nr*/, size_t /*regsz*/);
+
+/* --- @tvec_deserialize@ --- *
+ *
+ * Arguments: @struct tvec_reg *rv@ = vector of registers
+ * @buf *b@ = buffer to write on
+ * @const struct tvec_regdef *regs@ = vector of register
+ * descriptions, terminated by an entry with a null
+ * @name@ slot
+ * @unsigned nr@ = number of entries in the @rv@ vector
+ * @size_t regsz@ = true size of each element of @rv@
+ *
+ * Returns: Zero on success, %$-1$% on failure.
+ *
+ * Use: Deserialize a collection of register values.
+ *
+ * The size of the register vector @nr@ and the register
+ * definitions @regs@ must match those used when producing the
+ * serialization. For each serialized register value,
+ * deserialize and store the value into the appropriate register
+ * 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.
+ */
+
+extern int tvec_deserialize(struct tvec_reg */*rv*/, buf */*b*/,
+ const struct tvec_regdef */*regs*/,
+ unsigned /*nr*/, size_t /*regsz*/);
+
+/*----- Input utilities ---------------------------------------------------*/
+
+/* These are provided by the core for the benefit of type @parse@ methods,
+ * and test-environment @set@ functions, which get to read from the test
+ * input file. The latter are usually best implemented by calling on the
+ * former.
+ *
+ * The two main rules are as follows.
+ *
+ * * Leave the file position at the beginning of the line following
+ * whatever it was that you read.
+ *
+ * * When you read and consume a newline (which you do at least once, by
+ * the previous rule), then increment @tv->lno@ to keep track of the
+ * current line number.
+ */
+
+/* --- @tvec_syntax@, @tvec_syntax_v@ --- *
+ *
+ * Arguments: @struct tvec_state *tv@ = test-vector state
+ * @int ch@ = the character found (in @fgetc@ format)
+ * @const char *expect@, @va_list ap@ = what was expected
+ *
+ * Returns: %$-1$%.
+ *
+ * Use: Report a syntax error quoting @ch@ and @expect@. If @ch@ is
+ * a newline, then back up so that it can be read again (e.g.,
+ * by @tvec_flushtoeol@ or @tvec_nexttoken@, which will also
+ * advance the line number).
+ */
+
+extern PRINTF_LIKE(3, 4)
+ int tvec_syntax(struct tvec_state */*tv*/, int /*ch*/,
+ const char */*expect*/, ...);
+extern int tvec_syntax_v(struct tvec_state */*tv*/, int /*ch*/,
+ const char */*expect*/, va_list */*ap*/);
+
+/* --- @tvec_unkreg@ --- *
+ *
+ * Arguments: @struct tvec_state *tv@ = test-vector state
+ * @const char *name@ = register or pseudoregister name
+ *
+ * Returns: %$-1$%.
+ *
+ * Use: Reports an error that the register or pseudoregister is
+ * unrecognized.
+ */
+
+extern int tvec_unkreg(struct tvec_state */*tv*/, const char */*name*/);
+
+/* --- @tvec_dupreg@ --- *
+ *
+ * Arguments: @struct tvec_state *tv@ = test-vector state
+ * @const char *name@ = register or pseudoregister name
+ *
+ * Returns: %$-1$%.
+ *
+ * Use: Reports an error that the register or pseudoregister has been
+ * assigned already in the current test.
+ */
+
+extern int tvec_dupreg(struct tvec_state */*tv*/, const char */*name*/);
+
+/* --- @tvec_skipspc@ --- *
+ *
+ * Arguments: @struct tvec_state *tv@ = test-vector state
+ *
+ * Returns: ---
+ *
+ * Use: Advance over any whitespace characters other than newlines.
+ * This will stop at `;', end-of-file, or any other kind of
+ * non-whitespace; and it won't consume a newline.
+ */
+
+extern void tvec_skipspc(struct tvec_state */*tv*/);
+
+/* --- @tvec_flushtoeol@ --- *
+ *
+ * Arguments: @struct tvec_state *tv@ = test-vector state
+ * @unsigned f@ = flags (@TVFF_...@)
+ *
+ * Returns: Zero on success, %$-1$% on error.
+ *
+ * Use: Advance to the start of the next line, consuming the
+ * preceding newline.
+ *
+ * A syntax error is reported if no newline character is found,
+ * i.e., the file ends in mid-line. A syntax error is also
+ * reported if material other than whitespace or a comment is
+ * found before the end of the line end, and @TVFF_ALLOWANY@ is
+ * not set in @f@. The line number count is updated
+ * appropriately.
+ */
+
+#define TVFF_ALLOWANY 1u
+extern int tvec_flushtoeol(struct tvec_state */*tv*/, unsigned /*f*/);
+
+/* --- @tvec_nexttoken@ --- *
+ *
+ * Arguments: @struct tvec_state *tv@ = test-vector state
+ *
+ * Returns: Zero if there is a next token which can be read; %$-1$% if no
+ * token is available.
+ *
+ * Use: Advance to the next whitespace-separated token, which may be
+ * on the next line.
+ *
+ * Tokens are separated by non-newline whitespace, comments, and
+ * newlines followed by whitespace; a newline /not/ followed by
+ * whitespace instead begins the next assignment, and two
+ * newlines separated only by whitespace terminate the data for
+ * a test.
+ *
+ * If this function returns zero, then the next character in the
+ * file begins a suitable token which can be read and
+ * processed. If it returns %$-1$% then there is no such token,
+ * and the file position is left correctly. The line number
+ * count is updated appropriately.
+ */
+
+extern int tvec_nexttoken(struct tvec_state */*tv*/);
+
+/* --- @tvec_readword@, @tvec_readword_v@ --- *
+ *
+ * Arguments: @struct tvec_state *tv@ = test-vector state
+ * @dstr *d@ = string to append the word to
+ * @const char **p_inout@ = pointer into string, updated
+ * @const char *delims@ = additional delimiters to stop at
+ * @const char *expect@, @va_list ap@ = what was expected
+ *
+ * Returns: Zero on success, %$-1$% on failure.