ref: f1e8a146075542d085cfb8e632849415d32eb2b0
dir: /error.c/
#include <u.h> #include <libc.h> #include <thread.h> #include "dat.h" #include "fns.h" static ErrorCtx * errorctx(void) { /* Return a pointer to the current error context. * TODO: think about what needs its own context */ static ErrorCtx *c = nil; if(c == nil) c = alloc(DataErrorCtx); return c; } ErrorTrap * setuptrap(int n, ...) { ErrorCtx *c = errorctx(); c->count++; c->traps = allocextra(c, sizeof(*c->traps) * c->count); ErrorTrap *t = alloc(DataErrorTrap); va_list nums; va_start(nums, n); for(; n > 0; n--){ int x = va_arg(nums, int); assert(x >= EAny && x <= ErrorMax); if(x == EAny){ for(int i = 0; i < ErrorMax; i++) t->nums[i] = 1; }else t->nums[x] = 1; } va_end(nums); c->traps[c->count-1] = t; return t; } void endtrap(void) { ErrorCtx *c = errorctx(); c->count--; } char * errmsg(void) { ErrorCtx *c = errorctx(); return c->msg; } char * errdesc(void) { ErrorCtx *c = errorctx(); switch(c->num){ case ESyntax: return "SYNTAX ERROR"; case EValue: return "VALUE ERROR"; case EInternal: return "INTERNAL ERROR"; case EDomain: return "DOMAIN ERROR"; default: return "ERROR ???"; } } _Noreturn void error(int num, char *fmt, ...) { ErrorCtx *c; ErrorTrap *t; va_list args; va_start(args, fmt); c = errorctx(); c->num = num; vsnprint(c->msg, sizeof(c->msg), fmt, args); while(1){ assert(c->count > 0); c->count--; t = c->traps[c->count]; if(t->nums[num]) longjmp(t->env, 1); } }