3 ** Copyright (C) 2005-2011 Mike Pall. See Copyright Notice in luajit.h
5 ** Major portions taken verbatim or adapted from the Lua interpreter.
6 ** Copyright (C) 1994-2011 Lua.org, PUC-Rio. See Copyright Notice in lua.h
27 /* Userdata payload for I/O file. */
28 typedef struct IOFileUD
{
29 FILE *fp
; /* File handle. */
30 uint32_t type
; /* File type. */
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
38 #define IOFILE_FLAG_CLOSE 4 /* Close after io.lines() iterator. */
40 #define IOSTDF_UD(L, id) (&gcref(G(L)->gcroot[(id)])->ud)
41 #define IOSTDF_IOF(L, id) ((IOFileUD *)uddata(IOSTDF_UD(L, (id))))
43 /* -- Error handling ------------------------------------------------------ */
45 static int io_pushresult(lua_State
*L
, int ok
, const char *fname
)
48 setboolV(L
->top
++, 1);
51 int en
= errno
; /* Lua API calls may change this value. */
54 lua_pushfstring(L
, "%s: %s", fname
, strerror(en
));
56 lua_pushfstring(L
, "%s", strerror(en
));
57 setintV(L
->top
++, en
);
63 /* -- Open/close helpers -------------------------------------------------- */
65 static IOFileUD
*io_tofilep(lua_State
*L
)
67 if (!(L
->base
< L
->top
&& tvisudata(L
->base
) &&
68 udataV(L
->base
)->udtype
== UDTYPE_IO_FILE
))
69 lj_err_argtype(L
, 1, "FILE*");
70 return (IOFileUD
*)uddata(udataV(L
->base
));
73 static IOFileUD
*io_tofile(lua_State
*L
)
75 IOFileUD
*iof
= io_tofilep(L
);
77 lj_err_caller(L
, LJ_ERR_IOCLFL
);
81 static FILE *io_stdfile(lua_State
*L
, ptrdiff_t id
)
83 IOFileUD
*iof
= IOSTDF_IOF(L
, id
);
85 lj_err_caller(L
, LJ_ERR_IOSTDCL
);
89 static IOFileUD
*io_file_new(lua_State
*L
)
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
);
97 iof
->type
= IOFILE_TYPE_FILE
;
101 static IOFileUD
*io_file_open(lua_State
*L
, const char *mode
)
103 const char *fname
= strdata(lj_lib_checkstr(L
, 1));
104 IOFileUD
*iof
= io_file_new(L
);
105 iof
->fp
= fopen(fname
, mode
);
107 luaL_argerror(L
, 1, lj_str_pushf(L
, "%s: %s", fname
, strerror(errno
)));
111 static int io_file_close(lua_State
*L
, IOFileUD
*iof
)
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
) {
118 ok
= (pclose(iof
->fp
) != -1);
119 #elif LJ_TARGET_WINDOWS
120 ok
= (_pclose(iof
->fp
) != -1);
125 lua_assert((iof
->type
& IOFILE_TYPE_MASK
) == IOFILE_TYPE_STDF
);
127 lua_pushliteral(L
, "cannot close standard file");
131 return io_pushresult(L
, ok
, NULL
);
134 /* -- Read/write helpers -------------------------------------------------- */
136 static int io_file_readnum(lua_State
*L
, FILE *fp
)
139 if (fscanf(fp
, LUA_NUMBER_SCAN
, &d
) == 1) {
141 int32_t i
= lj_num2int(d
);
142 if (d
== (lua_Number
)i
&& !tvismzero((cTValue
*)&d
)) {
143 setintV(L
->top
++, i
);
147 setnumV(L
->top
++, d
);
155 static int io_file_testeof(lua_State
*L
, FILE *fp
)
159 lua_pushlstring(L
, NULL
, 0);
163 static int io_file_readline(lua_State
*L
, FILE *fp
, size_t chop
)
166 luaL_buffinit(L
, &b
);
169 char *p
= luaL_prepbuffer(&b
);
170 if (fgets(p
, LUAL_BUFFERSIZE
, fp
) == NULL
) { /* EOF? */
172 return (strV(L
->top
-1)->len
> 0); /* Anything read? */
175 if (len
== 0 || p
[len
-1] != '\n') { /* Partial line? */
176 luaL_addsize(&b
, len
);
178 luaL_addsize(&b
, len
- chop
); /* Keep or remove EOL. */
180 return 1; /* Got at least an EOL. */
185 static int io_file_readchars(lua_State
*L
, FILE *fp
, size_t n
)
187 size_t rlen
; /* how much to read */
188 size_t nr
; /* number of chars actually read */
190 luaL_buffinit(L
, &b
);
191 rlen
= LUAL_BUFFERSIZE
; /* try to read that much each time */
193 char *p
= luaL_prepbuffer(&b
);
194 if (rlen
> n
) rlen
= n
; /* cannot read more than asked */
195 nr
= fread(p
, 1, rlen
, fp
);
196 luaL_addsize(&b
, nr
);
197 n
-= nr
; /* still have to read `n' chars */
198 } while (n
> 0 && nr
== rlen
); /* until end of count or eof */
199 luaL_pushresult(&b
); /* close buffer */
200 return (n
== 0 || strV(L
->top
-1)->len
> 0);
203 static int io_file_read(lua_State
*L
, FILE *fp
, int start
)
205 int ok
, n
, nargs
= (int)(L
->top
- L
->base
) - start
;
208 ok
= io_file_readline(L
, fp
, 1);
209 n
= start
+1; /* Return 1 result. */
211 /* The results plus the buffers go on top of the args. */
212 luaL_checkstack(L
, nargs
+LUA_MINSTACK
, "too many arguments");
214 for (n
= start
; nargs
-- && ok
; n
++) {
215 if (tvisstr(L
->base
+n
)) {
216 const char *p
= strVdata(L
->base
+n
);
218 lj_err_arg(L
, n
+1, LJ_ERR_INVOPT
);
220 ok
= io_file_readnum(L
, fp
);
221 else if ((p
[1] & ~0x20) == 'L')
222 ok
= io_file_readline(L
, fp
, (p
[1] == 'l'));
223 else if (p
[1] == 'a')
224 io_file_readchars(L
, fp
, ~((size_t)0));
226 lj_err_arg(L
, n
+1, LJ_ERR_INVFMT
);
227 } else if (tvisnumber(L
->base
+n
)) {
228 size_t len
= (size_t)lj_lib_checkint(L
, n
+1);
229 ok
= len
? io_file_readchars(L
, fp
, len
) : io_file_testeof(L
, fp
);
231 lj_err_arg(L
, n
+1, LJ_ERR_INVOPT
);
236 return io_pushresult(L
, 0, NULL
);
238 setnilV(L
->top
-1); /* Replace last result with nil. */
242 static int io_file_write(lua_State
*L
, FILE *fp
, int start
)
246 for (tv
= L
->base
+start
; tv
< L
->top
; tv
++) {
248 MSize len
= strV(tv
)->len
;
249 status
= status
&& (fwrite(strVdata(tv
), 1, len
, fp
) == len
);
250 } else if (tvisint(tv
)) {
251 char buf
[LJ_STR_INTBUF
];
252 char *p
= lj_str_bufint(buf
, intV(tv
));
253 size_t len
= (size_t)(buf
+LJ_STR_INTBUF
-p
);
254 status
= status
&& (fwrite(p
, 1, len
, fp
) == len
);
255 } else if (tvisnum(tv
)) {
256 status
= status
&& (fprintf(fp
, LUA_NUMBER_FMT
, numV(tv
)) > 0);
258 lj_err_argt(L
, (int)(tv
- L
->base
) + 1, LUA_TSTRING
);
261 return io_pushresult(L
, status
, NULL
);
264 /* -- I/O file methods ---------------------------------------------------- */
266 #define LJLIB_MODULE_io_method
268 LJLIB_CF(io_method_close
)
270 IOFileUD
*iof
= L
->base
< L
->top
? io_tofile(L
) :
271 IOSTDF_IOF(L
, GCROOT_IO_OUTPUT
);
272 return io_file_close(L
, iof
);
275 LJLIB_CF(io_method_read
)
277 return io_file_read(L
, io_tofile(L
)->fp
, 1);
280 LJLIB_CF(io_method_write
) LJLIB_REC(io_write
0)
282 return io_file_write(L
, io_tofile(L
)->fp
, 1);
285 LJLIB_CF(io_method_flush
) LJLIB_REC(io_flush
0)
287 return io_pushresult(L
, fflush(io_tofile(L
)->fp
) == 0, NULL
);
290 LJLIB_CF(io_method_seek
)
292 FILE *fp
= io_tofile(L
)->fp
;
293 int opt
= lj_lib_checkopt(L
, 2, 1, "\3set\3cur\3end");
297 if (opt
== 0) opt
= SEEK_SET
;
298 else if (opt
== 1) opt
= SEEK_CUR
;
299 else if (opt
== 2) opt
= SEEK_END
;
303 ofs
= (int64_t)intV(o
);
305 ofs
= (int64_t)numV(o
);
306 else if (!tvisnil(o
))
307 lj_err_argt(L
, 3, LUA_TNUMBER
);
310 res
= fseeko(fp
, ofs
, opt
);
311 #elif _MSC_VER >= 1400
312 res
= _fseeki64(fp
, ofs
, opt
);
313 #elif defined(__MINGW32__)
314 res
= fseeko64(fp
, ofs
, opt
);
316 res
= fseek(fp
, (long)ofs
, opt
);
319 return io_pushresult(L
, 0, NULL
);
322 #elif _MSC_VER >= 1400
324 #elif defined(__MINGW32__)
327 ofs
= (int64_t)ftell(fp
);
329 setint64V(L
->top
-1, ofs
);
333 LJLIB_CF(io_method_setvbuf
)
335 FILE *fp
= io_tofile(L
)->fp
;
336 int opt
= lj_lib_checkopt(L
, 2, -1, "\4full\4line\2no");
337 size_t sz
= (size_t)lj_lib_optint(L
, 3, LUAL_BUFFERSIZE
);
338 if (opt
== 0) opt
= _IOFBF
;
339 else if (opt
== 1) opt
= _IOLBF
;
340 else if (opt
== 2) opt
= _IONBF
;
341 return io_pushresult(L
, setvbuf(fp
, NULL
, opt
, sz
) == 0, NULL
);
344 LJLIB_PUSH(top
-2) /* io_lines_iter */
345 LJLIB_CF(io_method_lines
)
348 setfuncV(L
, L
->top
, funcV(lj_lib_upvalue(L
, 1)));
349 setudataV(L
, L
->top
+1, udataV(L
->base
));
354 LJLIB_CF(io_method___gc
)
356 IOFileUD
*iof
= io_tofilep(L
);
357 if (iof
->fp
!= NULL
&& (iof
->type
& IOFILE_TYPE_MASK
) != IOFILE_TYPE_STDF
)
358 io_file_close(L
, iof
);
362 LJLIB_CF(io_method___tostring
)
364 IOFileUD
*iof
= io_tofilep(L
);
366 lua_pushfstring(L
, "file (%p)", iof
->fp
);
368 lua_pushliteral(L
, "file (closed)");
372 LJLIB_PUSH(top
-1) LJLIB_SET(__index
)
374 #include "lj_libdef.h"
376 /* -- I/O library functions ----------------------------------------------- */
378 #define LJLIB_MODULE_io
380 LJLIB_PUSH(top
-2) LJLIB_SET(!) /* Set environment. */
384 const char *fname
= strdata(lj_lib_checkstr(L
, 1));
385 GCstr
*s
= lj_lib_optstr(L
, 2);
386 const char *mode
= s
? strdata(s
) : "r";
387 IOFileUD
*iof
= io_file_new(L
);
388 iof
->fp
= fopen(fname
, mode
);
389 return iof
->fp
!= NULL
? 1 : io_pushresult(L
, 0, fname
);
394 #if LJ_TARGET_POSIX || LJ_TARGET_WINDOWS
395 const char *fname
= strdata(lj_lib_checkstr(L
, 1));
396 GCstr
*s
= lj_lib_optstr(L
, 2);
397 const char *mode
= s
? strdata(s
) : "r";
398 IOFileUD
*iof
= io_file_new(L
);
399 iof
->type
= IOFILE_TYPE_PIPE
;
402 iof
->fp
= popen(fname
, mode
);
404 iof
->fp
= _popen(fname
, mode
);
406 return iof
->fp
!= NULL
? 1 : io_pushresult(L
, 0, fname
);
408 luaL_error(L
, LUA_QL("popen") " not supported");
414 IOFileUD
*iof
= io_file_new(L
);
416 return iof
->fp
!= NULL
? 1 : io_pushresult(L
, 0, NULL
);
421 return lj_cf_io_method_close(L
);
426 return io_file_read(L
, io_stdfile(L
, GCROOT_IO_INPUT
), 0);
429 LJLIB_CF(io_write
) LJLIB_REC(io_write GCROOT_IO_OUTPUT
)
431 return io_file_write(L
, io_stdfile(L
, GCROOT_IO_OUTPUT
), 0);
434 LJLIB_CF(io_flush
) LJLIB_REC(io_flush GCROOT_IO_OUTPUT
)
436 return io_pushresult(L
, fflush(io_stdfile(L
, GCROOT_IO_OUTPUT
)) == 0, NULL
);
439 static int io_std_getset(lua_State
*L
, ptrdiff_t id
, const char *mode
)
441 if (L
->base
< L
->top
&& !tvisnil(L
->base
)) {
442 if (tvisudata(L
->base
)) {
446 io_file_open(L
, mode
);
448 /* NOBARRIER: The standard I/O handles are GC roots. */
449 setgcref(G(L
)->gcroot
[id
], gcV(L
->top
-1));
451 setudataV(L
, L
->top
++, IOSTDF_UD(L
, id
));
458 return io_std_getset(L
, GCROOT_IO_INPUT
, "r");
463 return io_std_getset(L
, GCROOT_IO_OUTPUT
, "w");
466 LJLIB_NOREG
LJLIB_CF(io_lines_iter
)
468 IOFileUD
*iof
= io_tofile(L
);
469 int ok
= io_file_readline(L
, iof
->fp
, 1);
471 lj_err_callermsg(L
, strerror(errno
));
472 if (!ok
&& (iof
->type
& IOFILE_FLAG_CLOSE
))
473 io_file_close(L
, iof
); /* Return values are ignored (ok is 0). */
477 LJLIB_PUSH(top
-3) /* io_lines_iter */
480 if (L
->base
< L
->top
&& !tvisnil(L
->base
)) { /* io.lines(fname) */
481 IOFileUD
*iof
= io_file_open(L
, "r");
482 iof
->type
= IOFILE_TYPE_FILE
|IOFILE_FLAG_CLOSE
;
483 setfuncV(L
, L
->top
-2, funcV(lj_lib_upvalue(L
, 1)));
484 } else { /* io.lines() iterates over stdin. */
485 setfuncV(L
, L
->top
, funcV(lj_lib_upvalue(L
, 1)));
486 setudataV(L
, L
->top
+1, IOSTDF_UD(L
, GCROOT_IO_INPUT
));
494 cTValue
*o
= lj_lib_checkany(L
, 1);
495 if (!(tvisudata(o
) && udataV(o
)->udtype
== UDTYPE_IO_FILE
))
497 else if (((IOFileUD
*)uddata(udataV(o
)))->fp
!= NULL
)
498 lua_pushliteral(L
, "file");
500 lua_pushliteral(L
, "closed file");
504 #include "lj_libdef.h"
506 /* ------------------------------------------------------------------------ */
508 static GCobj
*io_std_new(lua_State
*L
, FILE *fp
, const char *name
)
510 IOFileUD
*iof
= (IOFileUD
*)lua_newuserdata(L
, sizeof(IOFileUD
));
511 GCudata
*ud
= udataV(L
->top
-1);
512 ud
->udtype
= UDTYPE_IO_FILE
;
513 /* NOBARRIER: The GCudata is new (marked white). */
514 setgcref(ud
->metatable
, gcV(L
->top
-3));
516 iof
->type
= IOFILE_TYPE_STDF
;
517 lua_setfield(L
, -2, name
);
521 LUALIB_API
int luaopen_io(lua_State
*L
)
523 lj_lib_pushcf(L
, lj_cf_io_lines_iter
, FF_io_lines_iter
);
524 LJ_LIB_REG(L
, NULL
, io_method
);
525 copyTV(L
, L
->top
, L
->top
-1); L
->top
++;
526 lua_setfield(L
, LUA_REGISTRYINDEX
, LUA_FILEHANDLE
);
527 LJ_LIB_REG(L
, LUA_IOLIBNAME
, io
);
528 setgcref(G(L
)->gcroot
[GCROOT_IO_INPUT
], io_std_new(L
, stdin
, "stdin"));
529 setgcref(G(L
)->gcroot
[GCROOT_IO_OUTPUT
], io_std_new(L
, stdout
, "stdout"));
530 io_std_new(L
, stderr
, "stderr");