crap-libs/try/try.c

121 lines
2.3 KiB
C
Raw Normal View History

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) {
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
}