mirror of
https://github.com/mirror/make.git
synced 2025-03-27 20:40:35 +08:00
Some bug fixes and document updates.
This commit is contained in:
parent
e5324a8c6a
commit
8f2b1e2c7c
40
ChangeLog
40
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>
|
2000-11-17 Paul D. Smith <psmith@gnu.org>
|
||||||
|
|
||||||
* remake.c (f_mtime) [WINDOWS32]: On various advice, I changed the
|
* 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
|
the need for len or lastlen at all. Problem description with
|
||||||
sample code chages provided by Chris Faylor <cgf@redhat.com>.
|
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>
|
2000-10-05 Paul D. Smith <psmith@gnu.org>
|
||||||
|
|
||||||
* acinclude.m4 (AM_LC_MESSAGES): Remove undefined macro
|
* acinclude.m4 (AM_LC_MESSAGES): Remove undefined macro
|
||||||
|
@ -1,4 +1,5 @@
|
|||||||
set make=gnumake
|
set make=gnumake
|
||||||
|
+if not exist config.h copy config.h.W32 config.h
|
||||||
cd w32\subproc
|
cd w32\subproc
|
||||||
echo "Creating the subproc library"
|
echo "Creating the subproc library"
|
||||||
%ComSpec% /c build.bat
|
%ComSpec% /c build.bat
|
||||||
|
86
expand.c
86
expand.c
@ -92,7 +92,7 @@ initialize_variable_output ()
|
|||||||
|
|
||||||
/* Recursively expand V. The returned string is malloc'd. */
|
/* 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 *
|
char *
|
||||||
recursively_expand (v)
|
recursively_expand (v)
|
||||||
@ -469,52 +469,72 @@ variable_expand_for_file (line, file)
|
|||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Like allocated_variable_expand, but we first expand this variable in the
|
/* Like allocated_variable_expand, but for += target-specific variables.
|
||||||
context of the next variable set, then we append the expanded value. */
|
First recursively construct the variable value from its appended parts in
|
||||||
|
any upper variable sets. Then expand the resulting value. */
|
||||||
|
|
||||||
|
static char *
|
||||||
|
variable_append (name, length, set)
|
||||||
|
const char *name;
|
||||||
|
unsigned int length;
|
||||||
|
const struct variable_set_list *set;
|
||||||
|
{
|
||||||
|
const struct variable *v;
|
||||||
|
char *buf = 0;
|
||||||
|
|
||||||
|
/* If there's nothing left to check, return the empty buffer. */
|
||||||
|
if (!set)
|
||||||
|
return initialize_variable_output ();
|
||||||
|
|
||||||
|
/* Try to find the variable in this variable set. */
|
||||||
|
v = lookup_variable_in_set (name, length, set->set);
|
||||||
|
|
||||||
|
/* 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);
|
||||||
|
|
||||||
|
/* 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 ();
|
||||||
|
|
||||||
|
/* 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);
|
||||||
|
|
||||||
|
return variable_buffer_output (buf, v->value, strlen (v->value));
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
static char *
|
static char *
|
||||||
allocated_variable_append (v)
|
allocated_variable_append (v)
|
||||||
struct variable *v;
|
const struct variable *v;
|
||||||
{
|
{
|
||||||
struct variable_set_list *save;
|
char *val, *retval;
|
||||||
int len = strlen (v->name);
|
|
||||||
char *var = alloca (len + 4);
|
/* Construct the appended variable value. */
|
||||||
char *value;
|
|
||||||
|
|
||||||
char *obuf = variable_buffer;
|
char *obuf = variable_buffer;
|
||||||
unsigned int olen = variable_buffer_length;
|
unsigned int olen = variable_buffer_length;
|
||||||
|
|
||||||
variable_buffer = 0;
|
variable_buffer = 0;
|
||||||
|
|
||||||
assert(current_variable_set_list->next != 0);
|
val = variable_append (v->name, strlen (v->name), current_variable_set_list);
|
||||||
save = current_variable_set_list;
|
variable_buffer_output (val, "", 1);
|
||||||
current_variable_set_list = current_variable_set_list->next;
|
val = variable_buffer;
|
||||||
|
|
||||||
var[0] = '$';
|
|
||||||
var[1] = '(';
|
|
||||||
strcpy (&var[2], v->name);
|
|
||||||
var[len+2] = ')';
|
|
||||||
var[len+3] = '\0';
|
|
||||||
|
|
||||||
value = variable_expand_for_file (var, 0);
|
|
||||||
|
|
||||||
current_variable_set_list = save;
|
|
||||||
|
|
||||||
value += strlen (value);
|
|
||||||
value = variable_buffer_output (value, " ", 1);
|
|
||||||
value = variable_expand_string (value, v->value, (long)-1);
|
|
||||||
|
|
||||||
value = variable_buffer;
|
|
||||||
|
|
||||||
#if 0
|
|
||||||
/* Waste a little memory and save time. */
|
|
||||||
value = xrealloc (value, strlen (value))
|
|
||||||
#endif
|
|
||||||
|
|
||||||
variable_buffer = obuf;
|
variable_buffer = obuf;
|
||||||
variable_buffer_length = olen;
|
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.
|
/* Like variable_expand_for_file, but the returned string is malloc'd.
|
||||||
|
@ -786,9 +786,14 @@ struct string_desc
|
|||||||
#else
|
#else
|
||||||
static nls_uint32 SWAP PARAMS ((nls_uint32 i));
|
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
|
static inline nls_uint32
|
||||||
SWAP (i)
|
#if __STDC__
|
||||||
nls_uint32 i;
|
SWAP (nls_uint32 i)
|
||||||
|
#else
|
||||||
|
SWAP (i) nls_uint32 i;
|
||||||
|
#endif
|
||||||
{
|
{
|
||||||
return (i << 24) | ((i & 0xff00) << 8) | ((i >> 8) & 0xff00) | (i >> 24);
|
return (i << 24) | ((i & 0xff00) << 8) | ((i >> 8) & 0xff00) | (i >> 24);
|
||||||
}
|
}
|
||||||
|
34
make.texinfo
34
make.texinfo
@ -1,4 +1,4 @@
|
|||||||
\input texinfo @c -*- Texinfo -*-
|
input texinfo @c -*- Texinfo -*-
|
||||||
@c %**start of header
|
@c %**start of header
|
||||||
@setfilename make.info
|
@setfilename make.info
|
||||||
@settitle GNU @code{make}
|
@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
|
date. Unfortunately, these hosts provide no way to set a high
|
||||||
resolution file time stamp, so commands like @samp{cp -p} that
|
resolution file time stamp, so commands like @samp{cp -p} that
|
||||||
explicitly set a file's time stamp must discard its subsecond part. If
|
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
|
a file is created by such a command, you should list it as a
|
||||||
of @code{.LOW_RESOLUTION_TIME} so that @command{make} does not
|
prerequisite of @code{.LOW_RESOLUTION_TIME} so that @command{make} does
|
||||||
mistakenly conclude that the file is out of date. For example:
|
not mistakenly conclude that the file is out of date. For example:
|
||||||
|
|
||||||
@example
|
@example
|
||||||
@group
|
@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
|
Due to a limitation of the archive format, archive member time stamps
|
||||||
are always low resolution. You need not list archive members as
|
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.
|
automatically.
|
||||||
|
|
||||||
@findex .SILENT
|
@findex .SILENT
|
||||||
@ -2682,7 +2682,7 @@ be @emph{analogous}, but not necessarily @emph{identical}.
|
|||||||
Here is the syntax of a static pattern rule:
|
Here is the syntax of a static pattern rule:
|
||||||
|
|
||||||
@example
|
@example
|
||||||
@var{targets} @dots{}: @var{target-pattern}: @var{dep-patterns} @dots{}
|
@var{targets} @dots{}: @var{target-pattern}: @var{prereq-patterns} @dots{}
|
||||||
@var{commands}
|
@var{commands}
|
||||||
@dots{}
|
@dots{}
|
||||||
@end example
|
@end example
|
||||||
@ -2695,11 +2695,11 @@ Names}).
|
|||||||
|
|
||||||
@cindex target pattern, static (not implicit)
|
@cindex target pattern, static (not implicit)
|
||||||
@cindex stem
|
@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
|
prerequisites of each target. Each target is matched against the
|
||||||
@var{target-pattern} to extract a part of the target name, called 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}
|
@dfn{stem}. This stem is substituted into each of the @var{prereq-patterns}
|
||||||
to make the prerequisite names (one from each @var{dep-pattern}).
|
to make the prerequisite names (one from each @var{prereq-pattern}).
|
||||||
|
|
||||||
Each pattern normally contains the character @samp{%} just once. When the
|
Each pattern normally contains the character @samp{%} just once. When the
|
||||||
@var{target-pattern} matches a target, the @samp{%} can match any part of
|
@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.
|
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
|
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
|
type: all ordinary, or all double-colon. If they are double-colon, each
|
||||||
them is independent of the others. Each double-colon rule's commands are
|
of them is independent of the others. Each double-colon rule's commands
|
||||||
executed if the target is older than any prerequisites of that rule. This
|
are executed if the target is older than any prerequisites of that rule.
|
||||||
can result in executing none, any, or all of the double-colon rules.
|
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
|
Double-colon rules with the same target are in fact completely separate
|
||||||
from one another. Each double-colon rule is processed individually, just
|
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,
|
@var{pattern} may contain a @samp{%} which acts as a wildcard,
|
||||||
matching any number of any characters within a word. If
|
matching any number of any characters within a word. If
|
||||||
@var{replacement} also contains a @samp{%}, the @samp{%} is replaced
|
@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 in @code{patsubst}
|
||||||
@cindex @code{%}, quoting with @code{\} (backslash)
|
@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
|
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
|
@code{notdir} can be used to get a similar effect (@pxref{File Name
|
||||||
Functions, , Functions for File Names}). Note, however, that the
|
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:
|
the output of the @code{dir} function. Here is a table of the variants:
|
||||||
|
|
||||||
@table @samp
|
@table @samp
|
||||||
|
4
remake.c
4
remake.c
@ -1190,14 +1190,14 @@ f_mtime (file, search)
|
|||||||
if (adjusted_now < adjusted_mtime)
|
if (adjusted_now < adjusted_mtime)
|
||||||
{
|
{
|
||||||
#ifdef NO_FLOAT
|
#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);
|
file->name);
|
||||||
#else
|
#else
|
||||||
double from_now =
|
double from_now =
|
||||||
(FILE_TIMESTAMP_S (mtime) - FILE_TIMESTAMP_S (now)
|
(FILE_TIMESTAMP_S (mtime) - FILE_TIMESTAMP_S (now)
|
||||||
+ ((FILE_TIMESTAMP_NS (mtime) - FILE_TIMESTAMP_NS (now))
|
+ ((FILE_TIMESTAMP_NS (mtime) - FILE_TIMESTAMP_NS (now))
|
||||||
/ 1e9));
|
/ 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);
|
file->name, from_now);
|
||||||
#endif
|
#endif
|
||||||
clock_skew_detected = 1;
|
clock_skew_detected = 1;
|
||||||
|
@ -170,5 +170,29 @@ close(MAKEFILE);
|
|||||||
$answer = "; ok\n";
|
$answer = "; ok\n";
|
||||||
&compare_output($answer, &get_logfile(1));
|
&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;
|
1;
|
||||||
|
156
variable.c
156
variable.c
@ -45,9 +45,6 @@ static struct variable_set global_variable_set
|
|||||||
static struct variable_set_list global_setlist
|
static struct variable_set_list global_setlist
|
||||||
= { 0, &global_variable_set };
|
= { 0, &global_variable_set };
|
||||||
struct variable_set_list *current_variable_set_list = &global_setlist;
|
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. */
|
/* 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
|
/* Lookup a variable whose name is a string starting at NAME
|
||||||
and with LENGTH chars. NAME need not be null-terminated.
|
and with LENGTH chars. NAME need not be null-terminated.
|
||||||
Returns address of the `struct variable' containing all info
|
Returns address of the `struct variable' containing all info
|
||||||
on the variable, or nil if no such variable is defined.
|
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. */
|
|
||||||
|
|
||||||
struct variable *
|
struct variable *
|
||||||
lookup_variable (name, length)
|
lookup_variable (name, length)
|
||||||
char *name;
|
const char *name;
|
||||||
unsigned int length;
|
unsigned int length;
|
||||||
{
|
{
|
||||||
register struct variable_set_list *setlist;
|
const struct variable_set_list *setlist;
|
||||||
struct variable *firstv = 0;
|
|
||||||
|
|
||||||
register unsigned int i;
|
unsigned int i;
|
||||||
register unsigned int rawhash = 0;
|
unsigned int rawhash = 0;
|
||||||
|
|
||||||
for (i = 0; i < length; ++i)
|
for (i = 0; i < length; ++i)
|
||||||
HASH (rawhash, name[i]);
|
HASH (rawhash, name[i]);
|
||||||
@ -158,88 +149,74 @@ lookup_variable (name, length)
|
|||||||
for (setlist = current_variable_set_list;
|
for (setlist = current_variable_set_list;
|
||||||
setlist != 0; setlist = setlist->next)
|
setlist != 0; setlist = setlist->next)
|
||||||
{
|
{
|
||||||
register struct variable_set *set = setlist->set;
|
const struct variable_set *set = setlist->set;
|
||||||
register unsigned int hashval = rawhash % set->buckets;
|
unsigned int hashval = rawhash % set->buckets;
|
||||||
register struct variable *v;
|
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)
|
for (v = set->table[hashval]; v != 0; v = v->next)
|
||||||
if (*v->name == *name
|
if (*v->name == *name
|
||||||
&& strneq (v->name + 1, name + 1, length - 1)
|
&& strneq (v->name + 1, name + 1, length - 1)
|
||||||
&& v->name[length] == '\0')
|
&& v->name[length] == '\0')
|
||||||
break;
|
return v;
|
||||||
|
|
||||||
/* 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;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#ifdef VMS
|
#ifdef VMS
|
||||||
/* since we don't read envp[] on startup, try to get the
|
/* since we don't read envp[] on startup, try to get the
|
||||||
variable via getenv() here. */
|
variable via getenv() here. */
|
||||||
if (!firstv)
|
{
|
||||||
{
|
char *vname = alloca (length + 1);
|
||||||
char *vname = alloca (length + 1);
|
char *value;
|
||||||
char *value;
|
strncpy (vname, name, length);
|
||||||
strncpy (vname, name, length);
|
vname[length] = 0;
|
||||||
vname[length] = 0;
|
value = getenv (vname);
|
||||||
value = getenv (vname);
|
if (value != 0)
|
||||||
if (value != 0)
|
{
|
||||||
{
|
char *sptr;
|
||||||
char *sptr;
|
int scnt;
|
||||||
int scnt;
|
|
||||||
|
|
||||||
sptr = value;
|
sptr = value;
|
||||||
scnt = 0;
|
scnt = 0;
|
||||||
|
|
||||||
while ((sptr = strchr (sptr, '$')))
|
while ((sptr = strchr (sptr, '$')))
|
||||||
{
|
{
|
||||||
scnt++;
|
scnt++;
|
||||||
sptr++;
|
sptr++;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (scnt > 0)
|
if (scnt > 0)
|
||||||
{
|
{
|
||||||
char *nvalue;
|
char *nvalue;
|
||||||
char *nptr;
|
char *nptr;
|
||||||
|
|
||||||
nvalue = alloca (length + scnt + 1);
|
nvalue = alloca (strlen (value) + scnt + 1);
|
||||||
sptr = value;
|
sptr = value;
|
||||||
nptr = nvalue;
|
nptr = nvalue;
|
||||||
|
|
||||||
while (*sptr)
|
while (*sptr)
|
||||||
{
|
{
|
||||||
if (*sptr == '$')
|
if (*sptr == '$')
|
||||||
{
|
{
|
||||||
*nptr++ = '$';
|
*nptr++ = '$';
|
||||||
*nptr++ = '$';
|
*nptr++ = '$';
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
*nptr++ = *sptr;
|
*nptr++ = *sptr;
|
||||||
}
|
}
|
||||||
sptr++;
|
sptr++;
|
||||||
}
|
}
|
||||||
|
|
||||||
return define_variable (vname, length, nvalue, o_env, 1);
|
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 */
|
#endif /* VMS */
|
||||||
|
|
||||||
return firstv;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Lookup a variable whose name is a string starting at NAME
|
/* 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
|
Returns address of the `struct variable' containing all info
|
||||||
on the variable, or nil if no such variable is defined. */
|
on the variable, or nil if no such variable is defined. */
|
||||||
|
|
||||||
static struct variable *
|
struct variable *
|
||||||
lookup_variable_in_set (name, length, set)
|
lookup_variable_in_set (name, length, set)
|
||||||
char *name;
|
const char *name;
|
||||||
unsigned int length;
|
unsigned int length;
|
||||||
struct variable_set *set;
|
const struct variable_set *set;
|
||||||
{
|
{
|
||||||
register unsigned int i;
|
unsigned int i;
|
||||||
register unsigned int hash = 0;
|
unsigned int hash = 0;
|
||||||
register struct variable *v;
|
struct variable *v;
|
||||||
|
|
||||||
for (i = 0; i < length; ++i)
|
for (i = 0; i < length; ++i)
|
||||||
HASH (hash, name[i]);
|
HASH (hash, name[i]);
|
||||||
@ -788,7 +765,7 @@ try_variable_definition (flocp, line, origin, target_var)
|
|||||||
register char *end;
|
register char *end;
|
||||||
enum { f_bogus,
|
enum { f_bogus,
|
||||||
f_simple, f_recursive, f_append, f_conditional } flavor = 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;
|
struct variable *v;
|
||||||
int append = 0;
|
int append = 0;
|
||||||
|
|
||||||
@ -901,21 +878,16 @@ try_variable_definition (flocp, line, origin, target_var)
|
|||||||
break;
|
break;
|
||||||
case f_append:
|
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
|
/* 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. */
|
append only with other variables in the context of this target. */
|
||||||
if (target_var)
|
if (target_var)
|
||||||
{
|
{
|
||||||
append = 1;
|
append = 1;
|
||||||
current_variable_set_list->next = 0;
|
v = lookup_variable_in_set (expanded_name, strlen (expanded_name),
|
||||||
|
current_variable_set_list->set);
|
||||||
}
|
}
|
||||||
|
else
|
||||||
/* An appending variable definition "var += value".
|
v = lookup_variable (expanded_name, strlen (expanded_name));
|
||||||
Extract the old value and append the new one. */
|
|
||||||
v = lookup_variable (expanded_name, strlen (expanded_name));
|
|
||||||
|
|
||||||
current_variable_set_list->next = saved_next;
|
|
||||||
|
|
||||||
if (v == 0)
|
if (v == 0)
|
||||||
{
|
{
|
||||||
|
@ -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 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 *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
|
extern struct variable *define_variable_in_set
|
||||||
PARAMS ((char *name, unsigned int length, char *value,
|
PARAMS ((char *name, unsigned int length, char *value,
|
||||||
|
Loading…
Reference in New Issue
Block a user