add error handling system
This commit is contained in:
parent
957f5e2a35
commit
4dbc77845a
5 changed files with 155 additions and 0 deletions
|
@ -6,6 +6,7 @@
|
|||
#error "Only gcc and clang are supported"
|
||||
#endif
|
||||
|
||||
#include "neo/_error.h"
|
||||
#include "neo/_types.h"
|
||||
#include "neo/_stddef.h"
|
||||
|
||||
|
|
48
include/neo/_error.h
Normal file
48
include/neo/_error.h
Normal file
|
@ -0,0 +1,48 @@
|
|||
/** See the end of this file for copyright and license terms. */
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "neo/_types.h"
|
||||
|
||||
/**
|
||||
* Throw an error. If `err` is `nil`, the program halts.
|
||||
*
|
||||
* @param err: The error pointer passed to the callee
|
||||
* @param number: An error number appropriate for the condition,
|
||||
* usually one from `errno.h`
|
||||
* @param fmt: If non nil, a printf-style format string followed by
|
||||
* the values to insert which will become the error message.
|
||||
*/
|
||||
__attribute__(( __format__(printf, 3, 4) ))
|
||||
void yeet(error *err, int number, const char *restrict fmt, ...);
|
||||
|
||||
/**
|
||||
* Functions accepting an error pointer must call this to indicate success.
|
||||
*/
|
||||
#define succeed(errptr) ({ \
|
||||
if (errptr) \
|
||||
*(errptr) = nil; \
|
||||
})
|
||||
|
||||
/**
|
||||
* Functions passing an error pointer must call this to acknowledge an error.
|
||||
*/
|
||||
void catch(error *err);
|
||||
|
||||
/** Get the error number */
|
||||
#define errnum(err) ((err)->_number)
|
||||
/** Get an optional error message, this may be `nil` */
|
||||
#define errmsg(err) ((err)->_message)
|
||||
|
||||
/*
|
||||
* This file is part of libneo.
|
||||
* Copyright (c) 2021 Fefie <owo@fef.moe>.
|
||||
*
|
||||
* libneo is non-violent software: you may only use, redistribute,
|
||||
* and/or modify it under the terms of the CNPLv6+ as found in
|
||||
* the LICENSE file in the source code root directory or at
|
||||
* <https://git.pixie.town/thufie/CNPL>.
|
||||
*
|
||||
* libneo comes with ABSOLUTELY NO WARRANTY, to the extent
|
||||
* permitted by applicable law. See the CNPLv6+ for details.
|
||||
*/
|
|
@ -25,6 +25,7 @@ target_include_directories(neo PRIVATE
|
|||
)
|
||||
|
||||
target_sources(neo PRIVATE
|
||||
./error.c
|
||||
./nref.c
|
||||
)
|
||||
|
||||
|
|
81
src/error.c
Normal file
81
src/error.c
Normal file
|
@ -0,0 +1,81 @@
|
|||
/** See the end of this file for copyright and license terms. */
|
||||
|
||||
#include <stdarg.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
|
||||
#include "neo/_error.h"
|
||||
#include "neo/_nref.h"
|
||||
#include "neo/_stddef.h"
|
||||
#include "neo/_string.h"
|
||||
#include "neo/_types.h"
|
||||
#include "neo/toolchain.h"
|
||||
|
||||
/* flags for the error structure */
|
||||
#define NEO_ERR_CAUGHT (1 << 0)
|
||||
|
||||
/* TODO: we need one of these for every thread */
|
||||
static struct _neo_error _neo_error_instance = {
|
||||
._number = 0,
|
||||
._message = nil,
|
||||
._flags = NEO_ERR_CAUGHT,
|
||||
};
|
||||
|
||||
void yeet(error *err, int number, const char *restrict fmt, ...)
|
||||
{
|
||||
va_list vargs;
|
||||
usize msg_capacity = 64;
|
||||
char *msg = nil;
|
||||
int printf_ret;
|
||||
|
||||
if (fmt != nil) {
|
||||
do {
|
||||
msg = nalloc(msg_capacity, nil);
|
||||
va_start(vargs, fmt);
|
||||
printf_ret = vsnprintf(msg, msg_capacity, fmt, vargs);
|
||||
va_end(vargs);
|
||||
if (printf_ret > 0) {
|
||||
msg_capacity += printf_ret;
|
||||
nfree(msg);
|
||||
msg = nil;
|
||||
} else if (printf_ret < 0) {
|
||||
write(1, "Runtime error\n", 14);
|
||||
exit(1);
|
||||
}
|
||||
} while (msg == nil);
|
||||
} else {
|
||||
msg = "Runtime error";
|
||||
}
|
||||
|
||||
if (err == nil) {
|
||||
write(2, msg, strlen(msg));
|
||||
exit(number);
|
||||
}
|
||||
|
||||
*err = &_neo_error_instance;
|
||||
(*err)->_number = number;
|
||||
(*err)->_message = nstr(msg, nil);
|
||||
(*err)->_flags &= ~NEO_ERR_CAUGHT;
|
||||
}
|
||||
|
||||
void catch(error *err)
|
||||
{
|
||||
if ((*err)->_message)
|
||||
nput((*err)->_message);
|
||||
(*err)->_flags |= NEO_ERR_CAUGHT;
|
||||
*err = nil;
|
||||
}
|
||||
|
||||
/*
|
||||
* This file is part of libneo.
|
||||
* Copyright (c) 2021 Fefie <owo@fef.moe>.
|
||||
*
|
||||
* libneo is non-violent software: you may only use, redistribute,
|
||||
* and/or modify it under the terms of the CNPLv6+ as found in
|
||||
* the LICENSE file in the source code root directory or at
|
||||
* <https://git.pixie.town/thufie/CNPL>.
|
||||
*
|
||||
* libneo comes with ABSOLUTELY NO WARRANTY, to the extent
|
||||
* permitted by applicable law. See the CNPLv6+ for details.
|
||||
*/
|
24
src/include/neo/toolchain.h
Normal file
24
src/include/neo/toolchain.h
Normal file
|
@ -0,0 +1,24 @@
|
|||
/** See the end of this file for copyright and license terms. */
|
||||
|
||||
#pragma once
|
||||
|
||||
#define __neo_section(name) __attribute__(( __section__(#name) ))
|
||||
|
||||
#define __neo_init(fn) \
|
||||
__neo_section(.init_array) static void (*__neo_init_##fn)(void) = fn
|
||||
|
||||
#define __neo_fini(fn) \
|
||||
__neo_section(.fini_array) static void (*__neo_fini_##fn)(void) = fn
|
||||
|
||||
/*
|
||||
* This file is part of libneo.
|
||||
* Copyright (c) 2021 Fefie <owo@fef.moe>.
|
||||
*
|
||||
* libneo is non-violent software: you may only use, redistribute,
|
||||
* and/or modify it under the terms of the CNPLv6+ as found in
|
||||
* the LICENSE file in the source code root directory or at
|
||||
* <https://git.pixie.town/thufie/CNPL>.
|
||||
*
|
||||
* libneo comes with ABSOLUTELY NO WARRANTY, to the extent
|
||||
* permitted by applicable law. See the CNPLv6+ for details.
|
||||
*/
|
Loading…
Reference in a new issue