Upstream-Status: Inappropriate [debian patch]

Generate unified diff style reject files. Also include the C function names
in reject files whenever possible.

	$ cat > f.orig
	< a() {
	< 2
	< 3
	<
	< 5
	< 6
	< }

	$ sed -e 's/5/5a/' f.orig > f
	$ diff -U2 -p f.orig f > f.diff
	$ sed -e 's/5/5a/' -e 's/6/6x/' f.orig > f
	$ ./patch -F0 -s --no-backup-if-mismatch f --reject-unified < f.diff
	> 1 out of 1 hunk FAILED -- saving rejects to file f.rej

	$ cat f.rej
	> @@ -3,5 +3,5 @@ a() {
	>  3
	>  
	> -5
	> +5a
	>  6
	>  }

	$ ./patch -F0 -s --no-backup-if-mismatch f < f.diff
	> 1 out of 1 hunk FAILED -- saving rejects to file f.rej

	$ cat f.rej
	> *************** a() {
	> *** 3,7 ****
	>   3
	>   
	> - 5
	>   6
	>   }
	> --- 3,7 ----
	>   3
	>   
	> + 5a
	>   6
	>   }

	$ diff -Nu -p /dev/null f.orig > f2.diff
	$ ./patch -F0 -s --no-backup-if-mismatch f --reject-unified < f2.diff
	> Patch attempted to create file f, which already exists.
	> 1 out of 1 hunk FAILED -- saving rejects to file f.rej

	$ cat f.rej
	> @@ -0,0 +1,7 @@
	> +a() {
	> +2
	> +3
	> +
	> +5
	> +6
	> +}

	$ rm -f f f.orig f.rej f.diff f2.diff

Index: patch-2.5.9/pch.c
===================================================================
--- patch-2.5.9.orig/pch.c
+++ patch-2.5.9/pch.c
@@ -68,6 +68,7 @@ static LINENUM p_sline;			/* and the lin
 static LINENUM p_hunk_beg;		/* line number of current hunk */
 static LINENUM p_efake = -1;		/* end of faked up lines--don't free */
 static LINENUM p_bfake = -1;		/* beg of faked up lines */
+static char *p_c_function;		/* the C function a hunk is in */
 
 enum nametype { OLD, NEW, INDEX, NONE };
 
@@ -888,6 +889,19 @@ another_hunk (enum diff difftype, bool r
 	    next_intuit_at(line_beginning,p_input_line);
 	    return chars_read == (size_t) -1 ? -1 : 0;
 	}
+	s = buf;
+	while (*s == '*')
+	    s++;
+	if (*s == ' ')
+	  {
+	    p_c_function = s;
+	    while (*s != '\n')
+		s++;
+	    *s = '\0';
+	    p_c_function = savestr (p_c_function);
+	  }
+	else
+	    p_c_function = NULL;
 	p_hunk_beg = p_input_line + 1;
 	while (p_end < p_max) {
 	    chars_read = get_line ();
@@ -1277,8 +1291,18 @@ another_hunk (enum diff difftype, bool r
 	else
 	    p_repl_lines = 1;
 	if (*s == ' ') s++;
-	if (*s != '@')
+	if (*s++ != '@')
 	    malformed ();
+	if (*s++ == '@' && *s == ' ' && *s != '\0')
+	  {
+	    p_c_function = s;
+	    while (*s != '\n')
+		s++;
+	    *s = '\0';
+	    p_c_function = savestr (p_c_function);
+	  }
+	else
+	    p_c_function = NULL;
 	if (!p_ptrn_lines)
 	    p_first++;			/* do append rather than insert */
 	if (!p_repl_lines)
@@ -1884,6 +1908,12 @@ pch_hunk_beg (void)
     return p_hunk_beg;
 }
 
+char const *
+pch_c_function (void)
+{
+    return p_c_function;
+}
+
 /* Is the newline-terminated line a valid `ed' command for patch
    input?  If so, return the command character; if not, return 0.
    This accepts accepts just a subset of the valid commands, but it's
Index: patch-2.5.9/pch.h
===================================================================
--- patch-2.5.9.orig/pch.h
+++ patch-2.5.9/pch.h
@@ -25,6 +25,7 @@
 LINENUM pch_end (void);
 LINENUM pch_first (void);
 LINENUM pch_hunk_beg (void);
+char const *pch_c_function (void);
 LINENUM pch_newfirst (void);
 LINENUM pch_prefix_context (void);
 LINENUM pch_ptrn_lines (void);
Index: patch-2.5.9/patch.man
===================================================================
--- patch-2.5.9.orig/patch.man
+++ patch-2.5.9/patch.man
@@ -517,6 +517,9 @@ instead of the default
 .B \&.rej
 file.
 .TP
+\fB\*=reject\-unified\fP
+Produce unified reject files. The default is to produce context type reject files.
+.TP
 \fB\-R\fP  or  \fB\*=reverse\fP
 Assume that this patch was created with the old and new files swapped.
 (Yes, I'm afraid that does happen occasionally, human nature being what it
Index: patch-2.5.9/common.h
===================================================================
--- patch-2.5.9.orig/common.h
+++ patch-2.5.9/common.h
@@ -146,6 +146,7 @@ XTERN int invc;
 XTERN struct stat instat;
 XTERN bool dry_run;
 XTERN bool posixly_correct;
+XTERN bool unified_reject_files;
 
 XTERN char const *origprae;
 XTERN char const *origbase;
Index: patch-2.5.9/patch.c
===================================================================
--- patch-2.5.9.orig/patch.c
+++ patch-2.5.9/patch.c
@@ -522,6 +522,7 @@ static struct option const longopts[] =
   {"no-backup-if-mismatch", no_argument, NULL, CHAR_MAX + 6},
   {"posix", no_argument, NULL, CHAR_MAX + 7},
   {"quoting-style", required_argument, NULL, CHAR_MAX + 8},
+  {"unified-reject-files", no_argument, NULL, CHAR_MAX + 9},
   {NULL, no_argument, NULL, 0}
 };
 
@@ -580,6 +581,7 @@ static char const *const option_help[] =
 "  --verbose  Output extra information about the work being done.",
 "  --dry-run  Do not actually change any files; just print what would happen.",
 "  --posix  Conform to the POSIX standard.",
+"  --unified-reject-files  Create unified reject files.",
 "",
 "  -d DIR  --directory=DIR  Change the working directory to DIR first.",
 #if HAVE_SETMODE_DOS
@@ -779,6 +781,9 @@ get_some_switches (void)
 				     (enum quoting_style) i);
 		}
 		break;
+	    case CHAR_MAX + 9:
+		unified_reject_files = true;
+		break;
 	    default:
 		usage (stderr, 2);
 	}
@@ -927,6 +932,24 @@ locate_hunk (LINENUM fuzz)
     return 0;
 }
 
+static char *
+format_linerange (char rangebuf[LINENUM_LENGTH_BOUND*2 + 2],
+		  LINENUM first, LINENUM lines)
+{
+    if (lines == 1)
+      rangebuf = format_linenum (rangebuf, first);
+    else
+      {
+	char *rb;
+	rangebuf = format_linenum (rangebuf + LINENUM_LENGTH_BOUND + 1, lines);
+	rb = rangebuf-1;
+	rangebuf = format_linenum (rangebuf - LINENUM_LENGTH_BOUND - 1,
+				   (lines > 0) ? first : 0);
+	*rb = ',';
+      }
+    return rangebuf;
+}
+
 /* We did not find the pattern, dump out the hunk so they can handle it. */
 
 static void
@@ -943,8 +966,83 @@ abort_hunk (void)
       (int) NEW_CONTEXT_DIFF <= (int) diff_type ? " ****" : "";
     char const *minuses =
       (int) NEW_CONTEXT_DIFF <= (int) diff_type ? " ----" : " -----";
+    char const *function = pch_c_function();
+    if (function == NULL)
+	function = "";
+
+    if (unified_reject_files)
+      {
+	/* produce unified reject files */
+	char rangebuf0[LINENUM_LENGTH_BOUND*2 + 2];
+	char rangebuf1[LINENUM_LENGTH_BOUND*2 + 2];
+	LINENUM j;
+
+	/* Find the beginning of the remove and insert section. */
+	for (j = 0; j <= pat_end; j++)
+	  if (pch_char (j) == '=')
+	    break;
+	for (i = j+1; i <= pat_end; i++)
+	  if (pch_char (i) == '^')
+	    break;
+	if (pch_char (0) != '*' || j > pat_end || i > pat_end+1)
+	  fatal ("internal error in abort_hunk");
+	i = 1; j++;
+
+	/* @@ -from,lines +to,lines @@ */
+	fprintf (rejfp, "@@ -%s +%s @@%s\n",
+		 format_linerange (rangebuf0, oldfirst, pch_ptrn_lines()),
+		 format_linerange (rangebuf1, newfirst, pch_repl_lines()),
+		 function);
+
+	while (   (i <= pat_end && pch_char (i) != '=')
+	       || (j <= pat_end && pch_char (j) != '^'))
+	  {
+	    if (i <= pat_end
+		&& (pch_char (i) == '-' || pch_char (i) == '!'))
+	      {
+		fputc('-', rejfp);
+		pch_write_line (i++, rejfp);
+	      }
+	    else if (j <= pat_end
+		     && (pch_char (j) == '+' || pch_char (j) == '!'))
+	      {
+		fputc('+', rejfp);
+		pch_write_line (j++, rejfp);
+	      }
+	    else if ((i <= pat_end
+		      && (pch_char (i) == ' ' || pch_char (i) == '\n')) &&
+		     (j > pat_end
+		      || (pch_char (j) == ' ' || pch_char (j) == '\n')))
+	      {
+		/* Unless j is already past the end, lines i and j
+		   must be equal here.  */
+
+		if (pch_char (i) == ' ')
+		  fputc(' ', rejfp);
+		pch_write_line (i++, rejfp);
+		if (j <= pat_end)
+		  j++;
+	      }
+	    else if ((j <= pat_end &&
+		     (pch_char (j) == ' ' || pch_char (j) == '\n')) &&
+		     (pch_char (i) == '='))
+	      {
+		if (pch_char (j) == ' ')
+		  fputc(' ', rejfp);
+		pch_write_line (j++, rejfp);
+	      }
+	    else
+	      fatal ("internal error in abort_hunk");
+	  }
+
+	if (ferror (rejfp))
+	  write_fatal ();
+	return;
+      }
 
-    fprintf(rejfp, "***************\n");
+    /* produce context type reject files */
+   
+    fprintf(rejfp, "***************%s\n", function);
     for (i=0; i<=pat_end; i++) {
 	char numbuf0[LINENUM_LENGTH_BOUND + 1];
 	char numbuf1[LINENUM_LENGTH_BOUND + 1];
