Initial problem reported by naddy@, amounts to this:

------------------
A = truc.c

EXT=.o
a:
        echo ${A:${EXT}=.o}
------------------

our make:
echo truc.c

gmake (and other BSDs):
echo truc.o

The substitution used is called SYSV substitution, it takes the form
${VAR:before=after} and substitute before into after on each word of
the variable.

Back when I added recursive variable support into make, I only did this on
the rhs of that construct. Apparently, other makes do it on both sides.

Patch that seems to work.

I'd like some eyes on this, make sure it's 100% okay.

Also, I'm afraid that this WILL require a full test build of more or less
everything... as $ used to be not such a big deal inside substitutions.

and now, you need to double it ALSO on the lhs (matching part).

Index: varmodifiers.c
===================================================================
RCS file: /cvs/src/usr.bin/make/varmodifiers.c,v
retrieving revision 1.45
diff -u -p -r1.45 varmodifiers.c
--- varmodifiers.c      25 Jan 2017 14:17:45 -0000      1.45
+++ varmodifiers.c      23 Feb 2017 16:01:23 -0000
@@ -603,29 +603,48 @@ get_sysvpattern(const char **p, SymTable
 {
        VarPattern              *pattern;
        const char              *cp, *cp2;
-       BUFFER buf;
+       BUFFER buf, buf2;
        int cnt = 0;
        char startc = endc == ')' ? '(' : '{';
+
+       Buf_Init(&buf, 0);
        for (cp = *p;; cp++) {
                if (*cp == '=' && cnt == 0)
                        break;
-               if (*cp == '\0')
+               if (*cp == '\0') {
+                       Buf_Destroy(&buf);
                        return NULL;
+               }
                if (*cp == startc)
                        cnt++;
                else if (*cp == endc) {
                        cnt--;
-                       if (cnt < 0)
+                       if (cnt < 0) {
+                               Buf_Destroy(&buf);
                                return NULL;
+                       }
+               } else if (*cp == '$') {
+                       if (cp[1] == '$')
+                               cp++;
+                       else {
+                               size_t len;
+                               (void)Var_ParseBuffer(&buf, cp, ctxt, err, 
+                                   &len);
+                               cp += len - 1;
+                               continue;
+                       }
                }
+               Buf_AddChar(&buf, *cp);
        }
-       Buf_Init(&buf, 0);
+
+       Buf_Init(&buf2, 0);
        for (cp2 = cp+1;; cp2++) {
                if (((*cp2 == ':' && cp2[1] != endc) || *cp2 == endc) && 
                    cnt == 0)
                        break;
                if (*cp2 == '\0') {
                        Buf_Destroy(&buf);
+                       Buf_Destroy(&buf2);
                        return NULL;
                }
                if (*cp2 == startc)
@@ -634,6 +653,7 @@ get_sysvpattern(const char **p, SymTable
                        cnt--;
                        if (cnt < 0) {
                                Buf_Destroy(&buf);
+                               Buf_Destroy(&buf2);
                                return NULL;
                        }
                } else if (*cp2 == '$') {
@@ -641,20 +661,20 @@ get_sysvpattern(const char **p, SymTable
                                cp2++;
                        else {
                                size_t len;
-                               (void)Var_ParseBuffer(&buf, cp2, ctxt, err, 
+                               (void)Var_ParseBuffer(&buf2, cp2, ctxt, err, 
                                    &len);
                                cp2 += len - 1;
                                continue;
                        }
                }
-               Buf_AddChar(&buf, *cp2);
+               Buf_AddChar(&buf2, *cp2);
        }
 
        pattern = emalloc(sizeof(VarPattern));
-       pattern->lbuffer = pattern->lhs = Str_dupi(*p, cp);
-       pattern->leftLen = cp - *p;
-       pattern->rhs = Buf_Retrieve(&buf);
-       pattern->rightLen = Buf_Size(&buf);
+       pattern->lbuffer = pattern->lhs = Buf_Retrieve(&buf);
+       pattern->leftLen = Buf_Size(&buf);
+       pattern->rhs = Buf_Retrieve(&buf2);
+       pattern->rightLen = Buf_Size(&buf2);
        pattern->flags = 0;
        *p = cp2;
        return pattern;

Reply via email to