]> thyrsus.com Git - hexdump.git/commitdiff
Initial revision
authorEric S. Raymond <esr@thyrsus.com>
Thu, 7 Dec 1995 02:59:26 +0000 (02:59 +0000)
committerEric S. Raymond <esr@thyrsus.com>
Thu, 7 Dec 1995 02:59:26 +0000 (02:59 +0000)
hexdump.c [new file with mode: 0644]

diff --git a/hexdump.c b/hexdump.c
new file mode 100644 (file)
index 0000000..6e529a8
--- /dev/null
+++ b/hexdump.c
@@ -0,0 +1,282 @@
+/* hex.c -- generate CP/M style hex dumps */
+
+#include <stdio.h>
+#include <ctype.h>
+
+extern char *strchr();
+
+#define DEFWIDTH 16            /* Default # chars to show per line */
+#define MAXWIDTH 32            /* Maximum # of bytes per line  */
+
+typedef int bool;
+#define TRUE   1
+#define FALSE  0
+
+static long    linesize = DEFWIDTH;    /* # of bytes to print per line */
+static bool    eflag = FALSE;          /* display ebcdic if true */
+static bool    cflag = FALSE;          /* show printables as ASCII if true */
+static bool    gflag = FALSE;          /* suppress mid-page gutter if true */
+static long    start = 0L;             /* file offset to start dumping at */
+static long    length = 0L;            /* if nz, how many chars to dump */
+
+static char ebcdic[] =
+{
+/*        0   1   2   3   4   5   6   7   8   9   A   B   C   D   E   F  */
+/* 40 */ ' ','.','.','.','.','.','.','.','.','.','[','.','<','(','+','!',
+/* 50 */ '&','.','.','.','.','.','.','.','.','.',']','$','*',')',';','^',
+/* 60 */ '-','/','.','.','.','.','.','.','.','.','|',',','%','_','>','?',
+/* 70 */ '.','.','.','.','.','.','.','.','.','`',':','#','@','\'','=','"',
+/* 80 */ '.','a','b','c','d','e','f','g','h','i','.','.','.','.','.','.',
+/* 90 */ '.','j','k','l','m','n','o','p','q','r','.','.','.','.','.','.',
+/* A0 */ '.','~','s','t','u','v','w','x','y','z','.','.','.','.','.','.',
+/* B0 */ '.','.','.','.','.','.','.','.','.','.','.','.','.','.','.','.',
+/* C0 */ '{','A','B','C','D','E','F','G','H','I','.','.','.','.','.','.',
+/* D0 */ '}','J','K','L','M','N','O','P','Q','R','.','.','.','.','.','.',
+/* E0 */ '\\','.','S','T','U','V','W','X','Y','Z','.','.','.','.','.','.',
+/* F0 */ '0','1','2','3','4','5','6','7','8','9','.','.','.','.','.','.',
+};
+
+static void dumpfile(f)
+/* dump a single, specified file -- stdin if filename is NULL */
+FILE   *f;
+{
+    int     ch = '\0';         /* current character            */
+    char    ascii[MAXWIDTH+3]; /* printable ascii data         */
+    int     i = 0;             /* counter: # bytes processed   */
+    int     ai = 0;            /* index into ascii[]           */
+    int     offset = 0;                /* byte offset of line in file  */
+    int     hpos;              /* horizontal position counter  */
+    long    fstart = start;
+    long    flength = length;
+    char    *specials = "\b\f\n\r\t";
+    char    *escapes = "bfnrt";
+    char    *cp;
+
+    do {
+       ch = getc(f);
+
+       if (ch != EOF)
+       {
+           if (start && fstart-- > 0)
+               continue;
+
+           if (length && flength-- <= 0)
+               ch = EOF;
+       }
+
+       if (ch != EOF)
+       {
+           if (i++ % linesize == 0)
+           {
+               (void) printf("%04x ", offset);
+               offset += linesize;
+               hpos = 5;
+           }
+
+           /* output one space for the mid-page gutter */
+           if (!gflag)
+               if ((i - 1) % (linesize / 2) == 0)
+               {
+                   (void) putchar(' ');
+                   hpos++;
+                   ascii[ai++] = ' ';
+               }
+
+           /* dump the indicated representation of a character */
+           if (eflag)          /* we're dumping EBCDIC (blecch!) */
+           {
+               ascii[ai] = (ch >= 0x40) ? ebcdic[ch - 0x40] : '.';
+
+               if (cflag && (ascii[ai] != '.' || ch == ebcdic['.']))
+                   (void) printf("%c  ", ascii[ai]);
+               else if (cflag && ch && (cp = strchr(specials, ch)))
+                   (void) printf("\\%c ", escapes[cp - specials]);
+               else
+                   (void) printf("%02x ", ch);
+           }
+           else                /* we're dumping ASCII */
+           {
+               ascii[ai] = (isprint (ch) || ch == ' ') ? ch : '.';
+
+               if (cflag && (isprint(ch) || ch == ' '))
+                   (void) printf("%c  ", ch);
+               else if (cflag && ch && (cp = strchr(specials, ch)))
+                   (void) printf("\\%c ", escapes[cp - specials]);
+               else
+                   (void) printf("%02x ", ch);
+           }
+
+           /* update counters and things */
+           ai++;
+           hpos += 3;
+       }
+
+       /* At end-of-line or EOF, show ASCII or EBCDIC version of data. */
+       if (i && (ch == EOF || (i % linesize == 0)))
+       {
+           if (!cflag)
+           {
+               while (hpos < linesize * 3 + 7)
+               {
+                   hpos++;
+                   (void) putchar(' ');
+               }
+
+               ascii[ai] = '\0';
+               (void) printf("%s", ascii);
+           }
+
+           if (ch != EOF || (i % linesize != 0))
+               (void) putchar('\n');
+           ai = 0;             /* reset counters */
+       }
+    } while
+       (ch != EOF);
+}
+
+static long getoffs(cp)
+/* fetch decimal or hex integer to be used as file start or offset */
+char *cp;
+{
+    bool foundzero = FALSE;
+    long value = 0;
+    int base = 0;
+    char *hexdigits = "0123456789abcdefABCDEF";
+
+    for (; *cp; cp++)
+       if (*cp == '0')
+           foundzero = TRUE;
+       else if (isdigit(*cp))
+       {
+           base = 10;
+           break;
+       }
+        else if (*cp = 'x' || *cp == 'X' || *cp == 'h' || *cp == 'H')
+       {
+           base = 16;
+           cp++;
+           break;
+       }
+        else
+           return(-1L);
+
+    if (base == 0)
+       if (foundzero)
+           base = 10;
+        else
+           return(-1L);
+
+    if (base == 10)
+    {
+       for (; *cp; cp++)
+           if (isdigit(*cp))
+               value = value * 10 + (*cp - '0');
+           else
+               return(-1L);
+    }
+    else
+    {
+       for (; *cp; cp++)
+           if (strchr(hexdigits, *cp))
+               value = value*16 + (strchr(hexdigits, tolower(*cp))-hexdigits);
+           else
+               return(-1L);
+    }
+
+    return(value);
+}
+
+main(argc, argv)
+int argc;
+char *argv[];
+{
+    FILE    *infile;       /* file pointer input file */
+    int            dumpcount = 0;  /* count of files dumped so far */
+    char    *cp;
+
+    for (argv++, argc--; argc > 0; argv++, argc--)
+    {
+       char s = **argv;
+
+       if (s == '-' || s == '+')
+       {
+           int c = *++*argv;
+
+           switch (c)
+           {
+           case 'e': eflag = (s == '-'); continue;
+           case 'c': cflag = (s == '-'); continue;
+           case 'g': gflag = (s == '-'); continue;
+
+           case 's':
+               if ((*argv)[1])
+                   (*argv)++;
+               else
+                   argc--, argv++;
+               if (s == '-' && argc >= 0)
+               {
+                   if (cp = strchr(*argv, ','))
+                       *cp++ = '\0';
+                   if ((start = getoffs(*argv)) == -1L)
+                   {
+                       (void) fputs("hex: start offset no good\n", stderr);
+                       exit(0);
+                   }
+
+                   if (cp)
+                       if ((length = getoffs(cp)) == -1L)
+                       {
+                           (void) fputs("hex: length no good\n", stderr);
+                           exit(0);
+                       }
+               }
+               else
+                   start = length = 0L;
+               continue;
+
+           case '\0':
+               infile = stdin;
+               break;
+
+           case 'w':
+               if ((*argv)[1])
+                   (*argv)++;
+               else
+                   argc--, argv++;
+               if ((linesize = getoffs(*argv)) == -1L || linesize > MAXWIDTH)
+               {
+                   (void) fputs("hex: line width no good\n", stderr);
+                   exit(0);
+               }
+               if (linesize % 2)
+                   gflag = TRUE;
+               continue;
+
+           default:
+               (void) fprintf(stderr, "hex: no such option as %s\n", *argv);
+               exit(0);
+           }
+       }
+       else if ((infile = fopen(*argv, "r")) == NULL)
+       {
+           (void) fprintf(stderr, "hex: cannot open %s\n", *argv);
+           exit(1);
+       }
+
+       if (dumpcount > 0 || argc > 1)
+           if (infile == stdin)
+               (void) printf("---- <Standard input> ----\n");
+           else
+               (void) printf("---- %s ----\n", *argv);
+       dumpfile(infile);
+       dumpcount++;
+       if (infile != stdin)
+           (void) fclose(infile);
+    }
+
+    if (dumpcount == 0)
+       dumpfile(stdin);
+    return(0);
+}
+
+/* hex.c ends here */