From e662e0f1cdc132dc76033c423c13134cdaa20cf6 Mon Sep 17 00:00:00 2001 From: Roberto Ierusalimschy Date: Tue, 22 Aug 2000 14:47:17 -0300 Subject: [PATCH] simpler way to access _INPUT and _OUTPUT --- liolib.c | 112 +++++++++++++++++++++++-------------------------------- 1 file changed, 46 insertions(+), 66 deletions(-) diff --git a/liolib.c b/liolib.c index b92e809d..dc432b40 100644 --- a/liolib.c +++ b/liolib.c @@ -1,5 +1,5 @@ /* -** $Id: liolib.c,v 1.69 2000/08/09 19:16:57 roberto Exp roberto $ +** $Id: liolib.c,v 1.70 2000/08/14 19:10:14 roberto Exp roberto $ ** Standard I/O (and system) library ** See Copyright Notice in lua.h */ @@ -51,39 +51,14 @@ int pclose(); */ #define OUTFILE 1 typedef struct IOCtrl { - FILE *file[2]; /* values of _INPUT and _OUTPUT */ + int ref[2]; /* ref for strings _INPUT/_OUTPUT */ int iotag; /* tag for file handles */ int closedtag; /* tag for closed handles */ } IOCtrl; -static const char *const filenames[] = {"_INPUT", "_OUTPUT", NULL}; - - -static void atribTM (lua_State *L) { - IOCtrl *ctrl = (IOCtrl *)lua_getuserdata(L, lua_getparam(L, 1)); - const char *varname = luaL_check_string(L, 2); - lua_Object newvalue = lua_getparam(L, 4); - int inout; - if ((inout = luaL_findstring(varname, filenames)) != -1) { - if (lua_tag(L, newvalue) != ctrl->iotag) - luaL_verror(L, "%.20s value must be a valid file handle", - filenames[inout]); - ctrl->file[inout] = (FILE *)lua_getuserdata(L, newvalue); - } - /* set the actual variable */ - lua_pushglobals(L); - lua_pushstring(L, varname); - lua_pushobject(L, newvalue); - lua_rawset(L); -} - - -static void ctrl_collect (lua_State *L) { - IOCtrl *ctrl = (IOCtrl *)lua_getuserdata(L, lua_getparam(L, 1)); - free(ctrl); -} +static const char *const filenames[] = {"_INPUT", "_OUTPUT"}; static void pushresult (lua_State *L, int i) { @@ -105,10 +80,11 @@ static void pushresult (lua_State *L, int i) { static FILE *gethandle (lua_State *L, IOCtrl *ctrl, lua_Object f) { - if (lua_isuserdata(L, f)) { + void *p = lua_getuserdata(L, f); + if (p != NULL) { /* is `f' a userdata ? */ int ftag = lua_tag(L, f); - if (ftag == ctrl->iotag) - return (FILE *)lua_getuserdata(L, f); + if (ftag == ctrl->iotag) /* does it have the correct tag? */ + return (FILE *)p; else if (ftag == ctrl->closedtag) lua_error(L, "cannot access a closed file"); /* else go through */ @@ -124,14 +100,15 @@ static FILE *getnonullfile (lua_State *L, IOCtrl *ctrl, int arg) { } -static FILE *getfileparam (lua_State *L, IOCtrl *ctrl, int *arg, int inout) { - FILE *f = gethandle(L, ctrl, lua_getparam(L, *arg)); - if (f) { - (*arg)++; - return f; - } - else - return ctrl->file[inout]; +static FILE *getfilebyref (lua_State *L, IOCtrl *ctrl, int inout) { + FILE *f; + lua_pushglobals(L); + lua_pushref(L, ctrl->ref[inout]); + f = gethandle(L, ctrl, lua_rawget(L)); + if (f == NULL) + luaL_verror(L, "global variable `%.10s' is not a file handle", + filenames[inout]); + return f; } @@ -142,11 +119,7 @@ static void setfilebyname (lua_State *L, IOCtrl *ctrl, FILE *f, } -static void setfile (lua_State *L, IOCtrl *ctrl, FILE *f, int inout) { - ctrl->file[inout] = f; - lua_pushusertag(L, f, ctrl->iotag); - lua_setglobal(L, filenames[inout]); -} +#define setfile(L,ctrl,f,inout) (setfilebyname(L,ctrl,f,filenames[inout])) static void setreturn (lua_State *L, IOCtrl *ctrl, FILE *f, int inout) { @@ -163,10 +136,6 @@ static int closefile (lua_State *L, IOCtrl *ctrl, FILE *f) { if (f == stdin || f == stdout || f == stderr) return 1; else { - if (f == ctrl->file[INFILE]) - setfile(L, ctrl, stdin, INFILE); - else if (f == ctrl->file[OUTFILE]) - setfile(L, ctrl, stdout, OUTFILE); lua_pushusertag(L, f, ctrl->iotag); lua_settag(L, ctrl->closedtag); return (CLOSEFILE(L, f) == 0); @@ -182,9 +151,17 @@ static void io_close (lua_State *L) { static void file_collect (lua_State *L) { IOCtrl *ctrl = (IOCtrl *)lua_getuserdata(L, lua_getparam(L, 1)); - FILE *f = getnonullfile(L, ctrl, 2); - if (f != stdin && f != stdout && f != stderr) - CLOSEFILE(L, f); + if (ctrl == (IOCtrl *)lua_getuserdata(L, lua_getparam(L, 2))) { + /* collectig `ctrl' itself */ + lua_unref(L, ctrl->ref[INFILE]); + lua_unref(L, ctrl->ref[OUTFILE]); + free(ctrl); + } + else { /* collecting a file: Close it */ + FILE *f = getnonullfile(L, ctrl, 2); + if (f != stdin && f != stdout && f != stderr) + CLOSEFILE(L, f); + } } @@ -202,8 +179,8 @@ static void io_fromto (lua_State *L, int inout, const char *mode) { lua_Object f = lua_getparam(L, 2); FILE *current; if (f == LUA_NOOBJECT) { - pushresult(L, closefile(L, ctrl, ctrl->file[inout])); - return; + closefile(L, ctrl, getfilebyref(L, ctrl, inout)); + current = (inout == 0) ? stdin : stdout; } else if (lua_tag(L, f) == ctrl->iotag) /* deprecated option */ current = (FILE *)lua_getuserdata(L, f); @@ -368,8 +345,11 @@ static int read_chars (lua_State *L, FILE *f, size_t n) { static void io_read (lua_State *L) { IOCtrl *ctrl = (IOCtrl *)lua_getuserdata(L, lua_getparam(L, 1)); int arg = 2; - FILE *f = getfileparam(L, ctrl, &arg, INFILE); - lua_Object op = lua_getparam(L, arg); + lua_Object op; + FILE *f = gethandle(L, ctrl, lua_getparam(L, arg)); + if (f) arg++; + else f = getfilebyref(L, ctrl, INFILE); /* get _INPUT */ + op = lua_getparam(L, arg); do { /* repeat for each part */ size_t l; int success; @@ -414,9 +394,11 @@ static void io_read (lua_State *L) { static void io_write (lua_State *L) { IOCtrl *ctrl = (IOCtrl *)lua_getuserdata(L, lua_getparam(L, 1)); int arg = 2; - FILE *f = getfileparam(L, ctrl, &arg, OUTFILE); int status = 1; lua_Object o; + FILE *f = gethandle(L, ctrl, lua_getparam(L, arg)); + if (f) arg++; + else f = getfilebyref(L, ctrl, OUTFILE); /* get _OUTPUT */ while ((o = lua_getparam(L, arg)) != LUA_NOOBJECT) { if (lua_type(L, o)[2] == 'm') { /* nuMber? */ /* LUA_NUMBER */ /* optimization: could be done exactly as for strings */ @@ -641,28 +623,26 @@ static void openwithcontrol (lua_State *L) { lua_pushcclosure(L, iolibtag[i].func, 1); lua_setglobal(L, iolibtag[i].name); } + /* create references to variable names */ + lua_pushstring(L, filenames[INFILE]); + ctrl->ref[INFILE] = lua_ref(L, 1); + lua_pushstring(L, filenames[OUTFILE]); + ctrl->ref[OUTFILE] = lua_ref(L, 1); /* predefined file handles */ - ctrl->file[INFILE] = stdin; setfile(L, ctrl, stdin, INFILE); - ctrl->file[OUTFILE] = stdout; setfile(L, ctrl, stdout, OUTFILE); setfilebyname(L, ctrl, stdin, "_STDIN"); setfilebyname(L, ctrl, stdout, "_STDOUT"); setfilebyname(L, ctrl, stderr, "_STDERR"); - /* change file when assigned */ - lua_pushusertag(L, ctrl, ctrltag); - lua_pushcclosure(L, atribTM, 1); - lua_settagmethod(L, ctrl->iotag, "setglobal"); /* delete `ctrl' when collected */ lua_pushusertag(L, ctrl, ctrltag); - lua_pushcclosure(L, ctrl_collect, 1); + lua_pushcclosure(L, file_collect, 1); lua_settagmethod(L, ctrltag, "gc"); /* close files when collected */ - lua_pushusertag(L, ctrl, ctrltag); - lua_pushcclosure(L, file_collect, 1); - lua_settagmethod(L, ctrl->iotag, "gc"); + lua_copytagmethods(L, ctrl->iotag, ctrltag); } + void lua_iolibopen (lua_State *L) { luaL_openl(L, iolib); openwithcontrol(L);