| @@ -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)); | ||||