]> git.ipfire.org Git - thirdparty/make.git/commitdiff
Some bug fixes and document updates.
authorPaul Smith <psmith@gnu.org>
Sun, 21 Jan 2001 06:49:11 +0000 (06:49 +0000)
committerPaul Smith <psmith@gnu.org>
Sun, 21 Jan 2001 06:49:11 +0000 (06:49 +0000)
ChangeLog
build_w32.bat
expand.c
gettext.c
make.texinfo
remake.c
tests/scripts/features/targetvars
variable.c
variable.h

index 361e0430bc9be0fc3ff5c9125dec54e3d71a9fe2..966cb4a265eb8abf5f325df385300c7f20edbd6f 100644 (file)
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,37 @@
+2001-01-17  Paul D. Smith  <psmith@gnu.org>
+
+       * variable.c (lookup_variable) [VMS]: When getting values from the
+       environment, allocate enough space for the _value_ plus escapes,
+       not enough space for the name plus escapes :-/.
+       Reported by John Fowler <jfowler@nyx.net>.
+
+       * remake.c (f_mtime): Removed the "***" prefix from the mod time
+       warnings that make generates, so it doesn't look like an error.
+       Reported by Karl Berry <karl@gnu.org>.
+
+
+       Fix for PR/2020:  Rework appended target-specific variables.  I'm
+       fairly confident this algorithm is finally correct.
+
+       * expand.c (allocated_variable_append): Rewrite.  Instead of
+       expanding each appended variable then adding all the expanded
+       strings together, we append all the unexpanded values going up
+       through the variable set contexts, then expand the final result.
+       This behaves just like non-target-specific appended variable
+       values, while the old way didn't in various corner cases.
+       (variable_append): New function: recursively append the unexpanded
+       value of a variable, walking from the outermost variable scope to
+       the innermost.
+       * variable.c (lookup_variable): Remove the code that looked up the
+       variable set list if the found variable was "append".  We don't
+       need this anymore.
+       (lookup_variable_in_set): Make this non-static so we can use it
+       elsewhere.
+       (try_variable_definition): Use lookup_variable_in_set() rather
+       than faking out current_variable_set_list by hand (cleanup).
+       * variable.h: Add a prototype for the now non-static
+       lookup_variable_in_set().
+
 2000-11-17  Paul D. Smith  <psmith@gnu.org>
 
        * remake.c (f_mtime) [WINDOWS32]: On various advice, I changed the
        the need for len or lastlen at all.  Problem description with
        sample code chages provided by Chris Faylor <cgf@redhat.com>.
 
+2000-10-24  Paul D. Smith  <psmith@gnu.org>
+
+       * gettext.c (SWAP): Declare this with the prototype, otherwise
+       some systems don't work (non-32-bit?  Reported for Cray T3E).
+       Reported by Thorstein Thorsteinsson <thor@signe.teokem.lu.se>.
+
 2000-10-05  Paul D. Smith  <psmith@gnu.org>
 
        * acinclude.m4 (AM_LC_MESSAGES): Remove undefined macro
index 7ff771f2098789ebdb407ae456253e4f8c0988cc..559fe8d36de3a0b592ec7eb379cdc1b170bc20b4 100644 (file)
@@ -1,4 +1,5 @@
 set make=gnumake\r
++if not exist config.h copy config.h.W32 config.h\r
 cd w32\subproc\r
 echo "Creating the subproc library"\r
 %ComSpec% /c build.bat\r
index 8ada0cdf4797d8cb69f2f817fc5e683cbfb13214..e397cf4739a1dd105c2b40d44554638eca17a875 100644 (file)
--- a/expand.c
+++ b/expand.c
@@ -92,7 +92,7 @@ initialize_variable_output ()
 \f
 /* Recursively expand V.  The returned string is malloc'd.  */
 
-static char *allocated_variable_append PARAMS ((struct variable *v));
+static char *allocated_variable_append PARAMS ((const struct variable *v));
 
 char *
 recursively_expand (v)
@@ -469,52 +469,72 @@ variable_expand_for_file (line, file)
   return result;
 }
 \f
-/* Like allocated_variable_expand, but we first expand this variable in the
-    context of the next variable set, then we append the expanded value.  */
+/* Like allocated_variable_expand, but for += target-specific variables.
+   First recursively construct the variable value from its appended parts in
+   any upper variable sets.  Then expand the resulting value.  */
 
 static char *
-allocated_variable_append (v)
-     struct variable *v;
+variable_append (name, length, set)
+     const char *name;
+     unsigned int length;
+     const struct variable_set_list *set;
 {
-  struct variable_set_list *save;
-  int len = strlen (v->name);
-  char *var = alloca (len + 4);
-  char *value;
+  const struct variable *v;
+  char *buf = 0;
 
-  char *obuf = variable_buffer;
-  unsigned int olen = variable_buffer_length;
+  /* If there's nothing left to check, return the empty buffer.  */
+  if (!set)
+    return initialize_variable_output ();
 
-  variable_buffer = 0;
+  /* Try to find the variable in this variable set.  */
+  v = lookup_variable_in_set (name, length, set->set);
 
-  assert(current_variable_set_list->next != 0);
-  save = current_variable_set_list;
-  current_variable_set_list = current_variable_set_list->next;
+  /* If there isn't one, look to see if there's one in a set above us.  */
+  if (!v)
+    return variable_append (name, length, set->next);
 
-  var[0] = '$';
-  var[1] = '(';
-  strcpy (&var[2], v->name);
-  var[len+2] = ')';
-  var[len+3] = '\0';
+  /* If this variable type is append, first get any upper values.
+     If not, initialize the buffer.  */
+  if (v->append)
+    buf = variable_append (name, length, set->next);
+  else
+    buf = initialize_variable_output ();
 
-  value = variable_expand_for_file (var, 0);
+  /* Append this value to the buffer, and return it.
+     If we already have a value, first add a space.  */
+  if (buf > variable_buffer)
+    buf = variable_buffer_output (buf, " ", 1);
 
-  current_variable_set_list = save;
+  return variable_buffer_output (buf, v->value, strlen (v->value));
+}
+
+
+static char *
+allocated_variable_append (v)
+     const struct variable *v;
+{
+  char *val, *retval;
 
-  value += strlen (value);
-  value = variable_buffer_output (value, " ", 1);
-  value = variable_expand_string (value, v->value, (long)-1);
+  /* Construct the appended variable value.  */
 
-  value = variable_buffer;
+  char *obuf = variable_buffer;
+  unsigned int olen = variable_buffer_length;
 
-#if 0
-  /* Waste a little memory and save time.  */
-  value = xrealloc (value, strlen (value))
-#endif
+  variable_buffer = 0;
+
+  val = variable_append (v->name, strlen (v->name), current_variable_set_list);
+  variable_buffer_output (val, "", 1);
+  val = variable_buffer;
 
   variable_buffer = obuf;
   variable_buffer_length = olen;
 
-  return value;
+  /* Now expand it and return that.  */
+
+  retval = allocated_variable_expand (val);
+
+  free (val);
+  return retval;
 }
 
 /* Like variable_expand_for_file, but the returned string is malloc'd.
index 1ecb715b80e3a17944eb54f62057390b94597a15..b97df8dbf1846e20b9a04da7dfd01b9d0f845da2 100644 (file)
--- a/gettext.c
+++ b/gettext.c
@@ -786,9 +786,14 @@ struct string_desc
 #else
 static nls_uint32 SWAP PARAMS ((nls_uint32 i));
 
+/* Apparently on some (non-32-bit?) systems it's important to use the right
+   prototype.  Reported for a CRAY T3E.  */
 static inline nls_uint32
-SWAP (i)
-     nls_uint32 i;
+#if __STDC__
+  SWAP (nls_uint32 i)
+#else
+  SWAP (i) nls_uint32 i;
+#endif
 {
   return (i << 24) | ((i & 0xff00) << 8) | ((i >> 8) & 0xff00) | (i >> 24);
 }
index ca05fba3167fb014daf92b436bd4dadecdd9fa08..98a69856b4d2ee936f2c5ea6b6ae9797e126a846 100644 (file)
@@ -1,4 +1,4 @@
-\input texinfo                @c -*- Texinfo -*-
+input texinfo                @c -*- Texinfo -*-
 @c %**start of header
 @setfilename make.info
 @settitle GNU @code{make}
@@ -2465,9 +2465,9 @@ chance of @command{make} incorrectly concluding that a file is up to
 date.  Unfortunately, these hosts provide no way to set a high
 resolution file time stamp, so commands like @samp{cp -p} that
 explicitly set a file's time stamp must discard its subsecond part.  If
-a file is created by such a command, you should list it as a dependency
-of @code{.LOW_RESOLUTION_TIME} so that @command{make} does not
-mistakenly conclude that the file is out of date.  For example:
+a file is created by such a command, you should list it as a
+prerequisite of @code{.LOW_RESOLUTION_TIME} so that @command{make} does
+not mistakenly conclude that the file is out of date.  For example:
 
 @example
 @group
@@ -2485,7 +2485,7 @@ is at the start of the same second that @file{src}'s time stamp is in.
 
 Due to a limitation of the archive format, archive member time stamps
 are always low resolution.  You need not list archive members as
-dependencies of @code{.LOW_RESOLUTION_TIME}, as @command{make} does this
+prerequisites of @code{.LOW_RESOLUTION_TIME}, as @command{make} does this
 automatically.
 
 @findex .SILENT
@@ -2682,7 +2682,7 @@ be @emph{analogous}, but not necessarily @emph{identical}.
 Here is the syntax of a static pattern rule:
 
 @example
-@var{targets} @dots{}: @var{target-pattern}: @var{dep-patterns} @dots{}
+@var{targets} @dots{}: @var{target-pattern}: @var{prereq-patterns} @dots{}
         @var{commands}
         @dots{}
 @end example
@@ -2695,11 +2695,11 @@ Names}).
 
 @cindex target pattern, static (not implicit)
 @cindex stem
-The @var{target-pattern} and @var{dep-patterns} say how to compute the
+The @var{target-pattern} and @var{prereq-patterns} say how to compute the
 prerequisites of each target.  Each target is matched against the
 @var{target-pattern} to extract a part of the target name, called the
-@dfn{stem}.  This stem is substituted into each of the @var{dep-patterns}
-to make the prerequisite names (one from each @var{dep-pattern}).
+@dfn{stem}.  This stem is substituted into each of the @var{prereq-patterns}
+to make the prerequisite names (one from each @var{prereq-pattern}).
 
 Each pattern normally contains the character @samp{%} just once.  When the
 @var{target-pattern} matches a target, the @samp{%} can match any part of
@@ -2838,10 +2838,12 @@ to precisely the targets specified.
 ordinary rules when the same target appears in more than one rule.
 
 When a target appears in multiple rules, all the rules must be the same
-type: all ordinary, or all double-colon.  If they are double-colon, each of
-them is independent of the others.  Each double-colon rule's commands are
-executed if the target is older than any prerequisites of that rule.  This
-can result in executing none, any, or all of the double-colon rules.
+type: all ordinary, or all double-colon.  If they are double-colon, each
+of them is independent of the others.  Each double-colon rule's commands
+are executed if the target is older than any prerequisites of that rule.
+If there are no prerequisites for that rule, its commands are always
+executed (even if the target already exists).  This can result in
+executing none, any, or all of the double-colon rules.
 
 Double-colon rules with the same target are in fact completely separate
 from one another.  Each double-colon rule is processed individually, just
@@ -5481,7 +5483,9 @@ Finds whitespace-separated words in @var{text} that match
 @var{pattern} may contain a @samp{%} which acts as a wildcard,
 matching any number of any characters within a word.  If
 @var{replacement} also contains a @samp{%}, the @samp{%} is replaced
-by the text that matched the @samp{%} in @var{pattern}.@refill
+by the text that matched the @samp{%} in @var{pattern}.  Only the first
+@samp{%} in the @var{pattern} and @var{replacement} is treated this
+way; any subsequent @samp{%} is unchanged.@refill
 
 @cindex @code{%}, quoting in @code{patsubst}
 @cindex @code{%}, quoting with @code{\} (backslash)
@@ -8125,7 +8129,7 @@ appending @samp{D} or @samp{F}, respectively.  These variants are
 semi-obsolete in GNU @code{make} since the functions @code{dir} and
 @code{notdir} can be used to get a similar effect (@pxref{File Name
 Functions, , Functions for File Names}).  Note, however, that the
-@samp{F} variants all omit the trailing slash which always appears in
+@samp{D} variants all omit the trailing slash which always appears in
 the output of the @code{dir} function.  Here is a table of the variants:
 
 @table @samp
index f036b53e45b02da31feaef12fac1b62658baa799..06e8d3165cff71b737e9d1f84fa5e97715c48d5b 100644 (file)
--- a/remake.c
+++ b/remake.c
@@ -1190,14 +1190,14 @@ f_mtime (file, search)
            if (adjusted_now < adjusted_mtime)
              {
 #ifdef NO_FLOAT
-               error (NILF, _("*** Warning: File `%s' has modification time in the future"),
+               error (NILF, _("Warning: File `%s' has modification time in the future"),
                        file->name);
 #else
                double from_now =
                  (FILE_TIMESTAMP_S (mtime) - FILE_TIMESTAMP_S (now)
                   + ((FILE_TIMESTAMP_NS (mtime) - FILE_TIMESTAMP_NS (now))
                      / 1e9));
-               error (NILF, _("*** Warning: File `%s' has modification time %.2g s in the future"),
+               error (NILF, _("Warning: File `%s' has modification time %.2g s in the future"),
                       file->name, from_now);
 #endif
                clock_skew_detected = 1;
index a1bd88e54922a6090d63d381ce2e0ddc2c41ac81..a70d3ab6506cc6bb507ad53199e14a6bafba6224 100644 (file)
@@ -170,5 +170,29 @@ close(MAKEFILE);
 $answer = "; ok\n";
 &compare_output($answer, &get_logfile(1));
 
+# Test #12
+# PR/2020: More hassles with += target-specific vars.  I _really_ think
+# I nailed it this time :-/.
+
+$makefile5 = &get_tmpfile;
+
+open(MAKEFILE, "> $makefile5");
+print MAKEFILE <<'EOF';
+.PHONY: a
+
+BLAH := foo
+COMMAND = echo $(BLAH)
+
+a: ; @$(COMMAND)
+
+a: BLAH := bar
+a: COMMAND += snafu $(BLAH)
+EOF
+close(MAKEFILE);
+
+&run_make_with_options("$makefile5", "", &get_logfile);
+$answer = "bar snafu bar\n";
+&compare_output($answer, &get_logfile(1));
+
 
 1;
index 75ceb78d80c52954dacf03b35789d47892d19db7..f28e83cdd4802297d01a17011e69d3e341a4f27c 100644 (file)
@@ -45,9 +45,6 @@ static struct variable_set global_variable_set
 static struct variable_set_list global_setlist
   = { 0, &global_variable_set };
 struct variable_set_list *current_variable_set_list = &global_setlist;
-
-static struct variable *lookup_variable_in_set PARAMS ((char *name,
-                          unsigned int length, struct variable_set *set));
 \f
 /* Implement variables.  */
 
@@ -134,23 +131,17 @@ define_variable_in_set (name, length, value, origin, recursive, set, flocp)
 /* Lookup a variable whose name is a string starting at NAME
    and with LENGTH chars.  NAME need not be null-terminated.
    Returns address of the `struct variable' containing all info
-   on the variable, or nil if no such variable is defined.
-
-   If we find a variable which is in the process of being expanded,
-   try to find one further up the set_list chain.  If we don't find
-   one that isn't being expanded, return a pointer to whatever we
-   _did_ find.  */
+   on the variable, or nil if no such variable is defined.  */
 
 struct variable *
 lookup_variable (name, length)
-     char *name;
+     const char *name;
      unsigned int length;
 {
-  register struct variable_set_list *setlist;
-  struct variable *firstv = 0;
+  const struct variable_set_list *setlist;
 
-  register unsigned int i;
-  register unsigned int rawhash = 0;
+  unsigned int i;
+  unsigned int rawhash = 0;
 
   for (i = 0; i < length; ++i)
     HASH (rawhash, name[i]);
@@ -158,88 +149,74 @@ lookup_variable (name, length)
   for (setlist = current_variable_set_list;
        setlist != 0; setlist = setlist->next)
     {
-      register struct variable_set *set = setlist->set;
-      register unsigned int hashval = rawhash % set->buckets;
-      register struct variable *v;
+      const struct variable_set *set = setlist->set;
+      unsigned int hashval = rawhash % set->buckets;
+      struct variable *v;
 
-      /* Look through this set list.  */
+      /* Look through this set list; return it if found.  */
       for (v = set->table[hashval]; v != 0; v = v->next)
        if (*v->name == *name
            && strneq (v->name + 1, name + 1, length - 1)
            && v->name[length] == '\0')
-          break;
-
-      /* If we didn't find anything, go to the next set list.  */
-      if (!v)
-        continue;
-
-      /* If it's not being expanded already, we're done.  */
-      if (!v->expanding)
-        return v;
-
-      /* It is, so try to find another one.  If this is the first one we've
-         seen, keep a pointer in case we don't find anything else.  */
-      if (!firstv)
-        firstv = v;
+          return v;
     }
 
 #ifdef VMS
   /* since we don't read envp[] on startup, try to get the
      variable via getenv() here.  */
-  if (!firstv)
-    {
-      char *vname = alloca (length + 1);
-      char *value;
-      strncpy (vname, name, length);
-      vname[length] = 0;
-      value = getenv (vname);
-      if (value != 0)
-       {
-         char *sptr;
-         int scnt;
-
-         sptr = value;
-         scnt = 0;
-
-         while ((sptr = strchr (sptr, '$')))
-           {
-             scnt++;
-             sptr++;
-           }
-
-         if (scnt > 0)
-           {
-             char *nvalue;
-             char *nptr;
+  {
+    char *vname = alloca (length + 1);
+    char *value;
+    strncpy (vname, name, length);
+    vname[length] = 0;
+    value = getenv (vname);
+    if (value != 0)
+      {
+        char *sptr;
+        int scnt;
 
-             nvalue = alloca (length + scnt + 1);
-             sptr = value;
-             nptr = nvalue;
+        sptr = value;
+        scnt = 0;
 
-             while (*sptr)
-               {
-                 if (*sptr == '$')
-                   {
-                     *nptr++ = '$';
-                     *nptr++ = '$';
-                   }
-                 else
-                   {
-                     *nptr++ = *sptr;
-                   }
-                 sptr++;
-               }
+        while ((sptr = strchr (sptr, '$')))
+          {
+            scnt++;
+            sptr++;
+          }
 
-             return define_variable (vname, length, nvalue, o_env, 1);
+        if (scnt > 0)
+          {
+            char *nvalue;
+            char *nptr;
+
+            nvalue = alloca (strlen (value) + scnt + 1);
+            sptr = value;
+            nptr = nvalue;
+
+            while (*sptr)
+              {
+                if (*sptr == '$')
+                  {
+                    *nptr++ = '$';
+                    *nptr++ = '$';
+                  }
+                else
+                  {
+                    *nptr++ = *sptr;
+                  }
+                sptr++;
+              }
+
+            return define_variable (vname, length, nvalue, o_env, 1);
 
-           }
+          }
 
-         return define_variable (vname, length, value, o_env, 1);
-       }
-    }
+        return define_variable (vname, length, value, o_env, 1);
+      }
+  }
 #endif /* VMS */
 
-  return firstv;
+  return 0;
 }
 \f
 /* Lookup a variable whose name is a string starting at NAME
@@ -247,15 +224,15 @@ lookup_variable (name, length)
    Returns address of the `struct variable' containing all info
    on the variable, or nil if no such variable is defined.  */
 
-static struct variable *
+struct variable *
 lookup_variable_in_set (name, length, set)
-     char *name;
+     const char *name;
      unsigned int length;
-     struct variable_set *set;
+     const struct variable_set *set;
 {
-  register unsigned int i;
-  register unsigned int hash = 0;
-  register struct variable *v;
+  unsigned int i;
+  unsigned int hash = 0;
+  struct variable *v;
 
   for (i = 0; i < length; ++i)
     HASH (hash, name[i]);
@@ -788,7 +765,7 @@ try_variable_definition (flocp, line, origin, target_var)
   register char *end;
   enum { f_bogus,
          f_simple, f_recursive, f_append, f_conditional } flavor = f_bogus;
-  char *name, *expanded_name, *value, *alloc_value=NULL;
+  char *name, *expanded_name, *value=0, *alloc_value=NULL;
   struct variable *v;
   int append = 0;
 
@@ -901,21 +878,16 @@ try_variable_definition (flocp, line, origin, target_var)
       break;
     case f_append:
       {
-        struct variable_set_list *saved_next = current_variable_set_list->next;
-
         /* If we have += but we're in a target variable context, we want to
            append only with other variables in the context of this target.  */
         if (target_var)
           {
             append = 1;
-            current_variable_set_list->next = 0;
+            v = lookup_variable_in_set (expanded_name, strlen (expanded_name),
+                                        current_variable_set_list->set);
           }
-
-        /* An appending variable definition "var += value".
-           Extract the old value and append the new one.  */
-        v = lookup_variable (expanded_name, strlen (expanded_name));
-
-        current_variable_set_list->next = saved_next;
+        else
+          v = lookup_variable (expanded_name, strlen (expanded_name));
 
         if (v == 0)
           {
index d449ef82d97c7fbc8d4af060051d8983886bff44..9c23511b73312d400b18f65fbe4169ff532026a0 100644 (file)
@@ -108,7 +108,10 @@ extern void print_variable_set PARAMS ((struct variable_set *set, char *prefix))
 extern void merge_variable_set_lists PARAMS ((struct variable_set_list **setlist0, struct variable_set_list *setlist1));
 extern struct variable *try_variable_definition PARAMS ((const struct floc *flocp, char *line, enum variable_origin origin, int target_var));
 
-extern struct variable *lookup_variable PARAMS ((char *name, unsigned int length));
+extern struct variable *lookup_variable PARAMS ((const char *name, unsigned int length));
+extern struct variable *lookup_variable_in_set PARAMS ((const char *name,
+                                                        unsigned int length,
+                                                        const struct variable_set *set));
 
 extern struct variable *define_variable_in_set
     PARAMS ((char *name, unsigned int length, char *value,