Leave hook when resume catches error thrown from hook.
[luajit-2.0.git] / src / lib_io.c
blob8911958fa4e687d1594295a8cf82b818d4a0ddb5
1 /*
2 ** I/O library.
3 ** Copyright (C) 2005-2012 Mike Pall. See Copyright Notice in luajit.h
4 **
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
7 */
9 #include <errno.h>
10 #include <stdio.h>
12 #define lib_io_c
13 #define LUA_LIB
15 #include "lua.h"
16 #include "lauxlib.h"
17 #include "lualib.h"
19 #include "lj_obj.h"
20 #include "lj_err.h"
21 #include "lj_str.h"
22 #include "lj_state.h"
23 #include "lj_ff.h"
24 #include "lj_lib.h"
26 /* Userdata payload for I/O file. */
27 typedef struct IOFileUD {
28 FILE *fp; /* File handle. */
29 uint32_t type; /* File type. */
30 } IOFileUD;
32 #define IOFILE_TYPE_FILE 0 /* Regular file. */
33 #define IOFILE_TYPE_PIPE 1 /* Pipe. */
34 #define IOFILE_TYPE_STDF 2 /* Standard file handle. */
35 #define IOFILE_TYPE_MASK 3
37 #define IOFILE_FLAG_CLOSE 4 /* Close after io.lines() iterator. */
39 #define IOSTDF_UD(L, id) (&gcref(G(L)->gcroot[(id)])->ud)
40 #define IOSTDF_IOF(L, id) ((IOFileUD *)uddata(IOSTDF_UD(L, (id))))
42 /* -- Open/close helpers -------------------------------------------------- */
44 static IOFileUD *io_tofilep(lua_State *L)
46 if (!(L->base < L->top && tvisudata(L->base) &&
47 udataV(L->base)->udtype == UDTYPE_IO_FILE))
48 lj_err_argtype(L, 1, "FILE*");
49 return (IOFileUD *)uddata(udataV(L->base));
52 static IOFileUD *io_tofile(lua_State *L)
54 IOFileUD *iof = io_tofilep(L);
55 if (iof->fp == NULL)
56 lj_err_caller(L, LJ_ERR_IOCLFL);
57 return iof;
60 static FILE *io_stdfile(lua_State *L, ptrdiff_t id)
62 IOFileUD *iof = IOSTDF_IOF(L, id);
63 if (iof->fp == NULL)
64 lj_err_caller(L, LJ_ERR_IOSTDCL);
65 return iof->fp;
68 static IOFileUD *io_file_new(lua_State *L)
70 IOFileUD *iof = (IOFileUD *)lua_newuserdata(L, sizeof(IOFileUD));
71 GCudata *ud = udataV(L->top-1);
72 ud->udtype = UDTYPE_IO_FILE;
73 /* NOBARRIER: The GCudata is new (marked white). */
74 setgcrefr(ud->metatable, curr_func(L)->c.env);
75 iof->fp = NULL;
76 iof->type = IOFILE_TYPE_FILE;
77 return iof;
80 static IOFileUD *io_file_open(lua_State *L, const char *mode)
82 const char *fname = strdata(lj_lib_checkstr(L, 1));
83 IOFileUD *iof = io_file_new(L);
84 iof->fp = fopen(fname, mode);
85 if (iof->fp == NULL)
86 luaL_argerror(L, 1, lj_str_pushf(L, "%s: %s", fname, strerror(errno)));
87 return iof;
90 static int io_file_close(lua_State *L, IOFileUD *iof)
92 int ok;
93 if ((iof->type & IOFILE_TYPE_MASK) == IOFILE_TYPE_FILE) {
94 ok = (fclose(iof->fp) == 0);
95 } else if ((iof->type & IOFILE_TYPE_MASK) == IOFILE_TYPE_PIPE) {
96 int stat = -1;
97 #if LJ_TARGET_POSIX
98 stat = pclose(iof->fp);
99 #elif LJ_TARGET_WINDOWS
100 stat = _pclose(iof->fp);
101 #else
102 lua_assert(0);
103 return 0;
104 #endif
105 #if LJ_52
106 iof->fp = NULL;
107 return luaL_execresult(L, stat);
108 #else
109 ok = (stat != -1);
110 #endif
111 } else {
112 lua_assert((iof->type & IOFILE_TYPE_MASK) == IOFILE_TYPE_STDF);
113 setnilV(L->top++);
114 lua_pushliteral(L, "cannot close standard file");
115 return 2;
117 iof->fp = NULL;
118 return luaL_fileresult(L, ok, NULL);
121 /* -- Read/write helpers -------------------------------------------------- */
123 static int io_file_readnum(lua_State *L, FILE *fp)
125 lua_Number d;
126 if (fscanf(fp, LUA_NUMBER_SCAN, &d) == 1) {
127 if (LJ_DUALNUM) {
128 int32_t i = lj_num2int(d);
129 if (d == (lua_Number)i && !tvismzero((cTValue *)&d)) {
130 setintV(L->top++, i);
131 return 1;
134 setnumV(L->top++, d);
135 return 1;
136 } else {
137 setnilV(L->top++);
138 return 0;
142 static int io_file_testeof(lua_State *L, FILE *fp)
144 int c = getc(fp);
145 ungetc(c, fp);
146 lua_pushlstring(L, NULL, 0);
147 return (c != EOF);
150 static int io_file_readline(lua_State *L, FILE *fp, size_t chop)
152 luaL_Buffer b;
153 luaL_buffinit(L, &b);
154 for (;;) {
155 size_t len;
156 char *p = luaL_prepbuffer(&b);
157 if (fgets(p, LUAL_BUFFERSIZE, fp) == NULL) { /* EOF? */
158 luaL_pushresult(&b);
159 return (strV(L->top-1)->len > 0); /* Anything read? */
161 len = strlen(p);
162 if (len == 0 || p[len-1] != '\n') { /* Partial line? */
163 luaL_addsize(&b, len);
164 } else {
165 luaL_addsize(&b, len - chop); /* Keep or remove EOL. */
166 luaL_pushresult(&b);
167 return 1; /* Got at least an EOL. */
172 static int io_file_readchars(lua_State *L, FILE *fp, size_t n)
174 size_t rlen; /* how much to read */
175 size_t nr; /* number of chars actually read */
176 luaL_Buffer b;
177 luaL_buffinit(L, &b);
178 rlen = LUAL_BUFFERSIZE; /* try to read that much each time */
179 do {
180 char *p = luaL_prepbuffer(&b);
181 if (rlen > n) rlen = n; /* cannot read more than asked */
182 nr = fread(p, 1, rlen, fp);
183 luaL_addsize(&b, nr);
184 n -= nr; /* still have to read `n' chars */
185 } while (n > 0 && nr == rlen); /* until end of count or eof */
186 luaL_pushresult(&b); /* close buffer */
187 return (n == 0 || strV(L->top-1)->len > 0);
190 static int io_file_read(lua_State *L, FILE *fp, int start)
192 int ok, n, nargs = (int)(L->top - L->base) - start;
193 clearerr(fp);
194 if (nargs == 0) {
195 ok = io_file_readline(L, fp, 1);
196 n = start+1; /* Return 1 result. */
197 } else {
198 /* The results plus the buffers go on top of the args. */
199 luaL_checkstack(L, nargs+LUA_MINSTACK, "too many arguments");
200 ok = 1;
201 for (n = start; nargs-- && ok; n++) {
202 if (tvisstr(L->base+n)) {
203 const char *p = strVdata(L->base+n);
204 if (p[0] != '*')
205 lj_err_arg(L, n+1, LJ_ERR_INVOPT);
206 if (p[1] == 'n')
207 ok = io_file_readnum(L, fp);
208 else if ((p[1] & ~0x20) == 'L')
209 ok = io_file_readline(L, fp, (p[1] == 'l'));
210 else if (p[1] == 'a')
211 io_file_readchars(L, fp, ~((size_t)0));
212 else
213 lj_err_arg(L, n+1, LJ_ERR_INVFMT);
214 } else if (tvisnumber(L->base+n)) {
215 size_t len = (size_t)lj_lib_checkint(L, n+1);
216 ok = len ? io_file_readchars(L, fp, len) : io_file_testeof(L, fp);
217 } else {
218 lj_err_arg(L, n+1, LJ_ERR_INVOPT);
222 if (ferror(fp))
223 return luaL_fileresult(L, 0, NULL);
224 if (!ok)
225 setnilV(L->top-1); /* Replace last result with nil. */
226 return n - start;
229 static int io_file_write(lua_State *L, FILE *fp, int start)
231 cTValue *tv;
232 int status = 1;
233 for (tv = L->base+start; tv < L->top; tv++) {
234 if (tvisstr(tv)) {
235 MSize len = strV(tv)->len;
236 status = status && (fwrite(strVdata(tv), 1, len, fp) == len);
237 } else if (tvisint(tv)) {
238 char buf[LJ_STR_INTBUF];
239 char *p = lj_str_bufint(buf, intV(tv));
240 size_t len = (size_t)(buf+LJ_STR_INTBUF-p);
241 status = status && (fwrite(p, 1, len, fp) == len);
242 } else if (tvisnum(tv)) {
243 status = status && (fprintf(fp, LUA_NUMBER_FMT, numV(tv)) > 0);
244 } else {
245 lj_err_argt(L, (int)(tv - L->base) + 1, LUA_TSTRING);
248 if (LJ_52 && status) {
249 L->top = L->base+1;
250 if (start == 0)
251 setudataV(L, L->base, IOSTDF_UD(L, GCROOT_IO_OUTPUT));
252 return 1;
254 return luaL_fileresult(L, status, NULL);
257 static int io_file_iter(lua_State *L)
259 GCfunc *fn = curr_func(L);
260 IOFileUD *iof = uddata(udataV(&fn->c.upvalue[0]));
261 int n = fn->c.nupvalues - 1;
262 if (iof->fp == NULL)
263 lj_err_caller(L, LJ_ERR_IOCLFL);
264 L->top = L->base;
265 if (n) { /* Copy upvalues with options to stack. */
266 if (n > LUAI_MAXCSTACK)
267 lj_err_caller(L, LJ_ERR_STKOV);
268 lj_state_checkstack(L, (MSize)n);
269 memcpy(L->top, &fn->c.upvalue[1], n*sizeof(TValue));
270 L->top += n;
272 n = io_file_read(L, iof->fp, 0);
273 if (ferror(iof->fp))
274 lj_err_callermsg(L, strVdata(L->top-2));
275 if (tvisnil(L->base) && (iof->type & IOFILE_FLAG_CLOSE)) {
276 io_file_close(L, iof); /* Return values are ignored. */
277 return 0;
279 return n;
282 /* -- I/O file methods ---------------------------------------------------- */
284 #define LJLIB_MODULE_io_method
286 LJLIB_CF(io_method_close)
288 IOFileUD *iof = L->base < L->top ? io_tofile(L) :
289 IOSTDF_IOF(L, GCROOT_IO_OUTPUT);
290 return io_file_close(L, iof);
293 LJLIB_CF(io_method_read)
295 return io_file_read(L, io_tofile(L)->fp, 1);
298 LJLIB_CF(io_method_write) LJLIB_REC(io_write 0)
300 return io_file_write(L, io_tofile(L)->fp, 1);
303 LJLIB_CF(io_method_flush) LJLIB_REC(io_flush 0)
305 return luaL_fileresult(L, fflush(io_tofile(L)->fp) == 0, NULL);
308 LJLIB_CF(io_method_seek)
310 FILE *fp = io_tofile(L)->fp;
311 int opt = lj_lib_checkopt(L, 2, 1, "\3set\3cur\3end");
312 int64_t ofs = 0;
313 cTValue *o;
314 int res;
315 if (opt == 0) opt = SEEK_SET;
316 else if (opt == 1) opt = SEEK_CUR;
317 else if (opt == 2) opt = SEEK_END;
318 o = L->base+2;
319 if (o < L->top) {
320 if (tvisint(o))
321 ofs = (int64_t)intV(o);
322 else if (tvisnum(o))
323 ofs = (int64_t)numV(o);
324 else if (!tvisnil(o))
325 lj_err_argt(L, 3, LUA_TNUMBER);
327 #if LJ_TARGET_POSIX
328 res = fseeko(fp, ofs, opt);
329 #elif _MSC_VER >= 1400
330 res = _fseeki64(fp, ofs, opt);
331 #elif defined(__MINGW32__)
332 res = fseeko64(fp, ofs, opt);
333 #else
334 res = fseek(fp, (long)ofs, opt);
335 #endif
336 if (res)
337 return luaL_fileresult(L, 0, NULL);
338 #if LJ_TARGET_POSIX
339 ofs = ftello(fp);
340 #elif _MSC_VER >= 1400
341 ofs = _ftelli64(fp);
342 #elif defined(__MINGW32__)
343 ofs = ftello64(fp);
344 #else
345 ofs = (int64_t)ftell(fp);
346 #endif
347 setint64V(L->top-1, ofs);
348 return 1;
351 LJLIB_CF(io_method_setvbuf)
353 FILE *fp = io_tofile(L)->fp;
354 int opt = lj_lib_checkopt(L, 2, -1, "\4full\4line\2no");
355 size_t sz = (size_t)lj_lib_optint(L, 3, LUAL_BUFFERSIZE);
356 if (opt == 0) opt = _IOFBF;
357 else if (opt == 1) opt = _IOLBF;
358 else if (opt == 2) opt = _IONBF;
359 return luaL_fileresult(L, setvbuf(fp, NULL, opt, sz) == 0, NULL);
362 LJLIB_CF(io_method_lines)
364 io_tofile(L);
365 lua_pushcclosure(L, io_file_iter, (int)(L->top - L->base));
366 return 1;
369 LJLIB_CF(io_method___gc)
371 IOFileUD *iof = io_tofilep(L);
372 if (iof->fp != NULL && (iof->type & IOFILE_TYPE_MASK) != IOFILE_TYPE_STDF)
373 io_file_close(L, iof);
374 return 0;
377 LJLIB_CF(io_method___tostring)
379 IOFileUD *iof = io_tofilep(L);
380 if (iof->fp != NULL)
381 lua_pushfstring(L, "file (%p)", iof->fp);
382 else
383 lua_pushliteral(L, "file (closed)");
384 return 1;
387 LJLIB_PUSH(top-1) LJLIB_SET(__index)
389 #include "lj_libdef.h"
391 /* -- I/O library functions ----------------------------------------------- */
393 #define LJLIB_MODULE_io
395 LJLIB_PUSH(top-2) LJLIB_SET(!) /* Set environment. */
397 LJLIB_CF(io_open)
399 const char *fname = strdata(lj_lib_checkstr(L, 1));
400 GCstr *s = lj_lib_optstr(L, 2);
401 const char *mode = s ? strdata(s) : "r";
402 IOFileUD *iof = io_file_new(L);
403 iof->fp = fopen(fname, mode);
404 return iof->fp != NULL ? 1 : luaL_fileresult(L, 0, fname);
407 LJLIB_CF(io_popen)
409 #if LJ_TARGET_POSIX || LJ_TARGET_WINDOWS
410 const char *fname = strdata(lj_lib_checkstr(L, 1));
411 GCstr *s = lj_lib_optstr(L, 2);
412 const char *mode = s ? strdata(s) : "r";
413 IOFileUD *iof = io_file_new(L);
414 iof->type = IOFILE_TYPE_PIPE;
415 #if LJ_TARGET_POSIX
416 fflush(NULL);
417 iof->fp = popen(fname, mode);
418 #else
419 iof->fp = _popen(fname, mode);
420 #endif
421 return iof->fp != NULL ? 1 : luaL_fileresult(L, 0, fname);
422 #else
423 return luaL_error(L, LUA_QL("popen") " not supported");
424 #endif
427 LJLIB_CF(io_tmpfile)
429 IOFileUD *iof = io_file_new(L);
430 #if LJ_TARGET_PS3
431 iof->fp = NULL; errno = ENOSYS;
432 #else
433 iof->fp = tmpfile();
434 #endif
435 return iof->fp != NULL ? 1 : luaL_fileresult(L, 0, NULL);
438 LJLIB_CF(io_close)
440 return lj_cf_io_method_close(L);
443 LJLIB_CF(io_read)
445 return io_file_read(L, io_stdfile(L, GCROOT_IO_INPUT), 0);
448 LJLIB_CF(io_write) LJLIB_REC(io_write GCROOT_IO_OUTPUT)
450 return io_file_write(L, io_stdfile(L, GCROOT_IO_OUTPUT), 0);
453 LJLIB_CF(io_flush) LJLIB_REC(io_flush GCROOT_IO_OUTPUT)
455 return luaL_fileresult(L, fflush(io_stdfile(L, GCROOT_IO_OUTPUT)) == 0, NULL);
458 static int io_std_getset(lua_State *L, ptrdiff_t id, const char *mode)
460 if (L->base < L->top && !tvisnil(L->base)) {
461 if (tvisudata(L->base)) {
462 io_tofile(L);
463 L->top = L->base+1;
464 } else {
465 io_file_open(L, mode);
467 /* NOBARRIER: The standard I/O handles are GC roots. */
468 setgcref(G(L)->gcroot[id], gcV(L->top-1));
469 } else {
470 setudataV(L, L->top++, IOSTDF_UD(L, id));
472 return 1;
475 LJLIB_CF(io_input)
477 return io_std_getset(L, GCROOT_IO_INPUT, "r");
480 LJLIB_CF(io_output)
482 return io_std_getset(L, GCROOT_IO_OUTPUT, "w");
485 LJLIB_CF(io_lines)
487 if (L->base == L->top) setnilV(L->top++);
488 if (!tvisnil(L->base)) { /* io.lines(fname) */
489 IOFileUD *iof = io_file_open(L, "r");
490 iof->type = IOFILE_TYPE_FILE|IOFILE_FLAG_CLOSE;
491 L->top--;
492 setudataV(L, L->base, udataV(L->top));
493 } else { /* io.lines() iterates over stdin. */
494 setudataV(L, L->base, IOSTDF_UD(L, GCROOT_IO_INPUT));
496 lua_pushcclosure(L, io_file_iter, (int)(L->top - L->base));
497 return 1;
500 LJLIB_CF(io_type)
502 cTValue *o = lj_lib_checkany(L, 1);
503 if (!(tvisudata(o) && udataV(o)->udtype == UDTYPE_IO_FILE))
504 setnilV(L->top++);
505 else if (((IOFileUD *)uddata(udataV(o)))->fp != NULL)
506 lua_pushliteral(L, "file");
507 else
508 lua_pushliteral(L, "closed file");
509 return 1;
512 #include "lj_libdef.h"
514 /* ------------------------------------------------------------------------ */
516 static GCobj *io_std_new(lua_State *L, FILE *fp, const char *name)
518 IOFileUD *iof = (IOFileUD *)lua_newuserdata(L, sizeof(IOFileUD));
519 GCudata *ud = udataV(L->top-1);
520 ud->udtype = UDTYPE_IO_FILE;
521 /* NOBARRIER: The GCudata is new (marked white). */
522 setgcref(ud->metatable, gcV(L->top-3));
523 iof->fp = fp;
524 iof->type = IOFILE_TYPE_STDF;
525 lua_setfield(L, -2, name);
526 return obj2gco(ud);
529 LUALIB_API int luaopen_io(lua_State *L)
531 LJ_LIB_REG(L, NULL, io_method);
532 copyTV(L, L->top, L->top-1); L->top++;
533 lua_setfield(L, LUA_REGISTRYINDEX, LUA_FILEHANDLE);
534 LJ_LIB_REG(L, LUA_IOLIBNAME, io);
535 setgcref(G(L)->gcroot[GCROOT_IO_INPUT], io_std_new(L, stdin, "stdin"));
536 setgcref(G(L)->gcroot[GCROOT_IO_OUTPUT], io_std_new(L, stdout, "stdout"));
537 io_std_new(L, stderr, "stderr");
538 return 1;