cgi-bin/tek/lib/debug.lua
changeset 247 71a5ca44a68e
parent 244 3a4291950c9f
child 255 63e76b4e3956
     1.1 --- a/cgi-bin/tek/lib/debug.lua	Fri Sep 12 22:00:42 2008 +0200
     1.2 +++ b/cgi-bin/tek/lib/debug.lua	Mon Oct 06 21:36:21 2008 +0200
     1.3 @@ -50,7 +50,7 @@
     1.4  local unpack = unpack
     1.5  
     1.6  module "tek.lib.debug"
     1.7 -_VERSION = "Debug 4.0"
     1.8 +_VERSION = "Debug 4.1"
     1.9  
    1.10  -- symbolic:
    1.11  
    1.12 @@ -62,7 +62,7 @@
    1.13  
    1.14  -- global defaults:
    1.15  
    1.16 -level = ERROR
    1.17 +level = INFO
    1.18  out = stderr
    1.19  wrout = function(...) out:write(...) end
    1.20  
    1.21 @@ -140,40 +140,58 @@
    1.22  	stderr:write('To redirect the output, e.g.:\n')
    1.23  	stderr:write('  tek.lib.debug.out = io.open("logfile", "w")\n')
    1.24  	stderr:write('To dump a table, e.g.:\n')
    1.25 -	stderr:write('  tek.lib.debug.dump("app", app)\n')
    1.26 +	stderr:write('  tek.lib.debug.dump(app)\n')
    1.27  	stderr:write('Use "cont" to continue.\n')
    1.28  	debug.debug()
    1.29  end
    1.30  
    1.31  -------------------------------------------------------------------------------
    1.32 ---	dump(name, table): Dump a table
    1.33 +--	dump(table): Dump a table as Lua source using {{out}} as the output
    1.34 +--	stream. Cyclic references are silently dropped.
    1.35  -------------------------------------------------------------------------------
    1.36  
    1.37 -local function basicSerialize(o)
    1.38 -	if type(o) == "string" then
    1.39 -		return ("%q"):format(o)
    1.40 -	elseif type(o) == "userdata" then
    1.41 -		return "<userdata>"
    1.42 -	end
    1.43 -	return tostring(o)
    1.44 +local function encodenonascii(c)
    1.45 +	return ("\\%03d"):format(c:byte())
    1.46  end
    1.47  
    1.48 -function dump(name, value, saved)
    1.49 -	saved = saved or {}       -- initial value
    1.50 -	wrout(name, " = ")
    1.51 -	local t = type(value)
    1.52 -	if t == "table" then
    1.53 -		if saved[value] then    -- value already saved?
    1.54 -			wrout(saved[value], "\n")
    1.55 -		else
    1.56 -			saved[value] = name   -- save name for next time
    1.57 -			wrout("{}\n")
    1.58 -			for k,v in pairs(value) do      -- save its fields
    1.59 -				local fieldname = ("%s[%s]"):format(name, basicSerialize(k))
    1.60 -				dump(fieldname, v, saved)
    1.61 +local function encode(s)
    1.62 +	return s:gsub('([%z\001-\031\092"])', encodenonascii)
    1.63 +end
    1.64 +
    1.65 +local function dumpr(tab, indent, outfunc, saved)
    1.66 +	saved[tab] = tab
    1.67 +	local is = ("\t"):rep(indent)
    1.68 +	for key, val in pairs(tab) do
    1.69 +		if not saved[val] then
    1.70 +			outfunc(is)
    1.71 +			local t = type(key)
    1.72 +			if t == "number" or t == "boolean" then
    1.73 +				outfunc('[' .. tostring(key) .. '] = ')
    1.74 +			elseif t == "string" then
    1.75 +				if key:match("[^%a_]") then
    1.76 +					outfunc('["' .. encode(key) .. '"] = ')
    1.77 +				else
    1.78 +					outfunc(key .. ' = ')
    1.79 +				end
    1.80 +			else
    1.81 +				outfunc('["' .. tostring(key) .. '"] = ')
    1.82 +			end
    1.83 +			t = type(val)
    1.84 +			if t == "table" then
    1.85 +				outfunc('{\n')
    1.86 +				dumpr(val, indent + 1, outfunc, saved)
    1.87 +				outfunc(is .. '},\n')
    1.88 +			elseif t == "string" then
    1.89 +				outfunc('"' .. encode(val) .. '",\n')
    1.90 +			elseif t == "number" or t == "boolean" then
    1.91 +				outfunc(tostring(val) .. ',\n')
    1.92 +			else
    1.93 +				outfunc('"' .. tostring(val) .. '",\n')
    1.94  			end
    1.95  		end
    1.96 -	else
    1.97 -		wrout(basicSerialize(value), "\n")
    1.98  	end
    1.99  end
   1.100 +
   1.101 +function dump(tab, outf)
   1.102 +	dumpr(tab, 0, outf or wrout, { })
   1.103 +end