1 /* $NetBSD: lfunc.c,v 1.8 2018/08/04 17:30:01 alnsn Exp $ */ 2 3 /* 4 ** Id: lfunc.c,v 2.45.1.1 2017/04/19 17:39:34 roberto Exp 5 ** Auxiliary functions to manipulate prototypes and closures 6 ** See Copyright Notice in lua.h 7 */ 8 9 #define lfunc_c 10 #define LUA_CORE 11 12 #include "lprefix.h" 13 14 15 #ifndef _KERNEL 16 #include <stddef.h> 17 #endif /* _KERNEL */ 18 19 #include "lua.h" 20 21 #include "lfunc.h" 22 #include "lgc.h" 23 #include "lmem.h" 24 #include "lobject.h" 25 #include "lstate.h" 26 27 28 29 CClosure *luaF_newCclosure (lua_State *L, int n) { 30 GCObject *o = luaC_newobj(L, LUA_TCCL, sizeCclosure(n)); 31 CClosure *c = gco2ccl(o); 32 c->nupvalues = cast_byte(n); 33 return c; 34 } 35 36 37 LClosure *luaF_newLclosure (lua_State *L, int n) { 38 GCObject *o = luaC_newobj(L, LUA_TLCL, sizeLclosure(n)); 39 LClosure *c = gco2lcl(o); 40 c->p = NULL; 41 c->nupvalues = cast_byte(n); 42 while (n--) c->upvals[n] = NULL; 43 return c; 44 } 45 46 /* 47 ** fill a closure with new closed upvalues 48 */ 49 void luaF_initupvals (lua_State *L, LClosure *cl) { 50 int i; 51 for (i = 0; i < cl->nupvalues; i++) { 52 UpVal *uv = luaM_new(L, UpVal); 53 uv->refcount = 1; 54 uv->v = &uv->u.value; /* make it closed */ 55 setnilvalue(uv->v); 56 cl->upvals[i] = uv; 57 } 58 } 59 60 61 UpVal *luaF_findupval (lua_State *L, StkId level) { 62 UpVal **pp = &L->openupval; 63 UpVal *p; 64 UpVal *uv; 65 lua_assert(isintwups(L) || L->openupval == NULL); 66 while (*pp != NULL && (p = *pp)->v >= level) { 67 lua_assert(upisopen(p)); 68 if (p->v == level) /* found a corresponding upvalue? */ 69 return p; /* return it */ 70 pp = &p->u.open.next; 71 } 72 /* not found: create a new upvalue */ 73 uv = luaM_new(L, UpVal); 74 uv->refcount = 0; 75 uv->u.open.next = *pp; /* link it to list of open upvalues */ 76 uv->u.open.touched = 1; 77 *pp = uv; 78 uv->v = level; /* current value lives in the stack */ 79 if (!isintwups(L)) { /* thread not in list of threads with upvalues? */ 80 L->twups = G(L)->twups; /* link it to the list */ 81 G(L)->twups = L; 82 } 83 return uv; 84 } 85 86 87 void luaF_close (lua_State *L, StkId level) { 88 UpVal *uv; 89 while (L->openupval != NULL && (uv = L->openupval)->v >= level) { 90 lua_assert(upisopen(uv)); 91 L->openupval = uv->u.open.next; /* remove from 'open' list */ 92 if (uv->refcount == 0) /* no references? */ 93 luaM_free(L, uv); /* free upvalue */ 94 else { 95 setobj(L, &uv->u.value, uv->v); /* move value to upvalue slot */ 96 uv->v = &uv->u.value; /* now current value lives here */ 97 luaC_upvalbarrier(L, uv); 98 } 99 } 100 } 101 102 103 Proto *luaF_newproto (lua_State *L) { 104 GCObject *o = luaC_newobj(L, LUA_TPROTO, sizeof(Proto)); 105 Proto *f = gco2p(o); 106 f->k = NULL; 107 f->sizek = 0; 108 f->p = NULL; 109 f->sizep = 0; 110 f->code = NULL; 111 f->cache = NULL; 112 f->sizecode = 0; 113 f->lineinfo = NULL; 114 f->sizelineinfo = 0; 115 f->upvalues = NULL; 116 f->sizeupvalues = 0; 117 f->numparams = 0; 118 f->is_vararg = 0; 119 f->maxstacksize = 0; 120 f->locvars = NULL; 121 f->sizelocvars = 0; 122 f->linedefined = 0; 123 f->lastlinedefined = 0; 124 f->source = NULL; 125 return f; 126 } 127 128 129 void luaF_freeproto (lua_State *L, Proto *f) { 130 luaM_freearray(L, f->code, f->sizecode); 131 luaM_freearray(L, f->p, f->sizep); 132 luaM_freearray(L, f->k, f->sizek); 133 luaM_freearray(L, f->lineinfo, f->sizelineinfo); 134 luaM_freearray(L, f->locvars, f->sizelocvars); 135 luaM_freearray(L, f->upvalues, f->sizeupvalues); 136 luaM_free(L, f); 137 } 138 139 140 /* 141 ** Look for n-th local variable at line 'line' in function 'func'. 142 ** Returns NULL if not found. 143 */ 144 const char *luaF_getlocalname (const Proto *f, int local_number, int pc) { 145 int i; 146 for (i = 0; i<f->sizelocvars && f->locvars[i].startpc <= pc; i++) { 147 if (pc < f->locvars[i].endpc) { /* is variable active? */ 148 local_number--; 149 if (local_number == 0) 150 return getstr(f->locvars[i].varname); 151 } 152 } 153 return NULL; /* not found */ 154 } 155 156