error: refactor the whole thing
a.k.a. make it more complicated.
This commit is contained in:
parent
1d7d2a7b55
commit
ec5ed1e352
3 changed files with 59 additions and 37 deletions
|
@ -6,6 +6,9 @@
|
|||
|
||||
/**
|
||||
* Throw an error. If `err` is `nil`, the program halts.
|
||||
* Functions accepting an `err` object must call either `yeet` or `neat`
|
||||
* on the object exactly once, or the behavior is undefined.
|
||||
* If a function yeets an error, its return value is undefined.
|
||||
*
|
||||
* @param err: The error pointer passed to the callee
|
||||
* @param number: An error number appropriate for the condition,
|
||||
|
@ -14,24 +17,47 @@
|
|||
* 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, ...);
|
||||
void yeet(error *err, u32 number, const char *restrict fmt, ...);
|
||||
|
||||
/**
|
||||
* Functions accepting an error pointer must call this to indicate success.
|
||||
* Indicate an operation has completed successfully.
|
||||
* Functions accepting an `error` pointer must call either `yeet` or `neat`,
|
||||
* or the begavior is undefined.
|
||||
*
|
||||
* @param err: Error object
|
||||
*/
|
||||
#define neat(errptr) ({ \
|
||||
if (errptr) \
|
||||
*(errptr) = nil; \
|
||||
})
|
||||
void neat(error *err);
|
||||
|
||||
/**
|
||||
* Functions passing an error pointer must call this to acknowledge an error.
|
||||
* Release any resources allocated for an error.
|
||||
* This must always be called within the catch block of the outermost calling
|
||||
* function, i.e. the one that declared the error variable (not the ones just
|
||||
* accepting an error * argument and passing it through to further calls).
|
||||
*
|
||||
* Put another way, you probably need to call this if you had to put an `&`
|
||||
* before the error variable for passing it into `catch`.
|
||||
*
|
||||
* @param err: Error object to destroy
|
||||
*/
|
||||
void catch(error *err);
|
||||
void errput(error *err);
|
||||
|
||||
/** Get the error number */
|
||||
/**
|
||||
* Execute the expression after this macro call if the error pointed to
|
||||
* by `err` is an actual error, i.e. it has been `yeet`ed to.
|
||||
* Resources for the error must be released using `nput`.
|
||||
*/
|
||||
#define catch(err) if ((err) != nil && (err)->_number != 0)
|
||||
|
||||
/**
|
||||
* Get the error number.
|
||||
* Must only be used within a catch block and before `errput` is called.
|
||||
*/
|
||||
#define errnum(err) ((err)->_number)
|
||||
/** Get an optional error message, this may be `nil` */
|
||||
|
||||
/**
|
||||
* Get an optional error message, this may be `nil`
|
||||
* Must only be used within a catch block and before `errput` is called.
|
||||
*/
|
||||
#define errmsg(err) ((err)->_message)
|
||||
|
||||
/*
|
||||
|
|
|
@ -53,7 +53,7 @@ struct _neo_error {
|
|||
u32 _number;
|
||||
u32 _flags; /* see src/error.c */
|
||||
};
|
||||
typedef struct _neo_error *error;
|
||||
typedef struct _neo_error error;
|
||||
|
||||
/*
|
||||
* This file is part of libneo.
|
||||
|
|
48
src/error.c
48
src/error.c
|
@ -11,37 +11,26 @@
|
|||
#include "neo/_nref.h"
|
||||
#include "neo/_stddef.h"
|
||||
#include "neo/_string.h"
|
||||
#include "neo/_toolchain.h"
|
||||
#include "neo/_types.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, ...)
|
||||
void yeet(error *err, u32 number, const char *restrict fmt, ...)
|
||||
{
|
||||
va_list vargs;
|
||||
usize msg_capacity = 64;
|
||||
char *msg = nil;
|
||||
int printf_ret;
|
||||
int vsnprintf_ret;
|
||||
|
||||
if (fmt != nil) {
|
||||
do {
|
||||
msg = nalloc(msg_capacity, nil);
|
||||
va_start(vargs, fmt);
|
||||
printf_ret = vsnprintf(msg, msg_capacity, fmt, vargs);
|
||||
vsnprintf_ret = vsnprintf(msg, msg_capacity, fmt, vargs);
|
||||
va_end(vargs);
|
||||
if (printf_ret > 0) {
|
||||
msg_capacity += printf_ret;
|
||||
if (vsnprintf_ret > 0) {
|
||||
msg_capacity += vsnprintf_ret;
|
||||
nfree(msg);
|
||||
msg = nil;
|
||||
} else if (printf_ret < 0) {
|
||||
} else if (vsnprintf_ret < 0) {
|
||||
write(1, "Runtime error\n", 14);
|
||||
exit(1);
|
||||
}
|
||||
|
@ -55,18 +44,25 @@ void yeet(error *err, int number, const char *restrict fmt, ...)
|
|||
exit(number);
|
||||
}
|
||||
|
||||
*err = &_neo_error_instance;
|
||||
(*err)->_number = number;
|
||||
(*err)->_message = nstr(msg, nil);
|
||||
(*err)->_flags &= ~NEO_ERR_CAUGHT;
|
||||
err->_number = number;
|
||||
err->_message = nstr(msg, nil);
|
||||
}
|
||||
|
||||
void catch(error *err)
|
||||
void neat(error *err)
|
||||
{
|
||||
if ((*err)->_message)
|
||||
nput((*err)->_message);
|
||||
(*err)->_flags |= NEO_ERR_CAUGHT;
|
||||
*err = nil;
|
||||
if (err) {
|
||||
err->_number = 0;
|
||||
err->_message = nil;
|
||||
}
|
||||
}
|
||||
|
||||
void errput(error *err)
|
||||
{
|
||||
if (err != nil) {
|
||||
if (err->_message != nil)
|
||||
nput(err->_message);
|
||||
err->_number = 0xffffffff;
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
|
|
Loading…
Reference in a new issue