summaryrefslogtreecommitdiff
path: root/nqdasm.c
diff options
context:
space:
mode:
Diffstat (limited to 'nqdasm.c')
-rw-r--r--nqdasm.c93
1 files changed, 80 insertions, 13 deletions
diff --git a/nqdasm.c b/nqdasm.c
index a7020eb..0ecc5b1 100644
--- a/nqdasm.c
+++ b/nqdasm.c
@@ -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;
}