adff45ca21
fix a few bugs, improve memory usage Change-Id: I6ceefd033000a6178eab0dd513679b5d72cec81c
338 lines
11 KiB
Lua
338 lines
11 KiB
Lua
|
|
--RB LUA show all global variables; BILGUS
|
|
if not ... then --if executed directly this is nil
|
|
require "actions"
|
|
require "audio"
|
|
require "buttons"
|
|
require "color"
|
|
require "draw"
|
|
require "draw_floodfill"
|
|
require "draw_poly"
|
|
require "draw_text"
|
|
|
|
require "image"
|
|
require "image_save"
|
|
|
|
require "lcd"
|
|
require "math_ex"
|
|
require "pcm"
|
|
require "playlist"
|
|
require "print"
|
|
--require "settings" --uses a lot of memory
|
|
require "sound"
|
|
end
|
|
collectgarbage("collect")
|
|
|
|
local sDumpFile = "/rb-lua_functions.txt"
|
|
local filehandle
|
|
|
|
local function a2m_m2a(addr_member)
|
|
--turns members into addresses; addresses back into members
|
|
return addr_member
|
|
end
|
|
|
|
local function dtTag(sType)
|
|
--convert named type; 'number'.. to short type '[n]...'
|
|
--if '?' supplied print out datatype key; number = [n]...
|
|
local retType = "?"
|
|
local typ = {
|
|
["nil"] = "nil",
|
|
["boolean"] = "b",
|
|
["number"] = "n",
|
|
["string"] = "s",
|
|
["userdata"] = "u",
|
|
["function"] = "f",
|
|
["thread"] = "thr",
|
|
["table"] = "t"
|
|
}
|
|
if sType == "?" then retType = "Datatypes: " end
|
|
for k,v in pairs(typ) do
|
|
if sType == k then
|
|
retType = v break
|
|
elseif (sType == "?") then
|
|
retType = retType .. " [" ..v.. "] = " .. k
|
|
end
|
|
end
|
|
return " [" ..retType.. "] "
|
|
end
|
|
|
|
local function tableByName(tName)
|
|
--find the longest match possible to an actual table
|
|
--Name comes in as (table) tName.var so we can pass back out the name found PITA
|
|
--returns the table found (key and value)
|
|
local ld = {}
|
|
local sMatch = ""
|
|
local kMatch = nil
|
|
local vMatch = nil
|
|
|
|
----FUNCTIONS for tableByName -----------------------------------------------------
|
|
local function search4Str(n, k, v)
|
|
local sKey = tostring(k)
|
|
if string.find (n, sKey,1,true) then
|
|
if sKey:len() > sMatch:len() then sMatch = sKey kMatch = k vMatch = v end
|
|
--find the longest match we can
|
|
end
|
|
end
|
|
----END FUNCTIONS for tableByName -------------------------------------------------
|
|
|
|
if tName.val ~= nil and tName.val ~= "" then
|
|
for k, v in pairs(_G) do
|
|
--_G check both since some tables are only in _G or package.loaded
|
|
search4Str(tName.val, k, v)
|
|
end
|
|
for k, v in pairs(package.loaded) do --package.loaded
|
|
search4Str(tName.val, k, v)
|
|
end
|
|
if not string.find (sMatch, "_G",1,true) then sMatch = "_G." .. sMatch end
|
|
-- put the root _G in if not exist
|
|
if kMatch and vMatch then ld[kMatch] = vMatch tName.val = sMatch return ld end
|
|
end
|
|
tName.val = "_G"
|
|
return package.loaded --Not Found return default
|
|
end
|
|
|
|
local function dump_Tables(tBase, sFunc, tSeen, tRet)
|
|
--Based on: http://www.lua.org/cgi-bin/demo?globals
|
|
--Recurse through tBase tables copying all found Tables
|
|
local sSep=""
|
|
local ld={}
|
|
local tNameBuf = {}
|
|
local sName
|
|
if sFunc ~= "" then sSep = "." end
|
|
|
|
for k, v in pairs(tBase) do
|
|
k = tostring(k)
|
|
tNameBuf[1] = sFunc
|
|
tNameBuf[2] = sSep
|
|
tNameBuf[3] = k
|
|
|
|
|
|
if k ~= "loaded" and type(v) == "table" and not tSeen[v] then
|
|
tSeen[v]=sFunc
|
|
sName = table.concat(tNameBuf)
|
|
tRet[sName] = a2m_m2a(v) --place all keys into ld[i]=value
|
|
dump_Tables(v, sName, tSeen, tRet)
|
|
elseif type(v) == "table" and not tSeen[v] then
|
|
tSeen[v]=sFunc
|
|
tRet[table.concat(tNameBuf)] = a2m_m2a(v) -- dump 'loaded' table
|
|
for k1, v1 in pairs(v) do
|
|
if not _G[k1] and type(v1) == "table" and not tSeen[v1] then
|
|
-- dump tables that are loaded but not global
|
|
tSeen[v1]=sFunc
|
|
tNameBuf[3] = k1
|
|
sName = table.concat(tNameBuf)
|
|
tRet[sName] = a2m_m2a(v1) --place all keys into ld[i]=value
|
|
dump_Tables(v1, sName, tSeen, tRet)
|
|
end
|
|
end
|
|
end
|
|
end
|
|
end
|
|
|
|
local function dump_Functions(tBase)
|
|
--Based on: http://www.lua.org/cgi-bin/demo?globals
|
|
--We already recursed through tBase copying all found tables
|
|
--we look up the table by name and then (ab)use a2m_m2a() to load the address
|
|
--after finding the table by address in tBase we will
|
|
--put the table address of tFuncs in its place
|
|
local tFuncBuf = {}
|
|
for k,v in pairs(tBase) do
|
|
local tTable = a2m_m2a(v)
|
|
local tFuncs = {}
|
|
|
|
for key, val in pairs(tTable) do
|
|
if key ~= "loaded" then
|
|
tFuncBuf[1] = dtTag(type(val))
|
|
tFuncBuf[2] = tostring(key)
|
|
tFuncs[table.concat(tFuncBuf)]= val
|
|
--put the name and value in our tFuncs table
|
|
end
|
|
end
|
|
tBase[k] = a2m_m2a(tFuncs) -- copy the address back to tBase
|
|
end
|
|
|
|
end
|
|
|
|
local function get_common_branches(t, tRet)
|
|
--load t 'names(values)' into keys
|
|
--strip off long paths then iterate value if it exists
|
|
--local tRet={}
|
|
local sBranch = ""
|
|
local tName = {}
|
|
for k in pairs(t) do
|
|
tName["val"]=k
|
|
tableByName(tName)
|
|
sBranch = tName.val
|
|
if tRet[sBranch] == nil then
|
|
tRet[sBranch] = 1 --first instance of this branch
|
|
else
|
|
tRet[sBranch] = tRet[sBranch] + 1
|
|
end
|
|
end
|
|
end
|
|
|
|
local function pairsByPairs (t, tkSorted)
|
|
--tkSorted should be an already sorted (i)table with t[keys] in the values
|
|
--https://www.lua.org/pil/19.3.html
|
|
--!!Note: table sort default function does not like numbers as [KEY]!!
|
|
--see *sortbyKeys*cmp_alphanum*
|
|
|
|
local i = 0 -- iterator variable
|
|
local iter = function () -- iterator function
|
|
i = i + 1
|
|
if tkSorted[i] == nil then return nil
|
|
else return tkSorted[i], t[tkSorted[i]]
|
|
end
|
|
end
|
|
return iter
|
|
end
|
|
|
|
local function sortbyKeys(t, tkSorted)
|
|
--loads keys of (t) into values of tkSorted
|
|
--and then sorts them
|
|
--tkSorted has integer keys (see ipairs)
|
|
----FUNCTIONS for sortByKeys -------------
|
|
local cmp_alphanum = function (op1, op2)
|
|
local type1= type(op1)
|
|
local type2 = type(op2)
|
|
if type1 ~= type2 then
|
|
return type1 < type2
|
|
else
|
|
return op1 < op2
|
|
end
|
|
end
|
|
----END FUNCTIONS for sortByKeys ---------
|
|
for n in pairs(t) do table.insert(tkSorted, n) end
|
|
table.sort(tkSorted, cmp_alphanum)--table.sort(tkSorted)
|
|
end
|
|
|
|
local function funcprint(tBuf, strName, value)
|
|
local sType = type(value)
|
|
local sVal = ""
|
|
local sHex = ""
|
|
tBuf[#tBuf + 1] = "\t"
|
|
tBuf[#tBuf + 1] = strName
|
|
if nil ~= string.find (";string;number;userdata;boolean;", sType, 1, true) then
|
|
--If any of the above types print the contents of variable
|
|
sVal = tostring(value)
|
|
|
|
if type(value) == "number" then
|
|
sHex = " = 0x" .. string.format("%x", value)
|
|
else
|
|
sHex = ""
|
|
sVal = string.gsub(sVal, "\n", "\\n") --replace newline with \n
|
|
end
|
|
tBuf[#tBuf + 1] = " : "
|
|
tBuf[#tBuf + 1] = sVal
|
|
tBuf[#tBuf + 1] = sHex
|
|
end
|
|
tBuf[#tBuf + 1] = "\r\n"
|
|
end
|
|
|
|
local function errorHandler( err )
|
|
filehandle:write(" ERROR:" .. err .. "\n")
|
|
end
|
|
|
|
|
|
------------MAIN----------------------------------------------------------------
|
|
local _NIL = nil
|
|
local tSeen= {}
|
|
local tcBase = {}
|
|
local tkSortCbase = {}
|
|
local tMods= {}
|
|
local tkSortMods = {}
|
|
local tWriteBuf = {}
|
|
local n = 0 -- count of how many items were found
|
|
|
|
filehandle = io.open(sDumpFile, "w+") --overwrite
|
|
tWriteBuf[#tWriteBuf + 1] = "*Loaded Modules* \n"
|
|
|
|
xpcall( function()
|
|
dump_Tables(tableByName({["val"] = "_G"}),"", tSeen, tMods)
|
|
--you can put a table name here if you just wanted to display
|
|
--only its items, ex. "os" or "rb" or "io"
|
|
--However, it has to be accessible directly from _G
|
|
--so "rb.actions" wouldn't return anything since its technically
|
|
--enumerated through _G.rb
|
|
end , errorHandler )
|
|
tSeen = nil
|
|
|
|
xpcall( function()dump_Functions(tMods)end , errorHandler )
|
|
|
|
get_common_branches(tMods, tcBase)
|
|
|
|
sortbyKeys(tcBase, tkSortCbase)
|
|
sortbyKeys(tMods, tkSortMods)
|
|
|
|
for k, v in pairsByPairs(tcBase, tkSortCbase ) do
|
|
n = n + 1
|
|
if n ~= 1 then
|
|
tWriteBuf[#tWriteBuf + 1] = ", "
|
|
end
|
|
tWriteBuf[#tWriteBuf + 1] = tostring(k)
|
|
if n >= 3 then -- split loaded modules to multiple lines
|
|
n = 0
|
|
tWriteBuf[#tWriteBuf + 1] = "\r\n"
|
|
end
|
|
if #tWriteBuf > 25 then
|
|
filehandle:write(table.concat(tWriteBuf))
|
|
for i=1, #tWriteBuf do tWriteBuf[i] = _NIL end -- reuse table
|
|
end
|
|
end
|
|
if ... then
|
|
tcBase= nil tkSortCbase= nil
|
|
end
|
|
tWriteBuf[#tWriteBuf + 1] = "\r\n"
|
|
tWriteBuf[#tWriteBuf + 1] = dtTag("?")
|
|
tWriteBuf[#tWriteBuf + 1] = "\r\n\r\n"
|
|
tWriteBuf[#tWriteBuf + 1] = "Functions: \r\n"
|
|
|
|
n = 0
|
|
for key, val in pairsByPairs(tMods, tkSortMods) do
|
|
local tkSorted = {}
|
|
local tFuncs = a2m_m2a(val)
|
|
sortbyKeys(tFuncs, tkSorted)
|
|
tWriteBuf[#tWriteBuf + 1] = "\r\n"
|
|
tWriteBuf[#tWriteBuf + 1] = tostring(key)
|
|
tWriteBuf[#tWriteBuf + 1] = "\r\n"
|
|
for k, v in pairsByPairs(tFuncs, tkSorted) do
|
|
n = n + 1
|
|
funcprint(tWriteBuf, k,v)
|
|
if #tWriteBuf > 25 then
|
|
filehandle:write(table.concat(tWriteBuf))
|
|
for i=1, #tWriteBuf do tWriteBuf[i] = _NIL end -- reuse table
|
|
end
|
|
end
|
|
end
|
|
tWriteBuf[#tWriteBuf + 1] = "\r\n\r\n"
|
|
tWriteBuf[#tWriteBuf + 1] = n
|
|
tWriteBuf[#tWriteBuf + 1] = " Items Found \r\n"
|
|
filehandle:write(table.concat(tWriteBuf))
|
|
for i=1, #tWriteBuf do tWriteBuf[i] = _NIL end -- empty table
|
|
filehandle:close()
|
|
--rb.splash((rb.HZ or 100) * 5, n .. " Items dumped to : " .. sDumpFile)
|
|
--rb.splash(500, collectgarbage("count"))
|
|
if not ... then
|
|
local lu = collectgarbage("collect")
|
|
local used, allocd, free = rb.mem_stats()
|
|
local lu = collectgarbage("count")
|
|
local fmt = function(t, v) return string.format("%s: %d Kb\n", t, v /1024) end
|
|
local s_t = {}
|
|
s_t[1] = n
|
|
s_t[2] = " Items dumped to:\n"
|
|
s_t[3] = sDumpFile
|
|
s_t[4] = "\n\nLoaded Modules:\n"
|
|
n = 0
|
|
for k, v in pairsByPairs(tcBase, tkSortCbase ) do
|
|
n = n + 1
|
|
if n ~= 1 then
|
|
s_t[#s_t + 1] = ", "
|
|
end
|
|
s_t[#s_t + 1] = tostring(k)
|
|
if n >= 3 then -- split loaded modules to multiple lines
|
|
n = 0
|
|
s_t[#s_t + 1] = "\n"
|
|
end
|
|
end
|
|
rb.splash_scroller(5 * (rb.HZ or 100), table.concat(s_t))
|
|
end
|