]> git.ipfire.org Git - thirdparty/make.git/commitdiff
Improve backslash/newline handling to adhere to POSIX requirements.
authorPaul Smith <psmith@gnu.org>
Sat, 6 Nov 2010 21:56:23 +0000 (21:56 +0000)
committerPaul Smith <psmith@gnu.org>
Sat, 6 Nov 2010 21:56:23 +0000 (21:56 +0000)
20 files changed:
ChangeLog
NEWS
commands.c
commands.h
default.c
doc/make.texi
file.c
filedef.h
job.c
make.h
misc.c
read.c
rule.c
tests/ChangeLog
tests/scripts/features/targetvars
tests/scripts/functions/call
tests/scripts/misc/bs-nl [new file with mode: 0644]
tests/scripts/variables/special
variable.c
variable.h

index 0766522631c55e72fabfb962754833324581b3c2..fdcb106fa6e0da91bbd405303b943c775bf35465 100644 (file)
--- a/ChangeLog
+++ b/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.
diff --git a/NEWS b/NEWS
index 36bae59d874e9806682b5ddfc6b458988088c67e..a421375356030641fbaf85d4d71c7177532cced6 100644 (file)
--- a/NEWS
+++ b/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.
+
 \f
 Version 3.82
 
index f360bd40c5d4f693f117e7ea88d18ad0ef3576e5..ba3840ecf074515d9210d4297c3494f9d9b8d2d9 100644 (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;
     }
 }
 \f
@@ -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);
 
index 24426fa7611e11bed2a05d69b3cfc1f3a0c6e52f..643347d138c887391d5eac6ee4b61fa7ee0c89e8 100644 (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.  */
   };
 
index 4d6d984ba0850c1ca80c755c1f6bce0e7702f50b..46e023e61a6843ef60dea4fe61779a3f0d1312b1 100644 (file)
--- a/default.c
+++ b/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;
+        }
     }
 }
 
index 6f59f86c9db46b119a9ea497f10e630f041208a9..4d089aaa29935960d73a6594fe573d30acc30182 100644 (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
diff --git a/file.c b/file.c
index 0a4edb2559b961f1da029f0622f67eb89f9b2bfe..93212d1cd849508ad01ac53e4f1c9e43b7e81e47 100644 (file)
--- a/file.c
+++ b/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 ? ":" : "");
index 0a621b9bc210f1f5729500c0b97e464fa42b7aaa..98e3f49f6f740f219f5462fcac762334023b4e7b 100644 (file)
--- a/filedef.h
+++ b/filedef.h
@@ -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.  */
diff --git a/job.c b/job.c
index f4e6fa463b9ad32f2d5926664948f4cbf6712228..67b402d7257255f1d9d64a491c851245e62636d6 100644 (file)
--- a/job.c
+++ b/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);
diff --git a/make.h b/make.h
index e563da479e7258d72902ccf1c37dceae3431db5e..ea282df63dd3cdbfbd962f441508026914edd3ef 100644 (file)
--- a/make.h
+++ b/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)
 
diff --git a/misc.c b/misc.c
index 7a6f7731da9a15a72d522a8f0c14d3e8da0e30b8..607e2a7e228ff348b89d2e3fcca8f96381751785 100644 (file)
--- a/misc.c
+++ b/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
diff --git a/read.c b/read.c
index 9dfd4ea04c4805067c34b95feb41b51f9ebd03ff..7b5b0dd0a7b63aacbbdde7a794afe16bab3f6c60 100644 (file)
--- a/read.c
+++ b/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;
diff --git a/rule.c b/rule.c
index a966cc9949ea5554c0fa133c78f5dc81dc176485..3ad38ebef6db5af768c362c2d9c3b4a3de561d1c 100644 (file)
--- a/rule.c
+++ b/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;
     }
 }
 
index 527ecd80adb4dec9d09d9b17ce63c0122f243cab..b13e2ae22aa19e374e1e64a93d46f4e61cf42c4b 100644 (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.
index ddd6c1f5379f235e290820d1338a1879bff62f1f..6afd48aaa4e95eabb15343ca57d53421037476ba 100644 (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)
 !,
index f3c5470851c6eeaff930b5c8affc9bc6788d4071..6dd48b13eceadd2701780da413c4380ae25e5a0d 100644 (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)'; \
diff --git a/tests/scripts/misc/bs-nl b/tests/scripts/misc/bs-nl
new file mode 100644 (file)
index 0000000..979abb5
--- /dev/null
@@ -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;
index a1e15c22cb6ccda4d0009f151130341704d8cf3b..4637b2a25a4f02866554f709fda3558a256fc6fb 100644 (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
index 0d85546c6746e5c28cf0bf5fa661104586d3da28..b69908878508f768009a5b3921a7c9cec1bf6e7a 100644 (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
index c2158672eee38dee85395dbe57dea03470590668..04ca0740e37d146b26518c89f608d99b8c6bf1d3 100644 (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,