From e42f27d1477d25eead373ce45410306bfbfe78b2 Mon Sep 17 00:00:00 2001 From: Jim Meyering Date: Thu, 7 Dec 2000 10:05:09 +0000 Subject: (address_base, address_pad_len): New var. (output_address_fmt_string, address_fmt_buffer, address_pad): Remove. (flag_pseudo_start): Now int, not long int. (pseudo_offset): Now off_t, not long int. (n_specs, n_specs_allocated): Now size_t, not unsigned int. (format_address, format_address_none, format_address_std, format_address_label): Now accepts an extra char argument (an extra char to print if nonzero), and prints instead of returning a string. All callers changed. (bytes_per_block): Now size_t, not int. (format_address_none): Do not even print the extra char argument. This simplifies the callers. (format_address_std, format_address_label): Print off_t ourself instead of trying to use autoconfigured format. This is faster and more portable. (format_address_paren): New function. (dump): Remove unnecessary cast. (expand_address_fmt): Remove. (main): Use size_t, off_t, etc. instead of builtin types where this is advisable. Adjust to above changes. Remove unnecessary cast. --- src/od.c | 182 ++++++++++++++++++++++++++++++--------------------------------- 1 file changed, 87 insertions(+), 95 deletions(-) (limited to 'src/od.c') diff --git a/src/od.c b/src/od.c index 9ea7a52ea..f910e06cf 100644 --- a/src/od.c +++ b/src/od.c @@ -150,17 +150,15 @@ static const char *const charname[33] = "sp" }; -/* A printf control string for printing a file offset. */ -static const char *output_address_fmt_string; +/* Address base (8, 10 or 16). */ +int address_base; /* The number of octal digits required to represent the largest off_t value. */ #define MAX_ADDRESS_LENGTH \ ((sizeof (off_t) * CHAR_BIT + CHAR_BIT - 1) / 3) -/* Space for a normal address, a space, a pseudo address, parentheses - around the pseudo address, and a trailing zero byte. */ -static char address_fmt_buffer[2 * MAX_ADDRESS_LENGTH + 4]; -static char address_pad[MAX_ADDRESS_LENGTH + 1]; +/* Width of a normal address. */ +static int address_pad_len; static size_t string_min; static int flag_dump_strings; @@ -171,15 +169,15 @@ static int flag_dump_strings; static int traditional; /* Non-zero if an old-style `pseudo-address' was specified. */ -static long int flag_pseudo_start; +static int flag_pseudo_start; /* The difference between the old-style pseudo starting address and the number of bytes to skip. */ -static long int pseudo_offset; +static off_t pseudo_offset; -/* Function to format an address and optionally an additional parenthesized - pseudo-address; it returns the formatted string. */ -static const char *(*format_address) PARAMS ((off_t)); +/* Function that accepts an address and an optional following char, + and prints the address and char to stdout. */ +static void (*format_address) PARAMS ((off_t, char)); /* The number of input bytes to skip before formatting and writing. */ static off_t n_bytes_to_skip = 0; @@ -201,16 +199,16 @@ static int abbreviate_duplicate_blocks = 1; static struct tspec *spec; /* The number of format specs. */ -static unsigned int n_specs; +static size_t n_specs; /* The allocated length of SPEC. */ -static unsigned int n_specs_allocated; +static size_t n_specs_allocated; /* The number of input bytes formatted per output line. It must be a multiple of the least common multiple of the sizes associated with the specified output types. It should be as large as possible, but no larger than 16 -- unless specified with the -w option. */ -static unsigned int bytes_per_block; +static size_t bytes_per_block; /* Human-readable representation of *file_list (for error messages). It differs from *file_list only when *file_list is "-". */ @@ -1042,32 +1040,64 @@ skip (off_t n_skip) return err; } -static const char * -format_address_none (off_t address ATTRIBUTE_UNUSED) +static void +format_address_none (off_t address ATTRIBUTE_UNUSED, char c ATTRIBUTE_UNUSED) { - return ""; } -static const char * -format_address_std (off_t address) +static void +format_address_std (off_t address, char c) { - const char *address_string; + char buf[MAX_ADDRESS_LENGTH + 2]; + char *p = buf + sizeof buf; + char const *pbound; + + *--p = '\0'; + *--p = c; + pbound = p - address_pad_len; - sprintf (address_fmt_buffer, output_address_fmt_string, address); - address_string = address_fmt_buffer; - return address_string; + /* Use a special case of the code for each base. This is measurably + faster than generic code. */ + switch (address_base) + { + case 8: + do + *--p = '0' + (address & 7); + while ((address >>= 3) != 0); + break; + + case 10: + do + *--p = '0' + (address % 10); + while ((address /= 10) != 0); + break; + + case 16: + do + *--p = "0123456789abcdef"[address & 15]; + while ((address >>= 4) != 0); + break; + } + + while (pbound < p) + *--p = '0'; + + fputs (p, stdout); } -static const char * -format_address_label (off_t address) +static void +format_address_paren (off_t address, char c) { - const char *address_string; - assert (output_address_fmt_string != NULL); + putchar ('('); + format_address_std (address, ')'); + putchar (c); +} - sprintf (address_fmt_buffer, output_address_fmt_string, - address, address + pseudo_offset); - address_string = address_fmt_buffer; - return address_string; +static void +format_address_label (off_t address, char c) +{ + format_address_std (address, ' '); + format_address_paren (address + pseudo_offset, c); } /* Write N_BYTES bytes from CURR_BLOCK to standard output once for each @@ -1107,16 +1137,15 @@ write_block (off_t current_offset, off_t n_bytes, } else { - unsigned int i; + size_t i; prev_pair_equal = 0; for (i = 0; i < n_specs; i++) { - const char *addr_or_pad = (i == 0 - ? format_address (current_offset) - : address_pad); - - fputs (addr_or_pad, stdout); + if (i == 0) + format_address (current_offset, '\0'); + else + printf ("%*s", address_pad_len, ""); (*spec[i].print_function) (n_bytes, curr_block, spec[i].fmt_string); if (spec[i].hexl_mode_trailer) { @@ -1307,7 +1336,7 @@ read_block (size_t n, char *block, size_t *n_bytes_in_buffer) static int get_lcm (void) { - unsigned int i; + size_t i; int l_c_m = 1; for (i = 0; i < n_specs; i++) @@ -1436,7 +1465,7 @@ dump (void) /* Make bytes_to_write the smallest multiple of l_c_m that is at least as large as n_bytes_read. */ - bytes_to_write = l_c_m * (int) ((n_bytes_read + l_c_m - 1) / l_c_m); + bytes_to_write = l_c_m * ((n_bytes_read + l_c_m - 1) / l_c_m); memset (block[idx] + n_bytes_read, 0, bytes_to_write - n_bytes_read); write_block (current_offset, bytes_to_write, @@ -1444,8 +1473,7 @@ dump (void) current_offset += n_bytes_read; } - if (output_address_fmt_string != NULL) - printf ("%s\n", format_address (current_offset)); + format_address (current_offset, '\n'); if (limit_bytes_to_format && current_offset > end_offset) err |= check_and_close (); @@ -1523,10 +1551,8 @@ dump_strings (void) /* If we get here, the string is all printable and null-terminated, so print it. It is all in `buf' and `i' is its length. */ buf[i] = 0; - if (output_address_fmt_string != NULL) - { - printf ("%s ", format_address (address - i - 1)); - } + format_address (address - i - 1, ' '); + for (i = 0; (c = buf[i]); i++) { switch (c) @@ -1575,42 +1601,21 @@ dump_strings (void) return err; } -/* There must be exactly one %s format specifier in FORMAT_TEMPLATE. - Return the just-malloc'd result of using sprintf to insert - OFF_T_PRINTF_FORMAT_STRING into FORMAT_TEMPLATE. - Technically, the caller should free this memory, but IMHO it's not - worth it in this case. */ -static char * -expand_address_fmt (char const *format_template) -{ - size_t len = strlen (format_template); - char *fmt = xmalloc (len + 1); - /* Ensure that the literal we're inserting is no longer than the two-byte - string `%s' it's replacing. There's also the %%, so technically we don't - even need the `+ 1' above. */ - assert (OFF_T_PRINTF_FORMAT_STRING[0] == 0 - || OFF_T_PRINTF_FORMAT_STRING[1] == 0 - || OFF_T_PRINTF_FORMAT_STRING[2] == 0); - sprintf (fmt, format_template, OFF_T_PRINTF_FORMAT_STRING); - return fmt; -} - int main (int argc, char **argv) { int c; int n_files; - unsigned int i; - unsigned int l_c_m; - unsigned int address_pad_len; - unsigned long int desired_width IF_LINT (= 0); + size_t i; + int l_c_m; + size_t desired_width IF_LINT (= 0); int width_specified = 0; int n_failed_decodes = 0; int err; /* The old-style `pseudo starting address' to be printed in parentheses after any true address. */ - long int pseudo_start IF_LINT (= 0); + off_t pseudo_start IF_LINT (= 0); program_name = argv[0]; setlocale (LC_ALL, ""); @@ -1646,8 +1651,8 @@ main (int argc, char **argv) n_specs_allocated = 5; spec = (struct tspec *) xmalloc (n_specs_allocated * sizeof (struct tspec)); - output_address_fmt_string = expand_address_fmt ("%%07%so"); format_address = format_address_std; + address_base = 8; address_pad_len = 7; flag_dump_strings = 0; @@ -1666,22 +1671,21 @@ main (int argc, char **argv) switch (optarg[0]) { case 'd': - output_address_fmt_string = expand_address_fmt ("%%07%sd"); format_address = format_address_std; + address_base = 10; address_pad_len = 7; break; case 'o': - output_address_fmt_string = expand_address_fmt ("%%07%so"); format_address = format_address_std; + address_base = 8; address_pad_len = 7; break; case 'x': - output_address_fmt_string = expand_address_fmt ("%%06%sx"); format_address = format_address_std; + address_base = 16; address_pad_len = 6; break; case 'n': - output_address_fmt_string = NULL; format_address = format_address_none; address_pad_len = 0; break; @@ -1785,7 +1789,7 @@ it must be one character from [doxn]"), s_err = xstrtoumax (optarg, NULL, 10, &w_tmp, ""); if (s_err != LONGINT_OK) STRTOL_FATAL_ERROR (optarg, _("width specification"), s_err); - if (ULONG_MAX < w_tmp) + if (SIZE_MAX < w_tmp) error (EXIT_FAILURE, 0, _("%s is too large"), optarg); desired_width = w_tmp; } @@ -1885,29 +1889,17 @@ it must be one character from [doxn]"), if (flag_pseudo_start) { - static char buf[10]; - - if (output_address_fmt_string == NULL) + if (format_address == format_address_none) { - output_address_fmt_string = expand_address_fmt ("(%%07%so)"); - format_address = format_address_std; + address_base = 8; + address_pad_len = 7; + format_address = format_address_paren; } else - { - sprintf (buf, "%s (%s)", - output_address_fmt_string, - output_address_fmt_string); - output_address_fmt_string = buf; - format_address = format_address_label; - } + format_address = format_address_label; } } - assert (address_pad_len <= MAX_ADDRESS_LENGTH); - for (i = 0; i < address_pad_len; i++) - address_pad[i] = ' '; - address_pad[address_pad_len] = '\0'; - if (n_specs == 0) { if (decode_one_format ("o2", "o2", NULL, &(spec[0]))) @@ -1948,14 +1940,14 @@ it must be one character from [doxn]"), else { error (0, 0, _("warning: invalid width %lu; using %d instead"), - desired_width, l_c_m); + (unsigned long) desired_width, l_c_m); bytes_per_block = l_c_m; } } else { if (l_c_m < DEFAULT_BYTES_PER_BLOCK) - bytes_per_block = l_c_m * (int) (DEFAULT_BYTES_PER_BLOCK / l_c_m); + bytes_per_block = l_c_m * (DEFAULT_BYTES_PER_BLOCK / l_c_m); else bytes_per_block = l_c_m; } -- cgit v1.2.3-54-g00ecf