From 4d72c4c11e3aff65e9bb36e5fcf75f088b140049 Mon Sep 17 00:00:00 2001 From: Paul Smith Date: Wed, 10 Jul 2002 12:59:07 +0000 Subject: [PATCH] Implement SysV-style $$@ support. I looked at E.Parmelan's patch but decided to implement this a different way, and didn't use it. --- ChangeLog | 15 +++++ NEWS | 11 +++- doc/make.texi | 59 ++++++++++------- main.c | 4 +- po/.cvsignore | 3 +- read.c | 129 +++++++++++++++++++++++++++++++++++--- tests/ChangeLog | 5 ++ tests/scripts/variables/automatic | 29 ++++++++- tests/test_driver.pl | 18 +++++- 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 + + 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 * 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 . See the README file and the GNU make manual for details on sending bug reports. -Version +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 requiring that target A will always be rebuilt if target B is updated. Patch for this feature provided by Greg McGary . +* 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 + 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 \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 + + * scripts/variables/automatic: Add some tests for $$@, $$(@D), and + $$(@F). + 2002-07-09 Paul D. Smith * 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 -- 2.7.4