new implementation for userdatas, without `keys'

This commit is contained in:
Roberto Ierusalimschy
2001-06-06 15:00:19 -03:00
parent da673d31aa
commit d5b83ead90
17 changed files with 215 additions and 220 deletions

View File

@@ -1,5 +1,5 @@
/*
** $Id: liolib.c,v 1.111 2001/03/26 14:31:49 roberto Exp roberto $
** $Id: liolib.c,v 1.112 2001/04/23 16:35:45 roberto Exp roberto $
** Standard I/O (and system) library
** See Copyright Notice in lua.h
*/
@@ -48,15 +48,17 @@ int pclose(); */
#define OUTFILE 1
#define NOFILE 2
#define FILEHANDLE l_s("FileHandle")
#define FILEHANDLE l_s("FileHandle")
#define CLOSEDFILEHANDLE l_s("ClosedFileHandle")
static const l_char *const filenames[] = {l_s("_INPUT"), l_s("_OUTPUT")};
static const l_char *const basicfiles[] = {l_s("_STDIN"), l_s("_STDOUT")};
static int pushresult (lua_State *L, int i) {
if (i) {
lua_pushuserdata(L, NULL);
lua_newuserdatabox(L, NULL);
return 1;
}
else {
@@ -81,16 +83,15 @@ static int pushresult (lua_State *L, int i) {
static FILE *getopthandle (lua_State *L, int inout) {
FILE *p = (FILE *)lua_touserdata(L, 1);
if (p != NULL) { /* is it a userdata ? */
if (!checkfile(L, 1)) {
if (strcmp(lua_xtypename(L, 1), l_s("ClosedFileHandle")) == 0)
if (!checkfile(L, 1)) { /* not a valid file handle? */
if (strcmp(lua_xtypename(L, 1), CLOSEDFILEHANDLE) == 0)
luaL_argerror(L, 1, l_s("file is closed"));
else
luaL_argerror(L, 1, l_s("(invalid value)"));
}
/* move it to stack top */
lua_pushvalue(L, 1); lua_remove(L, 1);
lua_pushvalue(L, 1); lua_remove(L, 1); /* move it to stack top */
}
else if (inout != NOFILE) { /* try global value */
else { /* try global value */
lua_getglobal(L, filenames[inout]);
if (!checkfile(L,-1))
luaL_verror(L, l_s("global variable `%.10s' is not a valid file handle"),
@@ -101,46 +102,50 @@ static FILE *getopthandle (lua_State *L, int inout) {
}
static void pushfile (lua_State *L, FILE *f) {
lua_pushusertag(L, f, lua_name2tag(L, FILEHANDLE));
static void newfile (lua_State *L, FILE *f) {
lua_newuserdatabox(L, f);
lua_settag(L, lua_name2tag(L, FILEHANDLE));
}
static void setfilebyname (lua_State *L, FILE *f, const l_char *name) {
pushfile(L, f);
static void newfilewithname (lua_State *L, FILE *f, const l_char *name) {
newfile(L, f);
lua_setglobal(L, name);
}
#define setfile(L,f,inout) (setfilebyname(L,f,filenames[inout]))
static int setreturn (lua_State *L, FILE *f, int inout) {
static int setnewfile (lua_State *L, FILE *f, int inout) {
if (f == NULL)
return pushresult(L, 0);
else {
if (inout != NOFILE)
setfile(L, f, inout);
pushfile(L, f);
newfile(L, f);
if (inout != NOFILE) {
lua_pushvalue(L, -1);
lua_setglobal(L, filenames[inout]);
}
return 1;
}
}
static int closefile (lua_State *L, FILE *f) {
if (f == stdin || f == stdout || f == stderr)
return 1;
else {
lua_pushuserdata(L, f);
lua_settag(L, lua_name2tag(L, l_s("ClosedFileHandle")));
return (CLOSEFILE(L, f) == 0);
}
static void resetfile (lua_State *L, int inout) {
lua_getglobal(L, basicfiles[inout]);
lua_setglobal(L, filenames[inout]);
}
static int io_close (lua_State *L) {
FILE *f = (FILE *)luaL_check_userdata(L, 1, FILEHANDLE);
return pushresult(L, closefile(L, f));
FILE *f;
int status;
lua_settop(L, 1);
f = luaL_check_userdata(L, 1, FILEHANDLE);
if (f == stdin || f == stdout || f == stderr)
status = 1;
else {
lua_settag(L, lua_name2tag(L, CLOSEDFILEHANDLE));
status = (CLOSEFILE(L, f) == 0);
}
return pushresult(L, status);
}
@@ -154,12 +159,12 @@ static int file_collect (lua_State *L) {
static int io_open (lua_State *L) {
FILE *f = fopen(luaL_check_string(L, 1), luaL_check_string(L, 2));
return setreturn(L, f, NOFILE);
return setnewfile(L, f, NOFILE);
}
static int io_tmpfile (lua_State *L) {
return setreturn(L, tmpfile(), NOFILE);
return setnewfile(L, tmpfile(), NOFILE);
}
@@ -167,16 +172,15 @@ static int io_tmpfile (lua_State *L) {
static int io_fromto (lua_State *L, int inout, const l_char *mode) {
FILE *current;
if (lua_isnull(L, 1)) {
closefile(L, getopthandle(L, inout));
current = (inout == 0) ? stdin : stdout;
getopthandle(L, inout);
resetfile(L, inout);
return io_close(L);
}
else if (checkfile(L, 1)) /* deprecated option */
current = (FILE *)lua_touserdata(L, 1);
else {
const l_char *s = luaL_check_string(L, 1);
current = (*s == l_c('|')) ? popen(s+1, mode) : fopen(s, mode);
return setnewfile(L, current, inout);
}
return setreturn(L, current, inout);
}
@@ -192,7 +196,7 @@ static int io_writeto (lua_State *L) {
static int io_appendto (lua_State *L) {
FILE *current = fopen(luaL_check_string(L, 1), l_s("a"));
return setreturn(L, current, OUTFILE);
return setnewfile(L, current, OUTFILE);
}
@@ -388,8 +392,8 @@ static int io_seek (lua_State *L) {
static int io_flush (lua_State *L) {
FILE *f = getopthandle(L, NOFILE);
luaL_arg_check(L, f || lua_isnull(L, 1), 1, l_s("invalid file handle"));
FILE *f = (lua_isnull(L, 1)) ? (FILE *)NULL :
(FILE *)luaL_check_userdata(L, 1, FILEHANDLE);
return pushresult(L, fflush(f) == 0);
}
@@ -679,14 +683,14 @@ static const luaL_reg iolib[] = {
LUALIB_API int lua_iolibopen (lua_State *L) {
int iotag = lua_newxtype(L, FILEHANDLE, LUA_TUSERDATA);
lua_newxtype(L, l_s("ClosedFileHandle"), LUA_TUSERDATA);
lua_newxtype(L, CLOSEDFILEHANDLE, LUA_TUSERDATA);
luaL_openl(L, iolib);
/* predefined file handles */
setfile(L, stdin, INFILE);
setfile(L, stdout, OUTFILE);
setfilebyname(L, stdin, l_s("_STDIN"));
setfilebyname(L, stdout, l_s("_STDOUT"));
setfilebyname(L, stderr, l_s("_STDERR"));
newfilewithname(L, stdin, basicfiles[INFILE]);
newfilewithname(L, stdout, basicfiles[OUTFILE]);
newfilewithname(L, stderr, l_s("_STDERR"));
resetfile(L, INFILE);
resetfile(L, OUTFILE);
/* close files when collected */
lua_pushcfunction(L, file_collect);
lua_settagmethod(L, iotag, l_s("gc"));