summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorMike Pall <mike>2012-10-01 20:45:30 +0200
committerMike Pall <mike>2012-10-01 20:45:30 +0200
commitfcddd5a3a0269f30df0c0da6e9ff89d3e70d0e2c (patch)
tree4bce654a35af804e16eb55324aa92f9ab550a984 /src
parent3ad61689cf11ae73fef5dfe12f7ccb5fe539622e (diff)
downloadluajit-fcddd5a3a0269f30df0c0da6e9ff89d3e70d0e2c.tar.gz
luajit-fcddd5a3a0269f30df0c0da6e9ff89d3e70d0e2c.tar.bz2
luajit-fcddd5a3a0269f30df0c0da6e9ff89d3e70d0e2c.zip
From Lua 5.2: Add luaL_traceback().
Diffstat (limited to 'src')
-rw-r--r--src/lauxlib.h2
-rw-r--r--src/lib_base.c2
-rw-r--r--src/lib_debug.c50
-rw-r--r--src/lj_debug.c51
-rw-r--r--src/luajit.c14
5 files changed, 59 insertions, 60 deletions
diff --git a/src/lauxlib.h b/src/lauxlib.h
index b0f66d68..fed1491b 100644
--- a/src/lauxlib.h
+++ b/src/lauxlib.h
@@ -82,6 +82,8 @@ LUALIB_API int (luaL_loadfilex) (lua_State *L, const char *filename,
82 const char *mode); 82 const char *mode);
83LUALIB_API int (luaL_loadbufferx) (lua_State *L, const char *buff, size_t sz, 83LUALIB_API int (luaL_loadbufferx) (lua_State *L, const char *buff, size_t sz,
84 const char *name, const char *mode); 84 const char *name, const char *mode);
85LUALIB_API void luaL_traceback (lua_State *L, lua_State *L1, const char *msg,
86 int level);
85 87
86 88
87/* 89/*
diff --git a/src/lib_base.c b/src/lib_base.c
index 6f664eb6..568216e1 100644
--- a/src/lib_base.c
+++ b/src/lib_base.c
@@ -320,7 +320,7 @@ LJLIB_ASM(tostring) LJLIB_REC(.)
320 s = strV(lj_lib_upvalue(L, -(int32_t)itype(o))); 320 s = strV(lj_lib_upvalue(L, -(int32_t)itype(o)));
321 } else { 321 } else {
322 if (tvisfunc(o) && isffunc(funcV(o))) 322 if (tvisfunc(o) && isffunc(funcV(o)))
323 lua_pushfstring(L, "function: fast#%d", funcV(o)->c.ffid); 323 lua_pushfstring(L, "function: builtin#%d", funcV(o)->c.ffid);
324 else 324 else
325 lua_pushfstring(L, "%s: %p", lj_typename(o), lua_topointer(L, 1)); 325 lua_pushfstring(L, "%s: %p", lj_typename(o), lua_topointer(L, 1));
326 /* Note: lua_pushfstring calls the GC which may invalidate o. */ 326 /* Note: lua_pushfstring calls the GC which may invalidate o. */
diff --git a/src/lib_debug.c b/src/lib_debug.c
index 07b025af..06750266 100644
--- a/src/lib_debug.c
+++ b/src/lib_debug.c
@@ -383,55 +383,13 @@ LJLIB_CF(debug_debug)
383 383
384LJLIB_CF(debug_traceback) 384LJLIB_CF(debug_traceback)
385{ 385{
386 int level;
387 int firstpart = 1; /* still before eventual `...' */
388 int arg; 386 int arg;
389 lua_State *L1 = getthread(L, &arg); 387 lua_State *L1 = getthread(L, &arg);
390 lua_Debug ar; 388 const char *msg = lua_tostring(L, arg+1);
391 if (lua_isnumber(L, arg+2)) { 389 if (msg == NULL && L->top > L->base+arg)
392 level = (int)lua_tointeger(L, arg+2); 390 L->top = L->base+arg+1;
393 lua_pop(L, 1);
394 }
395 else 391 else
396 level = (L == L1) ? 1 : 0; /* level 0 may be this own function */ 392 luaL_traceback(L, L1, msg, lj_lib_optint(L, arg+2, (L == L1)));
397 if (lua_gettop(L) == arg)
398 lua_pushliteral(L, "");
399 else if (!lua_isstring(L, arg+1)) return 1; /* message is not a string */
400 else lua_pushliteral(L, "\n");
401 lua_pushliteral(L, "stack traceback:");
402 while (lua_getstack(L1, level++, &ar)) {
403 if (level > LEVELS1 && firstpart) {
404 /* no more than `LEVELS2' more levels? */
405 if (!lua_getstack(L1, level+LEVELS2, &ar)) {
406 level--; /* keep going */
407 } else {
408 lua_pushliteral(L, "\n\t..."); /* too many levels */
409 /* This only works with LuaJIT 2.x. Avoids O(n^2) behaviour. */
410 lua_getstack(L1, -10, &ar);
411 level = ar.i_ci - LEVELS2;
412 }
413 firstpart = 0;
414 continue;
415 }
416 lua_pushliteral(L, "\n\t");
417 lua_getinfo(L1, "Snl", &ar);
418 lua_pushfstring(L, "%s:", ar.short_src);
419 if (ar.currentline > 0)
420 lua_pushfstring(L, "%d:", ar.currentline);
421 if (*ar.namewhat != '\0') { /* is there a name? */
422 lua_pushfstring(L, " in function " LUA_QS, ar.name);
423 } else {
424 if (*ar.what == 'm') /* main? */
425 lua_pushfstring(L, " in main chunk");
426 else if (*ar.what == 'C' || *ar.what == 't')
427 lua_pushliteral(L, " ?"); /* C function or tail call */
428 else
429 lua_pushfstring(L, " in function <%s:%d>",
430 ar.short_src, ar.linedefined);
431 }
432 lua_concat(L, lua_gettop(L) - arg);
433 }
434 lua_concat(L, lua_gettop(L) - arg);
435 return 1; 393 return 1;
436} 394}
437 395
diff --git a/src/lj_debug.c b/src/lj_debug.c
index 0e26cd7c..4f4c4bb1 100644
--- a/src/lj_debug.c
+++ b/src/lj_debug.c
@@ -543,3 +543,54 @@ LUA_API int lua_getstack(lua_State *L, int level, lua_Debug *ar)
543 } 543 }
544} 544}
545 545
546/* Number of frames for the leading and trailing part of a traceback. */
547#define TRACEBACK_LEVELS1 12
548#define TRACEBACK_LEVELS2 10
549
550LUALIB_API void luaL_traceback (lua_State *L, lua_State *L1, const char *msg,
551 int level)
552{
553 int top = (int)(L->top - L->base);
554 int lim = TRACEBACK_LEVELS1;
555 lua_Debug ar;
556 if (msg) lua_pushfstring(L, "%s\n", msg);
557 lua_pushliteral(L, "stack traceback:");
558 while (lua_getstack(L1, level++, &ar)) {
559 GCfunc *fn;
560 if (level > lim) {
561 if (!lua_getstack(L1, level + TRACEBACK_LEVELS2, &ar)) {
562 level--;
563 } else {
564 lua_pushliteral(L, "\n\t...");
565 lua_getstack(L1, -10, &ar);
566 level = ar.i_ci - TRACEBACK_LEVELS2;
567 }
568 lim = 2147483647;
569 continue;
570 }
571 lua_getinfo(L1, "Snlf", &ar);
572 fn = funcV(L1->top-1); L1->top--;
573 if (isffunc(fn) && !*ar.namewhat)
574 lua_pushfstring(L, "\n\t[builtin#%d]:", fn->c.ffid);
575 else
576 lua_pushfstring(L, "\n\t%s:", ar.short_src);
577 if (ar.currentline > 0)
578 lua_pushfstring(L, "%d:", ar.currentline);
579 if (*ar.namewhat) {
580 lua_pushfstring(L, " in function " LUA_QS, ar.name);
581 } else {
582 if (*ar.what == 'm') {
583 lua_pushliteral(L, " in main chunk");
584 } else if (*ar.what == 'C') {
585 lua_pushfstring(L, " at %p", fn->c.f);
586 } else {
587 lua_pushfstring(L, " in function <%s:%d>",
588 ar.short_src, ar.linedefined);
589 }
590 }
591 if ((int)(L->top - L->base) - top >= 15)
592 lua_concat(L, (int)(L->top - L->base) - top);
593 }
594 lua_concat(L, (int)(L->top - L->base) - top);
595}
596
diff --git a/src/luajit.c b/src/luajit.c
index 22628aaf..a9476372 100644
--- a/src/luajit.c
+++ b/src/luajit.c
@@ -106,19 +106,7 @@ static int traceback(lua_State *L)
106 return 1; /* Return non-string error object. */ 106 return 1; /* Return non-string error object. */
107 lua_remove(L, 1); /* Replace object by result of __tostring metamethod. */ 107 lua_remove(L, 1); /* Replace object by result of __tostring metamethod. */
108 } 108 }
109 lua_getfield(L, LUA_GLOBALSINDEX, "debug"); 109 luaL_traceback(L, L, lua_tostring(L, 1), 1);
110 if (!lua_istable(L, -1)) {
111 lua_pop(L, 1);
112 return 1;
113 }
114 lua_getfield(L, -1, "traceback");
115 if (!lua_isfunction(L, -1)) {
116 lua_pop(L, 2);
117 return 1;
118 }
119 lua_pushvalue(L, 1); /* Push error message. */
120 lua_pushinteger(L, 2); /* Skip this function and debug.traceback(). */
121 lua_call(L, 2, 1); /* Call debug.traceback(). */
122 return 1; 110 return 1;
123} 111}
124 112