-- -- $Header: /Users/dap/lua/RCS/dump.lua,v 1.4 2007/02/11 08:32:44 dap Exp $ -- -- dump - dump out information about an object -- local string_meta = getmetatable(' ') local func_env = getfenv(getfenv) local dump_done = { fenv = {} } local function indented(lvl, out, fmt, ...) fmt = (" "):rep(2*lvl) .. fmt out(fmt, unpack(arg)) end local function varname(v, name) if not name then if type(v) == 'table' and v.__name and type(v.__name) == 'string' then name = v.__name else name = '**gok' end end return tostring(name) end local function dump_str(v, name, out, lvl) indented(lvl, out, "%8s = '%s'", varname(v, name), v) end local function dump_fun(v, name, out, lvl) indented(lvl, out, "%8s = %s", varname(v, name), tostring(v)) end local function dump_num(v, name, out, lvl) indented(lvl, out, "%8s = %s", varname(v, name), tostring(v)) end local function dump_userdata(v, name, out, lvl) indented(lvl, out, "%8s = '%s'", varname(v, v), tostring(v)) end local function dump_boolean(v, name, out, lvl) indented(lvl, out, "%8s = %s", varname(v, v), tostring(v)) end local function dump_nil(v, name, out, lvl) indented(lvl, out, "%8s = nil", varname(v, name)) end local function dump_tab(tab, name, out, lvl, seen) name = varname(tab, name) seen[tab] = true indented(lvl, out, '%8s = { %s', name, tostring(tab)) for k, v in pairs(tab) do if v == tab then -- self referential indented(lvl+1, out, '%8s = <*self*>', k) else dump(v, k, out, lvl+1, seen) end end indented(lvl, out, '}') end local function dump_mt(v, name, out, lvl, seen) local mt = getmetatable(v) if mt then dump(mt, ("meta '%s'"):format(varname(v, name)) , out, lvl, seen) end end function dump(v, name, out, lvl, seen) local t = type(v) local o = out or function (fmt, ...) print(fmt:format(unpack(arg))) end local lvl = lvl or 0 if not seen then seen = dump_done; seen.fenv[func_env] = true -- only show unusual ones end if t == 'table' then if seen and not seen[v] then dump_tab(v, name, o, lvl, seen) else local tnam = '' if v.__name and type(v.__name) == 'string' then tnam = ' (' .. v.__name .. ')' end indented(lvl, o, '%8s = %s%s', varname(v, name), tostring(v), tnam) end elseif t == 'function' then dump_fun(v, name, o, lvl) elseif t == type('string') then dump_str(v, name, o, lvl) elseif t == type(1) then dump_num(v, name, o, lvl) elseif t == type(true) then dump_boolean(v, name, o, lvl) elseif t == 'userdata' then dump_num(v, name, o, lvl) elseif t == type(nil) then dump_nil(v, name, o, lvl) else indented(lvl, o, '%8s = ***** type %s %s', name, t, tostring(v)) end local mt = getmetatable(v) if mt and t ~= 'string' or mt ~= string_meta then dump_mt(v, name, o, lvl, seen) end local fenv = debug.getfenv(v) if fenv and not seen.fenv[fenv] then seen.fenv[fenv] = true dump(fenv, 'fenv for ' .. name, o, lvl+1, seen) end end -- mark the global table as seen -- dump(_G, nil, function () end) -- faster: dump_done[_G] = true return true