Skip to content

Commit 0460290

Browse files
committed
Fix default justification width for non-printable/non-ASCII chars
Reproducer: unset s s='コーンシェル' echo ${#s} typeset -L s typeset -p s echo ${#s} Output: 6 typeset -L 18 s='コーンシェル ' 12 Expected output: 6 typeset -L 12 s=コーンシェル 6 Note that the typeset -L, -R or -Z option-argument values do not represent numbers of characters or bytes. Their purpose is to justify. They count horizontal terminal positions. Double-width characters, like Japanese, occupy two horizontal terminal positions each, instead of one, and ksh takes this into account. Thus, the justification width above is 12 though the string length in characters is 6, becasue each character occupies two terminal positions. Also, control characters have no width and do not count. This is similarly broken. src/cmd/ksh93/sh/name.c: - nv_newattr(): The default justification width was calculated based on strlen(), which counts bytes, not terminal positions. Use a loop with mbchar() and mbwidth() (see ast.h) to calculate the correct default width in terminal positions. Resolves: #189
1 parent a01ce5c commit 0460290

File tree

5 files changed

+42
-2
lines changed

5 files changed

+42
-2
lines changed

NEWS

+5
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,11 @@ This documents significant changes in the 1.0 branch of ksh 93u+m.
22
For full details, see the git log at: https://github.com/ksh93/ksh/tree/1.0
33
Uppercase BUG_* IDs are shell bug IDs as used by the Modernish shell library.
44

5+
2024-03-10:
6+
7+
- Fixed a longstanding bug where the default terminal width for typeset -L, -R,
8+
or -Z, if not given, was miscalculated for multibyte or control characters.
9+
510
2024-03-07:
611

712
- Fixed a bug that caused some systems to corrupt the display of multibyte

src/cmd/ksh93/include/version.h

+1-1
Original file line numberDiff line numberDiff line change
@@ -18,7 +18,7 @@
1818

1919
#define SH_RELEASE_FORK "93u+m" /* only change if you develop a new ksh93 fork */
2020
#define SH_RELEASE_SVER "1.0.9-beta" /* semantic version number: https://semver.org */
21-
#define SH_RELEASE_DATE "2024-03-07" /* must be in this format for $((.sh.version)) */
21+
#define SH_RELEASE_DATE "2024-03-10" /* must be in this format for $((.sh.version)) */
2222
#define SH_RELEASE_CPYR "(c) 2020-2024 Contributors to ksh " SH_RELEASE_FORK
2323

2424
/* Scripts sometimes field-split ${.sh.version}, so don't change amount of whitespace. */

src/cmd/ksh93/sh/name.c

+13
Original file line numberDiff line numberDiff line change
@@ -2996,7 +2996,20 @@ void nv_newattr (Namval_t *np, unsigned newatts, int size)
29962996
ap->nelem |= ARRAY_SCAN;
29972997
}
29982998
if(size==0 && !(newatts&NV_INTEGER) && (newatts&NV_HOST)!=NV_HOST && (newatts&(NV_LJUST|NV_RJUST|NV_ZFILL)))
2999+
{ /*
3000+
* Calculate the default terminal width for -L, -R, -Z if no numeric option-argument was given.
3001+
* Note: we count terminal positions, not characters (double-width adds 2, control char adds 0)
3002+
*/
3003+
char *cq = cp;
3004+
wchar_t c;
3005+
int w;
3006+
n = 0;
3007+
mbinit();
3008+
while(c = mbchar(cq))
3009+
if ((w = mbwidth(c)) > 0)
3010+
n += w;
29993011
size = n;
3012+
}
30003013
}
30013014
else if(!trans)
30023015
_nv_unset(np,NV_EXPORT);

src/cmd/ksh93/tests/attributes.sh

+8
Original file line numberDiff line numberDiff line change
@@ -845,5 +845,13 @@ do read -r -N6 var
845845
[[ $got == "$exp" ]] || err_exit "loop optimization bug with 'typeset -b' variables (expected '$exp', got '$got')"
846846
done <<< 'twotowthreetfourro'
847847

848+
# ======
849+
# control characters should not be counted for default justification` width
850+
# https://github.com/ksh93/ksh/issues/189
851+
exp='typeset -L 5 s=$'\''1\n2\a3\t4\x[0b]5'\'
852+
got=$(s=$'1\n2\a3\t4\v5'; typeset -L s; typeset -p s)
853+
[[ $got == "$exp" ]] || err_exit "default terminal width for typeset -L incorrect" \
854+
"(expected $(printf %q "$exp"); got $(printf %q "$got"))"
855+
848856
# ======
849857
exit $((Errors<125?Errors:125))

src/cmd/ksh93/tests/locale.sh

+15-1
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@
22
# #
33
# This software is part of the ast package #
44
# Copyright (c) 1982-2012 AT&T Intellectual Property #
5-
# Copyright (c) 2020-2023 Contributors to ksh 93u+m #
5+
# Copyright (c) 2020-2024 Contributors to ksh 93u+m #
66
# and is licensed under the #
77
# Eclipse Public License, Version 2.0 #
88
# #
@@ -454,5 +454,19 @@ then unset LANG "${!LC_@}" i
454454
fi
455455
fi
456456
457+
# ======
458+
# double-width characters should count for two for default justification width
459+
# https://github.com/ksh93/ksh/issues/189
460+
if ((SHOPT_MULTIBYTE))
461+
then unset s "${!LC_@}"
462+
LANG=C.UTF-8
463+
s='コーンシェル'
464+
typeset -L s
465+
got=$(typeset -p s; echo ${#s})
466+
exp=$'typeset -L 12 s=コーンシェル\n6' # each double-width character counts for two terminal positions
467+
[[ $got == "$exp" ]] || err_exit "default terminal width for typeset -L incorrect" \
468+
"(expected $(printf %q "$exp"); got $(printf %q "$got"))"
469+
fi
470+
457471
# ======
458472
exit $((Errors<125?Errors:125))

0 commit comments

Comments
 (0)