2 * Hexadecimal dumper (CP/M style format)
4 * Original version (c) Eric S. Raymond <esr@snark.thyrsus.com>
5 * Heavily modified by Martin Mares <mj@ucw.cz>
7 * Can be freely distributed and used under the terms of the GNU GPL.
20 #define DEFWIDTH 16 /* Default # chars to show per line */
21 #define MAXWIDTH 32 /* Maximum # of bytes per line */
27 static long linesize = DEFWIDTH; /* # of bytes to print per line */
28 static bool cflag = FALSE; /* show printables as ASCII if true */
29 static bool gflag = FALSE; /* suppress mid-page gutter if true */
30 static ucw_off_t start = 0; /* file offset to start dumping at */
31 static ucw_off_t length = 0; /* if nz, how many chars to dump */
33 static void dumpfile(FILE *f)
34 /* dump a single, specified file -- stdin if filename is NULL */
36 int ch = '\0'; /* current character */
37 char ascii[MAXWIDTH+3]; /* printable ascii data */
38 int i = 0; /* counter: # bytes processed */
39 int ai = 0; /* index into ascii[] */
40 ucw_off_t offset = start; /* byte offset of line in file */
41 int hpos = 0; /* horizontal position counter */
42 ucw_off_t fstart = start;
43 ucw_off_t flength = length;
44 char *specials = "\b\f\n\r\t";
45 char *escapes = "bfnrt";
48 if (fstart && ucw_seek(fileno(f), fstart, SEEK_SET) >= 0)
56 if (length && flength-- <= 0)
62 if (i++ % linesize == 0)
64 (void) printf("%04Lx ", (long long) offset);
69 /* output one space for the mid-page gutter */
71 if ((i - 1) % (linesize / 2) == 0)
78 /* dump the indicated representation of a character */
79 ascii[ai] = (isprint (ch) || ch == ' ') ? ch : '.';
81 if (cflag && (isprint(ch) || ch == ' '))
82 (void) printf("%c ", ch);
83 else if (cflag && ch && (cp = strchr(specials, ch)))
84 (void) printf("\\%c ", escapes[cp - specials]);
86 (void) printf("%02x ", ch);
88 /* update counters and things */
93 /* At end-of-line or EOF, show ASCII version of data. */
94 if (i && (ch == EOF || (i % linesize == 0)))
98 while (hpos < linesize * 3 + 7)
105 (void) printf("%s", ascii);
108 if (ch != EOF || (i % linesize != 0))
109 (void) putchar('\n');
110 ai = 0; /* reset counters */
116 static ucw_off_t getoffs(char *cp)
117 /* fetch decimal or hex integer to be used as file start or offset */
120 char *hexdigits = "0123456789abcdefABCDEF";
123 bool foundzero = FALSE;
129 else if (isdigit(*cp))
134 else if (*cp = 'x' || *cp == 'X' || *cp == 'h' || *cp == 'H')
153 value = value * 10 + (*cp - '0');
161 if (strchr(hexdigits, *cp))
162 value = value*16 + (strchr(hexdigits, tolower(*cp))-hexdigits);
170 int main(int argc, char **argv)
172 FILE *infile; /* file pointer input file */
173 int dumpcount = 0; /* count of files dumped so far */
177 for (argv++, argc--; argc > 0; argv++, argc--)
181 if (s == '-' || s == '+')
187 case 'c': cflag = (s == '-'); continue;
188 case 'g': gflag = (s == '-'); continue;
195 if (s == '-' && argc >= 0)
197 if (cp = strchr(*argv, ','))
199 if ((start = getoffs(*argv)) < 0)
201 (void) fputs("hex: start offset no good\n", stderr);
206 if ((length = getoffs(cp)) < 0)
208 (void) fputs("hex: length no good\n", stderr);
225 if ((linesize = getoffs(*argv)) == -1L || linesize > MAXWIDTH)
227 (void) fputs("hex: line width no good\n", stderr);
235 (void) fprintf(stderr, "hex: no such option as %s\n", *argv);
241 fd = ucw_open(*argv, O_RDONLY, 0);
242 if (fd < 0 || !(infile = fdopen(fd, "r")))
244 (void) fprintf(stderr, "hex: cannot open %s: %m\n", *argv);
249 if (dumpcount > 0 || argc > 1)
251 (void) printf("---- <Standard input> ----\n");
253 (void) printf("---- %s ----\n", *argv);
257 (void) fclose(infile);