From 1cac2585217f830d29f7e9d2a1226d55c80886b6 Mon Sep 17 00:00:00 2001 From: Denys Vlasenko Date: Mon, 1 Jan 2024 22:22:15 +0100 Subject: time: implement %% and \escapes in -f FMT function old new delta time_main 1217 1316 +99 Signed-off-by: Denys Vlasenko --- miscutils/time.c | 39 ++++++++++++++++++--------------------- testsuite/time.tests | 37 +++++++++++++++++++++++++++++++++++++ 2 files changed, 55 insertions(+), 21 deletions(-) create mode 100755 testsuite/time.tests diff --git a/miscutils/time.c b/miscutils/time.c index 4b1b043c3..77d35a832 100644 --- a/miscutils/time.c +++ b/miscutils/time.c @@ -226,28 +226,19 @@ static void summarize(const char *fmt, char **command, resource_t *resp) } switch (*fmt) { -#ifdef NOT_NEEDED - /* Handle literal char */ - /* Usually we optimize for size, but there is a limit - * for everything. With this we do a lot of 1-byte writes */ - default: - bb_putchar(*fmt); - break; -#endif - case '%': switch (*++fmt) { -#ifdef NOT_NEEDED_YET - /* Our format strings do not have these */ - /* and we do not take format str from user */ default: - bb_putchar('%'); + /* Unknown % is printed as "?" */ + bb_putchar('?'); + if (!*fmt) { + /* Trailing -f '...%' prints "...?" but NOT newline */ + goto ret; + } /*FALLTHROUGH*/ case '%': - if (!*fmt) goto ret; bb_putchar(*fmt); break; -#endif case 'C': /* The command that got timed. */ printargv(command); break; @@ -381,14 +372,21 @@ static void summarize(const char *fmt, char **command, resource_t *resp) } break; -#ifdef NOT_NEEDED_YET - case '\\': /* Format escape. */ + default: /* *fmt is '\': format escape */ switch (*++fmt) { default: + /* Unknown \ is printed as "?\" */ + bb_putchar('?'); bb_putchar('\\'); + if (!*fmt) { + /* Trailing -f '...\': GNU time 1.9 prints + * "...?\COMMAND" (it's probably a bug). + */ + puts(command[0]); + goto ret; + } /*FALLTHROUGH*/ case '\\': - if (!*fmt) goto ret; bb_putchar(*fmt); break; case 't': @@ -399,12 +397,11 @@ static void summarize(const char *fmt, char **command, resource_t *resp) break; } break; -#endif } ++fmt; } - /* ret: */ bb_putchar('\n'); + ret: ; } /* Run command CMD and return statistics on it. @@ -438,7 +435,7 @@ int time_main(int argc, char **argv) MAIN_EXTERNALLY_VISIBLE; int time_main(int argc UNUSED_PARAM, char **argv) { resource_t res; - /* $TIME has lowest prio (-v,-p,-f FMT overrride it) */ + /* $TIME has lowest prio (-v,-p,-f FMT override it) */ const char *output_format = getenv("TIME") ? : default_format; char *output_filename; int output_fd; diff --git a/testsuite/time.tests b/testsuite/time.tests new file mode 100755 index 000000000..4e31b3868 --- /dev/null +++ b/testsuite/time.tests @@ -0,0 +1,37 @@ +#!/bin/sh + +# Copyright 2024 by Denys Vlasenko +# Licensed under GPLv2, see file LICENSE in this source tree. + +. ./testing.sh + +# testing "description" "arguments" "result" "infile" "stdin" + +testing "time -f trailing backslash" \ + "time -f 'abc\' sleep 0 2>&1" \ + 'abc?\sleep\n' '' '' +# ^^^^^^^^^^^^^^ this is what GNU time version 1.9 prints + +testing "time -f trailing percent" \ + "time -f 'abc%' sleep 0 2>&1" \ + 'abc?' '' '' + +testing "time -f undefined backslash" \ + "time -f 'abc\^def' sleep 0 2>&1" \ + 'abc?\^def\n' '' '' + +testing "time -f undefined percent" \ + "time -f 'abc%^def' sleep 0 2>&1" \ + 'abc?^def\n' '' '' + +testing "time -f backslash tab and newline" \ + "time -f 'abc\ndef\txyz' sleep 0 2>&1" \ + 'abc +def xyz +' '' '' + +testing "time -f percent percent" \ + "time -f 'abc%%def' sleep 0 2>&1" \ + 'abc%def\n' '' '' + +exit $FAILCOUNT -- cgit v1.2.3