From 0a41ad2cfb6aa7af21f40fc870a0b917410b1d4b Mon Sep 17 00:00:00 2001 From: Paul Eggert 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