aboutsummaryrefslogtreecommitdiffstatshomepage
diff options
context:
space:
mode:
authorDavid Walter Seikel2014-04-18 00:37:17 +1000
committerDavid Walter Seikel2014-04-18 00:37:17 +1000
commit8e06e56e16183c18b01bf6941fde8c35b5562655 (patch)
treebe350cd2d49bb52fbf9442ba9e70cfedab848b94
parentConvert test_c to use GuiLua. (diff)
downloadSledjHamr-8e06e56e16183c18b01bf6941fde8c35b5562655.zip
SledjHamr-8e06e56e16183c18b01bf6941fde8c35b5562655.tar.gz
SledjHamr-8e06e56e16183c18b01bf6941fde8c35b5562655.tar.bz2
SledjHamr-8e06e56e16183c18b01bf6941fde8c35b5562655.tar.xz
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.
-rw-r--r--ClientHamr/GuiLua/GuiLua.c90
-rw-r--r--ClientHamr/GuiLua/GuiLua.h6
-rwxr-xr-xClientHamr/GuiLua/build.sh1
-rw-r--r--ClientHamr/GuiLua/skang.lua6
-rw-r--r--ClientHamr/GuiLua/test.lua3
-rw-r--r--ClientHamr/GuiLua/test.skang5
-rw-r--r--ClientHamr/GuiLua/test_c.c24
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.
142 142
143#include "GuiLua.h" 143#include "GuiLua.h"
144 144
145globals ourGlobals;
146 145
147static const char *ourName = "widget"; 146globals ourGlobals;
148static int skang, _M; 147static const char *globName = "ourGlobals";
149 148
150 149
151void dumpStack(lua_State *L, int i) 150void dumpStack(lua_State *L, int i)
@@ -255,6 +254,7 @@ char *getDateTime(struct tm **nowOut, char *dateOut, time_t *timeOut)
255// ( Just syntax sugar for call. 254// ( Just syntax sugar for call.
256// call ) Expects an integer, the number of results left after the call. 255// call ) Expects an integer, the number of results left after the call.
257// FIXME: Still to do, if we ever use them - 256// FIXME: Still to do, if we ever use them -
257// stack = Get a value from the stack, expects a stack index.
258// userdata + 258// userdata +
259// lightuserdata * 259// lightuserdata *
260// thread ^ 260// thread ^
@@ -445,6 +445,12 @@ int push_lua(lua_State *L, char *params, ...) // Stack usage [-0, +n, em]
445 lua_pushboolean(L, va_arg(vl, int)); // Stack usage [-0, +1, -] 445 lua_pushboolean(L, va_arg(vl, int)); // Stack usage [-0, +1, -]
446 break; 446 break;
447 } 447 }
448 case '=':
449 {
450 if (table) q = _push_name(L, q, &i); // Stack usage [-0, +1, m]
451 lua_pushvalue(L, va_arg(vl, int)); // Stack usage [-0, +1, -]
452 break;
453 }
448 case '@': 454 case '@':
449 { 455 {
450 int tabl = va_arg(vl, int); 456 int tabl = va_arg(vl, int);
@@ -528,7 +534,7 @@ static int window(lua_State *L)
528 char *title = NULL; 534 char *title = NULL;
529 int w = WIDTH, h = HEIGHT; 535 int w = WIDTH, h = HEIGHT;
530 536
531 lua_getfield(L, LUA_REGISTRYINDEX, "ourGlobals"); 537 lua_getfield(L, LUA_REGISTRYINDEX, globName);
532 ourGlobals = lua_touserdata(L, -1); 538 ourGlobals = lua_touserdata(L, -1);
533 lua_pop(L, 1); 539 lua_pop(L, 1);
534 540
@@ -552,7 +558,7 @@ static int loopWindow(lua_State *L)
552{ 558{
553 globals *ourGlobals; 559 globals *ourGlobals;
554 560
555 lua_getfield(L, LUA_REGISTRYINDEX, "ourGlobals"); 561 lua_getfield(L, LUA_REGISTRYINDEX, globName);
556 ourGlobals = lua_touserdata(L, -1); 562 ourGlobals = lua_touserdata(L, -1);
557 lua_pop(L, 1); 563 lua_pop(L, 1);
558 564
@@ -566,7 +572,7 @@ static int closeWindow(lua_State *L)
566{ 572{
567 globals *ourGlobals; 573 globals *ourGlobals;
568 574
569 lua_getfield(L, LUA_REGISTRYINDEX, "ourGlobals"); 575 lua_getfield(L, LUA_REGISTRYINDEX, globName);
570 ourGlobals = lua_touserdata(L, -1); 576 ourGlobals = lua_touserdata(L, -1);
571 lua_pop(L, 1); 577 lua_pop(L, 1);
572 578
@@ -584,72 +590,59 @@ static int closeWindow(lua_State *L)
584 return 0; 590 return 0;
585} 591}
586 592
587/* local widget = require 'widget' 593/* local widget = require 'libGuiLua'
588 594
589Lua's require() function will strip any stuff from the front of the name 595Lua's require() function will strip any stuff from the front of the name
590separated by a hyphen, so 'ClientHamr-GuiLua-widget' -> 'widget'. Then 596separated by a hyphen, so 'ClientHamr-GuiLua-libGuiLua' -> 'libGuiLua'. Then
591it will search through a path, and eventually find this widget.so (or 597it will search through a path, and eventually find this libGuiLua.so (or
592widget.dll or whatever), then call luaopen_widget(), which should return 598libGuiLua.dll or whatever), then call luaopen_libGuiLua(), which should return
593a table. The argument (only thing on the stack) for this function will 599a table. The argument (only thing on the stack) for this function will
594be 'widget'. 600be 'libGuiLua'.
595 601
596Normally luaL_register() creates a table of functions, that is the table 602Normally luaL_register() creates a table of functions, that is the table
597returned, but we want to do something different with skang. 603returned, but we want to do something different with skang.
598*/ 604*/
599int luaopen_widget(lua_State *L) 605int luaopen_libGuiLua(lua_State *L)
600{ 606{
601 // In theory, the only thing on the stack now is 'widget' from the require() call. 607 int skang;
602 608
603 // In theory this function only ever gets called once. 609 // In theory this function only ever gets called once.
604 memset(&ourGlobals, 0, sizeof(globals)); 610 memset(&ourGlobals, 0, sizeof(globals));
605 loggingStartup(&ourGlobals); 611 loggingStartup(&ourGlobals);
606 612
607 // Shove ourGlobals into the registry.
608 lua_pushlightuserdata(L, &ourGlobals);
609 lua_setfield(L, LUA_REGISTRYINDEX, "ourGlobals");
610
611// pseudo-indices, special tables that can be accessed like the stack - 613// pseudo-indices, special tables that can be accessed like the stack -
612// LUA_GLOBALSINDEX - thread environment, where globals are 614// LUA_GLOBALSINDEX - thread environment, where globals are
613// LUA_ENVIRONINDEX - C function environment, in this case luaopen_widget() is the C function 615// LUA_ENVIRONINDEX - C function environment, in this case luaopen_widget() is the C function
614// 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. 616// 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.
615// lua_upvalueindex(n) - C function upvalues 617// lua_upvalueindex(n) - C function upvalues
616 618
617// The only locals we care about are skang and _M. 619 // Shove ourGlobals into the registry.
618// All modules go into package.loaded[name] as well. 620 lua_pushlightuserdata(L, &ourGlobals);
619// skang is essentially a global anyway. 621 lua_setfield(L, LUA_REGISTRYINDEX, globName);
620// _M we pass back as the result, and our functions get added to it by skang.thingasm() 622
621// Not entirely true, _M is a proxy table, getmetatable(_M).__values[cfunc] would be our function. 623 // The skang module should have been loaded by now, so we can just grab it out of package.loaded[].
622 624 lua_getglobal(L, "package");
623// local skang = require 'skang' 625 lua_getfield(L, lua_gettop(L), "loaded");
624 lua_getglobal(L, "require"); 626 lua_remove(L, -2); // Removes "package"
625 lua_pushstring(L, "skang"); 627 lua_getfield(L, lua_gettop(L), SKANG);
626 lua_call(L, 1, 1); 628 lua_remove(L, -2); // Removes "loaded"
629 lua_setfield(L, LUA_REGISTRYINDEX, SKANG);
630 lua_getfield(L, LUA_REGISTRYINDEX, SKANG); // Puts the skang table back on the stack.
627 skang = lua_gettop(L); 631 skang = lua_gettop(L);
628 632
629 lua_setfield(L, LUA_REGISTRYINDEX, "skang");
630 lua_getfield(L, LUA_REGISTRYINDEX, "skang");
631
632// local _M = skang.moduleBegin('widget', nil, 'Copyright 2014 David Seikel', '0.1', '2014-04-08 00:42:00', nil, false)
633 push_lua(L, "@ ( $ ~ $ $ $ ~ ! )", skang, "moduleBegin", ourName, "Copyright 2014 David Seikel", "0.1", "2014-04-08 00:42:00", 0, 1);
634 _M = lua_gettop(L);
635
636 // Save this module in the C registry.
637 lua_setfield(L, LUA_REGISTRYINDEX, ourName);
638 lua_getfield(L, LUA_REGISTRYINDEX, ourName);
639
640 // Define our functions. 633 // Define our functions.
641 push_lua(L, "@ ( @ $ $ & $ )", skang, "thingasm", LUA_REGISTRYINDEX, ourName, "window", "Opens our window.", window, "number,number,string", 0); 634 push_lua(L, "@ ( = $ $ & $ )", skang, THINGASM, skang, "window", "Opens our window.", window, "number,number,string", 0);
642 push_lua(L, "@ ( @ $ $ & )", skang, "thingasm", LUA_REGISTRYINDEX, ourName, "loopWindow", "Run our windows main loop.", loopWindow, 0); 635 push_lua(L, "@ ( = $ $ & )", skang, THINGASM, skang, "loopWindow", "Run our windows main loop.", loopWindow, 0);
643 push_lua(L, "@ ( @ $ $ & )", skang, "thingasm", LUA_REGISTRYINDEX, ourName, "closeWindow", "Closes our window.", closeWindow, 0); 636 push_lua(L, "@ ( = $ $ & )", skang, THINGASM, skang, "closeWindow", "Closes our window.", closeWindow, 0);
644 637
645 // A test of the array building stuff. 638 // A test of the array building stuff.
646 push_lua(L, "@ ( { @ $ $ % $widget !required } )", skang, "thingasm", LUA_REGISTRYINDEX, ourName, "wibble", "It's wibbly!", 1, "'edit', 'The wibblinator:', 1, 1, 10, 50", 1, 0); 639 push_lua(L, "@ ( { = $ $ % $widget !required } )", skang, THINGASM, skang, "wibble", "It's wibbly!", 1, "'edit', 'The wibblinator:', 1, 1, 10, 50", 1, 0);
647
648 push_lua(L, "@ ( @ )", skang, "moduleEnd", LUA_REGISTRYINDEX, ourName, 0);
649 640
641 // Makes no difference what we return, but it's expecting something.
650 return 1; 642 return 1;
651} 643}
652 644
645
653void GuiLuaDo(int argc, char **argv) 646void GuiLuaDo(int argc, char **argv)
654{ 647{
655 lua_State *L; 648 lua_State *L;
@@ -672,13 +665,12 @@ void GuiLuaDo(int argc, char **argv)
672 lua_setfield(L, LUA_GLOBALSINDEX, "arg"); 665 lua_setfield(L, LUA_GLOBALSINDEX, "arg");
673 666
674 667
675 lua_getglobal(L, "require");
676 lua_pushstring(L, "skang");
677 // When we do this, skang will process all the arguments passed to GuiLuaDo(). 668 // When we do this, skang will process all the arguments passed to GuiLuaDo().
678 // This likely includes a module load, which likely loads the widget module above. 669 // This likely includes a module load, which likely opens a window.
670 lua_getglobal(L, "require");
671 lua_pushstring(L, SKANG);
679 lua_call(L, 1, 1); 672 lua_call(L, 1, 1);
680 skang = lua_gettop(L); 673 lua_pop(L, 1); // Ignore the returned value.
681 lua_setfield(L, LUA_REGISTRYINDEX, "skang");
682 674
683 675
684 // Run the main loop via a Lua call. 676 // 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;
29 29
30#define D() PD("DEBUG") 30#define D() PD("DEBUG")
31 31
32#define SKANG "skang"
33#define MODULEBEGIN "moduleBegin"
34#define MODULEEND "moduleEnd"
35#define THINGASM "thingasm"
36
37
32// "01:03:52 01-01-1973\n\0" 38// "01:03:52 01-01-1973\n\0"
33#define DATE_TIME_LEN 21 39#define DATE_TIME_LEN 21
34# define DATE_TIME_LEN 21 40# 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
23gcc $CFLAGS -fPIC -c GuiLua.c 23gcc $CFLAGS -fPIC -c GuiLua.c
24echo "C libraries" 24echo "C libraries"
25gcc $CFLAGS -shared -Wl,-soname,libGuiLua.so -o libGuiLua.so GuiLua.o 25gcc $CFLAGS -shared -Wl,-soname,libGuiLua.so -o libGuiLua.so GuiLua.o
26ln -fs libGuiLua.so widget.so
27echo "C apps" 26echo "C apps"
28gcc $CFLAGS -Wl,-export-dynamic -o skang skang.c $LDFLAGS -lGuiLua $libs 27gcc $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)
977 end 977 end
978end 978end
979 979
980
981-- Get our C functions installed into skang.
982-- This has to be after thingasm is defined.
983local GuiLua = require 'libGuiLua'
984
985
980thingasm('module,l', 'Load a module.', module, 'file') 986thingasm('module,l', 'Load a module.', module, 'file')
981thingasm('get', 'Get the current value of an existing Thing or metadata.', get, 'thing,key,name') 987thingasm('get', 'Get the current value of an existing Thing or metadata.', get, 'thing,key,name')
982thingasm('reset', 'Reset the current value of an existing Thing or metadata.', reset, 'thing,key,name') 988thingasm('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.
4 4
5local skang = require 'skang' 5local skang = require 'skang'
6local _M = skang.moduleBegin('test', nil, 'Copyright 2014 David Seikel', '0.1', '2014-03-27 03:57:00', [[ 6local _M = skang.moduleBegin('test', nil, 'Copyright 2014 David Seikel', '0.1', '2014-03-27 03:57:00', [[
7 local widget = require 'widget'
8 7
9 skang.clear 8 skang.clear
10 skang.window(200, 200, "G'day planet.") 9 skang.window(200, 200, "G'day planet.")
11 quitter = widget.button('Quit', 0.5, 0.5, 0.5, 0.5) 10 quitter = skang.button('Quit', 0.5, 0.5, 0.5, 0.5)
12 quitter:action('quit') 11 quitter:action('quit')
13]]) 12]])
14 13
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 @@
3-- There's an implied local this = require 'test' 3-- There's an implied local this = require 'test'
4-- There's an implied local skang = require 'skang' 4-- There's an implied local skang = require 'skang'
5 5
6local widget = require 'widget'
7-- local other = require 'otherPackageName' 6-- local other = require 'otherPackageName'
8 7
9skang.clear() 8skang.clear()
10widget.window(500, 500, "G'day planet.") 9skang.window(500, 500, "G'day planet.")
11 10
12--quitter = widget.button('Quit', 0.5, 0.5, 0.5, 0.5) 11--quitter = skang.button('Quit', 0.5, 0.5, 0.5, 0.5)
13--quitter:action('quit') -- 'quit' is looked up in ThingSpace.commands, and translated into the Lua 'skang.quit()'. 12--quitter:action('quit') -- 'quit' is looked up in ThingSpace.commands, and translated into the Lua 'skang.quit()'.
14 13
15--other.foo = 'stuff' 14--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)
55 55
56// local skang = require 'skang' 56// local skang = require 'skang'
57 lua_getglobal(L, "require"); 57 lua_getglobal(L, "require");
58 lua_pushstring(L, "skang"); 58 lua_pushstring(L, SKANG);
59 lua_call(L, 1, 1); 59 lua_call(L, 1, 1);
60 lua_setfield(L, LUA_REGISTRYINDEX, SKANG);
61 lua_getfield(L, LUA_REGISTRYINDEX, SKANG);
60 skang = lua_gettop(L); 62 skang = lua_gettop(L);
61 63
62 lua_setfield(L, LUA_REGISTRYINDEX, "skang");
63 lua_getfield(L, LUA_REGISTRYINDEX, "skang");
64
65// local _M = skang.moduleBegin('test_c', nil, 'Copyright 2014 David Seikel', '0.1', '2014-03-27 03:57:00', nil, false) 64// local _M = skang.moduleBegin('test_c', nil, 'Copyright 2014 David Seikel', '0.1', '2014-03-27 03:57:00', nil, false)
66 push_lua(L, "@ ( $ ~ $ $ $ ~ ! )", skang, "moduleBegin", ourName, "Copyright 2014 David Seikel", "0.1", "2014-03-27 03:57:00", 0, 1); 65 push_lua(L, "@ ( $ ~ $ $ $ ~ ! )", skang, MODULEBEGIN, ourName, "Copyright 2014 David Seikel", "0.1", "2014-03-27 03:57:00", 0, 1);
67 _M = lua_gettop(L);
68
69 // Save this module in the C registry.
70 lua_setfield(L, LUA_REGISTRYINDEX, ourName); 66 lua_setfield(L, LUA_REGISTRYINDEX, ourName);
71 lua_getfield(L, LUA_REGISTRYINDEX, ourName); 67 lua_getfield(L, LUA_REGISTRYINDEX, ourName);
68 _M = lua_gettop(L);
72 69
73// This uses function{} style. 70// This uses function{} style.
74// skang.thingasm{_M, 'cfooble,c', 'cfooble help text', 1, widget=\"'edit', 'The cfooble:', 1, 1, 10, 50\", required=true} 71// skang.thingasm{_M, 'cfooble,c', 'cfooble help text', 1, widget=\"'edit', 'The cfooble:', 1, 1, 10, 50\", required=true}
75 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); 72 push_lua(L, "@ ( { = $ $ % $widget !required } )", skang, THINGASM, _M, "cfooble,c", "cfooble help text", 1, "'edit', 'The cfooble:', 1, 1, 10, 50", 1, 0);
76 73
77// skang.thing(_M, 'cbar', 'Help text', 'Default') 74// skang.thing(_M, 'cbar', 'Help text', 'Default')
78 push_lua(L, "@ ( @ $ $ $ )", skang, "thingasm", LUA_REGISTRYINDEX, ourName, "cbar", "Help text", "Default", 0); 75 push_lua(L, "@ ( = $ $ $ )", skang, THINGASM, _M, "cbar", "Help text", "Default", 0);
79 76
80// skang.thingasm(_M, 'cfoo') 77// skang.thingasm(_M, 'cfoo')
81 push_lua(L, "@ ( @ $ )", skang, "thingasm", LUA_REGISTRYINDEX, ourName, "cfoo", 0); 78 push_lua(L, "@ ( = $ )", skang, THINGASM, _M, "cfoo", 0);
82 79
83// skang.thingasm(_M, 'cfunc', 'cfunc does nothing really', cfunc, 'number,string') 80// skang.thingasm(_M, 'cfunc', 'cfunc does nothing really', cfunc, 'number,string')
84 push_lua(L, "@ ( @ $ $ & $ )", skang, "thingasm", LUA_REGISTRYINDEX, ourName, "cfunc", "cfunc does nothing really", cfunc, "number,string", 0); 81 push_lua(L, "@ ( = $ $ & $ )", skang, THINGASM, _M, "cfunc", "cfunc does nothing really", cfunc, "number,string", 0);
85 82
86// skang.moduleEnd(_M) 83// skang.moduleEnd(_M)
87 push_lua(L, "@ ( @ )", skang, "moduleEnd", LUA_REGISTRYINDEX, ourName, 0); 84 push_lua(L, "@ ( = )", skang, MODULEEND, _M, 0);
88 85
86 // Return _M, the table itself, not the index.
89 return 1; 87 return 1;
90} 88}