mirror of
https://github.com/sigmasternchen/crap-libs
synced 2025-03-15 07:38:56 +00:00
we now have a stackstrace \o/
This commit is contained in:
parent
462ac20b39
commit
673e411c86
6 changed files with 149 additions and 56 deletions
13
try/Makefile
13
try/Makefile
|
@ -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
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
|
22
try/exceptions/exceptions.c
Normal file
22
try/exceptions/exceptions.c
Normal 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;
|
||||
}
|
32
try/exceptions/exceptions.h
Normal file
32
try/exceptions/exceptions.h
Normal 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
|
55
try/try.c
55
try/try.c
|
@ -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;
|
||||
}
|
||||
|
|
29
try/try.h
29
try/try.h
|
@ -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
|
||||
|
|
Loading…
Reference in a new issue