bug-coreutils
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

Re: tr '[:upper:]' '[:lower:]' -- misaligned construct


From: Jim Meyering
Subject: Re: tr '[:upper:]' '[:lower:]' -- misaligned construct
Date: Sat, 05 Jan 2008 12:07:15 +0100

Jim Meyering <address@hidden> wrote:

> Gerald Pfeifer <address@hidden> 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:
>>
>>   address@hidden:~> echo 'AbCd' | tr '[:lower:]' '[:upper:]'
>>   ABCD
>>
>>   address@hidden:~> 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:
>>
>>   address@hidden:~> 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);
        }




reply via email to

[Prev in Thread] Current Thread [Next in Thread]