diff options
Diffstat (limited to '')
-rw-r--r-- | libraries/luajit-2.0/src/lib_io.c | 533 |
1 files changed, 533 insertions, 0 deletions
diff --git a/libraries/luajit-2.0/src/lib_io.c b/libraries/luajit-2.0/src/lib_io.c new file mode 100644 index 0000000..7a59cc4 --- /dev/null +++ b/libraries/luajit-2.0/src/lib_io.c | |||
@@ -0,0 +1,533 @@ | |||
1 | /* | ||
2 | ** I/O library. | ||
3 | ** Copyright (C) 2005-2011 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 | */ | ||
8 | |||
9 | #include <errno.h> | ||
10 | #include <stdio.h> | ||
11 | |||
12 | #define lib_io_c | ||
13 | #define LUA_LIB | ||
14 | |||
15 | #include "lua.h" | ||
16 | #include "lauxlib.h" | ||
17 | #include "lualib.h" | ||
18 | |||
19 | #include "lj_obj.h" | ||
20 | #include "lj_gc.h" | ||
21 | #include "lj_err.h" | ||
22 | #include "lj_str.h" | ||
23 | #include "lj_ff.h" | ||
24 | #include "lj_trace.h" | ||
25 | #include "lj_lib.h" | ||
26 | |||
27 | /* Userdata payload for I/O file. */ | ||
28 | typedef struct IOFileUD { | ||
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)))) | ||
42 | |||
43 | /* -- Error handling ------------------------------------------------------ */ | ||
44 | |||
45 | static int io_pushresult(lua_State *L, int ok, const char *fname) | ||
46 | { | ||
47 | if (ok) { | ||
48 | setboolV(L->top++, 1); | ||
49 | return 1; | ||
50 | } else { | ||
51 | int en = errno; /* Lua API calls may change this value. */ | ||
52 | setnilV(L->top++); | ||
53 | if (fname) | ||
54 | lua_pushfstring(L, "%s: %s", fname, strerror(en)); | ||
55 | else | ||
56 | lua_pushfstring(L, "%s", strerror(en)); | ||
57 | setintV(L->top++, en); | ||
58 | lj_trace_abort(G(L)); | ||
59 | return 3; | ||
60 | } | ||
61 | } | ||
62 | |||
63 | /* -- Open/close helpers -------------------------------------------------- */ | ||
64 | |||
65 | static IOFileUD *io_tofilep(lua_State *L) | ||
66 | { | ||
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)); | ||
71 | } | ||
72 | |||
73 | static IOFileUD *io_tofile(lua_State *L) | ||
74 | { | ||
75 | IOFileUD *iof = io_tofilep(L); | ||
76 | if (iof->fp == NULL) | ||
77 | lj_err_caller(L, LJ_ERR_IOCLFL); | ||
78 | return iof; | ||
79 | } | ||
80 | |||
81 | static FILE *io_stdfile(lua_State *L, ptrdiff_t id) | ||
82 | { | ||
83 | IOFileUD *iof = IOSTDF_IOF(L, id); | ||
84 | if (iof->fp == NULL) | ||
85 | lj_err_caller(L, LJ_ERR_IOSTDCL); | ||
86 | return iof->fp; | ||
87 | } | ||
88 | |||
89 | static 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 | } | ||
100 | |||
101 | static IOFileUD *io_file_open(lua_State *L, const char *mode) | ||
102 | { | ||
103 | const char *fname = strdata(lj_lib_checkstr(L, 1)); | ||
104 | IOFileUD *iof = io_file_new(L); | ||
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; | ||
109 | } | ||
110 | |||
111 | static int io_file_close(lua_State *L, IOFileUD *iof) | ||
112 | { | ||
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) { | ||
117 | #if LJ_TARGET_POSIX | ||
118 | ok = (pclose(iof->fp) != -1); | ||
119 | #elif LJ_TARGET_WINDOWS | ||
120 | ok = (_pclose(iof->fp) != -1); | ||
121 | #else | ||
122 | ok = 0; | ||
123 | #endif | ||
124 | } else { | ||
125 | lua_assert((iof->type & IOFILE_TYPE_MASK) == IOFILE_TYPE_STDF); | ||
126 | setnilV(L->top++); | ||
127 | lua_pushliteral(L, "cannot close standard file"); | ||
128 | return 2; | ||
129 | } | ||
130 | iof->fp = NULL; | ||
131 | return io_pushresult(L, ok, NULL); | ||
132 | } | ||
133 | |||
134 | /* -- Read/write helpers -------------------------------------------------- */ | ||
135 | |||
136 | static int io_file_readnum(lua_State *L, FILE *fp) | ||
137 | { | ||
138 | lua_Number d; | ||
139 | if (fscanf(fp, LUA_NUMBER_SCAN, &d) == 1) { | ||
140 | if (LJ_DUALNUM) { | ||
141 | int32_t i = lj_num2int(d); | ||
142 | if (d == (lua_Number)i && !tvismzero((cTValue *)&d)) { | ||
143 | setintV(L->top++, i); | ||
144 | return 1; | ||
145 | } | ||
146 | } | ||
147 | setnumV(L->top++, d); | ||
148 | return 1; | ||
149 | } else { | ||
150 | setnilV(L->top++); | ||
151 | return 0; | ||
152 | } | ||
153 | } | ||
154 | |||
155 | static int io_file_testeof(lua_State *L, FILE *fp) | ||
156 | { | ||
157 | int c = getc(fp); | ||
158 | ungetc(c, fp); | ||
159 | lua_pushlstring(L, NULL, 0); | ||
160 | return (c != EOF); | ||
161 | } | ||
162 | |||
163 | static int io_file_readline(lua_State *L, FILE *fp, size_t chop) | ||
164 | { | ||
165 | luaL_Buffer b; | ||
166 | luaL_buffinit(L, &b); | ||
167 | for (;;) { | ||
168 | size_t len; | ||
169 | char *p = luaL_prepbuffer(&b); | ||
170 | if (fgets(p, LUAL_BUFFERSIZE, fp) == NULL) { /* EOF? */ | ||
171 | luaL_pushresult(&b); | ||
172 | return (strV(L->top-1)->len > 0); /* Anything read? */ | ||
173 | } | ||
174 | len = strlen(p); | ||
175 | if (len == 0 || p[len-1] != '\n') { /* Partial line? */ | ||
176 | luaL_addsize(&b, len); | ||
177 | } else { | ||
178 | luaL_addsize(&b, len - chop); /* Keep or remove EOL. */ | ||
179 | luaL_pushresult(&b); | ||
180 | return 1; /* Got at least an EOL. */ | ||
181 | } | ||
182 | } | ||
183 | } | ||
184 | |||
185 | static int io_file_readchars(lua_State *L, FILE *fp, size_t n) | ||
186 | { | ||
187 | size_t rlen; /* how much to read */ | ||
188 | size_t nr; /* number of chars actually read */ | ||
189 | luaL_Buffer b; | ||
190 | luaL_buffinit(L, &b); | ||
191 | rlen = LUAL_BUFFERSIZE; /* try to read that much each time */ | ||
192 | do { | ||
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); | ||
201 | } | ||
202 | |||
203 | static int io_file_read(lua_State *L, FILE *fp, int start) | ||
204 | { | ||
205 | int ok, n, nargs = (int)(L->top - L->base) - start; | ||
206 | clearerr(fp); | ||
207 | if (nargs == 0) { | ||
208 | ok = io_file_readline(L, fp, 1); | ||
209 | n = start+1; /* Return 1 result. */ | ||
210 | } else { | ||
211 | /* The results plus the buffers go on top of the args. */ | ||
212 | luaL_checkstack(L, nargs+LUA_MINSTACK, "too many arguments"); | ||
213 | ok = 1; | ||
214 | for (n = start; nargs-- && ok; n++) { | ||
215 | if (tvisstr(L->base+n)) { | ||
216 | const char *p = strVdata(L->base+n); | ||
217 | if (p[0] != '*') | ||
218 | lj_err_arg(L, n+1, LJ_ERR_INVOPT); | ||
219 | if (p[1] == 'n') | ||
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)); | ||
225 | else | ||
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); | ||
230 | } else { | ||
231 | lj_err_arg(L, n+1, LJ_ERR_INVOPT); | ||
232 | } | ||
233 | } | ||
234 | } | ||
235 | if (ferror(fp)) | ||
236 | return io_pushresult(L, 0, NULL); | ||
237 | if (!ok) | ||
238 | setnilV(L->top-1); /* Replace last result with nil. */ | ||
239 | return n - start; | ||
240 | } | ||
241 | |||
242 | static int io_file_write(lua_State *L, FILE *fp, int start) | ||
243 | { | ||
244 | cTValue *tv; | ||
245 | int status = 1; | ||
246 | for (tv = L->base+start; tv < L->top; tv++) { | ||
247 | if (tvisstr(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); | ||
257 | } else { | ||
258 | lj_err_argt(L, (int)(tv - L->base) + 1, LUA_TSTRING); | ||
259 | } | ||
260 | } | ||
261 | return io_pushresult(L, status, NULL); | ||
262 | } | ||
263 | |||
264 | /* -- I/O file methods ---------------------------------------------------- */ | ||
265 | |||
266 | #define LJLIB_MODULE_io_method | ||
267 | |||
268 | LJLIB_CF(io_method_close) | ||
269 | { | ||
270 | IOFileUD *iof = L->base < L->top ? io_tofile(L) : | ||
271 | IOSTDF_IOF(L, GCROOT_IO_OUTPUT); | ||
272 | return io_file_close(L, iof); | ||
273 | } | ||
274 | |||
275 | LJLIB_CF(io_method_read) | ||
276 | { | ||
277 | return io_file_read(L, io_tofile(L)->fp, 1); | ||
278 | } | ||
279 | |||
280 | LJLIB_CF(io_method_write) LJLIB_REC(io_write 0) | ||
281 | { | ||
282 | return io_file_write(L, io_tofile(L)->fp, 1); | ||
283 | } | ||
284 | |||
285 | LJLIB_CF(io_method_flush) LJLIB_REC(io_flush 0) | ||
286 | { | ||
287 | return io_pushresult(L, fflush(io_tofile(L)->fp) == 0, NULL); | ||
288 | } | ||
289 | |||
290 | LJLIB_CF(io_method_seek) | ||
291 | { | ||
292 | FILE *fp = io_tofile(L)->fp; | ||
293 | int opt = lj_lib_checkopt(L, 2, 1, "\3set\3cur\3end"); | ||
294 | int64_t ofs = 0; | ||
295 | cTValue *o; | ||
296 | int res; | ||
297 | if (opt == 0) opt = SEEK_SET; | ||
298 | else if (opt == 1) opt = SEEK_CUR; | ||
299 | else if (opt == 2) opt = SEEK_END; | ||
300 | o = L->base+2; | ||
301 | if (o < L->top) { | ||
302 | if (tvisint(o)) | ||
303 | ofs = (int64_t)intV(o); | ||
304 | else if (tvisnum(o)) | ||
305 | ofs = (int64_t)numV(o); | ||
306 | else if (!tvisnil(o)) | ||
307 | lj_err_argt(L, 3, LUA_TNUMBER); | ||
308 | } | ||
309 | #if LJ_TARGET_POSIX | ||
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); | ||
315 | #else | ||
316 | res = fseek(fp, (long)ofs, opt); | ||
317 | #endif | ||
318 | if (res) | ||
319 | return io_pushresult(L, 0, NULL); | ||
320 | #if LJ_TARGET_POSIX | ||
321 | ofs = ftello(fp); | ||
322 | #elif _MSC_VER >= 1400 | ||
323 | ofs = _ftelli64(fp); | ||
324 | #elif defined(__MINGW32__) | ||
325 | ofs = ftello64(fp); | ||
326 | #else | ||
327 | ofs = (int64_t)ftell(fp); | ||
328 | #endif | ||
329 | setint64V(L->top-1, ofs); | ||
330 | return 1; | ||
331 | } | ||
332 | |||
333 | LJLIB_CF(io_method_setvbuf) | ||
334 | { | ||
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); | ||
342 | } | ||
343 | |||
344 | LJLIB_PUSH(top-2) /* io_lines_iter */ | ||
345 | LJLIB_CF(io_method_lines) | ||
346 | { | ||
347 | io_tofile(L); | ||
348 | setfuncV(L, L->top, funcV(lj_lib_upvalue(L, 1))); | ||
349 | setudataV(L, L->top+1, udataV(L->base)); | ||
350 | L->top += 2; | ||
351 | return 2; | ||
352 | } | ||
353 | |||
354 | LJLIB_CF(io_method___gc) | ||
355 | { | ||
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); | ||
359 | return 0; | ||
360 | } | ||
361 | |||
362 | LJLIB_CF(io_method___tostring) | ||
363 | { | ||
364 | IOFileUD *iof = io_tofilep(L); | ||
365 | if (iof->fp != NULL) | ||
366 | lua_pushfstring(L, "file (%p)", iof->fp); | ||
367 | else | ||
368 | lua_pushliteral(L, "file (closed)"); | ||
369 | return 1; | ||
370 | } | ||
371 | |||
372 | LJLIB_PUSH(top-1) LJLIB_SET(__index) | ||
373 | |||
374 | #include "lj_libdef.h" | ||
375 | |||
376 | /* -- I/O library functions ----------------------------------------------- */ | ||
377 | |||
378 | #define LJLIB_MODULE_io | ||
379 | |||
380 | LJLIB_PUSH(top-2) LJLIB_SET(!) /* Set environment. */ | ||
381 | |||
382 | LJLIB_CF(io_open) | ||
383 | { | ||
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); | ||
390 | } | ||
391 | |||
392 | LJLIB_CF(io_popen) | ||
393 | { | ||
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; | ||
400 | #if LJ_TARGET_POSIX | ||
401 | fflush(NULL); | ||
402 | iof->fp = popen(fname, mode); | ||
403 | #else | ||
404 | iof->fp = _popen(fname, mode); | ||
405 | #endif | ||
406 | return iof->fp != NULL ? 1 : io_pushresult(L, 0, fname); | ||
407 | #else | ||
408 | luaL_error(L, LUA_QL("popen") " not supported"); | ||
409 | #endif | ||
410 | } | ||
411 | |||
412 | LJLIB_CF(io_tmpfile) | ||
413 | { | ||
414 | IOFileUD *iof = io_file_new(L); | ||
415 | iof->fp = tmpfile(); | ||
416 | return iof->fp != NULL ? 1 : io_pushresult(L, 0, NULL); | ||
417 | } | ||
418 | |||
419 | LJLIB_CF(io_close) | ||
420 | { | ||
421 | return lj_cf_io_method_close(L); | ||
422 | } | ||
423 | |||
424 | LJLIB_CF(io_read) | ||
425 | { | ||
426 | return io_file_read(L, io_stdfile(L, GCROOT_IO_INPUT), 0); | ||
427 | } | ||
428 | |||
429 | LJLIB_CF(io_write) LJLIB_REC(io_write GCROOT_IO_OUTPUT) | ||
430 | { | ||
431 | return io_file_write(L, io_stdfile(L, GCROOT_IO_OUTPUT), 0); | ||
432 | } | ||
433 | |||
434 | LJLIB_CF(io_flush) LJLIB_REC(io_flush GCROOT_IO_OUTPUT) | ||
435 | { | ||
436 | return io_pushresult(L, fflush(io_stdfile(L, GCROOT_IO_OUTPUT)) == 0, NULL); | ||
437 | } | ||
438 | |||
439 | static int io_std_getset(lua_State *L, ptrdiff_t id, const char *mode) | ||
440 | { | ||
441 | if (L->base < L->top && !tvisnil(L->base)) { | ||
442 | if (tvisudata(L->base)) { | ||
443 | io_tofile(L); | ||
444 | L->top = L->base+1; | ||
445 | } else { | ||
446 | io_file_open(L, mode); | ||
447 | } | ||
448 | /* NOBARRIER: The standard I/O handles are GC roots. */ | ||
449 | setgcref(G(L)->gcroot[id], gcV(L->top-1)); | ||
450 | } else { | ||
451 | setudataV(L, L->top++, IOSTDF_UD(L, id)); | ||
452 | } | ||
453 | return 1; | ||
454 | } | ||
455 | |||
456 | LJLIB_CF(io_input) | ||
457 | { | ||
458 | return io_std_getset(L, GCROOT_IO_INPUT, "r"); | ||
459 | } | ||
460 | |||
461 | LJLIB_CF(io_output) | ||
462 | { | ||
463 | return io_std_getset(L, GCROOT_IO_OUTPUT, "w"); | ||
464 | } | ||
465 | |||
466 | LJLIB_NOREG LJLIB_CF(io_lines_iter) | ||
467 | { | ||
468 | IOFileUD *iof = io_tofile(L); | ||
469 | int ok = io_file_readline(L, iof->fp, 1); | ||
470 | if (ferror(iof->fp)) | ||
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). */ | ||
474 | return ok; | ||
475 | } | ||
476 | |||
477 | LJLIB_PUSH(top-3) /* io_lines_iter */ | ||
478 | LJLIB_CF(io_lines) | ||
479 | { | ||
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)); | ||
487 | L->top += 2; | ||
488 | } | ||
489 | return 2; | ||
490 | } | ||
491 | |||
492 | LJLIB_CF(io_type) | ||
493 | { | ||
494 | cTValue *o = lj_lib_checkany(L, 1); | ||
495 | if (!(tvisudata(o) && udataV(o)->udtype == UDTYPE_IO_FILE)) | ||
496 | setnilV(L->top++); | ||
497 | else if (((IOFileUD *)uddata(udataV(o)))->fp != NULL) | ||
498 | lua_pushliteral(L, "file"); | ||
499 | else | ||
500 | lua_pushliteral(L, "closed file"); | ||
501 | return 1; | ||
502 | } | ||
503 | |||
504 | #include "lj_libdef.h" | ||
505 | |||
506 | /* ------------------------------------------------------------------------ */ | ||
507 | |||
508 | static GCobj *io_std_new(lua_State *L, FILE *fp, const char *name) | ||
509 | { | ||
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)); | ||
515 | iof->fp = fp; | ||
516 | iof->type = IOFILE_TYPE_STDF; | ||
517 | lua_setfield(L, -2, name); | ||
518 | return obj2gco(ud); | ||
519 | } | ||
520 | |||
521 | LUALIB_API int luaopen_io(lua_State *L) | ||
522 | { | ||
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"); | ||
531 | return 1; | ||
532 | } | ||
533 | |||