From: Eric S. Raymond Date: Thu, 7 Dec 1995 02:59:26 +0000 (+0000) Subject: Initial revision X-Git-Tag: 1.1~4 X-Git-Url: http://thyrsus.com/gitweb/?a=commitdiff_plain;h=f73489cc35bc1e05c29d305aea9ccdd693c96c7a;p=hexdump.git Initial revision --- diff --git a/hexdump.c b/hexdump.c new file mode 100644 index 0000000..6e529a8 --- /dev/null +++ b/hexdump.c @@ -0,0 +1,282 @@ +/* hex.c -- generate CP/M style hex dumps */ + +#include +#include + +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("---- ----\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 */