xref: /freebsd/contrib/lua/src/ldebug.c (revision a9490b81b032b43cdb3c8c76b4d01bbad9ff82c1)
18e3e3a7aSWarner Losh /*
20495ed39SKyle 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 
340495ed39SKyle Evans #define noLuaClosure(f)		((f) == NULL || (f)->c.tt == LUA_VCCL)
358e3e3a7aSWarner Losh 
368e3e3a7aSWarner Losh 
378c784bb8SWarner Losh static const char *funcnamefromcall (lua_State *L, CallInfo *ci,
388e3e3a7aSWarner Losh                                                    const char **name);
398e3e3a7aSWarner Losh 
408e3e3a7aSWarner Losh 
currentpc(CallInfo * ci)418e3e3a7aSWarner Losh static int currentpc (CallInfo *ci) {
428e3e3a7aSWarner Losh   lua_assert(isLua(ci));
438e3e3a7aSWarner Losh   return pcRel(ci->u.l.savedpc, ci_func(ci)->p);
448e3e3a7aSWarner Losh }
458e3e3a7aSWarner Losh 
468e3e3a7aSWarner Losh 
478e3e3a7aSWarner Losh /*
480495ed39SKyle Evans ** Get a "base line" to find the line corresponding to an instruction.
498c784bb8SWarner Losh ** Base lines are regularly placed at MAXIWTHABS intervals, so usually
508c784bb8SWarner Losh ** an integer division gets the right place. When the source file has
518c784bb8SWarner Losh ** large sequences of empty/comment lines, it may need extra entries,
528c784bb8SWarner Losh ** so the original estimate needs a correction.
538c784bb8SWarner Losh ** If the original estimate is -1, the initial 'if' ensures that the
548c784bb8SWarner Losh ** 'while' will run at least once.
558c784bb8SWarner Losh ** The assertion that the estimate is a lower bound for the correct base
568c784bb8SWarner Losh ** is valid as long as the debug info has been generated with the same
578c784bb8SWarner Losh ** value for MAXIWTHABS or smaller. (Previous releases use a little
588c784bb8SWarner Losh ** smaller value.)
598e3e3a7aSWarner Losh */
getbaseline(const Proto * f,int pc,int * basepc)600495ed39SKyle Evans static int getbaseline (const Proto *f, int pc, int *basepc) {
610495ed39SKyle Evans   if (f->sizeabslineinfo == 0 || pc < f->abslineinfo[0].pc) {
620495ed39SKyle Evans     *basepc = -1;  /* start from the beginning */
630495ed39SKyle Evans     return f->linedefined;
640495ed39SKyle Evans   }
650495ed39SKyle Evans   else {
668c784bb8SWarner Losh     int i = cast_uint(pc) / MAXIWTHABS - 1;  /* get an estimate */
678c784bb8SWarner Losh     /* estimate must be a lower bound of the correct base */
688c784bb8SWarner Losh     lua_assert(i < 0 ||
698c784bb8SWarner Losh               (i < f->sizeabslineinfo && f->abslineinfo[i].pc <= pc));
708c784bb8SWarner Losh     while (i + 1 < f->sizeabslineinfo && pc >= f->abslineinfo[i + 1].pc)
718c784bb8SWarner Losh       i++;  /* low estimate; adjust it */
720495ed39SKyle Evans     *basepc = f->abslineinfo[i].pc;
730495ed39SKyle Evans     return f->abslineinfo[i].line;
748e3e3a7aSWarner Losh   }
758e3e3a7aSWarner Losh }
768e3e3a7aSWarner Losh 
778e3e3a7aSWarner Losh 
788e3e3a7aSWarner Losh /*
790495ed39SKyle Evans ** Get the line corresponding to instruction 'pc' in function 'f';
800495ed39SKyle Evans ** first gets a base line and from there does the increments until
810495ed39SKyle Evans ** the desired instruction.
820495ed39SKyle Evans */
luaG_getfuncline(const Proto * f,int pc)830495ed39SKyle Evans int luaG_getfuncline (const Proto *f, int pc) {
840495ed39SKyle Evans   if (f->lineinfo == NULL)  /* no debug information? */
850495ed39SKyle Evans     return -1;
860495ed39SKyle Evans   else {
870495ed39SKyle Evans     int basepc;
880495ed39SKyle Evans     int baseline = getbaseline(f, pc, &basepc);
890495ed39SKyle Evans     while (basepc++ < pc) {  /* walk until given instruction */
900495ed39SKyle Evans       lua_assert(f->lineinfo[basepc] != ABSLINEINFO);
910495ed39SKyle Evans       baseline += f->lineinfo[basepc];  /* correct line */
920495ed39SKyle Evans     }
930495ed39SKyle Evans     return baseline;
940495ed39SKyle Evans   }
950495ed39SKyle Evans }
960495ed39SKyle Evans 
970495ed39SKyle Evans 
getcurrentline(CallInfo * ci)980495ed39SKyle Evans static int getcurrentline (CallInfo *ci) {
990495ed39SKyle Evans   return luaG_getfuncline(ci_func(ci)->p, currentpc(ci));
1000495ed39SKyle Evans }
1010495ed39SKyle Evans 
1020495ed39SKyle Evans 
1030495ed39SKyle Evans /*
1040495ed39SKyle Evans ** Set 'trap' for all active Lua frames.
1050495ed39SKyle Evans ** This function can be called during a signal, under "reasonable"
1060495ed39SKyle Evans ** assumptions. A new 'ci' is completely linked in the list before it
1070495ed39SKyle Evans ** becomes part of the "active" list, and we assume that pointers are
1080495ed39SKyle Evans ** atomic; see comment in next function.
1090495ed39SKyle Evans ** (A compiler doing interprocedural optimizations could, theoretically,
1100495ed39SKyle Evans ** reorder memory writes in such a way that the list could be
1110495ed39SKyle Evans ** temporarily broken while inserting a new element. We simply assume it
1120495ed39SKyle Evans ** has no good reasons to do that.)
1130495ed39SKyle Evans */
settraps(CallInfo * ci)1140495ed39SKyle Evans static void settraps (CallInfo *ci) {
1150495ed39SKyle Evans   for (; ci != NULL; ci = ci->previous)
1160495ed39SKyle Evans     if (isLua(ci))
1170495ed39SKyle Evans       ci->u.l.trap = 1;
1180495ed39SKyle Evans }
1190495ed39SKyle Evans 
1200495ed39SKyle Evans 
1210495ed39SKyle Evans /*
1220495ed39SKyle Evans ** This function can be called during a signal, under "reasonable"
1230495ed39SKyle Evans ** assumptions.
1240495ed39SKyle Evans ** Fields 'basehookcount' and 'hookcount' (set by 'resethookcount')
1250495ed39SKyle Evans ** are for debug only, and it is no problem if they get arbitrary
1260495ed39SKyle Evans ** values (causes at most one wrong hook call). 'hookmask' is an atomic
1270495ed39SKyle Evans ** value. We assume that pointers are atomic too (e.g., gcc ensures that
1280495ed39SKyle Evans ** for all platforms where it runs). Moreover, 'hook' is always checked
1290495ed39SKyle Evans ** before being called (see 'luaD_hook').
1308e3e3a7aSWarner Losh */
lua_sethook(lua_State * L,lua_Hook func,int mask,int count)1318e3e3a7aSWarner Losh LUA_API void lua_sethook (lua_State *L, lua_Hook func, int mask, int count) {
1328e3e3a7aSWarner Losh   if (func == NULL || mask == 0) {  /* turn off hooks? */
1338e3e3a7aSWarner Losh     mask = 0;
1348e3e3a7aSWarner Losh     func = NULL;
1358e3e3a7aSWarner Losh   }
1368e3e3a7aSWarner Losh   L->hook = func;
1378e3e3a7aSWarner Losh   L->basehookcount = count;
1388e3e3a7aSWarner Losh   resethookcount(L);
1398e3e3a7aSWarner Losh   L->hookmask = cast_byte(mask);
1400495ed39SKyle Evans   if (mask)
1410495ed39SKyle Evans     settraps(L->ci);  /* to trace inside 'luaV_execute' */
1428e3e3a7aSWarner Losh }
1438e3e3a7aSWarner Losh 
1448e3e3a7aSWarner Losh 
lua_gethook(lua_State * L)1458e3e3a7aSWarner Losh LUA_API lua_Hook lua_gethook (lua_State *L) {
1468e3e3a7aSWarner Losh   return L->hook;
1478e3e3a7aSWarner Losh }
1488e3e3a7aSWarner Losh 
1498e3e3a7aSWarner Losh 
lua_gethookmask(lua_State * L)1508e3e3a7aSWarner Losh LUA_API int lua_gethookmask (lua_State *L) {
1518e3e3a7aSWarner Losh   return L->hookmask;
1528e3e3a7aSWarner Losh }
1538e3e3a7aSWarner Losh 
1548e3e3a7aSWarner Losh 
lua_gethookcount(lua_State * L)1558e3e3a7aSWarner Losh LUA_API int lua_gethookcount (lua_State *L) {
1568e3e3a7aSWarner Losh   return L->basehookcount;
1578e3e3a7aSWarner Losh }
1588e3e3a7aSWarner Losh 
1598e3e3a7aSWarner Losh 
lua_getstack(lua_State * L,int level,lua_Debug * ar)1608e3e3a7aSWarner Losh LUA_API int lua_getstack (lua_State *L, int level, lua_Debug *ar) {
1618e3e3a7aSWarner Losh   int status;
1628e3e3a7aSWarner Losh   CallInfo *ci;
1638e3e3a7aSWarner Losh   if (level < 0) return 0;  /* invalid (negative) level */
1648e3e3a7aSWarner Losh   lua_lock(L);
1658e3e3a7aSWarner Losh   for (ci = L->ci; level > 0 && ci != &L->base_ci; ci = ci->previous)
1668e3e3a7aSWarner Losh     level--;
1678e3e3a7aSWarner Losh   if (level == 0 && ci != &L->base_ci) {  /* level found? */
1688e3e3a7aSWarner Losh     status = 1;
1698e3e3a7aSWarner Losh     ar->i_ci = ci;
1708e3e3a7aSWarner Losh   }
1718e3e3a7aSWarner Losh   else status = 0;  /* no such level */
1728e3e3a7aSWarner Losh   lua_unlock(L);
1738e3e3a7aSWarner Losh   return status;
1748e3e3a7aSWarner Losh }
1758e3e3a7aSWarner Losh 
1768e3e3a7aSWarner Losh 
upvalname(const Proto * p,int uv)1770495ed39SKyle Evans static const char *upvalname (const Proto *p, int uv) {
1788e3e3a7aSWarner Losh   TString *s = check_exp(uv < p->sizeupvalues, p->upvalues[uv].name);
1798e3e3a7aSWarner Losh   if (s == NULL) return "?";
1808e3e3a7aSWarner Losh   else return getstr(s);
1818e3e3a7aSWarner Losh }
1828e3e3a7aSWarner Losh 
1838e3e3a7aSWarner Losh 
findvararg(CallInfo * ci,int n,StkId * pos)1848e3e3a7aSWarner Losh static const char *findvararg (CallInfo *ci, int n, StkId *pos) {
185*a9490b81SWarner Losh   if (clLvalue(s2v(ci->func.p))->p->is_vararg) {
1860495ed39SKyle Evans     int nextra = ci->u.l.nextraargs;
1870495ed39SKyle Evans     if (n >= -nextra) {  /* 'n' is negative */
188*a9490b81SWarner Losh       *pos = ci->func.p - nextra - (n + 1);
1890495ed39SKyle Evans       return "(vararg)";  /* generic name for any vararg */
1900495ed39SKyle Evans     }
1910495ed39SKyle Evans   }
1928e3e3a7aSWarner Losh   return NULL;  /* no such vararg */
1938e3e3a7aSWarner Losh }
1948e3e3a7aSWarner Losh 
1958e3e3a7aSWarner Losh 
luaG_findlocal(lua_State * L,CallInfo * ci,int n,StkId * pos)1960495ed39SKyle Evans const char *luaG_findlocal (lua_State *L, CallInfo *ci, int n, StkId *pos) {
197*a9490b81SWarner Losh   StkId base = ci->func.p + 1;
1988e3e3a7aSWarner Losh   const char *name = NULL;
1998e3e3a7aSWarner Losh   if (isLua(ci)) {
2008e3e3a7aSWarner Losh     if (n < 0)  /* access to vararg values? */
201bf9580a1SKyle Evans       return findvararg(ci, n, pos);
2020495ed39SKyle Evans     else
2038e3e3a7aSWarner Losh       name = luaF_getlocalname(ci_func(ci)->p, n, currentpc(ci));
2048e3e3a7aSWarner Losh   }
2058e3e3a7aSWarner Losh   if (name == NULL) {  /* no 'standard' name? */
206*a9490b81SWarner Losh     StkId limit = (ci == L->ci) ? L->top.p : ci->next->func.p;
2070495ed39SKyle Evans     if (limit - base >= n && n > 0) {  /* is 'n' inside 'ci' stack? */
2080495ed39SKyle Evans       /* generic name for any valid slot */
2090495ed39SKyle Evans       name = isLua(ci) ? "(temporary)" : "(C temporary)";
2100495ed39SKyle Evans     }
2118e3e3a7aSWarner Losh     else
2128e3e3a7aSWarner Losh       return NULL;  /* no name */
2138e3e3a7aSWarner Losh   }
2140495ed39SKyle Evans   if (pos)
2158e3e3a7aSWarner Losh     *pos = base + (n - 1);
2168e3e3a7aSWarner Losh   return name;
2178e3e3a7aSWarner Losh }
2188e3e3a7aSWarner Losh 
2198e3e3a7aSWarner Losh 
lua_getlocal(lua_State * L,const lua_Debug * ar,int n)2208e3e3a7aSWarner Losh LUA_API const char *lua_getlocal (lua_State *L, const lua_Debug *ar, int n) {
2218e3e3a7aSWarner Losh   const char *name;
2228e3e3a7aSWarner Losh   lua_lock(L);
2238e3e3a7aSWarner Losh   if (ar == NULL) {  /* information about non-active function? */
224*a9490b81SWarner Losh     if (!isLfunction(s2v(L->top.p - 1)))  /* not a Lua function? */
2258e3e3a7aSWarner Losh       name = NULL;
2268e3e3a7aSWarner Losh     else  /* consider live variables at function start (parameters) */
227*a9490b81SWarner Losh       name = luaF_getlocalname(clLvalue(s2v(L->top.p - 1))->p, n, 0);
2288e3e3a7aSWarner Losh   }
2298e3e3a7aSWarner Losh   else {  /* active function; get information through 'ar' */
2308e3e3a7aSWarner Losh     StkId pos = NULL;  /* to avoid warnings */
2310495ed39SKyle Evans     name = luaG_findlocal(L, ar->i_ci, n, &pos);
2328e3e3a7aSWarner Losh     if (name) {
233*a9490b81SWarner Losh       setobjs2s(L, L->top.p, pos);
2348e3e3a7aSWarner Losh       api_incr_top(L);
2358e3e3a7aSWarner Losh     }
2368e3e3a7aSWarner Losh   }
2378e3e3a7aSWarner Losh   lua_unlock(L);
2388e3e3a7aSWarner Losh   return name;
2398e3e3a7aSWarner Losh }
2408e3e3a7aSWarner Losh 
2418e3e3a7aSWarner Losh 
lua_setlocal(lua_State * L,const lua_Debug * ar,int n)2428e3e3a7aSWarner Losh LUA_API const char *lua_setlocal (lua_State *L, const lua_Debug *ar, int n) {
2438e3e3a7aSWarner Losh   StkId pos = NULL;  /* to avoid warnings */
2448e3e3a7aSWarner Losh   const char *name;
2458e3e3a7aSWarner Losh   lua_lock(L);
2460495ed39SKyle Evans   name = luaG_findlocal(L, ar->i_ci, n, &pos);
2478e3e3a7aSWarner Losh   if (name) {
248*a9490b81SWarner Losh     setobjs2s(L, pos, L->top.p - 1);
249*a9490b81SWarner Losh     L->top.p--;  /* pop value */
2508e3e3a7aSWarner Losh   }
2518e3e3a7aSWarner Losh   lua_unlock(L);
2528e3e3a7aSWarner Losh   return name;
2538e3e3a7aSWarner Losh }
2548e3e3a7aSWarner Losh 
2558e3e3a7aSWarner Losh 
funcinfo(lua_Debug * ar,Closure * cl)2568e3e3a7aSWarner Losh static void funcinfo (lua_Debug *ar, Closure *cl) {
2578e3e3a7aSWarner Losh   if (noLuaClosure(cl)) {
2588e3e3a7aSWarner Losh     ar->source = "=[C]";
2590495ed39SKyle Evans     ar->srclen = LL("=[C]");
2608e3e3a7aSWarner Losh     ar->linedefined = -1;
2618e3e3a7aSWarner Losh     ar->lastlinedefined = -1;
2628e3e3a7aSWarner Losh     ar->what = "C";
2638e3e3a7aSWarner Losh   }
2648e3e3a7aSWarner Losh   else {
2650495ed39SKyle Evans     const Proto *p = cl->l.p;
2660495ed39SKyle Evans     if (p->source) {
2670495ed39SKyle Evans       ar->source = getstr(p->source);
2680495ed39SKyle Evans       ar->srclen = tsslen(p->source);
2690495ed39SKyle Evans     }
2700495ed39SKyle Evans     else {
2710495ed39SKyle Evans       ar->source = "=?";
2720495ed39SKyle Evans       ar->srclen = LL("=?");
2730495ed39SKyle Evans     }
2748e3e3a7aSWarner Losh     ar->linedefined = p->linedefined;
2758e3e3a7aSWarner Losh     ar->lastlinedefined = p->lastlinedefined;
2768e3e3a7aSWarner Losh     ar->what = (ar->linedefined == 0) ? "main" : "Lua";
2778e3e3a7aSWarner Losh   }
2780495ed39SKyle Evans   luaO_chunkid(ar->short_src, ar->source, ar->srclen);
2790495ed39SKyle Evans }
2800495ed39SKyle Evans 
2810495ed39SKyle Evans 
nextline(const Proto * p,int currentline,int pc)2820495ed39SKyle Evans static int nextline (const Proto *p, int currentline, int pc) {
2830495ed39SKyle Evans   if (p->lineinfo[pc] != ABSLINEINFO)
2840495ed39SKyle Evans     return currentline + p->lineinfo[pc];
2850495ed39SKyle Evans   else
2860495ed39SKyle Evans     return luaG_getfuncline(p, pc);
2878e3e3a7aSWarner Losh }
2888e3e3a7aSWarner Losh 
2898e3e3a7aSWarner Losh 
collectvalidlines(lua_State * L,Closure * f)2908e3e3a7aSWarner Losh static void collectvalidlines (lua_State *L, Closure *f) {
2918e3e3a7aSWarner Losh   if (noLuaClosure(f)) {
292*a9490b81SWarner Losh     setnilvalue(s2v(L->top.p));
2938e3e3a7aSWarner Losh     api_incr_top(L);
2948e3e3a7aSWarner Losh   }
2958e3e3a7aSWarner Losh   else {
2968e3e3a7aSWarner Losh     int i;
2978e3e3a7aSWarner Losh     TValue v;
2980495ed39SKyle Evans     const Proto *p = f->l.p;
2990495ed39SKyle Evans     int currentline = p->linedefined;
3008e3e3a7aSWarner Losh     Table *t = luaH_new(L);  /* new table to store active lines */
301*a9490b81SWarner Losh     sethvalue2s(L, L->top.p, t);  /* push it on stack */
3028e3e3a7aSWarner Losh     api_incr_top(L);
3030495ed39SKyle Evans     setbtvalue(&v);  /* boolean 'true' to be the value of all indices */
3048c784bb8SWarner Losh     if (!p->is_vararg)  /* regular function? */
3058c784bb8SWarner Losh       i = 0;  /* consider all instructions */
3068c784bb8SWarner Losh     else {  /* vararg function */
3078c784bb8SWarner Losh       lua_assert(GET_OPCODE(p->code[0]) == OP_VARARGPREP);
3088c784bb8SWarner Losh       currentline = nextline(p, currentline, 0);
3098c784bb8SWarner Losh       i = 1;  /* skip first instruction (OP_VARARGPREP) */
3108c784bb8SWarner Losh     }
3118c784bb8SWarner Losh     for (; i < p->sizelineinfo; i++) {  /* for each instruction */
3128c784bb8SWarner Losh       currentline = nextline(p, currentline, i);  /* get its line */
3130495ed39SKyle Evans       luaH_setint(L, t, currentline, &v);  /* table[line] = true */
3140495ed39SKyle Evans     }
3158e3e3a7aSWarner Losh   }
3168e3e3a7aSWarner Losh }
3178e3e3a7aSWarner Losh 
3188e3e3a7aSWarner Losh 
getfuncname(lua_State * L,CallInfo * ci,const char ** name)3198e3e3a7aSWarner Losh static const char *getfuncname (lua_State *L, CallInfo *ci, const char **name) {
3208c784bb8SWarner Losh   /* calling function is a known function? */
3218c784bb8SWarner Losh   if (ci != NULL && !(ci->callstatus & CIST_TAIL))
3228c784bb8SWarner Losh     return funcnamefromcall(L, ci->previous, name);
3238e3e3a7aSWarner Losh   else return NULL;  /* no way to find a name */
3248e3e3a7aSWarner Losh }
3258e3e3a7aSWarner Losh 
3268e3e3a7aSWarner Losh 
auxgetinfo(lua_State * L,const char * what,lua_Debug * ar,Closure * f,CallInfo * ci)3278e3e3a7aSWarner Losh static int auxgetinfo (lua_State *L, const char *what, lua_Debug *ar,
3288e3e3a7aSWarner Losh                        Closure *f, CallInfo *ci) {
3298e3e3a7aSWarner Losh   int status = 1;
3308e3e3a7aSWarner Losh   for (; *what; what++) {
3318e3e3a7aSWarner Losh     switch (*what) {
3328e3e3a7aSWarner Losh       case 'S': {
3338e3e3a7aSWarner Losh         funcinfo(ar, f);
3348e3e3a7aSWarner Losh         break;
3358e3e3a7aSWarner Losh       }
3368e3e3a7aSWarner Losh       case 'l': {
3370495ed39SKyle Evans         ar->currentline = (ci && isLua(ci)) ? getcurrentline(ci) : -1;
3388e3e3a7aSWarner Losh         break;
3398e3e3a7aSWarner Losh       }
3408e3e3a7aSWarner Losh       case 'u': {
3418e3e3a7aSWarner Losh         ar->nups = (f == NULL) ? 0 : f->c.nupvalues;
3428e3e3a7aSWarner Losh         if (noLuaClosure(f)) {
3438e3e3a7aSWarner Losh           ar->isvararg = 1;
3448e3e3a7aSWarner Losh           ar->nparams = 0;
3458e3e3a7aSWarner Losh         }
3468e3e3a7aSWarner Losh         else {
3478e3e3a7aSWarner Losh           ar->isvararg = f->l.p->is_vararg;
3488e3e3a7aSWarner Losh           ar->nparams = f->l.p->numparams;
3498e3e3a7aSWarner Losh         }
3508e3e3a7aSWarner Losh         break;
3518e3e3a7aSWarner Losh       }
3528e3e3a7aSWarner Losh       case 't': {
3538e3e3a7aSWarner Losh         ar->istailcall = (ci) ? ci->callstatus & CIST_TAIL : 0;
3548e3e3a7aSWarner Losh         break;
3558e3e3a7aSWarner Losh       }
3568e3e3a7aSWarner Losh       case 'n': {
3578e3e3a7aSWarner Losh         ar->namewhat = getfuncname(L, ci, &ar->name);
3588e3e3a7aSWarner Losh         if (ar->namewhat == NULL) {
3598e3e3a7aSWarner Losh           ar->namewhat = "";  /* not found */
3608e3e3a7aSWarner Losh           ar->name = NULL;
3618e3e3a7aSWarner Losh         }
3628e3e3a7aSWarner Losh         break;
3638e3e3a7aSWarner Losh       }
3640495ed39SKyle Evans       case 'r': {
3650495ed39SKyle Evans         if (ci == NULL || !(ci->callstatus & CIST_TRAN))
3660495ed39SKyle Evans           ar->ftransfer = ar->ntransfer = 0;
3670495ed39SKyle Evans         else {
3680495ed39SKyle Evans           ar->ftransfer = ci->u2.transferinfo.ftransfer;
3690495ed39SKyle Evans           ar->ntransfer = ci->u2.transferinfo.ntransfer;
3700495ed39SKyle Evans         }
3710495ed39SKyle Evans         break;
3720495ed39SKyle Evans       }
3738e3e3a7aSWarner Losh       case 'L':
3748e3e3a7aSWarner Losh       case 'f':  /* handled by lua_getinfo */
3758e3e3a7aSWarner Losh         break;
3768e3e3a7aSWarner Losh       default: status = 0;  /* invalid option */
3778e3e3a7aSWarner Losh     }
3788e3e3a7aSWarner Losh   }
3798e3e3a7aSWarner Losh   return status;
3808e3e3a7aSWarner Losh }
3818e3e3a7aSWarner Losh 
3828e3e3a7aSWarner Losh 
lua_getinfo(lua_State * L,const char * what,lua_Debug * ar)3838e3e3a7aSWarner Losh LUA_API int lua_getinfo (lua_State *L, const char *what, lua_Debug *ar) {
3848e3e3a7aSWarner Losh   int status;
3858e3e3a7aSWarner Losh   Closure *cl;
3868e3e3a7aSWarner Losh   CallInfo *ci;
3870495ed39SKyle Evans   TValue *func;
3888e3e3a7aSWarner Losh   lua_lock(L);
3898e3e3a7aSWarner Losh   if (*what == '>') {
3908e3e3a7aSWarner Losh     ci = NULL;
391*a9490b81SWarner Losh     func = s2v(L->top.p - 1);
3928e3e3a7aSWarner Losh     api_check(L, ttisfunction(func), "function expected");
3938e3e3a7aSWarner Losh     what++;  /* skip the '>' */
394*a9490b81SWarner Losh     L->top.p--;  /* pop function */
3958e3e3a7aSWarner Losh   }
3968e3e3a7aSWarner Losh   else {
3978e3e3a7aSWarner Losh     ci = ar->i_ci;
398*a9490b81SWarner Losh     func = s2v(ci->func.p);
3990495ed39SKyle Evans     lua_assert(ttisfunction(func));
4008e3e3a7aSWarner Losh   }
4018e3e3a7aSWarner Losh   cl = ttisclosure(func) ? clvalue(func) : NULL;
4028e3e3a7aSWarner Losh   status = auxgetinfo(L, what, ar, cl, ci);
4038e3e3a7aSWarner Losh   if (strchr(what, 'f')) {
404*a9490b81SWarner Losh     setobj2s(L, L->top.p, func);
4058e3e3a7aSWarner Losh     api_incr_top(L);
4068e3e3a7aSWarner Losh   }
4078e3e3a7aSWarner Losh   if (strchr(what, 'L'))
4088e3e3a7aSWarner Losh     collectvalidlines(L, cl);
4098e3e3a7aSWarner Losh   lua_unlock(L);
4108e3e3a7aSWarner Losh   return status;
4118e3e3a7aSWarner Losh }
4128e3e3a7aSWarner Losh 
4138e3e3a7aSWarner Losh 
4148e3e3a7aSWarner Losh /*
4158e3e3a7aSWarner Losh ** {======================================================
4168e3e3a7aSWarner Losh ** Symbolic Execution
4178e3e3a7aSWarner Losh ** =======================================================
4188e3e3a7aSWarner Losh */
4198e3e3a7aSWarner Losh 
4200495ed39SKyle Evans static const char *getobjname (const Proto *p, int lastpc, int reg,
4218e3e3a7aSWarner Losh                                const char **name);
4228e3e3a7aSWarner Losh 
4238e3e3a7aSWarner Losh 
4248e3e3a7aSWarner Losh /*
4250495ed39SKyle Evans ** Find a "name" for the constant 'c'.
4268e3e3a7aSWarner Losh */
kname(const Proto * p,int c,const char ** name)4270495ed39SKyle Evans static void kname (const Proto *p, int c, const char **name) {
4280495ed39SKyle Evans   TValue *kvalue = &p->k[c];
4290495ed39SKyle Evans   *name = (ttisstring(kvalue)) ? svalue(kvalue) : "?";
4308e3e3a7aSWarner Losh }
4310495ed39SKyle Evans 
4320495ed39SKyle Evans 
4330495ed39SKyle Evans /*
4340495ed39SKyle Evans ** Find a "name" for the register 'c'.
4350495ed39SKyle Evans */
rname(const Proto * p,int pc,int c,const char ** name)4360495ed39SKyle Evans static void rname (const Proto *p, int pc, int c, const char **name) {
4378e3e3a7aSWarner Losh   const char *what = getobjname(p, pc, c, name); /* search for 'c' */
4380495ed39SKyle Evans   if (!(what && *what == 'c'))  /* did not find a constant name? */
4390495ed39SKyle Evans     *name = "?";
4408e3e3a7aSWarner Losh }
4410495ed39SKyle Evans 
4420495ed39SKyle Evans 
4430495ed39SKyle Evans /*
4440495ed39SKyle Evans ** Find a "name" for a 'C' value in an RK instruction.
4450495ed39SKyle Evans */
rkname(const Proto * p,int pc,Instruction i,const char ** name)4460495ed39SKyle Evans static void rkname (const Proto *p, int pc, Instruction i, const char **name) {
4470495ed39SKyle Evans   int c = GETARG_C(i);  /* key index */
4480495ed39SKyle Evans   if (GETARG_k(i))  /* is 'c' a constant? */
4490495ed39SKyle Evans     kname(p, c, name);
4500495ed39SKyle Evans   else  /* 'c' is a register */
4510495ed39SKyle Evans     rname(p, pc, c, name);
4528e3e3a7aSWarner Losh }
4538e3e3a7aSWarner Losh 
4548e3e3a7aSWarner Losh 
filterpc(int pc,int jmptarget)4558e3e3a7aSWarner Losh static int filterpc (int pc, int jmptarget) {
4568e3e3a7aSWarner Losh   if (pc < jmptarget)  /* is code conditional (inside a jump)? */
4578e3e3a7aSWarner Losh     return -1;  /* cannot know who sets that register */
4588e3e3a7aSWarner Losh   else return pc;  /* current position sets that register */
4598e3e3a7aSWarner Losh }
4608e3e3a7aSWarner Losh 
4618e3e3a7aSWarner Losh 
4628e3e3a7aSWarner Losh /*
4630495ed39SKyle Evans ** Try to find last instruction before 'lastpc' that modified register 'reg'.
4648e3e3a7aSWarner Losh */
findsetreg(const Proto * p,int lastpc,int reg)4650495ed39SKyle Evans static int findsetreg (const Proto *p, int lastpc, int reg) {
4668e3e3a7aSWarner Losh   int pc;
4678e3e3a7aSWarner Losh   int setreg = -1;  /* keep last instruction that changed 'reg' */
4688e3e3a7aSWarner Losh   int jmptarget = 0;  /* any code before this address is conditional */
4690495ed39SKyle Evans   if (testMMMode(GET_OPCODE(p->code[lastpc])))
4700495ed39SKyle Evans     lastpc--;  /* previous instruction was not actually executed */
4718e3e3a7aSWarner Losh   for (pc = 0; pc < lastpc; pc++) {
4728e3e3a7aSWarner Losh     Instruction i = p->code[pc];
4738e3e3a7aSWarner Losh     OpCode op = GET_OPCODE(i);
4748e3e3a7aSWarner Losh     int a = GETARG_A(i);
4750495ed39SKyle Evans     int change;  /* true if current instruction changed 'reg' */
4768e3e3a7aSWarner Losh     switch (op) {
4770495ed39SKyle Evans       case OP_LOADNIL: {  /* set registers from 'a' to 'a+b' */
4788e3e3a7aSWarner Losh         int b = GETARG_B(i);
4790495ed39SKyle Evans         change = (a <= reg && reg <= a + b);
4808e3e3a7aSWarner Losh         break;
4818e3e3a7aSWarner Losh       }
4820495ed39SKyle Evans       case OP_TFORCALL: {  /* affect all regs above its base */
4830495ed39SKyle Evans         change = (reg >= a + 2);
4848e3e3a7aSWarner Losh         break;
4858e3e3a7aSWarner Losh       }
4868e3e3a7aSWarner Losh       case OP_CALL:
4870495ed39SKyle Evans       case OP_TAILCALL: {  /* affect all registers above base */
4880495ed39SKyle Evans         change = (reg >= a);
4898e3e3a7aSWarner Losh         break;
4908e3e3a7aSWarner Losh       }
4910495ed39SKyle Evans       case OP_JMP: {  /* doesn't change registers, but changes 'jmptarget' */
4920495ed39SKyle Evans         int b = GETARG_sJ(i);
4938e3e3a7aSWarner Losh         int dest = pc + 1 + b;
4940495ed39SKyle Evans         /* jump does not skip 'lastpc' and is larger than current one? */
4950495ed39SKyle Evans         if (dest <= lastpc && dest > jmptarget)
4968e3e3a7aSWarner Losh           jmptarget = dest;  /* update 'jmptarget' */
4970495ed39SKyle Evans         change = 0;
4988e3e3a7aSWarner Losh         break;
4998e3e3a7aSWarner Losh       }
5000495ed39SKyle Evans       default:  /* any instruction that sets A */
5010495ed39SKyle Evans         change = (testAMode(op) && reg == a);
5020495ed39SKyle Evans         break;
5030495ed39SKyle Evans     }
5040495ed39SKyle Evans     if (change)
5058e3e3a7aSWarner Losh       setreg = filterpc(pc, jmptarget);
5068e3e3a7aSWarner Losh   }
5078e3e3a7aSWarner Losh   return setreg;
5088e3e3a7aSWarner Losh }
5098e3e3a7aSWarner Losh 
5108e3e3a7aSWarner Losh 
5110495ed39SKyle Evans /*
5120495ed39SKyle Evans ** Check whether table being indexed by instruction 'i' is the
5130495ed39SKyle Evans ** environment '_ENV'
5140495ed39SKyle Evans */
gxf(const Proto * p,int pc,Instruction i,int isup)5150495ed39SKyle Evans static const char *gxf (const Proto *p, int pc, Instruction i, int isup) {
5160495ed39SKyle Evans   int t = GETARG_B(i);  /* table index */
5170495ed39SKyle Evans   const char *name;  /* name of indexed variable */
5180495ed39SKyle Evans   if (isup)  /* is an upvalue? */
5190495ed39SKyle Evans     name = upvalname(p, t);
5200495ed39SKyle Evans   else
5210495ed39SKyle Evans     getobjname(p, pc, t, &name);
5220495ed39SKyle Evans   return (name && strcmp(name, LUA_ENV) == 0) ? "global" : "field";
5230495ed39SKyle Evans }
5240495ed39SKyle Evans 
5250495ed39SKyle Evans 
getobjname(const Proto * p,int lastpc,int reg,const char ** name)5260495ed39SKyle Evans static const char *getobjname (const Proto *p, int lastpc, int reg,
5278e3e3a7aSWarner Losh                                const char **name) {
5288e3e3a7aSWarner Losh   int pc;
5298e3e3a7aSWarner Losh   *name = luaF_getlocalname(p, reg + 1, lastpc);
5308e3e3a7aSWarner Losh   if (*name)  /* is a local? */
5318e3e3a7aSWarner Losh     return "local";
5328e3e3a7aSWarner Losh   /* else try symbolic execution */
5338e3e3a7aSWarner Losh   pc = findsetreg(p, lastpc, reg);
5348e3e3a7aSWarner Losh   if (pc != -1) {  /* could find instruction? */
5358e3e3a7aSWarner Losh     Instruction i = p->code[pc];
5368e3e3a7aSWarner Losh     OpCode op = GET_OPCODE(i);
5378e3e3a7aSWarner Losh     switch (op) {
5388e3e3a7aSWarner Losh       case OP_MOVE: {
5398e3e3a7aSWarner Losh         int b = GETARG_B(i);  /* move from 'b' to 'a' */
5408e3e3a7aSWarner Losh         if (b < GETARG_A(i))
5418e3e3a7aSWarner Losh           return getobjname(p, pc, b, name);  /* get name for 'b' */
5428e3e3a7aSWarner Losh         break;
5438e3e3a7aSWarner Losh       }
5440495ed39SKyle Evans       case OP_GETTABUP: {
5450495ed39SKyle Evans         int k = GETARG_C(i);  /* key index */
5460495ed39SKyle Evans         kname(p, k, name);
5470495ed39SKyle Evans         return gxf(p, pc, i, 1);
5480495ed39SKyle Evans       }
5498e3e3a7aSWarner Losh       case OP_GETTABLE: {
5508e3e3a7aSWarner Losh         int k = GETARG_C(i);  /* key index */
5510495ed39SKyle Evans         rname(p, pc, k, name);
5520495ed39SKyle Evans         return gxf(p, pc, i, 0);
5530495ed39SKyle Evans       }
5540495ed39SKyle Evans       case OP_GETI: {
5550495ed39SKyle Evans         *name = "integer index";
5560495ed39SKyle Evans         return "field";
5570495ed39SKyle Evans       }
5580495ed39SKyle Evans       case OP_GETFIELD: {
5590495ed39SKyle Evans         int k = GETARG_C(i);  /* key index */
5600495ed39SKyle Evans         kname(p, k, name);
5610495ed39SKyle Evans         return gxf(p, pc, i, 0);
5628e3e3a7aSWarner Losh       }
5638e3e3a7aSWarner Losh       case OP_GETUPVAL: {
5648e3e3a7aSWarner Losh         *name = upvalname(p, GETARG_B(i));
5658e3e3a7aSWarner Losh         return "upvalue";
5668e3e3a7aSWarner Losh       }
5678e3e3a7aSWarner Losh       case OP_LOADK:
5688e3e3a7aSWarner Losh       case OP_LOADKX: {
5698e3e3a7aSWarner Losh         int b = (op == OP_LOADK) ? GETARG_Bx(i)
5708e3e3a7aSWarner Losh                                  : GETARG_Ax(p->code[pc + 1]);
5718e3e3a7aSWarner Losh         if (ttisstring(&p->k[b])) {
5728e3e3a7aSWarner Losh           *name = svalue(&p->k[b]);
5738e3e3a7aSWarner Losh           return "constant";
5748e3e3a7aSWarner Losh         }
5758e3e3a7aSWarner Losh         break;
5768e3e3a7aSWarner Losh       }
5778e3e3a7aSWarner Losh       case OP_SELF: {
5780495ed39SKyle Evans         rkname(p, pc, i, name);
5798e3e3a7aSWarner Losh         return "method";
5808e3e3a7aSWarner Losh       }
5818e3e3a7aSWarner Losh       default: break;  /* go through to return NULL */
5828e3e3a7aSWarner Losh     }
5838e3e3a7aSWarner Losh   }
5848e3e3a7aSWarner Losh   return NULL;  /* could not find reasonable name */
5858e3e3a7aSWarner Losh }
5868e3e3a7aSWarner Losh 
5878e3e3a7aSWarner Losh 
5888e3e3a7aSWarner Losh /*
5898e3e3a7aSWarner Losh ** Try to find a name for a function based on the code that called it.
5908e3e3a7aSWarner Losh ** (Only works when function was called by a Lua function.)
5918e3e3a7aSWarner Losh ** Returns what the name is (e.g., "for iterator", "method",
5928e3e3a7aSWarner Losh ** "metamethod") and sets '*name' to point to the name.
5938e3e3a7aSWarner Losh */
funcnamefromcode(lua_State * L,const Proto * p,int pc,const char ** name)5948c784bb8SWarner Losh static const char *funcnamefromcode (lua_State *L, const Proto *p,
5958c784bb8SWarner Losh                                      int pc, const char **name) {
5968e3e3a7aSWarner Losh   TMS tm = (TMS)0;  /* (initial value avoids warnings) */
5978e3e3a7aSWarner Losh   Instruction i = p->code[pc];  /* calling instruction */
5988e3e3a7aSWarner Losh   switch (GET_OPCODE(i)) {
5998e3e3a7aSWarner Losh     case OP_CALL:
6008e3e3a7aSWarner Losh     case OP_TAILCALL:
6018e3e3a7aSWarner Losh       return getobjname(p, pc, GETARG_A(i), name);  /* get function name */
6028e3e3a7aSWarner Losh     case OP_TFORCALL: {  /* for iterator */
6038e3e3a7aSWarner Losh       *name = "for iterator";
6048e3e3a7aSWarner Losh        return "for iterator";
6058e3e3a7aSWarner Losh     }
6068e3e3a7aSWarner Losh     /* other instructions can do calls through metamethods */
6078e3e3a7aSWarner Losh     case OP_SELF: case OP_GETTABUP: case OP_GETTABLE:
6080495ed39SKyle Evans     case OP_GETI: case OP_GETFIELD:
6098e3e3a7aSWarner Losh       tm = TM_INDEX;
6108e3e3a7aSWarner Losh       break;
6110495ed39SKyle Evans     case OP_SETTABUP: case OP_SETTABLE: case OP_SETI: case OP_SETFIELD:
6128e3e3a7aSWarner Losh       tm = TM_NEWINDEX;
6138e3e3a7aSWarner Losh       break;
6140495ed39SKyle Evans     case OP_MMBIN: case OP_MMBINI: case OP_MMBINK: {
6150495ed39SKyle Evans       tm = cast(TMS, GETARG_C(i));
6168e3e3a7aSWarner Losh       break;
6178e3e3a7aSWarner Losh     }
6188e3e3a7aSWarner Losh     case OP_UNM: tm = TM_UNM; break;
6198e3e3a7aSWarner Losh     case OP_BNOT: tm = TM_BNOT; break;
6208e3e3a7aSWarner Losh     case OP_LEN: tm = TM_LEN; break;
6218e3e3a7aSWarner Losh     case OP_CONCAT: tm = TM_CONCAT; break;
6228e3e3a7aSWarner Losh     case OP_EQ: tm = TM_EQ; break;
6238c784bb8SWarner Losh     /* no cases for OP_EQI and OP_EQK, as they don't call metamethods */
6248c784bb8SWarner Losh     case OP_LT: case OP_LTI: case OP_GTI: tm = TM_LT; break;
6258c784bb8SWarner Losh     case OP_LE: case OP_LEI: case OP_GEI: tm = TM_LE; break;
6268c784bb8SWarner Losh     case OP_CLOSE: case OP_RETURN: tm = TM_CLOSE; break;
6278e3e3a7aSWarner Losh     default:
6288e3e3a7aSWarner Losh       return NULL;  /* cannot find a reasonable name */
6298e3e3a7aSWarner Losh   }
6300495ed39SKyle Evans   *name = getstr(G(L)->tmname[tm]) + 2;
6318e3e3a7aSWarner Losh   return "metamethod";
6328e3e3a7aSWarner Losh }
6338e3e3a7aSWarner Losh 
6348c784bb8SWarner Losh 
6358c784bb8SWarner Losh /*
6368c784bb8SWarner Losh ** Try to find a name for a function based on how it was called.
6378c784bb8SWarner Losh */
funcnamefromcall(lua_State * L,CallInfo * ci,const char ** name)6388c784bb8SWarner Losh static const char *funcnamefromcall (lua_State *L, CallInfo *ci,
6398c784bb8SWarner Losh                                                    const char **name) {
6408c784bb8SWarner Losh   if (ci->callstatus & CIST_HOOKED) {  /* was it called inside a hook? */
6418c784bb8SWarner Losh     *name = "?";
6428c784bb8SWarner Losh     return "hook";
6438c784bb8SWarner Losh   }
6448c784bb8SWarner Losh   else if (ci->callstatus & CIST_FIN) {  /* was it called as a finalizer? */
6458c784bb8SWarner Losh     *name = "__gc";
6468c784bb8SWarner Losh     return "metamethod";  /* report it as such */
6478c784bb8SWarner Losh   }
6488c784bb8SWarner Losh   else if (isLua(ci))
6498c784bb8SWarner Losh     return funcnamefromcode(L, ci_func(ci)->p, currentpc(ci), name);
6508c784bb8SWarner Losh   else
6518c784bb8SWarner Losh     return NULL;
6528c784bb8SWarner Losh }
6538c784bb8SWarner Losh 
6548e3e3a7aSWarner Losh /* }====================================================== */
6558e3e3a7aSWarner Losh 
6568e3e3a7aSWarner Losh 
6578e3e3a7aSWarner Losh 
6588e3e3a7aSWarner Losh /*
659*a9490b81SWarner Losh ** Check whether pointer 'o' points to some value in the stack frame of
660*a9490b81SWarner Losh ** the current function and, if so, returns its index.  Because 'o' may
661*a9490b81SWarner Losh ** not point to a value in this stack, we cannot compare it with the
662*a9490b81SWarner Losh ** region boundaries (undefined behavior in ISO C).
6638e3e3a7aSWarner Losh */
instack(CallInfo * ci,const TValue * o)664*a9490b81SWarner Losh static int instack (CallInfo *ci, const TValue *o) {
665*a9490b81SWarner Losh   int pos;
666*a9490b81SWarner Losh   StkId base = ci->func.p + 1;
667*a9490b81SWarner Losh   for (pos = 0; base + pos < ci->top.p; pos++) {
668*a9490b81SWarner Losh     if (o == s2v(base + pos))
669*a9490b81SWarner Losh       return pos;
6708c784bb8SWarner Losh   }
671*a9490b81SWarner Losh   return -1;  /* not found */
6728e3e3a7aSWarner Losh }
6738e3e3a7aSWarner Losh 
6748e3e3a7aSWarner Losh 
6758e3e3a7aSWarner Losh /*
6768e3e3a7aSWarner Losh ** Checks whether value 'o' came from an upvalue. (That can only happen
6778e3e3a7aSWarner Losh ** with instructions OP_GETTABUP/OP_SETTABUP, which operate directly on
6788e3e3a7aSWarner Losh ** upvalues.)
6798e3e3a7aSWarner Losh */
getupvalname(CallInfo * ci,const TValue * o,const char ** name)6808e3e3a7aSWarner Losh static const char *getupvalname (CallInfo *ci, const TValue *o,
6818e3e3a7aSWarner Losh                                  const char **name) {
6828e3e3a7aSWarner Losh   LClosure *c = ci_func(ci);
6838e3e3a7aSWarner Losh   int i;
6848e3e3a7aSWarner Losh   for (i = 0; i < c->nupvalues; i++) {
685*a9490b81SWarner Losh     if (c->upvals[i]->v.p == o) {
6868e3e3a7aSWarner Losh       *name = upvalname(c->p, i);
6878e3e3a7aSWarner Losh       return "upvalue";
6888e3e3a7aSWarner Losh     }
6898e3e3a7aSWarner Losh   }
6908e3e3a7aSWarner Losh   return NULL;
6918e3e3a7aSWarner Losh }
6928e3e3a7aSWarner Losh 
6938e3e3a7aSWarner Losh 
formatvarinfo(lua_State * L,const char * kind,const char * name)6948c784bb8SWarner Losh static const char *formatvarinfo (lua_State *L, const char *kind,
6958c784bb8SWarner Losh                                                 const char *name) {
6968c784bb8SWarner Losh   if (kind == NULL)
6978c784bb8SWarner Losh     return "";  /* no information */
6988c784bb8SWarner Losh   else
6998c784bb8SWarner Losh     return luaO_pushfstring(L, " (%s '%s')", kind, name);
7008c784bb8SWarner Losh }
7018c784bb8SWarner Losh 
7028c784bb8SWarner Losh /*
7038c784bb8SWarner Losh ** Build a string with a "description" for the value 'o', such as
7048c784bb8SWarner Losh ** "variable 'x'" or "upvalue 'y'".
7058c784bb8SWarner Losh */
varinfo(lua_State * L,const TValue * o)7068e3e3a7aSWarner Losh static const char *varinfo (lua_State *L, const TValue *o) {
7078e3e3a7aSWarner Losh   CallInfo *ci = L->ci;
7088c784bb8SWarner Losh   const char *name = NULL;  /* to avoid warnings */
7098e3e3a7aSWarner Losh   const char *kind = NULL;
7108e3e3a7aSWarner Losh   if (isLua(ci)) {
7118e3e3a7aSWarner Losh     kind = getupvalname(ci, o, &name);  /* check whether 'o' is an upvalue */
712*a9490b81SWarner Losh     if (!kind) {  /* not an upvalue? */
713*a9490b81SWarner Losh       int reg = instack(ci, o);  /* try a register */
714*a9490b81SWarner Losh       if (reg >= 0)  /* is 'o' a register? */
715*a9490b81SWarner Losh         kind = getobjname(ci_func(ci)->p, currentpc(ci), reg, &name);
716*a9490b81SWarner Losh     }
7178e3e3a7aSWarner Losh   }
7188c784bb8SWarner Losh   return formatvarinfo(L, kind, name);
7198e3e3a7aSWarner Losh }
7208e3e3a7aSWarner Losh 
7218e3e3a7aSWarner Losh 
7228c784bb8SWarner Losh /*
7238c784bb8SWarner Losh ** Raise a type error
7248c784bb8SWarner Losh */
typeerror(lua_State * L,const TValue * o,const char * op,const char * extra)7258c784bb8SWarner Losh static l_noret typeerror (lua_State *L, const TValue *o, const char *op,
7268c784bb8SWarner Losh                           const char *extra) {
7278e3e3a7aSWarner Losh   const char *t = luaT_objtypename(L, o);
7288c784bb8SWarner Losh   luaG_runerror(L, "attempt to %s a %s value%s", op, t, extra);
7298c784bb8SWarner Losh }
7308c784bb8SWarner Losh 
7318c784bb8SWarner Losh 
7328c784bb8SWarner Losh /*
7338c784bb8SWarner Losh ** Raise a type error with "standard" information about the faulty
7348c784bb8SWarner Losh ** object 'o' (using 'varinfo').
7358c784bb8SWarner Losh */
luaG_typeerror(lua_State * L,const TValue * o,const char * op)7368c784bb8SWarner Losh l_noret luaG_typeerror (lua_State *L, const TValue *o, const char *op) {
7378c784bb8SWarner Losh   typeerror(L, o, op, varinfo(L, o));
7388c784bb8SWarner Losh }
7398c784bb8SWarner Losh 
7408c784bb8SWarner Losh 
7418c784bb8SWarner Losh /*
7428c784bb8SWarner Losh ** Raise an error for calling a non-callable object. Try to find a name
7438c784bb8SWarner Losh ** for the object based on how it was called ('funcnamefromcall'); if it
7448c784bb8SWarner Losh ** cannot get a name there, try 'varinfo'.
7458c784bb8SWarner Losh */
luaG_callerror(lua_State * L,const TValue * o)7468c784bb8SWarner Losh l_noret luaG_callerror (lua_State *L, const TValue *o) {
7478c784bb8SWarner Losh   CallInfo *ci = L->ci;
7488c784bb8SWarner Losh   const char *name = NULL;  /* to avoid warnings */
7498c784bb8SWarner Losh   const char *kind = funcnamefromcall(L, ci, &name);
7508c784bb8SWarner Losh   const char *extra = kind ? formatvarinfo(L, kind, name) : varinfo(L, o);
7518c784bb8SWarner Losh   typeerror(L, o, "call", extra);
7528e3e3a7aSWarner Losh }
7538e3e3a7aSWarner Losh 
7548e3e3a7aSWarner Losh 
luaG_forerror(lua_State * L,const TValue * o,const char * what)7550495ed39SKyle Evans l_noret luaG_forerror (lua_State *L, const TValue *o, const char *what) {
7560495ed39SKyle Evans   luaG_runerror(L, "bad 'for' %s (number expected, got %s)",
7570495ed39SKyle Evans                    what, luaT_objtypename(L, o));
7580495ed39SKyle Evans }
7590495ed39SKyle Evans 
7600495ed39SKyle Evans 
luaG_concaterror(lua_State * L,const TValue * p1,const TValue * p2)7618e3e3a7aSWarner Losh l_noret luaG_concaterror (lua_State *L, const TValue *p1, const TValue *p2) {
7628e3e3a7aSWarner Losh   if (ttisstring(p1) || cvt2str(p1)) p1 = p2;
7638e3e3a7aSWarner Losh   luaG_typeerror(L, p1, "concatenate");
7648e3e3a7aSWarner Losh }
7658e3e3a7aSWarner Losh 
7668e3e3a7aSWarner Losh 
luaG_opinterror(lua_State * L,const TValue * p1,const TValue * p2,const char * msg)7678e3e3a7aSWarner Losh l_noret luaG_opinterror (lua_State *L, const TValue *p1,
7688e3e3a7aSWarner Losh                          const TValue *p2, const char *msg) {
7690495ed39SKyle Evans   if (!ttisnumber(p1))  /* first operand is wrong? */
7708e3e3a7aSWarner Losh     p2 = p1;  /* now second is wrong */
7718e3e3a7aSWarner Losh   luaG_typeerror(L, p2, msg);
7728e3e3a7aSWarner Losh }
7738e3e3a7aSWarner Losh 
7748e3e3a7aSWarner Losh 
7758e3e3a7aSWarner Losh /*
7768e3e3a7aSWarner Losh ** Error when both values are convertible to numbers, but not to integers
7778e3e3a7aSWarner Losh */
luaG_tointerror(lua_State * L,const TValue * p1,const TValue * p2)7788e3e3a7aSWarner Losh l_noret luaG_tointerror (lua_State *L, const TValue *p1, const TValue *p2) {
7798e3e3a7aSWarner Losh   lua_Integer temp;
7808c784bb8SWarner Losh   if (!luaV_tointegerns(p1, &temp, LUA_FLOORN2I))
7818e3e3a7aSWarner Losh     p2 = p1;
7828e3e3a7aSWarner Losh   luaG_runerror(L, "number%s has no integer representation", varinfo(L, p2));
7838e3e3a7aSWarner Losh }
7848e3e3a7aSWarner Losh 
7858e3e3a7aSWarner Losh 
luaG_ordererror(lua_State * L,const TValue * p1,const TValue * p2)7868e3e3a7aSWarner Losh l_noret luaG_ordererror (lua_State *L, const TValue *p1, const TValue *p2) {
7878e3e3a7aSWarner Losh   const char *t1 = luaT_objtypename(L, p1);
7888e3e3a7aSWarner Losh   const char *t2 = luaT_objtypename(L, p2);
7898e3e3a7aSWarner Losh   if (strcmp(t1, t2) == 0)
7908e3e3a7aSWarner Losh     luaG_runerror(L, "attempt to compare two %s values", t1);
7918e3e3a7aSWarner Losh   else
7928e3e3a7aSWarner Losh     luaG_runerror(L, "attempt to compare %s with %s", t1, t2);
7938e3e3a7aSWarner Losh }
7948e3e3a7aSWarner Losh 
7958e3e3a7aSWarner Losh 
7968e3e3a7aSWarner Losh /* add src:line information to 'msg' */
luaG_addinfo(lua_State * L,const char * msg,TString * src,int line)7978e3e3a7aSWarner Losh const char *luaG_addinfo (lua_State *L, const char *msg, TString *src,
7988e3e3a7aSWarner Losh                                         int line) {
7998e3e3a7aSWarner Losh   char buff[LUA_IDSIZE];
8008e3e3a7aSWarner Losh   if (src)
8010495ed39SKyle Evans     luaO_chunkid(buff, getstr(src), tsslen(src));
8028e3e3a7aSWarner Losh   else {  /* no source available; use "?" instead */
8038e3e3a7aSWarner Losh     buff[0] = '?'; buff[1] = '\0';
8048e3e3a7aSWarner Losh   }
8058e3e3a7aSWarner Losh   return luaO_pushfstring(L, "%s:%d: %s", buff, line, msg);
8068e3e3a7aSWarner Losh }
8078e3e3a7aSWarner Losh 
8088e3e3a7aSWarner Losh 
luaG_errormsg(lua_State * L)8098e3e3a7aSWarner Losh l_noret luaG_errormsg (lua_State *L) {
8108e3e3a7aSWarner Losh   if (L->errfunc != 0) {  /* is there an error handling function? */
8118e3e3a7aSWarner Losh     StkId errfunc = restorestack(L, L->errfunc);
8120495ed39SKyle Evans     lua_assert(ttisfunction(s2v(errfunc)));
813*a9490b81SWarner Losh     setobjs2s(L, L->top.p, L->top.p - 1);  /* move argument */
814*a9490b81SWarner Losh     setobjs2s(L, L->top.p - 1, errfunc);  /* push function */
815*a9490b81SWarner Losh     L->top.p++;  /* assume EXTRA_STACK */
816*a9490b81SWarner Losh     luaD_callnoyield(L, L->top.p - 2, 1);  /* call it */
8178e3e3a7aSWarner Losh   }
8188e3e3a7aSWarner Losh   luaD_throw(L, LUA_ERRRUN);
8198e3e3a7aSWarner Losh }
8208e3e3a7aSWarner Losh 
8218e3e3a7aSWarner Losh 
luaG_runerror(lua_State * L,const char * fmt,...)8228e3e3a7aSWarner Losh l_noret luaG_runerror (lua_State *L, const char *fmt, ...) {
8238e3e3a7aSWarner Losh   CallInfo *ci = L->ci;
8248e3e3a7aSWarner Losh   const char *msg;
8258e3e3a7aSWarner Losh   va_list argp;
826e112e9d2SKyle Evans   luaC_checkGC(L);  /* error message uses memory */
8278e3e3a7aSWarner Losh   va_start(argp, fmt);
8288e3e3a7aSWarner Losh   msg = luaO_pushvfstring(L, fmt, argp);  /* format message */
8298e3e3a7aSWarner Losh   va_end(argp);
830*a9490b81SWarner Losh   if (isLua(ci)) {  /* if Lua function, add source:line information */
8310495ed39SKyle Evans     luaG_addinfo(L, msg, ci_func(ci)->p->source, getcurrentline(ci));
832*a9490b81SWarner Losh     setobjs2s(L, L->top.p - 2, L->top.p - 1);  /* remove 'msg' */
833*a9490b81SWarner Losh     L->top.p--;
834*a9490b81SWarner Losh   }
8358e3e3a7aSWarner Losh   luaG_errormsg(L);
8368e3e3a7aSWarner Losh }
8378e3e3a7aSWarner Losh 
8388e3e3a7aSWarner Losh 
8390495ed39SKyle Evans /*
8400495ed39SKyle Evans ** Check whether new instruction 'newpc' is in a different line from
8418c784bb8SWarner Losh ** previous instruction 'oldpc'. More often than not, 'newpc' is only
8428c784bb8SWarner Losh ** one or a few instructions after 'oldpc' (it must be after, see
8438c784bb8SWarner Losh ** caller), so try to avoid calling 'luaG_getfuncline'. If they are
8448c784bb8SWarner Losh ** too far apart, there is a good chance of a ABSLINEINFO in the way,
8458c784bb8SWarner Losh ** so it goes directly to 'luaG_getfuncline'.
8460495ed39SKyle Evans */
changedline(const Proto * p,int oldpc,int newpc)8470495ed39SKyle Evans static int changedline (const Proto *p, int oldpc, int newpc) {
8480495ed39SKyle Evans   if (p->lineinfo == NULL)  /* no debug information? */
8490495ed39SKyle Evans     return 0;
8508c784bb8SWarner Losh   if (newpc - oldpc < MAXIWTHABS / 2) {  /* not too far apart? */
851*a9490b81SWarner Losh     int delta = 0;  /* line difference */
8528c784bb8SWarner Losh     int pc = oldpc;
8538c784bb8SWarner Losh     for (;;) {
8548c784bb8SWarner Losh       int lineinfo = p->lineinfo[++pc];
8558c784bb8SWarner Losh       if (lineinfo == ABSLINEINFO)
8568c784bb8SWarner Losh         break;  /* cannot compute delta; fall through */
8578c784bb8SWarner Losh       delta += lineinfo;
8588c784bb8SWarner Losh       if (pc == newpc)
8598c784bb8SWarner Losh         return (delta != 0);  /* delta computed successfully */
8600495ed39SKyle Evans     }
8618c784bb8SWarner Losh   }
8628c784bb8SWarner Losh   /* either instructions are too far apart or there is an absolute line
8638c784bb8SWarner Losh      info in the way; compute line difference explicitly */
8648c784bb8SWarner Losh   return (luaG_getfuncline(p, oldpc) != luaG_getfuncline(p, newpc));
8650495ed39SKyle Evans }
8660495ed39SKyle Evans 
8670495ed39SKyle Evans 
8680495ed39SKyle Evans /*
8690495ed39SKyle Evans ** Traces the execution of a Lua function. Called before the execution
8700495ed39SKyle Evans ** of each opcode, when debug is on. 'L->oldpc' stores the last
8710495ed39SKyle Evans ** instruction traced, to detect line changes. When entering a new
8728c784bb8SWarner Losh ** function, 'npci' will be zero and will test as a new line whatever
8738c784bb8SWarner Losh ** the value of 'oldpc'.  Some exceptional conditions may return to
8748c784bb8SWarner Losh ** a function without setting 'oldpc'. In that case, 'oldpc' may be
8758c784bb8SWarner Losh ** invalid; if so, use zero as a valid value. (A wrong but valid 'oldpc'
8768c784bb8SWarner Losh ** at most causes an extra call to a line hook.)
8778c784bb8SWarner Losh ** This function is not "Protected" when called, so it should correct
878*a9490b81SWarner Losh ** 'L->top.p' before calling anything that can run the GC.
8790495ed39SKyle Evans */
luaG_traceexec(lua_State * L,const Instruction * pc)8800495ed39SKyle Evans int luaG_traceexec (lua_State *L, const Instruction *pc) {
8818e3e3a7aSWarner Losh   CallInfo *ci = L->ci;
8828e3e3a7aSWarner Losh   lu_byte mask = L->hookmask;
8830495ed39SKyle Evans   const Proto *p = ci_func(ci)->p;
8840495ed39SKyle Evans   int counthook;
8850495ed39SKyle Evans   if (!(mask & (LUA_MASKLINE | LUA_MASKCOUNT))) {  /* no hooks? */
8860495ed39SKyle Evans     ci->u.l.trap = 0;  /* don't need to stop again */
8870495ed39SKyle Evans     return 0;  /* turn off 'trap' */
8880495ed39SKyle Evans   }
8890495ed39SKyle Evans   pc++;  /* reference is always next instruction */
8900495ed39SKyle Evans   ci->u.l.savedpc = pc;  /* save 'pc' */
8910495ed39SKyle Evans   counthook = (--L->hookcount == 0 && (mask & LUA_MASKCOUNT));
8928e3e3a7aSWarner Losh   if (counthook)
8938e3e3a7aSWarner Losh     resethookcount(L);  /* reset count */
8948e3e3a7aSWarner Losh   else if (!(mask & LUA_MASKLINE))
8950495ed39SKyle Evans     return 1;  /* no line hook and count != 0; nothing to be done now */
8968e3e3a7aSWarner Losh   if (ci->callstatus & CIST_HOOKYIELD) {  /* called hook last time? */
8978e3e3a7aSWarner Losh     ci->callstatus &= ~CIST_HOOKYIELD;  /* erase mark */
8980495ed39SKyle Evans     return 1;  /* do not call hook again (VM yielded, so it did not move) */
8998e3e3a7aSWarner Losh   }
9008c784bb8SWarner Losh   if (!isIT(*(ci->u.l.savedpc - 1)))  /* top not being used? */
901*a9490b81SWarner Losh     L->top.p = ci->top.p;  /* correct top */
9028e3e3a7aSWarner Losh   if (counthook)
9030495ed39SKyle Evans     luaD_hook(L, LUA_HOOKCOUNT, -1, 0, 0);  /* call count hook */
9048e3e3a7aSWarner Losh   if (mask & LUA_MASKLINE) {
9058c784bb8SWarner Losh     /* 'L->oldpc' may be invalid; use zero in this case */
9068c784bb8SWarner Losh     int oldpc = (L->oldpc < p->sizecode) ? L->oldpc : 0;
9070495ed39SKyle Evans     int npci = pcRel(pc, p);
9088c784bb8SWarner Losh     if (npci <= oldpc ||  /* call hook when jump back (loop), */
9098c784bb8SWarner Losh         changedline(p, oldpc, npci)) {  /* or when enter new line */
9100495ed39SKyle Evans       int newline = luaG_getfuncline(p, npci);
9110495ed39SKyle Evans       luaD_hook(L, LUA_HOOKLINE, newline, 0, 0);  /* call line hook */
9128e3e3a7aSWarner Losh     }
9130495ed39SKyle Evans     L->oldpc = npci;  /* 'pc' of last call to line hook */
9140495ed39SKyle Evans   }
9158e3e3a7aSWarner Losh   if (L->status == LUA_YIELD) {  /* did hook yield? */
9168e3e3a7aSWarner Losh     if (counthook)
9178e3e3a7aSWarner Losh       L->hookcount = 1;  /* undo decrement to zero */
9188e3e3a7aSWarner Losh     ci->u.l.savedpc--;  /* undo increment (resume will increment it again) */
9198e3e3a7aSWarner Losh     ci->callstatus |= CIST_HOOKYIELD;  /* mark that it yielded */
9208e3e3a7aSWarner Losh     luaD_throw(L, LUA_YIELD);
9218e3e3a7aSWarner Losh   }
9220495ed39SKyle Evans   return 1;  /* keep 'trap' on */
9238e3e3a7aSWarner Losh }
9248e3e3a7aSWarner Losh 
925