Browse Source

Handle infinite recursion in include directives.

master
Ben Kurtovic 9 years ago
parent
commit
5cf943fd7e
2 changed files with 44 additions and 17 deletions
  1. +7
    -7
      src/asm_errors.h
  2. +37
    -10
      src/assembler.c

+ 7
- 7
src/asm_errors.h View File

@@ -6,23 +6,23 @@
/* Enums */

typedef enum {
ET_SYNTAX,
ET_FILEIO
ET_INCLUDE
} ASMErrorType;

typedef enum {
ED_INCLUDE_BAD_ARG,
ED_BAD_ARG,
ED_RECURSION,
ED_FILE_READ_ERR
} ASMErrorDesc;

/* Strings */

static const char *asm_error_types[] = {
"invalid syntax",
"file I/O"
"include directive"
};

static const char *asm_error_descs[] = {
"bad argument passed to include directive",
"couldn't read from file"
"missing or invalid argument",
"infinite recursion detected",
"couldn't read included file"
};

+ 37
- 10
src/assembler.c View File

@@ -515,6 +515,7 @@ char* read_include_path(const ASMLine *line)
if (!dup)
OUT_OF_MEMORY()

// TODO: should normalize filenames in some way to prevent accidental dupes
snprintf(path, maxlen, "%s/%.*s", dirname(dup), (int) (i - start),
line->data + start);
free(dup);
@@ -526,6 +527,23 @@ char* read_include_path(const ASMLine *line)
}

/*
Return whether the given path has already been loaded.
*/
static bool path_has_been_loaded(
const char *path, const LineBuffer *root, const ASMInclude *include)
{
if (!strcmp(path, root->filename))
return true;

while (include) {
if (!strcmp(path, include->lines->filename))
return true;
include = include->next;
}
return false;
}

/*
Build a LineBuffer into a ASMLines, normalizing them along the way.

This function operates recursively to handle includes, but handles no other
@@ -537,8 +555,8 @@ char* read_include_path(const ASMLine *line)
*includes may be updated in either case.
*/
static ErrorInfo* build_asm_lines(
const LineBuffer *source, ASMLine **head, ASMLine **tail,
ASMInclude **includes)
const LineBuffer *root, const LineBuffer *source, ASMLine **head,
ASMLine **tail, ASMInclude **includes)
{
ASMLine dummy = {.next = NULL};
ASMLine *line, *prev = &dummy;
@@ -559,17 +577,24 @@ static ErrorInfo* build_asm_lines(
ErrorInfo *ei;
char *path = read_include_path(line);
if (!path) {
ei = create_error(line, ET_SYNTAX, ED_INCLUDE_BAD_ARG);
ei = create_error(line, ET_INCLUDE, ED_BAD_ARG);
free_asm_lines(line);
free_asm_lines(dummy.next);
return ei;
}

if (path_has_been_loaded(path, root, *includes)) {
ei = create_error(line, ET_INCLUDE, ED_RECURSION);
free_asm_lines(line);
free_asm_lines(dummy.next);
free(path);
return ei;
}

// TODO: handle recursive includes properly
LineBuffer *incbuffer = read_source_file(path, false);
free(path);
if (!incbuffer) {
ei = create_error(line, ET_FILEIO, ED_FILE_READ_ERR);
ei = create_error(line, ET_INCLUDE, ED_FILE_READ_ERR);
free_asm_lines(line);
free_asm_lines(dummy.next);
return ei;
@@ -583,16 +608,17 @@ static ErrorInfo* build_asm_lines(
include->next = *includes;
*includes = include;

ASMLine *ihead, *itail;
if ((ei = build_asm_lines(incbuffer, &ihead, &itail, includes))) {
ASMLine *inchead, *inctail;
if ((ei = build_asm_lines(root, incbuffer, &inchead, &inctail,
includes))) {
append_to_error(ei, line);
free_asm_lines(line);
free_asm_lines(dummy.next);
return ei;
}

prev->next = ihead;
prev = itail;
prev->next = inchead;
prev = inctail;
free_asm_lines(line); // Destroy only the .include line
}
else {
@@ -634,7 +660,8 @@ static ErrorInfo* preprocess(AssemblerState *state, const LineBuffer *source)

ErrorInfo* ei;

if ((ei = build_asm_lines(source, &state->lines, NULL, &state->includes)))
if ((ei = build_asm_lines(source, source, &state->lines, NULL,
&state->includes)))
return ei;

// TODO: iterate here for all global preprocessor directives


Loading…
Cancel
Save