@@ -135,3 +135,34 @@ bool luaX_get_table_bool(lua_State *lua_state, char const *key, int table_index,
135135 throw std::runtime_error{
136136 " {} must contain a '{}' boolean field" _format (error_msg, key)};
137137}
138+
139+ static int pcall_error_traceback_handler (lua_State *lua_state)
140+ {
141+ assert (lua_state);
142+
143+ char const *msg = lua_tostring (lua_state, 1 );
144+ if (msg == nullptr ) { // is error object not a string?
145+ if (luaL_callmeta (lua_state, 1 ,
146+ " __tostring" ) && // does it have a metamethod
147+ lua_type (lua_state, -1 ) == LUA_TSTRING) { // that produces a string?
148+ return 1 ; // that is the message
149+ } else {
150+ msg = lua_pushfstring (lua_state, " (error object is a %s value)" ,
151+ luaL_typename (lua_state, 1 ));
152+ }
153+ }
154+ luaL_traceback (lua_state, lua_state, msg, 1 ); // append a standard traceback
155+ return 1 ; // return the traceback
156+ }
157+
158+ // wrapper function for lua_pcall to include a stack traceback
159+ int luaX_pcall (lua_State *lua_state, int narg, int nres)
160+ {
161+ int const base = lua_gettop (lua_state) - narg; // function index
162+ lua_pushcfunction (lua_state,
163+ pcall_error_traceback_handler); // push message handler
164+ lua_insert (lua_state, base); // put it under function and args
165+ int const status = lua_pcall (lua_state, narg, nres, base);
166+ lua_remove (lua_state, base); // remove message handler from the stack
167+ return status;
168+ }
0 commit comments