private static int io_readline (lua_State L) { LStream p = (LStream)lua_touserdata(L, lua_upvalueindex(1)); int i; int n = (int)lua_tointeger(L, lua_upvalueindex(2)); if (isclosed(p)) /* file is already closed? */ return luaL_error(L, "file is already closed"); lua_settop(L , 1); for (i = 1; i <= n; i++) /* push arguments to 'g_read' */ lua_pushvalue(L, lua_upvalueindex(3 + i)); n = g_read(L, p.f, 2); /* 'n' is number of results */ lua_assert(n > 0); /* should return at least a nil */ if (!lua_isnil(L, -n)) /* read at least one value? */ return n; /* return them */ else { /* first result is nil: EOF or error */ if (n > 1) { /* is there error information? */ /* 2nd result is error message */ return luaL_error(L, "%s", lua_tostring(L, -n + 1)); } if (lua_toboolean(L, lua_upvalueindex(3))!=0) { /* generator created file? */ lua_settop(L, 0); lua_pushvalue(L, lua_upvalueindex(1)); aux_close(L); /* close it */ } return 0; } }
/* ** function to (not) close the standard files stdin, stdout, and stderr */ private static int io_noclose (lua_State L) { LStream p = tolstream(L); p.closef = io_noclose; /* keep file opened */ lua_pushnil(L); lua_pushliteral(L, "cannot close standard file"); return 2; }
private static StreamProxy tofile (lua_State L) { LStream p = tolstream(L); if (isclosed(p)) luaL_error(L, "attempt to use a closed file"); lua_assert(p.f!=null); return p.f; }
private static int io_popen (lua_State L) { CharPtr filename = luaL_checkstring(L, 1); CharPtr mode = luaL_optstring(L, 2, "r"); LStream p = newprefile(L); p.f = lua_popen(L, filename, mode); p.closef = io_pclose; return (p.f == null) ? luaL_fileresult(L, 0, filename) : 1; }
private static int f_tostring (lua_State L) { LStream p = tolstream(L); if (isclosed(p)) lua_pushliteral(L, "file (closed)"); else lua_pushfstring(L, "file (%p)", p.f); return 1; }
private static void createstdfile (lua_State L, StreamProxy f, CharPtr k, CharPtr fname) { LStream p = newprefile(L); p.f = f; p.closef = io_noclose; if (k != null) { lua_pushvalue(L, -1); lua_setfield(L, LUA_REGISTRYINDEX, k); /* add file to registry */ } lua_setfield(L, -2, fname); /* add file to module */ }
private static int io_open (lua_State L) { CharPtr filename = luaL_checkstring(L, 1); CharPtr mode = luaL_optstring(L, 2, "r"); LStream p = newfile(L); int i = 0; /* check whether 'mode' matches '[rwa]%+?b?' */ if (!(mode[i] != '\0' && strchr("rwa", mode[i++]) != null && (mode[i] != '+' || ++i != 0) && /* skip if char is '+' */ (mode[i] != 'b' || ++i != 0) && /* skip if char is 'b' */ (mode[i] == '\0'))) return luaL_error(L, "invalid mode " + LUA_QS + " (should match " + LUA_QL("[rwa]%%+?b?") + ")", mode); p.f = fopen(filename, mode); return (p.f == null) ? luaL_fileresult(L, 0, filename) : 1; }
private static int io_tmpfile (lua_State L) { LStream p = newfile(L); p.f = tmpfile(); return (p.f == null) ? luaL_fileresult(L, 0, null) : 1; }
/* ** function to close 'popen' files */ private static int io_pclose (lua_State L) { LStream p = tolstream(L); return luaL_execresult(L, lua_pclose(L, p.f)); }
private static void opencheck (lua_State L, CharPtr fname, CharPtr mode) { LStream p = newfile(L); p.f = fopen(fname, mode); if (p.f == null) luaL_error(L, "cannot open file " + LUA_QS + " (%s)", fname, strerror(errno)); }
private static LStream newfile (lua_State L) { LStream p = newprefile(L); p.f = null; p.closef = io_fclose; return p; }
/* ** function to close regular files */ private static int io_fclose (lua_State L) { LStream p = tolstream(L); int res = fclose(p.f); return luaL_fileresult(L, (res == 0)?1:0, null); }
private static int f_gc (lua_State L) { LStream p = tolstream(L); if (!isclosed(p) && p.f != null) aux_close(L); /* ignore closed and incompletely open files */ return 0; }
private static int aux_close (lua_State L) { LStream p = tolstream(L); lua_CFunction cf = p.closef; p.closef = null; /* mark stream as closed */ return cf(L); /* close it */ }
/* ** When creating file handles, always creates a `closed' file handle ** before opening the actual file; so, if there is a memory error, the ** file is not left opened. */ private static LStream newprefile (lua_State L) { LStream p = (LStream)lua_newuserdata(L, typeof(LStream)); //FIXME:changed, sizeof->typeof p.closef = null; /* mark file handle as 'closed' */ luaL_setmetatable(L, LUA_FILEHANDLE); return p; }
public static bool isclosed(LStream p) { return (p.closef == null); }