#include #include #include #include "apl9.h" Datum *getquad(void); void setquad(Datum); Datum *getio(void); void setio(Datum); Datum *getpp(void); void setpp(Datum); Datum *getdiv(void); void setdiv(Datum); Array *runfile(Array *); Array *quadthrow1(Array *); Array *quadthrow2(Array *, Array *); QuadnameDef quadnames[] = { {L"⎕", NameTag, getquad, setquad, nil, nil}, {L"⎕IO", NameTag, getio, setio, nil, nil}, {L"⎕PP", NameTag, getpp, setpp, nil, nil}, {L"⎕DIV", NameTag, getdiv, setdiv, nil, nil}, {L"⎕RUN", FunctionTag, nil, nil, runfile, nil}, {L"⎕THROW", FunctionTag, nil, nil, quadthrow1, quadthrow2}, {nil, 0, nil, nil, nil, nil} /* MUST BE LAST */ }; Datum quadnamedatum(QuadnameDef q) { Datum d; d.tag = q.tag; switch(q.tag){ case NameTag: d.symbol = getsym(q.name); d.symbol->getfn = q.get; d.symbol->setfn = q.set; d.symbol->undefined = 0; break; case FunctionTag: d.func.type = FunctypeQuad; d.func.quad = malloc(sizeof(QuadnameDef)); *d.func.quad = q; d.func.left = nil; break; case MonadicOpTag: case DyadicOpTag: default: print("Can't use quad names with type=%d\n", q.tag); exits(nil); } return d; } /* ⎕ */ Datum * getquad(void) { print("⎕:\n\t"); Datum *result = evalline(nil, nil, 1); /* TODO check that the expression doesn't fail */ return result; } void setquad(Datum new) { print("%S\n", ppdatum(new)); } /* ⎕IO */ Datum * getio(void) { Datum *d = mallocz(sizeof(Datum), 1); d->tag = ArrayTag; d->array = mkscalarint(globalIO()); return d; } void setio(Datum new) { if(new.tag != ArrayTag || new.array->rank != 0 || new.array->type != AtypeInt || (new.array->intdata[0] != 0 && new.array->intdata[0] != 1)) throwerror(nil, EDomain); else globalIOset(new.array->intdata[0]); } /* ⎕PP */ Datum * getpp(void) { Datum *d = mallocz(sizeof(Datum), 1); d->tag = ArrayTag; d->array = mkscalarint(printprecision); return d; } void setpp(Datum new) { if(new.tag != ArrayTag || new.array->rank != 0 || new.array->type != AtypeInt || new.array->intdata[0] < 0) throwerror(nil, EDomain); else printprecision = new.array->intdata[0]; } /* ⎕DIV */ Datum * getdiv(void) { Datum *d = mallocz(sizeof(Datum), 1); d->tag = ArrayTag; d->array = mkscalarint(globalDIV()); return d; } void setdiv(Datum new) { if(new.tag != ArrayTag || new.array->rank != 0 || new.array->type != AtypeInt || (new.array->intdata[0] != 0 && new.array->intdata[0] != 1)) throwerror(nil, EDomain); else globalDIVset(new.array->intdata[0]); } /* ⎕RUN */ Array * runfile(Array *a) { print("Loading file %S\n", pparray(a)); if(a->type != AtypeRune || a->rank > 1){ return mkscalarint(0); } char *filename = smprint("%S", pparray(a)); Biobuf *bio = Bopen(filename, OREAD); if(bio == nil) return mkscalarint(0); while(1){ Rune r = Bgetrune(bio); Bungetrune(bio); if(r == Beof) break; else evalline(nil, bio, 1); } Bterm(bio); return mkscalarint(1); } /* ⎕THROW */ Array * quadthrow1(Array *code) { if(code->type != AtypeInt) throwerror(nil, EType); if(code->size != 1) throwerror(nil, ELength); throwerror(nil, code->intdata[0]); return nil; } Array * quadthrow2(Array *msg, Array *code) { if(code->type != AtypeInt || msg->type != AtypeRune) throwerror(nil, EType); if(code->size != 1) throwerror(nil, ELength); if(msg->rank > 1) throwerror(nil, ERank); throwerror(pparray(msg), code->intdata[0]); return nil; }