'lua_toclose' gets the index to be closed as an argument
Sometimes it is useful to mark to-be-closed an index that is not
at the top of the stack (e.g., if the value to be closed came from
a function call returning multiple values).
diff --git a/lapi.c b/lapi.c
index 91a6e38..da866a6 100644
--- a/lapi.c
+++ b/lapi.c
@@ -1207,12 +1207,19 @@
}
-LUA_API void lua_toclose (lua_State *L) {
- int nresults = L->ci->nresults;
- luaF_newtbcupval(L, L->top - 1); /* create new to-be-closed upvalue */
+LUA_API void lua_toclose (lua_State *L, int idx) {
+ int nresults;
+ StkId o;
+ lua_lock(L);
+ o = index2stack(L, idx);
+ nresults = L->ci->nresults;
+ api_check(L, L->openupval == NULL || uplevel(L->openupval) < o,
+ "there is an already marked index below");
+ luaF_newtbcupval(L, o); /* create new to-be-closed upvalue */
if (!hastocloseCfunc(nresults)) /* function not marked yet? */
L->ci->nresults = codeNresults(nresults); /* mark it */
lua_assert(hastocloseCfunc(L->ci->nresults));
+ lua_unlock(L);
}
diff --git a/ltests.c b/ltests.c
index 192ae86..c5c1040 100644
--- a/ltests.c
+++ b/ltests.c
@@ -1551,7 +1551,7 @@
return lua_yieldk(L1, nres, i, Cfunck);
}
else if EQ("toclose") {
- lua_toclose(L);
+ lua_toclose(L, getnum);
}
else luaL_error(L, "unknown instruction %s", buff);
}
diff --git a/lua.h b/lua.h
index fe468c8..6aa184d 100644
--- a/lua.h
+++ b/lua.h
@@ -333,7 +333,7 @@
LUA_API lua_Alloc (lua_getallocf) (lua_State *L, void **ud);
LUA_API void (lua_setallocf) (lua_State *L, lua_Alloc f, void *ud);
-LUA_API void (lua_toclose) (lua_State *L);
+LUA_API void (lua_toclose) (lua_State *L, int idx);
/*
diff --git a/testes/api.lua b/testes/api.lua
index a6ddca8..ed857fd 100644
--- a/testes/api.lua
+++ b/testes/api.lua
@@ -985,18 +985,20 @@
return x
end
- local a = T.testC([[
+ local a, b = T.testC([[
call 0 1 # create resource
- toclose # mark it to be closed
- return 1
+ pushint 34
+ toclose -2 # mark call result to be closed
+ toclose -1 # mark number to be closed (will be ignored)
+ return 2
]], newresource)
- assert(a[1] == 11)
+ assert(a[1] == 11 and b == 34)
assert(#openresource == 0) -- was closed
-- repeat the test, but calling function in a 'multret' context
local a = {T.testC([[
call 0 1 # create resource
- toclose # mark it to be closed
+ toclose 2 # mark it to be closed
return 2
]], newresource)}
assert(type(a[1]) == "string" and a[2][1] == 11)
@@ -1005,7 +1007,7 @@
-- error
local a, b = pcall(T.testC, [[
call 0 1 # create resource
- toclose # mark it to be closed
+ toclose -1 # mark it to be closed
error # resource is the error object
]], newresource)
assert(a == false and b[1] == 11)
@@ -1019,10 +1021,10 @@
local a = T.testC([[
pushvalue 2
call 0 1 # create resource
- toclose # mark it to be closed
+ toclose -1 # mark it to be closed
pushvalue 2
call 0 1 # create another resource
- toclose # mark it to be closed
+ toclose -1 # mark it to be closed
pushvalue 3
pushint 2 # there should be two open resources
call 1 0