186d7f5d3SJohn Marino /* Context-format output routines for GNU DIFF.
286d7f5d3SJohn Marino Copyright (C) 1988,1989,1991,1992,1993,1994,1998 Free Software Foundation, Inc.
386d7f5d3SJohn Marino
486d7f5d3SJohn Marino This file is part of GNU DIFF.
586d7f5d3SJohn Marino
686d7f5d3SJohn Marino GNU DIFF is free software; you can redistribute it and/or modify
786d7f5d3SJohn Marino it under the terms of the GNU General Public License as published by
886d7f5d3SJohn Marino the Free Software Foundation; either version 2, or (at your option)
986d7f5d3SJohn Marino any later version.
1086d7f5d3SJohn Marino
1186d7f5d3SJohn Marino GNU DIFF is distributed in the hope that it will be useful,
1286d7f5d3SJohn Marino but WITHOUT ANY WARRANTY; without even the implied warranty of
1386d7f5d3SJohn Marino MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
1486d7f5d3SJohn Marino GNU General Public License for more details.
1586d7f5d3SJohn Marino
1686d7f5d3SJohn Marino */
1786d7f5d3SJohn Marino
1886d7f5d3SJohn Marino #include "diff.h"
1986d7f5d3SJohn Marino
2086d7f5d3SJohn Marino static struct change *find_hunk PARAMS((struct change *));
2186d7f5d3SJohn Marino static void find_function PARAMS((struct file_data const *, int, char const **, size_t *));
2286d7f5d3SJohn Marino static void mark_ignorable PARAMS((struct change *));
2386d7f5d3SJohn Marino static void pr_context_hunk PARAMS((struct change *));
2486d7f5d3SJohn Marino static void pr_unidiff_hunk PARAMS((struct change *));
2586d7f5d3SJohn Marino static void print_context_label PARAMS ((char const *, struct file_data *, char const *));
2686d7f5d3SJohn Marino static void print_context_number_range PARAMS((struct file_data const *, int, int));
2786d7f5d3SJohn Marino static void print_unidiff_number_range PARAMS((struct file_data const *, int, int));
2886d7f5d3SJohn Marino
2986d7f5d3SJohn Marino /* Last place find_function started searching from. */
3086d7f5d3SJohn Marino static int find_function_last_search;
3186d7f5d3SJohn Marino
3286d7f5d3SJohn Marino /* The value find_function returned when it started searching there. */
3386d7f5d3SJohn Marino static int find_function_last_match;
3486d7f5d3SJohn Marino
3586d7f5d3SJohn Marino /* Print a label for a context diff, with a file name and date or a label. */
3686d7f5d3SJohn Marino
3786d7f5d3SJohn Marino static void
print_context_label(mark,inf,label)3886d7f5d3SJohn Marino print_context_label (mark, inf, label)
3986d7f5d3SJohn Marino char const *mark;
4086d7f5d3SJohn Marino struct file_data *inf;
4186d7f5d3SJohn Marino char const *label;
4286d7f5d3SJohn Marino {
4386d7f5d3SJohn Marino if (label)
4486d7f5d3SJohn Marino printf_output ("%s %s\n", mark, label);
4586d7f5d3SJohn Marino else
4686d7f5d3SJohn Marino {
4786d7f5d3SJohn Marino char const *ct = ctime (&inf->stat.st_mtime);
4886d7f5d3SJohn Marino if (!ct)
4986d7f5d3SJohn Marino ct = "?\n";
5086d7f5d3SJohn Marino /* See Posix.2 section 4.17.6.1.4 for this format. */
5186d7f5d3SJohn Marino printf_output ("%s %s\t%s", mark, inf->name, ct);
5286d7f5d3SJohn Marino }
5386d7f5d3SJohn Marino }
5486d7f5d3SJohn Marino
5586d7f5d3SJohn Marino /* Print a header for a context diff, with the file names and dates. */
5686d7f5d3SJohn Marino
5786d7f5d3SJohn Marino void
print_context_header(inf,unidiff_flag)5886d7f5d3SJohn Marino print_context_header (inf, unidiff_flag)
5986d7f5d3SJohn Marino struct file_data inf[];
6086d7f5d3SJohn Marino int unidiff_flag;
6186d7f5d3SJohn Marino {
6286d7f5d3SJohn Marino if (unidiff_flag)
6386d7f5d3SJohn Marino {
6486d7f5d3SJohn Marino print_context_label ("---", &inf[0], file_label[0]);
6586d7f5d3SJohn Marino print_context_label ("+++", &inf[1], file_label[1]);
6686d7f5d3SJohn Marino }
6786d7f5d3SJohn Marino else
6886d7f5d3SJohn Marino {
6986d7f5d3SJohn Marino print_context_label ("***", &inf[0], file_label[0]);
7086d7f5d3SJohn Marino print_context_label ("---", &inf[1], file_label[1]);
7186d7f5d3SJohn Marino }
7286d7f5d3SJohn Marino }
7386d7f5d3SJohn Marino
7486d7f5d3SJohn Marino /* Print an edit script in context format. */
7586d7f5d3SJohn Marino
7686d7f5d3SJohn Marino void
print_context_script(script,unidiff_flag)7786d7f5d3SJohn Marino print_context_script (script, unidiff_flag)
7886d7f5d3SJohn Marino struct change *script;
7986d7f5d3SJohn Marino int unidiff_flag;
8086d7f5d3SJohn Marino {
8186d7f5d3SJohn Marino if (ignore_blank_lines_flag || ignore_regexp_list)
8286d7f5d3SJohn Marino mark_ignorable (script);
8386d7f5d3SJohn Marino else
8486d7f5d3SJohn Marino {
8586d7f5d3SJohn Marino struct change *e;
8686d7f5d3SJohn Marino for (e = script; e; e = e->link)
8786d7f5d3SJohn Marino e->ignore = 0;
8886d7f5d3SJohn Marino }
8986d7f5d3SJohn Marino
9086d7f5d3SJohn Marino find_function_last_search = - files[0].prefix_lines;
9186d7f5d3SJohn Marino find_function_last_match = find_function_last_search - 1;
9286d7f5d3SJohn Marino
9386d7f5d3SJohn Marino if (unidiff_flag)
9486d7f5d3SJohn Marino print_script (script, find_hunk, pr_unidiff_hunk);
9586d7f5d3SJohn Marino else
9686d7f5d3SJohn Marino print_script (script, find_hunk, pr_context_hunk);
9786d7f5d3SJohn Marino }
9886d7f5d3SJohn Marino
9986d7f5d3SJohn Marino /* Print a pair of line numbers with a comma, translated for file FILE.
10086d7f5d3SJohn Marino If the second number is not greater, use the first in place of it.
10186d7f5d3SJohn Marino
10286d7f5d3SJohn Marino Args A and B are internal line numbers.
10386d7f5d3SJohn Marino We print the translated (real) line numbers. */
10486d7f5d3SJohn Marino
10586d7f5d3SJohn Marino static void
print_context_number_range(file,a,b)10686d7f5d3SJohn Marino print_context_number_range (file, a, b)
10786d7f5d3SJohn Marino struct file_data const *file;
10886d7f5d3SJohn Marino int a, b;
10986d7f5d3SJohn Marino {
11086d7f5d3SJohn Marino int trans_a, trans_b;
11186d7f5d3SJohn Marino translate_range (file, a, b, &trans_a, &trans_b);
11286d7f5d3SJohn Marino
11386d7f5d3SJohn Marino /* Note: we can have B < A in the case of a range of no lines.
11486d7f5d3SJohn Marino In this case, we should print the line number before the range,
11586d7f5d3SJohn Marino which is B. */
11686d7f5d3SJohn Marino if (trans_b > trans_a)
11786d7f5d3SJohn Marino printf_output ("%d,%d", trans_a, trans_b);
11886d7f5d3SJohn Marino else
11986d7f5d3SJohn Marino printf_output ("%d", trans_b);
12086d7f5d3SJohn Marino }
12186d7f5d3SJohn Marino
12286d7f5d3SJohn Marino /* Print a portion of an edit script in context format.
12386d7f5d3SJohn Marino HUNK is the beginning of the portion to be printed.
12486d7f5d3SJohn Marino The end is marked by a `link' that has been nulled out.
12586d7f5d3SJohn Marino
12686d7f5d3SJohn Marino Prints out lines from both files, and precedes each
12786d7f5d3SJohn Marino line with the appropriate flag-character. */
12886d7f5d3SJohn Marino
12986d7f5d3SJohn Marino static void
pr_context_hunk(hunk)13086d7f5d3SJohn Marino pr_context_hunk (hunk)
13186d7f5d3SJohn Marino struct change *hunk;
13286d7f5d3SJohn Marino {
13386d7f5d3SJohn Marino int first0, last0, first1, last1, show_from, show_to, i;
13486d7f5d3SJohn Marino struct change *next;
13586d7f5d3SJohn Marino char const *prefix;
13686d7f5d3SJohn Marino char const *function;
13786d7f5d3SJohn Marino size_t function_length;
13886d7f5d3SJohn Marino
13986d7f5d3SJohn Marino /* Determine range of line numbers involved in each file. */
14086d7f5d3SJohn Marino
14186d7f5d3SJohn Marino analyze_hunk (hunk, &first0, &last0, &first1, &last1, &show_from, &show_to);
14286d7f5d3SJohn Marino
14386d7f5d3SJohn Marino if (!show_from && !show_to)
14486d7f5d3SJohn Marino return;
14586d7f5d3SJohn Marino
14686d7f5d3SJohn Marino /* Include a context's width before and after. */
14786d7f5d3SJohn Marino
14886d7f5d3SJohn Marino i = - files[0].prefix_lines;
14986d7f5d3SJohn Marino first0 = max (first0 - context, i);
15086d7f5d3SJohn Marino first1 = max (first1 - context, i);
15186d7f5d3SJohn Marino last0 = min (last0 + context, files[0].valid_lines - 1);
15286d7f5d3SJohn Marino last1 = min (last1 + context, files[1].valid_lines - 1);
15386d7f5d3SJohn Marino
15486d7f5d3SJohn Marino /* If desired, find the preceding function definition line in file 0. */
15586d7f5d3SJohn Marino function = 0;
15686d7f5d3SJohn Marino if (function_regexp_list)
15786d7f5d3SJohn Marino find_function (&files[0], first0, &function, &function_length);
15886d7f5d3SJohn Marino
15986d7f5d3SJohn Marino begin_output ();
16086d7f5d3SJohn Marino
16186d7f5d3SJohn Marino /* If we looked for and found a function this is part of,
16286d7f5d3SJohn Marino include its name in the header of the diff section. */
16386d7f5d3SJohn Marino printf_output ("***************");
16486d7f5d3SJohn Marino
16586d7f5d3SJohn Marino if (function)
16686d7f5d3SJohn Marino {
16786d7f5d3SJohn Marino printf_output (" ");
16886d7f5d3SJohn Marino write_output (function, min (function_length - 1, 40));
16986d7f5d3SJohn Marino }
17086d7f5d3SJohn Marino
17186d7f5d3SJohn Marino printf_output ("\n*** ");
17286d7f5d3SJohn Marino print_context_number_range (&files[0], first0, last0);
17386d7f5d3SJohn Marino printf_output (" ****\n");
17486d7f5d3SJohn Marino
17586d7f5d3SJohn Marino if (show_from)
17686d7f5d3SJohn Marino {
17786d7f5d3SJohn Marino next = hunk;
17886d7f5d3SJohn Marino
17986d7f5d3SJohn Marino for (i = first0; i <= last0; i++)
18086d7f5d3SJohn Marino {
18186d7f5d3SJohn Marino /* Skip past changes that apply (in file 0)
18286d7f5d3SJohn Marino only to lines before line I. */
18386d7f5d3SJohn Marino
18486d7f5d3SJohn Marino while (next && next->line0 + next->deleted <= i)
18586d7f5d3SJohn Marino next = next->link;
18686d7f5d3SJohn Marino
18786d7f5d3SJohn Marino /* Compute the marking for line I. */
18886d7f5d3SJohn Marino
18986d7f5d3SJohn Marino prefix = " ";
19086d7f5d3SJohn Marino if (next && next->line0 <= i)
19186d7f5d3SJohn Marino /* The change NEXT covers this line.
19286d7f5d3SJohn Marino If lines were inserted here in file 1, this is "changed".
19386d7f5d3SJohn Marino Otherwise it is "deleted". */
19486d7f5d3SJohn Marino prefix = (next->inserted > 0 ? "!" : "-");
19586d7f5d3SJohn Marino
19686d7f5d3SJohn Marino print_1_line (prefix, &files[0].linbuf[i]);
19786d7f5d3SJohn Marino }
19886d7f5d3SJohn Marino }
19986d7f5d3SJohn Marino
20086d7f5d3SJohn Marino printf_output ("--- ");
20186d7f5d3SJohn Marino print_context_number_range (&files[1], first1, last1);
20286d7f5d3SJohn Marino printf_output (" ----\n");
20386d7f5d3SJohn Marino
20486d7f5d3SJohn Marino if (show_to)
20586d7f5d3SJohn Marino {
20686d7f5d3SJohn Marino next = hunk;
20786d7f5d3SJohn Marino
20886d7f5d3SJohn Marino for (i = first1; i <= last1; i++)
20986d7f5d3SJohn Marino {
21086d7f5d3SJohn Marino /* Skip past changes that apply (in file 1)
21186d7f5d3SJohn Marino only to lines before line I. */
21286d7f5d3SJohn Marino
21386d7f5d3SJohn Marino while (next && next->line1 + next->inserted <= i)
21486d7f5d3SJohn Marino next = next->link;
21586d7f5d3SJohn Marino
21686d7f5d3SJohn Marino /* Compute the marking for line I. */
21786d7f5d3SJohn Marino
21886d7f5d3SJohn Marino prefix = " ";
21986d7f5d3SJohn Marino if (next && next->line1 <= i)
22086d7f5d3SJohn Marino /* The change NEXT covers this line.
22186d7f5d3SJohn Marino If lines were deleted here in file 0, this is "changed".
22286d7f5d3SJohn Marino Otherwise it is "inserted". */
22386d7f5d3SJohn Marino prefix = (next->deleted > 0 ? "!" : "+");
22486d7f5d3SJohn Marino
22586d7f5d3SJohn Marino print_1_line (prefix, &files[1].linbuf[i]);
22686d7f5d3SJohn Marino }
22786d7f5d3SJohn Marino }
22886d7f5d3SJohn Marino }
22986d7f5d3SJohn Marino
23086d7f5d3SJohn Marino /* Print a pair of line numbers with a comma, translated for file FILE.
23186d7f5d3SJohn Marino If the second number is smaller, use the first in place of it.
23286d7f5d3SJohn Marino If the numbers are equal, print just one number.
23386d7f5d3SJohn Marino
23486d7f5d3SJohn Marino Args A and B are internal line numbers.
23586d7f5d3SJohn Marino We print the translated (real) line numbers. */
23686d7f5d3SJohn Marino
23786d7f5d3SJohn Marino static void
print_unidiff_number_range(file,a,b)23886d7f5d3SJohn Marino print_unidiff_number_range (file, a, b)
23986d7f5d3SJohn Marino struct file_data const *file;
24086d7f5d3SJohn Marino int a, b;
24186d7f5d3SJohn Marino {
24286d7f5d3SJohn Marino int trans_a, trans_b;
24386d7f5d3SJohn Marino translate_range (file, a, b, &trans_a, &trans_b);
24486d7f5d3SJohn Marino
24586d7f5d3SJohn Marino /* Note: we can have B < A in the case of a range of no lines.
24686d7f5d3SJohn Marino In this case, we should print the line number before the range,
24786d7f5d3SJohn Marino which is B. */
24886d7f5d3SJohn Marino if (trans_b <= trans_a)
24986d7f5d3SJohn Marino printf_output (trans_b == trans_a ? "%d" : "%d,0", trans_b);
25086d7f5d3SJohn Marino else
25186d7f5d3SJohn Marino printf_output ("%d,%d", trans_a, trans_b - trans_a + 1);
25286d7f5d3SJohn Marino }
25386d7f5d3SJohn Marino
25486d7f5d3SJohn Marino /* Print a portion of an edit script in unidiff format.
25586d7f5d3SJohn Marino HUNK is the beginning of the portion to be printed.
25686d7f5d3SJohn Marino The end is marked by a `link' that has been nulled out.
25786d7f5d3SJohn Marino
25886d7f5d3SJohn Marino Prints out lines from both files, and precedes each
25986d7f5d3SJohn Marino line with the appropriate flag-character. */
26086d7f5d3SJohn Marino
26186d7f5d3SJohn Marino static void
pr_unidiff_hunk(hunk)26286d7f5d3SJohn Marino pr_unidiff_hunk (hunk)
26386d7f5d3SJohn Marino struct change *hunk;
26486d7f5d3SJohn Marino {
26586d7f5d3SJohn Marino int first0, last0, first1, last1, show_from, show_to, i, j, k;
26686d7f5d3SJohn Marino struct change *next;
26786d7f5d3SJohn Marino char const *function;
26886d7f5d3SJohn Marino size_t function_length;
26986d7f5d3SJohn Marino
27086d7f5d3SJohn Marino /* Determine range of line numbers involved in each file. */
27186d7f5d3SJohn Marino
27286d7f5d3SJohn Marino analyze_hunk (hunk, &first0, &last0, &first1, &last1, &show_from, &show_to);
27386d7f5d3SJohn Marino
27486d7f5d3SJohn Marino if (!show_from && !show_to)
27586d7f5d3SJohn Marino return;
27686d7f5d3SJohn Marino
27786d7f5d3SJohn Marino /* Include a context's width before and after. */
27886d7f5d3SJohn Marino
27986d7f5d3SJohn Marino i = - files[0].prefix_lines;
28086d7f5d3SJohn Marino first0 = max (first0 - context, i);
28186d7f5d3SJohn Marino first1 = max (first1 - context, i);
28286d7f5d3SJohn Marino last0 = min (last0 + context, files[0].valid_lines - 1);
28386d7f5d3SJohn Marino last1 = min (last1 + context, files[1].valid_lines - 1);
28486d7f5d3SJohn Marino
28586d7f5d3SJohn Marino /* If desired, find the preceding function definition line in file 0. */
28686d7f5d3SJohn Marino function = 0;
28786d7f5d3SJohn Marino if (function_regexp_list)
28886d7f5d3SJohn Marino find_function (&files[0], first0, &function, &function_length);
28986d7f5d3SJohn Marino
29086d7f5d3SJohn Marino begin_output ();
29186d7f5d3SJohn Marino
29286d7f5d3SJohn Marino printf_output ("@@ -");
29386d7f5d3SJohn Marino print_unidiff_number_range (&files[0], first0, last0);
29486d7f5d3SJohn Marino printf_output (" +");
29586d7f5d3SJohn Marino print_unidiff_number_range (&files[1], first1, last1);
29686d7f5d3SJohn Marino printf_output (" @@");
29786d7f5d3SJohn Marino
29886d7f5d3SJohn Marino /* If we looked for and found a function this is part of,
29986d7f5d3SJohn Marino include its name in the header of the diff section. */
30086d7f5d3SJohn Marino
30186d7f5d3SJohn Marino if (function)
30286d7f5d3SJohn Marino {
30386d7f5d3SJohn Marino write_output (" ", 1);
30486d7f5d3SJohn Marino write_output (function, min (function_length - 1, 40));
30586d7f5d3SJohn Marino }
30686d7f5d3SJohn Marino write_output ("\n", 1);
30786d7f5d3SJohn Marino
30886d7f5d3SJohn Marino next = hunk;
30986d7f5d3SJohn Marino i = first0;
31086d7f5d3SJohn Marino j = first1;
31186d7f5d3SJohn Marino
31286d7f5d3SJohn Marino while (i <= last0 || j <= last1)
31386d7f5d3SJohn Marino {
31486d7f5d3SJohn Marino
31586d7f5d3SJohn Marino /* If the line isn't a difference, output the context from file 0. */
31686d7f5d3SJohn Marino
31786d7f5d3SJohn Marino if (!next || i < next->line0)
31886d7f5d3SJohn Marino {
31986d7f5d3SJohn Marino write_output (tab_align_flag ? "\t" : " ", 1);
32086d7f5d3SJohn Marino print_1_line (0, &files[0].linbuf[i++]);
32186d7f5d3SJohn Marino j++;
32286d7f5d3SJohn Marino }
32386d7f5d3SJohn Marino else
32486d7f5d3SJohn Marino {
32586d7f5d3SJohn Marino /* For each difference, first output the deleted part. */
32686d7f5d3SJohn Marino
32786d7f5d3SJohn Marino k = next->deleted;
32886d7f5d3SJohn Marino while (k--)
32986d7f5d3SJohn Marino {
33086d7f5d3SJohn Marino write_output ("-", 1);
33186d7f5d3SJohn Marino if (tab_align_flag)
33286d7f5d3SJohn Marino write_output ("\t", 1);
33386d7f5d3SJohn Marino print_1_line (0, &files[0].linbuf[i++]);
33486d7f5d3SJohn Marino }
33586d7f5d3SJohn Marino
33686d7f5d3SJohn Marino /* Then output the inserted part. */
33786d7f5d3SJohn Marino
33886d7f5d3SJohn Marino k = next->inserted;
33986d7f5d3SJohn Marino while (k--)
34086d7f5d3SJohn Marino {
34186d7f5d3SJohn Marino write_output ("+", 1);
34286d7f5d3SJohn Marino if (tab_align_flag)
34386d7f5d3SJohn Marino write_output ("\t", 1);
34486d7f5d3SJohn Marino print_1_line (0, &files[1].linbuf[j++]);
34586d7f5d3SJohn Marino }
34686d7f5d3SJohn Marino
34786d7f5d3SJohn Marino /* We're done with this hunk, so on to the next! */
34886d7f5d3SJohn Marino
34986d7f5d3SJohn Marino next = next->link;
35086d7f5d3SJohn Marino }
35186d7f5d3SJohn Marino }
35286d7f5d3SJohn Marino }
35386d7f5d3SJohn Marino
35486d7f5d3SJohn Marino /* Scan a (forward-ordered) edit script for the first place that more than
35586d7f5d3SJohn Marino 2*CONTEXT unchanged lines appear, and return a pointer
35686d7f5d3SJohn Marino to the `struct change' for the last change before those lines. */
35786d7f5d3SJohn Marino
35886d7f5d3SJohn Marino static struct change *
find_hunk(start)35986d7f5d3SJohn Marino find_hunk (start)
36086d7f5d3SJohn Marino struct change *start;
36186d7f5d3SJohn Marino {
36286d7f5d3SJohn Marino struct change *prev;
36386d7f5d3SJohn Marino int top0, top1;
36486d7f5d3SJohn Marino int thresh;
36586d7f5d3SJohn Marino
36686d7f5d3SJohn Marino do
36786d7f5d3SJohn Marino {
36886d7f5d3SJohn Marino /* Compute number of first line in each file beyond this changed. */
36986d7f5d3SJohn Marino top0 = start->line0 + start->deleted;
37086d7f5d3SJohn Marino top1 = start->line1 + start->inserted;
37186d7f5d3SJohn Marino prev = start;
37286d7f5d3SJohn Marino start = start->link;
37386d7f5d3SJohn Marino /* Threshold distance is 2*CONTEXT between two non-ignorable changes,
37486d7f5d3SJohn Marino but only CONTEXT if one is ignorable. */
37586d7f5d3SJohn Marino thresh = ((prev->ignore || (start && start->ignore))
37686d7f5d3SJohn Marino ? context
37786d7f5d3SJohn Marino : 2 * context + 1);
37886d7f5d3SJohn Marino /* It is not supposed to matter which file we check in the end-test.
37986d7f5d3SJohn Marino If it would matter, crash. */
38086d7f5d3SJohn Marino if (start && start->line0 - top0 != start->line1 - top1)
38186d7f5d3SJohn Marino abort ();
38286d7f5d3SJohn Marino } while (start
38386d7f5d3SJohn Marino /* Keep going if less than THRESH lines
38486d7f5d3SJohn Marino elapse before the affected line. */
38586d7f5d3SJohn Marino && start->line0 < top0 + thresh);
38686d7f5d3SJohn Marino
38786d7f5d3SJohn Marino return prev;
38886d7f5d3SJohn Marino }
38986d7f5d3SJohn Marino
39086d7f5d3SJohn Marino /* Set the `ignore' flag properly in each change in SCRIPT.
39186d7f5d3SJohn Marino It should be 1 if all the lines inserted or deleted in that change
39286d7f5d3SJohn Marino are ignorable lines. */
39386d7f5d3SJohn Marino
39486d7f5d3SJohn Marino static void
mark_ignorable(script)39586d7f5d3SJohn Marino mark_ignorable (script)
39686d7f5d3SJohn Marino struct change *script;
39786d7f5d3SJohn Marino {
39886d7f5d3SJohn Marino while (script)
39986d7f5d3SJohn Marino {
40086d7f5d3SJohn Marino struct change *next = script->link;
40186d7f5d3SJohn Marino int first0, last0, first1, last1, deletes, inserts;
40286d7f5d3SJohn Marino
40386d7f5d3SJohn Marino /* Turn this change into a hunk: detach it from the others. */
40486d7f5d3SJohn Marino script->link = 0;
40586d7f5d3SJohn Marino
40686d7f5d3SJohn Marino /* Determine whether this change is ignorable. */
40786d7f5d3SJohn Marino analyze_hunk (script, &first0, &last0, &first1, &last1, &deletes, &inserts);
40886d7f5d3SJohn Marino /* Reconnect the chain as before. */
40986d7f5d3SJohn Marino script->link = next;
41086d7f5d3SJohn Marino
41186d7f5d3SJohn Marino /* If the change is ignorable, mark it. */
41286d7f5d3SJohn Marino script->ignore = (!deletes && !inserts);
41386d7f5d3SJohn Marino
41486d7f5d3SJohn Marino /* Advance to the following change. */
41586d7f5d3SJohn Marino script = next;
41686d7f5d3SJohn Marino }
41786d7f5d3SJohn Marino }
41886d7f5d3SJohn Marino
41986d7f5d3SJohn Marino /* Find the last function-header line in FILE prior to line number LINENUM.
42086d7f5d3SJohn Marino This is a line containing a match for the regexp in `function_regexp'.
42186d7f5d3SJohn Marino Store the address of the line text into LINEP and the length of the
42286d7f5d3SJohn Marino line into LENP.
42386d7f5d3SJohn Marino Do not store anything if no function-header is found. */
42486d7f5d3SJohn Marino
42586d7f5d3SJohn Marino static void
find_function(file,linenum,linep,lenp)42686d7f5d3SJohn Marino find_function (file, linenum, linep, lenp)
42786d7f5d3SJohn Marino struct file_data const *file;
42886d7f5d3SJohn Marino int linenum;
42986d7f5d3SJohn Marino char const **linep;
43086d7f5d3SJohn Marino size_t *lenp;
43186d7f5d3SJohn Marino {
43286d7f5d3SJohn Marino int i = linenum;
43386d7f5d3SJohn Marino int last = find_function_last_search;
43486d7f5d3SJohn Marino find_function_last_search = i;
43586d7f5d3SJohn Marino
43686d7f5d3SJohn Marino while (--i >= last)
43786d7f5d3SJohn Marino {
43886d7f5d3SJohn Marino /* See if this line is what we want. */
43986d7f5d3SJohn Marino struct regexp_list *r;
44086d7f5d3SJohn Marino char const *line = file->linbuf[i];
44186d7f5d3SJohn Marino size_t len = file->linbuf[i + 1] - line;
44286d7f5d3SJohn Marino
44386d7f5d3SJohn Marino for (r = function_regexp_list; r; r = r->next)
44486d7f5d3SJohn Marino if (0 <= re_search (&r->buf, line, len, 0, len, 0))
44586d7f5d3SJohn Marino {
44686d7f5d3SJohn Marino *linep = line;
44786d7f5d3SJohn Marino *lenp = len;
44886d7f5d3SJohn Marino find_function_last_match = i;
44986d7f5d3SJohn Marino return;
45086d7f5d3SJohn Marino }
45186d7f5d3SJohn Marino }
45286d7f5d3SJohn Marino /* If we search back to where we started searching the previous time,
45386d7f5d3SJohn Marino find the line we found last time. */
45486d7f5d3SJohn Marino if (find_function_last_match >= - file->prefix_lines)
45586d7f5d3SJohn Marino {
45686d7f5d3SJohn Marino i = find_function_last_match;
45786d7f5d3SJohn Marino *linep = file->linbuf[i];
45886d7f5d3SJohn Marino *lenp = file->linbuf[i + 1] - *linep;
45986d7f5d3SJohn Marino return;
46086d7f5d3SJohn Marino }
46186d7f5d3SJohn Marino return;
46286d7f5d3SJohn Marino }
463