From 8e06e56e16183c18b01bf6941fde8c35b5562655 Mon Sep 17 00:00:00 2001 From: David Walter Seikel Date: Fri, 18 Apr 2014 00:37:17 +1000 Subject: Merge the widget module into the skang module, and some related clean ups. So now the skang module is a mix of C and Lua. --- ClientHamr/GuiLua/GuiLua.c | 90 ++++++++++++++++++++------------------------ ClientHamr/GuiLua/GuiLua.h | 6 +++ ClientHamr/GuiLua/build.sh | 1 - ClientHamr/GuiLua/skang.lua | 6 +++ ClientHamr/GuiLua/test.lua | 3 +- ClientHamr/GuiLua/test.skang | 5 +-- ClientHamr/GuiLua/test_c.c | 24 ++++++------ 7 files changed, 67 insertions(+), 68 deletions(-) diff --git a/ClientHamr/GuiLua/GuiLua.c b/ClientHamr/GuiLua/GuiLua.c index ac156ed..c463eca 100644 --- a/ClientHamr/GuiLua/GuiLua.c +++ b/ClientHamr/GuiLua/GuiLua.c @@ -142,10 +142,9 @@ and ordinary elementary widgets. Proper introspection can come later. #include "GuiLua.h" -globals ourGlobals; -static const char *ourName = "widget"; -static int skang, _M; +globals ourGlobals; +static const char *globName = "ourGlobals"; void dumpStack(lua_State *L, int i) @@ -255,6 +254,7 @@ char *getDateTime(struct tm **nowOut, char *dateOut, time_t *timeOut) // ( Just syntax sugar for call. // call ) Expects an integer, the number of results left after the call. // FIXME: Still to do, if we ever use them - +// stack = Get a value from the stack, expects a stack index. // userdata + // lightuserdata * // thread ^ @@ -445,6 +445,12 @@ int push_lua(lua_State *L, char *params, ...) // Stack usage [-0, +n, em] lua_pushboolean(L, va_arg(vl, int)); // Stack usage [-0, +1, -] break; } + case '=': + { + if (table) q = _push_name(L, q, &i); // Stack usage [-0, +1, m] + lua_pushvalue(L, va_arg(vl, int)); // Stack usage [-0, +1, -] + break; + } case '@': { int tabl = va_arg(vl, int); @@ -528,7 +534,7 @@ static int window(lua_State *L) char *title = NULL; int w = WIDTH, h = HEIGHT; - lua_getfield(L, LUA_REGISTRYINDEX, "ourGlobals"); + lua_getfield(L, LUA_REGISTRYINDEX, globName); ourGlobals = lua_touserdata(L, -1); lua_pop(L, 1); @@ -552,7 +558,7 @@ static int loopWindow(lua_State *L) { globals *ourGlobals; - lua_getfield(L, LUA_REGISTRYINDEX, "ourGlobals"); + lua_getfield(L, LUA_REGISTRYINDEX, globName); ourGlobals = lua_touserdata(L, -1); lua_pop(L, 1); @@ -566,7 +572,7 @@ static int closeWindow(lua_State *L) { globals *ourGlobals; - lua_getfield(L, LUA_REGISTRYINDEX, "ourGlobals"); + lua_getfield(L, LUA_REGISTRYINDEX, globName); ourGlobals = lua_touserdata(L, -1); lua_pop(L, 1); @@ -584,72 +590,59 @@ static int closeWindow(lua_State *L) return 0; } -/* local widget = require 'widget' +/* local widget = require 'libGuiLua' Lua's require() function will strip any stuff from the front of the name -separated by a hyphen, so 'ClientHamr-GuiLua-widget' -> 'widget'. Then -it will search through a path, and eventually find this widget.so (or -widget.dll or whatever), then call luaopen_widget(), which should return +separated by a hyphen, so 'ClientHamr-GuiLua-libGuiLua' -> 'libGuiLua'. Then +it will search through a path, and eventually find this libGuiLua.so (or +libGuiLua.dll or whatever), then call luaopen_libGuiLua(), which should return a table. The argument (only thing on the stack) for this function will -be 'widget'. +be 'libGuiLua'. Normally luaL_register() creates a table of functions, that is the table returned, but we want to do something different with skang. */ -int luaopen_widget(lua_State *L) +int luaopen_libGuiLua(lua_State *L) { - // In theory, the only thing on the stack now is 'widget' from the require() call. + int skang; // In theory this function only ever gets called once. memset(&ourGlobals, 0, sizeof(globals)); loggingStartup(&ourGlobals); - // Shove ourGlobals into the registry. - lua_pushlightuserdata(L, &ourGlobals); - lua_setfield(L, LUA_REGISTRYINDEX, "ourGlobals"); - // pseudo-indices, special tables that can be accessed like the stack - // LUA_GLOBALSINDEX - thread environment, where globals are // LUA_ENVIRONINDEX - C function environment, in this case luaopen_widget() is the C function // LUA_REGISTRYINDEX - C registry, global, for unique keys use the module name as a string, or a lightuserdata address to a C object in our module. // lua_upvalueindex(n) - C function upvalues -// The only locals we care about are skang and _M. -// All modules go into package.loaded[name] as well. -// skang is essentially a global anyway. -// _M we pass back as the result, and our functions get added to it by skang.thingasm() -// Not entirely true, _M is a proxy table, getmetatable(_M).__values[cfunc] would be our function. - -// local skang = require 'skang' - lua_getglobal(L, "require"); - lua_pushstring(L, "skang"); - lua_call(L, 1, 1); + // Shove ourGlobals into the registry. + lua_pushlightuserdata(L, &ourGlobals); + lua_setfield(L, LUA_REGISTRYINDEX, globName); + + // The skang module should have been loaded by now, so we can just grab it out of package.loaded[]. + lua_getglobal(L, "package"); + lua_getfield(L, lua_gettop(L), "loaded"); + lua_remove(L, -2); // Removes "package" + lua_getfield(L, lua_gettop(L), SKANG); + lua_remove(L, -2); // Removes "loaded" + lua_setfield(L, LUA_REGISTRYINDEX, SKANG); + lua_getfield(L, LUA_REGISTRYINDEX, SKANG); // Puts the skang table back on the stack. skang = lua_gettop(L); - lua_setfield(L, LUA_REGISTRYINDEX, "skang"); - lua_getfield(L, LUA_REGISTRYINDEX, "skang"); - -// local _M = skang.moduleBegin('widget', nil, 'Copyright 2014 David Seikel', '0.1', '2014-04-08 00:42:00', nil, false) - push_lua(L, "@ ( $ ~ $ $ $ ~ ! )", skang, "moduleBegin", ourName, "Copyright 2014 David Seikel", "0.1", "2014-04-08 00:42:00", 0, 1); - _M = lua_gettop(L); - - // Save this module in the C registry. - lua_setfield(L, LUA_REGISTRYINDEX, ourName); - lua_getfield(L, LUA_REGISTRYINDEX, ourName); - // Define our functions. - push_lua(L, "@ ( @ $ $ & $ )", skang, "thingasm", LUA_REGISTRYINDEX, ourName, "window", "Opens our window.", window, "number,number,string", 0); - push_lua(L, "@ ( @ $ $ & )", skang, "thingasm", LUA_REGISTRYINDEX, ourName, "loopWindow", "Run our windows main loop.", loopWindow, 0); - push_lua(L, "@ ( @ $ $ & )", skang, "thingasm", LUA_REGISTRYINDEX, ourName, "closeWindow", "Closes our window.", closeWindow, 0); + push_lua(L, "@ ( = $ $ & $ )", skang, THINGASM, skang, "window", "Opens our window.", window, "number,number,string", 0); + push_lua(L, "@ ( = $ $ & )", skang, THINGASM, skang, "loopWindow", "Run our windows main loop.", loopWindow, 0); + push_lua(L, "@ ( = $ $ & )", skang, THINGASM, skang, "closeWindow", "Closes our window.", closeWindow, 0); // A test of the array building stuff. - push_lua(L, "@ ( { @ $ $ % $widget !required } )", skang, "thingasm", LUA_REGISTRYINDEX, ourName, "wibble", "It's wibbly!", 1, "'edit', 'The wibblinator:', 1, 1, 10, 50", 1, 0); - - push_lua(L, "@ ( @ )", skang, "moduleEnd", LUA_REGISTRYINDEX, ourName, 0); + push_lua(L, "@ ( { = $ $ % $widget !required } )", skang, THINGASM, skang, "wibble", "It's wibbly!", 1, "'edit', 'The wibblinator:', 1, 1, 10, 50", 1, 0); + // Makes no difference what we return, but it's expecting something. return 1; } + void GuiLuaDo(int argc, char **argv) { lua_State *L; @@ -672,13 +665,12 @@ void GuiLuaDo(int argc, char **argv) lua_setfield(L, LUA_GLOBALSINDEX, "arg"); - lua_getglobal(L, "require"); - lua_pushstring(L, "skang"); // When we do this, skang will process all the arguments passed to GuiLuaDo(). - // This likely includes a module load, which likely loads the widget module above. + // This likely includes a module load, which likely opens a window. + lua_getglobal(L, "require"); + lua_pushstring(L, SKANG); lua_call(L, 1, 1); - skang = lua_gettop(L); - lua_setfield(L, LUA_REGISTRYINDEX, "skang"); + lua_pop(L, 1); // Ignore the returned value. // Run the main loop via a Lua call. diff --git a/ClientHamr/GuiLua/GuiLua.h b/ClientHamr/GuiLua/GuiLua.h index 1041224..50aa3da 100644 --- a/ClientHamr/GuiLua/GuiLua.h +++ b/ClientHamr/GuiLua/GuiLua.h @@ -29,6 +29,12 @@ typedef struct _globals globals; #define D() PD("DEBUG") +#define SKANG "skang" +#define MODULEBEGIN "moduleBegin" +#define MODULEEND "moduleEnd" +#define THINGASM "thingasm" + + // "01:03:52 01-01-1973\n\0" #define DATE_TIME_LEN 21 # define DATE_TIME_LEN 21 diff --git a/ClientHamr/GuiLua/build.sh b/ClientHamr/GuiLua/build.sh index c39df5b..076c106 100755 --- a/ClientHamr/GuiLua/build.sh +++ b/ClientHamr/GuiLua/build.sh @@ -23,6 +23,5 @@ gcc $CFLAGS -fPIC -shared -o test_c.so test_c.c gcc $CFLAGS -fPIC -c GuiLua.c echo "C libraries" gcc $CFLAGS -shared -Wl,-soname,libGuiLua.so -o libGuiLua.so GuiLua.o -ln -fs libGuiLua.so widget.so echo "C apps" gcc $CFLAGS -Wl,-export-dynamic -o skang skang.c $LDFLAGS -lGuiLua $libs diff --git a/ClientHamr/GuiLua/skang.lua b/ClientHamr/GuiLua/skang.lua index 1357b69..88bd6fb 100644 --- a/ClientHamr/GuiLua/skang.lua +++ b/ClientHamr/GuiLua/skang.lua @@ -977,6 +977,12 @@ set = function (stuff, key, name, value) end end + +-- Get our C functions installed into skang. +-- This has to be after thingasm is defined. +local GuiLua = require 'libGuiLua' + + thingasm('module,l', 'Load a module.', module, 'file') thingasm('get', 'Get the current value of an existing Thing or metadata.', get, 'thing,key,name') thingasm('reset', 'Reset the current value of an existing Thing or metadata.', reset, 'thing,key,name') diff --git a/ClientHamr/GuiLua/test.lua b/ClientHamr/GuiLua/test.lua index 6799154..a7e3b7f 100644 --- a/ClientHamr/GuiLua/test.lua +++ b/ClientHamr/GuiLua/test.lua @@ -4,11 +4,10 @@ do -- Only I'm not gonna indent this. local skang = require 'skang' local _M = skang.moduleBegin('test', nil, 'Copyright 2014 David Seikel', '0.1', '2014-03-27 03:57:00', [[ - local widget = require 'widget' skang.clear skang.window(200, 200, "G'day planet.") - quitter = widget.button('Quit', 0.5, 0.5, 0.5, 0.5) + quitter = skang.button('Quit', 0.5, 0.5, 0.5, 0.5) quitter:action('quit') ]]) diff --git a/ClientHamr/GuiLua/test.skang b/ClientHamr/GuiLua/test.skang index 6d7aab7..99d27e2 100644 --- a/ClientHamr/GuiLua/test.skang +++ b/ClientHamr/GuiLua/test.skang @@ -3,13 +3,12 @@ -- There's an implied local this = require 'test' -- There's an implied local skang = require 'skang' -local widget = require 'widget' -- local other = require 'otherPackageName' skang.clear() -widget.window(500, 500, "G'day planet.") +skang.window(500, 500, "G'day planet.") ---quitter = widget.button('Quit', 0.5, 0.5, 0.5, 0.5) +--quitter = skang.button('Quit', 0.5, 0.5, 0.5, 0.5) --quitter:action('quit') -- 'quit' is looked up in ThingSpace.commands, and translated into the Lua 'skang.quit()'. --other.foo = 'stuff' diff --git a/ClientHamr/GuiLua/test_c.c b/ClientHamr/GuiLua/test_c.c index 37b5c76..5328bda 100644 --- a/ClientHamr/GuiLua/test_c.c +++ b/ClientHamr/GuiLua/test_c.c @@ -55,36 +55,34 @@ int luaopen_test_c(lua_State *L) // local skang = require 'skang' lua_getglobal(L, "require"); - lua_pushstring(L, "skang"); + lua_pushstring(L, SKANG); lua_call(L, 1, 1); + lua_setfield(L, LUA_REGISTRYINDEX, SKANG); + lua_getfield(L, LUA_REGISTRYINDEX, SKANG); skang = lua_gettop(L); - lua_setfield(L, LUA_REGISTRYINDEX, "skang"); - lua_getfield(L, LUA_REGISTRYINDEX, "skang"); - // local _M = skang.moduleBegin('test_c', nil, 'Copyright 2014 David Seikel', '0.1', '2014-03-27 03:57:00', nil, false) - push_lua(L, "@ ( $ ~ $ $ $ ~ ! )", skang, "moduleBegin", ourName, "Copyright 2014 David Seikel", "0.1", "2014-03-27 03:57:00", 0, 1); - _M = lua_gettop(L); - - // Save this module in the C registry. + push_lua(L, "@ ( $ ~ $ $ $ ~ ! )", skang, MODULEBEGIN, ourName, "Copyright 2014 David Seikel", "0.1", "2014-03-27 03:57:00", 0, 1); lua_setfield(L, LUA_REGISTRYINDEX, ourName); lua_getfield(L, LUA_REGISTRYINDEX, ourName); + _M = lua_gettop(L); // This uses function{} style. // skang.thingasm{_M, 'cfooble,c', 'cfooble help text', 1, widget=\"'edit', 'The cfooble:', 1, 1, 10, 50\", required=true} - push_lua(L, "@ ( { @ $ $ % $widget !required } )", skang, "thingasm", LUA_REGISTRYINDEX, ourName, "cfooble,c", "cfooble help text", 1, "'edit', 'The cfooble:', 1, 1, 10, 50", 1, 0); + push_lua(L, "@ ( { = $ $ % $widget !required } )", skang, THINGASM, _M, "cfooble,c", "cfooble help text", 1, "'edit', 'The cfooble:', 1, 1, 10, 50", 1, 0); // skang.thing(_M, 'cbar', 'Help text', 'Default') - push_lua(L, "@ ( @ $ $ $ )", skang, "thingasm", LUA_REGISTRYINDEX, ourName, "cbar", "Help text", "Default", 0); + push_lua(L, "@ ( = $ $ $ )", skang, THINGASM, _M, "cbar", "Help text", "Default", 0); // skang.thingasm(_M, 'cfoo') - push_lua(L, "@ ( @ $ )", skang, "thingasm", LUA_REGISTRYINDEX, ourName, "cfoo", 0); + push_lua(L, "@ ( = $ )", skang, THINGASM, _M, "cfoo", 0); // skang.thingasm(_M, 'cfunc', 'cfunc does nothing really', cfunc, 'number,string') - push_lua(L, "@ ( @ $ $ & $ )", skang, "thingasm", LUA_REGISTRYINDEX, ourName, "cfunc", "cfunc does nothing really", cfunc, "number,string", 0); + push_lua(L, "@ ( = $ $ & $ )", skang, THINGASM, _M, "cfunc", "cfunc does nothing really", cfunc, "number,string", 0); // skang.moduleEnd(_M) - push_lua(L, "@ ( @ )", skang, "moduleEnd", LUA_REGISTRYINDEX, ourName, 0); + push_lua(L, "@ ( = )", skang, MODULEEND, _M, 0); + // Return _M, the table itself, not the index. return 1; } -- cgit v1.1