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
perror_with_name(char const * name)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
pfatal_with_name(char const * name)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
fatal(char const * msgid)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
message(char const * format_msgid,char const * arg1,char const * arg2)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
message5(char const * format_msgid,char const * arg1,char const * arg2,char const * arg3,char const * arg4)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
print_message_queue(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
sighandler(int sig)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
stophandler(int sig)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
process_signals(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
install_signal_handlers(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
get_funky_string(char ** dest,const char ** src,bool equals_end,size_t * output_count)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
set_color_palette(char const * palette)569 set_color_palette (char const *palette)
570 {
571 color_palette = palette;
572 }
573
574 static void
parse_diff_color(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
check_color_output(bool is_pipe)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
setup_output(char const * name0,char const * name1,bool recursive)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
c_escape_char(char c)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 *
c_escape(char const * str)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
begin_output(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
finish_output(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
lines_differ(char const * s1,char const * s2)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
find_change(struct change * start)1149 find_change (struct change *start)
1150 {
1151 return start;
1152 }
1153
1154 struct change * _GL_ATTRIBUTE_CONST
find_reverse_change(struct change * start)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
print_script(struct change * script,struct change * (* hunkfun)(struct change *),void (* printfun)(struct change *))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
print_1_line(char const * line_flag,char const * const * line)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
print_1_line_nl(char const * line_flag,char const * const * line,bool skip_nl)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
output_1_line(char const * base,char const * limit,char const * flag_format,char const * line_flag)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
put_indicator(const struct bin_str * ind)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
set_color_context(enum color_context color_context)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
translate_line_number(struct file_data const * file,lin i)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
translate_range(struct file_data const * file,lin a,lin b,printint * aptr,printint * bptr)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
print_number_range(char sepchar,struct file_data * file,lin a,lin b)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
analyze_hunk(struct change * hunk,lin * first0,lin * last0,lin * first1,lin * last1)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 *
concat(char const * s1,char const * s2,char const * s3)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 *
zalloc(size_t size)1553 zalloc (size_t size)
1554 {
1555 void *p = xmalloc (size);
1556 memset (p, 0, size);
1557 return p;
1558 }
1559
1560 void
debug_script(struct change * sp)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