From a42ac7e77a0262cfcb0cfab4ae5015bf963daa9d Mon Sep 17 00:00:00 2001 From: Martijn Dekker Date: Thu, 16 Jul 2020 04:23:40 +0100 Subject: [PATCH] Fix annoying usage/--help/--man message corruption In a locale other than C/POSIX, ksh produces corrupted usage messages for alternatives, e.g. this output of 'typeset -\?': | Usage: typeset [-bflmnprstuxACHS] [-a[type]] [-i[base]] <..CUT..> | [-T[tname]] [-Z[n]] [name[=value]...] | Or:[name[=value]...] | typeset[name[=value]...] | [[name[=value]...] | options[name[=value]...] | ] -f [name...] Correct output is: | Usage: typeset [-bflmnprstuxACHS] [-a[type]] [-i[base]] <..CUT..> | [-T[tname]] [-Z[n]] [name[=value]...] | Or: typeset [ options ] -f [name...] Similar corruption occurs in --help and --man output. This bug is ancient: it's already in ksh 1993-12-28 s+. ksh2020 has this fixed. A 'git bisect' run pinpointed the fix to this commit, which fixes the ERROR_translating macro after removing the AST-specific locale subsystem: https://github.com/att/ast/commit/4abc061e But making the same change in ksh 93u+m produced no results (probably because we have not removed that subsystem). However, disabling the use of translation macros in optget.sh altogether (replacing them with dummies that were already coded in a preprocessor directive fallback for a reduced standalone libast) turns out to work. It's not as if there is actually any translation anyway, so this effectively fixes this bug. The actual cause of this bug remains mysterious, but should be somewhere in the AST translation and/or locale subsystem. src/lib/libast/misc/optget.c: - Use fallback translation macros. src/cmd/ksh93/tests/builtins.sh: - Add regression tests for output of -?, --?x, --help and --man for a usage string with an alternative ("Or:") usage message. Before the fix, these failed when running the tests in the C.UTF-8 locale (as in 'bin/shtests -u builtins'). --- src/cmd/ksh93/tests/builtins.sh | 72 +++++++++++++++++++++++++++++++++ src/lib/libast/misc/optget.c | 2 +- 2 files changed, 73 insertions(+), 1 deletion(-) diff --git a/src/cmd/ksh93/tests/builtins.sh b/src/cmd/ksh93/tests/builtins.sh index 6fd3893f6..3dde36cfd 100755 --- a/src/cmd/ksh93/tests/builtins.sh +++ b/src/cmd/ksh93/tests/builtins.sh @@ -774,5 +774,77 @@ unset foo [[ $(printf '%(%f)T') == $(printf '%(%Y.%m.%d-%H:%M:%S)T') ]] || err_exit 'date format %f is not the same as %Y.%m.%d-%H:%M:%S' [[ $(printf '%(%q)T') == $(printf '%(%Qz)T') ]] && err_exit 'date format %q is the same as %Qz' +# ====== +# Test various AST getopts usage/manual outputs + +OPTIND=1 +USAGE=$' +[-s8? +@(#)$Id: foo (ksh93) 2020-07-16 $ +] +[+NAME?foo - bar] +[+DESC?Baz.] +[x:xylophone?Lorem.] +[y:ypsilon?Ipsum.] +[z:zeta?Sit.] + +[ name=value ... ] +-y [ name ... ] + +[+SEE ALSO?\bgetopts\b(1)] +' + +function testusage { + getopts "$USAGE" dummy 2>&1 +} + +actual=$(testusage -\?) +expect='Usage: testusage [-xyz] [ name=value ... ] + Or: testusage [ options ] -y [ name ... ]' +[[ $actual == "$expect" ]] || err_exit "getopts: '-?' output" \ + "(expected $(printf %q "$expect"), got $(printf %q "$actual"))" + +actual=$(testusage --\?x) +expect='Usage: testusage [ options | --help | --man ] [ name=value ... ] + Or: testusage [ options ] -y [ name ... ] +OPTIONS + -x, --xylophone Lorem.' +[[ $actual == "$expect" ]] || err_exit "getopts: '--?x' output" \ + "(expected $(printf %q "$expect"), got $(printf %q "$actual"))" + +actual=$(testusage --help) +expect='Usage: testusage [ options | --help | --man ] [ name=value ... ] + Or: testusage [ options ] -y [ name ... ] +OPTIONS + -x, --xylophone Lorem. + -y, --ypsilon Ipsum. + -z, --zeta Sit.' +[[ $actual == "$expect" ]] || err_exit "getopts: '--help' output" \ + "(expected $(printf %q "$expect"), got $(printf %q "$actual"))" + +actual=$(testusage --man) +expect='NAME + foo - bar + +SYNOPSIS + foo [ options | --help | --man ] [ name=value ... ] + foo [ options | --help | --man ] -y [ name ... ] + +DESC + Baz. + +OPTIONS + -x, --xylophone Lorem. + -y, --ypsilon Ipsum. + -z, --zeta Sit. + +SEE ALSO + getopts(1) + +IMPLEMENTATION + version foo (ksh93) 2020-07-16' +[[ $actual == "$expect" ]] || err_exit "getopts: '--man' output" \ + "(expected $(printf %q "$expect"), got $(printf %q "$actual"))" + # ====== exit $((Errors<125?Errors:125)) diff --git a/src/lib/libast/misc/optget.c b/src/lib/libast/misc/optget.c index 7c735bbac..cafa2565c 100644 --- a/src/lib/libast/misc/optget.c +++ b/src/lib/libast/misc/optget.c @@ -176,7 +176,7 @@ static unsigned char map[UCHAR_MAX]; static Optstate_t state; -#if !_PACKAGE_astsa +#if 0 /* #if !_PACKAGE_astsa // this somehow corrupts "Or:" usage mesages, e.g. in 'typeset -\?' */ #define ID ast.id