xref: /freebsd/contrib/lua/src/lapi.c (revision 0495ed398c4f64013bab2327eb13a303e1f90c13)
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