LCOV - code coverage report
Current view: top level - external/lua/src - lfunc.c (source / functions) Hit Total Coverage
Test: rapport Lines: 63 168 37.5 %
Date: 2021-12-10 16:22:55 Functions: 7 16 43.8 %
Branches: 9 72 12.5 %

           Branch data     Line data    Source code
       1                 :            : /*
       2                 :            : ** $Id: lfunc.c $
       3                 :            : ** Auxiliary functions to manipulate prototypes and closures
       4                 :            : ** See Copyright Notice in lua.h
       5                 :            : */
       6                 :            : 
       7                 :            : #define lfunc_c
       8                 :            : #define LUA_CORE
       9                 :            : 
      10                 :            : #include "lprefix.h"
      11                 :            : 
      12                 :            : 
      13                 :            : #include <stddef.h>
      14                 :            : 
      15                 :            : #include "lua.h"
      16                 :            : 
      17                 :            : #include "ldebug.h"
      18                 :            : #include "ldo.h"
      19                 :            : #include "lfunc.h"
      20                 :            : #include "lgc.h"
      21                 :            : #include "lmem.h"
      22                 :            : #include "lobject.h"
      23                 :            : #include "lstate.h"
      24                 :            : 
      25                 :            : 
      26                 :            : 
      27                 :       5670 : CClosure *luaF_newCclosure (lua_State *L, int nupvals) {
      28                 :       5670 :   GCObject *o = luaC_newobj(L, LUA_VCCL, sizeCclosure(nupvals));
      29                 :       5670 :   CClosure *c = gco2ccl(o);
      30                 :       5670 :   c->nupvalues = cast_byte(nupvals);
      31                 :       5670 :   return c;
      32                 :            : }
      33                 :            : 
      34                 :            : 
      35                 :        656 : LClosure *luaF_newLclosure (lua_State *L, int nupvals) {
      36                 :        656 :   GCObject *o = luaC_newobj(L, LUA_VLCL, sizeLclosure(nupvals));
      37                 :        656 :   LClosure *c = gco2lcl(o);
      38                 :        656 :   c->p = NULL;
      39                 :        656 :   c->nupvalues = cast_byte(nupvals);
      40         [ +  + ]:       1312 :   while (nupvals--) c->upvals[nupvals] = NULL;
      41                 :        656 :   return c;
      42                 :            : }
      43                 :            : 
      44                 :            : 
      45                 :            : /*
      46                 :            : ** fill a closure with new closed upvalues
      47                 :            : */
      48                 :        652 : void luaF_initupvals (lua_State *L, LClosure *cl) {
      49                 :            :   int i;
      50         [ +  + ]:       1304 :   for (i = 0; i < cl->nupvalues; i++) {
      51                 :        652 :     GCObject *o = luaC_newobj(L, LUA_VUPVAL, sizeof(UpVal));
      52                 :        652 :     UpVal *uv = gco2upv(o);
      53                 :        652 :     uv->v = &uv->u.value;  /* make it closed */
      54                 :        652 :     setnilvalue(uv->v);
      55                 :        652 :     cl->upvals[i] = uv;
      56   [ -  +  #  # ]:        652 :     luaC_objbarrier(L, cl, uv);
      57                 :        652 :   }
      58                 :        652 : }
      59                 :            : 
      60                 :            : 
      61                 :            : /*
      62                 :            : ** Create a new upvalue at the given level, and link it to the list of
      63                 :            : ** open upvalues of 'L' after entry 'prev'.
      64                 :            : **/
      65                 :          0 : static UpVal *newupval (lua_State *L, int tbc, StkId level, UpVal **prev) {
      66                 :          0 :   GCObject *o = luaC_newobj(L, LUA_VUPVAL, sizeof(UpVal));
      67                 :          0 :   UpVal *uv = gco2upv(o);
      68                 :          0 :   UpVal *next = *prev;
      69                 :          0 :   uv->v = s2v(level);  /* current value lives in the stack */
      70                 :          0 :   uv->tbc = tbc;
      71                 :          0 :   uv->u.open.next = next;  /* link it to list of open upvalues */
      72                 :          0 :   uv->u.open.previous = prev;
      73         [ #  # ]:          0 :   if (next)
      74                 :          0 :     next->u.open.previous = &uv->u.open.next;
      75                 :          0 :   *prev = uv;
      76         [ #  # ]:          0 :   if (!isintwups(L)) {  /* thread not in list of threads with upvalues? */
      77                 :          0 :     L->twups = G(L)->twups;  /* link it to the list */
      78                 :          0 :     G(L)->twups = L;
      79                 :          0 :   }
      80                 :          0 :   return uv;
      81                 :            : }
      82                 :            : 
      83                 :            : 
      84                 :            : /*
      85                 :            : ** Find and reuse, or create if it does not exist, an upvalue
      86                 :            : ** at the given level.
      87                 :            : */
      88                 :          0 : UpVal *luaF_findupval (lua_State *L, StkId level) {
      89                 :          0 :   UpVal **pp = &L->openupval;
      90                 :            :   UpVal *p;
      91                 :            :   lua_assert(isintwups(L) || L->openupval == NULL);
      92   [ #  #  #  # ]:          0 :   while ((p = *pp) != NULL && uplevel(p) >= level) {  /* search for it */
      93                 :            :     lua_assert(!isdead(G(L), p));
      94         [ #  # ]:          0 :     if (uplevel(p) == level)  /* corresponding upvalue? */
      95                 :          0 :       return p;  /* return it */
      96                 :          0 :     pp = &p->u.open.next;
      97                 :            :   }
      98                 :            :   /* not found: create a new upvalue after 'pp' */
      99                 :          0 :   return newupval(L, 0, level, pp);
     100                 :          0 : }
     101                 :            : 
     102                 :            : 
     103                 :          0 : static void callclose (lua_State *L, void *ud) {
     104                 :          0 :   UNUSED(ud);
     105                 :          0 :   luaD_callnoyield(L, L->top - 3, 0);
     106                 :          0 : }
     107                 :            : 
     108                 :            : 
     109                 :            : /*
     110                 :            : ** Prepare closing method plus its arguments for object 'obj' with
     111                 :            : ** error message 'err'. (This function assumes EXTRA_STACK.)
     112                 :            : */
     113                 :          0 : static int prepclosingmethod (lua_State *L, TValue *obj, TValue *err) {
     114                 :          0 :   StkId top = L->top;
     115                 :          0 :   const TValue *tm = luaT_gettmbyobj(L, obj, TM_CLOSE);
     116         [ #  # ]:          0 :   if (ttisnil(tm))  /* no metamethod? */
     117                 :          0 :     return 0;  /* nothing to call */
     118                 :          0 :   setobj2s(L, top, tm);  /* will call metamethod... */
     119                 :          0 :   setobj2s(L, top + 1, obj);  /* with 'self' as the 1st argument */
     120                 :          0 :   setobj2s(L, top + 2, err);  /* and error msg. as 2nd argument */
     121                 :          0 :   L->top = top + 3;  /* add function and arguments */
     122                 :          0 :   return 1;
     123                 :          0 : }
     124                 :            : 
     125                 :            : 
     126                 :            : /*
     127                 :            : ** Raise an error with message 'msg', inserting the name of the
     128                 :            : ** local variable at position 'level' in the stack.
     129                 :            : */
     130                 :          0 : static void varerror (lua_State *L, StkId level, const char *msg) {
     131                 :          0 :   int idx = cast_int(level - L->ci->func);
     132                 :          0 :   const char *vname = luaG_findlocal(L, L->ci, idx, NULL);
     133         [ #  # ]:          0 :   if (vname == NULL) vname = "?";
     134                 :          0 :   luaG_runerror(L, msg, vname);
     135                 :            : }
     136                 :            : 
     137                 :            : 
     138                 :            : /*
     139                 :            : ** Prepare and call a closing method. If status is OK, code is still
     140                 :            : ** inside the original protected call, and so any error will be handled
     141                 :            : ** there. Otherwise, a previous error already activated the original
     142                 :            : ** protected call, and so the call to the closing method must be
     143                 :            : ** protected here. (A status == CLOSEPROTECT behaves like a previous
     144                 :            : ** error, to also run the closing method in protected mode).
     145                 :            : ** If status is OK, the call to the closing method will be pushed
     146                 :            : ** at the top of the stack. Otherwise, values are pushed after
     147                 :            : ** the 'level' of the upvalue being closed, as everything after
     148                 :            : ** that won't be used again.
     149                 :            : */
     150                 :          0 : static int callclosemth (lua_State *L, StkId level, int status) {
     151                 :          0 :   TValue *uv = s2v(level);  /* value being closed */
     152         [ #  # ]:          0 :   if (likely(status == LUA_OK)) {
     153         [ #  # ]:          0 :     if (prepclosingmethod(L, uv, &G(L)->nilvalue))  /* something to call? */
     154                 :          0 :       callclose(L, NULL);  /* call closing method */
     155   [ #  #  #  # ]:          0 :     else if (!l_isfalse(uv))  /* non-closable non-false value? */
     156                 :          0 :       varerror(L, level, "attempt to close non-closable variable '%s'");
     157                 :          0 :   }
     158                 :            :   else {  /* must close the object in protected mode */
     159                 :            :     ptrdiff_t oldtop;
     160                 :          0 :     level++;  /* space for error message */
     161                 :          0 :     oldtop = savestack(L, level + 1);  /* top will be after that */
     162                 :          0 :     luaD_seterrorobj(L, status, level);  /* set error message */
     163         [ #  # ]:          0 :     if (prepclosingmethod(L, uv, s2v(level))) {  /* something to call? */
     164                 :          0 :       int newstatus = luaD_pcall(L, callclose, NULL, oldtop, 0);
     165   [ #  #  #  # ]:          0 :       if (newstatus != LUA_OK && status == CLOSEPROTECT)  /* first error? */
     166                 :          0 :         status = newstatus;  /* this will be the new error */
     167                 :            :       else {
     168         [ #  # ]:          0 :         if (newstatus != LUA_OK)  /* suppressed error? */
     169                 :          0 :           luaE_warnerror(L, "__close metamethod");
     170                 :            :         /* leave original error (or nil) on top */
     171                 :          0 :         L->top = restorestack(L, oldtop);
     172                 :            :       }
     173                 :          0 :     }
     174                 :            :     /* else no metamethod; ignore this case and keep original error */
     175                 :            :   }
     176                 :          0 :   return status;
     177                 :            : }
     178                 :            : 
     179                 :            : 
     180                 :            : /*
     181                 :            : ** Try to create a to-be-closed upvalue
     182                 :            : ** (can raise a memory-allocation error)
     183                 :            : */
     184                 :          0 : static void trynewtbcupval (lua_State *L, void *ud) {
     185                 :          0 :   newupval(L, 1, cast(StkId, ud), &L->openupval);
     186                 :          0 : }
     187                 :            : 
     188                 :            : 
     189                 :            : /*
     190                 :            : ** Create a to-be-closed upvalue. If there is a memory error
     191                 :            : ** when creating the upvalue, the closing method must be called here,
     192                 :            : ** as there is no upvalue to call it later.
     193                 :            : */
     194                 :          0 : void luaF_newtbcupval (lua_State *L, StkId level) {
     195                 :          0 :   TValue *obj = s2v(level);
     196                 :            :   lua_assert(L->openupval == NULL || uplevel(L->openupval) < level);
     197   [ #  #  #  # ]:          0 :   if (!l_isfalse(obj)) {  /* false doesn't need to be closed */
     198                 :            :     int status;
     199                 :          0 :     const TValue *tm = luaT_gettmbyobj(L, obj, TM_CLOSE);
     200         [ #  # ]:          0 :     if (ttisnil(tm))  /* no metamethod? */
     201                 :          0 :       varerror(L, level, "variable '%s' got a non-closable value");
     202                 :          0 :     status = luaD_rawrunprotected(L, trynewtbcupval, level);
     203         [ #  # ]:          0 :     if (unlikely(status != LUA_OK)) {  /* memory error creating upvalue? */
     204                 :            :       lua_assert(status == LUA_ERRMEM);
     205                 :          0 :       luaD_seterrorobj(L, LUA_ERRMEM, level + 1);  /* save error message */
     206                 :            :       /* next call must succeed, as object is closable */
     207                 :          0 :       prepclosingmethod(L, s2v(level), s2v(level + 1));
     208                 :          0 :       callclose(L, NULL);  /* call closing method */
     209                 :          0 :       luaD_throw(L, LUA_ERRMEM);  /* throw memory error */
     210                 :            :     }
     211                 :          0 :   }
     212                 :          0 : }
     213                 :            : 
     214                 :            : 
     215                 :          0 : void luaF_unlinkupval (UpVal *uv) {
     216                 :            :   lua_assert(upisopen(uv));
     217                 :          0 :   *uv->u.open.previous = uv->u.open.next;
     218         [ #  # ]:          0 :   if (uv->u.open.next)
     219                 :          0 :     uv->u.open.next->u.open.previous = uv->u.open.previous;
     220                 :          0 : }
     221                 :            : 
     222                 :            : 
     223                 :        329 : int luaF_close (lua_State *L, StkId level, int status) {
     224                 :            :   UpVal *uv;
     225   [ +  -  -  + ]:        329 :   while ((uv = L->openupval) != NULL && uplevel(uv) >= level) {
     226                 :          0 :     TValue *slot = &uv->u.value;  /* new position for value */
     227                 :            :     lua_assert(uplevel(uv) < L->top);
     228   [ #  #  #  # ]:          0 :     if (uv->tbc && status != NOCLOSINGMETH) {
     229                 :            :       /* must run closing method, which may change the stack */
     230                 :          0 :       ptrdiff_t levelrel = savestack(L, level);
     231                 :          0 :       status = callclosemth(L, uplevel(uv), status);
     232                 :          0 :       level = restorestack(L, levelrel);
     233                 :          0 :     }
     234                 :          0 :     luaF_unlinkupval(uv);
     235                 :          0 :     setobj(L, slot, uv->v);  /* move value to upvalue slot */
     236                 :          0 :     uv->v = slot;  /* now current value lives here */
     237         [ #  # ]:          0 :     if (!iswhite(uv)) {  /* neither white nor dead? */
     238                 :          0 :       nw2black(uv);  /* closed upvalues cannot be gray */
     239   [ #  #  #  #  :          0 :       luaC_barrier(L, uv, slot);
                   #  # ]
     240                 :          0 :     }
     241                 :            :   }
     242                 :        329 :   return status;
     243                 :            : }
     244                 :            : 
     245                 :            : 
     246                 :        656 : Proto *luaF_newproto (lua_State *L) {
     247                 :        656 :   GCObject *o = luaC_newobj(L, LUA_VPROTO, sizeof(Proto));
     248                 :        656 :   Proto *f = gco2p(o);
     249                 :        656 :   f->k = NULL;
     250                 :        656 :   f->sizek = 0;
     251                 :        656 :   f->p = NULL;
     252                 :        656 :   f->sizep = 0;
     253                 :        656 :   f->code = NULL;
     254                 :        656 :   f->sizecode = 0;
     255                 :        656 :   f->lineinfo = NULL;
     256                 :        656 :   f->sizelineinfo = 0;
     257                 :        656 :   f->abslineinfo = NULL;
     258                 :        656 :   f->sizeabslineinfo = 0;
     259                 :        656 :   f->upvalues = NULL;
     260                 :        656 :   f->sizeupvalues = 0;
     261                 :        656 :   f->numparams = 0;
     262                 :        656 :   f->is_vararg = 0;
     263                 :        656 :   f->maxstacksize = 0;
     264                 :        656 :   f->locvars = NULL;
     265                 :        656 :   f->sizelocvars = 0;
     266                 :        656 :   f->linedefined = 0;
     267                 :        656 :   f->lastlinedefined = 0;
     268                 :        656 :   f->source = NULL;
     269                 :        656 :   return f;
     270                 :            : }
     271                 :            : 
     272                 :            : 
     273                 :         40 : void luaF_freeproto (lua_State *L, Proto *f) {
     274                 :         40 :   luaM_freearray(L, f->code, f->sizecode);
     275                 :         40 :   luaM_freearray(L, f->p, f->sizep);
     276                 :         40 :   luaM_freearray(L, f->k, f->sizek);
     277                 :         40 :   luaM_freearray(L, f->lineinfo, f->sizelineinfo);
     278                 :         40 :   luaM_freearray(L, f->abslineinfo, f->sizeabslineinfo);
     279                 :         40 :   luaM_freearray(L, f->locvars, f->sizelocvars);
     280                 :         40 :   luaM_freearray(L, f->upvalues, f->sizeupvalues);
     281                 :         40 :   luaM_free(L, f);
     282                 :         40 : }
     283                 :            : 
     284                 :            : 
     285                 :            : /*
     286                 :            : ** Look for n-th local variable at line 'line' in function 'func'.
     287                 :            : ** Returns NULL if not found.
     288                 :            : */
     289                 :        491 : const char *luaF_getlocalname (const Proto *f, int local_number, int pc) {
     290                 :            :   int i;
     291   [ +  -  -  + ]:        491 :   for (i = 0; i<f->sizelocvars && f->locvars[i].startpc <= pc; i++) {
     292         [ #  # ]:          0 :     if (pc < f->locvars[i].endpc) {  /* is variable active? */
     293                 :          0 :       local_number--;
     294         [ #  # ]:          0 :       if (local_number == 0)
     295                 :          0 :         return getstr(f->locvars[i].varname);
     296                 :          0 :     }
     297                 :          0 :   }
     298                 :        491 :   return NULL;  /* not found */
     299                 :        491 : }
     300                 :            : 

Generated by: LCOV version 1.15