mirror of
https://https.git.savannah.gnu.org/git/diffutils.git
synced 2026-01-27 01:44:20 +00:00
diff: ignore tabs consistently with expanding them
* src/io.c (find_and_hash_each_line): * src/util.c (lines_differ): Treat '\0', '\a', '\b', '\f', '\r', '\v' consistently with how side.c treats them when expanding them, e.g., backspacing from column 1 is a no-op when counting tab columns. * tests/ignore-tab-expansion: New test. * tests/Makefile.am (TESTS): Add it.
This commit is contained in:
parent
6e091776f8
commit
572249e0fa
4
NEWS
4
NEWS
@ -19,6 +19,10 @@ GNU diffutils NEWS -*- outline -*-
|
||||
cp /proc/cmdline t; cmp -s /proc/cmdline t || echo files differ
|
||||
[bug present since "the beginning"]
|
||||
|
||||
diff -E no longer mishandles some input lines containing '\a', '\b',
|
||||
'\f', '\r', '\v', or '\0'.
|
||||
[bug present since 2.8]
|
||||
|
||||
diff -ly no longer mishandles non-ASCII input
|
||||
[bug#64461 introduced in 2.9]
|
||||
|
||||
|
||||
16
src/io.c
16
src/io.c
@ -292,7 +292,7 @@ find_and_hash_each_line (struct file_data *current)
|
||||
case IGNORE_TAB_EXPANSION_AND_TRAILING_SPACE:
|
||||
case IGNORE_TRAILING_SPACE:
|
||||
{
|
||||
intmax_t column = 0;
|
||||
intmax_t tab = 0, column = 0;
|
||||
for (unsigned char c; (c = *p++) != '\n'; )
|
||||
{
|
||||
if (ig_white_space & IGNORE_TRAILING_SPACE
|
||||
@ -318,19 +318,29 @@ find_and_hash_each_line (struct file_data *current)
|
||||
switch (c)
|
||||
{
|
||||
case '\b':
|
||||
column = (column ? column : tabsize) - 1;
|
||||
if (0 < column)
|
||||
column--;
|
||||
else if (0 < tab)
|
||||
{
|
||||
tab--;
|
||||
column = tabsize - 1;
|
||||
}
|
||||
break;
|
||||
|
||||
case '\t':
|
||||
c = ' ';
|
||||
repetitions = tabsize - column % tabsize;
|
||||
tab += column / tabsize + 1;
|
||||
column = 0;
|
||||
break;
|
||||
|
||||
case '\r':
|
||||
column = 0;
|
||||
tab = column = 0;
|
||||
break;
|
||||
|
||||
case '\0': case '\a': case '\f': case '\v':
|
||||
break;
|
||||
|
||||
default:
|
||||
column++;
|
||||
break;
|
||||
|
||||
32
src/util.c
32
src/util.c
@ -1212,14 +1212,38 @@ lines_differ (char const *s1, char const *s2)
|
||||
if (c1 != c2)
|
||||
break;
|
||||
}
|
||||
if (c1 == '\n')
|
||||
return false;
|
||||
|
||||
column++;
|
||||
if (c1 == '\t' || column == tabsize)
|
||||
switch (c1)
|
||||
{
|
||||
case '\n':
|
||||
return false;
|
||||
|
||||
case '\r':
|
||||
tab = column = 0;
|
||||
break;
|
||||
|
||||
case '\b':
|
||||
if (0 < column)
|
||||
column--;
|
||||
else if (0 < tab)
|
||||
{
|
||||
tab--;
|
||||
column = tabsize - 1;
|
||||
}
|
||||
break;
|
||||
|
||||
case '\0': case '\a': case '\f': case '\v':
|
||||
break;
|
||||
|
||||
default:
|
||||
column++;
|
||||
if (column < tabsize)
|
||||
break;
|
||||
FALLTHROUGH;
|
||||
case '\t':
|
||||
tab++;
|
||||
column = 0;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@ -16,6 +16,7 @@ TESTS = \
|
||||
invalid-re \
|
||||
function-line-vs-leading-space \
|
||||
ignore-matching-lines \
|
||||
ignore-tab-expansion \
|
||||
label-vs-func \
|
||||
large-subopt \
|
||||
new-file \
|
||||
|
||||
16
tests/ignore-tab-expansion
Executable file
16
tests/ignore-tab-expansion
Executable file
@ -0,0 +1,16 @@
|
||||
#!/bin/sh
|
||||
# Test ignoring tab expansion.
|
||||
|
||||
. "${srcdir=.}/init.sh"; path_prepend_ ../src
|
||||
|
||||
fail=0
|
||||
|
||||
for p in '\b' '\r' '\t ' '\n'; do
|
||||
printf "$p"'\b\tx\n' >a || framework_failure_
|
||||
printf "$p"'\b x\n' >b || framework_failure
|
||||
|
||||
diff -E a b >out || fail=1
|
||||
compare /dev/null out || fail=1
|
||||
done
|
||||
|
||||
Exit $fail
|
||||
Loading…
x
Reference in New Issue
Block a user