diff options
| -rw-r--r-- | liolib.c | 51 |
1 files changed, 36 insertions, 15 deletions
| @@ -1,5 +1,5 @@ | |||
| 1 | /* | 1 | /* |
| 2 | ** $Id: liolib.c,v 2.74 2006/06/22 16:12:59 roberto Exp roberto $ | 2 | ** $Id: liolib.c,v 2.75 2006/09/18 14:03:18 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 | */ |
| @@ -93,8 +93,17 @@ static FILE **newfile (lua_State *L) { | |||
| 93 | 93 | ||
| 94 | 94 | ||
| 95 | /* | 95 | /* |
| 96 | ** this function has a separated environment, which defines the | 96 | ** function to (not) close the standard files stdin, stdout, and stderr |
| 97 | ** correct __close for 'popen' files | 97 | */ |
| 98 | static int io_noclose (lua_State *L) { | ||
| 99 | lua_pushnil(L); | ||
| 100 | lua_pushliteral(L, "cannot close standard file"); | ||
| 101 | return 2; | ||
| 102 | } | ||
| 103 | |||
| 104 | |||
| 105 | /* | ||
| 106 | ** function to close 'popen' files | ||
| 98 | */ | 107 | */ |
| 99 | static int io_pclose (lua_State *L) { | 108 | static int io_pclose (lua_State *L) { |
| 100 | FILE **p = topfile(L); | 109 | FILE **p = topfile(L); |
| @@ -104,6 +113,9 @@ static int io_pclose (lua_State *L) { | |||
| 104 | } | 113 | } |
| 105 | 114 | ||
| 106 | 115 | ||
| 116 | /* | ||
| 117 | ** function to close regular files | ||
| 118 | */ | ||
| 107 | static int io_fclose (lua_State *L) { | 119 | static int io_fclose (lua_State *L) { |
| 108 | FILE **p = topfile(L); | 120 | FILE **p = topfile(L); |
| 109 | int ok = (fclose(*p) == 0); | 121 | int ok = (fclose(*p) == 0); |
| @@ -129,8 +141,8 @@ static int io_close (lua_State *L) { | |||
| 129 | 141 | ||
| 130 | static int io_gc (lua_State *L) { | 142 | static int io_gc (lua_State *L) { |
| 131 | FILE *f = *topfile(L); | 143 | FILE *f = *topfile(L); |
| 132 | /* ignore closed files and standard files */ | 144 | /* ignore closed files */ |
| 133 | if (f != NULL && f != stdin && f != stdout && f != stderr) | 145 | if (f != NULL) |
| 134 | aux_close(L); | 146 | aux_close(L); |
| 135 | return 0; | 147 | return 0; |
| 136 | } | 148 | } |
| @@ -155,6 +167,10 @@ static int io_open (lua_State *L) { | |||
| 155 | } | 167 | } |
| 156 | 168 | ||
| 157 | 169 | ||
| 170 | /* | ||
| 171 | ** this function has a separated environment, which defines the | ||
| 172 | ** correct __close for 'popen' files | ||
| 173 | */ | ||
| 158 | static int io_popen (lua_State *L) { | 174 | static int io_popen (lua_State *L) { |
| 159 | const char *filename = luaL_checkstring(L, 1); | 175 | const char *filename = luaL_checkstring(L, 1); |
| 160 | const char *mode = luaL_optstring(L, 2, "r"); | 176 | const char *mode = luaL_optstring(L, 2, "r"); |
| @@ -502,31 +518,36 @@ static void createstdfile (lua_State *L, FILE *f, int k, const char *fname) { | |||
| 502 | lua_pushvalue(L, -1); | 518 | lua_pushvalue(L, -1); |
| 503 | lua_rawseti(L, LUA_ENVIRONINDEX, k); | 519 | lua_rawseti(L, LUA_ENVIRONINDEX, k); |
| 504 | } | 520 | } |
| 505 | lua_setfield(L, -2, fname); | 521 | lua_pushvalue(L, -2); /* copy environment */ |
| 522 | lua_setfenv(L, -2); /* set it */ | ||
| 523 | lua_setfield(L, -3, fname); | ||
| 524 | } | ||
| 525 | |||
| 526 | |||
| 527 | static void newfenv (lua_State *L, lua_CFunction cls) { | ||
| 528 | lua_createtable(L, 0, 1); | ||
| 529 | lua_pushcfunction(L, cls); | ||
| 530 | lua_setfield(L, -2, "__close"); | ||
| 506 | } | 531 | } |
| 507 | 532 | ||
| 508 | 533 | ||
| 509 | LUALIB_API int luaopen_io (lua_State *L) { | 534 | LUALIB_API int luaopen_io (lua_State *L) { |
| 510 | createmeta(L); | 535 | createmeta(L); |
| 511 | /* create (private) environment (with fields IO_INPUT, IO_OUTPUT, __close) */ | 536 | /* create (private) environment (with fields IO_INPUT, IO_OUTPUT, __close) */ |
| 512 | lua_createtable(L, 2, 1); | 537 | newfenv(L, io_fclose); |
| 513 | lua_replace(L, LUA_ENVIRONINDEX); | 538 | lua_replace(L, LUA_ENVIRONINDEX); |
| 514 | /* open library */ | 539 | /* open library */ |
| 515 | luaL_register(L, LUA_IOLIBNAME, iolib); | 540 | luaL_register(L, LUA_IOLIBNAME, iolib); |
| 516 | /* create (and set) default files */ | 541 | /* create (and set) default files */ |
| 542 | newfenv(L, io_noclose); /* close function for default files */ | ||
| 517 | createstdfile(L, stdin, IO_INPUT, "stdin"); | 543 | createstdfile(L, stdin, IO_INPUT, "stdin"); |
| 518 | createstdfile(L, stdout, IO_OUTPUT, "stdout"); | 544 | createstdfile(L, stdout, IO_OUTPUT, "stdout"); |
| 519 | createstdfile(L, stderr, 0, "stderr"); | 545 | createstdfile(L, stderr, 0, "stderr"); |
| 520 | /* create environment for 'popen' */ | 546 | lua_pop(L, 1); /* pop environment for default files */ |
| 521 | lua_getfield(L, -1, "popen"); | 547 | lua_getfield(L, -1, "popen"); |
| 522 | lua_createtable(L, 0, 1); | 548 | newfenv(L, io_pclose); /* create environment for 'popen' */ |
| 523 | lua_pushcfunction(L, io_pclose); | 549 | lua_setfenv(L, -2); /* set fenv for 'popen' */ |
| 524 | lua_setfield(L, -2, "__close"); | ||
| 525 | lua_setfenv(L, -2); | ||
| 526 | lua_pop(L, 1); /* pop 'popen' */ | 550 | lua_pop(L, 1); /* pop 'popen' */ |
| 527 | /* set default close function */ | ||
| 528 | lua_pushcfunction(L, io_fclose); | ||
| 529 | lua_setfield(L, LUA_ENVIRONINDEX, "__close"); | ||
| 530 | return 1; | 551 | return 1; |
| 531 | } | 552 | } |
| 532 | 553 | ||
