Blame src/context.c

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