diff options
-rw-r--r-- | nqdasm.c | 81 |
1 files changed, 71 insertions, 10 deletions
@@ -1,25 +1,34 @@ #include <errno.h> #include <stdio.h> +#include <stdlib.h> #include <string.h> #include <unistd.h> #include "mnemonics.h" -#define ERROR(prog,...) \ +const char *progname; + +#define ERROR(...) \ do { \ - fprintf(stderr, "%s: ", prog); \ + fprintf(stderr, "%s: ", progname); \ fprintf(stderr, __VA_ARGS__); \ fprintf(stderr, "\n"); \ } while (0) -#define PERROR(prog,str) \ +#define PERROR(str) \ do { \ int err = errno; \ - fprintf(stderr, "%s: ", prog); \ + fprintf(stderr, "%s: ", progname); \ errno = err; \ perror(str); \ } while (0) +struct line { + const struct mnemonic *mnem; + uint16_t addr; + uint16_t value; +}; + static const struct mnemonic *match_instruction(unsigned bits) { for (int i = 0; i < MNEM_LAST; i++) { @@ -39,11 +48,59 @@ static void print_operand(FILE *out, unsigned bits, const struct operand *op) } } -static void disassemble(FILE *in, FILE *out) +static int resize_lines(struct line **lines, size_t alloc) +{ + struct line *result = realloc(*lines, alloc * sizeof **lines); + if (result) *lines = result; + else PERROR("Error allocating memory"); + return !result; +} + +static struct line *read_lines(FILE *in, size_t *count) { - unsigned bits; + size_t alloc = 16; + struct line *lines = NULL; + + *count = 0; + if (resize_lines(&lines, alloc)) goto fail; + + unsigned bits, addr = 0; while (fscanf(in, " %x\n", &bits) > 0) { - const struct mnemonic *m = match_instruction(bits); + if (addr > 0xffff) { + ERROR("Input exceeds 16-bit address space"); + goto fail; + } + if (*count >= alloc && resize_lines(&lines, alloc *= 2)) { + goto fail; + } + + lines[*count] = (struct line) { + .mnem = match_instruction(bits), + .value = bits, + .addr = addr, + }; + + addr += 2; + *count += 1; + } + + return lines; + +fail: + free(lines); + return NULL; +} + +static void disassemble(FILE *in, FILE *out) +{ + size_t count; + struct line *lines = read_lines(in, &count); + if (!lines) return; + + for (size_t i = 0; i < count; i++) { + unsigned bits = lines[i].value; + const struct mnemonic *m = lines[i].mnem; + if (!m) { fprintf(out, "\t.word 0x%04x\n", bits); continue; @@ -57,6 +114,8 @@ static void disassemble(FILE *in, FILE *out) } fprintf(out, "\n"); } + + free(lines); } static void usage(const char *progname) @@ -76,6 +135,8 @@ int main(int argc, char **argv) extern int optind; extern char *optarg; + + progname = argv[0]; for (int opt; (opt = getopt(argc, argv, "+ho:")) != -1;) { switch (opt) { case 'h': @@ -90,7 +151,7 @@ int main(int argc, char **argv) } if (optind < argc - 1) { - ERROR(argv[0], "Too many input files"); + ERROR("Too many input files"); return 1; } if (error) return 1; @@ -99,11 +160,11 @@ int main(int argc, char **argv) FILE *out = stdout; if (optind < argc && !(in = fopen(argv[optind], "r"))) { - PERROR(argv[0], "Error opening input file"); + PERROR("Error opening input file"); return 1; } if (outname && !(out = fopen(outname, "w"))) { - PERROR(argv[0], "Error opening output file"); + PERROR("Error opening output file"); fclose(in); return 1; } |