diff options
-rw-r--r-- | main.c | 206 |
1 files changed, 165 insertions, 41 deletions
@@ -12,6 +12,36 @@ #define ZXDUMP_STRIDE_GROUP 2 #define ZXDUMP_CHARSET_LEN 64 +#define ZXDUMP_FLAGS_NONE 0 +#define ZXDUMP_FLAGS_BASIC (1 << 0) + +#define ZX_CHAR_LOW(c) \ + (c <= ZXDUMP_CHARSET_LEN) + +#define ZX_CHAR_INVERSE_START 0x80 +#define ZX_CHAR_INVERSE_END 0xbf + +#define ZX_CHAR_INVERSE(c) \ + (c >= ZX_CHAR_INVERSE_START && c <= ZX_CHAR_INVERSE_END) + +#define ZX_CHAR_TOKEN_LOW_START 0x40 +#define ZX_CHAR_TOKEN_LOW_END 0x42 + +#define ZX_CHAR_TOKEN_LOW(c) \ + (c >= ZX_CHAR_TOKEN_LOW_START && c <= ZX_CHAR_TOKEN_LOW_END) + +#define ZX_CHAR_TOKEN_HIGH_START 0xc0 +#define ZX_CHAR_TOKEN_HIGH_END 0xff + +#define ZX_CHAR_TOKEN_HIGH(c) \ + (c >= 0xc0) + +#define ZX_BASIC_STATE_LEN 116 + +typedef struct _zx_basic_line { + uint16_t num, len; +} zx_basic_line; + static uint32_t zx_charset[ZXDUMP_CHARSET_LEN] = { 0x0020, 0x2598, 0x259d, 0x2580, 0x2596, 0x258c, 0x259e, 0x259b, 0x2592, '.', '.', '"', 0x00a3, '$', ':', '?', @@ -23,19 +53,20 @@ static uint32_t zx_charset[ZXDUMP_CHARSET_LEN] = { '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); - } +static char *zx_tokens_low[3] = { + "RND", "INKEY$", "PI", +}; - fprintf(stderr, "usage: %s [file]\n", argv[0]); - exit(1); -} +static char *zx_tokens[64] = { + "\"\"", "AT", "TAB", NULL, "CODE", "VAL", "LEN", "SIN", + "COS", "TAN", "ASN", "ACS", "ATN", "LN", "EXP", "INT", + "SQR", "SGN", "ABS", "PEEK", "USR", "STR$", "CHR$", "NOT", + "**", "OR", "AND", "<=", ">=", "<>", "THEN", "TO", + "STEP", "LPRINT", "LLIST", "STOP", "SLOW", "FAST", "NEW", "SCROLL", + "CONT", "DIM", "REM", "FOR", "GOTO", "GOSUB", "INPUT", "LOAD", + "LIST", "LET", "PAUSE", "NEXT", "POKE", "PRINT", "PLOT", "RUN", + "SAVE", "RAND", "IF", "CLS", "UNPLOT", "CLEAR", "RETURN" "COPY", +}; static inline size_t utf8_encode(uint8_t *buf, uint32_t codepoint) { if ((codepoint & 0x007f) == codepoint) { @@ -63,21 +94,33 @@ static inline size_t utf8_encode(uint8_t *buf, uint32_t codepoint) { } } -static inline int zx_putchar(uint8_t c) { +static inline int zx_putchar(uint8_t c, int inverse) { uint8_t sequence[4]; size_t len = utf8_encode(sequence, zx_charset[c]); + if (inverse) { + if (fputs("\033[7m", stdout) < 0) { + goto error_io; + } + } + if (fwrite(sequence, len, 1, stdout) < 1) { goto error_io; } + if (inverse) { + if (fputs("\033[27m", stdout) < 0) { + goto error_io; + } + } + return 0; error_io: return -1; } -static ssize_t dump_line(off_t offset, void *buf, size_t len, int tty) { +static ssize_t hexdump_line(off_t offset, void *buf, size_t len, int tty) { size_t i; if (printf("%08zx: ", offset) < 0) { @@ -96,7 +139,7 @@ static ssize_t dump_line(off_t offset, void *buf, size_t len, int tty) { } } - if (printf(" ") < 0) { + if (fputs(" ", stdout) < 0) { goto error_io; } @@ -104,19 +147,11 @@ static ssize_t dump_line(off_t offset, void *buf, size_t len, int tty) { uint8_t c = ((uint8_t *)buf)[offset+i]; if (c <= 0x3f) { - if (zx_putchar(c) < 0) { + if (zx_putchar(c, 0) < 0) { goto error_io; } } else if (c >= 0xa0 && c <= 0xbf) { - if (tty && printf("\033[7m") < 0) { - goto error_io; - } - - if (zx_putchar(c - 0xa0) < 0) { - goto error_io; - } - - if (tty && printf("\033[27m") < 0) { + if (zx_putchar(c - 0xa0, tty) < 0) { goto error_io; } } else { @@ -136,9 +171,9 @@ error_io: return -1; } -static ssize_t dump_fd(int fd) { +static ssize_t hexdump_fd(int fd) { void *buf; - ssize_t total = 0; + ssize_t total = 0; int tty = isatty(fileno(stdout)); struct stat st; @@ -164,8 +199,8 @@ static ssize_t dump_fd(int fd) { size_t left = len - i, linesz = left < ZXDUMP_STRIDE_LINE? left: ZXDUMP_STRIDE_LINE; - if (dump_line(offset, buf, linesz, tty) < 0) { - goto error_dump_line; + if (hexdump_line(offset, buf, linesz, tty) < 0) { + goto error_hexdump_line; } offset += linesz; @@ -177,7 +212,58 @@ static ssize_t dump_fd(int fd) { return total; -error_dump_line: +error_hexdump_line: +error_read: + free(buf); + +error_malloc: +error_fstat: + return -1; +} + +static inline int zx_print(uint8_t c, int tty) { + if (ZX_CHAR_LOW(c)) { + return zx_putchar(c, 0); + } else if (ZX_CHAR_TOKEN_LOW(c)) { + return fputs(zx_tokens_low[c - ZX_CHAR_TOKEN_LOW_START], stdout); + } else if (ZX_CHAR_INVERSE(c)) { + return zx_putchar(c, tty); + } else if (ZX_CHAR_TOKEN_HIGH(c)) { + return fputs(zx_tokens[c - ZX_CHAR_TOKEN_HIGH_START], stdout); + } +} + +static ssize_t basic_dump_fd(int fd) { + void *buf; + struct stat st; + ssize_t total = 0; + + 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++) { + + } + } + + free(buf); + + return total; + error_read: free(buf); @@ -186,36 +272,74 @@ error_fstat: return -1; } +static void usage(const char *prog, 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 [-b] [file]\n", prog); + exit(1); +} + int main(int argc, char **argv) { - int fd; + int fd, + flags = ZXDUMP_FLAGS_NONE, + argn; + + while (1) { + int c; + + if ((c = getopt(argc, argv, "b")) < 0) { + break; + } - if (argc == 1) { + switch (c) { + case 'b': + flags |= ZXDUMP_FLAGS_BASIC; + break; + + case '?': + default: + usage(argv[0], NULL); + } + } + + argn = argc - optind; + + if (argn == 0) { fd = fileno(stdin); - } else if (argc == 2) { - if ((fd = open(argv[1], O_RDONLY)) < 0) { + } else if (argn == 1) { + if ((fd = open(argv[optind], O_RDONLY)) < 0) { + fprintf(stderr, "%s: %s: %s\n", argv[0], argv[optind], strerror(errno)); + goto error_open; } } else { - usage(argc, argv, "Too many arguments provided"); + usage(argv[0], "Too many arguments provided"); } - if (dump_fd(fd) < 0) { + if (hexdump_fd(fd) < 0) { fprintf(stderr, "%s: %s: %s\n", argv[0], - (argc == 2)? argv[1]: "(stdin)", + (argn == 1)? argv[optind]: "(stdin)", strerror(errno)); - goto error_dump_fd; + goto error_hexdump_fd; } - if (argc == 2) { + if (argn == 1) { close(fd); } return 0; -error_dump_fd: - if (argc == 2) { +error_hexdump_fd: + if (argn == 1) { close(fd); } |