summaryrefslogtreecommitdiff
path: root/error.c
blob: e12318ab8ceb5cb6c24bf7de5ca99b80fa6c545a (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
72
73
#include <u.h>
#include <libc.h>
#include <thread.h>
#include <bio.h>

#include "apl9.h"

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

	if(fr == nil)
		td->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)
{
	ThreadData *td = getthreaddata();
	ErrorGuard *matching = td->globalerrorguard;
	DfnFrame *frame = getcurrentdfn();
	td->lasterror = err;
	if(td->lasterrormsg)
		free(td->lasterrormsg);
	td->lasterrormsg = runestrdup(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);
}

Rune *
errorstr(int code)
{
	Rune *err;
	switch(code){
	case ESyntax: err = L"SYNTAX ERROR"; break;
	case EIndex: err = L"INDEX ERROR"; break;
	case ERank: err = L"RANK ERROR"; break;
	case ELength: err = L"LENGTH ERROR"; break;
	case EValue: err = L"VALUE ERROR"; break;
	case EDomain: err = L"DOMAIN ERROR"; break;
	case ENotImplemented: err = L"NOT IMPLEMENTED"; break;
	default: err = L""; break;
	}
	return err;
}