bug-coreutils
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

coreutils "od" int cleanup


From: Paul Eggert
Subject: coreutils "od" int cleanup
Date: Tue, 03 Aug 2004 07:42:38 -0700
User-agent: Gnus/5.1006 (Gnus v5.10.6) Emacs/21.3 (gnu/linux)

This patch is mostly a code cleanup.  It fixes bugs that I think are
only theoretical: if you specify more than INT_MAX invalid decodings,
or are on a platform where strlen (PRIdMAX) > 3, "od" has undefined
behavior.

2004-08-03  Paul Eggert  <address@hidden>

        * src/od.c (FMT_BYTES_ALLOCATED): Now an enum, not a decimal
        constant.  Do not assume PRIdMAX etc. are strings of length 3 or
        less.
        (struct tspec): Use it.  fmt_string is now an array, not
        a pointer, as there's little point to the indirection here.
        (struct tspec, flag_dump_strings,
        traditional, flag_pseudo_start, limit_bytes_to_format,
        abbreviate_duplicate_blocks, have_read_stdin, simple_strtoul,
        decode_one_format, open_next_file, check_and_close,
        decode_format_string, skip, write_block, read_char, read_block,
        parse_old_offset, dump, dump_strings, main):
        Use bool for booleans.
        (struct tspec): Use void *, not char *, for generic pointers.
        (bytes_to_oct_digits, bytes_to_signed_dec_digits,
        bytes_to_unsigned_dec_digits, bytes_to_hex_digits):
        Use char, not unsigned int, since char suffices.
        (print_s_char, print_char, print_s_short, print_short,
        print_int, print_long, print_long_long, print_float,
        print_double, print_long_double): Rewrite to avoid casts.
        These now take void * arguments, instead of char *.
        Use the same body for all functions, except for the choice
        of type.  Assume C89 to simplify handling of signed char.
        (dump_hexl_mode_trailer, print_named_ascii, print_ascii):
        Rewrite to avoid casts.
        (print_named_ascii, print_ascii): Now takes void *, not char *.
        (decode_one_format): Use int for printf field widths, not
        unsigned int.  Pass void * to subsidiary printers,
        not char *.  Simplify handling of floating-point formats
        by factoring out common code dealing with precision and field width.
        (decode_format_string): Avoid need for temporary copy of
        each decoded struct tspec.
        (get_lcm): Remove unnecessary cast.
        (main): Fix bug where more than INT_MAX failed decodes were ignored.

Index: od.c
===================================================================
RCS file: /home/eggert/coreutils/cu/src/od.c,v
retrieving revision 1.149
retrieving revision 1.150
diff -p -u -r1.149 -r1.150
--- od.c        21 Jun 2004 15:03:35 -0000      1.149
+++ od.c        3 Aug 2004 14:38:53 -0000       1.150
@@ -63,7 +63,7 @@ typedef double LONG_DOUBLE;
 #endif
 
 #if HAVE_UNSIGNED_LONG_LONG
-typedef unsigned long long ulonglong_t;
+typedef unsigned long long int ulonglong_t;
 #else
 /* This is just a place-holder to avoid a few `#if' directives.
    In this case, the type isn't actually used.  */
@@ -96,15 +96,29 @@ enum output_format
     CHARACTER
   };
 
+/* The maximum number of bytes needed for a format string,
+   including the trailing null.  */
+enum
+  {
+    FMT_BYTES_ALLOCATED =
+      MAX ((sizeof " %0" - 1 + INT_STRLEN_BOUND (int)
+           + MAX (sizeof "ld",
+                  MAX (sizeof PRIdMAX,
+                       MAX (sizeof PRIoMAX,
+                            MAX (sizeof PRIuMAX,
+                                 sizeof PRIxMAX))))),
+          sizeof " %.Le" + 2 * INT_STRLEN_BOUND (int))
+  };
+
 /* Each output format specification (from `-t spec' or from
    old-style options) is represented by one of these structures.  */
 struct tspec
   {
     enum output_format fmt;
     enum size_spec size;
-    void (*print_function) (size_t, const char *, const char *);
-    char *fmt_string;
-    int hexl_mode_trailer;
+    void (*print_function) (size_t, void const *, char const *);
+    char fmt_string[FMT_BYTES_ALLOCATED];
+    bool hexl_mode_trailer;
     int field_width;
   };
 
@@ -121,16 +135,16 @@ char *program_name;
    10  unsigned decimal
    8   unsigned hexadecimal  */
 
-static const unsigned int bytes_to_oct_digits[] =
+static char const bytes_to_oct_digits[] =
 {0, 3, 6, 8, 11, 14, 16, 19, 22, 25, 27, 30, 32, 35, 38, 41, 43};
 
-static const unsigned int bytes_to_signed_dec_digits[] =
+static char const bytes_to_signed_dec_digits[] =
 {1, 4, 6, 8, 11, 13, 16, 18, 20, 23, 25, 28, 30, 33, 35, 37, 40};
 
-static const unsigned int bytes_to_unsigned_dec_digits[] =
+static char const bytes_to_unsigned_dec_digits[] =
 {0, 3, 5, 8, 10, 13, 15, 17, 20, 22, 25, 27, 29, 32, 34, 37, 39};
 
-static const unsigned int bytes_to_hex_digits[] =
+static char const bytes_to_hex_digits[] =
 {0, 2, 4, 6, 8, 10, 12, 14, 16, 18, 20, 22, 24, 26, 28, 30, 32};
 
 /* Convert enum size_spec to the size of the named type.  */
@@ -177,15 +191,15 @@ static int address_base;
 static int address_pad_len;
 
 static size_t string_min;
-static int flag_dump_strings;
+static bool flag_dump_strings;
 
-/* Non-zero if we should recognize the older non-option arguments
+/* True if we should recognize the older non-option arguments
    that specified at most one file and optional arguments specifying
    offset and pseudo-start address.  */
-static int traditional;
+static bool traditional;
 
-/* Non-zero if an old-style `pseudo-address' was specified.  */
-static int flag_pseudo_start;
+/* True if an old-style `pseudo-address' was specified.  */
+static bool flag_pseudo_start;
 
 /* The difference between the old-style pseudo starting address and
    the number of bytes to skip.  */
@@ -198,9 +212,9 @@ static void (*format_address) (uintmax_t
 /* The number of input bytes to skip before formatting and writing.  */
 static uintmax_t n_bytes_to_skip = 0;
 
-/* When zero, MAX_BYTES_TO_FORMAT and END_OFFSET are ignored, and all
+/* When false, MAX_BYTES_TO_FORMAT and END_OFFSET are ignored, and all
    input is formatted.  */
-static int limit_bytes_to_format = 0;
+static bool limit_bytes_to_format = false;
 
 /* The maximum number of bytes that will be formatted.  */
 static uintmax_t max_bytes_to_format;
@@ -208,10 +222,10 @@ static uintmax_t max_bytes_to_format;
 /* The offset of the first byte after the last byte to be formatted.  */
 static uintmax_t end_offset;
 
-/* When nonzero and two or more consecutive blocks are equal, format
+/* When true and two or more consecutive blocks are equal, format
    only the first block and output an asterisk alone on the following
    line to indicate that identical blocks have been elided.  */
-static int abbreviate_duplicate_blocks = 1;
+static bool abbreviate_duplicate_blocks = true;
 
 /* An array of specs describing how to format each input block.  */
 static struct tspec *spec;
@@ -242,13 +256,13 @@ static char const *const default_file_li
 /* The input stream associated with the current file.  */
 static FILE *in_stream;
 
-/* If nonzero, at least one of the files we read was standard input.  */
-static int have_read_stdin;
+/* If true, at least one of the files we read was standard input.  */
+static bool have_read_stdin;
 
 #define MAX_INTEGRAL_TYPE_SIZE sizeof (ulonglong_t)
 static enum size_spec integral_type_size[MAX_INTEGRAL_TYPE_SIZE + 1];
 
-#define MAX_FP_TYPE_SIZE sizeof(LONG_DOUBLE)
+#define MAX_FP_TYPE_SIZE sizeof (LONG_DOUBLE)
 static enum size_spec fp_type_size[MAX_FP_TYPE_SIZE + 1];
 
 #define COMMON_SHORT_OPTIONS "A:N:abcdfhij:lot:vx"
@@ -372,133 +386,98 @@ implies 32.  By default, od uses -A o -t
   exit (status);
 }
 
+/* Define the print functions.  */
+
 static void
-print_s_char (size_t n_bytes, const char *block, const char *fmt_string)
+print_s_char (size_t n_bytes, void const *block, char const *fmt_string)
 {
+  signed char const *p = block;
   size_t i;
-  for (i = n_bytes; i > 0; i--)
-    {
-      int tmp = (unsigned) *(const unsigned char *) block;
-      if (tmp > SCHAR_MAX)
-       tmp -= SCHAR_MAX - SCHAR_MIN + 1;
-      assert (tmp <= SCHAR_MAX);
-      printf (fmt_string, tmp);
-      block += sizeof (unsigned char);
-    }
+  for (i = n_bytes / sizeof *p; i != 0; i--)
+    printf (fmt_string, *p++);
 }
 
 static void
-print_char (size_t n_bytes, const char *block, const char *fmt_string)
+print_char (size_t n_bytes, void const *block, char const *fmt_string)
 {
+  unsigned char const *p = block;
   size_t i;
-  for (i = n_bytes; i > 0; i--)
-    {
-      unsigned int tmp = *(const unsigned char *) block;
-      printf (fmt_string, tmp);
-      block += sizeof (unsigned char);
-    }
+  for (i = n_bytes / sizeof *p; i != 0; i--)
+    printf (fmt_string, *p++);
 }
 
 static void
-print_s_short (size_t n_bytes, const char *block, const char *fmt_string)
+print_s_short (size_t n_bytes, void const *block, char const *fmt_string)
 {
+  short int const *p = block;
   size_t i;
-  for (i = n_bytes / sizeof (unsigned short); i > 0; i--)
-    {
-      int tmp = (unsigned) *(const unsigned short *) block;
-      if (tmp > SHRT_MAX)
-       tmp -= SHRT_MAX - SHRT_MIN + 1;
-      assert (tmp <= SHRT_MAX);
-      printf (fmt_string, tmp);
-      block += sizeof (unsigned short);
-    }
+  for (i = n_bytes / sizeof *p; i != 0; i--)
+    printf (fmt_string, *p++);
 }
 
 static void
-print_short (size_t n_bytes, const char *block, const char *fmt_string)
+print_short (size_t n_bytes, void const *block, char const *fmt_string)
 {
+  unsigned short int const *p = block;
   size_t i;
-  for (i = n_bytes / sizeof (unsigned short); i > 0; i--)
-    {
-      unsigned int tmp = *(const unsigned short *) block;
-      printf (fmt_string, tmp);
-      block += sizeof (unsigned short);
-    }
+  for (i = n_bytes / sizeof *p; i != 0; i--)
+    printf (fmt_string, *p++);
 }
 
 static void
-print_int (size_t n_bytes, const char *block, const char *fmt_string)
+print_int (size_t n_bytes, void const *block, char const *fmt_string)
 {
+  unsigned int const *p = block;
   size_t i;
-  for (i = n_bytes / sizeof (unsigned int); i > 0; i--)
-    {
-      unsigned int tmp = *(const unsigned int *) block;
-      printf (fmt_string, tmp);
-      block += sizeof (unsigned int);
-    }
+  for (i = n_bytes / sizeof *p; i != 0; i--)
+    printf (fmt_string, *p++);
 }
 
 static void
-print_long (size_t n_bytes, const char *block, const char *fmt_string)
+print_long (size_t n_bytes, void const *block, char const *fmt_string)
 {
+  unsigned long int const *p = block;
   size_t i;
-  for (i = n_bytes / sizeof (unsigned long); i > 0; i--)
-    {
-      unsigned long tmp = *(const unsigned long *) block;
-      printf (fmt_string, tmp);
-      block += sizeof (unsigned long);
-    }
+  for (i = n_bytes / sizeof *p; i != 0; i--)
+    printf (fmt_string, *p++);
 }
 
 static void
-print_long_long (size_t n_bytes, const char *block, const char *fmt_string)
+print_long_long (size_t n_bytes, void const *block, char const *fmt_string)
 {
+  ulonglong_t const *p = block;
   size_t i;
-  for (i = n_bytes / sizeof (ulonglong_t); i > 0; i--)
-    {
-      ulonglong_t tmp = *(const ulonglong_t *) block;
-      printf (fmt_string, tmp);
-      block += sizeof (ulonglong_t);
-    }
+  for (i = n_bytes / sizeof *p; i != 0; i--)
+    printf (fmt_string, *p++);
 }
 
 static void
-print_float (size_t n_bytes, const char *block, const char *fmt_string)
+print_float (size_t n_bytes, void const *block, char const *fmt_string)
 {
+  float const *p = block;
   size_t i;
-  for (i = n_bytes / sizeof (float); i > 0; i--)
-    {
-      float tmp = *(const float *) block;
-      printf (fmt_string, tmp);
-      block += sizeof (float);
-    }
+  for (i = n_bytes / sizeof *p; i != 0; i--)
+    printf (fmt_string, *p++);
 }
 
 static void
-print_double (size_t n_bytes, const char *block, const char *fmt_string)
+print_double (size_t n_bytes, void const *block, char const *fmt_string)
 {
+  double const *p = block;
   size_t i;
-  for (i = n_bytes / sizeof (double); i > 0; i--)
-    {
-      double tmp = *(const double *) block;
-      printf (fmt_string, tmp);
-      block += sizeof (double);
-    }
+  for (i = n_bytes / sizeof *p; i != 0; i--)
+    printf (fmt_string, *p++);
 }
 
 #ifdef HAVE_LONG_DOUBLE
 static void
-print_long_double (size_t n_bytes, const char *block, const char *fmt_string)
+print_long_double (size_t n_bytes, void const *block, char const *fmt_string)
 {
+  long double const *p = block;
   size_t i;
-  for (i = n_bytes / sizeof (LONG_DOUBLE); i > 0; i--)
-    {
-      LONG_DOUBLE tmp = *(const LONG_DOUBLE *) block;
-      printf (fmt_string, tmp);
-      block += sizeof (LONG_DOUBLE);
-    }
+  for (i = n_bytes / sizeof *p; i != 0; i--)
+    printf (fmt_string, *p++);
 }
-
 #endif
 
 static void
@@ -508,23 +487,22 @@ dump_hexl_mode_trailer (size_t n_bytes, 
   fputs ("  >", stdout);
   for (i = n_bytes; i > 0; i--)
     {
-      unsigned int c = *(const unsigned char *) block;
-      unsigned int c2 = (ISPRINT(c) ? c : '.');
+      unsigned char c = *block++;
+      unsigned char c2 = (ISPRINT(c) ? c : '.');
       putchar (c2);
-      block += sizeof (unsigned char);
     }
   putchar ('<');
 }
 
 static void
-print_named_ascii (size_t n_bytes, const char *block,
+print_named_ascii (size_t n_bytes, void const *block,
                   const char *unused_fmt_string ATTRIBUTE_UNUSED)
 {
+  unsigned char const *p = block;
   size_t i;
   for (i = n_bytes; i > 0; i--)
     {
-      unsigned int c = *(const unsigned char *) block;
-      unsigned int masked_c = (0x7f & c);
+      int masked_c = *p++ & 0x7f;
       const char *s;
       char buf[5];
 
@@ -539,18 +517,18 @@ print_named_ascii (size_t n_bytes, const
        }
 
       printf (" %3s", s);
-      block += sizeof (unsigned char);
     }
 }
 
 static void
-print_ascii (size_t n_bytes, const char *block,
+print_ascii (size_t n_bytes, void const *block,
             const char *unused_fmt_string ATTRIBUTE_UNUSED)
 {
+  unsigned char const *p = block;
   size_t i;
   for (i = n_bytes; i > 0; i--)
     {
-      unsigned int c = *(const unsigned char *) block;
+      unsigned char c = *p++;
       const char *s;
       char buf[5];
 
@@ -590,45 +568,44 @@ print_ascii (size_t n_bytes, const char 
 
        default:
          sprintf (buf, (ISPRINT (c) ? "  %c" : "%03o"), c);
-         s = (const char *) buf;
+         s = buf;
        }
 
       printf (" %3s", s);
-      block += sizeof (unsigned char);
     }
 }
 
 /* Convert a null-terminated (possibly zero-length) string S to an
    unsigned long integer value.  If S points to a non-digit set *P to S,
-   *VAL to 0, and return 0.  Otherwise, accumulate the integer value of
+   *VAL to 0, and return true.  Otherwise, accumulate the integer value of
    the string of digits.  If the string of digits represents a value
-   larger than ULONG_MAX, don't modify *VAL or *P and return nonzero.
+   larger than ULONG_MAX, don't modify *VAL or *P and return false.
    Otherwise, advance *P to the first non-digit after S, set *VAL to
-   the result of the conversion and return zero.  */
+   the result of the conversion and return true.  */
 
-static int
-simple_strtoul (const char *s, const char **p, long unsigned int *val)
+static bool
+simple_strtoul (const char *s, const char **p, unsigned long int *val)
 {
   unsigned long int sum;
 
   sum = 0;
   while (ISDIGIT (*s))
     {
-      unsigned int c = *s++ - '0';
+      int c = *s++ - '0';
       if (sum > (ULONG_MAX - c) / 10)
-       return 1;
+       return false;
       sum = sum * 10 + c;
     }
   *p = s;
   *val = sum;
-  return 0;
+  return true;
 }
 
 /* If S points to a single valid modern od format string, put
    a description of that format in *TSPEC, make *NEXT point at the
    character following the just-decoded format (if *NEXT is non-NULL),
-   and return zero.  If S is not valid, don't modify *NEXT or *TSPEC,
-   give a diagnostic, and return nonzero.  For example, if S were
+   and return true.  If S is not valid, don't modify *NEXT or *TSPEC,
+   give a diagnostic, and return false.  For example, if S were
    "d4afL" *NEXT would be set to "afL" and *TSPEC would be
      {
        fmt = SIGNED_DECIMAL;
@@ -640,7 +617,7 @@ simple_strtoul (const char *s, const cha
    string argument.
    */
 
-static int
+static bool
 decode_one_format (const char *s_orig, const char *s, const char **next,
                   struct tspec *tspec)
 {
@@ -648,11 +625,11 @@ decode_one_format (const char *s_orig, c
   unsigned long int size;
   enum output_format fmt;
   const char *pre_fmt_string;
-  char *fmt_string;
-  void (*print_function) (size_t, const char *, const char *);
+  void (*print_function) (size_t, void const *, char const *);
   const char *p;
-  unsigned int c;
-  unsigned int field_width = 0;
+  char c;
+  int field_width;
+  int precision;
 
   assert (tspec != NULL);
 
@@ -673,7 +650,7 @@ decode_one_format (const char *s_orig, c
 
        case 'S':
          ++s;
-         size = sizeof (short);
+         size = sizeof (short int);
          break;
 
        case 'I':
@@ -687,13 +664,13 @@ decode_one_format (const char *s_orig, c
          break;
 
        default:
-         if (simple_strtoul (s, &p, &size) != 0)
+         if (! simple_strtoul (s, &p, &size))
            {
-             /* The integer at P in S would overflow an unsigned long.
+             /* The integer at P in S would overflow an unsigned long int.
                 A digit string that long is sufficiently odd looking
                 that the following diagnostic is sufficient.  */
              error (0, 0, _("invalid type string `%s'"), s_orig);
-             return 1;
+             return false;
            }
          if (p == s)
            size = sizeof (int);
@@ -704,7 +681,7 @@ decode_one_format (const char *s_orig, c
                {
                  error (0, 0, _("invalid type string `%s';\n\
 this system doesn't provide a %lu-byte integral type"), s_orig, size);
-                 return 1;
+                 return false;
                }
              s = p;
            }
@@ -716,37 +693,34 @@ this system doesn't provide a %lu-byte i
    : ((Spec) == LONG ? (Long_format)                                   \
       : (Min_format)))                                                 \
 
-#define FMT_BYTES_ALLOCATED 9
-      fmt_string = xmalloc (FMT_BYTES_ALLOCATED);
-
       size_spec = integral_type_size[size];
 
       switch (c)
        {
        case 'd':
          fmt = SIGNED_DECIMAL;
-         sprintf (fmt_string, " %%%u%s",
+         sprintf (tspec->fmt_string, " %%%d%s",
                   (field_width = bytes_to_signed_dec_digits[size]),
                   ISPEC_TO_FORMAT (size_spec, "d", "ld", PRIdMAX));
          break;
 
        case 'o':
          fmt = OCTAL;
-         sprintf (fmt_string, " %%0%u%s",
+         sprintf (tspec->fmt_string, " %%0%d%s",
                   (field_width = bytes_to_oct_digits[size]),
                   ISPEC_TO_FORMAT (size_spec, "o", "lo", PRIoMAX));
          break;
 
        case 'u':
          fmt = UNSIGNED_DECIMAL;
-         sprintf (fmt_string, " %%%u%s",
+         sprintf (tspec->fmt_string, " %%%d%s",
                   (field_width = bytes_to_unsigned_dec_digits[size]),
                   ISPEC_TO_FORMAT (size_spec, "u", "lu", PRIuMAX));
          break;
 
        case 'x':
          fmt = HEXADECIMAL;
-         sprintf (fmt_string, " %%0%u%s",
+         sprintf (tspec->fmt_string, " %%0%d%s",
                   (field_width = bytes_to_hex_digits[size]),
                   ISPEC_TO_FORMAT (size_spec, "x", "lx", PRIxMAX));
          break;
@@ -755,7 +729,7 @@ this system doesn't provide a %lu-byte i
          abort ();
        }
 
-      assert (strlen (fmt_string) < FMT_BYTES_ALLOCATED);
+      assert (strlen (tspec->fmt_string) < FMT_BYTES_ALLOCATED);
 
       switch (size_spec)
        {
@@ -809,13 +783,13 @@ this system doesn't provide a %lu-byte i
          break;
 
        default:
-         if (simple_strtoul (s, &p, &size) != 0)
+         if (! simple_strtoul (s, &p, &size))
            {
-             /* The integer at P in S would overflow an unsigned long.
+             /* The integer at P in S would overflow an unsigned long int.
                 A digit string that long is sufficiently odd looking
                 that the following diagnostic is sufficient.  */
              error (0, 0, _("invalid type string `%s'"), s_orig);
-             return 1;
+             return false;
            }
          if (p == s)
            size = sizeof (double);
@@ -826,7 +800,7 @@ this system doesn't provide a %lu-byte i
                {
                  error (0, 0, _("invalid type string `%s';\n\
 this system doesn't provide a %lu-byte floating point type"), s_orig, size);
-                 return 1;
+                 return false;
                }
              s = p;
            }
@@ -840,39 +814,35 @@ this system doesn't provide a %lu-byte f
          print_function = print_float;
          /* Don't use %#e; not all systems support it.  */
          pre_fmt_string = " %%%d.%de";
-         fmt_string = xmalloc (strlen (pre_fmt_string));
-         sprintf (fmt_string, pre_fmt_string,
-                  (field_width = FLT_DIG + 8), FLT_DIG);
+         precision = FLT_DIG;
          break;
 
        case FLOAT_DOUBLE:
          print_function = print_double;
          pre_fmt_string = " %%%d.%de";
-         fmt_string = xmalloc (strlen (pre_fmt_string));
-         sprintf (fmt_string, pre_fmt_string,
-                  (field_width = DBL_DIG + 8), DBL_DIG);
+         precision = DBL_DIG;
          break;
 
 #ifdef HAVE_LONG_DOUBLE
        case FLOAT_LONG_DOUBLE:
          print_function = print_long_double;
          pre_fmt_string = " %%%d.%dLe";
-         fmt_string = xmalloc (strlen (pre_fmt_string));
-         sprintf (fmt_string, pre_fmt_string,
-                  (field_width = LDBL_DIG + 8), LDBL_DIG);
+         precision = LDBL_DIG;
          break;
 #endif
 
        default:
          abort ();
        }
+
+      field_width = precision + 8;
+      sprintf (tspec->fmt_string, pre_fmt_string, field_width, precision);
       break;
 
     case 'a':
       ++s;
       fmt = NAMED_CHARACTER;
       size_spec = CHAR;
-      fmt_string = NULL;
       print_function = print_named_ascii;
       field_width = 3;
       break;
@@ -881,7 +851,6 @@ this system doesn't provide a %lu-byte f
       ++s;
       fmt = CHARACTER;
       size_spec = CHAR;
-      fmt_string = NULL;
       print_function = print_ascii;
       field_width = 3;
       break;
@@ -889,13 +858,12 @@ this system doesn't provide a %lu-byte f
     default:
       error (0, 0, _("invalid character `%c' in type string `%s'"),
             *s, s_orig);
-      return 1;
+      return false;
     }
 
   tspec->size = size_spec;
   tspec->fmt = fmt;
   tspec->print_function = print_function;
-  tspec->fmt_string = fmt_string;
 
   tspec->field_width = field_width;
   tspec->hexl_mode_trailer = (*s == 'z');
@@ -905,7 +873,7 @@ this system doesn't provide a %lu-byte f
   if (next != NULL)
     *next = s;
 
-  return 0;
+  return true;
 }
 
 /* Given a list of one or more input filenames FILE_LIST, set the global
@@ -913,25 +881,25 @@ this system doesn't provide a %lu-byte f
    first one that can be successfully opened. Modify FILE_LIST to
    reference the next filename in the list.  A file name of "-" is
    interpreted as standard input.  If any file open fails, give an error
-   message and return nonzero.  */
+   message and return false.  */
 
-static int
+static bool
 open_next_file (void)
 {
-  int err = 0;
+  bool ok = true;
 
   do
     {
       input_filename = *file_list;
       if (input_filename == NULL)
-       return err;
+       return ok;
       ++file_list;
 
       if (STREQ (input_filename, "-"))
        {
          input_filename = _("standard input");
          in_stream = stdin;
-         have_read_stdin = 1;
+         have_read_stdin = true;
        }
       else
        {
@@ -939,30 +907,30 @@ open_next_file (void)
          if (in_stream == NULL)
            {
              error (0, errno, "%s", input_filename);
-             err = 1;
+             ok = false;
            }
        }
     }
   while (in_stream == NULL);
 
-  if (limit_bytes_to_format && !flag_dump_strings)
+  if (limit_bytes_to_format & !flag_dump_strings)
     SETVBUF (in_stream, NULL, _IONBF, 0);
   SET_BINARY (fileno (in_stream));
 
-  return err;
+  return ok;
 }
 
 /* Test whether there have been errors on in_stream, and close it if
-   it is not standard input.  Return nonzero if there has been an error
-   on in_stream or stdout; return zero otherwise.  This function will
+   it is not standard input.  Return false if there has been an error
+   on in_stream or stdout; return true otherwise.  This function will
    report more than one error only if both a read and a write error
    have occurred.  IN_ERRNO, if nonzero, is the error number
    corresponding to the most recent action for IN_STREAM.  */
 
-static int
+static bool
 check_and_close (int in_errno)
 {
-  int err = 0;
+  bool ok = true;
 
   if (in_stream != NULL)
     {
@@ -971,12 +939,12 @@ check_and_close (int in_errno)
          error (0, in_errno, _("%s: read error"), input_filename);
          if (in_stream != stdin)
            fclose (in_stream);
-         err = 1;
+         ok = false;
        }
       else if (in_stream != stdin && fclose (in_stream) == EOF)
        {
          error (0, errno, "%s", input_filename);
-         err = 1;
+         ok = false;
        }
 
       in_stream = NULL;
@@ -985,17 +953,17 @@ check_and_close (int in_errno)
   if (ferror (stdout))
     {
       error (0, 0, _("write error"));
-      err = 1;
+      ok = false;
     }
 
-  return err;
+  return ok;
 }
 
 /* Decode the modern od format string S.  Append the decoded
    representation to the global array SPEC, reallocating SPEC if
-   necessary.  Return zero if S is valid, nonzero otherwise.  */
+   necessary.  Return true if S is valid.  */
 
-static int
+static bool
 decode_format_string (const char *s)
 {
   const char *s_orig = s;
@@ -1003,40 +971,37 @@ decode_format_string (const char *s)
 
   while (*s != '\0')
     {
-      struct tspec tspec;
       const char *next;
 
-      if (decode_one_format (s_orig, s, &next, &tspec))
-       return 1;
-
-      assert (s != next);
-      s = next;
-
       if (n_specs_allocated <= n_specs)
        spec = x2nrealloc (spec, &n_specs_allocated, sizeof *spec);
 
-      memcpy (&spec[n_specs], &tspec, sizeof *spec);
+      if (! decode_one_format (s_orig, s, &next, &spec[n_specs]))
+       return false;
+
+      assert (s != next);
+      s = next;
       ++n_specs;
     }
 
-  return 0;
+  return true;
 }
 
 /* Given a list of one or more input filenames FILE_LIST, set the global
    file pointer IN_STREAM to position N_SKIP in the concatenation of
    those files.  If any file operation fails or if there are fewer than
    N_SKIP bytes in the combined input, give an error message and return
-   nonzero.  When possible, use seek rather than read operations to
+   false.  When possible, use seek rather than read operations to
    advance IN_STREAM.  */
 
-static int
+static bool
 skip (uintmax_t n_skip)
 {
-  int err = 0;
+  bool ok = true;
   int in_errno = 0;
 
   if (n_skip == 0)
-    return 0;
+    return true;
 
   while (in_stream != NULL)    /* EOF.  */
     {
@@ -1069,7 +1034,7 @@ skip (uintmax_t n_skip)
                  if (fseeko (in_stream, n_skip, SEEK_CUR) != 0)
                    {
                      in_errno = errno;
-                     err = 1;
+                     ok = false;
                    }
                  n_skip = 0;
                }
@@ -1092,7 +1057,7 @@ skip (uintmax_t n_skip)
                  if (n_bytes_read != n_bytes_to_read)
                    {
                      in_errno = errno;
-                     err = 1;
+                     ok = false;
                      n_skip = 0;
                      break;
                    }
@@ -1106,18 +1071,18 @@ skip (uintmax_t n_skip)
       else   /* cannot fstat() file */
        {
          error (0, errno, "%s", input_filename);
-         err = 1;
+         ok = false;
        }
 
-      err |= check_and_close (in_errno);
+      ok &= check_and_close (in_errno);
 
-      err |= open_next_file ();
+      ok &= open_next_file ();
     }
 
   if (n_skip != 0)
     error (EXIT_FAILURE, 0, _("cannot skip past end of combined input"));
 
-  return err;
+  return ok;
 }
 
 static void
@@ -1195,8 +1160,8 @@ static void
 write_block (uintmax_t current_offset, size_t n_bytes,
             const char *prev_block, const char *curr_block)
 {
-  static int first = 1;
-  static int prev_pair_equal = 0;
+  static bool first = true;
+  static bool prev_pair_equal = false;
 
 #define EQUAL_BLOCKS(b1, b2) (memcmp ((b1), (b2), bytes_per_block) == 0)
 
@@ -1212,14 +1177,14 @@ write_block (uintmax_t current_offset, s
       else
        {
          printf ("*\n");
-         prev_pair_equal = 1;
+         prev_pair_equal = true;
        }
     }
   else
     {
       size_t i;
 
-      prev_pair_equal = 0;
+      prev_pair_equal = false;
       for (i = 0; i < n_specs; i++)
        {
          if (i == 0)
@@ -1239,7 +1204,7 @@ write_block (uintmax_t current_offset, s
          putchar ('\n');
        }
     }
-  first = 0;
+  first = false;
 }
 
 /* Read a single byte into *C from the concatenation of the input files
@@ -1250,13 +1215,13 @@ write_block (uintmax_t current_offset, s
    and INPUT_FILENAME so they correspond to the next file in the list.
    Then try to read a byte from the newly opened file.  Repeat if
    necessary until EOF is reached for the last file in FILE_LIST, then
-   set *C to EOF and return.  Subsequent calls do likewise.  The return
-   value is nonzero if any errors occured, zero otherwise.  */
+   set *C to EOF and return.  Subsequent calls do likewise.  Return
+   true if successful.  */
 
-static int
+static bool
 read_char (int *c)
 {
-  int err = 0;
+  bool ok = true;
 
   *c = EOF;
 
@@ -1267,12 +1232,12 @@ read_char (int *c)
       if (*c != EOF)
        break;
 
-      err |= check_and_close (errno);
+      ok &= check_and_close (errno);
 
-      err |= open_next_file ();
+      ok &= open_next_file ();
     }
 
-  return err;
+  return ok;
 }
 
 /* Read N bytes into BLOCK from the concatenation of the input files
@@ -1283,23 +1248,23 @@ read_char (int *c)
    the global variables IN_STREAM and INPUT_FILENAME.  Then try to
    read the remaining bytes from the newly opened file.  Repeat if
    necessary until EOF is reached for the last file in FILE_LIST.
-   On subsequent calls, don't modify BLOCK and return zero.  Set
+   On subsequent calls, don't modify BLOCK and return true.  Set
    *N_BYTES_IN_BUFFER to the number of bytes read.  If an error occurs,
    it will be detected through ferror when the stream is about to be
    closed.  If there is an error, give a message but continue reading
-   as usual and return nonzero.  Otherwise return zero.  */
+   as usual and return false.  Otherwise return true.  */
 
-static int
+static bool
 read_block (size_t n, char *block, size_t *n_bytes_in_buffer)
 {
-  int err = 0;
+  bool ok = true;
 
   assert (0 < n && n <= bytes_per_block);
 
   *n_bytes_in_buffer = 0;
 
   if (n == 0)
-    return 0;
+    return true;
 
   while (in_stream != NULL)    /* EOF.  */
     {
@@ -1314,12 +1279,12 @@ read_block (size_t n, char *block, size_
       if (n_read == n_needed)
        break;
 
-      err |= check_and_close (errno);
+      ok &= check_and_close (errno);
 
-      err |= open_next_file ();
+      ok &= open_next_file ();
     }
 
-  return err;
+  return ok;
 }
 
 /* Return the least common multiple of the sizes associated
@@ -1332,21 +1297,21 @@ get_lcm (void)
   int l_c_m = 1;
 
   for (i = 0; i < n_specs; i++)
-    l_c_m = lcm (l_c_m, width_bytes[(int) spec[i].size]);
+    l_c_m = lcm (l_c_m, width_bytes[spec[i].size]);
   return l_c_m;
 }
 
 /* If S is a valid traditional offset specification with an optional
-   leading '+' return nonzero and set *OFFSET to the offset it denotes.  */
+   leading '+' return true and set *OFFSET to the offset it denotes.  */
 
-static int
+static bool
 parse_old_offset (const char *s, uintmax_t *offset)
 {
   int radix;
   enum strtol_error s_err;
 
   if (*s == '\0')
-    return 0;
+    return false;
 
   /* Skip over any leading '+'. */
   if (s[0] == '+')
@@ -1369,9 +1334,9 @@ parse_old_offset (const char *s, uintmax
   if (s_err != LONGINT_OK)
     {
       STRTOL_FAIL_WARN (s, _("old-style offset"), s_err);
-      return 0;
+      return false;
     }
-  return 1;
+  return true;
 }
 
 /* Read a chunk of size BYTES_PER_BLOCK from the input files, write the
@@ -1383,16 +1348,16 @@ parse_old_offset (const char *s, uintmax
    multiple of all format spec sizes.  Write the final block.  Finally,
    write on a line by itself the offset of the byte after the last byte
    read.  Accumulate return values from calls to read_block and
-   check_and_close, and if any was nonzero, return nonzero.
-   Otherwise, return zero.  */
+   check_and_close, and if any was false, return false.
+   Otherwise, return true.  */
 
-static int
+static bool
 dump (void)
 {
   char *block[2];
   uintmax_t current_offset;
-  int idx;
-  int err;
+  bool idx = false;
+  bool ok = true;
   size_t n_bytes_read;
 
   block[0] = xnmalloc (2, bytes_per_block);
@@ -1400,8 +1365,6 @@ dump (void)
 
   current_offset = n_bytes_to_skip;
 
-  idx = 0;
-  err = 0;
   if (limit_bytes_to_format)
     {
       while (1)
@@ -1414,7 +1377,7 @@ dump (void)
            }
          n_needed = MIN (end_offset - current_offset,
                          (uintmax_t) bytes_per_block);
-         err |= read_block (n_needed, block[idx], &n_bytes_read);
+         ok &= read_block (n_needed, block[idx], &n_bytes_read);
          if (n_bytes_read < bytes_per_block)
            break;
          assert (n_bytes_read == bytes_per_block);
@@ -1428,7 +1391,7 @@ dump (void)
     {
       while (1)
        {
-         err |= read_block (bytes_per_block, block[idx], &n_bytes_read);
+         ok &= read_block (bytes_per_block, block[idx], &n_bytes_read);
          if (n_bytes_read < bytes_per_block)
            break;
          assert (n_bytes_read == bytes_per_block);
@@ -1459,29 +1422,27 @@ dump (void)
   format_address (current_offset, '\n');
 
   if (limit_bytes_to_format && current_offset >= end_offset)
-    err |= check_and_close (0);
+    ok &= check_and_close (0);
 
   free (block[0]);
 
-  return err;
+  return ok;
 }
 
 /* STRINGS mode.  Find each "string constant" in the input.
    A string constant is a run of at least `string_min' ASCII
    graphic (or formatting) characters terminated by a null.
    Based on a function written by Richard Stallman for a
-   traditional version of od.  Return nonzero if an error
-   occurs.  Otherwise, return zero.  */
+   traditional version of od.  Return true if successful.  */
 
-static int
+static bool
 dump_strings (void)
 {
   size_t bufsize = MAX (100, string_min);
   char *buf = xmalloc (bufsize);
   uintmax_t address = n_bytes_to_skip;
-  int err;
+  bool ok = true;
 
-  err = 0;
   while (1)
     {
       size_t i;
@@ -1496,12 +1457,12 @@ dump_strings (void)
 
       for (i = 0; i < string_min; i++)
        {
-         err |= read_char (&c);
+         ok &= read_char (&c);
          address++;
          if (c < 0)
            {
              free (buf);
-             return err;
+             return ok;
            }
          if (!ISPRINT (c))
            /* Found a non-printing.  Try again starting with next char.  */
@@ -1517,12 +1478,12 @@ dump_strings (void)
            {
              buf = x2nrealloc (buf, &bufsize, sizeof *buf);
            }
-         err |= read_char (&c);
+         ok &= read_char (&c);
          address++;
          if (c < 0)
            {
              free (buf);
-             return err;
+             return ok;
            }
          if (c == '\0')
            break;              /* It is; print this string.  */
@@ -1580,8 +1541,8 @@ dump_strings (void)
 
   free (buf);
 
-  err |= check_and_close (0);
-  return err;
+  ok &= check_and_close (0);
+  return ok;
 }
 
 int
@@ -1592,9 +1553,8 @@ main (int argc, char **argv)
   size_t i;
   int l_c_m;
   size_t desired_width IF_LINT (= 0);
-  int width_specified = 0;
-  int n_failed_decodes = 0;
-  int err;
+  bool width_specified = false;
+  bool ok = true;
   char const *short_options = (posix2_version () < 200112
                               ? COMMON_SHORT_OPTIONS "s::w::"
                               : COMMON_SHORT_OPTIONS "s:w:");
@@ -1611,8 +1571,6 @@ main (int argc, char **argv)
 
   atexit (close_stdout);
 
-  err = 0;
-
   for (i = 0; i <= MAX_INTEGRAL_TYPE_SIZE; i++)
     integral_type_size[i] = NO_SIZE;
 
@@ -1621,7 +1579,7 @@ main (int argc, char **argv)
   integral_type_size[sizeof (int)] = INT;
   integral_type_size[sizeof (long int)] = LONG;
 #if HAVE_UNSIGNED_LONG_LONG
-  /* If `long' and `long long' have the same size, it's fine
+  /* If `long int' and `long long int' have the same size, it's fine
      to overwrite the entry for `long' with this one.  */
   integral_type_size[sizeof (ulonglong_t)] = LONG_LONG;
 #endif
@@ -1643,7 +1601,7 @@ main (int argc, char **argv)
   format_address = format_address_std;
   address_base = 8;
   address_pad_len = 7;
-  flag_dump_strings = 0;
+  flag_dump_strings = false;
 
   while ((c = getopt_long (argc, argv, short_options, long_options, NULL))
         != -1)
@@ -1694,7 +1652,7 @@ it must be one character from [doxn]"),
          break;
 
        case 'N':
-         limit_bytes_to_format = 1;
+         limit_bytes_to_format = true;
 
          s_err = xstrtoumax (optarg, NULL, 0, &max_bytes_to_format, "bkm");
          if (s_err != LONGINT_OK)
@@ -1717,20 +1675,19 @@ it must be one character from [doxn]"),
 
              string_min = tmp;
            }
-         flag_dump_strings = 1;
+         flag_dump_strings = true;
          break;
 
        case 't':
-         if (decode_format_string (optarg))
-           ++n_failed_decodes;
+         ok &= decode_format_string (optarg);
          break;
 
        case 'v':
-         abbreviate_duplicate_blocks = 0;
+         abbreviate_duplicate_blocks = false;
          break;
 
        case TRADITIONAL_OPTION:
-         traditional = 1;
+         traditional = true;
          break;
 
          /* The next several cases map the traditional format
@@ -1740,10 +1697,7 @@ it must be one character from [doxn]"),
 
 #define CASE_OLD_ARG(old_char,new_string)              \
        case old_char:                                  \
-         {                                             \
-           if (decode_format_string (new_string))      \
-             ++n_failed_decodes;                       \
-         }                                             \
+         ok &= decode_format_string (new_string);      \
          break
 
          CASE_OLD_ARG ('a', "a");
@@ -1767,7 +1721,7 @@ it must be one character from [doxn]"),
 #undef CASE_OLD_ARG
 
        case 'w':
-         width_specified = 1;
+         width_specified = true;
          if (optarg == NULL)
            {
              desired_width = 32;
@@ -1794,7 +1748,7 @@ it must be one character from [doxn]"),
        }
     }
 
-  if (n_failed_decodes > 0)
+  if (!ok)
     exit (EXIT_FAILURE);
 
   if (flag_dump_strings && n_specs > 0)
@@ -1832,7 +1786,7 @@ it must be one character from [doxn]"),
              && parse_old_offset (argv[optind + 1], &o2))
            {
              n_bytes_to_skip = o1;
-             flag_pseudo_start = 1;
+             flag_pseudo_start = true;
              pseudo_start = o2;
              argv += 2;
              n_files -= 2;
@@ -1859,7 +1813,7 @@ it must be one character from [doxn]"),
              && parse_old_offset (argv[optind + 2], &o2))
            {
              n_bytes_to_skip = o1;
-             flag_pseudo_start = 1;
+             flag_pseudo_start = true;
              pseudo_start = o2;
              argv[optind + 2] = argv[optind];
              argv += 2;
@@ -1902,7 +1856,7 @@ it must be one character from [doxn]"),
 
   if (n_specs == 0)
     {
-      if (decode_format_string ("o2"))
+      if (! decode_format_string ("o2"))
        {
          /* This happens on Cray systems that don't have a 2-byte
             integral type.  */
@@ -1929,12 +1883,12 @@ it must be one character from [doxn]"),
     }
 
   /* open the first input file */
-  err |= open_next_file ();
+  ok = open_next_file ();
   if (in_stream == NULL)
     goto cleanup;
 
   /* skip over any unwanted header bytes */
-  err |= skip (n_bytes_to_skip);
+  ok &= skip (n_bytes_to_skip);
   if (in_stream == NULL)
     goto cleanup;
 
@@ -1950,7 +1904,7 @@ it must be one character from [doxn]"),
       else
        {
          error (0, 0, _("warning: invalid width %lu; using %d instead"),
-                (unsigned long) desired_width, l_c_m);
+                (unsigned long int) desired_width, l_c_m);
          bytes_per_block = l_c_m;
        }
     }
@@ -1970,12 +1924,12 @@ it must be one character from [doxn]"),
     }
 #endif
 
-  err |= (flag_dump_strings ? dump_strings () : dump ());
+  ok &= (flag_dump_strings ? dump_strings () : dump ());
 
 cleanup:;
 
   if (have_read_stdin && fclose (stdin) == EOF)
     error (EXIT_FAILURE, errno, _("standard input"));
 
-  exit (err == 0 ? EXIT_SUCCESS : EXIT_FAILURE);
+  exit (ok ? EXIT_SUCCESS : EXIT_FAILURE);
 }




reply via email to

[Prev in Thread] Current Thread [Next in Thread]