Subject: Re: bug#49716: no -print0 for ls?

From: Paul Eggert <[email-masked]>
Date: Mon, 26 Jul 2021 01:05:50 -0700

On 7/25/21 10:10 AM, Pádraig Brady wrote:
> Right we should be especially careful of short options with ls.
> A long only option should suffice

OK, I installed the attached to implement 'ls --null'. (The last patch 
is the actual change; the other patches are cleanups.) This addresses 
the problem raised in the bug report.

Is there any pattern as to why some coreutils programs have a --null 
option and others have a --zero option? The two options seem to mean the 
same thing. Should we work toward standardizing on one spelling or the 
other (of course maintaining backward compatibility).
From 3753c706b7ccd756db955e850175b79f22911d57 Mon Sep 17 00:00:00 2001
From: Paul Eggert <[email-masked]>
Date: Sat, 17 Jul 2021 15:07:29 -0500
Subject: [PATCH 1/7] env: fix usage typo

* src/env.c (usage): Fix pluralization typo.
---
 src/env.c | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/src/env.c b/src/env.c
index 5a30696d9..685c24adb 100644
--- a/src/env.c
+++ b/src/env.c
@@ -141,7 +141,7 @@ Set each NAME to VALUE in the environment and run COMMAND.\n\
       --default-signal[=SIG]  reset handling of SIG signal(s) to the default\n\
 "), stdout);
       fputs (_("\
-      --ignore-signal[=SIG]   set handling of SIG signals(s) to do nothing\n\
+      --ignore-signal[=SIG]   set handling of SIG signal(s) to do nothing\n\
 "), stdout);
       fputs (_("\
       --list-signal-handling  list non default signal handling to stderr\n\
-- 
2.30.2

From 5622ab450e2402570cef48a5fed0eb0b4523b264 Mon Sep 17 00:00:00 2001
From: Paul Eggert <[email-masked]>
Date: Sun, 18 Jul 2021 00:12:29 -0500
Subject: [PATCH 2/7] maint: fix white space

---
 configure.ac     |  23 +++++---
 m4/jm-macros.m4  |   4 +-
 src/dd.c         |   2 +-
 src/expand.c     |   2 +-
 src/factor.c     | 143 ++++++++++++++++++++++++-----------------------
 src/set-fields.c |  24 ++++----
 src/stdbuf.c     |   2 +-
 src/unexpand.c   |   2 +-
 8 files changed, 105 insertions(+), 97 deletions(-)

diff --git a/configure.ac b/configure.ac
index c4d8ec0b6..6960b486a 100644
--- a/configure.ac
+++ b/configure.ac
@@ -287,7 +287,8 @@ void unset_TZ (void)
     if (! (to[0][0] == 'T' && to[0][1] == 'Z' && to[0][2] == '='))
       to++;
 }
-int main()
+int
+main ()
 {
   time_t now = time ((time_t *) 0);
   int hour_GMT0, hour_unset;
@@ -529,10 +530,11 @@ AC_LINK_IFELSE(
   [AC_LANG_SOURCE([[
     #include <cpuid.h>
 
-    int main(void)
+    int
+    main (void)
     {
       unsigned int eax, ebx, ecx, edx;
-      __get_cpuid(1, &eax, &ebx, &ecx, &edx);
+      __get_cpuid (1, &eax, &ebx, &ecx, &edx);
       return 1;
     }
   ]])
@@ -551,10 +553,11 @@ AC_COMPILE_IFELSE(
   [AC_LANG_SOURCE([[
     #include <x86intrin.h>
 
-    int main(void)
+    int
+    main (void)
     {
       __m128i a, b;
-      a = _mm_clmulepi64_si128(a, b, 0x00);
+      a = _mm_clmulepi64_si128 (a, b, 0x00);
       return 1;
     }
   ]])
@@ -580,10 +583,11 @@ AC_LINK_IFELSE(
   [AC_LANG_SOURCE([[
     #include <cpuid.h>
 
-    int main(void)
+    int
+    main (void)
     {
       unsigned int eax = 0, ebx = 0, ecx = 0, edx = 0;
-      __get_cpuid_count(7, 0, &eax, &ebx, &ecx, &edx);
+      __get_cpuid_count (7, 0, &eax, &ebx, &ecx, &edx);
       return 1;
     }
   ]])
@@ -600,10 +604,11 @@ AC_COMPILE_IFELSE(
   [AC_LANG_SOURCE([[
     #include <x86intrin.h>
 
-    int main(void)
+    int
+    main (void)
     {
       __m256i a, b;
-      a = _mm256_sad_epu8(a, b);
+      a = _mm256_sad_epu8 (a, b);
       return 1;
     }
   ]])
diff --git a/m4/jm-macros.m4 b/m4/jm-macros.m4
index fb66907f4..8ae9edf6c 100644
--- a/m4/jm-macros.m4
+++ b/m4/jm-macros.m4
@@ -1,4 +1,4 @@
-#serial 113   -*- autoconf -*-
+#serial 114   -*- autoconf -*-
 
 dnl Misc type-related macros for coreutils.
 
@@ -164,7 +164,7 @@ AC_DEFUN([coreutils_MACROS],
        [[#include <ieeefp.h>
        ]],
        [[#ifdef __i386__
-          fpsetprec(FP_PE);
+          fpsetprec (FP_PE);
          #else
          # error not required on 64 bit
          #endif
diff --git a/src/dd.c b/src/dd.c
index fc5108f8b..06be4b04e 100644
--- a/src/dd.c
+++ b/src/dd.c
@@ -1037,7 +1037,7 @@ quit (int code)
 }
 
 /* Return LEN rounded down to a multiple of IO_BUFSIZE
-   (to minimize calls to the expensive posix_fadvise(,POSIX_FADV_DONTNEED),
+   (to minimize calls to the expensive posix_fadvise (,POSIX_FADV_DONTNEED),
    while storing the remainder internally per FD.
    Pass LEN == 0 to get the current remainder.  */
 
diff --git a/src/expand.c b/src/expand.c
index dd9d2981a..4e32bfcbb 100644
--- a/src/expand.c
+++ b/src/expand.c
@@ -227,7 +227,7 @@ main (int argc, char **argv)
 
   finalize_tab_stops ();
 
-  set_file_list ( (optind < argc) ? &argv[optind] : NULL);
+  set_file_list ((optind < argc) ? &argv[optind] : NULL);
 
   expand ();
 
diff --git a/src/factor.c b/src/factor.c
index d1a6bb8e7..62a269fcf 100644
--- a/src/factor.c
+++ b/src/factor.c
@@ -265,10 +265,10 @@ static void factor (uintmax_t, uintmax_t, struct factors *);
     __x2 = (uintmax_t) __uh * __vl;                                     \
     __x3 = (uintmax_t) __uh * __vh;                                     \
                                                                         \
-    __x1 += __ll_highpart (__x0);/* this can't give carry */            \
-    __x1 += __x2;               /* but this indeed can */               \
-    if (__x1 < __x2)            /* did we get it? */                    \
-      __x3 += __ll_B;           /* yes, add it in the proper pos. */    \
+    __x1 += __ll_highpart (__x0);/* This can't give carry.  */		\
+    __x1 += __x2;		/* But this indeed can.  */		\
+    if (__x1 < __x2)		/* Did we get it?  */			\
+      __x3 += __ll_B;		/* Yes, add it in the proper pos.  */	\
                                                                         \
     (w1) = __x3 + __ll_highpart (__x1);                                 \
     (w0) = (__x1 << W_TYPE_SIZE / 2) + __ll_lowpart (__x0);             \
@@ -276,9 +276,9 @@ static void factor (uintmax_t, uintmax_t, struct factors *);
 #endif
 
 #if !defined udiv_qrnnd || defined UDIV_NEEDS_NORMALIZATION
-/* Define our own, not needing normalization. This function is
-   currently not performance critical, so keep it simple. Similar to
-   the mod macro below. */
+/* Define our own, not needing normalization.  This function is
+   currently not performance critical, so keep it simple.  Similar to
+   the mod macro below.  */
 # undef udiv_qrnnd
 # define udiv_qrnnd(q, r, n1, n0, d)                                    \
   do {                                                                  \
@@ -433,7 +433,7 @@ mod2 (uintmax_t *r1, uintmax_t a1, uintmax_t a0, uintmax_t d1, uintmax_t d0)
 static uintmax_t _GL_ATTRIBUTE_CONST
 gcd_odd (uintmax_t a, uintmax_t b)
 {
-  if ( (b & 1) == 0)
+  if ((b & 1) == 0)
     {
       uintmax_t t = b;
       b = a;
@@ -473,7 +473,7 @@ gcd2_odd (uintmax_t *r1, uintmax_t a1, uintmax_t a0, uintmax_t b1, uintmax_t b0)
 {
   assert (b0 & 1);
 
-  if ( (a0 | a1) == 0)
+  if ((a0 | a1) == 0)
     {
       *r1 = b1;
       return b0;
@@ -699,7 +699,7 @@ static bool dev_debug = false;
 /* Prove primality or run probabilistic tests.  */
 static bool flag_prove_primality = PROVE_PRIMALITY;
 
-/* Number of Miller-Rabin tests to run when not proving primality. */
+/* Number of Miller-Rabin tests to run when not proving primality.  */
 #define MR_REPS 25
 
 static void
@@ -713,22 +713,22 @@ factor_insert_refind (struct factors *factors, uintmax_t p, unsigned int i,
 
 /* Trial division with odd primes uses the following trick.
 
-   Let p be an odd prime, and B = 2^{W_TYPE_SIZE}. For simplicity,
+   Let p be an odd prime, and B = 2^{W_TYPE_SIZE}.  For simplicity,
    consider the case t < B (this is the second loop below).
 
    From our tables we get
 
      binv = p^{-1} (mod B)
-     lim = floor ( (B-1) / p ).
+     lim = floor ((B-1) / p).
 
-   First assume that t is a multiple of p, t = q * p. Then 0 <= q <= lim
+   First assume that t is a multiple of p, t = q * p.  Then 0 <= q <= lim
    (and all quotients in this range occur for some t).
 
    Then t = q * p is true also (mod B), and p is invertible we get
 
      q = t * binv (mod B).
 
-   Next, assume that t is *not* divisible by p. Since multiplication
+   Next, assume that t is *not* divisible by p.  Since multiplication
    by binv (mod B) is a one-to-one mapping,
 
      t * binv (mod B) > lim,
@@ -914,7 +914,7 @@ static const unsigned char  binvert_table[128] =
     _q0 = (u0) * _di;                                                   \
     if ((u1) >= (d))                                                    \
       {                                                                 \
-        uintmax_t _p1, _p0 _GL_UNUSED;                            \
+        uintmax_t _p1, _p0 _GL_UNUSED;					\
         umul_ppmm (_p1, _p0, _q0, d);                                   \
         (q1) = ((u1) - _p1) * _di;                                      \
         (q0) = _q0;                                                     \
@@ -926,14 +926,14 @@ static const unsigned char  binvert_table[128] =
       }                                                                 \
   } while (0)
 
-/* x B (mod n). */
+/* x B (mod n).  */
 #define redcify(r_prim, r, n)                                           \
   do {                                                                  \
-    uintmax_t _redcify_q _GL_UNUSED;                              \
+    uintmax_t _redcify_q _GL_UNUSED;					\
     udiv_qrnnd (_redcify_q, r_prim, r, 0, n);                           \
   } while (0)
 
-/* x B^2 (mod n). Requires x > 0, n1 < B/2 */
+/* x B^2 (mod n).  Requires x > 0, n1 < B/2.  */
 #define redcify2(r1, r0, x, n1, n0)                                     \
   do {                                                                  \
     uintmax_t _r1, _r0, _i;                                             \
@@ -958,7 +958,7 @@ static const unsigned char  binvert_table[128] =
   } while (0)
 
 /* Modular two-word multiplication, r = a * b mod m, with mi = m^(-1) mod B.
-   Both a and b must be in redc form, the result will be in redc form too. */
+   Both a and b must be in redc form, the result will be in redc form too.  */
 static inline uintmax_t
 mulredc (uintmax_t a, uintmax_t b, uintmax_t m, uintmax_t mi)
 {
@@ -976,7 +976,7 @@ mulredc (uintmax_t a, uintmax_t b, uintmax_t m, uintmax_t mi)
 
 /* Modular two-word multiplication, r = a * b mod m, with mi = m^(-1) mod B.
    Both a and b must be in redc form, the result will be in redc form too.
-   For performance reasons, the most significant bit of m must be clear. */
+   For performance reasons, the most significant bit of m must be clear.  */
 static uintmax_t
 mulredc2 (uintmax_t *r1p,
           uintmax_t a1, uintmax_t a0, uintmax_t b1, uintmax_t b0,
@@ -984,9 +984,9 @@ mulredc2 (uintmax_t *r1p,
 {
   uintmax_t r1, r0, q, p1, p0 _GL_UNUSED, t1, t0, s1, s0;
   mi = -mi;
-  assert ( (a1 >> (W_TYPE_SIZE - 1)) == 0);
-  assert ( (b1 >> (W_TYPE_SIZE - 1)) == 0);
-  assert ( (m1 >> (W_TYPE_SIZE - 1)) == 0);
+  assert ((a1 >> (W_TYPE_SIZE - 1)) == 0);
+  assert ((b1 >> (W_TYPE_SIZE - 1)) == 0);
+  assert ((m1 >> (W_TYPE_SIZE - 1)) == 0);
 
   /* First compute a0 * <b1, b0> B^{-1}
         +-----+
@@ -1112,7 +1112,7 @@ millerrabin (uintmax_t n, uintmax_t ni, uintmax_t b, uintmax_t q,
 {
   uintmax_t y = powm (b, q, n, ni, one);
 
-  uintmax_t nm1 = n - one;      /* -1, but in redc representation. */
+  uintmax_t nm1 = n - one;      /* -1, but in redc representation.  */
 
   if (y == one || y == nm1)
     return true;
@@ -1192,7 +1192,7 @@ prime_p (uintmax_t n)
   if (n <= 1)
     return false;
 
-  /* We have already casted out small primes. */
+  /* We have already casted out small primes.  */
   if (n < (uintmax_t) FIRST_OMITTED_PRIME * FIRST_OMITTED_PRIME)
     return true;
 
@@ -1231,7 +1231,7 @@ prime_p (uintmax_t n)
         }
       else
         {
-          /* After enough Miller-Rabin runs, be content. */
+          /* After enough Miller-Rabin runs, be content.  */
           is_prime = (r == MR_REPS - 1);
         }
 
@@ -1298,7 +1298,7 @@ prime2_p (uintmax_t n1, uintmax_t n0)
   redcify2 (one[1], one[0], 1, n1, n0);
   addmod2 (a_prim[1], a_prim[0], one[1], one[0], one[1], one[0], n1, n0);
 
-  /* FIXME: Use scalars or pointers in arguments? Some consistency needed. */
+  /* FIXME: Use scalars or pointers in arguments?  Some consistency needed.  */
   na[0] = n0;
   na[1] = n1;
 
@@ -1332,9 +1332,9 @@ prime2_p (uintmax_t n1, uintmax_t n0)
             }
           for (unsigned int i = 0; i < factors.nfactors && is_prime; i++)
             {
-              /* FIXME: We always have the factor 2. Do we really need to
-                 handle it here? We have done the same powering as part
-                 of millerrabin. */
+              /* FIXME: We always have the factor 2.  Do we really need to
+                 handle it here?  We have done the same powering as part
+                 of millerrabin.  */
               if (factors.p[i] == 2)
                 rsh2 (e[1], e[0], nm1[1], nm1[0], 1);
               else
@@ -1345,7 +1345,7 @@ prime2_p (uintmax_t n1, uintmax_t n0)
         }
       else
         {
-          /* After enough Miller-Rabin runs, be content. */
+          /* After enough Miller-Rabin runs, be content.  */
           is_prime = (r == MR_REPS - 1);
         }
 
@@ -1373,7 +1373,7 @@ mp_prime_p (mpz_t n)
   if (mpz_cmp_ui (n, 1) <= 0)
     return false;
 
-  /* We have already casted out small primes. */
+  /* We have already casted out small primes.  */
   if (mpz_cmp_ui (n, (long) FIRST_OMITTED_PRIME * FIRST_OMITTED_PRIME) < 0)
     return true;
 
@@ -1418,7 +1418,7 @@ mp_prime_p (mpz_t n)
         }
       else
         {
-          /* After enough Miller-Rabin runs, be content. */
+          /* After enough Miller-Rabin runs, be content.  */
           is_prime = (r == MR_REPS - 1);
         }
 
@@ -1463,7 +1463,7 @@ factor_using_pollard_rho (uintmax_t n, unsigned long int a,
     {
       assert (a < n);
 
-      binv (ni, n);             /* FIXME: when could we use old 'ni' value? */
+      binv (ni, n);             /* FIXME: when could we use old 'ni' value?  */
 
       for (;;)
         {
@@ -1598,7 +1598,7 @@ factor_using_pollard_rho2 (uintmax_t n1, uintmax_t n0, unsigned long int a,
 
       if (g1 == 0)
         {
-          /* The found factor is one word, and > 1. */
+          /* The found factor is one word, and > 1.  */
           divexact_21 (n1, n0, n1, n0, g0);     /* n = n / g */
 
           if (!prime_p (g0))
@@ -1619,9 +1619,12 @@ factor_using_pollard_rho2 (uintmax_t n1, uintmax_t n0, unsigned long int a,
               return;
             }
 
-          binv (ginv, g0);      /* Compute n = n / g.  Since the result will */
-          n0 = ginv * n0;       /* fit one word, we can compute the quotient */
-          n1 = 0;               /* modulo B, ignoring the high divisor word. */
+          /* Compute n = n / g.  Since the result will fit one word,
+             we can compute the quotient modulo B, ignoring the high
+             divisor word.  */
+          binv (ginv, g0);
+          n0 = ginv * n0;
+          n1 = 0;
 
           if (!prime2_p (g1, g0))
             factor_using_pollard_rho2 (g1, g0, a + 1, factors);
@@ -1747,7 +1750,7 @@ mp_factor_using_pollard_rho (mpz_t n, unsigned long int a,
 
 #if USE_SQUFOF
 /* FIXME: Maybe better to use an iteration converging to 1/sqrt(n)?  If
-   algorithm is replaced, consider also returning the remainder. */
+   algorithm is replaced, consider also returning the remainder.  */
 static uintmax_t _GL_ATTRIBUTE_CONST
 isqrt (uintmax_t n)
 {
@@ -1758,7 +1761,7 @@ isqrt (uintmax_t n)
 
   count_leading_zeros (c, n);
 
-  /* Make x > sqrt(n). This will be invariant through the loop. */
+  /* Make x > sqrt(n).  This will be invariant through the loop.  */
   x = (uintmax_t) 1 << ((W_TYPE_SIZE + 1 - c) / 2);
 
   for (;;)
@@ -1777,7 +1780,7 @@ isqrt2 (uintmax_t nh, uintmax_t nl)
   unsigned int shift;
   uintmax_t x;
 
-  /* Ensures the remainder fits in an uintmax_t. */
+  /* Ensures the remainder fits in an uintmax_t.  */
   assert (nh < ((uintmax_t) 1 << (W_TYPE_SIZE - 2)));
 
   if (nh == 0)
@@ -1786,11 +1789,11 @@ isqrt2 (uintmax_t nh, uintmax_t nl)
   count_leading_zeros (shift, nh);
   shift &= ~1;
 
-  /* Make x > sqrt(n) */
-  x = isqrt ( (nh << shift) + (nl >> (W_TYPE_SIZE - shift))) + 1;
+  /* Make x > sqrt (n).  */
+  x = isqrt ((nh << shift) + (nl >> (W_TYPE_SIZE - shift))) + 1;
   x <<= (W_TYPE_SIZE - shift) / 2;
 
-  /* Do we need more than one iteration? */
+  /* Do we need more than one iteration?  */
   for (;;)
     {
       uintmax_t r _GL_UNUSED;
@@ -1816,21 +1819,21 @@ isqrt2 (uintmax_t nh, uintmax_t nl)
     }
 }
 
-/* MAGIC[N] has a bit i set iff i is a quadratic residue mod N. */
+/* MAGIC[N] has a bit i set iff i is a quadratic residue mod N.  */
 # define MAGIC64 0x0202021202030213ULL
 # define MAGIC63 0x0402483012450293ULL
 # define MAGIC65 0x218a019866014613ULL
 # define MAGIC11 0x23b
 
-/* Return the square root if the input is a square, otherwise 0. */
+/* Return the square root if the input is a square, otherwise 0.  */
 static uintmax_t _GL_ATTRIBUTE_CONST
 is_square (uintmax_t x)
 {
-  /* Uses the tests suggested by Cohen. Excludes 99% of the non-squares before
-     computing the square root. */
+  /* Uses the tests suggested by Cohen.  Excludes 99% of the non-squares before
+     computing the square root.  */
   if (((MAGIC64 >> (x & 63)) & 1)
       && ((MAGIC63 >> (x % 63)) & 1)
-      /* Both 0 and 64 are squares mod (65) */
+      /* Both 0 and 64 are squares mod (65).  */
       && ((MAGIC65 >> ((x % 65) & 63)) & 1)
       && ((MAGIC11 >> (x % 11) & 1)))
     {
@@ -1841,7 +1844,7 @@ is_square (uintmax_t x)
   return 0;
 }
 
-/* invtab[i] = floor(0x10000 / (0x100 + i) */
+/* invtab[i] = floor (0x10000 / (0x100 + i) */
 static const unsigned short invtab[0x81] =
   {
     0x200,
@@ -1888,7 +1891,7 @@ static const unsigned short invtab[0x81] =
         _mask = -(uintmax_t) (_r >= (d));                               \
         (r) = _r - (_mask & (d));                                       \
         (q) = _q - _mask;                                               \
-        assert ( (q) * (d) + (r) == u);                                 \
+        assert ((q) * (d) + (r) == u);					\
       }                                                                 \
     else                                                                \
       {                                                                 \
@@ -1898,7 +1901,7 @@ static const unsigned short invtab[0x81] =
       }                                                                 \
   } while (0)
 
-/* Notes: Example N = 22117019. After first phase we find Q1 = 6314, Q
+/* Notes: Example N = 22117019.  After first phase we find Q1 = 6314, Q
    = 3025, P = 1737, representing F_{18} = (-6314, 2* 1737, 3025),
    with 3025 = 55^2.
 
@@ -1945,7 +1948,7 @@ static unsigned int q_freq[Q_FREQ_SIZE + 1];
 
 #if USE_SQUFOF
 /* Return true on success.  Expected to fail only for numbers
-   >= 2^{2*W_TYPE_SIZE - 2}, or close to that limit. */
+   >= 2^{2*W_TYPE_SIZE - 2}, or close to that limit.  */
 static bool
 factor_using_squfof (uintmax_t n1, uintmax_t n0, struct factors *factors)
 {
@@ -2016,7 +2019,7 @@ factor_using_squfof (uintmax_t n1, uintmax_t n0, struct factors *factors)
       assert (mu * n0 % 4 == 3);
 
       /* In the notation of the paper, with mu * n == 3 (mod 4), we
-         get \Delta = 4 mu * n, and the paper's \mu is 2 mu. As far as
+         get \Delta = 4 mu * n, and the paper's \mu is 2 mu.  As far as
          I understand it, the necessary bound is 4 \mu^3 < n, or 32
          mu^3 < n.
 
@@ -2024,7 +2027,7 @@ factor_using_squfof (uintmax_t n1, uintmax_t n0, struct factors *factors)
          105, we get a trivial factor, from the square 38809 = 197^2,
          without any corresponding Q earlier in the iteration.
 
-         Requiring 64 mu^3 < n seems sufficient. */
+         Requiring 64 mu^3 < n seems sufficient.  */
       if (n1 == 0)
         {
           if ((uintmax_t) mu*mu*mu >= n0 / 64)
@@ -2046,15 +2049,15 @@ factor_using_squfof (uintmax_t n1, uintmax_t n0, struct factors *factors)
       Q1 = 1;
       P = S;
 
-      /* Square root remainder fits in one word, so ignore high part. */
+      /* Square root remainder fits in one word, so ignore high part.  */
       Q = Dl - P*P;
-      /* FIXME: When can this differ from floor(sqrt(2 sqrt(D)))? */
+      /* FIXME: When can this differ from floor (sqrt (2 * sqrt (D)))?  */
       L = isqrt (2*S);
       B = 2*L;
       L1 = mu * 2 * L;
 
       /* The form is (+/- Q1, 2P, -/+ Q), of discriminant 4 (P^2 + Q Q1) =
-         4 D. */
+         4 D.  */
 
       for (i = 0; i <= B; i++)
         {
@@ -2074,7 +2077,7 @@ factor_using_squfof (uintmax_t n1, uintmax_t n0, struct factors *factors)
             {
               uintmax_t g = Q;
 
-              if ( (Q & 1) == 0)
+              if ((Q & 1) == 0)
                 g /= 2;
 
               g /= gcd_odd (g, mu);
@@ -2090,13 +2093,13 @@ factor_using_squfof (uintmax_t n1, uintmax_t n0, struct factors *factors)
             }
 
           /* I think the difference can be either sign, but mod
-             2^W_TYPE_SIZE arithmetic should be fine. */
+             2^W_TYPE_SIZE arithmetic should be fine.  */
           t = Q1 + q * (P - P1);
           Q1 = Q;
           Q = t;
           P = P1;
 
-          if ( (i & 1) == 0)
+          if ((i & 1) == 0)
             {
               uintmax_t r = is_square (Q);
               if (r)
@@ -2106,10 +2109,10 @@ factor_using_squfof (uintmax_t n1, uintmax_t n0, struct factors *factors)
                       if (queue[j].Q == r)
                         {
                           if (r == 1)
-                            /* Traversed entire cycle. */
+                            /* Traversed entire cycle.  */
                             goto next_multiplier;
 
-                          /* Need the absolute value for divisibility test. */
+                          /* Need the absolute value for divisibility test.  */
                           if (P >= queue[j].P)
                             t = P - queue[j].P;
                           else
@@ -2117,7 +2120,7 @@ factor_using_squfof (uintmax_t n1, uintmax_t n0, struct factors *factors)
                           if (t % r == 0)
                             {
                               /* Delete entries up to and including entry
-                                 j, which matched. */
+                                 j, which matched.  */
                               memmove (queue, queue + j + 1,
                                        (qpos - j - 1) * sizeof (queue[0]));
                               qpos -= (j + 1);
@@ -2127,15 +2130,15 @@ factor_using_squfof (uintmax_t n1, uintmax_t n0, struct factors *factors)
                     }
 
                   /* We have found a square form, which should give a
-                     factor. */
+                     factor.  */
                   Q1 = r;
-                  assert (S >= P); /* What signs are possible? */
+                  assert (S >= P); /* What signs are possible?  */
                   P += r * ((S - P) / r);
 
                   /* Note: Paper says (N - P*P) / Q1, that seems incorrect
-                     for the case D = 2N. */
+                     for the case D = 2N.  */
                   /* Compute Q = (D - P*P) / Q1, but we need double
-                     precision. */
+                     precision.  */
                   uintmax_t hi, lo;
                   umul_ppmm (hi, lo, P, P);
                   sub_ddmmss (hi, lo, Dh, Dl, hi, lo);
@@ -2148,7 +2151,7 @@ factor_using_squfof (uintmax_t n1, uintmax_t n0, struct factors *factors)
                          Step 4a in the algorithm description says q <--
                          floor([S+P]/\hat Q), but looking at the equations
                          in Sec. 3.1, it should be q <-- floor([S+P] / Q).
-                         (In this code, \hat Q is Q1). */
+                         (In this code, \hat Q is Q1).  */
                       div_smallq (q, rem, S+P, Q);
                       P1 = S - rem;     /* P1 = q*Q - P */
 
@@ -2164,7 +2167,7 @@ factor_using_squfof (uintmax_t n1, uintmax_t n0, struct factors *factors)
                       P = P1;
                     }
 
-                  if ( (Q & 1) == 0)
+                  if ((Q & 1) == 0)
                     Q /= 2;
                   Q /= gcd_odd (Q, mu);
 
diff --git a/src/set-fields.c b/src/set-fields.c
index 42f6c2189..a214ff21e 100644
--- a/src/set-fields.c
+++ b/src/set-fields.c
@@ -162,17 +162,17 @@ set_fields (char const *fieldstr, unsigned int options)
           in_digits = false;
           /* Starting a range. */
           if (dash_found)
-            FATAL_ERROR ( (options & SETFLD_ERRMSG_USE_POS)
-                          ?_("invalid byte or character range")
-                          :_("invalid field range"));
+            FATAL_ERROR ((options & SETFLD_ERRMSG_USE_POS)
+                         ? _("invalid byte or character range")
+                         : _("invalid field range"));
 
           dash_found = true;
           fieldstr++;
 
           if (lhs_specified && !value)
-            FATAL_ERROR ( (options & SETFLD_ERRMSG_USE_POS)
-                          ?_("byte/character positions are numbered from 1")
-                          :_("fields are numbered from 1"));
+            FATAL_ERROR ((options & SETFLD_ERRMSG_USE_POS)
+                         ? _("byte/character positions are numbered from 1")
+                         : _("fields are numbered from 1"));
 
           initial = (lhs_specified ? value : 1);
           value = 0;
@@ -216,9 +216,9 @@ set_fields (char const *fieldstr, unsigned int options)
             {
               /* A simple field number, not a range. */
               if (value == 0)
-                FATAL_ERROR ( (options & SETFLD_ERRMSG_USE_POS)
-                              ?_("byte/character positions are numbered from 1")
-                              :_("fields are numbered from 1"));
+                FATAL_ERROR ((options & SETFLD_ERRMSG_USE_POS)
+                             ? _("byte/character positions are numbered from 1")
+                             : _("fields are numbered from 1"));
 
               add_range_pair (value, value);
               value = 0;
@@ -275,9 +275,9 @@ set_fields (char const *fieldstr, unsigned int options)
     }
 
   if (!n_frp)
-    FATAL_ERROR ( (options&SETFLD_ERRMSG_USE_POS)
-                  ?_("missing list of byte/character positions")
-                  :_("missing list of fields"));
+    FATAL_ERROR ((options&SETFLD_ERRMSG_USE_POS)
+                 ? _("missing list of byte/character positions")
+                 : _("missing list of fields"));
 
   qsort (frp, n_frp, sizeof (frp[0]), compare_ranges);
 
diff --git a/src/stdbuf.c b/src/stdbuf.c
index dd39bd086..e8a0b6123 100644
--- a/src/stdbuf.c
+++ b/src/stdbuf.c
@@ -129,7 +129,7 @@ and are thus unaffected by 'stdbuf' settings.\n\
 /* argv[0] can be anything really, but generally it contains
    the path to the executable or just a name if it was executed
    using $PATH. In the latter case to get the path we can:
-   search getenv("PATH"), readlink("/prof/self/exe"), getenv("_"),
+   search getenv ("PATH"), readlink ("/prof/self/exe"), getenv ("_"),
    dladdr(), pstat_getpathname(), etc.  */
 
 static void
diff --git a/src/unexpand.c b/src/unexpand.c
index db0b74f24..cec392d6c 100644
--- a/src/unexpand.c
+++ b/src/unexpand.c
@@ -315,7 +315,7 @@ main (int argc, char **argv)
 
   finalize_tab_stops ();
 
-  set_file_list ( (optind < argc) ? &argv[optind] : NULL);
+  set_file_list ((optind < argc) ? &argv[optind] : NULL);
 
   unexpand ();
 
-- 
2.30.2

From 558959daa9fb04095c40153c494b5977ab675160 Mon Sep 17 00:00:00 2001
From: Paul Eggert <[email-masked]>
Date: Sat, 17 Jul 2021 15:47:56 -0500
Subject: [PATCH 3/7] build: update gnulib submodule to latest

---
 gnulib | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/gnulib b/gnulib
index ff7c8b21e..ec87cff2a 160000
--- a/gnulib
+++ b/gnulib
@@ -1 +1 @@
-Subproject commit ff7c8b21e259fdc4bc721ed55519cfee06739efa
+Subproject commit ec87cff2ac13f29f4aee88caa7e16e72cef3f490
-- 
2.30.2

From c09b25dd3f83f2db6d6dde57146b2ba747073308 Mon Sep 17 00:00:00 2001
From: Paul Eggert <[email-masked]>
Date: Sun, 25 Jul 2021 18:54:10 -0700
Subject: [PATCH 4/7] ls: simplify sprintf usage

* src/ls.c (format_user_or_group_width, print_long_format):
Use return value from sprintf instead of calling strlen on
the resulting buffer, or inferring the length some other way.
---
 src/ls.c | 38 ++++++++++++++------------------------
 1 file changed, 14 insertions(+), 24 deletions(-)

diff --git a/src/ls.c b/src/ls.c
index 1b20f17fe..a73aaf022 100644
--- a/src/ls.c
+++ b/src/ls.c
@@ -4227,8 +4227,7 @@ format_user_or_group_width (char const *name, unsigned long int id)
   else
     {
       char buf[INT_BUFSIZE_BOUND (id)];
-      sprintf (buf, "%lu", id);
-      return strlen (buf);
+      return sprintf (buf, "%lu", id);
     }
 }
 
@@ -4322,11 +4321,8 @@ print_long_format (const struct fileinfo *f)
   if (print_inode)
     {
       char hbuf[INT_BUFSIZE_BOUND (uintmax_t)];
-      sprintf (p, "%*s ", inode_number_width,
-               format_inode (hbuf, sizeof hbuf, f));
-      /* Increment by strlen (p) here, rather than by inode_number_width + 1.
-         The latter is wrong when inode_number_width is zero.  */
-      p += strlen (p);
+      p += sprintf (p, "%*s ", inode_number_width,
+                    format_inode (hbuf, sizeof hbuf, f));
     }
 
   if (print_block_size)
@@ -4349,13 +4345,9 @@ print_long_format (const struct fileinfo *f)
      "optional alternate access method flag".  */
   {
     char hbuf[INT_BUFSIZE_BOUND (uintmax_t)];
-    sprintf (p, "%s %*s ", modebuf, nlink_width,
-             ! f->stat_ok ? "?" : umaxtostr (f->stat.st_nlink, hbuf));
+    p += sprintf (p, "%s %*s ", modebuf, nlink_width,
+                  ! f->stat_ok ? "?" : umaxtostr (f->stat.st_nlink, hbuf));
   }
-  /* Increment by strlen (p) here, rather than by, e.g.,
-     sizeof modebuf - 2 + any_has_acl + 1 + nlink_width + 1.
-     The latter is wrong when nlink_width is zero.  */
-  p += strlen (p);
 
   DIRED_INDENT ();
 
@@ -4386,12 +4378,11 @@ print_long_format (const struct fileinfo *f)
       int blanks_width = (file_size_width
                           - (major_device_number_width + 2
                              + minor_device_number_width));
-      sprintf (p, "%*s, %*s ",
-               major_device_number_width + MAX (0, blanks_width),
-               umaxtostr (major (f->stat.st_rdev), majorbuf),
-               minor_device_number_width,
-               umaxtostr (minor (f->stat.st_rdev), minorbuf));
-      p += file_size_width + 1;
+      p += sprintf (p, "%*s, %*s ",
+                    major_device_number_width + MAX (0, blanks_width),
+                    umaxtostr (major (f->stat.st_rdev), majorbuf),
+                    minor_device_number_width,
+                    umaxtostr (minor (f->stat.st_rdev), minorbuf));
     }
   else
     {
@@ -4454,12 +4445,11 @@ print_long_format (const struct fileinfo *f)
       /* The time cannot be converted using the desired format, so
          print it as a huge integer number of seconds.  */
       char hbuf[INT_BUFSIZE_BOUND (intmax_t)];
-      sprintf (p, "%*s ", long_time_expected_width (),
-               (! f->stat_ok || ! btime_ok
-                ? "?"
-                : timetostr (when_timespec.tv_sec, hbuf)));
+      p += sprintf (p, "%*s ", long_time_expected_width (),
+                    (! f->stat_ok || ! btime_ok
+                     ? "?"
+                     : timetostr (when_timespec.tv_sec, hbuf)));
       /* FIXME: (maybe) We discarded when_timespec.tv_nsec. */
-      p += strlen (p);
     }
 
   DIRED_FPUTS (buf, stdout, p - buf);
-- 
2.30.2

From 0a41ad2cfb6aa7af21f40fc870a0b917410b1d4b Mon Sep 17 00:00:00 2001
From: Paul Eggert <[email-masked]>
Date: Sun, 25 Jul 2021 21:01:31 -0700
Subject: [PATCH 5/7] ls: demacroize
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit

Prefer functions or constants to macros where either will do.
That’s cleaner, and nowadays there’s no performance reason to
prefer macros.  All uses changed.
* src/ls.c (INITIAL_TABLE_SIZE, MIN_COLUMN_WIDTH):
Now constants instead of macros.
(file_or_link_mode): New function, replacing the old macro
FILE_OR_LINK_MODE.
(dired_outbyte): New function, replacing the old macro DIRED_PUTCHAR.
(dired_outbuf): New function, replacing the old macro DIRED_FPUTS.
(dired_outstring): New function, replacing the old macro
DIRED_FPUTS_LITERAL.
(dired_indent): New function, replacing the old macro DIRED_INDENT.
(push_current_dired_pos): New function, replacing the old macro
PUSH_CURRENT_DIRED_POS.
(assert_matching_dev_ino): New function, replacing the old macro
ASSERT_MATCHING_DEV_INO.
(do_stat, do_lstat, stat_for_mode, stat_for_ino, fstat_for_ino)
(signal_init, signal_restore, cmp_ctime, cmp_mtime, cmp_atime)
(cmp_btime, cmp_size, cmp_name, cmp_extension)
(fileinfo_name_width, cmp_width, cmp_version):
No longer inline; compilers can deduce this well enough nowadays.
(main): Protect unused assert with ‘if (false)’ rather than
commenting it out, so that the compiler checks the code.
(print_dir): Output the space and newline in the same buffer
as the human-readable number they surround.
(dirfirst_check): New function, replacing the old macro
DIRFIRST_CHECK.  Simplify by using subtraction.
(off_cmp): New function, replacing the old macro longdiff.
(print_long_format): No need to null-terminate the string now.
(format_user_or_group): Let printf count the bytes.
---
 src/ls.c | 275 ++++++++++++++++++++++++++++---------------------------
 1 file changed, 140 insertions(+), 135 deletions(-)

diff --git a/src/ls.c b/src/ls.c
index a73aaf022..efb87e405 100644
--- a/src/ls.c
+++ b/src/ls.c
@@ -135,10 +135,6 @@
 #define obstack_chunk_alloc malloc
 #define obstack_chunk_free free
 
-/* Return an int indicating the result of comparing two integers.
-   Subtracting doesn't always work, due to overflow.  */
-#define longdiff(a, b) ((a) < (b) ? -1 : (a) > (b))
-
 /* Unix-based readdir implementations have historically returned a dirent.d_ino
    value that is sometimes not equal to the stat-obtained st_ino value for
    that same entry.  This error occurs for a readdir entry that refers
@@ -316,7 +312,7 @@ static size_t quote_name_width (char const *name,
 
 /* Initial size of hash table.
    Most hierarchies are likely to be shallower than this.  */
-#define INITIAL_TABLE_SIZE 30
+enum { INITIAL_TABLE_SIZE = 30 };
 
 /* The set of 'active' directories, from the current command-line argument
    to the level in the hierarchy at which files are being listed.
@@ -366,9 +362,12 @@ static bool color_symlink_as_referent;
 static char const *hostname;
 
 /* mode of appropriate file for colorization */
-#define FILE_OR_LINK_MODE(File) \
-    ((color_symlink_as_referent && (File)->linkok) \
-     ? (File)->linkmode : (File)->stat.st_mode)
+static mode_t
+file_or_link_mode (struct fileinfo const *file)
+{
+  return (color_symlink_as_referent && file->linkok
+          ? file->linkmode : file->stat.st_mode);
+}

 /* Record of one pending directory waiting to be listed.  */
@@ -965,33 +964,43 @@ static size_t max_idx;
 
 /* The minimum width of a column is 3: 1 character for the name and 2
    for the separating white space.  */
-#define MIN_COLUMN_WIDTH	3
+enum { MIN_COLUMN_WIDTH = 3 };

-/* This zero-based index is used solely with the --dired option.
-   When that option is in effect, this counter is incremented for each
-   byte of output generated by this program so that the beginning
+/* This zero-based index is for the --dired option.  It is incremented
+   for each byte of output generated by this program so that the beginning
    and ending indices (in that output) of every file name can be recorded
    and later output themselves.  */
 static size_t dired_pos;
 
-#define DIRED_PUTCHAR(c) do {putchar ((c)); ++dired_pos;} while (0)
+static void
+dired_outbyte (char c)
+{
+  dired_pos++;
+  putchar (c);
+}
 
-/* Write S to STREAM and increment DIRED_POS by S_LEN.  */
-#define DIRED_FPUTS(s, stream, s_len) \
-    do {fputs (s, stream); dired_pos += s_len;} while (0)
+/* Output the buffer S, of length S_LEN, and increment DIRED_POS by S_LEN.  */
+static void
+dired_outbuf (char const *s, size_t s_len)
+{
+  dired_pos += s_len;
+  fwrite (s, sizeof *s, s_len, stdout);
+}
 
-/* Like DIRED_FPUTS, but for use when S is a literal string.  */
-#define DIRED_FPUTS_LITERAL(s, stream) \
-    do {fputs (s, stream); dired_pos += sizeof (s) - 1;} while (0)
+/* Output the string S, and increment DIRED_POS by its length.  */
+static void
+dired_outstring (char const *s)
+{
+  dired_outbuf (s, strlen (s));
+}
 
-#define DIRED_INDENT()							\
-    do									\
-      {									\
-        if (dired)							\
-          DIRED_FPUTS_LITERAL ("  ", stdout);				\
-      }									\
-    while (0)
+static void
+dired_indent (void)
+{
+  if (dired)
+    dired_outstring ("  ");
+}
 
 /* With --dired, store pairs of beginning and ending indices of file names.  */
 static struct obstack dired_obstack;
@@ -1004,13 +1013,12 @@ static struct obstack dired_obstack;
 static struct obstack subdired_obstack;
 
 /* Save the current index on the specified obstack, OBS.  */
-#define PUSH_CURRENT_DIRED_POS(obs)					\
-  do									\
-    {									\
-      if (dired)							\
-        obstack_grow (obs, &dired_pos, sizeof (dired_pos));		\
-    }									\
-  while (0)
+static void
+push_current_dired_pos (struct obstack *obs)
+{
+  if (dired)
+    obstack_grow (obs, &dired_pos, sizeof dired_pos);
+}
 
 /* With -R, this stack is used to help detect directory cycles.
    The device/inode pairs on this stack mirror the pairs in the
@@ -1047,18 +1055,15 @@ dev_ino_pop (void)
   return *di;
 }
 
-/* Note the use commented out below:
-#define ASSERT_MATCHING_DEV_INO(Name, Di)	\
-  do						\
-    {						\
-      struct stat sb;				\
-      assert (Name);				\
-      assert (0 <= stat (Name, &sb));		\
-      assert (sb.st_dev == Di.st_dev);		\
-      assert (sb.st_ino == Di.st_ino);		\
-    }						\
-  while (0)
-*/
+static void
+assert_matching_dev_ino (char const *name, struct dev_ino di)
+{
+  struct stat sb;
+  assert (name);
+  assert (0 <= stat (name, &sb));
+  assert (sb.st_dev == di.st_dev);
+  assert (sb.st_ino == di.st_ino);
+}
 
 /* Write to standard output PREFIX, followed by the quoting style and
    a space-separated list of the integers stored in OS all on one line.  */
@@ -1181,62 +1186,62 @@ do_statx (int fd, char const *name, struct stat *st, int flags,
   return ret;
 }
 
-static inline int
+static int
 do_stat (char const *name, struct stat *st)
 {
   return do_statx (AT_FDCWD, name, st, 0, calc_req_mask ());
 }
 
-static inline int
+static int
 do_lstat (char const *name, struct stat *st)
 {
   return do_statx (AT_FDCWD, name, st, AT_SYMLINK_NOFOLLOW, calc_req_mask ());
 }
 
-static inline int
+static int
 stat_for_mode (char const *name, struct stat *st)
 {
   return do_statx (AT_FDCWD, name, st, 0, STATX_MODE);
 }
 
 /* dev+ino should be static, so no need to sync with backing store */
-static inline int
+static int
 stat_for_ino (char const *name, struct stat *st)
 {
   return do_statx (AT_FDCWD, name, st, 0, STATX_INO);
 }
 
-static inline int
+static int
 fstat_for_ino (int fd, struct stat *st)
 {
   return do_statx (fd, "", st, AT_EMPTY_PATH, STATX_INO);
 }
 #else
-static inline int
+static int
 do_stat (char const *name, struct stat *st)
 {
   return stat (name, st);
 }
 
-static inline int
+static int
 do_lstat (char const *name, struct stat *st)
 {
   return lstat (name, st);
 }
 
-static inline int
+static int
 stat_for_mode (char const *name, struct stat *st)
 {
   return stat (name, st);
 }
 
-static inline int
+static int
 stat_for_ino (char const *name, struct stat *st)
 {
   return stat (name, st);
 }
 
-static inline int
+static int
 fstat_for_ino (int fd, struct stat *st)
 {
   return fstat (fd, st);
@@ -1614,13 +1619,13 @@ signal_setup (bool init)
     }
 }
 
-static inline void
+static void
 signal_init (void)
 {
   signal_setup (true);
 }
 
-static inline void
+static void
 signal_restore (void)
 {
   signal_setup (false);
@@ -1756,7 +1761,7 @@ main (int argc, char **argv)
     {
       print_current_files ();
       if (pending_dirs)
-        DIRED_PUTCHAR ('\n');
+        dired_outbyte ('\n');
     }
   else if (n_files <= 1 && pending_dirs && pending_dirs->next == 0)
     print_dir_name = false;
@@ -1776,7 +1781,8 @@ main (int argc, char **argv)
                  entry from the active_dir_set hash table.  */
               struct dev_ino di = dev_ino_pop ();
               struct dev_ino *found = hash_remove (active_dir_set, &di);
-              /* ASSERT_MATCHING_DEV_INO (thispend->realname, di); */
+              if (false)
+                assert_matching_dev_ino (thispend->realname, di);
               assert (found);
               dev_ino_free (found);
               free_pending_ent (thispend);
@@ -2957,9 +2963,9 @@ print_dir (char const *name, char const *realname, bool command_line_arg)
   if (recursive || print_dir_name)
     {
       if (!first)
-        DIRED_PUTCHAR ('\n');
+        dired_outbyte ('\n');
       first = false;
-      DIRED_INDENT ();
+      dired_indent ();
 
       char *absolute_name = NULL;
       if (print_hyperlink)
@@ -2974,7 +2980,7 @@ print_dir (char const *name, char const *realname, bool command_line_arg)
 
       free (absolute_name);
 
-      DIRED_FPUTS_LITERAL (":\n", stdout);
+      dired_outstring (":\n");
     }
 
   /* Read the directory entries, and insert the subfiles into the 'cwd_file'
@@ -3059,17 +3065,15 @@ print_dir (char const *name, char const *realname, bool command_line_arg)
 
   if (format == long_format || print_block_size)
     {
-      char const *p;
-      char buf[LONGEST_HUMAN_READABLE + 1];
-
-      DIRED_INDENT ();
-      p = _("total");
-      DIRED_FPUTS (p, stdout, strlen (p));
-      DIRED_PUTCHAR (' ');
-      p = human_readable (total_blocks, buf, human_output_opts,
-                          ST_NBLOCKSIZE, output_block_size);
-      DIRED_FPUTS (p, stdout, strlen (p));
-      DIRED_PUTCHAR ('\n');
+      char buf[LONGEST_HUMAN_READABLE + 3];
+      char *p = human_readable (total_blocks, buf + 1, human_output_opts,
+                                ST_NBLOCKSIZE, output_block_size);
+      char *pend = p + strlen (p);
+      *--p = ' ';
+      *pend++ = '\n';
+      dired_indent ();
+      dired_outstring (_("total"));
+      dired_outbuf (p, pend - p);
     }
 
   if (cwd_n_used)
@@ -3777,20 +3781,14 @@ xstrcoll (char const *a, char const *b)
 typedef void const *V;
 typedef int (*qsortFunc)(V a, V b);
 
-/* Used below in DEFINE_SORT_FUNCTIONS for _df_ sort function variants.
-   The do { ... } while(0) makes it possible to use the macro more like
-   a statement, without violating C89 rules: */
-#define DIRFIRST_CHECK(a, b)						\
-  do									\
-    {									\
-      bool a_is_dir = is_linked_directory ((struct fileinfo const *) a);\
-      bool b_is_dir = is_linked_directory ((struct fileinfo const *) b);\
-      if (a_is_dir && !b_is_dir)					\
-        return -1;         /* a goes before b */			\
-      if (!a_is_dir && b_is_dir)					\
-        return 1;          /* b goes before a */			\
-    }									\
-  while (0)
+/* Used below in DEFINE_SORT_FUNCTIONS for _df_ sort function variants.  */
+static int
+dirfirst_check (struct fileinfo const *a, struct fileinfo const *b,
+                int (*cmp) (V, V))
+{
+  int diff = is_linked_directory (b) - is_linked_directory (a);
+  return diff ? diff : cmp (a, b);
+}
 
 /* Define the 8 different sort function variants required for each sortkey.
    KEY_NAME is a token describing the sort key, e.g., ctime, atime, size.
@@ -3812,17 +3810,17 @@ typedef int (*qsortFunc)(V a, V b);
                                                                         \
   /* direct, dirfirst versions */					\
   static int xstrcoll_df_##key_name (V a, V b)				\
-  { DIRFIRST_CHECK (a, b); return key_cmp_func (a, b, xstrcoll); }	\
+  { return dirfirst_check (a, b, xstrcoll_##key_name); }		\
   static int _GL_ATTRIBUTE_PURE strcmp_df_##key_name (V a, V b)		\
-  { DIRFIRST_CHECK (a, b); return key_cmp_func (a, b, strcmp); }	\
+  { return dirfirst_check (a, b, strcmp_##key_name); }			\
                                                                         \
   /* reverse, dirfirst versions */					\
   static int rev_xstrcoll_df_##key_name (V a, V b)			\
-  { DIRFIRST_CHECK (a, b); return key_cmp_func (b, a, xstrcoll); }	\
+  { return dirfirst_check (a, b, rev_xstrcoll_##key_name); }		\
   static int _GL_ATTRIBUTE_PURE rev_strcmp_df_##key_name (V a, V b)	\
-  { DIRFIRST_CHECK (a, b); return key_cmp_func (b, a, strcmp); }
+  { return dirfirst_check (a, b, rev_strcmp_##key_name); }
 
-static inline int
+static int
 cmp_ctime (struct fileinfo const *a, struct fileinfo const *b,
            int (*cmp) (char const *, char const *))
 {
@@ -3831,7 +3829,7 @@ cmp_ctime (struct fileinfo const *a, struct fileinfo const *b,
   return diff ? diff : cmp (a->name, b->name);
 }
 
-static inline int
+static int
 cmp_mtime (struct fileinfo const *a, struct fileinfo const *b,
            int (*cmp) (char const *, char const *))
 {
@@ -3840,7 +3838,7 @@ cmp_mtime (struct fileinfo const *a, struct fileinfo const *b,
   return diff ? diff : cmp (a->name, b->name);
 }
 
-static inline int
+static int
 cmp_atime (struct fileinfo const *a, struct fileinfo const *b,
            int (*cmp) (char const *, char const *))
 {
@@ -3849,7 +3847,7 @@ cmp_atime (struct fileinfo const *a, struct fileinfo const *b,
   return diff ? diff : cmp (a->name, b->name);
 }
 
-static inline int
+static int
 cmp_btime (struct fileinfo const *a, struct fileinfo const *b,
            int (*cmp) (char const *, char const *))
 {
@@ -3858,15 +3856,21 @@ cmp_btime (struct fileinfo const *a, struct fileinfo const *b,
   return diff ? diff : cmp (a->name, b->name);
 }
 
-static inline int
+static int
+off_cmp (off_t a, off_t b)
+{
+  return a < b ? -1 : a > b;
+}
+
+static int
 cmp_size (struct fileinfo const *a, struct fileinfo const *b,
           int (*cmp) (char const *, char const *))
 {
-  int diff = longdiff (b->stat.st_size, a->stat.st_size);
+  int diff = off_cmp (b->stat.st_size, a->stat.st_size);
   return diff ? diff : cmp (a->name, b->name);
 }
 
-static inline int
+static int
 cmp_name (struct fileinfo const *a, struct fileinfo const *b,
           int (*cmp) (char const *, char const *))
 {
@@ -3876,7 +3880,7 @@ cmp_name (struct fileinfo const *a, struct fileinfo const *b,
 /* Compare file extensions.  Files with no extension are 'smallest'.
    If extensions are the same, compare by file names instead.  */
 
-static inline int
+static int
 cmp_extension (struct fileinfo const *a, struct fileinfo const *b,
                int (*cmp) (char const *, char const *))
 {
@@ -3889,7 +3893,7 @@ cmp_extension (struct fileinfo const *a, struct fileinfo const *b,
 /* Return the (cached) screen width,
    for the NAME associated with the passed fileinfo F.  */
 
-static inline size_t
+static size_t
 fileinfo_name_width (struct fileinfo const *f)
 {
   return f->width
@@ -3897,7 +3901,7 @@ fileinfo_name_width (struct fileinfo const *f)
          : quote_name_width (f->name, filename_quoting_options, f->quoted);
 }
 
-static inline int
+static int
 cmp_width (struct fileinfo const *a, struct fileinfo const *b,
           int (*cmp) (char const *, char const *))
 {
@@ -3923,20 +3927,32 @@ DEFINE_SORT_FUNCTIONS (width, cmp_width)
    because they all use a string comparison (either as the primary or secondary
    sort key), and xstrcoll has the ability to do a longjmp if strcoll fails for
    locale reasons.  Lastly, filevercmp is ALWAYS available with gnulib.  */
-static inline int
+static int
 cmp_version (struct fileinfo const *a, struct fileinfo const *b)
 {
   return filevercmp (a->name, b->name);
 }
 
-static int xstrcoll_version (V a, V b)
-{ return cmp_version (a, b); }
-static int rev_xstrcoll_version (V a, V b)
-{ return cmp_version (b, a); }
-static int xstrcoll_df_version (V a, V b)
-{ DIRFIRST_CHECK (a, b); return cmp_version (a, b); }
-static int rev_xstrcoll_df_version (V a, V b)
-{ DIRFIRST_CHECK (a, b); return cmp_version (b, a); }
+static int
+xstrcoll_version (V a, V b)
+{
+  return cmp_version (a, b);
+}
+static int
+rev_xstrcoll_version (V a, V b)
+{
+  return cmp_version (b, a);
+}
+static int
+xstrcoll_df_version (V a, V b)
+{
+  return dirfirst_check (a, b, xstrcoll_version);
+}
+static int
+rev_xstrcoll_df_version (V a, V b)
+{
+  return dirfirst_check (a, b, rev_xstrcoll_version);
+}

 /* We have 2^3 different variants for each sort-key function
@@ -4111,7 +4127,7 @@ print_current_files (void)
         {
           set_normal_color ();
           print_long_format (sorted_file[i]);
-          DIRED_PUTCHAR ('\n');
+          dired_outbyte ('\n');
         }
       break;
     }
@@ -4173,26 +4189,18 @@ long_time_expected_width (void)
 static void
 format_user_or_group (char const *name, unsigned long int id, int width)
 {
-  size_t len;
-
   if (name)
     {
       int width_gap = width - mbswidth (name, 0);
       int pad = MAX (0, width_gap);
-      fputs (name, stdout);
-      len = strlen (name) + pad;
+      dired_outstring (name);
 
       do
-        putchar (' ');
+        dired_outbyte (' ');
       while (pad--);
     }
   else
-    {
-      printf ("%*lu ", width, id);
-      len = width;
-    }
-
-  dired_pos += len + 1;
+    dired_pos += printf ("%*lu ", width, id);
 }
 
 /* Print the name or id of the user with id U, using a print width of
@@ -4349,11 +4357,11 @@ print_long_format (const struct fileinfo *f)
                   ! f->stat_ok ? "?" : umaxtostr (f->stat.st_nlink, hbuf));
   }
 
-  DIRED_INDENT ();
+  dired_indent ();
 
   if (print_owner || print_group || print_author || print_scontext)
     {
-      DIRED_FPUTS (buf, stdout, p - buf);
+      dired_outbuf (buf, p - buf);
 
       if (print_owner)
         format_user (f->stat.st_uid, owner_width, f->stat_ok);
@@ -4424,7 +4432,7 @@ print_long_format (const struct fileinfo *f)
       six_months_ago.tv_nsec = current_time.tv_nsec;
 
       recent = (timespec_cmp (six_months_ago, when_timespec) < 0
-                && (timespec_cmp (when_timespec, current_time) < 0));
+                && timespec_cmp (when_timespec, current_time) < 0);
 
       /* We assume here that all time zones are offset from UTC by a
          whole number of seconds.  */
@@ -4436,9 +4444,6 @@ print_long_format (const struct fileinfo *f)
     {
       p += s;
       *p++ = ' ';
-
-      /* NUL-terminate the string -- fputs (via DIRED_FPUTS) requires it.  */
-      *p = '\0';
     }
   else
     {
@@ -4452,14 +4457,14 @@ print_long_format (const struct fileinfo *f)
       /* FIXME: (maybe) We discarded when_timespec.tv_nsec. */
     }
 
-  DIRED_FPUTS (buf, stdout, p - buf);
+  dired_outbuf (buf, p - buf);
   size_t w = print_name_with_quoting (f, false, &dired_obstack, p - buf);
 
   if (f->filetype == symbolic_link)
     {
       if (f->linkname)
         {
-          DIRED_FPUTS_LITERAL (" -> ", stdout);
+          dired_outstring (" -> ");
           print_name_with_quoting (f, true, NULL, (p - buf) + w + 4);
           if (indicator_style != none)
             print_type_indicator (true, f->linkmode, unknown);
@@ -4727,7 +4732,7 @@ quote_name (char const *name, struct quoting_options const *options,
                         needs_general_quoting, NULL, &pad);
 
   if (pad && allow_pad)
-      DIRED_PUTCHAR (' ');
+    dired_outbyte (' ');
 
   if (color)
     print_color_indicator (color);
@@ -4756,14 +4761,14 @@ quote_name (char const *name, struct quoting_options const *options,
     }
 
   if (stack)
-    PUSH_CURRENT_DIRED_POS (stack);
+    push_current_dired_pos (stack);
 
   fwrite (buf + skip_quotes, 1, len - (skip_quotes * 2), stdout);
 
   dired_pos += len;
 
   if (stack)
-    PUSH_CURRENT_DIRED_POS (stack);
+    push_current_dired_pos (stack);
 
   if (absolute_name)
     {
@@ -4898,7 +4903,7 @@ print_type_indicator (bool stat_ok, mode_t mode, enum filetype type)
 {
   char c = get_type_indicator (stat_ok, mode, type);
   if (c)
-    DIRED_PUTCHAR (c);
+    dired_outbyte (c);
   return !!c;
 }
 
@@ -4939,7 +4944,7 @@ get_color_indicator (const struct fileinfo *f, bool symlink_target)
   else
     {
       name = f->name;
-      mode = FILE_OR_LINK_MODE (f);
+      mode = file_or_link_mode (f);
       linkok = f->linkok;
     }
 
-- 
2.30.2

From 39673b6d4cffe6315d2a572c3741777b3f6a3d28 Mon Sep 17 00:00:00 2001
From: Paul Eggert <[email-masked]>
Date: Mon, 26 Jul 2021 00:26:32 -0700
Subject: [PATCH 6/7] ls: port to wider off_t, uid_t, gid_t

* src/ls.c (dired_pos): Now off_t, not size_t, since it counts
output file offsets.
(dired_dump_obstack): This obstack's file offsets are now
off_t, not size_t.
(format_user_or_group, format_user_or_group_width):
ID arg is now uintmax_t, not unsigned long, since uid_t and
gid_t values might exceed ULONG_MAX.
(format_user_or_group_width): Use snprintf with NULL instead of
sprintf with a discarded buffer.  This avoids a stack buffer,
and so should be safer.
---
 src/ls.c | 20 ++++++++++----------
 1 file changed, 10 insertions(+), 10 deletions(-)

diff --git a/src/ls.c b/src/ls.c
index efb87e405..e442118ec 100644
--- a/src/ls.c
+++ b/src/ls.c
@@ -971,7 +971,7 @@ enum { MIN_COLUMN_WIDTH = 3 };
    for each byte of output generated by this program so that the beginning
    and ending indices (in that output) of every file name can be recorded
    and later output themselves.  */
-static size_t dired_pos;
+static off_t dired_pos;
 
 static void
 dired_outbyte (char c)
@@ -1076,10 +1076,13 @@ dired_dump_obstack (char const *prefix, struct obstack *os)
   n_pos = obstack_object_size (os) / sizeof (dired_pos);
   if (n_pos > 0)
     {
-      size_t *pos = (size_t *) obstack_finish (os);
+      off_t *pos = obstack_finish (os);
       fputs (prefix, stdout);
       for (size_t i = 0; i < n_pos; i++)
-        printf (" %lu", (unsigned long int) pos[i]);
+        {
+          intmax_t p = pos[i];
+          printf (" %"PRIdMAX, p);
+        }
       putchar ('\n');
     }
 }
@@ -4187,7 +4190,7 @@ long_time_expected_width (void)
    print width of WIDTH columns.  */
 
 static void
-format_user_or_group (char const *name, unsigned long int id, int width)
+format_user_or_group (char const *name, uintmax_t id, int width)
 {
   if (name)
     {
@@ -4200,7 +4203,7 @@ format_user_or_group (char const *name, unsigned long int id, int width)
       while (pad--);
     }
   else
-    dired_pos += printf ("%*lu ", width, id);
+    dired_pos += printf ("%*"PRIuMAX" ", width, id);
 }
 
 /* Print the name or id of the user with id U, using a print width of
@@ -4225,7 +4228,7 @@ format_group (gid_t g, int width, bool stat_ok)
 /* Return the number of columns that format_user_or_group will print.  */
 
 static int
-format_user_or_group_width (char const *name, unsigned long int id)
+format_user_or_group_width (char const *name, uintmax_t id)
 {
   if (name)
     {
@@ -4233,10 +4236,7 @@ format_user_or_group_width (char const *name, unsigned long int id)
       return MAX (0, len);
     }
   else
-    {
-      char buf[INT_BUFSIZE_BOUND (id)];
-      return sprintf (buf, "%lu", id);
-    }
+    return snprintf (NULL, 0, "%"PRIuMAX, id);
 }
 
 /* Return the number of columns that format_user will print.  */
-- 
2.30.2

From 7d44ac224c93940d1a708442c1edf1a927be7057 Mon Sep 17 00:00:00 2001
From: Paul Eggert <[email-masked]>
Date: Sun, 25 Jul 2021 21:24:02 -0700
Subject: [PATCH 7/7] ls: add --null option (Bug#49716)

* NEWS, doc/coreutils.texi (General output formatting):
* src/ls.c (usage): Document this.
* src/ls.c (NULL_OPTION): New constant.
(long_options): Add --null.
(eolbyte): New static var.
(dired_dump_obstack, main, print_dir, print_current_files)
(print_many_per_line, print_horizontal, print_with_separator):
Output eolbyte instead of '\n'.
(decode_switches): Decode --null.
* tests/ls/null-option.sh: New file.
* tests/local.mk (all_tests): Add it.
---
 NEWS                    |  3 +++
 doc/coreutils.texi      |  4 ++++
 src/ls.c                | 39 +++++++++++++++++++++++++--------------
 tests/local.mk          |  1 +
 tests/ls/null-option.sh | 33 +++++++++++++++++++++++++++++++++
 5 files changed, 66 insertions(+), 14 deletions(-)
 create mode 100755 tests/ls/null-option.sh

diff --git a/NEWS b/NEWS
index 5a1a98ace..8de0c31bd 100644
--- a/NEWS
+++ b/NEWS
@@ -83,6 +83,9 @@ GNU coreutils NEWS                                    -*- outline -*-
   ls now accepts the --sort=width option, to sort by file name width.
   This is useful to more compactly organize the default vertical column output.
 
+  ls now accepts the --null option, to terminate each output line with
+  NUL instead of newline.
+
   nl --line-increment can now take a negative number to decrement the count.
 
   stat supports more formats for representing decomposed device numbers.
diff --git a/doc/coreutils.texi b/doc/coreutils.texi
index ea040458e..a7e5ecb92 100644
--- a/doc/coreutils.texi
+++ b/doc/coreutils.texi
@@ -8137,6 +8137,10 @@ option.  It does not affect the file size written by @option{-l}.
 List files horizontally, with as many as will fit on each line,
 separated by @samp{, } (a comma and a space).
 
+@item --null
+@opindex --null
+@outputNUL
+
 @item -p
 @itemx --indicator-style=slash
 @opindex -p
diff --git a/src/ls.c b/src/ls.c
index e442118ec..61759fde9 100644
--- a/src/ls.c
+++ b/src/ls.c
@@ -838,6 +838,7 @@ enum
   HIDE_OPTION,
   HYPERLINK_OPTION,
   INDICATOR_STYLE_OPTION,
+  NULL_OPTION,
   QUOTING_STYLE_OPTION,
   SHOW_CONTROL_CHARS_OPTION,
   SI_OPTION,
@@ -858,6 +859,7 @@ static struct option const long_options[] =
   {"human-readable", no_argument, NULL, 'h'},
   {"inode", no_argument, NULL, 'i'},
   {"kibibytes", no_argument, NULL, 'k'},
+  {"null", no_argument, NULL, NULL_OPTION},
   {"numeric-uid-gid", no_argument, NULL, 'n'},
   {"no-group", no_argument, NULL, 'G'},
   {"hide-control-chars", no_argument, NULL, 'q'},
@@ -1065,6 +1067,8 @@ assert_matching_dev_ino (char const *name, struct dev_ino di)
   assert (sb.st_ino == di.st_ino);
 }
 
+static char eolbyte = '\n';
+
 /* Write to standard output PREFIX, followed by the quoting style and
    a space-separated list of the integers stored in OS all on one line.  */
 
@@ -1083,7 +1087,7 @@ dired_dump_obstack (char const *prefix, struct obstack *os)
           intmax_t p = pos[i];
           printf (" %"PRIdMAX, p);
         }
-      putchar ('\n');
+      putchar (eolbyte);
     }
 }
 
@@ -1764,7 +1768,7 @@ main (int argc, char **argv)
     {
       print_current_files ();
       if (pending_dirs)
-        dired_outbyte ('\n');
+        dired_outbyte (eolbyte);
     }
   else if (n_files <= 1 && pending_dirs && pending_dirs->next == 0)
     print_dir_name = false;
@@ -1832,8 +1836,9 @@ main (int argc, char **argv)
       /* No need to free these since we're about to exit.  */
       dired_dump_obstack ("//DIRED//", &dired_obstack);
       dired_dump_obstack ("//SUBDIRED//", &subdired_obstack);
-      printf ("//DIRED-OPTIONS// --quoting-style=%s\n",
-              quoting_style_args[get_quoting_style (filename_quoting_options)]);
+      printf ("//DIRED-OPTIONS// --quoting-style=%s%c",
+              quoting_style_args[get_quoting_style (filename_quoting_options)],
+              eolbyte);
     }
 
   if (LOOP_DETECT)
@@ -2265,6 +2270,10 @@ decode_switches (int argc, char **argv)
                                        indicator_style_types);
           break;
 
+        case NULL_OPTION:
+          eolbyte = 0;
+          break;
+
         case QUOTING_STYLE_OPTION:
           set_quoting_style (NULL,
                              XARGMATCH ("--quoting-style", optarg,
@@ -2966,7 +2975,7 @@ print_dir (char const *name, char const *realname, bool command_line_arg)
   if (recursive || print_dir_name)
     {
       if (!first)
-        dired_outbyte ('\n');
+        dired_outbyte (eolbyte);
       first = false;
       dired_indent ();
 
@@ -2983,7 +2992,8 @@ print_dir (char const *name, char const *realname, bool command_line_arg)
 
       free (absolute_name);
 
-      dired_outstring (":\n");
+      dired_outbyte (':');
+      dired_outbyte (eolbyte);
     }
 
   /* Read the directory entries, and insert the subfiles into the 'cwd_file'
@@ -3073,7 +3083,7 @@ print_dir (char const *name, char const *realname, bool command_line_arg)
                                 ST_NBLOCKSIZE, output_block_size);
       char *pend = p + strlen (p);
       *--p = ' ';
-      *pend++ = '\n';
+      *pend++ = eolbyte;
       dired_indent ();
       dired_outstring (_("total"));
       dired_outbuf (p, pend - p);
@@ -4103,7 +4113,7 @@ print_current_files (void)
       for (i = 0; i < cwd_n_used; i++)
         {
           print_file_name_and_frills (sorted_file[i], 0);
-          putchar ('\n');
+          putchar (eolbyte);
         }
       break;
 
@@ -4130,7 +4140,7 @@ print_current_files (void)
         {
           set_normal_color ();
           print_long_format (sorted_file[i]);
-          dired_outbyte ('\n');
+          dired_outbyte (eolbyte);
         }
       break;
     }
@@ -5121,7 +5131,7 @@ print_many_per_line (void)
           indent (pos + name_length, pos + max_name_length);
           pos += max_name_length;
         }
-      putchar ('\n');
+      putchar (eolbyte);
     }
 }
 
@@ -5146,7 +5156,7 @@ print_horizontal (void)
 
       if (col == 0)
         {
-          putchar ('\n');
+          putchar (eolbyte);
           pos = 0;
         }
       else
@@ -5161,7 +5171,7 @@ print_horizontal (void)
       name_length = length_of_file_name_and_frills (f);
       max_name_length = line_fmt->col_arr[col];
     }
-  putchar ('\n');
+  putchar (eolbyte);
 }
 
 /* Output name + SEP + ' '.  */
@@ -5191,7 +5201,7 @@ print_with_separator (char sep)
           else
             {
               pos = 0;
-              separator = '\n';
+              separator = eolbyte;
             }
 
           putchar (sep);
@@ -5201,7 +5211,7 @@ print_with_separator (char sep)
       print_file_name_and_frills (f, pos);
       pos += len;
     }
-  putchar ('\n');
+  putchar (eolbyte);
 }
 
 /* Assuming cursor is at position FROM, indent up to position TO.
@@ -5473,6 +5483,7 @@ Sort entries alphabetically if none of -cftuvSUX nor --sort is specified.\n\
 \n\
 "), stdout);
       fputs (_("\
+      --null                 end each output line with NUL, not newline\n\
   -n, --numeric-uid-gid      like -l, but list numeric user and group IDs\n\
   -N, --literal              print entry names without quoting\n\
   -o                         like -l, but do not list group information\n\
diff --git a/tests/local.mk b/tests/local.mk
index 81be52a34..441edc1be 100644
--- a/tests/local.mk
+++ b/tests/local.mk
@@ -612,6 +612,7 @@ all_tests =					\
   tests/ls/infloop.sh				\
   tests/ls/inode.sh				\
   tests/ls/m-option.sh				\
+  tests/ls/null-option.sh			\
   tests/ls/w-option.sh				\
   tests/ls/multihardlink.sh			\
   tests/ls/no-arg.sh				\
diff --git a/tests/ls/null-option.sh b/tests/ls/null-option.sh
new file mode 100755
index 000000000..fbf64e16d
--- /dev/null
+++ b/tests/ls/null-option.sh
@@ -0,0 +1,33 @@
+#!/bin/sh
+# Verify behavior of ls --null.
+
+# Copyright 2021 Free Software Foundation, Inc.
+
+# This program is free software: you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation, either version 3 of the License, or
+# (at your option) any later version.
+
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+# GNU General Public License for more details.
+
+# You should have received a copy of the GNU General Public License
+# along with this program.  If not, see <https://www.gnu.org/licenses/>.
+
+. "${srcdir=.}/tests/init.sh"; path_prepend_ ./src
+print_ver_ ls
+
+mkdir dir && touch dir/a dir/b dir/cc || framework_failure_
+
+LC_ALL=C ls --null dir >out || fail=1
+tr '\n' '\0' <<EOF >exp
+a
+b
+cc
+EOF
+
+compare exp out || fail=1
+
+Exit $fail
-- 
2.30.2