From 1514e49d4321efc30d597e05a072266c7c4d697d Mon Sep 17 00:00:00 2001 From: Roberto Ierusalimschy Date: Wed, 17 Mar 2010 18:37:37 -0300 Subject: avoid using function environments in C libraries (as it probably will be deprecated) --- liolib.c | 59 +++++++++++++++++++++++++++++++++++------------------------ 1 file changed, 35 insertions(+), 24 deletions(-) (limited to 'liolib.c') diff --git a/liolib.c b/liolib.c index 7f22bd8b..fce6b69b 100644 --- a/liolib.c +++ b/liolib.c @@ -1,5 +1,5 @@ /* -** $Id: liolib.c,v 2.85 2009/12/17 16:20:01 roberto Exp roberto $ +** $Id: liolib.c,v 2.86 2010/03/03 18:48:57 roberto Exp roberto $ ** Standard I/O (and system) library ** See Copyright Notice in lua.h */ @@ -103,13 +103,12 @@ static FILE *tofile (lua_State *L) { } - /* ** When creating file handles, always creates a `closed' file handle ** before opening the actual file; so, if there is a memory error, the ** file is not left opened. */ -static FILE **newfile (lua_State *L) { +static FILE **newprefile (lua_State *L) { FILE **pf = (FILE **)lua_newuserdata(L, sizeof(FILE *)); *pf = NULL; /* file handle is currently `closed' */ luaL_getmetatable(L, LUA_FILEHANDLE); @@ -118,6 +117,14 @@ static FILE **newfile (lua_State *L) { } +static FILE **newfile (lua_State *L) { + FILE **pf = newprefile(L); + lua_pushvalue(L, lua_upvalueindex(1)); /* set upvalue... */ + lua_setfenv(L, -2); /* ... as environment for new file */ + return pf; +} + + /* ** function to (not) close the standard files stdin, stdout, and stderr */ @@ -164,7 +171,7 @@ static int aux_close (lua_State *L) { static int io_close (lua_State *L) { if (lua_isnone(L, 1)) - lua_rawgeti(L, LUA_ENVIRONINDEX, IO_OUTPUT); + lua_rawgeti(L, lua_upvalueindex(1), IO_OUTPUT); tofile(L); /* make sure argument is a file */ return aux_close(L); } @@ -229,7 +236,7 @@ static int io_tmpfile (lua_State *L) { static FILE *getiofile (lua_State *L, int findex) { FILE *f; - lua_rawgeti(L, LUA_ENVIRONINDEX, findex); + lua_rawgeti(L, lua_upvalueindex(1), findex); f = *(FILE **)lua_touserdata(L, -1); if (f == NULL) luaL_error(L, "standard %s file is closed", fnames[findex - 1]); @@ -250,10 +257,10 @@ static int g_iofile (lua_State *L, int f, const char *mode) { tofile(L); /* check that it's a valid file handle */ lua_pushvalue(L, 1); } - lua_rawseti(L, LUA_ENVIRONINDEX, f); + lua_rawseti(L, lua_upvalueindex(1), f); } /* return current value */ - lua_rawgeti(L, LUA_ENVIRONINDEX, f); + lua_rawgeti(L, lua_upvalueindex(1), f); return 1; } @@ -295,7 +302,7 @@ static int io_lines (lua_State *L) { int toclose; if (lua_isnone(L, 1)) lua_pushnil(L); /* at least one argument */ if (lua_isnil(L, 1)) { /* no file name? */ - lua_rawgeti(L, LUA_ENVIRONINDEX, IO_INPUT); /* get default input */ + lua_rawgeti(L, lua_upvalueindex(1), IO_INPUT); /* get default input */ lua_replace(L, 1); /* put it at index 1 */ tofile(L); /* check that it's a valid file handle */ toclose = 0; /* do not close it after iteration */ @@ -576,23 +583,27 @@ static void createmeta (lua_State *L) { luaL_newmetatable(L, LUA_FILEHANDLE); /* create metatable for file handles */ lua_pushvalue(L, -1); /* push metatable */ lua_setfield(L, -2, "__index"); /* metatable.__index = metatable */ - luaL_register(L, NULL, flib); /* file methods */ + luaL_register(L, NULL, flib); /* add file methods to new metatable */ + lua_pop(L, 1); /* pop new metatable */ } static void createstdfile (lua_State *L, FILE *f, int k, const char *fname) { - *newfile(L) = f; + *newprefile(L) = f; if (k > 0) { - lua_pushvalue(L, -1); - lua_rawseti(L, LUA_ENVIRONINDEX, k); + lua_pushvalue(L, -1); /* copy new file */ + lua_rawseti(L, 1, k); /* add it to common upvalue */ } - lua_pushvalue(L, -2); /* copy environment */ - lua_setfenv(L, -2); /* set it */ - lua_setfield(L, -3, fname); + lua_pushvalue(L, 3); /* get environment for default files */ + lua_setfenv(L, -2); /* set it as environment for file */ + lua_setfield(L, 2, fname); /* add file to module */ } -static void newfenv (lua_State *L, lua_CFunction cls) { +/* +** pushes a new table with {__close = cls} +*/ +static void newenv (lua_State *L, lua_CFunction cls) { lua_createtable(L, 0, 1); lua_pushcfunction(L, cls); lua_setfield(L, -2, "__close"); @@ -600,21 +611,21 @@ static void newfenv (lua_State *L, lua_CFunction cls) { LUAMOD_API int luaopen_io (lua_State *L) { + lua_settop(L, 0); createmeta(L); /* create (private) environment (with fields IO_INPUT, IO_OUTPUT, __close) */ - newfenv(L, io_fclose); - lua_replace(L, LUA_ENVIRONINDEX); - /* open library */ - luaL_register(L, LUA_IOLIBNAME, iolib); + newenv(L, io_fclose); /* upvalue for all io functions at index 1 */ + lua_pushvalue(L, -1); /* copy to be consumed by 'openlib' */ + luaL_openlib(L, LUA_IOLIBNAME, iolib, 1); /* new module at index 2 */ /* create (and set) default files */ - newfenv(L, io_noclose); /* close function for default files */ + newenv(L, io_noclose); /* environment for default files at index 3 */ createstdfile(L, stdin, IO_INPUT, "stdin"); createstdfile(L, stdout, IO_OUTPUT, "stdout"); createstdfile(L, stderr, 0, "stderr"); lua_pop(L, 1); /* pop environment for default files */ - lua_getfield(L, -1, "popen"); - newfenv(L, io_pclose); /* create environment for 'popen' */ - lua_setfenv(L, -2); /* set fenv for 'popen' */ + lua_getfield(L, 2, "popen"); + newenv(L, io_pclose); /* create environment for 'popen' streams */ + lua_setupvalue(L, -2, 1); /* set it as upvalue for 'popen' */ lua_pop(L, 1); /* pop 'popen' */ return 1; } -- cgit v1.2.3-55-g6feb