aboutsummaryrefslogtreecommitdiff
path: root/src/lib_io.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/lib_io.c')
-rw-r--r--src/lib_io.c405
1 files changed, 190 insertions, 215 deletions
diff --git a/src/lib_io.c b/src/lib_io.c
index aefe4213..d69b99a4 100644
--- a/src/lib_io.c
+++ b/src/lib_io.c
@@ -17,14 +17,28 @@
17#include "lualib.h" 17#include "lualib.h"
18 18
19#include "lj_obj.h" 19#include "lj_obj.h"
20#include "lj_err.h"
21#include "lj_gc.h" 20#include "lj_gc.h"
21#include "lj_err.h"
22#include "lj_str.h"
22#include "lj_ff.h" 23#include "lj_ff.h"
24#include "lj_trace.h"
23#include "lj_lib.h" 25#include "lj_lib.h"
24 26
25/* Index of standard handles in function environment. */ 27/* Userdata payload for I/O file. */
26#define IO_INPUT 1 28typedef struct IOFileUD {
27#define IO_OUTPUT 2 29 FILE *fp; /* File handle. */
30 uint32_t type; /* File type. */
31} IOFileUD;
32
33#define IOFILE_TYPE_FILE 0 /* Regular file. */
34#define IOFILE_TYPE_PIPE 1 /* Pipe. */
35#define IOFILE_TYPE_STDF 2 /* Standard file handle. */
36#define IOFILE_TYPE_MASK 3
37
38#define IOFILE_FLAG_CLOSE 4 /* Close after io.lines() iterator. */
39
40#define IOSTDF_UD(L, id) (&gcref(G(L)->gcroot[(id)])->ud)
41#define IOSTDF_IOF(L, id) ((IOFileUD *)uddata(IOSTDF_UD(L, (id))))
28 42
29/* -- Error handling ------------------------------------------------------ */ 43/* -- Error handling ------------------------------------------------------ */
30 44
@@ -35,95 +49,102 @@ static int io_pushresult(lua_State *L, int ok, const char *fname)
35 return 1; 49 return 1;
36 } else { 50 } else {
37 int en = errno; /* Lua API calls may change this value. */ 51 int en = errno; /* Lua API calls may change this value. */
38 lua_pushnil(L); 52 setnilV(L->top++);
39 if (fname) 53 if (fname)
40 lua_pushfstring(L, "%s: %s", fname, strerror(en)); 54 lua_pushfstring(L, "%s: %s", fname, strerror(en));
41 else 55 else
42 lua_pushfstring(L, "%s", strerror(en)); 56 lua_pushfstring(L, "%s", strerror(en));
43 lua_pushinteger(L, en); 57 setintV(L->top++, en);
58 lj_trace_abort(G(L));
44 return 3; 59 return 3;
45 } 60 }
46} 61}
47 62
48static void io_file_error(lua_State *L, int arg, const char *fname) 63/* -- Open/close helpers -------------------------------------------------- */
64
65static IOFileUD *io_tofilep(lua_State *L)
49{ 66{
50 lua_pushfstring(L, "%s: %s", fname, strerror(errno)); 67 if (!(L->base < L->top && tvisudata(L->base) &&
51 luaL_argerror(L, arg, lua_tostring(L, -1)); 68 udataV(L->base)->udtype == UDTYPE_IO_FILE))
69 lj_err_argtype(L, 1, "FILE*");
70 return (IOFileUD *)uddata(udataV(L->base));
52} 71}
53 72
54/* -- Open helpers -------------------------------------------------------- */ 73static IOFileUD *io_tofile(lua_State *L)
55
56#define io_tofilep(L) ((FILE **)luaL_checkudata(L, 1, LUA_FILEHANDLE))
57
58static FILE *io_tofile(lua_State *L)
59{ 74{
60 FILE **f = io_tofilep(L); 75 IOFileUD *iof = io_tofilep(L);
61 if (*f == NULL) 76 if (iof->fp == NULL)
62 lj_err_caller(L, LJ_ERR_IOCLFL); 77 lj_err_caller(L, LJ_ERR_IOCLFL);
63 return *f; 78 return iof;
64} 79}
65 80
66static FILE **io_file_new(lua_State *L) 81static FILE *io_stdfile(lua_State *L, ptrdiff_t id)
67{ 82{
68 FILE **pf = (FILE **)lua_newuserdata(L, sizeof(FILE *)); 83 IOFileUD *iof = IOSTDF_IOF(L, id);
69 *pf = NULL; 84 if (iof->fp == NULL)
70 luaL_getmetatable(L, LUA_FILEHANDLE); 85 lj_err_caller(L, LJ_ERR_IOSTDCL);
71 lua_setmetatable(L, -2); 86 return iof->fp;
72 return pf;
73} 87}
74 88
75/* -- Close helpers ------------------------------------------------------- */ 89static IOFileUD *io_file_new(lua_State *L)
90{
91 IOFileUD *iof = (IOFileUD *)lua_newuserdata(L, sizeof(IOFileUD));
92 GCudata *ud = udataV(L->top-1);
93 ud->udtype = UDTYPE_IO_FILE;
94 /* NOBARRIER: The GCudata is new (marked white). */
95 setgcrefr(ud->metatable, curr_func(L)->c.env);
96 iof->fp = NULL;
97 iof->type = IOFILE_TYPE_FILE;
98 return iof;
99}
76 100
77static int lj_cf_io_std_close(lua_State *L) 101static IOFileUD *io_file_open(lua_State *L, const char *mode)
78{ 102{
79 lua_pushnil(L); 103 const char *fname = strdata(lj_lib_checkstr(L, 1));
80 lua_pushliteral(L, "cannot close standard file"); 104 IOFileUD *iof = io_file_new(L);
81 return 2; 105 iof->fp = fopen(fname, mode);
106 if (iof->fp == NULL)
107 luaL_argerror(L, 1, lj_str_pushf(L, "%s: %s", fname, strerror(errno)));
108 return iof;
82} 109}
83 110
84static int lj_cf_io_pipe_close(lua_State *L) 111static int io_file_close(lua_State *L, IOFileUD *iof)
85{ 112{
86 FILE **p = io_tofilep(L); 113 int ok;
114 if ((iof->type & IOFILE_TYPE_MASK) == IOFILE_TYPE_FILE) {
115 ok = (fclose(iof->fp) == 0);
116 } else if ((iof->type & IOFILE_TYPE_MASK) == IOFILE_TYPE_PIPE) {
87#if defined(LUA_USE_POSIX) 117#if defined(LUA_USE_POSIX)
88 int ok = (pclose(*p) != -1); 118 ok = (pclose(iof->fp) != -1);
89#elif defined(LUA_USE_WIN) 119#elif defined(LUA_USE_WIN)
90 int ok = (_pclose(*p) != -1); 120 ok = (_pclose(iof->fp) != -1);
91#else 121#else
92 int ok = 0; 122 ok = 0;
93#endif 123#endif
94 *p = NULL; 124 } else {
95 return io_pushresult(L, ok, NULL); 125 lua_assert((iof->type & IOFILE_TYPE_MASK) == IOFILE_TYPE_STDF);
96} 126 setnilV(L->top++);
97 127 lua_pushliteral(L, "cannot close standard file");
98static int lj_cf_io_file_close(lua_State *L) 128 return 2;
99{ 129 }
100 FILE **p = io_tofilep(L); 130 iof->fp = NULL;
101 int ok = (fclose(*p) == 0);
102 *p = NULL;
103 return io_pushresult(L, ok, NULL); 131 return io_pushresult(L, ok, NULL);
104} 132}
105 133
106static int io_file_close(lua_State *L)
107{
108 lua_getfenv(L, 1);
109 lua_getfield(L, -1, "__close");
110 return (lua_tocfunction(L, -1))(L);
111}
112
113/* -- Read/write helpers -------------------------------------------------- */ 134/* -- Read/write helpers -------------------------------------------------- */
114 135
115static int io_file_readnum(lua_State *L, FILE *fp) 136static int io_file_readnum(lua_State *L, FILE *fp)
116{ 137{
117 lua_Number d; 138 lua_Number d;
118 if (fscanf(fp, LUA_NUMBER_SCAN, &d) == 1) { 139 if (fscanf(fp, LUA_NUMBER_SCAN, &d) == 1) {
119 lua_pushnumber(L, d); 140 setnumV(L->top++, d);
120 return 1; 141 return 1;
121 } else { 142 } else {
122 return 0; /* read fails */ 143 return 0;
123 } 144 }
124} 145}
125 146
126static int test_eof(lua_State *L, FILE *fp) 147static int io_file_testeof(lua_State *L, FILE *fp)
127{ 148{
128 int c = getc(fp); 149 int c = getc(fp);
129 ungetc(c, fp); 150 ungetc(c, fp);
@@ -168,7 +189,7 @@ static int io_file_readchars(lua_State *L, FILE *fp, size_t n)
168 n -= nr; /* still have to read `n' chars */ 189 n -= nr; /* still have to read `n' chars */
169 } while (n > 0 && nr == rlen); /* until end of count or eof */ 190 } while (n > 0 && nr == rlen); /* until end of count or eof */
170 luaL_pushresult(&b); /* close buffer */ 191 luaL_pushresult(&b); /* close buffer */
171 return (n == 0 || lua_objlen(L, -1) > 0); 192 return (n == 0 || strV(L->top-1)->len > 0);
172} 193}
173 194
174static int io_file_read(lua_State *L, FILE *fp, int start) 195static int io_file_read(lua_State *L, FILE *fp, int start)
@@ -197,7 +218,7 @@ static int io_file_read(lua_State *L, FILE *fp, int start)
197 lj_err_arg(L, n+1, LJ_ERR_INVFMT); 218 lj_err_arg(L, n+1, LJ_ERR_INVFMT);
198 } else if (tvisnum(L->base+n)) { 219 } else if (tvisnum(L->base+n)) {
199 size_t len = (size_t)lj_lib_checkint(L, n+1); 220 size_t len = (size_t)lj_lib_checkint(L, n+1);
200 ok = len ? io_file_readchars(L, fp, len) : test_eof(L, fp); 221 ok = len ? io_file_readchars(L, fp, len) : io_file_testeof(L, fp);
201 } else { 222 } else {
202 lj_err_arg(L, n+1, LJ_ERR_INVOPT); 223 lj_err_arg(L, n+1, LJ_ERR_INVOPT);
203 } 224 }
@@ -233,30 +254,29 @@ static int io_file_write(lua_State *L, FILE *fp, int start)
233 254
234LJLIB_CF(io_method_close) 255LJLIB_CF(io_method_close)
235{ 256{
236 if (lua_isnone(L, 1)) 257 IOFileUD *iof = L->base < L->top ? io_tofile(L) :
237 lua_rawgeti(L, LUA_ENVIRONINDEX, IO_OUTPUT); 258 IOSTDF_IOF(L, GCROOT_IO_OUTPUT);
238 io_tofile(L); 259 return io_file_close(L, iof);
239 return io_file_close(L);
240} 260}
241 261
242LJLIB_CF(io_method_read) 262LJLIB_CF(io_method_read)
243{ 263{
244 return io_file_read(L, io_tofile(L), 1); 264 return io_file_read(L, io_tofile(L)->fp, 1);
245} 265}
246 266
247LJLIB_CF(io_method_write) 267LJLIB_CF(io_method_write) LJLIB_REC(io_write 0)
248{ 268{
249 return io_file_write(L, io_tofile(L), 1); 269 return io_file_write(L, io_tofile(L)->fp, 1);
250} 270}
251 271
252LJLIB_CF(io_method_flush) 272LJLIB_CF(io_method_flush) LJLIB_REC(io_flush 0)
253{ 273{
254 return io_pushresult(L, fflush(io_tofile(L)) == 0, NULL); 274 return io_pushresult(L, fflush(io_tofile(L)->fp) == 0, NULL);
255} 275}
256 276
257LJLIB_CF(io_method_seek) 277LJLIB_CF(io_method_seek)
258{ 278{
259 FILE *fp = io_tofile(L); 279 FILE *fp = io_tofile(L)->fp;
260 int opt = lj_lib_checkopt(L, 2, 1, "\3set\3cur\3end"); 280 int opt = lj_lib_checkopt(L, 2, 1, "\3set\3cur\3end");
261 lua_Number ofs; 281 lua_Number ofs;
262 int res; 282 int res;
@@ -294,39 +314,40 @@ LJLIB_CF(io_method_seek)
294 314
295LJLIB_CF(io_method_setvbuf) 315LJLIB_CF(io_method_setvbuf)
296{ 316{
297 FILE *fp = io_tofile(L); 317 FILE *fp = io_tofile(L)->fp;
298 int opt = lj_lib_checkopt(L, 2, -1, "\4full\4line\2no"); 318 int opt = lj_lib_checkopt(L, 2, -1, "\4full\4line\2no");
299 size_t sz = (size_t)lj_lib_optint(L, 3, LUAL_BUFFERSIZE); 319 size_t sz = (size_t)lj_lib_optint(L, 3, LUAL_BUFFERSIZE);
300 if (opt == 0) opt = _IOFBF; 320 if (opt == 0) opt = _IOFBF;
301 else if (opt == 1) opt = _IOLBF; 321 else if (opt == 1) opt = _IOLBF;
302 else if (opt == 2) opt = _IONBF; 322 else if (opt == 2) opt = _IONBF;
303 return io_pushresult(L, (setvbuf(fp, NULL, opt, sz) == 0), NULL); 323 return io_pushresult(L, setvbuf(fp, NULL, opt, sz) == 0, NULL);
304} 324}
305 325
306/* Forward declaration. */ 326LJLIB_PUSH(top-2) /* io_lines_iter */
307static void io_file_lines(lua_State *L, int idx, int toclose);
308
309LJLIB_CF(io_method_lines) 327LJLIB_CF(io_method_lines)
310{ 328{
311 io_tofile(L); 329 io_tofile(L);
312 io_file_lines(L, 1, 0); 330 setfuncV(L, L->top, funcV(lj_lib_upvalue(L, 1)));
313 return 1; 331 setudataV(L, L->top+1, udataV(L->base));
332 L->top += 2;
333 return 2;
314} 334}
315 335
316LJLIB_CF(io_method___gc) 336LJLIB_CF(io_method___gc)
317{ 337{
318 FILE *fp = *io_tofilep(L); 338 IOFileUD *iof = io_tofilep(L);
319 if (fp != NULL) io_file_close(L); 339 if (iof->fp != NULL)
340 io_file_close(L, iof);
320 return 0; 341 return 0;
321} 342}
322 343
323LJLIB_CF(io_method___tostring) 344LJLIB_CF(io_method___tostring)
324{ 345{
325 FILE *fp = *io_tofilep(L); 346 IOFileUD *iof = io_tofilep(L);
326 if (fp == NULL) 347 if (iof->fp != NULL)
327 lua_pushliteral(L, "file (closed)"); 348 lua_pushfstring(L, "file (%p)", iof->fp);
328 else 349 else
329 lua_pushfstring(L, "file (%p)", fp); 350 lua_pushliteral(L, "file (closed)");
330 return 1; 351 return 1;
331} 352}
332 353
@@ -340,30 +361,41 @@ LJLIB_PUSH(top-1) LJLIB_SET(__index)
340 361
341LJLIB_PUSH(top-2) LJLIB_SET(!) /* Set environment. */ 362LJLIB_PUSH(top-2) LJLIB_SET(!) /* Set environment. */
342 363
343static FILE *io_file_get(lua_State *L, int findex) 364LJLIB_CF(io_open)
344{ 365{
345 GCtab *fenv = tabref(curr_func(L)->c.env); 366 const char *fname = strdata(lj_lib_checkstr(L, 1));
346 GCudata *ud = udataV(&tvref(fenv->array)[findex]); 367 GCstr *s = lj_lib_optstr(L, 2);
347 FILE *fp = *(FILE **)uddata(ud); 368 const char *mode = s ? strdata(s) : "r";
348 if (fp == NULL) 369 IOFileUD *iof = io_file_new(L);
349 lj_err_caller(L, LJ_ERR_IOSTDCL); 370 iof->fp = fopen(fname, mode);
350 return fp; 371 return iof->fp != NULL ? 1 : io_pushresult(L, 0, fname);
351} 372}
352 373
353LJLIB_CF(io_open) 374LJLIB_CF(io_popen)
354{ 375{
355 const char *fname = luaL_checkstring(L, 1); 376#if defined(LUA_USE_POSIX) || defined(LUA_USE_WIN)
356 const char *mode = luaL_optstring(L, 2, "r"); 377 const char *fname = strdata(lj_lib_checkstr(L, 1));
357 FILE **pf = io_file_new(L); 378 GCstr *s = lj_lib_optstr(L, 2);
358 *pf = fopen(fname, mode); 379 const char *mode = s ? strdata(s) : "r";
359 return (*pf == NULL) ? io_pushresult(L, 0, fname) : 1; 380 IOFileUD *iof = io_file_new(L);
381 iof->type = IOFILE_TYPE_PIPE;
382#ifdef LUA_USE_POSIX
383 fflush(NULL);
384 iof->fp = popen(fname, mode);
385#else
386 iof->fp = _popen(fname, mode);
387#endif
388 return iof->fp != NULL ? 1 : io_pushresult(L, 0, fname);
389#else
390 luaL_error(L, LUA_QL("popen") " not supported");
391#endif
360} 392}
361 393
362LJLIB_CF(io_tmpfile) 394LJLIB_CF(io_tmpfile)
363{ 395{
364 FILE **pf = io_file_new(L); 396 IOFileUD *iof = io_file_new(L);
365 *pf = tmpfile(); 397 iof->fp = tmpfile();
366 return (*pf == NULL) ? io_pushresult(L, 0, NULL) : 1; 398 return iof->fp != NULL ? 1 : io_pushresult(L, 0, NULL);
367} 399}
368 400
369LJLIB_CF(io_close) 401LJLIB_CF(io_close)
@@ -373,169 +405,112 @@ LJLIB_CF(io_close)
373 405
374LJLIB_CF(io_read) 406LJLIB_CF(io_read)
375{ 407{
376 return io_file_read(L, io_file_get(L, IO_INPUT), 0); 408 return io_file_read(L, io_stdfile(L, GCROOT_IO_INPUT), 0);
377}
378
379LJLIB_CF(io_write)
380{
381 return io_file_write(L, io_file_get(L, IO_OUTPUT), 0);
382}
383
384LJLIB_CF(io_flush)
385{
386 return io_pushresult(L, fflush(io_file_get(L, IO_OUTPUT)) == 0, NULL);
387} 409}
388 410
389LJLIB_NOREG LJLIB_CF(io_lines_iter) 411LJLIB_CF(io_write) LJLIB_REC(io_write GCROOT_IO_OUTPUT)
390{
391 FILE *fp = *(FILE **)uddata(udataV(lj_lib_upvalue(L, 1)));
392 int ok;
393 if (fp == NULL)
394 lj_err_caller(L, LJ_ERR_IOCLFL);
395 ok = io_file_readline(L, fp);
396 if (ferror(fp))
397 return luaL_error(L, "%s", strerror(errno));
398 if (ok)
399 return 1;
400 if (tvistrue(lj_lib_upvalue(L, 2))) { /* Need to close file? */
401 L->top = L->base+1;
402 setudataV(L, L->base, udataV(lj_lib_upvalue(L, 1)));
403 io_file_close(L);
404 }
405 return 0;
406}
407
408static void io_file_lines(lua_State *L, int idx, int toclose)
409{ 412{
410 lua_pushvalue(L, idx); 413 return io_file_write(L, io_stdfile(L, GCROOT_IO_OUTPUT), 0);
411 lua_pushboolean(L, toclose);
412 lua_pushcclosure(L, lj_cf_io_lines_iter, 2);
413 funcV(L->top-1)->c.ffid = FF_io_lines_iter;
414} 414}
415 415
416LJLIB_CF(io_lines) 416LJLIB_CF(io_flush) LJLIB_REC(io_flush GCROOT_IO_OUTPUT)
417{ 417{
418 if (lua_isnoneornil(L, 1)) { /* no arguments? */ 418 return io_pushresult(L, fflush(io_stdfile(L, GCROOT_IO_OUTPUT)) == 0, NULL);
419 /* will iterate over default input */
420 lua_rawgeti(L, LUA_ENVIRONINDEX, IO_INPUT);
421 return lj_cf_io_method_lines(L);
422 } else {
423 const char *fname = luaL_checkstring(L, 1);
424 FILE **pf = io_file_new(L);
425 *pf = fopen(fname, "r");
426 if (*pf == NULL)
427 io_file_error(L, 1, fname);
428 io_file_lines(L, lua_gettop(L), 1);
429 return 1;
430 }
431} 419}
432 420
433static int io_std_get(lua_State *L, int fp, const char *mode) 421static int io_std_getset(lua_State *L, ptrdiff_t id, const char *mode)
434{ 422{
435 if (!lua_isnoneornil(L, 1)) { 423 if (L->base < L->top && !tvisnil(L->base)) {
436 const char *fname = lua_tostring(L, 1); 424 if (tvisudata(L->base)) {
437 if (fname) { 425 io_tofile(L);
438 FILE **pf = io_file_new(L); 426 L->top = L->base+1;
439 *pf = fopen(fname, mode);
440 if (*pf == NULL)
441 io_file_error(L, 1, fname);
442 } else { 427 } else {
443 io_tofile(L); /* check that it's a valid file handle */ 428 io_file_open(L, mode);
444 lua_pushvalue(L, 1);
445 } 429 }
446 lua_rawseti(L, LUA_ENVIRONINDEX, fp); 430 /* NOBARRIER: The standard I/O handles are GC roots. */
431 setgcref(G(L)->gcroot[id], gcV(L->top-1));
432 } else {
433 setudataV(L, L->top++, IOSTDF_UD(L, id));
447 } 434 }
448 /* return current value */
449 lua_rawgeti(L, LUA_ENVIRONINDEX, fp);
450 return 1; 435 return 1;
451} 436}
452 437
453LJLIB_CF(io_input) 438LJLIB_CF(io_input)
454{ 439{
455 return io_std_get(L, IO_INPUT, "r"); 440 return io_std_getset(L, GCROOT_IO_INPUT, "r");
456} 441}
457 442
458LJLIB_CF(io_output) 443LJLIB_CF(io_output)
459{ 444{
460 return io_std_get(L, IO_OUTPUT, "w"); 445 return io_std_getset(L, GCROOT_IO_OUTPUT, "w");
461} 446}
462 447
463LJLIB_CF(io_type) 448LJLIB_NOREG LJLIB_CF(io_lines_iter)
464{ 449{
465 void *ud; 450 IOFileUD *iof = io_tofile(L);
466 luaL_checkany(L, 1); 451 int ok = io_file_readline(L, iof->fp);
467 ud = lua_touserdata(L, 1); 452 if (ferror(iof->fp))
468 lua_getfield(L, LUA_REGISTRYINDEX, LUA_FILEHANDLE); 453 lj_err_callermsg(L, strerror(errno));
469 if (ud == NULL || !lua_getmetatable(L, 1) || !lua_rawequal(L, -2, -1)) 454 if (!ok && (iof->type & IOFILE_FLAG_CLOSE))
470 lua_pushnil(L); /* not a file */ 455 io_file_close(L, iof); /* Return values are ignored (ok is 0). */
471 else if (*((FILE **)ud) == NULL) 456 return ok;
472 lua_pushliteral(L, "closed file");
473 else
474 lua_pushliteral(L, "file");
475 return 1;
476} 457}
477 458
478LJLIB_PUSH(top-3) LJLIB_SET(!) /* Set environment. */ 459LJLIB_PUSH(top-3) /* io_lines_iter */
460LJLIB_CF(io_lines)
461{
462 if (L->base < L->top && !tvisnil(L->base)) { /* io.lines(fname) */
463 IOFileUD *iof = io_file_open(L, "r");
464 iof->type = IOFILE_TYPE_FILE|IOFILE_FLAG_CLOSE;
465 setfuncV(L, L->top-2, funcV(lj_lib_upvalue(L, 1)));
466 } else { /* io.lines() iterates over stdin. */
467 setfuncV(L, L->top, funcV(lj_lib_upvalue(L, 1)));
468 setudataV(L, L->top+1, IOSTDF_UD(L, GCROOT_IO_INPUT));
469 L->top += 2;
470 }
471 return 2;
472}
479 473
480LJLIB_CF(io_popen) 474LJLIB_CF(io_type)
481{ 475{
482#if defined(LUA_USE_POSIX) || defined(LUA_USE_WIN) 476 cTValue *o = lj_lib_checkany(L, 1);
483 const char *fname = luaL_checkstring(L, 1); 477 if (!(tvisudata(o) && udataV(o)->udtype == UDTYPE_IO_FILE))
484 const char *mode = luaL_optstring(L, 2, "r"); 478 setnilV(L->top++);
485 FILE **pf = io_file_new(L); 479 else if (((IOFileUD *)uddata(udataV(o)))->fp != NULL)
486#ifdef LUA_USE_POSIX 480 lua_pushliteral(L, "file");
487 fflush(NULL); 481 else
488 *pf = popen(fname, mode); 482 lua_pushliteral(L, "closed file");
489#else 483 return 1;
490 *pf = _popen(fname, mode);
491#endif
492 return (*pf == NULL) ? io_pushresult(L, 0, fname) : 1;
493#else
494 luaL_error(L, LUA_QL("popen") " not supported");
495#endif
496} 484}
497 485
498#include "lj_libdef.h" 486#include "lj_libdef.h"
499 487
500/* ------------------------------------------------------------------------ */ 488/* ------------------------------------------------------------------------ */
501 489
502static void io_std_new(lua_State *L, FILE *fp, int k, const char *fname) 490static GCobj *io_std_new(lua_State *L, FILE *fp, const char *name)
503{ 491{
504 FILE **pf = io_file_new(L); 492 IOFileUD *iof = (IOFileUD *)lua_newuserdata(L, sizeof(IOFileUD));
505 GCudata *ud = udataV(L->top-1); 493 GCudata *ud = udataV(L->top-1);
506 GCtab *envt = tabV(L->top-2); 494 ud->udtype = UDTYPE_IO_FILE;
507 *pf = fp; 495 /* NOBARRIER: The GCudata is new (marked white). */
508 setgcref(ud->env, obj2gco(envt)); 496 setgcref(ud->metatable, gcV(L->top-3));
509 lj_gc_objbarrier(L, obj2gco(ud), envt); 497 iof->fp = fp;
510 if (k > 0) { 498 iof->type = IOFILE_TYPE_STDF;
511 lua_pushvalue(L, -1); 499 lua_setfield(L, -2, name);
512 lua_rawseti(L, -5, k); 500 return obj2gco(ud);
513 }
514 lua_setfield(L, -3, fname);
515}
516
517static void io_fenv_new(lua_State *L, int narr, lua_CFunction cls)
518{
519 lua_createtable(L, narr, 1);
520 lua_pushcfunction(L, cls);
521 lua_setfield(L, -2, "__close");
522} 501}
523 502
524LUALIB_API int luaopen_io(lua_State *L) 503LUALIB_API int luaopen_io(lua_State *L)
525{ 504{
526 lua_getfield(L, LUA_REGISTRYINDEX, LUA_FILEHANDLE); 505 lua_pushcfunction(L, lj_cf_io_lines_iter);
527 if (tvisnil(L->top-1)) { 506 funcV(L->top-1)->c.ffid = FF_io_lines_iter;
528 LJ_LIB_REG_(L, NULL, io_method); 507 LJ_LIB_REG_(L, NULL, io_method);
529 lua_setfield(L, LUA_REGISTRYINDEX, LUA_FILEHANDLE); 508 copyTV(L, L->top, L->top-1); L->top++;
530 } 509 lua_setfield(L, LUA_REGISTRYINDEX, LUA_FILEHANDLE);
531 io_fenv_new(L, 0, lj_cf_io_pipe_close); /* top-3 */
532 io_fenv_new(L, 2, lj_cf_io_file_close); /* top-2 */
533 LJ_LIB_REG(L, io); 510 LJ_LIB_REG(L, io);
534 io_fenv_new(L, 0, lj_cf_io_std_close); 511 setgcref(G(L)->gcroot[GCROOT_IO_INPUT], io_std_new(L, stdin, "stdin"));
535 io_std_new(L, stdin, IO_INPUT, "stdin"); 512 setgcref(G(L)->gcroot[GCROOT_IO_OUTPUT], io_std_new(L, stdout, "stdout"));
536 io_std_new(L, stdout, IO_OUTPUT, "stdout"); 513 io_std_new(L, stderr, "stderr");
537 io_std_new(L, stderr, 0, "stderr");
538 L->top--;
539 return 1; 514 return 1;
540} 515}
541 516