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