diff options
author | Paul Smith <psmith@gnu.org> | 2010-11-06 21:56:23 +0000 |
---|---|---|
committer | Paul Smith <psmith@gnu.org> | 2010-11-06 21:56:23 +0000 |
commit | 391456aad790172c3cbbceb5544dd785c0e60a99 (patch) | |
tree | faf87797baba5fae47c98029e5d2c1ec741fb7d1 | |
parent | a86d1693bac05e04f90a2ee3c4fa3547c788377c (diff) | |
download | gunmake-391456aad790172c3cbbceb5544dd785c0e60a99.tar.gz |
Improve backslash/newline handling to adhere to POSIX requirements.
-rw-r--r-- | ChangeLog | 34 | ||||
-rw-r--r-- | NEWS | 13 | ||||
-rw-r--r-- | commands.c | 17 | ||||
-rw-r--r-- | commands.h | 5 | ||||
-rw-r--r-- | default.c | 63 | ||||
-rw-r--r-- | doc/make.texi | 23 | ||||
-rw-r--r-- | file.c | 13 | ||||
-rw-r--r-- | filedef.h | 1 | ||||
-rw-r--r-- | job.c | 32 | ||||
-rw-r--r-- | make.h | 4 | ||||
-rw-r--r-- | misc.c | 3 | ||||
-rw-r--r-- | read.c | 36 | ||||
-rw-r--r-- | rule.c | 1 | ||||
-rw-r--r-- | tests/ChangeLog | 8 | ||||
-rw-r--r-- | tests/scripts/features/targetvars | 2 | ||||
-rw-r--r-- | tests/scripts/functions/call | 2 | ||||
-rw-r--r-- | tests/scripts/misc/bs-nl | 76 | ||||
-rw-r--r-- | tests/scripts/variables/special | 2 | ||||
-rw-r--r-- | variable.c | 52 | ||||
-rw-r--r-- | variable.h | 3 |
20 files changed, 297 insertions, 93 deletions
@@ -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. @@ -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 @@ -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. */ }; @@ -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; + } } } diff --git a/doc/make.texi b/doc/make.texi index 6f59f86..4d089aa 100644 --- a/doc/make.texi +++ b/doc/make.texi @@ -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 @@ -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. */ @@ -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); @@ -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) @@ -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 @@ -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; @@ -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; } } diff --git a/tests/ChangeLog b/tests/ChangeLog index 527ecd8..b13e2ae 100644 --- a/tests/ChangeLog +++ b/tests/ChangeLog @@ -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. diff --git a/tests/scripts/features/targetvars b/tests/scripts/features/targetvars index ddd6c1f..6afd48a 100644 --- a/tests/scripts/features/targetvars +++ b/tests/scripts/features/targetvars @@ -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) !, diff --git a/tests/scripts/functions/call b/tests/scripts/functions/call index f3c5470..6dd48b1 100644 --- a/tests/scripts/functions/call +++ b/tests/scripts/functions/call @@ -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)'; \ diff --git a/tests/scripts/misc/bs-nl b/tests/scripts/misc/bs-nl new file mode 100644 index 0000000..979abb5 --- /dev/null +++ b/tests/scripts/misc/bs-nl @@ -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; diff --git a/tests/scripts/variables/special b/tests/scripts/variables/special index a1e15c2..4637b2a 100644 --- a/tests/scripts/variables/special +++ b/tests/scripts/variables/special @@ -53,7 +53,7 @@ all: # Test the .RECIPEPREFIX variable &run_make_test(' define foo -: foo-one \ +: foo-one\ foo-two : foo-three : foo-four @@ -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, |