18e3e3a7aSWarner Losh /*
20495ed39SKyle Evans ** $Id: ldo.c $
38e3e3a7aSWarner Losh ** Stack and Call structure of Lua
48e3e3a7aSWarner Losh ** See Copyright Notice in lua.h
58e3e3a7aSWarner Losh */
68e3e3a7aSWarner Losh
78e3e3a7aSWarner Losh #define ldo_c
88e3e3a7aSWarner Losh #define LUA_CORE
98e3e3a7aSWarner Losh
108e3e3a7aSWarner Losh #include "lprefix.h"
118e3e3a7aSWarner Losh
128e3e3a7aSWarner Losh
138e3e3a7aSWarner Losh #include <setjmp.h>
148e3e3a7aSWarner Losh #include <stdlib.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 "lopcodes.h"
278e3e3a7aSWarner Losh #include "lparser.h"
288e3e3a7aSWarner Losh #include "lstate.h"
298e3e3a7aSWarner Losh #include "lstring.h"
308e3e3a7aSWarner Losh #include "ltable.h"
318e3e3a7aSWarner Losh #include "ltm.h"
328e3e3a7aSWarner Losh #include "lundump.h"
338e3e3a7aSWarner Losh #include "lvm.h"
348e3e3a7aSWarner Losh #include "lzio.h"
358e3e3a7aSWarner Losh
368e3e3a7aSWarner Losh
378e3e3a7aSWarner Losh
388e3e3a7aSWarner Losh #define errorstatus(s) ((s) > LUA_YIELD)
398e3e3a7aSWarner Losh
408e3e3a7aSWarner Losh
418e3e3a7aSWarner Losh /*
428e3e3a7aSWarner Losh ** {======================================================
438e3e3a7aSWarner Losh ** Error-recovery functions
448e3e3a7aSWarner Losh ** =======================================================
458e3e3a7aSWarner Losh */
468e3e3a7aSWarner Losh
478e3e3a7aSWarner Losh /*
488e3e3a7aSWarner Losh ** LUAI_THROW/LUAI_TRY define how Lua does exception handling. By
498e3e3a7aSWarner Losh ** default, Lua handles errors with exceptions when compiling as
508e3e3a7aSWarner Losh ** C++ code, with _longjmp/_setjmp when asked to use them, and with
518e3e3a7aSWarner Losh ** longjmp/setjmp otherwise.
528e3e3a7aSWarner Losh */
538e3e3a7aSWarner Losh #if !defined(LUAI_THROW) /* { */
548e3e3a7aSWarner Losh
558e3e3a7aSWarner Losh #if defined(__cplusplus) && !defined(LUA_USE_LONGJMP) /* { */
568e3e3a7aSWarner Losh
578e3e3a7aSWarner Losh /* C++ exceptions */
588e3e3a7aSWarner Losh #define LUAI_THROW(L,c) throw(c)
598e3e3a7aSWarner Losh #define LUAI_TRY(L,c,a) \
608e3e3a7aSWarner Losh try { a } catch(...) { if ((c)->status == 0) (c)->status = -1; }
618e3e3a7aSWarner Losh #define luai_jmpbuf int /* dummy variable */
628e3e3a7aSWarner Losh
638e3e3a7aSWarner Losh #elif defined(LUA_USE_POSIX) /* }{ */
648e3e3a7aSWarner Losh
658e3e3a7aSWarner Losh /* in POSIX, try _longjmp/_setjmp (more efficient) */
668e3e3a7aSWarner Losh #define LUAI_THROW(L,c) _longjmp((c)->b, 1)
678e3e3a7aSWarner Losh #define LUAI_TRY(L,c,a) if (_setjmp((c)->b) == 0) { a }
688e3e3a7aSWarner Losh #define luai_jmpbuf jmp_buf
698e3e3a7aSWarner Losh
708e3e3a7aSWarner Losh #else /* }{ */
718e3e3a7aSWarner Losh
728e3e3a7aSWarner Losh /* ISO C handling with long jumps */
738e3e3a7aSWarner Losh #define LUAI_THROW(L,c) longjmp((c)->b, 1)
748e3e3a7aSWarner Losh #define LUAI_TRY(L,c,a) if (setjmp((c)->b) == 0) { a }
758e3e3a7aSWarner Losh #define luai_jmpbuf jmp_buf
768e3e3a7aSWarner Losh
778e3e3a7aSWarner Losh #endif /* } */
788e3e3a7aSWarner Losh
798e3e3a7aSWarner Losh #endif /* } */
808e3e3a7aSWarner Losh
818e3e3a7aSWarner Losh
828e3e3a7aSWarner Losh
838e3e3a7aSWarner Losh /* chain list of long jump buffers */
848e3e3a7aSWarner Losh struct lua_longjmp {
858e3e3a7aSWarner Losh struct lua_longjmp *previous;
868e3e3a7aSWarner Losh luai_jmpbuf b;
878e3e3a7aSWarner Losh volatile int status; /* error code */
888e3e3a7aSWarner Losh };
898e3e3a7aSWarner Losh
908e3e3a7aSWarner Losh
luaD_seterrorobj(lua_State * L,int errcode,StkId oldtop)910495ed39SKyle Evans void luaD_seterrorobj (lua_State *L, int errcode, StkId oldtop) {
928e3e3a7aSWarner Losh switch (errcode) {
938e3e3a7aSWarner Losh case LUA_ERRMEM: { /* memory error? */
948e3e3a7aSWarner Losh setsvalue2s(L, oldtop, G(L)->memerrmsg); /* reuse preregistered msg. */
958e3e3a7aSWarner Losh break;
968e3e3a7aSWarner Losh }
978e3e3a7aSWarner Losh case LUA_ERRERR: {
988e3e3a7aSWarner Losh setsvalue2s(L, oldtop, luaS_newliteral(L, "error in error handling"));
998e3e3a7aSWarner Losh break;
1008e3e3a7aSWarner Losh }
1018c784bb8SWarner Losh case LUA_OK: { /* special case only for closing upvalues */
1020495ed39SKyle Evans setnilvalue(s2v(oldtop)); /* no error message */
1030495ed39SKyle Evans break;
1040495ed39SKyle Evans }
1058e3e3a7aSWarner Losh default: {
1068c784bb8SWarner Losh lua_assert(errorstatus(errcode)); /* real error */
107*a9490b81SWarner Losh setobjs2s(L, oldtop, L->top.p - 1); /* error message on current top */
1088e3e3a7aSWarner Losh break;
1098e3e3a7aSWarner Losh }
1108e3e3a7aSWarner Losh }
111*a9490b81SWarner Losh L->top.p = oldtop + 1;
1128e3e3a7aSWarner Losh }
1138e3e3a7aSWarner Losh
1148e3e3a7aSWarner Losh
luaD_throw(lua_State * L,int errcode)1158e3e3a7aSWarner Losh l_noret luaD_throw (lua_State *L, int errcode) {
1168e3e3a7aSWarner Losh if (L->errorJmp) { /* thread has an error handler? */
1178e3e3a7aSWarner Losh L->errorJmp->status = errcode; /* set status */
1188e3e3a7aSWarner Losh LUAI_THROW(L, L->errorJmp); /* jump to it */
1198e3e3a7aSWarner Losh }
1208e3e3a7aSWarner Losh else { /* thread has no error handler */
1218e3e3a7aSWarner Losh global_State *g = G(L);
1228c784bb8SWarner Losh errcode = luaE_resetthread(L, errcode); /* close all upvalues */
1238e3e3a7aSWarner Losh if (g->mainthread->errorJmp) { /* main thread has a handler? */
124*a9490b81SWarner Losh setobjs2s(L, g->mainthread->top.p++, L->top.p - 1); /* copy error obj. */
1258e3e3a7aSWarner Losh luaD_throw(g->mainthread, errcode); /* re-throw in main thread */
1268e3e3a7aSWarner Losh }
1278e3e3a7aSWarner Losh else { /* no handler at all; abort */
1288e3e3a7aSWarner Losh if (g->panic) { /* panic function? */
1298e3e3a7aSWarner Losh lua_unlock(L);
1308e3e3a7aSWarner Losh g->panic(L); /* call panic function (last chance to jump out) */
1318e3e3a7aSWarner Losh }
1328e3e3a7aSWarner Losh abort();
1338e3e3a7aSWarner Losh }
1348e3e3a7aSWarner Losh }
1358e3e3a7aSWarner Losh }
1368e3e3a7aSWarner Losh
1378e3e3a7aSWarner Losh
luaD_rawrunprotected(lua_State * L,Pfunc f,void * ud)1388e3e3a7aSWarner Losh int luaD_rawrunprotected (lua_State *L, Pfunc f, void *ud) {
1390495ed39SKyle Evans l_uint32 oldnCcalls = L->nCcalls;
1408e3e3a7aSWarner Losh struct lua_longjmp lj;
1418e3e3a7aSWarner Losh lj.status = LUA_OK;
1428e3e3a7aSWarner Losh lj.previous = L->errorJmp; /* chain new error handler */
1438e3e3a7aSWarner Losh L->errorJmp = &lj;
1448e3e3a7aSWarner Losh LUAI_TRY(L, &lj,
1458e3e3a7aSWarner Losh (*f)(L, ud);
1468e3e3a7aSWarner Losh );
1478e3e3a7aSWarner Losh L->errorJmp = lj.previous; /* restore old error handler */
1488e3e3a7aSWarner Losh L->nCcalls = oldnCcalls;
1498e3e3a7aSWarner Losh return lj.status;
1508e3e3a7aSWarner Losh }
1518e3e3a7aSWarner Losh
1528e3e3a7aSWarner Losh /* }====================================================== */
1538e3e3a7aSWarner Losh
1548e3e3a7aSWarner Losh
1558e3e3a7aSWarner Losh /*
1568e3e3a7aSWarner Losh ** {==================================================================
1578e3e3a7aSWarner Losh ** Stack reallocation
1588e3e3a7aSWarner Losh ** ===================================================================
1598e3e3a7aSWarner Losh */
160*a9490b81SWarner Losh
161*a9490b81SWarner Losh
162*a9490b81SWarner Losh /*
163*a9490b81SWarner Losh ** Change all pointers to the stack into offsets.
164*a9490b81SWarner Losh */
relstack(lua_State * L)165*a9490b81SWarner Losh static void relstack (lua_State *L) {
1668e3e3a7aSWarner Losh CallInfo *ci;
1678e3e3a7aSWarner Losh UpVal *up;
168*a9490b81SWarner Losh L->top.offset = savestack(L, L->top.p);
169*a9490b81SWarner Losh L->tbclist.offset = savestack(L, L->tbclist.p);
1708e3e3a7aSWarner Losh for (up = L->openupval; up != NULL; up = up->u.open.next)
171*a9490b81SWarner Losh up->v.offset = savestack(L, uplevel(up));
1728e3e3a7aSWarner Losh for (ci = L->ci; ci != NULL; ci = ci->previous) {
173*a9490b81SWarner Losh ci->top.offset = savestack(L, ci->top.p);
174*a9490b81SWarner Losh ci->func.offset = savestack(L, ci->func.p);
175*a9490b81SWarner Losh }
176*a9490b81SWarner Losh }
177*a9490b81SWarner Losh
178*a9490b81SWarner Losh
179*a9490b81SWarner Losh /*
180*a9490b81SWarner Losh ** Change back all offsets into pointers.
181*a9490b81SWarner Losh */
correctstack(lua_State * L)182*a9490b81SWarner Losh static void correctstack (lua_State *L) {
183*a9490b81SWarner Losh CallInfo *ci;
184*a9490b81SWarner Losh UpVal *up;
185*a9490b81SWarner Losh L->top.p = restorestack(L, L->top.offset);
186*a9490b81SWarner Losh L->tbclist.p = restorestack(L, L->tbclist.offset);
187*a9490b81SWarner Losh for (up = L->openupval; up != NULL; up = up->u.open.next)
188*a9490b81SWarner Losh up->v.p = s2v(restorestack(L, up->v.offset));
189*a9490b81SWarner Losh for (ci = L->ci; ci != NULL; ci = ci->previous) {
190*a9490b81SWarner Losh ci->top.p = restorestack(L, ci->top.offset);
191*a9490b81SWarner Losh ci->func.p = restorestack(L, ci->func.offset);
1928e3e3a7aSWarner Losh if (isLua(ci))
1930495ed39SKyle Evans ci->u.l.trap = 1; /* signal to update 'trap' in 'luaV_execute' */
1948e3e3a7aSWarner Losh }
1958e3e3a7aSWarner Losh }
1968e3e3a7aSWarner Losh
1978e3e3a7aSWarner Losh
1988e3e3a7aSWarner Losh /* some space for error handling */
1998e3e3a7aSWarner Losh #define ERRORSTACKSIZE (LUAI_MAXSTACK + 200)
2008e3e3a7aSWarner Losh
2018c784bb8SWarner Losh /*
202*a9490b81SWarner Losh ** Reallocate the stack to a new size, correcting all pointers into it.
203*a9490b81SWarner Losh ** In ISO C, any pointer use after the pointer has been deallocated is
204*a9490b81SWarner Losh ** undefined behavior. So, before the reallocation, all pointers are
205*a9490b81SWarner Losh ** changed to offsets, and after the reallocation they are changed back
206*a9490b81SWarner Losh ** to pointers. As during the reallocation the pointers are invalid, the
207*a9490b81SWarner Losh ** reallocation cannot run emergency collections.
208*a9490b81SWarner Losh **
2098c784bb8SWarner Losh ** In case of allocation error, raise an error or return false according
2108c784bb8SWarner Losh ** to 'raiseerror'.
2118c784bb8SWarner Losh */
luaD_reallocstack(lua_State * L,int newsize,int raiseerror)2120495ed39SKyle Evans int luaD_reallocstack (lua_State *L, int newsize, int raiseerror) {
2138c784bb8SWarner Losh int oldsize = stacksize(L);
2148c784bb8SWarner Losh int i;
215*a9490b81SWarner Losh StkId newstack;
216*a9490b81SWarner Losh int oldgcstop = G(L)->gcstopem;
2178e3e3a7aSWarner Losh lua_assert(newsize <= LUAI_MAXSTACK || newsize == ERRORSTACKSIZE);
218*a9490b81SWarner Losh relstack(L); /* change pointers to offsets */
219*a9490b81SWarner Losh G(L)->gcstopem = 1; /* stop emergency collection */
220*a9490b81SWarner Losh newstack = luaM_reallocvector(L, L->stack.p, oldsize + EXTRA_STACK,
221*a9490b81SWarner Losh newsize + EXTRA_STACK, StackValue);
222*a9490b81SWarner Losh G(L)->gcstopem = oldgcstop; /* restore emergency collection */
2238c784bb8SWarner Losh if (l_unlikely(newstack == NULL)) { /* reallocation failed? */
224*a9490b81SWarner Losh correctstack(L); /* change offsets back to pointers */
2250495ed39SKyle Evans if (raiseerror)
2260495ed39SKyle Evans luaM_error(L);
2270495ed39SKyle Evans else return 0; /* do not raise an error */
2280495ed39SKyle Evans }
229*a9490b81SWarner Losh L->stack.p = newstack;
230*a9490b81SWarner Losh correctstack(L); /* change offsets back to pointers */
231*a9490b81SWarner Losh L->stack_last.p = L->stack.p + newsize;
232*a9490b81SWarner Losh for (i = oldsize + EXTRA_STACK; i < newsize + EXTRA_STACK; i++)
2338c784bb8SWarner Losh setnilvalue(s2v(newstack + i)); /* erase new segment */
2340495ed39SKyle Evans return 1;
2358e3e3a7aSWarner Losh }
2368e3e3a7aSWarner Losh
2378e3e3a7aSWarner Losh
2380495ed39SKyle Evans /*
239*a9490b81SWarner Losh ** Try to grow the stack by at least 'n' elements. When 'raiseerror'
2400495ed39SKyle Evans ** is true, raises any error; otherwise, return 0 in case of errors.
2410495ed39SKyle Evans */
luaD_growstack(lua_State * L,int n,int raiseerror)2420495ed39SKyle Evans int luaD_growstack (lua_State *L, int n, int raiseerror) {
2430495ed39SKyle Evans int size = stacksize(L);
2448c784bb8SWarner Losh if (l_unlikely(size > LUAI_MAXSTACK)) {
2450495ed39SKyle Evans /* if stack is larger than maximum, thread is already using the
2460495ed39SKyle Evans extra space reserved for errors, that is, thread is handling
2470495ed39SKyle Evans a stack error; cannot grow further than that. */
2480495ed39SKyle Evans lua_assert(stacksize(L) == ERRORSTACKSIZE);
2490495ed39SKyle Evans if (raiseerror)
2500495ed39SKyle Evans luaD_throw(L, LUA_ERRERR); /* error inside message handler */
2510495ed39SKyle Evans return 0; /* if not 'raiseerror', just signal it */
2520495ed39SKyle Evans }
253*a9490b81SWarner Losh else if (n < LUAI_MAXSTACK) { /* avoids arithmetic overflows */
2540495ed39SKyle Evans int newsize = 2 * size; /* tentative new size */
255*a9490b81SWarner Losh int needed = cast_int(L->top.p - L->stack.p) + n;
2560495ed39SKyle Evans if (newsize > LUAI_MAXSTACK) /* cannot cross the limit */
2570495ed39SKyle Evans newsize = LUAI_MAXSTACK;
2580495ed39SKyle Evans if (newsize < needed) /* but must respect what was asked for */
2590495ed39SKyle Evans newsize = needed;
2608c784bb8SWarner Losh if (l_likely(newsize <= LUAI_MAXSTACK))
2610495ed39SKyle Evans return luaD_reallocstack(L, newsize, raiseerror);
262*a9490b81SWarner Losh }
263*a9490b81SWarner Losh /* else stack overflow */
2640495ed39SKyle Evans /* add extra size to be able to handle the error message */
2650495ed39SKyle Evans luaD_reallocstack(L, ERRORSTACKSIZE, raiseerror);
2660495ed39SKyle Evans if (raiseerror)
2678e3e3a7aSWarner Losh luaG_runerror(L, "stack overflow");
2680495ed39SKyle Evans return 0;
2698e3e3a7aSWarner Losh }
2708e3e3a7aSWarner Losh
2718e3e3a7aSWarner Losh
272*a9490b81SWarner Losh /*
273*a9490b81SWarner Losh ** Compute how much of the stack is being used, by computing the
274*a9490b81SWarner Losh ** maximum top of all call frames in the stack and the current top.
275*a9490b81SWarner Losh */
stackinuse(lua_State * L)2768e3e3a7aSWarner Losh static int stackinuse (lua_State *L) {
2778e3e3a7aSWarner Losh CallInfo *ci;
2780495ed39SKyle Evans int res;
279*a9490b81SWarner Losh StkId lim = L->top.p;
2808e3e3a7aSWarner Losh for (ci = L->ci; ci != NULL; ci = ci->previous) {
281*a9490b81SWarner Losh if (lim < ci->top.p) lim = ci->top.p;
2828e3e3a7aSWarner Losh }
283*a9490b81SWarner Losh lua_assert(lim <= L->stack_last.p + EXTRA_STACK);
284*a9490b81SWarner Losh res = cast_int(lim - L->stack.p) + 1; /* part of stack in use */
2850495ed39SKyle Evans if (res < LUA_MINSTACK)
2860495ed39SKyle Evans res = LUA_MINSTACK; /* ensure a minimum size */
2870495ed39SKyle Evans return res;
2888e3e3a7aSWarner Losh }
2898e3e3a7aSWarner Losh
2908e3e3a7aSWarner Losh
2910495ed39SKyle Evans /*
2920495ed39SKyle Evans ** If stack size is more than 3 times the current use, reduce that size
2930495ed39SKyle Evans ** to twice the current use. (So, the final stack size is at most 2/3 the
2940495ed39SKyle Evans ** previous size, and half of its entries are empty.)
2950495ed39SKyle Evans ** As a particular case, if stack was handling a stack overflow and now
2960495ed39SKyle Evans ** it is not, 'max' (limited by LUAI_MAXSTACK) will be smaller than
2970495ed39SKyle Evans ** stacksize (equal to ERRORSTACKSIZE in this case), and so the stack
2980495ed39SKyle Evans ** will be reduced to a "regular" size.
2990495ed39SKyle Evans */
luaD_shrinkstack(lua_State * L)3008e3e3a7aSWarner Losh void luaD_shrinkstack (lua_State *L) {
3018e3e3a7aSWarner Losh int inuse = stackinuse(L);
302*a9490b81SWarner Losh int max = (inuse > LUAI_MAXSTACK / 3) ? LUAI_MAXSTACK : inuse * 3;
3038e3e3a7aSWarner Losh /* if thread is currently not handling a stack overflow and its
3040495ed39SKyle Evans size is larger than maximum "reasonable" size, shrink it */
305*a9490b81SWarner Losh if (inuse <= LUAI_MAXSTACK && stacksize(L) > max) {
306*a9490b81SWarner Losh int nsize = (inuse > LUAI_MAXSTACK / 2) ? LUAI_MAXSTACK : inuse * 2;
3070495ed39SKyle Evans luaD_reallocstack(L, nsize, 0); /* ok if that fails */
308*a9490b81SWarner Losh }
3098e3e3a7aSWarner Losh else /* don't change stack */
3108e3e3a7aSWarner Losh condmovestack(L,{},{}); /* (change only for debugging) */
3110495ed39SKyle Evans luaE_shrinkCI(L); /* shrink CI list */
3128e3e3a7aSWarner Losh }
3138e3e3a7aSWarner Losh
3148e3e3a7aSWarner Losh
luaD_inctop(lua_State * L)3158e3e3a7aSWarner Losh void luaD_inctop (lua_State *L) {
3168e3e3a7aSWarner Losh luaD_checkstack(L, 1);
317*a9490b81SWarner Losh L->top.p++;
3188e3e3a7aSWarner Losh }
3198e3e3a7aSWarner Losh
3208e3e3a7aSWarner Losh /* }================================================================== */
3218e3e3a7aSWarner Losh
3228e3e3a7aSWarner Losh
3238e3e3a7aSWarner Losh /*
3248e3e3a7aSWarner Losh ** Call a hook for the given event. Make sure there is a hook to be
3250495ed39SKyle Evans ** called. (Both 'L->hook' and 'L->hookmask', which trigger this
3268e3e3a7aSWarner Losh ** function, can be changed asynchronously by signals.)
3278e3e3a7aSWarner Losh */
luaD_hook(lua_State * L,int event,int line,int ftransfer,int ntransfer)3280495ed39SKyle Evans void luaD_hook (lua_State *L, int event, int line,
3290495ed39SKyle Evans int ftransfer, int ntransfer) {
3308e3e3a7aSWarner Losh lua_Hook hook = L->hook;
3318e3e3a7aSWarner Losh if (hook && L->allowhook) { /* make sure there is a hook */
3320495ed39SKyle Evans int mask = CIST_HOOKED;
3338e3e3a7aSWarner Losh CallInfo *ci = L->ci;
334*a9490b81SWarner Losh ptrdiff_t top = savestack(L, L->top.p); /* preserve original 'top' */
335*a9490b81SWarner Losh ptrdiff_t ci_top = savestack(L, ci->top.p); /* idem for 'ci->top' */
3368e3e3a7aSWarner Losh lua_Debug ar;
3378e3e3a7aSWarner Losh ar.event = event;
3388e3e3a7aSWarner Losh ar.currentline = line;
3398e3e3a7aSWarner Losh ar.i_ci = ci;
3400495ed39SKyle Evans if (ntransfer != 0) {
3410495ed39SKyle Evans mask |= CIST_TRAN; /* 'ci' has transfer information */
3420495ed39SKyle Evans ci->u2.transferinfo.ftransfer = ftransfer;
3430495ed39SKyle Evans ci->u2.transferinfo.ntransfer = ntransfer;
3440495ed39SKyle Evans }
345*a9490b81SWarner Losh if (isLua(ci) && L->top.p < ci->top.p)
346*a9490b81SWarner Losh L->top.p = ci->top.p; /* protect entire activation register */
3478e3e3a7aSWarner Losh luaD_checkstack(L, LUA_MINSTACK); /* ensure minimum stack size */
348*a9490b81SWarner Losh if (ci->top.p < L->top.p + LUA_MINSTACK)
349*a9490b81SWarner Losh ci->top.p = L->top.p + LUA_MINSTACK;
3508e3e3a7aSWarner Losh L->allowhook = 0; /* cannot call hooks inside a hook */
3510495ed39SKyle Evans ci->callstatus |= mask;
3528e3e3a7aSWarner Losh lua_unlock(L);
3538e3e3a7aSWarner Losh (*hook)(L, &ar);
3548e3e3a7aSWarner Losh lua_lock(L);
3558e3e3a7aSWarner Losh lua_assert(!L->allowhook);
3568e3e3a7aSWarner Losh L->allowhook = 1;
357*a9490b81SWarner Losh ci->top.p = restorestack(L, ci_top);
358*a9490b81SWarner Losh L->top.p = restorestack(L, top);
3590495ed39SKyle Evans ci->callstatus &= ~mask;
3608e3e3a7aSWarner Losh }
3618e3e3a7aSWarner Losh }
3628e3e3a7aSWarner Losh
3638e3e3a7aSWarner Losh
3648e3e3a7aSWarner Losh /*
3650495ed39SKyle Evans ** Executes a call hook for Lua functions. This function is called
3660495ed39SKyle Evans ** whenever 'hookmask' is not zero, so it checks whether call hooks are
3670495ed39SKyle Evans ** active.
3688e3e3a7aSWarner Losh */
luaD_hookcall(lua_State * L,CallInfo * ci)3690495ed39SKyle Evans void luaD_hookcall (lua_State *L, CallInfo *ci) {
3708c784bb8SWarner Losh L->oldpc = 0; /* set 'oldpc' for new function */
3718c784bb8SWarner Losh if (L->hookmask & LUA_MASKCALL) { /* is call hook on? */
3728c784bb8SWarner Losh int event = (ci->callstatus & CIST_TAIL) ? LUA_HOOKTAILCALL
3738c784bb8SWarner Losh : LUA_HOOKCALL;
3748c784bb8SWarner Losh Proto *p = ci_func(ci)->p;
3750495ed39SKyle Evans ci->u.l.savedpc++; /* hooks assume 'pc' is already incremented */
3768c784bb8SWarner Losh luaD_hook(L, event, -1, 1, p->numparams);
3770495ed39SKyle Evans ci->u.l.savedpc--; /* correct 'pc' */
3780495ed39SKyle Evans }
3798c784bb8SWarner Losh }
3800495ed39SKyle Evans
3810495ed39SKyle Evans
3828c784bb8SWarner Losh /*
3838c784bb8SWarner Losh ** Executes a return hook for Lua and C functions and sets/corrects
3848c784bb8SWarner Losh ** 'oldpc'. (Note that this correction is needed by the line hook, so it
3858c784bb8SWarner Losh ** is done even when return hooks are off.)
3868c784bb8SWarner Losh */
rethook(lua_State * L,CallInfo * ci,int nres)3878c784bb8SWarner Losh static void rethook (lua_State *L, CallInfo *ci, int nres) {
3888c784bb8SWarner Losh if (L->hookmask & LUA_MASKRET) { /* is return hook on? */
389*a9490b81SWarner Losh StkId firstres = L->top.p - nres; /* index of first result */
3908c784bb8SWarner Losh int delta = 0; /* correction for vararg functions */
3918c784bb8SWarner Losh int ftransfer;
3928c784bb8SWarner Losh if (isLua(ci)) {
3930495ed39SKyle Evans Proto *p = ci_func(ci)->p;
3940495ed39SKyle Evans if (p->is_vararg)
3950495ed39SKyle Evans delta = ci->u.l.nextraargs + p->numparams + 1;
3960495ed39SKyle Evans }
397*a9490b81SWarner Losh ci->func.p += delta; /* if vararg, back to virtual 'func' */
398*a9490b81SWarner Losh ftransfer = cast(unsigned short, firstres - ci->func.p);
3990495ed39SKyle Evans luaD_hook(L, LUA_HOOKRET, -1, ftransfer, nres); /* call it */
400*a9490b81SWarner Losh ci->func.p -= delta;
4010495ed39SKyle Evans }
4020495ed39SKyle Evans if (isLua(ci = ci->previous))
4038c784bb8SWarner Losh L->oldpc = pcRel(ci->u.l.savedpc, ci_func(ci)->p); /* set 'oldpc' */
4040495ed39SKyle Evans }
4050495ed39SKyle Evans
4060495ed39SKyle Evans
4070495ed39SKyle Evans /*
4080495ed39SKyle Evans ** Check whether 'func' has a '__call' metafield. If so, put it in the
4090495ed39SKyle Evans ** stack, below original 'func', so that 'luaD_precall' can call it. Raise
4100495ed39SKyle Evans ** an error if there is no '__call' metafield.
4110495ed39SKyle Evans */
luaD_tryfuncTM(lua_State * L,StkId func)4128c784bb8SWarner Losh StkId luaD_tryfuncTM (lua_State *L, StkId func) {
4138c784bb8SWarner Losh const TValue *tm;
4148e3e3a7aSWarner Losh StkId p;
4158c784bb8SWarner Losh checkstackGCp(L, 1, func); /* space for metamethod */
4168c784bb8SWarner Losh tm = luaT_gettmbyobj(L, s2v(func), TM_CALL); /* (after previous GC) */
4178c784bb8SWarner Losh if (l_unlikely(ttisnil(tm)))
4188c784bb8SWarner Losh luaG_callerror(L, s2v(func)); /* nothing to call */
419*a9490b81SWarner Losh for (p = L->top.p; p > func; p--) /* open space for metamethod */
4208e3e3a7aSWarner Losh setobjs2s(L, p, p-1);
421*a9490b81SWarner Losh L->top.p++; /* stack space pre-allocated by the caller */
4220495ed39SKyle Evans setobj2s(L, func, tm); /* metamethod is the new function to be called */
4238c784bb8SWarner Losh return func;
4248e3e3a7aSWarner Losh }
4258e3e3a7aSWarner Losh
4268e3e3a7aSWarner Losh
4278e3e3a7aSWarner Losh /*
4288e3e3a7aSWarner Losh ** Given 'nres' results at 'firstResult', move 'wanted' of them to 'res'.
4298e3e3a7aSWarner Losh ** Handle most typical cases (zero results for commands, one result for
4308e3e3a7aSWarner Losh ** expressions, multiple results for tail calls/single parameters)
4318e3e3a7aSWarner Losh ** separated.
4328e3e3a7aSWarner Losh */
moveresults(lua_State * L,StkId res,int nres,int wanted)4338c784bb8SWarner Losh l_sinline void moveresults (lua_State *L, StkId res, int nres, int wanted) {
4340495ed39SKyle Evans StkId firstresult;
4350495ed39SKyle Evans int i;
4368e3e3a7aSWarner Losh switch (wanted) { /* handle typical cases separately */
4370495ed39SKyle Evans case 0: /* no values needed */
438*a9490b81SWarner Losh L->top.p = res;
4390495ed39SKyle Evans return;
4400495ed39SKyle Evans case 1: /* one value needed */
4418e3e3a7aSWarner Losh if (nres == 0) /* no results? */
4420495ed39SKyle Evans setnilvalue(s2v(res)); /* adjust with nil */
4438c784bb8SWarner Losh else /* at least one result */
444*a9490b81SWarner Losh setobjs2s(L, res, L->top.p - nres); /* move it to proper place */
445*a9490b81SWarner Losh L->top.p = res + 1;
4460495ed39SKyle Evans return;
4470495ed39SKyle Evans case LUA_MULTRET:
4480495ed39SKyle Evans wanted = nres; /* we want all results */
4490495ed39SKyle Evans break;
4508c784bb8SWarner Losh default: /* two/more results and/or to-be-closed variables */
4510495ed39SKyle Evans if (hastocloseCfunc(wanted)) { /* to-be-closed variables? */
4528c784bb8SWarner Losh L->ci->callstatus |= CIST_CLSRET; /* in case of yields */
4538c784bb8SWarner Losh L->ci->u2.nres = nres;
454*a9490b81SWarner Losh res = luaF_close(L, res, CLOSEKTOP, 1);
4558c784bb8SWarner Losh L->ci->callstatus &= ~CIST_CLSRET;
456*a9490b81SWarner Losh if (L->hookmask) { /* if needed, call hook after '__close's */
457*a9490b81SWarner Losh ptrdiff_t savedres = savestack(L, res);
4588c784bb8SWarner Losh rethook(L, L->ci, nres);
459*a9490b81SWarner Losh res = restorestack(L, savedres); /* hook can move stack */
460*a9490b81SWarner Losh }
4618c784bb8SWarner Losh wanted = decodeNresults(wanted);
4620495ed39SKyle Evans if (wanted == LUA_MULTRET)
4638c784bb8SWarner Losh wanted = nres; /* we want all results */
4640495ed39SKyle Evans }
4658e3e3a7aSWarner Losh break;
4668e3e3a7aSWarner Losh }
4678c784bb8SWarner Losh /* generic case */
468*a9490b81SWarner Losh firstresult = L->top.p - nres; /* index of first result */
4698c784bb8SWarner Losh if (nres > wanted) /* extra results? */
4708c784bb8SWarner Losh nres = wanted; /* don't need them */
4718c784bb8SWarner Losh for (i = 0; i < nres; i++) /* move all results to correct place */
4720495ed39SKyle Evans setobjs2s(L, res + i, firstresult + i);
4738e3e3a7aSWarner Losh for (; i < wanted; i++) /* complete wanted number of results */
4740495ed39SKyle Evans setnilvalue(s2v(res + i));
475*a9490b81SWarner Losh L->top.p = res + wanted; /* top points after the last result */
4768e3e3a7aSWarner Losh }
4778e3e3a7aSWarner Losh
4788e3e3a7aSWarner Losh
4798e3e3a7aSWarner Losh /*
4808c784bb8SWarner Losh ** Finishes a function call: calls hook if necessary, moves current
4818c784bb8SWarner Losh ** number of results to proper place, and returns to previous call
4828c784bb8SWarner Losh ** info. If function has to close variables, hook must be called after
4838c784bb8SWarner Losh ** that.
4848e3e3a7aSWarner Losh */
luaD_poscall(lua_State * L,CallInfo * ci,int nres)4850495ed39SKyle Evans void luaD_poscall (lua_State *L, CallInfo *ci, int nres) {
4868c784bb8SWarner Losh int wanted = ci->nresults;
4878c784bb8SWarner Losh if (l_unlikely(L->hookmask && !hastocloseCfunc(wanted)))
4888c784bb8SWarner Losh rethook(L, ci, nres);
4898e3e3a7aSWarner Losh /* move results to proper place */
490*a9490b81SWarner Losh moveresults(L, ci->func.p, nres, wanted);
4918c784bb8SWarner Losh /* function cannot be in any of these cases when returning */
4928c784bb8SWarner Losh lua_assert(!(ci->callstatus &
4938c784bb8SWarner Losh (CIST_HOOKED | CIST_YPCALL | CIST_FIN | CIST_TRAN | CIST_CLSRET)));
4948c784bb8SWarner Losh L->ci = ci->previous; /* back to caller (after closing variables) */
4958e3e3a7aSWarner Losh }
4968e3e3a7aSWarner Losh
4978e3e3a7aSWarner Losh
4988e3e3a7aSWarner Losh
4990495ed39SKyle Evans #define next_ci(L) (L->ci->next ? L->ci->next : luaE_extendCI(L))
5008e3e3a7aSWarner Losh
5018e3e3a7aSWarner Losh
prepCallInfo(lua_State * L,StkId func,int nret,int mask,StkId top)5028c784bb8SWarner Losh l_sinline CallInfo *prepCallInfo (lua_State *L, StkId func, int nret,
5038c784bb8SWarner Losh int mask, StkId top) {
5048c784bb8SWarner Losh CallInfo *ci = L->ci = next_ci(L); /* new frame */
505*a9490b81SWarner Losh ci->func.p = func;
5068c784bb8SWarner Losh ci->nresults = nret;
5078c784bb8SWarner Losh ci->callstatus = mask;
508*a9490b81SWarner Losh ci->top.p = top;
5098c784bb8SWarner Losh return ci;
5108c784bb8SWarner Losh }
5118c784bb8SWarner Losh
5128c784bb8SWarner Losh
5138c784bb8SWarner Losh /*
5148c784bb8SWarner Losh ** precall for C functions
5158c784bb8SWarner Losh */
precallC(lua_State * L,StkId func,int nresults,lua_CFunction f)5168c784bb8SWarner Losh l_sinline int precallC (lua_State *L, StkId func, int nresults,
5178c784bb8SWarner Losh lua_CFunction f) {
5188c784bb8SWarner Losh int n; /* number of returns */
5198c784bb8SWarner Losh CallInfo *ci;
5208c784bb8SWarner Losh checkstackGCp(L, LUA_MINSTACK, func); /* ensure minimum stack size */
5218c784bb8SWarner Losh L->ci = ci = prepCallInfo(L, func, nresults, CIST_C,
522*a9490b81SWarner Losh L->top.p + LUA_MINSTACK);
523*a9490b81SWarner Losh lua_assert(ci->top.p <= L->stack_last.p);
5248c784bb8SWarner Losh if (l_unlikely(L->hookmask & LUA_MASKCALL)) {
525*a9490b81SWarner Losh int narg = cast_int(L->top.p - func) - 1;
5268c784bb8SWarner Losh luaD_hook(L, LUA_HOOKCALL, -1, 1, narg);
5278c784bb8SWarner Losh }
5288c784bb8SWarner Losh lua_unlock(L);
5298c784bb8SWarner Losh n = (*f)(L); /* do the actual call */
5308c784bb8SWarner Losh lua_lock(L);
5318c784bb8SWarner Losh api_checknelems(L, n);
5328c784bb8SWarner Losh luaD_poscall(L, ci, n);
5338c784bb8SWarner Losh return n;
5348c784bb8SWarner Losh }
5358c784bb8SWarner Losh
5368c784bb8SWarner Losh
5378e3e3a7aSWarner Losh /*
5380495ed39SKyle Evans ** Prepare a function for a tail call, building its call info on top
5390495ed39SKyle Evans ** of the current call info. 'narg1' is the number of arguments plus 1
5408c784bb8SWarner Losh ** (so that it includes the function itself). Return the number of
5418c784bb8SWarner Losh ** results, if it was a C function, or -1 for a Lua function.
5428e3e3a7aSWarner Losh */
luaD_pretailcall(lua_State * L,CallInfo * ci,StkId func,int narg1,int delta)5438c784bb8SWarner Losh int luaD_pretailcall (lua_State *L, CallInfo *ci, StkId func,
5448c784bb8SWarner Losh int narg1, int delta) {
5458c784bb8SWarner Losh retry:
5468c784bb8SWarner Losh switch (ttypetag(s2v(func))) {
5478c784bb8SWarner Losh case LUA_VCCL: /* C closure */
5488c784bb8SWarner Losh return precallC(L, func, LUA_MULTRET, clCvalue(s2v(func))->f);
5498c784bb8SWarner Losh case LUA_VLCF: /* light C function */
5508c784bb8SWarner Losh return precallC(L, func, LUA_MULTRET, fvalue(s2v(func)));
5518c784bb8SWarner Losh case LUA_VLCL: { /* Lua function */
5520495ed39SKyle Evans Proto *p = clLvalue(s2v(func))->p;
5530495ed39SKyle Evans int fsize = p->maxstacksize; /* frame size */
5540495ed39SKyle Evans int nfixparams = p->numparams;
5550495ed39SKyle Evans int i;
5568c784bb8SWarner Losh checkstackGCp(L, fsize - delta, func);
557*a9490b81SWarner Losh ci->func.p -= delta; /* restore 'func' (if vararg) */
5580495ed39SKyle Evans for (i = 0; i < narg1; i++) /* move down function and arguments */
559*a9490b81SWarner Losh setobjs2s(L, ci->func.p + i, func + i);
560*a9490b81SWarner Losh func = ci->func.p; /* moved-down function */
5610495ed39SKyle Evans for (; narg1 <= nfixparams; narg1++)
5620495ed39SKyle Evans setnilvalue(s2v(func + narg1)); /* complete missing arguments */
563*a9490b81SWarner Losh ci->top.p = func + 1 + fsize; /* top for new function */
564*a9490b81SWarner Losh lua_assert(ci->top.p <= L->stack_last.p);
5650495ed39SKyle Evans ci->u.l.savedpc = p->code; /* starting point */
5660495ed39SKyle Evans ci->callstatus |= CIST_TAIL;
567*a9490b81SWarner Losh L->top.p = func + narg1; /* set top */
5688c784bb8SWarner Losh return -1;
5698c784bb8SWarner Losh }
5708c784bb8SWarner Losh default: { /* not a function */
5718c784bb8SWarner Losh func = luaD_tryfuncTM(L, func); /* try to get '__call' metamethod */
5728c784bb8SWarner Losh /* return luaD_pretailcall(L, ci, func, narg1 + 1, delta); */
5738c784bb8SWarner Losh narg1++;
5748c784bb8SWarner Losh goto retry; /* try again */
5758c784bb8SWarner Losh }
5768c784bb8SWarner Losh }
5770495ed39SKyle Evans }
5780495ed39SKyle Evans
5790495ed39SKyle Evans
5800495ed39SKyle Evans /*
5810495ed39SKyle Evans ** Prepares the call to a function (C or Lua). For C functions, also do
5820495ed39SKyle Evans ** the call. The function to be called is at '*func'. The arguments
5830495ed39SKyle Evans ** are on the stack, right after the function. Returns the CallInfo
5840495ed39SKyle Evans ** to be executed, if it was a Lua function. Otherwise (a C function)
5850495ed39SKyle Evans ** returns NULL, with all the results on the stack, starting at the
5860495ed39SKyle Evans ** original function position.
5870495ed39SKyle Evans */
luaD_precall(lua_State * L,StkId func,int nresults)5880495ed39SKyle Evans CallInfo *luaD_precall (lua_State *L, StkId func, int nresults) {
5890495ed39SKyle Evans retry:
5900495ed39SKyle Evans switch (ttypetag(s2v(func))) {
5910495ed39SKyle Evans case LUA_VCCL: /* C closure */
5928c784bb8SWarner Losh precallC(L, func, nresults, clCvalue(s2v(func))->f);
5930495ed39SKyle Evans return NULL;
5948c784bb8SWarner Losh case LUA_VLCF: /* light C function */
5958c784bb8SWarner Losh precallC(L, func, nresults, fvalue(s2v(func)));
5968c784bb8SWarner Losh return NULL;
5970495ed39SKyle Evans case LUA_VLCL: { /* Lua function */
5980495ed39SKyle Evans CallInfo *ci;
5990495ed39SKyle Evans Proto *p = clLvalue(s2v(func))->p;
600*a9490b81SWarner Losh int narg = cast_int(L->top.p - func) - 1; /* number of real arguments */
6010495ed39SKyle Evans int nfixparams = p->numparams;
6028e3e3a7aSWarner Losh int fsize = p->maxstacksize; /* frame size */
6030495ed39SKyle Evans checkstackGCp(L, fsize, func);
6048c784bb8SWarner Losh L->ci = ci = prepCallInfo(L, func, nresults, 0, func + 1 + fsize);
6058e3e3a7aSWarner Losh ci->u.l.savedpc = p->code; /* starting point */
6060495ed39SKyle Evans for (; narg < nfixparams; narg++)
607*a9490b81SWarner Losh setnilvalue(s2v(L->top.p++)); /* complete missing arguments */
608*a9490b81SWarner Losh lua_assert(ci->top.p <= L->stack_last.p);
6090495ed39SKyle Evans return ci;
6108e3e3a7aSWarner Losh }
6118e3e3a7aSWarner Losh default: { /* not a function */
6128c784bb8SWarner Losh func = luaD_tryfuncTM(L, func); /* try to get '__call' metamethod */
6138c784bb8SWarner Losh /* return luaD_precall(L, func, nresults); */
6140495ed39SKyle Evans goto retry; /* try again with metamethod */
6158e3e3a7aSWarner Losh }
6168e3e3a7aSWarner Losh }
6178e3e3a7aSWarner Losh }
6188e3e3a7aSWarner Losh
6198e3e3a7aSWarner Losh
6208e3e3a7aSWarner Losh /*
6210495ed39SKyle Evans ** Call a function (C or Lua) through C. 'inc' can be 1 (increment
6220495ed39SKyle Evans ** number of recursive invocations in the C stack) or nyci (the same
6230495ed39SKyle Evans ** plus increment number of non-yieldable calls).
624*a9490b81SWarner Losh ** This function can be called with some use of EXTRA_STACK, so it should
625*a9490b81SWarner Losh ** check the stack before doing anything else. 'luaD_precall' already
626*a9490b81SWarner Losh ** does that.
6278e3e3a7aSWarner Losh */
ccall(lua_State * L,StkId func,int nResults,l_uint32 inc)628*a9490b81SWarner Losh l_sinline void ccall (lua_State *L, StkId func, int nResults, l_uint32 inc) {
6290495ed39SKyle Evans CallInfo *ci;
6300495ed39SKyle Evans L->nCcalls += inc;
631*a9490b81SWarner Losh if (l_unlikely(getCcalls(L) >= LUAI_MAXCCALLS)) {
632*a9490b81SWarner Losh checkstackp(L, 0, func); /* free any use of EXTRA_STACK */
6330495ed39SKyle Evans luaE_checkcstack(L);
634*a9490b81SWarner Losh }
6350495ed39SKyle Evans if ((ci = luaD_precall(L, func, nResults)) != NULL) { /* Lua function? */
6360495ed39SKyle Evans ci->callstatus = CIST_FRESH; /* mark that it is a "fresh" execute */
6370495ed39SKyle Evans luaV_execute(L, ci); /* call it */
6380495ed39SKyle Evans }
6390495ed39SKyle Evans L->nCcalls -= inc;
6408e3e3a7aSWarner Losh }
6418e3e3a7aSWarner Losh
6428e3e3a7aSWarner Losh
6438e3e3a7aSWarner Losh /*
6440495ed39SKyle Evans ** External interface for 'ccall'
6458e3e3a7aSWarner Losh */
luaD_call(lua_State * L,StkId func,int nResults)6468e3e3a7aSWarner Losh void luaD_call (lua_State *L, StkId func, int nResults) {
6470495ed39SKyle Evans ccall(L, func, nResults, 1);
6488e3e3a7aSWarner Losh }
6498e3e3a7aSWarner Losh
6508e3e3a7aSWarner Losh
6518e3e3a7aSWarner Losh /*
6520495ed39SKyle Evans ** Similar to 'luaD_call', but does not allow yields during the call.
6538e3e3a7aSWarner Losh */
luaD_callnoyield(lua_State * L,StkId func,int nResults)6548e3e3a7aSWarner Losh void luaD_callnoyield (lua_State *L, StkId func, int nResults) {
6550495ed39SKyle Evans ccall(L, func, nResults, nyci);
6568e3e3a7aSWarner Losh }
6578e3e3a7aSWarner Losh
6588e3e3a7aSWarner Losh
6598e3e3a7aSWarner Losh /*
6608c784bb8SWarner Losh ** Finish the job of 'lua_pcallk' after it was interrupted by an yield.
6618c784bb8SWarner Losh ** (The caller, 'finishCcall', does the final call to 'adjustresults'.)
6628c784bb8SWarner Losh ** The main job is to complete the 'luaD_pcall' called by 'lua_pcallk'.
6638c784bb8SWarner Losh ** If a '__close' method yields here, eventually control will be back
6648c784bb8SWarner Losh ** to 'finishCcall' (when that '__close' method finally returns) and
6658c784bb8SWarner Losh ** 'finishpcallk' will run again and close any still pending '__close'
6668c784bb8SWarner Losh ** methods. Similarly, if a '__close' method errs, 'precover' calls
6678c784bb8SWarner Losh ** 'unroll' which calls ''finishCcall' and we are back here again, to
6688c784bb8SWarner Losh ** close any pending '__close' methods.
6698c784bb8SWarner Losh ** Note that, up to the call to 'luaF_close', the corresponding
6708c784bb8SWarner Losh ** 'CallInfo' is not modified, so that this repeated run works like the
6718c784bb8SWarner Losh ** first one (except that it has at least one less '__close' to do). In
6728c784bb8SWarner Losh ** particular, field CIST_RECST preserves the error status across these
6738c784bb8SWarner Losh ** multiple runs, changing only if there is a new error.
6748e3e3a7aSWarner Losh */
finishpcallk(lua_State * L,CallInfo * ci)6758c784bb8SWarner Losh static int finishpcallk (lua_State *L, CallInfo *ci) {
6768c784bb8SWarner Losh int status = getcistrecst(ci); /* get original status */
6778c784bb8SWarner Losh if (l_likely(status == LUA_OK)) /* no error? */
6788c784bb8SWarner Losh status = LUA_YIELD; /* was interrupted by an yield */
6798c784bb8SWarner Losh else { /* error */
6808c784bb8SWarner Losh StkId func = restorestack(L, ci->u2.funcidx);
6818c784bb8SWarner Losh L->allowhook = getoah(ci->callstatus); /* restore 'allowhook' */
682*a9490b81SWarner Losh func = luaF_close(L, func, status, 1); /* can yield or raise an error */
6838c784bb8SWarner Losh luaD_seterrorobj(L, status, func);
6848c784bb8SWarner Losh luaD_shrinkstack(L); /* restore stack size in case of overflow */
6858c784bb8SWarner Losh setcistrecst(ci, LUA_OK); /* clear original status */
6868c784bb8SWarner Losh }
6878c784bb8SWarner Losh ci->callstatus &= ~CIST_YPCALL;
6888c784bb8SWarner Losh L->errfunc = ci->u.c.old_errfunc;
6898c784bb8SWarner Losh /* if it is here, there were errors or yields; unlike 'lua_pcallk',
6908c784bb8SWarner Losh do not change status */
6918c784bb8SWarner Losh return status;
6928c784bb8SWarner Losh }
6938c784bb8SWarner Losh
6948c784bb8SWarner Losh
6958c784bb8SWarner Losh /*
6968c784bb8SWarner Losh ** Completes the execution of a C function interrupted by an yield.
6978c784bb8SWarner Losh ** The interruption must have happened while the function was either
6988c784bb8SWarner Losh ** closing its tbc variables in 'moveresults' or executing
6998c784bb8SWarner Losh ** 'lua_callk'/'lua_pcallk'. In the first case, it just redoes
7008c784bb8SWarner Losh ** 'luaD_poscall'. In the second case, the call to 'finishpcallk'
7018c784bb8SWarner Losh ** finishes the interrupted execution of 'lua_pcallk'. After that, it
7028c784bb8SWarner Losh ** calls the continuation of the interrupted function and finally it
7038c784bb8SWarner Losh ** completes the job of the 'luaD_call' that called the function. In
7048c784bb8SWarner Losh ** the call to 'adjustresults', we do not know the number of results
7058c784bb8SWarner Losh ** of the function called by 'lua_callk'/'lua_pcallk', so we are
7068c784bb8SWarner Losh ** conservative and use LUA_MULTRET (always adjust).
7078c784bb8SWarner Losh */
finishCcall(lua_State * L,CallInfo * ci)7088c784bb8SWarner Losh static void finishCcall (lua_State *L, CallInfo *ci) {
7098c784bb8SWarner Losh int n; /* actual number of results from C function */
7108c784bb8SWarner Losh if (ci->callstatus & CIST_CLSRET) { /* was returning? */
7118c784bb8SWarner Losh lua_assert(hastocloseCfunc(ci->nresults));
7128c784bb8SWarner Losh n = ci->u2.nres; /* just redo 'luaD_poscall' */
7138c784bb8SWarner Losh /* don't need to reset CIST_CLSRET, as it will be set again anyway */
7148c784bb8SWarner Losh }
7158c784bb8SWarner Losh else {
7168c784bb8SWarner Losh int status = LUA_YIELD; /* default if there were no errors */
7178e3e3a7aSWarner Losh /* must have a continuation and must be able to call it */
7180495ed39SKyle Evans lua_assert(ci->u.c.k != NULL && yieldable(L));
7198c784bb8SWarner Losh if (ci->callstatus & CIST_YPCALL) /* was inside a 'lua_pcallk'? */
7208c784bb8SWarner Losh status = finishpcallk(L, ci); /* finish it */
7218c784bb8SWarner Losh adjustresults(L, LUA_MULTRET); /* finish 'lua_callk' */
7228e3e3a7aSWarner Losh lua_unlock(L);
7238c784bb8SWarner Losh n = (*ci->u.c.k)(L, status, ci->u.c.ctx); /* call continuation */
7248e3e3a7aSWarner Losh lua_lock(L);
7258e3e3a7aSWarner Losh api_checknelems(L, n);
7268c784bb8SWarner Losh }
7270495ed39SKyle Evans luaD_poscall(L, ci, n); /* finish 'luaD_call' */
7288e3e3a7aSWarner Losh }
7298e3e3a7aSWarner Losh
7308e3e3a7aSWarner Losh
7318e3e3a7aSWarner Losh /*
7328e3e3a7aSWarner Losh ** Executes "full continuation" (everything in the stack) of a
7338e3e3a7aSWarner Losh ** previously interrupted coroutine until the stack is empty (or another
7348c784bb8SWarner Losh ** interruption long-jumps out of the loop).
7358e3e3a7aSWarner Losh */
unroll(lua_State * L,void * ud)7368e3e3a7aSWarner Losh static void unroll (lua_State *L, void *ud) {
7370495ed39SKyle Evans CallInfo *ci;
7388c784bb8SWarner Losh UNUSED(ud);
7390495ed39SKyle Evans while ((ci = L->ci) != &L->base_ci) { /* something in the stack */
7400495ed39SKyle Evans if (!isLua(ci)) /* C function? */
7418c784bb8SWarner Losh finishCcall(L, ci); /* complete its execution */
7428e3e3a7aSWarner Losh else { /* Lua function */
7438e3e3a7aSWarner Losh luaV_finishOp(L); /* finish interrupted instruction */
7440495ed39SKyle Evans luaV_execute(L, ci); /* execute down to higher C 'boundary' */
7458e3e3a7aSWarner Losh }
7468e3e3a7aSWarner Losh }
7478e3e3a7aSWarner Losh }
7488e3e3a7aSWarner Losh
7498e3e3a7aSWarner Losh
7508e3e3a7aSWarner Losh /*
7518e3e3a7aSWarner Losh ** Try to find a suspended protected call (a "recover point") for the
7528e3e3a7aSWarner Losh ** given thread.
7538e3e3a7aSWarner Losh */
findpcall(lua_State * L)7548e3e3a7aSWarner Losh static CallInfo *findpcall (lua_State *L) {
7558e3e3a7aSWarner Losh CallInfo *ci;
7568e3e3a7aSWarner Losh for (ci = L->ci; ci != NULL; ci = ci->previous) { /* search for a pcall */
7578e3e3a7aSWarner Losh if (ci->callstatus & CIST_YPCALL)
7588e3e3a7aSWarner Losh return ci;
7598e3e3a7aSWarner Losh }
7608e3e3a7aSWarner Losh return NULL; /* no pending pcall */
7618e3e3a7aSWarner Losh }
7628e3e3a7aSWarner Losh
7638e3e3a7aSWarner Losh
7648e3e3a7aSWarner Losh /*
7658e3e3a7aSWarner Losh ** Signal an error in the call to 'lua_resume', not in the execution
7668e3e3a7aSWarner Losh ** of the coroutine itself. (Such errors should not be handled by any
7678e3e3a7aSWarner Losh ** coroutine error handler and should not kill the coroutine.)
7688e3e3a7aSWarner Losh */
resume_error(lua_State * L,const char * msg,int narg)7698e3e3a7aSWarner Losh static int resume_error (lua_State *L, const char *msg, int narg) {
770*a9490b81SWarner Losh L->top.p -= narg; /* remove args from the stack */
771*a9490b81SWarner Losh setsvalue2s(L, L->top.p, luaS_new(L, msg)); /* push error message */
7728e3e3a7aSWarner Losh api_incr_top(L);
7738e3e3a7aSWarner Losh lua_unlock(L);
7748e3e3a7aSWarner Losh return LUA_ERRRUN;
7758e3e3a7aSWarner Losh }
7768e3e3a7aSWarner Losh
7778e3e3a7aSWarner Losh
7788e3e3a7aSWarner Losh /*
7798e3e3a7aSWarner Losh ** Do the work for 'lua_resume' in protected mode. Most of the work
7808e3e3a7aSWarner Losh ** depends on the status of the coroutine: initial state, suspended
7818e3e3a7aSWarner Losh ** inside a hook, or regularly suspended (optionally with a continuation
7828e3e3a7aSWarner Losh ** function), plus erroneous cases: non-suspended coroutine or dead
7838e3e3a7aSWarner Losh ** coroutine.
7848e3e3a7aSWarner Losh */
resume(lua_State * L,void * ud)7858e3e3a7aSWarner Losh static void resume (lua_State *L, void *ud) {
7868e3e3a7aSWarner Losh int n = *(cast(int*, ud)); /* number of arguments */
787*a9490b81SWarner Losh StkId firstArg = L->top.p - n; /* first argument */
7888e3e3a7aSWarner Losh CallInfo *ci = L->ci;
7890495ed39SKyle Evans if (L->status == LUA_OK) /* starting a coroutine? */
7908c784bb8SWarner Losh ccall(L, firstArg - 1, LUA_MULTRET, 0); /* just call its body */
7918e3e3a7aSWarner Losh else { /* resuming from previous yield */
7928e3e3a7aSWarner Losh lua_assert(L->status == LUA_YIELD);
7938e3e3a7aSWarner Losh L->status = LUA_OK; /* mark that it is running (again) */
7948c784bb8SWarner Losh if (isLua(ci)) { /* yielded inside a hook? */
795*a9490b81SWarner Losh L->top.p = firstArg; /* discard arguments */
7960495ed39SKyle Evans luaV_execute(L, ci); /* just continue running Lua code */
7978c784bb8SWarner Losh }
7988e3e3a7aSWarner Losh else { /* 'common' yield */
7998e3e3a7aSWarner Losh if (ci->u.c.k != NULL) { /* does it have a continuation function? */
8008e3e3a7aSWarner Losh lua_unlock(L);
8018e3e3a7aSWarner Losh n = (*ci->u.c.k)(L, LUA_YIELD, ci->u.c.ctx); /* call continuation */
8028e3e3a7aSWarner Losh lua_lock(L);
8038e3e3a7aSWarner Losh api_checknelems(L, n);
8048e3e3a7aSWarner Losh }
8050495ed39SKyle Evans luaD_poscall(L, ci, n); /* finish 'luaD_call' */
8068e3e3a7aSWarner Losh }
8078e3e3a7aSWarner Losh unroll(L, NULL); /* run continuation */
8088e3e3a7aSWarner Losh }
8098e3e3a7aSWarner Losh }
8108e3e3a7aSWarner Losh
8118c784bb8SWarner Losh
8128c784bb8SWarner Losh /*
8138c784bb8SWarner Losh ** Unrolls a coroutine in protected mode while there are recoverable
8148c784bb8SWarner Losh ** errors, that is, errors inside a protected call. (Any error
8158c784bb8SWarner Losh ** interrupts 'unroll', and this loop protects it again so it can
8168c784bb8SWarner Losh ** continue.) Stops with a normal end (status == LUA_OK), an yield
8178c784bb8SWarner Losh ** (status == LUA_YIELD), or an unprotected error ('findpcall' doesn't
8188c784bb8SWarner Losh ** find a recover point).
8198c784bb8SWarner Losh */
precover(lua_State * L,int status)8208c784bb8SWarner Losh static int precover (lua_State *L, int status) {
8218c784bb8SWarner Losh CallInfo *ci;
8228c784bb8SWarner Losh while (errorstatus(status) && (ci = findpcall(L)) != NULL) {
8238c784bb8SWarner Losh L->ci = ci; /* go down to recovery functions */
8248c784bb8SWarner Losh setcistrecst(ci, status); /* status to finish 'pcall' */
8258c784bb8SWarner Losh status = luaD_rawrunprotected(L, unroll, NULL);
8268c784bb8SWarner Losh }
8278c784bb8SWarner Losh return status;
8288c784bb8SWarner Losh }
8298c784bb8SWarner Losh
8308c784bb8SWarner Losh
lua_resume(lua_State * L,lua_State * from,int nargs,int * nresults)8310495ed39SKyle Evans LUA_API int lua_resume (lua_State *L, lua_State *from, int nargs,
8320495ed39SKyle Evans int *nresults) {
8338e3e3a7aSWarner Losh int status;
8348e3e3a7aSWarner Losh lua_lock(L);
8358e3e3a7aSWarner Losh if (L->status == LUA_OK) { /* may be starting a coroutine */
8368e3e3a7aSWarner Losh if (L->ci != &L->base_ci) /* not in base level? */
8378e3e3a7aSWarner Losh return resume_error(L, "cannot resume non-suspended coroutine", nargs);
838*a9490b81SWarner Losh else if (L->top.p - (L->ci->func.p + 1) == nargs) /* no function? */
8398e3e3a7aSWarner Losh return resume_error(L, "cannot resume dead coroutine", nargs);
8400495ed39SKyle Evans }
8410495ed39SKyle Evans else if (L->status != LUA_YIELD) /* ended with errors? */
8420495ed39SKyle Evans return resume_error(L, "cannot resume dead coroutine", nargs);
8430495ed39SKyle Evans L->nCcalls = (from) ? getCcalls(from) : 0;
8448c784bb8SWarner Losh if (getCcalls(L) >= LUAI_MAXCCALLS)
8458c784bb8SWarner Losh return resume_error(L, "C stack overflow", nargs);
8468c784bb8SWarner Losh L->nCcalls++;
8478e3e3a7aSWarner Losh luai_userstateresume(L, nargs);
8488e3e3a7aSWarner Losh api_checknelems(L, (L->status == LUA_OK) ? nargs + 1 : nargs);
8498e3e3a7aSWarner Losh status = luaD_rawrunprotected(L, resume, &nargs);
8500495ed39SKyle Evans /* continue running after recoverable errors */
8518c784bb8SWarner Losh status = precover(L, status);
8528c784bb8SWarner Losh if (l_likely(!errorstatus(status)))
8530495ed39SKyle Evans lua_assert(status == L->status); /* normal end or yield */
8540495ed39SKyle Evans else { /* unrecoverable error */
8558e3e3a7aSWarner Losh L->status = cast_byte(status); /* mark thread as 'dead' */
856*a9490b81SWarner Losh luaD_seterrorobj(L, status, L->top.p); /* push error message */
857*a9490b81SWarner Losh L->ci->top.p = L->top.p;
8588e3e3a7aSWarner Losh }
8590495ed39SKyle Evans *nresults = (status == LUA_YIELD) ? L->ci->u2.nyield
860*a9490b81SWarner Losh : cast_int(L->top.p - (L->ci->func.p + 1));
8618e3e3a7aSWarner Losh lua_unlock(L);
8628e3e3a7aSWarner Losh return status;
8638e3e3a7aSWarner Losh }
8648e3e3a7aSWarner Losh
8658e3e3a7aSWarner Losh
lua_isyieldable(lua_State * L)8668e3e3a7aSWarner Losh LUA_API int lua_isyieldable (lua_State *L) {
8670495ed39SKyle Evans return yieldable(L);
8688e3e3a7aSWarner Losh }
8698e3e3a7aSWarner Losh
8708e3e3a7aSWarner Losh
lua_yieldk(lua_State * L,int nresults,lua_KContext ctx,lua_KFunction k)8718e3e3a7aSWarner Losh LUA_API int lua_yieldk (lua_State *L, int nresults, lua_KContext ctx,
8728e3e3a7aSWarner Losh lua_KFunction k) {
8730495ed39SKyle Evans CallInfo *ci;
8748e3e3a7aSWarner Losh luai_userstateyield(L, nresults);
8758e3e3a7aSWarner Losh lua_lock(L);
8760495ed39SKyle Evans ci = L->ci;
8778e3e3a7aSWarner Losh api_checknelems(L, nresults);
8788c784bb8SWarner Losh if (l_unlikely(!yieldable(L))) {
8798e3e3a7aSWarner Losh if (L != G(L)->mainthread)
8808e3e3a7aSWarner Losh luaG_runerror(L, "attempt to yield across a C-call boundary");
8818e3e3a7aSWarner Losh else
8828e3e3a7aSWarner Losh luaG_runerror(L, "attempt to yield from outside a coroutine");
8838e3e3a7aSWarner Losh }
8848e3e3a7aSWarner Losh L->status = LUA_YIELD;
8858c784bb8SWarner Losh ci->u2.nyield = nresults; /* save number of results */
8868e3e3a7aSWarner Losh if (isLua(ci)) { /* inside a hook? */
8870495ed39SKyle Evans lua_assert(!isLuacode(ci));
8888c784bb8SWarner Losh api_check(L, nresults == 0, "hooks cannot yield values");
8898e3e3a7aSWarner Losh api_check(L, k == NULL, "hooks cannot continue after yielding");
8908e3e3a7aSWarner Losh }
8918e3e3a7aSWarner Losh else {
8928e3e3a7aSWarner Losh if ((ci->u.c.k = k) != NULL) /* is there a continuation? */
8938e3e3a7aSWarner Losh ci->u.c.ctx = ctx; /* save context */
8948e3e3a7aSWarner Losh luaD_throw(L, LUA_YIELD);
8958e3e3a7aSWarner Losh }
8968e3e3a7aSWarner Losh lua_assert(ci->callstatus & CIST_HOOKED); /* must be inside a hook */
8978e3e3a7aSWarner Losh lua_unlock(L);
8988e3e3a7aSWarner Losh return 0; /* return to 'luaD_hook' */
8998e3e3a7aSWarner Losh }
9008e3e3a7aSWarner Losh
9018e3e3a7aSWarner Losh
9020495ed39SKyle Evans /*
9038c784bb8SWarner Losh ** Auxiliary structure to call 'luaF_close' in protected mode.
9048c784bb8SWarner Losh */
9058c784bb8SWarner Losh struct CloseP {
9068c784bb8SWarner Losh StkId level;
9078c784bb8SWarner Losh int status;
9088c784bb8SWarner Losh };
9098c784bb8SWarner Losh
9108c784bb8SWarner Losh
9118c784bb8SWarner Losh /*
9128c784bb8SWarner Losh ** Auxiliary function to call 'luaF_close' in protected mode.
9138c784bb8SWarner Losh */
closepaux(lua_State * L,void * ud)9148c784bb8SWarner Losh static void closepaux (lua_State *L, void *ud) {
9158c784bb8SWarner Losh struct CloseP *pcl = cast(struct CloseP *, ud);
9168c784bb8SWarner Losh luaF_close(L, pcl->level, pcl->status, 0);
9178c784bb8SWarner Losh }
9188c784bb8SWarner Losh
9198c784bb8SWarner Losh
9208c784bb8SWarner Losh /*
9218c784bb8SWarner Losh ** Calls 'luaF_close' in protected mode. Return the original status
9228c784bb8SWarner Losh ** or, in case of errors, the new status.
9238c784bb8SWarner Losh */
luaD_closeprotected(lua_State * L,ptrdiff_t level,int status)9248c784bb8SWarner Losh int luaD_closeprotected (lua_State *L, ptrdiff_t level, int status) {
9258c784bb8SWarner Losh CallInfo *old_ci = L->ci;
9268c784bb8SWarner Losh lu_byte old_allowhooks = L->allowhook;
9278c784bb8SWarner Losh for (;;) { /* keep closing upvalues until no more errors */
9288c784bb8SWarner Losh struct CloseP pcl;
9298c784bb8SWarner Losh pcl.level = restorestack(L, level); pcl.status = status;
9308c784bb8SWarner Losh status = luaD_rawrunprotected(L, &closepaux, &pcl);
9318c784bb8SWarner Losh if (l_likely(status == LUA_OK)) /* no more errors? */
9328c784bb8SWarner Losh return pcl.status;
9338c784bb8SWarner Losh else { /* an error occurred; restore saved state and repeat */
9348c784bb8SWarner Losh L->ci = old_ci;
9358c784bb8SWarner Losh L->allowhook = old_allowhooks;
9368c784bb8SWarner Losh }
9378c784bb8SWarner Losh }
9388c784bb8SWarner Losh }
9398c784bb8SWarner Losh
9408c784bb8SWarner Losh
9418c784bb8SWarner Losh /*
9420495ed39SKyle Evans ** Call the C function 'func' in protected mode, restoring basic
9430495ed39SKyle Evans ** thread information ('allowhook', etc.) and in particular
9440495ed39SKyle Evans ** its stack level in case of errors.
9450495ed39SKyle Evans */
luaD_pcall(lua_State * L,Pfunc func,void * u,ptrdiff_t old_top,ptrdiff_t ef)9468e3e3a7aSWarner Losh int luaD_pcall (lua_State *L, Pfunc func, void *u,
9478e3e3a7aSWarner Losh ptrdiff_t old_top, ptrdiff_t ef) {
9488e3e3a7aSWarner Losh int status;
9498e3e3a7aSWarner Losh CallInfo *old_ci = L->ci;
9508e3e3a7aSWarner Losh lu_byte old_allowhooks = L->allowhook;
9518e3e3a7aSWarner Losh ptrdiff_t old_errfunc = L->errfunc;
9528e3e3a7aSWarner Losh L->errfunc = ef;
9538e3e3a7aSWarner Losh status = luaD_rawrunprotected(L, func, u);
9548c784bb8SWarner Losh if (l_unlikely(status != LUA_OK)) { /* an error occurred? */
9558e3e3a7aSWarner Losh L->ci = old_ci;
9568e3e3a7aSWarner Losh L->allowhook = old_allowhooks;
9578c784bb8SWarner Losh status = luaD_closeprotected(L, old_top, status);
9588c784bb8SWarner Losh luaD_seterrorobj(L, status, restorestack(L, old_top));
9590495ed39SKyle Evans luaD_shrinkstack(L); /* restore stack size in case of overflow */
9608e3e3a7aSWarner Losh }
9618e3e3a7aSWarner Losh L->errfunc = old_errfunc;
9628e3e3a7aSWarner Losh return status;
9638e3e3a7aSWarner Losh }
9648e3e3a7aSWarner Losh
9658e3e3a7aSWarner Losh
9668e3e3a7aSWarner Losh
9678e3e3a7aSWarner Losh /*
9688e3e3a7aSWarner Losh ** Execute a protected parser.
9698e3e3a7aSWarner Losh */
9708e3e3a7aSWarner Losh struct SParser { /* data to 'f_parser' */
9718e3e3a7aSWarner Losh ZIO *z;
9728e3e3a7aSWarner Losh Mbuffer buff; /* dynamic structure used by the scanner */
9738e3e3a7aSWarner Losh Dyndata dyd; /* dynamic structures used by the parser */
9748e3e3a7aSWarner Losh const char *mode;
9758e3e3a7aSWarner Losh const char *name;
9768e3e3a7aSWarner Losh };
9778e3e3a7aSWarner Losh
9788e3e3a7aSWarner Losh
checkmode(lua_State * L,const char * mode,const char * x)9798e3e3a7aSWarner Losh static void checkmode (lua_State *L, const char *mode, const char *x) {
9808e3e3a7aSWarner Losh if (mode && strchr(mode, x[0]) == NULL) {
9818e3e3a7aSWarner Losh luaO_pushfstring(L,
9828e3e3a7aSWarner Losh "attempt to load a %s chunk (mode is '%s')", x, mode);
9838e3e3a7aSWarner Losh luaD_throw(L, LUA_ERRSYNTAX);
9848e3e3a7aSWarner Losh }
9858e3e3a7aSWarner Losh }
9868e3e3a7aSWarner Losh
9878e3e3a7aSWarner Losh
f_parser(lua_State * L,void * ud)9888e3e3a7aSWarner Losh static void f_parser (lua_State *L, void *ud) {
9898e3e3a7aSWarner Losh LClosure *cl;
9908e3e3a7aSWarner Losh struct SParser *p = cast(struct SParser *, ud);
9918e3e3a7aSWarner Losh int c = zgetc(p->z); /* read first character */
9928e3e3a7aSWarner Losh if (c == LUA_SIGNATURE[0]) {
9938e3e3a7aSWarner Losh checkmode(L, p->mode, "binary");
9948e3e3a7aSWarner Losh cl = luaU_undump(L, p->z, p->name);
9958e3e3a7aSWarner Losh }
9968e3e3a7aSWarner Losh else {
9978e3e3a7aSWarner Losh checkmode(L, p->mode, "text");
9988e3e3a7aSWarner Losh cl = luaY_parser(L, p->z, &p->buff, &p->dyd, p->name, c);
9998e3e3a7aSWarner Losh }
10008e3e3a7aSWarner Losh lua_assert(cl->nupvalues == cl->p->sizeupvalues);
10018e3e3a7aSWarner Losh luaF_initupvals(L, cl);
10028e3e3a7aSWarner Losh }
10038e3e3a7aSWarner Losh
10048e3e3a7aSWarner Losh
luaD_protectedparser(lua_State * L,ZIO * z,const char * name,const char * mode)10058e3e3a7aSWarner Losh int luaD_protectedparser (lua_State *L, ZIO *z, const char *name,
10068e3e3a7aSWarner Losh const char *mode) {
10078e3e3a7aSWarner Losh struct SParser p;
10088e3e3a7aSWarner Losh int status;
10090495ed39SKyle Evans incnny(L); /* cannot yield during parsing */
10108e3e3a7aSWarner Losh p.z = z; p.name = name; p.mode = mode;
10118e3e3a7aSWarner Losh p.dyd.actvar.arr = NULL; p.dyd.actvar.size = 0;
10128e3e3a7aSWarner Losh p.dyd.gt.arr = NULL; p.dyd.gt.size = 0;
10138e3e3a7aSWarner Losh p.dyd.label.arr = NULL; p.dyd.label.size = 0;
10148e3e3a7aSWarner Losh luaZ_initbuffer(L, &p.buff);
1015*a9490b81SWarner Losh status = luaD_pcall(L, f_parser, &p, savestack(L, L->top.p), L->errfunc);
10168e3e3a7aSWarner Losh luaZ_freebuffer(L, &p.buff);
10178e3e3a7aSWarner Losh luaM_freearray(L, p.dyd.actvar.arr, p.dyd.actvar.size);
10188e3e3a7aSWarner Losh luaM_freearray(L, p.dyd.gt.arr, p.dyd.gt.size);
10198e3e3a7aSWarner Losh luaM_freearray(L, p.dyd.label.arr, p.dyd.label.size);
10200495ed39SKyle Evans decnny(L);
10218e3e3a7aSWarner Losh return status;
10228e3e3a7aSWarner Losh }
10238e3e3a7aSWarner Losh
10248e3e3a7aSWarner Losh
1025