Patch from Jean Wolter:
authorRob Landley <rob@landley.net>
Wed, 19 Apr 2006 22:22:06 +0000 (22:22 -0000)
committerRob Landley <rob@landley.net>
Wed, 19 Apr 2006 22:22:06 +0000 (22:22 -0000)
it looks like the introduced support for character classes and
equivalence classes is not correct. The attached patch tries to fix
some symptoms and tries to make tr behave like gnu tr for the added
test cases. The patch

 - removes if clauses with side effects
 - fixes handling of buffer pointer (strcat added characters to the
   buffer without increasing the buffer pointer)
 - re-arranges character classes to match ASCII order

regards,
Jean

coreutils/tr.c
testsuite/tr/tr-works

index 15a9d17b01eef57a7cdbc348a4a0234deca81af7..752b13bf863affe1a90ae1be8a4bed5d4eb089b5 100644 (file)
@@ -116,7 +116,8 @@ static unsigned int expand(const char *arg, register unsigned char *buffer)
                        arg += 3; /* Skip the assumed a-z */
                } else if (*arg == '[') {
                        arg++;
-                       if (ENABLE_FEATURE_TR_CLASSES && *arg++ == ':') {
+                       i = *arg++;
+                       if (ENABLE_FEATURE_TR_CLASSES && i == ':') {
                                if (strncmp(arg, "alpha", 5) == 0) {
                                        for (i = 'A'; i <= 'Z'; i++)
                                                *buffer++ = i;
@@ -124,12 +125,12 @@ static unsigned int expand(const char *arg, register unsigned char *buffer)
                                                *buffer++ = i;
                                }
                                else if (strncmp(arg, "alnum", 5) == 0) {
+                                       for (i = '0'; i <= '9'; i++)
+                                               *buffer++ = i;
                                        for (i = 'A'; i <= 'Z'; i++)
                                                *buffer++ = i;
                                        for (i = 'a'; i <= 'z'; i++)
                                                *buffer++ = i;
-                                       for (i = '0'; i <= '9'; i++)
-                                               *buffer++ = i;
                                }
                                else if (strncmp(arg, "digit", 5) == 0)
                                        for (i = '0'; i <= '9'; i++)
@@ -140,10 +141,15 @@ static unsigned int expand(const char *arg, register unsigned char *buffer)
                                else if (strncmp(arg, "upper", 5) == 0)
                                        for (i = 'A'; i <= 'Z'; i++)
                                                *buffer++ = i;
-                               else if (strncmp(arg, "space", 5) == 0)
-                                       strcat((char*)buffer, " \f\n\r\t\v");
-                               else if (strncmp(arg, "blank", 5) == 0)
-                                       strcat((char*)buffer, " \t");
+                               else if (strncmp(arg, "space", 5) == 0) {
+                                   const char s[] = "\t\n\v\f\r ";
+                                       strcat((char*)buffer, s);
+                                       buffer += sizeof(s) - 1;
+                               }
+                               else if (strncmp(arg, "blank", 5) == 0) {
+                                       *buffer++ = '\t';
+                                       *buffer++ = ' ';
+                               }
                                /* gcc gives a warning if braces aren't used here */
                                else if (strncmp(arg, "punct", 5) == 0) {
                                        for (i = 0; i <= ASCII; i++)
@@ -156,13 +162,13 @@ static unsigned int expand(const char *arg, register unsigned char *buffer)
                                                        *buffer++ = i;
                                }
                                else {
-                                       strcat((char*)buffer, "[:");
-                                       arg++;
+                                       *buffer++ = '[';
+                                       *buffer++ = ':';
                                        continue;
                                }
                                break;
                        }
-                       if (ENABLE_FEATURE_TR_EQUIV && *arg++ == '=') {
+                       if (ENABLE_FEATURE_TR_EQUIV && i == '=') {
                                *buffer++ = *arg;
                                /* skip the closing =] */
                                arg += 3;
@@ -173,7 +179,6 @@ static unsigned int expand(const char *arg, register unsigned char *buffer)
                                arg -= 2;
                                continue;
                        }
-                       i = *arg++;
                        ac = *arg++;
                        while (i <= ac)
                                *buffer++ = i++;
index 8753a3f28aec35324cc83ae8a42269d48f889ef7..b7a6e8df70de5e00696032bfdd6ae4e18a9f5acc 100644 (file)
@@ -1,9 +1,24 @@
-echo "cbaab" | tr abc zyx > logfile.gnu
-echo "TESTING A B C" | tr [A-Z] [a-z] >> logfile.gnu
-echo abc[] | tr a[b AXB >> logfile.gnu
-
-echo "cbaab" | busybox tr abc zyx > logfile.bb
-echo "TESTING A B C" | busybox tr [A-Z] [a-z] >> logfile.bb
-echo abc[] | busybox tr a[b AXB >> logfile.bb
+run_tr ()
+{
+       echo -n "echo '$1' | tr '$2' '$3': "
+       echo "$1" | $bb tr "$2" "$3"
+       echo
+}
+tr_test ()
+{
+       run_tr "cbaab"          abc             zyx
+       run_tr "TESTING A B C"  '[A-Z]'         '[a-z]' 
+       run_tr "abc[]"          "a[b"           AXB
+       run_tr abc              '[:alpha:]'     A-ZA-Z
+       run_tr abc56            '[:alnum:]'     A-ZA-Zxxxxxxxxxx
+       run_tr 012              '[:digit:]'     abcdefghi
+       run_tr abc56            '[:lower:]'     '[:upper:]'
+       run_tr "        "       '[:space:]'     12345
+       run_tr "        "       '[:blank:]'     12
+       run_tr 'a b'            '[= =]'         X
+       run_tr "[:"             '[:'            ab
+}
 
+bb=        tr_test > logfile.gnu
+bb=busybox tr_test > logfile.bb
 cmp logfile.gnu logfile.bb