1*86d7f5d3SJohn Marino /* Context-format output routines for GNU DIFF.
2*86d7f5d3SJohn Marino Copyright (C) 1988,1989,1991,1992,1993,1994,1998 Free Software Foundation, Inc.
3*86d7f5d3SJohn Marino
4*86d7f5d3SJohn Marino This file is part of GNU DIFF.
5*86d7f5d3SJohn Marino
6*86d7f5d3SJohn Marino GNU DIFF is free software; you can redistribute it and/or modify
7*86d7f5d3SJohn Marino it under the terms of the GNU General Public License as published by
8*86d7f5d3SJohn Marino the Free Software Foundation; either version 2, or (at your option)
9*86d7f5d3SJohn Marino any later version.
10*86d7f5d3SJohn Marino
11*86d7f5d3SJohn Marino GNU DIFF is distributed in the hope that it will be useful,
12*86d7f5d3SJohn Marino but WITHOUT ANY WARRANTY; without even the implied warranty of
13*86d7f5d3SJohn Marino MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14*86d7f5d3SJohn Marino GNU General Public License for more details.
15*86d7f5d3SJohn Marino
16*86d7f5d3SJohn Marino */
17*86d7f5d3SJohn Marino
18*86d7f5d3SJohn Marino #include "diff.h"
19*86d7f5d3SJohn Marino
20*86d7f5d3SJohn Marino static struct change *find_hunk PARAMS((struct change *));
21*86d7f5d3SJohn Marino static void find_function PARAMS((struct file_data const *, int, char const **, size_t *));
22*86d7f5d3SJohn Marino static void mark_ignorable PARAMS((struct change *));
23*86d7f5d3SJohn Marino static void pr_context_hunk PARAMS((struct change *));
24*86d7f5d3SJohn Marino static void pr_unidiff_hunk PARAMS((struct change *));
25*86d7f5d3SJohn Marino static void print_context_label PARAMS ((char const *, struct file_data *, char const *));
26*86d7f5d3SJohn Marino static void print_context_number_range PARAMS((struct file_data const *, int, int));
27*86d7f5d3SJohn Marino static void print_unidiff_number_range PARAMS((struct file_data const *, int, int));
28*86d7f5d3SJohn Marino
29*86d7f5d3SJohn Marino /* Last place find_function started searching from. */
30*86d7f5d3SJohn Marino static int find_function_last_search;
31*86d7f5d3SJohn Marino
32*86d7f5d3SJohn Marino /* The value find_function returned when it started searching there. */
33*86d7f5d3SJohn Marino static int find_function_last_match;
34*86d7f5d3SJohn Marino
35*86d7f5d3SJohn Marino /* Print a label for a context diff, with a file name and date or a label. */
36*86d7f5d3SJohn Marino
37*86d7f5d3SJohn Marino static void
print_context_label(mark,inf,label)38*86d7f5d3SJohn Marino print_context_label (mark, inf, label)
39*86d7f5d3SJohn Marino char const *mark;
40*86d7f5d3SJohn Marino struct file_data *inf;
41*86d7f5d3SJohn Marino char const *label;
42*86d7f5d3SJohn Marino {
43*86d7f5d3SJohn Marino if (label)
44*86d7f5d3SJohn Marino printf_output ("%s %s\n", mark, label);
45*86d7f5d3SJohn Marino else
46*86d7f5d3SJohn Marino {
47*86d7f5d3SJohn Marino char const *ct = ctime (&inf->stat.st_mtime);
48*86d7f5d3SJohn Marino if (!ct)
49*86d7f5d3SJohn Marino ct = "?\n";
50*86d7f5d3SJohn Marino /* See Posix.2 section 4.17.6.1.4 for this format. */
51*86d7f5d3SJohn Marino printf_output ("%s %s\t%s", mark, inf->name, ct);
52*86d7f5d3SJohn Marino }
53*86d7f5d3SJohn Marino }
54*86d7f5d3SJohn Marino
55*86d7f5d3SJohn Marino /* Print a header for a context diff, with the file names and dates. */
56*86d7f5d3SJohn Marino
57*86d7f5d3SJohn Marino void
print_context_header(inf,unidiff_flag)58*86d7f5d3SJohn Marino print_context_header (inf, unidiff_flag)
59*86d7f5d3SJohn Marino struct file_data inf[];
60*86d7f5d3SJohn Marino int unidiff_flag;
61*86d7f5d3SJohn Marino {
62*86d7f5d3SJohn Marino if (unidiff_flag)
63*86d7f5d3SJohn Marino {
64*86d7f5d3SJohn Marino print_context_label ("---", &inf[0], file_label[0]);
65*86d7f5d3SJohn Marino print_context_label ("+++", &inf[1], file_label[1]);
66*86d7f5d3SJohn Marino }
67*86d7f5d3SJohn Marino else
68*86d7f5d3SJohn Marino {
69*86d7f5d3SJohn Marino print_context_label ("***", &inf[0], file_label[0]);
70*86d7f5d3SJohn Marino print_context_label ("---", &inf[1], file_label[1]);
71*86d7f5d3SJohn Marino }
72*86d7f5d3SJohn Marino }
73*86d7f5d3SJohn Marino
74*86d7f5d3SJohn Marino /* Print an edit script in context format. */
75*86d7f5d3SJohn Marino
76*86d7f5d3SJohn Marino void
print_context_script(script,unidiff_flag)77*86d7f5d3SJohn Marino print_context_script (script, unidiff_flag)
78*86d7f5d3SJohn Marino struct change *script;
79*86d7f5d3SJohn Marino int unidiff_flag;
80*86d7f5d3SJohn Marino {
81*86d7f5d3SJohn Marino if (ignore_blank_lines_flag || ignore_regexp_list)
82*86d7f5d3SJohn Marino mark_ignorable (script);
83*86d7f5d3SJohn Marino else
84*86d7f5d3SJohn Marino {
85*86d7f5d3SJohn Marino struct change *e;
86*86d7f5d3SJohn Marino for (e = script; e; e = e->link)
87*86d7f5d3SJohn Marino e->ignore = 0;
88*86d7f5d3SJohn Marino }
89*86d7f5d3SJohn Marino
90*86d7f5d3SJohn Marino find_function_last_search = - files[0].prefix_lines;
91*86d7f5d3SJohn Marino find_function_last_match = find_function_last_search - 1;
92*86d7f5d3SJohn Marino
93*86d7f5d3SJohn Marino if (unidiff_flag)
94*86d7f5d3SJohn Marino print_script (script, find_hunk, pr_unidiff_hunk);
95*86d7f5d3SJohn Marino else
96*86d7f5d3SJohn Marino print_script (script, find_hunk, pr_context_hunk);
97*86d7f5d3SJohn Marino }
98*86d7f5d3SJohn Marino
99*86d7f5d3SJohn Marino /* Print a pair of line numbers with a comma, translated for file FILE.
100*86d7f5d3SJohn Marino If the second number is not greater, use the first in place of it.
101*86d7f5d3SJohn Marino
102*86d7f5d3SJohn Marino Args A and B are internal line numbers.
103*86d7f5d3SJohn Marino We print the translated (real) line numbers. */
104*86d7f5d3SJohn Marino
105*86d7f5d3SJohn Marino static void
print_context_number_range(file,a,b)106*86d7f5d3SJohn Marino print_context_number_range (file, a, b)
107*86d7f5d3SJohn Marino struct file_data const *file;
108*86d7f5d3SJohn Marino int a, b;
109*86d7f5d3SJohn Marino {
110*86d7f5d3SJohn Marino int trans_a, trans_b;
111*86d7f5d3SJohn Marino translate_range (file, a, b, &trans_a, &trans_b);
112*86d7f5d3SJohn Marino
113*86d7f5d3SJohn Marino /* Note: we can have B < A in the case of a range of no lines.
114*86d7f5d3SJohn Marino In this case, we should print the line number before the range,
115*86d7f5d3SJohn Marino which is B. */
116*86d7f5d3SJohn Marino if (trans_b > trans_a)
117*86d7f5d3SJohn Marino printf_output ("%d,%d", trans_a, trans_b);
118*86d7f5d3SJohn Marino else
119*86d7f5d3SJohn Marino printf_output ("%d", trans_b);
120*86d7f5d3SJohn Marino }
121*86d7f5d3SJohn Marino
122*86d7f5d3SJohn Marino /* Print a portion of an edit script in context format.
123*86d7f5d3SJohn Marino HUNK is the beginning of the portion to be printed.
124*86d7f5d3SJohn Marino The end is marked by a `link' that has been nulled out.
125*86d7f5d3SJohn Marino
126*86d7f5d3SJohn Marino Prints out lines from both files, and precedes each
127*86d7f5d3SJohn Marino line with the appropriate flag-character. */
128*86d7f5d3SJohn Marino
129*86d7f5d3SJohn Marino static void
pr_context_hunk(hunk)130*86d7f5d3SJohn Marino pr_context_hunk (hunk)
131*86d7f5d3SJohn Marino struct change *hunk;
132*86d7f5d3SJohn Marino {
133*86d7f5d3SJohn Marino int first0, last0, first1, last1, show_from, show_to, i;
134*86d7f5d3SJohn Marino struct change *next;
135*86d7f5d3SJohn Marino char const *prefix;
136*86d7f5d3SJohn Marino char const *function;
137*86d7f5d3SJohn Marino size_t function_length;
138*86d7f5d3SJohn Marino
139*86d7f5d3SJohn Marino /* Determine range of line numbers involved in each file. */
140*86d7f5d3SJohn Marino
141*86d7f5d3SJohn Marino analyze_hunk (hunk, &first0, &last0, &first1, &last1, &show_from, &show_to);
142*86d7f5d3SJohn Marino
143*86d7f5d3SJohn Marino if (!show_from && !show_to)
144*86d7f5d3SJohn Marino return;
145*86d7f5d3SJohn Marino
146*86d7f5d3SJohn Marino /* Include a context's width before and after. */
147*86d7f5d3SJohn Marino
148*86d7f5d3SJohn Marino i = - files[0].prefix_lines;
149*86d7f5d3SJohn Marino first0 = max (first0 - context, i);
150*86d7f5d3SJohn Marino first1 = max (first1 - context, i);
151*86d7f5d3SJohn Marino last0 = min (last0 + context, files[0].valid_lines - 1);
152*86d7f5d3SJohn Marino last1 = min (last1 + context, files[1].valid_lines - 1);
153*86d7f5d3SJohn Marino
154*86d7f5d3SJohn Marino /* If desired, find the preceding function definition line in file 0. */
155*86d7f5d3SJohn Marino function = 0;
156*86d7f5d3SJohn Marino if (function_regexp_list)
157*86d7f5d3SJohn Marino find_function (&files[0], first0, &function, &function_length);
158*86d7f5d3SJohn Marino
159*86d7f5d3SJohn Marino begin_output ();
160*86d7f5d3SJohn Marino
161*86d7f5d3SJohn Marino /* If we looked for and found a function this is part of,
162*86d7f5d3SJohn Marino include its name in the header of the diff section. */
163*86d7f5d3SJohn Marino printf_output ("***************");
164*86d7f5d3SJohn Marino
165*86d7f5d3SJohn Marino if (function)
166*86d7f5d3SJohn Marino {
167*86d7f5d3SJohn Marino printf_output (" ");
168*86d7f5d3SJohn Marino write_output (function, min (function_length - 1, 40));
169*86d7f5d3SJohn Marino }
170*86d7f5d3SJohn Marino
171*86d7f5d3SJohn Marino printf_output ("\n*** ");
172*86d7f5d3SJohn Marino print_context_number_range (&files[0], first0, last0);
173*86d7f5d3SJohn Marino printf_output (" ****\n");
174*86d7f5d3SJohn Marino
175*86d7f5d3SJohn Marino if (show_from)
176*86d7f5d3SJohn Marino {
177*86d7f5d3SJohn Marino next = hunk;
178*86d7f5d3SJohn Marino
179*86d7f5d3SJohn Marino for (i = first0; i <= last0; i++)
180*86d7f5d3SJohn Marino {
181*86d7f5d3SJohn Marino /* Skip past changes that apply (in file 0)
182*86d7f5d3SJohn Marino only to lines before line I. */
183*86d7f5d3SJohn Marino
184*86d7f5d3SJohn Marino while (next && next->line0 + next->deleted <= i)
185*86d7f5d3SJohn Marino next = next->link;
186*86d7f5d3SJohn Marino
187*86d7f5d3SJohn Marino /* Compute the marking for line I. */
188*86d7f5d3SJohn Marino
189*86d7f5d3SJohn Marino prefix = " ";
190*86d7f5d3SJohn Marino if (next && next->line0 <= i)
191*86d7f5d3SJohn Marino /* The change NEXT covers this line.
192*86d7f5d3SJohn Marino If lines were inserted here in file 1, this is "changed".
193*86d7f5d3SJohn Marino Otherwise it is "deleted". */
194*86d7f5d3SJohn Marino prefix = (next->inserted > 0 ? "!" : "-");
195*86d7f5d3SJohn Marino
196*86d7f5d3SJohn Marino print_1_line (prefix, &files[0].linbuf[i]);
197*86d7f5d3SJohn Marino }
198*86d7f5d3SJohn Marino }
199*86d7f5d3SJohn Marino
200*86d7f5d3SJohn Marino printf_output ("--- ");
201*86d7f5d3SJohn Marino print_context_number_range (&files[1], first1, last1);
202*86d7f5d3SJohn Marino printf_output (" ----\n");
203*86d7f5d3SJohn Marino
204*86d7f5d3SJohn Marino if (show_to)
205*86d7f5d3SJohn Marino {
206*86d7f5d3SJohn Marino next = hunk;
207*86d7f5d3SJohn Marino
208*86d7f5d3SJohn Marino for (i = first1; i <= last1; i++)
209*86d7f5d3SJohn Marino {
210*86d7f5d3SJohn Marino /* Skip past changes that apply (in file 1)
211*86d7f5d3SJohn Marino only to lines before line I. */
212*86d7f5d3SJohn Marino
213*86d7f5d3SJohn Marino while (next && next->line1 + next->inserted <= i)
214*86d7f5d3SJohn Marino next = next->link;
215*86d7f5d3SJohn Marino
216*86d7f5d3SJohn Marino /* Compute the marking for line I. */
217*86d7f5d3SJohn Marino
218*86d7f5d3SJohn Marino prefix = " ";
219*86d7f5d3SJohn Marino if (next && next->line1 <= i)
220*86d7f5d3SJohn Marino /* The change NEXT covers this line.
221*86d7f5d3SJohn Marino If lines were deleted here in file 0, this is "changed".
222*86d7f5d3SJohn Marino Otherwise it is "inserted". */
223*86d7f5d3SJohn Marino prefix = (next->deleted > 0 ? "!" : "+");
224*86d7f5d3SJohn Marino
225*86d7f5d3SJohn Marino print_1_line (prefix, &files[1].linbuf[i]);
226*86d7f5d3SJohn Marino }
227*86d7f5d3SJohn Marino }
228*86d7f5d3SJohn Marino }
229*86d7f5d3SJohn Marino
230*86d7f5d3SJohn Marino /* Print a pair of line numbers with a comma, translated for file FILE.
231*86d7f5d3SJohn Marino If the second number is smaller, use the first in place of it.
232*86d7f5d3SJohn Marino If the numbers are equal, print just one number.
233*86d7f5d3SJohn Marino
234*86d7f5d3SJohn Marino Args A and B are internal line numbers.
235*86d7f5d3SJohn Marino We print the translated (real) line numbers. */
236*86d7f5d3SJohn Marino
237*86d7f5d3SJohn Marino static void
print_unidiff_number_range(file,a,b)238*86d7f5d3SJohn Marino print_unidiff_number_range (file, a, b)
239*86d7f5d3SJohn Marino struct file_data const *file;
240*86d7f5d3SJohn Marino int a, b;
241*86d7f5d3SJohn Marino {
242*86d7f5d3SJohn Marino int trans_a, trans_b;
243*86d7f5d3SJohn Marino translate_range (file, a, b, &trans_a, &trans_b);
244*86d7f5d3SJohn Marino
245*86d7f5d3SJohn Marino /* Note: we can have B < A in the case of a range of no lines.
246*86d7f5d3SJohn Marino In this case, we should print the line number before the range,
247*86d7f5d3SJohn Marino which is B. */
248*86d7f5d3SJohn Marino if (trans_b <= trans_a)
249*86d7f5d3SJohn Marino printf_output (trans_b == trans_a ? "%d" : "%d,0", trans_b);
250*86d7f5d3SJohn Marino else
251*86d7f5d3SJohn Marino printf_output ("%d,%d", trans_a, trans_b - trans_a + 1);
252*86d7f5d3SJohn Marino }
253*86d7f5d3SJohn Marino
254*86d7f5d3SJohn Marino /* Print a portion of an edit script in unidiff format.
255*86d7f5d3SJohn Marino HUNK is the beginning of the portion to be printed.
256*86d7f5d3SJohn Marino The end is marked by a `link' that has been nulled out.
257*86d7f5d3SJohn Marino
258*86d7f5d3SJohn Marino Prints out lines from both files, and precedes each
259*86d7f5d3SJohn Marino line with the appropriate flag-character. */
260*86d7f5d3SJohn Marino
261*86d7f5d3SJohn Marino static void
pr_unidiff_hunk(hunk)262*86d7f5d3SJohn Marino pr_unidiff_hunk (hunk)
263*86d7f5d3SJohn Marino struct change *hunk;
264*86d7f5d3SJohn Marino {
265*86d7f5d3SJohn Marino int first0, last0, first1, last1, show_from, show_to, i, j, k;
266*86d7f5d3SJohn Marino struct change *next;
267*86d7f5d3SJohn Marino char const *function;
268*86d7f5d3SJohn Marino size_t function_length;
269*86d7f5d3SJohn Marino
270*86d7f5d3SJohn Marino /* Determine range of line numbers involved in each file. */
271*86d7f5d3SJohn Marino
272*86d7f5d3SJohn Marino analyze_hunk (hunk, &first0, &last0, &first1, &last1, &show_from, &show_to);
273*86d7f5d3SJohn Marino
274*86d7f5d3SJohn Marino if (!show_from && !show_to)
275*86d7f5d3SJohn Marino return;
276*86d7f5d3SJohn Marino
277*86d7f5d3SJohn Marino /* Include a context's width before and after. */
278*86d7f5d3SJohn Marino
279*86d7f5d3SJohn Marino i = - files[0].prefix_lines;
280*86d7f5d3SJohn Marino first0 = max (first0 - context, i);
281*86d7f5d3SJohn Marino first1 = max (first1 - context, i);
282*86d7f5d3SJohn Marino last0 = min (last0 + context, files[0].valid_lines - 1);
283*86d7f5d3SJohn Marino last1 = min (last1 + context, files[1].valid_lines - 1);
284*86d7f5d3SJohn Marino
285*86d7f5d3SJohn Marino /* If desired, find the preceding function definition line in file 0. */
286*86d7f5d3SJohn Marino function = 0;
287*86d7f5d3SJohn Marino if (function_regexp_list)
288*86d7f5d3SJohn Marino find_function (&files[0], first0, &function, &function_length);
289*86d7f5d3SJohn Marino
290*86d7f5d3SJohn Marino begin_output ();
291*86d7f5d3SJohn Marino
292*86d7f5d3SJohn Marino printf_output ("@@ -");
293*86d7f5d3SJohn Marino print_unidiff_number_range (&files[0], first0, last0);
294*86d7f5d3SJohn Marino printf_output (" +");
295*86d7f5d3SJohn Marino print_unidiff_number_range (&files[1], first1, last1);
296*86d7f5d3SJohn Marino printf_output (" @@");
297*86d7f5d3SJohn Marino
298*86d7f5d3SJohn Marino /* If we looked for and found a function this is part of,
299*86d7f5d3SJohn Marino include its name in the header of the diff section. */
300*86d7f5d3SJohn Marino
301*86d7f5d3SJohn Marino if (function)
302*86d7f5d3SJohn Marino {
303*86d7f5d3SJohn Marino write_output (" ", 1);
304*86d7f5d3SJohn Marino write_output (function, min (function_length - 1, 40));
305*86d7f5d3SJohn Marino }
306*86d7f5d3SJohn Marino write_output ("\n", 1);
307*86d7f5d3SJohn Marino
308*86d7f5d3SJohn Marino next = hunk;
309*86d7f5d3SJohn Marino i = first0;
310*86d7f5d3SJohn Marino j = first1;
311*86d7f5d3SJohn Marino
312*86d7f5d3SJohn Marino while (i <= last0 || j <= last1)
313*86d7f5d3SJohn Marino {
314*86d7f5d3SJohn Marino
315*86d7f5d3SJohn Marino /* If the line isn't a difference, output the context from file 0. */
316*86d7f5d3SJohn Marino
317*86d7f5d3SJohn Marino if (!next || i < next->line0)
318*86d7f5d3SJohn Marino {
319*86d7f5d3SJohn Marino write_output (tab_align_flag ? "\t" : " ", 1);
320*86d7f5d3SJohn Marino print_1_line (0, &files[0].linbuf[i++]);
321*86d7f5d3SJohn Marino j++;
322*86d7f5d3SJohn Marino }
323*86d7f5d3SJohn Marino else
324*86d7f5d3SJohn Marino {
325*86d7f5d3SJohn Marino /* For each difference, first output the deleted part. */
326*86d7f5d3SJohn Marino
327*86d7f5d3SJohn Marino k = next->deleted;
328*86d7f5d3SJohn Marino while (k--)
329*86d7f5d3SJohn Marino {
330*86d7f5d3SJohn Marino write_output ("-", 1);
331*86d7f5d3SJohn Marino if (tab_align_flag)
332*86d7f5d3SJohn Marino write_output ("\t", 1);
333*86d7f5d3SJohn Marino print_1_line (0, &files[0].linbuf[i++]);
334*86d7f5d3SJohn Marino }
335*86d7f5d3SJohn Marino
336*86d7f5d3SJohn Marino /* Then output the inserted part. */
337*86d7f5d3SJohn Marino
338*86d7f5d3SJohn Marino k = next->inserted;
339*86d7f5d3SJohn Marino while (k--)
340*86d7f5d3SJohn Marino {
341*86d7f5d3SJohn Marino write_output ("+", 1);
342*86d7f5d3SJohn Marino if (tab_align_flag)
343*86d7f5d3SJohn Marino write_output ("\t", 1);
344*86d7f5d3SJohn Marino print_1_line (0, &files[1].linbuf[j++]);
345*86d7f5d3SJohn Marino }
346*86d7f5d3SJohn Marino
347*86d7f5d3SJohn Marino /* We're done with this hunk, so on to the next! */
348*86d7f5d3SJohn Marino
349*86d7f5d3SJohn Marino next = next->link;
350*86d7f5d3SJohn Marino }
351*86d7f5d3SJohn Marino }
352*86d7f5d3SJohn Marino }
353*86d7f5d3SJohn Marino
354*86d7f5d3SJohn Marino /* Scan a (forward-ordered) edit script for the first place that more than
355*86d7f5d3SJohn Marino 2*CONTEXT unchanged lines appear, and return a pointer
356*86d7f5d3SJohn Marino to the `struct change' for the last change before those lines. */
357*86d7f5d3SJohn Marino
358*86d7f5d3SJohn Marino static struct change *
find_hunk(start)359*86d7f5d3SJohn Marino find_hunk (start)
360*86d7f5d3SJohn Marino struct change *start;
361*86d7f5d3SJohn Marino {
362*86d7f5d3SJohn Marino struct change *prev;
363*86d7f5d3SJohn Marino int top0, top1;
364*86d7f5d3SJohn Marino int thresh;
365*86d7f5d3SJohn Marino
366*86d7f5d3SJohn Marino do
367*86d7f5d3SJohn Marino {
368*86d7f5d3SJohn Marino /* Compute number of first line in each file beyond this changed. */
369*86d7f5d3SJohn Marino top0 = start->line0 + start->deleted;
370*86d7f5d3SJohn Marino top1 = start->line1 + start->inserted;
371*86d7f5d3SJohn Marino prev = start;
372*86d7f5d3SJohn Marino start = start->link;
373*86d7f5d3SJohn Marino /* Threshold distance is 2*CONTEXT between two non-ignorable changes,
374*86d7f5d3SJohn Marino but only CONTEXT if one is ignorable. */
375*86d7f5d3SJohn Marino thresh = ((prev->ignore || (start && start->ignore))
376*86d7f5d3SJohn Marino ? context
377*86d7f5d3SJohn Marino : 2 * context + 1);
378*86d7f5d3SJohn Marino /* It is not supposed to matter which file we check in the end-test.
379*86d7f5d3SJohn Marino If it would matter, crash. */
380*86d7f5d3SJohn Marino if (start && start->line0 - top0 != start->line1 - top1)
381*86d7f5d3SJohn Marino abort ();
382*86d7f5d3SJohn Marino } while (start
383*86d7f5d3SJohn Marino /* Keep going if less than THRESH lines
384*86d7f5d3SJohn Marino elapse before the affected line. */
385*86d7f5d3SJohn Marino && start->line0 < top0 + thresh);
386*86d7f5d3SJohn Marino
387*86d7f5d3SJohn Marino return prev;
388*86d7f5d3SJohn Marino }
389*86d7f5d3SJohn Marino
390*86d7f5d3SJohn Marino /* Set the `ignore' flag properly in each change in SCRIPT.
391*86d7f5d3SJohn Marino It should be 1 if all the lines inserted or deleted in that change
392*86d7f5d3SJohn Marino are ignorable lines. */
393*86d7f5d3SJohn Marino
394*86d7f5d3SJohn Marino static void
mark_ignorable(script)395*86d7f5d3SJohn Marino mark_ignorable (script)
396*86d7f5d3SJohn Marino struct change *script;
397*86d7f5d3SJohn Marino {
398*86d7f5d3SJohn Marino while (script)
399*86d7f5d3SJohn Marino {
400*86d7f5d3SJohn Marino struct change *next = script->link;
401*86d7f5d3SJohn Marino int first0, last0, first1, last1, deletes, inserts;
402*86d7f5d3SJohn Marino
403*86d7f5d3SJohn Marino /* Turn this change into a hunk: detach it from the others. */
404*86d7f5d3SJohn Marino script->link = 0;
405*86d7f5d3SJohn Marino
406*86d7f5d3SJohn Marino /* Determine whether this change is ignorable. */
407*86d7f5d3SJohn Marino analyze_hunk (script, &first0, &last0, &first1, &last1, &deletes, &inserts);
408*86d7f5d3SJohn Marino /* Reconnect the chain as before. */
409*86d7f5d3SJohn Marino script->link = next;
410*86d7f5d3SJohn Marino
411*86d7f5d3SJohn Marino /* If the change is ignorable, mark it. */
412*86d7f5d3SJohn Marino script->ignore = (!deletes && !inserts);
413*86d7f5d3SJohn Marino
414*86d7f5d3SJohn Marino /* Advance to the following change. */
415*86d7f5d3SJohn Marino script = next;
416*86d7f5d3SJohn Marino }
417*86d7f5d3SJohn Marino }
418*86d7f5d3SJohn Marino
419*86d7f5d3SJohn Marino /* Find the last function-header line in FILE prior to line number LINENUM.
420*86d7f5d3SJohn Marino This is a line containing a match for the regexp in `function_regexp'.
421*86d7f5d3SJohn Marino Store the address of the line text into LINEP and the length of the
422*86d7f5d3SJohn Marino line into LENP.
423*86d7f5d3SJohn Marino Do not store anything if no function-header is found. */
424*86d7f5d3SJohn Marino
425*86d7f5d3SJohn Marino static void
find_function(file,linenum,linep,lenp)426*86d7f5d3SJohn Marino find_function (file, linenum, linep, lenp)
427*86d7f5d3SJohn Marino struct file_data const *file;
428*86d7f5d3SJohn Marino int linenum;
429*86d7f5d3SJohn Marino char const **linep;
430*86d7f5d3SJohn Marino size_t *lenp;
431*86d7f5d3SJohn Marino {
432*86d7f5d3SJohn Marino int i = linenum;
433*86d7f5d3SJohn Marino int last = find_function_last_search;
434*86d7f5d3SJohn Marino find_function_last_search = i;
435*86d7f5d3SJohn Marino
436*86d7f5d3SJohn Marino while (--i >= last)
437*86d7f5d3SJohn Marino {
438*86d7f5d3SJohn Marino /* See if this line is what we want. */
439*86d7f5d3SJohn Marino struct regexp_list *r;
440*86d7f5d3SJohn Marino char const *line = file->linbuf[i];
441*86d7f5d3SJohn Marino size_t len = file->linbuf[i + 1] - line;
442*86d7f5d3SJohn Marino
443*86d7f5d3SJohn Marino for (r = function_regexp_list; r; r = r->next)
444*86d7f5d3SJohn Marino if (0 <= re_search (&r->buf, line, len, 0, len, 0))
445*86d7f5d3SJohn Marino {
446*86d7f5d3SJohn Marino *linep = line;
447*86d7f5d3SJohn Marino *lenp = len;
448*86d7f5d3SJohn Marino find_function_last_match = i;
449*86d7f5d3SJohn Marino return;
450*86d7f5d3SJohn Marino }
451*86d7f5d3SJohn Marino }
452*86d7f5d3SJohn Marino /* If we search back to where we started searching the previous time,
453*86d7f5d3SJohn Marino find the line we found last time. */
454*86d7f5d3SJohn Marino if (find_function_last_match >= - file->prefix_lines)
455*86d7f5d3SJohn Marino {
456*86d7f5d3SJohn Marino i = find_function_last_match;
457*86d7f5d3SJohn Marino *linep = file->linbuf[i];
458*86d7f5d3SJohn Marino *lenp = file->linbuf[i + 1] - *linep;
459*86d7f5d3SJohn Marino return;
460*86d7f5d3SJohn Marino }
461*86d7f5d3SJohn Marino return;
462*86d7f5d3SJohn Marino }
463