]> git.ipfire.org Git - thirdparty/coreutils.git/commitdiff
ls: demacroize
authorPaul Eggert <eggert@cs.ucla.edu>
Mon, 26 Jul 2021 04:01:31 +0000 (21:01 -0700)
committerPaul Eggert <eggert@cs.ucla.edu>
Mon, 26 Jul 2021 07:59:37 +0000 (00:59 -0700)
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

index a73aaf022d34ffa2395a77469449f2673c7bfbeb..efb87e405d81e0ae584734cc0c60019eb404c7a9 100644 (file)
--- a/src/ls.c
+++ b/src/ls.c
 #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;
     }