aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--lapi.c2
-rw-r--r--ldebug.c18
-rw-r--r--ldebug.h2
-rw-r--r--lfunc.c6
-rw-r--r--lvm.c7
-rw-r--r--manual/manual.of25
-rw-r--r--testes/api.lua21
-rw-r--r--testes/db.lua20
-rw-r--r--testes/locals.lua21
9 files changed, 83 insertions, 39 deletions
diff --git a/lapi.c b/lapi.c
index 147ed0ff..9cabe7ca 100644
--- a/lapi.c
+++ b/lapi.c
@@ -1299,7 +1299,7 @@ static const char *aux_upvalue (TValue *fi, int n, TValue **val,
1299 *val = f->upvals[n-1]->v; 1299 *val = f->upvals[n-1]->v;
1300 if (owner) *owner = obj2gco(f->upvals[n - 1]); 1300 if (owner) *owner = obj2gco(f->upvals[n - 1]);
1301 name = p->upvalues[n-1].name; 1301 name = p->upvalues[n-1].name;
1302 return (name == NULL) ? "(*no name)" : getstr(name); 1302 return (name == NULL) ? "(no name)" : getstr(name);
1303 } 1303 }
1304 default: return NULL; /* not a closure */ 1304 default: return NULL; /* not a closure */
1305 } 1305 }
diff --git a/ldebug.c b/ldebug.c
index 766a5231..bd471e0c 100644
--- a/ldebug.c
+++ b/ldebug.c
@@ -192,15 +192,14 @@ static const char *findvararg (CallInfo *ci, int n, StkId *pos) {
192 int nextra = ci->u.l.nextraargs; 192 int nextra = ci->u.l.nextraargs;
193 if (n <= nextra) { 193 if (n <= nextra) {
194 *pos = ci->func - nextra + (n - 1); 194 *pos = ci->func - nextra + (n - 1);
195 return "(*vararg)"; /* generic name for any vararg */ 195 return "(vararg)"; /* generic name for any vararg */
196 } 196 }
197 } 197 }
198 return NULL; /* no such vararg */ 198 return NULL; /* no such vararg */
199} 199}
200 200
201 201
202static const char *findlocal (lua_State *L, CallInfo *ci, int n, 202const char *luaG_findlocal (lua_State *L, CallInfo *ci, int n, StkId *pos) {
203 StkId *pos) {
204 StkId base = ci->func + 1; 203 StkId base = ci->func + 1;
205 const char *name = NULL; 204 const char *name = NULL;
206 if (isLua(ci)) { 205 if (isLua(ci)) {
@@ -211,12 +210,15 @@ static const char *findlocal (lua_State *L, CallInfo *ci, int n,
211 } 210 }
212 if (name == NULL) { /* no 'standard' name? */ 211 if (name == NULL) { /* no 'standard' name? */
213 StkId limit = (ci == L->ci) ? L->top : ci->next->func; 212 StkId limit = (ci == L->ci) ? L->top : ci->next->func;
214 if (limit - base >= n && n > 0) /* is 'n' inside 'ci' stack? */ 213 if (limit - base >= n && n > 0) { /* is 'n' inside 'ci' stack? */
215 name = "(*temporary)"; /* generic name for any valid slot */ 214 /* generic name for any valid slot */
215 name = isLua(ci) ? "(temporary)" : "(C temporary)";
216 }
216 else 217 else
217 return NULL; /* no name */ 218 return NULL; /* no name */
218 } 219 }
219 *pos = base + (n - 1); 220 if (pos)
221 *pos = base + (n - 1);
220 return name; 222 return name;
221} 223}
222 224
@@ -232,7 +234,7 @@ LUA_API const char *lua_getlocal (lua_State *L, const lua_Debug *ar, int n) {
232 } 234 }
233 else { /* active function; get information through 'ar' */ 235 else { /* active function; get information through 'ar' */
234 StkId pos = NULL; /* to avoid warnings */ 236 StkId pos = NULL; /* to avoid warnings */
235 name = findlocal(L, ar->i_ci, n, &pos); 237 name = luaG_findlocal(L, ar->i_ci, n, &pos);
236 if (name) { 238 if (name) {
237 setobjs2s(L, L->top, pos); 239 setobjs2s(L, L->top, pos);
238 api_incr_top(L); 240 api_incr_top(L);
@@ -247,7 +249,7 @@ LUA_API const char *lua_setlocal (lua_State *L, const lua_Debug *ar, int n) {
247 StkId pos = NULL; /* to avoid warnings */ 249 StkId pos = NULL; /* to avoid warnings */
248 const char *name; 250 const char *name;
249 lua_lock(L); 251 lua_lock(L);
250 name = findlocal(L, ar->i_ci, n, &pos); 252 name = luaG_findlocal(L, ar->i_ci, n, &pos);
251 if (name) { 253 if (name) {
252 setobjs2s(L, pos, L->top - 1); 254 setobjs2s(L, pos, L->top - 1);
253 L->top--; /* pop value */ 255 L->top--; /* pop value */
diff --git a/ldebug.h b/ldebug.h
index f080711d..1fe0efab 100644
--- a/ldebug.h
+++ b/ldebug.h
@@ -22,6 +22,8 @@
22#define ABSLINEINFO (-0x80) 22#define ABSLINEINFO (-0x80)
23 23
24LUAI_FUNC int luaG_getfuncline (const Proto *f, int pc); 24LUAI_FUNC int luaG_getfuncline (const Proto *f, int pc);
25LUAI_FUNC const char *luaG_findlocal (lua_State *L, CallInfo *ci, int n,
26 StkId *pos);
25LUAI_FUNC l_noret luaG_typeerror (lua_State *L, const TValue *o, 27LUAI_FUNC l_noret luaG_typeerror (lua_State *L, const TValue *o,
26 const char *opname); 28 const char *opname);
27LUAI_FUNC l_noret luaG_forerror (lua_State *L, const TValue *o, 29LUAI_FUNC l_noret luaG_forerror (lua_State *L, const TValue *o,
diff --git a/lfunc.c b/lfunc.c
index aa6ce58f..11d2850f 100644
--- a/lfunc.c
+++ b/lfunc.c
@@ -14,6 +14,7 @@
14 14
15#include "lua.h" 15#include "lua.h"
16 16
17#include "ldebug.h"
17#include "ldo.h" 18#include "ldo.h"
18#include "lfunc.h" 19#include "lfunc.h"
19#include "lgc.h" 20#include "lgc.h"
@@ -140,6 +141,11 @@ static int closeupval (lua_State *L, TValue *uv, StkId level, int status) {
140 if (likely(status == LUA_OK)) { 141 if (likely(status == LUA_OK)) {
141 if (prepclosingmethod(L, uv, &G(L)->nilvalue)) /* something to call? */ 142 if (prepclosingmethod(L, uv, &G(L)->nilvalue)) /* something to call? */
142 callclose(L, NULL); /* call closing method */ 143 callclose(L, NULL); /* call closing method */
144 else if (!ttisnil(uv)) { /* non-closable non-nil value? */
145 const char *vname = luaG_findlocal(L, L->ci, level - L->ci->func, NULL);
146 if (vname == NULL) vname = "?";
147 luaG_runerror(L, "attempt to close non-closable variable '%s'", vname);
148 }
143 } 149 }
144 else { /* there was an error */ 150 else { /* there was an error */
145 /* save error message and set stack top to 'level + 1' */ 151 /* save error message and set stack top to 'level + 1' */
diff --git a/lvm.c b/lvm.c
index a6dcc9ff..50d967c6 100644
--- a/lvm.c
+++ b/lvm.c
@@ -1427,7 +1427,7 @@ void luaV_execute (lua_State *L, CallInfo *ci) {
1427 } 1427 }
1428 vmcase(OP_CLOSE) { 1428 vmcase(OP_CLOSE) {
1429 L->top = ra + 1; /* everything is free after this slot */ 1429 L->top = ra + 1; /* everything is free after this slot */
1430 ProtectNT(luaF_close(L, ra, LUA_OK)); 1430 Protect(luaF_close(L, ra, LUA_OK));
1431 vmbreak; 1431 vmbreak;
1432 } 1432 }
1433 vmcase(OP_TBC) { 1433 vmcase(OP_TBC) {
@@ -1717,9 +1717,8 @@ void luaV_execute (lua_State *L, CallInfo *ci) {
1717 vmbreak; 1717 vmbreak;
1718 } 1718 }
1719 vmcase(OP_TFORPREP) { 1719 vmcase(OP_TFORPREP) {
1720 /* is 'toclose' a function or has a '__close' metamethod? */ 1720 /* is 'toclose' not nil? */
1721 if (ttisfunction(s2v(ra + 3)) || 1721 if (!ttisnil(s2v(ra + 3))) {
1722 !ttisnil(luaT_gettmbyobj(L, s2v(ra + 3), TM_CLOSE))) {
1723 /* create to-be-closed upvalue for it */ 1722 /* create to-be-closed upvalue for it */
1724 halfProtect(luaF_newtbcupval(L, ra + 3)); 1723 halfProtect(luaF_newtbcupval(L, ra + 3));
1725 } 1724 }
diff --git a/manual/manual.of b/manual/manual.of
index f891c33e..3902f2f3 100644
--- a/manual/manual.of
+++ b/manual/manual.of
@@ -1063,11 +1063,16 @@ which start with @T{0x} or @T{0X}.
1063Hexadecimal constants also accept an optional fractional part 1063Hexadecimal constants also accept an optional fractional part
1064plus an optional binary exponent, 1064plus an optional binary exponent,
1065marked by a letter @Char{p} or @Char{P}. 1065marked by a letter @Char{p} or @Char{P}.
1066
1066A numeric constant with a radix point or an exponent 1067A numeric constant with a radix point or an exponent
1067denotes a float; 1068denotes a float;
1068otherwise, 1069otherwise,
1069if its value fits in an integer, 1070if its value fits in an integer or it is a hexadecimal constant,
1070it denotes an integer. 1071it denotes an integer;
1072otherwise (that is, a decimal integer numeral that overflows),
1073it denotes a float.
1074(Hexadecimal integer numerals that overflow @emph{wrap around};
1075they always denote an integer value.)
1071Examples of valid integer constants are 1076Examples of valid integer constants are
1072@verbatim{ 1077@verbatim{
10733 345 0xff 0xBEBADA 10783 345 0xff 0xBEBADA
@@ -1542,7 +1547,8 @@ If the value of the variable when it goes out of scope is a function,
1542that function is called; 1547that function is called;
1543otherwise, if the value has a @idx{__close} metamethod, 1548otherwise, if the value has a @idx{__close} metamethod,
1544that metamethod is called; 1549that metamethod is called;
1545otherwise, nothing is done. 1550otherwise, if the value is @nil, nothing is done;
1551otherwise, an error is raised.
1546In the function case, 1552In the function case,
1547if the scope is being closed by an error, 1553if the scope is being closed by an error,
1548the error object is passed as an argument to the function; 1554the error object is passed as an argument to the function;
@@ -1665,7 +1671,7 @@ If both operands are integers,
1665the operation is performed over integers and the result is an integer. 1671the operation is performed over integers and the result is an integer.
1666Otherwise, if both operands are numbers, 1672Otherwise, if both operands are numbers,
1667then they are converted to floats, 1673then they are converted to floats,
1668the operation is performed following the usual rules 1674the operation is performed following the machine's rules
1669for floating-point arithmetic 1675for floating-point arithmetic
1670(usually the @x{IEEE 754} standard), 1676(usually the @x{IEEE 754} standard),
1671and the result is a float. 1677and the result is a float.
@@ -4998,7 +5004,7 @@ This call leaves the final string on the top of the stack.
4998 5004
4999} 5005}
5000 5006
5001If you know beforehand the total size of the resulting string, 5007If you know beforehand the maximum size of the resulting string,
5002you can use the buffer like this: 5008you can use the buffer like this:
5003@itemize{ 5009@itemize{
5004 5010
@@ -5012,7 +5018,8 @@ size @id{sz} with a call @T{luaL_buffinitsize(L, &b, sz)}.}
5012@item{ 5018@item{
5013Finish by calling @T{luaL_pushresultsize(&b, sz)}, 5019Finish by calling @T{luaL_pushresultsize(&b, sz)},
5014where @id{sz} is the total size of the resulting string 5020where @id{sz} is the total size of the resulting string
5015copied into that space. 5021copied into that space (which may be smaller than or
5022equal to the preallocated size).
5016} 5023}
5017 5024
5018} 5025}
@@ -5028,8 +5035,8 @@ when you call a buffer operation,
5028the stack is at the same level 5035the stack is at the same level
5029it was immediately after the previous buffer operation. 5036it was immediately after the previous buffer operation.
5030(The only exception to this rule is @Lid{luaL_addvalue}.) 5037(The only exception to this rule is @Lid{luaL_addvalue}.)
5031After calling @Lid{luaL_pushresult} the stack is back to its 5038After calling @Lid{luaL_pushresult},
5032level when the buffer was initialized, 5039the stack is back to its level when the buffer was initialized,
5033plus the final string on its top. 5040plus the final string on its top.
5034 5041
5035} 5042}
@@ -7118,7 +7125,7 @@ empty string as a match immediately after another match.
7118As an example, 7125As an example,
7119consider the results of the following code: 7126consider the results of the following code:
7120@verbatim{ 7127@verbatim{
7121> string.gsub("abc", "()a*()", print) 7128> string.gsub("abc", "()a*()", print);
7122--> 1 2 7129--> 1 2
7123--> 3 3 7130--> 3 3
7124--> 4 4 7131--> 4 4
diff --git a/testes/api.lua b/testes/api.lua
index ed857fd0..6f35e132 100644
--- a/testes/api.lua
+++ b/testes/api.lua
@@ -366,7 +366,7 @@ do
366 -- "argerror" without frames 366 -- "argerror" without frames
367 assert(T.checkpanic("loadstring 4") == 367 assert(T.checkpanic("loadstring 4") ==
368 "bad argument #4 (string expected, got no value)") 368 "bad argument #4 (string expected, got no value)")
369 369
370 370
371 -- memory error 371 -- memory error
372 T.totalmem(T.totalmem()+10000) -- set low memory limit (+10k) 372 T.totalmem(T.totalmem()+10000) -- set low memory limit (+10k)
@@ -987,12 +987,12 @@ do
987 987
988 local a, b = T.testC([[ 988 local a, b = T.testC([[
989 call 0 1 # create resource 989 call 0 1 # create resource
990 pushint 34 990 pushnil
991 toclose -2 # mark call result to be closed 991 toclose -2 # mark call result to be closed
992 toclose -1 # mark number to be closed (will be ignored) 992 toclose -1 # mark nil to be closed (will be ignored)
993 return 2 993 return 2
994 ]], newresource) 994 ]], newresource)
995 assert(a[1] == 11 and b == 34) 995 assert(a[1] == 11 and b == nil)
996 assert(#openresource == 0) -- was closed 996 assert(#openresource == 0) -- was closed
997 997
998 -- repeat the test, but calling function in a 'multret' context 998 -- repeat the test, but calling function in a 'multret' context
@@ -1005,7 +1005,7 @@ do
1005 assert(#openresource == 0) -- was closed 1005 assert(#openresource == 0) -- was closed
1006 1006
1007 -- error 1007 -- error
1008 local a, b = pcall(T.testC, [[ 1008 local a, b = pcall(T.makeCfunc[[
1009 call 0 1 # create resource 1009 call 0 1 # create resource
1010 toclose -1 # mark it to be closed 1010 toclose -1 # mark it to be closed
1011 error # resource is the error object 1011 error # resource is the error object
@@ -1038,6 +1038,13 @@ do
1038 ]], newresource, check) 1038 ]], newresource, check)
1039 assert(a == 3) -- no extra items left in the stack 1039 assert(a == 3) -- no extra items left in the stack
1040 1040
1041 -- non-closable value
1042 local a, b = pcall(T.makeCfunc[[
1043 pushint 32
1044 toclose -1
1045 ]])
1046 assert(not a and string.find(b, "(C temporary)"))
1047
1041end 1048end
1042 1049
1043 1050
@@ -1249,9 +1256,9 @@ do -- closing state with no extra memory
1249 T.closestate(L) 1256 T.closestate(L)
1250 T.alloccount() 1257 T.alloccount()
1251end 1258end
1252 1259
1253do -- garbage collection with no extra memory 1260do -- garbage collection with no extra memory
1254 local L = T.newstate() 1261 local L = T.newstate()
1255 T.loadlib(L) 1262 T.loadlib(L)
1256 local res = (T.doremote(L, [[ 1263 local res = (T.doremote(L, [[
1257 _ENV = require"_G" 1264 _ENV = require"_G"
diff --git a/testes/db.lua b/testes/db.lua
index 5b243c39..976962b0 100644
--- a/testes/db.lua
+++ b/testes/db.lua
@@ -214,14 +214,14 @@ local function foo (a, ...)
214 local t = table.pack(...) 214 local t = table.pack(...)
215 for i = 1, t.n do 215 for i = 1, t.n do
216 local n, v = debug.getlocal(1, -i) 216 local n, v = debug.getlocal(1, -i)
217 assert(n == "(*vararg)" and v == t[i]) 217 assert(n == "(vararg)" and v == t[i])
218 end 218 end
219 assert(not debug.getlocal(1, -(t.n + 1))) 219 assert(not debug.getlocal(1, -(t.n + 1)))
220 assert(not debug.setlocal(1, -(t.n + 1), 30)) 220 assert(not debug.setlocal(1, -(t.n + 1), 30))
221 if t.n > 0 then 221 if t.n > 0 then
222 (function (x) 222 (function (x)
223 assert(debug.setlocal(2, -1, x) == "(*vararg)") 223 assert(debug.setlocal(2, -1, x) == "(vararg)")
224 assert(debug.setlocal(2, -t.n, x) == "(*vararg)") 224 assert(debug.setlocal(2, -t.n, x) == "(vararg)")
225 end)(430) 225 end)(430)
226 assert(... == 430) 226 assert(... == 430)
227 end 227 end
@@ -328,9 +328,9 @@ assert(a[f] and a[g] and a[assert] and a[debug.getlocal] and not a[print])
328-- tests for manipulating non-registered locals (C and Lua temporaries) 328-- tests for manipulating non-registered locals (C and Lua temporaries)
329 329
330local n, v = debug.getlocal(0, 1) 330local n, v = debug.getlocal(0, 1)
331assert(v == 0 and n == "(*temporary)") 331assert(v == 0 and n == "(C temporary)")
332local n, v = debug.getlocal(0, 2) 332local n, v = debug.getlocal(0, 2)
333assert(v == 2 and n == "(*temporary)") 333assert(v == 2 and n == "(C temporary)")
334assert(not debug.getlocal(0, 3)) 334assert(not debug.getlocal(0, 3))
335assert(not debug.getlocal(0, 0)) 335assert(not debug.getlocal(0, 0))
336 336
@@ -607,7 +607,7 @@ co = load[[
607local a = 0 607local a = 0
608-- 'A' should be visible to debugger only after its complete definition 608-- 'A' should be visible to debugger only after its complete definition
609debug.sethook(function (e, l) 609debug.sethook(function (e, l)
610 if l == 3 then a = a + 1; assert(debug.getlocal(2, 1) == "(*temporary)") 610 if l == 3 then a = a + 1; assert(debug.getlocal(2, 1) == "(temporary)")
611 elseif l == 4 then a = a + 1; assert(debug.getlocal(2, 1) == "A") 611 elseif l == 4 then a = a + 1; assert(debug.getlocal(2, 1) == "A")
612 end 612 end
613end, "l") 613end, "l")
@@ -875,15 +875,15 @@ local debug = require'debug'
875local a = 12 -- a local variable 875local a = 12 -- a local variable
876 876
877local n, v = debug.getlocal(1, 1) 877local n, v = debug.getlocal(1, 1)
878assert(n == "(*temporary)" and v == debug) -- unkown name but known value 878assert(n == "(temporary)" and v == debug) -- unkown name but known value
879n, v = debug.getlocal(1, 2) 879n, v = debug.getlocal(1, 2)
880assert(n == "(*temporary)" and v == 12) -- unkown name but known value 880assert(n == "(temporary)" and v == 12) -- unkown name but known value
881 881
882-- a function with an upvalue 882-- a function with an upvalue
883local f = function () local x; return a end 883local f = function () local x; return a end
884n, v = debug.getupvalue(f, 1) 884n, v = debug.getupvalue(f, 1)
885assert(n == "(*no name)" and v == 12) 885assert(n == "(no name)" and v == 12)
886assert(debug.setupvalue(f, 1, 13) == "(*no name)") 886assert(debug.setupvalue(f, 1, 13) == "(no name)")
887assert(a == 13) 887assert(a == 13)
888 888
889local t = debug.getinfo(f) 889local t = debug.getinfo(f)
diff --git a/testes/locals.lua b/testes/locals.lua
index 90a8b845..24681dd9 100644
--- a/testes/locals.lua
+++ b/testes/locals.lua
@@ -266,6 +266,27 @@ do -- errors in __close
266end 266end
267 267
268 268
269do
270
271 -- errors due to non-closable values
272 local function foo ()
273 local *toclose x = 34
274 end
275 local stat, msg = pcall(foo)
276 assert(not stat and string.find(msg, "variable 'x'"))
277
278
279 -- with other errors, non-closable values are ignored
280 local function foo ()
281 local *toclose x = 34
282 local *toclose y = function () error(32) end
283 end
284 local stat, msg = pcall(foo)
285 assert(not stat and msg == 32)
286
287end
288
289
269if rawget(_G, "T") then 290if rawget(_G, "T") then
270 291
271 -- memory error inside closing function 292 -- memory error inside closing function