tech-userlevel archive

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

Re: bin/41700: :tr modifier for NetBSD make [patch]



 >>  Some comments about the code....
 >>  (NB not about whether this is a good idea)

I've implemented all of your proposals.
See the patch below.

About ranges. I adapted the code to make possible implementing ranges in
the future.  That is, this patch allows `-' character inside "chars"
only at the beginning or at the end.

It is also possible to implement :tr/chars/repl/1 in the future.

Index: var.c
===================================================================
RCS file: /cvsroot/src/usr.bin/make/var.c,v
retrieving revision 1.152
diff -u -r1.152 var.c
--- var.c       16 Jun 2009 05:44:06 -0000      1.152
+++ var.c       11 Jul 2009 21:45:38 -0000
@@ -2093,6 +2093,60 @@
 
 /*-
  *-----------------------------------------------------------------------
+ * VarTranslate --
+ *      Char to char translation like tr(1)
+ *
+ * Input:
+ *     str             String to modify
+ *     chars           characters to be replaced
+ *     repl            replacement characters
+ *
+ * Results:
+ *      The string with changed characters or NULL if case of failure
+ *
+ * Side Effects:
+ *      None.
+ *
+ *-----------------------------------------------------------------------
+ */
+static char *
+VarTranslate(char *str, char *chars, char *repl)
+{
+    char *  buf;
+    int     table [UCHAR_MAX+1];
+    size_t  i;
+    size_t  len;
+    int     c,r;
+
+    /* initialization of translation table */
+    for (i=0; i <= UCHAR_MAX; ++i){
+       table [i] = i;
+    }
+
+    len = strlen (chars);
+    for (i=0; i < len; ++i){
+       c = (unsigned char) chars [i];
+       r = (unsigned char) repl [i];
+       if ((c == '-' || r == '-') && i != 0 && i != len-1)
+           return NULL;
+
+       table [c] = r;
+    }
+
+    /* translation */
+    len = strlen (str);
+    buf = bmake_malloc (len+1);
+    for (i=0; i < len; ++i) {
+       c = (unsigned char) str [i];
+       buf [i] = table [c];
+    }
+    buf [len] = 0;
+
+    return buf;
+}
+
+/*-
+ *-----------------------------------------------------------------------
  * VarChangeCase --
  *      Change the string to all uppercase or all lowercase
  *
@@ -2655,7 +2709,43 @@
        case 't':
            {
                cp = tstr + 1;  /* make sure it is set */
-               if (tstr[1] != endc && tstr[1] != ':') {
+               if (tstr[1] == 'r') {
+                   char *chars, *repl;
+                   int chars_len, repl_len;
+
+                   delim = tstr[2];
+                   tstr += 3;
+
+                   cp = tstr;
+                   chars = VarGetPattern(
+                       ctxt, &parsestate, errnum,
+                       &cp, delim, NULL,
+                       &chars_len,
+                       NULL);
+                   if (!chars)
+                       goto cleanup;
+
+                   repl = VarGetPattern(
+                       ctxt, &parsestate, errnum,
+                       &cp, delim, NULL,
+                       &repl_len,
+                       NULL);
+                   if (!repl)
+                       goto cleanup;
+
+                   delim = '\0';
+
+                   if (strlen (chars) != strlen (repl))
+                       goto tr_failed;
+
+                   termc = *cp;
+                   newStr = VarTranslate(nstr, chars, repl);
+                   if (!newStr)
+                       goto tr_failed;
+
+                   free(chars);
+                   free(repl);
+               }else if (tstr[1] != endc && tstr[1] != ':') {
                    if (tstr[1] == 's') {
                        /*
                         * Use the char (if any) at tstr[2]
@@ -3204,10 +3294,16 @@
        }
        tstr = cp;
     }
+
  out:
     *lengthPtr = tstr - start;
     return (nstr);
 
+ tr_failed:
+    Error("Error in :tr modifier for variable %s",
+         v->name);
+    goto cleanup;
+
  bad_modifier:
     /* "{(" */
     Error("Bad modifier `:%.*s' for %s", (int)strcspn(tstr, ":)}"), tstr,
Index: unit-tests/Makefile
===================================================================
RCS file: /cvsroot/src/usr.bin/make/unit-tests/Makefile,v
retrieving revision 1.23
diff -u -r1.23 Makefile
--- unit-tests/Makefile 25 Oct 2008 22:27:39 -0000      1.23
+++ unit-tests/Makefile 11 Jul 2009 21:45:38 -0000
@@ -29,6 +29,7 @@
        modmisc \
        modorder \
        modts \
+       modtr \
        modword \
        posix \
        qequals \
Index: unit-tests/modtr
===================================================================
RCS file: unit-tests/modtr
diff -N unit-tests/modtr
--- /dev/null   1 Jan 1970 00:00:00 -0000
+++ unit-tests/modtr    11 Jul 2009 21:45:38 -0000
@@ -0,0 +1,14 @@
+
+LIST= apple 0xf00dbeaf foo-bar
+
+all:   mod-tr
+
+mod-tr:
+       @echo 'LIST="${LIST}"'
+       @echo 'LIST:tr///="${LIST:tr///}"'
+       @echo 'LIST:tr|abcdef|ABCDEF|="${LIST:tr|abcdef|ABCDEF|:tr/-/+/}"'
+       @echo 'LIST:tr|abcdef|ABCDEF|="${LIST:tr|abcdef|ABCDEF|:tr/zy-/ZY+/}"'
+       @echo 'LIST:tr|abcdef|ABCDEF|="${LIST:tr|abcdef|ABCDEF|:tr/-zy/+ZY/}"'
+#      1 is not implemented (yet?)
+#      @echo 'LIST:tr///1="${LIST:tr///1}"'
+#      @echo 'LIST:tr|abcdef|ABCDEF|1="${LIST:tr|abcdef|ABCDEF|1}"'
Index: unit-tests/test.exp
===================================================================
RCS file: /cvsroot/src/usr.bin/make/unit-tests/test.exp,v
retrieving revision 1.27
diff -u -r1.27 test.exp
--- unit-tests/test.exp 3 Feb 2009 23:11:12 -0000       1.27
+++ unit-tests/test.exp 11 Jul 2009 21:45:38 -0000
@@ -147,6 +147,11 @@
 FU_mod-ts="a/b/cool"
 FU_mod-ts:ts:T="cool" == cool?
 B.${AAA:ts}="Baaa" == Baaa?
+LIST="apple 0xf00dbeaf foo-bar"
+LIST:tr///="apple 0xf00dbeaf foo-bar"
+LIST:tr|abcdef|ABCDEF|="ApplE 0xF00DBEAF Foo+BAr"
+LIST:tr|abcdef|ABCDEF|="ApplE 0xF00DBEAF Foo+BAr"
+LIST:tr|abcdef|ABCDEF|="ApplE 0xF00DBEAF Foo+BAr"
 make: Bad modifier `:[]' for LIST
 LIST:[]="" is an error
 LIST:[0]="one two three four five six"

-- 
Best regards, Aleksey Cheusov.


Home | Main Index | Thread Index | Old Index