[Top][All Lists]
[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 10:01:58 +0100 |
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 program to demonstrate:
#include <stdio.h>
#include <string.h>
#include <ctype.h>
#include <locale.h>
int
main ()
{
int n_upper = 0;
int n_lower = 0;
int i;
setlocale (LC_ALL, "");
for (i = 0; i < 256; i++)
{
printf ("%d %c: %s %s\n",
i, i, islower (i) ? " U" : "", isupper (i) ? "L" : "");
if (isupper (i))
++n_upper;
if (islower (i))
++n_lower;
}
return !(n_lower == n_upper);
}
$ gcc -O -W -Wall char-class-check.c
$ LC_ALL=en_US ./a.out|grep -c ': L'
56
$ LC_ALL=en_US ./a.out|grep -c ': U'
59