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