summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorXANTRONIX Development2023-09-11 18:32:47 -0400
committerXANTRONIX Development2023-09-11 18:32:47 -0400
commitdff861680fed0bb60452962b76e90c562f61b872 (patch)
tree32eed12ba301905d57ac10d6267cebc07bfe5049
parent1186261b3be58cdad08d265ef5652e10a69b8140 (diff)
downloadzxdump-dff861680fed0bb60452962b76e90c562f61b872.tar.gz
zxdump-dff861680fed0bb60452962b76e90c562f61b872.tar.bz2
zxdump-dff861680fed0bb60452962b76e90c562f61b872.zip
Begin work on BASIC listings
-rw-r--r--main.c206
1 files changed, 165 insertions, 41 deletions
diff --git a/main.c b/main.c
index 3e33516..d6e2514 100644
--- a/main.c
+++ b/main.c
@@ -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);
}