diff --git a/lauxlib.c b/lauxlib.c index 3f34db03..0524125e 100644 --- a/lauxlib.c +++ b/lauxlib.c @@ -1,5 +1,5 @@ /* -** $Id: lauxlib.c,v 1.86 2002/09/16 19:49:45 roberto Exp roberto $ +** $Id: lauxlib.c,v 1.87 2002/10/04 14:31:40 roberto Exp roberto $ ** Auxiliary functions for building Lua libraries ** See Copyright Notice in lua.h */ @@ -345,38 +345,42 @@ static const char *getF (lua_State *L, void *ud, size_t *size) { } -static int errfile (lua_State *L, const char *filename) { - if (filename == NULL) filename = "stdin"; +static int errfile (lua_State *L, int fnameindex) { + const char *filename = lua_tostring(L, fnameindex) + 1; lua_pushfstring(L, "cannot read %s: %s", filename, strerror(errno)); + lua_remove(L, fnameindex); return LUA_ERRFILE; } LUALIB_API int luaL_loadfile (lua_State *L, const char *filename) { LoadF lf; - int status; + int status, readstatus; int c; - int old_top = lua_gettop(L); - lf.f = (filename == NULL) ? stdin : fopen(filename, "r"); - if (lf.f == NULL) return errfile(L, filename); /* unable to open file */ + int fnameindex = lua_gettop(L) + 1; /* index of filename on the stack */ + if (filename == NULL) { + lua_pushliteral(L, "=stdin"); + lf.f = stdin; + } + else { + lua_pushfstring(L, "@%s", filename); + lf.f = fopen(filename, "r"); + } + if (lf.f == NULL) return errfile(L, fnameindex); /* unable to open file */ c = ungetc(getc(lf.f), lf.f); if (!(isspace(c) || isprint(c)) && lf.f != stdin) { /* binary file? */ fclose(lf.f); lf.f = fopen(filename, "rb"); /* reopen in binary mode */ - if (lf.f == NULL) return errfile(L, filename); /* unable to reopen file */ + if (lf.f == NULL) return errfile(L, fnameindex); /* unable to reopen file */ } - if (filename == NULL) - lua_pushliteral(L, "=stdin"); - else - lua_pushfstring(L, "@%s", filename); status = lua_load(L, getF, &lf, lua_tostring(L, -1)); - lua_remove(L, old_top+1); /* remove filename from stack */ - if (ferror(lf.f)) { - lua_settop(L, old_top); /* ignore results from `lua_load' */ - return errfile(L, filename); + readstatus = ferror(lf.f); + if (lf.f != stdin) fclose(lf.f); /* close file (even in case of errors) */ + if (readstatus) { + lua_settop(L, fnameindex); /* ignore results from `lua_load' */ + return errfile(L, fnameindex); } - if (lf.f != stdin) - fclose(lf.f); + lua_remove(L, fnameindex); return status; } diff --git a/liolib.c b/liolib.c index 13d63d33..c3981247 100644 --- a/liolib.c +++ b/liolib.c @@ -1,5 +1,5 @@ /* -** $Id: liolib.c,v 2.19 2002/09/19 20:12:47 roberto Exp roberto $ +** $Id: liolib.c,v 2.20 2002/10/11 20:40:32 roberto Exp roberto $ ** Standard I/O (and system) library ** See Copyright Notice in lua.h */ @@ -68,18 +68,25 @@ static FILE *tofile (lua_State *L, int findex) { } -static void newfile (lua_State *L, FILE *f) { - lua_boxpointer(L, f); +/* +** 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. +*/ +static FILE **newfile (lua_State *L) { + FILE **pf = (FILE **)lua_newuserdata(L, sizeof(FILE *)); + *pf = NULL; /* file handle is currently `closed' */ lua_pushliteral(L, FILEHANDLE); lua_rawget(L, LUA_REGISTRYINDEX); lua_setmetatable(L, -2); + return pf; } static void registerfile (lua_State *L, FILE *f, const char *name, const char *impname) { lua_pushstring(L, name); - newfile(L, f); + *newfile(L) = f; if (impname) { lua_pushstring(L, impname); lua_pushvalue(L, -2); @@ -89,16 +96,6 @@ static void registerfile (lua_State *L, FILE *f, const char *name, } -static int setnewfile (lua_State *L, FILE *f) { - if (f == NULL) - return pushresult(L, 0); - else { - newfile(L, f); - return 1; - } -} - - static int aux_close (lua_State *L) { FILE *f = tofile(L, 1); if (f == stdin || f == stdout || f == stderr) @@ -126,8 +123,11 @@ static int io_gc (lua_State *L) { static int io_open (lua_State *L) { - FILE *f = fopen(luaL_check_string(L, 1), luaL_opt_string(L, 2, "r")); - return setnewfile(L, f); + const char *filename = luaL_check_string(L, 1); + const char *mode = luaL_opt_string(L, 2, "r"); + FILE **pf = newfile(L); + *pf = fopen(filename, mode); + return (*pf == NULL) ? pushresult(L, 0) : 1; } @@ -136,14 +136,19 @@ static int io_popen (lua_State *L) { luaL_error(L, "`popen' not supported"); return 0; #else - FILE *f = popen(luaL_check_string(L, 1), luaL_opt_string(L, 2, "r")); - return setnewfile(L, f); + const char *filename = luaL_check_string(L, 1); + const char *mode = luaL_opt_string(L, 2, "r"); + FILE **pf = newfile(L); + *pf = popen(filename, mode); + return (*pf == NULL) ? pushresult(L, 0) : 1; #endif } static int io_tmpfile (lua_State *L) { - return setnewfile(L, tmpfile()); + FILE **pf = newfile(L); + *pf = tmpfile(); + return (*pf == NULL) ? pushresult(L, 0) : 1; } @@ -168,9 +173,9 @@ static int g_iofile (lua_State *L, const char *name, const char *mode) { const char *filename = lua_tostring(L, 1); lua_pushstring(L, name); if (filename) { - FILE *f = fopen(filename, mode); - luaL_arg_check(L, f, 1, strerror(errno)); - newfile(L, f); + FILE **pf = newfile(L); + *pf = fopen(filename, mode); + luaL_arg_check(L, *pf, 1, strerror(errno)); } else { tofile(L, 1); /* check that it's a valid file handle */ @@ -218,9 +223,10 @@ static int io_lines (lua_State *L) { return f_lines(L); } else { - FILE *f = fopen(luaL_check_string(L, 1), "r"); - luaL_arg_check(L, f, 1, strerror(errno)); - newfile(L, f); + const char *filename = luaL_check_string(L, 1); + FILE **pf = newfile(L); + *pf = fopen(filename, "r"); + luaL_arg_check(L, *pf, 1, strerror(errno)); aux_lines(L, lua_gettop(L), 1); return 1; }