summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorPaul Smith <psmith@gnu.org>2002-07-10 12:59:07 +0000
committerPaul Smith <psmith@gnu.org>2002-07-10 12:59:07 +0000
commit4d72c4c11e3aff65e9bb36e5fcf75f088b140049 (patch)
tree92a4ac290dd9b9f2261e60457aca9b5a951bc15b
parent6c9a393f954805d49ab6c66957b46199ddd6e78e (diff)
downloadgunmake-4d72c4c11e3aff65e9bb36e5fcf75f088b140049.tar.gz
Implement SysV-style $$@ support. I looked at E.Parmelan's patch but
decided to implement this a different way, and didn't use it.
-rw-r--r--ChangeLog15
-rw-r--r--NEWS11
-rw-r--r--doc/make.texi59
-rw-r--r--main.c4
-rw-r--r--po/.cvsignore3
-rw-r--r--read.c129
-rw-r--r--tests/ChangeLog5
-rw-r--r--tests/scripts/variables/automatic29
-rw-r--r--tests/test_driver.pl18
9 files changed, 233 insertions, 40 deletions
diff --git a/ChangeLog b/ChangeLog
index 97e88bc..97d08b5 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,18 @@
+2002-07-10 Paul D. Smith <psmith@gnu.org>
+
+ Implement the SysV make syntax $$@, $$(@D), and $$(@F) in the
+ prerequisite list. A real SysV make will expand the entire
+ prerequisites list _twice_: we don't do that as it's a big
+ backward-compatibility problem. We only replace those specific
+ variables.
+
+ * read.c (record_files): Replace any $@, $(@D), and $(@F) variable
+ references left in the list of prerequisites. Check for .POSIX as
+ we record targets, so we can disable non-POSIX behavior while
+ reading makefiles as well as running them.
+ (eval): Check the prerequisite list to see if we have anything
+ that looks like a SysV prerequisite variable reference.
+
2002-07-09 Paul D. Smith <psmith@gnu.org>
* doc/make.texi (Prerequisite Types): Add a new section describing
diff --git a/NEWS b/NEWS
index 4c73093..724458b 100644
--- a/NEWS
+++ b/NEWS
@@ -1,6 +1,6 @@
GNU make NEWS -*-indented-text-*-
History of user-visible changes.
- 06 July 2002
+ 10 July 2002
Copyright (C) 2002 Free Software Foundation, Inc.
See the end for copying conditions.
@@ -12,7 +12,7 @@ Please send GNU make bug reports to <bug-make@gnu.org>.
See the README file and the GNU make manual for details on sending bug
reports.
-Version <next>
+Version 3.80
* A new feature exists: order-only prerequisites. These prerequisites
affect the order in which targets are built, but they do not impact
@@ -21,6 +21,13 @@ Version <next>
requiring that target A will always be rebuilt if target B is updated.
Patch for this feature provided by Greg McGary <greg@mcgary.org>.
+* For compatibility with SysV make, GNU make now supports the peculiar
+ syntax $$@, $$(@D), and $$(@F) in the prerequisites list of a rule.
+ This syntax is only valid within explicit and static pattern rules: it
+ cannot be used in implicit (suffix or pattern) rules. Edouard G. Parmelan
+ <egp@free.fr> provided a patch implementing this feature; however, I
+ decided to implemented it myself in a different way.
+
* A new function is defined: $(quote ...). The argument to this
function is the _name_ of a variable. The result of the function is
the value of the variable, without having been expanded.
diff --git a/doc/make.texi b/doc/make.texi
index 6fac114..9a13b78 100644
--- a/doc/make.texi
+++ b/doc/make.texi
@@ -8410,6 +8410,16 @@ part of the first prerequisite.
Lists of the directory parts and the file-within-directory
parts of all prerequisites.
+@vindex $(+D)
+@vindex +D @r{(automatic variable)}
+@item $(+D)
+@vindex $(+F)
+@vindex +F @r{(automatic variable)}
+@itemx $(+F)
+Lists of the directory parts and the file-within-directory
+parts of all prerequisites, including multiple instances of duplicated
+prerequisites.
+
@vindex $(?D)
@vindex ?D @r{(automatic variable)}
@item $(?D)
@@ -8429,6 +8439,32 @@ deep significance; @samp{$<} refers to the variable named @code{<} just
as @samp{$(CFLAGS)} refers to the variable named @code{CFLAGS}.
You could just as well use @samp{$(<)} in place of @samp{$<}.
+@vindex $$@@
+@vindex $$(@@D)
+@vindex $$(@@F)
+@cindex $$@@, support for
+GNU @code{make} provides support for the SysV @code{make} feature that
+allows special variable references @code{$$@@}, @code{$$(@@D)}, and
+@code{$$(@@F)} (note the required double-''$''!) to appear with the
+@emph{prerequisites list} (normal automatic variables are available
+only within a command script). When appearing in a prerequisites
+list, these variables are expanded to the name of the target, the
+directory component of the target, and the file component of the
+target, respectively.
+
+Note that these variables are available only within explicit and
+static pattern (@pxref{Static Pattern, ,Static Pattern Rules}) rules;
+they have no special significance within implicit (suffix or pattern)
+rules. Also note that while SysV @code{make} actually expands its
+entire prerequisite list @emph{twice}, GNU @code{make} does not behave
+this way: instead it simply expands these special variables without
+re-expanding any other part of the prerequisites list.
+
+This somewhat bizarre feature is included only to provide some
+compatibility with SysV makefiles. In a native GNU @code{make} file
+there are other ways to accomplish the same results. This feature is
+disabled if the special pseudo target @code{.POSIX} is defined.
+
@node Pattern Match, Match-Anything Rules, Automatic, Pattern Rules
@subsection How Patterns Match
@@ -9323,29 +9359,6 @@ general feature of rule chaining.
@xref{Chained Rules, ,Chains of Implicit Rules}.
@item
-In System V @code{make}, the string @samp{$$@@} has the strange meaning
-that, in the prerequisites of a rule with multiple targets, it stands
-for the particular target that is being processed.
-
-This is not defined in GNU @code{make} because @samp{$$} should always
-stand for an ordinary @samp{$}.
-
-It is possible to get portions of this functionality through the use of
-static pattern rules (@pxref{Static Pattern, ,Static Pattern Rules}).
-The System V @code{make} rule:
-
-@example
-$(targets): $$@@.o lib.a
-@end example
-
-@noindent
-can be replaced with the GNU @code{make} static pattern rule:
-
-@example
-$(targets): %: %.o lib.a
-@end example
-
-@item
In System V and 4.3 BSD @code{make}, files found by @code{VPATH} search
(@pxref{Directory Search, ,Searching Directories for Prerequisites}) have their names changed inside command
strings. We feel it is much cleaner to always use automatic variables
diff --git a/main.c b/main.c
index 39f0bd3..fcf0b91 100644
--- a/main.c
+++ b/main.c
@@ -2169,9 +2169,9 @@ print_usage (bad)
}
if (!remote_description || *remote_description == '\0')
- fprintf (usageto, _("\nBuilt for %s"), make_host);
+ fprintf (usageto, _("\nThis program built for %s"), make_host);
else
- fprintf (usageto, "\nBuilt for %s (%s)", make_host, remote_description);
+ fprintf (usageto, "\nThis program built for %s (%s)", make_host, remote_description);
fprintf (usageto, _("\nReport bugs to <bug-make@gnu.org>\n"));
}
diff --git a/po/.cvsignore b/po/.cvsignore
index 82427cd..32b4d6f 100644
--- a/po/.cvsignore
+++ b/po/.cvsignore
@@ -1,3 +1,4 @@
-*.gmo *.mo *.pot
+*.gmo *.mo *.pot *.po
Makefile.in Makefile
+POTFILES
diff --git a/read.c b/read.c
index 4b7c79c..a6d85b2 100644
--- a/read.c
+++ b/read.c
@@ -132,7 +132,8 @@ static int conditional_line PARAMS ((char *line, const struct floc *flocp));
static void record_files PARAMS ((struct nameseq *filenames, char *pattern, char *pattern_percent,
struct dep *deps, unsigned int cmds_started, char *commands,
unsigned int commands_idx, int two_colon,
- const struct floc *flocp, int set_default));
+ int have_sysv_atvar,
+ const struct floc *flocp, int set_default));
static void record_target_var PARAMS ((struct nameseq *filenames, char *defn,
int two_colon,
enum variable_origin origin,
@@ -430,6 +431,7 @@ eval (ebuf, set_default)
unsigned int cmds_started, tgts_started;
int ignoring = 0, in_ignored_define = 0;
int no_targets = 0; /* Set when reading a rule without targets. */
+ int have_sysv_atvar = 0;
struct nameseq *filenames = 0;
struct dep *deps = 0;
long nlines = 0;
@@ -450,7 +452,7 @@ eval (ebuf, set_default)
fi.lineno = tgts_started; \
record_files (filenames, pattern, pattern_percent, deps, \
cmds_started, commands, commands_idx, two_colon, \
- &fi, set_default); \
+ have_sysv_atvar, &fi, set_default); \
} \
filenames = 0; \
commands_idx = 0; \
@@ -1057,6 +1059,16 @@ eval (ebuf, set_default)
}
}
+ /* Do any of the prerequisites appear to have $@ etc.? */
+ have_sysv_atvar = 0;
+ if (!posix_pedantic)
+ for (p = strchr (p2, '$'); p != 0; p = strchr (p+1, '$'))
+ if (p[1] == '@' || (p[1] == '(' && p[2] == '@'))
+ {
+ have_sysv_atvar = 1;
+ break;
+ }
+
/* Is this a static pattern rule: `target: %targ: %dep; ...'? */
p = strchr (p2, ':');
while (p != 0 && p[-1] == '\\')
@@ -1654,7 +1666,8 @@ record_target_var (filenames, defn, two_colon, origin, flocp)
static void
record_files (filenames, pattern, pattern_percent, deps, cmds_started,
- commands, commands_idx, two_colon, flocp, set_default)
+ commands, commands_idx, two_colon, have_sysv_atvar,
+ flocp, set_default)
struct nameseq *filenames;
char *pattern, *pattern_percent;
struct dep *deps;
@@ -1662,6 +1675,7 @@ record_files (filenames, pattern, pattern_percent, deps, cmds_started,
char *commands;
unsigned int commands_idx;
int two_colon;
+ int have_sysv_atvar;
const struct floc *flocp;
int set_default;
{
@@ -1684,16 +1698,22 @@ record_files (filenames, pattern, pattern_percent, deps, cmds_started,
for (; filenames != 0; filenames = nextf)
{
-
- register char *name = filenames->name;
- register struct file *f;
- register struct dep *d;
+ char *name = filenames->name;
+ struct file *f;
+ struct dep *d;
struct dep *this;
char *implicit_percent;
nextf = filenames->next;
free (filenames);
+ /* Check for .POSIX. We used to do this in snap_deps() but that's not
+ good enough: it doesn't happen until after the makefile is read,
+ which means we cannot use its value during parsing. */
+
+ if (streq (name, ".POSIX"))
+ posix_pedantic = 1;
+
implicit_percent = find_percent (name);
implicit |= implicit_percent != 0;
@@ -1772,6 +1792,101 @@ record_files (filenames, pattern, pattern_percent, deps, cmds_started,
}
}
+ /* If at least one of the dependencies uses $$@ etc. deal with that.
+ It would be very nice and very simple to just expand everything, but
+ it would break a lot of backward compatibility. Maybe that's OK
+ since we're just emulating a SysV function, and if we do that then
+ why not emulate it completely (that's what SysV make does: it
+ re-expands the entire prerequisite list, all the time, with $@
+ etc. in scope. But, it would be a pain indeed to document this
+ ("iff you use $$@, your prerequisite lists is expanded twice...")
+ Ouch. Maybe better to make the code more complex. */
+
+ if (have_sysv_atvar)
+ {
+ char *p;
+ int tlen = strlen (name);
+ char *fnp = strrchr (name, '/');
+ int dlen;
+ int flen;
+
+ if (fnp)
+ {
+ dlen = fnp - name;
+ ++fnp;
+ flen = strlen (fnp);
+ }
+ else
+ {
+ dlen = 0;
+ fnp = name;
+ flen = tlen;
+ }
+
+
+ for (d = this; d != 0; d = d->next)
+ for (p = strchr (d->name, '$'); p != 0; p = strchr (p+1, '$'))
+ {
+ char *s = p;
+ char *at;
+ int atlen;
+
+ /* If it's a '$@' or '$(@', it's escaped */
+ if ((++p)[0] == '$'
+ && (p[1] == '@' || (p[1] == '(' && p[2] == '@')))
+ {
+ bcopy (p, s, strlen (p)+1);
+ continue;
+ }
+
+ /* Maybe found one. Check. p will point to '@' [for $@] or
+ ')' [for $(@)] or 'D' [for $(@D)] or 'F' [for $(@F)]. */
+ if (p[0] != '@'
+ && (p[0] != '(' || (++p)[0] != '@'
+ || ((++p)[0] != ')'
+ && (p[1] != ')' || (p[0] != 'D' && p[0] != 'F')))))
+ continue;
+
+ /* Found one. Compute the length and string ptr. Move p
+ past the variable reference. */
+ switch (p[0])
+ {
+ case 'D':
+ atlen = dlen;
+ at = name;
+ p += 2;
+ break;
+
+ case 'F':
+ atlen = flen;
+ at = fnp;
+ p += 2;
+ break;
+
+ default:
+ atlen = tlen;
+ at = name;
+ ++p;
+ break;
+ }
+
+ /* Get more space. */
+ {
+ int soff = s - d->name;
+ int poff = p - d->name;
+ d->name = (char *) xrealloc (d->name,
+ strlen (d->name) + atlen + 1);
+ s = d->name + soff;
+ p = d->name + poff;
+ }
+
+ /* Copy the string over. */
+ bcopy(p, s+atlen, strlen (p)+1);
+ bcopy(at, s, atlen);
+ p = s + atlen - 1;
+ }
+ }
+
if (!two_colon)
{
/* Single-colon. Combine these dependencies
diff --git a/tests/ChangeLog b/tests/ChangeLog
index fec5186..3a13e9e 100644
--- a/tests/ChangeLog
+++ b/tests/ChangeLog
@@ -1,3 +1,8 @@
+2002-07-10 Paul D. Smith <psmith@gnu.org>
+
+ * scripts/variables/automatic: Add some tests for $$@, $$(@D), and
+ $$(@F).
+
2002-07-09 Paul D. Smith <psmith@gnu.org>
* scripts/variables/automatic: Create a test for automatic variables.
diff --git a/tests/scripts/variables/automatic b/tests/scripts/variables/automatic
index b80d478..cb17efe 100644
--- a/tests/scripts/variables/automatic
+++ b/tests/scripts/variables/automatic
@@ -30,9 +30,8 @@ close(MAKEFILE);
# TEST #1 -- simple test
# -------
-&touch(qw(foo.x baz.z));
-
-sleep(1);
+# Touch these into the past
+&utouch(-10, qw(foo.x baz.z));
&run_make_with_options($makefile, "", &get_logfile);
$answer = "touch $dir/bar.y
@@ -47,4 +46,28 @@ touch $dir/foo.x\n";
unlink(qw(foo.x bar.y baz.z));
+# TEST #2 -- test the SysV emulation of $$@ etc.
+# -------
+
+$makefile2 = &get_tmpfile;
+
+open(MAKEFILE, "> $makefile2");
+print MAKEFILE "dir = $dir\n";
+print MAKEFILE <<'EOF';
+.SUFFIXES:
+.DEFAULT: ; @echo '$@'
+
+$(dir)/foo $(dir)/bar: $@.x $$@.x $$$@.x $$$$@.x $$(@D).x $$(@F).x
+
+$(dir)/x.z $(dir)/y.z: $(dir)/%.z : $@.% $$@.% $$$@.% $$$$@.% $$(@D).% $$(@F).%
+EOF
+
+&run_make_with_options($makefile2, "$dir/foo $dir/bar", &get_logfile);
+$answer = ".x\n$dir/foo.x\n\$.x\n\$@.x\n$dir.x\nfoo.x\n$dir/bar.x\nbar.x\n";
+&compare_output($answer, &get_logfile(1));
+
+&run_make_with_options($makefile2, "$dir/x.z $dir/y.z", &get_logfile);
+$answer = ".x\n$dir/x.z.x\n\$.x\n\$@.x\n$dir.x\nx.z.x\n.y\n$dir/y.z.y\n\$.y\n\$@.y\n$dir.y\ny.z.y\n";
+&compare_output($answer, &get_logfile(1));
+
1;
diff --git a/tests/test_driver.pl b/tests/test_driver.pl
index a7a3b9f..38ee54a 100644
--- a/tests/test_driver.pl
+++ b/tests/test_driver.pl
@@ -825,15 +825,29 @@ sub remove_directory_tree_inner
sub touch
{
- local (@filenames) = @_;
local ($file);
- foreach $file (@filenames) {
+ foreach $file (@_) {
(open(T, ">> $file") && print(T "\n") && close(T))
|| &error("Couldn't touch $file: $!\n", 1);
}
}
+# Touch with a time offset. To DTRT, call touch() then use stat() to get the
+# access/mod time for each file and apply the offset.
+
+sub utouch
+{
+ local ($off) = shift;
+ local ($file);
+
+ &touch(@_);
+
+ local (@s) = stat($_[0]);
+
+ utime($s[8]+$off, $s[9]+$off, @_);
+}
+
# open a file, write some stuff to it, and close it.
sub create_file