exception.c 1.73 KB
Newer Older
Adam Blank's avatar
Adam Blank committed
1
2
3
4
5
6
7
8
#include "exception.h"

#include <stdarg.h>
#include <stdlib.h>
#include <string.h>

//// GLOBAL ERROR STATE ////

9
10
static exception_t exception_type;
static char *exception_error;
Adam Blank's avatar
Adam Blank committed
11
12
13

//// EVALUATION ERROR HANDLING ////

14
15
void exception_set(exception_t type, char *message) {
    free(exception_error);
Adam Blank's avatar
Adam Blank committed
16

17
18
    exception_type = type;
    exception_error = strdup(message);
Adam Blank's avatar
Adam Blank committed
19
20
}

21
void exception_set_format(exception_t type, char *format, ...) {
Adam Blank's avatar
Adam Blank committed
22
23
    va_list args;
    va_start(args, format);
24
    int result = vsnprintf(NULL, 0, format, args);
Adam Blank's avatar
Adam Blank committed
25
26
27
28
29
30
    va_end(args);
    if (result < 0) {
        fprintf(stderr, "failed to format exception message with format '%s'\n", format);
        abort();
    }

31
32
33
34
35
36
37
38
    char buf[result + 1];
    va_start(args, format);
    vsprintf(buf, format, args);
    va_end(args);
    exception_set(type, buf);
}
void exception_clear() {
    free(exception_error);
Adam Blank's avatar
Adam Blank committed
39

40
41
    exception_type = EXC_NONE;
    exception_error = NULL;
Adam Blank's avatar
Adam Blank committed
42
43
}

44
45
bool exception_occurred() {
    return exception_type != EXC_NONE;
Adam Blank's avatar
Adam Blank committed
46
47
}

48
static char *exception_type_to_str(exception_t type) {
Adam Blank's avatar
Adam Blank committed
49
50
51
52
53
54
55
56
57
58
59
60
61
62
    switch (type) {
        case EXC_NONE:          return "<none>";
        case EXC_SYNTAX_ERROR:  return "SyntaxError";
        case EXC_NAME_ERROR:    return "NameError";
        case EXC_TYPE_ERROR:    return "TypeError";
        case EXC_VALUE_ERROR:   return "ValueError";
        case EXC_INDEX_ERROR:   return "IndexError";
        case EXC_KEY_ERROR:     return "KeyError";
        case EXC_MEMORY_ERROR:  return "MemoryError";
        case EXC_INTERNAL:      return "<internal>";
    }
    return "<unknown>";
}
void exception_print(FILE *stream) {
63
64
65
    if (exception_occurred()) {
        fprintf(stream, "%s: %s\n",
                exception_type_to_str(exception_type), exception_error);
Adam Blank's avatar
Adam Blank committed
66
67
    }
}