+ /* Open the test. This is syntactically a paragraph of settings,
+ * so it's fair to report on missing register assignments.
+ */
+ open_test(tv);
+
+ /* Now there should be a separator. */
+ tvec_skipspc(tv); ch = getc(tv->fp);
+
+ if (ch == '*') {
+ /* Register explicitly marked unset. */
+
+ if (vd) {
+ tvec_error(tv, "can't unset special variables");
+ goto flush_line;
+ }
+ if (!(rd->f&(TVRF_OPT | TVRF_UNSET))) {
+ tvec_error(tv, "register `%s' must be assigned "
+ "a value in test `%s'", rd->name, tv->test->name);
+ goto flush_line;
+ }
+ r->f |= TVRF_SEEN;
+ if (tvec_flushtoeol(tv, 0)) goto bad;
+ } else {
+ /* Common case of a proper assignment. */
+
+ /* We must have a separator. */
+ if (ch != '=' && ch != ':')
+ { tvec_syntax(tv, ch, "`=', `:', or `*'"); goto flush_line; }
+ tvec_skipspc(tv);
+
+ if (!vd) {
+ /* An ordinary register. Parse a value and mark the register
+ * as live.
+ */
+
+ if (rd->ty->parse(&r->v, rd, tv)) goto flush_line;
+ r->f |= TVRF_LIVE | TVRF_SEEN;
+ } else {
+ /* A special register defined by an environment. */
+
+ /* Set up the register. */
+ if (vd->regsz <= sizeof(rbuf))
+ r = &rbuf;
+ else {
+ GROWBUF_REPLACE(&arena_stdlib, r_alloc, rsz, vd->regsz,
+ 8*sizeof(void *), 1);
+ r = r_alloc;
+ }
+
+ /* Read and set the value. */
+ rd->ty->init(&r->v, rd);
+ if (rd->ty->parse(&r->v, rd, tv)) goto flush_line;
+ if (!(tv->f&TVSF_SKIP) && vd->setvar(tv, d.buf, &r->v, varctx))
+ goto bad;
+
+ /* Clean up. */
+ rd->ty->release(&r->v, &vd->def); vd = 0;
+ }