| @@ -1,5 +1,5 @@ |
| 1 | /* | 1 | /* |
| 2 | ** $Id: liolib.c,v 2.73.1.2 2008/01/02 13:56:00 roberto Exp $ | 2 | ** $Id: liolib.c,v 2.73.1.3 2008/01/18 17:47:43 roberto Exp $ |
| 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 | */ |
| @@ -51,7 +51,7 @@ static void fileerror (lua_State *L, int arg, const char *filename) { · 45 unmodified lines |
| 51 | } | 51 | } |
| 52 | | 52 | |
| 53 | | 53 | |
| 54 | #define topfile(L) ((FILE **)luaL_checkudata(L, 1, LUA_FILEHANDLE)) | 54 | #define tofilep(L) ((FILE **)luaL_checkudata(L, 1, LUA_FILEHANDLE)) |
| 55 | | 55 | |
| 56 | | 56 | |
| 57 | static int io_type (lua_State *L) { | 57 | static int io_type (lua_State *L) { |
| @@ -70,7 +70,7 @@ static int io_type (lua_State *L) { · 12 unmodified lines |
| 70 | | 70 | |
| 71 | | 71 | |
| 72 | static FILE *tofile (lua_State *L) { | 72 | static FILE *tofile (lua_State *L) { |
| 73 | FILE **f = topfile(L); | 73 | FILE **f = tofilep(L); |
| 74 | if (*f == NULL) | 74 | if (*f == NULL) |
| 75 | luaL_error(L, "attempt to use a closed file"); | 75 | luaL_error(L, "attempt to use a closed file"); |
| 76 | return *f; | 76 | return *f; |
| @@ -93,24 +93,33 @@ static FILE **newfile (lua_State *L) { · 16 unmodified lines |
| 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 = tofilep(L); |
| 101 | int ok = lua_pclose(L, *p); | 110 | int ok = lua_pclose(L, *p); |
| 102 | *p = NULL; | 111 | *p = NULL; |
| 103 | return pushresult(L, ok, NULL); | 112 | return pushresult(L, ok, NULL); |
| 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 = tofilep(L); |
| 109 | int ok = 0; | 121 | int ok = (fclose(*p) == 0); |
| 110 | if (*p != stdin && *p != stdout && *p != stderr) { | 122 | *p = NULL; |
| 111 | ok = (fclose(*p) == 0); | | |
| 112 | *p = NULL; | | |
| 113 | } | | |
| 114 | return pushresult(L, ok, NULL); | 123 | return pushresult(L, ok, NULL); |
| 115 | } | 124 | } |
| 116 | | 125 | |
| @@ -131,17 +140,18 @@ static int io_close (lua_State *L) { · 14 unmodified lines |
| 131 | | 140 | |
| 132 | | 141 | |
| 133 | static int io_gc (lua_State *L) { | 142 | static int io_gc (lua_State *L) { |
| 134 | FILE *f = *topfile(L); | 143 | FILE *f = *tofilep(L); |
| 135 | if (f != NULL) /* ignore closed files */ | 144 | /* ignore closed files */ |
| | 145 | if (f != NULL) |
| 136 | aux_close(L); | 146 | aux_close(L); |
| 137 | return 0; | 147 | return 0; |
| 138 | } | 148 | } |
| 139 | | 149 | |
| 140 | | 150 | |
| 141 | static int io_tostring (lua_State *L) { | 151 | static int io_tostring (lua_State *L) { |
| 142 | FILE *f = *topfile(L); | 152 | FILE *f = *tofilep(L); |
| 143 | if (f == NULL) | 153 | if (f == NULL) |
| 144 | lua_pushstring(L, "file (closed)"); | 154 | lua_pushliteral(L, "file (closed)"); |
| 145 | else | 155 | else |
| 146 | lua_pushfstring(L, "file (%p)", f); | 156 | lua_pushfstring(L, "file (%p)", f); |
| 147 | return 1; | 157 | return 1; |
| @@ -157,6 +167,10 @@ static int io_open (lua_State *L) { · 9 unmodified lines |
| 157 | } | 167 | } |
| 158 | | 168 | |
| 159 | | 169 | |
| | 170 | /* |
| | 171 | ** this function has a separated environment, which defines the |
| | 172 | ** correct __close for 'popen' files |
| | 173 | */ |
| 160 | static int io_popen (lua_State *L) { | 174 | static int io_popen (lua_State *L) { |
| 161 | const char *filename = luaL_checkstring(L, 1); | 175 | const char *filename = luaL_checkstring(L, 1); |
| 162 | const char *mode = luaL_optstring(L, 2, "r"); | 176 | const char *mode = luaL_optstring(L, 2, "r"); |
| @@ -282,7 +296,7 @@ static int read_line (lua_State *L, FILE *f) { · 119 unmodified lines |
| 282 | char *p = luaL_prepbuffer(&b); | 296 | char *p = luaL_prepbuffer(&b); |
| 283 | if (fgets(p, LUAL_BUFFERSIZE, f) == NULL) { /* eof? */ | 297 | if (fgets(p, LUAL_BUFFERSIZE, f) == NULL) { /* eof? */ |
| 284 | luaL_pushresult(&b); /* close buffer */ | 298 | luaL_pushresult(&b); /* close buffer */ |
| 285 | return (lua_strlen(L, -1) > 0); /* check whether read something */ | 299 | return (lua_objlen(L, -1) > 0); /* check whether read something */ |
| 286 | } | 300 | } |
| 287 | l = strlen(p); | 301 | l = strlen(p); |
| 288 | if (l == 0 || p[l-1] != '\n') | 302 | if (l == 0 || p[l-1] != '\n') |
| @@ -310,7 +324,7 @@ static int read_chars (lua_State *L, FILE *f, size_t n) { · 21 unmodified lines |
| 310 | n -= nr; /* still have to read `n' chars */ | 324 | n -= nr; /* still have to read `n' chars */ |
| 311 | } while (n > 0 && nr == rlen); /* until end of count or eof */ | 325 | } while (n > 0 && nr == rlen); /* until end of count or eof */ |
| 312 | luaL_pushresult(&b); /* close buffer */ | 326 | luaL_pushresult(&b); /* close buffer */ |
| 313 | return (n == 0 || lua_strlen(L, -1) > 0); | 327 | return (n == 0 || lua_objlen(L, -1) > 0); |
| 314 | } | 328 | } |
| 315 | | 329 | |
| 316 | | 330 | |
| @@ -504,31 +518,36 @@ static void createstdfile (lua_State *L, FILE *f, int k, const char *fname) { · 187 unmodified lines |
| 504 | lua_pushvalue(L, -1); | 518 | lua_pushvalue(L, -1); |
| 505 | lua_rawseti(L, LUA_ENVIRONINDEX, k); | 519 | lua_rawseti(L, LUA_ENVIRONINDEX, k); |
| 506 | } | 520 | } |
| 507 | 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"); |
| 508 | } | 531 | } |
| 509 | | 532 | |
| 510 | | 533 | |
| 511 | LUALIB_API int luaopen_io (lua_State *L) { | 534 | LUALIB_API int luaopen_io (lua_State *L) { |
| 512 | createmeta(L); | 535 | createmeta(L); |
| 513 | /* create (private) environment (with fields IO_INPUT, IO_OUTPUT, __close) */ | 536 | /* create (private) environment (with fields IO_INPUT, IO_OUTPUT, __close) */ |
| 514 | lua_createtable(L, 2, 1); | 537 | newfenv(L, io_fclose); |
| 515 | lua_replace(L, LUA_ENVIRONINDEX); | 538 | lua_replace(L, LUA_ENVIRONINDEX); |
| 516 | /* open library */ | 539 | /* open library */ |
| 517 | luaL_register(L, LUA_IOLIBNAME, iolib); | 540 | luaL_register(L, LUA_IOLIBNAME, iolib); |
| 518 | /* create (and set) default files */ | 541 | /* create (and set) default files */ |
| | 542 | newfenv(L, io_noclose); /* close function for default files */ |
| 519 | createstdfile(L, stdin, IO_INPUT, "stdin"); | 543 | createstdfile(L, stdin, IO_INPUT, "stdin"); |
| 520 | createstdfile(L, stdout, IO_OUTPUT, "stdout"); | 544 | createstdfile(L, stdout, IO_OUTPUT, "stdout"); |
| 521 | createstdfile(L, stderr, 0, "stderr"); | 545 | createstdfile(L, stderr, 0, "stderr"); |
| 522 | /* create environment for 'popen' */ | 546 | lua_pop(L, 1); /* pop environment for default files */ |
| 523 | lua_getfield(L, -1, "popen"); | 547 | lua_getfield(L, -1, "popen"); |
| 524 | lua_createtable(L, 0, 1); | 548 | newfenv(L, io_pclose); /* create environment for 'popen' */ |
| 525 | lua_pushcfunction(L, io_pclose); | 549 | lua_setfenv(L, -2); /* set fenv for 'popen' */ |
| 526 | lua_setfield(L, -2, "__close"); | | |
| 527 | lua_setfenv(L, -2); | | |
| 528 | lua_pop(L, 1); /* pop 'popen' */ | 550 | lua_pop(L, 1); /* pop 'popen' */ |
| 529 | /* set default close function */ | | |
| 530 | lua_pushcfunction(L, io_fclose); | | |
| 531 | lua_setfield(L, LUA_ENVIRONINDEX, "__close"); | | |
| 532 | return 1; | 551 | return 1; |
| 533 | } | 552 | } |
| 534 | | 553 | |