32#if !defined(l_checkmode)
35#if !defined(L_MODEEXT)
40static int l_checkmode (
const char *mode) {
41 return (*mode !=
'\0' && strchr(
"rwa", *(mode++)) != NULL &&
42 (*mode !=
'+' || ((
void)(++mode), 1)) &&
43 (strspn(mode, L_MODEEXT) == strlen(mode)));
57#if defined(LUA_USE_POSIX)
59#define l_popen(L,c,m) (fflush(NULL), popen(c,m))
60#define l_pclose(L,file) (pclose(file))
62#elif defined(LUA_USE_WINDOWS)
64#define l_popen(L,c,m) (_popen(c,m))
65#define l_pclose(L,file) (_pclose(file))
67#if !defined(l_checkmodep)
69#define l_checkmodep(m) ((m[0] == 'r' || m[0] == 'w') && \
70 (m[1] == '\0' || ((m[1] == 'b' || m[1] == 't') && m[2] == '\0')))
76#define l_popen(L,c,m) \
78 luaL_error(L, "'popen' not supported"), \
80#define l_pclose(L,file) ((void)L, (void)file, -1)
87#if !defined(l_checkmodep)
89#define l_checkmodep(m) ((m[0] == 'r' || m[0] == 'w') && m[1] == '\0')
97#if defined(LUA_USE_POSIX)
98#define l_getc(f) getc_unlocked(f)
99#define l_lockfile(f) flockfile(f)
100#define l_unlockfile(f) funlockfile(f)
102#define l_getc(f) getc(f)
103#define l_lockfile(f) ((void)0)
104#define l_unlockfile(f) ((void)0)
118#if defined(LUA_USE_POSIX)
120#include <sys/types.h>
122#define l_fseek(f,o,w) fseeko(f,o,w)
123#define l_ftell(f) ftello(f)
124#define l_seeknum off_t
126#elif defined(LUA_USE_WINDOWS) && !defined(_CRTIMP_TYPEINFO) \
127 && defined(_MSC_VER) && (_MSC_VER >= 1400)
130#define l_fseek(f,o,w) _fseeki64(f,o,w)
131#define l_ftell(f) _ftelli64(f)
132#define l_seeknum __int64
137#define l_fseek(f,o,w) fseek(f,o,w)
138#define l_ftell(f) ftell(f)
139#define l_seeknum long
149#define IO_PREFIX "_IO_"
150#define IOPREF_LEN (sizeof(IO_PREFIX)/sizeof(char) - 1)
151#define IO_INPUT (IO_PREFIX "input")
152#define IO_OUTPUT (IO_PREFIX "output")
158#define tolstream(L) ((LStream *)luaL_checkudata(L, 1, LUA_FILEHANDLE))
160#define isclosed(p) ((p)->closef == NULL)
166 p = (LStream *)luaL_testudata(L, 1, LUA_FILEHANDLE);
169 else if (isclosed(p))
170 lua_pushliteral(L,
"closed file");
172 lua_pushliteral(L,
"file");
178 LStream *p = tolstream(L);
180 lua_pushliteral(L,
"file (closed)");
182 lua_pushfstring(L,
"file (%p)", p->f);
188 LStream *p = tolstream(L);
189 if (l_unlikely(isclosed(p)))
190 luaL_error(L,
"attempt to use a closed file");
201static LStream *newprefile (
lua_State *L) {
202 LStream *p = (LStream *)lua_newuserdatauv(L,
sizeof(LStream), 0);
204 luaL_setmetatable(L, LUA_FILEHANDLE);
215 LStream *p = tolstream(L);
216 volatile lua_CFunction cf = p->closef;
229 if (lua_isnone(L, 1))
230 lua_getfield(L, LUA_REGISTRYINDEX, IO_OUTPUT);
236 LStream *p = tolstream(L);
237 if (!isclosed(p) && p->f != NULL)
247 LStream *p = tolstream(L);
248 int res = fclose(p->f);
249 return luaL_fileresult(L, (res == 0), NULL);
254 LStream *p = newprefile(L);
256 p->closef = &io_fclose;
261static void opencheck (
lua_State *L,
const char *fname,
const char *mode) {
262 LStream *p = newfile(L);
263 p->f = fopen(fname, mode);
264 if (l_unlikely(p->f == NULL))
265 luaL_error(L,
"cannot open file '%s' (%s)", fname, strerror(errno));
270 const char *filename = luaL_checkstring(L, 1);
271 const char *mode = luaL_optstring(L, 2,
"r");
272 LStream *p = newfile(L);
273 const char *md = mode;
274 luaL_argcheck(L, l_checkmode(md), 2,
"invalid mode");
275 p->f = fopen(filename, mode);
276 return (p->f == NULL) ? luaL_fileresult(L, 0, filename) : 1;
284 LStream *p = tolstream(L);
286 return luaL_execresult(L, l_pclose(L, p->f));
291 const char *filename = luaL_checkstring(L, 1);
292 const char *mode = luaL_optstring(L, 2,
"r");
293 LStream *p = newprefile(L);
294 luaL_argcheck(L, l_checkmodep(mode), 2,
"invalid mode");
295 p->f = l_popen(L, filename, mode);
296 p->closef = &io_pclose;
297 return (p->f == NULL) ? luaL_fileresult(L, 0, filename) : 1;
302 LStream *p = newfile(L);
304 return (p->f == NULL) ? luaL_fileresult(L, 0, NULL) : 1;
308static FILE *getiofile (
lua_State *L,
const char *findex) {
310 lua_getfield(L, LUA_REGISTRYINDEX, findex);
311 p = (LStream *)lua_touserdata(L, -1);
312 if (l_unlikely(isclosed(p)))
313 luaL_error(L,
"default %s file is closed", findex + IOPREF_LEN);
318static int g_iofile (
lua_State *L,
const char *f,
const char *mode) {
319 if (!lua_isnoneornil(L, 1)) {
320 const char *filename = lua_tostring(L, 1);
322 opencheck(L, filename, mode);
327 lua_setfield(L, LUA_REGISTRYINDEX, f);
330 lua_getfield(L, LUA_REGISTRYINDEX, f);
336 return g_iofile(L, IO_INPUT,
"r");
341 return g_iofile(L, IO_OUTPUT,
"w");
352#define MAXARGLINE 250
363static void aux_lines (
lua_State *L,
int toclose) {
364 int n = lua_gettop(L) - 1;
365 luaL_argcheck(L, n <= MAXARGLINE, MAXARGLINE + 2,
"too many arguments");
367 lua_pushinteger(L, n);
368 lua_pushboolean(L, toclose);
370 lua_pushcclosure(L, io_readline, 3 + n);
388 if (lua_isnone(L, 1)) lua_pushnil(L);
389 if (lua_isnil(L, 1)) {
390 lua_getfield(L, LUA_REGISTRYINDEX, IO_INPUT);
396 const char *filename = luaL_checkstring(L, 1);
397 opencheck(L, filename,
"r");
401 aux_lines(L, toclose);
421#if !defined (L_MAXLENNUM)
422#define L_MAXLENNUM 200
431 char buff[L_MAXLENNUM + 1];
438static int nextc (
RN *rn) {
439 if (l_unlikely(rn->n >= L_MAXLENNUM)) {
444 rn->buff[rn->n++] = rn->c;
445 rn->c = l_getc(rn->f);
454static int test2 (
RN *rn,
const char *set) {
455 if (rn->c == set[0] || rn->c == set[1])
464static int readdigits (
RN *rn,
int hex) {
466 while ((hex ? isxdigit(rn->c) : isdigit(rn->c)) && nextc(rn))
477static int read_number (
lua_State *L, FILE *f) {
483 decp[0] = lua_getlocaledecpoint();
486 do { rn.c = l_getc(rn.f); }
while (isspace(rn.c));
488 if (test2(&rn,
"00")) {
489 if (test2(&rn,
"xX")) hex = 1;
492 count += readdigits(&rn, hex);
493 if (test2(&rn, decp))
494 count += readdigits(&rn, hex);
495 if (count > 0 && test2(&rn, (hex ?
"pP" :
"eE"))) {
501 rn.buff[rn.n] =
'\0';
502 if (l_likely(lua_stringtonumber(L, rn.buff)))
511static int test_eof (
lua_State *L, FILE *f) {
514 lua_pushliteral(L,
"");
519static int read_line (
lua_State *L, FILE *f,
int chop) {
522 luaL_buffinit(L, &b);
524 char *buff = luaL_prepbuffer(&b);
527 while (i < LUAL_BUFFERSIZE && (c = l_getc(f)) != EOF && c !=
'\n')
531 }
while (c != EOF && c !=
'\n');
532 if (!chop && c ==
'\n')
536 return (c ==
'\n' || lua_rawlen(L, -1) > 0);
540static void read_all (
lua_State *L, FILE *f) {
543 luaL_buffinit(L, &b);
545 char *p = luaL_prepbuffer(&b);
546 nr = fread(p,
sizeof(
char), LUAL_BUFFERSIZE, f);
547 luaL_addsize(&b, nr);
548 }
while (nr == LUAL_BUFFERSIZE);
553static int read_chars (
lua_State *L, FILE *f,
size_t n) {
557 luaL_buffinit(L, &b);
558 p = luaL_prepbuffsize(&b, n);
559 nr = fread(p,
sizeof(
char), n, f);
560 luaL_addsize(&b, nr);
566static int g_read (
lua_State *L, FILE *f,
int first) {
567 int nargs = lua_gettop(L) - 1;
571 success = read_line(L, f, 1);
576 luaL_checkstack(L, nargs+LUA_MINSTACK,
"too many arguments");
578 for (n = first; nargs-- && success; n++) {
579 if (lua_type(L, n) == LUA_TNUMBER) {
580 size_t l = (size_t)luaL_checkinteger(L, n);
581 success = (l == 0) ? test_eof(L, f) : read_chars(L, f, l);
584 const char *p = luaL_checkstring(L, n);
588 success = read_number(L, f);
591 success = read_line(L, f, 1);
594 success = read_line(L, f, 0);
601 return luaL_argerror(L, n,
"invalid format");
607 return luaL_fileresult(L, 0, NULL);
617 return g_read(L, getiofile(L, IO_INPUT), 1);
622 return g_read(L, tofile(L), 2);
630 LStream *p = (LStream *)lua_touserdata(L, lua_upvalueindex(1));
632 int n = (int)lua_tointeger(L, lua_upvalueindex(2));
634 return luaL_error(L,
"file is already closed");
636 luaL_checkstack(L, n,
"too many arguments");
637 for (i = 1; i <= n; i++)
638 lua_pushvalue(L, lua_upvalueindex(3 + i));
639 n = g_read(L, p->f, 2);
641 if (lua_toboolean(L, -n))
646 return luaL_error(L,
"%s", lua_tostring(L, -n + 1));
648 if (lua_toboolean(L, lua_upvalueindex(3))) {
650 lua_pushvalue(L, lua_upvalueindex(1));
660static int g_write (
lua_State *L, FILE *f,
int arg) {
661 int nargs = lua_gettop(L) - arg;
663 for (; nargs--; arg++) {
664 if (lua_type(L, arg) == LUA_TNUMBER) {
666 int len = lua_isinteger(L, arg)
667 ? fprintf(f, LUA_INTEGER_FMT,
668 (LUAI_UACINT)lua_tointeger(L, arg))
669 : fprintf(f, LUA_NUMBER_FMT,
670 (LUAI_UACNUMBER)lua_tonumber(L, arg));
671 status = status && (len > 0);
675 const char *s = luaL_checklstring(L, arg, &l);
676 status = status && (fwrite(s,
sizeof(
char), l, f) == l);
679 if (l_likely(status))
681 else return luaL_fileresult(L, status, NULL);
686 return g_write(L, getiofile(L, IO_OUTPUT), 1);
693 return g_write(L, f, 2);
698 static const int mode[] = {SEEK_SET, SEEK_CUR, SEEK_END};
699 static const char *
const modenames[] = {
"set",
"cur",
"end", NULL};
701 int op = luaL_checkoption(L, 2,
"cur", modenames);
702 lua_Integer p3 = luaL_optinteger(L, 3, 0);
703 l_seeknum offset = (l_seeknum)p3;
704 luaL_argcheck(L, (lua_Integer)offset == p3, 3,
705 "not an integer in proper range");
706 op = l_fseek(f, offset, mode[op]);
708 return luaL_fileresult(L, 0, NULL);
710 lua_pushinteger(L, (lua_Integer)l_ftell(f));
717 static const int mode[] = {_IONBF, _IOFBF, _IOLBF};
718 static const char *
const modenames[] = {
"no",
"full",
"line", NULL};
720 int op = luaL_checkoption(L, 2, NULL, modenames);
721 lua_Integer sz = luaL_optinteger(L, 3, LUAL_BUFFERSIZE);
722 int res = setvbuf(f, NULL, mode[op], (
size_t)sz);
723 return luaL_fileresult(L, res == 0, NULL);
729 return luaL_fileresult(L, fflush(getiofile(L, IO_OUTPUT)) == 0, NULL);
734 return luaL_fileresult(L, fflush(tofile(L)) == 0, NULL);
747 {
"output", io_output},
750 {
"tmpfile", io_tmpfile},
767 {
"setvbuf", f_setvbuf},
779 {
"__tostring", f_tostring},
785 luaL_newmetatable(L, LUA_FILEHANDLE);
786 luaL_setfuncs(L, metameth, 0);
787 luaL_newlibtable(L, meth);
788 luaL_setfuncs(L, meth, 0);
789 lua_setfield(L, -2,
"__index");
798 LStream *p = tolstream(L);
799 p->closef = &io_noclose;
801 lua_pushliteral(L,
"cannot close standard file");
806static void createstdfile (
lua_State *L, FILE *f,
const char *k,
808 LStream *p = newprefile(L);
810 p->closef = &io_noclose;
812 lua_pushvalue(L, -1);
813 lua_setfield(L, LUA_REGISTRYINDEX, k);
815 lua_setfield(L, -2, fname);
819LUAMOD_API
int luaopen_io (
lua_State *L) {
820 luaL_newlib(L, iolib);
823 createstdfile(L, stdin, IO_INPUT,
"stdin");
824 createstdfile(L, stdout, IO_OUTPUT,
"stdout");
825 createstdfile(L, stderr, NULL,
"stderr");