1/*
2** $Id: liolib.c $
3** Standard I/O (and system) library
4** See Copyright Notice in lua.h
5*/
6
7#define liolib_c
8#define LUA_LIB
9
10#include "lprefix.h"
11
12
13#include <ctype.h>
14#include <errno.h>
15#include <locale.h>
16#include <stdio.h>
17#include <stdlib.h>
18#include <string.h>
19
20#include "lua.h"
21
22#include "lauxlib.h"
23#include "lualib.h"
24
25
26
27
28/* Define this externally */
29extern FILE* lua_user_fopen(const char* fname,
30 const char* mode);
31
32
33/*
34** Change this macro to accept other modes for 'fopen' besides
35** the standard ones.
36*/
37#if !defined(l_checkmode)
38
39/* accepted extensions to 'mode' in 'fopen' */
40#if !defined(L_MODEEXT)
41#define L_MODEEXT "b"
42#endif
43
44/* Check whether 'mode' matches '[rwa]%+?[L_MODEEXT]*' */
45static int l_checkmode (const char *mode) {
46 return (*mode != '\0' && strchr("rwa", *(mode++)) != NULL &&
47 (*mode != '+' || ((void)(++mode), 1)) && /* skip if char is '+' */
48 (strspn(mode, L_MODEEXT) == strlen(mode))); /* check extensions */
49}
50
51#endif
52
53/*
54** {======================================================
55** l_popen spawns a new process connected to the current
56** one through the file streams.
57** =======================================================
58*/
59
60#if !defined(l_popen) /* { */
61
62#if defined(LUA_USE_POSIX) /* { */
63
64#define l_popen(L,c,m) (fflush(NULL), popen(c,m))
65#define l_pclose(L,file) (pclose(file))
66
67#elif defined(LUA_USE_WINDOWS) /* }{ */
68
69#define l_popen(L,c,m) (_popen(c,m))
70#define l_pclose(L,file) (_pclose(file))
71
72#if !defined(l_checkmodep)
73/* Windows accepts "[rw][bt]?" as valid modes */
74#define l_checkmodep(m) ((m[0] == 'r' || m[0] == 'w') && \
75 (m[1] == '\0' || ((m[1] == 'b' || m[1] == 't') && m[2] == '\0')))
76#endif
77
78#else /* }{ */
79
80/* ISO C definitions */
81#define l_popen(L,c,m) \
82 ((void)c, (void)m, \
83 luaL_error(L, "'popen' not supported"), \
84 (FILE*)0)
85#define l_pclose(L,file) ((void)L, (void)file, -1)
86
87#endif /* } */
88
89#endif /* } */
90
91
92#if !defined(l_checkmodep)
93/* By default, Lua accepts only "r" or "w" as valid modes */
94#define l_checkmodep(m) ((m[0] == 'r' || m[0] == 'w') && m[1] == '\0')
95#endif
96
97/* }====================================================== */
98
99
100#if !defined(l_getc) /* { */
101
102#if defined(LUA_USE_POSIX)
103#define l_getc(f) getc_unlocked(f)
104#define l_lockfile(f) flockfile(f)
105#define l_unlockfile(f) funlockfile(f)
106#else
107#define l_getc(f) getc(f)
108#define l_lockfile(f) ((void)0)
109#define l_unlockfile(f) ((void)0)
110#endif
111
112#endif /* } */
113
114
115/*
116** {======================================================
117** l_fseek: configuration for longer offsets
118** =======================================================
119*/
120
121#if !defined(l_fseek) /* { */
122
123#if defined(LUA_USE_POSIX) /* { */
124
125#include <sys/types.h>
126
127#define l_fseek(f,o,w) fseeko(f,o,w)
128#define l_ftell(f) ftello(f)
129#define l_seeknum off_t
130
131#elif defined(LUA_USE_WINDOWS) && !defined(_CRTIMP_TYPEINFO) \
132 && defined(_MSC_VER) && (_MSC_VER >= 1400) /* }{ */
133
134/* Windows (but not DDK) and Visual C++ 2005 or higher */
135#define l_fseek(f,o,w) _fseeki64(f,o,w)
136#define l_ftell(f) _ftelli64(f)
137#define l_seeknum __int64
138
139#else /* }{ */
140
141/* ISO C definitions */
142#define l_fseek(f,o,w) fseek(f,o,w)
143#define l_ftell(f) ftell(f)
144#define l_seeknum long
145
146#endif /* } */
147
148#endif /* } */
149
150/* }====================================================== */
151
152
153
154#define IO_PREFIX "_IO_"
155#define IOPREF_LEN (sizeof(IO_PREFIX)/sizeof(char) - 1)
156#define IO_INPUT (IO_PREFIX "input")
157#define IO_OUTPUT (IO_PREFIX "output")
158
159
160typedef luaL_Stream LStream;
161
162
163#define tolstream(L) ((LStream *)luaL_checkudata(L, 1, LUA_FILEHANDLE))
164
165#define isclosed(p) ((p)->closef == NULL)
166
167
168static int io_type (lua_State *L) {
169 LStream *p;
170 luaL_checkany(L, 1);
171 p = (LStream *)luaL_testudata(L, 1, LUA_FILEHANDLE);
172 if (p == NULL)
173 luaL_pushfail(L); /* not a file */
174 else if (isclosed(p))
175 lua_pushliteral(L, "closed file");
176 else
177 lua_pushliteral(L, "file");
178 return 1;
179}
180
181
182static int f_tostring (lua_State *L) {
183 LStream *p = tolstream(L);
184 if (isclosed(p))
185 lua_pushliteral(L, "file (closed)");
186 else
187 lua_pushfstring(L, "file (%p)", p->f);
188 return 1;
189}
190
191
192static FILE *tofile (lua_State *L) {
193 LStream *p = tolstream(L);
194 if (l_unlikely(isclosed(p)))
195 luaL_error(L, "attempt to use a closed file");
196 lua_assert(p->f);
197 return p->f;
198}
199
200
201/*
202** When creating file handles, always creates a 'closed' file handle
203** before opening the actual file; so, if there is a memory error, the
204** handle is in a consistent state.
205*/
206static LStream *newprefile (lua_State *L) {
207 LStream *p = (LStream *)lua_newuserdatauv(L, sizeof(LStream), 0);
208 p->closef = NULL; /* mark file handle as 'closed' */
209 luaL_setmetatable(L, LUA_FILEHANDLE);
210 return p;
211}
212
213
214/*
215** Calls the 'close' function from a file handle. The 'volatile' avoids
216** a bug in some versions of the Clang compiler (e.g., clang 3.0 for
217** 32 bits).
218*/
219static int aux_close (lua_State *L) {
220 LStream *p = tolstream(L);
221 volatile lua_CFunction cf = p->closef;
222 p->closef = NULL; /* mark stream as closed */
223 return (*cf)(L); /* close it */
224}
225
226
227static int f_close (lua_State *L) {
228 tofile(L); /* make sure argument is an open stream */
229 return aux_close(L);
230}
231
232
233static int io_close (lua_State *L) {
234 if (lua_isnone(L, 1)) /* no argument? */
235 lua_getfield(L, LUA_REGISTRYINDEX, IO_OUTPUT); /* use default output */
236 return f_close(L);
237}
238
239
240static int f_gc (lua_State *L) {
241 LStream *p = tolstream(L);
242 if (!isclosed(p) && p->f != NULL)
243 aux_close(L); /* ignore closed and incompletely open files */
244 return 0;
245}
246
247
248/*
249** function to close regular files
250*/
251static int io_fclose (lua_State *L) {
252 LStream *p = tolstream(L);
253 int res = fclose(p->f);
254 return luaL_fileresult(L, (res == 0), NULL);
255}
256
257
258static LStream *newfile (lua_State *L) {
259 LStream *p = newprefile(L);
260 p->f = NULL;
261 p->closef = &io_fclose;
262 return p;
263}
264
265
266static void opencheck (lua_State *L, const char *fname, const char *mode) {
267 LStream *p = newfile(L);
268 p->f = lua_user_fopen(fname, mode);
269 if (l_unlikely(p->f == NULL))
270 luaL_error(L, "cannot open file '%s' (%s)", fname, strerror(errno));
271}
272
273
274static int io_open (lua_State *L) {
275 const char *filename = luaL_checkstring(L, 1);
276 const char *mode = luaL_optstring(L, 2, "r");
277 LStream *p = newfile(L);
278 const char *md = mode; /* to traverse/check mode */
279 luaL_argcheck(L, l_checkmode(md), 2, "invalid mode");
280 p->f = lua_user_fopen(filename, mode);
281 return (p->f == NULL) ? luaL_fileresult(L, 0, filename) : 1;
282}
283
284
285/*
286** function to close 'popen' files
287*/
288static int io_pclose (lua_State *L) {
289 LStream *p = tolstream(L);
290 errno = 0;
291 return luaL_execresult(L, l_pclose(L, p->f));
292}
293
294
295static int io_popen (lua_State *L) {
296 const char *filename = luaL_checkstring(L, 1);
297 const char *mode = luaL_optstring(L, 2, "r");
298 LStream *p = newprefile(L);
299 luaL_argcheck(L, l_checkmodep(mode), 2, "invalid mode");
300 p->f = l_popen(L, filename, mode);
301 p->closef = &io_pclose;
302 return (p->f == NULL) ? luaL_fileresult(L, 0, filename) : 1;
303}
304
305
306static int io_tmpfile (lua_State *L) {
307 LStream *p = newfile(L);
308 p->f = tmpfile();
309 return (p->f == NULL) ? luaL_fileresult(L, 0, NULL) : 1;
310}
311
312
313static FILE *getiofile (lua_State *L, const char *findex) {
314 LStream *p;
315 lua_getfield(L, LUA_REGISTRYINDEX, findex);
316 p = (LStream *)lua_touserdata(L, -1);
317 if (l_unlikely(isclosed(p)))
318 luaL_error(L, "default %s file is closed", findex + IOPREF_LEN);
319 return p->f;
320}
321
322
323static int g_iofile (lua_State *L, const char *f, const char *mode) {
324 if (!lua_isnoneornil(L, 1)) {
325 const char *filename = lua_tostring(L, 1);
326 if (filename)
327 opencheck(L, filename, mode);
328 else {
329 tofile(L); /* check that it's a valid file handle */
330 lua_pushvalue(L, 1);
331 }
332 lua_setfield(L, LUA_REGISTRYINDEX, f);
333 }
334 /* return current value */
335 lua_getfield(L, LUA_REGISTRYINDEX, f);
336 return 1;
337}
338
339
340static int io_input (lua_State *L) {
341 return g_iofile(L, IO_INPUT, "r");
342}
343
344
345static int io_output (lua_State *L) {
346 return g_iofile(L, IO_OUTPUT, "w");
347}
348
349
350static int io_readline (lua_State *L);
351
352
353/*
354** maximum number of arguments to 'f:lines'/'io.lines' (it + 3 must fit
355** in the limit for upvalues of a closure)
356*/
357#define MAXARGLINE 250
358
359/*
360** Auxiliary function to create the iteration function for 'lines'.
361** The iteration function is a closure over 'io_readline', with
362** the following upvalues:
363** 1) The file being read (first value in the stack)
364** 2) the number of arguments to read
365** 3) a boolean, true iff file has to be closed when finished ('toclose')
366** *) a variable number of format arguments (rest of the stack)
367*/
368static void aux_lines (lua_State *L, int toclose) {
369 int n = lua_gettop(L) - 1; /* number of arguments to read */
370 luaL_argcheck(L, n <= MAXARGLINE, MAXARGLINE + 2, "too many arguments");
371 lua_pushvalue(L, 1); /* file */
372 lua_pushinteger(L, n); /* number of arguments to read */
373 lua_pushboolean(L, toclose); /* close/not close file when finished */
374 lua_rotate(L, 2, 3); /* move the three values to their positions */
375 lua_pushcclosure(L, io_readline, 3 + n);
376}
377
378
379static int f_lines (lua_State *L) {
380 tofile(L); /* check that it's a valid file handle */
381 aux_lines(L, 0);
382 return 1;
383}
384
385
386/*
387** Return an iteration function for 'io.lines'. If file has to be
388** closed, also returns the file itself as a second result (to be
389** closed as the state at the exit of a generic for).
390*/
391static int io_lines (lua_State *L) {
392 int toclose;
393 if (lua_isnone(L, 1)) lua_pushnil(L); /* at least one argument */
394 if (lua_isnil(L, 1)) { /* no file name? */
395 lua_getfield(L, LUA_REGISTRYINDEX, IO_INPUT); /* get default input */
396 lua_replace(L, 1); /* put it at index 1 */
397 tofile(L); /* check that it's a valid file handle */
398 toclose = 0; /* do not close it after iteration */
399 }
400 else { /* open a new file */
401 const char *filename = luaL_checkstring(L, 1);
402 opencheck(L, filename, "r");
403 lua_replace(L, 1); /* put file at index 1 */
404 toclose = 1; /* close it after iteration */
405 }
406 aux_lines(L, toclose); /* push iteration function */
407 if (toclose) {
408 lua_pushnil(L); /* state */
409 lua_pushnil(L); /* control */
410 lua_pushvalue(L, 1); /* file is the to-be-closed variable (4th result) */
411 return 4;
412 }
413 else
414 return 1;
415}
416
417
418/*
419** {======================================================
420** READ
421** =======================================================
422*/
423
424
425/* maximum length of a numeral */
426#if !defined (L_MAXLENNUM)
427#define L_MAXLENNUM 200
428#endif
429
430
431/* auxiliary structure used by 'read_number' */
432typedef struct {
433 FILE *f; /* file being read */
434 int c; /* current character (look ahead) */
435 int n; /* number of elements in buffer 'buff' */
436 char buff[L_MAXLENNUM + 1]; /* +1 for ending '\0' */
437} RN;
438
439
440/*
441** Add current char to buffer (if not out of space) and read next one
442*/
443static int nextc (RN *rn) {
444 if (l_unlikely(rn->n >= L_MAXLENNUM)) { /* buffer overflow? */
445 rn->buff[0] = '\0'; /* invalidate result */
446 return 0; /* fail */
447 }
448 else {
449 rn->buff[rn->n++] = rn->c; /* save current char */
450 rn->c = l_getc(rn->f); /* read next one */
451 return 1;
452 }
453}
454
455
456/*
457** Accept current char if it is in 'set' (of size 2)
458*/
459static int test2 (RN *rn, const char *set) {
460 if (rn->c == set[0] || rn->c == set[1])
461 return nextc(rn);
462 else return 0;
463}
464
465
466/*
467** Read a sequence of (hex)digits
468*/
469static int readdigits (RN *rn, int hex) {
470 int count = 0;
471 while ((hex ? isxdigit(rn->c) : isdigit(rn->c)) && nextc(rn))
472 count++;
473 return count;
474}
475
476
477/*
478** Read a number: first reads a valid prefix of a numeral into a buffer.
479** Then it calls 'lua_stringtonumber' to check whether the format is
480** correct and to convert it to a Lua number.
481*/
482static int read_number (lua_State *L, FILE *f) {
483 RN rn;
484 int count = 0;
485 int hex = 0;
486 char decp[2];
487 rn.f = f; rn.n = 0;
488 decp[0] = lua_getlocaledecpoint(); /* get decimal point from locale */
489 decp[1] = '.'; /* always accept a dot */
490 l_lockfile(rn.f);
491 do { rn.c = l_getc(rn.f); } while (isspace(rn.c)); /* skip spaces */
492 test2(&rn, "-+"); /* optional sign */
493 if (test2(&rn, "00")) {
494 if (test2(&rn, "xX")) hex = 1; /* numeral is hexadecimal */
495 else count = 1; /* count initial '0' as a valid digit */
496 }
497 count += readdigits(&rn, hex); /* integral part */
498 if (test2(&rn, decp)) /* decimal point? */
499 count += readdigits(&rn, hex); /* fractional part */
500 if (count > 0 && test2(&rn, (hex ? "pP" : "eE"))) { /* exponent mark? */
501 test2(&rn, "-+"); /* exponent sign */
502 readdigits(&rn, 0); /* exponent digits */
503 }
504 ungetc(rn.c, rn.f); /* unread look-ahead char */
505 l_unlockfile(rn.f);
506 rn.buff[rn.n] = '\0'; /* finish string */
507 if (l_likely(lua_stringtonumber(L, rn.buff)))
508 return 1; /* ok, it is a valid number */
509 else { /* invalid format */
510 lua_pushnil(L); /* "result" to be removed */
511 return 0; /* read fails */
512 }
513}
514
515
516static int test_eof (lua_State *L, FILE *f) {
517 int c = getc(f);
518 ungetc(c, f); /* no-op when c == EOF */
519 lua_pushliteral(L, "");
520 return (c != EOF);
521}
522
523
524static int read_line (lua_State *L, FILE *f, int chop) {
525 luaL_Buffer b;
526 int c;
527 luaL_buffinit(L, &b);
528 do { /* may need to read several chunks to get whole line */
529 char *buff = luaL_prepbuffer(&b); /* preallocate buffer space */
530 int i = 0;
531 l_lockfile(f); /* no memory errors can happen inside the lock */
532 while (i < LUAL_BUFFERSIZE && (c = l_getc(f)) != EOF && c != '\n')
533 buff[i++] = c; /* read up to end of line or buffer limit */
534 l_unlockfile(f);
535 luaL_addsize(&b, i);
536 } while (c != EOF && c != '\n'); /* repeat until end of line */
537 if (!chop && c == '\n') /* want a newline and have one? */
538 luaL_addchar(&b, c); /* add ending newline to result */
539 luaL_pushresult(&b); /* close buffer */
540 /* return ok if read something (either a newline or something else) */
541 return (c == '\n' || lua_rawlen(L, -1) > 0);
542}
543
544
545static void read_all (lua_State *L, FILE *f) {
546 size_t nr;
547 luaL_Buffer b;
548 luaL_buffinit(L, &b);
549 do { /* read file in chunks of LUAL_BUFFERSIZE bytes */
550 char *p = luaL_prepbuffer(&b);
551 nr = fread(p, sizeof(char), LUAL_BUFFERSIZE, f);
552 luaL_addsize(&b, nr);
553 } while (nr == LUAL_BUFFERSIZE);
554 luaL_pushresult(&b); /* close buffer */
555}
556
557
558static int read_chars (lua_State *L, FILE *f, size_t n) {
559 size_t nr; /* number of chars actually read */
560 char *p;
561 luaL_Buffer b;
562 luaL_buffinit(L, &b);
563 p = luaL_prepbuffsize(&b, n); /* prepare buffer to read whole block */
564 nr = fread(p, sizeof(char), n, f); /* try to read 'n' chars */
565 luaL_addsize(&b, nr);
566 luaL_pushresult(&b); /* close buffer */
567 return (nr > 0); /* true iff read something */
568}
569
570
571static int g_read (lua_State *L, FILE *f, int first) {
572 int nargs = lua_gettop(L) - 1;
573 int n, success;
574 clearerr(f);
575 if (nargs == 0) { /* no arguments? */
576 success = read_line(L, f, 1);
577 n = first + 1; /* to return 1 result */
578 }
579 else {
580 /* ensure stack space for all results and for auxlib's buffer */
581 luaL_checkstack(L, nargs+LUA_MINSTACK, "too many arguments");
582 success = 1;
583 for (n = first; nargs-- && success; n++) {
584 if (lua_type(L, n) == LUA_TNUMBER) {
585 size_t l = (size_t)luaL_checkinteger(L, n);
586 success = (l == 0) ? test_eof(L, f) : read_chars(L, f, l);
587 }
588 else {
589 const char *p = luaL_checkstring(L, n);
590 if (*p == '*') p++; /* skip optional '*' (for compatibility) */
591 switch (*p) {
592 case 'n': /* number */
593 success = read_number(L, f);
594 break;
595 case 'l': /* line */
596 success = read_line(L, f, 1);
597 break;
598 case 'L': /* line with end-of-line */
599 success = read_line(L, f, 0);
600 break;
601 case 'a': /* file */
602 read_all(L, f); /* read entire file */
603 success = 1; /* always success */
604 break;
605 default:
606 return luaL_argerror(L, n, "invalid format");
607 }
608 }
609 }
610 }
611 if (ferror(f))
612 return luaL_fileresult(L, 0, NULL);
613 if (!success) {
614 lua_pop(L, 1); /* remove last result */
615 luaL_pushfail(L); /* push nil instead */
616 }
617 return n - first;
618}
619
620
621static int io_read (lua_State *L) {
622 return g_read(L, getiofile(L, IO_INPUT), 1);
623}
624
625
626static int f_read (lua_State *L) {
627 return g_read(L, tofile(L), 2);
628}
629
630
631/*
632** Iteration function for 'lines'.
633*/
634static int io_readline (lua_State *L) {
635 LStream *p = (LStream *)lua_touserdata(L, lua_upvalueindex(1));
636 int i;
637 int n = (int)lua_tointeger(L, lua_upvalueindex(2));
638 if (isclosed(p)) /* file is already closed? */
639 return luaL_error(L, "file is already closed");
640 lua_settop(L , 1);
641 luaL_checkstack(L, n, "too many arguments");
642 for (i = 1; i <= n; i++) /* push arguments to 'g_read' */
643 lua_pushvalue(L, lua_upvalueindex(3 + i));
644 n = g_read(L, p->f, 2); /* 'n' is number of results */
645 lua_assert(n > 0); /* should return at least a nil */
646 if (lua_toboolean(L, -n)) /* read at least one value? */
647 return n; /* return them */
648 else { /* first result is false: EOF or error */
649 if (n > 1) { /* is there error information? */
650 /* 2nd result is error message */
651 return luaL_error(L, "%s", lua_tostring(L, -n + 1));
652 }
653 if (lua_toboolean(L, lua_upvalueindex(3))) { /* generator created file? */
654 lua_settop(L, 0); /* clear stack */
655 lua_pushvalue(L, lua_upvalueindex(1)); /* push file at index 1 */
656 aux_close(L); /* close it */
657 }
658 return 0;
659 }
660}
661
662/* }====================================================== */
663
664
665static int g_write (lua_State *L, FILE *f, int arg) {
666 int nargs = lua_gettop(L) - arg;
667 int status = 1;
668 for (; nargs--; arg++) {
669 if (lua_type(L, arg) == LUA_TNUMBER) {
670 /* optimization: could be done exactly as for strings */
671 int len = lua_isinteger(L, arg)
672 ? fprintf(f, LUA_INTEGER_FMT,
673 (LUAI_UACINT)lua_tointeger(L, arg))
674 : fprintf(f, LUA_NUMBER_FMT,
675 (LUAI_UACNUMBER)lua_tonumber(L, arg));
676 status = status && (len > 0);
677 }
678 else {
679 size_t l;
680 const char *s = luaL_checklstring(L, arg, &l);
681 status = status && (fwrite(s, sizeof(char), l, f) == l);
682 }
683 }
684 if (l_likely(status))
685 return 1; /* file handle already on stack top */
686 else return luaL_fileresult(L, status, NULL);
687}
688
689
690static int io_write (lua_State *L) {
691 return g_write(L, getiofile(L, IO_OUTPUT), 1);
692}
693
694
695static int f_write (lua_State *L) {
696 FILE *f = tofile(L);
697 lua_pushvalue(L, 1); /* push file at the stack top (to be returned) */
698 return g_write(L, f, 2);
699}
700
701
702static int f_seek (lua_State *L) {
703 static const int mode[] = {SEEK_SET, SEEK_CUR, SEEK_END};
704 static const char *const modenames[] = {"set", "cur", "end", NULL};
705 FILE *f = tofile(L);
706 int op = luaL_checkoption(L, 2, "cur", modenames);
707 lua_Integer p3 = luaL_optinteger(L, 3, 0);
708 l_seeknum offset = (l_seeknum)p3;
709 luaL_argcheck(L, (lua_Integer)offset == p3, 3,
710 "not an integer in proper range");
711 op = l_fseek(f, offset, mode[op]);
712 if (l_unlikely(op))
713 return luaL_fileresult(L, 0, NULL); /* error */
714 else {
715 lua_pushinteger(L, (lua_Integer)l_ftell(f));
716 return 1;
717 }
718}
719
720
721static int f_setvbuf (lua_State *L) {
722 static const int mode[] = {_IONBF, _IOFBF, _IOLBF};
723 static const char *const modenames[] = {"no", "full", "line", NULL};
724 FILE *f = tofile(L);
725 int op = luaL_checkoption(L, 2, NULL, modenames);
726 lua_Integer sz = luaL_optinteger(L, 3, LUAL_BUFFERSIZE);
727 int res = setvbuf(f, NULL, mode[op], (size_t)sz);
728 return luaL_fileresult(L, res == 0, NULL);
729}
730
731
732
733static int io_flush (lua_State *L) {
734 return luaL_fileresult(L, fflush(getiofile(L, IO_OUTPUT)) == 0, NULL);
735}
736
737
738static int f_flush (lua_State *L) {
739 return luaL_fileresult(L, fflush(tofile(L)) == 0, NULL);
740}
741
742
743/*
744** functions for 'io' library
745*/
746static const luaL_Reg iolib[] = {
747 {"close", io_close},
748 {"flush", io_flush},
749 {"input", io_input},
750 {"lines", io_lines},
751 {"open", io_open},
752 {"output", io_output},
753 {"popen", io_popen},
754 {"read", io_read},
755 {"tmpfile", io_tmpfile},
756 {"type", io_type},
757 {"write", io_write},
758 {NULL, NULL}
759};
760
761
762/*
763** methods for file handles
764*/
765static const luaL_Reg meth[] = {
766 {"read", f_read},
767 {"write", f_write},
768 {"lines", f_lines},
769 {"flush", f_flush},
770 {"seek", f_seek},
771 {"close", f_close},
772 {"setvbuf", f_setvbuf},
773 {NULL, NULL}
774};
775
776
777/*
778** metamethods for file handles
779*/
780static const luaL_Reg metameth[] = {
781 {"__index", NULL}, /* place holder */
782 {"__gc", f_gc},
783 {"__close", f_gc},
784 {"__tostring", f_tostring},
785 {NULL, NULL}
786};
787
788
789static void createmeta (lua_State *L) {
790 luaL_newmetatable(L, LUA_FILEHANDLE); /* metatable for file handles */
791 luaL_setfuncs(L, metameth, 0); /* add metamethods to new metatable */
792 luaL_newlibtable(L, meth); /* create method table */
793 luaL_setfuncs(L, meth, 0); /* add file methods to method table */
794 lua_setfield(L, -2, "__index"); /* metatable.__index = method table */
795 lua_pop(L, 1); /* pop metatable */
796}
797
798
799/*
800** function to (not) close the standard files stdin, stdout, and stderr
801*/
802static int io_noclose (lua_State *L) {
803 LStream *p = tolstream(L);
804 p->closef = &io_noclose; /* keep file opened */
805 luaL_pushfail(L);
806 lua_pushliteral(L, "cannot close standard file");
807 return 2;
808}
809
810
811static void createstdfile (lua_State *L, FILE *f, const char *k,
812 const char *fname) {
813 LStream *p = newprefile(L);
814 p->f = f;
815 p->closef = &io_noclose;
816 if (k != NULL) {
817 lua_pushvalue(L, -1);
818 lua_setfield(L, LUA_REGISTRYINDEX, k); /* add file to registry */
819 }
820 lua_setfield(L, -2, fname); /* add file to module */
821}
822
823
824LUAMOD_API int luaopen_io (lua_State *L) {
825 luaL_newlib(L, iolib); /* new module */
826 createmeta(L);
827 /* create (and set) default files */
828 createstdfile(L, stdin, IO_INPUT, "stdin");
829 createstdfile(L, stdout, IO_OUTPUT, "stdout");
830 createstdfile(L, stderr, NULL, "stderr");
831 return 1;
832}
833