xref: /dragonfly/contrib/diffutils/src/util.c (revision 279dd846)
1 /* Support routines for GNU DIFF.
2 
3    Copyright (C) 1988-1989, 1992-1995, 1998, 2001-2002, 2004, 2006, 2009-2013
4    Free Software Foundation, Inc.
5 
6    This file is part of GNU DIFF.
7 
8    This program is free software: you can redistribute it and/or modify
9    it under the terms of the GNU General Public License as published by
10    the Free Software Foundation, either version 3 of the License, or
11    (at your option) any later version.
12 
13    This program is distributed in the hope that it will be useful,
14    but WITHOUT ANY WARRANTY; without even the implied warranty of
15    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
16    GNU General Public License for more details.
17 
18    You should have received a copy of the GNU General Public License
19    along with this program.  If not, see <http://www.gnu.org/licenses/>.  */
20 
21 #include "diff.h"
22 #include <dirname.h>
23 #include <error.h>
24 #include <system-quote.h>
25 #include <xalloc.h>
26 #include "xvasprintf.h"
27 
28 char const pr_program[] = PR_PROGRAM;
29 
30 /* Queue up one-line messages to be printed at the end,
31    when -l is specified.  Each message is recorded with a 'struct msg'.  */
32 
33 struct msg
34 {
35   struct msg *next;
36   char args[1]; /* Format + 4 args, each '\0' terminated, concatenated.  */
37 };
38 
39 /* Head of the chain of queues messages.  */
40 
41 static struct msg *msg_chain;
42 
43 /* Tail of the chain of queues messages.  */
44 
45 static struct msg **msg_chain_end = &msg_chain;
46 
47 /* Use when a system call returns non-zero status.
48    NAME should normally be the file name.  */
49 
50 void
51 perror_with_name (char const *name)
52 {
53   error (0, errno, "%s", name);
54 }
55 
56 /* Use when a system call returns non-zero status and that is fatal.  */
57 
58 void
59 pfatal_with_name (char const *name)
60 {
61   int e = errno;
62   print_message_queue ();
63   error (EXIT_TROUBLE, e, "%s", name);
64   abort ();
65 }
66 
67 /* Print an error message containing MSGID, then exit.  */
68 
69 void
70 fatal (char const *msgid)
71 {
72   print_message_queue ();
73   error (EXIT_TROUBLE, 0, "%s", _(msgid));
74   abort ();
75 }
76 
77 /* Like printf, except if -l in effect then save the message and print later.
78    This is used for things like "Only in ...".  */
79 
80 void
81 message (char const *format_msgid, char const *arg1, char const *arg2)
82 {
83   message5 (format_msgid, arg1, arg2, 0, 0);
84 }
85 
86 void
87 message5 (char const *format_msgid, char const *arg1, char const *arg2,
88 	  char const *arg3, char const *arg4)
89 {
90   if (paginate)
91     {
92       char *p;
93       char const *arg[5];
94       int i;
95       size_t size[5];
96       size_t total_size = offsetof (struct msg, args);
97       struct msg *new;
98 
99       arg[0] = format_msgid;
100       arg[1] = arg1;
101       arg[2] = arg2;
102       arg[3] = arg3 ? arg3 : "";
103       arg[4] = arg4 ? arg4 : "";
104 
105       for (i = 0;  i < 5;  i++)
106 	total_size += size[i] = strlen (arg[i]) + 1;
107 
108       new = xmalloc (total_size);
109 
110       for (i = 0, p = new->args;  i < 5;  p += size[i++])
111 	memcpy (p, arg[i], size[i]);
112 
113       *msg_chain_end = new;
114       new->next = 0;
115       msg_chain_end = &new->next;
116     }
117   else
118     {
119       if (sdiff_merge_assist)
120 	putchar (' ');
121       printf (_(format_msgid), arg1, arg2, arg3, arg4);
122     }
123 }
124 
125 /* Output all the messages that were saved up by calls to 'message'.  */
126 
127 void
128 print_message_queue (void)
129 {
130   char const *arg[5];
131   int i;
132   struct msg *m = msg_chain;
133 
134   while (m)
135     {
136       struct msg *next = m->next;
137       arg[0] = m->args;
138       for (i = 0;  i < 4;  i++)
139 	arg[i + 1] = arg[i] + strlen (arg[i]) + 1;
140       printf (_(arg[0]), arg[1], arg[2], arg[3], arg[4]);
141       free (m);
142       m = next;
143     }
144 }
145 
146 /* Call before outputting the results of comparing files NAME0 and NAME1
147    to set up OUTFILE, the stdio stream for the output to go to.
148 
149    Usually, OUTFILE is just stdout.  But when -l was specified
150    we fork off a 'pr' and make OUTFILE a pipe to it.
151    'pr' then outputs to our stdout.  */
152 
153 static char const *current_name0;
154 static char const *current_name1;
155 static bool currently_recursive;
156 
157 void
158 setup_output (char const *name0, char const *name1, bool recursive)
159 {
160   current_name0 = name0;
161   current_name1 = name1;
162   currently_recursive = recursive;
163   outfile = 0;
164 }
165 
166 #if HAVE_WORKING_FORK
167 static pid_t pr_pid;
168 #endif
169 
170 static char c_escape_char (char c)
171 {
172   switch (c) {
173     case '\a': return 'a';
174     case '\b': return 'b';
175     case '\t': return 't';
176     case '\n': return 'n';
177     case '\v': return 'v';
178     case '\f': return 'f';
179     case '\r': return 'r';
180     case '"': return '"';
181     case '\\': return '\\';
182     default:
183       return c < 32;
184   }
185 }
186 
187 static char *
188 c_escape (char const *str)
189 {
190   char const *s;
191   size_t plus = 0;
192   bool must_quote = false;
193 
194   for (s = str; *s; s++)
195     {
196       char c = *s;
197 
198       if (c == ' ')
199 	{
200 	  must_quote = true;
201 	  continue;
202 	}
203       switch (c_escape_char (*s))
204 	{
205 	  case 1:
206 	    plus += 3;
207 	    /* fall through */
208 	  case 0:
209 	    break;
210 	  default:
211 	    plus++;
212 	    break;
213 	}
214     }
215 
216   if (must_quote || plus)
217     {
218       size_t s_len = s - str;
219       char *buffer = xmalloc (s_len + plus + 3);
220       char *b = buffer;
221 
222       *b++ = '"';
223       for (s = str; *s; s++)
224 	{
225 	  char c = *s;
226 	  char escape = c_escape_char (c);
227 
228 	  switch (escape)
229 	    {
230 	      case 0:
231 		*b++ = c;
232 		break;
233 	      case 1:
234 		*b++ = '\\';
235 		*b++ = ((c >> 6) & 03) + '0';
236 		*b++ = ((c >> 3) & 07) + '0';
237 		*b++ = ((c >> 0) & 07) + '0';
238 		break;
239 	      default:
240 		*b++ = '\\';
241 		*b++ = escape;
242 		break;
243 	    }
244 	}
245       *b++ = '"';
246       *b = 0;
247       return buffer;
248     }
249 
250   return (char *) str;
251 }
252 
253 void
254 begin_output (void)
255 {
256   char *names[2];
257   char *name;
258 
259   if (outfile != 0)
260     return;
261 
262   names[0] = c_escape (current_name0);
263   names[1] = c_escape (current_name1);
264 
265   /* Construct the header of this piece of diff.  */
266   /* POSIX 1003.1-2001 specifies this format.  But there are some bugs in
267      the standard: it says that we must print only the last component
268      of the pathnames, and it requires two spaces after "diff" if
269      there are no options.  These requirements are silly and do not
270      match historical practice.  */
271   name = xasprintf ("diff%s %s %s", switch_string, names[0], names[1]);
272 
273   if (paginate)
274     {
275       char const *argv[4];
276 
277       if (fflush (stdout) != 0)
278 	pfatal_with_name (_("write failed"));
279 
280       argv[0] = pr_program;
281       argv[1] = "-h";
282       argv[2] = name;
283       argv[3] = 0;
284 
285       /* Make OUTFILE a pipe to a subsidiary 'pr'.  */
286       {
287 #if HAVE_WORKING_FORK
288 	int pipes[2];
289 
290 	if (pipe (pipes) != 0)
291 	  pfatal_with_name ("pipe");
292 
293 	pr_pid = fork ();
294 	if (pr_pid < 0)
295 	  pfatal_with_name ("fork");
296 
297 	if (pr_pid == 0)
298 	  {
299 	    close (pipes[1]);
300 	    if (pipes[0] != STDIN_FILENO)
301 	      {
302 		if (dup2 (pipes[0], STDIN_FILENO) < 0)
303 		  pfatal_with_name ("dup2");
304 		close (pipes[0]);
305 	      }
306 
307 	    execv (pr_program, (char **) argv);
308 	    _exit (errno == ENOENT ? 127 : 126);
309 	  }
310 	else
311 	  {
312 	    close (pipes[0]);
313 	    outfile = fdopen (pipes[1], "w");
314 	    if (!outfile)
315 	      pfatal_with_name ("fdopen");
316 	  }
317 #else
318 	char *command = system_quote_argv (SCI_SYSTEM, (char **) argv);
319 	errno = 0;
320 	outfile = popen (command, "w");
321 	if (!outfile)
322 	  pfatal_with_name (command);
323 	free (command);
324 #endif
325       }
326     }
327   else
328     {
329 
330       /* If -l was not specified, output the diff straight to 'stdout'.  */
331 
332       outfile = stdout;
333 
334       /* If handling multiple files (because scanning a directory),
335 	 print which files the following output is about.  */
336       if (currently_recursive)
337 	printf ("%s\n", name);
338     }
339 
340   free (name);
341 
342   /* A special header is needed at the beginning of context output.  */
343   switch (output_style)
344     {
345     case OUTPUT_CONTEXT:
346       print_context_header (files, (char const *const *)names, false);
347       break;
348 
349     case OUTPUT_UNIFIED:
350       print_context_header (files, (char const *const *)names, true);
351       break;
352 
353     default:
354       break;
355     }
356 
357   if (names[0] != current_name0)
358     free (names[0]);
359   if (names[1] != current_name1)
360     free (names[1]);
361 }
362 
363 /* Call after the end of output of diffs for one file.
364    Close OUTFILE and get rid of the 'pr' subfork.  */
365 
366 void
367 finish_output (void)
368 {
369   if (outfile != 0 && outfile != stdout)
370     {
371       int status;
372       int wstatus;
373       int werrno = 0;
374       if (ferror (outfile))
375 	fatal ("write failed");
376 #if ! HAVE_WORKING_FORK
377       wstatus = pclose (outfile);
378       if (wstatus == -1)
379 	werrno = errno;
380 #else
381       if (fclose (outfile) != 0)
382 	pfatal_with_name (_("write failed"));
383       if (waitpid (pr_pid, &wstatus, 0) < 0)
384 	pfatal_with_name ("waitpid");
385 #endif
386       status = (! werrno && WIFEXITED (wstatus)
387 		? WEXITSTATUS (wstatus)
388 		: INT_MAX);
389       if (status)
390 	error (EXIT_TROUBLE, werrno,
391 	       _(status == 126
392 		 ? "subsidiary program '%s' could not be invoked"
393 		 : status == 127
394 		 ? "subsidiary program '%s' not found"
395 		 : status == INT_MAX
396 		 ? "subsidiary program '%s' failed"
397 		 : "subsidiary program '%s' failed (exit status %d)"),
398 	       pr_program, status);
399     }
400 
401   outfile = 0;
402 }
403 
404 /* Compare two lines (typically one from each input file)
405    according to the command line options.
406    For efficiency, this is invoked only when the lines do not match exactly
407    but an option like -i might cause us to ignore the difference.
408    Return nonzero if the lines differ.  */
409 
410 bool
411 lines_differ (char const *s1, char const *s2)
412 {
413   register char const *t1 = s1;
414   register char const *t2 = s2;
415   size_t column = 0;
416 
417   while (1)
418     {
419       register unsigned char c1 = *t1++;
420       register unsigned char c2 = *t2++;
421 
422       /* Test for exact char equality first, since it's a common case.  */
423       if (c1 != c2)
424 	{
425 	  switch (ignore_white_space)
426 	    {
427 	    case IGNORE_ALL_SPACE:
428 	      /* For -w, just skip past any white space.  */
429 	      while (isspace (c1) && c1 != '\n') c1 = *t1++;
430 	      while (isspace (c2) && c2 != '\n') c2 = *t2++;
431 	      break;
432 
433 	    case IGNORE_SPACE_CHANGE:
434 	      /* For -b, advance past any sequence of white space in
435 		 line 1 and consider it just one space, or nothing at
436 		 all if it is at the end of the line.  */
437 	      if (isspace (c1))
438 		{
439 		  while (c1 != '\n')
440 		    {
441 		      c1 = *t1++;
442 		      if (! isspace (c1))
443 			{
444 			  --t1;
445 			  c1 = ' ';
446 			  break;
447 			}
448 		    }
449 		}
450 
451 	      /* Likewise for line 2.  */
452 	      if (isspace (c2))
453 		{
454 		  while (c2 != '\n')
455 		    {
456 		      c2 = *t2++;
457 		      if (! isspace (c2))
458 			{
459 			  --t2;
460 			  c2 = ' ';
461 			  break;
462 			}
463 		    }
464 		}
465 
466 	      if (c1 != c2)
467 		{
468 		  /* If we went too far when doing the simple test
469 		     for equality, go back to the first non-white-space
470 		     character in both sides and try again.  */
471 		  if (c2 == ' ' && c1 != '\n'
472 		      && s1 + 1 < t1
473 		      && isspace ((unsigned char) t1[-2]))
474 		    {
475 		      --t1;
476 		      continue;
477 		    }
478 		  if (c1 == ' ' && c2 != '\n'
479 		      && s2 + 1 < t2
480 		      && isspace ((unsigned char) t2[-2]))
481 		    {
482 		      --t2;
483 		      continue;
484 		    }
485 		}
486 
487 	      break;
488 
489 	    case IGNORE_TRAILING_SPACE:
490 	    case IGNORE_TAB_EXPANSION_AND_TRAILING_SPACE:
491 	      if (isspace (c1) && isspace (c2))
492 		{
493 		  unsigned char c;
494 		  if (c1 != '\n')
495 		    {
496 		      char const *p = t1;
497 		      while ((c = *p) != '\n' && isspace (c))
498 			++p;
499 		      if (c != '\n')
500 			break;
501 		    }
502 		  if (c2 != '\n')
503 		    {
504 		      char const *p = t2;
505 		      while ((c = *p) != '\n' && isspace (c))
506 			++p;
507 		      if (c != '\n')
508 			break;
509 		    }
510 		  /* Both lines have nothing but whitespace left.  */
511 		  return false;
512 		}
513 	      if (ignore_white_space == IGNORE_TRAILING_SPACE)
514 		break;
515 	      /* Fall through.  */
516 	    case IGNORE_TAB_EXPANSION:
517 	      if ((c1 == ' ' && c2 == '\t')
518 		  || (c1 == '\t' && c2 == ' '))
519 		{
520 		  size_t column2 = column;
521 		  for (;; c1 = *t1++)
522 		    {
523 		      if (c1 == ' ')
524 			column++;
525 		      else if (c1 == '\t')
526 			column += tabsize - column % tabsize;
527 		      else
528 			break;
529 		    }
530 		  for (;; c2 = *t2++)
531 		    {
532 		      if (c2 == ' ')
533 			column2++;
534 		      else if (c2 == '\t')
535 			column2 += tabsize - column2 % tabsize;
536 		      else
537 			break;
538 		    }
539 		  if (column != column2)
540 		    return true;
541 		}
542 	      break;
543 
544 	    case IGNORE_NO_WHITE_SPACE:
545 	      break;
546 	    }
547 
548 	  /* Lowercase all letters if -i is specified.  */
549 
550 	  if (ignore_case)
551 	    {
552 	      c1 = tolower (c1);
553 	      c2 = tolower (c2);
554 	    }
555 
556 	  if (c1 != c2)
557 	    break;
558 	}
559       if (c1 == '\n')
560 	return false;
561 
562       column += c1 == '\t' ? tabsize - column % tabsize : 1;
563     }
564 
565   return true;
566 }
567 
568 /* Find the consecutive changes at the start of the script START.
569    Return the last link before the first gap.  */
570 
571 struct change * _GL_ATTRIBUTE_CONST
572 find_change (struct change *start)
573 {
574   return start;
575 }
576 
577 struct change * _GL_ATTRIBUTE_CONST
578 find_reverse_change (struct change *start)
579 {
580   return start;
581 }
582 
583 /* Divide SCRIPT into pieces by calling HUNKFUN and
584    print each piece with PRINTFUN.
585    Both functions take one arg, an edit script.
586 
587    HUNKFUN is called with the tail of the script
588    and returns the last link that belongs together with the start
589    of the tail.
590 
591    PRINTFUN takes a subscript which belongs together (with a null
592    link at the end) and prints it.  */
593 
594 void
595 print_script (struct change *script,
596 	      struct change * (*hunkfun) (struct change *),
597 	      void (*printfun) (struct change *))
598 {
599   struct change *next = script;
600 
601   while (next)
602     {
603       struct change *this, *end;
604 
605       /* Find a set of changes that belong together.  */
606       this = next;
607       end = (*hunkfun) (next);
608 
609       /* Disconnect them from the rest of the changes,
610 	 making them a hunk, and remember the rest for next iteration.  */
611       next = end->link;
612       end->link = 0;
613 #ifdef DEBUG
614       debug_script (this);
615 #endif
616 
617       /* Print this hunk.  */
618       (*printfun) (this);
619 
620       /* Reconnect the script so it will all be freed properly.  */
621       end->link = next;
622     }
623 }
624 
625 /* Print the text of a single line LINE,
626    flagging it with the characters in LINE_FLAG (which say whether
627    the line is inserted, deleted, changed, etc.).  LINE_FLAG must not
628    end in a blank, unless it is a single blank.  */
629 
630 void
631 print_1_line (char const *line_flag, char const *const *line)
632 {
633   char const *base = line[0], *limit = line[1]; /* Help the compiler.  */
634   FILE *out = outfile; /* Help the compiler some more.  */
635   char const *flag_format = 0;
636 
637   /* If -T was specified, use a Tab between the line-flag and the text.
638      Otherwise use a Space (as Unix diff does).
639      Print neither space nor tab if line-flags are empty.
640      But omit trailing blanks if requested.  */
641 
642   if (line_flag && *line_flag)
643     {
644       char const *flag_format_1 = flag_format = initial_tab ? "%s\t" : "%s ";
645       char const *line_flag_1 = line_flag;
646 
647       if (suppress_blank_empty && **line == '\n')
648 	{
649 	  flag_format_1 = "%s";
650 
651 	  /* This hack to omit trailing blanks takes advantage of the
652 	     fact that the only way that LINE_FLAG can end in a blank
653 	     is when LINE_FLAG consists of a single blank.  */
654 	  line_flag_1 += *line_flag_1 == ' ';
655 	}
656 
657       fprintf (out, flag_format_1, line_flag_1);
658     }
659 
660   output_1_line (base, limit, flag_format, line_flag);
661 
662   if ((!line_flag || line_flag[0]) && limit[-1] != '\n')
663     fprintf (out, "\n\\ %s\n", _("No newline at end of file"));
664 }
665 
666 /* Output a line from BASE up to LIMIT.
667    With -t, expand white space characters to spaces, and if FLAG_FORMAT
668    is nonzero, output it with argument LINE_FLAG after every
669    internal carriage return, so that tab stops continue to line up.  */
670 
671 void
672 output_1_line (char const *base, char const *limit, char const *flag_format,
673 	       char const *line_flag)
674 {
675   if (!expand_tabs)
676     fwrite (base, sizeof (char), limit - base, outfile);
677   else
678     {
679       register FILE *out = outfile;
680       register unsigned char c;
681       register char const *t = base;
682       register size_t column = 0;
683       size_t tab_size = tabsize;
684 
685       while (t < limit)
686 	switch ((c = *t++))
687 	  {
688 	  case '\t':
689 	    {
690 	      size_t spaces = tab_size - column % tab_size;
691 	      column += spaces;
692 	      do
693 		putc (' ', out);
694 	      while (--spaces);
695 	    }
696 	    break;
697 
698 	  case '\r':
699 	    putc (c, out);
700 	    if (flag_format && t < limit && *t != '\n')
701 	      fprintf (out, flag_format, line_flag);
702 	    column = 0;
703 	    break;
704 
705 	  case '\b':
706 	    if (column == 0)
707 	      continue;
708 	    column--;
709 	    putc (c, out);
710 	    break;
711 
712 	  default:
713 	    column += isprint (c) != 0;
714 	    putc (c, out);
715 	    break;
716 	  }
717     }
718 }
719 
720 char const change_letter[] = { 0, 'd', 'a', 'c' };
721 
722 /* Translate an internal line number (an index into diff's table of lines)
723    into an actual line number in the input file.
724    The internal line number is I.  FILE points to the data on the file.
725 
726    Internal line numbers count from 0 starting after the prefix.
727    Actual line numbers count from 1 within the entire file.  */
728 
729 lin _GL_ATTRIBUTE_PURE
730 translate_line_number (struct file_data const *file, lin i)
731 {
732   return i + file->prefix_lines + 1;
733 }
734 
735 /* Translate a line number range.  This is always done for printing,
736    so for convenience translate to long int rather than lin, so that the
737    caller can use printf with "%ld" without casting.  */
738 
739 void
740 translate_range (struct file_data const *file,
741 		 lin a, lin b,
742 		 long int *aptr, long int *bptr)
743 {
744   *aptr = translate_line_number (file, a - 1) + 1;
745   *bptr = translate_line_number (file, b + 1) - 1;
746 }
747 
748 /* Print a pair of line numbers with SEPCHAR, translated for file FILE.
749    If the two numbers are identical, print just one number.
750 
751    Args A and B are internal line numbers.
752    We print the translated (real) line numbers.  */
753 
754 void
755 print_number_range (char sepchar, struct file_data *file, lin a, lin b)
756 {
757   long int trans_a, trans_b;
758   translate_range (file, a, b, &trans_a, &trans_b);
759 
760   /* Note: we can have B < A in the case of a range of no lines.
761      In this case, we should print the line number before the range,
762      which is B.  */
763   if (trans_b > trans_a)
764     fprintf (outfile, "%ld%c%ld", trans_a, sepchar, trans_b);
765   else
766     fprintf (outfile, "%ld", trans_b);
767 }
768 
769 /* Look at a hunk of edit script and report the range of lines in each file
770    that it applies to.  HUNK is the start of the hunk, which is a chain
771    of 'struct change'.  The first and last line numbers of file 0 are stored in
772    *FIRST0 and *LAST0, and likewise for file 1 in *FIRST1 and *LAST1.
773    Note that these are internal line numbers that count from 0.
774 
775    If no lines from file 0 are deleted, then FIRST0 is LAST0+1.
776 
777    Return UNCHANGED if only ignorable lines are inserted or deleted,
778    OLD if lines of file 0 are deleted,
779    NEW if lines of file 1 are inserted,
780    and CHANGED if both kinds of changes are found. */
781 
782 enum changes
783 analyze_hunk (struct change *hunk,
784 	      lin *first0, lin *last0,
785 	      lin *first1, lin *last1)
786 {
787   struct change *next;
788   lin l0, l1;
789   lin show_from, show_to;
790   lin i;
791   bool trivial = ignore_blank_lines || ignore_regexp.fastmap;
792   size_t trivial_length = ignore_blank_lines - 1;
793     /* If 0, ignore zero-length lines;
794        if SIZE_MAX, do not ignore lines just because of their length.  */
795 
796   bool skip_white_space =
797     ignore_blank_lines && IGNORE_TRAILING_SPACE <= ignore_white_space;
798   bool skip_leading_white_space =
799     skip_white_space && IGNORE_SPACE_CHANGE <= ignore_white_space;
800 
801   char const * const *linbuf0 = files[0].linbuf;  /* Help the compiler.  */
802   char const * const *linbuf1 = files[1].linbuf;
803 
804   show_from = show_to = 0;
805 
806   *first0 = hunk->line0;
807   *first1 = hunk->line1;
808 
809   next = hunk;
810   do
811     {
812       l0 = next->line0 + next->deleted - 1;
813       l1 = next->line1 + next->inserted - 1;
814       show_from += next->deleted;
815       show_to += next->inserted;
816 
817       for (i = next->line0; i <= l0 && trivial; i++)
818 	{
819 	  char const *line = linbuf0[i];
820 	  char const *newline = linbuf0[i + 1] - 1;
821 	  size_t len = newline - line;
822 	  char const *p = line;
823 	  if (skip_white_space)
824 	    for (; *p != '\n'; p++)
825 	      if (! isspace ((unsigned char) *p))
826 		{
827 		  if (! skip_leading_white_space)
828 		    p = line;
829 		  break;
830 		}
831 	  if (newline - p != trivial_length
832 	      && (! ignore_regexp.fastmap
833 		  || re_search (&ignore_regexp, line, len, 0, len, 0) < 0))
834 	    trivial = 0;
835 	}
836 
837       for (i = next->line1; i <= l1 && trivial; i++)
838 	{
839 	  char const *line = linbuf1[i];
840 	  char const *newline = linbuf1[i + 1] - 1;
841 	  size_t len = newline - line;
842 	  char const *p = line;
843 	  if (skip_white_space)
844 	    for (; *p != '\n'; p++)
845 	      if (! isspace ((unsigned char) *p))
846 		{
847 		  if (! skip_leading_white_space)
848 		    p = line;
849 		  break;
850 		}
851 	  if (newline - p != trivial_length
852 	      && (! ignore_regexp.fastmap
853 		  || re_search (&ignore_regexp, line, len, 0, len, 0) < 0))
854 	    trivial = 0;
855 	}
856     }
857   while ((next = next->link) != 0);
858 
859   *last0 = l0;
860   *last1 = l1;
861 
862   /* If all inserted or deleted lines are ignorable,
863      tell the caller to ignore this hunk.  */
864 
865   if (trivial)
866     return UNCHANGED;
867 
868   return (show_from ? OLD : UNCHANGED) | (show_to ? NEW : UNCHANGED);
869 }
870 
871 /* Concatenate three strings, returning a newly malloc'd string.  */
872 
873 char *
874 concat (char const *s1, char const *s2, char const *s3)
875 {
876   char *new = xmalloc (strlen (s1) + strlen (s2) + strlen (s3) + 1);
877   sprintf (new, "%s%s%s", s1, s2, s3);
878   return new;
879 }
880 
881 /* Yield a new block of SIZE bytes, initialized to zero.  */
882 
883 void *
884 zalloc (size_t size)
885 {
886   void *p = xmalloc (size);
887   memset (p, 0, size);
888   return p;
889 }
890 
891 void
892 debug_script (struct change *sp)
893 {
894   fflush (stdout);
895 
896   for (; sp; sp = sp->link)
897     {
898       long int line0 = sp->line0;
899       long int line1 = sp->line1;
900       long int deleted = sp->deleted;
901       long int inserted = sp->inserted;
902       fprintf (stderr, "%3ld %3ld delete %ld insert %ld\n",
903 	       line0, line1, deleted, inserted);
904     }
905 
906   fflush (stderr);
907 }
908