summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--lex.c21
-rw-r--r--output.c2
-rw-r--r--test/Makefile2
-rw-r--r--test/full-pipeline/001-nop.test1
-rwxr-xr-xtest/full-pipeline/run-full-pipeline.sh75
5 files changed, 94 insertions, 7 deletions
diff --git a/lex.c b/lex.c
index 7294fbb..7384ca4 100644
--- a/lex.c
+++ b/lex.c
@@ -63,6 +63,13 @@ static int add_token(struct token t) {
return 0;
}
+static struct token last_token(void) {
+ if (tokens_count)
+ return tokens[tokens_count - 1];
+ else
+ return (struct token){ .type = TOKEN_EOL };
+}
+
static int lex_comma(struct token *t) {
if (expect(','))
return 1;
@@ -251,11 +258,6 @@ static int lex_misc(struct token *t) {
int i = 0;
int j = 0;
- if (!isalpha(buffer[column])) {
- emit("Error: '%c' cannot start an identifier\n", buffer[column]);
- return 1;
- }
-
for (i = column; isalnum(buffer[i]); i++) {
;
}
@@ -278,6 +280,12 @@ static int lex_misc(struct token *t) {
/* skip over colon, but don't have included it in the name */
if (t->type == TOKEN_LABEL) {
column++;
+ } else {
+ /* non-labels must start with an alpha */
+ if (!isalpha(t->s_val[0])) {
+ emit("Error: '%c' cannot start an identifier\n", t->s_val[0]);
+ return 1;
+ }
}
return 0;
}
@@ -356,7 +364,8 @@ int lex_line(void) {
break;
/* FIXME add support for expressions like `addi $0, $0, (1+2*3) */
default:
- if (isdigit(buffer[column])) {
+ /* allow numerical to start label only when at start of line */
+ if (isdigit(buffer[column]) && last_token().type != TOKEN_EOL) {
ret = lex_num(&tok);
} else {
ret = lex_misc(&tok);
diff --git a/output.c b/output.c
index 2afb5fe..047040a 100644
--- a/output.c
+++ b/output.c
@@ -165,7 +165,7 @@ int output_single(FILE *f, struct label *labels, size_t labels_count, struct ins
}
if (len == 2) {
-//#define RAW
+#define RAW
#ifdef RAW
fputc(0xFF & (i >> 24), f);
fputc(0xFF & (i >> 16), f);
diff --git a/test/Makefile b/test/Makefile
new file mode 100644
index 0000000..c2407c7
--- /dev/null
+++ b/test/Makefile
@@ -0,0 +1,2 @@
+test:
+ ./full-pipeline/run-full-pipeline.sh
diff --git a/test/full-pipeline/001-nop.test b/test/full-pipeline/001-nop.test
new file mode 100644
index 0000000..c27745a
--- /dev/null
+++ b/test/full-pipeline/001-nop.test
@@ -0,0 +1 @@
+nop
diff --git a/test/full-pipeline/run-full-pipeline.sh b/test/full-pipeline/run-full-pipeline.sh
new file mode 100755
index 0000000..34d4ff0
--- /dev/null
+++ b/test/full-pipeline/run-full-pipeline.sh
@@ -0,0 +1,75 @@
+#!/bin/bash -e
+
+#
+# Script for running all of the automated which will go from source to binary,
+# to source to binary, and compare the two binaries.
+# These tests won't find symmetrical errors (e.g. incorrectly translating 'add'
+# into the wrong opcode, and that same opcode back to 'add'), but provide some
+# level of confidence that the disassembler and assembler at least have parity.
+# Checking lower level things is the job of other tests.
+#
+
+fail() {
+ echo -e '[\e[1;31mFAIL\e[0m] '"$1:" "$2"
+}
+
+pass() {
+ echo -e '[\e[0;32mPASS\e[0m] '"$1"
+}
+
+clean() {
+ echo "Removing work dir $WORK"
+ rm -r "$WORK"
+}
+
+trap clean EXIT
+
+check_expected()
+{
+ [ -z "$1" ] && echo WARN: check_expected called with no argument
+ if [ -f "$1.expected" ] ; then
+ if ! diff "$1.expected" "$1.tmp" >/dev/null; then
+ fail "$1 didn't match expected"
+ fi
+ fi
+}
+
+WORK=$(mktemp -d)
+pushd $(dirname "$0") >/dev/null
+export ASM="$PWD/../../assembler"
+export DISASM="$PWD/../../disassembler"
+has_failure=0
+
+for first_stage_asm in *.test ; do
+ first_stage_bin="$WORK/first_stage.bin"
+ second_stage_asm="$WORK/second_stage.asm"
+ second_stage_bin="$WORK/second_stage.bin"
+
+ # Assemble test code
+ if ! "$ASM" "$first_stage_asm" "$first_stage_bin" ; then
+ fail "$first_stage_asm" "first stage assembly failed"
+ continue
+ fi
+
+ # Disassemble test code and re-assemble that disassembly
+ if ! "$DISASM" "$first_stage_bin" > "$second_stage_asm" ; then
+ fail "$first_stage_asm" "first stage disassembly failed"
+ continue
+ fi
+ if ! "$ASM" "$second_stage_asm" "$second_stage_bin" ; then
+ fail "$first_stage_asm" "second stage assembly failed"
+ continue
+ fi
+
+ # first stage bin and second stage identical for test pass
+ if diff "$first_stage_bin" "$second_stage_bin"; then
+ pass "$first_stage_asm"
+ else
+ fail "$first_stage_asm" "binary mismatch"
+ has_failure=1
+ fi
+
+done
+popd >/dev/null
+
+exit "$has_failure"