Subject: make's handling of SysV '%'
To: None <netbsd-bugs@NetBSD.ORG>
From: None <mikeb@snow.datametrics.com>
List: netbsd-bugs
Date: 01/16/1995 07:07:32
I'm sure most of you probably don't use this much, but since the company I
work for does development on many platforms... Anyhow, the following patch
fixes a problem when there are parens within a SysV style variable
substitution, ie:

OBJ=hello.o goodbye.o
TARGET=libfoo.a
all: $(OBJ:%=$(TARGET)(%))

Which also brings up another problem I've had. The above line produces:

all: libfoo.a(hello.o) libfoo.a(goodbye.o)

Yeah, yeah, why not 'all: libfoo.a(hello.o goodbye.o)', there are just too
many 'make's out there that don't support this, and I have to deal with
them. The problem is that the construct libfoo.a(hello.o) ends up using the
.c.o: implicit rule, and then a .o.a: implicit rule, which one must define,
as it is not in the default sys.mk, rather that the .c.a: implicit rule.
While this works, this differs from the other implemetations of make
that I have used, don't know what POSIX says about this, if it does. I
couldn't find where to fix (if one would call this a fix) this and I had
other work to get to. Perhaps someone that knows the make source could
either look into it or point me in the right direction.

Mike B

*** var.c.orig	Fri Jan 13 23:39:57 1995
--- var.c	Sat Jan 14 19:00:53 1995
***************
*** 1110,1115 ****
--- 1110,1119 ----
      Boolean 	    haveModifier;/* TRUE if have modifiers for the variable */
      register char   endc;    	/* Ending character when variable in parens
  				 * or braces */
+     register char   startc;	/* Starting character when variable in parens
+ 				 * or braces */
+     int             cnt;	/* Used to count brace pairs when variable in
+ 				 * in parens or braces */
      char    	    *start;
      Boolean 	    dynamic;	/* TRUE if the variable is local and we're
  				 * expanding it in a non-local context. This
***************
*** 1166,1172 ****
  	    endc = str[1];
  	}
      } else {
! 	endc = str[1] == '(' ? ')' : '}';
  
  	/*
  	 * Skip to the end character or a colon, whichever comes first.
--- 1170,1177 ----
  	    endc = str[1];
  	}
      } else {
! 	startc = str[1];
! 	endc = startc == '(' ? ')' : '}';
  
  	/*
  	 * Skip to the end character or a colon, whichever comes first.
***************
*** 1637,1647 ****
  		     * to verify it is a SYSV-make-style translation:
  		     * it must be: <string1>=<string2>)
  		     */
! 		    for (cp = tstr; *cp != '\0' && *cp != endc; cp++) {
  			if (*cp == '=') {
  			    eqFound = TRUE;
  			    /* continue looking for endc */
  			}
  		    }
  		    if (*cp == endc && eqFound) {
  			
--- 1642,1660 ----
  		     * to verify it is a SYSV-make-style translation:
  		     * it must be: <string1>=<string2>)
  		     */
! 		    cp = tstr;
! 		    cnt = 1;
! 		    while (*cp != '\0' && cnt) {
  			if (*cp == '=') {
  			    eqFound = TRUE;
  			    /* continue looking for endc */
  			}
+ 			else if (*cp == endc)
+ 			    cnt--;
+ 			else if (*cp == startc)
+ 			    cnt++;
+ 			if (cnt)
+ 			    cp++;
  		    }
  		    if (*cp == endc && eqFound) {
  			
***************
*** 1656,1663 ****
  			*cp++ = '\0';
  			
  			pattern.rhs = cp;
! 			while (*cp != endc) {
! 			    cp++;
  			}
  			pattern.rightLen = cp - pattern.rhs;
  			*cp = '\0';
--- 1669,1682 ----
  			*cp++ = '\0';
  			
  			pattern.rhs = cp;
! 			cnt = 1;
! 			while (cnt) {
! 			    if (*cp == endc)
! 				cnt--;
! 			    else if (*cp == startc)
! 				cnt++;
! 			    if (cnt)
! 				cp++;
  			}
  			pattern.rightLen = cp - pattern.rhs;
  			*cp = '\0';