18e3e3a7aSWarner Losh /*
20495ed39SKyle Evans ** $Id: lapi.c $
38e3e3a7aSWarner Losh ** Lua API
48e3e3a7aSWarner Losh ** See Copyright Notice in lua.h
58e3e3a7aSWarner Losh */
68e3e3a7aSWarner Losh
78e3e3a7aSWarner Losh #define lapi_c
88e3e3a7aSWarner Losh #define LUA_CORE
98e3e3a7aSWarner Losh
108e3e3a7aSWarner Losh #include "lprefix.h"
118e3e3a7aSWarner Losh
128e3e3a7aSWarner Losh
130495ed39SKyle Evans #include <limits.h>
148e3e3a7aSWarner Losh #include <stdarg.h>
158e3e3a7aSWarner Losh #include <string.h>
168e3e3a7aSWarner Losh
178e3e3a7aSWarner Losh #include "lua.h"
188e3e3a7aSWarner Losh
198e3e3a7aSWarner Losh #include "lapi.h"
208e3e3a7aSWarner Losh #include "ldebug.h"
218e3e3a7aSWarner Losh #include "ldo.h"
228e3e3a7aSWarner Losh #include "lfunc.h"
238e3e3a7aSWarner Losh #include "lgc.h"
248e3e3a7aSWarner Losh #include "lmem.h"
258e3e3a7aSWarner Losh #include "lobject.h"
268e3e3a7aSWarner Losh #include "lstate.h"
278e3e3a7aSWarner Losh #include "lstring.h"
288e3e3a7aSWarner Losh #include "ltable.h"
298e3e3a7aSWarner Losh #include "ltm.h"
308e3e3a7aSWarner Losh #include "lundump.h"
318e3e3a7aSWarner Losh #include "lvm.h"
328e3e3a7aSWarner Losh
338e3e3a7aSWarner Losh
348e3e3a7aSWarner Losh
358e3e3a7aSWarner Losh const char lua_ident[] =
368e3e3a7aSWarner Losh "$LuaVersion: " LUA_COPYRIGHT " $"
378e3e3a7aSWarner Losh "$LuaAuthors: " LUA_AUTHORS " $";
388e3e3a7aSWarner Losh
398e3e3a7aSWarner Losh
408e3e3a7aSWarner Losh
410495ed39SKyle Evans /*
428c784bb8SWarner Losh ** Test for a valid index (one that is not the 'nilvalue').
430495ed39SKyle Evans ** '!ttisnil(o)' implies 'o != &G(L)->nilvalue', so it is not needed.
440495ed39SKyle Evans ** However, it covers the most common cases in a faster way.
450495ed39SKyle Evans */
460495ed39SKyle Evans #define isvalid(L, o) (!ttisnil(o) || o != &G(L)->nilvalue)
470495ed39SKyle Evans
488e3e3a7aSWarner Losh
498e3e3a7aSWarner Losh /* test for pseudo index */
508e3e3a7aSWarner Losh #define ispseudo(i) ((i) <= LUA_REGISTRYINDEX)
518e3e3a7aSWarner Losh
528e3e3a7aSWarner Losh /* test for upvalue */
538e3e3a7aSWarner Losh #define isupvalue(i) ((i) < LUA_REGISTRYINDEX)
548e3e3a7aSWarner Losh
558e3e3a7aSWarner Losh
568c784bb8SWarner Losh /*
578c784bb8SWarner Losh ** Convert an acceptable index to a pointer to its respective value.
588c784bb8SWarner Losh ** Non-valid indices return the special nil value 'G(L)->nilvalue'.
598c784bb8SWarner Losh */
index2value(lua_State * L,int idx)600495ed39SKyle Evans static TValue *index2value (lua_State *L, int idx) {
618e3e3a7aSWarner Losh CallInfo *ci = L->ci;
628e3e3a7aSWarner Losh if (idx > 0) {
63*a9490b81SWarner Losh StkId o = ci->func.p + idx;
64*a9490b81SWarner Losh api_check(L, idx <= ci->top.p - (ci->func.p + 1), "unacceptable index");
65*a9490b81SWarner Losh if (o >= L->top.p) return &G(L)->nilvalue;
660495ed39SKyle Evans else return s2v(o);
678e3e3a7aSWarner Losh }
688e3e3a7aSWarner Losh else if (!ispseudo(idx)) { /* negative index */
69*a9490b81SWarner Losh api_check(L, idx != 0 && -idx <= L->top.p - (ci->func.p + 1),
70*a9490b81SWarner Losh "invalid index");
71*a9490b81SWarner Losh return s2v(L->top.p + idx);
728e3e3a7aSWarner Losh }
738e3e3a7aSWarner Losh else if (idx == LUA_REGISTRYINDEX)
748e3e3a7aSWarner Losh return &G(L)->l_registry;
758e3e3a7aSWarner Losh else { /* upvalues */
768e3e3a7aSWarner Losh idx = LUA_REGISTRYINDEX - idx;
778e3e3a7aSWarner Losh api_check(L, idx <= MAXUPVAL + 1, "upvalue index too large");
78*a9490b81SWarner Losh if (ttisCclosure(s2v(ci->func.p))) { /* C closure? */
79*a9490b81SWarner Losh CClosure *func = clCvalue(s2v(ci->func.p));
808c784bb8SWarner Losh return (idx <= func->nupvalues) ? &func->upvalue[idx-1]
818c784bb8SWarner Losh : &G(L)->nilvalue;
828c784bb8SWarner Losh }
838c784bb8SWarner Losh else { /* light C function or Lua function (through a hook)?) */
84*a9490b81SWarner Losh api_check(L, ttislcf(s2v(ci->func.p)), "caller not a C function");
858c784bb8SWarner Losh return &G(L)->nilvalue; /* no upvalues */
868e3e3a7aSWarner Losh }
878e3e3a7aSWarner Losh }
888e3e3a7aSWarner Losh }
898e3e3a7aSWarner Losh
908e3e3a7aSWarner Losh
918c784bb8SWarner Losh
928c784bb8SWarner Losh /*
938c784bb8SWarner Losh ** Convert a valid actual index (not a pseudo-index) to its address.
948c784bb8SWarner Losh */
index2stack(lua_State * L,int idx)958c784bb8SWarner Losh l_sinline StkId index2stack (lua_State *L, int idx) {
960495ed39SKyle Evans CallInfo *ci = L->ci;
970495ed39SKyle Evans if (idx > 0) {
98*a9490b81SWarner Losh StkId o = ci->func.p + idx;
99*a9490b81SWarner Losh api_check(L, o < L->top.p, "invalid index");
1000495ed39SKyle Evans return o;
1010495ed39SKyle Evans }
1020495ed39SKyle Evans else { /* non-positive index */
103*a9490b81SWarner Losh api_check(L, idx != 0 && -idx <= L->top.p - (ci->func.p + 1),
104*a9490b81SWarner Losh "invalid index");
1050495ed39SKyle Evans api_check(L, !ispseudo(idx), "invalid index");
106*a9490b81SWarner Losh return L->top.p + idx;
1070495ed39SKyle Evans }
1088e3e3a7aSWarner Losh }
1098e3e3a7aSWarner Losh
1108e3e3a7aSWarner Losh
lua_checkstack(lua_State * L,int n)1118e3e3a7aSWarner Losh LUA_API int lua_checkstack (lua_State *L, int n) {
1128e3e3a7aSWarner Losh int res;
1130495ed39SKyle Evans CallInfo *ci;
1148e3e3a7aSWarner Losh lua_lock(L);
1150495ed39SKyle Evans ci = L->ci;
1168e3e3a7aSWarner Losh api_check(L, n >= 0, "negative 'n'");
117*a9490b81SWarner Losh if (L->stack_last.p - L->top.p > n) /* stack large enough? */
1188e3e3a7aSWarner Losh res = 1; /* yes; check is OK */
119*a9490b81SWarner Losh else /* need to grow stack */
1200495ed39SKyle Evans res = luaD_growstack(L, n, 0);
121*a9490b81SWarner Losh if (res && ci->top.p < L->top.p + n)
122*a9490b81SWarner Losh ci->top.p = L->top.p + n; /* adjust frame top */
1238e3e3a7aSWarner Losh lua_unlock(L);
1248e3e3a7aSWarner Losh return res;
1258e3e3a7aSWarner Losh }
1268e3e3a7aSWarner Losh
1278e3e3a7aSWarner Losh
lua_xmove(lua_State * from,lua_State * to,int n)1288e3e3a7aSWarner Losh LUA_API void lua_xmove (lua_State *from, lua_State *to, int n) {
1298e3e3a7aSWarner Losh int i;
1308e3e3a7aSWarner Losh if (from == to) return;
1318e3e3a7aSWarner Losh lua_lock(to);
1328e3e3a7aSWarner Losh api_checknelems(from, n);
1338e3e3a7aSWarner Losh api_check(from, G(from) == G(to), "moving among independent states");
134*a9490b81SWarner Losh api_check(from, to->ci->top.p - to->top.p >= n, "stack overflow");
135*a9490b81SWarner Losh from->top.p -= n;
1368e3e3a7aSWarner Losh for (i = 0; i < n; i++) {
137*a9490b81SWarner Losh setobjs2s(to, to->top.p, from->top.p + i);
138*a9490b81SWarner Losh to->top.p++; /* stack already checked by previous 'api_check' */
1398e3e3a7aSWarner Losh }
1408e3e3a7aSWarner Losh lua_unlock(to);
1418e3e3a7aSWarner Losh }
1428e3e3a7aSWarner Losh
1438e3e3a7aSWarner Losh
lua_atpanic(lua_State * L,lua_CFunction panicf)1448e3e3a7aSWarner Losh LUA_API lua_CFunction lua_atpanic (lua_State *L, lua_CFunction panicf) {
1458e3e3a7aSWarner Losh lua_CFunction old;
1468e3e3a7aSWarner Losh lua_lock(L);
1478e3e3a7aSWarner Losh old = G(L)->panic;
1488e3e3a7aSWarner Losh G(L)->panic = panicf;
1498e3e3a7aSWarner Losh lua_unlock(L);
1508e3e3a7aSWarner Losh return old;
1518e3e3a7aSWarner Losh }
1528e3e3a7aSWarner Losh
1538e3e3a7aSWarner Losh
lua_version(lua_State * L)1540495ed39SKyle Evans LUA_API lua_Number lua_version (lua_State *L) {
1550495ed39SKyle Evans UNUSED(L);
1560495ed39SKyle Evans return LUA_VERSION_NUM;
1578e3e3a7aSWarner Losh }
1588e3e3a7aSWarner Losh
1598e3e3a7aSWarner Losh
1608e3e3a7aSWarner Losh
1618e3e3a7aSWarner Losh /*
1628e3e3a7aSWarner Losh ** basic stack manipulation
1638e3e3a7aSWarner Losh */
1648e3e3a7aSWarner Losh
1658e3e3a7aSWarner Losh
1668e3e3a7aSWarner Losh /*
1678e3e3a7aSWarner Losh ** convert an acceptable stack index into an absolute index
1688e3e3a7aSWarner Losh */
lua_absindex(lua_State * L,int idx)1698e3e3a7aSWarner Losh LUA_API int lua_absindex (lua_State *L, int idx) {
1708e3e3a7aSWarner Losh return (idx > 0 || ispseudo(idx))
1718e3e3a7aSWarner Losh ? idx
172*a9490b81SWarner Losh : cast_int(L->top.p - L->ci->func.p) + idx;
1738e3e3a7aSWarner Losh }
1748e3e3a7aSWarner Losh
1758e3e3a7aSWarner Losh
lua_gettop(lua_State * L)1768e3e3a7aSWarner Losh LUA_API int lua_gettop (lua_State *L) {
177*a9490b81SWarner Losh return cast_int(L->top.p - (L->ci->func.p + 1));
1788e3e3a7aSWarner Losh }
1798e3e3a7aSWarner Losh
1808e3e3a7aSWarner Losh
lua_settop(lua_State * L,int idx)1818e3e3a7aSWarner Losh LUA_API void lua_settop (lua_State *L, int idx) {
1820495ed39SKyle Evans CallInfo *ci;
1838c784bb8SWarner Losh StkId func, newtop;
1840495ed39SKyle Evans ptrdiff_t diff; /* difference for new top */
1858e3e3a7aSWarner Losh lua_lock(L);
1860495ed39SKyle Evans ci = L->ci;
187*a9490b81SWarner Losh func = ci->func.p;
1888e3e3a7aSWarner Losh if (idx >= 0) {
189*a9490b81SWarner Losh api_check(L, idx <= ci->top.p - (func + 1), "new top too large");
190*a9490b81SWarner Losh diff = ((func + 1) + idx) - L->top.p;
1910495ed39SKyle Evans for (; diff > 0; diff--)
192*a9490b81SWarner Losh setnilvalue(s2v(L->top.p++)); /* clear new slots */
1938e3e3a7aSWarner Losh }
1948e3e3a7aSWarner Losh else {
195*a9490b81SWarner Losh api_check(L, -(idx+1) <= (L->top.p - (func + 1)), "invalid new top");
1960495ed39SKyle Evans diff = idx + 1; /* will "subtract" index (as it is negative) */
1978e3e3a7aSWarner Losh }
198*a9490b81SWarner Losh api_check(L, L->tbclist.p < L->top.p, "previous pop of an unclosed slot");
199*a9490b81SWarner Losh newtop = L->top.p + diff;
200*a9490b81SWarner Losh if (diff < 0 && L->tbclist.p >= newtop) {
2018c784bb8SWarner Losh lua_assert(hastocloseCfunc(ci->nresults));
202*a9490b81SWarner Losh newtop = luaF_close(L, newtop, CLOSEKTOP, 0);
2038c784bb8SWarner Losh }
204*a9490b81SWarner Losh L->top.p = newtop; /* correct top only after closing any upvalue */
2058c784bb8SWarner Losh lua_unlock(L);
2068c784bb8SWarner Losh }
2078c784bb8SWarner Losh
2088c784bb8SWarner Losh
lua_closeslot(lua_State * L,int idx)2098c784bb8SWarner Losh LUA_API void lua_closeslot (lua_State *L, int idx) {
2108c784bb8SWarner Losh StkId level;
2118c784bb8SWarner Losh lua_lock(L);
2128c784bb8SWarner Losh level = index2stack(L, idx);
213*a9490b81SWarner Losh api_check(L, hastocloseCfunc(L->ci->nresults) && L->tbclist.p == level,
2148c784bb8SWarner Losh "no variable to close at given level");
215*a9490b81SWarner Losh level = luaF_close(L, level, CLOSEKTOP, 0);
2168c784bb8SWarner Losh setnilvalue(s2v(level));
2178e3e3a7aSWarner Losh lua_unlock(L);
2188e3e3a7aSWarner Losh }
2198e3e3a7aSWarner Losh
2208e3e3a7aSWarner Losh
2218e3e3a7aSWarner Losh /*
2228e3e3a7aSWarner Losh ** Reverse the stack segment from 'from' to 'to'
2238e3e3a7aSWarner Losh ** (auxiliary to 'lua_rotate')
2240495ed39SKyle Evans ** Note that we move(copy) only the value inside the stack.
2250495ed39SKyle Evans ** (We do not move additional fields that may exist.)
2268e3e3a7aSWarner Losh */
reverse(lua_State * L,StkId from,StkId to)2278c784bb8SWarner Losh l_sinline void reverse (lua_State *L, StkId from, StkId to) {
2288e3e3a7aSWarner Losh for (; from < to; from++, to--) {
2298e3e3a7aSWarner Losh TValue temp;
2300495ed39SKyle Evans setobj(L, &temp, s2v(from));
2318e3e3a7aSWarner Losh setobjs2s(L, from, to);
2328e3e3a7aSWarner Losh setobj2s(L, to, &temp);
2338e3e3a7aSWarner Losh }
2348e3e3a7aSWarner Losh }
2358e3e3a7aSWarner Losh
2368e3e3a7aSWarner Losh
2378e3e3a7aSWarner Losh /*
2388e3e3a7aSWarner Losh ** Let x = AB, where A is a prefix of length 'n'. Then,
2398e3e3a7aSWarner Losh ** rotate x n == BA. But BA == (A^r . B^r)^r.
2408e3e3a7aSWarner Losh */
lua_rotate(lua_State * L,int idx,int n)2418e3e3a7aSWarner Losh LUA_API void lua_rotate (lua_State *L, int idx, int n) {
2428e3e3a7aSWarner Losh StkId p, t, m;
2438e3e3a7aSWarner Losh lua_lock(L);
244*a9490b81SWarner Losh t = L->top.p - 1; /* end of stack segment being rotated */
2450495ed39SKyle Evans p = index2stack(L, idx); /* start of segment */
2468e3e3a7aSWarner Losh api_check(L, (n >= 0 ? n : -n) <= (t - p + 1), "invalid 'n'");
2478e3e3a7aSWarner Losh m = (n >= 0 ? t - n : p - n - 1); /* end of prefix */
2488e3e3a7aSWarner Losh reverse(L, p, m); /* reverse the prefix with length 'n' */
2498e3e3a7aSWarner Losh reverse(L, m + 1, t); /* reverse the suffix */
2508e3e3a7aSWarner Losh reverse(L, p, t); /* reverse the entire segment */
2518e3e3a7aSWarner Losh lua_unlock(L);
2528e3e3a7aSWarner Losh }
2538e3e3a7aSWarner Losh
2548e3e3a7aSWarner Losh
lua_copy(lua_State * L,int fromidx,int toidx)2558e3e3a7aSWarner Losh LUA_API void lua_copy (lua_State *L, int fromidx, int toidx) {
2568e3e3a7aSWarner Losh TValue *fr, *to;
2578e3e3a7aSWarner Losh lua_lock(L);
2580495ed39SKyle Evans fr = index2value(L, fromidx);
2590495ed39SKyle Evans to = index2value(L, toidx);
2600495ed39SKyle Evans api_check(L, isvalid(L, to), "invalid index");
2618e3e3a7aSWarner Losh setobj(L, to, fr);
2628e3e3a7aSWarner Losh if (isupvalue(toidx)) /* function upvalue? */
263*a9490b81SWarner Losh luaC_barrier(L, clCvalue(s2v(L->ci->func.p)), fr);
2648e3e3a7aSWarner Losh /* LUA_REGISTRYINDEX does not need gc barrier
2658e3e3a7aSWarner Losh (collector revisits it before finishing collection) */
2668e3e3a7aSWarner Losh lua_unlock(L);
2678e3e3a7aSWarner Losh }
2688e3e3a7aSWarner Losh
2698e3e3a7aSWarner Losh
lua_pushvalue(lua_State * L,int idx)2708e3e3a7aSWarner Losh LUA_API void lua_pushvalue (lua_State *L, int idx) {
2718e3e3a7aSWarner Losh lua_lock(L);
272*a9490b81SWarner Losh setobj2s(L, L->top.p, index2value(L, idx));
2738e3e3a7aSWarner Losh api_incr_top(L);
2748e3e3a7aSWarner Losh lua_unlock(L);
2758e3e3a7aSWarner Losh }
2768e3e3a7aSWarner Losh
2778e3e3a7aSWarner Losh
2788e3e3a7aSWarner Losh
2798e3e3a7aSWarner Losh /*
2808e3e3a7aSWarner Losh ** access functions (stack -> C)
2818e3e3a7aSWarner Losh */
2828e3e3a7aSWarner Losh
2838e3e3a7aSWarner Losh
lua_type(lua_State * L,int idx)2848e3e3a7aSWarner Losh LUA_API int lua_type (lua_State *L, int idx) {
2850495ed39SKyle Evans const TValue *o = index2value(L, idx);
2860495ed39SKyle Evans return (isvalid(L, o) ? ttype(o) : LUA_TNONE);
2878e3e3a7aSWarner Losh }
2888e3e3a7aSWarner Losh
2898e3e3a7aSWarner Losh
lua_typename(lua_State * L,int t)2908e3e3a7aSWarner Losh LUA_API const char *lua_typename (lua_State *L, int t) {
2918e3e3a7aSWarner Losh UNUSED(L);
2920495ed39SKyle Evans api_check(L, LUA_TNONE <= t && t < LUA_NUMTYPES, "invalid type");
2938e3e3a7aSWarner Losh return ttypename(t);
2948e3e3a7aSWarner Losh }
2958e3e3a7aSWarner Losh
2968e3e3a7aSWarner Losh
lua_iscfunction(lua_State * L,int idx)2978e3e3a7aSWarner Losh LUA_API int lua_iscfunction (lua_State *L, int idx) {
2980495ed39SKyle Evans const TValue *o = index2value(L, idx);
2998e3e3a7aSWarner Losh return (ttislcf(o) || (ttisCclosure(o)));
3008e3e3a7aSWarner Losh }
3018e3e3a7aSWarner Losh
3028e3e3a7aSWarner Losh
lua_isinteger(lua_State * L,int idx)3038e3e3a7aSWarner Losh LUA_API int lua_isinteger (lua_State *L, int idx) {
3040495ed39SKyle Evans const TValue *o = index2value(L, idx);
3058e3e3a7aSWarner Losh return ttisinteger(o);
3068e3e3a7aSWarner Losh }
3078e3e3a7aSWarner Losh
3088e3e3a7aSWarner Losh
lua_isnumber(lua_State * L,int idx)3098e3e3a7aSWarner Losh LUA_API int lua_isnumber (lua_State *L, int idx) {
3108e3e3a7aSWarner Losh lua_Number n;
3110495ed39SKyle Evans const TValue *o = index2value(L, idx);
3128e3e3a7aSWarner Losh return tonumber(o, &n);
3138e3e3a7aSWarner Losh }
3148e3e3a7aSWarner Losh
3158e3e3a7aSWarner Losh
lua_isstring(lua_State * L,int idx)3168e3e3a7aSWarner Losh LUA_API int lua_isstring (lua_State *L, int idx) {
3170495ed39SKyle Evans const TValue *o = index2value(L, idx);
3188e3e3a7aSWarner Losh return (ttisstring(o) || cvt2str(o));
3198e3e3a7aSWarner Losh }
3208e3e3a7aSWarner Losh
3218e3e3a7aSWarner Losh
lua_isuserdata(lua_State * L,int idx)3228e3e3a7aSWarner Losh LUA_API int lua_isuserdata (lua_State *L, int idx) {
3230495ed39SKyle Evans const TValue *o = index2value(L, idx);
3248e3e3a7aSWarner Losh return (ttisfulluserdata(o) || ttislightuserdata(o));
3258e3e3a7aSWarner Losh }
3268e3e3a7aSWarner Losh
3278e3e3a7aSWarner Losh
lua_rawequal(lua_State * L,int index1,int index2)3288e3e3a7aSWarner Losh LUA_API int lua_rawequal (lua_State *L, int index1, int index2) {
3290495ed39SKyle Evans const TValue *o1 = index2value(L, index1);
3300495ed39SKyle Evans const TValue *o2 = index2value(L, index2);
3310495ed39SKyle Evans return (isvalid(L, o1) && isvalid(L, o2)) ? luaV_rawequalobj(o1, o2) : 0;
3328e3e3a7aSWarner Losh }
3338e3e3a7aSWarner Losh
3348e3e3a7aSWarner Losh
lua_arith(lua_State * L,int op)3358e3e3a7aSWarner Losh LUA_API void lua_arith (lua_State *L, int op) {
3368e3e3a7aSWarner Losh lua_lock(L);
3378e3e3a7aSWarner Losh if (op != LUA_OPUNM && op != LUA_OPBNOT)
3388e3e3a7aSWarner Losh api_checknelems(L, 2); /* all other operations expect two operands */
3398e3e3a7aSWarner Losh else { /* for unary operations, add fake 2nd operand */
3408e3e3a7aSWarner Losh api_checknelems(L, 1);
341*a9490b81SWarner Losh setobjs2s(L, L->top.p, L->top.p - 1);
3428e3e3a7aSWarner Losh api_incr_top(L);
3438e3e3a7aSWarner Losh }
3448e3e3a7aSWarner Losh /* first operand at top - 2, second at top - 1; result go to top - 2 */
345*a9490b81SWarner Losh luaO_arith(L, op, s2v(L->top.p - 2), s2v(L->top.p - 1), L->top.p - 2);
346*a9490b81SWarner Losh L->top.p--; /* remove second operand */
3478e3e3a7aSWarner Losh lua_unlock(L);
3488e3e3a7aSWarner Losh }
3498e3e3a7aSWarner Losh
3508e3e3a7aSWarner Losh
lua_compare(lua_State * L,int index1,int index2,int op)3518e3e3a7aSWarner Losh LUA_API int lua_compare (lua_State *L, int index1, int index2, int op) {
3520495ed39SKyle Evans const TValue *o1;
3530495ed39SKyle Evans const TValue *o2;
3548e3e3a7aSWarner Losh int i = 0;
3558e3e3a7aSWarner Losh lua_lock(L); /* may call tag method */
3560495ed39SKyle Evans o1 = index2value(L, index1);
3570495ed39SKyle Evans o2 = index2value(L, index2);
3580495ed39SKyle Evans if (isvalid(L, o1) && isvalid(L, o2)) {
3598e3e3a7aSWarner Losh switch (op) {
3608e3e3a7aSWarner Losh case LUA_OPEQ: i = luaV_equalobj(L, o1, o2); break;
3618e3e3a7aSWarner Losh case LUA_OPLT: i = luaV_lessthan(L, o1, o2); break;
3628e3e3a7aSWarner Losh case LUA_OPLE: i = luaV_lessequal(L, o1, o2); break;
3638e3e3a7aSWarner Losh default: api_check(L, 0, "invalid option");
3648e3e3a7aSWarner Losh }
3658e3e3a7aSWarner Losh }
3668e3e3a7aSWarner Losh lua_unlock(L);
3678e3e3a7aSWarner Losh return i;
3688e3e3a7aSWarner Losh }
3698e3e3a7aSWarner Losh
3708e3e3a7aSWarner Losh
lua_stringtonumber(lua_State * L,const char * s)3718e3e3a7aSWarner Losh LUA_API size_t lua_stringtonumber (lua_State *L, const char *s) {
372*a9490b81SWarner Losh size_t sz = luaO_str2num(s, s2v(L->top.p));
3738e3e3a7aSWarner Losh if (sz != 0)
3748e3e3a7aSWarner Losh api_incr_top(L);
3758e3e3a7aSWarner Losh return sz;
3768e3e3a7aSWarner Losh }
3778e3e3a7aSWarner Losh
3788e3e3a7aSWarner Losh
lua_tonumberx(lua_State * L,int idx,int * pisnum)3798e3e3a7aSWarner Losh LUA_API lua_Number lua_tonumberx (lua_State *L, int idx, int *pisnum) {
3800495ed39SKyle Evans lua_Number n = 0;
3810495ed39SKyle Evans const TValue *o = index2value(L, idx);
3828e3e3a7aSWarner Losh int isnum = tonumber(o, &n);
3830495ed39SKyle Evans if (pisnum)
3840495ed39SKyle Evans *pisnum = isnum;
3858e3e3a7aSWarner Losh return n;
3868e3e3a7aSWarner Losh }
3878e3e3a7aSWarner Losh
3888e3e3a7aSWarner Losh
lua_tointegerx(lua_State * L,int idx,int * pisnum)3898e3e3a7aSWarner Losh LUA_API lua_Integer lua_tointegerx (lua_State *L, int idx, int *pisnum) {
3900495ed39SKyle Evans lua_Integer res = 0;
3910495ed39SKyle Evans const TValue *o = index2value(L, idx);
3928e3e3a7aSWarner Losh int isnum = tointeger(o, &res);
3930495ed39SKyle Evans if (pisnum)
3940495ed39SKyle Evans *pisnum = isnum;
3958e3e3a7aSWarner Losh return res;
3968e3e3a7aSWarner Losh }
3978e3e3a7aSWarner Losh
3988e3e3a7aSWarner Losh
lua_toboolean(lua_State * L,int idx)3998e3e3a7aSWarner Losh LUA_API int lua_toboolean (lua_State *L, int idx) {
4000495ed39SKyle Evans const TValue *o = index2value(L, idx);
4018e3e3a7aSWarner Losh return !l_isfalse(o);
4028e3e3a7aSWarner Losh }
4038e3e3a7aSWarner Losh
4048e3e3a7aSWarner Losh
lua_tolstring(lua_State * L,int idx,size_t * len)4058e3e3a7aSWarner Losh LUA_API const char *lua_tolstring (lua_State *L, int idx, size_t *len) {
4060495ed39SKyle Evans TValue *o;
4070495ed39SKyle Evans lua_lock(L);
4080495ed39SKyle Evans o = index2value(L, idx);
4098e3e3a7aSWarner Losh if (!ttisstring(o)) {
4108e3e3a7aSWarner Losh if (!cvt2str(o)) { /* not convertible? */
4118e3e3a7aSWarner Losh if (len != NULL) *len = 0;
4120495ed39SKyle Evans lua_unlock(L);
4138e3e3a7aSWarner Losh return NULL;
4148e3e3a7aSWarner Losh }
4158e3e3a7aSWarner Losh luaO_tostring(L, o);
4168e3e3a7aSWarner Losh luaC_checkGC(L);
4170495ed39SKyle Evans o = index2value(L, idx); /* previous call may reallocate the stack */
4188e3e3a7aSWarner Losh }
4198e3e3a7aSWarner Losh if (len != NULL)
4208e3e3a7aSWarner Losh *len = vslen(o);
4210495ed39SKyle Evans lua_unlock(L);
4228e3e3a7aSWarner Losh return svalue(o);
4238e3e3a7aSWarner Losh }
4248e3e3a7aSWarner Losh
4258e3e3a7aSWarner Losh
lua_rawlen(lua_State * L,int idx)4260495ed39SKyle Evans LUA_API lua_Unsigned lua_rawlen (lua_State *L, int idx) {
4270495ed39SKyle Evans const TValue *o = index2value(L, idx);
4280495ed39SKyle Evans switch (ttypetag(o)) {
4290495ed39SKyle Evans case LUA_VSHRSTR: return tsvalue(o)->shrlen;
4300495ed39SKyle Evans case LUA_VLNGSTR: return tsvalue(o)->u.lnglen;
4310495ed39SKyle Evans case LUA_VUSERDATA: return uvalue(o)->len;
4320495ed39SKyle Evans case LUA_VTABLE: return luaH_getn(hvalue(o));
4338e3e3a7aSWarner Losh default: return 0;
4348e3e3a7aSWarner Losh }
4358e3e3a7aSWarner Losh }
4368e3e3a7aSWarner Losh
4378e3e3a7aSWarner Losh
lua_tocfunction(lua_State * L,int idx)4388e3e3a7aSWarner Losh LUA_API lua_CFunction lua_tocfunction (lua_State *L, int idx) {
4390495ed39SKyle Evans const TValue *o = index2value(L, idx);
4408e3e3a7aSWarner Losh if (ttislcf(o)) return fvalue(o);
4418e3e3a7aSWarner Losh else if (ttisCclosure(o))
4428e3e3a7aSWarner Losh return clCvalue(o)->f;
4438e3e3a7aSWarner Losh else return NULL; /* not a C function */
4448e3e3a7aSWarner Losh }
4458e3e3a7aSWarner Losh
4468e3e3a7aSWarner Losh
touserdata(const TValue * o)4478c784bb8SWarner Losh l_sinline void *touserdata (const TValue *o) {
4480495ed39SKyle Evans switch (ttype(o)) {
4498e3e3a7aSWarner Losh case LUA_TUSERDATA: return getudatamem(uvalue(o));
4508e3e3a7aSWarner Losh case LUA_TLIGHTUSERDATA: return pvalue(o);
4518e3e3a7aSWarner Losh default: return NULL;
4528e3e3a7aSWarner Losh }
4538e3e3a7aSWarner Losh }
4548e3e3a7aSWarner Losh
4558e3e3a7aSWarner Losh
lua_touserdata(lua_State * L,int idx)4560495ed39SKyle Evans LUA_API void *lua_touserdata (lua_State *L, int idx) {
4570495ed39SKyle Evans const TValue *o = index2value(L, idx);
4580495ed39SKyle Evans return touserdata(o);
4590495ed39SKyle Evans }
4600495ed39SKyle Evans
4610495ed39SKyle Evans
lua_tothread(lua_State * L,int idx)4628e3e3a7aSWarner Losh LUA_API lua_State *lua_tothread (lua_State *L, int idx) {
4630495ed39SKyle Evans const TValue *o = index2value(L, idx);
4648e3e3a7aSWarner Losh return (!ttisthread(o)) ? NULL : thvalue(o);
4658e3e3a7aSWarner Losh }
4668e3e3a7aSWarner Losh
4678e3e3a7aSWarner Losh
4680495ed39SKyle Evans /*
4690495ed39SKyle Evans ** Returns a pointer to the internal representation of an object.
4700495ed39SKyle Evans ** Note that ANSI C does not allow the conversion of a pointer to
4710495ed39SKyle Evans ** function to a 'void*', so the conversion here goes through
4720495ed39SKyle Evans ** a 'size_t'. (As the returned pointer is only informative, this
4730495ed39SKyle Evans ** conversion should not be a problem.)
4740495ed39SKyle Evans */
lua_topointer(lua_State * L,int idx)4758e3e3a7aSWarner Losh LUA_API const void *lua_topointer (lua_State *L, int idx) {
4760495ed39SKyle Evans const TValue *o = index2value(L, idx);
4770495ed39SKyle Evans switch (ttypetag(o)) {
4780495ed39SKyle Evans case LUA_VLCF: return cast_voidp(cast_sizet(fvalue(o)));
4790495ed39SKyle Evans case LUA_VUSERDATA: case LUA_VLIGHTUSERDATA:
4800495ed39SKyle Evans return touserdata(o);
4810495ed39SKyle Evans default: {
4820495ed39SKyle Evans if (iscollectable(o))
4830495ed39SKyle Evans return gcvalue(o);
4840495ed39SKyle Evans else
4850495ed39SKyle Evans return NULL;
4860495ed39SKyle Evans }
4878e3e3a7aSWarner Losh }
4888e3e3a7aSWarner Losh }
4898e3e3a7aSWarner Losh
4908e3e3a7aSWarner Losh
4918e3e3a7aSWarner Losh
4928e3e3a7aSWarner Losh /*
4938e3e3a7aSWarner Losh ** push functions (C -> stack)
4948e3e3a7aSWarner Losh */
4958e3e3a7aSWarner Losh
4968e3e3a7aSWarner Losh
lua_pushnil(lua_State * L)4978e3e3a7aSWarner Losh LUA_API void lua_pushnil (lua_State *L) {
4988e3e3a7aSWarner Losh lua_lock(L);
499*a9490b81SWarner Losh setnilvalue(s2v(L->top.p));
5008e3e3a7aSWarner Losh api_incr_top(L);
5018e3e3a7aSWarner Losh lua_unlock(L);
5028e3e3a7aSWarner Losh }
5038e3e3a7aSWarner Losh
5048e3e3a7aSWarner Losh
lua_pushnumber(lua_State * L,lua_Number n)5058e3e3a7aSWarner Losh LUA_API void lua_pushnumber (lua_State *L, lua_Number n) {
5068e3e3a7aSWarner Losh lua_lock(L);
507*a9490b81SWarner Losh setfltvalue(s2v(L->top.p), n);
5088e3e3a7aSWarner Losh api_incr_top(L);
5098e3e3a7aSWarner Losh lua_unlock(L);
5108e3e3a7aSWarner Losh }
5118e3e3a7aSWarner Losh
5128e3e3a7aSWarner Losh
lua_pushinteger(lua_State * L,lua_Integer n)5138e3e3a7aSWarner Losh LUA_API void lua_pushinteger (lua_State *L, lua_Integer n) {
5148e3e3a7aSWarner Losh lua_lock(L);
515*a9490b81SWarner Losh setivalue(s2v(L->top.p), n);
5168e3e3a7aSWarner Losh api_incr_top(L);
5178e3e3a7aSWarner Losh lua_unlock(L);
5188e3e3a7aSWarner Losh }
5198e3e3a7aSWarner Losh
5208e3e3a7aSWarner Losh
5218e3e3a7aSWarner Losh /*
5228e3e3a7aSWarner Losh ** Pushes on the stack a string with given length. Avoid using 's' when
5238e3e3a7aSWarner Losh ** 'len' == 0 (as 's' can be NULL in that case), due to later use of
5248e3e3a7aSWarner Losh ** 'memcmp' and 'memcpy'.
5258e3e3a7aSWarner Losh */
lua_pushlstring(lua_State * L,const char * s,size_t len)5268e3e3a7aSWarner Losh LUA_API const char *lua_pushlstring (lua_State *L, const char *s, size_t len) {
5278e3e3a7aSWarner Losh TString *ts;
5288e3e3a7aSWarner Losh lua_lock(L);
5298e3e3a7aSWarner Losh ts = (len == 0) ? luaS_new(L, "") : luaS_newlstr(L, s, len);
530*a9490b81SWarner Losh setsvalue2s(L, L->top.p, ts);
5318e3e3a7aSWarner Losh api_incr_top(L);
5328e3e3a7aSWarner Losh luaC_checkGC(L);
5338e3e3a7aSWarner Losh lua_unlock(L);
5348e3e3a7aSWarner Losh return getstr(ts);
5358e3e3a7aSWarner Losh }
5368e3e3a7aSWarner Losh
5378e3e3a7aSWarner Losh
lua_pushstring(lua_State * L,const char * s)5388e3e3a7aSWarner Losh LUA_API const char *lua_pushstring (lua_State *L, const char *s) {
5398e3e3a7aSWarner Losh lua_lock(L);
5408e3e3a7aSWarner Losh if (s == NULL)
541*a9490b81SWarner Losh setnilvalue(s2v(L->top.p));
5428e3e3a7aSWarner Losh else {
5438e3e3a7aSWarner Losh TString *ts;
5448e3e3a7aSWarner Losh ts = luaS_new(L, s);
545*a9490b81SWarner Losh setsvalue2s(L, L->top.p, ts);
5468e3e3a7aSWarner Losh s = getstr(ts); /* internal copy's address */
5478e3e3a7aSWarner Losh }
5488e3e3a7aSWarner Losh api_incr_top(L);
5498e3e3a7aSWarner Losh luaC_checkGC(L);
5508e3e3a7aSWarner Losh lua_unlock(L);
5518e3e3a7aSWarner Losh return s;
5528e3e3a7aSWarner Losh }
5538e3e3a7aSWarner Losh
5548e3e3a7aSWarner Losh
lua_pushvfstring(lua_State * L,const char * fmt,va_list argp)5558e3e3a7aSWarner Losh LUA_API const char *lua_pushvfstring (lua_State *L, const char *fmt,
5568e3e3a7aSWarner Losh va_list argp) {
5578e3e3a7aSWarner Losh const char *ret;
5588e3e3a7aSWarner Losh lua_lock(L);
5598e3e3a7aSWarner Losh ret = luaO_pushvfstring(L, fmt, argp);
5608e3e3a7aSWarner Losh luaC_checkGC(L);
5618e3e3a7aSWarner Losh lua_unlock(L);
5628e3e3a7aSWarner Losh return ret;
5638e3e3a7aSWarner Losh }
5648e3e3a7aSWarner Losh
5658e3e3a7aSWarner Losh
lua_pushfstring(lua_State * L,const char * fmt,...)5668e3e3a7aSWarner Losh LUA_API const char *lua_pushfstring (lua_State *L, const char *fmt, ...) {
5678e3e3a7aSWarner Losh const char *ret;
5688e3e3a7aSWarner Losh va_list argp;
5698e3e3a7aSWarner Losh lua_lock(L);
5708e3e3a7aSWarner Losh va_start(argp, fmt);
5718e3e3a7aSWarner Losh ret = luaO_pushvfstring(L, fmt, argp);
5728e3e3a7aSWarner Losh va_end(argp);
5738e3e3a7aSWarner Losh luaC_checkGC(L);
5748e3e3a7aSWarner Losh lua_unlock(L);
5758e3e3a7aSWarner Losh return ret;
5768e3e3a7aSWarner Losh }
5778e3e3a7aSWarner Losh
5788e3e3a7aSWarner Losh
lua_pushcclosure(lua_State * L,lua_CFunction fn,int n)5798e3e3a7aSWarner Losh LUA_API void lua_pushcclosure (lua_State *L, lua_CFunction fn, int n) {
5808e3e3a7aSWarner Losh lua_lock(L);
5818e3e3a7aSWarner Losh if (n == 0) {
582*a9490b81SWarner Losh setfvalue(s2v(L->top.p), fn);
583e112e9d2SKyle Evans api_incr_top(L);
5848e3e3a7aSWarner Losh }
5858e3e3a7aSWarner Losh else {
5868e3e3a7aSWarner Losh CClosure *cl;
5878e3e3a7aSWarner Losh api_checknelems(L, n);
5888e3e3a7aSWarner Losh api_check(L, n <= MAXUPVAL, "upvalue index too large");
5898e3e3a7aSWarner Losh cl = luaF_newCclosure(L, n);
5908e3e3a7aSWarner Losh cl->f = fn;
591*a9490b81SWarner Losh L->top.p -= n;
5928e3e3a7aSWarner Losh while (n--) {
593*a9490b81SWarner Losh setobj2n(L, &cl->upvalue[n], s2v(L->top.p + n));
5948e3e3a7aSWarner Losh /* does not need barrier because closure is white */
5950495ed39SKyle Evans lua_assert(iswhite(cl));
5968e3e3a7aSWarner Losh }
597*a9490b81SWarner Losh setclCvalue(L, s2v(L->top.p), cl);
5988e3e3a7aSWarner Losh api_incr_top(L);
5998e3e3a7aSWarner Losh luaC_checkGC(L);
600e112e9d2SKyle Evans }
6018e3e3a7aSWarner Losh lua_unlock(L);
6028e3e3a7aSWarner Losh }
6038e3e3a7aSWarner Losh
6048e3e3a7aSWarner Losh
lua_pushboolean(lua_State * L,int b)6058e3e3a7aSWarner Losh LUA_API void lua_pushboolean (lua_State *L, int b) {
6068e3e3a7aSWarner Losh lua_lock(L);
6070495ed39SKyle Evans if (b)
608*a9490b81SWarner Losh setbtvalue(s2v(L->top.p));
6090495ed39SKyle Evans else
610*a9490b81SWarner Losh setbfvalue(s2v(L->top.p));
6118e3e3a7aSWarner Losh api_incr_top(L);
6128e3e3a7aSWarner Losh lua_unlock(L);
6138e3e3a7aSWarner Losh }
6148e3e3a7aSWarner Losh
6158e3e3a7aSWarner Losh
lua_pushlightuserdata(lua_State * L,void * p)6168e3e3a7aSWarner Losh LUA_API void lua_pushlightuserdata (lua_State *L, void *p) {
6178e3e3a7aSWarner Losh lua_lock(L);
618*a9490b81SWarner Losh setpvalue(s2v(L->top.p), p);
6198e3e3a7aSWarner Losh api_incr_top(L);
6208e3e3a7aSWarner Losh lua_unlock(L);
6218e3e3a7aSWarner Losh }
6228e3e3a7aSWarner Losh
6238e3e3a7aSWarner Losh
lua_pushthread(lua_State * L)6248e3e3a7aSWarner Losh LUA_API int lua_pushthread (lua_State *L) {
6258e3e3a7aSWarner Losh lua_lock(L);
626*a9490b81SWarner Losh setthvalue(L, s2v(L->top.p), L);
6278e3e3a7aSWarner Losh api_incr_top(L);
6288e3e3a7aSWarner Losh lua_unlock(L);
6298e3e3a7aSWarner Losh return (G(L)->mainthread == L);
6308e3e3a7aSWarner Losh }
6318e3e3a7aSWarner Losh
6328e3e3a7aSWarner Losh
6338e3e3a7aSWarner Losh
6348e3e3a7aSWarner Losh /*
6358e3e3a7aSWarner Losh ** get functions (Lua -> stack)
6368e3e3a7aSWarner Losh */
6378e3e3a7aSWarner Losh
6388e3e3a7aSWarner Losh
auxgetstr(lua_State * L,const TValue * t,const char * k)6398c784bb8SWarner Losh l_sinline int auxgetstr (lua_State *L, const TValue *t, const char *k) {
6408e3e3a7aSWarner Losh const TValue *slot;
6418e3e3a7aSWarner Losh TString *str = luaS_new(L, k);
6428e3e3a7aSWarner Losh if (luaV_fastget(L, t, str, slot, luaH_getstr)) {
643*a9490b81SWarner Losh setobj2s(L, L->top.p, slot);
6448e3e3a7aSWarner Losh api_incr_top(L);
6458e3e3a7aSWarner Losh }
6468e3e3a7aSWarner Losh else {
647*a9490b81SWarner Losh setsvalue2s(L, L->top.p, str);
6488e3e3a7aSWarner Losh api_incr_top(L);
649*a9490b81SWarner Losh luaV_finishget(L, t, s2v(L->top.p - 1), L->top.p - 1, slot);
6508e3e3a7aSWarner Losh }
6518e3e3a7aSWarner Losh lua_unlock(L);
652*a9490b81SWarner Losh return ttype(s2v(L->top.p - 1));
6538e3e3a7aSWarner Losh }
6548e3e3a7aSWarner Losh
6558e3e3a7aSWarner Losh
6568c784bb8SWarner Losh /*
6578c784bb8SWarner Losh ** Get the global table in the registry. Since all predefined
6588c784bb8SWarner Losh ** indices in the registry were inserted right when the registry
6598c784bb8SWarner Losh ** was created and never removed, they must always be in the array
6608c784bb8SWarner Losh ** part of the registry.
6618c784bb8SWarner Losh */
6628c784bb8SWarner Losh #define getGtable(L) \
6638c784bb8SWarner Losh (&hvalue(&G(L)->l_registry)->array[LUA_RIDX_GLOBALS - 1])
6648c784bb8SWarner Losh
6658c784bb8SWarner Losh
lua_getglobal(lua_State * L,const char * name)6668e3e3a7aSWarner Losh LUA_API int lua_getglobal (lua_State *L, const char *name) {
6678c784bb8SWarner Losh const TValue *G;
6688e3e3a7aSWarner Losh lua_lock(L);
6698c784bb8SWarner Losh G = getGtable(L);
6708c784bb8SWarner Losh return auxgetstr(L, G, name);
6718e3e3a7aSWarner Losh }
6728e3e3a7aSWarner Losh
6738e3e3a7aSWarner Losh
lua_gettable(lua_State * L,int idx)6748e3e3a7aSWarner Losh LUA_API int lua_gettable (lua_State *L, int idx) {
6750495ed39SKyle Evans const TValue *slot;
6760495ed39SKyle Evans TValue *t;
6778e3e3a7aSWarner Losh lua_lock(L);
6780495ed39SKyle Evans t = index2value(L, idx);
679*a9490b81SWarner Losh if (luaV_fastget(L, t, s2v(L->top.p - 1), slot, luaH_get)) {
680*a9490b81SWarner Losh setobj2s(L, L->top.p - 1, slot);
6810495ed39SKyle Evans }
6820495ed39SKyle Evans else
683*a9490b81SWarner Losh luaV_finishget(L, t, s2v(L->top.p - 1), L->top.p - 1, slot);
6848e3e3a7aSWarner Losh lua_unlock(L);
685*a9490b81SWarner Losh return ttype(s2v(L->top.p - 1));
6868e3e3a7aSWarner Losh }
6878e3e3a7aSWarner Losh
6888e3e3a7aSWarner Losh
lua_getfield(lua_State * L,int idx,const char * k)6898e3e3a7aSWarner Losh LUA_API int lua_getfield (lua_State *L, int idx, const char *k) {
6908e3e3a7aSWarner Losh lua_lock(L);
6910495ed39SKyle Evans return auxgetstr(L, index2value(L, idx), k);
6928e3e3a7aSWarner Losh }
6938e3e3a7aSWarner Losh
6948e3e3a7aSWarner Losh
lua_geti(lua_State * L,int idx,lua_Integer n)6958e3e3a7aSWarner Losh LUA_API int lua_geti (lua_State *L, int idx, lua_Integer n) {
6960495ed39SKyle Evans TValue *t;
6978e3e3a7aSWarner Losh const TValue *slot;
6988e3e3a7aSWarner Losh lua_lock(L);
6990495ed39SKyle Evans t = index2value(L, idx);
7000495ed39SKyle Evans if (luaV_fastgeti(L, t, n, slot)) {
701*a9490b81SWarner Losh setobj2s(L, L->top.p, slot);
7028e3e3a7aSWarner Losh }
7038e3e3a7aSWarner Losh else {
7040495ed39SKyle Evans TValue aux;
7050495ed39SKyle Evans setivalue(&aux, n);
706*a9490b81SWarner Losh luaV_finishget(L, t, &aux, L->top.p, slot);
7078e3e3a7aSWarner Losh }
7080495ed39SKyle Evans api_incr_top(L);
7098e3e3a7aSWarner Losh lua_unlock(L);
710*a9490b81SWarner Losh return ttype(s2v(L->top.p - 1));
7110495ed39SKyle Evans }
7120495ed39SKyle Evans
7130495ed39SKyle Evans
finishrawget(lua_State * L,const TValue * val)7148c784bb8SWarner Losh l_sinline int finishrawget (lua_State *L, const TValue *val) {
7150495ed39SKyle Evans if (isempty(val)) /* avoid copying empty items to the stack */
716*a9490b81SWarner Losh setnilvalue(s2v(L->top.p));
7170495ed39SKyle Evans else
718*a9490b81SWarner Losh setobj2s(L, L->top.p, val);
7190495ed39SKyle Evans api_incr_top(L);
7200495ed39SKyle Evans lua_unlock(L);
721*a9490b81SWarner Losh return ttype(s2v(L->top.p - 1));
7220495ed39SKyle Evans }
7230495ed39SKyle Evans
7240495ed39SKyle Evans
gettable(lua_State * L,int idx)7250495ed39SKyle Evans static Table *gettable (lua_State *L, int idx) {
7260495ed39SKyle Evans TValue *t = index2value(L, idx);
7270495ed39SKyle Evans api_check(L, ttistable(t), "table expected");
7280495ed39SKyle Evans return hvalue(t);
7298e3e3a7aSWarner Losh }
7308e3e3a7aSWarner Losh
7318e3e3a7aSWarner Losh
lua_rawget(lua_State * L,int idx)7328e3e3a7aSWarner Losh LUA_API int lua_rawget (lua_State *L, int idx) {
7330495ed39SKyle Evans Table *t;
7340495ed39SKyle Evans const TValue *val;
7358e3e3a7aSWarner Losh lua_lock(L);
7360495ed39SKyle Evans api_checknelems(L, 1);
7370495ed39SKyle Evans t = gettable(L, idx);
738*a9490b81SWarner Losh val = luaH_get(t, s2v(L->top.p - 1));
739*a9490b81SWarner Losh L->top.p--; /* remove key */
7400495ed39SKyle Evans return finishrawget(L, val);
7418e3e3a7aSWarner Losh }
7428e3e3a7aSWarner Losh
7438e3e3a7aSWarner Losh
lua_rawgeti(lua_State * L,int idx,lua_Integer n)7448e3e3a7aSWarner Losh LUA_API int lua_rawgeti (lua_State *L, int idx, lua_Integer n) {
7450495ed39SKyle Evans Table *t;
7468e3e3a7aSWarner Losh lua_lock(L);
7470495ed39SKyle Evans t = gettable(L, idx);
7480495ed39SKyle Evans return finishrawget(L, luaH_getint(t, n));
7498e3e3a7aSWarner Losh }
7508e3e3a7aSWarner Losh
7518e3e3a7aSWarner Losh
lua_rawgetp(lua_State * L,int idx,const void * p)7528e3e3a7aSWarner Losh LUA_API int lua_rawgetp (lua_State *L, int idx, const void *p) {
7530495ed39SKyle Evans Table *t;
7548e3e3a7aSWarner Losh TValue k;
7558e3e3a7aSWarner Losh lua_lock(L);
7560495ed39SKyle Evans t = gettable(L, idx);
7570495ed39SKyle Evans setpvalue(&k, cast_voidp(p));
7580495ed39SKyle Evans return finishrawget(L, luaH_get(t, &k));
7598e3e3a7aSWarner Losh }
7608e3e3a7aSWarner Losh
7618e3e3a7aSWarner Losh
lua_createtable(lua_State * L,int narray,int nrec)7628e3e3a7aSWarner Losh LUA_API void lua_createtable (lua_State *L, int narray, int nrec) {
7638e3e3a7aSWarner Losh Table *t;
7648e3e3a7aSWarner Losh lua_lock(L);
7658e3e3a7aSWarner Losh t = luaH_new(L);
766*a9490b81SWarner Losh sethvalue2s(L, L->top.p, t);
7678e3e3a7aSWarner Losh api_incr_top(L);
7688e3e3a7aSWarner Losh if (narray > 0 || nrec > 0)
7698e3e3a7aSWarner Losh luaH_resize(L, t, narray, nrec);
7708e3e3a7aSWarner Losh luaC_checkGC(L);
7718e3e3a7aSWarner Losh lua_unlock(L);
7728e3e3a7aSWarner Losh }
7738e3e3a7aSWarner Losh
7748e3e3a7aSWarner Losh
lua_getmetatable(lua_State * L,int objindex)7758e3e3a7aSWarner Losh LUA_API int lua_getmetatable (lua_State *L, int objindex) {
7768e3e3a7aSWarner Losh const TValue *obj;
7778e3e3a7aSWarner Losh Table *mt;
7788e3e3a7aSWarner Losh int res = 0;
7798e3e3a7aSWarner Losh lua_lock(L);
7800495ed39SKyle Evans obj = index2value(L, objindex);
7810495ed39SKyle Evans switch (ttype(obj)) {
7828e3e3a7aSWarner Losh case LUA_TTABLE:
7838e3e3a7aSWarner Losh mt = hvalue(obj)->metatable;
7848e3e3a7aSWarner Losh break;
7858e3e3a7aSWarner Losh case LUA_TUSERDATA:
7868e3e3a7aSWarner Losh mt = uvalue(obj)->metatable;
7878e3e3a7aSWarner Losh break;
7888e3e3a7aSWarner Losh default:
7890495ed39SKyle Evans mt = G(L)->mt[ttype(obj)];
7908e3e3a7aSWarner Losh break;
7918e3e3a7aSWarner Losh }
7928e3e3a7aSWarner Losh if (mt != NULL) {
793*a9490b81SWarner Losh sethvalue2s(L, L->top.p, mt);
7948e3e3a7aSWarner Losh api_incr_top(L);
7958e3e3a7aSWarner Losh res = 1;
7968e3e3a7aSWarner Losh }
7978e3e3a7aSWarner Losh lua_unlock(L);
7988e3e3a7aSWarner Losh return res;
7998e3e3a7aSWarner Losh }
8008e3e3a7aSWarner Losh
8018e3e3a7aSWarner Losh
lua_getiuservalue(lua_State * L,int idx,int n)8020495ed39SKyle Evans LUA_API int lua_getiuservalue (lua_State *L, int idx, int n) {
8030495ed39SKyle Evans TValue *o;
8040495ed39SKyle Evans int t;
8058e3e3a7aSWarner Losh lua_lock(L);
8060495ed39SKyle Evans o = index2value(L, idx);
8078e3e3a7aSWarner Losh api_check(L, ttisfulluserdata(o), "full userdata expected");
8080495ed39SKyle Evans if (n <= 0 || n > uvalue(o)->nuvalue) {
809*a9490b81SWarner Losh setnilvalue(s2v(L->top.p));
8100495ed39SKyle Evans t = LUA_TNONE;
8110495ed39SKyle Evans }
8120495ed39SKyle Evans else {
813*a9490b81SWarner Losh setobj2s(L, L->top.p, &uvalue(o)->uv[n - 1].uv);
814*a9490b81SWarner Losh t = ttype(s2v(L->top.p));
8150495ed39SKyle Evans }
8168e3e3a7aSWarner Losh api_incr_top(L);
8178e3e3a7aSWarner Losh lua_unlock(L);
8180495ed39SKyle Evans return t;
8198e3e3a7aSWarner Losh }
8208e3e3a7aSWarner Losh
8218e3e3a7aSWarner Losh
8228e3e3a7aSWarner Losh /*
8238e3e3a7aSWarner Losh ** set functions (stack -> Lua)
8248e3e3a7aSWarner Losh */
8258e3e3a7aSWarner Losh
8268e3e3a7aSWarner Losh /*
8278e3e3a7aSWarner Losh ** t[k] = value at the top of the stack (where 'k' is a string)
8288e3e3a7aSWarner Losh */
auxsetstr(lua_State * L,const TValue * t,const char * k)8298e3e3a7aSWarner Losh static void auxsetstr (lua_State *L, const TValue *t, const char *k) {
8308e3e3a7aSWarner Losh const TValue *slot;
8318e3e3a7aSWarner Losh TString *str = luaS_new(L, k);
8328e3e3a7aSWarner Losh api_checknelems(L, 1);
8330495ed39SKyle Evans if (luaV_fastget(L, t, str, slot, luaH_getstr)) {
834*a9490b81SWarner Losh luaV_finishfastset(L, t, slot, s2v(L->top.p - 1));
835*a9490b81SWarner Losh L->top.p--; /* pop value */
8360495ed39SKyle Evans }
8378e3e3a7aSWarner Losh else {
838*a9490b81SWarner Losh setsvalue2s(L, L->top.p, str); /* push 'str' (to make it a TValue) */
8398e3e3a7aSWarner Losh api_incr_top(L);
840*a9490b81SWarner Losh luaV_finishset(L, t, s2v(L->top.p - 1), s2v(L->top.p - 2), slot);
841*a9490b81SWarner Losh L->top.p -= 2; /* pop value and key */
8428e3e3a7aSWarner Losh }
8438e3e3a7aSWarner Losh lua_unlock(L); /* lock done by caller */
8448e3e3a7aSWarner Losh }
8458e3e3a7aSWarner Losh
8468e3e3a7aSWarner Losh
lua_setglobal(lua_State * L,const char * name)8478e3e3a7aSWarner Losh LUA_API void lua_setglobal (lua_State *L, const char *name) {
8488c784bb8SWarner Losh const TValue *G;
8498e3e3a7aSWarner Losh lua_lock(L); /* unlock done in 'auxsetstr' */
8508c784bb8SWarner Losh G = getGtable(L);
8518c784bb8SWarner Losh auxsetstr(L, G, name);
8528e3e3a7aSWarner Losh }
8538e3e3a7aSWarner Losh
8548e3e3a7aSWarner Losh
lua_settable(lua_State * L,int idx)8558e3e3a7aSWarner Losh LUA_API void lua_settable (lua_State *L, int idx) {
8560495ed39SKyle Evans TValue *t;
8570495ed39SKyle Evans const TValue *slot;
8588e3e3a7aSWarner Losh lua_lock(L);
8598e3e3a7aSWarner Losh api_checknelems(L, 2);
8600495ed39SKyle Evans t = index2value(L, idx);
861*a9490b81SWarner Losh if (luaV_fastget(L, t, s2v(L->top.p - 2), slot, luaH_get)) {
862*a9490b81SWarner Losh luaV_finishfastset(L, t, slot, s2v(L->top.p - 1));
8630495ed39SKyle Evans }
8640495ed39SKyle Evans else
865*a9490b81SWarner Losh luaV_finishset(L, t, s2v(L->top.p - 2), s2v(L->top.p - 1), slot);
866*a9490b81SWarner Losh L->top.p -= 2; /* pop index and value */
8678e3e3a7aSWarner Losh lua_unlock(L);
8688e3e3a7aSWarner Losh }
8698e3e3a7aSWarner Losh
8708e3e3a7aSWarner Losh
lua_setfield(lua_State * L,int idx,const char * k)8718e3e3a7aSWarner Losh LUA_API void lua_setfield (lua_State *L, int idx, const char *k) {
8728e3e3a7aSWarner Losh lua_lock(L); /* unlock done in 'auxsetstr' */
8730495ed39SKyle Evans auxsetstr(L, index2value(L, idx), k);
8748e3e3a7aSWarner Losh }
8758e3e3a7aSWarner Losh
8768e3e3a7aSWarner Losh
lua_seti(lua_State * L,int idx,lua_Integer n)8778e3e3a7aSWarner Losh LUA_API void lua_seti (lua_State *L, int idx, lua_Integer n) {
8780495ed39SKyle Evans TValue *t;
8798e3e3a7aSWarner Losh const TValue *slot;
8808e3e3a7aSWarner Losh lua_lock(L);
8818e3e3a7aSWarner Losh api_checknelems(L, 1);
8820495ed39SKyle Evans t = index2value(L, idx);
8830495ed39SKyle Evans if (luaV_fastgeti(L, t, n, slot)) {
884*a9490b81SWarner Losh luaV_finishfastset(L, t, slot, s2v(L->top.p - 1));
8858e3e3a7aSWarner Losh }
8860495ed39SKyle Evans else {
8870495ed39SKyle Evans TValue aux;
8880495ed39SKyle Evans setivalue(&aux, n);
889*a9490b81SWarner Losh luaV_finishset(L, t, &aux, s2v(L->top.p - 1), slot);
8900495ed39SKyle Evans }
891*a9490b81SWarner Losh L->top.p--; /* pop value */
8920495ed39SKyle Evans lua_unlock(L);
8930495ed39SKyle Evans }
8940495ed39SKyle Evans
8950495ed39SKyle Evans
aux_rawset(lua_State * L,int idx,TValue * key,int n)8960495ed39SKyle Evans static void aux_rawset (lua_State *L, int idx, TValue *key, int n) {
8970495ed39SKyle Evans Table *t;
8980495ed39SKyle Evans lua_lock(L);
8990495ed39SKyle Evans api_checknelems(L, n);
9000495ed39SKyle Evans t = gettable(L, idx);
901*a9490b81SWarner Losh luaH_set(L, t, key, s2v(L->top.p - 1));
9020495ed39SKyle Evans invalidateTMcache(t);
903*a9490b81SWarner Losh luaC_barrierback(L, obj2gco(t), s2v(L->top.p - 1));
904*a9490b81SWarner Losh L->top.p -= n;
9058e3e3a7aSWarner Losh lua_unlock(L);
9068e3e3a7aSWarner Losh }
9078e3e3a7aSWarner Losh
9088e3e3a7aSWarner Losh
lua_rawset(lua_State * L,int idx)9098e3e3a7aSWarner Losh LUA_API void lua_rawset (lua_State *L, int idx) {
910*a9490b81SWarner Losh aux_rawset(L, idx, s2v(L->top.p - 2), 2);
9118e3e3a7aSWarner Losh }
9128e3e3a7aSWarner Losh
9138e3e3a7aSWarner Losh
lua_rawsetp(lua_State * L,int idx,const void * p)9148e3e3a7aSWarner Losh LUA_API void lua_rawsetp (lua_State *L, int idx, const void *p) {
9150495ed39SKyle Evans TValue k;
9160495ed39SKyle Evans setpvalue(&k, cast_voidp(p));
9170495ed39SKyle Evans aux_rawset(L, idx, &k, 1);
9180495ed39SKyle Evans }
9190495ed39SKyle Evans
9200495ed39SKyle Evans
lua_rawseti(lua_State * L,int idx,lua_Integer n)9210495ed39SKyle Evans LUA_API void lua_rawseti (lua_State *L, int idx, lua_Integer n) {
9220495ed39SKyle Evans Table *t;
9238e3e3a7aSWarner Losh lua_lock(L);
9248e3e3a7aSWarner Losh api_checknelems(L, 1);
9250495ed39SKyle Evans t = gettable(L, idx);
926*a9490b81SWarner Losh luaH_setint(L, t, n, s2v(L->top.p - 1));
927*a9490b81SWarner Losh luaC_barrierback(L, obj2gco(t), s2v(L->top.p - 1));
928*a9490b81SWarner Losh L->top.p--;
9298e3e3a7aSWarner Losh lua_unlock(L);
9308e3e3a7aSWarner Losh }
9318e3e3a7aSWarner Losh
9328e3e3a7aSWarner Losh
lua_setmetatable(lua_State * L,int objindex)9338e3e3a7aSWarner Losh LUA_API int lua_setmetatable (lua_State *L, int objindex) {
9348e3e3a7aSWarner Losh TValue *obj;
9358e3e3a7aSWarner Losh Table *mt;
9368e3e3a7aSWarner Losh lua_lock(L);
9378e3e3a7aSWarner Losh api_checknelems(L, 1);
9380495ed39SKyle Evans obj = index2value(L, objindex);
939*a9490b81SWarner Losh if (ttisnil(s2v(L->top.p - 1)))
9408e3e3a7aSWarner Losh mt = NULL;
9418e3e3a7aSWarner Losh else {
942*a9490b81SWarner Losh api_check(L, ttistable(s2v(L->top.p - 1)), "table expected");
943*a9490b81SWarner Losh mt = hvalue(s2v(L->top.p - 1));
9448e3e3a7aSWarner Losh }
9450495ed39SKyle Evans switch (ttype(obj)) {
9468e3e3a7aSWarner Losh case LUA_TTABLE: {
9478e3e3a7aSWarner Losh hvalue(obj)->metatable = mt;
9488e3e3a7aSWarner Losh if (mt) {
9498e3e3a7aSWarner Losh luaC_objbarrier(L, gcvalue(obj), mt);
9508e3e3a7aSWarner Losh luaC_checkfinalizer(L, gcvalue(obj), mt);
9518e3e3a7aSWarner Losh }
9528e3e3a7aSWarner Losh break;
9538e3e3a7aSWarner Losh }
9548e3e3a7aSWarner Losh case LUA_TUSERDATA: {
9558e3e3a7aSWarner Losh uvalue(obj)->metatable = mt;
9568e3e3a7aSWarner Losh if (mt) {
9578e3e3a7aSWarner Losh luaC_objbarrier(L, uvalue(obj), mt);
9588e3e3a7aSWarner Losh luaC_checkfinalizer(L, gcvalue(obj), mt);
9598e3e3a7aSWarner Losh }
9608e3e3a7aSWarner Losh break;
9618e3e3a7aSWarner Losh }
9628e3e3a7aSWarner Losh default: {
9630495ed39SKyle Evans G(L)->mt[ttype(obj)] = mt;
9648e3e3a7aSWarner Losh break;
9658e3e3a7aSWarner Losh }
9668e3e3a7aSWarner Losh }
967*a9490b81SWarner Losh L->top.p--;
9688e3e3a7aSWarner Losh lua_unlock(L);
9698e3e3a7aSWarner Losh return 1;
9708e3e3a7aSWarner Losh }
9718e3e3a7aSWarner Losh
9728e3e3a7aSWarner Losh
lua_setiuservalue(lua_State * L,int idx,int n)9730495ed39SKyle Evans LUA_API int lua_setiuservalue (lua_State *L, int idx, int n) {
9740495ed39SKyle Evans TValue *o;
9750495ed39SKyle Evans int res;
9768e3e3a7aSWarner Losh lua_lock(L);
9778e3e3a7aSWarner Losh api_checknelems(L, 1);
9780495ed39SKyle Evans o = index2value(L, idx);
9798e3e3a7aSWarner Losh api_check(L, ttisfulluserdata(o), "full userdata expected");
9800495ed39SKyle Evans if (!(cast_uint(n) - 1u < cast_uint(uvalue(o)->nuvalue)))
9810495ed39SKyle Evans res = 0; /* 'n' not in [1, uvalue(o)->nuvalue] */
9820495ed39SKyle Evans else {
983*a9490b81SWarner Losh setobj(L, &uvalue(o)->uv[n - 1].uv, s2v(L->top.p - 1));
984*a9490b81SWarner Losh luaC_barrierback(L, gcvalue(o), s2v(L->top.p - 1));
9850495ed39SKyle Evans res = 1;
9860495ed39SKyle Evans }
987*a9490b81SWarner Losh L->top.p--;
9888e3e3a7aSWarner Losh lua_unlock(L);
9890495ed39SKyle Evans return res;
9908e3e3a7aSWarner Losh }
9918e3e3a7aSWarner Losh
9928e3e3a7aSWarner Losh
9938e3e3a7aSWarner Losh /*
9948e3e3a7aSWarner Losh ** 'load' and 'call' functions (run Lua code)
9958e3e3a7aSWarner Losh */
9968e3e3a7aSWarner Losh
9978e3e3a7aSWarner Losh
9988e3e3a7aSWarner Losh #define checkresults(L,na,nr) \
999*a9490b81SWarner Losh api_check(L, (nr) == LUA_MULTRET \
1000*a9490b81SWarner Losh || (L->ci->top.p - L->top.p >= (nr) - (na)), \
10018e3e3a7aSWarner Losh "results from function overflow current stack size")
10028e3e3a7aSWarner Losh
10038e3e3a7aSWarner Losh
lua_callk(lua_State * L,int nargs,int nresults,lua_KContext ctx,lua_KFunction k)10048e3e3a7aSWarner Losh LUA_API void lua_callk (lua_State *L, int nargs, int nresults,
10058e3e3a7aSWarner Losh lua_KContext ctx, lua_KFunction k) {
10068e3e3a7aSWarner Losh StkId func;
10078e3e3a7aSWarner Losh lua_lock(L);
10088e3e3a7aSWarner Losh api_check(L, k == NULL || !isLua(L->ci),
10098e3e3a7aSWarner Losh "cannot use continuations inside hooks");
10108e3e3a7aSWarner Losh api_checknelems(L, nargs+1);
10118e3e3a7aSWarner Losh api_check(L, L->status == LUA_OK, "cannot do calls on non-normal thread");
10128e3e3a7aSWarner Losh checkresults(L, nargs, nresults);
1013*a9490b81SWarner Losh func = L->top.p - (nargs+1);
10140495ed39SKyle Evans if (k != NULL && yieldable(L)) { /* need to prepare continuation? */
10158e3e3a7aSWarner Losh L->ci->u.c.k = k; /* save continuation */
10168e3e3a7aSWarner Losh L->ci->u.c.ctx = ctx; /* save context */
10178e3e3a7aSWarner Losh luaD_call(L, func, nresults); /* do the call */
10188e3e3a7aSWarner Losh }
10198e3e3a7aSWarner Losh else /* no continuation or no yieldable */
10208e3e3a7aSWarner Losh luaD_callnoyield(L, func, nresults); /* just do the call */
10218e3e3a7aSWarner Losh adjustresults(L, nresults);
10228e3e3a7aSWarner Losh lua_unlock(L);
10238e3e3a7aSWarner Losh }
10248e3e3a7aSWarner Losh
10258e3e3a7aSWarner Losh
10268e3e3a7aSWarner Losh
10278e3e3a7aSWarner Losh /*
10288e3e3a7aSWarner Losh ** Execute a protected call.
10298e3e3a7aSWarner Losh */
10308e3e3a7aSWarner Losh struct CallS { /* data to 'f_call' */
10318e3e3a7aSWarner Losh StkId func;
10328e3e3a7aSWarner Losh int nresults;
10338e3e3a7aSWarner Losh };
10348e3e3a7aSWarner Losh
10358e3e3a7aSWarner Losh
f_call(lua_State * L,void * ud)10368e3e3a7aSWarner Losh static void f_call (lua_State *L, void *ud) {
10378e3e3a7aSWarner Losh struct CallS *c = cast(struct CallS *, ud);
10388e3e3a7aSWarner Losh luaD_callnoyield(L, c->func, c->nresults);
10398e3e3a7aSWarner Losh }
10408e3e3a7aSWarner Losh
10418e3e3a7aSWarner Losh
10428e3e3a7aSWarner Losh
lua_pcallk(lua_State * L,int nargs,int nresults,int errfunc,lua_KContext ctx,lua_KFunction k)10438e3e3a7aSWarner Losh LUA_API int lua_pcallk (lua_State *L, int nargs, int nresults, int errfunc,
10448e3e3a7aSWarner Losh lua_KContext ctx, lua_KFunction k) {
10458e3e3a7aSWarner Losh struct CallS c;
10468e3e3a7aSWarner Losh int status;
10478e3e3a7aSWarner Losh ptrdiff_t func;
10488e3e3a7aSWarner Losh lua_lock(L);
10498e3e3a7aSWarner Losh api_check(L, k == NULL || !isLua(L->ci),
10508e3e3a7aSWarner Losh "cannot use continuations inside hooks");
10518e3e3a7aSWarner Losh api_checknelems(L, nargs+1);
10528e3e3a7aSWarner Losh api_check(L, L->status == LUA_OK, "cannot do calls on non-normal thread");
10538e3e3a7aSWarner Losh checkresults(L, nargs, nresults);
10548e3e3a7aSWarner Losh if (errfunc == 0)
10558e3e3a7aSWarner Losh func = 0;
10568e3e3a7aSWarner Losh else {
10570495ed39SKyle Evans StkId o = index2stack(L, errfunc);
10580495ed39SKyle Evans api_check(L, ttisfunction(s2v(o)), "error handler must be a function");
10598e3e3a7aSWarner Losh func = savestack(L, o);
10608e3e3a7aSWarner Losh }
1061*a9490b81SWarner Losh c.func = L->top.p - (nargs+1); /* function to be called */
10620495ed39SKyle Evans if (k == NULL || !yieldable(L)) { /* no continuation or no yieldable? */
10638e3e3a7aSWarner Losh c.nresults = nresults; /* do a 'conventional' protected call */
10648e3e3a7aSWarner Losh status = luaD_pcall(L, f_call, &c, savestack(L, c.func), func);
10658e3e3a7aSWarner Losh }
10668e3e3a7aSWarner Losh else { /* prepare continuation (call is already protected by 'resume') */
10678e3e3a7aSWarner Losh CallInfo *ci = L->ci;
10688e3e3a7aSWarner Losh ci->u.c.k = k; /* save continuation */
10698e3e3a7aSWarner Losh ci->u.c.ctx = ctx; /* save context */
10708e3e3a7aSWarner Losh /* save information for error recovery */
10710495ed39SKyle Evans ci->u2.funcidx = cast_int(savestack(L, c.func));
10728e3e3a7aSWarner Losh ci->u.c.old_errfunc = L->errfunc;
10738e3e3a7aSWarner Losh L->errfunc = func;
10748e3e3a7aSWarner Losh setoah(ci->callstatus, L->allowhook); /* save value of 'allowhook' */
10758e3e3a7aSWarner Losh ci->callstatus |= CIST_YPCALL; /* function can do error recovery */
10768e3e3a7aSWarner Losh luaD_call(L, c.func, nresults); /* do the call */
10778e3e3a7aSWarner Losh ci->callstatus &= ~CIST_YPCALL;
10788e3e3a7aSWarner Losh L->errfunc = ci->u.c.old_errfunc;
10798e3e3a7aSWarner Losh status = LUA_OK; /* if it is here, there were no errors */
10808e3e3a7aSWarner Losh }
10818e3e3a7aSWarner Losh adjustresults(L, nresults);
10828e3e3a7aSWarner Losh lua_unlock(L);
10838e3e3a7aSWarner Losh return status;
10848e3e3a7aSWarner Losh }
10858e3e3a7aSWarner Losh
10868e3e3a7aSWarner Losh
lua_load(lua_State * L,lua_Reader reader,void * data,const char * chunkname,const char * mode)10878e3e3a7aSWarner Losh LUA_API int lua_load (lua_State *L, lua_Reader reader, void *data,
10888e3e3a7aSWarner Losh const char *chunkname, const char *mode) {
10898e3e3a7aSWarner Losh ZIO z;
10908e3e3a7aSWarner Losh int status;
10918e3e3a7aSWarner Losh lua_lock(L);
10928e3e3a7aSWarner Losh if (!chunkname) chunkname = "?";
10938e3e3a7aSWarner Losh luaZ_init(L, &z, reader, data);
10948e3e3a7aSWarner Losh status = luaD_protectedparser(L, &z, chunkname, mode);
10958e3e3a7aSWarner Losh if (status == LUA_OK) { /* no errors? */
1096*a9490b81SWarner Losh LClosure *f = clLvalue(s2v(L->top.p - 1)); /* get new function */
10978e3e3a7aSWarner Losh if (f->nupvalues >= 1) { /* does it have an upvalue? */
10988e3e3a7aSWarner Losh /* get global table from registry */
10998c784bb8SWarner Losh const TValue *gt = getGtable(L);
11008e3e3a7aSWarner Losh /* set global table as 1st upvalue of 'f' (may be LUA_ENV) */
1101*a9490b81SWarner Losh setobj(L, f->upvals[0]->v.p, gt);
11020495ed39SKyle Evans luaC_barrier(L, f->upvals[0], gt);
11038e3e3a7aSWarner Losh }
11048e3e3a7aSWarner Losh }
11058e3e3a7aSWarner Losh lua_unlock(L);
11068e3e3a7aSWarner Losh return status;
11078e3e3a7aSWarner Losh }
11088e3e3a7aSWarner Losh
11098e3e3a7aSWarner Losh
lua_dump(lua_State * L,lua_Writer writer,void * data,int strip)11108e3e3a7aSWarner Losh LUA_API int lua_dump (lua_State *L, lua_Writer writer, void *data, int strip) {
11118e3e3a7aSWarner Losh int status;
11128e3e3a7aSWarner Losh TValue *o;
11138e3e3a7aSWarner Losh lua_lock(L);
11148e3e3a7aSWarner Losh api_checknelems(L, 1);
1115*a9490b81SWarner Losh o = s2v(L->top.p - 1);
11168e3e3a7aSWarner Losh if (isLfunction(o))
11178e3e3a7aSWarner Losh status = luaU_dump(L, getproto(o), writer, data, strip);
11188e3e3a7aSWarner Losh else
11198e3e3a7aSWarner Losh status = 1;
11208e3e3a7aSWarner Losh lua_unlock(L);
11218e3e3a7aSWarner Losh return status;
11228e3e3a7aSWarner Losh }
11238e3e3a7aSWarner Losh
11248e3e3a7aSWarner Losh
lua_status(lua_State * L)11258e3e3a7aSWarner Losh LUA_API int lua_status (lua_State *L) {
11268e3e3a7aSWarner Losh return L->status;
11278e3e3a7aSWarner Losh }
11288e3e3a7aSWarner Losh
11298e3e3a7aSWarner Losh
11308e3e3a7aSWarner Losh /*
11318e3e3a7aSWarner Losh ** Garbage-collection function
11328e3e3a7aSWarner Losh */
lua_gc(lua_State * L,int what,...)11330495ed39SKyle Evans LUA_API int lua_gc (lua_State *L, int what, ...) {
11340495ed39SKyle Evans va_list argp;
11358e3e3a7aSWarner Losh int res = 0;
11368c784bb8SWarner Losh global_State *g = G(L);
11378c784bb8SWarner Losh if (g->gcstp & GCSTPGC) /* internal stop? */
11388c784bb8SWarner Losh return -1; /* all options are invalid when stopped */
11398e3e3a7aSWarner Losh lua_lock(L);
11400495ed39SKyle Evans va_start(argp, what);
11418e3e3a7aSWarner Losh switch (what) {
11428e3e3a7aSWarner Losh case LUA_GCSTOP: {
11438c784bb8SWarner Losh g->gcstp = GCSTPUSR; /* stopped by the user */
11448e3e3a7aSWarner Losh break;
11458e3e3a7aSWarner Losh }
11468e3e3a7aSWarner Losh case LUA_GCRESTART: {
11478e3e3a7aSWarner Losh luaE_setdebt(g, 0);
11488c784bb8SWarner Losh g->gcstp = 0; /* (GCSTPGC must be already zero here) */
11498e3e3a7aSWarner Losh break;
11508e3e3a7aSWarner Losh }
11518e3e3a7aSWarner Losh case LUA_GCCOLLECT: {
11528e3e3a7aSWarner Losh luaC_fullgc(L, 0);
11538e3e3a7aSWarner Losh break;
11548e3e3a7aSWarner Losh }
11558e3e3a7aSWarner Losh case LUA_GCCOUNT: {
11568e3e3a7aSWarner Losh /* GC values are expressed in Kbytes: #bytes/2^10 */
11578e3e3a7aSWarner Losh res = cast_int(gettotalbytes(g) >> 10);
11588e3e3a7aSWarner Losh break;
11598e3e3a7aSWarner Losh }
11608e3e3a7aSWarner Losh case LUA_GCCOUNTB: {
11618e3e3a7aSWarner Losh res = cast_int(gettotalbytes(g) & 0x3ff);
11628e3e3a7aSWarner Losh break;
11638e3e3a7aSWarner Losh }
11648e3e3a7aSWarner Losh case LUA_GCSTEP: {
11650495ed39SKyle Evans int data = va_arg(argp, int);
11668e3e3a7aSWarner Losh l_mem debt = 1; /* =1 to signal that it did an actual step */
11678c784bb8SWarner Losh lu_byte oldstp = g->gcstp;
11688c784bb8SWarner Losh g->gcstp = 0; /* allow GC to run (GCSTPGC must be zero here) */
11698e3e3a7aSWarner Losh if (data == 0) {
11700495ed39SKyle Evans luaE_setdebt(g, 0); /* do a basic step */
11718e3e3a7aSWarner Losh luaC_step(L);
11728e3e3a7aSWarner Losh }
11738e3e3a7aSWarner Losh else { /* add 'data' to total debt */
11748e3e3a7aSWarner Losh debt = cast(l_mem, data) * 1024 + g->GCdebt;
11758e3e3a7aSWarner Losh luaE_setdebt(g, debt);
11768e3e3a7aSWarner Losh luaC_checkGC(L);
11778e3e3a7aSWarner Losh }
11788c784bb8SWarner Losh g->gcstp = oldstp; /* restore previous state */
11798e3e3a7aSWarner Losh if (debt > 0 && g->gcstate == GCSpause) /* end of cycle? */
11808e3e3a7aSWarner Losh res = 1; /* signal it */
11818e3e3a7aSWarner Losh break;
11828e3e3a7aSWarner Losh }
11838e3e3a7aSWarner Losh case LUA_GCSETPAUSE: {
11840495ed39SKyle Evans int data = va_arg(argp, int);
11850495ed39SKyle Evans res = getgcparam(g->gcpause);
11860495ed39SKyle Evans setgcparam(g->gcpause, data);
11878e3e3a7aSWarner Losh break;
11888e3e3a7aSWarner Losh }
11898e3e3a7aSWarner Losh case LUA_GCSETSTEPMUL: {
11900495ed39SKyle Evans int data = va_arg(argp, int);
11910495ed39SKyle Evans res = getgcparam(g->gcstepmul);
11920495ed39SKyle Evans setgcparam(g->gcstepmul, data);
11938e3e3a7aSWarner Losh break;
11948e3e3a7aSWarner Losh }
11958e3e3a7aSWarner Losh case LUA_GCISRUNNING: {
11968c784bb8SWarner Losh res = gcrunning(g);
11978e3e3a7aSWarner Losh break;
11988e3e3a7aSWarner Losh }
11990495ed39SKyle Evans case LUA_GCGEN: {
12000495ed39SKyle Evans int minormul = va_arg(argp, int);
12010495ed39SKyle Evans int majormul = va_arg(argp, int);
12020495ed39SKyle Evans res = isdecGCmodegen(g) ? LUA_GCGEN : LUA_GCINC;
12030495ed39SKyle Evans if (minormul != 0)
12040495ed39SKyle Evans g->genminormul = minormul;
12050495ed39SKyle Evans if (majormul != 0)
12060495ed39SKyle Evans setgcparam(g->genmajormul, majormul);
12070495ed39SKyle Evans luaC_changemode(L, KGC_GEN);
12080495ed39SKyle Evans break;
12090495ed39SKyle Evans }
12100495ed39SKyle Evans case LUA_GCINC: {
12110495ed39SKyle Evans int pause = va_arg(argp, int);
12120495ed39SKyle Evans int stepmul = va_arg(argp, int);
12130495ed39SKyle Evans int stepsize = va_arg(argp, int);
12140495ed39SKyle Evans res = isdecGCmodegen(g) ? LUA_GCGEN : LUA_GCINC;
12150495ed39SKyle Evans if (pause != 0)
12160495ed39SKyle Evans setgcparam(g->gcpause, pause);
12170495ed39SKyle Evans if (stepmul != 0)
12180495ed39SKyle Evans setgcparam(g->gcstepmul, stepmul);
12190495ed39SKyle Evans if (stepsize != 0)
12200495ed39SKyle Evans g->gcstepsize = stepsize;
12210495ed39SKyle Evans luaC_changemode(L, KGC_INC);
12220495ed39SKyle Evans break;
12230495ed39SKyle Evans }
12248e3e3a7aSWarner Losh default: res = -1; /* invalid option */
12258e3e3a7aSWarner Losh }
12260495ed39SKyle Evans va_end(argp);
12278e3e3a7aSWarner Losh lua_unlock(L);
12288e3e3a7aSWarner Losh return res;
12298e3e3a7aSWarner Losh }
12308e3e3a7aSWarner Losh
12318e3e3a7aSWarner Losh
12328e3e3a7aSWarner Losh
12338e3e3a7aSWarner Losh /*
12348e3e3a7aSWarner Losh ** miscellaneous functions
12358e3e3a7aSWarner Losh */
12368e3e3a7aSWarner Losh
12378e3e3a7aSWarner Losh
lua_error(lua_State * L)12388e3e3a7aSWarner Losh LUA_API int lua_error (lua_State *L) {
12390495ed39SKyle Evans TValue *errobj;
12408e3e3a7aSWarner Losh lua_lock(L);
1241*a9490b81SWarner Losh errobj = s2v(L->top.p - 1);
12428e3e3a7aSWarner Losh api_checknelems(L, 1);
12430495ed39SKyle Evans /* error object is the memory error message? */
12440495ed39SKyle Evans if (ttisshrstring(errobj) && eqshrstr(tsvalue(errobj), G(L)->memerrmsg))
12450495ed39SKyle Evans luaM_error(L); /* raise a memory error */
12460495ed39SKyle Evans else
12470495ed39SKyle Evans luaG_errormsg(L); /* raise a regular error */
12488e3e3a7aSWarner Losh /* code unreachable; will unlock when control actually leaves the kernel */
12498e3e3a7aSWarner Losh return 0; /* to avoid warnings */
12508e3e3a7aSWarner Losh }
12518e3e3a7aSWarner Losh
12528e3e3a7aSWarner Losh
lua_next(lua_State * L,int idx)12538e3e3a7aSWarner Losh LUA_API int lua_next (lua_State *L, int idx) {
12540495ed39SKyle Evans Table *t;
12558e3e3a7aSWarner Losh int more;
12568e3e3a7aSWarner Losh lua_lock(L);
12570495ed39SKyle Evans api_checknelems(L, 1);
12580495ed39SKyle Evans t = gettable(L, idx);
1259*a9490b81SWarner Losh more = luaH_next(L, t, L->top.p - 1);
12608e3e3a7aSWarner Losh if (more) {
12618e3e3a7aSWarner Losh api_incr_top(L);
12628e3e3a7aSWarner Losh }
12638e3e3a7aSWarner Losh else /* no more elements */
1264*a9490b81SWarner Losh L->top.p -= 1; /* remove key */
12658e3e3a7aSWarner Losh lua_unlock(L);
12668e3e3a7aSWarner Losh return more;
12678e3e3a7aSWarner Losh }
12688e3e3a7aSWarner Losh
12698e3e3a7aSWarner Losh
lua_toclose(lua_State * L,int idx)12700495ed39SKyle Evans LUA_API void lua_toclose (lua_State *L, int idx) {
12710495ed39SKyle Evans int nresults;
12720495ed39SKyle Evans StkId o;
12730495ed39SKyle Evans lua_lock(L);
12740495ed39SKyle Evans o = index2stack(L, idx);
12750495ed39SKyle Evans nresults = L->ci->nresults;
1276*a9490b81SWarner Losh api_check(L, L->tbclist.p < o, "given index below or equal a marked one");
12770495ed39SKyle Evans luaF_newtbcupval(L, o); /* create new to-be-closed upvalue */
12780495ed39SKyle Evans if (!hastocloseCfunc(nresults)) /* function not marked yet? */
12790495ed39SKyle Evans L->ci->nresults = codeNresults(nresults); /* mark it */
12800495ed39SKyle Evans lua_assert(hastocloseCfunc(L->ci->nresults));
12810495ed39SKyle Evans lua_unlock(L);
12820495ed39SKyle Evans }
12830495ed39SKyle Evans
12840495ed39SKyle Evans
lua_concat(lua_State * L,int n)12858e3e3a7aSWarner Losh LUA_API void lua_concat (lua_State *L, int n) {
12868e3e3a7aSWarner Losh lua_lock(L);
12878e3e3a7aSWarner Losh api_checknelems(L, n);
12880495ed39SKyle Evans if (n > 0)
12898e3e3a7aSWarner Losh luaV_concat(L, n);
12900495ed39SKyle Evans else { /* nothing to concatenate */
1291*a9490b81SWarner Losh setsvalue2s(L, L->top.p, luaS_newlstr(L, "", 0)); /* push empty string */
12928e3e3a7aSWarner Losh api_incr_top(L);
12938e3e3a7aSWarner Losh }
12948e3e3a7aSWarner Losh luaC_checkGC(L);
12958e3e3a7aSWarner Losh lua_unlock(L);
12968e3e3a7aSWarner Losh }
12978e3e3a7aSWarner Losh
12988e3e3a7aSWarner Losh
lua_len(lua_State * L,int idx)12998e3e3a7aSWarner Losh LUA_API void lua_len (lua_State *L, int idx) {
13000495ed39SKyle Evans TValue *t;
13018e3e3a7aSWarner Losh lua_lock(L);
13020495ed39SKyle Evans t = index2value(L, idx);
1303*a9490b81SWarner Losh luaV_objlen(L, L->top.p, t);
13048e3e3a7aSWarner Losh api_incr_top(L);
13058e3e3a7aSWarner Losh lua_unlock(L);
13068e3e3a7aSWarner Losh }
13078e3e3a7aSWarner Losh
13088e3e3a7aSWarner Losh
lua_getallocf(lua_State * L,void ** ud)13098e3e3a7aSWarner Losh LUA_API lua_Alloc lua_getallocf (lua_State *L, void **ud) {
13108e3e3a7aSWarner Losh lua_Alloc f;
13118e3e3a7aSWarner Losh lua_lock(L);
13128e3e3a7aSWarner Losh if (ud) *ud = G(L)->ud;
13138e3e3a7aSWarner Losh f = G(L)->frealloc;
13148e3e3a7aSWarner Losh lua_unlock(L);
13158e3e3a7aSWarner Losh return f;
13168e3e3a7aSWarner Losh }
13178e3e3a7aSWarner Losh
13188e3e3a7aSWarner Losh
lua_setallocf(lua_State * L,lua_Alloc f,void * ud)13198e3e3a7aSWarner Losh LUA_API void lua_setallocf (lua_State *L, lua_Alloc f, void *ud) {
13208e3e3a7aSWarner Losh lua_lock(L);
13218e3e3a7aSWarner Losh G(L)->ud = ud;
13228e3e3a7aSWarner Losh G(L)->frealloc = f;
13238e3e3a7aSWarner Losh lua_unlock(L);
13248e3e3a7aSWarner Losh }
13258e3e3a7aSWarner Losh
13268e3e3a7aSWarner Losh
lua_setwarnf(lua_State * L,lua_WarnFunction f,void * ud)13270495ed39SKyle Evans void lua_setwarnf (lua_State *L, lua_WarnFunction f, void *ud) {
13280495ed39SKyle Evans lua_lock(L);
13290495ed39SKyle Evans G(L)->ud_warn = ud;
13300495ed39SKyle Evans G(L)->warnf = f;
13310495ed39SKyle Evans lua_unlock(L);
13320495ed39SKyle Evans }
13330495ed39SKyle Evans
13340495ed39SKyle Evans
lua_warning(lua_State * L,const char * msg,int tocont)13350495ed39SKyle Evans void lua_warning (lua_State *L, const char *msg, int tocont) {
13360495ed39SKyle Evans lua_lock(L);
13370495ed39SKyle Evans luaE_warning(L, msg, tocont);
13380495ed39SKyle Evans lua_unlock(L);
13390495ed39SKyle Evans }
13400495ed39SKyle Evans
13410495ed39SKyle Evans
13420495ed39SKyle Evans
lua_newuserdatauv(lua_State * L,size_t size,int nuvalue)13430495ed39SKyle Evans LUA_API void *lua_newuserdatauv (lua_State *L, size_t size, int nuvalue) {
13448e3e3a7aSWarner Losh Udata *u;
13458e3e3a7aSWarner Losh lua_lock(L);
13460495ed39SKyle Evans api_check(L, 0 <= nuvalue && nuvalue < USHRT_MAX, "invalid value");
13470495ed39SKyle Evans u = luaS_newudata(L, size, nuvalue);
1348*a9490b81SWarner Losh setuvalue(L, s2v(L->top.p), u);
13498e3e3a7aSWarner Losh api_incr_top(L);
13508e3e3a7aSWarner Losh luaC_checkGC(L);
13518e3e3a7aSWarner Losh lua_unlock(L);
13528e3e3a7aSWarner Losh return getudatamem(u);
13538e3e3a7aSWarner Losh }
13548e3e3a7aSWarner Losh
13558e3e3a7aSWarner Losh
13568e3e3a7aSWarner Losh
aux_upvalue(TValue * fi,int n,TValue ** val,GCObject ** owner)13570495ed39SKyle Evans static const char *aux_upvalue (TValue *fi, int n, TValue **val,
13580495ed39SKyle Evans GCObject **owner) {
13590495ed39SKyle Evans switch (ttypetag(fi)) {
13600495ed39SKyle Evans case LUA_VCCL: { /* C closure */
13618e3e3a7aSWarner Losh CClosure *f = clCvalue(fi);
13620495ed39SKyle Evans if (!(cast_uint(n) - 1u < cast_uint(f->nupvalues)))
13630495ed39SKyle Evans return NULL; /* 'n' not in [1, f->nupvalues] */
13648e3e3a7aSWarner Losh *val = &f->upvalue[n-1];
13650495ed39SKyle Evans if (owner) *owner = obj2gco(f);
13668e3e3a7aSWarner Losh return "";
13678e3e3a7aSWarner Losh }
13680495ed39SKyle Evans case LUA_VLCL: { /* Lua closure */
13698e3e3a7aSWarner Losh LClosure *f = clLvalue(fi);
13708e3e3a7aSWarner Losh TString *name;
13718e3e3a7aSWarner Losh Proto *p = f->p;
13720495ed39SKyle Evans if (!(cast_uint(n) - 1u < cast_uint(p->sizeupvalues)))
13730495ed39SKyle Evans return NULL; /* 'n' not in [1, p->sizeupvalues] */
1374*a9490b81SWarner Losh *val = f->upvals[n-1]->v.p;
13750495ed39SKyle Evans if (owner) *owner = obj2gco(f->upvals[n - 1]);
13768e3e3a7aSWarner Losh name = p->upvalues[n-1].name;
13770495ed39SKyle Evans return (name == NULL) ? "(no name)" : getstr(name);
13788e3e3a7aSWarner Losh }
13798e3e3a7aSWarner Losh default: return NULL; /* not a closure */
13808e3e3a7aSWarner Losh }
13818e3e3a7aSWarner Losh }
13828e3e3a7aSWarner Losh
13838e3e3a7aSWarner Losh
lua_getupvalue(lua_State * L,int funcindex,int n)13848e3e3a7aSWarner Losh LUA_API const char *lua_getupvalue (lua_State *L, int funcindex, int n) {
13858e3e3a7aSWarner Losh const char *name;
13868e3e3a7aSWarner Losh TValue *val = NULL; /* to avoid warnings */
13878e3e3a7aSWarner Losh lua_lock(L);
13880495ed39SKyle Evans name = aux_upvalue(index2value(L, funcindex), n, &val, NULL);
13898e3e3a7aSWarner Losh if (name) {
1390*a9490b81SWarner Losh setobj2s(L, L->top.p, val);
13918e3e3a7aSWarner Losh api_incr_top(L);
13928e3e3a7aSWarner Losh }
13938e3e3a7aSWarner Losh lua_unlock(L);
13948e3e3a7aSWarner Losh return name;
13958e3e3a7aSWarner Losh }
13968e3e3a7aSWarner Losh
13978e3e3a7aSWarner Losh
lua_setupvalue(lua_State * L,int funcindex,int n)13988e3e3a7aSWarner Losh LUA_API const char *lua_setupvalue (lua_State *L, int funcindex, int n) {
13998e3e3a7aSWarner Losh const char *name;
14008e3e3a7aSWarner Losh TValue *val = NULL; /* to avoid warnings */
14010495ed39SKyle Evans GCObject *owner = NULL; /* to avoid warnings */
14020495ed39SKyle Evans TValue *fi;
14038e3e3a7aSWarner Losh lua_lock(L);
14040495ed39SKyle Evans fi = index2value(L, funcindex);
14058e3e3a7aSWarner Losh api_checknelems(L, 1);
14060495ed39SKyle Evans name = aux_upvalue(fi, n, &val, &owner);
14078e3e3a7aSWarner Losh if (name) {
1408*a9490b81SWarner Losh L->top.p--;
1409*a9490b81SWarner Losh setobj(L, val, s2v(L->top.p));
14100495ed39SKyle Evans luaC_barrier(L, owner, val);
14118e3e3a7aSWarner Losh }
14128e3e3a7aSWarner Losh lua_unlock(L);
14138e3e3a7aSWarner Losh return name;
14148e3e3a7aSWarner Losh }
14158e3e3a7aSWarner Losh
14168e3e3a7aSWarner Losh
getupvalref(lua_State * L,int fidx,int n,LClosure ** pf)14170495ed39SKyle Evans static UpVal **getupvalref (lua_State *L, int fidx, int n, LClosure **pf) {
14180495ed39SKyle Evans static const UpVal *const nullup = NULL;
14198e3e3a7aSWarner Losh LClosure *f;
14200495ed39SKyle Evans TValue *fi = index2value(L, fidx);
14218e3e3a7aSWarner Losh api_check(L, ttisLclosure(fi), "Lua function expected");
14228e3e3a7aSWarner Losh f = clLvalue(fi);
14230495ed39SKyle Evans if (pf) *pf = f;
14240495ed39SKyle Evans if (1 <= n && n <= f->p->sizeupvalues)
14258e3e3a7aSWarner Losh return &f->upvals[n - 1]; /* get its upvalue pointer */
14260495ed39SKyle Evans else
14270495ed39SKyle Evans return (UpVal**)&nullup;
14288e3e3a7aSWarner Losh }
14298e3e3a7aSWarner Losh
14308e3e3a7aSWarner Losh
lua_upvalueid(lua_State * L,int fidx,int n)14318e3e3a7aSWarner Losh LUA_API void *lua_upvalueid (lua_State *L, int fidx, int n) {
14320495ed39SKyle Evans TValue *fi = index2value(L, fidx);
14330495ed39SKyle Evans switch (ttypetag(fi)) {
14340495ed39SKyle Evans case LUA_VLCL: { /* lua closure */
14350495ed39SKyle Evans return *getupvalref(L, fidx, n, NULL);
14368e3e3a7aSWarner Losh }
14370495ed39SKyle Evans case LUA_VCCL: { /* C closure */
14388e3e3a7aSWarner Losh CClosure *f = clCvalue(fi);
14390495ed39SKyle Evans if (1 <= n && n <= f->nupvalues)
14408e3e3a7aSWarner Losh return &f->upvalue[n - 1];
14410495ed39SKyle Evans /* else */
14420495ed39SKyle Evans } /* FALLTHROUGH */
14430495ed39SKyle Evans case LUA_VLCF:
14440495ed39SKyle Evans return NULL; /* light C functions have no upvalues */
14458e3e3a7aSWarner Losh default: {
14460495ed39SKyle Evans api_check(L, 0, "function expected");
14478e3e3a7aSWarner Losh return NULL;
14488e3e3a7aSWarner Losh }
14498e3e3a7aSWarner Losh }
14508e3e3a7aSWarner Losh }
14518e3e3a7aSWarner Losh
14528e3e3a7aSWarner Losh
lua_upvaluejoin(lua_State * L,int fidx1,int n1,int fidx2,int n2)14538e3e3a7aSWarner Losh LUA_API void lua_upvaluejoin (lua_State *L, int fidx1, int n1,
14548e3e3a7aSWarner Losh int fidx2, int n2) {
14550495ed39SKyle Evans LClosure *f1;
14560495ed39SKyle Evans UpVal **up1 = getupvalref(L, fidx1, n1, &f1);
14570495ed39SKyle Evans UpVal **up2 = getupvalref(L, fidx2, n2, NULL);
14580495ed39SKyle Evans api_check(L, *up1 != NULL && *up2 != NULL, "invalid upvalue index");
14598e3e3a7aSWarner Losh *up1 = *up2;
14600495ed39SKyle Evans luaC_objbarrier(L, f1, *up1);
14618e3e3a7aSWarner Losh }
14628e3e3a7aSWarner Losh
14638e3e3a7aSWarner Losh
1464