From 496d0b744c5efbfb463065c4bf1fb45e66bda392 Mon Sep 17 00:00:00 2001 From: icedream Date: Thu, 11 Dec 2014 03:45:22 +0100 Subject: [PATCH] Adding some initial playing around with lua bytecode from secondary local source code copies. --- .gitmodules | 4 ++ GarrysMod.AddonCreator.sln | 6 ++ external/sharplua-mod | 1 + src/addoncreator/Addon/LuaAddonFileInfo.cs | 68 +++++++++++++++++++ src/addoncreator/Compiler/LuaCompiler.cs | 31 +++++++++ src/addoncreator/Extensions.cs | 8 ++- .../GarrysMod.AddonCreator.csproj | 13 ++++ src/addoncreator/packages.config | 1 + 8 files changed, 131 insertions(+), 1 deletion(-) create mode 100644 .gitmodules create mode 160000 external/sharplua-mod create mode 100644 src/addoncreator/Compiler/LuaCompiler.cs diff --git a/.gitmodules b/.gitmodules new file mode 100644 index 0000000..db87836 --- /dev/null +++ b/.gitmodules @@ -0,0 +1,4 @@ +[submodule "external/sharplua-mod"] + path = external/sharplua-mod + url = git://github.com/icedream/SharpLua.git + branch = master diff --git a/GarrysMod.AddonCreator.sln b/GarrysMod.AddonCreator.sln index dc441d0..15bf86a 100644 --- a/GarrysMod.AddonCreator.sln +++ b/GarrysMod.AddonCreator.sln @@ -12,6 +12,8 @@ Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = ".nuget", ".nuget", "{45F8AB .nuget\NuGet.targets = .nuget\NuGet.targets EndProjectSection EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "SharpLua", "external\sharplua-mod\SharpLua\SharpLua.csproj", "{90A9C907-11AD-4754-8B70-51CCB3A6C98A}" +EndProject Global GlobalSection(SolutionConfigurationPlatforms) = preSolution Debug|Any CPU = Debug|Any CPU @@ -22,6 +24,10 @@ Global {E33D031D-7866-40F9-9362-2776CB4A7B5B}.Debug|Any CPU.Build.0 = Debug|Any CPU {E33D031D-7866-40F9-9362-2776CB4A7B5B}.Release|Any CPU.ActiveCfg = Release|Any CPU {E33D031D-7866-40F9-9362-2776CB4A7B5B}.Release|Any CPU.Build.0 = Release|Any CPU + {90A9C907-11AD-4754-8B70-51CCB3A6C98A}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {90A9C907-11AD-4754-8B70-51CCB3A6C98A}.Debug|Any CPU.Build.0 = Debug|Any CPU + {90A9C907-11AD-4754-8B70-51CCB3A6C98A}.Release|Any CPU.ActiveCfg = Release|Any CPU + {90A9C907-11AD-4754-8B70-51CCB3A6C98A}.Release|Any CPU.Build.0 = Release|Any CPU EndGlobalSection GlobalSection(SolutionProperties) = preSolution HideSolutionNode = FALSE diff --git a/external/sharplua-mod b/external/sharplua-mod new file mode 160000 index 0000000..9438735 --- /dev/null +++ b/external/sharplua-mod @@ -0,0 +1 @@ +Subproject commit 9438735d98effb12451fec84afae0b2a29d5d5ac diff --git a/src/addoncreator/Addon/LuaAddonFileInfo.cs b/src/addoncreator/Addon/LuaAddonFileInfo.cs index b39cc06..b5d61de 100644 --- a/src/addoncreator/Addon/LuaAddonFileInfo.cs +++ b/src/addoncreator/Addon/LuaAddonFileInfo.cs @@ -5,6 +5,11 @@ using System.IO; using System.Linq; using System.Text; using System.Text.RegularExpressions; +#if LUA_BYTECODE +using GarrysMod.AddonCreator.Compiler; +using SharpLua; +using SharpLua.Visitors; +#endif namespace GarrysMod.AddonCreator.Addon { @@ -42,9 +47,72 @@ namespace GarrysMod.AddonCreator.Addon _luaCode = Encoding.UTF8.GetString(_fi.GetContents()); _luaCode = Regex.Replace(_luaCode, _stripCommentsRegex, m => m.Groups["linebreak"] != null ? m.Groups["linebreak"].Value : ""); +#if LUA_BYTECODE + GenerateBytecode(); +#else + _content = Encoding.UTF8.GetBytes(_luaCode); +#endif return _content; } +#if LUA_BYTECODE + private void GenerateBytecode() + { + var lua = Lua.lua_open(); + + if (Lua.lua_cpcall(lua, LuaMain, null) != 0) + throw new Exception(); + + Lua.lua_close(lua); + + Debug.WriteLine("Bytecode generated ({0} bytes)", _content.Length); + if (_content.Length == 0) + { + Debugger.Break(); + } + } + + private int LuaMain(Lua.LuaState lua) + { + try + { + var res = Lua.luaL_loadstring(lua, _luaCode); + if (res != 0) + { + Console.Error.WriteLine("ERROR while loading Lua code"); + return -1; + } + + using (var ms = new MemoryStream()) + { + Lua.lua_lock(lua); + Lua.luaU_dump(lua, Lua.clvalue(lua.top - 1).l.p, LuaWriter, ms, 1); + Lua.lua_unlock(lua); + + _content = ms.ToArray(); + } + + return 0; + } + catch (LuaSourceException error) + { + Console.Error.WriteLine("PARSE ERROR - Line {1}, col {2}: {0}", error.Message, error.Line, error.Column); + File.WriteAllText("generated.lua", _luaCode); + return -1; + } + catch (LuaScriptException error) + { + Console.Error.WriteLine("LUA ERROR - {1}: {0}", error.Message, error.Source); + File.WriteAllText("generated.lua", _luaCode); + return -1; + } + } + + static int LuaWriter(Lua.LuaState lua, Lua.CharPtr ptr, uint size, object targetStream) + { + return ((Lua.fwrite(ptr, (int)size, 1, (Stream)targetStream) != 1) && (size != 0)) ? 1 : 0; + } +#endif } } \ No newline at end of file diff --git a/src/addoncreator/Compiler/LuaCompiler.cs b/src/addoncreator/Compiler/LuaCompiler.cs new file mode 100644 index 0000000..2bc2e2e --- /dev/null +++ b/src/addoncreator/Compiler/LuaCompiler.cs @@ -0,0 +1,31 @@ +#if LUA_BYTECODE +using System; +using System.Collections.Generic; +using System.IO; +using System.Linq; +using System.Reflection.Emit; +using System.Text; +using KopiLua; + +namespace GarrysMod.AddonCreator.Compiler +{ + public static class LuaCompiler + { + public static byte[] Compile(string luaCode) + { + var lua = new NLua.Lua(); + + var b = new List(); + + var meth = new Func(() => luaCode); + lua.LoadString(luaCode, "luaCode"); + lua.RegisterFunction("appendBytecode", b, b.GetType().GetMethod("Add")); + lua.RegisterFunction("appendBytecode", b, b.GetType().GetMethod("Add")); + + lua.DoString("for b in string.gmatch(string.dump((luaCode),true),\".\") do appendBytecode(string.byte(b)) end"); + + return b.ToArray(); + } + } +} +#endif \ No newline at end of file diff --git a/src/addoncreator/Extensions.cs b/src/addoncreator/Extensions.cs index 90c42b0..f73d5a8 100644 --- a/src/addoncreator/Extensions.cs +++ b/src/addoncreator/Extensions.cs @@ -1,4 +1,5 @@ -using System.IO; +using System; +using System.IO; using System.Text; using System.Text.RegularExpressions; @@ -41,6 +42,11 @@ namespace GarrysMod.AddonCreator return sb.ToString(); } + public static string EscapeShellArgument(this String s) + { + return "\"" + Regex.Replace(s, @"(\\+)$", @"$1$1") + "\""; + } + /// /// Writes a string. If nullTerminated is true, the string will not be written using native string writing but without length prefix and with NULL char termination instead. /// diff --git a/src/addoncreator/GarrysMod.AddonCreator.csproj b/src/addoncreator/GarrysMod.AddonCreator.csproj index 6347bac..6e64a6e 100644 --- a/src/addoncreator/GarrysMod.AddonCreator.csproj +++ b/src/addoncreator/GarrysMod.AddonCreator.csproj @@ -44,10 +44,16 @@ GarrysMod.AddonCreator.Program + + ..\..\packages\NLua_Safe.1.3.1.5\lib\net40\KopiLua.dll + False $(SolutionDir)\packages\Newtonsoft.Json.6.0.5\lib\net40\Newtonsoft.Json.dll + + ..\..\packages\NLua_Safe.1.3.1.5\lib\net40\NLua.dll + @@ -57,6 +63,7 @@ + @@ -68,6 +75,12 @@ + + + {90a9c907-11ad-4754-8b70-51ccb3a6c98a} + SharpLua + + diff --git a/src/addoncreator/packages.config b/src/addoncreator/packages.config index 3dd77e6..a20b8b6 100644 --- a/src/addoncreator/packages.config +++ b/src/addoncreator/packages.config @@ -2,4 +2,5 @@ + \ No newline at end of file