summaryrefslogtreecommitdiff
path: root/src/liolib.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/liolib.c')
-rw-r--r--[-rwxr-xr-x]src/liolib.c106
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;
}
}