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));