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/>. */
26 #include <system-quote.h>
28 #include "xvasprintf.h"
31 /* Use SA_NOCLDSTOP as a proxy for whether the sigaction machinery is
34 # define SA_NOCLDSTOP 0
35 # define sigprocmask(How, Set, Oset) /* empty */
37 # if ! HAVE_SIGINTERRUPT
38 # define siginterrupt(sig, flag) /* empty */
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'. */
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. */
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. */
77 pfatal_with_name (char const *name)
80 print_message_queue ();
81 die (EXIT_TROUBLE, e, "%s", name);
84 /* Print an error message containing MSGID, then exit. */
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 ...". */
97 message (char const *format_msgid, char const *arg1, char const *arg2)
99 message5 (format_msgid, arg1, arg2, 0, 0);
103 message5 (char const *format_msgid, char const *arg1, char const *arg2,
104 char const *arg3, char const *arg4)
112 size_t total_size = offsetof (struct msg, args);
115 arg[0] = format_msgid;
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;
131 msg_chain_end = &new->next;
135 if (sdiff_merge_assist)
137 printf (_(format_msgid), arg1, arg2, arg3, arg4);
141 /* Output all the messages that were saved up by calls to 'message'. */
144 print_message_queue (void)
148 struct msg *m = msg_chain;
152 struct msg *next = m->next;
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]);
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. */
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. */
188 stophandler (int sig)
191 signal (sig, stophandler);
192 if (! interrupt_signal)
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. */
202 process_signals (void)
204 while (interrupt_signal || stop_signal_count)
210 set_color_context (RESET_CONTEXT);
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. */
225 stop_signal_count = stops - 1;
229 signal (sig, SIG_DFL);
231 /* Exit or suspend the program. */
233 sigprocmask (SIG_SETMASK, &oldset, NULL);
235 /* If execution reaches here, then the program has been
236 continued (after being suspended). */
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. */
249 /* The usual suspects. */
250 SIGALRM, SIGHUP, SIGINT, SIGPIPE, SIGQUIT, SIGTERM,
267 enum { nsigs = sizeof (sig) / sizeof *(sig) };
270 bool caught_sig[nsigs];
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);
295 for (j = 0; j < nsigs; j++)
297 caught_sig[j] = (signal (sig[j], SIG_IGN) != SIG_IGN);
300 signal (sig[j], sig[j] == SIGTSTP ? stophandler : sighandler);
301 siginterrupt (sig[j], 0);
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;
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
334 The resulting string is *not* null-terminated, but may contain
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. */
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 */
348 ST_GND, ST_BACKSLASH, ST_OCTAL, ST_HEX, ST_CARET, ST_END, ST_ERROR
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. */
359 state = ST_GND; /* Start in ground state. */
360 while (state < ST_END)
364 case ST_GND: /* Ground state (no escapes) */
369 state = ST_END; /* End of string */
372 state = ST_BACKSLASH; /* Backslash scape sequence */
376 state = ST_CARET; /* Caret escape */
382 state = ST_END; /* End */
393 case ST_BACKSLASH: /* Backslash escaped character */
404 state = ST_OCTAL; /* Octal sequence */
409 state = ST_HEX; /* Hex sequence */
415 case 'b': /* Backspace */
418 case 'e': /* Escape */
421 case 'f': /* Form feed */
424 case 'n': /* Newline */
427 case 'r': /* Carriage return */
436 case '?': /* Delete */
439 case '_': /* Space */
442 case '\0': /* End of string */
443 state = ST_ERROR; /* Error! */
445 default: /* Escaped character like \ ^ : = */
449 if (state == ST_BACKSLASH)
458 case ST_OCTAL: /* Octal sequence */
459 if (*p < '0' || *p > '7')
466 num = (num << 3) + (*(p++) - '0');
469 case ST_HEX: /* Hex sequence */
482 num = (num << 4) + (*(p++) - '0');
490 num = (num << 4) + (*(p++) - 'a') + 10;
498 num = (num << 4) + (*(p++) - 'A') + 10;
508 case ST_CARET: /* Caret escape */
509 state = ST_GND; /* Should be the next state... */
510 if (*p >= '@' && *p <= '~')
512 *(q++) = *(p++) & 037;
531 *output_count = count;
533 return state != ST_ERROR;
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;
569 set_color_palette (char const *palette)
571 color_palette = palette;
575 parse_diff_color (void)
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')
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
594 buf = color_buf = xstrdup (p);
596 enum parse_state state = PS_START;
601 case PS_START: /* First label character */
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;
619 ext->ext.string = buf;
621 state = (get_funky_string (&buf, &p, true, &ext->ext.len)
626 state = PS_DONE; /* Done! */
629 default: /* Assume it is file type label */
636 case PS_2: /* Second label character */
643 state = PS_FAIL; /* Error */
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);
661 if (state == PS_FAIL)
662 error (0, 0, _("unrecognized prefix: %s"), label);
666 case PS_4: /* Equal sign after *.ext */
669 ext->seq.string = buf;
670 state = (get_funky_string (&buf, &p, false, &ext->seq.len)
671 ? PS_START : PS_FAIL);
686 if (state == PS_FAIL)
688 struct color_ext_type *e;
689 struct color_ext_type *e2;
692 _("unparsable value for --palette"));
694 for (e = color_ext_list; e != NULL; /* empty */)
700 colors_enabled = false;
705 check_color_output (bool is_pipe)
709 if (! outfile || colors_style == NEVER)
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));
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. */
732 setup_output (char const *name0, char const *name1, bool recursive)
734 current_name0 = name0;
735 current_name1 = name1;
736 currently_recursive = recursive;
740 #if HAVE_WORKING_FORK
744 static char c_escape_char (char 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 '\\';
762 c_escape (char const *str)
766 bool must_quote = false;
768 for (s = str; *s; s++)
777 switch (c_escape_char (*s))
790 if (must_quote || plus)
792 size_t s_len = s - str;
793 char *buffer = xmalloc (s_len + plus + 3);
797 for (s = str; *s; s++)
800 char escape = c_escape_char (c);
809 *b++ = ((c >> 6) & 03) + '0';
810 *b++ = ((c >> 3) & 07) + '0';
811 *b++ = ((c >> 0) & 07) + '0';
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]);
851 if (fflush (stdout) != 0)
852 pfatal_with_name (_("write failed"));
854 argv[0] = pr_program;
859 /* Make OUTFILE a pipe to a subsidiary 'pr'. */
861 #if HAVE_WORKING_FORK
864 if (pipe (pipes) != 0)
865 pfatal_with_name ("pipe");
869 pfatal_with_name ("fork");
874 if (pipes[0] != STDIN_FILENO)
876 if (dup2 (pipes[0], STDIN_FILENO) < 0)
877 pfatal_with_name ("dup2");
881 execv (pr_program, (char **) argv);
882 _exit (errno == ENOENT ? 127 : 126);
887 outfile = fdopen (pipes[1], "w");
889 pfatal_with_name ("fdopen");
890 check_color_output (true);
893 char *command = system_quote_argv (SCI_SYSTEM, (char **) argv);
895 outfile = popen (command, "w");
897 pfatal_with_name (command);
898 check_color_output (true);
906 /* If -l was not specified, output the diff straight to '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);
919 /* A special header is needed at the beginning of context output. */
920 switch (output_style)
923 print_context_header (files, (char const *const *)names, false);
927 print_context_header (files, (char const *const *)names, true);
934 if (names[0] != current_name0)
936 if (names[1] != current_name1)
940 /* Call after the end of output of diffs for one file.
941 Close OUTFILE and get rid of the 'pr' subfork. */
946 if (outfile != 0 && outfile != stdout)
951 if (ferror (outfile))
952 fatal ("write failed");
953 #if ! HAVE_WORKING_FORK
954 wstatus = pclose (outfile);
958 if (fclose (outfile) != 0)
959 pfatal_with_name (_("write failed"));
960 if (waitpid (pr_pid, &wstatus, 0) < 0)
961 pfatal_with_name ("waitpid");
963 status = (! werrno && WIFEXITED (wstatus)
964 ? WEXITSTATUS (wstatus)
967 die (EXIT_TROUBLE, werrno,
969 ? "subsidiary program '%s' could not be invoked"
971 ? "subsidiary program '%s' not found"
973 ? "subsidiary program '%s' failed"
974 : "subsidiary program '%s' failed (exit status %d)"),
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. */
988 lines_differ (char const *s1, char const *s2)
990 register char const *t1 = s1;
991 register char const *t2 = s2;
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. */
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++;
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. */
1028 /* Likewise for line 2. */
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'
1050 && isspace ((unsigned char) t1[-2]))
1055 if (c1 == ' ' && c2 != '\n'
1057 && isspace ((unsigned char) t2[-2]))
1066 case IGNORE_TRAILING_SPACE:
1067 case IGNORE_TAB_EXPANSION_AND_TRAILING_SPACE:
1068 if (isspace (c1) && isspace (c2))
1074 while ((c = *p) != '\n' && isspace (c))
1082 while ((c = *p) != '\n' && isspace (c))
1087 /* Both lines have nothing but whitespace left. */
1090 if (ignore_white_space == IGNORE_TRAILING_SPACE)
1093 case IGNORE_TAB_EXPANSION:
1094 if ((c1 == ' ' && c2 == '\t')
1095 || (c1 == '\t' && c2 == ' '))
1097 size_t column2 = column;
1102 else if (c1 == '\t')
1103 column += tabsize - column % tabsize;
1111 else if (c2 == '\t')
1112 column2 += tabsize - column2 % tabsize;
1116 if (column != column2)
1121 case IGNORE_NO_WHITE_SPACE:
1125 /* Lowercase all letters if -i is specified. */
1139 column += c1 == '\t' ? tabsize - column % tabsize : 1;
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)
1154 struct change * _GL_ATTRIBUTE_CONST
1155 find_reverse_change (struct change *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
1168 PRINTFUN takes a subscript which belongs together (with a null
1169 link at the end) and prints it. */
1172 print_script (struct change *script,
1173 struct change * (*hunkfun) (struct change *),
1174 void (*printfun) (struct change *))
1176 struct change *next = script;
1180 struct change *this, *end;
1182 /* Find a set of changes that belong together. */
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. */
1191 debug_script (this);
1194 /* Print this hunk. */
1197 /* Reconnect the script so it will all be freed properly. */
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. */
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. */
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. */
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;
1270 size_t left = limit - base;
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)
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;
1293 counter_proc_signals++;
1294 if (counter_proc_signals == MAX_CHUNK)
1297 counter_proc_signals = 0;
1304 size_t spaces = tab_size - column % tab_size;
1314 if (flag_format && t < limit && *t != '\n')
1315 fprintf (out, flag_format, line_flag);
1327 column += isprint (c) != 0;
1337 C_LEFT, C_RIGHT, C_END, C_RESET, C_HEADER, C_ADD, C_DELETE, C_LINE
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;
1349 set_color_context (enum color_context color_context)
1351 if (color_context != RESET_CONTEXT)
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]);
1362 case LINE_NUMBER_CONTEXT:
1363 put_indicator (&color_indicator[C_LINE]);
1367 put_indicator (&color_indicator[C_ADD]);
1370 case DELETE_CONTEXT:
1371 put_indicator (&color_indicator[C_DELETE]);
1375 put_indicator (&color_indicator[C_RESET]);
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. */
1407 translate_range (struct file_data const *file,
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. */
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,
1430 if (trans_b > trans_a)
1431 fprintf (outfile, "%"pI"d%c%"pI"d", trans_a, sepchar, trans_b);
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. */
1450 analyze_hunk (struct change *hunk,
1451 lin *first0, lin *last0,
1452 lin *first1, lin *last1)
1454 struct change *next;
1456 lin show_from, show_to;
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;
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)
1499 if (newline - p != trivial_length
1500 && (! ignore_regexp.fastmap
1501 || re_search (&ignore_regexp, line, len, 0, len, 0) < 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)
1520 if (newline - p != trivial_length
1521 && (! ignore_regexp.fastmap
1522 || re_search (&ignore_regexp, line, len, 0, len, 0) < 0))
1526 while ((next = next->link) != 0);
1531 /* If all inserted or deleted lines are ignorable,
1532 tell the caller to ignore this hunk. */
1537 return (show_from ? OLD : UNCHANGED) | (show_to ? NEW : UNCHANGED);
1540 /* Concatenate three strings, returning a newly malloc'd string. */
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);
1550 /* Yield a new block of SIZE bytes, initialized to zero. */
1553 zalloc (size_t size)
1555 void *p = xmalloc (size);
1556 memset (p, 0, size);
1561 debug_script (struct change *sp)
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);