#include "macros.h"
#include "quis.h"
#include "report.h"
+
#include "tvec.h"
+#include "tvec-bench.h"
+#include "tvec-output.h"
/*----- Common machinery --------------------------------------------------*/
return (maxlen);
}
+/* --- @print_ident@ --- *
+ *
+ * Arguments: @struct tvec_state *tv@ = test-vector state
+ * @unsigned style@ = style to use for register dumps
+ * @const struct gprintf_ops *gops@ = output operations
+ * @void *go@ = output state
+ *
+ * Returns: ---
+ *
+ * Use: Write a benchmark identification to the output.
+ */
+
+static void print_ident(struct tvec_state *tv, unsigned style,
+ const struct gprintf_ops *gops, void *go)
+{
+ const struct tvec_regdef *rd;
+ unsigned f = 0;
+
+#define f_any 1u
+
+ for (rd = tv->test->regs; rd->name; rd++)
+ if (rd->f&TVRF_ID) {
+ if (!(f&f_any)) f |= f_any;
+ else if (style&TVSF_RAW) gops->putch(go, ' ');
+ else gprintf(gops, go, ", ");
+ gprintf(gops, go, "%s", rd->name);
+ if (style&TVSF_RAW) gops->putch(go, '=');
+ else gprintf(gops, go, " = ");
+ rd->ty->dump(&TVEC_REG(tv, in, rd->i)->v, rd, style, gops, go);
+ }
+
+#undef f_any
+}
+
/*----- Output layout -----------------------------------------------------*/
/* We have two main jobs in output layout: trimming trailing blanks; and
#define HA_LOCSEP (HFG(BLUE)) /* location separator `:' */
#define HA_ERR (HFG(MAGENTA) | HAF_BOLD) /* error messages */
#define HA_NOTE (HFG(YELLOW)) /* notices */
+#define HA_INFO 0 /* information */
#define HA_UNKLEV (HFG(WHITE) | HBG(RED) | HAF_BOLD) /* unknown level */
#define HA_UNSET (HFG(YELLOW)) /* register not set */
#define HA_FOUND (HFG(RED)) /* incorrect output value */
struct human_output {
struct tvec_output _o; /* output base class */
struct tvec_state *tv; /* stashed testing state */
+ arena *a; /* arena for memory allocation */
struct layout lyt; /* output layout */
char *outbuf; size_t outsz; /* buffer for formatted output */
dstr scoreboard; /* history of test group results */
va_list ap;
va_start(ap, p);
- n = gprintf_memputf(&h->outbuf, &h->outsz, maxsz, p, ap);
+ n = gprintf_memputf(h->a, &h->outbuf, &h->outsz, maxsz, p, ap);
va_end(ap);
if (layout_string(&h->lyt, h->outbuf, n)) return (-1);
return (n);
/* --- @human_bsession@ --- *
*
- * Arguments: @struct tvec_output *o@ = output sink, secretly a @struct
- * human_output@
+ * Arguments: @struct tvec_output *o@ = output sink, secretly a
+ * @struct human_output@
* @struct tvec_state *tv@ = the test state producing output
*
* Returns: ---
/* --- @human_esession@ --- *
*
- * Arguments: @struct tvec_output *o@ = output sink, secretly a @struct
- * human_output@
+ * Arguments: @struct tvec_output *o@ = output sink, secretly a
+ * @struct human_output@
*
* Returns: Suggested exit code.
*
/* --- @human_bgroup@ --- *
*
- * Arguments: @struct tvec_output *o@ = output sink, secretly a @struct
- * human_output@
+ * Arguments: @struct tvec_output *o@ = output sink, secretly a
+ * @struct human_output@
*
* Returns: ---
*
/* --- @human_skipgroup@ --- *
*
- * Arguments: @struct tvec_output *o@ = output sink, secretly a @struct
- * human_output@
+ * Arguments: @struct tvec_output *o@ = output sink, secretly a
+ * @struct human_output@
* @const char *excuse@, @va_list *ap@ = reason for skipping the
* group, or null
*
/* --- @human_egroup@ --- *
*
- * Arguments: @struct tvec_output *o@ = output sink, secretly a @struct
- * human_output@
+ * Arguments: @struct tvec_output *o@ = output sink, secretly a
+ * @struct human_output@
*
* Returns: ---
*
/* --- @human_btest@ --- *
*
- * Arguments: @struct tvec_output *o@ = output sink, secretly a @struct
- * human_output@
+ * Arguments: @struct tvec_output *o@ = output sink, secretly a
+ * @struct human_output@
*
* Returns: ---
*
/* --- @human_outcome@, @human_skip@, @human_fail@ --- *
*
- * Arguments: @struct tvec_output *o@ = output sink, secretly a @struct
- * human_output@
+ * Arguments: @struct tvec_output *o@ = output sink, secretly a
+ * @struct human_output@
* @unsigned attr@ = attribute to apply to the outcome
* @const char *outcome@ = outcome string to report
* @const char *detail@, @va_list *ap@ = a detail message
/* --- @human_dumpreg@ --- *
*
- * Arguments: @struct tvec_output *o@ = output sink, secretly a @struct
- * human_output@
+ * Arguments: @struct tvec_output *o@ = output sink, secretly a
+ * @struct human_output@
* @unsigned disp@ = register disposition
* @const union tvec_regval *rv@ = register value
* @const struct tvec_regdef *rd@ = register definition
/* --- @human_etest@ --- *
*
- * Arguments: @struct tvec_output *o@ = output sink, secretly a @struct
- * human_output@
+ * Arguments: @struct tvec_output *o@ = output sink, secretly a
+ * @struct human_output@
* @unsigned outcome@ = the test outcome
*
* Returns: ---
}
}
-/* --- @human_bbench@ --- *
- *
- * Arguments: @struct tvec_output *o@ = output sink, secretly a @struct
- * human_output@
- * @const char *ident@ = identifying register values
- * @unsigned unit@ = measurement unit (@TVBU_...@)
- *
- * Returns: ---
- *
- * Use: Report that a benchmark has started.
- *
- * The human driver just prints the start of the benchmark
- * report.
- */
-
-static void human_bbench(struct tvec_output *o,
- const char *ident, unsigned unit)
-{
- struct human_output *h = (struct human_output *)o;
- struct tvec_state *tv = h->tv;
-
- clear_progress(h);
- gprintf(&human_printops, h, "%s %s: ", tv->test->name, ident);
- if (h->f&HOF_TTY) fflush(h->lyt.fp);
-}
-
-/* --- @human_ebench@ --- *
- *
- * Arguments: @struct tvec_output *o@ = output sink, secretly a @struct
- * human_output@
- * @const char *ident@ = identifying register values
- * @unsigned unit@ = measurement unit (@TVBU_...@)
- * @const struct bench_timing *tm@ = measurement
- *
- * Returns: ---
- *
- * Use: Report a benchmark's results
- *
- * The human driver just delegates to the default benchmark
- * reporting, via the layout machinery.
- */
-
-static void human_ebench(struct tvec_output *o,
- const char *ident, unsigned unit,
- const struct bench_timing *tm)
-{
- struct human_output *h = (struct human_output *)o;
-
- tvec_benchreport(&human_printops, h, unit, 0, tm);
- layout_char(&h->lyt, '\n');
-}
-
/* --- @human_report@ --- *
*
- * Arguments: @struct tvec_output *o@ = output sink, secretly a @struct
- * human_output@
+ * Arguments: @struct tvec_output *o@ = output sink, secretly a
+ * @struct human_output@
* @unsigned level@ = message level (@TVLEV_...@)
* @const char *msg@, @va_list *ap@ = format string and
* arguments
}
if (f&f_progress) show_progress(h);
+ dstr_destroy(&d);
+
#undef f_flush
#undef f_progress
}
+/* --- @human_bbench@ --- *
+ *
+ * Arguments: @struct tvec_output *o@ = output sink, secretly a
+ * @struct human_output@
+ * @const char *desc@ = adhoc test description
+ * @unsigned unit@ = measurement unit (@BTU_...@)
+ *
+ * Returns: ---
+ *
+ * Use: Report that a benchmark has started.
+ *
+ * The human driver just prints the start of the benchmark
+ * report.
+ */
+
+static void human_bbench(struct tvec_output *o,
+ const char *desc, unsigned unit)
+{
+ struct human_output *h = (struct human_output *)o;
+ struct tvec_state *tv = h->tv;
+
+ clear_progress(h);
+ gprintf(&human_printops, h, "%s ", tv->test->name);
+ if (desc) gprintf(&human_printops, h, "%s", desc);
+ else print_ident(tv, TVSF_COMPACT, &human_printops, h);
+ gprintf(&human_printops, h, ": ");
+ if (h->f&HOF_TTY) fflush(h->lyt.fp);
+}
+
+/* --- @human_ebench@ --- *
+ *
+ * Arguments: @struct tvec_output *o@ = output sink, secretly a
+ * @struct human_output@
+ * @const char *desc@ = adhoc test description
+ * @unsigned unit@ = measurement unit (@BTU_...@)
+ * @const struct bench_timing *t@ = measurement
+ *
+ * Returns: ---
+ *
+ * Use: Report a benchmark's results.
+ *
+ * The human driver just delegates to the default benchmark
+ * reporting, via the layout machinery.
+ */
+
+static void human_ebench(struct tvec_output *o,
+ const char *desc, unsigned unit,
+ const struct bench_timing *t)
+{
+ struct human_output *h = (struct human_output *)o;
+
+ tvec_benchreport(&human_printops, h, unit, 0, t);
+ layout_char(&h->lyt, '\n');
+}
+
+static const struct tvec_benchoutops human_benchops =
+ { human_bbench, human_ebench };
+
+/* --- @human_extend@ --- *
+ *
+ * Arguments: @struct tvec_output *o@ = output sink, secretly a
+ * @struct human_output@
+ * @const char *name@ = extension name
+ *
+ * Returns: A pointer to the extension implementation, or null.
+ */
+
+static const void *human_extend(struct tvec_output *o, const char *name)
+{
+ if (STRCMP(name, ==, TVEC_BENCHOUTEXT)) return (&human_benchops);
+ else return (0);
+}
+
/* --- @human_destroy@ --- *
*
- * Arguments: @struct tvec_output *o@ = output sink, secretly a @struct
- * human_output@
+ * Arguments: @struct tvec_output *o@ = output sink, secretly a
+ * @struct human_output@
*
* Returns: ---
*
destroy_layout(&h->lyt,
h->lyt.fp == stdout || h->lyt.fp == stderr ? 0 : DLF_CLOSE);
dstr_destroy(&h->scoreboard);
- xfree(h->outbuf); xfree(h);
+ x_free(h->a, h->outbuf); x_free(h->a, h);
}
static const struct tvec_outops human_ops = {
human_bsession, human_esession,
human_bgroup, human_skipgroup, human_egroup,
human_btest, human_skip, human_fail, human_dumpreg, human_etest,
- human_bbench, human_ebench,
- human_report,
- human_destroy
+ human_report, human_extend, human_destroy
};
/* --- @tvec_humanoutput@ --- *
struct human_output *h;
const char *p;
- h = xmalloc(sizeof(*h)); h->_o.ops = &human_ops;
+ XNEW(h); h->a = arena_global; h->_o.ops = &human_ops;
h->f = 0; h->attr = 0;
init_layout(&h->lyt, fp, 0);
struct machine_output {
struct tvec_output _o; /* output base class */
struct tvec_state *tv; /* stashed testing state */
+ arena *a; /* arena for memory allocation */
FILE *fp; /* output stream */
char *outbuf; size_t outsz; /* buffer for formatted output */
unsigned grpix, testix; /* group and test indices */
va_list ap;
va_start(ap, p);
- n = gprintf_memputf(&m->outbuf, &m->outsz, maxsz, p, ap);
+ n = gprintf_memputf(m->a, &m->outbuf, &m->outsz, maxsz, p, ap);
va_end(ap);
return (machine_writem(m, m->outbuf, n));
}
const char *q;
for (q = p; *q; q++)
- if (!ISPRINT(*q)) goto quote;
+ if (!ISPRINT(*q) || ISSPACE(*q)) goto quote;
fputs(p, m->fp); return;
quote:
putc('"', m->fp); machine_writem(m, p, strlen(p)); putc('"', m->fp);
/* --- @machine_bsession@ --- *
*
- * Arguments: @struct tvec_output *o@ = output sink, secretly a @struct
- * machine_output@
+ * Arguments: @struct tvec_output *o@ = output sink, secretly a
+ * @struct machine_output@
* @struct tvec_state *tv@ = the test state producing output
*
* Returns: ---
/* --- @machine_esession@ --- *
*
- * Arguments: @struct tvec_output *o@ = output sink, secretly a @struct
- * machine_output@
+ * Arguments: @struct tvec_output *o@ = output sink, secretly a
+ * @struct machine_output@
*
* Returns: Suggested exit code.
*
/* --- @machine_bgroup@ --- *
*
- * Arguments: @struct tvec_output *o@ = output sink, secretly a @struct
- * machine_output@
+ * Arguments: @struct tvec_output *o@ = output sink, secretly a
+ * @struct machine_output@
*
* Returns: ---
*
/* --- @machine_skipgroup@ --- *
*
- * Arguments: @struct tvec_output *o@ = output sink, secretly a @struct
- * machine_output@
+ * Arguments: @struct tvec_output *o@ = output sink, secretly a
+ * @struct machine_output@
* @const char *excuse@, @va_list *ap@ = reason for skipping the
* group, or null
*
struct machine_output *m = (struct machine_output *)o;
struct tvec_state *tv = m->tv;
- fputs("BGROUP ", m->fp);
+ fputs("SKIPGRP ", m->fp);
machine_maybe_quote(m, tv->test->name);
if (excuse) {
fputs(" \"", m->fp);
/* --- @machine_egroup@ --- *
*
- * Arguments: @struct tvec_output *o@ = output sink, secretly a @struct
- * machine_output@
+ * Arguments: @struct tvec_output *o@ = output sink, secretly a
+ * @struct machine_output@
*
* Returns: ---
*
struct machine_output *m = (struct machine_output *)o;
struct tvec_state *tv = m->tv;
- fputs("EGROUP ", m->fp); machine_maybe_quote(m, tv->test->name);
- putc(' ', m->fp); machine_show_stats(m, tv->curr);
- putc('\n', m->fp);
+ if (!(tv->f&TVSF_SKIP)) {
+ fputs("EGROUP ", m->fp); machine_maybe_quote(m, tv->test->name);
+ putc(' ', m->fp); machine_show_stats(m, tv->curr);
+ putc('\n', m->fp);
+ }
}
/* --- @machine_btest@ --- *
*
- * Arguments: @struct tvec_output *o@ = output sink, secretly a @struct
- * machine_output@
+ * Arguments: @struct tvec_output *o@ = output sink, secretly a
+ * @struct machine_output@
*
* Returns: ---
*
static void machine_report_location(struct machine_output *m,
const char *file, unsigned lno)
- { machine_maybe_quote(m, file); fprintf(m->fp, ":%u", lno); }
+{
+ if (file) {
+ putc(' ', m->fp);
+ machine_maybe_quote(m, file);
+ fprintf(m->fp, ":%u", lno);
+ }
+}
/* --- @machine_outcome@, @machine_skip@, @machine_fail@ --- *
*
- * Arguments: @struct tvec_output *o@ = output sink, secretly a @struct
- * machine_output@
+ * Arguments: @struct tvec_output *o@ = output sink, secretly a
+ * @struct machine_output@
* @const char *outcome@ = outcome string to report
* @const char *detail@, @va_list *ap@ = a detail message
* @const char *excuse@, @va_list *ap@ = reason for skipping the
struct machine_output *m = (struct machine_output *)o;
struct tvec_state *tv = m->tv;
- fprintf(m->fp, "%s %u ", outcome, m->testix);
+ fprintf(m->fp, "%s %u", outcome, m->testix);
machine_report_location(m, tv->infile, tv->test_lno);
if (detail)
{ putc(' ', m->fp); vgprintf(&machine_printops, m, detail, ap); }
/* --- @machine_dumpreg@ --- *
*
- * Arguments: @struct tvec_output *o@ = output sink, secretly a @struct
- * machine_output@
+ * Arguments: @struct tvec_output *o@ = output sink, secretly a
+ * @struct machine_output@
* @unsigned disp@ = register disposition
* @const union tvec_regval *rv@ = register value
* @const struct tvec_regdef *rd@ = register definition
*
* Use: Dump a register.
*
- * The TAP driver applies highlighting to mismatching output
+ * The machine driver applies highlighting to mismatching output
* registers, but otherwise delegates to the register type
- * handler and the layout machinery. The result is that the
- * register dump is marked as a comment and indented.
+ * handler.
*/
static void machine_dumpreg(struct tvec_output *o,
}
if (f&f_reg) fprintf(m->fp, "%s = ", rd->name);
- rd->ty->dump(rv, rd, TVSF_RAW, &file_printops, m->fp);
+ if (!rv) fputs("#unset", m->fp);
+ else rd->ty->dump(rv, rd, TVSF_RAW, &file_printops, m->fp);
if (f&f_nl) putc('\n', m->fp);
#undef f_reg
/* --- @machine_etest@ --- *
*
- * Arguments: @struct tvec_output *o@ = output sink, secretly a @struct
- * machine_output@
+ * Arguments: @struct tvec_output *o@ = output sink, secretly a
+ * @struct machine_output@
* @unsigned outcome@ = the test outcome
*
* Returns: ---
*
* Use: Report that a test has finished.
*
- * The TAP driver reports the outcome of the test, if that's not
- * already decided.
+ * The machine driver reports the outcome of the test, if that's
+ * not already decided.
*/
static void machine_etest(struct tvec_output *o, unsigned outcome)
m->testix++; m->f &= ~MF_BENCH;
}
+/* --- @machine_report@ --- *
+ *
+ * Arguments: @struct tvec_output *o@ = output sink, secretly a
+ * @struct machine_output@
+ * @unsigned level@ = message level (@TVLEV_...@)
+ * @const char *msg@, @va_list *ap@ = format string and
+ * arguments
+ *
+ * Returns: ---
+ *
+ * Use: Report a message to the user.
+ *
+ * Each report level has its own output tag
+ */
+
+static void machine_report(struct tvec_output *o, unsigned level,
+ const char *msg, va_list *ap)
+{
+ struct machine_output *m = (struct machine_output *)o;
+ struct tvec_state *tv = m->tv;
+ const char *p;
+
+ for (p = tvec_strlevel(level); *p; p++) putc(TOUPPER(*p), m->fp);
+ machine_report_location(m, tv->infile, tv->lno);
+ fputs(" \"", m->fp); vgprintf(&machine_printops, m, msg, ap);
+ putc('"', m->fp);
+ putc('\n', m->fp);
+}
+
/* --- @machine_bbench@ --- *
*
- * Arguments: @struct tvec_output *o@ = output sink, secretly a @struct
- * machine_output@
- * @const char *ident@ = identifying register values
- * @unsigned unit@ = measurement unit (@TVBU_...@)
+ * Arguments: @struct tvec_output *o@ = output sink, secretly a
+ * @struct machine_output@
+ * @const char *desc@ = adhoc test description
+ * @unsigned unit@ = measurement unit (@BTU_...@)
*
* Returns: ---
*
* Use: Report that a benchmark has started.
*
- * The TAP driver does nothing here. All of the reporting
+ * The machine driver does nothing here. All of the reporting
* happens in @machine_ebench@.
*/
static void machine_bbench(struct tvec_output *o,
- const char *ident, unsigned unit)
+ const char *desc, unsigned unit)
{ ; }
/* --- @machine_ebench@ --- *
*
- * Arguments: @struct tvec_output *o@ = output sink, secretly a @struct
- * machine_output@
- * @const char *ident@ = identifying register values
- * @unsigned unit@ = measurement unit (@TVBU_...@)
- * @const struct bench_timing *tm@ = measurement
+ * Arguments: @struct tvec_output *o@ = output sink, secretly a
+ * @struct machine_output@
+ * @const char *desc@ = adhoc test description
+ * @unsigned unit@ = measurement unit (@BTU_...@)
+ * @const struct bench_timing *t@ = measurement
*
* Returns: ---
*
- * Use: Report a benchmark's results
+ * Use: Report a benchmark's results.
*
- * The TAP driver just delegates to the default benchmark
- * reporting, via the layout machinery so that the result is
- * printed as a comment.
+ * The machine driver prints the result as a `BENCH' output
+ * line, in raw format.
*/
static void machine_ebench(struct tvec_output *o,
- const char *ident, unsigned unit,
- const struct bench_timing *tm)
+ const char *desc, unsigned unit,
+ const struct bench_timing *t)
{
struct machine_output *m = (struct machine_output *)o;
struct tvec_state *tv = m->tv;
- fprintf(m->fp, "BENCH %u ", m->testix);
+ fprintf(m->fp, "BENCH %u", m->testix);
machine_report_location(m, tv->infile, tv->test_lno);
- fprintf(m->fp, " %s: ", ident);
- tvec_benchreport(&file_printops, m->fp, unit, TVSF_RAW, tm);
+ putc(' ', m->fp);
+ if (desc) machine_maybe_quote(m, desc);
+ else print_ident(tv, TVSF_RAW, &file_printops, m->fp);
+ fputs(": ", m->fp);
+ tvec_benchreport(&file_printops, m->fp, unit, TVSF_RAW, t);
putc('\n', m->fp); m->f |= MF_BENCH;
}
-/* --- @machine_report@ --- *
- *
- * Arguments: @struct tvec_output *o@ = output sink, secretly a @struct
- * machine_output@
- * @unsigned level@ = message level (@TVLEV_...@)
- * @const char *msg@, @va_list *ap@ = format string and
- * arguments
- *
- * Returns: ---
+static const struct tvec_benchoutops machine_benchops =
+ { machine_bbench, machine_ebench };
+
+/* --- @machine_extend@ --- *
*
- * Use: Report a message to the user.
+ * Arguments: @struct tvec_output *o@ = output sink, secretly a
+ * @struct machine_output@
+ * @const char *name@ = extension name
*
- * Messages are reported as comments, so that they can be
- * accumulated by the reader. An error will cause a later
- * bailout or, if we crash before then, a missing plan line,
- * either of which will cause the reader to report a serious
- * problem.
+ * Returns: A pointer to the extension implementation, or null.
*/
-static void machine_report(struct tvec_output *o, unsigned level,
- const char *msg, va_list *ap)
+static const void *machine_extend(struct tvec_output *o, const char *name)
{
- struct machine_output *m = (struct machine_output *)o;
- const char *p;
-
- for (p = tvec_strlevel(level); *p; p++) putc(TOUPPER(*p), m->fp);
- putc(' ', m->fp);
- putc('"', m->fp);
- vgprintf(&machine_printops, m, msg, ap);
- putc('"', m->fp);
- putc('\n', m->fp);
+ if (STRCMP(name, ==, TVEC_BENCHOUTEXT)) return (&machine_benchops);
+ else return (0);
}
/* --- @machine_destroy@ --- *
*
- * Arguments: @struct tvec_output *o@ = output sink, secretly a @struct
- * machine_output@
+ * Arguments: @struct tvec_output *o@ = output sink, secretly a
+ * @struct machine_output@
*
* Returns: ---
*
struct machine_output *m = (struct machine_output *)o;
if (m->fp != stdout && m->fp != stderr) fclose(m->fp);
- xfree(m->outbuf); xfree(m);
+ x_free(m->a, m->outbuf); x_free(m->a, m);
}
static const struct tvec_outops machine_ops = {
machine_bsession, machine_esession,
machine_bgroup, machine_skipgroup, machine_egroup,
machine_btest, machine_skip, machine_fail, machine_dumpreg, machine_etest,
- machine_bbench, machine_ebench,
- machine_report,
- machine_destroy
+ machine_report, machine_extend, machine_destroy
};
/* --- @tvec_machineoutput@ --- *
{
struct machine_output *m;
- m = xmalloc(sizeof(*m)); m->_o.ops = &machine_ops;
- m->fp = fp; m->outbuf = 0; m->outsz = 0; m->testix = 0;
+ XNEW(m); m->a = arena_global; m->_o.ops = &machine_ops;
+ m->f = 0; m->fp = fp; m->outbuf = 0; m->outsz = 0; m->testix = 0;
return (&m->_o);
}
struct tap_output {
struct tvec_output _o; /* output base class */
struct tvec_state *tv; /* stashed testing state */
+ arena *a; /* arena for memory allocation */
struct layout lyt; /* output layout */
char *outbuf; size_t outsz; /* buffer for formatted output */
unsigned grpix, testix; /* group and test indices */
va_list ap;
va_start(ap, p);
- n = gprintf_memputf(&t->outbuf, &t->outsz, maxsz, p, ap);
+ n = gprintf_memputf(t->a, &t->outbuf, &t->outsz, maxsz, p, ap);
va_end(ap);
if (layout_string(&t->lyt, t->outbuf, n)) return (-1);
return (n);
/* --- @tap_bsession@ --- *
*
- * Arguments: @struct tvec_output *o@ = output sink, secretly a @struct
- * tap_output@
+ * Arguments: @struct tvec_output *o@ = output sink, secretly a
+ * @struct tap_output@
* @struct tvec_state *tv@ = the test state producing output
*
* Returns: ---
/* --- @tap_esession@ --- *
*
- * Arguments: @struct tvec_output *o@ = output sink, secretly a @struct
- * tap_output@
+ * Arguments: @struct tvec_output *o@ = output sink, secretly a
+ * @struct tap_output@
*
* Returns: Suggested exit code.
*
/* --- @tap_bgroup@ --- *
*
- * Arguments: @struct tvec_output *o@ = output sink, secretly a @struct
- * tap_output@
+ * Arguments: @struct tvec_output *o@ = output sink, secretly a
+ * @struct tap_output@
*
* Returns: ---
*
/* --- @tap_skipgroup@ --- *
*
- * Arguments: @struct tvec_output *o@ = output sink, secretly a @struct
- * tap_output@
+ * Arguments: @struct tvec_output *o@ = output sink, secretly a
+ * @struct tap_output@
* @const char *excuse@, @va_list *ap@ = reason for skipping the
* group, or null
*
/* --- @tap_egroup@ --- *
*
- * Arguments: @struct tvec_output *o@ = output sink, secretly a @struct
- * tap_output@
+ * Arguments: @struct tvec_output *o@ = output sink, secretly a
+ * @struct tap_output@
*
* Returns: ---
*
/* --- @tap_btest@ --- *
*
- * Arguments: @struct tvec_output *o@ = output sink, secretly a @struct
- * tap_output@
+ * Arguments: @struct tvec_output *o@ = output sink, secretly a
+ * @struct tap_output@
*
* Returns: ---
*
/* --- @tap_outcome@, @tap_skip@, @tap_fail@ --- *
*
- * Arguments: @struct tvec_output *o@ = output sink, secretly a @struct
- * tap_output@
+ * Arguments: @struct tvec_output *o@ = output sink, secretly a
+ * @struct tap_output@
* @const char *head, *tail@ = outcome strings to report
* @const char *detail@, @va_list *ap@ = a detail message
* @const char *excuse@, @va_list *ap@ = reason for skipping the
/* --- @tap_dumpreg@ --- *
*
- * Arguments: @struct tvec_output *o@ = output sink, secretly a @struct
- * tap_output@
+ * Arguments: @struct tvec_output *o@ = output sink, secretly a
+ * @struct tap_output@
* @unsigned disp@ = register disposition
* @const union tvec_regval *rv@ = register value
* @const struct tvec_regdef *rd@ = register definition
/* --- @tap_etest@ --- *
*
- * Arguments: @struct tvec_output *o@ = output sink, secretly a @struct
- * tap_output@
+ * Arguments: @struct tvec_output *o@ = output sink, secretly a
+ * @struct tap_output@
* @unsigned outcome@ = the test outcome
*
* Returns: ---
}
}
-/* --- @tap_bbench@ --- *
- *
- * Arguments: @struct tvec_output *o@ = output sink, secretly a @struct
- * tap_output@
- * @const char *ident@ = identifying register values
- * @unsigned unit@ = measurement unit (@TVBU_...@)
- *
- * Returns: ---
- *
- * Use: Report that a benchmark has started.
- *
- * The TAP driver does nothing here. All of the reporting
- * happens in @tap_ebench@.
- */
-
-static void tap_bbench(struct tvec_output *o,
- const char *ident, unsigned unit)
- { ; }
-
-/* --- @tap_ebench@ --- *
- *
- * Arguments: @struct tvec_output *o@ = output sink, secretly a @struct
- * tap_output@
- * @const char *ident@ = identifying register values
- * @unsigned unit@ = measurement unit (@TVBU_...@)
- * @const struct bench_timing *tm@ = measurement
- *
- * Returns: ---
- *
- * Use: Report a benchmark's results
- *
- * The TAP driver just delegates to the default benchmark
- * reporting, via the layout machinery so that the result is
- * printed as a comment.
- */
-
-static void tap_ebench(struct tvec_output *o,
- const char *ident, unsigned unit,
- const struct bench_timing *tm)
-{
- struct tap_output *t = (struct tap_output *)o;
- struct tvec_state *tv = t->tv;
-
- set_layout_prefix(&t->lyt, " ## ");
- gprintf(&tap_printops, t, "%s %s: ", tv->test->name, ident);
- tvec_benchreport(&tap_printops, t, unit, 0, tm);
- layout_char(&t->lyt, '\n');
-}
-
/* --- @tap_report@ --- *
*
- * Arguments: @struct tvec_output *o@ = output sink, secretly a @struct
- * tap_output@
+ * Arguments: @struct tvec_output *o@ = output sink, secretly a
+ * @struct tap_output@
* @unsigned level@ = message level (@TVLEV_...@)
* @const char *msg@, @va_list *ap@ = format string and
* arguments
layout_char(&t->lyt, '\n');
}
+/* --- @tap_extend@ --- *
+ *
+ * Arguments: @struct tvec_output *o@ = output sink, secretly a
+ * @struct tap_output@
+ * @const char *name@ = extension name
+ *
+ * Returns: A pointer to the extension implementation, or null.
+ */
+
+static const void *tap_extend(struct tvec_output *o, const char *name)
+ { return (0); }
+
/* --- @tap_destroy@ --- *
*
- * Arguments: @struct tvec_output *o@ = output sink, secretly a @struct
- * tap_output@
+ * Arguments: @struct tvec_output *o@ = output sink, secretly a
+ * @struct tap_output@
*
* Returns: ---
*
destroy_layout(&t->lyt,
t->lyt.fp == stdout || t->lyt.fp == stderr ? 0 : DLF_CLOSE);
- xfree(t->outbuf); xfree(t);
+ x_free(t->a, t->outbuf); x_free(t->a, t);
}
static const struct tvec_outops tap_ops = {
tap_bsession, tap_esession,
tap_bgroup, tap_skipgroup, tap_egroup,
tap_btest, tap_skip, tap_fail, tap_dumpreg, tap_etest,
- tap_bbench, tap_ebench,
- tap_report,
- tap_destroy
+ tap_report, tap_extend, tap_destroy
};
/* --- @tvec_tapoutput@ --- *
{
struct tap_output *t;
- t = xmalloc(sizeof(*t)); t->_o.ops = &tap_ops;
+ XNEW(t); t->a = arena_global; t->_o.ops = &tap_ops;
init_layout(&t->lyt, fp, 0);
t->outbuf = 0; t->outsz = 0;
return (&t->_o);
* 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.
*/
struct tvec_output *tvec_dfltout(FILE *fp)
if (ttyp == -1) ttyp = isatty(fileno(fp));
if (ttyp) return (tvec_humanoutput(fp));
- else return (tvec_tapoutput(fp));
+ else return (tvec_machineoutput(fp));
}
/*----- That's all, folks -------------------------------------------------*/