2017-03-09 15:24:52 +00:00
|
|
|
#include "try.h"
|
2017-03-10 17:43:56 +00:00
|
|
|
#include "exceptions/exceptions.h"
|
2017-03-09 15:24:52 +00:00
|
|
|
|
|
|
|
#include <stdlib.h>
|
2017-03-10 17:43:56 +00:00
|
|
|
#include <stdio.h>
|
|
|
|
#include <execinfo.h>
|
|
|
|
#include <string.h>
|
|
|
|
#include <errno.h>
|
2017-03-09 15:24:52 +00:00
|
|
|
|
|
|
|
struct tryc {
|
|
|
|
bool used;
|
|
|
|
void* exception;
|
|
|
|
};
|
|
|
|
|
|
|
|
#define MAX_TRY 10
|
|
|
|
|
|
|
|
int trynr = 0;
|
|
|
|
|
|
|
|
struct tryc trys[MAX_TRY] = {0};
|
|
|
|
|
|
|
|
int stack_position = -1;
|
|
|
|
try_t stack[MAX_TRY] = {-1};
|
|
|
|
|
|
|
|
try_t find_free_id(void) {
|
|
|
|
for (int i = 0; i < MAX_TRY; i++) {
|
|
|
|
if (!trys[i].used)
|
|
|
|
return i;
|
|
|
|
}
|
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
|
|
|
|
try_t try_new(void) {
|
|
|
|
if (trynr >= MAX_TRY)
|
|
|
|
return -1;
|
|
|
|
try_t t = find_free_id();
|
|
|
|
trys[t].used = true;
|
|
|
|
trys[t].exception = NULL;
|
|
|
|
return t;
|
|
|
|
}
|
|
|
|
|
|
|
|
bool try_has_catch(try_t id) {
|
|
|
|
return trys[id].exception != NULL;
|
|
|
|
}
|
|
|
|
|
|
|
|
void* try_catch(try_t id) {
|
|
|
|
return trys[id].exception;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
void try_remove(try_t id) {
|
2017-03-10 17:43:56 +00:00
|
|
|
if (trys[id].used) {
|
|
|
|
trys[id].used = false;
|
|
|
|
trynr--;
|
|
|
|
}
|
2017-03-09 15:24:52 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
try_t try_pop(void) {
|
2017-03-10 17:43:56 +00:00
|
|
|
if (stack_position < 0)
|
|
|
|
return NO_TRY_BODY;
|
2017-03-09 15:24:52 +00:00
|
|
|
return stack[stack_position--];
|
|
|
|
}
|
|
|
|
|
|
|
|
void try_push(try_t id) {
|
2017-03-10 22:16:06 +00:00
|
|
|
if (id == NO_TRY_BODY)
|
|
|
|
return;
|
2017-03-09 15:24:52 +00:00
|
|
|
stack[++stack_position] = id;
|
|
|
|
}
|
|
|
|
|
2017-03-10 17:43:56 +00:00
|
|
|
#define BACKTRACE_BUFFER_SIZE 16
|
|
|
|
#define EXIT_BACKTRACE_FAILED 3
|
|
|
|
#define EXIT_UNCAUGHT 4
|
|
|
|
void print_backtrace(FILE* file) {
|
|
|
|
void* buffer[BACKTRACE_BUFFER_SIZE];
|
|
|
|
char** strings;
|
|
|
|
int entries = backtrace(buffer, BACKTRACE_BUFFER_SIZE);
|
|
|
|
strings = backtrace_symbols(buffer, entries);
|
|
|
|
|
|
|
|
if (strings == NULL) {
|
|
|
|
fprintf(file, " Error while backtracing: %s\n", strerror(errno));
|
|
|
|
exit(EXIT_BACKTRACE_FAILED);
|
|
|
|
}
|
|
|
|
|
|
|
|
int tmp = (entries < BACKTRACE_BUFFER_SIZE) ? entries : entries - 1;
|
|
|
|
|
|
|
|
// from 2, because of print_backtrace and try_throw
|
|
|
|
for (int i = 2; i < tmp; i++) {
|
|
|
|
fprintf(file, " at %s\n", strings[i]);
|
|
|
|
}
|
|
|
|
if (tmp < entries) {
|
|
|
|
fprintf(file, " ...\n");
|
|
|
|
}
|
|
|
|
exit(EXIT_UNCAUGHT);
|
|
|
|
}
|
|
|
|
|
2017-03-09 15:24:52 +00:00
|
|
|
void try_throw(try_t id, void* exception) {
|
2017-03-10 17:43:56 +00:00
|
|
|
if (id == NO_TRY_BODY) {
|
2017-03-11 01:00:02 +00:00
|
|
|
Exception_t* e = exception;
|
2017-03-10 22:16:06 +00:00
|
|
|
|
|
|
|
#ifdef PTHREAD_SCOPE_SYSTEM
|
|
|
|
// we are in a pthread environment
|
|
|
|
pthread_id_np_t tid;
|
|
|
|
tid = pthread_getthreadid_np();
|
|
|
|
fprintf(stderr, "\nUncaught error %s_t in thread %i\n: %s\n",
|
|
|
|
oop_get_class_name(oop_get_class_from_obj((void*) e)),
|
|
|
|
tid, e->msg);
|
|
|
|
#else
|
|
|
|
fprintf(stderr, "\nUncaught error %s_t: %s\n",
|
|
|
|
oop_get_class_name(oop_get_class_from_obj((void*) e)),
|
|
|
|
e->msg);
|
|
|
|
#endif
|
|
|
|
|
2017-03-10 17:43:56 +00:00
|
|
|
print_backtrace(stderr);
|
|
|
|
} else {
|
|
|
|
trys[id].exception = exception;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
void try_reset(try_t id) {
|
|
|
|
trys[id].exception = NULL;
|
2017-03-09 15:24:52 +00:00
|
|
|
}
|