1 -------------------------------------------------------------------------------
4 -- Written by Timm S. Mueller <tmueller at schulze-mueller.de>
5 -- See copyright notice in COPYRIGHT
8 -- Debug library - implements debug output and debug levels:
10 -- 2 || TRACE || used for tracking bugs
11 -- 4 || INFO || informational messages
12 -- 5 || WARN || something unexpected happened
13 -- 10 || ERROR || something went wrong, e.g. resource unavailable
14 -- 20 || FAIL || something went wrong that can't be coped with
16 -- The default debug level is 10 {{ERROR}}. To set the debug level
18 -- db = require "tek.lib.debug"
21 -- The default debug output stream is {{stderr}}.
22 -- To override it globally, e.g.:
23 -- db = require "tek.lib.debug"
24 -- db.out = io.open("logfile", "w")
27 -- - debug.console() - Enter debug console
28 -- - debug.dump() - Dump a table recursively
29 -- - debug.error() - Print a text in the {{ERROR}} debug level
30 -- - debug.execute() - Execute a function in the specified debug level
31 -- - debug.fail() - Print a text in the {{FAIL}} debug level
32 -- - debug.info() - Print a text in the {{INFO}} debug level
33 -- - debug.print() - Print a text in the specified debug level
34 -- - debug.stacktrace() - Print a stacktrace in the specified debug level
35 -- - debug.trace() - Print a text in the {{TRACE}} debug level
36 -- - debug.warn() - Print a text in the {{WARN}} debug level
38 -------------------------------------------------------------------------------
40 local debug = require "debug"
41 local getinfo = debug.getinfo
42 local stderr = io.stderr
46 local tonumber = tonumber
47 local tostring = tostring
48 local traceback = debug.traceback
52 module "tek.lib.debug"
53 _VERSION = "Debug 4.1"
67 wrout = function(...) out:write(...) end
69 -------------------------------------------------------------------------------
70 -- print(lvl, msg, ...): Prints formatted text if the global debug level
71 -- is less or equal the specified level.
72 -------------------------------------------------------------------------------
74 function print(lvl, msg, ...)
75 if level and lvl >= level then
76 local t = getinfo(3, "lS")
78 for i = 1, select('#', ...) do
79 local v = select(i, ...)
80 arg[i] = v and type(v) ~= "number" and tostring(v) or v or 0
82 wrout(("(%02d %d %s:%d) " .. msg):format(lvl,
83 time(), t.short_src, t.currentline, unpack(arg)) .. "\n")
87 -------------------------------------------------------------------------------
88 -- execute(lvl, func, ...): Executes the specified function if the global
89 -- debug library is less or equal the specified level.
90 -------------------------------------------------------------------------------
92 function execute(lvl, func, ...)
93 if level and lvl >= level then
98 -------------------------------------------------------------------------------
99 -- trace(msg, ...): Prints formatted debug info with {{TRACE}} level
100 -------------------------------------------------------------------------------
101 function trace(msg, ...) print(2, msg, ...) end
103 -------------------------------------------------------------------------------
104 -- info(msg, ...): Prints formatted debug info with {{INFO}} level
105 -------------------------------------------------------------------------------
106 function info(msg, ...) print(4, msg, ...) end
108 -------------------------------------------------------------------------------
109 -- warn(msg, ...): Prints formatted debug info with {{WARN}} level
110 -------------------------------------------------------------------------------
111 function warn(msg, ...) print(5, msg, ...) end
113 -------------------------------------------------------------------------------
114 -- error(msg, ...): Prints formatted debug info with {{ERROR}} level
115 -------------------------------------------------------------------------------
116 function error(msg, ...) print(10, msg, ...) end
118 -------------------------------------------------------------------------------
119 -- fail(msg, ...): Prints formatted debug info with {{FAIL}} level
120 -------------------------------------------------------------------------------
121 function fail(msg, ...) print(20, msg, ...) end
123 -------------------------------------------------------------------------------
124 -- stacktrace(debuglevel, stacklevel): Prints a stacktrace starting at
125 -- the function of the given {{level}} on the stack (excluding the
126 -- {{stracktrace}} function itself) if the global debug level is less
127 -- or equal the specified {{debuglevel}}.
128 -------------------------------------------------------------------------------
130 function stacktrace(lvl, level)
131 print(lvl, traceback("", level or 1 + 1))
134 -------------------------------------------------------------------------------
135 -- console(): Enter the debug console.
136 -------------------------------------------------------------------------------
139 stderr:write('Entering the debug console.\n')
140 stderr:write('To redirect the output, e.g.:\n')
141 stderr:write(' tek.lib.debug.out = io.open("logfile", "w")\n')
142 stderr:write('To dump a table, e.g.:\n')
143 stderr:write(' tek.lib.debug.dump(app)\n')
144 stderr:write('Use "cont" to continue.\n')
148 -------------------------------------------------------------------------------
149 -- dump(table): Dump a table as Lua source using {{out}} as the output
150 -- stream. Cyclic references are silently dropped.
151 -------------------------------------------------------------------------------
153 local function encodenonascii(c)
154 return ("\\%03d"):format(c:byte())
157 local function encode(s)
158 return s:gsub('([%z\001-\031\092"])', encodenonascii)
161 local function dumpr(tab, indent, outfunc, saved)
163 local is = ("\t"):rep(indent)
164 for key, val in pairs(tab) do
165 if not saved[val] then
168 if t == "number" or t == "boolean" then
169 outfunc('[' .. tostring(key) .. '] = ')
170 elseif t == "string" then
171 if key:match("[^%a_]") then
172 outfunc('["' .. encode(key) .. '"] = ')
174 outfunc(key .. ' = ')
177 outfunc('["' .. tostring(key) .. '"] = ')
182 dumpr(val, indent + 1, outfunc, saved)
183 outfunc(is .. '},\n')
184 elseif t == "string" then
185 outfunc('"' .. encode(val) .. '",\n')
186 elseif t == "number" or t == "boolean" then
187 outfunc(tostring(val) .. ',\n')
189 outfunc('"' .. tostring(val) .. '",\n')
195 function dump(tab, outf)
196 dumpr(tab, 0, outf or wrout, { })