@@@ tvec setvar
[mLib] / test / tvec-bench.c
index c1d8cc0..ad23043 100644 (file)
@@ -243,43 +243,54 @@ fail_timer:
   tvec_skipgroup(tv, "failed to create timer"); goto end;
 }
 
-/* --- @tvec_benchset@ --- *
+/* --- @tvec_benchfindvar@, @setvar@ --- *
  *
  * Arguments:  @struct tvec_state *tv@ = test vector state
  *             @const char *var@ = variable name to set
+ *             @const union tvec_regval *rv@ = register value
+ *             @void **ctx_out@ = where to put the @setvar@ context
  *             @void *ctx@ = context pointer
  *
- * Returns:    %$+1$% on success, %$0$% if the variable name was not
- *             recognized, or %$-1$% on any other error.
+ * Returns:    @tvec_benchfindvar@ returns a pointer to the variable
+ *             definition, or null; @setvar@ returns zero on success or
+ *             %$-1$% on error.
  *
- * Use:                Set a special variable.  The following special variables are
- *             supported.
+ * Use:                Find a definition for a special variable.  The following
+ *             special variables are supported.
  *
- *               * %|@target|% is the (approximate) number of seconds to run
+ *               * %|@target|% is the (approximate) duration to run
  *                 the benchmark.
  *
  *             Unrecognized variables are passed to the subordinate
  *             environment, if there is one.
  */
 
-int tvec_benchset(struct tvec_state *tv, const char *var, void *ctx)
+static int setvar(struct tvec_state *tv, const char *var,
+                 const union tvec_regval *rv, void *ctx)
 {
   struct tvec_benchctx *bc = ctx;
-  const struct tvec_benchenv *be = bc->be;
-  const struct tvec_env *subenv = be->env;
-  union tvec_regval rv;
-  static const struct tvec_floatinfo fi = { TVFF_NOMAX, 0.0, 0.0, 0.0 };
-  static const struct tvec_regdef rd =
-    { "@target", -1, &tvty_float, 0, { &fi } };
 
   if (STRCMP(var, ==, "@target")) {
     if (bc->f&TVBF_SETTRG) return (tvec_dupreg(tv, var));
-    if (tvty_float.parse(&rv, &rd, tv)) return (-1);
-    bc->bst->target_s = rv.f; bc->f |= TVBF_SETTRG; return (1);
-  } else if (subenv && subenv->set)
-    return (subenv->set(tv, var, bc->subctx));
-  else
-    return (0);
+    bc->bst->target_s = rv->f; bc->f |= TVBF_SETTRG;
+  } else assert("unknown var");
+  return (0);
+}
+
+static const struct tvec_vardef target_var =
+  { sizeof(struct tvec_reg), setvar, { "@target", -1, &tvty_duration, 0 } };
+
+const struct tvec_vardef *tvec_benchfindvar
+  (struct tvec_state *tv, const char *var, void **ctx_out, void *ctx)
+{
+  struct tvec_benchctx *bc = ctx;
+  const struct tvec_benchenv *be = bc->be;
+  const struct tvec_env *subenv = be->env;
+
+  if (STRCMP(var, ==, "@target")) { *ctx_out = bc; return (&target_var); }
+  else if (subenv && subenv->findvar)
+    return (subenv->findvar(tv, var, ctx_out, bc->subctx));
+  else return (0);
 }
 
 /* --- @tvec_benchbefore@ --- *
@@ -299,7 +310,6 @@ void tvec_benchbefore(struct tvec_state *tv, void *ctx)
   const struct tvec_benchenv *be = bc->be;
   const struct tvec_env *subenv = be->env;
 
-  /* Just call the subsidiary environment. */
   if (subenv && subenv->before) subenv->before(tv, bc->subctx);
 }