diff options
| author | Roberto Ierusalimschy <roberto@inf.puc-rio.br> | 2005-06-06 10:30:52 -0300 |
|---|---|---|
| committer | Roberto Ierusalimschy <roberto@inf.puc-rio.br> | 2005-06-06 10:30:52 -0300 |
| commit | 86add535d8ee1936c8ff2e9e74e8024377e7b296 (patch) | |
| tree | c421843bdd6a3d884bb3e746bfcd70a709d4aa1a /liolib.c | |
| parent | d987cf1f812b131788029d6de0c81ed64020e522 (diff) | |
| download | lua-86add535d8ee1936c8ff2e9e74e8024377e7b296.tar.gz lua-86add535d8ee1936c8ff2e9e74e8024377e7b296.tar.bz2 lua-86add535d8ee1936c8ff2e9e74e8024377e7b296.zip | |
'popen' is back
Diffstat (limited to 'liolib.c')
| -rw-r--r-- | liolib.c | 99 |
1 files changed, 66 insertions, 33 deletions
| @@ -1,5 +1,5 @@ | |||
| 1 | /* | 1 | /* |
| 2 | ** $Id: liolib.c,v 2.60 2005/05/16 21:19:00 roberto Exp roberto $ | 2 | ** $Id: liolib.c,v 2.61 2005/05/25 13:21:26 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 | */ |
| @@ -20,8 +20,8 @@ | |||
| 20 | 20 | ||
| 21 | 21 | ||
| 22 | 22 | ||
| 23 | #define IO_INPUT 1 | 23 | #define IO_INPUT 1 |
| 24 | #define IO_OUTPUT 2 | 24 | #define IO_OUTPUT 2 |
| 25 | 25 | ||
| 26 | 26 | ||
| 27 | static const char *const fnames[] = {"input", "output"}; | 27 | static const char *const fnames[] = {"input", "output"}; |
| @@ -91,29 +91,45 @@ static FILE **newfile (lua_State *L) { | |||
| 91 | } | 91 | } |
| 92 | 92 | ||
| 93 | 93 | ||
| 94 | /* | ||
| 95 | ** this function has a separated environment, which defines the | ||
| 96 | ** correct __close for 'popen' files | ||
| 97 | */ | ||
| 98 | static int io_pclose (lua_State *L) { | ||
| 99 | FILE **p = topfile(L); | ||
| 100 | int ok = lua_pclose(L, *p); | ||
| 101 | if (ok) *p = NULL; | ||
| 102 | return pushresult(L, ok, NULL); | ||
| 103 | } | ||
| 104 | |||
| 105 | |||
| 106 | static int io_fclose (lua_State *L) { | ||
| 107 | FILE **p = topfile(L); | ||
| 108 | int ok = (fclose(*p) == 0); | ||
| 109 | if (ok) *p = NULL; | ||
| 110 | return pushresult(L, ok, NULL); | ||
| 111 | } | ||
| 112 | |||
| 113 | |||
| 94 | static int aux_close (lua_State *L) { | 114 | static int aux_close (lua_State *L) { |
| 95 | FILE *f = tofile(L); | 115 | lua_getfenv(L, 1); |
| 96 | if (f == stdin || f == stdout || f == stderr) | 116 | lua_getfield(L, -1, "__close"); |
| 97 | return 0; /* file cannot be closed */ | 117 | return (lua_tocfunction(L, -1))(L); |
| 98 | else { | ||
| 99 | int ok = (fclose(f) == 0); | ||
| 100 | if (ok) | ||
| 101 | *(FILE **)lua_touserdata(L, 1) = NULL; /* mark file as closed */ | ||
| 102 | return ok; | ||
| 103 | } | ||
| 104 | } | 118 | } |
| 105 | 119 | ||
| 106 | 120 | ||
| 107 | static int io_close (lua_State *L) { | 121 | static int io_close (lua_State *L) { |
| 108 | if (lua_isnone(L, 1)) | 122 | if (lua_isnone(L, 1)) |
| 109 | lua_rawgeti(L, LUA_ENVIRONINDEX, IO_OUTPUT); | 123 | lua_rawgeti(L, LUA_ENVIRONINDEX, IO_OUTPUT); |
| 110 | return pushresult(L, aux_close(L), NULL); | 124 | tofile(L); /* make sure argument is a file */ |
| 125 | return aux_close(L); | ||
| 111 | } | 126 | } |
| 112 | 127 | ||
| 113 | 128 | ||
| 114 | static int io_gc (lua_State *L) { | 129 | static int io_gc (lua_State *L) { |
| 115 | FILE **f = topfile(L); | 130 | FILE *f = *topfile(L); |
| 116 | if (*f != NULL) /* ignore closed files */ | 131 | /* ignore closed files and standard files */ |
| 132 | if (f != NULL && f != stdin && f != stdout && f != stderr) | ||
| 117 | aux_close(L); | 133 | aux_close(L); |
| 118 | return 0; | 134 | return 0; |
| 119 | } | 135 | } |
| @@ -138,6 +154,15 @@ static int io_open (lua_State *L) { | |||
| 138 | } | 154 | } |
| 139 | 155 | ||
| 140 | 156 | ||
| 157 | static int io_popen (lua_State *L) { | ||
| 158 | const char *filename = luaL_checkstring(L, 1); | ||
| 159 | const char *mode = luaL_optstring(L, 2, "r"); | ||
| 160 | FILE **pf = newfile(L); | ||
| 161 | *pf = lua_popen(L, filename, mode); | ||
| 162 | return (*pf == NULL) ? pushresult(L, 0, filename) : 1; | ||
| 163 | } | ||
| 164 | |||
| 165 | |||
| 141 | static int io_tmpfile (lua_State *L) { | 166 | static int io_tmpfile (lua_State *L) { |
| 142 | FILE **pf = newfile(L); | 167 | FILE **pf = newfile(L); |
| 143 | *pf = tmpfile(); | 168 | *pf = tmpfile(); |
| @@ -352,7 +377,7 @@ static int io_readline (lua_State *L) { | |||
| 352 | luaL_error(L, "file is already closed"); | 377 | luaL_error(L, "file is already closed"); |
| 353 | sucess = read_line(L, f); | 378 | sucess = read_line(L, f); |
| 354 | if (ferror(f)) | 379 | if (ferror(f)) |
| 355 | luaL_error(L, "%s", strerror(errno)); | 380 | return luaL_error(L, "%s", strerror(errno)); |
| 356 | if (sucess) return 1; | 381 | if (sucess) return 1; |
| 357 | else { /* EOF */ | 382 | else { /* EOF */ |
| 358 | if (lua_toboolean(L, lua_upvalueindex(2))) { /* generator created file? */ | 383 | if (lua_toboolean(L, lua_upvalueindex(2))) { /* generator created file? */ |
| @@ -439,6 +464,7 @@ static const luaL_reg iolib[] = { | |||
| 439 | {"close", io_close}, | 464 | {"close", io_close}, |
| 440 | {"flush", io_flush}, | 465 | {"flush", io_flush}, |
| 441 | {"open", io_open}, | 466 | {"open", io_open}, |
| 467 | {"popen", io_popen}, | ||
| 442 | {"read", io_read}, | 468 | {"read", io_read}, |
| 443 | {"tmpfile", io_tmpfile}, | 469 | {"tmpfile", io_tmpfile}, |
| 444 | {"type", io_type}, | 470 | {"type", io_type}, |
| @@ -469,30 +495,37 @@ static void createmeta (lua_State *L) { | |||
| 469 | } | 495 | } |
| 470 | 496 | ||
| 471 | 497 | ||
| 472 | static void createupval (lua_State *L) { | 498 | static void createstdfile (lua_State *L, FILE *f, int k, const char *fname) { |
| 473 | lua_newtable(L); | 499 | *newfile(L) = f; |
| 474 | /* create (and set) default files */ | 500 | if (k > 0) { |
| 475 | *newfile(L) = stdin; | 501 | lua_pushvalue(L, -1); |
| 476 | lua_rawseti(L, -2, IO_INPUT); | 502 | lua_rawseti(L, LUA_ENVIRONINDEX, k); |
| 477 | *newfile(L) = stdout; | 503 | } |
| 478 | lua_rawseti(L, -2, IO_OUTPUT); | 504 | lua_setfield(L, -2, fname); |
| 479 | } | 505 | } |
| 480 | 506 | ||
| 481 | 507 | ||
| 482 | |||
| 483 | LUALIB_API int luaopen_io (lua_State *L) { | 508 | LUALIB_API int luaopen_io (lua_State *L) { |
| 484 | createmeta(L); | 509 | createmeta(L); |
| 485 | createupval(L); | 510 | /* create new (private) environment */ |
| 486 | lua_pushvalue(L, -1); | 511 | lua_newtable(L); |
| 487 | lua_replace(L, LUA_ENVIRONINDEX); | 512 | lua_replace(L, LUA_ENVIRONINDEX); |
| 513 | /* open library */ | ||
| 488 | luaL_openlib(L, LUA_IOLIBNAME, iolib, 0); | 514 | luaL_openlib(L, LUA_IOLIBNAME, iolib, 0); |
| 489 | /* put predefined file handles into `io' table */ | 515 | /* create (and set) default files */ |
| 490 | lua_rawgeti(L, -2, IO_INPUT); /* get current input from upval */ | 516 | createstdfile(L, stdin, IO_INPUT, "stdin"); |
| 491 | lua_setfield(L, -2, "stdin"); /* io.stdin = upval[IO_INPUT] */ | 517 | createstdfile(L, stdout, IO_OUTPUT, "stdout"); |
| 492 | lua_rawgeti(L, -2, IO_OUTPUT); /* get current output from upval */ | 518 | createstdfile(L, stderr, 0, "stderr"); |
| 493 | lua_setfield(L, -2, "stdout"); /* io.stdout = upval[IO_OUTPUT] */ | 519 | /* create environment for 'popen' */ |
| 494 | *newfile(L) = stderr; | 520 | lua_getfield(L, -1, "popen"); |
| 495 | lua_setfield(L, -2, "stderr"); /* io.stderr = newfile(stderr) */ | 521 | lua_newtable(L); |
| 522 | lua_pushcfunction(L, io_pclose); | ||
| 523 | lua_setfield(L, -2, "__close"); | ||
| 524 | lua_setfenv(L, -2); | ||
| 525 | lua_pop(L, 1); /* pop 'popen' */ | ||
| 526 | /* set default close function */ | ||
| 527 | lua_pushcfunction(L, io_fclose); | ||
| 528 | lua_setfield(L, LUA_ENVIRONINDEX, "__close"); | ||
| 496 | return 1; | 529 | return 1; |
| 497 | } | 530 | } |
| 498 | 531 | ||
