summaryrefslogtreecommitdiff
path: root/packages/patch/patch-2.5.9/unified-reject-files.diff
blob: 6bfa00dd75a90cd90b4d482acc77db14b706974b (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
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];