diff options
Diffstat (limited to '')
-rw-r--r-- | ClientHamr/GuiLua/GuiLua.c | 90 |
1 files changed, 41 insertions, 49 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 | ||
145 | globals ourGlobals; | ||
146 | 145 | ||
147 | static const char *ourName = "widget"; | 146 | globals ourGlobals; |
148 | static int skang, _M; | 147 | static const char *globName = "ourGlobals"; |
149 | 148 | ||
150 | 149 | ||
151 | void dumpStack(lua_State *L, int i) | 150 | void 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 | ||
589 | Lua's require() function will strip any stuff from the front of the name | 595 | Lua's require() function will strip any stuff from the front of the name |
590 | separated by a hyphen, so 'ClientHamr-GuiLua-widget' -> 'widget'. Then | 596 | separated by a hyphen, so 'ClientHamr-GuiLua-libGuiLua' -> 'libGuiLua'. Then |
591 | it will search through a path, and eventually find this widget.so (or | 597 | it will search through a path, and eventually find this libGuiLua.so (or |
592 | widget.dll or whatever), then call luaopen_widget(), which should return | 598 | libGuiLua.dll or whatever), then call luaopen_libGuiLua(), which should return |
593 | a table. The argument (only thing on the stack) for this function will | 599 | a table. The argument (only thing on the stack) for this function will |
594 | be 'widget'. | 600 | be 'libGuiLua'. |
595 | 601 | ||
596 | Normally luaL_register() creates a table of functions, that is the table | 602 | Normally luaL_register() creates a table of functions, that is the table |
597 | returned, but we want to do something different with skang. | 603 | returned, but we want to do something different with skang. |
598 | */ | 604 | */ |
599 | int luaopen_widget(lua_State *L) | 605 | int 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 | |||
653 | void GuiLuaDo(int argc, char **argv) | 646 | void 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. |