git: 45d84c2f06fa - stable/14 - tr: fix class handling in unicode world

From: Baptiste Daroussin <bapt_at_FreeBSD.org>
Date: Thu, 19 Feb 2026 09:14:53 UTC
The branch stable/14 has been updated by bapt:

URL: https://cgit.FreeBSD.org/src/commit/?id=45d84c2f06fa72e405f09e2468b10bdf10b806cf

commit 45d84c2f06fa72e405f09e2468b10bdf10b806cf
Author:     Baptiste Daroussin <bapt@FreeBSD.org>
AuthorDate: 2026-02-14 05:54:08 +0000
Commit:     Baptiste Daroussin <bapt@FreeBSD.org>
CommitDate: 2026-02-19 09:14:42 +0000

    tr: fix class handling in unicode world
    
    toupper/tolower logic was only handled for CCLASS_TOUPPER and
    CCLASS_TOLOWER, add support for CCLASS ([:alpha:])
    
    PR:             219900
    MFC After:      1 week
    
    (cherry picked from commit 625dc44832cd760be3d7242d8e21a530c7e32bfc)
---
 usr.bin/tr/tr.c | 34 ++++++++++++++++++++++++++++++++++
 1 file changed, 34 insertions(+)

diff --git a/usr.bin/tr/tr.c b/usr.bin/tr/tr.c
index 75638d6b3bc6..0eb9003ff831 100644
--- a/usr.bin/tr/tr.c
+++ b/usr.bin/tr/tr.c
@@ -253,6 +253,40 @@ main(int argc, char **argv)
 					break;
 			} while (s2.state == CCLASS_LOWER && s2.cnt > 1);
 			goto again;
+		} else if (s1.state == CCLASS &&
+			   s2.state == CCLASS_UPPER &&
+			   s1.cnt == 1 && s2.cnt == 1) {
+			do {
+				ch = towupper(s1.lastch);
+				cmap_add(map, s1.lastch, ch);
+				if (sflag && iswupper(ch))
+					cset_add(squeeze, ch);
+				if (!next(&s1))
+					goto endloop;
+			} while (s1.state == CCLASS && s1.cnt > 1);
+			/* skip upper set */
+			do {
+				if (!next(&s2))
+					break;
+			} while (s2.state == CCLASS_UPPER && s2.cnt > 1);
+			goto again;
+		} else if (s1.state == CCLASS &&
+			   s2.state == CCLASS_LOWER &&
+			   s1.cnt == 1 && s2.cnt == 1) {
+			do {
+				ch = towlower(s1.lastch);
+				cmap_add(map, s1.lastch, ch);
+				if (sflag && iswlower(ch))
+					cset_add(squeeze, ch);
+				if (!next(&s1))
+					goto endloop;
+			} while (s1.state == CCLASS && s1.cnt > 1);
+			/* skip lower set */
+			do {
+				if (!next(&s2))
+					break;
+			} while (s2.state == CCLASS_LOWER && s2.cnt > 1);
+			goto again;
 		} else {
 			cmap_add(map, s1.lastch, s2.lastch);
 			if (sflag)