NetBSD-Bugs archive

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

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



>Number:         41700
>Category:       bin
>Synopsis:       :tr modifier for NetBSD make [patch]
>Confidential:   no
>Severity:       non-critical
>Priority:       medium
>Responsible:    bin-bug-people
>State:          open
>Class:          change-request
>Submitter-Id:   net
>Arrival-Date:   Sat Jul 11 11:20:00 +0000 2009
>Originator:     Aleksey Cheusov
>Release:        NetBSD 5.0_STABLE
>Organization:
>Environment:
System: NetBSD chen.chizhovka.net 5.0_STABLE NetBSD 5.0_STABLE (GENERIC) #5: 
Fri May 1 16:04:32 EEST 2009 
cheusov%chen.chizhovka.net@localhost:/srv/obj/sys/arch/i386/compile/GENERIC i386
Architecture: i386
Machine: i386
>Description:
Some time ago I proposed to implement a new variable modifier for bmake, :tr
for character substitution in tr(1) manner.
http://mail-index.netbsd.org/tech-userlevel/2009/03/25/msg001973.html
There were short discussion and people agreed with my proposal.

Now I propose a patch.

>Fix:

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 11:13:54 -0000
@@ -130,6 +130,7 @@
 #include    <ctype.h>
 #include    <stdlib.h>
 #include    <limits.h>
+#include    <assert.h>
 
 #include    "make.h"
 #include    "buf.h"
@@ -2093,6 +2094,57 @@
 
 /*-
  *-----------------------------------------------------------------------
+ * 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
+ *
+ * Side Effects:
+ *      None.
+ *
+ *-----------------------------------------------------------------------
+ */
+static char *
+VarTranslate(char *str, char *chars, char *repl)
+{
+   Buffer  buf;
+   int     table [UCHAR_MAX+1];
+   int     r;
+   int     c;
+
+   /* initialization of translation table */
+   memset (table, -1, sizeof (table));
+
+   for (; *chars; ++chars, ++repl){
+       assert (*repl != 0);
+       table [(unsigned char) *chars] = (unsigned char) *repl;
+   }
+   assert (*repl == 0);
+
+   /* translation */
+   Buf_Init(&buf, 0);
+   for (; *str ; ++str) {
+       c = (unsigned char) *str;
+       r = table [c];
+       if (r == -1)
+          Buf_AddByte(&buf, (Byte)c);
+       else
+          Buf_AddByte(&buf, (Byte)r);
+   }
+   Buf_AddByte(&buf, (Byte)'\0');
+   str = (char *)Buf_GetAll(&buf, NULL);
+   Buf_Destroy(&buf, FALSE);
+   return str;
+}
+
+/*-
+ *-----------------------------------------------------------------------
  * VarChangeCase --
  *      Change the string to all uppercase or all lowercase
  *
@@ -2655,7 +2707,47 @@
        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)){
+                       free(chars);
+                       free(repl);
+
+                       Error("Bad arguments for :tr modifier for variable %s",
+                             v->name);
+                       goto cleanup;
+                   }
+
+                   termc = *cp;
+                   newStr = VarTranslate(nstr, chars, repl);
+
+                   free(chars);
+                   free(repl);
+               }else if (tstr[1] != endc && tstr[1] != ':') {
                    if (tstr[1] == 's') {
                        /*
                         * Use the char (if any) at tstr[2]



Home | Main Index | Thread Index | Old Index