Implement SysV-style $$@ support. I looked at E.Parmelan's patch but
authorPaul Smith <psmith@gnu.org>
Wed, 10 Jul 2002 12:59:07 +0000 (12:59 +0000)
committerPaul Smith <psmith@gnu.org>
Wed, 10 Jul 2002 12:59:07 +0000 (12:59 +0000)
decided to implement this a different way, and didn't use it.

ChangeLog
NEWS
doc/make.texi
main.c
po/.cvsignore
read.c
tests/ChangeLog
tests/scripts/variables/automatic
tests/test_driver.pl

index 97e88bc..97d08b5 100644 (file)
--- 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 (file)
--- 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.
 \f
-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.
index 6fac114..9a13b78 100644 (file)
@@ -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 (file)
--- 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"));
 }
index 82427cd..32b4d6f 100644 (file)
@@ -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 (file)
--- 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
index fec5186..3a13e9e 100644 (file)
@@ -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.
index b80d478..cb17efe 100644 (file)
@@ -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;
index a7a3b9f..38ee54a 100644 (file)
@@ -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