Parcourir la source

Implement normalize_line(), misc.

master
Ben Kurtovic il y a 9 ans
Parent
révision
8da3663670
1 fichiers modifiés avec 98 ajouts et 3 suppressions
  1. +98
    -3
      src/assembler.c

+ 98
- 3
src/assembler.c Voir le fichier

@@ -23,7 +23,6 @@ struct ASMLine {
const Line *original;
const char *filename;
struct ASMLine *next;
struct ASMLine *include;
};
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)
{
// 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) {
ASMLine *temp = line->next;
free(line->data);
free_asm_lines(line->include);
free(line);
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.

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
// 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;
}



Chargement…
Annuler
Enregistrer