emacs-diffs
[Top][All Lists]
Advanced

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

[Emacs-diffs] master 23e64fa 1/2: hexl: handle large files and I/O error


From: Paul Eggert
Subject: [Emacs-diffs] master 23e64fa 1/2: hexl: handle large files and I/O errors
Date: Thu, 23 Feb 2017 12:15:12 -0500 (EST)

branch: master
commit 23e64facf9f74133c6bacedeec56ad782ae69b65
Author: Paul Eggert <address@hidden>
Commit: Paul Eggert <address@hidden>

    hexl: handle large files and I/O errors
    
    * lib-src/hexl.c: Include inttypes.h, for PRIxMAX etc.
    Do not include ctype.h, as the code no longer uses isdigit.
    (DEFAULT_GROUPING, un_flag, iso_flag, group_by): Now local to ‘main’.
    (DEFAULT_BASE, endian): Remove; was not really used.
    (usage): Remove; now done by ‘main’, as that’s simpler.
    (progname): Now static.
    (output_error, hexchar): New functions.
    (main): Use them.  Simplify.  Remove "-oct", "-big-endian", and
    "-little-endian" options, as they did not work and were not used.
    Use SET_BINARY only on stdin, and fopen with "rb" otherwise.
    Use SET_BINARY only once on stdout.
    Do not assume file offsets fit in ‘long’.
    If an I/O error occurs, report it and exit with nonzero status.
---
 lib-src/hexl.c | 230 ++++++++++++++++++++++++---------------------------------
 1 file changed, 95 insertions(+), 135 deletions(-)

diff --git a/lib-src/hexl.c b/lib-src/hexl.c
index 2eef7b3..2c7e8c4 100644
--- a/lib-src/hexl.c
+++ b/lib-src/hexl.c
@@ -21,241 +21,201 @@ along with this program.  If not, see 
<http://www.gnu.org/licenses/>.  */
 
 #include <config.h>
 
+#include <inttypes.h>
 #include <stdio.h>
 #include <stdlib.h>
 #include <string.h>
-#include <ctype.h>
 
 #include <binary-io.h>
 
-#define DEFAULT_GROUPING       0x01
-#define DEFAULT_BASE           16
+static char *progname;
 
-int base = DEFAULT_BASE;
-bool un_flag = false, iso_flag = false, endian = true;
-int group_by = DEFAULT_GROUPING;
-char *progname;
+static _Noreturn void
+output_error (void)
+{
+  fprintf (stderr, "%s: write error\n", progname);
+  exit (EXIT_FAILURE);
+}
 
-_Noreturn void usage (void);
+static int
+hexchar (int c)
+{
+  return c - ('0' <= c && c <= '9' ? '0' : 'a' - 10);
+}
 
 int
 main (int argc, char **argv)
 {
-  register long address;
-  char string[18];
-  FILE *fp;
-
-  progname = *argv++; --argc;
+  int status = EXIT_SUCCESS;
+  int DEFAULT_GROUPING = 0x01;
+  int group_by = DEFAULT_GROUPING;
+  bool un_flag = false, iso_flag = false;
+  progname = *argv++;
 
   /*
    ** -hex             hex dump
-   ** -oct             Octal dump
    ** -group-by-8-bits
    ** -group-by-16-bits
    ** -group-by-32-bits
    ** -group-by-64-bits
    ** -iso             iso character set.
-   ** -big-endian      Big Endian
-   ** -little-endian   Little Endian
    ** -un || -de       from hexl format to binary.
    ** --               End switch list.
    ** <filename>       dump filename
    ** -                (as filename == stdin)
    */
 
-  while (*argv && *argv[0] == '-' && (*argv)[1])
+  for (; *argv && *argv[0] == '-' && (*argv)[1]; argv++)
     {
       /* A switch! */
       if (!strcmp (*argv, "--"))
        {
-         --argc; argv++;
+         argv++;
          break;
        }
       else if (!strcmp (*argv, "-un") || !strcmp (*argv, "-de"))
        {
          un_flag = true;
-         --argc; argv++;
+         SET_BINARY (fileno (stdout));
        }
       else if (!strcmp (*argv, "-hex"))
-       {
-         base = 16;
-         --argc; argv++;
-       }
+       /* Hex is the default and is only base supported.  */;
       else if (!strcmp (*argv, "-iso"))
-       {
-         iso_flag = true;
-         --argc; argv++;
-       }
-      else if (!strcmp (*argv, "-oct"))
-       {
-         base = 8;
-         --argc; argv++;
-       }
-      else if (!strcmp (*argv, "-big-endian"))
-       {
-         endian = true;
-         --argc; argv++;
-       }
-      else if (!strcmp (*argv, "-little-endian"))
-       {
-         endian = false;
-         --argc; argv++;
-       }
+       iso_flag = true;
       else if (!strcmp (*argv, "-group-by-8-bits"))
-       {
-         group_by = 0x00;
-         --argc; argv++;
-       }
+       group_by = 0x00;
       else if (!strcmp (*argv, "-group-by-16-bits"))
-       {
-         group_by = 0x01;
-         --argc; argv++;
-       }
+       group_by = 0x01;
       else if (!strcmp (*argv, "-group-by-32-bits"))
-       {
-         group_by = 0x03;
-         --argc; argv++;
-       }
+       group_by = 0x03;
       else if (!strcmp (*argv, "-group-by-64-bits"))
-       {
-         group_by = 0x07;
-         endian = false;
-         --argc; argv++;
-       }
+       group_by = 0x07;
       else
        {
          fprintf (stderr, "%s: invalid switch: \"%s\".\n", progname,
                   *argv);
-         usage ();
+         fprintf (stderr, "usage: %s [-de] [-iso]\n", progname);
+         return EXIT_FAILURE;
        }
     }
 
+  char const *filename = *argv ? *argv++ : "-";
+
   do
     {
-      if (*argv == NULL)
-       fp = stdin;
+      FILE *fp;
+
+      if (!strcmp (filename, "-"))
+       {
+         fp = stdin;
+         if (!un_flag)
+           SET_BINARY (fileno (stdin));
+       }
       else
        {
-         char *filename = *argv++;
-
-         if (!strcmp (filename, "-"))
-           fp = stdin;
-         else if ((fp = fopen (filename, "r")) == NULL)
+         fp = fopen (filename, un_flag ? "r" : "rb");
+         if (!fp)
            {
              perror (filename);
+             status = EXIT_FAILURE;
              continue;
            }
        }
 
       if (un_flag)
        {
-         SET_BINARY (fileno (stdout));
-
-         for (;;)
+         for (int c; 0 <= (c = getc (fp)); )
            {
-             int i, c = 0, d;
-             char buf[18];
-
-#define hexchar(x) (isdigit (x) ? x - '0' : x - 'a' + 10)
-
-             /* Skip 10 bytes.  */
-             if (fread (buf, 1, 10, fp) != 10)
-               break;
+             /* Skip address at start of line.  */
+             if (c != ' ')
+               continue;
 
-             for (i=0; i < 16; ++i)
+             for (int i = 0; i < 16; i++)
                {
-                 if ((c = getc (fp)) == ' ' || c == EOF)
+                 c = getc (fp);
+                 if (c < 0 || c == ' ')
                    break;
 
-                 d = getc (fp);
-                 c = hexchar (c) * 0x10 + hexchar (d);
-                 putchar (c);
-
-                 if ((i&group_by) == group_by)
-                   getc (fp);
-               }
-
-             if (c == ' ')
-               {
-                 while ((c = getc (fp)) != '\n' && c != EOF)
-                   ;
-
-                 if (c == EOF)
-                   break;
-               }
-             else
-               {
-                 if (i < 16)
+                 int hc = hexchar (c);
+                 c = getc (fp);
+                 if (c < 0)
                    break;
+                 putchar (hc * 0x10 + hexchar (c));
 
-                 /* Skip 18 bytes.  */
-                 if (fread (buf, 1, 18, fp) != 18)
-                   break;
+                 if ((i & group_by) == group_by)
+                   {
+                     c = getc (fp);
+                     if (c < 0)
+                       break;
+                   }
                }
+
+             while (0 <= c && c != '\n')
+               c = getc (fp);
+             if (c < 0)
+               break;
+             if (ferror (stdout))
+               output_error ();
            }
        }
       else
        {
-         SET_BINARY (fileno (fp));
-         address = 0;
+         int c = 0;
+         char string[18];
          string[0] = ' ';
          string[17] = '\0';
-         for (;;)
+         for (uintmax_t address = 0; 0 <= c; address += 0x10)
            {
-             register int i, c = 0;
-
-             for (i=0; i < 16; ++i)
+             int i;
+             for (i = 0; i < 16; i++)
                {
-                 if ((c = getc (fp)) == EOF)
+                 if (0 <= c)
+                   c = getc (fp);
+                 if (c < 0)
                    {
                      if (!i)
                        break;
 
                      fputs ("  ", stdout);
-                     string[i+1] = '\0';
+                     string[i + 1] = '\0';
                    }
                  else
                    {
                      if (!i)
-                       printf ("%08lx: ", address + 0ul);
+                       printf ("%08"PRIxMAX": ", address);
 
-                     if (iso_flag)
-                       string[i+1] =
-                         (c < 0x20 || (c >= 0x7F && c < 0xa0)) ? '.' :c;
-                     else
-                       string[i+1] = (c < 0x20 || c >= 0x7F) ? '.' : c;
+                     string[i + 1]
+                       = (c < 0x20 || (0x7F <= c && (!iso_flag || c < 0xa0))
+                          ? '.' : c);
 
                      printf ("%02x", c + 0u);
                    }
 
-                 if ((i&group_by) == group_by)
+                 if ((i & group_by) == group_by)
                    putchar (' ');
                }
 
              if (i)
                puts (string);
 
-             if (c == EOF)
-               break;
-
-             address += 0x10;
-
+             if (ferror (stdout))
+               output_error ();
            }
        }
 
-      if (fp != stdin)
-       fclose (fp);
+      bool trouble = ferror (fp) != 0;
+      trouble |= fp != stdin && fclose (fp) != 0;
+      if (trouble)
+       {
+         fprintf (stderr, "%s: read error\n", progname);
+         status = EXIT_FAILURE;
+       }
 
-    } while (*argv != NULL);
-  return EXIT_SUCCESS;
-}
+      filename = *argv++;
+    }
+  while (filename);
 
-void
-usage (void)
-{
-  fprintf (stderr, "usage: %s [-de] [-iso]\n", progname);
-  exit (EXIT_FAILURE);
+  if (ferror (stdout) || fclose (stdout) != 0)
+    output_error ();
+  return status;
 }
-
-
-/* hexl.c ends here */



reply via email to

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