-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathe4c_lite.c
More file actions
104 lines (74 loc) · 2.8 KB
/
e4c_lite.c
File metadata and controls
104 lines (74 loc) · 2.8 KB
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
103
104
/*
* exceptions4c lightweight version 1.0
*
* Copyright (c) 2014 Guillermo Calvo
* Licensed under the GNU Lesser General Public License
* Small modification was made by Denis Filatov
*/
#define _CRT_SECURE_NO_WARNINGS
#include <stdlib.h>
#include <stdio.h>
#include <errno.h>
#include "e4c_lite.h"
E4C_DEFINE_EXCEPTION(RuntimeException, "Runtime exception.", RuntimeException);
E4C_DEFINE_EXCEPTION(NullPointerException, "Null pointer.", RuntimeException);
struct e4c_context e4c = {0};
static const char * err_msg[] = {"\n\nError: %s (%s)\n\n", "\n\nUncaught %s: %s\n\n thrown at %s:%d\n\n"};
#ifdef E4C_DEBUG
static const char * __stages[] = {
"beginning", "trying", "catching", "finalizing", "done"
};
#endif
static void e4c_propagate(void){
e4c.frame[e4c.frames].uncaught = 1;
if(e4c.frames > 0) longjmp(e4c.jump[e4c.frames - 1], 1);
if(fprintf(stderr, e4c.err.file == NULL ? err_msg[0] : err_msg[1], e4c.err.type->name, e4c.err.message, e4c.err.file, e4c.err.line) > 0)
(void)fflush(stderr);
exit(EXIT_FAILURE);
}
int e4c_try(const char * file, int line){
if(e4c.frames >= E4C_MAX_FRAMES) e4c_throw(&RuntimeException, file, line, E2BIG, "Too many `try` blocks nested.");
e4c.frames++;
e4c.frame[e4c.frames].stage = e4c_beginning;
e4c.frame[e4c.frames].uncaught = 0;
e4c.err.err = 0;
#ifdef E4C_DEBUG
fprintf(stderr, "TRY %d [%s]: %s:%d\n", e4c.frames, __stages[e4c.frame[e4c.frames].stage], file, line);
#endif
return 1;
}
int e4c_hook(int is_catch){
int uncaught;
if (is_catch){
#ifdef E4C_DEBUG
fprintf(stderr, "CATCH %d [%s]:\n", e4c.frames, __stages[e4c.frame[e4c.frames].stage]);
#endif
return !(e4c.frame[e4c.frames].uncaught = 0);
}
uncaught = e4c.frame[e4c.frames].uncaught;
e4c.frame[e4c.frames].stage++;
if(e4c.frame[e4c.frames].stage == e4c_catching && !uncaught) e4c.frame[e4c.frames].stage++;
#ifdef E4C_DEBUG
fprintf(stderr, "HOOK %d [%s]:\n", e4c.frames, __stages[e4c.frame[e4c.frames].stage]);
#endif
if (e4c.frame[e4c.frames].stage < e4c_done) return 1;
e4c.frames--;
if(uncaught) e4c_propagate();
return 0;
}
int e4c_extends(const struct e4c_exception_type * child, const struct e4c_exception_type * parent){
for(; child != NULL && child->supertype != child; child = child->supertype)
if(child->supertype == parent) return 1;
return 0;
}
void e4c_throw(const struct e4c_exception_type * exception_type, const char * file, int line, int err, const char * message){
e4c.err.type = (exception_type != NULL ? exception_type : &NullPointerException);
e4c.err.file = file;
e4c.err.line = line;
e4c.err.err |= err;
#ifdef E4C_DEBUG
fprintf(stderr, "THROW %d [%s]:\n", e4c.frames, __stages[e4c.frame[e4c.frames].stage]);
#endif
(void)sprintf(e4c.err.message, "%.*s", (int)E4C_MESSAGE_SIZE - 1, (message != NULL ? message : e4c.err.type->default_message));
e4c_propagate();
}