aboutsummaryrefslogtreecommitdiff
path: root/lauxlib.c
diff options
context:
space:
mode:
authorRoberto Ierusalimschy <roberto@inf.puc-rio.br>2019-05-28 15:50:40 -0300
committerRoberto Ierusalimschy <roberto@inf.puc-rio.br>2019-05-28 15:50:40 -0300
commit2b8b53864c6b8655aa7198699884075b3e2f15fa (patch)
treec21e66f343f32ecd5db8df63e31980f4f9b2a3de /lauxlib.c
parentb293ae0577bebaca7169cb4f041b800641d5e2c4 (diff)
downloadlua-2b8b53864c6b8655aa7198699884075b3e2f15fa.tar.gz
lua-2b8b53864c6b8655aa7198699884075b3e2f15fa.tar.bz2
lua-2b8b53864c6b8655aa7198699884075b3e2f15fa.zip
Improvements in 'luaL_traceback'
'luaL_traceback' changed to use an aux buffer instead of concats. This should reduce the quantity of garbage it generates (in the form of intermediate strings) while producing a trackback. It also added information about the number of levels skipped when skipping levels in a trace.
Diffstat (limited to 'lauxlib.c')
-rw-r--r--lauxlib.c53
1 files changed, 29 insertions, 24 deletions
diff --git a/lauxlib.c b/lauxlib.c
index 89e53dc1..d49ef573 100644
--- a/lauxlib.c
+++ b/lauxlib.c
@@ -46,8 +46,8 @@
46 46
47 47
48/* 48/*
49** search for 'objidx' in table at index -1. 49** Search for 'objidx' in table at index -1. ('objidx' must be an
50** return 1 + string at top if find a good name. 50** absolute index.) Return 1 + string at top if it found a good name.
51*/ 51*/
52static int findfield (lua_State *L, int objidx, int level) { 52static int findfield (lua_State *L, int objidx, int level) {
53 if (level == 0 || !lua_istable(L, -1)) 53 if (level == 0 || !lua_istable(L, -1))
@@ -60,10 +60,10 @@ static int findfield (lua_State *L, int objidx, int level) {
60 return 1; 60 return 1;
61 } 61 }
62 else if (findfield(L, objidx, level - 1)) { /* try recursively */ 62 else if (findfield(L, objidx, level - 1)) { /* try recursively */
63 lua_remove(L, -2); /* remove table (but keep name) */ 63 /* stack: lib_name, lib_table, field_name (top) */
64 lua_pushliteral(L, "."); 64 lua_pushliteral(L, "."); /* place '.' between the two names */
65 lua_insert(L, -2); /* place '.' between the two names */ 65 lua_replace(L, -3); /* (in the slot ocupied by table) */
66 lua_concat(L, 3); 66 lua_concat(L, 3); /* lib_name.field_name */
67 return 1; 67 return 1;
68 } 68 }
69 } 69 }
@@ -86,8 +86,8 @@ static int pushglobalfuncname (lua_State *L, lua_Debug *ar) {
86 lua_pushstring(L, name + 3); /* push name without prefix */ 86 lua_pushstring(L, name + 3); /* push name without prefix */
87 lua_remove(L, -2); /* remove original name */ 87 lua_remove(L, -2); /* remove original name */
88 } 88 }
89 lua_copy(L, -1, top + 1); /* move name to proper place */ 89 lua_copy(L, -1, top + 1); /* copy name to proper place */
90 lua_pop(L, 2); /* remove pushed values */ 90 lua_settop(L, top + 1); /* remove table "loaded" an name copy */
91 return 1; 91 return 1;
92 } 92 }
93 else { 93 else {
@@ -130,32 +130,37 @@ static int lastlevel (lua_State *L) {
130 130
131LUALIB_API void luaL_traceback (lua_State *L, lua_State *L1, 131LUALIB_API void luaL_traceback (lua_State *L, lua_State *L1,
132 const char *msg, int level) { 132 const char *msg, int level) {
133 luaL_Buffer b;
133 lua_Debug ar; 134 lua_Debug ar;
134 int top = lua_gettop(L);
135 int last = lastlevel(L1); 135 int last = lastlevel(L1);
136 int n1 = (last - level > LEVELS1 + LEVELS2) ? LEVELS1 : -1; 136 int limit2show = (last - level > LEVELS1 + LEVELS2) ? LEVELS1 : -1;
137 if (msg) 137 luaL_buffinit(L, &b);
138 lua_pushfstring(L, "%s\n", msg); 138 if (msg) {
139 luaL_checkstack(L, 10, NULL); 139 luaL_addstring(&b, msg);
140 lua_pushliteral(L, "stack traceback:"); 140 luaL_addchar(&b, '\n');
141 }
142 luaL_addstring(&b, "stack traceback:");
141 while (lua_getstack(L1, level++, &ar)) { 143 while (lua_getstack(L1, level++, &ar)) {
142 if (n1-- == 0) { /* too many levels? */ 144 if (limit2show-- == 0) { /* too many levels? */
143 lua_pushliteral(L, "\n\t..."); /* add a '...' */ 145 int n = last - level - LEVELS2 + 1; /* number of levels to skip */
144 level = last - LEVELS2 + 1; /* and skip to last ones */ 146 lua_pushfstring(L, "\n\t...\t(skipping %d levels)", n);
147 luaL_addvalue(&b); /* add warning about skip */
148 level += n; /* and skip to last levels */
145 } 149 }
146 else { 150 else {
147 lua_getinfo(L1, "Slnt", &ar); 151 lua_getinfo(L1, "Slnt", &ar);
148 lua_pushfstring(L, "\n\t%s:", ar.short_src); 152 if (ar.currentline <= 0)
149 if (ar.currentline > 0) 153 lua_pushfstring(L, "\n\t%s: in ", ar.short_src);
150 lua_pushfstring(L, "%d:", ar.currentline); 154 else
151 lua_pushliteral(L, " in "); 155 lua_pushfstring(L, "\n\t%s:%d: in ", ar.short_src, ar.currentline);
156 luaL_addvalue(&b);
152 pushfuncname(L, &ar); 157 pushfuncname(L, &ar);
158 luaL_addvalue(&b);
153 if (ar.istailcall) 159 if (ar.istailcall)
154 lua_pushliteral(L, "\n\t(...tail calls...)"); 160 luaL_addstring(&b, "\n\t(...tail calls...)");
155 lua_concat(L, lua_gettop(L) - top);
156 } 161 }
157 } 162 }
158 lua_concat(L, lua_gettop(L) - top); 163 luaL_pushresult(&b);
159} 164}
160 165
161/* }====================================================== */ 166/* }====================================================== */