Browse Source

Add ASM error strings; refactor somewhat.

master
Ben Kurtovic 9 years ago
parent
commit
2879ac1350
3 changed files with 92 additions and 63 deletions
  1. +28
    -0
      src/asm_errors.h
  2. +63
    -38
      src/assembler.c
  3. +1
    -25
      src/assembler.h

+ 28
- 0
src/asm_errors.h View File

@@ -0,0 +1,28 @@
/* Copyright (C) 2014-2015 Ben Kurtovic <ben.kurtovic@gmail.com>
Released under the terms of the MIT License. See LICENSE for details. */

#pragma once

/* Enums */

typedef enum {
ET_SYNTAX,
ET_FILEIO
} ASMErrorType;

typedef enum {
ED_INCLUDE_BAD_ARG,
ED_FILE_READ_ERR
} ASMErrorDesc;

/* Strings */

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

static const char *asm_error_descs[] = {
"bad argument passed to include directive",
"couldn't read from file"
};

+ 63
- 38
src/assembler.c View File

@@ -9,6 +9,7 @@
#include <sys/stat.h>

#include "assembler.h"
#include "asm_errors.h"
#include "logging.h"
#include "util.h"

@@ -26,6 +27,9 @@
#define DIRECTIVE_OFFSET(line, d) \
(line->length > strlen(DIRECTIVE(d)) ? strlen(DIRECTIVE(d)) : 0)

#define ERROR_TYPE(err_info) (asm_error_types[err_info->type])
#define ERROR_DESC(err_info) (asm_error_descs[err_info->desc])

#define SYMBOL_TABLE_BUCKETS 128

/* Internal structs */
@@ -85,6 +89,21 @@ typedef struct {
ASMSymbolTable *symtable;
} AssemblerState;

struct ASMErrorLine {
char *data;
size_t length;
size_t lineno;
char *filename;
struct ASMErrorLine *next;
};
typedef struct ASMErrorLine ASMErrorLine;

struct ErrorInfo {
ASMErrorType type;
ASMErrorDesc desc;
ASMErrorLine *line;
};

/*
Deallocate a LineBuffer previously created with read_source_file().
*/
@@ -107,27 +126,30 @@ static void free_line_buffer(LineBuffer *buffer)

Return the buffer if reading was successful; it must be freed with
free_line_buffer() when done. Return NULL if an error occurred while
reading. A message will be printed to stderr in this case.
reading. If print_errors is true, a message will also be printed to stderr.
*/
static LineBuffer* read_source_file(const char *path)
static LineBuffer* read_source_file(const char *path, bool print_errors)
{
FILE *fp;
struct stat st;

if (!(fp = fopen(path, "r"))) {
ERROR_ERRNO("couldn't open source file")
if (print_errors)
ERROR_ERRNO("couldn't open source file")
return NULL;
}

if (fstat(fileno(fp), &st)) {
fclose(fp);
ERROR_ERRNO("couldn't open source file")
if (print_errors)
ERROR_ERRNO("couldn't open source file")
return NULL;
}
if (!(st.st_mode & S_IFREG)) {
fclose(fp);
ERROR("couldn't open source file: %s", st.st_mode & S_IFDIR ?
"Is a directory" : "Is not a regular file")
if (print_errors)
ERROR("couldn't open source file: %s", st.st_mode & S_IFDIR ?
"Is a directory" : "Is not a regular file")
return NULL;
}

@@ -154,7 +176,8 @@ static LineBuffer* read_source_file(const char *path)
break;
if (errno == ENOMEM)
OUT_OF_MEMORY()
ERROR_ERRNO("couldn't read source file")
if (print_errors)
ERROR_ERRNO("couldn't read source file")
fclose(fp);
source->lines = dummy.next;
free_line_buffer(source);
@@ -204,26 +227,31 @@ static bool write_binary_file(const char *path, const uint8_t *data, size_t size
}

/*
Create an ErrorLine object from an ASMLine.
Create an ASMErrorLine object from an ASMLine.
*/
static ErrorLine* create_error_line(const ASMLine *line)
static ASMErrorLine* create_error_line(const ASMLine *line)
{
ErrorLine *el = malloc(sizeof(ErrorLine));
ASMErrorLine *el = malloc(sizeof(ASMErrorLine));
if (!el)
OUT_OF_MEMORY()

if (!(el->data = malloc(sizeof(char) * line->original->length)))
const char *source = line->original->data;
size_t length = line->original->length;
if (!(el->data = malloc(sizeof(char) * length)))
OUT_OF_MEMORY()
memcpy(el->data, line->original->data, line->original->length);

el->length = line->original->length;
// Ignore spaces at beginning:
while (length > 0 && (*source == ' ' || *source == '\t'))
source++, length--;
memcpy(el->data, source, length);

el->length = length;
el->lineno = line->original->lineno;

el->filename = strdup(line->filename);
if (!el->filename)
OUT_OF_MEMORY()

el->index = -1;
el->next = NULL;
return el;
}
@@ -237,42 +265,40 @@ static ErrorLine* create_error_line(const ASMLine *line)
This function never fails (OOM triggers an exit()); the caller can be
confident the returned object is valid.
*/
static ErrorInfo* create_error(const ASMLine *line, ErrorType et, ErrorDesc ed)
static ErrorInfo* create_error(
const ASMLine *line, ASMErrorType err_type, ASMErrorDesc err_desc)
{
ErrorInfo *ei = malloc(sizeof(ErrorInfo));
if (!ei)
ErrorInfo *einfo = malloc(sizeof(ErrorInfo));
if (!einfo)
OUT_OF_MEMORY()

ei->type = et;
ei->desc = ed;
ei->line = create_error_line(line);
return ei;
einfo->type = err_type;
einfo->desc = err_desc;
einfo->line = create_error_line(line);
return einfo;
}

/*
Add an ASMLine to an ErrorInfo object, as part of a file trace.
*/
static void append_to_error(ErrorInfo *ei, const ASMLine *line)
static void append_to_error(ErrorInfo *einfo, const ASMLine *line)
{
ErrorLine* el = create_error_line(line);
el->next = ei->line;
ei->line = el;
ASMErrorLine* el = create_error_line(line);
el->next = einfo->line;
einfo->line = el;
}

/*
Print an ErrorInfo object returned by assemble() to the given stream.
*/
void error_info_print(const ErrorInfo *error_info, FILE *file)
void error_info_print(const ErrorInfo *einfo, FILE *file)
{
ErrorLine *line = error_info->line;
ASMErrorLine *line = einfo->line;

fprintf(file, "error: %d: %d\n", error_info->type, error_info->desc);
fprintf(file, "error: %s: %s\n", ERROR_TYPE(einfo), ERROR_DESC(einfo));
while (line) {
fprintf(file, "\t%s:%zu: %.*s\n", line->filename, line->lineno,
(int) line->length, line->data);
if (line->index >= 0)
fprintf(file, "\t%*s^\n", strlen(line->filename) + 3 + line->index, " ");

fprintf(file, "%s:%zu:\n", line->filename, line->lineno);
fprintf(file, " %.*s\n", (int) line->length, line->data);
line = line->next;
}
}
@@ -285,7 +311,7 @@ void error_info_destroy(ErrorInfo *error_info)
if (!error_info)
return;

ErrorLine *line = error_info->line, *temp;
ASMErrorLine *line = error_info->line, *temp;
while (line) {
temp = line->next;
free(line->data);
@@ -416,7 +442,7 @@ static ASMLine* normalize_line(const char *source, size_t length)
if (c >= 'A' && c <= 'Z')
c += 'a' - 'A';

if (c == '\t' || c == ' ')
if (c == ' ' || c == '\t')
space_pending = true;
else {
if (space_pending) {
@@ -539,9 +565,8 @@ static ErrorInfo* build_asm_lines(
return ei;
}

// TODO: update read_source_file() to change error behavior...
// TODO: handle recursive includes properly
LineBuffer *incbuffer = read_source_file(path);
LineBuffer *incbuffer = read_source_file(path, false);
free(path);
if (!incbuffer) {
ei = create_error(line, ET_FILEIO, ED_FILE_READ_ERR);
@@ -759,7 +784,7 @@ size_t assemble(const LineBuffer *source, uint8_t **binary_ptr, ErrorInfo **ei_p
*/
bool assemble_file(const char *src_path, const char *dst_path)
{
LineBuffer *source = read_source_file(src_path);
LineBuffer *source = read_source_file(src_path, true);
if (!source)
return false;



+ 1
- 25
src/assembler.h View File

@@ -23,31 +23,7 @@ typedef struct {
char *filename;
} LineBuffer;

typedef enum {
ET_SYNTAX,
ET_FILEIO
} ErrorType;

typedef enum {
ED_INCLUDE_BAD_ARG,
ED_FILE_READ_ERR
} ErrorDesc;

struct ErrorLine {
char *data;
size_t length;
size_t lineno;
char *filename;
ssize_t index;
struct ErrorLine *next;
};
typedef struct ErrorLine ErrorLine;

typedef struct {
ErrorType type;
ErrorDesc desc;
ErrorLine *line;
} ErrorInfo;
typedef struct ErrorInfo ErrorInfo;

/* Functions */



Loading…
Cancel
Save