#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); Datum *geta(void); Datum *getd(void); Array *runfile(Array *); Array *quadthrow1(Array *); Array *quadthrow2(Array *, Array *); Array *quadinfo(Array *); Array *quadproto(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"⎕A", NameTag, geta, nil, nil, nil}, {L"⎕D", NameTag, getd, nil, nil, nil}, {L"⎕RUN", FunctionTag, nil, nil, runfile, nil}, {L"⎕THROW", FunctionTag, nil, nil, quadthrow1, quadthrow2}, {L"⎕INFO", FunctionTag, nil, nil, quadinfo, nil}, {L"⎕PROTO", FunctionTag, nil, nil, quadproto, nil}, {nil, 0, nil, nil, nil, nil} /* MUST BE LAST */ }; void initquadnames(void) { Symbol *s; QuadnameDef q; int i; for(i = 0; quadnames[i].name != nil; i++){ q = quadnames[i]; if(q.tag == NameTag){ s = getsym(q.name, 1); s->getfn = q.get; s->setfn = q.set; s->undefined = 0; } } } Datum quadnamedatum(QuadnameDef q) { Datum d; d.tag = q.tag; switch(q.tag){ case NameTag: d.name = q.name; 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]); } /* ⎕A */ Datum * geta(void) { Datum *d = mallocz(sizeof(Datum), 1); d->tag = ArrayTag; d->array = mkrunearray(L"ABCDEFGHIJKLMNOPQRSTUVWXYZ"); return d; } /* ⎕D */ Datum * getd(void) { Datum *d = mallocz(sizeof(Datum), 1); d->tag = ArrayTag; d->array = mkrunearray(L"0123456789"); return d; } /* ⎕RUN */ Array * runfile(Array *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; } /* ⎕INFO */ Array * quadinfo(Array *a) { if(a->type != AtypeRune) throwerror(nil, EType); Rune *code = pparray(a); Datum *res = evalline(code, nil, 0); Rune *info; switch(res->tag){ case ArrayTag:{ char *typestring = "?"; switch(res->array->type){ case AtypeInt: typestring = "int"; break; case AtypeFloat: typestring = "float"; break; case AtypeRune: typestring = "rune"; break; case AtypeMixed: typestring = "mixed"; break; case AtypeArray: typestring = "array"; break; } uvlong size = arrayspaceused(res->array); info = runesmprint("Type = %s, size in bytes = %ulld", typestring, size); break; } default: info = runesmprint("Can't show info for datum tag %d", res->tag); } Array *infoarr = mkrunearray(info); free(code); free(res); free(info); return infoarr; } /* ⎕PROTO */ Array * quadproto(Array *a) { return fillelement(a); }