1 /* Support routines for GNU DIFF.
3 Copyright (C) 1988-1989, 1992-1995, 1998, 2001-2002, 2004, 2006, 2009-2010
4 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/>. */
27 char const pr_program[] = PR_PROGRAM;
29 /* Queue up one-line messages to be printed at the end,
30 when -l is specified. Each message is recorded with a `struct msg'. */
35 char args[1]; /* Format + 4 args, each '\0' terminated, concatenated. */
38 /* Head of the chain of queues messages. */
40 static struct msg *msg_chain;
42 /* Tail of the chain of queues messages. */
44 static struct msg **msg_chain_end = &msg_chain;
46 /* Use when a system call returns non-zero status.
47 NAME should normally be the file name. */
50 perror_with_name (char const *name)
52 error (0, errno, "%s", name);
55 /* Use when a system call returns non-zero status and that is fatal. */
58 pfatal_with_name (char const *name)
61 print_message_queue ();
62 error (EXIT_TROUBLE, e, "%s", name);
66 /* Print an error message containing MSGID, then exit. */
69 fatal (char const *msgid)
71 print_message_queue ();
72 error (EXIT_TROUBLE, 0, "%s", _(msgid));
76 /* Like printf, except if -l in effect then save the message and print later.
77 This is used for things like "Only in ...". */
80 message (char const *format_msgid, char const *arg1, char const *arg2)
82 message5 (format_msgid, arg1, arg2, 0, 0);
86 message5 (char const *format_msgid, char const *arg1, char const *arg2,
87 char const *arg3, char const *arg4)
95 size_t total_size = offsetof (struct msg, args);
98 arg[0] = format_msgid;
101 arg[3] = arg3 ? arg3 : "";
102 arg[4] = arg4 ? arg4 : "";
104 for (i = 0; i < 5; i++)
105 total_size += size[i] = strlen (arg[i]) + 1;
107 new = xmalloc (total_size);
109 for (i = 0, p = new->args; i < 5; p += size[i++])
110 memcpy (p, arg[i], size[i]);
112 *msg_chain_end = new;
114 msg_chain_end = &new->next;
118 if (sdiff_merge_assist)
120 printf (_(format_msgid), arg1, arg2, arg3, arg4);
124 /* Output all the messages that were saved up by calls to `message'. */
127 print_message_queue (void)
131 struct msg *m = msg_chain;
135 struct msg *next = m->next;
137 for (i = 0; i < 4; i++)
138 arg[i + 1] = arg[i] + strlen (arg[i]) + 1;
139 printf (_(arg[0]), arg[1], arg[2], arg[3], arg[4]);
145 /* Call before outputting the results of comparing files NAME0 and NAME1
146 to set up OUTFILE, the stdio stream for the output to go to.
148 Usually, OUTFILE is just stdout. But when -l was specified
149 we fork off a `pr' and make OUTFILE a pipe to it.
150 `pr' then outputs to our stdout. */
152 static char const *current_name0;
153 static char const *current_name1;
154 static bool currently_recursive;
157 setup_output (char const *name0, char const *name1, bool recursive)
159 current_name0 = name0;
160 current_name1 = name1;
161 currently_recursive = recursive;
165 #if HAVE_WORKING_FORK || HAVE_WORKING_VFORK
177 /* Construct the header of this piece of diff. */
178 name = xmalloc (strlen (current_name0) + strlen (current_name1)
179 + strlen (switch_string) + 7);
181 /* POSIX 1003.1-2001 specifies this format. But there are some bugs in
182 the standard: it says that we must print only the last component
183 of the pathnames, and it requires two spaces after "diff" if
184 there are no options. These requirements are silly and do not
185 match historical practice. */
186 sprintf (name, "diff%s %s %s", switch_string, current_name0, current_name1);
190 if (fflush (stdout) != 0)
191 pfatal_with_name (_("write failed"));
193 /* Make OUTFILE a pipe to a subsidiary `pr'. */
195 #if HAVE_WORKING_FORK || HAVE_WORKING_VFORK
198 if (pipe (pipes) != 0)
199 pfatal_with_name ("pipe");
203 pfatal_with_name ("fork");
208 if (pipes[0] != STDIN_FILENO)
210 if (dup2 (pipes[0], STDIN_FILENO) < 0)
211 pfatal_with_name ("dup2");
215 execl (pr_program, pr_program, "-h", name, (char *) 0);
216 _exit (errno == ENOENT ? 127 : 126);
221 outfile = fdopen (pipes[1], "w");
223 pfatal_with_name ("fdopen");
226 char *command = xmalloc (sizeof pr_program - 1 + 7
227 + shell_quote_length (name) + 1);
229 sprintf (command, "%s -f -h ", pr_program);
230 p = command + sizeof pr_program - 1 + 7;
231 p = shell_quote_copy (p, name);
234 outfile = popen (command, "w");
236 pfatal_with_name (command);
244 /* If -l was not specified, output the diff straight to `stdout'. */
248 /* If handling multiple files (because scanning a directory),
249 print which files the following output is about. */
250 if (currently_recursive)
251 printf ("%s\n", name);
256 /* A special header is needed at the beginning of context output. */
257 switch (output_style)
260 print_context_header (files, false);
264 print_context_header (files, true);
272 /* Call after the end of output of diffs for one file.
273 Close OUTFILE and get rid of the `pr' subfork. */
278 if (outfile != 0 && outfile != stdout)
283 if (ferror (outfile))
284 fatal ("write failed");
285 #if ! (HAVE_WORKING_FORK || HAVE_WORKING_VFORK)
286 wstatus = pclose (outfile);
290 if (fclose (outfile) != 0)
291 pfatal_with_name (_("write failed"));
292 if (waitpid (pr_pid, &wstatus, 0) < 0)
293 pfatal_with_name ("waitpid");
295 status = (! werrno && WIFEXITED (wstatus)
296 ? WEXITSTATUS (wstatus)
299 error (EXIT_TROUBLE, werrno,
301 ? "subsidiary program `%s' could not be invoked"
303 ? "subsidiary program `%s' not found"
305 ? "subsidiary program `%s' failed"
306 : "subsidiary program `%s' failed (exit status %d)"),
313 /* Compare two lines (typically one from each input file)
314 according to the command line options.
315 For efficiency, this is invoked only when the lines do not match exactly
316 but an option like -i might cause us to ignore the difference.
317 Return nonzero if the lines differ. */
320 lines_differ (char const *s1, char const *s2)
322 register char const *t1 = s1;
323 register char const *t2 = s2;
328 register unsigned char c1 = *t1++;
329 register unsigned char c2 = *t2++;
331 /* Test for exact char equality first, since it's a common case. */
334 switch (ignore_white_space)
336 case IGNORE_ALL_SPACE:
337 /* For -w, just skip past any white space. */
338 while (isspace (c1) && c1 != '\n') c1 = *t1++;
339 while (isspace (c2) && c2 != '\n') c2 = *t2++;
342 case IGNORE_SPACE_CHANGE:
343 /* For -b, advance past any sequence of white space in
344 line 1 and consider it just one space, or nothing at
345 all if it is at the end of the line. */
360 /* Likewise for line 2. */
377 /* If we went too far when doing the simple test
378 for equality, go back to the first non-white-space
379 character in both sides and try again. */
380 if (c2 == ' ' && c1 != '\n'
382 && isspace ((unsigned char) t1[-2]))
387 if (c1 == ' ' && c2 != '\n'
389 && isspace ((unsigned char) t2[-2]))
398 case IGNORE_TAB_EXPANSION:
399 if ((c1 == ' ' && c2 == '\t')
400 || (c1 == '\t' && c2 == ' '))
402 size_t column2 = column;
408 column += tabsize - column % tabsize;
417 column2 += tabsize - column2 % tabsize;
421 if (column != column2)
426 case IGNORE_NO_WHITE_SPACE:
430 /* Lowercase all letters if -i is specified. */
444 column += c1 == '\t' ? tabsize - column % tabsize : 1;
450 /* Find the consecutive changes at the start of the script START.
451 Return the last link before the first gap. */
454 find_change (struct change *start)
460 find_reverse_change (struct change *start)
465 /* Divide SCRIPT into pieces by calling HUNKFUN and
466 print each piece with PRINTFUN.
467 Both functions take one arg, an edit script.
469 HUNKFUN is called with the tail of the script
470 and returns the last link that belongs together with the start
473 PRINTFUN takes a subscript which belongs together (with a null
474 link at the end) and prints it. */
477 print_script (struct change *script,
478 struct change * (*hunkfun) (struct change *),
479 void (*printfun) (struct change *))
481 struct change *next = script;
485 struct change *this, *end;
487 /* Find a set of changes that belong together. */
489 end = (*hunkfun) (next);
491 /* Disconnect them from the rest of the changes,
492 making them a hunk, and remember the rest for next iteration. */
499 /* Print this hunk. */
502 /* Reconnect the script so it will all be freed properly. */
507 /* Print the text of a single line LINE,
508 flagging it with the characters in LINE_FLAG (which say whether
509 the line is inserted, deleted, changed, etc.). LINE_FLAG must not
510 end in a blank, unless it is a single blank. */
513 print_1_line (char const *line_flag, char const *const *line)
515 char const *base = line[0], *limit = line[1]; /* Help the compiler. */
516 FILE *out = outfile; /* Help the compiler some more. */
517 char const *flag_format = 0;
519 /* If -T was specified, use a Tab between the line-flag and the text.
520 Otherwise use a Space (as Unix diff does).
521 Print neither space nor tab if line-flags are empty.
522 But omit trailing blanks if requested. */
524 if (line_flag && *line_flag)
526 char const *flag_format_1 = flag_format = initial_tab ? "%s\t" : "%s ";
527 char const *line_flag_1 = line_flag;
529 if (suppress_blank_empty && **line == '\n')
531 flag_format_1 = "%s";
533 /* This hack to omit trailing blanks takes advantage of the
534 fact that the only way that LINE_FLAG can end in a blank
535 is when LINE_FLAG consists of a single blank. */
536 line_flag_1 += *line_flag_1 == ' ';
539 fprintf (out, flag_format_1, line_flag_1);
542 output_1_line (base, limit, flag_format, line_flag);
544 if ((!line_flag || line_flag[0]) && limit[-1] != '\n')
545 fprintf (out, "\n\\ %s\n", _("No newline at end of file"));
548 /* Output a line from BASE up to LIMIT.
549 With -t, expand white space characters to spaces, and if FLAG_FORMAT
550 is nonzero, output it with argument LINE_FLAG after every
551 internal carriage return, so that tab stops continue to line up. */
554 output_1_line (char const *base, char const *limit, char const *flag_format,
555 char const *line_flag)
558 fwrite (base, sizeof (char), limit - base, outfile);
561 register FILE *out = outfile;
562 register unsigned char c;
563 register char const *t = base;
564 register size_t column = 0;
565 size_t tab_size = tabsize;
572 size_t spaces = tab_size - column % tab_size;
582 if (flag_format && t < limit && *t != '\n')
583 fprintf (out, flag_format, line_flag);
595 column += isprint (c) != 0;
602 char const change_letter[] = { 0, 'd', 'a', 'c' };
604 /* Translate an internal line number (an index into diff's table of lines)
605 into an actual line number in the input file.
606 The internal line number is I. FILE points to the data on the file.
608 Internal line numbers count from 0 starting after the prefix.
609 Actual line numbers count from 1 within the entire file. */
612 translate_line_number (struct file_data const *file, lin i)
614 return i + file->prefix_lines + 1;
617 /* Translate a line number range. This is always done for printing,
618 so for convenience translate to long int rather than lin, so that the
619 caller can use printf with "%ld" without casting. */
622 translate_range (struct file_data const *file,
624 long int *aptr, long int *bptr)
626 *aptr = translate_line_number (file, a - 1) + 1;
627 *bptr = translate_line_number (file, b + 1) - 1;
630 /* Print a pair of line numbers with SEPCHAR, translated for file FILE.
631 If the two numbers are identical, print just one number.
633 Args A and B are internal line numbers.
634 We print the translated (real) line numbers. */
637 print_number_range (char sepchar, struct file_data *file, lin a, lin b)
639 long int trans_a, trans_b;
640 translate_range (file, a, b, &trans_a, &trans_b);
642 /* Note: we can have B < A in the case of a range of no lines.
643 In this case, we should print the line number before the range,
645 if (trans_b > trans_a)
646 fprintf (outfile, "%ld%c%ld", trans_a, sepchar, trans_b);
648 fprintf (outfile, "%ld", trans_b);
651 /* Look at a hunk of edit script and report the range of lines in each file
652 that it applies to. HUNK is the start of the hunk, which is a chain
653 of `struct change'. The first and last line numbers of file 0 are stored in
654 *FIRST0 and *LAST0, and likewise for file 1 in *FIRST1 and *LAST1.
655 Note that these are internal line numbers that count from 0.
657 If no lines from file 0 are deleted, then FIRST0 is LAST0+1.
659 Return UNCHANGED if only ignorable lines are inserted or deleted,
660 OLD if lines of file 0 are deleted,
661 NEW if lines of file 1 are inserted,
662 and CHANGED if both kinds of changes are found. */
665 analyze_hunk (struct change *hunk,
666 lin *first0, lin *last0,
667 lin *first1, lin *last1)
671 lin show_from, show_to;
673 bool trivial = ignore_blank_lines || ignore_regexp.fastmap;
674 size_t trivial_length = ignore_blank_lines - 1;
675 /* If 0, ignore zero-length lines;
676 if SIZE_MAX, do not ignore lines just because of their length. */
677 bool skip_leading_white_space =
678 (ignore_blank_lines && IGNORE_SPACE_CHANGE <= ignore_white_space);
680 char const * const *linbuf0 = files[0].linbuf; /* Help the compiler. */
681 char const * const *linbuf1 = files[1].linbuf;
683 show_from = show_to = 0;
685 *first0 = hunk->line0;
686 *first1 = hunk->line1;
691 l0 = next->line0 + next->deleted - 1;
692 l1 = next->line1 + next->inserted - 1;
693 show_from += next->deleted;
694 show_to += next->inserted;
696 for (i = next->line0; i <= l0 && trivial; i++)
698 char const *line = linbuf0[i];
699 char const *newline = linbuf0[i + 1] - 1;
700 size_t len = newline - line;
701 char const *p = line;
702 if (skip_leading_white_space)
703 while (isspace ((unsigned char) *p) && *p != '\n')
705 if (newline - p != trivial_length
706 && (! ignore_regexp.fastmap
707 || re_search (&ignore_regexp, line, len, 0, len, 0) < 0))
711 for (i = next->line1; i <= l1 && trivial; i++)
713 char const *line = linbuf1[i];
714 char const *newline = linbuf1[i + 1] - 1;
715 size_t len = newline - line;
716 char const *p = line;
717 if (skip_leading_white_space)
718 while (isspace ((unsigned char) *p) && *p != '\n')
720 if (newline - p != trivial_length
721 && (! ignore_regexp.fastmap
722 || re_search (&ignore_regexp, line, len, 0, len, 0) < 0))
726 while ((next = next->link) != 0);
731 /* If all inserted or deleted lines are ignorable,
732 tell the caller to ignore this hunk. */
737 return (show_from ? OLD : UNCHANGED) | (show_to ? NEW : UNCHANGED);
740 /* Concatenate three strings, returning a newly malloc'd string. */
743 concat (char const *s1, char const *s2, char const *s3)
745 char *new = xmalloc (strlen (s1) + strlen (s2) + strlen (s3) + 1);
746 sprintf (new, "%s%s%s", s1, s2, s3);
750 /* Yield a new block of SIZE bytes, initialized to zero. */
755 void *p = xmalloc (size);
760 /* Yield the newly malloc'd pathname
761 of the file in DIR whose filename is FILE. */
764 dir_file_pathname (char const *dir, char const *file)
766 char const *base = last_component (dir);
767 size_t baselen = base_len (base);
768 bool omit_slash = baselen == 0 || base[baselen - 1] == '/';
769 return concat (dir, "/" + omit_slash, file);
773 debug_script (struct change *sp)
777 for (; sp; sp = sp->link)
779 long int line0 = sp->line0;
780 long int line1 = sp->line1;
781 long int deleted = sp->deleted;
782 long int inserted = sp->inserted;
783 fprintf (stderr, "%3ld %3ld delete %ld insert %ld\n",
784 line0, line1, deleted, inserted);