tech-toolchain archive

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

make: sysV subst with variables



A colleague came accross this.

While make handles variables on the rhs of a sysV style substituion,
our handling of recursive modifiers prevented handling variables
on the lhs.

For the test case below, we'd get:

fun
make: Unknown modifier '/'
{S}fun=fun}
make: Unknown modifier '/'
{S}%=%}
In the Sun

Index: var.c
===================================================================
RCS file: /cvsroot/src/usr.bin/make/var.c,v
retrieving revision 1.166
diff -u -p -r1.166 var.c
--- var.c       21 May 2011 07:30:42 -0000      1.166
+++ var.c       1 Jun 2011 15:42:24 -0000
@@ -2498,14 +2498,51 @@ ApplyModifiers(char *nstr, const char *t
 
        if (*tstr == '$') {
            /*
-            * We have some complex modifiers in a variable.
+            * We may have some complex modifiers in a variable.
             */
            void *freeIt;
            char *rval;
            int rlen;
+           int c;
 
            rval = Var_Parse(tstr, ctxt, errnum, &rlen, &freeIt);
 
+           /*
+            * Consume tstr up to endc, or a ':'
+            * before trying to feed it to ourselves.
+            */
+           if (rval != NULL && *rval &&
+               (c = tstr[rlen]) != '\0' &&
+               c != ':' &&
+               c != endc) {
+               Buffer buf;
+               const char *cp2;
+               Boolean needSubst = FALSE;
+               int nest = 1;
+               
+               Buf_Init(&buf, rlen);
+               Buf_AddBytes(&buf, strlen(rval), rval);
+               for (cp2 = tstr + rlen; *cp2 != '\0' &&
+                        !(*cp2 == endc && nest == 1); cp2++) {
+                   if (*cp2 == startc)
+                       nest++;
+                   else if (*cp2 == endc)
+                       nest--;
+                   else if (*cp2 == '$')
+                       needSubst = TRUE;
+                   Buf_AddByte(&buf, *cp2);
+               }
+               rval = Buf_GetAll(&buf, NULL);
+               rlen = cp2 - tstr;
+               Buf_Destroy(&buf, 0);
+               if (needSubst) {
+                   rval = Var_Subst(NULL, rval, ctxt, 0);
+                   if (freeIt)
+                       free(freeIt);
+                   freeIt = rval;
+               }
+           }
+
            if (DEBUG(VAR)) {
                fprintf(debug_file, "Got '%s' from '%.*s'%.*s\n",
                       rval, rlen, tstr, rlen, tstr + rlen);
Index: unit-tests/sysv
===================================================================
RCS file: /cvsroot/src/usr.bin/make/unit-tests/sysv,v
retrieving revision 1.1
diff -u -p -r1.1 sysv
--- unit-tests/sysv     6 Mar 2011 00:02:14 -0000       1.1
+++ unit-tests/sysv     1 Jun 2011 15:42:24 -0000
@@ -5,9 +5,22 @@ FOOBAR = $(FOO:=bar)
 
 _this := ${.PARSEDIR}/${.PARSEFILE}
 
+B = /b
+S = /
+FUN = ${B}${S}fun
+SUN = the Sun
+
 # we expect nothing when FOO is empty
-all:
+all: foo fun
+
+foo:
        @echo FOOBAR = $(FOOBAR)
 .if empty(FOO)
-       @FOO="foo fu" ${.MAKE} -f ${_this}
+       @FOO="foo fu" ${.MAKE} -f ${_this} foo
 .endif
+
+fun:
+       @echo ${FUN:T}
+       @echo ${FUN:${B}${S}fun=fun}
+       @echo ${FUN:${B}${S}%=%}
+       @echo ${In:L:%=% ${SUN}}
Index: unit-tests/test.exp
===================================================================
RCS file: /cvsroot/src/usr.bin/make/unit-tests/test.exp,v
retrieving revision 1.37
diff -u -p -r1.37 test.exp
--- unit-tests/test.exp 11 Apr 2011 15:10:15 -0000      1.37
+++ unit-tests/test.exp 1 Jun 2011 15:42:24 -0000
@@ -317,6 +317,10 @@ Now we expect an error...
 V.i386 ?= OK
 FOOBAR =
 FOOBAR = foobar fubar
+fun
+fun
+fun
+In the Sun
 The answer is unknown
 The answer is unknown
 The answer is empty


Home | Main Index | Thread Index | Old Index