rc.conf: Add and document the missing root_rw_mount=YES
[dragonfly.git] / contrib / diffutils / src / util.c
blob4f4d9bb285eb1a5f46230312d0aba4c8c3fa5f27
1 /* Support routines for GNU DIFF.
3 Copyright (C) 1988-1989, 1992-1995, 1998, 2001-2002, 2004, 2006, 2009-2013,
4 2015-2018 Free Software Foundation, Inc.
6 This file is part of GNU DIFF.
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.
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.
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/>. */
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>
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
42 #ifndef SA_RESTART
43 # define SA_RESTART 0
44 #endif
46 char const pr_program[] = PR_PROGRAM;
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'. */
51 struct msg
53 struct msg *next;
54 char args[1]; /* Format + 4 args, each '\0' terminated, concatenated. */
57 /* Head of the chain of queues messages. */
59 static struct msg *msg_chain;
61 /* Tail of the chain of queues messages. */
63 static struct msg **msg_chain_end = &msg_chain;
65 /* Use when a system call returns non-zero status.
66 NAME should normally be the file name. */
68 void
69 perror_with_name (char const *name)
71 error (0, errno, "%s", name);
74 /* Use when a system call returns non-zero status and that is fatal. */
76 void
77 pfatal_with_name (char const *name)
79 int e = errno;
80 print_message_queue ();
81 die (EXIT_TROUBLE, e, "%s", name);
84 /* Print an error message containing MSGID, then exit. */
86 void
87 fatal (char const *msgid)
89 print_message_queue ();
90 die (EXIT_TROUBLE, 0, "%s", _(msgid));
93 /* Like printf, except if -l in effect then save the message and print later.
94 This is used for things like "Only in ...". */
96 void
97 message (char const *format_msgid, char const *arg1, char const *arg2)
99 message5 (format_msgid, arg1, arg2, 0, 0);
102 void
103 message5 (char const *format_msgid, char const *arg1, char const *arg2,
104 char const *arg3, char const *arg4)
106 if (paginate)
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;
115 arg[0] = format_msgid;
116 arg[1] = arg1;
117 arg[2] = arg2;
118 arg[3] = arg3 ? arg3 : "";
119 arg[4] = arg4 ? arg4 : "";
121 for (i = 0; i < 5; i++)
122 total_size += size[i] = strlen (arg[i]) + 1;
124 new = xmalloc (total_size);
126 for (i = 0, p = new->args; i < 5; p += size[i++])
127 memcpy (p, arg[i], size[i]);
129 *msg_chain_end = new;
130 new->next = 0;
131 msg_chain_end = &new->next;
133 else
135 if (sdiff_merge_assist)
136 putchar (' ');
137 printf (_(format_msgid), arg1, arg2, arg3, arg4);
141 /* Output all the messages that were saved up by calls to 'message'. */
143 void
144 print_message_queue (void)
146 char const *arg[5];
147 int i;
148 struct msg *m = msg_chain;
150 while (m)
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;
162 /* The set of signals that are caught. */
164 static sigset_t caught_signals;
166 /* If nonzero, the value of the pending fatal signal. */
168 static sig_atomic_t volatile interrupt_signal;
170 /* A count of the number of pending stop signals that have been received. */
172 static sig_atomic_t volatile stop_signal_count;
174 /* An ordinary signal was received; arrange for the program to exit. */
176 static void
177 sighandler (int sig)
179 if (! SA_NOCLDSTOP)
180 signal (sig, SIG_IGN);
181 if (! interrupt_signal)
182 interrupt_signal = sig;
185 /* A SIGTSTP was received; arrange for the program to suspend itself. */
187 static void
188 stophandler (int sig)
190 if (! SA_NOCLDSTOP)
191 signal (sig, stophandler);
192 if (! interrupt_signal)
193 stop_signal_count++;
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. */
201 static void
202 process_signals (void)
204 while (interrupt_signal || stop_signal_count)
206 int sig;
207 int stops;
208 sigset_t oldset;
210 set_color_context (RESET_CONTEXT);
211 fflush (stdout);
213 sigprocmask (SIG_BLOCK, &caught_signals, &oldset);
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;
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)
225 stop_signal_count = stops - 1;
226 sig = SIGSTOP;
228 else
229 signal (sig, SIG_DFL);
231 /* Exit or suspend the program. */
232 raise (sig);
233 sigprocmask (SIG_SETMASK, &oldset, NULL);
235 /* If execution reaches here, then the program has been
236 continued (after being suspended). */
240 static void
241 install_signal_handlers (void)
243 /* The signals that are trapped, and the number of such signals. */
244 static int const sig[] =
246 /* This one is handled specially. */
247 SIGTSTP,
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
267 enum { nsigs = sizeof (sig) / sizeof *(sig) };
269 #if ! SA_NOCLDSTOP
270 bool caught_sig[nsigs];
271 #endif
273 int j;
274 #if SA_NOCLDSTOP
275 struct sigaction act;
277 sigemptyset (&caught_signals);
278 for (j = 0; j < nsigs; j++)
280 sigaction (sig[j], NULL, &act);
281 if (act.sa_handler != SIG_IGN)
282 sigaddset (&caught_signals, sig[j]);
285 act.sa_mask = caught_signals;
286 act.sa_flags = SA_RESTART;
288 for (j = 0; j < nsigs; j++)
289 if (sigismember (&caught_signals, sig[j]))
291 act.sa_handler = sig[j] == SIGTSTP ? stophandler : sighandler;
292 sigaction (sig[j], &act, NULL);
294 #else
295 for (j = 0; j < nsigs; j++)
297 caught_sig[j] = (signal (sig[j], SIG_IGN) != SIG_IGN);
298 if (caught_sig[j])
300 signal (sig[j], sig[j] == SIGTSTP ? stophandler : sighandler);
301 siginterrupt (sig[j], 0);
304 #endif
308 static char const *current_name0;
309 static char const *current_name1;
310 static bool currently_recursive;
311 static bool colors_enabled;
313 static struct color_ext_type *color_ext_list = NULL;
315 struct bin_str
317 size_t len; /* Number of bytes */
318 const char *string; /* Pointer to the same */
321 struct color_ext_type
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 */
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.
334 The resulting string is *not* null-terminated, but may contain
335 embedded nulls.
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. */
341 static bool
342 get_funky_string (char **dest, const char **src, bool equals_end,
343 size_t *output_count)
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;
353 p = *src; /* We don't want to double-indirect */
354 q = *dest; /* the whole darn time. */
356 count = 0; /* No characters counted in yet. */
357 num = 0;
359 state = ST_GND; /* Start in ground state. */
360 while (state < ST_END)
362 switch (state)
364 case ST_GND: /* Ground state (no escapes) */
365 switch (*p)
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)
382 state = ST_END; /* End */
383 break;
385 FALLTHROUGH;
386 default:
387 *(q++) = *(p++);
388 ++count;
389 break;
391 break;
393 case ST_BACKSLASH: /* Backslash escaped character */
394 switch (*p)
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;
449 if (state == ST_BACKSLASH)
451 *(q++) = num;
452 ++count;
453 state = ST_GND;
455 ++p;
456 break;
458 case ST_OCTAL: /* Octal sequence */
459 if (*p < '0' || *p > '7')
461 *(q++) = num;
462 ++count;
463 state = ST_GND;
465 else
466 num = (num << 3) + (*(p++) - '0');
467 break;
469 case ST_HEX: /* Hex sequence */
470 switch (*p)
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;
506 break;
508 case ST_CARET: /* Caret escape */
509 state = ST_GND; /* Should be the next state... */
510 if (*p >= '@' && *p <= '~')
512 *(q++) = *(p++) & 037;
513 ++count;
515 else if (*p == '?')
517 *(q++) = 127;
518 ++count;
520 else
521 state = ST_ERROR;
522 break;
524 default:
525 abort ();
529 *dest = q;
530 *src = p;
531 *output_count = count;
533 return state != ST_ERROR;
536 enum parse_state
538 PS_START = 1,
539 PS_2,
540 PS_3,
541 PS_4,
542 PS_DONE,
543 PS_FAIL
546 #define LEN_STR_PAIR(s) sizeof (s) - 1, s
548 static struct bin_str color_indicator[] =
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 */
560 static const char *const indicator_name[] =
562 "lc", "rc", "ec", "rs", "hd", "ad", "de", "ln", NULL
564 ARGMATCH_VERIFY (indicator_name, color_indicator);
566 static char const *color_palette;
568 void
569 set_color_palette (char const *palette)
571 color_palette = palette;
574 static void
575 parse_diff_color (void)
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 */
584 if ((p = color_palette) == NULL || *p == '\0')
585 return;
587 ext = NULL;
588 strcpy (label, "??");
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);
596 enum parse_state state = PS_START;
597 while (true)
599 switch (state)
601 case PS_START: /* First label character */
602 switch (*p)
604 case ':':
605 ++p;
606 break;
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). */
614 ext = xmalloc (sizeof *ext);
615 ext->next = color_ext_list;
616 color_ext_list = ext;
618 ++p;
619 ext->ext.string = buf;
621 state = (get_funky_string (&buf, &p, true, &ext->ext.len)
622 ? PS_4 : PS_FAIL);
623 break;
625 case '\0':
626 state = PS_DONE; /* Done! */
627 goto done;
629 default: /* Assume it is file type label */
630 label[0] = *(p++);
631 state = PS_2;
632 break;
634 break;
636 case PS_2: /* Second label character */
637 if (*p)
639 label[1] = *(p++);
640 state = PS_3;
642 else
643 state = PS_FAIL; /* Error */
644 break;
646 case PS_3: /* Equal sign after indicator label */
647 state = PS_FAIL; /* Assume failure... */
648 if (*(p++) == '=')/* It *should* be... */
650 for (ind_no = 0; indicator_name[ind_no] != NULL; ++ind_no)
652 if (STREQ (label, indicator_name[ind_no]))
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;
661 if (state == PS_FAIL)
662 error (0, 0, _("unrecognized prefix: %s"), label);
664 break;
666 case PS_4: /* Equal sign after *.ext */
667 if (*(p++) == '=')
669 ext->seq.string = buf;
670 state = (get_funky_string (&buf, &p, false, &ext->seq.len)
671 ? PS_START : PS_FAIL);
673 else
674 state = PS_FAIL;
675 break;
677 case PS_FAIL:
678 goto done;
680 default:
681 abort ();
684 done:
686 if (state == PS_FAIL)
688 struct color_ext_type *e;
689 struct color_ext_type *e2;
691 error (0, 0,
692 _("unparsable value for --palette"));
693 free (color_buf);
694 for (e = color_ext_list; e != NULL; /* empty */)
696 e2 = e;
697 e = e->next;
698 free (e2);
700 colors_enabled = false;
704 static void
705 check_color_output (bool is_pipe)
707 bool output_is_tty;
709 if (! outfile || colors_style == NEVER)
710 return;
712 output_is_tty = presume_output_tty || (!is_pipe && isatty (fileno (outfile)));
714 colors_enabled = (colors_style == ALWAYS
715 || (colors_style == AUTO && output_is_tty));
717 if (colors_enabled)
718 parse_diff_color ();
720 if (output_is_tty)
721 install_signal_handlers ();
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.
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. */
731 void
732 setup_output (char const *name0, char const *name1, bool recursive)
734 current_name0 = name0;
735 current_name1 = name1;
736 currently_recursive = recursive;
737 outfile = 0;
740 #if HAVE_WORKING_FORK
741 static pid_t pr_pid;
742 #endif
744 static char c_escape_char (char c)
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;
761 static char *
762 c_escape (char const *str)
764 char const *s;
765 size_t plus = 0;
766 bool must_quote = false;
768 for (s = str; *s; s++)
770 char c = *s;
772 if (c == ' ')
774 must_quote = true;
775 continue;
777 switch (c_escape_char (*s))
779 case 1:
780 plus += 3;
781 /* fall through */
782 case 0:
783 break;
784 default:
785 plus++;
786 break;
790 if (must_quote || plus)
792 size_t s_len = s - str;
793 char *buffer = xmalloc (s_len + plus + 3);
794 char *b = buffer;
796 *b++ = '"';
797 for (s = str; *s; s++)
799 char c = *s;
800 char escape = c_escape_char (c);
802 switch (escape)
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;
819 *b++ = '"';
820 *b = 0;
821 return buffer;
824 return (char *) str;
827 void
828 begin_output (void)
830 char *names[2];
831 char *name;
833 if (outfile != 0)
834 return;
836 names[0] = c_escape (current_name0);
837 names[1] = c_escape (current_name1);
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]);
847 if (paginate)
849 char const *argv[4];
851 if (fflush (stdout) != 0)
852 pfatal_with_name (_("write failed"));
854 argv[0] = pr_program;
855 argv[1] = "-h";
856 argv[2] = name;
857 argv[3] = 0;
859 /* Make OUTFILE a pipe to a subsidiary 'pr'. */
861 #if HAVE_WORKING_FORK
862 int pipes[2];
864 if (pipe (pipes) != 0)
865 pfatal_with_name ("pipe");
867 pr_pid = fork ();
868 if (pr_pid < 0)
869 pfatal_with_name ("fork");
871 if (pr_pid == 0)
873 close (pipes[1]);
874 if (pipes[0] != STDIN_FILENO)
876 if (dup2 (pipes[0], STDIN_FILENO) < 0)
877 pfatal_with_name ("dup2");
878 close (pipes[0]);
881 execv (pr_program, (char **) argv);
882 _exit (errno == ENOENT ? 127 : 126);
884 else
886 close (pipes[0]);
887 outfile = fdopen (pipes[1], "w");
888 if (!outfile)
889 pfatal_with_name ("fdopen");
890 check_color_output (true);
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
903 else
906 /* If -l was not specified, output the diff straight to 'stdout'. */
908 outfile = stdout;
909 check_color_output (false);
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);
917 free (name);
919 /* A special header is needed at the beginning of context output. */
920 switch (output_style)
922 case OUTPUT_CONTEXT:
923 print_context_header (files, (char const *const *)names, false);
924 break;
926 case OUTPUT_UNIFIED:
927 print_context_header (files, (char const *const *)names, true);
928 break;
930 default:
931 break;
934 if (names[0] != current_name0)
935 free (names[0]);
936 if (names[1] != current_name1)
937 free (names[1]);
940 /* Call after the end of output of diffs for one file.
941 Close OUTFILE and get rid of the 'pr' subfork. */
943 void
944 finish_output (void)
946 if (outfile != 0 && outfile != stdout)
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);
978 outfile = 0;
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. */
987 bool
988 lines_differ (char const *s1, char const *s2)
990 register char const *t1 = s1;
991 register char const *t2 = s2;
992 size_t column = 0;
994 while (1)
996 register unsigned char c1 = *t1++;
997 register unsigned char c2 = *t2++;
999 /* Test for exact char equality first, since it's a common case. */
1000 if (c1 != c2)
1002 switch (ignore_white_space)
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;
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))
1016 while (c1 != '\n')
1018 c1 = *t1++;
1019 if (! isspace (c1))
1021 --t1;
1022 c1 = ' ';
1023 break;
1028 /* Likewise for line 2. */
1029 if (isspace (c2))
1031 while (c2 != '\n')
1033 c2 = *t2++;
1034 if (! isspace (c2))
1036 --t2;
1037 c2 = ' ';
1038 break;
1043 if (c1 != c2)
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]))
1052 --t1;
1053 continue;
1055 if (c1 == ' ' && c2 != '\n'
1056 && s2 + 1 < t2
1057 && isspace ((unsigned char) t2[-2]))
1059 --t2;
1060 continue;
1064 break;
1066 case IGNORE_TRAILING_SPACE:
1067 case IGNORE_TAB_EXPANSION_AND_TRAILING_SPACE:
1068 if (isspace (c1) && isspace (c2))
1070 unsigned char c;
1071 if (c1 != '\n')
1073 char const *p = t1;
1074 while ((c = *p) != '\n' && isspace (c))
1075 ++p;
1076 if (c != '\n')
1077 break;
1079 if (c2 != '\n')
1081 char const *p = t2;
1082 while ((c = *p) != '\n' && isspace (c))
1083 ++p;
1084 if (c != '\n')
1085 break;
1087 /* Both lines have nothing but whitespace left. */
1088 return false;
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 == ' '))
1097 size_t column2 = column;
1098 for (;; c1 = *t1++)
1100 if (c1 == ' ')
1101 column++;
1102 else if (c1 == '\t')
1103 column += tabsize - column % tabsize;
1104 else
1105 break;
1107 for (;; c2 = *t2++)
1109 if (c2 == ' ')
1110 column2++;
1111 else if (c2 == '\t')
1112 column2 += tabsize - column2 % tabsize;
1113 else
1114 break;
1116 if (column != column2)
1117 return true;
1119 break;
1121 case IGNORE_NO_WHITE_SPACE:
1122 break;
1125 /* Lowercase all letters if -i is specified. */
1127 if (ignore_case)
1129 c1 = tolower (c1);
1130 c2 = tolower (c2);
1133 if (c1 != c2)
1134 break;
1136 if (c1 == '\n')
1137 return false;
1139 column += c1 == '\t' ? tabsize - column % tabsize : 1;
1142 return true;
1145 /* Find the consecutive changes at the start of the script START.
1146 Return the last link before the first gap. */
1148 struct change * _GL_ATTRIBUTE_CONST
1149 find_change (struct change *start)
1151 return start;
1154 struct change * _GL_ATTRIBUTE_CONST
1155 find_reverse_change (struct change *start)
1157 return start;
1160 /* Divide SCRIPT into pieces by calling HUNKFUN and
1161 print each piece with PRINTFUN.
1162 Both functions take one arg, an edit script.
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.
1168 PRINTFUN takes a subscript which belongs together (with a null
1169 link at the end) and prints it. */
1171 void
1172 print_script (struct change *script,
1173 struct change * (*hunkfun) (struct change *),
1174 void (*printfun) (struct change *))
1176 struct change *next = script;
1178 while (next)
1180 struct change *this, *end;
1182 /* Find a set of changes that belong together. */
1183 this = next;
1184 end = (*hunkfun) (next);
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
1194 /* Print this hunk. */
1195 (*printfun) (this);
1197 /* Reconnect the script so it will all be freed properly. */
1198 end->link = next;
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. */
1207 void
1208 print_1_line (char const *line_flag, char const *const *line)
1210 print_1_line_nl (line_flag, line, false);
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. */
1219 void
1220 print_1_line_nl (char const *line_flag, char const *const *line, bool skip_nl)
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;
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. */
1231 if (line_flag && *line_flag)
1233 char const *flag_format_1 = flag_format = initial_tab ? "%s\t" : "%s ";
1234 char const *line_flag_1 = line_flag;
1236 if (suppress_blank_empty && **line == '\n')
1238 flag_format_1 = "%s";
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 == ' ';
1246 fprintf (out, flag_format_1, line_flag_1);
1249 output_1_line (base, limit - (skip_nl && limit[-1] == '\n'), flag_format, line_flag);
1251 if ((!line_flag || line_flag[0]) && limit[-1] != '\n')
1253 set_color_context (RESET_CONTEXT);
1254 fprintf (out, "\n\\ %s\n", _("No newline at end of file"));
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. */
1263 void
1264 output_1_line (char const *base, char const *limit, char const *flag_format,
1265 char const *line_flag)
1267 const size_t MAX_CHUNK = 1024;
1268 if (!expand_tabs)
1270 size_t left = limit - base;
1271 while (left)
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 ();
1282 else
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;
1291 while (t < limit)
1293 counter_proc_signals++;
1294 if (counter_proc_signals == MAX_CHUNK)
1296 process_signals ();
1297 counter_proc_signals = 0;
1300 switch ((c = *t++))
1302 case '\t':
1304 size_t spaces = tab_size - column % tab_size;
1305 column += spaces;
1307 putc (' ', out);
1308 while (--spaces);
1310 break;
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;
1319 case '\b':
1320 if (column == 0)
1321 continue;
1322 column--;
1323 putc (c, out);
1324 break;
1326 default:
1327 column += isprint (c) != 0;
1328 putc (c, out);
1329 break;
1335 enum indicator_no
1337 C_LEFT, C_RIGHT, C_END, C_RESET, C_HEADER, C_ADD, C_DELETE, C_LINE
1340 static void
1341 put_indicator (const struct bin_str *ind)
1343 fwrite (ind->string, ind->len, 1, outfile);
1346 static enum color_context last_context = RESET_CONTEXT;
1348 void
1349 set_color_context (enum color_context color_context)
1351 if (color_context != RESET_CONTEXT)
1352 process_signals ();
1353 if (colors_enabled && last_context != color_context)
1355 put_indicator (&color_indicator[C_LEFT]);
1356 switch (color_context)
1358 case HEADER_CONTEXT:
1359 put_indicator (&color_indicator[C_HEADER]);
1360 break;
1362 case LINE_NUMBER_CONTEXT:
1363 put_indicator (&color_indicator[C_LINE]);
1364 break;
1366 case ADD_CONTEXT:
1367 put_indicator (&color_indicator[C_ADD]);
1368 break;
1370 case DELETE_CONTEXT:
1371 put_indicator (&color_indicator[C_DELETE]);
1372 break;
1374 case RESET_CONTEXT:
1375 put_indicator (&color_indicator[C_RESET]);
1376 break;
1378 default:
1379 abort ();
1381 put_indicator (&color_indicator[C_RIGHT]);
1382 last_context = color_context;
1387 char const change_letter[] = { 0, 'd', 'a', 'c' };
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.
1393 Internal line numbers count from 0 starting after the prefix.
1394 Actual line numbers count from 1 within the entire file. */
1396 lin _GL_ATTRIBUTE_PURE
1397 translate_line_number (struct file_data const *file, lin i)
1399 return i + file->prefix_lines + 1;
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. */
1406 void
1407 translate_range (struct file_data const *file,
1408 lin a, lin b,
1409 printint *aptr, printint *bptr)
1411 *aptr = translate_line_number (file, a - 1) + 1;
1412 *bptr = translate_line_number (file, b + 1) - 1;
1415 /* Print a pair of line numbers with SEPCHAR, translated for file FILE.
1416 If the two numbers are identical, print just one number.
1418 Args A and B are internal line numbers.
1419 We print the translated (real) line numbers. */
1421 void
1422 print_number_range (char sepchar, struct file_data *file, lin a, lin b)
1424 printint trans_a, trans_b;
1425 translate_range (file, a, b, &trans_a, &trans_b);
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);
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.
1442 If no lines from file 0 are deleted, then FIRST0 is LAST0+1.
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. */
1449 enum changes
1450 analyze_hunk (struct change *hunk,
1451 lin *first0, lin *last0,
1452 lin *first1, lin *last1)
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. */
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;
1468 char const * const *linbuf0 = files[0].linbuf; /* Help the compiler. */
1469 char const * const *linbuf1 = files[1].linbuf;
1471 show_from = show_to = 0;
1473 *first0 = hunk->line0;
1474 *first1 = hunk->line1;
1476 next = hunk;
1479 l0 = next->line0 + next->deleted - 1;
1480 l1 = next->line1 + next->inserted - 1;
1481 show_from += next->deleted;
1482 show_to += next->inserted;
1484 for (i = next->line0; i <= l0 && trivial; i++)
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))
1495 if (! skip_leading_white_space)
1496 p = line;
1497 break;
1499 if (newline - p != trivial_length
1500 && (! ignore_regexp.fastmap
1501 || re_search (&ignore_regexp, line, len, 0, len, 0) < 0))
1502 trivial = 0;
1505 for (i = next->line1; i <= l1 && trivial; i++)
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))
1516 if (! skip_leading_white_space)
1517 p = line;
1518 break;
1520 if (newline - p != trivial_length
1521 && (! ignore_regexp.fastmap
1522 || re_search (&ignore_regexp, line, len, 0, len, 0) < 0))
1523 trivial = 0;
1526 while ((next = next->link) != 0);
1528 *last0 = l0;
1529 *last1 = l1;
1531 /* If all inserted or deleted lines are ignorable,
1532 tell the caller to ignore this hunk. */
1534 if (trivial)
1535 return UNCHANGED;
1537 return (show_from ? OLD : UNCHANGED) | (show_to ? NEW : UNCHANGED);
1540 /* Concatenate three strings, returning a newly malloc'd string. */
1542 char *
1543 concat (char const *s1, char const *s2, char const *s3)
1545 char *new = xmalloc (strlen (s1) + strlen (s2) + strlen (s3) + 1);
1546 sprintf (new, "%s%s%s", s1, s2, s3);
1547 return new;
1550 /* Yield a new block of SIZE bytes, initialized to zero. */
1552 void *
1553 zalloc (size_t size)
1555 void *p = xmalloc (size);
1556 memset (p, 0, size);
1557 return p;
1560 void
1561 debug_script (struct change *sp)
1563 fflush (stdout);
1565 for (; sp; sp = sp->link)
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);
1575 fflush (stderr);