LCOV - code coverage report
Current view: top level - src - ldo.c Coverage Total Hit
Test: Lua 5.2.4 Lines: 84.6 % 351 297
Test Date: 2024-04-28 10:23:12
Legend: Lines: hit not hit

            Line data    Source code
       1              : /*
       2              : ** $Id: ldo.c,v 2.108.1.3 2013/11/08 18:22:50 roberto Exp $
       3              : ** Stack and Call structure of Lua
       4              : ** See Copyright Notice in lua.h
       5              : */
       6              : 
       7              : 
       8              : #include <setjmp.h>
       9              : #include <stdlib.h>
      10              : #include <string.h>
      11              : 
      12              : #define ldo_c
      13              : #define LUA_CORE
      14              : 
      15              : #include "lua.h"
      16              : 
      17              : #include "lapi.h"
      18              : #include "ldebug.h"
      19              : #include "ldo.h"
      20              : #include "lfunc.h"
      21              : #include "lgc.h"
      22              : #include "lmem.h"
      23              : #include "lobject.h"
      24              : #include "lopcodes.h"
      25              : #include "lparser.h"
      26              : #include "lstate.h"
      27              : #include "lstring.h"
      28              : #include "ltable.h"
      29              : #include "ltm.h"
      30              : #include "lundump.h"
      31              : #include "lvm.h"
      32              : #include "lzio.h"
      33              : 
      34              : 
      35              : 
      36              : 
      37              : /*
      38              : ** {======================================================
      39              : ** Error-recovery functions
      40              : ** =======================================================
      41              : */
      42              : 
      43              : /*
      44              : ** LUAI_THROW/LUAI_TRY define how Lua does exception handling. By
      45              : ** default, Lua handles errors with exceptions when compiling as
      46              : ** C++ code, with _longjmp/_setjmp when asked to use them, and with
      47              : ** longjmp/setjmp otherwise.
      48              : */
      49              : #if !defined(LUAI_THROW)
      50              : 
      51              : #if defined(__cplusplus) && !defined(LUA_USE_LONGJMP)
      52              : /* C++ exceptions */
      53              : #define LUAI_THROW(L,c)         throw(c)
      54              : #define LUAI_TRY(L,c,a) \
      55              :         try { a } catch(...) { if ((c)->status == 0) (c)->status = -1; }
      56              : #define luai_jmpbuf             int  /* dummy variable */
      57              : 
      58              : #elif defined(LUA_USE_ULONGJMP)
      59              : /* in Unix, try _longjmp/_setjmp (more efficient) */
      60              : #define LUAI_THROW(L,c)         _longjmp((c)->b, 1)
      61              : #define LUAI_TRY(L,c,a)         if (_setjmp((c)->b) == 0) { a }
      62              : #define luai_jmpbuf             jmp_buf
      63              : 
      64              : #else
      65              : /* default handling with long jumps */
      66              : #define LUAI_THROW(L,c)         longjmp((c)->b, 1)
      67              : #define LUAI_TRY(L,c,a)         if (setjmp((c)->b) == 0) { a }
      68              : #define luai_jmpbuf             jmp_buf
      69              : 
      70              : #endif
      71              : 
      72              : #endif
      73              : 
      74              : 
      75              : 
      76              : /* chain list of long jump buffers */
      77              : struct lua_longjmp {
      78              :   struct lua_longjmp *previous;
      79              :   luai_jmpbuf b;
      80              :   volatile int status;  /* error code */
      81              : };
      82              : 
      83              : 
      84          396 : static void seterrorobj (lua_State *L, int errcode, StkId oldtop) {
      85          396 :   switch (errcode) {
      86            0 :     case LUA_ERRMEM: {  /* memory error? */
      87            0 :       setsvalue2s(L, oldtop, G(L)->memerrmsg); /* reuse preregistered msg. */
      88            0 :       break;
      89              :     }
      90            1 :     case LUA_ERRERR: {
      91            1 :       setsvalue2s(L, oldtop, luaS_newliteral(L, "error in error handling"));
      92            1 :       break;
      93              :     }
      94          395 :     default: {
      95          395 :       setobjs2s(L, oldtop, L->top - 1);  /* error message on current top */
      96          395 :       break;
      97              :     }
      98              :   }
      99          396 :   L->top = oldtop + 1;
     100          396 : }
     101              : 
     102              : 
     103         6349 : l_noret luaD_throw (lua_State *L, int errcode) {
     104         6349 :   if (L->errorJmp) {  /* thread has an error handler? */
     105         6349 :     L->errorJmp->status = errcode;  /* set status */
     106         6349 :     LUAI_THROW(L, L->errorJmp);  /* jump to it */
     107              :   }
     108              :   else {  /* thread has no error handler */
     109            0 :     L->status = cast_byte(errcode);  /* mark it as dead */
     110            0 :     if (G(L)->mainthread->errorJmp) {  /* main thread has a handler? */
     111            0 :       setobjs2s(L, G(L)->mainthread->top++, L->top - 1);  /* copy error obj. */
     112            0 :       luaD_throw(G(L)->mainthread, errcode);  /* re-throw in main thread */
     113              :     }
     114              :     else {  /* no handler at all; abort */
     115            0 :       if (G(L)->panic) {  /* panic function? */
     116              :         lua_unlock(L);
     117            0 :         G(L)->panic(L);  /* call it (last chance to jump out) */
     118              :       }
     119            0 :       abort();
     120              :     }
     121              :   }
     122              : }
     123              : 
     124              : 
     125         7878 : int luaD_rawrunprotected (lua_State *L, Pfunc f, void *ud) {
     126         7878 :   unsigned short oldnCcalls = L->nCcalls;
     127              :   struct lua_longjmp lj;
     128         7878 :   lj.status = LUA_OK;
     129         7878 :   lj.previous = L->errorJmp;  /* chain new error handler */
     130         7878 :   L->errorJmp = &lj;
     131         7878 :   LUAI_TRY(L, &lj,
     132              :     (*f)(L, ud);
     133              :   );
     134         7851 :   L->errorJmp = lj.previous;  /* restore old error handler */
     135         7851 :   L->nCcalls = oldnCcalls;
     136         7851 :   return lj.status;
     137              : }
     138              : 
     139              : /* }====================================================== */
     140              : 
     141              : 
     142          941 : static void correctstack (lua_State *L, TValue *oldstack) {
     143              :   CallInfo *ci;
     144              :   GCObject *up;
     145          941 :   L->top = (L->top - oldstack) + L->stack;
     146         2731 :   for (up = L->openupval; up != NULL; up = up->gch.next)
     147         1790 :     gco2uv(up)->v = (gco2uv(up)->v - oldstack) + L->stack;
     148         5798 :   for (ci = L->ci; ci != NULL; ci = ci->previous) {
     149         4857 :     ci->top = (ci->top - oldstack) + L->stack;
     150         4857 :     ci->func = (ci->func - oldstack) + L->stack;
     151         4857 :     if (isLua(ci))
     152         2462 :       ci->u.l.base = (ci->u.l.base - oldstack) + L->stack;
     153              :   }
     154          941 : }
     155              : 
     156              : 
     157              : /* some space for error handling */
     158              : #define ERRORSTACKSIZE  (LUAI_MAXSTACK + 200)
     159              : 
     160              : 
     161          941 : void luaD_reallocstack (lua_State *L, int newsize) {
     162          941 :   TValue *oldstack = L->stack;
     163          941 :   int lim = L->stacksize;
     164              :   lua_assert(newsize <= LUAI_MAXSTACK || newsize == ERRORSTACKSIZE);
     165              :   lua_assert(L->stack_last - L->stack == L->stacksize - EXTRA_STACK);
     166          941 :   luaM_reallocvector(L, L->stack, L->stacksize, newsize, TValue);
     167        24871 :   for (; lim < newsize; lim++)
     168        23930 :     setnilvalue(L->stack + lim); /* erase new segment */
     169          941 :   L->stacksize = newsize;
     170          941 :   L->stack_last = L->stack + newsize - EXTRA_STACK;
     171          941 :   correctstack(L, oldstack);
     172          941 : }
     173              : 
     174              : 
     175          432 : void luaD_growstack (lua_State *L, int n) {
     176          432 :   int size = L->stacksize;
     177          432 :   if (size > LUAI_MAXSTACK)  /* error after extra size? */
     178            0 :     luaD_throw(L, LUA_ERRERR);
     179              :   else {
     180          432 :     int needed = cast_int(L->top - L->stack) + n + EXTRA_STACK;
     181          432 :     int newsize = 2 * size;
     182          432 :     if (newsize > LUAI_MAXSTACK) newsize = LUAI_MAXSTACK;
     183          432 :     if (newsize < needed) newsize = needed;
     184          432 :     if (newsize > LUAI_MAXSTACK) {  /* stack overflow? */
     185            0 :       luaD_reallocstack(L, ERRORSTACKSIZE);
     186            0 :       luaG_runerror(L, "stack overflow");
     187              :     }
     188              :     else
     189          432 :       luaD_reallocstack(L, newsize);
     190              :   }
     191          432 : }
     192              : 
     193              : 
     194          596 : static int stackinuse (lua_State *L) {
     195              :   CallInfo *ci;
     196          596 :   StkId lim = L->top;
     197         3312 :   for (ci = L->ci; ci != NULL; ci = ci->previous) {
     198              :     lua_assert(ci->top <= L->stack_last);
     199         2716 :     if (lim < ci->top) lim = ci->top;
     200              :   }
     201          596 :   return cast_int(lim - L->stack) + 1;  /* part of stack in use */
     202              : }
     203              : 
     204              : 
     205          596 : void luaD_shrinkstack (lua_State *L) {
     206          596 :   int inuse = stackinuse(L);
     207          596 :   int goodsize = inuse + (inuse / 8) + 2*EXTRA_STACK;
     208          596 :   if (goodsize > LUAI_MAXSTACK) goodsize = LUAI_MAXSTACK;
     209          596 :   if (inuse > LUAI_MAXSTACK ||  /* handling stack overflow? */
     210          596 :       goodsize >= L->stacksize)  /* would grow instead of shrink? */
     211              :     condmovestack(L);  /* don't change stack (change only for debugging) */
     212              :   else
     213          509 :     luaD_reallocstack(L, goodsize);  /* shrink it */
     214          596 : }
     215              : 
     216              : 
     217          464 : void luaD_hook (lua_State *L, int event, int line) {
     218          464 :   lua_Hook hook = L->hook;
     219          464 :   if (hook && L->allowhook) {
     220          227 :     CallInfo *ci = L->ci;
     221          227 :     ptrdiff_t top = savestack(L, L->top);
     222          227 :     ptrdiff_t ci_top = savestack(L, ci->top);
     223              :     lua_Debug ar;
     224          227 :     ar.event = event;
     225          227 :     ar.currentline = line;
     226          227 :     ar.i_ci = ci;
     227          227 :     luaD_checkstack(L, LUA_MINSTACK);  /* ensure minimum stack size */
     228          227 :     ci->top = L->top + LUA_MINSTACK;
     229              :     lua_assert(ci->top <= L->stack_last);
     230          227 :     L->allowhook = 0;  /* cannot call hooks inside a hook */
     231          227 :     ci->callstatus |= CIST_HOOKED;
     232              :     lua_unlock(L);
     233          227 :     (*hook)(L, &ar);
     234              :     lua_lock(L);
     235              :     lua_assert(!L->allowhook);
     236          227 :     L->allowhook = 1;
     237          227 :     ci->top = restorestack(L, ci_top);
     238          227 :     L->top = restorestack(L, top);
     239          227 :     ci->callstatus &= ~CIST_HOOKED;
     240              :   }
     241          464 : }
     242              : 
     243              : 
     244          290 : static void callhook (lua_State *L, CallInfo *ci) {
     245          290 :   int hook = LUA_HOOKCALL;
     246          290 :   ci->u.l.savedpc++;  /* hooks assume 'pc' is already incremented */
     247          290 :   if (isLua(ci->previous) &&
     248          148 :       GET_OPCODE(*(ci->previous->u.l.savedpc - 1)) == OP_TAILCALL) {
     249            0 :     ci->callstatus |= CIST_TAIL;
     250            0 :     hook = LUA_HOOKTAILCALL;
     251              :   }
     252          290 :   luaD_hook(L, hook, -1);
     253          290 :   ci->u.l.savedpc--;  /* correct 'pc' */
     254          290 : }
     255              : 
     256              : 
     257          466 : static StkId adjust_varargs (lua_State *L, Proto *p, int actual) {
     258              :   int i;
     259          466 :   int nfixargs = p->numparams;
     260              :   StkId base, fixed;
     261              :   lua_assert(actual >= nfixargs);
     262              :   /* move fixed parameters to final position */
     263          466 :   luaD_checkstack(L, p->maxstacksize);  /* check again for new 'base' */
     264          466 :   fixed = L->top - actual;  /* first fixed argument */
     265          466 :   base = L->top;  /* final position of first argument */
     266          487 :   for (i=0; i<nfixargs; i++) {
     267           21 :     setobjs2s(L, L->top++, fixed + i);
     268           21 :     setnilvalue(fixed + i);
     269              :   }
     270          466 :   return base;
     271              : }
     272              : 
     273              : 
     274            7 : static StkId tryfuncTM (lua_State *L, StkId func) {
     275            7 :   const TValue *tm = luaT_gettmbyobj(L, func, TM_CALL);
     276              :   StkId p;
     277            7 :   ptrdiff_t funcr = savestack(L, func);
     278            7 :   if (!ttisfunction(tm))
     279            3 :     luaG_typeerror(L, func, "call");
     280              :   /* Open a hole inside the stack at `func' */
     281           12 :   for (p = L->top; p > func; p--) setobjs2s(L, p, p-1);
     282            4 :   incr_top(L);
     283            4 :   func = restorestack(L, funcr);  /* previous call may change stack */
     284            4 :   setobj2s(L, func, tm);  /* tag method is the new function to be called */
     285            4 :   return func;
     286              : }
     287              : 
     288              : 
     289              : 
     290              : #define next_ci(L) (L->ci = (L->ci->next ? L->ci->next : luaE_extendCI(L)))
     291              : 
     292              : 
     293              : /*
     294              : ** returns true if function has been executed (C function)
     295              : */
     296       129484 : int luaD_precall (lua_State *L, StkId func, int nresults) {
     297              :   lua_CFunction f;
     298              :   CallInfo *ci;
     299              :   int n;  /* number of arguments (Lua) or returns (C) */
     300       129484 :   ptrdiff_t funcr = savestack(L, func);
     301       129484 :   switch (ttype(func)) {
     302       104878 :     case LUA_TLCF:  /* light C function */
     303       104878 :       f = fvalue(func);
     304       104878 :       goto Cfunc;
     305          761 :     case LUA_TCCL: {  /* C closure */
     306          761 :       f = clCvalue(func)->f;
     307       105639 :      Cfunc:
     308       105639 :       luaD_checkstack(L, LUA_MINSTACK);  /* ensure minimum stack size */
     309       105639 :       ci = next_ci(L);  /* now 'enter' new function */
     310       105639 :       ci->nresults = nresults;
     311       105639 :       ci->func = restorestack(L, funcr);
     312       105639 :       ci->top = L->top + LUA_MINSTACK;
     313              :       lua_assert(ci->top <= L->stack_last);
     314       105639 :       ci->callstatus = 0;
     315       105639 :       luaC_checkGC(L);  /* stack grow uses memory */
     316       105639 :       if (L->hookmask & LUA_MASKCALL)
     317          142 :         luaD_hook(L, LUA_HOOKCALL, -1);
     318              :       lua_unlock(L);
     319       105639 :       n = (*f)(L);  /* do the actual call */
     320              :       lua_lock(L);
     321              :       api_checknelems(L, n);
     322        99496 :       luaD_poscall(L, L->top - n);
     323        99496 :       return 1;
     324              :     }
     325        23838 :     case LUA_TLCL: {  /* Lua function: prepare its call */
     326              :       StkId base;
     327        23838 :       Proto *p = clLvalue(func)->p;
     328        23838 :       n = cast_int(L->top - func) - 1;  /* number of real arguments */
     329        23838 :       luaD_checkstack(L, p->maxstacksize);
     330        24597 :       for (; n < p->numparams; n++)
     331          759 :         setnilvalue(L->top++);  /* complete missing arguments */
     332        23838 :       if (!p->is_vararg) {
     333        23372 :         func = restorestack(L, funcr);
     334        23372 :         base = func + 1;
     335              :       }
     336              :       else {
     337          466 :         base = adjust_varargs(L, p, n);
     338          466 :         func = restorestack(L, funcr);  /* previous call can change stack */
     339              :       }
     340        23838 :       ci = next_ci(L);  /* now 'enter' new function */
     341        23838 :       ci->nresults = nresults;
     342        23838 :       ci->func = func;
     343        23838 :       ci->u.l.base = base;
     344        23838 :       ci->top = base + p->maxstacksize;
     345              :       lua_assert(ci->top <= L->stack_last);
     346        23838 :       ci->u.l.savedpc = p->code;  /* starting point */
     347        23838 :       ci->callstatus = CIST_LUA;
     348        23838 :       L->top = ci->top;
     349        23838 :       luaC_checkGC(L);  /* stack grow uses memory */
     350        23838 :       if (L->hookmask & LUA_MASKCALL)
     351          290 :         callhook(L, ci);
     352        23838 :       return 0;
     353              :     }
     354            7 :     default: {  /* not a function */
     355            7 :       func = tryfuncTM(L, func);  /* retry with 'function' tag method */
     356            4 :       return luaD_precall(L, func, nresults);  /* now it must be a function */
     357              :     }
     358              :   }
     359              : }
     360              : 
     361              : 
     362       127814 : int luaD_poscall (lua_State *L, StkId firstResult) {
     363              :   StkId res;
     364              :   int wanted, i;
     365       127814 :   CallInfo *ci = L->ci;
     366       127814 :   if (L->hookmask & (LUA_MASKRET | LUA_MASKLINE)) {
     367            0 :     if (L->hookmask & LUA_MASKRET) {
     368            0 :       ptrdiff_t fr = savestack(L, firstResult);  /* hook may change stack */
     369            0 :       luaD_hook(L, LUA_HOOKRET, -1);
     370            0 :       firstResult = restorestack(L, fr);
     371              :     }
     372            0 :     L->oldpc = ci->previous->u.l.savedpc;  /* 'oldpc' for caller function */
     373              :   }
     374       127814 :   res = ci->func;  /* res == final position of 1st result */
     375       127814 :   wanted = ci->nresults;
     376       127814 :   L->ci = ci = ci->previous;  /* back to caller */
     377              :   /* move results to correct place */
     378       279685 :   for (i = wanted; i != 0 && firstResult < L->top; i--)
     379       151871 :     setobjs2s(L, res++, firstResult++);
     380       134496 :   while (i-- > 0)
     381         6682 :     setnilvalue(res++);
     382       127814 :   L->top = res;
     383       127814 :   return (wanted - LUA_MULTRET);  /* 0 iff wanted == LUA_MULTRET */
     384              : }
     385              : 
     386              : 
     387              : /*
     388              : ** Call a function (C or Lua). The function to be called is at *func.
     389              : ** The arguments are on the stack, right after the function.
     390              : ** When returns, all the results are on the stack, starting at the original
     391              : ** function position.
     392              : */
     393        57361 : void luaD_call (lua_State *L, StkId func, int nResults, int allowyield) {
     394        57361 :   if (++L->nCcalls >= LUAI_MAXCCALLS) {
     395            0 :     if (L->nCcalls == LUAI_MAXCCALLS)
     396            0 :       luaG_runerror(L, "C stack overflow");
     397            0 :     else if (L->nCcalls >= (LUAI_MAXCCALLS + (LUAI_MAXCCALLS>>3)))
     398            0 :       luaD_throw(L, LUA_ERRERR);  /* error while handing stack error */
     399              :   }
     400        57361 :   if (!allowyield) L->nny++;
     401        57361 :   if (!luaD_precall(L, func, nResults))  /* is a Lua function? */
     402         7016 :     luaV_execute(L);  /* call it */
     403        56979 :   if (!allowyield) L->nny--;
     404        56979 :   L->nCcalls--;
     405        56979 : }
     406              : 
     407              : 
     408            2 : static void finishCcall (lua_State *L) {
     409            2 :   CallInfo *ci = L->ci;
     410              :   int n;
     411              :   lua_assert(ci->u.c.k != NULL);  /* must have a continuation */
     412              :   lua_assert(L->nny == 0);
     413            2 :   if (ci->callstatus & CIST_YPCALL) {  /* was inside a pcall? */
     414            2 :     ci->callstatus &= ~CIST_YPCALL;  /* finish 'lua_pcall' */
     415            2 :     L->errfunc = ci->u.c.old_errfunc;
     416              :   }
     417              :   /* finish 'lua_callk'/'lua_pcall' */
     418            2 :   adjustresults(L, ci->nresults);
     419              :   /* call continuation function */
     420            2 :   if (!(ci->callstatus & CIST_STAT))  /* no call status? */
     421            2 :     ci->u.c.status = LUA_YIELD;  /* 'default' status */
     422              :   lua_assert(ci->u.c.status != LUA_OK);
     423            2 :   ci->callstatus = (ci->callstatus & ~(CIST_YPCALL | CIST_STAT)) | CIST_YIELDED;
     424              :   lua_unlock(L);
     425            2 :   n = (*ci->u.c.k)(L);
     426              :   lua_lock(L);
     427              :   api_checknelems(L, n);
     428              :   /* finish 'luaD_precall' */
     429            2 :   luaD_poscall(L, L->top - n);
     430            2 : }
     431              : 
     432              : 
     433         5950 : static void unroll (lua_State *L, void *ud) {
     434              :   UNUSED(ud);
     435              :   for (;;) {
     436         5969 :     if (L->ci == &L->base_ci)  /* stack is empty? */
     437           13 :       return;  /* coroutine finished normally */
     438         5956 :     if (!isLua(L->ci))  /* C function? */
     439            2 :       finishCcall(L);
     440              :     else {  /* Lua function */
     441         5954 :       luaV_finishOp(L);  /* finish interrupted instruction */
     442         5954 :       luaV_execute(L);  /* execute down to higher C 'boundary' */
     443              :     }
     444              :   }
     445              : }
     446              : 
     447              : 
     448              : /*
     449              : ** check whether thread has a suspended protected call
     450              : */
     451            2 : static CallInfo *findpcall (lua_State *L) {
     452              :   CallInfo *ci;
     453            8 :   for (ci = L->ci; ci != NULL; ci = ci->previous) {  /* search for a pcall */
     454            6 :     if (ci->callstatus & CIST_YPCALL)
     455            0 :       return ci;
     456              :   }
     457            2 :   return NULL;  /* no pending pcall */
     458              : }
     459              : 
     460              : 
     461            2 : static int recover (lua_State *L, int status) {
     462              :   StkId oldtop;
     463            2 :   CallInfo *ci = findpcall(L);
     464            2 :   if (ci == NULL) return 0;  /* no recovery point */
     465              :   /* "finish" luaD_pcall */
     466            0 :   oldtop = restorestack(L, ci->extra);
     467            0 :   luaF_close(L, oldtop);
     468            0 :   seterrorobj(L, status, oldtop);
     469            0 :   L->ci = ci;
     470            0 :   L->allowhook = ci->u.c.old_allowhook;
     471            0 :   L->nny = 0;  /* should be zero to be yieldable */
     472            0 :   luaD_shrinkstack(L);
     473            0 :   L->errfunc = ci->u.c.old_errfunc;
     474            0 :   ci->callstatus |= CIST_STAT;  /* call has error status */
     475            0 :   ci->u.c.status = status;  /* (here it is) */
     476            0 :   return 1;  /* continue running the coroutine */
     477              : }
     478              : 
     479              : 
     480              : /*
     481              : ** signal an error in the call to 'resume', not in the execution of the
     482              : ** coroutine itself. (Such errors should not be handled by any coroutine
     483              : ** error handler and should not kill the coroutine.)
     484              : */
     485            0 : static l_noret resume_error (lua_State *L, const char *msg, StkId firstArg) {
     486            0 :   L->top = firstArg;  /* remove args from the stack */
     487            0 :   setsvalue2s(L, L->top, luaS_new(L, msg));  /* push error message */
     488            0 :   api_incr_top(L);
     489            0 :   luaD_throw(L, -1);  /* jump back to 'lua_resume' */
     490              : }
     491              : 
     492              : 
     493              : /*
     494              : ** do the work for 'lua_resume' in protected mode
     495              : */
     496         5970 : static void resume (lua_State *L, void *ud) {
     497         5970 :   int nCcalls = L->nCcalls;
     498         5970 :   StkId firstArg = cast(StkId, ud);
     499         5970 :   CallInfo *ci = L->ci;
     500         5970 :   if (nCcalls >= LUAI_MAXCCALLS)
     501            0 :     resume_error(L, "C stack overflow", firstArg);
     502         5970 :   if (L->status == LUA_OK) {  /* may be starting a coroutine */
     503           20 :     if (ci != &L->base_ci)  /* not in base level? */
     504            0 :       resume_error(L, "cannot resume non-suspended coroutine", firstArg);
     505              :     /* coroutine is in base level; start running it */
     506           20 :     if (!luaD_precall(L, firstArg - 1, LUA_MULTRET))  /* Lua function? */
     507           20 :       luaV_execute(L);  /* call it */
     508              :   }
     509         5950 :   else if (L->status != LUA_YIELD)
     510            0 :     resume_error(L, "cannot resume dead coroutine", firstArg);
     511              :   else {  /* resuming from previous yield */
     512         5950 :     L->status = LUA_OK;
     513         5950 :     ci->func = restorestack(L, ci->extra);
     514         5950 :     if (isLua(ci))  /* yielded inside a hook? */
     515            0 :       luaV_execute(L);  /* just continue running Lua code */
     516              :     else {  /* 'common' yield */
     517         5950 :       if (ci->u.c.k != NULL) {  /* does it have a continuation? */
     518              :         int n;
     519            0 :         ci->u.c.status = LUA_YIELD;  /* 'default' status */
     520            0 :         ci->callstatus |= CIST_YIELDED;
     521              :         lua_unlock(L);
     522            0 :         n = (*ci->u.c.k)(L);  /* call continuation */
     523              :         lua_lock(L);
     524              :         api_checknelems(L, n);
     525            0 :         firstArg = L->top - n;  /* yield results come from continuation */
     526              :       }
     527         5950 :       luaD_poscall(L, firstArg);  /* finish 'luaD_precall' */
     528              :     }
     529         5950 :     unroll(L, NULL);
     530              :   }
     531              :   lua_assert(nCcalls == L->nCcalls);
     532           15 : }
     533              : 
     534              : 
     535         5970 : LUA_API int lua_resume (lua_State *L, lua_State *from, int nargs) {
     536              :   int status;
     537         5970 :   int oldnny = L->nny;  /* save 'nny' */
     538              :   lua_lock(L);
     539              :   luai_userstateresume(L, nargs);
     540         5970 :   L->nCcalls = (from) ? from->nCcalls + 1 : 1;
     541         5970 :   L->nny = 0;  /* allow yields */
     542              :   api_checknelems(L, (L->status == LUA_OK) ? nargs + 1 : nargs);
     543         5970 :   status = luaD_rawrunprotected(L, resume, L->top - nargs);
     544         5970 :   if (status == -1)  /* error calling 'lua_resume'? */
     545            0 :     status = LUA_ERRRUN;
     546              :   else {  /* yield or regular error */
     547         5970 :     while (status != LUA_OK && status != LUA_YIELD) {  /* error? */
     548            2 :       if (recover(L, status))  /* recover point? */
     549            0 :         status = luaD_rawrunprotected(L, unroll, NULL);  /* run continuation */
     550              :       else {  /* unrecoverable error */
     551            2 :         L->status = cast_byte(status);  /* mark thread as `dead' */
     552            2 :         seterrorobj(L, status, L->top);
     553            2 :         L->ci->top = L->top;
     554            2 :         break;
     555              :       }
     556              :     }
     557              :     lua_assert(status == L->status);
     558              :   }
     559         5970 :   L->nny = oldnny;  /* restore 'nny' */
     560         5970 :   L->nCcalls--;
     561              :   lua_assert(L->nCcalls == ((from) ? from->nCcalls : 0));
     562              :   lua_unlock(L);
     563         5970 :   return status;
     564              : }
     565              : 
     566              : 
     567         5954 : LUA_API int lua_yieldk (lua_State *L, int nresults, int ctx, lua_CFunction k) {
     568         5954 :   CallInfo *ci = L->ci;
     569              :   luai_userstateyield(L, nresults);
     570              :   lua_lock(L);
     571              :   api_checknelems(L, nresults);
     572         5954 :   if (L->nny > 0) {
     573            1 :     if (L != G(L)->mainthread)
     574            0 :       luaG_runerror(L, "attempt to yield across a C-call boundary");
     575              :     else
     576            1 :       luaG_runerror(L, "attempt to yield from outside a coroutine");
     577              :   }
     578         5953 :   L->status = LUA_YIELD;
     579         5953 :   ci->extra = savestack(L, ci->func);  /* save current 'func' */
     580         5953 :   if (isLua(ci)) {  /* inside a hook? */
     581              :     api_check(L, k == NULL, "hooks cannot continue after yielding");
     582              :   }
     583              :   else {
     584         5953 :     if ((ci->u.c.k = k) != NULL)  /* is there a continuation? */
     585            0 :       ci->u.c.ctx = ctx;  /* save context */
     586         5953 :     ci->func = L->top - nresults - 1;  /* protect stack below results */
     587         5953 :     luaD_throw(L, LUA_YIELD);
     588              :   }
     589              :   lua_assert(ci->callstatus & CIST_HOOKED);  /* must be inside a hook */
     590              :   lua_unlock(L);
     591            0 :   return 0;  /* return to 'luaD_hook' */
     592              : }
     593              : 
     594              : 
     595         1789 : int luaD_pcall (lua_State *L, Pfunc func, void *u,
     596              :                 ptrdiff_t old_top, ptrdiff_t ef) {
     597              :   int status;
     598         1789 :   CallInfo *old_ci = L->ci;
     599         1789 :   lu_byte old_allowhooks = L->allowhook;
     600         1789 :   unsigned short old_nny = L->nny;
     601         1789 :   ptrdiff_t old_errfunc = L->errfunc;
     602         1789 :   L->errfunc = ef;
     603         1789 :   status = luaD_rawrunprotected(L, func, u);
     604         1762 :   if (status != LUA_OK) {  /* an error occurred? */
     605          394 :     StkId oldtop = restorestack(L, old_top);
     606          394 :     luaF_close(L, oldtop);  /* close possible pending closures */
     607          394 :     seterrorobj(L, status, oldtop);
     608          394 :     L->ci = old_ci;
     609          394 :     L->allowhook = old_allowhooks;
     610          394 :     L->nny = old_nny;
     611          394 :     luaD_shrinkstack(L);
     612              :   }
     613         1762 :   L->errfunc = old_errfunc;
     614         1762 :   return status;
     615              : }
     616              : 
     617              : 
     618              : 
     619              : /*
     620              : ** Execute a protected parser.
     621              : */
     622              : struct SParser {  /* data to `f_parser' */
     623              :   ZIO *z;
     624              :   Mbuffer buff;  /* dynamic structure used by the scanner */
     625              :   Dyndata dyd;  /* dynamic structures used by the parser */
     626              :   const char *mode;
     627              :   const char *name;
     628              : };
     629              : 
     630              : 
     631          512 : static void checkmode (lua_State *L, const char *mode, const char *x) {
     632          512 :   if (mode && strchr(mode, x[0]) == NULL) {
     633            3 :     luaO_pushfstring(L,
     634              :        "attempt to load a %s chunk (mode is " LUA_QS ")", x, mode);
     635            3 :     luaD_throw(L, LUA_ERRSYNTAX);
     636              :   }
     637          509 : }
     638              : 
     639              : 
     640          513 : static void f_parser (lua_State *L, void *ud) {
     641              :   int i;
     642              :   Closure *cl;
     643          513 :   struct SParser *p = cast(struct SParser *, ud);
     644          513 :   int c = zgetc(p->z);  /* read first character */
     645          512 :   if (c == LUA_SIGNATURE[0]) {
     646           15 :     checkmode(L, p->mode, "binary");
     647           14 :     cl = luaU_undump(L, p->z, &p->buff, p->name);
     648              :   }
     649              :   else {
     650          497 :     checkmode(L, p->mode, "text");
     651          495 :     cl = luaY_parser(L, p->z, &p->buff, &p->dyd, p->name, c);
     652              :   }
     653              :   lua_assert(cl->l.nupvalues == cl->l.p->sizeupvalues);
     654          929 :   for (i = 0; i < cl->l.nupvalues; i++) {  /* initialize upvalues */
     655          464 :     UpVal *up = luaF_newupval(L);
     656          464 :     cl->l.upvals[i] = up;
     657          464 :     luaC_objbarrier(L, cl, up);
     658              :   }
     659          465 : }
     660              : 
     661              : 
     662          513 : int luaD_protectedparser (lua_State *L, ZIO *z, const char *name,
     663              :                                         const char *mode) {
     664              :   struct SParser p;
     665              :   int status;
     666          513 :   L->nny++;  /* cannot yield during parsing */
     667          513 :   p.z = z; p.name = name; p.mode = mode;
     668          513 :   p.dyd.actvar.arr = NULL; p.dyd.actvar.size = 0;
     669          513 :   p.dyd.gt.arr = NULL; p.dyd.gt.size = 0;
     670          513 :   p.dyd.label.arr = NULL; p.dyd.label.size = 0;
     671          513 :   luaZ_initbuffer(L, &p.buff);
     672          513 :   status = luaD_pcall(L, f_parser, &p, savestack(L, L->top), L->errfunc);
     673          513 :   luaZ_freebuffer(L, &p.buff);
     674          513 :   luaM_freearray(L, p.dyd.actvar.arr, p.dyd.actvar.size);
     675          513 :   luaM_freearray(L, p.dyd.gt.arr, p.dyd.gt.size);
     676          513 :   luaM_freearray(L, p.dyd.label.arr, p.dyd.label.size);
     677          513 :   L->nny--;
     678          513 :   return status;
     679              : }
     680              : 
     681              : 
        

Generated by: LCOV version 2.0-1