This is the same patch as in the previous post, but this one is for bash-5.2.

Additionally,

1) Backported the six-digit TIMEFORMAT precision from bash-5.3;

2) Fixed all the outstanding issues from the previous post;

3) Cleaned up the patch a little more.

Tested on Slackware, on Alpine Linux, and on Cygwin.

Patch (apply with `patch -p0'):


https://cgit.git.savannah.gnu.org/cgit/bash.git/commit/execute_cmd.c?h=devel&id=b91488b51cae38a7e07b7567b6ac42ea19d02740
Date: Fri, 16 Jun 2023 12:49:11 -0400
Subject: [..] TIMEFORMAT now accepts precisions up to six digits


(9/30/2025) Pourko:

For bash-5.2:

This patch makes the following changes to the `time' command:

0) TIMEFORMAT now accepts precisions up to six digits. (Backported from 5.3)

1) Adds a compile-time choice to use CLOCK_MONOTONIC, if available.
As a result, now we have a good timing accuracy on Cygwin too.

2) If shell-var TIMEWARMUP exists, and if it is set to an integer N>0, then
`time' runs a warmup loop N times, in hope to awaken idled-down CPUs before 
timing the command.  This can improve the accuracy of the measurement.
The observed benefit of this varies widely from one type of CPU to another. 
(Down to no effect whatsoever on some.)

3) If shell-var TIMEREPEAT exists, and if it is set to an integer N>1, then
`time' runs the command N times before taking the final clock-reading.

4) `time' leaves the elapsed time (wall clock) result in shell-var TIMERESULT,
according to the "%[p][l]R" portion of the TIMEFORMAT variable.

5) By moving the "before" and "after" clock-readings as close as possible to 
the 
command that's being timed, it noticeably increases the accuracy of the results
when measuring some fast, short-lasting commands.

6) Cleaned up some code for which I couldn't find a way to leave it as-is.
I left comments about the necessity of the changes.

7) Several bugs were fixed.

Patch (apply with `patch -p0'):

--- execute_cmd.c
+++ ../bash-5.2-patched/execute_cmd.c   Tue Sep 30 01:24:05 2025
@@ -108,6 +108,9 @@
 
 extern int command_string_index;
 extern char *the_printed_command;
+#if defined (CLOCK_MONOTONIC)
+extern struct timespec ts_shellstart;
+#endif
 extern time_t shell_start_time;
 #if defined (HAVE_GETTIMEOFDAY)
 extern struct timeval shellstart;
@@ -148,10 +151,10 @@
 static int execute_cond_command PARAMS((COND_COM *));
 #endif
 #if defined (COMMAND_TIMING)
-static int mkfmt PARAMS((char *, int, int, time_t, int));
+static int mkfmt PARAMS((char *, int, int, time_t, long));
 static void print_formatted_time PARAMS((FILE *, char *,
-                                     time_t, int, time_t, int,
-                                     time_t, int, int));
+                                     time_t, long, time_t, long,
+                                     time_t, long, int));
 static int time_command PARAMS((COMMAND *, int, int, int, struct fd_bitmap *));
 #endif
 #if defined (ARITH_FOR_COMMAND)
@@ -1154,24 +1157,31 @@
 
 #if defined (COMMAND_TIMING)
 
-#if defined (HAVE_GETRUSAGE) && defined (HAVE_GETTIMEOFDAY)
+#define TEST_NEW_TIMEWARMUP
+#define TEST_NEW_TIMEREPEAT
+#define TEST_NEW_TIMERESULT
+
+#if defined (HAVE_GETRUSAGE) || defined (HAVE_GETTIMEOFDAY)
 extern struct timeval *difftimeval PARAMS((struct timeval *, struct timeval *, 
struct timeval *));
 extern struct timeval *addtimeval PARAMS((struct timeval *, struct timeval *, 
struct timeval *));
 extern int timeval_to_cpu PARAMS((struct timeval *, struct timeval *, struct 
timeval *));
 #endif
 
+#if defined (CLOCK_MONOTONIC)
+extern struct timespec *difftimespec (struct timespec *, struct timespec *, 
struct timespec *);
+#endif
+
 #define POSIX_TIMEFORMAT "real %2R\nuser %2U\nsys %2S"
 #define BASH_TIMEFORMAT  "\nreal\t%3lR\nuser\t%3lU\nsys\t%3lS"
 
-static const int precs[] = { 0, 100, 10, 1 };
+static const int precs[] = { 0, 100000, 10000, 1000, 100, 10, 1 };
+static const int maxvals[] = { 1, 10, 100, 1000, 10000, 100000, 10000000 };
 
 /* Expand one `%'-prefixed escape sequence from a time format string. */
-static int
-mkfmt (buf, prec, lng, sec, sec_fraction)
-     char *buf;
-     int prec, lng;
-     time_t sec;
-     int sec_fraction;
+/* SEC_FRACTION is in usecs. We normalize and round that based on the
+  precision. */
+int
+mkfmt (char *buf, int prec, int lng, time_t sec, long sec_fraction)
 {
   time_t min;
   char abuf[INT_STRLEN_BOUND(time_t) + 1];
@@ -1205,10 +1215,31 @@
     buf[ind++] = abuf[aind++];
 
   /* We want to add a decimal point and PREC places after it if PREC is
-     nonzero.  PREC is not greater than 3.  SEC_FRACTION is between 0
-     and 999. */
+     nonzero.  PREC is not greater than 6.  SEC_FRACTION is between 0
+     and 999999 (microseconds). */
   if (prec != 0)
     {
+      /* We round here because we changed timeval_to_secs to return
+        microseconds and normalized clock_t_to_secs's fractional return
+        value to microseconds, deferring the work to be done to now.
+
+        sec_fraction is in microseconds. Take the value, cut off what we
+        don't want, round up if necessary, then convert back to
+        microseconds. */
+      if (prec != 6)
+       {
+         int frac, rest, maxval;
+
+         maxval = maxvals[6 - prec];
+         frac = sec_fraction / maxval;
+         rest = sec_fraction % maxval;
+
+         if (rest >= maxval/2)
+         frac++;
+
+         sec_fraction = frac * (1000000 / maxvals[prec]);
+       }
+  
       buf[ind++] = locale_decpoint ();
       for (aind = 1; aind <= prec; aind++)
        {
@@ -1242,20 +1273,14 @@
    the seconds and thousandths of a second of real, user, and system time,
    resectively. */
 static void
-print_formatted_time (fp, format, rs, rsf, us, usf, ss, ssf, cpu)
-     FILE *fp;
-     char *format;
-     time_t rs;
-     int rsf;
-     time_t us;
-     int usf;
-     time_t ss;
-     int ssf, cpu;
+print_formatted_time (FILE *fp, char *format,
+                     time_t rs, long rsf, time_t us, long usf, time_t ss, long 
ssf,
+                     int cpu)
 {
   int prec, lng, len;
   char *str, *s, ts[INT_STRLEN_BOUND (time_t) + sizeof ("mSS.FFFF")];
   time_t sum;
-  int sum_frac;
+  long sum_frac;
   int sindex, ssize;
 
   len = strlen (format);
@@ -1279,13 +1304,8 @@
       else if (s[1] == 'P')
        {
          s++;
-#if 0
-         /* clamp CPU usage at 100% */
-         if (cpu > 10000)
-           cpu = 10000;
-#endif
          sum = cpu / 100;
-         sum_frac = (cpu % 100) * 10;
+         sum_frac = (cpu % 100) * 10000;
          len = mkfmt (ts, 2, 0, sum, sum_frac);
          RESIZE_MALLOCED_BUFFER (str, sindex, len, ssize, 64);
          strcpy (str + sindex, ts);
@@ -1299,7 +1319,7 @@
          if (DIGIT (*s))               /* `precision' */
            {
              prec = *s++ - '0';
-             if (prec > 3) prec = 3;
+             if (prec > 6) prec = 6;
            }
          if (*s == 'l')                /* `length extender' */
            {
@@ -1307,7 +1327,12 @@
              s++;
            }
          if (*s == 'R' || *s == 'E')
+         {
            len = mkfmt (ts, prec, lng, rs, rsf);
+#if defined (TEST_NEW_TIMERESULT)
+        bind_variable ("TIMERESULT", ts, 0);
+#endif /* TEST_NEW_TIMERESULT */
+         }
          else if (*s == 'U')
            len = mkfmt (ts, prec, lng, us, usf);
          else if (*s == 'S')
@@ -1338,62 +1363,98 @@
      struct fd_bitmap *fds_to_close;
 {
   int rv, posix_time, old_flags, nullcmd, code;
-  time_t rs, us, ss;
-  int rsf, usf, ssf;
+  time_t rs, us, ss;           /* seconds */
+  long rsf, usf, ssf;          /* microseconds */
   int cpu;
   char *time_format;
   volatile procenv_t save_top_level;
   volatile int old_subshell;
-
-#if defined (HAVE_GETRUSAGE) && defined (HAVE_GETTIMEOFDAY)
-  struct timeval real, user, sys;
-  struct timeval before, after;
-#  if defined (HAVE_STRUCT_TIMEZONE)
-  struct timezone dtz;                         /* posix doesn't define this */
-#  endif
-  struct rusage selfb, selfa, kidsb, kidsa;    /* a = after, b = before */
-#else
-#  if defined (HAVE_TIMES)
-  clock_t tbefore, tafter, real, user, sys;
-  struct tms before, after;
-#  endif
-#endif
-
-#if defined (HAVE_GETRUSAGE) && defined (HAVE_GETTIMEOFDAY)
-#  if defined (HAVE_STRUCT_TIMEZONE)
-  gettimeofday (&before, &dtz);
-#  else
-  gettimeofday (&before, (void *)NULL);
-#  endif /* !HAVE_STRUCT_TIMEZONE */
-  getrusage (RUSAGE_SELF, &selfb);
-  getrusage (RUSAGE_CHILDREN, &kidsb);
-#else
-#  if defined (HAVE_TIMES)
-  tbefore = times (&before);
-#  endif
-#endif
-
-  old_subshell = subshell_environment;
-  posix_time = command && (command->flags & CMD_TIME_POSIX);
-
-  nullcmd = (command == 0) || (command->type == cm_simple && 
command->value.Simple->words == 0 && command->value.Simple->redirects == 0);
-  if (posixly_correct && nullcmd)
-    {
-#if defined (HAVE_GETRUSAGE)
-      selfb.ru_utime.tv_sec = kidsb.ru_utime.tv_sec = selfb.ru_stime.tv_sec = 
kidsb.ru_stime.tv_sec = 0;
-      selfb.ru_utime.tv_usec = kidsb.ru_utime.tv_usec = selfb.ru_stime.tv_usec 
= kidsb.ru_stime.tv_usec = 0;
-      before = shellstart;
-#else
-      before.tms_utime = before.tms_stime = before.tms_cutime = 
before.tms_cstime = 0;
-      tbefore = shell_start_time;
-#endif
-    }
-
+  
+  rs = rsf = us = usf = ss = ssf = cpu = 0;
+  
+  old_subshell = subshell_environment; 
+  posix_time = command && (command->flags & CMD_TIME_POSIX); 
+  nullcmd = (command == 0) || (command->type == cm_simple && 
command->value.Simple->words == 0 && command->value.Simple->redirects == 0); 
+  
+#if defined (TEST_NEW_TIMEWARMUP)
+  /* If variable TIMEWARMUP exists, and if it is set to an integer N>1,
+     then time_command will first run a warmup loop N times to increase the
+     CPU frequencies. This greatly improves the accuracy of the measurement. */
+  intmax_t nwarmup;
+  char *vwarmup = get_string_value ("TIMEWARMUP");
+  if (vwarmup == 0 || *vwarmup == 0 || legal_number (vwarmup, &nwarmup) == 0 
|| nwarmup < 0)
+    nwarmup = 0;  // default: no warmup
+  if (! nullcmd)
+    while (nwarmup--) { asm ("PAUSE"); QUIT; } // asm, so the compiler doesn't 
"optimize" this out.
+#endif /* TEST_NEW_TIMEWARMUP */
+  
+#if defined (TEST_NEW_TIMEREPEAT)
+  /* If variable TIMEREPEAT exists, and if it is set to an integer N>1,
+    then time_command will execute the pipeline N times between the
+    "before" and the "after" time-readings. */
+  intmax_t nrepeat;
+  char *vrepeat = get_string_value ("TIMEREPEAT");
+  if (vrepeat == 0 || *vrepeat == 0 || legal_number (vrepeat, &nrepeat) == 0 
|| nrepeat < 1)
+    nrepeat = 1;  // default: run the command once.
+#endif /* TEST_NEW_TIMEREPEAT */
+
+#if 0 /* REMOVE!
+     We don't need to involve time-zones in this. When taking "before" and 
"after" readings,
+     their difference will be the time-elapsed, regardless of which time-zone 
we're in. */
+#  if defined (HAVE_STRUCT_TIMEZONE) 
+  struct timezone dtz;                         /* posix doesn't define this */ 
+#  endif 
+#endif /* 0 */
+
+/* There are two kinds of readings we need to do here, and we need to keep 
these two 
+   separate for things to work properly. One is the reading of the wall-clock, 
which
+   can be accomplished by either one of clock_gettime(), gettimeofday(), or 
times(),
+   in order of preference. The other kind is the reading of the urs/sys times, 
which
+   can be accomplished by either getrusage() or times().  In the original code,
+   getrusage() and gettimeofday() were meshed together in a strange 
interdependency,
+   and one would not compile without the other, and it was really messy when 
trying
+   to add a new wall-clock.  By untangling these two kinds of readings, 
everything
+   compiles nicely, and was tested to work for any combination of 
absence/presence 
+   of the aforementioned four functions. It makes it easy to rearrange the 
order of
+   the clock-sources, if needed, or to add a new clock-source in the future. */
+  
+#if defined (HAVE_GETRUSAGE) 
+  struct rusage selfb, selfa, kidsb, kidsa;    /* a = after, b = before */ 
+  getrusage (RUSAGE_SELF, &selfb); 
+  getrusage (RUSAGE_CHILDREN, &kidsb); 
+#elif defined (HAVE_TIMES)
+#  ifndef USING_TIMES  
+#    define USING_TIMES   /* ..as this can be the fallback in two separate 
cases. */
+     clock_t t_before, t_after, t_real, t_user, t_sys;
+     struct tms tms_before, tms_after;
+     t_before = times (&tms_before);
+#  endif /* USING_TIMES */
+#endif /* HAVE_GETRUSAGE */
+
+#if defined (CLOCK_MONOTONIC)
+  struct timespec ts_before, ts_after, ts_real;
+  clock_gettime (CLOCK_MONOTONIC, &ts_before);
+#elif defined (HAVE_GETTIMEOFDAY)
+  struct timeval tv_before, tv_after, tv_real;
+  gettimeofday (&tv_before, NULL);
+#elif defined (HAVE_TIMES)
+#  ifndef USING_TIMES
+#    define USING_TIMES
+     clock_t t_before, t_after, t_real, t_user, t_sys;
+     struct tms tms_before, tms_after;
+     t_before = times (&tms_before);
+#  endif /* USING_TIMES */
+#endif /* CLOCK_MONOTONIC */
+  
+// 
########################################################################################
   old_flags = command->flags;
   COPY_PROCENV (top_level, save_top_level);
   command->flags &= ~(CMD_TIME_PIPELINE|CMD_TIME_POSIX);
   code = setjmp_nosigs (top_level);
   if (code == NOT_JUMPED)
+#if defined (TEST_NEW_TIMEREPEAT)
+    while (nrepeat--)
+#endif /* TEST_NEW_TIMEREPEAT */
     rv = execute_command_internal (command, asynchronous, pipe_in, pipe_out, 
fds_to_close);
   COPY_PROCENV (save_top_level, top_level);
 
@@ -1404,52 +1465,84 @@
      original top level. */
   if (code != NOT_JUMPED && subshell_environment && subshell_environment != 
old_subshell)
     sh_longjmp (top_level, code);
-
-  rs = us = ss = 0;
-  rsf = usf = ssf = cpu = 0;
-
-#if defined (HAVE_GETRUSAGE) && defined (HAVE_GETTIMEOFDAY)
-#  if defined (HAVE_STRUCT_TIMEZONE)
-  gettimeofday (&after, &dtz);
-#  else
-  gettimeofday (&after, (void *)NULL);
-#  endif /* !HAVE_STRUCT_TIMEZONE */
-  getrusage (RUSAGE_SELF, &selfa);
-  getrusage (RUSAGE_CHILDREN, &kidsa);
-
-  difftimeval (&real, &before, &after);
-  timeval_to_secs (&real, &rs, &rsf);
-
-  addtimeval (&user, difftimeval(&after, &selfb.ru_utime, &selfa.ru_utime),
-                    difftimeval(&before, &kidsb.ru_utime, &kidsa.ru_utime));
-  timeval_to_secs (&user, &us, &usf);
-
-  addtimeval (&sys, difftimeval(&after, &selfb.ru_stime, &selfa.ru_stime),
-                   difftimeval(&before, &kidsb.ru_stime, &kidsa.ru_stime));
-  timeval_to_secs (&sys, &ss, &ssf);
-
-  cpu = timeval_to_cpu (&real, &user, &sys);
-#else
-#  if defined (HAVE_TIMES)
-  tafter = times (&after);
-
-  real = tafter - tbefore;
-  clock_t_to_secs (real, &rs, &rsf);
-
-  user = (after.tms_utime - before.tms_utime) + (after.tms_cutime - 
before.tms_cutime);
-  clock_t_to_secs (user, &us, &usf);
-
-  sys = (after.tms_stime - before.tms_stime) + (after.tms_cstime - 
before.tms_cstime);
-  clock_t_to_secs (sys, &ss, &ssf);
-
-  cpu = (real == 0) ? 0 : ((user + sys) * 10000) / real;
-
-#  else
-  rs = us = ss = 0;
-  rsf = usf = ssf = cpu = 0;
-#  endif
-#endif
-
+// 
########################################################################################
+  
+  /* Take the "after" wall-clock readings, before anything else. */
+#if defined (CLOCK_MONOTONIC)
+  clock_gettime (CLOCK_MONOTONIC, &ts_after);
+#elif defined (HAVE_GETTIMEOFDAY)
+  gettimeofday (&tv_after, NULL);
+#endif  
+  
+  /* The proper place for this is here. */
+  if (posixly_correct && nullcmd) {
+#if defined (USING_TIMES)
+      tms_before.tms_utime = tms_before.tms_stime = tms_before.tms_cutime = 
tms_before.tms_cstime = 0;
+      t_before = shell_start_time * get_clk_tck();
+#endif 
+#if defined (HAVE_GETRUSAGE)
+      selfb.ru_utime.tv_sec = kidsb.ru_utime.tv_sec = selfb.ru_stime.tv_sec = 
kidsb.ru_stime.tv_sec = 0;
+      selfb.ru_utime.tv_usec = kidsb.ru_utime.tv_usec = selfb.ru_stime.tv_usec 
= kidsb.ru_stime.tv_usec = 0;
+#endif 
+#if defined (CLOCK_MONOTONIC)
+        ts_before = ts_shellstart;  // timespec
+#elif defined (HAVE_GETTIMEOFDAY)
+        tv_before = shellstart;  // timeval
+#endif 
+  }
+  
+  /* It is important that we put this here... */
+#if defined (USING_TIMES)
+  t_after = times (&tms_after);
+  
+  t_real = t_after - t_before;  // ticks
+  clock_t_to_secs (t_real, &rs, &rsf);
+  /* clock_t_to_secs returns RSF in milliseconds; multipy by 1000 to get 
microseconds. */ 
+  rsf *= 1000; 
+   
+  t_user = (tms_after.tms_utime - tms_before.tms_utime) + 
(tms_after.tms_cutime - tms_before.tms_cutime); 
+  clock_t_to_secs (t_user, &us, &usf); 
+  usf *= 1000; 
+ 
+  t_sys = (tms_after.tms_stime - tms_before.tms_stime) + (tms_after.tms_cstime 
- tms_before.tms_cstime); 
+  clock_t_to_secs (t_sys, &ss, &ssf); 
+  ssf *= 1000; 
+ 
+  cpu = (t_real == 0) ? 0 : ((t_user + t_sys) * 10000) / t_real; 
+#endif 
+   
+  // The current version of time_command() needs the seconds fraction in 
microseconds. So...
+  int sf_scale = 1000000;
+  
+#if defined (HAVE_GETRUSAGE)
+  getrusage (RUSAGE_SELF, &selfa); 
+  getrusage (RUSAGE_CHILDREN, &kidsa); 
+  
+  struct timeval rutv_before, rutv_after, rutv_user, rutv_sys;
+  
+  addtimeval (&rutv_user, difftimeval(&rutv_after, &selfb.ru_utime, 
&selfa.ru_utime),
+                         difftimeval(&rutv_before, &kidsb.ru_utime, 
&kidsa.ru_utime));
+  timeval_to_secs (&rutv_user, &us, &usf, sf_scale);
+
+  addtimeval (&rutv_sys, difftimeval(&rutv_after, &selfb.ru_stime, 
&selfa.ru_stime),
+                        difftimeval(&rutv_before, &kidsb.ru_stime, 
&kidsa.ru_stime));
+  timeval_to_secs (&rutv_sys, &ss, &ssf, sf_scale);
+#endif 
+  
+#if defined (CLOCK_MONOTONIC)
+  difftimespec (&ts_real, &ts_before, &ts_after);
+  timespec_to_secs (&ts_real, &rs, &rsf, sf_scale);
+#elif defined (HAVE_GETTIMEOFDAY)
+  difftimeval (&tv_real, &tv_before, &tv_after);
+  timeval_to_secs (&tv_real, &rs, &rsf, sf_scale);
+#endif 
+  
+  long real_scaled = rs * sf_scale + rsf;
+  if (real_scaled>0) {
+    long usr_sys_scaled = (us + ss) * sf_scale + usf + ssf;
+    cpu = usr_sys_scaled * 10000 / real_scaled;  // *100 for percent, then 
another *100 to keep 2 fract digits.
+  }
+  
   if (posix_time)
     time_format = POSIX_TIMEFORMAT;
   else if ((time_format = get_string_value ("TIMEFORMAT")) == 0)
--- lib/sh/timeval.c    Thu Jun 15 16:02:53 2023
+++ ../bash-5.2-patched/lib/sh/timeval.c        Mon Sep 29 04:30:30 2025
@@ -53,6 +53,24 @@
   return d;
 }
 
+struct timespec *
+difftimespec (struct timespec *d, struct timespec *t1, struct timespec *t2)
+{
+  d->tv_sec = t2->tv_sec - t1->tv_sec;
+  d->tv_nsec = t2->tv_nsec - t1->tv_nsec;
+  if (d->tv_nsec < 0)
+    {
+      d->tv_nsec += 1000000000;
+      d->tv_sec -= 1;
+      if (d->tv_sec < 0)               /* ??? -- BSD/OS does this */
+       {
+         d->tv_sec = 0;
+         d->tv_nsec = 0;
+       }
+    }
+  return d;
+}
+
 struct timeval *
 addtimeval (d, t1, t2)
      struct timeval *d, *t1, *t2;
@@ -130,31 +148,43 @@
   return ((t2.tv_sec == 0) ? 0 : t1.tv_sec / t2.tv_sec);
 }  
 
-/* Convert a pointer to a struct timeval to seconds and thousandths of a
-   second, returning the values in *SP and *SFP, respectively.  This does
-   rounding on the fractional part, not just truncation to three places. */
-void
-timeval_to_secs (tvp, sp, sfp)
-     struct timeval *tvp;
-     time_t *sp;
-     int *sfp;
-{
-  int rest;
 
-  *sp = tvp->tv_sec;
+long timeval_scale = 1000000;
+long timespec_scale = 1000000000;
 
-  *sfp = tvp->tv_usec % 1000000;       /* pretty much a no-op */
-  rest = *sfp % 1000;
-  *sfp = (*sfp * 1000) / 1000000;
-  if (rest >= 500)
-    *sfp += 1;
+/* Convert a pointer to a struct timeval to seconds and thousandths of a
+   second, returning the values in *SP and *SFP, respectively.  This does
+   rounding on the fractional part. */
+void timeval_to_secs (struct timeval *tvp, time_t *sp, long *sfp, long 
frac_scale) {
+  long mul, div, base_scale = timeval_scale;
+  *sp = tvp->tv_sec; 
+  *sfp = tvp->tv_usec; 
+  
+  if (frac_scale < base_scale) {
+    div = base_scale / frac_scale;
+    *sfp = ( *sfp * 10 / div + 5) / 10;
+  }
+  
+  if (frac_scale > base_scale) {
+    mul = frac_scale / base_scale;
+    *sfp = *sfp * mul;
+  }
+}
 
-  /* Sanity check */
-  if (*sfp >= 1000)
-    {
-      *sp += 1;
-      *sfp -= 1000;
-    }
+void timespec_to_secs (struct timespec *tsp, time_t *sp, long *sfp, long 
frac_scale) {
+  long mul, div, base_scale = timespec_scale;
+  *sp = tsp->tv_sec; 
+  *sfp = tsp->tv_nsec; 
+  
+  if (frac_scale < base_scale) {
+    div = base_scale / frac_scale;
+    *sfp = ( *sfp * 10 / div + 5) / 10;
+  }
+  
+  if (frac_scale > base_scale) {
+    mul = frac_scale / base_scale;
+    *sfp = *sfp * mul;
+  }
 }
   
 /* Print the contents of a struct timeval * in a standard way to stdio
@@ -166,14 +196,14 @@
 {
   time_t timestamp;
   long minutes;
-  int seconds, seconds_fraction;
+  long seconds, seconds_fraction;
 
-  timeval_to_secs (tvp, &timestamp, &seconds_fraction);
+  timeval_to_secs (tvp, &timestamp, &seconds_fraction, timeval_scale);
 
   minutes = timestamp / 60;
   seconds = timestamp % 60;
 
-  fprintf (fp, "%ldm%d%c%03ds",  minutes, seconds, locale_decpoint (), 
seconds_fraction);
+  fprintf (fp, "%ldm%ld%c%03lds",  minutes, seconds, locale_decpoint (), 
seconds_fraction);
 }
 
 #endif /* HAVE_TIMEVAL */
--- externs.h   Fri Mar  7 17:48:53 2025
+++ ../bash-5.2-patched/externs.h       Mon Sep 29 03:43:26 2025
@@ -500,6 +500,7 @@
    so we don't have to count on having a definition of struct timeval in
    scope when this file is included. */
 extern void timeval_to_secs ();
+extern void timespec_to_secs ();
 extern void print_timeval ();
 
 /* declarations for functions defined in lib/sh/tmpfile.c */
--- shell.c     Wed Mar 26 15:40:19 2025
+++ ../bash-5.2-patched/shell.c Mon Sep 29 20:02:44 2025
@@ -191,6 +191,7 @@
 /* time in seconds when the shell was started */
 time_t shell_start_time;
 struct timeval shellstart;
+struct timespec ts_shellstart;
 
 /* Are we running in an emacs shell window? */
 int running_under_emacs;
@@ -466,6 +467,7 @@
   shell_environment = env;
   set_shell_name (argv[0]);
 
+  clock_gettime (CLOCK_MONOTONIC, &ts_shellstart);
   gettimeofday (&shellstart, 0);
   shell_start_time = shellstart.tv_sec;
 
--

Reply via email to