From 295f6eb70fae100f2b74a98acbea64a6f3d1209f Mon Sep 17 00:00:00 2001 From: Ben Kurtovic Date: Tue, 28 Apr 2015 20:03:38 -0500 Subject: [PATCH] Implement space directive; allow commas in .byte. --- src/assembler/directives.h | 8 +++++--- src/assembler/parse_util.c | 8 +++++--- src/assembler/tokenizer.c | 31 +++++++++++++++++++++++++++++++ 3 files changed, 41 insertions(+), 6 deletions(-) diff --git a/src/assembler/directives.h b/src/assembler/directives.h index 9ade9bb..9e51bd7 100644 --- a/src/assembler/directives.h +++ b/src/assembler/directives.h @@ -6,7 +6,7 @@ #include #define DIRECTIVE_MARKER '.' -#define NUM_DIRECTIVES 15 +#define NUM_DIRECTIVES 16 #define DIR_INCLUDE ".include" @@ -22,6 +22,7 @@ #define DIR_ORIGIN ".org" #define DIR_BLOCK ".block" #define DIR_BYTE ".byte" +#define DIR_SPACE ".space" #define DIR_ASCII ".ascii" #define DIR_ASCIZ ".asciz" #define DIR_ASCIIZ ".asciiz" @@ -35,8 +36,9 @@ #define IS_LOCAL_DIRECTIVE(line) \ (IS_DIRECTIVE(line, DIR_ORIGIN) || IS_DIRECTIVE(line, DIR_BLOCK) || \ - IS_DIRECTIVE(line, DIR_BYTE) || IS_DIRECTIVE(line, DIR_ASCII) || \ - IS_DIRECTIVE(line, DIR_ASCIZ) || IS_DIRECTIVE(line, DIR_ASCIIZ)) + IS_DIRECTIVE(line, DIR_BYTE) || IS_DIRECTIVE(line, DIR_SPACE) || \ + IS_DIRECTIVE(line, DIR_ASCII) || IS_DIRECTIVE(line, DIR_ASCIZ) || \ + IS_DIRECTIVE(line, DIR_ASCIIZ)) #define DIRECTIVE_OFFSET(line, d) \ (DIRECTIVE_HAS_ARG(line, d) ? strlen(d) : 0) diff --git a/src/assembler/parse_util.c b/src/assembler/parse_util.c index 38dbc79..33b0419 100644 --- a/src/assembler/parse_util.c +++ b/src/assembler/parse_util.c @@ -147,9 +147,9 @@ bool parse_bytes(uint8_t **result, size_t *length, const char *arg, ssize_t size uint8_t *bytes = NULL; size_t nbytes = 0; - while (arg != end) { + while (arg < end) { const char *start = arg; - while (arg != end && *arg != ' ') + while (arg != end && *arg != ' ' && *arg != ',') arg++; uint32_t temp; @@ -164,7 +164,9 @@ bool parse_bytes(uint8_t **result, size_t *length, const char *arg, ssize_t size OUT_OF_MEMORY() bytes[nbytes - 1] = temp; - if (arg++ == end) + if (arg < end - 1 && *arg == ',' && *(arg + 1) == ' ') + arg += 2; + else if (arg++ >= end) break; } diff --git a/src/assembler/tokenizer.c b/src/assembler/tokenizer.c index e21995b..1da8552 100644 --- a/src/assembler/tokenizer.c +++ b/src/assembler/tokenizer.c @@ -146,6 +146,31 @@ static ErrorInfo* handle_block_directive( } /* + Parse a .space directive, which fills a region with a single byte. +*/ +static bool parse_space( + uint8_t **result, size_t *length, const char *arg, ssize_t size) +{ + uint8_t *bytes; + size_t nbytes; + if (!parse_bytes(&bytes, &nbytes, arg, size)) + return false; + + if (nbytes < 1 || nbytes > 2) { + free(bytes); + return false; + } + + *length = bytes[0]; + if (!(*result = malloc(sizeof(uint8_t) * (*length)))) + OUT_OF_MEMORY() + + memset(*result, nbytes == 2 ? bytes[1] : 0, *length); + free(bytes); + return true; +} + +/* Parse data encoded in a line into an ASMData object. On success, return NULL and store the instruction in *data_ptr. On failure, @@ -160,6 +185,9 @@ static ErrorInfo* parse_data( if (IS_DIRECTIVE(line, DIR_BYTE)) { directive = DIR_BYTE; parser = parse_bytes; + } else if (IS_DIRECTIVE(line, DIR_SPACE)) { + directive = DIR_SPACE; + parser = parse_space; } else if (IS_DIRECTIVE(line, DIR_ASCII)) { directive = DIR_ASCII; } else if (IS_DIRECTIVE(line, DIR_ASCIZ)) { @@ -205,6 +233,9 @@ static ErrorInfo* parse_instruction( // TODO DEBUG("parse_instruction(): %.*s", (int) line->length, line->data) + // SYNTAX NOTES: + // see http://clrhome.org/table/ and http://www.z80.info/z80undoc.htm + // return error_info_create(line, ET_PARSER, ED_PARSE_SYNTAX); ASMInstruction *inst = malloc(sizeof(ASMInstruction));