Advertisement
theoriginalbit

Error Override w/ Stack Trace! (v1.0 & v2.0)

Apr 30th, 2013
219
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
Lua 2.65 KB | None | 0 0
  1. --[[
  2. version 2.0
  3.  
  4. - hooks the error function by overriding it, calls native error on completion
  5. - exposes function to get latest stack trace
  6. - yields when needed, and only if needed! incase of large function call stacks & large no yield time on invoke
  7. - better file names (extension-less) and line numbers reported on traceback lines
  8. - allows pcalls to occur in trace
  9. - does not generate trace for "Terminated" or level of 0 errors, just calls native error
  10. - better formatted trace
  11. --]]
  12.  
  13. local nativeError = _G.error
  14.  
  15. local latestTrace
  16.  
  17. function _G.error(_msg, _level)
  18.   if _msg == "Terminated" or _level == 0 then
  19.     error(_msg, _level)
  20.   end
  21.   _level = type(_level) == "number" and _level + 1 or 2
  22.   local trace = {
  23.     "Error Message:",
  24.     string.format("   %s", _msg),
  25.     "",
  26.     "Stack Trace:"
  27.   }
  28.   local ok, err, last = nil, "", os.clock()
  29.   while true do
  30.     ok, err = pcall(nativeError, _msg, _level)
  31.     print(err)
  32.     if err:find("^bios") or err:find("^shell") then
  33.       break
  34.     end
  35.     local name, line = err:match("(%a+)%.?.-:(%d+).-")
  36.     trace[#trace+1] = string.format("   at %s :%d", name or "?", line or 0)
  37.     _level = _level + 1
  38.     if last + os.clock() > 4 then
  39.       os.queueEvent('d')
  40.       coroutine.yield('d')
  41.       last = os.clock()
  42.     end
  43.   end
  44.   latestTrace = trace
  45.   nativeError(_msg, _level)
  46. end
  47.  
  48. function getLatestStackTrace()
  49.   return latestTrace
  50. end
  51.  
  52. _G.error = nativeError
  53.  
  54. --[[
  55. version 1.0
  56.  
  57. - hooks the error function by overriding it, calls native error on completion
  58. - ignores message-less assertions, terminations and throwback levels of 0
  59. - shows filename and line number
  60. - can output to file or the terminal
  61. --]]
  62. local nativeError = error
  63.  
  64. local error_output_terminal = true
  65.  
  66. function error(_msg, _level)
  67.   if not _msg or _msg:lower() == 'assertion failed!' or _msg:lower() == 'terminated' or _lvl == 0 then nativeError(_msg, _lvl) end
  68.   _lvl = (_level + 1) or 2
  69.   local trace = {}
  70.   while true do
  71.     _lvl = _lvl + 1
  72.     ok, err = pcall(nativeError, _msg, _lvl)
  73.     if not (err:find('shell') or err:find('bios') or err:find('pcall')) then
  74.       local e = err:gsub(': '.._msg, '')
  75.       table.insert(trace, e)
  76.     else
  77.       break
  78.     end
  79.   end
  80.   trace[1] = trace[1]..': '.._msg
  81.   pcall(term.setTextColor, colors.red)
  82.   local traceOutput = table.concat(trace, '\n  ')
  83.   if error_output_terminal then
  84.     textutils.pagedPrint(traceOutput)
  85.   else
  86.     print(trace[1])
  87.     local h = fs.open('.trace_'..math.floor(os.day())..math.floor(os.time())..os.clock(), 'w')
  88.     h.write(traceOutput)
  89.   end
  90.   pcall(term.setTextColor, colors.white)
  91.   nativeError(nil, 0)
  92. end
  93.  
  94. error = nativeError
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement