- /* 
- ** $Id: ldo.c,v 2.157.1.1 2017/04/19 17:20:42 roberto Exp $ 
- ** Stack and Call structure of Lua 
- ** See Copyright Notice in lua.h 
- */ 
-   
- #define ldo_c 
- #define LUA_CORE 
-   
- #include "lprefix.h" 
-   
-   
- #include <setjmp.h> 
- #include <stdlib.h> 
- #include <string.h> 
-   
- #include "lua.h" 
-   
- #include "lapi.h" 
- #include "ldebug.h" 
- #include "ldo.h" 
- #include "lfunc.h" 
- #include "lgc.h" 
- #include "lmem.h" 
- #include "lobject.h" 
- #include "lopcodes.h" 
- #include "lparser.h" 
- #include "lstate.h" 
- #include "lstring.h" 
- #include "ltable.h" 
- #include "ltm.h" 
- #include "lundump.h" 
- #include "lvm.h" 
- #include "lzio.h" 
-   
-   
-   
- #define errorstatus(s)  ((s) > LUA_YIELD) 
-   
-   
- /* 
- ** {====================================================== 
- ** Error-recovery functions 
- ** ======================================================= 
- */ 
-   
- /* 
- ** LUAI_THROW/LUAI_TRY define how Lua does exception handling. By 
- ** default, Lua handles errors with exceptions when compiling as 
- ** C++ code, with _longjmp/_setjmp when asked to use them, and with 
- ** longjmp/setjmp otherwise. 
- */ 
- #if !defined(LUAI_THROW)                                /* { */ 
-   
- #if defined(__cplusplus) && !defined(LUA_USE_LONGJMP)   /* { */ 
-   
- /* C++ exceptions */ 
- #define LUAI_THROW(L,c)         throw(c) 
- #define LUAI_TRY(L,c,a) \ 
-         try { a } catch(...) { if ((c)->status == 0) (c)->status = -1; } 
- #define luai_jmpbuf             int  /* dummy variable */ 
-   
- #elif defined(LUA_USE_POSIX)                            /* }{ */ 
-   
- /* in POSIX, try _longjmp/_setjmp (more efficient) */ 
- #define LUAI_THROW(L,c)         _longjmp((c)->b, 1) 
- #define LUAI_TRY(L,c,a)         if (_setjmp((c)->b) == 0) { a } 
- #define luai_jmpbuf             jmp_buf 
-   
- #else                                                   /* }{ */ 
-   
- /* ISO C handling with long jumps */ 
- #define LUAI_THROW(L,c)         longjmp((c)->b, 1) 
- #define LUAI_TRY(L,c,a)         if (setjmp((c)->b) == 0) { a } 
- #define luai_jmpbuf             jmp_buf 
-   
- #endif                                                  /* } */ 
-   
- #endif                                                  /* } */ 
-   
-   
-   
- /* chain list of long jump buffers */ 
- struct lua_longjmp { 
-   struct lua_longjmp *previous; 
-   luai_jmpbuf b; 
-   volatile int status;  /* error code */ 
- }; 
-   
-   
- static void seterrorobj (lua_State *L, int errcode, StkId oldtop) { 
-   switch (errcode) { 
-     case LUA_ERRMEM: {  /* memory error? */ 
-       setsvalue2s(L, oldtop, G(L)->memerrmsg); /* reuse preregistered msg. */ 
-       break; 
-     } 
-     case LUA_ERRERR: { 
-       setsvalue2s(L, oldtop, luaS_newliteral(L, "error in error handling")); 
-       break; 
-     } 
-     default: { 
-       setobjs2s(L, oldtop, L->top - 1);  /* error message on current top */ 
-       break; 
-     } 
-   } 
-   L->top = oldtop + 1; 
- } 
-   
-   
- l_noret luaD_throw (lua_State *L, int errcode) { 
-   if (L->errorJmp) {  /* thread has an error handler? */ 
-     L->errorJmp->status = errcode;  /* set status */ 
-     LUAI_THROW(L, L->errorJmp);  /* jump to it */ 
-   } 
-   else {  /* thread has no error handler */ 
-     global_State *g = G(L); 
-     L->status = cast_byte(errcode);  /* mark it as dead */ 
-     if (g->mainthread->errorJmp) {  /* main thread has a handler? */ 
-       setobjs2s(L, g->mainthread->top++, L->top - 1);  /* copy error obj. */ 
-       luaD_throw(g->mainthread, errcode);  /* re-throw in main thread */ 
-     } 
-     else {  /* no handler at all; abort */ 
-       if (g->panic) {  /* panic function? */ 
-         seterrorobj(L, errcode, L->top);  /* assume EXTRA_STACK */ 
-         if (L->ci->top < L->top) 
-           L->ci->top = L->top;  /* pushing msg. can break this invariant */ 
-         lua_unlock(L); 
-         g->panic(L);  /* call panic function (last chance to jump out) */ 
-       } 
-     } 
-   } 
- } 
-   
-   
- int luaD_rawrunprotected (lua_State *L, Pfunc f, void *ud) { 
-   unsigned short oldnCcalls = L->nCcalls; 
-   struct lua_longjmp lj; 
-   lj.status = LUA_OK; 
-   lj.previous = L->errorJmp;  /* chain new error handler */ 
-   L->errorJmp = &lj; 
-   LUAI_TRY(L, &lj, 
-     (*f)(L, ud); 
-   ); 
-   L->errorJmp = lj.previous;  /* restore old error handler */ 
-   L->nCcalls = oldnCcalls; 
-   return lj.status; 
- } 
-   
- /* }====================================================== */ 
-   
-   
- /* 
- ** {================================================================== 
- ** Stack reallocation 
- ** =================================================================== 
- */ 
- static void correctstack (lua_State *L, TValue *oldstack) { 
-   CallInfo *ci; 
-   UpVal *up; 
-   L->top = (L->top - oldstack) + L->stack; 
-   for (up = L->openupval; up != NULL; up = up->u.open.next) 
-     up->v = (up->v - oldstack) + L->stack; 
-   for (ci = L->ci; ci != NULL; ci = ci->previous) { 
-     ci->top = (ci->top - oldstack) + L->stack; 
-     ci->func = (ci->func - oldstack) + L->stack; 
-     if (isLua(ci)) 
-       ci->u.l.base = (ci->u.l.base - oldstack) + L->stack; 
-   } 
- } 
-   
-   
- /* some space for error handling */ 
- #define ERRORSTACKSIZE  (LUAI_MAXSTACK + 200) 
-   
-   
- void luaD_reallocstack (lua_State *L, int newsize) { 
-   TValue *oldstack = L->stack; 
-   int lim = L->stacksize; 
-   lua_assert(newsize <= LUAI_MAXSTACK || newsize == ERRORSTACKSIZE); 
-   lua_assert(L->stack_last - L->stack == L->stacksize - EXTRA_STACK); 
-   luaM_reallocvector(L, L->stack, L->stacksize, newsize, TValue); 
-   for (; lim < newsize; lim++) 
-     setnilvalue(L->stack + lim); /* erase new segment */ 
-   L->stacksize = newsize; 
-   L->stack_last = L->stack + newsize - EXTRA_STACK; 
-   correctstack(L, oldstack); 
- } 
-   
-   
- void luaD_growstack (lua_State *L, int n) { 
-   int size = L->stacksize; 
-   if (size > LUAI_MAXSTACK)  /* error after extra size? */ 
-     luaD_throw(L, LUA_ERRERR); 
-   else { 
-     int needed = cast_int(L->top - L->stack) + n + EXTRA_STACK; 
-     int newsize = 2 * size; 
-     if (newsize > LUAI_MAXSTACK) newsize = LUAI_MAXSTACK; 
-     if (newsize < needed) newsize = needed; 
-     if (newsize > LUAI_MAXSTACK) {  /* stack overflow? */ 
-       luaD_reallocstack(L, ERRORSTACKSIZE); 
-       luaG_runerror(L, "stack overflow"); 
-     } 
-     else 
-       luaD_reallocstack(L, newsize); 
-   } 
- } 
-   
-   
- static int stackinuse (lua_State *L) { 
-   CallInfo *ci; 
-   StkId lim = L->top; 
-   for (ci = L->ci; ci != NULL; ci = ci->previous) { 
-     if (lim < ci->top) lim = ci->top; 
-   } 
-   lua_assert(lim <= L->stack_last); 
-   return cast_int(lim - L->stack) + 1;  /* part of stack in use */ 
- } 
-   
-   
- void luaD_shrinkstack (lua_State *L) { 
-   int inuse = stackinuse(L); 
-   int goodsize = inuse + (inuse / 8) + 2*EXTRA_STACK; 
-   if (goodsize > LUAI_MAXSTACK) 
-     goodsize = LUAI_MAXSTACK;  /* respect stack limit */ 
-   if (L->stacksize > LUAI_MAXSTACK)  /* had been handling stack overflow? */ 
-     luaE_freeCI(L);  /* free all CIs (list grew because of an error) */ 
-   else 
-     luaE_shrinkCI(L);  /* shrink list */ 
-   /* if thread is currently not handling a stack overflow and its 
-      good size is smaller than current size, shrink its stack */ 
-   if (inuse <= (LUAI_MAXSTACK - EXTRA_STACK) && 
-       goodsize < L->stacksize) 
-     luaD_reallocstack(L, goodsize); 
-   else  /* don't change stack */ 
-     condmovestack(L,{},{});  /* (change only for debugging) */ 
- } 
-   
-   
- void luaD_inctop (lua_State *L) { 
-   luaD_checkstack(L, 1); 
-   L->top++; 
- } 
-   
- /* }================================================================== */ 
-   
-   
- /* 
- ** Call a hook for the given event. Make sure there is a hook to be 
- ** called. (Both 'L->hook' and 'L->hookmask', which triggers this 
- ** function, can be changed asynchronously by signals.) 
- */ 
- void luaD_hook (lua_State *L, int event, int line) { 
-   lua_Hook hook = L->hook; 
-   if (hook && L->allowhook) {  /* make sure there is a hook */ 
-     CallInfo *ci = L->ci; 
-     ptrdiff_t top = savestack(L, L->top); 
-     ptrdiff_t ci_top = savestack(L, ci->top); 
-     lua_Debug ar; 
-     ar.event = event; 
-     ar.currentline = line; 
-     ar.i_ci = ci; 
-     luaD_checkstack(L, LUA_MINSTACK);  /* ensure minimum stack size */ 
-     ci->top = L->top + LUA_MINSTACK; 
-     lua_assert(ci->top <= L->stack_last); 
-     L->allowhook = 0;  /* cannot call hooks inside a hook */ 
-     ci->callstatus |= CIST_HOOKED; 
-     lua_unlock(L); 
-     (*hook)(L, &ar); 
-     lua_lock(L); 
-     lua_assert(!L->allowhook); 
-     L->allowhook = 1; 
-     ci->top = restorestack(L, ci_top); 
-     L->top = restorestack(L, top); 
-     ci->callstatus &= ~CIST_HOOKED; 
-   } 
- } 
-   
-   
- static void callhook (lua_State *L, CallInfo *ci) { 
-   int hook = LUA_HOOKCALL; 
-   ci->u.l.savedpc++;  /* hooks assume 'pc' is already incremented */ 
-   if (isLua(ci->previous) && 
-       GET_OPCODE(*(ci->previous->u.l.savedpc - 1)) == OP_TAILCALL) { 
-     ci->callstatus |= CIST_TAIL; 
-     hook = LUA_HOOKTAILCALL; 
-   } 
-   luaD_hook(L, hook, -1); 
-   ci->u.l.savedpc--;  /* correct 'pc' */ 
- } 
-   
-   
- static StkId adjust_varargs (lua_State *L, Proto *p, int actual) { 
-   int i; 
-   int nfixargs = p->numparams; 
-   StkId base, fixed; 
-   /* move fixed parameters to final position */ 
-   fixed = L->top - actual;  /* first fixed argument */ 
-   base = L->top;  /* final position of first argument */ 
-   for (i = 0; i < nfixargs && i < actual; i++) { 
-     setobjs2s(L, L->top++, fixed + i); 
-     setnilvalue(fixed + i);  /* erase original copy (for GC) */ 
-   } 
-   for (; i < nfixargs; i++) 
-     setnilvalue(L->top++);  /* complete missing arguments */ 
-   return base; 
- } 
-   
-   
- /* 
- ** Check whether __call metafield of 'func' is a function. If so, put 
- ** it in stack below original 'func' so that 'luaD_precall' can call 
- ** it. Raise an error if __call metafield is not a function. 
- */ 
- static void tryfuncTM (lua_State *L, StkId func) { 
-   const TValue *tm = luaT_gettmbyobj(L, func, TM_CALL); 
-   StkId p; 
-   if (!ttisfunction(tm)) 
-     luaG_typeerror(L, func, "call"); 
-   /* Open a hole inside the stack at 'func' */ 
-   for (p = L->top; p > func; p--) 
-     setobjs2s(L, p, p-1); 
-   L->top++;  /* slot ensured by caller */ 
-   setobj2s(L, func, tm);  /* tag method is the new function to be called */ 
- } 
-   
-   
- /* 
- ** Given 'nres' results at 'firstResult', move 'wanted' of them to 'res'. 
- ** Handle most typical cases (zero results for commands, one result for 
- ** expressions, multiple results for tail calls/single parameters) 
- ** separated. 
- */ 
- static int moveresults (lua_State *L, const TValue *firstResult, StkId res, 
-                                       int nres, int wanted) { 
-   switch (wanted) {  /* handle typical cases separately */ 
-     case 0: break;  /* nothing to move */ 
-     case 1: {  /* one result needed */ 
-       if (nres == 0)   /* no results? */ 
-         firstResult = luaO_nilobject;  /* adjust with nil */ 
-       setobjs2s(L, res, firstResult);  /* move it to proper place */ 
-       break; 
-     } 
-     case LUA_MULTRET: { 
-       int i; 
-       for (i = 0; i < nres; i++)  /* move all results to correct place */ 
-         setobjs2s(L, res + i, firstResult + i); 
-       L->top = res + nres; 
-       return 0;  /* wanted == LUA_MULTRET */ 
-     } 
-     default: { 
-       int i; 
-       if (wanted <= nres) {  /* enough results? */ 
-         for (i = 0; i < wanted; i++)  /* move wanted results to correct place */ 
-           setobjs2s(L, res + i, firstResult + i); 
-       } 
-       else {  /* not enough results; use all of them plus nils */ 
-         for (i = 0; i < nres; i++)  /* move all results to correct place */ 
-           setobjs2s(L, res + i, firstResult + i); 
-         for (; i < wanted; i++)  /* complete wanted number of results */ 
-           setnilvalue(res + i); 
-       } 
-       break; 
-     } 
-   } 
-   L->top = res + wanted;  /* top points after the last result */ 
-   return 1; 
- } 
-   
-   
- /* 
- ** Finishes a function call: calls hook if necessary, removes CallInfo, 
- ** moves current number of results to proper place; returns 0 iff call 
- ** wanted multiple (variable number of) results. 
- */ 
- int luaD_poscall (lua_State *L, CallInfo *ci, StkId firstResult, int nres) { 
-   StkId res; 
-   int wanted = ci->nresults; 
-   if (L->hookmask & (LUA_MASKRET | LUA_MASKLINE)) { 
-     if (L->hookmask & LUA_MASKRET) { 
-       ptrdiff_t fr = savestack(L, firstResult);  /* hook may change stack */ 
-       luaD_hook(L, LUA_HOOKRET, -1); 
-       firstResult = restorestack(L, fr); 
-     } 
-     L->oldpc = ci->previous->u.l.savedpc;  /* 'oldpc' for caller function */ 
-   } 
-   res = ci->func;  /* res == final position of 1st result */ 
-   L->ci = ci->previous;  /* back to caller */ 
-   /* move results to proper place */ 
-   return moveresults(L, firstResult, res, nres, wanted); 
- } 
-   
-   
-   
- #define next_ci(L) (L->ci = (L->ci->next ? L->ci->next : luaE_extendCI(L))) 
-   
-   
- /* macro to check stack size, preserving 'p' */ 
- #define checkstackp(L,n,p)  \ 
-   luaD_checkstackaux(L, n, \ 
-     ptrdiff_t t__ = savestack(L, p);  /* save 'p' */ \ 
-     luaC_checkGC(L),  /* stack grow uses memory */ \ 
-     p = restorestack(L, t__))  /* 'pos' part: restore 'p' */ 
-   
-   
- /* 
- ** Prepares a function call: checks the stack, creates a new CallInfo 
- ** entry, fills in the relevant information, calls hook if needed. 
- ** If function is a C function, does the call, too. (Otherwise, leave 
- ** the execution ('luaV_execute') to the caller, to allow stackless 
- ** calls.) Returns true iff function has been executed (C function). 
- */ 
- int luaD_precall (lua_State *L, StkId func, int nresults) { 
-   lua_CFunction f; 
-   CallInfo *ci; 
-   switch (ttype(func)) { 
-     case LUA_TCCL:  /* C closure */ 
-       f = clCvalue(func)->f; 
-       goto Cfunc; 
-     case LUA_TLCF:  /* light C function */ 
-       f = fvalue(func); 
-      Cfunc: { 
-       int n;  /* number of returns */ 
-       checkstackp(L, LUA_MINSTACK, func);  /* ensure minimum stack size */ 
-       ci = next_ci(L);  /* now 'enter' new function */ 
-       ci->nresults = nresults; 
-       ci->func = func; 
-       ci->top = L->top + LUA_MINSTACK; 
-       lua_assert(ci->top <= L->stack_last); 
-       ci->callstatus = 0; 
-       if (L->hookmask & LUA_MASKCALL) 
-         luaD_hook(L, LUA_HOOKCALL, -1); 
-       lua_unlock(L); 
-       n = (*f)(L);  /* do the actual call */ 
-       lua_lock(L); 
-       api_checknelems(L, n); 
-       luaD_poscall(L, ci, L->top - n, n); 
-       return 1; 
-     } 
-     case LUA_TLCL: {  /* Lua function: prepare its call */ 
-       StkId base; 
-       Proto *p = clLvalue(func)->p; 
-       int n = cast_int(L->top - func) - 1;  /* number of real arguments */ 
-       int fsize = p->maxstacksize;  /* frame size */ 
-       checkstackp(L, fsize, func); 
-       if (p->is_vararg) 
-         base = adjust_varargs(L, p, n); 
-       else {  /* non vararg function */ 
-         for (; n < p->numparams; n++) 
-           setnilvalue(L->top++);  /* complete missing arguments */ 
-         base = func + 1; 
-       } 
-       ci = next_ci(L);  /* now 'enter' new function */ 
-       ci->nresults = nresults; 
-       ci->func = func; 
-       ci->u.l.base = base; 
-       L->top = ci->top = base + fsize; 
-       lua_assert(ci->top <= L->stack_last); 
-       ci->u.l.savedpc = p->code;  /* starting point */ 
-       ci->callstatus = CIST_LUA; 
-       if (L->hookmask & LUA_MASKCALL) 
-         callhook(L, ci); 
-       return 0; 
-     } 
-     default: {  /* not a function */ 
-       checkstackp(L, 1, func);  /* ensure space for metamethod */ 
-       tryfuncTM(L, func);  /* try to get '__call' metamethod */ 
-       return luaD_precall(L, func, nresults);  /* now it must be a function */ 
-     } 
-   } 
- } 
-   
-   
- /* 
- ** Check appropriate error for stack overflow ("regular" overflow or 
- ** overflow while handling stack overflow). If 'nCalls' is larger than 
- ** LUAI_MAXCCALLS (which means it is handling a "regular" overflow) but 
- ** smaller than 9/8 of LUAI_MAXCCALLS, does not report an error (to 
- ** allow overflow handling to work) 
- */ 
- static void stackerror (lua_State *L) { 
-   if (L->nCcalls == LUAI_MAXCCALLS) 
-     luaG_runerror(L, "C stack overflow"); 
-   else if (L->nCcalls >= (LUAI_MAXCCALLS + (LUAI_MAXCCALLS>>3))) 
-     luaD_throw(L, LUA_ERRERR);  /* error while handing stack error */ 
- } 
-   
-   
- /* 
- ** Call a function (C or Lua). The function to be called is at *func. 
- ** The arguments are on the stack, right after the function. 
- ** When returns, all the results are on the stack, starting at the original 
- ** function position. 
- */ 
- void luaD_call (lua_State *L, StkId func, int nResults) { 
-   if (++L->nCcalls >= LUAI_MAXCCALLS) 
-     stackerror(L); 
-   if (!luaD_precall(L, func, nResults))  /* is a Lua function? */ 
-     luaV_execute(L);  /* call it */ 
-   L->nCcalls--; 
- } 
-   
-   
- /* 
- ** Similar to 'luaD_call', but does not allow yields during the call 
- */ 
- void luaD_callnoyield (lua_State *L, StkId func, int nResults) { 
-   L->nny++; 
-   luaD_call(L, func, nResults); 
-   L->nny--; 
- } 
-   
-   
- /* 
- ** Completes the execution of an interrupted C function, calling its 
- ** continuation function. 
- */ 
- static void finishCcall (lua_State *L, int status) { 
-   CallInfo *ci = L->ci; 
-   int n; 
-   /* must have a continuation and must be able to call it */ 
-   lua_assert(ci->u.c.k != NULL && L->nny == 0); 
-   /* error status can only happen in a protected call */ 
-   lua_assert((ci->callstatus & CIST_YPCALL) || status == LUA_YIELD); 
-   if (ci->callstatus & CIST_YPCALL) {  /* was inside a pcall? */ 
-     ci->callstatus &= ~CIST_YPCALL;  /* continuation is also inside it */ 
-     L->errfunc = ci->u.c.old_errfunc;  /* with the same error function */ 
-   } 
-   /* finish 'lua_callk'/'lua_pcall'; CIST_YPCALL and 'errfunc' already 
-      handled */ 
-   adjustresults(L, ci->nresults); 
-   lua_unlock(L); 
-   n = (*ci->u.c.k)(L, status, ci->u.c.ctx);  /* call continuation function */ 
-   lua_lock(L); 
-   api_checknelems(L, n); 
-   luaD_poscall(L, ci, L->top - n, n);  /* finish 'luaD_precall' */ 
- } 
-   
-   
- /* 
- ** Executes "full continuation" (everything in the stack) of a 
- ** previously interrupted coroutine until the stack is empty (or another 
- ** interruption long-jumps out of the loop). If the coroutine is 
- ** recovering from an error, 'ud' points to the error status, which must 
- ** be passed to the first continuation function (otherwise the default 
- ** status is LUA_YIELD). 
- */ 
- static void unroll (lua_State *L, void *ud) { 
-   if (ud != NULL)  /* error status? */ 
-     finishCcall(L, *(int *)ud);  /* finish 'lua_pcallk' callee */ 
-   while (L->ci != &L->base_ci) {  /* something in the stack */ 
-     if (!isLua(L->ci))  /* C function? */ 
-       finishCcall(L, LUA_YIELD);  /* complete its execution */ 
-     else {  /* Lua function */ 
-       luaV_finishOp(L);  /* finish interrupted instruction */ 
-       luaV_execute(L);  /* execute down to higher C 'boundary' */ 
-     } 
-   } 
- } 
-   
-   
- /* 
- ** Try to find a suspended protected call (a "recover point") for the 
- ** given thread. 
- */ 
- static CallInfo *findpcall (lua_State *L) { 
-   CallInfo *ci; 
-   for (ci = L->ci; ci != NULL; ci = ci->previous) {  /* search for a pcall */ 
-     if (ci->callstatus & CIST_YPCALL) 
-       return ci; 
-   } 
-   return NULL;  /* no pending pcall */ 
- } 
-   
-   
- /* 
- ** Recovers from an error in a coroutine. Finds a recover point (if 
- ** there is one) and completes the execution of the interrupted 
- ** 'luaD_pcall'. If there is no recover point, returns zero. 
- */ 
- static int recover (lua_State *L, int status) { 
-   StkId oldtop; 
-   CallInfo *ci = findpcall(L); 
-   if (ci == NULL) return 0;  /* no recovery point */ 
-   /* "finish" luaD_pcall */ 
-   oldtop = restorestack(L, ci->extra); 
-   luaF_close(L, oldtop); 
-   seterrorobj(L, status, oldtop); 
-   L->ci = ci; 
-   L->allowhook = getoah(ci->callstatus);  /* restore original 'allowhook' */ 
-   L->nny = 0;  /* should be zero to be yieldable */ 
-   luaD_shrinkstack(L); 
-   L->errfunc = ci->u.c.old_errfunc; 
-   return 1;  /* continue running the coroutine */ 
- } 
-   
-   
- /* 
- ** Signal an error in the call to 'lua_resume', not in the execution 
- ** of the coroutine itself. (Such errors should not be handled by any 
- ** coroutine error handler and should not kill the coroutine.) 
- */ 
- static int resume_error (lua_State *L, const char *msg, int narg) { 
-   L->top -= narg;  /* remove args from the stack */ 
-   setsvalue2s(L, L->top, luaS_new(L, msg));  /* push error message */ 
-   api_incr_top(L); 
-   lua_unlock(L); 
-   return LUA_ERRRUN; 
- } 
-   
-   
- /* 
- ** Do the work for 'lua_resume' in protected mode. Most of the work 
- ** depends on the status of the coroutine: initial state, suspended 
- ** inside a hook, or regularly suspended (optionally with a continuation 
- ** function), plus erroneous cases: non-suspended coroutine or dead 
- ** coroutine. 
- */ 
- static void resume (lua_State *L, void *ud) { 
-   int n = *(cast(int*, ud));  /* number of arguments */ 
-   StkId firstArg = L->top - n;  /* first argument */ 
-   CallInfo *ci = L->ci; 
-   if (L->status == LUA_OK) {  /* starting a coroutine? */ 
-     if (!luaD_precall(L, firstArg - 1, LUA_MULTRET))  /* Lua function? */ 
-       luaV_execute(L);  /* call it */ 
-   } 
-   else {  /* resuming from previous yield */ 
-     lua_assert(L->status == LUA_YIELD); 
-     L->status = LUA_OK;  /* mark that it is running (again) */ 
-     ci->func = restorestack(L, ci->extra); 
-     if (isLua(ci))  /* yielded inside a hook? */ 
-       luaV_execute(L);  /* just continue running Lua code */ 
-     else {  /* 'common' yield */ 
-       if (ci->u.c.k != NULL) {  /* does it have a continuation function? */ 
-         lua_unlock(L); 
-         n = (*ci->u.c.k)(L, LUA_YIELD, ci->u.c.ctx); /* call continuation */ 
-         lua_lock(L); 
-         api_checknelems(L, n); 
-         firstArg = L->top - n;  /* yield results come from continuation */ 
-       } 
-       luaD_poscall(L, ci, firstArg, n);  /* finish 'luaD_precall' */ 
-     } 
-     unroll(L, NULL);  /* run continuation */ 
-   } 
- } 
-   
-   
- LUA_API int lua_resume (lua_State *L, lua_State *from, int nargs) { 
-   int status; 
-   unsigned short oldnny = L->nny;  /* save "number of non-yieldable" calls */ 
-   lua_lock(L); 
-   if (L->status == LUA_OK) {  /* may be starting a coroutine */ 
-     if (L->ci != &L->base_ci)  /* not in base level? */ 
-       return resume_error(L, "cannot resume non-suspended coroutine", nargs); 
-   } 
-   else if (L->status != LUA_YIELD) 
-     return resume_error(L, "cannot resume dead coroutine", nargs); 
-   L->nCcalls = (from) ? from->nCcalls + 1 : 1; 
-   if (L->nCcalls >= LUAI_MAXCCALLS) 
-     return resume_error(L, "C stack overflow", nargs); 
-   luai_userstateresume(L, nargs); 
-   L->nny = 0;  /* allow yields */ 
-   api_checknelems(L, (L->status == LUA_OK) ? nargs + 1 : nargs); 
-   status = luaD_rawrunprotected(L, resume, &nargs); 
-   if (status == -1)  /* error calling 'lua_resume'? */ 
-     status = LUA_ERRRUN; 
-   else {  /* continue running after recoverable errors */ 
-     while (errorstatus(status) && recover(L, status)) { 
-       /* unroll continuation */ 
-       status = luaD_rawrunprotected(L, unroll, &status); 
-     } 
-     if (errorstatus(status)) {  /* unrecoverable error? */ 
-       L->status = cast_byte(status);  /* mark thread as 'dead' */ 
-       seterrorobj(L, status, L->top);  /* push error message */ 
-       L->ci->top = L->top; 
-     } 
-     else lua_assert(status == L->status);  /* normal end or yield */ 
-   } 
-   L->nny = oldnny;  /* restore 'nny' */ 
-   L->nCcalls--; 
-   lua_assert(L->nCcalls == ((from) ? from->nCcalls : 0)); 
-   lua_unlock(L); 
-   return status; 
- } 
-   
-   
- LUA_API int lua_isyieldable (lua_State *L) { 
-   return (L->nny == 0); 
- } 
-   
-   
- LUA_API int lua_yieldk (lua_State *L, int nresults, lua_KContext ctx, 
-                         lua_KFunction k) { 
-   CallInfo *ci = L->ci; 
-   luai_userstateyield(L, nresults); 
-   lua_lock(L); 
-   api_checknelems(L, nresults); 
-   if (L->nny > 0) { 
-     if (L != G(L)->mainthread) 
-       luaG_runerror(L, "attempt to yield across a C-call boundary"); 
-     else 
-       luaG_runerror(L, "attempt to yield from outside a coroutine"); 
-   } 
-   L->status = LUA_YIELD; 
-   ci->extra = savestack(L, ci->func);  /* save current 'func' */ 
-   if (isLua(ci)) {  /* inside a hook? */ 
-     api_check(L, k == NULL, "hooks cannot continue after yielding"); 
-   } 
-   else { 
-     if ((ci->u.c.k = k) != NULL)  /* is there a continuation? */ 
-       ci->u.c.ctx = ctx;  /* save context */ 
-     ci->func = L->top - nresults - 1;  /* protect stack below results */ 
-     luaD_throw(L, LUA_YIELD); 
-   } 
-   lua_assert(ci->callstatus & CIST_HOOKED);  /* must be inside a hook */ 
-   lua_unlock(L); 
-   return 0;  /* return to 'luaD_hook' */ 
- } 
-   
-   
- int luaD_pcall (lua_State *L, Pfunc func, void *u, 
-                 ptrdiff_t old_top, ptrdiff_t ef) { 
-   int status; 
-   CallInfo *old_ci = L->ci; 
-   lu_byte old_allowhooks = L->allowhook; 
-   unsigned short old_nny = L->nny; 
-   ptrdiff_t old_errfunc = L->errfunc; 
-   L->errfunc = ef; 
-   status = luaD_rawrunprotected(L, func, u); 
-   if (status != LUA_OK) {  /* an error occurred? */ 
-     StkId oldtop = restorestack(L, old_top); 
-     luaF_close(L, oldtop);  /* close possible pending closures */ 
-     seterrorobj(L, status, oldtop); 
-     L->ci = old_ci; 
-     L->allowhook = old_allowhooks; 
-     L->nny = old_nny; 
-     luaD_shrinkstack(L); 
-   } 
-   L->errfunc = old_errfunc; 
-   return status; 
- } 
-   
-   
-   
- /* 
- ** Execute a protected parser. 
- */ 
- struct SParser {  /* data to 'f_parser' */ 
-   ZIO *z; 
-   Mbuffer buff;  /* dynamic structure used by the scanner */ 
-   Dyndata dyd;  /* dynamic structures used by the parser */ 
-   const char *mode; 
-   const char *name; 
- }; 
-   
-   
- static void checkmode (lua_State *L, const char *mode, const char *x) { 
-   if (- mode  && strchr(- mode ,-  x [0]) ==-  NULL ) {
 
-     luaO_pushfstring(L, 
-        "attempt to load a %s chunk (mode is '%s')", x, mode); 
-     luaD_throw(L, LUA_ERRSYNTAX); 
-   } 
- } 
-   
-   
- static void f_parser (lua_State *L, void *ud) { 
-   LClosure *cl; 
-   struct SParser *p = cast(struct SParser *, ud); 
-   int c = zgetc(p->z);  /* read first character */ 
-   if (c == LUA_SIGNATURE[0]) { 
-     checkmode(L, p->mode, "binary"); 
-     cl = luaU_undump(L, p->z, p->name); 
-   } 
-   else { 
-     checkmode(L, p->mode, "text"); 
-     cl = luaY_parser(L, p->z, &p->buff, &p->dyd, p->name, c); 
-   } 
-   lua_assert(cl->nupvalues == cl->p->sizeupvalues); 
-   luaF_initupvals(L, cl); 
- } 
-   
-   
- int luaD_protectedparser (lua_State *L, ZIO *z, const char *name, 
-                                         const char *mode) { 
-   struct SParser p; 
-   int status; 
-   L->nny++;  /* cannot yield during parsing */ 
-   p.z = z; p.name = name; p.mode = mode; 
-   p.dyd.actvar.arr = NULL; p.dyd.actvar.size = 0; 
-   p.dyd.gt.arr = NULL; p.dyd.gt.size = 0; 
-   p.dyd.label.arr = NULL; p.dyd.label.size = 0; 
-   luaZ_initbuffer(L, &p.buff); 
-   status = luaD_pcall(L, f_parser, &p, savestack(L, L->top), L->errfunc); 
-   luaZ_freebuffer(L, &p.buff); 
-   luaM_freearray(L, p.dyd.actvar.arr, p.dyd.actvar.size); 
-   luaM_freearray(L, p.dyd.gt.arr, p.dyd.gt.size); 
-   luaM_freearray(L, p.dyd.label.arr, p.dyd.label.size); 
-   L->nny--; 
-   return status; 
- } 
-   
-   
-