Exceptions in C!

This commit is contained in:
vegowotenks 2025-06-13 16:30:32 +02:00
parent e8bea8924b
commit 26179d76aa
6 changed files with 134 additions and 0 deletions

View file

@ -20,3 +20,4 @@ add_subdirectory(./BinaryTree)
add_subdirectory(./Subprocess)
add_subdirectory(./TracingHeap)
add_subdirectory(./Complex)
add_subdirectory(./ExceptionalScope)

View file

@ -0,0 +1 @@
add_library(ExceptionalScope STATIC ExceptionalScope.c)

View file

@ -0,0 +1,51 @@
#include "ExceptionalScope.h"
#include "../errorcodes.h"
#include <setjmp.h>
#include <stdlib.h>
#include <string.h>
int ExceptionalScope_Create(ExceptionalScope* self)
{
memset(self, 0, sizeof(*self));
return EXIT_SUCCESS;
}
void ExceptionalScope_ActivateCleaners(ExceptionalScope* self)
{
while (self->cleaners != NULL) {
self->cleaners->action(self->cleaners->arg);
self->cleaners = self->cleaners->next;
}
}
void ExceptionalScope_Destroy(ExceptionalScope* self)
{
ExceptionalScope_ActivateCleaners(self);
}
void ExceptionalScope_PushCleaner(ExceptionalScope* self, ExceptionalScopeCleaner* cleaner)
{
cleaner->next = self->cleaners;
self->cleaners = cleaner;
}
int ExceptionalScope_PopCleaner(ExceptionalScope* self, ExceptionalScopeCleaner* cleaner)
{
if (self->cleaners != cleaner) return ENOTFOUND;
self->cleaners = self->cleaners->next;
return EXIT_SUCCESS;
}
[[noreturn]] void ExceptionalScope_Throw(ExceptionalScope* self, void* exception)
{
self->exception = exception;
ExceptionalScope_ActivateCleaners(self);
longjmp(self->handler, 1);
}

View file

@ -0,0 +1,33 @@
#ifndef UTILITIEC_EXCEPTIONALSCOPE_H
#define UTILITIEC_EXCEPTIONALSCOPE_H
#include <setjmp.h>
#define withScopedCleaner(scope, cleaner) for (int __cleanerDone##cleaner = (ExceptionalScope_PushCleaner(scope, &cleaner), 1); __cleanerDone##cleaner--; ExceptionalScope_PopCleaner(scope, &cleaner))
#define try(scope) if (setjmp((scope)->handler) == 0)
#define catch else
typedef void (*ExceptionalScopeCleanerFunction) (void* arg);
typedef struct ExceptionalScopeCleaner_s {
ExceptionalScopeCleanerFunction action;
void* arg;
struct ExceptionalScopeCleaner_s* next;
} ExceptionalScopeCleaner;
typedef struct ExceptionalScope_s {
jmp_buf handler; // jump here when the exception is thrown
ExceptionalScopeCleaner* cleaners; // execute all these before the jumping to the handler
void* exception;
} ExceptionalScope;
int ExceptionalScope_Create(ExceptionalScope* self);
void ExceptionalScope_Destroy(ExceptionalScope* self);
void ExceptionalScope_PushCleaner(ExceptionalScope* self, ExceptionalScopeCleaner* cleaner);
int ExceptionalScope_PopCleaner(ExceptionalScope* self, ExceptionalScopeCleaner* cleaner);
[[noreturn]] void ExceptionalScope_Throw(ExceptionalScope* self, void* exception);
#endif

View file

@ -60,4 +60,8 @@ target_link_libraries(QuadTree-test
rand
pointers
allocator-interface
add_executable(ExceptionalScope-test ExceptionalScope.test.c)
target_link_libraries(ExceptionalScope-test
ExceptionalScope
)

View file

@ -0,0 +1,44 @@
#include "../src/ExceptionalScope/ExceptionalScope.h"
#include <stdio.h>
#define unsafe
void print(const char* s)
{
unsafe {
puts(s);
}
}
int main()
{
ExceptionalScope scope;
ExceptionalScope_Create(&scope);
scope.exception = (void*) 0xCAFEBABE;
try(&scope) {
ExceptionalScopeCleaner outerCleaner = {
.next = NULL,
.arg = "Unwinding the cleaner stack #2",
.action = (ExceptionalScopeCleanerFunction) print,
};
withScopedCleaner(&scope, outerCleaner) {
ExceptionalScopeCleaner innerCleaner = {
.next = NULL,
.arg = "Unwinding the cleaner stack #1",
.action = (ExceptionalScopeCleanerFunction) print,
};
withScopedCleaner(&scope, innerCleaner) {
ExceptionalScope_Throw(&scope, (void*) 0xDEADBEEF);
puts("After the throw");
}
}
} catch {
printf("Caught an exception: %p\n", scope.exception);
}
ExceptionalScope_Destroy(&scope);
}