Browse Source

Fully support labels on the same line as other instructions.

master
Ben Kurtovic 9 years ago
parent
commit
0999915c40
1 changed files with 84 additions and 11 deletions
  1. +84
    -11
      src/assembler/preprocessor.c

+ 84
- 11
src/assembler/preprocessor.c View File

@@ -83,18 +83,76 @@
else FAIL_ON_COND_(true, ED_PP_UNKNOWN)

/*
Preprocess a single source line (source, length) into a normalized ASMLine.
Return whether the given character is a valid label character.
*/
static inline bool is_valid_label_char(char c, bool first)
{
return (c >= 'A' && c <= 'Z') || (c >= 'a' && c <= 'z') ||
(!first && c >= '0' && c <= '9') || c == '_';
}

/*
Preprocess a single source line for labels.

Return the index of first non-whitespace non-label character. *head_ptr is
updated to the first label in sequence, and *tail_ptr to the last. Both
will be set to NULL if the line doesn't contain labels.
*/
static size_t read_labels(
const char *source, size_t length, ASMLine **head_ptr, ASMLine **tail_ptr)
{
size_t start = 0, i, nexti;
while (start < length && (source[start] == ' ' || source[start] == '\t'))
start++;

i = start;
while (i < length && is_valid_label_char(source[i], i == start))
i++;

if (i == start || i == length || source[i] != ':') {
*head_ptr = NULL;
*tail_ptr = NULL;
return 0;
}

ASMLine *line = malloc(sizeof(ASMLine));
if (!line)
OUT_OF_MEMORY()

line->data = malloc(sizeof(char) * (i - start + 1));
if (!line->data)
OUT_OF_MEMORY()

*Only* the data and length fields in the ASMLine object are populated. The
normalization process converts tabs to spaces, lowercases all alphabetical
characters, and removes runs of multiple spaces (outside of string
literals), strips comments, and other things.
strncpy(line->data, source + start, i - start + 1);
line->length = i - start + 1;

nexti = read_labels(source + i + 1, length - i - 1, &line->next, tail_ptr);
*head_ptr = line;
if (!nexti)
*tail_ptr = line;
return i + 1 + nexti;
}

/*
Preprocess a single source line (source, length) into one or more ASMLines.

Only the data, length, and next fields of the ASMLine objects are
populated. The normalization process strips comments, makes various
adjustments outside of string literals (converts tabs to spaces, lowercases
all alphabetical characters, and removes runs of multiple spaces), among
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)
{
ASMLine *head, *tail;
size_t offset = read_labels(source, length, &head, &tail);

source += offset;
length -= offset;

char *data = malloc(sizeof(char) * length);
if (!data)
OUT_OF_MEMORY()
@@ -138,7 +196,7 @@ static ASMLine* normalize_line(const char *source, size_t length)

if (!has_content) {
free(data);
return NULL;
return head;
}

ASMLine *line = malloc(sizeof(ASMLine));
@@ -151,6 +209,12 @@ static ASMLine* normalize_line(const char *source, size_t length)

line->data = data;
line->length = di;
line->next = NULL;

if (head) { // Line has labels, so link the main part up
tail->next = line;
return head;
}
return line;
}

@@ -240,19 +304,28 @@ static ErrorInfo* build_asm_lines(
{
ErrorInfo *ei;
ASMLine dummy = {.next = NULL};
ASMLine *line, *prev = &dummy;
ASMLine *line, *prev = &dummy, *temp;
const Line *orig, *next_orig = source->lines;

while ((orig = next_orig)) {
line = normalize_line(orig->data, orig->length);
line = temp = normalize_line(orig->data, orig->length);
next_orig = orig->next;
if (!line)
continue;

// Populate ASMLine fields not set by normalize_line():
line->original = orig;
line->filename = source->filename;
line->next = NULL;
while (temp) {
temp->original = orig;
temp->filename = source->filename;
temp = temp->next;
}

// If there are multiple ASMLines, all but the last must be labels:
while (line->next) {
prev->next = line;
prev = line;
line = line->next;
}

if (IS_DIRECTIVE(line, DIR_INCLUDE)) {
char *path = read_include_path(line);


Loading…
Cancel
Save