1
0
Fork 0
mirror of git://git.code.sf.net/p/cdesktopenv/code synced 2025-02-15 04:32:24 +00:00

Fix $TIMEFORMAT zero-decimal and error behaviour (re: 70fc1da7)

The backported 'time' keyword code introduced a bug (shared by
ksh2020): the $TIMEFORMAT format sequences %0R, %0U and %0S output
a decimal fraction, acting as %1R, %1U and %1S.

A minor ksh2020 behaviour change that was also backported was that
the $TIMEFORMAT formatting no longer errored out on encountering an
invalid identifier, but continued. That behaviour is now reverted.

Neither of these two regressions occurred on older systems that
have to use times(3) instead of getrusage(2) or gettimeofday(2).

This commit also tweaks a regression test so that it doesn't fail
if the old times(3) interface is used.

src/cmd/ksh93/sh/xec.c: p_time():
- (Fix indentation of a for loop.)
- On modern systems, when outputting the result of $TIMEFORMAT
  format sequences, only print fraction if precision is nonzero.
- On modern systems, when encountering an invalid format sequence,
  abort formatting in the same way as done for old systems.
- On old systems, initialise 'n' in a more readable way when used
  as the index for tm[].

src/cmd/ksh93/tests/basic.sh:
- Don't fail, but issue warning on old systems that use times(3).
  Otherwise, check milliseconds: with the ksh 'sleep' builtin,
  'TIMEFORMAT=%3R; time sleep .002' should always output '0.002'.
- Change regression test for TIMEFORMAT='%0S%' to check for the
  correct output, '0%', instead of checking for an error message.
This commit is contained in:
Martijn Dekker 2020-07-15 01:53:12 +01:00
parent 70fc1da73e
commit c5820aabc9
2 changed files with 26 additions and 16 deletions

View file

@ -295,9 +295,6 @@ static void p_time(Shell_t *shp, Sfio_t *out, const char *format, clock_t *tm)
continue;
unsigned char l_modifier = 0;
int precision = 3;
#ifndef timeofday
n = 0;
#endif
sfwrite(stkp, first, format-first);
c = *++format;
@ -353,8 +350,9 @@ static void p_time(Shell_t *shp, Sfio_t *out, const char *format, clock_t *tm)
tvp = &tm[TM_SYS_IDX];
else
{
stkseek(stkp,offset);
errormsg(SH_DICT,ERROR_exit(0),e_badtformat,c);
continue;
return;
}
if(l_modifier)
l_time(stkp, tvp, precision);
@ -362,15 +360,21 @@ static void p_time(Shell_t *shp, Sfio_t *out, const char *format, clock_t *tm)
{
/* scale fraction from micro to milli, centi, or deci second according to precision */
int n, frac = tvp->tv_usec;
for(n = 3 + (3 - precision); n > 0; --n) frac /= 10;
sfprintf(stkp, "%d%c%0*d", tvp->tv_sec, GETDECIMAL(0), precision, frac);
for(n = 3 + (3 - precision); n > 0; --n)
frac /= 10;
if(precision)
sfprintf(stkp, "%d%c%0*d", tvp->tv_sec, GETDECIMAL(0), precision, frac);
else
sfprintf(stkp, "%d", tvp->tv_sec);
}
#else
if(c=='U')
if(c=='R')
n = 0;
else if(c=='U')
n = 1;
else if(c=='S')
n = 2;
else if(c!='R')
else
{
stkseek(stkp,offset);
errormsg(SH_DICT,ERROR_exit(0),e_badtformat,c);

View file

@ -553,25 +553,31 @@ $SHELL 2> /dev/null -c $'for i;\ndo :;done' || err_exit 'for i ; <newline> not v
) || err_exit "crash when sourcing multiple files (exit status $?)"
# ======
# The time keyword should correctly handle millisecond precision.
# This can be checked by verifying the last digit is not a zero
# when 'time sleep .002' is run.
# The time keyword should correctly handle millisecond precision, except
# on older systems that do not support getrusage(2) or gettimeofday(2).
result=$(
TIMEFORMAT=$'\%3R'
redirect 2>&1
time sleep .002
)
[[ ${result: -1} == 0 ]] && err_exit "the 'time' keyword doesn't properly support millisecond precision"
case $result in
0.000 | 0.010)
err_exit "warning: 'time' keyword doesn't support millisecond precision"
let "Errors--" ;;
0.002) ;;
*) err_exit "'time' keyword, millisecond precision: expected 0.002, got $result" ;;
esac
# A single '%' after a format specifier should not be a syntax
# error (it should be treated as a literal '%').
IFS=' '
result=( $(
expect='0%'
actual=$(
TIMEFORMAT=$'%0S%'
redirect 2>&1
time :
) )
[[ ${result[4]} == bad ]] && err_exit "'%' is not treated literally when placed after a format specifier"
)
[[ $actual == "$expect" ]] || err_exit "'%' is not treated literally when placed after a format specifier" \
"(expected $(printf %q "$expect"), got $(printf %q "$actual"))"
# The locale's radix point shouldn't be ignored
us=$(