summaryrefslogtreecommitdiff
path: root/src/liolib.c
diff options
context:
space:
mode:
authorLua Team <team@lua.org>2005-09-09 12:00:00 +0000
committerrepogen <>2005-09-09 12:00:00 +0000
commitbd80c4ee9b6d9464cf9f3ff4ee41890d8b3ca9e6 (patch)
treee1d7c1b341ccb9a3a1fb044ac6e67b5a5e0259b7 /src/liolib.c
parentbf6b5550cdfbc0c4a3a4577776ad76628d80718e (diff)
downloadlua-github-5.1-alpha.tar.gz
Lua 5.1-alpha5.1-alpha
Diffstat (limited to 'src/liolib.c')
-rw-r--r--src/liolib.c145
1 files changed, 88 insertions, 57 deletions
diff --git a/src/liolib.c b/src/liolib.c
index 1dba7eff..a7f8743f 100644
--- a/src/liolib.c
+++ b/src/liolib.c
@@ -1,5 +1,5 @@
/*
-** $Id: liolib.c,v 2.60 2005/05/16 21:19:00 roberto Exp $
+** $Id: liolib.c,v 2.67 2005/08/26 17:36:32 roberto Exp $
** Standard I/O (and system) library
** See Copyright Notice in lua.h
*/
@@ -20,8 +20,8 @@
-#define IO_INPUT 1
-#define IO_OUTPUT 2
+#define IO_INPUT 1
+#define IO_OUTPUT 2
static const char *const fnames[] = {"input", "output"};
@@ -50,17 +50,17 @@ static void fileerror (lua_State *L, int arg, const char *filename) {
}
-static FILE **topfile (lua_State *L) {
- FILE **f = (FILE **)luaL_checkudata(L, 1, LUA_FILEHANDLE);
- if (f == NULL) luaL_argerror(L, 1, "bad file");
- return f;
-}
+#define topfile(L) ((FILE **)luaL_checkudata(L, 1, LUA_FILEHANDLE))
static int io_type (lua_State *L) {
- FILE **f = (FILE **)luaL_checkudata(L, 1, LUA_FILEHANDLE);
- if (f == NULL) lua_pushnil(L);
- else if (*f == NULL)
+ void *ud;
+ luaL_checkany(L, 1);
+ ud = lua_touserdata(L, 1);
+ lua_getfield(L, LUA_REGISTRYINDEX, LUA_FILEHANDLE);
+ if (ud == NULL || !lua_getmetatable(L, 1) || !lua_rawequal(L, -2, -1))
+ lua_pushnil(L); /* not a file */
+ else if (*((FILE **)ud) == NULL)
lua_pushliteral(L, "closed file");
else
lua_pushliteral(L, "file");
@@ -91,29 +91,45 @@ static FILE **newfile (lua_State *L) {
}
+/*
+** this function has a separated environment, which defines the
+** correct __close for 'popen' files
+*/
+static int io_pclose (lua_State *L) {
+ FILE **p = topfile(L);
+ int ok = lua_pclose(L, *p);
+ if (ok) *p = NULL;
+ return pushresult(L, ok, NULL);
+}
+
+
+static int io_fclose (lua_State *L) {
+ FILE **p = topfile(L);
+ int ok = (fclose(*p) == 0);
+ if (ok) *p = NULL;
+ return pushresult(L, ok, NULL);
+}
+
+
static int aux_close (lua_State *L) {
- FILE *f = tofile(L);
- if (f == stdin || f == stdout || f == stderr)
- return 0; /* file cannot be closed */
- else {
- int ok = (fclose(f) == 0);
- if (ok)
- *(FILE **)lua_touserdata(L, 1) = NULL; /* mark file as closed */
- return ok;
- }
+ lua_getfenv(L, 1);
+ lua_getfield(L, -1, "__close");
+ return (lua_tocfunction(L, -1))(L);
}
static int io_close (lua_State *L) {
if (lua_isnone(L, 1))
lua_rawgeti(L, LUA_ENVIRONINDEX, IO_OUTPUT);
- return pushresult(L, aux_close(L), NULL);
+ tofile(L); /* make sure argument is a file */
+ return aux_close(L);
}
static int io_gc (lua_State *L) {
- FILE **f = topfile(L);
- if (*f != NULL) /* ignore closed files */
+ FILE *f = *topfile(L);
+ /* ignore closed files and standard files */
+ if (f != NULL && f != stdin && f != stdout && f != stderr)
aux_close(L);
return 0;
}
@@ -138,6 +154,15 @@ static int io_open (lua_State *L) {
}
+static int io_popen (lua_State *L) {
+ const char *filename = luaL_checkstring(L, 1);
+ const char *mode = luaL_optstring(L, 2, "r");
+ FILE **pf = newfile(L);
+ *pf = lua_popen(L, filename, mode);
+ return (*pf == NULL) ? pushresult(L, 0, filename) : 1;
+}
+
+
static int io_tmpfile (lua_State *L) {
FILE **pf = newfile(L);
*pf = tmpfile();
@@ -148,7 +173,6 @@ static int io_tmpfile (lua_State *L) {
static FILE *getiofile (lua_State *L, int findex) {
FILE *f;
lua_rawgeti(L, LUA_ENVIRONINDEX, findex);
- lua_assert(luaL_checkudata(L, -1, LUA_FILEHANDLE));
f = *(FILE **)lua_touserdata(L, -1);
if (f == NULL)
luaL_error(L, "standard %s file is closed", fnames[findex - 1]);
@@ -169,7 +193,6 @@ static int g_iofile (lua_State *L, int f, const char *mode) {
tofile(L); /* check that it's a valid file handle */
lua_pushvalue(L, 1);
}
- lua_assert(luaL_checkudata(L, -1, LUA_FILEHANDLE));
lua_rawseti(L, LUA_ENVIRONINDEX, f);
}
/* return current value */
@@ -352,7 +375,7 @@ static int io_readline (lua_State *L) {
luaL_error(L, "file is already closed");
sucess = read_line(L, f);
if (ferror(f))
- luaL_error(L, "%s", strerror(errno));
+ return luaL_error(L, "%s", strerror(errno));
if (sucess) return 1;
else { /* EOF */
if (lua_toboolean(L, lua_upvalueindex(2))) { /* generator created file? */
@@ -400,9 +423,8 @@ static int f_seek (lua_State *L) {
static const int mode[] = {SEEK_SET, SEEK_CUR, SEEK_END};
static const char *const modenames[] = {"set", "cur", "end", NULL};
FILE *f = tofile(L);
- int op = luaL_findstring(luaL_optstring(L, 2, "cur"), modenames);
+ int op = luaL_checkoption(L, 2, "cur", modenames);
lua_Integer offset = luaL_optinteger(L, 3, 0);
- luaL_argcheck(L, op != -1, 2, "invalid mode");
op = fseek(f, offset, mode[op]);
if (op)
return pushresult(L, 0, NULL); /* error */
@@ -417,9 +439,10 @@ static int f_setvbuf (lua_State *L) {
static const int mode[] = {_IONBF, _IOFBF, _IOLBF};
static const char *const modenames[] = {"no", "full", "line", NULL};
FILE *f = tofile(L);
- int op = luaL_findstring(luaL_checkstring(L, 2), modenames);
- luaL_argcheck(L, op != -1, 2, "invalid mode");
- return pushresult(L, setvbuf(f, NULL, mode[op], 0) == 0, NULL);
+ int op = luaL_checkoption(L, 2, NULL, modenames);
+ lua_Integer sz = luaL_optinteger(L, 3, BUFSIZ);
+ int res = setvbuf(f, NULL, mode[op], sz);
+ return pushresult(L, res == 0, NULL);
}
@@ -434,13 +457,14 @@ static int f_flush (lua_State *L) {
}
-static const luaL_reg iolib[] = {
- {"input", io_input},
- {"output", io_output},
- {"lines", io_lines},
+static const luaL_Reg iolib[] = {
{"close", io_close},
{"flush", io_flush},
+ {"input", io_input},
+ {"lines", io_lines},
{"open", io_open},
+ {"output", io_output},
+ {"popen", io_popen},
{"read", io_read},
{"tmpfile", io_tmpfile},
{"type", io_type},
@@ -449,14 +473,14 @@ static const luaL_reg iolib[] = {
};
-static const luaL_reg flib[] = {
+static const luaL_Reg flib[] = {
+ {"close", io_close},
{"flush", f_flush},
- {"read", f_read},
{"lines", f_lines},
+ {"read", f_read},
{"seek", f_seek},
{"setvbuf", f_setvbuf},
{"write", f_write},
- {"close", io_close},
{"__gc", io_gc},
{"__tostring", io_tostring},
{NULL, NULL}
@@ -467,34 +491,41 @@ static void createmeta (lua_State *L) {
luaL_newmetatable(L, LUA_FILEHANDLE); /* create metatable for file handles */
lua_pushvalue(L, -1); /* push metatable */
lua_setfield(L, -2, "__index"); /* metatable.__index = metatable */
- luaL_openlib(L, NULL, flib, 0); /* file methods */
+ luaL_register(L, NULL, flib); /* file methods */
}
-static void createupval (lua_State *L) {
- lua_newtable(L);
- /* create (and set) default files */
- *newfile(L) = stdin;
- lua_rawseti(L, -2, IO_INPUT);
- *newfile(L) = stdout;
- lua_rawseti(L, -2, IO_OUTPUT);
+static void createstdfile (lua_State *L, FILE *f, int k, const char *fname) {
+ *newfile(L) = f;
+ if (k > 0) {
+ lua_pushvalue(L, -1);
+ lua_rawseti(L, LUA_ENVIRONINDEX, k);
+ }
+ lua_setfield(L, -2, fname);
}
-
LUALIB_API int luaopen_io (lua_State *L) {
createmeta(L);
- createupval(L);
- lua_pushvalue(L, -1);
+ /* create new (private) environment */
+ lua_newtable(L);
lua_replace(L, LUA_ENVIRONINDEX);
- luaL_openlib(L, LUA_IOLIBNAME, iolib, 0);
- /* put predefined file handles into `io' table */
- lua_rawgeti(L, -2, IO_INPUT); /* get current input from upval */
- lua_setfield(L, -2, "stdin"); /* io.stdin = upval[IO_INPUT] */
- lua_rawgeti(L, -2, IO_OUTPUT); /* get current output from upval */
- lua_setfield(L, -2, "stdout"); /* io.stdout = upval[IO_OUTPUT] */
- *newfile(L) = stderr;
- lua_setfield(L, -2, "stderr"); /* io.stderr = newfile(stderr) */
+ /* open library */
+ luaL_register(L, LUA_IOLIBNAME, iolib);
+ /* create (and set) default files */
+ createstdfile(L, stdin, IO_INPUT, "stdin");
+ createstdfile(L, stdout, IO_OUTPUT, "stdout");
+ createstdfile(L, stderr, 0, "stderr");
+ /* create environment for 'popen' */
+ lua_getfield(L, -1, "popen");
+ lua_newtable(L);
+ lua_pushcfunction(L, io_pclose);
+ lua_setfield(L, -2, "__close");
+ lua_setfenv(L, -2);
+ lua_pop(L, 1); /* pop 'popen' */
+ /* set default close function */
+ lua_pushcfunction(L, io_fclose);
+ lua_setfield(L, LUA_ENVIRONINDEX, "__close");
return 1;
}