diff options
| author | Roberto Ierusalimschy <roberto@inf.puc-rio.br> | 2002-11-25 13:05:39 -0200 |
|---|---|---|
| committer | Roberto Ierusalimschy <roberto@inf.puc-rio.br> | 2002-11-25 13:05:39 -0200 |
| commit | d9340154accd593984fa0d2101fe5f3b63f4c3a2 (patch) | |
| tree | 9ca9227a2027acef0a507b27be77718f7b7e6260 /liolib.c | |
| parent | e47baca75a3854c9f3065c554d6758bd23c5d73f (diff) | |
| download | lua-d9340154accd593984fa0d2101fe5f3b63f4c3a2.tar.gz lua-d9340154accd593984fa0d2101fe5f3b63f4c3a2.tar.bz2 lua-d9340154accd593984fa0d2101fe5f3b63f4c3a2.zip | |
`__tostring' for files + small bug (could do invalid read inside
a userdata when it was not a file)
Diffstat (limited to 'liolib.c')
| -rw-r--r-- | liolib.c | 55 |
1 files changed, 35 insertions, 20 deletions
| @@ -1,5 +1,5 @@ | |||
| 1 | /* | 1 | /* |
| 2 | ** $Id: liolib.c,v 2.23 2002/11/14 15:41:38 roberto Exp roberto $ | 2 | ** $Id: liolib.c,v 2.24 2002/11/18 16:53:19 roberto Exp roberto $ |
| 3 | ** Standard I/O (and system) library | 3 | ** Standard I/O (and system) library |
| 4 | ** See Copyright Notice in lua.h | 4 | ** See Copyright Notice in lua.h |
| 5 | */ | 5 | */ |
| @@ -54,23 +54,26 @@ static int pushresult (lua_State *L, int i, const char *filename) { | |||
| 54 | } | 54 | } |
| 55 | 55 | ||
| 56 | 56 | ||
| 57 | static FILE *tofile (lua_State *L, int findex) { | 57 | static FILE **topfile (lua_State *L, int findex) { |
| 58 | FILE **f = (FILE **)lua_touserdata(L, findex); | 58 | FILE **f = (FILE **)lua_touserdata(L, findex); |
| 59 | if (f && *f && lua_getmetatable(L, findex) && | 59 | if (f == NULL || !lua_getmetatable(L, findex) || |
| 60 | lua_rawequal(L, -1, lua_upvalueindex(1))) { | 60 | !lua_rawequal(L, -1, lua_upvalueindex(1))) { |
| 61 | lua_pop(L, 1); | 61 | luaL_argerror(L, findex, "bad file"); |
| 62 | return *f; | ||
| 63 | } | ||
| 64 | if (findex > 0) { | ||
| 65 | if (f && *f == NULL) | ||
| 66 | luaL_error(L, "attempt to use a closed file"); | ||
| 67 | else | ||
| 68 | luaL_argerror(L, findex, "bad file"); | ||
| 69 | } | 62 | } |
| 70 | return NULL; | 63 | lua_pop(L, 1); |
| 64 | return f; | ||
| 65 | } | ||
| 66 | |||
| 67 | |||
| 68 | static FILE *tofile (lua_State *L, int findex) { | ||
| 69 | FILE **f = topfile(L, findex); | ||
| 70 | if (*f == NULL) | ||
| 71 | luaL_error(L, "attempt to use a closed file"); | ||
| 72 | return *f; | ||
| 71 | } | 73 | } |
| 72 | 74 | ||
| 73 | 75 | ||
| 76 | |||
| 74 | /* | 77 | /* |
| 75 | ** When creating file handles, always creates a `closed' file handle | 78 | ** When creating file handles, always creates a `closed' file handle |
| 76 | ** before opening the actual file; so, if there is a memory error, the | 79 | ** before opening the actual file; so, if there is a memory error, the |
| @@ -126,13 +129,25 @@ static int io_close (lua_State *L) { | |||
| 126 | 129 | ||
| 127 | 130 | ||
| 128 | static int io_gc (lua_State *L) { | 131 | static int io_gc (lua_State *L) { |
| 129 | FILE **f = (FILE **)lua_touserdata(L, 1); | 132 | FILE **f = topfile(L, 1); |
| 130 | if (!(f && *f == NULL)) /* ignore closed files */ | 133 | if (*f != NULL) /* ignore closed files */ |
| 131 | aux_close(L); | 134 | aux_close(L); |
| 132 | return 0; | 135 | return 0; |
| 133 | } | 136 | } |
| 134 | 137 | ||
| 135 | 138 | ||
| 139 | static int io_tostring (lua_State *L) { | ||
| 140 | char buff[32]; | ||
| 141 | FILE **f = topfile(L, 1); | ||
| 142 | if (*f == NULL) | ||
| 143 | strcpy(buff, "closed"); | ||
| 144 | else | ||
| 145 | sprintf(buff, "%p", lua_touserdata(L, 1)); | ||
| 146 | lua_pushfstring(L, "file (%s)", buff); | ||
| 147 | return 1; | ||
| 148 | } | ||
| 149 | |||
| 150 | |||
| 136 | static int io_open (lua_State *L) { | 151 | static int io_open (lua_State *L) { |
| 137 | const char *filename = luaL_checkstring(L, 1); | 152 | const char *filename = luaL_checkstring(L, 1); |
| 138 | const char *mode = luaL_optstring(L, 2, "r"); | 153 | const char *mode = luaL_optstring(L, 2, "r"); |
| @@ -164,13 +179,9 @@ static int io_tmpfile (lua_State *L) { | |||
| 164 | 179 | ||
| 165 | 180 | ||
| 166 | static FILE *getiofile (lua_State *L, const char *name) { | 181 | static FILE *getiofile (lua_State *L, const char *name) { |
| 167 | FILE *f; | ||
| 168 | lua_pushstring(L, name); | 182 | lua_pushstring(L, name); |
| 169 | lua_rawget(L, lua_upvalueindex(1)); | 183 | lua_rawget(L, lua_upvalueindex(1)); |
| 170 | f = tofile(L, -1); | 184 | return tofile(L, -1); |
| 171 | if (f == NULL) | ||
| 172 | luaL_error(L, "%s is closed", name); | ||
| 173 | return f; | ||
| 174 | } | 185 | } |
| 175 | 186 | ||
| 176 | 187 | ||
| @@ -478,6 +489,10 @@ static void createmeta (lua_State *L) { | |||
| 478 | lua_pushvalue(L, -2); /* push metatable (will be upvalue for `gc' method) */ | 489 | lua_pushvalue(L, -2); /* push metatable (will be upvalue for `gc' method) */ |
| 479 | lua_pushcclosure(L, io_gc, 1); | 490 | lua_pushcclosure(L, io_gc, 1); |
| 480 | lua_rawset(L, -3); /* metatable.__gc = io_gc */ | 491 | lua_rawset(L, -3); /* metatable.__gc = io_gc */ |
| 492 | lua_pushliteral(L, "__tostring"); | ||
| 493 | lua_pushvalue(L, -2); /* push metatable */ | ||
| 494 | lua_pushcclosure(L, io_tostring, 1); | ||
| 495 | lua_rawset(L, -3); | ||
| 481 | /* file methods */ | 496 | /* file methods */ |
| 482 | lua_pushliteral(L, "__index"); | 497 | lua_pushliteral(L, "__index"); |
| 483 | lua_pushvalue(L, -2); /* push metatable */ | 498 | lua_pushvalue(L, -2); /* push metatable */ |
