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