diff options
Diffstat (limited to 'nqdasm.c')
-rw-r--r-- | nqdasm.c | 93 |
1 files changed, 80 insertions, 13 deletions
@@ -1,8 +1,25 @@ +#include <errno.h> #include <stdio.h> #include <string.h> +#include <unistd.h> #include "mnemonics.h" +#define ERROR(prog,...) \ + do { \ + fprintf(stderr, "%s: ", prog); \ + fprintf(stderr, __VA_ARGS__); \ + fprintf(stderr, "\n"); \ + } while (0) + +#define PERROR(prog,str) \ + do { \ + int err = errno; \ + fprintf(stderr, "%s: ", prog); \ + errno = err; \ + perror(str); \ + } while (0) + static const struct mnemonic *match_instruction(unsigned bits) { for (int i = 0; i < MNEM_LAST; i++) { @@ -12,34 +29,84 @@ static const struct mnemonic *match_instruction(unsigned bits) return NULL; } -static void print_operand(unsigned bits, const struct operand *op) +static void print_operand(FILE *out, unsigned bits, const struct operand *op) { switch (op->type) { - case REG: printf( "r%d", 7 & (bits >> op->shift)); break; - case REGPTR: printf("@r%d", 7 & (bits >> op->shift)); break; - case IMM: printf( "%d", (uint8_t)(bits >> op->shift)); break; - case PCOFF: printf( "%d", (int8_t)(bits >> op->shift)); break; + case REG: fprintf(out, "r%d", 7 & (bits >> op->shift)); break; + case REGPTR: fprintf(out, "@r%d", 7 & (bits >> op->shift)); break; + case IMM: fprintf(out, "%d", (uint8_t)(bits >> op->shift)); break; + case PCOFF: fprintf(out, "%d", (int8_t)(bits >> op->shift)); break; } } -int main() +static void usage(const char *progname) +{ + printf("usage: %s [-o output] [input]\n", progname); + printf(" %s -h\n", progname); + printf("\n"); + printf("\t%-16s %s\n", "-h", "display this help text and exit"); + printf("\t%-16s %s\n", "-o output", "write output to 'output' (default=stdout)"); + printf("\t%-16s %s\n", "input", "read input from 'input' (default=stdin)"); +} + +int main(int argc, char **argv) { + const char *outname = NULL; + int error = 0; + + extern int optind; + extern char *optarg; + for (int opt; (opt = getopt(argc, argv, "+ho:")) != -1;) { + switch (opt) { + case 'h': + usage(argv[0]); + return 0; + case 'o': + outname = optarg; + break; + default: + error = 1; + } + } + + if (optind < argc - 1) { + ERROR(argv[0], "Too many input files"); + return 1; + } + if (error) return 1; + + FILE *in = stdin; + FILE *out = stdout; + + if (optind < argc && !(in = fopen(argv[optind], "r"))) { + PERROR(argv[0], "Error opening input file"); + return 1; + } + if (outname && !(out = fopen(outname, "w"))) { + PERROR(argv[0], "Error opening output file"); + fclose(in); + return 1; + } + unsigned bits; - while (scanf(" %x\n", &bits) > 0) { + while (fscanf(in, " %x\n", &bits) > 0) { const struct mnemonic *m = match_instruction(bits); if (!m) { - printf("\t.word 0x%04x\n", bits); + fprintf(out, "\t.word 0x%04x\n", bits); continue; } - printf("\t%s", m->mnem); + fprintf(out, "\t%s", m->mnem); for (int i = 0; i < 3 && m->operands[i].type; i++) { - if (i) printf(", "); - else printf("%*s", 8 - (int)strlen(m->mnem), ""); - print_operand(bits, m->operands + i); + if (i) fprintf(out, ", "); + else fprintf(out, "%*s", 8 - (int)strlen(m->mnem), ""); + print_operand(out, bits, m->operands + i); } - printf("\n"); + fprintf(out, "\n"); } + + fclose(in); + fclose(out); return 0; } |