<pre style='margin:0'>
Christopher Nielsen (mascguy) pushed a commit to branch master
in repository macports-legacy-support.

</pre>
<p><a href="https://github.com/macports/macports-legacy-support/commit/9a097faffab391c34de7a039d6251234c7b67df7">https://github.com/macports/macports-legacy-support/commit/9a097faffab391c34de7a039d6251234c7b67df7</a></p>
<pre style="white-space: pre; background: #F8F8F8"><span style='display:block; white-space:pre;color:#808000;'>commit 9a097faffab391c34de7a039d6251234c7b67df7
</span>Author: Fred Wright <fw@fwright.net>
AuthorDate: Mon May 5 22:36:20 2025 -0700

<span style='display:block; white-space:pre;color:#404040;'>    test_clocks: Implement replay feature.
</span><span style='display:block; white-space:pre;color:#404040;'>    
</span><span style='display:block; white-space:pre;color:#404040;'>    This allows previously captured logs (not necessarily on the same
</span><span style='display:block; white-space:pre;color:#404040;'>    system) to be replayed for the tests, to facilitate debugging and
</span><span style='display:block; white-space:pre;color:#404040;'>    testing.
</span><span style='display:block; white-space:pre;color:#404040;'>    
</span><span style='display:block; white-space:pre;color:#404040;'>    TESTED:
</span><span style='display:block; white-space:pre;color:#404040;'>    Works as expected.
</span>---
 test/test_clocks.c | 178 ++++++++++++++++++++++++++++++++++++++++++++---------
 1 file changed, 150 insertions(+), 28 deletions(-)

<span style='display:block; white-space:pre;color:#808080;'>diff --git a/test/test_clocks.c b/test/test_clocks.c
</span><span style='display:block; white-space:pre;color:#808080;'>index 998076b..a19139b 100644
</span><span style='display:block; white-space:pre;background:#e0e0ff;'>--- a/test/test_clocks.c
</span><span style='display:block; white-space:pre;background:#e0e0ff;'>+++ b/test/test_clocks.c
</span><span style='display:block; white-space:pre;background:#e0e0e0;'>@@ -22,6 +22,19 @@
</span>  * calculations may be done in floating-point, but its range may not be
  * sufficient for absolute (1970-relative) values in nanoseconds.  We sometimes
  * use long doubles, but they're not always better than doubles.
<span style='display:block; white-space:pre;background:#e0ffe0;'>+ *
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+ * Since clock values are inherently nonreproducible, the challenge in clock
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+ * tests is to have criteria which are tight enough to detect genuine problems,
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+ * while being loose enough to tolerate normal variations.  In many cases, we
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+ * rely on retries for the latter aspect.
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+ *
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+ * To facilitate debugging, we provide both a means to capture clock samples
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+ * into logfiles (either conditionally on errors or unconditionally), and a
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+ * means to replay previously captured logs into the tests.  Note that certain
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+ * parameters, such as the mach_time scale and the clock resolutions, are not
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+ * captured in the logfiles, so it's assumed that values from the current
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+ * system are acceptable.  Since the replayed clocks are always the nanosecond
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+ * versions, matching the mach_time scale is unimportant.
</span>  */
 
 #include <errno.h>
<span style='display:block; white-space:pre;background:#e0e0e0;'>@@ -88,7 +101,9 @@ typedef int64_t sns_time_t;
</span> #endif
 
 #define LL (long long)
<span style='display:block; white-space:pre;background:#e0ffe0;'>+#define LLP (long long *)
</span> #define ULL (unsigned long long)
<span style='display:block; white-space:pre;background:#e0ffe0;'>+#define ULLP (unsigned long long *)
</span> 
 typedef unsigned long pointer_int_t;
 
<span style='display:block; white-space:pre;background:#e0e0e0;'>@@ -686,26 +701,34 @@ get_stats(clock_idx_t clkidx, cstats_t *sp)
</span>     if (!diff) {
       if (++cursame > sp->maxsame) sp->maxsame = cursame;
     } else {
<span style='display:block; white-space:pre;background:#ffe0e0;'>-      cursame =0;
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+      cursame = 0;
</span>     }
   }
   sp->stddev = sqrt(sqsum / (NUM_DIFFS - 1));
 }
 
 /* Get and check one clock */
<span style='display:block; white-space:pre;background:#e0ffe0;'>+static int clock_replay_ns(clock_idx_t clkidx, int quiet);
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+
</span> static int
<span style='display:block; white-space:pre;background:#ffe0e0;'>-check_clock(clock_idx_t clkidx, cstats_t *sp, errinfo_t *ei)
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+check_clock(clock_idx_t clkidx, cstats_t *sp, errinfo_t *ei,
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+            int quiet, int replay)
</span> {
   int ret, tries = 0;
   useconds_t sleepus = STD_SLEEP_US;
 
   do {
<span style='display:block; white-space:pre;background:#ffe0e0;'>-    usleepx(sleepus);
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>-    if ((ret = collect_samples(clkidx, ei))) break;
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+    if (!replay) {
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+      usleepx(sleepus);
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+      if ((ret = collect_samples(clkidx, ei))) break;
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+    } else {
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+      ei->retries = -1;
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+      if ((ret = clock_replay_ns(clkidx, quiet))) return ret;
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+    }
</span>     ret = check_samples(clkidx, nsbufp[clock_types[clkidx]], 0, ei);
     if (ret <= 0) break;
     sleepus = MIN(sleepus * 2, MAX_SLEEP_US);
<span style='display:block; white-space:pre;background:#ffe0e0;'>-  } while (++tries < MAX_STEP_TRIES);
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+  } while (!replay && ++tries < MAX_STEP_TRIES);
</span> 
   ei->retries = tries;
   if (!ret && sp) get_stats(clkidx, sp);
<span style='display:block; white-space:pre;background:#e0e0e0;'>@@ -760,7 +783,7 @@ print_stats(const cstats_t *sp, const errinfo_t *ei)
</span> 
 /* Open logfile for writing */
 static FILE *
<span style='display:block; white-space:pre;background:#ffe0e0;'>-open_log(clock_idx_t clkidx, const char *extra, int quiet)
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+open_log(clock_idx_t clkidx, const char *extra, int quiet, int replay)
</span> {
   FILE *fp;
   const char *name = clock_names[clkidx];
<span style='display:block; white-space:pre;background:#e0e0e0;'>@@ -768,11 +791,16 @@ open_log(clock_idx_t clkidx, const char *extra, int quiet)
</span> 
   snprintf(fname, sizeof(fname), TEST_TEMP "/%s-%s%s.log",
            progname, name, extra);
<span style='display:block; white-space:pre;background:#ffe0e0;'>-  if(!(fp = fopen(fname, "w"))) {
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+  if(!(fp = fopen(fname, replay ? "r" : "w"))) {
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+    if (replay && errno == ENOENT) {
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+      if (!quiet) fprintf(stderr, "    Skipping nonexistent %s\n", fname);
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+      return NULL;
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+    }
</span>     fprintf(stderr, "    Unable to open %s\n", fname);
     return NULL;
   }
<span style='display:block; white-space:pre;background:#ffe0e0;'>-  if (!quiet) printf("      Logging to " TEST_TEMP "/\n");
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+  if (!quiet) printf("      %s %s/\n",
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+                     replay ? "Replaying from" : "Logging to", fname);
</span>   return fp;
 }
 
<span style='display:block; white-space:pre;background:#e0e0e0;'>@@ -785,7 +813,7 @@ clock_dump_ns(clock_idx_t clkidx, errinfo_t *ei, int verbose, int quiet)
</span>   sns_time_t last = nsbuf[0];
   FILE *fp;
 
<span style='display:block; white-space:pre;background:#ffe0e0;'>-  if (!(fp = open_log(clkidx, "", quiet))) return;
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+  if (!(fp = open_log(clkidx, "", quiet, 0))) return;
</span>   if (verbose >= 2) {
     fprintf(fp, "# Capture of %d %s samples (%s), retries = %d\n",
             NUM_SAMPLES, clock_names[clkidx],
<span style='display:block; white-space:pre;background:#e0e0e0;'>@@ -808,15 +836,53 @@ clock_dump_ns(clock_idx_t clkidx, errinfo_t *ei, int verbose, int quiet)
</span>   if (verbose) fprintf(fp, "# Index         Value       Delta\n");
   for (idx = 0; idx < NUM_SAMPLES; ++idx) {
     cur = nsbuf[idx];
<span style='display:block; white-space:pre;background:#ffe0e0;'>-    fprintf(fp, "%7d %19llu %5d\n", idx, ULL cur, (int) (cur - last));
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+    fprintf(fp, " %6d %19llu %5d\n", idx, ULL cur, (int) (cur - last));
</span>     last = cur;
   }
   fclose(fp);
 }
 
<span style='display:block; white-space:pre;background:#e0ffe0;'>+/* Replay data from prior dump */
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+static int
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+clock_replay_ns(clock_idx_t clkidx, int quiet)
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+{
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+  int ret = 0, count, idx = -1, diff;
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+  char pfx, eol, buf[256];
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+  ns_time_t cur, *nsbuf = nsbufp[clock_types[clkidx]];
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+  FILE *fp;
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+  if (!(fp = open_log(clkidx, "", quiet, 1))) return -1;
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+  do {
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+    if (!fgets(buf, sizeof(buf), fp)) {
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+      ret = !feof(fp);
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+      break;
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+    }
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+    count = sscanf(buf, "%c%d %llu %d%c",
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+                   &pfx, &idx, ULLP &cur, &diff, &eol);
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+    if (count < 0) {
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+      ret = 1;
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+      break;
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+    }
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+    if (pfx == '#') continue;
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+    if (pfx != ' ' || eol != '\n' || count != 5) {
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+      if (!quiet) fprintf(stderr, "    Bad line at/after index %d\n", idx);
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+      ret = -1;
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+      break;
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+    }
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+    if (idx < 0 || idx >= NUM_SAMPLES) {
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+      if (!quiet) fprintf(stderr, "    Skipping bad index %d\n", idx);
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+      continue;
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+    }
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+    nsbuf[idx] = cur;
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+  } while (1);
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+  fclose(fp);
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+  return ret;
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+}
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+
</span> /* Report info about one clock */
 static int
<span style='display:block; white-space:pre;background:#ffe0e0;'>-report_clock(clock_idx_t clkidx, int dump, int verbose, int quiet)
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+report_clock(clock_idx_t clkidx, int dump, int verbose, int quiet, int replay)
</span> {
   int err, ret = 0, vnq = verbose && !quiet;
   const char *name = clock_names[clkidx];
<span style='display:block; white-space:pre;background:#e0e0e0;'>@@ -825,6 +891,7 @@ report_clock(clock_idx_t clkidx, int dump, int verbose, int quiet)
</span> 
   if (vnq) printf("  Checking %s", name);
 
<span style='display:block; white-space:pre;background:#e0ffe0;'>+  /* In replay mode, assume that current resolutions are acceptable */
</span>   if ((err = getres(clkidx, &clock_res[clkidx]))) {
     if (!vnq) {
       printf("*** Error getting resolution of clock %s (%d): %s\n",
<span style='display:block; white-space:pre;background:#e0e0e0;'>@@ -840,7 +907,8 @@ report_clock(clock_idx_t clkidx, int dump, int verbose, int quiet)
</span>   }
   if (vnq) printf(" (resolution = %d ns)\n", (int) clock_res[clkidx]);
 
<span style='display:block; white-space:pre;background:#ffe0e0;'>-  if ((err = check_clock(clkidx, &stats, &info))) {
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+  if ((err = check_clock(clkidx, &stats, &info, quiet, replay))) {
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+    if (replay && info.retries < 0) return 0;  /* Just skip nonex replay */
</span>     report_clock_err(clkidx, &info, -1, verbose);
     ret = 1;
   }
<span style='display:block; white-space:pre;background:#e0e0e0;'>@@ -851,13 +919,13 @@ report_clock(clock_idx_t clkidx, int dump, int verbose, int quiet)
</span> 
 /* Report info about all clocks (singly) */
 static int
<span style='display:block; white-space:pre;background:#ffe0e0;'>-report_all_clocks(int dump, int verbose, int quiet)
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+report_all_clocks(int dump, int verbose, int quiet, int replay)
</span> {
   int ret = 0;
   clock_idx_t clkidx = 0;
 
   while (clkidx < (clock_idx_t) clock_idx_max) {
<span style='display:block; white-space:pre;background:#ffe0e0;'>-    ret |= report_clock(clkidx, dump, verbose, quiet);
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+    ret |= report_clock(clkidx, dump, verbose, quiet, replay);
</span>     ++clkidx;
   }
   return ret;
<span style='display:block; white-space:pre;background:#e0e0e0;'>@@ -1135,17 +1203,25 @@ get_dstats(clock_idx_t clkidx, dstats_t *dp)
</span> }
 
 /* Get and check one clock and reference */
<span style='display:block; white-space:pre;background:#e0ffe0;'>+static int clock_replay_dual_ns(clock_idx_t clkidx, int quiet);
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+
</span> static int
 check_clock_sandwich(clock_idx_t clkidx,
<span style='display:block; white-space:pre;background:#ffe0e0;'>-                     errinfo_t *ei, errinfo_t *eir, dstats_t *dp)
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+                     errinfo_t *ei, errinfo_t *eir, dstats_t *dp,
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+                     int quiet, int replay)
</span> {
   int ret, tries = 0;
   useconds_t sleepus = STD_SLEEP_US;
 
   do {
     ei->errnum = eir->errnum = errno = 0;
<span style='display:block; white-space:pre;background:#ffe0e0;'>-    usleepx(sleepus);
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>-    if ((ret = sandwich_samples(clkidx, ei))) break;
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+    if (!replay) {
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+      usleepx(sleepus);
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+      if ((ret = sandwich_samples(clkidx, ei))) break;
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+    } else {
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+      ei->retries = -1;
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+      if ((ret = clock_replay_dual_ns(clkidx, quiet))) return ret;
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+    }
</span>     sleepus = MIN(sleepus * 2, MAX_SLEEP_US);
 
     ret = check_samples(clock_idx_mach_absolute, refnsbuf, 0, eir);
<span style='display:block; white-space:pre;background:#e0e0e0;'>@@ -1155,7 +1231,7 @@ check_clock_sandwich(clock_idx_t clkidx,
</span>     if (ret) { if (ret < 0) break; continue; }
     ret = compare_clocks(clkidx, ei, eir, dp);
     if (ret <= 0) break;
<span style='display:block; white-space:pre;background:#ffe0e0;'>-  } while (++tries < MAX_STEP_TRIES);
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+  } while (!replay && ++tries < MAX_STEP_TRIES);
</span> 
   ei->retries = eir->retries = tries;
   return ret;
<span style='display:block; white-space:pre;background:#e0e0e0;'>@@ -1192,7 +1268,7 @@ clock_dump_dual_ns(clock_idx_t clkidx, errinfo_t *ei, errinfo_t *eir,
</span> 
   meanofs = (sns_time_t) (ei->first + ei->last - eir->first - eir->last) / 2;
 
<span style='display:block; white-space:pre;background:#ffe0e0;'>-  if (!(fp = open_log(clkidx, "-vs-mach", quiet))) return;
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+  if (!(fp = open_log(clkidx, "-vs-mach", quiet, 0))) return;
</span>   if (verbose >= 2) {
     fprintf(fp, "# Comparison of %d %s samples vs. mach (%s)\n",
             NUM_DIFFS, clock_names[clkidx],
<span style='display:block; white-space:pre;background:#e0e0e0;'>@@ -1241,20 +1317,64 @@ clock_dump_dual_ns(clock_idx_t clkidx, errinfo_t *ei, errinfo_t *eir,
</span>     mean = (cur + next) / 2;  diff = (sns_time_t) tstcur - mean - meanofs;
     tstmin = tstcur - (next + ei->difflim);
     tstmax = tstcur - (cur - ei->difflim);
<span style='display:block; white-space:pre;background:#ffe0e0;'>-    fprintf(fp, "%7d %19llu %5d %19llu %+5lld %+5lld %+5lld\n",
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+    fprintf(fp, " %6d %19llu %5d %19llu %+5lld %+5lld %+5lld\n",
</span>             idx, ULL cur, (int) (cur - last),
             ULL tstcur, LL diff, LL tstmin - meanofs, LL tstmax - meanofs);
     last = cur;
   }
   cur = refnsbuf[idx];
<span style='display:block; white-space:pre;background:#ffe0e0;'>-  fprintf(fp, "%7d %19llu %5d\n",
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+  fprintf(fp, " %6d %19llu %5d\n",
</span>          idx, ULL cur, (int) (cur - last));
   fclose(fp);
 }
 
<span style='display:block; white-space:pre;background:#e0ffe0;'>+/* Replay data from prior dump */
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+static int
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+clock_replay_dual_ns(clock_idx_t clkidx, int quiet)
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+{
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+  int ret = 0, count, idx = -1, diff1, diff2, ofs1, ofs2;
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+  char pfx, sep, eol, buf[256];
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+  ns_time_t cur, tstcur, *nsbuf = nsbufp[clock_types[clkidx]];
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+  FILE *fp;
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+  if (!(fp = open_log(clkidx, "-vs-mach", quiet, 1))) return -1;
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+  do {
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+    if (!fgets(buf, sizeof(buf), fp)) {
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+      ret = !feof(fp);
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+      break;
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+    }
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+    count = sscanf(buf, "%c%d %llu %d%c%llu %lld %lld %lld%c",
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+                   &pfx, &idx, ULLP &cur, &diff1, &sep,
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+                   ULLP &tstcur, LLP &diff2, LLP &ofs1, LLP &ofs2, &eol);
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+    if (count < 0) {
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+      ret = 1;
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+      break;
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+    }
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+    if (pfx == '#') continue;
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+    if (pfx != ' '
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+        || !((count == 10 && sep == ' ' && eol == '\n')
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+             || (count == 5 && sep == '\n'))) {
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+      if (!quiet) fprintf(stderr, "    Bad line at/after index %d\n", idx);
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+      ret = -1;
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+      break;
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+    }
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+    if (idx < 0 || idx >= NUM_SAMPLES
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+        || (idx >= NUM_DIFFS && sep == ' ')) {
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+      if (!quiet) fprintf(stderr, "    Skipping bad index %d\n", idx);
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+      continue;
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+    }
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+    if (sep == ' ') nsbuf[idx] = tstcur;
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+    refnsbuf[idx] = cur;
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+  } while (1);
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+  fclose(fp);
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+  return ret;
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+}
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+
</span> /* Report info about one clock comparison */
 static int
<span style='display:block; white-space:pre;background:#ffe0e0;'>-report_clock_compare(clock_idx_t clkidx, int dump, int verbose, int quiet)
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+report_clock_compare(clock_idx_t clkidx,
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+                     int dump, int verbose, int quiet, int replay)
</span> {
   int ret = 0, vnq = verbose && !quiet;
   const char *name = clock_names[clkidx];
<span style='display:block; white-space:pre;background:#e0e0e0;'>@@ -1263,7 +1383,8 @@ report_clock_compare(clock_idx_t clkidx, int dump, int verbose, int quiet)
</span> 
   if (vnq) printf("  Comparing %s to mach_absolute_time\n", name);
 
<span style='display:block; white-space:pre;background:#ffe0e0;'>-  if (check_clock_sandwich(clkidx, &info, &refinfo, &dstats)) {
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+  if (check_clock_sandwich(clkidx, &info, &refinfo, &dstats, quiet, replay)) {
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+    if (replay && info.retries < 0) return 0;  /* Just skip nonex replay */
</span>     if (refinfo.errnum) {
       report_clock_err(clock_idx_mach_absolute, &refinfo, 0, verbose);
     }
<span style='display:block; white-space:pre;background:#e0e0e0;'>@@ -1285,14 +1406,14 @@ report_clock_compare(clock_idx_t clkidx, int dump, int verbose, int quiet)
</span> 
 /* Report info about all clock comparisons */
 static int
<span style='display:block; white-space:pre;background:#ffe0e0;'>-report_all_clock_compares(int dump, int verbose, int quiet)
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+report_all_clock_compares(int dump, int verbose, int quiet, int replay)
</span> {
   int ret = 0;
   clock_idx_t clkidx = 0;
 
   while (clkidx < (clock_idx_t) clock_idx_max) {
     /* As sanity check, don't exclude self-compare */
<span style='display:block; white-space:pre;background:#ffe0e0;'>-    ret |= report_clock_compare(clkidx, dump, verbose, quiet);
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+    ret |= report_clock_compare(clkidx, dump, verbose, quiet, replay);
</span>     ++clkidx;
   }
   return ret;
<span style='display:block; white-space:pre;background:#e0e0e0;'>@@ -1784,7 +1905,7 @@ int
</span> main(int argc, char *argv[])
 {
   int argn = 1;
<span style='display:block; white-space:pre;background:#ffe0e0;'>-  int continuous = 0, dump = 0, quiet = 0, verbose = 0;
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+  int continuous = 0, dump = 0, quiet = 0, replay = 0, verbose = 0;
</span>   int err = 0, tterr, ttries;
   const char *cp;
   char chr;
<span style='display:block; white-space:pre;background:#e0e0e0;'>@@ -1797,6 +1918,7 @@ main(int argc, char *argv[])
</span>         case 'C': ++continuous; break;
         case 'd': ++dump; break;
         case 'q': ++quiet; break;
<span style='display:block; white-space:pre;background:#e0ffe0;'>+        case 'R': ++replay; break;
</span>         case 'v': ++verbose; break;
       }
     }
<span style='display:block; white-space:pre;background:#e0e0e0;'>@@ -1809,8 +1931,8 @@ main(int argc, char *argv[])
</span>   err |= check_invalid();
 
   while (!err) {
<span style='display:block; white-space:pre;background:#ffe0e0;'>-    err |= report_all_clocks(dump, verbose, quiet);
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>-    err |= report_all_clock_compares(dump, verbose, quiet);
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+    err |= report_all_clocks(dump, verbose, quiet, replay);
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+    err |= report_all_clock_compares(dump, verbose, quiet, replay);
</span>     err |= check_mach_scaling(verbose && !quiet);
 
     /*
</pre><pre style='margin:0'>

</pre>