Dear sir,

      There is currently an incompatibility between GNU make and Solaris make
that causes me much grief with many of my makefiles.  In Solaris make a
pattern substitution in a variable expansion can accept multiple target wild
cards.  GNU make only accepts a single wild card.  Here is an example
makefile:

A=rafile.o rbfile.o rcfile.o

B=$(A:r%.o=pre%post.a pre%post.b)

do:
        echo $(B)

Which will result in the following output from GNU make 3.77:

  preafilepost.a pre%post.b prebfilepost.a pre%post.b precfilepost.a
pre%post.b

I would like to get the following output as is generated by Solaris make:

  preafilepost.a preafilepost.b prebfilepost.a prebfilepost.b precfilepost.a
precfilepost.b

I have included a proposed patch to make 3.77 that implements my proposal. 
Please consider including this are a similar fix into a future version of
make.  Thank you.

                                                        -Richard Deken
diff -Naur make-3.77.orig/expand.c make-3.77/expand.c
--- make-3.77.orig/expand.c     Fri May 15 08:36:51 1998
+++ make-3.77/expand.c  Sat Apr  1 22:08:12 2000
@@ -344,8 +344,8 @@
                                replace[replace_end - replace_beg] = '\0';
                              }
 
-                           o = patsubst_expand (o, value, pattern, replace,
-                                                percent, (char *) 0);
+                           o = rpatsubst_expand (o, value, pattern, replace,
+                                                 percent);
                          }
                        else
                          o = subst_expand (o, value,
diff -Naur make-3.77.orig/function.c make-3.77/function.c
--- make-3.77.orig/function.c   Thu Jul  9 23:05:05 1998
+++ make-3.77/function.c        Sat Apr  1 22:11:15 2000
@@ -213,6 +213,117 @@
   return o;
 }
 
+/* Store into VARIABLE_BUFFER at O the result of scanning TEXT
+   and replacing strings matching PATTERN with REPLACE (replace may contain
+   multiple matches.  */
+
+char *
+rpatsubst_expand (o, text, pattern, replace, pattern_percent)
+     char *o;
+     char *text;
+     register char *pattern, *replace;
+     register char *pattern_percent;
+{
+  unsigned int pattern_prepercent_len, pattern_postpercent_len;
+  unsigned int replace_len;
+  char *replace_percent;
+  char *t, *l;
+  unsigned int len;
+  int doneany = 0;
+
+  /* Find pattern percent */
+  if (pattern_percent == 0)
+    pattern_percent = find_percent (pattern);
+  if (pattern_percent == 0)
+    /* With no % in the pattern, this is just a simple substitution.  */
+    return subst_expand (o, text, pattern, replace, strlen (pattern),
+                        strlen (replace), 1, 0);
+
+  /* Record the length of PATTERN before and after the %
+     so we don't have to compute it more than once.  */
+  pattern_prepercent_len = pattern_percent - pattern;
+  pattern_postpercent_len = strlen (pattern_percent + 1);
+
+  while ((t = find_next_token (&text, &len)) != 0)
+    {
+      int fail = 0;
+
+      /* Is it big enough to match?  */
+      if (len < pattern_prepercent_len + pattern_postpercent_len)
+       fail = 1;
+
+      /* Does the prefix match? */
+      if (!fail && pattern_prepercent_len > 0
+         && (*t != *pattern
+             || t[pattern_prepercent_len - 1] != pattern_percent[-1]
+             || strncmp (t + 1, pattern + 1, pattern_prepercent_len - 1)))
+       fail = 1;
+
+      /* Does the suffix match? */
+      if (!fail && pattern_postpercent_len > 0
+         && (t[len - 1] != pattern_percent[pattern_postpercent_len]
+             || t[len - pattern_postpercent_len] != pattern_percent[1]
+             || strncmp (&t[len - pattern_postpercent_len],
+                         &pattern_percent[1], pattern_postpercent_len - 1)))
+       fail = 1;
+
+      if (fail)
+       {
+         /* It didn't match.  Output the string.  */
+         o = variable_buffer_output (o, t, len);
+         o = variable_buffer_output (o, " ", 1);
+         doneany = 1;
+       }
+      else
+       {
+         /* It matched.  Output the replacement.  */      
+         fail = 1;
+         for (l = replace; replace_percent = find_percent (l);
+              l = replace_percent + 1)
+           {
+             /* Output the part of the replacement before the %.  */
+             replace_len = replace_percent - l;
+             if (replace_len)
+               {
+                 o = variable_buffer_output (o, l, replace_len);
+                 fail = 0;
+               }
+
+             /* Output the part of the matched string that
+                matched the % in the pattern.  */
+             replace_len = len - (pattern_prepercent_len
+                                  + pattern_postpercent_len);
+             if (replace_len)
+               {
+                  o = variable_buffer_output (o, t + pattern_prepercent_len,
+                                              replace_len);
+                  fail = 0;
+               }
+           }
+
+         /* Output the part of the replacement after the %.  */
+         replace_len = strlen (l);
+         if (replace_len)
+           {
+             o = variable_buffer_output (o, l, replace_len);
+             fail = 0;
+           }
+
+         /* Add space if replacement was not "" */
+         if (!fail)
+           {
+             o = variable_buffer_output (o, " ", 1);
+             doneany = 1;
+           }
+       }
+    }
+  if (doneany)
+    /* Kill the last space.  */
+    --o;
+
+  return o;
+}
+
 /* Handle variable-expansion-time functions such as $(dir foo/bar) ==> foo/  */
 
 /* These enumeration constants distinguish the
@@ -1005,7 +1116,7 @@
       p3 = expand_argument (p2 + 1, p);
       p2 = expand_argument (p + 1, end);
 
-      o = patsubst_expand (o, p2, text, p3, (char *) 0, (char *) 0);
+      o = rpatsubst_expand (o, p2, text, p3, (char*) 0);
 
       free (text);
       free (p3);
diff -Naur make-3.77.orig/variable.h make-3.77/variable.h
--- make-3.77.orig/variable.h   Fri May 15 13:07:41 1998
+++ make-3.77/variable.h        Sat Apr  1 22:13:09 2000
@@ -89,6 +89,8 @@
                unsigned int slen, unsigned int rlen, int by_word, int suffix_only));
 extern char *patsubst_expand PARAMS ((char *o, char *text, char *pattern, char 
*replace,
                char *pattern_percent, char *replace_percent));
+extern char *rpatsubst_expand PARAMS ((char *o, char *text, char *pattern, char 
+*replace,
+               char *pattern_percent));
 
 /* expand.c */
 extern char *recursively_expand PARAMS ((struct variable *v));

Reply via email to