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 | |
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)
-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 */ |