src/lj_debug.c - luajit-2.0-src

Functions defined

Macros defined

Source code

  1. /*
  2. ** Debugging and introspection.
  3. ** Copyright (C) 2005-2015 Mike Pall. See Copyright Notice in luajit.h
  4. */

  5. #define lj_debug_c
  6. #define LUA_CORE

  7. #include "lj_obj.h"
  8. #include "lj_err.h"
  9. #include "lj_debug.h"
  10. #include "lj_buf.h"
  11. #include "lj_tab.h"
  12. #include "lj_state.h"
  13. #include "lj_frame.h"
  14. #include "lj_bc.h"
  15. #include "lj_strfmt.h"
  16. #if LJ_HASJIT
  17. #include "lj_jit.h"
  18. #endif

  19. /* -- Frames -------------------------------------------------------------- */

  20. /* Get frame corresponding to a level. */
  21. cTValue *lj_debug_frame(lua_State *L, int level, int *size)
  22. {
  23.   cTValue *frame, *nextframe, *bot = tvref(L->stack)+LJ_FR2;
  24.   /* Traverse frames backwards. */
  25.   for (nextframe = frame = L->base-1; frame > bot; ) {
  26.     if (frame_gc(frame) == obj2gco(L))
  27.       level++;  /* Skip dummy frames. See lj_err_optype_call(). */
  28.     if (level-- == 0) {
  29.       *size = (int)(nextframe - frame);
  30.       return frame;  /* Level found. */
  31.     }
  32.     nextframe = frame;
  33.     if (frame_islua(frame)) {
  34.       frame = frame_prevl(frame);
  35.     } else {
  36.       if (frame_isvarg(frame))
  37.         level++;  /* Skip vararg pseudo-frame. */
  38.       frame = frame_prevd(frame);
  39.     }
  40.   }
  41.   *size = level;
  42.   return NULL/* Level not found. */
  43. }

  44. /* Invalid bytecode position. */
  45. #define NO_BCPOS        (~(BCPos)0)

  46. /* Return bytecode position for function/frame or NO_BCPOS. */
  47. static BCPos debug_framepc(lua_State *L, GCfunc *fn, cTValue *nextframe)
  48. {
  49.   const BCIns *ins;
  50.   GCproto *pt;
  51.   BCPos pos;
  52.   lua_assert(fn->c.gct == ~LJ_TFUNC || fn->c.gct == ~LJ_TTHREAD);
  53.   if (!isluafunc(fn)) {  /* Cannot derive a PC for non-Lua functions. */
  54.     return NO_BCPOS;
  55.   } else if (nextframe == NULL) {  /* Lua function on top. */
  56.     void *cf = cframe_raw(L->cframe);
  57.     if (cf == NULL || (char *)cframe_pc(cf) == (char *)cframe_L(cf))
  58.       return NO_BCPOS;
  59.     ins = cframe_pc(cf);  /* Only happens during error/hook handling. */
  60.   } else {
  61.     if (frame_islua(nextframe)) {
  62.       ins = frame_pc(nextframe);
  63.     } else if (frame_iscont(nextframe)) {
  64.       ins = frame_contpc(nextframe);
  65.     } else {
  66.       /* Lua function below errfunc/gc/hook: find cframe to get the PC. */
  67.       void *cf = cframe_raw(L->cframe);
  68.       TValue *f = L->base-1;
  69.       for (;;) {
  70.         if (cf == NULL)
  71.           return NO_BCPOS;
  72.         while (cframe_nres(cf) < 0) {
  73.           if (f >= restorestack(L, -cframe_nres(cf)))
  74.             break;
  75.           cf = cframe_raw(cframe_prev(cf));
  76.           if (cf == NULL)
  77.             return NO_BCPOS;
  78.         }
  79.         if (f < nextframe)
  80.           break;
  81.         if (frame_islua(f)) {
  82.           f = frame_prevl(f);
  83.         } else {
  84.           if (frame_isc(f) || (frame_iscont(f) && frame_iscont_fficb(f)))
  85.             cf = cframe_raw(cframe_prev(cf));
  86.           f = frame_prevd(f);
  87.         }
  88.       }
  89.       ins = cframe_pc(cf);
  90.     }
  91.   }
  92.   pt = funcproto(fn);
  93.   pos = proto_bcpos(pt, ins) - 1;
  94. #if LJ_HASJIT
  95.   if (pos > pt->sizebc) {  /* Undo the effects of lj_trace_exit for JLOOP. */
  96.     GCtrace *T = (GCtrace *)((char *)(ins-1) - offsetof(GCtrace, startins));
  97.     lua_assert(bc_isret(bc_op(ins[-1])));
  98.     pos = proto_bcpos(pt, mref(T->startpc, const BCIns));
  99.   }
  100. #endif
  101.   return pos;
  102. }

  103. /* -- Line numbers -------------------------------------------------------- */

  104. /* Get line number for a bytecode position. */
  105. BCLine LJ_FASTCALL lj_debug_line(GCproto *pt, BCPos pc)
  106. {
  107.   const void *lineinfo = proto_lineinfo(pt);
  108.   if (pc <= pt->sizebc && lineinfo) {
  109.     BCLine first = pt->firstline;
  110.     if (pc == pt->sizebc) return first + pt->numline;
  111.     if (pc-- == 0) return first;
  112.     if (pt->numline < 256)
  113.       return first + (BCLine)((const uint8_t *)lineinfo)[pc];
  114.     else if (pt->numline < 65536)
  115.       return first + (BCLine)((const uint16_t *)lineinfo)[pc];
  116.     else
  117.       return first + (BCLine)((const uint32_t *)lineinfo)[pc];
  118.   }
  119.   return 0;
  120. }

  121. /* Get line number for function/frame. */
  122. static BCLine debug_frameline(lua_State *L, GCfunc *fn, cTValue *nextframe)
  123. {
  124.   BCPos pc = debug_framepc(L, fn, nextframe);
  125.   if (pc != NO_BCPOS) {
  126.     GCproto *pt = funcproto(fn);
  127.     lua_assert(pc <= pt->sizebc);
  128.     return lj_debug_line(pt, pc);
  129.   }
  130.   return -1;
  131. }

  132. /* -- Variable names ------------------------------------------------------ */

  133. /* Get name of a local variable from slot number and PC. */
  134. static const char *debug_varname(const GCproto *pt, BCPos pc, BCReg slot)
  135. {
  136.   const char *p = (const char *)proto_varinfo(pt);
  137.   if (p) {
  138.     BCPos lastpc = 0;
  139.     for (;;) {
  140.       const char *name = p;
  141.       uint32_t vn = *(const uint8_t *)p;
  142.       BCPos startpc, endpc;
  143.       if (vn < VARNAME__MAX) {
  144.         if (vn == VARNAME_END) break/* End of varinfo. */
  145.       } else {
  146.         do { p++; } while (*(const uint8_t *)p);  /* Skip over variable name. */
  147.       }
  148.       p++;
  149.       lastpc = startpc = lastpc + lj_buf_ruleb128(&p);
  150.       if (startpc > pc) break;
  151.       endpc = startpc + lj_buf_ruleb128(&p);
  152.       if (pc < endpc && slot-- == 0) {
  153.         if (vn < VARNAME__MAX) {
  154. #define VARNAMESTR(name, str)        str "\0"
  155.           name = VARNAMEDEF(VARNAMESTR);
  156. #undef VARNAMESTR
  157.           if (--vn) while (*name++ || --vn) ;
  158.         }
  159.         return name;
  160.       }
  161.     }
  162.   }
  163.   return NULL;
  164. }

  165. /* Get name of local variable from 1-based slot number and function/frame. */
  166. static TValue *debug_localname(lua_State *L, const lua_Debug *ar,
  167.                                const char **name, BCReg slot1)
  168. {
  169.   uint32_t offset = (uint32_t)ar->i_ci & 0xffff;
  170.   uint32_t size = (uint32_t)ar->i_ci >> 16;
  171.   TValue *frame = tvref(L->stack) + offset;
  172.   TValue *nextframe = size ? frame + size : NULL;
  173.   GCfunc *fn = frame_func(frame);
  174.   BCPos pc = debug_framepc(L, fn, nextframe);
  175.   if (!nextframe) nextframe = L->top+LJ_FR2;
  176.   if ((int)slot1 < 0) {  /* Negative slot number is for varargs. */
  177.     if (pc != NO_BCPOS) {
  178.       GCproto *pt = funcproto(fn);
  179.       if ((pt->flags & PROTO_VARARG)) {
  180.         slot1 = pt->numparams + (BCReg)(-(int)slot1);
  181.         if (frame_isvarg(frame)) {  /* Vararg frame has been set up? (pc!=0) */
  182.           nextframe = frame;
  183.           frame = frame_prevd(frame);
  184.         }
  185.         if (frame + slot1+LJ_FR2 < nextframe) {
  186.           *name = "(*vararg)";
  187.           return frame+slot1;
  188.         }
  189.       }
  190.     }
  191.     return NULL;
  192.   }
  193.   if (pc != NO_BCPOS &&
  194.       (*name = debug_varname(funcproto(fn), pc, slot1-1)) != NULL)
  195.     ;
  196.   else if (slot1 > 0 && frame + slot1+LJ_FR2 < nextframe)
  197.     *name = "(*temporary)";
  198.   return frame+slot1;
  199. }

  200. /* Get name of upvalue. */
  201. const char *lj_debug_uvname(GCproto *pt, uint32_t idx)
  202. {
  203.   const uint8_t *p = proto_uvinfo(pt);
  204.   lua_assert(idx < pt->sizeuv);
  205.   if (!p) return "";
  206.   if (idx) while (*p++ || --idx) ;
  207.   return (const char *)p;
  208. }

  209. /* Get name and value of upvalue. */
  210. const char *lj_debug_uvnamev(cTValue *o, uint32_t idx, TValue **tvp)
  211. {
  212.   if (tvisfunc(o)) {
  213.     GCfunc *fn = funcV(o);
  214.     if (isluafunc(fn)) {
  215.       GCproto *pt = funcproto(fn);
  216.       if (idx < pt->sizeuv) {
  217.         *tvp = uvval(&gcref(fn->l.uvptr[idx])->uv);
  218.         return lj_debug_uvname(pt, idx);
  219.       }
  220.     } else {
  221.       if (idx < fn->c.nupvalues) {
  222.         *tvp = &fn->c.upvalue[idx];
  223.         return "";
  224.       }
  225.     }
  226.   }
  227.   return NULL;
  228. }

  229. /* Deduce name of an object from slot number and PC. */
  230. const char *lj_debug_slotname(GCproto *pt, const BCIns *ip, BCReg slot,
  231.                               const char **name)
  232. {
  233.   const char *lname;
  234. restart:
  235.   lname = debug_varname(pt, proto_bcpos(pt, ip), slot);
  236.   if (lname != NULL) { *name = lname; return "local"; }
  237.   while (--ip > proto_bc(pt)) {
  238.     BCIns ins = *ip;
  239.     BCOp op = bc_op(ins);
  240.     BCReg ra = bc_a(ins);
  241.     if (bcmode_a(op) == BCMbase) {
  242.       if (slot >= ra && (op != BC_KNIL || slot <= bc_d(ins)))
  243.         return NULL;
  244.     } else if (bcmode_a(op) == BCMdst && ra == slot) {
  245.       switch (bc_op(ins)) {
  246.       case BC_MOV:
  247.         if (ra == slot) { slot = bc_d(ins); goto restart; }
  248.         break;
  249.       case BC_GGET:
  250.         *name = strdata(gco2str(proto_kgc(pt, ~(ptrdiff_t)bc_d(ins))));
  251.         return "global";
  252.       case BC_TGETS:
  253.         *name = strdata(gco2str(proto_kgc(pt, ~(ptrdiff_t)bc_c(ins))));
  254.         if (ip > proto_bc(pt)) {
  255.           BCIns insp = ip[-1];
  256.           if (bc_op(insp) == BC_MOV && bc_a(insp) == ra+1+LJ_FR2 &&
  257.               bc_d(insp) == bc_b(ins))
  258.             return "method";
  259.         }
  260.         return "field";
  261.       case BC_UGET:
  262.         *name = lj_debug_uvname(pt, bc_d(ins));
  263.         return "upvalue";
  264.       default:
  265.         return NULL;
  266.       }
  267.     }
  268.   }
  269.   return NULL;
  270. }

  271. /* Deduce function name from caller of a frame. */
  272. const char *lj_debug_funcname(lua_State *L, cTValue *frame, const char **name)
  273. {
  274.   cTValue *pframe;
  275.   GCfunc *fn;
  276.   BCPos pc;
  277.   if (frame <= tvref(L->stack)+LJ_FR2)
  278.     return NULL;
  279.   if (frame_isvarg(frame))
  280.     frame = frame_prevd(frame);
  281.   pframe = frame_prev(frame);
  282.   fn = frame_func(pframe);
  283.   pc = debug_framepc(L, fn, frame);
  284.   if (pc != NO_BCPOS) {
  285.     GCproto *pt = funcproto(fn);
  286.     const BCIns *ip = &proto_bc(pt)[check_exp(pc < pt->sizebc, pc)];
  287.     MMS mm = bcmode_mm(bc_op(*ip));
  288.     if (mm == MM_call) {
  289.       BCReg slot = bc_a(*ip);
  290.       if (bc_op(*ip) == BC_ITERC) slot -= 3;
  291.       return lj_debug_slotname(pt, ip, slot, name);
  292.     } else if (mm != MM__MAX) {
  293.       *name = strdata(mmname_str(G(L), mm));
  294.       return "metamethod";
  295.     }
  296.   }
  297.   return NULL;
  298. }

  299. /* -- Source code locations ----------------------------------------------- */

  300. /* Generate shortened source name. */
  301. void lj_debug_shortname(char *out, GCstr *str, BCLine line)
  302. {
  303.   const char *src = strdata(str);
  304.   if (*src == '=') {
  305.     strncpy(out, src+1, LUA_IDSIZE);  /* Remove first char. */
  306.     out[LUA_IDSIZE-1] = '\0'/* Ensures null termination. */
  307.   } else if (*src == '@') {  /* Output "source", or "...source". */
  308.     size_t len = str->len-1;
  309.     src++;  /* Skip the `@' */
  310.     if (len >= LUA_IDSIZE) {
  311.       src += len-(LUA_IDSIZE-4);  /* Get last part of file name. */
  312.       *out++ = '.'; *out++ = '.'; *out++ = '.';
  313.     }
  314.     strcpy(out, src);
  315.   } else/* Output [string "string"] or [builtin:name]. */
  316.     size_t len;  /* Length, up to first control char. */
  317.     for (len = 0; len < LUA_IDSIZE-12; len++)
  318.       if (((const unsigned char *)src)[len] < ' ') break;
  319.     strcpy(out, line == ~(BCLine)0 ? "[builtin:" : "[string \""); out += 9;
  320.     if (src[len] != '\0') {  /* Must truncate? */
  321.       if (len > LUA_IDSIZE-15) len = LUA_IDSIZE-15;
  322.       strncpy(out, src, len); out += len;
  323.       strcpy(out, "..."); out += 3;
  324.     } else {
  325.       strcpy(out, src); out += len;
  326.     }
  327.     strcpy(out, line == ~(BCLine)0 ? "]" : "\"]");
  328.   }
  329. }

  330. /* Add current location of a frame to error message. */
  331. void lj_debug_addloc(lua_State *L, const char *msg,
  332.                      cTValue *frame, cTValue *nextframe)
  333. {
  334.   if (frame) {
  335.     GCfunc *fn = frame_func(frame);
  336.     if (isluafunc(fn)) {
  337.       BCLine line = debug_frameline(L, fn, nextframe);
  338.       if (line >= 0) {
  339.         GCproto *pt = funcproto(fn);
  340.         char buf[LUA_IDSIZE];
  341.         lj_debug_shortname(buf, proto_chunkname(pt), pt->firstline);
  342.         lj_strfmt_pushf(L, "%s:%d: %s", buf, line, msg);
  343.         return;
  344.       }
  345.     }
  346.   }
  347.   lj_strfmt_pushf(L, "%s", msg);
  348. }

  349. /* Push location string for a bytecode position to Lua stack. */
  350. void lj_debug_pushloc(lua_State *L, GCproto *pt, BCPos pc)
  351. {
  352.   GCstr *name = proto_chunkname(pt);
  353.   const char *s = strdata(name);
  354.   MSize i, len = name->len;
  355.   BCLine line = lj_debug_line(pt, pc);
  356.   if (pt->firstline == ~(BCLine)0) {
  357.     lj_strfmt_pushf(L, "builtin:%s", s);
  358.   } else if (*s == '@') {
  359.     s++; len--;
  360.     for (i = len; i > 0; i--)
  361.       if (s[i] == '/' || s[i] == '\\') {
  362.         s += i+1;
  363.         break;
  364.       }
  365.     lj_strfmt_pushf(L, "%s:%d", s, line);
  366.   } else if (len > 40) {
  367.     lj_strfmt_pushf(L, "%p:%d", pt, line);
  368.   } else if (*s == '=') {
  369.     lj_strfmt_pushf(L, "%s:%d", s+1, line);
  370.   } else {
  371.     lj_strfmt_pushf(L, "\"%s\":%d", s, line);
  372.   }
  373. }

  374. /* -- Public debug API ---------------------------------------------------- */

  375. /* lua_getupvalue() and lua_setupvalue() are in lj_api.c. */

  376. LUA_API const char *lua_getlocal(lua_State *L, const lua_Debug *ar, int n)
  377. {
  378.   const char *name = NULL;
  379.   if (ar) {
  380.     TValue *o = debug_localname(L, ar, &name, (BCReg)n);
  381.     if (name) {
  382.       copyTV(L, L->top, o);
  383.       incr_top(L);
  384.     }
  385.   } else if (tvisfunc(L->top-1) && isluafunc(funcV(L->top-1))) {
  386.     name = debug_varname(funcproto(funcV(L->top-1)), 0, (BCReg)n-1);
  387.   }
  388.   return name;
  389. }

  390. LUA_API const char *lua_setlocal(lua_State *L, const lua_Debug *ar, int n)
  391. {
  392.   const char *name = NULL;
  393.   TValue *o = debug_localname(L, ar, &name, (BCReg)n);
  394.   if (name)
  395.     copyTV(L, o, L->top-1);
  396.   L->top--;
  397.   return name;
  398. }

  399. int lj_debug_getinfo(lua_State *L, const char *what, lj_Debug *ar, int ext)
  400. {
  401.   int opt_f = 0, opt_L = 0;
  402.   TValue *frame = NULL;
  403.   TValue *nextframe = NULL;
  404.   GCfunc *fn;
  405.   if (*what == '>') {
  406.     TValue *func = L->top - 1;
  407.     api_check(L, tvisfunc(func));
  408.     fn = funcV(func);
  409.     L->top--;
  410.     what++;
  411.   } else {
  412.     uint32_t offset = (uint32_t)ar->i_ci & 0xffff;
  413.     uint32_t size = (uint32_t)ar->i_ci >> 16;
  414.     lua_assert(offset != 0);
  415.     frame = tvref(L->stack) + offset;
  416.     if (size) nextframe = frame + size;
  417.     lua_assert(frame <= tvref(L->maxstack) &&
  418.                (!nextframe || nextframe <= tvref(L->maxstack)));
  419.     fn = frame_func(frame);
  420.     lua_assert(fn->c.gct == ~LJ_TFUNC);
  421.   }
  422.   for (; *what; what++) {
  423.     if (*what == 'S') {
  424.       if (isluafunc(fn)) {
  425.         GCproto *pt = funcproto(fn);
  426.         BCLine firstline = pt->firstline;
  427.         GCstr *name = proto_chunkname(pt);
  428.         ar->source = strdata(name);
  429.         lj_debug_shortname(ar->short_src, name, pt->firstline);
  430.         ar->linedefined = (int)firstline;
  431.         ar->lastlinedefined = (int)(firstline + pt->numline);
  432.         ar->what = (firstline || !pt->numline) ? "Lua" : "main";
  433.       } else {
  434.         ar->source = "=[C]";
  435.         ar->short_src[0] = '[';
  436.         ar->short_src[1] = 'C';
  437.         ar->short_src[2] = ']';
  438.         ar->short_src[3] = '\0';
  439.         ar->linedefined = -1;
  440.         ar->lastlinedefined = -1;
  441.         ar->what = "C";
  442.       }
  443.     } else if (*what == 'l') {
  444.       ar->currentline = frame ? debug_frameline(L, fn, nextframe) : -1;
  445.     } else if (*what == 'u') {
  446.       ar->nups = fn->c.nupvalues;
  447.       if (ext) {
  448.         if (isluafunc(fn)) {
  449.           GCproto *pt = funcproto(fn);
  450.           ar->nparams = pt->numparams;
  451.           ar->isvararg = !!(pt->flags & PROTO_VARARG);
  452.         } else {
  453.           ar->nparams = 0;
  454.           ar->isvararg = 1;
  455.         }
  456.       }
  457.     } else if (*what == 'n') {
  458.       ar->namewhat = frame ? lj_debug_funcname(L, frame, &ar->name) : NULL;
  459.       if (ar->namewhat == NULL) {
  460.         ar->namewhat = "";
  461.         ar->name = NULL;
  462.       }
  463.     } else if (*what == 'f') {
  464.       opt_f = 1;
  465.     } else if (*what == 'L') {
  466.       opt_L = 1;
  467.     } else {
  468.       return 0/* Bad option. */
  469.     }
  470.   }
  471.   if (opt_f) {
  472.     setfuncV(L, L->top, fn);
  473.     incr_top(L);
  474.   }
  475.   if (opt_L) {
  476.     if (isluafunc(fn)) {
  477.       GCtab *t = lj_tab_new(L, 0, 0);
  478.       GCproto *pt = funcproto(fn);
  479.       const void *lineinfo = proto_lineinfo(pt);
  480.       if (lineinfo) {
  481.         BCLine first = pt->firstline;
  482.         int sz = pt->numline < 256 ? 1 : pt->numline < 65536 ? 2 : 4;
  483.         MSize i, szl = pt->sizebc-1;
  484.         for (i = 0; i < szl; i++) {
  485.           BCLine line = first +
  486.             (sz == 1 ? (BCLine)((const uint8_t *)lineinfo)[i] :
  487.              sz == 2 ? (BCLine)((const uint16_t *)lineinfo)[i] :
  488.              (BCLine)((const uint32_t *)lineinfo)[i]);
  489.           setboolV(lj_tab_setint(L, t, line), 1);
  490.         }
  491.       }
  492.       settabV(L, L->top, t);
  493.     } else {
  494.       setnilV(L->top);
  495.     }
  496.     incr_top(L);
  497.   }
  498.   return 1/* Ok. */
  499. }

  500. LUA_API int lua_getinfo(lua_State *L, const char *what, lua_Debug *ar)
  501. {
  502.   return lj_debug_getinfo(L, what, (lj_Debug *)ar, 0);
  503. }

  504. LUA_API int lua_getstack(lua_State *L, int level, lua_Debug *ar)
  505. {
  506.   int size;
  507.   cTValue *frame = lj_debug_frame(L, level, &size);
  508.   if (frame) {
  509.     ar->i_ci = (size << 16) + (int)(frame - tvref(L->stack));
  510.     return 1;
  511.   } else {
  512.     ar->i_ci = level - size;
  513.     return 0;
  514.   }
  515. }

  516. #if LJ_HASPROFILE
  517. /* Put the chunkname into a buffer. */
  518. static int debug_putchunkname(SBuf *sb, GCproto *pt, int pathstrip)
  519. {
  520.   GCstr *name = proto_chunkname(pt);
  521.   const char *p = strdata(name);
  522.   if (pt->firstline == ~(BCLine)0) {
  523.     lj_buf_putmem(sb, "[builtin:", 9);
  524.     lj_buf_putstr(sb, name);
  525.     lj_buf_putb(sb, ']');
  526.     return 0;
  527.   }
  528.   if (*p == '=' || *p == '@') {
  529.     MSize len = name->len-1;
  530.     p++;
  531.     if (pathstrip) {
  532.       int i;
  533.       for (i = len-1; i >= 0; i--)
  534.         if (p[i] == '/' || p[i] == '\\') {
  535.           len -= i+1;
  536.           p = p+i+1;
  537.           break;
  538.         }
  539.     }
  540.     lj_buf_putmem(sb, p, len);
  541.   } else {
  542.     lj_buf_putmem(sb, "[string]", 8);
  543.   }
  544.   return 1;
  545. }

  546. /* Put a compact stack dump into a buffer. */
  547. void lj_debug_dumpstack(lua_State *L, SBuf *sb, const char *fmt, int depth)
  548. {
  549.   int level = 0, dir = 1, pathstrip = 1;
  550.   MSize lastlen = 0;
  551.   if (depth < 0) { level = ~depth; depth = dir = -1; }  /* Reverse frames. */
  552.   while (level != depth) {  /* Loop through all frame. */
  553.     int size;
  554.     cTValue *frame = lj_debug_frame(L, level, &size);
  555.     if (frame) {
  556.       cTValue *nextframe = size ? frame+size : NULL;
  557.       GCfunc *fn = frame_func(frame);
  558.       const uint8_t *p = (const uint8_t *)fmt;
  559.       int c;
  560.       while ((c = *p++)) {
  561.         switch (c) {
  562.         case 'p'/* Preserve full path. */
  563.           pathstrip = 0;
  564.           break;
  565.         case 'F': case 'f': {  /* Dump function name. */
  566.           const char *name;
  567.           const char *what = lj_debug_funcname(L, frame, &name);
  568.           if (what) {
  569.             if (c == 'F' && isluafunc(fn)) {  /* Dump module:name for 'F'. */
  570.               GCproto *pt = funcproto(fn);
  571.               if (pt->firstline != ~(BCLine)0) {  /* Not a bytecode builtin. */
  572.                 debug_putchunkname(sb, pt, pathstrip);
  573.                 lj_buf_putb(sb, ':');
  574.               }
  575.             }
  576.             lj_buf_putmem(sb, name, (MSize)strlen(name));
  577.             break;
  578.           }  /* else: can't derive a name, dump module:line. */
  579.           }
  580.           /* fallthrough */
  581.         case 'l'/* Dump module:line. */
  582.           if (isluafunc(fn)) {
  583.             GCproto *pt = funcproto(fn);
  584.             if (debug_putchunkname(sb, pt, pathstrip)) {
  585.               /* Regular Lua function. */
  586.               BCLine line = c == 'l' ? debug_frameline(L, fn, nextframe) :
  587.                                        pt->firstline;
  588.               lj_buf_putb(sb, ':');
  589.               lj_strfmt_putint(sb, line >= 0 ? line : pt->firstline);
  590.             }
  591.           } else if (isffunc(fn)) {  /* Dump numbered builtins. */
  592.             lj_buf_putmem(sb, "[builtin#", 9);
  593.             lj_strfmt_putint(sb, fn->c.ffid);
  594.             lj_buf_putb(sb, ']');
  595.           } else/* Dump C function address. */
  596.             lj_buf_putb(sb, '@');
  597.             lj_strfmt_putptr(sb, fn->c.f);
  598.           }
  599.           break;
  600.         case 'Z'/* Zap trailing separator. */
  601.           lastlen = sbuflen(sb);
  602.           break;
  603.         default:
  604.           lj_buf_putb(sb, c);
  605.           break;
  606.         }
  607.       }
  608.     } else if (dir == 1) {
  609.       break;
  610.     } else {
  611.       level -= size;  /* Reverse frame order: quickly skip missing level. */
  612.     }
  613.     level += dir;
  614.   }
  615.   if (lastlen)
  616.     setsbufP(sb, sbufB(sb) + lastlen);  /* Zap trailing separator. */
  617. }
  618. #endif

  619. /* Number of frames for the leading and trailing part of a traceback. */
  620. #define TRACEBACK_LEVELS1        12
  621. #define TRACEBACK_LEVELS2        10

  622. LUALIB_API void luaL_traceback (lua_State *L, lua_State *L1, const char *msg,
  623.                                 int level)
  624. {
  625.   int top = (int)(L->top - L->base);
  626.   int lim = TRACEBACK_LEVELS1;
  627.   lua_Debug ar;
  628.   if (msg) lua_pushfstring(L, "%s\n", msg);
  629.   lua_pushliteral(L, "stack traceback:");
  630.   while (lua_getstack(L1, level++, &ar)) {
  631.     GCfunc *fn;
  632.     if (level > lim) {
  633.       if (!lua_getstack(L1, level + TRACEBACK_LEVELS2, &ar)) {
  634.         level--;
  635.       } else {
  636.         lua_pushliteral(L, "\n\t...");
  637.         lua_getstack(L1, -10, &ar);
  638.         level = ar.i_ci - TRACEBACK_LEVELS2;
  639.       }
  640.       lim = 2147483647;
  641.       continue;
  642.     }
  643.     lua_getinfo(L1, "Snlf", &ar);
  644.     fn = funcV(L1->top-1); L1->top--;
  645.     if (isffunc(fn) && !*ar.namewhat)
  646.       lua_pushfstring(L, "\n\t[builtin#%d]:", fn->c.ffid);
  647.     else
  648.       lua_pushfstring(L, "\n\t%s:", ar.short_src);
  649.     if (ar.currentline > 0)
  650.       lua_pushfstring(L, "%d:", ar.currentline);
  651.     if (*ar.namewhat) {
  652.       lua_pushfstring(L, " in function " LUA_QS, ar.name);
  653.     } else {
  654.       if (*ar.what == 'm') {
  655.         lua_pushliteral(L, " in main chunk");
  656.       } else if (*ar.what == 'C') {
  657.         lua_pushfstring(L, " at %p", fn->c.f);
  658.       } else {
  659.         lua_pushfstring(L, " in function <%s:%d>",
  660.                         ar.short_src, ar.linedefined);
  661.       }
  662.     }
  663.     if ((int)(L->top - L->base) - top >= 15)
  664.       lua_concat(L, (int)(L->top - L->base) - top);
  665.   }
  666.   lua_concat(L, (int)(L->top - L->base) - top);
  667. }