root/lj_debug.c

/* [<][>][^][v][top][bottom][index][help] */

DEFINITIONS

This source file includes following definitions.
  1. lj_debug_frame
  2. debug_framepc
  3. lj_debug_line
  4. debug_frameline
  5. debug_read_uleb128
  6. debug_varname
  7. debug_localname
  8. lj_debug_uvname
  9. lj_debug_uvnamev
  10. lj_debug_slotname
  11. lj_debug_funcname
  12. lj_debug_shortname
  13. lj_debug_addloc
  14. lj_debug_pushloc
  15. lua_getlocal
  16. lua_setlocal
  17. lj_debug_getinfo
  18. lua_getinfo
  19. lua_getstack
  20. luaL_traceback

   1 /*
   2 ** Debugging and introspection.
   3 ** Copyright (C) 2005-2017 Mike Pall. See Copyright Notice in luajit.h
   4 */
   5 
   6 #define lj_debug_c
   7 #define LUA_CORE
   8 
   9 #include "lj_obj.h"
  10 #include "lj_err.h"
  11 #include "lj_debug.h"
  12 #include "lj_str.h"
  13 #include "lj_tab.h"
  14 #include "lj_state.h"
  15 #include "lj_frame.h"
  16 #include "lj_bc.h"
  17 #include "lj_vm.h"
  18 #if LJ_HASJIT
  19 #include "lj_jit.h"
  20 #endif
  21 
  22 /* -- Frames -------------------------------------------------------------- */
  23 
  24 /* Get frame corresponding to a level. */
  25 cTValue *lj_debug_frame(lua_State *L, int level, int *size)
  26 {
  27   cTValue *frame, *nextframe, *bot = tvref(L->stack);
  28   /* Traverse frames backwards. */
  29   for (nextframe = frame = L->base-1; frame > bot; ) {
  30     if (frame_gc(frame) == obj2gco(L))
  31       level++;  /* Skip dummy frames. See lj_meta_call(). */
  32     if (level-- == 0) {
  33       *size = (int)(nextframe - frame);
  34       return frame;  /* Level found. */
  35     }
  36     nextframe = frame;
  37     if (frame_islua(frame)) {
  38       frame = frame_prevl(frame);
  39     } else {
  40       if (frame_isvarg(frame))
  41         level++;  /* Skip vararg pseudo-frame. */
  42       frame = frame_prevd(frame);
  43     }
  44   }
  45   *size = level;
  46   return NULL;  /* Level not found. */
  47 }
  48 
  49 /* Invalid bytecode position. */
  50 #define NO_BCPOS        (~(BCPos)0)
  51 
  52 /* Return bytecode position for function/frame or NO_BCPOS. */
  53 static BCPos debug_framepc(lua_State *L, GCfunc *fn, cTValue *nextframe)
  54 {
  55   const BCIns *ins;
  56   GCproto *pt;
  57   BCPos pos;
  58   lua_assert(fn->c.gct == ~LJ_TFUNC || fn->c.gct == ~LJ_TTHREAD);
  59   if (!isluafunc(fn)) {  /* Cannot derive a PC for non-Lua functions. */
  60     return NO_BCPOS;
  61   } else if (nextframe == NULL) {  /* Lua function on top. */
  62     void *cf = cframe_raw(L->cframe);
  63     if (cf == NULL || (char *)cframe_pc(cf) == (char *)cframe_L(cf))
  64       return NO_BCPOS;
  65     ins = cframe_pc(cf);  /* Only happens during error/hook handling. */
  66   } else {
  67     if (frame_islua(nextframe)) {
  68       ins = frame_pc(nextframe);
  69     } else if (frame_iscont(nextframe)) {
  70       ins = frame_contpc(nextframe);
  71     } else {
  72       /* Lua function below errfunc/gc/hook: find cframe to get the PC. */
  73       void *cf = cframe_raw(L->cframe);
  74       TValue *f = L->base-1;
  75       for (;;) {
  76         if (cf == NULL)
  77           return NO_BCPOS;
  78         while (cframe_nres(cf) < 0) {
  79           if (f >= restorestack(L, -cframe_nres(cf)))
  80             break;
  81           cf = cframe_raw(cframe_prev(cf));
  82           if (cf == NULL)
  83             return NO_BCPOS;
  84         }
  85         if (f < nextframe)
  86           break;
  87         if (frame_islua(f)) {
  88           f = frame_prevl(f);
  89         } else {
  90           if (frame_isc(f) || (LJ_HASFFI && frame_iscont(f) &&
  91                                (f-1)->u32.lo == LJ_CONT_FFI_CALLBACK))
  92             cf = cframe_raw(cframe_prev(cf));
  93           f = frame_prevd(f);
  94         }
  95       }
  96       ins = cframe_pc(cf);
  97     }
  98   }
  99   pt = funcproto(fn);
 100   pos = proto_bcpos(pt, ins) - 1;
 101 #if LJ_HASJIT
 102   if (pos > pt->sizebc) {  /* Undo the effects of lj_trace_exit for JLOOP. */
 103     GCtrace *T = (GCtrace *)((char *)(ins-1) - offsetof(GCtrace, startins));
 104     lua_assert(bc_isret(bc_op(ins[-1])));
 105     pos = proto_bcpos(pt, mref(T->startpc, const BCIns));
 106   }
 107 #endif
 108   return pos;
 109 }
 110 
 111 /* -- Line numbers -------------------------------------------------------- */
 112 
 113 /* Get line number for a bytecode position. */
 114 BCLine LJ_FASTCALL lj_debug_line(GCproto *pt, BCPos pc)
 115 {
 116   const void *lineinfo = proto_lineinfo(pt);
 117   if (pc <= pt->sizebc && lineinfo) {
 118     BCLine first = pt->firstline;
 119     if (pc == pt->sizebc) return first + pt->numline;
 120     if (pc-- == 0) return first;
 121     if (pt->numline < 256)
 122       return first + (BCLine)((const uint8_t *)lineinfo)[pc];
 123     else if (pt->numline < 65536)
 124       return first + (BCLine)((const uint16_t *)lineinfo)[pc];
 125     else
 126       return first + (BCLine)((const uint32_t *)lineinfo)[pc];
 127   }
 128   return 0;
 129 }
 130 
 131 /* Get line number for function/frame. */
 132 static BCLine debug_frameline(lua_State *L, GCfunc *fn, cTValue *nextframe)
 133 {
 134   BCPos pc = debug_framepc(L, fn, nextframe);
 135   if (pc != NO_BCPOS) {
 136     GCproto *pt = funcproto(fn);
 137     lua_assert(pc <= pt->sizebc);
 138     return lj_debug_line(pt, pc);
 139   }
 140   return -1;
 141 }
 142 
 143 /* -- Variable names ------------------------------------------------------ */
 144 
 145 /* Read ULEB128 value. */
 146 static uint32_t debug_read_uleb128(const uint8_t **pp)
 147 {
 148   const uint8_t *p = *pp;
 149   uint32_t v = *p++;
 150   if (LJ_UNLIKELY(v >= 0x80)) {
 151     int sh = 0;
 152     v &= 0x7f;
 153     do { v |= ((*p & 0x7f) << (sh += 7)); } while (*p++ >= 0x80);
 154   }
 155   *pp = p;
 156   return v;
 157 }
 158 
 159 /* Get name of a local variable from slot number and PC. */
 160 static const char *debug_varname(const GCproto *pt, BCPos pc, BCReg slot)
 161 {
 162   const uint8_t *p = proto_varinfo(pt);
 163   if (p) {
 164     BCPos lastpc = 0;
 165     for (;;) {
 166       const char *name = (const char *)p;
 167       uint32_t vn = *p++;
 168       BCPos startpc, endpc;
 169       if (vn < VARNAME__MAX) {
 170         if (vn == VARNAME_END) break;  /* End of varinfo. */
 171       } else {
 172         while (*p++) ;  /* Skip over variable name string. */
 173       }
 174       lastpc = startpc = lastpc + debug_read_uleb128(&p);
 175       if (startpc > pc) break;
 176       endpc = startpc + debug_read_uleb128(&p);
 177       if (pc < endpc && slot-- == 0) {
 178         if (vn < VARNAME__MAX) {
 179 #define VARNAMESTR(name, str)   str "\0"
 180           name = VARNAMEDEF(VARNAMESTR);
 181 #undef VARNAMESTR
 182           if (--vn) while (*name++ || --vn) ;
 183         }
 184         return name;
 185       }
 186     }
 187   }
 188   return NULL;
 189 }
 190 
 191 /* Get name of local variable from 1-based slot number and function/frame. */
 192 static TValue *debug_localname(lua_State *L, const lua_Debug *ar,
 193                                const char **name, BCReg slot1)
 194 {
 195   uint32_t offset = (uint32_t)ar->i_ci & 0xffff;
 196   uint32_t size = (uint32_t)ar->i_ci >> 16;
 197   TValue *frame = tvref(L->stack) + offset;
 198   TValue *nextframe = size ? frame + size : NULL;
 199   GCfunc *fn = frame_func(frame);
 200   BCPos pc = debug_framepc(L, fn, nextframe);
 201   if (!nextframe) nextframe = L->top;
 202   if ((int)slot1 < 0) {  /* Negative slot number is for varargs. */
 203     if (pc != NO_BCPOS) {
 204       GCproto *pt = funcproto(fn);
 205       if ((pt->flags & PROTO_VARARG)) {
 206         slot1 = pt->numparams + (BCReg)(-(int)slot1);
 207         if (frame_isvarg(frame)) {  /* Vararg frame has been set up? (pc!=0) */
 208           nextframe = frame;
 209           frame = frame_prevd(frame);
 210         }
 211         if (frame + slot1 < nextframe) {
 212           *name = "(*vararg)";
 213           return frame+slot1;
 214         }
 215       }
 216     }
 217     return NULL;
 218   }
 219   if (pc != NO_BCPOS &&
 220       (*name = debug_varname(funcproto(fn), pc, slot1-1)) != NULL)
 221     ;
 222   else if (slot1 > 0 && frame + slot1 < nextframe)
 223     *name = "(*temporary)";
 224   return frame+slot1;
 225 }
 226 
 227 /* Get name of upvalue. */
 228 const char *lj_debug_uvname(GCproto *pt, uint32_t idx)
 229 {
 230   const uint8_t *p = proto_uvinfo(pt);
 231   lua_assert(idx < pt->sizeuv);
 232   if (!p) return "";
 233   if (idx) while (*p++ || --idx) ;
 234   return (const char *)p;
 235 }
 236 
 237 /* Get name and value of upvalue. */
 238 const char *lj_debug_uvnamev(cTValue *o, uint32_t idx, TValue **tvp)
 239 {
 240   if (tvisfunc(o)) {
 241     GCfunc *fn = funcV(o);
 242     if (isluafunc(fn)) {
 243       GCproto *pt = funcproto(fn);
 244       if (idx < pt->sizeuv) {
 245         *tvp = uvval(&gcref(fn->l.uvptr[idx])->uv);
 246         return lj_debug_uvname(pt, idx);
 247       }
 248     } else {
 249       if (idx < fn->c.nupvalues) {
 250         *tvp = &fn->c.upvalue[idx];
 251         return "";
 252       }
 253     }
 254   }
 255   return NULL;
 256 }
 257 
 258 /* Deduce name of an object from slot number and PC. */
 259 const char *lj_debug_slotname(GCproto *pt, const BCIns *ip, BCReg slot,
 260                               const char **name)
 261 {
 262   const char *lname;
 263 restart:
 264   lname = debug_varname(pt, proto_bcpos(pt, ip), slot);
 265   if (lname != NULL) { *name = lname; return "local"; }
 266   while (--ip > proto_bc(pt)) {
 267     BCIns ins = *ip;
 268     BCOp op = bc_op(ins);
 269     BCReg ra = bc_a(ins);
 270     if (bcmode_a(op) == BCMbase) {
 271       if (slot >= ra && (op != BC_KNIL || slot <= bc_d(ins)))
 272         return NULL;
 273     } else if (bcmode_a(op) == BCMdst && ra == slot) {
 274       switch (bc_op(ins)) {
 275       case BC_MOV:
 276         if (ra == slot) { slot = bc_d(ins); goto restart; }
 277         break;
 278       case BC_GGET:
 279         *name = strdata(gco2str(proto_kgc(pt, ~(ptrdiff_t)bc_d(ins))));
 280         return "global";
 281       case BC_TGETS:
 282         *name = strdata(gco2str(proto_kgc(pt, ~(ptrdiff_t)bc_c(ins))));
 283         if (ip > proto_bc(pt)) {
 284           BCIns insp = ip[-1];
 285           if (bc_op(insp) == BC_MOV && bc_a(insp) == ra+1 &&
 286               bc_d(insp) == bc_b(ins))
 287             return "method";
 288         }
 289         return "field";
 290       case BC_UGET:
 291         *name = lj_debug_uvname(pt, bc_d(ins));
 292         return "upvalue";
 293       default:
 294         return NULL;
 295       }
 296     }
 297   }
 298   return NULL;
 299 }
 300 
 301 /* Deduce function name from caller of a frame. */
 302 const char *lj_debug_funcname(lua_State *L, TValue *frame, const char **name)
 303 {
 304   TValue *pframe;
 305   GCfunc *fn;
 306   BCPos pc;
 307   if (frame <= tvref(L->stack))
 308     return NULL;
 309   if (frame_isvarg(frame))
 310     frame = frame_prevd(frame);
 311   pframe = frame_prev(frame);
 312   fn = frame_func(pframe);
 313   pc = debug_framepc(L, fn, frame);
 314   if (pc != NO_BCPOS) {
 315     GCproto *pt = funcproto(fn);
 316     const BCIns *ip = &proto_bc(pt)[check_exp(pc < pt->sizebc, pc)];
 317     MMS mm = bcmode_mm(bc_op(*ip));
 318     if (mm == MM_call) {
 319       BCReg slot = bc_a(*ip);
 320       if (bc_op(*ip) == BC_ITERC) slot -= 3;
 321       return lj_debug_slotname(pt, ip, slot, name);
 322     } else if (mm != MM__MAX) {
 323       *name = strdata(mmname_str(G(L), mm));
 324       return "metamethod";
 325     }
 326   }
 327   return NULL;
 328 }
 329 
 330 /* -- Source code locations ----------------------------------------------- */
 331 
 332 /* Generate shortened source name. */
 333 void lj_debug_shortname(char *out, GCstr *str)
 334 {
 335   const char *src = strdata(str);
 336   if (*src == '=') {
 337     strncpy(out, src+1, LUA_IDSIZE);  /* Remove first char. */
 338     out[LUA_IDSIZE-1] = '\0';  /* Ensures null termination. */
 339   } else if (*src == '@') {  /* Output "source", or "...source". */
 340     size_t len = str->len-1;
 341     src++;  /* Skip the `@' */
 342     if (len >= LUA_IDSIZE) {
 343       src += len-(LUA_IDSIZE-4);  /* Get last part of file name. */
 344       *out++ = '.'; *out++ = '.'; *out++ = '.';
 345     }
 346     strcpy(out, src);
 347   } else {  /* Output [string "string"]. */
 348     size_t len;  /* Length, up to first control char. */
 349     for (len = 0; len < LUA_IDSIZE-12; len++)
 350       if (((const unsigned char *)src)[len] < ' ') break;
 351     strcpy(out, "[string \""); out += 9;
 352     if (src[len] != '\0') {  /* Must truncate? */
 353       if (len > LUA_IDSIZE-15) len = LUA_IDSIZE-15;
 354       strncpy(out, src, len); out += len;
 355       strcpy(out, "..."); out += 3;
 356     } else {
 357       strcpy(out, src); out += len;
 358     }
 359     strcpy(out, "\"]");
 360   }
 361 }
 362 
 363 /* Add current location of a frame to error message. */
 364 void lj_debug_addloc(lua_State *L, const char *msg,
 365                      cTValue *frame, cTValue *nextframe)
 366 {
 367   if (frame) {
 368     GCfunc *fn = frame_func(frame);
 369     if (isluafunc(fn)) {
 370       BCLine line = debug_frameline(L, fn, nextframe);
 371       if (line >= 0) {
 372         char buf[LUA_IDSIZE];
 373         lj_debug_shortname(buf, proto_chunkname(funcproto(fn)));
 374         lj_str_pushf(L, "%s:%d: %s", buf, line, msg);
 375         return;
 376       }
 377     }
 378   }
 379   lj_str_pushf(L, "%s", msg);
 380 }
 381 
 382 /* Push location string for a bytecode position to Lua stack. */
 383 void lj_debug_pushloc(lua_State *L, GCproto *pt, BCPos pc)
 384 {
 385   GCstr *name = proto_chunkname(pt);
 386   const char *s = strdata(name);
 387   MSize i, len = name->len;
 388   BCLine line = lj_debug_line(pt, pc);
 389   if (*s == '@') {
 390     s++; len--;
 391     for (i = len; i > 0; i--)
 392       if (s[i] == '/' || s[i] == '\\') {
 393         s += i+1;
 394         break;
 395       }
 396     lj_str_pushf(L, "%s:%d", s, line);
 397   } else if (len > 40) {
 398     lj_str_pushf(L, "%p:%d", pt, line);
 399   } else if (*s == '=') {
 400     lj_str_pushf(L, "%s:%d", s+1, line);
 401   } else {
 402     lj_str_pushf(L, "\"%s\":%d", s, line);
 403   }
 404 }
 405 
 406 /* -- Public debug API ---------------------------------------------------- */
 407 
 408 /* lua_getupvalue() and lua_setupvalue() are in lj_api.c. */
 409 
 410 LUA_API const char *lua_getlocal(lua_State *L, const lua_Debug *ar, int n)
 411 {
 412   const char *name = NULL;
 413   if (ar) {
 414     TValue *o = debug_localname(L, ar, &name, (BCReg)n);
 415     if (name) {
 416       copyTV(L, L->top, o);
 417       incr_top(L);
 418     }
 419   } else if (tvisfunc(L->top-1) && isluafunc(funcV(L->top-1))) {
 420     name = debug_varname(funcproto(funcV(L->top-1)), 0, (BCReg)n-1);
 421   }
 422   return name;
 423 }
 424 
 425 LUA_API const char *lua_setlocal(lua_State *L, const lua_Debug *ar, int n)
 426 {
 427   const char *name = NULL;
 428   TValue *o = debug_localname(L, ar, &name, (BCReg)n);
 429   if (name)
 430     copyTV(L, o, L->top-1);
 431   L->top--;
 432   return name;
 433 }
 434 
 435 int lj_debug_getinfo(lua_State *L, const char *what, lj_Debug *ar, int ext)
 436 {
 437   int opt_f = 0, opt_L = 0;
 438   TValue *frame = NULL;
 439   TValue *nextframe = NULL;
 440   GCfunc *fn;
 441   if (*what == '>') {
 442     TValue *func = L->top - 1;
 443     api_check(L, tvisfunc(func));
 444     fn = funcV(func);
 445     L->top--;
 446     what++;
 447   } else {
 448     uint32_t offset = (uint32_t)ar->i_ci & 0xffff;
 449     uint32_t size = (uint32_t)ar->i_ci >> 16;
 450     lua_assert(offset != 0);
 451     frame = tvref(L->stack) + offset;
 452     if (size) nextframe = frame + size;
 453     lua_assert(frame <= tvref(L->maxstack) &&
 454                (!nextframe || nextframe <= tvref(L->maxstack)));
 455     fn = frame_func(frame);
 456     lua_assert(fn->c.gct == ~LJ_TFUNC);
 457   }
 458   for (; *what; what++) {
 459     if (*what == 'S') {
 460       if (isluafunc(fn)) {
 461         GCproto *pt = funcproto(fn);
 462         BCLine firstline = pt->firstline;
 463         GCstr *name = proto_chunkname(pt);
 464         ar->source = strdata(name);
 465         lj_debug_shortname(ar->short_src, name);
 466         ar->linedefined = (int)firstline;
 467         ar->lastlinedefined = (int)(firstline + pt->numline);
 468         ar->what = (firstline || !pt->numline) ? "Lua" : "main";
 469       } else {
 470         ar->source = "=[C]";
 471         ar->short_src[0] = '[';
 472         ar->short_src[1] = 'C';
 473         ar->short_src[2] = ']';
 474         ar->short_src[3] = '\0';
 475         ar->linedefined = -1;
 476         ar->lastlinedefined = -1;
 477         ar->what = "C";
 478       }
 479     } else if (*what == 'l') {
 480       ar->currentline = frame ? debug_frameline(L, fn, nextframe) : -1;
 481     } else if (*what == 'u') {
 482       ar->nups = fn->c.nupvalues;
 483       if (ext) {
 484         if (isluafunc(fn)) {
 485           GCproto *pt = funcproto(fn);
 486           ar->nparams = pt->numparams;
 487           ar->isvararg = !!(pt->flags & PROTO_VARARG);
 488         } else {
 489           ar->nparams = 0;
 490           ar->isvararg = 1;
 491         }
 492       }
 493     } else if (*what == 'n') {
 494       ar->namewhat = frame ? lj_debug_funcname(L, frame, &ar->name) : NULL;
 495       if (ar->namewhat == NULL) {
 496         ar->namewhat = "";
 497         ar->name = NULL;
 498       }
 499     } else if (*what == 'f') {
 500       opt_f = 1;
 501     } else if (*what == 'L') {
 502       opt_L = 1;
 503     } else {
 504       return 0;  /* Bad option. */
 505     }
 506   }
 507   if (opt_f) {
 508     setfuncV(L, L->top, fn);
 509     incr_top(L);
 510   }
 511   if (opt_L) {
 512     if (isluafunc(fn)) {
 513       GCtab *t = lj_tab_new(L, 0, 0);
 514       GCproto *pt = funcproto(fn);
 515       const void *lineinfo = proto_lineinfo(pt);
 516       if (lineinfo) {
 517         BCLine first = pt->firstline;
 518         int sz = pt->numline < 256 ? 1 : pt->numline < 65536 ? 2 : 4;
 519         MSize i, szl = pt->sizebc-1;
 520         for (i = 0; i < szl; i++) {
 521           BCLine line = first +
 522             (sz == 1 ? (BCLine)((const uint8_t *)lineinfo)[i] :
 523              sz == 2 ? (BCLine)((const uint16_t *)lineinfo)[i] :
 524              (BCLine)((const uint32_t *)lineinfo)[i]);
 525           setboolV(lj_tab_setint(L, t, line), 1);
 526         }
 527       }
 528       settabV(L, L->top, t);
 529     } else {
 530       setnilV(L->top);
 531     }
 532     incr_top(L);
 533   }
 534   return 1;  /* Ok. */
 535 }
 536 
 537 LUA_API int lua_getinfo(lua_State *L, const char *what, lua_Debug *ar)
 538 {
 539   return lj_debug_getinfo(L, what, (lj_Debug *)ar, 0);
 540 }
 541 
 542 LUA_API int lua_getstack(lua_State *L, int level, lua_Debug *ar)
 543 {
 544   int size;
 545   cTValue *frame = lj_debug_frame(L, level, &size);
 546   if (frame) {
 547     ar->i_ci = (size << 16) + (int)(frame - tvref(L->stack));
 548     return 1;
 549   } else {
 550     ar->i_ci = level - size;
 551     return 0;
 552   }
 553 }
 554 
 555 /* Number of frames for the leading and trailing part of a traceback. */
 556 #define TRACEBACK_LEVELS1       12
 557 #define TRACEBACK_LEVELS2       10
 558 
 559 LUALIB_API void luaL_traceback (lua_State *L, lua_State *L1, const char *msg,
 560                                 int level)
 561 {
 562   int top = (int)(L->top - L->base);
 563   int lim = TRACEBACK_LEVELS1;
 564   lua_Debug ar;
 565   if (msg) lua_pushfstring(L, "%s\n", msg);
 566   lua_pushliteral(L, "stack traceback:");
 567   while (lua_getstack(L1, level++, &ar)) {
 568     GCfunc *fn;
 569     if (level > lim) {
 570       if (!lua_getstack(L1, level + TRACEBACK_LEVELS2, &ar)) {
 571         level--;
 572       } else {
 573         lua_pushliteral(L, "\n\t...");
 574         lua_getstack(L1, -10, &ar);
 575         level = ar.i_ci - TRACEBACK_LEVELS2;
 576       }
 577       lim = 2147483647;
 578       continue;
 579     }
 580     lua_getinfo(L1, "Snlf", &ar);
 581     fn = funcV(L1->top-1); L1->top--;
 582     if (isffunc(fn) && !*ar.namewhat)
 583       lua_pushfstring(L, "\n\t[builtin#%d]:", fn->c.ffid);
 584     else
 585       lua_pushfstring(L, "\n\t%s:", ar.short_src);
 586     if (ar.currentline > 0)
 587       lua_pushfstring(L, "%d:", ar.currentline);
 588     if (*ar.namewhat) {
 589       lua_pushfstring(L, " in function " LUA_QS, ar.name);
 590     } else {
 591       if (*ar.what == 'm') {
 592         lua_pushliteral(L, " in main chunk");
 593       } else if (*ar.what == 'C') {
 594         lua_pushfstring(L, " at %p", fn->c.f);
 595       } else {
 596         lua_pushfstring(L, " in function <%s:%d>",
 597                         ar.short_src, ar.linedefined);
 598       }
 599     }
 600     if ((int)(L->top - L->base) - top >= 15)
 601       lua_concat(L, (int)(L->top - L->base) - top);
 602   }
 603   lua_concat(L, (int)(L->top - L->base) - top);
 604 }
 605 

/* [<][>][^][v][top][bottom][index][help] */