Blame src/context.c

Packit Service fdd496
/* Context-format output routines for GNU DIFF.
Packit Service fdd496
Packit Service fdd496
   Copyright (C) 1988-1989, 1991-1995, 1998, 2001-2002, 2004, 2006, 2009-2013,
Packit Service fdd496
   2015-2017 Free Software Foundation, Inc.
Packit Service fdd496
Packit Service fdd496
   This file is part of GNU DIFF.
Packit Service fdd496
Packit Service fdd496
   This program is free software: you can redistribute it and/or modify
Packit Service fdd496
   it under the terms of the GNU General Public License as published by
Packit Service fdd496
   the Free Software Foundation, either version 3 of the License, or
Packit Service fdd496
   (at your option) any later version.
Packit Service fdd496
Packit Service fdd496
   This program is distributed in the hope that it will be useful,
Packit Service fdd496
   but WITHOUT ANY WARRANTY; without even the implied warranty of
Packit Service fdd496
   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
Packit Service fdd496
   GNU General Public License for more details.
Packit Service fdd496
Packit Service fdd496
   You should have received a copy of the GNU General Public License
Packit Service fdd496
   along with this program.  If not, see <http://www.gnu.org/licenses/>.  */
Packit Service fdd496
Packit Service fdd496
#include "diff.h"
Packit Service fdd496
#include "c-ctype.h"
Packit Service fdd496
#include <stat-time.h>
Packit Service fdd496
#include <strftime.h>
Packit Service fdd496
Packit Service fdd496
static char const *find_function (char const * const *, lin);
Packit Service fdd496
static struct change *find_hunk (struct change *);
Packit Service fdd496
static void mark_ignorable (struct change *);
Packit Service fdd496
static void pr_context_hunk (struct change *);
Packit Service fdd496
static void pr_unidiff_hunk (struct change *);
Packit Service fdd496
Packit Service fdd496
/* Last place find_function started searching from.  */
Packit Service fdd496
static lin find_function_last_search;
Packit Service fdd496
Packit Service fdd496
/* The value find_function returned when it started searching there.  */
Packit Service fdd496
static lin find_function_last_match;
Packit Service fdd496

Packit Service fdd496
/* Print a label for a context diff, with a file name and date or a label.  */
Packit Service fdd496
Packit Service fdd496
static void
Packit Service fdd496
print_context_label (char const *mark,
Packit Service fdd496
		     struct file_data *inf,
Packit Service fdd496
		     char const *name,
Packit Service fdd496
		     char const *label)
Packit Service fdd496
{
Packit Service fdd496
  if (label)
Packit Service fdd496
    fprintf (outfile, "%s %s\n", mark, label);
Packit Service fdd496
  else
Packit Service fdd496
    {
Packit Service fdd496
      char buf[MAX (INT_STRLEN_BOUND (int) + 32,
Packit Service fdd496
		    INT_STRLEN_BOUND (time_t) + 11)];
Packit Service fdd496
      struct tm const *tm = localtime (&inf->stat.st_mtime);
Packit Service fdd496
      int nsec = get_stat_mtime_ns (&inf->stat);
Packit Service fdd496
      if (! (tm && nstrftime (buf, sizeof buf, time_format, tm, 0, nsec)))
Packit Service fdd496
	{
Packit Service fdd496
	  verify (TYPE_IS_INTEGER (time_t));
Packit Service fdd496
	  if (LONG_MIN <= TYPE_MINIMUM (time_t)
Packit Service fdd496
	      && TYPE_MAXIMUM (time_t) <= LONG_MAX)
Packit Service fdd496
	    {
Packit Service fdd496
	      long int sec = inf->stat.st_mtime;
Packit Service fdd496
	      sprintf (buf, "%ld.%.9d", sec, nsec);
Packit Service fdd496
	    }
Packit Service fdd496
	  else if (TYPE_MAXIMUM (time_t) <= INTMAX_MAX)
Packit Service fdd496
	    {
Packit Service fdd496
	      intmax_t sec = inf->stat.st_mtime;
Packit Service fdd496
	      sprintf (buf, "%"PRIdMAX".%.9d", sec, nsec);
Packit Service fdd496
	    }
Packit Service fdd496
	  else
Packit Service fdd496
	    {
Packit Service fdd496
	      uintmax_t sec = inf->stat.st_mtime;
Packit Service fdd496
	      sprintf (buf, "%"PRIuMAX".%.9d", sec, nsec);
Packit Service fdd496
	    }
Packit Service fdd496
	}
Packit Service fdd496
      fprintf (outfile, "%s %s\t%s\n", mark, name, buf);
Packit Service fdd496
    }
Packit Service fdd496
}
Packit Service fdd496
Packit Service fdd496
/* Print a header for a context diff, with the file names and dates.  */
Packit Service fdd496
Packit Service fdd496
void
Packit Service fdd496
print_context_header (struct file_data inf[], char const *const *names, bool unidiff)
Packit Service fdd496
{
Packit Service fdd496
  set_color_context (HEADER_CONTEXT);
Packit Service fdd496
  if (unidiff)
Packit Service fdd496
    {
Packit Service fdd496
      print_context_label ("---", &inf[0], names[0], file_label[0]);
Packit Service fdd496
      print_context_label ("+++", &inf[1], names[1], file_label[1]);
Packit Service fdd496
    }
Packit Service fdd496
  else
Packit Service fdd496
    {
Packit Service fdd496
      print_context_label ("***", &inf[0], names[0], file_label[0]);
Packit Service fdd496
      print_context_label ("---", &inf[1], names[1], file_label[1]);
Packit Service fdd496
    }
Packit Service fdd496
  set_color_context (RESET_CONTEXT);
Packit Service fdd496
}
Packit Service fdd496
Packit Service fdd496
/* Print an edit script in context format.  */
Packit Service fdd496
Packit Service fdd496
void
Packit Service fdd496
print_context_script (struct change *script, bool unidiff)
Packit Service fdd496
{
Packit Service fdd496
  if (ignore_blank_lines || ignore_regexp.fastmap)
Packit Service fdd496
    mark_ignorable (script);
Packit Service fdd496
  else
Packit Service fdd496
    {
Packit Service fdd496
      struct change *e;
Packit Service fdd496
      for (e = script; e; e = e->link)
Packit Service fdd496
	e->ignore = false;
Packit Service fdd496
    }
Packit Service fdd496
Packit Service fdd496
  find_function_last_search = - files[0].prefix_lines;
Packit Service fdd496
  find_function_last_match = LIN_MAX;
Packit Service fdd496
Packit Service fdd496
  if (unidiff)
Packit Service fdd496
    print_script (script, find_hunk, pr_unidiff_hunk);
Packit Service fdd496
  else
Packit Service fdd496
    print_script (script, find_hunk, pr_context_hunk);
Packit Service fdd496
}
Packit Service fdd496

Packit Service fdd496
/* Print a pair of line numbers with a comma, translated for file FILE.
Packit Service fdd496
   If the second number is not greater, use the first in place of it.
Packit Service fdd496
Packit Service fdd496
   Args A and B are internal line numbers.
Packit Service fdd496
   We print the translated (real) line numbers.  */
Packit Service fdd496
Packit Service fdd496
static void
Packit Service fdd496
print_context_number_range (struct file_data const *file, lin a, lin b)
Packit Service fdd496
{
Packit Service fdd496
  printint trans_a, trans_b;
Packit Service fdd496
  translate_range (file, a, b, &trans_a, &trans_b);
Packit Service fdd496
Packit Service fdd496
  /* We can have B <= A in the case of a range of no lines.
Packit Service fdd496
     In this case, we should print the line number before the range,
Packit Service fdd496
     which is B.
Packit Service fdd496
Packit Service fdd496
     POSIX 1003.1-2001 requires two line numbers separated by a comma
Packit Service fdd496
     even if the line numbers are the same.  However, this does not
Packit Service fdd496
     match existing practice and is surely an error in the
Packit Service fdd496
     specification.  */
Packit Service fdd496
Packit Service fdd496
  if (trans_b <= trans_a)
Packit Service fdd496
    fprintf (outfile, "%"pI"d", trans_b);
Packit Service fdd496
  else
Packit Service fdd496
    fprintf (outfile, "%"pI"d,%"pI"d", trans_a, trans_b);
Packit Service fdd496
}
Packit Service fdd496
Packit Service fdd496
/* Print FUNCTION in a context header.  */
Packit Service fdd496
static void
Packit Service fdd496
print_context_function (FILE *out, char const *function)
Packit Service fdd496
{
Packit Service fdd496
  int i, j;
Packit Service fdd496
  putc (' ', out);
Packit Service fdd496
  for (i = 0; c_isspace ((unsigned char) function[i]) && function[i] != '\n'; i++)
Packit Service fdd496
    continue;
Packit Service fdd496
  for (j = i; j < i + 40 && function[j] != '\n'; j++)
Packit Service fdd496
    continue;
Packit Service fdd496
  while (i < j && c_isspace ((unsigned char) function[j - 1]))
Packit Service fdd496
    j--;
Packit Service fdd496
  fwrite (function + i, sizeof (char), j - i, out);
Packit Service fdd496
}
Packit Service fdd496

Packit Service fdd496
/* Print a portion of an edit script in context format.
Packit Service fdd496
   HUNK is the beginning of the portion to be printed.
Packit Service fdd496
   The end is marked by a 'link' that has been nulled out.
Packit Service fdd496
Packit Service fdd496
   Prints out lines from both files, and precedes each
Packit Service fdd496
   line with the appropriate flag-character.  */
Packit Service fdd496
Packit Service fdd496
static void
Packit Service fdd496
pr_context_hunk (struct change *hunk)
Packit Service fdd496
{
Packit Service fdd496
  lin first0, last0, first1, last1, i;
Packit Service fdd496
  char const *prefix;
Packit Service fdd496
  char const *function;
Packit Service fdd496
  FILE *out;
Packit Service fdd496
Packit Service fdd496
  /* Determine range of line numbers involved in each file.  */
Packit Service fdd496
Packit Service fdd496
  enum changes changes = analyze_hunk (hunk, &first0, &last0, &first1, &last1);
Packit Service fdd496
  if (! changes)
Packit Service fdd496
    return;
Packit Service fdd496
Packit Service fdd496
  /* Include a context's width before and after.  */
Packit Service fdd496
Packit Service fdd496
  i = - files[0].prefix_lines;
Packit Service fdd496
  first0 = MAX (first0 - context, i);
Packit Service fdd496
  first1 = MAX (first1 - context, i);
Packit Service fdd496
  if (last0 < files[0].valid_lines - context)
Packit Service fdd496
    last0 += context;
Packit Service fdd496
  else
Packit Service fdd496
    last0 = files[0].valid_lines - 1;
Packit Service fdd496
  if (last1 < files[1].valid_lines - context)
Packit Service fdd496
    last1 += context;
Packit Service fdd496
  else
Packit Service fdd496
    last1 = files[1].valid_lines - 1;
Packit Service fdd496
Packit Service fdd496
  /* If desired, find the preceding function definition line in file 0.  */
Packit Service fdd496
  function = NULL;
Packit Service fdd496
  if (function_regexp.fastmap)
Packit Service fdd496
    function = find_function (files[0].linbuf, first0);
Packit Service fdd496
Packit Service fdd496
  begin_output ();
Packit Service fdd496
  out = outfile;
Packit Service fdd496
Packit Service fdd496
  fputs ("***************", out);
Packit Service fdd496
Packit Service fdd496
  if (function)
Packit Service fdd496
    print_context_function (out, function);
Packit Service fdd496
Packit Service fdd496
  putc ('\n', out);
Packit Service fdd496
  set_color_context (LINE_NUMBER_CONTEXT);
Packit Service fdd496
  fputs ("*** ", out);
Packit Service fdd496
  print_context_number_range (&files[0], first0, last0);
Packit Service fdd496
  fputs (" ****", out);
Packit Service fdd496
  set_color_context (RESET_CONTEXT);
Packit Service fdd496
  putc ('\n', out);
Packit Service fdd496
Packit Service fdd496
  if (changes & OLD)
Packit Service fdd496
    {
Packit Service fdd496
      struct change *next = hunk;
Packit Service fdd496
Packit Service fdd496
      if (first0 <= last0)
Packit Service fdd496
        set_color_context (DELETE_CONTEXT);
Packit Service fdd496
Packit Service fdd496
      for (i = first0; i <= last0; i++)
Packit Service fdd496
	{
Packit Service fdd496
	  /* Skip past changes that apply (in file 0)
Packit Service fdd496
	     only to lines before line I.  */
Packit Service fdd496
Packit Service fdd496
	  while (next && next->line0 + next->deleted <= i)
Packit Service fdd496
	    next = next->link;
Packit Service fdd496
Packit Service fdd496
	  /* Compute the marking for line I.  */
Packit Service fdd496
Packit Service fdd496
	  prefix = " ";
Packit Service fdd496
	  if (next && next->line0 <= i)
Packit Service fdd496
            {
Packit Service fdd496
              /* The change NEXT covers this line.
Packit Service fdd496
                 If lines were inserted here in file 1, this is "changed".
Packit Service fdd496
                 Otherwise it is "deleted".  */
Packit Service fdd496
              prefix = (next->inserted > 0 ? "!" : "-");
Packit Service fdd496
            }
Packit Service fdd496
	  print_1_line_nl (prefix, &files[0].linbuf[i], true);
Packit Service fdd496
          if (i == last0)
Packit Service fdd496
            set_color_context (RESET_CONTEXT);
Packit Service fdd496
          if (files[0].linbuf[i + 1][-1] == '\n')
Packit Service fdd496
            putc ('\n', out);
Packit Service fdd496
	}
Packit Service fdd496
    }
Packit Service fdd496
Packit Service fdd496
  set_color_context (LINE_NUMBER_CONTEXT);
Packit Service fdd496
  fputs ("--- ", out);
Packit Service fdd496
  print_context_number_range (&files[1], first1, last1);
Packit Service fdd496
  fputs (" ----", out);
Packit Service fdd496
  set_color_context (RESET_CONTEXT);
Packit Service fdd496
  putc ('\n', out);
Packit Service fdd496
Packit Service fdd496
  if (changes & NEW)
Packit Service fdd496
    {
Packit Service fdd496
      struct change *next = hunk;
Packit Service fdd496
Packit Service fdd496
      if (first1 <= last1)
Packit Service fdd496
        set_color_context (ADD_CONTEXT);
Packit Service fdd496
Packit Service fdd496
      for (i = first1; i <= last1; i++)
Packit Service fdd496
	{
Packit Service fdd496
	  /* Skip past changes that apply (in file 1)
Packit Service fdd496
	     only to lines before line I.  */
Packit Service fdd496
Packit Service fdd496
	  while (next && next->line1 + next->inserted <= i)
Packit Service fdd496
	    next = next->link;
Packit Service fdd496
Packit Service fdd496
	  /* Compute the marking for line I.  */
Packit Service fdd496
Packit Service fdd496
	  prefix = " ";
Packit Service fdd496
	  if (next && next->line1 <= i)
Packit Service fdd496
            {
Packit Service fdd496
              /* The change NEXT covers this line.
Packit Service fdd496
                 If lines were deleted here in file 0, this is "changed".
Packit Service fdd496
                 Otherwise it is "inserted".  */
Packit Service fdd496
              prefix = (next->deleted > 0 ? "!" : "+");
Packit Service fdd496
            }
Packit Service fdd496
	  print_1_line_nl (prefix, &files[1].linbuf[i], true);
Packit Service fdd496
          if (i == last1)
Packit Service fdd496
            set_color_context (RESET_CONTEXT);
Packit Service fdd496
          if (files[1].linbuf[i + 1][-1] == '\n')
Packit Service fdd496
            putc ('\n', out);
Packit Service fdd496
	}
Packit Service fdd496
    }
Packit Service fdd496
}
Packit Service fdd496

Packit Service fdd496
/* Print a pair of line numbers with a comma, translated for file FILE.
Packit Service fdd496
   If the second number is smaller, use the first in place of it.
Packit Service fdd496
   If the numbers are equal, print just one number.
Packit Service fdd496
Packit Service fdd496
   Args A and B are internal line numbers.
Packit Service fdd496
   We print the translated (real) line numbers.  */
Packit Service fdd496
Packit Service fdd496
static void
Packit Service fdd496
print_unidiff_number_range (struct file_data const *file, lin a, lin b)
Packit Service fdd496
{
Packit Service fdd496
  printint trans_a, trans_b;
Packit Service fdd496
  translate_range (file, a, b, &trans_a, &trans_b);
Packit Service fdd496
Packit Service fdd496
  /* We can have B < A in the case of a range of no lines.
Packit Service fdd496
     In this case, we print the line number before the range,
Packit Service fdd496
     which is B.  It would be more logical to print A, but
Packit Service fdd496
     'patch' expects B in order to detect diffs against empty files.  */
Packit Service fdd496
  if (trans_b <= trans_a)
Packit Service fdd496
    fprintf (outfile, trans_b < trans_a ? "%"pI"d,0" : "%"pI"d", trans_b);
Packit Service fdd496
  else
Packit Service fdd496
    fprintf (outfile, "%"pI"d,%"pI"d", trans_a, trans_b - trans_a + 1);
Packit Service fdd496
}
Packit Service fdd496

Packit Service fdd496
/* Print a portion of an edit script in unidiff format.
Packit Service fdd496
   HUNK is the beginning of the portion to be printed.
Packit Service fdd496
   The end is marked by a 'link' that has been nulled out.
Packit Service fdd496
Packit Service fdd496
   Prints out lines from both files, and precedes each
Packit Service fdd496
   line with the appropriate flag-character.  */
Packit Service fdd496
Packit Service fdd496
static void
Packit Service fdd496
pr_unidiff_hunk (struct change *hunk)
Packit Service fdd496
{
Packit Service fdd496
  lin first0, last0, first1, last1;
Packit Service fdd496
  lin i, j, k;
Packit Service fdd496
  struct change *next;
Packit Service fdd496
  char const *function;
Packit Service fdd496
  FILE *out;
Packit Service fdd496
Packit Service fdd496
  /* Determine range of line numbers involved in each file.  */
Packit Service fdd496
Packit Service fdd496
  if (! analyze_hunk (hunk, &first0, &last0, &first1, &last1))
Packit Service fdd496
    return;
Packit Service fdd496
Packit Service fdd496
  /* Include a context's width before and after.  */
Packit Service fdd496
Packit Service fdd496
  i = - files[0].prefix_lines;
Packit Service fdd496
  first0 = MAX (first0 - context, i);
Packit Service fdd496
  first1 = MAX (first1 - context, i);
Packit Service fdd496
  if (last0 < files[0].valid_lines - context)
Packit Service fdd496
    last0 += context;
Packit Service fdd496
  else
Packit Service fdd496
    last0 = files[0].valid_lines - 1;
Packit Service fdd496
  if (last1 < files[1].valid_lines - context)
Packit Service fdd496
    last1 += context;
Packit Service fdd496
  else
Packit Service fdd496
    last1 = files[1].valid_lines - 1;
Packit Service fdd496
Packit Service fdd496
  /* If desired, find the preceding function definition line in file 0.  */
Packit Service fdd496
  function = NULL;
Packit Service fdd496
  if (function_regexp.fastmap)
Packit Service fdd496
    function = find_function (files[0].linbuf, first0);
Packit Service fdd496
Packit Service fdd496
  begin_output ();
Packit Service fdd496
  out = outfile;
Packit Service fdd496
Packit Service fdd496
  set_color_context (LINE_NUMBER_CONTEXT);
Packit Service fdd496
  fputs ("@@ -", out);
Packit Service fdd496
  print_unidiff_number_range (&files[0], first0, last0);
Packit Service fdd496
  fputs (" +", out);
Packit Service fdd496
  print_unidiff_number_range (&files[1], first1, last1);
Packit Service fdd496
  fputs (" @@", out);
Packit Service fdd496
  set_color_context (RESET_CONTEXT);
Packit Service fdd496
Packit Service fdd496
  if (function)
Packit Service fdd496
    print_context_function (out, function);
Packit Service fdd496
Packit Service fdd496
  putc ('\n', out);
Packit Service fdd496
Packit Service fdd496
  next = hunk;
Packit Service fdd496
  i = first0;
Packit Service fdd496
  j = first1;
Packit Service fdd496
Packit Service fdd496
  while (i <= last0 || j <= last1)
Packit Service fdd496
    {
Packit Service fdd496
Packit Service fdd496
      /* If the line isn't a difference, output the context from file 0. */
Packit Service fdd496
Packit Service fdd496
      if (!next || i < next->line0)
Packit Service fdd496
	{
Packit Service fdd496
	  char const *const *line = &files[0].linbuf[i++];
Packit Service fdd496
	  if (! (suppress_blank_empty && **line == '\n'))
Packit Service fdd496
	    putc (initial_tab ? '\t' : ' ', out);
Packit Service fdd496
	  print_1_line (NULL, line);
Packit Service fdd496
	  j++;
Packit Service fdd496
	}
Packit Service fdd496
      else
Packit Service fdd496
	{
Packit Service fdd496
	  /* For each difference, first output the deleted part. */
Packit Service fdd496
Packit Service fdd496
	  k = next->deleted;
Packit Service fdd496
          if (k)
Packit Service fdd496
            set_color_context (DELETE_CONTEXT);
Packit Service fdd496
Packit Service fdd496
	  while (k--)
Packit Service fdd496
	    {
Packit Service fdd496
	      char const * const *line = &files[0].linbuf[i++];
Packit Service fdd496
	      putc ('-', out);
Packit Service fdd496
	      if (initial_tab && ! (suppress_blank_empty && **line == '\n'))
Packit Service fdd496
		putc ('\t', out);
Packit Service fdd496
	      print_1_line_nl (NULL, line, true);
Packit Service fdd496
Packit Service fdd496
              if (!k)
Packit Service fdd496
                set_color_context (RESET_CONTEXT);
Packit Service fdd496
Packit Service fdd496
              if (line[1][-1] == '\n')
Packit Service fdd496
                putc ('\n', out);
Packit Service fdd496
	    }
Packit Service fdd496
Packit Service fdd496
	  /* Then output the inserted part. */
Packit Service fdd496
Packit Service fdd496
	  k = next->inserted;
Packit Service fdd496
          if (k)
Packit Service fdd496
            set_color_context (ADD_CONTEXT);
Packit Service fdd496
Packit Service fdd496
          while (k--)
Packit Service fdd496
	    {
Packit Service fdd496
	      char const * const *line = &files[1].linbuf[j++];
Packit Service fdd496
	      putc ('+', out);
Packit Service fdd496
	      if (initial_tab && ! (suppress_blank_empty && **line == '\n'))
Packit Service fdd496
		putc ('\t', out);
Packit Service fdd496
	      print_1_line_nl (NULL, line, true);
Packit Service fdd496
Packit Service fdd496
              if (!k)
Packit Service fdd496
                set_color_context (RESET_CONTEXT);
Packit Service fdd496
Packit Service fdd496
              if (line[1][-1] == '\n')
Packit Service fdd496
                putc ('\n', out);
Packit Service fdd496
	    }
Packit Service fdd496
Packit Service fdd496
	  /* We're done with this hunk, so on to the next! */
Packit Service fdd496
Packit Service fdd496
	  next = next->link;
Packit Service fdd496
	}
Packit Service fdd496
    }
Packit Service fdd496
}
Packit Service fdd496

Packit Service fdd496
/* Scan a (forward-ordered) edit script for the first place that more than
Packit Service fdd496
   2*CONTEXT unchanged lines appear, and return a pointer
Packit Service fdd496
   to the 'struct change' for the last change before those lines.  */
Packit Service fdd496
Packit Service fdd496
static struct change * _GL_ATTRIBUTE_PURE
Packit Service fdd496
find_hunk (struct change *start)
Packit Service fdd496
{
Packit Service fdd496
  struct change *prev;
Packit Service fdd496
  lin top0, top1;
Packit Service fdd496
  lin thresh;
Packit Service fdd496
Packit Service fdd496
  /* Threshold distance is CONTEXT if the second change is ignorable,
Packit Service fdd496
     2 * CONTEXT + 1 otherwise.  Integer overflow can't happen, due
Packit Service fdd496
     to CONTEXT_LIM.  */
Packit Service fdd496
  lin ignorable_threshold = context;
Packit Service fdd496
  lin non_ignorable_threshold = 2 * context + 1;
Packit Service fdd496
Packit Service fdd496
  do
Packit Service fdd496
    {
Packit Service fdd496
      /* Compute number of first line in each file beyond this changed.  */
Packit Service fdd496
      top0 = start->line0 + start->deleted;
Packit Service fdd496
      top1 = start->line1 + start->inserted;
Packit Service fdd496
      prev = start;
Packit Service fdd496
      start = start->link;
Packit Service fdd496
      thresh = (start && start->ignore
Packit Service fdd496
		? ignorable_threshold
Packit Service fdd496
		: non_ignorable_threshold);
Packit Service fdd496
      /* It is not supposed to matter which file we check in the end-test.
Packit Service fdd496
	 If it would matter, crash.  */
Packit Service fdd496
      if (start && start->line0 - top0 != start->line1 - top1)
Packit Service fdd496
	abort ();
Packit Service fdd496
    } while (start
Packit Service fdd496
	     /* Keep going if less than THRESH lines
Packit Service fdd496
		elapse before the affected line.  */
Packit Service fdd496
	     && start->line0 - top0 < thresh);
Packit Service fdd496
Packit Service fdd496
  return prev;
Packit Service fdd496
}
Packit Service fdd496
Packit Service fdd496
/* Set the 'ignore' flag properly in each change in SCRIPT.
Packit Service fdd496
   It should be 1 if all the lines inserted or deleted in that change
Packit Service fdd496
   are ignorable lines.  */
Packit Service fdd496
Packit Service fdd496
static void
Packit Service fdd496
mark_ignorable (struct change *script)
Packit Service fdd496
{
Packit Service fdd496
  while (script)
Packit Service fdd496
    {
Packit Service fdd496
      struct change *next = script->link;
Packit Service fdd496
      lin first0, last0, first1, last1;
Packit Service fdd496
Packit Service fdd496
      /* Turn this change into a hunk: detach it from the others.  */
Packit Service fdd496
      script->link = NULL;
Packit Service fdd496
Packit Service fdd496
      /* Determine whether this change is ignorable.  */
Packit Service fdd496
      script->ignore = ! analyze_hunk (script,
Packit Service fdd496
				       &first0, &last0, &first1, &last1);
Packit Service fdd496
Packit Service fdd496
      /* Reconnect the chain as before.  */
Packit Service fdd496
      script->link = next;
Packit Service fdd496
Packit Service fdd496
      /* Advance to the following change.  */
Packit Service fdd496
      script = next;
Packit Service fdd496
    }
Packit Service fdd496
}
Packit Service fdd496

Packit Service fdd496
/* Find the last function-header line in LINBUF prior to line number LINENUM.
Packit Service fdd496
   This is a line containing a match for the regexp in 'function_regexp'.
Packit Service fdd496
   Return the address of the text, or NULL if no function-header is found.  */
Packit Service fdd496
Packit Service fdd496
static char const *
Packit Service fdd496
find_function (char const * const *linbuf, lin linenum)
Packit Service fdd496
{
Packit Service fdd496
  lin i = linenum;
Packit Service fdd496
  lin last = find_function_last_search;
Packit Service fdd496
  find_function_last_search = i;
Packit Service fdd496
Packit Service fdd496
  while (last <= --i)
Packit Service fdd496
    {
Packit Service fdd496
      /* See if this line is what we want.  */
Packit Service fdd496
      char const *line = linbuf[i];
Packit Service fdd496
      size_t linelen = linbuf[i + 1] - line - 1;
Packit Service fdd496
Packit Service fdd496
      /* FIXME: re_search's size args should be size_t, not int.  */
Packit Service fdd496
      int len = MIN (linelen, INT_MAX);
Packit Service fdd496
Packit Service fdd496
      if (0 <= re_search (&function_regexp, line, len, 0, len, NULL))
Packit Service fdd496
	{
Packit Service fdd496
	  find_function_last_match = i;
Packit Service fdd496
	  return line;
Packit Service fdd496
	}
Packit Service fdd496
    }
Packit Service fdd496
  /* If we search back to where we started searching the previous time,
Packit Service fdd496
     find the line we found last time.  */
Packit Service fdd496
  if (find_function_last_match != LIN_MAX)
Packit Service fdd496
    return linbuf[find_function_last_match];
Packit Service fdd496
Packit Service fdd496
  return NULL;
Packit Service fdd496
}