diff options
Diffstat (limited to 'src/liolib.c')
-rw-r--r--[-rwxr-xr-x] | src/liolib.c | 106 |
1 files changed, 76 insertions, 30 deletions
diff --git a/src/liolib.c b/src/liolib.c index 41e7ec5..4814aa2 100755..100644 --- a/src/liolib.c +++ b/src/liolib.c @@ -1,10 +1,20 @@ /* -** $Id: liolib.c,v 2.101 2011/06/27 19:42:31 roberto Exp $ +** $Id: liolib.c,v 2.108 2011/11/25 12:50:03 roberto Exp $ ** Standard I/O (and system) library ** See Copyright Notice in lua.h */ +/* +** POSIX idiosyncrasy! +** This definition must come before the inclusion of 'stdio.h'; it +** should not affect non-POSIX systems +*/ +#if !defined(_FILE_OFFSET_BITS) +#define _FILE_OFFSET_BITS 64 +#endif + + #include <errno.h> #include <stdio.h> #include <stdlib.h> @@ -21,9 +31,12 @@ /* -** lua_popen spawns a new process connected to the current one through -** the file streams. +** {====================================================== +** lua_popen spawns a new process connected to the current +** one through the file streams. +** ======================================================= */ + #if !defined(lua_popen) /* { */ #if defined(LUA_USE_POPEN) /* { */ @@ -48,22 +61,50 @@ #endif /* } */ +/* }====================================================== */ + + +/* +** {====================================================== +** lua_fseek/lua_ftell: configuration for longer offsets +** ======================================================= +*/ + +#if !defined(lua_fseek) /* { */ + +#if defined(LUA_USE_POSIX) + +#define l_fseek(f,o,w) fseeko(f,o,w) +#define l_ftell(f) ftello(f) +#define l_seeknum off_t + +#elif defined(LUA_WIN) && !defined(_CRTIMP_TYPEINFO) \ + && defined(_MSC_VER) && (_MSC_VER >= 1400) +/* Windows (but not DDK) and Visual C++ 2005 or higher */ + +#define l_fseek(f,o,w) _fseeki64(f,o,w) +#define l_ftell(f) _ftelli64(f) +#define l_seeknum __int64 + +#else + +#define l_fseek(f,o,w) fseek(f,o,w) +#define l_ftell(f) ftell(f) +#define l_seeknum long + +#endif + +#endif /* } */ + +/* }====================================================== */ + #define IO_PREFIX "_IO_" #define IO_INPUT (IO_PREFIX "input") #define IO_OUTPUT (IO_PREFIX "output") -typedef struct LStream { - FILE *f; /* stream */ - lua_CFunction closef; /* to close stream (NULL for closed streams) */ -} LStream; - - -static void fileerror (lua_State *L, int arg, const char *filename) { - lua_pushfstring(L, "%s: %s", filename, strerror(errno)); - luaL_argerror(L, arg, lua_tostring(L, -1)); -} +typedef luaL_Stream LStream; #define tolstream(L) ((LStream *)luaL_checkudata(L, 1, LUA_FILEHANDLE)) @@ -159,6 +200,14 @@ static LStream *newfile (lua_State *L) { } +static void opencheck (lua_State *L, const char *fname, const char *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)); +} + + static int io_open (lua_State *L) { const char *filename = luaL_checkstring(L, 1); const char *mode = luaL_optstring(L, 2, "r"); @@ -169,7 +218,7 @@ static int io_open (lua_State *L) { (mode[i] != '+' || ++i) && /* skip if char is '+' */ (mode[i] != 'b' || ++i) && /* skip if char is 'b' */ (mode[i] == '\0'))) - return luaL_error(L, "invalid mode " LUA_QL("%s") + 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; @@ -215,12 +264,8 @@ static FILE *getiofile (lua_State *L, const char *findex) { static int g_iofile (lua_State *L, const char *f, const char *mode) { if (!lua_isnoneornil(L, 1)) { const char *filename = lua_tostring(L, 1); - if (filename) { - LStream *p = newfile(L); - p->f = fopen(filename, mode); - if (p->f == NULL) - fileerror(L, 1, filename); - } + if (filename) + opencheck(L, filename, mode); else { tofile(L); /* check that it's a valid file handle */ lua_pushvalue(L, 1); @@ -277,10 +322,7 @@ static int io_lines (lua_State *L) { } else { /* open a new file */ const char *filename = luaL_checkstring(L, 1); - LStream *p = newfile(L); - p->f = fopen(filename, "r"); - if (p->f == NULL) - fileerror(L, 1, filename); + opencheck(L, filename, "r"); lua_replace(L, 1); /* put file at index 1 */ toclose = 1; /* close it after iteration */ } @@ -444,9 +486,10 @@ static int io_readline (lua_State *L) { if (!lua_isnil(L, -n)) /* read at least one value? */ return n; /* return them */ else { /* first result is nil: EOF or error */ - if (!lua_isnil(L, -1)) /* is there error information? */ - return luaL_error(L, "%s", lua_tostring(L, -1)); /* error */ - /* else EOF */ + 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))) { /* generator created file? */ lua_settop(L, 0); lua_pushvalue(L, lua_upvalueindex(1)); @@ -496,12 +539,15 @@ static int f_seek (lua_State *L) { static const char *const modenames[] = {"set", "cur", "end", NULL}; FILE *f = tofile(L); int op = luaL_checkoption(L, 2, "cur", modenames); - long offset = luaL_optlong(L, 3, 0); - op = fseek(f, offset, mode[op]); + lua_Number p3 = luaL_optnumber(L, 3, 0); + l_seeknum offset = (l_seeknum)p3; + luaL_argcheck(L, (lua_Number)offset == p3, 3, + "not an integer in proper range"); + op = l_fseek(f, offset, mode[op]); if (op) return luaL_fileresult(L, 0, NULL); /* error */ else { - lua_pushinteger(L, ftell(f)); + lua_pushnumber(L, (lua_Number)l_ftell(f)); return 1; } } |