The MinGW.org Installation Manager Tool
Revision | d44c63915b2c84f4036799602e5753b330d74e3a (tree) |
---|---|
Zeit | 2013-09-21 17:35:52 |
Autor | Keith Marshall <keithmarshall@user...> |
Commiter | Keith Marshall |
Reimplement wsh.lua in C/C++; (cf. MinGW-Bug #2057).
@@ -1,3 +1,23 @@ | ||
1 | +2013-09-21 Keith Marshall <keithmarshall@users.sourceforge.net> | |
2 | + | |
3 | + Reimplement wsh.lua in C/C++; (cf. MinGW-Bug #2057). | |
4 | + | |
5 | + * src/pkgexec.cpp (LUA_INLINE): New function attribute definition. | |
6 | + (init_lua_path): Use it, reproducing the original function attributes. | |
7 | + (lua_isstringarg): New LUA_INLINE helper function; implement it. | |
8 | + (lua_wsh_libexec_path): New function; it implements wsh.libexec_path | |
9 | + (lua_wsh_execute): New function; it implements wsh.execute | |
10 | + (luaload_wsh): New function; it wraps references to lua_wsh_execute() | |
11 | + and lua_wsh_libexec_path() to provide the wsh module implementation. | |
12 | + (pkgXmlNode::DispatchScript): Preload it into the Lua interpreter. | |
13 | + | |
14 | + * scripts/libexec/setup.lua (M.argwrap): New method; implement it. | |
15 | + (M.shlink, M.unlink): Use it to collect their arguments into a single | |
16 | + string, to be passed as the command to be invoked by wsh.execute | |
17 | + | |
18 | + * scripts/libexec/wsh.lua: File is no longer required; delete it. | |
19 | + * Makefile.in (LIBEXEC_SCRIPTS): Remove reference to it. | |
20 | + | |
1 | 21 | 2013-09-20 Keith Marshall <keithmarshall@users.sourceforge.net> |
2 | 22 | |
3 | 23 | Establish default preferences for GUI; (cf. MinGW-Feature #2036) |
@@ -194,10 +194,11 @@ script_srcdir = ${srcdir}/scripts/libexec | ||
194 | 194 | |
195 | 195 | BIN_PROGRAMS = pkginfo$(EXEEXT) mingw-get$(EXEEXT) |
196 | 196 | LIBEXEC_PROGRAMS = guistub$(EXEEXT) guimain$(EXEEXT) lastrites$(EXEEXT) |
197 | -LIBEXEC_SCRIPTS = ${script_srcdir}/setup.lua ${script_srcdir}/wsh.lua \ | |
198 | - ${script_srcdir}/shlink.js ${script_srcdir}/unlink.js | |
199 | 197 | LIBEXEC_DATA = mingw-get-0.dll |
200 | 198 | |
199 | +LIBEXEC_SCRIPTS = ${script_srcdir}/setup.lua \ | |
200 | + ${script_srcdir}/shlink.js ${script_srcdir}/unlink.js | |
201 | + | |
201 | 202 | # Primary build goals... |
202 | 203 | # |
203 | 204 | all: all-core all-setup |
@@ -9,7 +9,7 @@ | ||
9 | 9 | -- This file is a component of mingw-get. |
10 | 10 | -- |
11 | 11 | -- Written by Keith Marshall <keithmarshall@users.sourceforge.net> |
12 | --- Copyright (C) 2012, MinGW Project | |
12 | +-- Copyright (C) 2012, 2013, MinGW.org Project | |
13 | 13 | -- |
14 | 14 | -- |
15 | 15 | -- Permission is hereby granted, free of charge, to any person obtaining a |
@@ -41,17 +41,25 @@ | ||
41 | 41 | return wsh.libexec_path( script, subsystem ) |
42 | 42 | end |
43 | 43 | -- |
44 | + function M.argwrap( arglist, ... ) | |
45 | + for argind, argval in ipairs {...} | |
46 | + do | |
47 | + arglist = arglist .. " " .. argval | |
48 | + end | |
49 | + return arglist | |
50 | + end | |
51 | +-- | |
44 | 52 | function M.shlink( args, ... ) |
45 | 53 | if args |
46 | 54 | then |
47 | - wsh.execute( M.libexec_path( "shlink.js" ), args, ... ) | |
55 | + wsh.execute( M.argwrap( M.libexec_path( "shlink.js" ), args, ... ) ) | |
48 | 56 | end |
49 | 57 | end |
50 | 58 | -- |
51 | 59 | function M.unlink( args, ... ) |
52 | 60 | if args |
53 | 61 | then |
54 | - wsh.execute( M.libexec_path( "unlink.js" ), args, ... ) | |
62 | + wsh.execute( M.argwrap( M.libexec_path( "unlink.js" ), args, ... ) ) | |
55 | 63 | end |
56 | 64 | end |
57 | 65 | -- |
@@ -1,65 +0,0 @@ | ||
1 | --- | |
2 | --- wsh.lua | |
3 | --- | |
4 | --- $Id$ | |
5 | --- | |
6 | --- Lua 5.2 module providing a simple API for invoking system services | |
7 | --- via the Microsoft Windows Scripting Host. | |
8 | --- | |
9 | --- | |
10 | --- This file is a component of mingw-get. | |
11 | --- | |
12 | --- Written by Keith Marshall <keithmarshall@users.sourceforge.net> | |
13 | --- Copyright (C) 2012, MinGW Project | |
14 | --- | |
15 | --- | |
16 | --- Permission is hereby granted, free of charge, to any person obtaining a | |
17 | --- copy of this software and associated documentation files (the "Software"), | |
18 | --- to deal in the Software without restriction, including without limitation | |
19 | --- the rights to use, copy, modify, merge, publish, distribute, sublicense, | |
20 | --- and/or sell copies of the Software, and to permit persons to whom the | |
21 | --- Software is furnished to do so, subject to the following conditions: | |
22 | --- | |
23 | --- The above copyright notice and this permission notice shall be included | |
24 | --- in all copies or substantial portions of the Software. | |
25 | --- | |
26 | --- THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS | |
27 | --- OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, | |
28 | --- FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL | |
29 | --- THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER | |
30 | --- LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING | |
31 | --- FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER | |
32 | --- DEALINGS IN THE SOFTWARE. | |
33 | --- | |
34 | - local M = {} | |
35 | - local cscript = "cscript -nologo" | |
36 | --- | |
37 | - function M.execute( ... ) | |
38 | - local function wsh_prepare( interpreter, ... ) | |
39 | - for argind, argval in ipairs {...} | |
40 | - do | |
41 | - interpreter = interpreter .. " " .. argval | |
42 | - end | |
43 | - return interpreter | |
44 | - end | |
45 | - os.execute( wsh_prepare( cscript, ... ) ) | |
46 | - end | |
47 | --- | |
48 | - function M.libexec_path( script, subsystem ) | |
49 | - local script_path = os.getenv( "APPROOT" ) | |
50 | - if script_path | |
51 | - then | |
52 | - script_path = script_path .. "libexec\\" | |
53 | - else | |
54 | - script_path = ".\\libexec\\" | |
55 | - end | |
56 | - if subsystem | |
57 | - then | |
58 | - script_path = script_path .. subsystem .. "\\" | |
59 | - end | |
60 | - return script_path .. script | |
61 | - end | |
62 | --- | |
63 | - return M | |
64 | --- | |
65 | --- $RCSfile$: end of file */ |
@@ -747,11 +747,14 @@ pkgActionItem::~pkgActionItem() | ||
747 | 747 | * |
748 | 748 | */ |
749 | 749 | #include "lua.hpp" |
750 | +#include <process.h> | |
750 | 751 | |
751 | 752 | static const char *action_key = "action"; |
752 | 753 | static const char *normal_key = "normal"; |
753 | 754 | |
754 | -static inline __attribute__((__always_inline__)) bool init_lua_path() | |
755 | +#define LUA_INLINE static inline __attribute__((__always_inline__)) | |
756 | + | |
757 | +LUA_INLINE bool init_lua_path() | |
755 | 758 | # define LUA_LIBEXEC_PATH "\\libexec\\mingw-get\\?.lua" |
756 | 759 | { |
757 | 760 | /* A one time initialisation hook, to ensure that the built-in Lua script |
@@ -762,6 +765,104 @@ static inline __attribute__((__always_inline__)) bool init_lua_path() | ||
762 | 765 | return true; |
763 | 766 | } |
764 | 767 | |
768 | +LUA_INLINE bool lua_isstringarg( lua_State *interpreter, int arg_index ) | |
769 | +{ | |
770 | + /* Convenience function to check if a particular argument was passed | |
771 | + * from Lua, and if so, if it has a valid string representation. | |
772 | + */ | |
773 | + return lua_isnoneornil( interpreter, arg_index ) ? false | |
774 | + : lua_isstring( interpreter, arg_index ); | |
775 | +} | |
776 | + | |
777 | +static int lua_wsh_libexec_path( lua_State *interpreter ) | |
778 | +{ | |
779 | + /* Implementation for the Lua wsh.libexec_path function; it supports | |
780 | + * usage conforming to either of the function prototypes: | |
781 | + * | |
782 | + * wsh.libexec_path( script ) | |
783 | + * wsh.libexec_path( script, subsystem ) | |
784 | + * | |
785 | + * returning the absolute file system path to "script", within the | |
786 | + * libexec tree for the applicable subsystem, (or for the system in | |
787 | + * general, if no "subsystem" argument is specified). | |
788 | + */ | |
789 | + const char *approot = approot_path(); | |
790 | + const char *script = lua_tostring( interpreter, 1 ); | |
791 | + | |
792 | + if( lua_isstringarg( interpreter, 2 ) ) | |
793 | + { | |
794 | + /* This is the case where a "subsystem" is specified, so we encode | |
795 | + * the applicable subsystem inclusive path name... | |
796 | + */ | |
797 | + const char *path = "%slibexec\\%s\\%s"; | |
798 | + const char *subsystem = lua_tostring( interpreter, 2 ); | |
799 | + char ref[1 + snprintf( NULL, 0, path, approot, subsystem, script )]; | |
800 | + snprintf( ref, sizeof( ref ), path, approot, subsystem, script ); | |
801 | + | |
802 | + /* ...which we then pass back to the Lua caller. | |
803 | + */ | |
804 | + lua_pushstring( interpreter, ref ); | |
805 | + } | |
806 | + else | |
807 | + { /* This is the case where no subsystem has been specified, | |
808 | + * so we encode the general system libexec path name... | |
809 | + */ | |
810 | + const char *path = "%slibexec\\%s"; | |
811 | + char ref[1 + snprintf( NULL, 0, path, approot, script )]; | |
812 | + snprintf( ref, sizeof( ref ), path, approot, script ); | |
813 | + | |
814 | + /* ...again passing it back to the Lua caller. | |
815 | + */ | |
816 | + lua_pushstring( interpreter, ref ); | |
817 | + } | |
818 | + /* In either case, we have one result to pass back. | |
819 | + */ | |
820 | + return 1; | |
821 | +} | |
822 | + | |
823 | +static int lua_wsh_execute( lua_State *interpreter ) | |
824 | +{ | |
825 | + /* Implementation for the Lua wsh.execute function; it conforms to | |
826 | + * an effective function prototype equivalent to: | |
827 | + * | |
828 | + * wsh.execute( command ) | |
829 | + * | |
830 | + * delivering a capability similar to os.execute, but using wscript | |
831 | + * as the command interpreter, rather than the system shell. | |
832 | + */ | |
833 | + if( lua_isstringarg( interpreter, 1 ) ) | |
834 | + { | |
835 | + /* If no "command" is specified, we silently process this as a no-op; | |
836 | + * when a command IS specified, we hand it off to the interpreter. | |
837 | + */ | |
838 | + const char *wsh = "wscript", *mode = "-nologo"; | |
839 | + spawnlp( _P_WAIT, wsh, wsh, mode, lua_tostring( interpreter, 1 ), NULL ); | |
840 | + } | |
841 | + /* Either way, we have nothing to return to the Lua caller. | |
842 | + */ | |
843 | + return 0; | |
844 | +} | |
845 | + | |
846 | +static int luaload_wsh( lua_State *interpreter ) | |
847 | +{ | |
848 | + /* Declare the functions provided by our Windows Script Host | |
849 | + * interface, wrapping them into the Lua "wsh" module... | |
850 | + */ | |
851 | + static struct luaL_Reg wsh_function_registry[] = | |
852 | + { | |
853 | + /* Lua Name Handler Function */ | |
854 | + /* -------------- -------------------- */ | |
855 | + { "execute", lua_wsh_execute }, | |
856 | + { "libexec_path", lua_wsh_libexec_path }, | |
857 | + { NULL, NULL } | |
858 | + }; | |
859 | + | |
860 | + /* ...and register the module within the active interpreter. | |
861 | + */ | |
862 | + luaL_newlib( interpreter, wsh_function_registry ); | |
863 | + return 1; | |
864 | +} | |
865 | + | |
765 | 866 | int pkgXmlNode::DispatchScript |
766 | 867 | ( int status, const char *context, const char *priority, pkgXmlNode *action ) |
767 | 868 | { |
@@ -792,12 +893,16 @@ int pkgXmlNode::DispatchScript | ||
792 | 893 | * have not yet attached an interpreter to this node, then... |
793 | 894 | */ |
794 | 895 | if( (interpreter == NULL) && ((interpreter = luaL_newstate()) != NULL) ) |
795 | - /* | |
796 | - * ...start one now, and initialise it by loading the standard | |
896 | + { | |
897 | + /* ...start one now, initialise it by loading the standard | |
797 | 898 | * lua libraries... |
798 | 899 | */ |
799 | 900 | luaL_openlibs( interpreter ); |
800 | 901 | |
902 | + /* ...and register our Windows Script Host interface... | |
903 | + */ | |
904 | + luaL_requiref( interpreter, "wsh", luaload_wsh, 1 ); | |
905 | + } | |
801 | 906 | /* ...then hand off the current script fragment to this active |
802 | 907 | * lua interpreter... |
803 | 908 | */ |