* bootstrap.conf (gnulib_modules): Remove gettime; add timespec_get.
* src/context.c (print_context_label): Get current time lazily.
Use C11 timespec_get rather than older Gnulib gettime function.
* src/diff.c: Do not include timespec.h.
(set_mtime_to_now): Remove. All uses removed.
* src/system.h: Include stat-time.h, timespec.h.
* bootstrap.conf (gnulib_modules): Add timespec, for timespec_cmp.
(same_file_attributes): Check birthtime and ns components too.
Check attributes earlier if they are more likely to differ.
* configure.ac: Do not check for strcasecoll (which doesn’t exist)
or stricoll (not worth the porting hassle, as it doesn’t set errno).
* src/dir.c: Always include mbcel.h, since we now always
use mbcel_strcasecmp.
(strcasecoll): Remove
(compare_collated, diff_dirs): Do the setjump business only when
not ignoring file name case, since mbcel_strcasecmp doesn’t fail
and doesn’t set errno. This fixes a bug in recent changes,
which incorrectly assumed mbcel_strcasecmp preserves errno.
* src/dir.c:
Always include mbcel.h, since we now always compile a call
to mbcel_strcasecmp.
(strcasecoll): Remove. It’s not worth bothering to port to
Microsoft stricoll’s idiosyncrasies; mbcel_strcasecmp is good enough.
And nobody ever implemented strcasecoll.
* bootstrap.conf (gnulib_modules): Add builtin-expect.
* lib/mbcel-strcasecmp.c: New file.
* lib/Makefile.am (libdiffutils_a_SOURCES): Add it.
* lib/mbcel.h (MBCEL_LEN_MAX, MBCEL_ENCODING_ERROR_SHIFT)
(MBCEL_UCHAR_FITS, MBCEL_UCHAR_EASILY_FITS): New constants.
(_GL_LIKELY): New macro.
(mbcel_scan): Use it. Simplify NetBSD code.
(mbcel_scant, mbcel_scanz, mbcel_cmp, mbcel_casecmp): New functions.
* src/dir.c (strcasecoll): Move defn here from system.h,
since only dir.c needs it. Use mbcel_strcasecmp instead
of strcasecmp.
* src/cmp.c (cmp): Redo to avoid the need for IF_LINT, while still
pacifying GCC. The machine code is a bit smaller too. The price
is a portmanteau variable, but it’s worth it.
* src/system.h (IF_LINT): Remove.
* src/dir.c (find_dir_file_pathname): Simplify. There is no
longer a need for volatile or setjmp, now that dir_read does all
the tricky sorting and longjmping.
* src/dir.c (dir_read): New args STARTFILE and STARTFILE_ONLY,
to avoid unnecessary allocation and copying. All uses changed.
* tests/starting-file: New test.
* tests/Makefile.am (TESTS): Add it.
* src/dir.c (diff_dirs, dir_loop): The ‘parent’ member is now
&noparent (instead of null) if there is no parent. Patch
a couple of uses that were missed earlier.
* lib/mbcel.h (mbcel_t):
Fix bug on NetBSD as I read its code incorrectly earlier.
Problem reported by Bruno Haible in:
https://lists.gnu.org/r/bug-gnulib/2023-07/msg00085.html
Mostly for documentation, use _GL_ATTRIBUTE_MAY_ALIAS to remind
compiler not to rely on strict C semantics for unions.
This should improve performance when doing recursive comparisons.
Currently there is no attempt to avoid file descriptor exhaustion,
just as previously there is no attempt to avoid file names
that provoke ENAMETOOLONG. Because of this change, ‘diff - A/B’
now works correctly when standard input is a directory.
* .gitignore: Add lib/dirent.h.
* bootstrap.conf (gnulib_modules): Add fdopendir.
* src/diff.c (main): Initialize noparent’s desc to AT_FDCWD.
(compare_files): Use fstatat with parent directory’s file
descriptor and relative name, instead of lstat or stat.
Likewise for openat and open.
* src/diff.h (struct file_data): New member ‘dirstream’.
(struct comparison): The ‘parent’ member is now &noparent (instead
of null) if there is no parent. All uses changed.
(curr): New toplevel variable, replacing ‘files’. All uses changed.
* src/dir.c: Include dirname.h, for last_component.
(dir_read): New arg PARENTDIRFD. Arg DIR is no longer
pointer-to-const since DIR->desc and DIR->dirstream are now
updated. Use PARENTDIRFD to open the directory via
opendat+fdopendir instead of via opendir. Update new dirstream
component instead of closing the directory, since it’s now the
caller’s responsibility to close the directory because callers now
want the file descriptor. All callers changed.
(diff_dirs): First arg CMP is no longer pointer-to-const since
CMP->file is updated by dir_read. All callers changed.
(find_dir_file_pathname): First arg is now struct file_data *,
not merely a file name. All callers changed.
* tests/stdin: Test new behavior when stdin is a directory.
This is a minor refactoring and simplification.
* src/context.c (find_hunk):
* src/util.c (find_change): Rename locals for clarity.
(find_reverse_change): Remove. All uses removed.
Regularize how assertions are done by using ‘unreachable’ or a new
macro ‘dassert’, or by removing unnecessary assertions.
* src/analyze.c (diff_2_files):
* src/util.c (get_funky_string, parse_diff_color)
(set_color_context):
Prefer unreachable to abort for code where it’s easy to
see that it cannot be reached.
* src/context.c (ATTRIBUTE_PURE):
* src/util.c (print_message_queue):
Prefer ‘dassert (X);’ to ‘if (!X) abort ();’.
* src/diff.c: Do not include assert.h; system.h does that if needed.
(usage): Remove the need for an assert by using fputs and fwrite
rather than printf. This is clearer anyway.
(compare_files): Remove ‘assert’ that hardware will check.
Prefer dassert to assert.
* src/ifdef.c (do_printf_spec):
Prefer dassert to comment.
* src/system.h (dassert): New macro. Include assert.h if needed.
* lib/mbcel.h: Include limits.h, stddef.h.
Add static assertions that MB_LEN_MAX has a sane value,
as the code relies on this. Help GCC by advising
it that mbrtoc32 never returns a value between
MB_LEN_MAX + 1 and (size_t) -1 / 2 inclusive.
* src/io.c (lines_differ): Move here ...
* src/util.c: ... from here, since it needs to be kept consistent
with find_and_hash_each line anyway, and there is no reason to
make it an extern function.
* src/side.c: Include mbcel.h instead of uchar.h.
(print_half_line): Simplify by using mbcel_scan rather than
mbrtoc32. Although this removes support for hypothetical platforms,
it makes the code easier to follow and a bit more efficient.
* bootstrap.conf (gnulib_modules): Add c32isspace, c32tolower.
* lib/Makefile.am (noinst_HEADERS): Add mbcel.h.
(libdiffutils_a_SOURCES): Add mbcel.c
* lib/mbcel.c, lib/mbcel.h: New files.
* src/io.c: Include mbcel.h, uchar.h.
(hash): 2nd arg is now hash_value, not merely unsigned char,
since the caller might pass a char32_t now.
(find_and_hash_each_line): Support multi-byte input.
* src/util.c: Include mbcel.h, uchar.h.
(lines_differ): New args S1LEN, S2LEN, needed for mbcel_scan.
Caller changed. Support multi-byte input.
* tests/ignore-case: New file.
* tests/Makefile.am (TESTS): Add it.
* tests/ignore-tab-expansion: Add UTF-8 test.
* tests/init.cfg (require_utf8_locale_): New function.
* tests/side-by-side: Use it. Add a column-counting test.
* src/side.c (print_half_line): Simplify. Don't worry about
initializing mbstate until it's needed. Avoid int overflow if the
byte sequence represents more than INT_MAX columns. Avoid need
for separate TP1 local.
* 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.
* src/util.c (output_1_line): When expanding tabs, treat backspace
before column 1 as no-op, since that’s what most devices do.
* tests/expand-tabs: New test.
* tests/Makefile.am (TESTS): Add it.
Problem reported by Gisle Vanem <https://bugs.gnu.org/64316>.
* src/io.c (find_and_hash_each_line):
Rely on xpalloc to check for integer overflow instead
of trying to do it ourselves incorrectly, with old code
that predated the use of xpalloc.
* src/system.h: Verify that LIN_MAX == IDX_MAX,
since the code now relies on this.
* tests/Makefile.am (TESTS): Add bug-64316.
* tests/bug-64316: New file