#include #include #include static void fdgc(Pointer*); static Metatable fdmeta = { .gc = fdgc, }; static void fdgc(Pointer *p) { int fd; assert(p->meta == &fdmeta); fd = (uintptr)p->v; assert(close(fd) == 0); } static void ppopen(Node *r, Node **av, int na) { int fd, omode; Node nodpath, nodmode; if(na != 2) pperror("open(path, mode): arg count"); ppexpr(av[0], &nodpath); ppexpr(av[1], &nodmode); if(nodpath.store.type != TSTRING || nodmode.store.type != TINT) pperror("open(path, mode): arg type"); omode = nodmode.store.ival; fd = open(nodpath.store.string->string, omode); if(fd < 0) pperror("open: %r"); r->op = OCONST; r->store.type = TPOINTER; r->store.pval = pppointernode((void*)(uintptr)fd, &fdmeta); } static void ppread(Node *r, Node **av, int na) { int fd, n; char buf[8192]; Node nodfd; if(na != 1) pperror("read(fd): arg count"); ppexpr(av[0], &nodfd); if(nodfd.store.type != TPOINTER) pperror("read(fd): arg type"); fd = (uintptr)nodfd.store.pval->v; n = read(fd, buf, sizeof(buf)); if(n < 0) pperror("read: %r"); if(n == 0) return; ppsetstringlen(r, buf, n); } static void usage(void) { fprint(2, "usage: %s\n", argv0); exits("usage"); } #ifdef __unix__ #define TESTFILE "/etc/services" #else #define TESTFILE "/lib/glass" #endif void main(int argc, char *argv[]) { ARGBEGIN{ default: usage(); }ARGEND static char ppscript[] = "\ OREAD = 0; \ OWRITE = 1; \ fd = open(\"" TESTFILE "\", OREAD); \ s = read(fd); \ while s != nil do { \ // print(s); \n\ s = read(fd); \ }; \ fd = {};"; ppsetup(); ppbind("open", ppopen); ppbind("read", ppread); ppcall("interpret", ppstring(ppscript), nil); gc(1); exits(nil); }