X-Git-Url: https://www.chiark.greenend.org.uk/ucgi/~mdw/git/mLib/blobdiff_plain/4b4bc64da0af7b5d69a65dab06bff6483e67e385..98ff9295493ed2b990f30768e11b18b6bc65eaa4:/test/tvec-output.c diff --git a/test/tvec-output.c b/test/tvec-output.c index 014423e..40ab769 100644 --- a/test/tvec-output.c +++ b/test/tvec-output.c @@ -44,6 +44,7 @@ #include "macros.h" #include "quis.h" #include "report.h" +#include "tty.h" #include "ttycolour.h" #include "tvec.h" @@ -80,7 +81,7 @@ static const char *regdisp(unsigned disp) * @const char *what, ...@ = format string describing where the * setting came from * - * Returns: @0@ if the string, or variable, is set to something + * Returns: @0@ if the string, or variable, is set to something * falseish, @1@ if it's set to something truish, or @dflt@ * otherwise. */ @@ -481,15 +482,57 @@ static int layout_string(struct layout *lyt, const char *p, size_t sz) /*----- Human-readable output ---------------------------------------------*/ +#define GENATTR(want, attrs, fgspc, fgcol, bgspc, bgcol) \ + { (want), (want), \ + { ((fgspc) << TTAF_FGSPCSHIFT) | \ + ((bgspc) << TTAF_BGSPCSHIFT) | (attrs), \ + 0, (fgcol), (bgcol) } } + +#define FGBG(want, attrs, fgcol, bgcol) \ + GENATTR(want | TTACF_FG | TTACF_BG, attrs, \ + TTCSPC_1BPCBR, TTCOL_##fgcol, TTCSPC_1BPCBR, TTCOL_##bgcol) +#define FG(want, attrs, fgcol) \ + GENATTR(want | TTACF_FG, attrs, \ + TTCSPC_1BPCBR, TTCOL_##fgcol, TTCSPC_NONE, 0) +#define BG(want, attrs, bgcol) \ + GENATTR(want | TTACF_BG, attrs, \ + TTCSPC_NONE, 0, TTCSPC_1BPCBR, TTCOL_##bgcol) +#define ATTR(want, attrs) \ + GENATTR(want, attrs, TTCSPC_NONE, 0, TTCSPC_NONE, 0) + +#define BOLD (TTWT_BOLD << TTAF_WTSHIFT) + +static const struct tty_attrlist + loc_attrs[] = { FG(0, 0, CYN), TTY_ATTRLIST_CLEAR }, + locsep_attrs[] = { FG(0, 0, BRBLU), TTY_ATTRLIST_CLEAR }, + note_attrs[] = { FG(0, 0, YLW), TTY_ATTRLIST_CLEAR }, + err_attrs[] = { FG(0, BOLD, MGN), TTY_ATTRLIST_CLEAR }, + unklv_attrs[] = { FGBG(0, BOLD, BRWHT, BRRED), ATTR(0, TTAF_INVV) }, + vfound_attrs[] = { FG(0, 0, RED), TTY_ATTRLIST_CLEAR }, + vexpect_attrs[] = { FG(0, 0, GRN), TTY_ATTRLIST_CLEAR }, + vunset_attrs[] = { FG(0, 0, YLW), TTY_ATTRLIST_CLEAR }, + lose_attrs[] = { FG(0, BOLD, RED), ATTR(0, BOLD | TTAF_INVV) }, + skip_attrs[] = { FG(0, 0, YLW), TTY_ATTRLIST_CLEAR }, + xfail_attrs[] = { FG(0, BOLD, BLU), ATTR(0, BOLD) }, + win_attrs[] = { FG(0, 0, GRN), TTY_ATTRLIST_CLEAR }, + sblose_attrs[] = { FG(0, BOLD, RED), ATTR(0, BOLD) }; + +#undef GENATTR +#undef FGBG +#undef FG +#undef BG +#undef ATTR +#undef BOLD + /* Predefined attributes. */ #define HIGHLIGHTS(_st, _) \ - _(_st, LOCFN, "lf", TC_FG(CYAN)) /* location filename */ \ - _(_st, LOCLN, "ln", TC_FG(CYAN)) /* location line number */ \ - _(_st, LOCSEP, "ls", TC_FG(BRBLUE)) /* location separator `:' */ \ + _(_st, LOCFN, "lf", loc_attrs) /* location filename */ \ + _(_st, LOCLN, "ln", loc_attrs) /* location line number */ \ + _(_st, LOCSEP, "ls", locsep_attrs) /* location separator `:' */ \ _(_st, INFO, "mi", 0) /* information */ \ - _(_st, NOTE, "mn", TC_FG(YELLOW)) /* notices */ \ - _(_st, ERR, "me", TC_FG(MAGENTA) | TCAF_BOLD) /* error messages */ \ - _(_st, UNKLEV, "mu", TC_FG(WHITE) | TC_BG(RED) | TCAF_BOLD) \ + _(_st, NOTE, "mn", note_attrs) /* notices */ \ + _(_st, ERR, "me", err_attrs) /* error messages */ \ + _(_st, UNKLV, "mu", unklv_attrs) /* unknown-level messages */ \ _(_st, DSINPUT, "di", 0) /* disposition for input value */ \ _(_st, DSOUTPUT, "do", 0) /* ... unsolicited output */ \ _(_st, DSMATCH, "dm", 0) /* ... matching output */ \ @@ -503,16 +546,16 @@ static int layout_string(struct layout *lyt, const char *p, size_t sz) _(_st, VINPUT, "vi", 0) /* input value */ \ _(_st, VOUTPUT, "vo", 0) /* unsolicited output value */ \ _(_st, VMATCH, "vm", 0) /* matching output value */ \ - _(_st, VFOUND, "vf", TC_FG(BRRED)) /* incorrect output value */ \ - _(_st, VEXPECT, "vx", TC_FG(GREEN)) /* reference output value */ \ - _(_st, VUNSET, "vu", TC_FG(YELLOW)) /* register not set */ \ - _(_st, LOSE, "ol", TC_FG(RED) | TCAF_BOLD) /* report failure */ \ - _(_st, SKIP, "os", TC_FG(YELLOW)) /* report a skipped test/group */ \ - _(_st, XFAIL, "ox", TC_FG(BLUE) | TCAF_BOLD) /* report expected fail */ \ - _(_st, WIN, "ow", TC_FG(GREEN)) /* report success */ \ - _(_st, SBLOSE, "sl", TC_FG(RED) | TCAF_BOLD) /* scoreboard failure */ \ - _(_st, SBSKIP, "ss", TC_FG(YELLOW)) /* scoreboard skipped test */ \ - _(_st, SBXFAIL, "sx", TC_FG(BLUE) | TCAF_BOLD) /* scoreboard xfail */ \ + _(_st, VFOUND, "vf", vfound_attrs) /* incorrect output value */ \ + _(_st, VEXPECT, "vx", vexpect_attrs) /* reference output value */ \ + _(_st, VUNSET, "vu", vunset_attrs) /* register not set */ \ + _(_st, LOSE, "ol", lose_attrs) /* report failure */ \ + _(_st, SKIP, "os", skip_attrs) /* report a skipped test/group */ \ + _(_st, XFAIL, "ox", xfail_attrs) /* report expected fail */ \ + _(_st, WIN, "ow", win_attrs) /* report success */ \ + _(_st, SBLOSE, "sl", sblose_attrs) /* scoreboard failure */ \ + _(_st, SBSKIP, "ss", skip_attrs) /* scoreboard skipped test */ \ + _(_st, SBXFAIL, "sx", xfail_attrs) /* scoreboard xfail */ \ _(_st, SBWIN, "sw", 0) /* scoreboard success */ TTYCOLOUR_DEFENUM(HIGHLIGHTS, HL_); @@ -525,11 +568,11 @@ struct human_output { struct tvec_output _o; /* output base class */ struct tvec_state *tv; /* stashed testing state */ arena *a; /* arena for memory allocation */ + struct tty *tty; /* output terminal, or null */ struct layout lyt; /* output layout */ char *outbuf; size_t outsz; /* buffer for formatted output */ dstr scoreboard; /* history of test group results */ - unsigned short attr[HL__LIMIT]; /* highlight attribute map */ - struct ttycolour_state tc; /* terminal colour state */ + struct tty_attr attr[HL__LIMIT]; /* highlight attribute map */ int maxlen; /* longest register name */ unsigned f; /* flags */ /* bits 0--7 from @TVHF_...@ */ @@ -552,7 +595,7 @@ static void setattr_common(struct human_output *h, const struct gprintf_ops *gops, void *go, int hl) { if (h->f&TVHF_COLOUR) - ttycolour_setattr(gops, go, &h->tc, hl < 0 ? 0 : h->attr[hl]); + tty_setattrg(h->tty, gops, go, hl >= 0 ? &h->attr[hl] : 0); } static void setattr(struct human_output *h, int hl) @@ -1018,7 +1061,7 @@ static void human_etest(struct tvec_output *o, unsigned outcome) * * Arguments: @struct tvec_output *o@ = output sink, secretly a * @struct human_output@ - * @unsigned level@ = message level (@TVLEV_...@) + * @unsigned level@ = message level (@TVLV_...@) * @const char *msg@, @va_list *ap@ = format string and * arguments * @@ -1045,9 +1088,9 @@ static void human_report(struct tvec_output *o, unsigned level, switch (level) { #define CASE(tag, name, val) \ - case TVLEV_##tag: levstr = name; levhl = HL_##tag; break; + case TVLV_##tag: levstr = name; levhl = HL_##tag; break; TVEC_LEVELS(CASE) - default: levstr = "??"; levhl = HL_UNKLEV; break; + default: levstr = "??"; levhl = HL_UNKLV; break; } if (h->f&HOF_PROGRESS) { clear_progress(h); f |= f_progress; } @@ -1157,6 +1200,7 @@ static void human_destroy(struct tvec_output *o) { struct human_output *h = (struct human_output *)o; + tty_close(h->tty); destroy_layout(&h->lyt, h->lyt.fp == stdout || h->lyt.fp == stderr ? 0 : DLF_CLOSE); dstr_destroy(&h->scoreboard); @@ -1205,7 +1249,6 @@ static const struct tvec_outops human_ops = { struct tvec_output *tvec_humanoutput(FILE *fp, unsigned f, unsigned m) { struct human_output *h; - const char *p; struct stat st_out, st_err; int rc_out, rc_err; @@ -1215,7 +1258,7 @@ struct tvec_output *tvec_humanoutput(FILE *fp, unsigned f, unsigned m) assert(!(f&~m)); if (!(m&TVHF_TTY)) - switch (getenv_boolean("TVEC_TTY", -1)) { + switch (getenv_boolean("MLIB_TVEC_TTY", -1)) { case 1: f |= TVHF_TTY; break; case 0: break; default: @@ -1223,14 +1266,12 @@ struct tvec_output *tvec_humanoutput(FILE *fp, unsigned f, unsigned m) break; } if (!(m&TVHF_COLOUR)) - switch (getenv_boolean("TVEC_COLOUR", -1)) { + switch (getenv_boolean("MLIB_TVEC_COLOUR", -1)) { case 1: f |= TVHF_COLOUR; break; case 0: break; default: - if (f&TVHF_TTY) { - p = getenv("TERM"); - if (p && STRCMP(p, !=, "dumb")) f |= TVHF_COLOUR; - } + if (ttycolour_enablep((f&TVHF_TTY ? TCEF_TTY : 0) | TCEF_DFLT)) + f |= TVHF_COLOUR; break; } @@ -1252,10 +1293,15 @@ struct tvec_output *tvec_humanoutput(FILE *fp, unsigned f, unsigned m) h->f = f; /* Initialize the colour tables. */ - if (h->f&TVHF_COLOUR) { - ttycolour_config(h->attr, "TVEC_COLOURS", TCIF_GETENV | TCIF_REPORT, - hltab); - ttycolour_init(&h->tc); + if (!(h->f&TVHF_COLOUR)) + h->tty = 0; + else { + h->tty = tty_open(fp, TTF_BORROW, 0); + if (!h->tty) + h->f &= ~TVHF_COLOUR; + else + ttycolour_config(h->attr, "MLIB_TVEC_COLOURS", + TCIF_GETENV | TCIF_REPORT, h->tty, hltab); } init_layout(&h->lyt, fp, 0); @@ -1672,7 +1718,7 @@ static void machine_etest(struct tvec_output *o, unsigned outcome) * * Arguments: @struct tvec_output *o@ = output sink, secretly a * @struct machine_output@ - * @unsigned level@ = message level (@TVLEV_...@) + * @unsigned level@ = message level (@TVLV_...@) * @const char *msg@, @va_list *ap@ = format string and * arguments * @@ -2123,7 +2169,7 @@ static void tap_etest(struct tvec_output *o, unsigned outcome) * * Arguments: @struct tvec_output *o@ = output sink, secretly a * @struct tap_output@ - * @unsigned level@ = message level (@TVLEV_...@) + * @unsigned level@ = message level (@TVLV_...@) * @const char *msg@, @va_list *ap@ = format string and * arguments * @@ -2504,7 +2550,7 @@ static void am_etest(struct tvec_output *o, unsigned outcome) * * Arguments: @struct tvec_output *o@ = output sink, secretly a * @struct automake_output@ - * @unsigned level@ = message level (@TVLEV_...@) + * @unsigned level@ = message level (@TVLV_...@) * @const char *msg@, @va_list *ap@ = format string and * arguments * @@ -2664,10 +2710,10 @@ struct tvec_output *tvec_amoutput(const struct tvec_amargs *a) struct tvec_output *tvec_dfltoutput(FILE *fp) { - int ttyp = getenv_boolean("TVEC_TTY", -1); + int ttyp = getenv_boolean("MLIB_TVEC_TTY", -1); if (ttyp == -1) ttyp = isatty(fileno(fp)); - if (ttyp) return (tvec_humanoutput(fp, 0, 0)); + if (ttyp) return (tvec_humanoutput(fp, TVHF_TTY, TVHF_TTY)); else return (tvec_machineoutput(fp)); }