/* signaller.c L. Stewart August 24, 1982 12:05 PM L. Stewart November 8, 1982 3:25 PM, osstatics */ #include <Signal.h> #include <Env.h> #include <Ec.h> extern MyFrame(); extern CallSwat(); extern CallersFrame(); extern ReturnLoc(); extern Call0(); extern Apply(); extern Ugt(); extern ByteBlt(); struct enab { int ensignal; int enproc; int enframe; int enenframe; int enid; int encontinue; struct Seal *enseal; }; #define lenenab 14 struct sigvec { int svused; int svmaxEnabled; struct enab sven[1]; }; #define lensigvec 4 #define sealseal 0132576 extern int getsv; extern int sigid; extern int signame; SigInit(svec, sveclen, gvproc) struct sigvec *svec; int sveclen; int gvproc; { sigid = 0; signame = 037777; getsv = gvproc; svec->svused = 0; svec->svmaxEnabled = (sveclen-lensigvec)/lenenab; }; int Enable(s, p, sl) int s, p; struct Seal *sl; { return(EnableWithFrame(s, p, sl, MyFrame())); }; int EnableWithFrame(s, p, sl, f) int s; /* signal */ int p; /* proc to call */ struct Seal *sl; int f; { struct sigvec *sv; struct enab *en; sv = Call0(getsv); if (sv->svused == sv->svmaxEnabled) { if (purgesv() >= sv->svmaxEnabled) CallSwat(ecSignal+1); }; en = &sv->sven[sv->svused]; sv->svused += 1; en->ensignal = s; en->enproc = p; en->enenframe = f; en->enframe = CallersFrame(f); en->enseal = sl; en->encontinue = ReturnLoc(f); sigid += 1; en->enid = sigid; sl->slauth = sealseal; sl->slid = sigid; return(0); }; Disable(sl) struct Seal *sl; { sl->slauth = 0; }; Signal(s, c) int s; /* Signal */ int c; /* unspecified */ { struct enab *en; struct sigvec *sv; int enindex; int enabres; int ent; int result; int argv[3]; sv = Call0(getsv); enindex = purgesv(); for (;;) { enabres = true; en = finden(s, &enindex); if (en==0) CallSwat(ecSignal+2); argv[0] = s; argv[1] = c; argv[2] = (int) en->enseal; result = Apply(argv, en->enproc, 3); switch (result) { case REJECT: continue; /* look for next catch phrase */ case RESUME: return; case RETRY: enabres = false; case CONTINUE: unwind(enindex, enabres); break; default: CallSwat(ecSignal+3); }; }; }; int Code() { signame += 1; return(signame); }; static int purgesv() { int f, prevf, invalid; int enf, dest, i; struct sigvec *sv; struct enab *en; struct Seal *sl; sv = Call0(getsv); f = CallersFrame(MyFrame()); prevf = 0; invalid = false; for (i = (sv->svused) - 1; i >= 0; i -= 1) { en = &sv->sven[i]; sl = en->enseal; if ((sl->slauth != sealseal) || (sl->slid != en->enid)) { en->enid = 0; invalid = true; continue; }; enf = en->enframe; while (Ugt(enf, f)) f = CallersFrame(f); if (Ugt(prevf, enf) || Ugt(f, enf)) { en->enid = 0; invalid = true; }; else prevf = f; }; dest = 0; if (invalid) { for (i=0; i < sv->svused; i+= 1) { en = &sv->sven[i]; if (en->enid == 0) continue; /* invalid */ if (dest != i) { ByteBlt(&sv->sven[dest], &sv->sven[i], lenenab); }; dest += 1; }; sv->svused = dest; }; return (sv->svused); }; static struct enab *finden(s, lvindex) int s, *lvindex; { struct sigvec *sv; struct enab *en; int i; sv = Call0(getsv); for (i = (*lvindex) - 1; i >= 0; i -= 1) { en = &sv->sven[i]; if ((en->ensignal == s) || (en->ensignal == ANY)) { *lvindex = i; return (en); }; }; *lvindex = (-1); return (0); }; static unwind(toenindex, result) int toenindex, result; { struct sigvec *sv; struct enab *toen, *en; int id, index, toframe, toenframe, prevframe, nextframe; int argv[3]; sv = Call0(getsv); toen = &sv->sven[toenindex]; id = toen->enid; index = purgesv(); /* purgesv should not invalidate toen */ if ((index<=toenindex) || (toen->enid != id)) CallSwat(ecSignal+4); toframe = toen->enframe; toenframe = toen->enenframe; prevframe = MyFrame(); en = finden(UNWIND, &index); for (;;) { nextframe = CallersFrame(prevframe); while ((index>toenindex) && (en->enframe == nextframe)) { argv[0] = UNWIND; argv[1] = 0; argv[2] = (int) en->enseal; Apply(argv, en->enproc, 3); en = finden(UNWIND, &index); }; if (nextframe==toframe) break; prevframe = nextframe; }; returnto(toenframe, toframe, toen->encontinue, result); };