From 8af8474319308dd0053e20079fd78b5661279f7d Mon Sep 17 00:00:00 2001
From: Bobby Bingham <koorogi@koorogi.info>
Date: Sun, 15 Jan 2017 14:11:56 -0600
Subject: nqdasm: read entire file into memory before processing

---
 nqdasm.c | 81 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++--------
 1 file changed, 71 insertions(+), 10 deletions(-)

(limited to 'nqdasm.c')

diff --git a/nqdasm.c b/nqdasm.c
index 3245570..86f8560 100644
--- a/nqdasm.c
+++ b/nqdasm.c
@@ -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;
 	}
-- 
cgit v1.2.3