summaryrefslogtreecommitdiff
path: root/error.c
diff options
context:
space:
mode:
Diffstat (limited to 'error.c')
-rw-r--r--error.c49
1 files changed, 45 insertions, 4 deletions
diff --git a/error.c b/error.c
index 47837a9..2a59553 100644
--- a/error.c
+++ b/error.c
@@ -5,7 +5,7 @@
#include "apl9.h"
-ErrorHandler globalerror;
+ErrorGuard *globalerrorguard;
Rune *errorstrs[] = {
[ESyntax] = L"SYNTAX ERROR",
@@ -20,11 +20,52 @@ Rune *errorstrs[] = {
[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)
{
- free(globalerror.msg);
- globalerror.msg = msg ? runestrdup(msg) : nil;
- longjmp(globalerror.jmp, 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);
}