we now have a stackstrace \o/

This commit is contained in:
overflowerror 2017-03-10 18:43:56 +01:00
parent 462ac20b39
commit 673e411c86
6 changed files with 149 additions and 56 deletions

View file

@ -5,9 +5,9 @@
#
CC = gcc
DEFS = -D_XOPEN_SOURCE=500 -D_BSD_SOURCE
DEFS = -D_XOPEN_SOURCE=500 -D_BSD_SOURCE -B "../oop/"
CFLAGS = -Wall -Wextra -g -std=c99 -DENDEBUG $(DEFS) -fPIC
LDFLAGS = $(DEFS)
LDFLAGS = $(DEFS) -rdynamic
LIBFLAGS = -shared $(DEFS)
.PHONY: all clean
@ -17,14 +17,19 @@ all: example libtry.so
%.o: %.c
$(CC) $(CFLAGS) -c -o $@ $<
example: example.o try.o
example: example.o try.o exceptions/exceptions.o ../oop/liboop.so
$(CC) $(LDFLAGS) -o $@ $^
libtry.so: try.o
libtry.so: try.o exceptions/exceptions.o ../oop/liboop.so
$(CC) $(LIBFLAGS) -o $@ $^
try.o: try.c try.h
example.o: example.c try.h
exceptions/exceptions.o: exceptions/exceptions.c exceptions/exceptions.h
../oop/liboop.so:
cd ../oop/ && $(MAKE) liboop.so
clean:
rm -f *.o example libtry.so
cd ../oop/ && $(MAKE) clean

View file

@ -1,54 +1,24 @@
#include "try.h"
#include "../oop/oop.h"
#include "exceptions/exceptions.h"
#include <stdio.h>
void function_with_throw(const char* e) {
subtry();
throw(e);
void function(void) { throws(exception_class)
throw(new exception("This is an uncaught exception."));
}
int main(void) {
// simple try-catch
try {
throw("Hello World 1");
} catch(const char* e) {
printf("Catch 1: %s\n", e);
} endtry;
// try-catch from function
try {
trycall function_with_throw("Hello World 2");
} catch(const char* e) {
printf("Catch 2: %s\n", e);
} endtry;
// nested try-catch
try {
const char* string;
try {
throw("Hello World 3");
} catch(const char* e) {
string = e;
} endtry;
throw(string);
} catch(const char* e) {
printf("Catch 3: %s\n", e);
} endtry;
// nested try-catch with throw in catch-clause
try {
tpush();
try {
throw("Hello World 4");
} catch(const char* e) {
cthrow(e);
} endtry;
} catch(const char* e) {
printf("Catch 4: %s\n", e);
throw(new exception("This is a caught exception."));
} catch(exception_class, exception_t* e) {
printf("Caught: %s\n", e->msg);
e->destruct(e);
} endtry;
function();
return 0;
}

View file

@ -0,0 +1,22 @@
#include "exceptions.h"
#include <stdlib.h>
void method(exception, destruct)(exception_t* this) {
this->super.destruct((object_t*) this);
}
void method(exception, populate)(exception_t* obj, class_t c) {
populate(object)((object_t*) obj, c);
add_method(obj, exception, destruct);
}
exception_t* method(exception, construct)(const char* msg) {
exception_t* obj = malloc(sizeof(exception_t));
populate(exception)(obj, exception_class);
obj->msg = msg;
return obj;
}

View file

@ -0,0 +1,32 @@
#ifndef EXCEPTIONS_H
#define EXCEPTIONS_H
#include "../../oop/oop.h"
#define exception construct(exception)
class_t exception_class;
class(exception, exception_class, object_class, true) {
extends(object_t);
const char* msg;
void (*destruct)(defclass exception*);
} exception_t;
void method(exception, populate)(exception_t*);
exception_t* method(exception, construct)(const char*);
#define exception construct(exception)
class_t exception_class;
class(exception, exception_class, object_class, true) {
extends(object_t);
const char* msg;
void (*destruct)(defclass exception*);
} exception_t;
void method(exception, populate)(exception_t*);
exception_t* method(exception, construct)(const char*);
#endif

View file

@ -1,6 +1,11 @@
#include "try.h"
#include "exceptions/exceptions.h"
#include <stdlib.h>
#include <stdio.h>
#include <execinfo.h>
#include <string.h>
#include <errno.h>
struct tryc {
bool used;
@ -43,11 +48,15 @@ void* try_catch(try_t id) {
void try_remove(try_t id) {
trys[id].used = false;
trynr--;
if (trys[id].used) {
trys[id].used = false;
trynr--;
}
}
try_t try_pop(void) {
if (stack_position < 0)
return NO_TRY_BODY;
return stack[stack_position--];
}
@ -55,6 +64,44 @@ void try_push(try_t id) {
stack[++stack_position] = id;
}
void try_throw(try_t id, void* exception) {
trys[id].exception = exception;
#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);
}
void try_throw(try_t id, void* exception) {
if (id == NO_TRY_BODY) {
exception_t* e = exception;
fprintf(stderr, "\nUncaught exception '%s_t' (\"%s\")\n",
oop_get_class_name(oop_get_class_from_obj((void*) e)),
e->msg);
print_backtrace(stderr);
} else {
trys[id].exception = exception;
}
}
void try_reset(try_t id) {
trys[id].exception = NULL;
}

View file

@ -3,17 +3,33 @@
#include <stdbool.h>
#include "../oop/oop.h"
#include "../misc/unused.h"
typedef int try_t;
#define try do { try_t _try_id = try_new(); void _try_f(void)
#define catch(e) ; _try_f(); if (try_has_catch(_try_id)) { e = try_catch(_try_id); try_remove(_try_id); do
#define endtry while(false); } } while(false);
#define throw(e) try_throw(_try_id, (void*) e); return;
#define throws(...) subtry();
#define try { bool _try_catch = false, _try_body = false; void* _try_data = NULL; try_t _try_id = try_new(); void _try_f(void)
#define pcatch(e) ; _try_f(); if (try_has_catch(_try_id)) { e = try_catch(_try_id); try_remove(_try_id); do
#define catch(c, ex) ; if (!_try_body) { _try_f(); _try_body = true; _try_data = try_catch(_try_id); _try_catch = try_has_catch(_try_id); try_remove(_try_id); } if (_try_catch && instanceof(_try_data, c)) { _try_catch = false; ex = _try_data; do
#define endtry while(false); } if (_try_catch) { UNUSED(_try_body); UNUSED(_try_data); }};
#define throw(e) { try_throw(_try_id, (void*) e); return; }
#define until(condition) ; do { try_reset(_try_id); _try_f(); } while(try_has_catch(_try_id) == condition); void* _try_result = try_catch(_try_id); try_remove(_try_id); if(true) { do
#define get_thrown() (_try_result)
#define failed false
#define succeeded true
#define subtry() try_t _try_id = try_pop();
#define tpush() try_push(_try_id)
#define cthrow(e) _try_id = try_pop(); throw(e);
#define trycall try_push(_try_id);
#define tpush() try_push(_try_id)
#define cthrow(e) _try_id = try_pop(); throw(e);
#define NO_TRY_BODY -1
try_t try_new(void);
bool try_has_catch(try_t);
@ -22,5 +38,6 @@ void try_remove(try_t);
void try_throw(try_t, void*);
try_t try_pop(void);
void try_push(try_t);
void try_reset(try_t);
#endif