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:
parent
a86d1693ba
commit
391456aad7
34
ChangeLog
34
ChangeLog
@ -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
13
NEWS
@ -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
|
||||
|
||||
|
17
commands.c
17
commands.c
@ -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);
|
||||
|
||||
|
@ -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. */
|
||||
};
|
||||
|
||||
|
63
default.c
63
default.c
@ -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;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -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
13
file.c
@ -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 ? ":" : "");
|
||||
|
@ -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
32
job.c
@ -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
4
make.h
@ -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
3
misc.c
@ -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
36
read.c
@ -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
1
rule.c
@ -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;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -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.
|
||||
|
@ -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)
|
||||
!,
|
||||
|
@ -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
76
tests/scripts/misc/bs-nl
Normal 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;
|
@ -53,7 +53,7 @@ all:
|
||||
# Test the .RECIPEPREFIX variable
|
||||
&run_make_test('
|
||||
define foo
|
||||
: foo-one \
|
||||
: foo-one\
|
||||
foo-two
|
||||
: foo-three
|
||||
: foo-four
|
||||
|
52
variable.c
52
variable.c
@ -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
|
||||
|
@ -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,
|
||||
|
Loading…
Reference in New Issue
Block a user