18e3e3a7aSWarner Losh /* 2*0495ed39SKyle 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 13*0495ed39SKyle 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 41*0495ed39SKyle Evans /* 42*0495ed39SKyle Evans ** Test for a valid index. 43*0495ed39SKyle Evans ** '!ttisnil(o)' implies 'o != &G(L)->nilvalue', so it is not needed. 44*0495ed39SKyle Evans ** However, it covers the most common cases in a faster way. 45*0495ed39SKyle Evans */ 46*0495ed39SKyle Evans #define isvalid(L, o) (!ttisnil(o) || o != &G(L)->nilvalue) 47*0495ed39SKyle 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 56*0495ed39SKyle Evans static TValue *index2value (lua_State *L, int idx) { 578e3e3a7aSWarner Losh CallInfo *ci = L->ci; 588e3e3a7aSWarner Losh if (idx > 0) { 59*0495ed39SKyle Evans StkId o = ci->func + idx; 60*0495ed39SKyle Evans api_check(L, idx <= L->ci->top - (ci->func + 1), "unacceptable index"); 61*0495ed39SKyle Evans if (o >= L->top) return &G(L)->nilvalue; 62*0495ed39SKyle Evans else return s2v(o); 638e3e3a7aSWarner Losh } 648e3e3a7aSWarner Losh else if (!ispseudo(idx)) { /* negative index */ 658e3e3a7aSWarner Losh api_check(L, idx != 0 && -idx <= L->top - (ci->func + 1), "invalid index"); 66*0495ed39SKyle Evans return s2v(L->top + idx); 678e3e3a7aSWarner Losh } 688e3e3a7aSWarner Losh else if (idx == LUA_REGISTRYINDEX) 698e3e3a7aSWarner Losh return &G(L)->l_registry; 708e3e3a7aSWarner Losh else { /* upvalues */ 718e3e3a7aSWarner Losh idx = LUA_REGISTRYINDEX - idx; 728e3e3a7aSWarner Losh api_check(L, idx <= MAXUPVAL + 1, "upvalue index too large"); 73*0495ed39SKyle Evans if (ttislcf(s2v(ci->func))) /* light C function? */ 74*0495ed39SKyle Evans return &G(L)->nilvalue; /* it has no upvalues */ 758e3e3a7aSWarner Losh else { 76*0495ed39SKyle Evans CClosure *func = clCvalue(s2v(ci->func)); 77*0495ed39SKyle Evans return (idx <= func->nupvalues) ? &func->upvalue[idx-1] : &G(L)->nilvalue; 788e3e3a7aSWarner Losh } 798e3e3a7aSWarner Losh } 808e3e3a7aSWarner Losh } 818e3e3a7aSWarner Losh 828e3e3a7aSWarner Losh 83*0495ed39SKyle Evans static StkId index2stack (lua_State *L, int idx) { 84*0495ed39SKyle Evans CallInfo *ci = L->ci; 85*0495ed39SKyle Evans if (idx > 0) { 86*0495ed39SKyle Evans StkId o = ci->func + idx; 87*0495ed39SKyle Evans api_check(L, o < L->top, "unacceptable index"); 88*0495ed39SKyle Evans return o; 89*0495ed39SKyle Evans } 90*0495ed39SKyle Evans else { /* non-positive index */ 91*0495ed39SKyle Evans api_check(L, idx != 0 && -idx <= L->top - (ci->func + 1), "invalid index"); 92*0495ed39SKyle Evans api_check(L, !ispseudo(idx), "invalid index"); 93*0495ed39SKyle Evans return L->top + idx; 94*0495ed39SKyle Evans } 958e3e3a7aSWarner Losh } 968e3e3a7aSWarner Losh 978e3e3a7aSWarner Losh 988e3e3a7aSWarner Losh LUA_API int lua_checkstack (lua_State *L, int n) { 998e3e3a7aSWarner Losh int res; 100*0495ed39SKyle Evans CallInfo *ci; 1018e3e3a7aSWarner Losh lua_lock(L); 102*0495ed39SKyle Evans ci = L->ci; 1038e3e3a7aSWarner Losh api_check(L, n >= 0, "negative 'n'"); 1048e3e3a7aSWarner Losh if (L->stack_last - L->top > n) /* stack large enough? */ 1058e3e3a7aSWarner Losh res = 1; /* yes; check is OK */ 1068e3e3a7aSWarner Losh else { /* no; need to grow stack */ 1078e3e3a7aSWarner Losh int inuse = cast_int(L->top - L->stack) + EXTRA_STACK; 1088e3e3a7aSWarner Losh if (inuse > LUAI_MAXSTACK - n) /* can grow without overflow? */ 1098e3e3a7aSWarner Losh res = 0; /* no */ 1108e3e3a7aSWarner Losh else /* try to grow stack */ 111*0495ed39SKyle Evans res = luaD_growstack(L, n, 0); 1128e3e3a7aSWarner Losh } 1138e3e3a7aSWarner Losh if (res && ci->top < L->top + n) 1148e3e3a7aSWarner Losh ci->top = L->top + n; /* adjust frame top */ 1158e3e3a7aSWarner Losh lua_unlock(L); 1168e3e3a7aSWarner Losh return res; 1178e3e3a7aSWarner Losh } 1188e3e3a7aSWarner Losh 1198e3e3a7aSWarner Losh 1208e3e3a7aSWarner Losh LUA_API void lua_xmove (lua_State *from, lua_State *to, int n) { 1218e3e3a7aSWarner Losh int i; 1228e3e3a7aSWarner Losh if (from == to) return; 1238e3e3a7aSWarner Losh lua_lock(to); 1248e3e3a7aSWarner Losh api_checknelems(from, n); 1258e3e3a7aSWarner Losh api_check(from, G(from) == G(to), "moving among independent states"); 1268e3e3a7aSWarner Losh api_check(from, to->ci->top - to->top >= n, "stack overflow"); 1278e3e3a7aSWarner Losh from->top -= n; 1288e3e3a7aSWarner Losh for (i = 0; i < n; i++) { 129*0495ed39SKyle Evans setobjs2s(to, to->top, from->top + i); 1308e3e3a7aSWarner Losh to->top++; /* stack already checked by previous 'api_check' */ 1318e3e3a7aSWarner Losh } 1328e3e3a7aSWarner Losh lua_unlock(to); 1338e3e3a7aSWarner Losh } 1348e3e3a7aSWarner Losh 1358e3e3a7aSWarner Losh 1368e3e3a7aSWarner Losh LUA_API lua_CFunction lua_atpanic (lua_State *L, lua_CFunction panicf) { 1378e3e3a7aSWarner Losh lua_CFunction old; 1388e3e3a7aSWarner Losh lua_lock(L); 1398e3e3a7aSWarner Losh old = G(L)->panic; 1408e3e3a7aSWarner Losh G(L)->panic = panicf; 1418e3e3a7aSWarner Losh lua_unlock(L); 1428e3e3a7aSWarner Losh return old; 1438e3e3a7aSWarner Losh } 1448e3e3a7aSWarner Losh 1458e3e3a7aSWarner Losh 146*0495ed39SKyle Evans LUA_API lua_Number lua_version (lua_State *L) { 147*0495ed39SKyle Evans UNUSED(L); 148*0495ed39SKyle Evans return LUA_VERSION_NUM; 1498e3e3a7aSWarner Losh } 1508e3e3a7aSWarner Losh 1518e3e3a7aSWarner Losh 1528e3e3a7aSWarner Losh 1538e3e3a7aSWarner Losh /* 1548e3e3a7aSWarner Losh ** basic stack manipulation 1558e3e3a7aSWarner Losh */ 1568e3e3a7aSWarner Losh 1578e3e3a7aSWarner Losh 1588e3e3a7aSWarner Losh /* 1598e3e3a7aSWarner Losh ** convert an acceptable stack index into an absolute index 1608e3e3a7aSWarner Losh */ 1618e3e3a7aSWarner Losh LUA_API int lua_absindex (lua_State *L, int idx) { 1628e3e3a7aSWarner Losh return (idx > 0 || ispseudo(idx)) 1638e3e3a7aSWarner Losh ? idx 1648e3e3a7aSWarner Losh : cast_int(L->top - L->ci->func) + idx; 1658e3e3a7aSWarner Losh } 1668e3e3a7aSWarner Losh 1678e3e3a7aSWarner Losh 1688e3e3a7aSWarner Losh LUA_API int lua_gettop (lua_State *L) { 1698e3e3a7aSWarner Losh return cast_int(L->top - (L->ci->func + 1)); 1708e3e3a7aSWarner Losh } 1718e3e3a7aSWarner Losh 1728e3e3a7aSWarner Losh 1738e3e3a7aSWarner Losh LUA_API void lua_settop (lua_State *L, int idx) { 174*0495ed39SKyle Evans CallInfo *ci; 175*0495ed39SKyle Evans StkId func; 176*0495ed39SKyle Evans ptrdiff_t diff; /* difference for new top */ 1778e3e3a7aSWarner Losh lua_lock(L); 178*0495ed39SKyle Evans ci = L->ci; 179*0495ed39SKyle Evans func = ci->func; 1808e3e3a7aSWarner Losh if (idx >= 0) { 181*0495ed39SKyle Evans api_check(L, idx <= ci->top - (func + 1), "new top too large"); 182*0495ed39SKyle Evans diff = ((func + 1) + idx) - L->top; 183*0495ed39SKyle Evans for (; diff > 0; diff--) 184*0495ed39SKyle Evans setnilvalue(s2v(L->top++)); /* clear new slots */ 1858e3e3a7aSWarner Losh } 1868e3e3a7aSWarner Losh else { 1878e3e3a7aSWarner Losh api_check(L, -(idx+1) <= (L->top - (func + 1)), "invalid new top"); 188*0495ed39SKyle Evans diff = idx + 1; /* will "subtract" index (as it is negative) */ 1898e3e3a7aSWarner Losh } 190*0495ed39SKyle Evans if (diff < 0 && hastocloseCfunc(ci->nresults)) 191*0495ed39SKyle Evans luaF_close(L, L->top + diff, LUA_OK); 192*0495ed39SKyle Evans L->top += diff; /* correct top only after closing any upvalue */ 1938e3e3a7aSWarner Losh lua_unlock(L); 1948e3e3a7aSWarner Losh } 1958e3e3a7aSWarner Losh 1968e3e3a7aSWarner Losh 1978e3e3a7aSWarner Losh /* 1988e3e3a7aSWarner Losh ** Reverse the stack segment from 'from' to 'to' 1998e3e3a7aSWarner Losh ** (auxiliary to 'lua_rotate') 200*0495ed39SKyle Evans ** Note that we move(copy) only the value inside the stack. 201*0495ed39SKyle Evans ** (We do not move additional fields that may exist.) 2028e3e3a7aSWarner Losh */ 2038e3e3a7aSWarner Losh static void reverse (lua_State *L, StkId from, StkId to) { 2048e3e3a7aSWarner Losh for (; from < to; from++, to--) { 2058e3e3a7aSWarner Losh TValue temp; 206*0495ed39SKyle Evans setobj(L, &temp, s2v(from)); 2078e3e3a7aSWarner Losh setobjs2s(L, from, to); 2088e3e3a7aSWarner Losh setobj2s(L, to, &temp); 2098e3e3a7aSWarner Losh } 2108e3e3a7aSWarner Losh } 2118e3e3a7aSWarner Losh 2128e3e3a7aSWarner Losh 2138e3e3a7aSWarner Losh /* 2148e3e3a7aSWarner Losh ** Let x = AB, where A is a prefix of length 'n'. Then, 2158e3e3a7aSWarner Losh ** rotate x n == BA. But BA == (A^r . B^r)^r. 2168e3e3a7aSWarner Losh */ 2178e3e3a7aSWarner Losh LUA_API void lua_rotate (lua_State *L, int idx, int n) { 2188e3e3a7aSWarner Losh StkId p, t, m; 2198e3e3a7aSWarner Losh lua_lock(L); 2208e3e3a7aSWarner Losh t = L->top - 1; /* end of stack segment being rotated */ 221*0495ed39SKyle Evans p = index2stack(L, idx); /* start of segment */ 2228e3e3a7aSWarner Losh api_check(L, (n >= 0 ? n : -n) <= (t - p + 1), "invalid 'n'"); 2238e3e3a7aSWarner Losh m = (n >= 0 ? t - n : p - n - 1); /* end of prefix */ 2248e3e3a7aSWarner Losh reverse(L, p, m); /* reverse the prefix with length 'n' */ 2258e3e3a7aSWarner Losh reverse(L, m + 1, t); /* reverse the suffix */ 2268e3e3a7aSWarner Losh reverse(L, p, t); /* reverse the entire segment */ 2278e3e3a7aSWarner Losh lua_unlock(L); 2288e3e3a7aSWarner Losh } 2298e3e3a7aSWarner Losh 2308e3e3a7aSWarner Losh 2318e3e3a7aSWarner Losh LUA_API void lua_copy (lua_State *L, int fromidx, int toidx) { 2328e3e3a7aSWarner Losh TValue *fr, *to; 2338e3e3a7aSWarner Losh lua_lock(L); 234*0495ed39SKyle Evans fr = index2value(L, fromidx); 235*0495ed39SKyle Evans to = index2value(L, toidx); 236*0495ed39SKyle Evans api_check(L, isvalid(L, to), "invalid index"); 2378e3e3a7aSWarner Losh setobj(L, to, fr); 2388e3e3a7aSWarner Losh if (isupvalue(toidx)) /* function upvalue? */ 239*0495ed39SKyle Evans luaC_barrier(L, clCvalue(s2v(L->ci->func)), fr); 2408e3e3a7aSWarner Losh /* LUA_REGISTRYINDEX does not need gc barrier 2418e3e3a7aSWarner Losh (collector revisits it before finishing collection) */ 2428e3e3a7aSWarner Losh lua_unlock(L); 2438e3e3a7aSWarner Losh } 2448e3e3a7aSWarner Losh 2458e3e3a7aSWarner Losh 2468e3e3a7aSWarner Losh LUA_API void lua_pushvalue (lua_State *L, int idx) { 2478e3e3a7aSWarner Losh lua_lock(L); 248*0495ed39SKyle Evans setobj2s(L, L->top, index2value(L, idx)); 2498e3e3a7aSWarner Losh api_incr_top(L); 2508e3e3a7aSWarner Losh lua_unlock(L); 2518e3e3a7aSWarner Losh } 2528e3e3a7aSWarner Losh 2538e3e3a7aSWarner Losh 2548e3e3a7aSWarner Losh 2558e3e3a7aSWarner Losh /* 2568e3e3a7aSWarner Losh ** access functions (stack -> C) 2578e3e3a7aSWarner Losh */ 2588e3e3a7aSWarner Losh 2598e3e3a7aSWarner Losh 2608e3e3a7aSWarner Losh LUA_API int lua_type (lua_State *L, int idx) { 261*0495ed39SKyle Evans const TValue *o = index2value(L, idx); 262*0495ed39SKyle Evans return (isvalid(L, o) ? ttype(o) : LUA_TNONE); 2638e3e3a7aSWarner Losh } 2648e3e3a7aSWarner Losh 2658e3e3a7aSWarner Losh 2668e3e3a7aSWarner Losh LUA_API const char *lua_typename (lua_State *L, int t) { 2678e3e3a7aSWarner Losh UNUSED(L); 268*0495ed39SKyle Evans api_check(L, LUA_TNONE <= t && t < LUA_NUMTYPES, "invalid type"); 2698e3e3a7aSWarner Losh return ttypename(t); 2708e3e3a7aSWarner Losh } 2718e3e3a7aSWarner Losh 2728e3e3a7aSWarner Losh 2738e3e3a7aSWarner Losh LUA_API int lua_iscfunction (lua_State *L, int idx) { 274*0495ed39SKyle Evans const TValue *o = index2value(L, idx); 2758e3e3a7aSWarner Losh return (ttislcf(o) || (ttisCclosure(o))); 2768e3e3a7aSWarner Losh } 2778e3e3a7aSWarner Losh 2788e3e3a7aSWarner Losh 2798e3e3a7aSWarner Losh LUA_API int lua_isinteger (lua_State *L, int idx) { 280*0495ed39SKyle Evans const TValue *o = index2value(L, idx); 2818e3e3a7aSWarner Losh return ttisinteger(o); 2828e3e3a7aSWarner Losh } 2838e3e3a7aSWarner Losh 2848e3e3a7aSWarner Losh 2858e3e3a7aSWarner Losh LUA_API int lua_isnumber (lua_State *L, int idx) { 2868e3e3a7aSWarner Losh lua_Number n; 287*0495ed39SKyle Evans const TValue *o = index2value(L, idx); 2888e3e3a7aSWarner Losh return tonumber(o, &n); 2898e3e3a7aSWarner Losh } 2908e3e3a7aSWarner Losh 2918e3e3a7aSWarner Losh 2928e3e3a7aSWarner Losh LUA_API int lua_isstring (lua_State *L, int idx) { 293*0495ed39SKyle Evans const TValue *o = index2value(L, idx); 2948e3e3a7aSWarner Losh return (ttisstring(o) || cvt2str(o)); 2958e3e3a7aSWarner Losh } 2968e3e3a7aSWarner Losh 2978e3e3a7aSWarner Losh 2988e3e3a7aSWarner Losh LUA_API int lua_isuserdata (lua_State *L, int idx) { 299*0495ed39SKyle Evans const TValue *o = index2value(L, idx); 3008e3e3a7aSWarner Losh return (ttisfulluserdata(o) || ttislightuserdata(o)); 3018e3e3a7aSWarner Losh } 3028e3e3a7aSWarner Losh 3038e3e3a7aSWarner Losh 3048e3e3a7aSWarner Losh LUA_API int lua_rawequal (lua_State *L, int index1, int index2) { 305*0495ed39SKyle Evans const TValue *o1 = index2value(L, index1); 306*0495ed39SKyle Evans const TValue *o2 = index2value(L, index2); 307*0495ed39SKyle Evans return (isvalid(L, o1) && isvalid(L, o2)) ? luaV_rawequalobj(o1, o2) : 0; 3088e3e3a7aSWarner Losh } 3098e3e3a7aSWarner Losh 3108e3e3a7aSWarner Losh 3118e3e3a7aSWarner Losh LUA_API void lua_arith (lua_State *L, int op) { 3128e3e3a7aSWarner Losh lua_lock(L); 3138e3e3a7aSWarner Losh if (op != LUA_OPUNM && op != LUA_OPBNOT) 3148e3e3a7aSWarner Losh api_checknelems(L, 2); /* all other operations expect two operands */ 3158e3e3a7aSWarner Losh else { /* for unary operations, add fake 2nd operand */ 3168e3e3a7aSWarner Losh api_checknelems(L, 1); 3178e3e3a7aSWarner Losh setobjs2s(L, L->top, L->top - 1); 3188e3e3a7aSWarner Losh api_incr_top(L); 3198e3e3a7aSWarner Losh } 3208e3e3a7aSWarner Losh /* first operand at top - 2, second at top - 1; result go to top - 2 */ 321*0495ed39SKyle Evans luaO_arith(L, op, s2v(L->top - 2), s2v(L->top - 1), L->top - 2); 3228e3e3a7aSWarner Losh L->top--; /* remove second operand */ 3238e3e3a7aSWarner Losh lua_unlock(L); 3248e3e3a7aSWarner Losh } 3258e3e3a7aSWarner Losh 3268e3e3a7aSWarner Losh 3278e3e3a7aSWarner Losh LUA_API int lua_compare (lua_State *L, int index1, int index2, int op) { 328*0495ed39SKyle Evans const TValue *o1; 329*0495ed39SKyle Evans const TValue *o2; 3308e3e3a7aSWarner Losh int i = 0; 3318e3e3a7aSWarner Losh lua_lock(L); /* may call tag method */ 332*0495ed39SKyle Evans o1 = index2value(L, index1); 333*0495ed39SKyle Evans o2 = index2value(L, index2); 334*0495ed39SKyle Evans if (isvalid(L, o1) && isvalid(L, o2)) { 3358e3e3a7aSWarner Losh switch (op) { 3368e3e3a7aSWarner Losh case LUA_OPEQ: i = luaV_equalobj(L, o1, o2); break; 3378e3e3a7aSWarner Losh case LUA_OPLT: i = luaV_lessthan(L, o1, o2); break; 3388e3e3a7aSWarner Losh case LUA_OPLE: i = luaV_lessequal(L, o1, o2); break; 3398e3e3a7aSWarner Losh default: api_check(L, 0, "invalid option"); 3408e3e3a7aSWarner Losh } 3418e3e3a7aSWarner Losh } 3428e3e3a7aSWarner Losh lua_unlock(L); 3438e3e3a7aSWarner Losh return i; 3448e3e3a7aSWarner Losh } 3458e3e3a7aSWarner Losh 3468e3e3a7aSWarner Losh 3478e3e3a7aSWarner Losh LUA_API size_t lua_stringtonumber (lua_State *L, const char *s) { 348*0495ed39SKyle Evans size_t sz = luaO_str2num(s, s2v(L->top)); 3498e3e3a7aSWarner Losh if (sz != 0) 3508e3e3a7aSWarner Losh api_incr_top(L); 3518e3e3a7aSWarner Losh return sz; 3528e3e3a7aSWarner Losh } 3538e3e3a7aSWarner Losh 3548e3e3a7aSWarner Losh 3558e3e3a7aSWarner Losh LUA_API lua_Number lua_tonumberx (lua_State *L, int idx, int *pisnum) { 356*0495ed39SKyle Evans lua_Number n = 0; 357*0495ed39SKyle Evans const TValue *o = index2value(L, idx); 3588e3e3a7aSWarner Losh int isnum = tonumber(o, &n); 359*0495ed39SKyle Evans if (pisnum) 360*0495ed39SKyle Evans *pisnum = isnum; 3618e3e3a7aSWarner Losh return n; 3628e3e3a7aSWarner Losh } 3638e3e3a7aSWarner Losh 3648e3e3a7aSWarner Losh 3658e3e3a7aSWarner Losh LUA_API lua_Integer lua_tointegerx (lua_State *L, int idx, int *pisnum) { 366*0495ed39SKyle Evans lua_Integer res = 0; 367*0495ed39SKyle Evans const TValue *o = index2value(L, idx); 3688e3e3a7aSWarner Losh int isnum = tointeger(o, &res); 369*0495ed39SKyle Evans if (pisnum) 370*0495ed39SKyle Evans *pisnum = isnum; 3718e3e3a7aSWarner Losh return res; 3728e3e3a7aSWarner Losh } 3738e3e3a7aSWarner Losh 3748e3e3a7aSWarner Losh 3758e3e3a7aSWarner Losh LUA_API int lua_toboolean (lua_State *L, int idx) { 376*0495ed39SKyle Evans const TValue *o = index2value(L, idx); 3778e3e3a7aSWarner Losh return !l_isfalse(o); 3788e3e3a7aSWarner Losh } 3798e3e3a7aSWarner Losh 3808e3e3a7aSWarner Losh 3818e3e3a7aSWarner Losh LUA_API const char *lua_tolstring (lua_State *L, int idx, size_t *len) { 382*0495ed39SKyle Evans TValue *o; 383*0495ed39SKyle Evans lua_lock(L); 384*0495ed39SKyle Evans o = index2value(L, idx); 3858e3e3a7aSWarner Losh if (!ttisstring(o)) { 3868e3e3a7aSWarner Losh if (!cvt2str(o)) { /* not convertible? */ 3878e3e3a7aSWarner Losh if (len != NULL) *len = 0; 388*0495ed39SKyle Evans lua_unlock(L); 3898e3e3a7aSWarner Losh return NULL; 3908e3e3a7aSWarner Losh } 3918e3e3a7aSWarner Losh luaO_tostring(L, o); 3928e3e3a7aSWarner Losh luaC_checkGC(L); 393*0495ed39SKyle Evans o = index2value(L, idx); /* previous call may reallocate the stack */ 3948e3e3a7aSWarner Losh } 3958e3e3a7aSWarner Losh if (len != NULL) 3968e3e3a7aSWarner Losh *len = vslen(o); 397*0495ed39SKyle Evans lua_unlock(L); 3988e3e3a7aSWarner Losh return svalue(o); 3998e3e3a7aSWarner Losh } 4008e3e3a7aSWarner Losh 4018e3e3a7aSWarner Losh 402*0495ed39SKyle Evans LUA_API lua_Unsigned lua_rawlen (lua_State *L, int idx) { 403*0495ed39SKyle Evans const TValue *o = index2value(L, idx); 404*0495ed39SKyle Evans switch (ttypetag(o)) { 405*0495ed39SKyle Evans case LUA_VSHRSTR: return tsvalue(o)->shrlen; 406*0495ed39SKyle Evans case LUA_VLNGSTR: return tsvalue(o)->u.lnglen; 407*0495ed39SKyle Evans case LUA_VUSERDATA: return uvalue(o)->len; 408*0495ed39SKyle Evans case LUA_VTABLE: return luaH_getn(hvalue(o)); 4098e3e3a7aSWarner Losh default: return 0; 4108e3e3a7aSWarner Losh } 4118e3e3a7aSWarner Losh } 4128e3e3a7aSWarner Losh 4138e3e3a7aSWarner Losh 4148e3e3a7aSWarner Losh LUA_API lua_CFunction lua_tocfunction (lua_State *L, int idx) { 415*0495ed39SKyle Evans const TValue *o = index2value(L, idx); 4168e3e3a7aSWarner Losh if (ttislcf(o)) return fvalue(o); 4178e3e3a7aSWarner Losh else if (ttisCclosure(o)) 4188e3e3a7aSWarner Losh return clCvalue(o)->f; 4198e3e3a7aSWarner Losh else return NULL; /* not a C function */ 4208e3e3a7aSWarner Losh } 4218e3e3a7aSWarner Losh 4228e3e3a7aSWarner Losh 423*0495ed39SKyle Evans static void *touserdata (const TValue *o) { 424*0495ed39SKyle Evans switch (ttype(o)) { 4258e3e3a7aSWarner Losh case LUA_TUSERDATA: return getudatamem(uvalue(o)); 4268e3e3a7aSWarner Losh case LUA_TLIGHTUSERDATA: return pvalue(o); 4278e3e3a7aSWarner Losh default: return NULL; 4288e3e3a7aSWarner Losh } 4298e3e3a7aSWarner Losh } 4308e3e3a7aSWarner Losh 4318e3e3a7aSWarner Losh 432*0495ed39SKyle Evans LUA_API void *lua_touserdata (lua_State *L, int idx) { 433*0495ed39SKyle Evans const TValue *o = index2value(L, idx); 434*0495ed39SKyle Evans return touserdata(o); 435*0495ed39SKyle Evans } 436*0495ed39SKyle Evans 437*0495ed39SKyle Evans 4388e3e3a7aSWarner Losh LUA_API lua_State *lua_tothread (lua_State *L, int idx) { 439*0495ed39SKyle Evans const TValue *o = index2value(L, idx); 4408e3e3a7aSWarner Losh return (!ttisthread(o)) ? NULL : thvalue(o); 4418e3e3a7aSWarner Losh } 4428e3e3a7aSWarner Losh 4438e3e3a7aSWarner Losh 444*0495ed39SKyle Evans /* 445*0495ed39SKyle Evans ** Returns a pointer to the internal representation of an object. 446*0495ed39SKyle Evans ** Note that ANSI C does not allow the conversion of a pointer to 447*0495ed39SKyle Evans ** function to a 'void*', so the conversion here goes through 448*0495ed39SKyle Evans ** a 'size_t'. (As the returned pointer is only informative, this 449*0495ed39SKyle Evans ** conversion should not be a problem.) 450*0495ed39SKyle Evans */ 4518e3e3a7aSWarner Losh LUA_API const void *lua_topointer (lua_State *L, int idx) { 452*0495ed39SKyle Evans const TValue *o = index2value(L, idx); 453*0495ed39SKyle Evans switch (ttypetag(o)) { 454*0495ed39SKyle Evans case LUA_VLCF: return cast_voidp(cast_sizet(fvalue(o))); 455*0495ed39SKyle Evans case LUA_VUSERDATA: case LUA_VLIGHTUSERDATA: 456*0495ed39SKyle Evans return touserdata(o); 457*0495ed39SKyle Evans default: { 458*0495ed39SKyle Evans if (iscollectable(o)) 459*0495ed39SKyle Evans return gcvalue(o); 460*0495ed39SKyle Evans else 461*0495ed39SKyle Evans return NULL; 462*0495ed39SKyle Evans } 4638e3e3a7aSWarner Losh } 4648e3e3a7aSWarner Losh } 4658e3e3a7aSWarner Losh 4668e3e3a7aSWarner Losh 4678e3e3a7aSWarner Losh 4688e3e3a7aSWarner Losh /* 4698e3e3a7aSWarner Losh ** push functions (C -> stack) 4708e3e3a7aSWarner Losh */ 4718e3e3a7aSWarner Losh 4728e3e3a7aSWarner Losh 4738e3e3a7aSWarner Losh LUA_API void lua_pushnil (lua_State *L) { 4748e3e3a7aSWarner Losh lua_lock(L); 475*0495ed39SKyle Evans setnilvalue(s2v(L->top)); 4768e3e3a7aSWarner Losh api_incr_top(L); 4778e3e3a7aSWarner Losh lua_unlock(L); 4788e3e3a7aSWarner Losh } 4798e3e3a7aSWarner Losh 4808e3e3a7aSWarner Losh 4818e3e3a7aSWarner Losh LUA_API void lua_pushnumber (lua_State *L, lua_Number n) { 4828e3e3a7aSWarner Losh lua_lock(L); 483*0495ed39SKyle Evans setfltvalue(s2v(L->top), n); 4848e3e3a7aSWarner Losh api_incr_top(L); 4858e3e3a7aSWarner Losh lua_unlock(L); 4868e3e3a7aSWarner Losh } 4878e3e3a7aSWarner Losh 4888e3e3a7aSWarner Losh 4898e3e3a7aSWarner Losh LUA_API void lua_pushinteger (lua_State *L, lua_Integer n) { 4908e3e3a7aSWarner Losh lua_lock(L); 491*0495ed39SKyle Evans setivalue(s2v(L->top), n); 4928e3e3a7aSWarner Losh api_incr_top(L); 4938e3e3a7aSWarner Losh lua_unlock(L); 4948e3e3a7aSWarner Losh } 4958e3e3a7aSWarner Losh 4968e3e3a7aSWarner Losh 4978e3e3a7aSWarner Losh /* 4988e3e3a7aSWarner Losh ** Pushes on the stack a string with given length. Avoid using 's' when 4998e3e3a7aSWarner Losh ** 'len' == 0 (as 's' can be NULL in that case), due to later use of 5008e3e3a7aSWarner Losh ** 'memcmp' and 'memcpy'. 5018e3e3a7aSWarner Losh */ 5028e3e3a7aSWarner Losh LUA_API const char *lua_pushlstring (lua_State *L, const char *s, size_t len) { 5038e3e3a7aSWarner Losh TString *ts; 5048e3e3a7aSWarner Losh lua_lock(L); 5058e3e3a7aSWarner Losh ts = (len == 0) ? luaS_new(L, "") : luaS_newlstr(L, s, len); 5068e3e3a7aSWarner Losh setsvalue2s(L, L->top, ts); 5078e3e3a7aSWarner Losh api_incr_top(L); 5088e3e3a7aSWarner Losh luaC_checkGC(L); 5098e3e3a7aSWarner Losh lua_unlock(L); 5108e3e3a7aSWarner Losh return getstr(ts); 5118e3e3a7aSWarner Losh } 5128e3e3a7aSWarner Losh 5138e3e3a7aSWarner Losh 5148e3e3a7aSWarner Losh LUA_API const char *lua_pushstring (lua_State *L, const char *s) { 5158e3e3a7aSWarner Losh lua_lock(L); 5168e3e3a7aSWarner Losh if (s == NULL) 517*0495ed39SKyle Evans setnilvalue(s2v(L->top)); 5188e3e3a7aSWarner Losh else { 5198e3e3a7aSWarner Losh TString *ts; 5208e3e3a7aSWarner Losh ts = luaS_new(L, s); 5218e3e3a7aSWarner Losh setsvalue2s(L, L->top, ts); 5228e3e3a7aSWarner Losh s = getstr(ts); /* internal copy's address */ 5238e3e3a7aSWarner Losh } 5248e3e3a7aSWarner Losh api_incr_top(L); 5258e3e3a7aSWarner Losh luaC_checkGC(L); 5268e3e3a7aSWarner Losh lua_unlock(L); 5278e3e3a7aSWarner Losh return s; 5288e3e3a7aSWarner Losh } 5298e3e3a7aSWarner Losh 5308e3e3a7aSWarner Losh 5318e3e3a7aSWarner Losh LUA_API const char *lua_pushvfstring (lua_State *L, const char *fmt, 5328e3e3a7aSWarner Losh va_list argp) { 5338e3e3a7aSWarner Losh const char *ret; 5348e3e3a7aSWarner Losh lua_lock(L); 5358e3e3a7aSWarner Losh ret = luaO_pushvfstring(L, fmt, argp); 5368e3e3a7aSWarner Losh luaC_checkGC(L); 5378e3e3a7aSWarner Losh lua_unlock(L); 5388e3e3a7aSWarner Losh return ret; 5398e3e3a7aSWarner Losh } 5408e3e3a7aSWarner Losh 5418e3e3a7aSWarner Losh 5428e3e3a7aSWarner Losh LUA_API const char *lua_pushfstring (lua_State *L, const char *fmt, ...) { 5438e3e3a7aSWarner Losh const char *ret; 5448e3e3a7aSWarner Losh va_list argp; 5458e3e3a7aSWarner Losh lua_lock(L); 5468e3e3a7aSWarner Losh va_start(argp, fmt); 5478e3e3a7aSWarner Losh ret = luaO_pushvfstring(L, fmt, argp); 5488e3e3a7aSWarner Losh va_end(argp); 5498e3e3a7aSWarner Losh luaC_checkGC(L); 5508e3e3a7aSWarner Losh lua_unlock(L); 5518e3e3a7aSWarner Losh return ret; 5528e3e3a7aSWarner Losh } 5538e3e3a7aSWarner Losh 5548e3e3a7aSWarner Losh 5558e3e3a7aSWarner Losh LUA_API void lua_pushcclosure (lua_State *L, lua_CFunction fn, int n) { 5568e3e3a7aSWarner Losh lua_lock(L); 5578e3e3a7aSWarner Losh if (n == 0) { 558*0495ed39SKyle Evans setfvalue(s2v(L->top), fn); 559e112e9d2SKyle Evans api_incr_top(L); 5608e3e3a7aSWarner Losh } 5618e3e3a7aSWarner Losh else { 5628e3e3a7aSWarner Losh CClosure *cl; 5638e3e3a7aSWarner Losh api_checknelems(L, n); 5648e3e3a7aSWarner Losh api_check(L, n <= MAXUPVAL, "upvalue index too large"); 5658e3e3a7aSWarner Losh cl = luaF_newCclosure(L, n); 5668e3e3a7aSWarner Losh cl->f = fn; 5678e3e3a7aSWarner Losh L->top -= n; 5688e3e3a7aSWarner Losh while (n--) { 569*0495ed39SKyle Evans setobj2n(L, &cl->upvalue[n], s2v(L->top + n)); 5708e3e3a7aSWarner Losh /* does not need barrier because closure is white */ 571*0495ed39SKyle Evans lua_assert(iswhite(cl)); 5728e3e3a7aSWarner Losh } 573*0495ed39SKyle Evans setclCvalue(L, s2v(L->top), cl); 5748e3e3a7aSWarner Losh api_incr_top(L); 5758e3e3a7aSWarner Losh luaC_checkGC(L); 576e112e9d2SKyle Evans } 5778e3e3a7aSWarner Losh lua_unlock(L); 5788e3e3a7aSWarner Losh } 5798e3e3a7aSWarner Losh 5808e3e3a7aSWarner Losh 5818e3e3a7aSWarner Losh LUA_API void lua_pushboolean (lua_State *L, int b) { 5828e3e3a7aSWarner Losh lua_lock(L); 583*0495ed39SKyle Evans if (b) 584*0495ed39SKyle Evans setbtvalue(s2v(L->top)); 585*0495ed39SKyle Evans else 586*0495ed39SKyle Evans setbfvalue(s2v(L->top)); 5878e3e3a7aSWarner Losh api_incr_top(L); 5888e3e3a7aSWarner Losh lua_unlock(L); 5898e3e3a7aSWarner Losh } 5908e3e3a7aSWarner Losh 5918e3e3a7aSWarner Losh 5928e3e3a7aSWarner Losh LUA_API void lua_pushlightuserdata (lua_State *L, void *p) { 5938e3e3a7aSWarner Losh lua_lock(L); 594*0495ed39SKyle Evans setpvalue(s2v(L->top), p); 5958e3e3a7aSWarner Losh api_incr_top(L); 5968e3e3a7aSWarner Losh lua_unlock(L); 5978e3e3a7aSWarner Losh } 5988e3e3a7aSWarner Losh 5998e3e3a7aSWarner Losh 6008e3e3a7aSWarner Losh LUA_API int lua_pushthread (lua_State *L) { 6018e3e3a7aSWarner Losh lua_lock(L); 602*0495ed39SKyle Evans setthvalue(L, s2v(L->top), L); 6038e3e3a7aSWarner Losh api_incr_top(L); 6048e3e3a7aSWarner Losh lua_unlock(L); 6058e3e3a7aSWarner Losh return (G(L)->mainthread == L); 6068e3e3a7aSWarner Losh } 6078e3e3a7aSWarner Losh 6088e3e3a7aSWarner Losh 6098e3e3a7aSWarner Losh 6108e3e3a7aSWarner Losh /* 6118e3e3a7aSWarner Losh ** get functions (Lua -> stack) 6128e3e3a7aSWarner Losh */ 6138e3e3a7aSWarner Losh 6148e3e3a7aSWarner Losh 6158e3e3a7aSWarner Losh static int auxgetstr (lua_State *L, const TValue *t, const char *k) { 6168e3e3a7aSWarner Losh const TValue *slot; 6178e3e3a7aSWarner Losh TString *str = luaS_new(L, k); 6188e3e3a7aSWarner Losh if (luaV_fastget(L, t, str, slot, luaH_getstr)) { 6198e3e3a7aSWarner Losh setobj2s(L, L->top, slot); 6208e3e3a7aSWarner Losh api_incr_top(L); 6218e3e3a7aSWarner Losh } 6228e3e3a7aSWarner Losh else { 6238e3e3a7aSWarner Losh setsvalue2s(L, L->top, str); 6248e3e3a7aSWarner Losh api_incr_top(L); 625*0495ed39SKyle Evans luaV_finishget(L, t, s2v(L->top - 1), L->top - 1, slot); 6268e3e3a7aSWarner Losh } 6278e3e3a7aSWarner Losh lua_unlock(L); 628*0495ed39SKyle Evans return ttype(s2v(L->top - 1)); 6298e3e3a7aSWarner Losh } 6308e3e3a7aSWarner Losh 6318e3e3a7aSWarner Losh 6328e3e3a7aSWarner Losh LUA_API int lua_getglobal (lua_State *L, const char *name) { 633*0495ed39SKyle Evans Table *reg; 6348e3e3a7aSWarner Losh lua_lock(L); 635*0495ed39SKyle Evans reg = hvalue(&G(L)->l_registry); 6368e3e3a7aSWarner Losh return auxgetstr(L, luaH_getint(reg, LUA_RIDX_GLOBALS), name); 6378e3e3a7aSWarner Losh } 6388e3e3a7aSWarner Losh 6398e3e3a7aSWarner Losh 6408e3e3a7aSWarner Losh LUA_API int lua_gettable (lua_State *L, int idx) { 641*0495ed39SKyle Evans const TValue *slot; 642*0495ed39SKyle Evans TValue *t; 6438e3e3a7aSWarner Losh lua_lock(L); 644*0495ed39SKyle Evans t = index2value(L, idx); 645*0495ed39SKyle Evans if (luaV_fastget(L, t, s2v(L->top - 1), slot, luaH_get)) { 646*0495ed39SKyle Evans setobj2s(L, L->top - 1, slot); 647*0495ed39SKyle Evans } 648*0495ed39SKyle Evans else 649*0495ed39SKyle Evans luaV_finishget(L, t, s2v(L->top - 1), L->top - 1, slot); 6508e3e3a7aSWarner Losh lua_unlock(L); 651*0495ed39SKyle Evans return ttype(s2v(L->top - 1)); 6528e3e3a7aSWarner Losh } 6538e3e3a7aSWarner Losh 6548e3e3a7aSWarner Losh 6558e3e3a7aSWarner Losh LUA_API int lua_getfield (lua_State *L, int idx, const char *k) { 6568e3e3a7aSWarner Losh lua_lock(L); 657*0495ed39SKyle Evans return auxgetstr(L, index2value(L, idx), k); 6588e3e3a7aSWarner Losh } 6598e3e3a7aSWarner Losh 6608e3e3a7aSWarner Losh 6618e3e3a7aSWarner Losh LUA_API int lua_geti (lua_State *L, int idx, lua_Integer n) { 662*0495ed39SKyle Evans TValue *t; 6638e3e3a7aSWarner Losh const TValue *slot; 6648e3e3a7aSWarner Losh lua_lock(L); 665*0495ed39SKyle Evans t = index2value(L, idx); 666*0495ed39SKyle Evans if (luaV_fastgeti(L, t, n, slot)) { 6678e3e3a7aSWarner Losh setobj2s(L, L->top, slot); 6688e3e3a7aSWarner Losh } 6698e3e3a7aSWarner Losh else { 670*0495ed39SKyle Evans TValue aux; 671*0495ed39SKyle Evans setivalue(&aux, n); 672*0495ed39SKyle Evans luaV_finishget(L, t, &aux, L->top, slot); 6738e3e3a7aSWarner Losh } 674*0495ed39SKyle Evans api_incr_top(L); 6758e3e3a7aSWarner Losh lua_unlock(L); 676*0495ed39SKyle Evans return ttype(s2v(L->top - 1)); 677*0495ed39SKyle Evans } 678*0495ed39SKyle Evans 679*0495ed39SKyle Evans 680*0495ed39SKyle Evans static int finishrawget (lua_State *L, const TValue *val) { 681*0495ed39SKyle Evans if (isempty(val)) /* avoid copying empty items to the stack */ 682*0495ed39SKyle Evans setnilvalue(s2v(L->top)); 683*0495ed39SKyle Evans else 684*0495ed39SKyle Evans setobj2s(L, L->top, val); 685*0495ed39SKyle Evans api_incr_top(L); 686*0495ed39SKyle Evans lua_unlock(L); 687*0495ed39SKyle Evans return ttype(s2v(L->top - 1)); 688*0495ed39SKyle Evans } 689*0495ed39SKyle Evans 690*0495ed39SKyle Evans 691*0495ed39SKyle Evans static Table *gettable (lua_State *L, int idx) { 692*0495ed39SKyle Evans TValue *t = index2value(L, idx); 693*0495ed39SKyle Evans api_check(L, ttistable(t), "table expected"); 694*0495ed39SKyle Evans return hvalue(t); 6958e3e3a7aSWarner Losh } 6968e3e3a7aSWarner Losh 6978e3e3a7aSWarner Losh 6988e3e3a7aSWarner Losh LUA_API int lua_rawget (lua_State *L, int idx) { 699*0495ed39SKyle Evans Table *t; 700*0495ed39SKyle Evans const TValue *val; 7018e3e3a7aSWarner Losh lua_lock(L); 702*0495ed39SKyle Evans api_checknelems(L, 1); 703*0495ed39SKyle Evans t = gettable(L, idx); 704*0495ed39SKyle Evans val = luaH_get(t, s2v(L->top - 1)); 705*0495ed39SKyle Evans L->top--; /* remove key */ 706*0495ed39SKyle Evans return finishrawget(L, val); 7078e3e3a7aSWarner Losh } 7088e3e3a7aSWarner Losh 7098e3e3a7aSWarner Losh 7108e3e3a7aSWarner Losh LUA_API int lua_rawgeti (lua_State *L, int idx, lua_Integer n) { 711*0495ed39SKyle Evans Table *t; 7128e3e3a7aSWarner Losh lua_lock(L); 713*0495ed39SKyle Evans t = gettable(L, idx); 714*0495ed39SKyle Evans return finishrawget(L, luaH_getint(t, n)); 7158e3e3a7aSWarner Losh } 7168e3e3a7aSWarner Losh 7178e3e3a7aSWarner Losh 7188e3e3a7aSWarner Losh LUA_API int lua_rawgetp (lua_State *L, int idx, const void *p) { 719*0495ed39SKyle Evans Table *t; 7208e3e3a7aSWarner Losh TValue k; 7218e3e3a7aSWarner Losh lua_lock(L); 722*0495ed39SKyle Evans t = gettable(L, idx); 723*0495ed39SKyle Evans setpvalue(&k, cast_voidp(p)); 724*0495ed39SKyle Evans return finishrawget(L, luaH_get(t, &k)); 7258e3e3a7aSWarner Losh } 7268e3e3a7aSWarner Losh 7278e3e3a7aSWarner Losh 7288e3e3a7aSWarner Losh LUA_API void lua_createtable (lua_State *L, int narray, int nrec) { 7298e3e3a7aSWarner Losh Table *t; 7308e3e3a7aSWarner Losh lua_lock(L); 7318e3e3a7aSWarner Losh t = luaH_new(L); 732*0495ed39SKyle Evans sethvalue2s(L, L->top, t); 7338e3e3a7aSWarner Losh api_incr_top(L); 7348e3e3a7aSWarner Losh if (narray > 0 || nrec > 0) 7358e3e3a7aSWarner Losh luaH_resize(L, t, narray, nrec); 7368e3e3a7aSWarner Losh luaC_checkGC(L); 7378e3e3a7aSWarner Losh lua_unlock(L); 7388e3e3a7aSWarner Losh } 7398e3e3a7aSWarner Losh 7408e3e3a7aSWarner Losh 7418e3e3a7aSWarner Losh LUA_API int lua_getmetatable (lua_State *L, int objindex) { 7428e3e3a7aSWarner Losh const TValue *obj; 7438e3e3a7aSWarner Losh Table *mt; 7448e3e3a7aSWarner Losh int res = 0; 7458e3e3a7aSWarner Losh lua_lock(L); 746*0495ed39SKyle Evans obj = index2value(L, objindex); 747*0495ed39SKyle Evans switch (ttype(obj)) { 7488e3e3a7aSWarner Losh case LUA_TTABLE: 7498e3e3a7aSWarner Losh mt = hvalue(obj)->metatable; 7508e3e3a7aSWarner Losh break; 7518e3e3a7aSWarner Losh case LUA_TUSERDATA: 7528e3e3a7aSWarner Losh mt = uvalue(obj)->metatable; 7538e3e3a7aSWarner Losh break; 7548e3e3a7aSWarner Losh default: 755*0495ed39SKyle Evans mt = G(L)->mt[ttype(obj)]; 7568e3e3a7aSWarner Losh break; 7578e3e3a7aSWarner Losh } 7588e3e3a7aSWarner Losh if (mt != NULL) { 759*0495ed39SKyle Evans sethvalue2s(L, L->top, mt); 7608e3e3a7aSWarner Losh api_incr_top(L); 7618e3e3a7aSWarner Losh res = 1; 7628e3e3a7aSWarner Losh } 7638e3e3a7aSWarner Losh lua_unlock(L); 7648e3e3a7aSWarner Losh return res; 7658e3e3a7aSWarner Losh } 7668e3e3a7aSWarner Losh 7678e3e3a7aSWarner Losh 768*0495ed39SKyle Evans LUA_API int lua_getiuservalue (lua_State *L, int idx, int n) { 769*0495ed39SKyle Evans TValue *o; 770*0495ed39SKyle Evans int t; 7718e3e3a7aSWarner Losh lua_lock(L); 772*0495ed39SKyle Evans o = index2value(L, idx); 7738e3e3a7aSWarner Losh api_check(L, ttisfulluserdata(o), "full userdata expected"); 774*0495ed39SKyle Evans if (n <= 0 || n > uvalue(o)->nuvalue) { 775*0495ed39SKyle Evans setnilvalue(s2v(L->top)); 776*0495ed39SKyle Evans t = LUA_TNONE; 777*0495ed39SKyle Evans } 778*0495ed39SKyle Evans else { 779*0495ed39SKyle Evans setobj2s(L, L->top, &uvalue(o)->uv[n - 1].uv); 780*0495ed39SKyle Evans t = ttype(s2v(L->top)); 781*0495ed39SKyle Evans } 7828e3e3a7aSWarner Losh api_incr_top(L); 7838e3e3a7aSWarner Losh lua_unlock(L); 784*0495ed39SKyle Evans return t; 7858e3e3a7aSWarner Losh } 7868e3e3a7aSWarner Losh 7878e3e3a7aSWarner Losh 7888e3e3a7aSWarner Losh /* 7898e3e3a7aSWarner Losh ** set functions (stack -> Lua) 7908e3e3a7aSWarner Losh */ 7918e3e3a7aSWarner Losh 7928e3e3a7aSWarner Losh /* 7938e3e3a7aSWarner Losh ** t[k] = value at the top of the stack (where 'k' is a string) 7948e3e3a7aSWarner Losh */ 7958e3e3a7aSWarner Losh static void auxsetstr (lua_State *L, const TValue *t, const char *k) { 7968e3e3a7aSWarner Losh const TValue *slot; 7978e3e3a7aSWarner Losh TString *str = luaS_new(L, k); 7988e3e3a7aSWarner Losh api_checknelems(L, 1); 799*0495ed39SKyle Evans if (luaV_fastget(L, t, str, slot, luaH_getstr)) { 800*0495ed39SKyle Evans luaV_finishfastset(L, t, slot, s2v(L->top - 1)); 8018e3e3a7aSWarner Losh L->top--; /* pop value */ 802*0495ed39SKyle Evans } 8038e3e3a7aSWarner Losh else { 8048e3e3a7aSWarner Losh setsvalue2s(L, L->top, str); /* push 'str' (to make it a TValue) */ 8058e3e3a7aSWarner Losh api_incr_top(L); 806*0495ed39SKyle Evans luaV_finishset(L, t, s2v(L->top - 1), s2v(L->top - 2), slot); 8078e3e3a7aSWarner Losh L->top -= 2; /* pop value and key */ 8088e3e3a7aSWarner Losh } 8098e3e3a7aSWarner Losh lua_unlock(L); /* lock done by caller */ 8108e3e3a7aSWarner Losh } 8118e3e3a7aSWarner Losh 8128e3e3a7aSWarner Losh 8138e3e3a7aSWarner Losh LUA_API void lua_setglobal (lua_State *L, const char *name) { 814*0495ed39SKyle Evans Table *reg; 8158e3e3a7aSWarner Losh lua_lock(L); /* unlock done in 'auxsetstr' */ 816*0495ed39SKyle Evans reg = hvalue(&G(L)->l_registry); 8178e3e3a7aSWarner Losh auxsetstr(L, luaH_getint(reg, LUA_RIDX_GLOBALS), name); 8188e3e3a7aSWarner Losh } 8198e3e3a7aSWarner Losh 8208e3e3a7aSWarner Losh 8218e3e3a7aSWarner Losh LUA_API void lua_settable (lua_State *L, int idx) { 822*0495ed39SKyle Evans TValue *t; 823*0495ed39SKyle Evans const TValue *slot; 8248e3e3a7aSWarner Losh lua_lock(L); 8258e3e3a7aSWarner Losh api_checknelems(L, 2); 826*0495ed39SKyle Evans t = index2value(L, idx); 827*0495ed39SKyle Evans if (luaV_fastget(L, t, s2v(L->top - 2), slot, luaH_get)) { 828*0495ed39SKyle Evans luaV_finishfastset(L, t, slot, s2v(L->top - 1)); 829*0495ed39SKyle Evans } 830*0495ed39SKyle Evans else 831*0495ed39SKyle Evans luaV_finishset(L, t, s2v(L->top - 2), s2v(L->top - 1), slot); 8328e3e3a7aSWarner Losh L->top -= 2; /* pop index and value */ 8338e3e3a7aSWarner Losh lua_unlock(L); 8348e3e3a7aSWarner Losh } 8358e3e3a7aSWarner Losh 8368e3e3a7aSWarner Losh 8378e3e3a7aSWarner Losh LUA_API void lua_setfield (lua_State *L, int idx, const char *k) { 8388e3e3a7aSWarner Losh lua_lock(L); /* unlock done in 'auxsetstr' */ 839*0495ed39SKyle Evans auxsetstr(L, index2value(L, idx), k); 8408e3e3a7aSWarner Losh } 8418e3e3a7aSWarner Losh 8428e3e3a7aSWarner Losh 8438e3e3a7aSWarner Losh LUA_API void lua_seti (lua_State *L, int idx, lua_Integer n) { 844*0495ed39SKyle Evans TValue *t; 8458e3e3a7aSWarner Losh const TValue *slot; 8468e3e3a7aSWarner Losh lua_lock(L); 8478e3e3a7aSWarner Losh api_checknelems(L, 1); 848*0495ed39SKyle Evans t = index2value(L, idx); 849*0495ed39SKyle Evans if (luaV_fastgeti(L, t, n, slot)) { 850*0495ed39SKyle Evans luaV_finishfastset(L, t, slot, s2v(L->top - 1)); 8518e3e3a7aSWarner Losh } 852*0495ed39SKyle Evans else { 853*0495ed39SKyle Evans TValue aux; 854*0495ed39SKyle Evans setivalue(&aux, n); 855*0495ed39SKyle Evans luaV_finishset(L, t, &aux, s2v(L->top - 1), slot); 856*0495ed39SKyle Evans } 857*0495ed39SKyle Evans L->top--; /* pop value */ 858*0495ed39SKyle Evans lua_unlock(L); 859*0495ed39SKyle Evans } 860*0495ed39SKyle Evans 861*0495ed39SKyle Evans 862*0495ed39SKyle Evans static void aux_rawset (lua_State *L, int idx, TValue *key, int n) { 863*0495ed39SKyle Evans Table *t; 864*0495ed39SKyle Evans TValue *slot; 865*0495ed39SKyle Evans lua_lock(L); 866*0495ed39SKyle Evans api_checknelems(L, n); 867*0495ed39SKyle Evans t = gettable(L, idx); 868*0495ed39SKyle Evans slot = luaH_set(L, t, key); 869*0495ed39SKyle Evans setobj2t(L, slot, s2v(L->top - 1)); 870*0495ed39SKyle Evans invalidateTMcache(t); 871*0495ed39SKyle Evans luaC_barrierback(L, obj2gco(t), s2v(L->top - 1)); 872*0495ed39SKyle Evans L->top -= n; 8738e3e3a7aSWarner Losh lua_unlock(L); 8748e3e3a7aSWarner Losh } 8758e3e3a7aSWarner Losh 8768e3e3a7aSWarner Losh 8778e3e3a7aSWarner Losh LUA_API void lua_rawset (lua_State *L, int idx) { 878*0495ed39SKyle Evans aux_rawset(L, idx, s2v(L->top - 2), 2); 8798e3e3a7aSWarner Losh } 8808e3e3a7aSWarner Losh 8818e3e3a7aSWarner Losh 8828e3e3a7aSWarner Losh LUA_API void lua_rawsetp (lua_State *L, int idx, const void *p) { 883*0495ed39SKyle Evans TValue k; 884*0495ed39SKyle Evans setpvalue(&k, cast_voidp(p)); 885*0495ed39SKyle Evans aux_rawset(L, idx, &k, 1); 886*0495ed39SKyle Evans } 887*0495ed39SKyle Evans 888*0495ed39SKyle Evans 889*0495ed39SKyle Evans LUA_API void lua_rawseti (lua_State *L, int idx, lua_Integer n) { 890*0495ed39SKyle Evans Table *t; 8918e3e3a7aSWarner Losh lua_lock(L); 8928e3e3a7aSWarner Losh api_checknelems(L, 1); 893*0495ed39SKyle Evans t = gettable(L, idx); 894*0495ed39SKyle Evans luaH_setint(L, t, n, s2v(L->top - 1)); 895*0495ed39SKyle Evans luaC_barrierback(L, obj2gco(t), s2v(L->top - 1)); 8968e3e3a7aSWarner Losh L->top--; 8978e3e3a7aSWarner Losh lua_unlock(L); 8988e3e3a7aSWarner Losh } 8998e3e3a7aSWarner Losh 9008e3e3a7aSWarner Losh 9018e3e3a7aSWarner Losh LUA_API int lua_setmetatable (lua_State *L, int objindex) { 9028e3e3a7aSWarner Losh TValue *obj; 9038e3e3a7aSWarner Losh Table *mt; 9048e3e3a7aSWarner Losh lua_lock(L); 9058e3e3a7aSWarner Losh api_checknelems(L, 1); 906*0495ed39SKyle Evans obj = index2value(L, objindex); 907*0495ed39SKyle Evans if (ttisnil(s2v(L->top - 1))) 9088e3e3a7aSWarner Losh mt = NULL; 9098e3e3a7aSWarner Losh else { 910*0495ed39SKyle Evans api_check(L, ttistable(s2v(L->top - 1)), "table expected"); 911*0495ed39SKyle Evans mt = hvalue(s2v(L->top - 1)); 9128e3e3a7aSWarner Losh } 913*0495ed39SKyle Evans switch (ttype(obj)) { 9148e3e3a7aSWarner Losh case LUA_TTABLE: { 9158e3e3a7aSWarner Losh hvalue(obj)->metatable = mt; 9168e3e3a7aSWarner Losh if (mt) { 9178e3e3a7aSWarner Losh luaC_objbarrier(L, gcvalue(obj), mt); 9188e3e3a7aSWarner Losh luaC_checkfinalizer(L, gcvalue(obj), mt); 9198e3e3a7aSWarner Losh } 9208e3e3a7aSWarner Losh break; 9218e3e3a7aSWarner Losh } 9228e3e3a7aSWarner Losh case LUA_TUSERDATA: { 9238e3e3a7aSWarner Losh uvalue(obj)->metatable = mt; 9248e3e3a7aSWarner Losh if (mt) { 9258e3e3a7aSWarner Losh luaC_objbarrier(L, uvalue(obj), mt); 9268e3e3a7aSWarner Losh luaC_checkfinalizer(L, gcvalue(obj), mt); 9278e3e3a7aSWarner Losh } 9288e3e3a7aSWarner Losh break; 9298e3e3a7aSWarner Losh } 9308e3e3a7aSWarner Losh default: { 931*0495ed39SKyle Evans G(L)->mt[ttype(obj)] = mt; 9328e3e3a7aSWarner Losh break; 9338e3e3a7aSWarner Losh } 9348e3e3a7aSWarner Losh } 9358e3e3a7aSWarner Losh L->top--; 9368e3e3a7aSWarner Losh lua_unlock(L); 9378e3e3a7aSWarner Losh return 1; 9388e3e3a7aSWarner Losh } 9398e3e3a7aSWarner Losh 9408e3e3a7aSWarner Losh 941*0495ed39SKyle Evans LUA_API int lua_setiuservalue (lua_State *L, int idx, int n) { 942*0495ed39SKyle Evans TValue *o; 943*0495ed39SKyle Evans int res; 9448e3e3a7aSWarner Losh lua_lock(L); 9458e3e3a7aSWarner Losh api_checknelems(L, 1); 946*0495ed39SKyle Evans o = index2value(L, idx); 9478e3e3a7aSWarner Losh api_check(L, ttisfulluserdata(o), "full userdata expected"); 948*0495ed39SKyle Evans if (!(cast_uint(n) - 1u < cast_uint(uvalue(o)->nuvalue))) 949*0495ed39SKyle Evans res = 0; /* 'n' not in [1, uvalue(o)->nuvalue] */ 950*0495ed39SKyle Evans else { 951*0495ed39SKyle Evans setobj(L, &uvalue(o)->uv[n - 1].uv, s2v(L->top - 1)); 952*0495ed39SKyle Evans luaC_barrierback(L, gcvalue(o), s2v(L->top - 1)); 953*0495ed39SKyle Evans res = 1; 954*0495ed39SKyle Evans } 9558e3e3a7aSWarner Losh L->top--; 9568e3e3a7aSWarner Losh lua_unlock(L); 957*0495ed39SKyle Evans return res; 9588e3e3a7aSWarner Losh } 9598e3e3a7aSWarner Losh 9608e3e3a7aSWarner Losh 9618e3e3a7aSWarner Losh /* 9628e3e3a7aSWarner Losh ** 'load' and 'call' functions (run Lua code) 9638e3e3a7aSWarner Losh */ 9648e3e3a7aSWarner Losh 9658e3e3a7aSWarner Losh 9668e3e3a7aSWarner Losh #define checkresults(L,na,nr) \ 9678e3e3a7aSWarner Losh api_check(L, (nr) == LUA_MULTRET || (L->ci->top - L->top >= (nr) - (na)), \ 9688e3e3a7aSWarner Losh "results from function overflow current stack size") 9698e3e3a7aSWarner Losh 9708e3e3a7aSWarner Losh 9718e3e3a7aSWarner Losh LUA_API void lua_callk (lua_State *L, int nargs, int nresults, 9728e3e3a7aSWarner Losh lua_KContext ctx, lua_KFunction k) { 9738e3e3a7aSWarner Losh StkId func; 9748e3e3a7aSWarner Losh lua_lock(L); 9758e3e3a7aSWarner Losh api_check(L, k == NULL || !isLua(L->ci), 9768e3e3a7aSWarner Losh "cannot use continuations inside hooks"); 9778e3e3a7aSWarner Losh api_checknelems(L, nargs+1); 9788e3e3a7aSWarner Losh api_check(L, L->status == LUA_OK, "cannot do calls on non-normal thread"); 9798e3e3a7aSWarner Losh checkresults(L, nargs, nresults); 9808e3e3a7aSWarner Losh func = L->top - (nargs+1); 981*0495ed39SKyle Evans if (k != NULL && yieldable(L)) { /* need to prepare continuation? */ 9828e3e3a7aSWarner Losh L->ci->u.c.k = k; /* save continuation */ 9838e3e3a7aSWarner Losh L->ci->u.c.ctx = ctx; /* save context */ 9848e3e3a7aSWarner Losh luaD_call(L, func, nresults); /* do the call */ 9858e3e3a7aSWarner Losh } 9868e3e3a7aSWarner Losh else /* no continuation or no yieldable */ 9878e3e3a7aSWarner Losh luaD_callnoyield(L, func, nresults); /* just do the call */ 9888e3e3a7aSWarner Losh adjustresults(L, nresults); 9898e3e3a7aSWarner Losh lua_unlock(L); 9908e3e3a7aSWarner Losh } 9918e3e3a7aSWarner Losh 9928e3e3a7aSWarner Losh 9938e3e3a7aSWarner Losh 9948e3e3a7aSWarner Losh /* 9958e3e3a7aSWarner Losh ** Execute a protected call. 9968e3e3a7aSWarner Losh */ 9978e3e3a7aSWarner Losh struct CallS { /* data to 'f_call' */ 9988e3e3a7aSWarner Losh StkId func; 9998e3e3a7aSWarner Losh int nresults; 10008e3e3a7aSWarner Losh }; 10018e3e3a7aSWarner Losh 10028e3e3a7aSWarner Losh 10038e3e3a7aSWarner Losh static void f_call (lua_State *L, void *ud) { 10048e3e3a7aSWarner Losh struct CallS *c = cast(struct CallS *, ud); 10058e3e3a7aSWarner Losh luaD_callnoyield(L, c->func, c->nresults); 10068e3e3a7aSWarner Losh } 10078e3e3a7aSWarner Losh 10088e3e3a7aSWarner Losh 10098e3e3a7aSWarner Losh 10108e3e3a7aSWarner Losh LUA_API int lua_pcallk (lua_State *L, int nargs, int nresults, int errfunc, 10118e3e3a7aSWarner Losh lua_KContext ctx, lua_KFunction k) { 10128e3e3a7aSWarner Losh struct CallS c; 10138e3e3a7aSWarner Losh int status; 10148e3e3a7aSWarner Losh ptrdiff_t func; 10158e3e3a7aSWarner Losh lua_lock(L); 10168e3e3a7aSWarner Losh api_check(L, k == NULL || !isLua(L->ci), 10178e3e3a7aSWarner Losh "cannot use continuations inside hooks"); 10188e3e3a7aSWarner Losh api_checknelems(L, nargs+1); 10198e3e3a7aSWarner Losh api_check(L, L->status == LUA_OK, "cannot do calls on non-normal thread"); 10208e3e3a7aSWarner Losh checkresults(L, nargs, nresults); 10218e3e3a7aSWarner Losh if (errfunc == 0) 10228e3e3a7aSWarner Losh func = 0; 10238e3e3a7aSWarner Losh else { 1024*0495ed39SKyle Evans StkId o = index2stack(L, errfunc); 1025*0495ed39SKyle Evans api_check(L, ttisfunction(s2v(o)), "error handler must be a function"); 10268e3e3a7aSWarner Losh func = savestack(L, o); 10278e3e3a7aSWarner Losh } 10288e3e3a7aSWarner Losh c.func = L->top - (nargs+1); /* function to be called */ 1029*0495ed39SKyle Evans if (k == NULL || !yieldable(L)) { /* no continuation or no yieldable? */ 10308e3e3a7aSWarner Losh c.nresults = nresults; /* do a 'conventional' protected call */ 10318e3e3a7aSWarner Losh status = luaD_pcall(L, f_call, &c, savestack(L, c.func), func); 10328e3e3a7aSWarner Losh } 10338e3e3a7aSWarner Losh else { /* prepare continuation (call is already protected by 'resume') */ 10348e3e3a7aSWarner Losh CallInfo *ci = L->ci; 10358e3e3a7aSWarner Losh ci->u.c.k = k; /* save continuation */ 10368e3e3a7aSWarner Losh ci->u.c.ctx = ctx; /* save context */ 10378e3e3a7aSWarner Losh /* save information for error recovery */ 1038*0495ed39SKyle Evans ci->u2.funcidx = cast_int(savestack(L, c.func)); 10398e3e3a7aSWarner Losh ci->u.c.old_errfunc = L->errfunc; 10408e3e3a7aSWarner Losh L->errfunc = func; 10418e3e3a7aSWarner Losh setoah(ci->callstatus, L->allowhook); /* save value of 'allowhook' */ 10428e3e3a7aSWarner Losh ci->callstatus |= CIST_YPCALL; /* function can do error recovery */ 10438e3e3a7aSWarner Losh luaD_call(L, c.func, nresults); /* do the call */ 10448e3e3a7aSWarner Losh ci->callstatus &= ~CIST_YPCALL; 10458e3e3a7aSWarner Losh L->errfunc = ci->u.c.old_errfunc; 10468e3e3a7aSWarner Losh status = LUA_OK; /* if it is here, there were no errors */ 10478e3e3a7aSWarner Losh } 10488e3e3a7aSWarner Losh adjustresults(L, nresults); 10498e3e3a7aSWarner Losh lua_unlock(L); 10508e3e3a7aSWarner Losh return status; 10518e3e3a7aSWarner Losh } 10528e3e3a7aSWarner Losh 10538e3e3a7aSWarner Losh 10548e3e3a7aSWarner Losh LUA_API int lua_load (lua_State *L, lua_Reader reader, void *data, 10558e3e3a7aSWarner Losh const char *chunkname, const char *mode) { 10568e3e3a7aSWarner Losh ZIO z; 10578e3e3a7aSWarner Losh int status; 10588e3e3a7aSWarner Losh lua_lock(L); 10598e3e3a7aSWarner Losh if (!chunkname) chunkname = "?"; 10608e3e3a7aSWarner Losh luaZ_init(L, &z, reader, data); 10618e3e3a7aSWarner Losh status = luaD_protectedparser(L, &z, chunkname, mode); 10628e3e3a7aSWarner Losh if (status == LUA_OK) { /* no errors? */ 1063*0495ed39SKyle Evans LClosure *f = clLvalue(s2v(L->top - 1)); /* get newly created function */ 10648e3e3a7aSWarner Losh if (f->nupvalues >= 1) { /* does it have an upvalue? */ 10658e3e3a7aSWarner Losh /* get global table from registry */ 10668e3e3a7aSWarner Losh Table *reg = hvalue(&G(L)->l_registry); 10678e3e3a7aSWarner Losh const TValue *gt = luaH_getint(reg, LUA_RIDX_GLOBALS); 10688e3e3a7aSWarner Losh /* set global table as 1st upvalue of 'f' (may be LUA_ENV) */ 10698e3e3a7aSWarner Losh setobj(L, f->upvals[0]->v, gt); 1070*0495ed39SKyle Evans luaC_barrier(L, f->upvals[0], gt); 10718e3e3a7aSWarner Losh } 10728e3e3a7aSWarner Losh } 10738e3e3a7aSWarner Losh lua_unlock(L); 10748e3e3a7aSWarner Losh return status; 10758e3e3a7aSWarner Losh } 10768e3e3a7aSWarner Losh 10778e3e3a7aSWarner Losh 10788e3e3a7aSWarner Losh LUA_API int lua_dump (lua_State *L, lua_Writer writer, void *data, int strip) { 10798e3e3a7aSWarner Losh int status; 10808e3e3a7aSWarner Losh TValue *o; 10818e3e3a7aSWarner Losh lua_lock(L); 10828e3e3a7aSWarner Losh api_checknelems(L, 1); 1083*0495ed39SKyle Evans o = s2v(L->top - 1); 10848e3e3a7aSWarner Losh if (isLfunction(o)) 10858e3e3a7aSWarner Losh status = luaU_dump(L, getproto(o), writer, data, strip); 10868e3e3a7aSWarner Losh else 10878e3e3a7aSWarner Losh status = 1; 10888e3e3a7aSWarner Losh lua_unlock(L); 10898e3e3a7aSWarner Losh return status; 10908e3e3a7aSWarner Losh } 10918e3e3a7aSWarner Losh 10928e3e3a7aSWarner Losh 10938e3e3a7aSWarner Losh LUA_API int lua_status (lua_State *L) { 10948e3e3a7aSWarner Losh return L->status; 10958e3e3a7aSWarner Losh } 10968e3e3a7aSWarner Losh 10978e3e3a7aSWarner Losh 10988e3e3a7aSWarner Losh /* 10998e3e3a7aSWarner Losh ** Garbage-collection function 11008e3e3a7aSWarner Losh */ 1101*0495ed39SKyle Evans LUA_API int lua_gc (lua_State *L, int what, ...) { 1102*0495ed39SKyle Evans va_list argp; 11038e3e3a7aSWarner Losh int res = 0; 11048e3e3a7aSWarner Losh global_State *g; 11058e3e3a7aSWarner Losh lua_lock(L); 11068e3e3a7aSWarner Losh g = G(L); 1107*0495ed39SKyle Evans va_start(argp, what); 11088e3e3a7aSWarner Losh switch (what) { 11098e3e3a7aSWarner Losh case LUA_GCSTOP: { 11108e3e3a7aSWarner Losh g->gcrunning = 0; 11118e3e3a7aSWarner Losh break; 11128e3e3a7aSWarner Losh } 11138e3e3a7aSWarner Losh case LUA_GCRESTART: { 11148e3e3a7aSWarner Losh luaE_setdebt(g, 0); 11158e3e3a7aSWarner Losh g->gcrunning = 1; 11168e3e3a7aSWarner Losh break; 11178e3e3a7aSWarner Losh } 11188e3e3a7aSWarner Losh case LUA_GCCOLLECT: { 11198e3e3a7aSWarner Losh luaC_fullgc(L, 0); 11208e3e3a7aSWarner Losh break; 11218e3e3a7aSWarner Losh } 11228e3e3a7aSWarner Losh case LUA_GCCOUNT: { 11238e3e3a7aSWarner Losh /* GC values are expressed in Kbytes: #bytes/2^10 */ 11248e3e3a7aSWarner Losh res = cast_int(gettotalbytes(g) >> 10); 11258e3e3a7aSWarner Losh break; 11268e3e3a7aSWarner Losh } 11278e3e3a7aSWarner Losh case LUA_GCCOUNTB: { 11288e3e3a7aSWarner Losh res = cast_int(gettotalbytes(g) & 0x3ff); 11298e3e3a7aSWarner Losh break; 11308e3e3a7aSWarner Losh } 11318e3e3a7aSWarner Losh case LUA_GCSTEP: { 1132*0495ed39SKyle Evans int data = va_arg(argp, int); 11338e3e3a7aSWarner Losh l_mem debt = 1; /* =1 to signal that it did an actual step */ 11348e3e3a7aSWarner Losh lu_byte oldrunning = g->gcrunning; 11358e3e3a7aSWarner Losh g->gcrunning = 1; /* allow GC to run */ 11368e3e3a7aSWarner Losh if (data == 0) { 1137*0495ed39SKyle Evans luaE_setdebt(g, 0); /* do a basic step */ 11388e3e3a7aSWarner Losh luaC_step(L); 11398e3e3a7aSWarner Losh } 11408e3e3a7aSWarner Losh else { /* add 'data' to total debt */ 11418e3e3a7aSWarner Losh debt = cast(l_mem, data) * 1024 + g->GCdebt; 11428e3e3a7aSWarner Losh luaE_setdebt(g, debt); 11438e3e3a7aSWarner Losh luaC_checkGC(L); 11448e3e3a7aSWarner Losh } 11458e3e3a7aSWarner Losh g->gcrunning = oldrunning; /* restore previous state */ 11468e3e3a7aSWarner Losh if (debt > 0 && g->gcstate == GCSpause) /* end of cycle? */ 11478e3e3a7aSWarner Losh res = 1; /* signal it */ 11488e3e3a7aSWarner Losh break; 11498e3e3a7aSWarner Losh } 11508e3e3a7aSWarner Losh case LUA_GCSETPAUSE: { 1151*0495ed39SKyle Evans int data = va_arg(argp, int); 1152*0495ed39SKyle Evans res = getgcparam(g->gcpause); 1153*0495ed39SKyle Evans setgcparam(g->gcpause, data); 11548e3e3a7aSWarner Losh break; 11558e3e3a7aSWarner Losh } 11568e3e3a7aSWarner Losh case LUA_GCSETSTEPMUL: { 1157*0495ed39SKyle Evans int data = va_arg(argp, int); 1158*0495ed39SKyle Evans res = getgcparam(g->gcstepmul); 1159*0495ed39SKyle Evans setgcparam(g->gcstepmul, data); 11608e3e3a7aSWarner Losh break; 11618e3e3a7aSWarner Losh } 11628e3e3a7aSWarner Losh case LUA_GCISRUNNING: { 11638e3e3a7aSWarner Losh res = g->gcrunning; 11648e3e3a7aSWarner Losh break; 11658e3e3a7aSWarner Losh } 1166*0495ed39SKyle Evans case LUA_GCGEN: { 1167*0495ed39SKyle Evans int minormul = va_arg(argp, int); 1168*0495ed39SKyle Evans int majormul = va_arg(argp, int); 1169*0495ed39SKyle Evans res = isdecGCmodegen(g) ? LUA_GCGEN : LUA_GCINC; 1170*0495ed39SKyle Evans if (minormul != 0) 1171*0495ed39SKyle Evans g->genminormul = minormul; 1172*0495ed39SKyle Evans if (majormul != 0) 1173*0495ed39SKyle Evans setgcparam(g->genmajormul, majormul); 1174*0495ed39SKyle Evans luaC_changemode(L, KGC_GEN); 1175*0495ed39SKyle Evans break; 1176*0495ed39SKyle Evans } 1177*0495ed39SKyle Evans case LUA_GCINC: { 1178*0495ed39SKyle Evans int pause = va_arg(argp, int); 1179*0495ed39SKyle Evans int stepmul = va_arg(argp, int); 1180*0495ed39SKyle Evans int stepsize = va_arg(argp, int); 1181*0495ed39SKyle Evans res = isdecGCmodegen(g) ? LUA_GCGEN : LUA_GCINC; 1182*0495ed39SKyle Evans if (pause != 0) 1183*0495ed39SKyle Evans setgcparam(g->gcpause, pause); 1184*0495ed39SKyle Evans if (stepmul != 0) 1185*0495ed39SKyle Evans setgcparam(g->gcstepmul, stepmul); 1186*0495ed39SKyle Evans if (stepsize != 0) 1187*0495ed39SKyle Evans g->gcstepsize = stepsize; 1188*0495ed39SKyle Evans luaC_changemode(L, KGC_INC); 1189*0495ed39SKyle Evans break; 1190*0495ed39SKyle Evans } 11918e3e3a7aSWarner Losh default: res = -1; /* invalid option */ 11928e3e3a7aSWarner Losh } 1193*0495ed39SKyle Evans va_end(argp); 11948e3e3a7aSWarner Losh lua_unlock(L); 11958e3e3a7aSWarner Losh return res; 11968e3e3a7aSWarner Losh } 11978e3e3a7aSWarner Losh 11988e3e3a7aSWarner Losh 11998e3e3a7aSWarner Losh 12008e3e3a7aSWarner Losh /* 12018e3e3a7aSWarner Losh ** miscellaneous functions 12028e3e3a7aSWarner Losh */ 12038e3e3a7aSWarner Losh 12048e3e3a7aSWarner Losh 12058e3e3a7aSWarner Losh LUA_API int lua_error (lua_State *L) { 1206*0495ed39SKyle Evans TValue *errobj; 12078e3e3a7aSWarner Losh lua_lock(L); 1208*0495ed39SKyle Evans errobj = s2v(L->top - 1); 12098e3e3a7aSWarner Losh api_checknelems(L, 1); 1210*0495ed39SKyle Evans /* error object is the memory error message? */ 1211*0495ed39SKyle Evans if (ttisshrstring(errobj) && eqshrstr(tsvalue(errobj), G(L)->memerrmsg)) 1212*0495ed39SKyle Evans luaM_error(L); /* raise a memory error */ 1213*0495ed39SKyle Evans else 1214*0495ed39SKyle Evans luaG_errormsg(L); /* raise a regular error */ 12158e3e3a7aSWarner Losh /* code unreachable; will unlock when control actually leaves the kernel */ 12168e3e3a7aSWarner Losh return 0; /* to avoid warnings */ 12178e3e3a7aSWarner Losh } 12188e3e3a7aSWarner Losh 12198e3e3a7aSWarner Losh 12208e3e3a7aSWarner Losh LUA_API int lua_next (lua_State *L, int idx) { 1221*0495ed39SKyle Evans Table *t; 12228e3e3a7aSWarner Losh int more; 12238e3e3a7aSWarner Losh lua_lock(L); 1224*0495ed39SKyle Evans api_checknelems(L, 1); 1225*0495ed39SKyle Evans t = gettable(L, idx); 1226*0495ed39SKyle Evans more = luaH_next(L, t, L->top - 1); 12278e3e3a7aSWarner Losh if (more) { 12288e3e3a7aSWarner Losh api_incr_top(L); 12298e3e3a7aSWarner Losh } 12308e3e3a7aSWarner Losh else /* no more elements */ 12318e3e3a7aSWarner Losh L->top -= 1; /* remove key */ 12328e3e3a7aSWarner Losh lua_unlock(L); 12338e3e3a7aSWarner Losh return more; 12348e3e3a7aSWarner Losh } 12358e3e3a7aSWarner Losh 12368e3e3a7aSWarner Losh 1237*0495ed39SKyle Evans LUA_API void lua_toclose (lua_State *L, int idx) { 1238*0495ed39SKyle Evans int nresults; 1239*0495ed39SKyle Evans StkId o; 1240*0495ed39SKyle Evans lua_lock(L); 1241*0495ed39SKyle Evans o = index2stack(L, idx); 1242*0495ed39SKyle Evans nresults = L->ci->nresults; 1243*0495ed39SKyle Evans api_check(L, L->openupval == NULL || uplevel(L->openupval) <= o, 1244*0495ed39SKyle Evans "marked index below or equal new one"); 1245*0495ed39SKyle Evans luaF_newtbcupval(L, o); /* create new to-be-closed upvalue */ 1246*0495ed39SKyle Evans if (!hastocloseCfunc(nresults)) /* function not marked yet? */ 1247*0495ed39SKyle Evans L->ci->nresults = codeNresults(nresults); /* mark it */ 1248*0495ed39SKyle Evans lua_assert(hastocloseCfunc(L->ci->nresults)); 1249*0495ed39SKyle Evans lua_unlock(L); 1250*0495ed39SKyle Evans } 1251*0495ed39SKyle Evans 1252*0495ed39SKyle Evans 12538e3e3a7aSWarner Losh LUA_API void lua_concat (lua_State *L, int n) { 12548e3e3a7aSWarner Losh lua_lock(L); 12558e3e3a7aSWarner Losh api_checknelems(L, n); 1256*0495ed39SKyle Evans if (n > 0) 12578e3e3a7aSWarner Losh luaV_concat(L, n); 1258*0495ed39SKyle Evans else { /* nothing to concatenate */ 1259*0495ed39SKyle Evans setsvalue2s(L, L->top, luaS_newlstr(L, "", 0)); /* push empty string */ 12608e3e3a7aSWarner Losh api_incr_top(L); 12618e3e3a7aSWarner Losh } 12628e3e3a7aSWarner Losh luaC_checkGC(L); 12638e3e3a7aSWarner Losh lua_unlock(L); 12648e3e3a7aSWarner Losh } 12658e3e3a7aSWarner Losh 12668e3e3a7aSWarner Losh 12678e3e3a7aSWarner Losh LUA_API void lua_len (lua_State *L, int idx) { 1268*0495ed39SKyle Evans TValue *t; 12698e3e3a7aSWarner Losh lua_lock(L); 1270*0495ed39SKyle Evans t = index2value(L, idx); 12718e3e3a7aSWarner Losh luaV_objlen(L, L->top, t); 12728e3e3a7aSWarner Losh api_incr_top(L); 12738e3e3a7aSWarner Losh lua_unlock(L); 12748e3e3a7aSWarner Losh } 12758e3e3a7aSWarner Losh 12768e3e3a7aSWarner Losh 12778e3e3a7aSWarner Losh LUA_API lua_Alloc lua_getallocf (lua_State *L, void **ud) { 12788e3e3a7aSWarner Losh lua_Alloc f; 12798e3e3a7aSWarner Losh lua_lock(L); 12808e3e3a7aSWarner Losh if (ud) *ud = G(L)->ud; 12818e3e3a7aSWarner Losh f = G(L)->frealloc; 12828e3e3a7aSWarner Losh lua_unlock(L); 12838e3e3a7aSWarner Losh return f; 12848e3e3a7aSWarner Losh } 12858e3e3a7aSWarner Losh 12868e3e3a7aSWarner Losh 12878e3e3a7aSWarner Losh LUA_API void lua_setallocf (lua_State *L, lua_Alloc f, void *ud) { 12888e3e3a7aSWarner Losh lua_lock(L); 12898e3e3a7aSWarner Losh G(L)->ud = ud; 12908e3e3a7aSWarner Losh G(L)->frealloc = f; 12918e3e3a7aSWarner Losh lua_unlock(L); 12928e3e3a7aSWarner Losh } 12938e3e3a7aSWarner Losh 12948e3e3a7aSWarner Losh 1295*0495ed39SKyle Evans void lua_setwarnf (lua_State *L, lua_WarnFunction f, void *ud) { 1296*0495ed39SKyle Evans lua_lock(L); 1297*0495ed39SKyle Evans G(L)->ud_warn = ud; 1298*0495ed39SKyle Evans G(L)->warnf = f; 1299*0495ed39SKyle Evans lua_unlock(L); 1300*0495ed39SKyle Evans } 1301*0495ed39SKyle Evans 1302*0495ed39SKyle Evans 1303*0495ed39SKyle Evans void lua_warning (lua_State *L, const char *msg, int tocont) { 1304*0495ed39SKyle Evans lua_lock(L); 1305*0495ed39SKyle Evans luaE_warning(L, msg, tocont); 1306*0495ed39SKyle Evans lua_unlock(L); 1307*0495ed39SKyle Evans } 1308*0495ed39SKyle Evans 1309*0495ed39SKyle Evans 1310*0495ed39SKyle Evans 1311*0495ed39SKyle Evans LUA_API void *lua_newuserdatauv (lua_State *L, size_t size, int nuvalue) { 13128e3e3a7aSWarner Losh Udata *u; 13138e3e3a7aSWarner Losh lua_lock(L); 1314*0495ed39SKyle Evans api_check(L, 0 <= nuvalue && nuvalue < USHRT_MAX, "invalid value"); 1315*0495ed39SKyle Evans u = luaS_newudata(L, size, nuvalue); 1316*0495ed39SKyle Evans setuvalue(L, s2v(L->top), u); 13178e3e3a7aSWarner Losh api_incr_top(L); 13188e3e3a7aSWarner Losh luaC_checkGC(L); 13198e3e3a7aSWarner Losh lua_unlock(L); 13208e3e3a7aSWarner Losh return getudatamem(u); 13218e3e3a7aSWarner Losh } 13228e3e3a7aSWarner Losh 13238e3e3a7aSWarner Losh 13248e3e3a7aSWarner Losh 1325*0495ed39SKyle Evans static const char *aux_upvalue (TValue *fi, int n, TValue **val, 1326*0495ed39SKyle Evans GCObject **owner) { 1327*0495ed39SKyle Evans switch (ttypetag(fi)) { 1328*0495ed39SKyle Evans case LUA_VCCL: { /* C closure */ 13298e3e3a7aSWarner Losh CClosure *f = clCvalue(fi); 1330*0495ed39SKyle Evans if (!(cast_uint(n) - 1u < cast_uint(f->nupvalues))) 1331*0495ed39SKyle Evans return NULL; /* 'n' not in [1, f->nupvalues] */ 13328e3e3a7aSWarner Losh *val = &f->upvalue[n-1]; 1333*0495ed39SKyle Evans if (owner) *owner = obj2gco(f); 13348e3e3a7aSWarner Losh return ""; 13358e3e3a7aSWarner Losh } 1336*0495ed39SKyle Evans case LUA_VLCL: { /* Lua closure */ 13378e3e3a7aSWarner Losh LClosure *f = clLvalue(fi); 13388e3e3a7aSWarner Losh TString *name; 13398e3e3a7aSWarner Losh Proto *p = f->p; 1340*0495ed39SKyle Evans if (!(cast_uint(n) - 1u < cast_uint(p->sizeupvalues))) 1341*0495ed39SKyle Evans return NULL; /* 'n' not in [1, p->sizeupvalues] */ 13428e3e3a7aSWarner Losh *val = f->upvals[n-1]->v; 1343*0495ed39SKyle Evans if (owner) *owner = obj2gco(f->upvals[n - 1]); 13448e3e3a7aSWarner Losh name = p->upvalues[n-1].name; 1345*0495ed39SKyle Evans return (name == NULL) ? "(no name)" : getstr(name); 13468e3e3a7aSWarner Losh } 13478e3e3a7aSWarner Losh default: return NULL; /* not a closure */ 13488e3e3a7aSWarner Losh } 13498e3e3a7aSWarner Losh } 13508e3e3a7aSWarner Losh 13518e3e3a7aSWarner Losh 13528e3e3a7aSWarner Losh LUA_API const char *lua_getupvalue (lua_State *L, int funcindex, int n) { 13538e3e3a7aSWarner Losh const char *name; 13548e3e3a7aSWarner Losh TValue *val = NULL; /* to avoid warnings */ 13558e3e3a7aSWarner Losh lua_lock(L); 1356*0495ed39SKyle Evans name = aux_upvalue(index2value(L, funcindex), n, &val, NULL); 13578e3e3a7aSWarner Losh if (name) { 13588e3e3a7aSWarner Losh setobj2s(L, L->top, val); 13598e3e3a7aSWarner Losh api_incr_top(L); 13608e3e3a7aSWarner Losh } 13618e3e3a7aSWarner Losh lua_unlock(L); 13628e3e3a7aSWarner Losh return name; 13638e3e3a7aSWarner Losh } 13648e3e3a7aSWarner Losh 13658e3e3a7aSWarner Losh 13668e3e3a7aSWarner Losh LUA_API const char *lua_setupvalue (lua_State *L, int funcindex, int n) { 13678e3e3a7aSWarner Losh const char *name; 13688e3e3a7aSWarner Losh TValue *val = NULL; /* to avoid warnings */ 1369*0495ed39SKyle Evans GCObject *owner = NULL; /* to avoid warnings */ 1370*0495ed39SKyle Evans TValue *fi; 13718e3e3a7aSWarner Losh lua_lock(L); 1372*0495ed39SKyle Evans fi = index2value(L, funcindex); 13738e3e3a7aSWarner Losh api_checknelems(L, 1); 1374*0495ed39SKyle Evans name = aux_upvalue(fi, n, &val, &owner); 13758e3e3a7aSWarner Losh if (name) { 13768e3e3a7aSWarner Losh L->top--; 1377*0495ed39SKyle Evans setobj(L, val, s2v(L->top)); 1378*0495ed39SKyle Evans luaC_barrier(L, owner, val); 13798e3e3a7aSWarner Losh } 13808e3e3a7aSWarner Losh lua_unlock(L); 13818e3e3a7aSWarner Losh return name; 13828e3e3a7aSWarner Losh } 13838e3e3a7aSWarner Losh 13848e3e3a7aSWarner Losh 1385*0495ed39SKyle Evans static UpVal **getupvalref (lua_State *L, int fidx, int n, LClosure **pf) { 1386*0495ed39SKyle Evans static const UpVal *const nullup = NULL; 13878e3e3a7aSWarner Losh LClosure *f; 1388*0495ed39SKyle Evans TValue *fi = index2value(L, fidx); 13898e3e3a7aSWarner Losh api_check(L, ttisLclosure(fi), "Lua function expected"); 13908e3e3a7aSWarner Losh f = clLvalue(fi); 1391*0495ed39SKyle Evans if (pf) *pf = f; 1392*0495ed39SKyle Evans if (1 <= n && n <= f->p->sizeupvalues) 13938e3e3a7aSWarner Losh return &f->upvals[n - 1]; /* get its upvalue pointer */ 1394*0495ed39SKyle Evans else 1395*0495ed39SKyle Evans return (UpVal**)&nullup; 13968e3e3a7aSWarner Losh } 13978e3e3a7aSWarner Losh 13988e3e3a7aSWarner Losh 13998e3e3a7aSWarner Losh LUA_API void *lua_upvalueid (lua_State *L, int fidx, int n) { 1400*0495ed39SKyle Evans TValue *fi = index2value(L, fidx); 1401*0495ed39SKyle Evans switch (ttypetag(fi)) { 1402*0495ed39SKyle Evans case LUA_VLCL: { /* lua closure */ 1403*0495ed39SKyle Evans return *getupvalref(L, fidx, n, NULL); 14048e3e3a7aSWarner Losh } 1405*0495ed39SKyle Evans case LUA_VCCL: { /* C closure */ 14068e3e3a7aSWarner Losh CClosure *f = clCvalue(fi); 1407*0495ed39SKyle Evans if (1 <= n && n <= f->nupvalues) 14088e3e3a7aSWarner Losh return &f->upvalue[n - 1]; 1409*0495ed39SKyle Evans /* else */ 1410*0495ed39SKyle Evans } /* FALLTHROUGH */ 1411*0495ed39SKyle Evans case LUA_VLCF: 1412*0495ed39SKyle Evans return NULL; /* light C functions have no upvalues */ 14138e3e3a7aSWarner Losh default: { 1414*0495ed39SKyle Evans api_check(L, 0, "function expected"); 14158e3e3a7aSWarner Losh return NULL; 14168e3e3a7aSWarner Losh } 14178e3e3a7aSWarner Losh } 14188e3e3a7aSWarner Losh } 14198e3e3a7aSWarner Losh 14208e3e3a7aSWarner Losh 14218e3e3a7aSWarner Losh LUA_API void lua_upvaluejoin (lua_State *L, int fidx1, int n1, 14228e3e3a7aSWarner Losh int fidx2, int n2) { 1423*0495ed39SKyle Evans LClosure *f1; 1424*0495ed39SKyle Evans UpVal **up1 = getupvalref(L, fidx1, n1, &f1); 1425*0495ed39SKyle Evans UpVal **up2 = getupvalref(L, fidx2, n2, NULL); 1426*0495ed39SKyle Evans api_check(L, *up1 != NULL && *up2 != NULL, "invalid upvalue index"); 14278e3e3a7aSWarner Losh *up1 = *up2; 1428*0495ed39SKyle Evans luaC_objbarrier(L, f1, *up1); 14298e3e3a7aSWarner Losh } 14308e3e3a7aSWarner Losh 14318e3e3a7aSWarner Losh 1432