summaryrefslogtreecommitdiff
path: root/error.c
blob: 2a595531d43039644ed6d65df9c65c0bc0735cf0 (plain) (blame)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
#include <u.h>
#include <libc.h>
#include <thread.h>
#include <bio.h>

#include "apl9.h"

ErrorGuard *globalerrorguard;

Rune *errorstrs[] = {
	[ESyntax] = L"SYNTAX ERROR",
	[EParse] = L"PARSE ERROR",
	[EValue] = L"VALUE ERROR",
	[EDomain] = L"DOMAIN ERROR",
	[ERank] = L"RANK ERROR",
	[EType] = L"TYPE ERROR",
	[ELength] = L"LENGTH ERROR",
	[EIndex] = L"INDEX ERROR",
	[EShape] = L"SHAPE ERROR",
	[ENotImplemented] = L"NOT IMPLEMENTED",
};

ErrorGuard *
newerrorguard(Array *codes, Statement *guard)
{
	DfnFrame *fr = getcurrentdfn();
	ErrorGuard *eg = emallocz(sizeof(ErrorGuard), 1);
	eg->active = 1;
	eg->guard = guard;

	if(fr == nil)
		globalerrorguard = eg;
	else{
		eg->next = fr->errorguards;
		fr->errorguards = eg;
		eg->frame = dupdfnframe(fr);
	}

	for(int i = 0; i < GetSize(codes); i++)
		eg->code |= (1<<codes->intdata[i]);

	return eg;
}

void
throwerror(Rune *msg, int err)
{
	ErrorGuard *matching = globalerrorguard;
	DfnFrame *frame = getcurrentdfn();
	ThreadData *td = getthreaddata();
	td->lasterror = err;
	if(td->lasterrormsg)
		free(td->lasterrormsg);
	td->lasterrormsg = msg;

	while(frame != nil){
		for(ErrorGuard *eg = frame->errorguards; eg != nil; eg = eg->next){
			if(!eg->active)
				continue;
			if(((1<<err) & eg->code) || (eg->code == 1)){
				matching = eg;
				goto match;
			}
		}
		frame = frame->prev;
		popdfnframe();
	}
match:
	longjmp(matching->jmp, 1);
}