xref: /minix3/external/mit/lua/dist/src/liolib.c (revision 0a6a1f1d05b60e214de2f05a7310ddd1f0e590e7)
1*0a6a1f1dSLionel Sambuc /*	$NetBSD: liolib.c,v 1.4 2015/10/08 13:21:00 mbalmer Exp $	*/
211be35a1SLionel Sambuc 
311be35a1SLionel Sambuc /*
4*0a6a1f1dSLionel Sambuc ** Id: liolib.c,v 2.144 2015/04/03 18:41:57 roberto Exp
511be35a1SLionel Sambuc ** Standard I/O (and system) library
611be35a1SLionel Sambuc ** See Copyright Notice in lua.h
711be35a1SLionel Sambuc */
811be35a1SLionel Sambuc 
9*0a6a1f1dSLionel Sambuc #define liolib_c
10*0a6a1f1dSLionel Sambuc #define LUA_LIB
1111be35a1SLionel Sambuc 
12*0a6a1f1dSLionel Sambuc #include "lprefix.h"
13*0a6a1f1dSLionel Sambuc 
14*0a6a1f1dSLionel Sambuc 
15*0a6a1f1dSLionel Sambuc #include <ctype.h>
1611be35a1SLionel Sambuc #include <errno.h>
17*0a6a1f1dSLionel Sambuc #include <locale.h>
1811be35a1SLionel Sambuc #include <stdio.h>
1911be35a1SLionel Sambuc #include <stdlib.h>
2011be35a1SLionel Sambuc #include <string.h>
2111be35a1SLionel Sambuc 
2211be35a1SLionel Sambuc #include "lua.h"
2311be35a1SLionel Sambuc 
2411be35a1SLionel Sambuc #include "lauxlib.h"
2511be35a1SLionel Sambuc #include "lualib.h"
2611be35a1SLionel Sambuc 
2711be35a1SLionel Sambuc 
28*0a6a1f1dSLionel Sambuc #if !defined(l_checkmode)
2911be35a1SLionel Sambuc 
30*0a6a1f1dSLionel Sambuc /*
31*0a6a1f1dSLionel Sambuc ** Check whether 'mode' matches '[rwa]%+?b?'.
32*0a6a1f1dSLionel Sambuc ** Change this macro to accept other modes for 'fopen' besides
33*0a6a1f1dSLionel Sambuc ** the standard ones.
34*0a6a1f1dSLionel Sambuc */
35*0a6a1f1dSLionel Sambuc #define l_checkmode(mode) \
36*0a6a1f1dSLionel Sambuc 	(*mode != '\0' && strchr("rwa", *(mode++)) != NULL &&	\
37*0a6a1f1dSLionel Sambuc 	(*mode != '+' || ++mode) &&  /* skip if char is '+' */	\
38*0a6a1f1dSLionel Sambuc 	(*mode != 'b' || ++mode) &&  /* skip if char is 'b' */	\
39*0a6a1f1dSLionel Sambuc 	(*mode == '\0'))
40*0a6a1f1dSLionel Sambuc 
41*0a6a1f1dSLionel Sambuc #endif
42*0a6a1f1dSLionel Sambuc 
43*0a6a1f1dSLionel Sambuc /*
44*0a6a1f1dSLionel Sambuc ** {======================================================
45*0a6a1f1dSLionel Sambuc ** l_popen spawns a new process connected to the current
46*0a6a1f1dSLionel Sambuc ** one through the file streams.
47*0a6a1f1dSLionel Sambuc ** =======================================================
48*0a6a1f1dSLionel Sambuc */
49*0a6a1f1dSLionel Sambuc 
50*0a6a1f1dSLionel Sambuc #if !defined(l_popen)		/* { */
51*0a6a1f1dSLionel Sambuc 
52*0a6a1f1dSLionel Sambuc #if defined(LUA_USE_POSIX)	/* { */
53*0a6a1f1dSLionel Sambuc 
54*0a6a1f1dSLionel Sambuc #define l_popen(L,c,m)		(fflush(NULL), popen(c,m))
55*0a6a1f1dSLionel Sambuc #define l_pclose(L,file)	(pclose(file))
56*0a6a1f1dSLionel Sambuc 
57*0a6a1f1dSLionel Sambuc #elif defined(LUA_USE_WINDOWS)	/* }{ */
58*0a6a1f1dSLionel Sambuc 
59*0a6a1f1dSLionel Sambuc #define l_popen(L,c,m)		(_popen(c,m))
60*0a6a1f1dSLionel Sambuc #define l_pclose(L,file)	(_pclose(file))
61*0a6a1f1dSLionel Sambuc 
62*0a6a1f1dSLionel Sambuc #else				/* }{ */
63*0a6a1f1dSLionel Sambuc 
64*0a6a1f1dSLionel Sambuc /* ISO C definitions */
65*0a6a1f1dSLionel Sambuc #define l_popen(L,c,m)  \
66*0a6a1f1dSLionel Sambuc 	  ((void)((void)c, m), \
67*0a6a1f1dSLionel Sambuc 	  luaL_error(L, "'popen' not supported"), \
68*0a6a1f1dSLionel Sambuc 	  (FILE*)0)
69*0a6a1f1dSLionel Sambuc #define l_pclose(L,file)		((void)L, (void)file, -1)
70*0a6a1f1dSLionel Sambuc 
71*0a6a1f1dSLionel Sambuc #endif				/* } */
72*0a6a1f1dSLionel Sambuc 
73*0a6a1f1dSLionel Sambuc #endif				/* } */
74*0a6a1f1dSLionel Sambuc 
75*0a6a1f1dSLionel Sambuc /* }====================================================== */
7611be35a1SLionel Sambuc 
7711be35a1SLionel Sambuc 
78*0a6a1f1dSLionel Sambuc #if !defined(l_getc)		/* { */
79*0a6a1f1dSLionel Sambuc 
80*0a6a1f1dSLionel Sambuc #if defined(LUA_USE_POSIX)
81*0a6a1f1dSLionel Sambuc #define l_getc(f)		getc_unlocked(f)
82*0a6a1f1dSLionel Sambuc #define l_lockfile(f)		flockfile(f)
83*0a6a1f1dSLionel Sambuc #define l_unlockfile(f)		funlockfile(f)
84*0a6a1f1dSLionel Sambuc #else
85*0a6a1f1dSLionel Sambuc #define l_getc(f)		getc(f)
86*0a6a1f1dSLionel Sambuc #define l_lockfile(f)		((void)0)
87*0a6a1f1dSLionel Sambuc #define l_unlockfile(f)		((void)0)
88*0a6a1f1dSLionel Sambuc #endif
89*0a6a1f1dSLionel Sambuc 
90*0a6a1f1dSLionel Sambuc #endif				/* } */
9111be35a1SLionel Sambuc 
9211be35a1SLionel Sambuc 
93*0a6a1f1dSLionel Sambuc /*
94*0a6a1f1dSLionel Sambuc ** {======================================================
95*0a6a1f1dSLionel Sambuc ** l_fseek: configuration for longer offsets
96*0a6a1f1dSLionel Sambuc ** =======================================================
97*0a6a1f1dSLionel Sambuc */
98*0a6a1f1dSLionel Sambuc 
99*0a6a1f1dSLionel Sambuc #if !defined(l_fseek)		/* { */
100*0a6a1f1dSLionel Sambuc 
101*0a6a1f1dSLionel Sambuc #if defined(LUA_USE_POSIX)	/* { */
102*0a6a1f1dSLionel Sambuc 
103*0a6a1f1dSLionel Sambuc #include <sys/types.h>
104*0a6a1f1dSLionel Sambuc 
105*0a6a1f1dSLionel Sambuc #define l_fseek(f,o,w)		fseeko(f,o,w)
106*0a6a1f1dSLionel Sambuc #define l_ftell(f)		ftello(f)
107*0a6a1f1dSLionel Sambuc #define l_seeknum		off_t
108*0a6a1f1dSLionel Sambuc 
109*0a6a1f1dSLionel Sambuc #elif defined(LUA_USE_WINDOWS) && !defined(_CRTIMP_TYPEINFO) \
110*0a6a1f1dSLionel Sambuc    && defined(_MSC_VER) && (_MSC_VER >= 1400)	/* }{ */
111*0a6a1f1dSLionel Sambuc 
112*0a6a1f1dSLionel Sambuc /* Windows (but not DDK) and Visual C++ 2005 or higher */
113*0a6a1f1dSLionel Sambuc #define l_fseek(f,o,w)		_fseeki64(f,o,w)
114*0a6a1f1dSLionel Sambuc #define l_ftell(f)		_ftelli64(f)
115*0a6a1f1dSLionel Sambuc #define l_seeknum		__int64
116*0a6a1f1dSLionel Sambuc 
117*0a6a1f1dSLionel Sambuc #else				/* }{ */
118*0a6a1f1dSLionel Sambuc 
119*0a6a1f1dSLionel Sambuc /* ISO C definitions */
120*0a6a1f1dSLionel Sambuc #define l_fseek(f,o,w)		fseek(f,o,w)
121*0a6a1f1dSLionel Sambuc #define l_ftell(f)		ftell(f)
122*0a6a1f1dSLionel Sambuc #define l_seeknum		long
123*0a6a1f1dSLionel Sambuc 
124*0a6a1f1dSLionel Sambuc #endif				/* } */
125*0a6a1f1dSLionel Sambuc 
126*0a6a1f1dSLionel Sambuc #endif				/* } */
127*0a6a1f1dSLionel Sambuc 
128*0a6a1f1dSLionel Sambuc /* }====================================================== */
12911be35a1SLionel Sambuc 
13011be35a1SLionel Sambuc 
131*0a6a1f1dSLionel Sambuc #define IO_PREFIX	"_IO_"
132*0a6a1f1dSLionel Sambuc #define IOPREF_LEN	(sizeof(IO_PREFIX)/sizeof(char) - 1)
133*0a6a1f1dSLionel Sambuc #define IO_INPUT	(IO_PREFIX "input")
134*0a6a1f1dSLionel Sambuc #define IO_OUTPUT	(IO_PREFIX "output")
13511be35a1SLionel Sambuc 
13611be35a1SLionel Sambuc 
137*0a6a1f1dSLionel Sambuc typedef luaL_Stream LStream;
138*0a6a1f1dSLionel Sambuc 
139*0a6a1f1dSLionel Sambuc 
140*0a6a1f1dSLionel Sambuc #define tolstream(L)	((LStream *)luaL_checkudata(L, 1, LUA_FILEHANDLE))
141*0a6a1f1dSLionel Sambuc 
142*0a6a1f1dSLionel Sambuc #define isclosed(p)	((p)->closef == NULL)
14311be35a1SLionel Sambuc 
14411be35a1SLionel Sambuc 
io_type(lua_State * L)14511be35a1SLionel Sambuc static int io_type (lua_State *L) {
146*0a6a1f1dSLionel Sambuc   LStream *p;
14711be35a1SLionel Sambuc   luaL_checkany(L, 1);
148*0a6a1f1dSLionel Sambuc   p = (LStream *)luaL_testudata(L, 1, LUA_FILEHANDLE);
149*0a6a1f1dSLionel Sambuc   if (p == NULL)
15011be35a1SLionel Sambuc     lua_pushnil(L);  /* not a file */
151*0a6a1f1dSLionel Sambuc   else if (isclosed(p))
15211be35a1SLionel Sambuc     lua_pushliteral(L, "closed file");
15311be35a1SLionel Sambuc   else
15411be35a1SLionel Sambuc     lua_pushliteral(L, "file");
15511be35a1SLionel Sambuc   return 1;
15611be35a1SLionel Sambuc }
15711be35a1SLionel Sambuc 
15811be35a1SLionel Sambuc 
f_tostring(lua_State * L)159*0a6a1f1dSLionel Sambuc static int f_tostring (lua_State *L) {
160*0a6a1f1dSLionel Sambuc   LStream *p = tolstream(L);
161*0a6a1f1dSLionel Sambuc   if (isclosed(p))
162*0a6a1f1dSLionel Sambuc     lua_pushliteral(L, "file (closed)");
163*0a6a1f1dSLionel Sambuc   else
164*0a6a1f1dSLionel Sambuc     lua_pushfstring(L, "file (%p)", p->f);
165*0a6a1f1dSLionel Sambuc   return 1;
16611be35a1SLionel Sambuc }
16711be35a1SLionel Sambuc 
16811be35a1SLionel Sambuc 
tofile(lua_State * L)169*0a6a1f1dSLionel Sambuc static FILE *tofile (lua_State *L) {
170*0a6a1f1dSLionel Sambuc   LStream *p = tolstream(L);
171*0a6a1f1dSLionel Sambuc   if (isclosed(p))
172*0a6a1f1dSLionel Sambuc     luaL_error(L, "attempt to use a closed file");
173*0a6a1f1dSLionel Sambuc   lua_assert(p->f);
174*0a6a1f1dSLionel Sambuc   return p->f;
175*0a6a1f1dSLionel Sambuc }
176*0a6a1f1dSLionel Sambuc 
17711be35a1SLionel Sambuc 
17811be35a1SLionel Sambuc /*
179*0a6a1f1dSLionel Sambuc ** When creating file handles, always creates a 'closed' file handle
18011be35a1SLionel Sambuc ** before opening the actual file; so, if there is a memory error, the
18111be35a1SLionel Sambuc ** file is not left opened.
18211be35a1SLionel Sambuc */
newprefile(lua_State * L)183*0a6a1f1dSLionel Sambuc static LStream *newprefile (lua_State *L) {
184*0a6a1f1dSLionel Sambuc   LStream *p = (LStream *)lua_newuserdata(L, sizeof(LStream));
185*0a6a1f1dSLionel Sambuc   p->closef = NULL;  /* mark file handle as 'closed' */
186*0a6a1f1dSLionel Sambuc   luaL_setmetatable(L, LUA_FILEHANDLE);
187*0a6a1f1dSLionel Sambuc   return p;
18811be35a1SLionel Sambuc }
18911be35a1SLionel Sambuc 
19011be35a1SLionel Sambuc 
19111be35a1SLionel Sambuc /*
192*0a6a1f1dSLionel Sambuc ** Calls the 'close' function from a file handle. The 'volatile' avoids
193*0a6a1f1dSLionel Sambuc ** a bug in some versions of the Clang compiler (e.g., clang 3.0 for
194*0a6a1f1dSLionel Sambuc ** 32 bits).
19511be35a1SLionel Sambuc */
aux_close(lua_State * L)196*0a6a1f1dSLionel Sambuc static int aux_close (lua_State *L) {
197*0a6a1f1dSLionel Sambuc   LStream *p = tolstream(L);
198*0a6a1f1dSLionel Sambuc   volatile lua_CFunction cf = p->closef;
199*0a6a1f1dSLionel Sambuc   p->closef = NULL;  /* mark stream as closed */
200*0a6a1f1dSLionel Sambuc   return (*cf)(L);  /* close it */
20111be35a1SLionel Sambuc }
20211be35a1SLionel Sambuc 
20311be35a1SLionel Sambuc 
io_close(lua_State * L)204*0a6a1f1dSLionel Sambuc static int io_close (lua_State *L) {
205*0a6a1f1dSLionel Sambuc   if (lua_isnone(L, 1))  /* no argument? */
206*0a6a1f1dSLionel Sambuc     lua_getfield(L, LUA_REGISTRYINDEX, IO_OUTPUT);  /* use standard output */
207*0a6a1f1dSLionel Sambuc   tofile(L);  /* make sure argument is an open stream */
208*0a6a1f1dSLionel Sambuc   return aux_close(L);
209*0a6a1f1dSLionel Sambuc }
210*0a6a1f1dSLionel Sambuc 
211*0a6a1f1dSLionel Sambuc 
f_gc(lua_State * L)212*0a6a1f1dSLionel Sambuc static int f_gc (lua_State *L) {
213*0a6a1f1dSLionel Sambuc   LStream *p = tolstream(L);
214*0a6a1f1dSLionel Sambuc   if (!isclosed(p) && p->f != NULL)
215*0a6a1f1dSLionel Sambuc     aux_close(L);  /* ignore closed and incompletely open files */
216*0a6a1f1dSLionel Sambuc   return 0;
21711be35a1SLionel Sambuc }
21811be35a1SLionel Sambuc 
21911be35a1SLionel Sambuc 
22011be35a1SLionel Sambuc /*
22111be35a1SLionel Sambuc ** function to close regular files
22211be35a1SLionel Sambuc */
io_fclose(lua_State * L)22311be35a1SLionel Sambuc static int io_fclose (lua_State *L) {
224*0a6a1f1dSLionel Sambuc   LStream *p = tolstream(L);
225*0a6a1f1dSLionel Sambuc   int res = fclose(p->f);
226*0a6a1f1dSLionel Sambuc   return luaL_fileresult(L, (res == 0), NULL);
22711be35a1SLionel Sambuc }
22811be35a1SLionel Sambuc 
22911be35a1SLionel Sambuc 
newfile(lua_State * L)230*0a6a1f1dSLionel Sambuc static LStream *newfile (lua_State *L) {
231*0a6a1f1dSLionel Sambuc   LStream *p = newprefile(L);
232*0a6a1f1dSLionel Sambuc   p->f = NULL;
233*0a6a1f1dSLionel Sambuc   p->closef = &io_fclose;
234*0a6a1f1dSLionel Sambuc   return p;
23511be35a1SLionel Sambuc }
23611be35a1SLionel Sambuc 
23711be35a1SLionel Sambuc 
opencheck(lua_State * L,const char * fname,const char * mode)238*0a6a1f1dSLionel Sambuc static void opencheck (lua_State *L, const char *fname, const char *mode) {
239*0a6a1f1dSLionel Sambuc   LStream *p = newfile(L);
240*0a6a1f1dSLionel Sambuc   p->f = fopen(fname, mode);
241*0a6a1f1dSLionel Sambuc   if (p->f == NULL)
242*0a6a1f1dSLionel Sambuc     luaL_error(L, "cannot open file '%s' (%s)", fname, strerror(errno));
24311be35a1SLionel Sambuc }
24411be35a1SLionel Sambuc 
24511be35a1SLionel Sambuc 
io_open(lua_State * L)24611be35a1SLionel Sambuc static int io_open (lua_State *L) {
24711be35a1SLionel Sambuc   const char *filename = luaL_checkstring(L, 1);
24811be35a1SLionel Sambuc   const char *mode = luaL_optstring(L, 2, "r");
249*0a6a1f1dSLionel Sambuc   LStream *p = newfile(L);
250*0a6a1f1dSLionel Sambuc   const char *md = mode;  /* to traverse/check mode */
251*0a6a1f1dSLionel Sambuc   luaL_argcheck(L, l_checkmode(md), 2, "invalid mode");
252*0a6a1f1dSLionel Sambuc   p->f = fopen(filename, mode);
253*0a6a1f1dSLionel Sambuc   return (p->f == NULL) ? luaL_fileresult(L, 0, filename) : 1;
25411be35a1SLionel Sambuc }
25511be35a1SLionel Sambuc 
25611be35a1SLionel Sambuc 
25711be35a1SLionel Sambuc /*
258*0a6a1f1dSLionel Sambuc ** function to close 'popen' files
25911be35a1SLionel Sambuc */
io_pclose(lua_State * L)260*0a6a1f1dSLionel Sambuc static int io_pclose (lua_State *L) {
261*0a6a1f1dSLionel Sambuc   LStream *p = tolstream(L);
262*0a6a1f1dSLionel Sambuc   return luaL_execresult(L, l_pclose(L, p->f));
263*0a6a1f1dSLionel Sambuc }
264*0a6a1f1dSLionel Sambuc 
265*0a6a1f1dSLionel Sambuc 
io_popen(lua_State * L)26611be35a1SLionel Sambuc static int io_popen (lua_State *L) {
26711be35a1SLionel Sambuc   const char *filename = luaL_checkstring(L, 1);
26811be35a1SLionel Sambuc   const char *mode = luaL_optstring(L, 2, "r");
269*0a6a1f1dSLionel Sambuc   LStream *p = newprefile(L);
270*0a6a1f1dSLionel Sambuc   p->f = l_popen(L, filename, mode);
271*0a6a1f1dSLionel Sambuc   p->closef = &io_pclose;
272*0a6a1f1dSLionel Sambuc   return (p->f == NULL) ? luaL_fileresult(L, 0, filename) : 1;
27311be35a1SLionel Sambuc }
27411be35a1SLionel Sambuc 
27511be35a1SLionel Sambuc 
io_tmpfile(lua_State * L)27611be35a1SLionel Sambuc static int io_tmpfile (lua_State *L) {
277*0a6a1f1dSLionel Sambuc   LStream *p = newfile(L);
278*0a6a1f1dSLionel Sambuc   p->f = tmpfile();
279*0a6a1f1dSLionel Sambuc   return (p->f == NULL) ? luaL_fileresult(L, 0, NULL) : 1;
28011be35a1SLionel Sambuc }
28111be35a1SLionel Sambuc 
28211be35a1SLionel Sambuc 
getiofile(lua_State * L,const char * findex)283*0a6a1f1dSLionel Sambuc static FILE *getiofile (lua_State *L, const char *findex) {
284*0a6a1f1dSLionel Sambuc   LStream *p;
285*0a6a1f1dSLionel Sambuc   lua_getfield(L, LUA_REGISTRYINDEX, findex);
286*0a6a1f1dSLionel Sambuc   p = (LStream *)lua_touserdata(L, -1);
287*0a6a1f1dSLionel Sambuc   if (isclosed(p))
288*0a6a1f1dSLionel Sambuc     luaL_error(L, "standard %s file is closed", findex + IOPREF_LEN);
289*0a6a1f1dSLionel Sambuc   return p->f;
29011be35a1SLionel Sambuc }
29111be35a1SLionel Sambuc 
29211be35a1SLionel Sambuc 
g_iofile(lua_State * L,const char * f,const char * mode)293*0a6a1f1dSLionel Sambuc static int g_iofile (lua_State *L, const char *f, const char *mode) {
29411be35a1SLionel Sambuc   if (!lua_isnoneornil(L, 1)) {
29511be35a1SLionel Sambuc     const char *filename = lua_tostring(L, 1);
296*0a6a1f1dSLionel Sambuc     if (filename)
297*0a6a1f1dSLionel Sambuc       opencheck(L, filename, mode);
29811be35a1SLionel Sambuc     else {
29911be35a1SLionel Sambuc       tofile(L);  /* check that it's a valid file handle */
30011be35a1SLionel Sambuc       lua_pushvalue(L, 1);
30111be35a1SLionel Sambuc     }
302*0a6a1f1dSLionel Sambuc     lua_setfield(L, LUA_REGISTRYINDEX, f);
30311be35a1SLionel Sambuc   }
30411be35a1SLionel Sambuc   /* return current value */
305*0a6a1f1dSLionel Sambuc   lua_getfield(L, LUA_REGISTRYINDEX, f);
30611be35a1SLionel Sambuc   return 1;
30711be35a1SLionel Sambuc }
30811be35a1SLionel Sambuc 
30911be35a1SLionel Sambuc 
io_input(lua_State * L)31011be35a1SLionel Sambuc static int io_input (lua_State *L) {
31111be35a1SLionel Sambuc   return g_iofile(L, IO_INPUT, "r");
31211be35a1SLionel Sambuc }
31311be35a1SLionel Sambuc 
31411be35a1SLionel Sambuc 
io_output(lua_State * L)31511be35a1SLionel Sambuc static int io_output (lua_State *L) {
31611be35a1SLionel Sambuc   return g_iofile(L, IO_OUTPUT, "w");
31711be35a1SLionel Sambuc }
31811be35a1SLionel Sambuc 
31911be35a1SLionel Sambuc 
32011be35a1SLionel Sambuc static int io_readline (lua_State *L);
32111be35a1SLionel Sambuc 
32211be35a1SLionel Sambuc 
aux_lines(lua_State * L,int toclose)323*0a6a1f1dSLionel Sambuc static void aux_lines (lua_State *L, int toclose) {
324*0a6a1f1dSLionel Sambuc   int n = lua_gettop(L) - 1;  /* number of arguments to read */
325*0a6a1f1dSLionel Sambuc   lua_pushinteger(L, n);  /* number of arguments to read */
32611be35a1SLionel Sambuc   lua_pushboolean(L, toclose);  /* close/not close file when finished */
327*0a6a1f1dSLionel Sambuc   lua_rotate(L, 2, 2);  /* move 'n' and 'toclose' to their positions */
328*0a6a1f1dSLionel Sambuc   lua_pushcclosure(L, io_readline, 3 + n);
32911be35a1SLionel Sambuc }
33011be35a1SLionel Sambuc 
33111be35a1SLionel Sambuc 
f_lines(lua_State * L)33211be35a1SLionel Sambuc static int f_lines (lua_State *L) {
33311be35a1SLionel Sambuc   tofile(L);  /* check that it's a valid file handle */
334*0a6a1f1dSLionel Sambuc   aux_lines(L, 0);
33511be35a1SLionel Sambuc   return 1;
33611be35a1SLionel Sambuc }
33711be35a1SLionel Sambuc 
33811be35a1SLionel Sambuc 
io_lines(lua_State * L)33911be35a1SLionel Sambuc static int io_lines (lua_State *L) {
340*0a6a1f1dSLionel Sambuc   int toclose;
341*0a6a1f1dSLionel Sambuc   if (lua_isnone(L, 1)) lua_pushnil(L);  /* at least one argument */
342*0a6a1f1dSLionel Sambuc   if (lua_isnil(L, 1)) {  /* no file name? */
343*0a6a1f1dSLionel Sambuc     lua_getfield(L, LUA_REGISTRYINDEX, IO_INPUT);  /* get default input */
344*0a6a1f1dSLionel Sambuc     lua_replace(L, 1);  /* put it at index 1 */
345*0a6a1f1dSLionel Sambuc     tofile(L);  /* check that it's a valid file handle */
346*0a6a1f1dSLionel Sambuc     toclose = 0;  /* do not close it after iteration */
34711be35a1SLionel Sambuc   }
348*0a6a1f1dSLionel Sambuc   else {  /* open a new file */
34911be35a1SLionel Sambuc     const char *filename = luaL_checkstring(L, 1);
350*0a6a1f1dSLionel Sambuc     opencheck(L, filename, "r");
351*0a6a1f1dSLionel Sambuc     lua_replace(L, 1);  /* put file at index 1 */
352*0a6a1f1dSLionel Sambuc     toclose = 1;  /* close it after iteration */
35311be35a1SLionel Sambuc   }
354*0a6a1f1dSLionel Sambuc   aux_lines(L, toclose);
355*0a6a1f1dSLionel Sambuc   return 1;
35611be35a1SLionel Sambuc }
35711be35a1SLionel Sambuc 
35811be35a1SLionel Sambuc 
35911be35a1SLionel Sambuc /*
36011be35a1SLionel Sambuc ** {======================================================
36111be35a1SLionel Sambuc ** READ
36211be35a1SLionel Sambuc ** =======================================================
36311be35a1SLionel Sambuc */
36411be35a1SLionel Sambuc 
36511be35a1SLionel Sambuc 
366*0a6a1f1dSLionel Sambuc /* maximum length of a numeral */
367*0a6a1f1dSLionel Sambuc #define MAXRN		200
368*0a6a1f1dSLionel Sambuc 
369*0a6a1f1dSLionel Sambuc /* auxiliary structure used by 'read_number' */
370*0a6a1f1dSLionel Sambuc typedef struct {
371*0a6a1f1dSLionel Sambuc   FILE *f;  /* file being read */
372*0a6a1f1dSLionel Sambuc   int c;  /* current character (look ahead) */
373*0a6a1f1dSLionel Sambuc   int n;  /* number of elements in buffer 'buff' */
374*0a6a1f1dSLionel Sambuc   char buff[MAXRN + 1];  /* +1 for ending '\0' */
375*0a6a1f1dSLionel Sambuc } RN;
376*0a6a1f1dSLionel Sambuc 
377*0a6a1f1dSLionel Sambuc 
378*0a6a1f1dSLionel Sambuc /*
379*0a6a1f1dSLionel Sambuc ** Add current char to buffer (if not out of space) and read next one
380*0a6a1f1dSLionel Sambuc */
nextc(RN * rn)381*0a6a1f1dSLionel Sambuc static int nextc (RN *rn) {
382*0a6a1f1dSLionel Sambuc   if (rn->n >= MAXRN) {  /* buffer overflow? */
383*0a6a1f1dSLionel Sambuc     rn->buff[0] = '\0';  /* invalidate result */
384*0a6a1f1dSLionel Sambuc     return 0;  /* fail */
38511be35a1SLionel Sambuc   }
38611be35a1SLionel Sambuc   else {
387*0a6a1f1dSLionel Sambuc     rn->buff[rn->n++] = rn->c;  /* save current char */
388*0a6a1f1dSLionel Sambuc     rn->c = l_getc(rn->f);  /* read next one */
389*0a6a1f1dSLionel Sambuc     return 1;
390*0a6a1f1dSLionel Sambuc   }
391*0a6a1f1dSLionel Sambuc }
392*0a6a1f1dSLionel Sambuc 
393*0a6a1f1dSLionel Sambuc 
394*0a6a1f1dSLionel Sambuc /*
395*0a6a1f1dSLionel Sambuc ** Accept current char if it is in 'set' (of size 1 or 2)
396*0a6a1f1dSLionel Sambuc */
test2(RN * rn,const char * set)397*0a6a1f1dSLionel Sambuc static int test2 (RN *rn, const char *set) {
398*0a6a1f1dSLionel Sambuc   if (rn->c == set[0] || (rn->c == set[1] && rn->c != '\0'))
399*0a6a1f1dSLionel Sambuc     return nextc(rn);
400*0a6a1f1dSLionel Sambuc   else return 0;
401*0a6a1f1dSLionel Sambuc }
402*0a6a1f1dSLionel Sambuc 
403*0a6a1f1dSLionel Sambuc 
404*0a6a1f1dSLionel Sambuc /*
405*0a6a1f1dSLionel Sambuc ** Read a sequence of (hex)digits
406*0a6a1f1dSLionel Sambuc */
readdigits(RN * rn,int hex)407*0a6a1f1dSLionel Sambuc static int readdigits (RN *rn, int hex) {
408*0a6a1f1dSLionel Sambuc   int count = 0;
409*0a6a1f1dSLionel Sambuc   while ((hex ? isxdigit(rn->c) : isdigit(rn->c)) && nextc(rn))
410*0a6a1f1dSLionel Sambuc     count++;
411*0a6a1f1dSLionel Sambuc   return count;
412*0a6a1f1dSLionel Sambuc }
413*0a6a1f1dSLionel Sambuc 
414*0a6a1f1dSLionel Sambuc 
415*0a6a1f1dSLionel Sambuc /*
416*0a6a1f1dSLionel Sambuc ** Read a number: first reads a valid prefix of a numeral into a buffer.
417*0a6a1f1dSLionel Sambuc ** Then it calls 'lua_stringtonumber' to check whether the format is
418*0a6a1f1dSLionel Sambuc ** correct and to convert it to a Lua number
419*0a6a1f1dSLionel Sambuc */
read_number(lua_State * L,FILE * f)420*0a6a1f1dSLionel Sambuc static int read_number (lua_State *L, FILE *f) {
421*0a6a1f1dSLionel Sambuc   RN rn;
422*0a6a1f1dSLionel Sambuc   int count = 0;
423*0a6a1f1dSLionel Sambuc   int hex = 0;
424*0a6a1f1dSLionel Sambuc   char decp[2];
425*0a6a1f1dSLionel Sambuc   rn.f = f; rn.n = 0;
426*0a6a1f1dSLionel Sambuc   decp[0] = lua_getlocaledecpoint();  /* get decimal point from locale */
427*0a6a1f1dSLionel Sambuc   decp[1] = '\0';
428*0a6a1f1dSLionel Sambuc   l_lockfile(rn.f);
429*0a6a1f1dSLionel Sambuc   do { rn.c = l_getc(rn.f); } while (isspace(rn.c));  /* skip spaces */
430*0a6a1f1dSLionel Sambuc   test2(&rn, "-+");  /* optional signal */
431*0a6a1f1dSLionel Sambuc   if (test2(&rn, "0")) {
432*0a6a1f1dSLionel Sambuc     if (test2(&rn, "xX")) hex = 1;  /* numeral is hexadecimal */
433*0a6a1f1dSLionel Sambuc     else count = 1;  /* count initial '0' as a valid digit */
434*0a6a1f1dSLionel Sambuc   }
435*0a6a1f1dSLionel Sambuc   count += readdigits(&rn, hex);  /* integral part */
436*0a6a1f1dSLionel Sambuc   if (test2(&rn, decp))  /* decimal point? */
437*0a6a1f1dSLionel Sambuc     count += readdigits(&rn, hex);  /* fractional part */
438*0a6a1f1dSLionel Sambuc   if (count > 0 && test2(&rn, (hex ? "pP" : "eE"))) {  /* exponent mark? */
439*0a6a1f1dSLionel Sambuc     test2(&rn, "-+");  /* exponent signal */
440*0a6a1f1dSLionel Sambuc     readdigits(&rn, 0);  /* exponent digits */
441*0a6a1f1dSLionel Sambuc   }
442*0a6a1f1dSLionel Sambuc   ungetc(rn.c, rn.f);  /* unread look-ahead char */
443*0a6a1f1dSLionel Sambuc   l_unlockfile(rn.f);
444*0a6a1f1dSLionel Sambuc   rn.buff[rn.n] = '\0';  /* finish string */
445*0a6a1f1dSLionel Sambuc   if (lua_stringtonumber(L, rn.buff))  /* is this a valid number? */
446*0a6a1f1dSLionel Sambuc     return 1;  /* ok */
447*0a6a1f1dSLionel Sambuc   else {  /* invalid format */
44811be35a1SLionel Sambuc    lua_pushnil(L);  /* "result" to be removed */
44911be35a1SLionel Sambuc    return 0;  /* read fails */
45011be35a1SLionel Sambuc   }
45111be35a1SLionel Sambuc }
45211be35a1SLionel Sambuc 
45311be35a1SLionel Sambuc 
test_eof(lua_State * L,FILE * f)45411be35a1SLionel Sambuc static int test_eof (lua_State *L, FILE *f) {
45511be35a1SLionel Sambuc   int c = getc(f);
456*0a6a1f1dSLionel Sambuc   ungetc(c, f);  /* no-op when c == EOF */
457*0a6a1f1dSLionel Sambuc   lua_pushliteral(L, "");
45811be35a1SLionel Sambuc   return (c != EOF);
45911be35a1SLionel Sambuc }
46011be35a1SLionel Sambuc 
46111be35a1SLionel Sambuc 
read_line(lua_State * L,FILE * f,int chop)462*0a6a1f1dSLionel Sambuc static int read_line (lua_State *L, FILE *f, int chop) {
463*0a6a1f1dSLionel Sambuc   luaL_Buffer b;
464*0a6a1f1dSLionel Sambuc   int c = '\0';
465*0a6a1f1dSLionel Sambuc   luaL_buffinit(L, &b);
466*0a6a1f1dSLionel Sambuc   while (c != EOF && c != '\n') {  /* repeat until end of line */
467*0a6a1f1dSLionel Sambuc     char *buff = luaL_prepbuffer(&b);  /* pre-allocate buffer */
468*0a6a1f1dSLionel Sambuc     int i = 0;
469*0a6a1f1dSLionel Sambuc     l_lockfile(f);  /* no memory errors can happen inside the lock */
470*0a6a1f1dSLionel Sambuc     while (i < LUAL_BUFFERSIZE && (c = l_getc(f)) != EOF && c != '\n')
471*0a6a1f1dSLionel Sambuc       buff[i++] = c;
472*0a6a1f1dSLionel Sambuc     l_unlockfile(f);
473*0a6a1f1dSLionel Sambuc     luaL_addsize(&b, i);
474*0a6a1f1dSLionel Sambuc   }
475*0a6a1f1dSLionel Sambuc   if (!chop && c == '\n')  /* want a newline and have one? */
476*0a6a1f1dSLionel Sambuc     luaL_addchar(&b, c);  /* add ending newline to result */
477*0a6a1f1dSLionel Sambuc   luaL_pushresult(&b);  /* close buffer */
478*0a6a1f1dSLionel Sambuc   /* return ok if read something (either a newline or something else) */
479*0a6a1f1dSLionel Sambuc   return (c == '\n' || lua_rawlen(L, -1) > 0);
480*0a6a1f1dSLionel Sambuc }
481*0a6a1f1dSLionel Sambuc 
482*0a6a1f1dSLionel Sambuc 
read_all(lua_State * L,FILE * f)483*0a6a1f1dSLionel Sambuc static void read_all (lua_State *L, FILE *f) {
484*0a6a1f1dSLionel Sambuc   size_t nr;
48511be35a1SLionel Sambuc   luaL_Buffer b;
48611be35a1SLionel Sambuc   luaL_buffinit(L, &b);
487*0a6a1f1dSLionel Sambuc   do {  /* read file in chunks of LUAL_BUFFERSIZE bytes */
488*0a6a1f1dSLionel Sambuc     char *p = luaL_prepbuffsize(&b, LUAL_BUFFERSIZE);
489*0a6a1f1dSLionel Sambuc     nr = fread(p, sizeof(char), LUAL_BUFFERSIZE, f);
490*0a6a1f1dSLionel Sambuc     luaL_addsize(&b, nr);
491*0a6a1f1dSLionel Sambuc   } while (nr == LUAL_BUFFERSIZE);
49211be35a1SLionel Sambuc   luaL_pushresult(&b);  /* close buffer */
49311be35a1SLionel Sambuc }
49411be35a1SLionel Sambuc 
49511be35a1SLionel Sambuc 
read_chars(lua_State * L,FILE * f,size_t n)49611be35a1SLionel Sambuc static int read_chars (lua_State *L, FILE *f, size_t n) {
49711be35a1SLionel Sambuc   size_t nr;  /* number of chars actually read */
498*0a6a1f1dSLionel Sambuc   char *p;
49911be35a1SLionel Sambuc   luaL_Buffer b;
50011be35a1SLionel Sambuc   luaL_buffinit(L, &b);
501*0a6a1f1dSLionel Sambuc   p = luaL_prepbuffsize(&b, n);  /* prepare buffer to read whole block */
502*0a6a1f1dSLionel Sambuc   nr = fread(p, sizeof(char), n, f);  /* try to read 'n' chars */
50311be35a1SLionel Sambuc   luaL_addsize(&b, nr);
50411be35a1SLionel Sambuc   luaL_pushresult(&b);  /* close buffer */
505*0a6a1f1dSLionel Sambuc   return (nr > 0);  /* true iff read something */
50611be35a1SLionel Sambuc }
50711be35a1SLionel Sambuc 
50811be35a1SLionel Sambuc 
g_read(lua_State * L,FILE * f,int first)50911be35a1SLionel Sambuc static int g_read (lua_State *L, FILE *f, int first) {
51011be35a1SLionel Sambuc   int nargs = lua_gettop(L) - 1;
51111be35a1SLionel Sambuc   int success;
51211be35a1SLionel Sambuc   int n;
51311be35a1SLionel Sambuc   clearerr(f);
51411be35a1SLionel Sambuc   if (nargs == 0) {  /* no arguments? */
515*0a6a1f1dSLionel Sambuc     success = read_line(L, f, 1);
51611be35a1SLionel Sambuc     n = first+1;  /* to return 1 result */
51711be35a1SLionel Sambuc   }
51811be35a1SLionel Sambuc   else {  /* ensure stack space for all results and for auxlib's buffer */
51911be35a1SLionel Sambuc     luaL_checkstack(L, nargs+LUA_MINSTACK, "too many arguments");
52011be35a1SLionel Sambuc     success = 1;
52111be35a1SLionel Sambuc     for (n = first; nargs-- && success; n++) {
52211be35a1SLionel Sambuc       if (lua_type(L, n) == LUA_TNUMBER) {
523*0a6a1f1dSLionel Sambuc         size_t l = (size_t)luaL_checkinteger(L, n);
52411be35a1SLionel Sambuc         success = (l == 0) ? test_eof(L, f) : read_chars(L, f, l);
52511be35a1SLionel Sambuc       }
52611be35a1SLionel Sambuc       else {
527*0a6a1f1dSLionel Sambuc         const char *p = luaL_checkstring(L, n);
528*0a6a1f1dSLionel Sambuc         if (*p == '*') p++;  /* skip optional '*' (for compatibility) */
529*0a6a1f1dSLionel Sambuc         switch (*p) {
53011be35a1SLionel Sambuc           case 'n':  /* number */
53111be35a1SLionel Sambuc             success = read_number(L, f);
53211be35a1SLionel Sambuc             break;
53311be35a1SLionel Sambuc           case 'l':  /* line */
534*0a6a1f1dSLionel Sambuc             success = read_line(L, f, 1);
535*0a6a1f1dSLionel Sambuc             break;
536*0a6a1f1dSLionel Sambuc           case 'L':  /* line with end-of-line */
537*0a6a1f1dSLionel Sambuc             success = read_line(L, f, 0);
53811be35a1SLionel Sambuc             break;
53911be35a1SLionel Sambuc           case 'a':  /* file */
540*0a6a1f1dSLionel Sambuc             read_all(L, f);  /* read entire file */
54111be35a1SLionel Sambuc             success = 1; /* always success */
54211be35a1SLionel Sambuc             break;
54311be35a1SLionel Sambuc           default:
54411be35a1SLionel Sambuc             return luaL_argerror(L, n, "invalid format");
54511be35a1SLionel Sambuc         }
54611be35a1SLionel Sambuc       }
54711be35a1SLionel Sambuc     }
54811be35a1SLionel Sambuc   }
54911be35a1SLionel Sambuc   if (ferror(f))
550*0a6a1f1dSLionel Sambuc     return luaL_fileresult(L, 0, NULL);
55111be35a1SLionel Sambuc   if (!success) {
55211be35a1SLionel Sambuc     lua_pop(L, 1);  /* remove last result */
55311be35a1SLionel Sambuc     lua_pushnil(L);  /* push nil instead */
55411be35a1SLionel Sambuc   }
55511be35a1SLionel Sambuc   return n - first;
55611be35a1SLionel Sambuc }
55711be35a1SLionel Sambuc 
55811be35a1SLionel Sambuc 
io_read(lua_State * L)55911be35a1SLionel Sambuc static int io_read (lua_State *L) {
56011be35a1SLionel Sambuc   return g_read(L, getiofile(L, IO_INPUT), 1);
56111be35a1SLionel Sambuc }
56211be35a1SLionel Sambuc 
56311be35a1SLionel Sambuc 
f_read(lua_State * L)56411be35a1SLionel Sambuc static int f_read (lua_State *L) {
56511be35a1SLionel Sambuc   return g_read(L, tofile(L), 2);
56611be35a1SLionel Sambuc }
56711be35a1SLionel Sambuc 
56811be35a1SLionel Sambuc 
io_readline(lua_State * L)56911be35a1SLionel Sambuc static int io_readline (lua_State *L) {
570*0a6a1f1dSLionel Sambuc   LStream *p = (LStream *)lua_touserdata(L, lua_upvalueindex(1));
571*0a6a1f1dSLionel Sambuc   int i;
572*0a6a1f1dSLionel Sambuc   int n = (int)lua_tointeger(L, lua_upvalueindex(2));
573*0a6a1f1dSLionel Sambuc   if (isclosed(p))  /* file is already closed? */
574*0a6a1f1dSLionel Sambuc     return luaL_error(L, "file is already closed");
575*0a6a1f1dSLionel Sambuc   lua_settop(L , 1);
576*0a6a1f1dSLionel Sambuc   luaL_checkstack(L, n, "too many arguments");
577*0a6a1f1dSLionel Sambuc   for (i = 1; i <= n; i++)  /* push arguments to 'g_read' */
578*0a6a1f1dSLionel Sambuc     lua_pushvalue(L, lua_upvalueindex(3 + i));
579*0a6a1f1dSLionel Sambuc   n = g_read(L, p->f, 2);  /* 'n' is number of results */
580*0a6a1f1dSLionel Sambuc   lua_assert(n > 0);  /* should return at least a nil */
581*0a6a1f1dSLionel Sambuc   if (lua_toboolean(L, -n))  /* read at least one value? */
582*0a6a1f1dSLionel Sambuc     return n;  /* return them */
583*0a6a1f1dSLionel Sambuc   else {  /* first result is nil: EOF or error */
584*0a6a1f1dSLionel Sambuc     if (n > 1) {  /* is there error information? */
585*0a6a1f1dSLionel Sambuc       /* 2nd result is error message */
586*0a6a1f1dSLionel Sambuc       return luaL_error(L, "%s", lua_tostring(L, -n + 1));
587*0a6a1f1dSLionel Sambuc     }
588*0a6a1f1dSLionel Sambuc     if (lua_toboolean(L, lua_upvalueindex(3))) {  /* generator created file? */
58911be35a1SLionel Sambuc       lua_settop(L, 0);
59011be35a1SLionel Sambuc       lua_pushvalue(L, lua_upvalueindex(1));
59111be35a1SLionel Sambuc       aux_close(L);  /* close it */
59211be35a1SLionel Sambuc     }
59311be35a1SLionel Sambuc     return 0;
59411be35a1SLionel Sambuc   }
59511be35a1SLionel Sambuc }
59611be35a1SLionel Sambuc 
59711be35a1SLionel Sambuc /* }====================================================== */
59811be35a1SLionel Sambuc 
59911be35a1SLionel Sambuc 
g_write(lua_State * L,FILE * f,int arg)60011be35a1SLionel Sambuc static int g_write (lua_State *L, FILE *f, int arg) {
601*0a6a1f1dSLionel Sambuc   int nargs = lua_gettop(L) - arg;
60211be35a1SLionel Sambuc   int status = 1;
60311be35a1SLionel Sambuc   for (; nargs--; arg++) {
60411be35a1SLionel Sambuc     if (lua_type(L, arg) == LUA_TNUMBER) {
60511be35a1SLionel Sambuc       /* optimization: could be done exactly as for strings */
606*0a6a1f1dSLionel Sambuc       int len = lua_isinteger(L, arg)
607*0a6a1f1dSLionel Sambuc                 ? fprintf(f, LUA_INTEGER_FMT, lua_tointeger(L, arg))
608*0a6a1f1dSLionel Sambuc                 : fprintf(f, LUA_NUMBER_FMT, lua_tonumber(L, arg));
609*0a6a1f1dSLionel Sambuc       status = status && (len > 0);
61011be35a1SLionel Sambuc     }
61111be35a1SLionel Sambuc     else {
61211be35a1SLionel Sambuc       size_t l;
61311be35a1SLionel Sambuc       const char *s = luaL_checklstring(L, arg, &l);
61411be35a1SLionel Sambuc       status = status && (fwrite(s, sizeof(char), l, f) == l);
61511be35a1SLionel Sambuc     }
61611be35a1SLionel Sambuc   }
617*0a6a1f1dSLionel Sambuc   if (status) return 1;  /* file handle already on stack top */
618*0a6a1f1dSLionel Sambuc   else return luaL_fileresult(L, status, NULL);
61911be35a1SLionel Sambuc }
62011be35a1SLionel Sambuc 
62111be35a1SLionel Sambuc 
io_write(lua_State * L)62211be35a1SLionel Sambuc static int io_write (lua_State *L) {
62311be35a1SLionel Sambuc   return g_write(L, getiofile(L, IO_OUTPUT), 1);
62411be35a1SLionel Sambuc }
62511be35a1SLionel Sambuc 
62611be35a1SLionel Sambuc 
f_write(lua_State * L)62711be35a1SLionel Sambuc static int f_write (lua_State *L) {
628*0a6a1f1dSLionel Sambuc   FILE *f = tofile(L);
629*0a6a1f1dSLionel Sambuc   lua_pushvalue(L, 1);  /* push file at the stack top (to be returned) */
630*0a6a1f1dSLionel Sambuc   return g_write(L, f, 2);
63111be35a1SLionel Sambuc }
63211be35a1SLionel Sambuc 
63311be35a1SLionel Sambuc 
f_seek(lua_State * L)63411be35a1SLionel Sambuc static int f_seek (lua_State *L) {
63511be35a1SLionel Sambuc   static const int mode[] = {SEEK_SET, SEEK_CUR, SEEK_END};
63611be35a1SLionel Sambuc   static const char *const modenames[] = {"set", "cur", "end", NULL};
63711be35a1SLionel Sambuc   FILE *f = tofile(L);
63811be35a1SLionel Sambuc   int op = luaL_checkoption(L, 2, "cur", modenames);
639*0a6a1f1dSLionel Sambuc   lua_Integer p3 = luaL_optinteger(L, 3, 0);
640*0a6a1f1dSLionel Sambuc   l_seeknum offset = (l_seeknum)p3;
641*0a6a1f1dSLionel Sambuc   luaL_argcheck(L, (lua_Integer)offset == p3, 3,
642*0a6a1f1dSLionel Sambuc                   "not an integer in proper range");
643*0a6a1f1dSLionel Sambuc   op = l_fseek(f, offset, mode[op]);
64411be35a1SLionel Sambuc   if (op)
645*0a6a1f1dSLionel Sambuc     return luaL_fileresult(L, 0, NULL);  /* error */
64611be35a1SLionel Sambuc   else {
647*0a6a1f1dSLionel Sambuc     lua_pushinteger(L, (lua_Integer)l_ftell(f));
64811be35a1SLionel Sambuc     return 1;
64911be35a1SLionel Sambuc   }
65011be35a1SLionel Sambuc }
65111be35a1SLionel Sambuc 
65211be35a1SLionel Sambuc 
f_setvbuf(lua_State * L)65311be35a1SLionel Sambuc static int f_setvbuf (lua_State *L) {
65411be35a1SLionel Sambuc   static const int mode[] = {_IONBF, _IOFBF, _IOLBF};
65511be35a1SLionel Sambuc   static const char *const modenames[] = {"no", "full", "line", NULL};
65611be35a1SLionel Sambuc   FILE *f = tofile(L);
65711be35a1SLionel Sambuc   int op = luaL_checkoption(L, 2, NULL, modenames);
65811be35a1SLionel Sambuc   lua_Integer sz = luaL_optinteger(L, 3, LUAL_BUFFERSIZE);
659*0a6a1f1dSLionel Sambuc   int res = setvbuf(f, NULL, mode[op], (size_t)sz);
660*0a6a1f1dSLionel Sambuc   return luaL_fileresult(L, res == 0, NULL);
66111be35a1SLionel Sambuc }
66211be35a1SLionel Sambuc 
66311be35a1SLionel Sambuc 
66411be35a1SLionel Sambuc 
io_flush(lua_State * L)66511be35a1SLionel Sambuc static int io_flush (lua_State *L) {
666*0a6a1f1dSLionel Sambuc   return luaL_fileresult(L, fflush(getiofile(L, IO_OUTPUT)) == 0, NULL);
66711be35a1SLionel Sambuc }
66811be35a1SLionel Sambuc 
66911be35a1SLionel Sambuc 
f_flush(lua_State * L)67011be35a1SLionel Sambuc static int f_flush (lua_State *L) {
671*0a6a1f1dSLionel Sambuc   return luaL_fileresult(L, fflush(tofile(L)) == 0, NULL);
67211be35a1SLionel Sambuc }
67311be35a1SLionel Sambuc 
67411be35a1SLionel Sambuc 
675*0a6a1f1dSLionel Sambuc /*
676*0a6a1f1dSLionel Sambuc ** functions for 'io' library
677*0a6a1f1dSLionel Sambuc */
67811be35a1SLionel Sambuc static const luaL_Reg iolib[] = {
67911be35a1SLionel Sambuc   {"close", io_close},
68011be35a1SLionel Sambuc   {"flush", io_flush},
68111be35a1SLionel Sambuc   {"input", io_input},
68211be35a1SLionel Sambuc   {"lines", io_lines},
68311be35a1SLionel Sambuc   {"open", io_open},
68411be35a1SLionel Sambuc   {"output", io_output},
68511be35a1SLionel Sambuc   {"popen", io_popen},
68611be35a1SLionel Sambuc   {"read", io_read},
68711be35a1SLionel Sambuc   {"tmpfile", io_tmpfile},
68811be35a1SLionel Sambuc   {"type", io_type},
68911be35a1SLionel Sambuc   {"write", io_write},
69011be35a1SLionel Sambuc   {NULL, NULL}
69111be35a1SLionel Sambuc };
69211be35a1SLionel Sambuc 
69311be35a1SLionel Sambuc 
694*0a6a1f1dSLionel Sambuc /*
695*0a6a1f1dSLionel Sambuc ** methods for file handles
696*0a6a1f1dSLionel Sambuc */
69711be35a1SLionel Sambuc static const luaL_Reg flib[] = {
69811be35a1SLionel Sambuc   {"close", io_close},
69911be35a1SLionel Sambuc   {"flush", f_flush},
70011be35a1SLionel Sambuc   {"lines", f_lines},
70111be35a1SLionel Sambuc   {"read", f_read},
70211be35a1SLionel Sambuc   {"seek", f_seek},
70311be35a1SLionel Sambuc   {"setvbuf", f_setvbuf},
70411be35a1SLionel Sambuc   {"write", f_write},
705*0a6a1f1dSLionel Sambuc   {"__gc", f_gc},
706*0a6a1f1dSLionel Sambuc   {"__tostring", f_tostring},
70711be35a1SLionel Sambuc   {NULL, NULL}
70811be35a1SLionel Sambuc };
70911be35a1SLionel Sambuc 
71011be35a1SLionel Sambuc 
createmeta(lua_State * L)71111be35a1SLionel Sambuc static void createmeta (lua_State *L) {
71211be35a1SLionel Sambuc   luaL_newmetatable(L, LUA_FILEHANDLE);  /* create metatable for file handles */
71311be35a1SLionel Sambuc   lua_pushvalue(L, -1);  /* push metatable */
71411be35a1SLionel Sambuc   lua_setfield(L, -2, "__index");  /* metatable.__index = metatable */
715*0a6a1f1dSLionel Sambuc   luaL_setfuncs(L, flib, 0);  /* add file methods to new metatable */
716*0a6a1f1dSLionel Sambuc   lua_pop(L, 1);  /* pop new metatable */
71711be35a1SLionel Sambuc }
71811be35a1SLionel Sambuc 
71911be35a1SLionel Sambuc 
720*0a6a1f1dSLionel Sambuc /*
721*0a6a1f1dSLionel Sambuc ** function to (not) close the standard files stdin, stdout, and stderr
722*0a6a1f1dSLionel Sambuc */
io_noclose(lua_State * L)723*0a6a1f1dSLionel Sambuc static int io_noclose (lua_State *L) {
724*0a6a1f1dSLionel Sambuc   LStream *p = tolstream(L);
725*0a6a1f1dSLionel Sambuc   p->closef = &io_noclose;  /* keep file opened */
726*0a6a1f1dSLionel Sambuc   lua_pushnil(L);
727*0a6a1f1dSLionel Sambuc   lua_pushliteral(L, "cannot close standard file");
728*0a6a1f1dSLionel Sambuc   return 2;
729*0a6a1f1dSLionel Sambuc }
730*0a6a1f1dSLionel Sambuc 
731*0a6a1f1dSLionel Sambuc 
createstdfile(lua_State * L,FILE * f,const char * k,const char * fname)732*0a6a1f1dSLionel Sambuc static void createstdfile (lua_State *L, FILE *f, const char *k,
733*0a6a1f1dSLionel Sambuc                            const char *fname) {
734*0a6a1f1dSLionel Sambuc   LStream *p = newprefile(L);
735*0a6a1f1dSLionel Sambuc   p->f = f;
736*0a6a1f1dSLionel Sambuc   p->closef = &io_noclose;
737*0a6a1f1dSLionel Sambuc   if (k != NULL) {
73811be35a1SLionel Sambuc     lua_pushvalue(L, -1);
739*0a6a1f1dSLionel Sambuc     lua_setfield(L, LUA_REGISTRYINDEX, k);  /* add file to registry */
74011be35a1SLionel Sambuc   }
741*0a6a1f1dSLionel Sambuc   lua_setfield(L, -2, fname);  /* add file to module */
74211be35a1SLionel Sambuc }
74311be35a1SLionel Sambuc 
74411be35a1SLionel Sambuc 
luaopen_io(lua_State * L)745*0a6a1f1dSLionel Sambuc LUAMOD_API int luaopen_io (lua_State *L) {
746*0a6a1f1dSLionel Sambuc   luaL_newlib(L, iolib);  /* new module */
74711be35a1SLionel Sambuc   createmeta(L);
74811be35a1SLionel Sambuc   /* create (and set) default files */
74911be35a1SLionel Sambuc   createstdfile(L, stdin, IO_INPUT, "stdin");
75011be35a1SLionel Sambuc   createstdfile(L, stdout, IO_OUTPUT, "stdout");
751*0a6a1f1dSLionel Sambuc   createstdfile(L, stderr, NULL, "stderr");
75211be35a1SLionel Sambuc   return 1;
75311be35a1SLionel Sambuc }
75411be35a1SLionel Sambuc 
755