1
0
mirror of https://github.com/mirror/make.git synced 2025-04-24 12:00:35 +08:00

Improve backslash/newline handling to adhere to POSIX requirements.

This commit is contained in:
Paul Smith 2010-11-06 21:56:23 +00:00
parent a86d1693ba
commit 391456aad7
20 changed files with 297 additions and 93 deletions

View File

@ -1,3 +1,37 @@
2010-11-06 Paul Smith <psmith@gnu.org>
* variable.c (print_auto_variable): Print auto variables; ignore others.
(print_noauto_variable): Print non-auto variables; ignore others.
(print_variable_set): Allow the caller to select which type to print.
(print_target_variables): Show all the non-auto variables for a target.
* default.c (install_default_suffix_rules): Initialize recipe_prefix.
* rule.c (install_pattern_rule): Ditto.
* read.c (record_files): Pass in the current recipe prefix. Remember
it in the struct command for these targets.
(eval): Remember the value of RECIPEPREFIX when we start parsing.
Do not remove recipe prefixes from the recipe here: we'll do it later.
* job.c (start_job_command): Remove recipe prefix characters early,
before we print the output or chop it up.
* file.c (print_file): If recipe_prefix is not standard, reset it
in -p output. Assign target variables in -p output as well.
* commands.c (chop_commands): Max command lines is USHRT_MAX.
Set any_recurse as a bitfield.
* make.h (USHRT_MAX): Define if not set.
2010-10-27 Paul Smith <psmith@gnu.org>
* commands.h (struct commands): Rearrange to make better use of
memory. Add new recipe_prefix value.
2010-10-26 Paul Smith <psmith@gnu.org>
* doc/make.texi (Setting): Document the treatment of
backslash-newline in variable values.
* misc.c (collapse_continuations): Do not collapse multiple
backslash-newlines into a single space. Fixes Savannah bug #16670.
2010-08-29 Paul Smith <psmith@gnu.org>
* doc/make.texi (Implicit Variables): Document LDLIBS and LOADLIBES.

13
NEWS
View File

@ -15,6 +15,13 @@ A complete list of bugs fixed in this version is available here:
http://sv.gnu.org/bugs/index.php?group=make&report_id=111&fix_release_id=101&set=custom
* WARNING: Backward-incompatibility!
This version of make adheres to the POSIX backslash/newline handling,
introducing the following differences:
* Each backslash/newline in a variable value is replaced with a space;
multiple consecutive backslash/newlines do not condense into one space.
* In recipes, a recipe prefix following a backslash-newlines is removed.
* New command line option: --trace enables tracing of targets. When enabled
the recipe to be invoked is printed even if it would otherwise be suppressed
by .SILENT or a "@" prefix character. Also before each recipe is run the
@ -24,6 +31,12 @@ http://sv.gnu.org/bugs/index.php?group=make&report_id=111&fix_release_id=101&set
* On failure, the makefile name and linenumber of the recipe that failed are
shown.
* A .RECIPEPREFIX setting is remembered per-recipe and variables expanded
in that recipe also use that recipe prefix setting.
* In -p output, .RECIPEPREFIX settings are shown and all target-specific
variables are output as if in a makefile, instead of as comments.
Version 3.82

View File

@ -402,6 +402,9 @@ chop_commands (struct commands *cmds)
/* Finally, set the corresponding CMDS->lines_flags elements and the
CMDS->any_recurse flag. */
if (nlines > USHRT_MAX)
fatal (&cmds->fileinfo, _("Recipe has too many lines (%ud)"), nlines);
cmds->ncommand_lines = nlines;
cmds->command_lines = lines;
@ -433,7 +436,7 @@ chop_commands (struct commands *cmds)
flags |= COMMANDS_RECURSE;
cmds->lines_flags[idx] = flags;
cmds->any_recurse |= flags & COMMANDS_RECURSE;
cmds->any_recurse |= flags & COMMANDS_RECURSE ? 1 : 0;
}
}
@ -685,10 +688,16 @@ print_commands (const struct commands *cmds)
while (*s != '\0')
{
const char *end;
int bs;
end = strchr (s, '\n');
if (end == 0)
end = s + strlen (s);
/* Print one full logical recipe line: find a non-escaped newline. */
for (end = s, bs = 0; *end != '\0'; ++end)
{
if (*end == '\n' && !bs)
break;
bs = *end == '\\' ? !bs : 0;
}
printf ("%c%.*s\n", cmd_prefix, (int) (end - s), s);

View File

@ -23,10 +23,11 @@ struct commands
{
struct floc fileinfo; /* Where commands were defined. */
char *commands; /* Commands text. */
unsigned int ncommand_lines;/* Number of command lines. */
char **command_lines; /* Commands chopped up into lines. */
char *lines_flags; /* One set of flag bits for each line. */
int any_recurse; /* Nonzero if any `lines_recurse' elt has */
unsigned short ncommand_lines;/* Number of command lines. */
char recipe_prefix; /* Recipe prefix for this command set. */
unsigned int any_recurse:1; /* Nonzero if any `lines_flags' elt has */
/* the COMMANDS_RECURSE bit set. */
};

View File

@ -53,7 +53,7 @@ static char default_suffixes[]
static struct pspec default_pattern_rules[] =
{
{ "(%)", "%",
"$(AR) $(ARFLAGS) $@ $<" },
"$(AR) $(ARFLAGS) $@ $<" },
/* The X.out rules are only in BSD's default set because
BSD Make has no null-suffix rules, so `foo.out' and
@ -63,13 +63,13 @@ static struct pspec default_pattern_rules[] =
"copy $< $@" },
#else
{ "%.out", "%",
"@rm -f $@ \n cp $< $@" },
"@rm -f $@ \n cp $< $@" },
#endif
/* Syntax is "ctangle foo.w foo.ch foo.c". */
{ "%.c", "%.w %.ch",
"$(CTANGLE) $^ $@" },
"$(CTANGLE) $^ $@" },
{ "%.tex", "%.w %.ch",
"$(CWEAVE) $^ $@" },
"$(CWEAVE) $^ $@" },
{ 0, 0, 0 }
};
@ -88,21 +88,21 @@ static struct pspec default_terminal_rules[] =
"if f$$search($@) .nes. \"\" then +$(CHECKOUT,v)" },
/* SCCS. */
/* ain't no SCCS on vms */
/* ain't no SCCS on vms */
#else
/* RCS. */
{ "%", "%,v",
"$(CHECKOUT,v)" },
"$(CHECKOUT,v)" },
{ "%", "RCS/%,v",
"$(CHECKOUT,v)" },
"$(CHECKOUT,v)" },
{ "%", "RCS/%",
"$(CHECKOUT,v)" },
"$(CHECKOUT,v)" },
/* SCCS. */
{ "%", "s.%",
"$(GET) $(GFLAGS) $(SCCS_OUTPUT_OPTION) $<" },
"$(GET) $(GFLAGS) $(SCCS_OUTPUT_OPTION) $<" },
{ "%", "SCCS/s.%",
"$(GET) $(GFLAGS) $(SCCS_OUTPUT_OPTION) $<" },
"$(GET) $(GFLAGS) $(SCCS_OUTPUT_OPTION) $<" },
#endif /* !VMS */
{ 0, 0, 0 }
};
@ -293,13 +293,13 @@ static char *default_suffix_rules[] =
"$(TEXI2DVI) $(TEXI2DVI_FLAGS) $<",
".w.c",
"$(CTANGLE) $< - $@", /* The `-' says there is no `.ch' file. */
"$(CTANGLE) $< - $@", /* The `-' says there is no `.ch' file. */
".web.p",
"$(TANGLE) $<",
".w.tex",
"$(CWEAVE) $< - $@", /* The `-' says there is no `.ch' file. */
"$(CWEAVE) $< - $@", /* The `-' says there is no `.ch' file. */
".web.tex",
"$(WEAVE) $<",
@ -401,7 +401,7 @@ static const char *default_variables[] =
#ifdef GCC_IS_NATIVE
"CC", "gcc",
# ifdef __MSDOS__
"CXX", "gpp", /* g++ is an invalid name on MSDOS */
"CXX", "gpp", /* g++ is an invalid name on MSDOS */
# else
"CXX", "gcc",
# endif /* __MSDOS__ */
@ -419,17 +419,17 @@ static const char *default_variables[] =
"COFLAGS", "",
"CPP", "$(CC) -E",
#ifdef CRAY
#ifdef CRAY
"CF77PPFLAGS", "-P",
"CF77PP", "/lib/cpp",
"CFT", "cft77",
"CF", "cf77",
"FC", "$(CF)",
#else /* Not CRAY. */
#ifdef _IBMR2
#else /* Not CRAY. */
#ifdef _IBMR2
"FC", "xlf",
#else
#ifdef __convex__
#ifdef __convex__
"FC", "fc",
#else
"FC", "f77",
@ -439,7 +439,7 @@ static const char *default_variables[] =
However, there is no way to make implicit rules use them and FC. */
"F77", "$(FC)",
"F77FLAGS", "$(FFLAGS)",
#endif /* Cray. */
#endif /* Cray. */
"GET", SCCS_GET,
"LD", "ld",
#ifdef GCC_IS_NATIVE
@ -449,20 +449,20 @@ static const char *default_variables[] =
#endif
"LINT", "lint",
"M2C", "m2c",
#ifdef pyr
#ifdef pyr
"PC", "pascal",
#else
#ifdef CRAY
#ifdef CRAY
"PC", "PASCAL",
"SEGLDR", "segldr",
#else
"PC", "pc",
#endif /* CRAY. */
#endif /* pyr. */
#endif /* CRAY. */
#endif /* pyr. */
#ifdef GCC_IS_NATIVE
"YACC", "bison -y",
#else
"YACC", "yacc", /* Or "bison -y" */
"YACC", "yacc", /* Or "bison -y" */
#endif
"MAKEINFO", "makeinfo",
"TEX", "tex",
@ -508,11 +508,11 @@ static const char *default_variables[] =
"PREPROCESS.r", "$(FC) $(FFLAGS) $(RFLAGS) $(TARGET_ARCH) -F",
"LINT.c", "$(LINT) $(LINTFLAGS) $(CPPFLAGS) $(TARGET_ARCH)",
#ifndef NO_MINUS_C_MINUS_O
#ifndef NO_MINUS_C_MINUS_O
"OUTPUT_OPTION", "-o $@",
#endif
#ifdef SCCS_GET_MINUS_G
#ifdef SCCS_GET_MINUS_G
"SCCS_OUTPUT_OPTION", "-G$@",
#endif
@ -567,12 +567,13 @@ install_default_suffix_rules (void)
struct file *f = enter_file (strcache_add (s[0]));
/* Don't clobber cmds given in a makefile if there were any. */
if (f->cmds == 0)
{
f->cmds = xmalloc (sizeof (struct commands));
f->cmds->fileinfo.filenm = 0;
f->cmds->commands = s[1];
f->cmds->command_lines = 0;
}
{
f->cmds = xmalloc (sizeof (struct commands));
f->cmds->fileinfo.filenm = 0;
f->cmds->commands = s[1];
f->cmds->command_lines = 0;
f->cmds->recipe_prefix = RECIPEPREFIX_DEFAULT;
}
}
}

View File

@ -1633,7 +1633,7 @@ expands to @file{bar}, @code{$$^} expands to @file{bar boo},
Note that the directory prefix (D), as described in @ref{Implicit Rule
Search, ,Implicit Rule Search Algorithm}, is appended (after
expansion) to all the patterns in the prerequisites list. As an
example:
example:@refill
@example
.SECONDEXPANSION:
@ -1641,12 +1641,14 @@ example:
/tmp/foo.o:
%.o: $$(addsuffix /%.c,foo bar) foo.h
@@echo $^
@end example
The prerequisite list after the secondary expansion and directory
prefix reconstruction will be @file{/tmp/foo/foo.c /tmp/var/bar/foo.c
foo.h}. If you are not interested in this reconstruction, you can use
@code{$$*} instead of @code{%} in the prerequisites list.
The prerequisite list printed, after the secondary expansion and
directory prefix reconstruction, will be @file{/tmp/foo/foo.c
/tmp/bar/foo.c foo.h}. If you are not interested in this
reconstruction, you can use @code{$$*} instead of @code{%} in the
prerequisites list.
@node Rules, Recipes, Makefiles, Top
@chapter Writing Rules
@ -5422,11 +5424,12 @@ The variable name may contain function and variable references, which
are expanded when the line is read to find the actual variable name to use.
There is no limit on the length of the value of a variable except the
amount of swapping space on the computer. When a variable definition is
long, it is a good idea to break it into several lines by inserting
backslash-newline at convenient places in the definition. This will not
affect the functioning of @code{make}, but it will make the makefile easier
to read.
amount of memory on the computer. When a variable definition is long,
it is a good idea to break it into several lines by inserting
backslash-newline at convenient places in the definition. This will
make the makefile easier to read. Every backslash-newline, along with
any leading whitespace on the following line, will be replaced by a
single space in the value of the variable.
Most variable names are considered to have the empty string as a value if
you have never set them. Several variables have built-in initial values

13
file.c
View File

@ -920,6 +920,19 @@ print_file (const void *item)
const struct file *f = item;
putchar ('\n');
if (f->cmds && f->cmds->recipe_prefix != cmd_prefix)
{
fputs (".RECIPEPREFIX = ", stdout);
cmd_prefix = f->cmds->recipe_prefix;
if (cmd_prefix != RECIPEPREFIX_DEFAULT)
putchar (cmd_prefix);
putchar ('\n');
}
if (f->variables != 0)
print_target_variables (f);
if (!f->is_target)
puts (_("# Not a target:"));
printf ("%s:%s", f->name, f->double_colon ? ":" : "");

View File

@ -63,7 +63,6 @@ struct file
short int update_status; /* Status of the last attempt to update,
or -1 if none has been made. */
enum cmd_state /* State of the commands. */
{ /* Note: It is important that cs_not_started be zero. */
cs_not_started, /* Not yet started. */

32
job.c
View File

@ -1088,8 +1088,23 @@ start_job_command (struct child *child)
child->file->cmds->lines_flags[child->command_line - 1]
|= flags & COMMANDS_RECURSE;
/* Figure out an argument list from this command line. */
/* POSIX requires that a recipe prefix after a backslash-newline should
be ignored. Remove it now so the output is correct. */
{
char prefix = child->file->cmds->recipe_prefix;
char *p1, *p2;
p1 = p2 = p;
while (*p1 != '\0')
{
*(p2++) = *p1;
if (p1[0] == '\n' && p1[1] == prefix)
++p1;
++p1;
}
*p2 = *p1;
}
/* Figure out an argument list from this command line. */
{
char *end = 0;
#ifdef VMS
@ -1097,7 +1112,7 @@ start_job_command (struct child *child)
#else
argv = construct_command_argv (p, &end, child->file,
child->file->cmds->lines_flags[child->command_line - 1],
&child->sh_batch_file);
&child->sh_batch_file);
#endif
if (end == NULL)
child->command_ptr = NULL;
@ -2321,7 +2336,7 @@ void clean_tmp (void)
static char **
construct_command_argv_internal (char *line, char **restp, char *shell,
char *shellflags, char *ifs, int flags,
char **batch_filename_ptr)
char **batch_filename_p)
{
#ifdef __MSDOS__
/* MSDOS supports both the stock DOS shell and ports of Unixy shells.
@ -2567,10 +2582,9 @@ construct_command_argv_internal (char *line, char **restp, char *shell,
{
/* Backslash-newline is handled differently depending on what
kind of string we're in: inside single-quoted strings you
keep them; in double-quoted strings they disappear.
For DOS/Windows/OS2, if we don't have a POSIX shell,
we keep the pre-POSIX behavior of removing the
backslash-newline. */
keep them; in double-quoted strings they disappear. For
DOS/Windows/OS2, if we don't have a POSIX shell, we keep the
pre-POSIX behavior of removing the backslash-newline. */
if (instring == '"'
#if defined (__MSDOS__) || defined (__EMX__) || defined (WINDOWS32)
|| !unixy_shell
@ -3126,7 +3140,7 @@ construct_command_argv_internal (char *line, char **restp, char *shell,
char **
construct_command_argv (char *line, char **restp, struct file *file,
int cmd_flags, char **batch_filename_ptr)
int cmd_flags, char **batch_filename_p)
{
char *shell, *ifs, *shellflags;
char **argv;
@ -3240,7 +3254,7 @@ construct_command_argv (char *line, char **restp, struct file *file,
}
argv = construct_command_argv_internal (line, restp, shell, shellflags, ifs,
cmd_flags, batch_filename_ptr);
cmd_flags, batch_filename_p);
free (shell);
free (shellflags);

4
make.h
View File

@ -148,6 +148,10 @@ unsigned int get_path_max (void);
# define CHAR_BIT 8
#endif
#ifndef USHRT_MAX
# define USHRT_MAX 65535
#endif
/* Nonzero if the integer type T is signed. */
#define INTEGER_TYPE_SIGNED(t) ((t) -1 < 0)

3
misc.c
View File

@ -118,9 +118,6 @@ collapse_continuations (char *line)
if (backslash)
{
in = next_token (in);
/* Removing this loop will fix Savannah bug #16670: do we want to? */
while (out > line && isblank ((unsigned char)out[-1]))
--out;
*out++ = ' ';
}
else

36
read.c
View File

@ -146,7 +146,7 @@ static void record_files (struct nameseq *filenames, const char *pattern,
const char *pattern_percent, char *depstr,
unsigned int cmds_started, char *commands,
unsigned int commands_idx, int two_colon,
const struct floc *flocp);
char prefix, const struct floc *flocp);
static void record_target_var (struct nameseq *filenames, char *defn,
enum variable_origin origin,
struct vmodifiers *vmod,
@ -559,6 +559,7 @@ eval (struct ebuffer *ebuf, int set_default)
char *depstr = 0;
long nlines = 0;
int two_colon = 0;
char prefix;
const char *pattern = 0;
const char *pattern_percent;
struct floc *fstart;
@ -572,7 +573,7 @@ eval (struct ebuffer *ebuf, int set_default)
fi.lineno = tgts_started; \
record_files (filenames, pattern, pattern_percent, depstr, \
cmds_started, commands, commands_idx, two_colon, \
&fi); \
prefix, &fi); \
filenames = 0; \
} \
commands_idx = 0; \
@ -624,7 +625,7 @@ eval (struct ebuffer *ebuf, int set_default)
linelen = strlen (line);
/* Check for a shell command line first.
If it is not one, we can stop treating tab specially. */
If it is not one, we can stop treating cmd_prefix specially. */
if (line[0] == cmd_prefix)
{
if (no_targets)
@ -641,32 +642,19 @@ eval (struct ebuffer *ebuf, int set_default)
/* Yep, this is a shell command, and we don't care. */
continue;
/* Append this command line to the line being accumulated.
Strip command prefix chars that appear after newlines. */
if (commands_idx == 0)
cmds_started = ebuf->floc.lineno;
/* Append this command line to the line being accumulated.
Skip the initial command prefix character. */
if (linelen + commands_idx > commands_len)
{
commands_len = (linelen + commands_idx) * 2;
commands = xrealloc (commands, commands_len);
}
p = &commands[commands_idx];
p2 = line + 1;
while (--linelen)
{
++commands_idx;
*(p++) = *p2;
if (p2[0] == '\n' && p2[1] == cmd_prefix)
{
++p2;
--linelen;
}
++p2;
}
*p = '\n';
++commands_idx;
memcpy (&commands[commands_idx], line + 1, linelen - 1);
commands_idx += linelen - 1;
commands[commands_idx++] = '\n';
continue;
}
}
@ -1089,6 +1077,9 @@ eval (struct ebuffer *ebuf, int set_default)
Unquote any = in the dependency list. */
find_char_unquote (lb_next, '=', 0, 0, 0);
/* Remember the command prefix for this target. */
prefix = cmd_prefix;
/* We have some targets, so don't ignore the following commands. */
no_targets = 0;
@ -1840,7 +1831,7 @@ record_files (struct nameseq *filenames, const char *pattern,
const char *pattern_percent, char *depstr,
unsigned int cmds_started, char *commands,
unsigned int commands_idx, int two_colon,
const struct floc *flocp)
char prefix, const struct floc *flocp)
{
struct commands *cmds;
struct dep *deps;
@ -1866,6 +1857,7 @@ record_files (struct nameseq *filenames, const char *pattern,
cmds->fileinfo.lineno = cmds_started;
cmds->commands = xstrndup (commands, commands_idx);
cmds->command_lines = 0;
cmds->recipe_prefix = prefix;
}
else
cmds = 0;

1
rule.c
View File

@ -389,6 +389,7 @@ install_pattern_rule (struct pspec *p, int terminal)
anyway because somebody might want to free them later. */
r->cmds->commands = xstrdup (p->commands);
r->cmds->command_lines = 0;
r->cmds->recipe_prefix = RECIPEPREFIX_DEFAULT;
}
}

View File

@ -1,3 +1,11 @@
2010-11-06 Paul Smith <psmith@gnu.org>
* scripts/features/targetvars: Fix known-good output for BS/NL changes.
* scripts/functions/call: Ditto.
* scripts/variables/special: Ditto.
* scripts/misc/bs-nl: New test suite for backslash/newline testing.
2010-08-29 Paul Smith <psmith@gnu.org>
* scripts/features/errors: Add new error message to output text.

View File

@ -240,7 +240,7 @@ run_make_test(undef, 'FOO=C', "C f1\n");
# TEST #20: Check for continuation after semicolons
run_make_test(q!
a: A = 'hello; \
a: A = 'hello;\
world'
a: ; @echo $(A)
!,

View File

@ -38,7 +38,7 @@ two = $(call one,$(1),foo,$(2))
DEP_foo = bar baz quux
DEP_baz = quux blarp
rest = $(wordlist 2,$(words ${1}),${1})
tclose = $(if $1,$(firstword $1) \
tclose = $(if $1,$(firstword $1)\
$(call tclose,$(sort ${DEP_$(firstword $1)} $(call rest,$1))))
all: ; @echo '$(call reverse,bar,foo)'; \

76
tests/scripts/misc/bs-nl Normal file
View File

@ -0,0 +1,76 @@
# -*-perl-*-
$description = "Test backslash-newline handling.";
$details = "";
# TEST #1
# -------
# Backslash-newlines in recipes
# These are basic backslash-newlines with no tricks
run_make_test("fast:;\@echo fa\\\nst\n",
'', 'fast');
run_make_test("slow:;\@: no-op; echo sl\\\now\n",
'', 'slow');
run_make_test("dquote:;\@echo \"dqu\\\note\"\n",
'', 'dquote');
run_make_test("squote:;\@echo 'squ\\\note'\n",
'', "squ\\\note");
# Ensure that a leading prefix character is omitted
run_make_test("fast:;\@echo fa\\\n\tst\n",
'', 'fast');
run_make_test("slow:;\@: no-op; echo sl\\\n\tow\n",
'', 'slow');
run_make_test("dquote:;\@echo \"dqu\\\n\tote\"\n",
'', 'dquote');
run_make_test("squote:;\@echo 'squ\\\n\tote'\n",
'', "squ\\\note");
# Ensure that ONLY the leading prefix character is omitted
run_make_test("fast:;\@echo fa\\\n\t st\n",
'', 'fa st');
run_make_test("slow:;\@: no-op; echo sl\\\n\t\tow\n",
'', "sl ow");
run_make_test("dquote:;\@echo \"dqu\\\n\t ote\"\n",
'', 'dqu ote');
run_make_test("squote:;\@echo 'squ\\\n\t\t ote'\n",
'', "squ\\\n\t ote");
# Backslash-newlines in variable values
# Simple
run_make_test("
var = he\\\nllo
var:;\@echo '|\$(var)|'",
'', "|he llo|");
# Preserve preceding space
run_make_test("
var = he \\\nllo
var:;\@echo '|\$(var)|'",
'', "|he llo|");
# Remove leading space
run_make_test("
var = he\\\n llo
var:;\@echo '|\$(var)|'",
'', "|he llo|");
# One space per bs-nl
run_make_test("
var = he\\\n\\\n\\\n llo
var:;\@echo '|\$(var)|'",
'', "|he llo|");
1;

View File

@ -53,7 +53,7 @@ all:
# Test the .RECIPEPREFIX variable
&run_make_test('
define foo
: foo-one \
: foo-one\
foo-two
: foo-three
: foo-four

View File

@ -1553,6 +1553,9 @@ print_variable (const void *item, void *arg)
switch (v->origin)
{
case o_automatic:
origin = _("automatic");
break;
case o_default:
origin = _("default");
break;
@ -1571,9 +1574,6 @@ print_variable (const void *item, void *arg)
case o_override:
origin = _("`override' directive");
break;
case o_automatic:
origin = _("automatic");
break;
case o_invalid:
default:
abort ();
@ -1617,13 +1617,34 @@ print_variable (const void *item, void *arg)
}
static void
print_auto_variable (const void *item, void *arg)
{
const struct variable *v = item;
if (v->origin == o_automatic)
print_variable (item, arg);
}
static void
print_noauto_variable (const void *item, void *arg)
{
const struct variable *v = item;
if (v->origin != o_automatic)
print_variable (item, arg);
}
/* Print all the variables in SET. PREFIX is printed before
the actual variable definitions (everything else is comments). */
void
print_variable_set (struct variable_set *set, char *prefix)
print_variable_set (struct variable_set *set, char *prefix, int pauto)
{
hash_map_arg (&set->table, print_variable, prefix);
hash_map_arg (&set->table, (pauto ? print_auto_variable : print_variable),
prefix);
fputs (_("# variable set hash-table stats:\n"), stdout);
fputs ("# ", stdout);
@ -1638,7 +1659,7 @@ print_variable_data_base (void)
{
puts (_("\n# Variables\n"));
print_variable_set (&global_variable_set, "");
print_variable_set (&global_variable_set, "", 0);
puts (_("\n# Pattern-specific Variable Values"));
@ -1667,7 +1688,24 @@ void
print_file_variables (const struct file *file)
{
if (file->variables != 0)
print_variable_set (file->variables->set, "# ");
print_variable_set (file->variables->set, "# ", 1);
}
void
print_target_variables (const struct file *file)
{
if (file->variables != 0)
{
int l = strlen (file->name);
char *t = alloca (l + 3);
strcpy (t, file->name);
t[l] = ':';
t[l+1] = ' ';
t[l+2] = '\0';
hash_map_arg (&file->variables->set->table, print_noauto_variable, t);
}
}
#ifdef WINDOWS32

View File

@ -147,7 +147,8 @@ void pop_variable_scope (void);
void define_automatic_variables (void);
void initialize_file_variables (struct file *file, int reading);
void print_file_variables (const struct file *file);
void print_variable_set (struct variable_set *set, char *prefix);
void print_file_variables (const struct file *file);
void print_target_variables (const struct file *file);
void merge_variable_set_lists (struct variable_set_list **to_list,
struct variable_set_list *from_list);
struct variable *do_variable_definition (const struct floc *flocp,