LCOV - code coverage report
Current view: top level - src - od.c (source / functions) Hit Total Coverage
Test: coreutils.info Lines: 684 783 87.4 %
Date: 2018-01-30 Functions: 28 32 87.5 %

          Line data    Source code
       1             : /* od -- dump files in octal and other formats
       2             :    Copyright (C) 92, 1995-2007 Free Software Foundation, Inc.
       3             : 
       4             :    This program is free software: you can redistribute it and/or modify
       5             :    it under the terms of the GNU General Public License as published by
       6             :    the Free Software Foundation, either version 3 of the License, or
       7             :    (at your option) any later version.
       8             : 
       9             :    This program is distributed in the hope that it will be useful,
      10             :    but WITHOUT ANY WARRANTY; without even the implied warranty of
      11             :    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
      12             :    GNU General Public License for more details.
      13             : 
      14             :    You should have received a copy of the GNU General Public License
      15             :    along with this program.  If not, see <http://www.gnu.org/licenses/>.  */
      16             : 
      17             : /* Written by Jim Meyering.  */
      18             : 
      19             : #include <config.h>
      20             : 
      21             : #include <stdio.h>
      22             : #include <assert.h>
      23             : #include <getopt.h>
      24             : #include <sys/types.h>
      25             : #include "system.h"
      26             : #include "error.h"
      27             : #include "quote.h"
      28             : #include "xstrtol.h"
      29             : 
      30             : /* The official name of this program (e.g., no `g' prefix).  */
      31             : #define PROGRAM_NAME "od"
      32             : 
      33             : #define AUTHORS "Jim Meyering"
      34             : 
      35             : #include <float.h>
      36             : 
      37             : #ifdef HAVE_LONG_DOUBLE
      38             : typedef long double LONG_DOUBLE;
      39             : #else
      40             : typedef double LONG_DOUBLE;
      41             : #endif
      42             : 
      43             : /* The default number of input bytes per output line.  */
      44             : #define DEFAULT_BYTES_PER_BLOCK 16
      45             : 
      46             : /* The number of decimal digits of precision in a float.  */
      47             : #ifndef FLT_DIG
      48             : # define FLT_DIG 7
      49             : #endif
      50             : 
      51             : /* The number of decimal digits of precision in a double.  */
      52             : #ifndef DBL_DIG
      53             : # define DBL_DIG 15
      54             : #endif
      55             : 
      56             : #if HAVE_UNSIGNED_LONG_LONG_INT
      57             : typedef unsigned long long int unsigned_long_long_int;
      58             : #else
      59             : /* This is just a place-holder to avoid a few `#if' directives.
      60             :    In this case, the type isn't actually used.  */
      61             : typedef unsigned long int unsigned_long_long_int;
      62             : #endif
      63             : 
      64             : enum size_spec
      65             :   {
      66             :     NO_SIZE,
      67             :     CHAR,
      68             :     SHORT,
      69             :     INT,
      70             :     LONG,
      71             :     LONG_LONG,
      72             :     /* FIXME: add INTMAX support, too */
      73             :     FLOAT_SINGLE,
      74             :     FLOAT_DOUBLE,
      75             :     FLOAT_LONG_DOUBLE,
      76             :     N_SIZE_SPECS
      77             :   };
      78             : 
      79             : enum output_format
      80             :   {
      81             :     SIGNED_DECIMAL,
      82             :     UNSIGNED_DECIMAL,
      83             :     OCTAL,
      84             :     HEXADECIMAL,
      85             :     FLOATING_POINT,
      86             :     NAMED_CHARACTER,
      87             :     CHARACTER
      88             :   };
      89             : 
      90             : /* The maximum number of bytes needed for a format string,
      91             :    including the trailing null.  */
      92             : enum
      93             :   {
      94             :     FMT_BYTES_ALLOCATED =
      95             :       MAX ((sizeof " %0" - 1 + INT_STRLEN_BOUND (int)
      96             :             + MAX (sizeof "ld",
      97             :                    MAX (sizeof PRIdMAX,
      98             :                         MAX (sizeof PRIoMAX,
      99             :                              MAX (sizeof PRIuMAX,
     100             :                                   sizeof PRIxMAX))))),
     101             :            sizeof " %.Le" + 2 * INT_STRLEN_BOUND (int))
     102             :   };
     103             : 
     104             : /* Each output format specification (from `-t spec' or from
     105             :    old-style options) is represented by one of these structures.  */
     106             : struct tspec
     107             :   {
     108             :     enum output_format fmt;
     109             :     enum size_spec size;
     110             :     void (*print_function) (size_t, void const *, char const *);
     111             :     char fmt_string[FMT_BYTES_ALLOCATED];
     112             :     bool hexl_mode_trailer;
     113             :     int field_width;
     114             :   };
     115             : 
     116             : /* The name this program was run with.  */
     117             : char *program_name;
     118             : 
     119             : /* Convert the number of 8-bit bytes of a binary representation to
     120             :    the number of characters (digits + sign if the type is signed)
     121             :    required to represent the same quantity in the specified base/type.
     122             :    For example, a 32-bit (4-byte) quantity may require a field width
     123             :    as wide as the following for these types:
     124             :    11   unsigned octal
     125             :    11   signed decimal
     126             :    10   unsigned decimal
     127             :    8    unsigned hexadecimal  */
     128             : 
     129             : static unsigned int const bytes_to_oct_digits[] =
     130             : {0, 3, 6, 8, 11, 14, 16, 19, 22, 25, 27, 30, 32, 35, 38, 41, 43};
     131             : 
     132             : static unsigned int const bytes_to_signed_dec_digits[] =
     133             : {1, 4, 6, 8, 11, 13, 16, 18, 20, 23, 25, 28, 30, 33, 35, 37, 40};
     134             : 
     135             : static unsigned int const bytes_to_unsigned_dec_digits[] =
     136             : {0, 3, 5, 8, 10, 13, 15, 17, 20, 22, 25, 27, 29, 32, 34, 37, 39};
     137             : 
     138             : static unsigned int const bytes_to_hex_digits[] =
     139             : {0, 2, 4, 6, 8, 10, 12, 14, 16, 18, 20, 22, 24, 26, 28, 30, 32};
     140             : 
     141             : #define MAX_INTEGRAL_TYPE_SIZE sizeof (unsigned_long_long_int)
     142             : 
     143             : /* It'll be a while before we see integral types wider than 16 bytes,
     144             :    but if/when it happens, this check will catch it.  Without this check,
     145             :    a wider type would provoke a buffer overrun.  */
     146             : verify (MAX_INTEGRAL_TYPE_SIZE
     147             :         < sizeof bytes_to_hex_digits / sizeof *bytes_to_hex_digits);
     148             : 
     149             : /* Make sure the other arrays have the same length.  */
     150             : verify (sizeof bytes_to_oct_digits == sizeof bytes_to_signed_dec_digits);
     151             : verify (sizeof bytes_to_oct_digits == sizeof bytes_to_unsigned_dec_digits);
     152             : verify (sizeof bytes_to_oct_digits == sizeof bytes_to_hex_digits);
     153             : 
     154             : /* Convert enum size_spec to the size of the named type.  */
     155             : static const int width_bytes[] =
     156             : {
     157             :   -1,
     158             :   sizeof (char),
     159             :   sizeof (short int),
     160             :   sizeof (int),
     161             :   sizeof (long int),
     162             :   sizeof (unsigned_long_long_int),
     163             :   sizeof (float),
     164             :   sizeof (double),
     165             :   sizeof (LONG_DOUBLE)
     166             : };
     167             : 
     168             : /* Ensure that for each member of `enum size_spec' there is an
     169             :    initializer in the width_bytes array.  */
     170             : verify (sizeof width_bytes / sizeof width_bytes[0] == N_SIZE_SPECS);
     171             : 
     172             : /* Names for some non-printing characters.  */
     173             : static const char *const charname[33] =
     174             : {
     175             :   "nul", "soh", "stx", "etx", "eot", "enq", "ack", "bel",
     176             :   "bs", "ht", "nl", "vt", "ff", "cr", "so", "si",
     177             :   "dle", "dc1", "dc2", "dc3", "dc4", "nak", "syn", "etb",
     178             :   "can", "em", "sub", "esc", "fs", "gs", "rs", "us",
     179             :   "sp"
     180             : };
     181             : 
     182             : /* Address base (8, 10 or 16).  */
     183             : static int address_base;
     184             : 
     185             : /* The number of octal digits required to represent the largest
     186             :    address value.  */
     187             : #define MAX_ADDRESS_LENGTH \
     188             :   ((sizeof (uintmax_t) * CHAR_BIT + CHAR_BIT - 1) / 3)
     189             : 
     190             : /* Width of a normal address.  */
     191             : static int address_pad_len;
     192             : 
     193             : static size_t string_min;
     194             : static bool flag_dump_strings;
     195             : 
     196             : /* True if we should recognize the older non-option arguments
     197             :    that specified at most one file and optional arguments specifying
     198             :    offset and pseudo-start address.  */
     199             : static bool traditional;
     200             : 
     201             : /* True if an old-style `pseudo-address' was specified.  */
     202             : static bool flag_pseudo_start;
     203             : 
     204             : /* The difference between the old-style pseudo starting address and
     205             :    the number of bytes to skip.  */
     206             : static uintmax_t pseudo_offset;
     207             : 
     208             : /* Function that accepts an address and an optional following char,
     209             :    and prints the address and char to stdout.  */
     210             : static void (*format_address) (uintmax_t, char);
     211             : 
     212             : /* The number of input bytes to skip before formatting and writing.  */
     213             : static uintmax_t n_bytes_to_skip = 0;
     214             : 
     215             : /* When false, MAX_BYTES_TO_FORMAT and END_OFFSET are ignored, and all
     216             :    input is formatted.  */
     217             : static bool limit_bytes_to_format = false;
     218             : 
     219             : /* The maximum number of bytes that will be formatted.  */
     220             : static uintmax_t max_bytes_to_format;
     221             : 
     222             : /* The offset of the first byte after the last byte to be formatted.  */
     223             : static uintmax_t end_offset;
     224             : 
     225             : /* When true and two or more consecutive blocks are equal, format
     226             :    only the first block and output an asterisk alone on the following
     227             :    line to indicate that identical blocks have been elided.  */
     228             : static bool abbreviate_duplicate_blocks = true;
     229             : 
     230             : /* An array of specs describing how to format each input block.  */
     231             : static struct tspec *spec;
     232             : 
     233             : /* The number of format specs.  */
     234             : static size_t n_specs;
     235             : 
     236             : /* The allocated length of SPEC.  */
     237             : static size_t n_specs_allocated;
     238             : 
     239             : /* The number of input bytes formatted per output line.  It must be
     240             :    a multiple of the least common multiple of the sizes associated with
     241             :    the specified output types.  It should be as large as possible, but
     242             :    no larger than 16 -- unless specified with the -w option.  */
     243             : static size_t bytes_per_block;
     244             : 
     245             : /* Human-readable representation of *file_list (for error messages).
     246             :    It differs from file_list[-1] only when file_list[-1] is "-".  */
     247             : static char const *input_filename;
     248             : 
     249             : /* A NULL-terminated list of the file-arguments from the command line.  */
     250             : static char const *const *file_list;
     251             : 
     252             : /* Initializer for file_list if no file-arguments
     253             :    were specified on the command line.  */
     254             : static char const *const default_file_list[] = {"-", NULL};
     255             : 
     256             : /* The input stream associated with the current file.  */
     257             : static FILE *in_stream;
     258             : 
     259             : /* If true, at least one of the files we read was standard input.  */
     260             : static bool have_read_stdin;
     261             : 
     262             : /* Map the size in bytes to a type identifier.  */
     263             : static enum size_spec integral_type_size[MAX_INTEGRAL_TYPE_SIZE + 1];
     264             : 
     265             : #define MAX_FP_TYPE_SIZE sizeof (LONG_DOUBLE)
     266             : static enum size_spec fp_type_size[MAX_FP_TYPE_SIZE + 1];
     267             : 
     268             : static char const short_options[] = "A:aBbcDdeFfHhIij:LlN:OoS:st:vw::Xx";
     269             : 
     270             : /* For long options that have no equivalent short option, use a
     271             :    non-character as a pseudo short option, starting with CHAR_MAX + 1.  */
     272             : enum
     273             : {
     274             :   TRADITIONAL_OPTION = CHAR_MAX + 1
     275             : };
     276             : 
     277             : static struct option const long_options[] =
     278             : {
     279             :   {"skip-bytes", required_argument, NULL, 'j'},
     280             :   {"address-radix", required_argument, NULL, 'A'},
     281             :   {"read-bytes", required_argument, NULL, 'N'},
     282             :   {"format", required_argument, NULL, 't'},
     283             :   {"output-duplicates", no_argument, NULL, 'v'},
     284             :   {"strings", optional_argument, NULL, 'S'},
     285             :   {"traditional", no_argument, NULL, TRADITIONAL_OPTION},
     286             :   {"width", optional_argument, NULL, 'w'},
     287             : 
     288             :   {GETOPT_HELP_OPTION_DECL},
     289             :   {GETOPT_VERSION_OPTION_DECL},
     290             :   {NULL, 0, NULL, 0}
     291             : };
     292             : 
     293             : void
     294          11 : usage (int status)
     295             : {
     296          11 :   if (status != EXIT_SUCCESS)
     297          10 :     fprintf (stderr, _("Try `%s --help' for more information.\n"),
     298             :              program_name);
     299             :   else
     300             :     {
     301           1 :       printf (_("\
     302             : Usage: %s [OPTION]... [FILE]...\n\
     303             :   or:  %s [-abcdfilosx]... [FILE] [[+]OFFSET[.][b]]\n\
     304             :   or:  %s --traditional [OPTION]... [FILE] [[+]OFFSET[.][b] [+][LABEL][.][b]]\n\
     305             : "),
     306             :               program_name, program_name, program_name);
     307           1 :       fputs (_("\n\
     308             : Write an unambiguous representation, octal bytes by default,\n\
     309             : of FILE to standard output.  With more than one FILE argument,\n\
     310             : concatenate them in the listed order to form the input.\n\
     311             : With no FILE, or when FILE is -, read standard input.\n\
     312             : \n\
     313             : "), stdout);
     314           1 :       fputs (_("\
     315             : All arguments to long options are mandatory for short options.\n\
     316             : "), stdout);
     317           1 :       fputs (_("\
     318             :   -A, --address-radix=RADIX   decide how file offsets are printed\n\
     319             :   -j, --skip-bytes=BYTES      skip BYTES input bytes first\n\
     320             : "), stdout);
     321           1 :       fputs (_("\
     322             :   -N, --read-bytes=BYTES      limit dump to BYTES input bytes\n\
     323             :   -S, --strings[=BYTES]       output strings of at least BYTES graphic chars\n\
     324             :   -t, --format=TYPE           select output format or formats\n\
     325             :   -v, --output-duplicates     do not use * to mark line suppression\n\
     326             :   -w, --width[=BYTES]         output BYTES bytes per output line\n\
     327             :       --traditional           accept arguments in traditional form\n\
     328             : "), stdout);
     329           1 :       fputs (HELP_OPTION_DESCRIPTION, stdout);
     330           1 :       fputs (VERSION_OPTION_DESCRIPTION, stdout);
     331           1 :       fputs (_("\
     332             : \n\
     333             : Traditional format specifications may be intermixed; they accumulate:\n\
     334             :   -a   same as -t a,  select named characters, ignoring high-order bit\n\
     335             :   -b   same as -t o1, select octal bytes\n\
     336             :   -c   same as -t c,  select ASCII characters or backslash escapes\n\
     337             :   -d   same as -t u2, select unsigned decimal 2-byte units\n\
     338             : "), stdout);
     339           1 :       fputs (_("\
     340             :   -f   same as -t fF, select floats\n\
     341             :   -i   same as -t dI, select decimal ints\n\
     342             :   -l   same as -t dL, select decimal longs\n\
     343             :   -o   same as -t o2, select octal 2-byte units\n\
     344             :   -s   same as -t d2, select decimal 2-byte units\n\
     345             :   -x   same as -t x2, select hexadecimal 2-byte units\n\
     346             : "), stdout);
     347           1 :       fputs (_("\
     348             : \n\
     349             : If first and second call formats both apply, the second format is assumed\n\
     350             : if the last operand begins with + or (if there are 2 operands) a digit.\n\
     351             : An OFFSET operand means -j OFFSET.  LABEL is the pseudo-address\n\
     352             : at first byte printed, incremented when dump is progressing.\n\
     353             : For OFFSET and LABEL, a 0x or 0X prefix indicates hexadecimal;\n\
     354             : suffixes may be . for octal and b for multiply by 512.\n\
     355             : "), stdout);
     356           1 :       fputs (_("\
     357             : \n\
     358             : TYPE is made up of one or more of these specifications:\n\
     359             : \n\
     360             :   a          named character, ignoring high-order bit\n\
     361             :   c          ASCII character or backslash escape\n\
     362             : "), stdout);
     363           1 :       fputs (_("\
     364             :   d[SIZE]    signed decimal, SIZE bytes per integer\n\
     365             :   f[SIZE]    floating point, SIZE bytes per integer\n\
     366             :   o[SIZE]    octal, SIZE bytes per integer\n\
     367             :   u[SIZE]    unsigned decimal, SIZE bytes per integer\n\
     368             :   x[SIZE]    hexadecimal, SIZE bytes per integer\n\
     369             : "), stdout);
     370           1 :       fputs (_("\
     371             : \n\
     372             : SIZE is a number.  For TYPE in doux, SIZE may also be C for\n\
     373             : sizeof(char), S for sizeof(short), I for sizeof(int) or L for\n\
     374             : sizeof(long).  If TYPE is f, SIZE may also be F for sizeof(float), D\n\
     375             : for sizeof(double) or L for sizeof(long double).\n\
     376             : "), stdout);
     377           1 :       fputs (_("\
     378             : \n\
     379             : RADIX is d for decimal, o for octal, x for hexadecimal or n for none.\n\
     380             : BYTES is hexadecimal with 0x or 0X prefix, and may have a multiplier suffix:\n\
     381             : b 512, kB 1000, K 1024, MB 1000*1000, M 1024*1024,\n\
     382             : GB 1000*1000*1000, G 1024*1024*1024, and so on for T, P, E, Z, Y.\n\
     383             : Adding a z suffix to any type displays printable characters at the end of each\n\
     384             : output line.  \
     385             : "), stdout);
     386           1 :       fputs (_("\
     387             : --string without a number implies 3.  --width without a number\n\
     388             : implies 32.  By default, od uses -A o -t d2 -w16.\n\
     389             : "), stdout);
     390           1 :       emit_bug_reporting_address ();
     391             :     }
     392          11 :   exit (status);
     393             : }
     394             : 
     395             : /* Define the print functions.  */
     396             : 
     397             : static void
     398           0 : print_s_char (size_t n_bytes, void const *block, char const *fmt_string)
     399             : {
     400           0 :   signed char const *p = block;
     401             :   size_t i;
     402           0 :   for (i = n_bytes / sizeof *p; i != 0; i--)
     403           0 :     printf (fmt_string, *p++);
     404           0 : }
     405             : 
     406             : static void
     407           2 : print_char (size_t n_bytes, void const *block, char const *fmt_string)
     408             : {
     409           2 :   unsigned char const *p = block;
     410             :   size_t i;
     411          18 :   for (i = n_bytes / sizeof *p; i != 0; i--)
     412          16 :     printf (fmt_string, *p++);
     413           2 : }
     414             : 
     415             : static void
     416           1 : print_s_short (size_t n_bytes, void const *block, char const *fmt_string)
     417             : {
     418           1 :   short int const *p = block;
     419             :   size_t i;
     420           5 :   for (i = n_bytes / sizeof *p; i != 0; i--)
     421           4 :     printf (fmt_string, *p++);
     422           1 : }
     423             : 
     424             : static void
     425          53 : print_short (size_t n_bytes, void const *block, char const *fmt_string)
     426             : {
     427          53 :   unsigned short int const *p = block;
     428             :   size_t i;
     429         274 :   for (i = n_bytes / sizeof *p; i != 0; i--)
     430         221 :     printf (fmt_string, *p++);
     431          53 : }
     432             : 
     433             : static void
     434           6 : print_int (size_t n_bytes, void const *block, char const *fmt_string)
     435             : {
     436           6 :   unsigned int const *p = block;
     437             :   size_t i;
     438          18 :   for (i = n_bytes / sizeof *p; i != 0; i--)
     439          12 :     printf (fmt_string, *p++);
     440           6 : }
     441             : 
     442             : static void
     443           0 : print_long (size_t n_bytes, void const *block, char const *fmt_string)
     444             : {
     445           0 :   unsigned long int const *p = block;
     446             :   size_t i;
     447           0 :   for (i = n_bytes / sizeof *p; i != 0; i--)
     448           0 :     printf (fmt_string, *p++);
     449           0 : }
     450             : 
     451             : static void
     452           5 : print_long_long (size_t n_bytes, void const *block, char const *fmt_string)
     453             : {
     454           5 :   unsigned_long_long_int const *p = block;
     455             :   size_t i;
     456          10 :   for (i = n_bytes / sizeof *p; i != 0; i--)
     457           5 :     printf (fmt_string, *p++);
     458           5 : }
     459             : 
     460             : static void
     461           2 : print_float (size_t n_bytes, void const *block, char const *fmt_string)
     462             : {
     463           2 :   float const *p = block;
     464             :   size_t i;
     465           6 :   for (i = n_bytes / sizeof *p; i != 0; i--)
     466           4 :     printf (fmt_string, *p++);
     467           2 : }
     468             : 
     469             : static void
     470           3 : print_double (size_t n_bytes, void const *block, char const *fmt_string)
     471             : {
     472           3 :   double const *p = block;
     473             :   size_t i;
     474           7 :   for (i = n_bytes / sizeof *p; i != 0; i--)
     475           4 :     printf (fmt_string, *p++);
     476           3 : }
     477             : 
     478             : #ifdef HAVE_LONG_DOUBLE
     479             : static void
     480           1 : print_long_double (size_t n_bytes, void const *block, char const *fmt_string)
     481             : {
     482           1 :   long double const *p = block;
     483             :   size_t i;
     484           2 :   for (i = n_bytes / sizeof *p; i != 0; i--)
     485           1 :     printf (fmt_string, *p++);
     486           1 : }
     487             : #endif
     488             : 
     489             : static void
     490           2 : dump_hexl_mode_trailer (size_t n_bytes, const char *block)
     491             : {
     492             :   size_t i;
     493           2 :   fputs ("  >", stdout);
     494          26 :   for (i = n_bytes; i > 0; i--)
     495             :     {
     496          24 :       unsigned char c = *block++;
     497          24 :       unsigned char c2 = (isprint (c) ? c : '.');
     498          24 :       putchar (c2);
     499             :     }
     500           2 :   putchar ('<');
     501           2 : }
     502             : 
     503             : static void
     504           7 : print_named_ascii (size_t n_bytes, void const *block,
     505             :                    const char *unused_fmt_string ATTRIBUTE_UNUSED)
     506             : {
     507           7 :   unsigned char const *p = block;
     508             :   size_t i;
     509          63 :   for (i = n_bytes; i > 0; i--)
     510             :     {
     511          56 :       int masked_c = *p++ & 0x7f;
     512             :       const char *s;
     513             :       char buf[5];
     514             : 
     515          56 :       if (masked_c == 127)
     516          52 :         s = "del";
     517           4 :       else if (masked_c <= 040)
     518           2 :         s = charname[masked_c];
     519             :       else
     520             :         {
     521           2 :           sprintf (buf, "  %c", masked_c);
     522           2 :           s = buf;
     523             :         }
     524             : 
     525          56 :       printf (" %3s", s);
     526             :     }
     527           7 : }
     528             : 
     529             : static void
     530           9 : print_ascii (size_t n_bytes, void const *block,
     531             :              const char *unused_fmt_string ATTRIBUTE_UNUSED)
     532             : {
     533           9 :   unsigned char const *p = block;
     534             :   size_t i;
     535          81 :   for (i = n_bytes; i > 0; i--)
     536             :     {
     537          72 :       unsigned char c = *p++;
     538             :       const char *s;
     539             :       char buf[5];
     540             : 
     541          72 :       switch (c)
     542             :         {
     543          61 :         case '\0':
     544          61 :           s = " \\0";
     545          61 :           break;
     546             : 
     547           1 :         case '\a':
     548           1 :           s = " \\a";
     549           1 :           break;
     550             : 
     551           1 :         case '\b':
     552           1 :           s = " \\b";
     553           1 :           break;
     554             : 
     555           1 :         case '\f':
     556           1 :           s = " \\f";
     557           1 :           break;
     558             : 
     559           2 :         case '\n':
     560           2 :           s = " \\n";
     561           2 :           break;
     562             : 
     563           1 :         case '\r':
     564           1 :           s = " \\r";
     565           1 :           break;
     566             : 
     567           1 :         case '\t':
     568           1 :           s = " \\t";
     569           1 :           break;
     570             : 
     571           3 :         case '\v':
     572           3 :           s = " \\v";
     573           3 :           break;
     574             : 
     575           1 :         default:
     576           1 :           sprintf (buf, (isprint (c) ? "  %c" : "%03o"), c);
     577           1 :           s = buf;
     578             :         }
     579             : 
     580          72 :       printf (" %3s", s);
     581             :     }
     582           9 : }
     583             : 
     584             : /* Convert a null-terminated (possibly zero-length) string S to an
     585             :    unsigned long integer value.  If S points to a non-digit set *P to S,
     586             :    *VAL to 0, and return true.  Otherwise, accumulate the integer value of
     587             :    the string of digits.  If the string of digits represents a value
     588             :    larger than ULONG_MAX, don't modify *VAL or *P and return false.
     589             :    Otherwise, advance *P to the first non-digit after S, set *VAL to
     590             :    the result of the conversion and return true.  */
     591             : 
     592             : static bool
     593          15 : simple_strtoul (const char *s, const char **p, unsigned long int *val)
     594             : {
     595             :   unsigned long int sum;
     596             : 
     597          15 :   sum = 0;
     598          42 :   while (ISDIGIT (*s))
     599             :     {
     600          12 :       int c = *s++ - '0';
     601          12 :       if (sum > (ULONG_MAX - c) / 10)
     602           0 :         return false;
     603          12 :       sum = sum * 10 + c;
     604             :     }
     605          15 :   *p = s;
     606          15 :   *val = sum;
     607          15 :   return true;
     608             : }
     609             : 
     610             : /* If S points to a single valid modern od format string, put
     611             :    a description of that format in *TSPEC, make *NEXT point at the
     612             :    character following the just-decoded format (if *NEXT is non-NULL),
     613             :    and return true.  If S is not valid, don't modify *NEXT or *TSPEC,
     614             :    give a diagnostic, and return false.  For example, if S were
     615             :    "d4afL" *NEXT would be set to "afL" and *TSPEC would be
     616             :      {
     617             :        fmt = SIGNED_DECIMAL;
     618             :        size = INT or LONG; (whichever integral_type_size[4] resolves to)
     619             :        print_function = print_int; (assuming size == INT)
     620             :        fmt_string = "%011d%c";
     621             :       }
     622             :    S_ORIG is solely for reporting errors.  It should be the full format
     623             :    string argument.
     624             :    */
     625             : 
     626             : static bool
     627         137 : decode_one_format (const char *s_orig, const char *s, const char **next,
     628             :                    struct tspec *tspec)
     629             : {
     630             :   enum size_spec size_spec;
     631             :   unsigned long int size;
     632             :   enum output_format fmt;
     633             :   const char *pre_fmt_string;
     634             :   void (*print_function) (size_t, void const *, char const *);
     635             :   const char *p;
     636             :   char c;
     637             :   int field_width;
     638             :   int precision;
     639             : 
     640         137 :   assert (tspec != NULL);
     641             : 
     642         137 :   switch (*s)
     643             :     {
     644          97 :     case 'd':
     645             :     case 'o':
     646             :     case 'u':
     647             :     case 'x':
     648          97 :       c = *s;
     649          97 :       ++s;
     650          97 :       switch (*s)
     651             :         {
     652           1 :         case 'C':
     653           1 :           ++s;
     654           1 :           size = sizeof (char);
     655           1 :           break;
     656             : 
     657          78 :         case 'S':
     658          78 :           ++s;
     659          78 :           size = sizeof (short int);
     660          78 :           break;
     661             : 
     662           1 :         case 'I':
     663           1 :           ++s;
     664           1 :           size = sizeof (int);
     665           1 :           break;
     666             : 
     667           5 :         case 'L':
     668           5 :           ++s;
     669           5 :           size = sizeof (long int);
     670           5 :           break;
     671             : 
     672          12 :         default:
     673          12 :           if (! simple_strtoul (s, &p, &size))
     674             :             {
     675             :               /* The integer at P in S would overflow an unsigned long int.
     676             :                  A digit string that long is sufficiently odd looking
     677             :                  that the following diagnostic is sufficient.  */
     678           0 :               error (0, 0, _("invalid type string %s"), quote (s_orig));
     679           0 :               return false;
     680             :             }
     681          12 :           if (p == s)
     682           2 :             size = sizeof (int);
     683             :           else
     684             :             {
     685          10 :               if (MAX_INTEGRAL_TYPE_SIZE < size
     686           9 :                   || integral_type_size[size] == NO_SIZE)
     687             :                 {
     688           1 :                   error (0, 0, _("invalid type string %s;\n\
     689             : this system doesn't provide a %lu-byte integral type"), quote (s_orig), size);
     690           1 :                   return false;
     691             :                 }
     692           9 :               s = p;
     693             :             }
     694          11 :           break;
     695             :         }
     696             : 
     697             : #define ISPEC_TO_FORMAT(Spec, Min_format, Long_format, Max_format)      \
     698             :   ((Spec) == LONG_LONG ? (Max_format)                                   \
     699             :    : ((Spec) == LONG ? (Long_format)                                    \
     700             :       : (Min_format)))                                                  \
     701             : 
     702          96 :       size_spec = integral_type_size[size];
     703             : 
     704          96 :       switch (c)
     705             :         {
     706           3 :         case 'd':
     707           3 :           fmt = SIGNED_DECIMAL;
     708           8 :           sprintf (tspec->fmt_string, " %%%d%s",
     709           3 :                    (field_width = bytes_to_signed_dec_digits[size]),
     710           2 :                    ISPEC_TO_FORMAT (size_spec, "d", "ld", PRIdMAX));
     711           3 :           break;
     712             : 
     713          83 :         case 'o':
     714          83 :           fmt = OCTAL;
     715         248 :           sprintf (tspec->fmt_string, " %%0%d%s",
     716          83 :                    (field_width = bytes_to_oct_digits[size]),
     717          82 :                    ISPEC_TO_FORMAT (size_spec, "o", "lo", PRIoMAX));
     718          83 :           break;
     719             : 
     720           7 :         case 'u':
     721           7 :           fmt = UNSIGNED_DECIMAL;
     722          19 :           sprintf (tspec->fmt_string, " %%%d%s",
     723           7 :                    (field_width = bytes_to_unsigned_dec_digits[size]),
     724           5 :                    ISPEC_TO_FORMAT (size_spec, "u", "lu", PRIuMAX));
     725           7 :           break;
     726             : 
     727           3 :         case 'x':
     728           3 :           fmt = HEXADECIMAL;
     729           8 :           sprintf (tspec->fmt_string, " %%0%d%s",
     730           3 :                    (field_width = bytes_to_hex_digits[size]),
     731           2 :                    ISPEC_TO_FORMAT (size_spec, "x", "lx", PRIxMAX));
     732           3 :           break;
     733             : 
     734           0 :         default:
     735           0 :           abort ();
     736             :         }
     737             : 
     738          96 :       assert (strlen (tspec->fmt_string) < FMT_BYTES_ALLOCATED);
     739             : 
     740          96 :       switch (size_spec)
     741             :         {
     742           2 :         case CHAR:
     743           2 :           print_function = (fmt == SIGNED_DECIMAL
     744             :                             ? print_s_char
     745           2 :                             : print_char);
     746           2 :           break;
     747             : 
     748          83 :         case SHORT:
     749          83 :           print_function = (fmt == SIGNED_DECIMAL
     750             :                             ? print_s_short
     751          83 :                             : print_short);
     752          83 :           break;
     753             : 
     754           6 :         case INT:
     755           6 :           print_function = print_int;
     756           6 :           break;
     757             : 
     758           0 :         case LONG:
     759           0 :           print_function = print_long;
     760           0 :           break;
     761             : 
     762           5 :         case LONG_LONG:
     763           5 :           print_function = print_long_long;
     764           5 :           break;
     765             : 
     766           0 :         default:
     767           0 :           abort ();
     768             :         }
     769          96 :       break;
     770             : 
     771           7 :     case 'f':
     772           7 :       fmt = FLOATING_POINT;
     773           7 :       ++s;
     774           7 :       switch (*s)
     775             :         {
     776           1 :         case 'F':
     777           1 :           ++s;
     778           1 :           size = sizeof (float);
     779           1 :           break;
     780             : 
     781           2 :         case 'D':
     782           2 :           ++s;
     783           2 :           size = sizeof (double);
     784           2 :           break;
     785             : 
     786           1 :         case 'L':
     787           1 :           ++s;
     788           1 :           size = sizeof (LONG_DOUBLE);
     789           1 :           break;
     790             : 
     791           3 :         default:
     792           3 :           if (! simple_strtoul (s, &p, &size))
     793             :             {
     794             :               /* The integer at P in S would overflow an unsigned long int.
     795             :                  A digit string that long is sufficiently odd looking
     796             :                  that the following diagnostic is sufficient.  */
     797           0 :               error (0, 0, _("invalid type string %s"), quote (s_orig));
     798           0 :               return false;
     799             :             }
     800           3 :           if (p == s)
     801           1 :             size = sizeof (double);
     802             :           else
     803             :             {
     804           2 :               if (size > MAX_FP_TYPE_SIZE
     805           2 :                   || fp_type_size[size] == NO_SIZE)
     806             :                 {
     807           1 :                   error (0, 0, _("invalid type string %s;\n\
     808             : this system doesn't provide a %lu-byte floating point type"),
     809             :                          quote (s_orig), size);
     810           1 :                   return false;
     811             :                 }
     812           1 :               s = p;
     813             :             }
     814           2 :           break;
     815             :         }
     816           6 :       size_spec = fp_type_size[size];
     817             : 
     818           6 :       switch (size_spec)
     819             :         {
     820           2 :         case FLOAT_SINGLE:
     821           2 :           print_function = print_float;
     822             :           /* Don't use %#e; not all systems support it.  */
     823           2 :           pre_fmt_string = " %%%d.%de";
     824           2 :           precision = FLT_DIG;
     825           2 :           break;
     826             : 
     827           3 :         case FLOAT_DOUBLE:
     828           3 :           print_function = print_double;
     829           3 :           pre_fmt_string = " %%%d.%de";
     830           3 :           precision = DBL_DIG;
     831           3 :           break;
     832             : 
     833             : #ifdef HAVE_LONG_DOUBLE
     834           1 :         case FLOAT_LONG_DOUBLE:
     835           1 :           print_function = print_long_double;
     836           1 :           pre_fmt_string = " %%%d.%dLe";
     837           1 :           precision = LDBL_DIG;
     838           1 :           break;
     839             : #endif
     840             : 
     841           0 :         default:
     842           0 :           abort ();
     843             :         }
     844             : 
     845           6 :       field_width = precision + 8;
     846           6 :       sprintf (tspec->fmt_string, pre_fmt_string, field_width, precision);
     847           6 :       break;
     848             : 
     849           9 :     case 'a':
     850           9 :       ++s;
     851           9 :       fmt = NAMED_CHARACTER;
     852           9 :       size_spec = CHAR;
     853           9 :       print_function = print_named_ascii;
     854           9 :       field_width = 3;
     855           9 :       break;
     856             : 
     857           9 :     case 'c':
     858           9 :       ++s;
     859           9 :       fmt = CHARACTER;
     860           9 :       size_spec = CHAR;
     861           9 :       print_function = print_ascii;
     862           9 :       field_width = 3;
     863           9 :       break;
     864             : 
     865          15 :     default:
     866          30 :       error (0, 0, _("invalid character `%c' in type string %s"),
     867          15 :              *s, quote (s_orig));
     868          15 :       return false;
     869             :     }
     870             : 
     871         120 :   tspec->size = size_spec;
     872         120 :   tspec->fmt = fmt;
     873         120 :   tspec->print_function = print_function;
     874             : 
     875         120 :   tspec->field_width = field_width;
     876         120 :   tspec->hexl_mode_trailer = (*s == 'z');
     877         120 :   if (tspec->hexl_mode_trailer)
     878           2 :     s++;
     879             : 
     880         120 :   if (next != NULL)
     881         120 :     *next = s;
     882             : 
     883         120 :   return true;
     884             : }
     885             : 
     886             : /* Given a list of one or more input filenames FILE_LIST, set the global
     887             :    file pointer IN_STREAM and the global string INPUT_FILENAME to the
     888             :    first one that can be successfully opened. Modify FILE_LIST to
     889             :    reference the next filename in the list.  A file name of "-" is
     890             :    interpreted as standard input.  If any file open fails, give an error
     891             :    message and return false.  */
     892             : 
     893             : static bool
     894         235 : open_next_file (void)
     895             : {
     896         235 :   bool ok = true;
     897             : 
     898             :   do
     899             :     {
     900         257 :       input_filename = *file_list;
     901         257 :       if (input_filename == NULL)
     902         112 :         return ok;
     903         145 :       ++file_list;
     904             : 
     905         145 :       if (STREQ (input_filename, "-"))
     906             :         {
     907         111 :           input_filename = _("standard input");
     908         111 :           in_stream = stdin;
     909         111 :           have_read_stdin = true;
     910             :           if (O_BINARY && ! isatty (STDIN_FILENO))
     911             :             freopen (NULL, "rb", stdin);
     912             :         }
     913             :       else
     914             :         {
     915          34 :           in_stream = fopen (input_filename, (O_BINARY ? "rb" : "r"));
     916          34 :           if (in_stream == NULL)
     917             :             {
     918          22 :               error (0, errno, "%s", input_filename);
     919          22 :               ok = false;
     920             :             }
     921             :         }
     922             :     }
     923         145 :   while (in_stream == NULL);
     924             : 
     925         123 :   if (limit_bytes_to_format & !flag_dump_strings)
     926          11 :     setvbuf (in_stream, NULL, _IONBF, 0);
     927             : 
     928         123 :   return ok;
     929             : }
     930             : 
     931             : /* Test whether there have been errors on in_stream, and close it if
     932             :    it is not standard input.  Return false if there has been an error
     933             :    on in_stream or stdout; return true otherwise.  This function will
     934             :    report more than one error only if both a read and a write error
     935             :    have occurred.  IN_ERRNO, if nonzero, is the error number
     936             :    corresponding to the most recent action for IN_STREAM.  */
     937             : 
     938             : static bool
     939         122 : check_and_close (int in_errno)
     940             : {
     941         122 :   bool ok = true;
     942             : 
     943         122 :   if (in_stream != NULL)
     944             :     {
     945         122 :       if (ferror (in_stream))
     946             :         {
     947           9 :           error (0, in_errno, _("%s: read error"), input_filename);
     948           9 :           if (! STREQ (file_list[-1], "-"))
     949           9 :             fclose (in_stream);
     950           9 :           ok = false;
     951             :         }
     952         113 :       else if (! STREQ (file_list[-1], "-") && fclose (in_stream) != 0)
     953             :         {
     954           0 :           error (0, errno, "%s", input_filename);
     955           0 :           ok = false;
     956             :         }
     957             : 
     958         122 :       in_stream = NULL;
     959             :     }
     960             : 
     961         122 :   if (ferror (stdout))
     962             :     {
     963           0 :       error (0, 0, _("write error"));
     964           0 :       ok = false;
     965             :     }
     966             : 
     967         122 :   return ok;
     968             : }
     969             : 
     970             : /* Decode the modern od format string S.  Append the decoded
     971             :    representation to the global array SPEC, reallocating SPEC if
     972             :    necessary.  Return true if S is valid.  */
     973             : 
     974             : static bool
     975         136 : decode_format_string (const char *s)
     976             : {
     977         136 :   const char *s_orig = s;
     978         136 :   assert (s != NULL);
     979             : 
     980         392 :   while (*s != '\0')
     981             :     {
     982             :       const char *next;
     983             : 
     984         137 :       if (n_specs_allocated <= n_specs)
     985         137 :         spec = X2NREALLOC (spec, &n_specs_allocated);
     986             : 
     987         137 :       if (! decode_one_format (s_orig, s, &next, &spec[n_specs]))
     988          17 :         return false;
     989             : 
     990         120 :       assert (s != next);
     991         120 :       s = next;
     992         120 :       ++n_specs;
     993             :     }
     994             : 
     995         119 :   return true;
     996             : }
     997             : 
     998             : /* Given a list of one or more input filenames FILE_LIST, set the global
     999             :    file pointer IN_STREAM to position N_SKIP in the concatenation of
    1000             :    those files.  If any file operation fails or if there are fewer than
    1001             :    N_SKIP bytes in the combined input, give an error message and return
    1002             :    false.  When possible, use seek rather than read operations to
    1003             :    advance IN_STREAM.  */
    1004             : 
    1005             : static bool
    1006         104 : skip (uintmax_t n_skip)
    1007             : {
    1008         104 :   bool ok = true;
    1009         104 :   int in_errno = 0;
    1010             : 
    1011         104 :   if (n_skip == 0)
    1012          97 :     return true;
    1013             : 
    1014          15 :   while (in_stream != NULL)     /* EOF.  */
    1015             :     {
    1016             :       struct stat file_stats;
    1017             : 
    1018             :       /* First try seeking.  For large offsets, this extra work is
    1019             :          worthwhile.  If the offset is below some threshold it may be
    1020             :          more efficient to move the pointer by reading.  There are two
    1021             :          issues when trying to seek:
    1022             :            - the file must be seekable.
    1023             :            - before seeking to the specified position, make sure
    1024             :              that the new position is in the current file.
    1025             :              Try to do that by getting file's size using fstat.
    1026             :              But that will work only for regular files.  */
    1027             : 
    1028           7 :       if (fstat (fileno (in_stream), &file_stats) == 0)
    1029             :         {
    1030             :           /* The st_size field is valid only for regular files
    1031             :              (and for symbolic links, which cannot occur here).
    1032             :              If the number of bytes left to skip is larger than
    1033             :              the size of the current file, we can decrement n_skip
    1034             :              and go on to the next file.  Skip this optimization also
    1035             :              when st_size is 0, because some kernels report that
    1036             :              nonempty files in /proc have st_size == 0.  */
    1037           7 :           if (S_ISREG (file_stats.st_mode) && 0 < file_stats.st_size)
    1038             :             {
    1039           4 :               if ((uintmax_t) file_stats.st_size < n_skip)
    1040           1 :                 n_skip -= file_stats.st_size;
    1041             :               else
    1042             :                 {
    1043           1 :                   if (fseeko (in_stream, n_skip, SEEK_CUR) != 0)
    1044             :                     {
    1045           0 :                       in_errno = errno;
    1046           0 :                       ok = false;
    1047             :                     }
    1048           1 :                   n_skip = 0;
    1049             :                 }
    1050             :             }
    1051             : 
    1052             :           /* If it's not a regular file with nonnegative size,
    1053             :              position the file pointer by reading.  */
    1054             : 
    1055             :           else
    1056             :             {
    1057             :               char buf[BUFSIZ];
    1058           5 :               size_t n_bytes_read, n_bytes_to_read = BUFSIZ;
    1059             : 
    1060          12 :               while (0 < n_skip)
    1061             :                 {
    1062           5 :                   if (n_skip < n_bytes_to_read)
    1063           4 :                     n_bytes_to_read = n_skip;
    1064           5 :                   n_bytes_read = fread (buf, 1, n_bytes_to_read, in_stream);
    1065           5 :                   n_skip -= n_bytes_read;
    1066           5 :                   if (n_bytes_read != n_bytes_to_read)
    1067             :                     {
    1068           3 :                       in_errno = errno;
    1069           3 :                       ok = false;
    1070           3 :                       n_skip = 0;
    1071           3 :                       break;
    1072             :                     }
    1073             :                 }
    1074             :             }
    1075             : 
    1076           7 :           if (n_skip == 0)
    1077           6 :             break;
    1078             :         }
    1079             : 
    1080             :       else   /* cannot fstat() file */
    1081             :         {
    1082           0 :           error (0, errno, "%s", input_filename);
    1083           0 :           ok = false;
    1084             :         }
    1085             : 
    1086           1 :       ok &= check_and_close (in_errno);
    1087             : 
    1088           1 :       ok &= open_next_file ();
    1089             :     }
    1090             : 
    1091           7 :   if (n_skip != 0)
    1092           1 :     error (EXIT_FAILURE, 0, _("cannot skip past end of combined input"));
    1093             : 
    1094           6 :   return ok;
    1095             : }
    1096             : 
    1097             : static void
    1098           2 : format_address_none (uintmax_t address ATTRIBUTE_UNUSED, char c ATTRIBUTE_UNUSED)
    1099             : {
    1100           2 : }
    1101             : 
    1102             : static void
    1103         200 : format_address_std (uintmax_t address, char c)
    1104             : {
    1105             :   char buf[MAX_ADDRESS_LENGTH + 2];
    1106         200 :   char *p = buf + sizeof buf;
    1107             :   char const *pbound;
    1108             : 
    1109         200 :   *--p = '\0';
    1110         200 :   *--p = c;
    1111         200 :   pbound = p - address_pad_len;
    1112             : 
    1113             :   /* Use a special case of the code for each base.  This is measurably
    1114             :      faster than generic code.  */
    1115         200 :   switch (address_base)
    1116             :     {
    1117         390 :     case 8:
    1118             :       do
    1119         289 :         *--p = '0' + (address & 7);
    1120         289 :       while ((address >>= 3) != 0);
    1121         188 :       break;
    1122             : 
    1123           1 :     case 10:
    1124             :       do
    1125           5 :         *--p = '0' + (address % 10);
    1126           5 :       while ((address /= 10) != 0);
    1127           4 :       break;
    1128             : 
    1129           1 :     case 16:
    1130             :       do
    1131           9 :         *--p = "0123456789abcdef"[address & 15];
    1132           9 :       while ((address >>= 4) != 0);
    1133           8 :       break;
    1134             :     }
    1135             : 
    1136        1503 :   while (pbound < p)
    1137        1103 :     *--p = '0';
    1138             : 
    1139         200 :   fputs (p, stdout);
    1140         200 : }
    1141             : 
    1142             : static void
    1143           0 : format_address_paren (uintmax_t address, char c)
    1144             : {
    1145           0 :   putchar ('(');
    1146           0 :   format_address_std (address, ')');
    1147           0 :   if (c)
    1148           0 :     putchar (c);
    1149           0 : }
    1150             : 
    1151             : static void
    1152           0 : format_address_label (uintmax_t address, char c)
    1153             : {
    1154           0 :   format_address_std (address, ' ');
    1155           0 :   format_address_paren (address + pseudo_offset, c);
    1156           0 : }
    1157             : 
    1158             : /* Write N_BYTES bytes from CURR_BLOCK to standard output once for each
    1159             :    of the N_SPEC format specs.  CURRENT_OFFSET is the byte address of
    1160             :    CURR_BLOCK in the concatenation of input files, and it is printed
    1161             :    (optionally) only before the output line associated with the first
    1162             :    format spec.  When duplicate blocks are being abbreviated, the output
    1163             :    for a sequence of identical input blocks is the output for the first
    1164             :    block followed by an asterisk alone on a line.  It is valid to compare
    1165             :    the blocks PREV_BLOCK and CURR_BLOCK only when N_BYTES == BYTES_PER_BLOCK.
    1166             :    That condition may be false only for the last input block -- and then
    1167             :    only when it has not been padded to length BYTES_PER_BLOCK.  */
    1168             : 
    1169             : static void
    1170          90 : write_block (uintmax_t current_offset, size_t n_bytes,
    1171             :              const char *prev_block, const char *curr_block)
    1172             : {
    1173             :   static bool first = true;
    1174             :   static bool prev_pair_equal = false;
    1175             : 
    1176             : #define EQUAL_BLOCKS(b1, b2) (memcmp (b1, b2, bytes_per_block) == 0)
    1177             : 
    1178          90 :   if (abbreviate_duplicate_blocks
    1179          89 :       && !first && n_bytes == bytes_per_block
    1180           4 :       && EQUAL_BLOCKS (prev_block, curr_block))
    1181             :     {
    1182           8 :       if (prev_pair_equal)
    1183             :         {
    1184             :           /* The two preceding blocks were equal, and the current
    1185             :              block is the same as the last one, so print nothing.  */
    1186             :         }
    1187             :       else
    1188             :         {
    1189           2 :           printf ("*\n");
    1190           2 :           prev_pair_equal = true;
    1191             :         }
    1192             :     }
    1193             :   else
    1194             :     {
    1195             :       size_t i;
    1196             : 
    1197          86 :       prev_pair_equal = false;
    1198         175 :       for (i = 0; i < n_specs; i++)
    1199             :         {
    1200          89 :           if (i == 0)
    1201          86 :             format_address (current_offset, '\0');
    1202             :           else
    1203           3 :             printf ("%*s", address_pad_len, "");
    1204          89 :           (*spec[i].print_function) (n_bytes, curr_block, spec[i].fmt_string);
    1205          89 :           if (spec[i].hexl_mode_trailer)
    1206             :             {
    1207             :               /* space-pad out to full line width, then dump the trailer */
    1208           2 :               int datum_width = width_bytes[spec[i].size];
    1209           2 :               int blank_fields = (bytes_per_block - n_bytes) / datum_width;
    1210           2 :               int field_width = spec[i].field_width + 1;
    1211           2 :               printf ("%*s", blank_fields * field_width, "");
    1212           2 :               dump_hexl_mode_trailer (n_bytes, curr_block);
    1213             :             }
    1214          89 :           putchar ('\n');
    1215             :         }
    1216             :     }
    1217          90 :   first = false;
    1218          90 : }
    1219             : 
    1220             : /* Read a single byte into *C from the concatenation of the input files
    1221             :    named in the global array FILE_LIST.  On the first call to this
    1222             :    function, the global variable IN_STREAM is expected to be an open
    1223             :    stream associated with the input file INPUT_FILENAME.  If IN_STREAM
    1224             :    is at end-of-file, close it and update the global variables IN_STREAM
    1225             :    and INPUT_FILENAME so they correspond to the next file in the list.
    1226             :    Then try to read a byte from the newly opened file.  Repeat if
    1227             :    necessary until EOF is reached for the last file in FILE_LIST, then
    1228             :    set *C to EOF and return.  Subsequent calls do likewise.  Return
    1229             :    true if successful.  */
    1230             : 
    1231             : static bool
    1232          90 : read_char (int *c)
    1233             : {
    1234          90 :   bool ok = true;
    1235             : 
    1236          90 :   *c = EOF;
    1237             : 
    1238         191 :   while (in_stream != NULL)     /* EOF.  */
    1239             :     {
    1240          91 :       *c = fgetc (in_stream);
    1241             : 
    1242          91 :       if (*c != EOF)
    1243          80 :         break;
    1244             : 
    1245          11 :       ok &= check_and_close (errno);
    1246             : 
    1247          11 :       ok &= open_next_file ();
    1248             :     }
    1249             : 
    1250          90 :   return ok;
    1251             : }
    1252             : 
    1253             : /* Read N bytes into BLOCK from the concatenation of the input files
    1254             :    named in the global array FILE_LIST.  On the first call to this
    1255             :    function, the global variable IN_STREAM is expected to be an open
    1256             :    stream associated with the input file INPUT_FILENAME.  If all N
    1257             :    bytes cannot be read from IN_STREAM, close IN_STREAM and update
    1258             :    the global variables IN_STREAM and INPUT_FILENAME.  Then try to
    1259             :    read the remaining bytes from the newly opened file.  Repeat if
    1260             :    necessary until EOF is reached for the last file in FILE_LIST.
    1261             :    On subsequent calls, don't modify BLOCK and return true.  Set
    1262             :    *N_BYTES_IN_BUFFER to the number of bytes read.  If an error occurs,
    1263             :    it will be detected through ferror when the stream is about to be
    1264             :    closed.  If there is an error, give a message but continue reading
    1265             :    as usual and return false.  Otherwise return true.  */
    1266             : 
    1267             : static bool
    1268         102 : read_block (size_t n, char *block, size_t *n_bytes_in_buffer)
    1269             : {
    1270         102 :   bool ok = true;
    1271             : 
    1272         102 :   assert (0 < n && n <= bytes_per_block);
    1273             : 
    1274         102 :   *n_bytes_in_buffer = 0;
    1275             : 
    1276         102 :   if (n == 0)
    1277           0 :     return true;
    1278             : 
    1279         311 :   while (in_stream != NULL)     /* EOF.  */
    1280             :     {
    1281             :       size_t n_needed;
    1282             :       size_t n_read;
    1283             : 
    1284         120 :       n_needed = n - *n_bytes_in_buffer;
    1285         120 :       n_read = fread (block + *n_bytes_in_buffer, 1, n_needed, in_stream);
    1286             : 
    1287         120 :       *n_bytes_in_buffer += n_read;
    1288             : 
    1289         120 :       if (n_read == n_needed)
    1290          13 :         break;
    1291             : 
    1292         107 :       ok &= check_and_close (errno);
    1293             : 
    1294         107 :       ok &= open_next_file ();
    1295             :     }
    1296             : 
    1297         102 :   return ok;
    1298             : }
    1299             : 
    1300             : /* Return the least common multiple of the sizes associated
    1301             :    with the format specs.  */
    1302             : 
    1303             : static int
    1304         181 : get_lcm (void)
    1305             : {
    1306             :   size_t i;
    1307         181 :   int l_c_m = 1;
    1308             : 
    1309         368 :   for (i = 0; i < n_specs; i++)
    1310         187 :     l_c_m = lcm (l_c_m, width_bytes[spec[i].size]);
    1311         181 :   return l_c_m;
    1312             : }
    1313             : 
    1314             : /* If S is a valid traditional offset specification with an optional
    1315             :    leading '+' return true and set *OFFSET to the offset it denotes.  */
    1316             : 
    1317             : static bool
    1318          25 : parse_old_offset (const char *s, uintmax_t *offset)
    1319             : {
    1320             :   int radix;
    1321             : 
    1322          25 :   if (*s == '\0')
    1323           1 :     return false;
    1324             : 
    1325             :   /* Skip over any leading '+'. */
    1326          24 :   if (s[0] == '+')
    1327          17 :     ++s;
    1328             : 
    1329             :   /* Determine the radix we'll use to interpret S.  If there is a `.',
    1330             :      it's decimal, otherwise, if the string begins with `0X'or `0x',
    1331             :      it's hexadecimal, else octal.  */
    1332          24 :   if (strchr (s, '.') != NULL)
    1333           8 :     radix = 10;
    1334             :   else
    1335             :     {
    1336          16 :       if (s[0] == '0' && (s[1] == 'x' || s[1] == 'X'))
    1337           2 :         radix = 16;
    1338             :       else
    1339          14 :         radix = 8;
    1340             :     }
    1341             : 
    1342          24 :   return xstrtoumax (s, NULL, radix, offset, "Bb") == LONGINT_OK;
    1343             : }
    1344             : 
    1345             : /* Read a chunk of size BYTES_PER_BLOCK from the input files, write the
    1346             :    formatted block to standard output, and repeat until the specified
    1347             :    maximum number of bytes has been read or until all input has been
    1348             :    processed.  If the last block read is smaller than BYTES_PER_BLOCK
    1349             :    and its size is not a multiple of the size associated with a format
    1350             :    spec, extend the input block with zero bytes until its length is a
    1351             :    multiple of all format spec sizes.  Write the final block.  Finally,
    1352             :    write on a line by itself the offset of the byte after the last byte
    1353             :    read.  Accumulate return values from calls to read_block and
    1354             :    check_and_close, and if any was false, return false.
    1355             :    Otherwise, return true.  */
    1356             : 
    1357             : static bool
    1358          92 : dump (void)
    1359             : {
    1360             :   char *block[2];
    1361             :   uintmax_t current_offset;
    1362          92 :   bool idx = false;
    1363          92 :   bool ok = true;
    1364             :   size_t n_bytes_read;
    1365             : 
    1366          92 :   block[0] = xnmalloc (2, bytes_per_block);
    1367          92 :   block[1] = block[0] + bytes_per_block;
    1368             : 
    1369          92 :   current_offset = n_bytes_to_skip;
    1370             : 
    1371          92 :   if (limit_bytes_to_format)
    1372             :     {
    1373             :       while (1)
    1374           0 :         {
    1375             :           size_t n_needed;
    1376          11 :           if (current_offset >= end_offset)
    1377             :             {
    1378           2 :               n_bytes_read = 0;
    1379           2 :               break;
    1380             :             }
    1381           9 :           n_needed = MIN (end_offset - current_offset,
    1382             :                           (uintmax_t) bytes_per_block);
    1383           9 :           ok &= read_block (n_needed, block[idx], &n_bytes_read);
    1384           9 :           if (n_bytes_read < bytes_per_block)
    1385           9 :             break;
    1386           0 :           assert (n_bytes_read == bytes_per_block);
    1387           0 :           write_block (current_offset, n_bytes_read,
    1388           0 :                        block[!idx], block[idx]);
    1389           0 :           current_offset += n_bytes_read;
    1390           0 :           idx = !idx;
    1391             :         }
    1392             :     }
    1393             :   else
    1394             :     {
    1395             :       while (1)
    1396             :         {
    1397         105 :           ok &= read_block (bytes_per_block, block[idx], &n_bytes_read);
    1398          93 :           if (n_bytes_read < bytes_per_block)
    1399          81 :             break;
    1400          12 :           assert (n_bytes_read == bytes_per_block);
    1401          24 :           write_block (current_offset, n_bytes_read,
    1402          12 :                        block[!idx], block[idx]);
    1403          12 :           current_offset += n_bytes_read;
    1404          12 :           idx = !idx;
    1405             :         }
    1406             :     }
    1407             : 
    1408          92 :   if (n_bytes_read > 0)
    1409             :     {
    1410             :       int l_c_m;
    1411             :       size_t bytes_to_write;
    1412             : 
    1413          78 :       l_c_m = get_lcm ();
    1414             : 
    1415             :       /* Make bytes_to_write the smallest multiple of l_c_m that
    1416             :          is at least as large as n_bytes_read.  */
    1417          78 :       bytes_to_write = l_c_m * ((n_bytes_read + l_c_m - 1) / l_c_m);
    1418             : 
    1419          78 :       memset (block[idx] + n_bytes_read, 0, bytes_to_write - n_bytes_read);
    1420         156 :       write_block (current_offset, bytes_to_write,
    1421          78 :                    block[!idx], block[idx]);
    1422          78 :       current_offset += n_bytes_read;
    1423             :     }
    1424             : 
    1425          92 :   format_address (current_offset, '\n');
    1426             : 
    1427          92 :   if (limit_bytes_to_format && current_offset >= end_offset)
    1428           3 :     ok &= check_and_close (0);
    1429             : 
    1430          92 :   free (block[0]);
    1431             : 
    1432          92 :   return ok;
    1433             : }
    1434             : 
    1435             : /* STRINGS mode.  Find each "string constant" in the input.
    1436             :    A string constant is a run of at least `string_min' ASCII
    1437             :    graphic (or formatting) characters terminated by a null.
    1438             :    Based on a function written by Richard Stallman for a
    1439             :    traditional version of od.  Return true if successful.  */
    1440             : 
    1441             : static bool
    1442          11 : dump_strings (void)
    1443             : {
    1444          11 :   size_t bufsize = MAX (100, string_min);
    1445          11 :   char *buf = xmalloc (bufsize);
    1446          10 :   uintmax_t address = n_bytes_to_skip;
    1447          10 :   bool ok = true;
    1448             : 
    1449             :   while (1)
    1450          24 :     {
    1451             :       size_t i;
    1452             :       int c;
    1453             : 
    1454             :       /* See if the next `string_min' chars are all printing chars.  */
    1455          76 :     tryline:
    1456             : 
    1457          76 :       if (limit_bytes_to_format
    1458           0 :           && (end_offset < string_min || end_offset - string_min <= address))
    1459             :         break;
    1460             : 
    1461          88 :       for (i = 0; i < string_min; i++)
    1462             :         {
    1463          59 :           ok &= read_char (&c);
    1464          59 :           address++;
    1465          59 :           if (c < 0)
    1466             :             {
    1467           7 :               free (buf);
    1468          17 :               return ok;
    1469             :             }
    1470          52 :           if (! isprint (c))
    1471             :             /* Found a non-printing.  Try again starting with next char.  */
    1472          40 :             goto tryline;
    1473          12 :           buf[i] = c;
    1474             :         }
    1475             : 
    1476             :       /* We found a run of `string_min' printable characters.
    1477             :          Now see if it is terminated with a null byte.  */
    1478          60 :       while (!limit_bytes_to_format || address < end_offset)
    1479             :         {
    1480          31 :           if (i == bufsize)
    1481             :             {
    1482           0 :               buf = X2REALLOC (buf, &bufsize);
    1483             :             }
    1484          31 :           ok &= read_char (&c);
    1485          31 :           address++;
    1486          31 :           if (c < 0)
    1487             :             {
    1488           3 :               free (buf);
    1489           3 :               return ok;
    1490             :             }
    1491          28 :           if (c == '\0')
    1492          24 :             break;              /* It is; print this string.  */
    1493           4 :           if (! isprint (c))
    1494           2 :             goto tryline;       /* It isn't; give up on this string.  */
    1495           2 :           buf[i++] = c;         /* String continues; store it all.  */
    1496             :         }
    1497             : 
    1498             :       /* If we get here, the string is all printable and null-terminated,
    1499             :          so print it.  It is all in `buf' and `i' is its length.  */
    1500          24 :       buf[i] = 0;
    1501          24 :       format_address (address - i - 1, ' ');
    1502             : 
    1503          32 :       for (i = 0; (c = buf[i]); i++)
    1504             :         {
    1505           8 :           switch (c)
    1506             :             {
    1507           0 :             case '\a':
    1508           0 :               fputs ("\\a", stdout);
    1509           0 :               break;
    1510             : 
    1511           0 :             case '\b':
    1512           0 :               fputs ("\\b", stdout);
    1513           0 :               break;
    1514             : 
    1515           0 :             case '\f':
    1516           0 :               fputs ("\\f", stdout);
    1517           0 :               break;
    1518             : 
    1519           0 :             case '\n':
    1520           0 :               fputs ("\\n", stdout);
    1521           0 :               break;
    1522             : 
    1523           0 :             case '\r':
    1524           0 :               fputs ("\\r", stdout);
    1525           0 :               break;
    1526             : 
    1527           0 :             case '\t':
    1528           0 :               fputs ("\\t", stdout);
    1529           0 :               break;
    1530             : 
    1531           0 :             case '\v':
    1532           0 :               fputs ("\\v", stdout);
    1533           0 :               break;
    1534             : 
    1535           8 :             default:
    1536           8 :               putc (c, stdout);
    1537             :             }
    1538             :         }
    1539          24 :       putchar ('\n');
    1540             :     }
    1541             : 
    1542             :   /* We reach this point only if we search through
    1543             :      (max_bytes_to_format - string_min) bytes before reaching EOF.  */
    1544             : 
    1545           0 :   free (buf);
    1546             : 
    1547           0 :   ok &= check_and_close (0);
    1548           0 :   return ok;
    1549             : }
    1550             : 
    1551             : int
    1552         156 : main (int argc, char **argv)
    1553             : {
    1554             :   int n_files;
    1555             :   size_t i;
    1556             :   int l_c_m;
    1557             :   size_t desired_width IF_LINT (= 0);
    1558         156 :   bool modern = false;
    1559         156 :   bool width_specified = false;
    1560         156 :   bool ok = true;
    1561             :   static char const multipliers[] = "bEGKkMmPTYZ0";
    1562             : 
    1563             :   /* The old-style `pseudo starting address' to be printed in parentheses
    1564             :      after any true address.  */
    1565             :   uintmax_t pseudo_start IF_LINT (= 0);
    1566             : 
    1567             :   initialize_main (&argc, &argv);
    1568         156 :   program_name = argv[0];
    1569         156 :   setlocale (LC_ALL, "");
    1570             :   bindtextdomain (PACKAGE, LOCALEDIR);
    1571             :   textdomain (PACKAGE);
    1572             : 
    1573         156 :   atexit (close_stdout);
    1574             : 
    1575        1560 :   for (i = 0; i <= MAX_INTEGRAL_TYPE_SIZE; i++)
    1576        1404 :     integral_type_size[i] = NO_SIZE;
    1577             : 
    1578         156 :   integral_type_size[sizeof (char)] = CHAR;
    1579         156 :   integral_type_size[sizeof (short int)] = SHORT;
    1580         156 :   integral_type_size[sizeof (int)] = INT;
    1581         156 :   integral_type_size[sizeof (long int)] = LONG;
    1582             : #if HAVE_UNSIGNED_LONG_LONG_INT
    1583             :   /* If `long int' and `long long int' have the same size, it's fine
    1584             :      to overwrite the entry for `long' with this one.  */
    1585         156 :   integral_type_size[sizeof (unsigned_long_long_int)] = LONG_LONG;
    1586             : #endif
    1587             : 
    1588        2808 :   for (i = 0; i <= MAX_FP_TYPE_SIZE; i++)
    1589        2652 :     fp_type_size[i] = NO_SIZE;
    1590             : 
    1591         156 :   fp_type_size[sizeof (float)] = FLOAT_SINGLE;
    1592             :   /* The array entry for `double' is filled in after that for LONG_DOUBLE
    1593             :      so that if `long double' is the same type or if long double isn't
    1594             :      supported FLOAT_LONG_DOUBLE will never be used.  */
    1595         156 :   fp_type_size[sizeof (LONG_DOUBLE)] = FLOAT_LONG_DOUBLE;
    1596         156 :   fp_type_size[sizeof (double)] = FLOAT_DOUBLE;
    1597             : 
    1598         156 :   n_specs = 0;
    1599         156 :   n_specs_allocated = 0;
    1600         156 :   spec = NULL;
    1601             : 
    1602         156 :   format_address = format_address_std;
    1603         156 :   address_base = 8;
    1604         156 :   address_pad_len = 7;
    1605         156 :   flag_dump_strings = false;
    1606             : 
    1607             :   for (;;)
    1608         100 :     {
    1609             :       uintmax_t tmp;
    1610             :       enum strtol_error s_err;
    1611         256 :       int oi = -1;
    1612         256 :       int c = getopt_long (argc, argv, short_options, long_options, &oi);
    1613         256 :       if (c == -1)
    1614         134 :         break;
    1615             : 
    1616         122 :       switch (c)
    1617             :         {
    1618          10 :         case 'A':
    1619          10 :           modern = true;
    1620          10 :           switch (optarg[0])
    1621             :             {
    1622           2 :             case 'd':
    1623           2 :               format_address = format_address_std;
    1624           2 :               address_base = 10;
    1625           2 :               address_pad_len = 7;
    1626           2 :               break;
    1627           1 :             case 'o':
    1628           1 :               format_address = format_address_std;
    1629           1 :               address_base = 8;
    1630           1 :               address_pad_len = 7;
    1631           1 :               break;
    1632           5 :             case 'x':
    1633           5 :               format_address = format_address_std;
    1634           5 :               address_base = 16;
    1635           5 :               address_pad_len = 6;
    1636           5 :               break;
    1637           1 :             case 'n':
    1638           1 :               format_address = format_address_none;
    1639           1 :               address_pad_len = 0;
    1640           1 :               break;
    1641           1 :             default:
    1642           1 :               error (EXIT_FAILURE, 0,
    1643             :                      _("invalid output address radix `%c'; \
    1644             : it must be one character from [doxn]"),
    1645           1 :                      optarg[0]);
    1646           0 :               break;
    1647             :             }
    1648           9 :           break;
    1649             : 
    1650           3 :         case 'j':
    1651           3 :           modern = true;
    1652           3 :           s_err = xstrtoumax (optarg, NULL, 0, &n_bytes_to_skip, multipliers);
    1653           3 :           if (s_err != LONGINT_OK)
    1654           1 :             xstrtol_fatal (s_err, oi, c, long_options, optarg);
    1655           2 :           break;
    1656             : 
    1657          16 :         case 'N':
    1658          16 :           modern = true;
    1659          16 :           limit_bytes_to_format = true;
    1660             : 
    1661          16 :           s_err = xstrtoumax (optarg, NULL, 0, &max_bytes_to_format,
    1662             :                               multipliers);
    1663          16 :           if (s_err != LONGINT_OK)
    1664           5 :             xstrtol_fatal (s_err, oi, c, long_options, optarg);
    1665          11 :           break;
    1666             : 
    1667          12 :         case 'S':
    1668          12 :           modern = true;
    1669          12 :           if (optarg == NULL)
    1670           7 :             string_min = 3;
    1671             :           else
    1672             :             {
    1673           5 :               s_err = xstrtoumax (optarg, NULL, 0, &tmp, multipliers);
    1674           5 :               if (s_err != LONGINT_OK)
    1675           1 :                 xstrtol_fatal (s_err, oi, c, long_options, optarg);
    1676             : 
    1677             :               /* The minimum string length may be no larger than SIZE_MAX,
    1678             :                  since we may allocate a buffer of this size.  */
    1679             :               if (SIZE_MAX < tmp)
    1680             :                 error (EXIT_FAILURE, 0, _("%s is too large"), optarg);
    1681             : 
    1682           4 :               string_min = tmp;
    1683             :             }
    1684          11 :           flag_dump_strings = true;
    1685          11 :           break;
    1686             : 
    1687          28 :         case 't':
    1688          28 :           modern = true;
    1689          28 :           ok &= decode_format_string (optarg);
    1690          28 :           break;
    1691             : 
    1692           1 :         case 'v':
    1693           1 :           modern = true;
    1694           1 :           abbreviate_duplicate_blocks = false;
    1695           1 :           break;
    1696             : 
    1697           4 :         case TRADITIONAL_OPTION:
    1698           4 :           traditional = true;
    1699           4 :           break;
    1700             : 
    1701             :           /* The next several cases map the traditional format
    1702             :              specification options to the corresponding modern format
    1703             :              specs.  GNU od accepts any combination of old- and
    1704             :              new-style options.  Format specification options accumulate.
    1705             :              The obsolescent and undocumented formats are compatible
    1706             :              with FreeBSD 4.10 od.  */
    1707             : 
    1708             : #define CASE_OLD_ARG(old_char,new_string)               \
    1709             :         case old_char:                                  \
    1710             :           ok &= decode_format_string (new_string);  \
    1711             :           break
    1712             : 
    1713           7 :           CASE_OLD_ARG ('a', "a");
    1714           1 :           CASE_OLD_ARG ('b', "o1");
    1715           9 :           CASE_OLD_ARG ('c', "c");
    1716           1 :           CASE_OLD_ARG ('D', "u4"); /* obsolescent and undocumented */
    1717           1 :           CASE_OLD_ARG ('d', "u2");
    1718           2 :         case 'F': /* obsolescent and undocumented alias */
    1719           2 :           CASE_OLD_ARG ('e', "fD"); /* obsolescent and undocumented */
    1720           1 :           CASE_OLD_ARG ('f', "fF");
    1721           1 :         case 'X': /* obsolescent and undocumented alias */
    1722           1 :           CASE_OLD_ARG ('H', "x4"); /* obsolescent and undocumented */
    1723           1 :           CASE_OLD_ARG ('i', "dI");
    1724           1 :         case 'I': case 'L': /* obsolescent and undocumented aliases */
    1725           1 :           CASE_OLD_ARG ('l', "dL");
    1726           1 :           CASE_OLD_ARG ('O', "o4"); /* obsolesent and undocumented */
    1727           2 :         case 'B': /* obsolescent and undocumented alias */
    1728           2 :           CASE_OLD_ARG ('o', "o2");
    1729           1 :           CASE_OLD_ARG ('s', "d2");
    1730           1 :         case 'h': /* obsolescent and undocumented alias */
    1731           1 :           CASE_OLD_ARG ('x', "x2");
    1732             : 
    1733             : #undef CASE_OLD_ARG
    1734             : 
    1735           7 :         case 'w':
    1736           7 :           modern = true;
    1737           7 :           width_specified = true;
    1738           7 :           if (optarg == NULL)
    1739             :             {
    1740           2 :               desired_width = 32;
    1741             :             }
    1742             :           else
    1743             :             {
    1744             :               uintmax_t w_tmp;
    1745           5 :               s_err = xstrtoumax (optarg, NULL, 10, &w_tmp, "");
    1746           5 :               if (s_err != LONGINT_OK)
    1747           3 :                 xstrtol_fatal (s_err, oi, c, long_options, optarg);
    1748             :               if (SIZE_MAX < w_tmp)
    1749             :                 error (EXIT_FAILURE, 0, _("%s is too large"), optarg);
    1750           2 :               desired_width = w_tmp;
    1751             :             }
    1752           4 :           break;
    1753             : 
    1754           1 :         case_GETOPT_HELP_CHAR;
    1755             : 
    1756           1 :         case_GETOPT_VERSION_CHAR (PROGRAM_NAME, AUTHORS);
    1757             : 
    1758           9 :         default:
    1759           9 :           usage (EXIT_FAILURE);
    1760           0 :           break;
    1761             :         }
    1762             :     }
    1763             : 
    1764         134 :   if (!ok)
    1765          17 :     exit (EXIT_FAILURE);
    1766             : 
    1767         117 :   if (flag_dump_strings && n_specs > 0)
    1768           0 :     error (EXIT_FAILURE, 0,
    1769             :            _("no type may be specified when dumping strings"));
    1770             : 
    1771         117 :   n_files = argc - optind;
    1772             : 
    1773             :   /* If the --traditional option is used, there may be from
    1774             :      0 to 3 remaining command line arguments;  handle each case
    1775             :      separately.
    1776             :         od [file] [[+]offset[.][b] [[+]label[.][b]]]
    1777             :      The offset and label have the same syntax.
    1778             : 
    1779             :      If --traditional is not given, and if no modern options are
    1780             :      given, and if the offset begins with + or (if there are two
    1781             :      operands) a digit, accept only this form, as per POSIX:
    1782             :         od [file] [[+]offset[.][b]]
    1783             :   */
    1784             : 
    1785         117 :   if (!modern | traditional)
    1786             :     {
    1787             :       uintmax_t o1;
    1788             :       uintmax_t o2;
    1789             : 
    1790          68 :       switch (n_files)
    1791             :         {
    1792          18 :         case 1:
    1793          18 :           if ((traditional || argv[optind][0] == '+')
    1794          15 :               && parse_old_offset (argv[optind], &o1))
    1795             :             {
    1796           4 :               n_bytes_to_skip = o1;
    1797           4 :               --n_files;
    1798           4 :               ++argv;
    1799             :             }
    1800          18 :           break;
    1801             : 
    1802          15 :         case 2:
    1803          15 :           if ((traditional || argv[optind + 1][0] == '+'
    1804          10 :                || ISDIGIT (argv[optind + 1][0]))
    1805          10 :               && parse_old_offset (argv[optind + 1], &o2))
    1806             :             {
    1807           4 :               if (traditional && parse_old_offset (argv[optind], &o1))
    1808             :                 {
    1809           0 :                   n_bytes_to_skip = o1;
    1810           0 :                   flag_pseudo_start = true;
    1811           0 :                   pseudo_start = o2;
    1812           0 :                   argv += 2;
    1813           0 :                   n_files -= 2;
    1814             :                 }
    1815             :               else
    1816             :                 {
    1817           4 :                   n_bytes_to_skip = o2;
    1818           4 :                   --n_files;
    1819           4 :                   argv[optind + 1] = argv[optind];
    1820           4 :                   ++argv;
    1821             :                 }
    1822             :             }
    1823          15 :           break;
    1824             : 
    1825           7 :         case 3:
    1826           7 :           if (traditional
    1827           0 :               && parse_old_offset (argv[optind + 1], &o1)
    1828           0 :               && parse_old_offset (argv[optind + 2], &o2))
    1829             :             {
    1830           0 :               n_bytes_to_skip = o1;
    1831           0 :               flag_pseudo_start = true;
    1832           0 :               pseudo_start = o2;
    1833           0 :               argv[optind + 2] = argv[optind];
    1834           0 :               argv += 2;
    1835           0 :               n_files -= 2;
    1836             :             }
    1837           7 :           break;
    1838             :         }
    1839             : 
    1840          68 :       if (traditional && 1 < n_files)
    1841             :         {
    1842           1 :           error (0, 0, _("extra operand %s"), quote (argv[optind + 1]));
    1843           1 :           error (0, 0, "%s\n",
    1844             :                  _("Compatibility mode supports at most one file."));
    1845           1 :           usage (EXIT_FAILURE);
    1846             :         }
    1847             :     }
    1848             : 
    1849         116 :   if (flag_pseudo_start)
    1850             :     {
    1851           0 :       if (format_address == format_address_none)
    1852             :         {
    1853           0 :           address_base = 8;
    1854           0 :           address_pad_len = 7;
    1855           0 :           format_address = format_address_paren;
    1856             :         }
    1857             :       else
    1858           0 :         format_address = format_address_label;
    1859             :     }
    1860             : 
    1861         116 :   if (limit_bytes_to_format)
    1862             :     {
    1863          11 :       end_offset = n_bytes_to_skip + max_bytes_to_format;
    1864          11 :       if (end_offset < n_bytes_to_skip)
    1865           0 :         error (EXIT_FAILURE, 0, _("skip-bytes + read-bytes is too large"));
    1866             :     }
    1867             : 
    1868         116 :   if (n_specs == 0)
    1869          78 :     decode_format_string ("oS");
    1870             : 
    1871         116 :   if (n_files > 0)
    1872             :     {
    1873             :       /* Set the global pointer FILE_LIST so that it
    1874             :          references the first file-argument on the command-line.  */
    1875             : 
    1876          46 :       file_list = (char const *const *) &argv[optind];
    1877             :     }
    1878             :   else
    1879             :     {
    1880             :       /* No files were listed on the command line.
    1881             :          Set the global pointer FILE_LIST so that it
    1882             :          references the null-terminated list of one name: "-".  */
    1883             : 
    1884          70 :       file_list = default_file_list;
    1885             :     }
    1886             : 
    1887             :   /* open the first input file */
    1888         116 :   ok = open_next_file ();
    1889         116 :   if (in_stream == NULL)
    1890          12 :     goto cleanup;
    1891             : 
    1892             :   /* skip over any unwanted header bytes */
    1893         104 :   ok &= skip (n_bytes_to_skip);
    1894         103 :   if (in_stream == NULL)
    1895           0 :     goto cleanup;
    1896             : 
    1897         103 :   pseudo_offset = (flag_pseudo_start ? pseudo_start - n_bytes_to_skip : 0);
    1898             : 
    1899             :   /* Compute output block length.  */
    1900         103 :   l_c_m = get_lcm ();
    1901             : 
    1902         103 :   if (width_specified)
    1903             :     {
    1904           4 :       if (desired_width != 0 && desired_width % l_c_m == 0)
    1905           3 :         bytes_per_block = desired_width;
    1906             :       else
    1907             :         {
    1908           1 :           error (0, 0, _("warning: invalid width %lu; using %d instead"),
    1909             :                  (unsigned long int) desired_width, l_c_m);
    1910           1 :           bytes_per_block = l_c_m;
    1911             :         }
    1912             :     }
    1913             :   else
    1914             :     {
    1915          99 :       if (l_c_m < DEFAULT_BYTES_PER_BLOCK)
    1916          98 :         bytes_per_block = l_c_m * (DEFAULT_BYTES_PER_BLOCK / l_c_m);
    1917             :       else
    1918           1 :         bytes_per_block = l_c_m;
    1919             :     }
    1920             : 
    1921             : #ifdef DEBUG
    1922             :   for (i = 0; i < n_specs; i++)
    1923             :     {
    1924             :       printf (_("%d: fmt=\"%s\" width=%d\n"),
    1925             :               i, spec[i].fmt_string, width_bytes[spec[i].size]);
    1926             :     }
    1927             : #endif
    1928             : 
    1929         103 :   ok &= (flag_dump_strings ? dump_strings () : dump ());
    1930             : 
    1931         114 : cleanup:;
    1932             : 
    1933         114 :   if (have_read_stdin && fclose (stdin) == EOF)
    1934           0 :     error (EXIT_FAILURE, errno, _("standard input"));
    1935             : 
    1936         114 :   exit (ok ? EXIT_SUCCESS : EXIT_FAILURE);
    1937             : }

Generated by: LCOV version 1.10