const char *encodemap, \
const signed char *decodemap) \
{ \
- ctxn##_codec *bc = CREATE(ctxn##_codec); \
+ ctxn##_codec *bc; \
+ \
+ NEW(bc); \
bc->c.ops = ops; \
bc->ctx.acc = 0; \
bc->ctx.qsz = (flags & ctxn##_FLAGMASK) ^ ctxn##_FLAGXOR; \
static codec *encoder(unsigned flags, const char *indent, unsigned maxlen)
{
- null_codec *nc = CREATE(null_codec);
+ null_codec *nc;
+
+ NEW(nc);
nc->c.ops = &ops;
return (&nc->c);
}
static codec *decoder(unsigned flags)
{
- null_codec *nc = CREATE(null_codec);
+ null_codec *nc;
+
+ NEW(nc);
nc->c.ops = &ops;
return (&nc->c);
}
float) var=FLT ;;
double) var=DBL ;;
long-double) var=LDBL ;;
- *) AC_MSG_ERROR([unexpected floating-point type \`$ty']) ;;
+ *) AC_MSG_ERROR([unexpected floating-point type `$ty']) ;;
esac
case $fmt in
nil) value=UNKNOWN ;;
ieee-f128-be) value=IEEE_F128_BE ;;
intel-f80-le) value=INTEL_F80_LE ;;
intel-f80-be) value=INTEL_F80_BE ;;
- *) AC_MSG_ERROR([unexpected floating-point format \`$fmt']) ;;
+ *) AC_MSG_ERROR([unexpected floating-point format `$fmt']) ;;
esac
AC_DEFINE_UNQUOTED([${var}_FORMAT], [FLTFMT_$value])
done])
--- /dev/null
+{
+ mLib-sub-chunks
+ Memcheck:Leak
+ match-leak-kinds: reachable
+ fun:malloc
+ fun:_alloc
+ fun:subarena_alloc
+}
.I p
to point to freshly allocated memory large enough for the type that
.I p
-points to;
+points to.
The
.B X_NEWV
macro sets
.
.\" @A_CREATE
.\" @A_DESTROY
+.\" @A_SUBNEW
.\" @CREATE
.\" @DESTROY
+.\" @NEW
.
.\"--------------------------------------------------------------------------
.SH NAME
.BI "void subarena_create(subarena *" s ", arena *" a );
.BI "void subarena_destroy(subarena *" s );
.BI "void subarena_alloc(subarena *" s ", size_t " sz );
+.BI "void *A_CREATE(subarena *" s ", " type );
+.BI "A_SUBNEW(" type "* " p ", subarena *" s );
.BI "void subarena_free(subarena *" s ", void *" p ", size_t " sz );
+.BI "void A_DESTROY(subarena *" s ", " type " *" p );
.PP
.B "void sub_init(void);"
.BI "void *sub_alloc(size_t " sz );
-.BI "void sub_free(void *" p ", size_t " sz );
-.PP
-.BI "void *A_CREATE(subarena *" s ", " type );
-.BI "void A_DESTROY(subarena *" s ", " type " *" p );
.BI "void *CREATE(" type );
+.BI "NEW(" type "* " p );
+.BI "void sub_free(void *" p ", size_t " sz );
.BI "void DESTROY(" type " *" p );
.fi
.
.BR subarena_free .
If you do, you'll get what you deserve.
.PP
-The pair of macros
-.B A_CREATE
+The macros
+.BR A_CREATE ,
+.BR A_SUBNEW ,
and
.B A_DESTROY
are intended to provide a slightly more natural interface to
.VE
can be replaced by
.VS
-mystruct p = A_CREATE(s, mystruct);
+mystruct *p = A_CREATE(s, mystruct);
+.VE
+or
+.VS
+mystruct *p;
+A_SUBNEW(p, s);
.VE
Similarly, the block can be freed by saying
.VS
and
.B sub_free
and the macros
-.B CREATE
+.BI CREATE ,
+.BI NEW
and
.B DESTROY
use this subarena.
#define A_CREATE(a, type) subarena_alloc((a), sizeof(type))
+/* --- @A_SUBNEW@ --- *
+ *
+ * Arguments: @type *p@ = a pointer to allocate
+ * @subarena *s@ = pointer to arena
+ *
+ * Returns: ---
+ *
+ * Use: Set @p@ to point to a freshly allocated block large enough to
+ * hold an object of the type pointed to by @p@. If there is
+ * not enough memory, the exception @EXC_NOMEM@ is thrown.
+ */
+
+#define A_SUBNEW(p, a) \
+ do { (p) = subarena_alloc((a), sizeof(*(p))); } while (0)
+
/* --- @A_DESTROY@ --- *
*
* Arguments: @subarena *s@ = pointer to arena
#define CREATE(type) sub_alloc(sizeof(type))
+/* --- @NEW@ --- *
+ *
+ * Arguments: @type *p@ = a pointer to allocate
+ *
+ * Returns: ---
+ *
+ * Use: Set @p@ to point to a freshly allocated block large enough to
+ * hold an object of the type pointed to by @p@. If there is
+ * not enough memory, the exception @EXC_NOMEM@ is thrown.
+ */
+
+#define NEW(p) do { (p) = sub_alloc(sizeof(*(p))); } while (0)
+
/* --- @DESTROY@ --- *
*
* Arguments: @void *p@ = pointer to an object
sel_timer *t;
for (t = s->timers; t && TV_CMP(&t->tv, <=, &a.now); t = t->next) {
- pt = CREATE(ptimer);
+ NEW(pt);
pt->t = t;
t->pend = pt;
*ptt = pt;
for (f = s->files[i]; f; f = f->next) {
if (!FD_ISSET(f->fd, &a.fd[i]))
continue;
- pf = CREATE(pfile);
+ NEW(pf);
pf->f = f;
f->pend = pf;
*pff = pf;
_s = _p->free; \
_p->free = _s->next; \
} else { \
- _s = CREATE(dspoolstr); \
+ NEW(_s); \
DCREATE(&_s->ds); \
if (_p->isz) \
DENSURE(&_s->ds, _p->isz); \
.VP
/* --- Make a new hashtable item --- */
.VP
- i = CREATE(item);
+ NEW(i);
i->k = xstrdup(k);
/* ... */
.VP
bc->be = be; bc->bst = 0; bc->subctx = 0;
if (!tvec_benchprep(tv, be->bst, BTF_INDIRECT))
{ bc->bst = *be->bst; bc->dflt_target = bc->bst->target_s; }
- if (subenv && subenv->ctxsz) bc->subctx = x_alloc(tv->a, subenv->ctxsz);
- if (subenv && subenv->setup) subenv->setup(tv, subenv, bc, bc->subctx);
+ if (subenv && subenv->ctxsz)
+ bc->subctx = pool_alloc(tv->p_group, subenv->ctxsz);
+ if (subenv && subenv->setup)
+ subenv->setup(tv, subenv, bc, bc->subctx);
}
/* --- @tvec_benchfindvar@, @setvar@ --- *
/* Tear down any subsidiary environment. */
if (subenv && subenv->teardown) subenv->teardown(tv, bc->subctx);
- if (bc->subctx) x_free(tv->a, bc->subctx);
/* If the benchmark state was temporary, then dispose of it. */
if (bc->bst) {
assert(out < TVOUT_LIMIT); tv->curr[out]++;
tv->output->ops->etest(tv->output, out);
tv->f &= ~TVSF_OPEN;
+ pool_recycle(tv->p_test);
}
/* --- @tvec_xfail@ --- *
tv->f &= ~(TVSF_SKIP | TVSF_MUFFLE);
tvec_initregs(tv);
for (i = 0; i < TVOUT_LIMIT; i++) tv->curr[i] = 0;
- if (env && env->ctxsz) g->ctx = x_alloc(tv->a, env->ctxsz);
+ if (env && env->ctxsz) g->ctx = pool_alloc(tv->p_group, env->ctxsz);
if (env && env->setup) env->setup(tv, env, 0, g->ctx);
}
if (tv->f&TVSF_OPEN) check(tv, g);
if (!(tv->f&TVSF_SKIP)) report_group(tv);
env = t->env; if (env && env->teardown) env->teardown(tv, g->ctx);
- tvec_releaseregs(tv); tv->test = 0; x_free(tv->a, g->ctx); g->ctx = 0;
+ tvec_releaseregs(tv); tv->test = 0; g->ctx = 0; pool_recycle(tv->p_group);
}
/* --- @core_findvar@, @core_setvar@ --- *
/* General setup. */
tv_out->f = 0;
tv_out->a = arena_global;
+ tv_out->p_session = pool_create(tv_out->a);
+ tv_out->p_group = pool_sub(tv_out->p_session);
+ tv_out->p_test = pool_sub(tv_out->p_session);
/* Run sanity checks on the test configuration. */
bad = 0;
/* Standard initialization for file-directed testing. */
tv_out->cfg = *config;
- tv_out->in = x_allocv(tv_out->a, tv_out->cfg.nreg, tv_out->cfg.regsz);
- tv_out->out = x_allocv(tv_out->a, tv_out->cfg.nrout, tv_out->cfg.regsz);
+ tv_out->in = pool_allocv(tv_out->p_session,
+ tv_out->cfg.nreg, tv_out->cfg.regsz);
+ tv_out->out = pool_allocv(tv_out->p_session,
+ tv_out->cfg.nrout, tv_out->cfg.regsz);
for (i = 0; i < tv_out->cfg.nreg; i++) {
TVEC_REG(tv_out, in, i)->f = 0;
if (i < tv_out->cfg.nrout) TVEC_REG(tv_out, out, i)->f = 0;
if (tv->test) tvec_releaseregs(tv);
tv->output->ops->destroy(tv->output);
- x_free(tv->a, tv->in); x_free(tv->a, tv->out);
+ pool_destroy(tv->p_session);
return (rc);
}
void tvec_endgroup(struct tvec_state *tv)
{
if (!(tv->f&TVSF_SKIP)) report_group(tv);
- tv->test = 0;
+ tv->test = 0; pool_recycle(tv->p_group);
}
/* --- @tvec_begintest@ --- *
", fp);
}
+struct bench_resource {
+ pool_resource r;
+ struct bench_state **bst;
+};
+
+static void release_bench(pool_resource *r)
+{
+ struct bench_resource *br = (struct bench_resource *)r;
+
+ if (*br->bst) { bench_destroy(*br->bst); *br->bst = 0; }
+}
+
/* --- @tvec_parseargs@ --- *
*
* Arguments: @int argc@ = number of command-line arguments
struct tvec_amargs am;
double benchtime = 1.0, scale;
struct bench_timer *tm;
+ struct bench_resource *br;
const char *p; char *q;
int opt;
unsigned f = 0;
}
tvec_begin(tv_out, config, o); *argpos_out = optind;
+ POOL_NEW(br, tv_out->p_session);
+ br->bst = &tvec_benchstate;
+ POOL_ADD(tv_out->p_session, &br->r, release_bench);
#undef f_bogus
#undef f_bench
if (env && env->setup == tvec_remotesetup)
env = ((struct tvec_remoteenv *)env)->r.env;
if (!env || !env->ctxsz) ctx = 0;
- else ctx = x_alloc(srvtv.a, env->ctxsz);
+ else ctx = pool_alloc(srvtv.p_group, env->ctxsz);
if (env && env->setup) env->setup(&srvtv, env, 0, ctx);
/* Initialize the registers. */
/* Tear down the environment and release other resources. */
if (env && env->teardown) env->teardown(&srvtv, ctx);
tvec_releaseregs(&srvtv);
- x_free(srvtv.a, ctx); srvtv.test = 0; env = 0; ctx = 0;
+ srvtv.test = 0; env = 0; ctx = 0; pool_recycle(srvtv.p_group);
/* Report completion. */
QUEUEPK(&srvtv, &srvrc, QF_FORCE, TVPK_EGROUP | TVPF_ACK);
/* Clean up and return. */
if (env && env->teardown) env->teardown(&srvtv, ctx);
if (vd) vd->def.ty->release(&r->v, &vd->def);
- x_free(srvtv.a, ctx); x_free(srvtv.a, r_alloc);
+ x_free(srvtv.a, r_alloc); dstr_destroy(&d);
if (srvtv.test) tvec_releaseregs(&srvtv);
release_comms(&srvtv, &srvrc); tvec_end(&srvtv);
return (rc ? 2 : 0);
const struct tvec_remoteenv *re = (const struct tvec_remoteenv *)env;
const struct tvec_env *subenv = re->r.env;
- r->tv = tv;
+ r->tv = tv; r->subctx = 0;
init_comms(&r->rc);
r->re = re; r->kid = -1;
DCREATE(&r->prgwant); DCREATE(&r->progress);
if (connect_remote(tv, r))
tvec_skipgroup(tv, "failed to connect to test backend");
reset_vars(r);
- if (subenv && subenv->ctxsz) r->subctx = x_alloc(tv->a, subenv->ctxsz);
- else r->subctx = 0;
- if (subenv && subenv->setup) subenv->setup(tv, subenv, r, r->subctx);
+ if (subenv && subenv->ctxsz)
+ r->subctx = pool_alloc(tv->p_group, subenv->ctxsz);
+ if (subenv && subenv->setup)
+ subenv->setup(tv, subenv, r, r->subctx);
}
/* --- @tvec_remotefindvar@, @setvar_local@, @setvar_remote@ --- *
buf b;
if (subenv && subenv->teardown) subenv->teardown(tv, r->subctx);
- x_free(tv->a, r->subctx);
if (r->rc.outfd >= 0) {
QUEUEPK(tv, &r->rc, QF_FORCE, TVPK_EGROUP);
if (!handle_packets(tv, r, RCVF_ALLOWEOF, TVPK_EGROUP | TVPF_ACK, &b))
reset(tc);
- if (subenv && subenv->ctxsz) tc->subctx = x_alloc(tv->a, subenv->ctxsz);
- else tc->subctx = 0;
+ if (subenv && subenv->ctxsz)
+ tc->subctx = pool_alloc(tv->p_group, subenv->ctxsz);
+ else
+ tc->subctx = 0;
if (subenv && subenv->setup) subenv->setup(tv, subenv, tc, tc->subctx);
}
/* Just call the subsidiary environment. */
if (subenv && subenv->teardown) subenv->teardown(tv, tc->subctx);
- x_free(tv->a, tc->subctx);
}
/*----- That's all, folks -------------------------------------------------*/
unsigned f = 0;
#define f_range 1u
+ d.a = &tv->p_test->a;
if (tvec_readword(tv, &d, 0, delims, what)) { rc = -1; goto end; }
p = d.buf;
if (parse_unsigned_integer(&u, &p, p)) goto bad;
*u_out = u; rc = 0;
end:
- dstr_destroy(&d);
return (rc);
bad:
double x;
int olderr, rc;
+ d.a = &tv->p_test->a;
+
/* Check for special tokens. */
if (STRCMP(p, ==, "#nan")) {
#ifdef NAN
/* All done. */
*x_out = x; rc = 0;
end:
- dstr_destroy(&d);
return (rc);
}
int ch, err, rc;
set_up_encoding(&ccl, &cdf, code); cdc = 0;
+ d.a = w.a = &tv->p_test->a;
if (tvec_nexttoken(tv)) return (tvec_syntax(tv, fgetc(tv->fp), "string"));
do {
dstr_ensure(&d, n);
fill_pattern(d.buf + d.len, n, pp, sz); d.len += n;
}
- xfree(pp); pp = 0;
+ free(pp); pp = 0;
}
/* Anything else is an error. */
end:
/* Clean up any debris. */
if (cdc) cdc->ops->destroy(cdc);
- if (pp) xfree(pp);
+ if (pp) free(pp);
dstr_destroy(&d); dstr_destroy(&w);
return (rc);
}
dstr d = DSTR_INIT;
int rc;
+ d.a = &tv->p_test->a;
if (tvec_readword(tv, &d, 0, ";", "signed integer"))
{ rc = -1; goto end; }
if (parse_signed(&rv->i, d.buf, rd->arg.p, tv)) { rc = -1; goto end; }
rc = 0;
end:
- dstr_destroy(&d);
return (rc);
}
dstr d = DSTR_INIT;
int rc;
+ d.a = &tv->p_test->a;
if (tvec_readword(tv, &d, 0, ";", "unsigned integer"))
{ rc = -1; goto end; }
if (parse_unsigned(&rv->u, d.buf, rd->arg.p, tv)) { rc = -1; goto end; }
rc = 0;
end:
- dstr_destroy(&d);
return (rc);
}
dstr d = DSTR_INIT;
int rc;
+ d.a = &tv->p_test->a;
if (tvec_readword(tv, &d, 0, ";", "floating-point number"))
{ rc = -1; goto end; }
if (parse_floating(&rv->f, 0, d.buf, rd->arg.p, tv))
{ rc = -1; goto end; }
rc = 0;
end:
- dstr_destroy(&d);
return (rc);
}
double t;
int rc;
+ d.a = &tv->p_test->a;
if (tvec_readword(tv, &d, 0, ";", "duration")) { rc = -1; goto end; }
if (parse_floating(&t, &q, d.buf,
rd->arg.p ? rd->arg.p : &tvflt_nonneg, tv))
rv->f = t; rc = 0;
end:
- dstr_destroy(&d);
return (rc);
}
dstr d = DSTR_INIT; \
int rc; \
\
+ d.a = &tv->p_test->a; \
if (tvec_readword(tv, &d, 0, \
";", "%s tag or " LITSTR_##tag_, ei->name)) \
{ rc = -1; goto end; } \
done: \
rc = 0; \
end: \
- dstr_destroy(&d); \
return (rc); \
}
const struct tvec_ienuminfo tvenum_cmp =
{ "cmp", cmp_assoc, &tvrange_int };
+static const struct tvec_passoc dummy_assoc[] = { TVEC_ENDENUM };
+static const struct tvec_penuminfo dummy_peinfo = { "pointer", dummy_assoc };
+
/* --- @tvec_claimeq_tenum@ --- *
*
* Arguments: @struct tvec_state *tv@ = test-vector state
union tvec_misc arg; \
struct tvec_reg rval, rref; \
\
+ PREFLIGHT_##tag; \
arg.p = ei; \
rval.f = rref.f = TVRF_LIVE; \
rval.v.slot = GET_##tag(e0); rref.v.slot = GET_##tag(e1); \
return (tvec_claimeq(tv, &tvty_##slot##enum, &arg, \
&rval, &rref, file, lno, expr)); \
}
+#define PREFLIGHT_INT do ; while (0)
#define GET_INT(e) (e)
+#define PREFLIGHT_UINT do ; while (0)
#define GET_UINT(e) (e)
+#define PREFLIGHT_FLT do ; while (0)
#define GET_FLT(e) (e)
+#define PREFLIGHT_PTR \
+ if (!ei) ei = &dummy_peinfo
#define GET_PTR(e) (UNCONST(void, (e)))
TVEC_MISCSLOTS(DEFCLAIM)
#undef DEFCLAIM
+#undef PREFLIGHT_INT
#undef GET_INT
+#undef PREFLIGHT_UINT
#undef GET_UINT
+#undef PREFLIGHT_FLT
#undef GET_FLT
+#undef PREFLIGHT_PTR
#undef GET_PTR
/*----- Flag types --------------------------------------------------------*/
dstr d = DSTR_INIT;
int ch, rc;
+ d.a = &tv->p_test->a;
+
for (;;) {
/* Read the next item. */
}
/* Otherwise, try to parse it as a raw integer. */
- if (parse_unsigned(&t, d.buf, fi->range, tv))
- { rc = -1; goto end; }
- v |= t;
+ if (parse_unsigned(&t, d.buf, fi->range, tv)) { rc = -1; goto end; }
+ if (m&t) { tvec_error(tv, "colliding flag setting"); rc = -1; goto end; }
+ v |= t; m |= t;
next:
/* Advance to the next token. If it's a separator then consume it, and
/* Done. */
rv->u = v; rc = 0;
end:
- dstr_destroy(&d);
return (rc);
}
union tvec_misc arg;
struct tvec_reg rval, rref;
+ arg.p = fi;
rval.f = rref.f = TVRF_LIVE; rval.v.u = f0; rref.v.u = f1;
return (tvec_claimeq(tv, &tvty_flags, &arg,
&rval, &rref, file, lno, expr));
unsigned f = 0;
#define f_quote 1u
+ d.a = &tv->p_test->a;
+
/* Advance until we find something. */
if (tvec_nexttoken(tv))
return (tvec_syntax(tv, fgetc(tv->fp), "character"));
/* Done. */
rc = 0;
end:
- dstr_destroy(&d);
return (rc);
#undef f_quote
# include "macros.h"
#endif
+#ifndef MLIB_POOL_H
+# include "pool.h"
+#endif
+
/*----- Miscellaneous values ----------------------------------------------*/
/* These are attached to structures which represent extension points, as a
/* Memory allocation. Read-only for all callers. */
arena *a;
+ pool *p_session, *p_group, *p_test; /* allocation pools */
/* Test configuration. Read-only for all callers. */
struct tvec_config cfg; /* test configuration */
/* Adhoc testing state. Private. */
struct tvec_test adhoc_test;
- const struct tvec_test *adhoc_tests[];
+ const struct tvec_test *adhoc_tests[2];
};
/* @TVEC_REG(tv, vec, i)@
static const struct kw { const char *name; uint32 val; }
kw_colours[] = {
- { "no", COLS_NO },
- { "8", COLS_8 },
- { "16", COLS_16 },
- { "88", COLS_88 },
- { "256", COLS_256 },
- { "16m", COLS_16M },
- { 0, 0 }
+ { "no", COLS_NO },
+ { "8", COLS_8 },
+ { "16", COLS_16 },
+ { "88", COLS_88 },
+ { "256", COLS_256 },
+ { "16m", COLS_16M },
+ { 0, 0 }
};
static const struct enummap {
uint32 mask;
const struct kw *kw;
} enummap[] = {
- { "colours", TTACF_CSPCMASK, kw_colours },
- { 0, 0, 0 }
+ { "colours", TTACF_CSPCMASK | TTACF_FG | TTACF_BG,
+ kw_colours },
+ { 0, 0, 0 }
};
const char *name; unsigned code;
struct tty *(*init)(FILE */*fp*/);
} betab[] = {
+#ifdef HAVE_UNIBILIUM
{ "unibilium", TTBK_UNIBI, termunibi_init },
+#endif
+#ifdef HAVE_TERMINFO
{ "terminfo", TTBK_TERMINFO, terminfo_init },
+#endif
+#ifdef HAVE_TERMCAP
{ "termcap", TTBK_TERMCAP, termcap_init },
+#endif
{ "ansi", TTBK_ANSI, ansi_init },
{ 0, 0, 0 }
};
#include <stdio.h>
+
#include "exc.h"
+#include "macros.h"
+#include "report.h"
+#include "tvec.h"
+#include "tvec-adhoc.h"
+#include "tvec-types.h"
+
+static struct tvec_state tvstate;
+static int step;
-void func(void)
+#define TESTGROUP(name) \
+ TVEC_TESTGROUP_TAG(grp, &tvstate, name) \
+ MC_BEFORE(init, { step = 0; })
+#define TEST TVEC_TEST_TAG(test, &tvstate)
+#define STEP(s) do { \
+ tvec_claim(&tvstate, s == step, __FILE__, __LINE__, \
+ "found %d /= expected %d", s, step); \
+ step++; \
+ } while (0)
+#define MISSTEP do { \
+ tvec_claim(&tvstate, 0, __FILE__, __LINE__, \
+ "shouldn't have reached here"); \
+ step++; \
+ } while (0)
+
+static void func(void)
{
- printf("cabbage\n");
- TRY {
- printf("dibble\n");
- THROW(EXC_FAIL, "excession");
- printf("can't see me\n");
- } CATCH switch (exc_type) {
- case 1:
- printf("exc type 1 (not possible)\n");
- break;
- case EXC_FAIL:
- printf("exc type 2 (%s)\n", exc_s);
- break;
- default:
- RETHROW;
+ TRY { STEP(2); THROW(EXC_FAIL, "excession"); MISSTEP; }
+ CATCH switch (exc_type) {
+ case EXC_FAIL: TVEC_CLAIMEQ_TEXTZ(&tvstate, exc_s, "excession"); break;
+ default: MISSTEP; break;
} END_TRY;
- printf("fennel\n");
- THROW(EXC_ERRNO, 53);
+ TRY { STEP(3); THROW(EXC_ERRNO, 53); }
+ CATCH switch (exc_type) {
+ case EXC_ERRNO: RETHROW;
+ default: MISSTEP; break;
+ } END_TRY;
+ MISSTEP;
}
-int main(void)
+int main(int argc, char *argv[])
{
- printf("apple\n");
- TRY {
- printf("banana\n");
- func();
- printf("can't see me\n");
- } CATCH switch (exc_type) {
- default:
- printf("%lu exception (val = %i)\n", exc_type, exc_i);
- break;
- } END_TRY;
- printf("hello! __exc_list = ");
- if (__exc_list) printf("%p", (void *)__exc_list);
- else printf("(nil)");
- putchar('\n');
+ int argpos;
+
+ tvec_parseargs(argc, argv, &tvstate, &argpos, &tvec_adhocconfig);
+ if (argpos < argc) die(2, "no input files expected");
+
+ TESTGROUP("flow") {
+ STEP(0);
+ TRY { STEP(1); func(); MISSTEP; }
+ CATCH switch (exc_type) {
+ case EXC_ERRNO: STEP(4); TVEC_CLAIMEQ_INT(&tvstate, exc_i, 53); break;
+ default: MISSTEP;
+ } END_TRY;
+ STEP(5);
+ }
+
+ TESTGROUP("final")
+ TVEC_CLAIMEQ_PTR(&tvstate, __exc_list, 0);
- return (0);
+ return (tvec_end(&tvstate));
}
## exc
AT_SETUP([utilities: exc])
AT_KEYWORDS([utils exc])
-AT_DATA([expout],
-[apple
-banana
-cabbage
-dibble
-exc type 2 (excession)
-fennel
-65 exception (val = 53)
-hello! __exc_list = (nil)
-])
-AT_CHECK([BUILDDIR/t/exc.t], [0], [expout])
+AT_CHECK([BUILDDIR/t/exc.t -fh], [0], [ignore])
AT_CLEANUP
## fltfmt