Heya, I noticed that tr was in pending, taking a look at the source code.
It doesn't look very unclean, nor does it fail any test cases. The only 2 things
in the TODO are -t and -a. Neither POSIX or GNU tr specify a -a[scii] option.
The name gives a general idea of what it's supposed to do 
(Stop acting utf-8 safe and treat everything as extended ASCII?)

I added in a -t[runcate] option and a corresponding test case.

I also cleaned up some of code (foobar[0] to *foobar, removing sizeof(char), 
etc)

- Oliver Webb <[email protected]>
From a4b43368a4d8bbcb023811069921d672606da74b Mon Sep 17 00:00:00 2001
From: Oliver Webb <[email protected]>
Date: Fri, 20 Oct 2023 23:06:58 -0500
Subject: [PATCH] Added tr -t and test case for it, Minor formatting cleanup in
 tr.c

---
 tests/tr.test     |  1 +
 toys/pending/tr.c | 37 ++++++++++++++++++++-----------------
 2 files changed, 21 insertions(+), 17 deletions(-)

diff --git a/tests/tr.test b/tests/tr.test
index bb00a3ff..9b3070cf 100755
--- a/tests/tr.test
+++ b/tests/tr.test
@@ -7,5 +7,6 @@
 testing "" "tr 1 2" "223223223" "" "123123123"
 testing "-d" "tr -d 1" "232323" "" "123123123"
 testing "-s" "tr -s 1" "12223331222333" "" "111222333111222333"
+testing "-t" "tr -t 1234 567" "5674" "" "1234"
 
 testing "no pathological flushing" "seq 10000000 | tr 1 2 > /dev/null" "" "" ""
diff --git a/toys/pending/tr.c b/toys/pending/tr.c
index 4e09263f..99eb8f19 100644
--- a/toys/pending/tr.c
+++ b/toys/pending/tr.c
@@ -3,21 +3,22 @@
  * Copyright 2014 Sandeep Sharma <[email protected]>
  *
  * See http://pubs.opengroup.org/onlinepubs/9699919799/utilities/tr.html
- * TODO: -t (truncate) -a (ascii)
+ * TODO: -a (ascii)
 
-USE_TR(NEWTOY(tr, "^>2<1Ccsd[+cC]", TOYFLAG_USR|TOYFLAG_BIN))
+USE_TR(NEWTOY(tr, "^>2<1Ccstd[+cC]", TOYFLAG_USR|TOYFLAG_BIN))
 
 config TR
   bool "tr"
   default n
   help
-    usage: tr [-cds] SET1 [SET2]
+    usage: tr [-cdst] SET1 [SET2]
 
     Translate, squeeze, or delete characters from stdin, writing to stdout
 
     -c/-C  Take complement of SET1
     -d     Delete input characters coded SET1
     -s     Squeeze multiple output characters of SET2 into one character
+    -t     Truncate SET2 to length of SET1
 */
 
 #define FOR_tr
@@ -92,7 +93,7 @@ static int handle_escape_char(char **esc_val) //taken from printf
     switch (*ptr) {
       case 'n':  result = '\n'; break;
       case 't':  result = '\t'; break;
-      case 'e':  result = (char)27; break;
+      case 'e':  result = '\e'; break;
       case 'b':  result = '\b'; break;
       case 'a':  result = '\a'; break;
       case 'f':  result = '\f'; break;
@@ -123,32 +124,33 @@ static int find_class(char *class_name)
   return i;
 }
 
-static char *expand_set(char *arg, int *len)
+static char *expand_set(char *arg, int *len, size_t until)
 {
   int i = 0, j, k, size = 256;
-  char *set = xzalloc(size*sizeof(char));
+  char *set = xzalloc(size), *orig = arg;
 
   while (*arg) {
+    if (arg-orig >= until) break;
     if (i >= size) {
       size += 256;
       set = xrealloc(set, size);
     }
     if (*arg == '\\') {
       arg++;
-      set[i++] = (int)handle_escape_char(&arg);
+      set[i++] = handle_escape_char(&arg);
       arg++;
       continue;
     }
     if (arg[1] == '-') {
       if (!arg[2]) goto save;
-      j = arg[0];
+      j = *arg;
       k = arg[2];
       if (j > k) perror_exit("reverse colating order");
       while (j <= k) set[i++] = j++;
       arg += 3;
       continue;
     }
-    if (arg[0] == '[' && arg[1] == ':') {
+    if (*arg == '[' && arg[1] == ':') {
 
       if ((j = find_class(arg)) == class_invalid) goto save;
 
@@ -185,7 +187,7 @@ static char *expand_set(char *arg, int *len)
       arg += 9; //never here for class_xdigit.
       continue;
     }
-    if (arg[0] == '[' && arg[1] == '=') { //[=char=] only
+    if (*arg == '[' && arg[1] == '=') { //[=char=] only
       arg += 2;
       if (*arg) set[i++] = *arg;
       if (!arg[1] || arg[1] != '=' || arg[2] != ']')
@@ -218,10 +220,10 @@ static void print_map(char *set1, char *set2)
 
 static void do_complement(char **set)
 {
-  int i, j;
+  int i = 0, j = 0;
   char *comp = xmalloc(256);
 
-  for (i = 0, j = 0;i < 256; i++) {
+  for (; i < 256; i++) {
     if (memchr(*set, i, TT.len1)) continue;
     else comp[j++] = (char)i;
   }
@@ -233,16 +235,17 @@ static void do_complement(char **set)
 void tr_main(void)
 {
   char *set1, *set2 = NULL;
-  int i;
+  int i = 0;
 
   TT.map = xmalloc(256*sizeof(*TT.map));
-  for (i = 0; i < 256; i++) TT.map[i] = i; //init map
+  for (; i < 256; i++) TT.map[i] = i; //init map
 
-  set1 = expand_set(toys.optargs[0], &TT.len1);
+  set1 = expand_set(*toys.optargs, &TT.len1,
+      FLAG(t) ? strlen(toys.optargs[1]) : -1);
   if (FLAG(c)) do_complement(&set1);
   if (toys.optargs[1]) {
-    if (toys.optargs[1][0] == '\0') error_exit("set2 can't be empty string");
-    set2 = expand_set(toys.optargs[1], &TT.len2);
+    if (!*toys.optargs[1]) error_exit("set2 can't be empty string");
+    set2 = expand_set(toys.optargs[1], &TT.len2, -1);
   }
   map_translation(set1, set2);
 
-- 
2.34.1

_______________________________________________
Toybox mailing list
[email protected]
http://lists.landley.net/listinfo.cgi/toybox-landley.net

Reply via email to