Bläddra i källkod

traceback function moved to auxlib

Roberto Ierusalimschy 18 år sedan
förälder
incheckning
3f78748ef3
4 ändrade filer med 69 tillägg och 67 borttagningar
  1. 53 1
      lauxlib.c
  2. 3 1
      lauxlib.h
  3. 6 45
      ldblib.c
  4. 7 20
      lua.c

+ 53 - 1
lauxlib.c

@@ -1,5 +1,5 @@
 /*
-** $Id: lauxlib.c,v 1.168 2007/06/21 13:48:04 roberto Exp roberto $
+** $Id: lauxlib.c,v 1.169 2007/06/21 14:09:59 roberto Exp roberto $
 ** Auxiliary functions for building Lua libraries
 ** See Copyright Notice in lua.h
 */
@@ -89,6 +89,58 @@ LUALIB_API int luaL_error (lua_State *L, const char *fmt, ...) {
   return lua_error(L);
 }
 
+
+#define LEVELS1	12	/* size of the first part of the stack */
+#define LEVELS2	10	/* size of the second part of the stack */
+
+
+static void pushfuncname (lua_State *L, lua_Debug *ar) {
+  if (*ar->namewhat != '\0')  /* is there a name? */
+    lua_pushfstring(L, "function " LUA_QS, ar->name);
+  else if (*ar->what == 'm')  /* main? */
+      lua_pushfstring(L, "main chunk");
+  else if (*ar->what == 'C' || *ar->what == 't')
+    lua_pushliteral(L, " ?");  /* C function or tail call */
+  else
+    lua_pushfstring(L, "function <%s:%d>", ar->short_src, ar->linedefined);
+}
+
+
+static int countlevels (lua_State *L) {
+  lua_Debug ar;
+  int level = 1;
+  while (lua_getstack(L, level, &ar)) level++;
+  return level;
+}
+
+
+LUALIB_API const char *luaL_traceback (lua_State *L, lua_State *L1,
+                                       const char *msg, int level) {
+  lua_Debug ar;
+  int top = lua_gettop(L);
+  int numlevels = countlevels(L1);
+  int mark = (numlevels > LEVELS1 + LEVELS2) ? LEVELS1 : 0;
+  if (msg) lua_pushfstring(L, "%s\n", msg);
+  lua_pushliteral(L, "stack traceback:");
+  while (lua_getstack(L1, level++, &ar)) {
+    if (level == mark) {  /* too many levels? */
+      lua_pushliteral(L, "\n\t...");  /* add a '...' */
+      level = numlevels - LEVELS2;  /* and skip to last ones */
+    }
+    else {
+      lua_getinfo(L1, "Sln", &ar);
+      lua_pushfstring(L, "\n\t%s:", ar.short_src);
+      if (ar.currentline > 0)
+        lua_pushfstring(L, "%d:", ar.currentline);
+      lua_pushliteral(L, " in ");
+      pushfuncname(L, &ar);
+      lua_concat(L, lua_gettop(L) - top);
+    }
+  }
+  lua_concat(L, lua_gettop(L) - top);
+  return lua_tostring(L, -1);
+}
+
 /* }====================================================== */
 
 

+ 3 - 1
lauxlib.h

@@ -1,5 +1,5 @@
 /*
-** $Id: lauxlib.h,v 1.90 2007/05/15 18:46:12 roberto Exp roberto $
+** $Id: lauxlib.h,v 1.91 2007/06/21 13:48:04 roberto Exp roberto $
 ** Auxiliary functions for building Lua libraries
 ** See Copyright Notice in lua.h
 */
@@ -78,6 +78,8 @@ LUALIB_API const char *(luaL_gsub) (lua_State *L, const char *s, const char *p,
 LUALIB_API const char *(luaL_findtable) (lua_State *L, int idx,
                                          const char *fname, int szhint);
 
+LUALIB_API const char *luaL_traceback (lua_State *L, lua_State *L1,
+                                       const char *msg, int level);
 
 
 

+ 6 - 45
ldblib.c

@@ -1,5 +1,5 @@
 /*
-** $Id: ldblib.c,v 1.105 2006/09/11 14:07:24 roberto Exp roberto $
+** $Id: ldblib.c,v 1.106 2007/04/26 20:39:38 roberto Exp roberto $
 ** Interface from Lua to its debug API
 ** See Copyright Notice in lua.h
 */
@@ -315,55 +315,16 @@ static int db_debug (lua_State *L) {
 }
 
 
-#define LEVELS1	12	/* size of the first part of the stack */
-#define LEVELS2	10	/* size of the second part of the stack */
-
 static int db_errorfb (lua_State *L) {
-  lua_Debug ar;
-  int firstpart = 1;  /* still before eventual `...' */
   int arg;
   lua_State *L1 = getthread(L, &arg);
   const char *msg = lua_tostring(L, arg + 1);
-  int level = (lua_isnumber(L, arg + 2)) ?
-                     (int)lua_tointeger(L, arg + 2) :
-                     (L == L1) ? 1 : 0;  /* level 0 may be this own function */
-  lua_settop(L, ++arg);
-  if (msg) lua_pushfstring(L, "%s\n", msg);
-  else if (!lua_isnil(L, arg))  /* is there a non-string 'msg'? */
-    return 1;  /* return it untouched */
-  lua_pushliteral(L, "stack traceback:");
-  while (lua_getstack(L1, level++, &ar)) {
-    if (level > LEVELS1 && firstpart) {
-      /* no more than `LEVELS2' more levels? */
-      if (!lua_getstack(L1, level+LEVELS2, &ar))
-        level--;  /* keep going */
-      else {
-        lua_pushliteral(L, "\n\t...");  /* too many levels */
-        while (lua_getstack(L1, level+LEVELS2, &ar))  /* find last levels */
-          level++;
-      }
-      firstpart = 0;
-      continue;
-    }
-    lua_pushliteral(L, "\n\t");
-    lua_getinfo(L1, "Snl", &ar);
-    lua_pushfstring(L, "%s:", ar.short_src);
-    if (ar.currentline > 0)
-      lua_pushfstring(L, "%d:", ar.currentline);
-    if (*ar.namewhat != '\0')  /* is there a name? */
-        lua_pushfstring(L, " in function " LUA_QS, ar.name);
-    else {
-      if (*ar.what == 'm')  /* main? */
-        lua_pushfstring(L, " in main chunk");
-      else if (*ar.what == 'C' || *ar.what == 't')
-        lua_pushliteral(L, " ?");  /* C function or tail call */
-      else
-        lua_pushfstring(L, " in function <%s:%d>",
-                           ar.short_src, ar.linedefined);
-    }
-    lua_concat(L, lua_gettop(L) - arg);
+  if (msg == NULL && !lua_isnoneornil(L, arg + 1))  /* non-string 'msg'? */
+    lua_pushvalue(L, arg + 1);  /* return it untouched */
+  else {
+    int level = luaL_optint(L, arg + 2, (L == L1) ? 1 : 0);
+    luaL_traceback(L, L1, msg, level);
   }
-  lua_concat(L, lua_gettop(L) - arg);
   return 1;
 }
 

+ 7 - 20
lua.c

@@ -1,5 +1,5 @@
 /*
-** $Id: lua.c,v 1.164 2006/10/10 17:40:17 roberto Exp roberto $
+** $Id: lua.c,v 1.165 2007/04/26 20:39:38 roberto Exp roberto $
 ** Lua stand-alone interpreter
 ** See Copyright Notice in lua.h
 */
@@ -73,27 +73,14 @@ static int report (lua_State *L, int status) {
 }
 
 
-static int gettraceback (lua_State *L) {
-  lua_getfield(L, LUA_GLOBALSINDEX, "debug");
-  if (!lua_istable(L, -1)) return 0;
-  lua_getfield(L, -1, "traceback");  /* check 'debug.traceback' */
-  if (!lua_isfunction(L, -1)) return 0;
-  return 1;  /* there is a function 'debug.traceback' */
-}
-
-
 static int traceback (lua_State *L) {
-  if (lua_isnoneornil(L, 1))  /* no error object? */
-    return 1;  /* keep it that way */
-  if (!gettraceback(L))  /* no 'debug.traceback' function? */
-    lua_pushvalue(L, 1);  /* keep original message */
-  else {
-    lua_pushvalue(L, 1);  /* pass error message */
-    lua_pushinteger(L, 2);  /* skip this function and traceback */
-    lua_call(L, 2, 1);  /* call traceback */
+  const char *msg = lua_tostring(L, 1);
+  if (msg)
+    luaL_traceback(L, L, msg, 2);
+  else if (!lua_isnoneornil(L, 1)) {  /* is there an error object? */
+    if (!luaL_callmeta(L, 1, "__tostring"))  /* try its 'tostring' metamethod */
+      lua_pushliteral(L, "(no error message)");
   }
-  if (!lua_isstring(L, -1) && !luaL_callmeta(L, 1, "__tostring"))
-    lua_pushliteral(L, "(no error message)");
   return 1;
 }