shithub: lpa

ref: b69af6813720ca5ca47f267d7e8d832ae0b77172
dir: /error.c/

View raw version
#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);
	}
}