ref: ea234b61b3258a71793584c729427da8264e9a2f
dir: /hx.c/
#ifdef __unix__
#ifdef __linux__
#define _GNU_SOURCE
#else
#define _DEFAULT_SOURCE
#endif
#define _FILE_OFFSET_BITS 64
#include <fcntl.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#define OREAD O_RDONLY
#define nil NULL
#define exits(s) do { return (s) != nil; } while (0)
typedef size_t u64int;
#else
#include <u.h>
#include <libc.h>
#endif
enum
{
Bufsz = 4*1024*1024,
Linesz = 87,
};
static int section = 0, pipeit = 0;
static unsigned char *buf;
static const char b2h[] = (
"000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f"
"202122232425262728292a2b2c2d2e2f303132333435363738393a3b3c3d3e3f"
"404142434445464748494a4b4c4d4e4f505152535455565758595a5b5c5d5e5f"
"606162636465666768696a6b6c6d6e6f707172737475767778797a7b7c7d7e7f"
"808182838485868788898a8b8c8d8e8f909192939495969798999a9b9c9d9e9f"
"a0a1a2a3a4a5a6a7a8a9aaabacadaeafb0b1b2b3b4b5b6b7b8b9babbbcbdbebf"
"c0c1c2c3c4c5c6c7c8c9cacbcccdcecfd0d1d2d3d4d5d6d7d8d9dadbdcdddedf"
"e0e1e2e3e4e5e6e7e8e9eaebecedeeeff0f1f2f3f4f5f6f7f8f9fafbfcfdfeff"
);
static int
hx(int fd)
{
u64int addr;
long sz, i;
char s[65536], c;
unsigned char line[16];
int wroff, off, eof, lineoff, r;
again:
#ifdef __linux__
readahead(fd, 0, Bufsz);
#endif
lineoff = 0;
off = 0;
eof = 0;
sz = 0;
for (addr = 0; eof == 0;) {
if ((sz = read(fd, buf, Bufsz)) < 1) {
section = 0;
break;
}
if (pipeit > 0)
write(pipeit, buf, sz);
for (i = 0; i < sz; ) {
if (lineoff == 0) {
s[off++] = b2h[((addr>>55) & 0x1fe)];
s[off++] = b2h[((addr>>55) & 0x1fe)+1];
s[off++] = b2h[((addr>>47) & 0x1fe)];
s[off++] = b2h[((addr>>47) & 0x1fe)+1];
s[off++] = b2h[((addr>>39) & 0x1fe)];
s[off++] = b2h[((addr>>39) & 0x1fe)+1];
s[off++] = b2h[((addr>>31) & 0x1fe)];
s[off++] = b2h[((addr>>31) & 0x1fe)+1];
s[off++] = b2h[((addr>>23) & 0x1fe)];
s[off++] = b2h[((addr>>23) & 0x1fe)+1];
s[off++] = b2h[((addr>>15) & 0x1fe)];
s[off++] = b2h[((addr>>15) & 0x1fe)+1];
s[off++] = b2h[((addr>>7) & 0x1fe)];
s[off++] = b2h[((addr>>7) & 0x1fe)+1];
s[off++] = b2h[((addr<<1) & 0x1fe)];
s[off++] = b2h[((addr<<1) & 0x1fe)+1];
s[off++] = ' ';
s[off++] = ' ';
}
for (; i < sz && lineoff < 16; i++, addr++) {
if (lineoff < 16)
line[lineoff++] = buf[i];
s[off++] = b2h[(int)buf[i]*2+0];
s[off++] = b2h[(int)buf[i]*2+1];
s[off++] = ' ';
if (lineoff == 8)
s[off++] = ' ';
}
if (lineoff == 16) {
ascii:
s[off++] = ' ';
s[off++] = '|';
for (lineoff = 0; lineoff < 16; lineoff++) {
c = line[lineoff];
if (c < 0x20 || c > 0x7e)
c = '.';
s[off++] = c;
}
s[off++] = '|';
s[off++] = '\n';
lineoff = 0;
}
if (off >= (int)sizeof(s)-Linesz) {
writes:
for (wroff = 0; wroff < off; wroff += r) {
if ((r = write(pipeit+1, s+wroff, off-wroff)) < 0) {
sz = -1;
break;
}
}
off = 0;
}
}
if (section)
break;
if (sz == 0)
continue;
#ifdef __linux__
readahead(fd, addr, Bufsz);
#endif
sz = 0;
goto writes;
}
if (sz >= 0) {
if (eof == 0 && lineoff > 0 && lineoff < 16) {
eof = 1;
if (lineoff == 8)
off--;
for (; lineoff < 16; lineoff++) {
line[lineoff] = 0;
s[off++] = ' ';
s[off++] = ' ';
s[off++] = ' ';
if (lineoff == 8)
s[off++] = ' ';
}
i = sz = 0;
goto ascii;
}
for (wroff = 0; wroff < off; wroff += r) {
if ((r = write(pipeit+1, s+wroff, off-wroff)) < 0) {
sz = -1;
break;
}
}
}
if (section) {
write(pipeit+1, "\n", 1);
goto again;
}
return sz != 0;
}
#ifdef __unix__
int
#else
void
#endif
main(int argc, char **argv)
{
int i, fd, res, opts;
if ((buf = malloc(Bufsz)) == nil) {
perror("buf");
exits("buf");
}
res = 0;
opts = 0;
for (i = 1; i < argc && res == 0; i++) {
if (argv[i][0] == '-' && argv[i][2] == 0) {
switch (argv[i][1]) {
case 's':
section = 1;
opts++;
break;
case 'p':
pipeit = 1;
opts++;
break;
default:
write(2, "unknown option: -", 17);
write(2, argv[i]+1, 1);
write(2, "\n", 1);
exits("usage");
}
if (opts == argc-1) {
fd = 0;
goto dump;
}
continue;
}
if ((fd = open(argv[i], OREAD)) < 0) {
perror(argv[i]);
res = 1;
} else {
if (argc > 2+opts) {
write(pipeit+1, "hx ", 3);
write(pipeit+1, argv[i], strlen(argv[i]));
write(pipeit+1, "\n", 1);
}
dump:
if ((res = hx(fd)) != 0)
perror(argv[1]);
close(fd);
}
}
memset(buf, 0, Bufsz);
free(buf);
exits(res == 0 ? nil : "error");
}