110 lines
2.2 KiB
C
110 lines
2.2 KiB
C
|
#include <stdio.h>
|
||
|
#include <stdlib.h>
|
||
|
#include <stdint.h>
|
||
|
#include <unistd.h>
|
||
|
#include <sys/stat.h>
|
||
|
|
||
|
#include <zx/charset.h>
|
||
|
#include <zx/hexdump.h>
|
||
|
|
||
|
static ssize_t hexdump_line(off_t offset, void *buf, size_t len, int tty, FILE *stream) {
|
||
|
size_t i;
|
||
|
|
||
|
if (printf("%08zx: ", offset) < 0) {
|
||
|
goto error_io;
|
||
|
}
|
||
|
|
||
|
for (i=0; i<len; i++) {
|
||
|
if (i > 0 && (i % ZX81_HEXDUMP_STRIDE_GROUP) == 0) {
|
||
|
if (fputc(' ', stream) < 0) {
|
||
|
goto error_io;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
if (fprintf(stream, "%02x", ((uint8_t *)buf)[offset+i]) < 0) {
|
||
|
goto error_io;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
if (fputs(" ", stream) < 0) {
|
||
|
goto error_io;
|
||
|
}
|
||
|
|
||
|
for (i=0; i<len; i++) {
|
||
|
uint8_t c = ((uint8_t *)buf)[offset+i];
|
||
|
|
||
|
if (c <= 0x3f) {
|
||
|
if (zx81_fputc(c, 0, stream) < 0) {
|
||
|
goto error_io;
|
||
|
}
|
||
|
} else if (c >= 0xa0 && c <= 0xbf) {
|
||
|
if (zx81_fputc(c - 0xa0, tty, stream) < 0) {
|
||
|
goto error_io;
|
||
|
}
|
||
|
} else {
|
||
|
if (fputc('.', stream) < 0) {
|
||
|
goto error_io;
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
|
||
|
if (fputc('\n', stream) < 0) {
|
||
|
goto error_io;
|
||
|
}
|
||
|
|
||
|
return fflush(stream);
|
||
|
|
||
|
error_io:
|
||
|
return -1;
|
||
|
}
|
||
|
|
||
|
ssize_t zx81_hexdump(int fd, FILE *stream) {
|
||
|
void *buf;
|
||
|
ssize_t total = 0;
|
||
|
int tty = isatty(fileno(stdout));
|
||
|
struct stat st;
|
||
|
|
||
|
if (fstat(fd, &st) < 0) {
|
||
|
goto error_fstat;
|
||
|
}
|
||
|
|
||
|
if ((buf = malloc(st.st_blksize)) == NULL) {
|
||
|
goto error_malloc;
|
||
|
}
|
||
|
|
||
|
while (1) {
|
||
|
ssize_t len, i;
|
||
|
off_t offset = 0;
|
||
|
|
||
|
if ((len = read(fd, buf, st.st_blksize)) < 0) {
|
||
|
goto error_read;
|
||
|
} else if (len == 0) {
|
||
|
break;
|
||
|
}
|
||
|
|
||
|
for (i=0; i<len; i+=ZX81_HEXDUMP_STRIDE_LINE) {
|
||
|
size_t left = len - i,
|
||
|
linesz = left < ZX81_HEXDUMP_STRIDE_LINE? left: ZX81_HEXDUMP_STRIDE_LINE;
|
||
|
|
||
|
if (hexdump_line(offset, buf, linesz, tty, stream) < 0) {
|
||
|
goto error_hexdump_line;
|
||
|
}
|
||
|
|
||
|
offset += linesz;
|
||
|
total += linesz;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
free(buf);
|
||
|
|
||
|
return total;
|
||
|
|
||
|
error_hexdump_line:
|
||
|
error_read:
|
||
|
free(buf);
|
||
|
|
||
|
error_malloc:
|
||
|
error_fstat:
|
||
|
return -1;
|
||
|
}
|