| @@ -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 | 3 | ** Standard I/O (and system) library |
| 4 | 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 | 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 | 72 | static FILE *tofile (lua_State *L) { |
| 73 | | − FILE **f = topfile(L); |
| 73 | + FILE **f = tofilep(L); |
| 74 | 74 | if (*f == NULL) |
| 75 | 75 | luaL_error(L, "attempt to use a closed file"); |
| 76 | 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 |
| 97 | | −** correct __close for 'popen' files |
| 96 | +** function to (not) close the standard files stdin, stdout, and stderr |
| 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 | 108 | static int io_pclose (lua_State *L) { |
| 100 | | − FILE **p = topfile(L); |
| 109 | + FILE **p = tofilep(L); |
| 101 | 110 | int ok = lua_pclose(L, *p); |
| 102 | 111 | *p = NULL; |
| 103 | 112 | return pushresult(L, ok, NULL); |
| 104 | 113 | } |
| 105 | 114 | |
| 106 | 115 | |
| 116 | +/* |
| 117 | +** function to close regular files |
| 118 | +*/ |
| 107 | 119 | static int io_fclose (lua_State *L) { |
| 108 | | − FILE **p = topfile(L); |
| 109 | | − int ok = 0; |
| 110 | | − if (*p != stdin && *p != stdout && *p != stderr) { |
| 111 | | − ok = (fclose(*p) == 0); |
| 112 | | − *p = NULL; |
| 113 | | − } |
| 120 | + FILE **p = tofilep(L); |
| 121 | + int ok = (fclose(*p) == 0); |
| 122 | + *p = NULL; |
| 114 | 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 | 142 | static int io_gc (lua_State *L) { |
| 134 | | − FILE *f = *topfile(L); |
| 135 | | − if (f != NULL) /* ignore closed files */ |
| 143 | + FILE *f = *tofilep(L); |
| 144 | + /* ignore closed files */ |
| 145 | + if (f != NULL) |
| 136 | 146 | aux_close(L); |
| 137 | 147 | return 0; |
| 138 | 148 | } |
| 139 | 149 | |
| 140 | 150 | |
| 141 | 151 | static int io_tostring (lua_State *L) { |
| 142 | | − FILE *f = *topfile(L); |
| 152 | + FILE *f = *tofilep(L); |
| 143 | 153 | if (f == NULL) |
| 144 | | − lua_pushstring(L, "file (closed)"); |
| 154 | + lua_pushliteral(L, "file (closed)"); |
| 145 | 155 | else |
| 146 | 156 | lua_pushfstring(L, "file (%p)", f); |
| 147 | 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 | 174 | static int io_popen (lua_State *L) { |
| 161 | 175 | const char *filename = luaL_checkstring(L, 1); |
| 162 | 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 | 296 | char *p = luaL_prepbuffer(&b); |
| 283 | 297 | if (fgets(p, LUAL_BUFFERSIZE, f) == NULL) { /* eof? */ |
| 284 | 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 | 301 | l = strlen(p); |
| 288 | 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 | 324 | n -= nr; /* still have to read `n' chars */ |
| 311 | 325 | } while (n > 0 && nr == rlen); /* until end of count or eof */ |
| 312 | 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 | 518 | lua_pushvalue(L, -1); |
| 505 | 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 | 534 | LUALIB_API int luaopen_io (lua_State *L) { |
| 512 | 535 | createmeta(L); |
| 513 | 536 | /* create (private) environment (with fields IO_INPUT, IO_OUTPUT, __close) */ |
| 514 | | − lua_createtable(L, 2, 1); |
| 537 | + newfenv(L, io_fclose); |
| 515 | 538 | lua_replace(L, LUA_ENVIRONINDEX); |
| 516 | 539 | /* open library */ |
| 517 | 540 | luaL_register(L, LUA_IOLIBNAME, iolib); |
| 518 | 541 | /* create (and set) default files */ |
| 542 | + newfenv(L, io_noclose); /* close function for default files */ |
| 519 | 543 | createstdfile(L, stdin, IO_INPUT, "stdin"); |
| 520 | 544 | createstdfile(L, stdout, IO_OUTPUT, "stdout"); |
| 521 | 545 | createstdfile(L, stderr, 0, "stderr"); |
| 522 | | − /* create environment for 'popen' */ |
| 546 | + lua_pop(L, 1); /* pop environment for default files */ |
| 523 | 547 | lua_getfield(L, -1, "popen"); |
| 524 | | − lua_createtable(L, 0, 1); |
| 525 | | − lua_pushcfunction(L, io_pclose); |
| 526 | | − lua_setfield(L, -2, "__close"); |
| 527 | | − lua_setfenv(L, -2); |
| 548 | + newfenv(L, io_pclose); /* create environment for 'popen' */ |
| 549 | + lua_setfenv(L, -2); /* set fenv for 'popen' */ |
| 528 | 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 | 551 | return 1; |
| 533 | 552 | } |
| 534 | 553 | |