|
@@ -23,7 +23,6 @@ struct ASMLine { |
|
|
const Line *original; |
|
|
const Line *original; |
|
|
const char *filename; |
|
|
const char *filename; |
|
|
struct ASMLine *next; |
|
|
struct ASMLine *next; |
|
|
struct ASMLine *include; |
|
|
|
|
|
}; |
|
|
}; |
|
|
typedef struct ASMLine ASMLine; |
|
|
typedef struct ASMLine ASMLine; |
|
|
|
|
|
|
|
@@ -198,7 +197,7 @@ static bool write_binary_file(const char *path, const uint8_t *data, size_t size |
|
|
void error_info_print(const ErrorInfo *error_info, FILE *file) |
|
|
void error_info_print(const ErrorInfo *error_info, FILE *file) |
|
|
{ |
|
|
{ |
|
|
// TODO |
|
|
// TODO |
|
|
fprintf(file, "Error: Unknown error"); |
|
|
|
|
|
|
|
|
fprintf(file, "Error: Unknown error\n"); |
|
|
} |
|
|
} |
|
|
|
|
|
|
|
|
/* |
|
|
/* |
|
@@ -241,7 +240,6 @@ static void free_asm_lines(ASMLine *line) |
|
|
while (line) { |
|
|
while (line) { |
|
|
ASMLine *temp = line->next; |
|
|
ASMLine *temp = line->next; |
|
|
free(line->data); |
|
|
free(line->data); |
|
|
free_asm_lines(line->include); |
|
|
|
|
|
free(line); |
|
|
free(line); |
|
|
line = temp; |
|
|
line = temp; |
|
|
} |
|
|
} |
|
@@ -295,6 +293,75 @@ static void free_asm_symtable(ASMSymbolTable *symtable) |
|
|
} |
|
|
} |
|
|
|
|
|
|
|
|
/* |
|
|
/* |
|
|
|
|
|
Preprocess a single source line (source, length) into a normalized ASMLine. |
|
|
|
|
|
|
|
|
|
|
|
*Only* the data and length fields in the ASMLine object are populated. The |
|
|
|
|
|
normalization process converts tabs to spaces, removes runs of multiple |
|
|
|
|
|
spaces (outside of string literals), strips comments, and other things. |
|
|
|
|
|
|
|
|
|
|
|
Return NULL if an ASM line was not generated from the source, i.e. if it is |
|
|
|
|
|
blank after being stripped. |
|
|
|
|
|
*/ |
|
|
|
|
|
static ASMLine* normalize_line(const char *source, size_t length) |
|
|
|
|
|
{ |
|
|
|
|
|
char *data = malloc(sizeof(char) * length); |
|
|
|
|
|
if (!data) |
|
|
|
|
|
OUT_OF_MEMORY() |
|
|
|
|
|
|
|
|
|
|
|
size_t si, di, slashes = 0; |
|
|
|
|
|
bool has_content = false, space_pending = false, in_string = false; |
|
|
|
|
|
for (si = di = 0; si < length; si++) { |
|
|
|
|
|
char c = source[si]; |
|
|
|
|
|
|
|
|
|
|
|
if (c == '\\') |
|
|
|
|
|
slashes++; |
|
|
|
|
|
else |
|
|
|
|
|
slashes = 0; |
|
|
|
|
|
|
|
|
|
|
|
if (in_string) { |
|
|
|
|
|
if (c == '"' && (slashes % 2) == 0) |
|
|
|
|
|
in_string = false; |
|
|
|
|
|
|
|
|
|
|
|
data[di++] = c; |
|
|
|
|
|
} else { |
|
|
|
|
|
if (c == ';') |
|
|
|
|
|
break; |
|
|
|
|
|
if (c == '"' && (slashes % 2) == 0) |
|
|
|
|
|
in_string = true; |
|
|
|
|
|
|
|
|
|
|
|
if (c == '\t' || c == ' ') |
|
|
|
|
|
space_pending = true; |
|
|
|
|
|
else { |
|
|
|
|
|
if (space_pending) { |
|
|
|
|
|
if (has_content) |
|
|
|
|
|
data[di++] = ' '; |
|
|
|
|
|
space_pending = false; |
|
|
|
|
|
} |
|
|
|
|
|
has_content = true; |
|
|
|
|
|
data[di++] = c; |
|
|
|
|
|
} |
|
|
|
|
|
} |
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
if (!has_content) { |
|
|
|
|
|
free(data); |
|
|
|
|
|
return NULL; |
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
ASMLine *line = malloc(sizeof(ASMLine)); |
|
|
|
|
|
if (!line) |
|
|
|
|
|
OUT_OF_MEMORY() |
|
|
|
|
|
|
|
|
|
|
|
data = realloc(data, sizeof(char) * di); |
|
|
|
|
|
if (!data) |
|
|
|
|
|
OUT_OF_MEMORY() |
|
|
|
|
|
|
|
|
|
|
|
line->data = data; |
|
|
|
|
|
line->length = di; |
|
|
|
|
|
return line; |
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
/* |
|
|
Preprocess the LineBuffer into ASMLines. Change some state along the way. |
|
|
Preprocess the LineBuffer into ASMLines. Change some state along the way. |
|
|
|
|
|
|
|
|
This function processes include directives, so read_source_file() may be |
|
|
This function processes include directives, so read_source_file() may be |
|
@@ -322,6 +389,34 @@ static ErrorInfo* preprocess(AssemblerState *state, const LineBuffer *source) |
|
|
// if giving reported and actual rom size, check reported is <= actual |
|
|
// if giving reported and actual rom size, check reported is <= actual |
|
|
// ensure no duplicate explicit assignments |
|
|
// ensure no duplicate explicit assignments |
|
|
|
|
|
|
|
|
|
|
|
ASMLine dummy = {.next = NULL}; |
|
|
|
|
|
ASMLine *line, *prev = &dummy; |
|
|
|
|
|
const Line *orig = source->lines; |
|
|
|
|
|
|
|
|
|
|
|
while (orig) { |
|
|
|
|
|
if ((line = normalize_line(orig->data, orig->length))) { |
|
|
|
|
|
line->original = orig; |
|
|
|
|
|
line->filename = source->filename; |
|
|
|
|
|
line->next = NULL; |
|
|
|
|
|
|
|
|
|
|
|
prev->next = line; |
|
|
|
|
|
prev = line; |
|
|
|
|
|
} |
|
|
|
|
|
orig = orig->next; |
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
state->lines = dummy.next; |
|
|
|
|
|
|
|
|
|
|
|
#ifdef DEBUG_MODE |
|
|
|
|
|
DEBUG("Dumping ASMLines:") |
|
|
|
|
|
const ASMLine *temp = state->lines; |
|
|
|
|
|
while (temp) { |
|
|
|
|
|
DEBUG("- %-40.*s [%s:%02zu]", (int) temp->length, temp->data, |
|
|
|
|
|
temp->filename, temp->original->lineno) |
|
|
|
|
|
temp = temp->next; |
|
|
|
|
|
} |
|
|
|
|
|
#endif |
|
|
|
|
|
|
|
|
return NULL; |
|
|
return NULL; |
|
|
} |
|
|
} |
|
|
|
|
|
|
|
|