aboutsummaryrefslogtreecommitdiff
path: root/liolib.c
diff options
context:
space:
mode:
Diffstat (limited to 'liolib.c')
-rw-r--r--liolib.c99
1 files changed, 66 insertions, 33 deletions
diff --git a/liolib.c b/liolib.c
index 692dd666..f80eff99 100644
--- a/liolib.c
+++ b/liolib.c
@@ -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
27static const char *const fnames[] = {"input", "output"}; 27static 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*/
98static 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
106static 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
94static int aux_close (lua_State *L) { 114static 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
107static int io_close (lua_State *L) { 121static 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
114static int io_gc (lua_State *L) { 129static 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
157static 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
141static int io_tmpfile (lua_State *L) { 166static 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
472static void createupval (lua_State *L) { 498static 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
483LUALIB_API int luaopen_io (lua_State *L) { 508LUALIB_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