@@ -6,7 +6,7 @@ | |||||
#include <string.h> | #include <string.h> | ||||
#define DIRECTIVE_MARKER '.' | #define DIRECTIVE_MARKER '.' | ||||
#define NUM_DIRECTIVES 15 | |||||
#define NUM_DIRECTIVES 16 | |||||
#define DIR_INCLUDE ".include" | #define DIR_INCLUDE ".include" | ||||
@@ -22,6 +22,7 @@ | |||||
#define DIR_ORIGIN ".org" | #define DIR_ORIGIN ".org" | ||||
#define DIR_BLOCK ".block" | #define DIR_BLOCK ".block" | ||||
#define DIR_BYTE ".byte" | #define DIR_BYTE ".byte" | ||||
#define DIR_SPACE ".space" | |||||
#define DIR_ASCII ".ascii" | #define DIR_ASCII ".ascii" | ||||
#define DIR_ASCIZ ".asciz" | #define DIR_ASCIZ ".asciz" | ||||
#define DIR_ASCIIZ ".asciiz" | #define DIR_ASCIIZ ".asciiz" | ||||
@@ -35,8 +36,9 @@ | |||||
#define IS_LOCAL_DIRECTIVE(line) \ | #define IS_LOCAL_DIRECTIVE(line) \ | ||||
(IS_DIRECTIVE(line, DIR_ORIGIN) || IS_DIRECTIVE(line, DIR_BLOCK) || \ | (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) \ | #define DIRECTIVE_OFFSET(line, d) \ | ||||
(DIRECTIVE_HAS_ARG(line, d) ? strlen(d) : 0) | (DIRECTIVE_HAS_ARG(line, d) ? strlen(d) : 0) | ||||
@@ -147,9 +147,9 @@ bool parse_bytes(uint8_t **result, size_t *length, const char *arg, ssize_t size | |||||
uint8_t *bytes = NULL; | uint8_t *bytes = NULL; | ||||
size_t nbytes = 0; | size_t nbytes = 0; | ||||
while (arg != end) { | |||||
while (arg < end) { | |||||
const char *start = arg; | const char *start = arg; | ||||
while (arg != end && *arg != ' ') | |||||
while (arg != end && *arg != ' ' && *arg != ',') | |||||
arg++; | arg++; | ||||
uint32_t temp; | 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() | OUT_OF_MEMORY() | ||||
bytes[nbytes - 1] = temp; | bytes[nbytes - 1] = temp; | ||||
if (arg++ == end) | |||||
if (arg < end - 1 && *arg == ',' && *(arg + 1) == ' ') | |||||
arg += 2; | |||||
else if (arg++ >= end) | |||||
break; | break; | ||||
} | } | ||||
@@ -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. | Parse data encoded in a line into an ASMData object. | ||||
On success, return NULL and store the instruction in *data_ptr. On failure, | 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)) { | if (IS_DIRECTIVE(line, DIR_BYTE)) { | ||||
directive = DIR_BYTE; | directive = DIR_BYTE; | ||||
parser = parse_bytes; | parser = parse_bytes; | ||||
} else if (IS_DIRECTIVE(line, DIR_SPACE)) { | |||||
directive = DIR_SPACE; | |||||
parser = parse_space; | |||||
} else if (IS_DIRECTIVE(line, DIR_ASCII)) { | } else if (IS_DIRECTIVE(line, DIR_ASCII)) { | ||||
directive = DIR_ASCII; | directive = DIR_ASCII; | ||||
} else if (IS_DIRECTIVE(line, DIR_ASCIZ)) { | } else if (IS_DIRECTIVE(line, DIR_ASCIZ)) { | ||||
@@ -205,6 +233,9 @@ static ErrorInfo* parse_instruction( | |||||
// TODO | // TODO | ||||
DEBUG("parse_instruction(): %.*s", (int) line->length, line->data) | 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); | // return error_info_create(line, ET_PARSER, ED_PARSE_SYNTAX); | ||||
ASMInstruction *inst = malloc(sizeof(ASMInstruction)); | ASMInstruction *inst = malloc(sizeof(ASMInstruction)); | ||||