summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--ChangeLog40
-rw-r--r--build_w32.bat1
-rw-r--r--expand.c82
-rw-r--r--gettext.c9
-rw-r--r--make.texinfo34
-rw-r--r--remake.c4
-rw-r--r--tests/scripts/features/targetvars24
-rw-r--r--variable.c162
-rw-r--r--variable.h5
9 files changed, 215 insertions, 146 deletions
diff --git a/ChangeLog b/ChangeLog
index 361e043..966cb4a 100644
--- 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
@@ -11,6 +45,12 @@
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
diff --git a/build_w32.bat b/build_w32.bat
index 7ff771f..559fe8d 100644
--- a/build_w32.bat
+++ b/build_w32.bat
@@ -1,4 +1,5 @@
set make=gnumake
++if not exist config.h copy config.h.W32 config.h
cd w32\subproc
echo "Creating the subproc library"
%ComSpec% /c build.bat
diff --git a/expand.c b/expand.c
index 8ada0cd..e397cf4 100644
--- a/expand.c
+++ b/expand.c
@@ -92,7 +92,7 @@ initialize_variable_output ()
/* 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;
}
-/* 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.
diff --git a/gettext.c b/gettext.c
index 1ecb715..b97df8d 100644
--- 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);
}
diff --git a/make.texinfo b/make.texinfo
index ca05fba..98a6985 100644
--- a/make.texinfo
+++ b/make.texinfo
@@ -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
diff --git a/remake.c b/remake.c
index f036b53..06e8d31 100644
--- 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;
diff --git a/tests/scripts/features/targetvars b/tests/scripts/features/targetvars
index a1bd88e..a70d3ab 100644
--- a/tests/scripts/features/targetvars
+++ b/tests/scripts/features/targetvars
@@ -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;
diff --git a/variable.c b/variable.c
index 75ceb78..f28e83c 100644
--- a/variable.c
+++ b/variable.c
@@ -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));
/* 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;
}
/* 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)
{
diff --git a/variable.h b/variable.h
index d449ef8..9c23511 100644
--- a/variable.h
+++ b/variable.h
@@ -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,