#include "gbos.h" /* xxd [-c N] [file]: hex dump a file, or stdin. * * Eight bytes per line, not the usual sixteen: offset + 8 hex pairs + the * ASCII column is 38 of the terminal's 40 columns, where 16 would wrap every * line and make the dump unreadable. -c overrides it anyway. * * There is no seek syscall, so this streams from the start - which is also * why there is no -s (skip). -l stops after N bytes, which is how you look at * a program image: /bin/ is a whole 16 KiB ROM bank, and dumping all of * it is 2048 lines (and more than a pipe's temp file can hold). */ #define MAXC 16 /* atou() is 8-bit; -l wants up to 16 KiB */ static unsigned int atou16(const char *s) { unsigned int n = 0; while (*s >= '0' && *s <= '9') { n = n * 10 + (unsigned char)(*s - '0'); s++; } return n; } static char hexd(unsigned char v) { return (char)(v < 10 ? '0' + v : 'a' + (v - 10)); } static void hex2(unsigned char v) { putc(hexd((unsigned char)(v >> 4))); putc(hexd((unsigned char)(v & 15))); } static void hex4(unsigned int v) { hex2((unsigned char)(v >> 8)); hex2((unsigned char)v); } void main(void) { char *argv[8]; unsigned char buf[MAXC]; unsigned char argc = argv_parse(argv, 8); char *cv = optval(argv, argc, 'c'); char *lv = optval(argv, argc, 'l'); unsigned int limit = 0; /* 0 = no limit */ unsigned char cols = 8, fd = NOFD, n = 0, i; unsigned int off = 0; char *fname = 0; int ch; if (cv) { cols = atou(cv); if (cols == 0 || cols > MAXC) cols = 8; } if (lv) limit = atou16(lv); for (i = 0; i < argc; i++) { if (argv[i][0] == '-') continue; if (cv == argv[i] || lv == argv[i]) continue; fname = argv[i]; break; } if (fname) { fd = open(fname, O_READ); if (fd == EISDIR) { puts("xxd: is a directory"); nl(); sexit(2); } if (fd == NOFD) { puts("xxd: no such file"); nl(); sexit(2); } } for (;;) { if (limit && off + n >= limit) ch = -1; /* -l: stop after N bytes */ else if (fd == NOFD) { char c = readc(); ch = (c == EOF) ? -1 : c; } else ch = fgetc(fd); if (ch >= 0) buf[n++] = (unsigned char)ch; if (n == cols || (ch < 0 && n)) { /* full line, or the last one */ hex4(off); puts(": "); for (i = 0; i < cols; i++) { if (i < n) hex2(buf[i]); else { putc(' '); putc(' '); } /* pad so ASCII stays aligned */ putc(' '); } for (i = 0; i < n; i++) putc((buf[i] >= 32 && buf[i] < 127) ? (char)buf[i] : '.'); nl(); off += n; n = 0; } if (ch < 0) break; } if (fd != NOFD) close(fd); }