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