diff options
Diffstat (limited to 'liolib.c')
-rw-r--r-- | liolib.c | 59 |
1 files changed, 35 insertions, 24 deletions
@@ -1,5 +1,5 @@ | |||
1 | /* | 1 | /* |
2 | ** $Id: liolib.c,v 2.85 2009/12/17 16:20:01 roberto Exp roberto $ | 2 | ** $Id: liolib.c,v 2.86 2010/03/03 18:48:57 roberto Exp roberto $ |
3 | ** Standard I/O (and system) library | 3 | ** Standard I/O (and system) library |
4 | ** See Copyright Notice in lua.h | 4 | ** See Copyright Notice in lua.h |
5 | */ | 5 | */ |
@@ -103,13 +103,12 @@ static FILE *tofile (lua_State *L) { | |||
103 | } | 103 | } |
104 | 104 | ||
105 | 105 | ||
106 | |||
107 | /* | 106 | /* |
108 | ** When creating file handles, always creates a `closed' file handle | 107 | ** When creating file handles, always creates a `closed' file handle |
109 | ** before opening the actual file; so, if there is a memory error, the | 108 | ** before opening the actual file; so, if there is a memory error, the |
110 | ** file is not left opened. | 109 | ** file is not left opened. |
111 | */ | 110 | */ |
112 | static FILE **newfile (lua_State *L) { | 111 | static FILE **newprefile (lua_State *L) { |
113 | FILE **pf = (FILE **)lua_newuserdata(L, sizeof(FILE *)); | 112 | FILE **pf = (FILE **)lua_newuserdata(L, sizeof(FILE *)); |
114 | *pf = NULL; /* file handle is currently `closed' */ | 113 | *pf = NULL; /* file handle is currently `closed' */ |
115 | luaL_getmetatable(L, LUA_FILEHANDLE); | 114 | luaL_getmetatable(L, LUA_FILEHANDLE); |
@@ -118,6 +117,14 @@ static FILE **newfile (lua_State *L) { | |||
118 | } | 117 | } |
119 | 118 | ||
120 | 119 | ||
120 | static FILE **newfile (lua_State *L) { | ||
121 | FILE **pf = newprefile(L); | ||
122 | lua_pushvalue(L, lua_upvalueindex(1)); /* set upvalue... */ | ||
123 | lua_setfenv(L, -2); /* ... as environment for new file */ | ||
124 | return pf; | ||
125 | } | ||
126 | |||
127 | |||
121 | /* | 128 | /* |
122 | ** function to (not) close the standard files stdin, stdout, and stderr | 129 | ** function to (not) close the standard files stdin, stdout, and stderr |
123 | */ | 130 | */ |
@@ -164,7 +171,7 @@ static int aux_close (lua_State *L) { | |||
164 | 171 | ||
165 | static int io_close (lua_State *L) { | 172 | static int io_close (lua_State *L) { |
166 | if (lua_isnone(L, 1)) | 173 | if (lua_isnone(L, 1)) |
167 | lua_rawgeti(L, LUA_ENVIRONINDEX, IO_OUTPUT); | 174 | lua_rawgeti(L, lua_upvalueindex(1), IO_OUTPUT); |
168 | tofile(L); /* make sure argument is a file */ | 175 | tofile(L); /* make sure argument is a file */ |
169 | return aux_close(L); | 176 | return aux_close(L); |
170 | } | 177 | } |
@@ -229,7 +236,7 @@ static int io_tmpfile (lua_State *L) { | |||
229 | 236 | ||
230 | static FILE *getiofile (lua_State *L, int findex) { | 237 | static FILE *getiofile (lua_State *L, int findex) { |
231 | FILE *f; | 238 | FILE *f; |
232 | lua_rawgeti(L, LUA_ENVIRONINDEX, findex); | 239 | lua_rawgeti(L, lua_upvalueindex(1), findex); |
233 | f = *(FILE **)lua_touserdata(L, -1); | 240 | f = *(FILE **)lua_touserdata(L, -1); |
234 | if (f == NULL) | 241 | if (f == NULL) |
235 | luaL_error(L, "standard %s file is closed", fnames[findex - 1]); | 242 | 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) { | |||
250 | tofile(L); /* check that it's a valid file handle */ | 257 | tofile(L); /* check that it's a valid file handle */ |
251 | lua_pushvalue(L, 1); | 258 | lua_pushvalue(L, 1); |
252 | } | 259 | } |
253 | lua_rawseti(L, LUA_ENVIRONINDEX, f); | 260 | lua_rawseti(L, lua_upvalueindex(1), f); |
254 | } | 261 | } |
255 | /* return current value */ | 262 | /* return current value */ |
256 | lua_rawgeti(L, LUA_ENVIRONINDEX, f); | 263 | lua_rawgeti(L, lua_upvalueindex(1), f); |
257 | return 1; | 264 | return 1; |
258 | } | 265 | } |
259 | 266 | ||
@@ -295,7 +302,7 @@ static int io_lines (lua_State *L) { | |||
295 | int toclose; | 302 | int toclose; |
296 | if (lua_isnone(L, 1)) lua_pushnil(L); /* at least one argument */ | 303 | if (lua_isnone(L, 1)) lua_pushnil(L); /* at least one argument */ |
297 | if (lua_isnil(L, 1)) { /* no file name? */ | 304 | if (lua_isnil(L, 1)) { /* no file name? */ |
298 | lua_rawgeti(L, LUA_ENVIRONINDEX, IO_INPUT); /* get default input */ | 305 | lua_rawgeti(L, lua_upvalueindex(1), IO_INPUT); /* get default input */ |
299 | lua_replace(L, 1); /* put it at index 1 */ | 306 | lua_replace(L, 1); /* put it at index 1 */ |
300 | tofile(L); /* check that it's a valid file handle */ | 307 | tofile(L); /* check that it's a valid file handle */ |
301 | toclose = 0; /* do not close it after iteration */ | 308 | toclose = 0; /* do not close it after iteration */ |
@@ -576,23 +583,27 @@ static void createmeta (lua_State *L) { | |||
576 | luaL_newmetatable(L, LUA_FILEHANDLE); /* create metatable for file handles */ | 583 | luaL_newmetatable(L, LUA_FILEHANDLE); /* create metatable for file handles */ |
577 | lua_pushvalue(L, -1); /* push metatable */ | 584 | lua_pushvalue(L, -1); /* push metatable */ |
578 | lua_setfield(L, -2, "__index"); /* metatable.__index = metatable */ | 585 | lua_setfield(L, -2, "__index"); /* metatable.__index = metatable */ |
579 | luaL_register(L, NULL, flib); /* file methods */ | 586 | luaL_register(L, NULL, flib); /* add file methods to new metatable */ |
587 | lua_pop(L, 1); /* pop new metatable */ | ||
580 | } | 588 | } |
581 | 589 | ||
582 | 590 | ||
583 | static void createstdfile (lua_State *L, FILE *f, int k, const char *fname) { | 591 | static void createstdfile (lua_State *L, FILE *f, int k, const char *fname) { |
584 | *newfile(L) = f; | 592 | *newprefile(L) = f; |
585 | if (k > 0) { | 593 | if (k > 0) { |
586 | lua_pushvalue(L, -1); | 594 | lua_pushvalue(L, -1); /* copy new file */ |
587 | lua_rawseti(L, LUA_ENVIRONINDEX, k); | 595 | lua_rawseti(L, 1, k); /* add it to common upvalue */ |
588 | } | 596 | } |
589 | lua_pushvalue(L, -2); /* copy environment */ | 597 | lua_pushvalue(L, 3); /* get environment for default files */ |
590 | lua_setfenv(L, -2); /* set it */ | 598 | lua_setfenv(L, -2); /* set it as environment for file */ |
591 | lua_setfield(L, -3, fname); | 599 | lua_setfield(L, 2, fname); /* add file to module */ |
592 | } | 600 | } |
593 | 601 | ||
594 | 602 | ||
595 | static void newfenv (lua_State *L, lua_CFunction cls) { | 603 | /* |
604 | ** pushes a new table with {__close = cls} | ||
605 | */ | ||
606 | static void newenv (lua_State *L, lua_CFunction cls) { | ||
596 | lua_createtable(L, 0, 1); | 607 | lua_createtable(L, 0, 1); |
597 | lua_pushcfunction(L, cls); | 608 | lua_pushcfunction(L, cls); |
598 | lua_setfield(L, -2, "__close"); | 609 | lua_setfield(L, -2, "__close"); |
@@ -600,21 +611,21 @@ static void newfenv (lua_State *L, lua_CFunction cls) { | |||
600 | 611 | ||
601 | 612 | ||
602 | LUAMOD_API int luaopen_io (lua_State *L) { | 613 | LUAMOD_API int luaopen_io (lua_State *L) { |
614 | lua_settop(L, 0); | ||
603 | createmeta(L); | 615 | createmeta(L); |
604 | /* create (private) environment (with fields IO_INPUT, IO_OUTPUT, __close) */ | 616 | /* create (private) environment (with fields IO_INPUT, IO_OUTPUT, __close) */ |
605 | newfenv(L, io_fclose); | 617 | newenv(L, io_fclose); /* upvalue for all io functions at index 1 */ |
606 | lua_replace(L, LUA_ENVIRONINDEX); | 618 | lua_pushvalue(L, -1); /* copy to be consumed by 'openlib' */ |
607 | /* open library */ | 619 | luaL_openlib(L, LUA_IOLIBNAME, iolib, 1); /* new module at index 2 */ |
608 | luaL_register(L, LUA_IOLIBNAME, iolib); | ||
609 | /* create (and set) default files */ | 620 | /* create (and set) default files */ |
610 | newfenv(L, io_noclose); /* close function for default files */ | 621 | newenv(L, io_noclose); /* environment for default files at index 3 */ |
611 | createstdfile(L, stdin, IO_INPUT, "stdin"); | 622 | createstdfile(L, stdin, IO_INPUT, "stdin"); |
612 | createstdfile(L, stdout, IO_OUTPUT, "stdout"); | 623 | createstdfile(L, stdout, IO_OUTPUT, "stdout"); |
613 | createstdfile(L, stderr, 0, "stderr"); | 624 | createstdfile(L, stderr, 0, "stderr"); |
614 | lua_pop(L, 1); /* pop environment for default files */ | 625 | lua_pop(L, 1); /* pop environment for default files */ |
615 | lua_getfield(L, -1, "popen"); | 626 | lua_getfield(L, 2, "popen"); |
616 | newfenv(L, io_pclose); /* create environment for 'popen' */ | 627 | newenv(L, io_pclose); /* create environment for 'popen' streams */ |
617 | lua_setfenv(L, -2); /* set fenv for 'popen' */ | 628 | lua_setupvalue(L, -2, 1); /* set it as upvalue for 'popen' */ |
618 | lua_pop(L, 1); /* pop 'popen' */ | 629 | lua_pop(L, 1); /* pop 'popen' */ |
619 | return 1; | 630 | return 1; |
620 | } | 631 | } |