[gnu.utils.bug] Make 3.55 and the $* variable

hrp@boring.cray.com (Hal Peterson) (09/21/89)

I am using GNU Make 3.55 on a Sun-3/50 running SunOS 3.5.  I built it
with GCC 1.35.

Stem handling isn't quite correct; it's deleting directories.
Consider this Makefile:

	.SUFFIXES:	.c .o
	.c.o:
		@echo This should be foo/bar:  $*
	foo/bar.o:	foo/bar.c

If the directory foo exists and contains the file bar.c, here's  what
Make 3.54 does.  I didn't keep around a copy of 3.55, but it does the
same thing once it's been patched to handle rules without commands:

	67 /usr/earth4/gnu/src/make-3.55 $ make -v
	GNU Make version 3.54, by Richard Stallman and Roland McGrath.
	Copyright (C) 1988, 1989 Free Software Foundation, Inc.
	This is free software; see the source for copying conditions.
	There is NO warranty; not even for MERCHANTABILITY or FITNESS FOR A
	PARTICULAR PURPOSE.

	This should be foo/bar: bar
	68 /usr/earth4/gnu/src/make-3.55 $

Notice that $* strips leading directories from the target name, which
it should not.  From the manual, ``How Patterns Match'':

	When the target pattern does not contain a slash (and usually it does
	not), directory names in the file names are removed from the file name
	before it is compared with the target prefix and suffix.  The
	directory names, along with the slash that ends them, are added back
	to the stem.  Thus, `e%t' does match the file name `src/eat', with
	`src/a' as the stem.  When dependencies are turned into file names,
	the directories from the stem are added at the front, while the rest
	of the stem is substituted for the `%'.  The stem `src/a' with a
	dependency pattern `c%r' gives the file name `src/car'.

The diffs that follow seem to make this better by using two different
variables for pattern matching and for saving in file->stem.

--
Hal Peterson			Domain:  hrp@cray.com
Cray Research			Old style:  hrp%cray.com@uc.msc.umn.edu
1440 Northland Dr.		UUCP:  uunet!cray!hrp
Mendota Hts, MN  55120  USA	Telephone:  +1 612 681 3145
========================================================================
*** implicit-DIST.c	Wed Sep 20 13:43:00 1989
--- implicit.c	Wed Sep 20 16:14:35 1989
***************
*** 155,160 ****
--- 155,162 ----
      {
        int specific_rule_may_have_matched = 0;
        int check_lastslash;
+       char *stem_base;
+       int stem_baselen;
  
        /* If the pattern rule has deps but no commands, ignore it.
  	 Users cancel built-in rules by redefining them without commands.  */
***************
*** 182,189 ****
  
  	  /* From the lengths of the filename and the pattern parts,
  	     find the stem: the part of the filename that matches the %.  */
! 	  stem = filename + (suffix - target - 1);
! 	  stemlen = namelen - rule->lens[i] + 1;
  
  	  /* Set CHECK_LASTSLASH if FILENAME contains a directory
  	     prefix and the target pattern does not contain a slash.  */
--- 184,191 ----
  
  	  /* From the lengths of the filename and the pattern parts,
  	     find the stem: the part of the filename that matches the %.  */
! 	  stem_base = stem = filename + (suffix - target - 1);
! 	  stem_baselen = stemlen = namelen - rule->lens[i] + 1;
  
  	  /* Set CHECK_LASTSLASH if FILENAME contains a directory
  	     prefix and the target pattern does not contain a slash.  */
***************
*** 193,215 ****
  	    {
  	      /* In that case, don't include the
  		 directory prefix in STEM here.  */
! 	      stem += lastslash - filename + 1;
! 	      stemlen -= (lastslash - filename) + 1;
  	    }
  
  	  /* Check that filename is long enough to match the whole pattern.  */
! 	  if (stemlen <= 0)
  	    continue;
  
  	  /* Check that the rule pattern matches the text before the stem.  */
  	  if (check_lastslash)
  	    {
! 	      if (stem > (lastslash + 1)
! 		  && strncmp (target, lastslash + 1, stem - lastslash - 1))
  		continue;
  	    }
! 	  else if (stem > filename
! 		   && strncmp (target, filename, stem - filename))
  	    continue;
  
  	  /* Check that the rule pattern matches the text after the stem.
--- 195,217 ----
  	    {
  	      /* In that case, don't include the
  		 directory prefix in STEM here.  */
! 	      stem_base += lastslash - filename + 1;
! 	      stem_baselen -= (lastslash - filename) + 1;
  	    }
  
  	  /* Check that filename is long enough to match the whole pattern.  */
! 	  if (stem_baselen <= 0)
  	    continue;
  
  	  /* Check that the rule pattern matches the text before the stem.  */
  	  if (check_lastslash)
  	    {
! 	      if (stem_base > (lastslash + 1)
! 		  && strncmp (target, lastslash + 1, stem_base - lastslash - 1))
  		continue;
  	    }
! 	  else if (stem_base > filename
! 		   && strncmp (target, filename, stem_base - filename))
  	    continue;
  
  	  /* Check that the rule pattern matches the text after the stem.
***************
*** 217,224 ****
  	     first two characters immediately.  This saves time in the very
  	     common case where the first character matches because it is a
  	     period.  */
! 	  if (*suffix != stem[stemlen]
! 	      || (*suffix != '\0' && !streq (&suffix[1], &stem[stemlen + 1])))
  	    continue;
  
  	  /* Record if we match a rule that not all filenames will match.  */
--- 219,226 ----
  	     first two characters immediately.  This saves time in the very
  	     common case where the first character matches because it is a
  	     period.  */
! 	  if (*suffix != stem_base[stem_baselen]
! 	      || (*suffix != '\0' && !streq (&suffix[1], &stem_base[stem_baselen + 1])))
  	    continue;
  
  	  /* Record if we match a rule that not all filenames will match.  */
***************
*** 271,276 ****
--- 273,280 ----
        for (i = 0; i < nrules; i++)
  	{
  	  int check_lastslash;
+ 	  char *stem_base;
+ 	  int stem_baselen;
  
  	  rule = tryrules[i];
  
***************
*** 290,308 ****
  
  	  /* From the lengths of the filename and the matching pattern parts,
  	     find the stem: the part of the filename that matches the %.  */
! 	  stem = filename
  	    + (rule->suffixes[matches[i]] - rule->targets[matches[i]]) - 1;
! 	  stemlen = namelen - rule->lens[matches[i]] + 1;
  	  check_lastslash = lastslash != 0
  	                    && index (rule->targets[matches[i]], '/') == 0;
  	  if (check_lastslash)
  	    {
! 	      stem += lastslash - filename + 1;
! 	      stemlen -= (lastslash - filename) + 1;
  	    }
  
  	  DEBUGP2 ("Trying pattern rule with stem `%.*s'.\n",
! 		   stemlen, stem);
  
  	  /* Try each dependency; see if it "exists".  */
  
--- 294,312 ----
  
  	  /* From the lengths of the filename and the matching pattern parts,
  	     find the stem: the part of the filename that matches the %.  */
! 	  stem_base = stem = filename
  	    + (rule->suffixes[matches[i]] - rule->targets[matches[i]]) - 1;
! 	  stem_baselen = stemlen = namelen - rule->lens[matches[i]] + 1;
  	  check_lastslash = lastslash != 0
  	                    && index (rule->targets[matches[i]], '/') == 0;
  	  if (check_lastslash)
  	    {
! 	      stem_base += lastslash - filename + 1;
! 	      stem_baselen -= (lastslash - filename) + 1;
  	    }
  
  	  DEBUGP2 ("Trying pattern rule with stem `%.*s'.\n",
! 		   stem_baselen, stem_base);
  
  	  /* Try each dependency; see if it "exists".  */
  
***************
*** 323,330 ****
  		    i = 0;
  		  bcopy (dep_name (dep), depname + i, p - dep_name (dep));
  		  i += p - dep_name (dep);
! 		  bcopy (stem, depname + i, stemlen);
! 		  i += stemlen;
  		  strcpy (depname + i, p + 1);
  		  p = depname;
  		}
--- 327,334 ----
  		    i = 0;
  		  bcopy (dep_name (dep), depname + i, p - dep_name (dep));
  		  i += p - dep_name (dep);
! 		  bcopy (stem_base, depname + i, stem_baselen);
! 		  i += stem_baselen;
  		  strcpy (depname + i, p + 1);
  		  p = depname;
  		}