xref: /freebsd/contrib/lua/src/ldebug.c (revision 0495ed398c4f64013bab2327eb13a303e1f90c13)
18e3e3a7aSWarner Losh /*
2*0495ed39SKyle Evans ** $Id: ldebug.c $
38e3e3a7aSWarner Losh ** Debug Interface
48e3e3a7aSWarner Losh ** See Copyright Notice in lua.h
58e3e3a7aSWarner Losh */
68e3e3a7aSWarner Losh 
78e3e3a7aSWarner Losh #define ldebug_c
88e3e3a7aSWarner Losh #define LUA_CORE
98e3e3a7aSWarner Losh 
108e3e3a7aSWarner Losh #include "lprefix.h"
118e3e3a7aSWarner Losh 
128e3e3a7aSWarner Losh 
138e3e3a7aSWarner Losh #include <stdarg.h>
148e3e3a7aSWarner Losh #include <stddef.h>
158e3e3a7aSWarner Losh #include <string.h>
168e3e3a7aSWarner Losh 
178e3e3a7aSWarner Losh #include "lua.h"
188e3e3a7aSWarner Losh 
198e3e3a7aSWarner Losh #include "lapi.h"
208e3e3a7aSWarner Losh #include "lcode.h"
218e3e3a7aSWarner Losh #include "ldebug.h"
228e3e3a7aSWarner Losh #include "ldo.h"
238e3e3a7aSWarner Losh #include "lfunc.h"
248e3e3a7aSWarner Losh #include "lobject.h"
258e3e3a7aSWarner Losh #include "lopcodes.h"
268e3e3a7aSWarner Losh #include "lstate.h"
278e3e3a7aSWarner Losh #include "lstring.h"
288e3e3a7aSWarner Losh #include "ltable.h"
298e3e3a7aSWarner Losh #include "ltm.h"
308e3e3a7aSWarner Losh #include "lvm.h"
318e3e3a7aSWarner Losh 
328e3e3a7aSWarner Losh 
338e3e3a7aSWarner Losh 
34*0495ed39SKyle Evans #define noLuaClosure(f)		((f) == NULL || (f)->c.tt == LUA_VCCL)
358e3e3a7aSWarner Losh 
36*0495ed39SKyle Evans /* inverse of 'pcRel' */
37*0495ed39SKyle Evans #define invpcRel(pc, p)		((p)->code + (pc) + 1)
388e3e3a7aSWarner Losh 
398e3e3a7aSWarner Losh static const char *funcnamefromcode (lua_State *L, CallInfo *ci,
408e3e3a7aSWarner Losh                                     const char **name);
418e3e3a7aSWarner Losh 
428e3e3a7aSWarner Losh 
438e3e3a7aSWarner Losh static int currentpc (CallInfo *ci) {
448e3e3a7aSWarner Losh   lua_assert(isLua(ci));
458e3e3a7aSWarner Losh   return pcRel(ci->u.l.savedpc, ci_func(ci)->p);
468e3e3a7aSWarner Losh }
478e3e3a7aSWarner Losh 
488e3e3a7aSWarner Losh 
498e3e3a7aSWarner Losh /*
50*0495ed39SKyle Evans ** Get a "base line" to find the line corresponding to an instruction.
51*0495ed39SKyle Evans ** For that, search the array of absolute line info for the largest saved
52*0495ed39SKyle Evans ** instruction smaller or equal to the wanted instruction. A special
53*0495ed39SKyle Evans ** case is when there is no absolute info or the instruction is before
54*0495ed39SKyle Evans ** the first absolute one.
558e3e3a7aSWarner Losh */
56*0495ed39SKyle Evans static int getbaseline (const Proto *f, int pc, int *basepc) {
57*0495ed39SKyle Evans   if (f->sizeabslineinfo == 0 || pc < f->abslineinfo[0].pc) {
58*0495ed39SKyle Evans     *basepc = -1;  /* start from the beginning */
59*0495ed39SKyle Evans     return f->linedefined;
60*0495ed39SKyle Evans   }
61*0495ed39SKyle Evans   else {
62*0495ed39SKyle Evans     unsigned int i;
63*0495ed39SKyle Evans     if (pc >= f->abslineinfo[f->sizeabslineinfo - 1].pc)
64*0495ed39SKyle Evans       i = f->sizeabslineinfo - 1;  /* instruction is after last saved one */
65*0495ed39SKyle Evans     else {  /* binary search */
66*0495ed39SKyle Evans       unsigned int j = f->sizeabslineinfo - 1;  /* pc < anchorlines[j] */
67*0495ed39SKyle Evans       i = 0;  /* abslineinfo[i] <= pc */
68*0495ed39SKyle Evans       while (i < j - 1) {
69*0495ed39SKyle Evans         unsigned int m = (j + i) / 2;
70*0495ed39SKyle Evans         if (pc >= f->abslineinfo[m].pc)
71*0495ed39SKyle Evans           i = m;
72*0495ed39SKyle Evans         else
73*0495ed39SKyle Evans           j = m;
74*0495ed39SKyle Evans       }
75*0495ed39SKyle Evans     }
76*0495ed39SKyle Evans     *basepc = f->abslineinfo[i].pc;
77*0495ed39SKyle Evans     return f->abslineinfo[i].line;
788e3e3a7aSWarner Losh   }
798e3e3a7aSWarner Losh }
808e3e3a7aSWarner Losh 
818e3e3a7aSWarner Losh 
828e3e3a7aSWarner Losh /*
83*0495ed39SKyle Evans ** Get the line corresponding to instruction 'pc' in function 'f';
84*0495ed39SKyle Evans ** first gets a base line and from there does the increments until
85*0495ed39SKyle Evans ** the desired instruction.
86*0495ed39SKyle Evans */
87*0495ed39SKyle Evans int luaG_getfuncline (const Proto *f, int pc) {
88*0495ed39SKyle Evans   if (f->lineinfo == NULL)  /* no debug information? */
89*0495ed39SKyle Evans     return -1;
90*0495ed39SKyle Evans   else {
91*0495ed39SKyle Evans     int basepc;
92*0495ed39SKyle Evans     int baseline = getbaseline(f, pc, &basepc);
93*0495ed39SKyle Evans     while (basepc++ < pc) {  /* walk until given instruction */
94*0495ed39SKyle Evans       lua_assert(f->lineinfo[basepc] != ABSLINEINFO);
95*0495ed39SKyle Evans       baseline += f->lineinfo[basepc];  /* correct line */
96*0495ed39SKyle Evans     }
97*0495ed39SKyle Evans     return baseline;
98*0495ed39SKyle Evans   }
99*0495ed39SKyle Evans }
100*0495ed39SKyle Evans 
101*0495ed39SKyle Evans 
102*0495ed39SKyle Evans static int getcurrentline (CallInfo *ci) {
103*0495ed39SKyle Evans   return luaG_getfuncline(ci_func(ci)->p, currentpc(ci));
104*0495ed39SKyle Evans }
105*0495ed39SKyle Evans 
106*0495ed39SKyle Evans 
107*0495ed39SKyle Evans /*
108*0495ed39SKyle Evans ** Set 'trap' for all active Lua frames.
109*0495ed39SKyle Evans ** This function can be called during a signal, under "reasonable"
110*0495ed39SKyle Evans ** assumptions. A new 'ci' is completely linked in the list before it
111*0495ed39SKyle Evans ** becomes part of the "active" list, and we assume that pointers are
112*0495ed39SKyle Evans ** atomic; see comment in next function.
113*0495ed39SKyle Evans ** (A compiler doing interprocedural optimizations could, theoretically,
114*0495ed39SKyle Evans ** reorder memory writes in such a way that the list could be
115*0495ed39SKyle Evans ** temporarily broken while inserting a new element. We simply assume it
116*0495ed39SKyle Evans ** has no good reasons to do that.)
117*0495ed39SKyle Evans */
118*0495ed39SKyle Evans static void settraps (CallInfo *ci) {
119*0495ed39SKyle Evans   for (; ci != NULL; ci = ci->previous)
120*0495ed39SKyle Evans     if (isLua(ci))
121*0495ed39SKyle Evans       ci->u.l.trap = 1;
122*0495ed39SKyle Evans }
123*0495ed39SKyle Evans 
124*0495ed39SKyle Evans 
125*0495ed39SKyle Evans /*
126*0495ed39SKyle Evans ** This function can be called during a signal, under "reasonable"
127*0495ed39SKyle Evans ** assumptions.
128*0495ed39SKyle Evans ** Fields 'basehookcount' and 'hookcount' (set by 'resethookcount')
129*0495ed39SKyle Evans ** are for debug only, and it is no problem if they get arbitrary
130*0495ed39SKyle Evans ** values (causes at most one wrong hook call). 'hookmask' is an atomic
131*0495ed39SKyle Evans ** value. We assume that pointers are atomic too (e.g., gcc ensures that
132*0495ed39SKyle Evans ** for all platforms where it runs). Moreover, 'hook' is always checked
133*0495ed39SKyle Evans ** before being called (see 'luaD_hook').
1348e3e3a7aSWarner Losh */
1358e3e3a7aSWarner Losh LUA_API void lua_sethook (lua_State *L, lua_Hook func, int mask, int count) {
1368e3e3a7aSWarner Losh   if (func == NULL || mask == 0) {  /* turn off hooks? */
1378e3e3a7aSWarner Losh     mask = 0;
1388e3e3a7aSWarner Losh     func = NULL;
1398e3e3a7aSWarner Losh   }
1408e3e3a7aSWarner Losh   L->hook = func;
1418e3e3a7aSWarner Losh   L->basehookcount = count;
1428e3e3a7aSWarner Losh   resethookcount(L);
1438e3e3a7aSWarner Losh   L->hookmask = cast_byte(mask);
144*0495ed39SKyle Evans   if (mask)
145*0495ed39SKyle Evans     settraps(L->ci);  /* to trace inside 'luaV_execute' */
1468e3e3a7aSWarner Losh }
1478e3e3a7aSWarner Losh 
1488e3e3a7aSWarner Losh 
1498e3e3a7aSWarner Losh LUA_API lua_Hook lua_gethook (lua_State *L) {
1508e3e3a7aSWarner Losh   return L->hook;
1518e3e3a7aSWarner Losh }
1528e3e3a7aSWarner Losh 
1538e3e3a7aSWarner Losh 
1548e3e3a7aSWarner Losh LUA_API int lua_gethookmask (lua_State *L) {
1558e3e3a7aSWarner Losh   return L->hookmask;
1568e3e3a7aSWarner Losh }
1578e3e3a7aSWarner Losh 
1588e3e3a7aSWarner Losh 
1598e3e3a7aSWarner Losh LUA_API int lua_gethookcount (lua_State *L) {
1608e3e3a7aSWarner Losh   return L->basehookcount;
1618e3e3a7aSWarner Losh }
1628e3e3a7aSWarner Losh 
1638e3e3a7aSWarner Losh 
1648e3e3a7aSWarner Losh LUA_API int lua_getstack (lua_State *L, int level, lua_Debug *ar) {
1658e3e3a7aSWarner Losh   int status;
1668e3e3a7aSWarner Losh   CallInfo *ci;
1678e3e3a7aSWarner Losh   if (level < 0) return 0;  /* invalid (negative) level */
1688e3e3a7aSWarner Losh   lua_lock(L);
1698e3e3a7aSWarner Losh   for (ci = L->ci; level > 0 && ci != &L->base_ci; ci = ci->previous)
1708e3e3a7aSWarner Losh     level--;
1718e3e3a7aSWarner Losh   if (level == 0 && ci != &L->base_ci) {  /* level found? */
1728e3e3a7aSWarner Losh     status = 1;
1738e3e3a7aSWarner Losh     ar->i_ci = ci;
1748e3e3a7aSWarner Losh   }
1758e3e3a7aSWarner Losh   else status = 0;  /* no such level */
1768e3e3a7aSWarner Losh   lua_unlock(L);
1778e3e3a7aSWarner Losh   return status;
1788e3e3a7aSWarner Losh }
1798e3e3a7aSWarner Losh 
1808e3e3a7aSWarner Losh 
181*0495ed39SKyle Evans static const char *upvalname (const Proto *p, int uv) {
1828e3e3a7aSWarner Losh   TString *s = check_exp(uv < p->sizeupvalues, p->upvalues[uv].name);
1838e3e3a7aSWarner Losh   if (s == NULL) return "?";
1848e3e3a7aSWarner Losh   else return getstr(s);
1858e3e3a7aSWarner Losh }
1868e3e3a7aSWarner Losh 
1878e3e3a7aSWarner Losh 
1888e3e3a7aSWarner Losh static const char *findvararg (CallInfo *ci, int n, StkId *pos) {
189*0495ed39SKyle Evans   if (clLvalue(s2v(ci->func))->p->is_vararg) {
190*0495ed39SKyle Evans     int nextra = ci->u.l.nextraargs;
191*0495ed39SKyle Evans     if (n >= -nextra) {  /* 'n' is negative */
192*0495ed39SKyle Evans       *pos = ci->func - nextra - (n + 1);
193*0495ed39SKyle Evans       return "(vararg)";  /* generic name for any vararg */
194*0495ed39SKyle Evans     }
195*0495ed39SKyle Evans   }
1968e3e3a7aSWarner Losh   return NULL;  /* no such vararg */
1978e3e3a7aSWarner Losh }
1988e3e3a7aSWarner Losh 
1998e3e3a7aSWarner Losh 
200*0495ed39SKyle Evans const char *luaG_findlocal (lua_State *L, CallInfo *ci, int n, StkId *pos) {
201*0495ed39SKyle Evans   StkId base = ci->func + 1;
2028e3e3a7aSWarner Losh   const char *name = NULL;
2038e3e3a7aSWarner Losh   if (isLua(ci)) {
2048e3e3a7aSWarner Losh     if (n < 0)  /* access to vararg values? */
205bf9580a1SKyle Evans       return findvararg(ci, n, pos);
206*0495ed39SKyle Evans     else
2078e3e3a7aSWarner Losh       name = luaF_getlocalname(ci_func(ci)->p, n, currentpc(ci));
2088e3e3a7aSWarner Losh   }
2098e3e3a7aSWarner Losh   if (name == NULL) {  /* no 'standard' name? */
2108e3e3a7aSWarner Losh     StkId limit = (ci == L->ci) ? L->top : ci->next->func;
211*0495ed39SKyle Evans     if (limit - base >= n && n > 0) {  /* is 'n' inside 'ci' stack? */
212*0495ed39SKyle Evans       /* generic name for any valid slot */
213*0495ed39SKyle Evans       name = isLua(ci) ? "(temporary)" : "(C temporary)";
214*0495ed39SKyle Evans     }
2158e3e3a7aSWarner Losh     else
2168e3e3a7aSWarner Losh       return NULL;  /* no name */
2178e3e3a7aSWarner Losh   }
218*0495ed39SKyle Evans   if (pos)
2198e3e3a7aSWarner Losh     *pos = base + (n - 1);
2208e3e3a7aSWarner Losh   return name;
2218e3e3a7aSWarner Losh }
2228e3e3a7aSWarner Losh 
2238e3e3a7aSWarner Losh 
2248e3e3a7aSWarner Losh LUA_API const char *lua_getlocal (lua_State *L, const lua_Debug *ar, int n) {
2258e3e3a7aSWarner Losh   const char *name;
2268e3e3a7aSWarner Losh   lua_lock(L);
2278e3e3a7aSWarner Losh   if (ar == NULL) {  /* information about non-active function? */
228*0495ed39SKyle Evans     if (!isLfunction(s2v(L->top - 1)))  /* not a Lua function? */
2298e3e3a7aSWarner Losh       name = NULL;
2308e3e3a7aSWarner Losh     else  /* consider live variables at function start (parameters) */
231*0495ed39SKyle Evans       name = luaF_getlocalname(clLvalue(s2v(L->top - 1))->p, n, 0);
2328e3e3a7aSWarner Losh   }
2338e3e3a7aSWarner Losh   else {  /* active function; get information through 'ar' */
2348e3e3a7aSWarner Losh     StkId pos = NULL;  /* to avoid warnings */
235*0495ed39SKyle Evans     name = luaG_findlocal(L, ar->i_ci, n, &pos);
2368e3e3a7aSWarner Losh     if (name) {
237*0495ed39SKyle Evans       setobjs2s(L, L->top, pos);
2388e3e3a7aSWarner Losh       api_incr_top(L);
2398e3e3a7aSWarner Losh     }
2408e3e3a7aSWarner Losh   }
2418e3e3a7aSWarner Losh   lua_unlock(L);
2428e3e3a7aSWarner Losh   return name;
2438e3e3a7aSWarner Losh }
2448e3e3a7aSWarner Losh 
2458e3e3a7aSWarner Losh 
2468e3e3a7aSWarner Losh LUA_API const char *lua_setlocal (lua_State *L, const lua_Debug *ar, int n) {
2478e3e3a7aSWarner Losh   StkId pos = NULL;  /* to avoid warnings */
2488e3e3a7aSWarner Losh   const char *name;
2498e3e3a7aSWarner Losh   lua_lock(L);
250*0495ed39SKyle Evans   name = luaG_findlocal(L, ar->i_ci, n, &pos);
2518e3e3a7aSWarner Losh   if (name) {
2528e3e3a7aSWarner Losh     setobjs2s(L, pos, L->top - 1);
2538e3e3a7aSWarner Losh     L->top--;  /* pop value */
2548e3e3a7aSWarner Losh   }
2558e3e3a7aSWarner Losh   lua_unlock(L);
2568e3e3a7aSWarner Losh   return name;
2578e3e3a7aSWarner Losh }
2588e3e3a7aSWarner Losh 
2598e3e3a7aSWarner Losh 
2608e3e3a7aSWarner Losh static void funcinfo (lua_Debug *ar, Closure *cl) {
2618e3e3a7aSWarner Losh   if (noLuaClosure(cl)) {
2628e3e3a7aSWarner Losh     ar->source = "=[C]";
263*0495ed39SKyle Evans     ar->srclen = LL("=[C]");
2648e3e3a7aSWarner Losh     ar->linedefined = -1;
2658e3e3a7aSWarner Losh     ar->lastlinedefined = -1;
2668e3e3a7aSWarner Losh     ar->what = "C";
2678e3e3a7aSWarner Losh   }
2688e3e3a7aSWarner Losh   else {
269*0495ed39SKyle Evans     const Proto *p = cl->l.p;
270*0495ed39SKyle Evans     if (p->source) {
271*0495ed39SKyle Evans       ar->source = getstr(p->source);
272*0495ed39SKyle Evans       ar->srclen = tsslen(p->source);
273*0495ed39SKyle Evans     }
274*0495ed39SKyle Evans     else {
275*0495ed39SKyle Evans       ar->source = "=?";
276*0495ed39SKyle Evans       ar->srclen = LL("=?");
277*0495ed39SKyle Evans     }
2788e3e3a7aSWarner Losh     ar->linedefined = p->linedefined;
2798e3e3a7aSWarner Losh     ar->lastlinedefined = p->lastlinedefined;
2808e3e3a7aSWarner Losh     ar->what = (ar->linedefined == 0) ? "main" : "Lua";
2818e3e3a7aSWarner Losh   }
282*0495ed39SKyle Evans   luaO_chunkid(ar->short_src, ar->source, ar->srclen);
283*0495ed39SKyle Evans }
284*0495ed39SKyle Evans 
285*0495ed39SKyle Evans 
286*0495ed39SKyle Evans static int nextline (const Proto *p, int currentline, int pc) {
287*0495ed39SKyle Evans   if (p->lineinfo[pc] != ABSLINEINFO)
288*0495ed39SKyle Evans     return currentline + p->lineinfo[pc];
289*0495ed39SKyle Evans   else
290*0495ed39SKyle Evans     return luaG_getfuncline(p, pc);
2918e3e3a7aSWarner Losh }
2928e3e3a7aSWarner Losh 
2938e3e3a7aSWarner Losh 
2948e3e3a7aSWarner Losh static void collectvalidlines (lua_State *L, Closure *f) {
2958e3e3a7aSWarner Losh   if (noLuaClosure(f)) {
296*0495ed39SKyle Evans     setnilvalue(s2v(L->top));
2978e3e3a7aSWarner Losh     api_incr_top(L);
2988e3e3a7aSWarner Losh   }
2998e3e3a7aSWarner Losh   else {
3008e3e3a7aSWarner Losh     int i;
3018e3e3a7aSWarner Losh     TValue v;
302*0495ed39SKyle Evans     const Proto *p = f->l.p;
303*0495ed39SKyle Evans     int currentline = p->linedefined;
3048e3e3a7aSWarner Losh     Table *t = luaH_new(L);  /* new table to store active lines */
305*0495ed39SKyle Evans     sethvalue2s(L, L->top, t);  /* push it on stack */
3068e3e3a7aSWarner Losh     api_incr_top(L);
307*0495ed39SKyle Evans     setbtvalue(&v);  /* boolean 'true' to be the value of all indices */
308*0495ed39SKyle Evans     for (i = 0; i < p->sizelineinfo; i++) {  /* for all lines with code */
309*0495ed39SKyle Evans       currentline = nextline(p, currentline, i);
310*0495ed39SKyle Evans       luaH_setint(L, t, currentline, &v);  /* table[line] = true */
311*0495ed39SKyle Evans     }
3128e3e3a7aSWarner Losh   }
3138e3e3a7aSWarner Losh }
3148e3e3a7aSWarner Losh 
3158e3e3a7aSWarner Losh 
3168e3e3a7aSWarner Losh static const char *getfuncname (lua_State *L, CallInfo *ci, const char **name) {
3178e3e3a7aSWarner Losh   if (ci == NULL)  /* no 'ci'? */
3188e3e3a7aSWarner Losh     return NULL;  /* no info */
3198e3e3a7aSWarner Losh   else if (ci->callstatus & CIST_FIN) {  /* is this a finalizer? */
3208e3e3a7aSWarner Losh     *name = "__gc";
3218e3e3a7aSWarner Losh     return "metamethod";  /* report it as such */
3228e3e3a7aSWarner Losh   }
3238e3e3a7aSWarner Losh   /* calling function is a known Lua function? */
3248e3e3a7aSWarner Losh   else if (!(ci->callstatus & CIST_TAIL) && isLua(ci->previous))
3258e3e3a7aSWarner Losh     return funcnamefromcode(L, ci->previous, name);
3268e3e3a7aSWarner Losh   else return NULL;  /* no way to find a name */
3278e3e3a7aSWarner Losh }
3288e3e3a7aSWarner Losh 
3298e3e3a7aSWarner Losh 
3308e3e3a7aSWarner Losh static int auxgetinfo (lua_State *L, const char *what, lua_Debug *ar,
3318e3e3a7aSWarner Losh                        Closure *f, CallInfo *ci) {
3328e3e3a7aSWarner Losh   int status = 1;
3338e3e3a7aSWarner Losh   for (; *what; what++) {
3348e3e3a7aSWarner Losh     switch (*what) {
3358e3e3a7aSWarner Losh       case 'S': {
3368e3e3a7aSWarner Losh         funcinfo(ar, f);
3378e3e3a7aSWarner Losh         break;
3388e3e3a7aSWarner Losh       }
3398e3e3a7aSWarner Losh       case 'l': {
340*0495ed39SKyle Evans         ar->currentline = (ci && isLua(ci)) ? getcurrentline(ci) : -1;
3418e3e3a7aSWarner Losh         break;
3428e3e3a7aSWarner Losh       }
3438e3e3a7aSWarner Losh       case 'u': {
3448e3e3a7aSWarner Losh         ar->nups = (f == NULL) ? 0 : f->c.nupvalues;
3458e3e3a7aSWarner Losh         if (noLuaClosure(f)) {
3468e3e3a7aSWarner Losh           ar->isvararg = 1;
3478e3e3a7aSWarner Losh           ar->nparams = 0;
3488e3e3a7aSWarner Losh         }
3498e3e3a7aSWarner Losh         else {
3508e3e3a7aSWarner Losh           ar->isvararg = f->l.p->is_vararg;
3518e3e3a7aSWarner Losh           ar->nparams = f->l.p->numparams;
3528e3e3a7aSWarner Losh         }
3538e3e3a7aSWarner Losh         break;
3548e3e3a7aSWarner Losh       }
3558e3e3a7aSWarner Losh       case 't': {
3568e3e3a7aSWarner Losh         ar->istailcall = (ci) ? ci->callstatus & CIST_TAIL : 0;
3578e3e3a7aSWarner Losh         break;
3588e3e3a7aSWarner Losh       }
3598e3e3a7aSWarner Losh       case 'n': {
3608e3e3a7aSWarner Losh         ar->namewhat = getfuncname(L, ci, &ar->name);
3618e3e3a7aSWarner Losh         if (ar->namewhat == NULL) {
3628e3e3a7aSWarner Losh           ar->namewhat = "";  /* not found */
3638e3e3a7aSWarner Losh           ar->name = NULL;
3648e3e3a7aSWarner Losh         }
3658e3e3a7aSWarner Losh         break;
3668e3e3a7aSWarner Losh       }
367*0495ed39SKyle Evans       case 'r': {
368*0495ed39SKyle Evans         if (ci == NULL || !(ci->callstatus & CIST_TRAN))
369*0495ed39SKyle Evans           ar->ftransfer = ar->ntransfer = 0;
370*0495ed39SKyle Evans         else {
371*0495ed39SKyle Evans           ar->ftransfer = ci->u2.transferinfo.ftransfer;
372*0495ed39SKyle Evans           ar->ntransfer = ci->u2.transferinfo.ntransfer;
373*0495ed39SKyle Evans         }
374*0495ed39SKyle Evans         break;
375*0495ed39SKyle Evans       }
3768e3e3a7aSWarner Losh       case 'L':
3778e3e3a7aSWarner Losh       case 'f':  /* handled by lua_getinfo */
3788e3e3a7aSWarner Losh         break;
3798e3e3a7aSWarner Losh       default: status = 0;  /* invalid option */
3808e3e3a7aSWarner Losh     }
3818e3e3a7aSWarner Losh   }
3828e3e3a7aSWarner Losh   return status;
3838e3e3a7aSWarner Losh }
3848e3e3a7aSWarner Losh 
3858e3e3a7aSWarner Losh 
3868e3e3a7aSWarner Losh LUA_API int lua_getinfo (lua_State *L, const char *what, lua_Debug *ar) {
3878e3e3a7aSWarner Losh   int status;
3888e3e3a7aSWarner Losh   Closure *cl;
3898e3e3a7aSWarner Losh   CallInfo *ci;
390*0495ed39SKyle Evans   TValue *func;
3918e3e3a7aSWarner Losh   lua_lock(L);
3928e3e3a7aSWarner Losh   if (*what == '>') {
3938e3e3a7aSWarner Losh     ci = NULL;
394*0495ed39SKyle Evans     func = s2v(L->top - 1);
3958e3e3a7aSWarner Losh     api_check(L, ttisfunction(func), "function expected");
3968e3e3a7aSWarner Losh     what++;  /* skip the '>' */
3978e3e3a7aSWarner Losh     L->top--;  /* pop function */
3988e3e3a7aSWarner Losh   }
3998e3e3a7aSWarner Losh   else {
4008e3e3a7aSWarner Losh     ci = ar->i_ci;
401*0495ed39SKyle Evans     func = s2v(ci->func);
402*0495ed39SKyle Evans     lua_assert(ttisfunction(func));
4038e3e3a7aSWarner Losh   }
4048e3e3a7aSWarner Losh   cl = ttisclosure(func) ? clvalue(func) : NULL;
4058e3e3a7aSWarner Losh   status = auxgetinfo(L, what, ar, cl, ci);
4068e3e3a7aSWarner Losh   if (strchr(what, 'f')) {
407*0495ed39SKyle Evans     setobj2s(L, L->top, func);
4088e3e3a7aSWarner Losh     api_incr_top(L);
4098e3e3a7aSWarner Losh   }
4108e3e3a7aSWarner Losh   if (strchr(what, 'L'))
4118e3e3a7aSWarner Losh     collectvalidlines(L, cl);
4128e3e3a7aSWarner Losh   lua_unlock(L);
4138e3e3a7aSWarner Losh   return status;
4148e3e3a7aSWarner Losh }
4158e3e3a7aSWarner Losh 
4168e3e3a7aSWarner Losh 
4178e3e3a7aSWarner Losh /*
4188e3e3a7aSWarner Losh ** {======================================================
4198e3e3a7aSWarner Losh ** Symbolic Execution
4208e3e3a7aSWarner Losh ** =======================================================
4218e3e3a7aSWarner Losh */
4228e3e3a7aSWarner Losh 
423*0495ed39SKyle Evans static const char *getobjname (const Proto *p, int lastpc, int reg,
4248e3e3a7aSWarner Losh                                const char **name);
4258e3e3a7aSWarner Losh 
4268e3e3a7aSWarner Losh 
4278e3e3a7aSWarner Losh /*
428*0495ed39SKyle Evans ** Find a "name" for the constant 'c'.
4298e3e3a7aSWarner Losh */
430*0495ed39SKyle Evans static void kname (const Proto *p, int c, const char **name) {
431*0495ed39SKyle Evans   TValue *kvalue = &p->k[c];
432*0495ed39SKyle Evans   *name = (ttisstring(kvalue)) ? svalue(kvalue) : "?";
4338e3e3a7aSWarner Losh }
434*0495ed39SKyle Evans 
435*0495ed39SKyle Evans 
436*0495ed39SKyle Evans /*
437*0495ed39SKyle Evans ** Find a "name" for the register 'c'.
438*0495ed39SKyle Evans */
439*0495ed39SKyle Evans static void rname (const Proto *p, int pc, int c, const char **name) {
4408e3e3a7aSWarner Losh   const char *what = getobjname(p, pc, c, name); /* search for 'c' */
441*0495ed39SKyle Evans   if (!(what && *what == 'c'))  /* did not find a constant name? */
442*0495ed39SKyle Evans     *name = "?";
4438e3e3a7aSWarner Losh }
444*0495ed39SKyle Evans 
445*0495ed39SKyle Evans 
446*0495ed39SKyle Evans /*
447*0495ed39SKyle Evans ** Find a "name" for a 'C' value in an RK instruction.
448*0495ed39SKyle Evans */
449*0495ed39SKyle Evans static void rkname (const Proto *p, int pc, Instruction i, const char **name) {
450*0495ed39SKyle Evans   int c = GETARG_C(i);  /* key index */
451*0495ed39SKyle Evans   if (GETARG_k(i))  /* is 'c' a constant? */
452*0495ed39SKyle Evans     kname(p, c, name);
453*0495ed39SKyle Evans   else  /* 'c' is a register */
454*0495ed39SKyle Evans     rname(p, pc, c, name);
4558e3e3a7aSWarner Losh }
4568e3e3a7aSWarner Losh 
4578e3e3a7aSWarner Losh 
4588e3e3a7aSWarner Losh static int filterpc (int pc, int jmptarget) {
4598e3e3a7aSWarner Losh   if (pc < jmptarget)  /* is code conditional (inside a jump)? */
4608e3e3a7aSWarner Losh     return -1;  /* cannot know who sets that register */
4618e3e3a7aSWarner Losh   else return pc;  /* current position sets that register */
4628e3e3a7aSWarner Losh }
4638e3e3a7aSWarner Losh 
4648e3e3a7aSWarner Losh 
4658e3e3a7aSWarner Losh /*
466*0495ed39SKyle Evans ** Try to find last instruction before 'lastpc' that modified register 'reg'.
4678e3e3a7aSWarner Losh */
468*0495ed39SKyle Evans static int findsetreg (const Proto *p, int lastpc, int reg) {
4698e3e3a7aSWarner Losh   int pc;
4708e3e3a7aSWarner Losh   int setreg = -1;  /* keep last instruction that changed 'reg' */
4718e3e3a7aSWarner Losh   int jmptarget = 0;  /* any code before this address is conditional */
472*0495ed39SKyle Evans   if (testMMMode(GET_OPCODE(p->code[lastpc])))
473*0495ed39SKyle Evans     lastpc--;  /* previous instruction was not actually executed */
4748e3e3a7aSWarner Losh   for (pc = 0; pc < lastpc; pc++) {
4758e3e3a7aSWarner Losh     Instruction i = p->code[pc];
4768e3e3a7aSWarner Losh     OpCode op = GET_OPCODE(i);
4778e3e3a7aSWarner Losh     int a = GETARG_A(i);
478*0495ed39SKyle Evans     int change;  /* true if current instruction changed 'reg' */
4798e3e3a7aSWarner Losh     switch (op) {
480*0495ed39SKyle Evans       case OP_LOADNIL: {  /* set registers from 'a' to 'a+b' */
4818e3e3a7aSWarner Losh         int b = GETARG_B(i);
482*0495ed39SKyle Evans         change = (a <= reg && reg <= a + b);
4838e3e3a7aSWarner Losh         break;
4848e3e3a7aSWarner Losh       }
485*0495ed39SKyle Evans       case OP_TFORCALL: {  /* affect all regs above its base */
486*0495ed39SKyle Evans         change = (reg >= a + 2);
4878e3e3a7aSWarner Losh         break;
4888e3e3a7aSWarner Losh       }
4898e3e3a7aSWarner Losh       case OP_CALL:
490*0495ed39SKyle Evans       case OP_TAILCALL: {  /* affect all registers above base */
491*0495ed39SKyle Evans         change = (reg >= a);
4928e3e3a7aSWarner Losh         break;
4938e3e3a7aSWarner Losh       }
494*0495ed39SKyle Evans       case OP_JMP: {  /* doesn't change registers, but changes 'jmptarget' */
495*0495ed39SKyle Evans         int b = GETARG_sJ(i);
4968e3e3a7aSWarner Losh         int dest = pc + 1 + b;
497*0495ed39SKyle Evans         /* jump does not skip 'lastpc' and is larger than current one? */
498*0495ed39SKyle Evans         if (dest <= lastpc && dest > jmptarget)
4998e3e3a7aSWarner Losh           jmptarget = dest;  /* update 'jmptarget' */
500*0495ed39SKyle Evans         change = 0;
5018e3e3a7aSWarner Losh         break;
5028e3e3a7aSWarner Losh       }
503*0495ed39SKyle Evans       default:  /* any instruction that sets A */
504*0495ed39SKyle Evans         change = (testAMode(op) && reg == a);
505*0495ed39SKyle Evans         break;
506*0495ed39SKyle Evans     }
507*0495ed39SKyle Evans     if (change)
5088e3e3a7aSWarner Losh       setreg = filterpc(pc, jmptarget);
5098e3e3a7aSWarner Losh   }
5108e3e3a7aSWarner Losh   return setreg;
5118e3e3a7aSWarner Losh }
5128e3e3a7aSWarner Losh 
5138e3e3a7aSWarner Losh 
514*0495ed39SKyle Evans /*
515*0495ed39SKyle Evans ** Check whether table being indexed by instruction 'i' is the
516*0495ed39SKyle Evans ** environment '_ENV'
517*0495ed39SKyle Evans */
518*0495ed39SKyle Evans static const char *gxf (const Proto *p, int pc, Instruction i, int isup) {
519*0495ed39SKyle Evans   int t = GETARG_B(i);  /* table index */
520*0495ed39SKyle Evans   const char *name;  /* name of indexed variable */
521*0495ed39SKyle Evans   if (isup)  /* is an upvalue? */
522*0495ed39SKyle Evans     name = upvalname(p, t);
523*0495ed39SKyle Evans   else
524*0495ed39SKyle Evans     getobjname(p, pc, t, &name);
525*0495ed39SKyle Evans   return (name && strcmp(name, LUA_ENV) == 0) ? "global" : "field";
526*0495ed39SKyle Evans }
527*0495ed39SKyle Evans 
528*0495ed39SKyle Evans 
529*0495ed39SKyle Evans static const char *getobjname (const Proto *p, int lastpc, int reg,
5308e3e3a7aSWarner Losh                                const char **name) {
5318e3e3a7aSWarner Losh   int pc;
5328e3e3a7aSWarner Losh   *name = luaF_getlocalname(p, reg + 1, lastpc);
5338e3e3a7aSWarner Losh   if (*name)  /* is a local? */
5348e3e3a7aSWarner Losh     return "local";
5358e3e3a7aSWarner Losh   /* else try symbolic execution */
5368e3e3a7aSWarner Losh   pc = findsetreg(p, lastpc, reg);
5378e3e3a7aSWarner Losh   if (pc != -1) {  /* could find instruction? */
5388e3e3a7aSWarner Losh     Instruction i = p->code[pc];
5398e3e3a7aSWarner Losh     OpCode op = GET_OPCODE(i);
5408e3e3a7aSWarner Losh     switch (op) {
5418e3e3a7aSWarner Losh       case OP_MOVE: {
5428e3e3a7aSWarner Losh         int b = GETARG_B(i);  /* move from 'b' to 'a' */
5438e3e3a7aSWarner Losh         if (b < GETARG_A(i))
5448e3e3a7aSWarner Losh           return getobjname(p, pc, b, name);  /* get name for 'b' */
5458e3e3a7aSWarner Losh         break;
5468e3e3a7aSWarner Losh       }
547*0495ed39SKyle Evans       case OP_GETTABUP: {
548*0495ed39SKyle Evans         int k = GETARG_C(i);  /* key index */
549*0495ed39SKyle Evans         kname(p, k, name);
550*0495ed39SKyle Evans         return gxf(p, pc, i, 1);
551*0495ed39SKyle Evans       }
5528e3e3a7aSWarner Losh       case OP_GETTABLE: {
5538e3e3a7aSWarner Losh         int k = GETARG_C(i);  /* key index */
554*0495ed39SKyle Evans         rname(p, pc, k, name);
555*0495ed39SKyle Evans         return gxf(p, pc, i, 0);
556*0495ed39SKyle Evans       }
557*0495ed39SKyle Evans       case OP_GETI: {
558*0495ed39SKyle Evans         *name = "integer index";
559*0495ed39SKyle Evans         return "field";
560*0495ed39SKyle Evans       }
561*0495ed39SKyle Evans       case OP_GETFIELD: {
562*0495ed39SKyle Evans         int k = GETARG_C(i);  /* key index */
563*0495ed39SKyle Evans         kname(p, k, name);
564*0495ed39SKyle Evans         return gxf(p, pc, i, 0);
5658e3e3a7aSWarner Losh       }
5668e3e3a7aSWarner Losh       case OP_GETUPVAL: {
5678e3e3a7aSWarner Losh         *name = upvalname(p, GETARG_B(i));
5688e3e3a7aSWarner Losh         return "upvalue";
5698e3e3a7aSWarner Losh       }
5708e3e3a7aSWarner Losh       case OP_LOADK:
5718e3e3a7aSWarner Losh       case OP_LOADKX: {
5728e3e3a7aSWarner Losh         int b = (op == OP_LOADK) ? GETARG_Bx(i)
5738e3e3a7aSWarner Losh                                  : GETARG_Ax(p->code[pc + 1]);
5748e3e3a7aSWarner Losh         if (ttisstring(&p->k[b])) {
5758e3e3a7aSWarner Losh           *name = svalue(&p->k[b]);
5768e3e3a7aSWarner Losh           return "constant";
5778e3e3a7aSWarner Losh         }
5788e3e3a7aSWarner Losh         break;
5798e3e3a7aSWarner Losh       }
5808e3e3a7aSWarner Losh       case OP_SELF: {
581*0495ed39SKyle Evans         rkname(p, pc, i, name);
5828e3e3a7aSWarner Losh         return "method";
5838e3e3a7aSWarner Losh       }
5848e3e3a7aSWarner Losh       default: break;  /* go through to return NULL */
5858e3e3a7aSWarner Losh     }
5868e3e3a7aSWarner Losh   }
5878e3e3a7aSWarner Losh   return NULL;  /* could not find reasonable name */
5888e3e3a7aSWarner Losh }
5898e3e3a7aSWarner Losh 
5908e3e3a7aSWarner Losh 
5918e3e3a7aSWarner Losh /*
5928e3e3a7aSWarner Losh ** Try to find a name for a function based on the code that called it.
5938e3e3a7aSWarner Losh ** (Only works when function was called by a Lua function.)
5948e3e3a7aSWarner Losh ** Returns what the name is (e.g., "for iterator", "method",
5958e3e3a7aSWarner Losh ** "metamethod") and sets '*name' to point to the name.
5968e3e3a7aSWarner Losh */
5978e3e3a7aSWarner Losh static const char *funcnamefromcode (lua_State *L, CallInfo *ci,
5988e3e3a7aSWarner Losh                                      const char **name) {
5998e3e3a7aSWarner Losh   TMS tm = (TMS)0;  /* (initial value avoids warnings) */
600*0495ed39SKyle Evans   const Proto *p = ci_func(ci)->p;  /* calling function */
6018e3e3a7aSWarner Losh   int pc = currentpc(ci);  /* calling instruction index */
6028e3e3a7aSWarner Losh   Instruction i = p->code[pc];  /* calling instruction */
6038e3e3a7aSWarner Losh   if (ci->callstatus & CIST_HOOKED) {  /* was it called inside a hook? */
6048e3e3a7aSWarner Losh     *name = "?";
6058e3e3a7aSWarner Losh     return "hook";
6068e3e3a7aSWarner Losh   }
6078e3e3a7aSWarner Losh   switch (GET_OPCODE(i)) {
6088e3e3a7aSWarner Losh     case OP_CALL:
6098e3e3a7aSWarner Losh     case OP_TAILCALL:
6108e3e3a7aSWarner Losh       return getobjname(p, pc, GETARG_A(i), name);  /* get function name */
6118e3e3a7aSWarner Losh     case OP_TFORCALL: {  /* for iterator */
6128e3e3a7aSWarner Losh       *name = "for iterator";
6138e3e3a7aSWarner Losh        return "for iterator";
6148e3e3a7aSWarner Losh     }
6158e3e3a7aSWarner Losh     /* other instructions can do calls through metamethods */
6168e3e3a7aSWarner Losh     case OP_SELF: case OP_GETTABUP: case OP_GETTABLE:
617*0495ed39SKyle Evans     case OP_GETI: case OP_GETFIELD:
6188e3e3a7aSWarner Losh       tm = TM_INDEX;
6198e3e3a7aSWarner Losh       break;
620*0495ed39SKyle Evans     case OP_SETTABUP: case OP_SETTABLE: case OP_SETI: case OP_SETFIELD:
6218e3e3a7aSWarner Losh       tm = TM_NEWINDEX;
6228e3e3a7aSWarner Losh       break;
623*0495ed39SKyle Evans     case OP_MMBIN: case OP_MMBINI: case OP_MMBINK: {
624*0495ed39SKyle Evans       tm = cast(TMS, GETARG_C(i));
6258e3e3a7aSWarner Losh       break;
6268e3e3a7aSWarner Losh     }
6278e3e3a7aSWarner Losh     case OP_UNM: tm = TM_UNM; break;
6288e3e3a7aSWarner Losh     case OP_BNOT: tm = TM_BNOT; break;
6298e3e3a7aSWarner Losh     case OP_LEN: tm = TM_LEN; break;
6308e3e3a7aSWarner Losh     case OP_CONCAT: tm = TM_CONCAT; break;
6318e3e3a7aSWarner Losh     case OP_EQ: tm = TM_EQ; break;
632*0495ed39SKyle Evans     case OP_LT: case OP_LE: case OP_LTI: case OP_LEI:
633*0495ed39SKyle Evans       *name = "order";  /* '<=' can call '__lt', etc. */
634*0495ed39SKyle Evans       return "metamethod";
635*0495ed39SKyle Evans     case OP_CLOSE: case OP_RETURN:
636*0495ed39SKyle Evans       *name = "close";
637*0495ed39SKyle Evans       return "metamethod";
6388e3e3a7aSWarner Losh     default:
6398e3e3a7aSWarner Losh       return NULL;  /* cannot find a reasonable name */
6408e3e3a7aSWarner Losh   }
641*0495ed39SKyle Evans   *name = getstr(G(L)->tmname[tm]) + 2;
6428e3e3a7aSWarner Losh   return "metamethod";
6438e3e3a7aSWarner Losh }
6448e3e3a7aSWarner Losh 
6458e3e3a7aSWarner Losh /* }====================================================== */
6468e3e3a7aSWarner Losh 
6478e3e3a7aSWarner Losh 
6488e3e3a7aSWarner Losh 
6498e3e3a7aSWarner Losh /*
6508e3e3a7aSWarner Losh ** The subtraction of two potentially unrelated pointers is
6518e3e3a7aSWarner Losh ** not ISO C, but it should not crash a program; the subsequent
6528e3e3a7aSWarner Losh ** checks are ISO C and ensure a correct result.
6538e3e3a7aSWarner Losh */
6548e3e3a7aSWarner Losh static int isinstack (CallInfo *ci, const TValue *o) {
655*0495ed39SKyle Evans   StkId base = ci->func + 1;
656*0495ed39SKyle Evans   ptrdiff_t i = cast(StkId, o) - base;
657*0495ed39SKyle Evans   return (0 <= i && i < (ci->top - base) && s2v(base + i) == o);
6588e3e3a7aSWarner Losh }
6598e3e3a7aSWarner Losh 
6608e3e3a7aSWarner Losh 
6618e3e3a7aSWarner Losh /*
6628e3e3a7aSWarner Losh ** Checks whether value 'o' came from an upvalue. (That can only happen
6638e3e3a7aSWarner Losh ** with instructions OP_GETTABUP/OP_SETTABUP, which operate directly on
6648e3e3a7aSWarner Losh ** upvalues.)
6658e3e3a7aSWarner Losh */
6668e3e3a7aSWarner Losh static const char *getupvalname (CallInfo *ci, const TValue *o,
6678e3e3a7aSWarner Losh                                  const char **name) {
6688e3e3a7aSWarner Losh   LClosure *c = ci_func(ci);
6698e3e3a7aSWarner Losh   int i;
6708e3e3a7aSWarner Losh   for (i = 0; i < c->nupvalues; i++) {
6718e3e3a7aSWarner Losh     if (c->upvals[i]->v == o) {
6728e3e3a7aSWarner Losh       *name = upvalname(c->p, i);
6738e3e3a7aSWarner Losh       return "upvalue";
6748e3e3a7aSWarner Losh     }
6758e3e3a7aSWarner Losh   }
6768e3e3a7aSWarner Losh   return NULL;
6778e3e3a7aSWarner Losh }
6788e3e3a7aSWarner Losh 
6798e3e3a7aSWarner Losh 
6808e3e3a7aSWarner Losh static const char *varinfo (lua_State *L, const TValue *o) {
6818e3e3a7aSWarner Losh   const char *name = NULL;  /* to avoid warnings */
6828e3e3a7aSWarner Losh   CallInfo *ci = L->ci;
6838e3e3a7aSWarner Losh   const char *kind = NULL;
6848e3e3a7aSWarner Losh   if (isLua(ci)) {
6858e3e3a7aSWarner Losh     kind = getupvalname(ci, o, &name);  /* check whether 'o' is an upvalue */
6868e3e3a7aSWarner Losh     if (!kind && isinstack(ci, o))  /* no? try a register */
6878e3e3a7aSWarner Losh       kind = getobjname(ci_func(ci)->p, currentpc(ci),
688*0495ed39SKyle Evans                         cast_int(cast(StkId, o) - (ci->func + 1)), &name);
6898e3e3a7aSWarner Losh   }
6908e3e3a7aSWarner Losh   return (kind) ? luaO_pushfstring(L, " (%s '%s')", kind, name) : "";
6918e3e3a7aSWarner Losh }
6928e3e3a7aSWarner Losh 
6938e3e3a7aSWarner Losh 
6948e3e3a7aSWarner Losh l_noret luaG_typeerror (lua_State *L, const TValue *o, const char *op) {
6958e3e3a7aSWarner Losh   const char *t = luaT_objtypename(L, o);
6968e3e3a7aSWarner Losh   luaG_runerror(L, "attempt to %s a %s value%s", op, t, varinfo(L, o));
6978e3e3a7aSWarner Losh }
6988e3e3a7aSWarner Losh 
6998e3e3a7aSWarner Losh 
700*0495ed39SKyle Evans l_noret luaG_forerror (lua_State *L, const TValue *o, const char *what) {
701*0495ed39SKyle Evans   luaG_runerror(L, "bad 'for' %s (number expected, got %s)",
702*0495ed39SKyle Evans                    what, luaT_objtypename(L, o));
703*0495ed39SKyle Evans }
704*0495ed39SKyle Evans 
705*0495ed39SKyle Evans 
7068e3e3a7aSWarner Losh l_noret luaG_concaterror (lua_State *L, const TValue *p1, const TValue *p2) {
7078e3e3a7aSWarner Losh   if (ttisstring(p1) || cvt2str(p1)) p1 = p2;
7088e3e3a7aSWarner Losh   luaG_typeerror(L, p1, "concatenate");
7098e3e3a7aSWarner Losh }
7108e3e3a7aSWarner Losh 
7118e3e3a7aSWarner Losh 
7128e3e3a7aSWarner Losh l_noret luaG_opinterror (lua_State *L, const TValue *p1,
7138e3e3a7aSWarner Losh                          const TValue *p2, const char *msg) {
714*0495ed39SKyle Evans   if (!ttisnumber(p1))  /* first operand is wrong? */
7158e3e3a7aSWarner Losh     p2 = p1;  /* now second is wrong */
7168e3e3a7aSWarner Losh   luaG_typeerror(L, p2, msg);
7178e3e3a7aSWarner Losh }
7188e3e3a7aSWarner Losh 
7198e3e3a7aSWarner Losh 
7208e3e3a7aSWarner Losh /*
7218e3e3a7aSWarner Losh ** Error when both values are convertible to numbers, but not to integers
7228e3e3a7aSWarner Losh */
7238e3e3a7aSWarner Losh l_noret luaG_tointerror (lua_State *L, const TValue *p1, const TValue *p2) {
7248e3e3a7aSWarner Losh   lua_Integer temp;
725*0495ed39SKyle Evans   if (!tointegerns(p1, &temp))
7268e3e3a7aSWarner Losh     p2 = p1;
7278e3e3a7aSWarner Losh   luaG_runerror(L, "number%s has no integer representation", varinfo(L, p2));
7288e3e3a7aSWarner Losh }
7298e3e3a7aSWarner Losh 
7308e3e3a7aSWarner Losh 
7318e3e3a7aSWarner Losh l_noret luaG_ordererror (lua_State *L, const TValue *p1, const TValue *p2) {
7328e3e3a7aSWarner Losh   const char *t1 = luaT_objtypename(L, p1);
7338e3e3a7aSWarner Losh   const char *t2 = luaT_objtypename(L, p2);
7348e3e3a7aSWarner Losh   if (strcmp(t1, t2) == 0)
7358e3e3a7aSWarner Losh     luaG_runerror(L, "attempt to compare two %s values", t1);
7368e3e3a7aSWarner Losh   else
7378e3e3a7aSWarner Losh     luaG_runerror(L, "attempt to compare %s with %s", t1, t2);
7388e3e3a7aSWarner Losh }
7398e3e3a7aSWarner Losh 
7408e3e3a7aSWarner Losh 
7418e3e3a7aSWarner Losh /* add src:line information to 'msg' */
7428e3e3a7aSWarner Losh const char *luaG_addinfo (lua_State *L, const char *msg, TString *src,
7438e3e3a7aSWarner Losh                                         int line) {
7448e3e3a7aSWarner Losh   char buff[LUA_IDSIZE];
7458e3e3a7aSWarner Losh   if (src)
746*0495ed39SKyle Evans     luaO_chunkid(buff, getstr(src), tsslen(src));
7478e3e3a7aSWarner Losh   else {  /* no source available; use "?" instead */
7488e3e3a7aSWarner Losh     buff[0] = '?'; buff[1] = '\0';
7498e3e3a7aSWarner Losh   }
7508e3e3a7aSWarner Losh   return luaO_pushfstring(L, "%s:%d: %s", buff, line, msg);
7518e3e3a7aSWarner Losh }
7528e3e3a7aSWarner Losh 
7538e3e3a7aSWarner Losh 
7548e3e3a7aSWarner Losh l_noret luaG_errormsg (lua_State *L) {
7558e3e3a7aSWarner Losh   if (L->errfunc != 0) {  /* is there an error handling function? */
7568e3e3a7aSWarner Losh     StkId errfunc = restorestack(L, L->errfunc);
757*0495ed39SKyle Evans     lua_assert(ttisfunction(s2v(errfunc)));
7588e3e3a7aSWarner Losh     setobjs2s(L, L->top, L->top - 1);  /* move argument */
7598e3e3a7aSWarner Losh     setobjs2s(L, L->top - 1, errfunc);  /* push function */
7608e3e3a7aSWarner Losh     L->top++;  /* assume EXTRA_STACK */
7618e3e3a7aSWarner Losh     luaD_callnoyield(L, L->top - 2, 1);  /* call it */
7628e3e3a7aSWarner Losh   }
7638e3e3a7aSWarner Losh   luaD_throw(L, LUA_ERRRUN);
7648e3e3a7aSWarner Losh }
7658e3e3a7aSWarner Losh 
7668e3e3a7aSWarner Losh 
7678e3e3a7aSWarner Losh l_noret luaG_runerror (lua_State *L, const char *fmt, ...) {
7688e3e3a7aSWarner Losh   CallInfo *ci = L->ci;
7698e3e3a7aSWarner Losh   const char *msg;
7708e3e3a7aSWarner Losh   va_list argp;
771e112e9d2SKyle Evans   luaC_checkGC(L);  /* error message uses memory */
7728e3e3a7aSWarner Losh   va_start(argp, fmt);
7738e3e3a7aSWarner Losh   msg = luaO_pushvfstring(L, fmt, argp);  /* format message */
7748e3e3a7aSWarner Losh   va_end(argp);
7758e3e3a7aSWarner Losh   if (isLua(ci))  /* if Lua function, add source:line information */
776*0495ed39SKyle Evans     luaG_addinfo(L, msg, ci_func(ci)->p->source, getcurrentline(ci));
7778e3e3a7aSWarner Losh   luaG_errormsg(L);
7788e3e3a7aSWarner Losh }
7798e3e3a7aSWarner Losh 
7808e3e3a7aSWarner Losh 
781*0495ed39SKyle Evans /*
782*0495ed39SKyle Evans ** Check whether new instruction 'newpc' is in a different line from
783*0495ed39SKyle Evans ** previous instruction 'oldpc'.
784*0495ed39SKyle Evans */
785*0495ed39SKyle Evans static int changedline (const Proto *p, int oldpc, int newpc) {
786*0495ed39SKyle Evans   if (p->lineinfo == NULL)  /* no debug information? */
787*0495ed39SKyle Evans     return 0;
788*0495ed39SKyle Evans   while (oldpc++ < newpc) {
789*0495ed39SKyle Evans     if (p->lineinfo[oldpc] != 0)
790*0495ed39SKyle Evans       return (luaG_getfuncline(p, oldpc - 1) != luaG_getfuncline(p, newpc));
791*0495ed39SKyle Evans   }
792*0495ed39SKyle Evans   return 0;  /* no line changes between positions */
793*0495ed39SKyle Evans }
794*0495ed39SKyle Evans 
795*0495ed39SKyle Evans 
796*0495ed39SKyle Evans /*
797*0495ed39SKyle Evans ** Traces the execution of a Lua function. Called before the execution
798*0495ed39SKyle Evans ** of each opcode, when debug is on. 'L->oldpc' stores the last
799*0495ed39SKyle Evans ** instruction traced, to detect line changes. When entering a new
800*0495ed39SKyle Evans ** function, 'npci' will be zero and will test as a new line without
801*0495ed39SKyle Evans ** the need for 'oldpc'; so, 'oldpc' does not need to be initialized
802*0495ed39SKyle Evans ** before. Some exceptional conditions may return to a function without
803*0495ed39SKyle Evans ** updating 'oldpc'. In that case, 'oldpc' may be invalid; if so, it is
804*0495ed39SKyle Evans ** reset to zero.  (A wrong but valid 'oldpc' at most causes an extra
805*0495ed39SKyle Evans ** call to a line hook.)
806*0495ed39SKyle Evans */
807*0495ed39SKyle Evans int luaG_traceexec (lua_State *L, const Instruction *pc) {
8088e3e3a7aSWarner Losh   CallInfo *ci = L->ci;
8098e3e3a7aSWarner Losh   lu_byte mask = L->hookmask;
810*0495ed39SKyle Evans   const Proto *p = ci_func(ci)->p;
811*0495ed39SKyle Evans   int counthook;
812*0495ed39SKyle Evans   /* 'L->oldpc' may be invalid; reset it in this case */
813*0495ed39SKyle Evans   int oldpc = (L->oldpc < p->sizecode) ? L->oldpc : 0;
814*0495ed39SKyle Evans   if (!(mask & (LUA_MASKLINE | LUA_MASKCOUNT))) {  /* no hooks? */
815*0495ed39SKyle Evans     ci->u.l.trap = 0;  /* don't need to stop again */
816*0495ed39SKyle Evans     return 0;  /* turn off 'trap' */
817*0495ed39SKyle Evans   }
818*0495ed39SKyle Evans   pc++;  /* reference is always next instruction */
819*0495ed39SKyle Evans   ci->u.l.savedpc = pc;  /* save 'pc' */
820*0495ed39SKyle Evans   counthook = (--L->hookcount == 0 && (mask & LUA_MASKCOUNT));
8218e3e3a7aSWarner Losh   if (counthook)
8228e3e3a7aSWarner Losh     resethookcount(L);  /* reset count */
8238e3e3a7aSWarner Losh   else if (!(mask & LUA_MASKLINE))
824*0495ed39SKyle Evans     return 1;  /* no line hook and count != 0; nothing to be done now */
8258e3e3a7aSWarner Losh   if (ci->callstatus & CIST_HOOKYIELD) {  /* called hook last time? */
8268e3e3a7aSWarner Losh     ci->callstatus &= ~CIST_HOOKYIELD;  /* erase mark */
827*0495ed39SKyle Evans     return 1;  /* do not call hook again (VM yielded, so it did not move) */
8288e3e3a7aSWarner Losh   }
829*0495ed39SKyle Evans   if (!isIT(*(ci->u.l.savedpc - 1)))
830*0495ed39SKyle Evans     L->top = ci->top;  /* prepare top */
8318e3e3a7aSWarner Losh   if (counthook)
832*0495ed39SKyle Evans     luaD_hook(L, LUA_HOOKCOUNT, -1, 0, 0);  /* call count hook */
8338e3e3a7aSWarner Losh   if (mask & LUA_MASKLINE) {
834*0495ed39SKyle Evans     int npci = pcRel(pc, p);
835*0495ed39SKyle Evans     if (npci == 0 ||  /* call linehook when enter a new function, */
836*0495ed39SKyle Evans         pc <= invpcRel(oldpc, p) ||  /* when jump back (loop), or when */
837*0495ed39SKyle Evans         changedline(p, oldpc, npci)) {  /* enter new line */
838*0495ed39SKyle Evans       int newline = luaG_getfuncline(p, npci);
839*0495ed39SKyle Evans       luaD_hook(L, LUA_HOOKLINE, newline, 0, 0);  /* call line hook */
8408e3e3a7aSWarner Losh     }
841*0495ed39SKyle Evans     L->oldpc = npci;  /* 'pc' of last call to line hook */
842*0495ed39SKyle Evans   }
8438e3e3a7aSWarner Losh   if (L->status == LUA_YIELD) {  /* did hook yield? */
8448e3e3a7aSWarner Losh     if (counthook)
8458e3e3a7aSWarner Losh       L->hookcount = 1;  /* undo decrement to zero */
8468e3e3a7aSWarner Losh     ci->u.l.savedpc--;  /* undo increment (resume will increment it again) */
8478e3e3a7aSWarner Losh     ci->callstatus |= CIST_HOOKYIELD;  /* mark that it yielded */
8488e3e3a7aSWarner Losh     luaD_throw(L, LUA_YIELD);
8498e3e3a7aSWarner Losh   }
850*0495ed39SKyle Evans   return 1;  /* keep 'trap' on */
8518e3e3a7aSWarner Losh }
8528e3e3a7aSWarner Losh 
853