+/* --- @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).
+ */
+
+int tvec_syntax(struct tvec_state *tv, int ch, const char *expect, ...)
+{
+ va_list ap;
+
+ va_start(ap, expect); tvec_syntax_v(tv, ch, expect, &ap); va_end(ap);
+ return (-1);
+}
+
+int tvec_syntax_v(struct tvec_state *tv, int ch,
+ const char *expect, va_list *ap)
+{
+ dstr d = DSTR_INIT;
+ char found[8];
+
+ switch (ch) {
+ case EOF: strcpy(found, "#eof"); break;
+ case '\n': strcpy(found, "#eol"); ungetc(ch, tv->fp); break;
+ default:
+ if (isprint(ch)) sprintf(found, "`%c'", ch);
+ else sprintf(found, "#\\x%02x", ch);
+ break;
+ }
+ dstr_vputf(&d, expect, ap);
+ tvec_error(tv, "syntax error: expected %s but found %s", d.buf, found);
+ dstr_destroy(&d); return (-1);
+}
+
+/* --- @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.
+ */
+
+int tvec_dupreg(struct tvec_state *tv, const char *name)
+ { return (tvec_error(tv, "register `%s' is already set", 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.
+ */