summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--liolib.c90
1 files changed, 69 insertions, 21 deletions
diff --git a/liolib.c b/liolib.c
index 9938129e..042657be 100644
--- a/liolib.c
+++ b/liolib.c
@@ -1,5 +1,5 @@
1/* 1/*
2** $Id: liolib.c,v 2.16 2002/08/16 20:02:13 roberto Exp roberto $ 2** $Id: liolib.c,v 2.17 2002/08/21 14:57:48 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*/
@@ -32,7 +32,6 @@
32 32
33 33
34#define FILEHANDLE "FileHandle" 34#define FILEHANDLE "FileHandle"
35#define CLOSEDFILEHANDLE "ClosedFileHandle"
36 35
37#define IO_INPUT "_input" 36#define IO_INPUT "_input"
38#define IO_OUTPUT "_output" 37#define IO_OUTPUT "_output"
@@ -54,13 +53,17 @@ static int pushresult (lua_State *L, int i) {
54 53
55static FILE *tofile (lua_State *L, int findex) { 54static FILE *tofile (lua_State *L, int findex) {
56 FILE **f = (FILE **)lua_touserdata(L, findex); 55 FILE **f = (FILE **)lua_touserdata(L, findex);
57 if (f && lua_getmetatable(L, findex) && 56 if (f && *f && lua_getmetatable(L, findex) &&
58 lua_rawequal(L, -1, lua_upvalueindex(1))) { 57 lua_rawequal(L, -1, lua_upvalueindex(1))) {
59 lua_pop(L, 1); 58 lua_pop(L, 1);
60 return *f; 59 return *f;
61 } 60 }
62 if (findex > 0) 61 if (findex > 0) {
63 luaL_argerror(L, findex, "bad file"); 62 if (f && *f == NULL)
63 luaL_error(L, "attempt to use a closed file");
64 else
65 luaL_argerror(L, findex, "bad file");
66 }
64 return NULL; 67 return NULL;
65} 68}
66 69
@@ -96,22 +99,29 @@ static int setnewfile (lua_State *L, FILE *f) {
96} 99}
97 100
98 101
102static int aux_close (lua_State *L) {
103 FILE *f = tofile(L, 1);
104 if (f == stdin || f == stdout || f == stderr)
105 return 0; /* file cannot be closed */
106 *(FILE **)lua_touserdata(L, 1) = NULL; /* mark file as closed */
107 return (pclose(f) != -1) || (fclose(f) == 0);
108}
109
110
99static int io_close (lua_State *L) { 111static int io_close (lua_State *L) {
100 FILE *f;
101 int status = 1;
102 if (lua_isnone(L, 1)) { 112 if (lua_isnone(L, 1)) {
103 lua_pushstring(L, IO_OUTPUT); 113 lua_pushstring(L, IO_OUTPUT);
104 lua_rawget(L, lua_upvalueindex(1)); 114 lua_rawget(L, lua_upvalueindex(1));
105 } 115 }
106 f = tofile(L, 1); 116 return pushresult(L, aux_close(L));
107 if (f != stdin && f != stdout && f != stderr) { 117}
108 lua_settop(L, 1); /* make sure file is on top */ 118
109 lua_pushliteral(L, CLOSEDFILEHANDLE); 119
110 lua_rawget(L, LUA_REGISTRYINDEX); 120static int io_gc (lua_State *L) {
111 lua_setmetatable(L, 1); 121 FILE **f = (FILE **)lua_touserdata(L, 1);
112 status = (pclose(f) != -1) || (fclose(f) == 0); 122 if (!(f && *f == NULL)) /* ignore closed files */
113 } 123 aux_close(L);
114 return pushresult(L, status); 124 return 0;
115} 125}
116 126
117 127
@@ -182,6 +192,30 @@ static int io_output (lua_State *L) {
182} 192}
183 193
184 194
195static int io_readline (lua_State *L);
196
197static int io_lines (lua_State *L) {
198 FILE *f = fopen(luaL_check_string(L, 1), "r");
199 luaL_arg_check(L, f, 1, strerror(errno));
200 lua_pushliteral(L, FILEHANDLE);
201 lua_rawget(L, LUA_REGISTRYINDEX);
202 newfile(L, f);
203 lua_pushboolean(L, 1); /* must close file when finished */
204 lua_pushcclosure(L, io_readline, 3);
205 return 1;
206}
207
208static int f_lines (lua_State *L) {
209 tofile(L, 1); /* check that it's a valid file handle */
210 lua_pushliteral(L, FILEHANDLE);
211 lua_rawget(L, LUA_REGISTRYINDEX);
212 lua_pushvalue(L, 1);
213 lua_pushboolean(L, 0); /* does not close file when finished */
214 lua_pushcclosure(L, io_readline, 3);
215 return 1;
216}
217
218
185/* 219/*
186** {====================================================== 220** {======================================================
187** READ 221** READ
@@ -303,6 +337,22 @@ static int f_read (lua_State *L) {
303 return g_read(L, tofile(L, 1), 2); 337 return g_read(L, tofile(L, 1), 2);
304} 338}
305 339
340
341static int io_readline (lua_State *L) {
342 FILE *f = *(FILE **)lua_touserdata(L, lua_upvalueindex(2));
343 if (f == NULL) /* file is already closed? */
344 luaL_error(L, "file is already closed");
345 if (read_line(L, f)) return 1;
346 else { /* EOF */
347 if (lua_toboolean(L, lua_upvalueindex(3))) { /* generator created file? */
348 lua_settop(L, 0);
349 lua_pushvalue(L, lua_upvalueindex(2));
350 aux_close(L); /* close it */
351 }
352 return 0;
353 }
354}
355
306/* }====================================================== */ 356/* }====================================================== */
307 357
308 358
@@ -366,6 +416,7 @@ static int f_flush (lua_State *L) {
366static const luaL_reg iolib[] = { 416static const luaL_reg iolib[] = {
367 {"input", io_input}, 417 {"input", io_input},
368 {"output", io_output}, 418 {"output", io_output},
419 {"lines", io_lines},
369 {"close", io_close}, 420 {"close", io_close},
370 {"flush", io_flush}, 421 {"flush", io_flush},
371 {"open", io_open}, 422 {"open", io_open},
@@ -380,6 +431,7 @@ static const luaL_reg iolib[] = {
380static const luaL_reg flib[] = { 431static const luaL_reg flib[] = {
381 {"flush", f_flush}, 432 {"flush", f_flush},
382 {"read", f_read}, 433 {"read", f_read},
434 {"lines", f_lines},
383 {"seek", f_seek}, 435 {"seek", f_seek},
384 {"write", f_write}, 436 {"write", f_write},
385 {"close", io_close}, 437 {"close", io_close},
@@ -393,7 +445,7 @@ static void createmeta (lua_State *L) {
393 /* close files when collected */ 445 /* close files when collected */
394 lua_pushliteral(L, "__gc"); /* S: `gc' mt FH */ 446 lua_pushliteral(L, "__gc"); /* S: `gc' mt FH */
395 lua_pushvalue(L, -2); /* S: mt `gc' mt FH */ 447 lua_pushvalue(L, -2); /* S: mt `gc' mt FH */
396 lua_pushcclosure(L, io_close, 1); /* S: close `gc' mt FH */ 448 lua_pushcclosure(L, io_gc, 1); /* S: close `gc' mt FH */
397 lua_rawset(L, -3); /* S: mt FH */ 449 lua_rawset(L, -3); /* S: mt FH */
398 /* file methods */ 450 /* file methods */
399 lua_pushliteral(L, "__gettable"); /* S: `gettable' mt FH */ 451 lua_pushliteral(L, "__gettable"); /* S: `gettable' mt FH */
@@ -403,10 +455,6 @@ static void createmeta (lua_State *L) {
403 luaL_openlib(L, flib, 1); /* S: mt FH */ 455 luaL_openlib(L, flib, 1); /* S: mt FH */
404 /* put new metatable into registry */ 456 /* put new metatable into registry */
405 lua_rawset(L, LUA_REGISTRYINDEX); /* S: empty */ 457 lua_rawset(L, LUA_REGISTRYINDEX); /* S: empty */
406 /* meta table for CLOSEDFILEHANDLE */
407 lua_pushliteral(L, CLOSEDFILEHANDLE);
408 lua_newtable(L);
409 lua_rawset(L, LUA_REGISTRYINDEX);
410} 458}
411 459
412/* }====================================================== */ 460/* }====================================================== */