1*8e3e3a7aSWarner Losh /* 2*8e3e3a7aSWarner Losh ** $Id: ldo.c,v 2.157 2016/12/13 15:52:21 roberto Exp $ 3*8e3e3a7aSWarner Losh ** Stack and Call structure of Lua 4*8e3e3a7aSWarner Losh ** See Copyright Notice in lua.h 5*8e3e3a7aSWarner Losh */ 6*8e3e3a7aSWarner Losh 7*8e3e3a7aSWarner Losh #define ldo_c 8*8e3e3a7aSWarner Losh #define LUA_CORE 9*8e3e3a7aSWarner Losh 10*8e3e3a7aSWarner Losh #include "lprefix.h" 11*8e3e3a7aSWarner Losh 12*8e3e3a7aSWarner Losh 13*8e3e3a7aSWarner Losh #include <setjmp.h> 14*8e3e3a7aSWarner Losh #include <stdlib.h> 15*8e3e3a7aSWarner Losh #include <string.h> 16*8e3e3a7aSWarner Losh 17*8e3e3a7aSWarner Losh #include "lua.h" 18*8e3e3a7aSWarner Losh 19*8e3e3a7aSWarner Losh #include "lapi.h" 20*8e3e3a7aSWarner Losh #include "ldebug.h" 21*8e3e3a7aSWarner Losh #include "ldo.h" 22*8e3e3a7aSWarner Losh #include "lfunc.h" 23*8e3e3a7aSWarner Losh #include "lgc.h" 24*8e3e3a7aSWarner Losh #include "lmem.h" 25*8e3e3a7aSWarner Losh #include "lobject.h" 26*8e3e3a7aSWarner Losh #include "lopcodes.h" 27*8e3e3a7aSWarner Losh #include "lparser.h" 28*8e3e3a7aSWarner Losh #include "lstate.h" 29*8e3e3a7aSWarner Losh #include "lstring.h" 30*8e3e3a7aSWarner Losh #include "ltable.h" 31*8e3e3a7aSWarner Losh #include "ltm.h" 32*8e3e3a7aSWarner Losh #include "lundump.h" 33*8e3e3a7aSWarner Losh #include "lvm.h" 34*8e3e3a7aSWarner Losh #include "lzio.h" 35*8e3e3a7aSWarner Losh 36*8e3e3a7aSWarner Losh 37*8e3e3a7aSWarner Losh 38*8e3e3a7aSWarner Losh #define errorstatus(s) ((s) > LUA_YIELD) 39*8e3e3a7aSWarner Losh 40*8e3e3a7aSWarner Losh 41*8e3e3a7aSWarner Losh /* 42*8e3e3a7aSWarner Losh ** {====================================================== 43*8e3e3a7aSWarner Losh ** Error-recovery functions 44*8e3e3a7aSWarner Losh ** ======================================================= 45*8e3e3a7aSWarner Losh */ 46*8e3e3a7aSWarner Losh 47*8e3e3a7aSWarner Losh /* 48*8e3e3a7aSWarner Losh ** LUAI_THROW/LUAI_TRY define how Lua does exception handling. By 49*8e3e3a7aSWarner Losh ** default, Lua handles errors with exceptions when compiling as 50*8e3e3a7aSWarner Losh ** C++ code, with _longjmp/_setjmp when asked to use them, and with 51*8e3e3a7aSWarner Losh ** longjmp/setjmp otherwise. 52*8e3e3a7aSWarner Losh */ 53*8e3e3a7aSWarner Losh #if !defined(LUAI_THROW) /* { */ 54*8e3e3a7aSWarner Losh 55*8e3e3a7aSWarner Losh #if defined(__cplusplus) && !defined(LUA_USE_LONGJMP) /* { */ 56*8e3e3a7aSWarner Losh 57*8e3e3a7aSWarner Losh /* C++ exceptions */ 58*8e3e3a7aSWarner Losh #define LUAI_THROW(L,c) throw(c) 59*8e3e3a7aSWarner Losh #define LUAI_TRY(L,c,a) \ 60*8e3e3a7aSWarner Losh try { a } catch(...) { if ((c)->status == 0) (c)->status = -1; } 61*8e3e3a7aSWarner Losh #define luai_jmpbuf int /* dummy variable */ 62*8e3e3a7aSWarner Losh 63*8e3e3a7aSWarner Losh #elif defined(LUA_USE_POSIX) /* }{ */ 64*8e3e3a7aSWarner Losh 65*8e3e3a7aSWarner Losh /* in POSIX, try _longjmp/_setjmp (more efficient) */ 66*8e3e3a7aSWarner Losh #define LUAI_THROW(L,c) _longjmp((c)->b, 1) 67*8e3e3a7aSWarner Losh #define LUAI_TRY(L,c,a) if (_setjmp((c)->b) == 0) { a } 68*8e3e3a7aSWarner Losh #define luai_jmpbuf jmp_buf 69*8e3e3a7aSWarner Losh 70*8e3e3a7aSWarner Losh #else /* }{ */ 71*8e3e3a7aSWarner Losh 72*8e3e3a7aSWarner Losh /* ISO C handling with long jumps */ 73*8e3e3a7aSWarner Losh #define LUAI_THROW(L,c) longjmp((c)->b, 1) 74*8e3e3a7aSWarner Losh #define LUAI_TRY(L,c,a) if (setjmp((c)->b) == 0) { a } 75*8e3e3a7aSWarner Losh #define luai_jmpbuf jmp_buf 76*8e3e3a7aSWarner Losh 77*8e3e3a7aSWarner Losh #endif /* } */ 78*8e3e3a7aSWarner Losh 79*8e3e3a7aSWarner Losh #endif /* } */ 80*8e3e3a7aSWarner Losh 81*8e3e3a7aSWarner Losh 82*8e3e3a7aSWarner Losh 83*8e3e3a7aSWarner Losh /* chain list of long jump buffers */ 84*8e3e3a7aSWarner Losh struct lua_longjmp { 85*8e3e3a7aSWarner Losh struct lua_longjmp *previous; 86*8e3e3a7aSWarner Losh luai_jmpbuf b; 87*8e3e3a7aSWarner Losh volatile int status; /* error code */ 88*8e3e3a7aSWarner Losh }; 89*8e3e3a7aSWarner Losh 90*8e3e3a7aSWarner Losh 91*8e3e3a7aSWarner Losh static void seterrorobj (lua_State *L, int errcode, StkId oldtop) { 92*8e3e3a7aSWarner Losh switch (errcode) { 93*8e3e3a7aSWarner Losh case LUA_ERRMEM: { /* memory error? */ 94*8e3e3a7aSWarner Losh setsvalue2s(L, oldtop, G(L)->memerrmsg); /* reuse preregistered msg. */ 95*8e3e3a7aSWarner Losh break; 96*8e3e3a7aSWarner Losh } 97*8e3e3a7aSWarner Losh case LUA_ERRERR: { 98*8e3e3a7aSWarner Losh setsvalue2s(L, oldtop, luaS_newliteral(L, "error in error handling")); 99*8e3e3a7aSWarner Losh break; 100*8e3e3a7aSWarner Losh } 101*8e3e3a7aSWarner Losh default: { 102*8e3e3a7aSWarner Losh setobjs2s(L, oldtop, L->top - 1); /* error message on current top */ 103*8e3e3a7aSWarner Losh break; 104*8e3e3a7aSWarner Losh } 105*8e3e3a7aSWarner Losh } 106*8e3e3a7aSWarner Losh L->top = oldtop + 1; 107*8e3e3a7aSWarner Losh } 108*8e3e3a7aSWarner Losh 109*8e3e3a7aSWarner Losh 110*8e3e3a7aSWarner Losh l_noret luaD_throw (lua_State *L, int errcode) { 111*8e3e3a7aSWarner Losh if (L->errorJmp) { /* thread has an error handler? */ 112*8e3e3a7aSWarner Losh L->errorJmp->status = errcode; /* set status */ 113*8e3e3a7aSWarner Losh LUAI_THROW(L, L->errorJmp); /* jump to it */ 114*8e3e3a7aSWarner Losh } 115*8e3e3a7aSWarner Losh else { /* thread has no error handler */ 116*8e3e3a7aSWarner Losh global_State *g = G(L); 117*8e3e3a7aSWarner Losh L->status = cast_byte(errcode); /* mark it as dead */ 118*8e3e3a7aSWarner Losh if (g->mainthread->errorJmp) { /* main thread has a handler? */ 119*8e3e3a7aSWarner Losh setobjs2s(L, g->mainthread->top++, L->top - 1); /* copy error obj. */ 120*8e3e3a7aSWarner Losh luaD_throw(g->mainthread, errcode); /* re-throw in main thread */ 121*8e3e3a7aSWarner Losh } 122*8e3e3a7aSWarner Losh else { /* no handler at all; abort */ 123*8e3e3a7aSWarner Losh if (g->panic) { /* panic function? */ 124*8e3e3a7aSWarner Losh seterrorobj(L, errcode, L->top); /* assume EXTRA_STACK */ 125*8e3e3a7aSWarner Losh if (L->ci->top < L->top) 126*8e3e3a7aSWarner Losh L->ci->top = L->top; /* pushing msg. can break this invariant */ 127*8e3e3a7aSWarner Losh lua_unlock(L); 128*8e3e3a7aSWarner Losh g->panic(L); /* call panic function (last chance to jump out) */ 129*8e3e3a7aSWarner Losh } 130*8e3e3a7aSWarner Losh abort(); 131*8e3e3a7aSWarner Losh } 132*8e3e3a7aSWarner Losh } 133*8e3e3a7aSWarner Losh } 134*8e3e3a7aSWarner Losh 135*8e3e3a7aSWarner Losh 136*8e3e3a7aSWarner Losh int luaD_rawrunprotected (lua_State *L, Pfunc f, void *ud) { 137*8e3e3a7aSWarner Losh unsigned short oldnCcalls = L->nCcalls; 138*8e3e3a7aSWarner Losh struct lua_longjmp lj; 139*8e3e3a7aSWarner Losh lj.status = LUA_OK; 140*8e3e3a7aSWarner Losh lj.previous = L->errorJmp; /* chain new error handler */ 141*8e3e3a7aSWarner Losh L->errorJmp = &lj; 142*8e3e3a7aSWarner Losh LUAI_TRY(L, &lj, 143*8e3e3a7aSWarner Losh (*f)(L, ud); 144*8e3e3a7aSWarner Losh ); 145*8e3e3a7aSWarner Losh L->errorJmp = lj.previous; /* restore old error handler */ 146*8e3e3a7aSWarner Losh L->nCcalls = oldnCcalls; 147*8e3e3a7aSWarner Losh return lj.status; 148*8e3e3a7aSWarner Losh } 149*8e3e3a7aSWarner Losh 150*8e3e3a7aSWarner Losh /* }====================================================== */ 151*8e3e3a7aSWarner Losh 152*8e3e3a7aSWarner Losh 153*8e3e3a7aSWarner Losh /* 154*8e3e3a7aSWarner Losh ** {================================================================== 155*8e3e3a7aSWarner Losh ** Stack reallocation 156*8e3e3a7aSWarner Losh ** =================================================================== 157*8e3e3a7aSWarner Losh */ 158*8e3e3a7aSWarner Losh static void correctstack (lua_State *L, TValue *oldstack) { 159*8e3e3a7aSWarner Losh CallInfo *ci; 160*8e3e3a7aSWarner Losh UpVal *up; 161*8e3e3a7aSWarner Losh L->top = (L->top - oldstack) + L->stack; 162*8e3e3a7aSWarner Losh for (up = L->openupval; up != NULL; up = up->u.open.next) 163*8e3e3a7aSWarner Losh up->v = (up->v - oldstack) + L->stack; 164*8e3e3a7aSWarner Losh for (ci = L->ci; ci != NULL; ci = ci->previous) { 165*8e3e3a7aSWarner Losh ci->top = (ci->top - oldstack) + L->stack; 166*8e3e3a7aSWarner Losh ci->func = (ci->func - oldstack) + L->stack; 167*8e3e3a7aSWarner Losh if (isLua(ci)) 168*8e3e3a7aSWarner Losh ci->u.l.base = (ci->u.l.base - oldstack) + L->stack; 169*8e3e3a7aSWarner Losh } 170*8e3e3a7aSWarner Losh } 171*8e3e3a7aSWarner Losh 172*8e3e3a7aSWarner Losh 173*8e3e3a7aSWarner Losh /* some space for error handling */ 174*8e3e3a7aSWarner Losh #define ERRORSTACKSIZE (LUAI_MAXSTACK + 200) 175*8e3e3a7aSWarner Losh 176*8e3e3a7aSWarner Losh 177*8e3e3a7aSWarner Losh void luaD_reallocstack (lua_State *L, int newsize) { 178*8e3e3a7aSWarner Losh TValue *oldstack = L->stack; 179*8e3e3a7aSWarner Losh int lim = L->stacksize; 180*8e3e3a7aSWarner Losh lua_assert(newsize <= LUAI_MAXSTACK || newsize == ERRORSTACKSIZE); 181*8e3e3a7aSWarner Losh lua_assert(L->stack_last - L->stack == L->stacksize - EXTRA_STACK); 182*8e3e3a7aSWarner Losh luaM_reallocvector(L, L->stack, L->stacksize, newsize, TValue); 183*8e3e3a7aSWarner Losh for (; lim < newsize; lim++) 184*8e3e3a7aSWarner Losh setnilvalue(L->stack + lim); /* erase new segment */ 185*8e3e3a7aSWarner Losh L->stacksize = newsize; 186*8e3e3a7aSWarner Losh L->stack_last = L->stack + newsize - EXTRA_STACK; 187*8e3e3a7aSWarner Losh correctstack(L, oldstack); 188*8e3e3a7aSWarner Losh } 189*8e3e3a7aSWarner Losh 190*8e3e3a7aSWarner Losh 191*8e3e3a7aSWarner Losh void luaD_growstack (lua_State *L, int n) { 192*8e3e3a7aSWarner Losh int size = L->stacksize; 193*8e3e3a7aSWarner Losh if (size > LUAI_MAXSTACK) /* error after extra size? */ 194*8e3e3a7aSWarner Losh luaD_throw(L, LUA_ERRERR); 195*8e3e3a7aSWarner Losh else { 196*8e3e3a7aSWarner Losh int needed = cast_int(L->top - L->stack) + n + EXTRA_STACK; 197*8e3e3a7aSWarner Losh int newsize = 2 * size; 198*8e3e3a7aSWarner Losh if (newsize > LUAI_MAXSTACK) newsize = LUAI_MAXSTACK; 199*8e3e3a7aSWarner Losh if (newsize < needed) newsize = needed; 200*8e3e3a7aSWarner Losh if (newsize > LUAI_MAXSTACK) { /* stack overflow? */ 201*8e3e3a7aSWarner Losh luaD_reallocstack(L, ERRORSTACKSIZE); 202*8e3e3a7aSWarner Losh luaG_runerror(L, "stack overflow"); 203*8e3e3a7aSWarner Losh } 204*8e3e3a7aSWarner Losh else 205*8e3e3a7aSWarner Losh luaD_reallocstack(L, newsize); 206*8e3e3a7aSWarner Losh } 207*8e3e3a7aSWarner Losh } 208*8e3e3a7aSWarner Losh 209*8e3e3a7aSWarner Losh 210*8e3e3a7aSWarner Losh static int stackinuse (lua_State *L) { 211*8e3e3a7aSWarner Losh CallInfo *ci; 212*8e3e3a7aSWarner Losh StkId lim = L->top; 213*8e3e3a7aSWarner Losh for (ci = L->ci; ci != NULL; ci = ci->previous) { 214*8e3e3a7aSWarner Losh if (lim < ci->top) lim = ci->top; 215*8e3e3a7aSWarner Losh } 216*8e3e3a7aSWarner Losh lua_assert(lim <= L->stack_last); 217*8e3e3a7aSWarner Losh return cast_int(lim - L->stack) + 1; /* part of stack in use */ 218*8e3e3a7aSWarner Losh } 219*8e3e3a7aSWarner Losh 220*8e3e3a7aSWarner Losh 221*8e3e3a7aSWarner Losh void luaD_shrinkstack (lua_State *L) { 222*8e3e3a7aSWarner Losh int inuse = stackinuse(L); 223*8e3e3a7aSWarner Losh int goodsize = inuse + (inuse / 8) + 2*EXTRA_STACK; 224*8e3e3a7aSWarner Losh if (goodsize > LUAI_MAXSTACK) 225*8e3e3a7aSWarner Losh goodsize = LUAI_MAXSTACK; /* respect stack limit */ 226*8e3e3a7aSWarner Losh if (L->stacksize > LUAI_MAXSTACK) /* had been handling stack overflow? */ 227*8e3e3a7aSWarner Losh luaE_freeCI(L); /* free all CIs (list grew because of an error) */ 228*8e3e3a7aSWarner Losh else 229*8e3e3a7aSWarner Losh luaE_shrinkCI(L); /* shrink list */ 230*8e3e3a7aSWarner Losh /* if thread is currently not handling a stack overflow and its 231*8e3e3a7aSWarner Losh good size is smaller than current size, shrink its stack */ 232*8e3e3a7aSWarner Losh if (inuse <= (LUAI_MAXSTACK - EXTRA_STACK) && 233*8e3e3a7aSWarner Losh goodsize < L->stacksize) 234*8e3e3a7aSWarner Losh luaD_reallocstack(L, goodsize); 235*8e3e3a7aSWarner Losh else /* don't change stack */ 236*8e3e3a7aSWarner Losh condmovestack(L,{},{}); /* (change only for debugging) */ 237*8e3e3a7aSWarner Losh } 238*8e3e3a7aSWarner Losh 239*8e3e3a7aSWarner Losh 240*8e3e3a7aSWarner Losh void luaD_inctop (lua_State *L) { 241*8e3e3a7aSWarner Losh luaD_checkstack(L, 1); 242*8e3e3a7aSWarner Losh L->top++; 243*8e3e3a7aSWarner Losh } 244*8e3e3a7aSWarner Losh 245*8e3e3a7aSWarner Losh /* }================================================================== */ 246*8e3e3a7aSWarner Losh 247*8e3e3a7aSWarner Losh 248*8e3e3a7aSWarner Losh /* 249*8e3e3a7aSWarner Losh ** Call a hook for the given event. Make sure there is a hook to be 250*8e3e3a7aSWarner Losh ** called. (Both 'L->hook' and 'L->hookmask', which triggers this 251*8e3e3a7aSWarner Losh ** function, can be changed asynchronously by signals.) 252*8e3e3a7aSWarner Losh */ 253*8e3e3a7aSWarner Losh void luaD_hook (lua_State *L, int event, int line) { 254*8e3e3a7aSWarner Losh lua_Hook hook = L->hook; 255*8e3e3a7aSWarner Losh if (hook && L->allowhook) { /* make sure there is a hook */ 256*8e3e3a7aSWarner Losh CallInfo *ci = L->ci; 257*8e3e3a7aSWarner Losh ptrdiff_t top = savestack(L, L->top); 258*8e3e3a7aSWarner Losh ptrdiff_t ci_top = savestack(L, ci->top); 259*8e3e3a7aSWarner Losh lua_Debug ar; 260*8e3e3a7aSWarner Losh ar.event = event; 261*8e3e3a7aSWarner Losh ar.currentline = line; 262*8e3e3a7aSWarner Losh ar.i_ci = ci; 263*8e3e3a7aSWarner Losh luaD_checkstack(L, LUA_MINSTACK); /* ensure minimum stack size */ 264*8e3e3a7aSWarner Losh ci->top = L->top + LUA_MINSTACK; 265*8e3e3a7aSWarner Losh lua_assert(ci->top <= L->stack_last); 266*8e3e3a7aSWarner Losh L->allowhook = 0; /* cannot call hooks inside a hook */ 267*8e3e3a7aSWarner Losh ci->callstatus |= CIST_HOOKED; 268*8e3e3a7aSWarner Losh lua_unlock(L); 269*8e3e3a7aSWarner Losh (*hook)(L, &ar); 270*8e3e3a7aSWarner Losh lua_lock(L); 271*8e3e3a7aSWarner Losh lua_assert(!L->allowhook); 272*8e3e3a7aSWarner Losh L->allowhook = 1; 273*8e3e3a7aSWarner Losh ci->top = restorestack(L, ci_top); 274*8e3e3a7aSWarner Losh L->top = restorestack(L, top); 275*8e3e3a7aSWarner Losh ci->callstatus &= ~CIST_HOOKED; 276*8e3e3a7aSWarner Losh } 277*8e3e3a7aSWarner Losh } 278*8e3e3a7aSWarner Losh 279*8e3e3a7aSWarner Losh 280*8e3e3a7aSWarner Losh static void callhook (lua_State *L, CallInfo *ci) { 281*8e3e3a7aSWarner Losh int hook = LUA_HOOKCALL; 282*8e3e3a7aSWarner Losh ci->u.l.savedpc++; /* hooks assume 'pc' is already incremented */ 283*8e3e3a7aSWarner Losh if (isLua(ci->previous) && 284*8e3e3a7aSWarner Losh GET_OPCODE(*(ci->previous->u.l.savedpc - 1)) == OP_TAILCALL) { 285*8e3e3a7aSWarner Losh ci->callstatus |= CIST_TAIL; 286*8e3e3a7aSWarner Losh hook = LUA_HOOKTAILCALL; 287*8e3e3a7aSWarner Losh } 288*8e3e3a7aSWarner Losh luaD_hook(L, hook, -1); 289*8e3e3a7aSWarner Losh ci->u.l.savedpc--; /* correct 'pc' */ 290*8e3e3a7aSWarner Losh } 291*8e3e3a7aSWarner Losh 292*8e3e3a7aSWarner Losh 293*8e3e3a7aSWarner Losh static StkId adjust_varargs (lua_State *L, Proto *p, int actual) { 294*8e3e3a7aSWarner Losh int i; 295*8e3e3a7aSWarner Losh int nfixargs = p->numparams; 296*8e3e3a7aSWarner Losh StkId base, fixed; 297*8e3e3a7aSWarner Losh /* move fixed parameters to final position */ 298*8e3e3a7aSWarner Losh fixed = L->top - actual; /* first fixed argument */ 299*8e3e3a7aSWarner Losh base = L->top; /* final position of first argument */ 300*8e3e3a7aSWarner Losh for (i = 0; i < nfixargs && i < actual; i++) { 301*8e3e3a7aSWarner Losh setobjs2s(L, L->top++, fixed + i); 302*8e3e3a7aSWarner Losh setnilvalue(fixed + i); /* erase original copy (for GC) */ 303*8e3e3a7aSWarner Losh } 304*8e3e3a7aSWarner Losh for (; i < nfixargs; i++) 305*8e3e3a7aSWarner Losh setnilvalue(L->top++); /* complete missing arguments */ 306*8e3e3a7aSWarner Losh return base; 307*8e3e3a7aSWarner Losh } 308*8e3e3a7aSWarner Losh 309*8e3e3a7aSWarner Losh 310*8e3e3a7aSWarner Losh /* 311*8e3e3a7aSWarner Losh ** Check whether __call metafield of 'func' is a function. If so, put 312*8e3e3a7aSWarner Losh ** it in stack below original 'func' so that 'luaD_precall' can call 313*8e3e3a7aSWarner Losh ** it. Raise an error if __call metafield is not a function. 314*8e3e3a7aSWarner Losh */ 315*8e3e3a7aSWarner Losh static void tryfuncTM (lua_State *L, StkId func) { 316*8e3e3a7aSWarner Losh const TValue *tm = luaT_gettmbyobj(L, func, TM_CALL); 317*8e3e3a7aSWarner Losh StkId p; 318*8e3e3a7aSWarner Losh if (!ttisfunction(tm)) 319*8e3e3a7aSWarner Losh luaG_typeerror(L, func, "call"); 320*8e3e3a7aSWarner Losh /* Open a hole inside the stack at 'func' */ 321*8e3e3a7aSWarner Losh for (p = L->top; p > func; p--) 322*8e3e3a7aSWarner Losh setobjs2s(L, p, p-1); 323*8e3e3a7aSWarner Losh L->top++; /* slot ensured by caller */ 324*8e3e3a7aSWarner Losh setobj2s(L, func, tm); /* tag method is the new function to be called */ 325*8e3e3a7aSWarner Losh } 326*8e3e3a7aSWarner Losh 327*8e3e3a7aSWarner Losh 328*8e3e3a7aSWarner Losh /* 329*8e3e3a7aSWarner Losh ** Given 'nres' results at 'firstResult', move 'wanted' of them to 'res'. 330*8e3e3a7aSWarner Losh ** Handle most typical cases (zero results for commands, one result for 331*8e3e3a7aSWarner Losh ** expressions, multiple results for tail calls/single parameters) 332*8e3e3a7aSWarner Losh ** separated. 333*8e3e3a7aSWarner Losh */ 334*8e3e3a7aSWarner Losh static int moveresults (lua_State *L, const TValue *firstResult, StkId res, 335*8e3e3a7aSWarner Losh int nres, int wanted) { 336*8e3e3a7aSWarner Losh switch (wanted) { /* handle typical cases separately */ 337*8e3e3a7aSWarner Losh case 0: break; /* nothing to move */ 338*8e3e3a7aSWarner Losh case 1: { /* one result needed */ 339*8e3e3a7aSWarner Losh if (nres == 0) /* no results? */ 340*8e3e3a7aSWarner Losh firstResult = luaO_nilobject; /* adjust with nil */ 341*8e3e3a7aSWarner Losh setobjs2s(L, res, firstResult); /* move it to proper place */ 342*8e3e3a7aSWarner Losh break; 343*8e3e3a7aSWarner Losh } 344*8e3e3a7aSWarner Losh case LUA_MULTRET: { 345*8e3e3a7aSWarner Losh int i; 346*8e3e3a7aSWarner Losh for (i = 0; i < nres; i++) /* move all results to correct place */ 347*8e3e3a7aSWarner Losh setobjs2s(L, res + i, firstResult + i); 348*8e3e3a7aSWarner Losh L->top = res + nres; 349*8e3e3a7aSWarner Losh return 0; /* wanted == LUA_MULTRET */ 350*8e3e3a7aSWarner Losh } 351*8e3e3a7aSWarner Losh default: { 352*8e3e3a7aSWarner Losh int i; 353*8e3e3a7aSWarner Losh if (wanted <= nres) { /* enough results? */ 354*8e3e3a7aSWarner Losh for (i = 0; i < wanted; i++) /* move wanted results to correct place */ 355*8e3e3a7aSWarner Losh setobjs2s(L, res + i, firstResult + i); 356*8e3e3a7aSWarner Losh } 357*8e3e3a7aSWarner Losh else { /* not enough results; use all of them plus nils */ 358*8e3e3a7aSWarner Losh for (i = 0; i < nres; i++) /* move all results to correct place */ 359*8e3e3a7aSWarner Losh setobjs2s(L, res + i, firstResult + i); 360*8e3e3a7aSWarner Losh for (; i < wanted; i++) /* complete wanted number of results */ 361*8e3e3a7aSWarner Losh setnilvalue(res + i); 362*8e3e3a7aSWarner Losh } 363*8e3e3a7aSWarner Losh break; 364*8e3e3a7aSWarner Losh } 365*8e3e3a7aSWarner Losh } 366*8e3e3a7aSWarner Losh L->top = res + wanted; /* top points after the last result */ 367*8e3e3a7aSWarner Losh return 1; 368*8e3e3a7aSWarner Losh } 369*8e3e3a7aSWarner Losh 370*8e3e3a7aSWarner Losh 371*8e3e3a7aSWarner Losh /* 372*8e3e3a7aSWarner Losh ** Finishes a function call: calls hook if necessary, removes CallInfo, 373*8e3e3a7aSWarner Losh ** moves current number of results to proper place; returns 0 iff call 374*8e3e3a7aSWarner Losh ** wanted multiple (variable number of) results. 375*8e3e3a7aSWarner Losh */ 376*8e3e3a7aSWarner Losh int luaD_poscall (lua_State *L, CallInfo *ci, StkId firstResult, int nres) { 377*8e3e3a7aSWarner Losh StkId res; 378*8e3e3a7aSWarner Losh int wanted = ci->nresults; 379*8e3e3a7aSWarner Losh if (L->hookmask & (LUA_MASKRET | LUA_MASKLINE)) { 380*8e3e3a7aSWarner Losh if (L->hookmask & LUA_MASKRET) { 381*8e3e3a7aSWarner Losh ptrdiff_t fr = savestack(L, firstResult); /* hook may change stack */ 382*8e3e3a7aSWarner Losh luaD_hook(L, LUA_HOOKRET, -1); 383*8e3e3a7aSWarner Losh firstResult = restorestack(L, fr); 384*8e3e3a7aSWarner Losh } 385*8e3e3a7aSWarner Losh L->oldpc = ci->previous->u.l.savedpc; /* 'oldpc' for caller function */ 386*8e3e3a7aSWarner Losh } 387*8e3e3a7aSWarner Losh res = ci->func; /* res == final position of 1st result */ 388*8e3e3a7aSWarner Losh L->ci = ci->previous; /* back to caller */ 389*8e3e3a7aSWarner Losh /* move results to proper place */ 390*8e3e3a7aSWarner Losh return moveresults(L, firstResult, res, nres, wanted); 391*8e3e3a7aSWarner Losh } 392*8e3e3a7aSWarner Losh 393*8e3e3a7aSWarner Losh 394*8e3e3a7aSWarner Losh 395*8e3e3a7aSWarner Losh #define next_ci(L) (L->ci = (L->ci->next ? L->ci->next : luaE_extendCI(L))) 396*8e3e3a7aSWarner Losh 397*8e3e3a7aSWarner Losh 398*8e3e3a7aSWarner Losh /* macro to check stack size, preserving 'p' */ 399*8e3e3a7aSWarner Losh #define checkstackp(L,n,p) \ 400*8e3e3a7aSWarner Losh luaD_checkstackaux(L, n, \ 401*8e3e3a7aSWarner Losh ptrdiff_t t__ = savestack(L, p); /* save 'p' */ \ 402*8e3e3a7aSWarner Losh luaC_checkGC(L), /* stack grow uses memory */ \ 403*8e3e3a7aSWarner Losh p = restorestack(L, t__)) /* 'pos' part: restore 'p' */ 404*8e3e3a7aSWarner Losh 405*8e3e3a7aSWarner Losh 406*8e3e3a7aSWarner Losh /* 407*8e3e3a7aSWarner Losh ** Prepares a function call: checks the stack, creates a new CallInfo 408*8e3e3a7aSWarner Losh ** entry, fills in the relevant information, calls hook if needed. 409*8e3e3a7aSWarner Losh ** If function is a C function, does the call, too. (Otherwise, leave 410*8e3e3a7aSWarner Losh ** the execution ('luaV_execute') to the caller, to allow stackless 411*8e3e3a7aSWarner Losh ** calls.) Returns true iff function has been executed (C function). 412*8e3e3a7aSWarner Losh */ 413*8e3e3a7aSWarner Losh int luaD_precall (lua_State *L, StkId func, int nresults) { 414*8e3e3a7aSWarner Losh lua_CFunction f; 415*8e3e3a7aSWarner Losh CallInfo *ci; 416*8e3e3a7aSWarner Losh switch (ttype(func)) { 417*8e3e3a7aSWarner Losh case LUA_TCCL: /* C closure */ 418*8e3e3a7aSWarner Losh f = clCvalue(func)->f; 419*8e3e3a7aSWarner Losh goto Cfunc; 420*8e3e3a7aSWarner Losh case LUA_TLCF: /* light C function */ 421*8e3e3a7aSWarner Losh f = fvalue(func); 422*8e3e3a7aSWarner Losh Cfunc: { 423*8e3e3a7aSWarner Losh int n; /* number of returns */ 424*8e3e3a7aSWarner Losh checkstackp(L, LUA_MINSTACK, func); /* ensure minimum stack size */ 425*8e3e3a7aSWarner Losh ci = next_ci(L); /* now 'enter' new function */ 426*8e3e3a7aSWarner Losh ci->nresults = nresults; 427*8e3e3a7aSWarner Losh ci->func = func; 428*8e3e3a7aSWarner Losh ci->top = L->top + LUA_MINSTACK; 429*8e3e3a7aSWarner Losh lua_assert(ci->top <= L->stack_last); 430*8e3e3a7aSWarner Losh ci->callstatus = 0; 431*8e3e3a7aSWarner Losh if (L->hookmask & LUA_MASKCALL) 432*8e3e3a7aSWarner Losh luaD_hook(L, LUA_HOOKCALL, -1); 433*8e3e3a7aSWarner Losh lua_unlock(L); 434*8e3e3a7aSWarner Losh n = (*f)(L); /* do the actual call */ 435*8e3e3a7aSWarner Losh lua_lock(L); 436*8e3e3a7aSWarner Losh api_checknelems(L, n); 437*8e3e3a7aSWarner Losh luaD_poscall(L, ci, L->top - n, n); 438*8e3e3a7aSWarner Losh return 1; 439*8e3e3a7aSWarner Losh } 440*8e3e3a7aSWarner Losh case LUA_TLCL: { /* Lua function: prepare its call */ 441*8e3e3a7aSWarner Losh StkId base; 442*8e3e3a7aSWarner Losh Proto *p = clLvalue(func)->p; 443*8e3e3a7aSWarner Losh int n = cast_int(L->top - func) - 1; /* number of real arguments */ 444*8e3e3a7aSWarner Losh int fsize = p->maxstacksize; /* frame size */ 445*8e3e3a7aSWarner Losh checkstackp(L, fsize, func); 446*8e3e3a7aSWarner Losh if (p->is_vararg) 447*8e3e3a7aSWarner Losh base = adjust_varargs(L, p, n); 448*8e3e3a7aSWarner Losh else { /* non vararg function */ 449*8e3e3a7aSWarner Losh for (; n < p->numparams; n++) 450*8e3e3a7aSWarner Losh setnilvalue(L->top++); /* complete missing arguments */ 451*8e3e3a7aSWarner Losh base = func + 1; 452*8e3e3a7aSWarner Losh } 453*8e3e3a7aSWarner Losh ci = next_ci(L); /* now 'enter' new function */ 454*8e3e3a7aSWarner Losh ci->nresults = nresults; 455*8e3e3a7aSWarner Losh ci->func = func; 456*8e3e3a7aSWarner Losh ci->u.l.base = base; 457*8e3e3a7aSWarner Losh L->top = ci->top = base + fsize; 458*8e3e3a7aSWarner Losh lua_assert(ci->top <= L->stack_last); 459*8e3e3a7aSWarner Losh ci->u.l.savedpc = p->code; /* starting point */ 460*8e3e3a7aSWarner Losh ci->callstatus = CIST_LUA; 461*8e3e3a7aSWarner Losh if (L->hookmask & LUA_MASKCALL) 462*8e3e3a7aSWarner Losh callhook(L, ci); 463*8e3e3a7aSWarner Losh return 0; 464*8e3e3a7aSWarner Losh } 465*8e3e3a7aSWarner Losh default: { /* not a function */ 466*8e3e3a7aSWarner Losh checkstackp(L, 1, func); /* ensure space for metamethod */ 467*8e3e3a7aSWarner Losh tryfuncTM(L, func); /* try to get '__call' metamethod */ 468*8e3e3a7aSWarner Losh return luaD_precall(L, func, nresults); /* now it must be a function */ 469*8e3e3a7aSWarner Losh } 470*8e3e3a7aSWarner Losh } 471*8e3e3a7aSWarner Losh } 472*8e3e3a7aSWarner Losh 473*8e3e3a7aSWarner Losh 474*8e3e3a7aSWarner Losh /* 475*8e3e3a7aSWarner Losh ** Check appropriate error for stack overflow ("regular" overflow or 476*8e3e3a7aSWarner Losh ** overflow while handling stack overflow). If 'nCalls' is larger than 477*8e3e3a7aSWarner Losh ** LUAI_MAXCCALLS (which means it is handling a "regular" overflow) but 478*8e3e3a7aSWarner Losh ** smaller than 9/8 of LUAI_MAXCCALLS, does not report an error (to 479*8e3e3a7aSWarner Losh ** allow overflow handling to work) 480*8e3e3a7aSWarner Losh */ 481*8e3e3a7aSWarner Losh static void stackerror (lua_State *L) { 482*8e3e3a7aSWarner Losh if (L->nCcalls == LUAI_MAXCCALLS) 483*8e3e3a7aSWarner Losh luaG_runerror(L, "C stack overflow"); 484*8e3e3a7aSWarner Losh else if (L->nCcalls >= (LUAI_MAXCCALLS + (LUAI_MAXCCALLS>>3))) 485*8e3e3a7aSWarner Losh luaD_throw(L, LUA_ERRERR); /* error while handing stack error */ 486*8e3e3a7aSWarner Losh } 487*8e3e3a7aSWarner Losh 488*8e3e3a7aSWarner Losh 489*8e3e3a7aSWarner Losh /* 490*8e3e3a7aSWarner Losh ** Call a function (C or Lua). The function to be called is at *func. 491*8e3e3a7aSWarner Losh ** The arguments are on the stack, right after the function. 492*8e3e3a7aSWarner Losh ** When returns, all the results are on the stack, starting at the original 493*8e3e3a7aSWarner Losh ** function position. 494*8e3e3a7aSWarner Losh */ 495*8e3e3a7aSWarner Losh void luaD_call (lua_State *L, StkId func, int nResults) { 496*8e3e3a7aSWarner Losh if (++L->nCcalls >= LUAI_MAXCCALLS) 497*8e3e3a7aSWarner Losh stackerror(L); 498*8e3e3a7aSWarner Losh if (!luaD_precall(L, func, nResults)) /* is a Lua function? */ 499*8e3e3a7aSWarner Losh luaV_execute(L); /* call it */ 500*8e3e3a7aSWarner Losh L->nCcalls--; 501*8e3e3a7aSWarner Losh } 502*8e3e3a7aSWarner Losh 503*8e3e3a7aSWarner Losh 504*8e3e3a7aSWarner Losh /* 505*8e3e3a7aSWarner Losh ** Similar to 'luaD_call', but does not allow yields during the call 506*8e3e3a7aSWarner Losh */ 507*8e3e3a7aSWarner Losh void luaD_callnoyield (lua_State *L, StkId func, int nResults) { 508*8e3e3a7aSWarner Losh L->nny++; 509*8e3e3a7aSWarner Losh luaD_call(L, func, nResults); 510*8e3e3a7aSWarner Losh L->nny--; 511*8e3e3a7aSWarner Losh } 512*8e3e3a7aSWarner Losh 513*8e3e3a7aSWarner Losh 514*8e3e3a7aSWarner Losh /* 515*8e3e3a7aSWarner Losh ** Completes the execution of an interrupted C function, calling its 516*8e3e3a7aSWarner Losh ** continuation function. 517*8e3e3a7aSWarner Losh */ 518*8e3e3a7aSWarner Losh static void finishCcall (lua_State *L, int status) { 519*8e3e3a7aSWarner Losh CallInfo *ci = L->ci; 520*8e3e3a7aSWarner Losh int n; 521*8e3e3a7aSWarner Losh /* must have a continuation and must be able to call it */ 522*8e3e3a7aSWarner Losh lua_assert(ci->u.c.k != NULL && L->nny == 0); 523*8e3e3a7aSWarner Losh /* error status can only happen in a protected call */ 524*8e3e3a7aSWarner Losh lua_assert((ci->callstatus & CIST_YPCALL) || status == LUA_YIELD); 525*8e3e3a7aSWarner Losh if (ci->callstatus & CIST_YPCALL) { /* was inside a pcall? */ 526*8e3e3a7aSWarner Losh ci->callstatus &= ~CIST_YPCALL; /* continuation is also inside it */ 527*8e3e3a7aSWarner Losh L->errfunc = ci->u.c.old_errfunc; /* with the same error function */ 528*8e3e3a7aSWarner Losh } 529*8e3e3a7aSWarner Losh /* finish 'lua_callk'/'lua_pcall'; CIST_YPCALL and 'errfunc' already 530*8e3e3a7aSWarner Losh handled */ 531*8e3e3a7aSWarner Losh adjustresults(L, ci->nresults); 532*8e3e3a7aSWarner Losh lua_unlock(L); 533*8e3e3a7aSWarner Losh n = (*ci->u.c.k)(L, status, ci->u.c.ctx); /* call continuation function */ 534*8e3e3a7aSWarner Losh lua_lock(L); 535*8e3e3a7aSWarner Losh api_checknelems(L, n); 536*8e3e3a7aSWarner Losh luaD_poscall(L, ci, L->top - n, n); /* finish 'luaD_precall' */ 537*8e3e3a7aSWarner Losh } 538*8e3e3a7aSWarner Losh 539*8e3e3a7aSWarner Losh 540*8e3e3a7aSWarner Losh /* 541*8e3e3a7aSWarner Losh ** Executes "full continuation" (everything in the stack) of a 542*8e3e3a7aSWarner Losh ** previously interrupted coroutine until the stack is empty (or another 543*8e3e3a7aSWarner Losh ** interruption long-jumps out of the loop). If the coroutine is 544*8e3e3a7aSWarner Losh ** recovering from an error, 'ud' points to the error status, which must 545*8e3e3a7aSWarner Losh ** be passed to the first continuation function (otherwise the default 546*8e3e3a7aSWarner Losh ** status is LUA_YIELD). 547*8e3e3a7aSWarner Losh */ 548*8e3e3a7aSWarner Losh static void unroll (lua_State *L, void *ud) { 549*8e3e3a7aSWarner Losh if (ud != NULL) /* error status? */ 550*8e3e3a7aSWarner Losh finishCcall(L, *(int *)ud); /* finish 'lua_pcallk' callee */ 551*8e3e3a7aSWarner Losh while (L->ci != &L->base_ci) { /* something in the stack */ 552*8e3e3a7aSWarner Losh if (!isLua(L->ci)) /* C function? */ 553*8e3e3a7aSWarner Losh finishCcall(L, LUA_YIELD); /* complete its execution */ 554*8e3e3a7aSWarner Losh else { /* Lua function */ 555*8e3e3a7aSWarner Losh luaV_finishOp(L); /* finish interrupted instruction */ 556*8e3e3a7aSWarner Losh luaV_execute(L); /* execute down to higher C 'boundary' */ 557*8e3e3a7aSWarner Losh } 558*8e3e3a7aSWarner Losh } 559*8e3e3a7aSWarner Losh } 560*8e3e3a7aSWarner Losh 561*8e3e3a7aSWarner Losh 562*8e3e3a7aSWarner Losh /* 563*8e3e3a7aSWarner Losh ** Try to find a suspended protected call (a "recover point") for the 564*8e3e3a7aSWarner Losh ** given thread. 565*8e3e3a7aSWarner Losh */ 566*8e3e3a7aSWarner Losh static CallInfo *findpcall (lua_State *L) { 567*8e3e3a7aSWarner Losh CallInfo *ci; 568*8e3e3a7aSWarner Losh for (ci = L->ci; ci != NULL; ci = ci->previous) { /* search for a pcall */ 569*8e3e3a7aSWarner Losh if (ci->callstatus & CIST_YPCALL) 570*8e3e3a7aSWarner Losh return ci; 571*8e3e3a7aSWarner Losh } 572*8e3e3a7aSWarner Losh return NULL; /* no pending pcall */ 573*8e3e3a7aSWarner Losh } 574*8e3e3a7aSWarner Losh 575*8e3e3a7aSWarner Losh 576*8e3e3a7aSWarner Losh /* 577*8e3e3a7aSWarner Losh ** Recovers from an error in a coroutine. Finds a recover point (if 578*8e3e3a7aSWarner Losh ** there is one) and completes the execution of the interrupted 579*8e3e3a7aSWarner Losh ** 'luaD_pcall'. If there is no recover point, returns zero. 580*8e3e3a7aSWarner Losh */ 581*8e3e3a7aSWarner Losh static int recover (lua_State *L, int status) { 582*8e3e3a7aSWarner Losh StkId oldtop; 583*8e3e3a7aSWarner Losh CallInfo *ci = findpcall(L); 584*8e3e3a7aSWarner Losh if (ci == NULL) return 0; /* no recovery point */ 585*8e3e3a7aSWarner Losh /* "finish" luaD_pcall */ 586*8e3e3a7aSWarner Losh oldtop = restorestack(L, ci->extra); 587*8e3e3a7aSWarner Losh luaF_close(L, oldtop); 588*8e3e3a7aSWarner Losh seterrorobj(L, status, oldtop); 589*8e3e3a7aSWarner Losh L->ci = ci; 590*8e3e3a7aSWarner Losh L->allowhook = getoah(ci->callstatus); /* restore original 'allowhook' */ 591*8e3e3a7aSWarner Losh L->nny = 0; /* should be zero to be yieldable */ 592*8e3e3a7aSWarner Losh luaD_shrinkstack(L); 593*8e3e3a7aSWarner Losh L->errfunc = ci->u.c.old_errfunc; 594*8e3e3a7aSWarner Losh return 1; /* continue running the coroutine */ 595*8e3e3a7aSWarner Losh } 596*8e3e3a7aSWarner Losh 597*8e3e3a7aSWarner Losh 598*8e3e3a7aSWarner Losh /* 599*8e3e3a7aSWarner Losh ** Signal an error in the call to 'lua_resume', not in the execution 600*8e3e3a7aSWarner Losh ** of the coroutine itself. (Such errors should not be handled by any 601*8e3e3a7aSWarner Losh ** coroutine error handler and should not kill the coroutine.) 602*8e3e3a7aSWarner Losh */ 603*8e3e3a7aSWarner Losh static int resume_error (lua_State *L, const char *msg, int narg) { 604*8e3e3a7aSWarner Losh L->top -= narg; /* remove args from the stack */ 605*8e3e3a7aSWarner Losh setsvalue2s(L, L->top, luaS_new(L, msg)); /* push error message */ 606*8e3e3a7aSWarner Losh api_incr_top(L); 607*8e3e3a7aSWarner Losh lua_unlock(L); 608*8e3e3a7aSWarner Losh return LUA_ERRRUN; 609*8e3e3a7aSWarner Losh } 610*8e3e3a7aSWarner Losh 611*8e3e3a7aSWarner Losh 612*8e3e3a7aSWarner Losh /* 613*8e3e3a7aSWarner Losh ** Do the work for 'lua_resume' in protected mode. Most of the work 614*8e3e3a7aSWarner Losh ** depends on the status of the coroutine: initial state, suspended 615*8e3e3a7aSWarner Losh ** inside a hook, or regularly suspended (optionally with a continuation 616*8e3e3a7aSWarner Losh ** function), plus erroneous cases: non-suspended coroutine or dead 617*8e3e3a7aSWarner Losh ** coroutine. 618*8e3e3a7aSWarner Losh */ 619*8e3e3a7aSWarner Losh static void resume (lua_State *L, void *ud) { 620*8e3e3a7aSWarner Losh int n = *(cast(int*, ud)); /* number of arguments */ 621*8e3e3a7aSWarner Losh StkId firstArg = L->top - n; /* first argument */ 622*8e3e3a7aSWarner Losh CallInfo *ci = L->ci; 623*8e3e3a7aSWarner Losh if (L->status == LUA_OK) { /* starting a coroutine? */ 624*8e3e3a7aSWarner Losh if (!luaD_precall(L, firstArg - 1, LUA_MULTRET)) /* Lua function? */ 625*8e3e3a7aSWarner Losh luaV_execute(L); /* call it */ 626*8e3e3a7aSWarner Losh } 627*8e3e3a7aSWarner Losh else { /* resuming from previous yield */ 628*8e3e3a7aSWarner Losh lua_assert(L->status == LUA_YIELD); 629*8e3e3a7aSWarner Losh L->status = LUA_OK; /* mark that it is running (again) */ 630*8e3e3a7aSWarner Losh ci->func = restorestack(L, ci->extra); 631*8e3e3a7aSWarner Losh if (isLua(ci)) /* yielded inside a hook? */ 632*8e3e3a7aSWarner Losh luaV_execute(L); /* just continue running Lua code */ 633*8e3e3a7aSWarner Losh else { /* 'common' yield */ 634*8e3e3a7aSWarner Losh if (ci->u.c.k != NULL) { /* does it have a continuation function? */ 635*8e3e3a7aSWarner Losh lua_unlock(L); 636*8e3e3a7aSWarner Losh n = (*ci->u.c.k)(L, LUA_YIELD, ci->u.c.ctx); /* call continuation */ 637*8e3e3a7aSWarner Losh lua_lock(L); 638*8e3e3a7aSWarner Losh api_checknelems(L, n); 639*8e3e3a7aSWarner Losh firstArg = L->top - n; /* yield results come from continuation */ 640*8e3e3a7aSWarner Losh } 641*8e3e3a7aSWarner Losh luaD_poscall(L, ci, firstArg, n); /* finish 'luaD_precall' */ 642*8e3e3a7aSWarner Losh } 643*8e3e3a7aSWarner Losh unroll(L, NULL); /* run continuation */ 644*8e3e3a7aSWarner Losh } 645*8e3e3a7aSWarner Losh } 646*8e3e3a7aSWarner Losh 647*8e3e3a7aSWarner Losh 648*8e3e3a7aSWarner Losh LUA_API int lua_resume (lua_State *L, lua_State *from, int nargs) { 649*8e3e3a7aSWarner Losh int status; 650*8e3e3a7aSWarner Losh unsigned short oldnny = L->nny; /* save "number of non-yieldable" calls */ 651*8e3e3a7aSWarner Losh lua_lock(L); 652*8e3e3a7aSWarner Losh if (L->status == LUA_OK) { /* may be starting a coroutine */ 653*8e3e3a7aSWarner Losh if (L->ci != &L->base_ci) /* not in base level? */ 654*8e3e3a7aSWarner Losh return resume_error(L, "cannot resume non-suspended coroutine", nargs); 655*8e3e3a7aSWarner Losh } 656*8e3e3a7aSWarner Losh else if (L->status != LUA_YIELD) 657*8e3e3a7aSWarner Losh return resume_error(L, "cannot resume dead coroutine", nargs); 658*8e3e3a7aSWarner Losh L->nCcalls = (from) ? from->nCcalls + 1 : 1; 659*8e3e3a7aSWarner Losh if (L->nCcalls >= LUAI_MAXCCALLS) 660*8e3e3a7aSWarner Losh return resume_error(L, "C stack overflow", nargs); 661*8e3e3a7aSWarner Losh luai_userstateresume(L, nargs); 662*8e3e3a7aSWarner Losh L->nny = 0; /* allow yields */ 663*8e3e3a7aSWarner Losh api_checknelems(L, (L->status == LUA_OK) ? nargs + 1 : nargs); 664*8e3e3a7aSWarner Losh status = luaD_rawrunprotected(L, resume, &nargs); 665*8e3e3a7aSWarner Losh if (status == -1) /* error calling 'lua_resume'? */ 666*8e3e3a7aSWarner Losh status = LUA_ERRRUN; 667*8e3e3a7aSWarner Losh else { /* continue running after recoverable errors */ 668*8e3e3a7aSWarner Losh while (errorstatus(status) && recover(L, status)) { 669*8e3e3a7aSWarner Losh /* unroll continuation */ 670*8e3e3a7aSWarner Losh status = luaD_rawrunprotected(L, unroll, &status); 671*8e3e3a7aSWarner Losh } 672*8e3e3a7aSWarner Losh if (errorstatus(status)) { /* unrecoverable error? */ 673*8e3e3a7aSWarner Losh L->status = cast_byte(status); /* mark thread as 'dead' */ 674*8e3e3a7aSWarner Losh seterrorobj(L, status, L->top); /* push error message */ 675*8e3e3a7aSWarner Losh L->ci->top = L->top; 676*8e3e3a7aSWarner Losh } 677*8e3e3a7aSWarner Losh else lua_assert(status == L->status); /* normal end or yield */ 678*8e3e3a7aSWarner Losh } 679*8e3e3a7aSWarner Losh L->nny = oldnny; /* restore 'nny' */ 680*8e3e3a7aSWarner Losh L->nCcalls--; 681*8e3e3a7aSWarner Losh lua_assert(L->nCcalls == ((from) ? from->nCcalls : 0)); 682*8e3e3a7aSWarner Losh lua_unlock(L); 683*8e3e3a7aSWarner Losh return status; 684*8e3e3a7aSWarner Losh } 685*8e3e3a7aSWarner Losh 686*8e3e3a7aSWarner Losh 687*8e3e3a7aSWarner Losh LUA_API int lua_isyieldable (lua_State *L) { 688*8e3e3a7aSWarner Losh return (L->nny == 0); 689*8e3e3a7aSWarner Losh } 690*8e3e3a7aSWarner Losh 691*8e3e3a7aSWarner Losh 692*8e3e3a7aSWarner Losh LUA_API int lua_yieldk (lua_State *L, int nresults, lua_KContext ctx, 693*8e3e3a7aSWarner Losh lua_KFunction k) { 694*8e3e3a7aSWarner Losh CallInfo *ci = L->ci; 695*8e3e3a7aSWarner Losh luai_userstateyield(L, nresults); 696*8e3e3a7aSWarner Losh lua_lock(L); 697*8e3e3a7aSWarner Losh api_checknelems(L, nresults); 698*8e3e3a7aSWarner Losh if (L->nny > 0) { 699*8e3e3a7aSWarner Losh if (L != G(L)->mainthread) 700*8e3e3a7aSWarner Losh luaG_runerror(L, "attempt to yield across a C-call boundary"); 701*8e3e3a7aSWarner Losh else 702*8e3e3a7aSWarner Losh luaG_runerror(L, "attempt to yield from outside a coroutine"); 703*8e3e3a7aSWarner Losh } 704*8e3e3a7aSWarner Losh L->status = LUA_YIELD; 705*8e3e3a7aSWarner Losh ci->extra = savestack(L, ci->func); /* save current 'func' */ 706*8e3e3a7aSWarner Losh if (isLua(ci)) { /* inside a hook? */ 707*8e3e3a7aSWarner Losh api_check(L, k == NULL, "hooks cannot continue after yielding"); 708*8e3e3a7aSWarner Losh } 709*8e3e3a7aSWarner Losh else { 710*8e3e3a7aSWarner Losh if ((ci->u.c.k = k) != NULL) /* is there a continuation? */ 711*8e3e3a7aSWarner Losh ci->u.c.ctx = ctx; /* save context */ 712*8e3e3a7aSWarner Losh ci->func = L->top - nresults - 1; /* protect stack below results */ 713*8e3e3a7aSWarner Losh luaD_throw(L, LUA_YIELD); 714*8e3e3a7aSWarner Losh } 715*8e3e3a7aSWarner Losh lua_assert(ci->callstatus & CIST_HOOKED); /* must be inside a hook */ 716*8e3e3a7aSWarner Losh lua_unlock(L); 717*8e3e3a7aSWarner Losh return 0; /* return to 'luaD_hook' */ 718*8e3e3a7aSWarner Losh } 719*8e3e3a7aSWarner Losh 720*8e3e3a7aSWarner Losh 721*8e3e3a7aSWarner Losh int luaD_pcall (lua_State *L, Pfunc func, void *u, 722*8e3e3a7aSWarner Losh ptrdiff_t old_top, ptrdiff_t ef) { 723*8e3e3a7aSWarner Losh int status; 724*8e3e3a7aSWarner Losh CallInfo *old_ci = L->ci; 725*8e3e3a7aSWarner Losh lu_byte old_allowhooks = L->allowhook; 726*8e3e3a7aSWarner Losh unsigned short old_nny = L->nny; 727*8e3e3a7aSWarner Losh ptrdiff_t old_errfunc = L->errfunc; 728*8e3e3a7aSWarner Losh L->errfunc = ef; 729*8e3e3a7aSWarner Losh status = luaD_rawrunprotected(L, func, u); 730*8e3e3a7aSWarner Losh if (status != LUA_OK) { /* an error occurred? */ 731*8e3e3a7aSWarner Losh StkId oldtop = restorestack(L, old_top); 732*8e3e3a7aSWarner Losh luaF_close(L, oldtop); /* close possible pending closures */ 733*8e3e3a7aSWarner Losh seterrorobj(L, status, oldtop); 734*8e3e3a7aSWarner Losh L->ci = old_ci; 735*8e3e3a7aSWarner Losh L->allowhook = old_allowhooks; 736*8e3e3a7aSWarner Losh L->nny = old_nny; 737*8e3e3a7aSWarner Losh luaD_shrinkstack(L); 738*8e3e3a7aSWarner Losh } 739*8e3e3a7aSWarner Losh L->errfunc = old_errfunc; 740*8e3e3a7aSWarner Losh return status; 741*8e3e3a7aSWarner Losh } 742*8e3e3a7aSWarner Losh 743*8e3e3a7aSWarner Losh 744*8e3e3a7aSWarner Losh 745*8e3e3a7aSWarner Losh /* 746*8e3e3a7aSWarner Losh ** Execute a protected parser. 747*8e3e3a7aSWarner Losh */ 748*8e3e3a7aSWarner Losh struct SParser { /* data to 'f_parser' */ 749*8e3e3a7aSWarner Losh ZIO *z; 750*8e3e3a7aSWarner Losh Mbuffer buff; /* dynamic structure used by the scanner */ 751*8e3e3a7aSWarner Losh Dyndata dyd; /* dynamic structures used by the parser */ 752*8e3e3a7aSWarner Losh const char *mode; 753*8e3e3a7aSWarner Losh const char *name; 754*8e3e3a7aSWarner Losh }; 755*8e3e3a7aSWarner Losh 756*8e3e3a7aSWarner Losh 757*8e3e3a7aSWarner Losh static void checkmode (lua_State *L, const char *mode, const char *x) { 758*8e3e3a7aSWarner Losh if (mode && strchr(mode, x[0]) == NULL) { 759*8e3e3a7aSWarner Losh luaO_pushfstring(L, 760*8e3e3a7aSWarner Losh "attempt to load a %s chunk (mode is '%s')", x, mode); 761*8e3e3a7aSWarner Losh luaD_throw(L, LUA_ERRSYNTAX); 762*8e3e3a7aSWarner Losh } 763*8e3e3a7aSWarner Losh } 764*8e3e3a7aSWarner Losh 765*8e3e3a7aSWarner Losh 766*8e3e3a7aSWarner Losh static void f_parser (lua_State *L, void *ud) { 767*8e3e3a7aSWarner Losh LClosure *cl; 768*8e3e3a7aSWarner Losh struct SParser *p = cast(struct SParser *, ud); 769*8e3e3a7aSWarner Losh int c = zgetc(p->z); /* read first character */ 770*8e3e3a7aSWarner Losh if (c == LUA_SIGNATURE[0]) { 771*8e3e3a7aSWarner Losh checkmode(L, p->mode, "binary"); 772*8e3e3a7aSWarner Losh cl = luaU_undump(L, p->z, p->name); 773*8e3e3a7aSWarner Losh } 774*8e3e3a7aSWarner Losh else { 775*8e3e3a7aSWarner Losh checkmode(L, p->mode, "text"); 776*8e3e3a7aSWarner Losh cl = luaY_parser(L, p->z, &p->buff, &p->dyd, p->name, c); 777*8e3e3a7aSWarner Losh } 778*8e3e3a7aSWarner Losh lua_assert(cl->nupvalues == cl->p->sizeupvalues); 779*8e3e3a7aSWarner Losh luaF_initupvals(L, cl); 780*8e3e3a7aSWarner Losh } 781*8e3e3a7aSWarner Losh 782*8e3e3a7aSWarner Losh 783*8e3e3a7aSWarner Losh int luaD_protectedparser (lua_State *L, ZIO *z, const char *name, 784*8e3e3a7aSWarner Losh const char *mode) { 785*8e3e3a7aSWarner Losh struct SParser p; 786*8e3e3a7aSWarner Losh int status; 787*8e3e3a7aSWarner Losh L->nny++; /* cannot yield during parsing */ 788*8e3e3a7aSWarner Losh p.z = z; p.name = name; p.mode = mode; 789*8e3e3a7aSWarner Losh p.dyd.actvar.arr = NULL; p.dyd.actvar.size = 0; 790*8e3e3a7aSWarner Losh p.dyd.gt.arr = NULL; p.dyd.gt.size = 0; 791*8e3e3a7aSWarner Losh p.dyd.label.arr = NULL; p.dyd.label.size = 0; 792*8e3e3a7aSWarner Losh luaZ_initbuffer(L, &p.buff); 793*8e3e3a7aSWarner Losh status = luaD_pcall(L, f_parser, &p, savestack(L, L->top), L->errfunc); 794*8e3e3a7aSWarner Losh luaZ_freebuffer(L, &p.buff); 795*8e3e3a7aSWarner Losh luaM_freearray(L, p.dyd.actvar.arr, p.dyd.actvar.size); 796*8e3e3a7aSWarner Losh luaM_freearray(L, p.dyd.gt.arr, p.dyd.gt.size); 797*8e3e3a7aSWarner Losh luaM_freearray(L, p.dyd.label.arr, p.dyd.label.size); 798*8e3e3a7aSWarner Losh L->nny--; 799*8e3e3a7aSWarner Losh return status; 800*8e3e3a7aSWarner Losh } 801*8e3e3a7aSWarner Losh 802*8e3e3a7aSWarner Losh 803