#include #include #include #include typedef struct Offtab Offtab; struct Offtab { char *member; uintptr offset; }; Offtab tmofftab[] = { {"hour", offsetof(Tm, hour)}, {"mday", offsetof(Tm, mday)}, {"min", offsetof(Tm, min)}, {"mon", offsetof(Tm, mon)}, {"sec", offsetof(Tm, sec)}, {"wday", offsetof(Tm, wday)}, {"yday", offsetof(Tm, yday)}, {"year", offsetof(Tm, year)}, }; #define OFFNIL ((uintptr)-1ULL) uintptr offsearch(Offtab *tab, int nel, char *member) { int lo, mid, hi, rv; lo = 0; hi = nel; while(lo <= hi){ mid = (lo + hi) / 2; rv = strcmp(tab[mid].member, member); if(rv > 0) hi = mid - 1; else if(rv < 0) lo = mid + 1; else return tab[mid].offset; } return OFFNIL; } void pptime(Node *r, Node **av, int na) { long *t; USED(av); USED(na); r->op = OCONST; r->store.type = TINT; r->store.ival = time(nil); } void timegetset(Node *v, char *nam, Node *res, int *val) { int *iptr; Tm *t; uintptr off; assert(v != nil); assert(nam != nil); assert(res != nil); t = v->store.pval->v; off = offsearch(tmofftab, nelem(tmofftab), nam); if(off == OFFNIL) pperror("unknown member %q", nam); iptr = (int*)((char*)t + off); /* set */ if(val != nil) *iptr = *val; res->op = OCONST; res->store.type = TINT; res->store.ival = *iptr; } void timeindex(Node *v, char *nam, Node *res) { timegetset(v, nam, res, nil); } void timenewindex(Node *v, char *nam, Node *res) { int val; if(res->store.type != TINT) pperror("expected int in assignment"); val = res->store.ival; timegetset(v, nam, res, &val); } void timegc(Pointer *p) { USED(p); } static Metatable timetable = { .index = timeindex, .newindex = timenewindex, .gc = timegc, }; void pplocaltime(Node *r, Node **av, int na) { Node res; Tm *t; if(na != 1) pperror("localtime(long clock): expected argument"); ppexpr(av[0], &res); if(res.store.type != TINT) pperror("localtime(long clock): expected TINT)"); t = localtime((long)res.store.ival); r->op = OCONST; r->store.type = TPOINTER; r->store.pval = pppointernode(t, &timetable); } void usage(void) { fprint(2, "usage: %s\n", argv0); exits("usage"); } void main(int argc, char *argv[]) { ARGBEGIN{ default: usage(); }ARGEND ppsetup(); ppbind("time", pptime); ppbind("localtime", pplocaltime); /* char ppcode[] = "\ loop 0, 10 do { \ t0 = time(); \ tm = localtime(t0); \ print(tm.hour, \":\", tm.min, \":\", itoa(tm.sec, \"%.02d\"), \"\\n\"); \ }"; ppcall("interpret", as(ppcode)); ppcall("interpret", as("t0=time(); tm=localtime(t0); print(tm.sec, \"\\n\");")); for(i = 0; i < 100; i++){ ppcall("interpret", as("assert(localtime(time()).sec >= 0);")); } */ ppcall("interpret", ppstring("defn checktime(t){ assert(tm.hour == 6); assert(tm.min == 6); assert(tm.sec == 6); };"), nil); ppcall("interpret", ppstring("tm = localtime(time()); tm.hour = 6; tm.min = 6; tm.sec = 6; checktime(tm); tm = {};"), nil); exits(nil); }