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