Initial commit

This commit is contained in:
XANTRONIX Development 2023-09-10 22:31:41 -04:00
commit 788e4546de

189
main.c Normal file
View file

@ -0,0 +1,189 @@
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <stdarg.h>
#include <inttypes.h>
#include <fcntl.h>
#include <unistd.h>
#include <sys/stat.h>
#include <errno.h>
#define ZXDUMP_STRIDE_LINE 16
#define ZXDUMP_STRIDE_GROUP 2
#define ZXDUMP_CHARSET_LEN 64
static uint16_t charset[ZXDUMP_CHARSET_LEN] = {
0x0020, 0x2598, 0x259d, 0x2580, 0x2596, 0x258c, 0x259e, 0x259b,
0x2592, '.', '.', '"', 0x00a3, '$', ':', '?',
'(', ')', '>', '<', '=', '+', '-', '*',
'/', ';', ',', '.', '0', '1', '2', '3',
'4', '5', '6', '7', '8', '9', 'A', 'B',
'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J',
'K', 'L', 'M', 'N', 'O', 'P', 'Q', 'R',
'S', 'T', 'U', 'V', 'W', 'X', 'Y', 'Z',
};
static void usage(int argc, char **argv, char *message, ...) {
if (message != NULL) {
va_list args;
va_start(args, message);
vfprintf(stderr, message, args);
fputc('\n', stderr);
va_end(args);
}
fprintf(stderr, "usage: %s file\n", argv[0]);
exit(1);
}
static ssize_t dump_line(off_t offset, void *buf, size_t len) {
size_t i;
if (printf("%08zx: ", offset) < 0) {
goto error_io;
}
for (i=0; i<ZXDUMP_STRIDE_LINE; i++) {
if (i > 0 && (i % ZXDUMP_STRIDE_GROUP) == 0) {
if (putchar(' ') < 0) {
goto error_io;
}
}
if (i < len) {
if (printf("%02x", ((uint8_t *)buf)[offset+i]) < 0) {
goto error_io;
}
} else {
if (printf(" ") < 0) {
goto error_io;
}
}
}
if (printf(" ") < 0) {
goto error_io;
}
for (i=0; i<ZXDUMP_STRIDE_LINE; i++) {
uint8_t c = ((uint8_t *)buf)[offset+i];
if (c <= ZXDUMP_CHARSET_LEN) {
uint16_t printable = charset[c];
/* XXX: Implement support for inverse colours */
if (printable & 0xf800) {
uint8_t sequence[2] = {
0xc0 | ((printable & 0x1f00) >> 8),
0x80 | (printable & 0x003f)
};
if (fwrite(sequence, 2, 1, stdout) < 1) {
goto error_io;
}
} else {
if (putchar((uint8_t)(printable & 0x00ff)) < 0) {
goto error_io;
}
}
} else {
if (putchar('.') < 0) {
goto error_io;
}
}
}
if (putchar('\n') < 0) {
goto error_io;
}
return fflush(stdout);
error_io:
return -1;
}
static ssize_t dump_fd(int fd) {
void *buf;
ssize_t offset = 0;
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;
if ((len = read(fd, buf, st.st_blksize)) < 0) {
goto error_read;
} else if (len == 0) {
break;
}
for (i=0; i<len; i+=ZXDUMP_STRIDE_LINE) {
size_t left = len - i,
linesz = left < ZXDUMP_STRIDE_LINE? left: ZXDUMP_STRIDE_LINE;
if (dump_line(offset, buf, linesz) < 0) {
goto error_dump_line;
}
offset += linesz;
}
}
free(buf);
return offset;
error_dump_line:
error_read:
free(buf);
error_malloc:
error_fstat:
return -1;
}
int main(int argc, char **argv) {
int fd;
if (argc == 1) {
fd = fileno(stdin);
} else if (argc == 2) {
if ((fd = open(argv[1], O_RDONLY)) < 0) {
goto error_open;
}
} else {
usage(argc, argv, "Too many arguments provided");
}
if (dump_fd(fd) < 0) {
fprintf(stderr, "%s: %s: %s\n",
argv[0],
(argc == 2)? argv[1]: "(stdin)",
strerror(errno));
goto error_dump_fd;
}
if (argc == 2) {
close(fd);
}
return 0;
error_dump_fd:
if (argc == 2) {
close(fd);
}
error_open:
return 1;
}