@@@ tvec setvar
[mLib] / test / tvec.h
index 5d37c3f..1e1e154 100644 (file)
@@ -337,6 +337,18 @@ typedef void tvec_testfn(const struct tvec_reg */*in*/,
 
 struct tvec_env;
 
+typedef int tvec_setvarfn(struct tvec_state */*tv*/, const char */*var*/,
+                         const union tvec_regval */*rv*/, void */*ctx*/);
+  /* Called after a variable is read.  Return zero on success or %$-1$% on
+   * error.  This function is never called if the test group is skipped.
+   */
+
+struct tvec_vardef {
+  size_t regsz;                                /* (minimum) register size */
+  tvec_setvarfn *setvar;               /* function to set variable */
+  struct tvec_regdef def;              /* register definition */
+};
+
 typedef void tvec_envsetupfn(struct tvec_state */*tv*/,
                             const struct tvec_env */*env*/,
                             void */*pctx*/, void */*ctx*/);
@@ -348,19 +360,23 @@ typedef void tvec_envsetupfn(struct tvec_state */*tv*/,
    * will not.
    */
 
-typedef int tvec_envsetfn(struct tvec_state */*tv*/,
-                         const char */*var*/, void */*ctx*/);
-  /* Called when the parser finds a %|@var|%' setting to parse and store the
-   * value.  Return %$+1$% on success, %$0$% if the variable name was not
-   * recognized, or %$-1$% on any other error (which should have been
-   * reported via @tvec_error@).
+typedef const struct tvec_vardef *tvec_envfindvarfn
+  (struct tvec_state */*tv*/, const char */*name*/,
+   void **/*ctx_out*/, void */*ctx*/);
+  /* Called when the parser finds a %|@var|%' special variable.  If a
+   * suitable variable was found, set @*ctx_out@ to a suitable context and
+   * return the variable definition; the context will be passed to the
+   * variable definition's @setvar@ function.  If no suitable variable was
+   * found, then return null.
    */
 
 typedef void tvec_envbeforefn(struct tvec_state */*tv*/, void */*ctx*/);
   /* Called prior to running a test.  This is the right place to act on any
    * `%|@var|%' settings.  If preparation fails, the function should call
    * @tvec_skip@ with a suitable excuse.  This function is never called if
-   * the test group is skipped.
+   * the test group is skipped.  It %%\emph{is}%% called if the test will be
+   * skipped due to erroneous test data.  It should check the @TVSF_ACTIVE@
+   * flag if necessary.
    */
 
 typedef void tvec_envrunfn(struct tvec_state */*tv*/,
@@ -376,9 +392,9 @@ typedef void tvec_envrunfn(struct tvec_state */*tv*/,
 typedef void tvec_envafterfn(struct tvec_state */*tv*/, void */*ctx*/);
   /* Called after running or skipping a test.  Typical actions involve
    * resetting whatever things were established by @set@.  This function
-   * %%\emph{is}%% called if the test group is skipped, so that the test
-   * environment can reset variables set by the @set@ entry point.  It should
-   * check the @TVSF_SKIP@ flag if necessary.
+   * %%\emph{is}%% called if the test group is skipped or the test data is
+   * erroneous, so that the test environment can reset variables set by the
+   * @set@ entry point.  It should check the @TVSF_SKIP@ flag if necessary.
    */
 
 typedef void tvec_envteardownfn(struct tvec_state */*tv*/, void */*ctx*/);
@@ -397,7 +413,7 @@ struct tvec_env {
   size_t ctxsz;                                /* environment context size */
 
   tvec_envsetupfn *setup;              /* setup for group */
-  tvec_envsetfn *set;                  /* set variable */
+  tvec_envfindvarfn *findvar;          /* find variable */
   tvec_envbeforefn *before;            /* prepare for test */
   tvec_envrunfn *run;                  /* run test function */
   tvec_envafterfn *after;              /* clean up after test */
@@ -1147,7 +1163,7 @@ extern struct bench_state *tvec_benchstate;
  */
 
 extern tvec_envsetupfn tvec_benchsetup;
-extern tvec_envsetfn tvec_benchset;
+extern tvec_envfindvarfn tvec_benchfindvar;
 extern tvec_envbeforefn tvec_benchbefore;
 extern tvec_envrunfn tvec_benchrun;
 extern tvec_envafterfn tvec_benchafter;
@@ -1156,7 +1172,7 @@ extern tvec_envteardownfn tvec_benchteardown;
 #define TVEC_BENCHENV                                                  \
   { sizeof(struct tvec_benchctx),                                      \
     tvec_benchsetup,                                                   \
-    tvec_benchset,                                                     \
+    tvec_benchfindvar,                                                 \
     tvec_benchbefore,                                                  \
     tvec_benchrun,                                                     \
     tvec_benchafter,                                                   \
@@ -1198,6 +1214,8 @@ struct tvec_remotectx {
   struct tvec_state *tv;               /* test vector state */
   struct tvec_remotecomms rc;          /* communication state */
   const struct tvec_remoteenv *re;     /* environment configuration */
+  void *subctx;                                /* subenvironment context */
+  struct tvec_vardef vd;               /* temporary variable definition */
   unsigned ver;                                /* protocol version */
   pid_t kid;                           /* child process id */
   int errfd;                           /* child stderr descriptor */
@@ -1205,8 +1223,8 @@ struct tvec_remotectx {
   dstr prgwant, progress;              /* progress: wanted/reported */
   unsigned exwant, exit;               /* exit status wanted/reported */
 #define TVRF_RCNMASK 0x0300u           /*   reconnection behaviour: */
-#define TVRCN_SKIP 0x0000u             /*     skip unless connected */
-#define TVRCN_DEMAND 0x0100u           /*     connect on demand */
+#define TVRCN_DEMAND 0x0000u           /*     connect on demand */
+#define TVRCN_SKIP 0x0100u             /*     skip unless connected */
 #define TVRCN_FORCE 0x0200u            /*     force reconnection */
 #define TVRF_MUFFLE 0x0400u            /*   muffle child stderr */
 #define TVRF_SETEXIT 0x0800u           /*   set `@exit' */
@@ -1237,6 +1255,7 @@ typedef int tvec_connectfn(pid_t */*kid_out*/, int */*infd_out*/,
 struct tvec_remoteenv_slots {
   tvec_connectfn *connect;             /* connection function */
   const struct tvec_env *env;          /* subsidiary environment */
+  unsigned dflt_reconn;                        /* default reconnection */
 };
 
 struct tvec_remoteenv {
@@ -1296,15 +1315,16 @@ union tvec_remoteenv_subclass_kludge {
 
 /* Remote environment. */
 extern tvec_envsetupfn tvec_remotesetup;
-extern tvec_envsetfn tvec_remoteset;
+extern tvec_envfindvarfn tvec_remotefindvar;
+extern tvec_envbeforefn tvec_remotebefore;
 extern tvec_envrunfn tvec_remoterun;
 extern tvec_envafterfn tvec_remoteafter;
 extern tvec_envteardownfn tvec_remoteteardown;
 #define TVEC_REMOTEENV                                                 \
   { sizeof(struct tvec_remotectx),                                     \
     tvec_remotesetup,                                                  \
-    tvec_remoteset,                                                    \
-    0,                                                                 \
+    tvec_remotefindvar,                                                        \
+    tvec_remotebefore,                                                 \
     tvec_remoterun,                                                    \
     tvec_remoteafter,                                                  \
     tvec_remoteteardown }
@@ -1372,23 +1392,25 @@ extern tvec_connectfn tvec_fork, tvec_exec;
 
 struct tvec_timeoutenv {
   struct tvec_env _env;
-  unsigned timer;                      /* the timer (@ITIMER_...@) */
+  int timer;                   /* the timer (@ITIMER_...@) */
   double t;                            /* time to wait (in seconds) */
   const struct tvec_env *env;          /* subsidiary environment */
 };
 
 struct tvec_timeoutctx {
   const struct tvec_timeoutenv *te;    /* saved environment description */
-  unsigned timer;                      /* timer code (as overridden) */
+  int timer;                           /* timer code (as overridden) */
   double t;                            /* time to wait (as overridden) */
   unsigned f;                          /* flags */
 #define TVTF_SETTMO 1u                 /*   set `@timeout' */
-#define TVTF_SETMASK (TVTF_SETTMO)     /*   mask of @TVTF_SET...@ */
+#define TVTF_SETTMR 2u                 /*   set `@timer' */
+#define TVTF_SETMASK (TVTF_SETTMO | TVTF_SETTMR)
+                                       /*   mask of @TVTF_SET...@ */
   void *subctx;
 };
 
 extern tvec_envsetupfn tvec_timeoutsetup;
-extern tvec_envsetfn tvec_timeoutset;
+extern tvec_envfindvarfn tvec_timeoutfindvar;
 extern tvec_envbeforefn tvec_timeoutbefore;
 extern tvec_envrunfn tvec_timeoutrun;
 extern tvec_envafterfn tvec_timeoutafter;
@@ -1396,7 +1418,7 @@ extern tvec_envteardownfn tvec_timeoutteardown;
 #define TVEC_TIMEOUTENV                                                        \
        { sizeof(struct tvec_timeoutctx),                               \
          tvec_timeoutsetup,                                            \
-         tvec_timeoutset,                                              \
+         tvec_timeoutfindvar,                                          \
          tvec_timeoutbefore,                                           \
          tvec_timeoutrun,                                              \
          tvec_timeoutafter,                                            \
@@ -1616,6 +1638,19 @@ extern PRINTF_LIKE(3, 4)
 extern int tvec_syntax_v(struct tvec_state */*tv*/, int /*ch*/,
                         const char */*expect*/, va_list */*ap*/);
 
+/* --- @tvec_unkreg@ --- *
+ *
+ * Arguments:  @struct tvec_state *tv@ = test-vector state
+ *             @const char *name@ = register or pseudoregister name
+ *
+ * Returns:    %$-1$%.
+ *
+ * Use:                Reports an error that the register or pseudoregister is
+ *             unrecognized.
+ */
+
+extern int tvec_unkreg(struct tvec_state */*tv*/, const char */*name*/);
+
 /* --- @tvec_dupreg@ --- *
  *
  * Arguments:  @struct tvec_state *tv@ = test-vector state
@@ -1932,6 +1967,18 @@ extern int tvec_claimeq_float(struct tvec_state */*tv*/,
 
 extern const struct tvec_floatinfo tvflt_finite, tvflt_nonneg;
 
+/*----- Durations ---------------------------------------------------------*/
+
+/* A duration measures a time interval in seconds.  The input format consists
+ * of a nonnegative decimal floating-point number in @strtod@ format followed
+ * by an optional unit specification.
+ *
+ * No @tvec_claimeq_...@ function is provided for durations: use
+ * @tvec_claimeq_float@.
+ */
+
+extern const struct tvec_regty tvty_duration;
+
 /*----- Enumerated types --------------------------------------------------*/
 
 /* An enumeration describes a set of values of some underlying type, each of