1
1
/* Support routines for GNU DIFF.
3
Copyright (C) 1988, 1989, 1992, 1993, 1994, 1995, 1998, 2001, 2002
3
Copyright (C) 1988-1989, 1992-1995, 1998, 2001-2002, 2004, 2006, 2009-2010
4
4
Free Software Foundation, Inc.
6
6
This file is part of GNU DIFF.
8
GNU DIFF is free software; you can redistribute it and/or modify
8
This program is free software: you can redistribute it and/or modify
9
9
it under the terms of the GNU General Public License as published by
10
the Free Software Foundation; either version 2, or (at your option)
10
the Free Software Foundation, either version 3 of the License, or
11
(at your option) any later version.
13
GNU DIFF is distributed in the hope that it will be useful,
13
This program is distributed in the hope that it will be useful,
14
14
but WITHOUT ANY WARRANTY; without even the implied warranty of
15
15
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16
16
GNU General Public License for more details.
18
18
You should have received a copy of the GNU General Public License
19
along with this program; see the file COPYING.
20
If not, write to the Free Software Foundation,
21
59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
19
along with this program. If not, see <http://www.gnu.org/licenses/>. */
24
22
#include <dirname.h>
28
25
#include <xalloc.h>
30
27
char const pr_program[] = PR_PROGRAM;
218
215
execl (pr_program, pr_program, "-h", name, (char *) 0);
219
_exit (errno == ENOEXEC ? 126 : 127);
216
_exit (errno == ENOENT ? 127 : 126);
229
226
char *command = xmalloc (sizeof pr_program - 1 + 7
230
+ quote_system_arg ((char *) 0, name) + 1);
227
+ shell_quote_length (name) + 1);
232
229
sprintf (command, "%s -f -h ", pr_program);
233
230
p = command + sizeof pr_program - 1 + 7;
234
p += quote_system_arg (p, name);
231
p = shell_quote_copy (p, name);
237
234
outfile = popen (command, "w");
260
257
switch (output_style)
262
259
case OUTPUT_CONTEXT:
263
print_context_header (files, 0);
260
print_context_header (files, false);
266
263
case OUTPUT_UNIFIED:
267
print_context_header (files, 1);
264
print_context_header (files, true);
294
292
if (waitpid (pr_pid, &wstatus, 0) < 0)
295
293
pfatal_with_name ("waitpid");
297
if (! werrno && WIFEXITED (wstatus) && WEXITSTATUS (wstatus) == 127)
298
error (EXIT_TROUBLE, 0, _("subsidiary program `%s' not found"),
301
error (EXIT_TROUBLE, werrno, _("subsidiary program `%s' failed"),
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)"),
315
320
lines_differ (char const *s1, char const *s2)
317
register unsigned char const *t1 = (unsigned char const *) s1;
318
register unsigned char const *t2 = (unsigned char const *) s2;
322
register char const *t1 = s1;
323
register char const *t2 = s2;
319
324
size_t column = 0;
331
336
case IGNORE_ALL_SPACE:
332
337
/* For -w, just skip past any white space. */
333
while (ISSPACE (c1) && c1 != '\n') c1 = *t1++;
334
while (ISSPACE (c2) && c2 != '\n') c2 = *t2++;
338
while (isspace (c1) && c1 != '\n') c1 = *t1++;
339
while (isspace (c2) && c2 != '\n') c2 = *t2++;
337
342
case IGNORE_SPACE_CHANGE:
338
343
/* For -b, advance past any sequence of white space in
339
344
line 1 and consider it just one space, or nothing at
340
345
all if it is at the end of the line. */
343
348
while (c1 != '\n')
373
378
for equality, go back to the first non-white-space
374
379
character in both sides and try again. */
375
380
if (c2 == ' ' && c1 != '\n'
376
&& (unsigned char const *) s1 + 1 < t1
382
&& isspace ((unsigned char) t1[-2]))
382
387
if (c1 == ' ' && c2 != '\n'
383
&& (unsigned char const *) s2 + 1 < t2
389
&& isspace ((unsigned char) t2[-2]))
502
507
/* Print the text of a single line LINE,
503
508
flagging it with the characters in LINE_FLAG (which say whether
504
the line is inserted, deleted, changed, etc.). */
509
the line is inserted, deleted, changed, etc.). LINE_FLAG must not
510
end in a blank, unless it is a single blank. */
507
513
print_1_line (char const *line_flag, char const *const *line)
513
519
/* If -T was specified, use a Tab between the line-flag and the text.
514
520
Otherwise use a Space (as Unix diff does).
515
Print neither space nor tab if line-flags are empty. */
521
Print neither space nor tab if line-flags are empty.
522
But omit trailing blanks if requested. */
517
524
if (line_flag && *line_flag)
519
flag_format = initial_tab ? "%s\t" : "%s ";
520
fprintf (out, flag_format, 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);
523
542
output_1_line (base, limit, flag_format, line_flag);
536
555
char const *line_flag)
538
557
if (!expand_tabs)
539
fwrite (base, limit - base, 1, outfile);
558
fwrite (base, sizeof (char), limit - base, outfile);
542
561
register FILE *out = outfile;
543
562
register unsigned char c;
544
563
register char const *t = base;
545
register unsigned int column = 0;
564
register size_t column = 0;
565
size_t tab_size = tabsize;
547
567
while (t < limit)
548
568
switch ((c = *t++))
552
unsigned int spaces = TAB_WIDTH - column % TAB_WIDTH;
572
size_t spaces = tab_size - column % tab_size;
553
573
column += spaces;
598
617
/* Translate a line number range. This is always done for printing,
599
so for convenience translate to long rather than lin, so that the
618
so for convenience translate to long int rather than lin, so that the
600
619
caller can use printf with "%ld" without casting. */
603
622
translate_range (struct file_data const *file,
605
long *aptr, long *bptr)
624
long int *aptr, long int *bptr)
607
626
*aptr = translate_line_number (file, a - 1) + 1;
608
627
*bptr = translate_line_number (file, b + 1) - 1;
618
637
print_number_range (char sepchar, struct file_data *file, lin a, lin b)
620
long trans_a, trans_b;
639
long int trans_a, trans_b;
621
640
translate_range (file, a, b, &trans_a, &trans_b);
623
642
/* Note: we can have B < A in the case of a range of no lines.
652
671
lin show_from, show_to;
654
673
bool trivial = ignore_blank_lines || ignore_regexp.fastmap;
655
size_t trivial_length = (int) ignore_blank_lines - 1;
674
size_t trivial_length = ignore_blank_lines - 1;
656
675
/* If 0, ignore zero-length lines;
657
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);
659
680
char const * const *linbuf0 = files[0].linbuf; /* Help the compiler. */
660
681
char const * const *linbuf1 = files[1].linbuf;
675
696
for (i = next->line0; i <= l0 && trivial; i++)
677
698
char const *line = linbuf0[i];
678
size_t len = linbuf0[i + 1] - line - 1;
679
if (len != trivial_length
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
680
706
&& (! ignore_regexp.fastmap
681
707
|| re_search (&ignore_regexp, line, len, 0, len, 0) < 0))
685
711
for (i = next->line1; i <= l1 && trivial; i++)
687
713
char const *line = linbuf1[i];
688
size_t len = linbuf1[i + 1] - line - 1;
689
if (len != trivial_length
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
690
721
&& (! ignore_regexp.fastmap
691
722
|| re_search (&ignore_regexp, line, len, 0, len, 0) < 0))
733
764
dir_file_pathname (char const *dir, char const *file)
735
char const *base = base_name (dir);
736
bool omit_slash = !*base || base[strlen (base) - 1] == '/';
766
char const *base = last_component (dir);
767
size_t baselen = base_len (base);
768
bool omit_slash = baselen == 0 || base[baselen - 1] == '/';
737
769
return concat (dir, "/" + omit_slash, file);
745
777
for (; sp; sp = sp->link)
747
long line0 = sp->line0;
748
long line1 = sp->line1;
749
long deleted = sp->deleted;
750
long inserted = sp->inserted;
779
long int line0 = sp->line0;
780
long int line1 = sp->line1;
781
long int deleted = sp->deleted;
782
long int inserted = sp->inserted;
751
783
fprintf (stderr, "%3ld %3ld delete %ld insert %ld\n",
752
784
line0, line1, deleted, inserted);