From adff45ca2167d1bcdc17212db1c20c695a9e8cd9 Mon Sep 17 00:00:00 2001 From: William Wilgus Date: Thu, 6 May 2021 10:34:05 -0400 Subject: [PATCH] lua -- temp loader fix a few bugs, improve memory usage Change-Id: I6ceefd033000a6178eab0dd513679b5d72cec81c --- .../lua/include_lua/create_kbd_layout.lua | 143 ++++++++++-------- apps/plugins/lua/include_lua/menubuttons.lua | 47 +++++- .../lua/include_lua/menucoresettings.lua | 46 ++++-- apps/plugins/lua/include_lua/printtable.lua | 2 +- apps/plugins/lua/include_lua/temploader.lua | 61 ++++++-- apps/plugins/lua/rockaux.c | 2 + apps/plugins/lua_scripts/print_lua_func.lua | 31 +++- 7 files changed, 233 insertions(+), 99 deletions(-) diff --git a/apps/plugins/lua/include_lua/create_kbd_layout.lua b/apps/plugins/lua/include_lua/create_kbd_layout.lua index 3d8f343cc9..7d0792a667 100644 --- a/apps/plugins/lua/include_lua/create_kbd_layout.lua +++ b/apps/plugins/lua/include_lua/create_kbd_layout.lua @@ -1,82 +1,99 @@ +--[[ +/*************************************************************************** + * __________ __ ___. + * Open \______ \ ____ ____ | | _\_ |__ _______ ___ + * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ / + * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < < + * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \ + * \/ \/ \/ \/ \/ + * $Id$ + * + * Copyright (C) 2021 William Wilgus + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY + * KIND, either express or implied. + * + ****************************************************************************/ +]] --create keyboard layout --BILGUS 4/2021 --- kbdlayout = require("create_kbd_layout") --- local layout = kbdlayout.create_keyboard_layout("abcd") -local _kbdlayout = {} do +-- create_kbd_layout = require("create_kbd_layout") +-- local layout = create_kbd_layout("abcd") - local function encode_short(n) - return string.char(bit.band(0x00FF, n), bit.rshift(bit.band(0xFF00, n), 8)) - end +local function encode_short(n) + return string.char(bit.band(0x00FF, n), bit.rshift(bit.band(0xFF00, n), 8)) +end - local function utf8decode(str) - local INVALID = 0xfffd - local t = {} - local function check_char(c) - local tail = false - local code - c = string.byte(c) - if (c <= 0x7f) or (c >= 0xc2) then - -- Start of new character - if (c < 0x80) then -- U-00000000 - U-0000007F, 1 string.byte - code = c; - elseif (c < 0xe0) then -- U-00000080 - U-000007FF, 2 string.bytes - tail = 1; - code = bit.band(c, 0x1f) - elseif (c < 0xf0) then -- U-00000800 - U-0000FFFF, 3 string.bytes - tail = 2; - code = bit.band(c, 0x0f) - elseif (c < 0xf5) then -- U-00010000 - U-001FFFFF, 4 string.bytes - tail = 3; - code = bit.band(c, 0x07) - else - -- Invalid size - code = 0xfffd; - end - - while tail and c ~= 0 do - tail = tail - 1 - if bit.band(c, 0xc0) == 0x80 then - -- Valid continuation character - code = bit.bor(bit.lshift(code, 6),bit.band(c, 0x3f)) - else - -- Invalid continuation char - code = INVALID; - break; - end - end +local function utf8decode(str) + local INVALID = 0xfffd + local t = {} + local function check_char(c) + local tail = false + local code + c = string.byte(c) + if (c <= 0x7f) or (c >= 0xc2) then + -- Start of new character + if (c < 0x80) then -- U-00000000 - U-0000007F, 1 string.byte + code = c; + elseif (c < 0xe0) then -- U-00000080 - U-000007FF, 2 string.bytes + tail = 1; + code = bit.band(c, 0x1f) + elseif (c < 0xf0) then -- U-00000800 - U-0000FFFF, 3 string.bytes + tail = 2; + code = bit.band(c, 0x0f) + elseif (c < 0xf5) then -- U-00010000 - U-001FFFFF, 4 string.bytes + tail = 3; + code = bit.band(c, 0x07) else - -- Invalid UTF-8 char + -- Invalid size code = INVALID; end - -- currently we don't support chars above U-FFFF - t[#t + 1 ] = encode_short((code < 0x10000) and code or 0xfffd) + + while tail and c ~= 0 do + tail = tail - 1 + if bit.band(c, 0xc0) == 0x80 then + -- Valid continuation character + code = bit.bor(bit.lshift(code, 6),bit.band(c, 0x3f)) + else + -- Invalid continuation char + code = INVALID; + break; + end + end + else + -- Invalid UTF-8 char + code = INVALID; end - str:gsub(".", check_char) -- run check function for every char - return table.concat(t) + -- currently we don't support chars above U-FFFF + t[#t + 1 ] = encode_short((code < 0x10000) and code or INVALID) end + str:gsub(".", check_char) -- run check function for every char + return table.concat(t) +end - local function create_keyboard_layout(s_layout) - local insert = table.insert - lines = {} +local function create_keyboard_layout(s_layout) + local insert = table.insert + lines = {} - local t={} - for str in string.gmatch(s_layout, "([^\n]+)") do - local len = string.len(str) - lines[#lines + 1] = - table.concat({encode_short(len), utf8decode(str)}) - end - lines[#lines + 1] = encode_short(0xFEFF) - - return table.concat(lines) + for str in string.gmatch(s_layout, "([^\n]+)") do + local len = string.len(str) + lines[#lines + 1] = + table.concat({encode_short(len), utf8decode(str)}) end - _kbdlayout.create_keyboard_layout = create_keyboard_layout - _kbdlayout.utf8decode = utf8decode + lines[#lines + 1] = encode_short(0xFEFF) + + return table.concat(lines) end --[[ local name = "Test_KBD_LAYOUT_" .. tostring(1) -local test = _kbdlayout.create_keyboard_layout("ABCDEFGHIJKLM\nNOPQRSTUVWXYZ\n0123456789") +local test = create_keyboard_layout("ABCDEFGHIJKLM\nNOPQRSTUVWXYZ\n0123456789") local file = io.open('/' .. name, "w+") -- overwrite, rb ignores the 'b' flag file:write(test)-- write the layout to the file now file:close() @@ -87,4 +104,4 @@ if not file then end rb.kbd_input(name, test) ]] -return _kbdlayout +return create_keyboard_layout diff --git a/apps/plugins/lua/include_lua/menubuttons.lua b/apps/plugins/lua/include_lua/menubuttons.lua index e358d94a10..7c19592bbe 100644 --- a/apps/plugins/lua/include_lua/menubuttons.lua +++ b/apps/plugins/lua/include_lua/menubuttons.lua @@ -1,6 +1,42 @@ +--[[ +/*************************************************************************** + * __________ __ ___. + * Open \______ \ ____ ____ | | _\_ |__ _______ ___ + * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ / + * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < < + * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \ + * \/ \/ \/ \/ \/ + * $Id$ + * + * Copyright (C) 2021 William Wilgus + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY + * KIND, either express or implied. + * + ****************************************************************************/ +]] +-- Bilgus 4/2021 +local oldrb = rb +local tmploader = require("temploader") -local rbac_is_loaded = (package.loaded.actions ~= nil) -require("actions") -- Contains rb.actions & rb.contexts +local a_is_loaded = (package.loaded.actions ~= nil) +local rbold = rb + +if not a_is_loaded then + --replace the rb table so we can keep the defines out of the namespace + rb = {} +end + +--require("actions") -- Contains rb.actions & rb.contexts +local actions, err = tmploader("actions") +if err then + error(err) +end -- Menu Button definitions -- local button_t = { @@ -19,10 +55,5 @@ local button_t = { UPR = rb.actions.PLA_UP_REPEAT, } -if not rbac_is_loaded then - rb.actions = nil - rb.contexts = nil - package.loaded.actionss = nil -end - +rb = oldrb return button_t diff --git a/apps/plugins/lua/include_lua/menucoresettings.lua b/apps/plugins/lua/include_lua/menucoresettings.lua index 01128830f3..13f3b8ea69 100644 --- a/apps/plugins/lua/include_lua/menucoresettings.lua +++ b/apps/plugins/lua/include_lua/menucoresettings.lua @@ -1,19 +1,51 @@ +--[[ +/*************************************************************************** + * __________ __ ___. + * Open \______ \ ____ ____ | | _\_ |__ _______ ___ + * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ / + * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < < + * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \ + * \/ \/ \/ \/ \/ + * $Id$ + * + * Copyright (C) 2021 William Wilgus + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY + * KIND, either express or implied. + * + ****************************************************************************/ +]] --menu core settings loaded from rockbox user settings --Bilgus 4/2021 local function get_core_settings() + local tmploader = require("temploader") + -- rbsettings is a large module to have sitting in RAM + -- if user already has it in RAM then use that local rbs_is_loaded = (package.loaded.rbsettings ~= nil) local s_is_loaded = (package.loaded.settings ~= nil) + local rbold = rb - require("rbsettings") - require("settings") - rb.metadata = nil -- remove track metadata settings + if not rbs_is_loaded then + --replace the rb table so we can keep the defines out of the namespace + rb = { global_settings = rb.global_settings, + global_status = rb.global_status} + end + + tmploader("rbsettings") + tmploader("settings") local rb_settings = rb.settings.dump('global_settings', "system") local color_table = {} local talk_table = {} local list_settings_table = {} local list_settings = "cursor_style|show_icons|statusbar|scrollbar|scrollbar_width|list_separator_height|backdrop_file|" + for key, value in pairs(rb_settings) do key = key or "" if (key:find("color")) then @@ -27,15 +59,9 @@ local function get_core_settings() if not s_is_loaded then rb.settings = nil - package.loaded.settings = nil - end - - if not rbs_is_loaded then - rb.system = nil - rb.metadata = nil - package.loaded.rbsettings = nil end + rb = rbold rb.core_color_table = color_table rb.core_talk_table = talk_table rb.core_list_settings_table = list_settings_table diff --git a/apps/plugins/lua/include_lua/printtable.lua b/apps/plugins/lua/include_lua/printtable.lua index 7a883367b7..c70fc1343f 100644 --- a/apps/plugins/lua/include_lua/printtable.lua +++ b/apps/plugins/lua/include_lua/printtable.lua @@ -337,7 +337,7 @@ function print_table(t, t_count, settings) table_p = init_position(15, 5) line, maxline = _print.opt.area(5, 1, rb.LCD_WIDTH - 10 - sb_width, rb.LCD_HEIGHT - 2) - if curpos > maxline then + if (curpos or 0) > maxline then local c = maxline / 2 start = (start or 1) + curpos - maxline curpos = maxline diff --git a/apps/plugins/lua/include_lua/temploader.lua b/apps/plugins/lua/include_lua/temploader.lua index 69eae468a8..7fd58aee99 100644 --- a/apps/plugins/lua/include_lua/temploader.lua +++ b/apps/plugins/lua/include_lua/temploader.lua @@ -1,30 +1,63 @@ --[[ -temp loader allows some lua requires to be loaded and later garbage collected -unfortunately the module needs to be formatted in such a way to pass back a -call table in order to keep the functions within from being garbage collected -too early +/*************************************************************************** + * __________ __ ___. + * Open \______ \ ____ ____ | | _\_ |__ _______ ___ + * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ / + * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < < + * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \ + * \/ \/ \/ \/ \/ + * $Id$ + * + * Copyright (C) 2021 William Wilgus + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY + * KIND, either express or implied. + * + ****************************************************************************/ +-- +temp_loader allows some (pure) lua requires to be loaded and later garbage collected +unfortunately the 'required' module needs to be formatted in such a way to +pass back a reference to a function or call table in order to keep the functions +within from being garbage collected too early -BE AWARE this bypasses the module loader which would allow code reuse -so if you aren't careful this memory saving tool could spell disaster -for free RAM if you load the same code multiple times +modules that add things to _G table are unaffected by using this function +except if later you use require or temp_loader those tables will again +be reloaded with fresh data since nothing was recorded about the module being loaded + +modulename - same as require() +newinstance == true -- get a new copy (from disk) of the module +... other args for the module + +BE AWARE this bypasses the module loader +which would allow code reuse so if you aren't careful this memory saving tool +could spell disaster for free RAM if you load the same code multiple times --]] - -local function tempload(modulename) +local function tempload(modulename, newinstance, ...) --http://lua-users.org/wiki/LuaModulesLoader local errmsg = "" + -- Is there current a loaded module by this name? + if package.loaded[modulename] ~= nil and not newinstance then + return require(modulename) + end -- Find source local modulepath = string.gsub(modulename, "%.", "/") for path in string.gmatch(package.path, "([^;]+)") do local filename = string.gsub(path, "%?", modulepath) - local file = io.open(filename, "r") + --attempt to open and compile module + local file, err = loadfile(filename) if file then - -- Compile and return the module - return assert(loadstring(assert(file:read("*a")), filename))() + -- execute the compiled chunk + return file(... or modulename) end - errmsg = errmsg.."\n\tno file '"..filename.."' (temp loader)" + errmsg = table.concat({errmsg, "\n\tno file '", filename, "' (temp loader)"}) end - return errmsg + return nil, errmsg end return tempload diff --git a/apps/plugins/lua/rockaux.c b/apps/plugins/lua/rockaux.c index 73fe458889..058ad313fa 100644 --- a/apps/plugins/lua/rockaux.c +++ b/apps/plugins/lua/rockaux.c @@ -52,6 +52,8 @@ char *strerror(int errnum) */ int splash_scroller(int timeout, const char* str) { + if (!str) + str = "[nil]"; int w, ch_w, ch_h; rb->lcd_getstringsize("W", &ch_w, &ch_h); diff --git a/apps/plugins/lua_scripts/print_lua_func.lua b/apps/plugins/lua_scripts/print_lua_func.lua index 8cfbcf0e8e..8519914d5f 100644 --- a/apps/plugins/lua_scripts/print_lua_func.lua +++ b/apps/plugins/lua_scripts/print_lua_func.lua @@ -279,8 +279,9 @@ end for i=1, #tWriteBuf do tWriteBuf[i] = _NIL end -- reuse table end end - - tcBase= nil tkSortCbase= nil + if ... then + tcBase= nil tkSortCbase= nil + end tWriteBuf[#tWriteBuf + 1] = "\r\n" tWriteBuf[#tWriteBuf + 1] = dtTag("?") tWriteBuf[#tWriteBuf + 1] = "\r\n\r\n" @@ -309,5 +310,29 @@ end filehandle:write(table.concat(tWriteBuf)) for i=1, #tWriteBuf do tWriteBuf[i] = _NIL end -- empty table filehandle:close() - rb.splash(rb.HZ * 5, n .. " Items dumped to : " .. sDumpFile) + --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