Jim Meyering <[EMAIL PROTECTED]> wrote: > Gerald Pfeifer <[EMAIL PROTECTED]> wrote: >> I've been using tr '[:upper:]' '[:lower:]' for a while, but with >> version 6.9.90 (and 6.9.91) I know get the following hard error: >> >> [EMAIL PROTECTED]:~> echo 'AbCd' | tr '[:lower:]' '[:upper:]' >> ABCD >> >> [EMAIL PROTECTED]:~> echo 'AbCd' | tr '[:upper:]' '[:lower:]' >> tr: misaligned [:upper:] and/or [:lower:] construct >> >> That machine is running in an ISO-8859 locale on openSUSE 11.0 FACTORY: >> >> [EMAIL PROTECTED]:~> set | egrep '^(LANG|LC)' >> LANG=en_US.iso-8859-1 >> LC_COLLATE=C >> >> I searched Google, the mailing list archives, and checked the ChangeLog >> in git but didn't find any matching information. Earlier versions as >> well as FreeBSD 6.2 tr and Solaris 9 tr process both invocations above >> as expected. >> >> To exclude any problems caused by the alpha status of openSUSE FACTORY >> I also downloaded coreutils-6.9.91 and built it (./configure ; make) >> on an openSUSE 10.3 machine. The result is the same. > > Hi Gerald, > > Thank you for the bug report. > > That locale definition has 3 more upper-case letters than lower-case, > and GNU tr's implementation has always required that the > lists of upper- and lower- case characters -- defined by > the isupper and islower functions -- have the same length. > > I'll look into removing that requirement.
Here's a tentative patch that also avoids repeated (and wasteful) initialization of the xlate array. diff --git a/src/tr.c b/src/tr.c index dff602e..6a154db 100644 --- a/src/tr.c +++ b/src/tr.c @@ -1,5 +1,5 @@ /* tr -- a filter to translate characters - Copyright (C) 91, 1995-2007 Free Software Foundation, Inc. + Copyright (C) 91, 1995-2008 Free Software Foundation, Inc. This program is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by @@ -1818,6 +1818,7 @@ main (int argc, char **argv) s2->state = BEGIN_STATE; for (;;) { + bool case_convert = false; c1 = get_next (s1, &class_s1); c2 = get_next (s2, &class_s2); @@ -1831,12 +1832,14 @@ main (int argc, char **argv) if (class_s1 == UL_LOWER && class_s2 == UL_UPPER) { + case_convert = true; for (i = 0; i < N_CHARS; i++) if (islower (i)) xlate[i] = toupper (i); } else if (class_s1 == UL_UPPER && class_s2 == UL_LOWER) { + case_convert = true; for (i = 0; i < N_CHARS; i++) if (isupper (i)) xlate[i] = tolower (i); @@ -1854,6 +1857,13 @@ main (int argc, char **argv) break; xlate[c1] = c2; } + + if (case_convert) + { + enum Upper_Lower_class cl; + do { get_next (s1, &cl); } while (cl == class_s1); + do { get_next (s2, &cl); } while (cl == class_s2); + } } assert (c1 == -1 || truncate_set1); } _______________________________________________ Bug-coreutils mailing list Bug-coreutils@gnu.org http://lists.gnu.org/mailman/listinfo/bug-coreutils