File: except.c

package info (click to toggle)
ruby-ferret 0.11.8.4%2Bdebian-2
  • links: PTS, VCS
  • area: main
  • in suites: wheezy
  • size: 4,368 kB
  • sloc: ansic: 69,786; ruby: 8,131; makefile: 5
file content (102 lines) | stat: -rw-r--r-- 2,750 bytes parent folder | download | duplicates (3)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
#include <stdarg.h>
#include "global.h"
#include "except.h"
#include "threading.h"
#include "internal.h"

static const char *const ERROR_TYPES[] = {
    "Body",
    "Finally",
    "Exception",
    "IO Error",
    "File Not Found Error",
    "Argument Error",
    "End-of-File Error",
    "Unsupported Function Error",
    "State Error",
    "Parse Error",
    "Memory Error",
    "Index Error",
    "Lock Error"
};

char *const UNSUPPORTED_ERROR_MSG = "Unsupported operation";
char *const EOF_ERROR_MSG = "Read past end of file";
char xmsg_buffer[XMSG_BUFFER_SIZE];
char xmsg_buffer_final[XMSG_BUFFER_SIZE];

static thread_key_t exception_stack_key;
static thread_once_t exception_stack_key_once = THREAD_ONCE_INIT;

static void exception_stack_alloc(void)
{
    thread_key_create(&exception_stack_key, NULL);
}

void xpush_context(xcontext_t *context)
{
    xcontext_t *top_context;
    thread_once(&exception_stack_key_once, *exception_stack_alloc);
    top_context = (xcontext_t *)thread_getspecific(exception_stack_key);
    context->next = top_context;
    thread_setspecific(exception_stack_key, context);
    context->handled = true;
    context->in_finally = false;
}

static INLINE void xraise_context(xcontext_t *context,
                                    volatile int excode,
                                    const char *const msg)
{
    context->msg = msg;
    context->excode = excode;
    context->handled = false;
    longjmp(context->jbuf, excode);
}

#ifndef FRT_HAS_VARARGS
void RAISE(int excode, const char *fmt, ...)
{
    va_list args;
    va_start(args, fmt);
    vsnprintf(xmsg_buffer, XMSG_BUFFER_SIZE, fmt, args);
    xraise(excode, xmsg_buffer);
    va_end(args);
}
#endif

void xraise(int excode, const char *const msg)
{
    xcontext_t *top_context;
    thread_once(&exception_stack_key_once, *exception_stack_alloc);
    top_context = (xcontext_t *)thread_getspecific(exception_stack_key);

    if (!top_context) {
        XEXIT(ERROR_TYPES[excode], msg);
    }
    else if (!top_context->in_finally) {
        xraise_context(top_context, excode, msg);
    }
    else if (top_context->handled) {
        top_context->msg = msg;
        top_context->excode = excode;
        top_context->handled = false;
    }
}

void xpop_context()
{
    xcontext_t *top_cxt, *context;
    thread_once(&exception_stack_key_once, *exception_stack_alloc);
    top_cxt = (xcontext_t *)thread_getspecific(exception_stack_key);
    context = top_cxt->next;
    thread_setspecific(exception_stack_key, context);
    if (!top_cxt->handled) {
        if (context) {
            xraise_context(context, top_cxt->excode, top_cxt->msg);
        }
        else {
            XEXIT(ERROR_TYPES[top_cxt->excode], top_cxt->msg);
        }
    }
}