xref: /dragonfly/contrib/diffutils/src/util.c (revision 029e6489)
1 /* Support routines for GNU DIFF.
2 
3    Copyright (C) 1988-1989, 1992-1995, 1998, 2001-2002, 2004, 2006, 2009-2013,
4    2015-2018 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 "argmatch.h"
23 #include "die.h"
24 #include <dirname.h>
25 #include <error.h>
26 #include <system-quote.h>
27 #include <xalloc.h>
28 #include "xvasprintf.h"
29 #include <signal.h>
30 
31 /* Use SA_NOCLDSTOP as a proxy for whether the sigaction machinery is
32    present.  */
33 #ifndef SA_NOCLDSTOP
34 # define SA_NOCLDSTOP 0
35 # define sigprocmask(How, Set, Oset) /* empty */
36 # define sigset_t int
37 # if ! HAVE_SIGINTERRUPT
38 #  define siginterrupt(sig, flag) /* empty */
39 # endif
40 #endif
41 
42 #ifndef SA_RESTART
43 # define SA_RESTART 0
44 #endif
45 
46 char const pr_program[] = PR_PROGRAM;
47 
48 /* Queue up one-line messages to be printed at the end,
49    when -l is specified.  Each message is recorded with a 'struct msg'.  */
50 
51 struct msg
52 {
53   struct msg *next;
54   char args[1]; /* Format + 4 args, each '\0' terminated, concatenated.  */
55 };
56 
57 /* Head of the chain of queues messages.  */
58 
59 static struct msg *msg_chain;
60 
61 /* Tail of the chain of queues messages.  */
62 
63 static struct msg **msg_chain_end = &msg_chain;
64 
65 /* Use when a system call returns non-zero status.
66    NAME should normally be the file name.  */
67 
68 void
69 perror_with_name (char const *name)
70 {
71   error (0, errno, "%s", name);
72 }
73 
74 /* Use when a system call returns non-zero status and that is fatal.  */
75 
76 void
77 pfatal_with_name (char const *name)
78 {
79   int e = errno;
80   print_message_queue ();
81   die (EXIT_TROUBLE, e, "%s", name);
82 }
83 
84 /* Print an error message containing MSGID, then exit.  */
85 
86 void
87 fatal (char const *msgid)
88 {
89   print_message_queue ();
90   die (EXIT_TROUBLE, 0, "%s", _(msgid));
91 }
92 
93 /* Like printf, except if -l in effect then save the message and print later.
94    This is used for things like "Only in ...".  */
95 
96 void
97 message (char const *format_msgid, char const *arg1, char const *arg2)
98 {
99   message5 (format_msgid, arg1, arg2, 0, 0);
100 }
101 
102 void
103 message5 (char const *format_msgid, char const *arg1, char const *arg2,
104 	  char const *arg3, char const *arg4)
105 {
106   if (paginate)
107     {
108       char *p;
109       char const *arg[5];
110       int i;
111       size_t size[5];
112       size_t total_size = offsetof (struct msg, args);
113       struct msg *new;
114 
115       arg[0] = format_msgid;
116       arg[1] = arg1;
117       arg[2] = arg2;
118       arg[3] = arg3 ? arg3 : "";
119       arg[4] = arg4 ? arg4 : "";
120 
121       for (i = 0;  i < 5;  i++)
122 	total_size += size[i] = strlen (arg[i]) + 1;
123 
124       new = xmalloc (total_size);
125 
126       for (i = 0, p = new->args;  i < 5;  p += size[i++])
127 	memcpy (p, arg[i], size[i]);
128 
129       *msg_chain_end = new;
130       new->next = 0;
131       msg_chain_end = &new->next;
132     }
133   else
134     {
135       if (sdiff_merge_assist)
136 	putchar (' ');
137       printf (_(format_msgid), arg1, arg2, arg3, arg4);
138     }
139 }
140 
141 /* Output all the messages that were saved up by calls to 'message'.  */
142 
143 void
144 print_message_queue (void)
145 {
146   char const *arg[5];
147   int i;
148   struct msg *m = msg_chain;
149 
150   while (m)
151     {
152       struct msg *next = m->next;
153       arg[0] = m->args;
154       for (i = 0;  i < 4;  i++)
155 	arg[i + 1] = arg[i] + strlen (arg[i]) + 1;
156       printf (_(arg[0]), arg[1], arg[2], arg[3], arg[4]);
157       free (m);
158       m = next;
159     }
160 }
161 
162 /* The set of signals that are caught.  */
163 
164 static sigset_t caught_signals;
165 
166 /* If nonzero, the value of the pending fatal signal.  */
167 
168 static sig_atomic_t volatile interrupt_signal;
169 
170 /* A count of the number of pending stop signals that have been received.  */
171 
172 static sig_atomic_t volatile stop_signal_count;
173 
174 /* An ordinary signal was received; arrange for the program to exit.  */
175 
176 static void
177 sighandler (int sig)
178 {
179   if (! SA_NOCLDSTOP)
180     signal (sig, SIG_IGN);
181   if (! interrupt_signal)
182     interrupt_signal = sig;
183 }
184 
185 /* A SIGTSTP was received; arrange for the program to suspend itself.  */
186 
187 static void
188 stophandler (int sig)
189 {
190   if (! SA_NOCLDSTOP)
191     signal (sig, stophandler);
192   if (! interrupt_signal)
193     stop_signal_count++;
194 }
195 /* Process any pending signals.  If signals are caught, this function
196    should be called periodically.  Ideally there should never be an
197    unbounded amount of time when signals are not being processed.
198    Signal handling can restore the default colors, so callers must
199    immediately change colors after invoking this function.  */
200 
201 static void
202 process_signals (void)
203 {
204   while (interrupt_signal || stop_signal_count)
205     {
206       int sig;
207       int stops;
208       sigset_t oldset;
209 
210       set_color_context (RESET_CONTEXT);
211       fflush (stdout);
212 
213       sigprocmask (SIG_BLOCK, &caught_signals, &oldset);
214 
215       /* Reload interrupt_signal and stop_signal_count, in case a new
216          signal was handled before sigprocmask took effect.  */
217       sig = interrupt_signal;
218       stops = stop_signal_count;
219 
220       /* SIGTSTP is special, since the application can receive that signal
221          more than once.  In this case, don't set the signal handler to the
222          default.  Instead, just raise the uncatchable SIGSTOP.  */
223       if (stops)
224         {
225           stop_signal_count = stops - 1;
226           sig = SIGSTOP;
227         }
228       else
229         signal (sig, SIG_DFL);
230 
231       /* Exit or suspend the program.  */
232       raise (sig);
233       sigprocmask (SIG_SETMASK, &oldset, NULL);
234 
235       /* If execution reaches here, then the program has been
236          continued (after being suspended).  */
237     }
238 }
239 
240 static void
241 install_signal_handlers (void)
242 {
243   /* The signals that are trapped, and the number of such signals.  */
244   static int const sig[] =
245     {
246       /* This one is handled specially.  */
247       SIGTSTP,
248 
249       /* The usual suspects.  */
250       SIGALRM, SIGHUP, SIGINT, SIGPIPE, SIGQUIT, SIGTERM,
251 #ifdef SIGPOLL
252       SIGPOLL,
253 #endif
254 #ifdef SIGPROF
255       SIGPROF,
256 #endif
257 #ifdef SIGVTALRM
258       SIGVTALRM,
259 #endif
260 #ifdef SIGXCPU
261       SIGXCPU,
262 #endif
263 #ifdef SIGXFSZ
264       SIGXFSZ,
265 #endif
266     };
267   enum { nsigs = sizeof (sig) / sizeof *(sig) };
268 
269 #if ! SA_NOCLDSTOP
270   bool caught_sig[nsigs];
271 #endif
272   {
273     int j;
274 #if SA_NOCLDSTOP
275     struct sigaction act;
276 
277     sigemptyset (&caught_signals);
278     for (j = 0; j < nsigs; j++)
279       {
280         sigaction (sig[j], NULL, &act);
281         if (act.sa_handler != SIG_IGN)
282           sigaddset (&caught_signals, sig[j]);
283       }
284 
285     act.sa_mask = caught_signals;
286     act.sa_flags = SA_RESTART;
287 
288     for (j = 0; j < nsigs; j++)
289       if (sigismember (&caught_signals, sig[j]))
290         {
291           act.sa_handler = sig[j] == SIGTSTP ? stophandler : sighandler;
292           sigaction (sig[j], &act, NULL);
293         }
294 #else
295     for (j = 0; j < nsigs; j++)
296       {
297         caught_sig[j] = (signal (sig[j], SIG_IGN) != SIG_IGN);
298         if (caught_sig[j])
299           {
300             signal (sig[j], sig[j] == SIGTSTP ? stophandler : sighandler);
301             siginterrupt (sig[j], 0);
302           }
303       }
304 #endif
305     }
306 }
307 
308 static char const *current_name0;
309 static char const *current_name1;
310 static bool currently_recursive;
311 static bool colors_enabled;
312 
313 static struct color_ext_type *color_ext_list = NULL;
314 
315 struct bin_str
316   {
317     size_t len;			/* Number of bytes */
318     const char *string;		/* Pointer to the same */
319   };
320 
321 struct color_ext_type
322   {
323     struct bin_str ext;		/* The extension we're looking for */
324     struct bin_str seq;		/* The sequence to output when we do */
325     struct color_ext_type *next;	/* Next in list */
326   };
327 
328 /* Parse a string as part of the --palette argument; this may involve
329    decoding all kinds of escape characters.  If equals_end is set an
330    unescaped equal sign ends the string, otherwise only a : or \0
331    does.  Set *OUTPUT_COUNT to the number of bytes output.  Return
332    true if successful.
333 
334    The resulting string is *not* null-terminated, but may contain
335    embedded nulls.
336 
337    Note that both dest and src are char **; on return they point to
338    the first free byte after the array and the character that ended
339    the input string, respectively.  */
340 
341 static bool
342 get_funky_string (char **dest, const char **src, bool equals_end,
343                   size_t *output_count)
344 {
345   char num;			/* For numerical codes */
346   size_t count;			/* Something to count with */
347   enum {
348     ST_GND, ST_BACKSLASH, ST_OCTAL, ST_HEX, ST_CARET, ST_END, ST_ERROR
349   } state;
350   const char *p;
351   char *q;
352 
353   p = *src;			/* We don't want to double-indirect */
354   q = *dest;			/* the whole darn time.  */
355 
356   count = 0;			/* No characters counted in yet.  */
357   num = 0;
358 
359   state = ST_GND;		/* Start in ground state.  */
360   while (state < ST_END)
361     {
362       switch (state)
363         {
364         case ST_GND:		/* Ground state (no escapes) */
365           switch (*p)
366             {
367             case ':':
368             case '\0':
369               state = ST_END;	/* End of string */
370               break;
371             case '\\':
372               state = ST_BACKSLASH; /* Backslash scape sequence */
373               ++p;
374               break;
375             case '^':
376               state = ST_CARET; /* Caret escape */
377               ++p;
378               break;
379             case '=':
380               if (equals_end)
381                 {
382                   state = ST_END; /* End */
383                   break;
384                 }
385               FALLTHROUGH;
386             default:
387               *(q++) = *(p++);
388               ++count;
389               break;
390             }
391           break;
392 
393         case ST_BACKSLASH:	/* Backslash escaped character */
394           switch (*p)
395             {
396             case '0':
397             case '1':
398             case '2':
399             case '3':
400             case '4':
401             case '5':
402             case '6':
403             case '7':
404               state = ST_OCTAL;	/* Octal sequence */
405               num = *p - '0';
406               break;
407             case 'x':
408             case 'X':
409               state = ST_HEX;	/* Hex sequence */
410               num = 0;
411               break;
412             case 'a':		/* Bell */
413               num = '\a';
414               break;
415             case 'b':		/* Backspace */
416               num = '\b';
417               break;
418             case 'e':		/* Escape */
419               num = 27;
420               break;
421             case 'f':		/* Form feed */
422               num = '\f';
423               break;
424             case 'n':		/* Newline */
425               num = '\n';
426               break;
427             case 'r':		/* Carriage return */
428               num = '\r';
429               break;
430             case 't':		/* Tab */
431               num = '\t';
432               break;
433             case 'v':		/* Vtab */
434               num = '\v';
435               break;
436             case '?':		/* Delete */
437               num = 127;
438               break;
439             case '_':		/* Space */
440               num = ' ';
441               break;
442             case '\0':		/* End of string */
443               state = ST_ERROR;	/* Error! */
444               break;
445             default:		/* Escaped character like \ ^ : = */
446               num = *p;
447               break;
448             }
449           if (state == ST_BACKSLASH)
450             {
451               *(q++) = num;
452               ++count;
453               state = ST_GND;
454             }
455           ++p;
456           break;
457 
458         case ST_OCTAL:		/* Octal sequence */
459           if (*p < '0' || *p > '7')
460             {
461               *(q++) = num;
462               ++count;
463               state = ST_GND;
464             }
465           else
466             num = (num << 3) + (*(p++) - '0');
467           break;
468 
469         case ST_HEX:		/* Hex sequence */
470           switch (*p)
471             {
472             case '0':
473             case '1':
474             case '2':
475             case '3':
476             case '4':
477             case '5':
478             case '6':
479             case '7':
480             case '8':
481             case '9':
482               num = (num << 4) + (*(p++) - '0');
483               break;
484             case 'a':
485             case 'b':
486             case 'c':
487             case 'd':
488             case 'e':
489             case 'f':
490               num = (num << 4) + (*(p++) - 'a') + 10;
491               break;
492             case 'A':
493             case 'B':
494             case 'C':
495             case 'D':
496             case 'E':
497             case 'F':
498               num = (num << 4) + (*(p++) - 'A') + 10;
499               break;
500             default:
501               *(q++) = num;
502               ++count;
503               state = ST_GND;
504               break;
505             }
506           break;
507 
508         case ST_CARET:		/* Caret escape */
509           state = ST_GND;	/* Should be the next state... */
510           if (*p >= '@' && *p <= '~')
511             {
512               *(q++) = *(p++) & 037;
513               ++count;
514             }
515           else if (*p == '?')
516             {
517               *(q++) = 127;
518               ++count;
519             }
520           else
521             state = ST_ERROR;
522           break;
523 
524         default:
525           abort ();
526         }
527     }
528 
529   *dest = q;
530   *src = p;
531   *output_count = count;
532 
533   return state != ST_ERROR;
534 }
535 
536 enum parse_state
537   {
538     PS_START = 1,
539     PS_2,
540     PS_3,
541     PS_4,
542     PS_DONE,
543     PS_FAIL
544   };
545 
546 #define LEN_STR_PAIR(s) sizeof (s) - 1, s
547 
548 static struct bin_str color_indicator[] =
549   {
550     { LEN_STR_PAIR ("\033[") },		/* lc: Left of color sequence */
551     { LEN_STR_PAIR ("m") },		/* rc: Right of color sequence */
552     { 0, NULL },			/* ec: End color (replaces lc+rs+rc) */
553     { LEN_STR_PAIR ("0") },		/* rs: Reset to ordinary colors */
554     { LEN_STR_PAIR ("1") },		/* hd: Header */
555     { LEN_STR_PAIR ("32") },		/* ad: Add line */
556     { LEN_STR_PAIR ("31") },		/* de: Delete line */
557     { LEN_STR_PAIR ("36") },		/* ln: Line number */
558   };
559 
560 static const char *const indicator_name[] =
561   {
562     "lc", "rc", "ec", "rs", "hd", "ad", "de", "ln", NULL
563   };
564 ARGMATCH_VERIFY (indicator_name, color_indicator);
565 
566 static char const *color_palette;
567 
568 void
569 set_color_palette (char const *palette)
570 {
571   color_palette = palette;
572 }
573 
574 static void
575 parse_diff_color (void)
576 {
577   char *color_buf;
578   const char *p;		/* Pointer to character being parsed */
579   char *buf;			/* color_buf buffer pointer */
580   int ind_no;			/* Indicator number */
581   char label[3];		/* Indicator label */
582   struct color_ext_type *ext;	/* Extension we are working on */
583 
584   if ((p = color_palette) == NULL || *p == '\0')
585     return;
586 
587   ext = NULL;
588   strcpy (label, "??");
589 
590   /* This is an overly conservative estimate, but any possible
591      --palette string will *not* generate a color_buf longer than
592      itself, so it is a safe way of allocating a buffer in
593      advance.  */
594   buf = color_buf = xstrdup (p);
595 
596   enum parse_state state = PS_START;
597   while (true)
598     {
599       switch (state)
600         {
601         case PS_START:		/* First label character */
602           switch (*p)
603             {
604             case ':':
605               ++p;
606               break;
607 
608             case '*':
609               /* Allocate new extension block and add to head of
610                  linked list (this way a later definition will
611                  override an earlier one, which can be useful for
612                  having terminal-specific defs override global).  */
613 
614               ext = xmalloc (sizeof *ext);
615               ext->next = color_ext_list;
616               color_ext_list = ext;
617 
618               ++p;
619               ext->ext.string = buf;
620 
621               state = (get_funky_string (&buf, &p, true, &ext->ext.len)
622                        ? PS_4 : PS_FAIL);
623               break;
624 
625             case '\0':
626               state = PS_DONE;	/* Done! */
627               goto done;
628 
629             default:	/* Assume it is file type label */
630               label[0] = *(p++);
631               state = PS_2;
632               break;
633             }
634           break;
635 
636         case PS_2:		/* Second label character */
637           if (*p)
638             {
639               label[1] = *(p++);
640               state = PS_3;
641             }
642           else
643             state = PS_FAIL;	/* Error */
644           break;
645 
646         case PS_3:		/* Equal sign after indicator label */
647           state = PS_FAIL;	/* Assume failure...  */
648           if (*(p++) == '=')/* It *should* be...  */
649             {
650               for (ind_no = 0; indicator_name[ind_no] != NULL; ++ind_no)
651                 {
652                   if (STREQ (label, indicator_name[ind_no]))
653                     {
654                       color_indicator[ind_no].string = buf;
655                       state = (get_funky_string (&buf, &p, false,
656                                                  &color_indicator[ind_no].len)
657                                ? PS_START : PS_FAIL);
658                       break;
659                     }
660                 }
661               if (state == PS_FAIL)
662                 error (0, 0, _("unrecognized prefix: %s"), label);
663             }
664           break;
665 
666         case PS_4:		/* Equal sign after *.ext */
667           if (*(p++) == '=')
668             {
669               ext->seq.string = buf;
670               state = (get_funky_string (&buf, &p, false, &ext->seq.len)
671                        ? PS_START : PS_FAIL);
672             }
673           else
674             state = PS_FAIL;
675           break;
676 
677         case PS_FAIL:
678           goto done;
679 
680         default:
681           abort ();
682         }
683     }
684  done:
685 
686   if (state == PS_FAIL)
687     {
688       struct color_ext_type *e;
689       struct color_ext_type *e2;
690 
691       error (0, 0,
692              _("unparsable value for --palette"));
693       free (color_buf);
694       for (e = color_ext_list; e != NULL; /* empty */)
695         {
696           e2 = e;
697           e = e->next;
698           free (e2);
699         }
700       colors_enabled = false;
701     }
702 }
703 
704 static void
705 check_color_output (bool is_pipe)
706 {
707   bool output_is_tty;
708 
709   if (! outfile || colors_style == NEVER)
710     return;
711 
712   output_is_tty = presume_output_tty || (!is_pipe && isatty (fileno (outfile)));
713 
714   colors_enabled = (colors_style == ALWAYS
715                     || (colors_style == AUTO && output_is_tty));
716 
717   if (colors_enabled)
718     parse_diff_color ();
719 
720   if (output_is_tty)
721     install_signal_handlers ();
722 }
723 
724 /* Call before outputting the results of comparing files NAME0 and NAME1
725    to set up OUTFILE, the stdio stream for the output to go to.
726 
727    Usually, OUTFILE is just stdout.  But when -l was specified
728    we fork off a 'pr' and make OUTFILE a pipe to it.
729    'pr' then outputs to our stdout.  */
730 
731 void
732 setup_output (char const *name0, char const *name1, bool recursive)
733 {
734   current_name0 = name0;
735   current_name1 = name1;
736   currently_recursive = recursive;
737   outfile = 0;
738 }
739 
740 #if HAVE_WORKING_FORK
741 static pid_t pr_pid;
742 #endif
743 
744 static char c_escape_char (char c)
745 {
746   switch (c) {
747     case '\a': return 'a';
748     case '\b': return 'b';
749     case '\t': return 't';
750     case '\n': return 'n';
751     case '\v': return 'v';
752     case '\f': return 'f';
753     case '\r': return 'r';
754     case '"': return '"';
755     case '\\': return '\\';
756     default:
757       return c < 32;
758   }
759 }
760 
761 static char *
762 c_escape (char const *str)
763 {
764   char const *s;
765   size_t plus = 0;
766   bool must_quote = false;
767 
768   for (s = str; *s; s++)
769     {
770       char c = *s;
771 
772       if (c == ' ')
773 	{
774 	  must_quote = true;
775 	  continue;
776 	}
777       switch (c_escape_char (*s))
778 	{
779 	  case 1:
780 	    plus += 3;
781 	    /* fall through */
782 	  case 0:
783 	    break;
784 	  default:
785 	    plus++;
786 	    break;
787 	}
788     }
789 
790   if (must_quote || plus)
791     {
792       size_t s_len = s - str;
793       char *buffer = xmalloc (s_len + plus + 3);
794       char *b = buffer;
795 
796       *b++ = '"';
797       for (s = str; *s; s++)
798 	{
799 	  char c = *s;
800 	  char escape = c_escape_char (c);
801 
802 	  switch (escape)
803 	    {
804 	      case 0:
805 		*b++ = c;
806 		break;
807 	      case 1:
808 		*b++ = '\\';
809 		*b++ = ((c >> 6) & 03) + '0';
810 		*b++ = ((c >> 3) & 07) + '0';
811 		*b++ = ((c >> 0) & 07) + '0';
812 		break;
813 	      default:
814 		*b++ = '\\';
815 		*b++ = escape;
816 		break;
817 	    }
818 	}
819       *b++ = '"';
820       *b = 0;
821       return buffer;
822     }
823 
824   return (char *) str;
825 }
826 
827 void
828 begin_output (void)
829 {
830   char *names[2];
831   char *name;
832 
833   if (outfile != 0)
834     return;
835 
836   names[0] = c_escape (current_name0);
837   names[1] = c_escape (current_name1);
838 
839   /* Construct the header of this piece of diff.  */
840   /* POSIX 1003.1-2001 specifies this format.  But there are some bugs in
841      the standard: it says that we must print only the last component
842      of the pathnames, and it requires two spaces after "diff" if
843      there are no options.  These requirements are silly and do not
844      match historical practice.  */
845   name = xasprintf ("diff%s %s %s", switch_string, names[0], names[1]);
846 
847   if (paginate)
848     {
849       char const *argv[4];
850 
851       if (fflush (stdout) != 0)
852 	pfatal_with_name (_("write failed"));
853 
854       argv[0] = pr_program;
855       argv[1] = "-h";
856       argv[2] = name;
857       argv[3] = 0;
858 
859       /* Make OUTFILE a pipe to a subsidiary 'pr'.  */
860       {
861 #if HAVE_WORKING_FORK
862 	int pipes[2];
863 
864 	if (pipe (pipes) != 0)
865 	  pfatal_with_name ("pipe");
866 
867 	pr_pid = fork ();
868 	if (pr_pid < 0)
869 	  pfatal_with_name ("fork");
870 
871 	if (pr_pid == 0)
872 	  {
873 	    close (pipes[1]);
874 	    if (pipes[0] != STDIN_FILENO)
875 	      {
876 		if (dup2 (pipes[0], STDIN_FILENO) < 0)
877 		  pfatal_with_name ("dup2");
878 		close (pipes[0]);
879 	      }
880 
881 	    execv (pr_program, (char **) argv);
882 	    _exit (errno == ENOENT ? 127 : 126);
883 	  }
884 	else
885 	  {
886 	    close (pipes[0]);
887 	    outfile = fdopen (pipes[1], "w");
888 	    if (!outfile)
889 	      pfatal_with_name ("fdopen");
890 	    check_color_output (true);
891 	  }
892 #else
893 	char *command = system_quote_argv (SCI_SYSTEM, (char **) argv);
894 	errno = 0;
895 	outfile = popen (command, "w");
896 	if (!outfile)
897 	  pfatal_with_name (command);
898 	check_color_output (true);
899 	free (command);
900 #endif
901       }
902     }
903   else
904     {
905 
906       /* If -l was not specified, output the diff straight to 'stdout'.  */
907 
908       outfile = stdout;
909       check_color_output (false);
910 
911       /* If handling multiple files (because scanning a directory),
912 	 print which files the following output is about.  */
913       if (currently_recursive)
914 	printf ("%s\n", name);
915     }
916 
917   free (name);
918 
919   /* A special header is needed at the beginning of context output.  */
920   switch (output_style)
921     {
922     case OUTPUT_CONTEXT:
923       print_context_header (files, (char const *const *)names, false);
924       break;
925 
926     case OUTPUT_UNIFIED:
927       print_context_header (files, (char const *const *)names, true);
928       break;
929 
930     default:
931       break;
932     }
933 
934   if (names[0] != current_name0)
935     free (names[0]);
936   if (names[1] != current_name1)
937     free (names[1]);
938 }
939 
940 /* Call after the end of output of diffs for one file.
941    Close OUTFILE and get rid of the 'pr' subfork.  */
942 
943 void
944 finish_output (void)
945 {
946   if (outfile != 0 && outfile != stdout)
947     {
948       int status;
949       int wstatus;
950       int werrno = 0;
951       if (ferror (outfile))
952 	fatal ("write failed");
953 #if ! HAVE_WORKING_FORK
954       wstatus = pclose (outfile);
955       if (wstatus == -1)
956 	werrno = errno;
957 #else
958       if (fclose (outfile) != 0)
959 	pfatal_with_name (_("write failed"));
960       if (waitpid (pr_pid, &wstatus, 0) < 0)
961 	pfatal_with_name ("waitpid");
962 #endif
963       status = (! werrno && WIFEXITED (wstatus)
964 		? WEXITSTATUS (wstatus)
965 		: INT_MAX);
966       if (status)
967 	die (EXIT_TROUBLE, werrno,
968 	       _(status == 126
969 		 ? "subsidiary program '%s' could not be invoked"
970 		 : status == 127
971 		 ? "subsidiary program '%s' not found"
972 		 : status == INT_MAX
973 		 ? "subsidiary program '%s' failed"
974 		 : "subsidiary program '%s' failed (exit status %d)"),
975 	       pr_program, status);
976     }
977 
978   outfile = 0;
979 }
980 
981 /* Compare two lines (typically one from each input file)
982    according to the command line options.
983    For efficiency, this is invoked only when the lines do not match exactly
984    but an option like -i might cause us to ignore the difference.
985    Return nonzero if the lines differ.  */
986 
987 bool
988 lines_differ (char const *s1, char const *s2)
989 {
990   register char const *t1 = s1;
991   register char const *t2 = s2;
992   size_t column = 0;
993 
994   while (1)
995     {
996       register unsigned char c1 = *t1++;
997       register unsigned char c2 = *t2++;
998 
999       /* Test for exact char equality first, since it's a common case.  */
1000       if (c1 != c2)
1001 	{
1002 	  switch (ignore_white_space)
1003 	    {
1004 	    case IGNORE_ALL_SPACE:
1005 	      /* For -w, just skip past any white space.  */
1006 	      while (isspace (c1) && c1 != '\n') c1 = *t1++;
1007 	      while (isspace (c2) && c2 != '\n') c2 = *t2++;
1008 	      break;
1009 
1010 	    case IGNORE_SPACE_CHANGE:
1011 	      /* For -b, advance past any sequence of white space in
1012 		 line 1 and consider it just one space, or nothing at
1013 		 all if it is at the end of the line.  */
1014 	      if (isspace (c1))
1015 		{
1016 		  while (c1 != '\n')
1017 		    {
1018 		      c1 = *t1++;
1019 		      if (! isspace (c1))
1020 			{
1021 			  --t1;
1022 			  c1 = ' ';
1023 			  break;
1024 			}
1025 		    }
1026 		}
1027 
1028 	      /* Likewise for line 2.  */
1029 	      if (isspace (c2))
1030 		{
1031 		  while (c2 != '\n')
1032 		    {
1033 		      c2 = *t2++;
1034 		      if (! isspace (c2))
1035 			{
1036 			  --t2;
1037 			  c2 = ' ';
1038 			  break;
1039 			}
1040 		    }
1041 		}
1042 
1043 	      if (c1 != c2)
1044 		{
1045 		  /* If we went too far when doing the simple test
1046 		     for equality, go back to the first non-white-space
1047 		     character in both sides and try again.  */
1048 		  if (c2 == ' ' && c1 != '\n'
1049 		      && s1 + 1 < t1
1050 		      && isspace ((unsigned char) t1[-2]))
1051 		    {
1052 		      --t1;
1053 		      continue;
1054 		    }
1055 		  if (c1 == ' ' && c2 != '\n'
1056 		      && s2 + 1 < t2
1057 		      && isspace ((unsigned char) t2[-2]))
1058 		    {
1059 		      --t2;
1060 		      continue;
1061 		    }
1062 		}
1063 
1064 	      break;
1065 
1066 	    case IGNORE_TRAILING_SPACE:
1067 	    case IGNORE_TAB_EXPANSION_AND_TRAILING_SPACE:
1068 	      if (isspace (c1) && isspace (c2))
1069 		{
1070 		  unsigned char c;
1071 		  if (c1 != '\n')
1072 		    {
1073 		      char const *p = t1;
1074 		      while ((c = *p) != '\n' && isspace (c))
1075 			++p;
1076 		      if (c != '\n')
1077 			break;
1078 		    }
1079 		  if (c2 != '\n')
1080 		    {
1081 		      char const *p = t2;
1082 		      while ((c = *p) != '\n' && isspace (c))
1083 			++p;
1084 		      if (c != '\n')
1085 			break;
1086 		    }
1087 		  /* Both lines have nothing but whitespace left.  */
1088 		  return false;
1089 		}
1090 	      if (ignore_white_space == IGNORE_TRAILING_SPACE)
1091 		break;
1092 	      FALLTHROUGH;
1093 	    case IGNORE_TAB_EXPANSION:
1094 	      if ((c1 == ' ' && c2 == '\t')
1095 		  || (c1 == '\t' && c2 == ' '))
1096 		{
1097 		  size_t column2 = column;
1098 		  for (;; c1 = *t1++)
1099 		    {
1100 		      if (c1 == ' ')
1101 			column++;
1102 		      else if (c1 == '\t')
1103 			column += tabsize - column % tabsize;
1104 		      else
1105 			break;
1106 		    }
1107 		  for (;; c2 = *t2++)
1108 		    {
1109 		      if (c2 == ' ')
1110 			column2++;
1111 		      else if (c2 == '\t')
1112 			column2 += tabsize - column2 % tabsize;
1113 		      else
1114 			break;
1115 		    }
1116 		  if (column != column2)
1117 		    return true;
1118 		}
1119 	      break;
1120 
1121 	    case IGNORE_NO_WHITE_SPACE:
1122 	      break;
1123 	    }
1124 
1125 	  /* Lowercase all letters if -i is specified.  */
1126 
1127 	  if (ignore_case)
1128 	    {
1129 	      c1 = tolower (c1);
1130 	      c2 = tolower (c2);
1131 	    }
1132 
1133 	  if (c1 != c2)
1134 	    break;
1135 	}
1136       if (c1 == '\n')
1137 	return false;
1138 
1139       column += c1 == '\t' ? tabsize - column % tabsize : 1;
1140     }
1141 
1142   return true;
1143 }
1144 
1145 /* Find the consecutive changes at the start of the script START.
1146    Return the last link before the first gap.  */
1147 
1148 struct change * _GL_ATTRIBUTE_CONST
1149 find_change (struct change *start)
1150 {
1151   return start;
1152 }
1153 
1154 struct change * _GL_ATTRIBUTE_CONST
1155 find_reverse_change (struct change *start)
1156 {
1157   return start;
1158 }
1159 
1160 /* Divide SCRIPT into pieces by calling HUNKFUN and
1161    print each piece with PRINTFUN.
1162    Both functions take one arg, an edit script.
1163 
1164    HUNKFUN is called with the tail of the script
1165    and returns the last link that belongs together with the start
1166    of the tail.
1167 
1168    PRINTFUN takes a subscript which belongs together (with a null
1169    link at the end) and prints it.  */
1170 
1171 void
1172 print_script (struct change *script,
1173 	      struct change * (*hunkfun) (struct change *),
1174 	      void (*printfun) (struct change *))
1175 {
1176   struct change *next = script;
1177 
1178   while (next)
1179     {
1180       struct change *this, *end;
1181 
1182       /* Find a set of changes that belong together.  */
1183       this = next;
1184       end = (*hunkfun) (next);
1185 
1186       /* Disconnect them from the rest of the changes,
1187 	 making them a hunk, and remember the rest for next iteration.  */
1188       next = end->link;
1189       end->link = 0;
1190 #ifdef DEBUG
1191       debug_script (this);
1192 #endif
1193 
1194       /* Print this hunk.  */
1195       (*printfun) (this);
1196 
1197       /* Reconnect the script so it will all be freed properly.  */
1198       end->link = next;
1199     }
1200 }
1201 
1202 /* Print the text of a single line LINE,
1203    flagging it with the characters in LINE_FLAG (which say whether
1204    the line is inserted, deleted, changed, etc.).  LINE_FLAG must not
1205    end in a blank, unless it is a single blank.  */
1206 
1207 void
1208 print_1_line (char const *line_flag, char const *const *line)
1209 {
1210   print_1_line_nl (line_flag, line, false);
1211 }
1212 
1213 /* Print the text of a single line LINE,
1214    flagging it with the characters in LINE_FLAG (which say whether
1215    the line is inserted, deleted, changed, etc.).  LINE_FLAG must not
1216    end in a blank, unless it is a single blank.  If SKIP_NL is set, then
1217    the final '\n' is not printed.  */
1218 
1219 void
1220 print_1_line_nl (char const *line_flag, char const *const *line, bool skip_nl)
1221 {
1222   char const *base = line[0], *limit = line[1]; /* Help the compiler.  */
1223   FILE *out = outfile; /* Help the compiler some more.  */
1224   char const *flag_format = 0;
1225 
1226   /* If -T was specified, use a Tab between the line-flag and the text.
1227      Otherwise use a Space (as Unix diff does).
1228      Print neither space nor tab if line-flags are empty.
1229      But omit trailing blanks if requested.  */
1230 
1231   if (line_flag && *line_flag)
1232     {
1233       char const *flag_format_1 = flag_format = initial_tab ? "%s\t" : "%s ";
1234       char const *line_flag_1 = line_flag;
1235 
1236       if (suppress_blank_empty && **line == '\n')
1237 	{
1238 	  flag_format_1 = "%s";
1239 
1240 	  /* This hack to omit trailing blanks takes advantage of the
1241 	     fact that the only way that LINE_FLAG can end in a blank
1242 	     is when LINE_FLAG consists of a single blank.  */
1243 	  line_flag_1 += *line_flag_1 == ' ';
1244 	}
1245 
1246       fprintf (out, flag_format_1, line_flag_1);
1247     }
1248 
1249   output_1_line (base, limit - (skip_nl && limit[-1] == '\n'), flag_format, line_flag);
1250 
1251   if ((!line_flag || line_flag[0]) && limit[-1] != '\n')
1252     {
1253       set_color_context (RESET_CONTEXT);
1254       fprintf (out, "\n\\ %s\n", _("No newline at end of file"));
1255     }
1256 }
1257 
1258 /* Output a line from BASE up to LIMIT.
1259    With -t, expand white space characters to spaces, and if FLAG_FORMAT
1260    is nonzero, output it with argument LINE_FLAG after every
1261    internal carriage return, so that tab stops continue to line up.  */
1262 
1263 void
1264 output_1_line (char const *base, char const *limit, char const *flag_format,
1265 	       char const *line_flag)
1266 {
1267   const size_t MAX_CHUNK = 1024;
1268   if (!expand_tabs)
1269     {
1270       size_t left = limit - base;
1271       while (left)
1272         {
1273           size_t to_write = MIN (left, MAX_CHUNK);
1274           size_t written = fwrite (base, sizeof (char), to_write, outfile);
1275           if (written < to_write)
1276             return;
1277           base += written;
1278           left -= written;
1279           process_signals ();
1280         }
1281     }
1282   else
1283     {
1284       register FILE *out = outfile;
1285       register unsigned char c;
1286       register char const *t = base;
1287       register size_t column = 0;
1288       size_t tab_size = tabsize;
1289       size_t counter_proc_signals = 0;
1290 
1291       while (t < limit)
1292         {
1293           counter_proc_signals++;
1294           if (counter_proc_signals == MAX_CHUNK)
1295             {
1296               process_signals ();
1297               counter_proc_signals = 0;
1298             }
1299 
1300           switch ((c = *t++))
1301             {
1302             case '\t':
1303               {
1304                 size_t spaces = tab_size - column % tab_size;
1305                 column += spaces;
1306                 do
1307                   putc (' ', out);
1308                 while (--spaces);
1309               }
1310               break;
1311 
1312             case '\r':
1313               putc (c, out);
1314               if (flag_format && t < limit && *t != '\n')
1315                 fprintf (out, flag_format, line_flag);
1316               column = 0;
1317               break;
1318 
1319             case '\b':
1320               if (column == 0)
1321                 continue;
1322               column--;
1323               putc (c, out);
1324               break;
1325 
1326             default:
1327               column += isprint (c) != 0;
1328               putc (c, out);
1329               break;
1330             }
1331         }
1332     }
1333 }
1334 
1335 enum indicator_no
1336   {
1337     C_LEFT, C_RIGHT, C_END, C_RESET, C_HEADER, C_ADD, C_DELETE, C_LINE
1338   };
1339 
1340 static void
1341 put_indicator (const struct bin_str *ind)
1342 {
1343   fwrite (ind->string, ind->len, 1, outfile);
1344 }
1345 
1346 static enum color_context last_context = RESET_CONTEXT;
1347 
1348 void
1349 set_color_context (enum color_context color_context)
1350 {
1351   if (color_context != RESET_CONTEXT)
1352     process_signals ();
1353   if (colors_enabled && last_context != color_context)
1354     {
1355       put_indicator (&color_indicator[C_LEFT]);
1356       switch (color_context)
1357         {
1358         case HEADER_CONTEXT:
1359           put_indicator (&color_indicator[C_HEADER]);
1360           break;
1361 
1362         case LINE_NUMBER_CONTEXT:
1363           put_indicator (&color_indicator[C_LINE]);
1364           break;
1365 
1366         case ADD_CONTEXT:
1367           put_indicator (&color_indicator[C_ADD]);
1368           break;
1369 
1370         case DELETE_CONTEXT:
1371           put_indicator (&color_indicator[C_DELETE]);
1372           break;
1373 
1374         case RESET_CONTEXT:
1375           put_indicator (&color_indicator[C_RESET]);
1376           break;
1377 
1378         default:
1379           abort ();
1380         }
1381       put_indicator (&color_indicator[C_RIGHT]);
1382       last_context = color_context;
1383     }
1384 }
1385 
1386 
1387 char const change_letter[] = { 0, 'd', 'a', 'c' };
1388 
1389 /* Translate an internal line number (an index into diff's table of lines)
1390    into an actual line number in the input file.
1391    The internal line number is I.  FILE points to the data on the file.
1392 
1393    Internal line numbers count from 0 starting after the prefix.
1394    Actual line numbers count from 1 within the entire file.  */
1395 
1396 lin _GL_ATTRIBUTE_PURE
1397 translate_line_number (struct file_data const *file, lin i)
1398 {
1399   return i + file->prefix_lines + 1;
1400 }
1401 
1402 /* Translate a line number range.  This is always done for printing,
1403    so for convenience translate to printint rather than lin, so that the
1404    caller can use printf with "%"pI"d" without casting.  */
1405 
1406 void
1407 translate_range (struct file_data const *file,
1408 		 lin a, lin b,
1409 		 printint *aptr, printint *bptr)
1410 {
1411   *aptr = translate_line_number (file, a - 1) + 1;
1412   *bptr = translate_line_number (file, b + 1) - 1;
1413 }
1414 
1415 /* Print a pair of line numbers with SEPCHAR, translated for file FILE.
1416    If the two numbers are identical, print just one number.
1417 
1418    Args A and B are internal line numbers.
1419    We print the translated (real) line numbers.  */
1420 
1421 void
1422 print_number_range (char sepchar, struct file_data *file, lin a, lin b)
1423 {
1424   printint trans_a, trans_b;
1425   translate_range (file, a, b, &trans_a, &trans_b);
1426 
1427   /* Note: we can have B < A in the case of a range of no lines.
1428      In this case, we should print the line number before the range,
1429      which is B.  */
1430   if (trans_b > trans_a)
1431     fprintf (outfile, "%"pI"d%c%"pI"d", trans_a, sepchar, trans_b);
1432   else
1433     fprintf (outfile, "%"pI"d", trans_b);
1434 }
1435 
1436 /* Look at a hunk of edit script and report the range of lines in each file
1437    that it applies to.  HUNK is the start of the hunk, which is a chain
1438    of 'struct change'.  The first and last line numbers of file 0 are stored in
1439    *FIRST0 and *LAST0, and likewise for file 1 in *FIRST1 and *LAST1.
1440    Note that these are internal line numbers that count from 0.
1441 
1442    If no lines from file 0 are deleted, then FIRST0 is LAST0+1.
1443 
1444    Return UNCHANGED if only ignorable lines are inserted or deleted,
1445    OLD if lines of file 0 are deleted,
1446    NEW if lines of file 1 are inserted,
1447    and CHANGED if both kinds of changes are found. */
1448 
1449 enum changes
1450 analyze_hunk (struct change *hunk,
1451 	      lin *first0, lin *last0,
1452 	      lin *first1, lin *last1)
1453 {
1454   struct change *next;
1455   lin l0, l1;
1456   lin show_from, show_to;
1457   lin i;
1458   bool trivial = ignore_blank_lines || ignore_regexp.fastmap;
1459   size_t trivial_length = ignore_blank_lines - 1;
1460     /* If 0, ignore zero-length lines;
1461        if SIZE_MAX, do not ignore lines just because of their length.  */
1462 
1463   bool skip_white_space =
1464     ignore_blank_lines && IGNORE_TRAILING_SPACE <= ignore_white_space;
1465   bool skip_leading_white_space =
1466     skip_white_space && IGNORE_SPACE_CHANGE <= ignore_white_space;
1467 
1468   char const * const *linbuf0 = files[0].linbuf;  /* Help the compiler.  */
1469   char const * const *linbuf1 = files[1].linbuf;
1470 
1471   show_from = show_to = 0;
1472 
1473   *first0 = hunk->line0;
1474   *first1 = hunk->line1;
1475 
1476   next = hunk;
1477   do
1478     {
1479       l0 = next->line0 + next->deleted - 1;
1480       l1 = next->line1 + next->inserted - 1;
1481       show_from += next->deleted;
1482       show_to += next->inserted;
1483 
1484       for (i = next->line0; i <= l0 && trivial; i++)
1485 	{
1486 	  char const *line = linbuf0[i];
1487 	  char const *lastbyte = linbuf0[i + 1] - 1;
1488 	  char const *newline = lastbyte + (*lastbyte != '\n');
1489 	  size_t len = newline - line;
1490 	  char const *p = line;
1491 	  if (skip_white_space)
1492 	    for (; *p != '\n'; p++)
1493 	      if (! isspace ((unsigned char) *p))
1494 		{
1495 		  if (! skip_leading_white_space)
1496 		    p = line;
1497 		  break;
1498 		}
1499 	  if (newline - p != trivial_length
1500 	      && (! ignore_regexp.fastmap
1501 		  || re_search (&ignore_regexp, line, len, 0, len, 0) < 0))
1502 	    trivial = 0;
1503 	}
1504 
1505       for (i = next->line1; i <= l1 && trivial; i++)
1506 	{
1507 	  char const *line = linbuf1[i];
1508 	  char const *lastbyte = linbuf1[i + 1] - 1;
1509 	  char const *newline = lastbyte + (*lastbyte != '\n');
1510 	  size_t len = newline - line;
1511 	  char const *p = line;
1512 	  if (skip_white_space)
1513 	    for (; *p != '\n'; p++)
1514 	      if (! isspace ((unsigned char) *p))
1515 		{
1516 		  if (! skip_leading_white_space)
1517 		    p = line;
1518 		  break;
1519 		}
1520 	  if (newline - p != trivial_length
1521 	      && (! ignore_regexp.fastmap
1522 		  || re_search (&ignore_regexp, line, len, 0, len, 0) < 0))
1523 	    trivial = 0;
1524 	}
1525     }
1526   while ((next = next->link) != 0);
1527 
1528   *last0 = l0;
1529   *last1 = l1;
1530 
1531   /* If all inserted or deleted lines are ignorable,
1532      tell the caller to ignore this hunk.  */
1533 
1534   if (trivial)
1535     return UNCHANGED;
1536 
1537   return (show_from ? OLD : UNCHANGED) | (show_to ? NEW : UNCHANGED);
1538 }
1539 
1540 /* Concatenate three strings, returning a newly malloc'd string.  */
1541 
1542 char *
1543 concat (char const *s1, char const *s2, char const *s3)
1544 {
1545   char *new = xmalloc (strlen (s1) + strlen (s2) + strlen (s3) + 1);
1546   sprintf (new, "%s%s%s", s1, s2, s3);
1547   return new;
1548 }
1549 
1550 /* Yield a new block of SIZE bytes, initialized to zero.  */
1551 
1552 void *
1553 zalloc (size_t size)
1554 {
1555   void *p = xmalloc (size);
1556   memset (p, 0, size);
1557   return p;
1558 }
1559 
1560 void
1561 debug_script (struct change *sp)
1562 {
1563   fflush (stdout);
1564 
1565   for (; sp; sp = sp->link)
1566     {
1567       printint line0 = sp->line0;
1568       printint line1 = sp->line1;
1569       printint deleted = sp->deleted;
1570       printint inserted = sp->inserted;
1571       fprintf (stderr, "%3"pI"d %3"pI"d delete %"pI"d insert %"pI"d\n",
1572 	       line0, line1, deleted, inserted);
1573     }
1574 
1575   fflush (stderr);
1576 }
1577