From 2f5377d0e006bafc39a9dc4154cb8f790b589ea4 Mon Sep 17 00:00:00 2001 From: Nathan Craddock Date: Mon, 8 Jan 2024 21:21:08 -0700 Subject: [PATCH 1/5] fix: update build.zig for module changes --- build.zig | 19 ++++++------------- 1 file changed, 6 insertions(+), 13 deletions(-) diff --git a/build.zig b/build.zig index a11f56d..b88c3ad 100644 --- a/build.zig +++ b/build.zig @@ -23,7 +23,7 @@ pub fn build(b: *Build) void { // Zig module const ziglua = b.addModule("ziglua", .{ - .source_file = switch (lua_version) { + .root_source_file = switch (lua_version) { .lua_51 => .{ .path = "src/ziglua-5.1/lib.zig" }, .lua_52 => .{ .path = "src/ziglua-5.2/lib.zig" }, .lua_53 => .{ .path = "src/ziglua-5.3/lib.zig" }, @@ -70,7 +70,7 @@ pub fn build(b: *Build) void { .target = target, .optimize = optimize, }); - exe.addModule("ziglua", ziglua); + exe.root_module.addImport("ziglua", ziglua); exe.linkLibrary(lib); const artifact = b.addInstallArtifact(exe, .{}); @@ -86,7 +86,7 @@ pub fn build(b: *Build) void { } } -fn buildLua(b: *Build, target: std.zig.CrossTarget, optimize: std.builtin.OptimizeMode, lua_version: LuaVersion, shared: bool) *Step.Compile { +fn buildLua(b: *Build, target: Build.ResolvedTarget, optimize: std.builtin.OptimizeMode, lua_version: LuaVersion, shared: bool) *Step.Compile { const lib_opts = .{ .name = "lua", .target = target, @@ -111,17 +111,14 @@ fn buildLua(b: *Build, target: std.zig.CrossTarget, optimize: std.builtin.Optimi .lua_54 => "lib/lua-5.4/src", else => unreachable, }; - lib.addIncludePath(.{ .path = b.pathJoin(&.{ lib_dir, "include" }) }); - - const os_tag = target.os_tag orelse - (std.zig.system.NativeTargetInfo.detect(target) catch unreachable).target.os.tag; + lib.addIncludePath(.{ .path = lib_dir }); const flags = [_][]const u8{ // Standard version used in Lua Makefile "-std=gnu99", // Define target-specific macro - switch (os_tag) { + switch (target.result.os.tag) { .linux => "-DLUA_USE_LINUX", .macos => "-DLUA_USE_MACOSX", .windows => "-DLUA_USE_WINDOWS", @@ -153,7 +150,7 @@ fn buildLua(b: *Build, target: std.zig.CrossTarget, optimize: std.builtin.Optimi } /// Luau has diverged enough from Lua (C++, project structure, ...) that it is easier to separate the build logic -fn buildLuau(b: *Build, target: std.zig.CrossTarget, optimize: std.builtin.OptimizeMode, shared: bool) *Step.Compile { +fn buildLuau(b: *Build, target: Build.ResolvedTarget, optimize: std.builtin.OptimizeMode, shared: bool) *Step.Compile { const lib_opts = .{ .name = "luau", .target = target, @@ -171,10 +168,6 @@ fn buildLuau(b: *Build, target: std.zig.CrossTarget, optimize: std.builtin.Optim lib.addIncludePath(.{ .path = "lib/luau/Ast/include" }); lib.addIncludePath(.{ .path = b.pathJoin(&.{ lib_dir, "include" }) }); - const os_tag = target.os_tag orelse - (std.zig.system.NativeTargetInfo.detect(target) catch unreachable).target.os.tag; - _ = os_tag; - const flags = [_][]const u8{ "-DLUA_USE_LONGJMP=1", "-DLUA_API=extern\"C\"", From f9ef4207726217153fef2847c85470e694b20e86 Mon Sep 17 00:00:00 2001 From: Nathan Craddock Date: Tue, 9 Jan 2024 08:59:52 -0700 Subject: [PATCH 2/5] Remove vendored lua libraries Use the Zig package manager to download the sources for Lua 5.1 through Lua 5.4. Luau still needs to be done this way. The LuaVersion enum strings are changed to remove the _ characters, this is a breaking change. Also makes the tests rely on the module rather than the raw source file. Not sure if this is a good idea yet, just testing some things. This links the compiled lua library to the ziglua module so it doesn't need to be linked manually in other projects. --- build.zig | 331 +++--- build.zig.zon | 23 +- lib/lua-5.1/COPYRIGHT | 34 - lib/lua-5.1/Makefile | 128 --- lib/lua-5.1/README | 37 - lib/lua-5.1/src/Makefile | 182 ---- lib/lua-5.1/src/lapi.c | 1087 -------------------- lib/lua-5.1/src/lapi.h | 16 - lib/lua-5.1/src/lauxlib.c | 652 ------------ lib/lua-5.1/src/lauxlib.h | 174 ---- lib/lua-5.1/src/lbaselib.c | 653 ------------ lib/lua-5.1/src/lcode.c | 831 --------------- lib/lua-5.1/src/lcode.h | 76 -- lib/lua-5.1/src/ldblib.c | 398 -------- lib/lua-5.1/src/ldebug.c | 638 ------------ lib/lua-5.1/src/ldebug.h | 33 - lib/lua-5.1/src/ldo.c | 519 ---------- lib/lua-5.1/src/ldo.h | 57 -- lib/lua-5.1/src/ldump.c | 164 --- lib/lua-5.1/src/lfunc.c | 174 ---- lib/lua-5.1/src/lfunc.h | 34 - lib/lua-5.1/src/lgc.c | 710 ------------- lib/lua-5.1/src/lgc.h | 110 -- lib/lua-5.1/src/linit.c | 38 - lib/lua-5.1/src/liolib.c | 556 ---------- lib/lua-5.1/src/llex.c | 463 --------- lib/lua-5.1/src/llex.h | 81 -- lib/lua-5.1/src/llimits.h | 128 --- lib/lua-5.1/src/lmathlib.c | 263 ----- lib/lua-5.1/src/lmem.c | 86 -- lib/lua-5.1/src/lmem.h | 49 - lib/lua-5.1/src/loadlib.c | 666 ------------ lib/lua-5.1/src/lobject.c | 214 ---- lib/lua-5.1/src/lobject.h | 381 ------- lib/lua-5.1/src/lopcodes.c | 102 -- lib/lua-5.1/src/lopcodes.h | 268 ----- lib/lua-5.1/src/loslib.c | 243 ----- lib/lua-5.1/src/lparser.c | 1339 ------------------------ lib/lua-5.1/src/lparser.h | 82 -- lib/lua-5.1/src/lstate.c | 214 ---- lib/lua-5.1/src/lstate.h | 169 ---- lib/lua-5.1/src/lstring.c | 111 -- lib/lua-5.1/src/lstring.h | 31 - lib/lua-5.1/src/lstrlib.c | 871 ---------------- lib/lua-5.1/src/ltable.c | 588 ----------- lib/lua-5.1/src/ltable.h | 40 - lib/lua-5.1/src/ltablib.c | 287 ------ lib/lua-5.1/src/ltm.c | 75 -- lib/lua-5.1/src/ltm.h | 54 - lib/lua-5.1/src/lua.c | 392 ------- lib/lua-5.1/src/lua.h | 388 ------- lib/lua-5.1/src/luac.c | 200 ---- lib/lua-5.1/src/luaconf.h | 763 -------------- lib/lua-5.1/src/lualib.h | 53 - lib/lua-5.1/src/lundump.c | 227 ----- lib/lua-5.1/src/lundump.h | 36 - lib/lua-5.1/src/lvm.c | 767 -------------- lib/lua-5.1/src/lvm.h | 36 - lib/lua-5.1/src/lzio.c | 82 -- lib/lua-5.1/src/lzio.h | 67 -- lib/lua-5.1/src/print.c | 227 ----- lib/lua-5.2/Makefile | 114 --- lib/lua-5.2/README | 6 - lib/lua-5.2/license | 7 - lib/lua-5.2/src/Makefile | 187 ---- lib/lua-5.2/src/lapi.c | 1284 ----------------------- lib/lua-5.2/src/lapi.h | 24 - lib/lua-5.2/src/lauxlib.c | 959 ------------------ lib/lua-5.2/src/lauxlib.h | 212 ---- lib/lua-5.2/src/lbaselib.c | 458 --------- lib/lua-5.2/src/lbitlib.c | 212 ---- lib/lua-5.2/src/lcode.c | 881 ---------------- lib/lua-5.2/src/lcode.h | 83 -- lib/lua-5.2/src/lcorolib.c | 155 --- lib/lua-5.2/src/lctype.c | 52 - lib/lua-5.2/src/lctype.h | 95 -- lib/lua-5.2/src/ldblib.c | 408 -------- lib/lua-5.2/src/ldebug.c | 610 ----------- lib/lua-5.2/src/ldebug.h | 34 - lib/lua-5.2/src/ldo.c | 681 ------------- lib/lua-5.2/src/ldo.h | 46 - lib/lua-5.2/src/ldump.c | 173 ---- lib/lua-5.2/src/lfunc.c | 161 --- lib/lua-5.2/src/lfunc.h | 33 - lib/lua-5.2/src/lgc.c | 1220 ---------------------- lib/lua-5.2/src/lgc.h | 157 --- lib/lua-5.2/src/linit.c | 67 -- lib/lua-5.2/src/liolib.c | 666 ------------ lib/lua-5.2/src/llex.c | 530 ---------- lib/lua-5.2/src/llex.h | 78 -- lib/lua-5.2/src/llimits.h | 309 ------ lib/lua-5.2/src/lmathlib.c | 279 ----- lib/lua-5.2/src/lmem.c | 99 -- lib/lua-5.2/src/lmem.h | 57 -- lib/lua-5.2/src/loadlib.c | 725 ------------- lib/lua-5.2/src/lobject.c | 287 ------ lib/lua-5.2/src/lobject.h | 607 ----------- lib/lua-5.2/src/lopcodes.c | 107 -- lib/lua-5.2/src/lopcodes.h | 288 ------ lib/lua-5.2/src/loslib.c | 323 ------ lib/lua-5.2/src/lparser.c | 1638 ------------------------------ lib/lua-5.2/src/lparser.h | 119 --- lib/lua-5.2/src/lstate.c | 323 ------ lib/lua-5.2/src/lstate.h | 228 ----- lib/lua-5.2/src/lstring.c | 185 ---- lib/lua-5.2/src/lstring.h | 46 - lib/lua-5.2/src/lstrlib.c | 1019 ------------------- lib/lua-5.2/src/ltable.c | 588 ----------- lib/lua-5.2/src/ltable.h | 45 - lib/lua-5.2/src/ltablib.c | 285 ------ lib/lua-5.2/src/ltm.c | 77 -- lib/lua-5.2/src/ltm.h | 57 -- lib/lua-5.2/src/lua.c | 497 --------- lib/lua-5.2/src/lua.h | 444 -------- lib/lua-5.2/src/lua.hpp | 9 - lib/lua-5.2/src/luac.c | 432 -------- lib/lua-5.2/src/luaconf.h | 551 ---------- lib/lua-5.2/src/lualib.h | 55 - lib/lua-5.2/src/lundump.c | 258 ----- lib/lua-5.2/src/lundump.h | 28 - lib/lua-5.2/src/lvm.c | 867 ---------------- lib/lua-5.2/src/lvm.h | 44 - lib/lua-5.2/src/lzio.c | 76 -- lib/lua-5.2/src/lzio.h | 65 -- lib/lua-5.3/Makefile | 114 --- lib/lua-5.3/README | 6 - lib/lua-5.3/license | 7 - lib/lua-5.3/src/Makefile | 197 ---- lib/lua-5.3/src/lapi.c | 1299 ------------------------ lib/lua-5.3/src/lapi.h | 24 - lib/lua-5.3/src/lauxlib.c | 1048 ------------------- lib/lua-5.3/src/lauxlib.h | 264 ----- lib/lua-5.3/src/lbaselib.c | 498 --------- lib/lua-5.3/src/lbitlib.c | 233 ----- lib/lua-5.3/src/lcode.c | 1203 ---------------------- lib/lua-5.3/src/lcode.h | 88 -- lib/lua-5.3/src/lcorolib.c | 168 --- lib/lua-5.3/src/lctype.c | 55 - lib/lua-5.3/src/lctype.h | 95 -- lib/lua-5.3/src/ldblib.c | 456 --------- lib/lua-5.3/src/ldebug.c | 700 ------------- lib/lua-5.3/src/ldebug.h | 39 - lib/lua-5.3/src/ldo.c | 802 --------------- lib/lua-5.3/src/ldo.h | 58 -- lib/lua-5.3/src/ldump.c | 215 ---- lib/lua-5.3/src/lfunc.c | 151 --- lib/lua-5.3/src/lfunc.h | 61 -- lib/lua-5.3/src/lgc.c | 1179 --------------------- lib/lua-5.3/src/lgc.h | 147 --- lib/lua-5.3/src/linit.c | 68 -- lib/lua-5.3/src/liolib.c | 778 -------------- lib/lua-5.3/src/llex.c | 568 ----------- lib/lua-5.3/src/llex.h | 85 -- lib/lua-5.3/src/llimits.h | 323 ------ lib/lua-5.3/src/lmathlib.c | 410 -------- lib/lua-5.3/src/lmem.c | 100 -- lib/lua-5.3/src/lmem.h | 69 -- lib/lua-5.3/src/loadlib.c | 790 --------------- lib/lua-5.3/src/lobject.c | 522 ---------- lib/lua-5.3/src/lobject.h | 549 ---------- lib/lua-5.3/src/lopcodes.c | 124 --- lib/lua-5.3/src/lopcodes.h | 297 ------ lib/lua-5.3/src/loslib.c | 409 -------- lib/lua-5.3/src/lparser.c | 1653 ------------------------------ lib/lua-5.3/src/lparser.h | 133 --- lib/lua-5.3/src/lprefix.h | 45 - lib/lua-5.3/src/lstate.c | 347 ------- lib/lua-5.3/src/lstate.h | 253 ----- lib/lua-5.3/src/lstring.c | 248 ----- lib/lua-5.3/src/lstring.h | 49 - lib/lua-5.3/src/lstrlib.c | 1584 ----------------------------- lib/lua-5.3/src/ltable.c | 688 ------------- lib/lua-5.3/src/ltable.h | 66 -- lib/lua-5.3/src/ltablib.c | 450 --------- lib/lua-5.3/src/ltm.c | 165 --- lib/lua-5.3/src/ltm.h | 76 -- lib/lua-5.3/src/lua.c | 612 ----------- lib/lua-5.3/src/lua.h | 485 --------- lib/lua-5.3/src/lua.hpp | 9 - lib/lua-5.3/src/luac.c | 450 --------- lib/lua-5.3/src/luaconf.h | 790 --------------- lib/lua-5.3/src/lualib.h | 61 -- lib/lua-5.3/src/lundump.c | 287 ------ lib/lua-5.3/src/lundump.h | 32 - lib/lua-5.3/src/lutf8lib.c | 256 ----- lib/lua-5.3/src/lvm.c | 1322 ------------------------ lib/lua-5.3/src/lvm.h | 113 --- lib/lua-5.3/src/lzio.c | 68 -- lib/lua-5.3/src/lzio.h | 66 -- lib/lua-5.4/Makefile | 106 -- lib/lua-5.4/README | 6 - lib/lua-5.4/license | 7 - lib/lua-5.4/src/Makefile | 225 ----- lib/lua-5.4/src/lapi.c | 1463 --------------------------- lib/lua-5.4/src/lapi.h | 52 - lib/lua-5.4/src/lauxlib.c | 1112 -------------------- lib/lua-5.4/src/lauxlib.h | 301 ------ lib/lua-5.4/src/lbaselib.c | 549 ---------- lib/lua-5.4/src/lcode.c | 1871 ---------------------------------- lib/lua-5.4/src/lcode.h | 104 -- lib/lua-5.4/src/lcorolib.c | 210 ---- lib/lua-5.4/src/lctype.c | 64 -- lib/lua-5.4/src/lctype.h | 101 -- lib/lua-5.4/src/ldblib.c | 483 --------- lib/lua-5.4/src/ldebug.c | 924 ----------------- lib/lua-5.4/src/ldebug.h | 63 -- lib/lua-5.4/src/ldo.c | 1024 ------------------- lib/lua-5.4/src/ldo.h | 88 -- lib/lua-5.4/src/ldump.c | 230 ----- lib/lua-5.4/src/lfunc.c | 294 ------ lib/lua-5.4/src/lfunc.h | 64 -- lib/lua-5.4/src/lgc.c | 1739 ------------------------------- lib/lua-5.4/src/lgc.h | 202 ---- lib/lua-5.4/src/linit.c | 65 -- lib/lua-5.4/src/liolib.c | 828 --------------- lib/lua-5.4/src/ljumptab.h | 112 -- lib/lua-5.4/src/llex.c | 581 ----------- lib/lua-5.4/src/llex.h | 91 -- lib/lua-5.4/src/llimits.h | 380 ------- lib/lua-5.4/src/lmathlib.c | 764 -------------- lib/lua-5.4/src/lmem.c | 215 ---- lib/lua-5.4/src/lmem.h | 93 -- lib/lua-5.4/src/loadlib.c | 767 -------------- lib/lua-5.4/src/lobject.c | 602 ----------- lib/lua-5.4/src/lobject.h | 815 --------------- lib/lua-5.4/src/lopcodes.c | 104 -- lib/lua-5.4/src/lopcodes.h | 405 -------- lib/lua-5.4/src/lopnames.h | 103 -- lib/lua-5.4/src/loslib.c | 428 -------- lib/lua-5.4/src/lparser.c | 1967 ------------------------------------ lib/lua-5.4/src/lparser.h | 171 ---- lib/lua-5.4/src/lprefix.h | 45 - lib/lua-5.4/src/lstate.c | 445 -------- lib/lua-5.4/src/lstate.h | 409 -------- lib/lua-5.4/src/lstring.c | 273 ----- lib/lua-5.4/src/lstring.h | 57 -- lib/lua-5.4/src/lstrlib.c | 1874 ---------------------------------- lib/lua-5.4/src/ltable.c | 980 ------------------ lib/lua-5.4/src/ltable.h | 65 -- lib/lua-5.4/src/ltablib.c | 430 -------- lib/lua-5.4/src/ltm.c | 271 ----- lib/lua-5.4/src/ltm.h | 104 -- lib/lua-5.4/src/lua.c | 679 ------------- lib/lua-5.4/src/lua.h | 523 ---------- lib/lua-5.4/src/lua.hpp | 9 - lib/lua-5.4/src/luac.c | 723 ------------- lib/lua-5.4/src/luaconf.h | 793 --------------- lib/lua-5.4/src/lualib.h | 52 - lib/lua-5.4/src/lundump.c | 335 ------ lib/lua-5.4/src/lundump.h | 36 - lib/lua-5.4/src/lutf8lib.c | 291 ------ lib/lua-5.4/src/lvm.c | 1901 ---------------------------------- lib/lua-5.4/src/lvm.h | 141 --- lib/lua-5.4/src/lzio.c | 68 -- lib/lua-5.4/src/lzio.h | 66 -- makefile | 8 +- src/ziglua-5.1/lib.zig | 6 +- src/ziglua-5.1/tests.zig | 2 +- src/ziglua-5.2/lib.zig | 6 +- src/ziglua-5.2/tests.zig | 2 +- src/ziglua-5.3/lib.zig | 6 +- src/ziglua-5.3/tests.zig | 2 +- src/ziglua-5.4/lib.zig | 6 +- src/ziglua-5.4/tests.zig | 2 +- 264 files changed, 203 insertions(+), 92995 deletions(-) delete mode 100644 lib/lua-5.1/COPYRIGHT delete mode 100644 lib/lua-5.1/Makefile delete mode 100644 lib/lua-5.1/README delete mode 100644 lib/lua-5.1/src/Makefile delete mode 100644 lib/lua-5.1/src/lapi.c delete mode 100644 lib/lua-5.1/src/lapi.h delete mode 100644 lib/lua-5.1/src/lauxlib.c delete mode 100644 lib/lua-5.1/src/lauxlib.h delete mode 100644 lib/lua-5.1/src/lbaselib.c delete mode 100644 lib/lua-5.1/src/lcode.c delete mode 100644 lib/lua-5.1/src/lcode.h delete mode 100644 lib/lua-5.1/src/ldblib.c delete mode 100644 lib/lua-5.1/src/ldebug.c delete mode 100644 lib/lua-5.1/src/ldebug.h delete mode 100644 lib/lua-5.1/src/ldo.c delete mode 100644 lib/lua-5.1/src/ldo.h delete mode 100644 lib/lua-5.1/src/ldump.c delete mode 100644 lib/lua-5.1/src/lfunc.c delete mode 100644 lib/lua-5.1/src/lfunc.h delete mode 100644 lib/lua-5.1/src/lgc.c delete mode 100644 lib/lua-5.1/src/lgc.h delete mode 100644 lib/lua-5.1/src/linit.c delete mode 100644 lib/lua-5.1/src/liolib.c delete mode 100644 lib/lua-5.1/src/llex.c delete mode 100644 lib/lua-5.1/src/llex.h delete mode 100644 lib/lua-5.1/src/llimits.h delete mode 100644 lib/lua-5.1/src/lmathlib.c delete mode 100644 lib/lua-5.1/src/lmem.c delete mode 100644 lib/lua-5.1/src/lmem.h delete mode 100644 lib/lua-5.1/src/loadlib.c delete mode 100644 lib/lua-5.1/src/lobject.c delete mode 100644 lib/lua-5.1/src/lobject.h delete mode 100644 lib/lua-5.1/src/lopcodes.c delete mode 100644 lib/lua-5.1/src/lopcodes.h delete mode 100644 lib/lua-5.1/src/loslib.c delete mode 100644 lib/lua-5.1/src/lparser.c delete mode 100644 lib/lua-5.1/src/lparser.h delete mode 100644 lib/lua-5.1/src/lstate.c delete mode 100644 lib/lua-5.1/src/lstate.h delete mode 100644 lib/lua-5.1/src/lstring.c delete mode 100644 lib/lua-5.1/src/lstring.h delete mode 100644 lib/lua-5.1/src/lstrlib.c delete mode 100644 lib/lua-5.1/src/ltable.c delete mode 100644 lib/lua-5.1/src/ltable.h delete mode 100644 lib/lua-5.1/src/ltablib.c delete mode 100644 lib/lua-5.1/src/ltm.c delete mode 100644 lib/lua-5.1/src/ltm.h delete mode 100644 lib/lua-5.1/src/lua.c delete mode 100644 lib/lua-5.1/src/lua.h delete mode 100644 lib/lua-5.1/src/luac.c delete mode 100644 lib/lua-5.1/src/luaconf.h delete mode 100644 lib/lua-5.1/src/lualib.h delete mode 100644 lib/lua-5.1/src/lundump.c delete mode 100644 lib/lua-5.1/src/lundump.h delete mode 100644 lib/lua-5.1/src/lvm.c delete mode 100644 lib/lua-5.1/src/lvm.h delete mode 100644 lib/lua-5.1/src/lzio.c delete mode 100644 lib/lua-5.1/src/lzio.h delete mode 100644 lib/lua-5.1/src/print.c delete mode 100644 lib/lua-5.2/Makefile delete mode 100644 lib/lua-5.2/README delete mode 100644 lib/lua-5.2/license delete mode 100644 lib/lua-5.2/src/Makefile delete mode 100644 lib/lua-5.2/src/lapi.c delete mode 100644 lib/lua-5.2/src/lapi.h delete mode 100644 lib/lua-5.2/src/lauxlib.c delete mode 100644 lib/lua-5.2/src/lauxlib.h delete mode 100644 lib/lua-5.2/src/lbaselib.c delete mode 100644 lib/lua-5.2/src/lbitlib.c delete mode 100644 lib/lua-5.2/src/lcode.c delete mode 100644 lib/lua-5.2/src/lcode.h delete mode 100644 lib/lua-5.2/src/lcorolib.c delete mode 100644 lib/lua-5.2/src/lctype.c delete mode 100644 lib/lua-5.2/src/lctype.h delete mode 100644 lib/lua-5.2/src/ldblib.c delete mode 100644 lib/lua-5.2/src/ldebug.c delete mode 100644 lib/lua-5.2/src/ldebug.h delete mode 100644 lib/lua-5.2/src/ldo.c delete mode 100644 lib/lua-5.2/src/ldo.h delete mode 100644 lib/lua-5.2/src/ldump.c delete mode 100644 lib/lua-5.2/src/lfunc.c delete mode 100644 lib/lua-5.2/src/lfunc.h delete mode 100644 lib/lua-5.2/src/lgc.c delete mode 100644 lib/lua-5.2/src/lgc.h delete mode 100644 lib/lua-5.2/src/linit.c delete mode 100644 lib/lua-5.2/src/liolib.c delete mode 100644 lib/lua-5.2/src/llex.c delete mode 100644 lib/lua-5.2/src/llex.h delete mode 100644 lib/lua-5.2/src/llimits.h delete mode 100644 lib/lua-5.2/src/lmathlib.c delete mode 100644 lib/lua-5.2/src/lmem.c delete mode 100644 lib/lua-5.2/src/lmem.h delete mode 100644 lib/lua-5.2/src/loadlib.c delete mode 100644 lib/lua-5.2/src/lobject.c delete mode 100644 lib/lua-5.2/src/lobject.h delete mode 100644 lib/lua-5.2/src/lopcodes.c delete mode 100644 lib/lua-5.2/src/lopcodes.h delete mode 100644 lib/lua-5.2/src/loslib.c delete mode 100644 lib/lua-5.2/src/lparser.c delete mode 100644 lib/lua-5.2/src/lparser.h delete mode 100644 lib/lua-5.2/src/lstate.c delete mode 100644 lib/lua-5.2/src/lstate.h delete mode 100644 lib/lua-5.2/src/lstring.c delete mode 100644 lib/lua-5.2/src/lstring.h delete mode 100644 lib/lua-5.2/src/lstrlib.c delete mode 100644 lib/lua-5.2/src/ltable.c delete mode 100644 lib/lua-5.2/src/ltable.h delete mode 100644 lib/lua-5.2/src/ltablib.c delete mode 100644 lib/lua-5.2/src/ltm.c delete mode 100644 lib/lua-5.2/src/ltm.h delete mode 100644 lib/lua-5.2/src/lua.c delete mode 100644 lib/lua-5.2/src/lua.h delete mode 100644 lib/lua-5.2/src/lua.hpp delete mode 100644 lib/lua-5.2/src/luac.c delete mode 100644 lib/lua-5.2/src/luaconf.h delete mode 100644 lib/lua-5.2/src/lualib.h delete mode 100644 lib/lua-5.2/src/lundump.c delete mode 100644 lib/lua-5.2/src/lundump.h delete mode 100644 lib/lua-5.2/src/lvm.c delete mode 100644 lib/lua-5.2/src/lvm.h delete mode 100644 lib/lua-5.2/src/lzio.c delete mode 100644 lib/lua-5.2/src/lzio.h delete mode 100644 lib/lua-5.3/Makefile delete mode 100644 lib/lua-5.3/README delete mode 100644 lib/lua-5.3/license delete mode 100644 lib/lua-5.3/src/Makefile delete mode 100644 lib/lua-5.3/src/lapi.c delete mode 100644 lib/lua-5.3/src/lapi.h delete mode 100644 lib/lua-5.3/src/lauxlib.c delete mode 100644 lib/lua-5.3/src/lauxlib.h delete mode 100644 lib/lua-5.3/src/lbaselib.c delete mode 100644 lib/lua-5.3/src/lbitlib.c delete mode 100644 lib/lua-5.3/src/lcode.c delete mode 100644 lib/lua-5.3/src/lcode.h delete mode 100644 lib/lua-5.3/src/lcorolib.c delete mode 100644 lib/lua-5.3/src/lctype.c delete mode 100644 lib/lua-5.3/src/lctype.h delete mode 100644 lib/lua-5.3/src/ldblib.c delete mode 100644 lib/lua-5.3/src/ldebug.c delete mode 100644 lib/lua-5.3/src/ldebug.h delete mode 100644 lib/lua-5.3/src/ldo.c delete mode 100644 lib/lua-5.3/src/ldo.h delete mode 100644 lib/lua-5.3/src/ldump.c delete mode 100644 lib/lua-5.3/src/lfunc.c delete mode 100644 lib/lua-5.3/src/lfunc.h delete mode 100644 lib/lua-5.3/src/lgc.c delete mode 100644 lib/lua-5.3/src/lgc.h delete mode 100644 lib/lua-5.3/src/linit.c delete mode 100644 lib/lua-5.3/src/liolib.c delete mode 100644 lib/lua-5.3/src/llex.c delete mode 100644 lib/lua-5.3/src/llex.h delete mode 100644 lib/lua-5.3/src/llimits.h delete mode 100644 lib/lua-5.3/src/lmathlib.c delete mode 100644 lib/lua-5.3/src/lmem.c delete mode 100644 lib/lua-5.3/src/lmem.h delete mode 100644 lib/lua-5.3/src/loadlib.c delete mode 100644 lib/lua-5.3/src/lobject.c delete mode 100644 lib/lua-5.3/src/lobject.h delete mode 100644 lib/lua-5.3/src/lopcodes.c delete mode 100644 lib/lua-5.3/src/lopcodes.h delete mode 100644 lib/lua-5.3/src/loslib.c delete mode 100644 lib/lua-5.3/src/lparser.c delete mode 100644 lib/lua-5.3/src/lparser.h delete mode 100644 lib/lua-5.3/src/lprefix.h delete mode 100644 lib/lua-5.3/src/lstate.c delete mode 100644 lib/lua-5.3/src/lstate.h delete mode 100644 lib/lua-5.3/src/lstring.c delete mode 100644 lib/lua-5.3/src/lstring.h delete mode 100644 lib/lua-5.3/src/lstrlib.c delete mode 100644 lib/lua-5.3/src/ltable.c delete mode 100644 lib/lua-5.3/src/ltable.h delete mode 100644 lib/lua-5.3/src/ltablib.c delete mode 100644 lib/lua-5.3/src/ltm.c delete mode 100644 lib/lua-5.3/src/ltm.h delete mode 100644 lib/lua-5.3/src/lua.c delete mode 100644 lib/lua-5.3/src/lua.h delete mode 100644 lib/lua-5.3/src/lua.hpp delete mode 100644 lib/lua-5.3/src/luac.c delete mode 100644 lib/lua-5.3/src/luaconf.h delete mode 100644 lib/lua-5.3/src/lualib.h delete mode 100644 lib/lua-5.3/src/lundump.c delete mode 100644 lib/lua-5.3/src/lundump.h delete mode 100644 lib/lua-5.3/src/lutf8lib.c delete mode 100644 lib/lua-5.3/src/lvm.c delete mode 100644 lib/lua-5.3/src/lvm.h delete mode 100644 lib/lua-5.3/src/lzio.c delete mode 100644 lib/lua-5.3/src/lzio.h delete mode 100644 lib/lua-5.4/Makefile delete mode 100644 lib/lua-5.4/README delete mode 100644 lib/lua-5.4/license delete mode 100644 lib/lua-5.4/src/Makefile delete mode 100644 lib/lua-5.4/src/lapi.c delete mode 100644 lib/lua-5.4/src/lapi.h delete mode 100644 lib/lua-5.4/src/lauxlib.c delete mode 100644 lib/lua-5.4/src/lauxlib.h delete mode 100644 lib/lua-5.4/src/lbaselib.c delete mode 100644 lib/lua-5.4/src/lcode.c delete mode 100644 lib/lua-5.4/src/lcode.h delete mode 100644 lib/lua-5.4/src/lcorolib.c delete mode 100644 lib/lua-5.4/src/lctype.c delete mode 100644 lib/lua-5.4/src/lctype.h delete mode 100644 lib/lua-5.4/src/ldblib.c delete mode 100644 lib/lua-5.4/src/ldebug.c delete mode 100644 lib/lua-5.4/src/ldebug.h delete mode 100644 lib/lua-5.4/src/ldo.c delete mode 100644 lib/lua-5.4/src/ldo.h delete mode 100644 lib/lua-5.4/src/ldump.c delete mode 100644 lib/lua-5.4/src/lfunc.c delete mode 100644 lib/lua-5.4/src/lfunc.h delete mode 100644 lib/lua-5.4/src/lgc.c delete mode 100644 lib/lua-5.4/src/lgc.h delete mode 100644 lib/lua-5.4/src/linit.c delete mode 100644 lib/lua-5.4/src/liolib.c delete mode 100644 lib/lua-5.4/src/ljumptab.h delete mode 100644 lib/lua-5.4/src/llex.c delete mode 100644 lib/lua-5.4/src/llex.h delete mode 100644 lib/lua-5.4/src/llimits.h delete mode 100644 lib/lua-5.4/src/lmathlib.c delete mode 100644 lib/lua-5.4/src/lmem.c delete mode 100644 lib/lua-5.4/src/lmem.h delete mode 100644 lib/lua-5.4/src/loadlib.c delete mode 100644 lib/lua-5.4/src/lobject.c delete mode 100644 lib/lua-5.4/src/lobject.h delete mode 100644 lib/lua-5.4/src/lopcodes.c delete mode 100644 lib/lua-5.4/src/lopcodes.h delete mode 100644 lib/lua-5.4/src/lopnames.h delete mode 100644 lib/lua-5.4/src/loslib.c delete mode 100644 lib/lua-5.4/src/lparser.c delete mode 100644 lib/lua-5.4/src/lparser.h delete mode 100644 lib/lua-5.4/src/lprefix.h delete mode 100644 lib/lua-5.4/src/lstate.c delete mode 100644 lib/lua-5.4/src/lstate.h delete mode 100644 lib/lua-5.4/src/lstring.c delete mode 100644 lib/lua-5.4/src/lstring.h delete mode 100644 lib/lua-5.4/src/lstrlib.c delete mode 100644 lib/lua-5.4/src/ltable.c delete mode 100644 lib/lua-5.4/src/ltable.h delete mode 100644 lib/lua-5.4/src/ltablib.c delete mode 100644 lib/lua-5.4/src/ltm.c delete mode 100644 lib/lua-5.4/src/ltm.h delete mode 100644 lib/lua-5.4/src/lua.c delete mode 100644 lib/lua-5.4/src/lua.h delete mode 100644 lib/lua-5.4/src/lua.hpp delete mode 100644 lib/lua-5.4/src/luac.c delete mode 100644 lib/lua-5.4/src/luaconf.h delete mode 100644 lib/lua-5.4/src/lualib.h delete mode 100644 lib/lua-5.4/src/lundump.c delete mode 100644 lib/lua-5.4/src/lundump.h delete mode 100644 lib/lua-5.4/src/lutf8lib.c delete mode 100644 lib/lua-5.4/src/lvm.c delete mode 100644 lib/lua-5.4/src/lvm.h delete mode 100644 lib/lua-5.4/src/lzio.c delete mode 100644 lib/lua-5.4/src/lzio.h diff --git a/build.zig b/build.zig index b88c3ad..064abde 100644 --- a/build.zig +++ b/build.zig @@ -4,10 +4,10 @@ const Build = std.Build; const Step = std.Build.Step; pub const LuaVersion = enum { - lua_51, - lua_52, - lua_53, - lua_54, + lua51, + lua52, + lua53, + lua54, luau, }; @@ -18,40 +18,43 @@ pub fn build(b: *Build) void { const target = b.standardTargetOptions(.{}); const optimize = b.standardOptimizeOption(.{}); - const lua_version = b.option(LuaVersion, "version", "Lua API and library version") orelse .lua_54; + const lua_version = b.option(LuaVersion, "version", "Lua API and library version") orelse .lua54; const shared = b.option(bool, "shared", "Build shared library instead of static") orelse false; + const upstream = b.dependency(@tagName(lua_version), .{}); + // Zig module const ziglua = b.addModule("ziglua", .{ .root_source_file = switch (lua_version) { - .lua_51 => .{ .path = "src/ziglua-5.1/lib.zig" }, - .lua_52 => .{ .path = "src/ziglua-5.2/lib.zig" }, - .lua_53 => .{ .path = "src/ziglua-5.3/lib.zig" }, - .lua_54 => .{ .path = "src/ziglua-5.4/lib.zig" }, + .lua51 => .{ .path = "src/ziglua-5.1/lib.zig" }, + .lua52 => .{ .path = "src/ziglua-5.2/lib.zig" }, + .lua53 => .{ .path = "src/ziglua-5.3/lib.zig" }, + .lua54 => .{ .path = "src/ziglua-5.4/lib.zig" }, .luau => .{ .path = "src/zigluau/lib.zig" }, }, }); const lib = switch (lua_version) { - .lua_51, .lua_52, .lua_53, .lua_54 => buildLua(b, target, optimize, lua_version, shared), .luau => buildLuau(b, target, optimize, shared), + else => buildLua(b, target, optimize, upstream, lua_version, shared), }; - b.installArtifact(lib); + ziglua.addIncludePath(upstream.path("src")); + ziglua.linkLibrary(lib); // Tests const tests = b.addTest(.{ .root_source_file = switch (lua_version) { - .lua_51 => .{ .path = "src/ziglua-5.1/tests.zig" }, - .lua_52 => .{ .path = "src/ziglua-5.2/tests.zig" }, - .lua_53 => .{ .path = "src/ziglua-5.3/tests.zig" }, - .lua_54 => .{ .path = "src/ziglua-5.4/tests.zig" }, + .lua51 => .{ .path = "src/ziglua-5.1/tests.zig" }, + .lua52 => .{ .path = "src/ziglua-5.2/tests.zig" }, + .lua53 => .{ .path = "src/ziglua-5.3/tests.zig" }, + .lua54 => .{ .path = "src/ziglua-5.4/tests.zig" }, .luau => .{ .path = "src/zigluau/tests.zig" }, }, .target = target, .optimize = optimize, }); - tests.linkLibrary(lib); + tests.root_module.addImport("ziglua", ziglua); const run_tests = b.addRunArtifact(tests); const test_step = b.step("test", "Run ziglua tests"); @@ -71,7 +74,6 @@ pub fn build(b: *Build) void { .optimize = optimize, }); exe.root_module.addImport("ziglua", ziglua); - exe.linkLibrary(lib); const artifact = b.addInstallArtifact(exe, .{}); const exe_step = b.step(b.fmt("install-example-{s}", .{example[0]}), b.fmt("Install {s} example", .{example[0]})); @@ -86,16 +88,17 @@ pub fn build(b: *Build) void { } } -fn buildLua(b: *Build, target: Build.ResolvedTarget, optimize: std.builtin.OptimizeMode, lua_version: LuaVersion, shared: bool) *Step.Compile { +fn buildLua(b: *Build, target: Build.ResolvedTarget, optimize: std.builtin.OptimizeMode, upstream: *Build.Dependency, lua_version: LuaVersion, shared: bool) *Step.Compile { + const lib_opts = .{ .name = "lua", .target = target, .optimize = optimize, .version = switch (lua_version) { - .lua_51 => std.SemanticVersion{ .major = 5, .minor = 1, .patch = 5 }, - .lua_52 => std.SemanticVersion{ .major = 5, .minor = 2, .patch = 4 }, - .lua_53 => std.SemanticVersion{ .major = 5, .minor = 3, .patch = 6 }, - .lua_54 => std.SemanticVersion{ .major = 5, .minor = 4, .patch = 6 }, + .lua51 => std.SemanticVersion{ .major = 5, .minor = 1, .patch = 5 }, + .lua52 => std.SemanticVersion{ .major = 5, .minor = 2, .patch = 4 }, + .lua53 => std.SemanticVersion{ .major = 5, .minor = 3, .patch = 6 }, + .lua54 => std.SemanticVersion{ .major = 5, .minor = 4, .patch = 6 }, else => unreachable, }, }; @@ -104,14 +107,7 @@ fn buildLua(b: *Build, target: Build.ResolvedTarget, optimize: std.builtin.Optim else b.addStaticLibrary(lib_opts); - const lib_dir = switch (lua_version) { - .lua_51 => "lib/lua-5.1/src", - .lua_52 => "lib/lua-5.2/src", - .lua_53 => "lib/lua-5.3/src", - .lua_54 => "lib/lua-5.4/src", - else => unreachable, - }; - lib.addIncludePath(.{ .path = lib_dir }); + lib.addIncludePath(upstream.path("src")); const flags = [_][]const u8{ // Standard version used in Lua Makefile @@ -130,22 +126,17 @@ fn buildLua(b: *Build, target: Build.ResolvedTarget, optimize: std.builtin.Optim }; const lua_source_files = switch (lua_version) { - .lua_51 => &lua_51_source_files, - .lua_52 => &lua_52_source_files, - .lua_53 => &lua_53_source_files, - .lua_54 => &lua_54_source_files, + .lua51 => &lua_51_source_files, + .lua52 => &lua_52_source_files, + .lua53 => &lua_53_source_files, + .lua54 => &lua_54_source_files, else => unreachable, }; for (lua_source_files) |file| { - lib.addCSourceFile(.{ .file = .{ .path = b.pathJoin(&.{ lib_dir, file }) }, .flags = &flags }); + lib.addCSourceFile(.{ .file = upstream.path(file), .flags = &flags }); } lib.linkLibC(); - lib.installHeader(b.pathJoin(&.{ lib_dir, "lua.h" }), "lua/lua.h"); - lib.installHeader(b.pathJoin(&.{ lib_dir, "lualib.h" }), "lua/lualib.h"); - lib.installHeader(b.pathJoin(&.{ lib_dir, "lauxlib.h" }), "lua/lauxlib.h"); - lib.installHeader(b.pathJoin(&.{ lib_dir, "luaconf.h" }), "lua/luaconf.h"); - return lib; } @@ -181,150 +172,150 @@ fn buildLuau(b: *Build, target: Build.ResolvedTarget, optimize: std.builtin.Opti lib.addCSourceFile(.{ .file = .{ .path = "src/zigluau/luau.cpp" }, .flags = &flags }); lib.linkLibCpp(); - lib.installHeader("lib/luau/VM/include/lua.h", "lua/lua.h"); - lib.installHeader("lib/luau/VM/include/lualib.h", "lua/lualib.h"); - lib.installHeader("lib/luau/VM/include/luaconf.h", "lua/luaconf.h"); - lib.installHeader("lib/luau/Compiler/include/luacode.h", "lua/luacode.h"); + lib.installHeader("lib/luau/VM/include/lua.h", "lua.h"); + lib.installHeader("lib/luau/VM/include/lualib.h", "lualib.h"); + lib.installHeader("lib/luau/VM/include/luaconf.h", "luaconf.h"); + lib.installHeader("lib/luau/Compiler/include/luacode.h", "luacode.h"); return lib; } const lua_51_source_files = [_][]const u8{ - "lapi.c", - "lcode.c", - "ldebug.c", - "ldo.c", - "ldump.c", - "lfunc.c", - "lgc.c", - "llex.c", - "lmem.c", - "lobject.c", - "lopcodes.c", - "lparser.c", - "lstate.c", - "lstring.c", - "ltable.c", - "ltm.c", - "lundump.c", - "lvm.c", - "lzio.c", - "lauxlib.c", - "lbaselib.c", - "ldblib.c", - "liolib.c", - "lmathlib.c", - "loslib.c", - "ltablib.c", - "lstrlib.c", - "loadlib.c", - "linit.c", + "src/lapi.c", + "src/lcode.c", + "src/ldebug.c", + "src/ldo.c", + "src/ldump.c", + "src/lfunc.c", + "src/lgc.c", + "src/llex.c", + "src/lmem.c", + "src/lobject.c", + "src/lopcodes.c", + "src/lparser.c", + "src/lstate.c", + "src/lstring.c", + "src/ltable.c", + "src/ltm.c", + "src/lundump.c", + "src/lvm.c", + "src/lzio.c", + "src/lauxlib.c", + "src/lbaselib.c", + "src/ldblib.c", + "src/liolib.c", + "src/lmathlib.c", + "src/loslib.c", + "src/ltablib.c", + "src/lstrlib.c", + "src/loadlib.c", + "src/linit.c", }; const lua_52_source_files = [_][]const u8{ - "lapi.c", - "lcode.c", - "lctype.c", - "ldebug.c", - "ldo.c", - "ldump.c", - "lfunc.c", - "lgc.c", - "llex.c", - "lmem.c", - "lobject.c", - "lopcodes.c", - "lparser.c", - "lstate.c", - "lstring.c", - "ltable.c", - "ltm.c", - "lundump.c", - "lvm.c", - "lzio.c", - "lauxlib.c", - "lbaselib.c", - "lbitlib.c", - "lcorolib.c", - "ldblib.c", - "liolib.c", - "lmathlib.c", - "loslib.c", - "lstrlib.c", - "ltablib.c", - "loadlib.c", - "linit.c", + "src/lapi.c", + "src/lcode.c", + "src/lctype.c", + "src/ldebug.c", + "src/ldo.c", + "src/ldump.c", + "src/lfunc.c", + "src/lgc.c", + "src/llex.c", + "src/lmem.c", + "src/lobject.c", + "src/lopcodes.c", + "src/lparser.c", + "src/lstate.c", + "src/lstring.c", + "src/ltable.c", + "src/ltm.c", + "src/lundump.c", + "src/lvm.c", + "src/lzio.c", + "src/lauxlib.c", + "src/lbaselib.c", + "src/lbitlib.c", + "src/lcorolib.c", + "src/ldblib.c", + "src/liolib.c", + "src/lmathlib.c", + "src/loslib.c", + "src/lstrlib.c", + "src/ltablib.c", + "src/loadlib.c", + "src/linit.c", }; const lua_53_source_files = [_][]const u8{ - "lapi.c", - "lcode.c", - "lctype.c", - "ldebug.c", - "ldo.c", - "ldump.c", - "lfunc.c", - "lgc.c", - "llex.c", - "lmem.c", - "lobject.c", - "lopcodes.c", - "lparser.c", - "lstate.c", - "lstring.c", - "ltable.c", - "ltm.c", - "lundump.c", - "lvm.c", - "lzio.c", - "lauxlib.c", - "lbaselib.c", - "lbitlib.c", - "lcorolib.c", - "ldblib.c", - "liolib.c", - "lmathlib.c", - "loslib.c", - "lstrlib.c", - "ltablib.c", - "lutf8lib.c", - "loadlib.c", - "linit.c", + "src/lapi.c", + "src/lcode.c", + "src/lctype.c", + "src/ldebug.c", + "src/ldo.c", + "src/ldump.c", + "src/lfunc.c", + "src/lgc.c", + "src/llex.c", + "src/lmem.c", + "src/lobject.c", + "src/lopcodes.c", + "src/lparser.c", + "src/lstate.c", + "src/lstring.c", + "src/ltable.c", + "src/ltm.c", + "src/lundump.c", + "src/lvm.c", + "src/lzio.c", + "src/lauxlib.c", + "src/lbaselib.c", + "src/lbitlib.c", + "src/lcorolib.c", + "src/ldblib.c", + "src/liolib.c", + "src/lmathlib.c", + "src/loslib.c", + "src/lstrlib.c", + "src/ltablib.c", + "src/lutf8lib.c", + "src/loadlib.c", + "src/linit.c", }; const lua_54_source_files = [_][]const u8{ - "lapi.c", - "lcode.c", - "lctype.c", - "ldebug.c", - "ldo.c", - "ldump.c", - "lfunc.c", - "lgc.c", - "llex.c", - "lmem.c", - "lobject.c", - "lopcodes.c", - "lparser.c", - "lstate.c", - "lstring.c", - "ltable.c", - "ltm.c", - "lundump.c", - "lvm.c", - "lzio.c", - "lauxlib.c", - "lbaselib.c", - "lcorolib.c", - "ldblib.c", - "liolib.c", - "lmathlib.c", - "loadlib.c", - "loslib.c", - "lstrlib.c", - "ltablib.c", - "lutf8lib.c", - "linit.c", + "src/lapi.c", + "src/lcode.c", + "src/lctype.c", + "src/ldebug.c", + "src/ldo.c", + "src/ldump.c", + "src/lfunc.c", + "src/lgc.c", + "src/llex.c", + "src/lmem.c", + "src/lobject.c", + "src/lopcodes.c", + "src/lparser.c", + "src/lstate.c", + "src/lstring.c", + "src/ltable.c", + "src/ltm.c", + "src/lundump.c", + "src/lvm.c", + "src/lzio.c", + "src/lauxlib.c", + "src/lbaselib.c", + "src/lcorolib.c", + "src/ldblib.c", + "src/liolib.c", + "src/lmathlib.c", + "src/loadlib.c", + "src/loslib.c", + "src/lstrlib.c", + "src/ltablib.c", + "src/lutf8lib.c", + "src/linit.c", }; const luau_source_files = [_][]const u8{ diff --git a/build.zig.zon b/build.zig.zon index 5f34ffd..a0df66b 100644 --- a/build.zig.zon +++ b/build.zig.zon @@ -1,6 +1,27 @@ .{ .name = "ziglua", - .description = "Zig bindings for the Lua C API", .version = "0.1.0", .paths = .{ "" }, + + .dependencies = .{ + .lua51 = .{ + .url = "https://www.lua.org/ftp/lua-5.1.5.tar.gz", + .hash = "1220089572fb380fb4679b16421fc53851a8226bcebc9ce44463a0f4ada5c9bd737f", + }, + + .lua52 = .{ + .url = "https://www.lua.org/ftp/lua-5.2.4.tar.gz", + .hash = "1220d5b2b39738f0644d9ed5b7431973f1a16b937ef86d4cf85887ef3e9fda7a3379", + }, + + .lua53 = .{ + .url = "https://www.lua.org/ftp/lua-5.3.6.tar.gz", + .hash = "1220937a223531ef6b3fea8f653dc135310b0e84805e7efa148870191f5ab915c828", + }, + + .lua54 = .{ + .url = "https://www.lua.org/ftp/lua-5.4.6.tar.gz", + .hash = "1220f93ada1fa077ab096bf88a5b159ad421dbf6a478edec78ddb186d0c21d3476d9", + }, + }, } diff --git a/lib/lua-5.1/COPYRIGHT b/lib/lua-5.1/COPYRIGHT deleted file mode 100644 index a860268..0000000 --- a/lib/lua-5.1/COPYRIGHT +++ /dev/null @@ -1,34 +0,0 @@ -Lua License ------------ - -Lua is licensed under the terms of the MIT license reproduced below. -This means that Lua is free software and can be used for both academic -and commercial purposes at absolutely no cost. - -For details and rationale, see http://www.lua.org/license.html . - -=============================================================================== - -Copyright (C) 1994-2012 Lua.org, PUC-Rio. - -Permission is hereby granted, free of charge, to any person obtaining a copy -of this software and associated documentation files (the "Software"), to deal -in the Software without restriction, including without limitation the rights -to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -copies of the Software, and to permit persons to whom the Software is -furnished to do so, subject to the following conditions: - -The above copyright notice and this permission notice shall be included in -all copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN -THE SOFTWARE. - -=============================================================================== - -(end of COPYRIGHT) diff --git a/lib/lua-5.1/Makefile b/lib/lua-5.1/Makefile deleted file mode 100644 index 209a132..0000000 --- a/lib/lua-5.1/Makefile +++ /dev/null @@ -1,128 +0,0 @@ -# makefile for installing Lua -# see INSTALL for installation instructions -# see src/Makefile and src/luaconf.h for further customization - -# == CHANGE THE SETTINGS BELOW TO SUIT YOUR ENVIRONMENT ======================= - -# Your platform. See PLATS for possible values. -PLAT= none - -# Where to install. The installation starts in the src and doc directories, -# so take care if INSTALL_TOP is not an absolute path. -INSTALL_TOP= /usr/local -INSTALL_BIN= $(INSTALL_TOP)/bin -INSTALL_INC= $(INSTALL_TOP)/include -INSTALL_LIB= $(INSTALL_TOP)/lib -INSTALL_MAN= $(INSTALL_TOP)/man/man1 -# -# You probably want to make INSTALL_LMOD and INSTALL_CMOD consistent with -# LUA_ROOT, LUA_LDIR, and LUA_CDIR in luaconf.h (and also with etc/lua.pc). -INSTALL_LMOD= $(INSTALL_TOP)/share/lua/$V -INSTALL_CMOD= $(INSTALL_TOP)/lib/lua/$V - -# How to install. If your install program does not support "-p", then you -# may have to run ranlib on the installed liblua.a (do "make ranlib"). -INSTALL= install -p -INSTALL_EXEC= $(INSTALL) -m 0755 -INSTALL_DATA= $(INSTALL) -m 0644 -# -# If you don't have install you can use cp instead. -# INSTALL= cp -p -# INSTALL_EXEC= $(INSTALL) -# INSTALL_DATA= $(INSTALL) - -# Utilities. -MKDIR= mkdir -p -RANLIB= ranlib - -# == END OF USER SETTINGS. NO NEED TO CHANGE ANYTHING BELOW THIS LINE ========= - -# Convenience platforms targets. -PLATS= aix ansi bsd freebsd generic linux macosx mingw posix solaris - -# What to install. -TO_BIN= lua luac -TO_INC= lua.h luaconf.h lualib.h lauxlib.h ../etc/lua.hpp -TO_LIB= liblua.a -TO_MAN= lua.1 luac.1 - -# Lua version and release. -V= 5.1 -R= 5.1.5 - -all: $(PLAT) - -$(PLATS) clean: - cd src && $(MAKE) $@ - -test: dummy - src/lua test/hello.lua - -install: dummy - cd src && $(MKDIR) $(INSTALL_BIN) $(INSTALL_INC) $(INSTALL_LIB) $(INSTALL_MAN) $(INSTALL_LMOD) $(INSTALL_CMOD) - cd src && $(INSTALL_EXEC) $(TO_BIN) $(INSTALL_BIN) - cd src && $(INSTALL_DATA) $(TO_INC) $(INSTALL_INC) - cd src && $(INSTALL_DATA) $(TO_LIB) $(INSTALL_LIB) - cd doc && $(INSTALL_DATA) $(TO_MAN) $(INSTALL_MAN) - -ranlib: - cd src && cd $(INSTALL_LIB) && $(RANLIB) $(TO_LIB) - -local: - $(MAKE) install INSTALL_TOP=.. - -none: - @echo "Please do" - @echo " make PLATFORM" - @echo "where PLATFORM is one of these:" - @echo " $(PLATS)" - @echo "See INSTALL for complete instructions." - -# make may get confused with test/ and INSTALL in a case-insensitive OS -dummy: - -# echo config parameters -echo: - @echo "" - @echo "These are the parameters currently set in src/Makefile to build Lua $R:" - @echo "" - @cd src && $(MAKE) -s echo - @echo "" - @echo "These are the parameters currently set in Makefile to install Lua $R:" - @echo "" - @echo "PLAT = $(PLAT)" - @echo "INSTALL_TOP = $(INSTALL_TOP)" - @echo "INSTALL_BIN = $(INSTALL_BIN)" - @echo "INSTALL_INC = $(INSTALL_INC)" - @echo "INSTALL_LIB = $(INSTALL_LIB)" - @echo "INSTALL_MAN = $(INSTALL_MAN)" - @echo "INSTALL_LMOD = $(INSTALL_LMOD)" - @echo "INSTALL_CMOD = $(INSTALL_CMOD)" - @echo "INSTALL_EXEC = $(INSTALL_EXEC)" - @echo "INSTALL_DATA = $(INSTALL_DATA)" - @echo "" - @echo "See also src/luaconf.h ." - @echo "" - -# echo private config parameters -pecho: - @echo "V = $(V)" - @echo "R = $(R)" - @echo "TO_BIN = $(TO_BIN)" - @echo "TO_INC = $(TO_INC)" - @echo "TO_LIB = $(TO_LIB)" - @echo "TO_MAN = $(TO_MAN)" - -# echo config parameters as Lua code -# uncomment the last sed expression if you want nil instead of empty strings -lecho: - @echo "-- installation parameters for Lua $R" - @echo "VERSION = '$V'" - @echo "RELEASE = '$R'" - @$(MAKE) echo | grep = | sed -e 's/= /= "/' -e 's/$$/"/' #-e 's/""/nil/' - @echo "-- EOF" - -# list targets that do not create files (but not all makes understand .PHONY) -.PHONY: all $(PLATS) clean test install local none dummy echo pecho lecho - -# (end of Makefile) diff --git a/lib/lua-5.1/README b/lib/lua-5.1/README deleted file mode 100644 index 11b4dff..0000000 --- a/lib/lua-5.1/README +++ /dev/null @@ -1,37 +0,0 @@ -README for Lua 5.1 - -See INSTALL for installation instructions. -See HISTORY for a summary of changes since the last released version. - -* What is Lua? - ------------ - Lua is a powerful, light-weight programming language designed for extending - applications. Lua is also frequently used as a general-purpose, stand-alone - language. Lua is free software. - - For complete information, visit Lua's web site at http://www.lua.org/ . - For an executive summary, see http://www.lua.org/about.html . - - Lua has been used in many different projects around the world. - For a short list, see http://www.lua.org/uses.html . - -* Availability - ------------ - Lua is freely available for both academic and commercial purposes. - See COPYRIGHT and http://www.lua.org/license.html for details. - Lua can be downloaded at http://www.lua.org/download.html . - -* Installation - ------------ - Lua is implemented in pure ANSI C, and compiles unmodified in all known - platforms that have an ANSI C compiler. In most Unix-like platforms, simply - do "make" with a suitable target. See INSTALL for detailed instructions. - -* Origin - ------ - Lua is developed at Lua.org, a laboratory of the Department of Computer - Science of PUC-Rio (the Pontifical Catholic University of Rio de Janeiro - in Brazil). - For more information about the authors, see http://www.lua.org/authors.html . - -(end of README) diff --git a/lib/lua-5.1/src/Makefile b/lib/lua-5.1/src/Makefile deleted file mode 100644 index e0d4c9f..0000000 --- a/lib/lua-5.1/src/Makefile +++ /dev/null @@ -1,182 +0,0 @@ -# makefile for building Lua -# see ../INSTALL for installation instructions -# see ../Makefile and luaconf.h for further customization - -# == CHANGE THE SETTINGS BELOW TO SUIT YOUR ENVIRONMENT ======================= - -# Your platform. See PLATS for possible values. -PLAT= none - -CC= gcc -CFLAGS= -O2 -Wall $(MYCFLAGS) -AR= ar rcu -RANLIB= ranlib -RM= rm -f -LIBS= -lm $(MYLIBS) - -MYCFLAGS= -MYLDFLAGS= -MYLIBS= - -# == END OF USER SETTINGS. NO NEED TO CHANGE ANYTHING BELOW THIS LINE ========= - -PLATS= aix ansi bsd freebsd generic linux macosx mingw posix solaris - -LUA_A= liblua.a -CORE_O= lapi.o lcode.o ldebug.o ldo.o ldump.o lfunc.o lgc.o llex.o lmem.o \ - lobject.o lopcodes.o lparser.o lstate.o lstring.o ltable.o ltm.o \ - lundump.o lvm.o lzio.o -LIB_O= lauxlib.o lbaselib.o ldblib.o liolib.o lmathlib.o loslib.o ltablib.o \ - lstrlib.o loadlib.o linit.o - -LUA_T= lua -LUA_O= lua.o - -LUAC_T= luac -LUAC_O= luac.o print.o - -ALL_O= $(CORE_O) $(LIB_O) $(LUA_O) $(LUAC_O) -ALL_T= $(LUA_A) $(LUA_T) $(LUAC_T) -ALL_A= $(LUA_A) - -default: $(PLAT) - -all: $(ALL_T) - -o: $(ALL_O) - -a: $(ALL_A) - -$(LUA_A): $(CORE_O) $(LIB_O) - $(AR) $@ $(CORE_O) $(LIB_O) # DLL needs all object files - $(RANLIB) $@ - -$(LUA_T): $(LUA_O) $(LUA_A) - $(CC) -o $@ $(MYLDFLAGS) $(LUA_O) $(LUA_A) $(LIBS) - -$(LUAC_T): $(LUAC_O) $(LUA_A) - $(CC) -o $@ $(MYLDFLAGS) $(LUAC_O) $(LUA_A) $(LIBS) - -clean: - $(RM) $(ALL_T) $(ALL_O) - -depend: - @$(CC) $(CFLAGS) -MM l*.c print.c - -echo: - @echo "PLAT = $(PLAT)" - @echo "CC = $(CC)" - @echo "CFLAGS = $(CFLAGS)" - @echo "AR = $(AR)" - @echo "RANLIB = $(RANLIB)" - @echo "RM = $(RM)" - @echo "MYCFLAGS = $(MYCFLAGS)" - @echo "MYLDFLAGS = $(MYLDFLAGS)" - @echo "MYLIBS = $(MYLIBS)" - -# convenience targets for popular platforms - -none: - @echo "Please choose a platform:" - @echo " $(PLATS)" - -aix: - $(MAKE) all CC="xlc" CFLAGS="-O2 -DLUA_USE_POSIX -DLUA_USE_DLOPEN" MYLIBS="-ldl" MYLDFLAGS="-brtl -bexpall" - -ansi: - $(MAKE) all MYCFLAGS=-DLUA_ANSI - -bsd: - $(MAKE) all MYCFLAGS="-DLUA_USE_POSIX -DLUA_USE_DLOPEN" MYLIBS="-Wl,-E" - -freebsd: - $(MAKE) all MYCFLAGS="-DLUA_USE_LINUX" MYLIBS="-Wl,-E -lreadline" - -generic: - $(MAKE) all MYCFLAGS= - -linux: - $(MAKE) all MYCFLAGS=-DLUA_USE_LINUX MYLIBS="-Wl,-E -ldl -lreadline -lhistory -lncurses" - -macosx: - $(MAKE) all MYCFLAGS=-DLUA_USE_LINUX MYLIBS="-lreadline" -# use this on Mac OS X 10.3- -# $(MAKE) all MYCFLAGS=-DLUA_USE_MACOSX - -mingw: - $(MAKE) "LUA_A=lua51.dll" "LUA_T=lua.exe" \ - "AR=$(CC) -shared -o" "RANLIB=strip --strip-unneeded" \ - "MYCFLAGS=-DLUA_BUILD_AS_DLL" "MYLIBS=" "MYLDFLAGS=-s" lua.exe - $(MAKE) "LUAC_T=luac.exe" luac.exe - -posix: - $(MAKE) all MYCFLAGS=-DLUA_USE_POSIX - -solaris: - $(MAKE) all MYCFLAGS="-DLUA_USE_POSIX -DLUA_USE_DLOPEN" MYLIBS="-ldl" - -# list targets that do not create files (but not all makes understand .PHONY) -.PHONY: all $(PLATS) default o a clean depend echo none - -# DO NOT DELETE - -lapi.o: lapi.c lua.h luaconf.h lapi.h lobject.h llimits.h ldebug.h \ - lstate.h ltm.h lzio.h lmem.h ldo.h lfunc.h lgc.h lstring.h ltable.h \ - lundump.h lvm.h -lauxlib.o: lauxlib.c lua.h luaconf.h lauxlib.h -lbaselib.o: lbaselib.c lua.h luaconf.h lauxlib.h lualib.h -lcode.o: lcode.c lua.h luaconf.h lcode.h llex.h lobject.h llimits.h \ - lzio.h lmem.h lopcodes.h lparser.h ldebug.h lstate.h ltm.h ldo.h lgc.h \ - ltable.h -ldblib.o: ldblib.c lua.h luaconf.h lauxlib.h lualib.h -ldebug.o: ldebug.c lua.h luaconf.h lapi.h lobject.h llimits.h lcode.h \ - llex.h lzio.h lmem.h lopcodes.h lparser.h ldebug.h lstate.h ltm.h ldo.h \ - lfunc.h lstring.h lgc.h ltable.h lvm.h -ldo.o: ldo.c lua.h luaconf.h ldebug.h lstate.h lobject.h llimits.h ltm.h \ - lzio.h lmem.h ldo.h lfunc.h lgc.h lopcodes.h lparser.h lstring.h \ - ltable.h lundump.h lvm.h -ldump.o: ldump.c lua.h luaconf.h lobject.h llimits.h lstate.h ltm.h \ - lzio.h lmem.h lundump.h -lfunc.o: lfunc.c lua.h luaconf.h lfunc.h lobject.h llimits.h lgc.h lmem.h \ - lstate.h ltm.h lzio.h -lgc.o: lgc.c lua.h luaconf.h ldebug.h lstate.h lobject.h llimits.h ltm.h \ - lzio.h lmem.h ldo.h lfunc.h lgc.h lstring.h ltable.h -linit.o: linit.c lua.h luaconf.h lualib.h lauxlib.h -liolib.o: liolib.c lua.h luaconf.h lauxlib.h lualib.h -llex.o: llex.c lua.h luaconf.h ldo.h lobject.h llimits.h lstate.h ltm.h \ - lzio.h lmem.h llex.h lparser.h lstring.h lgc.h ltable.h -lmathlib.o: lmathlib.c lua.h luaconf.h lauxlib.h lualib.h -lmem.o: lmem.c lua.h luaconf.h ldebug.h lstate.h lobject.h llimits.h \ - ltm.h lzio.h lmem.h ldo.h -loadlib.o: loadlib.c lua.h luaconf.h lauxlib.h lualib.h -lobject.o: lobject.c lua.h luaconf.h ldo.h lobject.h llimits.h lstate.h \ - ltm.h lzio.h lmem.h lstring.h lgc.h lvm.h -lopcodes.o: lopcodes.c lopcodes.h llimits.h lua.h luaconf.h -loslib.o: loslib.c lua.h luaconf.h lauxlib.h lualib.h -lparser.o: lparser.c lua.h luaconf.h lcode.h llex.h lobject.h llimits.h \ - lzio.h lmem.h lopcodes.h lparser.h ldebug.h lstate.h ltm.h ldo.h \ - lfunc.h lstring.h lgc.h ltable.h -lstate.o: lstate.c lua.h luaconf.h ldebug.h lstate.h lobject.h llimits.h \ - ltm.h lzio.h lmem.h ldo.h lfunc.h lgc.h llex.h lstring.h ltable.h -lstring.o: lstring.c lua.h luaconf.h lmem.h llimits.h lobject.h lstate.h \ - ltm.h lzio.h lstring.h lgc.h -lstrlib.o: lstrlib.c lua.h luaconf.h lauxlib.h lualib.h -ltable.o: ltable.c lua.h luaconf.h ldebug.h lstate.h lobject.h llimits.h \ - ltm.h lzio.h lmem.h ldo.h lgc.h ltable.h -ltablib.o: ltablib.c lua.h luaconf.h lauxlib.h lualib.h -ltm.o: ltm.c lua.h luaconf.h lobject.h llimits.h lstate.h ltm.h lzio.h \ - lmem.h lstring.h lgc.h ltable.h -lua.o: lua.c lua.h luaconf.h lauxlib.h lualib.h -luac.o: luac.c lua.h luaconf.h lauxlib.h ldo.h lobject.h llimits.h \ - lstate.h ltm.h lzio.h lmem.h lfunc.h lopcodes.h lstring.h lgc.h \ - lundump.h -lundump.o: lundump.c lua.h luaconf.h ldebug.h lstate.h lobject.h \ - llimits.h ltm.h lzio.h lmem.h ldo.h lfunc.h lstring.h lgc.h lundump.h -lvm.o: lvm.c lua.h luaconf.h ldebug.h lstate.h lobject.h llimits.h ltm.h \ - lzio.h lmem.h ldo.h lfunc.h lgc.h lopcodes.h lstring.h ltable.h lvm.h -lzio.o: lzio.c lua.h luaconf.h llimits.h lmem.h lstate.h lobject.h ltm.h \ - lzio.h -print.o: print.c ldebug.h lstate.h lua.h luaconf.h lobject.h llimits.h \ - ltm.h lzio.h lmem.h lopcodes.h lundump.h - -# (end of Makefile) diff --git a/lib/lua-5.1/src/lapi.c b/lib/lua-5.1/src/lapi.c deleted file mode 100644 index 5d5145d..0000000 --- a/lib/lua-5.1/src/lapi.c +++ /dev/null @@ -1,1087 +0,0 @@ -/* -** $Id: lapi.c,v 2.55.1.5 2008/07/04 18:41:18 roberto Exp $ -** Lua API -** See Copyright Notice in lua.h -*/ - - -#include -#include -#include -#include - -#define lapi_c -#define LUA_CORE - -#include "lua.h" - -#include "lapi.h" -#include "ldebug.h" -#include "ldo.h" -#include "lfunc.h" -#include "lgc.h" -#include "lmem.h" -#include "lobject.h" -#include "lstate.h" -#include "lstring.h" -#include "ltable.h" -#include "ltm.h" -#include "lundump.h" -#include "lvm.h" - - - -const char lua_ident[] = - "$Lua: " LUA_RELEASE " " LUA_COPYRIGHT " $\n" - "$Authors: " LUA_AUTHORS " $\n" - "$URL: www.lua.org $\n"; - - - -#define api_checknelems(L, n) api_check(L, (n) <= (L->top - L->base)) - -#define api_checkvalidindex(L, i) api_check(L, (i) != luaO_nilobject) - -#define api_incr_top(L) {api_check(L, L->top < L->ci->top); L->top++;} - - - -static TValue *index2adr (lua_State *L, int idx) { - if (idx > 0) { - TValue *o = L->base + (idx - 1); - api_check(L, idx <= L->ci->top - L->base); - if (o >= L->top) return cast(TValue *, luaO_nilobject); - else return o; - } - else if (idx > LUA_REGISTRYINDEX) { - api_check(L, idx != 0 && -idx <= L->top - L->base); - return L->top + idx; - } - else switch (idx) { /* pseudo-indices */ - case LUA_REGISTRYINDEX: return registry(L); - case LUA_ENVIRONINDEX: { - Closure *func = curr_func(L); - sethvalue(L, &L->env, func->c.env); - return &L->env; - } - case LUA_GLOBALSINDEX: return gt(L); - default: { - Closure *func = curr_func(L); - idx = LUA_GLOBALSINDEX - idx; - return (idx <= func->c.nupvalues) - ? &func->c.upvalue[idx-1] - : cast(TValue *, luaO_nilobject); - } - } -} - - -static Table *getcurrenv (lua_State *L) { - if (L->ci == L->base_ci) /* no enclosing function? */ - return hvalue(gt(L)); /* use global table as environment */ - else { - Closure *func = curr_func(L); - return func->c.env; - } -} - - -void luaA_pushobject (lua_State *L, const TValue *o) { - setobj2s(L, L->top, o); - api_incr_top(L); -} - - -LUA_API int lua_checkstack (lua_State *L, int size) { - int res = 1; - lua_lock(L); - if (size > LUAI_MAXCSTACK || (L->top - L->base + size) > LUAI_MAXCSTACK) - res = 0; /* stack overflow */ - else if (size > 0) { - luaD_checkstack(L, size); - if (L->ci->top < L->top + size) - L->ci->top = L->top + size; - } - lua_unlock(L); - return res; -} - - -LUA_API void lua_xmove (lua_State *from, lua_State *to, int n) { - int i; - if (from == to) return; - lua_lock(to); - api_checknelems(from, n); - api_check(from, G(from) == G(to)); - api_check(from, to->ci->top - to->top >= n); - from->top -= n; - for (i = 0; i < n; i++) { - setobj2s(to, to->top++, from->top + i); - } - lua_unlock(to); -} - - -LUA_API void lua_setlevel (lua_State *from, lua_State *to) { - to->nCcalls = from->nCcalls; -} - - -LUA_API lua_CFunction lua_atpanic (lua_State *L, lua_CFunction panicf) { - lua_CFunction old; - lua_lock(L); - old = G(L)->panic; - G(L)->panic = panicf; - lua_unlock(L); - return old; -} - - -LUA_API lua_State *lua_newthread (lua_State *L) { - lua_State *L1; - lua_lock(L); - luaC_checkGC(L); - L1 = luaE_newthread(L); - setthvalue(L, L->top, L1); - api_incr_top(L); - lua_unlock(L); - luai_userstatethread(L, L1); - return L1; -} - - - -/* -** basic stack manipulation -*/ - - -LUA_API int lua_gettop (lua_State *L) { - return cast_int(L->top - L->base); -} - - -LUA_API void lua_settop (lua_State *L, int idx) { - lua_lock(L); - if (idx >= 0) { - api_check(L, idx <= L->stack_last - L->base); - while (L->top < L->base + idx) - setnilvalue(L->top++); - L->top = L->base + idx; - } - else { - api_check(L, -(idx+1) <= (L->top - L->base)); - L->top += idx+1; /* `subtract' index (index is negative) */ - } - lua_unlock(L); -} - - -LUA_API void lua_remove (lua_State *L, int idx) { - StkId p; - lua_lock(L); - p = index2adr(L, idx); - api_checkvalidindex(L, p); - while (++p < L->top) setobjs2s(L, p-1, p); - L->top--; - lua_unlock(L); -} - - -LUA_API void lua_insert (lua_State *L, int idx) { - StkId p; - StkId q; - lua_lock(L); - p = index2adr(L, idx); - api_checkvalidindex(L, p); - for (q = L->top; q>p; q--) setobjs2s(L, q, q-1); - setobjs2s(L, p, L->top); - lua_unlock(L); -} - - -LUA_API void lua_replace (lua_State *L, int idx) { - StkId o; - lua_lock(L); - /* explicit test for incompatible code */ - if (idx == LUA_ENVIRONINDEX && L->ci == L->base_ci) - luaG_runerror(L, "no calling environment"); - api_checknelems(L, 1); - o = index2adr(L, idx); - api_checkvalidindex(L, o); - if (idx == LUA_ENVIRONINDEX) { - Closure *func = curr_func(L); - api_check(L, ttistable(L->top - 1)); - func->c.env = hvalue(L->top - 1); - luaC_barrier(L, func, L->top - 1); - } - else { - setobj(L, o, L->top - 1); - if (idx < LUA_GLOBALSINDEX) /* function upvalue? */ - luaC_barrier(L, curr_func(L), L->top - 1); - } - L->top--; - lua_unlock(L); -} - - -LUA_API void lua_pushvalue (lua_State *L, int idx) { - lua_lock(L); - setobj2s(L, L->top, index2adr(L, idx)); - api_incr_top(L); - lua_unlock(L); -} - - - -/* -** access functions (stack -> C) -*/ - - -LUA_API int lua_type (lua_State *L, int idx) { - StkId o = index2adr(L, idx); - return (o == luaO_nilobject) ? LUA_TNONE : ttype(o); -} - - -LUA_API const char *lua_typename (lua_State *L, int t) { - UNUSED(L); - return (t == LUA_TNONE) ? "no value" : luaT_typenames[t]; -} - - -LUA_API int lua_iscfunction (lua_State *L, int idx) { - StkId o = index2adr(L, idx); - return iscfunction(o); -} - - -LUA_API int lua_isnumber (lua_State *L, int idx) { - TValue n; - const TValue *o = index2adr(L, idx); - return tonumber(o, &n); -} - - -LUA_API int lua_isstring (lua_State *L, int idx) { - int t = lua_type(L, idx); - return (t == LUA_TSTRING || t == LUA_TNUMBER); -} - - -LUA_API int lua_isuserdata (lua_State *L, int idx) { - const TValue *o = index2adr(L, idx); - return (ttisuserdata(o) || ttislightuserdata(o)); -} - - -LUA_API int lua_rawequal (lua_State *L, int index1, int index2) { - StkId o1 = index2adr(L, index1); - StkId o2 = index2adr(L, index2); - return (o1 == luaO_nilobject || o2 == luaO_nilobject) ? 0 - : luaO_rawequalObj(o1, o2); -} - - -LUA_API int lua_equal (lua_State *L, int index1, int index2) { - StkId o1, o2; - int i; - lua_lock(L); /* may call tag method */ - o1 = index2adr(L, index1); - o2 = index2adr(L, index2); - i = (o1 == luaO_nilobject || o2 == luaO_nilobject) ? 0 : equalobj(L, o1, o2); - lua_unlock(L); - return i; -} - - -LUA_API int lua_lessthan (lua_State *L, int index1, int index2) { - StkId o1, o2; - int i; - lua_lock(L); /* may call tag method */ - o1 = index2adr(L, index1); - o2 = index2adr(L, index2); - i = (o1 == luaO_nilobject || o2 == luaO_nilobject) ? 0 - : luaV_lessthan(L, o1, o2); - lua_unlock(L); - return i; -} - - - -LUA_API lua_Number lua_tonumber (lua_State *L, int idx) { - TValue n; - const TValue *o = index2adr(L, idx); - if (tonumber(o, &n)) - return nvalue(o); - else - return 0; -} - - -LUA_API lua_Integer lua_tointeger (lua_State *L, int idx) { - TValue n; - const TValue *o = index2adr(L, idx); - if (tonumber(o, &n)) { - lua_Integer res; - lua_Number num = nvalue(o); - lua_number2integer(res, num); - return res; - } - else - return 0; -} - - -LUA_API int lua_toboolean (lua_State *L, int idx) { - const TValue *o = index2adr(L, idx); - return !l_isfalse(o); -} - - -LUA_API const char *lua_tolstring (lua_State *L, int idx, size_t *len) { - StkId o = index2adr(L, idx); - if (!ttisstring(o)) { - lua_lock(L); /* `luaV_tostring' may create a new string */ - if (!luaV_tostring(L, o)) { /* conversion failed? */ - if (len != NULL) *len = 0; - lua_unlock(L); - return NULL; - } - luaC_checkGC(L); - o = index2adr(L, idx); /* previous call may reallocate the stack */ - lua_unlock(L); - } - if (len != NULL) *len = tsvalue(o)->len; - return svalue(o); -} - - -LUA_API size_t lua_objlen (lua_State *L, int idx) { - StkId o = index2adr(L, idx); - switch (ttype(o)) { - case LUA_TSTRING: return tsvalue(o)->len; - case LUA_TUSERDATA: return uvalue(o)->len; - case LUA_TTABLE: return luaH_getn(hvalue(o)); - case LUA_TNUMBER: { - size_t l; - lua_lock(L); /* `luaV_tostring' may create a new string */ - l = (luaV_tostring(L, o) ? tsvalue(o)->len : 0); - lua_unlock(L); - return l; - } - default: return 0; - } -} - - -LUA_API lua_CFunction lua_tocfunction (lua_State *L, int idx) { - StkId o = index2adr(L, idx); - return (!iscfunction(o)) ? NULL : clvalue(o)->c.f; -} - - -LUA_API void *lua_touserdata (lua_State *L, int idx) { - StkId o = index2adr(L, idx); - switch (ttype(o)) { - case LUA_TUSERDATA: return (rawuvalue(o) + 1); - case LUA_TLIGHTUSERDATA: return pvalue(o); - default: return NULL; - } -} - - -LUA_API lua_State *lua_tothread (lua_State *L, int idx) { - StkId o = index2adr(L, idx); - return (!ttisthread(o)) ? NULL : thvalue(o); -} - - -LUA_API const void *lua_topointer (lua_State *L, int idx) { - StkId o = index2adr(L, idx); - switch (ttype(o)) { - case LUA_TTABLE: return hvalue(o); - case LUA_TFUNCTION: return clvalue(o); - case LUA_TTHREAD: return thvalue(o); - case LUA_TUSERDATA: - case LUA_TLIGHTUSERDATA: - return lua_touserdata(L, idx); - default: return NULL; - } -} - - - -/* -** push functions (C -> stack) -*/ - - -LUA_API void lua_pushnil (lua_State *L) { - lua_lock(L); - setnilvalue(L->top); - api_incr_top(L); - lua_unlock(L); -} - - -LUA_API void lua_pushnumber (lua_State *L, lua_Number n) { - lua_lock(L); - setnvalue(L->top, n); - api_incr_top(L); - lua_unlock(L); -} - - -LUA_API void lua_pushinteger (lua_State *L, lua_Integer n) { - lua_lock(L); - setnvalue(L->top, cast_num(n)); - api_incr_top(L); - lua_unlock(L); -} - - -LUA_API void lua_pushlstring (lua_State *L, const char *s, size_t len) { - lua_lock(L); - luaC_checkGC(L); - setsvalue2s(L, L->top, luaS_newlstr(L, s, len)); - api_incr_top(L); - lua_unlock(L); -} - - -LUA_API void lua_pushstring (lua_State *L, const char *s) { - if (s == NULL) - lua_pushnil(L); - else - lua_pushlstring(L, s, strlen(s)); -} - - -LUA_API const char *lua_pushvfstring (lua_State *L, const char *fmt, - va_list argp) { - const char *ret; - lua_lock(L); - luaC_checkGC(L); - ret = luaO_pushvfstring(L, fmt, argp); - lua_unlock(L); - return ret; -} - - -LUA_API const char *lua_pushfstring (lua_State *L, const char *fmt, ...) { - const char *ret; - va_list argp; - lua_lock(L); - luaC_checkGC(L); - va_start(argp, fmt); - ret = luaO_pushvfstring(L, fmt, argp); - va_end(argp); - lua_unlock(L); - return ret; -} - - -LUA_API void lua_pushcclosure (lua_State *L, lua_CFunction fn, int n) { - Closure *cl; - lua_lock(L); - luaC_checkGC(L); - api_checknelems(L, n); - cl = luaF_newCclosure(L, n, getcurrenv(L)); - cl->c.f = fn; - L->top -= n; - while (n--) - setobj2n(L, &cl->c.upvalue[n], L->top+n); - setclvalue(L, L->top, cl); - lua_assert(iswhite(obj2gco(cl))); - api_incr_top(L); - lua_unlock(L); -} - - -LUA_API void lua_pushboolean (lua_State *L, int b) { - lua_lock(L); - setbvalue(L->top, (b != 0)); /* ensure that true is 1 */ - api_incr_top(L); - lua_unlock(L); -} - - -LUA_API void lua_pushlightuserdata (lua_State *L, void *p) { - lua_lock(L); - setpvalue(L->top, p); - api_incr_top(L); - lua_unlock(L); -} - - -LUA_API int lua_pushthread (lua_State *L) { - lua_lock(L); - setthvalue(L, L->top, L); - api_incr_top(L); - lua_unlock(L); - return (G(L)->mainthread == L); -} - - - -/* -** get functions (Lua -> stack) -*/ - - -LUA_API void lua_gettable (lua_State *L, int idx) { - StkId t; - lua_lock(L); - t = index2adr(L, idx); - api_checkvalidindex(L, t); - luaV_gettable(L, t, L->top - 1, L->top - 1); - lua_unlock(L); -} - - -LUA_API void lua_getfield (lua_State *L, int idx, const char *k) { - StkId t; - TValue key; - lua_lock(L); - t = index2adr(L, idx); - api_checkvalidindex(L, t); - setsvalue(L, &key, luaS_new(L, k)); - luaV_gettable(L, t, &key, L->top); - api_incr_top(L); - lua_unlock(L); -} - - -LUA_API void lua_rawget (lua_State *L, int idx) { - StkId t; - lua_lock(L); - t = index2adr(L, idx); - api_check(L, ttistable(t)); - setobj2s(L, L->top - 1, luaH_get(hvalue(t), L->top - 1)); - lua_unlock(L); -} - - -LUA_API void lua_rawgeti (lua_State *L, int idx, int n) { - StkId o; - lua_lock(L); - o = index2adr(L, idx); - api_check(L, ttistable(o)); - setobj2s(L, L->top, luaH_getnum(hvalue(o), n)); - api_incr_top(L); - lua_unlock(L); -} - - -LUA_API void lua_createtable (lua_State *L, int narray, int nrec) { - lua_lock(L); - luaC_checkGC(L); - sethvalue(L, L->top, luaH_new(L, narray, nrec)); - api_incr_top(L); - lua_unlock(L); -} - - -LUA_API int lua_getmetatable (lua_State *L, int objindex) { - const TValue *obj; - Table *mt = NULL; - int res; - lua_lock(L); - obj = index2adr(L, objindex); - switch (ttype(obj)) { - case LUA_TTABLE: - mt = hvalue(obj)->metatable; - break; - case LUA_TUSERDATA: - mt = uvalue(obj)->metatable; - break; - default: - mt = G(L)->mt[ttype(obj)]; - break; - } - if (mt == NULL) - res = 0; - else { - sethvalue(L, L->top, mt); - api_incr_top(L); - res = 1; - } - lua_unlock(L); - return res; -} - - -LUA_API void lua_getfenv (lua_State *L, int idx) { - StkId o; - lua_lock(L); - o = index2adr(L, idx); - api_checkvalidindex(L, o); - switch (ttype(o)) { - case LUA_TFUNCTION: - sethvalue(L, L->top, clvalue(o)->c.env); - break; - case LUA_TUSERDATA: - sethvalue(L, L->top, uvalue(o)->env); - break; - case LUA_TTHREAD: - setobj2s(L, L->top, gt(thvalue(o))); - break; - default: - setnilvalue(L->top); - break; - } - api_incr_top(L); - lua_unlock(L); -} - - -/* -** set functions (stack -> Lua) -*/ - - -LUA_API void lua_settable (lua_State *L, int idx) { - StkId t; - lua_lock(L); - api_checknelems(L, 2); - t = index2adr(L, idx); - api_checkvalidindex(L, t); - luaV_settable(L, t, L->top - 2, L->top - 1); - L->top -= 2; /* pop index and value */ - lua_unlock(L); -} - - -LUA_API void lua_setfield (lua_State *L, int idx, const char *k) { - StkId t; - TValue key; - lua_lock(L); - api_checknelems(L, 1); - t = index2adr(L, idx); - api_checkvalidindex(L, t); - setsvalue(L, &key, luaS_new(L, k)); - luaV_settable(L, t, &key, L->top - 1); - L->top--; /* pop value */ - lua_unlock(L); -} - - -LUA_API void lua_rawset (lua_State *L, int idx) { - StkId t; - lua_lock(L); - api_checknelems(L, 2); - t = index2adr(L, idx); - api_check(L, ttistable(t)); - setobj2t(L, luaH_set(L, hvalue(t), L->top-2), L->top-1); - luaC_barriert(L, hvalue(t), L->top-1); - L->top -= 2; - lua_unlock(L); -} - - -LUA_API void lua_rawseti (lua_State *L, int idx, int n) { - StkId o; - lua_lock(L); - api_checknelems(L, 1); - o = index2adr(L, idx); - api_check(L, ttistable(o)); - setobj2t(L, luaH_setnum(L, hvalue(o), n), L->top-1); - luaC_barriert(L, hvalue(o), L->top-1); - L->top--; - lua_unlock(L); -} - - -LUA_API int lua_setmetatable (lua_State *L, int objindex) { - TValue *obj; - Table *mt; - lua_lock(L); - api_checknelems(L, 1); - obj = index2adr(L, objindex); - api_checkvalidindex(L, obj); - if (ttisnil(L->top - 1)) - mt = NULL; - else { - api_check(L, ttistable(L->top - 1)); - mt = hvalue(L->top - 1); - } - switch (ttype(obj)) { - case LUA_TTABLE: { - hvalue(obj)->metatable = mt; - if (mt) - luaC_objbarriert(L, hvalue(obj), mt); - break; - } - case LUA_TUSERDATA: { - uvalue(obj)->metatable = mt; - if (mt) - luaC_objbarrier(L, rawuvalue(obj), mt); - break; - } - default: { - G(L)->mt[ttype(obj)] = mt; - break; - } - } - L->top--; - lua_unlock(L); - return 1; -} - - -LUA_API int lua_setfenv (lua_State *L, int idx) { - StkId o; - int res = 1; - lua_lock(L); - api_checknelems(L, 1); - o = index2adr(L, idx); - api_checkvalidindex(L, o); - api_check(L, ttistable(L->top - 1)); - switch (ttype(o)) { - case LUA_TFUNCTION: - clvalue(o)->c.env = hvalue(L->top - 1); - break; - case LUA_TUSERDATA: - uvalue(o)->env = hvalue(L->top - 1); - break; - case LUA_TTHREAD: - sethvalue(L, gt(thvalue(o)), hvalue(L->top - 1)); - break; - default: - res = 0; - break; - } - if (res) luaC_objbarrier(L, gcvalue(o), hvalue(L->top - 1)); - L->top--; - lua_unlock(L); - return res; -} - - -/* -** `load' and `call' functions (run Lua code) -*/ - - -#define adjustresults(L,nres) \ - { if (nres == LUA_MULTRET && L->top >= L->ci->top) L->ci->top = L->top; } - - -#define checkresults(L,na,nr) \ - api_check(L, (nr) == LUA_MULTRET || (L->ci->top - L->top >= (nr) - (na))) - - -LUA_API void lua_call (lua_State *L, int nargs, int nresults) { - StkId func; - lua_lock(L); - api_checknelems(L, nargs+1); - checkresults(L, nargs, nresults); - func = L->top - (nargs+1); - luaD_call(L, func, nresults); - adjustresults(L, nresults); - lua_unlock(L); -} - - - -/* -** Execute a protected call. -*/ -struct CallS { /* data to `f_call' */ - StkId func; - int nresults; -}; - - -static void f_call (lua_State *L, void *ud) { - struct CallS *c = cast(struct CallS *, ud); - luaD_call(L, c->func, c->nresults); -} - - - -LUA_API int lua_pcall (lua_State *L, int nargs, int nresults, int errfunc) { - struct CallS c; - int status; - ptrdiff_t func; - lua_lock(L); - api_checknelems(L, nargs+1); - checkresults(L, nargs, nresults); - if (errfunc == 0) - func = 0; - else { - StkId o = index2adr(L, errfunc); - api_checkvalidindex(L, o); - func = savestack(L, o); - } - c.func = L->top - (nargs+1); /* function to be called */ - c.nresults = nresults; - status = luaD_pcall(L, f_call, &c, savestack(L, c.func), func); - adjustresults(L, nresults); - lua_unlock(L); - return status; -} - - -/* -** Execute a protected C call. -*/ -struct CCallS { /* data to `f_Ccall' */ - lua_CFunction func; - void *ud; -}; - - -static void f_Ccall (lua_State *L, void *ud) { - struct CCallS *c = cast(struct CCallS *, ud); - Closure *cl; - cl = luaF_newCclosure(L, 0, getcurrenv(L)); - cl->c.f = c->func; - setclvalue(L, L->top, cl); /* push function */ - api_incr_top(L); - setpvalue(L->top, c->ud); /* push only argument */ - api_incr_top(L); - luaD_call(L, L->top - 2, 0); -} - - -LUA_API int lua_cpcall (lua_State *L, lua_CFunction func, void *ud) { - struct CCallS c; - int status; - lua_lock(L); - c.func = func; - c.ud = ud; - status = luaD_pcall(L, f_Ccall, &c, savestack(L, L->top), 0); - lua_unlock(L); - return status; -} - - -LUA_API int lua_load (lua_State *L, lua_Reader reader, void *data, - const char *chunkname) { - ZIO z; - int status; - lua_lock(L); - if (!chunkname) chunkname = "?"; - luaZ_init(L, &z, reader, data); - status = luaD_protectedparser(L, &z, chunkname); - lua_unlock(L); - return status; -} - - -LUA_API int lua_dump (lua_State *L, lua_Writer writer, void *data) { - int status; - TValue *o; - lua_lock(L); - api_checknelems(L, 1); - o = L->top - 1; - if (isLfunction(o)) - status = luaU_dump(L, clvalue(o)->l.p, writer, data, 0); - else - status = 1; - lua_unlock(L); - return status; -} - - -LUA_API int lua_status (lua_State *L) { - return L->status; -} - - -/* -** Garbage-collection function -*/ - -LUA_API int lua_gc (lua_State *L, int what, int data) { - int res = 0; - global_State *g; - lua_lock(L); - g = G(L); - switch (what) { - case LUA_GCSTOP: { - g->GCthreshold = MAX_LUMEM; - break; - } - case LUA_GCRESTART: { - g->GCthreshold = g->totalbytes; - break; - } - case LUA_GCCOLLECT: { - luaC_fullgc(L); - break; - } - case LUA_GCCOUNT: { - /* GC values are expressed in Kbytes: #bytes/2^10 */ - res = cast_int(g->totalbytes >> 10); - break; - } - case LUA_GCCOUNTB: { - res = cast_int(g->totalbytes & 0x3ff); - break; - } - case LUA_GCSTEP: { - lu_mem a = (cast(lu_mem, data) << 10); - if (a <= g->totalbytes) - g->GCthreshold = g->totalbytes - a; - else - g->GCthreshold = 0; - while (g->GCthreshold <= g->totalbytes) { - luaC_step(L); - if (g->gcstate == GCSpause) { /* end of cycle? */ - res = 1; /* signal it */ - break; - } - } - break; - } - case LUA_GCSETPAUSE: { - res = g->gcpause; - g->gcpause = data; - break; - } - case LUA_GCSETSTEPMUL: { - res = g->gcstepmul; - g->gcstepmul = data; - break; - } - default: res = -1; /* invalid option */ - } - lua_unlock(L); - return res; -} - - - -/* -** miscellaneous functions -*/ - - -LUA_API int lua_error (lua_State *L) { - lua_lock(L); - api_checknelems(L, 1); - luaG_errormsg(L); - lua_unlock(L); - return 0; /* to avoid warnings */ -} - - -LUA_API int lua_next (lua_State *L, int idx) { - StkId t; - int more; - lua_lock(L); - t = index2adr(L, idx); - api_check(L, ttistable(t)); - more = luaH_next(L, hvalue(t), L->top - 1); - if (more) { - api_incr_top(L); - } - else /* no more elements */ - L->top -= 1; /* remove key */ - lua_unlock(L); - return more; -} - - -LUA_API void lua_concat (lua_State *L, int n) { - lua_lock(L); - api_checknelems(L, n); - if (n >= 2) { - luaC_checkGC(L); - luaV_concat(L, n, cast_int(L->top - L->base) - 1); - L->top -= (n-1); - } - else if (n == 0) { /* push empty string */ - setsvalue2s(L, L->top, luaS_newlstr(L, "", 0)); - api_incr_top(L); - } - /* else n == 1; nothing to do */ - lua_unlock(L); -} - - -LUA_API lua_Alloc lua_getallocf (lua_State *L, void **ud) { - lua_Alloc f; - lua_lock(L); - if (ud) *ud = G(L)->ud; - f = G(L)->frealloc; - lua_unlock(L); - return f; -} - - -LUA_API void lua_setallocf (lua_State *L, lua_Alloc f, void *ud) { - lua_lock(L); - G(L)->ud = ud; - G(L)->frealloc = f; - lua_unlock(L); -} - - -LUA_API void *lua_newuserdata (lua_State *L, size_t size) { - Udata *u; - lua_lock(L); - luaC_checkGC(L); - u = luaS_newudata(L, size, getcurrenv(L)); - setuvalue(L, L->top, u); - api_incr_top(L); - lua_unlock(L); - return u + 1; -} - - - - -static const char *aux_upvalue (StkId fi, int n, TValue **val) { - Closure *f; - if (!ttisfunction(fi)) return NULL; - f = clvalue(fi); - if (f->c.isC) { - if (!(1 <= n && n <= f->c.nupvalues)) return NULL; - *val = &f->c.upvalue[n-1]; - return ""; - } - else { - Proto *p = f->l.p; - if (!(1 <= n && n <= p->sizeupvalues)) return NULL; - *val = f->l.upvals[n-1]->v; - return getstr(p->upvalues[n-1]); - } -} - - -LUA_API const char *lua_getupvalue (lua_State *L, int funcindex, int n) { - const char *name; - TValue *val; - lua_lock(L); - name = aux_upvalue(index2adr(L, funcindex), n, &val); - if (name) { - setobj2s(L, L->top, val); - api_incr_top(L); - } - lua_unlock(L); - return name; -} - - -LUA_API const char *lua_setupvalue (lua_State *L, int funcindex, int n) { - const char *name; - TValue *val; - StkId fi; - lua_lock(L); - fi = index2adr(L, funcindex); - api_checknelems(L, 1); - name = aux_upvalue(fi, n, &val); - if (name) { - L->top--; - setobj(L, val, L->top); - luaC_barrier(L, clvalue(fi), L->top); - } - lua_unlock(L); - return name; -} - diff --git a/lib/lua-5.1/src/lapi.h b/lib/lua-5.1/src/lapi.h deleted file mode 100644 index 2c3fab2..0000000 --- a/lib/lua-5.1/src/lapi.h +++ /dev/null @@ -1,16 +0,0 @@ -/* -** $Id: lapi.h,v 2.2.1.1 2007/12/27 13:02:25 roberto Exp $ -** Auxiliary functions from Lua API -** See Copyright Notice in lua.h -*/ - -#ifndef lapi_h -#define lapi_h - - -#include "lobject.h" - - -LUAI_FUNC void luaA_pushobject (lua_State *L, const TValue *o); - -#endif diff --git a/lib/lua-5.1/src/lauxlib.c b/lib/lua-5.1/src/lauxlib.c deleted file mode 100644 index 10f14e2..0000000 --- a/lib/lua-5.1/src/lauxlib.c +++ /dev/null @@ -1,652 +0,0 @@ -/* -** $Id: lauxlib.c,v 1.159.1.3 2008/01/21 13:20:51 roberto Exp $ -** Auxiliary functions for building Lua libraries -** See Copyright Notice in lua.h -*/ - - -#include -#include -#include -#include -#include -#include - - -/* This file uses only the official API of Lua. -** Any function declared here could be written as an application function. -*/ - -#define lauxlib_c -#define LUA_LIB - -#include "lua.h" - -#include "lauxlib.h" - - -#define FREELIST_REF 0 /* free list of references */ - - -/* convert a stack index to positive */ -#define abs_index(L, i) ((i) > 0 || (i) <= LUA_REGISTRYINDEX ? (i) : \ - lua_gettop(L) + (i) + 1) - - -/* -** {====================================================== -** Error-report functions -** ======================================================= -*/ - - -LUALIB_API int luaL_argerror (lua_State *L, int narg, const char *extramsg) { - lua_Debug ar; - if (!lua_getstack(L, 0, &ar)) /* no stack frame? */ - return luaL_error(L, "bad argument #%d (%s)", narg, extramsg); - lua_getinfo(L, "n", &ar); - if (strcmp(ar.namewhat, "method") == 0) { - narg--; /* do not count `self' */ - if (narg == 0) /* error is in the self argument itself? */ - return luaL_error(L, "calling " LUA_QS " on bad self (%s)", - ar.name, extramsg); - } - if (ar.name == NULL) - ar.name = "?"; - return luaL_error(L, "bad argument #%d to " LUA_QS " (%s)", - narg, ar.name, extramsg); -} - - -LUALIB_API int luaL_typerror (lua_State *L, int narg, const char *tname) { - const char *msg = lua_pushfstring(L, "%s expected, got %s", - tname, luaL_typename(L, narg)); - return luaL_argerror(L, narg, msg); -} - - -static void tag_error (lua_State *L, int narg, int tag) { - luaL_typerror(L, narg, lua_typename(L, tag)); -} - - -LUALIB_API void luaL_where (lua_State *L, int level) { - lua_Debug ar; - if (lua_getstack(L, level, &ar)) { /* check function at level */ - lua_getinfo(L, "Sl", &ar); /* get info about it */ - if (ar.currentline > 0) { /* is there info? */ - lua_pushfstring(L, "%s:%d: ", ar.short_src, ar.currentline); - return; - } - } - lua_pushliteral(L, ""); /* else, no information available... */ -} - - -LUALIB_API int luaL_error (lua_State *L, const char *fmt, ...) { - va_list argp; - va_start(argp, fmt); - luaL_where(L, 1); - lua_pushvfstring(L, fmt, argp); - va_end(argp); - lua_concat(L, 2); - return lua_error(L); -} - -/* }====================================================== */ - - -LUALIB_API int luaL_checkoption (lua_State *L, int narg, const char *def, - const char *const lst[]) { - const char *name = (def) ? luaL_optstring(L, narg, def) : - luaL_checkstring(L, narg); - int i; - for (i=0; lst[i]; i++) - if (strcmp(lst[i], name) == 0) - return i; - return luaL_argerror(L, narg, - lua_pushfstring(L, "invalid option " LUA_QS, name)); -} - - -LUALIB_API int luaL_newmetatable (lua_State *L, const char *tname) { - lua_getfield(L, LUA_REGISTRYINDEX, tname); /* get registry.name */ - if (!lua_isnil(L, -1)) /* name already in use? */ - return 0; /* leave previous value on top, but return 0 */ - lua_pop(L, 1); - lua_newtable(L); /* create metatable */ - lua_pushvalue(L, -1); - lua_setfield(L, LUA_REGISTRYINDEX, tname); /* registry.name = metatable */ - return 1; -} - - -LUALIB_API void *luaL_checkudata (lua_State *L, int ud, const char *tname) { - void *p = lua_touserdata(L, ud); - if (p != NULL) { /* value is a userdata? */ - if (lua_getmetatable(L, ud)) { /* does it have a metatable? */ - lua_getfield(L, LUA_REGISTRYINDEX, tname); /* get correct metatable */ - if (lua_rawequal(L, -1, -2)) { /* does it have the correct mt? */ - lua_pop(L, 2); /* remove both metatables */ - return p; - } - } - } - luaL_typerror(L, ud, tname); /* else error */ - return NULL; /* to avoid warnings */ -} - - -LUALIB_API void luaL_checkstack (lua_State *L, int space, const char *mes) { - if (!lua_checkstack(L, space)) - luaL_error(L, "stack overflow (%s)", mes); -} - - -LUALIB_API void luaL_checktype (lua_State *L, int narg, int t) { - if (lua_type(L, narg) != t) - tag_error(L, narg, t); -} - - -LUALIB_API void luaL_checkany (lua_State *L, int narg) { - if (lua_type(L, narg) == LUA_TNONE) - luaL_argerror(L, narg, "value expected"); -} - - -LUALIB_API const char *luaL_checklstring (lua_State *L, int narg, size_t *len) { - const char *s = lua_tolstring(L, narg, len); - if (!s) tag_error(L, narg, LUA_TSTRING); - return s; -} - - -LUALIB_API const char *luaL_optlstring (lua_State *L, int narg, - const char *def, size_t *len) { - if (lua_isnoneornil(L, narg)) { - if (len) - *len = (def ? strlen(def) : 0); - return def; - } - else return luaL_checklstring(L, narg, len); -} - - -LUALIB_API lua_Number luaL_checknumber (lua_State *L, int narg) { - lua_Number d = lua_tonumber(L, narg); - if (d == 0 && !lua_isnumber(L, narg)) /* avoid extra test when d is not 0 */ - tag_error(L, narg, LUA_TNUMBER); - return d; -} - - -LUALIB_API lua_Number luaL_optnumber (lua_State *L, int narg, lua_Number def) { - return luaL_opt(L, luaL_checknumber, narg, def); -} - - -LUALIB_API lua_Integer luaL_checkinteger (lua_State *L, int narg) { - lua_Integer d = lua_tointeger(L, narg); - if (d == 0 && !lua_isnumber(L, narg)) /* avoid extra test when d is not 0 */ - tag_error(L, narg, LUA_TNUMBER); - return d; -} - - -LUALIB_API lua_Integer luaL_optinteger (lua_State *L, int narg, - lua_Integer def) { - return luaL_opt(L, luaL_checkinteger, narg, def); -} - - -LUALIB_API int luaL_getmetafield (lua_State *L, int obj, const char *event) { - if (!lua_getmetatable(L, obj)) /* no metatable? */ - return 0; - lua_pushstring(L, event); - lua_rawget(L, -2); - if (lua_isnil(L, -1)) { - lua_pop(L, 2); /* remove metatable and metafield */ - return 0; - } - else { - lua_remove(L, -2); /* remove only metatable */ - return 1; - } -} - - -LUALIB_API int luaL_callmeta (lua_State *L, int obj, const char *event) { - obj = abs_index(L, obj); - if (!luaL_getmetafield(L, obj, event)) /* no metafield? */ - return 0; - lua_pushvalue(L, obj); - lua_call(L, 1, 1); - return 1; -} - - -LUALIB_API void (luaL_register) (lua_State *L, const char *libname, - const luaL_Reg *l) { - luaI_openlib(L, libname, l, 0); -} - - -static int libsize (const luaL_Reg *l) { - int size = 0; - for (; l->name; l++) size++; - return size; -} - - -LUALIB_API void luaI_openlib (lua_State *L, const char *libname, - const luaL_Reg *l, int nup) { - if (libname) { - int size = libsize(l); - /* check whether lib already exists */ - luaL_findtable(L, LUA_REGISTRYINDEX, "_LOADED", 1); - lua_getfield(L, -1, libname); /* get _LOADED[libname] */ - if (!lua_istable(L, -1)) { /* not found? */ - lua_pop(L, 1); /* remove previous result */ - /* try global variable (and create one if it does not exist) */ - if (luaL_findtable(L, LUA_GLOBALSINDEX, libname, size) != NULL) - luaL_error(L, "name conflict for module " LUA_QS, libname); - lua_pushvalue(L, -1); - lua_setfield(L, -3, libname); /* _LOADED[libname] = new table */ - } - lua_remove(L, -2); /* remove _LOADED table */ - lua_insert(L, -(nup+1)); /* move library table to below upvalues */ - } - for (; l->name; l++) { - int i; - for (i=0; ifunc, nup); - lua_setfield(L, -(nup+2), l->name); - } - lua_pop(L, nup); /* remove upvalues */ -} - - - -/* -** {====================================================== -** getn-setn: size for arrays -** ======================================================= -*/ - -#if defined(LUA_COMPAT_GETN) - -static int checkint (lua_State *L, int topop) { - int n = (lua_type(L, -1) == LUA_TNUMBER) ? lua_tointeger(L, -1) : -1; - lua_pop(L, topop); - return n; -} - - -static void getsizes (lua_State *L) { - lua_getfield(L, LUA_REGISTRYINDEX, "LUA_SIZES"); - if (lua_isnil(L, -1)) { /* no `size' table? */ - lua_pop(L, 1); /* remove nil */ - lua_newtable(L); /* create it */ - lua_pushvalue(L, -1); /* `size' will be its own metatable */ - lua_setmetatable(L, -2); - lua_pushliteral(L, "kv"); - lua_setfield(L, -2, "__mode"); /* metatable(N).__mode = "kv" */ - lua_pushvalue(L, -1); - lua_setfield(L, LUA_REGISTRYINDEX, "LUA_SIZES"); /* store in register */ - } -} - - -LUALIB_API void luaL_setn (lua_State *L, int t, int n) { - t = abs_index(L, t); - lua_pushliteral(L, "n"); - lua_rawget(L, t); - if (checkint(L, 1) >= 0) { /* is there a numeric field `n'? */ - lua_pushliteral(L, "n"); /* use it */ - lua_pushinteger(L, n); - lua_rawset(L, t); - } - else { /* use `sizes' */ - getsizes(L); - lua_pushvalue(L, t); - lua_pushinteger(L, n); - lua_rawset(L, -3); /* sizes[t] = n */ - lua_pop(L, 1); /* remove `sizes' */ - } -} - - -LUALIB_API int luaL_getn (lua_State *L, int t) { - int n; - t = abs_index(L, t); - lua_pushliteral(L, "n"); /* try t.n */ - lua_rawget(L, t); - if ((n = checkint(L, 1)) >= 0) return n; - getsizes(L); /* else try sizes[t] */ - lua_pushvalue(L, t); - lua_rawget(L, -2); - if ((n = checkint(L, 2)) >= 0) return n; - return (int)lua_objlen(L, t); -} - -#endif - -/* }====================================================== */ - - - -LUALIB_API const char *luaL_gsub (lua_State *L, const char *s, const char *p, - const char *r) { - const char *wild; - size_t l = strlen(p); - luaL_Buffer b; - luaL_buffinit(L, &b); - while ((wild = strstr(s, p)) != NULL) { - luaL_addlstring(&b, s, wild - s); /* push prefix */ - luaL_addstring(&b, r); /* push replacement in place of pattern */ - s = wild + l; /* continue after `p' */ - } - luaL_addstring(&b, s); /* push last suffix */ - luaL_pushresult(&b); - return lua_tostring(L, -1); -} - - -LUALIB_API const char *luaL_findtable (lua_State *L, int idx, - const char *fname, int szhint) { - const char *e; - lua_pushvalue(L, idx); - do { - e = strchr(fname, '.'); - if (e == NULL) e = fname + strlen(fname); - lua_pushlstring(L, fname, e - fname); - lua_rawget(L, -2); - if (lua_isnil(L, -1)) { /* no such field? */ - lua_pop(L, 1); /* remove this nil */ - lua_createtable(L, 0, (*e == '.' ? 1 : szhint)); /* new table for field */ - lua_pushlstring(L, fname, e - fname); - lua_pushvalue(L, -2); - lua_settable(L, -4); /* set new table into field */ - } - else if (!lua_istable(L, -1)) { /* field has a non-table value? */ - lua_pop(L, 2); /* remove table and value */ - return fname; /* return problematic part of the name */ - } - lua_remove(L, -2); /* remove previous table */ - fname = e + 1; - } while (*e == '.'); - return NULL; -} - - - -/* -** {====================================================== -** Generic Buffer manipulation -** ======================================================= -*/ - - -#define bufflen(B) ((B)->p - (B)->buffer) -#define bufffree(B) ((size_t)(LUAL_BUFFERSIZE - bufflen(B))) - -#define LIMIT (LUA_MINSTACK/2) - - -static int emptybuffer (luaL_Buffer *B) { - size_t l = bufflen(B); - if (l == 0) return 0; /* put nothing on stack */ - else { - lua_pushlstring(B->L, B->buffer, l); - B->p = B->buffer; - B->lvl++; - return 1; - } -} - - -static void adjuststack (luaL_Buffer *B) { - if (B->lvl > 1) { - lua_State *L = B->L; - int toget = 1; /* number of levels to concat */ - size_t toplen = lua_strlen(L, -1); - do { - size_t l = lua_strlen(L, -(toget+1)); - if (B->lvl - toget + 1 >= LIMIT || toplen > l) { - toplen += l; - toget++; - } - else break; - } while (toget < B->lvl); - lua_concat(L, toget); - B->lvl = B->lvl - toget + 1; - } -} - - -LUALIB_API char *luaL_prepbuffer (luaL_Buffer *B) { - if (emptybuffer(B)) - adjuststack(B); - return B->buffer; -} - - -LUALIB_API void luaL_addlstring (luaL_Buffer *B, const char *s, size_t l) { - while (l--) - luaL_addchar(B, *s++); -} - - -LUALIB_API void luaL_addstring (luaL_Buffer *B, const char *s) { - luaL_addlstring(B, s, strlen(s)); -} - - -LUALIB_API void luaL_pushresult (luaL_Buffer *B) { - emptybuffer(B); - lua_concat(B->L, B->lvl); - B->lvl = 1; -} - - -LUALIB_API void luaL_addvalue (luaL_Buffer *B) { - lua_State *L = B->L; - size_t vl; - const char *s = lua_tolstring(L, -1, &vl); - if (vl <= bufffree(B)) { /* fit into buffer? */ - memcpy(B->p, s, vl); /* put it there */ - B->p += vl; - lua_pop(L, 1); /* remove from stack */ - } - else { - if (emptybuffer(B)) - lua_insert(L, -2); /* put buffer before new value */ - B->lvl++; /* add new value into B stack */ - adjuststack(B); - } -} - - -LUALIB_API void luaL_buffinit (lua_State *L, luaL_Buffer *B) { - B->L = L; - B->p = B->buffer; - B->lvl = 0; -} - -/* }====================================================== */ - - -LUALIB_API int luaL_ref (lua_State *L, int t) { - int ref; - t = abs_index(L, t); - if (lua_isnil(L, -1)) { - lua_pop(L, 1); /* remove from stack */ - return LUA_REFNIL; /* `nil' has a unique fixed reference */ - } - lua_rawgeti(L, t, FREELIST_REF); /* get first free element */ - ref = (int)lua_tointeger(L, -1); /* ref = t[FREELIST_REF] */ - lua_pop(L, 1); /* remove it from stack */ - if (ref != 0) { /* any free element? */ - lua_rawgeti(L, t, ref); /* remove it from list */ - lua_rawseti(L, t, FREELIST_REF); /* (t[FREELIST_REF] = t[ref]) */ - } - else { /* no free elements */ - ref = (int)lua_objlen(L, t); - ref++; /* create new reference */ - } - lua_rawseti(L, t, ref); - return ref; -} - - -LUALIB_API void luaL_unref (lua_State *L, int t, int ref) { - if (ref >= 0) { - t = abs_index(L, t); - lua_rawgeti(L, t, FREELIST_REF); - lua_rawseti(L, t, ref); /* t[ref] = t[FREELIST_REF] */ - lua_pushinteger(L, ref); - lua_rawseti(L, t, FREELIST_REF); /* t[FREELIST_REF] = ref */ - } -} - - - -/* -** {====================================================== -** Load functions -** ======================================================= -*/ - -typedef struct LoadF { - int extraline; - FILE *f; - char buff[LUAL_BUFFERSIZE]; -} LoadF; - - -static const char *getF (lua_State *L, void *ud, size_t *size) { - LoadF *lf = (LoadF *)ud; - (void)L; - if (lf->extraline) { - lf->extraline = 0; - *size = 1; - return "\n"; - } - if (feof(lf->f)) return NULL; - *size = fread(lf->buff, 1, sizeof(lf->buff), lf->f); - return (*size > 0) ? lf->buff : NULL; -} - - -static int errfile (lua_State *L, const char *what, int fnameindex) { - const char *serr = strerror(errno); - const char *filename = lua_tostring(L, fnameindex) + 1; - lua_pushfstring(L, "cannot %s %s: %s", what, filename, serr); - lua_remove(L, fnameindex); - return LUA_ERRFILE; -} - - -LUALIB_API int luaL_loadfile (lua_State *L, const char *filename) { - LoadF lf; - int status, readstatus; - int c; - int fnameindex = lua_gettop(L) + 1; /* index of filename on the stack */ - lf.extraline = 0; - if (filename == NULL) { - lua_pushliteral(L, "=stdin"); - lf.f = stdin; - } - else { - lua_pushfstring(L, "@%s", filename); - lf.f = fopen(filename, "r"); - if (lf.f == NULL) return errfile(L, "open", fnameindex); - } - c = getc(lf.f); - if (c == '#') { /* Unix exec. file? */ - lf.extraline = 1; - while ((c = getc(lf.f)) != EOF && c != '\n') ; /* skip first line */ - if (c == '\n') c = getc(lf.f); - } - if (c == LUA_SIGNATURE[0] && filename) { /* binary file? */ - lf.f = freopen(filename, "rb", lf.f); /* reopen in binary mode */ - if (lf.f == NULL) return errfile(L, "reopen", fnameindex); - /* skip eventual `#!...' */ - while ((c = getc(lf.f)) != EOF && c != LUA_SIGNATURE[0]) ; - lf.extraline = 0; - } - ungetc(c, lf.f); - status = lua_load(L, getF, &lf, lua_tostring(L, -1)); - readstatus = ferror(lf.f); - if (filename) fclose(lf.f); /* close file (even in case of errors) */ - if (readstatus) { - lua_settop(L, fnameindex); /* ignore results from `lua_load' */ - return errfile(L, "read", fnameindex); - } - lua_remove(L, fnameindex); - return status; -} - - -typedef struct LoadS { - const char *s; - size_t size; -} LoadS; - - -static const char *getS (lua_State *L, void *ud, size_t *size) { - LoadS *ls = (LoadS *)ud; - (void)L; - if (ls->size == 0) return NULL; - *size = ls->size; - ls->size = 0; - return ls->s; -} - - -LUALIB_API int luaL_loadbuffer (lua_State *L, const char *buff, size_t size, - const char *name) { - LoadS ls; - ls.s = buff; - ls.size = size; - return lua_load(L, getS, &ls, name); -} - - -LUALIB_API int (luaL_loadstring) (lua_State *L, const char *s) { - return luaL_loadbuffer(L, s, strlen(s), s); -} - - - -/* }====================================================== */ - - -static void *l_alloc (void *ud, void *ptr, size_t osize, size_t nsize) { - (void)ud; - (void)osize; - if (nsize == 0) { - free(ptr); - return NULL; - } - else - return realloc(ptr, nsize); -} - - -static int panic (lua_State *L) { - (void)L; /* to avoid warnings */ - fprintf(stderr, "PANIC: unprotected error in call to Lua API (%s)\n", - lua_tostring(L, -1)); - return 0; -} - - -LUALIB_API lua_State *luaL_newstate (void) { - lua_State *L = lua_newstate(l_alloc, NULL); - if (L) lua_atpanic(L, &panic); - return L; -} - diff --git a/lib/lua-5.1/src/lauxlib.h b/lib/lua-5.1/src/lauxlib.h deleted file mode 100644 index 3425823..0000000 --- a/lib/lua-5.1/src/lauxlib.h +++ /dev/null @@ -1,174 +0,0 @@ -/* -** $Id: lauxlib.h,v 1.88.1.1 2007/12/27 13:02:25 roberto Exp $ -** Auxiliary functions for building Lua libraries -** See Copyright Notice in lua.h -*/ - - -#ifndef lauxlib_h -#define lauxlib_h - - -#include -#include - -#include "lua.h" - - -#if defined(LUA_COMPAT_GETN) -LUALIB_API int (luaL_getn) (lua_State *L, int t); -LUALIB_API void (luaL_setn) (lua_State *L, int t, int n); -#else -#define luaL_getn(L,i) ((int)lua_objlen(L, i)) -#define luaL_setn(L,i,j) ((void)0) /* no op! */ -#endif - -#if defined(LUA_COMPAT_OPENLIB) -#define luaI_openlib luaL_openlib -#endif - - -/* extra error code for `luaL_load' */ -#define LUA_ERRFILE (LUA_ERRERR+1) - - -typedef struct luaL_Reg { - const char *name; - lua_CFunction func; -} luaL_Reg; - - - -LUALIB_API void (luaI_openlib) (lua_State *L, const char *libname, - const luaL_Reg *l, int nup); -LUALIB_API void (luaL_register) (lua_State *L, const char *libname, - const luaL_Reg *l); -LUALIB_API int (luaL_getmetafield) (lua_State *L, int obj, const char *e); -LUALIB_API int (luaL_callmeta) (lua_State *L, int obj, const char *e); -LUALIB_API int (luaL_typerror) (lua_State *L, int narg, const char *tname); -LUALIB_API int (luaL_argerror) (lua_State *L, int numarg, const char *extramsg); -LUALIB_API const char *(luaL_checklstring) (lua_State *L, int numArg, - size_t *l); -LUALIB_API const char *(luaL_optlstring) (lua_State *L, int numArg, - const char *def, size_t *l); -LUALIB_API lua_Number (luaL_checknumber) (lua_State *L, int numArg); -LUALIB_API lua_Number (luaL_optnumber) (lua_State *L, int nArg, lua_Number def); - -LUALIB_API lua_Integer (luaL_checkinteger) (lua_State *L, int numArg); -LUALIB_API lua_Integer (luaL_optinteger) (lua_State *L, int nArg, - lua_Integer def); - -LUALIB_API void (luaL_checkstack) (lua_State *L, int sz, const char *msg); -LUALIB_API void (luaL_checktype) (lua_State *L, int narg, int t); -LUALIB_API void (luaL_checkany) (lua_State *L, int narg); - -LUALIB_API int (luaL_newmetatable) (lua_State *L, const char *tname); -LUALIB_API void *(luaL_checkudata) (lua_State *L, int ud, const char *tname); - -LUALIB_API void (luaL_where) (lua_State *L, int lvl); -LUALIB_API int (luaL_error) (lua_State *L, const char *fmt, ...); - -LUALIB_API int (luaL_checkoption) (lua_State *L, int narg, const char *def, - const char *const lst[]); - -LUALIB_API int (luaL_ref) (lua_State *L, int t); -LUALIB_API void (luaL_unref) (lua_State *L, int t, int ref); - -LUALIB_API int (luaL_loadfile) (lua_State *L, const char *filename); -LUALIB_API int (luaL_loadbuffer) (lua_State *L, const char *buff, size_t sz, - const char *name); -LUALIB_API int (luaL_loadstring) (lua_State *L, const char *s); - -LUALIB_API lua_State *(luaL_newstate) (void); - - -LUALIB_API const char *(luaL_gsub) (lua_State *L, const char *s, const char *p, - const char *r); - -LUALIB_API const char *(luaL_findtable) (lua_State *L, int idx, - const char *fname, int szhint); - - - - -/* -** =============================================================== -** some useful macros -** =============================================================== -*/ - -#define luaL_argcheck(L, cond,numarg,extramsg) \ - ((void)((cond) || luaL_argerror(L, (numarg), (extramsg)))) -#define luaL_checkstring(L,n) (luaL_checklstring(L, (n), NULL)) -#define luaL_optstring(L,n,d) (luaL_optlstring(L, (n), (d), NULL)) -#define luaL_checkint(L,n) ((int)luaL_checkinteger(L, (n))) -#define luaL_optint(L,n,d) ((int)luaL_optinteger(L, (n), (d))) -#define luaL_checklong(L,n) ((long)luaL_checkinteger(L, (n))) -#define luaL_optlong(L,n,d) ((long)luaL_optinteger(L, (n), (d))) - -#define luaL_typename(L,i) lua_typename(L, lua_type(L,(i))) - -#define luaL_dofile(L, fn) \ - (luaL_loadfile(L, fn) || lua_pcall(L, 0, LUA_MULTRET, 0)) - -#define luaL_dostring(L, s) \ - (luaL_loadstring(L, s) || lua_pcall(L, 0, LUA_MULTRET, 0)) - -#define luaL_getmetatable(L,n) (lua_getfield(L, LUA_REGISTRYINDEX, (n))) - -#define luaL_opt(L,f,n,d) (lua_isnoneornil(L,(n)) ? (d) : f(L,(n))) - -/* -** {====================================================== -** Generic Buffer manipulation -** ======================================================= -*/ - - - -typedef struct luaL_Buffer { - char *p; /* current position in buffer */ - int lvl; /* number of strings in the stack (level) */ - lua_State *L; - char buffer[LUAL_BUFFERSIZE]; -} luaL_Buffer; - -#define luaL_addchar(B,c) \ - ((void)((B)->p < ((B)->buffer+LUAL_BUFFERSIZE) || luaL_prepbuffer(B)), \ - (*(B)->p++ = (char)(c))) - -/* compatibility only */ -#define luaL_putchar(B,c) luaL_addchar(B,c) - -#define luaL_addsize(B,n) ((B)->p += (n)) - -LUALIB_API void (luaL_buffinit) (lua_State *L, luaL_Buffer *B); -LUALIB_API char *(luaL_prepbuffer) (luaL_Buffer *B); -LUALIB_API void (luaL_addlstring) (luaL_Buffer *B, const char *s, size_t l); -LUALIB_API void (luaL_addstring) (luaL_Buffer *B, const char *s); -LUALIB_API void (luaL_addvalue) (luaL_Buffer *B); -LUALIB_API void (luaL_pushresult) (luaL_Buffer *B); - - -/* }====================================================== */ - - -/* compatibility with ref system */ - -/* pre-defined references */ -#define LUA_NOREF (-2) -#define LUA_REFNIL (-1) - -#define lua_ref(L,lock) ((lock) ? luaL_ref(L, LUA_REGISTRYINDEX) : \ - (lua_pushstring(L, "unlocked references are obsolete"), lua_error(L), 0)) - -#define lua_unref(L,ref) luaL_unref(L, LUA_REGISTRYINDEX, (ref)) - -#define lua_getref(L,ref) lua_rawgeti(L, LUA_REGISTRYINDEX, (ref)) - - -#define luaL_reg luaL_Reg - -#endif - - diff --git a/lib/lua-5.1/src/lbaselib.c b/lib/lua-5.1/src/lbaselib.c deleted file mode 100644 index 2ab550b..0000000 --- a/lib/lua-5.1/src/lbaselib.c +++ /dev/null @@ -1,653 +0,0 @@ -/* -** $Id: lbaselib.c,v 1.191.1.6 2008/02/14 16:46:22 roberto Exp $ -** Basic library -** See Copyright Notice in lua.h -*/ - - - -#include -#include -#include -#include - -#define lbaselib_c -#define LUA_LIB - -#include "lua.h" - -#include "lauxlib.h" -#include "lualib.h" - - - - -/* -** If your system does not support `stdout', you can just remove this function. -** If you need, you can define your own `print' function, following this -** model but changing `fputs' to put the strings at a proper place -** (a console window or a log file, for instance). -*/ -static int luaB_print (lua_State *L) { - int n = lua_gettop(L); /* number of arguments */ - int i; - lua_getglobal(L, "tostring"); - for (i=1; i<=n; i++) { - const char *s; - lua_pushvalue(L, -1); /* function to be called */ - lua_pushvalue(L, i); /* value to print */ - lua_call(L, 1, 1); - s = lua_tostring(L, -1); /* get result */ - if (s == NULL) - return luaL_error(L, LUA_QL("tostring") " must return a string to " - LUA_QL("print")); - if (i>1) fputs("\t", stdout); - fputs(s, stdout); - lua_pop(L, 1); /* pop result */ - } - fputs("\n", stdout); - return 0; -} - - -static int luaB_tonumber (lua_State *L) { - int base = luaL_optint(L, 2, 10); - if (base == 10) { /* standard conversion */ - luaL_checkany(L, 1); - if (lua_isnumber(L, 1)) { - lua_pushnumber(L, lua_tonumber(L, 1)); - return 1; - } - } - else { - const char *s1 = luaL_checkstring(L, 1); - char *s2; - unsigned long n; - luaL_argcheck(L, 2 <= base && base <= 36, 2, "base out of range"); - n = strtoul(s1, &s2, base); - if (s1 != s2) { /* at least one valid digit? */ - while (isspace((unsigned char)(*s2))) s2++; /* skip trailing spaces */ - if (*s2 == '\0') { /* no invalid trailing characters? */ - lua_pushnumber(L, (lua_Number)n); - return 1; - } - } - } - lua_pushnil(L); /* else not a number */ - return 1; -} - - -static int luaB_error (lua_State *L) { - int level = luaL_optint(L, 2, 1); - lua_settop(L, 1); - if (lua_isstring(L, 1) && level > 0) { /* add extra information? */ - luaL_where(L, level); - lua_pushvalue(L, 1); - lua_concat(L, 2); - } - return lua_error(L); -} - - -static int luaB_getmetatable (lua_State *L) { - luaL_checkany(L, 1); - if (!lua_getmetatable(L, 1)) { - lua_pushnil(L); - return 1; /* no metatable */ - } - luaL_getmetafield(L, 1, "__metatable"); - return 1; /* returns either __metatable field (if present) or metatable */ -} - - -static int luaB_setmetatable (lua_State *L) { - int t = lua_type(L, 2); - luaL_checktype(L, 1, LUA_TTABLE); - luaL_argcheck(L, t == LUA_TNIL || t == LUA_TTABLE, 2, - "nil or table expected"); - if (luaL_getmetafield(L, 1, "__metatable")) - luaL_error(L, "cannot change a protected metatable"); - lua_settop(L, 2); - lua_setmetatable(L, 1); - return 1; -} - - -static void getfunc (lua_State *L, int opt) { - if (lua_isfunction(L, 1)) lua_pushvalue(L, 1); - else { - lua_Debug ar; - int level = opt ? luaL_optint(L, 1, 1) : luaL_checkint(L, 1); - luaL_argcheck(L, level >= 0, 1, "level must be non-negative"); - if (lua_getstack(L, level, &ar) == 0) - luaL_argerror(L, 1, "invalid level"); - lua_getinfo(L, "f", &ar); - if (lua_isnil(L, -1)) - luaL_error(L, "no function environment for tail call at level %d", - level); - } -} - - -static int luaB_getfenv (lua_State *L) { - getfunc(L, 1); - if (lua_iscfunction(L, -1)) /* is a C function? */ - lua_pushvalue(L, LUA_GLOBALSINDEX); /* return the thread's global env. */ - else - lua_getfenv(L, -1); - return 1; -} - - -static int luaB_setfenv (lua_State *L) { - luaL_checktype(L, 2, LUA_TTABLE); - getfunc(L, 0); - lua_pushvalue(L, 2); - if (lua_isnumber(L, 1) && lua_tonumber(L, 1) == 0) { - /* change environment of current thread */ - lua_pushthread(L); - lua_insert(L, -2); - lua_setfenv(L, -2); - return 0; - } - else if (lua_iscfunction(L, -2) || lua_setfenv(L, -2) == 0) - luaL_error(L, - LUA_QL("setfenv") " cannot change environment of given object"); - return 1; -} - - -static int luaB_rawequal (lua_State *L) { - luaL_checkany(L, 1); - luaL_checkany(L, 2); - lua_pushboolean(L, lua_rawequal(L, 1, 2)); - return 1; -} - - -static int luaB_rawget (lua_State *L) { - luaL_checktype(L, 1, LUA_TTABLE); - luaL_checkany(L, 2); - lua_settop(L, 2); - lua_rawget(L, 1); - return 1; -} - -static int luaB_rawset (lua_State *L) { - luaL_checktype(L, 1, LUA_TTABLE); - luaL_checkany(L, 2); - luaL_checkany(L, 3); - lua_settop(L, 3); - lua_rawset(L, 1); - return 1; -} - - -static int luaB_gcinfo (lua_State *L) { - lua_pushinteger(L, lua_getgccount(L)); - return 1; -} - - -static int luaB_collectgarbage (lua_State *L) { - static const char *const opts[] = {"stop", "restart", "collect", - "count", "step", "setpause", "setstepmul", NULL}; - static const int optsnum[] = {LUA_GCSTOP, LUA_GCRESTART, LUA_GCCOLLECT, - LUA_GCCOUNT, LUA_GCSTEP, LUA_GCSETPAUSE, LUA_GCSETSTEPMUL}; - int o = luaL_checkoption(L, 1, "collect", opts); - int ex = luaL_optint(L, 2, 0); - int res = lua_gc(L, optsnum[o], ex); - switch (optsnum[o]) { - case LUA_GCCOUNT: { - int b = lua_gc(L, LUA_GCCOUNTB, 0); - lua_pushnumber(L, res + ((lua_Number)b/1024)); - return 1; - } - case LUA_GCSTEP: { - lua_pushboolean(L, res); - return 1; - } - default: { - lua_pushnumber(L, res); - return 1; - } - } -} - - -static int luaB_type (lua_State *L) { - luaL_checkany(L, 1); - lua_pushstring(L, luaL_typename(L, 1)); - return 1; -} - - -static int luaB_next (lua_State *L) { - luaL_checktype(L, 1, LUA_TTABLE); - lua_settop(L, 2); /* create a 2nd argument if there isn't one */ - if (lua_next(L, 1)) - return 2; - else { - lua_pushnil(L); - return 1; - } -} - - -static int luaB_pairs (lua_State *L) { - luaL_checktype(L, 1, LUA_TTABLE); - lua_pushvalue(L, lua_upvalueindex(1)); /* return generator, */ - lua_pushvalue(L, 1); /* state, */ - lua_pushnil(L); /* and initial value */ - return 3; -} - - -static int ipairsaux (lua_State *L) { - int i = luaL_checkint(L, 2); - luaL_checktype(L, 1, LUA_TTABLE); - i++; /* next value */ - lua_pushinteger(L, i); - lua_rawgeti(L, 1, i); - return (lua_isnil(L, -1)) ? 0 : 2; -} - - -static int luaB_ipairs (lua_State *L) { - luaL_checktype(L, 1, LUA_TTABLE); - lua_pushvalue(L, lua_upvalueindex(1)); /* return generator, */ - lua_pushvalue(L, 1); /* state, */ - lua_pushinteger(L, 0); /* and initial value */ - return 3; -} - - -static int load_aux (lua_State *L, int status) { - if (status == 0) /* OK? */ - return 1; - else { - lua_pushnil(L); - lua_insert(L, -2); /* put before error message */ - return 2; /* return nil plus error message */ - } -} - - -static int luaB_loadstring (lua_State *L) { - size_t l; - const char *s = luaL_checklstring(L, 1, &l); - const char *chunkname = luaL_optstring(L, 2, s); - return load_aux(L, luaL_loadbuffer(L, s, l, chunkname)); -} - - -static int luaB_loadfile (lua_State *L) { - const char *fname = luaL_optstring(L, 1, NULL); - return load_aux(L, luaL_loadfile(L, fname)); -} - - -/* -** Reader for generic `load' function: `lua_load' uses the -** stack for internal stuff, so the reader cannot change the -** stack top. Instead, it keeps its resulting string in a -** reserved slot inside the stack. -*/ -static const char *generic_reader (lua_State *L, void *ud, size_t *size) { - (void)ud; /* to avoid warnings */ - luaL_checkstack(L, 2, "too many nested functions"); - lua_pushvalue(L, 1); /* get function */ - lua_call(L, 0, 1); /* call it */ - if (lua_isnil(L, -1)) { - *size = 0; - return NULL; - } - else if (lua_isstring(L, -1)) { - lua_replace(L, 3); /* save string in a reserved stack slot */ - return lua_tolstring(L, 3, size); - } - else luaL_error(L, "reader function must return a string"); - return NULL; /* to avoid warnings */ -} - - -static int luaB_load (lua_State *L) { - int status; - const char *cname = luaL_optstring(L, 2, "=(load)"); - luaL_checktype(L, 1, LUA_TFUNCTION); - lua_settop(L, 3); /* function, eventual name, plus one reserved slot */ - status = lua_load(L, generic_reader, NULL, cname); - return load_aux(L, status); -} - - -static int luaB_dofile (lua_State *L) { - const char *fname = luaL_optstring(L, 1, NULL); - int n = lua_gettop(L); - if (luaL_loadfile(L, fname) != 0) lua_error(L); - lua_call(L, 0, LUA_MULTRET); - return lua_gettop(L) - n; -} - - -static int luaB_assert (lua_State *L) { - luaL_checkany(L, 1); - if (!lua_toboolean(L, 1)) - return luaL_error(L, "%s", luaL_optstring(L, 2, "assertion failed!")); - return lua_gettop(L); -} - - -static int luaB_unpack (lua_State *L) { - int i, e, n; - luaL_checktype(L, 1, LUA_TTABLE); - i = luaL_optint(L, 2, 1); - e = luaL_opt(L, luaL_checkint, 3, luaL_getn(L, 1)); - if (i > e) return 0; /* empty range */ - n = e - i + 1; /* number of elements */ - if (n <= 0 || !lua_checkstack(L, n)) /* n <= 0 means arith. overflow */ - return luaL_error(L, "too many results to unpack"); - lua_rawgeti(L, 1, i); /* push arg[i] (avoiding overflow problems) */ - while (i++ < e) /* push arg[i + 1...e] */ - lua_rawgeti(L, 1, i); - return n; -} - - -static int luaB_select (lua_State *L) { - int n = lua_gettop(L); - if (lua_type(L, 1) == LUA_TSTRING && *lua_tostring(L, 1) == '#') { - lua_pushinteger(L, n-1); - return 1; - } - else { - int i = luaL_checkint(L, 1); - if (i < 0) i = n + i; - else if (i > n) i = n; - luaL_argcheck(L, 1 <= i, 1, "index out of range"); - return n - i; - } -} - - -static int luaB_pcall (lua_State *L) { - int status; - luaL_checkany(L, 1); - status = lua_pcall(L, lua_gettop(L) - 1, LUA_MULTRET, 0); - lua_pushboolean(L, (status == 0)); - lua_insert(L, 1); - return lua_gettop(L); /* return status + all results */ -} - - -static int luaB_xpcall (lua_State *L) { - int status; - luaL_checkany(L, 2); - lua_settop(L, 2); - lua_insert(L, 1); /* put error function under function to be called */ - status = lua_pcall(L, 0, LUA_MULTRET, 1); - lua_pushboolean(L, (status == 0)); - lua_replace(L, 1); - return lua_gettop(L); /* return status + all results */ -} - - -static int luaB_tostring (lua_State *L) { - luaL_checkany(L, 1); - if (luaL_callmeta(L, 1, "__tostring")) /* is there a metafield? */ - return 1; /* use its value */ - switch (lua_type(L, 1)) { - case LUA_TNUMBER: - lua_pushstring(L, lua_tostring(L, 1)); - break; - case LUA_TSTRING: - lua_pushvalue(L, 1); - break; - case LUA_TBOOLEAN: - lua_pushstring(L, (lua_toboolean(L, 1) ? "true" : "false")); - break; - case LUA_TNIL: - lua_pushliteral(L, "nil"); - break; - default: - lua_pushfstring(L, "%s: %p", luaL_typename(L, 1), lua_topointer(L, 1)); - break; - } - return 1; -} - - -static int luaB_newproxy (lua_State *L) { - lua_settop(L, 1); - lua_newuserdata(L, 0); /* create proxy */ - if (lua_toboolean(L, 1) == 0) - return 1; /* no metatable */ - else if (lua_isboolean(L, 1)) { - lua_newtable(L); /* create a new metatable `m' ... */ - lua_pushvalue(L, -1); /* ... and mark `m' as a valid metatable */ - lua_pushboolean(L, 1); - lua_rawset(L, lua_upvalueindex(1)); /* weaktable[m] = true */ - } - else { - int validproxy = 0; /* to check if weaktable[metatable(u)] == true */ - if (lua_getmetatable(L, 1)) { - lua_rawget(L, lua_upvalueindex(1)); - validproxy = lua_toboolean(L, -1); - lua_pop(L, 1); /* remove value */ - } - luaL_argcheck(L, validproxy, 1, "boolean or proxy expected"); - lua_getmetatable(L, 1); /* metatable is valid; get it */ - } - lua_setmetatable(L, 2); - return 1; -} - - -static const luaL_Reg base_funcs[] = { - {"assert", luaB_assert}, - {"collectgarbage", luaB_collectgarbage}, - {"dofile", luaB_dofile}, - {"error", luaB_error}, - {"gcinfo", luaB_gcinfo}, - {"getfenv", luaB_getfenv}, - {"getmetatable", luaB_getmetatable}, - {"loadfile", luaB_loadfile}, - {"load", luaB_load}, - {"loadstring", luaB_loadstring}, - {"next", luaB_next}, - {"pcall", luaB_pcall}, - {"print", luaB_print}, - {"rawequal", luaB_rawequal}, - {"rawget", luaB_rawget}, - {"rawset", luaB_rawset}, - {"select", luaB_select}, - {"setfenv", luaB_setfenv}, - {"setmetatable", luaB_setmetatable}, - {"tonumber", luaB_tonumber}, - {"tostring", luaB_tostring}, - {"type", luaB_type}, - {"unpack", luaB_unpack}, - {"xpcall", luaB_xpcall}, - {NULL, NULL} -}; - - -/* -** {====================================================== -** Coroutine library -** ======================================================= -*/ - -#define CO_RUN 0 /* running */ -#define CO_SUS 1 /* suspended */ -#define CO_NOR 2 /* 'normal' (it resumed another coroutine) */ -#define CO_DEAD 3 - -static const char *const statnames[] = - {"running", "suspended", "normal", "dead"}; - -static int costatus (lua_State *L, lua_State *co) { - if (L == co) return CO_RUN; - switch (lua_status(co)) { - case LUA_YIELD: - return CO_SUS; - case 0: { - lua_Debug ar; - if (lua_getstack(co, 0, &ar) > 0) /* does it have frames? */ - return CO_NOR; /* it is running */ - else if (lua_gettop(co) == 0) - return CO_DEAD; - else - return CO_SUS; /* initial state */ - } - default: /* some error occured */ - return CO_DEAD; - } -} - - -static int luaB_costatus (lua_State *L) { - lua_State *co = lua_tothread(L, 1); - luaL_argcheck(L, co, 1, "coroutine expected"); - lua_pushstring(L, statnames[costatus(L, co)]); - return 1; -} - - -static int auxresume (lua_State *L, lua_State *co, int narg) { - int status = costatus(L, co); - if (!lua_checkstack(co, narg)) - luaL_error(L, "too many arguments to resume"); - if (status != CO_SUS) { - lua_pushfstring(L, "cannot resume %s coroutine", statnames[status]); - return -1; /* error flag */ - } - lua_xmove(L, co, narg); - lua_setlevel(L, co); - status = lua_resume(co, narg); - if (status == 0 || status == LUA_YIELD) { - int nres = lua_gettop(co); - if (!lua_checkstack(L, nres + 1)) - luaL_error(L, "too many results to resume"); - lua_xmove(co, L, nres); /* move yielded values */ - return nres; - } - else { - lua_xmove(co, L, 1); /* move error message */ - return -1; /* error flag */ - } -} - - -static int luaB_coresume (lua_State *L) { - lua_State *co = lua_tothread(L, 1); - int r; - luaL_argcheck(L, co, 1, "coroutine expected"); - r = auxresume(L, co, lua_gettop(L) - 1); - if (r < 0) { - lua_pushboolean(L, 0); - lua_insert(L, -2); - return 2; /* return false + error message */ - } - else { - lua_pushboolean(L, 1); - lua_insert(L, -(r + 1)); - return r + 1; /* return true + `resume' returns */ - } -} - - -static int luaB_auxwrap (lua_State *L) { - lua_State *co = lua_tothread(L, lua_upvalueindex(1)); - int r = auxresume(L, co, lua_gettop(L)); - if (r < 0) { - if (lua_isstring(L, -1)) { /* error object is a string? */ - luaL_where(L, 1); /* add extra info */ - lua_insert(L, -2); - lua_concat(L, 2); - } - lua_error(L); /* propagate error */ - } - return r; -} - - -static int luaB_cocreate (lua_State *L) { - lua_State *NL = lua_newthread(L); - luaL_argcheck(L, lua_isfunction(L, 1) && !lua_iscfunction(L, 1), 1, - "Lua function expected"); - lua_pushvalue(L, 1); /* move function to top */ - lua_xmove(L, NL, 1); /* move function from L to NL */ - return 1; -} - - -static int luaB_cowrap (lua_State *L) { - luaB_cocreate(L); - lua_pushcclosure(L, luaB_auxwrap, 1); - return 1; -} - - -static int luaB_yield (lua_State *L) { - return lua_yield(L, lua_gettop(L)); -} - - -static int luaB_corunning (lua_State *L) { - if (lua_pushthread(L)) - lua_pushnil(L); /* main thread is not a coroutine */ - return 1; -} - - -static const luaL_Reg co_funcs[] = { - {"create", luaB_cocreate}, - {"resume", luaB_coresume}, - {"running", luaB_corunning}, - {"status", luaB_costatus}, - {"wrap", luaB_cowrap}, - {"yield", luaB_yield}, - {NULL, NULL} -}; - -/* }====================================================== */ - - -static void auxopen (lua_State *L, const char *name, - lua_CFunction f, lua_CFunction u) { - lua_pushcfunction(L, u); - lua_pushcclosure(L, f, 1); - lua_setfield(L, -2, name); -} - - -static void base_open (lua_State *L) { - /* set global _G */ - lua_pushvalue(L, LUA_GLOBALSINDEX); - lua_setglobal(L, "_G"); - /* open lib into global table */ - luaL_register(L, "_G", base_funcs); - lua_pushliteral(L, LUA_VERSION); - lua_setglobal(L, "_VERSION"); /* set global _VERSION */ - /* `ipairs' and `pairs' need auxiliary functions as upvalues */ - auxopen(L, "ipairs", luaB_ipairs, ipairsaux); - auxopen(L, "pairs", luaB_pairs, luaB_next); - /* `newproxy' needs a weaktable as upvalue */ - lua_createtable(L, 0, 1); /* new table `w' */ - lua_pushvalue(L, -1); /* `w' will be its own metatable */ - lua_setmetatable(L, -2); - lua_pushliteral(L, "kv"); - lua_setfield(L, -2, "__mode"); /* metatable(w).__mode = "kv" */ - lua_pushcclosure(L, luaB_newproxy, 1); - lua_setglobal(L, "newproxy"); /* set global `newproxy' */ -} - - -LUALIB_API int luaopen_base (lua_State *L) { - base_open(L); - luaL_register(L, LUA_COLIBNAME, co_funcs); - return 2; -} - diff --git a/lib/lua-5.1/src/lcode.c b/lib/lua-5.1/src/lcode.c deleted file mode 100644 index 679cb9c..0000000 --- a/lib/lua-5.1/src/lcode.c +++ /dev/null @@ -1,831 +0,0 @@ -/* -** $Id: lcode.c,v 2.25.1.5 2011/01/31 14:53:16 roberto Exp $ -** Code generator for Lua -** See Copyright Notice in lua.h -*/ - - -#include - -#define lcode_c -#define LUA_CORE - -#include "lua.h" - -#include "lcode.h" -#include "ldebug.h" -#include "ldo.h" -#include "lgc.h" -#include "llex.h" -#include "lmem.h" -#include "lobject.h" -#include "lopcodes.h" -#include "lparser.h" -#include "ltable.h" - - -#define hasjumps(e) ((e)->t != (e)->f) - - -static int isnumeral(expdesc *e) { - return (e->k == VKNUM && e->t == NO_JUMP && e->f == NO_JUMP); -} - - -void luaK_nil (FuncState *fs, int from, int n) { - Instruction *previous; - if (fs->pc > fs->lasttarget) { /* no jumps to current position? */ - if (fs->pc == 0) { /* function start? */ - if (from >= fs->nactvar) - return; /* positions are already clean */ - } - else { - previous = &fs->f->code[fs->pc-1]; - if (GET_OPCODE(*previous) == OP_LOADNIL) { - int pfrom = GETARG_A(*previous); - int pto = GETARG_B(*previous); - if (pfrom <= from && from <= pto+1) { /* can connect both? */ - if (from+n-1 > pto) - SETARG_B(*previous, from+n-1); - return; - } - } - } - } - luaK_codeABC(fs, OP_LOADNIL, from, from+n-1, 0); /* else no optimization */ -} - - -int luaK_jump (FuncState *fs) { - int jpc = fs->jpc; /* save list of jumps to here */ - int j; - fs->jpc = NO_JUMP; - j = luaK_codeAsBx(fs, OP_JMP, 0, NO_JUMP); - luaK_concat(fs, &j, jpc); /* keep them on hold */ - return j; -} - - -void luaK_ret (FuncState *fs, int first, int nret) { - luaK_codeABC(fs, OP_RETURN, first, nret+1, 0); -} - - -static int condjump (FuncState *fs, OpCode op, int A, int B, int C) { - luaK_codeABC(fs, op, A, B, C); - return luaK_jump(fs); -} - - -static void fixjump (FuncState *fs, int pc, int dest) { - Instruction *jmp = &fs->f->code[pc]; - int offset = dest-(pc+1); - lua_assert(dest != NO_JUMP); - if (abs(offset) > MAXARG_sBx) - luaX_syntaxerror(fs->ls, "control structure too long"); - SETARG_sBx(*jmp, offset); -} - - -/* -** returns current `pc' and marks it as a jump target (to avoid wrong -** optimizations with consecutive instructions not in the same basic block). -*/ -int luaK_getlabel (FuncState *fs) { - fs->lasttarget = fs->pc; - return fs->pc; -} - - -static int getjump (FuncState *fs, int pc) { - int offset = GETARG_sBx(fs->f->code[pc]); - if (offset == NO_JUMP) /* point to itself represents end of list */ - return NO_JUMP; /* end of list */ - else - return (pc+1)+offset; /* turn offset into absolute position */ -} - - -static Instruction *getjumpcontrol (FuncState *fs, int pc) { - Instruction *pi = &fs->f->code[pc]; - if (pc >= 1 && testTMode(GET_OPCODE(*(pi-1)))) - return pi-1; - else - return pi; -} - - -/* -** check whether list has any jump that do not produce a value -** (or produce an inverted value) -*/ -static int need_value (FuncState *fs, int list) { - for (; list != NO_JUMP; list = getjump(fs, list)) { - Instruction i = *getjumpcontrol(fs, list); - if (GET_OPCODE(i) != OP_TESTSET) return 1; - } - return 0; /* not found */ -} - - -static int patchtestreg (FuncState *fs, int node, int reg) { - Instruction *i = getjumpcontrol(fs, node); - if (GET_OPCODE(*i) != OP_TESTSET) - return 0; /* cannot patch other instructions */ - if (reg != NO_REG && reg != GETARG_B(*i)) - SETARG_A(*i, reg); - else /* no register to put value or register already has the value */ - *i = CREATE_ABC(OP_TEST, GETARG_B(*i), 0, GETARG_C(*i)); - - return 1; -} - - -static void removevalues (FuncState *fs, int list) { - for (; list != NO_JUMP; list = getjump(fs, list)) - patchtestreg(fs, list, NO_REG); -} - - -static void patchlistaux (FuncState *fs, int list, int vtarget, int reg, - int dtarget) { - while (list != NO_JUMP) { - int next = getjump(fs, list); - if (patchtestreg(fs, list, reg)) - fixjump(fs, list, vtarget); - else - fixjump(fs, list, dtarget); /* jump to default target */ - list = next; - } -} - - -static void dischargejpc (FuncState *fs) { - patchlistaux(fs, fs->jpc, fs->pc, NO_REG, fs->pc); - fs->jpc = NO_JUMP; -} - - -void luaK_patchlist (FuncState *fs, int list, int target) { - if (target == fs->pc) - luaK_patchtohere(fs, list); - else { - lua_assert(target < fs->pc); - patchlistaux(fs, list, target, NO_REG, target); - } -} - - -void luaK_patchtohere (FuncState *fs, int list) { - luaK_getlabel(fs); - luaK_concat(fs, &fs->jpc, list); -} - - -void luaK_concat (FuncState *fs, int *l1, int l2) { - if (l2 == NO_JUMP) return; - else if (*l1 == NO_JUMP) - *l1 = l2; - else { - int list = *l1; - int next; - while ((next = getjump(fs, list)) != NO_JUMP) /* find last element */ - list = next; - fixjump(fs, list, l2); - } -} - - -void luaK_checkstack (FuncState *fs, int n) { - int newstack = fs->freereg + n; - if (newstack > fs->f->maxstacksize) { - if (newstack >= MAXSTACK) - luaX_syntaxerror(fs->ls, "function or expression too complex"); - fs->f->maxstacksize = cast_byte(newstack); - } -} - - -void luaK_reserveregs (FuncState *fs, int n) { - luaK_checkstack(fs, n); - fs->freereg += n; -} - - -static void freereg (FuncState *fs, int reg) { - if (!ISK(reg) && reg >= fs->nactvar) { - fs->freereg--; - lua_assert(reg == fs->freereg); - } -} - - -static void freeexp (FuncState *fs, expdesc *e) { - if (e->k == VNONRELOC) - freereg(fs, e->u.s.info); -} - - -static int addk (FuncState *fs, TValue *k, TValue *v) { - lua_State *L = fs->L; - TValue *idx = luaH_set(L, fs->h, k); - Proto *f = fs->f; - int oldsize = f->sizek; - if (ttisnumber(idx)) { - lua_assert(luaO_rawequalObj(&fs->f->k[cast_int(nvalue(idx))], v)); - return cast_int(nvalue(idx)); - } - else { /* constant not found; create a new entry */ - setnvalue(idx, cast_num(fs->nk)); - luaM_growvector(L, f->k, fs->nk, f->sizek, TValue, - MAXARG_Bx, "constant table overflow"); - while (oldsize < f->sizek) setnilvalue(&f->k[oldsize++]); - setobj(L, &f->k[fs->nk], v); - luaC_barrier(L, f, v); - return fs->nk++; - } -} - - -int luaK_stringK (FuncState *fs, TString *s) { - TValue o; - setsvalue(fs->L, &o, s); - return addk(fs, &o, &o); -} - - -int luaK_numberK (FuncState *fs, lua_Number r) { - TValue o; - setnvalue(&o, r); - return addk(fs, &o, &o); -} - - -static int boolK (FuncState *fs, int b) { - TValue o; - setbvalue(&o, b); - return addk(fs, &o, &o); -} - - -static int nilK (FuncState *fs) { - TValue k, v; - setnilvalue(&v); - /* cannot use nil as key; instead use table itself to represent nil */ - sethvalue(fs->L, &k, fs->h); - return addk(fs, &k, &v); -} - - -void luaK_setreturns (FuncState *fs, expdesc *e, int nresults) { - if (e->k == VCALL) { /* expression is an open function call? */ - SETARG_C(getcode(fs, e), nresults+1); - } - else if (e->k == VVARARG) { - SETARG_B(getcode(fs, e), nresults+1); - SETARG_A(getcode(fs, e), fs->freereg); - luaK_reserveregs(fs, 1); - } -} - - -void luaK_setoneret (FuncState *fs, expdesc *e) { - if (e->k == VCALL) { /* expression is an open function call? */ - e->k = VNONRELOC; - e->u.s.info = GETARG_A(getcode(fs, e)); - } - else if (e->k == VVARARG) { - SETARG_B(getcode(fs, e), 2); - e->k = VRELOCABLE; /* can relocate its simple result */ - } -} - - -void luaK_dischargevars (FuncState *fs, expdesc *e) { - switch (e->k) { - case VLOCAL: { - e->k = VNONRELOC; - break; - } - case VUPVAL: { - e->u.s.info = luaK_codeABC(fs, OP_GETUPVAL, 0, e->u.s.info, 0); - e->k = VRELOCABLE; - break; - } - case VGLOBAL: { - e->u.s.info = luaK_codeABx(fs, OP_GETGLOBAL, 0, e->u.s.info); - e->k = VRELOCABLE; - break; - } - case VINDEXED: { - freereg(fs, e->u.s.aux); - freereg(fs, e->u.s.info); - e->u.s.info = luaK_codeABC(fs, OP_GETTABLE, 0, e->u.s.info, e->u.s.aux); - e->k = VRELOCABLE; - break; - } - case VVARARG: - case VCALL: { - luaK_setoneret(fs, e); - break; - } - default: break; /* there is one value available (somewhere) */ - } -} - - -static int code_label (FuncState *fs, int A, int b, int jump) { - luaK_getlabel(fs); /* those instructions may be jump targets */ - return luaK_codeABC(fs, OP_LOADBOOL, A, b, jump); -} - - -static void discharge2reg (FuncState *fs, expdesc *e, int reg) { - luaK_dischargevars(fs, e); - switch (e->k) { - case VNIL: { - luaK_nil(fs, reg, 1); - break; - } - case VFALSE: case VTRUE: { - luaK_codeABC(fs, OP_LOADBOOL, reg, e->k == VTRUE, 0); - break; - } - case VK: { - luaK_codeABx(fs, OP_LOADK, reg, e->u.s.info); - break; - } - case VKNUM: { - luaK_codeABx(fs, OP_LOADK, reg, luaK_numberK(fs, e->u.nval)); - break; - } - case VRELOCABLE: { - Instruction *pc = &getcode(fs, e); - SETARG_A(*pc, reg); - break; - } - case VNONRELOC: { - if (reg != e->u.s.info) - luaK_codeABC(fs, OP_MOVE, reg, e->u.s.info, 0); - break; - } - default: { - lua_assert(e->k == VVOID || e->k == VJMP); - return; /* nothing to do... */ - } - } - e->u.s.info = reg; - e->k = VNONRELOC; -} - - -static void discharge2anyreg (FuncState *fs, expdesc *e) { - if (e->k != VNONRELOC) { - luaK_reserveregs(fs, 1); - discharge2reg(fs, e, fs->freereg-1); - } -} - - -static void exp2reg (FuncState *fs, expdesc *e, int reg) { - discharge2reg(fs, e, reg); - if (e->k == VJMP) - luaK_concat(fs, &e->t, e->u.s.info); /* put this jump in `t' list */ - if (hasjumps(e)) { - int final; /* position after whole expression */ - int p_f = NO_JUMP; /* position of an eventual LOAD false */ - int p_t = NO_JUMP; /* position of an eventual LOAD true */ - if (need_value(fs, e->t) || need_value(fs, e->f)) { - int fj = (e->k == VJMP) ? NO_JUMP : luaK_jump(fs); - p_f = code_label(fs, reg, 0, 1); - p_t = code_label(fs, reg, 1, 0); - luaK_patchtohere(fs, fj); - } - final = luaK_getlabel(fs); - patchlistaux(fs, e->f, final, reg, p_f); - patchlistaux(fs, e->t, final, reg, p_t); - } - e->f = e->t = NO_JUMP; - e->u.s.info = reg; - e->k = VNONRELOC; -} - - -void luaK_exp2nextreg (FuncState *fs, expdesc *e) { - luaK_dischargevars(fs, e); - freeexp(fs, e); - luaK_reserveregs(fs, 1); - exp2reg(fs, e, fs->freereg - 1); -} - - -int luaK_exp2anyreg (FuncState *fs, expdesc *e) { - luaK_dischargevars(fs, e); - if (e->k == VNONRELOC) { - if (!hasjumps(e)) return e->u.s.info; /* exp is already in a register */ - if (e->u.s.info >= fs->nactvar) { /* reg. is not a local? */ - exp2reg(fs, e, e->u.s.info); /* put value on it */ - return e->u.s.info; - } - } - luaK_exp2nextreg(fs, e); /* default */ - return e->u.s.info; -} - - -void luaK_exp2val (FuncState *fs, expdesc *e) { - if (hasjumps(e)) - luaK_exp2anyreg(fs, e); - else - luaK_dischargevars(fs, e); -} - - -int luaK_exp2RK (FuncState *fs, expdesc *e) { - luaK_exp2val(fs, e); - switch (e->k) { - case VKNUM: - case VTRUE: - case VFALSE: - case VNIL: { - if (fs->nk <= MAXINDEXRK) { /* constant fit in RK operand? */ - e->u.s.info = (e->k == VNIL) ? nilK(fs) : - (e->k == VKNUM) ? luaK_numberK(fs, e->u.nval) : - boolK(fs, (e->k == VTRUE)); - e->k = VK; - return RKASK(e->u.s.info); - } - else break; - } - case VK: { - if (e->u.s.info <= MAXINDEXRK) /* constant fit in argC? */ - return RKASK(e->u.s.info); - else break; - } - default: break; - } - /* not a constant in the right range: put it in a register */ - return luaK_exp2anyreg(fs, e); -} - - -void luaK_storevar (FuncState *fs, expdesc *var, expdesc *ex) { - switch (var->k) { - case VLOCAL: { - freeexp(fs, ex); - exp2reg(fs, ex, var->u.s.info); - return; - } - case VUPVAL: { - int e = luaK_exp2anyreg(fs, ex); - luaK_codeABC(fs, OP_SETUPVAL, e, var->u.s.info, 0); - break; - } - case VGLOBAL: { - int e = luaK_exp2anyreg(fs, ex); - luaK_codeABx(fs, OP_SETGLOBAL, e, var->u.s.info); - break; - } - case VINDEXED: { - int e = luaK_exp2RK(fs, ex); - luaK_codeABC(fs, OP_SETTABLE, var->u.s.info, var->u.s.aux, e); - break; - } - default: { - lua_assert(0); /* invalid var kind to store */ - break; - } - } - freeexp(fs, ex); -} - - -void luaK_self (FuncState *fs, expdesc *e, expdesc *key) { - int func; - luaK_exp2anyreg(fs, e); - freeexp(fs, e); - func = fs->freereg; - luaK_reserveregs(fs, 2); - luaK_codeABC(fs, OP_SELF, func, e->u.s.info, luaK_exp2RK(fs, key)); - freeexp(fs, key); - e->u.s.info = func; - e->k = VNONRELOC; -} - - -static void invertjump (FuncState *fs, expdesc *e) { - Instruction *pc = getjumpcontrol(fs, e->u.s.info); - lua_assert(testTMode(GET_OPCODE(*pc)) && GET_OPCODE(*pc) != OP_TESTSET && - GET_OPCODE(*pc) != OP_TEST); - SETARG_A(*pc, !(GETARG_A(*pc))); -} - - -static int jumponcond (FuncState *fs, expdesc *e, int cond) { - if (e->k == VRELOCABLE) { - Instruction ie = getcode(fs, e); - if (GET_OPCODE(ie) == OP_NOT) { - fs->pc--; /* remove previous OP_NOT */ - return condjump(fs, OP_TEST, GETARG_B(ie), 0, !cond); - } - /* else go through */ - } - discharge2anyreg(fs, e); - freeexp(fs, e); - return condjump(fs, OP_TESTSET, NO_REG, e->u.s.info, cond); -} - - -void luaK_goiftrue (FuncState *fs, expdesc *e) { - int pc; /* pc of last jump */ - luaK_dischargevars(fs, e); - switch (e->k) { - case VK: case VKNUM: case VTRUE: { - pc = NO_JUMP; /* always true; do nothing */ - break; - } - case VJMP: { - invertjump(fs, e); - pc = e->u.s.info; - break; - } - default: { - pc = jumponcond(fs, e, 0); - break; - } - } - luaK_concat(fs, &e->f, pc); /* insert last jump in `f' list */ - luaK_patchtohere(fs, e->t); - e->t = NO_JUMP; -} - - -static void luaK_goiffalse (FuncState *fs, expdesc *e) { - int pc; /* pc of last jump */ - luaK_dischargevars(fs, e); - switch (e->k) { - case VNIL: case VFALSE: { - pc = NO_JUMP; /* always false; do nothing */ - break; - } - case VJMP: { - pc = e->u.s.info; - break; - } - default: { - pc = jumponcond(fs, e, 1); - break; - } - } - luaK_concat(fs, &e->t, pc); /* insert last jump in `t' list */ - luaK_patchtohere(fs, e->f); - e->f = NO_JUMP; -} - - -static void codenot (FuncState *fs, expdesc *e) { - luaK_dischargevars(fs, e); - switch (e->k) { - case VNIL: case VFALSE: { - e->k = VTRUE; - break; - } - case VK: case VKNUM: case VTRUE: { - e->k = VFALSE; - break; - } - case VJMP: { - invertjump(fs, e); - break; - } - case VRELOCABLE: - case VNONRELOC: { - discharge2anyreg(fs, e); - freeexp(fs, e); - e->u.s.info = luaK_codeABC(fs, OP_NOT, 0, e->u.s.info, 0); - e->k = VRELOCABLE; - break; - } - default: { - lua_assert(0); /* cannot happen */ - break; - } - } - /* interchange true and false lists */ - { int temp = e->f; e->f = e->t; e->t = temp; } - removevalues(fs, e->f); - removevalues(fs, e->t); -} - - -void luaK_indexed (FuncState *fs, expdesc *t, expdesc *k) { - t->u.s.aux = luaK_exp2RK(fs, k); - t->k = VINDEXED; -} - - -static int constfolding (OpCode op, expdesc *e1, expdesc *e2) { - lua_Number v1, v2, r; - if (!isnumeral(e1) || !isnumeral(e2)) return 0; - v1 = e1->u.nval; - v2 = e2->u.nval; - switch (op) { - case OP_ADD: r = luai_numadd(v1, v2); break; - case OP_SUB: r = luai_numsub(v1, v2); break; - case OP_MUL: r = luai_nummul(v1, v2); break; - case OP_DIV: - if (v2 == 0) return 0; /* do not attempt to divide by 0 */ - r = luai_numdiv(v1, v2); break; - case OP_MOD: - if (v2 == 0) return 0; /* do not attempt to divide by 0 */ - r = luai_nummod(v1, v2); break; - case OP_POW: r = luai_numpow(v1, v2); break; - case OP_UNM: r = luai_numunm(v1); break; - case OP_LEN: return 0; /* no constant folding for 'len' */ - default: lua_assert(0); r = 0; break; - } - if (luai_numisnan(r)) return 0; /* do not attempt to produce NaN */ - e1->u.nval = r; - return 1; -} - - -static void codearith (FuncState *fs, OpCode op, expdesc *e1, expdesc *e2) { - if (constfolding(op, e1, e2)) - return; - else { - int o2 = (op != OP_UNM && op != OP_LEN) ? luaK_exp2RK(fs, e2) : 0; - int o1 = luaK_exp2RK(fs, e1); - if (o1 > o2) { - freeexp(fs, e1); - freeexp(fs, e2); - } - else { - freeexp(fs, e2); - freeexp(fs, e1); - } - e1->u.s.info = luaK_codeABC(fs, op, 0, o1, o2); - e1->k = VRELOCABLE; - } -} - - -static void codecomp (FuncState *fs, OpCode op, int cond, expdesc *e1, - expdesc *e2) { - int o1 = luaK_exp2RK(fs, e1); - int o2 = luaK_exp2RK(fs, e2); - freeexp(fs, e2); - freeexp(fs, e1); - if (cond == 0 && op != OP_EQ) { - int temp; /* exchange args to replace by `<' or `<=' */ - temp = o1; o1 = o2; o2 = temp; /* o1 <==> o2 */ - cond = 1; - } - e1->u.s.info = condjump(fs, op, cond, o1, o2); - e1->k = VJMP; -} - - -void luaK_prefix (FuncState *fs, UnOpr op, expdesc *e) { - expdesc e2; - e2.t = e2.f = NO_JUMP; e2.k = VKNUM; e2.u.nval = 0; - switch (op) { - case OPR_MINUS: { - if (!isnumeral(e)) - luaK_exp2anyreg(fs, e); /* cannot operate on non-numeric constants */ - codearith(fs, OP_UNM, e, &e2); - break; - } - case OPR_NOT: codenot(fs, e); break; - case OPR_LEN: { - luaK_exp2anyreg(fs, e); /* cannot operate on constants */ - codearith(fs, OP_LEN, e, &e2); - break; - } - default: lua_assert(0); - } -} - - -void luaK_infix (FuncState *fs, BinOpr op, expdesc *v) { - switch (op) { - case OPR_AND: { - luaK_goiftrue(fs, v); - break; - } - case OPR_OR: { - luaK_goiffalse(fs, v); - break; - } - case OPR_CONCAT: { - luaK_exp2nextreg(fs, v); /* operand must be on the `stack' */ - break; - } - case OPR_ADD: case OPR_SUB: case OPR_MUL: case OPR_DIV: - case OPR_MOD: case OPR_POW: { - if (!isnumeral(v)) luaK_exp2RK(fs, v); - break; - } - default: { - luaK_exp2RK(fs, v); - break; - } - } -} - - -void luaK_posfix (FuncState *fs, BinOpr op, expdesc *e1, expdesc *e2) { - switch (op) { - case OPR_AND: { - lua_assert(e1->t == NO_JUMP); /* list must be closed */ - luaK_dischargevars(fs, e2); - luaK_concat(fs, &e2->f, e1->f); - *e1 = *e2; - break; - } - case OPR_OR: { - lua_assert(e1->f == NO_JUMP); /* list must be closed */ - luaK_dischargevars(fs, e2); - luaK_concat(fs, &e2->t, e1->t); - *e1 = *e2; - break; - } - case OPR_CONCAT: { - luaK_exp2val(fs, e2); - if (e2->k == VRELOCABLE && GET_OPCODE(getcode(fs, e2)) == OP_CONCAT) { - lua_assert(e1->u.s.info == GETARG_B(getcode(fs, e2))-1); - freeexp(fs, e1); - SETARG_B(getcode(fs, e2), e1->u.s.info); - e1->k = VRELOCABLE; e1->u.s.info = e2->u.s.info; - } - else { - luaK_exp2nextreg(fs, e2); /* operand must be on the 'stack' */ - codearith(fs, OP_CONCAT, e1, e2); - } - break; - } - case OPR_ADD: codearith(fs, OP_ADD, e1, e2); break; - case OPR_SUB: codearith(fs, OP_SUB, e1, e2); break; - case OPR_MUL: codearith(fs, OP_MUL, e1, e2); break; - case OPR_DIV: codearith(fs, OP_DIV, e1, e2); break; - case OPR_MOD: codearith(fs, OP_MOD, e1, e2); break; - case OPR_POW: codearith(fs, OP_POW, e1, e2); break; - case OPR_EQ: codecomp(fs, OP_EQ, 1, e1, e2); break; - case OPR_NE: codecomp(fs, OP_EQ, 0, e1, e2); break; - case OPR_LT: codecomp(fs, OP_LT, 1, e1, e2); break; - case OPR_LE: codecomp(fs, OP_LE, 1, e1, e2); break; - case OPR_GT: codecomp(fs, OP_LT, 0, e1, e2); break; - case OPR_GE: codecomp(fs, OP_LE, 0, e1, e2); break; - default: lua_assert(0); - } -} - - -void luaK_fixline (FuncState *fs, int line) { - fs->f->lineinfo[fs->pc - 1] = line; -} - - -static int luaK_code (FuncState *fs, Instruction i, int line) { - Proto *f = fs->f; - dischargejpc(fs); /* `pc' will change */ - /* put new instruction in code array */ - luaM_growvector(fs->L, f->code, fs->pc, f->sizecode, Instruction, - MAX_INT, "code size overflow"); - f->code[fs->pc] = i; - /* save corresponding line information */ - luaM_growvector(fs->L, f->lineinfo, fs->pc, f->sizelineinfo, int, - MAX_INT, "code size overflow"); - f->lineinfo[fs->pc] = line; - return fs->pc++; -} - - -int luaK_codeABC (FuncState *fs, OpCode o, int a, int b, int c) { - lua_assert(getOpMode(o) == iABC); - lua_assert(getBMode(o) != OpArgN || b == 0); - lua_assert(getCMode(o) != OpArgN || c == 0); - return luaK_code(fs, CREATE_ABC(o, a, b, c), fs->ls->lastline); -} - - -int luaK_codeABx (FuncState *fs, OpCode o, int a, unsigned int bc) { - lua_assert(getOpMode(o) == iABx || getOpMode(o) == iAsBx); - lua_assert(getCMode(o) == OpArgN); - return luaK_code(fs, CREATE_ABx(o, a, bc), fs->ls->lastline); -} - - -void luaK_setlist (FuncState *fs, int base, int nelems, int tostore) { - int c = (nelems - 1)/LFIELDS_PER_FLUSH + 1; - int b = (tostore == LUA_MULTRET) ? 0 : tostore; - lua_assert(tostore != 0); - if (c <= MAXARG_C) - luaK_codeABC(fs, OP_SETLIST, base, b, c); - else { - luaK_codeABC(fs, OP_SETLIST, base, b, 0); - luaK_code(fs, cast(Instruction, c), fs->ls->lastline); - } - fs->freereg = base + 1; /* free registers with list values */ -} - diff --git a/lib/lua-5.1/src/lcode.h b/lib/lua-5.1/src/lcode.h deleted file mode 100644 index b941c60..0000000 --- a/lib/lua-5.1/src/lcode.h +++ /dev/null @@ -1,76 +0,0 @@ -/* -** $Id: lcode.h,v 1.48.1.1 2007/12/27 13:02:25 roberto Exp $ -** Code generator for Lua -** See Copyright Notice in lua.h -*/ - -#ifndef lcode_h -#define lcode_h - -#include "llex.h" -#include "lobject.h" -#include "lopcodes.h" -#include "lparser.h" - - -/* -** Marks the end of a patch list. It is an invalid value both as an absolute -** address, and as a list link (would link an element to itself). -*/ -#define NO_JUMP (-1) - - -/* -** grep "ORDER OPR" if you change these enums -*/ -typedef enum BinOpr { - OPR_ADD, OPR_SUB, OPR_MUL, OPR_DIV, OPR_MOD, OPR_POW, - OPR_CONCAT, - OPR_NE, OPR_EQ, - OPR_LT, OPR_LE, OPR_GT, OPR_GE, - OPR_AND, OPR_OR, - OPR_NOBINOPR -} BinOpr; - - -typedef enum UnOpr { OPR_MINUS, OPR_NOT, OPR_LEN, OPR_NOUNOPR } UnOpr; - - -#define getcode(fs,e) ((fs)->f->code[(e)->u.s.info]) - -#define luaK_codeAsBx(fs,o,A,sBx) luaK_codeABx(fs,o,A,(sBx)+MAXARG_sBx) - -#define luaK_setmultret(fs,e) luaK_setreturns(fs, e, LUA_MULTRET) - -LUAI_FUNC int luaK_codeABx (FuncState *fs, OpCode o, int A, unsigned int Bx); -LUAI_FUNC int luaK_codeABC (FuncState *fs, OpCode o, int A, int B, int C); -LUAI_FUNC void luaK_fixline (FuncState *fs, int line); -LUAI_FUNC void luaK_nil (FuncState *fs, int from, int n); -LUAI_FUNC void luaK_reserveregs (FuncState *fs, int n); -LUAI_FUNC void luaK_checkstack (FuncState *fs, int n); -LUAI_FUNC int luaK_stringK (FuncState *fs, TString *s); -LUAI_FUNC int luaK_numberK (FuncState *fs, lua_Number r); -LUAI_FUNC void luaK_dischargevars (FuncState *fs, expdesc *e); -LUAI_FUNC int luaK_exp2anyreg (FuncState *fs, expdesc *e); -LUAI_FUNC void luaK_exp2nextreg (FuncState *fs, expdesc *e); -LUAI_FUNC void luaK_exp2val (FuncState *fs, expdesc *e); -LUAI_FUNC int luaK_exp2RK (FuncState *fs, expdesc *e); -LUAI_FUNC void luaK_self (FuncState *fs, expdesc *e, expdesc *key); -LUAI_FUNC void luaK_indexed (FuncState *fs, expdesc *t, expdesc *k); -LUAI_FUNC void luaK_goiftrue (FuncState *fs, expdesc *e); -LUAI_FUNC void luaK_storevar (FuncState *fs, expdesc *var, expdesc *e); -LUAI_FUNC void luaK_setreturns (FuncState *fs, expdesc *e, int nresults); -LUAI_FUNC void luaK_setoneret (FuncState *fs, expdesc *e); -LUAI_FUNC int luaK_jump (FuncState *fs); -LUAI_FUNC void luaK_ret (FuncState *fs, int first, int nret); -LUAI_FUNC void luaK_patchlist (FuncState *fs, int list, int target); -LUAI_FUNC void luaK_patchtohere (FuncState *fs, int list); -LUAI_FUNC void luaK_concat (FuncState *fs, int *l1, int l2); -LUAI_FUNC int luaK_getlabel (FuncState *fs); -LUAI_FUNC void luaK_prefix (FuncState *fs, UnOpr op, expdesc *v); -LUAI_FUNC void luaK_infix (FuncState *fs, BinOpr op, expdesc *v); -LUAI_FUNC void luaK_posfix (FuncState *fs, BinOpr op, expdesc *v1, expdesc *v2); -LUAI_FUNC void luaK_setlist (FuncState *fs, int base, int nelems, int tostore); - - -#endif diff --git a/lib/lua-5.1/src/ldblib.c b/lib/lua-5.1/src/ldblib.c deleted file mode 100644 index 2027eda..0000000 --- a/lib/lua-5.1/src/ldblib.c +++ /dev/null @@ -1,398 +0,0 @@ -/* -** $Id: ldblib.c,v 1.104.1.4 2009/08/04 18:50:18 roberto Exp $ -** Interface from Lua to its debug API -** See Copyright Notice in lua.h -*/ - - -#include -#include -#include - -#define ldblib_c -#define LUA_LIB - -#include "lua.h" - -#include "lauxlib.h" -#include "lualib.h" - - - -static int db_getregistry (lua_State *L) { - lua_pushvalue(L, LUA_REGISTRYINDEX); - return 1; -} - - -static int db_getmetatable (lua_State *L) { - luaL_checkany(L, 1); - if (!lua_getmetatable(L, 1)) { - lua_pushnil(L); /* no metatable */ - } - return 1; -} - - -static int db_setmetatable (lua_State *L) { - int t = lua_type(L, 2); - luaL_argcheck(L, t == LUA_TNIL || t == LUA_TTABLE, 2, - "nil or table expected"); - lua_settop(L, 2); - lua_pushboolean(L, lua_setmetatable(L, 1)); - return 1; -} - - -static int db_getfenv (lua_State *L) { - luaL_checkany(L, 1); - lua_getfenv(L, 1); - return 1; -} - - -static int db_setfenv (lua_State *L) { - luaL_checktype(L, 2, LUA_TTABLE); - lua_settop(L, 2); - if (lua_setfenv(L, 1) == 0) - luaL_error(L, LUA_QL("setfenv") - " cannot change environment of given object"); - return 1; -} - - -static void settabss (lua_State *L, const char *i, const char *v) { - lua_pushstring(L, v); - lua_setfield(L, -2, i); -} - - -static void settabsi (lua_State *L, const char *i, int v) { - lua_pushinteger(L, v); - lua_setfield(L, -2, i); -} - - -static lua_State *getthread (lua_State *L, int *arg) { - if (lua_isthread(L, 1)) { - *arg = 1; - return lua_tothread(L, 1); - } - else { - *arg = 0; - return L; - } -} - - -static void treatstackoption (lua_State *L, lua_State *L1, const char *fname) { - if (L == L1) { - lua_pushvalue(L, -2); - lua_remove(L, -3); - } - else - lua_xmove(L1, L, 1); - lua_setfield(L, -2, fname); -} - - -static int db_getinfo (lua_State *L) { - lua_Debug ar; - int arg; - lua_State *L1 = getthread(L, &arg); - const char *options = luaL_optstring(L, arg+2, "flnSu"); - if (lua_isnumber(L, arg+1)) { - if (!lua_getstack(L1, (int)lua_tointeger(L, arg+1), &ar)) { - lua_pushnil(L); /* level out of range */ - return 1; - } - } - else if (lua_isfunction(L, arg+1)) { - lua_pushfstring(L, ">%s", options); - options = lua_tostring(L, -1); - lua_pushvalue(L, arg+1); - lua_xmove(L, L1, 1); - } - else - return luaL_argerror(L, arg+1, "function or level expected"); - if (!lua_getinfo(L1, options, &ar)) - return luaL_argerror(L, arg+2, "invalid option"); - lua_createtable(L, 0, 2); - if (strchr(options, 'S')) { - settabss(L, "source", ar.source); - settabss(L, "short_src", ar.short_src); - settabsi(L, "linedefined", ar.linedefined); - settabsi(L, "lastlinedefined", ar.lastlinedefined); - settabss(L, "what", ar.what); - } - if (strchr(options, 'l')) - settabsi(L, "currentline", ar.currentline); - if (strchr(options, 'u')) - settabsi(L, "nups", ar.nups); - if (strchr(options, 'n')) { - settabss(L, "name", ar.name); - settabss(L, "namewhat", ar.namewhat); - } - if (strchr(options, 'L')) - treatstackoption(L, L1, "activelines"); - if (strchr(options, 'f')) - treatstackoption(L, L1, "func"); - return 1; /* return table */ -} - - -static int db_getlocal (lua_State *L) { - int arg; - lua_State *L1 = getthread(L, &arg); - lua_Debug ar; - const char *name; - if (!lua_getstack(L1, luaL_checkint(L, arg+1), &ar)) /* out of range? */ - return luaL_argerror(L, arg+1, "level out of range"); - name = lua_getlocal(L1, &ar, luaL_checkint(L, arg+2)); - if (name) { - lua_xmove(L1, L, 1); - lua_pushstring(L, name); - lua_pushvalue(L, -2); - return 2; - } - else { - lua_pushnil(L); - return 1; - } -} - - -static int db_setlocal (lua_State *L) { - int arg; - lua_State *L1 = getthread(L, &arg); - lua_Debug ar; - if (!lua_getstack(L1, luaL_checkint(L, arg+1), &ar)) /* out of range? */ - return luaL_argerror(L, arg+1, "level out of range"); - luaL_checkany(L, arg+3); - lua_settop(L, arg+3); - lua_xmove(L, L1, 1); - lua_pushstring(L, lua_setlocal(L1, &ar, luaL_checkint(L, arg+2))); - return 1; -} - - -static int auxupvalue (lua_State *L, int get) { - const char *name; - int n = luaL_checkint(L, 2); - luaL_checktype(L, 1, LUA_TFUNCTION); - if (lua_iscfunction(L, 1)) return 0; /* cannot touch C upvalues from Lua */ - name = get ? lua_getupvalue(L, 1, n) : lua_setupvalue(L, 1, n); - if (name == NULL) return 0; - lua_pushstring(L, name); - lua_insert(L, -(get+1)); - return get + 1; -} - - -static int db_getupvalue (lua_State *L) { - return auxupvalue(L, 1); -} - - -static int db_setupvalue (lua_State *L) { - luaL_checkany(L, 3); - return auxupvalue(L, 0); -} - - - -static const char KEY_HOOK = 'h'; - - -static void hookf (lua_State *L, lua_Debug *ar) { - static const char *const hooknames[] = - {"call", "return", "line", "count", "tail return"}; - lua_pushlightuserdata(L, (void *)&KEY_HOOK); - lua_rawget(L, LUA_REGISTRYINDEX); - lua_pushlightuserdata(L, L); - lua_rawget(L, -2); - if (lua_isfunction(L, -1)) { - lua_pushstring(L, hooknames[(int)ar->event]); - if (ar->currentline >= 0) - lua_pushinteger(L, ar->currentline); - else lua_pushnil(L); - lua_assert(lua_getinfo(L, "lS", ar)); - lua_call(L, 2, 0); - } -} - - -static int makemask (const char *smask, int count) { - int mask = 0; - if (strchr(smask, 'c')) mask |= LUA_MASKCALL; - if (strchr(smask, 'r')) mask |= LUA_MASKRET; - if (strchr(smask, 'l')) mask |= LUA_MASKLINE; - if (count > 0) mask |= LUA_MASKCOUNT; - return mask; -} - - -static char *unmakemask (int mask, char *smask) { - int i = 0; - if (mask & LUA_MASKCALL) smask[i++] = 'c'; - if (mask & LUA_MASKRET) smask[i++] = 'r'; - if (mask & LUA_MASKLINE) smask[i++] = 'l'; - smask[i] = '\0'; - return smask; -} - - -static void gethooktable (lua_State *L) { - lua_pushlightuserdata(L, (void *)&KEY_HOOK); - lua_rawget(L, LUA_REGISTRYINDEX); - if (!lua_istable(L, -1)) { - lua_pop(L, 1); - lua_createtable(L, 0, 1); - lua_pushlightuserdata(L, (void *)&KEY_HOOK); - lua_pushvalue(L, -2); - lua_rawset(L, LUA_REGISTRYINDEX); - } -} - - -static int db_sethook (lua_State *L) { - int arg, mask, count; - lua_Hook func; - lua_State *L1 = getthread(L, &arg); - if (lua_isnoneornil(L, arg+1)) { - lua_settop(L, arg+1); - func = NULL; mask = 0; count = 0; /* turn off hooks */ - } - else { - const char *smask = luaL_checkstring(L, arg+2); - luaL_checktype(L, arg+1, LUA_TFUNCTION); - count = luaL_optint(L, arg+3, 0); - func = hookf; mask = makemask(smask, count); - } - gethooktable(L); - lua_pushlightuserdata(L, L1); - lua_pushvalue(L, arg+1); - lua_rawset(L, -3); /* set new hook */ - lua_pop(L, 1); /* remove hook table */ - lua_sethook(L1, func, mask, count); /* set hooks */ - return 0; -} - - -static int db_gethook (lua_State *L) { - int arg; - lua_State *L1 = getthread(L, &arg); - char buff[5]; - int mask = lua_gethookmask(L1); - lua_Hook hook = lua_gethook(L1); - if (hook != NULL && hook != hookf) /* external hook? */ - lua_pushliteral(L, "external hook"); - else { - gethooktable(L); - lua_pushlightuserdata(L, L1); - lua_rawget(L, -2); /* get hook */ - lua_remove(L, -2); /* remove hook table */ - } - lua_pushstring(L, unmakemask(mask, buff)); - lua_pushinteger(L, lua_gethookcount(L1)); - return 3; -} - - -static int db_debug (lua_State *L) { - for (;;) { - char buffer[250]; - fputs("lua_debug> ", stderr); - if (fgets(buffer, sizeof(buffer), stdin) == 0 || - strcmp(buffer, "cont\n") == 0) - return 0; - if (luaL_loadbuffer(L, buffer, strlen(buffer), "=(debug command)") || - lua_pcall(L, 0, 0, 0)) { - fputs(lua_tostring(L, -1), stderr); - fputs("\n", stderr); - } - lua_settop(L, 0); /* remove eventual returns */ - } -} - - -#define LEVELS1 12 /* size of the first part of the stack */ -#define LEVELS2 10 /* size of the second part of the stack */ - -static int db_errorfb (lua_State *L) { - int level; - int firstpart = 1; /* still before eventual `...' */ - int arg; - lua_State *L1 = getthread(L, &arg); - lua_Debug ar; - if (lua_isnumber(L, arg+2)) { - level = (int)lua_tointeger(L, arg+2); - lua_pop(L, 1); - } - else - level = (L == L1) ? 1 : 0; /* level 0 may be this own function */ - if (lua_gettop(L) == arg) - lua_pushliteral(L, ""); - else if (!lua_isstring(L, arg+1)) return 1; /* message is not a string */ - else lua_pushliteral(L, "\n"); - lua_pushliteral(L, "stack traceback:"); - while (lua_getstack(L1, level++, &ar)) { - if (level > LEVELS1 && firstpart) { - /* no more than `LEVELS2' more levels? */ - if (!lua_getstack(L1, level+LEVELS2, &ar)) - level--; /* keep going */ - else { - lua_pushliteral(L, "\n\t..."); /* too many levels */ - while (lua_getstack(L1, level+LEVELS2, &ar)) /* find last levels */ - level++; - } - firstpart = 0; - continue; - } - lua_pushliteral(L, "\n\t"); - lua_getinfo(L1, "Snl", &ar); - lua_pushfstring(L, "%s:", ar.short_src); - if (ar.currentline > 0) - lua_pushfstring(L, "%d:", ar.currentline); - if (*ar.namewhat != '\0') /* is there a name? */ - lua_pushfstring(L, " in function " LUA_QS, ar.name); - else { - if (*ar.what == 'm') /* main? */ - lua_pushfstring(L, " in main chunk"); - else if (*ar.what == 'C' || *ar.what == 't') - lua_pushliteral(L, " ?"); /* C function or tail call */ - else - lua_pushfstring(L, " in function <%s:%d>", - ar.short_src, ar.linedefined); - } - lua_concat(L, lua_gettop(L) - arg); - } - lua_concat(L, lua_gettop(L) - arg); - return 1; -} - - -static const luaL_Reg dblib[] = { - {"debug", db_debug}, - {"getfenv", db_getfenv}, - {"gethook", db_gethook}, - {"getinfo", db_getinfo}, - {"getlocal", db_getlocal}, - {"getregistry", db_getregistry}, - {"getmetatable", db_getmetatable}, - {"getupvalue", db_getupvalue}, - {"setfenv", db_setfenv}, - {"sethook", db_sethook}, - {"setlocal", db_setlocal}, - {"setmetatable", db_setmetatable}, - {"setupvalue", db_setupvalue}, - {"traceback", db_errorfb}, - {NULL, NULL} -}; - - -LUALIB_API int luaopen_debug (lua_State *L) { - luaL_register(L, LUA_DBLIBNAME, dblib); - return 1; -} - diff --git a/lib/lua-5.1/src/ldebug.c b/lib/lua-5.1/src/ldebug.c deleted file mode 100644 index 50ad3d3..0000000 --- a/lib/lua-5.1/src/ldebug.c +++ /dev/null @@ -1,638 +0,0 @@ -/* -** $Id: ldebug.c,v 2.29.1.6 2008/05/08 16:56:26 roberto Exp $ -** Debug Interface -** See Copyright Notice in lua.h -*/ - - -#include -#include -#include - - -#define ldebug_c -#define LUA_CORE - -#include "lua.h" - -#include "lapi.h" -#include "lcode.h" -#include "ldebug.h" -#include "ldo.h" -#include "lfunc.h" -#include "lobject.h" -#include "lopcodes.h" -#include "lstate.h" -#include "lstring.h" -#include "ltable.h" -#include "ltm.h" -#include "lvm.h" - - - -static const char *getfuncname (lua_State *L, CallInfo *ci, const char **name); - - -static int currentpc (lua_State *L, CallInfo *ci) { - if (!isLua(ci)) return -1; /* function is not a Lua function? */ - if (ci == L->ci) - ci->savedpc = L->savedpc; - return pcRel(ci->savedpc, ci_func(ci)->l.p); -} - - -static int currentline (lua_State *L, CallInfo *ci) { - int pc = currentpc(L, ci); - if (pc < 0) - return -1; /* only active lua functions have current-line information */ - else - return getline(ci_func(ci)->l.p, pc); -} - - -/* -** this function can be called asynchronous (e.g. during a signal) -*/ -LUA_API int lua_sethook (lua_State *L, lua_Hook func, int mask, int count) { - if (func == NULL || mask == 0) { /* turn off hooks? */ - mask = 0; - func = NULL; - } - L->hook = func; - L->basehookcount = count; - resethookcount(L); - L->hookmask = cast_byte(mask); - return 1; -} - - -LUA_API lua_Hook lua_gethook (lua_State *L) { - return L->hook; -} - - -LUA_API int lua_gethookmask (lua_State *L) { - return L->hookmask; -} - - -LUA_API int lua_gethookcount (lua_State *L) { - return L->basehookcount; -} - - -LUA_API int lua_getstack (lua_State *L, int level, lua_Debug *ar) { - int status; - CallInfo *ci; - lua_lock(L); - for (ci = L->ci; level > 0 && ci > L->base_ci; ci--) { - level--; - if (f_isLua(ci)) /* Lua function? */ - level -= ci->tailcalls; /* skip lost tail calls */ - } - if (level == 0 && ci > L->base_ci) { /* level found? */ - status = 1; - ar->i_ci = cast_int(ci - L->base_ci); - } - else if (level < 0) { /* level is of a lost tail call? */ - status = 1; - ar->i_ci = 0; - } - else status = 0; /* no such level */ - lua_unlock(L); - return status; -} - - -static Proto *getluaproto (CallInfo *ci) { - return (isLua(ci) ? ci_func(ci)->l.p : NULL); -} - - -static const char *findlocal (lua_State *L, CallInfo *ci, int n) { - const char *name; - Proto *fp = getluaproto(ci); - if (fp && (name = luaF_getlocalname(fp, n, currentpc(L, ci))) != NULL) - return name; /* is a local variable in a Lua function */ - else { - StkId limit = (ci == L->ci) ? L->top : (ci+1)->func; - if (limit - ci->base >= n && n > 0) /* is 'n' inside 'ci' stack? */ - return "(*temporary)"; - else - return NULL; - } -} - - -LUA_API const char *lua_getlocal (lua_State *L, const lua_Debug *ar, int n) { - CallInfo *ci = L->base_ci + ar->i_ci; - const char *name = findlocal(L, ci, n); - lua_lock(L); - if (name) - luaA_pushobject(L, ci->base + (n - 1)); - lua_unlock(L); - return name; -} - - -LUA_API const char *lua_setlocal (lua_State *L, const lua_Debug *ar, int n) { - CallInfo *ci = L->base_ci + ar->i_ci; - const char *name = findlocal(L, ci, n); - lua_lock(L); - if (name) - setobjs2s(L, ci->base + (n - 1), L->top - 1); - L->top--; /* pop value */ - lua_unlock(L); - return name; -} - - -static void funcinfo (lua_Debug *ar, Closure *cl) { - if (cl->c.isC) { - ar->source = "=[C]"; - ar->linedefined = -1; - ar->lastlinedefined = -1; - ar->what = "C"; - } - else { - ar->source = getstr(cl->l.p->source); - ar->linedefined = cl->l.p->linedefined; - ar->lastlinedefined = cl->l.p->lastlinedefined; - ar->what = (ar->linedefined == 0) ? "main" : "Lua"; - } - luaO_chunkid(ar->short_src, ar->source, LUA_IDSIZE); -} - - -static void info_tailcall (lua_Debug *ar) { - ar->name = ar->namewhat = ""; - ar->what = "tail"; - ar->lastlinedefined = ar->linedefined = ar->currentline = -1; - ar->source = "=(tail call)"; - luaO_chunkid(ar->short_src, ar->source, LUA_IDSIZE); - ar->nups = 0; -} - - -static void collectvalidlines (lua_State *L, Closure *f) { - if (f == NULL || f->c.isC) { - setnilvalue(L->top); - } - else { - Table *t = luaH_new(L, 0, 0); - int *lineinfo = f->l.p->lineinfo; - int i; - for (i=0; il.p->sizelineinfo; i++) - setbvalue(luaH_setnum(L, t, lineinfo[i]), 1); - sethvalue(L, L->top, t); - } - incr_top(L); -} - - -static int auxgetinfo (lua_State *L, const char *what, lua_Debug *ar, - Closure *f, CallInfo *ci) { - int status = 1; - if (f == NULL) { - info_tailcall(ar); - return status; - } - for (; *what; what++) { - switch (*what) { - case 'S': { - funcinfo(ar, f); - break; - } - case 'l': { - ar->currentline = (ci) ? currentline(L, ci) : -1; - break; - } - case 'u': { - ar->nups = f->c.nupvalues; - break; - } - case 'n': { - ar->namewhat = (ci) ? getfuncname(L, ci, &ar->name) : NULL; - if (ar->namewhat == NULL) { - ar->namewhat = ""; /* not found */ - ar->name = NULL; - } - break; - } - case 'L': - case 'f': /* handled by lua_getinfo */ - break; - default: status = 0; /* invalid option */ - } - } - return status; -} - - -LUA_API int lua_getinfo (lua_State *L, const char *what, lua_Debug *ar) { - int status; - Closure *f = NULL; - CallInfo *ci = NULL; - lua_lock(L); - if (*what == '>') { - StkId func = L->top - 1; - luai_apicheck(L, ttisfunction(func)); - what++; /* skip the '>' */ - f = clvalue(func); - L->top--; /* pop function */ - } - else if (ar->i_ci != 0) { /* no tail call? */ - ci = L->base_ci + ar->i_ci; - lua_assert(ttisfunction(ci->func)); - f = clvalue(ci->func); - } - status = auxgetinfo(L, what, ar, f, ci); - if (strchr(what, 'f')) { - if (f == NULL) setnilvalue(L->top); - else setclvalue(L, L->top, f); - incr_top(L); - } - if (strchr(what, 'L')) - collectvalidlines(L, f); - lua_unlock(L); - return status; -} - - -/* -** {====================================================== -** Symbolic Execution and code checker -** ======================================================= -*/ - -#define check(x) if (!(x)) return 0; - -#define checkjump(pt,pc) check(0 <= pc && pc < pt->sizecode) - -#define checkreg(pt,reg) check((reg) < (pt)->maxstacksize) - - - -static int precheck (const Proto *pt) { - check(pt->maxstacksize <= MAXSTACK); - check(pt->numparams+(pt->is_vararg & VARARG_HASARG) <= pt->maxstacksize); - check(!(pt->is_vararg & VARARG_NEEDSARG) || - (pt->is_vararg & VARARG_HASARG)); - check(pt->sizeupvalues <= pt->nups); - check(pt->sizelineinfo == pt->sizecode || pt->sizelineinfo == 0); - check(pt->sizecode > 0 && GET_OPCODE(pt->code[pt->sizecode-1]) == OP_RETURN); - return 1; -} - - -#define checkopenop(pt,pc) luaG_checkopenop((pt)->code[(pc)+1]) - -int luaG_checkopenop (Instruction i) { - switch (GET_OPCODE(i)) { - case OP_CALL: - case OP_TAILCALL: - case OP_RETURN: - case OP_SETLIST: { - check(GETARG_B(i) == 0); - return 1; - } - default: return 0; /* invalid instruction after an open call */ - } -} - - -static int checkArgMode (const Proto *pt, int r, enum OpArgMask mode) { - switch (mode) { - case OpArgN: check(r == 0); break; - case OpArgU: break; - case OpArgR: checkreg(pt, r); break; - case OpArgK: - check(ISK(r) ? INDEXK(r) < pt->sizek : r < pt->maxstacksize); - break; - } - return 1; -} - - -static Instruction symbexec (const Proto *pt, int lastpc, int reg) { - int pc; - int last; /* stores position of last instruction that changed `reg' */ - last = pt->sizecode-1; /* points to final return (a `neutral' instruction) */ - check(precheck(pt)); - for (pc = 0; pc < lastpc; pc++) { - Instruction i = pt->code[pc]; - OpCode op = GET_OPCODE(i); - int a = GETARG_A(i); - int b = 0; - int c = 0; - check(op < NUM_OPCODES); - checkreg(pt, a); - switch (getOpMode(op)) { - case iABC: { - b = GETARG_B(i); - c = GETARG_C(i); - check(checkArgMode(pt, b, getBMode(op))); - check(checkArgMode(pt, c, getCMode(op))); - break; - } - case iABx: { - b = GETARG_Bx(i); - if (getBMode(op) == OpArgK) check(b < pt->sizek); - break; - } - case iAsBx: { - b = GETARG_sBx(i); - if (getBMode(op) == OpArgR) { - int dest = pc+1+b; - check(0 <= dest && dest < pt->sizecode); - if (dest > 0) { - int j; - /* check that it does not jump to a setlist count; this - is tricky, because the count from a previous setlist may - have the same value of an invalid setlist; so, we must - go all the way back to the first of them (if any) */ - for (j = 0; j < dest; j++) { - Instruction d = pt->code[dest-1-j]; - if (!(GET_OPCODE(d) == OP_SETLIST && GETARG_C(d) == 0)) break; - } - /* if 'j' is even, previous value is not a setlist (even if - it looks like one) */ - check((j&1) == 0); - } - } - break; - } - } - if (testAMode(op)) { - if (a == reg) last = pc; /* change register `a' */ - } - if (testTMode(op)) { - check(pc+2 < pt->sizecode); /* check skip */ - check(GET_OPCODE(pt->code[pc+1]) == OP_JMP); - } - switch (op) { - case OP_LOADBOOL: { - if (c == 1) { /* does it jump? */ - check(pc+2 < pt->sizecode); /* check its jump */ - check(GET_OPCODE(pt->code[pc+1]) != OP_SETLIST || - GETARG_C(pt->code[pc+1]) != 0); - } - break; - } - case OP_LOADNIL: { - if (a <= reg && reg <= b) - last = pc; /* set registers from `a' to `b' */ - break; - } - case OP_GETUPVAL: - case OP_SETUPVAL: { - check(b < pt->nups); - break; - } - case OP_GETGLOBAL: - case OP_SETGLOBAL: { - check(ttisstring(&pt->k[b])); - break; - } - case OP_SELF: { - checkreg(pt, a+1); - if (reg == a+1) last = pc; - break; - } - case OP_CONCAT: { - check(b < c); /* at least two operands */ - break; - } - case OP_TFORLOOP: { - check(c >= 1); /* at least one result (control variable) */ - checkreg(pt, a+2+c); /* space for results */ - if (reg >= a+2) last = pc; /* affect all regs above its base */ - break; - } - case OP_FORLOOP: - case OP_FORPREP: - checkreg(pt, a+3); - /* go through */ - case OP_JMP: { - int dest = pc+1+b; - /* not full check and jump is forward and do not skip `lastpc'? */ - if (reg != NO_REG && pc < dest && dest <= lastpc) - pc += b; /* do the jump */ - break; - } - case OP_CALL: - case OP_TAILCALL: { - if (b != 0) { - checkreg(pt, a+b-1); - } - c--; /* c = num. returns */ - if (c == LUA_MULTRET) { - check(checkopenop(pt, pc)); - } - else if (c != 0) - checkreg(pt, a+c-1); - if (reg >= a) last = pc; /* affect all registers above base */ - break; - } - case OP_RETURN: { - b--; /* b = num. returns */ - if (b > 0) checkreg(pt, a+b-1); - break; - } - case OP_SETLIST: { - if (b > 0) checkreg(pt, a + b); - if (c == 0) { - pc++; - check(pc < pt->sizecode - 1); - } - break; - } - case OP_CLOSURE: { - int nup, j; - check(b < pt->sizep); - nup = pt->p[b]->nups; - check(pc + nup < pt->sizecode); - for (j = 1; j <= nup; j++) { - OpCode op1 = GET_OPCODE(pt->code[pc + j]); - check(op1 == OP_GETUPVAL || op1 == OP_MOVE); - } - if (reg != NO_REG) /* tracing? */ - pc += nup; /* do not 'execute' these pseudo-instructions */ - break; - } - case OP_VARARG: { - check((pt->is_vararg & VARARG_ISVARARG) && - !(pt->is_vararg & VARARG_NEEDSARG)); - b--; - if (b == LUA_MULTRET) check(checkopenop(pt, pc)); - checkreg(pt, a+b-1); - break; - } - default: break; - } - } - return pt->code[last]; -} - -#undef check -#undef checkjump -#undef checkreg - -/* }====================================================== */ - - -int luaG_checkcode (const Proto *pt) { - return (symbexec(pt, pt->sizecode, NO_REG) != 0); -} - - -static const char *kname (Proto *p, int c) { - if (ISK(c) && ttisstring(&p->k[INDEXK(c)])) - return svalue(&p->k[INDEXK(c)]); - else - return "?"; -} - - -static const char *getobjname (lua_State *L, CallInfo *ci, int stackpos, - const char **name) { - if (isLua(ci)) { /* a Lua function? */ - Proto *p = ci_func(ci)->l.p; - int pc = currentpc(L, ci); - Instruction i; - *name = luaF_getlocalname(p, stackpos+1, pc); - if (*name) /* is a local? */ - return "local"; - i = symbexec(p, pc, stackpos); /* try symbolic execution */ - lua_assert(pc != -1); - switch (GET_OPCODE(i)) { - case OP_GETGLOBAL: { - int g = GETARG_Bx(i); /* global index */ - lua_assert(ttisstring(&p->k[g])); - *name = svalue(&p->k[g]); - return "global"; - } - case OP_MOVE: { - int a = GETARG_A(i); - int b = GETARG_B(i); /* move from `b' to `a' */ - if (b < a) - return getobjname(L, ci, b, name); /* get name for `b' */ - break; - } - case OP_GETTABLE: { - int k = GETARG_C(i); /* key index */ - *name = kname(p, k); - return "field"; - } - case OP_GETUPVAL: { - int u = GETARG_B(i); /* upvalue index */ - *name = p->upvalues ? getstr(p->upvalues[u]) : "?"; - return "upvalue"; - } - case OP_SELF: { - int k = GETARG_C(i); /* key index */ - *name = kname(p, k); - return "method"; - } - default: break; - } - } - return NULL; /* no useful name found */ -} - - -static const char *getfuncname (lua_State *L, CallInfo *ci, const char **name) { - Instruction i; - if ((isLua(ci) && ci->tailcalls > 0) || !isLua(ci - 1)) - return NULL; /* calling function is not Lua (or is unknown) */ - ci--; /* calling function */ - i = ci_func(ci)->l.p->code[currentpc(L, ci)]; - if (GET_OPCODE(i) == OP_CALL || GET_OPCODE(i) == OP_TAILCALL || - GET_OPCODE(i) == OP_TFORLOOP) - return getobjname(L, ci, GETARG_A(i), name); - else - return NULL; /* no useful name can be found */ -} - - -/* only ANSI way to check whether a pointer points to an array */ -static int isinstack (CallInfo *ci, const TValue *o) { - StkId p; - for (p = ci->base; p < ci->top; p++) - if (o == p) return 1; - return 0; -} - - -void luaG_typeerror (lua_State *L, const TValue *o, const char *op) { - const char *name = NULL; - const char *t = luaT_typenames[ttype(o)]; - const char *kind = (isinstack(L->ci, o)) ? - getobjname(L, L->ci, cast_int(o - L->base), &name) : - NULL; - if (kind) - luaG_runerror(L, "attempt to %s %s " LUA_QS " (a %s value)", - op, kind, name, t); - else - luaG_runerror(L, "attempt to %s a %s value", op, t); -} - - -void luaG_concaterror (lua_State *L, StkId p1, StkId p2) { - if (ttisstring(p1) || ttisnumber(p1)) p1 = p2; - lua_assert(!ttisstring(p1) && !ttisnumber(p1)); - luaG_typeerror(L, p1, "concatenate"); -} - - -void luaG_aritherror (lua_State *L, const TValue *p1, const TValue *p2) { - TValue temp; - if (luaV_tonumber(p1, &temp) == NULL) - p2 = p1; /* first operand is wrong */ - luaG_typeerror(L, p2, "perform arithmetic on"); -} - - -int luaG_ordererror (lua_State *L, const TValue *p1, const TValue *p2) { - const char *t1 = luaT_typenames[ttype(p1)]; - const char *t2 = luaT_typenames[ttype(p2)]; - if (t1[2] == t2[2]) - luaG_runerror(L, "attempt to compare two %s values", t1); - else - luaG_runerror(L, "attempt to compare %s with %s", t1, t2); - return 0; -} - - -static void addinfo (lua_State *L, const char *msg) { - CallInfo *ci = L->ci; - if (isLua(ci)) { /* is Lua code? */ - char buff[LUA_IDSIZE]; /* add file:line information */ - int line = currentline(L, ci); - luaO_chunkid(buff, getstr(getluaproto(ci)->source), LUA_IDSIZE); - luaO_pushfstring(L, "%s:%d: %s", buff, line, msg); - } -} - - -void luaG_errormsg (lua_State *L) { - if (L->errfunc != 0) { /* is there an error handling function? */ - StkId errfunc = restorestack(L, L->errfunc); - if (!ttisfunction(errfunc)) luaD_throw(L, LUA_ERRERR); - setobjs2s(L, L->top, L->top - 1); /* move argument */ - setobjs2s(L, L->top - 1, errfunc); /* push function */ - incr_top(L); - luaD_call(L, L->top - 2, 1); /* call it */ - } - luaD_throw(L, LUA_ERRRUN); -} - - -void luaG_runerror (lua_State *L, const char *fmt, ...) { - va_list argp; - va_start(argp, fmt); - addinfo(L, luaO_pushvfstring(L, fmt, argp)); - va_end(argp); - luaG_errormsg(L); -} - diff --git a/lib/lua-5.1/src/ldebug.h b/lib/lua-5.1/src/ldebug.h deleted file mode 100644 index ba28a97..0000000 --- a/lib/lua-5.1/src/ldebug.h +++ /dev/null @@ -1,33 +0,0 @@ -/* -** $Id: ldebug.h,v 2.3.1.1 2007/12/27 13:02:25 roberto Exp $ -** Auxiliary functions from Debug Interface module -** See Copyright Notice in lua.h -*/ - -#ifndef ldebug_h -#define ldebug_h - - -#include "lstate.h" - - -#define pcRel(pc, p) (cast(int, (pc) - (p)->code) - 1) - -#define getline(f,pc) (((f)->lineinfo) ? (f)->lineinfo[pc] : 0) - -#define resethookcount(L) (L->hookcount = L->basehookcount) - - -LUAI_FUNC void luaG_typeerror (lua_State *L, const TValue *o, - const char *opname); -LUAI_FUNC void luaG_concaterror (lua_State *L, StkId p1, StkId p2); -LUAI_FUNC void luaG_aritherror (lua_State *L, const TValue *p1, - const TValue *p2); -LUAI_FUNC int luaG_ordererror (lua_State *L, const TValue *p1, - const TValue *p2); -LUAI_FUNC void luaG_runerror (lua_State *L, const char *fmt, ...); -LUAI_FUNC void luaG_errormsg (lua_State *L); -LUAI_FUNC int luaG_checkcode (const Proto *pt); -LUAI_FUNC int luaG_checkopenop (Instruction i); - -#endif diff --git a/lib/lua-5.1/src/ldo.c b/lib/lua-5.1/src/ldo.c deleted file mode 100644 index 30333bf..0000000 --- a/lib/lua-5.1/src/ldo.c +++ /dev/null @@ -1,519 +0,0 @@ -/* -** $Id: ldo.c,v 2.38.1.4 2012/01/18 02:27:10 roberto Exp $ -** Stack and Call structure of Lua -** See Copyright Notice in lua.h -*/ - - -#include -#include -#include - -#define ldo_c -#define LUA_CORE - -#include "lua.h" - -#include "ldebug.h" -#include "ldo.h" -#include "lfunc.h" -#include "lgc.h" -#include "lmem.h" -#include "lobject.h" -#include "lopcodes.h" -#include "lparser.h" -#include "lstate.h" -#include "lstring.h" -#include "ltable.h" -#include "ltm.h" -#include "lundump.h" -#include "lvm.h" -#include "lzio.h" - - - - -/* -** {====================================================== -** Error-recovery functions -** ======================================================= -*/ - - -/* chain list of long jump buffers */ -struct lua_longjmp { - struct lua_longjmp *previous; - luai_jmpbuf b; - volatile int status; /* error code */ -}; - - -void luaD_seterrorobj (lua_State *L, int errcode, StkId oldtop) { - switch (errcode) { - case LUA_ERRMEM: { - setsvalue2s(L, oldtop, luaS_newliteral(L, MEMERRMSG)); - break; - } - case LUA_ERRERR: { - setsvalue2s(L, oldtop, luaS_newliteral(L, "error in error handling")); - break; - } - case LUA_ERRSYNTAX: - case LUA_ERRRUN: { - setobjs2s(L, oldtop, L->top - 1); /* error message on current top */ - break; - } - } - L->top = oldtop + 1; -} - - -static void restore_stack_limit (lua_State *L) { - lua_assert(L->stack_last - L->stack == L->stacksize - EXTRA_STACK - 1); - if (L->size_ci > LUAI_MAXCALLS) { /* there was an overflow? */ - int inuse = cast_int(L->ci - L->base_ci); - if (inuse + 1 < LUAI_MAXCALLS) /* can `undo' overflow? */ - luaD_reallocCI(L, LUAI_MAXCALLS); - } -} - - -static void resetstack (lua_State *L, int status) { - L->ci = L->base_ci; - L->base = L->ci->base; - luaF_close(L, L->base); /* close eventual pending closures */ - luaD_seterrorobj(L, status, L->base); - L->nCcalls = L->baseCcalls; - L->allowhook = 1; - restore_stack_limit(L); - L->errfunc = 0; - L->errorJmp = NULL; -} - - -void luaD_throw (lua_State *L, int errcode) { - if (L->errorJmp) { - L->errorJmp->status = errcode; - LUAI_THROW(L, L->errorJmp); - } - else { - L->status = cast_byte(errcode); - if (G(L)->panic) { - resetstack(L, errcode); - lua_unlock(L); - G(L)->panic(L); - } - exit(EXIT_FAILURE); - } -} - - -int luaD_rawrunprotected (lua_State *L, Pfunc f, void *ud) { - struct lua_longjmp lj; - lj.status = 0; - lj.previous = L->errorJmp; /* chain new error handler */ - L->errorJmp = &lj; - LUAI_TRY(L, &lj, - (*f)(L, ud); - ); - L->errorJmp = lj.previous; /* restore old error handler */ - return lj.status; -} - -/* }====================================================== */ - - -static void correctstack (lua_State *L, TValue *oldstack) { - CallInfo *ci; - GCObject *up; - L->top = (L->top - oldstack) + L->stack; - for (up = L->openupval; up != NULL; up = up->gch.next) - gco2uv(up)->v = (gco2uv(up)->v - oldstack) + L->stack; - for (ci = L->base_ci; ci <= L->ci; ci++) { - ci->top = (ci->top - oldstack) + L->stack; - ci->base = (ci->base - oldstack) + L->stack; - ci->func = (ci->func - oldstack) + L->stack; - } - L->base = (L->base - oldstack) + L->stack; -} - - -void luaD_reallocstack (lua_State *L, int newsize) { - TValue *oldstack = L->stack; - int realsize = newsize + 1 + EXTRA_STACK; - lua_assert(L->stack_last - L->stack == L->stacksize - EXTRA_STACK - 1); - luaM_reallocvector(L, L->stack, L->stacksize, realsize, TValue); - L->stacksize = realsize; - L->stack_last = L->stack+newsize; - correctstack(L, oldstack); -} - - -void luaD_reallocCI (lua_State *L, int newsize) { - CallInfo *oldci = L->base_ci; - luaM_reallocvector(L, L->base_ci, L->size_ci, newsize, CallInfo); - L->size_ci = newsize; - L->ci = (L->ci - oldci) + L->base_ci; - L->end_ci = L->base_ci + L->size_ci - 1; -} - - -void luaD_growstack (lua_State *L, int n) { - if (n <= L->stacksize) /* double size is enough? */ - luaD_reallocstack(L, 2*L->stacksize); - else - luaD_reallocstack(L, L->stacksize + n); -} - - -static CallInfo *growCI (lua_State *L) { - if (L->size_ci > LUAI_MAXCALLS) /* overflow while handling overflow? */ - luaD_throw(L, LUA_ERRERR); - else { - luaD_reallocCI(L, 2*L->size_ci); - if (L->size_ci > LUAI_MAXCALLS) - luaG_runerror(L, "stack overflow"); - } - return ++L->ci; -} - - -void luaD_callhook (lua_State *L, int event, int line) { - lua_Hook hook = L->hook; - if (hook && L->allowhook) { - ptrdiff_t top = savestack(L, L->top); - ptrdiff_t ci_top = savestack(L, L->ci->top); - lua_Debug ar; - ar.event = event; - ar.currentline = line; - if (event == LUA_HOOKTAILRET) - ar.i_ci = 0; /* tail call; no debug information about it */ - else - ar.i_ci = cast_int(L->ci - L->base_ci); - luaD_checkstack(L, LUA_MINSTACK); /* ensure minimum stack size */ - L->ci->top = L->top + LUA_MINSTACK; - lua_assert(L->ci->top <= L->stack_last); - L->allowhook = 0; /* cannot call hooks inside a hook */ - lua_unlock(L); - (*hook)(L, &ar); - lua_lock(L); - lua_assert(!L->allowhook); - L->allowhook = 1; - L->ci->top = restorestack(L, ci_top); - L->top = restorestack(L, top); - } -} - - -static StkId adjust_varargs (lua_State *L, Proto *p, int actual) { - int i; - int nfixargs = p->numparams; - Table *htab = NULL; - StkId base, fixed; - for (; actual < nfixargs; ++actual) - setnilvalue(L->top++); -#if defined(LUA_COMPAT_VARARG) - if (p->is_vararg & VARARG_NEEDSARG) { /* compat. with old-style vararg? */ - int nvar = actual - nfixargs; /* number of extra arguments */ - lua_assert(p->is_vararg & VARARG_HASARG); - luaC_checkGC(L); - luaD_checkstack(L, p->maxstacksize); - htab = luaH_new(L, nvar, 1); /* create `arg' table */ - for (i=0; itop - nvar + i); - /* store counter in field `n' */ - setnvalue(luaH_setstr(L, htab, luaS_newliteral(L, "n")), cast_num(nvar)); - } -#endif - /* move fixed parameters to final position */ - fixed = L->top - actual; /* first fixed argument */ - base = L->top; /* final position of first argument */ - for (i=0; itop++, fixed+i); - setnilvalue(fixed+i); - } - /* add `arg' parameter */ - if (htab) { - sethvalue(L, L->top++, htab); - lua_assert(iswhite(obj2gco(htab))); - } - return base; -} - - -static StkId tryfuncTM (lua_State *L, StkId func) { - const TValue *tm = luaT_gettmbyobj(L, func, TM_CALL); - StkId p; - ptrdiff_t funcr = savestack(L, func); - if (!ttisfunction(tm)) - luaG_typeerror(L, func, "call"); - /* Open a hole inside the stack at `func' */ - for (p = L->top; p > func; p--) setobjs2s(L, p, p-1); - incr_top(L); - func = restorestack(L, funcr); /* previous call may change stack */ - setobj2s(L, func, tm); /* tag method is the new function to be called */ - return func; -} - - - -#define inc_ci(L) \ - ((L->ci == L->end_ci) ? growCI(L) : \ - (condhardstacktests(luaD_reallocCI(L, L->size_ci)), ++L->ci)) - - -int luaD_precall (lua_State *L, StkId func, int nresults) { - LClosure *cl; - ptrdiff_t funcr; - if (!ttisfunction(func)) /* `func' is not a function? */ - func = tryfuncTM(L, func); /* check the `function' tag method */ - funcr = savestack(L, func); - cl = &clvalue(func)->l; - L->ci->savedpc = L->savedpc; - if (!cl->isC) { /* Lua function? prepare its call */ - CallInfo *ci; - StkId st, base; - Proto *p = cl->p; - luaD_checkstack(L, p->maxstacksize + p->numparams); - func = restorestack(L, funcr); - if (!p->is_vararg) { /* no varargs? */ - base = func + 1; - if (L->top > base + p->numparams) - L->top = base + p->numparams; - } - else { /* vararg function */ - int nargs = cast_int(L->top - func) - 1; - base = adjust_varargs(L, p, nargs); - func = restorestack(L, funcr); /* previous call may change the stack */ - } - ci = inc_ci(L); /* now `enter' new function */ - ci->func = func; - L->base = ci->base = base; - ci->top = L->base + p->maxstacksize; - lua_assert(ci->top <= L->stack_last); - L->savedpc = p->code; /* starting point */ - ci->tailcalls = 0; - ci->nresults = nresults; - for (st = L->top; st < ci->top; st++) - setnilvalue(st); - L->top = ci->top; - if (L->hookmask & LUA_MASKCALL) { - L->savedpc++; /* hooks assume 'pc' is already incremented */ - luaD_callhook(L, LUA_HOOKCALL, -1); - L->savedpc--; /* correct 'pc' */ - } - return PCRLUA; - } - else { /* if is a C function, call it */ - CallInfo *ci; - int n; - luaD_checkstack(L, LUA_MINSTACK); /* ensure minimum stack size */ - ci = inc_ci(L); /* now `enter' new function */ - ci->func = restorestack(L, funcr); - L->base = ci->base = ci->func + 1; - ci->top = L->top + LUA_MINSTACK; - lua_assert(ci->top <= L->stack_last); - ci->nresults = nresults; - if (L->hookmask & LUA_MASKCALL) - luaD_callhook(L, LUA_HOOKCALL, -1); - lua_unlock(L); - n = (*curr_func(L)->c.f)(L); /* do the actual call */ - lua_lock(L); - if (n < 0) /* yielding? */ - return PCRYIELD; - else { - luaD_poscall(L, L->top - n); - return PCRC; - } - } -} - - -static StkId callrethooks (lua_State *L, StkId firstResult) { - ptrdiff_t fr = savestack(L, firstResult); /* next call may change stack */ - luaD_callhook(L, LUA_HOOKRET, -1); - if (f_isLua(L->ci)) { /* Lua function? */ - while ((L->hookmask & LUA_MASKRET) && L->ci->tailcalls--) /* tail calls */ - luaD_callhook(L, LUA_HOOKTAILRET, -1); - } - return restorestack(L, fr); -} - - -int luaD_poscall (lua_State *L, StkId firstResult) { - StkId res; - int wanted, i; - CallInfo *ci; - if (L->hookmask & LUA_MASKRET) - firstResult = callrethooks(L, firstResult); - ci = L->ci--; - res = ci->func; /* res == final position of 1st result */ - wanted = ci->nresults; - L->base = (ci - 1)->base; /* restore base */ - L->savedpc = (ci - 1)->savedpc; /* restore savedpc */ - /* move results to correct place */ - for (i = wanted; i != 0 && firstResult < L->top; i--) - setobjs2s(L, res++, firstResult++); - while (i-- > 0) - setnilvalue(res++); - L->top = res; - return (wanted - LUA_MULTRET); /* 0 iff wanted == LUA_MULTRET */ -} - - -/* -** Call a function (C or Lua). The function to be called is at *func. -** The arguments are on the stack, right after the function. -** When returns, all the results are on the stack, starting at the original -** function position. -*/ -void luaD_call (lua_State *L, StkId func, int nResults) { - if (++L->nCcalls >= LUAI_MAXCCALLS) { - if (L->nCcalls == LUAI_MAXCCALLS) - luaG_runerror(L, "C stack overflow"); - else if (L->nCcalls >= (LUAI_MAXCCALLS + (LUAI_MAXCCALLS>>3))) - luaD_throw(L, LUA_ERRERR); /* error while handing stack error */ - } - if (luaD_precall(L, func, nResults) == PCRLUA) /* is a Lua function? */ - luaV_execute(L, 1); /* call it */ - L->nCcalls--; - luaC_checkGC(L); -} - - -static void resume (lua_State *L, void *ud) { - StkId firstArg = cast(StkId, ud); - CallInfo *ci = L->ci; - if (L->status == 0) { /* start coroutine? */ - lua_assert(ci == L->base_ci && firstArg > L->base); - if (luaD_precall(L, firstArg - 1, LUA_MULTRET) != PCRLUA) - return; - } - else { /* resuming from previous yield */ - lua_assert(L->status == LUA_YIELD); - L->status = 0; - if (!f_isLua(ci)) { /* `common' yield? */ - /* finish interrupted execution of `OP_CALL' */ - lua_assert(GET_OPCODE(*((ci-1)->savedpc - 1)) == OP_CALL || - GET_OPCODE(*((ci-1)->savedpc - 1)) == OP_TAILCALL); - if (luaD_poscall(L, firstArg)) /* complete it... */ - L->top = L->ci->top; /* and correct top if not multiple results */ - } - else /* yielded inside a hook: just continue its execution */ - L->base = L->ci->base; - } - luaV_execute(L, cast_int(L->ci - L->base_ci)); -} - - -static int resume_error (lua_State *L, const char *msg) { - L->top = L->ci->base; - setsvalue2s(L, L->top, luaS_new(L, msg)); - incr_top(L); - lua_unlock(L); - return LUA_ERRRUN; -} - - -LUA_API int lua_resume (lua_State *L, int nargs) { - int status; - lua_lock(L); - if (L->status != LUA_YIELD && (L->status != 0 || L->ci != L->base_ci)) - return resume_error(L, "cannot resume non-suspended coroutine"); - if (L->nCcalls >= LUAI_MAXCCALLS) - return resume_error(L, "C stack overflow"); - luai_userstateresume(L, nargs); - lua_assert(L->errfunc == 0); - L->baseCcalls = ++L->nCcalls; - status = luaD_rawrunprotected(L, resume, L->top - nargs); - if (status != 0) { /* error? */ - L->status = cast_byte(status); /* mark thread as `dead' */ - luaD_seterrorobj(L, status, L->top); - L->ci->top = L->top; - } - else { - lua_assert(L->nCcalls == L->baseCcalls); - status = L->status; - } - --L->nCcalls; - lua_unlock(L); - return status; -} - - -LUA_API int lua_yield (lua_State *L, int nresults) { - luai_userstateyield(L, nresults); - lua_lock(L); - if (L->nCcalls > L->baseCcalls) - luaG_runerror(L, "attempt to yield across metamethod/C-call boundary"); - L->base = L->top - nresults; /* protect stack slots below */ - L->status = LUA_YIELD; - lua_unlock(L); - return -1; -} - - -int luaD_pcall (lua_State *L, Pfunc func, void *u, - ptrdiff_t old_top, ptrdiff_t ef) { - int status; - unsigned short oldnCcalls = L->nCcalls; - ptrdiff_t old_ci = saveci(L, L->ci); - lu_byte old_allowhooks = L->allowhook; - ptrdiff_t old_errfunc = L->errfunc; - L->errfunc = ef; - status = luaD_rawrunprotected(L, func, u); - if (status != 0) { /* an error occurred? */ - StkId oldtop = restorestack(L, old_top); - luaF_close(L, oldtop); /* close eventual pending closures */ - luaD_seterrorobj(L, status, oldtop); - L->nCcalls = oldnCcalls; - L->ci = restoreci(L, old_ci); - L->base = L->ci->base; - L->savedpc = L->ci->savedpc; - L->allowhook = old_allowhooks; - restore_stack_limit(L); - } - L->errfunc = old_errfunc; - return status; -} - - - -/* -** Execute a protected parser. -*/ -struct SParser { /* data to `f_parser' */ - ZIO *z; - Mbuffer buff; /* buffer to be used by the scanner */ - const char *name; -}; - -static void f_parser (lua_State *L, void *ud) { - int i; - Proto *tf; - Closure *cl; - struct SParser *p = cast(struct SParser *, ud); - int c = luaZ_lookahead(p->z); - luaC_checkGC(L); - tf = ((c == LUA_SIGNATURE[0]) ? luaU_undump : luaY_parser)(L, p->z, - &p->buff, p->name); - cl = luaF_newLclosure(L, tf->nups, hvalue(gt(L))); - cl->l.p = tf; - for (i = 0; i < tf->nups; i++) /* initialize eventual upvalues */ - cl->l.upvals[i] = luaF_newupval(L); - setclvalue(L, L->top, cl); - incr_top(L); -} - - -int luaD_protectedparser (lua_State *L, ZIO *z, const char *name) { - struct SParser p; - int status; - p.z = z; p.name = name; - luaZ_initbuffer(L, &p.buff); - status = luaD_pcall(L, f_parser, &p, savestack(L, L->top), L->errfunc); - luaZ_freebuffer(L, &p.buff); - return status; -} - - diff --git a/lib/lua-5.1/src/ldo.h b/lib/lua-5.1/src/ldo.h deleted file mode 100644 index 98fddac..0000000 --- a/lib/lua-5.1/src/ldo.h +++ /dev/null @@ -1,57 +0,0 @@ -/* -** $Id: ldo.h,v 2.7.1.1 2007/12/27 13:02:25 roberto Exp $ -** Stack and Call structure of Lua -** See Copyright Notice in lua.h -*/ - -#ifndef ldo_h -#define ldo_h - - -#include "lobject.h" -#include "lstate.h" -#include "lzio.h" - - -#define luaD_checkstack(L,n) \ - if ((char *)L->stack_last - (char *)L->top <= (n)*(int)sizeof(TValue)) \ - luaD_growstack(L, n); \ - else condhardstacktests(luaD_reallocstack(L, L->stacksize - EXTRA_STACK - 1)); - - -#define incr_top(L) {luaD_checkstack(L,1); L->top++;} - -#define savestack(L,p) ((char *)(p) - (char *)L->stack) -#define restorestack(L,n) ((TValue *)((char *)L->stack + (n))) - -#define saveci(L,p) ((char *)(p) - (char *)L->base_ci) -#define restoreci(L,n) ((CallInfo *)((char *)L->base_ci + (n))) - - -/* results from luaD_precall */ -#define PCRLUA 0 /* initiated a call to a Lua function */ -#define PCRC 1 /* did a call to a C function */ -#define PCRYIELD 2 /* C funtion yielded */ - - -/* type of protected functions, to be ran by `runprotected' */ -typedef void (*Pfunc) (lua_State *L, void *ud); - -LUAI_FUNC int luaD_protectedparser (lua_State *L, ZIO *z, const char *name); -LUAI_FUNC void luaD_callhook (lua_State *L, int event, int line); -LUAI_FUNC int luaD_precall (lua_State *L, StkId func, int nresults); -LUAI_FUNC void luaD_call (lua_State *L, StkId func, int nResults); -LUAI_FUNC int luaD_pcall (lua_State *L, Pfunc func, void *u, - ptrdiff_t oldtop, ptrdiff_t ef); -LUAI_FUNC int luaD_poscall (lua_State *L, StkId firstResult); -LUAI_FUNC void luaD_reallocCI (lua_State *L, int newsize); -LUAI_FUNC void luaD_reallocstack (lua_State *L, int newsize); -LUAI_FUNC void luaD_growstack (lua_State *L, int n); - -LUAI_FUNC void luaD_throw (lua_State *L, int errcode); -LUAI_FUNC int luaD_rawrunprotected (lua_State *L, Pfunc f, void *ud); - -LUAI_FUNC void luaD_seterrorobj (lua_State *L, int errcode, StkId oldtop); - -#endif - diff --git a/lib/lua-5.1/src/ldump.c b/lib/lua-5.1/src/ldump.c deleted file mode 100644 index c9d3d48..0000000 --- a/lib/lua-5.1/src/ldump.c +++ /dev/null @@ -1,164 +0,0 @@ -/* -** $Id: ldump.c,v 2.8.1.1 2007/12/27 13:02:25 roberto Exp $ -** save precompiled Lua chunks -** See Copyright Notice in lua.h -*/ - -#include - -#define ldump_c -#define LUA_CORE - -#include "lua.h" - -#include "lobject.h" -#include "lstate.h" -#include "lundump.h" - -typedef struct { - lua_State* L; - lua_Writer writer; - void* data; - int strip; - int status; -} DumpState; - -#define DumpMem(b,n,size,D) DumpBlock(b,(n)*(size),D) -#define DumpVar(x,D) DumpMem(&x,1,sizeof(x),D) - -static void DumpBlock(const void* b, size_t size, DumpState* D) -{ - if (D->status==0) - { - lua_unlock(D->L); - D->status=(*D->writer)(D->L,b,size,D->data); - lua_lock(D->L); - } -} - -static void DumpChar(int y, DumpState* D) -{ - char x=(char)y; - DumpVar(x,D); -} - -static void DumpInt(int x, DumpState* D) -{ - DumpVar(x,D); -} - -static void DumpNumber(lua_Number x, DumpState* D) -{ - DumpVar(x,D); -} - -static void DumpVector(const void* b, int n, size_t size, DumpState* D) -{ - DumpInt(n,D); - DumpMem(b,n,size,D); -} - -static void DumpString(const TString* s, DumpState* D) -{ - if (s==NULL || getstr(s)==NULL) - { - size_t size=0; - DumpVar(size,D); - } - else - { - size_t size=s->tsv.len+1; /* include trailing '\0' */ - DumpVar(size,D); - DumpBlock(getstr(s),size,D); - } -} - -#define DumpCode(f,D) DumpVector(f->code,f->sizecode,sizeof(Instruction),D) - -static void DumpFunction(const Proto* f, const TString* p, DumpState* D); - -static void DumpConstants(const Proto* f, DumpState* D) -{ - int i,n=f->sizek; - DumpInt(n,D); - for (i=0; ik[i]; - DumpChar(ttype(o),D); - switch (ttype(o)) - { - case LUA_TNIL: - break; - case LUA_TBOOLEAN: - DumpChar(bvalue(o),D); - break; - case LUA_TNUMBER: - DumpNumber(nvalue(o),D); - break; - case LUA_TSTRING: - DumpString(rawtsvalue(o),D); - break; - default: - lua_assert(0); /* cannot happen */ - break; - } - } - n=f->sizep; - DumpInt(n,D); - for (i=0; ip[i],f->source,D); -} - -static void DumpDebug(const Proto* f, DumpState* D) -{ - int i,n; - n= (D->strip) ? 0 : f->sizelineinfo; - DumpVector(f->lineinfo,n,sizeof(int),D); - n= (D->strip) ? 0 : f->sizelocvars; - DumpInt(n,D); - for (i=0; ilocvars[i].varname,D); - DumpInt(f->locvars[i].startpc,D); - DumpInt(f->locvars[i].endpc,D); - } - n= (D->strip) ? 0 : f->sizeupvalues; - DumpInt(n,D); - for (i=0; iupvalues[i],D); -} - -static void DumpFunction(const Proto* f, const TString* p, DumpState* D) -{ - DumpString((f->source==p || D->strip) ? NULL : f->source,D); - DumpInt(f->linedefined,D); - DumpInt(f->lastlinedefined,D); - DumpChar(f->nups,D); - DumpChar(f->numparams,D); - DumpChar(f->is_vararg,D); - DumpChar(f->maxstacksize,D); - DumpCode(f,D); - DumpConstants(f,D); - DumpDebug(f,D); -} - -static void DumpHeader(DumpState* D) -{ - char h[LUAC_HEADERSIZE]; - luaU_header(h); - DumpBlock(h,LUAC_HEADERSIZE,D); -} - -/* -** dump Lua function as precompiled chunk -*/ -int luaU_dump (lua_State* L, const Proto* f, lua_Writer w, void* data, int strip) -{ - DumpState D; - D.L=L; - D.writer=w; - D.data=data; - D.strip=strip; - D.status=0; - DumpHeader(&D); - DumpFunction(f,NULL,&D); - return D.status; -} diff --git a/lib/lua-5.1/src/lfunc.c b/lib/lua-5.1/src/lfunc.c deleted file mode 100644 index 813e88f..0000000 --- a/lib/lua-5.1/src/lfunc.c +++ /dev/null @@ -1,174 +0,0 @@ -/* -** $Id: lfunc.c,v 2.12.1.2 2007/12/28 14:58:43 roberto Exp $ -** Auxiliary functions to manipulate prototypes and closures -** See Copyright Notice in lua.h -*/ - - -#include - -#define lfunc_c -#define LUA_CORE - -#include "lua.h" - -#include "lfunc.h" -#include "lgc.h" -#include "lmem.h" -#include "lobject.h" -#include "lstate.h" - - - -Closure *luaF_newCclosure (lua_State *L, int nelems, Table *e) { - Closure *c = cast(Closure *, luaM_malloc(L, sizeCclosure(nelems))); - luaC_link(L, obj2gco(c), LUA_TFUNCTION); - c->c.isC = 1; - c->c.env = e; - c->c.nupvalues = cast_byte(nelems); - return c; -} - - -Closure *luaF_newLclosure (lua_State *L, int nelems, Table *e) { - Closure *c = cast(Closure *, luaM_malloc(L, sizeLclosure(nelems))); - luaC_link(L, obj2gco(c), LUA_TFUNCTION); - c->l.isC = 0; - c->l.env = e; - c->l.nupvalues = cast_byte(nelems); - while (nelems--) c->l.upvals[nelems] = NULL; - return c; -} - - -UpVal *luaF_newupval (lua_State *L) { - UpVal *uv = luaM_new(L, UpVal); - luaC_link(L, obj2gco(uv), LUA_TUPVAL); - uv->v = &uv->u.value; - setnilvalue(uv->v); - return uv; -} - - -UpVal *luaF_findupval (lua_State *L, StkId level) { - global_State *g = G(L); - GCObject **pp = &L->openupval; - UpVal *p; - UpVal *uv; - while (*pp != NULL && (p = ngcotouv(*pp))->v >= level) { - lua_assert(p->v != &p->u.value); - if (p->v == level) { /* found a corresponding upvalue? */ - if (isdead(g, obj2gco(p))) /* is it dead? */ - changewhite(obj2gco(p)); /* ressurect it */ - return p; - } - pp = &p->next; - } - uv = luaM_new(L, UpVal); /* not found: create a new one */ - uv->tt = LUA_TUPVAL; - uv->marked = luaC_white(g); - uv->v = level; /* current value lives in the stack */ - uv->next = *pp; /* chain it in the proper position */ - *pp = obj2gco(uv); - uv->u.l.prev = &g->uvhead; /* double link it in `uvhead' list */ - uv->u.l.next = g->uvhead.u.l.next; - uv->u.l.next->u.l.prev = uv; - g->uvhead.u.l.next = uv; - lua_assert(uv->u.l.next->u.l.prev == uv && uv->u.l.prev->u.l.next == uv); - return uv; -} - - -static void unlinkupval (UpVal *uv) { - lua_assert(uv->u.l.next->u.l.prev == uv && uv->u.l.prev->u.l.next == uv); - uv->u.l.next->u.l.prev = uv->u.l.prev; /* remove from `uvhead' list */ - uv->u.l.prev->u.l.next = uv->u.l.next; -} - - -void luaF_freeupval (lua_State *L, UpVal *uv) { - if (uv->v != &uv->u.value) /* is it open? */ - unlinkupval(uv); /* remove from open list */ - luaM_free(L, uv); /* free upvalue */ -} - - -void luaF_close (lua_State *L, StkId level) { - UpVal *uv; - global_State *g = G(L); - while (L->openupval != NULL && (uv = ngcotouv(L->openupval))->v >= level) { - GCObject *o = obj2gco(uv); - lua_assert(!isblack(o) && uv->v != &uv->u.value); - L->openupval = uv->next; /* remove from `open' list */ - if (isdead(g, o)) - luaF_freeupval(L, uv); /* free upvalue */ - else { - unlinkupval(uv); - setobj(L, &uv->u.value, uv->v); - uv->v = &uv->u.value; /* now current value lives here */ - luaC_linkupval(L, uv); /* link upvalue into `gcroot' list */ - } - } -} - - -Proto *luaF_newproto (lua_State *L) { - Proto *f = luaM_new(L, Proto); - luaC_link(L, obj2gco(f), LUA_TPROTO); - f->k = NULL; - f->sizek = 0; - f->p = NULL; - f->sizep = 0; - f->code = NULL; - f->sizecode = 0; - f->sizelineinfo = 0; - f->sizeupvalues = 0; - f->nups = 0; - f->upvalues = NULL; - f->numparams = 0; - f->is_vararg = 0; - f->maxstacksize = 0; - f->lineinfo = NULL; - f->sizelocvars = 0; - f->locvars = NULL; - f->linedefined = 0; - f->lastlinedefined = 0; - f->source = NULL; - return f; -} - - -void luaF_freeproto (lua_State *L, Proto *f) { - luaM_freearray(L, f->code, f->sizecode, Instruction); - luaM_freearray(L, f->p, f->sizep, Proto *); - luaM_freearray(L, f->k, f->sizek, TValue); - luaM_freearray(L, f->lineinfo, f->sizelineinfo, int); - luaM_freearray(L, f->locvars, f->sizelocvars, struct LocVar); - luaM_freearray(L, f->upvalues, f->sizeupvalues, TString *); - luaM_free(L, f); -} - - -void luaF_freeclosure (lua_State *L, Closure *c) { - int size = (c->c.isC) ? sizeCclosure(c->c.nupvalues) : - sizeLclosure(c->l.nupvalues); - luaM_freemem(L, c, size); -} - - -/* -** Look for n-th local variable at line `line' in function `func'. -** Returns NULL if not found. -*/ -const char *luaF_getlocalname (const Proto *f, int local_number, int pc) { - int i; - for (i = 0; isizelocvars && f->locvars[i].startpc <= pc; i++) { - if (pc < f->locvars[i].endpc) { /* is variable active? */ - local_number--; - if (local_number == 0) - return getstr(f->locvars[i].varname); - } - } - return NULL; /* not found */ -} - diff --git a/lib/lua-5.1/src/lfunc.h b/lib/lua-5.1/src/lfunc.h deleted file mode 100644 index a68cf51..0000000 --- a/lib/lua-5.1/src/lfunc.h +++ /dev/null @@ -1,34 +0,0 @@ -/* -** $Id: lfunc.h,v 2.4.1.1 2007/12/27 13:02:25 roberto Exp $ -** Auxiliary functions to manipulate prototypes and closures -** See Copyright Notice in lua.h -*/ - -#ifndef lfunc_h -#define lfunc_h - - -#include "lobject.h" - - -#define sizeCclosure(n) (cast(int, sizeof(CClosure)) + \ - cast(int, sizeof(TValue)*((n)-1))) - -#define sizeLclosure(n) (cast(int, sizeof(LClosure)) + \ - cast(int, sizeof(TValue *)*((n)-1))) - - -LUAI_FUNC Proto *luaF_newproto (lua_State *L); -LUAI_FUNC Closure *luaF_newCclosure (lua_State *L, int nelems, Table *e); -LUAI_FUNC Closure *luaF_newLclosure (lua_State *L, int nelems, Table *e); -LUAI_FUNC UpVal *luaF_newupval (lua_State *L); -LUAI_FUNC UpVal *luaF_findupval (lua_State *L, StkId level); -LUAI_FUNC void luaF_close (lua_State *L, StkId level); -LUAI_FUNC void luaF_freeproto (lua_State *L, Proto *f); -LUAI_FUNC void luaF_freeclosure (lua_State *L, Closure *c); -LUAI_FUNC void luaF_freeupval (lua_State *L, UpVal *uv); -LUAI_FUNC const char *luaF_getlocalname (const Proto *func, int local_number, - int pc); - - -#endif diff --git a/lib/lua-5.1/src/lgc.c b/lib/lua-5.1/src/lgc.c deleted file mode 100644 index e909c79..0000000 --- a/lib/lua-5.1/src/lgc.c +++ /dev/null @@ -1,710 +0,0 @@ -/* -** $Id: lgc.c,v 2.38.1.2 2011/03/18 18:05:38 roberto Exp $ -** Garbage Collector -** See Copyright Notice in lua.h -*/ - -#include - -#define lgc_c -#define LUA_CORE - -#include "lua.h" - -#include "ldebug.h" -#include "ldo.h" -#include "lfunc.h" -#include "lgc.h" -#include "lmem.h" -#include "lobject.h" -#include "lstate.h" -#include "lstring.h" -#include "ltable.h" -#include "ltm.h" - - -#define GCSTEPSIZE 1024u -#define GCSWEEPMAX 40 -#define GCSWEEPCOST 10 -#define GCFINALIZECOST 100 - - -#define maskmarks cast_byte(~(bitmask(BLACKBIT)|WHITEBITS)) - -#define makewhite(g,x) \ - ((x)->gch.marked = cast_byte(((x)->gch.marked & maskmarks) | luaC_white(g))) - -#define white2gray(x) reset2bits((x)->gch.marked, WHITE0BIT, WHITE1BIT) -#define black2gray(x) resetbit((x)->gch.marked, BLACKBIT) - -#define stringmark(s) reset2bits((s)->tsv.marked, WHITE0BIT, WHITE1BIT) - - -#define isfinalized(u) testbit((u)->marked, FINALIZEDBIT) -#define markfinalized(u) l_setbit((u)->marked, FINALIZEDBIT) - - -#define KEYWEAK bitmask(KEYWEAKBIT) -#define VALUEWEAK bitmask(VALUEWEAKBIT) - - - -#define markvalue(g,o) { checkconsistency(o); \ - if (iscollectable(o) && iswhite(gcvalue(o))) reallymarkobject(g,gcvalue(o)); } - -#define markobject(g,t) { if (iswhite(obj2gco(t))) \ - reallymarkobject(g, obj2gco(t)); } - - -#define setthreshold(g) (g->GCthreshold = (g->estimate/100) * g->gcpause) - - -static void removeentry (Node *n) { - lua_assert(ttisnil(gval(n))); - if (iscollectable(gkey(n))) - setttype(gkey(n), LUA_TDEADKEY); /* dead key; remove it */ -} - - -static void reallymarkobject (global_State *g, GCObject *o) { - lua_assert(iswhite(o) && !isdead(g, o)); - white2gray(o); - switch (o->gch.tt) { - case LUA_TSTRING: { - return; - } - case LUA_TUSERDATA: { - Table *mt = gco2u(o)->metatable; - gray2black(o); /* udata are never gray */ - if (mt) markobject(g, mt); - markobject(g, gco2u(o)->env); - return; - } - case LUA_TUPVAL: { - UpVal *uv = gco2uv(o); - markvalue(g, uv->v); - if (uv->v == &uv->u.value) /* closed? */ - gray2black(o); /* open upvalues are never black */ - return; - } - case LUA_TFUNCTION: { - gco2cl(o)->c.gclist = g->gray; - g->gray = o; - break; - } - case LUA_TTABLE: { - gco2h(o)->gclist = g->gray; - g->gray = o; - break; - } - case LUA_TTHREAD: { - gco2th(o)->gclist = g->gray; - g->gray = o; - break; - } - case LUA_TPROTO: { - gco2p(o)->gclist = g->gray; - g->gray = o; - break; - } - default: lua_assert(0); - } -} - - -static void marktmu (global_State *g) { - GCObject *u = g->tmudata; - if (u) { - do { - u = u->gch.next; - makewhite(g, u); /* may be marked, if left from previous GC */ - reallymarkobject(g, u); - } while (u != g->tmudata); - } -} - - -/* move `dead' udata that need finalization to list `tmudata' */ -size_t luaC_separateudata (lua_State *L, int all) { - global_State *g = G(L); - size_t deadmem = 0; - GCObject **p = &g->mainthread->next; - GCObject *curr; - while ((curr = *p) != NULL) { - if (!(iswhite(curr) || all) || isfinalized(gco2u(curr))) - p = &curr->gch.next; /* don't bother with them */ - else if (fasttm(L, gco2u(curr)->metatable, TM_GC) == NULL) { - markfinalized(gco2u(curr)); /* don't need finalization */ - p = &curr->gch.next; - } - else { /* must call its gc method */ - deadmem += sizeudata(gco2u(curr)); - markfinalized(gco2u(curr)); - *p = curr->gch.next; - /* link `curr' at the end of `tmudata' list */ - if (g->tmudata == NULL) /* list is empty? */ - g->tmudata = curr->gch.next = curr; /* creates a circular list */ - else { - curr->gch.next = g->tmudata->gch.next; - g->tmudata->gch.next = curr; - g->tmudata = curr; - } - } - } - return deadmem; -} - - -static int traversetable (global_State *g, Table *h) { - int i; - int weakkey = 0; - int weakvalue = 0; - const TValue *mode; - if (h->metatable) - markobject(g, h->metatable); - mode = gfasttm(g, h->metatable, TM_MODE); - if (mode && ttisstring(mode)) { /* is there a weak mode? */ - weakkey = (strchr(svalue(mode), 'k') != NULL); - weakvalue = (strchr(svalue(mode), 'v') != NULL); - if (weakkey || weakvalue) { /* is really weak? */ - h->marked &= ~(KEYWEAK | VALUEWEAK); /* clear bits */ - h->marked |= cast_byte((weakkey << KEYWEAKBIT) | - (weakvalue << VALUEWEAKBIT)); - h->gclist = g->weak; /* must be cleared after GC, ... */ - g->weak = obj2gco(h); /* ... so put in the appropriate list */ - } - } - if (weakkey && weakvalue) return 1; - if (!weakvalue) { - i = h->sizearray; - while (i--) - markvalue(g, &h->array[i]); - } - i = sizenode(h); - while (i--) { - Node *n = gnode(h, i); - lua_assert(ttype(gkey(n)) != LUA_TDEADKEY || ttisnil(gval(n))); - if (ttisnil(gval(n))) - removeentry(n); /* remove empty entries */ - else { - lua_assert(!ttisnil(gkey(n))); - if (!weakkey) markvalue(g, gkey(n)); - if (!weakvalue) markvalue(g, gval(n)); - } - } - return weakkey || weakvalue; -} - - -/* -** All marks are conditional because a GC may happen while the -** prototype is still being created -*/ -static void traverseproto (global_State *g, Proto *f) { - int i; - if (f->source) stringmark(f->source); - for (i=0; isizek; i++) /* mark literals */ - markvalue(g, &f->k[i]); - for (i=0; isizeupvalues; i++) { /* mark upvalue names */ - if (f->upvalues[i]) - stringmark(f->upvalues[i]); - } - for (i=0; isizep; i++) { /* mark nested protos */ - if (f->p[i]) - markobject(g, f->p[i]); - } - for (i=0; isizelocvars; i++) { /* mark local-variable names */ - if (f->locvars[i].varname) - stringmark(f->locvars[i].varname); - } -} - - - -static void traverseclosure (global_State *g, Closure *cl) { - markobject(g, cl->c.env); - if (cl->c.isC) { - int i; - for (i=0; ic.nupvalues; i++) /* mark its upvalues */ - markvalue(g, &cl->c.upvalue[i]); - } - else { - int i; - lua_assert(cl->l.nupvalues == cl->l.p->nups); - markobject(g, cl->l.p); - for (i=0; il.nupvalues; i++) /* mark its upvalues */ - markobject(g, cl->l.upvals[i]); - } -} - - -static void checkstacksizes (lua_State *L, StkId max) { - int ci_used = cast_int(L->ci - L->base_ci); /* number of `ci' in use */ - int s_used = cast_int(max - L->stack); /* part of stack in use */ - if (L->size_ci > LUAI_MAXCALLS) /* handling overflow? */ - return; /* do not touch the stacks */ - if (4*ci_used < L->size_ci && 2*BASIC_CI_SIZE < L->size_ci) - luaD_reallocCI(L, L->size_ci/2); /* still big enough... */ - condhardstacktests(luaD_reallocCI(L, ci_used + 1)); - if (4*s_used < L->stacksize && - 2*(BASIC_STACK_SIZE+EXTRA_STACK) < L->stacksize) - luaD_reallocstack(L, L->stacksize/2); /* still big enough... */ - condhardstacktests(luaD_reallocstack(L, s_used)); -} - - -static void traversestack (global_State *g, lua_State *l) { - StkId o, lim; - CallInfo *ci; - markvalue(g, gt(l)); - lim = l->top; - for (ci = l->base_ci; ci <= l->ci; ci++) { - lua_assert(ci->top <= l->stack_last); - if (lim < ci->top) lim = ci->top; - } - for (o = l->stack; o < l->top; o++) - markvalue(g, o); - for (; o <= lim; o++) - setnilvalue(o); - checkstacksizes(l, lim); -} - - -/* -** traverse one gray object, turning it to black. -** Returns `quantity' traversed. -*/ -static l_mem propagatemark (global_State *g) { - GCObject *o = g->gray; - lua_assert(isgray(o)); - gray2black(o); - switch (o->gch.tt) { - case LUA_TTABLE: { - Table *h = gco2h(o); - g->gray = h->gclist; - if (traversetable(g, h)) /* table is weak? */ - black2gray(o); /* keep it gray */ - return sizeof(Table) + sizeof(TValue) * h->sizearray + - sizeof(Node) * sizenode(h); - } - case LUA_TFUNCTION: { - Closure *cl = gco2cl(o); - g->gray = cl->c.gclist; - traverseclosure(g, cl); - return (cl->c.isC) ? sizeCclosure(cl->c.nupvalues) : - sizeLclosure(cl->l.nupvalues); - } - case LUA_TTHREAD: { - lua_State *th = gco2th(o); - g->gray = th->gclist; - th->gclist = g->grayagain; - g->grayagain = o; - black2gray(o); - traversestack(g, th); - return sizeof(lua_State) + sizeof(TValue) * th->stacksize + - sizeof(CallInfo) * th->size_ci; - } - case LUA_TPROTO: { - Proto *p = gco2p(o); - g->gray = p->gclist; - traverseproto(g, p); - return sizeof(Proto) + sizeof(Instruction) * p->sizecode + - sizeof(Proto *) * p->sizep + - sizeof(TValue) * p->sizek + - sizeof(int) * p->sizelineinfo + - sizeof(LocVar) * p->sizelocvars + - sizeof(TString *) * p->sizeupvalues; - } - default: lua_assert(0); return 0; - } -} - - -static size_t propagateall (global_State *g) { - size_t m = 0; - while (g->gray) m += propagatemark(g); - return m; -} - - -/* -** The next function tells whether a key or value can be cleared from -** a weak table. Non-collectable objects are never removed from weak -** tables. Strings behave as `values', so are never removed too. for -** other objects: if really collected, cannot keep them; for userdata -** being finalized, keep them in keys, but not in values -*/ -static int iscleared (const TValue *o, int iskey) { - if (!iscollectable(o)) return 0; - if (ttisstring(o)) { - stringmark(rawtsvalue(o)); /* strings are `values', so are never weak */ - return 0; - } - return iswhite(gcvalue(o)) || - (ttisuserdata(o) && (!iskey && isfinalized(uvalue(o)))); -} - - -/* -** clear collected entries from weaktables -*/ -static void cleartable (GCObject *l) { - while (l) { - Table *h = gco2h(l); - int i = h->sizearray; - lua_assert(testbit(h->marked, VALUEWEAKBIT) || - testbit(h->marked, KEYWEAKBIT)); - if (testbit(h->marked, VALUEWEAKBIT)) { - while (i--) { - TValue *o = &h->array[i]; - if (iscleared(o, 0)) /* value was collected? */ - setnilvalue(o); /* remove value */ - } - } - i = sizenode(h); - while (i--) { - Node *n = gnode(h, i); - if (!ttisnil(gval(n)) && /* non-empty entry? */ - (iscleared(key2tval(n), 1) || iscleared(gval(n), 0))) { - setnilvalue(gval(n)); /* remove value ... */ - removeentry(n); /* remove entry from table */ - } - } - l = h->gclist; - } -} - - -static void freeobj (lua_State *L, GCObject *o) { - switch (o->gch.tt) { - case LUA_TPROTO: luaF_freeproto(L, gco2p(o)); break; - case LUA_TFUNCTION: luaF_freeclosure(L, gco2cl(o)); break; - case LUA_TUPVAL: luaF_freeupval(L, gco2uv(o)); break; - case LUA_TTABLE: luaH_free(L, gco2h(o)); break; - case LUA_TTHREAD: { - lua_assert(gco2th(o) != L && gco2th(o) != G(L)->mainthread); - luaE_freethread(L, gco2th(o)); - break; - } - case LUA_TSTRING: { - G(L)->strt.nuse--; - luaM_freemem(L, o, sizestring(gco2ts(o))); - break; - } - case LUA_TUSERDATA: { - luaM_freemem(L, o, sizeudata(gco2u(o))); - break; - } - default: lua_assert(0); - } -} - - - -#define sweepwholelist(L,p) sweeplist(L,p,MAX_LUMEM) - - -static GCObject **sweeplist (lua_State *L, GCObject **p, lu_mem count) { - GCObject *curr; - global_State *g = G(L); - int deadmask = otherwhite(g); - while ((curr = *p) != NULL && count-- > 0) { - if (curr->gch.tt == LUA_TTHREAD) /* sweep open upvalues of each thread */ - sweepwholelist(L, &gco2th(curr)->openupval); - if ((curr->gch.marked ^ WHITEBITS) & deadmask) { /* not dead? */ - lua_assert(!isdead(g, curr) || testbit(curr->gch.marked, FIXEDBIT)); - makewhite(g, curr); /* make it white (for next cycle) */ - p = &curr->gch.next; - } - else { /* must erase `curr' */ - lua_assert(isdead(g, curr) || deadmask == bitmask(SFIXEDBIT)); - *p = curr->gch.next; - if (curr == g->rootgc) /* is the first element of the list? */ - g->rootgc = curr->gch.next; /* adjust first */ - freeobj(L, curr); - } - } - return p; -} - - -static void checkSizes (lua_State *L) { - global_State *g = G(L); - /* check size of string hash */ - if (g->strt.nuse < cast(lu_int32, g->strt.size/4) && - g->strt.size > MINSTRTABSIZE*2) - luaS_resize(L, g->strt.size/2); /* table is too big */ - /* check size of buffer */ - if (luaZ_sizebuffer(&g->buff) > LUA_MINBUFFER*2) { /* buffer too big? */ - size_t newsize = luaZ_sizebuffer(&g->buff) / 2; - luaZ_resizebuffer(L, &g->buff, newsize); - } -} - - -static void GCTM (lua_State *L) { - global_State *g = G(L); - GCObject *o = g->tmudata->gch.next; /* get first element */ - Udata *udata = rawgco2u(o); - const TValue *tm; - /* remove udata from `tmudata' */ - if (o == g->tmudata) /* last element? */ - g->tmudata = NULL; - else - g->tmudata->gch.next = udata->uv.next; - udata->uv.next = g->mainthread->next; /* return it to `root' list */ - g->mainthread->next = o; - makewhite(g, o); - tm = fasttm(L, udata->uv.metatable, TM_GC); - if (tm != NULL) { - lu_byte oldah = L->allowhook; - lu_mem oldt = g->GCthreshold; - L->allowhook = 0; /* stop debug hooks during GC tag method */ - g->GCthreshold = 2*g->totalbytes; /* avoid GC steps */ - setobj2s(L, L->top, tm); - setuvalue(L, L->top+1, udata); - L->top += 2; - luaD_call(L, L->top - 2, 0); - L->allowhook = oldah; /* restore hooks */ - g->GCthreshold = oldt; /* restore threshold */ - } -} - - -/* -** Call all GC tag methods -*/ -void luaC_callGCTM (lua_State *L) { - while (G(L)->tmudata) - GCTM(L); -} - - -void luaC_freeall (lua_State *L) { - global_State *g = G(L); - int i; - g->currentwhite = WHITEBITS | bitmask(SFIXEDBIT); /* mask to collect all elements */ - sweepwholelist(L, &g->rootgc); - for (i = 0; i < g->strt.size; i++) /* free all string lists */ - sweepwholelist(L, &g->strt.hash[i]); -} - - -static void markmt (global_State *g) { - int i; - for (i=0; imt[i]) markobject(g, g->mt[i]); -} - - -/* mark root set */ -static void markroot (lua_State *L) { - global_State *g = G(L); - g->gray = NULL; - g->grayagain = NULL; - g->weak = NULL; - markobject(g, g->mainthread); - /* make global table be traversed before main stack */ - markvalue(g, gt(g->mainthread)); - markvalue(g, registry(L)); - markmt(g); - g->gcstate = GCSpropagate; -} - - -static void remarkupvals (global_State *g) { - UpVal *uv; - for (uv = g->uvhead.u.l.next; uv != &g->uvhead; uv = uv->u.l.next) { - lua_assert(uv->u.l.next->u.l.prev == uv && uv->u.l.prev->u.l.next == uv); - if (isgray(obj2gco(uv))) - markvalue(g, uv->v); - } -} - - -static void atomic (lua_State *L) { - global_State *g = G(L); - size_t udsize; /* total size of userdata to be finalized */ - /* remark occasional upvalues of (maybe) dead threads */ - remarkupvals(g); - /* traverse objects cautch by write barrier and by 'remarkupvals' */ - propagateall(g); - /* remark weak tables */ - g->gray = g->weak; - g->weak = NULL; - lua_assert(!iswhite(obj2gco(g->mainthread))); - markobject(g, L); /* mark running thread */ - markmt(g); /* mark basic metatables (again) */ - propagateall(g); - /* remark gray again */ - g->gray = g->grayagain; - g->grayagain = NULL; - propagateall(g); - udsize = luaC_separateudata(L, 0); /* separate userdata to be finalized */ - marktmu(g); /* mark `preserved' userdata */ - udsize += propagateall(g); /* remark, to propagate `preserveness' */ - cleartable(g->weak); /* remove collected objects from weak tables */ - /* flip current white */ - g->currentwhite = cast_byte(otherwhite(g)); - g->sweepstrgc = 0; - g->sweepgc = &g->rootgc; - g->gcstate = GCSsweepstring; - g->estimate = g->totalbytes - udsize; /* first estimate */ -} - - -static l_mem singlestep (lua_State *L) { - global_State *g = G(L); - /*lua_checkmemory(L);*/ - switch (g->gcstate) { - case GCSpause: { - markroot(L); /* start a new collection */ - return 0; - } - case GCSpropagate: { - if (g->gray) - return propagatemark(g); - else { /* no more `gray' objects */ - atomic(L); /* finish mark phase */ - return 0; - } - } - case GCSsweepstring: { - lu_mem old = g->totalbytes; - sweepwholelist(L, &g->strt.hash[g->sweepstrgc++]); - if (g->sweepstrgc >= g->strt.size) /* nothing more to sweep? */ - g->gcstate = GCSsweep; /* end sweep-string phase */ - lua_assert(old >= g->totalbytes); - g->estimate -= old - g->totalbytes; - return GCSWEEPCOST; - } - case GCSsweep: { - lu_mem old = g->totalbytes; - g->sweepgc = sweeplist(L, g->sweepgc, GCSWEEPMAX); - if (*g->sweepgc == NULL) { /* nothing more to sweep? */ - checkSizes(L); - g->gcstate = GCSfinalize; /* end sweep phase */ - } - lua_assert(old >= g->totalbytes); - g->estimate -= old - g->totalbytes; - return GCSWEEPMAX*GCSWEEPCOST; - } - case GCSfinalize: { - if (g->tmudata) { - GCTM(L); - if (g->estimate > GCFINALIZECOST) - g->estimate -= GCFINALIZECOST; - return GCFINALIZECOST; - } - else { - g->gcstate = GCSpause; /* end collection */ - g->gcdept = 0; - return 0; - } - } - default: lua_assert(0); return 0; - } -} - - -void luaC_step (lua_State *L) { - global_State *g = G(L); - l_mem lim = (GCSTEPSIZE/100) * g->gcstepmul; - if (lim == 0) - lim = (MAX_LUMEM-1)/2; /* no limit */ - g->gcdept += g->totalbytes - g->GCthreshold; - do { - lim -= singlestep(L); - if (g->gcstate == GCSpause) - break; - } while (lim > 0); - if (g->gcstate != GCSpause) { - if (g->gcdept < GCSTEPSIZE) - g->GCthreshold = g->totalbytes + GCSTEPSIZE; /* - lim/g->gcstepmul;*/ - else { - g->gcdept -= GCSTEPSIZE; - g->GCthreshold = g->totalbytes; - } - } - else { - setthreshold(g); - } -} - - -void luaC_fullgc (lua_State *L) { - global_State *g = G(L); - if (g->gcstate <= GCSpropagate) { - /* reset sweep marks to sweep all elements (returning them to white) */ - g->sweepstrgc = 0; - g->sweepgc = &g->rootgc; - /* reset other collector lists */ - g->gray = NULL; - g->grayagain = NULL; - g->weak = NULL; - g->gcstate = GCSsweepstring; - } - lua_assert(g->gcstate != GCSpause && g->gcstate != GCSpropagate); - /* finish any pending sweep phase */ - while (g->gcstate != GCSfinalize) { - lua_assert(g->gcstate == GCSsweepstring || g->gcstate == GCSsweep); - singlestep(L); - } - markroot(L); - while (g->gcstate != GCSpause) { - singlestep(L); - } - setthreshold(g); -} - - -void luaC_barrierf (lua_State *L, GCObject *o, GCObject *v) { - global_State *g = G(L); - lua_assert(isblack(o) && iswhite(v) && !isdead(g, v) && !isdead(g, o)); - lua_assert(g->gcstate != GCSfinalize && g->gcstate != GCSpause); - lua_assert(ttype(&o->gch) != LUA_TTABLE); - /* must keep invariant? */ - if (g->gcstate == GCSpropagate) - reallymarkobject(g, v); /* restore invariant */ - else /* don't mind */ - makewhite(g, o); /* mark as white just to avoid other barriers */ -} - - -void luaC_barrierback (lua_State *L, Table *t) { - global_State *g = G(L); - GCObject *o = obj2gco(t); - lua_assert(isblack(o) && !isdead(g, o)); - lua_assert(g->gcstate != GCSfinalize && g->gcstate != GCSpause); - black2gray(o); /* make table gray (again) */ - t->gclist = g->grayagain; - g->grayagain = o; -} - - -void luaC_link (lua_State *L, GCObject *o, lu_byte tt) { - global_State *g = G(L); - o->gch.next = g->rootgc; - g->rootgc = o; - o->gch.marked = luaC_white(g); - o->gch.tt = tt; -} - - -void luaC_linkupval (lua_State *L, UpVal *uv) { - global_State *g = G(L); - GCObject *o = obj2gco(uv); - o->gch.next = g->rootgc; /* link upvalue into `rootgc' list */ - g->rootgc = o; - if (isgray(o)) { - if (g->gcstate == GCSpropagate) { - gray2black(o); /* closed upvalues need barrier */ - luaC_barrier(L, uv, uv->v); - } - else { /* sweep phase: sweep it (turning it into white) */ - makewhite(g, o); - lua_assert(g->gcstate != GCSfinalize && g->gcstate != GCSpause); - } - } -} - diff --git a/lib/lua-5.1/src/lgc.h b/lib/lua-5.1/src/lgc.h deleted file mode 100644 index 5a8dc60..0000000 --- a/lib/lua-5.1/src/lgc.h +++ /dev/null @@ -1,110 +0,0 @@ -/* -** $Id: lgc.h,v 2.15.1.1 2007/12/27 13:02:25 roberto Exp $ -** Garbage Collector -** See Copyright Notice in lua.h -*/ - -#ifndef lgc_h -#define lgc_h - - -#include "lobject.h" - - -/* -** Possible states of the Garbage Collector -*/ -#define GCSpause 0 -#define GCSpropagate 1 -#define GCSsweepstring 2 -#define GCSsweep 3 -#define GCSfinalize 4 - - -/* -** some userful bit tricks -*/ -#define resetbits(x,m) ((x) &= cast(lu_byte, ~(m))) -#define setbits(x,m) ((x) |= (m)) -#define testbits(x,m) ((x) & (m)) -#define bitmask(b) (1<<(b)) -#define bit2mask(b1,b2) (bitmask(b1) | bitmask(b2)) -#define l_setbit(x,b) setbits(x, bitmask(b)) -#define resetbit(x,b) resetbits(x, bitmask(b)) -#define testbit(x,b) testbits(x, bitmask(b)) -#define set2bits(x,b1,b2) setbits(x, (bit2mask(b1, b2))) -#define reset2bits(x,b1,b2) resetbits(x, (bit2mask(b1, b2))) -#define test2bits(x,b1,b2) testbits(x, (bit2mask(b1, b2))) - - - -/* -** Layout for bit use in `marked' field: -** bit 0 - object is white (type 0) -** bit 1 - object is white (type 1) -** bit 2 - object is black -** bit 3 - for userdata: has been finalized -** bit 3 - for tables: has weak keys -** bit 4 - for tables: has weak values -** bit 5 - object is fixed (should not be collected) -** bit 6 - object is "super" fixed (only the main thread) -*/ - - -#define WHITE0BIT 0 -#define WHITE1BIT 1 -#define BLACKBIT 2 -#define FINALIZEDBIT 3 -#define KEYWEAKBIT 3 -#define VALUEWEAKBIT 4 -#define FIXEDBIT 5 -#define SFIXEDBIT 6 -#define WHITEBITS bit2mask(WHITE0BIT, WHITE1BIT) - - -#define iswhite(x) test2bits((x)->gch.marked, WHITE0BIT, WHITE1BIT) -#define isblack(x) testbit((x)->gch.marked, BLACKBIT) -#define isgray(x) (!isblack(x) && !iswhite(x)) - -#define otherwhite(g) (g->currentwhite ^ WHITEBITS) -#define isdead(g,v) ((v)->gch.marked & otherwhite(g) & WHITEBITS) - -#define changewhite(x) ((x)->gch.marked ^= WHITEBITS) -#define gray2black(x) l_setbit((x)->gch.marked, BLACKBIT) - -#define valiswhite(x) (iscollectable(x) && iswhite(gcvalue(x))) - -#define luaC_white(g) cast(lu_byte, (g)->currentwhite & WHITEBITS) - - -#define luaC_checkGC(L) { \ - condhardstacktests(luaD_reallocstack(L, L->stacksize - EXTRA_STACK - 1)); \ - if (G(L)->totalbytes >= G(L)->GCthreshold) \ - luaC_step(L); } - - -#define luaC_barrier(L,p,v) { if (valiswhite(v) && isblack(obj2gco(p))) \ - luaC_barrierf(L,obj2gco(p),gcvalue(v)); } - -#define luaC_barriert(L,t,v) { if (valiswhite(v) && isblack(obj2gco(t))) \ - luaC_barrierback(L,t); } - -#define luaC_objbarrier(L,p,o) \ - { if (iswhite(obj2gco(o)) && isblack(obj2gco(p))) \ - luaC_barrierf(L,obj2gco(p),obj2gco(o)); } - -#define luaC_objbarriert(L,t,o) \ - { if (iswhite(obj2gco(o)) && isblack(obj2gco(t))) luaC_barrierback(L,t); } - -LUAI_FUNC size_t luaC_separateudata (lua_State *L, int all); -LUAI_FUNC void luaC_callGCTM (lua_State *L); -LUAI_FUNC void luaC_freeall (lua_State *L); -LUAI_FUNC void luaC_step (lua_State *L); -LUAI_FUNC void luaC_fullgc (lua_State *L); -LUAI_FUNC void luaC_link (lua_State *L, GCObject *o, lu_byte tt); -LUAI_FUNC void luaC_linkupval (lua_State *L, UpVal *uv); -LUAI_FUNC void luaC_barrierf (lua_State *L, GCObject *o, GCObject *v); -LUAI_FUNC void luaC_barrierback (lua_State *L, Table *t); - - -#endif diff --git a/lib/lua-5.1/src/linit.c b/lib/lua-5.1/src/linit.c deleted file mode 100644 index c1f90df..0000000 --- a/lib/lua-5.1/src/linit.c +++ /dev/null @@ -1,38 +0,0 @@ -/* -** $Id: linit.c,v 1.14.1.1 2007/12/27 13:02:25 roberto Exp $ -** Initialization of libraries for lua.c -** See Copyright Notice in lua.h -*/ - - -#define linit_c -#define LUA_LIB - -#include "lua.h" - -#include "lualib.h" -#include "lauxlib.h" - - -static const luaL_Reg lualibs[] = { - {"", luaopen_base}, - {LUA_LOADLIBNAME, luaopen_package}, - {LUA_TABLIBNAME, luaopen_table}, - {LUA_IOLIBNAME, luaopen_io}, - {LUA_OSLIBNAME, luaopen_os}, - {LUA_STRLIBNAME, luaopen_string}, - {LUA_MATHLIBNAME, luaopen_math}, - {LUA_DBLIBNAME, luaopen_debug}, - {NULL, NULL} -}; - - -LUALIB_API void luaL_openlibs (lua_State *L) { - const luaL_Reg *lib = lualibs; - for (; lib->func; lib++) { - lua_pushcfunction(L, lib->func); - lua_pushstring(L, lib->name); - lua_call(L, 1, 0); - } -} - diff --git a/lib/lua-5.1/src/liolib.c b/lib/lua-5.1/src/liolib.c deleted file mode 100644 index 649f9a5..0000000 --- a/lib/lua-5.1/src/liolib.c +++ /dev/null @@ -1,556 +0,0 @@ -/* -** $Id: liolib.c,v 2.73.1.4 2010/05/14 15:33:51 roberto Exp $ -** Standard I/O (and system) library -** See Copyright Notice in lua.h -*/ - - -#include -#include -#include -#include - -#define liolib_c -#define LUA_LIB - -#include "lua.h" - -#include "lauxlib.h" -#include "lualib.h" - - - -#define IO_INPUT 1 -#define IO_OUTPUT 2 - - -static const char *const fnames[] = {"input", "output"}; - - -static int pushresult (lua_State *L, int i, const char *filename) { - int en = errno; /* calls to Lua API may change this value */ - if (i) { - lua_pushboolean(L, 1); - return 1; - } - else { - lua_pushnil(L); - if (filename) - lua_pushfstring(L, "%s: %s", filename, strerror(en)); - else - lua_pushfstring(L, "%s", strerror(en)); - lua_pushinteger(L, en); - return 3; - } -} - - -static void fileerror (lua_State *L, int arg, const char *filename) { - lua_pushfstring(L, "%s: %s", filename, strerror(errno)); - luaL_argerror(L, arg, lua_tostring(L, -1)); -} - - -#define tofilep(L) ((FILE **)luaL_checkudata(L, 1, LUA_FILEHANDLE)) - - -static int io_type (lua_State *L) { - void *ud; - luaL_checkany(L, 1); - ud = lua_touserdata(L, 1); - lua_getfield(L, LUA_REGISTRYINDEX, LUA_FILEHANDLE); - if (ud == NULL || !lua_getmetatable(L, 1) || !lua_rawequal(L, -2, -1)) - lua_pushnil(L); /* not a file */ - else if (*((FILE **)ud) == NULL) - lua_pushliteral(L, "closed file"); - else - lua_pushliteral(L, "file"); - return 1; -} - - -static FILE *tofile (lua_State *L) { - FILE **f = tofilep(L); - if (*f == NULL) - luaL_error(L, "attempt to use a closed file"); - return *f; -} - - - -/* -** When creating file handles, always creates a `closed' file handle -** before opening the actual file; so, if there is a memory error, the -** file is not left opened. -*/ -static FILE **newfile (lua_State *L) { - FILE **pf = (FILE **)lua_newuserdata(L, sizeof(FILE *)); - *pf = NULL; /* file handle is currently `closed' */ - luaL_getmetatable(L, LUA_FILEHANDLE); - lua_setmetatable(L, -2); - return pf; -} - - -/* -** function to (not) close the standard files stdin, stdout, and stderr -*/ -static int io_noclose (lua_State *L) { - lua_pushnil(L); - lua_pushliteral(L, "cannot close standard file"); - return 2; -} - - -/* -** function to close 'popen' files -*/ -static int io_pclose (lua_State *L) { - FILE **p = tofilep(L); - int ok = lua_pclose(L, *p); - *p = NULL; - return pushresult(L, ok, NULL); -} - - -/* -** function to close regular files -*/ -static int io_fclose (lua_State *L) { - FILE **p = tofilep(L); - int ok = (fclose(*p) == 0); - *p = NULL; - return pushresult(L, ok, NULL); -} - - -static int aux_close (lua_State *L) { - lua_getfenv(L, 1); - lua_getfield(L, -1, "__close"); - return (lua_tocfunction(L, -1))(L); -} - - -static int io_close (lua_State *L) { - if (lua_isnone(L, 1)) - lua_rawgeti(L, LUA_ENVIRONINDEX, IO_OUTPUT); - tofile(L); /* make sure argument is a file */ - return aux_close(L); -} - - -static int io_gc (lua_State *L) { - FILE *f = *tofilep(L); - /* ignore closed files */ - if (f != NULL) - aux_close(L); - return 0; -} - - -static int io_tostring (lua_State *L) { - FILE *f = *tofilep(L); - if (f == NULL) - lua_pushliteral(L, "file (closed)"); - else - lua_pushfstring(L, "file (%p)", f); - return 1; -} - - -static int io_open (lua_State *L) { - const char *filename = luaL_checkstring(L, 1); - const char *mode = luaL_optstring(L, 2, "r"); - FILE **pf = newfile(L); - *pf = fopen(filename, mode); - return (*pf == NULL) ? pushresult(L, 0, filename) : 1; -} - - -/* -** this function has a separated environment, which defines the -** correct __close for 'popen' files -*/ -static int io_popen (lua_State *L) { - const char *filename = luaL_checkstring(L, 1); - const char *mode = luaL_optstring(L, 2, "r"); - FILE **pf = newfile(L); - *pf = lua_popen(L, filename, mode); - return (*pf == NULL) ? pushresult(L, 0, filename) : 1; -} - - -static int io_tmpfile (lua_State *L) { - FILE **pf = newfile(L); - *pf = tmpfile(); - return (*pf == NULL) ? pushresult(L, 0, NULL) : 1; -} - - -static FILE *getiofile (lua_State *L, int findex) { - FILE *f; - lua_rawgeti(L, LUA_ENVIRONINDEX, findex); - f = *(FILE **)lua_touserdata(L, -1); - if (f == NULL) - luaL_error(L, "standard %s file is closed", fnames[findex - 1]); - return f; -} - - -static int g_iofile (lua_State *L, int f, const char *mode) { - if (!lua_isnoneornil(L, 1)) { - const char *filename = lua_tostring(L, 1); - if (filename) { - FILE **pf = newfile(L); - *pf = fopen(filename, mode); - if (*pf == NULL) - fileerror(L, 1, filename); - } - else { - tofile(L); /* check that it's a valid file handle */ - lua_pushvalue(L, 1); - } - lua_rawseti(L, LUA_ENVIRONINDEX, f); - } - /* return current value */ - lua_rawgeti(L, LUA_ENVIRONINDEX, f); - return 1; -} - - -static int io_input (lua_State *L) { - return g_iofile(L, IO_INPUT, "r"); -} - - -static int io_output (lua_State *L) { - return g_iofile(L, IO_OUTPUT, "w"); -} - - -static int io_readline (lua_State *L); - - -static void aux_lines (lua_State *L, int idx, int toclose) { - lua_pushvalue(L, idx); - lua_pushboolean(L, toclose); /* close/not close file when finished */ - lua_pushcclosure(L, io_readline, 2); -} - - -static int f_lines (lua_State *L) { - tofile(L); /* check that it's a valid file handle */ - aux_lines(L, 1, 0); - return 1; -} - - -static int io_lines (lua_State *L) { - if (lua_isnoneornil(L, 1)) { /* no arguments? */ - /* will iterate over default input */ - lua_rawgeti(L, LUA_ENVIRONINDEX, IO_INPUT); - return f_lines(L); - } - else { - const char *filename = luaL_checkstring(L, 1); - FILE **pf = newfile(L); - *pf = fopen(filename, "r"); - if (*pf == NULL) - fileerror(L, 1, filename); - aux_lines(L, lua_gettop(L), 1); - return 1; - } -} - - -/* -** {====================================================== -** READ -** ======================================================= -*/ - - -static int read_number (lua_State *L, FILE *f) { - lua_Number d; - if (fscanf(f, LUA_NUMBER_SCAN, &d) == 1) { - lua_pushnumber(L, d); - return 1; - } - else { - lua_pushnil(L); /* "result" to be removed */ - return 0; /* read fails */ - } -} - - -static int test_eof (lua_State *L, FILE *f) { - int c = getc(f); - ungetc(c, f); - lua_pushlstring(L, NULL, 0); - return (c != EOF); -} - - -static int read_line (lua_State *L, FILE *f) { - luaL_Buffer b; - luaL_buffinit(L, &b); - for (;;) { - size_t l; - char *p = luaL_prepbuffer(&b); - if (fgets(p, LUAL_BUFFERSIZE, f) == NULL) { /* eof? */ - luaL_pushresult(&b); /* close buffer */ - return (lua_objlen(L, -1) > 0); /* check whether read something */ - } - l = strlen(p); - if (l == 0 || p[l-1] != '\n') - luaL_addsize(&b, l); - else { - luaL_addsize(&b, l - 1); /* do not include `eol' */ - luaL_pushresult(&b); /* close buffer */ - return 1; /* read at least an `eol' */ - } - } -} - - -static int read_chars (lua_State *L, FILE *f, size_t n) { - size_t rlen; /* how much to read */ - size_t nr; /* number of chars actually read */ - luaL_Buffer b; - luaL_buffinit(L, &b); - rlen = LUAL_BUFFERSIZE; /* try to read that much each time */ - do { - char *p = luaL_prepbuffer(&b); - if (rlen > n) rlen = n; /* cannot read more than asked */ - nr = fread(p, sizeof(char), rlen, f); - luaL_addsize(&b, nr); - n -= nr; /* still have to read `n' chars */ - } while (n > 0 && nr == rlen); /* until end of count or eof */ - luaL_pushresult(&b); /* close buffer */ - return (n == 0 || lua_objlen(L, -1) > 0); -} - - -static int g_read (lua_State *L, FILE *f, int first) { - int nargs = lua_gettop(L) - 1; - int success; - int n; - clearerr(f); - if (nargs == 0) { /* no arguments? */ - success = read_line(L, f); - n = first+1; /* to return 1 result */ - } - else { /* ensure stack space for all results and for auxlib's buffer */ - luaL_checkstack(L, nargs+LUA_MINSTACK, "too many arguments"); - success = 1; - for (n = first; nargs-- && success; n++) { - if (lua_type(L, n) == LUA_TNUMBER) { - size_t l = (size_t)lua_tointeger(L, n); - success = (l == 0) ? test_eof(L, f) : read_chars(L, f, l); - } - else { - const char *p = lua_tostring(L, n); - luaL_argcheck(L, p && p[0] == '*', n, "invalid option"); - switch (p[1]) { - case 'n': /* number */ - success = read_number(L, f); - break; - case 'l': /* line */ - success = read_line(L, f); - break; - case 'a': /* file */ - read_chars(L, f, ~((size_t)0)); /* read MAX_SIZE_T chars */ - success = 1; /* always success */ - break; - default: - return luaL_argerror(L, n, "invalid format"); - } - } - } - } - if (ferror(f)) - return pushresult(L, 0, NULL); - if (!success) { - lua_pop(L, 1); /* remove last result */ - lua_pushnil(L); /* push nil instead */ - } - return n - first; -} - - -static int io_read (lua_State *L) { - return g_read(L, getiofile(L, IO_INPUT), 1); -} - - -static int f_read (lua_State *L) { - return g_read(L, tofile(L), 2); -} - - -static int io_readline (lua_State *L) { - FILE *f = *(FILE **)lua_touserdata(L, lua_upvalueindex(1)); - int sucess; - if (f == NULL) /* file is already closed? */ - luaL_error(L, "file is already closed"); - sucess = read_line(L, f); - if (ferror(f)) - return luaL_error(L, "%s", strerror(errno)); - if (sucess) return 1; - else { /* EOF */ - if (lua_toboolean(L, lua_upvalueindex(2))) { /* generator created file? */ - lua_settop(L, 0); - lua_pushvalue(L, lua_upvalueindex(1)); - aux_close(L); /* close it */ - } - return 0; - } -} - -/* }====================================================== */ - - -static int g_write (lua_State *L, FILE *f, int arg) { - int nargs = lua_gettop(L) - 1; - int status = 1; - for (; nargs--; arg++) { - if (lua_type(L, arg) == LUA_TNUMBER) { - /* optimization: could be done exactly as for strings */ - status = status && - fprintf(f, LUA_NUMBER_FMT, lua_tonumber(L, arg)) > 0; - } - else { - size_t l; - const char *s = luaL_checklstring(L, arg, &l); - status = status && (fwrite(s, sizeof(char), l, f) == l); - } - } - return pushresult(L, status, NULL); -} - - -static int io_write (lua_State *L) { - return g_write(L, getiofile(L, IO_OUTPUT), 1); -} - - -static int f_write (lua_State *L) { - return g_write(L, tofile(L), 2); -} - - -static int f_seek (lua_State *L) { - static const int mode[] = {SEEK_SET, SEEK_CUR, SEEK_END}; - static const char *const modenames[] = {"set", "cur", "end", NULL}; - FILE *f = tofile(L); - int op = luaL_checkoption(L, 2, "cur", modenames); - long offset = luaL_optlong(L, 3, 0); - op = fseek(f, offset, mode[op]); - if (op) - return pushresult(L, 0, NULL); /* error */ - else { - lua_pushinteger(L, ftell(f)); - return 1; - } -} - - -static int f_setvbuf (lua_State *L) { - static const int mode[] = {_IONBF, _IOFBF, _IOLBF}; - static const char *const modenames[] = {"no", "full", "line", NULL}; - FILE *f = tofile(L); - int op = luaL_checkoption(L, 2, NULL, modenames); - lua_Integer sz = luaL_optinteger(L, 3, LUAL_BUFFERSIZE); - int res = setvbuf(f, NULL, mode[op], sz); - return pushresult(L, res == 0, NULL); -} - - - -static int io_flush (lua_State *L) { - return pushresult(L, fflush(getiofile(L, IO_OUTPUT)) == 0, NULL); -} - - -static int f_flush (lua_State *L) { - return pushresult(L, fflush(tofile(L)) == 0, NULL); -} - - -static const luaL_Reg iolib[] = { - {"close", io_close}, - {"flush", io_flush}, - {"input", io_input}, - {"lines", io_lines}, - {"open", io_open}, - {"output", io_output}, - {"popen", io_popen}, - {"read", io_read}, - {"tmpfile", io_tmpfile}, - {"type", io_type}, - {"write", io_write}, - {NULL, NULL} -}; - - -static const luaL_Reg flib[] = { - {"close", io_close}, - {"flush", f_flush}, - {"lines", f_lines}, - {"read", f_read}, - {"seek", f_seek}, - {"setvbuf", f_setvbuf}, - {"write", f_write}, - {"__gc", io_gc}, - {"__tostring", io_tostring}, - {NULL, NULL} -}; - - -static void createmeta (lua_State *L) { - luaL_newmetatable(L, LUA_FILEHANDLE); /* create metatable for file handles */ - lua_pushvalue(L, -1); /* push metatable */ - lua_setfield(L, -2, "__index"); /* metatable.__index = metatable */ - luaL_register(L, NULL, flib); /* file methods */ -} - - -static void createstdfile (lua_State *L, FILE *f, int k, const char *fname) { - *newfile(L) = f; - if (k > 0) { - lua_pushvalue(L, -1); - lua_rawseti(L, LUA_ENVIRONINDEX, k); - } - lua_pushvalue(L, -2); /* copy environment */ - lua_setfenv(L, -2); /* set it */ - lua_setfield(L, -3, fname); -} - - -static void newfenv (lua_State *L, lua_CFunction cls) { - lua_createtable(L, 0, 1); - lua_pushcfunction(L, cls); - lua_setfield(L, -2, "__close"); -} - - -LUALIB_API int luaopen_io (lua_State *L) { - createmeta(L); - /* create (private) environment (with fields IO_INPUT, IO_OUTPUT, __close) */ - newfenv(L, io_fclose); - lua_replace(L, LUA_ENVIRONINDEX); - /* open library */ - luaL_register(L, LUA_IOLIBNAME, iolib); - /* create (and set) default files */ - newfenv(L, io_noclose); /* close function for default files */ - createstdfile(L, stdin, IO_INPUT, "stdin"); - createstdfile(L, stdout, IO_OUTPUT, "stdout"); - createstdfile(L, stderr, 0, "stderr"); - lua_pop(L, 1); /* pop environment for default files */ - lua_getfield(L, -1, "popen"); - newfenv(L, io_pclose); /* create environment for 'popen' */ - lua_setfenv(L, -2); /* set fenv for 'popen' */ - lua_pop(L, 1); /* pop 'popen' */ - return 1; -} - diff --git a/lib/lua-5.1/src/llex.c b/lib/lua-5.1/src/llex.c deleted file mode 100644 index 88c6790..0000000 --- a/lib/lua-5.1/src/llex.c +++ /dev/null @@ -1,463 +0,0 @@ -/* -** $Id: llex.c,v 2.20.1.2 2009/11/23 14:58:22 roberto Exp $ -** Lexical Analyzer -** See Copyright Notice in lua.h -*/ - - -#include -#include -#include - -#define llex_c -#define LUA_CORE - -#include "lua.h" - -#include "ldo.h" -#include "llex.h" -#include "lobject.h" -#include "lparser.h" -#include "lstate.h" -#include "lstring.h" -#include "ltable.h" -#include "lzio.h" - - - -#define next(ls) (ls->current = zgetc(ls->z)) - - - - -#define currIsNewline(ls) (ls->current == '\n' || ls->current == '\r') - - -/* ORDER RESERVED */ -const char *const luaX_tokens [] = { - "and", "break", "do", "else", "elseif", - "end", "false", "for", "function", "if", - "in", "local", "nil", "not", "or", "repeat", - "return", "then", "true", "until", "while", - "..", "...", "==", ">=", "<=", "~=", - "", "", "", "", - NULL -}; - - -#define save_and_next(ls) (save(ls, ls->current), next(ls)) - - -static void save (LexState *ls, int c) { - Mbuffer *b = ls->buff; - if (b->n + 1 > b->buffsize) { - size_t newsize; - if (b->buffsize >= MAX_SIZET/2) - luaX_lexerror(ls, "lexical element too long", 0); - newsize = b->buffsize * 2; - luaZ_resizebuffer(ls->L, b, newsize); - } - b->buffer[b->n++] = cast(char, c); -} - - -void luaX_init (lua_State *L) { - int i; - for (i=0; itsv.reserved = cast_byte(i+1); /* reserved word */ - } -} - - -#define MAXSRC 80 - - -const char *luaX_token2str (LexState *ls, int token) { - if (token < FIRST_RESERVED) { - lua_assert(token == cast(unsigned char, token)); - return (iscntrl(token)) ? luaO_pushfstring(ls->L, "char(%d)", token) : - luaO_pushfstring(ls->L, "%c", token); - } - else - return luaX_tokens[token-FIRST_RESERVED]; -} - - -static const char *txtToken (LexState *ls, int token) { - switch (token) { - case TK_NAME: - case TK_STRING: - case TK_NUMBER: - save(ls, '\0'); - return luaZ_buffer(ls->buff); - default: - return luaX_token2str(ls, token); - } -} - - -void luaX_lexerror (LexState *ls, const char *msg, int token) { - char buff[MAXSRC]; - luaO_chunkid(buff, getstr(ls->source), MAXSRC); - msg = luaO_pushfstring(ls->L, "%s:%d: %s", buff, ls->linenumber, msg); - if (token) - luaO_pushfstring(ls->L, "%s near " LUA_QS, msg, txtToken(ls, token)); - luaD_throw(ls->L, LUA_ERRSYNTAX); -} - - -void luaX_syntaxerror (LexState *ls, const char *msg) { - luaX_lexerror(ls, msg, ls->t.token); -} - - -TString *luaX_newstring (LexState *ls, const char *str, size_t l) { - lua_State *L = ls->L; - TString *ts = luaS_newlstr(L, str, l); - TValue *o = luaH_setstr(L, ls->fs->h, ts); /* entry for `str' */ - if (ttisnil(o)) { - setbvalue(o, 1); /* make sure `str' will not be collected */ - luaC_checkGC(L); - } - return ts; -} - - -static void inclinenumber (LexState *ls) { - int old = ls->current; - lua_assert(currIsNewline(ls)); - next(ls); /* skip `\n' or `\r' */ - if (currIsNewline(ls) && ls->current != old) - next(ls); /* skip `\n\r' or `\r\n' */ - if (++ls->linenumber >= MAX_INT) - luaX_syntaxerror(ls, "chunk has too many lines"); -} - - -void luaX_setinput (lua_State *L, LexState *ls, ZIO *z, TString *source) { - ls->decpoint = '.'; - ls->L = L; - ls->lookahead.token = TK_EOS; /* no look-ahead token */ - ls->z = z; - ls->fs = NULL; - ls->linenumber = 1; - ls->lastline = 1; - ls->source = source; - luaZ_resizebuffer(ls->L, ls->buff, LUA_MINBUFFER); /* initialize buffer */ - next(ls); /* read first char */ -} - - - -/* -** ======================================================= -** LEXICAL ANALYZER -** ======================================================= -*/ - - - -static int check_next (LexState *ls, const char *set) { - if (!strchr(set, ls->current)) - return 0; - save_and_next(ls); - return 1; -} - - -static void buffreplace (LexState *ls, char from, char to) { - size_t n = luaZ_bufflen(ls->buff); - char *p = luaZ_buffer(ls->buff); - while (n--) - if (p[n] == from) p[n] = to; -} - - -static void trydecpoint (LexState *ls, SemInfo *seminfo) { - /* format error: try to update decimal point separator */ - struct lconv *cv = localeconv(); - char old = ls->decpoint; - ls->decpoint = (cv ? cv->decimal_point[0] : '.'); - buffreplace(ls, old, ls->decpoint); /* try updated decimal separator */ - if (!luaO_str2d(luaZ_buffer(ls->buff), &seminfo->r)) { - /* format error with correct decimal point: no more options */ - buffreplace(ls, ls->decpoint, '.'); /* undo change (for error message) */ - luaX_lexerror(ls, "malformed number", TK_NUMBER); - } -} - - -/* LUA_NUMBER */ -static void read_numeral (LexState *ls, SemInfo *seminfo) { - lua_assert(isdigit(ls->current)); - do { - save_and_next(ls); - } while (isdigit(ls->current) || ls->current == '.'); - if (check_next(ls, "Ee")) /* `E'? */ - check_next(ls, "+-"); /* optional exponent sign */ - while (isalnum(ls->current) || ls->current == '_') - save_and_next(ls); - save(ls, '\0'); - buffreplace(ls, '.', ls->decpoint); /* follow locale for decimal point */ - if (!luaO_str2d(luaZ_buffer(ls->buff), &seminfo->r)) /* format error? */ - trydecpoint(ls, seminfo); /* try to update decimal point separator */ -} - - -static int skip_sep (LexState *ls) { - int count = 0; - int s = ls->current; - lua_assert(s == '[' || s == ']'); - save_and_next(ls); - while (ls->current == '=') { - save_and_next(ls); - count++; - } - return (ls->current == s) ? count : (-count) - 1; -} - - -static void read_long_string (LexState *ls, SemInfo *seminfo, int sep) { - int cont = 0; - (void)(cont); /* avoid warnings when `cont' is not used */ - save_and_next(ls); /* skip 2nd `[' */ - if (currIsNewline(ls)) /* string starts with a newline? */ - inclinenumber(ls); /* skip it */ - for (;;) { - switch (ls->current) { - case EOZ: - luaX_lexerror(ls, (seminfo) ? "unfinished long string" : - "unfinished long comment", TK_EOS); - break; /* to avoid warnings */ -#if defined(LUA_COMPAT_LSTR) - case '[': { - if (skip_sep(ls) == sep) { - save_and_next(ls); /* skip 2nd `[' */ - cont++; -#if LUA_COMPAT_LSTR == 1 - if (sep == 0) - luaX_lexerror(ls, "nesting of [[...]] is deprecated", '['); -#endif - } - break; - } -#endif - case ']': { - if (skip_sep(ls) == sep) { - save_and_next(ls); /* skip 2nd `]' */ -#if defined(LUA_COMPAT_LSTR) && LUA_COMPAT_LSTR == 2 - cont--; - if (sep == 0 && cont >= 0) break; -#endif - goto endloop; - } - break; - } - case '\n': - case '\r': { - save(ls, '\n'); - inclinenumber(ls); - if (!seminfo) luaZ_resetbuffer(ls->buff); /* avoid wasting space */ - break; - } - default: { - if (seminfo) save_and_next(ls); - else next(ls); - } - } - } endloop: - if (seminfo) - seminfo->ts = luaX_newstring(ls, luaZ_buffer(ls->buff) + (2 + sep), - luaZ_bufflen(ls->buff) - 2*(2 + sep)); -} - - -static void read_string (LexState *ls, int del, SemInfo *seminfo) { - save_and_next(ls); - while (ls->current != del) { - switch (ls->current) { - case EOZ: - luaX_lexerror(ls, "unfinished string", TK_EOS); - continue; /* to avoid warnings */ - case '\n': - case '\r': - luaX_lexerror(ls, "unfinished string", TK_STRING); - continue; /* to avoid warnings */ - case '\\': { - int c; - next(ls); /* do not save the `\' */ - switch (ls->current) { - case 'a': c = '\a'; break; - case 'b': c = '\b'; break; - case 'f': c = '\f'; break; - case 'n': c = '\n'; break; - case 'r': c = '\r'; break; - case 't': c = '\t'; break; - case 'v': c = '\v'; break; - case '\n': /* go through */ - case '\r': save(ls, '\n'); inclinenumber(ls); continue; - case EOZ: continue; /* will raise an error next loop */ - default: { - if (!isdigit(ls->current)) - save_and_next(ls); /* handles \\, \", \', and \? */ - else { /* \xxx */ - int i = 0; - c = 0; - do { - c = 10*c + (ls->current-'0'); - next(ls); - } while (++i<3 && isdigit(ls->current)); - if (c > UCHAR_MAX) - luaX_lexerror(ls, "escape sequence too large", TK_STRING); - save(ls, c); - } - continue; - } - } - save(ls, c); - next(ls); - continue; - } - default: - save_and_next(ls); - } - } - save_and_next(ls); /* skip delimiter */ - seminfo->ts = luaX_newstring(ls, luaZ_buffer(ls->buff) + 1, - luaZ_bufflen(ls->buff) - 2); -} - - -static int llex (LexState *ls, SemInfo *seminfo) { - luaZ_resetbuffer(ls->buff); - for (;;) { - switch (ls->current) { - case '\n': - case '\r': { - inclinenumber(ls); - continue; - } - case '-': { - next(ls); - if (ls->current != '-') return '-'; - /* else is a comment */ - next(ls); - if (ls->current == '[') { - int sep = skip_sep(ls); - luaZ_resetbuffer(ls->buff); /* `skip_sep' may dirty the buffer */ - if (sep >= 0) { - read_long_string(ls, NULL, sep); /* long comment */ - luaZ_resetbuffer(ls->buff); - continue; - } - } - /* else short comment */ - while (!currIsNewline(ls) && ls->current != EOZ) - next(ls); - continue; - } - case '[': { - int sep = skip_sep(ls); - if (sep >= 0) { - read_long_string(ls, seminfo, sep); - return TK_STRING; - } - else if (sep == -1) return '['; - else luaX_lexerror(ls, "invalid long string delimiter", TK_STRING); - } - case '=': { - next(ls); - if (ls->current != '=') return '='; - else { next(ls); return TK_EQ; } - } - case '<': { - next(ls); - if (ls->current != '=') return '<'; - else { next(ls); return TK_LE; } - } - case '>': { - next(ls); - if (ls->current != '=') return '>'; - else { next(ls); return TK_GE; } - } - case '~': { - next(ls); - if (ls->current != '=') return '~'; - else { next(ls); return TK_NE; } - } - case '"': - case '\'': { - read_string(ls, ls->current, seminfo); - return TK_STRING; - } - case '.': { - save_and_next(ls); - if (check_next(ls, ".")) { - if (check_next(ls, ".")) - return TK_DOTS; /* ... */ - else return TK_CONCAT; /* .. */ - } - else if (!isdigit(ls->current)) return '.'; - else { - read_numeral(ls, seminfo); - return TK_NUMBER; - } - } - case EOZ: { - return TK_EOS; - } - default: { - if (isspace(ls->current)) { - lua_assert(!currIsNewline(ls)); - next(ls); - continue; - } - else if (isdigit(ls->current)) { - read_numeral(ls, seminfo); - return TK_NUMBER; - } - else if (isalpha(ls->current) || ls->current == '_') { - /* identifier or reserved word */ - TString *ts; - do { - save_and_next(ls); - } while (isalnum(ls->current) || ls->current == '_'); - ts = luaX_newstring(ls, luaZ_buffer(ls->buff), - luaZ_bufflen(ls->buff)); - if (ts->tsv.reserved > 0) /* reserved word? */ - return ts->tsv.reserved - 1 + FIRST_RESERVED; - else { - seminfo->ts = ts; - return TK_NAME; - } - } - else { - int c = ls->current; - next(ls); - return c; /* single-char tokens (+ - / ...) */ - } - } - } - } -} - - -void luaX_next (LexState *ls) { - ls->lastline = ls->linenumber; - if (ls->lookahead.token != TK_EOS) { /* is there a look-ahead token? */ - ls->t = ls->lookahead; /* use this one */ - ls->lookahead.token = TK_EOS; /* and discharge it */ - } - else - ls->t.token = llex(ls, &ls->t.seminfo); /* read next token */ -} - - -void luaX_lookahead (LexState *ls) { - lua_assert(ls->lookahead.token == TK_EOS); - ls->lookahead.token = llex(ls, &ls->lookahead.seminfo); -} - diff --git a/lib/lua-5.1/src/llex.h b/lib/lua-5.1/src/llex.h deleted file mode 100644 index a9201ce..0000000 --- a/lib/lua-5.1/src/llex.h +++ /dev/null @@ -1,81 +0,0 @@ -/* -** $Id: llex.h,v 1.58.1.1 2007/12/27 13:02:25 roberto Exp $ -** Lexical Analyzer -** See Copyright Notice in lua.h -*/ - -#ifndef llex_h -#define llex_h - -#include "lobject.h" -#include "lzio.h" - - -#define FIRST_RESERVED 257 - -/* maximum length of a reserved word */ -#define TOKEN_LEN (sizeof("function")/sizeof(char)) - - -/* -* WARNING: if you change the order of this enumeration, -* grep "ORDER RESERVED" -*/ -enum RESERVED { - /* terminal symbols denoted by reserved words */ - TK_AND = FIRST_RESERVED, TK_BREAK, - TK_DO, TK_ELSE, TK_ELSEIF, TK_END, TK_FALSE, TK_FOR, TK_FUNCTION, - TK_IF, TK_IN, TK_LOCAL, TK_NIL, TK_NOT, TK_OR, TK_REPEAT, - TK_RETURN, TK_THEN, TK_TRUE, TK_UNTIL, TK_WHILE, - /* other terminal symbols */ - TK_CONCAT, TK_DOTS, TK_EQ, TK_GE, TK_LE, TK_NE, TK_NUMBER, - TK_NAME, TK_STRING, TK_EOS -}; - -/* number of reserved words */ -#define NUM_RESERVED (cast(int, TK_WHILE-FIRST_RESERVED+1)) - - -/* array with token `names' */ -LUAI_DATA const char *const luaX_tokens []; - - -typedef union { - lua_Number r; - TString *ts; -} SemInfo; /* semantics information */ - - -typedef struct Token { - int token; - SemInfo seminfo; -} Token; - - -typedef struct LexState { - int current; /* current character (charint) */ - int linenumber; /* input line counter */ - int lastline; /* line of last token `consumed' */ - Token t; /* current token */ - Token lookahead; /* look ahead token */ - struct FuncState *fs; /* `FuncState' is private to the parser */ - struct lua_State *L; - ZIO *z; /* input stream */ - Mbuffer *buff; /* buffer for tokens */ - TString *source; /* current source name */ - char decpoint; /* locale decimal point */ -} LexState; - - -LUAI_FUNC void luaX_init (lua_State *L); -LUAI_FUNC void luaX_setinput (lua_State *L, LexState *ls, ZIO *z, - TString *source); -LUAI_FUNC TString *luaX_newstring (LexState *ls, const char *str, size_t l); -LUAI_FUNC void luaX_next (LexState *ls); -LUAI_FUNC void luaX_lookahead (LexState *ls); -LUAI_FUNC void luaX_lexerror (LexState *ls, const char *msg, int token); -LUAI_FUNC void luaX_syntaxerror (LexState *ls, const char *s); -LUAI_FUNC const char *luaX_token2str (LexState *ls, int token); - - -#endif diff --git a/lib/lua-5.1/src/llimits.h b/lib/lua-5.1/src/llimits.h deleted file mode 100644 index ca8dcb7..0000000 --- a/lib/lua-5.1/src/llimits.h +++ /dev/null @@ -1,128 +0,0 @@ -/* -** $Id: llimits.h,v 1.69.1.1 2007/12/27 13:02:25 roberto Exp $ -** Limits, basic types, and some other `installation-dependent' definitions -** See Copyright Notice in lua.h -*/ - -#ifndef llimits_h -#define llimits_h - - -#include -#include - - -#include "lua.h" - - -typedef LUAI_UINT32 lu_int32; - -typedef LUAI_UMEM lu_mem; - -typedef LUAI_MEM l_mem; - - - -/* chars used as small naturals (so that `char' is reserved for characters) */ -typedef unsigned char lu_byte; - - -#define MAX_SIZET ((size_t)(~(size_t)0)-2) - -#define MAX_LUMEM ((lu_mem)(~(lu_mem)0)-2) - - -#define MAX_INT (INT_MAX-2) /* maximum value of an int (-2 for safety) */ - -/* -** conversion of pointer to integer -** this is for hashing only; there is no problem if the integer -** cannot hold the whole pointer value -*/ -#define IntPoint(p) ((unsigned int)(lu_mem)(p)) - - - -/* type to ensure maximum alignment */ -typedef LUAI_USER_ALIGNMENT_T L_Umaxalign; - - -/* result of a `usual argument conversion' over lua_Number */ -typedef LUAI_UACNUMBER l_uacNumber; - - -/* internal assertions for in-house debugging */ -#ifdef lua_assert - -#define check_exp(c,e) (lua_assert(c), (e)) -#define api_check(l,e) lua_assert(e) - -#else - -#define lua_assert(c) ((void)0) -#define check_exp(c,e) (e) -#define api_check luai_apicheck - -#endif - - -#ifndef UNUSED -#define UNUSED(x) ((void)(x)) /* to avoid warnings */ -#endif - - -#ifndef cast -#define cast(t, exp) ((t)(exp)) -#endif - -#define cast_byte(i) cast(lu_byte, (i)) -#define cast_num(i) cast(lua_Number, (i)) -#define cast_int(i) cast(int, (i)) - - - -/* -** type for virtual-machine instructions -** must be an unsigned with (at least) 4 bytes (see details in lopcodes.h) -*/ -typedef lu_int32 Instruction; - - - -/* maximum stack for a Lua function */ -#define MAXSTACK 250 - - - -/* minimum size for the string table (must be power of 2) */ -#ifndef MINSTRTABSIZE -#define MINSTRTABSIZE 32 -#endif - - -/* minimum size for string buffer */ -#ifndef LUA_MINBUFFER -#define LUA_MINBUFFER 32 -#endif - - -#ifndef lua_lock -#define lua_lock(L) ((void) 0) -#define lua_unlock(L) ((void) 0) -#endif - -#ifndef luai_threadyield -#define luai_threadyield(L) {lua_unlock(L); lua_lock(L);} -#endif - - -/* -** macro to control inclusion of some hard tests on stack reallocation -*/ -#ifndef HARDSTACKTESTS -#define condhardstacktests(x) ((void)0) -#else -#define condhardstacktests(x) x -#endif - -#endif diff --git a/lib/lua-5.1/src/lmathlib.c b/lib/lua-5.1/src/lmathlib.c deleted file mode 100644 index 441fbf7..0000000 --- a/lib/lua-5.1/src/lmathlib.c +++ /dev/null @@ -1,263 +0,0 @@ -/* -** $Id: lmathlib.c,v 1.67.1.1 2007/12/27 13:02:25 roberto Exp $ -** Standard mathematical library -** See Copyright Notice in lua.h -*/ - - -#include -#include - -#define lmathlib_c -#define LUA_LIB - -#include "lua.h" - -#include "lauxlib.h" -#include "lualib.h" - - -#undef PI -#define PI (3.14159265358979323846) -#define RADIANS_PER_DEGREE (PI/180.0) - - - -static int math_abs (lua_State *L) { - lua_pushnumber(L, fabs(luaL_checknumber(L, 1))); - return 1; -} - -static int math_sin (lua_State *L) { - lua_pushnumber(L, sin(luaL_checknumber(L, 1))); - return 1; -} - -static int math_sinh (lua_State *L) { - lua_pushnumber(L, sinh(luaL_checknumber(L, 1))); - return 1; -} - -static int math_cos (lua_State *L) { - lua_pushnumber(L, cos(luaL_checknumber(L, 1))); - return 1; -} - -static int math_cosh (lua_State *L) { - lua_pushnumber(L, cosh(luaL_checknumber(L, 1))); - return 1; -} - -static int math_tan (lua_State *L) { - lua_pushnumber(L, tan(luaL_checknumber(L, 1))); - return 1; -} - -static int math_tanh (lua_State *L) { - lua_pushnumber(L, tanh(luaL_checknumber(L, 1))); - return 1; -} - -static int math_asin (lua_State *L) { - lua_pushnumber(L, asin(luaL_checknumber(L, 1))); - return 1; -} - -static int math_acos (lua_State *L) { - lua_pushnumber(L, acos(luaL_checknumber(L, 1))); - return 1; -} - -static int math_atan (lua_State *L) { - lua_pushnumber(L, atan(luaL_checknumber(L, 1))); - return 1; -} - -static int math_atan2 (lua_State *L) { - lua_pushnumber(L, atan2(luaL_checknumber(L, 1), luaL_checknumber(L, 2))); - return 1; -} - -static int math_ceil (lua_State *L) { - lua_pushnumber(L, ceil(luaL_checknumber(L, 1))); - return 1; -} - -static int math_floor (lua_State *L) { - lua_pushnumber(L, floor(luaL_checknumber(L, 1))); - return 1; -} - -static int math_fmod (lua_State *L) { - lua_pushnumber(L, fmod(luaL_checknumber(L, 1), luaL_checknumber(L, 2))); - return 1; -} - -static int math_modf (lua_State *L) { - double ip; - double fp = modf(luaL_checknumber(L, 1), &ip); - lua_pushnumber(L, ip); - lua_pushnumber(L, fp); - return 2; -} - -static int math_sqrt (lua_State *L) { - lua_pushnumber(L, sqrt(luaL_checknumber(L, 1))); - return 1; -} - -static int math_pow (lua_State *L) { - lua_pushnumber(L, pow(luaL_checknumber(L, 1), luaL_checknumber(L, 2))); - return 1; -} - -static int math_log (lua_State *L) { - lua_pushnumber(L, log(luaL_checknumber(L, 1))); - return 1; -} - -static int math_log10 (lua_State *L) { - lua_pushnumber(L, log10(luaL_checknumber(L, 1))); - return 1; -} - -static int math_exp (lua_State *L) { - lua_pushnumber(L, exp(luaL_checknumber(L, 1))); - return 1; -} - -static int math_deg (lua_State *L) { - lua_pushnumber(L, luaL_checknumber(L, 1)/RADIANS_PER_DEGREE); - return 1; -} - -static int math_rad (lua_State *L) { - lua_pushnumber(L, luaL_checknumber(L, 1)*RADIANS_PER_DEGREE); - return 1; -} - -static int math_frexp (lua_State *L) { - int e; - lua_pushnumber(L, frexp(luaL_checknumber(L, 1), &e)); - lua_pushinteger(L, e); - return 2; -} - -static int math_ldexp (lua_State *L) { - lua_pushnumber(L, ldexp(luaL_checknumber(L, 1), luaL_checkint(L, 2))); - return 1; -} - - - -static int math_min (lua_State *L) { - int n = lua_gettop(L); /* number of arguments */ - lua_Number dmin = luaL_checknumber(L, 1); - int i; - for (i=2; i<=n; i++) { - lua_Number d = luaL_checknumber(L, i); - if (d < dmin) - dmin = d; - } - lua_pushnumber(L, dmin); - return 1; -} - - -static int math_max (lua_State *L) { - int n = lua_gettop(L); /* number of arguments */ - lua_Number dmax = luaL_checknumber(L, 1); - int i; - for (i=2; i<=n; i++) { - lua_Number d = luaL_checknumber(L, i); - if (d > dmax) - dmax = d; - } - lua_pushnumber(L, dmax); - return 1; -} - - -static int math_random (lua_State *L) { - /* the `%' avoids the (rare) case of r==1, and is needed also because on - some systems (SunOS!) `rand()' may return a value larger than RAND_MAX */ - lua_Number r = (lua_Number)(rand()%RAND_MAX) / (lua_Number)RAND_MAX; - switch (lua_gettop(L)) { /* check number of arguments */ - case 0: { /* no arguments */ - lua_pushnumber(L, r); /* Number between 0 and 1 */ - break; - } - case 1: { /* only upper limit */ - int u = luaL_checkint(L, 1); - luaL_argcheck(L, 1<=u, 1, "interval is empty"); - lua_pushnumber(L, floor(r*u)+1); /* int between 1 and `u' */ - break; - } - case 2: { /* lower and upper limits */ - int l = luaL_checkint(L, 1); - int u = luaL_checkint(L, 2); - luaL_argcheck(L, l<=u, 2, "interval is empty"); - lua_pushnumber(L, floor(r*(u-l+1))+l); /* int between `l' and `u' */ - break; - } - default: return luaL_error(L, "wrong number of arguments"); - } - return 1; -} - - -static int math_randomseed (lua_State *L) { - srand(luaL_checkint(L, 1)); - return 0; -} - - -static const luaL_Reg mathlib[] = { - {"abs", math_abs}, - {"acos", math_acos}, - {"asin", math_asin}, - {"atan2", math_atan2}, - {"atan", math_atan}, - {"ceil", math_ceil}, - {"cosh", math_cosh}, - {"cos", math_cos}, - {"deg", math_deg}, - {"exp", math_exp}, - {"floor", math_floor}, - {"fmod", math_fmod}, - {"frexp", math_frexp}, - {"ldexp", math_ldexp}, - {"log10", math_log10}, - {"log", math_log}, - {"max", math_max}, - {"min", math_min}, - {"modf", math_modf}, - {"pow", math_pow}, - {"rad", math_rad}, - {"random", math_random}, - {"randomseed", math_randomseed}, - {"sinh", math_sinh}, - {"sin", math_sin}, - {"sqrt", math_sqrt}, - {"tanh", math_tanh}, - {"tan", math_tan}, - {NULL, NULL} -}; - - -/* -** Open math library -*/ -LUALIB_API int luaopen_math (lua_State *L) { - luaL_register(L, LUA_MATHLIBNAME, mathlib); - lua_pushnumber(L, PI); - lua_setfield(L, -2, "pi"); - lua_pushnumber(L, HUGE_VAL); - lua_setfield(L, -2, "huge"); -#if defined(LUA_COMPAT_MOD) - lua_getfield(L, -1, "fmod"); - lua_setfield(L, -2, "mod"); -#endif - return 1; -} - diff --git a/lib/lua-5.1/src/lmem.c b/lib/lua-5.1/src/lmem.c deleted file mode 100644 index ae7d8c9..0000000 --- a/lib/lua-5.1/src/lmem.c +++ /dev/null @@ -1,86 +0,0 @@ -/* -** $Id: lmem.c,v 1.70.1.1 2007/12/27 13:02:25 roberto Exp $ -** Interface to Memory Manager -** See Copyright Notice in lua.h -*/ - - -#include - -#define lmem_c -#define LUA_CORE - -#include "lua.h" - -#include "ldebug.h" -#include "ldo.h" -#include "lmem.h" -#include "lobject.h" -#include "lstate.h" - - - -/* -** About the realloc function: -** void * frealloc (void *ud, void *ptr, size_t osize, size_t nsize); -** (`osize' is the old size, `nsize' is the new size) -** -** Lua ensures that (ptr == NULL) iff (osize == 0). -** -** * frealloc(ud, NULL, 0, x) creates a new block of size `x' -** -** * frealloc(ud, p, x, 0) frees the block `p' -** (in this specific case, frealloc must return NULL). -** particularly, frealloc(ud, NULL, 0, 0) does nothing -** (which is equivalent to free(NULL) in ANSI C) -** -** frealloc returns NULL if it cannot create or reallocate the area -** (any reallocation to an equal or smaller size cannot fail!) -*/ - - - -#define MINSIZEARRAY 4 - - -void *luaM_growaux_ (lua_State *L, void *block, int *size, size_t size_elems, - int limit, const char *errormsg) { - void *newblock; - int newsize; - if (*size >= limit/2) { /* cannot double it? */ - if (*size >= limit) /* cannot grow even a little? */ - luaG_runerror(L, errormsg); - newsize = limit; /* still have at least one free place */ - } - else { - newsize = (*size)*2; - if (newsize < MINSIZEARRAY) - newsize = MINSIZEARRAY; /* minimum size */ - } - newblock = luaM_reallocv(L, block, *size, newsize, size_elems); - *size = newsize; /* update only when everything else is OK */ - return newblock; -} - - -void *luaM_toobig (lua_State *L) { - luaG_runerror(L, "memory allocation error: block too big"); - return NULL; /* to avoid warnings */ -} - - - -/* -** generic allocation routine. -*/ -void *luaM_realloc_ (lua_State *L, void *block, size_t osize, size_t nsize) { - global_State *g = G(L); - lua_assert((osize == 0) == (block == NULL)); - block = (*g->frealloc)(g->ud, block, osize, nsize); - if (block == NULL && nsize > 0) - luaD_throw(L, LUA_ERRMEM); - lua_assert((nsize == 0) == (block == NULL)); - g->totalbytes = (g->totalbytes - osize) + nsize; - return block; -} - diff --git a/lib/lua-5.1/src/lmem.h b/lib/lua-5.1/src/lmem.h deleted file mode 100644 index 7c2dcb3..0000000 --- a/lib/lua-5.1/src/lmem.h +++ /dev/null @@ -1,49 +0,0 @@ -/* -** $Id: lmem.h,v 1.31.1.1 2007/12/27 13:02:25 roberto Exp $ -** Interface to Memory Manager -** See Copyright Notice in lua.h -*/ - -#ifndef lmem_h -#define lmem_h - - -#include - -#include "llimits.h" -#include "lua.h" - -#define MEMERRMSG "not enough memory" - - -#define luaM_reallocv(L,b,on,n,e) \ - ((cast(size_t, (n)+1) <= MAX_SIZET/(e)) ? /* +1 to avoid warnings */ \ - luaM_realloc_(L, (b), (on)*(e), (n)*(e)) : \ - luaM_toobig(L)) - -#define luaM_freemem(L, b, s) luaM_realloc_(L, (b), (s), 0) -#define luaM_free(L, b) luaM_realloc_(L, (b), sizeof(*(b)), 0) -#define luaM_freearray(L, b, n, t) luaM_reallocv(L, (b), n, 0, sizeof(t)) - -#define luaM_malloc(L,t) luaM_realloc_(L, NULL, 0, (t)) -#define luaM_new(L,t) cast(t *, luaM_malloc(L, sizeof(t))) -#define luaM_newvector(L,n,t) \ - cast(t *, luaM_reallocv(L, NULL, 0, n, sizeof(t))) - -#define luaM_growvector(L,v,nelems,size,t,limit,e) \ - if ((nelems)+1 > (size)) \ - ((v)=cast(t *, luaM_growaux_(L,v,&(size),sizeof(t),limit,e))) - -#define luaM_reallocvector(L, v,oldn,n,t) \ - ((v)=cast(t *, luaM_reallocv(L, v, oldn, n, sizeof(t)))) - - -LUAI_FUNC void *luaM_realloc_ (lua_State *L, void *block, size_t oldsize, - size_t size); -LUAI_FUNC void *luaM_toobig (lua_State *L); -LUAI_FUNC void *luaM_growaux_ (lua_State *L, void *block, int *size, - size_t size_elem, int limit, - const char *errormsg); - -#endif - diff --git a/lib/lua-5.1/src/loadlib.c b/lib/lua-5.1/src/loadlib.c deleted file mode 100644 index 6158c53..0000000 --- a/lib/lua-5.1/src/loadlib.c +++ /dev/null @@ -1,666 +0,0 @@ -/* -** $Id: loadlib.c,v 1.52.1.4 2009/09/09 13:17:16 roberto Exp $ -** Dynamic library loader for Lua -** See Copyright Notice in lua.h -** -** This module contains an implementation of loadlib for Unix systems -** that have dlfcn, an implementation for Darwin (Mac OS X), an -** implementation for Windows, and a stub for other systems. -*/ - - -#include -#include - - -#define loadlib_c -#define LUA_LIB - -#include "lua.h" - -#include "lauxlib.h" -#include "lualib.h" - - -/* prefix for open functions in C libraries */ -#define LUA_POF "luaopen_" - -/* separator for open functions in C libraries */ -#define LUA_OFSEP "_" - - -#define LIBPREFIX "LOADLIB: " - -#define POF LUA_POF -#define LIB_FAIL "open" - - -/* error codes for ll_loadfunc */ -#define ERRLIB 1 -#define ERRFUNC 2 - -#define setprogdir(L) ((void)0) - - -static void ll_unloadlib (void *lib); -static void *ll_load (lua_State *L, const char *path); -static lua_CFunction ll_sym (lua_State *L, void *lib, const char *sym); - - - -#if defined(LUA_DL_DLOPEN) -/* -** {======================================================================== -** This is an implementation of loadlib based on the dlfcn interface. -** The dlfcn interface is available in Linux, SunOS, Solaris, IRIX, FreeBSD, -** NetBSD, AIX 4.2, HPUX 11, and probably most other Unix flavors, at least -** as an emulation layer on top of native functions. -** ========================================================================= -*/ - -#include - -static void ll_unloadlib (void *lib) { - dlclose(lib); -} - - -static void *ll_load (lua_State *L, const char *path) { - void *lib = dlopen(path, RTLD_NOW); - if (lib == NULL) lua_pushstring(L, dlerror()); - return lib; -} - - -static lua_CFunction ll_sym (lua_State *L, void *lib, const char *sym) { - lua_CFunction f = (lua_CFunction)dlsym(lib, sym); - if (f == NULL) lua_pushstring(L, dlerror()); - return f; -} - -/* }====================================================== */ - - - -#elif defined(LUA_DL_DLL) -/* -** {====================================================================== -** This is an implementation of loadlib for Windows using native functions. -** ======================================================================= -*/ - -#include - - -#undef setprogdir - -static void setprogdir (lua_State *L) { - char buff[MAX_PATH + 1]; - char *lb; - DWORD nsize = sizeof(buff)/sizeof(char); - DWORD n = GetModuleFileNameA(NULL, buff, nsize); - if (n == 0 || n == nsize || (lb = strrchr(buff, '\\')) == NULL) - luaL_error(L, "unable to get ModuleFileName"); - else { - *lb = '\0'; - luaL_gsub(L, lua_tostring(L, -1), LUA_EXECDIR, buff); - lua_remove(L, -2); /* remove original string */ - } -} - - -static void pusherror (lua_State *L) { - int error = GetLastError(); - char buffer[128]; - if (FormatMessageA(FORMAT_MESSAGE_IGNORE_INSERTS | FORMAT_MESSAGE_FROM_SYSTEM, - NULL, error, 0, buffer, sizeof(buffer), NULL)) - lua_pushstring(L, buffer); - else - lua_pushfstring(L, "system error %d\n", error); -} - -static void ll_unloadlib (void *lib) { - FreeLibrary((HINSTANCE)lib); -} - - -static void *ll_load (lua_State *L, const char *path) { - HINSTANCE lib = LoadLibraryA(path); - if (lib == NULL) pusherror(L); - return lib; -} - - -static lua_CFunction ll_sym (lua_State *L, void *lib, const char *sym) { - lua_CFunction f = (lua_CFunction)GetProcAddress((HINSTANCE)lib, sym); - if (f == NULL) pusherror(L); - return f; -} - -/* }====================================================== */ - - - -#elif defined(LUA_DL_DYLD) -/* -** {====================================================================== -** Native Mac OS X / Darwin Implementation -** ======================================================================= -*/ - -#include - - -/* Mac appends a `_' before C function names */ -#undef POF -#define POF "_" LUA_POF - - -static void pusherror (lua_State *L) { - const char *err_str; - const char *err_file; - NSLinkEditErrors err; - int err_num; - NSLinkEditError(&err, &err_num, &err_file, &err_str); - lua_pushstring(L, err_str); -} - - -static const char *errorfromcode (NSObjectFileImageReturnCode ret) { - switch (ret) { - case NSObjectFileImageInappropriateFile: - return "file is not a bundle"; - case NSObjectFileImageArch: - return "library is for wrong CPU type"; - case NSObjectFileImageFormat: - return "bad format"; - case NSObjectFileImageAccess: - return "cannot access file"; - case NSObjectFileImageFailure: - default: - return "unable to load library"; - } -} - - -static void ll_unloadlib (void *lib) { - NSUnLinkModule((NSModule)lib, NSUNLINKMODULE_OPTION_RESET_LAZY_REFERENCES); -} - - -static void *ll_load (lua_State *L, const char *path) { - NSObjectFileImage img; - NSObjectFileImageReturnCode ret; - /* this would be a rare case, but prevents crashing if it happens */ - if(!_dyld_present()) { - lua_pushliteral(L, "dyld not present"); - return NULL; - } - ret = NSCreateObjectFileImageFromFile(path, &img); - if (ret == NSObjectFileImageSuccess) { - NSModule mod = NSLinkModule(img, path, NSLINKMODULE_OPTION_PRIVATE | - NSLINKMODULE_OPTION_RETURN_ON_ERROR); - NSDestroyObjectFileImage(img); - if (mod == NULL) pusherror(L); - return mod; - } - lua_pushstring(L, errorfromcode(ret)); - return NULL; -} - - -static lua_CFunction ll_sym (lua_State *L, void *lib, const char *sym) { - NSSymbol nss = NSLookupSymbolInModule((NSModule)lib, sym); - if (nss == NULL) { - lua_pushfstring(L, "symbol " LUA_QS " not found", sym); - return NULL; - } - return (lua_CFunction)NSAddressOfSymbol(nss); -} - -/* }====================================================== */ - - - -#else -/* -** {====================================================== -** Fallback for other systems -** ======================================================= -*/ - -#undef LIB_FAIL -#define LIB_FAIL "absent" - - -#define DLMSG "dynamic libraries not enabled; check your Lua installation" - - -static void ll_unloadlib (void *lib) { - (void)lib; /* to avoid warnings */ -} - - -static void *ll_load (lua_State *L, const char *path) { - (void)path; /* to avoid warnings */ - lua_pushliteral(L, DLMSG); - return NULL; -} - - -static lua_CFunction ll_sym (lua_State *L, void *lib, const char *sym) { - (void)lib; (void)sym; /* to avoid warnings */ - lua_pushliteral(L, DLMSG); - return NULL; -} - -/* }====================================================== */ -#endif - - - -static void **ll_register (lua_State *L, const char *path) { - void **plib; - lua_pushfstring(L, "%s%s", LIBPREFIX, path); - lua_gettable(L, LUA_REGISTRYINDEX); /* check library in registry? */ - if (!lua_isnil(L, -1)) /* is there an entry? */ - plib = (void **)lua_touserdata(L, -1); - else { /* no entry yet; create one */ - lua_pop(L, 1); - plib = (void **)lua_newuserdata(L, sizeof(const void *)); - *plib = NULL; - luaL_getmetatable(L, "_LOADLIB"); - lua_setmetatable(L, -2); - lua_pushfstring(L, "%s%s", LIBPREFIX, path); - lua_pushvalue(L, -2); - lua_settable(L, LUA_REGISTRYINDEX); - } - return plib; -} - - -/* -** __gc tag method: calls library's `ll_unloadlib' function with the lib -** handle -*/ -static int gctm (lua_State *L) { - void **lib = (void **)luaL_checkudata(L, 1, "_LOADLIB"); - if (*lib) ll_unloadlib(*lib); - *lib = NULL; /* mark library as closed */ - return 0; -} - - -static int ll_loadfunc (lua_State *L, const char *path, const char *sym) { - void **reg = ll_register(L, path); - if (*reg == NULL) *reg = ll_load(L, path); - if (*reg == NULL) - return ERRLIB; /* unable to load library */ - else { - lua_CFunction f = ll_sym(L, *reg, sym); - if (f == NULL) - return ERRFUNC; /* unable to find function */ - lua_pushcfunction(L, f); - return 0; /* return function */ - } -} - - -static int ll_loadlib (lua_State *L) { - const char *path = luaL_checkstring(L, 1); - const char *init = luaL_checkstring(L, 2); - int stat = ll_loadfunc(L, path, init); - if (stat == 0) /* no errors? */ - return 1; /* return the loaded function */ - else { /* error; error message is on stack top */ - lua_pushnil(L); - lua_insert(L, -2); - lua_pushstring(L, (stat == ERRLIB) ? LIB_FAIL : "init"); - return 3; /* return nil, error message, and where */ - } -} - - - -/* -** {====================================================== -** 'require' function -** ======================================================= -*/ - - -static int readable (const char *filename) { - FILE *f = fopen(filename, "r"); /* try to open file */ - if (f == NULL) return 0; /* open failed */ - fclose(f); - return 1; -} - - -static const char *pushnexttemplate (lua_State *L, const char *path) { - const char *l; - while (*path == *LUA_PATHSEP) path++; /* skip separators */ - if (*path == '\0') return NULL; /* no more templates */ - l = strchr(path, *LUA_PATHSEP); /* find next separator */ - if (l == NULL) l = path + strlen(path); - lua_pushlstring(L, path, l - path); /* template */ - return l; -} - - -static const char *findfile (lua_State *L, const char *name, - const char *pname) { - const char *path; - name = luaL_gsub(L, name, ".", LUA_DIRSEP); - lua_getfield(L, LUA_ENVIRONINDEX, pname); - path = lua_tostring(L, -1); - if (path == NULL) - luaL_error(L, LUA_QL("package.%s") " must be a string", pname); - lua_pushliteral(L, ""); /* error accumulator */ - while ((path = pushnexttemplate(L, path)) != NULL) { - const char *filename; - filename = luaL_gsub(L, lua_tostring(L, -1), LUA_PATH_MARK, name); - lua_remove(L, -2); /* remove path template */ - if (readable(filename)) /* does file exist and is readable? */ - return filename; /* return that file name */ - lua_pushfstring(L, "\n\tno file " LUA_QS, filename); - lua_remove(L, -2); /* remove file name */ - lua_concat(L, 2); /* add entry to possible error message */ - } - return NULL; /* not found */ -} - - -static void loaderror (lua_State *L, const char *filename) { - luaL_error(L, "error loading module " LUA_QS " from file " LUA_QS ":\n\t%s", - lua_tostring(L, 1), filename, lua_tostring(L, -1)); -} - - -static int loader_Lua (lua_State *L) { - const char *filename; - const char *name = luaL_checkstring(L, 1); - filename = findfile(L, name, "path"); - if (filename == NULL) return 1; /* library not found in this path */ - if (luaL_loadfile(L, filename) != 0) - loaderror(L, filename); - return 1; /* library loaded successfully */ -} - - -static const char *mkfuncname (lua_State *L, const char *modname) { - const char *funcname; - const char *mark = strchr(modname, *LUA_IGMARK); - if (mark) modname = mark + 1; - funcname = luaL_gsub(L, modname, ".", LUA_OFSEP); - funcname = lua_pushfstring(L, POF"%s", funcname); - lua_remove(L, -2); /* remove 'gsub' result */ - return funcname; -} - - -static int loader_C (lua_State *L) { - const char *funcname; - const char *name = luaL_checkstring(L, 1); - const char *filename = findfile(L, name, "cpath"); - if (filename == NULL) return 1; /* library not found in this path */ - funcname = mkfuncname(L, name); - if (ll_loadfunc(L, filename, funcname) != 0) - loaderror(L, filename); - return 1; /* library loaded successfully */ -} - - -static int loader_Croot (lua_State *L) { - const char *funcname; - const char *filename; - const char *name = luaL_checkstring(L, 1); - const char *p = strchr(name, '.'); - int stat; - if (p == NULL) return 0; /* is root */ - lua_pushlstring(L, name, p - name); - filename = findfile(L, lua_tostring(L, -1), "cpath"); - if (filename == NULL) return 1; /* root not found */ - funcname = mkfuncname(L, name); - if ((stat = ll_loadfunc(L, filename, funcname)) != 0) { - if (stat != ERRFUNC) loaderror(L, filename); /* real error */ - lua_pushfstring(L, "\n\tno module " LUA_QS " in file " LUA_QS, - name, filename); - return 1; /* function not found */ - } - return 1; -} - - -static int loader_preload (lua_State *L) { - const char *name = luaL_checkstring(L, 1); - lua_getfield(L, LUA_ENVIRONINDEX, "preload"); - if (!lua_istable(L, -1)) - luaL_error(L, LUA_QL("package.preload") " must be a table"); - lua_getfield(L, -1, name); - if (lua_isnil(L, -1)) /* not found? */ - lua_pushfstring(L, "\n\tno field package.preload['%s']", name); - return 1; -} - - -static const int sentinel_ = 0; -#define sentinel ((void *)&sentinel_) - - -static int ll_require (lua_State *L) { - const char *name = luaL_checkstring(L, 1); - int i; - lua_settop(L, 1); /* _LOADED table will be at index 2 */ - lua_getfield(L, LUA_REGISTRYINDEX, "_LOADED"); - lua_getfield(L, 2, name); - if (lua_toboolean(L, -1)) { /* is it there? */ - if (lua_touserdata(L, -1) == sentinel) /* check loops */ - luaL_error(L, "loop or previous error loading module " LUA_QS, name); - return 1; /* package is already loaded */ - } - /* else must load it; iterate over available loaders */ - lua_getfield(L, LUA_ENVIRONINDEX, "loaders"); - if (!lua_istable(L, -1)) - luaL_error(L, LUA_QL("package.loaders") " must be a table"); - lua_pushliteral(L, ""); /* error message accumulator */ - for (i=1; ; i++) { - lua_rawgeti(L, -2, i); /* get a loader */ - if (lua_isnil(L, -1)) - luaL_error(L, "module " LUA_QS " not found:%s", - name, lua_tostring(L, -2)); - lua_pushstring(L, name); - lua_call(L, 1, 1); /* call it */ - if (lua_isfunction(L, -1)) /* did it find module? */ - break; /* module loaded successfully */ - else if (lua_isstring(L, -1)) /* loader returned error message? */ - lua_concat(L, 2); /* accumulate it */ - else - lua_pop(L, 1); - } - lua_pushlightuserdata(L, sentinel); - lua_setfield(L, 2, name); /* _LOADED[name] = sentinel */ - lua_pushstring(L, name); /* pass name as argument to module */ - lua_call(L, 1, 1); /* run loaded module */ - if (!lua_isnil(L, -1)) /* non-nil return? */ - lua_setfield(L, 2, name); /* _LOADED[name] = returned value */ - lua_getfield(L, 2, name); - if (lua_touserdata(L, -1) == sentinel) { /* module did not set a value? */ - lua_pushboolean(L, 1); /* use true as result */ - lua_pushvalue(L, -1); /* extra copy to be returned */ - lua_setfield(L, 2, name); /* _LOADED[name] = true */ - } - return 1; -} - -/* }====================================================== */ - - - -/* -** {====================================================== -** 'module' function -** ======================================================= -*/ - - -static void setfenv (lua_State *L) { - lua_Debug ar; - if (lua_getstack(L, 1, &ar) == 0 || - lua_getinfo(L, "f", &ar) == 0 || /* get calling function */ - lua_iscfunction(L, -1)) - luaL_error(L, LUA_QL("module") " not called from a Lua function"); - lua_pushvalue(L, -2); - lua_setfenv(L, -2); - lua_pop(L, 1); -} - - -static void dooptions (lua_State *L, int n) { - int i; - for (i = 2; i <= n; i++) { - lua_pushvalue(L, i); /* get option (a function) */ - lua_pushvalue(L, -2); /* module */ - lua_call(L, 1, 0); - } -} - - -static void modinit (lua_State *L, const char *modname) { - const char *dot; - lua_pushvalue(L, -1); - lua_setfield(L, -2, "_M"); /* module._M = module */ - lua_pushstring(L, modname); - lua_setfield(L, -2, "_NAME"); - dot = strrchr(modname, '.'); /* look for last dot in module name */ - if (dot == NULL) dot = modname; - else dot++; - /* set _PACKAGE as package name (full module name minus last part) */ - lua_pushlstring(L, modname, dot - modname); - lua_setfield(L, -2, "_PACKAGE"); -} - - -static int ll_module (lua_State *L) { - const char *modname = luaL_checkstring(L, 1); - int loaded = lua_gettop(L) + 1; /* index of _LOADED table */ - lua_getfield(L, LUA_REGISTRYINDEX, "_LOADED"); - lua_getfield(L, loaded, modname); /* get _LOADED[modname] */ - if (!lua_istable(L, -1)) { /* not found? */ - lua_pop(L, 1); /* remove previous result */ - /* try global variable (and create one if it does not exist) */ - if (luaL_findtable(L, LUA_GLOBALSINDEX, modname, 1) != NULL) - return luaL_error(L, "name conflict for module " LUA_QS, modname); - lua_pushvalue(L, -1); - lua_setfield(L, loaded, modname); /* _LOADED[modname] = new table */ - } - /* check whether table already has a _NAME field */ - lua_getfield(L, -1, "_NAME"); - if (!lua_isnil(L, -1)) /* is table an initialized module? */ - lua_pop(L, 1); - else { /* no; initialize it */ - lua_pop(L, 1); - modinit(L, modname); - } - lua_pushvalue(L, -1); - setfenv(L); - dooptions(L, loaded - 1); - return 0; -} - - -static int ll_seeall (lua_State *L) { - luaL_checktype(L, 1, LUA_TTABLE); - if (!lua_getmetatable(L, 1)) { - lua_createtable(L, 0, 1); /* create new metatable */ - lua_pushvalue(L, -1); - lua_setmetatable(L, 1); - } - lua_pushvalue(L, LUA_GLOBALSINDEX); - lua_setfield(L, -2, "__index"); /* mt.__index = _G */ - return 0; -} - - -/* }====================================================== */ - - - -/* auxiliary mark (for internal use) */ -#define AUXMARK "\1" - -static void setpath (lua_State *L, const char *fieldname, const char *envname, - const char *def) { - const char *path = getenv(envname); - if (path == NULL) /* no environment variable? */ - lua_pushstring(L, def); /* use default */ - else { - /* replace ";;" by ";AUXMARK;" and then AUXMARK by default path */ - path = luaL_gsub(L, path, LUA_PATHSEP LUA_PATHSEP, - LUA_PATHSEP AUXMARK LUA_PATHSEP); - luaL_gsub(L, path, AUXMARK, def); - lua_remove(L, -2); - } - setprogdir(L); - lua_setfield(L, -2, fieldname); -} - - -static const luaL_Reg pk_funcs[] = { - {"loadlib", ll_loadlib}, - {"seeall", ll_seeall}, - {NULL, NULL} -}; - - -static const luaL_Reg ll_funcs[] = { - {"module", ll_module}, - {"require", ll_require}, - {NULL, NULL} -}; - - -static const lua_CFunction loaders[] = - {loader_preload, loader_Lua, loader_C, loader_Croot, NULL}; - - -LUALIB_API int luaopen_package (lua_State *L) { - int i; - /* create new type _LOADLIB */ - luaL_newmetatable(L, "_LOADLIB"); - lua_pushcfunction(L, gctm); - lua_setfield(L, -2, "__gc"); - /* create `package' table */ - luaL_register(L, LUA_LOADLIBNAME, pk_funcs); -#if defined(LUA_COMPAT_LOADLIB) - lua_getfield(L, -1, "loadlib"); - lua_setfield(L, LUA_GLOBALSINDEX, "loadlib"); -#endif - lua_pushvalue(L, -1); - lua_replace(L, LUA_ENVIRONINDEX); - /* create `loaders' table */ - lua_createtable(L, sizeof(loaders)/sizeof(loaders[0]) - 1, 0); - /* fill it with pre-defined loaders */ - for (i=0; loaders[i] != NULL; i++) { - lua_pushcfunction(L, loaders[i]); - lua_rawseti(L, -2, i+1); - } - lua_setfield(L, -2, "loaders"); /* put it in field `loaders' */ - setpath(L, "path", LUA_PATH, LUA_PATH_DEFAULT); /* set field `path' */ - setpath(L, "cpath", LUA_CPATH, LUA_CPATH_DEFAULT); /* set field `cpath' */ - /* store config information */ - lua_pushliteral(L, LUA_DIRSEP "\n" LUA_PATHSEP "\n" LUA_PATH_MARK "\n" - LUA_EXECDIR "\n" LUA_IGMARK); - lua_setfield(L, -2, "config"); - /* set field `loaded' */ - luaL_findtable(L, LUA_REGISTRYINDEX, "_LOADED", 2); - lua_setfield(L, -2, "loaded"); - /* set field `preload' */ - lua_newtable(L); - lua_setfield(L, -2, "preload"); - lua_pushvalue(L, LUA_GLOBALSINDEX); - luaL_register(L, NULL, ll_funcs); /* open lib into global table */ - lua_pop(L, 1); - return 1; /* return 'package' table */ -} - diff --git a/lib/lua-5.1/src/lobject.c b/lib/lua-5.1/src/lobject.c deleted file mode 100644 index 4ff5073..0000000 --- a/lib/lua-5.1/src/lobject.c +++ /dev/null @@ -1,214 +0,0 @@ -/* -** $Id: lobject.c,v 2.22.1.1 2007/12/27 13:02:25 roberto Exp $ -** Some generic functions over Lua objects -** See Copyright Notice in lua.h -*/ - -#include -#include -#include -#include -#include - -#define lobject_c -#define LUA_CORE - -#include "lua.h" - -#include "ldo.h" -#include "lmem.h" -#include "lobject.h" -#include "lstate.h" -#include "lstring.h" -#include "lvm.h" - - - -const TValue luaO_nilobject_ = {{NULL}, LUA_TNIL}; - - -/* -** converts an integer to a "floating point byte", represented as -** (eeeeexxx), where the real value is (1xxx) * 2^(eeeee - 1) if -** eeeee != 0 and (xxx) otherwise. -*/ -int luaO_int2fb (unsigned int x) { - int e = 0; /* expoent */ - while (x >= 16) { - x = (x+1) >> 1; - e++; - } - if (x < 8) return x; - else return ((e+1) << 3) | (cast_int(x) - 8); -} - - -/* converts back */ -int luaO_fb2int (int x) { - int e = (x >> 3) & 31; - if (e == 0) return x; - else return ((x & 7)+8) << (e - 1); -} - - -int luaO_log2 (unsigned int x) { - static const lu_byte log_2[256] = { - 0,1,2,2,3,3,3,3,4,4,4,4,4,4,4,4,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5, - 6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6, - 7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7, - 7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7, - 8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8, - 8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8, - 8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8, - 8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8 - }; - int l = -1; - while (x >= 256) { l += 8; x >>= 8; } - return l + log_2[x]; - -} - - -int luaO_rawequalObj (const TValue *t1, const TValue *t2) { - if (ttype(t1) != ttype(t2)) return 0; - else switch (ttype(t1)) { - case LUA_TNIL: - return 1; - case LUA_TNUMBER: - return luai_numeq(nvalue(t1), nvalue(t2)); - case LUA_TBOOLEAN: - return bvalue(t1) == bvalue(t2); /* boolean true must be 1 !! */ - case LUA_TLIGHTUSERDATA: - return pvalue(t1) == pvalue(t2); - default: - lua_assert(iscollectable(t1)); - return gcvalue(t1) == gcvalue(t2); - } -} - - -int luaO_str2d (const char *s, lua_Number *result) { - char *endptr; - *result = lua_str2number(s, &endptr); - if (endptr == s) return 0; /* conversion failed */ - if (*endptr == 'x' || *endptr == 'X') /* maybe an hexadecimal constant? */ - *result = cast_num(strtoul(s, &endptr, 16)); - if (*endptr == '\0') return 1; /* most common case */ - while (isspace(cast(unsigned char, *endptr))) endptr++; - if (*endptr != '\0') return 0; /* invalid trailing characters? */ - return 1; -} - - - -static void pushstr (lua_State *L, const char *str) { - setsvalue2s(L, L->top, luaS_new(L, str)); - incr_top(L); -} - - -/* this function handles only `%d', `%c', %f, %p, and `%s' formats */ -const char *luaO_pushvfstring (lua_State *L, const char *fmt, va_list argp) { - int n = 1; - pushstr(L, ""); - for (;;) { - const char *e = strchr(fmt, '%'); - if (e == NULL) break; - setsvalue2s(L, L->top, luaS_newlstr(L, fmt, e-fmt)); - incr_top(L); - switch (*(e+1)) { - case 's': { - const char *s = va_arg(argp, char *); - if (s == NULL) s = "(null)"; - pushstr(L, s); - break; - } - case 'c': { - char buff[2]; - buff[0] = cast(char, va_arg(argp, int)); - buff[1] = '\0'; - pushstr(L, buff); - break; - } - case 'd': { - setnvalue(L->top, cast_num(va_arg(argp, int))); - incr_top(L); - break; - } - case 'f': { - setnvalue(L->top, cast_num(va_arg(argp, l_uacNumber))); - incr_top(L); - break; - } - case 'p': { - char buff[4*sizeof(void *) + 8]; /* should be enough space for a `%p' */ - sprintf(buff, "%p", va_arg(argp, void *)); - pushstr(L, buff); - break; - } - case '%': { - pushstr(L, "%"); - break; - } - default: { - char buff[3]; - buff[0] = '%'; - buff[1] = *(e+1); - buff[2] = '\0'; - pushstr(L, buff); - break; - } - } - n += 2; - fmt = e+2; - } - pushstr(L, fmt); - luaV_concat(L, n+1, cast_int(L->top - L->base) - 1); - L->top -= n; - return svalue(L->top - 1); -} - - -const char *luaO_pushfstring (lua_State *L, const char *fmt, ...) { - const char *msg; - va_list argp; - va_start(argp, fmt); - msg = luaO_pushvfstring(L, fmt, argp); - va_end(argp); - return msg; -} - - -void luaO_chunkid (char *out, const char *source, size_t bufflen) { - if (*source == '=') { - strncpy(out, source+1, bufflen); /* remove first char */ - out[bufflen-1] = '\0'; /* ensures null termination */ - } - else { /* out = "source", or "...source" */ - if (*source == '@') { - size_t l; - source++; /* skip the `@' */ - bufflen -= sizeof(" '...' "); - l = strlen(source); - strcpy(out, ""); - if (l > bufflen) { - source += (l-bufflen); /* get last part of file name */ - strcat(out, "..."); - } - strcat(out, source); - } - else { /* out = [string "string"] */ - size_t len = strcspn(source, "\n\r"); /* stop at first newline */ - bufflen -= sizeof(" [string \"...\"] "); - if (len > bufflen) len = bufflen; - strcpy(out, "[string \""); - if (source[len] != '\0') { /* must truncate? */ - strncat(out, source, len); - strcat(out, "..."); - } - else - strcat(out, source); - strcat(out, "\"]"); - } - } -} diff --git a/lib/lua-5.1/src/lobject.h b/lib/lua-5.1/src/lobject.h deleted file mode 100644 index f1e447e..0000000 --- a/lib/lua-5.1/src/lobject.h +++ /dev/null @@ -1,381 +0,0 @@ -/* -** $Id: lobject.h,v 2.20.1.2 2008/08/06 13:29:48 roberto Exp $ -** Type definitions for Lua objects -** See Copyright Notice in lua.h -*/ - - -#ifndef lobject_h -#define lobject_h - - -#include - - -#include "llimits.h" -#include "lua.h" - - -/* tags for values visible from Lua */ -#define LAST_TAG LUA_TTHREAD - -#define NUM_TAGS (LAST_TAG+1) - - -/* -** Extra tags for non-values -*/ -#define LUA_TPROTO (LAST_TAG+1) -#define LUA_TUPVAL (LAST_TAG+2) -#define LUA_TDEADKEY (LAST_TAG+3) - - -/* -** Union of all collectable objects -*/ -typedef union GCObject GCObject; - - -/* -** Common Header for all collectable objects (in macro form, to be -** included in other objects) -*/ -#define CommonHeader GCObject *next; lu_byte tt; lu_byte marked - - -/* -** Common header in struct form -*/ -typedef struct GCheader { - CommonHeader; -} GCheader; - - - - -/* -** Union of all Lua values -*/ -typedef union { - GCObject *gc; - void *p; - lua_Number n; - int b; -} Value; - - -/* -** Tagged Values -*/ - -#define TValuefields Value value; int tt - -typedef struct lua_TValue { - TValuefields; -} TValue; - - -/* Macros to test type */ -#define ttisnil(o) (ttype(o) == LUA_TNIL) -#define ttisnumber(o) (ttype(o) == LUA_TNUMBER) -#define ttisstring(o) (ttype(o) == LUA_TSTRING) -#define ttistable(o) (ttype(o) == LUA_TTABLE) -#define ttisfunction(o) (ttype(o) == LUA_TFUNCTION) -#define ttisboolean(o) (ttype(o) == LUA_TBOOLEAN) -#define ttisuserdata(o) (ttype(o) == LUA_TUSERDATA) -#define ttisthread(o) (ttype(o) == LUA_TTHREAD) -#define ttislightuserdata(o) (ttype(o) == LUA_TLIGHTUSERDATA) - -/* Macros to access values */ -#define ttype(o) ((o)->tt) -#define gcvalue(o) check_exp(iscollectable(o), (o)->value.gc) -#define pvalue(o) check_exp(ttislightuserdata(o), (o)->value.p) -#define nvalue(o) check_exp(ttisnumber(o), (o)->value.n) -#define rawtsvalue(o) check_exp(ttisstring(o), &(o)->value.gc->ts) -#define tsvalue(o) (&rawtsvalue(o)->tsv) -#define rawuvalue(o) check_exp(ttisuserdata(o), &(o)->value.gc->u) -#define uvalue(o) (&rawuvalue(o)->uv) -#define clvalue(o) check_exp(ttisfunction(o), &(o)->value.gc->cl) -#define hvalue(o) check_exp(ttistable(o), &(o)->value.gc->h) -#define bvalue(o) check_exp(ttisboolean(o), (o)->value.b) -#define thvalue(o) check_exp(ttisthread(o), &(o)->value.gc->th) - -#define l_isfalse(o) (ttisnil(o) || (ttisboolean(o) && bvalue(o) == 0)) - -/* -** for internal debug only -*/ -#define checkconsistency(obj) \ - lua_assert(!iscollectable(obj) || (ttype(obj) == (obj)->value.gc->gch.tt)) - -#define checkliveness(g,obj) \ - lua_assert(!iscollectable(obj) || \ - ((ttype(obj) == (obj)->value.gc->gch.tt) && !isdead(g, (obj)->value.gc))) - - -/* Macros to set values */ -#define setnilvalue(obj) ((obj)->tt=LUA_TNIL) - -#define setnvalue(obj,x) \ - { TValue *i_o=(obj); i_o->value.n=(x); i_o->tt=LUA_TNUMBER; } - -#define setpvalue(obj,x) \ - { TValue *i_o=(obj); i_o->value.p=(x); i_o->tt=LUA_TLIGHTUSERDATA; } - -#define setbvalue(obj,x) \ - { TValue *i_o=(obj); i_o->value.b=(x); i_o->tt=LUA_TBOOLEAN; } - -#define setsvalue(L,obj,x) \ - { TValue *i_o=(obj); \ - i_o->value.gc=cast(GCObject *, (x)); i_o->tt=LUA_TSTRING; \ - checkliveness(G(L),i_o); } - -#define setuvalue(L,obj,x) \ - { TValue *i_o=(obj); \ - i_o->value.gc=cast(GCObject *, (x)); i_o->tt=LUA_TUSERDATA; \ - checkliveness(G(L),i_o); } - -#define setthvalue(L,obj,x) \ - { TValue *i_o=(obj); \ - i_o->value.gc=cast(GCObject *, (x)); i_o->tt=LUA_TTHREAD; \ - checkliveness(G(L),i_o); } - -#define setclvalue(L,obj,x) \ - { TValue *i_o=(obj); \ - i_o->value.gc=cast(GCObject *, (x)); i_o->tt=LUA_TFUNCTION; \ - checkliveness(G(L),i_o); } - -#define sethvalue(L,obj,x) \ - { TValue *i_o=(obj); \ - i_o->value.gc=cast(GCObject *, (x)); i_o->tt=LUA_TTABLE; \ - checkliveness(G(L),i_o); } - -#define setptvalue(L,obj,x) \ - { TValue *i_o=(obj); \ - i_o->value.gc=cast(GCObject *, (x)); i_o->tt=LUA_TPROTO; \ - checkliveness(G(L),i_o); } - - - - -#define setobj(L,obj1,obj2) \ - { const TValue *o2=(obj2); TValue *o1=(obj1); \ - o1->value = o2->value; o1->tt=o2->tt; \ - checkliveness(G(L),o1); } - - -/* -** different types of sets, according to destination -*/ - -/* from stack to (same) stack */ -#define setobjs2s setobj -/* to stack (not from same stack) */ -#define setobj2s setobj -#define setsvalue2s setsvalue -#define sethvalue2s sethvalue -#define setptvalue2s setptvalue -/* from table to same table */ -#define setobjt2t setobj -/* to table */ -#define setobj2t setobj -/* to new object */ -#define setobj2n setobj -#define setsvalue2n setsvalue - -#define setttype(obj, tt) (ttype(obj) = (tt)) - - -#define iscollectable(o) (ttype(o) >= LUA_TSTRING) - - - -typedef TValue *StkId; /* index to stack elements */ - - -/* -** String headers for string table -*/ -typedef union TString { - L_Umaxalign dummy; /* ensures maximum alignment for strings */ - struct { - CommonHeader; - lu_byte reserved; - unsigned int hash; - size_t len; - } tsv; -} TString; - - -#define getstr(ts) cast(const char *, (ts) + 1) -#define svalue(o) getstr(rawtsvalue(o)) - - - -typedef union Udata { - L_Umaxalign dummy; /* ensures maximum alignment for `local' udata */ - struct { - CommonHeader; - struct Table *metatable; - struct Table *env; - size_t len; - } uv; -} Udata; - - - - -/* -** Function Prototypes -*/ -typedef struct Proto { - CommonHeader; - TValue *k; /* constants used by the function */ - Instruction *code; - struct Proto **p; /* functions defined inside the function */ - int *lineinfo; /* map from opcodes to source lines */ - struct LocVar *locvars; /* information about local variables */ - TString **upvalues; /* upvalue names */ - TString *source; - int sizeupvalues; - int sizek; /* size of `k' */ - int sizecode; - int sizelineinfo; - int sizep; /* size of `p' */ - int sizelocvars; - int linedefined; - int lastlinedefined; - GCObject *gclist; - lu_byte nups; /* number of upvalues */ - lu_byte numparams; - lu_byte is_vararg; - lu_byte maxstacksize; -} Proto; - - -/* masks for new-style vararg */ -#define VARARG_HASARG 1 -#define VARARG_ISVARARG 2 -#define VARARG_NEEDSARG 4 - - -typedef struct LocVar { - TString *varname; - int startpc; /* first point where variable is active */ - int endpc; /* first point where variable is dead */ -} LocVar; - - - -/* -** Upvalues -*/ - -typedef struct UpVal { - CommonHeader; - TValue *v; /* points to stack or to its own value */ - union { - TValue value; /* the value (when closed) */ - struct { /* double linked list (when open) */ - struct UpVal *prev; - struct UpVal *next; - } l; - } u; -} UpVal; - - -/* -** Closures -*/ - -#define ClosureHeader \ - CommonHeader; lu_byte isC; lu_byte nupvalues; GCObject *gclist; \ - struct Table *env - -typedef struct CClosure { - ClosureHeader; - lua_CFunction f; - TValue upvalue[1]; -} CClosure; - - -typedef struct LClosure { - ClosureHeader; - struct Proto *p; - UpVal *upvals[1]; -} LClosure; - - -typedef union Closure { - CClosure c; - LClosure l; -} Closure; - - -#define iscfunction(o) (ttype(o) == LUA_TFUNCTION && clvalue(o)->c.isC) -#define isLfunction(o) (ttype(o) == LUA_TFUNCTION && !clvalue(o)->c.isC) - - -/* -** Tables -*/ - -typedef union TKey { - struct { - TValuefields; - struct Node *next; /* for chaining */ - } nk; - TValue tvk; -} TKey; - - -typedef struct Node { - TValue i_val; - TKey i_key; -} Node; - - -typedef struct Table { - CommonHeader; - lu_byte flags; /* 1<

lsizenode)) - - -#define luaO_nilobject (&luaO_nilobject_) - -LUAI_DATA const TValue luaO_nilobject_; - -#define ceillog2(x) (luaO_log2((x)-1) + 1) - -LUAI_FUNC int luaO_log2 (unsigned int x); -LUAI_FUNC int luaO_int2fb (unsigned int x); -LUAI_FUNC int luaO_fb2int (int x); -LUAI_FUNC int luaO_rawequalObj (const TValue *t1, const TValue *t2); -LUAI_FUNC int luaO_str2d (const char *s, lua_Number *result); -LUAI_FUNC const char *luaO_pushvfstring (lua_State *L, const char *fmt, - va_list argp); -LUAI_FUNC const char *luaO_pushfstring (lua_State *L, const char *fmt, ...); -LUAI_FUNC void luaO_chunkid (char *out, const char *source, size_t len); - - -#endif - diff --git a/lib/lua-5.1/src/lopcodes.c b/lib/lua-5.1/src/lopcodes.c deleted file mode 100644 index 4cc7452..0000000 --- a/lib/lua-5.1/src/lopcodes.c +++ /dev/null @@ -1,102 +0,0 @@ -/* -** $Id: lopcodes.c,v 1.37.1.1 2007/12/27 13:02:25 roberto Exp $ -** See Copyright Notice in lua.h -*/ - - -#define lopcodes_c -#define LUA_CORE - - -#include "lopcodes.h" - - -/* ORDER OP */ - -const char *const luaP_opnames[NUM_OPCODES+1] = { - "MOVE", - "LOADK", - "LOADBOOL", - "LOADNIL", - "GETUPVAL", - "GETGLOBAL", - "GETTABLE", - "SETGLOBAL", - "SETUPVAL", - "SETTABLE", - "NEWTABLE", - "SELF", - "ADD", - "SUB", - "MUL", - "DIV", - "MOD", - "POW", - "UNM", - "NOT", - "LEN", - "CONCAT", - "JMP", - "EQ", - "LT", - "LE", - "TEST", - "TESTSET", - "CALL", - "TAILCALL", - "RETURN", - "FORLOOP", - "FORPREP", - "TFORLOOP", - "SETLIST", - "CLOSE", - "CLOSURE", - "VARARG", - NULL -}; - - -#define opmode(t,a,b,c,m) (((t)<<7) | ((a)<<6) | ((b)<<4) | ((c)<<2) | (m)) - -const lu_byte luaP_opmodes[NUM_OPCODES] = { -/* T A B C mode opcode */ - opmode(0, 1, OpArgR, OpArgN, iABC) /* OP_MOVE */ - ,opmode(0, 1, OpArgK, OpArgN, iABx) /* OP_LOADK */ - ,opmode(0, 1, OpArgU, OpArgU, iABC) /* OP_LOADBOOL */ - ,opmode(0, 1, OpArgR, OpArgN, iABC) /* OP_LOADNIL */ - ,opmode(0, 1, OpArgU, OpArgN, iABC) /* OP_GETUPVAL */ - ,opmode(0, 1, OpArgK, OpArgN, iABx) /* OP_GETGLOBAL */ - ,opmode(0, 1, OpArgR, OpArgK, iABC) /* OP_GETTABLE */ - ,opmode(0, 0, OpArgK, OpArgN, iABx) /* OP_SETGLOBAL */ - ,opmode(0, 0, OpArgU, OpArgN, iABC) /* OP_SETUPVAL */ - ,opmode(0, 0, OpArgK, OpArgK, iABC) /* OP_SETTABLE */ - ,opmode(0, 1, OpArgU, OpArgU, iABC) /* OP_NEWTABLE */ - ,opmode(0, 1, OpArgR, OpArgK, iABC) /* OP_SELF */ - ,opmode(0, 1, OpArgK, OpArgK, iABC) /* OP_ADD */ - ,opmode(0, 1, OpArgK, OpArgK, iABC) /* OP_SUB */ - ,opmode(0, 1, OpArgK, OpArgK, iABC) /* OP_MUL */ - ,opmode(0, 1, OpArgK, OpArgK, iABC) /* OP_DIV */ - ,opmode(0, 1, OpArgK, OpArgK, iABC) /* OP_MOD */ - ,opmode(0, 1, OpArgK, OpArgK, iABC) /* OP_POW */ - ,opmode(0, 1, OpArgR, OpArgN, iABC) /* OP_UNM */ - ,opmode(0, 1, OpArgR, OpArgN, iABC) /* OP_NOT */ - ,opmode(0, 1, OpArgR, OpArgN, iABC) /* OP_LEN */ - ,opmode(0, 1, OpArgR, OpArgR, iABC) /* OP_CONCAT */ - ,opmode(0, 0, OpArgR, OpArgN, iAsBx) /* OP_JMP */ - ,opmode(1, 0, OpArgK, OpArgK, iABC) /* OP_EQ */ - ,opmode(1, 0, OpArgK, OpArgK, iABC) /* OP_LT */ - ,opmode(1, 0, OpArgK, OpArgK, iABC) /* OP_LE */ - ,opmode(1, 1, OpArgR, OpArgU, iABC) /* OP_TEST */ - ,opmode(1, 1, OpArgR, OpArgU, iABC) /* OP_TESTSET */ - ,opmode(0, 1, OpArgU, OpArgU, iABC) /* OP_CALL */ - ,opmode(0, 1, OpArgU, OpArgU, iABC) /* OP_TAILCALL */ - ,opmode(0, 0, OpArgU, OpArgN, iABC) /* OP_RETURN */ - ,opmode(0, 1, OpArgR, OpArgN, iAsBx) /* OP_FORLOOP */ - ,opmode(0, 1, OpArgR, OpArgN, iAsBx) /* OP_FORPREP */ - ,opmode(1, 0, OpArgN, OpArgU, iABC) /* OP_TFORLOOP */ - ,opmode(0, 0, OpArgU, OpArgU, iABC) /* OP_SETLIST */ - ,opmode(0, 0, OpArgN, OpArgN, iABC) /* OP_CLOSE */ - ,opmode(0, 1, OpArgU, OpArgN, iABx) /* OP_CLOSURE */ - ,opmode(0, 1, OpArgU, OpArgN, iABC) /* OP_VARARG */ -}; - diff --git a/lib/lua-5.1/src/lopcodes.h b/lib/lua-5.1/src/lopcodes.h deleted file mode 100644 index 41224d6..0000000 --- a/lib/lua-5.1/src/lopcodes.h +++ /dev/null @@ -1,268 +0,0 @@ -/* -** $Id: lopcodes.h,v 1.125.1.1 2007/12/27 13:02:25 roberto Exp $ -** Opcodes for Lua virtual machine -** See Copyright Notice in lua.h -*/ - -#ifndef lopcodes_h -#define lopcodes_h - -#include "llimits.h" - - -/*=========================================================================== - We assume that instructions are unsigned numbers. - All instructions have an opcode in the first 6 bits. - Instructions can have the following fields: - `A' : 8 bits - `B' : 9 bits - `C' : 9 bits - `Bx' : 18 bits (`B' and `C' together) - `sBx' : signed Bx - - A signed argument is represented in excess K; that is, the number - value is the unsigned value minus K. K is exactly the maximum value - for that argument (so that -max is represented by 0, and +max is - represented by 2*max), which is half the maximum for the corresponding - unsigned argument. -===========================================================================*/ - - -enum OpMode {iABC, iABx, iAsBx}; /* basic instruction format */ - - -/* -** size and position of opcode arguments. -*/ -#define SIZE_C 9 -#define SIZE_B 9 -#define SIZE_Bx (SIZE_C + SIZE_B) -#define SIZE_A 8 - -#define SIZE_OP 6 - -#define POS_OP 0 -#define POS_A (POS_OP + SIZE_OP) -#define POS_C (POS_A + SIZE_A) -#define POS_B (POS_C + SIZE_C) -#define POS_Bx POS_C - - -/* -** limits for opcode arguments. -** we use (signed) int to manipulate most arguments, -** so they must fit in LUAI_BITSINT-1 bits (-1 for sign) -*/ -#if SIZE_Bx < LUAI_BITSINT-1 -#define MAXARG_Bx ((1<>1) /* `sBx' is signed */ -#else -#define MAXARG_Bx MAX_INT -#define MAXARG_sBx MAX_INT -#endif - - -#define MAXARG_A ((1<>POS_OP) & MASK1(SIZE_OP,0))) -#define SET_OPCODE(i,o) ((i) = (((i)&MASK0(SIZE_OP,POS_OP)) | \ - ((cast(Instruction, o)<>POS_A) & MASK1(SIZE_A,0))) -#define SETARG_A(i,u) ((i) = (((i)&MASK0(SIZE_A,POS_A)) | \ - ((cast(Instruction, u)<>POS_B) & MASK1(SIZE_B,0))) -#define SETARG_B(i,b) ((i) = (((i)&MASK0(SIZE_B,POS_B)) | \ - ((cast(Instruction, b)<>POS_C) & MASK1(SIZE_C,0))) -#define SETARG_C(i,b) ((i) = (((i)&MASK0(SIZE_C,POS_C)) | \ - ((cast(Instruction, b)<>POS_Bx) & MASK1(SIZE_Bx,0))) -#define SETARG_Bx(i,b) ((i) = (((i)&MASK0(SIZE_Bx,POS_Bx)) | \ - ((cast(Instruction, b)< C) then pc++ */ -OP_TESTSET,/* A B C if (R(B) <=> C) then R(A) := R(B) else pc++ */ - -OP_CALL,/* A B C R(A), ... ,R(A+C-2) := R(A)(R(A+1), ... ,R(A+B-1)) */ -OP_TAILCALL,/* A B C return R(A)(R(A+1), ... ,R(A+B-1)) */ -OP_RETURN,/* A B return R(A), ... ,R(A+B-2) (see note) */ - -OP_FORLOOP,/* A sBx R(A)+=R(A+2); - if R(A) =) R(A)*/ -OP_CLOSURE,/* A Bx R(A) := closure(KPROTO[Bx], R(A), ... ,R(A+n)) */ - -OP_VARARG/* A B R(A), R(A+1), ..., R(A+B-1) = vararg */ -} OpCode; - - -#define NUM_OPCODES (cast(int, OP_VARARG) + 1) - - - -/*=========================================================================== - Notes: - (*) In OP_CALL, if (B == 0) then B = top. C is the number of returns - 1, - and can be 0: OP_CALL then sets `top' to last_result+1, so - next open instruction (OP_CALL, OP_RETURN, OP_SETLIST) may use `top'. - - (*) In OP_VARARG, if (B == 0) then use actual number of varargs and - set top (like in OP_CALL with C == 0). - - (*) In OP_RETURN, if (B == 0) then return up to `top' - - (*) In OP_SETLIST, if (B == 0) then B = `top'; - if (C == 0) then next `instruction' is real C - - (*) For comparisons, A specifies what condition the test should accept - (true or false). - - (*) All `skips' (pc++) assume that next instruction is a jump -===========================================================================*/ - - -/* -** masks for instruction properties. The format is: -** bits 0-1: op mode -** bits 2-3: C arg mode -** bits 4-5: B arg mode -** bit 6: instruction set register A -** bit 7: operator is a test -*/ - -enum OpArgMask { - OpArgN, /* argument is not used */ - OpArgU, /* argument is used */ - OpArgR, /* argument is a register or a jump offset */ - OpArgK /* argument is a constant or register/constant */ -}; - -LUAI_DATA const lu_byte luaP_opmodes[NUM_OPCODES]; - -#define getOpMode(m) (cast(enum OpMode, luaP_opmodes[m] & 3)) -#define getBMode(m) (cast(enum OpArgMask, (luaP_opmodes[m] >> 4) & 3)) -#define getCMode(m) (cast(enum OpArgMask, (luaP_opmodes[m] >> 2) & 3)) -#define testAMode(m) (luaP_opmodes[m] & (1 << 6)) -#define testTMode(m) (luaP_opmodes[m] & (1 << 7)) - - -LUAI_DATA const char *const luaP_opnames[NUM_OPCODES+1]; /* opcode names */ - - -/* number of list items to accumulate before a SETLIST instruction */ -#define LFIELDS_PER_FLUSH 50 - - -#endif diff --git a/lib/lua-5.1/src/loslib.c b/lib/lua-5.1/src/loslib.c deleted file mode 100644 index da06a57..0000000 --- a/lib/lua-5.1/src/loslib.c +++ /dev/null @@ -1,243 +0,0 @@ -/* -** $Id: loslib.c,v 1.19.1.3 2008/01/18 16:38:18 roberto Exp $ -** Standard Operating System library -** See Copyright Notice in lua.h -*/ - - -#include -#include -#include -#include -#include - -#define loslib_c -#define LUA_LIB - -#include "lua.h" - -#include "lauxlib.h" -#include "lualib.h" - - -static int os_pushresult (lua_State *L, int i, const char *filename) { - int en = errno; /* calls to Lua API may change this value */ - if (i) { - lua_pushboolean(L, 1); - return 1; - } - else { - lua_pushnil(L); - lua_pushfstring(L, "%s: %s", filename, strerror(en)); - lua_pushinteger(L, en); - return 3; - } -} - - -static int os_execute (lua_State *L) { - lua_pushinteger(L, system(luaL_optstring(L, 1, NULL))); - return 1; -} - - -static int os_remove (lua_State *L) { - const char *filename = luaL_checkstring(L, 1); - return os_pushresult(L, remove(filename) == 0, filename); -} - - -static int os_rename (lua_State *L) { - const char *fromname = luaL_checkstring(L, 1); - const char *toname = luaL_checkstring(L, 2); - return os_pushresult(L, rename(fromname, toname) == 0, fromname); -} - - -static int os_tmpname (lua_State *L) { - char buff[LUA_TMPNAMBUFSIZE]; - int err; - lua_tmpnam(buff, err); - if (err) - return luaL_error(L, "unable to generate a unique filename"); - lua_pushstring(L, buff); - return 1; -} - - -static int os_getenv (lua_State *L) { - lua_pushstring(L, getenv(luaL_checkstring(L, 1))); /* if NULL push nil */ - return 1; -} - - -static int os_clock (lua_State *L) { - lua_pushnumber(L, ((lua_Number)clock())/(lua_Number)CLOCKS_PER_SEC); - return 1; -} - - -/* -** {====================================================== -** Time/Date operations -** { year=%Y, month=%m, day=%d, hour=%H, min=%M, sec=%S, -** wday=%w+1, yday=%j, isdst=? } -** ======================================================= -*/ - -static void setfield (lua_State *L, const char *key, int value) { - lua_pushinteger(L, value); - lua_setfield(L, -2, key); -} - -static void setboolfield (lua_State *L, const char *key, int value) { - if (value < 0) /* undefined? */ - return; /* does not set field */ - lua_pushboolean(L, value); - lua_setfield(L, -2, key); -} - -static int getboolfield (lua_State *L, const char *key) { - int res; - lua_getfield(L, -1, key); - res = lua_isnil(L, -1) ? -1 : lua_toboolean(L, -1); - lua_pop(L, 1); - return res; -} - - -static int getfield (lua_State *L, const char *key, int d) { - int res; - lua_getfield(L, -1, key); - if (lua_isnumber(L, -1)) - res = (int)lua_tointeger(L, -1); - else { - if (d < 0) - return luaL_error(L, "field " LUA_QS " missing in date table", key); - res = d; - } - lua_pop(L, 1); - return res; -} - - -static int os_date (lua_State *L) { - const char *s = luaL_optstring(L, 1, "%c"); - time_t t = luaL_opt(L, (time_t)luaL_checknumber, 2, time(NULL)); - struct tm *stm; - if (*s == '!') { /* UTC? */ - stm = gmtime(&t); - s++; /* skip `!' */ - } - else - stm = localtime(&t); - if (stm == NULL) /* invalid date? */ - lua_pushnil(L); - else if (strcmp(s, "*t") == 0) { - lua_createtable(L, 0, 9); /* 9 = number of fields */ - setfield(L, "sec", stm->tm_sec); - setfield(L, "min", stm->tm_min); - setfield(L, "hour", stm->tm_hour); - setfield(L, "day", stm->tm_mday); - setfield(L, "month", stm->tm_mon+1); - setfield(L, "year", stm->tm_year+1900); - setfield(L, "wday", stm->tm_wday+1); - setfield(L, "yday", stm->tm_yday+1); - setboolfield(L, "isdst", stm->tm_isdst); - } - else { - char cc[3]; - luaL_Buffer b; - cc[0] = '%'; cc[2] = '\0'; - luaL_buffinit(L, &b); - for (; *s; s++) { - if (*s != '%' || *(s + 1) == '\0') /* no conversion specifier? */ - luaL_addchar(&b, *s); - else { - size_t reslen; - char buff[200]; /* should be big enough for any conversion result */ - cc[1] = *(++s); - reslen = strftime(buff, sizeof(buff), cc, stm); - luaL_addlstring(&b, buff, reslen); - } - } - luaL_pushresult(&b); - } - return 1; -} - - -static int os_time (lua_State *L) { - time_t t; - if (lua_isnoneornil(L, 1)) /* called without args? */ - t = time(NULL); /* get current time */ - else { - struct tm ts; - luaL_checktype(L, 1, LUA_TTABLE); - lua_settop(L, 1); /* make sure table is at the top */ - ts.tm_sec = getfield(L, "sec", 0); - ts.tm_min = getfield(L, "min", 0); - ts.tm_hour = getfield(L, "hour", 12); - ts.tm_mday = getfield(L, "day", -1); - ts.tm_mon = getfield(L, "month", -1) - 1; - ts.tm_year = getfield(L, "year", -1) - 1900; - ts.tm_isdst = getboolfield(L, "isdst"); - t = mktime(&ts); - } - if (t == (time_t)(-1)) - lua_pushnil(L); - else - lua_pushnumber(L, (lua_Number)t); - return 1; -} - - -static int os_difftime (lua_State *L) { - lua_pushnumber(L, difftime((time_t)(luaL_checknumber(L, 1)), - (time_t)(luaL_optnumber(L, 2, 0)))); - return 1; -} - -/* }====================================================== */ - - -static int os_setlocale (lua_State *L) { - static const int cat[] = {LC_ALL, LC_COLLATE, LC_CTYPE, LC_MONETARY, - LC_NUMERIC, LC_TIME}; - static const char *const catnames[] = {"all", "collate", "ctype", "monetary", - "numeric", "time", NULL}; - const char *l = luaL_optstring(L, 1, NULL); - int op = luaL_checkoption(L, 2, "all", catnames); - lua_pushstring(L, setlocale(cat[op], l)); - return 1; -} - - -static int os_exit (lua_State *L) { - exit(luaL_optint(L, 1, EXIT_SUCCESS)); -} - -static const luaL_Reg syslib[] = { - {"clock", os_clock}, - {"date", os_date}, - {"difftime", os_difftime}, - {"execute", os_execute}, - {"exit", os_exit}, - {"getenv", os_getenv}, - {"remove", os_remove}, - {"rename", os_rename}, - {"setlocale", os_setlocale}, - {"time", os_time}, - {"tmpname", os_tmpname}, - {NULL, NULL} -}; - -/* }====================================================== */ - - - -LUALIB_API int luaopen_os (lua_State *L) { - luaL_register(L, LUA_OSLIBNAME, syslib); - return 1; -} - diff --git a/lib/lua-5.1/src/lparser.c b/lib/lua-5.1/src/lparser.c deleted file mode 100644 index dda7488..0000000 --- a/lib/lua-5.1/src/lparser.c +++ /dev/null @@ -1,1339 +0,0 @@ -/* -** $Id: lparser.c,v 2.42.1.4 2011/10/21 19:31:42 roberto Exp $ -** Lua Parser -** See Copyright Notice in lua.h -*/ - - -#include - -#define lparser_c -#define LUA_CORE - -#include "lua.h" - -#include "lcode.h" -#include "ldebug.h" -#include "ldo.h" -#include "lfunc.h" -#include "llex.h" -#include "lmem.h" -#include "lobject.h" -#include "lopcodes.h" -#include "lparser.h" -#include "lstate.h" -#include "lstring.h" -#include "ltable.h" - - - -#define hasmultret(k) ((k) == VCALL || (k) == VVARARG) - -#define getlocvar(fs, i) ((fs)->f->locvars[(fs)->actvar[i]]) - -#define luaY_checklimit(fs,v,l,m) if ((v)>(l)) errorlimit(fs,l,m) - - -/* -** nodes for block list (list of active blocks) -*/ -typedef struct BlockCnt { - struct BlockCnt *previous; /* chain */ - int breaklist; /* list of jumps out of this loop */ - lu_byte nactvar; /* # active locals outside the breakable structure */ - lu_byte upval; /* true if some variable in the block is an upvalue */ - lu_byte isbreakable; /* true if `block' is a loop */ -} BlockCnt; - - - -/* -** prototypes for recursive non-terminal functions -*/ -static void chunk (LexState *ls); -static void expr (LexState *ls, expdesc *v); - - -static void anchor_token (LexState *ls) { - if (ls->t.token == TK_NAME || ls->t.token == TK_STRING) { - TString *ts = ls->t.seminfo.ts; - luaX_newstring(ls, getstr(ts), ts->tsv.len); - } -} - - -static void error_expected (LexState *ls, int token) { - luaX_syntaxerror(ls, - luaO_pushfstring(ls->L, LUA_QS " expected", luaX_token2str(ls, token))); -} - - -static void errorlimit (FuncState *fs, int limit, const char *what) { - const char *msg = (fs->f->linedefined == 0) ? - luaO_pushfstring(fs->L, "main function has more than %d %s", limit, what) : - luaO_pushfstring(fs->L, "function at line %d has more than %d %s", - fs->f->linedefined, limit, what); - luaX_lexerror(fs->ls, msg, 0); -} - - -static int testnext (LexState *ls, int c) { - if (ls->t.token == c) { - luaX_next(ls); - return 1; - } - else return 0; -} - - -static void check (LexState *ls, int c) { - if (ls->t.token != c) - error_expected(ls, c); -} - -static void checknext (LexState *ls, int c) { - check(ls, c); - luaX_next(ls); -} - - -#define check_condition(ls,c,msg) { if (!(c)) luaX_syntaxerror(ls, msg); } - - - -static void check_match (LexState *ls, int what, int who, int where) { - if (!testnext(ls, what)) { - if (where == ls->linenumber) - error_expected(ls, what); - else { - luaX_syntaxerror(ls, luaO_pushfstring(ls->L, - LUA_QS " expected (to close " LUA_QS " at line %d)", - luaX_token2str(ls, what), luaX_token2str(ls, who), where)); - } - } -} - - -static TString *str_checkname (LexState *ls) { - TString *ts; - check(ls, TK_NAME); - ts = ls->t.seminfo.ts; - luaX_next(ls); - return ts; -} - - -static void init_exp (expdesc *e, expkind k, int i) { - e->f = e->t = NO_JUMP; - e->k = k; - e->u.s.info = i; -} - - -static void codestring (LexState *ls, expdesc *e, TString *s) { - init_exp(e, VK, luaK_stringK(ls->fs, s)); -} - - -static void checkname(LexState *ls, expdesc *e) { - codestring(ls, e, str_checkname(ls)); -} - - -static int registerlocalvar (LexState *ls, TString *varname) { - FuncState *fs = ls->fs; - Proto *f = fs->f; - int oldsize = f->sizelocvars; - luaM_growvector(ls->L, f->locvars, fs->nlocvars, f->sizelocvars, - LocVar, SHRT_MAX, "too many local variables"); - while (oldsize < f->sizelocvars) f->locvars[oldsize++].varname = NULL; - f->locvars[fs->nlocvars].varname = varname; - luaC_objbarrier(ls->L, f, varname); - return fs->nlocvars++; -} - - -#define new_localvarliteral(ls,v,n) \ - new_localvar(ls, luaX_newstring(ls, "" v, (sizeof(v)/sizeof(char))-1), n) - - -static void new_localvar (LexState *ls, TString *name, int n) { - FuncState *fs = ls->fs; - luaY_checklimit(fs, fs->nactvar+n+1, LUAI_MAXVARS, "local variables"); - fs->actvar[fs->nactvar+n] = cast(unsigned short, registerlocalvar(ls, name)); -} - - -static void adjustlocalvars (LexState *ls, int nvars) { - FuncState *fs = ls->fs; - fs->nactvar = cast_byte(fs->nactvar + nvars); - for (; nvars; nvars--) { - getlocvar(fs, fs->nactvar - nvars).startpc = fs->pc; - } -} - - -static void removevars (LexState *ls, int tolevel) { - FuncState *fs = ls->fs; - while (fs->nactvar > tolevel) - getlocvar(fs, --fs->nactvar).endpc = fs->pc; -} - - -static int indexupvalue (FuncState *fs, TString *name, expdesc *v) { - int i; - Proto *f = fs->f; - int oldsize = f->sizeupvalues; - for (i=0; inups; i++) { - if (fs->upvalues[i].k == v->k && fs->upvalues[i].info == v->u.s.info) { - lua_assert(f->upvalues[i] == name); - return i; - } - } - /* new one */ - luaY_checklimit(fs, f->nups + 1, LUAI_MAXUPVALUES, "upvalues"); - luaM_growvector(fs->L, f->upvalues, f->nups, f->sizeupvalues, - TString *, MAX_INT, ""); - while (oldsize < f->sizeupvalues) f->upvalues[oldsize++] = NULL; - f->upvalues[f->nups] = name; - luaC_objbarrier(fs->L, f, name); - lua_assert(v->k == VLOCAL || v->k == VUPVAL); - fs->upvalues[f->nups].k = cast_byte(v->k); - fs->upvalues[f->nups].info = cast_byte(v->u.s.info); - return f->nups++; -} - - -static int searchvar (FuncState *fs, TString *n) { - int i; - for (i=fs->nactvar-1; i >= 0; i--) { - if (n == getlocvar(fs, i).varname) - return i; - } - return -1; /* not found */ -} - - -static void markupval (FuncState *fs, int level) { - BlockCnt *bl = fs->bl; - while (bl && bl->nactvar > level) bl = bl->previous; - if (bl) bl->upval = 1; -} - - -static int singlevaraux (FuncState *fs, TString *n, expdesc *var, int base) { - if (fs == NULL) { /* no more levels? */ - init_exp(var, VGLOBAL, NO_REG); /* default is global variable */ - return VGLOBAL; - } - else { - int v = searchvar(fs, n); /* look up at current level */ - if (v >= 0) { - init_exp(var, VLOCAL, v); - if (!base) - markupval(fs, v); /* local will be used as an upval */ - return VLOCAL; - } - else { /* not found at current level; try upper one */ - if (singlevaraux(fs->prev, n, var, 0) == VGLOBAL) - return VGLOBAL; - var->u.s.info = indexupvalue(fs, n, var); /* else was LOCAL or UPVAL */ - var->k = VUPVAL; /* upvalue in this level */ - return VUPVAL; - } - } -} - - -static void singlevar (LexState *ls, expdesc *var) { - TString *varname = str_checkname(ls); - FuncState *fs = ls->fs; - if (singlevaraux(fs, varname, var, 1) == VGLOBAL) - var->u.s.info = luaK_stringK(fs, varname); /* info points to global name */ -} - - -static void adjust_assign (LexState *ls, int nvars, int nexps, expdesc *e) { - FuncState *fs = ls->fs; - int extra = nvars - nexps; - if (hasmultret(e->k)) { - extra++; /* includes call itself */ - if (extra < 0) extra = 0; - luaK_setreturns(fs, e, extra); /* last exp. provides the difference */ - if (extra > 1) luaK_reserveregs(fs, extra-1); - } - else { - if (e->k != VVOID) luaK_exp2nextreg(fs, e); /* close last expression */ - if (extra > 0) { - int reg = fs->freereg; - luaK_reserveregs(fs, extra); - luaK_nil(fs, reg, extra); - } - } -} - - -static void enterlevel (LexState *ls) { - if (++ls->L->nCcalls > LUAI_MAXCCALLS) - luaX_lexerror(ls, "chunk has too many syntax levels", 0); -} - - -#define leavelevel(ls) ((ls)->L->nCcalls--) - - -static void enterblock (FuncState *fs, BlockCnt *bl, lu_byte isbreakable) { - bl->breaklist = NO_JUMP; - bl->isbreakable = isbreakable; - bl->nactvar = fs->nactvar; - bl->upval = 0; - bl->previous = fs->bl; - fs->bl = bl; - lua_assert(fs->freereg == fs->nactvar); -} - - -static void leaveblock (FuncState *fs) { - BlockCnt *bl = fs->bl; - fs->bl = bl->previous; - removevars(fs->ls, bl->nactvar); - if (bl->upval) - luaK_codeABC(fs, OP_CLOSE, bl->nactvar, 0, 0); - /* a block either controls scope or breaks (never both) */ - lua_assert(!bl->isbreakable || !bl->upval); - lua_assert(bl->nactvar == fs->nactvar); - fs->freereg = fs->nactvar; /* free registers */ - luaK_patchtohere(fs, bl->breaklist); -} - - -static void pushclosure (LexState *ls, FuncState *func, expdesc *v) { - FuncState *fs = ls->fs; - Proto *f = fs->f; - int oldsize = f->sizep; - int i; - luaM_growvector(ls->L, f->p, fs->np, f->sizep, Proto *, - MAXARG_Bx, "constant table overflow"); - while (oldsize < f->sizep) f->p[oldsize++] = NULL; - f->p[fs->np++] = func->f; - luaC_objbarrier(ls->L, f, func->f); - init_exp(v, VRELOCABLE, luaK_codeABx(fs, OP_CLOSURE, 0, fs->np-1)); - for (i=0; if->nups; i++) { - OpCode o = (func->upvalues[i].k == VLOCAL) ? OP_MOVE : OP_GETUPVAL; - luaK_codeABC(fs, o, 0, func->upvalues[i].info, 0); - } -} - - -static void open_func (LexState *ls, FuncState *fs) { - lua_State *L = ls->L; - Proto *f = luaF_newproto(L); - fs->f = f; - fs->prev = ls->fs; /* linked list of funcstates */ - fs->ls = ls; - fs->L = L; - ls->fs = fs; - fs->pc = 0; - fs->lasttarget = -1; - fs->jpc = NO_JUMP; - fs->freereg = 0; - fs->nk = 0; - fs->np = 0; - fs->nlocvars = 0; - fs->nactvar = 0; - fs->bl = NULL; - f->source = ls->source; - f->maxstacksize = 2; /* registers 0/1 are always valid */ - fs->h = luaH_new(L, 0, 0); - /* anchor table of constants and prototype (to avoid being collected) */ - sethvalue2s(L, L->top, fs->h); - incr_top(L); - setptvalue2s(L, L->top, f); - incr_top(L); -} - - -static void close_func (LexState *ls) { - lua_State *L = ls->L; - FuncState *fs = ls->fs; - Proto *f = fs->f; - removevars(ls, 0); - luaK_ret(fs, 0, 0); /* final return */ - luaM_reallocvector(L, f->code, f->sizecode, fs->pc, Instruction); - f->sizecode = fs->pc; - luaM_reallocvector(L, f->lineinfo, f->sizelineinfo, fs->pc, int); - f->sizelineinfo = fs->pc; - luaM_reallocvector(L, f->k, f->sizek, fs->nk, TValue); - f->sizek = fs->nk; - luaM_reallocvector(L, f->p, f->sizep, fs->np, Proto *); - f->sizep = fs->np; - luaM_reallocvector(L, f->locvars, f->sizelocvars, fs->nlocvars, LocVar); - f->sizelocvars = fs->nlocvars; - luaM_reallocvector(L, f->upvalues, f->sizeupvalues, f->nups, TString *); - f->sizeupvalues = f->nups; - lua_assert(luaG_checkcode(f)); - lua_assert(fs->bl == NULL); - ls->fs = fs->prev; - /* last token read was anchored in defunct function; must reanchor it */ - if (fs) anchor_token(ls); - L->top -= 2; /* remove table and prototype from the stack */ -} - - -Proto *luaY_parser (lua_State *L, ZIO *z, Mbuffer *buff, const char *name) { - struct LexState lexstate; - struct FuncState funcstate; - lexstate.buff = buff; - luaX_setinput(L, &lexstate, z, luaS_new(L, name)); - open_func(&lexstate, &funcstate); - funcstate.f->is_vararg = VARARG_ISVARARG; /* main func. is always vararg */ - luaX_next(&lexstate); /* read first token */ - chunk(&lexstate); - check(&lexstate, TK_EOS); - close_func(&lexstate); - lua_assert(funcstate.prev == NULL); - lua_assert(funcstate.f->nups == 0); - lua_assert(lexstate.fs == NULL); - return funcstate.f; -} - - - -/*============================================================*/ -/* GRAMMAR RULES */ -/*============================================================*/ - - -static void field (LexState *ls, expdesc *v) { - /* field -> ['.' | ':'] NAME */ - FuncState *fs = ls->fs; - expdesc key; - luaK_exp2anyreg(fs, v); - luaX_next(ls); /* skip the dot or colon */ - checkname(ls, &key); - luaK_indexed(fs, v, &key); -} - - -static void yindex (LexState *ls, expdesc *v) { - /* index -> '[' expr ']' */ - luaX_next(ls); /* skip the '[' */ - expr(ls, v); - luaK_exp2val(ls->fs, v); - checknext(ls, ']'); -} - - -/* -** {====================================================================== -** Rules for Constructors -** ======================================================================= -*/ - - -struct ConsControl { - expdesc v; /* last list item read */ - expdesc *t; /* table descriptor */ - int nh; /* total number of `record' elements */ - int na; /* total number of array elements */ - int tostore; /* number of array elements pending to be stored */ -}; - - -static void recfield (LexState *ls, struct ConsControl *cc) { - /* recfield -> (NAME | `['exp1`]') = exp1 */ - FuncState *fs = ls->fs; - int reg = ls->fs->freereg; - expdesc key, val; - int rkkey; - if (ls->t.token == TK_NAME) { - luaY_checklimit(fs, cc->nh, MAX_INT, "items in a constructor"); - checkname(ls, &key); - } - else /* ls->t.token == '[' */ - yindex(ls, &key); - cc->nh++; - checknext(ls, '='); - rkkey = luaK_exp2RK(fs, &key); - expr(ls, &val); - luaK_codeABC(fs, OP_SETTABLE, cc->t->u.s.info, rkkey, luaK_exp2RK(fs, &val)); - fs->freereg = reg; /* free registers */ -} - - -static void closelistfield (FuncState *fs, struct ConsControl *cc) { - if (cc->v.k == VVOID) return; /* there is no list item */ - luaK_exp2nextreg(fs, &cc->v); - cc->v.k = VVOID; - if (cc->tostore == LFIELDS_PER_FLUSH) { - luaK_setlist(fs, cc->t->u.s.info, cc->na, cc->tostore); /* flush */ - cc->tostore = 0; /* no more items pending */ - } -} - - -static void lastlistfield (FuncState *fs, struct ConsControl *cc) { - if (cc->tostore == 0) return; - if (hasmultret(cc->v.k)) { - luaK_setmultret(fs, &cc->v); - luaK_setlist(fs, cc->t->u.s.info, cc->na, LUA_MULTRET); - cc->na--; /* do not count last expression (unknown number of elements) */ - } - else { - if (cc->v.k != VVOID) - luaK_exp2nextreg(fs, &cc->v); - luaK_setlist(fs, cc->t->u.s.info, cc->na, cc->tostore); - } -} - - -static void listfield (LexState *ls, struct ConsControl *cc) { - expr(ls, &cc->v); - luaY_checklimit(ls->fs, cc->na, MAX_INT, "items in a constructor"); - cc->na++; - cc->tostore++; -} - - -static void constructor (LexState *ls, expdesc *t) { - /* constructor -> ?? */ - FuncState *fs = ls->fs; - int line = ls->linenumber; - int pc = luaK_codeABC(fs, OP_NEWTABLE, 0, 0, 0); - struct ConsControl cc; - cc.na = cc.nh = cc.tostore = 0; - cc.t = t; - init_exp(t, VRELOCABLE, pc); - init_exp(&cc.v, VVOID, 0); /* no value (yet) */ - luaK_exp2nextreg(ls->fs, t); /* fix it at stack top (for gc) */ - checknext(ls, '{'); - do { - lua_assert(cc.v.k == VVOID || cc.tostore > 0); - if (ls->t.token == '}') break; - closelistfield(fs, &cc); - switch(ls->t.token) { - case TK_NAME: { /* may be listfields or recfields */ - luaX_lookahead(ls); - if (ls->lookahead.token != '=') /* expression? */ - listfield(ls, &cc); - else - recfield(ls, &cc); - break; - } - case '[': { /* constructor_item -> recfield */ - recfield(ls, &cc); - break; - } - default: { /* constructor_part -> listfield */ - listfield(ls, &cc); - break; - } - } - } while (testnext(ls, ',') || testnext(ls, ';')); - check_match(ls, '}', '{', line); - lastlistfield(fs, &cc); - SETARG_B(fs->f->code[pc], luaO_int2fb(cc.na)); /* set initial array size */ - SETARG_C(fs->f->code[pc], luaO_int2fb(cc.nh)); /* set initial table size */ -} - -/* }====================================================================== */ - - - -static void parlist (LexState *ls) { - /* parlist -> [ param { `,' param } ] */ - FuncState *fs = ls->fs; - Proto *f = fs->f; - int nparams = 0; - f->is_vararg = 0; - if (ls->t.token != ')') { /* is `parlist' not empty? */ - do { - switch (ls->t.token) { - case TK_NAME: { /* param -> NAME */ - new_localvar(ls, str_checkname(ls), nparams++); - break; - } - case TK_DOTS: { /* param -> `...' */ - luaX_next(ls); -#if defined(LUA_COMPAT_VARARG) - /* use `arg' as default name */ - new_localvarliteral(ls, "arg", nparams++); - f->is_vararg = VARARG_HASARG | VARARG_NEEDSARG; -#endif - f->is_vararg |= VARARG_ISVARARG; - break; - } - default: luaX_syntaxerror(ls, " or " LUA_QL("...") " expected"); - } - } while (!f->is_vararg && testnext(ls, ',')); - } - adjustlocalvars(ls, nparams); - f->numparams = cast_byte(fs->nactvar - (f->is_vararg & VARARG_HASARG)); - luaK_reserveregs(fs, fs->nactvar); /* reserve register for parameters */ -} - - -static void body (LexState *ls, expdesc *e, int needself, int line) { - /* body -> `(' parlist `)' chunk END */ - FuncState new_fs; - open_func(ls, &new_fs); - new_fs.f->linedefined = line; - checknext(ls, '('); - if (needself) { - new_localvarliteral(ls, "self", 0); - adjustlocalvars(ls, 1); - } - parlist(ls); - checknext(ls, ')'); - chunk(ls); - new_fs.f->lastlinedefined = ls->linenumber; - check_match(ls, TK_END, TK_FUNCTION, line); - close_func(ls); - pushclosure(ls, &new_fs, e); -} - - -static int explist1 (LexState *ls, expdesc *v) { - /* explist1 -> expr { `,' expr } */ - int n = 1; /* at least one expression */ - expr(ls, v); - while (testnext(ls, ',')) { - luaK_exp2nextreg(ls->fs, v); - expr(ls, v); - n++; - } - return n; -} - - -static void funcargs (LexState *ls, expdesc *f) { - FuncState *fs = ls->fs; - expdesc args; - int base, nparams; - int line = ls->linenumber; - switch (ls->t.token) { - case '(': { /* funcargs -> `(' [ explist1 ] `)' */ - if (line != ls->lastline) - luaX_syntaxerror(ls,"ambiguous syntax (function call x new statement)"); - luaX_next(ls); - if (ls->t.token == ')') /* arg list is empty? */ - args.k = VVOID; - else { - explist1(ls, &args); - luaK_setmultret(fs, &args); - } - check_match(ls, ')', '(', line); - break; - } - case '{': { /* funcargs -> constructor */ - constructor(ls, &args); - break; - } - case TK_STRING: { /* funcargs -> STRING */ - codestring(ls, &args, ls->t.seminfo.ts); - luaX_next(ls); /* must use `seminfo' before `next' */ - break; - } - default: { - luaX_syntaxerror(ls, "function arguments expected"); - return; - } - } - lua_assert(f->k == VNONRELOC); - base = f->u.s.info; /* base register for call */ - if (hasmultret(args.k)) - nparams = LUA_MULTRET; /* open call */ - else { - if (args.k != VVOID) - luaK_exp2nextreg(fs, &args); /* close last argument */ - nparams = fs->freereg - (base+1); - } - init_exp(f, VCALL, luaK_codeABC(fs, OP_CALL, base, nparams+1, 2)); - luaK_fixline(fs, line); - fs->freereg = base+1; /* call remove function and arguments and leaves - (unless changed) one result */ -} - - - - -/* -** {====================================================================== -** Expression parsing -** ======================================================================= -*/ - - -static void prefixexp (LexState *ls, expdesc *v) { - /* prefixexp -> NAME | '(' expr ')' */ - switch (ls->t.token) { - case '(': { - int line = ls->linenumber; - luaX_next(ls); - expr(ls, v); - check_match(ls, ')', '(', line); - luaK_dischargevars(ls->fs, v); - return; - } - case TK_NAME: { - singlevar(ls, v); - return; - } - default: { - luaX_syntaxerror(ls, "unexpected symbol"); - return; - } - } -} - - -static void primaryexp (LexState *ls, expdesc *v) { - /* primaryexp -> - prefixexp { `.' NAME | `[' exp `]' | `:' NAME funcargs | funcargs } */ - FuncState *fs = ls->fs; - prefixexp(ls, v); - for (;;) { - switch (ls->t.token) { - case '.': { /* field */ - field(ls, v); - break; - } - case '[': { /* `[' exp1 `]' */ - expdesc key; - luaK_exp2anyreg(fs, v); - yindex(ls, &key); - luaK_indexed(fs, v, &key); - break; - } - case ':': { /* `:' NAME funcargs */ - expdesc key; - luaX_next(ls); - checkname(ls, &key); - luaK_self(fs, v, &key); - funcargs(ls, v); - break; - } - case '(': case TK_STRING: case '{': { /* funcargs */ - luaK_exp2nextreg(fs, v); - funcargs(ls, v); - break; - } - default: return; - } - } -} - - -static void simpleexp (LexState *ls, expdesc *v) { - /* simpleexp -> NUMBER | STRING | NIL | true | false | ... | - constructor | FUNCTION body | primaryexp */ - switch (ls->t.token) { - case TK_NUMBER: { - init_exp(v, VKNUM, 0); - v->u.nval = ls->t.seminfo.r; - break; - } - case TK_STRING: { - codestring(ls, v, ls->t.seminfo.ts); - break; - } - case TK_NIL: { - init_exp(v, VNIL, 0); - break; - } - case TK_TRUE: { - init_exp(v, VTRUE, 0); - break; - } - case TK_FALSE: { - init_exp(v, VFALSE, 0); - break; - } - case TK_DOTS: { /* vararg */ - FuncState *fs = ls->fs; - check_condition(ls, fs->f->is_vararg, - "cannot use " LUA_QL("...") " outside a vararg function"); - fs->f->is_vararg &= ~VARARG_NEEDSARG; /* don't need 'arg' */ - init_exp(v, VVARARG, luaK_codeABC(fs, OP_VARARG, 0, 1, 0)); - break; - } - case '{': { /* constructor */ - constructor(ls, v); - return; - } - case TK_FUNCTION: { - luaX_next(ls); - body(ls, v, 0, ls->linenumber); - return; - } - default: { - primaryexp(ls, v); - return; - } - } - luaX_next(ls); -} - - -static UnOpr getunopr (int op) { - switch (op) { - case TK_NOT: return OPR_NOT; - case '-': return OPR_MINUS; - case '#': return OPR_LEN; - default: return OPR_NOUNOPR; - } -} - - -static BinOpr getbinopr (int op) { - switch (op) { - case '+': return OPR_ADD; - case '-': return OPR_SUB; - case '*': return OPR_MUL; - case '/': return OPR_DIV; - case '%': return OPR_MOD; - case '^': return OPR_POW; - case TK_CONCAT: return OPR_CONCAT; - case TK_NE: return OPR_NE; - case TK_EQ: return OPR_EQ; - case '<': return OPR_LT; - case TK_LE: return OPR_LE; - case '>': return OPR_GT; - case TK_GE: return OPR_GE; - case TK_AND: return OPR_AND; - case TK_OR: return OPR_OR; - default: return OPR_NOBINOPR; - } -} - - -static const struct { - lu_byte left; /* left priority for each binary operator */ - lu_byte right; /* right priority */ -} priority[] = { /* ORDER OPR */ - {6, 6}, {6, 6}, {7, 7}, {7, 7}, {7, 7}, /* `+' `-' `/' `%' */ - {10, 9}, {5, 4}, /* power and concat (right associative) */ - {3, 3}, {3, 3}, /* equality and inequality */ - {3, 3}, {3, 3}, {3, 3}, {3, 3}, /* order */ - {2, 2}, {1, 1} /* logical (and/or) */ -}; - -#define UNARY_PRIORITY 8 /* priority for unary operators */ - - -/* -** subexpr -> (simpleexp | unop subexpr) { binop subexpr } -** where `binop' is any binary operator with a priority higher than `limit' -*/ -static BinOpr subexpr (LexState *ls, expdesc *v, unsigned int limit) { - BinOpr op; - UnOpr uop; - enterlevel(ls); - uop = getunopr(ls->t.token); - if (uop != OPR_NOUNOPR) { - luaX_next(ls); - subexpr(ls, v, UNARY_PRIORITY); - luaK_prefix(ls->fs, uop, v); - } - else simpleexp(ls, v); - /* expand while operators have priorities higher than `limit' */ - op = getbinopr(ls->t.token); - while (op != OPR_NOBINOPR && priority[op].left > limit) { - expdesc v2; - BinOpr nextop; - luaX_next(ls); - luaK_infix(ls->fs, op, v); - /* read sub-expression with higher priority */ - nextop = subexpr(ls, &v2, priority[op].right); - luaK_posfix(ls->fs, op, v, &v2); - op = nextop; - } - leavelevel(ls); - return op; /* return first untreated operator */ -} - - -static void expr (LexState *ls, expdesc *v) { - subexpr(ls, v, 0); -} - -/* }==================================================================== */ - - - -/* -** {====================================================================== -** Rules for Statements -** ======================================================================= -*/ - - -static int block_follow (int token) { - switch (token) { - case TK_ELSE: case TK_ELSEIF: case TK_END: - case TK_UNTIL: case TK_EOS: - return 1; - default: return 0; - } -} - - -static void block (LexState *ls) { - /* block -> chunk */ - FuncState *fs = ls->fs; - BlockCnt bl; - enterblock(fs, &bl, 0); - chunk(ls); - lua_assert(bl.breaklist == NO_JUMP); - leaveblock(fs); -} - - -/* -** structure to chain all variables in the left-hand side of an -** assignment -*/ -struct LHS_assign { - struct LHS_assign *prev; - expdesc v; /* variable (global, local, upvalue, or indexed) */ -}; - - -/* -** check whether, in an assignment to a local variable, the local variable -** is needed in a previous assignment (to a table). If so, save original -** local value in a safe place and use this safe copy in the previous -** assignment. -*/ -static void check_conflict (LexState *ls, struct LHS_assign *lh, expdesc *v) { - FuncState *fs = ls->fs; - int extra = fs->freereg; /* eventual position to save local variable */ - int conflict = 0; - for (; lh; lh = lh->prev) { - if (lh->v.k == VINDEXED) { - if (lh->v.u.s.info == v->u.s.info) { /* conflict? */ - conflict = 1; - lh->v.u.s.info = extra; /* previous assignment will use safe copy */ - } - if (lh->v.u.s.aux == v->u.s.info) { /* conflict? */ - conflict = 1; - lh->v.u.s.aux = extra; /* previous assignment will use safe copy */ - } - } - } - if (conflict) { - luaK_codeABC(fs, OP_MOVE, fs->freereg, v->u.s.info, 0); /* make copy */ - luaK_reserveregs(fs, 1); - } -} - - -static void assignment (LexState *ls, struct LHS_assign *lh, int nvars) { - expdesc e; - check_condition(ls, VLOCAL <= lh->v.k && lh->v.k <= VINDEXED, - "syntax error"); - if (testnext(ls, ',')) { /* assignment -> `,' primaryexp assignment */ - struct LHS_assign nv; - nv.prev = lh; - primaryexp(ls, &nv.v); - if (nv.v.k == VLOCAL) - check_conflict(ls, lh, &nv.v); - luaY_checklimit(ls->fs, nvars, LUAI_MAXCCALLS - ls->L->nCcalls, - "variables in assignment"); - assignment(ls, &nv, nvars+1); - } - else { /* assignment -> `=' explist1 */ - int nexps; - checknext(ls, '='); - nexps = explist1(ls, &e); - if (nexps != nvars) { - adjust_assign(ls, nvars, nexps, &e); - if (nexps > nvars) - ls->fs->freereg -= nexps - nvars; /* remove extra values */ - } - else { - luaK_setoneret(ls->fs, &e); /* close last expression */ - luaK_storevar(ls->fs, &lh->v, &e); - return; /* avoid default */ - } - } - init_exp(&e, VNONRELOC, ls->fs->freereg-1); /* default assignment */ - luaK_storevar(ls->fs, &lh->v, &e); -} - - -static int cond (LexState *ls) { - /* cond -> exp */ - expdesc v; - expr(ls, &v); /* read condition */ - if (v.k == VNIL) v.k = VFALSE; /* `falses' are all equal here */ - luaK_goiftrue(ls->fs, &v); - return v.f; -} - - -static void breakstat (LexState *ls) { - FuncState *fs = ls->fs; - BlockCnt *bl = fs->bl; - int upval = 0; - while (bl && !bl->isbreakable) { - upval |= bl->upval; - bl = bl->previous; - } - if (!bl) - luaX_syntaxerror(ls, "no loop to break"); - if (upval) - luaK_codeABC(fs, OP_CLOSE, bl->nactvar, 0, 0); - luaK_concat(fs, &bl->breaklist, luaK_jump(fs)); -} - - -static void whilestat (LexState *ls, int line) { - /* whilestat -> WHILE cond DO block END */ - FuncState *fs = ls->fs; - int whileinit; - int condexit; - BlockCnt bl; - luaX_next(ls); /* skip WHILE */ - whileinit = luaK_getlabel(fs); - condexit = cond(ls); - enterblock(fs, &bl, 1); - checknext(ls, TK_DO); - block(ls); - luaK_patchlist(fs, luaK_jump(fs), whileinit); - check_match(ls, TK_END, TK_WHILE, line); - leaveblock(fs); - luaK_patchtohere(fs, condexit); /* false conditions finish the loop */ -} - - -static void repeatstat (LexState *ls, int line) { - /* repeatstat -> REPEAT block UNTIL cond */ - int condexit; - FuncState *fs = ls->fs; - int repeat_init = luaK_getlabel(fs); - BlockCnt bl1, bl2; - enterblock(fs, &bl1, 1); /* loop block */ - enterblock(fs, &bl2, 0); /* scope block */ - luaX_next(ls); /* skip REPEAT */ - chunk(ls); - check_match(ls, TK_UNTIL, TK_REPEAT, line); - condexit = cond(ls); /* read condition (inside scope block) */ - if (!bl2.upval) { /* no upvalues? */ - leaveblock(fs); /* finish scope */ - luaK_patchlist(ls->fs, condexit, repeat_init); /* close the loop */ - } - else { /* complete semantics when there are upvalues */ - breakstat(ls); /* if condition then break */ - luaK_patchtohere(ls->fs, condexit); /* else... */ - leaveblock(fs); /* finish scope... */ - luaK_patchlist(ls->fs, luaK_jump(fs), repeat_init); /* and repeat */ - } - leaveblock(fs); /* finish loop */ -} - - -static int exp1 (LexState *ls) { - expdesc e; - int k; - expr(ls, &e); - k = e.k; - luaK_exp2nextreg(ls->fs, &e); - return k; -} - - -static void forbody (LexState *ls, int base, int line, int nvars, int isnum) { - /* forbody -> DO block */ - BlockCnt bl; - FuncState *fs = ls->fs; - int prep, endfor; - adjustlocalvars(ls, 3); /* control variables */ - checknext(ls, TK_DO); - prep = isnum ? luaK_codeAsBx(fs, OP_FORPREP, base, NO_JUMP) : luaK_jump(fs); - enterblock(fs, &bl, 0); /* scope for declared variables */ - adjustlocalvars(ls, nvars); - luaK_reserveregs(fs, nvars); - block(ls); - leaveblock(fs); /* end of scope for declared variables */ - luaK_patchtohere(fs, prep); - endfor = (isnum) ? luaK_codeAsBx(fs, OP_FORLOOP, base, NO_JUMP) : - luaK_codeABC(fs, OP_TFORLOOP, base, 0, nvars); - luaK_fixline(fs, line); /* pretend that `OP_FOR' starts the loop */ - luaK_patchlist(fs, (isnum ? endfor : luaK_jump(fs)), prep + 1); -} - - -static void fornum (LexState *ls, TString *varname, int line) { - /* fornum -> NAME = exp1,exp1[,exp1] forbody */ - FuncState *fs = ls->fs; - int base = fs->freereg; - new_localvarliteral(ls, "(for index)", 0); - new_localvarliteral(ls, "(for limit)", 1); - new_localvarliteral(ls, "(for step)", 2); - new_localvar(ls, varname, 3); - checknext(ls, '='); - exp1(ls); /* initial value */ - checknext(ls, ','); - exp1(ls); /* limit */ - if (testnext(ls, ',')) - exp1(ls); /* optional step */ - else { /* default step = 1 */ - luaK_codeABx(fs, OP_LOADK, fs->freereg, luaK_numberK(fs, 1)); - luaK_reserveregs(fs, 1); - } - forbody(ls, base, line, 1, 1); -} - - -static void forlist (LexState *ls, TString *indexname) { - /* forlist -> NAME {,NAME} IN explist1 forbody */ - FuncState *fs = ls->fs; - expdesc e; - int nvars = 0; - int line; - int base = fs->freereg; - /* create control variables */ - new_localvarliteral(ls, "(for generator)", nvars++); - new_localvarliteral(ls, "(for state)", nvars++); - new_localvarliteral(ls, "(for control)", nvars++); - /* create declared variables */ - new_localvar(ls, indexname, nvars++); - while (testnext(ls, ',')) - new_localvar(ls, str_checkname(ls), nvars++); - checknext(ls, TK_IN); - line = ls->linenumber; - adjust_assign(ls, 3, explist1(ls, &e), &e); - luaK_checkstack(fs, 3); /* extra space to call generator */ - forbody(ls, base, line, nvars - 3, 0); -} - - -static void forstat (LexState *ls, int line) { - /* forstat -> FOR (fornum | forlist) END */ - FuncState *fs = ls->fs; - TString *varname; - BlockCnt bl; - enterblock(fs, &bl, 1); /* scope for loop and control variables */ - luaX_next(ls); /* skip `for' */ - varname = str_checkname(ls); /* first variable name */ - switch (ls->t.token) { - case '=': fornum(ls, varname, line); break; - case ',': case TK_IN: forlist(ls, varname); break; - default: luaX_syntaxerror(ls, LUA_QL("=") " or " LUA_QL("in") " expected"); - } - check_match(ls, TK_END, TK_FOR, line); - leaveblock(fs); /* loop scope (`break' jumps to this point) */ -} - - -static int test_then_block (LexState *ls) { - /* test_then_block -> [IF | ELSEIF] cond THEN block */ - int condexit; - luaX_next(ls); /* skip IF or ELSEIF */ - condexit = cond(ls); - checknext(ls, TK_THEN); - block(ls); /* `then' part */ - return condexit; -} - - -static void ifstat (LexState *ls, int line) { - /* ifstat -> IF cond THEN block {ELSEIF cond THEN block} [ELSE block] END */ - FuncState *fs = ls->fs; - int flist; - int escapelist = NO_JUMP; - flist = test_then_block(ls); /* IF cond THEN block */ - while (ls->t.token == TK_ELSEIF) { - luaK_concat(fs, &escapelist, luaK_jump(fs)); - luaK_patchtohere(fs, flist); - flist = test_then_block(ls); /* ELSEIF cond THEN block */ - } - if (ls->t.token == TK_ELSE) { - luaK_concat(fs, &escapelist, luaK_jump(fs)); - luaK_patchtohere(fs, flist); - luaX_next(ls); /* skip ELSE (after patch, for correct line info) */ - block(ls); /* `else' part */ - } - else - luaK_concat(fs, &escapelist, flist); - luaK_patchtohere(fs, escapelist); - check_match(ls, TK_END, TK_IF, line); -} - - -static void localfunc (LexState *ls) { - expdesc v, b; - FuncState *fs = ls->fs; - new_localvar(ls, str_checkname(ls), 0); - init_exp(&v, VLOCAL, fs->freereg); - luaK_reserveregs(fs, 1); - adjustlocalvars(ls, 1); - body(ls, &b, 0, ls->linenumber); - luaK_storevar(fs, &v, &b); - /* debug information will only see the variable after this point! */ - getlocvar(fs, fs->nactvar - 1).startpc = fs->pc; -} - - -static void localstat (LexState *ls) { - /* stat -> LOCAL NAME {`,' NAME} [`=' explist1] */ - int nvars = 0; - int nexps; - expdesc e; - do { - new_localvar(ls, str_checkname(ls), nvars++); - } while (testnext(ls, ',')); - if (testnext(ls, '=')) - nexps = explist1(ls, &e); - else { - e.k = VVOID; - nexps = 0; - } - adjust_assign(ls, nvars, nexps, &e); - adjustlocalvars(ls, nvars); -} - - -static int funcname (LexState *ls, expdesc *v) { - /* funcname -> NAME {field} [`:' NAME] */ - int needself = 0; - singlevar(ls, v); - while (ls->t.token == '.') - field(ls, v); - if (ls->t.token == ':') { - needself = 1; - field(ls, v); - } - return needself; -} - - -static void funcstat (LexState *ls, int line) { - /* funcstat -> FUNCTION funcname body */ - int needself; - expdesc v, b; - luaX_next(ls); /* skip FUNCTION */ - needself = funcname(ls, &v); - body(ls, &b, needself, line); - luaK_storevar(ls->fs, &v, &b); - luaK_fixline(ls->fs, line); /* definition `happens' in the first line */ -} - - -static void exprstat (LexState *ls) { - /* stat -> func | assignment */ - FuncState *fs = ls->fs; - struct LHS_assign v; - primaryexp(ls, &v.v); - if (v.v.k == VCALL) /* stat -> func */ - SETARG_C(getcode(fs, &v.v), 1); /* call statement uses no results */ - else { /* stat -> assignment */ - v.prev = NULL; - assignment(ls, &v, 1); - } -} - - -static void retstat (LexState *ls) { - /* stat -> RETURN explist */ - FuncState *fs = ls->fs; - expdesc e; - int first, nret; /* registers with returned values */ - luaX_next(ls); /* skip RETURN */ - if (block_follow(ls->t.token) || ls->t.token == ';') - first = nret = 0; /* return no values */ - else { - nret = explist1(ls, &e); /* optional return values */ - if (hasmultret(e.k)) { - luaK_setmultret(fs, &e); - if (e.k == VCALL && nret == 1) { /* tail call? */ - SET_OPCODE(getcode(fs,&e), OP_TAILCALL); - lua_assert(GETARG_A(getcode(fs,&e)) == fs->nactvar); - } - first = fs->nactvar; - nret = LUA_MULTRET; /* return all values */ - } - else { - if (nret == 1) /* only one single value? */ - first = luaK_exp2anyreg(fs, &e); - else { - luaK_exp2nextreg(fs, &e); /* values must go to the `stack' */ - first = fs->nactvar; /* return all `active' values */ - lua_assert(nret == fs->freereg - first); - } - } - } - luaK_ret(fs, first, nret); -} - - -static int statement (LexState *ls) { - int line = ls->linenumber; /* may be needed for error messages */ - switch (ls->t.token) { - case TK_IF: { /* stat -> ifstat */ - ifstat(ls, line); - return 0; - } - case TK_WHILE: { /* stat -> whilestat */ - whilestat(ls, line); - return 0; - } - case TK_DO: { /* stat -> DO block END */ - luaX_next(ls); /* skip DO */ - block(ls); - check_match(ls, TK_END, TK_DO, line); - return 0; - } - case TK_FOR: { /* stat -> forstat */ - forstat(ls, line); - return 0; - } - case TK_REPEAT: { /* stat -> repeatstat */ - repeatstat(ls, line); - return 0; - } - case TK_FUNCTION: { - funcstat(ls, line); /* stat -> funcstat */ - return 0; - } - case TK_LOCAL: { /* stat -> localstat */ - luaX_next(ls); /* skip LOCAL */ - if (testnext(ls, TK_FUNCTION)) /* local function? */ - localfunc(ls); - else - localstat(ls); - return 0; - } - case TK_RETURN: { /* stat -> retstat */ - retstat(ls); - return 1; /* must be last statement */ - } - case TK_BREAK: { /* stat -> breakstat */ - luaX_next(ls); /* skip BREAK */ - breakstat(ls); - return 1; /* must be last statement */ - } - default: { - exprstat(ls); - return 0; /* to avoid warnings */ - } - } -} - - -static void chunk (LexState *ls) { - /* chunk -> { stat [`;'] } */ - int islast = 0; - enterlevel(ls); - while (!islast && !block_follow(ls->t.token)) { - islast = statement(ls); - testnext(ls, ';'); - lua_assert(ls->fs->f->maxstacksize >= ls->fs->freereg && - ls->fs->freereg >= ls->fs->nactvar); - ls->fs->freereg = ls->fs->nactvar; /* free registers */ - } - leavelevel(ls); -} - -/* }====================================================================== */ diff --git a/lib/lua-5.1/src/lparser.h b/lib/lua-5.1/src/lparser.h deleted file mode 100644 index 18836af..0000000 --- a/lib/lua-5.1/src/lparser.h +++ /dev/null @@ -1,82 +0,0 @@ -/* -** $Id: lparser.h,v 1.57.1.1 2007/12/27 13:02:25 roberto Exp $ -** Lua Parser -** See Copyright Notice in lua.h -*/ - -#ifndef lparser_h -#define lparser_h - -#include "llimits.h" -#include "lobject.h" -#include "lzio.h" - - -/* -** Expression descriptor -*/ - -typedef enum { - VVOID, /* no value */ - VNIL, - VTRUE, - VFALSE, - VK, /* info = index of constant in `k' */ - VKNUM, /* nval = numerical value */ - VLOCAL, /* info = local register */ - VUPVAL, /* info = index of upvalue in `upvalues' */ - VGLOBAL, /* info = index of table; aux = index of global name in `k' */ - VINDEXED, /* info = table register; aux = index register (or `k') */ - VJMP, /* info = instruction pc */ - VRELOCABLE, /* info = instruction pc */ - VNONRELOC, /* info = result register */ - VCALL, /* info = instruction pc */ - VVARARG /* info = instruction pc */ -} expkind; - -typedef struct expdesc { - expkind k; - union { - struct { int info, aux; } s; - lua_Number nval; - } u; - int t; /* patch list of `exit when true' */ - int f; /* patch list of `exit when false' */ -} expdesc; - - -typedef struct upvaldesc { - lu_byte k; - lu_byte info; -} upvaldesc; - - -struct BlockCnt; /* defined in lparser.c */ - - -/* state needed to generate code for a given function */ -typedef struct FuncState { - Proto *f; /* current function header */ - Table *h; /* table to find (and reuse) elements in `k' */ - struct FuncState *prev; /* enclosing function */ - struct LexState *ls; /* lexical state */ - struct lua_State *L; /* copy of the Lua state */ - struct BlockCnt *bl; /* chain of current blocks */ - int pc; /* next position to code (equivalent to `ncode') */ - int lasttarget; /* `pc' of last `jump target' */ - int jpc; /* list of pending jumps to `pc' */ - int freereg; /* first free register */ - int nk; /* number of elements in `k' */ - int np; /* number of elements in `p' */ - short nlocvars; /* number of elements in `locvars' */ - lu_byte nactvar; /* number of active local variables */ - upvaldesc upvalues[LUAI_MAXUPVALUES]; /* upvalues */ - unsigned short actvar[LUAI_MAXVARS]; /* declared-variable stack */ -} FuncState; - - -LUAI_FUNC Proto *luaY_parser (lua_State *L, ZIO *z, Mbuffer *buff, - const char *name); - - -#endif diff --git a/lib/lua-5.1/src/lstate.c b/lib/lua-5.1/src/lstate.c deleted file mode 100644 index 4313b83..0000000 --- a/lib/lua-5.1/src/lstate.c +++ /dev/null @@ -1,214 +0,0 @@ -/* -** $Id: lstate.c,v 2.36.1.2 2008/01/03 15:20:39 roberto Exp $ -** Global State -** See Copyright Notice in lua.h -*/ - - -#include - -#define lstate_c -#define LUA_CORE - -#include "lua.h" - -#include "ldebug.h" -#include "ldo.h" -#include "lfunc.h" -#include "lgc.h" -#include "llex.h" -#include "lmem.h" -#include "lstate.h" -#include "lstring.h" -#include "ltable.h" -#include "ltm.h" - - -#define state_size(x) (sizeof(x) + LUAI_EXTRASPACE) -#define fromstate(l) (cast(lu_byte *, (l)) - LUAI_EXTRASPACE) -#define tostate(l) (cast(lua_State *, cast(lu_byte *, l) + LUAI_EXTRASPACE)) - - -/* -** Main thread combines a thread state and the global state -*/ -typedef struct LG { - lua_State l; - global_State g; -} LG; - - - -static void stack_init (lua_State *L1, lua_State *L) { - /* initialize CallInfo array */ - L1->base_ci = luaM_newvector(L, BASIC_CI_SIZE, CallInfo); - L1->ci = L1->base_ci; - L1->size_ci = BASIC_CI_SIZE; - L1->end_ci = L1->base_ci + L1->size_ci - 1; - /* initialize stack array */ - L1->stack = luaM_newvector(L, BASIC_STACK_SIZE + EXTRA_STACK, TValue); - L1->stacksize = BASIC_STACK_SIZE + EXTRA_STACK; - L1->top = L1->stack; - L1->stack_last = L1->stack+(L1->stacksize - EXTRA_STACK)-1; - /* initialize first ci */ - L1->ci->func = L1->top; - setnilvalue(L1->top++); /* `function' entry for this `ci' */ - L1->base = L1->ci->base = L1->top; - L1->ci->top = L1->top + LUA_MINSTACK; -} - - -static void freestack (lua_State *L, lua_State *L1) { - luaM_freearray(L, L1->base_ci, L1->size_ci, CallInfo); - luaM_freearray(L, L1->stack, L1->stacksize, TValue); -} - - -/* -** open parts that may cause memory-allocation errors -*/ -static void f_luaopen (lua_State *L, void *ud) { - global_State *g = G(L); - UNUSED(ud); - stack_init(L, L); /* init stack */ - sethvalue(L, gt(L), luaH_new(L, 0, 2)); /* table of globals */ - sethvalue(L, registry(L), luaH_new(L, 0, 2)); /* registry */ - luaS_resize(L, MINSTRTABSIZE); /* initial size of string table */ - luaT_init(L); - luaX_init(L); - luaS_fix(luaS_newliteral(L, MEMERRMSG)); - g->GCthreshold = 4*g->totalbytes; -} - - -static void preinit_state (lua_State *L, global_State *g) { - G(L) = g; - L->stack = NULL; - L->stacksize = 0; - L->errorJmp = NULL; - L->hook = NULL; - L->hookmask = 0; - L->basehookcount = 0; - L->allowhook = 1; - resethookcount(L); - L->openupval = NULL; - L->size_ci = 0; - L->nCcalls = L->baseCcalls = 0; - L->status = 0; - L->base_ci = L->ci = NULL; - L->savedpc = NULL; - L->errfunc = 0; - setnilvalue(gt(L)); -} - - -static void close_state (lua_State *L) { - global_State *g = G(L); - luaF_close(L, L->stack); /* close all upvalues for this thread */ - luaC_freeall(L); /* collect all objects */ - lua_assert(g->rootgc == obj2gco(L)); - lua_assert(g->strt.nuse == 0); - luaM_freearray(L, G(L)->strt.hash, G(L)->strt.size, TString *); - luaZ_freebuffer(L, &g->buff); - freestack(L, L); - lua_assert(g->totalbytes == sizeof(LG)); - (*g->frealloc)(g->ud, fromstate(L), state_size(LG), 0); -} - - -lua_State *luaE_newthread (lua_State *L) { - lua_State *L1 = tostate(luaM_malloc(L, state_size(lua_State))); - luaC_link(L, obj2gco(L1), LUA_TTHREAD); - preinit_state(L1, G(L)); - stack_init(L1, L); /* init stack */ - setobj2n(L, gt(L1), gt(L)); /* share table of globals */ - L1->hookmask = L->hookmask; - L1->basehookcount = L->basehookcount; - L1->hook = L->hook; - resethookcount(L1); - lua_assert(iswhite(obj2gco(L1))); - return L1; -} - - -void luaE_freethread (lua_State *L, lua_State *L1) { - luaF_close(L1, L1->stack); /* close all upvalues for this thread */ - lua_assert(L1->openupval == NULL); - luai_userstatefree(L1); - freestack(L, L1); - luaM_freemem(L, fromstate(L1), state_size(lua_State)); -} - - -LUA_API lua_State *lua_newstate (lua_Alloc f, void *ud) { - int i; - lua_State *L; - global_State *g; - void *l = (*f)(ud, NULL, 0, state_size(LG)); - if (l == NULL) return NULL; - L = tostate(l); - g = &((LG *)L)->g; - L->next = NULL; - L->tt = LUA_TTHREAD; - g->currentwhite = bit2mask(WHITE0BIT, FIXEDBIT); - L->marked = luaC_white(g); - set2bits(L->marked, FIXEDBIT, SFIXEDBIT); - preinit_state(L, g); - g->frealloc = f; - g->ud = ud; - g->mainthread = L; - g->uvhead.u.l.prev = &g->uvhead; - g->uvhead.u.l.next = &g->uvhead; - g->GCthreshold = 0; /* mark it as unfinished state */ - g->strt.size = 0; - g->strt.nuse = 0; - g->strt.hash = NULL; - setnilvalue(registry(L)); - luaZ_initbuffer(L, &g->buff); - g->panic = NULL; - g->gcstate = GCSpause; - g->rootgc = obj2gco(L); - g->sweepstrgc = 0; - g->sweepgc = &g->rootgc; - g->gray = NULL; - g->grayagain = NULL; - g->weak = NULL; - g->tmudata = NULL; - g->totalbytes = sizeof(LG); - g->gcpause = LUAI_GCPAUSE; - g->gcstepmul = LUAI_GCMUL; - g->gcdept = 0; - for (i=0; imt[i] = NULL; - if (luaD_rawrunprotected(L, f_luaopen, NULL) != 0) { - /* memory allocation error: free partial state */ - close_state(L); - L = NULL; - } - else - luai_userstateopen(L); - return L; -} - - -static void callallgcTM (lua_State *L, void *ud) { - UNUSED(ud); - luaC_callGCTM(L); /* call GC metamethods for all udata */ -} - - -LUA_API void lua_close (lua_State *L) { - L = G(L)->mainthread; /* only the main thread can be closed */ - lua_lock(L); - luaF_close(L, L->stack); /* close all upvalues for this thread */ - luaC_separateudata(L, 1); /* separate udata that have GC metamethods */ - L->errfunc = 0; /* no error function during GC metamethods */ - do { /* repeat until no more errors */ - L->ci = L->base_ci; - L->base = L->top = L->ci->base; - L->nCcalls = L->baseCcalls = 0; - } while (luaD_rawrunprotected(L, callallgcTM, NULL) != 0); - lua_assert(G(L)->tmudata == NULL); - luai_userstateclose(L); - close_state(L); -} - diff --git a/lib/lua-5.1/src/lstate.h b/lib/lua-5.1/src/lstate.h deleted file mode 100644 index 3bc575b..0000000 --- a/lib/lua-5.1/src/lstate.h +++ /dev/null @@ -1,169 +0,0 @@ -/* -** $Id: lstate.h,v 2.24.1.2 2008/01/03 15:20:39 roberto Exp $ -** Global State -** See Copyright Notice in lua.h -*/ - -#ifndef lstate_h -#define lstate_h - -#include "lua.h" - -#include "lobject.h" -#include "ltm.h" -#include "lzio.h" - - - -struct lua_longjmp; /* defined in ldo.c */ - - -/* table of globals */ -#define gt(L) (&L->l_gt) - -/* registry */ -#define registry(L) (&G(L)->l_registry) - - -/* extra stack space to handle TM calls and some other extras */ -#define EXTRA_STACK 5 - - -#define BASIC_CI_SIZE 8 - -#define BASIC_STACK_SIZE (2*LUA_MINSTACK) - - - -typedef struct stringtable { - GCObject **hash; - lu_int32 nuse; /* number of elements */ - int size; -} stringtable; - - -/* -** informations about a call -*/ -typedef struct CallInfo { - StkId base; /* base for this function */ - StkId func; /* function index in the stack */ - StkId top; /* top for this function */ - const Instruction *savedpc; - int nresults; /* expected number of results from this function */ - int tailcalls; /* number of tail calls lost under this entry */ -} CallInfo; - - - -#define curr_func(L) (clvalue(L->ci->func)) -#define ci_func(ci) (clvalue((ci)->func)) -#define f_isLua(ci) (!ci_func(ci)->c.isC) -#define isLua(ci) (ttisfunction((ci)->func) && f_isLua(ci)) - - -/* -** `global state', shared by all threads of this state -*/ -typedef struct global_State { - stringtable strt; /* hash table for strings */ - lua_Alloc frealloc; /* function to reallocate memory */ - void *ud; /* auxiliary data to `frealloc' */ - lu_byte currentwhite; - lu_byte gcstate; /* state of garbage collector */ - int sweepstrgc; /* position of sweep in `strt' */ - GCObject *rootgc; /* list of all collectable objects */ - GCObject **sweepgc; /* position of sweep in `rootgc' */ - GCObject *gray; /* list of gray objects */ - GCObject *grayagain; /* list of objects to be traversed atomically */ - GCObject *weak; /* list of weak tables (to be cleared) */ - GCObject *tmudata; /* last element of list of userdata to be GC */ - Mbuffer buff; /* temporary buffer for string concatentation */ - lu_mem GCthreshold; - lu_mem totalbytes; /* number of bytes currently allocated */ - lu_mem estimate; /* an estimate of number of bytes actually in use */ - lu_mem gcdept; /* how much GC is `behind schedule' */ - int gcpause; /* size of pause between successive GCs */ - int gcstepmul; /* GC `granularity' */ - lua_CFunction panic; /* to be called in unprotected errors */ - TValue l_registry; - struct lua_State *mainthread; - UpVal uvhead; /* head of double-linked list of all open upvalues */ - struct Table *mt[NUM_TAGS]; /* metatables for basic types */ - TString *tmname[TM_N]; /* array with tag-method names */ -} global_State; - - -/* -** `per thread' state -*/ -struct lua_State { - CommonHeader; - lu_byte status; - StkId top; /* first free slot in the stack */ - StkId base; /* base of current function */ - global_State *l_G; - CallInfo *ci; /* call info for current function */ - const Instruction *savedpc; /* `savedpc' of current function */ - StkId stack_last; /* last free slot in the stack */ - StkId stack; /* stack base */ - CallInfo *end_ci; /* points after end of ci array*/ - CallInfo *base_ci; /* array of CallInfo's */ - int stacksize; - int size_ci; /* size of array `base_ci' */ - unsigned short nCcalls; /* number of nested C calls */ - unsigned short baseCcalls; /* nested C calls when resuming coroutine */ - lu_byte hookmask; - lu_byte allowhook; - int basehookcount; - int hookcount; - lua_Hook hook; - TValue l_gt; /* table of globals */ - TValue env; /* temporary place for environments */ - GCObject *openupval; /* list of open upvalues in this stack */ - GCObject *gclist; - struct lua_longjmp *errorJmp; /* current error recover point */ - ptrdiff_t errfunc; /* current error handling function (stack index) */ -}; - - -#define G(L) (L->l_G) - - -/* -** Union of all collectable objects -*/ -union GCObject { - GCheader gch; - union TString ts; - union Udata u; - union Closure cl; - struct Table h; - struct Proto p; - struct UpVal uv; - struct lua_State th; /* thread */ -}; - - -/* macros to convert a GCObject into a specific value */ -#define rawgco2ts(o) check_exp((o)->gch.tt == LUA_TSTRING, &((o)->ts)) -#define gco2ts(o) (&rawgco2ts(o)->tsv) -#define rawgco2u(o) check_exp((o)->gch.tt == LUA_TUSERDATA, &((o)->u)) -#define gco2u(o) (&rawgco2u(o)->uv) -#define gco2cl(o) check_exp((o)->gch.tt == LUA_TFUNCTION, &((o)->cl)) -#define gco2h(o) check_exp((o)->gch.tt == LUA_TTABLE, &((o)->h)) -#define gco2p(o) check_exp((o)->gch.tt == LUA_TPROTO, &((o)->p)) -#define gco2uv(o) check_exp((o)->gch.tt == LUA_TUPVAL, &((o)->uv)) -#define ngcotouv(o) \ - check_exp((o) == NULL || (o)->gch.tt == LUA_TUPVAL, &((o)->uv)) -#define gco2th(o) check_exp((o)->gch.tt == LUA_TTHREAD, &((o)->th)) - -/* macro to convert any Lua object into a GCObject */ -#define obj2gco(v) (cast(GCObject *, (v))) - - -LUAI_FUNC lua_State *luaE_newthread (lua_State *L); -LUAI_FUNC void luaE_freethread (lua_State *L, lua_State *L1); - -#endif - diff --git a/lib/lua-5.1/src/lstring.c b/lib/lua-5.1/src/lstring.c deleted file mode 100644 index 4911315..0000000 --- a/lib/lua-5.1/src/lstring.c +++ /dev/null @@ -1,111 +0,0 @@ -/* -** $Id: lstring.c,v 2.8.1.1 2007/12/27 13:02:25 roberto Exp $ -** String table (keeps all strings handled by Lua) -** See Copyright Notice in lua.h -*/ - - -#include - -#define lstring_c -#define LUA_CORE - -#include "lua.h" - -#include "lmem.h" -#include "lobject.h" -#include "lstate.h" -#include "lstring.h" - - - -void luaS_resize (lua_State *L, int newsize) { - GCObject **newhash; - stringtable *tb; - int i; - if (G(L)->gcstate == GCSsweepstring) - return; /* cannot resize during GC traverse */ - newhash = luaM_newvector(L, newsize, GCObject *); - tb = &G(L)->strt; - for (i=0; isize; i++) { - GCObject *p = tb->hash[i]; - while (p) { /* for each node in the list */ - GCObject *next = p->gch.next; /* save next */ - unsigned int h = gco2ts(p)->hash; - int h1 = lmod(h, newsize); /* new position */ - lua_assert(cast_int(h%newsize) == lmod(h, newsize)); - p->gch.next = newhash[h1]; /* chain it */ - newhash[h1] = p; - p = next; - } - } - luaM_freearray(L, tb->hash, tb->size, TString *); - tb->size = newsize; - tb->hash = newhash; -} - - -static TString *newlstr (lua_State *L, const char *str, size_t l, - unsigned int h) { - TString *ts; - stringtable *tb; - if (l+1 > (MAX_SIZET - sizeof(TString))/sizeof(char)) - luaM_toobig(L); - ts = cast(TString *, luaM_malloc(L, (l+1)*sizeof(char)+sizeof(TString))); - ts->tsv.len = l; - ts->tsv.hash = h; - ts->tsv.marked = luaC_white(G(L)); - ts->tsv.tt = LUA_TSTRING; - ts->tsv.reserved = 0; - memcpy(ts+1, str, l*sizeof(char)); - ((char *)(ts+1))[l] = '\0'; /* ending 0 */ - tb = &G(L)->strt; - h = lmod(h, tb->size); - ts->tsv.next = tb->hash[h]; /* chain new entry */ - tb->hash[h] = obj2gco(ts); - tb->nuse++; - if (tb->nuse > cast(lu_int32, tb->size) && tb->size <= MAX_INT/2) - luaS_resize(L, tb->size*2); /* too crowded */ - return ts; -} - - -TString *luaS_newlstr (lua_State *L, const char *str, size_t l) { - GCObject *o; - unsigned int h = cast(unsigned int, l); /* seed */ - size_t step = (l>>5)+1; /* if string is too long, don't hash all its chars */ - size_t l1; - for (l1=l; l1>=step; l1-=step) /* compute hash */ - h = h ^ ((h<<5)+(h>>2)+cast(unsigned char, str[l1-1])); - for (o = G(L)->strt.hash[lmod(h, G(L)->strt.size)]; - o != NULL; - o = o->gch.next) { - TString *ts = rawgco2ts(o); - if (ts->tsv.len == l && (memcmp(str, getstr(ts), l) == 0)) { - /* string may be dead */ - if (isdead(G(L), o)) changewhite(o); - return ts; - } - } - return newlstr(L, str, l, h); /* not found */ -} - - -Udata *luaS_newudata (lua_State *L, size_t s, Table *e) { - Udata *u; - if (s > MAX_SIZET - sizeof(Udata)) - luaM_toobig(L); - u = cast(Udata *, luaM_malloc(L, s + sizeof(Udata))); - u->uv.marked = luaC_white(G(L)); /* is not finalized */ - u->uv.tt = LUA_TUSERDATA; - u->uv.len = s; - u->uv.metatable = NULL; - u->uv.env = e; - /* chain it on udata list (after main thread) */ - u->uv.next = G(L)->mainthread->next; - G(L)->mainthread->next = obj2gco(u); - return u; -} - diff --git a/lib/lua-5.1/src/lstring.h b/lib/lua-5.1/src/lstring.h deleted file mode 100644 index 73a2ff8..0000000 --- a/lib/lua-5.1/src/lstring.h +++ /dev/null @@ -1,31 +0,0 @@ -/* -** $Id: lstring.h,v 1.43.1.1 2007/12/27 13:02:25 roberto Exp $ -** String table (keep all strings handled by Lua) -** See Copyright Notice in lua.h -*/ - -#ifndef lstring_h -#define lstring_h - - -#include "lgc.h" -#include "lobject.h" -#include "lstate.h" - - -#define sizestring(s) (sizeof(union TString)+((s)->len+1)*sizeof(char)) - -#define sizeudata(u) (sizeof(union Udata)+(u)->len) - -#define luaS_new(L, s) (luaS_newlstr(L, s, strlen(s))) -#define luaS_newliteral(L, s) (luaS_newlstr(L, "" s, \ - (sizeof(s)/sizeof(char))-1)) - -#define luaS_fix(s) l_setbit((s)->tsv.marked, FIXEDBIT) - -LUAI_FUNC void luaS_resize (lua_State *L, int newsize); -LUAI_FUNC Udata *luaS_newudata (lua_State *L, size_t s, Table *e); -LUAI_FUNC TString *luaS_newlstr (lua_State *L, const char *str, size_t l); - - -#endif diff --git a/lib/lua-5.1/src/lstrlib.c b/lib/lua-5.1/src/lstrlib.c deleted file mode 100644 index 7a03489..0000000 --- a/lib/lua-5.1/src/lstrlib.c +++ /dev/null @@ -1,871 +0,0 @@ -/* -** $Id: lstrlib.c,v 1.132.1.5 2010/05/14 15:34:19 roberto Exp $ -** Standard library for string operations and pattern-matching -** See Copyright Notice in lua.h -*/ - - -#include -#include -#include -#include -#include - -#define lstrlib_c -#define LUA_LIB - -#include "lua.h" - -#include "lauxlib.h" -#include "lualib.h" - - -/* macro to `unsign' a character */ -#define uchar(c) ((unsigned char)(c)) - - - -static int str_len (lua_State *L) { - size_t l; - luaL_checklstring(L, 1, &l); - lua_pushinteger(L, l); - return 1; -} - - -static ptrdiff_t posrelat (ptrdiff_t pos, size_t len) { - /* relative string position: negative means back from end */ - if (pos < 0) pos += (ptrdiff_t)len + 1; - return (pos >= 0) ? pos : 0; -} - - -static int str_sub (lua_State *L) { - size_t l; - const char *s = luaL_checklstring(L, 1, &l); - ptrdiff_t start = posrelat(luaL_checkinteger(L, 2), l); - ptrdiff_t end = posrelat(luaL_optinteger(L, 3, -1), l); - if (start < 1) start = 1; - if (end > (ptrdiff_t)l) end = (ptrdiff_t)l; - if (start <= end) - lua_pushlstring(L, s+start-1, end-start+1); - else lua_pushliteral(L, ""); - return 1; -} - - -static int str_reverse (lua_State *L) { - size_t l; - luaL_Buffer b; - const char *s = luaL_checklstring(L, 1, &l); - luaL_buffinit(L, &b); - while (l--) luaL_addchar(&b, s[l]); - luaL_pushresult(&b); - return 1; -} - - -static int str_lower (lua_State *L) { - size_t l; - size_t i; - luaL_Buffer b; - const char *s = luaL_checklstring(L, 1, &l); - luaL_buffinit(L, &b); - for (i=0; i 0) - luaL_addlstring(&b, s, l); - luaL_pushresult(&b); - return 1; -} - - -static int str_byte (lua_State *L) { - size_t l; - const char *s = luaL_checklstring(L, 1, &l); - ptrdiff_t posi = posrelat(luaL_optinteger(L, 2, 1), l); - ptrdiff_t pose = posrelat(luaL_optinteger(L, 3, posi), l); - int n, i; - if (posi <= 0) posi = 1; - if ((size_t)pose > l) pose = l; - if (posi > pose) return 0; /* empty interval; return no values */ - n = (int)(pose - posi + 1); - if (posi + n <= pose) /* overflow? */ - luaL_error(L, "string slice too long"); - luaL_checkstack(L, n, "string slice too long"); - for (i=0; i= ms->level || ms->capture[l].len == CAP_UNFINISHED) - return luaL_error(ms->L, "invalid capture index"); - return l; -} - - -static int capture_to_close (MatchState *ms) { - int level = ms->level; - for (level--; level>=0; level--) - if (ms->capture[level].len == CAP_UNFINISHED) return level; - return luaL_error(ms->L, "invalid pattern capture"); -} - - -static const char *classend (MatchState *ms, const char *p) { - switch (*p++) { - case L_ESC: { - if (*p == '\0') - luaL_error(ms->L, "malformed pattern (ends with " LUA_QL("%%") ")"); - return p+1; - } - case '[': { - if (*p == '^') p++; - do { /* look for a `]' */ - if (*p == '\0') - luaL_error(ms->L, "malformed pattern (missing " LUA_QL("]") ")"); - if (*(p++) == L_ESC && *p != '\0') - p++; /* skip escapes (e.g. `%]') */ - } while (*p != ']'); - return p+1; - } - default: { - return p; - } - } -} - - -static int match_class (int c, int cl) { - int res; - switch (tolower(cl)) { - case 'a' : res = isalpha(c); break; - case 'c' : res = iscntrl(c); break; - case 'd' : res = isdigit(c); break; - case 'l' : res = islower(c); break; - case 'p' : res = ispunct(c); break; - case 's' : res = isspace(c); break; - case 'u' : res = isupper(c); break; - case 'w' : res = isalnum(c); break; - case 'x' : res = isxdigit(c); break; - case 'z' : res = (c == 0); break; - default: return (cl == c); - } - return (islower(cl) ? res : !res); -} - - -static int matchbracketclass (int c, const char *p, const char *ec) { - int sig = 1; - if (*(p+1) == '^') { - sig = 0; - p++; /* skip the `^' */ - } - while (++p < ec) { - if (*p == L_ESC) { - p++; - if (match_class(c, uchar(*p))) - return sig; - } - else if ((*(p+1) == '-') && (p+2 < ec)) { - p+=2; - if (uchar(*(p-2)) <= c && c <= uchar(*p)) - return sig; - } - else if (uchar(*p) == c) return sig; - } - return !sig; -} - - -static int singlematch (int c, const char *p, const char *ep) { - switch (*p) { - case '.': return 1; /* matches any char */ - case L_ESC: return match_class(c, uchar(*(p+1))); - case '[': return matchbracketclass(c, p, ep-1); - default: return (uchar(*p) == c); - } -} - - -static const char *match (MatchState *ms, const char *s, const char *p); - - -static const char *matchbalance (MatchState *ms, const char *s, - const char *p) { - if (*p == 0 || *(p+1) == 0) - luaL_error(ms->L, "unbalanced pattern"); - if (*s != *p) return NULL; - else { - int b = *p; - int e = *(p+1); - int cont = 1; - while (++s < ms->src_end) { - if (*s == e) { - if (--cont == 0) return s+1; - } - else if (*s == b) cont++; - } - } - return NULL; /* string ends out of balance */ -} - - -static const char *max_expand (MatchState *ms, const char *s, - const char *p, const char *ep) { - ptrdiff_t i = 0; /* counts maximum expand for item */ - while ((s+i)src_end && singlematch(uchar(*(s+i)), p, ep)) - i++; - /* keeps trying to match with the maximum repetitions */ - while (i>=0) { - const char *res = match(ms, (s+i), ep+1); - if (res) return res; - i--; /* else didn't match; reduce 1 repetition to try again */ - } - return NULL; -} - - -static const char *min_expand (MatchState *ms, const char *s, - const char *p, const char *ep) { - for (;;) { - const char *res = match(ms, s, ep+1); - if (res != NULL) - return res; - else if (ssrc_end && singlematch(uchar(*s), p, ep)) - s++; /* try with one more repetition */ - else return NULL; - } -} - - -static const char *start_capture (MatchState *ms, const char *s, - const char *p, int what) { - const char *res; - int level = ms->level; - if (level >= LUA_MAXCAPTURES) luaL_error(ms->L, "too many captures"); - ms->capture[level].init = s; - ms->capture[level].len = what; - ms->level = level+1; - if ((res=match(ms, s, p)) == NULL) /* match failed? */ - ms->level--; /* undo capture */ - return res; -} - - -static const char *end_capture (MatchState *ms, const char *s, - const char *p) { - int l = capture_to_close(ms); - const char *res; - ms->capture[l].len = s - ms->capture[l].init; /* close capture */ - if ((res = match(ms, s, p)) == NULL) /* match failed? */ - ms->capture[l].len = CAP_UNFINISHED; /* undo capture */ - return res; -} - - -static const char *match_capture (MatchState *ms, const char *s, int l) { - size_t len; - l = check_capture(ms, l); - len = ms->capture[l].len; - if ((size_t)(ms->src_end-s) >= len && - memcmp(ms->capture[l].init, s, len) == 0) - return s+len; - else return NULL; -} - - -static const char *match (MatchState *ms, const char *s, const char *p) { - init: /* using goto's to optimize tail recursion */ - switch (*p) { - case '(': { /* start capture */ - if (*(p+1) == ')') /* position capture? */ - return start_capture(ms, s, p+2, CAP_POSITION); - else - return start_capture(ms, s, p+1, CAP_UNFINISHED); - } - case ')': { /* end capture */ - return end_capture(ms, s, p+1); - } - case L_ESC: { - switch (*(p+1)) { - case 'b': { /* balanced string? */ - s = matchbalance(ms, s, p+2); - if (s == NULL) return NULL; - p+=4; goto init; /* else return match(ms, s, p+4); */ - } - case 'f': { /* frontier? */ - const char *ep; char previous; - p += 2; - if (*p != '[') - luaL_error(ms->L, "missing " LUA_QL("[") " after " - LUA_QL("%%f") " in pattern"); - ep = classend(ms, p); /* points to what is next */ - previous = (s == ms->src_init) ? '\0' : *(s-1); - if (matchbracketclass(uchar(previous), p, ep-1) || - !matchbracketclass(uchar(*s), p, ep-1)) return NULL; - p=ep; goto init; /* else return match(ms, s, ep); */ - } - default: { - if (isdigit(uchar(*(p+1)))) { /* capture results (%0-%9)? */ - s = match_capture(ms, s, uchar(*(p+1))); - if (s == NULL) return NULL; - p+=2; goto init; /* else return match(ms, s, p+2) */ - } - goto dflt; /* case default */ - } - } - } - case '\0': { /* end of pattern */ - return s; /* match succeeded */ - } - case '$': { - if (*(p+1) == '\0') /* is the `$' the last char in pattern? */ - return (s == ms->src_end) ? s : NULL; /* check end of string */ - else goto dflt; - } - default: dflt: { /* it is a pattern item */ - const char *ep = classend(ms, p); /* points to what is next */ - int m = ssrc_end && singlematch(uchar(*s), p, ep); - switch (*ep) { - case '?': { /* optional */ - const char *res; - if (m && ((res=match(ms, s+1, ep+1)) != NULL)) - return res; - p=ep+1; goto init; /* else return match(ms, s, ep+1); */ - } - case '*': { /* 0 or more repetitions */ - return max_expand(ms, s, p, ep); - } - case '+': { /* 1 or more repetitions */ - return (m ? max_expand(ms, s+1, p, ep) : NULL); - } - case '-': { /* 0 or more repetitions (minimum) */ - return min_expand(ms, s, p, ep); - } - default: { - if (!m) return NULL; - s++; p=ep; goto init; /* else return match(ms, s+1, ep); */ - } - } - } - } -} - - - -static const char *lmemfind (const char *s1, size_t l1, - const char *s2, size_t l2) { - if (l2 == 0) return s1; /* empty strings are everywhere */ - else if (l2 > l1) return NULL; /* avoids a negative `l1' */ - else { - const char *init; /* to search for a `*s2' inside `s1' */ - l2--; /* 1st char will be checked by `memchr' */ - l1 = l1-l2; /* `s2' cannot be found after that */ - while (l1 > 0 && (init = (const char *)memchr(s1, *s2, l1)) != NULL) { - init++; /* 1st char is already checked */ - if (memcmp(init, s2+1, l2) == 0) - return init-1; - else { /* correct `l1' and `s1' to try again */ - l1 -= init-s1; - s1 = init; - } - } - return NULL; /* not found */ - } -} - - -static void push_onecapture (MatchState *ms, int i, const char *s, - const char *e) { - if (i >= ms->level) { - if (i == 0) /* ms->level == 0, too */ - lua_pushlstring(ms->L, s, e - s); /* add whole match */ - else - luaL_error(ms->L, "invalid capture index"); - } - else { - ptrdiff_t l = ms->capture[i].len; - if (l == CAP_UNFINISHED) luaL_error(ms->L, "unfinished capture"); - if (l == CAP_POSITION) - lua_pushinteger(ms->L, ms->capture[i].init - ms->src_init + 1); - else - lua_pushlstring(ms->L, ms->capture[i].init, l); - } -} - - -static int push_captures (MatchState *ms, const char *s, const char *e) { - int i; - int nlevels = (ms->level == 0 && s) ? 1 : ms->level; - luaL_checkstack(ms->L, nlevels, "too many captures"); - for (i = 0; i < nlevels; i++) - push_onecapture(ms, i, s, e); - return nlevels; /* number of strings pushed */ -} - - -static int str_find_aux (lua_State *L, int find) { - size_t l1, l2; - const char *s = luaL_checklstring(L, 1, &l1); - const char *p = luaL_checklstring(L, 2, &l2); - ptrdiff_t init = posrelat(luaL_optinteger(L, 3, 1), l1) - 1; - if (init < 0) init = 0; - else if ((size_t)(init) > l1) init = (ptrdiff_t)l1; - if (find && (lua_toboolean(L, 4) || /* explicit request? */ - strpbrk(p, SPECIALS) == NULL)) { /* or no special characters? */ - /* do a plain search */ - const char *s2 = lmemfind(s+init, l1-init, p, l2); - if (s2) { - lua_pushinteger(L, s2-s+1); - lua_pushinteger(L, s2-s+l2); - return 2; - } - } - else { - MatchState ms; - int anchor = (*p == '^') ? (p++, 1) : 0; - const char *s1=s+init; - ms.L = L; - ms.src_init = s; - ms.src_end = s+l1; - do { - const char *res; - ms.level = 0; - if ((res=match(&ms, s1, p)) != NULL) { - if (find) { - lua_pushinteger(L, s1-s+1); /* start */ - lua_pushinteger(L, res-s); /* end */ - return push_captures(&ms, NULL, 0) + 2; - } - else - return push_captures(&ms, s1, res); - } - } while (s1++ < ms.src_end && !anchor); - } - lua_pushnil(L); /* not found */ - return 1; -} - - -static int str_find (lua_State *L) { - return str_find_aux(L, 1); -} - - -static int str_match (lua_State *L) { - return str_find_aux(L, 0); -} - - -static int gmatch_aux (lua_State *L) { - MatchState ms; - size_t ls; - const char *s = lua_tolstring(L, lua_upvalueindex(1), &ls); - const char *p = lua_tostring(L, lua_upvalueindex(2)); - const char *src; - ms.L = L; - ms.src_init = s; - ms.src_end = s+ls; - for (src = s + (size_t)lua_tointeger(L, lua_upvalueindex(3)); - src <= ms.src_end; - src++) { - const char *e; - ms.level = 0; - if ((e = match(&ms, src, p)) != NULL) { - lua_Integer newstart = e-s; - if (e == src) newstart++; /* empty match? go at least one position */ - lua_pushinteger(L, newstart); - lua_replace(L, lua_upvalueindex(3)); - return push_captures(&ms, src, e); - } - } - return 0; /* not found */ -} - - -static int gmatch (lua_State *L) { - luaL_checkstring(L, 1); - luaL_checkstring(L, 2); - lua_settop(L, 2); - lua_pushinteger(L, 0); - lua_pushcclosure(L, gmatch_aux, 3); - return 1; -} - - -static int gfind_nodef (lua_State *L) { - return luaL_error(L, LUA_QL("string.gfind") " was renamed to " - LUA_QL("string.gmatch")); -} - - -static void add_s (MatchState *ms, luaL_Buffer *b, const char *s, - const char *e) { - size_t l, i; - const char *news = lua_tolstring(ms->L, 3, &l); - for (i = 0; i < l; i++) { - if (news[i] != L_ESC) - luaL_addchar(b, news[i]); - else { - i++; /* skip ESC */ - if (!isdigit(uchar(news[i]))) - luaL_addchar(b, news[i]); - else if (news[i] == '0') - luaL_addlstring(b, s, e - s); - else { - push_onecapture(ms, news[i] - '1', s, e); - luaL_addvalue(b); /* add capture to accumulated result */ - } - } - } -} - - -static void add_value (MatchState *ms, luaL_Buffer *b, const char *s, - const char *e) { - lua_State *L = ms->L; - switch (lua_type(L, 3)) { - case LUA_TNUMBER: - case LUA_TSTRING: { - add_s(ms, b, s, e); - return; - } - case LUA_TFUNCTION: { - int n; - lua_pushvalue(L, 3); - n = push_captures(ms, s, e); - lua_call(L, n, 1); - break; - } - case LUA_TTABLE: { - push_onecapture(ms, 0, s, e); - lua_gettable(L, 3); - break; - } - } - if (!lua_toboolean(L, -1)) { /* nil or false? */ - lua_pop(L, 1); - lua_pushlstring(L, s, e - s); /* keep original text */ - } - else if (!lua_isstring(L, -1)) - luaL_error(L, "invalid replacement value (a %s)", luaL_typename(L, -1)); - luaL_addvalue(b); /* add result to accumulator */ -} - - -static int str_gsub (lua_State *L) { - size_t srcl; - const char *src = luaL_checklstring(L, 1, &srcl); - const char *p = luaL_checkstring(L, 2); - int tr = lua_type(L, 3); - int max_s = luaL_optint(L, 4, srcl+1); - int anchor = (*p == '^') ? (p++, 1) : 0; - int n = 0; - MatchState ms; - luaL_Buffer b; - luaL_argcheck(L, tr == LUA_TNUMBER || tr == LUA_TSTRING || - tr == LUA_TFUNCTION || tr == LUA_TTABLE, 3, - "string/function/table expected"); - luaL_buffinit(L, &b); - ms.L = L; - ms.src_init = src; - ms.src_end = src+srcl; - while (n < max_s) { - const char *e; - ms.level = 0; - e = match(&ms, src, p); - if (e) { - n++; - add_value(&ms, &b, src, e); - } - if (e && e>src) /* non empty match? */ - src = e; /* skip it */ - else if (src < ms.src_end) - luaL_addchar(&b, *src++); - else break; - if (anchor) break; - } - luaL_addlstring(&b, src, ms.src_end-src); - luaL_pushresult(&b); - lua_pushinteger(L, n); /* number of substitutions */ - return 2; -} - -/* }====================================================== */ - - -/* maximum size of each formatted item (> len(format('%99.99f', -1e308))) */ -#define MAX_ITEM 512 -/* valid flags in a format specification */ -#define FLAGS "-+ #0" -/* -** maximum size of each format specification (such as '%-099.99d') -** (+10 accounts for %99.99x plus margin of error) -*/ -#define MAX_FORMAT (sizeof(FLAGS) + sizeof(LUA_INTFRMLEN) + 10) - - -static void addquoted (lua_State *L, luaL_Buffer *b, int arg) { - size_t l; - const char *s = luaL_checklstring(L, arg, &l); - luaL_addchar(b, '"'); - while (l--) { - switch (*s) { - case '"': case '\\': case '\n': { - luaL_addchar(b, '\\'); - luaL_addchar(b, *s); - break; - } - case '\r': { - luaL_addlstring(b, "\\r", 2); - break; - } - case '\0': { - luaL_addlstring(b, "\\000", 4); - break; - } - default: { - luaL_addchar(b, *s); - break; - } - } - s++; - } - luaL_addchar(b, '"'); -} - -static const char *scanformat (lua_State *L, const char *strfrmt, char *form) { - const char *p = strfrmt; - while (*p != '\0' && strchr(FLAGS, *p) != NULL) p++; /* skip flags */ - if ((size_t)(p - strfrmt) >= sizeof(FLAGS)) - luaL_error(L, "invalid format (repeated flags)"); - if (isdigit(uchar(*p))) p++; /* skip width */ - if (isdigit(uchar(*p))) p++; /* (2 digits at most) */ - if (*p == '.') { - p++; - if (isdigit(uchar(*p))) p++; /* skip precision */ - if (isdigit(uchar(*p))) p++; /* (2 digits at most) */ - } - if (isdigit(uchar(*p))) - luaL_error(L, "invalid format (width or precision too long)"); - *(form++) = '%'; - strncpy(form, strfrmt, p - strfrmt + 1); - form += p - strfrmt + 1; - *form = '\0'; - return p; -} - - -static void addintlen (char *form) { - size_t l = strlen(form); - char spec = form[l - 1]; - strcpy(form + l - 1, LUA_INTFRMLEN); - form[l + sizeof(LUA_INTFRMLEN) - 2] = spec; - form[l + sizeof(LUA_INTFRMLEN) - 1] = '\0'; -} - - -static int str_format (lua_State *L) { - int top = lua_gettop(L); - int arg = 1; - size_t sfl; - const char *strfrmt = luaL_checklstring(L, arg, &sfl); - const char *strfrmt_end = strfrmt+sfl; - luaL_Buffer b; - luaL_buffinit(L, &b); - while (strfrmt < strfrmt_end) { - if (*strfrmt != L_ESC) - luaL_addchar(&b, *strfrmt++); - else if (*++strfrmt == L_ESC) - luaL_addchar(&b, *strfrmt++); /* %% */ - else { /* format item */ - char form[MAX_FORMAT]; /* to store the format (`%...') */ - char buff[MAX_ITEM]; /* to store the formatted item */ - if (++arg > top) - luaL_argerror(L, arg, "no value"); - strfrmt = scanformat(L, strfrmt, form); - switch (*strfrmt++) { - case 'c': { - sprintf(buff, form, (int)luaL_checknumber(L, arg)); - break; - } - case 'd': case 'i': { - addintlen(form); - sprintf(buff, form, (LUA_INTFRM_T)luaL_checknumber(L, arg)); - break; - } - case 'o': case 'u': case 'x': case 'X': { - addintlen(form); - sprintf(buff, form, (unsigned LUA_INTFRM_T)luaL_checknumber(L, arg)); - break; - } - case 'e': case 'E': case 'f': - case 'g': case 'G': { - sprintf(buff, form, (double)luaL_checknumber(L, arg)); - break; - } - case 'q': { - addquoted(L, &b, arg); - continue; /* skip the 'addsize' at the end */ - } - case 's': { - size_t l; - const char *s = luaL_checklstring(L, arg, &l); - if (!strchr(form, '.') && l >= 100) { - /* no precision and string is too long to be formatted; - keep original string */ - lua_pushvalue(L, arg); - luaL_addvalue(&b); - continue; /* skip the `addsize' at the end */ - } - else { - sprintf(buff, form, s); - break; - } - } - default: { /* also treat cases `pnLlh' */ - return luaL_error(L, "invalid option " LUA_QL("%%%c") " to " - LUA_QL("format"), *(strfrmt - 1)); - } - } - luaL_addlstring(&b, buff, strlen(buff)); - } - } - luaL_pushresult(&b); - return 1; -} - - -static const luaL_Reg strlib[] = { - {"byte", str_byte}, - {"char", str_char}, - {"dump", str_dump}, - {"find", str_find}, - {"format", str_format}, - {"gfind", gfind_nodef}, - {"gmatch", gmatch}, - {"gsub", str_gsub}, - {"len", str_len}, - {"lower", str_lower}, - {"match", str_match}, - {"rep", str_rep}, - {"reverse", str_reverse}, - {"sub", str_sub}, - {"upper", str_upper}, - {NULL, NULL} -}; - - -static void createmetatable (lua_State *L) { - lua_createtable(L, 0, 1); /* create metatable for strings */ - lua_pushliteral(L, ""); /* dummy string */ - lua_pushvalue(L, -2); - lua_setmetatable(L, -2); /* set string metatable */ - lua_pop(L, 1); /* pop dummy string */ - lua_pushvalue(L, -2); /* string library... */ - lua_setfield(L, -2, "__index"); /* ...is the __index metamethod */ - lua_pop(L, 1); /* pop metatable */ -} - - -/* -** Open string library -*/ -LUALIB_API int luaopen_string (lua_State *L) { - luaL_register(L, LUA_STRLIBNAME, strlib); -#if defined(LUA_COMPAT_GFIND) - lua_getfield(L, -1, "gmatch"); - lua_setfield(L, -2, "gfind"); -#endif - createmetatable(L); - return 1; -} - diff --git a/lib/lua-5.1/src/ltable.c b/lib/lua-5.1/src/ltable.c deleted file mode 100644 index ec84f4f..0000000 --- a/lib/lua-5.1/src/ltable.c +++ /dev/null @@ -1,588 +0,0 @@ -/* -** $Id: ltable.c,v 2.32.1.2 2007/12/28 15:32:23 roberto Exp $ -** Lua tables (hash) -** See Copyright Notice in lua.h -*/ - - -/* -** Implementation of tables (aka arrays, objects, or hash tables). -** Tables keep its elements in two parts: an array part and a hash part. -** Non-negative integer keys are all candidates to be kept in the array -** part. The actual size of the array is the largest `n' such that at -** least half the slots between 0 and n are in use. -** Hash uses a mix of chained scatter table with Brent's variation. -** A main invariant of these tables is that, if an element is not -** in its main position (i.e. the `original' position that its hash gives -** to it), then the colliding element is in its own main position. -** Hence even when the load factor reaches 100%, performance remains good. -*/ - -#include -#include - -#define ltable_c -#define LUA_CORE - -#include "lua.h" - -#include "ldebug.h" -#include "ldo.h" -#include "lgc.h" -#include "lmem.h" -#include "lobject.h" -#include "lstate.h" -#include "ltable.h" - - -/* -** max size of array part is 2^MAXBITS -*/ -#if LUAI_BITSINT > 26 -#define MAXBITS 26 -#else -#define MAXBITS (LUAI_BITSINT-2) -#endif - -#define MAXASIZE (1 << MAXBITS) - - -#define hashpow2(t,n) (gnode(t, lmod((n), sizenode(t)))) - -#define hashstr(t,str) hashpow2(t, (str)->tsv.hash) -#define hashboolean(t,p) hashpow2(t, p) - - -/* -** for some types, it is better to avoid modulus by power of 2, as -** they tend to have many 2 factors. -*/ -#define hashmod(t,n) (gnode(t, ((n) % ((sizenode(t)-1)|1)))) - - -#define hashpointer(t,p) hashmod(t, IntPoint(p)) - - -/* -** number of ints inside a lua_Number -*/ -#define numints cast_int(sizeof(lua_Number)/sizeof(int)) - - - -#define dummynode (&dummynode_) - -static const Node dummynode_ = { - {{NULL}, LUA_TNIL}, /* value */ - {{{NULL}, LUA_TNIL, NULL}} /* key */ -}; - - -/* -** hash for lua_Numbers -*/ -static Node *hashnum (const Table *t, lua_Number n) { - unsigned int a[numints]; - int i; - if (luai_numeq(n, 0)) /* avoid problems with -0 */ - return gnode(t, 0); - memcpy(a, &n, sizeof(a)); - for (i = 1; i < numints; i++) a[0] += a[i]; - return hashmod(t, a[0]); -} - - - -/* -** returns the `main' position of an element in a table (that is, the index -** of its hash value) -*/ -static Node *mainposition (const Table *t, const TValue *key) { - switch (ttype(key)) { - case LUA_TNUMBER: - return hashnum(t, nvalue(key)); - case LUA_TSTRING: - return hashstr(t, rawtsvalue(key)); - case LUA_TBOOLEAN: - return hashboolean(t, bvalue(key)); - case LUA_TLIGHTUSERDATA: - return hashpointer(t, pvalue(key)); - default: - return hashpointer(t, gcvalue(key)); - } -} - - -/* -** returns the index for `key' if `key' is an appropriate key to live in -** the array part of the table, -1 otherwise. -*/ -static int arrayindex (const TValue *key) { - if (ttisnumber(key)) { - lua_Number n = nvalue(key); - int k; - lua_number2int(k, n); - if (luai_numeq(cast_num(k), n)) - return k; - } - return -1; /* `key' did not match some condition */ -} - - -/* -** returns the index of a `key' for table traversals. First goes all -** elements in the array part, then elements in the hash part. The -** beginning of a traversal is signalled by -1. -*/ -static int findindex (lua_State *L, Table *t, StkId key) { - int i; - if (ttisnil(key)) return -1; /* first iteration */ - i = arrayindex(key); - if (0 < i && i <= t->sizearray) /* is `key' inside array part? */ - return i-1; /* yes; that's the index (corrected to C) */ - else { - Node *n = mainposition(t, key); - do { /* check whether `key' is somewhere in the chain */ - /* key may be dead already, but it is ok to use it in `next' */ - if (luaO_rawequalObj(key2tval(n), key) || - (ttype(gkey(n)) == LUA_TDEADKEY && iscollectable(key) && - gcvalue(gkey(n)) == gcvalue(key))) { - i = cast_int(n - gnode(t, 0)); /* key index in hash table */ - /* hash elements are numbered after array ones */ - return i + t->sizearray; - } - else n = gnext(n); - } while (n); - luaG_runerror(L, "invalid key to " LUA_QL("next")); /* key not found */ - return 0; /* to avoid warnings */ - } -} - - -int luaH_next (lua_State *L, Table *t, StkId key) { - int i = findindex(L, t, key); /* find original element */ - for (i++; i < t->sizearray; i++) { /* try first array part */ - if (!ttisnil(&t->array[i])) { /* a non-nil value? */ - setnvalue(key, cast_num(i+1)); - setobj2s(L, key+1, &t->array[i]); - return 1; - } - } - for (i -= t->sizearray; i < sizenode(t); i++) { /* then hash part */ - if (!ttisnil(gval(gnode(t, i)))) { /* a non-nil value? */ - setobj2s(L, key, key2tval(gnode(t, i))); - setobj2s(L, key+1, gval(gnode(t, i))); - return 1; - } - } - return 0; /* no more elements */ -} - - -/* -** {============================================================= -** Rehash -** ============================================================== -*/ - - -static int computesizes (int nums[], int *narray) { - int i; - int twotoi; /* 2^i */ - int a = 0; /* number of elements smaller than 2^i */ - int na = 0; /* number of elements to go to array part */ - int n = 0; /* optimal size for array part */ - for (i = 0, twotoi = 1; twotoi/2 < *narray; i++, twotoi *= 2) { - if (nums[i] > 0) { - a += nums[i]; - if (a > twotoi/2) { /* more than half elements present? */ - n = twotoi; /* optimal size (till now) */ - na = a; /* all elements smaller than n will go to array part */ - } - } - if (a == *narray) break; /* all elements already counted */ - } - *narray = n; - lua_assert(*narray/2 <= na && na <= *narray); - return na; -} - - -static int countint (const TValue *key, int *nums) { - int k = arrayindex(key); - if (0 < k && k <= MAXASIZE) { /* is `key' an appropriate array index? */ - nums[ceillog2(k)]++; /* count as such */ - return 1; - } - else - return 0; -} - - -static int numusearray (const Table *t, int *nums) { - int lg; - int ttlg; /* 2^lg */ - int ause = 0; /* summation of `nums' */ - int i = 1; /* count to traverse all array keys */ - for (lg=0, ttlg=1; lg<=MAXBITS; lg++, ttlg*=2) { /* for each slice */ - int lc = 0; /* counter */ - int lim = ttlg; - if (lim > t->sizearray) { - lim = t->sizearray; /* adjust upper limit */ - if (i > lim) - break; /* no more elements to count */ - } - /* count elements in range (2^(lg-1), 2^lg] */ - for (; i <= lim; i++) { - if (!ttisnil(&t->array[i-1])) - lc++; - } - nums[lg] += lc; - ause += lc; - } - return ause; -} - - -static int numusehash (const Table *t, int *nums, int *pnasize) { - int totaluse = 0; /* total number of elements */ - int ause = 0; /* summation of `nums' */ - int i = sizenode(t); - while (i--) { - Node *n = &t->node[i]; - if (!ttisnil(gval(n))) { - ause += countint(key2tval(n), nums); - totaluse++; - } - } - *pnasize += ause; - return totaluse; -} - - -static void setarrayvector (lua_State *L, Table *t, int size) { - int i; - luaM_reallocvector(L, t->array, t->sizearray, size, TValue); - for (i=t->sizearray; iarray[i]); - t->sizearray = size; -} - - -static void setnodevector (lua_State *L, Table *t, int size) { - int lsize; - if (size == 0) { /* no elements to hash part? */ - t->node = cast(Node *, dummynode); /* use common `dummynode' */ - lsize = 0; - } - else { - int i; - lsize = ceillog2(size); - if (lsize > MAXBITS) - luaG_runerror(L, "table overflow"); - size = twoto(lsize); - t->node = luaM_newvector(L, size, Node); - for (i=0; ilsizenode = cast_byte(lsize); - t->lastfree = gnode(t, size); /* all positions are free */ -} - - -static void resize (lua_State *L, Table *t, int nasize, int nhsize) { - int i; - int oldasize = t->sizearray; - int oldhsize = t->lsizenode; - Node *nold = t->node; /* save old hash ... */ - if (nasize > oldasize) /* array part must grow? */ - setarrayvector(L, t, nasize); - /* create new hash part with appropriate size */ - setnodevector(L, t, nhsize); - if (nasize < oldasize) { /* array part must shrink? */ - t->sizearray = nasize; - /* re-insert elements from vanishing slice */ - for (i=nasize; iarray[i])) - setobjt2t(L, luaH_setnum(L, t, i+1), &t->array[i]); - } - /* shrink array */ - luaM_reallocvector(L, t->array, oldasize, nasize, TValue); - } - /* re-insert elements from hash part */ - for (i = twoto(oldhsize) - 1; i >= 0; i--) { - Node *old = nold+i; - if (!ttisnil(gval(old))) - setobjt2t(L, luaH_set(L, t, key2tval(old)), gval(old)); - } - if (nold != dummynode) - luaM_freearray(L, nold, twoto(oldhsize), Node); /* free old array */ -} - - -void luaH_resizearray (lua_State *L, Table *t, int nasize) { - int nsize = (t->node == dummynode) ? 0 : sizenode(t); - resize(L, t, nasize, nsize); -} - - -static void rehash (lua_State *L, Table *t, const TValue *ek) { - int nasize, na; - int nums[MAXBITS+1]; /* nums[i] = number of keys between 2^(i-1) and 2^i */ - int i; - int totaluse; - for (i=0; i<=MAXBITS; i++) nums[i] = 0; /* reset counts */ - nasize = numusearray(t, nums); /* count keys in array part */ - totaluse = nasize; /* all those keys are integer keys */ - totaluse += numusehash(t, nums, &nasize); /* count keys in hash part */ - /* count extra key */ - nasize += countint(ek, nums); - totaluse++; - /* compute new size for array part */ - na = computesizes(nums, &nasize); - /* resize the table to new computed sizes */ - resize(L, t, nasize, totaluse - na); -} - - - -/* -** }============================================================= -*/ - - -Table *luaH_new (lua_State *L, int narray, int nhash) { - Table *t = luaM_new(L, Table); - luaC_link(L, obj2gco(t), LUA_TTABLE); - t->metatable = NULL; - t->flags = cast_byte(~0); - /* temporary values (kept only if some malloc fails) */ - t->array = NULL; - t->sizearray = 0; - t->lsizenode = 0; - t->node = cast(Node *, dummynode); - setarrayvector(L, t, narray); - setnodevector(L, t, nhash); - return t; -} - - -void luaH_free (lua_State *L, Table *t) { - if (t->node != dummynode) - luaM_freearray(L, t->node, sizenode(t), Node); - luaM_freearray(L, t->array, t->sizearray, TValue); - luaM_free(L, t); -} - - -static Node *getfreepos (Table *t) { - while (t->lastfree-- > t->node) { - if (ttisnil(gkey(t->lastfree))) - return t->lastfree; - } - return NULL; /* could not find a free place */ -} - - - -/* -** inserts a new key into a hash table; first, check whether key's main -** position is free. If not, check whether colliding node is in its main -** position or not: if it is not, move colliding node to an empty place and -** put new key in its main position; otherwise (colliding node is in its main -** position), new key goes to an empty position. -*/ -static TValue *newkey (lua_State *L, Table *t, const TValue *key) { - Node *mp = mainposition(t, key); - if (!ttisnil(gval(mp)) || mp == dummynode) { - Node *othern; - Node *n = getfreepos(t); /* get a free place */ - if (n == NULL) { /* cannot find a free place? */ - rehash(L, t, key); /* grow table */ - return luaH_set(L, t, key); /* re-insert key into grown table */ - } - lua_assert(n != dummynode); - othern = mainposition(t, key2tval(mp)); - if (othern != mp) { /* is colliding node out of its main position? */ - /* yes; move colliding node into free position */ - while (gnext(othern) != mp) othern = gnext(othern); /* find previous */ - gnext(othern) = n; /* redo the chain with `n' in place of `mp' */ - *n = *mp; /* copy colliding node into free pos. (mp->next also goes) */ - gnext(mp) = NULL; /* now `mp' is free */ - setnilvalue(gval(mp)); - } - else { /* colliding node is in its own main position */ - /* new node will go into free position */ - gnext(n) = gnext(mp); /* chain new position */ - gnext(mp) = n; - mp = n; - } - } - gkey(mp)->value = key->value; gkey(mp)->tt = key->tt; - luaC_barriert(L, t, key); - lua_assert(ttisnil(gval(mp))); - return gval(mp); -} - - -/* -** search function for integers -*/ -const TValue *luaH_getnum (Table *t, int key) { - /* (1 <= key && key <= t->sizearray) */ - if (cast(unsigned int, key-1) < cast(unsigned int, t->sizearray)) - return &t->array[key-1]; - else { - lua_Number nk = cast_num(key); - Node *n = hashnum(t, nk); - do { /* check whether `key' is somewhere in the chain */ - if (ttisnumber(gkey(n)) && luai_numeq(nvalue(gkey(n)), nk)) - return gval(n); /* that's it */ - else n = gnext(n); - } while (n); - return luaO_nilobject; - } -} - - -/* -** search function for strings -*/ -const TValue *luaH_getstr (Table *t, TString *key) { - Node *n = hashstr(t, key); - do { /* check whether `key' is somewhere in the chain */ - if (ttisstring(gkey(n)) && rawtsvalue(gkey(n)) == key) - return gval(n); /* that's it */ - else n = gnext(n); - } while (n); - return luaO_nilobject; -} - - -/* -** main search function -*/ -const TValue *luaH_get (Table *t, const TValue *key) { - switch (ttype(key)) { - case LUA_TNIL: return luaO_nilobject; - case LUA_TSTRING: return luaH_getstr(t, rawtsvalue(key)); - case LUA_TNUMBER: { - int k; - lua_Number n = nvalue(key); - lua_number2int(k, n); - if (luai_numeq(cast_num(k), nvalue(key))) /* index is int? */ - return luaH_getnum(t, k); /* use specialized version */ - /* else go through */ - } - default: { - Node *n = mainposition(t, key); - do { /* check whether `key' is somewhere in the chain */ - if (luaO_rawequalObj(key2tval(n), key)) - return gval(n); /* that's it */ - else n = gnext(n); - } while (n); - return luaO_nilobject; - } - } -} - - -TValue *luaH_set (lua_State *L, Table *t, const TValue *key) { - const TValue *p = luaH_get(t, key); - t->flags = 0; - if (p != luaO_nilobject) - return cast(TValue *, p); - else { - if (ttisnil(key)) luaG_runerror(L, "table index is nil"); - else if (ttisnumber(key) && luai_numisnan(nvalue(key))) - luaG_runerror(L, "table index is NaN"); - return newkey(L, t, key); - } -} - - -TValue *luaH_setnum (lua_State *L, Table *t, int key) { - const TValue *p = luaH_getnum(t, key); - if (p != luaO_nilobject) - return cast(TValue *, p); - else { - TValue k; - setnvalue(&k, cast_num(key)); - return newkey(L, t, &k); - } -} - - -TValue *luaH_setstr (lua_State *L, Table *t, TString *key) { - const TValue *p = luaH_getstr(t, key); - if (p != luaO_nilobject) - return cast(TValue *, p); - else { - TValue k; - setsvalue(L, &k, key); - return newkey(L, t, &k); - } -} - - -static int unbound_search (Table *t, unsigned int j) { - unsigned int i = j; /* i is zero or a present index */ - j++; - /* find `i' and `j' such that i is present and j is not */ - while (!ttisnil(luaH_getnum(t, j))) { - i = j; - j *= 2; - if (j > cast(unsigned int, MAX_INT)) { /* overflow? */ - /* table was built with bad purposes: resort to linear search */ - i = 1; - while (!ttisnil(luaH_getnum(t, i))) i++; - return i - 1; - } - } - /* now do a binary search between them */ - while (j - i > 1) { - unsigned int m = (i+j)/2; - if (ttisnil(luaH_getnum(t, m))) j = m; - else i = m; - } - return i; -} - - -/* -** Try to find a boundary in table `t'. A `boundary' is an integer index -** such that t[i] is non-nil and t[i+1] is nil (and 0 if t[1] is nil). -*/ -int luaH_getn (Table *t) { - unsigned int j = t->sizearray; - if (j > 0 && ttisnil(&t->array[j - 1])) { - /* there is a boundary in the array part: (binary) search for it */ - unsigned int i = 0; - while (j - i > 1) { - unsigned int m = (i+j)/2; - if (ttisnil(&t->array[m - 1])) j = m; - else i = m; - } - return i; - } - /* else must find a boundary in hash part */ - else if (t->node == dummynode) /* hash part is empty? */ - return j; /* that is easy... */ - else return unbound_search(t, j); -} - - - -#if defined(LUA_DEBUG) - -Node *luaH_mainposition (const Table *t, const TValue *key) { - return mainposition(t, key); -} - -int luaH_isdummy (Node *n) { return n == dummynode; } - -#endif diff --git a/lib/lua-5.1/src/ltable.h b/lib/lua-5.1/src/ltable.h deleted file mode 100644 index f5b9d5e..0000000 --- a/lib/lua-5.1/src/ltable.h +++ /dev/null @@ -1,40 +0,0 @@ -/* -** $Id: ltable.h,v 2.10.1.1 2007/12/27 13:02:25 roberto Exp $ -** Lua tables (hash) -** See Copyright Notice in lua.h -*/ - -#ifndef ltable_h -#define ltable_h - -#include "lobject.h" - - -#define gnode(t,i) (&(t)->node[i]) -#define gkey(n) (&(n)->i_key.nk) -#define gval(n) (&(n)->i_val) -#define gnext(n) ((n)->i_key.nk.next) - -#define key2tval(n) (&(n)->i_key.tvk) - - -LUAI_FUNC const TValue *luaH_getnum (Table *t, int key); -LUAI_FUNC TValue *luaH_setnum (lua_State *L, Table *t, int key); -LUAI_FUNC const TValue *luaH_getstr (Table *t, TString *key); -LUAI_FUNC TValue *luaH_setstr (lua_State *L, Table *t, TString *key); -LUAI_FUNC const TValue *luaH_get (Table *t, const TValue *key); -LUAI_FUNC TValue *luaH_set (lua_State *L, Table *t, const TValue *key); -LUAI_FUNC Table *luaH_new (lua_State *L, int narray, int lnhash); -LUAI_FUNC void luaH_resizearray (lua_State *L, Table *t, int nasize); -LUAI_FUNC void luaH_free (lua_State *L, Table *t); -LUAI_FUNC int luaH_next (lua_State *L, Table *t, StkId key); -LUAI_FUNC int luaH_getn (Table *t); - - -#if defined(LUA_DEBUG) -LUAI_FUNC Node *luaH_mainposition (const Table *t, const TValue *key); -LUAI_FUNC int luaH_isdummy (Node *n); -#endif - - -#endif diff --git a/lib/lua-5.1/src/ltablib.c b/lib/lua-5.1/src/ltablib.c deleted file mode 100644 index b6d9cb4..0000000 --- a/lib/lua-5.1/src/ltablib.c +++ /dev/null @@ -1,287 +0,0 @@ -/* -** $Id: ltablib.c,v 1.38.1.3 2008/02/14 16:46:58 roberto Exp $ -** Library for Table Manipulation -** See Copyright Notice in lua.h -*/ - - -#include - -#define ltablib_c -#define LUA_LIB - -#include "lua.h" - -#include "lauxlib.h" -#include "lualib.h" - - -#define aux_getn(L,n) (luaL_checktype(L, n, LUA_TTABLE), luaL_getn(L, n)) - - -static int foreachi (lua_State *L) { - int i; - int n = aux_getn(L, 1); - luaL_checktype(L, 2, LUA_TFUNCTION); - for (i=1; i <= n; i++) { - lua_pushvalue(L, 2); /* function */ - lua_pushinteger(L, i); /* 1st argument */ - lua_rawgeti(L, 1, i); /* 2nd argument */ - lua_call(L, 2, 1); - if (!lua_isnil(L, -1)) - return 1; - lua_pop(L, 1); /* remove nil result */ - } - return 0; -} - - -static int foreach (lua_State *L) { - luaL_checktype(L, 1, LUA_TTABLE); - luaL_checktype(L, 2, LUA_TFUNCTION); - lua_pushnil(L); /* first key */ - while (lua_next(L, 1)) { - lua_pushvalue(L, 2); /* function */ - lua_pushvalue(L, -3); /* key */ - lua_pushvalue(L, -3); /* value */ - lua_call(L, 2, 1); - if (!lua_isnil(L, -1)) - return 1; - lua_pop(L, 2); /* remove value and result */ - } - return 0; -} - - -static int maxn (lua_State *L) { - lua_Number max = 0; - luaL_checktype(L, 1, LUA_TTABLE); - lua_pushnil(L); /* first key */ - while (lua_next(L, 1)) { - lua_pop(L, 1); /* remove value */ - if (lua_type(L, -1) == LUA_TNUMBER) { - lua_Number v = lua_tonumber(L, -1); - if (v > max) max = v; - } - } - lua_pushnumber(L, max); - return 1; -} - - -static int getn (lua_State *L) { - lua_pushinteger(L, aux_getn(L, 1)); - return 1; -} - - -static int setn (lua_State *L) { - luaL_checktype(L, 1, LUA_TTABLE); -#ifndef luaL_setn - luaL_setn(L, 1, luaL_checkint(L, 2)); -#else - luaL_error(L, LUA_QL("setn") " is obsolete"); -#endif - lua_pushvalue(L, 1); - return 1; -} - - -static int tinsert (lua_State *L) { - int e = aux_getn(L, 1) + 1; /* first empty element */ - int pos; /* where to insert new element */ - switch (lua_gettop(L)) { - case 2: { /* called with only 2 arguments */ - pos = e; /* insert new element at the end */ - break; - } - case 3: { - int i; - pos = luaL_checkint(L, 2); /* 2nd argument is the position */ - if (pos > e) e = pos; /* `grow' array if necessary */ - for (i = e; i > pos; i--) { /* move up elements */ - lua_rawgeti(L, 1, i-1); - lua_rawseti(L, 1, i); /* t[i] = t[i-1] */ - } - break; - } - default: { - return luaL_error(L, "wrong number of arguments to " LUA_QL("insert")); - } - } - luaL_setn(L, 1, e); /* new size */ - lua_rawseti(L, 1, pos); /* t[pos] = v */ - return 0; -} - - -static int tremove (lua_State *L) { - int e = aux_getn(L, 1); - int pos = luaL_optint(L, 2, e); - if (!(1 <= pos && pos <= e)) /* position is outside bounds? */ - return 0; /* nothing to remove */ - luaL_setn(L, 1, e - 1); /* t.n = n-1 */ - lua_rawgeti(L, 1, pos); /* result = t[pos] */ - for ( ;pos= P */ - while (lua_rawgeti(L, 1, ++i), sort_comp(L, -1, -2)) { - if (i>u) luaL_error(L, "invalid order function for sorting"); - lua_pop(L, 1); /* remove a[i] */ - } - /* repeat --j until a[j] <= P */ - while (lua_rawgeti(L, 1, --j), sort_comp(L, -3, -1)) { - if (j - -#define ltm_c -#define LUA_CORE - -#include "lua.h" - -#include "lobject.h" -#include "lstate.h" -#include "lstring.h" -#include "ltable.h" -#include "ltm.h" - - - -const char *const luaT_typenames[] = { - "nil", "boolean", "userdata", "number", - "string", "table", "function", "userdata", "thread", - "proto", "upval" -}; - - -void luaT_init (lua_State *L) { - static const char *const luaT_eventname[] = { /* ORDER TM */ - "__index", "__newindex", - "__gc", "__mode", "__eq", - "__add", "__sub", "__mul", "__div", "__mod", - "__pow", "__unm", "__len", "__lt", "__le", - "__concat", "__call" - }; - int i; - for (i=0; itmname[i] = luaS_new(L, luaT_eventname[i]); - luaS_fix(G(L)->tmname[i]); /* never collect these names */ - } -} - - -/* -** function to be used with macro "fasttm": optimized for absence of -** tag methods -*/ -const TValue *luaT_gettm (Table *events, TMS event, TString *ename) { - const TValue *tm = luaH_getstr(events, ename); - lua_assert(event <= TM_EQ); - if (ttisnil(tm)) { /* no tag method? */ - events->flags |= cast_byte(1u<metatable; - break; - case LUA_TUSERDATA: - mt = uvalue(o)->metatable; - break; - default: - mt = G(L)->mt[ttype(o)]; - } - return (mt ? luaH_getstr(mt, G(L)->tmname[event]) : luaO_nilobject); -} - diff --git a/lib/lua-5.1/src/ltm.h b/lib/lua-5.1/src/ltm.h deleted file mode 100644 index 64343b7..0000000 --- a/lib/lua-5.1/src/ltm.h +++ /dev/null @@ -1,54 +0,0 @@ -/* -** $Id: ltm.h,v 2.6.1.1 2007/12/27 13:02:25 roberto Exp $ -** Tag methods -** See Copyright Notice in lua.h -*/ - -#ifndef ltm_h -#define ltm_h - - -#include "lobject.h" - - -/* -* WARNING: if you change the order of this enumeration, -* grep "ORDER TM" -*/ -typedef enum { - TM_INDEX, - TM_NEWINDEX, - TM_GC, - TM_MODE, - TM_EQ, /* last tag method with `fast' access */ - TM_ADD, - TM_SUB, - TM_MUL, - TM_DIV, - TM_MOD, - TM_POW, - TM_UNM, - TM_LEN, - TM_LT, - TM_LE, - TM_CONCAT, - TM_CALL, - TM_N /* number of elements in the enum */ -} TMS; - - - -#define gfasttm(g,et,e) ((et) == NULL ? NULL : \ - ((et)->flags & (1u<<(e))) ? NULL : luaT_gettm(et, e, (g)->tmname[e])) - -#define fasttm(l,et,e) gfasttm(G(l), et, e) - -LUAI_DATA const char *const luaT_typenames[]; - - -LUAI_FUNC const TValue *luaT_gettm (Table *events, TMS event, TString *ename); -LUAI_FUNC const TValue *luaT_gettmbyobj (lua_State *L, const TValue *o, - TMS event); -LUAI_FUNC void luaT_init (lua_State *L); - -#endif diff --git a/lib/lua-5.1/src/lua.c b/lib/lua-5.1/src/lua.c deleted file mode 100644 index 3a46609..0000000 --- a/lib/lua-5.1/src/lua.c +++ /dev/null @@ -1,392 +0,0 @@ -/* -** $Id: lua.c,v 1.160.1.2 2007/12/28 15:32:23 roberto Exp $ -** Lua stand-alone interpreter -** See Copyright Notice in lua.h -*/ - - -#include -#include -#include -#include - -#define lua_c - -#include "lua.h" - -#include "lauxlib.h" -#include "lualib.h" - - - -static lua_State *globalL = NULL; - -static const char *progname = LUA_PROGNAME; - - - -static void lstop (lua_State *L, lua_Debug *ar) { - (void)ar; /* unused arg. */ - lua_sethook(L, NULL, 0, 0); - luaL_error(L, "interrupted!"); -} - - -static void laction (int i) { - signal(i, SIG_DFL); /* if another SIGINT happens before lstop, - terminate process (default action) */ - lua_sethook(globalL, lstop, LUA_MASKCALL | LUA_MASKRET | LUA_MASKCOUNT, 1); -} - - -static void print_usage (void) { - fprintf(stderr, - "usage: %s [options] [script [args]].\n" - "Available options are:\n" - " -e stat execute string " LUA_QL("stat") "\n" - " -l name require library " LUA_QL("name") "\n" - " -i enter interactive mode after executing " LUA_QL("script") "\n" - " -v show version information\n" - " -- stop handling options\n" - " - execute stdin and stop handling options\n" - , - progname); - fflush(stderr); -} - - -static void l_message (const char *pname, const char *msg) { - if (pname) fprintf(stderr, "%s: ", pname); - fprintf(stderr, "%s\n", msg); - fflush(stderr); -} - - -static int report (lua_State *L, int status) { - if (status && !lua_isnil(L, -1)) { - const char *msg = lua_tostring(L, -1); - if (msg == NULL) msg = "(error object is not a string)"; - l_message(progname, msg); - lua_pop(L, 1); - } - return status; -} - - -static int traceback (lua_State *L) { - if (!lua_isstring(L, 1)) /* 'message' not a string? */ - return 1; /* keep it intact */ - lua_getfield(L, LUA_GLOBALSINDEX, "debug"); - if (!lua_istable(L, -1)) { - lua_pop(L, 1); - return 1; - } - lua_getfield(L, -1, "traceback"); - if (!lua_isfunction(L, -1)) { - lua_pop(L, 2); - return 1; - } - lua_pushvalue(L, 1); /* pass error message */ - lua_pushinteger(L, 2); /* skip this function and traceback */ - lua_call(L, 2, 1); /* call debug.traceback */ - return 1; -} - - -static int docall (lua_State *L, int narg, int clear) { - int status; - int base = lua_gettop(L) - narg; /* function index */ - lua_pushcfunction(L, traceback); /* push traceback function */ - lua_insert(L, base); /* put it under chunk and args */ - signal(SIGINT, laction); - status = lua_pcall(L, narg, (clear ? 0 : LUA_MULTRET), base); - signal(SIGINT, SIG_DFL); - lua_remove(L, base); /* remove traceback function */ - /* force a complete garbage collection in case of errors */ - if (status != 0) lua_gc(L, LUA_GCCOLLECT, 0); - return status; -} - - -static void print_version (void) { - l_message(NULL, LUA_RELEASE " " LUA_COPYRIGHT); -} - - -static int getargs (lua_State *L, char **argv, int n) { - int narg; - int i; - int argc = 0; - while (argv[argc]) argc++; /* count total number of arguments */ - narg = argc - (n + 1); /* number of arguments to the script */ - luaL_checkstack(L, narg + 3, "too many arguments to script"); - for (i=n+1; i < argc; i++) - lua_pushstring(L, argv[i]); - lua_createtable(L, narg, n + 1); - for (i=0; i < argc; i++) { - lua_pushstring(L, argv[i]); - lua_rawseti(L, -2, i - n); - } - return narg; -} - - -static int dofile (lua_State *L, const char *name) { - int status = luaL_loadfile(L, name) || docall(L, 0, 1); - return report(L, status); -} - - -static int dostring (lua_State *L, const char *s, const char *name) { - int status = luaL_loadbuffer(L, s, strlen(s), name) || docall(L, 0, 1); - return report(L, status); -} - - -static int dolibrary (lua_State *L, const char *name) { - lua_getglobal(L, "require"); - lua_pushstring(L, name); - return report(L, docall(L, 1, 1)); -} - - -static const char *get_prompt (lua_State *L, int firstline) { - const char *p; - lua_getfield(L, LUA_GLOBALSINDEX, firstline ? "_PROMPT" : "_PROMPT2"); - p = lua_tostring(L, -1); - if (p == NULL) p = (firstline ? LUA_PROMPT : LUA_PROMPT2); - lua_pop(L, 1); /* remove global */ - return p; -} - - -static int incomplete (lua_State *L, int status) { - if (status == LUA_ERRSYNTAX) { - size_t lmsg; - const char *msg = lua_tolstring(L, -1, &lmsg); - const char *tp = msg + lmsg - (sizeof(LUA_QL("")) - 1); - if (strstr(msg, LUA_QL("")) == tp) { - lua_pop(L, 1); - return 1; - } - } - return 0; /* else... */ -} - - -static int pushline (lua_State *L, int firstline) { - char buffer[LUA_MAXINPUT]; - char *b = buffer; - size_t l; - const char *prmt = get_prompt(L, firstline); - if (lua_readline(L, b, prmt) == 0) - return 0; /* no input */ - l = strlen(b); - if (l > 0 && b[l-1] == '\n') /* line ends with newline? */ - b[l-1] = '\0'; /* remove it */ - if (firstline && b[0] == '=') /* first line starts with `=' ? */ - lua_pushfstring(L, "return %s", b+1); /* change it to `return' */ - else - lua_pushstring(L, b); - lua_freeline(L, b); - return 1; -} - - -static int loadline (lua_State *L) { - int status; - lua_settop(L, 0); - if (!pushline(L, 1)) - return -1; /* no input */ - for (;;) { /* repeat until gets a complete line */ - status = luaL_loadbuffer(L, lua_tostring(L, 1), lua_strlen(L, 1), "=stdin"); - if (!incomplete(L, status)) break; /* cannot try to add lines? */ - if (!pushline(L, 0)) /* no more input? */ - return -1; - lua_pushliteral(L, "\n"); /* add a new line... */ - lua_insert(L, -2); /* ...between the two lines */ - lua_concat(L, 3); /* join them */ - } - lua_saveline(L, 1); - lua_remove(L, 1); /* remove line */ - return status; -} - - -static void dotty (lua_State *L) { - int status; - const char *oldprogname = progname; - progname = NULL; - while ((status = loadline(L)) != -1) { - if (status == 0) status = docall(L, 0, 0); - report(L, status); - if (status == 0 && lua_gettop(L) > 0) { /* any result to print? */ - lua_getglobal(L, "print"); - lua_insert(L, 1); - if (lua_pcall(L, lua_gettop(L)-1, 0, 0) != 0) - l_message(progname, lua_pushfstring(L, - "error calling " LUA_QL("print") " (%s)", - lua_tostring(L, -1))); - } - } - lua_settop(L, 0); /* clear stack */ - fputs("\n", stdout); - fflush(stdout); - progname = oldprogname; -} - - -static int handle_script (lua_State *L, char **argv, int n) { - int status; - const char *fname; - int narg = getargs(L, argv, n); /* collect arguments */ - lua_setglobal(L, "arg"); - fname = argv[n]; - if (strcmp(fname, "-") == 0 && strcmp(argv[n-1], "--") != 0) - fname = NULL; /* stdin */ - status = luaL_loadfile(L, fname); - lua_insert(L, -(narg+1)); - if (status == 0) - status = docall(L, narg, 0); - else - lua_pop(L, narg); - return report(L, status); -} - - -/* check that argument has no extra characters at the end */ -#define notail(x) {if ((x)[2] != '\0') return -1;} - - -static int collectargs (char **argv, int *pi, int *pv, int *pe) { - int i; - for (i = 1; argv[i] != NULL; i++) { - if (argv[i][0] != '-') /* not an option? */ - return i; - switch (argv[i][1]) { /* option */ - case '-': - notail(argv[i]); - return (argv[i+1] != NULL ? i+1 : 0); - case '\0': - return i; - case 'i': - notail(argv[i]); - *pi = 1; /* go through */ - case 'v': - notail(argv[i]); - *pv = 1; - break; - case 'e': - *pe = 1; /* go through */ - case 'l': - if (argv[i][2] == '\0') { - i++; - if (argv[i] == NULL) return -1; - } - break; - default: return -1; /* invalid option */ - } - } - return 0; -} - - -static int runargs (lua_State *L, char **argv, int n) { - int i; - for (i = 1; i < n; i++) { - if (argv[i] == NULL) continue; - lua_assert(argv[i][0] == '-'); - switch (argv[i][1]) { /* option */ - case 'e': { - const char *chunk = argv[i] + 2; - if (*chunk == '\0') chunk = argv[++i]; - lua_assert(chunk != NULL); - if (dostring(L, chunk, "=(command line)") != 0) - return 1; - break; - } - case 'l': { - const char *filename = argv[i] + 2; - if (*filename == '\0') filename = argv[++i]; - lua_assert(filename != NULL); - if (dolibrary(L, filename)) - return 1; /* stop if file fails */ - break; - } - default: break; - } - } - return 0; -} - - -static int handle_luainit (lua_State *L) { - const char *init = getenv(LUA_INIT); - if (init == NULL) return 0; /* status OK */ - else if (init[0] == '@') - return dofile(L, init+1); - else - return dostring(L, init, "=" LUA_INIT); -} - - -struct Smain { - int argc; - char **argv; - int status; -}; - - -static int pmain (lua_State *L) { - struct Smain *s = (struct Smain *)lua_touserdata(L, 1); - char **argv = s->argv; - int script; - int has_i = 0, has_v = 0, has_e = 0; - globalL = L; - if (argv[0] && argv[0][0]) progname = argv[0]; - lua_gc(L, LUA_GCSTOP, 0); /* stop collector during initialization */ - luaL_openlibs(L); /* open libraries */ - lua_gc(L, LUA_GCRESTART, 0); - s->status = handle_luainit(L); - if (s->status != 0) return 0; - script = collectargs(argv, &has_i, &has_v, &has_e); - if (script < 0) { /* invalid args? */ - print_usage(); - s->status = 1; - return 0; - } - if (has_v) print_version(); - s->status = runargs(L, argv, (script > 0) ? script : s->argc); - if (s->status != 0) return 0; - if (script) - s->status = handle_script(L, argv, script); - if (s->status != 0) return 0; - if (has_i) - dotty(L); - else if (script == 0 && !has_e && !has_v) { - if (lua_stdin_is_tty()) { - print_version(); - dotty(L); - } - else dofile(L, NULL); /* executes stdin as a file */ - } - return 0; -} - - -int main (int argc, char **argv) { - int status; - struct Smain s; - lua_State *L = lua_open(); /* create state */ - if (L == NULL) { - l_message(argv[0], "cannot create state: not enough memory"); - return EXIT_FAILURE; - } - s.argc = argc; - s.argv = argv; - status = lua_cpcall(L, &pmain, &s); - report(L, status); - lua_close(L); - return (status || s.status) ? EXIT_FAILURE : EXIT_SUCCESS; -} - diff --git a/lib/lua-5.1/src/lua.h b/lib/lua-5.1/src/lua.h deleted file mode 100644 index a4b73e7..0000000 --- a/lib/lua-5.1/src/lua.h +++ /dev/null @@ -1,388 +0,0 @@ -/* -** $Id: lua.h,v 1.218.1.7 2012/01/13 20:36:20 roberto Exp $ -** Lua - An Extensible Extension Language -** Lua.org, PUC-Rio, Brazil (http://www.lua.org) -** See Copyright Notice at the end of this file -*/ - - -#ifndef lua_h -#define lua_h - -#include -#include - - -#include "luaconf.h" - - -#define LUA_VERSION "Lua 5.1" -#define LUA_RELEASE "Lua 5.1.5" -#define LUA_VERSION_NUM 501 -#define LUA_COPYRIGHT "Copyright (C) 1994-2012 Lua.org, PUC-Rio" -#define LUA_AUTHORS "R. Ierusalimschy, L. H. de Figueiredo & W. Celes" - - -/* mark for precompiled code (`Lua') */ -#define LUA_SIGNATURE "\033Lua" - -/* option for multiple returns in `lua_pcall' and `lua_call' */ -#define LUA_MULTRET (-1) - - -/* -** pseudo-indices -*/ -#define LUA_REGISTRYINDEX (-10000) -#define LUA_ENVIRONINDEX (-10001) -#define LUA_GLOBALSINDEX (-10002) -#define lua_upvalueindex(i) (LUA_GLOBALSINDEX-(i)) - - -/* thread status; 0 is OK */ -#define LUA_YIELD 1 -#define LUA_ERRRUN 2 -#define LUA_ERRSYNTAX 3 -#define LUA_ERRMEM 4 -#define LUA_ERRERR 5 - - -typedef struct lua_State lua_State; - -typedef int (*lua_CFunction) (lua_State *L); - - -/* -** functions that read/write blocks when loading/dumping Lua chunks -*/ -typedef const char * (*lua_Reader) (lua_State *L, void *ud, size_t *sz); - -typedef int (*lua_Writer) (lua_State *L, const void* p, size_t sz, void* ud); - - -/* -** prototype for memory-allocation functions -*/ -typedef void * (*lua_Alloc) (void *ud, void *ptr, size_t osize, size_t nsize); - - -/* -** basic types -*/ -#define LUA_TNONE (-1) - -#define LUA_TNIL 0 -#define LUA_TBOOLEAN 1 -#define LUA_TLIGHTUSERDATA 2 -#define LUA_TNUMBER 3 -#define LUA_TSTRING 4 -#define LUA_TTABLE 5 -#define LUA_TFUNCTION 6 -#define LUA_TUSERDATA 7 -#define LUA_TTHREAD 8 - - - -/* minimum Lua stack available to a C function */ -#define LUA_MINSTACK 20 - - -/* -** generic extra include file -*/ -#if defined(LUA_USER_H) -#include LUA_USER_H -#endif - - -/* type of numbers in Lua */ -typedef LUA_NUMBER lua_Number; - - -/* type for integer functions */ -typedef LUA_INTEGER lua_Integer; - - - -/* -** state manipulation -*/ -LUA_API lua_State *(lua_newstate) (lua_Alloc f, void *ud); -LUA_API void (lua_close) (lua_State *L); -LUA_API lua_State *(lua_newthread) (lua_State *L); - -LUA_API lua_CFunction (lua_atpanic) (lua_State *L, lua_CFunction panicf); - - -/* -** basic stack manipulation -*/ -LUA_API int (lua_gettop) (lua_State *L); -LUA_API void (lua_settop) (lua_State *L, int idx); -LUA_API void (lua_pushvalue) (lua_State *L, int idx); -LUA_API void (lua_remove) (lua_State *L, int idx); -LUA_API void (lua_insert) (lua_State *L, int idx); -LUA_API void (lua_replace) (lua_State *L, int idx); -LUA_API int (lua_checkstack) (lua_State *L, int sz); - -LUA_API void (lua_xmove) (lua_State *from, lua_State *to, int n); - - -/* -** access functions (stack -> C) -*/ - -LUA_API int (lua_isnumber) (lua_State *L, int idx); -LUA_API int (lua_isstring) (lua_State *L, int idx); -LUA_API int (lua_iscfunction) (lua_State *L, int idx); -LUA_API int (lua_isuserdata) (lua_State *L, int idx); -LUA_API int (lua_type) (lua_State *L, int idx); -LUA_API const char *(lua_typename) (lua_State *L, int tp); - -LUA_API int (lua_equal) (lua_State *L, int idx1, int idx2); -LUA_API int (lua_rawequal) (lua_State *L, int idx1, int idx2); -LUA_API int (lua_lessthan) (lua_State *L, int idx1, int idx2); - -LUA_API lua_Number (lua_tonumber) (lua_State *L, int idx); -LUA_API lua_Integer (lua_tointeger) (lua_State *L, int idx); -LUA_API int (lua_toboolean) (lua_State *L, int idx); -LUA_API const char *(lua_tolstring) (lua_State *L, int idx, size_t *len); -LUA_API size_t (lua_objlen) (lua_State *L, int idx); -LUA_API lua_CFunction (lua_tocfunction) (lua_State *L, int idx); -LUA_API void *(lua_touserdata) (lua_State *L, int idx); -LUA_API lua_State *(lua_tothread) (lua_State *L, int idx); -LUA_API const void *(lua_topointer) (lua_State *L, int idx); - - -/* -** push functions (C -> stack) -*/ -LUA_API void (lua_pushnil) (lua_State *L); -LUA_API void (lua_pushnumber) (lua_State *L, lua_Number n); -LUA_API void (lua_pushinteger) (lua_State *L, lua_Integer n); -LUA_API void (lua_pushlstring) (lua_State *L, const char *s, size_t l); -LUA_API void (lua_pushstring) (lua_State *L, const char *s); -LUA_API const char *(lua_pushvfstring) (lua_State *L, const char *fmt, - va_list argp); -LUA_API const char *(lua_pushfstring) (lua_State *L, const char *fmt, ...); -LUA_API void (lua_pushcclosure) (lua_State *L, lua_CFunction fn, int n); -LUA_API void (lua_pushboolean) (lua_State *L, int b); -LUA_API void (lua_pushlightuserdata) (lua_State *L, void *p); -LUA_API int (lua_pushthread) (lua_State *L); - - -/* -** get functions (Lua -> stack) -*/ -LUA_API void (lua_gettable) (lua_State *L, int idx); -LUA_API void (lua_getfield) (lua_State *L, int idx, const char *k); -LUA_API void (lua_rawget) (lua_State *L, int idx); -LUA_API void (lua_rawgeti) (lua_State *L, int idx, int n); -LUA_API void (lua_createtable) (lua_State *L, int narr, int nrec); -LUA_API void *(lua_newuserdata) (lua_State *L, size_t sz); -LUA_API int (lua_getmetatable) (lua_State *L, int objindex); -LUA_API void (lua_getfenv) (lua_State *L, int idx); - - -/* -** set functions (stack -> Lua) -*/ -LUA_API void (lua_settable) (lua_State *L, int idx); -LUA_API void (lua_setfield) (lua_State *L, int idx, const char *k); -LUA_API void (lua_rawset) (lua_State *L, int idx); -LUA_API void (lua_rawseti) (lua_State *L, int idx, int n); -LUA_API int (lua_setmetatable) (lua_State *L, int objindex); -LUA_API int (lua_setfenv) (lua_State *L, int idx); - - -/* -** `load' and `call' functions (load and run Lua code) -*/ -LUA_API void (lua_call) (lua_State *L, int nargs, int nresults); -LUA_API int (lua_pcall) (lua_State *L, int nargs, int nresults, int errfunc); -LUA_API int (lua_cpcall) (lua_State *L, lua_CFunction func, void *ud); -LUA_API int (lua_load) (lua_State *L, lua_Reader reader, void *dt, - const char *chunkname); - -LUA_API int (lua_dump) (lua_State *L, lua_Writer writer, void *data); - - -/* -** coroutine functions -*/ -LUA_API int (lua_yield) (lua_State *L, int nresults); -LUA_API int (lua_resume) (lua_State *L, int narg); -LUA_API int (lua_status) (lua_State *L); - -/* -** garbage-collection function and options -*/ - -#define LUA_GCSTOP 0 -#define LUA_GCRESTART 1 -#define LUA_GCCOLLECT 2 -#define LUA_GCCOUNT 3 -#define LUA_GCCOUNTB 4 -#define LUA_GCSTEP 5 -#define LUA_GCSETPAUSE 6 -#define LUA_GCSETSTEPMUL 7 - -LUA_API int (lua_gc) (lua_State *L, int what, int data); - - -/* -** miscellaneous functions -*/ - -LUA_API int (lua_error) (lua_State *L); - -LUA_API int (lua_next) (lua_State *L, int idx); - -LUA_API void (lua_concat) (lua_State *L, int n); - -LUA_API lua_Alloc (lua_getallocf) (lua_State *L, void **ud); -LUA_API void lua_setallocf (lua_State *L, lua_Alloc f, void *ud); - - - -/* -** =============================================================== -** some useful macros -** =============================================================== -*/ - -#define lua_pop(L,n) lua_settop(L, -(n)-1) - -#define lua_newtable(L) lua_createtable(L, 0, 0) - -#define lua_register(L,n,f) (lua_pushcfunction(L, (f)), lua_setglobal(L, (n))) - -#define lua_pushcfunction(L,f) lua_pushcclosure(L, (f), 0) - -#define lua_strlen(L,i) lua_objlen(L, (i)) - -#define lua_isfunction(L,n) (lua_type(L, (n)) == LUA_TFUNCTION) -#define lua_istable(L,n) (lua_type(L, (n)) == LUA_TTABLE) -#define lua_islightuserdata(L,n) (lua_type(L, (n)) == LUA_TLIGHTUSERDATA) -#define lua_isnil(L,n) (lua_type(L, (n)) == LUA_TNIL) -#define lua_isboolean(L,n) (lua_type(L, (n)) == LUA_TBOOLEAN) -#define lua_isthread(L,n) (lua_type(L, (n)) == LUA_TTHREAD) -#define lua_isnone(L,n) (lua_type(L, (n)) == LUA_TNONE) -#define lua_isnoneornil(L, n) (lua_type(L, (n)) <= 0) - -#define lua_pushliteral(L, s) \ - lua_pushlstring(L, "" s, (sizeof(s)/sizeof(char))-1) - -#define lua_setglobal(L,s) lua_setfield(L, LUA_GLOBALSINDEX, (s)) -#define lua_getglobal(L,s) lua_getfield(L, LUA_GLOBALSINDEX, (s)) - -#define lua_tostring(L,i) lua_tolstring(L, (i), NULL) - - - -/* -** compatibility macros and functions -*/ - -#define lua_open() luaL_newstate() - -#define lua_getregistry(L) lua_pushvalue(L, LUA_REGISTRYINDEX) - -#define lua_getgccount(L) lua_gc(L, LUA_GCCOUNT, 0) - -#define lua_Chunkreader lua_Reader -#define lua_Chunkwriter lua_Writer - - -/* hack */ -LUA_API void lua_setlevel (lua_State *from, lua_State *to); - - -/* -** {====================================================================== -** Debug API -** ======================================================================= -*/ - - -/* -** Event codes -*/ -#define LUA_HOOKCALL 0 -#define LUA_HOOKRET 1 -#define LUA_HOOKLINE 2 -#define LUA_HOOKCOUNT 3 -#define LUA_HOOKTAILRET 4 - - -/* -** Event masks -*/ -#define LUA_MASKCALL (1 << LUA_HOOKCALL) -#define LUA_MASKRET (1 << LUA_HOOKRET) -#define LUA_MASKLINE (1 << LUA_HOOKLINE) -#define LUA_MASKCOUNT (1 << LUA_HOOKCOUNT) - -typedef struct lua_Debug lua_Debug; /* activation record */ - - -/* Functions to be called by the debuger in specific events */ -typedef void (*lua_Hook) (lua_State *L, lua_Debug *ar); - - -LUA_API int lua_getstack (lua_State *L, int level, lua_Debug *ar); -LUA_API int lua_getinfo (lua_State *L, const char *what, lua_Debug *ar); -LUA_API const char *lua_getlocal (lua_State *L, const lua_Debug *ar, int n); -LUA_API const char *lua_setlocal (lua_State *L, const lua_Debug *ar, int n); -LUA_API const char *lua_getupvalue (lua_State *L, int funcindex, int n); -LUA_API const char *lua_setupvalue (lua_State *L, int funcindex, int n); - -LUA_API int lua_sethook (lua_State *L, lua_Hook func, int mask, int count); -LUA_API lua_Hook lua_gethook (lua_State *L); -LUA_API int lua_gethookmask (lua_State *L); -LUA_API int lua_gethookcount (lua_State *L); - - -struct lua_Debug { - int event; - const char *name; /* (n) */ - const char *namewhat; /* (n) `global', `local', `field', `method' */ - const char *what; /* (S) `Lua', `C', `main', `tail' */ - const char *source; /* (S) */ - int currentline; /* (l) */ - int nups; /* (u) number of upvalues */ - int linedefined; /* (S) */ - int lastlinedefined; /* (S) */ - char short_src[LUA_IDSIZE]; /* (S) */ - /* private part */ - int i_ci; /* active function */ -}; - -/* }====================================================================== */ - - -/****************************************************************************** -* Copyright (C) 1994-2012 Lua.org, PUC-Rio. All rights reserved. -* -* Permission is hereby granted, free of charge, to any person obtaining -* a copy of this software and associated documentation files (the -* "Software"), to deal in the Software without restriction, including -* without limitation the rights to use, copy, modify, merge, publish, -* distribute, sublicense, and/or sell copies of the Software, and to -* permit persons to whom the Software is furnished to do so, subject to -* the following conditions: -* -* The above copyright notice and this permission notice shall be -* included in all copies or substantial portions of the Software. -* -* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, -* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF -* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. -* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY -* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, -* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE -* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. -******************************************************************************/ - - -#endif diff --git a/lib/lua-5.1/src/luac.c b/lib/lua-5.1/src/luac.c deleted file mode 100644 index d070173..0000000 --- a/lib/lua-5.1/src/luac.c +++ /dev/null @@ -1,200 +0,0 @@ -/* -** $Id: luac.c,v 1.54 2006/06/02 17:37:11 lhf Exp $ -** Lua compiler (saves bytecodes to files; also list bytecodes) -** See Copyright Notice in lua.h -*/ - -#include -#include -#include -#include - -#define luac_c -#define LUA_CORE - -#include "lua.h" -#include "lauxlib.h" - -#include "ldo.h" -#include "lfunc.h" -#include "lmem.h" -#include "lobject.h" -#include "lopcodes.h" -#include "lstring.h" -#include "lundump.h" - -#define PROGNAME "luac" /* default program name */ -#define OUTPUT PROGNAME ".out" /* default output file */ - -static int listing=0; /* list bytecodes? */ -static int dumping=1; /* dump bytecodes? */ -static int stripping=0; /* strip debug information? */ -static char Output[]={ OUTPUT }; /* default output file name */ -static const char* output=Output; /* actual output file name */ -static const char* progname=PROGNAME; /* actual program name */ - -static void fatal(const char* message) -{ - fprintf(stderr,"%s: %s\n",progname,message); - exit(EXIT_FAILURE); -} - -static void cannot(const char* what) -{ - fprintf(stderr,"%s: cannot %s %s: %s\n",progname,what,output,strerror(errno)); - exit(EXIT_FAILURE); -} - -static void usage(const char* message) -{ - if (*message=='-') - fprintf(stderr,"%s: unrecognized option " LUA_QS "\n",progname,message); - else - fprintf(stderr,"%s: %s\n",progname,message); - fprintf(stderr, - "usage: %s [options] [filenames].\n" - "Available options are:\n" - " - process stdin\n" - " -l list\n" - " -o name output to file " LUA_QL("name") " (default is \"%s\")\n" - " -p parse only\n" - " -s strip debug information\n" - " -v show version information\n" - " -- stop handling options\n", - progname,Output); - exit(EXIT_FAILURE); -} - -#define IS(s) (strcmp(argv[i],s)==0) - -static int doargs(int argc, char* argv[]) -{ - int i; - int version=0; - if (argv[0]!=NULL && *argv[0]!=0) progname=argv[0]; - for (i=1; itop+(i))->l.p) - -static const Proto* combine(lua_State* L, int n) -{ - if (n==1) - return toproto(L,-1); - else - { - int i,pc; - Proto* f=luaF_newproto(L); - setptvalue2s(L,L->top,f); incr_top(L); - f->source=luaS_newliteral(L,"=(" PROGNAME ")"); - f->maxstacksize=1; - pc=2*n+1; - f->code=luaM_newvector(L,pc,Instruction); - f->sizecode=pc; - f->p=luaM_newvector(L,n,Proto*); - f->sizep=n; - pc=0; - for (i=0; ip[i]=toproto(L,i-n-1); - f->code[pc++]=CREATE_ABx(OP_CLOSURE,0,i); - f->code[pc++]=CREATE_ABC(OP_CALL,0,1,1); - } - f->code[pc++]=CREATE_ABC(OP_RETURN,0,1,0); - return f; - } -} - -static int writer(lua_State* L, const void* p, size_t size, void* u) -{ - UNUSED(L); - return (fwrite(p,size,1,(FILE*)u)!=1) && (size!=0); -} - -struct Smain { - int argc; - char** argv; -}; - -static int pmain(lua_State* L) -{ - struct Smain* s = (struct Smain*)lua_touserdata(L, 1); - int argc=s->argc; - char** argv=s->argv; - const Proto* f; - int i; - if (!lua_checkstack(L,argc)) fatal("too many input files"); - for (i=0; i1); - if (dumping) - { - FILE* D= (output==NULL) ? stdout : fopen(output,"wb"); - if (D==NULL) cannot("open"); - lua_lock(L); - luaU_dump(L,f,writer,D,stripping); - lua_unlock(L); - if (ferror(D)) cannot("write"); - if (fclose(D)) cannot("close"); - } - return 0; -} - -int main(int argc, char* argv[]) -{ - lua_State* L; - struct Smain s; - int i=doargs(argc,argv); - argc-=i; argv+=i; - if (argc<=0) usage("no input files given"); - L=lua_open(); - if (L==NULL) fatal("not enough memory for state"); - s.argc=argc; - s.argv=argv; - if (lua_cpcall(L,pmain,&s)!=0) fatal(lua_tostring(L,-1)); - lua_close(L); - return EXIT_SUCCESS; -} diff --git a/lib/lua-5.1/src/luaconf.h b/lib/lua-5.1/src/luaconf.h deleted file mode 100644 index e2cb261..0000000 --- a/lib/lua-5.1/src/luaconf.h +++ /dev/null @@ -1,763 +0,0 @@ -/* -** $Id: luaconf.h,v 1.82.1.7 2008/02/11 16:25:08 roberto Exp $ -** Configuration file for Lua -** See Copyright Notice in lua.h -*/ - - -#ifndef lconfig_h -#define lconfig_h - -#include -#include - - -/* -** ================================================================== -** Search for "@@" to find all configurable definitions. -** =================================================================== -*/ - - -/* -@@ LUA_ANSI controls the use of non-ansi features. -** CHANGE it (define it) if you want Lua to avoid the use of any -** non-ansi feature or library. -*/ -#if defined(__STRICT_ANSI__) -#define LUA_ANSI -#endif - - -#if !defined(LUA_ANSI) && defined(_WIN32) -#define LUA_WIN -#endif - -#if defined(LUA_USE_LINUX) -#define LUA_USE_POSIX -#define LUA_USE_DLOPEN /* needs an extra library: -ldl */ -#define LUA_USE_READLINE /* needs some extra libraries */ -#endif - -#if defined(LUA_USE_MACOSX) -#define LUA_USE_POSIX -#define LUA_DL_DYLD /* does not need extra library */ -#endif - - - -/* -@@ LUA_USE_POSIX includes all functionallity listed as X/Open System -@* Interfaces Extension (XSI). -** CHANGE it (define it) if your system is XSI compatible. -*/ -#if defined(LUA_USE_POSIX) -#define LUA_USE_MKSTEMP -#define LUA_USE_ISATTY -#define LUA_USE_POPEN -#define LUA_USE_ULONGJMP -#endif - - -/* -@@ LUA_PATH and LUA_CPATH are the names of the environment variables that -@* Lua check to set its paths. -@@ LUA_INIT is the name of the environment variable that Lua -@* checks for initialization code. -** CHANGE them if you want different names. -*/ -#define LUA_PATH "LUA_PATH" -#define LUA_CPATH "LUA_CPATH" -#define LUA_INIT "LUA_INIT" - - -/* -@@ LUA_PATH_DEFAULT is the default path that Lua uses to look for -@* Lua libraries. -@@ LUA_CPATH_DEFAULT is the default path that Lua uses to look for -@* C libraries. -** CHANGE them if your machine has a non-conventional directory -** hierarchy or if you want to install your libraries in -** non-conventional directories. -*/ -#if defined(_WIN32) -/* -** In Windows, any exclamation mark ('!') in the path is replaced by the -** path of the directory of the executable file of the current process. -*/ -#define LUA_LDIR "!\\lua\\" -#define LUA_CDIR "!\\" -#define LUA_PATH_DEFAULT \ - ".\\?.lua;" LUA_LDIR"?.lua;" LUA_LDIR"?\\init.lua;" \ - LUA_CDIR"?.lua;" LUA_CDIR"?\\init.lua" -#define LUA_CPATH_DEFAULT \ - ".\\?.dll;" LUA_CDIR"?.dll;" LUA_CDIR"loadall.dll" - -#else -#define LUA_ROOT "/usr/local/" -#define LUA_LDIR LUA_ROOT "share/lua/5.1/" -#define LUA_CDIR LUA_ROOT "lib/lua/5.1/" -#define LUA_PATH_DEFAULT \ - "./?.lua;" LUA_LDIR"?.lua;" LUA_LDIR"?/init.lua;" \ - LUA_CDIR"?.lua;" LUA_CDIR"?/init.lua" -#define LUA_CPATH_DEFAULT \ - "./?.so;" LUA_CDIR"?.so;" LUA_CDIR"loadall.so" -#endif - - -/* -@@ LUA_DIRSEP is the directory separator (for submodules). -** CHANGE it if your machine does not use "/" as the directory separator -** and is not Windows. (On Windows Lua automatically uses "\".) -*/ -#if defined(_WIN32) -#define LUA_DIRSEP "\\" -#else -#define LUA_DIRSEP "/" -#endif - - -/* -@@ LUA_PATHSEP is the character that separates templates in a path. -@@ LUA_PATH_MARK is the string that marks the substitution points in a -@* template. -@@ LUA_EXECDIR in a Windows path is replaced by the executable's -@* directory. -@@ LUA_IGMARK is a mark to ignore all before it when bulding the -@* luaopen_ function name. -** CHANGE them if for some reason your system cannot use those -** characters. (E.g., if one of those characters is a common character -** in file/directory names.) Probably you do not need to change them. -*/ -#define LUA_PATHSEP ";" -#define LUA_PATH_MARK "?" -#define LUA_EXECDIR "!" -#define LUA_IGMARK "-" - - -/* -@@ LUA_INTEGER is the integral type used by lua_pushinteger/lua_tointeger. -** CHANGE that if ptrdiff_t is not adequate on your machine. (On most -** machines, ptrdiff_t gives a good choice between int or long.) -*/ -#define LUA_INTEGER ptrdiff_t - - -/* -@@ LUA_API is a mark for all core API functions. -@@ LUALIB_API is a mark for all standard library functions. -** CHANGE them if you need to define those functions in some special way. -** For instance, if you want to create one Windows DLL with the core and -** the libraries, you may want to use the following definition (define -** LUA_BUILD_AS_DLL to get it). -*/ -#if defined(LUA_BUILD_AS_DLL) - -#if defined(LUA_CORE) || defined(LUA_LIB) -#define LUA_API __declspec(dllexport) -#else -#define LUA_API __declspec(dllimport) -#endif - -#else - -#define LUA_API extern - -#endif - -/* more often than not the libs go together with the core */ -#define LUALIB_API LUA_API - - -/* -@@ LUAI_FUNC is a mark for all extern functions that are not to be -@* exported to outside modules. -@@ LUAI_DATA is a mark for all extern (const) variables that are not to -@* be exported to outside modules. -** CHANGE them if you need to mark them in some special way. Elf/gcc -** (versions 3.2 and later) mark them as "hidden" to optimize access -** when Lua is compiled as a shared library. -*/ -#if defined(luaall_c) -#define LUAI_FUNC static -#define LUAI_DATA /* empty */ - -#elif defined(__GNUC__) && ((__GNUC__*100 + __GNUC_MINOR__) >= 302) && \ - defined(__ELF__) -#define LUAI_FUNC __attribute__((visibility("hidden"))) extern -#define LUAI_DATA LUAI_FUNC - -#else -#define LUAI_FUNC extern -#define LUAI_DATA extern -#endif - - - -/* -@@ LUA_QL describes how error messages quote program elements. -** CHANGE it if you want a different appearance. -*/ -#define LUA_QL(x) "'" x "'" -#define LUA_QS LUA_QL("%s") - - -/* -@@ LUA_IDSIZE gives the maximum size for the description of the source -@* of a function in debug information. -** CHANGE it if you want a different size. -*/ -#define LUA_IDSIZE 60 - - -/* -** {================================================================== -** Stand-alone configuration -** =================================================================== -*/ - -#if defined(lua_c) || defined(luaall_c) - -/* -@@ lua_stdin_is_tty detects whether the standard input is a 'tty' (that -@* is, whether we're running lua interactively). -** CHANGE it if you have a better definition for non-POSIX/non-Windows -** systems. -*/ -#if defined(LUA_USE_ISATTY) -#include -#define lua_stdin_is_tty() isatty(0) -#elif defined(LUA_WIN) -#include -#include -#define lua_stdin_is_tty() _isatty(_fileno(stdin)) -#else -#define lua_stdin_is_tty() 1 /* assume stdin is a tty */ -#endif - - -/* -@@ LUA_PROMPT is the default prompt used by stand-alone Lua. -@@ LUA_PROMPT2 is the default continuation prompt used by stand-alone Lua. -** CHANGE them if you want different prompts. (You can also change the -** prompts dynamically, assigning to globals _PROMPT/_PROMPT2.) -*/ -#define LUA_PROMPT "> " -#define LUA_PROMPT2 ">> " - - -/* -@@ LUA_PROGNAME is the default name for the stand-alone Lua program. -** CHANGE it if your stand-alone interpreter has a different name and -** your system is not able to detect that name automatically. -*/ -#define LUA_PROGNAME "lua" - - -/* -@@ LUA_MAXINPUT is the maximum length for an input line in the -@* stand-alone interpreter. -** CHANGE it if you need longer lines. -*/ -#define LUA_MAXINPUT 512 - - -/* -@@ lua_readline defines how to show a prompt and then read a line from -@* the standard input. -@@ lua_saveline defines how to "save" a read line in a "history". -@@ lua_freeline defines how to free a line read by lua_readline. -** CHANGE them if you want to improve this functionality (e.g., by using -** GNU readline and history facilities). -*/ -#if defined(LUA_USE_READLINE) -#include -#include -#include -#define lua_readline(L,b,p) ((void)L, ((b)=readline(p)) != NULL) -#define lua_saveline(L,idx) \ - if (lua_strlen(L,idx) > 0) /* non-empty line? */ \ - add_history(lua_tostring(L, idx)); /* add it to history */ -#define lua_freeline(L,b) ((void)L, free(b)) -#else -#define lua_readline(L,b,p) \ - ((void)L, fputs(p, stdout), fflush(stdout), /* show prompt */ \ - fgets(b, LUA_MAXINPUT, stdin) != NULL) /* get line */ -#define lua_saveline(L,idx) { (void)L; (void)idx; } -#define lua_freeline(L,b) { (void)L; (void)b; } -#endif - -#endif - -/* }================================================================== */ - - -/* -@@ LUAI_GCPAUSE defines the default pause between garbage-collector cycles -@* as a percentage. -** CHANGE it if you want the GC to run faster or slower (higher values -** mean larger pauses which mean slower collection.) You can also change -** this value dynamically. -*/ -#define LUAI_GCPAUSE 200 /* 200% (wait memory to double before next GC) */ - - -/* -@@ LUAI_GCMUL defines the default speed of garbage collection relative to -@* memory allocation as a percentage. -** CHANGE it if you want to change the granularity of the garbage -** collection. (Higher values mean coarser collections. 0 represents -** infinity, where each step performs a full collection.) You can also -** change this value dynamically. -*/ -#define LUAI_GCMUL 200 /* GC runs 'twice the speed' of memory allocation */ - - - -/* -@@ LUA_COMPAT_GETN controls compatibility with old getn behavior. -** CHANGE it (define it) if you want exact compatibility with the -** behavior of setn/getn in Lua 5.0. -*/ -#undef LUA_COMPAT_GETN - -/* -@@ LUA_COMPAT_LOADLIB controls compatibility about global loadlib. -** CHANGE it to undefined as soon as you do not need a global 'loadlib' -** function (the function is still available as 'package.loadlib'). -*/ -#undef LUA_COMPAT_LOADLIB - -/* -@@ LUA_COMPAT_VARARG controls compatibility with old vararg feature. -** CHANGE it to undefined as soon as your programs use only '...' to -** access vararg parameters (instead of the old 'arg' table). -*/ -#define LUA_COMPAT_VARARG - -/* -@@ LUA_COMPAT_MOD controls compatibility with old math.mod function. -** CHANGE it to undefined as soon as your programs use 'math.fmod' or -** the new '%' operator instead of 'math.mod'. -*/ -#define LUA_COMPAT_MOD - -/* -@@ LUA_COMPAT_LSTR controls compatibility with old long string nesting -@* facility. -** CHANGE it to 2 if you want the old behaviour, or undefine it to turn -** off the advisory error when nesting [[...]]. -*/ -#define LUA_COMPAT_LSTR 1 - -/* -@@ LUA_COMPAT_GFIND controls compatibility with old 'string.gfind' name. -** CHANGE it to undefined as soon as you rename 'string.gfind' to -** 'string.gmatch'. -*/ -#define LUA_COMPAT_GFIND - -/* -@@ LUA_COMPAT_OPENLIB controls compatibility with old 'luaL_openlib' -@* behavior. -** CHANGE it to undefined as soon as you replace to 'luaL_register' -** your uses of 'luaL_openlib' -*/ -#define LUA_COMPAT_OPENLIB - - - -/* -@@ luai_apicheck is the assert macro used by the Lua-C API. -** CHANGE luai_apicheck if you want Lua to perform some checks in the -** parameters it gets from API calls. This may slow down the interpreter -** a bit, but may be quite useful when debugging C code that interfaces -** with Lua. A useful redefinition is to use assert.h. -*/ -#if defined(LUA_USE_APICHECK) -#include -#define luai_apicheck(L,o) { (void)L; assert(o); } -#else -#define luai_apicheck(L,o) { (void)L; } -#endif - - -/* -@@ LUAI_BITSINT defines the number of bits in an int. -** CHANGE here if Lua cannot automatically detect the number of bits of -** your machine. Probably you do not need to change this. -*/ -/* avoid overflows in comparison */ -#if INT_MAX-20 < 32760 -#define LUAI_BITSINT 16 -#elif INT_MAX > 2147483640L -/* int has at least 32 bits */ -#define LUAI_BITSINT 32 -#else -#error "you must define LUA_BITSINT with number of bits in an integer" -#endif - - -/* -@@ LUAI_UINT32 is an unsigned integer with at least 32 bits. -@@ LUAI_INT32 is an signed integer with at least 32 bits. -@@ LUAI_UMEM is an unsigned integer big enough to count the total -@* memory used by Lua. -@@ LUAI_MEM is a signed integer big enough to count the total memory -@* used by Lua. -** CHANGE here if for some weird reason the default definitions are not -** good enough for your machine. (The definitions in the 'else' -** part always works, but may waste space on machines with 64-bit -** longs.) Probably you do not need to change this. -*/ -#if LUAI_BITSINT >= 32 -#define LUAI_UINT32 unsigned int -#define LUAI_INT32 int -#define LUAI_MAXINT32 INT_MAX -#define LUAI_UMEM size_t -#define LUAI_MEM ptrdiff_t -#else -/* 16-bit ints */ -#define LUAI_UINT32 unsigned long -#define LUAI_INT32 long -#define LUAI_MAXINT32 LONG_MAX -#define LUAI_UMEM unsigned long -#define LUAI_MEM long -#endif - - -/* -@@ LUAI_MAXCALLS limits the number of nested calls. -** CHANGE it if you need really deep recursive calls. This limit is -** arbitrary; its only purpose is to stop infinite recursion before -** exhausting memory. -*/ -#define LUAI_MAXCALLS 20000 - - -/* -@@ LUAI_MAXCSTACK limits the number of Lua stack slots that a C function -@* can use. -** CHANGE it if you need lots of (Lua) stack space for your C -** functions. This limit is arbitrary; its only purpose is to stop C -** functions to consume unlimited stack space. (must be smaller than -** -LUA_REGISTRYINDEX) -*/ -#define LUAI_MAXCSTACK 8000 - - - -/* -** {================================================================== -** CHANGE (to smaller values) the following definitions if your system -** has a small C stack. (Or you may want to change them to larger -** values if your system has a large C stack and these limits are -** too rigid for you.) Some of these constants control the size of -** stack-allocated arrays used by the compiler or the interpreter, while -** others limit the maximum number of recursive calls that the compiler -** or the interpreter can perform. Values too large may cause a C stack -** overflow for some forms of deep constructs. -** =================================================================== -*/ - - -/* -@@ LUAI_MAXCCALLS is the maximum depth for nested C calls (short) and -@* syntactical nested non-terminals in a program. -*/ -#define LUAI_MAXCCALLS 200 - - -/* -@@ LUAI_MAXVARS is the maximum number of local variables per function -@* (must be smaller than 250). -*/ -#define LUAI_MAXVARS 200 - - -/* -@@ LUAI_MAXUPVALUES is the maximum number of upvalues per function -@* (must be smaller than 250). -*/ -#define LUAI_MAXUPVALUES 60 - - -/* -@@ LUAL_BUFFERSIZE is the buffer size used by the lauxlib buffer system. -*/ -#define LUAL_BUFFERSIZE BUFSIZ - -/* }================================================================== */ - - - - -/* -** {================================================================== -@@ LUA_NUMBER is the type of numbers in Lua. -** CHANGE the following definitions only if you want to build Lua -** with a number type different from double. You may also need to -** change lua_number2int & lua_number2integer. -** =================================================================== -*/ - -#define LUA_NUMBER_DOUBLE -#define LUA_NUMBER double - -/* -@@ LUAI_UACNUMBER is the result of an 'usual argument conversion' -@* over a number. -*/ -#define LUAI_UACNUMBER double - - -/* -@@ LUA_NUMBER_SCAN is the format for reading numbers. -@@ LUA_NUMBER_FMT is the format for writing numbers. -@@ lua_number2str converts a number to a string. -@@ LUAI_MAXNUMBER2STR is maximum size of previous conversion. -@@ lua_str2number converts a string to a number. -*/ -#define LUA_NUMBER_SCAN "%lf" -#define LUA_NUMBER_FMT "%.14g" -#define lua_number2str(s,n) sprintf((s), LUA_NUMBER_FMT, (n)) -#define LUAI_MAXNUMBER2STR 32 /* 16 digits, sign, point, and \0 */ -#define lua_str2number(s,p) strtod((s), (p)) - - -/* -@@ The luai_num* macros define the primitive operations over numbers. -*/ -#if defined(LUA_CORE) -#include -#define luai_numadd(a,b) ((a)+(b)) -#define luai_numsub(a,b) ((a)-(b)) -#define luai_nummul(a,b) ((a)*(b)) -#define luai_numdiv(a,b) ((a)/(b)) -#define luai_nummod(a,b) ((a) - floor((a)/(b))*(b)) -#define luai_numpow(a,b) (pow(a,b)) -#define luai_numunm(a) (-(a)) -#define luai_numeq(a,b) ((a)==(b)) -#define luai_numlt(a,b) ((a)<(b)) -#define luai_numle(a,b) ((a)<=(b)) -#define luai_numisnan(a) (!luai_numeq((a), (a))) -#endif - - -/* -@@ lua_number2int is a macro to convert lua_Number to int. -@@ lua_number2integer is a macro to convert lua_Number to lua_Integer. -** CHANGE them if you know a faster way to convert a lua_Number to -** int (with any rounding method and without throwing errors) in your -** system. In Pentium machines, a naive typecast from double to int -** in C is extremely slow, so any alternative is worth trying. -*/ - -/* On a Pentium, resort to a trick */ -#if defined(LUA_NUMBER_DOUBLE) && !defined(LUA_ANSI) && !defined(__SSE2__) && \ - (defined(__i386) || defined (_M_IX86) || defined(__i386__)) - -/* On a Microsoft compiler, use assembler */ -#if defined(_MSC_VER) - -#define lua_number2int(i,d) __asm fld d __asm fistp i -#define lua_number2integer(i,n) lua_number2int(i, n) - -/* the next trick should work on any Pentium, but sometimes clashes - with a DirectX idiosyncrasy */ -#else - -union luai_Cast { double l_d; long l_l; }; -#define lua_number2int(i,d) \ - { volatile union luai_Cast u; u.l_d = (d) + 6755399441055744.0; (i) = u.l_l; } -#define lua_number2integer(i,n) lua_number2int(i, n) - -#endif - - -/* this option always works, but may be slow */ -#else -#define lua_number2int(i,d) ((i)=(int)(d)) -#define lua_number2integer(i,d) ((i)=(lua_Integer)(d)) - -#endif - -/* }================================================================== */ - - -/* -@@ LUAI_USER_ALIGNMENT_T is a type that requires maximum alignment. -** CHANGE it if your system requires alignments larger than double. (For -** instance, if your system supports long doubles and they must be -** aligned in 16-byte boundaries, then you should add long double in the -** union.) Probably you do not need to change this. -*/ -#define LUAI_USER_ALIGNMENT_T union { double u; void *s; long l; } - - -/* -@@ LUAI_THROW/LUAI_TRY define how Lua does exception handling. -** CHANGE them if you prefer to use longjmp/setjmp even with C++ -** or if want/don't to use _longjmp/_setjmp instead of regular -** longjmp/setjmp. By default, Lua handles errors with exceptions when -** compiling as C++ code, with _longjmp/_setjmp when asked to use them, -** and with longjmp/setjmp otherwise. -*/ -#if defined(__cplusplus) -/* C++ exceptions */ -#define LUAI_THROW(L,c) throw(c) -#define LUAI_TRY(L,c,a) try { a } catch(...) \ - { if ((c)->status == 0) (c)->status = -1; } -#define luai_jmpbuf int /* dummy variable */ - -#elif defined(LUA_USE_ULONGJMP) -/* in Unix, try _longjmp/_setjmp (more efficient) */ -#define LUAI_THROW(L,c) _longjmp((c)->b, 1) -#define LUAI_TRY(L,c,a) if (_setjmp((c)->b) == 0) { a } -#define luai_jmpbuf jmp_buf - -#else -/* default handling with long jumps */ -#define LUAI_THROW(L,c) longjmp((c)->b, 1) -#define LUAI_TRY(L,c,a) if (setjmp((c)->b) == 0) { a } -#define luai_jmpbuf jmp_buf - -#endif - - -/* -@@ LUA_MAXCAPTURES is the maximum number of captures that a pattern -@* can do during pattern-matching. -** CHANGE it if you need more captures. This limit is arbitrary. -*/ -#define LUA_MAXCAPTURES 32 - - -/* -@@ lua_tmpnam is the function that the OS library uses to create a -@* temporary name. -@@ LUA_TMPNAMBUFSIZE is the maximum size of a name created by lua_tmpnam. -** CHANGE them if you have an alternative to tmpnam (which is considered -** insecure) or if you want the original tmpnam anyway. By default, Lua -** uses tmpnam except when POSIX is available, where it uses mkstemp. -*/ -#if defined(loslib_c) || defined(luaall_c) - -#if defined(LUA_USE_MKSTEMP) -#include -#define LUA_TMPNAMBUFSIZE 32 -#define lua_tmpnam(b,e) { \ - strcpy(b, "/tmp/lua_XXXXXX"); \ - e = mkstemp(b); \ - if (e != -1) close(e); \ - e = (e == -1); } - -#else -#define LUA_TMPNAMBUFSIZE L_tmpnam -#define lua_tmpnam(b,e) { e = (tmpnam(b) == NULL); } -#endif - -#endif - - -/* -@@ lua_popen spawns a new process connected to the current one through -@* the file streams. -** CHANGE it if you have a way to implement it in your system. -*/ -#if defined(LUA_USE_POPEN) - -#define lua_popen(L,c,m) ((void)L, fflush(NULL), popen(c,m)) -#define lua_pclose(L,file) ((void)L, (pclose(file) != -1)) - -#elif defined(LUA_WIN) - -#define lua_popen(L,c,m) ((void)L, _popen(c,m)) -#define lua_pclose(L,file) ((void)L, (_pclose(file) != -1)) - -#else - -#define lua_popen(L,c,m) ((void)((void)c, m), \ - luaL_error(L, LUA_QL("popen") " not supported"), (FILE*)0) -#define lua_pclose(L,file) ((void)((void)L, file), 0) - -#endif - -/* -@@ LUA_DL_* define which dynamic-library system Lua should use. -** CHANGE here if Lua has problems choosing the appropriate -** dynamic-library system for your platform (either Windows' DLL, Mac's -** dyld, or Unix's dlopen). If your system is some kind of Unix, there -** is a good chance that it has dlopen, so LUA_DL_DLOPEN will work for -** it. To use dlopen you also need to adapt the src/Makefile (probably -** adding -ldl to the linker options), so Lua does not select it -** automatically. (When you change the makefile to add -ldl, you must -** also add -DLUA_USE_DLOPEN.) -** If you do not want any kind of dynamic library, undefine all these -** options. -** By default, _WIN32 gets LUA_DL_DLL and MAC OS X gets LUA_DL_DYLD. -*/ -#if defined(LUA_USE_DLOPEN) -#define LUA_DL_DLOPEN -#endif - -#if defined(LUA_WIN) -#define LUA_DL_DLL -#endif - - -/* -@@ LUAI_EXTRASPACE allows you to add user-specific data in a lua_State -@* (the data goes just *before* the lua_State pointer). -** CHANGE (define) this if you really need that. This value must be -** a multiple of the maximum alignment required for your machine. -*/ -#define LUAI_EXTRASPACE 0 - - -/* -@@ luai_userstate* allow user-specific actions on threads. -** CHANGE them if you defined LUAI_EXTRASPACE and need to do something -** extra when a thread is created/deleted/resumed/yielded. -*/ -#define luai_userstateopen(L) ((void)L) -#define luai_userstateclose(L) ((void)L) -#define luai_userstatethread(L,L1) ((void)L) -#define luai_userstatefree(L) ((void)L) -#define luai_userstateresume(L,n) ((void)L) -#define luai_userstateyield(L,n) ((void)L) - - -/* -@@ LUA_INTFRMLEN is the length modifier for integer conversions -@* in 'string.format'. -@@ LUA_INTFRM_T is the integer type correspoding to the previous length -@* modifier. -** CHANGE them if your system supports long long or does not support long. -*/ - -#if defined(LUA_USELONGLONG) - -#define LUA_INTFRMLEN "ll" -#define LUA_INTFRM_T long long - -#else - -#define LUA_INTFRMLEN "l" -#define LUA_INTFRM_T long - -#endif - - - -/* =================================================================== */ - -/* -** Local configuration. You can use this space to add your redefinitions -** without modifying the main part of the file. -*/ - - - -#endif - diff --git a/lib/lua-5.1/src/lualib.h b/lib/lua-5.1/src/lualib.h deleted file mode 100644 index 469417f..0000000 --- a/lib/lua-5.1/src/lualib.h +++ /dev/null @@ -1,53 +0,0 @@ -/* -** $Id: lualib.h,v 1.36.1.1 2007/12/27 13:02:25 roberto Exp $ -** Lua standard libraries -** See Copyright Notice in lua.h -*/ - - -#ifndef lualib_h -#define lualib_h - -#include "lua.h" - - -/* Key to file-handle type */ -#define LUA_FILEHANDLE "FILE*" - - -#define LUA_COLIBNAME "coroutine" -LUALIB_API int (luaopen_base) (lua_State *L); - -#define LUA_TABLIBNAME "table" -LUALIB_API int (luaopen_table) (lua_State *L); - -#define LUA_IOLIBNAME "io" -LUALIB_API int (luaopen_io) (lua_State *L); - -#define LUA_OSLIBNAME "os" -LUALIB_API int (luaopen_os) (lua_State *L); - -#define LUA_STRLIBNAME "string" -LUALIB_API int (luaopen_string) (lua_State *L); - -#define LUA_MATHLIBNAME "math" -LUALIB_API int (luaopen_math) (lua_State *L); - -#define LUA_DBLIBNAME "debug" -LUALIB_API int (luaopen_debug) (lua_State *L); - -#define LUA_LOADLIBNAME "package" -LUALIB_API int (luaopen_package) (lua_State *L); - - -/* open all previous libraries */ -LUALIB_API void (luaL_openlibs) (lua_State *L); - - - -#ifndef lua_assert -#define lua_assert(x) ((void)0) -#endif - - -#endif diff --git a/lib/lua-5.1/src/lundump.c b/lib/lua-5.1/src/lundump.c deleted file mode 100644 index 8010a45..0000000 --- a/lib/lua-5.1/src/lundump.c +++ /dev/null @@ -1,227 +0,0 @@ -/* -** $Id: lundump.c,v 2.7.1.4 2008/04/04 19:51:41 roberto Exp $ -** load precompiled Lua chunks -** See Copyright Notice in lua.h -*/ - -#include - -#define lundump_c -#define LUA_CORE - -#include "lua.h" - -#include "ldebug.h" -#include "ldo.h" -#include "lfunc.h" -#include "lmem.h" -#include "lobject.h" -#include "lstring.h" -#include "lundump.h" -#include "lzio.h" - -typedef struct { - lua_State* L; - ZIO* Z; - Mbuffer* b; - const char* name; -} LoadState; - -#ifdef LUAC_TRUST_BINARIES -#define IF(c,s) -#define error(S,s) -#else -#define IF(c,s) if (c) error(S,s) - -static void error(LoadState* S, const char* why) -{ - luaO_pushfstring(S->L,"%s: %s in precompiled chunk",S->name,why); - luaD_throw(S->L,LUA_ERRSYNTAX); -} -#endif - -#define LoadMem(S,b,n,size) LoadBlock(S,b,(n)*(size)) -#define LoadByte(S) (lu_byte)LoadChar(S) -#define LoadVar(S,x) LoadMem(S,&x,1,sizeof(x)) -#define LoadVector(S,b,n,size) LoadMem(S,b,n,size) - -static void LoadBlock(LoadState* S, void* b, size_t size) -{ - size_t r=luaZ_read(S->Z,b,size); - IF (r!=0, "unexpected end"); -} - -static int LoadChar(LoadState* S) -{ - char x; - LoadVar(S,x); - return x; -} - -static int LoadInt(LoadState* S) -{ - int x; - LoadVar(S,x); - IF (x<0, "bad integer"); - return x; -} - -static lua_Number LoadNumber(LoadState* S) -{ - lua_Number x; - LoadVar(S,x); - return x; -} - -static TString* LoadString(LoadState* S) -{ - size_t size; - LoadVar(S,size); - if (size==0) - return NULL; - else - { - char* s=luaZ_openspace(S->L,S->b,size); - LoadBlock(S,s,size); - return luaS_newlstr(S->L,s,size-1); /* remove trailing '\0' */ - } -} - -static void LoadCode(LoadState* S, Proto* f) -{ - int n=LoadInt(S); - f->code=luaM_newvector(S->L,n,Instruction); - f->sizecode=n; - LoadVector(S,f->code,n,sizeof(Instruction)); -} - -static Proto* LoadFunction(LoadState* S, TString* p); - -static void LoadConstants(LoadState* S, Proto* f) -{ - int i,n; - n=LoadInt(S); - f->k=luaM_newvector(S->L,n,TValue); - f->sizek=n; - for (i=0; ik[i]); - for (i=0; ik[i]; - int t=LoadChar(S); - switch (t) - { - case LUA_TNIL: - setnilvalue(o); - break; - case LUA_TBOOLEAN: - setbvalue(o,LoadChar(S)!=0); - break; - case LUA_TNUMBER: - setnvalue(o,LoadNumber(S)); - break; - case LUA_TSTRING: - setsvalue2n(S->L,o,LoadString(S)); - break; - default: - error(S,"bad constant"); - break; - } - } - n=LoadInt(S); - f->p=luaM_newvector(S->L,n,Proto*); - f->sizep=n; - for (i=0; ip[i]=NULL; - for (i=0; ip[i]=LoadFunction(S,f->source); -} - -static void LoadDebug(LoadState* S, Proto* f) -{ - int i,n; - n=LoadInt(S); - f->lineinfo=luaM_newvector(S->L,n,int); - f->sizelineinfo=n; - LoadVector(S,f->lineinfo,n,sizeof(int)); - n=LoadInt(S); - f->locvars=luaM_newvector(S->L,n,LocVar); - f->sizelocvars=n; - for (i=0; ilocvars[i].varname=NULL; - for (i=0; ilocvars[i].varname=LoadString(S); - f->locvars[i].startpc=LoadInt(S); - f->locvars[i].endpc=LoadInt(S); - } - n=LoadInt(S); - f->upvalues=luaM_newvector(S->L,n,TString*); - f->sizeupvalues=n; - for (i=0; iupvalues[i]=NULL; - for (i=0; iupvalues[i]=LoadString(S); -} - -static Proto* LoadFunction(LoadState* S, TString* p) -{ - Proto* f; - if (++S->L->nCcalls > LUAI_MAXCCALLS) error(S,"code too deep"); - f=luaF_newproto(S->L); - setptvalue2s(S->L,S->L->top,f); incr_top(S->L); - f->source=LoadString(S); if (f->source==NULL) f->source=p; - f->linedefined=LoadInt(S); - f->lastlinedefined=LoadInt(S); - f->nups=LoadByte(S); - f->numparams=LoadByte(S); - f->is_vararg=LoadByte(S); - f->maxstacksize=LoadByte(S); - LoadCode(S,f); - LoadConstants(S,f); - LoadDebug(S,f); - IF (!luaG_checkcode(f), "bad code"); - S->L->top--; - S->L->nCcalls--; - return f; -} - -static void LoadHeader(LoadState* S) -{ - char h[LUAC_HEADERSIZE]; - char s[LUAC_HEADERSIZE]; - luaU_header(h); - LoadBlock(S,s,LUAC_HEADERSIZE); - IF (memcmp(h,s,LUAC_HEADERSIZE)!=0, "bad header"); -} - -/* -** load precompiled chunk -*/ -Proto* luaU_undump (lua_State* L, ZIO* Z, Mbuffer* buff, const char* name) -{ - LoadState S; - if (*name=='@' || *name=='=') - S.name=name+1; - else if (*name==LUA_SIGNATURE[0]) - S.name="binary string"; - else - S.name=name; - S.L=L; - S.Z=Z; - S.b=buff; - LoadHeader(&S); - return LoadFunction(&S,luaS_newliteral(L,"=?")); -} - -/* -* make header -*/ -void luaU_header (char* h) -{ - int x=1; - memcpy(h,LUA_SIGNATURE,sizeof(LUA_SIGNATURE)-1); - h+=sizeof(LUA_SIGNATURE)-1; - *h++=(char)LUAC_VERSION; - *h++=(char)LUAC_FORMAT; - *h++=(char)*(char*)&x; /* endianness */ - *h++=(char)sizeof(int); - *h++=(char)sizeof(size_t); - *h++=(char)sizeof(Instruction); - *h++=(char)sizeof(lua_Number); - *h++=(char)(((lua_Number)0.5)==0); /* is lua_Number integral? */ -} diff --git a/lib/lua-5.1/src/lundump.h b/lib/lua-5.1/src/lundump.h deleted file mode 100644 index c80189d..0000000 --- a/lib/lua-5.1/src/lundump.h +++ /dev/null @@ -1,36 +0,0 @@ -/* -** $Id: lundump.h,v 1.37.1.1 2007/12/27 13:02:25 roberto Exp $ -** load precompiled Lua chunks -** See Copyright Notice in lua.h -*/ - -#ifndef lundump_h -#define lundump_h - -#include "lobject.h" -#include "lzio.h" - -/* load one chunk; from lundump.c */ -LUAI_FUNC Proto* luaU_undump (lua_State* L, ZIO* Z, Mbuffer* buff, const char* name); - -/* make header; from lundump.c */ -LUAI_FUNC void luaU_header (char* h); - -/* dump one chunk; from ldump.c */ -LUAI_FUNC int luaU_dump (lua_State* L, const Proto* f, lua_Writer w, void* data, int strip); - -#ifdef luac_c -/* print one chunk; from print.c */ -LUAI_FUNC void luaU_print (const Proto* f, int full); -#endif - -/* for header of binary files -- this is Lua 5.1 */ -#define LUAC_VERSION 0x51 - -/* for header of binary files -- this is the official format */ -#define LUAC_FORMAT 0 - -/* size of header of binary files */ -#define LUAC_HEADERSIZE 12 - -#endif diff --git a/lib/lua-5.1/src/lvm.c b/lib/lua-5.1/src/lvm.c deleted file mode 100644 index e0a0cd8..0000000 --- a/lib/lua-5.1/src/lvm.c +++ /dev/null @@ -1,767 +0,0 @@ -/* -** $Id: lvm.c,v 2.63.1.5 2011/08/17 20:43:11 roberto Exp $ -** Lua virtual machine -** See Copyright Notice in lua.h -*/ - - -#include -#include -#include - -#define lvm_c -#define LUA_CORE - -#include "lua.h" - -#include "ldebug.h" -#include "ldo.h" -#include "lfunc.h" -#include "lgc.h" -#include "lobject.h" -#include "lopcodes.h" -#include "lstate.h" -#include "lstring.h" -#include "ltable.h" -#include "ltm.h" -#include "lvm.h" - - - -/* limit for table tag-method chains (to avoid loops) */ -#define MAXTAGLOOP 100 - - -const TValue *luaV_tonumber (const TValue *obj, TValue *n) { - lua_Number num; - if (ttisnumber(obj)) return obj; - if (ttisstring(obj) && luaO_str2d(svalue(obj), &num)) { - setnvalue(n, num); - return n; - } - else - return NULL; -} - - -int luaV_tostring (lua_State *L, StkId obj) { - if (!ttisnumber(obj)) - return 0; - else { - char s[LUAI_MAXNUMBER2STR]; - lua_Number n = nvalue(obj); - lua_number2str(s, n); - setsvalue2s(L, obj, luaS_new(L, s)); - return 1; - } -} - - -static void traceexec (lua_State *L, const Instruction *pc) { - lu_byte mask = L->hookmask; - const Instruction *oldpc = L->savedpc; - L->savedpc = pc; - if ((mask & LUA_MASKCOUNT) && L->hookcount == 0) { - resethookcount(L); - luaD_callhook(L, LUA_HOOKCOUNT, -1); - } - if (mask & LUA_MASKLINE) { - Proto *p = ci_func(L->ci)->l.p; - int npc = pcRel(pc, p); - int newline = getline(p, npc); - /* call linehook when enter a new function, when jump back (loop), - or when enter a new line */ - if (npc == 0 || pc <= oldpc || newline != getline(p, pcRel(oldpc, p))) - luaD_callhook(L, LUA_HOOKLINE, newline); - } -} - - -static void callTMres (lua_State *L, StkId res, const TValue *f, - const TValue *p1, const TValue *p2) { - ptrdiff_t result = savestack(L, res); - setobj2s(L, L->top, f); /* push function */ - setobj2s(L, L->top+1, p1); /* 1st argument */ - setobj2s(L, L->top+2, p2); /* 2nd argument */ - luaD_checkstack(L, 3); - L->top += 3; - luaD_call(L, L->top - 3, 1); - res = restorestack(L, result); - L->top--; - setobjs2s(L, res, L->top); -} - - - -static void callTM (lua_State *L, const TValue *f, const TValue *p1, - const TValue *p2, const TValue *p3) { - setobj2s(L, L->top, f); /* push function */ - setobj2s(L, L->top+1, p1); /* 1st argument */ - setobj2s(L, L->top+2, p2); /* 2nd argument */ - setobj2s(L, L->top+3, p3); /* 3th argument */ - luaD_checkstack(L, 4); - L->top += 4; - luaD_call(L, L->top - 4, 0); -} - - -void luaV_gettable (lua_State *L, const TValue *t, TValue *key, StkId val) { - int loop; - for (loop = 0; loop < MAXTAGLOOP; loop++) { - const TValue *tm; - if (ttistable(t)) { /* `t' is a table? */ - Table *h = hvalue(t); - const TValue *res = luaH_get(h, key); /* do a primitive get */ - if (!ttisnil(res) || /* result is no nil? */ - (tm = fasttm(L, h->metatable, TM_INDEX)) == NULL) { /* or no TM? */ - setobj2s(L, val, res); - return; - } - /* else will try the tag method */ - } - else if (ttisnil(tm = luaT_gettmbyobj(L, t, TM_INDEX))) - luaG_typeerror(L, t, "index"); - if (ttisfunction(tm)) { - callTMres(L, val, tm, t, key); - return; - } - t = tm; /* else repeat with `tm' */ - } - luaG_runerror(L, "loop in gettable"); -} - - -void luaV_settable (lua_State *L, const TValue *t, TValue *key, StkId val) { - int loop; - TValue temp; - for (loop = 0; loop < MAXTAGLOOP; loop++) { - const TValue *tm; - if (ttistable(t)) { /* `t' is a table? */ - Table *h = hvalue(t); - TValue *oldval = luaH_set(L, h, key); /* do a primitive set */ - if (!ttisnil(oldval) || /* result is no nil? */ - (tm = fasttm(L, h->metatable, TM_NEWINDEX)) == NULL) { /* or no TM? */ - setobj2t(L, oldval, val); - h->flags = 0; - luaC_barriert(L, h, val); - return; - } - /* else will try the tag method */ - } - else if (ttisnil(tm = luaT_gettmbyobj(L, t, TM_NEWINDEX))) - luaG_typeerror(L, t, "index"); - if (ttisfunction(tm)) { - callTM(L, tm, t, key, val); - return; - } - /* else repeat with `tm' */ - setobj(L, &temp, tm); /* avoid pointing inside table (may rehash) */ - t = &temp; - } - luaG_runerror(L, "loop in settable"); -} - - -static int call_binTM (lua_State *L, const TValue *p1, const TValue *p2, - StkId res, TMS event) { - const TValue *tm = luaT_gettmbyobj(L, p1, event); /* try first operand */ - if (ttisnil(tm)) - tm = luaT_gettmbyobj(L, p2, event); /* try second operand */ - if (ttisnil(tm)) return 0; - callTMres(L, res, tm, p1, p2); - return 1; -} - - -static const TValue *get_compTM (lua_State *L, Table *mt1, Table *mt2, - TMS event) { - const TValue *tm1 = fasttm(L, mt1, event); - const TValue *tm2; - if (tm1 == NULL) return NULL; /* no metamethod */ - if (mt1 == mt2) return tm1; /* same metatables => same metamethods */ - tm2 = fasttm(L, mt2, event); - if (tm2 == NULL) return NULL; /* no metamethod */ - if (luaO_rawequalObj(tm1, tm2)) /* same metamethods? */ - return tm1; - return NULL; -} - - -static int call_orderTM (lua_State *L, const TValue *p1, const TValue *p2, - TMS event) { - const TValue *tm1 = luaT_gettmbyobj(L, p1, event); - const TValue *tm2; - if (ttisnil(tm1)) return -1; /* no metamethod? */ - tm2 = luaT_gettmbyobj(L, p2, event); - if (!luaO_rawequalObj(tm1, tm2)) /* different metamethods? */ - return -1; - callTMres(L, L->top, tm1, p1, p2); - return !l_isfalse(L->top); -} - - -static int l_strcmp (const TString *ls, const TString *rs) { - const char *l = getstr(ls); - size_t ll = ls->tsv.len; - const char *r = getstr(rs); - size_t lr = rs->tsv.len; - for (;;) { - int temp = strcoll(l, r); - if (temp != 0) return temp; - else { /* strings are equal up to a `\0' */ - size_t len = strlen(l); /* index of first `\0' in both strings */ - if (len == lr) /* r is finished? */ - return (len == ll) ? 0 : 1; - else if (len == ll) /* l is finished? */ - return -1; /* l is smaller than r (because r is not finished) */ - /* both strings longer than `len'; go on comparing (after the `\0') */ - len++; - l += len; ll -= len; r += len; lr -= len; - } - } -} - - -int luaV_lessthan (lua_State *L, const TValue *l, const TValue *r) { - int res; - if (ttype(l) != ttype(r)) - return luaG_ordererror(L, l, r); - else if (ttisnumber(l)) - return luai_numlt(nvalue(l), nvalue(r)); - else if (ttisstring(l)) - return l_strcmp(rawtsvalue(l), rawtsvalue(r)) < 0; - else if ((res = call_orderTM(L, l, r, TM_LT)) != -1) - return res; - return luaG_ordererror(L, l, r); -} - - -static int lessequal (lua_State *L, const TValue *l, const TValue *r) { - int res; - if (ttype(l) != ttype(r)) - return luaG_ordererror(L, l, r); - else if (ttisnumber(l)) - return luai_numle(nvalue(l), nvalue(r)); - else if (ttisstring(l)) - return l_strcmp(rawtsvalue(l), rawtsvalue(r)) <= 0; - else if ((res = call_orderTM(L, l, r, TM_LE)) != -1) /* first try `le' */ - return res; - else if ((res = call_orderTM(L, r, l, TM_LT)) != -1) /* else try `lt' */ - return !res; - return luaG_ordererror(L, l, r); -} - - -int luaV_equalval (lua_State *L, const TValue *t1, const TValue *t2) { - const TValue *tm; - lua_assert(ttype(t1) == ttype(t2)); - switch (ttype(t1)) { - case LUA_TNIL: return 1; - case LUA_TNUMBER: return luai_numeq(nvalue(t1), nvalue(t2)); - case LUA_TBOOLEAN: return bvalue(t1) == bvalue(t2); /* true must be 1 !! */ - case LUA_TLIGHTUSERDATA: return pvalue(t1) == pvalue(t2); - case LUA_TUSERDATA: { - if (uvalue(t1) == uvalue(t2)) return 1; - tm = get_compTM(L, uvalue(t1)->metatable, uvalue(t2)->metatable, - TM_EQ); - break; /* will try TM */ - } - case LUA_TTABLE: { - if (hvalue(t1) == hvalue(t2)) return 1; - tm = get_compTM(L, hvalue(t1)->metatable, hvalue(t2)->metatable, TM_EQ); - break; /* will try TM */ - } - default: return gcvalue(t1) == gcvalue(t2); - } - if (tm == NULL) return 0; /* no TM? */ - callTMres(L, L->top, tm, t1, t2); /* call TM */ - return !l_isfalse(L->top); -} - - -void luaV_concat (lua_State *L, int total, int last) { - do { - StkId top = L->base + last + 1; - int n = 2; /* number of elements handled in this pass (at least 2) */ - if (!(ttisstring(top-2) || ttisnumber(top-2)) || !tostring(L, top-1)) { - if (!call_binTM(L, top-2, top-1, top-2, TM_CONCAT)) - luaG_concaterror(L, top-2, top-1); - } else if (tsvalue(top-1)->len == 0) /* second op is empty? */ - (void)tostring(L, top - 2); /* result is first op (as string) */ - else { - /* at least two string values; get as many as possible */ - size_t tl = tsvalue(top-1)->len; - char *buffer; - int i; - /* collect total length */ - for (n = 1; n < total && tostring(L, top-n-1); n++) { - size_t l = tsvalue(top-n-1)->len; - if (l >= MAX_SIZET - tl) luaG_runerror(L, "string length overflow"); - tl += l; - } - buffer = luaZ_openspace(L, &G(L)->buff, tl); - tl = 0; - for (i=n; i>0; i--) { /* concat all strings */ - size_t l = tsvalue(top-i)->len; - memcpy(buffer+tl, svalue(top-i), l); - tl += l; - } - setsvalue2s(L, top-n, luaS_newlstr(L, buffer, tl)); - } - total -= n-1; /* got `n' strings to create 1 new */ - last -= n-1; - } while (total > 1); /* repeat until only 1 result left */ -} - - -static void Arith (lua_State *L, StkId ra, const TValue *rb, - const TValue *rc, TMS op) { - TValue tempb, tempc; - const TValue *b, *c; - if ((b = luaV_tonumber(rb, &tempb)) != NULL && - (c = luaV_tonumber(rc, &tempc)) != NULL) { - lua_Number nb = nvalue(b), nc = nvalue(c); - switch (op) { - case TM_ADD: setnvalue(ra, luai_numadd(nb, nc)); break; - case TM_SUB: setnvalue(ra, luai_numsub(nb, nc)); break; - case TM_MUL: setnvalue(ra, luai_nummul(nb, nc)); break; - case TM_DIV: setnvalue(ra, luai_numdiv(nb, nc)); break; - case TM_MOD: setnvalue(ra, luai_nummod(nb, nc)); break; - case TM_POW: setnvalue(ra, luai_numpow(nb, nc)); break; - case TM_UNM: setnvalue(ra, luai_numunm(nb)); break; - default: lua_assert(0); break; - } - } - else if (!call_binTM(L, rb, rc, ra, op)) - luaG_aritherror(L, rb, rc); -} - - - -/* -** some macros for common tasks in `luaV_execute' -*/ - -#define runtime_check(L, c) { if (!(c)) break; } - -#define RA(i) (base+GETARG_A(i)) -/* to be used after possible stack reallocation */ -#define RB(i) check_exp(getBMode(GET_OPCODE(i)) == OpArgR, base+GETARG_B(i)) -#define RC(i) check_exp(getCMode(GET_OPCODE(i)) == OpArgR, base+GETARG_C(i)) -#define RKB(i) check_exp(getBMode(GET_OPCODE(i)) == OpArgK, \ - ISK(GETARG_B(i)) ? k+INDEXK(GETARG_B(i)) : base+GETARG_B(i)) -#define RKC(i) check_exp(getCMode(GET_OPCODE(i)) == OpArgK, \ - ISK(GETARG_C(i)) ? k+INDEXK(GETARG_C(i)) : base+GETARG_C(i)) -#define KBx(i) check_exp(getBMode(GET_OPCODE(i)) == OpArgK, k+GETARG_Bx(i)) - - -#define dojump(L,pc,i) {(pc) += (i); luai_threadyield(L);} - - -#define Protect(x) { L->savedpc = pc; {x;}; base = L->base; } - - -#define arith_op(op,tm) { \ - TValue *rb = RKB(i); \ - TValue *rc = RKC(i); \ - if (ttisnumber(rb) && ttisnumber(rc)) { \ - lua_Number nb = nvalue(rb), nc = nvalue(rc); \ - setnvalue(ra, op(nb, nc)); \ - } \ - else \ - Protect(Arith(L, ra, rb, rc, tm)); \ - } - - - -void luaV_execute (lua_State *L, int nexeccalls) { - LClosure *cl; - StkId base; - TValue *k; - const Instruction *pc; - reentry: /* entry point */ - lua_assert(isLua(L->ci)); - pc = L->savedpc; - cl = &clvalue(L->ci->func)->l; - base = L->base; - k = cl->p->k; - /* main loop of interpreter */ - for (;;) { - const Instruction i = *pc++; - StkId ra; - if ((L->hookmask & (LUA_MASKLINE | LUA_MASKCOUNT)) && - (--L->hookcount == 0 || L->hookmask & LUA_MASKLINE)) { - traceexec(L, pc); - if (L->status == LUA_YIELD) { /* did hook yield? */ - L->savedpc = pc - 1; - return; - } - base = L->base; - } - /* warning!! several calls may realloc the stack and invalidate `ra' */ - ra = RA(i); - lua_assert(base == L->base && L->base == L->ci->base); - lua_assert(base <= L->top && L->top <= L->stack + L->stacksize); - lua_assert(L->top == L->ci->top || luaG_checkopenop(i)); - switch (GET_OPCODE(i)) { - case OP_MOVE: { - setobjs2s(L, ra, RB(i)); - continue; - } - case OP_LOADK: { - setobj2s(L, ra, KBx(i)); - continue; - } - case OP_LOADBOOL: { - setbvalue(ra, GETARG_B(i)); - if (GETARG_C(i)) pc++; /* skip next instruction (if C) */ - continue; - } - case OP_LOADNIL: { - TValue *rb = RB(i); - do { - setnilvalue(rb--); - } while (rb >= ra); - continue; - } - case OP_GETUPVAL: { - int b = GETARG_B(i); - setobj2s(L, ra, cl->upvals[b]->v); - continue; - } - case OP_GETGLOBAL: { - TValue g; - TValue *rb = KBx(i); - sethvalue(L, &g, cl->env); - lua_assert(ttisstring(rb)); - Protect(luaV_gettable(L, &g, rb, ra)); - continue; - } - case OP_GETTABLE: { - Protect(luaV_gettable(L, RB(i), RKC(i), ra)); - continue; - } - case OP_SETGLOBAL: { - TValue g; - sethvalue(L, &g, cl->env); - lua_assert(ttisstring(KBx(i))); - Protect(luaV_settable(L, &g, KBx(i), ra)); - continue; - } - case OP_SETUPVAL: { - UpVal *uv = cl->upvals[GETARG_B(i)]; - setobj(L, uv->v, ra); - luaC_barrier(L, uv, ra); - continue; - } - case OP_SETTABLE: { - Protect(luaV_settable(L, ra, RKB(i), RKC(i))); - continue; - } - case OP_NEWTABLE: { - int b = GETARG_B(i); - int c = GETARG_C(i); - sethvalue(L, ra, luaH_new(L, luaO_fb2int(b), luaO_fb2int(c))); - Protect(luaC_checkGC(L)); - continue; - } - case OP_SELF: { - StkId rb = RB(i); - setobjs2s(L, ra+1, rb); - Protect(luaV_gettable(L, rb, RKC(i), ra)); - continue; - } - case OP_ADD: { - arith_op(luai_numadd, TM_ADD); - continue; - } - case OP_SUB: { - arith_op(luai_numsub, TM_SUB); - continue; - } - case OP_MUL: { - arith_op(luai_nummul, TM_MUL); - continue; - } - case OP_DIV: { - arith_op(luai_numdiv, TM_DIV); - continue; - } - case OP_MOD: { - arith_op(luai_nummod, TM_MOD); - continue; - } - case OP_POW: { - arith_op(luai_numpow, TM_POW); - continue; - } - case OP_UNM: { - TValue *rb = RB(i); - if (ttisnumber(rb)) { - lua_Number nb = nvalue(rb); - setnvalue(ra, luai_numunm(nb)); - } - else { - Protect(Arith(L, ra, rb, rb, TM_UNM)); - } - continue; - } - case OP_NOT: { - int res = l_isfalse(RB(i)); /* next assignment may change this value */ - setbvalue(ra, res); - continue; - } - case OP_LEN: { - const TValue *rb = RB(i); - switch (ttype(rb)) { - case LUA_TTABLE: { - setnvalue(ra, cast_num(luaH_getn(hvalue(rb)))); - break; - } - case LUA_TSTRING: { - setnvalue(ra, cast_num(tsvalue(rb)->len)); - break; - } - default: { /* try metamethod */ - Protect( - if (!call_binTM(L, rb, luaO_nilobject, ra, TM_LEN)) - luaG_typeerror(L, rb, "get length of"); - ) - } - } - continue; - } - case OP_CONCAT: { - int b = GETARG_B(i); - int c = GETARG_C(i); - Protect(luaV_concat(L, c-b+1, c); luaC_checkGC(L)); - setobjs2s(L, RA(i), base+b); - continue; - } - case OP_JMP: { - dojump(L, pc, GETARG_sBx(i)); - continue; - } - case OP_EQ: { - TValue *rb = RKB(i); - TValue *rc = RKC(i); - Protect( - if (equalobj(L, rb, rc) == GETARG_A(i)) - dojump(L, pc, GETARG_sBx(*pc)); - ) - pc++; - continue; - } - case OP_LT: { - Protect( - if (luaV_lessthan(L, RKB(i), RKC(i)) == GETARG_A(i)) - dojump(L, pc, GETARG_sBx(*pc)); - ) - pc++; - continue; - } - case OP_LE: { - Protect( - if (lessequal(L, RKB(i), RKC(i)) == GETARG_A(i)) - dojump(L, pc, GETARG_sBx(*pc)); - ) - pc++; - continue; - } - case OP_TEST: { - if (l_isfalse(ra) != GETARG_C(i)) - dojump(L, pc, GETARG_sBx(*pc)); - pc++; - continue; - } - case OP_TESTSET: { - TValue *rb = RB(i); - if (l_isfalse(rb) != GETARG_C(i)) { - setobjs2s(L, ra, rb); - dojump(L, pc, GETARG_sBx(*pc)); - } - pc++; - continue; - } - case OP_CALL: { - int b = GETARG_B(i); - int nresults = GETARG_C(i) - 1; - if (b != 0) L->top = ra+b; /* else previous instruction set top */ - L->savedpc = pc; - switch (luaD_precall(L, ra, nresults)) { - case PCRLUA: { - nexeccalls++; - goto reentry; /* restart luaV_execute over new Lua function */ - } - case PCRC: { - /* it was a C function (`precall' called it); adjust results */ - if (nresults >= 0) L->top = L->ci->top; - base = L->base; - continue; - } - default: { - return; /* yield */ - } - } - } - case OP_TAILCALL: { - int b = GETARG_B(i); - if (b != 0) L->top = ra+b; /* else previous instruction set top */ - L->savedpc = pc; - lua_assert(GETARG_C(i) - 1 == LUA_MULTRET); - switch (luaD_precall(L, ra, LUA_MULTRET)) { - case PCRLUA: { - /* tail call: put new frame in place of previous one */ - CallInfo *ci = L->ci - 1; /* previous frame */ - int aux; - StkId func = ci->func; - StkId pfunc = (ci+1)->func; /* previous function index */ - if (L->openupval) luaF_close(L, ci->base); - L->base = ci->base = ci->func + ((ci+1)->base - pfunc); - for (aux = 0; pfunc+aux < L->top; aux++) /* move frame down */ - setobjs2s(L, func+aux, pfunc+aux); - ci->top = L->top = func+aux; /* correct top */ - lua_assert(L->top == L->base + clvalue(func)->l.p->maxstacksize); - ci->savedpc = L->savedpc; - ci->tailcalls++; /* one more call lost */ - L->ci--; /* remove new frame */ - goto reentry; - } - case PCRC: { /* it was a C function (`precall' called it) */ - base = L->base; - continue; - } - default: { - return; /* yield */ - } - } - } - case OP_RETURN: { - int b = GETARG_B(i); - if (b != 0) L->top = ra+b-1; - if (L->openupval) luaF_close(L, base); - L->savedpc = pc; - b = luaD_poscall(L, ra); - if (--nexeccalls == 0) /* was previous function running `here'? */ - return; /* no: return */ - else { /* yes: continue its execution */ - if (b) L->top = L->ci->top; - lua_assert(isLua(L->ci)); - lua_assert(GET_OPCODE(*((L->ci)->savedpc - 1)) == OP_CALL); - goto reentry; - } - } - case OP_FORLOOP: { - lua_Number step = nvalue(ra+2); - lua_Number idx = luai_numadd(nvalue(ra), step); /* increment index */ - lua_Number limit = nvalue(ra+1); - if (luai_numlt(0, step) ? luai_numle(idx, limit) - : luai_numle(limit, idx)) { - dojump(L, pc, GETARG_sBx(i)); /* jump back */ - setnvalue(ra, idx); /* update internal index... */ - setnvalue(ra+3, idx); /* ...and external index */ - } - continue; - } - case OP_FORPREP: { - const TValue *init = ra; - const TValue *plimit = ra+1; - const TValue *pstep = ra+2; - L->savedpc = pc; /* next steps may throw errors */ - if (!tonumber(init, ra)) - luaG_runerror(L, LUA_QL("for") " initial value must be a number"); - else if (!tonumber(plimit, ra+1)) - luaG_runerror(L, LUA_QL("for") " limit must be a number"); - else if (!tonumber(pstep, ra+2)) - luaG_runerror(L, LUA_QL("for") " step must be a number"); - setnvalue(ra, luai_numsub(nvalue(ra), nvalue(pstep))); - dojump(L, pc, GETARG_sBx(i)); - continue; - } - case OP_TFORLOOP: { - StkId cb = ra + 3; /* call base */ - setobjs2s(L, cb+2, ra+2); - setobjs2s(L, cb+1, ra+1); - setobjs2s(L, cb, ra); - L->top = cb+3; /* func. + 2 args (state and index) */ - Protect(luaD_call(L, cb, GETARG_C(i))); - L->top = L->ci->top; - cb = RA(i) + 3; /* previous call may change the stack */ - if (!ttisnil(cb)) { /* continue loop? */ - setobjs2s(L, cb-1, cb); /* save control variable */ - dojump(L, pc, GETARG_sBx(*pc)); /* jump back */ - } - pc++; - continue; - } - case OP_SETLIST: { - int n = GETARG_B(i); - int c = GETARG_C(i); - int last; - Table *h; - if (n == 0) { - n = cast_int(L->top - ra) - 1; - L->top = L->ci->top; - } - if (c == 0) c = cast_int(*pc++); - runtime_check(L, ttistable(ra)); - h = hvalue(ra); - last = ((c-1)*LFIELDS_PER_FLUSH) + n; - if (last > h->sizearray) /* needs more space? */ - luaH_resizearray(L, h, last); /* pre-alloc it at once */ - for (; n > 0; n--) { - TValue *val = ra+n; - setobj2t(L, luaH_setnum(L, h, last--), val); - luaC_barriert(L, h, val); - } - continue; - } - case OP_CLOSE: { - luaF_close(L, ra); - continue; - } - case OP_CLOSURE: { - Proto *p; - Closure *ncl; - int nup, j; - p = cl->p->p[GETARG_Bx(i)]; - nup = p->nups; - ncl = luaF_newLclosure(L, nup, cl->env); - ncl->l.p = p; - for (j=0; jl.upvals[j] = cl->upvals[GETARG_B(*pc)]; - else { - lua_assert(GET_OPCODE(*pc) == OP_MOVE); - ncl->l.upvals[j] = luaF_findupval(L, base + GETARG_B(*pc)); - } - } - setclvalue(L, ra, ncl); - Protect(luaC_checkGC(L)); - continue; - } - case OP_VARARG: { - int b = GETARG_B(i) - 1; - int j; - CallInfo *ci = L->ci; - int n = cast_int(ci->base - ci->func) - cl->p->numparams - 1; - if (b == LUA_MULTRET) { - Protect(luaD_checkstack(L, n)); - ra = RA(i); /* previous call may change the stack */ - b = n; - L->top = ra + n; - } - for (j = 0; j < b; j++) { - if (j < n) { - setobjs2s(L, ra + j, ci->base - n + j); - } - else { - setnilvalue(ra + j); - } - } - continue; - } - } - } -} - diff --git a/lib/lua-5.1/src/lvm.h b/lib/lua-5.1/src/lvm.h deleted file mode 100644 index bfe4f56..0000000 --- a/lib/lua-5.1/src/lvm.h +++ /dev/null @@ -1,36 +0,0 @@ -/* -** $Id: lvm.h,v 2.5.1.1 2007/12/27 13:02:25 roberto Exp $ -** Lua virtual machine -** See Copyright Notice in lua.h -*/ - -#ifndef lvm_h -#define lvm_h - - -#include "ldo.h" -#include "lobject.h" -#include "ltm.h" - - -#define tostring(L,o) ((ttype(o) == LUA_TSTRING) || (luaV_tostring(L, o))) - -#define tonumber(o,n) (ttype(o) == LUA_TNUMBER || \ - (((o) = luaV_tonumber(o,n)) != NULL)) - -#define equalobj(L,o1,o2) \ - (ttype(o1) == ttype(o2) && luaV_equalval(L, o1, o2)) - - -LUAI_FUNC int luaV_lessthan (lua_State *L, const TValue *l, const TValue *r); -LUAI_FUNC int luaV_equalval (lua_State *L, const TValue *t1, const TValue *t2); -LUAI_FUNC const TValue *luaV_tonumber (const TValue *obj, TValue *n); -LUAI_FUNC int luaV_tostring (lua_State *L, StkId obj); -LUAI_FUNC void luaV_gettable (lua_State *L, const TValue *t, TValue *key, - StkId val); -LUAI_FUNC void luaV_settable (lua_State *L, const TValue *t, TValue *key, - StkId val); -LUAI_FUNC void luaV_execute (lua_State *L, int nexeccalls); -LUAI_FUNC void luaV_concat (lua_State *L, int total, int last); - -#endif diff --git a/lib/lua-5.1/src/lzio.c b/lib/lua-5.1/src/lzio.c deleted file mode 100644 index 293edd5..0000000 --- a/lib/lua-5.1/src/lzio.c +++ /dev/null @@ -1,82 +0,0 @@ -/* -** $Id: lzio.c,v 1.31.1.1 2007/12/27 13:02:25 roberto Exp $ -** a generic input stream interface -** See Copyright Notice in lua.h -*/ - - -#include - -#define lzio_c -#define LUA_CORE - -#include "lua.h" - -#include "llimits.h" -#include "lmem.h" -#include "lstate.h" -#include "lzio.h" - - -int luaZ_fill (ZIO *z) { - size_t size; - lua_State *L = z->L; - const char *buff; - lua_unlock(L); - buff = z->reader(L, z->data, &size); - lua_lock(L); - if (buff == NULL || size == 0) return EOZ; - z->n = size - 1; - z->p = buff; - return char2int(*(z->p++)); -} - - -int luaZ_lookahead (ZIO *z) { - if (z->n == 0) { - if (luaZ_fill(z) == EOZ) - return EOZ; - else { - z->n++; /* luaZ_fill removed first byte; put back it */ - z->p--; - } - } - return char2int(*z->p); -} - - -void luaZ_init (lua_State *L, ZIO *z, lua_Reader reader, void *data) { - z->L = L; - z->reader = reader; - z->data = data; - z->n = 0; - z->p = NULL; -} - - -/* --------------------------------------------------------------- read --- */ -size_t luaZ_read (ZIO *z, void *b, size_t n) { - while (n) { - size_t m; - if (luaZ_lookahead(z) == EOZ) - return n; /* return number of missing bytes */ - m = (n <= z->n) ? n : z->n; /* min. between n and z->n */ - memcpy(b, z->p, m); - z->n -= m; - z->p += m; - b = (char *)b + m; - n -= m; - } - return 0; -} - -/* ------------------------------------------------------------------------ */ -char *luaZ_openspace (lua_State *L, Mbuffer *buff, size_t n) { - if (n > buff->buffsize) { - if (n < LUA_MINBUFFER) n = LUA_MINBUFFER; - luaZ_resizebuffer(L, buff, n); - } - return buff->buffer; -} - - diff --git a/lib/lua-5.1/src/lzio.h b/lib/lua-5.1/src/lzio.h deleted file mode 100644 index 51d695d..0000000 --- a/lib/lua-5.1/src/lzio.h +++ /dev/null @@ -1,67 +0,0 @@ -/* -** $Id: lzio.h,v 1.21.1.1 2007/12/27 13:02:25 roberto Exp $ -** Buffered streams -** See Copyright Notice in lua.h -*/ - - -#ifndef lzio_h -#define lzio_h - -#include "lua.h" - -#include "lmem.h" - - -#define EOZ (-1) /* end of stream */ - -typedef struct Zio ZIO; - -#define char2int(c) cast(int, cast(unsigned char, (c))) - -#define zgetc(z) (((z)->n--)>0 ? char2int(*(z)->p++) : luaZ_fill(z)) - -typedef struct Mbuffer { - char *buffer; - size_t n; - size_t buffsize; -} Mbuffer; - -#define luaZ_initbuffer(L, buff) ((buff)->buffer = NULL, (buff)->buffsize = 0) - -#define luaZ_buffer(buff) ((buff)->buffer) -#define luaZ_sizebuffer(buff) ((buff)->buffsize) -#define luaZ_bufflen(buff) ((buff)->n) - -#define luaZ_resetbuffer(buff) ((buff)->n = 0) - - -#define luaZ_resizebuffer(L, buff, size) \ - (luaM_reallocvector(L, (buff)->buffer, (buff)->buffsize, size, char), \ - (buff)->buffsize = size) - -#define luaZ_freebuffer(L, buff) luaZ_resizebuffer(L, buff, 0) - - -LUAI_FUNC char *luaZ_openspace (lua_State *L, Mbuffer *buff, size_t n); -LUAI_FUNC void luaZ_init (lua_State *L, ZIO *z, lua_Reader reader, - void *data); -LUAI_FUNC size_t luaZ_read (ZIO* z, void* b, size_t n); /* read next n bytes */ -LUAI_FUNC int luaZ_lookahead (ZIO *z); - - - -/* --------- Private Part ------------------ */ - -struct Zio { - size_t n; /* bytes still unread */ - const char *p; /* current position in buffer */ - lua_Reader reader; - void* data; /* additional data */ - lua_State *L; /* Lua state (for reader) */ -}; - - -LUAI_FUNC int luaZ_fill (ZIO *z); - -#endif diff --git a/lib/lua-5.1/src/print.c b/lib/lua-5.1/src/print.c deleted file mode 100644 index e240cfc..0000000 --- a/lib/lua-5.1/src/print.c +++ /dev/null @@ -1,227 +0,0 @@ -/* -** $Id: print.c,v 1.55a 2006/05/31 13:30:05 lhf Exp $ -** print bytecodes -** See Copyright Notice in lua.h -*/ - -#include -#include - -#define luac_c -#define LUA_CORE - -#include "ldebug.h" -#include "lobject.h" -#include "lopcodes.h" -#include "lundump.h" - -#define PrintFunction luaU_print - -#define Sizeof(x) ((int)sizeof(x)) -#define VOID(p) ((const void*)(p)) - -static void PrintString(const TString* ts) -{ - const char* s=getstr(ts); - size_t i,n=ts->tsv.len; - putchar('"'); - for (i=0; ik[i]; - switch (ttype(o)) - { - case LUA_TNIL: - printf("nil"); - break; - case LUA_TBOOLEAN: - printf(bvalue(o) ? "true" : "false"); - break; - case LUA_TNUMBER: - printf(LUA_NUMBER_FMT,nvalue(o)); - break; - case LUA_TSTRING: - PrintString(rawtsvalue(o)); - break; - default: /* cannot happen */ - printf("? type=%d",ttype(o)); - break; - } -} - -static void PrintCode(const Proto* f) -{ - const Instruction* code=f->code; - int pc,n=f->sizecode; - for (pc=0; pc0) printf("[%d]\t",line); else printf("[-]\t"); - printf("%-9s\t",luaP_opnames[o]); - switch (getOpMode(o)) - { - case iABC: - printf("%d",a); - if (getBMode(o)!=OpArgN) printf(" %d",ISK(b) ? (-1-INDEXK(b)) : b); - if (getCMode(o)!=OpArgN) printf(" %d",ISK(c) ? (-1-INDEXK(c)) : c); - break; - case iABx: - if (getBMode(o)==OpArgK) printf("%d %d",a,-1-bx); else printf("%d %d",a,bx); - break; - case iAsBx: - if (o==OP_JMP) printf("%d",sbx); else printf("%d %d",a,sbx); - break; - } - switch (o) - { - case OP_LOADK: - printf("\t; "); PrintConstant(f,bx); - break; - case OP_GETUPVAL: - case OP_SETUPVAL: - printf("\t; %s", (f->sizeupvalues>0) ? getstr(f->upvalues[b]) : "-"); - break; - case OP_GETGLOBAL: - case OP_SETGLOBAL: - printf("\t; %s",svalue(&f->k[bx])); - break; - case OP_GETTABLE: - case OP_SELF: - if (ISK(c)) { printf("\t; "); PrintConstant(f,INDEXK(c)); } - break; - case OP_SETTABLE: - case OP_ADD: - case OP_SUB: - case OP_MUL: - case OP_DIV: - case OP_POW: - case OP_EQ: - case OP_LT: - case OP_LE: - if (ISK(b) || ISK(c)) - { - printf("\t; "); - if (ISK(b)) PrintConstant(f,INDEXK(b)); else printf("-"); - printf(" "); - if (ISK(c)) PrintConstant(f,INDEXK(c)); else printf("-"); - } - break; - case OP_JMP: - case OP_FORLOOP: - case OP_FORPREP: - printf("\t; to %d",sbx+pc+2); - break; - case OP_CLOSURE: - printf("\t; %p",VOID(f->p[bx])); - break; - case OP_SETLIST: - if (c==0) printf("\t; %d",(int)code[++pc]); - else printf("\t; %d",c); - break; - default: - break; - } - printf("\n"); - } -} - -#define SS(x) (x==1)?"":"s" -#define S(x) x,SS(x) - -static void PrintHeader(const Proto* f) -{ - const char* s=getstr(f->source); - if (*s=='@' || *s=='=') - s++; - else if (*s==LUA_SIGNATURE[0]) - s="(bstring)"; - else - s="(string)"; - printf("\n%s <%s:%d,%d> (%d instruction%s, %d bytes at %p)\n", - (f->linedefined==0)?"main":"function",s, - f->linedefined,f->lastlinedefined, - S(f->sizecode),f->sizecode*Sizeof(Instruction),VOID(f)); - printf("%d%s param%s, %d slot%s, %d upvalue%s, ", - f->numparams,f->is_vararg?"+":"",SS(f->numparams), - S(f->maxstacksize),S(f->nups)); - printf("%d local%s, %d constant%s, %d function%s\n", - S(f->sizelocvars),S(f->sizek),S(f->sizep)); -} - -static void PrintConstants(const Proto* f) -{ - int i,n=f->sizek; - printf("constants (%d) for %p:\n",n,VOID(f)); - for (i=0; isizelocvars; - printf("locals (%d) for %p:\n",n,VOID(f)); - for (i=0; ilocvars[i].varname),f->locvars[i].startpc+1,f->locvars[i].endpc+1); - } -} - -static void PrintUpvalues(const Proto* f) -{ - int i,n=f->sizeupvalues; - printf("upvalues (%d) for %p:\n",n,VOID(f)); - if (f->upvalues==NULL) return; - for (i=0; iupvalues[i])); - } -} - -void PrintFunction(const Proto* f, int full) -{ - int i,n=f->sizep; - PrintHeader(f); - PrintCode(f); - if (full) - { - PrintConstants(f); - PrintLocals(f); - PrintUpvalues(f); - } - for (i=0; ip[i],full); -} diff --git a/lib/lua-5.2/Makefile b/lib/lua-5.2/Makefile deleted file mode 100644 index b2a62cf..0000000 --- a/lib/lua-5.2/Makefile +++ /dev/null @@ -1,114 +0,0 @@ -# Makefile for installing Lua -# See doc/readme.html for installation and customization instructions. - -# == CHANGE THE SETTINGS BELOW TO SUIT YOUR ENVIRONMENT ======================= - -# Your platform. See PLATS for possible values. -PLAT= none - -# Where to install. The installation starts in the src and doc directories, -# so take care if INSTALL_TOP is not an absolute path. See the local target. -# You may want to make INSTALL_LMOD and INSTALL_CMOD consistent with -# LUA_ROOT, LUA_LDIR, and LUA_CDIR in luaconf.h. -INSTALL_TOP= /usr/local -INSTALL_BIN= $(INSTALL_TOP)/bin -INSTALL_INC= $(INSTALL_TOP)/include -INSTALL_LIB= $(INSTALL_TOP)/lib -INSTALL_MAN= $(INSTALL_TOP)/man/man1 -INSTALL_LMOD= $(INSTALL_TOP)/share/lua/$V -INSTALL_CMOD= $(INSTALL_TOP)/lib/lua/$V - -# How to install. If your install program does not support "-p", then -# you may have to run ranlib on the installed liblua.a. -INSTALL= install -p -INSTALL_EXEC= $(INSTALL) -m 0755 -INSTALL_DATA= $(INSTALL) -m 0644 -# -# If you don't have "install" you can use "cp" instead. -# INSTALL= cp -p -# INSTALL_EXEC= $(INSTALL) -# INSTALL_DATA= $(INSTALL) - -# Other utilities. -MKDIR= mkdir -p -RM= rm -f - -# == END OF USER SETTINGS -- NO NEED TO CHANGE ANYTHING BELOW THIS LINE ======= - -# Convenience platforms targets. -PLATS= aix ansi bsd freebsd generic linux macosx mingw posix solaris - -# What to install. -TO_BIN= lua luac -TO_INC= lua.h luaconf.h lualib.h lauxlib.h lua.hpp -TO_LIB= liblua.a -TO_MAN= lua.1 luac.1 - -# Lua version and release. -V= 5.2 -R= $V.4 - -# Targets start here. -all: $(PLAT) - -$(PLATS) clean: - cd src && $(MAKE) $@ - -test: dummy - src/lua -v - -install: dummy - cd src && $(MKDIR) $(INSTALL_BIN) $(INSTALL_INC) $(INSTALL_LIB) $(INSTALL_MAN) $(INSTALL_LMOD) $(INSTALL_CMOD) - cd src && $(INSTALL_EXEC) $(TO_BIN) $(INSTALL_BIN) - cd src && $(INSTALL_DATA) $(TO_INC) $(INSTALL_INC) - cd src && $(INSTALL_DATA) $(TO_LIB) $(INSTALL_LIB) - cd doc && $(INSTALL_DATA) $(TO_MAN) $(INSTALL_MAN) - -uninstall: - cd src && cd $(INSTALL_BIN) && $(RM) $(TO_BIN) - cd src && cd $(INSTALL_INC) && $(RM) $(TO_INC) - cd src && cd $(INSTALL_LIB) && $(RM) $(TO_LIB) - cd doc && cd $(INSTALL_MAN) && $(RM) $(TO_MAN) - -local: - $(MAKE) install INSTALL_TOP=../install - -none: - @echo "Please do 'make PLATFORM' where PLATFORM is one of these:" - @echo " $(PLATS)" - @echo "See doc/readme.html for complete instructions." - -# make may get confused with test/ and install/ -dummy: - -# echo config parameters -echo: - @cd src && $(MAKE) -s echo - @echo "PLAT= $(PLAT)" - @echo "V= $V" - @echo "R= $R" - @echo "TO_BIN= $(TO_BIN)" - @echo "TO_INC= $(TO_INC)" - @echo "TO_LIB= $(TO_LIB)" - @echo "TO_MAN= $(TO_MAN)" - @echo "INSTALL_TOP= $(INSTALL_TOP)" - @echo "INSTALL_BIN= $(INSTALL_BIN)" - @echo "INSTALL_INC= $(INSTALL_INC)" - @echo "INSTALL_LIB= $(INSTALL_LIB)" - @echo "INSTALL_MAN= $(INSTALL_MAN)" - @echo "INSTALL_LMOD= $(INSTALL_LMOD)" - @echo "INSTALL_CMOD= $(INSTALL_CMOD)" - @echo "INSTALL_EXEC= $(INSTALL_EXEC)" - @echo "INSTALL_DATA= $(INSTALL_DATA)" - -# echo pkg-config data -pc: - @echo "version=$R" - @echo "prefix=$(INSTALL_TOP)" - @echo "libdir=$(INSTALL_LIB)" - @echo "includedir=$(INSTALL_INC)" - -# list targets that do not create files (but not all makes understand .PHONY) -.PHONY: all $(PLATS) clean test install local none dummy echo pecho lecho - -# (end of Makefile) diff --git a/lib/lua-5.2/README b/lib/lua-5.2/README deleted file mode 100644 index 710e3ee..0000000 --- a/lib/lua-5.2/README +++ /dev/null @@ -1,6 +0,0 @@ - -This is Lua 5.2.4, released on 25 Feb 2015. - -For installation instructions, license details, and -further information about Lua, see doc/readme.html. - diff --git a/lib/lua-5.2/license b/lib/lua-5.2/license deleted file mode 100644 index 00425ce..0000000 --- a/lib/lua-5.2/license +++ /dev/null @@ -1,7 +0,0 @@ -Copyright © 1994–2021 Lua.org, PUC-Rio. - -Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: - -The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. diff --git a/lib/lua-5.2/src/Makefile b/lib/lua-5.2/src/Makefile deleted file mode 100644 index 7b4b2b7..0000000 --- a/lib/lua-5.2/src/Makefile +++ /dev/null @@ -1,187 +0,0 @@ -# Makefile for building Lua -# See ../doc/readme.html for installation and customization instructions. - -# == CHANGE THE SETTINGS BELOW TO SUIT YOUR ENVIRONMENT ======================= - -# Your platform. See PLATS for possible values. -PLAT= none - -CC= gcc -CFLAGS= -O2 -Wall -DLUA_COMPAT_ALL $(SYSCFLAGS) $(MYCFLAGS) -LDFLAGS= $(SYSLDFLAGS) $(MYLDFLAGS) -LIBS= -lm $(SYSLIBS) $(MYLIBS) - -AR= ar rcu -RANLIB= ranlib -RM= rm -f - -SYSCFLAGS= -SYSLDFLAGS= -SYSLIBS= - -MYCFLAGS= -MYLDFLAGS= -MYLIBS= -MYOBJS= - -# == END OF USER SETTINGS -- NO NEED TO CHANGE ANYTHING BELOW THIS LINE ======= - -PLATS= aix ansi bsd freebsd generic linux macosx mingw posix solaris - -LUA_A= liblua.a -CORE_O= lapi.o lcode.o lctype.o ldebug.o ldo.o ldump.o lfunc.o lgc.o llex.o \ - lmem.o lobject.o lopcodes.o lparser.o lstate.o lstring.o ltable.o \ - ltm.o lundump.o lvm.o lzio.o -LIB_O= lauxlib.o lbaselib.o lbitlib.o lcorolib.o ldblib.o liolib.o \ - lmathlib.o loslib.o lstrlib.o ltablib.o loadlib.o linit.o -BASE_O= $(CORE_O) $(LIB_O) $(MYOBJS) - -LUA_T= lua -LUA_O= lua.o - -LUAC_T= luac -LUAC_O= luac.o - -ALL_O= $(BASE_O) $(LUA_O) $(LUAC_O) -ALL_T= $(LUA_A) $(LUA_T) $(LUAC_T) -ALL_A= $(LUA_A) - -# Targets start here. -default: $(PLAT) - -all: $(ALL_T) - -o: $(ALL_O) - -a: $(ALL_A) - -$(LUA_A): $(BASE_O) - $(AR) $@ $(BASE_O) - $(RANLIB) $@ - -$(LUA_T): $(LUA_O) $(LUA_A) - $(CC) -o $@ $(LDFLAGS) $(LUA_O) $(LUA_A) $(LIBS) - -$(LUAC_T): $(LUAC_O) $(LUA_A) - $(CC) -o $@ $(LDFLAGS) $(LUAC_O) $(LUA_A) $(LIBS) - -clean: - $(RM) $(ALL_T) $(ALL_O) - -depend: - @$(CC) $(CFLAGS) -MM l*.c - -echo: - @echo "PLAT= $(PLAT)" - @echo "CC= $(CC)" - @echo "CFLAGS= $(CFLAGS)" - @echo "LDFLAGS= $(SYSLDFLAGS)" - @echo "LIBS= $(LIBS)" - @echo "AR= $(AR)" - @echo "RANLIB= $(RANLIB)" - @echo "RM= $(RM)" - -# Convenience targets for popular platforms -ALL= all - -none: - @echo "Please do 'make PLATFORM' where PLATFORM is one of these:" - @echo " $(PLATS)" - -aix: - $(MAKE) $(ALL) CC="xlc" CFLAGS="-O2 -DLUA_USE_POSIX -DLUA_USE_DLOPEN" SYSLIBS="-ldl" SYSLDFLAGS="-brtl -bexpall" - -ansi: - $(MAKE) $(ALL) SYSCFLAGS="-DLUA_ANSI" - -bsd: - $(MAKE) $(ALL) SYSCFLAGS="-DLUA_USE_POSIX -DLUA_USE_DLOPEN" SYSLIBS="-Wl,-E" - -freebsd: - $(MAKE) $(ALL) SYSCFLAGS="-DLUA_USE_LINUX" SYSLIBS="-Wl,-E -lreadline" - -generic: $(ALL) - -linux: - $(MAKE) $(ALL) SYSCFLAGS="-DLUA_USE_LINUX" SYSLIBS="-Wl,-E -ldl -lreadline" - -macosx: - $(MAKE) $(ALL) SYSCFLAGS="-DLUA_USE_MACOSX" SYSLIBS="-lreadline" CC=cc - -mingw: - $(MAKE) "LUA_A=lua52.dll" "LUA_T=lua.exe" \ - "AR=$(CC) -shared -o" "RANLIB=strip --strip-unneeded" \ - "SYSCFLAGS=-DLUA_BUILD_AS_DLL" "SYSLIBS=" "SYSLDFLAGS=-s" lua.exe - $(MAKE) "LUAC_T=luac.exe" luac.exe - -posix: - $(MAKE) $(ALL) SYSCFLAGS="-DLUA_USE_POSIX" - -solaris: - $(MAKE) $(ALL) SYSCFLAGS="-DLUA_USE_POSIX -DLUA_USE_DLOPEN" SYSLIBS="-ldl" - -# list targets that do not create files (but not all makes understand .PHONY) -.PHONY: all $(PLATS) default o a clean depend echo none - -# DO NOT DELETE - -lapi.o: lapi.c lua.h luaconf.h lapi.h llimits.h lstate.h lobject.h ltm.h \ - lzio.h lmem.h ldebug.h ldo.h lfunc.h lgc.h lstring.h ltable.h lundump.h \ - lvm.h -lauxlib.o: lauxlib.c lua.h luaconf.h lauxlib.h -lbaselib.o: lbaselib.c lua.h luaconf.h lauxlib.h lualib.h -lbitlib.o: lbitlib.c lua.h luaconf.h lauxlib.h lualib.h -lcode.o: lcode.c lua.h luaconf.h lcode.h llex.h lobject.h llimits.h \ - lzio.h lmem.h lopcodes.h lparser.h ldebug.h lstate.h ltm.h ldo.h lgc.h \ - lstring.h ltable.h lvm.h -lcorolib.o: lcorolib.c lua.h luaconf.h lauxlib.h lualib.h -lctype.o: lctype.c lctype.h lua.h luaconf.h llimits.h -ldblib.o: ldblib.c lua.h luaconf.h lauxlib.h lualib.h -ldebug.o: ldebug.c lua.h luaconf.h lapi.h llimits.h lstate.h lobject.h \ - ltm.h lzio.h lmem.h lcode.h llex.h lopcodes.h lparser.h ldebug.h ldo.h \ - lfunc.h lstring.h lgc.h ltable.h lvm.h -ldo.o: ldo.c lua.h luaconf.h lapi.h llimits.h lstate.h lobject.h ltm.h \ - lzio.h lmem.h ldebug.h ldo.h lfunc.h lgc.h lopcodes.h lparser.h \ - lstring.h ltable.h lundump.h lvm.h -ldump.o: ldump.c lua.h luaconf.h lobject.h llimits.h lstate.h ltm.h \ - lzio.h lmem.h lundump.h -lfunc.o: lfunc.c lua.h luaconf.h lfunc.h lobject.h llimits.h lgc.h \ - lstate.h ltm.h lzio.h lmem.h -lgc.o: lgc.c lua.h luaconf.h ldebug.h lstate.h lobject.h llimits.h ltm.h \ - lzio.h lmem.h ldo.h lfunc.h lgc.h lstring.h ltable.h -linit.o: linit.c lua.h luaconf.h lualib.h lauxlib.h -liolib.o: liolib.c lua.h luaconf.h lauxlib.h lualib.h -llex.o: llex.c lua.h luaconf.h lctype.h llimits.h ldo.h lobject.h \ - lstate.h ltm.h lzio.h lmem.h llex.h lparser.h lstring.h lgc.h ltable.h -lmathlib.o: lmathlib.c lua.h luaconf.h lauxlib.h lualib.h -lmem.o: lmem.c lua.h luaconf.h ldebug.h lstate.h lobject.h llimits.h \ - ltm.h lzio.h lmem.h ldo.h lgc.h -loadlib.o: loadlib.c lua.h luaconf.h lauxlib.h lualib.h -lobject.o: lobject.c lua.h luaconf.h lctype.h llimits.h ldebug.h lstate.h \ - lobject.h ltm.h lzio.h lmem.h ldo.h lstring.h lgc.h lvm.h -lopcodes.o: lopcodes.c lopcodes.h llimits.h lua.h luaconf.h -loslib.o: loslib.c lua.h luaconf.h lauxlib.h lualib.h -lparser.o: lparser.c lua.h luaconf.h lcode.h llex.h lobject.h llimits.h \ - lzio.h lmem.h lopcodes.h lparser.h ldebug.h lstate.h ltm.h ldo.h lfunc.h \ - lstring.h lgc.h ltable.h -lstate.o: lstate.c lua.h luaconf.h lapi.h llimits.h lstate.h lobject.h \ - ltm.h lzio.h lmem.h ldebug.h ldo.h lfunc.h lgc.h llex.h lstring.h \ - ltable.h -lstring.o: lstring.c lua.h luaconf.h lmem.h llimits.h lobject.h lstate.h \ - ltm.h lzio.h lstring.h lgc.h -lstrlib.o: lstrlib.c lua.h luaconf.h lauxlib.h lualib.h -ltable.o: ltable.c lua.h luaconf.h ldebug.h lstate.h lobject.h llimits.h \ - ltm.h lzio.h lmem.h ldo.h lgc.h lstring.h ltable.h lvm.h -ltablib.o: ltablib.c lua.h luaconf.h lauxlib.h lualib.h -ltm.o: ltm.c lua.h luaconf.h lobject.h llimits.h lstate.h ltm.h lzio.h \ - lmem.h lstring.h lgc.h ltable.h -lua.o: lua.c lua.h luaconf.h lauxlib.h lualib.h -luac.o: luac.c lua.h luaconf.h lauxlib.h lobject.h llimits.h lstate.h \ - ltm.h lzio.h lmem.h lundump.h ldebug.h lopcodes.h -lundump.o: lundump.c lua.h luaconf.h ldebug.h lstate.h lobject.h \ - llimits.h ltm.h lzio.h lmem.h ldo.h lfunc.h lstring.h lgc.h lundump.h -lvm.o: lvm.c lua.h luaconf.h ldebug.h lstate.h lobject.h llimits.h ltm.h \ - lzio.h lmem.h ldo.h lfunc.h lgc.h lopcodes.h lstring.h ltable.h lvm.h -lzio.o: lzio.c lua.h luaconf.h llimits.h lmem.h lstate.h lobject.h ltm.h \ - lzio.h - diff --git a/lib/lua-5.2/src/lapi.c b/lib/lua-5.2/src/lapi.c deleted file mode 100644 index d011431..0000000 --- a/lib/lua-5.2/src/lapi.c +++ /dev/null @@ -1,1284 +0,0 @@ -/* -** $Id: lapi.c,v 2.171.1.1 2013/04/12 18:48:47 roberto Exp $ -** Lua API -** See Copyright Notice in lua.h -*/ - - -#include -#include - -#define lapi_c -#define LUA_CORE - -#include "lua.h" - -#include "lapi.h" -#include "ldebug.h" -#include "ldo.h" -#include "lfunc.h" -#include "lgc.h" -#include "lmem.h" -#include "lobject.h" -#include "lstate.h" -#include "lstring.h" -#include "ltable.h" -#include "ltm.h" -#include "lundump.h" -#include "lvm.h" - - - -const char lua_ident[] = - "$LuaVersion: " LUA_COPYRIGHT " $" - "$LuaAuthors: " LUA_AUTHORS " $"; - - -/* value at a non-valid index */ -#define NONVALIDVALUE cast(TValue *, luaO_nilobject) - -/* corresponding test */ -#define isvalid(o) ((o) != luaO_nilobject) - -/* test for pseudo index */ -#define ispseudo(i) ((i) <= LUA_REGISTRYINDEX) - -/* test for valid but not pseudo index */ -#define isstackindex(i, o) (isvalid(o) && !ispseudo(i)) - -#define api_checkvalidindex(L, o) api_check(L, isvalid(o), "invalid index") - -#define api_checkstackindex(L, i, o) \ - api_check(L, isstackindex(i, o), "index not in the stack") - - -static TValue *index2addr (lua_State *L, int idx) { - CallInfo *ci = L->ci; - if (idx > 0) { - TValue *o = ci->func + idx; - api_check(L, idx <= ci->top - (ci->func + 1), "unacceptable index"); - if (o >= L->top) return NONVALIDVALUE; - else return o; - } - else if (!ispseudo(idx)) { /* negative index */ - api_check(L, idx != 0 && -idx <= L->top - (ci->func + 1), "invalid index"); - return L->top + idx; - } - else if (idx == LUA_REGISTRYINDEX) - return &G(L)->l_registry; - else { /* upvalues */ - idx = LUA_REGISTRYINDEX - idx; - api_check(L, idx <= MAXUPVAL + 1, "upvalue index too large"); - if (ttislcf(ci->func)) /* light C function? */ - return NONVALIDVALUE; /* it has no upvalues */ - else { - CClosure *func = clCvalue(ci->func); - return (idx <= func->nupvalues) ? &func->upvalue[idx-1] : NONVALIDVALUE; - } - } -} - - -/* -** to be called by 'lua_checkstack' in protected mode, to grow stack -** capturing memory errors -*/ -static void growstack (lua_State *L, void *ud) { - int size = *(int *)ud; - luaD_growstack(L, size); -} - - -LUA_API int lua_checkstack (lua_State *L, int size) { - int res; - CallInfo *ci = L->ci; - lua_lock(L); - if (L->stack_last - L->top > size) /* stack large enough? */ - res = 1; /* yes; check is OK */ - else { /* no; need to grow stack */ - int inuse = cast_int(L->top - L->stack) + EXTRA_STACK; - if (inuse > LUAI_MAXSTACK - size) /* can grow without overflow? */ - res = 0; /* no */ - else /* try to grow stack */ - res = (luaD_rawrunprotected(L, &growstack, &size) == LUA_OK); - } - if (res && ci->top < L->top + size) - ci->top = L->top + size; /* adjust frame top */ - lua_unlock(L); - return res; -} - - -LUA_API void lua_xmove (lua_State *from, lua_State *to, int n) { - int i; - if (from == to) return; - lua_lock(to); - api_checknelems(from, n); - api_check(from, G(from) == G(to), "moving among independent states"); - api_check(from, to->ci->top - to->top >= n, "not enough elements to move"); - from->top -= n; - for (i = 0; i < n; i++) { - setobj2s(to, to->top++, from->top + i); - } - lua_unlock(to); -} - - -LUA_API lua_CFunction lua_atpanic (lua_State *L, lua_CFunction panicf) { - lua_CFunction old; - lua_lock(L); - old = G(L)->panic; - G(L)->panic = panicf; - lua_unlock(L); - return old; -} - - -LUA_API const lua_Number *lua_version (lua_State *L) { - static const lua_Number version = LUA_VERSION_NUM; - if (L == NULL) return &version; - else return G(L)->version; -} - - - -/* -** basic stack manipulation -*/ - - -/* -** convert an acceptable stack index into an absolute index -*/ -LUA_API int lua_absindex (lua_State *L, int idx) { - return (idx > 0 || ispseudo(idx)) - ? idx - : cast_int(L->top - L->ci->func + idx); -} - - -LUA_API int lua_gettop (lua_State *L) { - return cast_int(L->top - (L->ci->func + 1)); -} - - -LUA_API void lua_settop (lua_State *L, int idx) { - StkId func = L->ci->func; - lua_lock(L); - if (idx >= 0) { - api_check(L, idx <= L->stack_last - (func + 1), "new top too large"); - while (L->top < (func + 1) + idx) - setnilvalue(L->top++); - L->top = (func + 1) + idx; - } - else { - api_check(L, -(idx+1) <= (L->top - (func + 1)), "invalid new top"); - L->top += idx+1; /* `subtract' index (index is negative) */ - } - lua_unlock(L); -} - - -LUA_API void lua_remove (lua_State *L, int idx) { - StkId p; - lua_lock(L); - p = index2addr(L, idx); - api_checkstackindex(L, idx, p); - while (++p < L->top) setobjs2s(L, p-1, p); - L->top--; - lua_unlock(L); -} - - -LUA_API void lua_insert (lua_State *L, int idx) { - StkId p; - StkId q; - lua_lock(L); - p = index2addr(L, idx); - api_checkstackindex(L, idx, p); - for (q = L->top; q > p; q--) /* use L->top as a temporary */ - setobjs2s(L, q, q - 1); - setobjs2s(L, p, L->top); - lua_unlock(L); -} - - -static void moveto (lua_State *L, TValue *fr, int idx) { - TValue *to = index2addr(L, idx); - api_checkvalidindex(L, to); - setobj(L, to, fr); - if (idx < LUA_REGISTRYINDEX) /* function upvalue? */ - luaC_barrier(L, clCvalue(L->ci->func), fr); - /* LUA_REGISTRYINDEX does not need gc barrier - (collector revisits it before finishing collection) */ -} - - -LUA_API void lua_replace (lua_State *L, int idx) { - lua_lock(L); - api_checknelems(L, 1); - moveto(L, L->top - 1, idx); - L->top--; - lua_unlock(L); -} - - -LUA_API void lua_copy (lua_State *L, int fromidx, int toidx) { - TValue *fr; - lua_lock(L); - fr = index2addr(L, fromidx); - moveto(L, fr, toidx); - lua_unlock(L); -} - - -LUA_API void lua_pushvalue (lua_State *L, int idx) { - lua_lock(L); - setobj2s(L, L->top, index2addr(L, idx)); - api_incr_top(L); - lua_unlock(L); -} - - - -/* -** access functions (stack -> C) -*/ - - -LUA_API int lua_type (lua_State *L, int idx) { - StkId o = index2addr(L, idx); - return (isvalid(o) ? ttypenv(o) : LUA_TNONE); -} - - -LUA_API const char *lua_typename (lua_State *L, int t) { - UNUSED(L); - return ttypename(t); -} - - -LUA_API int lua_iscfunction (lua_State *L, int idx) { - StkId o = index2addr(L, idx); - return (ttislcf(o) || (ttisCclosure(o))); -} - - -LUA_API int lua_isnumber (lua_State *L, int idx) { - TValue n; - const TValue *o = index2addr(L, idx); - return tonumber(o, &n); -} - - -LUA_API int lua_isstring (lua_State *L, int idx) { - int t = lua_type(L, idx); - return (t == LUA_TSTRING || t == LUA_TNUMBER); -} - - -LUA_API int lua_isuserdata (lua_State *L, int idx) { - const TValue *o = index2addr(L, idx); - return (ttisuserdata(o) || ttislightuserdata(o)); -} - - -LUA_API int lua_rawequal (lua_State *L, int index1, int index2) { - StkId o1 = index2addr(L, index1); - StkId o2 = index2addr(L, index2); - return (isvalid(o1) && isvalid(o2)) ? luaV_rawequalobj(o1, o2) : 0; -} - - -LUA_API void lua_arith (lua_State *L, int op) { - StkId o1; /* 1st operand */ - StkId o2; /* 2nd operand */ - lua_lock(L); - if (op != LUA_OPUNM) /* all other operations expect two operands */ - api_checknelems(L, 2); - else { /* for unary minus, add fake 2nd operand */ - api_checknelems(L, 1); - setobjs2s(L, L->top, L->top - 1); - L->top++; - } - o1 = L->top - 2; - o2 = L->top - 1; - if (ttisnumber(o1) && ttisnumber(o2)) { - setnvalue(o1, luaO_arith(op, nvalue(o1), nvalue(o2))); - } - else - luaV_arith(L, o1, o1, o2, cast(TMS, op - LUA_OPADD + TM_ADD)); - L->top--; - lua_unlock(L); -} - - -LUA_API int lua_compare (lua_State *L, int index1, int index2, int op) { - StkId o1, o2; - int i = 0; - lua_lock(L); /* may call tag method */ - o1 = index2addr(L, index1); - o2 = index2addr(L, index2); - if (isvalid(o1) && isvalid(o2)) { - switch (op) { - case LUA_OPEQ: i = equalobj(L, o1, o2); break; - case LUA_OPLT: i = luaV_lessthan(L, o1, o2); break; - case LUA_OPLE: i = luaV_lessequal(L, o1, o2); break; - default: api_check(L, 0, "invalid option"); - } - } - lua_unlock(L); - return i; -} - - -LUA_API lua_Number lua_tonumberx (lua_State *L, int idx, int *isnum) { - TValue n; - const TValue *o = index2addr(L, idx); - if (tonumber(o, &n)) { - if (isnum) *isnum = 1; - return nvalue(o); - } - else { - if (isnum) *isnum = 0; - return 0; - } -} - - -LUA_API lua_Integer lua_tointegerx (lua_State *L, int idx, int *isnum) { - TValue n; - const TValue *o = index2addr(L, idx); - if (tonumber(o, &n)) { - lua_Integer res; - lua_Number num = nvalue(o); - lua_number2integer(res, num); - if (isnum) *isnum = 1; - return res; - } - else { - if (isnum) *isnum = 0; - return 0; - } -} - - -LUA_API lua_Unsigned lua_tounsignedx (lua_State *L, int idx, int *isnum) { - TValue n; - const TValue *o = index2addr(L, idx); - if (tonumber(o, &n)) { - lua_Unsigned res; - lua_Number num = nvalue(o); - lua_number2unsigned(res, num); - if (isnum) *isnum = 1; - return res; - } - else { - if (isnum) *isnum = 0; - return 0; - } -} - - -LUA_API int lua_toboolean (lua_State *L, int idx) { - const TValue *o = index2addr(L, idx); - return !l_isfalse(o); -} - - -LUA_API const char *lua_tolstring (lua_State *L, int idx, size_t *len) { - StkId o = index2addr(L, idx); - if (!ttisstring(o)) { - lua_lock(L); /* `luaV_tostring' may create a new string */ - if (!luaV_tostring(L, o)) { /* conversion failed? */ - if (len != NULL) *len = 0; - lua_unlock(L); - return NULL; - } - luaC_checkGC(L); - o = index2addr(L, idx); /* previous call may reallocate the stack */ - lua_unlock(L); - } - if (len != NULL) *len = tsvalue(o)->len; - return svalue(o); -} - - -LUA_API size_t lua_rawlen (lua_State *L, int idx) { - StkId o = index2addr(L, idx); - switch (ttypenv(o)) { - case LUA_TSTRING: return tsvalue(o)->len; - case LUA_TUSERDATA: return uvalue(o)->len; - case LUA_TTABLE: return luaH_getn(hvalue(o)); - default: return 0; - } -} - - -LUA_API lua_CFunction lua_tocfunction (lua_State *L, int idx) { - StkId o = index2addr(L, idx); - if (ttislcf(o)) return fvalue(o); - else if (ttisCclosure(o)) - return clCvalue(o)->f; - else return NULL; /* not a C function */ -} - - -LUA_API void *lua_touserdata (lua_State *L, int idx) { - StkId o = index2addr(L, idx); - switch (ttypenv(o)) { - case LUA_TUSERDATA: return (rawuvalue(o) + 1); - case LUA_TLIGHTUSERDATA: return pvalue(o); - default: return NULL; - } -} - - -LUA_API lua_State *lua_tothread (lua_State *L, int idx) { - StkId o = index2addr(L, idx); - return (!ttisthread(o)) ? NULL : thvalue(o); -} - - -LUA_API const void *lua_topointer (lua_State *L, int idx) { - StkId o = index2addr(L, idx); - switch (ttype(o)) { - case LUA_TTABLE: return hvalue(o); - case LUA_TLCL: return clLvalue(o); - case LUA_TCCL: return clCvalue(o); - case LUA_TLCF: return cast(void *, cast(size_t, fvalue(o))); - case LUA_TTHREAD: return thvalue(o); - case LUA_TUSERDATA: - case LUA_TLIGHTUSERDATA: - return lua_touserdata(L, idx); - default: return NULL; - } -} - - - -/* -** push functions (C -> stack) -*/ - - -LUA_API void lua_pushnil (lua_State *L) { - lua_lock(L); - setnilvalue(L->top); - api_incr_top(L); - lua_unlock(L); -} - - -LUA_API void lua_pushnumber (lua_State *L, lua_Number n) { - lua_lock(L); - setnvalue(L->top, n); - luai_checknum(L, L->top, - luaG_runerror(L, "C API - attempt to push a signaling NaN")); - api_incr_top(L); - lua_unlock(L); -} - - -LUA_API void lua_pushinteger (lua_State *L, lua_Integer n) { - lua_lock(L); - setnvalue(L->top, cast_num(n)); - api_incr_top(L); - lua_unlock(L); -} - - -LUA_API void lua_pushunsigned (lua_State *L, lua_Unsigned u) { - lua_Number n; - lua_lock(L); - n = lua_unsigned2number(u); - setnvalue(L->top, n); - api_incr_top(L); - lua_unlock(L); -} - - -LUA_API const char *lua_pushlstring (lua_State *L, const char *s, size_t len) { - TString *ts; - lua_lock(L); - luaC_checkGC(L); - ts = luaS_newlstr(L, s, len); - setsvalue2s(L, L->top, ts); - api_incr_top(L); - lua_unlock(L); - return getstr(ts); -} - - -LUA_API const char *lua_pushstring (lua_State *L, const char *s) { - if (s == NULL) { - lua_pushnil(L); - return NULL; - } - else { - TString *ts; - lua_lock(L); - luaC_checkGC(L); - ts = luaS_new(L, s); - setsvalue2s(L, L->top, ts); - api_incr_top(L); - lua_unlock(L); - return getstr(ts); - } -} - - -LUA_API const char *lua_pushvfstring (lua_State *L, const char *fmt, - va_list argp) { - const char *ret; - lua_lock(L); - luaC_checkGC(L); - ret = luaO_pushvfstring(L, fmt, argp); - lua_unlock(L); - return ret; -} - - -LUA_API const char *lua_pushfstring (lua_State *L, const char *fmt, ...) { - const char *ret; - va_list argp; - lua_lock(L); - luaC_checkGC(L); - va_start(argp, fmt); - ret = luaO_pushvfstring(L, fmt, argp); - va_end(argp); - lua_unlock(L); - return ret; -} - - -LUA_API void lua_pushcclosure (lua_State *L, lua_CFunction fn, int n) { - lua_lock(L); - if (n == 0) { - setfvalue(L->top, fn); - } - else { - Closure *cl; - api_checknelems(L, n); - api_check(L, n <= MAXUPVAL, "upvalue index too large"); - luaC_checkGC(L); - cl = luaF_newCclosure(L, n); - cl->c.f = fn; - L->top -= n; - while (n--) - setobj2n(L, &cl->c.upvalue[n], L->top + n); - setclCvalue(L, L->top, cl); - } - api_incr_top(L); - lua_unlock(L); -} - - -LUA_API void lua_pushboolean (lua_State *L, int b) { - lua_lock(L); - setbvalue(L->top, (b != 0)); /* ensure that true is 1 */ - api_incr_top(L); - lua_unlock(L); -} - - -LUA_API void lua_pushlightuserdata (lua_State *L, void *p) { - lua_lock(L); - setpvalue(L->top, p); - api_incr_top(L); - lua_unlock(L); -} - - -LUA_API int lua_pushthread (lua_State *L) { - lua_lock(L); - setthvalue(L, L->top, L); - api_incr_top(L); - lua_unlock(L); - return (G(L)->mainthread == L); -} - - - -/* -** get functions (Lua -> stack) -*/ - - -LUA_API void lua_getglobal (lua_State *L, const char *var) { - Table *reg = hvalue(&G(L)->l_registry); - const TValue *gt; /* global table */ - lua_lock(L); - gt = luaH_getint(reg, LUA_RIDX_GLOBALS); - setsvalue2s(L, L->top++, luaS_new(L, var)); - luaV_gettable(L, gt, L->top - 1, L->top - 1); - lua_unlock(L); -} - - -LUA_API void lua_gettable (lua_State *L, int idx) { - StkId t; - lua_lock(L); - t = index2addr(L, idx); - luaV_gettable(L, t, L->top - 1, L->top - 1); - lua_unlock(L); -} - - -LUA_API void lua_getfield (lua_State *L, int idx, const char *k) { - StkId t; - lua_lock(L); - t = index2addr(L, idx); - setsvalue2s(L, L->top, luaS_new(L, k)); - api_incr_top(L); - luaV_gettable(L, t, L->top - 1, L->top - 1); - lua_unlock(L); -} - - -LUA_API void lua_rawget (lua_State *L, int idx) { - StkId t; - lua_lock(L); - t = index2addr(L, idx); - api_check(L, ttistable(t), "table expected"); - setobj2s(L, L->top - 1, luaH_get(hvalue(t), L->top - 1)); - lua_unlock(L); -} - - -LUA_API void lua_rawgeti (lua_State *L, int idx, int n) { - StkId t; - lua_lock(L); - t = index2addr(L, idx); - api_check(L, ttistable(t), "table expected"); - setobj2s(L, L->top, luaH_getint(hvalue(t), n)); - api_incr_top(L); - lua_unlock(L); -} - - -LUA_API void lua_rawgetp (lua_State *L, int idx, const void *p) { - StkId t; - TValue k; - lua_lock(L); - t = index2addr(L, idx); - api_check(L, ttistable(t), "table expected"); - setpvalue(&k, cast(void *, p)); - setobj2s(L, L->top, luaH_get(hvalue(t), &k)); - api_incr_top(L); - lua_unlock(L); -} - - -LUA_API void lua_createtable (lua_State *L, int narray, int nrec) { - Table *t; - lua_lock(L); - luaC_checkGC(L); - t = luaH_new(L); - sethvalue(L, L->top, t); - api_incr_top(L); - if (narray > 0 || nrec > 0) - luaH_resize(L, t, narray, nrec); - lua_unlock(L); -} - - -LUA_API int lua_getmetatable (lua_State *L, int objindex) { - const TValue *obj; - Table *mt = NULL; - int res; - lua_lock(L); - obj = index2addr(L, objindex); - switch (ttypenv(obj)) { - case LUA_TTABLE: - mt = hvalue(obj)->metatable; - break; - case LUA_TUSERDATA: - mt = uvalue(obj)->metatable; - break; - default: - mt = G(L)->mt[ttypenv(obj)]; - break; - } - if (mt == NULL) - res = 0; - else { - sethvalue(L, L->top, mt); - api_incr_top(L); - res = 1; - } - lua_unlock(L); - return res; -} - - -LUA_API void lua_getuservalue (lua_State *L, int idx) { - StkId o; - lua_lock(L); - o = index2addr(L, idx); - api_check(L, ttisuserdata(o), "userdata expected"); - if (uvalue(o)->env) { - sethvalue(L, L->top, uvalue(o)->env); - } else - setnilvalue(L->top); - api_incr_top(L); - lua_unlock(L); -} - - -/* -** set functions (stack -> Lua) -*/ - - -LUA_API void lua_setglobal (lua_State *L, const char *var) { - Table *reg = hvalue(&G(L)->l_registry); - const TValue *gt; /* global table */ - lua_lock(L); - api_checknelems(L, 1); - gt = luaH_getint(reg, LUA_RIDX_GLOBALS); - setsvalue2s(L, L->top++, luaS_new(L, var)); - luaV_settable(L, gt, L->top - 1, L->top - 2); - L->top -= 2; /* pop value and key */ - lua_unlock(L); -} - - -LUA_API void lua_settable (lua_State *L, int idx) { - StkId t; - lua_lock(L); - api_checknelems(L, 2); - t = index2addr(L, idx); - luaV_settable(L, t, L->top - 2, L->top - 1); - L->top -= 2; /* pop index and value */ - lua_unlock(L); -} - - -LUA_API void lua_setfield (lua_State *L, int idx, const char *k) { - StkId t; - lua_lock(L); - api_checknelems(L, 1); - t = index2addr(L, idx); - setsvalue2s(L, L->top++, luaS_new(L, k)); - luaV_settable(L, t, L->top - 1, L->top - 2); - L->top -= 2; /* pop value and key */ - lua_unlock(L); -} - - -LUA_API void lua_rawset (lua_State *L, int idx) { - StkId t; - lua_lock(L); - api_checknelems(L, 2); - t = index2addr(L, idx); - api_check(L, ttistable(t), "table expected"); - setobj2t(L, luaH_set(L, hvalue(t), L->top-2), L->top-1); - invalidateTMcache(hvalue(t)); - luaC_barrierback(L, gcvalue(t), L->top-1); - L->top -= 2; - lua_unlock(L); -} - - -LUA_API void lua_rawseti (lua_State *L, int idx, int n) { - StkId t; - lua_lock(L); - api_checknelems(L, 1); - t = index2addr(L, idx); - api_check(L, ttistable(t), "table expected"); - luaH_setint(L, hvalue(t), n, L->top - 1); - luaC_barrierback(L, gcvalue(t), L->top-1); - L->top--; - lua_unlock(L); -} - - -LUA_API void lua_rawsetp (lua_State *L, int idx, const void *p) { - StkId t; - TValue k; - lua_lock(L); - api_checknelems(L, 1); - t = index2addr(L, idx); - api_check(L, ttistable(t), "table expected"); - setpvalue(&k, cast(void *, p)); - setobj2t(L, luaH_set(L, hvalue(t), &k), L->top - 1); - luaC_barrierback(L, gcvalue(t), L->top - 1); - L->top--; - lua_unlock(L); -} - - -LUA_API int lua_setmetatable (lua_State *L, int objindex) { - TValue *obj; - Table *mt; - lua_lock(L); - api_checknelems(L, 1); - obj = index2addr(L, objindex); - if (ttisnil(L->top - 1)) - mt = NULL; - else { - api_check(L, ttistable(L->top - 1), "table expected"); - mt = hvalue(L->top - 1); - } - switch (ttypenv(obj)) { - case LUA_TTABLE: { - hvalue(obj)->metatable = mt; - if (mt) { - luaC_objbarrierback(L, gcvalue(obj), mt); - luaC_checkfinalizer(L, gcvalue(obj), mt); - } - break; - } - case LUA_TUSERDATA: { - uvalue(obj)->metatable = mt; - if (mt) { - luaC_objbarrier(L, rawuvalue(obj), mt); - luaC_checkfinalizer(L, gcvalue(obj), mt); - } - break; - } - default: { - G(L)->mt[ttypenv(obj)] = mt; - break; - } - } - L->top--; - lua_unlock(L); - return 1; -} - - -LUA_API void lua_setuservalue (lua_State *L, int idx) { - StkId o; - lua_lock(L); - api_checknelems(L, 1); - o = index2addr(L, idx); - api_check(L, ttisuserdata(o), "userdata expected"); - if (ttisnil(L->top - 1)) - uvalue(o)->env = NULL; - else { - api_check(L, ttistable(L->top - 1), "table expected"); - uvalue(o)->env = hvalue(L->top - 1); - luaC_objbarrier(L, gcvalue(o), hvalue(L->top - 1)); - } - L->top--; - lua_unlock(L); -} - - -/* -** `load' and `call' functions (run Lua code) -*/ - - -#define checkresults(L,na,nr) \ - api_check(L, (nr) == LUA_MULTRET || (L->ci->top - L->top >= (nr) - (na)), \ - "results from function overflow current stack size") - - -LUA_API int lua_getctx (lua_State *L, int *ctx) { - if (L->ci->callstatus & CIST_YIELDED) { - if (ctx) *ctx = L->ci->u.c.ctx; - return L->ci->u.c.status; - } - else return LUA_OK; -} - - -LUA_API void lua_callk (lua_State *L, int nargs, int nresults, int ctx, - lua_CFunction k) { - StkId func; - lua_lock(L); - api_check(L, k == NULL || !isLua(L->ci), - "cannot use continuations inside hooks"); - api_checknelems(L, nargs+1); - api_check(L, L->status == LUA_OK, "cannot do calls on non-normal thread"); - checkresults(L, nargs, nresults); - func = L->top - (nargs+1); - if (k != NULL && L->nny == 0) { /* need to prepare continuation? */ - L->ci->u.c.k = k; /* save continuation */ - L->ci->u.c.ctx = ctx; /* save context */ - luaD_call(L, func, nresults, 1); /* do the call */ - } - else /* no continuation or no yieldable */ - luaD_call(L, func, nresults, 0); /* just do the call */ - adjustresults(L, nresults); - lua_unlock(L); -} - - - -/* -** Execute a protected call. -*/ -struct CallS { /* data to `f_call' */ - StkId func; - int nresults; -}; - - -static void f_call (lua_State *L, void *ud) { - struct CallS *c = cast(struct CallS *, ud); - luaD_call(L, c->func, c->nresults, 0); -} - - - -LUA_API int lua_pcallk (lua_State *L, int nargs, int nresults, int errfunc, - int ctx, lua_CFunction k) { - struct CallS c; - int status; - ptrdiff_t func; - lua_lock(L); - api_check(L, k == NULL || !isLua(L->ci), - "cannot use continuations inside hooks"); - api_checknelems(L, nargs+1); - api_check(L, L->status == LUA_OK, "cannot do calls on non-normal thread"); - checkresults(L, nargs, nresults); - if (errfunc == 0) - func = 0; - else { - StkId o = index2addr(L, errfunc); - api_checkstackindex(L, errfunc, o); - func = savestack(L, o); - } - c.func = L->top - (nargs+1); /* function to be called */ - if (k == NULL || L->nny > 0) { /* no continuation or no yieldable? */ - c.nresults = nresults; /* do a 'conventional' protected call */ - status = luaD_pcall(L, f_call, &c, savestack(L, c.func), func); - } - else { /* prepare continuation (call is already protected by 'resume') */ - CallInfo *ci = L->ci; - ci->u.c.k = k; /* save continuation */ - ci->u.c.ctx = ctx; /* save context */ - /* save information for error recovery */ - ci->extra = savestack(L, c.func); - ci->u.c.old_allowhook = L->allowhook; - ci->u.c.old_errfunc = L->errfunc; - L->errfunc = func; - /* mark that function may do error recovery */ - ci->callstatus |= CIST_YPCALL; - luaD_call(L, c.func, nresults, 1); /* do the call */ - ci->callstatus &= ~CIST_YPCALL; - L->errfunc = ci->u.c.old_errfunc; - status = LUA_OK; /* if it is here, there were no errors */ - } - adjustresults(L, nresults); - lua_unlock(L); - return status; -} - - -LUA_API int lua_load (lua_State *L, lua_Reader reader, void *data, - const char *chunkname, const char *mode) { - ZIO z; - int status; - lua_lock(L); - if (!chunkname) chunkname = "?"; - luaZ_init(L, &z, reader, data); - status = luaD_protectedparser(L, &z, chunkname, mode); - if (status == LUA_OK) { /* no errors? */ - LClosure *f = clLvalue(L->top - 1); /* get newly created function */ - if (f->nupvalues == 1) { /* does it have one upvalue? */ - /* get global table from registry */ - Table *reg = hvalue(&G(L)->l_registry); - const TValue *gt = luaH_getint(reg, LUA_RIDX_GLOBALS); - /* set global table as 1st upvalue of 'f' (may be LUA_ENV) */ - setobj(L, f->upvals[0]->v, gt); - luaC_barrier(L, f->upvals[0], gt); - } - } - lua_unlock(L); - return status; -} - - -LUA_API int lua_dump (lua_State *L, lua_Writer writer, void *data) { - int status; - TValue *o; - lua_lock(L); - api_checknelems(L, 1); - o = L->top - 1; - if (isLfunction(o)) - status = luaU_dump(L, getproto(o), writer, data, 0); - else - status = 1; - lua_unlock(L); - return status; -} - - -LUA_API int lua_status (lua_State *L) { - return L->status; -} - - -/* -** Garbage-collection function -*/ - -LUA_API int lua_gc (lua_State *L, int what, int data) { - int res = 0; - global_State *g; - lua_lock(L); - g = G(L); - switch (what) { - case LUA_GCSTOP: { - g->gcrunning = 0; - break; - } - case LUA_GCRESTART: { - luaE_setdebt(g, 0); - g->gcrunning = 1; - break; - } - case LUA_GCCOLLECT: { - luaC_fullgc(L, 0); - break; - } - case LUA_GCCOUNT: { - /* GC values are expressed in Kbytes: #bytes/2^10 */ - res = cast_int(gettotalbytes(g) >> 10); - break; - } - case LUA_GCCOUNTB: { - res = cast_int(gettotalbytes(g) & 0x3ff); - break; - } - case LUA_GCSTEP: { - if (g->gckind == KGC_GEN) { /* generational mode? */ - res = (g->GCestimate == 0); /* true if it will do major collection */ - luaC_forcestep(L); /* do a single step */ - } - else { - lu_mem debt = cast(lu_mem, data) * 1024 - GCSTEPSIZE; - if (g->gcrunning) - debt += g->GCdebt; /* include current debt */ - luaE_setdebt(g, debt); - luaC_forcestep(L); - if (g->gcstate == GCSpause) /* end of cycle? */ - res = 1; /* signal it */ - } - break; - } - case LUA_GCSETPAUSE: { - res = g->gcpause; - g->gcpause = data; - break; - } - case LUA_GCSETMAJORINC: { - res = g->gcmajorinc; - g->gcmajorinc = data; - break; - } - case LUA_GCSETSTEPMUL: { - res = g->gcstepmul; - g->gcstepmul = data; - break; - } - case LUA_GCISRUNNING: { - res = g->gcrunning; - break; - } - case LUA_GCGEN: { /* change collector to generational mode */ - luaC_changemode(L, KGC_GEN); - break; - } - case LUA_GCINC: { /* change collector to incremental mode */ - luaC_changemode(L, KGC_NORMAL); - break; - } - default: res = -1; /* invalid option */ - } - lua_unlock(L); - return res; -} - - - -/* -** miscellaneous functions -*/ - - -LUA_API int lua_error (lua_State *L) { - lua_lock(L); - api_checknelems(L, 1); - luaG_errormsg(L); - /* code unreachable; will unlock when control actually leaves the kernel */ - return 0; /* to avoid warnings */ -} - - -LUA_API int lua_next (lua_State *L, int idx) { - StkId t; - int more; - lua_lock(L); - t = index2addr(L, idx); - api_check(L, ttistable(t), "table expected"); - more = luaH_next(L, hvalue(t), L->top - 1); - if (more) { - api_incr_top(L); - } - else /* no more elements */ - L->top -= 1; /* remove key */ - lua_unlock(L); - return more; -} - - -LUA_API void lua_concat (lua_State *L, int n) { - lua_lock(L); - api_checknelems(L, n); - if (n >= 2) { - luaC_checkGC(L); - luaV_concat(L, n); - } - else if (n == 0) { /* push empty string */ - setsvalue2s(L, L->top, luaS_newlstr(L, "", 0)); - api_incr_top(L); - } - /* else n == 1; nothing to do */ - lua_unlock(L); -} - - -LUA_API void lua_len (lua_State *L, int idx) { - StkId t; - lua_lock(L); - t = index2addr(L, idx); - luaV_objlen(L, L->top, t); - api_incr_top(L); - lua_unlock(L); -} - - -LUA_API lua_Alloc lua_getallocf (lua_State *L, void **ud) { - lua_Alloc f; - lua_lock(L); - if (ud) *ud = G(L)->ud; - f = G(L)->frealloc; - lua_unlock(L); - return f; -} - - -LUA_API void lua_setallocf (lua_State *L, lua_Alloc f, void *ud) { - lua_lock(L); - G(L)->ud = ud; - G(L)->frealloc = f; - lua_unlock(L); -} - - -LUA_API void *lua_newuserdata (lua_State *L, size_t size) { - Udata *u; - lua_lock(L); - luaC_checkGC(L); - u = luaS_newudata(L, size, NULL); - setuvalue(L, L->top, u); - api_incr_top(L); - lua_unlock(L); - return u + 1; -} - - - -static const char *aux_upvalue (StkId fi, int n, TValue **val, - GCObject **owner) { - switch (ttype(fi)) { - case LUA_TCCL: { /* C closure */ - CClosure *f = clCvalue(fi); - if (!(1 <= n && n <= f->nupvalues)) return NULL; - *val = &f->upvalue[n-1]; - if (owner) *owner = obj2gco(f); - return ""; - } - case LUA_TLCL: { /* Lua closure */ - LClosure *f = clLvalue(fi); - TString *name; - Proto *p = f->p; - if (!(1 <= n && n <= p->sizeupvalues)) return NULL; - *val = f->upvals[n-1]->v; - if (owner) *owner = obj2gco(f->upvals[n - 1]); - name = p->upvalues[n-1].name; - return (name == NULL) ? "" : getstr(name); - } - default: return NULL; /* not a closure */ - } -} - - -LUA_API const char *lua_getupvalue (lua_State *L, int funcindex, int n) { - const char *name; - TValue *val = NULL; /* to avoid warnings */ - lua_lock(L); - name = aux_upvalue(index2addr(L, funcindex), n, &val, NULL); - if (name) { - setobj2s(L, L->top, val); - api_incr_top(L); - } - lua_unlock(L); - return name; -} - - -LUA_API const char *lua_setupvalue (lua_State *L, int funcindex, int n) { - const char *name; - TValue *val = NULL; /* to avoid warnings */ - GCObject *owner = NULL; /* to avoid warnings */ - StkId fi; - lua_lock(L); - fi = index2addr(L, funcindex); - api_checknelems(L, 1); - name = aux_upvalue(fi, n, &val, &owner); - if (name) { - L->top--; - setobj(L, val, L->top); - luaC_barrier(L, owner, L->top); - } - lua_unlock(L); - return name; -} - - -static UpVal **getupvalref (lua_State *L, int fidx, int n, LClosure **pf) { - LClosure *f; - StkId fi = index2addr(L, fidx); - api_check(L, ttisLclosure(fi), "Lua function expected"); - f = clLvalue(fi); - api_check(L, (1 <= n && n <= f->p->sizeupvalues), "invalid upvalue index"); - if (pf) *pf = f; - return &f->upvals[n - 1]; /* get its upvalue pointer */ -} - - -LUA_API void *lua_upvalueid (lua_State *L, int fidx, int n) { - StkId fi = index2addr(L, fidx); - switch (ttype(fi)) { - case LUA_TLCL: { /* lua closure */ - return *getupvalref(L, fidx, n, NULL); - } - case LUA_TCCL: { /* C closure */ - CClosure *f = clCvalue(fi); - api_check(L, 1 <= n && n <= f->nupvalues, "invalid upvalue index"); - return &f->upvalue[n - 1]; - } - default: { - api_check(L, 0, "closure expected"); - return NULL; - } - } -} - - -LUA_API void lua_upvaluejoin (lua_State *L, int fidx1, int n1, - int fidx2, int n2) { - LClosure *f1; - UpVal **up1 = getupvalref(L, fidx1, n1, &f1); - UpVal **up2 = getupvalref(L, fidx2, n2, NULL); - *up1 = *up2; - luaC_objbarrier(L, f1, *up2); -} - diff --git a/lib/lua-5.2/src/lapi.h b/lib/lua-5.2/src/lapi.h deleted file mode 100644 index c7d34ad..0000000 --- a/lib/lua-5.2/src/lapi.h +++ /dev/null @@ -1,24 +0,0 @@ -/* -** $Id: lapi.h,v 2.7.1.1 2013/04/12 18:48:47 roberto Exp $ -** Auxiliary functions from Lua API -** See Copyright Notice in lua.h -*/ - -#ifndef lapi_h -#define lapi_h - - -#include "llimits.h" -#include "lstate.h" - -#define api_incr_top(L) {L->top++; api_check(L, L->top <= L->ci->top, \ - "stack overflow");} - -#define adjustresults(L,nres) \ - { if ((nres) == LUA_MULTRET && L->ci->top < L->top) L->ci->top = L->top; } - -#define api_checknelems(L,n) api_check(L, (n) < (L->top - L->ci->func), \ - "not enough elements in the stack") - - -#endif diff --git a/lib/lua-5.2/src/lauxlib.c b/lib/lua-5.2/src/lauxlib.c deleted file mode 100644 index b00f8c7..0000000 --- a/lib/lua-5.2/src/lauxlib.c +++ /dev/null @@ -1,959 +0,0 @@ -/* -** $Id: lauxlib.c,v 1.248.1.1 2013/04/12 18:48:47 roberto Exp $ -** Auxiliary functions for building Lua libraries -** See Copyright Notice in lua.h -*/ - - -#include -#include -#include -#include -#include - - -/* This file uses only the official API of Lua. -** Any function declared here could be written as an application function. -*/ - -#define lauxlib_c -#define LUA_LIB - -#include "lua.h" - -#include "lauxlib.h" - - -/* -** {====================================================== -** Traceback -** ======================================================= -*/ - - -#define LEVELS1 12 /* size of the first part of the stack */ -#define LEVELS2 10 /* size of the second part of the stack */ - - - -/* -** search for 'objidx' in table at index -1. -** return 1 + string at top if find a good name. -*/ -static int findfield (lua_State *L, int objidx, int level) { - if (level == 0 || !lua_istable(L, -1)) - return 0; /* not found */ - lua_pushnil(L); /* start 'next' loop */ - while (lua_next(L, -2)) { /* for each pair in table */ - if (lua_type(L, -2) == LUA_TSTRING) { /* ignore non-string keys */ - if (lua_rawequal(L, objidx, -1)) { /* found object? */ - lua_pop(L, 1); /* remove value (but keep name) */ - return 1; - } - else if (findfield(L, objidx, level - 1)) { /* try recursively */ - lua_remove(L, -2); /* remove table (but keep name) */ - lua_pushliteral(L, "."); - lua_insert(L, -2); /* place '.' between the two names */ - lua_concat(L, 3); - return 1; - } - } - lua_pop(L, 1); /* remove value */ - } - return 0; /* not found */ -} - - -static int pushglobalfuncname (lua_State *L, lua_Debug *ar) { - int top = lua_gettop(L); - lua_getinfo(L, "f", ar); /* push function */ - lua_pushglobaltable(L); - if (findfield(L, top + 1, 2)) { - lua_copy(L, -1, top + 1); /* move name to proper place */ - lua_pop(L, 2); /* remove pushed values */ - return 1; - } - else { - lua_settop(L, top); /* remove function and global table */ - return 0; - } -} - - -static void pushfuncname (lua_State *L, lua_Debug *ar) { - if (*ar->namewhat != '\0') /* is there a name? */ - lua_pushfstring(L, "function " LUA_QS, ar->name); - else if (*ar->what == 'm') /* main? */ - lua_pushliteral(L, "main chunk"); - else if (*ar->what == 'C') { - if (pushglobalfuncname(L, ar)) { - lua_pushfstring(L, "function " LUA_QS, lua_tostring(L, -1)); - lua_remove(L, -2); /* remove name */ - } - else - lua_pushliteral(L, "?"); - } - else - lua_pushfstring(L, "function <%s:%d>", ar->short_src, ar->linedefined); -} - - -static int countlevels (lua_State *L) { - lua_Debug ar; - int li = 1, le = 1; - /* find an upper bound */ - while (lua_getstack(L, le, &ar)) { li = le; le *= 2; } - /* do a binary search */ - while (li < le) { - int m = (li + le)/2; - if (lua_getstack(L, m, &ar)) li = m + 1; - else le = m; - } - return le - 1; -} - - -LUALIB_API void luaL_traceback (lua_State *L, lua_State *L1, - const char *msg, int level) { - lua_Debug ar; - int top = lua_gettop(L); - int numlevels = countlevels(L1); - int mark = (numlevels > LEVELS1 + LEVELS2) ? LEVELS1 : 0; - if (msg) lua_pushfstring(L, "%s\n", msg); - lua_pushliteral(L, "stack traceback:"); - while (lua_getstack(L1, level++, &ar)) { - if (level == mark) { /* too many levels? */ - lua_pushliteral(L, "\n\t..."); /* add a '...' */ - level = numlevels - LEVELS2; /* and skip to last ones */ - } - else { - lua_getinfo(L1, "Slnt", &ar); - lua_pushfstring(L, "\n\t%s:", ar.short_src); - if (ar.currentline > 0) - lua_pushfstring(L, "%d:", ar.currentline); - lua_pushliteral(L, " in "); - pushfuncname(L, &ar); - if (ar.istailcall) - lua_pushliteral(L, "\n\t(...tail calls...)"); - lua_concat(L, lua_gettop(L) - top); - } - } - lua_concat(L, lua_gettop(L) - top); -} - -/* }====================================================== */ - - -/* -** {====================================================== -** Error-report functions -** ======================================================= -*/ - -LUALIB_API int luaL_argerror (lua_State *L, int narg, const char *extramsg) { - lua_Debug ar; - if (!lua_getstack(L, 0, &ar)) /* no stack frame? */ - return luaL_error(L, "bad argument #%d (%s)", narg, extramsg); - lua_getinfo(L, "n", &ar); - if (strcmp(ar.namewhat, "method") == 0) { - narg--; /* do not count `self' */ - if (narg == 0) /* error is in the self argument itself? */ - return luaL_error(L, "calling " LUA_QS " on bad self (%s)", - ar.name, extramsg); - } - if (ar.name == NULL) - ar.name = (pushglobalfuncname(L, &ar)) ? lua_tostring(L, -1) : "?"; - return luaL_error(L, "bad argument #%d to " LUA_QS " (%s)", - narg, ar.name, extramsg); -} - - -static int typeerror (lua_State *L, int narg, const char *tname) { - const char *msg = lua_pushfstring(L, "%s expected, got %s", - tname, luaL_typename(L, narg)); - return luaL_argerror(L, narg, msg); -} - - -static void tag_error (lua_State *L, int narg, int tag) { - typeerror(L, narg, lua_typename(L, tag)); -} - - -LUALIB_API void luaL_where (lua_State *L, int level) { - lua_Debug ar; - if (lua_getstack(L, level, &ar)) { /* check function at level */ - lua_getinfo(L, "Sl", &ar); /* get info about it */ - if (ar.currentline > 0) { /* is there info? */ - lua_pushfstring(L, "%s:%d: ", ar.short_src, ar.currentline); - return; - } - } - lua_pushliteral(L, ""); /* else, no information available... */ -} - - -LUALIB_API int luaL_error (lua_State *L, const char *fmt, ...) { - va_list argp; - va_start(argp, fmt); - luaL_where(L, 1); - lua_pushvfstring(L, fmt, argp); - va_end(argp); - lua_concat(L, 2); - return lua_error(L); -} - - -LUALIB_API int luaL_fileresult (lua_State *L, int stat, const char *fname) { - int en = errno; /* calls to Lua API may change this value */ - if (stat) { - lua_pushboolean(L, 1); - return 1; - } - else { - lua_pushnil(L); - if (fname) - lua_pushfstring(L, "%s: %s", fname, strerror(en)); - else - lua_pushstring(L, strerror(en)); - lua_pushinteger(L, en); - return 3; - } -} - - -#if !defined(inspectstat) /* { */ - -#if defined(LUA_USE_POSIX) - -#include - -/* -** use appropriate macros to interpret 'pclose' return status -*/ -#define inspectstat(stat,what) \ - if (WIFEXITED(stat)) { stat = WEXITSTATUS(stat); } \ - else if (WIFSIGNALED(stat)) { stat = WTERMSIG(stat); what = "signal"; } - -#else - -#define inspectstat(stat,what) /* no op */ - -#endif - -#endif /* } */ - - -LUALIB_API int luaL_execresult (lua_State *L, int stat) { - const char *what = "exit"; /* type of termination */ - if (stat == -1) /* error? */ - return luaL_fileresult(L, 0, NULL); - else { - inspectstat(stat, what); /* interpret result */ - if (*what == 'e' && stat == 0) /* successful termination? */ - lua_pushboolean(L, 1); - else - lua_pushnil(L); - lua_pushstring(L, what); - lua_pushinteger(L, stat); - return 3; /* return true/nil,what,code */ - } -} - -/* }====================================================== */ - - -/* -** {====================================================== -** Userdata's metatable manipulation -** ======================================================= -*/ - -LUALIB_API int luaL_newmetatable (lua_State *L, const char *tname) { - luaL_getmetatable(L, tname); /* try to get metatable */ - if (!lua_isnil(L, -1)) /* name already in use? */ - return 0; /* leave previous value on top, but return 0 */ - lua_pop(L, 1); - lua_newtable(L); /* create metatable */ - lua_pushvalue(L, -1); - lua_setfield(L, LUA_REGISTRYINDEX, tname); /* registry.name = metatable */ - return 1; -} - - -LUALIB_API void luaL_setmetatable (lua_State *L, const char *tname) { - luaL_getmetatable(L, tname); - lua_setmetatable(L, -2); -} - - -LUALIB_API void *luaL_testudata (lua_State *L, int ud, const char *tname) { - void *p = lua_touserdata(L, ud); - if (p != NULL) { /* value is a userdata? */ - if (lua_getmetatable(L, ud)) { /* does it have a metatable? */ - luaL_getmetatable(L, tname); /* get correct metatable */ - if (!lua_rawequal(L, -1, -2)) /* not the same? */ - p = NULL; /* value is a userdata with wrong metatable */ - lua_pop(L, 2); /* remove both metatables */ - return p; - } - } - return NULL; /* value is not a userdata with a metatable */ -} - - -LUALIB_API void *luaL_checkudata (lua_State *L, int ud, const char *tname) { - void *p = luaL_testudata(L, ud, tname); - if (p == NULL) typeerror(L, ud, tname); - return p; -} - -/* }====================================================== */ - - -/* -** {====================================================== -** Argument check functions -** ======================================================= -*/ - -LUALIB_API int luaL_checkoption (lua_State *L, int narg, const char *def, - const char *const lst[]) { - const char *name = (def) ? luaL_optstring(L, narg, def) : - luaL_checkstring(L, narg); - int i; - for (i=0; lst[i]; i++) - if (strcmp(lst[i], name) == 0) - return i; - return luaL_argerror(L, narg, - lua_pushfstring(L, "invalid option " LUA_QS, name)); -} - - -LUALIB_API void luaL_checkstack (lua_State *L, int space, const char *msg) { - /* keep some extra space to run error routines, if needed */ - const int extra = LUA_MINSTACK; - if (!lua_checkstack(L, space + extra)) { - if (msg) - luaL_error(L, "stack overflow (%s)", msg); - else - luaL_error(L, "stack overflow"); - } -} - - -LUALIB_API void luaL_checktype (lua_State *L, int narg, int t) { - if (lua_type(L, narg) != t) - tag_error(L, narg, t); -} - - -LUALIB_API void luaL_checkany (lua_State *L, int narg) { - if (lua_type(L, narg) == LUA_TNONE) - luaL_argerror(L, narg, "value expected"); -} - - -LUALIB_API const char *luaL_checklstring (lua_State *L, int narg, size_t *len) { - const char *s = lua_tolstring(L, narg, len); - if (!s) tag_error(L, narg, LUA_TSTRING); - return s; -} - - -LUALIB_API const char *luaL_optlstring (lua_State *L, int narg, - const char *def, size_t *len) { - if (lua_isnoneornil(L, narg)) { - if (len) - *len = (def ? strlen(def) : 0); - return def; - } - else return luaL_checklstring(L, narg, len); -} - - -LUALIB_API lua_Number luaL_checknumber (lua_State *L, int narg) { - int isnum; - lua_Number d = lua_tonumberx(L, narg, &isnum); - if (!isnum) - tag_error(L, narg, LUA_TNUMBER); - return d; -} - - -LUALIB_API lua_Number luaL_optnumber (lua_State *L, int narg, lua_Number def) { - return luaL_opt(L, luaL_checknumber, narg, def); -} - - -LUALIB_API lua_Integer luaL_checkinteger (lua_State *L, int narg) { - int isnum; - lua_Integer d = lua_tointegerx(L, narg, &isnum); - if (!isnum) - tag_error(L, narg, LUA_TNUMBER); - return d; -} - - -LUALIB_API lua_Unsigned luaL_checkunsigned (lua_State *L, int narg) { - int isnum; - lua_Unsigned d = lua_tounsignedx(L, narg, &isnum); - if (!isnum) - tag_error(L, narg, LUA_TNUMBER); - return d; -} - - -LUALIB_API lua_Integer luaL_optinteger (lua_State *L, int narg, - lua_Integer def) { - return luaL_opt(L, luaL_checkinteger, narg, def); -} - - -LUALIB_API lua_Unsigned luaL_optunsigned (lua_State *L, int narg, - lua_Unsigned def) { - return luaL_opt(L, luaL_checkunsigned, narg, def); -} - -/* }====================================================== */ - - -/* -** {====================================================== -** Generic Buffer manipulation -** ======================================================= -*/ - -/* -** check whether buffer is using a userdata on the stack as a temporary -** buffer -*/ -#define buffonstack(B) ((B)->b != (B)->initb) - - -/* -** returns a pointer to a free area with at least 'sz' bytes -*/ -LUALIB_API char *luaL_prepbuffsize (luaL_Buffer *B, size_t sz) { - lua_State *L = B->L; - if (B->size - B->n < sz) { /* not enough space? */ - char *newbuff; - size_t newsize = B->size * 2; /* double buffer size */ - if (newsize - B->n < sz) /* not big enough? */ - newsize = B->n + sz; - if (newsize < B->n || newsize - B->n < sz) - luaL_error(L, "buffer too large"); - /* create larger buffer */ - newbuff = (char *)lua_newuserdata(L, newsize * sizeof(char)); - /* move content to new buffer */ - memcpy(newbuff, B->b, B->n * sizeof(char)); - if (buffonstack(B)) - lua_remove(L, -2); /* remove old buffer */ - B->b = newbuff; - B->size = newsize; - } - return &B->b[B->n]; -} - - -LUALIB_API void luaL_addlstring (luaL_Buffer *B, const char *s, size_t l) { - char *b = luaL_prepbuffsize(B, l); - memcpy(b, s, l * sizeof(char)); - luaL_addsize(B, l); -} - - -LUALIB_API void luaL_addstring (luaL_Buffer *B, const char *s) { - luaL_addlstring(B, s, strlen(s)); -} - - -LUALIB_API void luaL_pushresult (luaL_Buffer *B) { - lua_State *L = B->L; - lua_pushlstring(L, B->b, B->n); - if (buffonstack(B)) - lua_remove(L, -2); /* remove old buffer */ -} - - -LUALIB_API void luaL_pushresultsize (luaL_Buffer *B, size_t sz) { - luaL_addsize(B, sz); - luaL_pushresult(B); -} - - -LUALIB_API void luaL_addvalue (luaL_Buffer *B) { - lua_State *L = B->L; - size_t l; - const char *s = lua_tolstring(L, -1, &l); - if (buffonstack(B)) - lua_insert(L, -2); /* put value below buffer */ - luaL_addlstring(B, s, l); - lua_remove(L, (buffonstack(B)) ? -2 : -1); /* remove value */ -} - - -LUALIB_API void luaL_buffinit (lua_State *L, luaL_Buffer *B) { - B->L = L; - B->b = B->initb; - B->n = 0; - B->size = LUAL_BUFFERSIZE; -} - - -LUALIB_API char *luaL_buffinitsize (lua_State *L, luaL_Buffer *B, size_t sz) { - luaL_buffinit(L, B); - return luaL_prepbuffsize(B, sz); -} - -/* }====================================================== */ - - -/* -** {====================================================== -** Reference system -** ======================================================= -*/ - -/* index of free-list header */ -#define freelist 0 - - -LUALIB_API int luaL_ref (lua_State *L, int t) { - int ref; - if (lua_isnil(L, -1)) { - lua_pop(L, 1); /* remove from stack */ - return LUA_REFNIL; /* `nil' has a unique fixed reference */ - } - t = lua_absindex(L, t); - lua_rawgeti(L, t, freelist); /* get first free element */ - ref = (int)lua_tointeger(L, -1); /* ref = t[freelist] */ - lua_pop(L, 1); /* remove it from stack */ - if (ref != 0) { /* any free element? */ - lua_rawgeti(L, t, ref); /* remove it from list */ - lua_rawseti(L, t, freelist); /* (t[freelist] = t[ref]) */ - } - else /* no free elements */ - ref = (int)lua_rawlen(L, t) + 1; /* get a new reference */ - lua_rawseti(L, t, ref); - return ref; -} - - -LUALIB_API void luaL_unref (lua_State *L, int t, int ref) { - if (ref >= 0) { - t = lua_absindex(L, t); - lua_rawgeti(L, t, freelist); - lua_rawseti(L, t, ref); /* t[ref] = t[freelist] */ - lua_pushinteger(L, ref); - lua_rawseti(L, t, freelist); /* t[freelist] = ref */ - } -} - -/* }====================================================== */ - - -/* -** {====================================================== -** Load functions -** ======================================================= -*/ - -typedef struct LoadF { - int n; /* number of pre-read characters */ - FILE *f; /* file being read */ - char buff[LUAL_BUFFERSIZE]; /* area for reading file */ -} LoadF; - - -static const char *getF (lua_State *L, void *ud, size_t *size) { - LoadF *lf = (LoadF *)ud; - (void)L; /* not used */ - if (lf->n > 0) { /* are there pre-read characters to be read? */ - *size = lf->n; /* return them (chars already in buffer) */ - lf->n = 0; /* no more pre-read characters */ - } - else { /* read a block from file */ - /* 'fread' can return > 0 *and* set the EOF flag. If next call to - 'getF' called 'fread', it might still wait for user input. - The next check avoids this problem. */ - if (feof(lf->f)) return NULL; - *size = fread(lf->buff, 1, sizeof(lf->buff), lf->f); /* read block */ - } - return lf->buff; -} - - -static int errfile (lua_State *L, const char *what, int fnameindex) { - const char *serr = strerror(errno); - const char *filename = lua_tostring(L, fnameindex) + 1; - lua_pushfstring(L, "cannot %s %s: %s", what, filename, serr); - lua_remove(L, fnameindex); - return LUA_ERRFILE; -} - - -static int skipBOM (LoadF *lf) { - const char *p = "\xEF\xBB\xBF"; /* Utf8 BOM mark */ - int c; - lf->n = 0; - do { - c = getc(lf->f); - if (c == EOF || c != *(const unsigned char *)p++) return c; - lf->buff[lf->n++] = c; /* to be read by the parser */ - } while (*p != '\0'); - lf->n = 0; /* prefix matched; discard it */ - return getc(lf->f); /* return next character */ -} - - -/* -** reads the first character of file 'f' and skips an optional BOM mark -** in its beginning plus its first line if it starts with '#'. Returns -** true if it skipped the first line. In any case, '*cp' has the -** first "valid" character of the file (after the optional BOM and -** a first-line comment). -*/ -static int skipcomment (LoadF *lf, int *cp) { - int c = *cp = skipBOM(lf); - if (c == '#') { /* first line is a comment (Unix exec. file)? */ - do { /* skip first line */ - c = getc(lf->f); - } while (c != EOF && c != '\n') ; - *cp = getc(lf->f); /* skip end-of-line, if present */ - return 1; /* there was a comment */ - } - else return 0; /* no comment */ -} - - -LUALIB_API int luaL_loadfilex (lua_State *L, const char *filename, - const char *mode) { - LoadF lf; - int status, readstatus; - int c; - int fnameindex = lua_gettop(L) + 1; /* index of filename on the stack */ - if (filename == NULL) { - lua_pushliteral(L, "=stdin"); - lf.f = stdin; - } - else { - lua_pushfstring(L, "@%s", filename); - lf.f = fopen(filename, "r"); - if (lf.f == NULL) return errfile(L, "open", fnameindex); - } - if (skipcomment(&lf, &c)) /* read initial portion */ - lf.buff[lf.n++] = '\n'; /* add line to correct line numbers */ - if (c == LUA_SIGNATURE[0] && filename) { /* binary file? */ - lf.f = freopen(filename, "rb", lf.f); /* reopen in binary mode */ - if (lf.f == NULL) return errfile(L, "reopen", fnameindex); - skipcomment(&lf, &c); /* re-read initial portion */ - } - if (c != EOF) - lf.buff[lf.n++] = c; /* 'c' is the first character of the stream */ - status = lua_load(L, getF, &lf, lua_tostring(L, -1), mode); - readstatus = ferror(lf.f); - if (filename) fclose(lf.f); /* close file (even in case of errors) */ - if (readstatus) { - lua_settop(L, fnameindex); /* ignore results from `lua_load' */ - return errfile(L, "read", fnameindex); - } - lua_remove(L, fnameindex); - return status; -} - - -typedef struct LoadS { - const char *s; - size_t size; -} LoadS; - - -static const char *getS (lua_State *L, void *ud, size_t *size) { - LoadS *ls = (LoadS *)ud; - (void)L; /* not used */ - if (ls->size == 0) return NULL; - *size = ls->size; - ls->size = 0; - return ls->s; -} - - -LUALIB_API int luaL_loadbufferx (lua_State *L, const char *buff, size_t size, - const char *name, const char *mode) { - LoadS ls; - ls.s = buff; - ls.size = size; - return lua_load(L, getS, &ls, name, mode); -} - - -LUALIB_API int luaL_loadstring (lua_State *L, const char *s) { - return luaL_loadbuffer(L, s, strlen(s), s); -} - -/* }====================================================== */ - - - -LUALIB_API int luaL_getmetafield (lua_State *L, int obj, const char *event) { - if (!lua_getmetatable(L, obj)) /* no metatable? */ - return 0; - lua_pushstring(L, event); - lua_rawget(L, -2); - if (lua_isnil(L, -1)) { - lua_pop(L, 2); /* remove metatable and metafield */ - return 0; - } - else { - lua_remove(L, -2); /* remove only metatable */ - return 1; - } -} - - -LUALIB_API int luaL_callmeta (lua_State *L, int obj, const char *event) { - obj = lua_absindex(L, obj); - if (!luaL_getmetafield(L, obj, event)) /* no metafield? */ - return 0; - lua_pushvalue(L, obj); - lua_call(L, 1, 1); - return 1; -} - - -LUALIB_API int luaL_len (lua_State *L, int idx) { - int l; - int isnum; - lua_len(L, idx); - l = (int)lua_tointegerx(L, -1, &isnum); - if (!isnum) - luaL_error(L, "object length is not a number"); - lua_pop(L, 1); /* remove object */ - return l; -} - - -LUALIB_API const char *luaL_tolstring (lua_State *L, int idx, size_t *len) { - if (!luaL_callmeta(L, idx, "__tostring")) { /* no metafield? */ - switch (lua_type(L, idx)) { - case LUA_TNUMBER: - case LUA_TSTRING: - lua_pushvalue(L, idx); - break; - case LUA_TBOOLEAN: - lua_pushstring(L, (lua_toboolean(L, idx) ? "true" : "false")); - break; - case LUA_TNIL: - lua_pushliteral(L, "nil"); - break; - default: - lua_pushfstring(L, "%s: %p", luaL_typename(L, idx), - lua_topointer(L, idx)); - break; - } - } - return lua_tolstring(L, -1, len); -} - - -/* -** {====================================================== -** Compatibility with 5.1 module functions -** ======================================================= -*/ -#if defined(LUA_COMPAT_MODULE) - -static const char *luaL_findtable (lua_State *L, int idx, - const char *fname, int szhint) { - const char *e; - if (idx) lua_pushvalue(L, idx); - do { - e = strchr(fname, '.'); - if (e == NULL) e = fname + strlen(fname); - lua_pushlstring(L, fname, e - fname); - lua_rawget(L, -2); - if (lua_isnil(L, -1)) { /* no such field? */ - lua_pop(L, 1); /* remove this nil */ - lua_createtable(L, 0, (*e == '.' ? 1 : szhint)); /* new table for field */ - lua_pushlstring(L, fname, e - fname); - lua_pushvalue(L, -2); - lua_settable(L, -4); /* set new table into field */ - } - else if (!lua_istable(L, -1)) { /* field has a non-table value? */ - lua_pop(L, 2); /* remove table and value */ - return fname; /* return problematic part of the name */ - } - lua_remove(L, -2); /* remove previous table */ - fname = e + 1; - } while (*e == '.'); - return NULL; -} - - -/* -** Count number of elements in a luaL_Reg list. -*/ -static int libsize (const luaL_Reg *l) { - int size = 0; - for (; l && l->name; l++) size++; - return size; -} - - -/* -** Find or create a module table with a given name. The function -** first looks at the _LOADED table and, if that fails, try a -** global variable with that name. In any case, leaves on the stack -** the module table. -*/ -LUALIB_API void luaL_pushmodule (lua_State *L, const char *modname, - int sizehint) { - luaL_findtable(L, LUA_REGISTRYINDEX, "_LOADED", 1); /* get _LOADED table */ - lua_getfield(L, -1, modname); /* get _LOADED[modname] */ - if (!lua_istable(L, -1)) { /* not found? */ - lua_pop(L, 1); /* remove previous result */ - /* try global variable (and create one if it does not exist) */ - lua_pushglobaltable(L); - if (luaL_findtable(L, 0, modname, sizehint) != NULL) - luaL_error(L, "name conflict for module " LUA_QS, modname); - lua_pushvalue(L, -1); - lua_setfield(L, -3, modname); /* _LOADED[modname] = new table */ - } - lua_remove(L, -2); /* remove _LOADED table */ -} - - -LUALIB_API void luaL_openlib (lua_State *L, const char *libname, - const luaL_Reg *l, int nup) { - luaL_checkversion(L); - if (libname) { - luaL_pushmodule(L, libname, libsize(l)); /* get/create library table */ - lua_insert(L, -(nup + 1)); /* move library table to below upvalues */ - } - if (l) - luaL_setfuncs(L, l, nup); - else - lua_pop(L, nup); /* remove upvalues */ -} - -#endif -/* }====================================================== */ - -/* -** set functions from list 'l' into table at top - 'nup'; each -** function gets the 'nup' elements at the top as upvalues. -** Returns with only the table at the stack. -*/ -LUALIB_API void luaL_setfuncs (lua_State *L, const luaL_Reg *l, int nup) { - luaL_checkversion(L); - luaL_checkstack(L, nup, "too many upvalues"); - for (; l->name != NULL; l++) { /* fill the table with given functions */ - int i; - for (i = 0; i < nup; i++) /* copy upvalues to the top */ - lua_pushvalue(L, -nup); - lua_pushcclosure(L, l->func, nup); /* closure with those upvalues */ - lua_setfield(L, -(nup + 2), l->name); - } - lua_pop(L, nup); /* remove upvalues */ -} - - -/* -** ensure that stack[idx][fname] has a table and push that table -** into the stack -*/ -LUALIB_API int luaL_getsubtable (lua_State *L, int idx, const char *fname) { - lua_getfield(L, idx, fname); - if (lua_istable(L, -1)) return 1; /* table already there */ - else { - lua_pop(L, 1); /* remove previous result */ - idx = lua_absindex(L, idx); - lua_newtable(L); - lua_pushvalue(L, -1); /* copy to be left at top */ - lua_setfield(L, idx, fname); /* assign new table to field */ - return 0; /* false, because did not find table there */ - } -} - - -/* -** stripped-down 'require'. Calls 'openf' to open a module, -** registers the result in 'package.loaded' table and, if 'glb' -** is true, also registers the result in the global table. -** Leaves resulting module on the top. -*/ -LUALIB_API void luaL_requiref (lua_State *L, const char *modname, - lua_CFunction openf, int glb) { - lua_pushcfunction(L, openf); - lua_pushstring(L, modname); /* argument to open function */ - lua_call(L, 1, 1); /* open module */ - luaL_getsubtable(L, LUA_REGISTRYINDEX, "_LOADED"); - lua_pushvalue(L, -2); /* make copy of module (call result) */ - lua_setfield(L, -2, modname); /* _LOADED[modname] = module */ - lua_pop(L, 1); /* remove _LOADED table */ - if (glb) { - lua_pushvalue(L, -1); /* copy of 'mod' */ - lua_setglobal(L, modname); /* _G[modname] = module */ - } -} - - -LUALIB_API const char *luaL_gsub (lua_State *L, const char *s, const char *p, - const char *r) { - const char *wild; - size_t l = strlen(p); - luaL_Buffer b; - luaL_buffinit(L, &b); - while ((wild = strstr(s, p)) != NULL) { - luaL_addlstring(&b, s, wild - s); /* push prefix */ - luaL_addstring(&b, r); /* push replacement in place of pattern */ - s = wild + l; /* continue after `p' */ - } - luaL_addstring(&b, s); /* push last suffix */ - luaL_pushresult(&b); - return lua_tostring(L, -1); -} - - -static void *l_alloc (void *ud, void *ptr, size_t osize, size_t nsize) { - (void)ud; (void)osize; /* not used */ - if (nsize == 0) { - free(ptr); - return NULL; - } - else - return realloc(ptr, nsize); -} - - -static int panic (lua_State *L) { - luai_writestringerror("PANIC: unprotected error in call to Lua API (%s)\n", - lua_tostring(L, -1)); - return 0; /* return to Lua to abort */ -} - - -LUALIB_API lua_State *luaL_newstate (void) { - lua_State *L = lua_newstate(l_alloc, NULL); - if (L) lua_atpanic(L, &panic); - return L; -} - - -LUALIB_API void luaL_checkversion_ (lua_State *L, lua_Number ver) { - const lua_Number *v = lua_version(L); - if (v != lua_version(NULL)) - luaL_error(L, "multiple Lua VMs detected"); - else if (*v != ver) - luaL_error(L, "version mismatch: app. needs %f, Lua core provides %f", - ver, *v); - /* check conversions number -> integer types */ - lua_pushnumber(L, -(lua_Number)0x1234); - if (lua_tointeger(L, -1) != -0x1234 || - lua_tounsigned(L, -1) != (lua_Unsigned)-0x1234) - luaL_error(L, "bad conversion number->int;" - " must recompile Lua with proper settings"); - lua_pop(L, 1); -} - diff --git a/lib/lua-5.2/src/lauxlib.h b/lib/lua-5.2/src/lauxlib.h deleted file mode 100644 index 0fb023b..0000000 --- a/lib/lua-5.2/src/lauxlib.h +++ /dev/null @@ -1,212 +0,0 @@ -/* -** $Id: lauxlib.h,v 1.120.1.1 2013/04/12 18:48:47 roberto Exp $ -** Auxiliary functions for building Lua libraries -** See Copyright Notice in lua.h -*/ - - -#ifndef lauxlib_h -#define lauxlib_h - - -#include -#include - -#include "lua.h" - - - -/* extra error code for `luaL_load' */ -#define LUA_ERRFILE (LUA_ERRERR+1) - - -typedef struct luaL_Reg { - const char *name; - lua_CFunction func; -} luaL_Reg; - - -LUALIB_API void (luaL_checkversion_) (lua_State *L, lua_Number ver); -#define luaL_checkversion(L) luaL_checkversion_(L, LUA_VERSION_NUM) - -LUALIB_API int (luaL_getmetafield) (lua_State *L, int obj, const char *e); -LUALIB_API int (luaL_callmeta) (lua_State *L, int obj, const char *e); -LUALIB_API const char *(luaL_tolstring) (lua_State *L, int idx, size_t *len); -LUALIB_API int (luaL_argerror) (lua_State *L, int numarg, const char *extramsg); -LUALIB_API const char *(luaL_checklstring) (lua_State *L, int numArg, - size_t *l); -LUALIB_API const char *(luaL_optlstring) (lua_State *L, int numArg, - const char *def, size_t *l); -LUALIB_API lua_Number (luaL_checknumber) (lua_State *L, int numArg); -LUALIB_API lua_Number (luaL_optnumber) (lua_State *L, int nArg, lua_Number def); - -LUALIB_API lua_Integer (luaL_checkinteger) (lua_State *L, int numArg); -LUALIB_API lua_Integer (luaL_optinteger) (lua_State *L, int nArg, - lua_Integer def); -LUALIB_API lua_Unsigned (luaL_checkunsigned) (lua_State *L, int numArg); -LUALIB_API lua_Unsigned (luaL_optunsigned) (lua_State *L, int numArg, - lua_Unsigned def); - -LUALIB_API void (luaL_checkstack) (lua_State *L, int sz, const char *msg); -LUALIB_API void (luaL_checktype) (lua_State *L, int narg, int t); -LUALIB_API void (luaL_checkany) (lua_State *L, int narg); - -LUALIB_API int (luaL_newmetatable) (lua_State *L, const char *tname); -LUALIB_API void (luaL_setmetatable) (lua_State *L, const char *tname); -LUALIB_API void *(luaL_testudata) (lua_State *L, int ud, const char *tname); -LUALIB_API void *(luaL_checkudata) (lua_State *L, int ud, const char *tname); - -LUALIB_API void (luaL_where) (lua_State *L, int lvl); -LUALIB_API int (luaL_error) (lua_State *L, const char *fmt, ...); - -LUALIB_API int (luaL_checkoption) (lua_State *L, int narg, const char *def, - const char *const lst[]); - -LUALIB_API int (luaL_fileresult) (lua_State *L, int stat, const char *fname); -LUALIB_API int (luaL_execresult) (lua_State *L, int stat); - -/* pre-defined references */ -#define LUA_NOREF (-2) -#define LUA_REFNIL (-1) - -LUALIB_API int (luaL_ref) (lua_State *L, int t); -LUALIB_API void (luaL_unref) (lua_State *L, int t, int ref); - -LUALIB_API int (luaL_loadfilex) (lua_State *L, const char *filename, - const char *mode); - -#define luaL_loadfile(L,f) luaL_loadfilex(L,f,NULL) - -LUALIB_API int (luaL_loadbufferx) (lua_State *L, const char *buff, size_t sz, - const char *name, const char *mode); -LUALIB_API int (luaL_loadstring) (lua_State *L, const char *s); - -LUALIB_API lua_State *(luaL_newstate) (void); - -LUALIB_API int (luaL_len) (lua_State *L, int idx); - -LUALIB_API const char *(luaL_gsub) (lua_State *L, const char *s, const char *p, - const char *r); - -LUALIB_API void (luaL_setfuncs) (lua_State *L, const luaL_Reg *l, int nup); - -LUALIB_API int (luaL_getsubtable) (lua_State *L, int idx, const char *fname); - -LUALIB_API void (luaL_traceback) (lua_State *L, lua_State *L1, - const char *msg, int level); - -LUALIB_API void (luaL_requiref) (lua_State *L, const char *modname, - lua_CFunction openf, int glb); - -/* -** =============================================================== -** some useful macros -** =============================================================== -*/ - - -#define luaL_newlibtable(L,l) \ - lua_createtable(L, 0, sizeof(l)/sizeof((l)[0]) - 1) - -#define luaL_newlib(L,l) (luaL_newlibtable(L,l), luaL_setfuncs(L,l,0)) - -#define luaL_argcheck(L, cond,numarg,extramsg) \ - ((void)((cond) || luaL_argerror(L, (numarg), (extramsg)))) -#define luaL_checkstring(L,n) (luaL_checklstring(L, (n), NULL)) -#define luaL_optstring(L,n,d) (luaL_optlstring(L, (n), (d), NULL)) -#define luaL_checkint(L,n) ((int)luaL_checkinteger(L, (n))) -#define luaL_optint(L,n,d) ((int)luaL_optinteger(L, (n), (d))) -#define luaL_checklong(L,n) ((long)luaL_checkinteger(L, (n))) -#define luaL_optlong(L,n,d) ((long)luaL_optinteger(L, (n), (d))) - -#define luaL_typename(L,i) lua_typename(L, lua_type(L,(i))) - -#define luaL_dofile(L, fn) \ - (luaL_loadfile(L, fn) || lua_pcall(L, 0, LUA_MULTRET, 0)) - -#define luaL_dostring(L, s) \ - (luaL_loadstring(L, s) || lua_pcall(L, 0, LUA_MULTRET, 0)) - -#define luaL_getmetatable(L,n) (lua_getfield(L, LUA_REGISTRYINDEX, (n))) - -#define luaL_opt(L,f,n,d) (lua_isnoneornil(L,(n)) ? (d) : f(L,(n))) - -#define luaL_loadbuffer(L,s,sz,n) luaL_loadbufferx(L,s,sz,n,NULL) - - -/* -** {====================================================== -** Generic Buffer manipulation -** ======================================================= -*/ - -typedef struct luaL_Buffer { - char *b; /* buffer address */ - size_t size; /* buffer size */ - size_t n; /* number of characters in buffer */ - lua_State *L; - char initb[LUAL_BUFFERSIZE]; /* initial buffer */ -} luaL_Buffer; - - -#define luaL_addchar(B,c) \ - ((void)((B)->n < (B)->size || luaL_prepbuffsize((B), 1)), \ - ((B)->b[(B)->n++] = (c))) - -#define luaL_addsize(B,s) ((B)->n += (s)) - -LUALIB_API void (luaL_buffinit) (lua_State *L, luaL_Buffer *B); -LUALIB_API char *(luaL_prepbuffsize) (luaL_Buffer *B, size_t sz); -LUALIB_API void (luaL_addlstring) (luaL_Buffer *B, const char *s, size_t l); -LUALIB_API void (luaL_addstring) (luaL_Buffer *B, const char *s); -LUALIB_API void (luaL_addvalue) (luaL_Buffer *B); -LUALIB_API void (luaL_pushresult) (luaL_Buffer *B); -LUALIB_API void (luaL_pushresultsize) (luaL_Buffer *B, size_t sz); -LUALIB_API char *(luaL_buffinitsize) (lua_State *L, luaL_Buffer *B, size_t sz); - -#define luaL_prepbuffer(B) luaL_prepbuffsize(B, LUAL_BUFFERSIZE) - -/* }====================================================== */ - - - -/* -** {====================================================== -** File handles for IO library -** ======================================================= -*/ - -/* -** A file handle is a userdata with metatable 'LUA_FILEHANDLE' and -** initial structure 'luaL_Stream' (it may contain other fields -** after that initial structure). -*/ - -#define LUA_FILEHANDLE "FILE*" - - -typedef struct luaL_Stream { - FILE *f; /* stream (NULL for incompletely created streams) */ - lua_CFunction closef; /* to close stream (NULL for closed streams) */ -} luaL_Stream; - -/* }====================================================== */ - - - -/* compatibility with old module system */ -#if defined(LUA_COMPAT_MODULE) - -LUALIB_API void (luaL_pushmodule) (lua_State *L, const char *modname, - int sizehint); -LUALIB_API void (luaL_openlib) (lua_State *L, const char *libname, - const luaL_Reg *l, int nup); - -#define luaL_register(L,n,l) (luaL_openlib(L,(n),(l),0)) - -#endif - - -#endif - - diff --git a/lib/lua-5.2/src/lbaselib.c b/lib/lua-5.2/src/lbaselib.c deleted file mode 100644 index 5255b3c..0000000 --- a/lib/lua-5.2/src/lbaselib.c +++ /dev/null @@ -1,458 +0,0 @@ -/* -** $Id: lbaselib.c,v 1.276.1.1 2013/04/12 18:48:47 roberto Exp $ -** Basic library -** See Copyright Notice in lua.h -*/ - - - -#include -#include -#include -#include - -#define lbaselib_c -#define LUA_LIB - -#include "lua.h" - -#include "lauxlib.h" -#include "lualib.h" - - -static int luaB_print (lua_State *L) { - int n = lua_gettop(L); /* number of arguments */ - int i; - lua_getglobal(L, "tostring"); - for (i=1; i<=n; i++) { - const char *s; - size_t l; - lua_pushvalue(L, -1); /* function to be called */ - lua_pushvalue(L, i); /* value to print */ - lua_call(L, 1, 1); - s = lua_tolstring(L, -1, &l); /* get result */ - if (s == NULL) - return luaL_error(L, - LUA_QL("tostring") " must return a string to " LUA_QL("print")); - if (i>1) luai_writestring("\t", 1); - luai_writestring(s, l); - lua_pop(L, 1); /* pop result */ - } - luai_writeline(); - return 0; -} - - -#define SPACECHARS " \f\n\r\t\v" - -static int luaB_tonumber (lua_State *L) { - if (lua_isnoneornil(L, 2)) { /* standard conversion */ - int isnum; - lua_Number n = lua_tonumberx(L, 1, &isnum); - if (isnum) { - lua_pushnumber(L, n); - return 1; - } /* else not a number; must be something */ - luaL_checkany(L, 1); - } - else { - size_t l; - const char *s = luaL_checklstring(L, 1, &l); - const char *e = s + l; /* end point for 's' */ - int base = luaL_checkint(L, 2); - int neg = 0; - luaL_argcheck(L, 2 <= base && base <= 36, 2, "base out of range"); - s += strspn(s, SPACECHARS); /* skip initial spaces */ - if (*s == '-') { s++; neg = 1; } /* handle signal */ - else if (*s == '+') s++; - if (isalnum((unsigned char)*s)) { - lua_Number n = 0; - do { - int digit = (isdigit((unsigned char)*s)) ? *s - '0' - : toupper((unsigned char)*s) - 'A' + 10; - if (digit >= base) break; /* invalid numeral; force a fail */ - n = n * (lua_Number)base + (lua_Number)digit; - s++; - } while (isalnum((unsigned char)*s)); - s += strspn(s, SPACECHARS); /* skip trailing spaces */ - if (s == e) { /* no invalid trailing characters? */ - lua_pushnumber(L, (neg) ? -n : n); - return 1; - } /* else not a number */ - } /* else not a number */ - } - lua_pushnil(L); /* not a number */ - return 1; -} - - -static int luaB_error (lua_State *L) { - int level = luaL_optint(L, 2, 1); - lua_settop(L, 1); - if (lua_isstring(L, 1) && level > 0) { /* add extra information? */ - luaL_where(L, level); - lua_pushvalue(L, 1); - lua_concat(L, 2); - } - return lua_error(L); -} - - -static int luaB_getmetatable (lua_State *L) { - luaL_checkany(L, 1); - if (!lua_getmetatable(L, 1)) { - lua_pushnil(L); - return 1; /* no metatable */ - } - luaL_getmetafield(L, 1, "__metatable"); - return 1; /* returns either __metatable field (if present) or metatable */ -} - - -static int luaB_setmetatable (lua_State *L) { - int t = lua_type(L, 2); - luaL_checktype(L, 1, LUA_TTABLE); - luaL_argcheck(L, t == LUA_TNIL || t == LUA_TTABLE, 2, - "nil or table expected"); - if (luaL_getmetafield(L, 1, "__metatable")) - return luaL_error(L, "cannot change a protected metatable"); - lua_settop(L, 2); - lua_setmetatable(L, 1); - return 1; -} - - -static int luaB_rawequal (lua_State *L) { - luaL_checkany(L, 1); - luaL_checkany(L, 2); - lua_pushboolean(L, lua_rawequal(L, 1, 2)); - return 1; -} - - -static int luaB_rawlen (lua_State *L) { - int t = lua_type(L, 1); - luaL_argcheck(L, t == LUA_TTABLE || t == LUA_TSTRING, 1, - "table or string expected"); - lua_pushinteger(L, lua_rawlen(L, 1)); - return 1; -} - - -static int luaB_rawget (lua_State *L) { - luaL_checktype(L, 1, LUA_TTABLE); - luaL_checkany(L, 2); - lua_settop(L, 2); - lua_rawget(L, 1); - return 1; -} - -static int luaB_rawset (lua_State *L) { - luaL_checktype(L, 1, LUA_TTABLE); - luaL_checkany(L, 2); - luaL_checkany(L, 3); - lua_settop(L, 3); - lua_rawset(L, 1); - return 1; -} - - -static int luaB_collectgarbage (lua_State *L) { - static const char *const opts[] = {"stop", "restart", "collect", - "count", "step", "setpause", "setstepmul", - "setmajorinc", "isrunning", "generational", "incremental", NULL}; - static const int optsnum[] = {LUA_GCSTOP, LUA_GCRESTART, LUA_GCCOLLECT, - LUA_GCCOUNT, LUA_GCSTEP, LUA_GCSETPAUSE, LUA_GCSETSTEPMUL, - LUA_GCSETMAJORINC, LUA_GCISRUNNING, LUA_GCGEN, LUA_GCINC}; - int o = optsnum[luaL_checkoption(L, 1, "collect", opts)]; - int ex = luaL_optint(L, 2, 0); - int res = lua_gc(L, o, ex); - switch (o) { - case LUA_GCCOUNT: { - int b = lua_gc(L, LUA_GCCOUNTB, 0); - lua_pushnumber(L, res + ((lua_Number)b/1024)); - lua_pushinteger(L, b); - return 2; - } - case LUA_GCSTEP: case LUA_GCISRUNNING: { - lua_pushboolean(L, res); - return 1; - } - default: { - lua_pushinteger(L, res); - return 1; - } - } -} - - -static int luaB_type (lua_State *L) { - luaL_checkany(L, 1); - lua_pushstring(L, luaL_typename(L, 1)); - return 1; -} - - -static int pairsmeta (lua_State *L, const char *method, int iszero, - lua_CFunction iter) { - if (!luaL_getmetafield(L, 1, method)) { /* no metamethod? */ - luaL_checktype(L, 1, LUA_TTABLE); /* argument must be a table */ - lua_pushcfunction(L, iter); /* will return generator, */ - lua_pushvalue(L, 1); /* state, */ - if (iszero) lua_pushinteger(L, 0); /* and initial value */ - else lua_pushnil(L); - } - else { - lua_pushvalue(L, 1); /* argument 'self' to metamethod */ - lua_call(L, 1, 3); /* get 3 values from metamethod */ - } - return 3; -} - - -static int luaB_next (lua_State *L) { - luaL_checktype(L, 1, LUA_TTABLE); - lua_settop(L, 2); /* create a 2nd argument if there isn't one */ - if (lua_next(L, 1)) - return 2; - else { - lua_pushnil(L); - return 1; - } -} - - -static int luaB_pairs (lua_State *L) { - return pairsmeta(L, "__pairs", 0, luaB_next); -} - - -static int ipairsaux (lua_State *L) { - int i = luaL_checkint(L, 2); - luaL_checktype(L, 1, LUA_TTABLE); - i++; /* next value */ - lua_pushinteger(L, i); - lua_rawgeti(L, 1, i); - return (lua_isnil(L, -1)) ? 1 : 2; -} - - -static int luaB_ipairs (lua_State *L) { - return pairsmeta(L, "__ipairs", 1, ipairsaux); -} - - -static int load_aux (lua_State *L, int status, int envidx) { - if (status == LUA_OK) { - if (envidx != 0) { /* 'env' parameter? */ - lua_pushvalue(L, envidx); /* environment for loaded function */ - if (!lua_setupvalue(L, -2, 1)) /* set it as 1st upvalue */ - lua_pop(L, 1); /* remove 'env' if not used by previous call */ - } - return 1; - } - else { /* error (message is on top of the stack) */ - lua_pushnil(L); - lua_insert(L, -2); /* put before error message */ - return 2; /* return nil plus error message */ - } -} - - -static int luaB_loadfile (lua_State *L) { - const char *fname = luaL_optstring(L, 1, NULL); - const char *mode = luaL_optstring(L, 2, NULL); - int env = (!lua_isnone(L, 3) ? 3 : 0); /* 'env' index or 0 if no 'env' */ - int status = luaL_loadfilex(L, fname, mode); - return load_aux(L, status, env); -} - - -/* -** {====================================================== -** Generic Read function -** ======================================================= -*/ - - -/* -** reserved slot, above all arguments, to hold a copy of the returned -** string to avoid it being collected while parsed. 'load' has four -** optional arguments (chunk, source name, mode, and environment). -*/ -#define RESERVEDSLOT 5 - - -/* -** Reader for generic `load' function: `lua_load' uses the -** stack for internal stuff, so the reader cannot change the -** stack top. Instead, it keeps its resulting string in a -** reserved slot inside the stack. -*/ -static const char *generic_reader (lua_State *L, void *ud, size_t *size) { - (void)(ud); /* not used */ - luaL_checkstack(L, 2, "too many nested functions"); - lua_pushvalue(L, 1); /* get function */ - lua_call(L, 0, 1); /* call it */ - if (lua_isnil(L, -1)) { - lua_pop(L, 1); /* pop result */ - *size = 0; - return NULL; - } - else if (!lua_isstring(L, -1)) - luaL_error(L, "reader function must return a string"); - lua_replace(L, RESERVEDSLOT); /* save string in reserved slot */ - return lua_tolstring(L, RESERVEDSLOT, size); -} - - -static int luaB_load (lua_State *L) { - int status; - size_t l; - const char *s = lua_tolstring(L, 1, &l); - const char *mode = luaL_optstring(L, 3, "bt"); - int env = (!lua_isnone(L, 4) ? 4 : 0); /* 'env' index or 0 if no 'env' */ - if (s != NULL) { /* loading a string? */ - const char *chunkname = luaL_optstring(L, 2, s); - status = luaL_loadbufferx(L, s, l, chunkname, mode); - } - else { /* loading from a reader function */ - const char *chunkname = luaL_optstring(L, 2, "=(load)"); - luaL_checktype(L, 1, LUA_TFUNCTION); - lua_settop(L, RESERVEDSLOT); /* create reserved slot */ - status = lua_load(L, generic_reader, NULL, chunkname, mode); - } - return load_aux(L, status, env); -} - -/* }====================================================== */ - - -static int dofilecont (lua_State *L) { - return lua_gettop(L) - 1; -} - - -static int luaB_dofile (lua_State *L) { - const char *fname = luaL_optstring(L, 1, NULL); - lua_settop(L, 1); - if (luaL_loadfile(L, fname) != LUA_OK) - return lua_error(L); - lua_callk(L, 0, LUA_MULTRET, 0, dofilecont); - return dofilecont(L); -} - - -static int luaB_assert (lua_State *L) { - if (!lua_toboolean(L, 1)) - return luaL_error(L, "%s", luaL_optstring(L, 2, "assertion failed!")); - return lua_gettop(L); -} - - -static int luaB_select (lua_State *L) { - int n = lua_gettop(L); - if (lua_type(L, 1) == LUA_TSTRING && *lua_tostring(L, 1) == '#') { - lua_pushinteger(L, n-1); - return 1; - } - else { - int i = luaL_checkint(L, 1); - if (i < 0) i = n + i; - else if (i > n) i = n; - luaL_argcheck(L, 1 <= i, 1, "index out of range"); - return n - i; - } -} - - -static int finishpcall (lua_State *L, int status) { - if (!lua_checkstack(L, 1)) { /* no space for extra boolean? */ - lua_settop(L, 0); /* create space for return values */ - lua_pushboolean(L, 0); - lua_pushstring(L, "stack overflow"); - return 2; /* return false, msg */ - } - lua_pushboolean(L, status); /* first result (status) */ - lua_replace(L, 1); /* put first result in first slot */ - return lua_gettop(L); -} - - -static int pcallcont (lua_State *L) { - int status = lua_getctx(L, NULL); - return finishpcall(L, (status == LUA_YIELD)); -} - - -static int luaB_pcall (lua_State *L) { - int status; - luaL_checkany(L, 1); - lua_pushnil(L); - lua_insert(L, 1); /* create space for status result */ - status = lua_pcallk(L, lua_gettop(L) - 2, LUA_MULTRET, 0, 0, pcallcont); - return finishpcall(L, (status == LUA_OK)); -} - - -static int luaB_xpcall (lua_State *L) { - int status; - int n = lua_gettop(L); - luaL_argcheck(L, n >= 2, 2, "value expected"); - lua_pushvalue(L, 1); /* exchange function... */ - lua_copy(L, 2, 1); /* ...and error handler */ - lua_replace(L, 2); - status = lua_pcallk(L, n - 2, LUA_MULTRET, 1, 0, pcallcont); - return finishpcall(L, (status == LUA_OK)); -} - - -static int luaB_tostring (lua_State *L) { - luaL_checkany(L, 1); - luaL_tolstring(L, 1, NULL); - return 1; -} - - -static const luaL_Reg base_funcs[] = { - {"assert", luaB_assert}, - {"collectgarbage", luaB_collectgarbage}, - {"dofile", luaB_dofile}, - {"error", luaB_error}, - {"getmetatable", luaB_getmetatable}, - {"ipairs", luaB_ipairs}, - {"loadfile", luaB_loadfile}, - {"load", luaB_load}, -#if defined(LUA_COMPAT_LOADSTRING) - {"loadstring", luaB_load}, -#endif - {"next", luaB_next}, - {"pairs", luaB_pairs}, - {"pcall", luaB_pcall}, - {"print", luaB_print}, - {"rawequal", luaB_rawequal}, - {"rawlen", luaB_rawlen}, - {"rawget", luaB_rawget}, - {"rawset", luaB_rawset}, - {"select", luaB_select}, - {"setmetatable", luaB_setmetatable}, - {"tonumber", luaB_tonumber}, - {"tostring", luaB_tostring}, - {"type", luaB_type}, - {"xpcall", luaB_xpcall}, - {NULL, NULL} -}; - - -LUAMOD_API int luaopen_base (lua_State *L) { - /* set global _G */ - lua_pushglobaltable(L); - lua_pushglobaltable(L); - lua_setfield(L, -2, "_G"); - /* open lib into global table */ - luaL_setfuncs(L, base_funcs, 0); - lua_pushliteral(L, LUA_VERSION); - lua_setfield(L, -2, "_VERSION"); /* set global _VERSION */ - return 1; -} - diff --git a/lib/lua-5.2/src/lbitlib.c b/lib/lua-5.2/src/lbitlib.c deleted file mode 100644 index 31c7b66..0000000 --- a/lib/lua-5.2/src/lbitlib.c +++ /dev/null @@ -1,212 +0,0 @@ -/* -** $Id: lbitlib.c,v 1.18.1.2 2013/07/09 18:01:41 roberto Exp $ -** Standard library for bitwise operations -** See Copyright Notice in lua.h -*/ - -#define lbitlib_c -#define LUA_LIB - -#include "lua.h" - -#include "lauxlib.h" -#include "lualib.h" - - -/* number of bits to consider in a number */ -#if !defined(LUA_NBITS) -#define LUA_NBITS 32 -#endif - - -#define ALLONES (~(((~(lua_Unsigned)0) << (LUA_NBITS - 1)) << 1)) - -/* macro to trim extra bits */ -#define trim(x) ((x) & ALLONES) - - -/* builds a number with 'n' ones (1 <= n <= LUA_NBITS) */ -#define mask(n) (~((ALLONES << 1) << ((n) - 1))) - - -typedef lua_Unsigned b_uint; - - - -static b_uint andaux (lua_State *L) { - int i, n = lua_gettop(L); - b_uint r = ~(b_uint)0; - for (i = 1; i <= n; i++) - r &= luaL_checkunsigned(L, i); - return trim(r); -} - - -static int b_and (lua_State *L) { - b_uint r = andaux(L); - lua_pushunsigned(L, r); - return 1; -} - - -static int b_test (lua_State *L) { - b_uint r = andaux(L); - lua_pushboolean(L, r != 0); - return 1; -} - - -static int b_or (lua_State *L) { - int i, n = lua_gettop(L); - b_uint r = 0; - for (i = 1; i <= n; i++) - r |= luaL_checkunsigned(L, i); - lua_pushunsigned(L, trim(r)); - return 1; -} - - -static int b_xor (lua_State *L) { - int i, n = lua_gettop(L); - b_uint r = 0; - for (i = 1; i <= n; i++) - r ^= luaL_checkunsigned(L, i); - lua_pushunsigned(L, trim(r)); - return 1; -} - - -static int b_not (lua_State *L) { - b_uint r = ~luaL_checkunsigned(L, 1); - lua_pushunsigned(L, trim(r)); - return 1; -} - - -static int b_shift (lua_State *L, b_uint r, int i) { - if (i < 0) { /* shift right? */ - i = -i; - r = trim(r); - if (i >= LUA_NBITS) r = 0; - else r >>= i; - } - else { /* shift left */ - if (i >= LUA_NBITS) r = 0; - else r <<= i; - r = trim(r); - } - lua_pushunsigned(L, r); - return 1; -} - - -static int b_lshift (lua_State *L) { - return b_shift(L, luaL_checkunsigned(L, 1), luaL_checkint(L, 2)); -} - - -static int b_rshift (lua_State *L) { - return b_shift(L, luaL_checkunsigned(L, 1), -luaL_checkint(L, 2)); -} - - -static int b_arshift (lua_State *L) { - b_uint r = luaL_checkunsigned(L, 1); - int i = luaL_checkint(L, 2); - if (i < 0 || !(r & ((b_uint)1 << (LUA_NBITS - 1)))) - return b_shift(L, r, -i); - else { /* arithmetic shift for 'negative' number */ - if (i >= LUA_NBITS) r = ALLONES; - else - r = trim((r >> i) | ~(~(b_uint)0 >> i)); /* add signal bit */ - lua_pushunsigned(L, r); - return 1; - } -} - - -static int b_rot (lua_State *L, int i) { - b_uint r = luaL_checkunsigned(L, 1); - i &= (LUA_NBITS - 1); /* i = i % NBITS */ - r = trim(r); - if (i != 0) /* avoid undefined shift of LUA_NBITS when i == 0 */ - r = (r << i) | (r >> (LUA_NBITS - i)); - lua_pushunsigned(L, trim(r)); - return 1; -} - - -static int b_lrot (lua_State *L) { - return b_rot(L, luaL_checkint(L, 2)); -} - - -static int b_rrot (lua_State *L) { - return b_rot(L, -luaL_checkint(L, 2)); -} - - -/* -** get field and width arguments for field-manipulation functions, -** checking whether they are valid. -** ('luaL_error' called without 'return' to avoid later warnings about -** 'width' being used uninitialized.) -*/ -static int fieldargs (lua_State *L, int farg, int *width) { - int f = luaL_checkint(L, farg); - int w = luaL_optint(L, farg + 1, 1); - luaL_argcheck(L, 0 <= f, farg, "field cannot be negative"); - luaL_argcheck(L, 0 < w, farg + 1, "width must be positive"); - if (f + w > LUA_NBITS) - luaL_error(L, "trying to access non-existent bits"); - *width = w; - return f; -} - - -static int b_extract (lua_State *L) { - int w; - b_uint r = luaL_checkunsigned(L, 1); - int f = fieldargs(L, 2, &w); - r = (r >> f) & mask(w); - lua_pushunsigned(L, r); - return 1; -} - - -static int b_replace (lua_State *L) { - int w; - b_uint r = luaL_checkunsigned(L, 1); - b_uint v = luaL_checkunsigned(L, 2); - int f = fieldargs(L, 3, &w); - int m = mask(w); - v &= m; /* erase bits outside given width */ - r = (r & ~(m << f)) | (v << f); - lua_pushunsigned(L, r); - return 1; -} - - -static const luaL_Reg bitlib[] = { - {"arshift", b_arshift}, - {"band", b_and}, - {"bnot", b_not}, - {"bor", b_or}, - {"bxor", b_xor}, - {"btest", b_test}, - {"extract", b_extract}, - {"lrotate", b_lrot}, - {"lshift", b_lshift}, - {"replace", b_replace}, - {"rrotate", b_rrot}, - {"rshift", b_rshift}, - {NULL, NULL} -}; - - - -LUAMOD_API int luaopen_bit32 (lua_State *L) { - luaL_newlib(L, bitlib); - return 1; -} - diff --git a/lib/lua-5.2/src/lcode.c b/lib/lua-5.2/src/lcode.c deleted file mode 100644 index 820b95c..0000000 --- a/lib/lua-5.2/src/lcode.c +++ /dev/null @@ -1,881 +0,0 @@ -/* -** $Id: lcode.c,v 2.62.1.1 2013/04/12 18:48:47 roberto Exp $ -** Code generator for Lua -** See Copyright Notice in lua.h -*/ - - -#include - -#define lcode_c -#define LUA_CORE - -#include "lua.h" - -#include "lcode.h" -#include "ldebug.h" -#include "ldo.h" -#include "lgc.h" -#include "llex.h" -#include "lmem.h" -#include "lobject.h" -#include "lopcodes.h" -#include "lparser.h" -#include "lstring.h" -#include "ltable.h" -#include "lvm.h" - - -#define hasjumps(e) ((e)->t != (e)->f) - - -static int isnumeral(expdesc *e) { - return (e->k == VKNUM && e->t == NO_JUMP && e->f == NO_JUMP); -} - - -void luaK_nil (FuncState *fs, int from, int n) { - Instruction *previous; - int l = from + n - 1; /* last register to set nil */ - if (fs->pc > fs->lasttarget) { /* no jumps to current position? */ - previous = &fs->f->code[fs->pc-1]; - if (GET_OPCODE(*previous) == OP_LOADNIL) { - int pfrom = GETARG_A(*previous); - int pl = pfrom + GETARG_B(*previous); - if ((pfrom <= from && from <= pl + 1) || - (from <= pfrom && pfrom <= l + 1)) { /* can connect both? */ - if (pfrom < from) from = pfrom; /* from = min(from, pfrom) */ - if (pl > l) l = pl; /* l = max(l, pl) */ - SETARG_A(*previous, from); - SETARG_B(*previous, l - from); - return; - } - } /* else go through */ - } - luaK_codeABC(fs, OP_LOADNIL, from, n - 1, 0); /* else no optimization */ -} - - -int luaK_jump (FuncState *fs) { - int jpc = fs->jpc; /* save list of jumps to here */ - int j; - fs->jpc = NO_JUMP; - j = luaK_codeAsBx(fs, OP_JMP, 0, NO_JUMP); - luaK_concat(fs, &j, jpc); /* keep them on hold */ - return j; -} - - -void luaK_ret (FuncState *fs, int first, int nret) { - luaK_codeABC(fs, OP_RETURN, first, nret+1, 0); -} - - -static int condjump (FuncState *fs, OpCode op, int A, int B, int C) { - luaK_codeABC(fs, op, A, B, C); - return luaK_jump(fs); -} - - -static void fixjump (FuncState *fs, int pc, int dest) { - Instruction *jmp = &fs->f->code[pc]; - int offset = dest-(pc+1); - lua_assert(dest != NO_JUMP); - if (abs(offset) > MAXARG_sBx) - luaX_syntaxerror(fs->ls, "control structure too long"); - SETARG_sBx(*jmp, offset); -} - - -/* -** returns current `pc' and marks it as a jump target (to avoid wrong -** optimizations with consecutive instructions not in the same basic block). -*/ -int luaK_getlabel (FuncState *fs) { - fs->lasttarget = fs->pc; - return fs->pc; -} - - -static int getjump (FuncState *fs, int pc) { - int offset = GETARG_sBx(fs->f->code[pc]); - if (offset == NO_JUMP) /* point to itself represents end of list */ - return NO_JUMP; /* end of list */ - else - return (pc+1)+offset; /* turn offset into absolute position */ -} - - -static Instruction *getjumpcontrol (FuncState *fs, int pc) { - Instruction *pi = &fs->f->code[pc]; - if (pc >= 1 && testTMode(GET_OPCODE(*(pi-1)))) - return pi-1; - else - return pi; -} - - -/* -** check whether list has any jump that do not produce a value -** (or produce an inverted value) -*/ -static int need_value (FuncState *fs, int list) { - for (; list != NO_JUMP; list = getjump(fs, list)) { - Instruction i = *getjumpcontrol(fs, list); - if (GET_OPCODE(i) != OP_TESTSET) return 1; - } - return 0; /* not found */ -} - - -static int patchtestreg (FuncState *fs, int node, int reg) { - Instruction *i = getjumpcontrol(fs, node); - if (GET_OPCODE(*i) != OP_TESTSET) - return 0; /* cannot patch other instructions */ - if (reg != NO_REG && reg != GETARG_B(*i)) - SETARG_A(*i, reg); - else /* no register to put value or register already has the value */ - *i = CREATE_ABC(OP_TEST, GETARG_B(*i), 0, GETARG_C(*i)); - - return 1; -} - - -static void removevalues (FuncState *fs, int list) { - for (; list != NO_JUMP; list = getjump(fs, list)) - patchtestreg(fs, list, NO_REG); -} - - -static void patchlistaux (FuncState *fs, int list, int vtarget, int reg, - int dtarget) { - while (list != NO_JUMP) { - int next = getjump(fs, list); - if (patchtestreg(fs, list, reg)) - fixjump(fs, list, vtarget); - else - fixjump(fs, list, dtarget); /* jump to default target */ - list = next; - } -} - - -static void dischargejpc (FuncState *fs) { - patchlistaux(fs, fs->jpc, fs->pc, NO_REG, fs->pc); - fs->jpc = NO_JUMP; -} - - -void luaK_patchlist (FuncState *fs, int list, int target) { - if (target == fs->pc) - luaK_patchtohere(fs, list); - else { - lua_assert(target < fs->pc); - patchlistaux(fs, list, target, NO_REG, target); - } -} - - -LUAI_FUNC void luaK_patchclose (FuncState *fs, int list, int level) { - level++; /* argument is +1 to reserve 0 as non-op */ - while (list != NO_JUMP) { - int next = getjump(fs, list); - lua_assert(GET_OPCODE(fs->f->code[list]) == OP_JMP && - (GETARG_A(fs->f->code[list]) == 0 || - GETARG_A(fs->f->code[list]) >= level)); - SETARG_A(fs->f->code[list], level); - list = next; - } -} - - -void luaK_patchtohere (FuncState *fs, int list) { - luaK_getlabel(fs); - luaK_concat(fs, &fs->jpc, list); -} - - -void luaK_concat (FuncState *fs, int *l1, int l2) { - if (l2 == NO_JUMP) return; - else if (*l1 == NO_JUMP) - *l1 = l2; - else { - int list = *l1; - int next; - while ((next = getjump(fs, list)) != NO_JUMP) /* find last element */ - list = next; - fixjump(fs, list, l2); - } -} - - -static int luaK_code (FuncState *fs, Instruction i) { - Proto *f = fs->f; - dischargejpc(fs); /* `pc' will change */ - /* put new instruction in code array */ - luaM_growvector(fs->ls->L, f->code, fs->pc, f->sizecode, Instruction, - MAX_INT, "opcodes"); - f->code[fs->pc] = i; - /* save corresponding line information */ - luaM_growvector(fs->ls->L, f->lineinfo, fs->pc, f->sizelineinfo, int, - MAX_INT, "opcodes"); - f->lineinfo[fs->pc] = fs->ls->lastline; - return fs->pc++; -} - - -int luaK_codeABC (FuncState *fs, OpCode o, int a, int b, int c) { - lua_assert(getOpMode(o) == iABC); - lua_assert(getBMode(o) != OpArgN || b == 0); - lua_assert(getCMode(o) != OpArgN || c == 0); - lua_assert(a <= MAXARG_A && b <= MAXARG_B && c <= MAXARG_C); - return luaK_code(fs, CREATE_ABC(o, a, b, c)); -} - - -int luaK_codeABx (FuncState *fs, OpCode o, int a, unsigned int bc) { - lua_assert(getOpMode(o) == iABx || getOpMode(o) == iAsBx); - lua_assert(getCMode(o) == OpArgN); - lua_assert(a <= MAXARG_A && bc <= MAXARG_Bx); - return luaK_code(fs, CREATE_ABx(o, a, bc)); -} - - -static int codeextraarg (FuncState *fs, int a) { - lua_assert(a <= MAXARG_Ax); - return luaK_code(fs, CREATE_Ax(OP_EXTRAARG, a)); -} - - -int luaK_codek (FuncState *fs, int reg, int k) { - if (k <= MAXARG_Bx) - return luaK_codeABx(fs, OP_LOADK, reg, k); - else { - int p = luaK_codeABx(fs, OP_LOADKX, reg, 0); - codeextraarg(fs, k); - return p; - } -} - - -void luaK_checkstack (FuncState *fs, int n) { - int newstack = fs->freereg + n; - if (newstack > fs->f->maxstacksize) { - if (newstack >= MAXSTACK) - luaX_syntaxerror(fs->ls, "function or expression too complex"); - fs->f->maxstacksize = cast_byte(newstack); - } -} - - -void luaK_reserveregs (FuncState *fs, int n) { - luaK_checkstack(fs, n); - fs->freereg += n; -} - - -static void freereg (FuncState *fs, int reg) { - if (!ISK(reg) && reg >= fs->nactvar) { - fs->freereg--; - lua_assert(reg == fs->freereg); - } -} - - -static void freeexp (FuncState *fs, expdesc *e) { - if (e->k == VNONRELOC) - freereg(fs, e->u.info); -} - - -static int addk (FuncState *fs, TValue *key, TValue *v) { - lua_State *L = fs->ls->L; - TValue *idx = luaH_set(L, fs->h, key); - Proto *f = fs->f; - int k, oldsize; - if (ttisnumber(idx)) { - lua_Number n = nvalue(idx); - lua_number2int(k, n); - if (luaV_rawequalobj(&f->k[k], v)) - return k; - /* else may be a collision (e.g., between 0.0 and "\0\0\0\0\0\0\0\0"); - go through and create a new entry for this value */ - } - /* constant not found; create a new entry */ - oldsize = f->sizek; - k = fs->nk; - /* numerical value does not need GC barrier; - table has no metatable, so it does not need to invalidate cache */ - setnvalue(idx, cast_num(k)); - luaM_growvector(L, f->k, k, f->sizek, TValue, MAXARG_Ax, "constants"); - while (oldsize < f->sizek) setnilvalue(&f->k[oldsize++]); - setobj(L, &f->k[k], v); - fs->nk++; - luaC_barrier(L, f, v); - return k; -} - - -int luaK_stringK (FuncState *fs, TString *s) { - TValue o; - setsvalue(fs->ls->L, &o, s); - return addk(fs, &o, &o); -} - - -int luaK_numberK (FuncState *fs, lua_Number r) { - int n; - lua_State *L = fs->ls->L; - TValue o; - setnvalue(&o, r); - if (r == 0 || luai_numisnan(NULL, r)) { /* handle -0 and NaN */ - /* use raw representation as key to avoid numeric problems */ - setsvalue(L, L->top++, luaS_newlstr(L, (char *)&r, sizeof(r))); - n = addk(fs, L->top - 1, &o); - L->top--; - } - else - n = addk(fs, &o, &o); /* regular case */ - return n; -} - - -static int boolK (FuncState *fs, int b) { - TValue o; - setbvalue(&o, b); - return addk(fs, &o, &o); -} - - -static int nilK (FuncState *fs) { - TValue k, v; - setnilvalue(&v); - /* cannot use nil as key; instead use table itself to represent nil */ - sethvalue(fs->ls->L, &k, fs->h); - return addk(fs, &k, &v); -} - - -void luaK_setreturns (FuncState *fs, expdesc *e, int nresults) { - if (e->k == VCALL) { /* expression is an open function call? */ - SETARG_C(getcode(fs, e), nresults+1); - } - else if (e->k == VVARARG) { - SETARG_B(getcode(fs, e), nresults+1); - SETARG_A(getcode(fs, e), fs->freereg); - luaK_reserveregs(fs, 1); - } -} - - -void luaK_setoneret (FuncState *fs, expdesc *e) { - if (e->k == VCALL) { /* expression is an open function call? */ - e->k = VNONRELOC; - e->u.info = GETARG_A(getcode(fs, e)); - } - else if (e->k == VVARARG) { - SETARG_B(getcode(fs, e), 2); - e->k = VRELOCABLE; /* can relocate its simple result */ - } -} - - -void luaK_dischargevars (FuncState *fs, expdesc *e) { - switch (e->k) { - case VLOCAL: { - e->k = VNONRELOC; - break; - } - case VUPVAL: { - e->u.info = luaK_codeABC(fs, OP_GETUPVAL, 0, e->u.info, 0); - e->k = VRELOCABLE; - break; - } - case VINDEXED: { - OpCode op = OP_GETTABUP; /* assume 't' is in an upvalue */ - freereg(fs, e->u.ind.idx); - if (e->u.ind.vt == VLOCAL) { /* 't' is in a register? */ - freereg(fs, e->u.ind.t); - op = OP_GETTABLE; - } - e->u.info = luaK_codeABC(fs, op, 0, e->u.ind.t, e->u.ind.idx); - e->k = VRELOCABLE; - break; - } - case VVARARG: - case VCALL: { - luaK_setoneret(fs, e); - break; - } - default: break; /* there is one value available (somewhere) */ - } -} - - -static int code_label (FuncState *fs, int A, int b, int jump) { - luaK_getlabel(fs); /* those instructions may be jump targets */ - return luaK_codeABC(fs, OP_LOADBOOL, A, b, jump); -} - - -static void discharge2reg (FuncState *fs, expdesc *e, int reg) { - luaK_dischargevars(fs, e); - switch (e->k) { - case VNIL: { - luaK_nil(fs, reg, 1); - break; - } - case VFALSE: case VTRUE: { - luaK_codeABC(fs, OP_LOADBOOL, reg, e->k == VTRUE, 0); - break; - } - case VK: { - luaK_codek(fs, reg, e->u.info); - break; - } - case VKNUM: { - luaK_codek(fs, reg, luaK_numberK(fs, e->u.nval)); - break; - } - case VRELOCABLE: { - Instruction *pc = &getcode(fs, e); - SETARG_A(*pc, reg); - break; - } - case VNONRELOC: { - if (reg != e->u.info) - luaK_codeABC(fs, OP_MOVE, reg, e->u.info, 0); - break; - } - default: { - lua_assert(e->k == VVOID || e->k == VJMP); - return; /* nothing to do... */ - } - } - e->u.info = reg; - e->k = VNONRELOC; -} - - -static void discharge2anyreg (FuncState *fs, expdesc *e) { - if (e->k != VNONRELOC) { - luaK_reserveregs(fs, 1); - discharge2reg(fs, e, fs->freereg-1); - } -} - - -static void exp2reg (FuncState *fs, expdesc *e, int reg) { - discharge2reg(fs, e, reg); - if (e->k == VJMP) - luaK_concat(fs, &e->t, e->u.info); /* put this jump in `t' list */ - if (hasjumps(e)) { - int final; /* position after whole expression */ - int p_f = NO_JUMP; /* position of an eventual LOAD false */ - int p_t = NO_JUMP; /* position of an eventual LOAD true */ - if (need_value(fs, e->t) || need_value(fs, e->f)) { - int fj = (e->k == VJMP) ? NO_JUMP : luaK_jump(fs); - p_f = code_label(fs, reg, 0, 1); - p_t = code_label(fs, reg, 1, 0); - luaK_patchtohere(fs, fj); - } - final = luaK_getlabel(fs); - patchlistaux(fs, e->f, final, reg, p_f); - patchlistaux(fs, e->t, final, reg, p_t); - } - e->f = e->t = NO_JUMP; - e->u.info = reg; - e->k = VNONRELOC; -} - - -void luaK_exp2nextreg (FuncState *fs, expdesc *e) { - luaK_dischargevars(fs, e); - freeexp(fs, e); - luaK_reserveregs(fs, 1); - exp2reg(fs, e, fs->freereg - 1); -} - - -int luaK_exp2anyreg (FuncState *fs, expdesc *e) { - luaK_dischargevars(fs, e); - if (e->k == VNONRELOC) { - if (!hasjumps(e)) return e->u.info; /* exp is already in a register */ - if (e->u.info >= fs->nactvar) { /* reg. is not a local? */ - exp2reg(fs, e, e->u.info); /* put value on it */ - return e->u.info; - } - } - luaK_exp2nextreg(fs, e); /* default */ - return e->u.info; -} - - -void luaK_exp2anyregup (FuncState *fs, expdesc *e) { - if (e->k != VUPVAL || hasjumps(e)) - luaK_exp2anyreg(fs, e); -} - - -void luaK_exp2val (FuncState *fs, expdesc *e) { - if (hasjumps(e)) - luaK_exp2anyreg(fs, e); - else - luaK_dischargevars(fs, e); -} - - -int luaK_exp2RK (FuncState *fs, expdesc *e) { - luaK_exp2val(fs, e); - switch (e->k) { - case VTRUE: - case VFALSE: - case VNIL: { - if (fs->nk <= MAXINDEXRK) { /* constant fits in RK operand? */ - e->u.info = (e->k == VNIL) ? nilK(fs) : boolK(fs, (e->k == VTRUE)); - e->k = VK; - return RKASK(e->u.info); - } - else break; - } - case VKNUM: { - e->u.info = luaK_numberK(fs, e->u.nval); - e->k = VK; - /* go through */ - } - case VK: { - if (e->u.info <= MAXINDEXRK) /* constant fits in argC? */ - return RKASK(e->u.info); - else break; - } - default: break; - } - /* not a constant in the right range: put it in a register */ - return luaK_exp2anyreg(fs, e); -} - - -void luaK_storevar (FuncState *fs, expdesc *var, expdesc *ex) { - switch (var->k) { - case VLOCAL: { - freeexp(fs, ex); - exp2reg(fs, ex, var->u.info); - return; - } - case VUPVAL: { - int e = luaK_exp2anyreg(fs, ex); - luaK_codeABC(fs, OP_SETUPVAL, e, var->u.info, 0); - break; - } - case VINDEXED: { - OpCode op = (var->u.ind.vt == VLOCAL) ? OP_SETTABLE : OP_SETTABUP; - int e = luaK_exp2RK(fs, ex); - luaK_codeABC(fs, op, var->u.ind.t, var->u.ind.idx, e); - break; - } - default: { - lua_assert(0); /* invalid var kind to store */ - break; - } - } - freeexp(fs, ex); -} - - -void luaK_self (FuncState *fs, expdesc *e, expdesc *key) { - int ereg; - luaK_exp2anyreg(fs, e); - ereg = e->u.info; /* register where 'e' was placed */ - freeexp(fs, e); - e->u.info = fs->freereg; /* base register for op_self */ - e->k = VNONRELOC; - luaK_reserveregs(fs, 2); /* function and 'self' produced by op_self */ - luaK_codeABC(fs, OP_SELF, e->u.info, ereg, luaK_exp2RK(fs, key)); - freeexp(fs, key); -} - - -static void invertjump (FuncState *fs, expdesc *e) { - Instruction *pc = getjumpcontrol(fs, e->u.info); - lua_assert(testTMode(GET_OPCODE(*pc)) && GET_OPCODE(*pc) != OP_TESTSET && - GET_OPCODE(*pc) != OP_TEST); - SETARG_A(*pc, !(GETARG_A(*pc))); -} - - -static int jumponcond (FuncState *fs, expdesc *e, int cond) { - if (e->k == VRELOCABLE) { - Instruction ie = getcode(fs, e); - if (GET_OPCODE(ie) == OP_NOT) { - fs->pc--; /* remove previous OP_NOT */ - return condjump(fs, OP_TEST, GETARG_B(ie), 0, !cond); - } - /* else go through */ - } - discharge2anyreg(fs, e); - freeexp(fs, e); - return condjump(fs, OP_TESTSET, NO_REG, e->u.info, cond); -} - - -void luaK_goiftrue (FuncState *fs, expdesc *e) { - int pc; /* pc of last jump */ - luaK_dischargevars(fs, e); - switch (e->k) { - case VJMP: { - invertjump(fs, e); - pc = e->u.info; - break; - } - case VK: case VKNUM: case VTRUE: { - pc = NO_JUMP; /* always true; do nothing */ - break; - } - default: { - pc = jumponcond(fs, e, 0); - break; - } - } - luaK_concat(fs, &e->f, pc); /* insert last jump in `f' list */ - luaK_patchtohere(fs, e->t); - e->t = NO_JUMP; -} - - -void luaK_goiffalse (FuncState *fs, expdesc *e) { - int pc; /* pc of last jump */ - luaK_dischargevars(fs, e); - switch (e->k) { - case VJMP: { - pc = e->u.info; - break; - } - case VNIL: case VFALSE: { - pc = NO_JUMP; /* always false; do nothing */ - break; - } - default: { - pc = jumponcond(fs, e, 1); - break; - } - } - luaK_concat(fs, &e->t, pc); /* insert last jump in `t' list */ - luaK_patchtohere(fs, e->f); - e->f = NO_JUMP; -} - - -static void codenot (FuncState *fs, expdesc *e) { - luaK_dischargevars(fs, e); - switch (e->k) { - case VNIL: case VFALSE: { - e->k = VTRUE; - break; - } - case VK: case VKNUM: case VTRUE: { - e->k = VFALSE; - break; - } - case VJMP: { - invertjump(fs, e); - break; - } - case VRELOCABLE: - case VNONRELOC: { - discharge2anyreg(fs, e); - freeexp(fs, e); - e->u.info = luaK_codeABC(fs, OP_NOT, 0, e->u.info, 0); - e->k = VRELOCABLE; - break; - } - default: { - lua_assert(0); /* cannot happen */ - break; - } - } - /* interchange true and false lists */ - { int temp = e->f; e->f = e->t; e->t = temp; } - removevalues(fs, e->f); - removevalues(fs, e->t); -} - - -void luaK_indexed (FuncState *fs, expdesc *t, expdesc *k) { - lua_assert(!hasjumps(t)); - t->u.ind.t = t->u.info; - t->u.ind.idx = luaK_exp2RK(fs, k); - t->u.ind.vt = (t->k == VUPVAL) ? VUPVAL - : check_exp(vkisinreg(t->k), VLOCAL); - t->k = VINDEXED; -} - - -static int constfolding (OpCode op, expdesc *e1, expdesc *e2) { - lua_Number r; - if (!isnumeral(e1) || !isnumeral(e2)) return 0; - if ((op == OP_DIV || op == OP_MOD) && e2->u.nval == 0) - return 0; /* do not attempt to divide by 0 */ - r = luaO_arith(op - OP_ADD + LUA_OPADD, e1->u.nval, e2->u.nval); - e1->u.nval = r; - return 1; -} - - -static void codearith (FuncState *fs, OpCode op, - expdesc *e1, expdesc *e2, int line) { - if (constfolding(op, e1, e2)) - return; - else { - int o2 = (op != OP_UNM && op != OP_LEN) ? luaK_exp2RK(fs, e2) : 0; - int o1 = luaK_exp2RK(fs, e1); - if (o1 > o2) { - freeexp(fs, e1); - freeexp(fs, e2); - } - else { - freeexp(fs, e2); - freeexp(fs, e1); - } - e1->u.info = luaK_codeABC(fs, op, 0, o1, o2); - e1->k = VRELOCABLE; - luaK_fixline(fs, line); - } -} - - -static void codecomp (FuncState *fs, OpCode op, int cond, expdesc *e1, - expdesc *e2) { - int o1 = luaK_exp2RK(fs, e1); - int o2 = luaK_exp2RK(fs, e2); - freeexp(fs, e2); - freeexp(fs, e1); - if (cond == 0 && op != OP_EQ) { - int temp; /* exchange args to replace by `<' or `<=' */ - temp = o1; o1 = o2; o2 = temp; /* o1 <==> o2 */ - cond = 1; - } - e1->u.info = condjump(fs, op, cond, o1, o2); - e1->k = VJMP; -} - - -void luaK_prefix (FuncState *fs, UnOpr op, expdesc *e, int line) { - expdesc e2; - e2.t = e2.f = NO_JUMP; e2.k = VKNUM; e2.u.nval = 0; - switch (op) { - case OPR_MINUS: { - if (isnumeral(e)) /* minus constant? */ - e->u.nval = luai_numunm(NULL, e->u.nval); /* fold it */ - else { - luaK_exp2anyreg(fs, e); - codearith(fs, OP_UNM, e, &e2, line); - } - break; - } - case OPR_NOT: codenot(fs, e); break; - case OPR_LEN: { - luaK_exp2anyreg(fs, e); /* cannot operate on constants */ - codearith(fs, OP_LEN, e, &e2, line); - break; - } - default: lua_assert(0); - } -} - - -void luaK_infix (FuncState *fs, BinOpr op, expdesc *v) { - switch (op) { - case OPR_AND: { - luaK_goiftrue(fs, v); - break; - } - case OPR_OR: { - luaK_goiffalse(fs, v); - break; - } - case OPR_CONCAT: { - luaK_exp2nextreg(fs, v); /* operand must be on the `stack' */ - break; - } - case OPR_ADD: case OPR_SUB: case OPR_MUL: case OPR_DIV: - case OPR_MOD: case OPR_POW: { - if (!isnumeral(v)) luaK_exp2RK(fs, v); - break; - } - default: { - luaK_exp2RK(fs, v); - break; - } - } -} - - -void luaK_posfix (FuncState *fs, BinOpr op, - expdesc *e1, expdesc *e2, int line) { - switch (op) { - case OPR_AND: { - lua_assert(e1->t == NO_JUMP); /* list must be closed */ - luaK_dischargevars(fs, e2); - luaK_concat(fs, &e2->f, e1->f); - *e1 = *e2; - break; - } - case OPR_OR: { - lua_assert(e1->f == NO_JUMP); /* list must be closed */ - luaK_dischargevars(fs, e2); - luaK_concat(fs, &e2->t, e1->t); - *e1 = *e2; - break; - } - case OPR_CONCAT: { - luaK_exp2val(fs, e2); - if (e2->k == VRELOCABLE && GET_OPCODE(getcode(fs, e2)) == OP_CONCAT) { - lua_assert(e1->u.info == GETARG_B(getcode(fs, e2))-1); - freeexp(fs, e1); - SETARG_B(getcode(fs, e2), e1->u.info); - e1->k = VRELOCABLE; e1->u.info = e2->u.info; - } - else { - luaK_exp2nextreg(fs, e2); /* operand must be on the 'stack' */ - codearith(fs, OP_CONCAT, e1, e2, line); - } - break; - } - case OPR_ADD: case OPR_SUB: case OPR_MUL: case OPR_DIV: - case OPR_MOD: case OPR_POW: { - codearith(fs, cast(OpCode, op - OPR_ADD + OP_ADD), e1, e2, line); - break; - } - case OPR_EQ: case OPR_LT: case OPR_LE: { - codecomp(fs, cast(OpCode, op - OPR_EQ + OP_EQ), 1, e1, e2); - break; - } - case OPR_NE: case OPR_GT: case OPR_GE: { - codecomp(fs, cast(OpCode, op - OPR_NE + OP_EQ), 0, e1, e2); - break; - } - default: lua_assert(0); - } -} - - -void luaK_fixline (FuncState *fs, int line) { - fs->f->lineinfo[fs->pc - 1] = line; -} - - -void luaK_setlist (FuncState *fs, int base, int nelems, int tostore) { - int c = (nelems - 1)/LFIELDS_PER_FLUSH + 1; - int b = (tostore == LUA_MULTRET) ? 0 : tostore; - lua_assert(tostore != 0); - if (c <= MAXARG_C) - luaK_codeABC(fs, OP_SETLIST, base, b, c); - else if (c <= MAXARG_Ax) { - luaK_codeABC(fs, OP_SETLIST, base, b, 0); - codeextraarg(fs, c); - } - else - luaX_syntaxerror(fs->ls, "constructor too long"); - fs->freereg = base + 1; /* free registers with list values */ -} - diff --git a/lib/lua-5.2/src/lcode.h b/lib/lua-5.2/src/lcode.h deleted file mode 100644 index 6a1424c..0000000 --- a/lib/lua-5.2/src/lcode.h +++ /dev/null @@ -1,83 +0,0 @@ -/* -** $Id: lcode.h,v 1.58.1.1 2013/04/12 18:48:47 roberto Exp $ -** Code generator for Lua -** See Copyright Notice in lua.h -*/ - -#ifndef lcode_h -#define lcode_h - -#include "llex.h" -#include "lobject.h" -#include "lopcodes.h" -#include "lparser.h" - - -/* -** Marks the end of a patch list. It is an invalid value both as an absolute -** address, and as a list link (would link an element to itself). -*/ -#define NO_JUMP (-1) - - -/* -** grep "ORDER OPR" if you change these enums (ORDER OP) -*/ -typedef enum BinOpr { - OPR_ADD, OPR_SUB, OPR_MUL, OPR_DIV, OPR_MOD, OPR_POW, - OPR_CONCAT, - OPR_EQ, OPR_LT, OPR_LE, - OPR_NE, OPR_GT, OPR_GE, - OPR_AND, OPR_OR, - OPR_NOBINOPR -} BinOpr; - - -typedef enum UnOpr { OPR_MINUS, OPR_NOT, OPR_LEN, OPR_NOUNOPR } UnOpr; - - -#define getcode(fs,e) ((fs)->f->code[(e)->u.info]) - -#define luaK_codeAsBx(fs,o,A,sBx) luaK_codeABx(fs,o,A,(sBx)+MAXARG_sBx) - -#define luaK_setmultret(fs,e) luaK_setreturns(fs, e, LUA_MULTRET) - -#define luaK_jumpto(fs,t) luaK_patchlist(fs, luaK_jump(fs), t) - -LUAI_FUNC int luaK_codeABx (FuncState *fs, OpCode o, int A, unsigned int Bx); -LUAI_FUNC int luaK_codeABC (FuncState *fs, OpCode o, int A, int B, int C); -LUAI_FUNC int luaK_codek (FuncState *fs, int reg, int k); -LUAI_FUNC void luaK_fixline (FuncState *fs, int line); -LUAI_FUNC void luaK_nil (FuncState *fs, int from, int n); -LUAI_FUNC void luaK_reserveregs (FuncState *fs, int n); -LUAI_FUNC void luaK_checkstack (FuncState *fs, int n); -LUAI_FUNC int luaK_stringK (FuncState *fs, TString *s); -LUAI_FUNC int luaK_numberK (FuncState *fs, lua_Number r); -LUAI_FUNC void luaK_dischargevars (FuncState *fs, expdesc *e); -LUAI_FUNC int luaK_exp2anyreg (FuncState *fs, expdesc *e); -LUAI_FUNC void luaK_exp2anyregup (FuncState *fs, expdesc *e); -LUAI_FUNC void luaK_exp2nextreg (FuncState *fs, expdesc *e); -LUAI_FUNC void luaK_exp2val (FuncState *fs, expdesc *e); -LUAI_FUNC int luaK_exp2RK (FuncState *fs, expdesc *e); -LUAI_FUNC void luaK_self (FuncState *fs, expdesc *e, expdesc *key); -LUAI_FUNC void luaK_indexed (FuncState *fs, expdesc *t, expdesc *k); -LUAI_FUNC void luaK_goiftrue (FuncState *fs, expdesc *e); -LUAI_FUNC void luaK_goiffalse (FuncState *fs, expdesc *e); -LUAI_FUNC void luaK_storevar (FuncState *fs, expdesc *var, expdesc *e); -LUAI_FUNC void luaK_setreturns (FuncState *fs, expdesc *e, int nresults); -LUAI_FUNC void luaK_setoneret (FuncState *fs, expdesc *e); -LUAI_FUNC int luaK_jump (FuncState *fs); -LUAI_FUNC void luaK_ret (FuncState *fs, int first, int nret); -LUAI_FUNC void luaK_patchlist (FuncState *fs, int list, int target); -LUAI_FUNC void luaK_patchtohere (FuncState *fs, int list); -LUAI_FUNC void luaK_patchclose (FuncState *fs, int list, int level); -LUAI_FUNC void luaK_concat (FuncState *fs, int *l1, int l2); -LUAI_FUNC int luaK_getlabel (FuncState *fs); -LUAI_FUNC void luaK_prefix (FuncState *fs, UnOpr op, expdesc *v, int line); -LUAI_FUNC void luaK_infix (FuncState *fs, BinOpr op, expdesc *v); -LUAI_FUNC void luaK_posfix (FuncState *fs, BinOpr op, expdesc *v1, - expdesc *v2, int line); -LUAI_FUNC void luaK_setlist (FuncState *fs, int base, int nelems, int tostore); - - -#endif diff --git a/lib/lua-5.2/src/lcorolib.c b/lib/lua-5.2/src/lcorolib.c deleted file mode 100644 index ce4f6ad..0000000 --- a/lib/lua-5.2/src/lcorolib.c +++ /dev/null @@ -1,155 +0,0 @@ -/* -** $Id: lcorolib.c,v 1.5.1.1 2013/04/12 18:48:47 roberto Exp $ -** Coroutine Library -** See Copyright Notice in lua.h -*/ - - -#include - - -#define lcorolib_c -#define LUA_LIB - -#include "lua.h" - -#include "lauxlib.h" -#include "lualib.h" - - -static int auxresume (lua_State *L, lua_State *co, int narg) { - int status; - if (!lua_checkstack(co, narg)) { - lua_pushliteral(L, "too many arguments to resume"); - return -1; /* error flag */ - } - if (lua_status(co) == LUA_OK && lua_gettop(co) == 0) { - lua_pushliteral(L, "cannot resume dead coroutine"); - return -1; /* error flag */ - } - lua_xmove(L, co, narg); - status = lua_resume(co, L, narg); - if (status == LUA_OK || status == LUA_YIELD) { - int nres = lua_gettop(co); - if (!lua_checkstack(L, nres + 1)) { - lua_pop(co, nres); /* remove results anyway */ - lua_pushliteral(L, "too many results to resume"); - return -1; /* error flag */ - } - lua_xmove(co, L, nres); /* move yielded values */ - return nres; - } - else { - lua_xmove(co, L, 1); /* move error message */ - return -1; /* error flag */ - } -} - - -static int luaB_coresume (lua_State *L) { - lua_State *co = lua_tothread(L, 1); - int r; - luaL_argcheck(L, co, 1, "coroutine expected"); - r = auxresume(L, co, lua_gettop(L) - 1); - if (r < 0) { - lua_pushboolean(L, 0); - lua_insert(L, -2); - return 2; /* return false + error message */ - } - else { - lua_pushboolean(L, 1); - lua_insert(L, -(r + 1)); - return r + 1; /* return true + `resume' returns */ - } -} - - -static int luaB_auxwrap (lua_State *L) { - lua_State *co = lua_tothread(L, lua_upvalueindex(1)); - int r = auxresume(L, co, lua_gettop(L)); - if (r < 0) { - if (lua_isstring(L, -1)) { /* error object is a string? */ - luaL_where(L, 1); /* add extra info */ - lua_insert(L, -2); - lua_concat(L, 2); - } - return lua_error(L); /* propagate error */ - } - return r; -} - - -static int luaB_cocreate (lua_State *L) { - lua_State *NL; - luaL_checktype(L, 1, LUA_TFUNCTION); - NL = lua_newthread(L); - lua_pushvalue(L, 1); /* move function to top */ - lua_xmove(L, NL, 1); /* move function from L to NL */ - return 1; -} - - -static int luaB_cowrap (lua_State *L) { - luaB_cocreate(L); - lua_pushcclosure(L, luaB_auxwrap, 1); - return 1; -} - - -static int luaB_yield (lua_State *L) { - return lua_yield(L, lua_gettop(L)); -} - - -static int luaB_costatus (lua_State *L) { - lua_State *co = lua_tothread(L, 1); - luaL_argcheck(L, co, 1, "coroutine expected"); - if (L == co) lua_pushliteral(L, "running"); - else { - switch (lua_status(co)) { - case LUA_YIELD: - lua_pushliteral(L, "suspended"); - break; - case LUA_OK: { - lua_Debug ar; - if (lua_getstack(co, 0, &ar) > 0) /* does it have frames? */ - lua_pushliteral(L, "normal"); /* it is running */ - else if (lua_gettop(co) == 0) - lua_pushliteral(L, "dead"); - else - lua_pushliteral(L, "suspended"); /* initial state */ - break; - } - default: /* some error occurred */ - lua_pushliteral(L, "dead"); - break; - } - } - return 1; -} - - -static int luaB_corunning (lua_State *L) { - int ismain = lua_pushthread(L); - lua_pushboolean(L, ismain); - return 2; -} - - -static const luaL_Reg co_funcs[] = { - {"create", luaB_cocreate}, - {"resume", luaB_coresume}, - {"running", luaB_corunning}, - {"status", luaB_costatus}, - {"wrap", luaB_cowrap}, - {"yield", luaB_yield}, - {NULL, NULL} -}; - - - -LUAMOD_API int luaopen_coroutine (lua_State *L) { - luaL_newlib(L, co_funcs); - return 1; -} - diff --git a/lib/lua-5.2/src/lctype.c b/lib/lua-5.2/src/lctype.c deleted file mode 100644 index 93f8cad..0000000 --- a/lib/lua-5.2/src/lctype.c +++ /dev/null @@ -1,52 +0,0 @@ -/* -** $Id: lctype.c,v 1.11.1.1 2013/04/12 18:48:47 roberto Exp $ -** 'ctype' functions for Lua -** See Copyright Notice in lua.h -*/ - -#define lctype_c -#define LUA_CORE - -#include "lctype.h" - -#if !LUA_USE_CTYPE /* { */ - -#include - -LUAI_DDEF const lu_byte luai_ctype_[UCHAR_MAX + 2] = { - 0x00, /* EOZ */ - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0. */ - 0x00, 0x08, 0x08, 0x08, 0x08, 0x08, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 1. */ - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x0c, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, /* 2. */ - 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, - 0x16, 0x16, 0x16, 0x16, 0x16, 0x16, 0x16, 0x16, /* 3. */ - 0x16, 0x16, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, - 0x04, 0x15, 0x15, 0x15, 0x15, 0x15, 0x15, 0x05, /* 4. */ - 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, - 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, /* 5. */ - 0x05, 0x05, 0x05, 0x04, 0x04, 0x04, 0x04, 0x05, - 0x04, 0x15, 0x15, 0x15, 0x15, 0x15, 0x15, 0x05, /* 6. */ - 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, - 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, /* 7. */ - 0x05, 0x05, 0x05, 0x04, 0x04, 0x04, 0x04, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 8. */ - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 9. */ - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* a. */ - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* b. */ - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* c. */ - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* d. */ - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* e. */ - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* f. */ - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -}; - -#endif /* } */ diff --git a/lib/lua-5.2/src/lctype.h b/lib/lua-5.2/src/lctype.h deleted file mode 100644 index b09b21a..0000000 --- a/lib/lua-5.2/src/lctype.h +++ /dev/null @@ -1,95 +0,0 @@ -/* -** $Id: lctype.h,v 1.12.1.1 2013/04/12 18:48:47 roberto Exp $ -** 'ctype' functions for Lua -** See Copyright Notice in lua.h -*/ - -#ifndef lctype_h -#define lctype_h - -#include "lua.h" - - -/* -** WARNING: the functions defined here do not necessarily correspond -** to the similar functions in the standard C ctype.h. They are -** optimized for the specific needs of Lua -*/ - -#if !defined(LUA_USE_CTYPE) - -#if 'A' == 65 && '0' == 48 -/* ASCII case: can use its own tables; faster and fixed */ -#define LUA_USE_CTYPE 0 -#else -/* must use standard C ctype */ -#define LUA_USE_CTYPE 1 -#endif - -#endif - - -#if !LUA_USE_CTYPE /* { */ - -#include - -#include "llimits.h" - - -#define ALPHABIT 0 -#define DIGITBIT 1 -#define PRINTBIT 2 -#define SPACEBIT 3 -#define XDIGITBIT 4 - - -#define MASK(B) (1 << (B)) - - -/* -** add 1 to char to allow index -1 (EOZ) -*/ -#define testprop(c,p) (luai_ctype_[(c)+1] & (p)) - -/* -** 'lalpha' (Lua alphabetic) and 'lalnum' (Lua alphanumeric) both include '_' -*/ -#define lislalpha(c) testprop(c, MASK(ALPHABIT)) -#define lislalnum(c) testprop(c, (MASK(ALPHABIT) | MASK(DIGITBIT))) -#define lisdigit(c) testprop(c, MASK(DIGITBIT)) -#define lisspace(c) testprop(c, MASK(SPACEBIT)) -#define lisprint(c) testprop(c, MASK(PRINTBIT)) -#define lisxdigit(c) testprop(c, MASK(XDIGITBIT)) - -/* -** this 'ltolower' only works for alphabetic characters -*/ -#define ltolower(c) ((c) | ('A' ^ 'a')) - - -/* two more entries for 0 and -1 (EOZ) */ -LUAI_DDEC const lu_byte luai_ctype_[UCHAR_MAX + 2]; - - -#else /* }{ */ - -/* -** use standard C ctypes -*/ - -#include - - -#define lislalpha(c) (isalpha(c) || (c) == '_') -#define lislalnum(c) (isalnum(c) || (c) == '_') -#define lisdigit(c) (isdigit(c)) -#define lisspace(c) (isspace(c)) -#define lisprint(c) (isprint(c)) -#define lisxdigit(c) (isxdigit(c)) - -#define ltolower(c) (tolower(c)) - -#endif /* } */ - -#endif - diff --git a/lib/lua-5.2/src/ldblib.c b/lib/lua-5.2/src/ldblib.c deleted file mode 100644 index bd8df9d..0000000 --- a/lib/lua-5.2/src/ldblib.c +++ /dev/null @@ -1,408 +0,0 @@ -/* -** $Id: ldblib.c,v 1.132.1.2 2015/02/19 17:16:55 roberto Exp $ -** Interface from Lua to its debug API -** See Copyright Notice in lua.h -*/ - - -#include -#include -#include - -#define ldblib_c -#define LUA_LIB - -#include "lua.h" - -#include "lauxlib.h" -#include "lualib.h" - - -#define HOOKKEY "_HKEY" - - -static void checkstack (lua_State *L, lua_State *L1, int n) { - if (L != L1 && !lua_checkstack(L1, n)) - luaL_error(L, "stack overflow"); -} - - -static int db_getregistry (lua_State *L) { - lua_pushvalue(L, LUA_REGISTRYINDEX); - return 1; -} - - -static int db_getmetatable (lua_State *L) { - luaL_checkany(L, 1); - if (!lua_getmetatable(L, 1)) { - lua_pushnil(L); /* no metatable */ - } - return 1; -} - - -static int db_setmetatable (lua_State *L) { - int t = lua_type(L, 2); - luaL_argcheck(L, t == LUA_TNIL || t == LUA_TTABLE, 2, - "nil or table expected"); - lua_settop(L, 2); - lua_setmetatable(L, 1); - return 1; /* return 1st argument */ -} - - -static int db_getuservalue (lua_State *L) { - if (lua_type(L, 1) != LUA_TUSERDATA) - lua_pushnil(L); - else - lua_getuservalue(L, 1); - return 1; -} - - -static int db_setuservalue (lua_State *L) { - if (lua_type(L, 1) == LUA_TLIGHTUSERDATA) - luaL_argerror(L, 1, "full userdata expected, got light userdata"); - luaL_checktype(L, 1, LUA_TUSERDATA); - if (!lua_isnoneornil(L, 2)) - luaL_checktype(L, 2, LUA_TTABLE); - lua_settop(L, 2); - lua_setuservalue(L, 1); - return 1; -} - - -static void settabss (lua_State *L, const char *i, const char *v) { - lua_pushstring(L, v); - lua_setfield(L, -2, i); -} - - -static void settabsi (lua_State *L, const char *i, int v) { - lua_pushinteger(L, v); - lua_setfield(L, -2, i); -} - - -static void settabsb (lua_State *L, const char *i, int v) { - lua_pushboolean(L, v); - lua_setfield(L, -2, i); -} - - -static lua_State *getthread (lua_State *L, int *arg) { - if (lua_isthread(L, 1)) { - *arg = 1; - return lua_tothread(L, 1); - } - else { - *arg = 0; - return L; - } -} - - -static void treatstackoption (lua_State *L, lua_State *L1, const char *fname) { - if (L == L1) { - lua_pushvalue(L, -2); - lua_remove(L, -3); - } - else - lua_xmove(L1, L, 1); - lua_setfield(L, -2, fname); -} - - -static int db_getinfo (lua_State *L) { - lua_Debug ar; - int arg; - lua_State *L1 = getthread(L, &arg); - const char *options = luaL_optstring(L, arg+2, "flnStu"); - checkstack(L, L1, 3); - if (lua_isnumber(L, arg+1)) { - if (!lua_getstack(L1, (int)lua_tointeger(L, arg+1), &ar)) { - lua_pushnil(L); /* level out of range */ - return 1; - } - } - else if (lua_isfunction(L, arg+1)) { - lua_pushfstring(L, ">%s", options); - options = lua_tostring(L, -1); - lua_pushvalue(L, arg+1); - lua_xmove(L, L1, 1); - } - else - return luaL_argerror(L, arg+1, "function or level expected"); - if (!lua_getinfo(L1, options, &ar)) - return luaL_argerror(L, arg+2, "invalid option"); - lua_createtable(L, 0, 2); - if (strchr(options, 'S')) { - settabss(L, "source", ar.source); - settabss(L, "short_src", ar.short_src); - settabsi(L, "linedefined", ar.linedefined); - settabsi(L, "lastlinedefined", ar.lastlinedefined); - settabss(L, "what", ar.what); - } - if (strchr(options, 'l')) - settabsi(L, "currentline", ar.currentline); - if (strchr(options, 'u')) { - settabsi(L, "nups", ar.nups); - settabsi(L, "nparams", ar.nparams); - settabsb(L, "isvararg", ar.isvararg); - } - if (strchr(options, 'n')) { - settabss(L, "name", ar.name); - settabss(L, "namewhat", ar.namewhat); - } - if (strchr(options, 't')) - settabsb(L, "istailcall", ar.istailcall); - if (strchr(options, 'L')) - treatstackoption(L, L1, "activelines"); - if (strchr(options, 'f')) - treatstackoption(L, L1, "func"); - return 1; /* return table */ -} - - -static int db_getlocal (lua_State *L) { - int arg; - lua_State *L1 = getthread(L, &arg); - lua_Debug ar; - const char *name; - int nvar = luaL_checkint(L, arg+2); /* local-variable index */ - if (lua_isfunction(L, arg + 1)) { /* function argument? */ - lua_pushvalue(L, arg + 1); /* push function */ - lua_pushstring(L, lua_getlocal(L, NULL, nvar)); /* push local name */ - return 1; - } - else { /* stack-level argument */ - if (!lua_getstack(L1, luaL_checkint(L, arg+1), &ar)) /* out of range? */ - return luaL_argerror(L, arg+1, "level out of range"); - checkstack(L, L1, 1); - name = lua_getlocal(L1, &ar, nvar); - if (name) { - lua_xmove(L1, L, 1); /* push local value */ - lua_pushstring(L, name); /* push name */ - lua_pushvalue(L, -2); /* re-order */ - return 2; - } - else { - lua_pushnil(L); /* no name (nor value) */ - return 1; - } - } -} - - -static int db_setlocal (lua_State *L) { - int arg; - lua_State *L1 = getthread(L, &arg); - lua_Debug ar; - if (!lua_getstack(L1, luaL_checkint(L, arg+1), &ar)) /* out of range? */ - return luaL_argerror(L, arg+1, "level out of range"); - luaL_checkany(L, arg+3); - lua_settop(L, arg+3); - checkstack(L, L1, 1); - lua_xmove(L, L1, 1); - lua_pushstring(L, lua_setlocal(L1, &ar, luaL_checkint(L, arg+2))); - return 1; -} - - -static int auxupvalue (lua_State *L, int get) { - const char *name; - int n = luaL_checkint(L, 2); - luaL_checktype(L, 1, LUA_TFUNCTION); - name = get ? lua_getupvalue(L, 1, n) : lua_setupvalue(L, 1, n); - if (name == NULL) return 0; - lua_pushstring(L, name); - lua_insert(L, -(get+1)); - return get + 1; -} - - -static int db_getupvalue (lua_State *L) { - return auxupvalue(L, 1); -} - - -static int db_setupvalue (lua_State *L) { - luaL_checkany(L, 3); - return auxupvalue(L, 0); -} - - -static int checkupval (lua_State *L, int argf, int argnup) { - lua_Debug ar; - int nup = luaL_checkint(L, argnup); - luaL_checktype(L, argf, LUA_TFUNCTION); - lua_pushvalue(L, argf); - lua_getinfo(L, ">u", &ar); - luaL_argcheck(L, 1 <= nup && nup <= ar.nups, argnup, "invalid upvalue index"); - return nup; -} - - -static int db_upvalueid (lua_State *L) { - int n = checkupval(L, 1, 2); - lua_pushlightuserdata(L, lua_upvalueid(L, 1, n)); - return 1; -} - - -static int db_upvaluejoin (lua_State *L) { - int n1 = checkupval(L, 1, 2); - int n2 = checkupval(L, 3, 4); - luaL_argcheck(L, !lua_iscfunction(L, 1), 1, "Lua function expected"); - luaL_argcheck(L, !lua_iscfunction(L, 3), 3, "Lua function expected"); - lua_upvaluejoin(L, 1, n1, 3, n2); - return 0; -} - - -#define gethooktable(L) luaL_getsubtable(L, LUA_REGISTRYINDEX, HOOKKEY) - - -static void hookf (lua_State *L, lua_Debug *ar) { - static const char *const hooknames[] = - {"call", "return", "line", "count", "tail call"}; - gethooktable(L); - lua_pushthread(L); - lua_rawget(L, -2); - if (lua_isfunction(L, -1)) { - lua_pushstring(L, hooknames[(int)ar->event]); - if (ar->currentline >= 0) - lua_pushinteger(L, ar->currentline); - else lua_pushnil(L); - lua_assert(lua_getinfo(L, "lS", ar)); - lua_call(L, 2, 0); - } -} - - -static int makemask (const char *smask, int count) { - int mask = 0; - if (strchr(smask, 'c')) mask |= LUA_MASKCALL; - if (strchr(smask, 'r')) mask |= LUA_MASKRET; - if (strchr(smask, 'l')) mask |= LUA_MASKLINE; - if (count > 0) mask |= LUA_MASKCOUNT; - return mask; -} - - -static char *unmakemask (int mask, char *smask) { - int i = 0; - if (mask & LUA_MASKCALL) smask[i++] = 'c'; - if (mask & LUA_MASKRET) smask[i++] = 'r'; - if (mask & LUA_MASKLINE) smask[i++] = 'l'; - smask[i] = '\0'; - return smask; -} - - -static int db_sethook (lua_State *L) { - int arg, mask, count; - lua_Hook func; - lua_State *L1 = getthread(L, &arg); - if (lua_isnoneornil(L, arg+1)) { - lua_settop(L, arg+1); - func = NULL; mask = 0; count = 0; /* turn off hooks */ - } - else { - const char *smask = luaL_checkstring(L, arg+2); - luaL_checktype(L, arg+1, LUA_TFUNCTION); - count = luaL_optint(L, arg+3, 0); - func = hookf; mask = makemask(smask, count); - } - if (gethooktable(L) == 0) { /* creating hook table? */ - lua_pushstring(L, "k"); - lua_setfield(L, -2, "__mode"); /** hooktable.__mode = "k" */ - lua_pushvalue(L, -1); - lua_setmetatable(L, -2); /* setmetatable(hooktable) = hooktable */ - } - checkstack(L, L1, 1); - lua_pushthread(L1); lua_xmove(L1, L, 1); - lua_pushvalue(L, arg+1); - lua_rawset(L, -3); /* set new hook */ - lua_sethook(L1, func, mask, count); /* set hooks */ - return 0; -} - - -static int db_gethook (lua_State *L) { - int arg; - lua_State *L1 = getthread(L, &arg); - char buff[5]; - int mask = lua_gethookmask(L1); - lua_Hook hook = lua_gethook(L1); - if (hook != NULL && hook != hookf) /* external hook? */ - lua_pushliteral(L, "external hook"); - else { - gethooktable(L); - checkstack(L, L1, 1); - lua_pushthread(L1); lua_xmove(L1, L, 1); - lua_rawget(L, -2); /* get hook */ - lua_remove(L, -2); /* remove hook table */ - } - lua_pushstring(L, unmakemask(mask, buff)); - lua_pushinteger(L, lua_gethookcount(L1)); - return 3; -} - - -static int db_debug (lua_State *L) { - for (;;) { - char buffer[250]; - luai_writestringerror("%s", "lua_debug> "); - if (fgets(buffer, sizeof(buffer), stdin) == 0 || - strcmp(buffer, "cont\n") == 0) - return 0; - if (luaL_loadbuffer(L, buffer, strlen(buffer), "=(debug command)") || - lua_pcall(L, 0, 0, 0)) - luai_writestringerror("%s\n", lua_tostring(L, -1)); - lua_settop(L, 0); /* remove eventual returns */ - } -} - - -static int db_traceback (lua_State *L) { - int arg; - lua_State *L1 = getthread(L, &arg); - const char *msg = lua_tostring(L, arg + 1); - if (msg == NULL && !lua_isnoneornil(L, arg + 1)) /* non-string 'msg'? */ - lua_pushvalue(L, arg + 1); /* return it untouched */ - else { - int level = luaL_optint(L, arg + 2, (L == L1) ? 1 : 0); - luaL_traceback(L, L1, msg, level); - } - return 1; -} - - -static const luaL_Reg dblib[] = { - {"debug", db_debug}, - {"getuservalue", db_getuservalue}, - {"gethook", db_gethook}, - {"getinfo", db_getinfo}, - {"getlocal", db_getlocal}, - {"getregistry", db_getregistry}, - {"getmetatable", db_getmetatable}, - {"getupvalue", db_getupvalue}, - {"upvaluejoin", db_upvaluejoin}, - {"upvalueid", db_upvalueid}, - {"setuservalue", db_setuservalue}, - {"sethook", db_sethook}, - {"setlocal", db_setlocal}, - {"setmetatable", db_setmetatable}, - {"setupvalue", db_setupvalue}, - {"traceback", db_traceback}, - {NULL, NULL} -}; - - -LUAMOD_API int luaopen_debug (lua_State *L) { - luaL_newlib(L, dblib); - return 1; -} - diff --git a/lib/lua-5.2/src/ldebug.c b/lib/lua-5.2/src/ldebug.c deleted file mode 100644 index 9611846..0000000 --- a/lib/lua-5.2/src/ldebug.c +++ /dev/null @@ -1,610 +0,0 @@ -/* -** $Id: ldebug.c,v 2.90.1.4 2015/02/19 17:05:13 roberto Exp $ -** Debug Interface -** See Copyright Notice in lua.h -*/ - - -#include -#include -#include - - -#define ldebug_c -#define LUA_CORE - -#include "lua.h" - -#include "lapi.h" -#include "lcode.h" -#include "ldebug.h" -#include "ldo.h" -#include "lfunc.h" -#include "lobject.h" -#include "lopcodes.h" -#include "lstate.h" -#include "lstring.h" -#include "ltable.h" -#include "ltm.h" -#include "lvm.h" - - - -#define noLuaClosure(f) ((f) == NULL || (f)->c.tt == LUA_TCCL) - - -static const char *getfuncname (lua_State *L, CallInfo *ci, const char **name); - - -static int currentpc (CallInfo *ci) { - lua_assert(isLua(ci)); - return pcRel(ci->u.l.savedpc, ci_func(ci)->p); -} - - -static int currentline (CallInfo *ci) { - return getfuncline(ci_func(ci)->p, currentpc(ci)); -} - - -static void swapextra (lua_State *L) { - if (L->status == LUA_YIELD) { - CallInfo *ci = L->ci; /* get function that yielded */ - StkId temp = ci->func; /* exchange its 'func' and 'extra' values */ - ci->func = restorestack(L, ci->extra); - ci->extra = savestack(L, temp); - } -} - - -/* -** this function can be called asynchronous (e.g. during a signal) -*/ -LUA_API int lua_sethook (lua_State *L, lua_Hook func, int mask, int count) { - if (func == NULL || mask == 0) { /* turn off hooks? */ - mask = 0; - func = NULL; - } - if (isLua(L->ci)) - L->oldpc = L->ci->u.l.savedpc; - L->hook = func; - L->basehookcount = count; - resethookcount(L); - L->hookmask = cast_byte(mask); - return 1; -} - - -LUA_API lua_Hook lua_gethook (lua_State *L) { - return L->hook; -} - - -LUA_API int lua_gethookmask (lua_State *L) { - return L->hookmask; -} - - -LUA_API int lua_gethookcount (lua_State *L) { - return L->basehookcount; -} - - -LUA_API int lua_getstack (lua_State *L, int level, lua_Debug *ar) { - int status; - CallInfo *ci; - if (level < 0) return 0; /* invalid (negative) level */ - lua_lock(L); - for (ci = L->ci; level > 0 && ci != &L->base_ci; ci = ci->previous) - level--; - if (level == 0 && ci != &L->base_ci) { /* level found? */ - status = 1; - ar->i_ci = ci; - } - else status = 0; /* no such level */ - lua_unlock(L); - return status; -} - - -static const char *upvalname (Proto *p, int uv) { - TString *s = check_exp(uv < p->sizeupvalues, p->upvalues[uv].name); - if (s == NULL) return "?"; - else return getstr(s); -} - - -static const char *findvararg (CallInfo *ci, int n, StkId *pos) { - int nparams = clLvalue(ci->func)->p->numparams; - if (n >= ci->u.l.base - ci->func - nparams) - return NULL; /* no such vararg */ - else { - *pos = ci->func + nparams + n; - return "(*vararg)"; /* generic name for any vararg */ - } -} - - -static const char *findlocal (lua_State *L, CallInfo *ci, int n, - StkId *pos) { - const char *name = NULL; - StkId base; - if (isLua(ci)) { - if (n < 0) /* access to vararg values? */ - return findvararg(ci, -n, pos); - else { - base = ci->u.l.base; - name = luaF_getlocalname(ci_func(ci)->p, n, currentpc(ci)); - } - } - else - base = ci->func + 1; - if (name == NULL) { /* no 'standard' name? */ - StkId limit = (ci == L->ci) ? L->top : ci->next->func; - if (limit - base >= n && n > 0) /* is 'n' inside 'ci' stack? */ - name = "(*temporary)"; /* generic name for any valid slot */ - else - return NULL; /* no name */ - } - *pos = base + (n - 1); - return name; -} - - -LUA_API const char *lua_getlocal (lua_State *L, const lua_Debug *ar, int n) { - const char *name; - lua_lock(L); - swapextra(L); - if (ar == NULL) { /* information about non-active function? */ - if (!isLfunction(L->top - 1)) /* not a Lua function? */ - name = NULL; - else /* consider live variables at function start (parameters) */ - name = luaF_getlocalname(clLvalue(L->top - 1)->p, n, 0); - } - else { /* active function; get information through 'ar' */ - StkId pos = 0; /* to avoid warnings */ - name = findlocal(L, ar->i_ci, n, &pos); - if (name) { - setobj2s(L, L->top, pos); - api_incr_top(L); - } - } - swapextra(L); - lua_unlock(L); - return name; -} - - -LUA_API const char *lua_setlocal (lua_State *L, const lua_Debug *ar, int n) { - StkId pos = 0; /* to avoid warnings */ - const char *name; - lua_lock(L); - swapextra(L); - name = findlocal(L, ar->i_ci, n, &pos); - if (name) - setobjs2s(L, pos, L->top - 1); - L->top--; /* pop value */ - swapextra(L); - lua_unlock(L); - return name; -} - - -static void funcinfo (lua_Debug *ar, Closure *cl) { - if (noLuaClosure(cl)) { - ar->source = "=[C]"; - ar->linedefined = -1; - ar->lastlinedefined = -1; - ar->what = "C"; - } - else { - Proto *p = cl->l.p; - ar->source = p->source ? getstr(p->source) : "=?"; - ar->linedefined = p->linedefined; - ar->lastlinedefined = p->lastlinedefined; - ar->what = (ar->linedefined == 0) ? "main" : "Lua"; - } - luaO_chunkid(ar->short_src, ar->source, LUA_IDSIZE); -} - - -static void collectvalidlines (lua_State *L, Closure *f) { - if (noLuaClosure(f)) { - setnilvalue(L->top); - api_incr_top(L); - } - else { - int i; - TValue v; - int *lineinfo = f->l.p->lineinfo; - Table *t = luaH_new(L); /* new table to store active lines */ - sethvalue(L, L->top, t); /* push it on stack */ - api_incr_top(L); - setbvalue(&v, 1); /* boolean 'true' to be the value of all indices */ - for (i = 0; i < f->l.p->sizelineinfo; i++) /* for all lines with code */ - luaH_setint(L, t, lineinfo[i], &v); /* table[line] = true */ - } -} - - -static int auxgetinfo (lua_State *L, const char *what, lua_Debug *ar, - Closure *f, CallInfo *ci) { - int status = 1; - for (; *what; what++) { - switch (*what) { - case 'S': { - funcinfo(ar, f); - break; - } - case 'l': { - ar->currentline = (ci && isLua(ci)) ? currentline(ci) : -1; - break; - } - case 'u': { - ar->nups = (f == NULL) ? 0 : f->c.nupvalues; - if (noLuaClosure(f)) { - ar->isvararg = 1; - ar->nparams = 0; - } - else { - ar->isvararg = f->l.p->is_vararg; - ar->nparams = f->l.p->numparams; - } - break; - } - case 't': { - ar->istailcall = (ci) ? ci->callstatus & CIST_TAIL : 0; - break; - } - case 'n': { - /* calling function is a known Lua function? */ - if (ci && !(ci->callstatus & CIST_TAIL) && isLua(ci->previous)) - ar->namewhat = getfuncname(L, ci->previous, &ar->name); - else - ar->namewhat = NULL; - if (ar->namewhat == NULL) { - ar->namewhat = ""; /* not found */ - ar->name = NULL; - } - break; - } - case 'L': - case 'f': /* handled by lua_getinfo */ - break; - default: status = 0; /* invalid option */ - } - } - return status; -} - - -LUA_API int lua_getinfo (lua_State *L, const char *what, lua_Debug *ar) { - int status; - Closure *cl; - CallInfo *ci; - StkId func; - lua_lock(L); - swapextra(L); - if (*what == '>') { - ci = NULL; - func = L->top - 1; - api_check(L, ttisfunction(func), "function expected"); - what++; /* skip the '>' */ - L->top--; /* pop function */ - } - else { - ci = ar->i_ci; - func = ci->func; - lua_assert(ttisfunction(ci->func)); - } - cl = ttisclosure(func) ? clvalue(func) : NULL; - status = auxgetinfo(L, what, ar, cl, ci); - if (strchr(what, 'f')) { - setobjs2s(L, L->top, func); - api_incr_top(L); - } - swapextra(L); - if (strchr(what, 'L')) - collectvalidlines(L, cl); - lua_unlock(L); - return status; -} - - -/* -** {====================================================== -** Symbolic Execution -** ======================================================= -*/ - -static const char *getobjname (Proto *p, int lastpc, int reg, - const char **name); - - -/* -** find a "name" for the RK value 'c' -*/ -static void kname (Proto *p, int pc, int c, const char **name) { - if (ISK(c)) { /* is 'c' a constant? */ - TValue *kvalue = &p->k[INDEXK(c)]; - if (ttisstring(kvalue)) { /* literal constant? */ - *name = svalue(kvalue); /* it is its own name */ - return; - } - /* else no reasonable name found */ - } - else { /* 'c' is a register */ - const char *what = getobjname(p, pc, c, name); /* search for 'c' */ - if (what && *what == 'c') { /* found a constant name? */ - return; /* 'name' already filled */ - } - /* else no reasonable name found */ - } - *name = "?"; /* no reasonable name found */ -} - - -static int filterpc (int pc, int jmptarget) { - if (pc < jmptarget) /* is code conditional (inside a jump)? */ - return -1; /* cannot know who sets that register */ - else return pc; /* current position sets that register */ -} - - -/* -** try to find last instruction before 'lastpc' that modified register 'reg' -*/ -static int findsetreg (Proto *p, int lastpc, int reg) { - int pc; - int setreg = -1; /* keep last instruction that changed 'reg' */ - int jmptarget = 0; /* any code before this address is conditional */ - for (pc = 0; pc < lastpc; pc++) { - Instruction i = p->code[pc]; - OpCode op = GET_OPCODE(i); - int a = GETARG_A(i); - switch (op) { - case OP_LOADNIL: { - int b = GETARG_B(i); - if (a <= reg && reg <= a + b) /* set registers from 'a' to 'a+b' */ - setreg = filterpc(pc, jmptarget); - break; - } - case OP_TFORCALL: { - if (reg >= a + 2) /* affect all regs above its base */ - setreg = filterpc(pc, jmptarget); - break; - } - case OP_CALL: - case OP_TAILCALL: { - if (reg >= a) /* affect all registers above base */ - setreg = filterpc(pc, jmptarget); - break; - } - case OP_JMP: { - int b = GETARG_sBx(i); - int dest = pc + 1 + b; - /* jump is forward and do not skip `lastpc'? */ - if (pc < dest && dest <= lastpc) { - if (dest > jmptarget) - jmptarget = dest; /* update 'jmptarget' */ - } - break; - } - case OP_TEST: { - if (reg == a) /* jumped code can change 'a' */ - setreg = filterpc(pc, jmptarget); - break; - } - default: - if (testAMode(op) && reg == a) /* any instruction that set A */ - setreg = filterpc(pc, jmptarget); - break; - } - } - return setreg; -} - - -static const char *getobjname (Proto *p, int lastpc, int reg, - const char **name) { - int pc; - *name = luaF_getlocalname(p, reg + 1, lastpc); - if (*name) /* is a local? */ - return "local"; - /* else try symbolic execution */ - pc = findsetreg(p, lastpc, reg); - if (pc != -1) { /* could find instruction? */ - Instruction i = p->code[pc]; - OpCode op = GET_OPCODE(i); - switch (op) { - case OP_MOVE: { - int b = GETARG_B(i); /* move from 'b' to 'a' */ - if (b < GETARG_A(i)) - return getobjname(p, pc, b, name); /* get name for 'b' */ - break; - } - case OP_GETTABUP: - case OP_GETTABLE: { - int k = GETARG_C(i); /* key index */ - int t = GETARG_B(i); /* table index */ - const char *vn = (op == OP_GETTABLE) /* name of indexed variable */ - ? luaF_getlocalname(p, t + 1, pc) - : upvalname(p, t); - kname(p, pc, k, name); - return (vn && strcmp(vn, LUA_ENV) == 0) ? "global" : "field"; - } - case OP_GETUPVAL: { - *name = upvalname(p, GETARG_B(i)); - return "upvalue"; - } - case OP_LOADK: - case OP_LOADKX: { - int b = (op == OP_LOADK) ? GETARG_Bx(i) - : GETARG_Ax(p->code[pc + 1]); - if (ttisstring(&p->k[b])) { - *name = svalue(&p->k[b]); - return "constant"; - } - break; - } - case OP_SELF: { - int k = GETARG_C(i); /* key index */ - kname(p, pc, k, name); - return "method"; - } - default: break; /* go through to return NULL */ - } - } - return NULL; /* could not find reasonable name */ -} - - -static const char *getfuncname (lua_State *L, CallInfo *ci, const char **name) { - TMS tm; - Proto *p = ci_func(ci)->p; /* calling function */ - int pc = currentpc(ci); /* calling instruction index */ - Instruction i = p->code[pc]; /* calling instruction */ - switch (GET_OPCODE(i)) { - case OP_CALL: - case OP_TAILCALL: /* get function name */ - return getobjname(p, pc, GETARG_A(i), name); - case OP_TFORCALL: { /* for iterator */ - *name = "for iterator"; - return "for iterator"; - } - /* all other instructions can call only through metamethods */ - case OP_SELF: - case OP_GETTABUP: - case OP_GETTABLE: tm = TM_INDEX; break; - case OP_SETTABUP: - case OP_SETTABLE: tm = TM_NEWINDEX; break; - case OP_EQ: tm = TM_EQ; break; - case OP_ADD: tm = TM_ADD; break; - case OP_SUB: tm = TM_SUB; break; - case OP_MUL: tm = TM_MUL; break; - case OP_DIV: tm = TM_DIV; break; - case OP_MOD: tm = TM_MOD; break; - case OP_POW: tm = TM_POW; break; - case OP_UNM: tm = TM_UNM; break; - case OP_LEN: tm = TM_LEN; break; - case OP_LT: tm = TM_LT; break; - case OP_LE: tm = TM_LE; break; - case OP_CONCAT: tm = TM_CONCAT; break; - default: - return NULL; /* else no useful name can be found */ - } - *name = getstr(G(L)->tmname[tm]); - return "metamethod"; -} - -/* }====================================================== */ - - - -/* -** only ANSI way to check whether a pointer points to an array -** (used only for error messages, so efficiency is not a big concern) -*/ -static int isinstack (CallInfo *ci, const TValue *o) { - StkId p; - for (p = ci->u.l.base; p < ci->top; p++) - if (o == p) return 1; - return 0; -} - - -static const char *getupvalname (CallInfo *ci, const TValue *o, - const char **name) { - LClosure *c = ci_func(ci); - int i; - for (i = 0; i < c->nupvalues; i++) { - if (c->upvals[i]->v == o) { - *name = upvalname(c->p, i); - return "upvalue"; - } - } - return NULL; -} - - -l_noret luaG_typeerror (lua_State *L, const TValue *o, const char *op) { - CallInfo *ci = L->ci; - const char *name = NULL; - const char *t = objtypename(o); - const char *kind = NULL; - if (isLua(ci)) { - kind = getupvalname(ci, o, &name); /* check whether 'o' is an upvalue */ - if (!kind && isinstack(ci, o)) /* no? try a register */ - kind = getobjname(ci_func(ci)->p, currentpc(ci), - cast_int(o - ci->u.l.base), &name); - } - if (kind) - luaG_runerror(L, "attempt to %s %s " LUA_QS " (a %s value)", - op, kind, name, t); - else - luaG_runerror(L, "attempt to %s a %s value", op, t); -} - - -l_noret luaG_concaterror (lua_State *L, StkId p1, StkId p2) { - if (ttisstring(p1) || ttisnumber(p1)) p1 = p2; - lua_assert(!ttisstring(p1) && !ttisnumber(p1)); - luaG_typeerror(L, p1, "concatenate"); -} - - -l_noret luaG_aritherror (lua_State *L, const TValue *p1, const TValue *p2) { - TValue temp; - if (luaV_tonumber(p1, &temp) == NULL) - p2 = p1; /* first operand is wrong */ - luaG_typeerror(L, p2, "perform arithmetic on"); -} - - -l_noret luaG_ordererror (lua_State *L, const TValue *p1, const TValue *p2) { - const char *t1 = objtypename(p1); - const char *t2 = objtypename(p2); - if (t1 == t2) - luaG_runerror(L, "attempt to compare two %s values", t1); - else - luaG_runerror(L, "attempt to compare %s with %s", t1, t2); -} - - -static void addinfo (lua_State *L, const char *msg) { - CallInfo *ci = L->ci; - if (isLua(ci)) { /* is Lua code? */ - char buff[LUA_IDSIZE]; /* add file:line information */ - int line = currentline(ci); - TString *src = ci_func(ci)->p->source; - if (src) - luaO_chunkid(buff, getstr(src), LUA_IDSIZE); - else { /* no source available; use "?" instead */ - buff[0] = '?'; buff[1] = '\0'; - } - luaO_pushfstring(L, "%s:%d: %s", buff, line, msg); - } -} - - -l_noret luaG_errormsg (lua_State *L) { - if (L->errfunc != 0) { /* is there an error handling function? */ - StkId errfunc = restorestack(L, L->errfunc); - if (!ttisfunction(errfunc)) luaD_throw(L, LUA_ERRERR); - setobjs2s(L, L->top, L->top - 1); /* move argument */ - setobjs2s(L, L->top - 1, errfunc); /* push function */ - L->top++; - luaD_call(L, L->top - 2, 1, 0); /* call it */ - } - luaD_throw(L, LUA_ERRRUN); -} - - -l_noret luaG_runerror (lua_State *L, const char *fmt, ...) { - va_list argp; - va_start(argp, fmt); - addinfo(L, luaO_pushvfstring(L, fmt, argp)); - va_end(argp); - luaG_errormsg(L); -} - diff --git a/lib/lua-5.2/src/ldebug.h b/lib/lua-5.2/src/ldebug.h deleted file mode 100644 index 6445c76..0000000 --- a/lib/lua-5.2/src/ldebug.h +++ /dev/null @@ -1,34 +0,0 @@ -/* -** $Id: ldebug.h,v 2.7.1.1 2013/04/12 18:48:47 roberto Exp $ -** Auxiliary functions from Debug Interface module -** See Copyright Notice in lua.h -*/ - -#ifndef ldebug_h -#define ldebug_h - - -#include "lstate.h" - - -#define pcRel(pc, p) (cast(int, (pc) - (p)->code) - 1) - -#define getfuncline(f,pc) (((f)->lineinfo) ? (f)->lineinfo[pc] : 0) - -#define resethookcount(L) (L->hookcount = L->basehookcount) - -/* Active Lua function (given call info) */ -#define ci_func(ci) (clLvalue((ci)->func)) - - -LUAI_FUNC l_noret luaG_typeerror (lua_State *L, const TValue *o, - const char *opname); -LUAI_FUNC l_noret luaG_concaterror (lua_State *L, StkId p1, StkId p2); -LUAI_FUNC l_noret luaG_aritherror (lua_State *L, const TValue *p1, - const TValue *p2); -LUAI_FUNC l_noret luaG_ordererror (lua_State *L, const TValue *p1, - const TValue *p2); -LUAI_FUNC l_noret luaG_runerror (lua_State *L, const char *fmt, ...); -LUAI_FUNC l_noret luaG_errormsg (lua_State *L); - -#endif diff --git a/lib/lua-5.2/src/ldo.c b/lib/lua-5.2/src/ldo.c deleted file mode 100644 index e9dd5fa..0000000 --- a/lib/lua-5.2/src/ldo.c +++ /dev/null @@ -1,681 +0,0 @@ -/* -** $Id: ldo.c,v 2.108.1.3 2013/11/08 18:22:50 roberto Exp $ -** Stack and Call structure of Lua -** See Copyright Notice in lua.h -*/ - - -#include -#include -#include - -#define ldo_c -#define LUA_CORE - -#include "lua.h" - -#include "lapi.h" -#include "ldebug.h" -#include "ldo.h" -#include "lfunc.h" -#include "lgc.h" -#include "lmem.h" -#include "lobject.h" -#include "lopcodes.h" -#include "lparser.h" -#include "lstate.h" -#include "lstring.h" -#include "ltable.h" -#include "ltm.h" -#include "lundump.h" -#include "lvm.h" -#include "lzio.h" - - - - -/* -** {====================================================== -** Error-recovery functions -** ======================================================= -*/ - -/* -** LUAI_THROW/LUAI_TRY define how Lua does exception handling. By -** default, Lua handles errors with exceptions when compiling as -** C++ code, with _longjmp/_setjmp when asked to use them, and with -** longjmp/setjmp otherwise. -*/ -#if !defined(LUAI_THROW) - -#if defined(__cplusplus) && !defined(LUA_USE_LONGJMP) -/* C++ exceptions */ -#define LUAI_THROW(L,c) throw(c) -#define LUAI_TRY(L,c,a) \ - try { a } catch(...) { if ((c)->status == 0) (c)->status = -1; } -#define luai_jmpbuf int /* dummy variable */ - -#elif defined(LUA_USE_ULONGJMP) -/* in Unix, try _longjmp/_setjmp (more efficient) */ -#define LUAI_THROW(L,c) _longjmp((c)->b, 1) -#define LUAI_TRY(L,c,a) if (_setjmp((c)->b) == 0) { a } -#define luai_jmpbuf jmp_buf - -#else -/* default handling with long jumps */ -#define LUAI_THROW(L,c) longjmp((c)->b, 1) -#define LUAI_TRY(L,c,a) if (setjmp((c)->b) == 0) { a } -#define luai_jmpbuf jmp_buf - -#endif - -#endif - - - -/* chain list of long jump buffers */ -struct lua_longjmp { - struct lua_longjmp *previous; - luai_jmpbuf b; - volatile int status; /* error code */ -}; - - -static void seterrorobj (lua_State *L, int errcode, StkId oldtop) { - switch (errcode) { - case LUA_ERRMEM: { /* memory error? */ - setsvalue2s(L, oldtop, G(L)->memerrmsg); /* reuse preregistered msg. */ - break; - } - case LUA_ERRERR: { - setsvalue2s(L, oldtop, luaS_newliteral(L, "error in error handling")); - break; - } - default: { - setobjs2s(L, oldtop, L->top - 1); /* error message on current top */ - break; - } - } - L->top = oldtop + 1; -} - - -l_noret luaD_throw (lua_State *L, int errcode) { - if (L->errorJmp) { /* thread has an error handler? */ - L->errorJmp->status = errcode; /* set status */ - LUAI_THROW(L, L->errorJmp); /* jump to it */ - } - else { /* thread has no error handler */ - L->status = cast_byte(errcode); /* mark it as dead */ - if (G(L)->mainthread->errorJmp) { /* main thread has a handler? */ - setobjs2s(L, G(L)->mainthread->top++, L->top - 1); /* copy error obj. */ - luaD_throw(G(L)->mainthread, errcode); /* re-throw in main thread */ - } - else { /* no handler at all; abort */ - if (G(L)->panic) { /* panic function? */ - lua_unlock(L); - G(L)->panic(L); /* call it (last chance to jump out) */ - } - abort(); - } - } -} - - -int luaD_rawrunprotected (lua_State *L, Pfunc f, void *ud) { - unsigned short oldnCcalls = L->nCcalls; - struct lua_longjmp lj; - lj.status = LUA_OK; - lj.previous = L->errorJmp; /* chain new error handler */ - L->errorJmp = &lj; - LUAI_TRY(L, &lj, - (*f)(L, ud); - ); - L->errorJmp = lj.previous; /* restore old error handler */ - L->nCcalls = oldnCcalls; - return lj.status; -} - -/* }====================================================== */ - - -static void correctstack (lua_State *L, TValue *oldstack) { - CallInfo *ci; - GCObject *up; - L->top = (L->top - oldstack) + L->stack; - for (up = L->openupval; up != NULL; up = up->gch.next) - gco2uv(up)->v = (gco2uv(up)->v - oldstack) + L->stack; - for (ci = L->ci; ci != NULL; ci = ci->previous) { - ci->top = (ci->top - oldstack) + L->stack; - ci->func = (ci->func - oldstack) + L->stack; - if (isLua(ci)) - ci->u.l.base = (ci->u.l.base - oldstack) + L->stack; - } -} - - -/* some space for error handling */ -#define ERRORSTACKSIZE (LUAI_MAXSTACK + 200) - - -void luaD_reallocstack (lua_State *L, int newsize) { - TValue *oldstack = L->stack; - int lim = L->stacksize; - lua_assert(newsize <= LUAI_MAXSTACK || newsize == ERRORSTACKSIZE); - lua_assert(L->stack_last - L->stack == L->stacksize - EXTRA_STACK); - luaM_reallocvector(L, L->stack, L->stacksize, newsize, TValue); - for (; lim < newsize; lim++) - setnilvalue(L->stack + lim); /* erase new segment */ - L->stacksize = newsize; - L->stack_last = L->stack + newsize - EXTRA_STACK; - correctstack(L, oldstack); -} - - -void luaD_growstack (lua_State *L, int n) { - int size = L->stacksize; - if (size > LUAI_MAXSTACK) /* error after extra size? */ - luaD_throw(L, LUA_ERRERR); - else { - int needed = cast_int(L->top - L->stack) + n + EXTRA_STACK; - int newsize = 2 * size; - if (newsize > LUAI_MAXSTACK) newsize = LUAI_MAXSTACK; - if (newsize < needed) newsize = needed; - if (newsize > LUAI_MAXSTACK) { /* stack overflow? */ - luaD_reallocstack(L, ERRORSTACKSIZE); - luaG_runerror(L, "stack overflow"); - } - else - luaD_reallocstack(L, newsize); - } -} - - -static int stackinuse (lua_State *L) { - CallInfo *ci; - StkId lim = L->top; - for (ci = L->ci; ci != NULL; ci = ci->previous) { - lua_assert(ci->top <= L->stack_last); - if (lim < ci->top) lim = ci->top; - } - return cast_int(lim - L->stack) + 1; /* part of stack in use */ -} - - -void luaD_shrinkstack (lua_State *L) { - int inuse = stackinuse(L); - int goodsize = inuse + (inuse / 8) + 2*EXTRA_STACK; - if (goodsize > LUAI_MAXSTACK) goodsize = LUAI_MAXSTACK; - if (inuse > LUAI_MAXSTACK || /* handling stack overflow? */ - goodsize >= L->stacksize) /* would grow instead of shrink? */ - condmovestack(L); /* don't change stack (change only for debugging) */ - else - luaD_reallocstack(L, goodsize); /* shrink it */ -} - - -void luaD_hook (lua_State *L, int event, int line) { - lua_Hook hook = L->hook; - if (hook && L->allowhook) { - CallInfo *ci = L->ci; - ptrdiff_t top = savestack(L, L->top); - ptrdiff_t ci_top = savestack(L, ci->top); - lua_Debug ar; - ar.event = event; - ar.currentline = line; - ar.i_ci = ci; - luaD_checkstack(L, LUA_MINSTACK); /* ensure minimum stack size */ - ci->top = L->top + LUA_MINSTACK; - lua_assert(ci->top <= L->stack_last); - L->allowhook = 0; /* cannot call hooks inside a hook */ - ci->callstatus |= CIST_HOOKED; - lua_unlock(L); - (*hook)(L, &ar); - lua_lock(L); - lua_assert(!L->allowhook); - L->allowhook = 1; - ci->top = restorestack(L, ci_top); - L->top = restorestack(L, top); - ci->callstatus &= ~CIST_HOOKED; - } -} - - -static void callhook (lua_State *L, CallInfo *ci) { - int hook = LUA_HOOKCALL; - ci->u.l.savedpc++; /* hooks assume 'pc' is already incremented */ - if (isLua(ci->previous) && - GET_OPCODE(*(ci->previous->u.l.savedpc - 1)) == OP_TAILCALL) { - ci->callstatus |= CIST_TAIL; - hook = LUA_HOOKTAILCALL; - } - luaD_hook(L, hook, -1); - ci->u.l.savedpc--; /* correct 'pc' */ -} - - -static StkId adjust_varargs (lua_State *L, Proto *p, int actual) { - int i; - int nfixargs = p->numparams; - StkId base, fixed; - lua_assert(actual >= nfixargs); - /* move fixed parameters to final position */ - luaD_checkstack(L, p->maxstacksize); /* check again for new 'base' */ - fixed = L->top - actual; /* first fixed argument */ - base = L->top; /* final position of first argument */ - for (i=0; itop++, fixed + i); - setnilvalue(fixed + i); - } - return base; -} - - -static StkId tryfuncTM (lua_State *L, StkId func) { - const TValue *tm = luaT_gettmbyobj(L, func, TM_CALL); - StkId p; - ptrdiff_t funcr = savestack(L, func); - if (!ttisfunction(tm)) - luaG_typeerror(L, func, "call"); - /* Open a hole inside the stack at `func' */ - for (p = L->top; p > func; p--) setobjs2s(L, p, p-1); - incr_top(L); - func = restorestack(L, funcr); /* previous call may change stack */ - setobj2s(L, func, tm); /* tag method is the new function to be called */ - return func; -} - - - -#define next_ci(L) (L->ci = (L->ci->next ? L->ci->next : luaE_extendCI(L))) - - -/* -** returns true if function has been executed (C function) -*/ -int luaD_precall (lua_State *L, StkId func, int nresults) { - lua_CFunction f; - CallInfo *ci; - int n; /* number of arguments (Lua) or returns (C) */ - ptrdiff_t funcr = savestack(L, func); - switch (ttype(func)) { - case LUA_TLCF: /* light C function */ - f = fvalue(func); - goto Cfunc; - case LUA_TCCL: { /* C closure */ - f = clCvalue(func)->f; - Cfunc: - luaD_checkstack(L, LUA_MINSTACK); /* ensure minimum stack size */ - ci = next_ci(L); /* now 'enter' new function */ - ci->nresults = nresults; - ci->func = restorestack(L, funcr); - ci->top = L->top + LUA_MINSTACK; - lua_assert(ci->top <= L->stack_last); - ci->callstatus = 0; - luaC_checkGC(L); /* stack grow uses memory */ - if (L->hookmask & LUA_MASKCALL) - luaD_hook(L, LUA_HOOKCALL, -1); - lua_unlock(L); - n = (*f)(L); /* do the actual call */ - lua_lock(L); - api_checknelems(L, n); - luaD_poscall(L, L->top - n); - return 1; - } - case LUA_TLCL: { /* Lua function: prepare its call */ - StkId base; - Proto *p = clLvalue(func)->p; - n = cast_int(L->top - func) - 1; /* number of real arguments */ - luaD_checkstack(L, p->maxstacksize); - for (; n < p->numparams; n++) - setnilvalue(L->top++); /* complete missing arguments */ - if (!p->is_vararg) { - func = restorestack(L, funcr); - base = func + 1; - } - else { - base = adjust_varargs(L, p, n); - func = restorestack(L, funcr); /* previous call can change stack */ - } - ci = next_ci(L); /* now 'enter' new function */ - ci->nresults = nresults; - ci->func = func; - ci->u.l.base = base; - ci->top = base + p->maxstacksize; - lua_assert(ci->top <= L->stack_last); - ci->u.l.savedpc = p->code; /* starting point */ - ci->callstatus = CIST_LUA; - L->top = ci->top; - luaC_checkGC(L); /* stack grow uses memory */ - if (L->hookmask & LUA_MASKCALL) - callhook(L, ci); - return 0; - } - default: { /* not a function */ - func = tryfuncTM(L, func); /* retry with 'function' tag method */ - return luaD_precall(L, func, nresults); /* now it must be a function */ - } - } -} - - -int luaD_poscall (lua_State *L, StkId firstResult) { - StkId res; - int wanted, i; - CallInfo *ci = L->ci; - if (L->hookmask & (LUA_MASKRET | LUA_MASKLINE)) { - if (L->hookmask & LUA_MASKRET) { - ptrdiff_t fr = savestack(L, firstResult); /* hook may change stack */ - luaD_hook(L, LUA_HOOKRET, -1); - firstResult = restorestack(L, fr); - } - L->oldpc = ci->previous->u.l.savedpc; /* 'oldpc' for caller function */ - } - res = ci->func; /* res == final position of 1st result */ - wanted = ci->nresults; - L->ci = ci = ci->previous; /* back to caller */ - /* move results to correct place */ - for (i = wanted; i != 0 && firstResult < L->top; i--) - setobjs2s(L, res++, firstResult++); - while (i-- > 0) - setnilvalue(res++); - L->top = res; - return (wanted - LUA_MULTRET); /* 0 iff wanted == LUA_MULTRET */ -} - - -/* -** Call a function (C or Lua). The function to be called is at *func. -** The arguments are on the stack, right after the function. -** When returns, all the results are on the stack, starting at the original -** function position. -*/ -void luaD_call (lua_State *L, StkId func, int nResults, int allowyield) { - if (++L->nCcalls >= LUAI_MAXCCALLS) { - if (L->nCcalls == LUAI_MAXCCALLS) - luaG_runerror(L, "C stack overflow"); - else if (L->nCcalls >= (LUAI_MAXCCALLS + (LUAI_MAXCCALLS>>3))) - luaD_throw(L, LUA_ERRERR); /* error while handing stack error */ - } - if (!allowyield) L->nny++; - if (!luaD_precall(L, func, nResults)) /* is a Lua function? */ - luaV_execute(L); /* call it */ - if (!allowyield) L->nny--; - L->nCcalls--; -} - - -static void finishCcall (lua_State *L) { - CallInfo *ci = L->ci; - int n; - lua_assert(ci->u.c.k != NULL); /* must have a continuation */ - lua_assert(L->nny == 0); - if (ci->callstatus & CIST_YPCALL) { /* was inside a pcall? */ - ci->callstatus &= ~CIST_YPCALL; /* finish 'lua_pcall' */ - L->errfunc = ci->u.c.old_errfunc; - } - /* finish 'lua_callk'/'lua_pcall' */ - adjustresults(L, ci->nresults); - /* call continuation function */ - if (!(ci->callstatus & CIST_STAT)) /* no call status? */ - ci->u.c.status = LUA_YIELD; /* 'default' status */ - lua_assert(ci->u.c.status != LUA_OK); - ci->callstatus = (ci->callstatus & ~(CIST_YPCALL | CIST_STAT)) | CIST_YIELDED; - lua_unlock(L); - n = (*ci->u.c.k)(L); - lua_lock(L); - api_checknelems(L, n); - /* finish 'luaD_precall' */ - luaD_poscall(L, L->top - n); -} - - -static void unroll (lua_State *L, void *ud) { - UNUSED(ud); - for (;;) { - if (L->ci == &L->base_ci) /* stack is empty? */ - return; /* coroutine finished normally */ - if (!isLua(L->ci)) /* C function? */ - finishCcall(L); - else { /* Lua function */ - luaV_finishOp(L); /* finish interrupted instruction */ - luaV_execute(L); /* execute down to higher C 'boundary' */ - } - } -} - - -/* -** check whether thread has a suspended protected call -*/ -static CallInfo *findpcall (lua_State *L) { - CallInfo *ci; - for (ci = L->ci; ci != NULL; ci = ci->previous) { /* search for a pcall */ - if (ci->callstatus & CIST_YPCALL) - return ci; - } - return NULL; /* no pending pcall */ -} - - -static int recover (lua_State *L, int status) { - StkId oldtop; - CallInfo *ci = findpcall(L); - if (ci == NULL) return 0; /* no recovery point */ - /* "finish" luaD_pcall */ - oldtop = restorestack(L, ci->extra); - luaF_close(L, oldtop); - seterrorobj(L, status, oldtop); - L->ci = ci; - L->allowhook = ci->u.c.old_allowhook; - L->nny = 0; /* should be zero to be yieldable */ - luaD_shrinkstack(L); - L->errfunc = ci->u.c.old_errfunc; - ci->callstatus |= CIST_STAT; /* call has error status */ - ci->u.c.status = status; /* (here it is) */ - return 1; /* continue running the coroutine */ -} - - -/* -** signal an error in the call to 'resume', not in the execution of the -** coroutine itself. (Such errors should not be handled by any coroutine -** error handler and should not kill the coroutine.) -*/ -static l_noret resume_error (lua_State *L, const char *msg, StkId firstArg) { - L->top = firstArg; /* remove args from the stack */ - setsvalue2s(L, L->top, luaS_new(L, msg)); /* push error message */ - api_incr_top(L); - luaD_throw(L, -1); /* jump back to 'lua_resume' */ -} - - -/* -** do the work for 'lua_resume' in protected mode -*/ -static void resume (lua_State *L, void *ud) { - int nCcalls = L->nCcalls; - StkId firstArg = cast(StkId, ud); - CallInfo *ci = L->ci; - if (nCcalls >= LUAI_MAXCCALLS) - resume_error(L, "C stack overflow", firstArg); - if (L->status == LUA_OK) { /* may be starting a coroutine */ - if (ci != &L->base_ci) /* not in base level? */ - resume_error(L, "cannot resume non-suspended coroutine", firstArg); - /* coroutine is in base level; start running it */ - if (!luaD_precall(L, firstArg - 1, LUA_MULTRET)) /* Lua function? */ - luaV_execute(L); /* call it */ - } - else if (L->status != LUA_YIELD) - resume_error(L, "cannot resume dead coroutine", firstArg); - else { /* resuming from previous yield */ - L->status = LUA_OK; - ci->func = restorestack(L, ci->extra); - if (isLua(ci)) /* yielded inside a hook? */ - luaV_execute(L); /* just continue running Lua code */ - else { /* 'common' yield */ - if (ci->u.c.k != NULL) { /* does it have a continuation? */ - int n; - ci->u.c.status = LUA_YIELD; /* 'default' status */ - ci->callstatus |= CIST_YIELDED; - lua_unlock(L); - n = (*ci->u.c.k)(L); /* call continuation */ - lua_lock(L); - api_checknelems(L, n); - firstArg = L->top - n; /* yield results come from continuation */ - } - luaD_poscall(L, firstArg); /* finish 'luaD_precall' */ - } - unroll(L, NULL); - } - lua_assert(nCcalls == L->nCcalls); -} - - -LUA_API int lua_resume (lua_State *L, lua_State *from, int nargs) { - int status; - int oldnny = L->nny; /* save 'nny' */ - lua_lock(L); - luai_userstateresume(L, nargs); - L->nCcalls = (from) ? from->nCcalls + 1 : 1; - L->nny = 0; /* allow yields */ - api_checknelems(L, (L->status == LUA_OK) ? nargs + 1 : nargs); - status = luaD_rawrunprotected(L, resume, L->top - nargs); - if (status == -1) /* error calling 'lua_resume'? */ - status = LUA_ERRRUN; - else { /* yield or regular error */ - while (status != LUA_OK && status != LUA_YIELD) { /* error? */ - if (recover(L, status)) /* recover point? */ - status = luaD_rawrunprotected(L, unroll, NULL); /* run continuation */ - else { /* unrecoverable error */ - L->status = cast_byte(status); /* mark thread as `dead' */ - seterrorobj(L, status, L->top); - L->ci->top = L->top; - break; - } - } - lua_assert(status == L->status); - } - L->nny = oldnny; /* restore 'nny' */ - L->nCcalls--; - lua_assert(L->nCcalls == ((from) ? from->nCcalls : 0)); - lua_unlock(L); - return status; -} - - -LUA_API int lua_yieldk (lua_State *L, int nresults, int ctx, lua_CFunction k) { - CallInfo *ci = L->ci; - luai_userstateyield(L, nresults); - lua_lock(L); - api_checknelems(L, nresults); - if (L->nny > 0) { - if (L != G(L)->mainthread) - luaG_runerror(L, "attempt to yield across a C-call boundary"); - else - luaG_runerror(L, "attempt to yield from outside a coroutine"); - } - L->status = LUA_YIELD; - ci->extra = savestack(L, ci->func); /* save current 'func' */ - if (isLua(ci)) { /* inside a hook? */ - api_check(L, k == NULL, "hooks cannot continue after yielding"); - } - else { - if ((ci->u.c.k = k) != NULL) /* is there a continuation? */ - ci->u.c.ctx = ctx; /* save context */ - ci->func = L->top - nresults - 1; /* protect stack below results */ - luaD_throw(L, LUA_YIELD); - } - lua_assert(ci->callstatus & CIST_HOOKED); /* must be inside a hook */ - lua_unlock(L); - return 0; /* return to 'luaD_hook' */ -} - - -int luaD_pcall (lua_State *L, Pfunc func, void *u, - ptrdiff_t old_top, ptrdiff_t ef) { - int status; - CallInfo *old_ci = L->ci; - lu_byte old_allowhooks = L->allowhook; - unsigned short old_nny = L->nny; - ptrdiff_t old_errfunc = L->errfunc; - L->errfunc = ef; - status = luaD_rawrunprotected(L, func, u); - if (status != LUA_OK) { /* an error occurred? */ - StkId oldtop = restorestack(L, old_top); - luaF_close(L, oldtop); /* close possible pending closures */ - seterrorobj(L, status, oldtop); - L->ci = old_ci; - L->allowhook = old_allowhooks; - L->nny = old_nny; - luaD_shrinkstack(L); - } - L->errfunc = old_errfunc; - return status; -} - - - -/* -** Execute a protected parser. -*/ -struct SParser { /* data to `f_parser' */ - ZIO *z; - Mbuffer buff; /* dynamic structure used by the scanner */ - Dyndata dyd; /* dynamic structures used by the parser */ - const char *mode; - const char *name; -}; - - -static void checkmode (lua_State *L, const char *mode, const char *x) { - if (mode && strchr(mode, x[0]) == NULL) { - luaO_pushfstring(L, - "attempt to load a %s chunk (mode is " LUA_QS ")", x, mode); - luaD_throw(L, LUA_ERRSYNTAX); - } -} - - -static void f_parser (lua_State *L, void *ud) { - int i; - Closure *cl; - struct SParser *p = cast(struct SParser *, ud); - int c = zgetc(p->z); /* read first character */ - if (c == LUA_SIGNATURE[0]) { - checkmode(L, p->mode, "binary"); - cl = luaU_undump(L, p->z, &p->buff, p->name); - } - else { - checkmode(L, p->mode, "text"); - cl = luaY_parser(L, p->z, &p->buff, &p->dyd, p->name, c); - } - lua_assert(cl->l.nupvalues == cl->l.p->sizeupvalues); - for (i = 0; i < cl->l.nupvalues; i++) { /* initialize upvalues */ - UpVal *up = luaF_newupval(L); - cl->l.upvals[i] = up; - luaC_objbarrier(L, cl, up); - } -} - - -int luaD_protectedparser (lua_State *L, ZIO *z, const char *name, - const char *mode) { - struct SParser p; - int status; - L->nny++; /* cannot yield during parsing */ - p.z = z; p.name = name; p.mode = mode; - p.dyd.actvar.arr = NULL; p.dyd.actvar.size = 0; - p.dyd.gt.arr = NULL; p.dyd.gt.size = 0; - p.dyd.label.arr = NULL; p.dyd.label.size = 0; - luaZ_initbuffer(L, &p.buff); - status = luaD_pcall(L, f_parser, &p, savestack(L, L->top), L->errfunc); - luaZ_freebuffer(L, &p.buff); - luaM_freearray(L, p.dyd.actvar.arr, p.dyd.actvar.size); - luaM_freearray(L, p.dyd.gt.arr, p.dyd.gt.size); - luaM_freearray(L, p.dyd.label.arr, p.dyd.label.size); - L->nny--; - return status; -} - - diff --git a/lib/lua-5.2/src/ldo.h b/lib/lua-5.2/src/ldo.h deleted file mode 100644 index d3d3082..0000000 --- a/lib/lua-5.2/src/ldo.h +++ /dev/null @@ -1,46 +0,0 @@ -/* -** $Id: ldo.h,v 2.20.1.1 2013/04/12 18:48:47 roberto Exp $ -** Stack and Call structure of Lua -** See Copyright Notice in lua.h -*/ - -#ifndef ldo_h -#define ldo_h - - -#include "lobject.h" -#include "lstate.h" -#include "lzio.h" - - -#define luaD_checkstack(L,n) if (L->stack_last - L->top <= (n)) \ - luaD_growstack(L, n); else condmovestack(L); - - -#define incr_top(L) {L->top++; luaD_checkstack(L,0);} - -#define savestack(L,p) ((char *)(p) - (char *)L->stack) -#define restorestack(L,n) ((TValue *)((char *)L->stack + (n))) - - -/* type of protected functions, to be ran by `runprotected' */ -typedef void (*Pfunc) (lua_State *L, void *ud); - -LUAI_FUNC int luaD_protectedparser (lua_State *L, ZIO *z, const char *name, - const char *mode); -LUAI_FUNC void luaD_hook (lua_State *L, int event, int line); -LUAI_FUNC int luaD_precall (lua_State *L, StkId func, int nresults); -LUAI_FUNC void luaD_call (lua_State *L, StkId func, int nResults, - int allowyield); -LUAI_FUNC int luaD_pcall (lua_State *L, Pfunc func, void *u, - ptrdiff_t oldtop, ptrdiff_t ef); -LUAI_FUNC int luaD_poscall (lua_State *L, StkId firstResult); -LUAI_FUNC void luaD_reallocstack (lua_State *L, int newsize); -LUAI_FUNC void luaD_growstack (lua_State *L, int n); -LUAI_FUNC void luaD_shrinkstack (lua_State *L); - -LUAI_FUNC l_noret luaD_throw (lua_State *L, int errcode); -LUAI_FUNC int luaD_rawrunprotected (lua_State *L, Pfunc f, void *ud); - -#endif - diff --git a/lib/lua-5.2/src/ldump.c b/lib/lua-5.2/src/ldump.c deleted file mode 100644 index 61fa2cd..0000000 --- a/lib/lua-5.2/src/ldump.c +++ /dev/null @@ -1,173 +0,0 @@ -/* -** $Id: ldump.c,v 2.17.1.1 2013/04/12 18:48:47 roberto Exp $ -** save precompiled Lua chunks -** See Copyright Notice in lua.h -*/ - -#include - -#define ldump_c -#define LUA_CORE - -#include "lua.h" - -#include "lobject.h" -#include "lstate.h" -#include "lundump.h" - -typedef struct { - lua_State* L; - lua_Writer writer; - void* data; - int strip; - int status; -} DumpState; - -#define DumpMem(b,n,size,D) DumpBlock(b,(n)*(size),D) -#define DumpVar(x,D) DumpMem(&x,1,sizeof(x),D) - -static void DumpBlock(const void* b, size_t size, DumpState* D) -{ - if (D->status==0) - { - lua_unlock(D->L); - D->status=(*D->writer)(D->L,b,size,D->data); - lua_lock(D->L); - } -} - -static void DumpChar(int y, DumpState* D) -{ - char x=(char)y; - DumpVar(x,D); -} - -static void DumpInt(int x, DumpState* D) -{ - DumpVar(x,D); -} - -static void DumpNumber(lua_Number x, DumpState* D) -{ - DumpVar(x,D); -} - -static void DumpVector(const void* b, int n, size_t size, DumpState* D) -{ - DumpInt(n,D); - DumpMem(b,n,size,D); -} - -static void DumpString(const TString* s, DumpState* D) -{ - if (s==NULL) - { - size_t size=0; - DumpVar(size,D); - } - else - { - size_t size=s->tsv.len+1; /* include trailing '\0' */ - DumpVar(size,D); - DumpBlock(getstr(s),size*sizeof(char),D); - } -} - -#define DumpCode(f,D) DumpVector(f->code,f->sizecode,sizeof(Instruction),D) - -static void DumpFunction(const Proto* f, DumpState* D); - -static void DumpConstants(const Proto* f, DumpState* D) -{ - int i,n=f->sizek; - DumpInt(n,D); - for (i=0; ik[i]; - DumpChar(ttypenv(o),D); - switch (ttypenv(o)) - { - case LUA_TNIL: - break; - case LUA_TBOOLEAN: - DumpChar(bvalue(o),D); - break; - case LUA_TNUMBER: - DumpNumber(nvalue(o),D); - break; - case LUA_TSTRING: - DumpString(rawtsvalue(o),D); - break; - default: lua_assert(0); - } - } - n=f->sizep; - DumpInt(n,D); - for (i=0; ip[i],D); -} - -static void DumpUpvalues(const Proto* f, DumpState* D) -{ - int i,n=f->sizeupvalues; - DumpInt(n,D); - for (i=0; iupvalues[i].instack,D); - DumpChar(f->upvalues[i].idx,D); - } -} - -static void DumpDebug(const Proto* f, DumpState* D) -{ - int i,n; - DumpString((D->strip) ? NULL : f->source,D); - n= (D->strip) ? 0 : f->sizelineinfo; - DumpVector(f->lineinfo,n,sizeof(int),D); - n= (D->strip) ? 0 : f->sizelocvars; - DumpInt(n,D); - for (i=0; ilocvars[i].varname,D); - DumpInt(f->locvars[i].startpc,D); - DumpInt(f->locvars[i].endpc,D); - } - n= (D->strip) ? 0 : f->sizeupvalues; - DumpInt(n,D); - for (i=0; iupvalues[i].name,D); -} - -static void DumpFunction(const Proto* f, DumpState* D) -{ - DumpInt(f->linedefined,D); - DumpInt(f->lastlinedefined,D); - DumpChar(f->numparams,D); - DumpChar(f->is_vararg,D); - DumpChar(f->maxstacksize,D); - DumpCode(f,D); - DumpConstants(f,D); - DumpUpvalues(f,D); - DumpDebug(f,D); -} - -static void DumpHeader(DumpState* D) -{ - lu_byte h[LUAC_HEADERSIZE]; - luaU_header(h); - DumpBlock(h,LUAC_HEADERSIZE,D); -} - -/* -** dump Lua function as precompiled chunk -*/ -int luaU_dump (lua_State* L, const Proto* f, lua_Writer w, void* data, int strip) -{ - DumpState D; - D.L=L; - D.writer=w; - D.data=data; - D.strip=strip; - D.status=0; - DumpHeader(&D); - DumpFunction(f,&D); - return D.status; -} diff --git a/lib/lua-5.2/src/lfunc.c b/lib/lua-5.2/src/lfunc.c deleted file mode 100644 index e90e152..0000000 --- a/lib/lua-5.2/src/lfunc.c +++ /dev/null @@ -1,161 +0,0 @@ -/* -** $Id: lfunc.c,v 2.30.1.1 2013/04/12 18:48:47 roberto Exp $ -** Auxiliary functions to manipulate prototypes and closures -** See Copyright Notice in lua.h -*/ - - -#include - -#define lfunc_c -#define LUA_CORE - -#include "lua.h" - -#include "lfunc.h" -#include "lgc.h" -#include "lmem.h" -#include "lobject.h" -#include "lstate.h" - - - -Closure *luaF_newCclosure (lua_State *L, int n) { - Closure *c = &luaC_newobj(L, LUA_TCCL, sizeCclosure(n), NULL, 0)->cl; - c->c.nupvalues = cast_byte(n); - return c; -} - - -Closure *luaF_newLclosure (lua_State *L, int n) { - Closure *c = &luaC_newobj(L, LUA_TLCL, sizeLclosure(n), NULL, 0)->cl; - c->l.p = NULL; - c->l.nupvalues = cast_byte(n); - while (n--) c->l.upvals[n] = NULL; - return c; -} - - -UpVal *luaF_newupval (lua_State *L) { - UpVal *uv = &luaC_newobj(L, LUA_TUPVAL, sizeof(UpVal), NULL, 0)->uv; - uv->v = &uv->u.value; - setnilvalue(uv->v); - return uv; -} - - -UpVal *luaF_findupval (lua_State *L, StkId level) { - global_State *g = G(L); - GCObject **pp = &L->openupval; - UpVal *p; - UpVal *uv; - while (*pp != NULL && (p = gco2uv(*pp))->v >= level) { - GCObject *o = obj2gco(p); - lua_assert(p->v != &p->u.value); - lua_assert(!isold(o) || isold(obj2gco(L))); - if (p->v == level) { /* found a corresponding upvalue? */ - if (isdead(g, o)) /* is it dead? */ - changewhite(o); /* resurrect it */ - return p; - } - pp = &p->next; - } - /* not found: create a new one */ - uv = &luaC_newobj(L, LUA_TUPVAL, sizeof(UpVal), pp, 0)->uv; - uv->v = level; /* current value lives in the stack */ - uv->u.l.prev = &g->uvhead; /* double link it in `uvhead' list */ - uv->u.l.next = g->uvhead.u.l.next; - uv->u.l.next->u.l.prev = uv; - g->uvhead.u.l.next = uv; - lua_assert(uv->u.l.next->u.l.prev == uv && uv->u.l.prev->u.l.next == uv); - return uv; -} - - -static void unlinkupval (UpVal *uv) { - lua_assert(uv->u.l.next->u.l.prev == uv && uv->u.l.prev->u.l.next == uv); - uv->u.l.next->u.l.prev = uv->u.l.prev; /* remove from `uvhead' list */ - uv->u.l.prev->u.l.next = uv->u.l.next; -} - - -void luaF_freeupval (lua_State *L, UpVal *uv) { - if (uv->v != &uv->u.value) /* is it open? */ - unlinkupval(uv); /* remove from open list */ - luaM_free(L, uv); /* free upvalue */ -} - - -void luaF_close (lua_State *L, StkId level) { - UpVal *uv; - global_State *g = G(L); - while (L->openupval != NULL && (uv = gco2uv(L->openupval))->v >= level) { - GCObject *o = obj2gco(uv); - lua_assert(!isblack(o) && uv->v != &uv->u.value); - L->openupval = uv->next; /* remove from `open' list */ - if (isdead(g, o)) - luaF_freeupval(L, uv); /* free upvalue */ - else { - unlinkupval(uv); /* remove upvalue from 'uvhead' list */ - setobj(L, &uv->u.value, uv->v); /* move value to upvalue slot */ - uv->v = &uv->u.value; /* now current value lives here */ - gch(o)->next = g->allgc; /* link upvalue into 'allgc' list */ - g->allgc = o; - luaC_checkupvalcolor(g, uv); - } - } -} - - -Proto *luaF_newproto (lua_State *L) { - Proto *f = &luaC_newobj(L, LUA_TPROTO, sizeof(Proto), NULL, 0)->p; - f->k = NULL; - f->sizek = 0; - f->p = NULL; - f->sizep = 0; - f->code = NULL; - f->cache = NULL; - f->sizecode = 0; - f->lineinfo = NULL; - f->sizelineinfo = 0; - f->upvalues = NULL; - f->sizeupvalues = 0; - f->numparams = 0; - f->is_vararg = 0; - f->maxstacksize = 0; - f->locvars = NULL; - f->sizelocvars = 0; - f->linedefined = 0; - f->lastlinedefined = 0; - f->source = NULL; - return f; -} - - -void luaF_freeproto (lua_State *L, Proto *f) { - luaM_freearray(L, f->code, f->sizecode); - luaM_freearray(L, f->p, f->sizep); - luaM_freearray(L, f->k, f->sizek); - luaM_freearray(L, f->lineinfo, f->sizelineinfo); - luaM_freearray(L, f->locvars, f->sizelocvars); - luaM_freearray(L, f->upvalues, f->sizeupvalues); - luaM_free(L, f); -} - - -/* -** Look for n-th local variable at line `line' in function `func'. -** Returns NULL if not found. -*/ -const char *luaF_getlocalname (const Proto *f, int local_number, int pc) { - int i; - for (i = 0; isizelocvars && f->locvars[i].startpc <= pc; i++) { - if (pc < f->locvars[i].endpc) { /* is variable active? */ - local_number--; - if (local_number == 0) - return getstr(f->locvars[i].varname); - } - } - return NULL; /* not found */ -} - diff --git a/lib/lua-5.2/src/lfunc.h b/lib/lua-5.2/src/lfunc.h deleted file mode 100644 index ca0d3a3..0000000 --- a/lib/lua-5.2/src/lfunc.h +++ /dev/null @@ -1,33 +0,0 @@ -/* -** $Id: lfunc.h,v 2.8.1.1 2013/04/12 18:48:47 roberto Exp $ -** Auxiliary functions to manipulate prototypes and closures -** See Copyright Notice in lua.h -*/ - -#ifndef lfunc_h -#define lfunc_h - - -#include "lobject.h" - - -#define sizeCclosure(n) (cast(int, sizeof(CClosure)) + \ - cast(int, sizeof(TValue)*((n)-1))) - -#define sizeLclosure(n) (cast(int, sizeof(LClosure)) + \ - cast(int, sizeof(TValue *)*((n)-1))) - - -LUAI_FUNC Proto *luaF_newproto (lua_State *L); -LUAI_FUNC Closure *luaF_newCclosure (lua_State *L, int nelems); -LUAI_FUNC Closure *luaF_newLclosure (lua_State *L, int nelems); -LUAI_FUNC UpVal *luaF_newupval (lua_State *L); -LUAI_FUNC UpVal *luaF_findupval (lua_State *L, StkId level); -LUAI_FUNC void luaF_close (lua_State *L, StkId level); -LUAI_FUNC void luaF_freeproto (lua_State *L, Proto *f); -LUAI_FUNC void luaF_freeupval (lua_State *L, UpVal *uv); -LUAI_FUNC const char *luaF_getlocalname (const Proto *func, int local_number, - int pc); - - -#endif diff --git a/lib/lua-5.2/src/lgc.c b/lib/lua-5.2/src/lgc.c deleted file mode 100644 index 553fd17..0000000 --- a/lib/lua-5.2/src/lgc.c +++ /dev/null @@ -1,1220 +0,0 @@ -/* -** $Id: lgc.c,v 2.140.1.3 2014/09/01 16:55:08 roberto Exp $ -** Garbage Collector -** See Copyright Notice in lua.h -*/ - -#include - -#define lgc_c -#define LUA_CORE - -#include "lua.h" - -#include "ldebug.h" -#include "ldo.h" -#include "lfunc.h" -#include "lgc.h" -#include "lmem.h" -#include "lobject.h" -#include "lstate.h" -#include "lstring.h" -#include "ltable.h" -#include "ltm.h" - - - -/* -** cost of sweeping one element (the size of a small object divided -** by some adjust for the sweep speed) -*/ -#define GCSWEEPCOST ((sizeof(TString) + 4) / 4) - -/* maximum number of elements to sweep in each single step */ -#define GCSWEEPMAX (cast_int((GCSTEPSIZE / GCSWEEPCOST) / 4)) - -/* maximum number of finalizers to call in each GC step */ -#define GCFINALIZENUM 4 - - -/* -** macro to adjust 'stepmul': 'stepmul' is actually used like -** 'stepmul / STEPMULADJ' (value chosen by tests) -*/ -#define STEPMULADJ 200 - - -/* -** macro to adjust 'pause': 'pause' is actually used like -** 'pause / PAUSEADJ' (value chosen by tests) -*/ -#define PAUSEADJ 100 - - -/* -** 'makewhite' erases all color bits plus the old bit and then -** sets only the current white bit -*/ -#define maskcolors (~(bit2mask(BLACKBIT, OLDBIT) | WHITEBITS)) -#define makewhite(g,x) \ - (gch(x)->marked = cast_byte((gch(x)->marked & maskcolors) | luaC_white(g))) - -#define white2gray(x) resetbits(gch(x)->marked, WHITEBITS) -#define black2gray(x) resetbit(gch(x)->marked, BLACKBIT) - - -#define isfinalized(x) testbit(gch(x)->marked, FINALIZEDBIT) - -#define checkdeadkey(n) lua_assert(!ttisdeadkey(gkey(n)) || ttisnil(gval(n))) - - -#define checkconsistency(obj) \ - lua_longassert(!iscollectable(obj) || righttt(obj)) - - -#define markvalue(g,o) { checkconsistency(o); \ - if (valiswhite(o)) reallymarkobject(g,gcvalue(o)); } - -#define markobject(g,t) { if ((t) && iswhite(obj2gco(t))) \ - reallymarkobject(g, obj2gco(t)); } - -static void reallymarkobject (global_State *g, GCObject *o); - - -/* -** {====================================================== -** Generic functions -** ======================================================= -*/ - - -/* -** one after last element in a hash array -*/ -#define gnodelast(h) gnode(h, cast(size_t, sizenode(h))) - - -/* -** link table 'h' into list pointed by 'p' -*/ -#define linktable(h,p) ((h)->gclist = *(p), *(p) = obj2gco(h)) - - -/* -** if key is not marked, mark its entry as dead (therefore removing it -** from the table) -*/ -static void removeentry (Node *n) { - lua_assert(ttisnil(gval(n))); - if (valiswhite(gkey(n))) - setdeadvalue(gkey(n)); /* unused and unmarked key; remove it */ -} - - -/* -** tells whether a key or value can be cleared from a weak -** table. Non-collectable objects are never removed from weak -** tables. Strings behave as `values', so are never removed too. for -** other objects: if really collected, cannot keep them; for objects -** being finalized, keep them in keys, but not in values -*/ -static int iscleared (global_State *g, const TValue *o) { - if (!iscollectable(o)) return 0; - else if (ttisstring(o)) { - markobject(g, rawtsvalue(o)); /* strings are `values', so are never weak */ - return 0; - } - else return iswhite(gcvalue(o)); -} - - -/* -** barrier that moves collector forward, that is, mark the white object -** being pointed by a black object. -*/ -void luaC_barrier_ (lua_State *L, GCObject *o, GCObject *v) { - global_State *g = G(L); - lua_assert(isblack(o) && iswhite(v) && !isdead(g, v) && !isdead(g, o)); - lua_assert(g->gcstate != GCSpause); - lua_assert(gch(o)->tt != LUA_TTABLE); - if (keepinvariantout(g)) /* must keep invariant? */ - reallymarkobject(g, v); /* restore invariant */ - else { /* sweep phase */ - lua_assert(issweepphase(g)); - makewhite(g, o); /* mark main obj. as white to avoid other barriers */ - } -} - - -/* -** barrier that moves collector backward, that is, mark the black object -** pointing to a white object as gray again. (Current implementation -** only works for tables; access to 'gclist' is not uniform across -** different types.) -*/ -void luaC_barrierback_ (lua_State *L, GCObject *o) { - global_State *g = G(L); - lua_assert(isblack(o) && !isdead(g, o) && gch(o)->tt == LUA_TTABLE); - black2gray(o); /* make object gray (again) */ - gco2t(o)->gclist = g->grayagain; - g->grayagain = o; -} - - -/* -** barrier for prototypes. When creating first closure (cache is -** NULL), use a forward barrier; this may be the only closure of the -** prototype (if it is a "regular" function, with a single instance) -** and the prototype may be big, so it is better to avoid traversing -** it again. Otherwise, use a backward barrier, to avoid marking all -** possible instances. -*/ -LUAI_FUNC void luaC_barrierproto_ (lua_State *L, Proto *p, Closure *c) { - global_State *g = G(L); - lua_assert(isblack(obj2gco(p))); - if (p->cache == NULL) { /* first time? */ - luaC_objbarrier(L, p, c); - } - else { /* use a backward barrier */ - black2gray(obj2gco(p)); /* make prototype gray (again) */ - p->gclist = g->grayagain; - g->grayagain = obj2gco(p); - } -} - - -/* -** check color (and invariants) for an upvalue that was closed, -** i.e., moved into the 'allgc' list -*/ -void luaC_checkupvalcolor (global_State *g, UpVal *uv) { - GCObject *o = obj2gco(uv); - lua_assert(!isblack(o)); /* open upvalues are never black */ - if (isgray(o)) { - if (keepinvariant(g)) { - resetoldbit(o); /* see MOVE OLD rule */ - gray2black(o); /* it is being visited now */ - markvalue(g, uv->v); - } - else { - lua_assert(issweepphase(g)); - makewhite(g, o); - } - } -} - - -/* -** create a new collectable object (with given type and size) and link -** it to '*list'. 'offset' tells how many bytes to allocate before the -** object itself (used only by states). -*/ -GCObject *luaC_newobj (lua_State *L, int tt, size_t sz, GCObject **list, - int offset) { - global_State *g = G(L); - char *raw = cast(char *, luaM_newobject(L, novariant(tt), sz)); - GCObject *o = obj2gco(raw + offset); - if (list == NULL) - list = &g->allgc; /* standard list for collectable objects */ - gch(o)->marked = luaC_white(g); - gch(o)->tt = tt; - gch(o)->next = *list; - *list = o; - return o; -} - -/* }====================================================== */ - - - -/* -** {====================================================== -** Mark functions -** ======================================================= -*/ - - -/* -** mark an object. Userdata, strings, and closed upvalues are visited -** and turned black here. Other objects are marked gray and added -** to appropriate list to be visited (and turned black) later. (Open -** upvalues are already linked in 'headuv' list.) -*/ -static void reallymarkobject (global_State *g, GCObject *o) { - lu_mem size; - white2gray(o); - switch (gch(o)->tt) { - case LUA_TSHRSTR: - case LUA_TLNGSTR: { - size = sizestring(gco2ts(o)); - break; /* nothing else to mark; make it black */ - } - case LUA_TUSERDATA: { - Table *mt = gco2u(o)->metatable; - markobject(g, mt); - markobject(g, gco2u(o)->env); - size = sizeudata(gco2u(o)); - break; - } - case LUA_TUPVAL: { - UpVal *uv = gco2uv(o); - markvalue(g, uv->v); - if (uv->v != &uv->u.value) /* open? */ - return; /* open upvalues remain gray */ - size = sizeof(UpVal); - break; - } - case LUA_TLCL: { - gco2lcl(o)->gclist = g->gray; - g->gray = o; - return; - } - case LUA_TCCL: { - gco2ccl(o)->gclist = g->gray; - g->gray = o; - return; - } - case LUA_TTABLE: { - linktable(gco2t(o), &g->gray); - return; - } - case LUA_TTHREAD: { - gco2th(o)->gclist = g->gray; - g->gray = o; - return; - } - case LUA_TPROTO: { - gco2p(o)->gclist = g->gray; - g->gray = o; - return; - } - default: lua_assert(0); return; - } - gray2black(o); - g->GCmemtrav += size; -} - - -/* -** mark metamethods for basic types -*/ -static void markmt (global_State *g) { - int i; - for (i=0; i < LUA_NUMTAGS; i++) - markobject(g, g->mt[i]); -} - - -/* -** mark all objects in list of being-finalized -*/ -static void markbeingfnz (global_State *g) { - GCObject *o; - for (o = g->tobefnz; o != NULL; o = gch(o)->next) { - makewhite(g, o); - reallymarkobject(g, o); - } -} - - -/* -** mark all values stored in marked open upvalues. (See comment in -** 'lstate.h'.) -*/ -static void remarkupvals (global_State *g) { - UpVal *uv; - for (uv = g->uvhead.u.l.next; uv != &g->uvhead; uv = uv->u.l.next) { - if (isgray(obj2gco(uv))) - markvalue(g, uv->v); - } -} - - -/* -** mark root set and reset all gray lists, to start a new -** incremental (or full) collection -*/ -static void restartcollection (global_State *g) { - g->gray = g->grayagain = NULL; - g->weak = g->allweak = g->ephemeron = NULL; - markobject(g, g->mainthread); - markvalue(g, &g->l_registry); - markmt(g); - markbeingfnz(g); /* mark any finalizing object left from previous cycle */ -} - -/* }====================================================== */ - - -/* -** {====================================================== -** Traverse functions -** ======================================================= -*/ - -static void traverseweakvalue (global_State *g, Table *h) { - Node *n, *limit = gnodelast(h); - /* if there is array part, assume it may have white values (do not - traverse it just to check) */ - int hasclears = (h->sizearray > 0); - for (n = gnode(h, 0); n < limit; n++) { - checkdeadkey(n); - if (ttisnil(gval(n))) /* entry is empty? */ - removeentry(n); /* remove it */ - else { - lua_assert(!ttisnil(gkey(n))); - markvalue(g, gkey(n)); /* mark key */ - if (!hasclears && iscleared(g, gval(n))) /* is there a white value? */ - hasclears = 1; /* table will have to be cleared */ - } - } - if (hasclears) - linktable(h, &g->weak); /* has to be cleared later */ - else /* no white values */ - linktable(h, &g->grayagain); /* no need to clean */ -} - - -static int traverseephemeron (global_State *g, Table *h) { - int marked = 0; /* true if an object is marked in this traversal */ - int hasclears = 0; /* true if table has white keys */ - int prop = 0; /* true if table has entry "white-key -> white-value" */ - Node *n, *limit = gnodelast(h); - int i; - /* traverse array part (numeric keys are 'strong') */ - for (i = 0; i < h->sizearray; i++) { - if (valiswhite(&h->array[i])) { - marked = 1; - reallymarkobject(g, gcvalue(&h->array[i])); - } - } - /* traverse hash part */ - for (n = gnode(h, 0); n < limit; n++) { - checkdeadkey(n); - if (ttisnil(gval(n))) /* entry is empty? */ - removeentry(n); /* remove it */ - else if (iscleared(g, gkey(n))) { /* key is not marked (yet)? */ - hasclears = 1; /* table must be cleared */ - if (valiswhite(gval(n))) /* value not marked yet? */ - prop = 1; /* must propagate again */ - } - else if (valiswhite(gval(n))) { /* value not marked yet? */ - marked = 1; - reallymarkobject(g, gcvalue(gval(n))); /* mark it now */ - } - } - if (g->gcstate != GCSatomic || prop) - linktable(h, &g->ephemeron); /* have to propagate again */ - else if (hasclears) /* does table have white keys? */ - linktable(h, &g->allweak); /* may have to clean white keys */ - else /* no white keys */ - linktable(h, &g->grayagain); /* no need to clean */ - return marked; -} - - -static void traversestrongtable (global_State *g, Table *h) { - Node *n, *limit = gnodelast(h); - int i; - for (i = 0; i < h->sizearray; i++) /* traverse array part */ - markvalue(g, &h->array[i]); - for (n = gnode(h, 0); n < limit; n++) { /* traverse hash part */ - checkdeadkey(n); - if (ttisnil(gval(n))) /* entry is empty? */ - removeentry(n); /* remove it */ - else { - lua_assert(!ttisnil(gkey(n))); - markvalue(g, gkey(n)); /* mark key */ - markvalue(g, gval(n)); /* mark value */ - } - } -} - - -static lu_mem traversetable (global_State *g, Table *h) { - const char *weakkey, *weakvalue; - const TValue *mode = gfasttm(g, h->metatable, TM_MODE); - markobject(g, h->metatable); - if (mode && ttisstring(mode) && /* is there a weak mode? */ - ((weakkey = strchr(svalue(mode), 'k')), - (weakvalue = strchr(svalue(mode), 'v')), - (weakkey || weakvalue))) { /* is really weak? */ - black2gray(obj2gco(h)); /* keep table gray */ - if (!weakkey) /* strong keys? */ - traverseweakvalue(g, h); - else if (!weakvalue) /* strong values? */ - traverseephemeron(g, h); - else /* all weak */ - linktable(h, &g->allweak); /* nothing to traverse now */ - } - else /* not weak */ - traversestrongtable(g, h); - return sizeof(Table) + sizeof(TValue) * h->sizearray + - sizeof(Node) * cast(size_t, sizenode(h)); -} - - -static int traverseproto (global_State *g, Proto *f) { - int i; - if (f->cache && iswhite(obj2gco(f->cache))) - f->cache = NULL; /* allow cache to be collected */ - markobject(g, f->source); - for (i = 0; i < f->sizek; i++) /* mark literals */ - markvalue(g, &f->k[i]); - for (i = 0; i < f->sizeupvalues; i++) /* mark upvalue names */ - markobject(g, f->upvalues[i].name); - for (i = 0; i < f->sizep; i++) /* mark nested protos */ - markobject(g, f->p[i]); - for (i = 0; i < f->sizelocvars; i++) /* mark local-variable names */ - markobject(g, f->locvars[i].varname); - return sizeof(Proto) + sizeof(Instruction) * f->sizecode + - sizeof(Proto *) * f->sizep + - sizeof(TValue) * f->sizek + - sizeof(int) * f->sizelineinfo + - sizeof(LocVar) * f->sizelocvars + - sizeof(Upvaldesc) * f->sizeupvalues; -} - - -static lu_mem traverseCclosure (global_State *g, CClosure *cl) { - int i; - for (i = 0; i < cl->nupvalues; i++) /* mark its upvalues */ - markvalue(g, &cl->upvalue[i]); - return sizeCclosure(cl->nupvalues); -} - -static lu_mem traverseLclosure (global_State *g, LClosure *cl) { - int i; - markobject(g, cl->p); /* mark its prototype */ - for (i = 0; i < cl->nupvalues; i++) /* mark its upvalues */ - markobject(g, cl->upvals[i]); - return sizeLclosure(cl->nupvalues); -} - - -static lu_mem traversestack (global_State *g, lua_State *th) { - int n = 0; - StkId o = th->stack; - if (o == NULL) - return 1; /* stack not completely built yet */ - for (; o < th->top; o++) /* mark live elements in the stack */ - markvalue(g, o); - if (g->gcstate == GCSatomic) { /* final traversal? */ - StkId lim = th->stack + th->stacksize; /* real end of stack */ - for (; o < lim; o++) /* clear not-marked stack slice */ - setnilvalue(o); - } - else { /* count call infos to compute size */ - CallInfo *ci; - for (ci = &th->base_ci; ci != th->ci; ci = ci->next) - n++; - } - return sizeof(lua_State) + sizeof(TValue) * th->stacksize + - sizeof(CallInfo) * n; -} - - -/* -** traverse one gray object, turning it to black (except for threads, -** which are always gray). -*/ -static void propagatemark (global_State *g) { - lu_mem size; - GCObject *o = g->gray; - lua_assert(isgray(o)); - gray2black(o); - switch (gch(o)->tt) { - case LUA_TTABLE: { - Table *h = gco2t(o); - g->gray = h->gclist; /* remove from 'gray' list */ - size = traversetable(g, h); - break; - } - case LUA_TLCL: { - LClosure *cl = gco2lcl(o); - g->gray = cl->gclist; /* remove from 'gray' list */ - size = traverseLclosure(g, cl); - break; - } - case LUA_TCCL: { - CClosure *cl = gco2ccl(o); - g->gray = cl->gclist; /* remove from 'gray' list */ - size = traverseCclosure(g, cl); - break; - } - case LUA_TTHREAD: { - lua_State *th = gco2th(o); - g->gray = th->gclist; /* remove from 'gray' list */ - th->gclist = g->grayagain; - g->grayagain = o; /* insert into 'grayagain' list */ - black2gray(o); - size = traversestack(g, th); - break; - } - case LUA_TPROTO: { - Proto *p = gco2p(o); - g->gray = p->gclist; /* remove from 'gray' list */ - size = traverseproto(g, p); - break; - } - default: lua_assert(0); return; - } - g->GCmemtrav += size; -} - - -static void propagateall (global_State *g) { - while (g->gray) propagatemark(g); -} - - -static void propagatelist (global_State *g, GCObject *l) { - lua_assert(g->gray == NULL); /* no grays left */ - g->gray = l; - propagateall(g); /* traverse all elements from 'l' */ -} - -/* -** retraverse all gray lists. Because tables may be reinserted in other -** lists when traversed, traverse the original lists to avoid traversing -** twice the same table (which is not wrong, but inefficient) -*/ -static void retraversegrays (global_State *g) { - GCObject *weak = g->weak; /* save original lists */ - GCObject *grayagain = g->grayagain; - GCObject *ephemeron = g->ephemeron; - g->weak = g->grayagain = g->ephemeron = NULL; - propagateall(g); /* traverse main gray list */ - propagatelist(g, grayagain); - propagatelist(g, weak); - propagatelist(g, ephemeron); -} - - -static void convergeephemerons (global_State *g) { - int changed; - do { - GCObject *w; - GCObject *next = g->ephemeron; /* get ephemeron list */ - g->ephemeron = NULL; /* tables will return to this list when traversed */ - changed = 0; - while ((w = next) != NULL) { - next = gco2t(w)->gclist; - if (traverseephemeron(g, gco2t(w))) { /* traverse marked some value? */ - propagateall(g); /* propagate changes */ - changed = 1; /* will have to revisit all ephemeron tables */ - } - } - } while (changed); -} - -/* }====================================================== */ - - -/* -** {====================================================== -** Sweep Functions -** ======================================================= -*/ - - -/* -** clear entries with unmarked keys from all weaktables in list 'l' up -** to element 'f' -*/ -static void clearkeys (global_State *g, GCObject *l, GCObject *f) { - for (; l != f; l = gco2t(l)->gclist) { - Table *h = gco2t(l); - Node *n, *limit = gnodelast(h); - for (n = gnode(h, 0); n < limit; n++) { - if (!ttisnil(gval(n)) && (iscleared(g, gkey(n)))) { - setnilvalue(gval(n)); /* remove value ... */ - removeentry(n); /* and remove entry from table */ - } - } - } -} - - -/* -** clear entries with unmarked values from all weaktables in list 'l' up -** to element 'f' -*/ -static void clearvalues (global_State *g, GCObject *l, GCObject *f) { - for (; l != f; l = gco2t(l)->gclist) { - Table *h = gco2t(l); - Node *n, *limit = gnodelast(h); - int i; - for (i = 0; i < h->sizearray; i++) { - TValue *o = &h->array[i]; - if (iscleared(g, o)) /* value was collected? */ - setnilvalue(o); /* remove value */ - } - for (n = gnode(h, 0); n < limit; n++) { - if (!ttisnil(gval(n)) && iscleared(g, gval(n))) { - setnilvalue(gval(n)); /* remove value ... */ - removeentry(n); /* and remove entry from table */ - } - } - } -} - - -static void freeobj (lua_State *L, GCObject *o) { - switch (gch(o)->tt) { - case LUA_TPROTO: luaF_freeproto(L, gco2p(o)); break; - case LUA_TLCL: { - luaM_freemem(L, o, sizeLclosure(gco2lcl(o)->nupvalues)); - break; - } - case LUA_TCCL: { - luaM_freemem(L, o, sizeCclosure(gco2ccl(o)->nupvalues)); - break; - } - case LUA_TUPVAL: luaF_freeupval(L, gco2uv(o)); break; - case LUA_TTABLE: luaH_free(L, gco2t(o)); break; - case LUA_TTHREAD: luaE_freethread(L, gco2th(o)); break; - case LUA_TUSERDATA: luaM_freemem(L, o, sizeudata(gco2u(o))); break; - case LUA_TSHRSTR: - G(L)->strt.nuse--; - /* go through */ - case LUA_TLNGSTR: { - luaM_freemem(L, o, sizestring(gco2ts(o))); - break; - } - default: lua_assert(0); - } -} - - -#define sweepwholelist(L,p) sweeplist(L,p,MAX_LUMEM) -static GCObject **sweeplist (lua_State *L, GCObject **p, lu_mem count); - - -/* -** sweep the (open) upvalues of a thread and resize its stack and -** list of call-info structures. -*/ -static void sweepthread (lua_State *L, lua_State *L1) { - if (L1->stack == NULL) return; /* stack not completely built yet */ - sweepwholelist(L, &L1->openupval); /* sweep open upvalues */ - luaE_freeCI(L1); /* free extra CallInfo slots */ - /* should not change the stack during an emergency gc cycle */ - if (G(L)->gckind != KGC_EMERGENCY) - luaD_shrinkstack(L1); -} - - -/* -** sweep at most 'count' elements from a list of GCObjects erasing dead -** objects, where a dead (not alive) object is one marked with the "old" -** (non current) white and not fixed. -** In non-generational mode, change all non-dead objects back to white, -** preparing for next collection cycle. -** In generational mode, keep black objects black, and also mark them as -** old; stop when hitting an old object, as all objects after that -** one will be old too. -** When object is a thread, sweep its list of open upvalues too. -*/ -static GCObject **sweeplist (lua_State *L, GCObject **p, lu_mem count) { - global_State *g = G(L); - int ow = otherwhite(g); - int toclear, toset; /* bits to clear and to set in all live objects */ - int tostop; /* stop sweep when this is true */ - if (isgenerational(g)) { /* generational mode? */ - toclear = ~0; /* clear nothing */ - toset = bitmask(OLDBIT); /* set the old bit of all surviving objects */ - tostop = bitmask(OLDBIT); /* do not sweep old generation */ - } - else { /* normal mode */ - toclear = maskcolors; /* clear all color bits + old bit */ - toset = luaC_white(g); /* make object white */ - tostop = 0; /* do not stop */ - } - while (*p != NULL && count-- > 0) { - GCObject *curr = *p; - int marked = gch(curr)->marked; - if (isdeadm(ow, marked)) { /* is 'curr' dead? */ - *p = gch(curr)->next; /* remove 'curr' from list */ - freeobj(L, curr); /* erase 'curr' */ - } - else { - if (testbits(marked, tostop)) - return NULL; /* stop sweeping this list */ - if (gch(curr)->tt == LUA_TTHREAD) - sweepthread(L, gco2th(curr)); /* sweep thread's upvalues */ - /* update marks */ - gch(curr)->marked = cast_byte((marked & toclear) | toset); - p = &gch(curr)->next; /* go to next element */ - } - } - return (*p == NULL) ? NULL : p; -} - - -/* -** sweep a list until a live object (or end of list) -*/ -static GCObject **sweeptolive (lua_State *L, GCObject **p, int *n) { - GCObject ** old = p; - int i = 0; - do { - i++; - p = sweeplist(L, p, 1); - } while (p == old); - if (n) *n += i; - return p; -} - -/* }====================================================== */ - - -/* -** {====================================================== -** Finalization -** ======================================================= -*/ - -static void checkSizes (lua_State *L) { - global_State *g = G(L); - if (g->gckind != KGC_EMERGENCY) { /* do not change sizes in emergency */ - int hs = g->strt.size / 2; /* half the size of the string table */ - if (g->strt.nuse < cast(lu_int32, hs)) /* using less than that half? */ - luaS_resize(L, hs); /* halve its size */ - luaZ_freebuffer(L, &g->buff); /* free concatenation buffer */ - } -} - - -static GCObject *udata2finalize (global_State *g) { - GCObject *o = g->tobefnz; /* get first element */ - lua_assert(isfinalized(o)); - g->tobefnz = gch(o)->next; /* remove it from 'tobefnz' list */ - gch(o)->next = g->allgc; /* return it to 'allgc' list */ - g->allgc = o; - resetbit(gch(o)->marked, SEPARATED); /* mark that it is not in 'tobefnz' */ - lua_assert(!isold(o)); /* see MOVE OLD rule */ - if (!keepinvariantout(g)) /* not keeping invariant? */ - makewhite(g, o); /* "sweep" object */ - return o; -} - - -static void dothecall (lua_State *L, void *ud) { - UNUSED(ud); - luaD_call(L, L->top - 2, 0, 0); -} - - -static void GCTM (lua_State *L, int propagateerrors) { - global_State *g = G(L); - const TValue *tm; - TValue v; - setgcovalue(L, &v, udata2finalize(g)); - tm = luaT_gettmbyobj(L, &v, TM_GC); - if (tm != NULL && ttisfunction(tm)) { /* is there a finalizer? */ - int status; - lu_byte oldah = L->allowhook; - int running = g->gcrunning; - L->allowhook = 0; /* stop debug hooks during GC metamethod */ - g->gcrunning = 0; /* avoid GC steps */ - setobj2s(L, L->top, tm); /* push finalizer... */ - setobj2s(L, L->top + 1, &v); /* ... and its argument */ - L->top += 2; /* and (next line) call the finalizer */ - status = luaD_pcall(L, dothecall, NULL, savestack(L, L->top - 2), 0); - L->allowhook = oldah; /* restore hooks */ - g->gcrunning = running; /* restore state */ - if (status != LUA_OK && propagateerrors) { /* error while running __gc? */ - if (status == LUA_ERRRUN) { /* is there an error object? */ - const char *msg = (ttisstring(L->top - 1)) - ? svalue(L->top - 1) - : "no message"; - luaO_pushfstring(L, "error in __gc metamethod (%s)", msg); - status = LUA_ERRGCMM; /* error in __gc metamethod */ - } - luaD_throw(L, status); /* re-throw error */ - } - } -} - - -/* -** move all unreachable objects (or 'all' objects) that need -** finalization from list 'finobj' to list 'tobefnz' (to be finalized) -*/ -static void separatetobefnz (lua_State *L, int all) { - global_State *g = G(L); - GCObject **p = &g->finobj; - GCObject *curr; - GCObject **lastnext = &g->tobefnz; - /* find last 'next' field in 'tobefnz' list (to add elements in its end) */ - while (*lastnext != NULL) - lastnext = &gch(*lastnext)->next; - while ((curr = *p) != NULL) { /* traverse all finalizable objects */ - lua_assert(!isfinalized(curr)); - lua_assert(testbit(gch(curr)->marked, SEPARATED)); - if (!(iswhite(curr) || all)) /* not being collected? */ - p = &gch(curr)->next; /* don't bother with it */ - else { - l_setbit(gch(curr)->marked, FINALIZEDBIT); /* won't be finalized again */ - *p = gch(curr)->next; /* remove 'curr' from 'finobj' list */ - gch(curr)->next = *lastnext; /* link at the end of 'tobefnz' list */ - *lastnext = curr; - lastnext = &gch(curr)->next; - } - } -} - - -/* -** if object 'o' has a finalizer, remove it from 'allgc' list (must -** search the list to find it) and link it in 'finobj' list. -*/ -void luaC_checkfinalizer (lua_State *L, GCObject *o, Table *mt) { - global_State *g = G(L); - if (testbit(gch(o)->marked, SEPARATED) || /* obj. is already separated... */ - isfinalized(o) || /* ... or is finalized... */ - gfasttm(g, mt, TM_GC) == NULL) /* or has no finalizer? */ - return; /* nothing to be done */ - else { /* move 'o' to 'finobj' list */ - GCObject **p; - GCheader *ho = gch(o); - if (g->sweepgc == &ho->next) { /* avoid removing current sweep object */ - lua_assert(issweepphase(g)); - g->sweepgc = sweeptolive(L, g->sweepgc, NULL); - } - /* search for pointer pointing to 'o' */ - for (p = &g->allgc; *p != o; p = &gch(*p)->next) { /* empty */ } - *p = ho->next; /* remove 'o' from root list */ - ho->next = g->finobj; /* link it in list 'finobj' */ - g->finobj = o; - l_setbit(ho->marked, SEPARATED); /* mark it as such */ - if (!keepinvariantout(g)) /* not keeping invariant? */ - makewhite(g, o); /* "sweep" object */ - else - resetoldbit(o); /* see MOVE OLD rule */ - } -} - -/* }====================================================== */ - - -/* -** {====================================================== -** GC control -** ======================================================= -*/ - - -/* -** set a reasonable "time" to wait before starting a new GC cycle; -** cycle will start when memory use hits threshold -*/ -static void setpause (global_State *g, l_mem estimate) { - l_mem debt, threshold; - estimate = estimate / PAUSEADJ; /* adjust 'estimate' */ - threshold = (g->gcpause < MAX_LMEM / estimate) /* overflow? */ - ? estimate * g->gcpause /* no overflow */ - : MAX_LMEM; /* overflow; truncate to maximum */ - debt = -cast(l_mem, threshold - gettotalbytes(g)); - luaE_setdebt(g, debt); -} - - -#define sweepphases \ - (bitmask(GCSsweepstring) | bitmask(GCSsweepudata) | bitmask(GCSsweep)) - - -/* -** enter first sweep phase (strings) and prepare pointers for other -** sweep phases. The calls to 'sweeptolive' make pointers point to an -** object inside the list (instead of to the header), so that the real -** sweep do not need to skip objects created between "now" and the start -** of the real sweep. -** Returns how many objects it swept. -*/ -static int entersweep (lua_State *L) { - global_State *g = G(L); - int n = 0; - g->gcstate = GCSsweepstring; - lua_assert(g->sweepgc == NULL && g->sweepfin == NULL); - /* prepare to sweep strings, finalizable objects, and regular objects */ - g->sweepstrgc = 0; - g->sweepfin = sweeptolive(L, &g->finobj, &n); - g->sweepgc = sweeptolive(L, &g->allgc, &n); - return n; -} - - -/* -** change GC mode -*/ -void luaC_changemode (lua_State *L, int mode) { - global_State *g = G(L); - if (mode == g->gckind) return; /* nothing to change */ - if (mode == KGC_GEN) { /* change to generational mode */ - /* make sure gray lists are consistent */ - luaC_runtilstate(L, bitmask(GCSpropagate)); - g->GCestimate = gettotalbytes(g); - g->gckind = KGC_GEN; - } - else { /* change to incremental mode */ - /* sweep all objects to turn them back to white - (as white has not changed, nothing extra will be collected) */ - g->gckind = KGC_NORMAL; - entersweep(L); - luaC_runtilstate(L, ~sweepphases); - } -} - - -/* -** call all pending finalizers -*/ -static void callallpendingfinalizers (lua_State *L, int propagateerrors) { - global_State *g = G(L); - while (g->tobefnz) { - resetoldbit(g->tobefnz); - GCTM(L, propagateerrors); - } -} - - -void luaC_freeallobjects (lua_State *L) { - global_State *g = G(L); - int i; - separatetobefnz(L, 1); /* separate all objects with finalizers */ - lua_assert(g->finobj == NULL); - callallpendingfinalizers(L, 0); - g->currentwhite = WHITEBITS; /* this "white" makes all objects look dead */ - g->gckind = KGC_NORMAL; - sweepwholelist(L, &g->finobj); /* finalizers can create objs. in 'finobj' */ - sweepwholelist(L, &g->allgc); - for (i = 0; i < g->strt.size; i++) /* free all string lists */ - sweepwholelist(L, &g->strt.hash[i]); - lua_assert(g->strt.nuse == 0); -} - - -static l_mem atomic (lua_State *L) { - global_State *g = G(L); - l_mem work = -cast(l_mem, g->GCmemtrav); /* start counting work */ - GCObject *origweak, *origall; - lua_assert(!iswhite(obj2gco(g->mainthread))); - markobject(g, L); /* mark running thread */ - /* registry and global metatables may be changed by API */ - markvalue(g, &g->l_registry); - markmt(g); /* mark basic metatables */ - /* remark occasional upvalues of (maybe) dead threads */ - remarkupvals(g); - propagateall(g); /* propagate changes */ - work += g->GCmemtrav; /* stop counting (do not (re)count grays) */ - /* traverse objects caught by write barrier and by 'remarkupvals' */ - retraversegrays(g); - work -= g->GCmemtrav; /* restart counting */ - convergeephemerons(g); - /* at this point, all strongly accessible objects are marked. */ - /* clear values from weak tables, before checking finalizers */ - clearvalues(g, g->weak, NULL); - clearvalues(g, g->allweak, NULL); - origweak = g->weak; origall = g->allweak; - work += g->GCmemtrav; /* stop counting (objects being finalized) */ - separatetobefnz(L, 0); /* separate objects to be finalized */ - markbeingfnz(g); /* mark objects that will be finalized */ - propagateall(g); /* remark, to propagate `preserveness' */ - work -= g->GCmemtrav; /* restart counting */ - convergeephemerons(g); - /* at this point, all resurrected objects are marked. */ - /* remove dead objects from weak tables */ - clearkeys(g, g->ephemeron, NULL); /* clear keys from all ephemeron tables */ - clearkeys(g, g->allweak, NULL); /* clear keys from all allweak tables */ - /* clear values from resurrected weak tables */ - clearvalues(g, g->weak, origweak); - clearvalues(g, g->allweak, origall); - g->currentwhite = cast_byte(otherwhite(g)); /* flip current white */ - work += g->GCmemtrav; /* complete counting */ - return work; /* estimate of memory marked by 'atomic' */ -} - - -static lu_mem singlestep (lua_State *L) { - global_State *g = G(L); - switch (g->gcstate) { - case GCSpause: { - /* start to count memory traversed */ - g->GCmemtrav = g->strt.size * sizeof(GCObject*); - lua_assert(!isgenerational(g)); - restartcollection(g); - g->gcstate = GCSpropagate; - return g->GCmemtrav; - } - case GCSpropagate: { - if (g->gray) { - lu_mem oldtrav = g->GCmemtrav; - propagatemark(g); - return g->GCmemtrav - oldtrav; /* memory traversed in this step */ - } - else { /* no more `gray' objects */ - lu_mem work; - int sw; - g->gcstate = GCSatomic; /* finish mark phase */ - g->GCestimate = g->GCmemtrav; /* save what was counted */; - work = atomic(L); /* add what was traversed by 'atomic' */ - g->GCestimate += work; /* estimate of total memory traversed */ - sw = entersweep(L); - return work + sw * GCSWEEPCOST; - } - } - case GCSsweepstring: { - int i; - for (i = 0; i < GCSWEEPMAX && g->sweepstrgc + i < g->strt.size; i++) - sweepwholelist(L, &g->strt.hash[g->sweepstrgc + i]); - g->sweepstrgc += i; - if (g->sweepstrgc >= g->strt.size) /* no more strings to sweep? */ - g->gcstate = GCSsweepudata; - return i * GCSWEEPCOST; - } - case GCSsweepudata: { - if (g->sweepfin) { - g->sweepfin = sweeplist(L, g->sweepfin, GCSWEEPMAX); - return GCSWEEPMAX*GCSWEEPCOST; - } - else { - g->gcstate = GCSsweep; - return 0; - } - } - case GCSsweep: { - if (g->sweepgc) { - g->sweepgc = sweeplist(L, g->sweepgc, GCSWEEPMAX); - return GCSWEEPMAX*GCSWEEPCOST; - } - else { - /* sweep main thread */ - GCObject *mt = obj2gco(g->mainthread); - sweeplist(L, &mt, 1); - checkSizes(L); - g->gcstate = GCSpause; /* finish collection */ - return GCSWEEPCOST; - } - } - default: lua_assert(0); return 0; - } -} - - -/* -** advances the garbage collector until it reaches a state allowed -** by 'statemask' -*/ -void luaC_runtilstate (lua_State *L, int statesmask) { - global_State *g = G(L); - while (!testbit(statesmask, g->gcstate)) - singlestep(L); -} - - -static void generationalcollection (lua_State *L) { - global_State *g = G(L); - lua_assert(g->gcstate == GCSpropagate); - if (g->GCestimate == 0) { /* signal for another major collection? */ - luaC_fullgc(L, 0); /* perform a full regular collection */ - g->GCestimate = gettotalbytes(g); /* update control */ - } - else { - lu_mem estimate = g->GCestimate; - luaC_runtilstate(L, bitmask(GCSpause)); /* run complete (minor) cycle */ - g->gcstate = GCSpropagate; /* skip restart */ - if (gettotalbytes(g) > (estimate / 100) * g->gcmajorinc) - g->GCestimate = 0; /* signal for a major collection */ - else - g->GCestimate = estimate; /* keep estimate from last major coll. */ - - } - setpause(g, gettotalbytes(g)); - lua_assert(g->gcstate == GCSpropagate); -} - - -static void incstep (lua_State *L) { - global_State *g = G(L); - l_mem debt = g->GCdebt; - int stepmul = g->gcstepmul; - if (stepmul < 40) stepmul = 40; /* avoid ridiculous low values (and 0) */ - /* convert debt from Kb to 'work units' (avoid zero debt and overflows) */ - debt = (debt / STEPMULADJ) + 1; - debt = (debt < MAX_LMEM / stepmul) ? debt * stepmul : MAX_LMEM; - do { /* always perform at least one single step */ - lu_mem work = singlestep(L); /* do some work */ - debt -= work; - } while (debt > -GCSTEPSIZE && g->gcstate != GCSpause); - if (g->gcstate == GCSpause) - setpause(g, g->GCestimate); /* pause until next cycle */ - else { - debt = (debt / stepmul) * STEPMULADJ; /* convert 'work units' to Kb */ - luaE_setdebt(g, debt); - } -} - - -/* -** performs a basic GC step -*/ -void luaC_forcestep (lua_State *L) { - global_State *g = G(L); - int i; - if (isgenerational(g)) generationalcollection(L); - else incstep(L); - /* run a few finalizers (or all of them at the end of a collect cycle) */ - for (i = 0; g->tobefnz && (i < GCFINALIZENUM || g->gcstate == GCSpause); i++) - GCTM(L, 1); /* call one finalizer */ -} - - -/* -** performs a basic GC step only if collector is running -*/ -void luaC_step (lua_State *L) { - global_State *g = G(L); - if (g->gcrunning) luaC_forcestep(L); - else luaE_setdebt(g, -GCSTEPSIZE); /* avoid being called too often */ -} - - - -/* -** performs a full GC cycle; if "isemergency", does not call -** finalizers (which could change stack positions) -*/ -void luaC_fullgc (lua_State *L, int isemergency) { - global_State *g = G(L); - int origkind = g->gckind; - lua_assert(origkind != KGC_EMERGENCY); - if (isemergency) /* do not run finalizers during emergency GC */ - g->gckind = KGC_EMERGENCY; - else { - g->gckind = KGC_NORMAL; - callallpendingfinalizers(L, 1); - } - if (keepinvariant(g)) { /* may there be some black objects? */ - /* must sweep all objects to turn them back to white - (as white has not changed, nothing will be collected) */ - entersweep(L); - } - /* finish any pending sweep phase to start a new cycle */ - luaC_runtilstate(L, bitmask(GCSpause)); - luaC_runtilstate(L, ~bitmask(GCSpause)); /* start new collection */ - luaC_runtilstate(L, bitmask(GCSpause)); /* run entire collection */ - if (origkind == KGC_GEN) { /* generational mode? */ - /* generational mode must be kept in propagate phase */ - luaC_runtilstate(L, bitmask(GCSpropagate)); - } - g->gckind = origkind; - setpause(g, gettotalbytes(g)); - if (!isemergency) /* do not run finalizers during emergency GC */ - callallpendingfinalizers(L, 1); -} - -/* }====================================================== */ - - diff --git a/lib/lua-5.2/src/lgc.h b/lib/lua-5.2/src/lgc.h deleted file mode 100644 index 84bb1cd..0000000 --- a/lib/lua-5.2/src/lgc.h +++ /dev/null @@ -1,157 +0,0 @@ -/* -** $Id: lgc.h,v 2.58.1.1 2013/04/12 18:48:47 roberto Exp $ -** Garbage Collector -** See Copyright Notice in lua.h -*/ - -#ifndef lgc_h -#define lgc_h - - -#include "lobject.h" -#include "lstate.h" - -/* -** Collectable objects may have one of three colors: white, which -** means the object is not marked; gray, which means the -** object is marked, but its references may be not marked; and -** black, which means that the object and all its references are marked. -** The main invariant of the garbage collector, while marking objects, -** is that a black object can never point to a white one. Moreover, -** any gray object must be in a "gray list" (gray, grayagain, weak, -** allweak, ephemeron) so that it can be visited again before finishing -** the collection cycle. These lists have no meaning when the invariant -** is not being enforced (e.g., sweep phase). -*/ - - - -/* how much to allocate before next GC step */ -#if !defined(GCSTEPSIZE) -/* ~100 small strings */ -#define GCSTEPSIZE (cast_int(100 * sizeof(TString))) -#endif - - -/* -** Possible states of the Garbage Collector -*/ -#define GCSpropagate 0 -#define GCSatomic 1 -#define GCSsweepstring 2 -#define GCSsweepudata 3 -#define GCSsweep 4 -#define GCSpause 5 - - -#define issweepphase(g) \ - (GCSsweepstring <= (g)->gcstate && (g)->gcstate <= GCSsweep) - -#define isgenerational(g) ((g)->gckind == KGC_GEN) - -/* -** macros to tell when main invariant (white objects cannot point to black -** ones) must be kept. During a non-generational collection, the sweep -** phase may break the invariant, as objects turned white may point to -** still-black objects. The invariant is restored when sweep ends and -** all objects are white again. During a generational collection, the -** invariant must be kept all times. -*/ - -#define keepinvariant(g) (isgenerational(g) || g->gcstate <= GCSatomic) - - -/* -** Outside the collector, the state in generational mode is kept in -** 'propagate', so 'keepinvariant' is always true. -*/ -#define keepinvariantout(g) \ - check_exp(g->gcstate == GCSpropagate || !isgenerational(g), \ - g->gcstate <= GCSatomic) - - -/* -** some useful bit tricks -*/ -#define resetbits(x,m) ((x) &= cast(lu_byte, ~(m))) -#define setbits(x,m) ((x) |= (m)) -#define testbits(x,m) ((x) & (m)) -#define bitmask(b) (1<<(b)) -#define bit2mask(b1,b2) (bitmask(b1) | bitmask(b2)) -#define l_setbit(x,b) setbits(x, bitmask(b)) -#define resetbit(x,b) resetbits(x, bitmask(b)) -#define testbit(x,b) testbits(x, bitmask(b)) - - -/* Layout for bit use in `marked' field: */ -#define WHITE0BIT 0 /* object is white (type 0) */ -#define WHITE1BIT 1 /* object is white (type 1) */ -#define BLACKBIT 2 /* object is black */ -#define FINALIZEDBIT 3 /* object has been separated for finalization */ -#define SEPARATED 4 /* object is in 'finobj' list or in 'tobefnz' */ -#define FIXEDBIT 5 /* object is fixed (should not be collected) */ -#define OLDBIT 6 /* object is old (only in generational mode) */ -/* bit 7 is currently used by tests (luaL_checkmemory) */ - -#define WHITEBITS bit2mask(WHITE0BIT, WHITE1BIT) - - -#define iswhite(x) testbits((x)->gch.marked, WHITEBITS) -#define isblack(x) testbit((x)->gch.marked, BLACKBIT) -#define isgray(x) /* neither white nor black */ \ - (!testbits((x)->gch.marked, WHITEBITS | bitmask(BLACKBIT))) - -#define isold(x) testbit((x)->gch.marked, OLDBIT) - -/* MOVE OLD rule: whenever an object is moved to the beginning of - a GC list, its old bit must be cleared */ -#define resetoldbit(o) resetbit((o)->gch.marked, OLDBIT) - -#define otherwhite(g) (g->currentwhite ^ WHITEBITS) -#define isdeadm(ow,m) (!(((m) ^ WHITEBITS) & (ow))) -#define isdead(g,v) isdeadm(otherwhite(g), (v)->gch.marked) - -#define changewhite(x) ((x)->gch.marked ^= WHITEBITS) -#define gray2black(x) l_setbit((x)->gch.marked, BLACKBIT) - -#define valiswhite(x) (iscollectable(x) && iswhite(gcvalue(x))) - -#define luaC_white(g) cast(lu_byte, (g)->currentwhite & WHITEBITS) - - -#define luaC_condGC(L,c) \ - {if (G(L)->GCdebt > 0) {c;}; condchangemem(L);} -#define luaC_checkGC(L) luaC_condGC(L, luaC_step(L);) - - -#define luaC_barrier(L,p,v) { if (valiswhite(v) && isblack(obj2gco(p))) \ - luaC_barrier_(L,obj2gco(p),gcvalue(v)); } - -#define luaC_barrierback(L,p,v) { if (valiswhite(v) && isblack(obj2gco(p))) \ - luaC_barrierback_(L,p); } - -#define luaC_objbarrier(L,p,o) \ - { if (iswhite(obj2gco(o)) && isblack(obj2gco(p))) \ - luaC_barrier_(L,obj2gco(p),obj2gco(o)); } - -#define luaC_objbarrierback(L,p,o) \ - { if (iswhite(obj2gco(o)) && isblack(obj2gco(p))) luaC_barrierback_(L,p); } - -#define luaC_barrierproto(L,p,c) \ - { if (isblack(obj2gco(p))) luaC_barrierproto_(L,p,c); } - -LUAI_FUNC void luaC_freeallobjects (lua_State *L); -LUAI_FUNC void luaC_step (lua_State *L); -LUAI_FUNC void luaC_forcestep (lua_State *L); -LUAI_FUNC void luaC_runtilstate (lua_State *L, int statesmask); -LUAI_FUNC void luaC_fullgc (lua_State *L, int isemergency); -LUAI_FUNC GCObject *luaC_newobj (lua_State *L, int tt, size_t sz, - GCObject **list, int offset); -LUAI_FUNC void luaC_barrier_ (lua_State *L, GCObject *o, GCObject *v); -LUAI_FUNC void luaC_barrierback_ (lua_State *L, GCObject *o); -LUAI_FUNC void luaC_barrierproto_ (lua_State *L, Proto *p, Closure *c); -LUAI_FUNC void luaC_checkfinalizer (lua_State *L, GCObject *o, Table *mt); -LUAI_FUNC void luaC_checkupvalcolor (global_State *g, UpVal *uv); -LUAI_FUNC void luaC_changemode (lua_State *L, int mode); - -#endif diff --git a/lib/lua-5.2/src/linit.c b/lib/lua-5.2/src/linit.c deleted file mode 100644 index c1a3830..0000000 --- a/lib/lua-5.2/src/linit.c +++ /dev/null @@ -1,67 +0,0 @@ -/* -** $Id: linit.c,v 1.32.1.1 2013/04/12 18:48:47 roberto Exp $ -** Initialization of libraries for lua.c and other clients -** See Copyright Notice in lua.h -*/ - - -/* -** If you embed Lua in your program and need to open the standard -** libraries, call luaL_openlibs in your program. If you need a -** different set of libraries, copy this file to your project and edit -** it to suit your needs. -*/ - - -#define linit_c -#define LUA_LIB - -#include "lua.h" - -#include "lualib.h" -#include "lauxlib.h" - - -/* -** these libs are loaded by lua.c and are readily available to any Lua -** program -*/ -static const luaL_Reg loadedlibs[] = { - {"_G", luaopen_base}, - {LUA_LOADLIBNAME, luaopen_package}, - {LUA_COLIBNAME, luaopen_coroutine}, - {LUA_TABLIBNAME, luaopen_table}, - {LUA_IOLIBNAME, luaopen_io}, - {LUA_OSLIBNAME, luaopen_os}, - {LUA_STRLIBNAME, luaopen_string}, - {LUA_BITLIBNAME, luaopen_bit32}, - {LUA_MATHLIBNAME, luaopen_math}, - {LUA_DBLIBNAME, luaopen_debug}, - {NULL, NULL} -}; - - -/* -** these libs are preloaded and must be required before used -*/ -static const luaL_Reg preloadedlibs[] = { - {NULL, NULL} -}; - - -LUALIB_API void luaL_openlibs (lua_State *L) { - const luaL_Reg *lib; - /* call open functions from 'loadedlibs' and set results to global table */ - for (lib = loadedlibs; lib->func; lib++) { - luaL_requiref(L, lib->name, lib->func, 1); - lua_pop(L, 1); /* remove lib */ - } - /* add open functions from 'preloadedlibs' into 'package.preload' table */ - luaL_getsubtable(L, LUA_REGISTRYINDEX, "_PRELOAD"); - for (lib = preloadedlibs; lib->func; lib++) { - lua_pushcfunction(L, lib->func); - lua_setfield(L, -2, lib->name); - } - lua_pop(L, 1); /* remove _PRELOAD table */ -} - diff --git a/lib/lua-5.2/src/liolib.c b/lib/lua-5.2/src/liolib.c deleted file mode 100644 index 2a4ec4a..0000000 --- a/lib/lua-5.2/src/liolib.c +++ /dev/null @@ -1,666 +0,0 @@ -/* -** $Id: liolib.c,v 2.112.1.1 2013/04/12 18:48:47 roberto Exp $ -** Standard I/O (and system) library -** See Copyright Notice in lua.h -*/ - - -/* -** This definition must come before the inclusion of 'stdio.h'; it -** should not affect non-POSIX systems -*/ -#if !defined(_FILE_OFFSET_BITS) -#define _LARGEFILE_SOURCE 1 -#define _FILE_OFFSET_BITS 64 -#endif - - -#include -#include -#include -#include - -#define liolib_c -#define LUA_LIB - -#include "lua.h" - -#include "lauxlib.h" -#include "lualib.h" - - -#if !defined(lua_checkmode) - -/* -** Check whether 'mode' matches '[rwa]%+?b?'. -** Change this macro to accept other modes for 'fopen' besides -** the standard ones. -*/ -#define lua_checkmode(mode) \ - (*mode != '\0' && strchr("rwa", *(mode++)) != NULL && \ - (*mode != '+' || ++mode) && /* skip if char is '+' */ \ - (*mode != 'b' || ++mode) && /* skip if char is 'b' */ \ - (*mode == '\0')) - -#endif - -/* -** {====================================================== -** lua_popen spawns a new process connected to the current -** one through the file streams. -** ======================================================= -*/ - -#if !defined(lua_popen) /* { */ - -#if defined(LUA_USE_POPEN) /* { */ - -#define lua_popen(L,c,m) ((void)L, fflush(NULL), popen(c,m)) -#define lua_pclose(L,file) ((void)L, pclose(file)) - -#elif defined(LUA_WIN) /* }{ */ - -#define lua_popen(L,c,m) ((void)L, _popen(c,m)) -#define lua_pclose(L,file) ((void)L, _pclose(file)) - - -#else /* }{ */ - -#define lua_popen(L,c,m) ((void)((void)c, m), \ - luaL_error(L, LUA_QL("popen") " not supported"), (FILE*)0) -#define lua_pclose(L,file) ((void)((void)L, file), -1) - - -#endif /* } */ - -#endif /* } */ - -/* }====================================================== */ - - -/* -** {====================================================== -** lua_fseek: configuration for longer offsets -** ======================================================= -*/ - -#if !defined(lua_fseek) && !defined(LUA_ANSI) /* { */ - -#if defined(LUA_USE_POSIX) /* { */ - -#define l_fseek(f,o,w) fseeko(f,o,w) -#define l_ftell(f) ftello(f) -#define l_seeknum off_t - -#elif defined(LUA_WIN) && !defined(_CRTIMP_TYPEINFO) \ - && defined(_MSC_VER) && (_MSC_VER >= 1400) /* }{ */ -/* Windows (but not DDK) and Visual C++ 2005 or higher */ - -#define l_fseek(f,o,w) _fseeki64(f,o,w) -#define l_ftell(f) _ftelli64(f) -#define l_seeknum __int64 - -#endif /* } */ - -#endif /* } */ - - -#if !defined(l_fseek) /* default definitions */ -#define l_fseek(f,o,w) fseek(f,o,w) -#define l_ftell(f) ftell(f) -#define l_seeknum long -#endif - -/* }====================================================== */ - - -#define IO_PREFIX "_IO_" -#define IO_INPUT (IO_PREFIX "input") -#define IO_OUTPUT (IO_PREFIX "output") - - -typedef luaL_Stream LStream; - - -#define tolstream(L) ((LStream *)luaL_checkudata(L, 1, LUA_FILEHANDLE)) - -#define isclosed(p) ((p)->closef == NULL) - - -static int io_type (lua_State *L) { - LStream *p; - luaL_checkany(L, 1); - p = (LStream *)luaL_testudata(L, 1, LUA_FILEHANDLE); - if (p == NULL) - lua_pushnil(L); /* not a file */ - else if (isclosed(p)) - lua_pushliteral(L, "closed file"); - else - lua_pushliteral(L, "file"); - return 1; -} - - -static int f_tostring (lua_State *L) { - LStream *p = tolstream(L); - if (isclosed(p)) - lua_pushliteral(L, "file (closed)"); - else - lua_pushfstring(L, "file (%p)", p->f); - return 1; -} - - -static FILE *tofile (lua_State *L) { - LStream *p = tolstream(L); - if (isclosed(p)) - luaL_error(L, "attempt to use a closed file"); - lua_assert(p->f); - return p->f; -} - - -/* -** When creating file handles, always creates a `closed' file handle -** before opening the actual file; so, if there is a memory error, the -** file is not left opened. -*/ -static LStream *newprefile (lua_State *L) { - LStream *p = (LStream *)lua_newuserdata(L, sizeof(LStream)); - p->closef = NULL; /* mark file handle as 'closed' */ - luaL_setmetatable(L, LUA_FILEHANDLE); - return p; -} - - -static int aux_close (lua_State *L) { - LStream *p = tolstream(L); - lua_CFunction cf = p->closef; - p->closef = NULL; /* mark stream as closed */ - return (*cf)(L); /* close it */ -} - - -static int io_close (lua_State *L) { - if (lua_isnone(L, 1)) /* no argument? */ - lua_getfield(L, LUA_REGISTRYINDEX, IO_OUTPUT); /* use standard output */ - tofile(L); /* make sure argument is an open stream */ - return aux_close(L); -} - - -static int f_gc (lua_State *L) { - LStream *p = tolstream(L); - if (!isclosed(p) && p->f != NULL) - aux_close(L); /* ignore closed and incompletely open files */ - return 0; -} - - -/* -** function to close regular files -*/ -static int io_fclose (lua_State *L) { - LStream *p = tolstream(L); - int res = fclose(p->f); - return luaL_fileresult(L, (res == 0), NULL); -} - - -static LStream *newfile (lua_State *L) { - LStream *p = newprefile(L); - p->f = NULL; - p->closef = &io_fclose; - return p; -} - - -static void opencheck (lua_State *L, const char *fname, const char *mode) { - LStream *p = newfile(L); - p->f = fopen(fname, mode); - if (p->f == NULL) - luaL_error(L, "cannot open file " LUA_QS " (%s)", fname, strerror(errno)); -} - - -static int io_open (lua_State *L) { - const char *filename = luaL_checkstring(L, 1); - const char *mode = luaL_optstring(L, 2, "r"); - LStream *p = newfile(L); - const char *md = mode; /* to traverse/check mode */ - luaL_argcheck(L, lua_checkmode(md), 2, "invalid mode"); - p->f = fopen(filename, mode); - return (p->f == NULL) ? luaL_fileresult(L, 0, filename) : 1; -} - - -/* -** function to close 'popen' files -*/ -static int io_pclose (lua_State *L) { - LStream *p = tolstream(L); - return luaL_execresult(L, lua_pclose(L, p->f)); -} - - -static int io_popen (lua_State *L) { - const char *filename = luaL_checkstring(L, 1); - const char *mode = luaL_optstring(L, 2, "r"); - LStream *p = newprefile(L); - p->f = lua_popen(L, filename, mode); - p->closef = &io_pclose; - return (p->f == NULL) ? luaL_fileresult(L, 0, filename) : 1; -} - - -static int io_tmpfile (lua_State *L) { - LStream *p = newfile(L); - p->f = tmpfile(); - return (p->f == NULL) ? luaL_fileresult(L, 0, NULL) : 1; -} - - -static FILE *getiofile (lua_State *L, const char *findex) { - LStream *p; - lua_getfield(L, LUA_REGISTRYINDEX, findex); - p = (LStream *)lua_touserdata(L, -1); - if (isclosed(p)) - luaL_error(L, "standard %s file is closed", findex + strlen(IO_PREFIX)); - return p->f; -} - - -static int g_iofile (lua_State *L, const char *f, const char *mode) { - if (!lua_isnoneornil(L, 1)) { - const char *filename = lua_tostring(L, 1); - if (filename) - opencheck(L, filename, mode); - else { - tofile(L); /* check that it's a valid file handle */ - lua_pushvalue(L, 1); - } - lua_setfield(L, LUA_REGISTRYINDEX, f); - } - /* return current value */ - lua_getfield(L, LUA_REGISTRYINDEX, f); - return 1; -} - - -static int io_input (lua_State *L) { - return g_iofile(L, IO_INPUT, "r"); -} - - -static int io_output (lua_State *L) { - return g_iofile(L, IO_OUTPUT, "w"); -} - - -static int io_readline (lua_State *L); - - -static void aux_lines (lua_State *L, int toclose) { - int i; - int n = lua_gettop(L) - 1; /* number of arguments to read */ - /* ensure that arguments will fit here and into 'io_readline' stack */ - luaL_argcheck(L, n <= LUA_MINSTACK - 3, LUA_MINSTACK - 3, "too many options"); - lua_pushvalue(L, 1); /* file handle */ - lua_pushinteger(L, n); /* number of arguments to read */ - lua_pushboolean(L, toclose); /* close/not close file when finished */ - for (i = 1; i <= n; i++) lua_pushvalue(L, i + 1); /* copy arguments */ - lua_pushcclosure(L, io_readline, 3 + n); -} - - -static int f_lines (lua_State *L) { - tofile(L); /* check that it's a valid file handle */ - aux_lines(L, 0); - return 1; -} - - -static int io_lines (lua_State *L) { - int toclose; - if (lua_isnone(L, 1)) lua_pushnil(L); /* at least one argument */ - if (lua_isnil(L, 1)) { /* no file name? */ - lua_getfield(L, LUA_REGISTRYINDEX, IO_INPUT); /* get default input */ - lua_replace(L, 1); /* put it at index 1 */ - tofile(L); /* check that it's a valid file handle */ - toclose = 0; /* do not close it after iteration */ - } - else { /* open a new file */ - const char *filename = luaL_checkstring(L, 1); - opencheck(L, filename, "r"); - lua_replace(L, 1); /* put file at index 1 */ - toclose = 1; /* close it after iteration */ - } - aux_lines(L, toclose); - return 1; -} - - -/* -** {====================================================== -** READ -** ======================================================= -*/ - - -static int read_number (lua_State *L, FILE *f) { - lua_Number d; - if (fscanf(f, LUA_NUMBER_SCAN, &d) == 1) { - lua_pushnumber(L, d); - return 1; - } - else { - lua_pushnil(L); /* "result" to be removed */ - return 0; /* read fails */ - } -} - - -static int test_eof (lua_State *L, FILE *f) { - int c = getc(f); - ungetc(c, f); - lua_pushlstring(L, NULL, 0); - return (c != EOF); -} - - -static int read_line (lua_State *L, FILE *f, int chop) { - luaL_Buffer b; - luaL_buffinit(L, &b); - for (;;) { - size_t l; - char *p = luaL_prepbuffer(&b); - if (fgets(p, LUAL_BUFFERSIZE, f) == NULL) { /* eof? */ - luaL_pushresult(&b); /* close buffer */ - return (lua_rawlen(L, -1) > 0); /* check whether read something */ - } - l = strlen(p); - if (l == 0 || p[l-1] != '\n') - luaL_addsize(&b, l); - else { - luaL_addsize(&b, l - chop); /* chop 'eol' if needed */ - luaL_pushresult(&b); /* close buffer */ - return 1; /* read at least an `eol' */ - } - } -} - - -#define MAX_SIZE_T (~(size_t)0) - -static void read_all (lua_State *L, FILE *f) { - size_t rlen = LUAL_BUFFERSIZE; /* how much to read in each cycle */ - luaL_Buffer b; - luaL_buffinit(L, &b); - for (;;) { - char *p = luaL_prepbuffsize(&b, rlen); - size_t nr = fread(p, sizeof(char), rlen, f); - luaL_addsize(&b, nr); - if (nr < rlen) break; /* eof? */ - else if (rlen <= (MAX_SIZE_T / 4)) /* avoid buffers too large */ - rlen *= 2; /* double buffer size at each iteration */ - } - luaL_pushresult(&b); /* close buffer */ -} - - -static int read_chars (lua_State *L, FILE *f, size_t n) { - size_t nr; /* number of chars actually read */ - char *p; - luaL_Buffer b; - luaL_buffinit(L, &b); - p = luaL_prepbuffsize(&b, n); /* prepare buffer to read whole block */ - nr = fread(p, sizeof(char), n, f); /* try to read 'n' chars */ - luaL_addsize(&b, nr); - luaL_pushresult(&b); /* close buffer */ - return (nr > 0); /* true iff read something */ -} - - -static int g_read (lua_State *L, FILE *f, int first) { - int nargs = lua_gettop(L) - 1; - int success; - int n; - clearerr(f); - if (nargs == 0) { /* no arguments? */ - success = read_line(L, f, 1); - n = first+1; /* to return 1 result */ - } - else { /* ensure stack space for all results and for auxlib's buffer */ - luaL_checkstack(L, nargs+LUA_MINSTACK, "too many arguments"); - success = 1; - for (n = first; nargs-- && success; n++) { - if (lua_type(L, n) == LUA_TNUMBER) { - size_t l = (size_t)lua_tointeger(L, n); - success = (l == 0) ? test_eof(L, f) : read_chars(L, f, l); - } - else { - const char *p = lua_tostring(L, n); - luaL_argcheck(L, p && p[0] == '*', n, "invalid option"); - switch (p[1]) { - case 'n': /* number */ - success = read_number(L, f); - break; - case 'l': /* line */ - success = read_line(L, f, 1); - break; - case 'L': /* line with end-of-line */ - success = read_line(L, f, 0); - break; - case 'a': /* file */ - read_all(L, f); /* read entire file */ - success = 1; /* always success */ - break; - default: - return luaL_argerror(L, n, "invalid format"); - } - } - } - } - if (ferror(f)) - return luaL_fileresult(L, 0, NULL); - if (!success) { - lua_pop(L, 1); /* remove last result */ - lua_pushnil(L); /* push nil instead */ - } - return n - first; -} - - -static int io_read (lua_State *L) { - return g_read(L, getiofile(L, IO_INPUT), 1); -} - - -static int f_read (lua_State *L) { - return g_read(L, tofile(L), 2); -} - - -static int io_readline (lua_State *L) { - LStream *p = (LStream *)lua_touserdata(L, lua_upvalueindex(1)); - int i; - int n = (int)lua_tointeger(L, lua_upvalueindex(2)); - if (isclosed(p)) /* file is already closed? */ - return luaL_error(L, "file is already closed"); - lua_settop(L , 1); - for (i = 1; i <= n; i++) /* push arguments to 'g_read' */ - lua_pushvalue(L, lua_upvalueindex(3 + i)); - n = g_read(L, p->f, 2); /* 'n' is number of results */ - lua_assert(n > 0); /* should return at least a nil */ - if (!lua_isnil(L, -n)) /* read at least one value? */ - return n; /* return them */ - else { /* first result is nil: EOF or error */ - if (n > 1) { /* is there error information? */ - /* 2nd result is error message */ - return luaL_error(L, "%s", lua_tostring(L, -n + 1)); - } - if (lua_toboolean(L, lua_upvalueindex(3))) { /* generator created file? */ - lua_settop(L, 0); - lua_pushvalue(L, lua_upvalueindex(1)); - aux_close(L); /* close it */ - } - return 0; - } -} - -/* }====================================================== */ - - -static int g_write (lua_State *L, FILE *f, int arg) { - int nargs = lua_gettop(L) - arg; - int status = 1; - for (; nargs--; arg++) { - if (lua_type(L, arg) == LUA_TNUMBER) { - /* optimization: could be done exactly as for strings */ - status = status && - fprintf(f, LUA_NUMBER_FMT, lua_tonumber(L, arg)) > 0; - } - else { - size_t l; - const char *s = luaL_checklstring(L, arg, &l); - status = status && (fwrite(s, sizeof(char), l, f) == l); - } - } - if (status) return 1; /* file handle already on stack top */ - else return luaL_fileresult(L, status, NULL); -} - - -static int io_write (lua_State *L) { - return g_write(L, getiofile(L, IO_OUTPUT), 1); -} - - -static int f_write (lua_State *L) { - FILE *f = tofile(L); - lua_pushvalue(L, 1); /* push file at the stack top (to be returned) */ - return g_write(L, f, 2); -} - - -static int f_seek (lua_State *L) { - static const int mode[] = {SEEK_SET, SEEK_CUR, SEEK_END}; - static const char *const modenames[] = {"set", "cur", "end", NULL}; - FILE *f = tofile(L); - int op = luaL_checkoption(L, 2, "cur", modenames); - lua_Number p3 = luaL_optnumber(L, 3, 0); - l_seeknum offset = (l_seeknum)p3; - luaL_argcheck(L, (lua_Number)offset == p3, 3, - "not an integer in proper range"); - op = l_fseek(f, offset, mode[op]); - if (op) - return luaL_fileresult(L, 0, NULL); /* error */ - else { - lua_pushnumber(L, (lua_Number)l_ftell(f)); - return 1; - } -} - - -static int f_setvbuf (lua_State *L) { - static const int mode[] = {_IONBF, _IOFBF, _IOLBF}; - static const char *const modenames[] = {"no", "full", "line", NULL}; - FILE *f = tofile(L); - int op = luaL_checkoption(L, 2, NULL, modenames); - lua_Integer sz = luaL_optinteger(L, 3, LUAL_BUFFERSIZE); - int res = setvbuf(f, NULL, mode[op], sz); - return luaL_fileresult(L, res == 0, NULL); -} - - - -static int io_flush (lua_State *L) { - return luaL_fileresult(L, fflush(getiofile(L, IO_OUTPUT)) == 0, NULL); -} - - -static int f_flush (lua_State *L) { - return luaL_fileresult(L, fflush(tofile(L)) == 0, NULL); -} - - -/* -** functions for 'io' library -*/ -static const luaL_Reg iolib[] = { - {"close", io_close}, - {"flush", io_flush}, - {"input", io_input}, - {"lines", io_lines}, - {"open", io_open}, - {"output", io_output}, - {"popen", io_popen}, - {"read", io_read}, - {"tmpfile", io_tmpfile}, - {"type", io_type}, - {"write", io_write}, - {NULL, NULL} -}; - - -/* -** methods for file handles -*/ -static const luaL_Reg flib[] = { - {"close", io_close}, - {"flush", f_flush}, - {"lines", f_lines}, - {"read", f_read}, - {"seek", f_seek}, - {"setvbuf", f_setvbuf}, - {"write", f_write}, - {"__gc", f_gc}, - {"__tostring", f_tostring}, - {NULL, NULL} -}; - - -static void createmeta (lua_State *L) { - luaL_newmetatable(L, LUA_FILEHANDLE); /* create metatable for file handles */ - lua_pushvalue(L, -1); /* push metatable */ - lua_setfield(L, -2, "__index"); /* metatable.__index = metatable */ - luaL_setfuncs(L, flib, 0); /* add file methods to new metatable */ - lua_pop(L, 1); /* pop new metatable */ -} - - -/* -** function to (not) close the standard files stdin, stdout, and stderr -*/ -static int io_noclose (lua_State *L) { - LStream *p = tolstream(L); - p->closef = &io_noclose; /* keep file opened */ - lua_pushnil(L); - lua_pushliteral(L, "cannot close standard file"); - return 2; -} - - -static void createstdfile (lua_State *L, FILE *f, const char *k, - const char *fname) { - LStream *p = newprefile(L); - p->f = f; - p->closef = &io_noclose; - if (k != NULL) { - lua_pushvalue(L, -1); - lua_setfield(L, LUA_REGISTRYINDEX, k); /* add file to registry */ - } - lua_setfield(L, -2, fname); /* add file to module */ -} - - -LUAMOD_API int luaopen_io (lua_State *L) { - luaL_newlib(L, iolib); /* new module */ - createmeta(L); - /* create (and set) default files */ - createstdfile(L, stdin, IO_INPUT, "stdin"); - createstdfile(L, stdout, IO_OUTPUT, "stdout"); - createstdfile(L, stderr, NULL, "stderr"); - return 1; -} - diff --git a/lib/lua-5.2/src/llex.c b/lib/lua-5.2/src/llex.c deleted file mode 100644 index 32cdcf1..0000000 --- a/lib/lua-5.2/src/llex.c +++ /dev/null @@ -1,530 +0,0 @@ -/* -** $Id: llex.c,v 2.63.1.3 2015/02/09 17:56:34 roberto Exp $ -** Lexical Analyzer -** See Copyright Notice in lua.h -*/ - - -#include -#include - -#define llex_c -#define LUA_CORE - -#include "lua.h" - -#include "lctype.h" -#include "ldo.h" -#include "llex.h" -#include "lobject.h" -#include "lparser.h" -#include "lstate.h" -#include "lstring.h" -#include "ltable.h" -#include "lzio.h" - - - -#define next(ls) (ls->current = zgetc(ls->z)) - - - -#define currIsNewline(ls) (ls->current == '\n' || ls->current == '\r') - - -/* ORDER RESERVED */ -static const char *const luaX_tokens [] = { - "and", "break", "do", "else", "elseif", - "end", "false", "for", "function", "goto", "if", - "in", "local", "nil", "not", "or", "repeat", - "return", "then", "true", "until", "while", - "..", "...", "==", ">=", "<=", "~=", "::", "", - "", "", "" -}; - - -#define save_and_next(ls) (save(ls, ls->current), next(ls)) - - -static l_noret lexerror (LexState *ls, const char *msg, int token); - - -static void save (LexState *ls, int c) { - Mbuffer *b = ls->buff; - if (luaZ_bufflen(b) + 1 > luaZ_sizebuffer(b)) { - size_t newsize; - if (luaZ_sizebuffer(b) >= MAX_SIZET/2) - lexerror(ls, "lexical element too long", 0); - newsize = luaZ_sizebuffer(b) * 2; - luaZ_resizebuffer(ls->L, b, newsize); - } - b->buffer[luaZ_bufflen(b)++] = cast(char, c); -} - - -void luaX_init (lua_State *L) { - int i; - for (i=0; itsv.extra = cast_byte(i+1); /* reserved word */ - } -} - - -const char *luaX_token2str (LexState *ls, int token) { - if (token < FIRST_RESERVED) { /* single-byte symbols? */ - lua_assert(token == cast(unsigned char, token)); - return (lisprint(token)) ? luaO_pushfstring(ls->L, LUA_QL("%c"), token) : - luaO_pushfstring(ls->L, "char(%d)", token); - } - else { - const char *s = luaX_tokens[token - FIRST_RESERVED]; - if (token < TK_EOS) /* fixed format (symbols and reserved words)? */ - return luaO_pushfstring(ls->L, LUA_QS, s); - else /* names, strings, and numerals */ - return s; - } -} - - -static const char *txtToken (LexState *ls, int token) { - switch (token) { - case TK_NAME: - case TK_STRING: - case TK_NUMBER: - save(ls, '\0'); - return luaO_pushfstring(ls->L, LUA_QS, luaZ_buffer(ls->buff)); - default: - return luaX_token2str(ls, token); - } -} - - -static l_noret lexerror (LexState *ls, const char *msg, int token) { - char buff[LUA_IDSIZE]; - luaO_chunkid(buff, getstr(ls->source), LUA_IDSIZE); - msg = luaO_pushfstring(ls->L, "%s:%d: %s", buff, ls->linenumber, msg); - if (token) - luaO_pushfstring(ls->L, "%s near %s", msg, txtToken(ls, token)); - luaD_throw(ls->L, LUA_ERRSYNTAX); -} - - -l_noret luaX_syntaxerror (LexState *ls, const char *msg) { - lexerror(ls, msg, ls->t.token); -} - - -/* -** creates a new string and anchors it in function's table so that -** it will not be collected until the end of the function's compilation -** (by that time it should be anchored in function's prototype) -*/ -TString *luaX_newstring (LexState *ls, const char *str, size_t l) { - lua_State *L = ls->L; - TValue *o; /* entry for `str' */ - TString *ts = luaS_newlstr(L, str, l); /* create new string */ - setsvalue2s(L, L->top++, ts); /* temporarily anchor it in stack */ - o = luaH_set(L, ls->fs->h, L->top - 1); - if (ttisnil(o)) { /* not in use yet? (see 'addK') */ - /* boolean value does not need GC barrier; - table has no metatable, so it does not need to invalidate cache */ - setbvalue(o, 1); /* t[string] = true */ - luaC_checkGC(L); - } - else { /* string already present */ - ts = rawtsvalue(keyfromval(o)); /* re-use value previously stored */ - } - L->top--; /* remove string from stack */ - return ts; -} - - -/* -** increment line number and skips newline sequence (any of -** \n, \r, \n\r, or \r\n) -*/ -static void inclinenumber (LexState *ls) { - int old = ls->current; - lua_assert(currIsNewline(ls)); - next(ls); /* skip `\n' or `\r' */ - if (currIsNewline(ls) && ls->current != old) - next(ls); /* skip `\n\r' or `\r\n' */ - if (++ls->linenumber >= MAX_INT) - lexerror(ls, "chunk has too many lines", 0); -} - - -void luaX_setinput (lua_State *L, LexState *ls, ZIO *z, TString *source, - int firstchar) { - ls->decpoint = '.'; - ls->L = L; - ls->current = firstchar; - ls->lookahead.token = TK_EOS; /* no look-ahead token */ - ls->z = z; - ls->fs = NULL; - ls->linenumber = 1; - ls->lastline = 1; - ls->source = source; - ls->envn = luaS_new(L, LUA_ENV); /* create env name */ - luaS_fix(ls->envn); /* never collect this name */ - luaZ_resizebuffer(ls->L, ls->buff, LUA_MINBUFFER); /* initialize buffer */ -} - - - -/* -** ======================================================= -** LEXICAL ANALYZER -** ======================================================= -*/ - - - -static int check_next (LexState *ls, const char *set) { - if (ls->current == '\0' || !strchr(set, ls->current)) - return 0; - save_and_next(ls); - return 1; -} - - -/* -** change all characters 'from' in buffer to 'to' -*/ -static void buffreplace (LexState *ls, char from, char to) { - size_t n = luaZ_bufflen(ls->buff); - char *p = luaZ_buffer(ls->buff); - while (n--) - if (p[n] == from) p[n] = to; -} - - -#if !defined(getlocaledecpoint) -#define getlocaledecpoint() (localeconv()->decimal_point[0]) -#endif - - -#define buff2d(b,e) luaO_str2d(luaZ_buffer(b), luaZ_bufflen(b) - 1, e) - -/* -** in case of format error, try to change decimal point separator to -** the one defined in the current locale and check again -*/ -static void trydecpoint (LexState *ls, SemInfo *seminfo) { - char old = ls->decpoint; - ls->decpoint = getlocaledecpoint(); - buffreplace(ls, old, ls->decpoint); /* try new decimal separator */ - if (!buff2d(ls->buff, &seminfo->r)) { - /* format error with correct decimal point: no more options */ - buffreplace(ls, ls->decpoint, '.'); /* undo change (for error message) */ - lexerror(ls, "malformed number", TK_NUMBER); - } -} - - -/* LUA_NUMBER */ -/* -** this function is quite liberal in what it accepts, as 'luaO_str2d' -** will reject ill-formed numerals. -*/ -static void read_numeral (LexState *ls, SemInfo *seminfo) { - const char *expo = "Ee"; - int first = ls->current; - lua_assert(lisdigit(ls->current)); - save_and_next(ls); - if (first == '0' && check_next(ls, "Xx")) /* hexadecimal? */ - expo = "Pp"; - for (;;) { - if (check_next(ls, expo)) /* exponent part? */ - check_next(ls, "+-"); /* optional exponent sign */ - if (lisxdigit(ls->current) || ls->current == '.') - save_and_next(ls); - else break; - } - save(ls, '\0'); - buffreplace(ls, '.', ls->decpoint); /* follow locale for decimal point */ - if (!buff2d(ls->buff, &seminfo->r)) /* format error? */ - trydecpoint(ls, seminfo); /* try to update decimal point separator */ -} - - -/* -** skip a sequence '[=*[' or ']=*]' and return its number of '='s or -** -1 if sequence is malformed -*/ -static int skip_sep (LexState *ls) { - int count = 0; - int s = ls->current; - lua_assert(s == '[' || s == ']'); - save_and_next(ls); - while (ls->current == '=') { - save_and_next(ls); - count++; - } - return (ls->current == s) ? count : (-count) - 1; -} - - -static void read_long_string (LexState *ls, SemInfo *seminfo, int sep) { - save_and_next(ls); /* skip 2nd `[' */ - if (currIsNewline(ls)) /* string starts with a newline? */ - inclinenumber(ls); /* skip it */ - for (;;) { - switch (ls->current) { - case EOZ: - lexerror(ls, (seminfo) ? "unfinished long string" : - "unfinished long comment", TK_EOS); - break; /* to avoid warnings */ - case ']': { - if (skip_sep(ls) == sep) { - save_and_next(ls); /* skip 2nd `]' */ - goto endloop; - } - break; - } - case '\n': case '\r': { - save(ls, '\n'); - inclinenumber(ls); - if (!seminfo) luaZ_resetbuffer(ls->buff); /* avoid wasting space */ - break; - } - default: { - if (seminfo) save_and_next(ls); - else next(ls); - } - } - } endloop: - if (seminfo) - seminfo->ts = luaX_newstring(ls, luaZ_buffer(ls->buff) + (2 + sep), - luaZ_bufflen(ls->buff) - 2*(2 + sep)); -} - - -static void escerror (LexState *ls, int *c, int n, const char *msg) { - int i; - luaZ_resetbuffer(ls->buff); /* prepare error message */ - save(ls, '\\'); - for (i = 0; i < n && c[i] != EOZ; i++) - save(ls, c[i]); - lexerror(ls, msg, TK_STRING); -} - - -static int readhexaesc (LexState *ls) { - int c[3], i; /* keep input for error message */ - int r = 0; /* result accumulator */ - c[0] = 'x'; /* for error message */ - for (i = 1; i < 3; i++) { /* read two hexadecimal digits */ - c[i] = next(ls); - if (!lisxdigit(c[i])) - escerror(ls, c, i + 1, "hexadecimal digit expected"); - r = (r << 4) + luaO_hexavalue(c[i]); - } - return r; -} - - -static int readdecesc (LexState *ls) { - int c[3], i; - int r = 0; /* result accumulator */ - for (i = 0; i < 3 && lisdigit(ls->current); i++) { /* read up to 3 digits */ - c[i] = ls->current; - r = 10*r + c[i] - '0'; - next(ls); - } - if (r > UCHAR_MAX) - escerror(ls, c, i, "decimal escape too large"); - return r; -} - - -static void read_string (LexState *ls, int del, SemInfo *seminfo) { - save_and_next(ls); /* keep delimiter (for error messages) */ - while (ls->current != del) { - switch (ls->current) { - case EOZ: - lexerror(ls, "unfinished string", TK_EOS); - break; /* to avoid warnings */ - case '\n': - case '\r': - lexerror(ls, "unfinished string", TK_STRING); - break; /* to avoid warnings */ - case '\\': { /* escape sequences */ - int c; /* final character to be saved */ - next(ls); /* do not save the `\' */ - switch (ls->current) { - case 'a': c = '\a'; goto read_save; - case 'b': c = '\b'; goto read_save; - case 'f': c = '\f'; goto read_save; - case 'n': c = '\n'; goto read_save; - case 'r': c = '\r'; goto read_save; - case 't': c = '\t'; goto read_save; - case 'v': c = '\v'; goto read_save; - case 'x': c = readhexaesc(ls); goto read_save; - case '\n': case '\r': - inclinenumber(ls); c = '\n'; goto only_save; - case '\\': case '\"': case '\'': - c = ls->current; goto read_save; - case EOZ: goto no_save; /* will raise an error next loop */ - case 'z': { /* zap following span of spaces */ - next(ls); /* skip the 'z' */ - while (lisspace(ls->current)) { - if (currIsNewline(ls)) inclinenumber(ls); - else next(ls); - } - goto no_save; - } - default: { - if (!lisdigit(ls->current)) - escerror(ls, &ls->current, 1, "invalid escape sequence"); - /* digital escape \ddd */ - c = readdecesc(ls); - goto only_save; - } - } - read_save: next(ls); /* read next character */ - only_save: save(ls, c); /* save 'c' */ - no_save: break; - } - default: - save_and_next(ls); - } - } - save_and_next(ls); /* skip delimiter */ - seminfo->ts = luaX_newstring(ls, luaZ_buffer(ls->buff) + 1, - luaZ_bufflen(ls->buff) - 2); -} - - -static int llex (LexState *ls, SemInfo *seminfo) { - luaZ_resetbuffer(ls->buff); - for (;;) { - switch (ls->current) { - case '\n': case '\r': { /* line breaks */ - inclinenumber(ls); - break; - } - case ' ': case '\f': case '\t': case '\v': { /* spaces */ - next(ls); - break; - } - case '-': { /* '-' or '--' (comment) */ - next(ls); - if (ls->current != '-') return '-'; - /* else is a comment */ - next(ls); - if (ls->current == '[') { /* long comment? */ - int sep = skip_sep(ls); - luaZ_resetbuffer(ls->buff); /* `skip_sep' may dirty the buffer */ - if (sep >= 0) { - read_long_string(ls, NULL, sep); /* skip long comment */ - luaZ_resetbuffer(ls->buff); /* previous call may dirty the buff. */ - break; - } - } - /* else short comment */ - while (!currIsNewline(ls) && ls->current != EOZ) - next(ls); /* skip until end of line (or end of file) */ - break; - } - case '[': { /* long string or simply '[' */ - int sep = skip_sep(ls); - if (sep >= 0) { - read_long_string(ls, seminfo, sep); - return TK_STRING; - } - else if (sep == -1) return '['; - else lexerror(ls, "invalid long string delimiter", TK_STRING); - } - case '=': { - next(ls); - if (ls->current != '=') return '='; - else { next(ls); return TK_EQ; } - } - case '<': { - next(ls); - if (ls->current != '=') return '<'; - else { next(ls); return TK_LE; } - } - case '>': { - next(ls); - if (ls->current != '=') return '>'; - else { next(ls); return TK_GE; } - } - case '~': { - next(ls); - if (ls->current != '=') return '~'; - else { next(ls); return TK_NE; } - } - case ':': { - next(ls); - if (ls->current != ':') return ':'; - else { next(ls); return TK_DBCOLON; } - } - case '"': case '\'': { /* short literal strings */ - read_string(ls, ls->current, seminfo); - return TK_STRING; - } - case '.': { /* '.', '..', '...', or number */ - save_and_next(ls); - if (check_next(ls, ".")) { - if (check_next(ls, ".")) - return TK_DOTS; /* '...' */ - else return TK_CONCAT; /* '..' */ - } - else if (!lisdigit(ls->current)) return '.'; - /* else go through */ - } - case '0': case '1': case '2': case '3': case '4': - case '5': case '6': case '7': case '8': case '9': { - read_numeral(ls, seminfo); - return TK_NUMBER; - } - case EOZ: { - return TK_EOS; - } - default: { - if (lislalpha(ls->current)) { /* identifier or reserved word? */ - TString *ts; - do { - save_and_next(ls); - } while (lislalnum(ls->current)); - ts = luaX_newstring(ls, luaZ_buffer(ls->buff), - luaZ_bufflen(ls->buff)); - seminfo->ts = ts; - if (isreserved(ts)) /* reserved word? */ - return ts->tsv.extra - 1 + FIRST_RESERVED; - else { - return TK_NAME; - } - } - else { /* single-char tokens (+ - / ...) */ - int c = ls->current; - next(ls); - return c; - } - } - } - } -} - - -void luaX_next (LexState *ls) { - ls->lastline = ls->linenumber; - if (ls->lookahead.token != TK_EOS) { /* is there a look-ahead token? */ - ls->t = ls->lookahead; /* use this one */ - ls->lookahead.token = TK_EOS; /* and discharge it */ - } - else - ls->t.token = llex(ls, &ls->t.seminfo); /* read next token */ -} - - -int luaX_lookahead (LexState *ls) { - lua_assert(ls->lookahead.token == TK_EOS); - ls->lookahead.token = llex(ls, &ls->lookahead.seminfo); - return ls->lookahead.token; -} - diff --git a/lib/lua-5.2/src/llex.h b/lib/lua-5.2/src/llex.h deleted file mode 100644 index a4acdd3..0000000 --- a/lib/lua-5.2/src/llex.h +++ /dev/null @@ -1,78 +0,0 @@ -/* -** $Id: llex.h,v 1.72.1.1 2013/04/12 18:48:47 roberto Exp $ -** Lexical Analyzer -** See Copyright Notice in lua.h -*/ - -#ifndef llex_h -#define llex_h - -#include "lobject.h" -#include "lzio.h" - - -#define FIRST_RESERVED 257 - - - -/* -* WARNING: if you change the order of this enumeration, -* grep "ORDER RESERVED" -*/ -enum RESERVED { - /* terminal symbols denoted by reserved words */ - TK_AND = FIRST_RESERVED, TK_BREAK, - TK_DO, TK_ELSE, TK_ELSEIF, TK_END, TK_FALSE, TK_FOR, TK_FUNCTION, - TK_GOTO, TK_IF, TK_IN, TK_LOCAL, TK_NIL, TK_NOT, TK_OR, TK_REPEAT, - TK_RETURN, TK_THEN, TK_TRUE, TK_UNTIL, TK_WHILE, - /* other terminal symbols */ - TK_CONCAT, TK_DOTS, TK_EQ, TK_GE, TK_LE, TK_NE, TK_DBCOLON, TK_EOS, - TK_NUMBER, TK_NAME, TK_STRING -}; - -/* number of reserved words */ -#define NUM_RESERVED (cast(int, TK_WHILE-FIRST_RESERVED+1)) - - -typedef union { - lua_Number r; - TString *ts; -} SemInfo; /* semantics information */ - - -typedef struct Token { - int token; - SemInfo seminfo; -} Token; - - -/* state of the lexer plus state of the parser when shared by all - functions */ -typedef struct LexState { - int current; /* current character (charint) */ - int linenumber; /* input line counter */ - int lastline; /* line of last token `consumed' */ - Token t; /* current token */ - Token lookahead; /* look ahead token */ - struct FuncState *fs; /* current function (parser) */ - struct lua_State *L; - ZIO *z; /* input stream */ - Mbuffer *buff; /* buffer for tokens */ - struct Dyndata *dyd; /* dynamic structures used by the parser */ - TString *source; /* current source name */ - TString *envn; /* environment variable name */ - char decpoint; /* locale decimal point */ -} LexState; - - -LUAI_FUNC void luaX_init (lua_State *L); -LUAI_FUNC void luaX_setinput (lua_State *L, LexState *ls, ZIO *z, - TString *source, int firstchar); -LUAI_FUNC TString *luaX_newstring (LexState *ls, const char *str, size_t l); -LUAI_FUNC void luaX_next (LexState *ls); -LUAI_FUNC int luaX_lookahead (LexState *ls); -LUAI_FUNC l_noret luaX_syntaxerror (LexState *ls, const char *s); -LUAI_FUNC const char *luaX_token2str (LexState *ls, int token); - - -#endif diff --git a/lib/lua-5.2/src/llimits.h b/lib/lua-5.2/src/llimits.h deleted file mode 100644 index 152dd05..0000000 --- a/lib/lua-5.2/src/llimits.h +++ /dev/null @@ -1,309 +0,0 @@ -/* -** $Id: llimits.h,v 1.103.1.1 2013/04/12 18:48:47 roberto Exp $ -** Limits, basic types, and some other `installation-dependent' definitions -** See Copyright Notice in lua.h -*/ - -#ifndef llimits_h -#define llimits_h - - -#include -#include - - -#include "lua.h" - - -typedef unsigned LUA_INT32 lu_int32; - -typedef LUAI_UMEM lu_mem; - -typedef LUAI_MEM l_mem; - - - -/* chars used as small naturals (so that `char' is reserved for characters) */ -typedef unsigned char lu_byte; - - -#define MAX_SIZET ((size_t)(~(size_t)0)-2) - -#define MAX_LUMEM ((lu_mem)(~(lu_mem)0)-2) - -#define MAX_LMEM ((l_mem) ((MAX_LUMEM >> 1) - 2)) - - -#define MAX_INT (INT_MAX-2) /* maximum value of an int (-2 for safety) */ - -/* -** conversion of pointer to integer -** this is for hashing only; there is no problem if the integer -** cannot hold the whole pointer value -*/ -#define IntPoint(p) ((unsigned int)(lu_mem)(p)) - - - -/* type to ensure maximum alignment */ -#if !defined(LUAI_USER_ALIGNMENT_T) -#define LUAI_USER_ALIGNMENT_T union { double u; void *s; long l; } -#endif - -typedef LUAI_USER_ALIGNMENT_T L_Umaxalign; - - -/* result of a `usual argument conversion' over lua_Number */ -typedef LUAI_UACNUMBER l_uacNumber; - - -/* internal assertions for in-house debugging */ -#if defined(lua_assert) -#define check_exp(c,e) (lua_assert(c), (e)) -/* to avoid problems with conditions too long */ -#define lua_longassert(c) { if (!(c)) lua_assert(0); } -#else -#define lua_assert(c) ((void)0) -#define check_exp(c,e) (e) -#define lua_longassert(c) ((void)0) -#endif - -/* -** assertion for checking API calls -*/ -#if !defined(luai_apicheck) - -#if defined(LUA_USE_APICHECK) -#include -#define luai_apicheck(L,e) assert(e) -#else -#define luai_apicheck(L,e) lua_assert(e) -#endif - -#endif - -#define api_check(l,e,msg) luai_apicheck(l,(e) && msg) - - -#if !defined(UNUSED) -#define UNUSED(x) ((void)(x)) /* to avoid warnings */ -#endif - - -#define cast(t, exp) ((t)(exp)) - -#define cast_byte(i) cast(lu_byte, (i)) -#define cast_num(i) cast(lua_Number, (i)) -#define cast_int(i) cast(int, (i)) -#define cast_uchar(i) cast(unsigned char, (i)) - - -/* -** non-return type -*/ -#if defined(__GNUC__) -#define l_noret void __attribute__((noreturn)) -#elif defined(_MSC_VER) -#define l_noret void __declspec(noreturn) -#else -#define l_noret void -#endif - - - -/* -** maximum depth for nested C calls and syntactical nested non-terminals -** in a program. (Value must fit in an unsigned short int.) -*/ -#if !defined(LUAI_MAXCCALLS) -#define LUAI_MAXCCALLS 200 -#endif - -/* -** maximum number of upvalues in a closure (both C and Lua). (Value -** must fit in an unsigned char.) -*/ -#define MAXUPVAL UCHAR_MAX - - -/* -** type for virtual-machine instructions -** must be an unsigned with (at least) 4 bytes (see details in lopcodes.h) -*/ -typedef lu_int32 Instruction; - - - -/* maximum stack for a Lua function */ -#define MAXSTACK 250 - - - -/* minimum size for the string table (must be power of 2) */ -#if !defined(MINSTRTABSIZE) -#define MINSTRTABSIZE 32 -#endif - - -/* minimum size for string buffer */ -#if !defined(LUA_MINBUFFER) -#define LUA_MINBUFFER 32 -#endif - - -#if !defined(lua_lock) -#define lua_lock(L) ((void) 0) -#define lua_unlock(L) ((void) 0) -#endif - -#if !defined(luai_threadyield) -#define luai_threadyield(L) {lua_unlock(L); lua_lock(L);} -#endif - - -/* -** these macros allow user-specific actions on threads when you defined -** LUAI_EXTRASPACE and need to do something extra when a thread is -** created/deleted/resumed/yielded. -*/ -#if !defined(luai_userstateopen) -#define luai_userstateopen(L) ((void)L) -#endif - -#if !defined(luai_userstateclose) -#define luai_userstateclose(L) ((void)L) -#endif - -#if !defined(luai_userstatethread) -#define luai_userstatethread(L,L1) ((void)L) -#endif - -#if !defined(luai_userstatefree) -#define luai_userstatefree(L,L1) ((void)L) -#endif - -#if !defined(luai_userstateresume) -#define luai_userstateresume(L,n) ((void)L) -#endif - -#if !defined(luai_userstateyield) -#define luai_userstateyield(L,n) ((void)L) -#endif - -/* -** lua_number2int is a macro to convert lua_Number to int. -** lua_number2integer is a macro to convert lua_Number to lua_Integer. -** lua_number2unsigned is a macro to convert a lua_Number to a lua_Unsigned. -** lua_unsigned2number is a macro to convert a lua_Unsigned to a lua_Number. -** luai_hashnum is a macro to hash a lua_Number value into an integer. -** The hash must be deterministic and give reasonable values for -** both small and large values (outside the range of integers). -*/ - -#if defined(MS_ASMTRICK) || defined(LUA_MSASMTRICK) /* { */ -/* trick with Microsoft assembler for X86 */ - -#define lua_number2int(i,n) __asm {__asm fld n __asm fistp i} -#define lua_number2integer(i,n) lua_number2int(i, n) -#define lua_number2unsigned(i,n) \ - {__int64 l; __asm {__asm fld n __asm fistp l} i = (unsigned int)l;} - - -#elif defined(LUA_IEEE754TRICK) /* }{ */ -/* the next trick should work on any machine using IEEE754 with - a 32-bit int type */ - -union luai_Cast { double l_d; LUA_INT32 l_p[2]; }; - -#if !defined(LUA_IEEEENDIAN) /* { */ -#define LUAI_EXTRAIEEE \ - static const union luai_Cast ieeeendian = {-(33.0 + 6755399441055744.0)}; -#define LUA_IEEEENDIANLOC (ieeeendian.l_p[1] == 33) -#else -#define LUA_IEEEENDIANLOC LUA_IEEEENDIAN -#define LUAI_EXTRAIEEE /* empty */ -#endif /* } */ - -#define lua_number2int32(i,n,t) \ - { LUAI_EXTRAIEEE \ - volatile union luai_Cast u; u.l_d = (n) + 6755399441055744.0; \ - (i) = (t)u.l_p[LUA_IEEEENDIANLOC]; } - -#define luai_hashnum(i,n) \ - { volatile union luai_Cast u; u.l_d = (n) + 1.0; /* avoid -0 */ \ - (i) = u.l_p[0]; (i) += u.l_p[1]; } /* add double bits for his hash */ - -#define lua_number2int(i,n) lua_number2int32(i, n, int) -#define lua_number2unsigned(i,n) lua_number2int32(i, n, lua_Unsigned) - -/* the trick can be expanded to lua_Integer when it is a 32-bit value */ -#if defined(LUA_IEEELL) -#define lua_number2integer(i,n) lua_number2int32(i, n, lua_Integer) -#endif - -#endif /* } */ - - -/* the following definitions always work, but may be slow */ - -#if !defined(lua_number2int) -#define lua_number2int(i,n) ((i)=(int)(n)) -#endif - -#if !defined(lua_number2integer) -#define lua_number2integer(i,n) ((i)=(lua_Integer)(n)) -#endif - -#if !defined(lua_number2unsigned) /* { */ -/* the following definition assures proper modulo behavior */ -#if defined(LUA_NUMBER_DOUBLE) || defined(LUA_NUMBER_FLOAT) -#include -#define SUPUNSIGNED ((lua_Number)(~(lua_Unsigned)0) + 1) -#define lua_number2unsigned(i,n) \ - ((i)=(lua_Unsigned)((n) - floor((n)/SUPUNSIGNED)*SUPUNSIGNED)) -#else -#define lua_number2unsigned(i,n) ((i)=(lua_Unsigned)(n)) -#endif -#endif /* } */ - - -#if !defined(lua_unsigned2number) -/* on several machines, coercion from unsigned to double is slow, - so it may be worth to avoid */ -#define lua_unsigned2number(u) \ - (((u) <= (lua_Unsigned)INT_MAX) ? (lua_Number)(int)(u) : (lua_Number)(u)) -#endif - - - -#if defined(ltable_c) && !defined(luai_hashnum) - -#include -#include - -#define luai_hashnum(i,n) { int e; \ - n = l_mathop(frexp)(n, &e) * (lua_Number)(INT_MAX - DBL_MAX_EXP); \ - lua_number2int(i, n); i += e; } - -#endif - - - -/* -** macro to control inclusion of some hard tests on stack reallocation -*/ -#if !defined(HARDSTACKTESTS) -#define condmovestack(L) ((void)0) -#else -/* realloc stack keeping its size */ -#define condmovestack(L) luaD_reallocstack((L), (L)->stacksize) -#endif - -#if !defined(HARDMEMTESTS) -#define condchangemem(L) condmovestack(L) -#else -#define condchangemem(L) \ - ((void)(!(G(L)->gcrunning) || (luaC_fullgc(L, 0), 1))) -#endif - -#endif diff --git a/lib/lua-5.2/src/lmathlib.c b/lib/lua-5.2/src/lmathlib.c deleted file mode 100644 index fe9fc54..0000000 --- a/lib/lua-5.2/src/lmathlib.c +++ /dev/null @@ -1,279 +0,0 @@ -/* -** $Id: lmathlib.c,v 1.83.1.1 2013/04/12 18:48:47 roberto Exp $ -** Standard mathematical library -** See Copyright Notice in lua.h -*/ - - -#include -#include - -#define lmathlib_c -#define LUA_LIB - -#include "lua.h" - -#include "lauxlib.h" -#include "lualib.h" - - -#undef PI -#define PI ((lua_Number)(3.1415926535897932384626433832795)) -#define RADIANS_PER_DEGREE ((lua_Number)(PI/180.0)) - - - -static int math_abs (lua_State *L) { - lua_pushnumber(L, l_mathop(fabs)(luaL_checknumber(L, 1))); - return 1; -} - -static int math_sin (lua_State *L) { - lua_pushnumber(L, l_mathop(sin)(luaL_checknumber(L, 1))); - return 1; -} - -static int math_sinh (lua_State *L) { - lua_pushnumber(L, l_mathop(sinh)(luaL_checknumber(L, 1))); - return 1; -} - -static int math_cos (lua_State *L) { - lua_pushnumber(L, l_mathop(cos)(luaL_checknumber(L, 1))); - return 1; -} - -static int math_cosh (lua_State *L) { - lua_pushnumber(L, l_mathop(cosh)(luaL_checknumber(L, 1))); - return 1; -} - -static int math_tan (lua_State *L) { - lua_pushnumber(L, l_mathop(tan)(luaL_checknumber(L, 1))); - return 1; -} - -static int math_tanh (lua_State *L) { - lua_pushnumber(L, l_mathop(tanh)(luaL_checknumber(L, 1))); - return 1; -} - -static int math_asin (lua_State *L) { - lua_pushnumber(L, l_mathop(asin)(luaL_checknumber(L, 1))); - return 1; -} - -static int math_acos (lua_State *L) { - lua_pushnumber(L, l_mathop(acos)(luaL_checknumber(L, 1))); - return 1; -} - -static int math_atan (lua_State *L) { - lua_pushnumber(L, l_mathop(atan)(luaL_checknumber(L, 1))); - return 1; -} - -static int math_atan2 (lua_State *L) { - lua_pushnumber(L, l_mathop(atan2)(luaL_checknumber(L, 1), - luaL_checknumber(L, 2))); - return 1; -} - -static int math_ceil (lua_State *L) { - lua_pushnumber(L, l_mathop(ceil)(luaL_checknumber(L, 1))); - return 1; -} - -static int math_floor (lua_State *L) { - lua_pushnumber(L, l_mathop(floor)(luaL_checknumber(L, 1))); - return 1; -} - -static int math_fmod (lua_State *L) { - lua_pushnumber(L, l_mathop(fmod)(luaL_checknumber(L, 1), - luaL_checknumber(L, 2))); - return 1; -} - -static int math_modf (lua_State *L) { - lua_Number ip; - lua_Number fp = l_mathop(modf)(luaL_checknumber(L, 1), &ip); - lua_pushnumber(L, ip); - lua_pushnumber(L, fp); - return 2; -} - -static int math_sqrt (lua_State *L) { - lua_pushnumber(L, l_mathop(sqrt)(luaL_checknumber(L, 1))); - return 1; -} - -static int math_pow (lua_State *L) { - lua_Number x = luaL_checknumber(L, 1); - lua_Number y = luaL_checknumber(L, 2); - lua_pushnumber(L, l_mathop(pow)(x, y)); - return 1; -} - -static int math_log (lua_State *L) { - lua_Number x = luaL_checknumber(L, 1); - lua_Number res; - if (lua_isnoneornil(L, 2)) - res = l_mathop(log)(x); - else { - lua_Number base = luaL_checknumber(L, 2); - if (base == (lua_Number)10.0) res = l_mathop(log10)(x); - else res = l_mathop(log)(x)/l_mathop(log)(base); - } - lua_pushnumber(L, res); - return 1; -} - -#if defined(LUA_COMPAT_LOG10) -static int math_log10 (lua_State *L) { - lua_pushnumber(L, l_mathop(log10)(luaL_checknumber(L, 1))); - return 1; -} -#endif - -static int math_exp (lua_State *L) { - lua_pushnumber(L, l_mathop(exp)(luaL_checknumber(L, 1))); - return 1; -} - -static int math_deg (lua_State *L) { - lua_pushnumber(L, luaL_checknumber(L, 1)/RADIANS_PER_DEGREE); - return 1; -} - -static int math_rad (lua_State *L) { - lua_pushnumber(L, luaL_checknumber(L, 1)*RADIANS_PER_DEGREE); - return 1; -} - -static int math_frexp (lua_State *L) { - int e; - lua_pushnumber(L, l_mathop(frexp)(luaL_checknumber(L, 1), &e)); - lua_pushinteger(L, e); - return 2; -} - -static int math_ldexp (lua_State *L) { - lua_Number x = luaL_checknumber(L, 1); - int ep = luaL_checkint(L, 2); - lua_pushnumber(L, l_mathop(ldexp)(x, ep)); - return 1; -} - - - -static int math_min (lua_State *L) { - int n = lua_gettop(L); /* number of arguments */ - lua_Number dmin = luaL_checknumber(L, 1); - int i; - for (i=2; i<=n; i++) { - lua_Number d = luaL_checknumber(L, i); - if (d < dmin) - dmin = d; - } - lua_pushnumber(L, dmin); - return 1; -} - - -static int math_max (lua_State *L) { - int n = lua_gettop(L); /* number of arguments */ - lua_Number dmax = luaL_checknumber(L, 1); - int i; - for (i=2; i<=n; i++) { - lua_Number d = luaL_checknumber(L, i); - if (d > dmax) - dmax = d; - } - lua_pushnumber(L, dmax); - return 1; -} - - -static int math_random (lua_State *L) { - /* the `%' avoids the (rare) case of r==1, and is needed also because on - some systems (SunOS!) `rand()' may return a value larger than RAND_MAX */ - lua_Number r = (lua_Number)(rand()%RAND_MAX) / (lua_Number)RAND_MAX; - switch (lua_gettop(L)) { /* check number of arguments */ - case 0: { /* no arguments */ - lua_pushnumber(L, r); /* Number between 0 and 1 */ - break; - } - case 1: { /* only upper limit */ - lua_Number u = luaL_checknumber(L, 1); - luaL_argcheck(L, (lua_Number)1.0 <= u, 1, "interval is empty"); - lua_pushnumber(L, l_mathop(floor)(r*u) + (lua_Number)(1.0)); /* [1, u] */ - break; - } - case 2: { /* lower and upper limits */ - lua_Number l = luaL_checknumber(L, 1); - lua_Number u = luaL_checknumber(L, 2); - luaL_argcheck(L, l <= u, 2, "interval is empty"); - lua_pushnumber(L, l_mathop(floor)(r*(u-l+1)) + l); /* [l, u] */ - break; - } - default: return luaL_error(L, "wrong number of arguments"); - } - return 1; -} - - -static int math_randomseed (lua_State *L) { - srand(luaL_checkunsigned(L, 1)); - (void)rand(); /* discard first value to avoid undesirable correlations */ - return 0; -} - - -static const luaL_Reg mathlib[] = { - {"abs", math_abs}, - {"acos", math_acos}, - {"asin", math_asin}, - {"atan2", math_atan2}, - {"atan", math_atan}, - {"ceil", math_ceil}, - {"cosh", math_cosh}, - {"cos", math_cos}, - {"deg", math_deg}, - {"exp", math_exp}, - {"floor", math_floor}, - {"fmod", math_fmod}, - {"frexp", math_frexp}, - {"ldexp", math_ldexp}, -#if defined(LUA_COMPAT_LOG10) - {"log10", math_log10}, -#endif - {"log", math_log}, - {"max", math_max}, - {"min", math_min}, - {"modf", math_modf}, - {"pow", math_pow}, - {"rad", math_rad}, - {"random", math_random}, - {"randomseed", math_randomseed}, - {"sinh", math_sinh}, - {"sin", math_sin}, - {"sqrt", math_sqrt}, - {"tanh", math_tanh}, - {"tan", math_tan}, - {NULL, NULL} -}; - - -/* -** Open math library -*/ -LUAMOD_API int luaopen_math (lua_State *L) { - luaL_newlib(L, mathlib); - lua_pushnumber(L, PI); - lua_setfield(L, -2, "pi"); - lua_pushnumber(L, HUGE_VAL); - lua_setfield(L, -2, "huge"); - return 1; -} - diff --git a/lib/lua-5.2/src/lmem.c b/lib/lua-5.2/src/lmem.c deleted file mode 100644 index ee343e3..0000000 --- a/lib/lua-5.2/src/lmem.c +++ /dev/null @@ -1,99 +0,0 @@ -/* -** $Id: lmem.c,v 1.84.1.1 2013/04/12 18:48:47 roberto Exp $ -** Interface to Memory Manager -** See Copyright Notice in lua.h -*/ - - -#include - -#define lmem_c -#define LUA_CORE - -#include "lua.h" - -#include "ldebug.h" -#include "ldo.h" -#include "lgc.h" -#include "lmem.h" -#include "lobject.h" -#include "lstate.h" - - - -/* -** About the realloc function: -** void * frealloc (void *ud, void *ptr, size_t osize, size_t nsize); -** (`osize' is the old size, `nsize' is the new size) -** -** * frealloc(ud, NULL, x, s) creates a new block of size `s' (no -** matter 'x'). -** -** * frealloc(ud, p, x, 0) frees the block `p' -** (in this specific case, frealloc must return NULL); -** particularly, frealloc(ud, NULL, 0, 0) does nothing -** (which is equivalent to free(NULL) in ANSI C) -** -** frealloc returns NULL if it cannot create or reallocate the area -** (any reallocation to an equal or smaller size cannot fail!) -*/ - - - -#define MINSIZEARRAY 4 - - -void *luaM_growaux_ (lua_State *L, void *block, int *size, size_t size_elems, - int limit, const char *what) { - void *newblock; - int newsize; - if (*size >= limit/2) { /* cannot double it? */ - if (*size >= limit) /* cannot grow even a little? */ - luaG_runerror(L, "too many %s (limit is %d)", what, limit); - newsize = limit; /* still have at least one free place */ - } - else { - newsize = (*size)*2; - if (newsize < MINSIZEARRAY) - newsize = MINSIZEARRAY; /* minimum size */ - } - newblock = luaM_reallocv(L, block, *size, newsize, size_elems); - *size = newsize; /* update only when everything else is OK */ - return newblock; -} - - -l_noret luaM_toobig (lua_State *L) { - luaG_runerror(L, "memory allocation error: block too big"); -} - - - -/* -** generic allocation routine. -*/ -void *luaM_realloc_ (lua_State *L, void *block, size_t osize, size_t nsize) { - void *newblock; - global_State *g = G(L); - size_t realosize = (block) ? osize : 0; - lua_assert((realosize == 0) == (block == NULL)); -#if defined(HARDMEMTESTS) - if (nsize > realosize && g->gcrunning) - luaC_fullgc(L, 1); /* force a GC whenever possible */ -#endif - newblock = (*g->frealloc)(g->ud, block, osize, nsize); - if (newblock == NULL && nsize > 0) { - api_check(L, nsize > realosize, - "realloc cannot fail when shrinking a block"); - if (g->gcrunning) { - luaC_fullgc(L, 1); /* try to free some memory... */ - newblock = (*g->frealloc)(g->ud, block, osize, nsize); /* try again */ - } - if (newblock == NULL) - luaD_throw(L, LUA_ERRMEM); - } - lua_assert((nsize == 0) == (newblock == NULL)); - g->GCdebt = (g->GCdebt + nsize) - realosize; - return newblock; -} - diff --git a/lib/lua-5.2/src/lmem.h b/lib/lua-5.2/src/lmem.h deleted file mode 100644 index bd4f4e0..0000000 --- a/lib/lua-5.2/src/lmem.h +++ /dev/null @@ -1,57 +0,0 @@ -/* -** $Id: lmem.h,v 1.40.1.1 2013/04/12 18:48:47 roberto Exp $ -** Interface to Memory Manager -** See Copyright Notice in lua.h -*/ - -#ifndef lmem_h -#define lmem_h - - -#include - -#include "llimits.h" -#include "lua.h" - - -/* -** This macro avoids the runtime division MAX_SIZET/(e), as 'e' is -** always constant. -** The macro is somewhat complex to avoid warnings: -** +1 avoids warnings of "comparison has constant result"; -** cast to 'void' avoids warnings of "value unused". -*/ -#define luaM_reallocv(L,b,on,n,e) \ - (cast(void, \ - (cast(size_t, (n)+1) > MAX_SIZET/(e)) ? (luaM_toobig(L), 0) : 0), \ - luaM_realloc_(L, (b), (on)*(e), (n)*(e))) - -#define luaM_freemem(L, b, s) luaM_realloc_(L, (b), (s), 0) -#define luaM_free(L, b) luaM_realloc_(L, (b), sizeof(*(b)), 0) -#define luaM_freearray(L, b, n) luaM_reallocv(L, (b), n, 0, sizeof((b)[0])) - -#define luaM_malloc(L,s) luaM_realloc_(L, NULL, 0, (s)) -#define luaM_new(L,t) cast(t *, luaM_malloc(L, sizeof(t))) -#define luaM_newvector(L,n,t) \ - cast(t *, luaM_reallocv(L, NULL, 0, n, sizeof(t))) - -#define luaM_newobject(L,tag,s) luaM_realloc_(L, NULL, tag, (s)) - -#define luaM_growvector(L,v,nelems,size,t,limit,e) \ - if ((nelems)+1 > (size)) \ - ((v)=cast(t *, luaM_growaux_(L,v,&(size),sizeof(t),limit,e))) - -#define luaM_reallocvector(L, v,oldn,n,t) \ - ((v)=cast(t *, luaM_reallocv(L, v, oldn, n, sizeof(t)))) - -LUAI_FUNC l_noret luaM_toobig (lua_State *L); - -/* not to be called directly */ -LUAI_FUNC void *luaM_realloc_ (lua_State *L, void *block, size_t oldsize, - size_t size); -LUAI_FUNC void *luaM_growaux_ (lua_State *L, void *block, int *size, - size_t size_elem, int limit, - const char *what); - -#endif - diff --git a/lib/lua-5.2/src/loadlib.c b/lib/lua-5.2/src/loadlib.c deleted file mode 100644 index bedbea3..0000000 --- a/lib/lua-5.2/src/loadlib.c +++ /dev/null @@ -1,725 +0,0 @@ -/* -** $Id: loadlib.c,v 1.111.1.1 2013/04/12 18:48:47 roberto Exp $ -** Dynamic library loader for Lua -** See Copyright Notice in lua.h -** -** This module contains an implementation of loadlib for Unix systems -** that have dlfcn, an implementation for Windows, and a stub for other -** systems. -*/ - - -/* -** if needed, includes windows header before everything else -*/ -#if defined(_WIN32) -#include -#endif - - -#include -#include - - -#define loadlib_c -#define LUA_LIB - -#include "lua.h" - -#include "lauxlib.h" -#include "lualib.h" - - -/* -** LUA_PATH and LUA_CPATH are the names of the environment -** variables that Lua check to set its paths. -*/ -#if !defined(LUA_PATH) -#define LUA_PATH "LUA_PATH" -#endif - -#if !defined(LUA_CPATH) -#define LUA_CPATH "LUA_CPATH" -#endif - -#define LUA_PATHSUFFIX "_" LUA_VERSION_MAJOR "_" LUA_VERSION_MINOR - -#define LUA_PATHVERSION LUA_PATH LUA_PATHSUFFIX -#define LUA_CPATHVERSION LUA_CPATH LUA_PATHSUFFIX - -/* -** LUA_PATH_SEP is the character that separates templates in a path. -** LUA_PATH_MARK is the string that marks the substitution points in a -** template. -** LUA_EXEC_DIR in a Windows path is replaced by the executable's -** directory. -** LUA_IGMARK is a mark to ignore all before it when building the -** luaopen_ function name. -*/ -#if !defined (LUA_PATH_SEP) -#define LUA_PATH_SEP ";" -#endif -#if !defined (LUA_PATH_MARK) -#define LUA_PATH_MARK "?" -#endif -#if !defined (LUA_EXEC_DIR) -#define LUA_EXEC_DIR "!" -#endif -#if !defined (LUA_IGMARK) -#define LUA_IGMARK "-" -#endif - - -/* -** LUA_CSUBSEP is the character that replaces dots in submodule names -** when searching for a C loader. -** LUA_LSUBSEP is the character that replaces dots in submodule names -** when searching for a Lua loader. -*/ -#if !defined(LUA_CSUBSEP) -#define LUA_CSUBSEP LUA_DIRSEP -#endif - -#if !defined(LUA_LSUBSEP) -#define LUA_LSUBSEP LUA_DIRSEP -#endif - - -/* prefix for open functions in C libraries */ -#define LUA_POF "luaopen_" - -/* separator for open functions in C libraries */ -#define LUA_OFSEP "_" - - -/* table (in the registry) that keeps handles for all loaded C libraries */ -#define CLIBS "_CLIBS" - -#define LIB_FAIL "open" - - -/* error codes for ll_loadfunc */ -#define ERRLIB 1 -#define ERRFUNC 2 - -#define setprogdir(L) ((void)0) - - -/* -** system-dependent functions -*/ -static void ll_unloadlib (void *lib); -static void *ll_load (lua_State *L, const char *path, int seeglb); -static lua_CFunction ll_sym (lua_State *L, void *lib, const char *sym); - - - -#if defined(LUA_USE_DLOPEN) -/* -** {======================================================================== -** This is an implementation of loadlib based on the dlfcn interface. -** The dlfcn interface is available in Linux, SunOS, Solaris, IRIX, FreeBSD, -** NetBSD, AIX 4.2, HPUX 11, and probably most other Unix flavors, at least -** as an emulation layer on top of native functions. -** ========================================================================= -*/ - -#include - -static void ll_unloadlib (void *lib) { - dlclose(lib); -} - - -static void *ll_load (lua_State *L, const char *path, int seeglb) { - void *lib = dlopen(path, RTLD_NOW | (seeglb ? RTLD_GLOBAL : RTLD_LOCAL)); - if (lib == NULL) lua_pushstring(L, dlerror()); - return lib; -} - - -static lua_CFunction ll_sym (lua_State *L, void *lib, const char *sym) { - lua_CFunction f = (lua_CFunction)dlsym(lib, sym); - if (f == NULL) lua_pushstring(L, dlerror()); - return f; -} - -/* }====================================================== */ - - - -#elif defined(LUA_DL_DLL) -/* -** {====================================================================== -** This is an implementation of loadlib for Windows using native functions. -** ======================================================================= -*/ - -#undef setprogdir - -/* -** optional flags for LoadLibraryEx -*/ -#if !defined(LUA_LLE_FLAGS) -#define LUA_LLE_FLAGS 0 -#endif - - -static void setprogdir (lua_State *L) { - char buff[MAX_PATH + 1]; - char *lb; - DWORD nsize = sizeof(buff)/sizeof(char); - DWORD n = GetModuleFileNameA(NULL, buff, nsize); - if (n == 0 || n == nsize || (lb = strrchr(buff, '\\')) == NULL) - luaL_error(L, "unable to get ModuleFileName"); - else { - *lb = '\0'; - luaL_gsub(L, lua_tostring(L, -1), LUA_EXEC_DIR, buff); - lua_remove(L, -2); /* remove original string */ - } -} - - -static void pusherror (lua_State *L) { - int error = GetLastError(); - char buffer[128]; - if (FormatMessageA(FORMAT_MESSAGE_IGNORE_INSERTS | FORMAT_MESSAGE_FROM_SYSTEM, - NULL, error, 0, buffer, sizeof(buffer)/sizeof(char), NULL)) - lua_pushstring(L, buffer); - else - lua_pushfstring(L, "system error %d\n", error); -} - -static void ll_unloadlib (void *lib) { - FreeLibrary((HMODULE)lib); -} - - -static void *ll_load (lua_State *L, const char *path, int seeglb) { - HMODULE lib = LoadLibraryExA(path, NULL, LUA_LLE_FLAGS); - (void)(seeglb); /* not used: symbols are 'global' by default */ - if (lib == NULL) pusherror(L); - return lib; -} - - -static lua_CFunction ll_sym (lua_State *L, void *lib, const char *sym) { - lua_CFunction f = (lua_CFunction)GetProcAddress((HMODULE)lib, sym); - if (f == NULL) pusherror(L); - return f; -} - -/* }====================================================== */ - - -#else -/* -** {====================================================== -** Fallback for other systems -** ======================================================= -*/ - -#undef LIB_FAIL -#define LIB_FAIL "absent" - - -#define DLMSG "dynamic libraries not enabled; check your Lua installation" - - -static void ll_unloadlib (void *lib) { - (void)(lib); /* not used */ -} - - -static void *ll_load (lua_State *L, const char *path, int seeglb) { - (void)(path); (void)(seeglb); /* not used */ - lua_pushliteral(L, DLMSG); - return NULL; -} - - -static lua_CFunction ll_sym (lua_State *L, void *lib, const char *sym) { - (void)(lib); (void)(sym); /* not used */ - lua_pushliteral(L, DLMSG); - return NULL; -} - -/* }====================================================== */ -#endif - - -static void *ll_checkclib (lua_State *L, const char *path) { - void *plib; - lua_getfield(L, LUA_REGISTRYINDEX, CLIBS); - lua_getfield(L, -1, path); - plib = lua_touserdata(L, -1); /* plib = CLIBS[path] */ - lua_pop(L, 2); /* pop CLIBS table and 'plib' */ - return plib; -} - - -static void ll_addtoclib (lua_State *L, const char *path, void *plib) { - lua_getfield(L, LUA_REGISTRYINDEX, CLIBS); - lua_pushlightuserdata(L, plib); - lua_pushvalue(L, -1); - lua_setfield(L, -3, path); /* CLIBS[path] = plib */ - lua_rawseti(L, -2, luaL_len(L, -2) + 1); /* CLIBS[#CLIBS + 1] = plib */ - lua_pop(L, 1); /* pop CLIBS table */ -} - - -/* -** __gc tag method for CLIBS table: calls 'll_unloadlib' for all lib -** handles in list CLIBS -*/ -static int gctm (lua_State *L) { - int n = luaL_len(L, 1); - for (; n >= 1; n--) { /* for each handle, in reverse order */ - lua_rawgeti(L, 1, n); /* get handle CLIBS[n] */ - ll_unloadlib(lua_touserdata(L, -1)); - lua_pop(L, 1); /* pop handle */ - } - return 0; -} - - -static int ll_loadfunc (lua_State *L, const char *path, const char *sym) { - void *reg = ll_checkclib(L, path); /* check loaded C libraries */ - if (reg == NULL) { /* must load library? */ - reg = ll_load(L, path, *sym == '*'); - if (reg == NULL) return ERRLIB; /* unable to load library */ - ll_addtoclib(L, path, reg); - } - if (*sym == '*') { /* loading only library (no function)? */ - lua_pushboolean(L, 1); /* return 'true' */ - return 0; /* no errors */ - } - else { - lua_CFunction f = ll_sym(L, reg, sym); - if (f == NULL) - return ERRFUNC; /* unable to find function */ - lua_pushcfunction(L, f); /* else create new function */ - return 0; /* no errors */ - } -} - - -static int ll_loadlib (lua_State *L) { - const char *path = luaL_checkstring(L, 1); - const char *init = luaL_checkstring(L, 2); - int stat = ll_loadfunc(L, path, init); - if (stat == 0) /* no errors? */ - return 1; /* return the loaded function */ - else { /* error; error message is on stack top */ - lua_pushnil(L); - lua_insert(L, -2); - lua_pushstring(L, (stat == ERRLIB) ? LIB_FAIL : "init"); - return 3; /* return nil, error message, and where */ - } -} - - - -/* -** {====================================================== -** 'require' function -** ======================================================= -*/ - - -static int readable (const char *filename) { - FILE *f = fopen(filename, "r"); /* try to open file */ - if (f == NULL) return 0; /* open failed */ - fclose(f); - return 1; -} - - -static const char *pushnexttemplate (lua_State *L, const char *path) { - const char *l; - while (*path == *LUA_PATH_SEP) path++; /* skip separators */ - if (*path == '\0') return NULL; /* no more templates */ - l = strchr(path, *LUA_PATH_SEP); /* find next separator */ - if (l == NULL) l = path + strlen(path); - lua_pushlstring(L, path, l - path); /* template */ - return l; -} - - -static const char *searchpath (lua_State *L, const char *name, - const char *path, - const char *sep, - const char *dirsep) { - luaL_Buffer msg; /* to build error message */ - luaL_buffinit(L, &msg); - if (*sep != '\0') /* non-empty separator? */ - name = luaL_gsub(L, name, sep, dirsep); /* replace it by 'dirsep' */ - while ((path = pushnexttemplate(L, path)) != NULL) { - const char *filename = luaL_gsub(L, lua_tostring(L, -1), - LUA_PATH_MARK, name); - lua_remove(L, -2); /* remove path template */ - if (readable(filename)) /* does file exist and is readable? */ - return filename; /* return that file name */ - lua_pushfstring(L, "\n\tno file " LUA_QS, filename); - lua_remove(L, -2); /* remove file name */ - luaL_addvalue(&msg); /* concatenate error msg. entry */ - } - luaL_pushresult(&msg); /* create error message */ - return NULL; /* not found */ -} - - -static int ll_searchpath (lua_State *L) { - const char *f = searchpath(L, luaL_checkstring(L, 1), - luaL_checkstring(L, 2), - luaL_optstring(L, 3, "."), - luaL_optstring(L, 4, LUA_DIRSEP)); - if (f != NULL) return 1; - else { /* error message is on top of the stack */ - lua_pushnil(L); - lua_insert(L, -2); - return 2; /* return nil + error message */ - } -} - - -static const char *findfile (lua_State *L, const char *name, - const char *pname, - const char *dirsep) { - const char *path; - lua_getfield(L, lua_upvalueindex(1), pname); - path = lua_tostring(L, -1); - if (path == NULL) - luaL_error(L, LUA_QL("package.%s") " must be a string", pname); - return searchpath(L, name, path, ".", dirsep); -} - - -static int checkload (lua_State *L, int stat, const char *filename) { - if (stat) { /* module loaded successfully? */ - lua_pushstring(L, filename); /* will be 2nd argument to module */ - return 2; /* return open function and file name */ - } - else - return luaL_error(L, "error loading module " LUA_QS - " from file " LUA_QS ":\n\t%s", - lua_tostring(L, 1), filename, lua_tostring(L, -1)); -} - - -static int searcher_Lua (lua_State *L) { - const char *filename; - const char *name = luaL_checkstring(L, 1); - filename = findfile(L, name, "path", LUA_LSUBSEP); - if (filename == NULL) return 1; /* module not found in this path */ - return checkload(L, (luaL_loadfile(L, filename) == LUA_OK), filename); -} - - -static int loadfunc (lua_State *L, const char *filename, const char *modname) { - const char *funcname; - const char *mark; - modname = luaL_gsub(L, modname, ".", LUA_OFSEP); - mark = strchr(modname, *LUA_IGMARK); - if (mark) { - int stat; - funcname = lua_pushlstring(L, modname, mark - modname); - funcname = lua_pushfstring(L, LUA_POF"%s", funcname); - stat = ll_loadfunc(L, filename, funcname); - if (stat != ERRFUNC) return stat; - modname = mark + 1; /* else go ahead and try old-style name */ - } - funcname = lua_pushfstring(L, LUA_POF"%s", modname); - return ll_loadfunc(L, filename, funcname); -} - - -static int searcher_C (lua_State *L) { - const char *name = luaL_checkstring(L, 1); - const char *filename = findfile(L, name, "cpath", LUA_CSUBSEP); - if (filename == NULL) return 1; /* module not found in this path */ - return checkload(L, (loadfunc(L, filename, name) == 0), filename); -} - - -static int searcher_Croot (lua_State *L) { - const char *filename; - const char *name = luaL_checkstring(L, 1); - const char *p = strchr(name, '.'); - int stat; - if (p == NULL) return 0; /* is root */ - lua_pushlstring(L, name, p - name); - filename = findfile(L, lua_tostring(L, -1), "cpath", LUA_CSUBSEP); - if (filename == NULL) return 1; /* root not found */ - if ((stat = loadfunc(L, filename, name)) != 0) { - if (stat != ERRFUNC) - return checkload(L, 0, filename); /* real error */ - else { /* open function not found */ - lua_pushfstring(L, "\n\tno module " LUA_QS " in file " LUA_QS, - name, filename); - return 1; - } - } - lua_pushstring(L, filename); /* will be 2nd argument to module */ - return 2; -} - - -static int searcher_preload (lua_State *L) { - const char *name = luaL_checkstring(L, 1); - lua_getfield(L, LUA_REGISTRYINDEX, "_PRELOAD"); - lua_getfield(L, -1, name); - if (lua_isnil(L, -1)) /* not found? */ - lua_pushfstring(L, "\n\tno field package.preload['%s']", name); - return 1; -} - - -static void findloader (lua_State *L, const char *name) { - int i; - luaL_Buffer msg; /* to build error message */ - luaL_buffinit(L, &msg); - lua_getfield(L, lua_upvalueindex(1), "searchers"); /* will be at index 3 */ - if (!lua_istable(L, 3)) - luaL_error(L, LUA_QL("package.searchers") " must be a table"); - /* iterate over available searchers to find a loader */ - for (i = 1; ; i++) { - lua_rawgeti(L, 3, i); /* get a searcher */ - if (lua_isnil(L, -1)) { /* no more searchers? */ - lua_pop(L, 1); /* remove nil */ - luaL_pushresult(&msg); /* create error message */ - luaL_error(L, "module " LUA_QS " not found:%s", - name, lua_tostring(L, -1)); - } - lua_pushstring(L, name); - lua_call(L, 1, 2); /* call it */ - if (lua_isfunction(L, -2)) /* did it find a loader? */ - return; /* module loader found */ - else if (lua_isstring(L, -2)) { /* searcher returned error message? */ - lua_pop(L, 1); /* remove extra return */ - luaL_addvalue(&msg); /* concatenate error message */ - } - else - lua_pop(L, 2); /* remove both returns */ - } -} - - -static int ll_require (lua_State *L) { - const char *name = luaL_checkstring(L, 1); - lua_settop(L, 1); /* _LOADED table will be at index 2 */ - lua_getfield(L, LUA_REGISTRYINDEX, "_LOADED"); - lua_getfield(L, 2, name); /* _LOADED[name] */ - if (lua_toboolean(L, -1)) /* is it there? */ - return 1; /* package is already loaded */ - /* else must load package */ - lua_pop(L, 1); /* remove 'getfield' result */ - findloader(L, name); - lua_pushstring(L, name); /* pass name as argument to module loader */ - lua_insert(L, -2); /* name is 1st argument (before search data) */ - lua_call(L, 2, 1); /* run loader to load module */ - if (!lua_isnil(L, -1)) /* non-nil return? */ - lua_setfield(L, 2, name); /* _LOADED[name] = returned value */ - lua_getfield(L, 2, name); - if (lua_isnil(L, -1)) { /* module did not set a value? */ - lua_pushboolean(L, 1); /* use true as result */ - lua_pushvalue(L, -1); /* extra copy to be returned */ - lua_setfield(L, 2, name); /* _LOADED[name] = true */ - } - return 1; -} - -/* }====================================================== */ - - - -/* -** {====================================================== -** 'module' function -** ======================================================= -*/ -#if defined(LUA_COMPAT_MODULE) - -/* -** changes the environment variable of calling function -*/ -static void set_env (lua_State *L) { - lua_Debug ar; - if (lua_getstack(L, 1, &ar) == 0 || - lua_getinfo(L, "f", &ar) == 0 || /* get calling function */ - lua_iscfunction(L, -1)) - luaL_error(L, LUA_QL("module") " not called from a Lua function"); - lua_pushvalue(L, -2); /* copy new environment table to top */ - lua_setupvalue(L, -2, 1); - lua_pop(L, 1); /* remove function */ -} - - -static void dooptions (lua_State *L, int n) { - int i; - for (i = 2; i <= n; i++) { - if (lua_isfunction(L, i)) { /* avoid 'calling' extra info. */ - lua_pushvalue(L, i); /* get option (a function) */ - lua_pushvalue(L, -2); /* module */ - lua_call(L, 1, 0); - } - } -} - - -static void modinit (lua_State *L, const char *modname) { - const char *dot; - lua_pushvalue(L, -1); - lua_setfield(L, -2, "_M"); /* module._M = module */ - lua_pushstring(L, modname); - lua_setfield(L, -2, "_NAME"); - dot = strrchr(modname, '.'); /* look for last dot in module name */ - if (dot == NULL) dot = modname; - else dot++; - /* set _PACKAGE as package name (full module name minus last part) */ - lua_pushlstring(L, modname, dot - modname); - lua_setfield(L, -2, "_PACKAGE"); -} - - -static int ll_module (lua_State *L) { - const char *modname = luaL_checkstring(L, 1); - int lastarg = lua_gettop(L); /* last parameter */ - luaL_pushmodule(L, modname, 1); /* get/create module table */ - /* check whether table already has a _NAME field */ - lua_getfield(L, -1, "_NAME"); - if (!lua_isnil(L, -1)) /* is table an initialized module? */ - lua_pop(L, 1); - else { /* no; initialize it */ - lua_pop(L, 1); - modinit(L, modname); - } - lua_pushvalue(L, -1); - set_env(L); - dooptions(L, lastarg); - return 1; -} - - -static int ll_seeall (lua_State *L) { - luaL_checktype(L, 1, LUA_TTABLE); - if (!lua_getmetatable(L, 1)) { - lua_createtable(L, 0, 1); /* create new metatable */ - lua_pushvalue(L, -1); - lua_setmetatable(L, 1); - } - lua_pushglobaltable(L); - lua_setfield(L, -2, "__index"); /* mt.__index = _G */ - return 0; -} - -#endif -/* }====================================================== */ - - - -/* auxiliary mark (for internal use) */ -#define AUXMARK "\1" - - -/* -** return registry.LUA_NOENV as a boolean -*/ -static int noenv (lua_State *L) { - int b; - lua_getfield(L, LUA_REGISTRYINDEX, "LUA_NOENV"); - b = lua_toboolean(L, -1); - lua_pop(L, 1); /* remove value */ - return b; -} - - -static void setpath (lua_State *L, const char *fieldname, const char *envname1, - const char *envname2, const char *def) { - const char *path = getenv(envname1); - if (path == NULL) /* no environment variable? */ - path = getenv(envname2); /* try alternative name */ - if (path == NULL || noenv(L)) /* no environment variable? */ - lua_pushstring(L, def); /* use default */ - else { - /* replace ";;" by ";AUXMARK;" and then AUXMARK by default path */ - path = luaL_gsub(L, path, LUA_PATH_SEP LUA_PATH_SEP, - LUA_PATH_SEP AUXMARK LUA_PATH_SEP); - luaL_gsub(L, path, AUXMARK, def); - lua_remove(L, -2); - } - setprogdir(L); - lua_setfield(L, -2, fieldname); -} - - -static const luaL_Reg pk_funcs[] = { - {"loadlib", ll_loadlib}, - {"searchpath", ll_searchpath}, -#if defined(LUA_COMPAT_MODULE) - {"seeall", ll_seeall}, -#endif - {NULL, NULL} -}; - - -static const luaL_Reg ll_funcs[] = { -#if defined(LUA_COMPAT_MODULE) - {"module", ll_module}, -#endif - {"require", ll_require}, - {NULL, NULL} -}; - - -static void createsearcherstable (lua_State *L) { - static const lua_CFunction searchers[] = - {searcher_preload, searcher_Lua, searcher_C, searcher_Croot, NULL}; - int i; - /* create 'searchers' table */ - lua_createtable(L, sizeof(searchers)/sizeof(searchers[0]) - 1, 0); - /* fill it with pre-defined searchers */ - for (i=0; searchers[i] != NULL; i++) { - lua_pushvalue(L, -2); /* set 'package' as upvalue for all searchers */ - lua_pushcclosure(L, searchers[i], 1); - lua_rawseti(L, -2, i+1); - } -} - - -LUAMOD_API int luaopen_package (lua_State *L) { - /* create table CLIBS to keep track of loaded C libraries */ - luaL_getsubtable(L, LUA_REGISTRYINDEX, CLIBS); - lua_createtable(L, 0, 1); /* metatable for CLIBS */ - lua_pushcfunction(L, gctm); - lua_setfield(L, -2, "__gc"); /* set finalizer for CLIBS table */ - lua_setmetatable(L, -2); - /* create `package' table */ - luaL_newlib(L, pk_funcs); - createsearcherstable(L); -#if defined(LUA_COMPAT_LOADERS) - lua_pushvalue(L, -1); /* make a copy of 'searchers' table */ - lua_setfield(L, -3, "loaders"); /* put it in field `loaders' */ -#endif - lua_setfield(L, -2, "searchers"); /* put it in field 'searchers' */ - /* set field 'path' */ - setpath(L, "path", LUA_PATHVERSION, LUA_PATH, LUA_PATH_DEFAULT); - /* set field 'cpath' */ - setpath(L, "cpath", LUA_CPATHVERSION, LUA_CPATH, LUA_CPATH_DEFAULT); - /* store config information */ - lua_pushliteral(L, LUA_DIRSEP "\n" LUA_PATH_SEP "\n" LUA_PATH_MARK "\n" - LUA_EXEC_DIR "\n" LUA_IGMARK "\n"); - lua_setfield(L, -2, "config"); - /* set field `loaded' */ - luaL_getsubtable(L, LUA_REGISTRYINDEX, "_LOADED"); - lua_setfield(L, -2, "loaded"); - /* set field `preload' */ - luaL_getsubtable(L, LUA_REGISTRYINDEX, "_PRELOAD"); - lua_setfield(L, -2, "preload"); - lua_pushglobaltable(L); - lua_pushvalue(L, -2); /* set 'package' as upvalue for next lib */ - luaL_setfuncs(L, ll_funcs, 1); /* open lib into global table */ - lua_pop(L, 1); /* pop global table */ - return 1; /* return 'package' table */ -} - diff --git a/lib/lua-5.2/src/lobject.c b/lib/lua-5.2/src/lobject.c deleted file mode 100644 index 882d994..0000000 --- a/lib/lua-5.2/src/lobject.c +++ /dev/null @@ -1,287 +0,0 @@ -/* -** $Id: lobject.c,v 2.58.1.1 2013/04/12 18:48:47 roberto Exp $ -** Some generic functions over Lua objects -** See Copyright Notice in lua.h -*/ - -#include -#include -#include -#include - -#define lobject_c -#define LUA_CORE - -#include "lua.h" - -#include "lctype.h" -#include "ldebug.h" -#include "ldo.h" -#include "lmem.h" -#include "lobject.h" -#include "lstate.h" -#include "lstring.h" -#include "lvm.h" - - - -LUAI_DDEF const TValue luaO_nilobject_ = {NILCONSTANT}; - - -/* -** converts an integer to a "floating point byte", represented as -** (eeeeexxx), where the real value is (1xxx) * 2^(eeeee - 1) if -** eeeee != 0 and (xxx) otherwise. -*/ -int luaO_int2fb (unsigned int x) { - int e = 0; /* exponent */ - if (x < 8) return x; - while (x >= 0x10) { - x = (x+1) >> 1; - e++; - } - return ((e+1) << 3) | (cast_int(x) - 8); -} - - -/* converts back */ -int luaO_fb2int (int x) { - int e = (x >> 3) & 0x1f; - if (e == 0) return x; - else return ((x & 7) + 8) << (e - 1); -} - - -int luaO_ceillog2 (unsigned int x) { - static const lu_byte log_2[256] = { - 0,1,2,2,3,3,3,3,4,4,4,4,4,4,4,4,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5, - 6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6, - 7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7, - 7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7, - 8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8, - 8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8, - 8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8, - 8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8 - }; - int l = 0; - x--; - while (x >= 256) { l += 8; x >>= 8; } - return l + log_2[x]; -} - - -lua_Number luaO_arith (int op, lua_Number v1, lua_Number v2) { - switch (op) { - case LUA_OPADD: return luai_numadd(NULL, v1, v2); - case LUA_OPSUB: return luai_numsub(NULL, v1, v2); - case LUA_OPMUL: return luai_nummul(NULL, v1, v2); - case LUA_OPDIV: return luai_numdiv(NULL, v1, v2); - case LUA_OPMOD: return luai_nummod(NULL, v1, v2); - case LUA_OPPOW: return luai_numpow(NULL, v1, v2); - case LUA_OPUNM: return luai_numunm(NULL, v1); - default: lua_assert(0); return 0; - } -} - - -int luaO_hexavalue (int c) { - if (lisdigit(c)) return c - '0'; - else return ltolower(c) - 'a' + 10; -} - - -#if !defined(lua_strx2number) - -#include - - -static int isneg (const char **s) { - if (**s == '-') { (*s)++; return 1; } - else if (**s == '+') (*s)++; - return 0; -} - - -static lua_Number readhexa (const char **s, lua_Number r, int *count) { - for (; lisxdigit(cast_uchar(**s)); (*s)++) { /* read integer part */ - r = (r * cast_num(16.0)) + cast_num(luaO_hexavalue(cast_uchar(**s))); - (*count)++; - } - return r; -} - - -/* -** convert an hexadecimal numeric string to a number, following -** C99 specification for 'strtod' -*/ -static lua_Number lua_strx2number (const char *s, char **endptr) { - lua_Number r = 0.0; - int e = 0, i = 0; - int neg = 0; /* 1 if number is negative */ - *endptr = cast(char *, s); /* nothing is valid yet */ - while (lisspace(cast_uchar(*s))) s++; /* skip initial spaces */ - neg = isneg(&s); /* check signal */ - if (!(*s == '0' && (*(s + 1) == 'x' || *(s + 1) == 'X'))) /* check '0x' */ - return 0.0; /* invalid format (no '0x') */ - s += 2; /* skip '0x' */ - r = readhexa(&s, r, &i); /* read integer part */ - if (*s == '.') { - s++; /* skip dot */ - r = readhexa(&s, r, &e); /* read fractional part */ - } - if (i == 0 && e == 0) - return 0.0; /* invalid format (no digit) */ - e *= -4; /* each fractional digit divides value by 2^-4 */ - *endptr = cast(char *, s); /* valid up to here */ - if (*s == 'p' || *s == 'P') { /* exponent part? */ - int exp1 = 0; - int neg1; - s++; /* skip 'p' */ - neg1 = isneg(&s); /* signal */ - if (!lisdigit(cast_uchar(*s))) - goto ret; /* must have at least one digit */ - while (lisdigit(cast_uchar(*s))) /* read exponent */ - exp1 = exp1 * 10 + *(s++) - '0'; - if (neg1) exp1 = -exp1; - e += exp1; - } - *endptr = cast(char *, s); /* valid up to here */ - ret: - if (neg) r = -r; - return l_mathop(ldexp)(r, e); -} - -#endif - - -int luaO_str2d (const char *s, size_t len, lua_Number *result) { - char *endptr; - if (strpbrk(s, "nN")) /* reject 'inf' and 'nan' */ - return 0; - else if (strpbrk(s, "xX")) /* hexa? */ - *result = lua_strx2number(s, &endptr); - else - *result = lua_str2number(s, &endptr); - if (endptr == s) return 0; /* nothing recognized */ - while (lisspace(cast_uchar(*endptr))) endptr++; - return (endptr == s + len); /* OK if no trailing characters */ -} - - - -static void pushstr (lua_State *L, const char *str, size_t l) { - setsvalue2s(L, L->top++, luaS_newlstr(L, str, l)); -} - - -/* this function handles only `%d', `%c', %f, %p, and `%s' formats */ -const char *luaO_pushvfstring (lua_State *L, const char *fmt, va_list argp) { - int n = 0; - for (;;) { - const char *e = strchr(fmt, '%'); - if (e == NULL) break; - luaD_checkstack(L, 2); /* fmt + item */ - pushstr(L, fmt, e - fmt); - switch (*(e+1)) { - case 's': { - const char *s = va_arg(argp, char *); - if (s == NULL) s = "(null)"; - pushstr(L, s, strlen(s)); - break; - } - case 'c': { - char buff; - buff = cast(char, va_arg(argp, int)); - pushstr(L, &buff, 1); - break; - } - case 'd': { - setnvalue(L->top++, cast_num(va_arg(argp, int))); - break; - } - case 'f': { - setnvalue(L->top++, cast_num(va_arg(argp, l_uacNumber))); - break; - } - case 'p': { - char buff[4*sizeof(void *) + 8]; /* should be enough space for a `%p' */ - int l = sprintf(buff, "%p", va_arg(argp, void *)); - pushstr(L, buff, l); - break; - } - case '%': { - pushstr(L, "%", 1); - break; - } - default: { - luaG_runerror(L, - "invalid option " LUA_QL("%%%c") " to " LUA_QL("lua_pushfstring"), - *(e + 1)); - } - } - n += 2; - fmt = e+2; - } - luaD_checkstack(L, 1); - pushstr(L, fmt, strlen(fmt)); - if (n > 0) luaV_concat(L, n + 1); - return svalue(L->top - 1); -} - - -const char *luaO_pushfstring (lua_State *L, const char *fmt, ...) { - const char *msg; - va_list argp; - va_start(argp, fmt); - msg = luaO_pushvfstring(L, fmt, argp); - va_end(argp); - return msg; -} - - -/* number of chars of a literal string without the ending \0 */ -#define LL(x) (sizeof(x)/sizeof(char) - 1) - -#define RETS "..." -#define PRE "[string \"" -#define POS "\"]" - -#define addstr(a,b,l) ( memcpy(a,b,(l) * sizeof(char)), a += (l) ) - -void luaO_chunkid (char *out, const char *source, size_t bufflen) { - size_t l = strlen(source); - if (*source == '=') { /* 'literal' source */ - if (l <= bufflen) /* small enough? */ - memcpy(out, source + 1, l * sizeof(char)); - else { /* truncate it */ - addstr(out, source + 1, bufflen - 1); - *out = '\0'; - } - } - else if (*source == '@') { /* file name */ - if (l <= bufflen) /* small enough? */ - memcpy(out, source + 1, l * sizeof(char)); - else { /* add '...' before rest of name */ - addstr(out, RETS, LL(RETS)); - bufflen -= LL(RETS); - memcpy(out, source + 1 + l - bufflen, bufflen * sizeof(char)); - } - } - else { /* string; format as [string "source"] */ - const char *nl = strchr(source, '\n'); /* find first new line (if any) */ - addstr(out, PRE, LL(PRE)); /* add prefix */ - bufflen -= LL(PRE RETS POS) + 1; /* save space for prefix+suffix+'\0' */ - if (l < bufflen && nl == NULL) { /* small one-line source? */ - addstr(out, source, l); /* keep it */ - } - else { - if (nl != NULL) l = nl - source; /* stop at first newline */ - if (l > bufflen) l = bufflen; - addstr(out, source, l); - addstr(out, RETS, LL(RETS)); - } - memcpy(out, POS, (LL(POS) + 1) * sizeof(char)); - } -} - diff --git a/lib/lua-5.2/src/lobject.h b/lib/lua-5.2/src/lobject.h deleted file mode 100644 index bc0bb69..0000000 --- a/lib/lua-5.2/src/lobject.h +++ /dev/null @@ -1,607 +0,0 @@ -/* -** $Id: lobject.h,v 2.71.1.2 2014/05/07 14:14:58 roberto Exp $ -** Type definitions for Lua objects -** See Copyright Notice in lua.h -*/ - - -#ifndef lobject_h -#define lobject_h - - -#include - - -#include "llimits.h" -#include "lua.h" - - -/* -** Extra tags for non-values -*/ -#define LUA_TPROTO LUA_NUMTAGS -#define LUA_TUPVAL (LUA_NUMTAGS+1) -#define LUA_TDEADKEY (LUA_NUMTAGS+2) - -/* -** number of all possible tags (including LUA_TNONE but excluding DEADKEY) -*/ -#define LUA_TOTALTAGS (LUA_TUPVAL+2) - - -/* -** tags for Tagged Values have the following use of bits: -** bits 0-3: actual tag (a LUA_T* value) -** bits 4-5: variant bits -** bit 6: whether value is collectable -*/ - -#define VARBITS (3 << 4) - - -/* -** LUA_TFUNCTION variants: -** 0 - Lua function -** 1 - light C function -** 2 - regular C function (closure) -*/ - -/* Variant tags for functions */ -#define LUA_TLCL (LUA_TFUNCTION | (0 << 4)) /* Lua closure */ -#define LUA_TLCF (LUA_TFUNCTION | (1 << 4)) /* light C function */ -#define LUA_TCCL (LUA_TFUNCTION | (2 << 4)) /* C closure */ - - -/* Variant tags for strings */ -#define LUA_TSHRSTR (LUA_TSTRING | (0 << 4)) /* short strings */ -#define LUA_TLNGSTR (LUA_TSTRING | (1 << 4)) /* long strings */ - - -/* Bit mark for collectable types */ -#define BIT_ISCOLLECTABLE (1 << 6) - -/* mark a tag as collectable */ -#define ctb(t) ((t) | BIT_ISCOLLECTABLE) - - -/* -** Union of all collectable objects -*/ -typedef union GCObject GCObject; - - -/* -** Common Header for all collectable objects (in macro form, to be -** included in other objects) -*/ -#define CommonHeader GCObject *next; lu_byte tt; lu_byte marked - - -/* -** Common header in struct form -*/ -typedef struct GCheader { - CommonHeader; -} GCheader; - - - -/* -** Union of all Lua values -*/ -typedef union Value Value; - - -#define numfield lua_Number n; /* numbers */ - - - -/* -** Tagged Values. This is the basic representation of values in Lua, -** an actual value plus a tag with its type. -*/ - -#define TValuefields Value value_; int tt_ - -typedef struct lua_TValue TValue; - - -/* macro defining a nil value */ -#define NILCONSTANT {NULL}, LUA_TNIL - - -#define val_(o) ((o)->value_) -#define num_(o) (val_(o).n) - - -/* raw type tag of a TValue */ -#define rttype(o) ((o)->tt_) - -/* tag with no variants (bits 0-3) */ -#define novariant(x) ((x) & 0x0F) - -/* type tag of a TValue (bits 0-3 for tags + variant bits 4-5) */ -#define ttype(o) (rttype(o) & 0x3F) - -/* type tag of a TValue with no variants (bits 0-3) */ -#define ttypenv(o) (novariant(rttype(o))) - - -/* Macros to test type */ -#define checktag(o,t) (rttype(o) == (t)) -#define checktype(o,t) (ttypenv(o) == (t)) -#define ttisnumber(o) checktag((o), LUA_TNUMBER) -#define ttisnil(o) checktag((o), LUA_TNIL) -#define ttisboolean(o) checktag((o), LUA_TBOOLEAN) -#define ttislightuserdata(o) checktag((o), LUA_TLIGHTUSERDATA) -#define ttisstring(o) checktype((o), LUA_TSTRING) -#define ttisshrstring(o) checktag((o), ctb(LUA_TSHRSTR)) -#define ttislngstring(o) checktag((o), ctb(LUA_TLNGSTR)) -#define ttistable(o) checktag((o), ctb(LUA_TTABLE)) -#define ttisfunction(o) checktype(o, LUA_TFUNCTION) -#define ttisclosure(o) ((rttype(o) & 0x1F) == LUA_TFUNCTION) -#define ttisCclosure(o) checktag((o), ctb(LUA_TCCL)) -#define ttisLclosure(o) checktag((o), ctb(LUA_TLCL)) -#define ttislcf(o) checktag((o), LUA_TLCF) -#define ttisuserdata(o) checktag((o), ctb(LUA_TUSERDATA)) -#define ttisthread(o) checktag((o), ctb(LUA_TTHREAD)) -#define ttisdeadkey(o) checktag((o), LUA_TDEADKEY) - -#define ttisequal(o1,o2) (rttype(o1) == rttype(o2)) - -/* Macros to access values */ -#define nvalue(o) check_exp(ttisnumber(o), num_(o)) -#define gcvalue(o) check_exp(iscollectable(o), val_(o).gc) -#define pvalue(o) check_exp(ttislightuserdata(o), val_(o).p) -#define rawtsvalue(o) check_exp(ttisstring(o), &val_(o).gc->ts) -#define tsvalue(o) (&rawtsvalue(o)->tsv) -#define rawuvalue(o) check_exp(ttisuserdata(o), &val_(o).gc->u) -#define uvalue(o) (&rawuvalue(o)->uv) -#define clvalue(o) check_exp(ttisclosure(o), &val_(o).gc->cl) -#define clLvalue(o) check_exp(ttisLclosure(o), &val_(o).gc->cl.l) -#define clCvalue(o) check_exp(ttisCclosure(o), &val_(o).gc->cl.c) -#define fvalue(o) check_exp(ttislcf(o), val_(o).f) -#define hvalue(o) check_exp(ttistable(o), &val_(o).gc->h) -#define bvalue(o) check_exp(ttisboolean(o), val_(o).b) -#define thvalue(o) check_exp(ttisthread(o), &val_(o).gc->th) -/* a dead value may get the 'gc' field, but cannot access its contents */ -#define deadvalue(o) check_exp(ttisdeadkey(o), cast(void *, val_(o).gc)) - -#define l_isfalse(o) (ttisnil(o) || (ttisboolean(o) && bvalue(o) == 0)) - - -#define iscollectable(o) (rttype(o) & BIT_ISCOLLECTABLE) - - -/* Macros for internal tests */ -#define righttt(obj) (ttype(obj) == gcvalue(obj)->gch.tt) - -#define checkliveness(g,obj) \ - lua_longassert(!iscollectable(obj) || \ - (righttt(obj) && !isdead(g,gcvalue(obj)))) - - -/* Macros to set values */ -#define settt_(o,t) ((o)->tt_=(t)) - -#define setnvalue(obj,x) \ - { TValue *io=(obj); num_(io)=(x); settt_(io, LUA_TNUMBER); } - -#define setnilvalue(obj) settt_(obj, LUA_TNIL) - -#define setfvalue(obj,x) \ - { TValue *io=(obj); val_(io).f=(x); settt_(io, LUA_TLCF); } - -#define setpvalue(obj,x) \ - { TValue *io=(obj); val_(io).p=(x); settt_(io, LUA_TLIGHTUSERDATA); } - -#define setbvalue(obj,x) \ - { TValue *io=(obj); val_(io).b=(x); settt_(io, LUA_TBOOLEAN); } - -#define setgcovalue(L,obj,x) \ - { TValue *io=(obj); GCObject *i_g=(x); \ - val_(io).gc=i_g; settt_(io, ctb(gch(i_g)->tt)); } - -#define setsvalue(L,obj,x) \ - { TValue *io=(obj); \ - TString *x_ = (x); \ - val_(io).gc=cast(GCObject *, x_); settt_(io, ctb(x_->tsv.tt)); \ - checkliveness(G(L),io); } - -#define setuvalue(L,obj,x) \ - { TValue *io=(obj); \ - val_(io).gc=cast(GCObject *, (x)); settt_(io, ctb(LUA_TUSERDATA)); \ - checkliveness(G(L),io); } - -#define setthvalue(L,obj,x) \ - { TValue *io=(obj); \ - val_(io).gc=cast(GCObject *, (x)); settt_(io, ctb(LUA_TTHREAD)); \ - checkliveness(G(L),io); } - -#define setclLvalue(L,obj,x) \ - { TValue *io=(obj); \ - val_(io).gc=cast(GCObject *, (x)); settt_(io, ctb(LUA_TLCL)); \ - checkliveness(G(L),io); } - -#define setclCvalue(L,obj,x) \ - { TValue *io=(obj); \ - val_(io).gc=cast(GCObject *, (x)); settt_(io, ctb(LUA_TCCL)); \ - checkliveness(G(L),io); } - -#define sethvalue(L,obj,x) \ - { TValue *io=(obj); \ - val_(io).gc=cast(GCObject *, (x)); settt_(io, ctb(LUA_TTABLE)); \ - checkliveness(G(L),io); } - -#define setdeadvalue(obj) settt_(obj, LUA_TDEADKEY) - - - -#define setobj(L,obj1,obj2) \ - { const TValue *io2=(obj2); TValue *io1=(obj1); \ - io1->value_ = io2->value_; io1->tt_ = io2->tt_; \ - checkliveness(G(L),io1); } - - -/* -** different types of assignments, according to destination -*/ - -/* from stack to (same) stack */ -#define setobjs2s setobj -/* to stack (not from same stack) */ -#define setobj2s setobj -#define setsvalue2s setsvalue -#define sethvalue2s sethvalue -#define setptvalue2s setptvalue -/* from table to same table */ -#define setobjt2t setobj -/* to table */ -#define setobj2t setobj -/* to new object */ -#define setobj2n setobj -#define setsvalue2n setsvalue - - -/* check whether a number is valid (useful only for NaN trick) */ -#define luai_checknum(L,o,c) { /* empty */ } - - -/* -** {====================================================== -** NaN Trick -** ======================================================= -*/ -#if defined(LUA_NANTRICK) - -/* -** numbers are represented in the 'd_' field. All other values have the -** value (NNMARK | tag) in 'tt__'. A number with such pattern would be -** a "signaled NaN", which is never generated by regular operations by -** the CPU (nor by 'strtod') -*/ - -/* allows for external implementation for part of the trick */ -#if !defined(NNMARK) /* { */ - - -#if !defined(LUA_IEEEENDIAN) -#error option 'LUA_NANTRICK' needs 'LUA_IEEEENDIAN' -#endif - - -#define NNMARK 0x7FF7A500 -#define NNMASK 0x7FFFFF00 - -#undef TValuefields -#undef NILCONSTANT - -#if (LUA_IEEEENDIAN == 0) /* { */ - -/* little endian */ -#define TValuefields \ - union { struct { Value v__; int tt__; } i; double d__; } u -#define NILCONSTANT {{{NULL}, tag2tt(LUA_TNIL)}} -/* field-access macros */ -#define v_(o) ((o)->u.i.v__) -#define d_(o) ((o)->u.d__) -#define tt_(o) ((o)->u.i.tt__) - -#else /* }{ */ - -/* big endian */ -#define TValuefields \ - union { struct { int tt__; Value v__; } i; double d__; } u -#define NILCONSTANT {{tag2tt(LUA_TNIL), {NULL}}} -/* field-access macros */ -#define v_(o) ((o)->u.i.v__) -#define d_(o) ((o)->u.d__) -#define tt_(o) ((o)->u.i.tt__) - -#endif /* } */ - -#endif /* } */ - - -/* correspondence with standard representation */ -#undef val_ -#define val_(o) v_(o) -#undef num_ -#define num_(o) d_(o) - - -#undef numfield -#define numfield /* no such field; numbers are the entire struct */ - -/* basic check to distinguish numbers from non-numbers */ -#undef ttisnumber -#define ttisnumber(o) ((tt_(o) & NNMASK) != NNMARK) - -#define tag2tt(t) (NNMARK | (t)) - -#undef rttype -#define rttype(o) (ttisnumber(o) ? LUA_TNUMBER : tt_(o) & 0xff) - -#undef settt_ -#define settt_(o,t) (tt_(o) = tag2tt(t)) - -#undef setnvalue -#define setnvalue(obj,x) \ - { TValue *io_=(obj); num_(io_)=(x); lua_assert(ttisnumber(io_)); } - -#undef setobj -#define setobj(L,obj1,obj2) \ - { const TValue *o2_=(obj2); TValue *o1_=(obj1); \ - o1_->u = o2_->u; \ - checkliveness(G(L),o1_); } - - -/* -** these redefinitions are not mandatory, but these forms are more efficient -*/ - -#undef checktag -#undef checktype -#define checktag(o,t) (tt_(o) == tag2tt(t)) -#define checktype(o,t) (ctb(tt_(o) | VARBITS) == ctb(tag2tt(t) | VARBITS)) - -#undef ttisequal -#define ttisequal(o1,o2) \ - (ttisnumber(o1) ? ttisnumber(o2) : (tt_(o1) == tt_(o2))) - - -#undef luai_checknum -#define luai_checknum(L,o,c) { if (!ttisnumber(o)) c; } - -#endif -/* }====================================================== */ - - - -/* -** {====================================================== -** types and prototypes -** ======================================================= -*/ - - -union Value { - GCObject *gc; /* collectable objects */ - void *p; /* light userdata */ - int b; /* booleans */ - lua_CFunction f; /* light C functions */ - numfield /* numbers */ -}; - - -struct lua_TValue { - TValuefields; -}; - - -typedef TValue *StkId; /* index to stack elements */ - - - - -/* -** Header for string value; string bytes follow the end of this structure -*/ -typedef union TString { - L_Umaxalign dummy; /* ensures maximum alignment for strings */ - struct { - CommonHeader; - lu_byte extra; /* reserved words for short strings; "has hash" for longs */ - unsigned int hash; - size_t len; /* number of characters in string */ - } tsv; -} TString; - - -/* get the actual string (array of bytes) from a TString */ -#define getstr(ts) cast(const char *, (ts) + 1) - -/* get the actual string (array of bytes) from a Lua value */ -#define svalue(o) getstr(rawtsvalue(o)) - - -/* -** Header for userdata; memory area follows the end of this structure -*/ -typedef union Udata { - L_Umaxalign dummy; /* ensures maximum alignment for `local' udata */ - struct { - CommonHeader; - struct Table *metatable; - struct Table *env; - size_t len; /* number of bytes */ - } uv; -} Udata; - - - -/* -** Description of an upvalue for function prototypes -*/ -typedef struct Upvaldesc { - TString *name; /* upvalue name (for debug information) */ - lu_byte instack; /* whether it is in stack */ - lu_byte idx; /* index of upvalue (in stack or in outer function's list) */ -} Upvaldesc; - - -/* -** Description of a local variable for function prototypes -** (used for debug information) -*/ -typedef struct LocVar { - TString *varname; - int startpc; /* first point where variable is active */ - int endpc; /* first point where variable is dead */ -} LocVar; - - -/* -** Function Prototypes -*/ -typedef struct Proto { - CommonHeader; - TValue *k; /* constants used by the function */ - Instruction *code; - struct Proto **p; /* functions defined inside the function */ - int *lineinfo; /* map from opcodes to source lines (debug information) */ - LocVar *locvars; /* information about local variables (debug information) */ - Upvaldesc *upvalues; /* upvalue information */ - union Closure *cache; /* last created closure with this prototype */ - TString *source; /* used for debug information */ - int sizeupvalues; /* size of 'upvalues' */ - int sizek; /* size of `k' */ - int sizecode; - int sizelineinfo; - int sizep; /* size of `p' */ - int sizelocvars; - int linedefined; - int lastlinedefined; - GCObject *gclist; - lu_byte numparams; /* number of fixed parameters */ - lu_byte is_vararg; - lu_byte maxstacksize; /* maximum stack used by this function */ -} Proto; - - - -/* -** Lua Upvalues -*/ -typedef struct UpVal { - CommonHeader; - TValue *v; /* points to stack or to its own value */ - union { - TValue value; /* the value (when closed) */ - struct { /* double linked list (when open) */ - struct UpVal *prev; - struct UpVal *next; - } l; - } u; -} UpVal; - - -/* -** Closures -*/ - -#define ClosureHeader \ - CommonHeader; lu_byte nupvalues; GCObject *gclist - -typedef struct CClosure { - ClosureHeader; - lua_CFunction f; - TValue upvalue[1]; /* list of upvalues */ -} CClosure; - - -typedef struct LClosure { - ClosureHeader; - struct Proto *p; - UpVal *upvals[1]; /* list of upvalues */ -} LClosure; - - -typedef union Closure { - CClosure c; - LClosure l; -} Closure; - - -#define isLfunction(o) ttisLclosure(o) - -#define getproto(o) (clLvalue(o)->p) - - -/* -** Tables -*/ - -typedef union TKey { - struct { - TValuefields; - struct Node *next; /* for chaining */ - } nk; - TValue tvk; -} TKey; - - -typedef struct Node { - TValue i_val; - TKey i_key; -} Node; - - -typedef struct Table { - CommonHeader; - lu_byte flags; /* 1<

lsizenode)) - - -/* -** (address of) a fixed nil value -*/ -#define luaO_nilobject (&luaO_nilobject_) - - -LUAI_DDEC const TValue luaO_nilobject_; - - -LUAI_FUNC int luaO_int2fb (unsigned int x); -LUAI_FUNC int luaO_fb2int (int x); -LUAI_FUNC int luaO_ceillog2 (unsigned int x); -LUAI_FUNC lua_Number luaO_arith (int op, lua_Number v1, lua_Number v2); -LUAI_FUNC int luaO_str2d (const char *s, size_t len, lua_Number *result); -LUAI_FUNC int luaO_hexavalue (int c); -LUAI_FUNC const char *luaO_pushvfstring (lua_State *L, const char *fmt, - va_list argp); -LUAI_FUNC const char *luaO_pushfstring (lua_State *L, const char *fmt, ...); -LUAI_FUNC void luaO_chunkid (char *out, const char *source, size_t len); - - -#endif - diff --git a/lib/lua-5.2/src/lopcodes.c b/lib/lua-5.2/src/lopcodes.c deleted file mode 100644 index 4190dc7..0000000 --- a/lib/lua-5.2/src/lopcodes.c +++ /dev/null @@ -1,107 +0,0 @@ -/* -** $Id: lopcodes.c,v 1.49.1.1 2013/04/12 18:48:47 roberto Exp $ -** Opcodes for Lua virtual machine -** See Copyright Notice in lua.h -*/ - - -#define lopcodes_c -#define LUA_CORE - - -#include "lopcodes.h" - - -/* ORDER OP */ - -LUAI_DDEF const char *const luaP_opnames[NUM_OPCODES+1] = { - "MOVE", - "LOADK", - "LOADKX", - "LOADBOOL", - "LOADNIL", - "GETUPVAL", - "GETTABUP", - "GETTABLE", - "SETTABUP", - "SETUPVAL", - "SETTABLE", - "NEWTABLE", - "SELF", - "ADD", - "SUB", - "MUL", - "DIV", - "MOD", - "POW", - "UNM", - "NOT", - "LEN", - "CONCAT", - "JMP", - "EQ", - "LT", - "LE", - "TEST", - "TESTSET", - "CALL", - "TAILCALL", - "RETURN", - "FORLOOP", - "FORPREP", - "TFORCALL", - "TFORLOOP", - "SETLIST", - "CLOSURE", - "VARARG", - "EXTRAARG", - NULL -}; - - -#define opmode(t,a,b,c,m) (((t)<<7) | ((a)<<6) | ((b)<<4) | ((c)<<2) | (m)) - -LUAI_DDEF const lu_byte luaP_opmodes[NUM_OPCODES] = { -/* T A B C mode opcode */ - opmode(0, 1, OpArgR, OpArgN, iABC) /* OP_MOVE */ - ,opmode(0, 1, OpArgK, OpArgN, iABx) /* OP_LOADK */ - ,opmode(0, 1, OpArgN, OpArgN, iABx) /* OP_LOADKX */ - ,opmode(0, 1, OpArgU, OpArgU, iABC) /* OP_LOADBOOL */ - ,opmode(0, 1, OpArgU, OpArgN, iABC) /* OP_LOADNIL */ - ,opmode(0, 1, OpArgU, OpArgN, iABC) /* OP_GETUPVAL */ - ,opmode(0, 1, OpArgU, OpArgK, iABC) /* OP_GETTABUP */ - ,opmode(0, 1, OpArgR, OpArgK, iABC) /* OP_GETTABLE */ - ,opmode(0, 0, OpArgK, OpArgK, iABC) /* OP_SETTABUP */ - ,opmode(0, 0, OpArgU, OpArgN, iABC) /* OP_SETUPVAL */ - ,opmode(0, 0, OpArgK, OpArgK, iABC) /* OP_SETTABLE */ - ,opmode(0, 1, OpArgU, OpArgU, iABC) /* OP_NEWTABLE */ - ,opmode(0, 1, OpArgR, OpArgK, iABC) /* OP_SELF */ - ,opmode(0, 1, OpArgK, OpArgK, iABC) /* OP_ADD */ - ,opmode(0, 1, OpArgK, OpArgK, iABC) /* OP_SUB */ - ,opmode(0, 1, OpArgK, OpArgK, iABC) /* OP_MUL */ - ,opmode(0, 1, OpArgK, OpArgK, iABC) /* OP_DIV */ - ,opmode(0, 1, OpArgK, OpArgK, iABC) /* OP_MOD */ - ,opmode(0, 1, OpArgK, OpArgK, iABC) /* OP_POW */ - ,opmode(0, 1, OpArgR, OpArgN, iABC) /* OP_UNM */ - ,opmode(0, 1, OpArgR, OpArgN, iABC) /* OP_NOT */ - ,opmode(0, 1, OpArgR, OpArgN, iABC) /* OP_LEN */ - ,opmode(0, 1, OpArgR, OpArgR, iABC) /* OP_CONCAT */ - ,opmode(0, 0, OpArgR, OpArgN, iAsBx) /* OP_JMP */ - ,opmode(1, 0, OpArgK, OpArgK, iABC) /* OP_EQ */ - ,opmode(1, 0, OpArgK, OpArgK, iABC) /* OP_LT */ - ,opmode(1, 0, OpArgK, OpArgK, iABC) /* OP_LE */ - ,opmode(1, 0, OpArgN, OpArgU, iABC) /* OP_TEST */ - ,opmode(1, 1, OpArgR, OpArgU, iABC) /* OP_TESTSET */ - ,opmode(0, 1, OpArgU, OpArgU, iABC) /* OP_CALL */ - ,opmode(0, 1, OpArgU, OpArgU, iABC) /* OP_TAILCALL */ - ,opmode(0, 0, OpArgU, OpArgN, iABC) /* OP_RETURN */ - ,opmode(0, 1, OpArgR, OpArgN, iAsBx) /* OP_FORLOOP */ - ,opmode(0, 1, OpArgR, OpArgN, iAsBx) /* OP_FORPREP */ - ,opmode(0, 0, OpArgN, OpArgU, iABC) /* OP_TFORCALL */ - ,opmode(0, 1, OpArgR, OpArgN, iAsBx) /* OP_TFORLOOP */ - ,opmode(0, 0, OpArgU, OpArgU, iABC) /* OP_SETLIST */ - ,opmode(0, 1, OpArgU, OpArgN, iABx) /* OP_CLOSURE */ - ,opmode(0, 1, OpArgU, OpArgN, iABC) /* OP_VARARG */ - ,opmode(0, 0, OpArgU, OpArgU, iAx) /* OP_EXTRAARG */ -}; - diff --git a/lib/lua-5.2/src/lopcodes.h b/lib/lua-5.2/src/lopcodes.h deleted file mode 100644 index 8e2f80a..0000000 --- a/lib/lua-5.2/src/lopcodes.h +++ /dev/null @@ -1,288 +0,0 @@ -/* -** $Id: lopcodes.h,v 1.142.1.2 2014/10/20 18:32:09 roberto Exp $ -** Opcodes for Lua virtual machine -** See Copyright Notice in lua.h -*/ - -#ifndef lopcodes_h -#define lopcodes_h - -#include "llimits.h" - - -/*=========================================================================== - We assume that instructions are unsigned numbers. - All instructions have an opcode in the first 6 bits. - Instructions can have the following fields: - `A' : 8 bits - `B' : 9 bits - `C' : 9 bits - 'Ax' : 26 bits ('A', 'B', and 'C' together) - `Bx' : 18 bits (`B' and `C' together) - `sBx' : signed Bx - - A signed argument is represented in excess K; that is, the number - value is the unsigned value minus K. K is exactly the maximum value - for that argument (so that -max is represented by 0, and +max is - represented by 2*max), which is half the maximum for the corresponding - unsigned argument. -===========================================================================*/ - - -enum OpMode {iABC, iABx, iAsBx, iAx}; /* basic instruction format */ - - -/* -** size and position of opcode arguments. -*/ -#define SIZE_C 9 -#define SIZE_B 9 -#define SIZE_Bx (SIZE_C + SIZE_B) -#define SIZE_A 8 -#define SIZE_Ax (SIZE_C + SIZE_B + SIZE_A) - -#define SIZE_OP 6 - -#define POS_OP 0 -#define POS_A (POS_OP + SIZE_OP) -#define POS_C (POS_A + SIZE_A) -#define POS_B (POS_C + SIZE_C) -#define POS_Bx POS_C -#define POS_Ax POS_A - - -/* -** limits for opcode arguments. -** we use (signed) int to manipulate most arguments, -** so they must fit in LUAI_BITSINT-1 bits (-1 for sign) -*/ -#if SIZE_Bx < LUAI_BITSINT-1 -#define MAXARG_Bx ((1<>1) /* `sBx' is signed */ -#else -#define MAXARG_Bx MAX_INT -#define MAXARG_sBx MAX_INT -#endif - -#if SIZE_Ax < LUAI_BITSINT-1 -#define MAXARG_Ax ((1<>POS_OP) & MASK1(SIZE_OP,0))) -#define SET_OPCODE(i,o) ((i) = (((i)&MASK0(SIZE_OP,POS_OP)) | \ - ((cast(Instruction, o)<>pos) & MASK1(size,0))) -#define setarg(i,v,pos,size) ((i) = (((i)&MASK0(size,pos)) | \ - ((cast(Instruction, v)<= R(A - 1) */ -OP_EQ,/* A B C if ((RK(B) == RK(C)) ~= A) then pc++ */ -OP_LT,/* A B C if ((RK(B) < RK(C)) ~= A) then pc++ */ -OP_LE,/* A B C if ((RK(B) <= RK(C)) ~= A) then pc++ */ - -OP_TEST,/* A C if not (R(A) <=> C) then pc++ */ -OP_TESTSET,/* A B C if (R(B) <=> C) then R(A) := R(B) else pc++ */ - -OP_CALL,/* A B C R(A), ... ,R(A+C-2) := R(A)(R(A+1), ... ,R(A+B-1)) */ -OP_TAILCALL,/* A B C return R(A)(R(A+1), ... ,R(A+B-1)) */ -OP_RETURN,/* A B return R(A), ... ,R(A+B-2) (see note) */ - -OP_FORLOOP,/* A sBx R(A)+=R(A+2); - if R(A) > 4) & 3)) -#define getCMode(m) (cast(enum OpArgMask, (luaP_opmodes[m] >> 2) & 3)) -#define testAMode(m) (luaP_opmodes[m] & (1 << 6)) -#define testTMode(m) (luaP_opmodes[m] & (1 << 7)) - - -LUAI_DDEC const char *const luaP_opnames[NUM_OPCODES+1]; /* opcode names */ - - -/* number of list items to accumulate before a SETLIST instruction */ -#define LFIELDS_PER_FLUSH 50 - - -#endif diff --git a/lib/lua-5.2/src/loslib.c b/lib/lua-5.2/src/loslib.c deleted file mode 100644 index 052ba17..0000000 --- a/lib/lua-5.2/src/loslib.c +++ /dev/null @@ -1,323 +0,0 @@ -/* -** $Id: loslib.c,v 1.40.1.1 2013/04/12 18:48:47 roberto Exp $ -** Standard Operating System library -** See Copyright Notice in lua.h -*/ - - -#include -#include -#include -#include -#include - -#define loslib_c -#define LUA_LIB - -#include "lua.h" - -#include "lauxlib.h" -#include "lualib.h" - - -/* -** list of valid conversion specifiers for the 'strftime' function -*/ -#if !defined(LUA_STRFTIMEOPTIONS) - -#if !defined(LUA_USE_POSIX) -#define LUA_STRFTIMEOPTIONS { "aAbBcdHIjmMpSUwWxXyYz%", "" } -#else -#define LUA_STRFTIMEOPTIONS \ - { "aAbBcCdDeFgGhHIjmMnprRStTuUVwWxXyYzZ%", "" \ - "", "E", "cCxXyY", \ - "O", "deHImMSuUVwWy" } -#endif - -#endif - - - -/* -** By default, Lua uses tmpnam except when POSIX is available, where it -** uses mkstemp. -*/ -#if defined(LUA_USE_MKSTEMP) -#include -#define LUA_TMPNAMBUFSIZE 32 -#define lua_tmpnam(b,e) { \ - strcpy(b, "/tmp/lua_XXXXXX"); \ - e = mkstemp(b); \ - if (e != -1) close(e); \ - e = (e == -1); } - -#elif !defined(lua_tmpnam) - -#define LUA_TMPNAMBUFSIZE L_tmpnam -#define lua_tmpnam(b,e) { e = (tmpnam(b) == NULL); } - -#endif - - -/* -** By default, Lua uses gmtime/localtime, except when POSIX is available, -** where it uses gmtime_r/localtime_r -*/ -#if defined(LUA_USE_GMTIME_R) - -#define l_gmtime(t,r) gmtime_r(t,r) -#define l_localtime(t,r) localtime_r(t,r) - -#elif !defined(l_gmtime) - -#define l_gmtime(t,r) ((void)r, gmtime(t)) -#define l_localtime(t,r) ((void)r, localtime(t)) - -#endif - - - -static int os_execute (lua_State *L) { - const char *cmd = luaL_optstring(L, 1, NULL); - int stat = system(cmd); - if (cmd != NULL) - return luaL_execresult(L, stat); - else { - lua_pushboolean(L, stat); /* true if there is a shell */ - return 1; - } -} - - -static int os_remove (lua_State *L) { - const char *filename = luaL_checkstring(L, 1); - return luaL_fileresult(L, remove(filename) == 0, filename); -} - - -static int os_rename (lua_State *L) { - const char *fromname = luaL_checkstring(L, 1); - const char *toname = luaL_checkstring(L, 2); - return luaL_fileresult(L, rename(fromname, toname) == 0, NULL); -} - - -static int os_tmpname (lua_State *L) { - char buff[LUA_TMPNAMBUFSIZE]; - int err; - lua_tmpnam(buff, err); - if (err) - return luaL_error(L, "unable to generate a unique filename"); - lua_pushstring(L, buff); - return 1; -} - - -static int os_getenv (lua_State *L) { - lua_pushstring(L, getenv(luaL_checkstring(L, 1))); /* if NULL push nil */ - return 1; -} - - -static int os_clock (lua_State *L) { - lua_pushnumber(L, ((lua_Number)clock())/(lua_Number)CLOCKS_PER_SEC); - return 1; -} - - -/* -** {====================================================== -** Time/Date operations -** { year=%Y, month=%m, day=%d, hour=%H, min=%M, sec=%S, -** wday=%w+1, yday=%j, isdst=? } -** ======================================================= -*/ - -static void setfield (lua_State *L, const char *key, int value) { - lua_pushinteger(L, value); - lua_setfield(L, -2, key); -} - -static void setboolfield (lua_State *L, const char *key, int value) { - if (value < 0) /* undefined? */ - return; /* does not set field */ - lua_pushboolean(L, value); - lua_setfield(L, -2, key); -} - -static int getboolfield (lua_State *L, const char *key) { - int res; - lua_getfield(L, -1, key); - res = lua_isnil(L, -1) ? -1 : lua_toboolean(L, -1); - lua_pop(L, 1); - return res; -} - - -static int getfield (lua_State *L, const char *key, int d) { - int res, isnum; - lua_getfield(L, -1, key); - res = (int)lua_tointegerx(L, -1, &isnum); - if (!isnum) { - if (d < 0) - return luaL_error(L, "field " LUA_QS " missing in date table", key); - res = d; - } - lua_pop(L, 1); - return res; -} - - -static const char *checkoption (lua_State *L, const char *conv, char *buff) { - static const char *const options[] = LUA_STRFTIMEOPTIONS; - unsigned int i; - for (i = 0; i < sizeof(options)/sizeof(options[0]); i += 2) { - if (*conv != '\0' && strchr(options[i], *conv) != NULL) { - buff[1] = *conv; - if (*options[i + 1] == '\0') { /* one-char conversion specifier? */ - buff[2] = '\0'; /* end buffer */ - return conv + 1; - } - else if (*(conv + 1) != '\0' && - strchr(options[i + 1], *(conv + 1)) != NULL) { - buff[2] = *(conv + 1); /* valid two-char conversion specifier */ - buff[3] = '\0'; /* end buffer */ - return conv + 2; - } - } - } - luaL_argerror(L, 1, - lua_pushfstring(L, "invalid conversion specifier '%%%s'", conv)); - return conv; /* to avoid warnings */ -} - - -static int os_date (lua_State *L) { - const char *s = luaL_optstring(L, 1, "%c"); - time_t t = luaL_opt(L, (time_t)luaL_checknumber, 2, time(NULL)); - struct tm tmr, *stm; - if (*s == '!') { /* UTC? */ - stm = l_gmtime(&t, &tmr); - s++; /* skip `!' */ - } - else - stm = l_localtime(&t, &tmr); - if (stm == NULL) /* invalid date? */ - lua_pushnil(L); - else if (strcmp(s, "*t") == 0) { - lua_createtable(L, 0, 9); /* 9 = number of fields */ - setfield(L, "sec", stm->tm_sec); - setfield(L, "min", stm->tm_min); - setfield(L, "hour", stm->tm_hour); - setfield(L, "day", stm->tm_mday); - setfield(L, "month", stm->tm_mon+1); - setfield(L, "year", stm->tm_year+1900); - setfield(L, "wday", stm->tm_wday+1); - setfield(L, "yday", stm->tm_yday+1); - setboolfield(L, "isdst", stm->tm_isdst); - } - else { - char cc[4]; - luaL_Buffer b; - cc[0] = '%'; - luaL_buffinit(L, &b); - while (*s) { - if (*s != '%') /* no conversion specifier? */ - luaL_addchar(&b, *s++); - else { - size_t reslen; - char buff[200]; /* should be big enough for any conversion result */ - s = checkoption(L, s + 1, cc); - reslen = strftime(buff, sizeof(buff), cc, stm); - luaL_addlstring(&b, buff, reslen); - } - } - luaL_pushresult(&b); - } - return 1; -} - - -static int os_time (lua_State *L) { - time_t t; - if (lua_isnoneornil(L, 1)) /* called without args? */ - t = time(NULL); /* get current time */ - else { - struct tm ts; - luaL_checktype(L, 1, LUA_TTABLE); - lua_settop(L, 1); /* make sure table is at the top */ - ts.tm_sec = getfield(L, "sec", 0); - ts.tm_min = getfield(L, "min", 0); - ts.tm_hour = getfield(L, "hour", 12); - ts.tm_mday = getfield(L, "day", -1); - ts.tm_mon = getfield(L, "month", -1) - 1; - ts.tm_year = getfield(L, "year", -1) - 1900; - ts.tm_isdst = getboolfield(L, "isdst"); - t = mktime(&ts); - } - if (t == (time_t)(-1)) - lua_pushnil(L); - else - lua_pushnumber(L, (lua_Number)t); - return 1; -} - - -static int os_difftime (lua_State *L) { - lua_pushnumber(L, difftime((time_t)(luaL_checknumber(L, 1)), - (time_t)(luaL_optnumber(L, 2, 0)))); - return 1; -} - -/* }====================================================== */ - - -static int os_setlocale (lua_State *L) { - static const int cat[] = {LC_ALL, LC_COLLATE, LC_CTYPE, LC_MONETARY, - LC_NUMERIC, LC_TIME}; - static const char *const catnames[] = {"all", "collate", "ctype", "monetary", - "numeric", "time", NULL}; - const char *l = luaL_optstring(L, 1, NULL); - int op = luaL_checkoption(L, 2, "all", catnames); - lua_pushstring(L, setlocale(cat[op], l)); - return 1; -} - - -static int os_exit (lua_State *L) { - int status; - if (lua_isboolean(L, 1)) - status = (lua_toboolean(L, 1) ? EXIT_SUCCESS : EXIT_FAILURE); - else - status = luaL_optint(L, 1, EXIT_SUCCESS); - if (lua_toboolean(L, 2)) - lua_close(L); - if (L) exit(status); /* 'if' to avoid warnings for unreachable 'return' */ - return 0; -} - - -static const luaL_Reg syslib[] = { - {"clock", os_clock}, - {"date", os_date}, - {"difftime", os_difftime}, - {"execute", os_execute}, - {"exit", os_exit}, - {"getenv", os_getenv}, - {"remove", os_remove}, - {"rename", os_rename}, - {"setlocale", os_setlocale}, - {"time", os_time}, - {"tmpname", os_tmpname}, - {NULL, NULL} -}; - -/* }====================================================== */ - - - -LUAMOD_API int luaopen_os (lua_State *L) { - luaL_newlib(L, syslib); - return 1; -} - diff --git a/lib/lua-5.2/src/lparser.c b/lib/lua-5.2/src/lparser.c deleted file mode 100644 index 9e1a9ca..0000000 --- a/lib/lua-5.2/src/lparser.c +++ /dev/null @@ -1,1638 +0,0 @@ -/* -** $Id: lparser.c,v 2.130.1.1 2013/04/12 18:48:47 roberto Exp $ -** Lua Parser -** See Copyright Notice in lua.h -*/ - - -#include - -#define lparser_c -#define LUA_CORE - -#include "lua.h" - -#include "lcode.h" -#include "ldebug.h" -#include "ldo.h" -#include "lfunc.h" -#include "llex.h" -#include "lmem.h" -#include "lobject.h" -#include "lopcodes.h" -#include "lparser.h" -#include "lstate.h" -#include "lstring.h" -#include "ltable.h" - - - -/* maximum number of local variables per function (must be smaller - than 250, due to the bytecode format) */ -#define MAXVARS 200 - - -#define hasmultret(k) ((k) == VCALL || (k) == VVARARG) - - - -/* -** nodes for block list (list of active blocks) -*/ -typedef struct BlockCnt { - struct BlockCnt *previous; /* chain */ - short firstlabel; /* index of first label in this block */ - short firstgoto; /* index of first pending goto in this block */ - lu_byte nactvar; /* # active locals outside the block */ - lu_byte upval; /* true if some variable in the block is an upvalue */ - lu_byte isloop; /* true if `block' is a loop */ -} BlockCnt; - - - -/* -** prototypes for recursive non-terminal functions -*/ -static void statement (LexState *ls); -static void expr (LexState *ls, expdesc *v); - - -static void anchor_token (LexState *ls) { - /* last token from outer function must be EOS */ - lua_assert(ls->fs != NULL || ls->t.token == TK_EOS); - if (ls->t.token == TK_NAME || ls->t.token == TK_STRING) { - TString *ts = ls->t.seminfo.ts; - luaX_newstring(ls, getstr(ts), ts->tsv.len); - } -} - - -/* semantic error */ -static l_noret semerror (LexState *ls, const char *msg) { - ls->t.token = 0; /* remove 'near to' from final message */ - luaX_syntaxerror(ls, msg); -} - - -static l_noret error_expected (LexState *ls, int token) { - luaX_syntaxerror(ls, - luaO_pushfstring(ls->L, "%s expected", luaX_token2str(ls, token))); -} - - -static l_noret errorlimit (FuncState *fs, int limit, const char *what) { - lua_State *L = fs->ls->L; - const char *msg; - int line = fs->f->linedefined; - const char *where = (line == 0) - ? "main function" - : luaO_pushfstring(L, "function at line %d", line); - msg = luaO_pushfstring(L, "too many %s (limit is %d) in %s", - what, limit, where); - luaX_syntaxerror(fs->ls, msg); -} - - -static void checklimit (FuncState *fs, int v, int l, const char *what) { - if (v > l) errorlimit(fs, l, what); -} - - -static int testnext (LexState *ls, int c) { - if (ls->t.token == c) { - luaX_next(ls); - return 1; - } - else return 0; -} - - -static void check (LexState *ls, int c) { - if (ls->t.token != c) - error_expected(ls, c); -} - - -static void checknext (LexState *ls, int c) { - check(ls, c); - luaX_next(ls); -} - - -#define check_condition(ls,c,msg) { if (!(c)) luaX_syntaxerror(ls, msg); } - - - -static void check_match (LexState *ls, int what, int who, int where) { - if (!testnext(ls, what)) { - if (where == ls->linenumber) - error_expected(ls, what); - else { - luaX_syntaxerror(ls, luaO_pushfstring(ls->L, - "%s expected (to close %s at line %d)", - luaX_token2str(ls, what), luaX_token2str(ls, who), where)); - } - } -} - - -static TString *str_checkname (LexState *ls) { - TString *ts; - check(ls, TK_NAME); - ts = ls->t.seminfo.ts; - luaX_next(ls); - return ts; -} - - -static void init_exp (expdesc *e, expkind k, int i) { - e->f = e->t = NO_JUMP; - e->k = k; - e->u.info = i; -} - - -static void codestring (LexState *ls, expdesc *e, TString *s) { - init_exp(e, VK, luaK_stringK(ls->fs, s)); -} - - -static void checkname (LexState *ls, expdesc *e) { - codestring(ls, e, str_checkname(ls)); -} - - -static int registerlocalvar (LexState *ls, TString *varname) { - FuncState *fs = ls->fs; - Proto *f = fs->f; - int oldsize = f->sizelocvars; - luaM_growvector(ls->L, f->locvars, fs->nlocvars, f->sizelocvars, - LocVar, SHRT_MAX, "local variables"); - while (oldsize < f->sizelocvars) f->locvars[oldsize++].varname = NULL; - f->locvars[fs->nlocvars].varname = varname; - luaC_objbarrier(ls->L, f, varname); - return fs->nlocvars++; -} - - -static void new_localvar (LexState *ls, TString *name) { - FuncState *fs = ls->fs; - Dyndata *dyd = ls->dyd; - int reg = registerlocalvar(ls, name); - checklimit(fs, dyd->actvar.n + 1 - fs->firstlocal, - MAXVARS, "local variables"); - luaM_growvector(ls->L, dyd->actvar.arr, dyd->actvar.n + 1, - dyd->actvar.size, Vardesc, MAX_INT, "local variables"); - dyd->actvar.arr[dyd->actvar.n++].idx = cast(short, reg); -} - - -static void new_localvarliteral_ (LexState *ls, const char *name, size_t sz) { - new_localvar(ls, luaX_newstring(ls, name, sz)); -} - -#define new_localvarliteral(ls,v) \ - new_localvarliteral_(ls, "" v, (sizeof(v)/sizeof(char))-1) - - -static LocVar *getlocvar (FuncState *fs, int i) { - int idx = fs->ls->dyd->actvar.arr[fs->firstlocal + i].idx; - lua_assert(idx < fs->nlocvars); - return &fs->f->locvars[idx]; -} - - -static void adjustlocalvars (LexState *ls, int nvars) { - FuncState *fs = ls->fs; - fs->nactvar = cast_byte(fs->nactvar + nvars); - for (; nvars; nvars--) { - getlocvar(fs, fs->nactvar - nvars)->startpc = fs->pc; - } -} - - -static void removevars (FuncState *fs, int tolevel) { - fs->ls->dyd->actvar.n -= (fs->nactvar - tolevel); - while (fs->nactvar > tolevel) - getlocvar(fs, --fs->nactvar)->endpc = fs->pc; -} - - -static int searchupvalue (FuncState *fs, TString *name) { - int i; - Upvaldesc *up = fs->f->upvalues; - for (i = 0; i < fs->nups; i++) { - if (luaS_eqstr(up[i].name, name)) return i; - } - return -1; /* not found */ -} - - -static int newupvalue (FuncState *fs, TString *name, expdesc *v) { - Proto *f = fs->f; - int oldsize = f->sizeupvalues; - checklimit(fs, fs->nups + 1, MAXUPVAL, "upvalues"); - luaM_growvector(fs->ls->L, f->upvalues, fs->nups, f->sizeupvalues, - Upvaldesc, MAXUPVAL, "upvalues"); - while (oldsize < f->sizeupvalues) f->upvalues[oldsize++].name = NULL; - f->upvalues[fs->nups].instack = (v->k == VLOCAL); - f->upvalues[fs->nups].idx = cast_byte(v->u.info); - f->upvalues[fs->nups].name = name; - luaC_objbarrier(fs->ls->L, f, name); - return fs->nups++; -} - - -static int searchvar (FuncState *fs, TString *n) { - int i; - for (i = cast_int(fs->nactvar) - 1; i >= 0; i--) { - if (luaS_eqstr(n, getlocvar(fs, i)->varname)) - return i; - } - return -1; /* not found */ -} - - -/* - Mark block where variable at given level was defined - (to emit close instructions later). -*/ -static void markupval (FuncState *fs, int level) { - BlockCnt *bl = fs->bl; - while (bl->nactvar > level) bl = bl->previous; - bl->upval = 1; -} - - -/* - Find variable with given name 'n'. If it is an upvalue, add this - upvalue into all intermediate functions. -*/ -static int singlevaraux (FuncState *fs, TString *n, expdesc *var, int base) { - if (fs == NULL) /* no more levels? */ - return VVOID; /* default is global */ - else { - int v = searchvar(fs, n); /* look up locals at current level */ - if (v >= 0) { /* found? */ - init_exp(var, VLOCAL, v); /* variable is local */ - if (!base) - markupval(fs, v); /* local will be used as an upval */ - return VLOCAL; - } - else { /* not found as local at current level; try upvalues */ - int idx = searchupvalue(fs, n); /* try existing upvalues */ - if (idx < 0) { /* not found? */ - if (singlevaraux(fs->prev, n, var, 0) == VVOID) /* try upper levels */ - return VVOID; /* not found; is a global */ - /* else was LOCAL or UPVAL */ - idx = newupvalue(fs, n, var); /* will be a new upvalue */ - } - init_exp(var, VUPVAL, idx); - return VUPVAL; - } - } -} - - -static void singlevar (LexState *ls, expdesc *var) { - TString *varname = str_checkname(ls); - FuncState *fs = ls->fs; - if (singlevaraux(fs, varname, var, 1) == VVOID) { /* global name? */ - expdesc key; - singlevaraux(fs, ls->envn, var, 1); /* get environment variable */ - lua_assert(var->k == VLOCAL || var->k == VUPVAL); - codestring(ls, &key, varname); /* key is variable name */ - luaK_indexed(fs, var, &key); /* env[varname] */ - } -} - - -static void adjust_assign (LexState *ls, int nvars, int nexps, expdesc *e) { - FuncState *fs = ls->fs; - int extra = nvars - nexps; - if (hasmultret(e->k)) { - extra++; /* includes call itself */ - if (extra < 0) extra = 0; - luaK_setreturns(fs, e, extra); /* last exp. provides the difference */ - if (extra > 1) luaK_reserveregs(fs, extra-1); - } - else { - if (e->k != VVOID) luaK_exp2nextreg(fs, e); /* close last expression */ - if (extra > 0) { - int reg = fs->freereg; - luaK_reserveregs(fs, extra); - luaK_nil(fs, reg, extra); - } - } -} - - -static void enterlevel (LexState *ls) { - lua_State *L = ls->L; - ++L->nCcalls; - checklimit(ls->fs, L->nCcalls, LUAI_MAXCCALLS, "C levels"); -} - - -#define leavelevel(ls) ((ls)->L->nCcalls--) - - -static void closegoto (LexState *ls, int g, Labeldesc *label) { - int i; - FuncState *fs = ls->fs; - Labellist *gl = &ls->dyd->gt; - Labeldesc *gt = &gl->arr[g]; - lua_assert(luaS_eqstr(gt->name, label->name)); - if (gt->nactvar < label->nactvar) { - TString *vname = getlocvar(fs, gt->nactvar)->varname; - const char *msg = luaO_pushfstring(ls->L, - " at line %d jumps into the scope of local " LUA_QS, - getstr(gt->name), gt->line, getstr(vname)); - semerror(ls, msg); - } - luaK_patchlist(fs, gt->pc, label->pc); - /* remove goto from pending list */ - for (i = g; i < gl->n - 1; i++) - gl->arr[i] = gl->arr[i + 1]; - gl->n--; -} - - -/* -** try to close a goto with existing labels; this solves backward jumps -*/ -static int findlabel (LexState *ls, int g) { - int i; - BlockCnt *bl = ls->fs->bl; - Dyndata *dyd = ls->dyd; - Labeldesc *gt = &dyd->gt.arr[g]; - /* check labels in current block for a match */ - for (i = bl->firstlabel; i < dyd->label.n; i++) { - Labeldesc *lb = &dyd->label.arr[i]; - if (luaS_eqstr(lb->name, gt->name)) { /* correct label? */ - if (gt->nactvar > lb->nactvar && - (bl->upval || dyd->label.n > bl->firstlabel)) - luaK_patchclose(ls->fs, gt->pc, lb->nactvar); - closegoto(ls, g, lb); /* close it */ - return 1; - } - } - return 0; /* label not found; cannot close goto */ -} - - -static int newlabelentry (LexState *ls, Labellist *l, TString *name, - int line, int pc) { - int n = l->n; - luaM_growvector(ls->L, l->arr, n, l->size, - Labeldesc, SHRT_MAX, "labels/gotos"); - l->arr[n].name = name; - l->arr[n].line = line; - l->arr[n].nactvar = ls->fs->nactvar; - l->arr[n].pc = pc; - l->n++; - return n; -} - - -/* -** check whether new label 'lb' matches any pending gotos in current -** block; solves forward jumps -*/ -static void findgotos (LexState *ls, Labeldesc *lb) { - Labellist *gl = &ls->dyd->gt; - int i = ls->fs->bl->firstgoto; - while (i < gl->n) { - if (luaS_eqstr(gl->arr[i].name, lb->name)) - closegoto(ls, i, lb); - else - i++; - } -} - - -/* -** "export" pending gotos to outer level, to check them against -** outer labels; if the block being exited has upvalues, and -** the goto exits the scope of any variable (which can be the -** upvalue), close those variables being exited. -*/ -static void movegotosout (FuncState *fs, BlockCnt *bl) { - int i = bl->firstgoto; - Labellist *gl = &fs->ls->dyd->gt; - /* correct pending gotos to current block and try to close it - with visible labels */ - while (i < gl->n) { - Labeldesc *gt = &gl->arr[i]; - if (gt->nactvar > bl->nactvar) { - if (bl->upval) - luaK_patchclose(fs, gt->pc, bl->nactvar); - gt->nactvar = bl->nactvar; - } - if (!findlabel(fs->ls, i)) - i++; /* move to next one */ - } -} - - -static void enterblock (FuncState *fs, BlockCnt *bl, lu_byte isloop) { - bl->isloop = isloop; - bl->nactvar = fs->nactvar; - bl->firstlabel = fs->ls->dyd->label.n; - bl->firstgoto = fs->ls->dyd->gt.n; - bl->upval = 0; - bl->previous = fs->bl; - fs->bl = bl; - lua_assert(fs->freereg == fs->nactvar); -} - - -/* -** create a label named "break" to resolve break statements -*/ -static void breaklabel (LexState *ls) { - TString *n = luaS_new(ls->L, "break"); - int l = newlabelentry(ls, &ls->dyd->label, n, 0, ls->fs->pc); - findgotos(ls, &ls->dyd->label.arr[l]); -} - -/* -** generates an error for an undefined 'goto'; choose appropriate -** message when label name is a reserved word (which can only be 'break') -*/ -static l_noret undefgoto (LexState *ls, Labeldesc *gt) { - const char *msg = isreserved(gt->name) - ? "<%s> at line %d not inside a loop" - : "no visible label " LUA_QS " for at line %d"; - msg = luaO_pushfstring(ls->L, msg, getstr(gt->name), gt->line); - semerror(ls, msg); -} - - -static void leaveblock (FuncState *fs) { - BlockCnt *bl = fs->bl; - LexState *ls = fs->ls; - if (bl->previous && bl->upval) { - /* create a 'jump to here' to close upvalues */ - int j = luaK_jump(fs); - luaK_patchclose(fs, j, bl->nactvar); - luaK_patchtohere(fs, j); - } - if (bl->isloop) - breaklabel(ls); /* close pending breaks */ - fs->bl = bl->previous; - removevars(fs, bl->nactvar); - lua_assert(bl->nactvar == fs->nactvar); - fs->freereg = fs->nactvar; /* free registers */ - ls->dyd->label.n = bl->firstlabel; /* remove local labels */ - if (bl->previous) /* inner block? */ - movegotosout(fs, bl); /* update pending gotos to outer block */ - else if (bl->firstgoto < ls->dyd->gt.n) /* pending gotos in outer block? */ - undefgoto(ls, &ls->dyd->gt.arr[bl->firstgoto]); /* error */ -} - - -/* -** adds a new prototype into list of prototypes -*/ -static Proto *addprototype (LexState *ls) { - Proto *clp; - lua_State *L = ls->L; - FuncState *fs = ls->fs; - Proto *f = fs->f; /* prototype of current function */ - if (fs->np >= f->sizep) { - int oldsize = f->sizep; - luaM_growvector(L, f->p, fs->np, f->sizep, Proto *, MAXARG_Bx, "functions"); - while (oldsize < f->sizep) f->p[oldsize++] = NULL; - } - f->p[fs->np++] = clp = luaF_newproto(L); - luaC_objbarrier(L, f, clp); - return clp; -} - - -/* -** codes instruction to create new closure in parent function. -** The OP_CLOSURE instruction must use the last available register, -** so that, if it invokes the GC, the GC knows which registers -** are in use at that time. -*/ -static void codeclosure (LexState *ls, expdesc *v) { - FuncState *fs = ls->fs->prev; - init_exp(v, VRELOCABLE, luaK_codeABx(fs, OP_CLOSURE, 0, fs->np - 1)); - luaK_exp2nextreg(fs, v); /* fix it at the last register */ -} - - -static void open_func (LexState *ls, FuncState *fs, BlockCnt *bl) { - lua_State *L = ls->L; - Proto *f; - fs->prev = ls->fs; /* linked list of funcstates */ - fs->ls = ls; - ls->fs = fs; - fs->pc = 0; - fs->lasttarget = 0; - fs->jpc = NO_JUMP; - fs->freereg = 0; - fs->nk = 0; - fs->np = 0; - fs->nups = 0; - fs->nlocvars = 0; - fs->nactvar = 0; - fs->firstlocal = ls->dyd->actvar.n; - fs->bl = NULL; - f = fs->f; - f->source = ls->source; - f->maxstacksize = 2; /* registers 0/1 are always valid */ - fs->h = luaH_new(L); - /* anchor table of constants (to avoid being collected) */ - sethvalue2s(L, L->top, fs->h); - incr_top(L); - enterblock(fs, bl, 0); -} - - -static void close_func (LexState *ls) { - lua_State *L = ls->L; - FuncState *fs = ls->fs; - Proto *f = fs->f; - luaK_ret(fs, 0, 0); /* final return */ - leaveblock(fs); - luaM_reallocvector(L, f->code, f->sizecode, fs->pc, Instruction); - f->sizecode = fs->pc; - luaM_reallocvector(L, f->lineinfo, f->sizelineinfo, fs->pc, int); - f->sizelineinfo = fs->pc; - luaM_reallocvector(L, f->k, f->sizek, fs->nk, TValue); - f->sizek = fs->nk; - luaM_reallocvector(L, f->p, f->sizep, fs->np, Proto *); - f->sizep = fs->np; - luaM_reallocvector(L, f->locvars, f->sizelocvars, fs->nlocvars, LocVar); - f->sizelocvars = fs->nlocvars; - luaM_reallocvector(L, f->upvalues, f->sizeupvalues, fs->nups, Upvaldesc); - f->sizeupvalues = fs->nups; - lua_assert(fs->bl == NULL); - ls->fs = fs->prev; - /* last token read was anchored in defunct function; must re-anchor it */ - anchor_token(ls); - L->top--; /* pop table of constants */ - luaC_checkGC(L); -} - - - -/*============================================================*/ -/* GRAMMAR RULES */ -/*============================================================*/ - - -/* -** check whether current token is in the follow set of a block. -** 'until' closes syntactical blocks, but do not close scope, -** so it handled in separate. -*/ -static int block_follow (LexState *ls, int withuntil) { - switch (ls->t.token) { - case TK_ELSE: case TK_ELSEIF: - case TK_END: case TK_EOS: - return 1; - case TK_UNTIL: return withuntil; - default: return 0; - } -} - - -static void statlist (LexState *ls) { - /* statlist -> { stat [`;'] } */ - while (!block_follow(ls, 1)) { - if (ls->t.token == TK_RETURN) { - statement(ls); - return; /* 'return' must be last statement */ - } - statement(ls); - } -} - - -static void fieldsel (LexState *ls, expdesc *v) { - /* fieldsel -> ['.' | ':'] NAME */ - FuncState *fs = ls->fs; - expdesc key; - luaK_exp2anyregup(fs, v); - luaX_next(ls); /* skip the dot or colon */ - checkname(ls, &key); - luaK_indexed(fs, v, &key); -} - - -static void yindex (LexState *ls, expdesc *v) { - /* index -> '[' expr ']' */ - luaX_next(ls); /* skip the '[' */ - expr(ls, v); - luaK_exp2val(ls->fs, v); - checknext(ls, ']'); -} - - -/* -** {====================================================================== -** Rules for Constructors -** ======================================================================= -*/ - - -struct ConsControl { - expdesc v; /* last list item read */ - expdesc *t; /* table descriptor */ - int nh; /* total number of `record' elements */ - int na; /* total number of array elements */ - int tostore; /* number of array elements pending to be stored */ -}; - - -static void recfield (LexState *ls, struct ConsControl *cc) { - /* recfield -> (NAME | `['exp1`]') = exp1 */ - FuncState *fs = ls->fs; - int reg = ls->fs->freereg; - expdesc key, val; - int rkkey; - if (ls->t.token == TK_NAME) { - checklimit(fs, cc->nh, MAX_INT, "items in a constructor"); - checkname(ls, &key); - } - else /* ls->t.token == '[' */ - yindex(ls, &key); - cc->nh++; - checknext(ls, '='); - rkkey = luaK_exp2RK(fs, &key); - expr(ls, &val); - luaK_codeABC(fs, OP_SETTABLE, cc->t->u.info, rkkey, luaK_exp2RK(fs, &val)); - fs->freereg = reg; /* free registers */ -} - - -static void closelistfield (FuncState *fs, struct ConsControl *cc) { - if (cc->v.k == VVOID) return; /* there is no list item */ - luaK_exp2nextreg(fs, &cc->v); - cc->v.k = VVOID; - if (cc->tostore == LFIELDS_PER_FLUSH) { - luaK_setlist(fs, cc->t->u.info, cc->na, cc->tostore); /* flush */ - cc->tostore = 0; /* no more items pending */ - } -} - - -static void lastlistfield (FuncState *fs, struct ConsControl *cc) { - if (cc->tostore == 0) return; - if (hasmultret(cc->v.k)) { - luaK_setmultret(fs, &cc->v); - luaK_setlist(fs, cc->t->u.info, cc->na, LUA_MULTRET); - cc->na--; /* do not count last expression (unknown number of elements) */ - } - else { - if (cc->v.k != VVOID) - luaK_exp2nextreg(fs, &cc->v); - luaK_setlist(fs, cc->t->u.info, cc->na, cc->tostore); - } -} - - -static void listfield (LexState *ls, struct ConsControl *cc) { - /* listfield -> exp */ - expr(ls, &cc->v); - checklimit(ls->fs, cc->na, MAX_INT, "items in a constructor"); - cc->na++; - cc->tostore++; -} - - -static void field (LexState *ls, struct ConsControl *cc) { - /* field -> listfield | recfield */ - switch(ls->t.token) { - case TK_NAME: { /* may be 'listfield' or 'recfield' */ - if (luaX_lookahead(ls) != '=') /* expression? */ - listfield(ls, cc); - else - recfield(ls, cc); - break; - } - case '[': { - recfield(ls, cc); - break; - } - default: { - listfield(ls, cc); - break; - } - } -} - - -static void constructor (LexState *ls, expdesc *t) { - /* constructor -> '{' [ field { sep field } [sep] ] '}' - sep -> ',' | ';' */ - FuncState *fs = ls->fs; - int line = ls->linenumber; - int pc = luaK_codeABC(fs, OP_NEWTABLE, 0, 0, 0); - struct ConsControl cc; - cc.na = cc.nh = cc.tostore = 0; - cc.t = t; - init_exp(t, VRELOCABLE, pc); - init_exp(&cc.v, VVOID, 0); /* no value (yet) */ - luaK_exp2nextreg(ls->fs, t); /* fix it at stack top */ - checknext(ls, '{'); - do { - lua_assert(cc.v.k == VVOID || cc.tostore > 0); - if (ls->t.token == '}') break; - closelistfield(fs, &cc); - field(ls, &cc); - } while (testnext(ls, ',') || testnext(ls, ';')); - check_match(ls, '}', '{', line); - lastlistfield(fs, &cc); - SETARG_B(fs->f->code[pc], luaO_int2fb(cc.na)); /* set initial array size */ - SETARG_C(fs->f->code[pc], luaO_int2fb(cc.nh)); /* set initial table size */ -} - -/* }====================================================================== */ - - - -static void parlist (LexState *ls) { - /* parlist -> [ param { `,' param } ] */ - FuncState *fs = ls->fs; - Proto *f = fs->f; - int nparams = 0; - f->is_vararg = 0; - if (ls->t.token != ')') { /* is `parlist' not empty? */ - do { - switch (ls->t.token) { - case TK_NAME: { /* param -> NAME */ - new_localvar(ls, str_checkname(ls)); - nparams++; - break; - } - case TK_DOTS: { /* param -> `...' */ - luaX_next(ls); - f->is_vararg = 1; - break; - } - default: luaX_syntaxerror(ls, " or " LUA_QL("...") " expected"); - } - } while (!f->is_vararg && testnext(ls, ',')); - } - adjustlocalvars(ls, nparams); - f->numparams = cast_byte(fs->nactvar); - luaK_reserveregs(fs, fs->nactvar); /* reserve register for parameters */ -} - - -static void body (LexState *ls, expdesc *e, int ismethod, int line) { - /* body -> `(' parlist `)' block END */ - FuncState new_fs; - BlockCnt bl; - new_fs.f = addprototype(ls); - new_fs.f->linedefined = line; - open_func(ls, &new_fs, &bl); - checknext(ls, '('); - if (ismethod) { - new_localvarliteral(ls, "self"); /* create 'self' parameter */ - adjustlocalvars(ls, 1); - } - parlist(ls); - checknext(ls, ')'); - statlist(ls); - new_fs.f->lastlinedefined = ls->linenumber; - check_match(ls, TK_END, TK_FUNCTION, line); - codeclosure(ls, e); - close_func(ls); -} - - -static int explist (LexState *ls, expdesc *v) { - /* explist -> expr { `,' expr } */ - int n = 1; /* at least one expression */ - expr(ls, v); - while (testnext(ls, ',')) { - luaK_exp2nextreg(ls->fs, v); - expr(ls, v); - n++; - } - return n; -} - - -static void funcargs (LexState *ls, expdesc *f, int line) { - FuncState *fs = ls->fs; - expdesc args; - int base, nparams; - switch (ls->t.token) { - case '(': { /* funcargs -> `(' [ explist ] `)' */ - luaX_next(ls); - if (ls->t.token == ')') /* arg list is empty? */ - args.k = VVOID; - else { - explist(ls, &args); - luaK_setmultret(fs, &args); - } - check_match(ls, ')', '(', line); - break; - } - case '{': { /* funcargs -> constructor */ - constructor(ls, &args); - break; - } - case TK_STRING: { /* funcargs -> STRING */ - codestring(ls, &args, ls->t.seminfo.ts); - luaX_next(ls); /* must use `seminfo' before `next' */ - break; - } - default: { - luaX_syntaxerror(ls, "function arguments expected"); - } - } - lua_assert(f->k == VNONRELOC); - base = f->u.info; /* base register for call */ - if (hasmultret(args.k)) - nparams = LUA_MULTRET; /* open call */ - else { - if (args.k != VVOID) - luaK_exp2nextreg(fs, &args); /* close last argument */ - nparams = fs->freereg - (base+1); - } - init_exp(f, VCALL, luaK_codeABC(fs, OP_CALL, base, nparams+1, 2)); - luaK_fixline(fs, line); - fs->freereg = base+1; /* call remove function and arguments and leaves - (unless changed) one result */ -} - - - - -/* -** {====================================================================== -** Expression parsing -** ======================================================================= -*/ - - -static void primaryexp (LexState *ls, expdesc *v) { - /* primaryexp -> NAME | '(' expr ')' */ - switch (ls->t.token) { - case '(': { - int line = ls->linenumber; - luaX_next(ls); - expr(ls, v); - check_match(ls, ')', '(', line); - luaK_dischargevars(ls->fs, v); - return; - } - case TK_NAME: { - singlevar(ls, v); - return; - } - default: { - luaX_syntaxerror(ls, "unexpected symbol"); - } - } -} - - -static void suffixedexp (LexState *ls, expdesc *v) { - /* suffixedexp -> - primaryexp { '.' NAME | '[' exp ']' | ':' NAME funcargs | funcargs } */ - FuncState *fs = ls->fs; - int line = ls->linenumber; - primaryexp(ls, v); - for (;;) { - switch (ls->t.token) { - case '.': { /* fieldsel */ - fieldsel(ls, v); - break; - } - case '[': { /* `[' exp1 `]' */ - expdesc key; - luaK_exp2anyregup(fs, v); - yindex(ls, &key); - luaK_indexed(fs, v, &key); - break; - } - case ':': { /* `:' NAME funcargs */ - expdesc key; - luaX_next(ls); - checkname(ls, &key); - luaK_self(fs, v, &key); - funcargs(ls, v, line); - break; - } - case '(': case TK_STRING: case '{': { /* funcargs */ - luaK_exp2nextreg(fs, v); - funcargs(ls, v, line); - break; - } - default: return; - } - } -} - - -static void simpleexp (LexState *ls, expdesc *v) { - /* simpleexp -> NUMBER | STRING | NIL | TRUE | FALSE | ... | - constructor | FUNCTION body | suffixedexp */ - switch (ls->t.token) { - case TK_NUMBER: { - init_exp(v, VKNUM, 0); - v->u.nval = ls->t.seminfo.r; - break; - } - case TK_STRING: { - codestring(ls, v, ls->t.seminfo.ts); - break; - } - case TK_NIL: { - init_exp(v, VNIL, 0); - break; - } - case TK_TRUE: { - init_exp(v, VTRUE, 0); - break; - } - case TK_FALSE: { - init_exp(v, VFALSE, 0); - break; - } - case TK_DOTS: { /* vararg */ - FuncState *fs = ls->fs; - check_condition(ls, fs->f->is_vararg, - "cannot use " LUA_QL("...") " outside a vararg function"); - init_exp(v, VVARARG, luaK_codeABC(fs, OP_VARARG, 0, 1, 0)); - break; - } - case '{': { /* constructor */ - constructor(ls, v); - return; - } - case TK_FUNCTION: { - luaX_next(ls); - body(ls, v, 0, ls->linenumber); - return; - } - default: { - suffixedexp(ls, v); - return; - } - } - luaX_next(ls); -} - - -static UnOpr getunopr (int op) { - switch (op) { - case TK_NOT: return OPR_NOT; - case '-': return OPR_MINUS; - case '#': return OPR_LEN; - default: return OPR_NOUNOPR; - } -} - - -static BinOpr getbinopr (int op) { - switch (op) { - case '+': return OPR_ADD; - case '-': return OPR_SUB; - case '*': return OPR_MUL; - case '/': return OPR_DIV; - case '%': return OPR_MOD; - case '^': return OPR_POW; - case TK_CONCAT: return OPR_CONCAT; - case TK_NE: return OPR_NE; - case TK_EQ: return OPR_EQ; - case '<': return OPR_LT; - case TK_LE: return OPR_LE; - case '>': return OPR_GT; - case TK_GE: return OPR_GE; - case TK_AND: return OPR_AND; - case TK_OR: return OPR_OR; - default: return OPR_NOBINOPR; - } -} - - -static const struct { - lu_byte left; /* left priority for each binary operator */ - lu_byte right; /* right priority */ -} priority[] = { /* ORDER OPR */ - {6, 6}, {6, 6}, {7, 7}, {7, 7}, {7, 7}, /* `+' `-' `*' `/' `%' */ - {10, 9}, {5, 4}, /* ^, .. (right associative) */ - {3, 3}, {3, 3}, {3, 3}, /* ==, <, <= */ - {3, 3}, {3, 3}, {3, 3}, /* ~=, >, >= */ - {2, 2}, {1, 1} /* and, or */ -}; - -#define UNARY_PRIORITY 8 /* priority for unary operators */ - - -/* -** subexpr -> (simpleexp | unop subexpr) { binop subexpr } -** where `binop' is any binary operator with a priority higher than `limit' -*/ -static BinOpr subexpr (LexState *ls, expdesc *v, int limit) { - BinOpr op; - UnOpr uop; - enterlevel(ls); - uop = getunopr(ls->t.token); - if (uop != OPR_NOUNOPR) { - int line = ls->linenumber; - luaX_next(ls); - subexpr(ls, v, UNARY_PRIORITY); - luaK_prefix(ls->fs, uop, v, line); - } - else simpleexp(ls, v); - /* expand while operators have priorities higher than `limit' */ - op = getbinopr(ls->t.token); - while (op != OPR_NOBINOPR && priority[op].left > limit) { - expdesc v2; - BinOpr nextop; - int line = ls->linenumber; - luaX_next(ls); - luaK_infix(ls->fs, op, v); - /* read sub-expression with higher priority */ - nextop = subexpr(ls, &v2, priority[op].right); - luaK_posfix(ls->fs, op, v, &v2, line); - op = nextop; - } - leavelevel(ls); - return op; /* return first untreated operator */ -} - - -static void expr (LexState *ls, expdesc *v) { - subexpr(ls, v, 0); -} - -/* }==================================================================== */ - - - -/* -** {====================================================================== -** Rules for Statements -** ======================================================================= -*/ - - -static void block (LexState *ls) { - /* block -> statlist */ - FuncState *fs = ls->fs; - BlockCnt bl; - enterblock(fs, &bl, 0); - statlist(ls); - leaveblock(fs); -} - - -/* -** structure to chain all variables in the left-hand side of an -** assignment -*/ -struct LHS_assign { - struct LHS_assign *prev; - expdesc v; /* variable (global, local, upvalue, or indexed) */ -}; - - -/* -** check whether, in an assignment to an upvalue/local variable, the -** upvalue/local variable is begin used in a previous assignment to a -** table. If so, save original upvalue/local value in a safe place and -** use this safe copy in the previous assignment. -*/ -static void check_conflict (LexState *ls, struct LHS_assign *lh, expdesc *v) { - FuncState *fs = ls->fs; - int extra = fs->freereg; /* eventual position to save local variable */ - int conflict = 0; - for (; lh; lh = lh->prev) { /* check all previous assignments */ - if (lh->v.k == VINDEXED) { /* assigning to a table? */ - /* table is the upvalue/local being assigned now? */ - if (lh->v.u.ind.vt == v->k && lh->v.u.ind.t == v->u.info) { - conflict = 1; - lh->v.u.ind.vt = VLOCAL; - lh->v.u.ind.t = extra; /* previous assignment will use safe copy */ - } - /* index is the local being assigned? (index cannot be upvalue) */ - if (v->k == VLOCAL && lh->v.u.ind.idx == v->u.info) { - conflict = 1; - lh->v.u.ind.idx = extra; /* previous assignment will use safe copy */ - } - } - } - if (conflict) { - /* copy upvalue/local value to a temporary (in position 'extra') */ - OpCode op = (v->k == VLOCAL) ? OP_MOVE : OP_GETUPVAL; - luaK_codeABC(fs, op, extra, v->u.info, 0); - luaK_reserveregs(fs, 1); - } -} - - -static void assignment (LexState *ls, struct LHS_assign *lh, int nvars) { - expdesc e; - check_condition(ls, vkisvar(lh->v.k), "syntax error"); - if (testnext(ls, ',')) { /* assignment -> ',' suffixedexp assignment */ - struct LHS_assign nv; - nv.prev = lh; - suffixedexp(ls, &nv.v); - if (nv.v.k != VINDEXED) - check_conflict(ls, lh, &nv.v); - checklimit(ls->fs, nvars + ls->L->nCcalls, LUAI_MAXCCALLS, - "C levels"); - assignment(ls, &nv, nvars+1); - } - else { /* assignment -> `=' explist */ - int nexps; - checknext(ls, '='); - nexps = explist(ls, &e); - if (nexps != nvars) { - adjust_assign(ls, nvars, nexps, &e); - if (nexps > nvars) - ls->fs->freereg -= nexps - nvars; /* remove extra values */ - } - else { - luaK_setoneret(ls->fs, &e); /* close last expression */ - luaK_storevar(ls->fs, &lh->v, &e); - return; /* avoid default */ - } - } - init_exp(&e, VNONRELOC, ls->fs->freereg-1); /* default assignment */ - luaK_storevar(ls->fs, &lh->v, &e); -} - - -static int cond (LexState *ls) { - /* cond -> exp */ - expdesc v; - expr(ls, &v); /* read condition */ - if (v.k == VNIL) v.k = VFALSE; /* `falses' are all equal here */ - luaK_goiftrue(ls->fs, &v); - return v.f; -} - - -static void gotostat (LexState *ls, int pc) { - int line = ls->linenumber; - TString *label; - int g; - if (testnext(ls, TK_GOTO)) - label = str_checkname(ls); - else { - luaX_next(ls); /* skip break */ - label = luaS_new(ls->L, "break"); - } - g = newlabelentry(ls, &ls->dyd->gt, label, line, pc); - findlabel(ls, g); /* close it if label already defined */ -} - - -/* check for repeated labels on the same block */ -static void checkrepeated (FuncState *fs, Labellist *ll, TString *label) { - int i; - for (i = fs->bl->firstlabel; i < ll->n; i++) { - if (luaS_eqstr(label, ll->arr[i].name)) { - const char *msg = luaO_pushfstring(fs->ls->L, - "label " LUA_QS " already defined on line %d", - getstr(label), ll->arr[i].line); - semerror(fs->ls, msg); - } - } -} - - -/* skip no-op statements */ -static void skipnoopstat (LexState *ls) { - while (ls->t.token == ';' || ls->t.token == TK_DBCOLON) - statement(ls); -} - - -static void labelstat (LexState *ls, TString *label, int line) { - /* label -> '::' NAME '::' */ - FuncState *fs = ls->fs; - Labellist *ll = &ls->dyd->label; - int l; /* index of new label being created */ - checkrepeated(fs, ll, label); /* check for repeated labels */ - checknext(ls, TK_DBCOLON); /* skip double colon */ - /* create new entry for this label */ - l = newlabelentry(ls, ll, label, line, fs->pc); - skipnoopstat(ls); /* skip other no-op statements */ - if (block_follow(ls, 0)) { /* label is last no-op statement in the block? */ - /* assume that locals are already out of scope */ - ll->arr[l].nactvar = fs->bl->nactvar; - } - findgotos(ls, &ll->arr[l]); -} - - -static void whilestat (LexState *ls, int line) { - /* whilestat -> WHILE cond DO block END */ - FuncState *fs = ls->fs; - int whileinit; - int condexit; - BlockCnt bl; - luaX_next(ls); /* skip WHILE */ - whileinit = luaK_getlabel(fs); - condexit = cond(ls); - enterblock(fs, &bl, 1); - checknext(ls, TK_DO); - block(ls); - luaK_jumpto(fs, whileinit); - check_match(ls, TK_END, TK_WHILE, line); - leaveblock(fs); - luaK_patchtohere(fs, condexit); /* false conditions finish the loop */ -} - - -static void repeatstat (LexState *ls, int line) { - /* repeatstat -> REPEAT block UNTIL cond */ - int condexit; - FuncState *fs = ls->fs; - int repeat_init = luaK_getlabel(fs); - BlockCnt bl1, bl2; - enterblock(fs, &bl1, 1); /* loop block */ - enterblock(fs, &bl2, 0); /* scope block */ - luaX_next(ls); /* skip REPEAT */ - statlist(ls); - check_match(ls, TK_UNTIL, TK_REPEAT, line); - condexit = cond(ls); /* read condition (inside scope block) */ - if (bl2.upval) /* upvalues? */ - luaK_patchclose(fs, condexit, bl2.nactvar); - leaveblock(fs); /* finish scope */ - luaK_patchlist(fs, condexit, repeat_init); /* close the loop */ - leaveblock(fs); /* finish loop */ -} - - -static int exp1 (LexState *ls) { - expdesc e; - int reg; - expr(ls, &e); - luaK_exp2nextreg(ls->fs, &e); - lua_assert(e.k == VNONRELOC); - reg = e.u.info; - return reg; -} - - -static void forbody (LexState *ls, int base, int line, int nvars, int isnum) { - /* forbody -> DO block */ - BlockCnt bl; - FuncState *fs = ls->fs; - int prep, endfor; - adjustlocalvars(ls, 3); /* control variables */ - checknext(ls, TK_DO); - prep = isnum ? luaK_codeAsBx(fs, OP_FORPREP, base, NO_JUMP) : luaK_jump(fs); - enterblock(fs, &bl, 0); /* scope for declared variables */ - adjustlocalvars(ls, nvars); - luaK_reserveregs(fs, nvars); - block(ls); - leaveblock(fs); /* end of scope for declared variables */ - luaK_patchtohere(fs, prep); - if (isnum) /* numeric for? */ - endfor = luaK_codeAsBx(fs, OP_FORLOOP, base, NO_JUMP); - else { /* generic for */ - luaK_codeABC(fs, OP_TFORCALL, base, 0, nvars); - luaK_fixline(fs, line); - endfor = luaK_codeAsBx(fs, OP_TFORLOOP, base + 2, NO_JUMP); - } - luaK_patchlist(fs, endfor, prep + 1); - luaK_fixline(fs, line); -} - - -static void fornum (LexState *ls, TString *varname, int line) { - /* fornum -> NAME = exp1,exp1[,exp1] forbody */ - FuncState *fs = ls->fs; - int base = fs->freereg; - new_localvarliteral(ls, "(for index)"); - new_localvarliteral(ls, "(for limit)"); - new_localvarliteral(ls, "(for step)"); - new_localvar(ls, varname); - checknext(ls, '='); - exp1(ls); /* initial value */ - checknext(ls, ','); - exp1(ls); /* limit */ - if (testnext(ls, ',')) - exp1(ls); /* optional step */ - else { /* default step = 1 */ - luaK_codek(fs, fs->freereg, luaK_numberK(fs, 1)); - luaK_reserveregs(fs, 1); - } - forbody(ls, base, line, 1, 1); -} - - -static void forlist (LexState *ls, TString *indexname) { - /* forlist -> NAME {,NAME} IN explist forbody */ - FuncState *fs = ls->fs; - expdesc e; - int nvars = 4; /* gen, state, control, plus at least one declared var */ - int line; - int base = fs->freereg; - /* create control variables */ - new_localvarliteral(ls, "(for generator)"); - new_localvarliteral(ls, "(for state)"); - new_localvarliteral(ls, "(for control)"); - /* create declared variables */ - new_localvar(ls, indexname); - while (testnext(ls, ',')) { - new_localvar(ls, str_checkname(ls)); - nvars++; - } - checknext(ls, TK_IN); - line = ls->linenumber; - adjust_assign(ls, 3, explist(ls, &e), &e); - luaK_checkstack(fs, 3); /* extra space to call generator */ - forbody(ls, base, line, nvars - 3, 0); -} - - -static void forstat (LexState *ls, int line) { - /* forstat -> FOR (fornum | forlist) END */ - FuncState *fs = ls->fs; - TString *varname; - BlockCnt bl; - enterblock(fs, &bl, 1); /* scope for loop and control variables */ - luaX_next(ls); /* skip `for' */ - varname = str_checkname(ls); /* first variable name */ - switch (ls->t.token) { - case '=': fornum(ls, varname, line); break; - case ',': case TK_IN: forlist(ls, varname); break; - default: luaX_syntaxerror(ls, LUA_QL("=") " or " LUA_QL("in") " expected"); - } - check_match(ls, TK_END, TK_FOR, line); - leaveblock(fs); /* loop scope (`break' jumps to this point) */ -} - - -static void test_then_block (LexState *ls, int *escapelist) { - /* test_then_block -> [IF | ELSEIF] cond THEN block */ - BlockCnt bl; - FuncState *fs = ls->fs; - expdesc v; - int jf; /* instruction to skip 'then' code (if condition is false) */ - luaX_next(ls); /* skip IF or ELSEIF */ - expr(ls, &v); /* read condition */ - checknext(ls, TK_THEN); - if (ls->t.token == TK_GOTO || ls->t.token == TK_BREAK) { - luaK_goiffalse(ls->fs, &v); /* will jump to label if condition is true */ - enterblock(fs, &bl, 0); /* must enter block before 'goto' */ - gotostat(ls, v.t); /* handle goto/break */ - skipnoopstat(ls); /* skip other no-op statements */ - if (block_follow(ls, 0)) { /* 'goto' is the entire block? */ - leaveblock(fs); - return; /* and that is it */ - } - else /* must skip over 'then' part if condition is false */ - jf = luaK_jump(fs); - } - else { /* regular case (not goto/break) */ - luaK_goiftrue(ls->fs, &v); /* skip over block if condition is false */ - enterblock(fs, &bl, 0); - jf = v.f; - } - statlist(ls); /* `then' part */ - leaveblock(fs); - if (ls->t.token == TK_ELSE || - ls->t.token == TK_ELSEIF) /* followed by 'else'/'elseif'? */ - luaK_concat(fs, escapelist, luaK_jump(fs)); /* must jump over it */ - luaK_patchtohere(fs, jf); -} - - -static void ifstat (LexState *ls, int line) { - /* ifstat -> IF cond THEN block {ELSEIF cond THEN block} [ELSE block] END */ - FuncState *fs = ls->fs; - int escapelist = NO_JUMP; /* exit list for finished parts */ - test_then_block(ls, &escapelist); /* IF cond THEN block */ - while (ls->t.token == TK_ELSEIF) - test_then_block(ls, &escapelist); /* ELSEIF cond THEN block */ - if (testnext(ls, TK_ELSE)) - block(ls); /* `else' part */ - check_match(ls, TK_END, TK_IF, line); - luaK_patchtohere(fs, escapelist); /* patch escape list to 'if' end */ -} - - -static void localfunc (LexState *ls) { - expdesc b; - FuncState *fs = ls->fs; - new_localvar(ls, str_checkname(ls)); /* new local variable */ - adjustlocalvars(ls, 1); /* enter its scope */ - body(ls, &b, 0, ls->linenumber); /* function created in next register */ - /* debug information will only see the variable after this point! */ - getlocvar(fs, b.u.info)->startpc = fs->pc; -} - - -static void localstat (LexState *ls) { - /* stat -> LOCAL NAME {`,' NAME} [`=' explist] */ - int nvars = 0; - int nexps; - expdesc e; - do { - new_localvar(ls, str_checkname(ls)); - nvars++; - } while (testnext(ls, ',')); - if (testnext(ls, '=')) - nexps = explist(ls, &e); - else { - e.k = VVOID; - nexps = 0; - } - adjust_assign(ls, nvars, nexps, &e); - adjustlocalvars(ls, nvars); -} - - -static int funcname (LexState *ls, expdesc *v) { - /* funcname -> NAME {fieldsel} [`:' NAME] */ - int ismethod = 0; - singlevar(ls, v); - while (ls->t.token == '.') - fieldsel(ls, v); - if (ls->t.token == ':') { - ismethod = 1; - fieldsel(ls, v); - } - return ismethod; -} - - -static void funcstat (LexState *ls, int line) { - /* funcstat -> FUNCTION funcname body */ - int ismethod; - expdesc v, b; - luaX_next(ls); /* skip FUNCTION */ - ismethod = funcname(ls, &v); - body(ls, &b, ismethod, line); - luaK_storevar(ls->fs, &v, &b); - luaK_fixline(ls->fs, line); /* definition `happens' in the first line */ -} - - -static void exprstat (LexState *ls) { - /* stat -> func | assignment */ - FuncState *fs = ls->fs; - struct LHS_assign v; - suffixedexp(ls, &v.v); - if (ls->t.token == '=' || ls->t.token == ',') { /* stat -> assignment ? */ - v.prev = NULL; - assignment(ls, &v, 1); - } - else { /* stat -> func */ - check_condition(ls, v.v.k == VCALL, "syntax error"); - SETARG_C(getcode(fs, &v.v), 1); /* call statement uses no results */ - } -} - - -static void retstat (LexState *ls) { - /* stat -> RETURN [explist] [';'] */ - FuncState *fs = ls->fs; - expdesc e; - int first, nret; /* registers with returned values */ - if (block_follow(ls, 1) || ls->t.token == ';') - first = nret = 0; /* return no values */ - else { - nret = explist(ls, &e); /* optional return values */ - if (hasmultret(e.k)) { - luaK_setmultret(fs, &e); - if (e.k == VCALL && nret == 1) { /* tail call? */ - SET_OPCODE(getcode(fs,&e), OP_TAILCALL); - lua_assert(GETARG_A(getcode(fs,&e)) == fs->nactvar); - } - first = fs->nactvar; - nret = LUA_MULTRET; /* return all values */ - } - else { - if (nret == 1) /* only one single value? */ - first = luaK_exp2anyreg(fs, &e); - else { - luaK_exp2nextreg(fs, &e); /* values must go to the `stack' */ - first = fs->nactvar; /* return all `active' values */ - lua_assert(nret == fs->freereg - first); - } - } - } - luaK_ret(fs, first, nret); - testnext(ls, ';'); /* skip optional semicolon */ -} - - -static void statement (LexState *ls) { - int line = ls->linenumber; /* may be needed for error messages */ - enterlevel(ls); - switch (ls->t.token) { - case ';': { /* stat -> ';' (empty statement) */ - luaX_next(ls); /* skip ';' */ - break; - } - case TK_IF: { /* stat -> ifstat */ - ifstat(ls, line); - break; - } - case TK_WHILE: { /* stat -> whilestat */ - whilestat(ls, line); - break; - } - case TK_DO: { /* stat -> DO block END */ - luaX_next(ls); /* skip DO */ - block(ls); - check_match(ls, TK_END, TK_DO, line); - break; - } - case TK_FOR: { /* stat -> forstat */ - forstat(ls, line); - break; - } - case TK_REPEAT: { /* stat -> repeatstat */ - repeatstat(ls, line); - break; - } - case TK_FUNCTION: { /* stat -> funcstat */ - funcstat(ls, line); - break; - } - case TK_LOCAL: { /* stat -> localstat */ - luaX_next(ls); /* skip LOCAL */ - if (testnext(ls, TK_FUNCTION)) /* local function? */ - localfunc(ls); - else - localstat(ls); - break; - } - case TK_DBCOLON: { /* stat -> label */ - luaX_next(ls); /* skip double colon */ - labelstat(ls, str_checkname(ls), line); - break; - } - case TK_RETURN: { /* stat -> retstat */ - luaX_next(ls); /* skip RETURN */ - retstat(ls); - break; - } - case TK_BREAK: /* stat -> breakstat */ - case TK_GOTO: { /* stat -> 'goto' NAME */ - gotostat(ls, luaK_jump(ls->fs)); - break; - } - default: { /* stat -> func | assignment */ - exprstat(ls); - break; - } - } - lua_assert(ls->fs->f->maxstacksize >= ls->fs->freereg && - ls->fs->freereg >= ls->fs->nactvar); - ls->fs->freereg = ls->fs->nactvar; /* free registers */ - leavelevel(ls); -} - -/* }====================================================================== */ - - -/* -** compiles the main function, which is a regular vararg function with an -** upvalue named LUA_ENV -*/ -static void mainfunc (LexState *ls, FuncState *fs) { - BlockCnt bl; - expdesc v; - open_func(ls, fs, &bl); - fs->f->is_vararg = 1; /* main function is always vararg */ - init_exp(&v, VLOCAL, 0); /* create and... */ - newupvalue(fs, ls->envn, &v); /* ...set environment upvalue */ - luaX_next(ls); /* read first token */ - statlist(ls); /* parse main body */ - check(ls, TK_EOS); - close_func(ls); -} - - -Closure *luaY_parser (lua_State *L, ZIO *z, Mbuffer *buff, - Dyndata *dyd, const char *name, int firstchar) { - LexState lexstate; - FuncState funcstate; - Closure *cl = luaF_newLclosure(L, 1); /* create main closure */ - /* anchor closure (to avoid being collected) */ - setclLvalue(L, L->top, cl); - incr_top(L); - funcstate.f = cl->l.p = luaF_newproto(L); - funcstate.f->source = luaS_new(L, name); /* create and anchor TString */ - lexstate.buff = buff; - lexstate.dyd = dyd; - dyd->actvar.n = dyd->gt.n = dyd->label.n = 0; - luaX_setinput(L, &lexstate, z, funcstate.f->source, firstchar); - mainfunc(&lexstate, &funcstate); - lua_assert(!funcstate.prev && funcstate.nups == 1 && !lexstate.fs); - /* all scopes should be correctly finished */ - lua_assert(dyd->actvar.n == 0 && dyd->gt.n == 0 && dyd->label.n == 0); - return cl; /* it's on the stack too */ -} - diff --git a/lib/lua-5.2/src/lparser.h b/lib/lua-5.2/src/lparser.h deleted file mode 100644 index 0346e3c..0000000 --- a/lib/lua-5.2/src/lparser.h +++ /dev/null @@ -1,119 +0,0 @@ -/* -** $Id: lparser.h,v 1.70.1.1 2013/04/12 18:48:47 roberto Exp $ -** Lua Parser -** See Copyright Notice in lua.h -*/ - -#ifndef lparser_h -#define lparser_h - -#include "llimits.h" -#include "lobject.h" -#include "lzio.h" - - -/* -** Expression descriptor -*/ - -typedef enum { - VVOID, /* no value */ - VNIL, - VTRUE, - VFALSE, - VK, /* info = index of constant in `k' */ - VKNUM, /* nval = numerical value */ - VNONRELOC, /* info = result register */ - VLOCAL, /* info = local register */ - VUPVAL, /* info = index of upvalue in 'upvalues' */ - VINDEXED, /* t = table register/upvalue; idx = index R/K */ - VJMP, /* info = instruction pc */ - VRELOCABLE, /* info = instruction pc */ - VCALL, /* info = instruction pc */ - VVARARG /* info = instruction pc */ -} expkind; - - -#define vkisvar(k) (VLOCAL <= (k) && (k) <= VINDEXED) -#define vkisinreg(k) ((k) == VNONRELOC || (k) == VLOCAL) - -typedef struct expdesc { - expkind k; - union { - struct { /* for indexed variables (VINDEXED) */ - short idx; /* index (R/K) */ - lu_byte t; /* table (register or upvalue) */ - lu_byte vt; /* whether 't' is register (VLOCAL) or upvalue (VUPVAL) */ - } ind; - int info; /* for generic use */ - lua_Number nval; /* for VKNUM */ - } u; - int t; /* patch list of `exit when true' */ - int f; /* patch list of `exit when false' */ -} expdesc; - - -/* description of active local variable */ -typedef struct Vardesc { - short idx; /* variable index in stack */ -} Vardesc; - - -/* description of pending goto statements and label statements */ -typedef struct Labeldesc { - TString *name; /* label identifier */ - int pc; /* position in code */ - int line; /* line where it appeared */ - lu_byte nactvar; /* local level where it appears in current block */ -} Labeldesc; - - -/* list of labels or gotos */ -typedef struct Labellist { - Labeldesc *arr; /* array */ - int n; /* number of entries in use */ - int size; /* array size */ -} Labellist; - - -/* dynamic structures used by the parser */ -typedef struct Dyndata { - struct { /* list of active local variables */ - Vardesc *arr; - int n; - int size; - } actvar; - Labellist gt; /* list of pending gotos */ - Labellist label; /* list of active labels */ -} Dyndata; - - -/* control of blocks */ -struct BlockCnt; /* defined in lparser.c */ - - -/* state needed to generate code for a given function */ -typedef struct FuncState { - Proto *f; /* current function header */ - Table *h; /* table to find (and reuse) elements in `k' */ - struct FuncState *prev; /* enclosing function */ - struct LexState *ls; /* lexical state */ - struct BlockCnt *bl; /* chain of current blocks */ - int pc; /* next position to code (equivalent to `ncode') */ - int lasttarget; /* 'label' of last 'jump label' */ - int jpc; /* list of pending jumps to `pc' */ - int nk; /* number of elements in `k' */ - int np; /* number of elements in `p' */ - int firstlocal; /* index of first local var (in Dyndata array) */ - short nlocvars; /* number of elements in 'f->locvars' */ - lu_byte nactvar; /* number of active local variables */ - lu_byte nups; /* number of upvalues */ - lu_byte freereg; /* first free register */ -} FuncState; - - -LUAI_FUNC Closure *luaY_parser (lua_State *L, ZIO *z, Mbuffer *buff, - Dyndata *dyd, const char *name, int firstchar); - - -#endif diff --git a/lib/lua-5.2/src/lstate.c b/lib/lua-5.2/src/lstate.c deleted file mode 100644 index c7f2672..0000000 --- a/lib/lua-5.2/src/lstate.c +++ /dev/null @@ -1,323 +0,0 @@ -/* -** $Id: lstate.c,v 2.99.1.2 2013/11/08 17:45:31 roberto Exp $ -** Global State -** See Copyright Notice in lua.h -*/ - - -#include -#include - -#define lstate_c -#define LUA_CORE - -#include "lua.h" - -#include "lapi.h" -#include "ldebug.h" -#include "ldo.h" -#include "lfunc.h" -#include "lgc.h" -#include "llex.h" -#include "lmem.h" -#include "lstate.h" -#include "lstring.h" -#include "ltable.h" -#include "ltm.h" - - -#if !defined(LUAI_GCPAUSE) -#define LUAI_GCPAUSE 200 /* 200% */ -#endif - -#if !defined(LUAI_GCMAJOR) -#define LUAI_GCMAJOR 200 /* 200% */ -#endif - -#if !defined(LUAI_GCMUL) -#define LUAI_GCMUL 200 /* GC runs 'twice the speed' of memory allocation */ -#endif - - -#define MEMERRMSG "not enough memory" - - -/* -** a macro to help the creation of a unique random seed when a state is -** created; the seed is used to randomize hashes. -*/ -#if !defined(luai_makeseed) -#include -#define luai_makeseed() cast(unsigned int, time(NULL)) -#endif - - - -/* -** thread state + extra space -*/ -typedef struct LX { -#if defined(LUAI_EXTRASPACE) - char buff[LUAI_EXTRASPACE]; -#endif - lua_State l; -} LX; - - -/* -** Main thread combines a thread state and the global state -*/ -typedef struct LG { - LX l; - global_State g; -} LG; - - - -#define fromstate(L) (cast(LX *, cast(lu_byte *, (L)) - offsetof(LX, l))) - - -/* -** Compute an initial seed as random as possible. In ANSI, rely on -** Address Space Layout Randomization (if present) to increase -** randomness.. -*/ -#define addbuff(b,p,e) \ - { size_t t = cast(size_t, e); \ - memcpy(buff + p, &t, sizeof(t)); p += sizeof(t); } - -static unsigned int makeseed (lua_State *L) { - char buff[4 * sizeof(size_t)]; - unsigned int h = luai_makeseed(); - int p = 0; - addbuff(buff, p, L); /* heap variable */ - addbuff(buff, p, &h); /* local variable */ - addbuff(buff, p, luaO_nilobject); /* global variable */ - addbuff(buff, p, &lua_newstate); /* public function */ - lua_assert(p == sizeof(buff)); - return luaS_hash(buff, p, h); -} - - -/* -** set GCdebt to a new value keeping the value (totalbytes + GCdebt) -** invariant -*/ -void luaE_setdebt (global_State *g, l_mem debt) { - g->totalbytes -= (debt - g->GCdebt); - g->GCdebt = debt; -} - - -CallInfo *luaE_extendCI (lua_State *L) { - CallInfo *ci = luaM_new(L, CallInfo); - lua_assert(L->ci->next == NULL); - L->ci->next = ci; - ci->previous = L->ci; - ci->next = NULL; - return ci; -} - - -void luaE_freeCI (lua_State *L) { - CallInfo *ci = L->ci; - CallInfo *next = ci->next; - ci->next = NULL; - while ((ci = next) != NULL) { - next = ci->next; - luaM_free(L, ci); - } -} - - -static void stack_init (lua_State *L1, lua_State *L) { - int i; CallInfo *ci; - /* initialize stack array */ - L1->stack = luaM_newvector(L, BASIC_STACK_SIZE, TValue); - L1->stacksize = BASIC_STACK_SIZE; - for (i = 0; i < BASIC_STACK_SIZE; i++) - setnilvalue(L1->stack + i); /* erase new stack */ - L1->top = L1->stack; - L1->stack_last = L1->stack + L1->stacksize - EXTRA_STACK; - /* initialize first ci */ - ci = &L1->base_ci; - ci->next = ci->previous = NULL; - ci->callstatus = 0; - ci->func = L1->top; - setnilvalue(L1->top++); /* 'function' entry for this 'ci' */ - ci->top = L1->top + LUA_MINSTACK; - L1->ci = ci; -} - - -static void freestack (lua_State *L) { - if (L->stack == NULL) - return; /* stack not completely built yet */ - L->ci = &L->base_ci; /* free the entire 'ci' list */ - luaE_freeCI(L); - luaM_freearray(L, L->stack, L->stacksize); /* free stack array */ -} - - -/* -** Create registry table and its predefined values -*/ -static void init_registry (lua_State *L, global_State *g) { - TValue mt; - /* create registry */ - Table *registry = luaH_new(L); - sethvalue(L, &g->l_registry, registry); - luaH_resize(L, registry, LUA_RIDX_LAST, 0); - /* registry[LUA_RIDX_MAINTHREAD] = L */ - setthvalue(L, &mt, L); - luaH_setint(L, registry, LUA_RIDX_MAINTHREAD, &mt); - /* registry[LUA_RIDX_GLOBALS] = table of globals */ - sethvalue(L, &mt, luaH_new(L)); - luaH_setint(L, registry, LUA_RIDX_GLOBALS, &mt); -} - - -/* -** open parts of the state that may cause memory-allocation errors -*/ -static void f_luaopen (lua_State *L, void *ud) { - global_State *g = G(L); - UNUSED(ud); - stack_init(L, L); /* init stack */ - init_registry(L, g); - luaS_resize(L, MINSTRTABSIZE); /* initial size of string table */ - luaT_init(L); - luaX_init(L); - /* pre-create memory-error message */ - g->memerrmsg = luaS_newliteral(L, MEMERRMSG); - luaS_fix(g->memerrmsg); /* it should never be collected */ - g->gcrunning = 1; /* allow gc */ - g->version = lua_version(NULL); - luai_userstateopen(L); -} - - -/* -** preinitialize a state with consistent values without allocating -** any memory (to avoid errors) -*/ -static void preinit_state (lua_State *L, global_State *g) { - G(L) = g; - L->stack = NULL; - L->ci = NULL; - L->stacksize = 0; - L->errorJmp = NULL; - L->nCcalls = 0; - L->hook = NULL; - L->hookmask = 0; - L->basehookcount = 0; - L->allowhook = 1; - resethookcount(L); - L->openupval = NULL; - L->nny = 1; - L->status = LUA_OK; - L->errfunc = 0; -} - - -static void close_state (lua_State *L) { - global_State *g = G(L); - luaF_close(L, L->stack); /* close all upvalues for this thread */ - luaC_freeallobjects(L); /* collect all objects */ - if (g->version) /* closing a fully built state? */ - luai_userstateclose(L); - luaM_freearray(L, G(L)->strt.hash, G(L)->strt.size); - luaZ_freebuffer(L, &g->buff); - freestack(L); - lua_assert(gettotalbytes(g) == sizeof(LG)); - (*g->frealloc)(g->ud, fromstate(L), sizeof(LG), 0); /* free main block */ -} - - -LUA_API lua_State *lua_newthread (lua_State *L) { - lua_State *L1; - lua_lock(L); - luaC_checkGC(L); - L1 = &luaC_newobj(L, LUA_TTHREAD, sizeof(LX), NULL, offsetof(LX, l))->th; - setthvalue(L, L->top, L1); - api_incr_top(L); - preinit_state(L1, G(L)); - L1->hookmask = L->hookmask; - L1->basehookcount = L->basehookcount; - L1->hook = L->hook; - resethookcount(L1); - luai_userstatethread(L, L1); - stack_init(L1, L); /* init stack */ - lua_unlock(L); - return L1; -} - - -void luaE_freethread (lua_State *L, lua_State *L1) { - LX *l = fromstate(L1); - luaF_close(L1, L1->stack); /* close all upvalues for this thread */ - lua_assert(L1->openupval == NULL); - luai_userstatefree(L, L1); - freestack(L1); - luaM_free(L, l); -} - - -LUA_API lua_State *lua_newstate (lua_Alloc f, void *ud) { - int i; - lua_State *L; - global_State *g; - LG *l = cast(LG *, (*f)(ud, NULL, LUA_TTHREAD, sizeof(LG))); - if (l == NULL) return NULL; - L = &l->l.l; - g = &l->g; - L->next = NULL; - L->tt = LUA_TTHREAD; - g->currentwhite = bit2mask(WHITE0BIT, FIXEDBIT); - L->marked = luaC_white(g); - g->gckind = KGC_NORMAL; - preinit_state(L, g); - g->frealloc = f; - g->ud = ud; - g->mainthread = L; - g->seed = makeseed(L); - g->uvhead.u.l.prev = &g->uvhead; - g->uvhead.u.l.next = &g->uvhead; - g->gcrunning = 0; /* no GC while building state */ - g->GCestimate = 0; - g->strt.size = 0; - g->strt.nuse = 0; - g->strt.hash = NULL; - setnilvalue(&g->l_registry); - luaZ_initbuffer(L, &g->buff); - g->panic = NULL; - g->version = NULL; - g->gcstate = GCSpause; - g->allgc = NULL; - g->finobj = NULL; - g->tobefnz = NULL; - g->sweepgc = g->sweepfin = NULL; - g->gray = g->grayagain = NULL; - g->weak = g->ephemeron = g->allweak = NULL; - g->totalbytes = sizeof(LG); - g->GCdebt = 0; - g->gcpause = LUAI_GCPAUSE; - g->gcmajorinc = LUAI_GCMAJOR; - g->gcstepmul = LUAI_GCMUL; - for (i=0; i < LUA_NUMTAGS; i++) g->mt[i] = NULL; - if (luaD_rawrunprotected(L, f_luaopen, NULL) != LUA_OK) { - /* memory allocation error: free partial state */ - close_state(L); - L = NULL; - } - return L; -} - - -LUA_API void lua_close (lua_State *L) { - L = G(L)->mainthread; /* only the main thread can be closed */ - lua_lock(L); - close_state(L); -} - - diff --git a/lib/lua-5.2/src/lstate.h b/lib/lua-5.2/src/lstate.h deleted file mode 100644 index daffd9a..0000000 --- a/lib/lua-5.2/src/lstate.h +++ /dev/null @@ -1,228 +0,0 @@ -/* -** $Id: lstate.h,v 2.82.1.1 2013/04/12 18:48:47 roberto Exp $ -** Global State -** See Copyright Notice in lua.h -*/ - -#ifndef lstate_h -#define lstate_h - -#include "lua.h" - -#include "lobject.h" -#include "ltm.h" -#include "lzio.h" - - -/* - -** Some notes about garbage-collected objects: All objects in Lua must -** be kept somehow accessible until being freed. -** -** Lua keeps most objects linked in list g->allgc. The link uses field -** 'next' of the CommonHeader. -** -** Strings are kept in several lists headed by the array g->strt.hash. -** -** Open upvalues are not subject to independent garbage collection. They -** are collected together with their respective threads. Lua keeps a -** double-linked list with all open upvalues (g->uvhead) so that it can -** mark objects referred by them. (They are always gray, so they must -** be remarked in the atomic step. Usually their contents would be marked -** when traversing the respective threads, but the thread may already be -** dead, while the upvalue is still accessible through closures.) -** -** Objects with finalizers are kept in the list g->finobj. -** -** The list g->tobefnz links all objects being finalized. - -*/ - - -struct lua_longjmp; /* defined in ldo.c */ - - - -/* extra stack space to handle TM calls and some other extras */ -#define EXTRA_STACK 5 - - -#define BASIC_STACK_SIZE (2*LUA_MINSTACK) - - -/* kinds of Garbage Collection */ -#define KGC_NORMAL 0 -#define KGC_EMERGENCY 1 /* gc was forced by an allocation failure */ -#define KGC_GEN 2 /* generational collection */ - - -typedef struct stringtable { - GCObject **hash; - lu_int32 nuse; /* number of elements */ - int size; -} stringtable; - - -/* -** information about a call -*/ -typedef struct CallInfo { - StkId func; /* function index in the stack */ - StkId top; /* top for this function */ - struct CallInfo *previous, *next; /* dynamic call link */ - short nresults; /* expected number of results from this function */ - lu_byte callstatus; - ptrdiff_t extra; - union { - struct { /* only for Lua functions */ - StkId base; /* base for this function */ - const Instruction *savedpc; - } l; - struct { /* only for C functions */ - int ctx; /* context info. in case of yields */ - lua_CFunction k; /* continuation in case of yields */ - ptrdiff_t old_errfunc; - lu_byte old_allowhook; - lu_byte status; - } c; - } u; -} CallInfo; - - -/* -** Bits in CallInfo status -*/ -#define CIST_LUA (1<<0) /* call is running a Lua function */ -#define CIST_HOOKED (1<<1) /* call is running a debug hook */ -#define CIST_REENTRY (1<<2) /* call is running on same invocation of - luaV_execute of previous call */ -#define CIST_YIELDED (1<<3) /* call reentered after suspension */ -#define CIST_YPCALL (1<<4) /* call is a yieldable protected call */ -#define CIST_STAT (1<<5) /* call has an error status (pcall) */ -#define CIST_TAIL (1<<6) /* call was tail called */ -#define CIST_HOOKYIELD (1<<7) /* last hook called yielded */ - - -#define isLua(ci) ((ci)->callstatus & CIST_LUA) - - -/* -** `global state', shared by all threads of this state -*/ -typedef struct global_State { - lua_Alloc frealloc; /* function to reallocate memory */ - void *ud; /* auxiliary data to `frealloc' */ - lu_mem totalbytes; /* number of bytes currently allocated - GCdebt */ - l_mem GCdebt; /* bytes allocated not yet compensated by the collector */ - lu_mem GCmemtrav; /* memory traversed by the GC */ - lu_mem GCestimate; /* an estimate of the non-garbage memory in use */ - stringtable strt; /* hash table for strings */ - TValue l_registry; - unsigned int seed; /* randomized seed for hashes */ - lu_byte currentwhite; - lu_byte gcstate; /* state of garbage collector */ - lu_byte gckind; /* kind of GC running */ - lu_byte gcrunning; /* true if GC is running */ - int sweepstrgc; /* position of sweep in `strt' */ - GCObject *allgc; /* list of all collectable objects */ - GCObject *finobj; /* list of collectable objects with finalizers */ - GCObject **sweepgc; /* current position of sweep in list 'allgc' */ - GCObject **sweepfin; /* current position of sweep in list 'finobj' */ - GCObject *gray; /* list of gray objects */ - GCObject *grayagain; /* list of objects to be traversed atomically */ - GCObject *weak; /* list of tables with weak values */ - GCObject *ephemeron; /* list of ephemeron tables (weak keys) */ - GCObject *allweak; /* list of all-weak tables */ - GCObject *tobefnz; /* list of userdata to be GC */ - UpVal uvhead; /* head of double-linked list of all open upvalues */ - Mbuffer buff; /* temporary buffer for string concatenation */ - int gcpause; /* size of pause between successive GCs */ - int gcmajorinc; /* pause between major collections (only in gen. mode) */ - int gcstepmul; /* GC `granularity' */ - lua_CFunction panic; /* to be called in unprotected errors */ - struct lua_State *mainthread; - const lua_Number *version; /* pointer to version number */ - TString *memerrmsg; /* memory-error message */ - TString *tmname[TM_N]; /* array with tag-method names */ - struct Table *mt[LUA_NUMTAGS]; /* metatables for basic types */ -} global_State; - - -/* -** `per thread' state -*/ -struct lua_State { - CommonHeader; - lu_byte status; - StkId top; /* first free slot in the stack */ - global_State *l_G; - CallInfo *ci; /* call info for current function */ - const Instruction *oldpc; /* last pc traced */ - StkId stack_last; /* last free slot in the stack */ - StkId stack; /* stack base */ - int stacksize; - unsigned short nny; /* number of non-yieldable calls in stack */ - unsigned short nCcalls; /* number of nested C calls */ - lu_byte hookmask; - lu_byte allowhook; - int basehookcount; - int hookcount; - lua_Hook hook; - GCObject *openupval; /* list of open upvalues in this stack */ - GCObject *gclist; - struct lua_longjmp *errorJmp; /* current error recover point */ - ptrdiff_t errfunc; /* current error handling function (stack index) */ - CallInfo base_ci; /* CallInfo for first level (C calling Lua) */ -}; - - -#define G(L) (L->l_G) - - -/* -** Union of all collectable objects -*/ -union GCObject { - GCheader gch; /* common header */ - union TString ts; - union Udata u; - union Closure cl; - struct Table h; - struct Proto p; - struct UpVal uv; - struct lua_State th; /* thread */ -}; - - -#define gch(o) (&(o)->gch) - -/* macros to convert a GCObject into a specific value */ -#define rawgco2ts(o) \ - check_exp(novariant((o)->gch.tt) == LUA_TSTRING, &((o)->ts)) -#define gco2ts(o) (&rawgco2ts(o)->tsv) -#define rawgco2u(o) check_exp((o)->gch.tt == LUA_TUSERDATA, &((o)->u)) -#define gco2u(o) (&rawgco2u(o)->uv) -#define gco2lcl(o) check_exp((o)->gch.tt == LUA_TLCL, &((o)->cl.l)) -#define gco2ccl(o) check_exp((o)->gch.tt == LUA_TCCL, &((o)->cl.c)) -#define gco2cl(o) \ - check_exp(novariant((o)->gch.tt) == LUA_TFUNCTION, &((o)->cl)) -#define gco2t(o) check_exp((o)->gch.tt == LUA_TTABLE, &((o)->h)) -#define gco2p(o) check_exp((o)->gch.tt == LUA_TPROTO, &((o)->p)) -#define gco2uv(o) check_exp((o)->gch.tt == LUA_TUPVAL, &((o)->uv)) -#define gco2th(o) check_exp((o)->gch.tt == LUA_TTHREAD, &((o)->th)) - -/* macro to convert any Lua object into a GCObject */ -#define obj2gco(v) (cast(GCObject *, (v))) - - -/* actual number of total bytes allocated */ -#define gettotalbytes(g) ((g)->totalbytes + (g)->GCdebt) - -LUAI_FUNC void luaE_setdebt (global_State *g, l_mem debt); -LUAI_FUNC void luaE_freethread (lua_State *L, lua_State *L1); -LUAI_FUNC CallInfo *luaE_extendCI (lua_State *L); -LUAI_FUNC void luaE_freeCI (lua_State *L); - - -#endif - diff --git a/lib/lua-5.2/src/lstring.c b/lib/lua-5.2/src/lstring.c deleted file mode 100644 index af96c89..0000000 --- a/lib/lua-5.2/src/lstring.c +++ /dev/null @@ -1,185 +0,0 @@ -/* -** $Id: lstring.c,v 2.26.1.1 2013/04/12 18:48:47 roberto Exp $ -** String table (keeps all strings handled by Lua) -** See Copyright Notice in lua.h -*/ - - -#include - -#define lstring_c -#define LUA_CORE - -#include "lua.h" - -#include "lmem.h" -#include "lobject.h" -#include "lstate.h" -#include "lstring.h" - - -/* -** Lua will use at most ~(2^LUAI_HASHLIMIT) bytes from a string to -** compute its hash -*/ -#if !defined(LUAI_HASHLIMIT) -#define LUAI_HASHLIMIT 5 -#endif - - -/* -** equality for long strings -*/ -int luaS_eqlngstr (TString *a, TString *b) { - size_t len = a->tsv.len; - lua_assert(a->tsv.tt == LUA_TLNGSTR && b->tsv.tt == LUA_TLNGSTR); - return (a == b) || /* same instance or... */ - ((len == b->tsv.len) && /* equal length and ... */ - (memcmp(getstr(a), getstr(b), len) == 0)); /* equal contents */ -} - - -/* -** equality for strings -*/ -int luaS_eqstr (TString *a, TString *b) { - return (a->tsv.tt == b->tsv.tt) && - (a->tsv.tt == LUA_TSHRSTR ? eqshrstr(a, b) : luaS_eqlngstr(a, b)); -} - - -unsigned int luaS_hash (const char *str, size_t l, unsigned int seed) { - unsigned int h = seed ^ cast(unsigned int, l); - size_t l1; - size_t step = (l >> LUAI_HASHLIMIT) + 1; - for (l1 = l; l1 >= step; l1 -= step) - h = h ^ ((h<<5) + (h>>2) + cast_byte(str[l1 - 1])); - return h; -} - - -/* -** resizes the string table -*/ -void luaS_resize (lua_State *L, int newsize) { - int i; - stringtable *tb = &G(L)->strt; - /* cannot resize while GC is traversing strings */ - luaC_runtilstate(L, ~bitmask(GCSsweepstring)); - if (newsize > tb->size) { - luaM_reallocvector(L, tb->hash, tb->size, newsize, GCObject *); - for (i = tb->size; i < newsize; i++) tb->hash[i] = NULL; - } - /* rehash */ - for (i=0; isize; i++) { - GCObject *p = tb->hash[i]; - tb->hash[i] = NULL; - while (p) { /* for each node in the list */ - GCObject *next = gch(p)->next; /* save next */ - unsigned int h = lmod(gco2ts(p)->hash, newsize); /* new position */ - gch(p)->next = tb->hash[h]; /* chain it */ - tb->hash[h] = p; - resetoldbit(p); /* see MOVE OLD rule */ - p = next; - } - } - if (newsize < tb->size) { - /* shrinking slice must be empty */ - lua_assert(tb->hash[newsize] == NULL && tb->hash[tb->size - 1] == NULL); - luaM_reallocvector(L, tb->hash, tb->size, newsize, GCObject *); - } - tb->size = newsize; -} - - -/* -** creates a new string object -*/ -static TString *createstrobj (lua_State *L, const char *str, size_t l, - int tag, unsigned int h, GCObject **list) { - TString *ts; - size_t totalsize; /* total size of TString object */ - totalsize = sizeof(TString) + ((l + 1) * sizeof(char)); - ts = &luaC_newobj(L, tag, totalsize, list, 0)->ts; - ts->tsv.len = l; - ts->tsv.hash = h; - ts->tsv.extra = 0; - memcpy(ts+1, str, l*sizeof(char)); - ((char *)(ts+1))[l] = '\0'; /* ending 0 */ - return ts; -} - - -/* -** creates a new short string, inserting it into string table -*/ -static TString *newshrstr (lua_State *L, const char *str, size_t l, - unsigned int h) { - GCObject **list; /* (pointer to) list where it will be inserted */ - stringtable *tb = &G(L)->strt; - TString *s; - if (tb->nuse >= cast(lu_int32, tb->size) && tb->size <= MAX_INT/2) - luaS_resize(L, tb->size*2); /* too crowded */ - list = &tb->hash[lmod(h, tb->size)]; - s = createstrobj(L, str, l, LUA_TSHRSTR, h, list); - tb->nuse++; - return s; -} - - -/* -** checks whether short string exists and reuses it or creates a new one -*/ -static TString *internshrstr (lua_State *L, const char *str, size_t l) { - GCObject *o; - global_State *g = G(L); - unsigned int h = luaS_hash(str, l, g->seed); - for (o = g->strt.hash[lmod(h, g->strt.size)]; - o != NULL; - o = gch(o)->next) { - TString *ts = rawgco2ts(o); - if (h == ts->tsv.hash && - l == ts->tsv.len && - (memcmp(str, getstr(ts), l * sizeof(char)) == 0)) { - if (isdead(G(L), o)) /* string is dead (but was not collected yet)? */ - changewhite(o); /* resurrect it */ - return ts; - } - } - return newshrstr(L, str, l, h); /* not found; create a new string */ -} - - -/* -** new string (with explicit length) -*/ -TString *luaS_newlstr (lua_State *L, const char *str, size_t l) { - if (l <= LUAI_MAXSHORTLEN) /* short string? */ - return internshrstr(L, str, l); - else { - if (l + 1 > (MAX_SIZET - sizeof(TString))/sizeof(char)) - luaM_toobig(L); - return createstrobj(L, str, l, LUA_TLNGSTR, G(L)->seed, NULL); - } -} - - -/* -** new zero-terminated string -*/ -TString *luaS_new (lua_State *L, const char *str) { - return luaS_newlstr(L, str, strlen(str)); -} - - -Udata *luaS_newudata (lua_State *L, size_t s, Table *e) { - Udata *u; - if (s > MAX_SIZET - sizeof(Udata)) - luaM_toobig(L); - u = &luaC_newobj(L, LUA_TUSERDATA, sizeof(Udata) + s, NULL, 0)->u; - u->uv.len = s; - u->uv.metatable = NULL; - u->uv.env = e; - return u; -} - diff --git a/lib/lua-5.2/src/lstring.h b/lib/lua-5.2/src/lstring.h deleted file mode 100644 index 260e7f1..0000000 --- a/lib/lua-5.2/src/lstring.h +++ /dev/null @@ -1,46 +0,0 @@ -/* -** $Id: lstring.h,v 1.49.1.1 2013/04/12 18:48:47 roberto Exp $ -** String table (keep all strings handled by Lua) -** See Copyright Notice in lua.h -*/ - -#ifndef lstring_h -#define lstring_h - -#include "lgc.h" -#include "lobject.h" -#include "lstate.h" - - -#define sizestring(s) (sizeof(union TString)+((s)->len+1)*sizeof(char)) - -#define sizeudata(u) (sizeof(union Udata)+(u)->len) - -#define luaS_newliteral(L, s) (luaS_newlstr(L, "" s, \ - (sizeof(s)/sizeof(char))-1)) - -#define luaS_fix(s) l_setbit((s)->tsv.marked, FIXEDBIT) - - -/* -** test whether a string is a reserved word -*/ -#define isreserved(s) ((s)->tsv.tt == LUA_TSHRSTR && (s)->tsv.extra > 0) - - -/* -** equality for short strings, which are always internalized -*/ -#define eqshrstr(a,b) check_exp((a)->tsv.tt == LUA_TSHRSTR, (a) == (b)) - - -LUAI_FUNC unsigned int luaS_hash (const char *str, size_t l, unsigned int seed); -LUAI_FUNC int luaS_eqlngstr (TString *a, TString *b); -LUAI_FUNC int luaS_eqstr (TString *a, TString *b); -LUAI_FUNC void luaS_resize (lua_State *L, int newsize); -LUAI_FUNC Udata *luaS_newudata (lua_State *L, size_t s, Table *e); -LUAI_FUNC TString *luaS_newlstr (lua_State *L, const char *str, size_t l); -LUAI_FUNC TString *luaS_new (lua_State *L, const char *str); - - -#endif diff --git a/lib/lua-5.2/src/lstrlib.c b/lib/lua-5.2/src/lstrlib.c deleted file mode 100644 index 9261fd2..0000000 --- a/lib/lua-5.2/src/lstrlib.c +++ /dev/null @@ -1,1019 +0,0 @@ -/* -** $Id: lstrlib.c,v 1.178.1.1 2013/04/12 18:48:47 roberto Exp $ -** Standard library for string operations and pattern-matching -** See Copyright Notice in lua.h -*/ - - -#include -#include -#include -#include -#include - -#define lstrlib_c -#define LUA_LIB - -#include "lua.h" - -#include "lauxlib.h" -#include "lualib.h" - - -/* -** maximum number of captures that a pattern can do during -** pattern-matching. This limit is arbitrary. -*/ -#if !defined(LUA_MAXCAPTURES) -#define LUA_MAXCAPTURES 32 -#endif - - -/* macro to `unsign' a character */ -#define uchar(c) ((unsigned char)(c)) - - - -static int str_len (lua_State *L) { - size_t l; - luaL_checklstring(L, 1, &l); - lua_pushinteger(L, (lua_Integer)l); - return 1; -} - - -/* translate a relative string position: negative means back from end */ -static size_t posrelat (ptrdiff_t pos, size_t len) { - if (pos >= 0) return (size_t)pos; - else if (0u - (size_t)pos > len) return 0; - else return len - ((size_t)-pos) + 1; -} - - -static int str_sub (lua_State *L) { - size_t l; - const char *s = luaL_checklstring(L, 1, &l); - size_t start = posrelat(luaL_checkinteger(L, 2), l); - size_t end = posrelat(luaL_optinteger(L, 3, -1), l); - if (start < 1) start = 1; - if (end > l) end = l; - if (start <= end) - lua_pushlstring(L, s + start - 1, end - start + 1); - else lua_pushliteral(L, ""); - return 1; -} - - -static int str_reverse (lua_State *L) { - size_t l, i; - luaL_Buffer b; - const char *s = luaL_checklstring(L, 1, &l); - char *p = luaL_buffinitsize(L, &b, l); - for (i = 0; i < l; i++) - p[i] = s[l - i - 1]; - luaL_pushresultsize(&b, l); - return 1; -} - - -static int str_lower (lua_State *L) { - size_t l; - size_t i; - luaL_Buffer b; - const char *s = luaL_checklstring(L, 1, &l); - char *p = luaL_buffinitsize(L, &b, l); - for (i=0; i> 1) - -static int str_rep (lua_State *L) { - size_t l, lsep; - const char *s = luaL_checklstring(L, 1, &l); - int n = luaL_checkint(L, 2); - const char *sep = luaL_optlstring(L, 3, "", &lsep); - if (n <= 0) lua_pushliteral(L, ""); - else if (l + lsep < l || l + lsep >= MAXSIZE / n) /* may overflow? */ - return luaL_error(L, "resulting string too large"); - else { - size_t totallen = n * l + (n - 1) * lsep; - luaL_Buffer b; - char *p = luaL_buffinitsize(L, &b, totallen); - while (n-- > 1) { /* first n-1 copies (followed by separator) */ - memcpy(p, s, l * sizeof(char)); p += l; - if (lsep > 0) { /* avoid empty 'memcpy' (may be expensive) */ - memcpy(p, sep, lsep * sizeof(char)); p += lsep; - } - } - memcpy(p, s, l * sizeof(char)); /* last copy (not followed by separator) */ - luaL_pushresultsize(&b, totallen); - } - return 1; -} - - -static int str_byte (lua_State *L) { - size_t l; - const char *s = luaL_checklstring(L, 1, &l); - size_t posi = posrelat(luaL_optinteger(L, 2, 1), l); - size_t pose = posrelat(luaL_optinteger(L, 3, posi), l); - int n, i; - if (posi < 1) posi = 1; - if (pose > l) pose = l; - if (posi > pose) return 0; /* empty interval; return no values */ - n = (int)(pose - posi + 1); - if (posi + n <= pose) /* (size_t -> int) overflow? */ - return luaL_error(L, "string slice too long"); - luaL_checkstack(L, n, "string slice too long"); - for (i=0; i= ms->level || ms->capture[l].len == CAP_UNFINISHED) - return luaL_error(ms->L, "invalid capture index %%%d", l + 1); - return l; -} - - -static int capture_to_close (MatchState *ms) { - int level = ms->level; - for (level--; level>=0; level--) - if (ms->capture[level].len == CAP_UNFINISHED) return level; - return luaL_error(ms->L, "invalid pattern capture"); -} - - -static const char *classend (MatchState *ms, const char *p) { - switch (*p++) { - case L_ESC: { - if (p == ms->p_end) - luaL_error(ms->L, "malformed pattern (ends with " LUA_QL("%%") ")"); - return p+1; - } - case '[': { - if (*p == '^') p++; - do { /* look for a `]' */ - if (p == ms->p_end) - luaL_error(ms->L, "malformed pattern (missing " LUA_QL("]") ")"); - if (*(p++) == L_ESC && p < ms->p_end) - p++; /* skip escapes (e.g. `%]') */ - } while (*p != ']'); - return p+1; - } - default: { - return p; - } - } -} - - -static int match_class (int c, int cl) { - int res; - switch (tolower(cl)) { - case 'a' : res = isalpha(c); break; - case 'c' : res = iscntrl(c); break; - case 'd' : res = isdigit(c); break; - case 'g' : res = isgraph(c); break; - case 'l' : res = islower(c); break; - case 'p' : res = ispunct(c); break; - case 's' : res = isspace(c); break; - case 'u' : res = isupper(c); break; - case 'w' : res = isalnum(c); break; - case 'x' : res = isxdigit(c); break; - case 'z' : res = (c == 0); break; /* deprecated option */ - default: return (cl == c); - } - return (islower(cl) ? res : !res); -} - - -static int matchbracketclass (int c, const char *p, const char *ec) { - int sig = 1; - if (*(p+1) == '^') { - sig = 0; - p++; /* skip the `^' */ - } - while (++p < ec) { - if (*p == L_ESC) { - p++; - if (match_class(c, uchar(*p))) - return sig; - } - else if ((*(p+1) == '-') && (p+2 < ec)) { - p+=2; - if (uchar(*(p-2)) <= c && c <= uchar(*p)) - return sig; - } - else if (uchar(*p) == c) return sig; - } - return !sig; -} - - -static int singlematch (MatchState *ms, const char *s, const char *p, - const char *ep) { - if (s >= ms->src_end) - return 0; - else { - int c = uchar(*s); - switch (*p) { - case '.': return 1; /* matches any char */ - case L_ESC: return match_class(c, uchar(*(p+1))); - case '[': return matchbracketclass(c, p, ep-1); - default: return (uchar(*p) == c); - } - } -} - - -static const char *matchbalance (MatchState *ms, const char *s, - const char *p) { - if (p >= ms->p_end - 1) - luaL_error(ms->L, "malformed pattern " - "(missing arguments to " LUA_QL("%%b") ")"); - if (*s != *p) return NULL; - else { - int b = *p; - int e = *(p+1); - int cont = 1; - while (++s < ms->src_end) { - if (*s == e) { - if (--cont == 0) return s+1; - } - else if (*s == b) cont++; - } - } - return NULL; /* string ends out of balance */ -} - - -static const char *max_expand (MatchState *ms, const char *s, - const char *p, const char *ep) { - ptrdiff_t i = 0; /* counts maximum expand for item */ - while (singlematch(ms, s + i, p, ep)) - i++; - /* keeps trying to match with the maximum repetitions */ - while (i>=0) { - const char *res = match(ms, (s+i), ep+1); - if (res) return res; - i--; /* else didn't match; reduce 1 repetition to try again */ - } - return NULL; -} - - -static const char *min_expand (MatchState *ms, const char *s, - const char *p, const char *ep) { - for (;;) { - const char *res = match(ms, s, ep+1); - if (res != NULL) - return res; - else if (singlematch(ms, s, p, ep)) - s++; /* try with one more repetition */ - else return NULL; - } -} - - -static const char *start_capture (MatchState *ms, const char *s, - const char *p, int what) { - const char *res; - int level = ms->level; - if (level >= LUA_MAXCAPTURES) luaL_error(ms->L, "too many captures"); - ms->capture[level].init = s; - ms->capture[level].len = what; - ms->level = level+1; - if ((res=match(ms, s, p)) == NULL) /* match failed? */ - ms->level--; /* undo capture */ - return res; -} - - -static const char *end_capture (MatchState *ms, const char *s, - const char *p) { - int l = capture_to_close(ms); - const char *res; - ms->capture[l].len = s - ms->capture[l].init; /* close capture */ - if ((res = match(ms, s, p)) == NULL) /* match failed? */ - ms->capture[l].len = CAP_UNFINISHED; /* undo capture */ - return res; -} - - -static const char *match_capture (MatchState *ms, const char *s, int l) { - size_t len; - l = check_capture(ms, l); - len = ms->capture[l].len; - if ((size_t)(ms->src_end-s) >= len && - memcmp(ms->capture[l].init, s, len) == 0) - return s+len; - else return NULL; -} - - -static const char *match (MatchState *ms, const char *s, const char *p) { - if (ms->matchdepth-- == 0) - luaL_error(ms->L, "pattern too complex"); - init: /* using goto's to optimize tail recursion */ - if (p != ms->p_end) { /* end of pattern? */ - switch (*p) { - case '(': { /* start capture */ - if (*(p + 1) == ')') /* position capture? */ - s = start_capture(ms, s, p + 2, CAP_POSITION); - else - s = start_capture(ms, s, p + 1, CAP_UNFINISHED); - break; - } - case ')': { /* end capture */ - s = end_capture(ms, s, p + 1); - break; - } - case '$': { - if ((p + 1) != ms->p_end) /* is the `$' the last char in pattern? */ - goto dflt; /* no; go to default */ - s = (s == ms->src_end) ? s : NULL; /* check end of string */ - break; - } - case L_ESC: { /* escaped sequences not in the format class[*+?-]? */ - switch (*(p + 1)) { - case 'b': { /* balanced string? */ - s = matchbalance(ms, s, p + 2); - if (s != NULL) { - p += 4; goto init; /* return match(ms, s, p + 4); */ - } /* else fail (s == NULL) */ - break; - } - case 'f': { /* frontier? */ - const char *ep; char previous; - p += 2; - if (*p != '[') - luaL_error(ms->L, "missing " LUA_QL("[") " after " - LUA_QL("%%f") " in pattern"); - ep = classend(ms, p); /* points to what is next */ - previous = (s == ms->src_init) ? '\0' : *(s - 1); - if (!matchbracketclass(uchar(previous), p, ep - 1) && - matchbracketclass(uchar(*s), p, ep - 1)) { - p = ep; goto init; /* return match(ms, s, ep); */ - } - s = NULL; /* match failed */ - break; - } - case '0': case '1': case '2': case '3': - case '4': case '5': case '6': case '7': - case '8': case '9': { /* capture results (%0-%9)? */ - s = match_capture(ms, s, uchar(*(p + 1))); - if (s != NULL) { - p += 2; goto init; /* return match(ms, s, p + 2) */ - } - break; - } - default: goto dflt; - } - break; - } - default: dflt: { /* pattern class plus optional suffix */ - const char *ep = classend(ms, p); /* points to optional suffix */ - /* does not match at least once? */ - if (!singlematch(ms, s, p, ep)) { - if (*ep == '*' || *ep == '?' || *ep == '-') { /* accept empty? */ - p = ep + 1; goto init; /* return match(ms, s, ep + 1); */ - } - else /* '+' or no suffix */ - s = NULL; /* fail */ - } - else { /* matched once */ - switch (*ep) { /* handle optional suffix */ - case '?': { /* optional */ - const char *res; - if ((res = match(ms, s + 1, ep + 1)) != NULL) - s = res; - else { - p = ep + 1; goto init; /* else return match(ms, s, ep + 1); */ - } - break; - } - case '+': /* 1 or more repetitions */ - s++; /* 1 match already done */ - /* go through */ - case '*': /* 0 or more repetitions */ - s = max_expand(ms, s, p, ep); - break; - case '-': /* 0 or more repetitions (minimum) */ - s = min_expand(ms, s, p, ep); - break; - default: /* no suffix */ - s++; p = ep; goto init; /* return match(ms, s + 1, ep); */ - } - } - break; - } - } - } - ms->matchdepth++; - return s; -} - - - -static const char *lmemfind (const char *s1, size_t l1, - const char *s2, size_t l2) { - if (l2 == 0) return s1; /* empty strings are everywhere */ - else if (l2 > l1) return NULL; /* avoids a negative `l1' */ - else { - const char *init; /* to search for a `*s2' inside `s1' */ - l2--; /* 1st char will be checked by `memchr' */ - l1 = l1-l2; /* `s2' cannot be found after that */ - while (l1 > 0 && (init = (const char *)memchr(s1, *s2, l1)) != NULL) { - init++; /* 1st char is already checked */ - if (memcmp(init, s2+1, l2) == 0) - return init-1; - else { /* correct `l1' and `s1' to try again */ - l1 -= init-s1; - s1 = init; - } - } - return NULL; /* not found */ - } -} - - -static void push_onecapture (MatchState *ms, int i, const char *s, - const char *e) { - if (i >= ms->level) { - if (i == 0) /* ms->level == 0, too */ - lua_pushlstring(ms->L, s, e - s); /* add whole match */ - else - luaL_error(ms->L, "invalid capture index"); - } - else { - ptrdiff_t l = ms->capture[i].len; - if (l == CAP_UNFINISHED) luaL_error(ms->L, "unfinished capture"); - if (l == CAP_POSITION) - lua_pushinteger(ms->L, ms->capture[i].init - ms->src_init + 1); - else - lua_pushlstring(ms->L, ms->capture[i].init, l); - } -} - - -static int push_captures (MatchState *ms, const char *s, const char *e) { - int i; - int nlevels = (ms->level == 0 && s) ? 1 : ms->level; - luaL_checkstack(ms->L, nlevels, "too many captures"); - for (i = 0; i < nlevels; i++) - push_onecapture(ms, i, s, e); - return nlevels; /* number of strings pushed */ -} - - -/* check whether pattern has no special characters */ -static int nospecials (const char *p, size_t l) { - size_t upto = 0; - do { - if (strpbrk(p + upto, SPECIALS)) - return 0; /* pattern has a special character */ - upto += strlen(p + upto) + 1; /* may have more after \0 */ - } while (upto <= l); - return 1; /* no special chars found */ -} - - -static int str_find_aux (lua_State *L, int find) { - size_t ls, lp; - const char *s = luaL_checklstring(L, 1, &ls); - const char *p = luaL_checklstring(L, 2, &lp); - size_t init = posrelat(luaL_optinteger(L, 3, 1), ls); - if (init < 1) init = 1; - else if (init > ls + 1) { /* start after string's end? */ - lua_pushnil(L); /* cannot find anything */ - return 1; - } - /* explicit request or no special characters? */ - if (find && (lua_toboolean(L, 4) || nospecials(p, lp))) { - /* do a plain search */ - const char *s2 = lmemfind(s + init - 1, ls - init + 1, p, lp); - if (s2) { - lua_pushinteger(L, s2 - s + 1); - lua_pushinteger(L, s2 - s + lp); - return 2; - } - } - else { - MatchState ms; - const char *s1 = s + init - 1; - int anchor = (*p == '^'); - if (anchor) { - p++; lp--; /* skip anchor character */ - } - ms.L = L; - ms.matchdepth = MAXCCALLS; - ms.src_init = s; - ms.src_end = s + ls; - ms.p_end = p + lp; - do { - const char *res; - ms.level = 0; - lua_assert(ms.matchdepth == MAXCCALLS); - if ((res=match(&ms, s1, p)) != NULL) { - if (find) { - lua_pushinteger(L, s1 - s + 1); /* start */ - lua_pushinteger(L, res - s); /* end */ - return push_captures(&ms, NULL, 0) + 2; - } - else - return push_captures(&ms, s1, res); - } - } while (s1++ < ms.src_end && !anchor); - } - lua_pushnil(L); /* not found */ - return 1; -} - - -static int str_find (lua_State *L) { - return str_find_aux(L, 1); -} - - -static int str_match (lua_State *L) { - return str_find_aux(L, 0); -} - - -static int gmatch_aux (lua_State *L) { - MatchState ms; - size_t ls, lp; - const char *s = lua_tolstring(L, lua_upvalueindex(1), &ls); - const char *p = lua_tolstring(L, lua_upvalueindex(2), &lp); - const char *src; - ms.L = L; - ms.matchdepth = MAXCCALLS; - ms.src_init = s; - ms.src_end = s+ls; - ms.p_end = p + lp; - for (src = s + (size_t)lua_tointeger(L, lua_upvalueindex(3)); - src <= ms.src_end; - src++) { - const char *e; - ms.level = 0; - lua_assert(ms.matchdepth == MAXCCALLS); - if ((e = match(&ms, src, p)) != NULL) { - lua_Integer newstart = e-s; - if (e == src) newstart++; /* empty match? go at least one position */ - lua_pushinteger(L, newstart); - lua_replace(L, lua_upvalueindex(3)); - return push_captures(&ms, src, e); - } - } - return 0; /* not found */ -} - - -static int gmatch (lua_State *L) { - luaL_checkstring(L, 1); - luaL_checkstring(L, 2); - lua_settop(L, 2); - lua_pushinteger(L, 0); - lua_pushcclosure(L, gmatch_aux, 3); - return 1; -} - - -static void add_s (MatchState *ms, luaL_Buffer *b, const char *s, - const char *e) { - size_t l, i; - const char *news = lua_tolstring(ms->L, 3, &l); - for (i = 0; i < l; i++) { - if (news[i] != L_ESC) - luaL_addchar(b, news[i]); - else { - i++; /* skip ESC */ - if (!isdigit(uchar(news[i]))) { - if (news[i] != L_ESC) - luaL_error(ms->L, "invalid use of " LUA_QL("%c") - " in replacement string", L_ESC); - luaL_addchar(b, news[i]); - } - else if (news[i] == '0') - luaL_addlstring(b, s, e - s); - else { - push_onecapture(ms, news[i] - '1', s, e); - luaL_addvalue(b); /* add capture to accumulated result */ - } - } - } -} - - -static void add_value (MatchState *ms, luaL_Buffer *b, const char *s, - const char *e, int tr) { - lua_State *L = ms->L; - switch (tr) { - case LUA_TFUNCTION: { - int n; - lua_pushvalue(L, 3); - n = push_captures(ms, s, e); - lua_call(L, n, 1); - break; - } - case LUA_TTABLE: { - push_onecapture(ms, 0, s, e); - lua_gettable(L, 3); - break; - } - default: { /* LUA_TNUMBER or LUA_TSTRING */ - add_s(ms, b, s, e); - return; - } - } - if (!lua_toboolean(L, -1)) { /* nil or false? */ - lua_pop(L, 1); - lua_pushlstring(L, s, e - s); /* keep original text */ - } - else if (!lua_isstring(L, -1)) - luaL_error(L, "invalid replacement value (a %s)", luaL_typename(L, -1)); - luaL_addvalue(b); /* add result to accumulator */ -} - - -static int str_gsub (lua_State *L) { - size_t srcl, lp; - const char *src = luaL_checklstring(L, 1, &srcl); - const char *p = luaL_checklstring(L, 2, &lp); - int tr = lua_type(L, 3); - size_t max_s = luaL_optinteger(L, 4, srcl+1); - int anchor = (*p == '^'); - size_t n = 0; - MatchState ms; - luaL_Buffer b; - luaL_argcheck(L, tr == LUA_TNUMBER || tr == LUA_TSTRING || - tr == LUA_TFUNCTION || tr == LUA_TTABLE, 3, - "string/function/table expected"); - luaL_buffinit(L, &b); - if (anchor) { - p++; lp--; /* skip anchor character */ - } - ms.L = L; - ms.matchdepth = MAXCCALLS; - ms.src_init = src; - ms.src_end = src+srcl; - ms.p_end = p + lp; - while (n < max_s) { - const char *e; - ms.level = 0; - lua_assert(ms.matchdepth == MAXCCALLS); - e = match(&ms, src, p); - if (e) { - n++; - add_value(&ms, &b, src, e, tr); - } - if (e && e>src) /* non empty match? */ - src = e; /* skip it */ - else if (src < ms.src_end) - luaL_addchar(&b, *src++); - else break; - if (anchor) break; - } - luaL_addlstring(&b, src, ms.src_end-src); - luaL_pushresult(&b); - lua_pushinteger(L, n); /* number of substitutions */ - return 2; -} - -/* }====================================================== */ - - - -/* -** {====================================================== -** STRING FORMAT -** ======================================================= -*/ - -/* -** LUA_INTFRMLEN is the length modifier for integer conversions in -** 'string.format'; LUA_INTFRM_T is the integer type corresponding to -** the previous length -*/ -#if !defined(LUA_INTFRMLEN) /* { */ -#if defined(LUA_USE_LONGLONG) - -#define LUA_INTFRMLEN "ll" -#define LUA_INTFRM_T long long - -#else - -#define LUA_INTFRMLEN "l" -#define LUA_INTFRM_T long - -#endif -#endif /* } */ - - -/* -** LUA_FLTFRMLEN is the length modifier for float conversions in -** 'string.format'; LUA_FLTFRM_T is the float type corresponding to -** the previous length -*/ -#if !defined(LUA_FLTFRMLEN) - -#define LUA_FLTFRMLEN "" -#define LUA_FLTFRM_T double - -#endif - - -/* maximum size of each formatted item (> len(format('%99.99f', -1e308))) */ -#define MAX_ITEM 512 -/* valid flags in a format specification */ -#define FLAGS "-+ #0" -/* -** maximum size of each format specification (such as '%-099.99d') -** (+10 accounts for %99.99x plus margin of error) -*/ -#define MAX_FORMAT (sizeof(FLAGS) + sizeof(LUA_INTFRMLEN) + 10) - - -static void addquoted (lua_State *L, luaL_Buffer *b, int arg) { - size_t l; - const char *s = luaL_checklstring(L, arg, &l); - luaL_addchar(b, '"'); - while (l--) { - if (*s == '"' || *s == '\\' || *s == '\n') { - luaL_addchar(b, '\\'); - luaL_addchar(b, *s); - } - else if (*s == '\0' || iscntrl(uchar(*s))) { - char buff[10]; - if (!isdigit(uchar(*(s+1)))) - sprintf(buff, "\\%d", (int)uchar(*s)); - else - sprintf(buff, "\\%03d", (int)uchar(*s)); - luaL_addstring(b, buff); - } - else - luaL_addchar(b, *s); - s++; - } - luaL_addchar(b, '"'); -} - -static const char *scanformat (lua_State *L, const char *strfrmt, char *form) { - const char *p = strfrmt; - while (*p != '\0' && strchr(FLAGS, *p) != NULL) p++; /* skip flags */ - if ((size_t)(p - strfrmt) >= sizeof(FLAGS)/sizeof(char)) - luaL_error(L, "invalid format (repeated flags)"); - if (isdigit(uchar(*p))) p++; /* skip width */ - if (isdigit(uchar(*p))) p++; /* (2 digits at most) */ - if (*p == '.') { - p++; - if (isdigit(uchar(*p))) p++; /* skip precision */ - if (isdigit(uchar(*p))) p++; /* (2 digits at most) */ - } - if (isdigit(uchar(*p))) - luaL_error(L, "invalid format (width or precision too long)"); - *(form++) = '%'; - memcpy(form, strfrmt, (p - strfrmt + 1) * sizeof(char)); - form += p - strfrmt + 1; - *form = '\0'; - return p; -} - - -/* -** add length modifier into formats -*/ -static void addlenmod (char *form, const char *lenmod) { - size_t l = strlen(form); - size_t lm = strlen(lenmod); - char spec = form[l - 1]; - strcpy(form + l - 1, lenmod); - form[l + lm - 1] = spec; - form[l + lm] = '\0'; -} - - -static int str_format (lua_State *L) { - int top = lua_gettop(L); - int arg = 1; - size_t sfl; - const char *strfrmt = luaL_checklstring(L, arg, &sfl); - const char *strfrmt_end = strfrmt+sfl; - luaL_Buffer b; - luaL_buffinit(L, &b); - while (strfrmt < strfrmt_end) { - if (*strfrmt != L_ESC) - luaL_addchar(&b, *strfrmt++); - else if (*++strfrmt == L_ESC) - luaL_addchar(&b, *strfrmt++); /* %% */ - else { /* format item */ - char form[MAX_FORMAT]; /* to store the format (`%...') */ - char *buff = luaL_prepbuffsize(&b, MAX_ITEM); /* to put formatted item */ - int nb = 0; /* number of bytes in added item */ - if (++arg > top) - luaL_argerror(L, arg, "no value"); - strfrmt = scanformat(L, strfrmt, form); - switch (*strfrmt++) { - case 'c': { - nb = sprintf(buff, form, luaL_checkint(L, arg)); - break; - } - case 'd': case 'i': { - lua_Number n = luaL_checknumber(L, arg); - LUA_INTFRM_T ni = (LUA_INTFRM_T)n; - lua_Number diff = n - (lua_Number)ni; - luaL_argcheck(L, -1 < diff && diff < 1, arg, - "not a number in proper range"); - addlenmod(form, LUA_INTFRMLEN); - nb = sprintf(buff, form, ni); - break; - } - case 'o': case 'u': case 'x': case 'X': { - lua_Number n = luaL_checknumber(L, arg); - unsigned LUA_INTFRM_T ni = (unsigned LUA_INTFRM_T)n; - lua_Number diff = n - (lua_Number)ni; - luaL_argcheck(L, -1 < diff && diff < 1, arg, - "not a non-negative number in proper range"); - addlenmod(form, LUA_INTFRMLEN); - nb = sprintf(buff, form, ni); - break; - } - case 'e': case 'E': case 'f': -#if defined(LUA_USE_AFORMAT) - case 'a': case 'A': -#endif - case 'g': case 'G': { - addlenmod(form, LUA_FLTFRMLEN); - nb = sprintf(buff, form, (LUA_FLTFRM_T)luaL_checknumber(L, arg)); - break; - } - case 'q': { - addquoted(L, &b, arg); - break; - } - case 's': { - size_t l; - const char *s = luaL_tolstring(L, arg, &l); - if (!strchr(form, '.') && l >= 100) { - /* no precision and string is too long to be formatted; - keep original string */ - luaL_addvalue(&b); - break; - } - else { - nb = sprintf(buff, form, s); - lua_pop(L, 1); /* remove result from 'luaL_tolstring' */ - break; - } - } - default: { /* also treat cases `pnLlh' */ - return luaL_error(L, "invalid option " LUA_QL("%%%c") " to " - LUA_QL("format"), *(strfrmt - 1)); - } - } - luaL_addsize(&b, nb); - } - } - luaL_pushresult(&b); - return 1; -} - -/* }====================================================== */ - - -static const luaL_Reg strlib[] = { - {"byte", str_byte}, - {"char", str_char}, - {"dump", str_dump}, - {"find", str_find}, - {"format", str_format}, - {"gmatch", gmatch}, - {"gsub", str_gsub}, - {"len", str_len}, - {"lower", str_lower}, - {"match", str_match}, - {"rep", str_rep}, - {"reverse", str_reverse}, - {"sub", str_sub}, - {"upper", str_upper}, - {NULL, NULL} -}; - - -static void createmetatable (lua_State *L) { - lua_createtable(L, 0, 1); /* table to be metatable for strings */ - lua_pushliteral(L, ""); /* dummy string */ - lua_pushvalue(L, -2); /* copy table */ - lua_setmetatable(L, -2); /* set table as metatable for strings */ - lua_pop(L, 1); /* pop dummy string */ - lua_pushvalue(L, -2); /* get string library */ - lua_setfield(L, -2, "__index"); /* metatable.__index = string */ - lua_pop(L, 1); /* pop metatable */ -} - - -/* -** Open string library -*/ -LUAMOD_API int luaopen_string (lua_State *L) { - luaL_newlib(L, strlib); - createmetatable(L); - return 1; -} - diff --git a/lib/lua-5.2/src/ltable.c b/lib/lua-5.2/src/ltable.c deleted file mode 100644 index 5d76f97..0000000 --- a/lib/lua-5.2/src/ltable.c +++ /dev/null @@ -1,588 +0,0 @@ -/* -** $Id: ltable.c,v 2.72.1.1 2013/04/12 18:48:47 roberto Exp $ -** Lua tables (hash) -** See Copyright Notice in lua.h -*/ - - -/* -** Implementation of tables (aka arrays, objects, or hash tables). -** Tables keep its elements in two parts: an array part and a hash part. -** Non-negative integer keys are all candidates to be kept in the array -** part. The actual size of the array is the largest `n' such that at -** least half the slots between 0 and n are in use. -** Hash uses a mix of chained scatter table with Brent's variation. -** A main invariant of these tables is that, if an element is not -** in its main position (i.e. the `original' position that its hash gives -** to it), then the colliding element is in its own main position. -** Hence even when the load factor reaches 100%, performance remains good. -*/ - -#include - -#define ltable_c -#define LUA_CORE - -#include "lua.h" - -#include "ldebug.h" -#include "ldo.h" -#include "lgc.h" -#include "lmem.h" -#include "lobject.h" -#include "lstate.h" -#include "lstring.h" -#include "ltable.h" -#include "lvm.h" - - -/* -** max size of array part is 2^MAXBITS -*/ -#if LUAI_BITSINT >= 32 -#define MAXBITS 30 -#else -#define MAXBITS (LUAI_BITSINT-2) -#endif - -#define MAXASIZE (1 << MAXBITS) - - -#define hashpow2(t,n) (gnode(t, lmod((n), sizenode(t)))) - -#define hashstr(t,str) hashpow2(t, (str)->tsv.hash) -#define hashboolean(t,p) hashpow2(t, p) - - -/* -** for some types, it is better to avoid modulus by power of 2, as -** they tend to have many 2 factors. -*/ -#define hashmod(t,n) (gnode(t, ((n) % ((sizenode(t)-1)|1)))) - - -#define hashpointer(t,p) hashmod(t, IntPoint(p)) - - -#define dummynode (&dummynode_) - -#define isdummy(n) ((n) == dummynode) - -static const Node dummynode_ = { - {NILCONSTANT}, /* value */ - {{NILCONSTANT, NULL}} /* key */ -}; - - -/* -** hash for lua_Numbers -*/ -static Node *hashnum (const Table *t, lua_Number n) { - int i; - luai_hashnum(i, n); - if (i < 0) { - if (cast(unsigned int, i) == 0u - i) /* use unsigned to avoid overflows */ - i = 0; /* handle INT_MIN */ - i = -i; /* must be a positive value */ - } - return hashmod(t, i); -} - - - -/* -** returns the `main' position of an element in a table (that is, the index -** of its hash value) -*/ -static Node *mainposition (const Table *t, const TValue *key) { - switch (ttype(key)) { - case LUA_TNUMBER: - return hashnum(t, nvalue(key)); - case LUA_TLNGSTR: { - TString *s = rawtsvalue(key); - if (s->tsv.extra == 0) { /* no hash? */ - s->tsv.hash = luaS_hash(getstr(s), s->tsv.len, s->tsv.hash); - s->tsv.extra = 1; /* now it has its hash */ - } - return hashstr(t, rawtsvalue(key)); - } - case LUA_TSHRSTR: - return hashstr(t, rawtsvalue(key)); - case LUA_TBOOLEAN: - return hashboolean(t, bvalue(key)); - case LUA_TLIGHTUSERDATA: - return hashpointer(t, pvalue(key)); - case LUA_TLCF: - return hashpointer(t, fvalue(key)); - default: - return hashpointer(t, gcvalue(key)); - } -} - - -/* -** returns the index for `key' if `key' is an appropriate key to live in -** the array part of the table, -1 otherwise. -*/ -static int arrayindex (const TValue *key) { - if (ttisnumber(key)) { - lua_Number n = nvalue(key); - int k; - lua_number2int(k, n); - if (luai_numeq(cast_num(k), n)) - return k; - } - return -1; /* `key' did not match some condition */ -} - - -/* -** returns the index of a `key' for table traversals. First goes all -** elements in the array part, then elements in the hash part. The -** beginning of a traversal is signaled by -1. -*/ -static int findindex (lua_State *L, Table *t, StkId key) { - int i; - if (ttisnil(key)) return -1; /* first iteration */ - i = arrayindex(key); - if (0 < i && i <= t->sizearray) /* is `key' inside array part? */ - return i-1; /* yes; that's the index (corrected to C) */ - else { - Node *n = mainposition(t, key); - for (;;) { /* check whether `key' is somewhere in the chain */ - /* key may be dead already, but it is ok to use it in `next' */ - if (luaV_rawequalobj(gkey(n), key) || - (ttisdeadkey(gkey(n)) && iscollectable(key) && - deadvalue(gkey(n)) == gcvalue(key))) { - i = cast_int(n - gnode(t, 0)); /* key index in hash table */ - /* hash elements are numbered after array ones */ - return i + t->sizearray; - } - else n = gnext(n); - if (n == NULL) - luaG_runerror(L, "invalid key to " LUA_QL("next")); /* key not found */ - } - } -} - - -int luaH_next (lua_State *L, Table *t, StkId key) { - int i = findindex(L, t, key); /* find original element */ - for (i++; i < t->sizearray; i++) { /* try first array part */ - if (!ttisnil(&t->array[i])) { /* a non-nil value? */ - setnvalue(key, cast_num(i+1)); - setobj2s(L, key+1, &t->array[i]); - return 1; - } - } - for (i -= t->sizearray; i < sizenode(t); i++) { /* then hash part */ - if (!ttisnil(gval(gnode(t, i)))) { /* a non-nil value? */ - setobj2s(L, key, gkey(gnode(t, i))); - setobj2s(L, key+1, gval(gnode(t, i))); - return 1; - } - } - return 0; /* no more elements */ -} - - -/* -** {============================================================= -** Rehash -** ============================================================== -*/ - - -static int computesizes (int nums[], int *narray) { - int i; - int twotoi; /* 2^i */ - int a = 0; /* number of elements smaller than 2^i */ - int na = 0; /* number of elements to go to array part */ - int n = 0; /* optimal size for array part */ - for (i = 0, twotoi = 1; twotoi/2 < *narray; i++, twotoi *= 2) { - if (nums[i] > 0) { - a += nums[i]; - if (a > twotoi/2) { /* more than half elements present? */ - n = twotoi; /* optimal size (till now) */ - na = a; /* all elements smaller than n will go to array part */ - } - } - if (a == *narray) break; /* all elements already counted */ - } - *narray = n; - lua_assert(*narray/2 <= na && na <= *narray); - return na; -} - - -static int countint (const TValue *key, int *nums) { - int k = arrayindex(key); - if (0 < k && k <= MAXASIZE) { /* is `key' an appropriate array index? */ - nums[luaO_ceillog2(k)]++; /* count as such */ - return 1; - } - else - return 0; -} - - -static int numusearray (const Table *t, int *nums) { - int lg; - int ttlg; /* 2^lg */ - int ause = 0; /* summation of `nums' */ - int i = 1; /* count to traverse all array keys */ - for (lg=0, ttlg=1; lg<=MAXBITS; lg++, ttlg*=2) { /* for each slice */ - int lc = 0; /* counter */ - int lim = ttlg; - if (lim > t->sizearray) { - lim = t->sizearray; /* adjust upper limit */ - if (i > lim) - break; /* no more elements to count */ - } - /* count elements in range (2^(lg-1), 2^lg] */ - for (; i <= lim; i++) { - if (!ttisnil(&t->array[i-1])) - lc++; - } - nums[lg] += lc; - ause += lc; - } - return ause; -} - - -static int numusehash (const Table *t, int *nums, int *pnasize) { - int totaluse = 0; /* total number of elements */ - int ause = 0; /* summation of `nums' */ - int i = sizenode(t); - while (i--) { - Node *n = &t->node[i]; - if (!ttisnil(gval(n))) { - ause += countint(gkey(n), nums); - totaluse++; - } - } - *pnasize += ause; - return totaluse; -} - - -static void setarrayvector (lua_State *L, Table *t, int size) { - int i; - luaM_reallocvector(L, t->array, t->sizearray, size, TValue); - for (i=t->sizearray; iarray[i]); - t->sizearray = size; -} - - -static void setnodevector (lua_State *L, Table *t, int size) { - int lsize; - if (size == 0) { /* no elements to hash part? */ - t->node = cast(Node *, dummynode); /* use common `dummynode' */ - lsize = 0; - } - else { - int i; - lsize = luaO_ceillog2(size); - if (lsize > MAXBITS) - luaG_runerror(L, "table overflow"); - size = twoto(lsize); - t->node = luaM_newvector(L, size, Node); - for (i=0; ilsizenode = cast_byte(lsize); - t->lastfree = gnode(t, size); /* all positions are free */ -} - - -void luaH_resize (lua_State *L, Table *t, int nasize, int nhsize) { - int i; - int oldasize = t->sizearray; - int oldhsize = t->lsizenode; - Node *nold = t->node; /* save old hash ... */ - if (nasize > oldasize) /* array part must grow? */ - setarrayvector(L, t, nasize); - /* create new hash part with appropriate size */ - setnodevector(L, t, nhsize); - if (nasize < oldasize) { /* array part must shrink? */ - t->sizearray = nasize; - /* re-insert elements from vanishing slice */ - for (i=nasize; iarray[i])) - luaH_setint(L, t, i + 1, &t->array[i]); - } - /* shrink array */ - luaM_reallocvector(L, t->array, oldasize, nasize, TValue); - } - /* re-insert elements from hash part */ - for (i = twoto(oldhsize) - 1; i >= 0; i--) { - Node *old = nold+i; - if (!ttisnil(gval(old))) { - /* doesn't need barrier/invalidate cache, as entry was - already present in the table */ - setobjt2t(L, luaH_set(L, t, gkey(old)), gval(old)); - } - } - if (!isdummy(nold)) - luaM_freearray(L, nold, cast(size_t, twoto(oldhsize))); /* free old array */ -} - - -void luaH_resizearray (lua_State *L, Table *t, int nasize) { - int nsize = isdummy(t->node) ? 0 : sizenode(t); - luaH_resize(L, t, nasize, nsize); -} - - -static void rehash (lua_State *L, Table *t, const TValue *ek) { - int nasize, na; - int nums[MAXBITS+1]; /* nums[i] = number of keys with 2^(i-1) < k <= 2^i */ - int i; - int totaluse; - for (i=0; i<=MAXBITS; i++) nums[i] = 0; /* reset counts */ - nasize = numusearray(t, nums); /* count keys in array part */ - totaluse = nasize; /* all those keys are integer keys */ - totaluse += numusehash(t, nums, &nasize); /* count keys in hash part */ - /* count extra key */ - nasize += countint(ek, nums); - totaluse++; - /* compute new size for array part */ - na = computesizes(nums, &nasize); - /* resize the table to new computed sizes */ - luaH_resize(L, t, nasize, totaluse - na); -} - - - -/* -** }============================================================= -*/ - - -Table *luaH_new (lua_State *L) { - Table *t = &luaC_newobj(L, LUA_TTABLE, sizeof(Table), NULL, 0)->h; - t->metatable = NULL; - t->flags = cast_byte(~0); - t->array = NULL; - t->sizearray = 0; - setnodevector(L, t, 0); - return t; -} - - -void luaH_free (lua_State *L, Table *t) { - if (!isdummy(t->node)) - luaM_freearray(L, t->node, cast(size_t, sizenode(t))); - luaM_freearray(L, t->array, t->sizearray); - luaM_free(L, t); -} - - -static Node *getfreepos (Table *t) { - while (t->lastfree > t->node) { - t->lastfree--; - if (ttisnil(gkey(t->lastfree))) - return t->lastfree; - } - return NULL; /* could not find a free place */ -} - - - -/* -** inserts a new key into a hash table; first, check whether key's main -** position is free. If not, check whether colliding node is in its main -** position or not: if it is not, move colliding node to an empty place and -** put new key in its main position; otherwise (colliding node is in its main -** position), new key goes to an empty position. -*/ -TValue *luaH_newkey (lua_State *L, Table *t, const TValue *key) { - Node *mp; - if (ttisnil(key)) luaG_runerror(L, "table index is nil"); - else if (ttisnumber(key) && luai_numisnan(L, nvalue(key))) - luaG_runerror(L, "table index is NaN"); - mp = mainposition(t, key); - if (!ttisnil(gval(mp)) || isdummy(mp)) { /* main position is taken? */ - Node *othern; - Node *n = getfreepos(t); /* get a free place */ - if (n == NULL) { /* cannot find a free place? */ - rehash(L, t, key); /* grow table */ - /* whatever called 'newkey' take care of TM cache and GC barrier */ - return luaH_set(L, t, key); /* insert key into grown table */ - } - lua_assert(!isdummy(n)); - othern = mainposition(t, gkey(mp)); - if (othern != mp) { /* is colliding node out of its main position? */ - /* yes; move colliding node into free position */ - while (gnext(othern) != mp) othern = gnext(othern); /* find previous */ - gnext(othern) = n; /* redo the chain with `n' in place of `mp' */ - *n = *mp; /* copy colliding node into free pos. (mp->next also goes) */ - gnext(mp) = NULL; /* now `mp' is free */ - setnilvalue(gval(mp)); - } - else { /* colliding node is in its own main position */ - /* new node will go into free position */ - gnext(n) = gnext(mp); /* chain new position */ - gnext(mp) = n; - mp = n; - } - } - setobj2t(L, gkey(mp), key); - luaC_barrierback(L, obj2gco(t), key); - lua_assert(ttisnil(gval(mp))); - return gval(mp); -} - - -/* -** search function for integers -*/ -const TValue *luaH_getint (Table *t, int key) { - /* (1 <= key && key <= t->sizearray) */ - if (cast(unsigned int, key-1) < cast(unsigned int, t->sizearray)) - return &t->array[key-1]; - else { - lua_Number nk = cast_num(key); - Node *n = hashnum(t, nk); - do { /* check whether `key' is somewhere in the chain */ - if (ttisnumber(gkey(n)) && luai_numeq(nvalue(gkey(n)), nk)) - return gval(n); /* that's it */ - else n = gnext(n); - } while (n); - return luaO_nilobject; - } -} - - -/* -** search function for short strings -*/ -const TValue *luaH_getstr (Table *t, TString *key) { - Node *n = hashstr(t, key); - lua_assert(key->tsv.tt == LUA_TSHRSTR); - do { /* check whether `key' is somewhere in the chain */ - if (ttisshrstring(gkey(n)) && eqshrstr(rawtsvalue(gkey(n)), key)) - return gval(n); /* that's it */ - else n = gnext(n); - } while (n); - return luaO_nilobject; -} - - -/* -** main search function -*/ -const TValue *luaH_get (Table *t, const TValue *key) { - switch (ttype(key)) { - case LUA_TSHRSTR: return luaH_getstr(t, rawtsvalue(key)); - case LUA_TNIL: return luaO_nilobject; - case LUA_TNUMBER: { - int k; - lua_Number n = nvalue(key); - lua_number2int(k, n); - if (luai_numeq(cast_num(k), n)) /* index is int? */ - return luaH_getint(t, k); /* use specialized version */ - /* else go through */ - } - default: { - Node *n = mainposition(t, key); - do { /* check whether `key' is somewhere in the chain */ - if (luaV_rawequalobj(gkey(n), key)) - return gval(n); /* that's it */ - else n = gnext(n); - } while (n); - return luaO_nilobject; - } - } -} - - -/* -** beware: when using this function you probably need to check a GC -** barrier and invalidate the TM cache. -*/ -TValue *luaH_set (lua_State *L, Table *t, const TValue *key) { - const TValue *p = luaH_get(t, key); - if (p != luaO_nilobject) - return cast(TValue *, p); - else return luaH_newkey(L, t, key); -} - - -void luaH_setint (lua_State *L, Table *t, int key, TValue *value) { - const TValue *p = luaH_getint(t, key); - TValue *cell; - if (p != luaO_nilobject) - cell = cast(TValue *, p); - else { - TValue k; - setnvalue(&k, cast_num(key)); - cell = luaH_newkey(L, t, &k); - } - setobj2t(L, cell, value); -} - - -static int unbound_search (Table *t, unsigned int j) { - unsigned int i = j; /* i is zero or a present index */ - j++; - /* find `i' and `j' such that i is present and j is not */ - while (!ttisnil(luaH_getint(t, j))) { - i = j; - j *= 2; - if (j > cast(unsigned int, MAX_INT)) { /* overflow? */ - /* table was built with bad purposes: resort to linear search */ - i = 1; - while (!ttisnil(luaH_getint(t, i))) i++; - return i - 1; - } - } - /* now do a binary search between them */ - while (j - i > 1) { - unsigned int m = (i+j)/2; - if (ttisnil(luaH_getint(t, m))) j = m; - else i = m; - } - return i; -} - - -/* -** Try to find a boundary in table `t'. A `boundary' is an integer index -** such that t[i] is non-nil and t[i+1] is nil (and 0 if t[1] is nil). -*/ -int luaH_getn (Table *t) { - unsigned int j = t->sizearray; - if (j > 0 && ttisnil(&t->array[j - 1])) { - /* there is a boundary in the array part: (binary) search for it */ - unsigned int i = 0; - while (j - i > 1) { - unsigned int m = (i+j)/2; - if (ttisnil(&t->array[m - 1])) j = m; - else i = m; - } - return i; - } - /* else must find a boundary in hash part */ - else if (isdummy(t->node)) /* hash part is empty? */ - return j; /* that is easy... */ - else return unbound_search(t, j); -} - - - -#if defined(LUA_DEBUG) - -Node *luaH_mainposition (const Table *t, const TValue *key) { - return mainposition(t, key); -} - -int luaH_isdummy (Node *n) { return isdummy(n); } - -#endif diff --git a/lib/lua-5.2/src/ltable.h b/lib/lua-5.2/src/ltable.h deleted file mode 100644 index d69449b..0000000 --- a/lib/lua-5.2/src/ltable.h +++ /dev/null @@ -1,45 +0,0 @@ -/* -** $Id: ltable.h,v 2.16.1.2 2013/08/30 15:49:41 roberto Exp $ -** Lua tables (hash) -** See Copyright Notice in lua.h -*/ - -#ifndef ltable_h -#define ltable_h - -#include "lobject.h" - - -#define gnode(t,i) (&(t)->node[i]) -#define gkey(n) (&(n)->i_key.tvk) -#define gval(n) (&(n)->i_val) -#define gnext(n) ((n)->i_key.nk.next) - -#define invalidateTMcache(t) ((t)->flags = 0) - -/* returns the key, given the value of a table entry */ -#define keyfromval(v) \ - (gkey(cast(Node *, cast(char *, (v)) - offsetof(Node, i_val)))) - - -LUAI_FUNC const TValue *luaH_getint (Table *t, int key); -LUAI_FUNC void luaH_setint (lua_State *L, Table *t, int key, TValue *value); -LUAI_FUNC const TValue *luaH_getstr (Table *t, TString *key); -LUAI_FUNC const TValue *luaH_get (Table *t, const TValue *key); -LUAI_FUNC TValue *luaH_newkey (lua_State *L, Table *t, const TValue *key); -LUAI_FUNC TValue *luaH_set (lua_State *L, Table *t, const TValue *key); -LUAI_FUNC Table *luaH_new (lua_State *L); -LUAI_FUNC void luaH_resize (lua_State *L, Table *t, int nasize, int nhsize); -LUAI_FUNC void luaH_resizearray (lua_State *L, Table *t, int nasize); -LUAI_FUNC void luaH_free (lua_State *L, Table *t); -LUAI_FUNC int luaH_next (lua_State *L, Table *t, StkId key); -LUAI_FUNC int luaH_getn (Table *t); - - -#if defined(LUA_DEBUG) -LUAI_FUNC Node *luaH_mainposition (const Table *t, const TValue *key); -LUAI_FUNC int luaH_isdummy (Node *n); -#endif - - -#endif diff --git a/lib/lua-5.2/src/ltablib.c b/lib/lua-5.2/src/ltablib.c deleted file mode 100644 index 99764d2..0000000 --- a/lib/lua-5.2/src/ltablib.c +++ /dev/null @@ -1,285 +0,0 @@ -/* -** $Id: ltablib.c,v 1.65.1.2 2014/05/07 16:32:55 roberto Exp $ -** Library for Table Manipulation -** See Copyright Notice in lua.h -*/ - - -#include -#include - -#define ltablib_c -#define LUA_LIB - -#include "lua.h" - -#include "lauxlib.h" -#include "lualib.h" - - -#define aux_getn(L,n) (luaL_checktype(L, n, LUA_TTABLE), luaL_len(L, n)) - - - -#if defined(LUA_COMPAT_MAXN) -static int maxn (lua_State *L) { - lua_Number max = 0; - luaL_checktype(L, 1, LUA_TTABLE); - lua_pushnil(L); /* first key */ - while (lua_next(L, 1)) { - lua_pop(L, 1); /* remove value */ - if (lua_type(L, -1) == LUA_TNUMBER) { - lua_Number v = lua_tonumber(L, -1); - if (v > max) max = v; - } - } - lua_pushnumber(L, max); - return 1; -} -#endif - - -static int tinsert (lua_State *L) { - int e = aux_getn(L, 1) + 1; /* first empty element */ - int pos; /* where to insert new element */ - switch (lua_gettop(L)) { - case 2: { /* called with only 2 arguments */ - pos = e; /* insert new element at the end */ - break; - } - case 3: { - int i; - pos = luaL_checkint(L, 2); /* 2nd argument is the position */ - luaL_argcheck(L, 1 <= pos && pos <= e, 2, "position out of bounds"); - for (i = e; i > pos; i--) { /* move up elements */ - lua_rawgeti(L, 1, i-1); - lua_rawseti(L, 1, i); /* t[i] = t[i-1] */ - } - break; - } - default: { - return luaL_error(L, "wrong number of arguments to " LUA_QL("insert")); - } - } - lua_rawseti(L, 1, pos); /* t[pos] = v */ - return 0; -} - - -static int tremove (lua_State *L) { - int size = aux_getn(L, 1); - int pos = luaL_optint(L, 2, size); - if (pos != size) /* validate 'pos' if given */ - luaL_argcheck(L, 1 <= pos && pos <= size + 1, 1, "position out of bounds"); - lua_rawgeti(L, 1, pos); /* result = t[pos] */ - for ( ; pos < size; pos++) { - lua_rawgeti(L, 1, pos+1); - lua_rawseti(L, 1, pos); /* t[pos] = t[pos+1] */ - } - lua_pushnil(L); - lua_rawseti(L, 1, pos); /* t[pos] = nil */ - return 1; -} - - -static void addfield (lua_State *L, luaL_Buffer *b, int i) { - lua_rawgeti(L, 1, i); - if (!lua_isstring(L, -1)) - luaL_error(L, "invalid value (%s) at index %d in table for " - LUA_QL("concat"), luaL_typename(L, -1), i); - luaL_addvalue(b); -} - - -static int tconcat (lua_State *L) { - luaL_Buffer b; - size_t lsep; - int i, last; - const char *sep = luaL_optlstring(L, 2, "", &lsep); - luaL_checktype(L, 1, LUA_TTABLE); - i = luaL_optint(L, 3, 1); - last = luaL_opt(L, luaL_checkint, 4, luaL_len(L, 1)); - luaL_buffinit(L, &b); - for (; i < last; i++) { - addfield(L, &b, i); - luaL_addlstring(&b, sep, lsep); - } - if (i == last) /* add last value (if interval was not empty) */ - addfield(L, &b, i); - luaL_pushresult(&b); - return 1; -} - - -/* -** {====================================================== -** Pack/unpack -** ======================================================= -*/ - -static int pack (lua_State *L) { - int n = lua_gettop(L); /* number of elements to pack */ - lua_createtable(L, n, 1); /* create result table */ - lua_pushinteger(L, n); - lua_setfield(L, -2, "n"); /* t.n = number of elements */ - if (n > 0) { /* at least one element? */ - int i; - lua_pushvalue(L, 1); - lua_rawseti(L, -2, 1); /* insert first element */ - lua_replace(L, 1); /* move table into index 1 */ - for (i = n; i >= 2; i--) /* assign other elements */ - lua_rawseti(L, 1, i); - } - return 1; /* return table */ -} - - -static int unpack (lua_State *L) { - int i, e; - unsigned int n; - luaL_checktype(L, 1, LUA_TTABLE); - i = luaL_optint(L, 2, 1); - e = luaL_opt(L, luaL_checkint, 3, luaL_len(L, 1)); - if (i > e) return 0; /* empty range */ - n = (unsigned int)e - (unsigned int)i; /* number of elements minus 1 */ - if (n > (INT_MAX - 10) || !lua_checkstack(L, ++n)) - return luaL_error(L, "too many results to unpack"); - lua_rawgeti(L, 1, i); /* push arg[i] (avoiding overflow problems) */ - while (i++ < e) /* push arg[i + 1...e] */ - lua_rawgeti(L, 1, i); - return n; -} - -/* }====================================================== */ - - - -/* -** {====================================================== -** Quicksort -** (based on `Algorithms in MODULA-3', Robert Sedgewick; -** Addison-Wesley, 1993.) -** ======================================================= -*/ - - -static void set2 (lua_State *L, int i, int j) { - lua_rawseti(L, 1, i); - lua_rawseti(L, 1, j); -} - -static int sort_comp (lua_State *L, int a, int b) { - if (!lua_isnil(L, 2)) { /* function? */ - int res; - lua_pushvalue(L, 2); - lua_pushvalue(L, a-1); /* -1 to compensate function */ - lua_pushvalue(L, b-2); /* -2 to compensate function and `a' */ - lua_call(L, 2, 1); - res = lua_toboolean(L, -1); - lua_pop(L, 1); - return res; - } - else /* a < b? */ - return lua_compare(L, a, b, LUA_OPLT); -} - -static void auxsort (lua_State *L, int l, int u) { - while (l < u) { /* for tail recursion */ - int i, j; - /* sort elements a[l], a[(l+u)/2] and a[u] */ - lua_rawgeti(L, 1, l); - lua_rawgeti(L, 1, u); - if (sort_comp(L, -1, -2)) /* a[u] < a[l]? */ - set2(L, l, u); /* swap a[l] - a[u] */ - else - lua_pop(L, 2); - if (u-l == 1) break; /* only 2 elements */ - i = (l+u)/2; - lua_rawgeti(L, 1, i); - lua_rawgeti(L, 1, l); - if (sort_comp(L, -2, -1)) /* a[i]= P */ - while (lua_rawgeti(L, 1, ++i), sort_comp(L, -1, -2)) { - if (i>=u) luaL_error(L, "invalid order function for sorting"); - lua_pop(L, 1); /* remove a[i] */ - } - /* repeat --j until a[j] <= P */ - while (lua_rawgeti(L, 1, --j), sort_comp(L, -3, -1)) { - if (j<=l) luaL_error(L, "invalid order function for sorting"); - lua_pop(L, 1); /* remove a[j] */ - } - if (j - -#define ltm_c -#define LUA_CORE - -#include "lua.h" - -#include "lobject.h" -#include "lstate.h" -#include "lstring.h" -#include "ltable.h" -#include "ltm.h" - - -static const char udatatypename[] = "userdata"; - -LUAI_DDEF const char *const luaT_typenames_[LUA_TOTALTAGS] = { - "no value", - "nil", "boolean", udatatypename, "number", - "string", "table", "function", udatatypename, "thread", - "proto", "upval" /* these last two cases are used for tests only */ -}; - - -void luaT_init (lua_State *L) { - static const char *const luaT_eventname[] = { /* ORDER TM */ - "__index", "__newindex", - "__gc", "__mode", "__len", "__eq", - "__add", "__sub", "__mul", "__div", "__mod", - "__pow", "__unm", "__lt", "__le", - "__concat", "__call" - }; - int i; - for (i=0; itmname[i] = luaS_new(L, luaT_eventname[i]); - luaS_fix(G(L)->tmname[i]); /* never collect these names */ - } -} - - -/* -** function to be used with macro "fasttm": optimized for absence of -** tag methods -*/ -const TValue *luaT_gettm (Table *events, TMS event, TString *ename) { - const TValue *tm = luaH_getstr(events, ename); - lua_assert(event <= TM_EQ); - if (ttisnil(tm)) { /* no tag method? */ - events->flags |= cast_byte(1u<metatable; - break; - case LUA_TUSERDATA: - mt = uvalue(o)->metatable; - break; - default: - mt = G(L)->mt[ttypenv(o)]; - } - return (mt ? luaH_getstr(mt, G(L)->tmname[event]) : luaO_nilobject); -} - diff --git a/lib/lua-5.2/src/ltm.h b/lib/lua-5.2/src/ltm.h deleted file mode 100644 index 7f89c84..0000000 --- a/lib/lua-5.2/src/ltm.h +++ /dev/null @@ -1,57 +0,0 @@ -/* -** $Id: ltm.h,v 2.11.1.1 2013/04/12 18:48:47 roberto Exp $ -** Tag methods -** See Copyright Notice in lua.h -*/ - -#ifndef ltm_h -#define ltm_h - - -#include "lobject.h" - - -/* -* WARNING: if you change the order of this enumeration, -* grep "ORDER TM" -*/ -typedef enum { - TM_INDEX, - TM_NEWINDEX, - TM_GC, - TM_MODE, - TM_LEN, - TM_EQ, /* last tag method with `fast' access */ - TM_ADD, - TM_SUB, - TM_MUL, - TM_DIV, - TM_MOD, - TM_POW, - TM_UNM, - TM_LT, - TM_LE, - TM_CONCAT, - TM_CALL, - TM_N /* number of elements in the enum */ -} TMS; - - - -#define gfasttm(g,et,e) ((et) == NULL ? NULL : \ - ((et)->flags & (1u<<(e))) ? NULL : luaT_gettm(et, e, (g)->tmname[e])) - -#define fasttm(l,et,e) gfasttm(G(l), et, e) - -#define ttypename(x) luaT_typenames_[(x) + 1] -#define objtypename(x) ttypename(ttypenv(x)) - -LUAI_DDEC const char *const luaT_typenames_[LUA_TOTALTAGS]; - - -LUAI_FUNC const TValue *luaT_gettm (Table *events, TMS event, TString *ename); -LUAI_FUNC const TValue *luaT_gettmbyobj (lua_State *L, const TValue *o, - TMS event); -LUAI_FUNC void luaT_init (lua_State *L); - -#endif diff --git a/lib/lua-5.2/src/lua.c b/lib/lua-5.2/src/lua.c deleted file mode 100644 index 4345e55..0000000 --- a/lib/lua-5.2/src/lua.c +++ /dev/null @@ -1,497 +0,0 @@ -/* -** $Id: lua.c,v 1.206.1.1 2013/04/12 18:48:47 roberto Exp $ -** Lua stand-alone interpreter -** See Copyright Notice in lua.h -*/ - - -#include -#include -#include -#include - -#define lua_c - -#include "lua.h" - -#include "lauxlib.h" -#include "lualib.h" - - -#if !defined(LUA_PROMPT) -#define LUA_PROMPT "> " -#define LUA_PROMPT2 ">> " -#endif - -#if !defined(LUA_PROGNAME) -#define LUA_PROGNAME "lua" -#endif - -#if !defined(LUA_MAXINPUT) -#define LUA_MAXINPUT 512 -#endif - -#if !defined(LUA_INIT) -#define LUA_INIT "LUA_INIT" -#endif - -#define LUA_INITVERSION \ - LUA_INIT "_" LUA_VERSION_MAJOR "_" LUA_VERSION_MINOR - - -/* -** lua_stdin_is_tty detects whether the standard input is a 'tty' (that -** is, whether we're running lua interactively). -*/ -#if defined(LUA_USE_ISATTY) -#include -#define lua_stdin_is_tty() isatty(0) -#elif defined(LUA_WIN) -#include -#include -#define lua_stdin_is_tty() _isatty(_fileno(stdin)) -#else -#define lua_stdin_is_tty() 1 /* assume stdin is a tty */ -#endif - - -/* -** lua_readline defines how to show a prompt and then read a line from -** the standard input. -** lua_saveline defines how to "save" a read line in a "history". -** lua_freeline defines how to free a line read by lua_readline. -*/ -#if defined(LUA_USE_READLINE) - -#include -#include -#include -#define lua_readline(L,b,p) ((void)L, ((b)=readline(p)) != NULL) -#define lua_saveline(L,idx) \ - if (lua_rawlen(L,idx) > 0) /* non-empty line? */ \ - add_history(lua_tostring(L, idx)); /* add it to history */ -#define lua_freeline(L,b) ((void)L, free(b)) - -#elif !defined(lua_readline) - -#define lua_readline(L,b,p) \ - ((void)L, fputs(p, stdout), fflush(stdout), /* show prompt */ \ - fgets(b, LUA_MAXINPUT, stdin) != NULL) /* get line */ -#define lua_saveline(L,idx) { (void)L; (void)idx; } -#define lua_freeline(L,b) { (void)L; (void)b; } - -#endif - - - - -static lua_State *globalL = NULL; - -static const char *progname = LUA_PROGNAME; - - - -static void lstop (lua_State *L, lua_Debug *ar) { - (void)ar; /* unused arg. */ - lua_sethook(L, NULL, 0, 0); - luaL_error(L, "interrupted!"); -} - - -static void laction (int i) { - signal(i, SIG_DFL); /* if another SIGINT happens before lstop, - terminate process (default action) */ - lua_sethook(globalL, lstop, LUA_MASKCALL | LUA_MASKRET | LUA_MASKCOUNT, 1); -} - - -static void print_usage (const char *badoption) { - luai_writestringerror("%s: ", progname); - if (badoption[1] == 'e' || badoption[1] == 'l') - luai_writestringerror("'%s' needs argument\n", badoption); - else - luai_writestringerror("unrecognized option '%s'\n", badoption); - luai_writestringerror( - "usage: %s [options] [script [args]]\n" - "Available options are:\n" - " -e stat execute string " LUA_QL("stat") "\n" - " -i enter interactive mode after executing " LUA_QL("script") "\n" - " -l name require library " LUA_QL("name") "\n" - " -v show version information\n" - " -E ignore environment variables\n" - " -- stop handling options\n" - " - stop handling options and execute stdin\n" - , - progname); -} - - -static void l_message (const char *pname, const char *msg) { - if (pname) luai_writestringerror("%s: ", pname); - luai_writestringerror("%s\n", msg); -} - - -static int report (lua_State *L, int status) { - if (status != LUA_OK && !lua_isnil(L, -1)) { - const char *msg = lua_tostring(L, -1); - if (msg == NULL) msg = "(error object is not a string)"; - l_message(progname, msg); - lua_pop(L, 1); - /* force a complete garbage collection in case of errors */ - lua_gc(L, LUA_GCCOLLECT, 0); - } - return status; -} - - -/* the next function is called unprotected, so it must avoid errors */ -static void finalreport (lua_State *L, int status) { - if (status != LUA_OK) { - const char *msg = (lua_type(L, -1) == LUA_TSTRING) ? lua_tostring(L, -1) - : NULL; - if (msg == NULL) msg = "(error object is not a string)"; - l_message(progname, msg); - lua_pop(L, 1); - } -} - - -static int traceback (lua_State *L) { - const char *msg = lua_tostring(L, 1); - if (msg) - luaL_traceback(L, L, msg, 1); - else if (!lua_isnoneornil(L, 1)) { /* is there an error object? */ - if (!luaL_callmeta(L, 1, "__tostring")) /* try its 'tostring' metamethod */ - lua_pushliteral(L, "(no error message)"); - } - return 1; -} - - -static int docall (lua_State *L, int narg, int nres) { - int status; - int base = lua_gettop(L) - narg; /* function index */ - lua_pushcfunction(L, traceback); /* push traceback function */ - lua_insert(L, base); /* put it under chunk and args */ - globalL = L; /* to be available to 'laction' */ - signal(SIGINT, laction); - status = lua_pcall(L, narg, nres, base); - signal(SIGINT, SIG_DFL); - lua_remove(L, base); /* remove traceback function */ - return status; -} - - -static void print_version (void) { - luai_writestring(LUA_COPYRIGHT, strlen(LUA_COPYRIGHT)); - luai_writeline(); -} - - -static int getargs (lua_State *L, char **argv, int n) { - int narg; - int i; - int argc = 0; - while (argv[argc]) argc++; /* count total number of arguments */ - narg = argc - (n + 1); /* number of arguments to the script */ - luaL_checkstack(L, narg + 3, "too many arguments to script"); - for (i=n+1; i < argc; i++) - lua_pushstring(L, argv[i]); - lua_createtable(L, narg, n + 1); - for (i=0; i < argc; i++) { - lua_pushstring(L, argv[i]); - lua_rawseti(L, -2, i - n); - } - return narg; -} - - -static int dofile (lua_State *L, const char *name) { - int status = luaL_loadfile(L, name); - if (status == LUA_OK) status = docall(L, 0, 0); - return report(L, status); -} - - -static int dostring (lua_State *L, const char *s, const char *name) { - int status = luaL_loadbuffer(L, s, strlen(s), name); - if (status == LUA_OK) status = docall(L, 0, 0); - return report(L, status); -} - - -static int dolibrary (lua_State *L, const char *name) { - int status; - lua_getglobal(L, "require"); - lua_pushstring(L, name); - status = docall(L, 1, 1); /* call 'require(name)' */ - if (status == LUA_OK) - lua_setglobal(L, name); /* global[name] = require return */ - return report(L, status); -} - - -static const char *get_prompt (lua_State *L, int firstline) { - const char *p; - lua_getglobal(L, firstline ? "_PROMPT" : "_PROMPT2"); - p = lua_tostring(L, -1); - if (p == NULL) p = (firstline ? LUA_PROMPT : LUA_PROMPT2); - return p; -} - -/* mark in error messages for incomplete statements */ -#define EOFMARK "" -#define marklen (sizeof(EOFMARK)/sizeof(char) - 1) - -static int incomplete (lua_State *L, int status) { - if (status == LUA_ERRSYNTAX) { - size_t lmsg; - const char *msg = lua_tolstring(L, -1, &lmsg); - if (lmsg >= marklen && strcmp(msg + lmsg - marklen, EOFMARK) == 0) { - lua_pop(L, 1); - return 1; - } - } - return 0; /* else... */ -} - - -static int pushline (lua_State *L, int firstline) { - char buffer[LUA_MAXINPUT]; - char *b = buffer; - size_t l; - const char *prmt = get_prompt(L, firstline); - int readstatus = lua_readline(L, b, prmt); - lua_pop(L, 1); /* remove result from 'get_prompt' */ - if (readstatus == 0) - return 0; /* no input */ - l = strlen(b); - if (l > 0 && b[l-1] == '\n') /* line ends with newline? */ - b[l-1] = '\0'; /* remove it */ - if (firstline && b[0] == '=') /* first line starts with `=' ? */ - lua_pushfstring(L, "return %s", b+1); /* change it to `return' */ - else - lua_pushstring(L, b); - lua_freeline(L, b); - return 1; -} - - -static int loadline (lua_State *L) { - int status; - lua_settop(L, 0); - if (!pushline(L, 1)) - return -1; /* no input */ - for (;;) { /* repeat until gets a complete line */ - size_t l; - const char *line = lua_tolstring(L, 1, &l); - status = luaL_loadbuffer(L, line, l, "=stdin"); - if (!incomplete(L, status)) break; /* cannot try to add lines? */ - if (!pushline(L, 0)) /* no more input? */ - return -1; - lua_pushliteral(L, "\n"); /* add a new line... */ - lua_insert(L, -2); /* ...between the two lines */ - lua_concat(L, 3); /* join them */ - } - lua_saveline(L, 1); - lua_remove(L, 1); /* remove line */ - return status; -} - - -static void dotty (lua_State *L) { - int status; - const char *oldprogname = progname; - progname = NULL; - while ((status = loadline(L)) != -1) { - if (status == LUA_OK) status = docall(L, 0, LUA_MULTRET); - report(L, status); - if (status == LUA_OK && lua_gettop(L) > 0) { /* any result to print? */ - luaL_checkstack(L, LUA_MINSTACK, "too many results to print"); - lua_getglobal(L, "print"); - lua_insert(L, 1); - if (lua_pcall(L, lua_gettop(L)-1, 0, 0) != LUA_OK) - l_message(progname, lua_pushfstring(L, - "error calling " LUA_QL("print") " (%s)", - lua_tostring(L, -1))); - } - } - lua_settop(L, 0); /* clear stack */ - luai_writeline(); - progname = oldprogname; -} - - -static int handle_script (lua_State *L, char **argv, int n) { - int status; - const char *fname; - int narg = getargs(L, argv, n); /* collect arguments */ - lua_setglobal(L, "arg"); - fname = argv[n]; - if (strcmp(fname, "-") == 0 && strcmp(argv[n-1], "--") != 0) - fname = NULL; /* stdin */ - status = luaL_loadfile(L, fname); - lua_insert(L, -(narg+1)); - if (status == LUA_OK) - status = docall(L, narg, LUA_MULTRET); - else - lua_pop(L, narg); - return report(L, status); -} - - -/* check that argument has no extra characters at the end */ -#define noextrachars(x) {if ((x)[2] != '\0') return -1;} - - -/* indices of various argument indicators in array args */ -#define has_i 0 /* -i */ -#define has_v 1 /* -v */ -#define has_e 2 /* -e */ -#define has_E 3 /* -E */ - -#define num_has 4 /* number of 'has_*' */ - - -static int collectargs (char **argv, int *args) { - int i; - for (i = 1; argv[i] != NULL; i++) { - if (argv[i][0] != '-') /* not an option? */ - return i; - switch (argv[i][1]) { /* option */ - case '-': - noextrachars(argv[i]); - return (argv[i+1] != NULL ? i+1 : 0); - case '\0': - return i; - case 'E': - args[has_E] = 1; - break; - case 'i': - noextrachars(argv[i]); - args[has_i] = 1; /* go through */ - case 'v': - noextrachars(argv[i]); - args[has_v] = 1; - break; - case 'e': - args[has_e] = 1; /* go through */ - case 'l': /* both options need an argument */ - if (argv[i][2] == '\0') { /* no concatenated argument? */ - i++; /* try next 'argv' */ - if (argv[i] == NULL || argv[i][0] == '-') - return -(i - 1); /* no next argument or it is another option */ - } - break; - default: /* invalid option; return its index... */ - return -i; /* ...as a negative value */ - } - } - return 0; -} - - -static int runargs (lua_State *L, char **argv, int n) { - int i; - for (i = 1; i < n; i++) { - lua_assert(argv[i][0] == '-'); - switch (argv[i][1]) { /* option */ - case 'e': { - const char *chunk = argv[i] + 2; - if (*chunk == '\0') chunk = argv[++i]; - lua_assert(chunk != NULL); - if (dostring(L, chunk, "=(command line)") != LUA_OK) - return 0; - break; - } - case 'l': { - const char *filename = argv[i] + 2; - if (*filename == '\0') filename = argv[++i]; - lua_assert(filename != NULL); - if (dolibrary(L, filename) != LUA_OK) - return 0; /* stop if file fails */ - break; - } - default: break; - } - } - return 1; -} - - -static int handle_luainit (lua_State *L) { - const char *name = "=" LUA_INITVERSION; - const char *init = getenv(name + 1); - if (init == NULL) { - name = "=" LUA_INIT; - init = getenv(name + 1); /* try alternative name */ - } - if (init == NULL) return LUA_OK; - else if (init[0] == '@') - return dofile(L, init+1); - else - return dostring(L, init, name); -} - - -static int pmain (lua_State *L) { - int argc = (int)lua_tointeger(L, 1); - char **argv = (char **)lua_touserdata(L, 2); - int script; - int args[num_has]; - args[has_i] = args[has_v] = args[has_e] = args[has_E] = 0; - if (argv[0] && argv[0][0]) progname = argv[0]; - script = collectargs(argv, args); - if (script < 0) { /* invalid arg? */ - print_usage(argv[-script]); - return 0; - } - if (args[has_v]) print_version(); - if (args[has_E]) { /* option '-E'? */ - lua_pushboolean(L, 1); /* signal for libraries to ignore env. vars. */ - lua_setfield(L, LUA_REGISTRYINDEX, "LUA_NOENV"); - } - /* open standard libraries */ - luaL_checkversion(L); - lua_gc(L, LUA_GCSTOP, 0); /* stop collector during initialization */ - luaL_openlibs(L); /* open libraries */ - lua_gc(L, LUA_GCRESTART, 0); - if (!args[has_E] && handle_luainit(L) != LUA_OK) - return 0; /* error running LUA_INIT */ - /* execute arguments -e and -l */ - if (!runargs(L, argv, (script > 0) ? script : argc)) return 0; - /* execute main script (if there is one) */ - if (script && handle_script(L, argv, script) != LUA_OK) return 0; - if (args[has_i]) /* -i option? */ - dotty(L); - else if (script == 0 && !args[has_e] && !args[has_v]) { /* no arguments? */ - if (lua_stdin_is_tty()) { - print_version(); - dotty(L); - } - else dofile(L, NULL); /* executes stdin as a file */ - } - lua_pushboolean(L, 1); /* signal no errors */ - return 1; -} - - -int main (int argc, char **argv) { - int status, result; - lua_State *L = luaL_newstate(); /* create state */ - if (L == NULL) { - l_message(argv[0], "cannot create state: not enough memory"); - return EXIT_FAILURE; - } - /* call 'pmain' in protected mode */ - lua_pushcfunction(L, &pmain); - lua_pushinteger(L, argc); /* 1st argument */ - lua_pushlightuserdata(L, argv); /* 2nd argument */ - status = lua_pcall(L, 2, 1, 0); - result = lua_toboolean(L, -1); /* get result */ - finalreport(L, status); - lua_close(L); - return (result && status == LUA_OK) ? EXIT_SUCCESS : EXIT_FAILURE; -} - diff --git a/lib/lua-5.2/src/lua.h b/lib/lua-5.2/src/lua.h deleted file mode 100644 index ff4a108..0000000 --- a/lib/lua-5.2/src/lua.h +++ /dev/null @@ -1,444 +0,0 @@ -/* -** $Id: lua.h,v 1.285.1.4 2015/02/21 14:04:50 roberto Exp $ -** Lua - A Scripting Language -** Lua.org, PUC-Rio, Brazil (http://www.lua.org) -** See Copyright Notice at the end of this file -*/ - - -#ifndef lua_h -#define lua_h - -#include -#include - - -#include "luaconf.h" - - -#define LUA_VERSION_MAJOR "5" -#define LUA_VERSION_MINOR "2" -#define LUA_VERSION_NUM 502 -#define LUA_VERSION_RELEASE "4" - -#define LUA_VERSION "Lua " LUA_VERSION_MAJOR "." LUA_VERSION_MINOR -#define LUA_RELEASE LUA_VERSION "." LUA_VERSION_RELEASE -#define LUA_COPYRIGHT LUA_RELEASE " Copyright (C) 1994-2015 Lua.org, PUC-Rio" -#define LUA_AUTHORS "R. Ierusalimschy, L. H. de Figueiredo, W. Celes" - - -/* mark for precompiled code ('Lua') */ -#define LUA_SIGNATURE "\033Lua" - -/* option for multiple returns in 'lua_pcall' and 'lua_call' */ -#define LUA_MULTRET (-1) - - -/* -** pseudo-indices -*/ -#define LUA_REGISTRYINDEX LUAI_FIRSTPSEUDOIDX -#define lua_upvalueindex(i) (LUA_REGISTRYINDEX - (i)) - - -/* thread status */ -#define LUA_OK 0 -#define LUA_YIELD 1 -#define LUA_ERRRUN 2 -#define LUA_ERRSYNTAX 3 -#define LUA_ERRMEM 4 -#define LUA_ERRGCMM 5 -#define LUA_ERRERR 6 - - -typedef struct lua_State lua_State; - -typedef int (*lua_CFunction) (lua_State *L); - - -/* -** functions that read/write blocks when loading/dumping Lua chunks -*/ -typedef const char * (*lua_Reader) (lua_State *L, void *ud, size_t *sz); - -typedef int (*lua_Writer) (lua_State *L, const void* p, size_t sz, void* ud); - - -/* -** prototype for memory-allocation functions -*/ -typedef void * (*lua_Alloc) (void *ud, void *ptr, size_t osize, size_t nsize); - - -/* -** basic types -*/ -#define LUA_TNONE (-1) - -#define LUA_TNIL 0 -#define LUA_TBOOLEAN 1 -#define LUA_TLIGHTUSERDATA 2 -#define LUA_TNUMBER 3 -#define LUA_TSTRING 4 -#define LUA_TTABLE 5 -#define LUA_TFUNCTION 6 -#define LUA_TUSERDATA 7 -#define LUA_TTHREAD 8 - -#define LUA_NUMTAGS 9 - - - -/* minimum Lua stack available to a C function */ -#define LUA_MINSTACK 20 - - -/* predefined values in the registry */ -#define LUA_RIDX_MAINTHREAD 1 -#define LUA_RIDX_GLOBALS 2 -#define LUA_RIDX_LAST LUA_RIDX_GLOBALS - - -/* type of numbers in Lua */ -typedef LUA_NUMBER lua_Number; - - -/* type for integer functions */ -typedef LUA_INTEGER lua_Integer; - -/* unsigned integer type */ -typedef LUA_UNSIGNED lua_Unsigned; - - - -/* -** generic extra include file -*/ -#if defined(LUA_USER_H) -#include LUA_USER_H -#endif - - -/* -** RCS ident string -*/ -extern const char lua_ident[]; - - -/* -** state manipulation -*/ -LUA_API lua_State *(lua_newstate) (lua_Alloc f, void *ud); -LUA_API void (lua_close) (lua_State *L); -LUA_API lua_State *(lua_newthread) (lua_State *L); - -LUA_API lua_CFunction (lua_atpanic) (lua_State *L, lua_CFunction panicf); - - -LUA_API const lua_Number *(lua_version) (lua_State *L); - - -/* -** basic stack manipulation -*/ -LUA_API int (lua_absindex) (lua_State *L, int idx); -LUA_API int (lua_gettop) (lua_State *L); -LUA_API void (lua_settop) (lua_State *L, int idx); -LUA_API void (lua_pushvalue) (lua_State *L, int idx); -LUA_API void (lua_remove) (lua_State *L, int idx); -LUA_API void (lua_insert) (lua_State *L, int idx); -LUA_API void (lua_replace) (lua_State *L, int idx); -LUA_API void (lua_copy) (lua_State *L, int fromidx, int toidx); -LUA_API int (lua_checkstack) (lua_State *L, int sz); - -LUA_API void (lua_xmove) (lua_State *from, lua_State *to, int n); - - -/* -** access functions (stack -> C) -*/ - -LUA_API int (lua_isnumber) (lua_State *L, int idx); -LUA_API int (lua_isstring) (lua_State *L, int idx); -LUA_API int (lua_iscfunction) (lua_State *L, int idx); -LUA_API int (lua_isuserdata) (lua_State *L, int idx); -LUA_API int (lua_type) (lua_State *L, int idx); -LUA_API const char *(lua_typename) (lua_State *L, int tp); - -LUA_API lua_Number (lua_tonumberx) (lua_State *L, int idx, int *isnum); -LUA_API lua_Integer (lua_tointegerx) (lua_State *L, int idx, int *isnum); -LUA_API lua_Unsigned (lua_tounsignedx) (lua_State *L, int idx, int *isnum); -LUA_API int (lua_toboolean) (lua_State *L, int idx); -LUA_API const char *(lua_tolstring) (lua_State *L, int idx, size_t *len); -LUA_API size_t (lua_rawlen) (lua_State *L, int idx); -LUA_API lua_CFunction (lua_tocfunction) (lua_State *L, int idx); -LUA_API void *(lua_touserdata) (lua_State *L, int idx); -LUA_API lua_State *(lua_tothread) (lua_State *L, int idx); -LUA_API const void *(lua_topointer) (lua_State *L, int idx); - - -/* -** Comparison and arithmetic functions -*/ - -#define LUA_OPADD 0 /* ORDER TM */ -#define LUA_OPSUB 1 -#define LUA_OPMUL 2 -#define LUA_OPDIV 3 -#define LUA_OPMOD 4 -#define LUA_OPPOW 5 -#define LUA_OPUNM 6 - -LUA_API void (lua_arith) (lua_State *L, int op); - -#define LUA_OPEQ 0 -#define LUA_OPLT 1 -#define LUA_OPLE 2 - -LUA_API int (lua_rawequal) (lua_State *L, int idx1, int idx2); -LUA_API int (lua_compare) (lua_State *L, int idx1, int idx2, int op); - - -/* -** push functions (C -> stack) -*/ -LUA_API void (lua_pushnil) (lua_State *L); -LUA_API void (lua_pushnumber) (lua_State *L, lua_Number n); -LUA_API void (lua_pushinteger) (lua_State *L, lua_Integer n); -LUA_API void (lua_pushunsigned) (lua_State *L, lua_Unsigned n); -LUA_API const char *(lua_pushlstring) (lua_State *L, const char *s, size_t l); -LUA_API const char *(lua_pushstring) (lua_State *L, const char *s); -LUA_API const char *(lua_pushvfstring) (lua_State *L, const char *fmt, - va_list argp); -LUA_API const char *(lua_pushfstring) (lua_State *L, const char *fmt, ...); -LUA_API void (lua_pushcclosure) (lua_State *L, lua_CFunction fn, int n); -LUA_API void (lua_pushboolean) (lua_State *L, int b); -LUA_API void (lua_pushlightuserdata) (lua_State *L, void *p); -LUA_API int (lua_pushthread) (lua_State *L); - - -/* -** get functions (Lua -> stack) -*/ -LUA_API void (lua_getglobal) (lua_State *L, const char *var); -LUA_API void (lua_gettable) (lua_State *L, int idx); -LUA_API void (lua_getfield) (lua_State *L, int idx, const char *k); -LUA_API void (lua_rawget) (lua_State *L, int idx); -LUA_API void (lua_rawgeti) (lua_State *L, int idx, int n); -LUA_API void (lua_rawgetp) (lua_State *L, int idx, const void *p); -LUA_API void (lua_createtable) (lua_State *L, int narr, int nrec); -LUA_API void *(lua_newuserdata) (lua_State *L, size_t sz); -LUA_API int (lua_getmetatable) (lua_State *L, int objindex); -LUA_API void (lua_getuservalue) (lua_State *L, int idx); - - -/* -** set functions (stack -> Lua) -*/ -LUA_API void (lua_setglobal) (lua_State *L, const char *var); -LUA_API void (lua_settable) (lua_State *L, int idx); -LUA_API void (lua_setfield) (lua_State *L, int idx, const char *k); -LUA_API void (lua_rawset) (lua_State *L, int idx); -LUA_API void (lua_rawseti) (lua_State *L, int idx, int n); -LUA_API void (lua_rawsetp) (lua_State *L, int idx, const void *p); -LUA_API int (lua_setmetatable) (lua_State *L, int objindex); -LUA_API void (lua_setuservalue) (lua_State *L, int idx); - - -/* -** 'load' and 'call' functions (load and run Lua code) -*/ -LUA_API void (lua_callk) (lua_State *L, int nargs, int nresults, int ctx, - lua_CFunction k); -#define lua_call(L,n,r) lua_callk(L, (n), (r), 0, NULL) - -LUA_API int (lua_getctx) (lua_State *L, int *ctx); - -LUA_API int (lua_pcallk) (lua_State *L, int nargs, int nresults, int errfunc, - int ctx, lua_CFunction k); -#define lua_pcall(L,n,r,f) lua_pcallk(L, (n), (r), (f), 0, NULL) - -LUA_API int (lua_load) (lua_State *L, lua_Reader reader, void *dt, - const char *chunkname, - const char *mode); - -LUA_API int (lua_dump) (lua_State *L, lua_Writer writer, void *data); - - -/* -** coroutine functions -*/ -LUA_API int (lua_yieldk) (lua_State *L, int nresults, int ctx, - lua_CFunction k); -#define lua_yield(L,n) lua_yieldk(L, (n), 0, NULL) -LUA_API int (lua_resume) (lua_State *L, lua_State *from, int narg); -LUA_API int (lua_status) (lua_State *L); - -/* -** garbage-collection function and options -*/ - -#define LUA_GCSTOP 0 -#define LUA_GCRESTART 1 -#define LUA_GCCOLLECT 2 -#define LUA_GCCOUNT 3 -#define LUA_GCCOUNTB 4 -#define LUA_GCSTEP 5 -#define LUA_GCSETPAUSE 6 -#define LUA_GCSETSTEPMUL 7 -#define LUA_GCSETMAJORINC 8 -#define LUA_GCISRUNNING 9 -#define LUA_GCGEN 10 -#define LUA_GCINC 11 - -LUA_API int (lua_gc) (lua_State *L, int what, int data); - - -/* -** miscellaneous functions -*/ - -LUA_API int (lua_error) (lua_State *L); - -LUA_API int (lua_next) (lua_State *L, int idx); - -LUA_API void (lua_concat) (lua_State *L, int n); -LUA_API void (lua_len) (lua_State *L, int idx); - -LUA_API lua_Alloc (lua_getallocf) (lua_State *L, void **ud); -LUA_API void (lua_setallocf) (lua_State *L, lua_Alloc f, void *ud); - - - -/* -** =============================================================== -** some useful macros -** =============================================================== -*/ - -#define lua_tonumber(L,i) lua_tonumberx(L,i,NULL) -#define lua_tointeger(L,i) lua_tointegerx(L,i,NULL) -#define lua_tounsigned(L,i) lua_tounsignedx(L,i,NULL) - -#define lua_pop(L,n) lua_settop(L, -(n)-1) - -#define lua_newtable(L) lua_createtable(L, 0, 0) - -#define lua_register(L,n,f) (lua_pushcfunction(L, (f)), lua_setglobal(L, (n))) - -#define lua_pushcfunction(L,f) lua_pushcclosure(L, (f), 0) - -#define lua_isfunction(L,n) (lua_type(L, (n)) == LUA_TFUNCTION) -#define lua_istable(L,n) (lua_type(L, (n)) == LUA_TTABLE) -#define lua_islightuserdata(L,n) (lua_type(L, (n)) == LUA_TLIGHTUSERDATA) -#define lua_isnil(L,n) (lua_type(L, (n)) == LUA_TNIL) -#define lua_isboolean(L,n) (lua_type(L, (n)) == LUA_TBOOLEAN) -#define lua_isthread(L,n) (lua_type(L, (n)) == LUA_TTHREAD) -#define lua_isnone(L,n) (lua_type(L, (n)) == LUA_TNONE) -#define lua_isnoneornil(L, n) (lua_type(L, (n)) <= 0) - -#define lua_pushliteral(L, s) \ - lua_pushlstring(L, "" s, (sizeof(s)/sizeof(char))-1) - -#define lua_pushglobaltable(L) \ - lua_rawgeti(L, LUA_REGISTRYINDEX, LUA_RIDX_GLOBALS) - -#define lua_tostring(L,i) lua_tolstring(L, (i), NULL) - - - -/* -** {====================================================================== -** Debug API -** ======================================================================= -*/ - - -/* -** Event codes -*/ -#define LUA_HOOKCALL 0 -#define LUA_HOOKRET 1 -#define LUA_HOOKLINE 2 -#define LUA_HOOKCOUNT 3 -#define LUA_HOOKTAILCALL 4 - - -/* -** Event masks -*/ -#define LUA_MASKCALL (1 << LUA_HOOKCALL) -#define LUA_MASKRET (1 << LUA_HOOKRET) -#define LUA_MASKLINE (1 << LUA_HOOKLINE) -#define LUA_MASKCOUNT (1 << LUA_HOOKCOUNT) - -typedef struct lua_Debug lua_Debug; /* activation record */ - - -/* Functions to be called by the debugger in specific events */ -typedef void (*lua_Hook) (lua_State *L, lua_Debug *ar); - - -LUA_API int (lua_getstack) (lua_State *L, int level, lua_Debug *ar); -LUA_API int (lua_getinfo) (lua_State *L, const char *what, lua_Debug *ar); -LUA_API const char *(lua_getlocal) (lua_State *L, const lua_Debug *ar, int n); -LUA_API const char *(lua_setlocal) (lua_State *L, const lua_Debug *ar, int n); -LUA_API const char *(lua_getupvalue) (lua_State *L, int funcindex, int n); -LUA_API const char *(lua_setupvalue) (lua_State *L, int funcindex, int n); - -LUA_API void *(lua_upvalueid) (lua_State *L, int fidx, int n); -LUA_API void (lua_upvaluejoin) (lua_State *L, int fidx1, int n1, - int fidx2, int n2); - -LUA_API int (lua_sethook) (lua_State *L, lua_Hook func, int mask, int count); -LUA_API lua_Hook (lua_gethook) (lua_State *L); -LUA_API int (lua_gethookmask) (lua_State *L); -LUA_API int (lua_gethookcount) (lua_State *L); - - -struct lua_Debug { - int event; - const char *name; /* (n) */ - const char *namewhat; /* (n) 'global', 'local', 'field', 'method' */ - const char *what; /* (S) 'Lua', 'C', 'main', 'tail' */ - const char *source; /* (S) */ - int currentline; /* (l) */ - int linedefined; /* (S) */ - int lastlinedefined; /* (S) */ - unsigned char nups; /* (u) number of upvalues */ - unsigned char nparams;/* (u) number of parameters */ - char isvararg; /* (u) */ - char istailcall; /* (t) */ - char short_src[LUA_IDSIZE]; /* (S) */ - /* private part */ - struct CallInfo *i_ci; /* active function */ -}; - -/* }====================================================================== */ - - -/****************************************************************************** -* Copyright (C) 1994-2015 Lua.org, PUC-Rio. -* -* Permission is hereby granted, free of charge, to any person obtaining -* a copy of this software and associated documentation files (the -* "Software"), to deal in the Software without restriction, including -* without limitation the rights to use, copy, modify, merge, publish, -* distribute, sublicense, and/or sell copies of the Software, and to -* permit persons to whom the Software is furnished to do so, subject to -* the following conditions: -* -* The above copyright notice and this permission notice shall be -* included in all copies or substantial portions of the Software. -* -* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, -* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF -* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. -* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY -* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, -* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE -* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. -******************************************************************************/ - - -#endif diff --git a/lib/lua-5.2/src/lua.hpp b/lib/lua-5.2/src/lua.hpp deleted file mode 100644 index ec417f5..0000000 --- a/lib/lua-5.2/src/lua.hpp +++ /dev/null @@ -1,9 +0,0 @@ -// lua.hpp -// Lua header files for C++ -// <> not supplied automatically because Lua also compiles as C++ - -extern "C" { -#include "lua.h" -#include "lualib.h" -#include "lauxlib.h" -} diff --git a/lib/lua-5.2/src/luac.c b/lib/lua-5.2/src/luac.c deleted file mode 100644 index 7409706..0000000 --- a/lib/lua-5.2/src/luac.c +++ /dev/null @@ -1,432 +0,0 @@ -/* -** $Id: luac.c,v 1.69 2011/11/29 17:46:33 lhf Exp $ -** Lua compiler (saves bytecodes to files; also list bytecodes) -** See Copyright Notice in lua.h -*/ - -#include -#include -#include -#include - -#define luac_c -#define LUA_CORE - -#include "lua.h" -#include "lauxlib.h" - -#include "lobject.h" -#include "lstate.h" -#include "lundump.h" - -static void PrintFunction(const Proto* f, int full); -#define luaU_print PrintFunction - -#define PROGNAME "luac" /* default program name */ -#define OUTPUT PROGNAME ".out" /* default output file */ - -static int listing=0; /* list bytecodes? */ -static int dumping=1; /* dump bytecodes? */ -static int stripping=0; /* strip debug information? */ -static char Output[]={ OUTPUT }; /* default output file name */ -static const char* output=Output; /* actual output file name */ -static const char* progname=PROGNAME; /* actual program name */ - -static void fatal(const char* message) -{ - fprintf(stderr,"%s: %s\n",progname,message); - exit(EXIT_FAILURE); -} - -static void cannot(const char* what) -{ - fprintf(stderr,"%s: cannot %s %s: %s\n",progname,what,output,strerror(errno)); - exit(EXIT_FAILURE); -} - -static void usage(const char* message) -{ - if (*message=='-') - fprintf(stderr,"%s: unrecognized option " LUA_QS "\n",progname,message); - else - fprintf(stderr,"%s: %s\n",progname,message); - fprintf(stderr, - "usage: %s [options] [filenames]\n" - "Available options are:\n" - " -l list (use -l -l for full listing)\n" - " -o name output to file " LUA_QL("name") " (default is \"%s\")\n" - " -p parse only\n" - " -s strip debug information\n" - " -v show version information\n" - " -- stop handling options\n" - " - stop handling options and process stdin\n" - ,progname,Output); - exit(EXIT_FAILURE); -} - -#define IS(s) (strcmp(argv[i],s)==0) - -static int doargs(int argc, char* argv[]) -{ - int i; - int version=0; - if (argv[0]!=NULL && *argv[0]!=0) progname=argv[0]; - for (i=1; itop+(i)) - -static const Proto* combine(lua_State* L, int n) -{ - if (n==1) - return toproto(L,-1); - else - { - Proto* f; - int i=n; - if (lua_load(L,reader,&i,"=(" PROGNAME ")",NULL)!=LUA_OK) fatal(lua_tostring(L,-1)); - f=toproto(L,-1); - for (i=0; ip[i]=toproto(L,i-n-1); - if (f->p[i]->sizeupvalues>0) f->p[i]->upvalues[0].instack=0; - } - f->sizelineinfo=0; - return f; - } -} - -static int writer(lua_State* L, const void* p, size_t size, void* u) -{ - UNUSED(L); - return (fwrite(p,size,1,(FILE*)u)!=1) && (size!=0); -} - -static int pmain(lua_State* L) -{ - int argc=(int)lua_tointeger(L,1); - char** argv=(char**)lua_touserdata(L,2); - const Proto* f; - int i; - if (!lua_checkstack(L,argc)) fatal("too many input files"); - for (i=0; i1); - if (dumping) - { - FILE* D= (output==NULL) ? stdout : fopen(output,"wb"); - if (D==NULL) cannot("open"); - lua_lock(L); - luaU_dump(L,f,writer,D,stripping); - lua_unlock(L); - if (ferror(D)) cannot("write"); - if (fclose(D)) cannot("close"); - } - return 0; -} - -int main(int argc, char* argv[]) -{ - lua_State* L; - int i=doargs(argc,argv); - argc-=i; argv+=i; - if (argc<=0) usage("no input files given"); - L=luaL_newstate(); - if (L==NULL) fatal("cannot create state: not enough memory"); - lua_pushcfunction(L,&pmain); - lua_pushinteger(L,argc); - lua_pushlightuserdata(L,argv); - if (lua_pcall(L,2,0,0)!=LUA_OK) fatal(lua_tostring(L,-1)); - lua_close(L); - return EXIT_SUCCESS; -} - -/* -** $Id: print.c,v 1.69 2013/07/04 01:03:46 lhf Exp $ -** print bytecodes -** See Copyright Notice in lua.h -*/ - -#include -#include - -#define luac_c -#define LUA_CORE - -#include "ldebug.h" -#include "lobject.h" -#include "lopcodes.h" - -#define VOID(p) ((const void*)(p)) - -static void PrintString(const TString* ts) -{ - const char* s=getstr(ts); - size_t i,n=ts->tsv.len; - printf("%c",'"'); - for (i=0; ik[i]; - switch (ttypenv(o)) - { - case LUA_TNIL: - printf("nil"); - break; - case LUA_TBOOLEAN: - printf(bvalue(o) ? "true" : "false"); - break; - case LUA_TNUMBER: - printf(LUA_NUMBER_FMT,nvalue(o)); - break; - case LUA_TSTRING: - PrintString(rawtsvalue(o)); - break; - default: /* cannot happen */ - printf("? type=%d",ttype(o)); - break; - } -} - -#define UPVALNAME(x) ((f->upvalues[x].name) ? getstr(f->upvalues[x].name) : "-") -#define MYK(x) (-1-(x)) - -static void PrintCode(const Proto* f) -{ - const Instruction* code=f->code; - int pc,n=f->sizecode; - for (pc=0; pc0) printf("[%d]\t",line); else printf("[-]\t"); - printf("%-9s\t",luaP_opnames[o]); - switch (getOpMode(o)) - { - case iABC: - printf("%d",a); - if (getBMode(o)!=OpArgN) printf(" %d",ISK(b) ? (MYK(INDEXK(b))) : b); - if (getCMode(o)!=OpArgN) printf(" %d",ISK(c) ? (MYK(INDEXK(c))) : c); - break; - case iABx: - printf("%d",a); - if (getBMode(o)==OpArgK) printf(" %d",MYK(bx)); - if (getBMode(o)==OpArgU) printf(" %d",bx); - break; - case iAsBx: - printf("%d %d",a,sbx); - break; - case iAx: - printf("%d",MYK(ax)); - break; - } - switch (o) - { - case OP_LOADK: - printf("\t; "); PrintConstant(f,bx); - break; - case OP_GETUPVAL: - case OP_SETUPVAL: - printf("\t; %s",UPVALNAME(b)); - break; - case OP_GETTABUP: - printf("\t; %s",UPVALNAME(b)); - if (ISK(c)) { printf(" "); PrintConstant(f,INDEXK(c)); } - break; - case OP_SETTABUP: - printf("\t; %s",UPVALNAME(a)); - if (ISK(b)) { printf(" "); PrintConstant(f,INDEXK(b)); } - if (ISK(c)) { printf(" "); PrintConstant(f,INDEXK(c)); } - break; - case OP_GETTABLE: - case OP_SELF: - if (ISK(c)) { printf("\t; "); PrintConstant(f,INDEXK(c)); } - break; - case OP_SETTABLE: - case OP_ADD: - case OP_SUB: - case OP_MUL: - case OP_DIV: - case OP_POW: - case OP_EQ: - case OP_LT: - case OP_LE: - if (ISK(b) || ISK(c)) - { - printf("\t; "); - if (ISK(b)) PrintConstant(f,INDEXK(b)); else printf("-"); - printf(" "); - if (ISK(c)) PrintConstant(f,INDEXK(c)); else printf("-"); - } - break; - case OP_JMP: - case OP_FORLOOP: - case OP_FORPREP: - case OP_TFORLOOP: - printf("\t; to %d",sbx+pc+2); - break; - case OP_CLOSURE: - printf("\t; %p",VOID(f->p[bx])); - break; - case OP_SETLIST: - if (c==0) printf("\t; %d",(int)code[++pc]); else printf("\t; %d",c); - break; - case OP_EXTRAARG: - printf("\t; "); PrintConstant(f,ax); - break; - default: - break; - } - printf("\n"); - } -} - -#define SS(x) ((x==1)?"":"s") -#define S(x) (int)(x),SS(x) - -static void PrintHeader(const Proto* f) -{ - const char* s=f->source ? getstr(f->source) : "=?"; - if (*s=='@' || *s=='=') - s++; - else if (*s==LUA_SIGNATURE[0]) - s="(bstring)"; - else - s="(string)"; - printf("\n%s <%s:%d,%d> (%d instruction%s at %p)\n", - (f->linedefined==0)?"main":"function",s, - f->linedefined,f->lastlinedefined, - S(f->sizecode),VOID(f)); - printf("%d%s param%s, %d slot%s, %d upvalue%s, ", - (int)(f->numparams),f->is_vararg?"+":"",SS(f->numparams), - S(f->maxstacksize),S(f->sizeupvalues)); - printf("%d local%s, %d constant%s, %d function%s\n", - S(f->sizelocvars),S(f->sizek),S(f->sizep)); -} - -static void PrintDebug(const Proto* f) -{ - int i,n; - n=f->sizek; - printf("constants (%d) for %p:\n",n,VOID(f)); - for (i=0; isizelocvars; - printf("locals (%d) for %p:\n",n,VOID(f)); - for (i=0; ilocvars[i].varname),f->locvars[i].startpc+1,f->locvars[i].endpc+1); - } - n=f->sizeupvalues; - printf("upvalues (%d) for %p:\n",n,VOID(f)); - for (i=0; iupvalues[i].instack,f->upvalues[i].idx); - } -} - -static void PrintFunction(const Proto* f, int full) -{ - int i,n=f->sizep; - PrintHeader(f); - PrintCode(f); - if (full) PrintDebug(f); - for (i=0; ip[i],full); -} diff --git a/lib/lua-5.2/src/luaconf.h b/lib/lua-5.2/src/luaconf.h deleted file mode 100644 index 1b0ff59..0000000 --- a/lib/lua-5.2/src/luaconf.h +++ /dev/null @@ -1,551 +0,0 @@ -/* -** $Id: luaconf.h,v 1.176.1.2 2013/11/21 17:26:16 roberto Exp $ -** Configuration file for Lua -** See Copyright Notice in lua.h -*/ - - -#ifndef lconfig_h -#define lconfig_h - -#include -#include - - -/* -** ================================================================== -** Search for "@@" to find all configurable definitions. -** =================================================================== -*/ - - -/* -@@ LUA_ANSI controls the use of non-ansi features. -** CHANGE it (define it) if you want Lua to avoid the use of any -** non-ansi feature or library. -*/ -#if !defined(LUA_ANSI) && defined(__STRICT_ANSI__) -#define LUA_ANSI -#endif - - -#if !defined(LUA_ANSI) && defined(_WIN32) && !defined(_WIN32_WCE) -#define LUA_WIN /* enable goodies for regular Windows platforms */ -#endif - -#if defined(LUA_WIN) -#define LUA_DL_DLL -#define LUA_USE_AFORMAT /* assume 'printf' handles 'aA' specifiers */ -#endif - - - -#if defined(LUA_USE_LINUX) -#define LUA_USE_POSIX -#define LUA_USE_DLOPEN /* needs an extra library: -ldl */ -#define LUA_USE_READLINE /* needs some extra libraries */ -#define LUA_USE_STRTODHEX /* assume 'strtod' handles hex formats */ -#define LUA_USE_AFORMAT /* assume 'printf' handles 'aA' specifiers */ -#define LUA_USE_LONGLONG /* assume support for long long */ -#endif - -#if defined(LUA_USE_MACOSX) -#define LUA_USE_POSIX -#define LUA_USE_DLOPEN /* does not need -ldl */ -#define LUA_USE_READLINE /* needs an extra library: -lreadline */ -#define LUA_USE_STRTODHEX /* assume 'strtod' handles hex formats */ -#define LUA_USE_AFORMAT /* assume 'printf' handles 'aA' specifiers */ -#define LUA_USE_LONGLONG /* assume support for long long */ -#endif - - - -/* -@@ LUA_USE_POSIX includes all functionality listed as X/Open System -@* Interfaces Extension (XSI). -** CHANGE it (define it) if your system is XSI compatible. -*/ -#if defined(LUA_USE_POSIX) -#define LUA_USE_MKSTEMP -#define LUA_USE_ISATTY -#define LUA_USE_POPEN -#define LUA_USE_ULONGJMP -#define LUA_USE_GMTIME_R -#endif - - - -/* -@@ LUA_PATH_DEFAULT is the default path that Lua uses to look for -@* Lua libraries. -@@ LUA_CPATH_DEFAULT is the default path that Lua uses to look for -@* C libraries. -** CHANGE them if your machine has a non-conventional directory -** hierarchy or if you want to install your libraries in -** non-conventional directories. -*/ -#if defined(_WIN32) /* { */ -/* -** In Windows, any exclamation mark ('!') in the path is replaced by the -** path of the directory of the executable file of the current process. -*/ -#define LUA_LDIR "!\\lua\\" -#define LUA_CDIR "!\\" -#define LUA_PATH_DEFAULT \ - LUA_LDIR"?.lua;" LUA_LDIR"?\\init.lua;" \ - LUA_CDIR"?.lua;" LUA_CDIR"?\\init.lua;" ".\\?.lua" -#define LUA_CPATH_DEFAULT \ - LUA_CDIR"?.dll;" LUA_CDIR"loadall.dll;" ".\\?.dll" - -#else /* }{ */ - -#define LUA_VDIR LUA_VERSION_MAJOR "." LUA_VERSION_MINOR "/" -#define LUA_ROOT "/usr/local/" -#define LUA_LDIR LUA_ROOT "share/lua/" LUA_VDIR -#define LUA_CDIR LUA_ROOT "lib/lua/" LUA_VDIR -#define LUA_PATH_DEFAULT \ - LUA_LDIR"?.lua;" LUA_LDIR"?/init.lua;" \ - LUA_CDIR"?.lua;" LUA_CDIR"?/init.lua;" "./?.lua" -#define LUA_CPATH_DEFAULT \ - LUA_CDIR"?.so;" LUA_CDIR"loadall.so;" "./?.so" -#endif /* } */ - - -/* -@@ LUA_DIRSEP is the directory separator (for submodules). -** CHANGE it if your machine does not use "/" as the directory separator -** and is not Windows. (On Windows Lua automatically uses "\".) -*/ -#if defined(_WIN32) -#define LUA_DIRSEP "\\" -#else -#define LUA_DIRSEP "/" -#endif - - -/* -@@ LUA_ENV is the name of the variable that holds the current -@@ environment, used to access global names. -** CHANGE it if you do not like this name. -*/ -#define LUA_ENV "_ENV" - - -/* -@@ LUA_API is a mark for all core API functions. -@@ LUALIB_API is a mark for all auxiliary library functions. -@@ LUAMOD_API is a mark for all standard library opening functions. -** CHANGE them if you need to define those functions in some special way. -** For instance, if you want to create one Windows DLL with the core and -** the libraries, you may want to use the following definition (define -** LUA_BUILD_AS_DLL to get it). -*/ -#if defined(LUA_BUILD_AS_DLL) /* { */ - -#if defined(LUA_CORE) || defined(LUA_LIB) /* { */ -#define LUA_API __declspec(dllexport) -#else /* }{ */ -#define LUA_API __declspec(dllimport) -#endif /* } */ - -#else /* }{ */ - -#define LUA_API extern - -#endif /* } */ - - -/* more often than not the libs go together with the core */ -#define LUALIB_API LUA_API -#define LUAMOD_API LUALIB_API - - -/* -@@ LUAI_FUNC is a mark for all extern functions that are not to be -@* exported to outside modules. -@@ LUAI_DDEF and LUAI_DDEC are marks for all extern (const) variables -@* that are not to be exported to outside modules (LUAI_DDEF for -@* definitions and LUAI_DDEC for declarations). -** CHANGE them if you need to mark them in some special way. Elf/gcc -** (versions 3.2 and later) mark them as "hidden" to optimize access -** when Lua is compiled as a shared library. Not all elf targets support -** this attribute. Unfortunately, gcc does not offer a way to check -** whether the target offers that support, and those without support -** give a warning about it. To avoid these warnings, change to the -** default definition. -*/ -#if defined(__GNUC__) && ((__GNUC__*100 + __GNUC_MINOR__) >= 302) && \ - defined(__ELF__) /* { */ -#define LUAI_FUNC __attribute__((visibility("hidden"))) extern -#define LUAI_DDEC LUAI_FUNC -#define LUAI_DDEF /* empty */ - -#else /* }{ */ -#define LUAI_FUNC extern -#define LUAI_DDEC extern -#define LUAI_DDEF /* empty */ -#endif /* } */ - - - -/* -@@ LUA_QL describes how error messages quote program elements. -** CHANGE it if you want a different appearance. -*/ -#define LUA_QL(x) "'" x "'" -#define LUA_QS LUA_QL("%s") - - -/* -@@ LUA_IDSIZE gives the maximum size for the description of the source -@* of a function in debug information. -** CHANGE it if you want a different size. -*/ -#define LUA_IDSIZE 60 - - -/* -@@ luai_writestring/luai_writeline define how 'print' prints its results. -** They are only used in libraries and the stand-alone program. (The #if -** avoids including 'stdio.h' everywhere.) -*/ -#if defined(LUA_LIB) || defined(lua_c) -#include -#define luai_writestring(s,l) fwrite((s), sizeof(char), (l), stdout) -#define luai_writeline() (luai_writestring("\n", 1), fflush(stdout)) -#endif - -/* -@@ luai_writestringerror defines how to print error messages. -** (A format string with one argument is enough for Lua...) -*/ -#define luai_writestringerror(s,p) \ - (fprintf(stderr, (s), (p)), fflush(stderr)) - - -/* -@@ LUAI_MAXSHORTLEN is the maximum length for short strings, that is, -** strings that are internalized. (Cannot be smaller than reserved words -** or tags for metamethods, as these strings must be internalized; -** #("function") = 8, #("__newindex") = 10.) -*/ -#define LUAI_MAXSHORTLEN 40 - - - -/* -** {================================================================== -** Compatibility with previous versions -** =================================================================== -*/ - -/* -@@ LUA_COMPAT_ALL controls all compatibility options. -** You can define it to get all options, or change specific options -** to fit your specific needs. -*/ -#if defined(LUA_COMPAT_ALL) /* { */ - -/* -@@ LUA_COMPAT_UNPACK controls the presence of global 'unpack'. -** You can replace it with 'table.unpack'. -*/ -#define LUA_COMPAT_UNPACK - -/* -@@ LUA_COMPAT_LOADERS controls the presence of table 'package.loaders'. -** You can replace it with 'package.searchers'. -*/ -#define LUA_COMPAT_LOADERS - -/* -@@ macro 'lua_cpcall' emulates deprecated function lua_cpcall. -** You can call your C function directly (with light C functions). -*/ -#define lua_cpcall(L,f,u) \ - (lua_pushcfunction(L, (f)), \ - lua_pushlightuserdata(L,(u)), \ - lua_pcall(L,1,0,0)) - - -/* -@@ LUA_COMPAT_LOG10 defines the function 'log10' in the math library. -** You can rewrite 'log10(x)' as 'log(x, 10)'. -*/ -#define LUA_COMPAT_LOG10 - -/* -@@ LUA_COMPAT_LOADSTRING defines the function 'loadstring' in the base -** library. You can rewrite 'loadstring(s)' as 'load(s)'. -*/ -#define LUA_COMPAT_LOADSTRING - -/* -@@ LUA_COMPAT_MAXN defines the function 'maxn' in the table library. -*/ -#define LUA_COMPAT_MAXN - -/* -@@ The following macros supply trivial compatibility for some -** changes in the API. The macros themselves document how to -** change your code to avoid using them. -*/ -#define lua_strlen(L,i) lua_rawlen(L, (i)) - -#define lua_objlen(L,i) lua_rawlen(L, (i)) - -#define lua_equal(L,idx1,idx2) lua_compare(L,(idx1),(idx2),LUA_OPEQ) -#define lua_lessthan(L,idx1,idx2) lua_compare(L,(idx1),(idx2),LUA_OPLT) - -/* -@@ LUA_COMPAT_MODULE controls compatibility with previous -** module functions 'module' (Lua) and 'luaL_register' (C). -*/ -#define LUA_COMPAT_MODULE - -#endif /* } */ - -/* }================================================================== */ - - - -/* -@@ LUAI_BITSINT defines the number of bits in an int. -** CHANGE here if Lua cannot automatically detect the number of bits of -** your machine. Probably you do not need to change this. -*/ -/* avoid overflows in comparison */ -#if INT_MAX-20 < 32760 /* { */ -#define LUAI_BITSINT 16 -#elif INT_MAX > 2147483640L /* }{ */ -/* int has at least 32 bits */ -#define LUAI_BITSINT 32 -#else /* }{ */ -#error "you must define LUA_BITSINT with number of bits in an integer" -#endif /* } */ - - -/* -@@ LUA_INT32 is a signed integer with exactly 32 bits. -@@ LUAI_UMEM is an unsigned integer big enough to count the total -@* memory used by Lua. -@@ LUAI_MEM is a signed integer big enough to count the total memory -@* used by Lua. -** CHANGE here if for some weird reason the default definitions are not -** good enough for your machine. Probably you do not need to change -** this. -*/ -#if LUAI_BITSINT >= 32 /* { */ -#define LUA_INT32 int -#define LUAI_UMEM size_t -#define LUAI_MEM ptrdiff_t -#else /* }{ */ -/* 16-bit ints */ -#define LUA_INT32 long -#define LUAI_UMEM unsigned long -#define LUAI_MEM long -#endif /* } */ - - -/* -@@ LUAI_MAXSTACK limits the size of the Lua stack. -** CHANGE it if you need a different limit. This limit is arbitrary; -** its only purpose is to stop Lua from consuming unlimited stack -** space (and to reserve some numbers for pseudo-indices). -*/ -#if LUAI_BITSINT >= 32 -#define LUAI_MAXSTACK 1000000 -#else -#define LUAI_MAXSTACK 15000 -#endif - -/* reserve some space for error handling */ -#define LUAI_FIRSTPSEUDOIDX (-LUAI_MAXSTACK - 1000) - - - - -/* -@@ LUAL_BUFFERSIZE is the buffer size used by the lauxlib buffer system. -** CHANGE it if it uses too much C-stack space. -*/ -#define LUAL_BUFFERSIZE BUFSIZ - - - - -/* -** {================================================================== -@@ LUA_NUMBER is the type of numbers in Lua. -** CHANGE the following definitions only if you want to build Lua -** with a number type different from double. You may also need to -** change lua_number2int & lua_number2integer. -** =================================================================== -*/ - -#define LUA_NUMBER_DOUBLE -#define LUA_NUMBER double - -/* -@@ LUAI_UACNUMBER is the result of an 'usual argument conversion' -@* over a number. -*/ -#define LUAI_UACNUMBER double - - -/* -@@ LUA_NUMBER_SCAN is the format for reading numbers. -@@ LUA_NUMBER_FMT is the format for writing numbers. -@@ lua_number2str converts a number to a string. -@@ LUAI_MAXNUMBER2STR is maximum size of previous conversion. -*/ -#define LUA_NUMBER_SCAN "%lf" -#define LUA_NUMBER_FMT "%.14g" -#define lua_number2str(s,n) sprintf((s), LUA_NUMBER_FMT, (n)) -#define LUAI_MAXNUMBER2STR 32 /* 16 digits, sign, point, and \0 */ - - -/* -@@ l_mathop allows the addition of an 'l' or 'f' to all math operations -*/ -#define l_mathop(x) (x) - - -/* -@@ lua_str2number converts a decimal numeric string to a number. -@@ lua_strx2number converts an hexadecimal numeric string to a number. -** In C99, 'strtod' does both conversions. C89, however, has no function -** to convert floating hexadecimal strings to numbers. For these -** systems, you can leave 'lua_strx2number' undefined and Lua will -** provide its own implementation. -*/ -#define lua_str2number(s,p) strtod((s), (p)) - -#if defined(LUA_USE_STRTODHEX) -#define lua_strx2number(s,p) strtod((s), (p)) -#endif - - -/* -@@ The luai_num* macros define the primitive operations over numbers. -*/ - -/* the following operations need the math library */ -#if defined(lobject_c) || defined(lvm_c) -#include -#define luai_nummod(L,a,b) ((a) - l_mathop(floor)((a)/(b))*(b)) -#define luai_numpow(L,a,b) (l_mathop(pow)(a,b)) -#endif - -/* these are quite standard operations */ -#if defined(LUA_CORE) -#define luai_numadd(L,a,b) ((a)+(b)) -#define luai_numsub(L,a,b) ((a)-(b)) -#define luai_nummul(L,a,b) ((a)*(b)) -#define luai_numdiv(L,a,b) ((a)/(b)) -#define luai_numunm(L,a) (-(a)) -#define luai_numeq(a,b) ((a)==(b)) -#define luai_numlt(L,a,b) ((a)<(b)) -#define luai_numle(L,a,b) ((a)<=(b)) -#define luai_numisnan(L,a) (!luai_numeq((a), (a))) -#endif - - - -/* -@@ LUA_INTEGER is the integral type used by lua_pushinteger/lua_tointeger. -** CHANGE that if ptrdiff_t is not adequate on your machine. (On most -** machines, ptrdiff_t gives a good choice between int or long.) -*/ -#define LUA_INTEGER ptrdiff_t - -/* -@@ LUA_UNSIGNED is the integral type used by lua_pushunsigned/lua_tounsigned. -** It must have at least 32 bits. -*/ -#define LUA_UNSIGNED unsigned LUA_INT32 - - - -/* -** Some tricks with doubles -*/ - -#if defined(LUA_NUMBER_DOUBLE) && !defined(LUA_ANSI) /* { */ -/* -** The next definitions activate some tricks to speed up the -** conversion from doubles to integer types, mainly to LUA_UNSIGNED. -** -@@ LUA_MSASMTRICK uses Microsoft assembler to avoid clashes with a -** DirectX idiosyncrasy. -** -@@ LUA_IEEE754TRICK uses a trick that should work on any machine -** using IEEE754 with a 32-bit integer type. -** -@@ LUA_IEEELL extends the trick to LUA_INTEGER; should only be -** defined when LUA_INTEGER is a 32-bit integer. -** -@@ LUA_IEEEENDIAN is the endianness of doubles in your machine -** (0 for little endian, 1 for big endian); if not defined, Lua will -** check it dynamically for LUA_IEEE754TRICK (but not for LUA_NANTRICK). -** -@@ LUA_NANTRICK controls the use of a trick to pack all types into -** a single double value, using NaN values to represent non-number -** values. The trick only works on 32-bit machines (ints and pointers -** are 32-bit values) with numbers represented as IEEE 754-2008 doubles -** with conventional endianess (12345678 or 87654321), in CPUs that do -** not produce signaling NaN values (all NaNs are quiet). -*/ - -/* Microsoft compiler on a Pentium (32 bit) ? */ -#if defined(LUA_WIN) && defined(_MSC_VER) && defined(_M_IX86) /* { */ - -#define LUA_MSASMTRICK -#define LUA_IEEEENDIAN 0 -#define LUA_NANTRICK - - -/* pentium 32 bits? */ -#elif defined(__i386__) || defined(__i386) || defined(__X86__) /* }{ */ - -#define LUA_IEEE754TRICK -#define LUA_IEEELL -#define LUA_IEEEENDIAN 0 -#define LUA_NANTRICK - -/* pentium 64 bits? */ -#elif defined(__x86_64) /* }{ */ - -#define LUA_IEEE754TRICK -#define LUA_IEEEENDIAN 0 - -#elif defined(__POWERPC__) || defined(__ppc__) /* }{ */ - -#define LUA_IEEE754TRICK -#define LUA_IEEEENDIAN 1 - -#else /* }{ */ - -/* assume IEEE754 and a 32-bit integer type */ -#define LUA_IEEE754TRICK - -#endif /* } */ - -#endif /* } */ - -/* }================================================================== */ - - - - -/* =================================================================== */ - -/* -** Local configuration. You can use this space to add your redefinitions -** without modifying the main part of the file. -*/ - - - -#endif - diff --git a/lib/lua-5.2/src/lualib.h b/lib/lua-5.2/src/lualib.h deleted file mode 100644 index da82005..0000000 --- a/lib/lua-5.2/src/lualib.h +++ /dev/null @@ -1,55 +0,0 @@ -/* -** $Id: lualib.h,v 1.43.1.1 2013/04/12 18:48:47 roberto Exp $ -** Lua standard libraries -** See Copyright Notice in lua.h -*/ - - -#ifndef lualib_h -#define lualib_h - -#include "lua.h" - - - -LUAMOD_API int (luaopen_base) (lua_State *L); - -#define LUA_COLIBNAME "coroutine" -LUAMOD_API int (luaopen_coroutine) (lua_State *L); - -#define LUA_TABLIBNAME "table" -LUAMOD_API int (luaopen_table) (lua_State *L); - -#define LUA_IOLIBNAME "io" -LUAMOD_API int (luaopen_io) (lua_State *L); - -#define LUA_OSLIBNAME "os" -LUAMOD_API int (luaopen_os) (lua_State *L); - -#define LUA_STRLIBNAME "string" -LUAMOD_API int (luaopen_string) (lua_State *L); - -#define LUA_BITLIBNAME "bit32" -LUAMOD_API int (luaopen_bit32) (lua_State *L); - -#define LUA_MATHLIBNAME "math" -LUAMOD_API int (luaopen_math) (lua_State *L); - -#define LUA_DBLIBNAME "debug" -LUAMOD_API int (luaopen_debug) (lua_State *L); - -#define LUA_LOADLIBNAME "package" -LUAMOD_API int (luaopen_package) (lua_State *L); - - -/* open all previous libraries */ -LUALIB_API void (luaL_openlibs) (lua_State *L); - - - -#if !defined(lua_assert) -#define lua_assert(x) ((void)0) -#endif - - -#endif diff --git a/lib/lua-5.2/src/lundump.c b/lib/lua-5.2/src/lundump.c deleted file mode 100644 index 4163cb5..0000000 --- a/lib/lua-5.2/src/lundump.c +++ /dev/null @@ -1,258 +0,0 @@ -/* -** $Id: lundump.c,v 2.22.1.1 2013/04/12 18:48:47 roberto Exp $ -** load precompiled Lua chunks -** See Copyright Notice in lua.h -*/ - -#include - -#define lundump_c -#define LUA_CORE - -#include "lua.h" - -#include "ldebug.h" -#include "ldo.h" -#include "lfunc.h" -#include "lmem.h" -#include "lobject.h" -#include "lstring.h" -#include "lundump.h" -#include "lzio.h" - -typedef struct { - lua_State* L; - ZIO* Z; - Mbuffer* b; - const char* name; -} LoadState; - -static l_noret error(LoadState* S, const char* why) -{ - luaO_pushfstring(S->L,"%s: %s precompiled chunk",S->name,why); - luaD_throw(S->L,LUA_ERRSYNTAX); -} - -#define LoadMem(S,b,n,size) LoadBlock(S,b,(n)*(size)) -#define LoadByte(S) (lu_byte)LoadChar(S) -#define LoadVar(S,x) LoadMem(S,&x,1,sizeof(x)) -#define LoadVector(S,b,n,size) LoadMem(S,b,n,size) - -#if !defined(luai_verifycode) -#define luai_verifycode(L,b,f) /* empty */ -#endif - -static void LoadBlock(LoadState* S, void* b, size_t size) -{ - if (luaZ_read(S->Z,b,size)!=0) error(S,"truncated"); -} - -static int LoadChar(LoadState* S) -{ - char x; - LoadVar(S,x); - return x; -} - -static int LoadInt(LoadState* S) -{ - int x; - LoadVar(S,x); - if (x<0) error(S,"corrupted"); - return x; -} - -static lua_Number LoadNumber(LoadState* S) -{ - lua_Number x; - LoadVar(S,x); - return x; -} - -static TString* LoadString(LoadState* S) -{ - size_t size; - LoadVar(S,size); - if (size==0) - return NULL; - else - { - char* s=luaZ_openspace(S->L,S->b,size); - LoadBlock(S,s,size*sizeof(char)); - return luaS_newlstr(S->L,s,size-1); /* remove trailing '\0' */ - } -} - -static void LoadCode(LoadState* S, Proto* f) -{ - int n=LoadInt(S); - f->code=luaM_newvector(S->L,n,Instruction); - f->sizecode=n; - LoadVector(S,f->code,n,sizeof(Instruction)); -} - -static void LoadFunction(LoadState* S, Proto* f); - -static void LoadConstants(LoadState* S, Proto* f) -{ - int i,n; - n=LoadInt(S); - f->k=luaM_newvector(S->L,n,TValue); - f->sizek=n; - for (i=0; ik[i]); - for (i=0; ik[i]; - int t=LoadChar(S); - switch (t) - { - case LUA_TNIL: - setnilvalue(o); - break; - case LUA_TBOOLEAN: - setbvalue(o,LoadChar(S)); - break; - case LUA_TNUMBER: - setnvalue(o,LoadNumber(S)); - break; - case LUA_TSTRING: - setsvalue2n(S->L,o,LoadString(S)); - break; - default: lua_assert(0); - } - } - n=LoadInt(S); - f->p=luaM_newvector(S->L,n,Proto*); - f->sizep=n; - for (i=0; ip[i]=NULL; - for (i=0; ip[i]=luaF_newproto(S->L); - LoadFunction(S,f->p[i]); - } -} - -static void LoadUpvalues(LoadState* S, Proto* f) -{ - int i,n; - n=LoadInt(S); - f->upvalues=luaM_newvector(S->L,n,Upvaldesc); - f->sizeupvalues=n; - for (i=0; iupvalues[i].name=NULL; - for (i=0; iupvalues[i].instack=LoadByte(S); - f->upvalues[i].idx=LoadByte(S); - } -} - -static void LoadDebug(LoadState* S, Proto* f) -{ - int i,n; - f->source=LoadString(S); - n=LoadInt(S); - f->lineinfo=luaM_newvector(S->L,n,int); - f->sizelineinfo=n; - LoadVector(S,f->lineinfo,n,sizeof(int)); - n=LoadInt(S); - f->locvars=luaM_newvector(S->L,n,LocVar); - f->sizelocvars=n; - for (i=0; ilocvars[i].varname=NULL; - for (i=0; ilocvars[i].varname=LoadString(S); - f->locvars[i].startpc=LoadInt(S); - f->locvars[i].endpc=LoadInt(S); - } - n=LoadInt(S); - for (i=0; iupvalues[i].name=LoadString(S); -} - -static void LoadFunction(LoadState* S, Proto* f) -{ - f->linedefined=LoadInt(S); - f->lastlinedefined=LoadInt(S); - f->numparams=LoadByte(S); - f->is_vararg=LoadByte(S); - f->maxstacksize=LoadByte(S); - LoadCode(S,f); - LoadConstants(S,f); - LoadUpvalues(S,f); - LoadDebug(S,f); -} - -/* the code below must be consistent with the code in luaU_header */ -#define N0 LUAC_HEADERSIZE -#define N1 (sizeof(LUA_SIGNATURE)-sizeof(char)) -#define N2 N1+2 -#define N3 N2+6 - -static void LoadHeader(LoadState* S) -{ - lu_byte h[LUAC_HEADERSIZE]; - lu_byte s[LUAC_HEADERSIZE]; - luaU_header(h); - memcpy(s,h,sizeof(char)); /* first char already read */ - LoadBlock(S,s+sizeof(char),LUAC_HEADERSIZE-sizeof(char)); - if (memcmp(h,s,N0)==0) return; - if (memcmp(h,s,N1)!=0) error(S,"not a"); - if (memcmp(h,s,N2)!=0) error(S,"version mismatch in"); - if (memcmp(h,s,N3)!=0) error(S,"incompatible"); else error(S,"corrupted"); -} - -/* -** load precompiled chunk -*/ -Closure* luaU_undump (lua_State* L, ZIO* Z, Mbuffer* buff, const char* name) -{ - LoadState S; - Closure* cl; - if (*name=='@' || *name=='=') - S.name=name+1; - else if (*name==LUA_SIGNATURE[0]) - S.name="binary string"; - else - S.name=name; - S.L=L; - S.Z=Z; - S.b=buff; - LoadHeader(&S); - cl=luaF_newLclosure(L,1); - setclLvalue(L,L->top,cl); incr_top(L); - cl->l.p=luaF_newproto(L); - LoadFunction(&S,cl->l.p); - if (cl->l.p->sizeupvalues != 1) - { - Proto* p=cl->l.p; - cl=luaF_newLclosure(L,cl->l.p->sizeupvalues); - cl->l.p=p; - setclLvalue(L,L->top-1,cl); - } - luai_verifycode(L,buff,cl->l.p); - return cl; -} - -#define MYINT(s) (s[0]-'0') -#define VERSION MYINT(LUA_VERSION_MAJOR)*16+MYINT(LUA_VERSION_MINOR) -#define FORMAT 0 /* this is the official format */ - -/* -* make header for precompiled chunks -* if you change the code below be sure to update LoadHeader and FORMAT above -* and LUAC_HEADERSIZE in lundump.h -*/ -void luaU_header (lu_byte* h) -{ - int x=1; - memcpy(h,LUA_SIGNATURE,sizeof(LUA_SIGNATURE)-sizeof(char)); - h+=sizeof(LUA_SIGNATURE)-sizeof(char); - *h++=cast_byte(VERSION); - *h++=cast_byte(FORMAT); - *h++=cast_byte(*(char*)&x); /* endianness */ - *h++=cast_byte(sizeof(int)); - *h++=cast_byte(sizeof(size_t)); - *h++=cast_byte(sizeof(Instruction)); - *h++=cast_byte(sizeof(lua_Number)); - *h++=cast_byte(((lua_Number)0.5)==0); /* is lua_Number integral? */ - memcpy(h,LUAC_TAIL,sizeof(LUAC_TAIL)-sizeof(char)); -} diff --git a/lib/lua-5.2/src/lundump.h b/lib/lua-5.2/src/lundump.h deleted file mode 100644 index 5255db2..0000000 --- a/lib/lua-5.2/src/lundump.h +++ /dev/null @@ -1,28 +0,0 @@ -/* -** $Id: lundump.h,v 1.39.1.1 2013/04/12 18:48:47 roberto Exp $ -** load precompiled Lua chunks -** See Copyright Notice in lua.h -*/ - -#ifndef lundump_h -#define lundump_h - -#include "lobject.h" -#include "lzio.h" - -/* load one chunk; from lundump.c */ -LUAI_FUNC Closure* luaU_undump (lua_State* L, ZIO* Z, Mbuffer* buff, const char* name); - -/* make header; from lundump.c */ -LUAI_FUNC void luaU_header (lu_byte* h); - -/* dump one chunk; from ldump.c */ -LUAI_FUNC int luaU_dump (lua_State* L, const Proto* f, lua_Writer w, void* data, int strip); - -/* data to catch conversion errors */ -#define LUAC_TAIL "\x19\x93\r\n\x1a\n" - -/* size in bytes of header of binary files */ -#define LUAC_HEADERSIZE (sizeof(LUA_SIGNATURE)-sizeof(char)+2+6+sizeof(LUAC_TAIL)-sizeof(char)) - -#endif diff --git a/lib/lua-5.2/src/lvm.c b/lib/lua-5.2/src/lvm.c deleted file mode 100644 index 141b9fd..0000000 --- a/lib/lua-5.2/src/lvm.c +++ /dev/null @@ -1,867 +0,0 @@ -/* -** $Id: lvm.c,v 2.155.1.1 2013/04/12 18:48:47 roberto Exp $ -** Lua virtual machine -** See Copyright Notice in lua.h -*/ - - -#include -#include -#include - -#define lvm_c -#define LUA_CORE - -#include "lua.h" - -#include "ldebug.h" -#include "ldo.h" -#include "lfunc.h" -#include "lgc.h" -#include "lobject.h" -#include "lopcodes.h" -#include "lstate.h" -#include "lstring.h" -#include "ltable.h" -#include "ltm.h" -#include "lvm.h" - - - -/* limit for table tag-method chains (to avoid loops) */ -#define MAXTAGLOOP 100 - - -const TValue *luaV_tonumber (const TValue *obj, TValue *n) { - lua_Number num; - if (ttisnumber(obj)) return obj; - if (ttisstring(obj) && luaO_str2d(svalue(obj), tsvalue(obj)->len, &num)) { - setnvalue(n, num); - return n; - } - else - return NULL; -} - - -int luaV_tostring (lua_State *L, StkId obj) { - if (!ttisnumber(obj)) - return 0; - else { - char s[LUAI_MAXNUMBER2STR]; - lua_Number n = nvalue(obj); - int l = lua_number2str(s, n); - setsvalue2s(L, obj, luaS_newlstr(L, s, l)); - return 1; - } -} - - -static void traceexec (lua_State *L) { - CallInfo *ci = L->ci; - lu_byte mask = L->hookmask; - int counthook = ((mask & LUA_MASKCOUNT) && L->hookcount == 0); - if (counthook) - resethookcount(L); /* reset count */ - if (ci->callstatus & CIST_HOOKYIELD) { /* called hook last time? */ - ci->callstatus &= ~CIST_HOOKYIELD; /* erase mark */ - return; /* do not call hook again (VM yielded, so it did not move) */ - } - if (counthook) - luaD_hook(L, LUA_HOOKCOUNT, -1); /* call count hook */ - if (mask & LUA_MASKLINE) { - Proto *p = ci_func(ci)->p; - int npc = pcRel(ci->u.l.savedpc, p); - int newline = getfuncline(p, npc); - if (npc == 0 || /* call linehook when enter a new function, */ - ci->u.l.savedpc <= L->oldpc || /* when jump back (loop), or when */ - newline != getfuncline(p, pcRel(L->oldpc, p))) /* enter a new line */ - luaD_hook(L, LUA_HOOKLINE, newline); /* call line hook */ - } - L->oldpc = ci->u.l.savedpc; - if (L->status == LUA_YIELD) { /* did hook yield? */ - if (counthook) - L->hookcount = 1; /* undo decrement to zero */ - ci->u.l.savedpc--; /* undo increment (resume will increment it again) */ - ci->callstatus |= CIST_HOOKYIELD; /* mark that it yielded */ - ci->func = L->top - 1; /* protect stack below results */ - luaD_throw(L, LUA_YIELD); - } -} - - -static void callTM (lua_State *L, const TValue *f, const TValue *p1, - const TValue *p2, TValue *p3, int hasres) { - ptrdiff_t result = savestack(L, p3); - setobj2s(L, L->top++, f); /* push function */ - setobj2s(L, L->top++, p1); /* 1st argument */ - setobj2s(L, L->top++, p2); /* 2nd argument */ - if (!hasres) /* no result? 'p3' is third argument */ - setobj2s(L, L->top++, p3); /* 3rd argument */ - /* metamethod may yield only when called from Lua code */ - luaD_call(L, L->top - (4 - hasres), hasres, isLua(L->ci)); - if (hasres) { /* if has result, move it to its place */ - p3 = restorestack(L, result); - setobjs2s(L, p3, --L->top); - } -} - - -void luaV_gettable (lua_State *L, const TValue *t, TValue *key, StkId val) { - int loop; - for (loop = 0; loop < MAXTAGLOOP; loop++) { - const TValue *tm; - if (ttistable(t)) { /* `t' is a table? */ - Table *h = hvalue(t); - const TValue *res = luaH_get(h, key); /* do a primitive get */ - if (!ttisnil(res) || /* result is not nil? */ - (tm = fasttm(L, h->metatable, TM_INDEX)) == NULL) { /* or no TM? */ - setobj2s(L, val, res); - return; - } - /* else will try the tag method */ - } - else if (ttisnil(tm = luaT_gettmbyobj(L, t, TM_INDEX))) - luaG_typeerror(L, t, "index"); - if (ttisfunction(tm)) { - callTM(L, tm, t, key, val, 1); - return; - } - t = tm; /* else repeat with 'tm' */ - } - luaG_runerror(L, "loop in gettable"); -} - - -void luaV_settable (lua_State *L, const TValue *t, TValue *key, StkId val) { - int loop; - for (loop = 0; loop < MAXTAGLOOP; loop++) { - const TValue *tm; - if (ttistable(t)) { /* `t' is a table? */ - Table *h = hvalue(t); - TValue *oldval = cast(TValue *, luaH_get(h, key)); - /* if previous value is not nil, there must be a previous entry - in the table; moreover, a metamethod has no relevance */ - if (!ttisnil(oldval) || - /* previous value is nil; must check the metamethod */ - ((tm = fasttm(L, h->metatable, TM_NEWINDEX)) == NULL && - /* no metamethod; is there a previous entry in the table? */ - (oldval != luaO_nilobject || - /* no previous entry; must create one. (The next test is - always true; we only need the assignment.) */ - (oldval = luaH_newkey(L, h, key), 1)))) { - /* no metamethod and (now) there is an entry with given key */ - setobj2t(L, oldval, val); /* assign new value to that entry */ - invalidateTMcache(h); - luaC_barrierback(L, obj2gco(h), val); - return; - } - /* else will try the metamethod */ - } - else /* not a table; check metamethod */ - if (ttisnil(tm = luaT_gettmbyobj(L, t, TM_NEWINDEX))) - luaG_typeerror(L, t, "index"); - /* there is a metamethod */ - if (ttisfunction(tm)) { - callTM(L, tm, t, key, val, 0); - return; - } - t = tm; /* else repeat with 'tm' */ - } - luaG_runerror(L, "loop in settable"); -} - - -static int call_binTM (lua_State *L, const TValue *p1, const TValue *p2, - StkId res, TMS event) { - const TValue *tm = luaT_gettmbyobj(L, p1, event); /* try first operand */ - if (ttisnil(tm)) - tm = luaT_gettmbyobj(L, p2, event); /* try second operand */ - if (ttisnil(tm)) return 0; - callTM(L, tm, p1, p2, res, 1); - return 1; -} - - -static const TValue *get_equalTM (lua_State *L, Table *mt1, Table *mt2, - TMS event) { - const TValue *tm1 = fasttm(L, mt1, event); - const TValue *tm2; - if (tm1 == NULL) return NULL; /* no metamethod */ - if (mt1 == mt2) return tm1; /* same metatables => same metamethods */ - tm2 = fasttm(L, mt2, event); - if (tm2 == NULL) return NULL; /* no metamethod */ - if (luaV_rawequalobj(tm1, tm2)) /* same metamethods? */ - return tm1; - return NULL; -} - - -static int call_orderTM (lua_State *L, const TValue *p1, const TValue *p2, - TMS event) { - if (!call_binTM(L, p1, p2, L->top, event)) - return -1; /* no metamethod */ - else - return !l_isfalse(L->top); -} - - -static int l_strcmp (const TString *ls, const TString *rs) { - const char *l = getstr(ls); - size_t ll = ls->tsv.len; - const char *r = getstr(rs); - size_t lr = rs->tsv.len; - for (;;) { - int temp = strcoll(l, r); - if (temp != 0) return temp; - else { /* strings are equal up to a `\0' */ - size_t len = strlen(l); /* index of first `\0' in both strings */ - if (len == lr) /* r is finished? */ - return (len == ll) ? 0 : 1; - else if (len == ll) /* l is finished? */ - return -1; /* l is smaller than r (because r is not finished) */ - /* both strings longer than `len'; go on comparing (after the `\0') */ - len++; - l += len; ll -= len; r += len; lr -= len; - } - } -} - - -int luaV_lessthan (lua_State *L, const TValue *l, const TValue *r) { - int res; - if (ttisnumber(l) && ttisnumber(r)) - return luai_numlt(L, nvalue(l), nvalue(r)); - else if (ttisstring(l) && ttisstring(r)) - return l_strcmp(rawtsvalue(l), rawtsvalue(r)) < 0; - else if ((res = call_orderTM(L, l, r, TM_LT)) < 0) - luaG_ordererror(L, l, r); - return res; -} - - -int luaV_lessequal (lua_State *L, const TValue *l, const TValue *r) { - int res; - if (ttisnumber(l) && ttisnumber(r)) - return luai_numle(L, nvalue(l), nvalue(r)); - else if (ttisstring(l) && ttisstring(r)) - return l_strcmp(rawtsvalue(l), rawtsvalue(r)) <= 0; - else if ((res = call_orderTM(L, l, r, TM_LE)) >= 0) /* first try `le' */ - return res; - else if ((res = call_orderTM(L, r, l, TM_LT)) < 0) /* else try `lt' */ - luaG_ordererror(L, l, r); - return !res; -} - - -/* -** equality of Lua values. L == NULL means raw equality (no metamethods) -*/ -int luaV_equalobj_ (lua_State *L, const TValue *t1, const TValue *t2) { - const TValue *tm; - lua_assert(ttisequal(t1, t2)); - switch (ttype(t1)) { - case LUA_TNIL: return 1; - case LUA_TNUMBER: return luai_numeq(nvalue(t1), nvalue(t2)); - case LUA_TBOOLEAN: return bvalue(t1) == bvalue(t2); /* true must be 1 !! */ - case LUA_TLIGHTUSERDATA: return pvalue(t1) == pvalue(t2); - case LUA_TLCF: return fvalue(t1) == fvalue(t2); - case LUA_TSHRSTR: return eqshrstr(rawtsvalue(t1), rawtsvalue(t2)); - case LUA_TLNGSTR: return luaS_eqlngstr(rawtsvalue(t1), rawtsvalue(t2)); - case LUA_TUSERDATA: { - if (uvalue(t1) == uvalue(t2)) return 1; - else if (L == NULL) return 0; - tm = get_equalTM(L, uvalue(t1)->metatable, uvalue(t2)->metatable, TM_EQ); - break; /* will try TM */ - } - case LUA_TTABLE: { - if (hvalue(t1) == hvalue(t2)) return 1; - else if (L == NULL) return 0; - tm = get_equalTM(L, hvalue(t1)->metatable, hvalue(t2)->metatable, TM_EQ); - break; /* will try TM */ - } - default: - lua_assert(iscollectable(t1)); - return gcvalue(t1) == gcvalue(t2); - } - if (tm == NULL) return 0; /* no TM? */ - callTM(L, tm, t1, t2, L->top, 1); /* call TM */ - return !l_isfalse(L->top); -} - - -void luaV_concat (lua_State *L, int total) { - lua_assert(total >= 2); - do { - StkId top = L->top; - int n = 2; /* number of elements handled in this pass (at least 2) */ - if (!(ttisstring(top-2) || ttisnumber(top-2)) || !tostring(L, top-1)) { - if (!call_binTM(L, top-2, top-1, top-2, TM_CONCAT)) - luaG_concaterror(L, top-2, top-1); - } - else if (tsvalue(top-1)->len == 0) /* second operand is empty? */ - (void)tostring(L, top - 2); /* result is first operand */ - else if (ttisstring(top-2) && tsvalue(top-2)->len == 0) { - setobjs2s(L, top - 2, top - 1); /* result is second op. */ - } - else { - /* at least two non-empty string values; get as many as possible */ - size_t tl = tsvalue(top-1)->len; - char *buffer; - int i; - /* collect total length */ - for (i = 1; i < total && tostring(L, top-i-1); i++) { - size_t l = tsvalue(top-i-1)->len; - if (l >= (MAX_SIZET/sizeof(char)) - tl) - luaG_runerror(L, "string length overflow"); - tl += l; - } - buffer = luaZ_openspace(L, &G(L)->buff, tl); - tl = 0; - n = i; - do { /* concat all strings */ - size_t l = tsvalue(top-i)->len; - memcpy(buffer+tl, svalue(top-i), l * sizeof(char)); - tl += l; - } while (--i > 0); - setsvalue2s(L, top-n, luaS_newlstr(L, buffer, tl)); - } - total -= n-1; /* got 'n' strings to create 1 new */ - L->top -= n-1; /* popped 'n' strings and pushed one */ - } while (total > 1); /* repeat until only 1 result left */ -} - - -void luaV_objlen (lua_State *L, StkId ra, const TValue *rb) { - const TValue *tm; - switch (ttypenv(rb)) { - case LUA_TTABLE: { - Table *h = hvalue(rb); - tm = fasttm(L, h->metatable, TM_LEN); - if (tm) break; /* metamethod? break switch to call it */ - setnvalue(ra, cast_num(luaH_getn(h))); /* else primitive len */ - return; - } - case LUA_TSTRING: { - setnvalue(ra, cast_num(tsvalue(rb)->len)); - return; - } - default: { /* try metamethod */ - tm = luaT_gettmbyobj(L, rb, TM_LEN); - if (ttisnil(tm)) /* no metamethod? */ - luaG_typeerror(L, rb, "get length of"); - break; - } - } - callTM(L, tm, rb, rb, ra, 1); -} - - -void luaV_arith (lua_State *L, StkId ra, const TValue *rb, - const TValue *rc, TMS op) { - TValue tempb, tempc; - const TValue *b, *c; - if ((b = luaV_tonumber(rb, &tempb)) != NULL && - (c = luaV_tonumber(rc, &tempc)) != NULL) { - lua_Number res = luaO_arith(op - TM_ADD + LUA_OPADD, nvalue(b), nvalue(c)); - setnvalue(ra, res); - } - else if (!call_binTM(L, rb, rc, ra, op)) - luaG_aritherror(L, rb, rc); -} - - -/* -** check whether cached closure in prototype 'p' may be reused, that is, -** whether there is a cached closure with the same upvalues needed by -** new closure to be created. -*/ -static Closure *getcached (Proto *p, UpVal **encup, StkId base) { - Closure *c = p->cache; - if (c != NULL) { /* is there a cached closure? */ - int nup = p->sizeupvalues; - Upvaldesc *uv = p->upvalues; - int i; - for (i = 0; i < nup; i++) { /* check whether it has right upvalues */ - TValue *v = uv[i].instack ? base + uv[i].idx : encup[uv[i].idx]->v; - if (c->l.upvals[i]->v != v) - return NULL; /* wrong upvalue; cannot reuse closure */ - } - } - return c; /* return cached closure (or NULL if no cached closure) */ -} - - -/* -** create a new Lua closure, push it in the stack, and initialize -** its upvalues. Note that the call to 'luaC_barrierproto' must come -** before the assignment to 'p->cache', as the function needs the -** original value of that field. -*/ -static void pushclosure (lua_State *L, Proto *p, UpVal **encup, StkId base, - StkId ra) { - int nup = p->sizeupvalues; - Upvaldesc *uv = p->upvalues; - int i; - Closure *ncl = luaF_newLclosure(L, nup); - ncl->l.p = p; - setclLvalue(L, ra, ncl); /* anchor new closure in stack */ - for (i = 0; i < nup; i++) { /* fill in its upvalues */ - if (uv[i].instack) /* upvalue refers to local variable? */ - ncl->l.upvals[i] = luaF_findupval(L, base + uv[i].idx); - else /* get upvalue from enclosing function */ - ncl->l.upvals[i] = encup[uv[i].idx]; - } - luaC_barrierproto(L, p, ncl); - p->cache = ncl; /* save it on cache for reuse */ -} - - -/* -** finish execution of an opcode interrupted by an yield -*/ -void luaV_finishOp (lua_State *L) { - CallInfo *ci = L->ci; - StkId base = ci->u.l.base; - Instruction inst = *(ci->u.l.savedpc - 1); /* interrupted instruction */ - OpCode op = GET_OPCODE(inst); - switch (op) { /* finish its execution */ - case OP_ADD: case OP_SUB: case OP_MUL: case OP_DIV: - case OP_MOD: case OP_POW: case OP_UNM: case OP_LEN: - case OP_GETTABUP: case OP_GETTABLE: case OP_SELF: { - setobjs2s(L, base + GETARG_A(inst), --L->top); - break; - } - case OP_LE: case OP_LT: case OP_EQ: { - int res = !l_isfalse(L->top - 1); - L->top--; - /* metamethod should not be called when operand is K */ - lua_assert(!ISK(GETARG_B(inst))); - if (op == OP_LE && /* "<=" using "<" instead? */ - ttisnil(luaT_gettmbyobj(L, base + GETARG_B(inst), TM_LE))) - res = !res; /* invert result */ - lua_assert(GET_OPCODE(*ci->u.l.savedpc) == OP_JMP); - if (res != GETARG_A(inst)) /* condition failed? */ - ci->u.l.savedpc++; /* skip jump instruction */ - break; - } - case OP_CONCAT: { - StkId top = L->top - 1; /* top when 'call_binTM' was called */ - int b = GETARG_B(inst); /* first element to concatenate */ - int total = cast_int(top - 1 - (base + b)); /* yet to concatenate */ - setobj2s(L, top - 2, top); /* put TM result in proper position */ - if (total > 1) { /* are there elements to concat? */ - L->top = top - 1; /* top is one after last element (at top-2) */ - luaV_concat(L, total); /* concat them (may yield again) */ - } - /* move final result to final position */ - setobj2s(L, ci->u.l.base + GETARG_A(inst), L->top - 1); - L->top = ci->top; /* restore top */ - break; - } - case OP_TFORCALL: { - lua_assert(GET_OPCODE(*ci->u.l.savedpc) == OP_TFORLOOP); - L->top = ci->top; /* correct top */ - break; - } - case OP_CALL: { - if (GETARG_C(inst) - 1 >= 0) /* nresults >= 0? */ - L->top = ci->top; /* adjust results */ - break; - } - case OP_TAILCALL: case OP_SETTABUP: case OP_SETTABLE: - break; - default: lua_assert(0); - } -} - - - -/* -** some macros for common tasks in `luaV_execute' -*/ - -#if !defined luai_runtimecheck -#define luai_runtimecheck(L, c) /* void */ -#endif - - -#define RA(i) (base+GETARG_A(i)) -/* to be used after possible stack reallocation */ -#define RB(i) check_exp(getBMode(GET_OPCODE(i)) == OpArgR, base+GETARG_B(i)) -#define RC(i) check_exp(getCMode(GET_OPCODE(i)) == OpArgR, base+GETARG_C(i)) -#define RKB(i) check_exp(getBMode(GET_OPCODE(i)) == OpArgK, \ - ISK(GETARG_B(i)) ? k+INDEXK(GETARG_B(i)) : base+GETARG_B(i)) -#define RKC(i) check_exp(getCMode(GET_OPCODE(i)) == OpArgK, \ - ISK(GETARG_C(i)) ? k+INDEXK(GETARG_C(i)) : base+GETARG_C(i)) -#define KBx(i) \ - (k + (GETARG_Bx(i) != 0 ? GETARG_Bx(i) - 1 : GETARG_Ax(*ci->u.l.savedpc++))) - - -/* execute a jump instruction */ -#define dojump(ci,i,e) \ - { int a = GETARG_A(i); \ - if (a > 0) luaF_close(L, ci->u.l.base + a - 1); \ - ci->u.l.savedpc += GETARG_sBx(i) + e; } - -/* for test instructions, execute the jump instruction that follows it */ -#define donextjump(ci) { i = *ci->u.l.savedpc; dojump(ci, i, 1); } - - -#define Protect(x) { {x;}; base = ci->u.l.base; } - -#define checkGC(L,c) \ - Protect( luaC_condGC(L,{L->top = (c); /* limit of live values */ \ - luaC_step(L); \ - L->top = ci->top;}) /* restore top */ \ - luai_threadyield(L); ) - - -#define arith_op(op,tm) { \ - TValue *rb = RKB(i); \ - TValue *rc = RKC(i); \ - if (ttisnumber(rb) && ttisnumber(rc)) { \ - lua_Number nb = nvalue(rb), nc = nvalue(rc); \ - setnvalue(ra, op(L, nb, nc)); \ - } \ - else { Protect(luaV_arith(L, ra, rb, rc, tm)); } } - - -#define vmdispatch(o) switch(o) -#define vmcase(l,b) case l: {b} break; -#define vmcasenb(l,b) case l: {b} /* nb = no break */ - -void luaV_execute (lua_State *L) { - CallInfo *ci = L->ci; - LClosure *cl; - TValue *k; - StkId base; - newframe: /* reentry point when frame changes (call/return) */ - lua_assert(ci == L->ci); - cl = clLvalue(ci->func); - k = cl->p->k; - base = ci->u.l.base; - /* main loop of interpreter */ - for (;;) { - Instruction i = *(ci->u.l.savedpc++); - StkId ra; - if ((L->hookmask & (LUA_MASKLINE | LUA_MASKCOUNT)) && - (--L->hookcount == 0 || L->hookmask & LUA_MASKLINE)) { - Protect(traceexec(L)); - } - /* WARNING: several calls may realloc the stack and invalidate `ra' */ - ra = RA(i); - lua_assert(base == ci->u.l.base); - lua_assert(base <= L->top && L->top < L->stack + L->stacksize); - vmdispatch (GET_OPCODE(i)) { - vmcase(OP_MOVE, - setobjs2s(L, ra, RB(i)); - ) - vmcase(OP_LOADK, - TValue *rb = k + GETARG_Bx(i); - setobj2s(L, ra, rb); - ) - vmcase(OP_LOADKX, - TValue *rb; - lua_assert(GET_OPCODE(*ci->u.l.savedpc) == OP_EXTRAARG); - rb = k + GETARG_Ax(*ci->u.l.savedpc++); - setobj2s(L, ra, rb); - ) - vmcase(OP_LOADBOOL, - setbvalue(ra, GETARG_B(i)); - if (GETARG_C(i)) ci->u.l.savedpc++; /* skip next instruction (if C) */ - ) - vmcase(OP_LOADNIL, - int b = GETARG_B(i); - do { - setnilvalue(ra++); - } while (b--); - ) - vmcase(OP_GETUPVAL, - int b = GETARG_B(i); - setobj2s(L, ra, cl->upvals[b]->v); - ) - vmcase(OP_GETTABUP, - int b = GETARG_B(i); - Protect(luaV_gettable(L, cl->upvals[b]->v, RKC(i), ra)); - ) - vmcase(OP_GETTABLE, - Protect(luaV_gettable(L, RB(i), RKC(i), ra)); - ) - vmcase(OP_SETTABUP, - int a = GETARG_A(i); - Protect(luaV_settable(L, cl->upvals[a]->v, RKB(i), RKC(i))); - ) - vmcase(OP_SETUPVAL, - UpVal *uv = cl->upvals[GETARG_B(i)]; - setobj(L, uv->v, ra); - luaC_barrier(L, uv, ra); - ) - vmcase(OP_SETTABLE, - Protect(luaV_settable(L, ra, RKB(i), RKC(i))); - ) - vmcase(OP_NEWTABLE, - int b = GETARG_B(i); - int c = GETARG_C(i); - Table *t = luaH_new(L); - sethvalue(L, ra, t); - if (b != 0 || c != 0) - luaH_resize(L, t, luaO_fb2int(b), luaO_fb2int(c)); - checkGC(L, ra + 1); - ) - vmcase(OP_SELF, - StkId rb = RB(i); - setobjs2s(L, ra+1, rb); - Protect(luaV_gettable(L, rb, RKC(i), ra)); - ) - vmcase(OP_ADD, - arith_op(luai_numadd, TM_ADD); - ) - vmcase(OP_SUB, - arith_op(luai_numsub, TM_SUB); - ) - vmcase(OP_MUL, - arith_op(luai_nummul, TM_MUL); - ) - vmcase(OP_DIV, - arith_op(luai_numdiv, TM_DIV); - ) - vmcase(OP_MOD, - arith_op(luai_nummod, TM_MOD); - ) - vmcase(OP_POW, - arith_op(luai_numpow, TM_POW); - ) - vmcase(OP_UNM, - TValue *rb = RB(i); - if (ttisnumber(rb)) { - lua_Number nb = nvalue(rb); - setnvalue(ra, luai_numunm(L, nb)); - } - else { - Protect(luaV_arith(L, ra, rb, rb, TM_UNM)); - } - ) - vmcase(OP_NOT, - TValue *rb = RB(i); - int res = l_isfalse(rb); /* next assignment may change this value */ - setbvalue(ra, res); - ) - vmcase(OP_LEN, - Protect(luaV_objlen(L, ra, RB(i))); - ) - vmcase(OP_CONCAT, - int b = GETARG_B(i); - int c = GETARG_C(i); - StkId rb; - L->top = base + c + 1; /* mark the end of concat operands */ - Protect(luaV_concat(L, c - b + 1)); - ra = RA(i); /* 'luav_concat' may invoke TMs and move the stack */ - rb = b + base; - setobjs2s(L, ra, rb); - checkGC(L, (ra >= rb ? ra + 1 : rb)); - L->top = ci->top; /* restore top */ - ) - vmcase(OP_JMP, - dojump(ci, i, 0); - ) - vmcase(OP_EQ, - TValue *rb = RKB(i); - TValue *rc = RKC(i); - Protect( - if (cast_int(equalobj(L, rb, rc)) != GETARG_A(i)) - ci->u.l.savedpc++; - else - donextjump(ci); - ) - ) - vmcase(OP_LT, - Protect( - if (luaV_lessthan(L, RKB(i), RKC(i)) != GETARG_A(i)) - ci->u.l.savedpc++; - else - donextjump(ci); - ) - ) - vmcase(OP_LE, - Protect( - if (luaV_lessequal(L, RKB(i), RKC(i)) != GETARG_A(i)) - ci->u.l.savedpc++; - else - donextjump(ci); - ) - ) - vmcase(OP_TEST, - if (GETARG_C(i) ? l_isfalse(ra) : !l_isfalse(ra)) - ci->u.l.savedpc++; - else - donextjump(ci); - ) - vmcase(OP_TESTSET, - TValue *rb = RB(i); - if (GETARG_C(i) ? l_isfalse(rb) : !l_isfalse(rb)) - ci->u.l.savedpc++; - else { - setobjs2s(L, ra, rb); - donextjump(ci); - } - ) - vmcase(OP_CALL, - int b = GETARG_B(i); - int nresults = GETARG_C(i) - 1; - if (b != 0) L->top = ra+b; /* else previous instruction set top */ - if (luaD_precall(L, ra, nresults)) { /* C function? */ - if (nresults >= 0) L->top = ci->top; /* adjust results */ - base = ci->u.l.base; - } - else { /* Lua function */ - ci = L->ci; - ci->callstatus |= CIST_REENTRY; - goto newframe; /* restart luaV_execute over new Lua function */ - } - ) - vmcase(OP_TAILCALL, - int b = GETARG_B(i); - if (b != 0) L->top = ra+b; /* else previous instruction set top */ - lua_assert(GETARG_C(i) - 1 == LUA_MULTRET); - if (luaD_precall(L, ra, LUA_MULTRET)) /* C function? */ - base = ci->u.l.base; - else { - /* tail call: put called frame (n) in place of caller one (o) */ - CallInfo *nci = L->ci; /* called frame */ - CallInfo *oci = nci->previous; /* caller frame */ - StkId nfunc = nci->func; /* called function */ - StkId ofunc = oci->func; /* caller function */ - /* last stack slot filled by 'precall' */ - StkId lim = nci->u.l.base + getproto(nfunc)->numparams; - int aux; - /* close all upvalues from previous call */ - if (cl->p->sizep > 0) luaF_close(L, oci->u.l.base); - /* move new frame into old one */ - for (aux = 0; nfunc + aux < lim; aux++) - setobjs2s(L, ofunc + aux, nfunc + aux); - oci->u.l.base = ofunc + (nci->u.l.base - nfunc); /* correct base */ - oci->top = L->top = ofunc + (L->top - nfunc); /* correct top */ - oci->u.l.savedpc = nci->u.l.savedpc; - oci->callstatus |= CIST_TAIL; /* function was tail called */ - ci = L->ci = oci; /* remove new frame */ - lua_assert(L->top == oci->u.l.base + getproto(ofunc)->maxstacksize); - goto newframe; /* restart luaV_execute over new Lua function */ - } - ) - vmcasenb(OP_RETURN, - int b = GETARG_B(i); - if (b != 0) L->top = ra+b-1; - if (cl->p->sizep > 0) luaF_close(L, base); - b = luaD_poscall(L, ra); - if (!(ci->callstatus & CIST_REENTRY)) /* 'ci' still the called one */ - return; /* external invocation: return */ - else { /* invocation via reentry: continue execution */ - ci = L->ci; - if (b) L->top = ci->top; - lua_assert(isLua(ci)); - lua_assert(GET_OPCODE(*((ci)->u.l.savedpc - 1)) == OP_CALL); - goto newframe; /* restart luaV_execute over new Lua function */ - } - ) - vmcase(OP_FORLOOP, - lua_Number step = nvalue(ra+2); - lua_Number idx = luai_numadd(L, nvalue(ra), step); /* increment index */ - lua_Number limit = nvalue(ra+1); - if (luai_numlt(L, 0, step) ? luai_numle(L, idx, limit) - : luai_numle(L, limit, idx)) { - ci->u.l.savedpc += GETARG_sBx(i); /* jump back */ - setnvalue(ra, idx); /* update internal index... */ - setnvalue(ra+3, idx); /* ...and external index */ - } - ) - vmcase(OP_FORPREP, - const TValue *init = ra; - const TValue *plimit = ra+1; - const TValue *pstep = ra+2; - if (!tonumber(init, ra)) - luaG_runerror(L, LUA_QL("for") " initial value must be a number"); - else if (!tonumber(plimit, ra+1)) - luaG_runerror(L, LUA_QL("for") " limit must be a number"); - else if (!tonumber(pstep, ra+2)) - luaG_runerror(L, LUA_QL("for") " step must be a number"); - setnvalue(ra, luai_numsub(L, nvalue(ra), nvalue(pstep))); - ci->u.l.savedpc += GETARG_sBx(i); - ) - vmcasenb(OP_TFORCALL, - StkId cb = ra + 3; /* call base */ - setobjs2s(L, cb+2, ra+2); - setobjs2s(L, cb+1, ra+1); - setobjs2s(L, cb, ra); - L->top = cb + 3; /* func. + 2 args (state and index) */ - Protect(luaD_call(L, cb, GETARG_C(i), 1)); - L->top = ci->top; - i = *(ci->u.l.savedpc++); /* go to next instruction */ - ra = RA(i); - lua_assert(GET_OPCODE(i) == OP_TFORLOOP); - goto l_tforloop; - ) - vmcase(OP_TFORLOOP, - l_tforloop: - if (!ttisnil(ra + 1)) { /* continue loop? */ - setobjs2s(L, ra, ra + 1); /* save control variable */ - ci->u.l.savedpc += GETARG_sBx(i); /* jump back */ - } - ) - vmcase(OP_SETLIST, - int n = GETARG_B(i); - int c = GETARG_C(i); - int last; - Table *h; - if (n == 0) n = cast_int(L->top - ra) - 1; - if (c == 0) { - lua_assert(GET_OPCODE(*ci->u.l.savedpc) == OP_EXTRAARG); - c = GETARG_Ax(*ci->u.l.savedpc++); - } - luai_runtimecheck(L, ttistable(ra)); - h = hvalue(ra); - last = ((c-1)*LFIELDS_PER_FLUSH) + n; - if (last > h->sizearray) /* needs more space? */ - luaH_resizearray(L, h, last); /* pre-allocate it at once */ - for (; n > 0; n--) { - TValue *val = ra+n; - luaH_setint(L, h, last--, val); - luaC_barrierback(L, obj2gco(h), val); - } - L->top = ci->top; /* correct top (in case of previous open call) */ - ) - vmcase(OP_CLOSURE, - Proto *p = cl->p->p[GETARG_Bx(i)]; - Closure *ncl = getcached(p, cl->upvals, base); /* cached closure */ - if (ncl == NULL) /* no match? */ - pushclosure(L, p, cl->upvals, base, ra); /* create a new one */ - else - setclLvalue(L, ra, ncl); /* push cashed closure */ - checkGC(L, ra + 1); - ) - vmcase(OP_VARARG, - int b = GETARG_B(i) - 1; - int j; - int n = cast_int(base - ci->func) - cl->p->numparams - 1; - if (b < 0) { /* B == 0? */ - b = n; /* get all var. arguments */ - Protect(luaD_checkstack(L, n)); - ra = RA(i); /* previous call may change the stack */ - L->top = ra + n; - } - for (j = 0; j < b; j++) { - if (j < n) { - setobjs2s(L, ra + j, base - n + j); - } - else { - setnilvalue(ra + j); - } - } - ) - vmcase(OP_EXTRAARG, - lua_assert(0); - ) - } - } -} - diff --git a/lib/lua-5.2/src/lvm.h b/lib/lua-5.2/src/lvm.h deleted file mode 100644 index 5380270..0000000 --- a/lib/lua-5.2/src/lvm.h +++ /dev/null @@ -1,44 +0,0 @@ -/* -** $Id: lvm.h,v 2.18.1.1 2013/04/12 18:48:47 roberto Exp $ -** Lua virtual machine -** See Copyright Notice in lua.h -*/ - -#ifndef lvm_h -#define lvm_h - - -#include "ldo.h" -#include "lobject.h" -#include "ltm.h" - - -#define tostring(L,o) (ttisstring(o) || (luaV_tostring(L, o))) - -#define tonumber(o,n) (ttisnumber(o) || (((o) = luaV_tonumber(o,n)) != NULL)) - -#define equalobj(L,o1,o2) (ttisequal(o1, o2) && luaV_equalobj_(L, o1, o2)) - -#define luaV_rawequalobj(o1,o2) equalobj(NULL,o1,o2) - - -/* not to called directly */ -LUAI_FUNC int luaV_equalobj_ (lua_State *L, const TValue *t1, const TValue *t2); - - -LUAI_FUNC int luaV_lessthan (lua_State *L, const TValue *l, const TValue *r); -LUAI_FUNC int luaV_lessequal (lua_State *L, const TValue *l, const TValue *r); -LUAI_FUNC const TValue *luaV_tonumber (const TValue *obj, TValue *n); -LUAI_FUNC int luaV_tostring (lua_State *L, StkId obj); -LUAI_FUNC void luaV_gettable (lua_State *L, const TValue *t, TValue *key, - StkId val); -LUAI_FUNC void luaV_settable (lua_State *L, const TValue *t, TValue *key, - StkId val); -LUAI_FUNC void luaV_finishOp (lua_State *L); -LUAI_FUNC void luaV_execute (lua_State *L); -LUAI_FUNC void luaV_concat (lua_State *L, int total); -LUAI_FUNC void luaV_arith (lua_State *L, StkId ra, const TValue *rb, - const TValue *rc, TMS op); -LUAI_FUNC void luaV_objlen (lua_State *L, StkId ra, const TValue *rb); - -#endif diff --git a/lib/lua-5.2/src/lzio.c b/lib/lua-5.2/src/lzio.c deleted file mode 100644 index 20efea9..0000000 --- a/lib/lua-5.2/src/lzio.c +++ /dev/null @@ -1,76 +0,0 @@ -/* -** $Id: lzio.c,v 1.35.1.1 2013/04/12 18:48:47 roberto Exp $ -** Buffered streams -** See Copyright Notice in lua.h -*/ - - -#include - -#define lzio_c -#define LUA_CORE - -#include "lua.h" - -#include "llimits.h" -#include "lmem.h" -#include "lstate.h" -#include "lzio.h" - - -int luaZ_fill (ZIO *z) { - size_t size; - lua_State *L = z->L; - const char *buff; - lua_unlock(L); - buff = z->reader(L, z->data, &size); - lua_lock(L); - if (buff == NULL || size == 0) - return EOZ; - z->n = size - 1; /* discount char being returned */ - z->p = buff; - return cast_uchar(*(z->p++)); -} - - -void luaZ_init (lua_State *L, ZIO *z, lua_Reader reader, void *data) { - z->L = L; - z->reader = reader; - z->data = data; - z->n = 0; - z->p = NULL; -} - - -/* --------------------------------------------------------------- read --- */ -size_t luaZ_read (ZIO *z, void *b, size_t n) { - while (n) { - size_t m; - if (z->n == 0) { /* no bytes in buffer? */ - if (luaZ_fill(z) == EOZ) /* try to read more */ - return n; /* no more input; return number of missing bytes */ - else { - z->n++; /* luaZ_fill consumed first byte; put it back */ - z->p--; - } - } - m = (n <= z->n) ? n : z->n; /* min. between n and z->n */ - memcpy(b, z->p, m); - z->n -= m; - z->p += m; - b = (char *)b + m; - n -= m; - } - return 0; -} - -/* ------------------------------------------------------------------------ */ -char *luaZ_openspace (lua_State *L, Mbuffer *buff, size_t n) { - if (n > buff->buffsize) { - if (n < LUA_MINBUFFER) n = LUA_MINBUFFER; - luaZ_resizebuffer(L, buff, n); - } - return buff->buffer; -} - - diff --git a/lib/lua-5.2/src/lzio.h b/lib/lua-5.2/src/lzio.h deleted file mode 100644 index 441f747..0000000 --- a/lib/lua-5.2/src/lzio.h +++ /dev/null @@ -1,65 +0,0 @@ -/* -** $Id: lzio.h,v 1.26.1.1 2013/04/12 18:48:47 roberto Exp $ -** Buffered streams -** See Copyright Notice in lua.h -*/ - - -#ifndef lzio_h -#define lzio_h - -#include "lua.h" - -#include "lmem.h" - - -#define EOZ (-1) /* end of stream */ - -typedef struct Zio ZIO; - -#define zgetc(z) (((z)->n--)>0 ? cast_uchar(*(z)->p++) : luaZ_fill(z)) - - -typedef struct Mbuffer { - char *buffer; - size_t n; - size_t buffsize; -} Mbuffer; - -#define luaZ_initbuffer(L, buff) ((buff)->buffer = NULL, (buff)->buffsize = 0) - -#define luaZ_buffer(buff) ((buff)->buffer) -#define luaZ_sizebuffer(buff) ((buff)->buffsize) -#define luaZ_bufflen(buff) ((buff)->n) - -#define luaZ_resetbuffer(buff) ((buff)->n = 0) - - -#define luaZ_resizebuffer(L, buff, size) \ - (luaM_reallocvector(L, (buff)->buffer, (buff)->buffsize, size, char), \ - (buff)->buffsize = size) - -#define luaZ_freebuffer(L, buff) luaZ_resizebuffer(L, buff, 0) - - -LUAI_FUNC char *luaZ_openspace (lua_State *L, Mbuffer *buff, size_t n); -LUAI_FUNC void luaZ_init (lua_State *L, ZIO *z, lua_Reader reader, - void *data); -LUAI_FUNC size_t luaZ_read (ZIO* z, void* b, size_t n); /* read next n bytes */ - - - -/* --------- Private Part ------------------ */ - -struct Zio { - size_t n; /* bytes still unread */ - const char *p; /* current position in buffer */ - lua_Reader reader; /* reader function */ - void* data; /* additional data */ - lua_State *L; /* Lua state (for reader) */ -}; - - -LUAI_FUNC int luaZ_fill (ZIO *z); - -#endif diff --git a/lib/lua-5.3/Makefile b/lib/lua-5.3/Makefile deleted file mode 100644 index a2820e0..0000000 --- a/lib/lua-5.3/Makefile +++ /dev/null @@ -1,114 +0,0 @@ -# Makefile for installing Lua -# See doc/readme.html for installation and customization instructions. - -# == CHANGE THE SETTINGS BELOW TO SUIT YOUR ENVIRONMENT ======================= - -# Your platform. See PLATS for possible values. -PLAT= none - -# Where to install. The installation starts in the src and doc directories, -# so take care if INSTALL_TOP is not an absolute path. See the local target. -# You may want to make INSTALL_LMOD and INSTALL_CMOD consistent with -# LUA_ROOT, LUA_LDIR, and LUA_CDIR in luaconf.h. -INSTALL_TOP= /usr/local -INSTALL_BIN= $(INSTALL_TOP)/bin -INSTALL_INC= $(INSTALL_TOP)/include -INSTALL_LIB= $(INSTALL_TOP)/lib -INSTALL_MAN= $(INSTALL_TOP)/man/man1 -INSTALL_LMOD= $(INSTALL_TOP)/share/lua/$V -INSTALL_CMOD= $(INSTALL_TOP)/lib/lua/$V - -# How to install. If your install program does not support "-p", then -# you may have to run ranlib on the installed liblua.a. -INSTALL= install -p -INSTALL_EXEC= $(INSTALL) -m 0755 -INSTALL_DATA= $(INSTALL) -m 0644 -# -# If you don't have "install" you can use "cp" instead. -# INSTALL= cp -p -# INSTALL_EXEC= $(INSTALL) -# INSTALL_DATA= $(INSTALL) - -# Other utilities. -MKDIR= mkdir -p -RM= rm -f - -# == END OF USER SETTINGS -- NO NEED TO CHANGE ANYTHING BELOW THIS LINE ======= - -# Convenience platforms targets. -PLATS= aix bsd c89 freebsd generic linux macosx mingw posix solaris - -# What to install. -TO_BIN= lua luac -TO_INC= lua.h luaconf.h lualib.h lauxlib.h lua.hpp -TO_LIB= liblua.a -TO_MAN= lua.1 luac.1 - -# Lua version and release. -V= 5.3 -R= $V.6 - -# Targets start here. -all: $(PLAT) - -$(PLATS) clean: - cd src && $(MAKE) $@ - -test: dummy - src/lua -v - -install: dummy - cd src && $(MKDIR) $(INSTALL_BIN) $(INSTALL_INC) $(INSTALL_LIB) $(INSTALL_MAN) $(INSTALL_LMOD) $(INSTALL_CMOD) - cd src && $(INSTALL_EXEC) $(TO_BIN) $(INSTALL_BIN) - cd src && $(INSTALL_DATA) $(TO_INC) $(INSTALL_INC) - cd src && $(INSTALL_DATA) $(TO_LIB) $(INSTALL_LIB) - cd doc && $(INSTALL_DATA) $(TO_MAN) $(INSTALL_MAN) - -uninstall: - cd src && cd $(INSTALL_BIN) && $(RM) $(TO_BIN) - cd src && cd $(INSTALL_INC) && $(RM) $(TO_INC) - cd src && cd $(INSTALL_LIB) && $(RM) $(TO_LIB) - cd doc && cd $(INSTALL_MAN) && $(RM) $(TO_MAN) - -local: - $(MAKE) install INSTALL_TOP=../install - -none: - @echo "Please do 'make PLATFORM' where PLATFORM is one of these:" - @echo " $(PLATS)" - @echo "See doc/readme.html for complete instructions." - -# make may get confused with test/ and install/ -dummy: - -# echo config parameters -echo: - @cd src && $(MAKE) -s echo - @echo "PLAT= $(PLAT)" - @echo "V= $V" - @echo "R= $R" - @echo "TO_BIN= $(TO_BIN)" - @echo "TO_INC= $(TO_INC)" - @echo "TO_LIB= $(TO_LIB)" - @echo "TO_MAN= $(TO_MAN)" - @echo "INSTALL_TOP= $(INSTALL_TOP)" - @echo "INSTALL_BIN= $(INSTALL_BIN)" - @echo "INSTALL_INC= $(INSTALL_INC)" - @echo "INSTALL_LIB= $(INSTALL_LIB)" - @echo "INSTALL_MAN= $(INSTALL_MAN)" - @echo "INSTALL_LMOD= $(INSTALL_LMOD)" - @echo "INSTALL_CMOD= $(INSTALL_CMOD)" - @echo "INSTALL_EXEC= $(INSTALL_EXEC)" - @echo "INSTALL_DATA= $(INSTALL_DATA)" - -# echo pkg-config data -pc: - @echo "version=$R" - @echo "prefix=$(INSTALL_TOP)" - @echo "libdir=$(INSTALL_LIB)" - @echo "includedir=$(INSTALL_INC)" - -# list targets that do not create files (but not all makes understand .PHONY) -.PHONY: all $(PLATS) clean test install local none dummy echo pecho lecho - -# (end of Makefile) diff --git a/lib/lua-5.3/README b/lib/lua-5.3/README deleted file mode 100644 index f8bdb6f..0000000 --- a/lib/lua-5.3/README +++ /dev/null @@ -1,6 +0,0 @@ - -This is Lua 5.3.6, released on 14 Sep 2020. - -For installation instructions, license details, and -further information about Lua, see doc/readme.html. - diff --git a/lib/lua-5.3/license b/lib/lua-5.3/license deleted file mode 100644 index 00425ce..0000000 --- a/lib/lua-5.3/license +++ /dev/null @@ -1,7 +0,0 @@ -Copyright © 1994–2021 Lua.org, PUC-Rio. - -Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: - -The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. diff --git a/lib/lua-5.3/src/Makefile b/lib/lua-5.3/src/Makefile deleted file mode 100644 index a13afb9..0000000 --- a/lib/lua-5.3/src/Makefile +++ /dev/null @@ -1,197 +0,0 @@ -# Makefile for building Lua -# See ../doc/readme.html for installation and customization instructions. - -# == CHANGE THE SETTINGS BELOW TO SUIT YOUR ENVIRONMENT ======================= - -# Your platform. See PLATS for possible values. -PLAT= none - -CC= gcc -std=gnu99 -CFLAGS= -O2 -Wall -Wextra -DLUA_COMPAT_5_2 $(SYSCFLAGS) $(MYCFLAGS) -LDFLAGS= $(SYSLDFLAGS) $(MYLDFLAGS) -LIBS= -lm $(SYSLIBS) $(MYLIBS) - -AR= ar rcu -RANLIB= ranlib -RM= rm -f - -SYSCFLAGS= -SYSLDFLAGS= -SYSLIBS= - -MYCFLAGS= -MYLDFLAGS= -MYLIBS= -MYOBJS= - -# == END OF USER SETTINGS -- NO NEED TO CHANGE ANYTHING BELOW THIS LINE ======= - -PLATS= aix bsd c89 freebsd generic linux macosx mingw posix solaris - -LUA_A= liblua.a -CORE_O= lapi.o lcode.o lctype.o ldebug.o ldo.o ldump.o lfunc.o lgc.o llex.o \ - lmem.o lobject.o lopcodes.o lparser.o lstate.o lstring.o ltable.o \ - ltm.o lundump.o lvm.o lzio.o -LIB_O= lauxlib.o lbaselib.o lbitlib.o lcorolib.o ldblib.o liolib.o \ - lmathlib.o loslib.o lstrlib.o ltablib.o lutf8lib.o loadlib.o linit.o -BASE_O= $(CORE_O) $(LIB_O) $(MYOBJS) - -LUA_T= lua -LUA_O= lua.o - -LUAC_T= luac -LUAC_O= luac.o - -ALL_O= $(BASE_O) $(LUA_O) $(LUAC_O) -ALL_T= $(LUA_A) $(LUA_T) $(LUAC_T) -ALL_A= $(LUA_A) - -# Targets start here. -default: $(PLAT) - -all: $(ALL_T) - -o: $(ALL_O) - -a: $(ALL_A) - -$(LUA_A): $(BASE_O) - $(AR) $@ $(BASE_O) - $(RANLIB) $@ - -$(LUA_T): $(LUA_O) $(LUA_A) - $(CC) -o $@ $(LDFLAGS) $(LUA_O) $(LUA_A) $(LIBS) - -$(LUAC_T): $(LUAC_O) $(LUA_A) - $(CC) -o $@ $(LDFLAGS) $(LUAC_O) $(LUA_A) $(LIBS) - -clean: - $(RM) $(ALL_T) $(ALL_O) - -depend: - @$(CC) $(CFLAGS) -MM l*.c - -echo: - @echo "PLAT= $(PLAT)" - @echo "CC= $(CC)" - @echo "CFLAGS= $(CFLAGS)" - @echo "LDFLAGS= $(SYSLDFLAGS)" - @echo "LIBS= $(LIBS)" - @echo "AR= $(AR)" - @echo "RANLIB= $(RANLIB)" - @echo "RM= $(RM)" - -# Convenience targets for popular platforms -ALL= all - -none: - @echo "Please do 'make PLATFORM' where PLATFORM is one of these:" - @echo " $(PLATS)" - -aix: - $(MAKE) $(ALL) CC="xlc" CFLAGS="-O2 -DLUA_USE_POSIX -DLUA_USE_DLOPEN" SYSLIBS="-ldl" SYSLDFLAGS="-brtl -bexpall" - -bsd: - $(MAKE) $(ALL) SYSCFLAGS="-DLUA_USE_POSIX -DLUA_USE_DLOPEN" SYSLIBS="-Wl,-E" - -c89: - $(MAKE) $(ALL) SYSCFLAGS="-DLUA_USE_C89" CC="gcc -std=c89" - @echo '' - @echo '*** C89 does not guarantee 64-bit integers for Lua.' - @echo '' - - -freebsd: - $(MAKE) $(ALL) SYSCFLAGS="-DLUA_USE_LINUX -I/usr/include/edit" SYSLIBS="-Wl,-E -ledit" CC="cc" - -generic: $(ALL) - -linux: - $(MAKE) $(ALL) SYSCFLAGS="-DLUA_USE_LINUX" SYSLIBS="-Wl,-E -ldl -lreadline" - -macosx: - $(MAKE) $(ALL) SYSCFLAGS="-DLUA_USE_MACOSX" SYSLIBS="-lreadline" - -mingw: - $(MAKE) "LUA_A=lua53.dll" "LUA_T=lua.exe" \ - "AR=$(CC) -shared -o" "RANLIB=strip --strip-unneeded" \ - "SYSCFLAGS=-DLUA_BUILD_AS_DLL" "SYSLIBS=" "SYSLDFLAGS=-s" lua.exe - $(MAKE) "LUAC_T=luac.exe" luac.exe - -posix: - $(MAKE) $(ALL) SYSCFLAGS="-DLUA_USE_POSIX" - -solaris: - $(MAKE) $(ALL) SYSCFLAGS="-DLUA_USE_POSIX -DLUA_USE_DLOPEN -D_REENTRANT" SYSLIBS="-ldl" - -# list targets that do not create files (but not all makes understand .PHONY) -.PHONY: all $(PLATS) default o a clean depend echo none - -# DO NOT DELETE - -lapi.o: lapi.c lprefix.h lua.h luaconf.h lapi.h llimits.h lstate.h \ - lobject.h ltm.h lzio.h lmem.h ldebug.h ldo.h lfunc.h lgc.h lstring.h \ - ltable.h lundump.h lvm.h -lauxlib.o: lauxlib.c lprefix.h lua.h luaconf.h lauxlib.h -lbaselib.o: lbaselib.c lprefix.h lua.h luaconf.h lauxlib.h lualib.h -lbitlib.o: lbitlib.c lprefix.h lua.h luaconf.h lauxlib.h lualib.h -lcode.o: lcode.c lprefix.h lua.h luaconf.h lcode.h llex.h lobject.h \ - llimits.h lzio.h lmem.h lopcodes.h lparser.h ldebug.h lstate.h ltm.h \ - ldo.h lgc.h lstring.h ltable.h lvm.h -lcorolib.o: lcorolib.c lprefix.h lua.h luaconf.h lauxlib.h lualib.h -lctype.o: lctype.c lprefix.h lctype.h lua.h luaconf.h llimits.h -ldblib.o: ldblib.c lprefix.h lua.h luaconf.h lauxlib.h lualib.h -ldebug.o: ldebug.c lprefix.h lua.h luaconf.h lapi.h llimits.h lstate.h \ - lobject.h ltm.h lzio.h lmem.h lcode.h llex.h lopcodes.h lparser.h \ - ldebug.h ldo.h lfunc.h lstring.h lgc.h ltable.h lvm.h -ldo.o: ldo.c lprefix.h lua.h luaconf.h lapi.h llimits.h lstate.h \ - lobject.h ltm.h lzio.h lmem.h ldebug.h ldo.h lfunc.h lgc.h lopcodes.h \ - lparser.h lstring.h ltable.h lundump.h lvm.h -ldump.o: ldump.c lprefix.h lua.h luaconf.h lobject.h llimits.h lstate.h \ - ltm.h lzio.h lmem.h lundump.h -lfunc.o: lfunc.c lprefix.h lua.h luaconf.h lfunc.h lobject.h llimits.h \ - lgc.h lstate.h ltm.h lzio.h lmem.h -lgc.o: lgc.c lprefix.h lua.h luaconf.h ldebug.h lstate.h lobject.h \ - llimits.h ltm.h lzio.h lmem.h ldo.h lfunc.h lgc.h lstring.h ltable.h -linit.o: linit.c lprefix.h lua.h luaconf.h lualib.h lauxlib.h -liolib.o: liolib.c lprefix.h lua.h luaconf.h lauxlib.h lualib.h -llex.o: llex.c lprefix.h lua.h luaconf.h lctype.h llimits.h ldebug.h \ - lstate.h lobject.h ltm.h lzio.h lmem.h ldo.h lgc.h llex.h lparser.h \ - lstring.h ltable.h -lmathlib.o: lmathlib.c lprefix.h lua.h luaconf.h lauxlib.h lualib.h -lmem.o: lmem.c lprefix.h lua.h luaconf.h ldebug.h lstate.h lobject.h \ - llimits.h ltm.h lzio.h lmem.h ldo.h lgc.h -loadlib.o: loadlib.c lprefix.h lua.h luaconf.h lauxlib.h lualib.h -lobject.o: lobject.c lprefix.h lua.h luaconf.h lctype.h llimits.h \ - ldebug.h lstate.h lobject.h ltm.h lzio.h lmem.h ldo.h lstring.h lgc.h \ - lvm.h -lopcodes.o: lopcodes.c lprefix.h lopcodes.h llimits.h lua.h luaconf.h -loslib.o: loslib.c lprefix.h lua.h luaconf.h lauxlib.h lualib.h -lparser.o: lparser.c lprefix.h lua.h luaconf.h lcode.h llex.h lobject.h \ - llimits.h lzio.h lmem.h lopcodes.h lparser.h ldebug.h lstate.h ltm.h \ - ldo.h lfunc.h lstring.h lgc.h ltable.h -lstate.o: lstate.c lprefix.h lua.h luaconf.h lapi.h llimits.h lstate.h \ - lobject.h ltm.h lzio.h lmem.h ldebug.h ldo.h lfunc.h lgc.h llex.h \ - lstring.h ltable.h -lstring.o: lstring.c lprefix.h lua.h luaconf.h ldebug.h lstate.h \ - lobject.h llimits.h ltm.h lzio.h lmem.h ldo.h lstring.h lgc.h -lstrlib.o: lstrlib.c lprefix.h lua.h luaconf.h lauxlib.h lualib.h -ltable.o: ltable.c lprefix.h lua.h luaconf.h ldebug.h lstate.h lobject.h \ - llimits.h ltm.h lzio.h lmem.h ldo.h lgc.h lstring.h ltable.h lvm.h -ltablib.o: ltablib.c lprefix.h lua.h luaconf.h lauxlib.h lualib.h -ltm.o: ltm.c lprefix.h lua.h luaconf.h ldebug.h lstate.h lobject.h \ - llimits.h ltm.h lzio.h lmem.h ldo.h lstring.h lgc.h ltable.h lvm.h -lua.o: lua.c lprefix.h lua.h luaconf.h lauxlib.h lualib.h -luac.o: luac.c lprefix.h lua.h luaconf.h lauxlib.h lobject.h llimits.h \ - lstate.h ltm.h lzio.h lmem.h lundump.h ldebug.h lopcodes.h -lundump.o: lundump.c lprefix.h lua.h luaconf.h ldebug.h lstate.h \ - lobject.h llimits.h ltm.h lzio.h lmem.h ldo.h lfunc.h lstring.h lgc.h \ - lundump.h -lutf8lib.o: lutf8lib.c lprefix.h lua.h luaconf.h lauxlib.h lualib.h -lvm.o: lvm.c lprefix.h lua.h luaconf.h ldebug.h lstate.h lobject.h \ - llimits.h ltm.h lzio.h lmem.h ldo.h lfunc.h lgc.h lopcodes.h lstring.h \ - ltable.h lvm.h -lzio.o: lzio.c lprefix.h lua.h luaconf.h llimits.h lmem.h lstate.h \ - lobject.h ltm.h lzio.h - -# (end of Makefile) diff --git a/lib/lua-5.3/src/lapi.c b/lib/lua-5.3/src/lapi.c deleted file mode 100644 index 711895b..0000000 --- a/lib/lua-5.3/src/lapi.c +++ /dev/null @@ -1,1299 +0,0 @@ -/* -** $Id: lapi.c,v 2.259.1.2 2017/12/06 18:35:12 roberto Exp $ -** Lua API -** See Copyright Notice in lua.h -*/ - -#define lapi_c -#define LUA_CORE - -#include "lprefix.h" - - -#include -#include - -#include "lua.h" - -#include "lapi.h" -#include "ldebug.h" -#include "ldo.h" -#include "lfunc.h" -#include "lgc.h" -#include "lmem.h" -#include "lobject.h" -#include "lstate.h" -#include "lstring.h" -#include "ltable.h" -#include "ltm.h" -#include "lundump.h" -#include "lvm.h" - - - -const char lua_ident[] = - "$LuaVersion: " LUA_COPYRIGHT " $" - "$LuaAuthors: " LUA_AUTHORS " $"; - - -/* value at a non-valid index */ -#define NONVALIDVALUE cast(TValue *, luaO_nilobject) - -/* corresponding test */ -#define isvalid(o) ((o) != luaO_nilobject) - -/* test for pseudo index */ -#define ispseudo(i) ((i) <= LUA_REGISTRYINDEX) - -/* test for upvalue */ -#define isupvalue(i) ((i) < LUA_REGISTRYINDEX) - -/* test for valid but not pseudo index */ -#define isstackindex(i, o) (isvalid(o) && !ispseudo(i)) - -#define api_checkvalidindex(l,o) api_check(l, isvalid(o), "invalid index") - -#define api_checkstackindex(l, i, o) \ - api_check(l, isstackindex(i, o), "index not in the stack") - - -static TValue *index2addr (lua_State *L, int idx) { - CallInfo *ci = L->ci; - if (idx > 0) { - TValue *o = ci->func + idx; - api_check(L, idx <= ci->top - (ci->func + 1), "unacceptable index"); - if (o >= L->top) return NONVALIDVALUE; - else return o; - } - else if (!ispseudo(idx)) { /* negative index */ - api_check(L, idx != 0 && -idx <= L->top - (ci->func + 1), "invalid index"); - return L->top + idx; - } - else if (idx == LUA_REGISTRYINDEX) - return &G(L)->l_registry; - else { /* upvalues */ - idx = LUA_REGISTRYINDEX - idx; - api_check(L, idx <= MAXUPVAL + 1, "upvalue index too large"); - if (ttislcf(ci->func)) /* light C function? */ - return NONVALIDVALUE; /* it has no upvalues */ - else { - CClosure *func = clCvalue(ci->func); - return (idx <= func->nupvalues) ? &func->upvalue[idx-1] : NONVALIDVALUE; - } - } -} - - -/* -** to be called by 'lua_checkstack' in protected mode, to grow stack -** capturing memory errors -*/ -static void growstack (lua_State *L, void *ud) { - int size = *(int *)ud; - luaD_growstack(L, size); -} - - -LUA_API int lua_checkstack (lua_State *L, int n) { - int res; - CallInfo *ci = L->ci; - lua_lock(L); - api_check(L, n >= 0, "negative 'n'"); - if (L->stack_last - L->top > n) /* stack large enough? */ - res = 1; /* yes; check is OK */ - else { /* no; need to grow stack */ - int inuse = cast_int(L->top - L->stack) + EXTRA_STACK; - if (inuse > LUAI_MAXSTACK - n) /* can grow without overflow? */ - res = 0; /* no */ - else /* try to grow stack */ - res = (luaD_rawrunprotected(L, &growstack, &n) == LUA_OK); - } - if (res && ci->top < L->top + n) - ci->top = L->top + n; /* adjust frame top */ - lua_unlock(L); - return res; -} - - -LUA_API void lua_xmove (lua_State *from, lua_State *to, int n) { - int i; - if (from == to) return; - lua_lock(to); - api_checknelems(from, n); - api_check(from, G(from) == G(to), "moving among independent states"); - api_check(from, to->ci->top - to->top >= n, "stack overflow"); - from->top -= n; - for (i = 0; i < n; i++) { - setobj2s(to, to->top, from->top + i); - to->top++; /* stack already checked by previous 'api_check' */ - } - lua_unlock(to); -} - - -LUA_API lua_CFunction lua_atpanic (lua_State *L, lua_CFunction panicf) { - lua_CFunction old; - lua_lock(L); - old = G(L)->panic; - G(L)->panic = panicf; - lua_unlock(L); - return old; -} - - -LUA_API const lua_Number *lua_version (lua_State *L) { - static const lua_Number version = LUA_VERSION_NUM; - if (L == NULL) return &version; - else return G(L)->version; -} - - - -/* -** basic stack manipulation -*/ - - -/* -** convert an acceptable stack index into an absolute index -*/ -LUA_API int lua_absindex (lua_State *L, int idx) { - return (idx > 0 || ispseudo(idx)) - ? idx - : cast_int(L->top - L->ci->func) + idx; -} - - -LUA_API int lua_gettop (lua_State *L) { - return cast_int(L->top - (L->ci->func + 1)); -} - - -LUA_API void lua_settop (lua_State *L, int idx) { - StkId func = L->ci->func; - lua_lock(L); - if (idx >= 0) { - api_check(L, idx <= L->stack_last - (func + 1), "new top too large"); - while (L->top < (func + 1) + idx) - setnilvalue(L->top++); - L->top = (func + 1) + idx; - } - else { - api_check(L, -(idx+1) <= (L->top - (func + 1)), "invalid new top"); - L->top += idx+1; /* 'subtract' index (index is negative) */ - } - lua_unlock(L); -} - - -/* -** Reverse the stack segment from 'from' to 'to' -** (auxiliary to 'lua_rotate') -*/ -static void reverse (lua_State *L, StkId from, StkId to) { - for (; from < to; from++, to--) { - TValue temp; - setobj(L, &temp, from); - setobjs2s(L, from, to); - setobj2s(L, to, &temp); - } -} - - -/* -** Let x = AB, where A is a prefix of length 'n'. Then, -** rotate x n == BA. But BA == (A^r . B^r)^r. -*/ -LUA_API void lua_rotate (lua_State *L, int idx, int n) { - StkId p, t, m; - lua_lock(L); - t = L->top - 1; /* end of stack segment being rotated */ - p = index2addr(L, idx); /* start of segment */ - api_checkstackindex(L, idx, p); - api_check(L, (n >= 0 ? n : -n) <= (t - p + 1), "invalid 'n'"); - m = (n >= 0 ? t - n : p - n - 1); /* end of prefix */ - reverse(L, p, m); /* reverse the prefix with length 'n' */ - reverse(L, m + 1, t); /* reverse the suffix */ - reverse(L, p, t); /* reverse the entire segment */ - lua_unlock(L); -} - - -LUA_API void lua_copy (lua_State *L, int fromidx, int toidx) { - TValue *fr, *to; - lua_lock(L); - fr = index2addr(L, fromidx); - to = index2addr(L, toidx); - api_checkvalidindex(L, to); - setobj(L, to, fr); - if (isupvalue(toidx)) /* function upvalue? */ - luaC_barrier(L, clCvalue(L->ci->func), fr); - /* LUA_REGISTRYINDEX does not need gc barrier - (collector revisits it before finishing collection) */ - lua_unlock(L); -} - - -LUA_API void lua_pushvalue (lua_State *L, int idx) { - lua_lock(L); - setobj2s(L, L->top, index2addr(L, idx)); - api_incr_top(L); - lua_unlock(L); -} - - - -/* -** access functions (stack -> C) -*/ - - -LUA_API int lua_type (lua_State *L, int idx) { - StkId o = index2addr(L, idx); - return (isvalid(o) ? ttnov(o) : LUA_TNONE); -} - - -LUA_API const char *lua_typename (lua_State *L, int t) { - UNUSED(L); - api_check(L, LUA_TNONE <= t && t < LUA_NUMTAGS, "invalid tag"); - return ttypename(t); -} - - -LUA_API int lua_iscfunction (lua_State *L, int idx) { - StkId o = index2addr(L, idx); - return (ttislcf(o) || (ttisCclosure(o))); -} - - -LUA_API int lua_isinteger (lua_State *L, int idx) { - StkId o = index2addr(L, idx); - return ttisinteger(o); -} - - -LUA_API int lua_isnumber (lua_State *L, int idx) { - lua_Number n; - const TValue *o = index2addr(L, idx); - return tonumber(o, &n); -} - - -LUA_API int lua_isstring (lua_State *L, int idx) { - const TValue *o = index2addr(L, idx); - return (ttisstring(o) || cvt2str(o)); -} - - -LUA_API int lua_isuserdata (lua_State *L, int idx) { - const TValue *o = index2addr(L, idx); - return (ttisfulluserdata(o) || ttislightuserdata(o)); -} - - -LUA_API int lua_rawequal (lua_State *L, int index1, int index2) { - StkId o1 = index2addr(L, index1); - StkId o2 = index2addr(L, index2); - return (isvalid(o1) && isvalid(o2)) ? luaV_rawequalobj(o1, o2) : 0; -} - - -LUA_API void lua_arith (lua_State *L, int op) { - lua_lock(L); - if (op != LUA_OPUNM && op != LUA_OPBNOT) - api_checknelems(L, 2); /* all other operations expect two operands */ - else { /* for unary operations, add fake 2nd operand */ - api_checknelems(L, 1); - setobjs2s(L, L->top, L->top - 1); - api_incr_top(L); - } - /* first operand at top - 2, second at top - 1; result go to top - 2 */ - luaO_arith(L, op, L->top - 2, L->top - 1, L->top - 2); - L->top--; /* remove second operand */ - lua_unlock(L); -} - - -LUA_API int lua_compare (lua_State *L, int index1, int index2, int op) { - StkId o1, o2; - int i = 0; - lua_lock(L); /* may call tag method */ - o1 = index2addr(L, index1); - o2 = index2addr(L, index2); - if (isvalid(o1) && isvalid(o2)) { - switch (op) { - case LUA_OPEQ: i = luaV_equalobj(L, o1, o2); break; - case LUA_OPLT: i = luaV_lessthan(L, o1, o2); break; - case LUA_OPLE: i = luaV_lessequal(L, o1, o2); break; - default: api_check(L, 0, "invalid option"); - } - } - lua_unlock(L); - return i; -} - - -LUA_API size_t lua_stringtonumber (lua_State *L, const char *s) { - size_t sz = luaO_str2num(s, L->top); - if (sz != 0) - api_incr_top(L); - return sz; -} - - -LUA_API lua_Number lua_tonumberx (lua_State *L, int idx, int *pisnum) { - lua_Number n; - const TValue *o = index2addr(L, idx); - int isnum = tonumber(o, &n); - if (!isnum) - n = 0; /* call to 'tonumber' may change 'n' even if it fails */ - if (pisnum) *pisnum = isnum; - return n; -} - - -LUA_API lua_Integer lua_tointegerx (lua_State *L, int idx, int *pisnum) { - lua_Integer res; - const TValue *o = index2addr(L, idx); - int isnum = tointeger(o, &res); - if (!isnum) - res = 0; /* call to 'tointeger' may change 'n' even if it fails */ - if (pisnum) *pisnum = isnum; - return res; -} - - -LUA_API int lua_toboolean (lua_State *L, int idx) { - const TValue *o = index2addr(L, idx); - return !l_isfalse(o); -} - - -LUA_API const char *lua_tolstring (lua_State *L, int idx, size_t *len) { - StkId o = index2addr(L, idx); - if (!ttisstring(o)) { - if (!cvt2str(o)) { /* not convertible? */ - if (len != NULL) *len = 0; - return NULL; - } - lua_lock(L); /* 'luaO_tostring' may create a new string */ - luaO_tostring(L, o); - luaC_checkGC(L); - o = index2addr(L, idx); /* previous call may reallocate the stack */ - lua_unlock(L); - } - if (len != NULL) - *len = vslen(o); - return svalue(o); -} - - -LUA_API size_t lua_rawlen (lua_State *L, int idx) { - StkId o = index2addr(L, idx); - switch (ttype(o)) { - case LUA_TSHRSTR: return tsvalue(o)->shrlen; - case LUA_TLNGSTR: return tsvalue(o)->u.lnglen; - case LUA_TUSERDATA: return uvalue(o)->len; - case LUA_TTABLE: return luaH_getn(hvalue(o)); - default: return 0; - } -} - - -LUA_API lua_CFunction lua_tocfunction (lua_State *L, int idx) { - StkId o = index2addr(L, idx); - if (ttislcf(o)) return fvalue(o); - else if (ttisCclosure(o)) - return clCvalue(o)->f; - else return NULL; /* not a C function */ -} - - -LUA_API void *lua_touserdata (lua_State *L, int idx) { - StkId o = index2addr(L, idx); - switch (ttnov(o)) { - case LUA_TUSERDATA: return getudatamem(uvalue(o)); - case LUA_TLIGHTUSERDATA: return pvalue(o); - default: return NULL; - } -} - - -LUA_API lua_State *lua_tothread (lua_State *L, int idx) { - StkId o = index2addr(L, idx); - return (!ttisthread(o)) ? NULL : thvalue(o); -} - - -LUA_API const void *lua_topointer (lua_State *L, int idx) { - StkId o = index2addr(L, idx); - switch (ttype(o)) { - case LUA_TTABLE: return hvalue(o); - case LUA_TLCL: return clLvalue(o); - case LUA_TCCL: return clCvalue(o); - case LUA_TLCF: return cast(void *, cast(size_t, fvalue(o))); - case LUA_TTHREAD: return thvalue(o); - case LUA_TUSERDATA: return getudatamem(uvalue(o)); - case LUA_TLIGHTUSERDATA: return pvalue(o); - default: return NULL; - } -} - - - -/* -** push functions (C -> stack) -*/ - - -LUA_API void lua_pushnil (lua_State *L) { - lua_lock(L); - setnilvalue(L->top); - api_incr_top(L); - lua_unlock(L); -} - - -LUA_API void lua_pushnumber (lua_State *L, lua_Number n) { - lua_lock(L); - setfltvalue(L->top, n); - api_incr_top(L); - lua_unlock(L); -} - - -LUA_API void lua_pushinteger (lua_State *L, lua_Integer n) { - lua_lock(L); - setivalue(L->top, n); - api_incr_top(L); - lua_unlock(L); -} - - -/* -** Pushes on the stack a string with given length. Avoid using 's' when -** 'len' == 0 (as 's' can be NULL in that case), due to later use of -** 'memcmp' and 'memcpy'. -*/ -LUA_API const char *lua_pushlstring (lua_State *L, const char *s, size_t len) { - TString *ts; - lua_lock(L); - ts = (len == 0) ? luaS_new(L, "") : luaS_newlstr(L, s, len); - setsvalue2s(L, L->top, ts); - api_incr_top(L); - luaC_checkGC(L); - lua_unlock(L); - return getstr(ts); -} - - -LUA_API const char *lua_pushstring (lua_State *L, const char *s) { - lua_lock(L); - if (s == NULL) - setnilvalue(L->top); - else { - TString *ts; - ts = luaS_new(L, s); - setsvalue2s(L, L->top, ts); - s = getstr(ts); /* internal copy's address */ - } - api_incr_top(L); - luaC_checkGC(L); - lua_unlock(L); - return s; -} - - -LUA_API const char *lua_pushvfstring (lua_State *L, const char *fmt, - va_list argp) { - const char *ret; - lua_lock(L); - ret = luaO_pushvfstring(L, fmt, argp); - luaC_checkGC(L); - lua_unlock(L); - return ret; -} - - -LUA_API const char *lua_pushfstring (lua_State *L, const char *fmt, ...) { - const char *ret; - va_list argp; - lua_lock(L); - va_start(argp, fmt); - ret = luaO_pushvfstring(L, fmt, argp); - va_end(argp); - luaC_checkGC(L); - lua_unlock(L); - return ret; -} - - -LUA_API void lua_pushcclosure (lua_State *L, lua_CFunction fn, int n) { - lua_lock(L); - if (n == 0) { - setfvalue(L->top, fn); - api_incr_top(L); - } - else { - CClosure *cl; - api_checknelems(L, n); - api_check(L, n <= MAXUPVAL, "upvalue index too large"); - cl = luaF_newCclosure(L, n); - cl->f = fn; - L->top -= n; - while (n--) { - setobj2n(L, &cl->upvalue[n], L->top + n); - /* does not need barrier because closure is white */ - } - setclCvalue(L, L->top, cl); - api_incr_top(L); - luaC_checkGC(L); - } - lua_unlock(L); -} - - -LUA_API void lua_pushboolean (lua_State *L, int b) { - lua_lock(L); - setbvalue(L->top, (b != 0)); /* ensure that true is 1 */ - api_incr_top(L); - lua_unlock(L); -} - - -LUA_API void lua_pushlightuserdata (lua_State *L, void *p) { - lua_lock(L); - setpvalue(L->top, p); - api_incr_top(L); - lua_unlock(L); -} - - -LUA_API int lua_pushthread (lua_State *L) { - lua_lock(L); - setthvalue(L, L->top, L); - api_incr_top(L); - lua_unlock(L); - return (G(L)->mainthread == L); -} - - - -/* -** get functions (Lua -> stack) -*/ - - -static int auxgetstr (lua_State *L, const TValue *t, const char *k) { - const TValue *slot; - TString *str = luaS_new(L, k); - if (luaV_fastget(L, t, str, slot, luaH_getstr)) { - setobj2s(L, L->top, slot); - api_incr_top(L); - } - else { - setsvalue2s(L, L->top, str); - api_incr_top(L); - luaV_finishget(L, t, L->top - 1, L->top - 1, slot); - } - lua_unlock(L); - return ttnov(L->top - 1); -} - - -LUA_API int lua_getglobal (lua_State *L, const char *name) { - Table *reg = hvalue(&G(L)->l_registry); - lua_lock(L); - return auxgetstr(L, luaH_getint(reg, LUA_RIDX_GLOBALS), name); -} - - -LUA_API int lua_gettable (lua_State *L, int idx) { - StkId t; - lua_lock(L); - t = index2addr(L, idx); - luaV_gettable(L, t, L->top - 1, L->top - 1); - lua_unlock(L); - return ttnov(L->top - 1); -} - - -LUA_API int lua_getfield (lua_State *L, int idx, const char *k) { - lua_lock(L); - return auxgetstr(L, index2addr(L, idx), k); -} - - -LUA_API int lua_geti (lua_State *L, int idx, lua_Integer n) { - StkId t; - const TValue *slot; - lua_lock(L); - t = index2addr(L, idx); - if (luaV_fastget(L, t, n, slot, luaH_getint)) { - setobj2s(L, L->top, slot); - api_incr_top(L); - } - else { - setivalue(L->top, n); - api_incr_top(L); - luaV_finishget(L, t, L->top - 1, L->top - 1, slot); - } - lua_unlock(L); - return ttnov(L->top - 1); -} - - -LUA_API int lua_rawget (lua_State *L, int idx) { - StkId t; - lua_lock(L); - t = index2addr(L, idx); - api_check(L, ttistable(t), "table expected"); - setobj2s(L, L->top - 1, luaH_get(hvalue(t), L->top - 1)); - lua_unlock(L); - return ttnov(L->top - 1); -} - - -LUA_API int lua_rawgeti (lua_State *L, int idx, lua_Integer n) { - StkId t; - lua_lock(L); - t = index2addr(L, idx); - api_check(L, ttistable(t), "table expected"); - setobj2s(L, L->top, luaH_getint(hvalue(t), n)); - api_incr_top(L); - lua_unlock(L); - return ttnov(L->top - 1); -} - - -LUA_API int lua_rawgetp (lua_State *L, int idx, const void *p) { - StkId t; - TValue k; - lua_lock(L); - t = index2addr(L, idx); - api_check(L, ttistable(t), "table expected"); - setpvalue(&k, cast(void *, p)); - setobj2s(L, L->top, luaH_get(hvalue(t), &k)); - api_incr_top(L); - lua_unlock(L); - return ttnov(L->top - 1); -} - - -LUA_API void lua_createtable (lua_State *L, int narray, int nrec) { - Table *t; - lua_lock(L); - t = luaH_new(L); - sethvalue(L, L->top, t); - api_incr_top(L); - if (narray > 0 || nrec > 0) - luaH_resize(L, t, narray, nrec); - luaC_checkGC(L); - lua_unlock(L); -} - - -LUA_API int lua_getmetatable (lua_State *L, int objindex) { - const TValue *obj; - Table *mt; - int res = 0; - lua_lock(L); - obj = index2addr(L, objindex); - switch (ttnov(obj)) { - case LUA_TTABLE: - mt = hvalue(obj)->metatable; - break; - case LUA_TUSERDATA: - mt = uvalue(obj)->metatable; - break; - default: - mt = G(L)->mt[ttnov(obj)]; - break; - } - if (mt != NULL) { - sethvalue(L, L->top, mt); - api_incr_top(L); - res = 1; - } - lua_unlock(L); - return res; -} - - -LUA_API int lua_getuservalue (lua_State *L, int idx) { - StkId o; - lua_lock(L); - o = index2addr(L, idx); - api_check(L, ttisfulluserdata(o), "full userdata expected"); - getuservalue(L, uvalue(o), L->top); - api_incr_top(L); - lua_unlock(L); - return ttnov(L->top - 1); -} - - -/* -** set functions (stack -> Lua) -*/ - -/* -** t[k] = value at the top of the stack (where 'k' is a string) -*/ -static void auxsetstr (lua_State *L, const TValue *t, const char *k) { - const TValue *slot; - TString *str = luaS_new(L, k); - api_checknelems(L, 1); - if (luaV_fastset(L, t, str, slot, luaH_getstr, L->top - 1)) - L->top--; /* pop value */ - else { - setsvalue2s(L, L->top, str); /* push 'str' (to make it a TValue) */ - api_incr_top(L); - luaV_finishset(L, t, L->top - 1, L->top - 2, slot); - L->top -= 2; /* pop value and key */ - } - lua_unlock(L); /* lock done by caller */ -} - - -LUA_API void lua_setglobal (lua_State *L, const char *name) { - Table *reg = hvalue(&G(L)->l_registry); - lua_lock(L); /* unlock done in 'auxsetstr' */ - auxsetstr(L, luaH_getint(reg, LUA_RIDX_GLOBALS), name); -} - - -LUA_API void lua_settable (lua_State *L, int idx) { - StkId t; - lua_lock(L); - api_checknelems(L, 2); - t = index2addr(L, idx); - luaV_settable(L, t, L->top - 2, L->top - 1); - L->top -= 2; /* pop index and value */ - lua_unlock(L); -} - - -LUA_API void lua_setfield (lua_State *L, int idx, const char *k) { - lua_lock(L); /* unlock done in 'auxsetstr' */ - auxsetstr(L, index2addr(L, idx), k); -} - - -LUA_API void lua_seti (lua_State *L, int idx, lua_Integer n) { - StkId t; - const TValue *slot; - lua_lock(L); - api_checknelems(L, 1); - t = index2addr(L, idx); - if (luaV_fastset(L, t, n, slot, luaH_getint, L->top - 1)) - L->top--; /* pop value */ - else { - setivalue(L->top, n); - api_incr_top(L); - luaV_finishset(L, t, L->top - 1, L->top - 2, slot); - L->top -= 2; /* pop value and key */ - } - lua_unlock(L); -} - - -LUA_API void lua_rawset (lua_State *L, int idx) { - StkId o; - TValue *slot; - lua_lock(L); - api_checknelems(L, 2); - o = index2addr(L, idx); - api_check(L, ttistable(o), "table expected"); - slot = luaH_set(L, hvalue(o), L->top - 2); - setobj2t(L, slot, L->top - 1); - invalidateTMcache(hvalue(o)); - luaC_barrierback(L, hvalue(o), L->top-1); - L->top -= 2; - lua_unlock(L); -} - - -LUA_API void lua_rawseti (lua_State *L, int idx, lua_Integer n) { - StkId o; - lua_lock(L); - api_checknelems(L, 1); - o = index2addr(L, idx); - api_check(L, ttistable(o), "table expected"); - luaH_setint(L, hvalue(o), n, L->top - 1); - luaC_barrierback(L, hvalue(o), L->top-1); - L->top--; - lua_unlock(L); -} - - -LUA_API void lua_rawsetp (lua_State *L, int idx, const void *p) { - StkId o; - TValue k, *slot; - lua_lock(L); - api_checknelems(L, 1); - o = index2addr(L, idx); - api_check(L, ttistable(o), "table expected"); - setpvalue(&k, cast(void *, p)); - slot = luaH_set(L, hvalue(o), &k); - setobj2t(L, slot, L->top - 1); - luaC_barrierback(L, hvalue(o), L->top - 1); - L->top--; - lua_unlock(L); -} - - -LUA_API int lua_setmetatable (lua_State *L, int objindex) { - TValue *obj; - Table *mt; - lua_lock(L); - api_checknelems(L, 1); - obj = index2addr(L, objindex); - if (ttisnil(L->top - 1)) - mt = NULL; - else { - api_check(L, ttistable(L->top - 1), "table expected"); - mt = hvalue(L->top - 1); - } - switch (ttnov(obj)) { - case LUA_TTABLE: { - hvalue(obj)->metatable = mt; - if (mt) { - luaC_objbarrier(L, gcvalue(obj), mt); - luaC_checkfinalizer(L, gcvalue(obj), mt); - } - break; - } - case LUA_TUSERDATA: { - uvalue(obj)->metatable = mt; - if (mt) { - luaC_objbarrier(L, uvalue(obj), mt); - luaC_checkfinalizer(L, gcvalue(obj), mt); - } - break; - } - default: { - G(L)->mt[ttnov(obj)] = mt; - break; - } - } - L->top--; - lua_unlock(L); - return 1; -} - - -LUA_API void lua_setuservalue (lua_State *L, int idx) { - StkId o; - lua_lock(L); - api_checknelems(L, 1); - o = index2addr(L, idx); - api_check(L, ttisfulluserdata(o), "full userdata expected"); - setuservalue(L, uvalue(o), L->top - 1); - luaC_barrier(L, gcvalue(o), L->top - 1); - L->top--; - lua_unlock(L); -} - - -/* -** 'load' and 'call' functions (run Lua code) -*/ - - -#define checkresults(L,na,nr) \ - api_check(L, (nr) == LUA_MULTRET || (L->ci->top - L->top >= (nr) - (na)), \ - "results from function overflow current stack size") - - -LUA_API void lua_callk (lua_State *L, int nargs, int nresults, - lua_KContext ctx, lua_KFunction k) { - StkId func; - lua_lock(L); - api_check(L, k == NULL || !isLua(L->ci), - "cannot use continuations inside hooks"); - api_checknelems(L, nargs+1); - api_check(L, L->status == LUA_OK, "cannot do calls on non-normal thread"); - checkresults(L, nargs, nresults); - func = L->top - (nargs+1); - if (k != NULL && L->nny == 0) { /* need to prepare continuation? */ - L->ci->u.c.k = k; /* save continuation */ - L->ci->u.c.ctx = ctx; /* save context */ - luaD_call(L, func, nresults); /* do the call */ - } - else /* no continuation or no yieldable */ - luaD_callnoyield(L, func, nresults); /* just do the call */ - adjustresults(L, nresults); - lua_unlock(L); -} - - - -/* -** Execute a protected call. -*/ -struct CallS { /* data to 'f_call' */ - StkId func; - int nresults; -}; - - -static void f_call (lua_State *L, void *ud) { - struct CallS *c = cast(struct CallS *, ud); - luaD_callnoyield(L, c->func, c->nresults); -} - - - -LUA_API int lua_pcallk (lua_State *L, int nargs, int nresults, int errfunc, - lua_KContext ctx, lua_KFunction k) { - struct CallS c; - int status; - ptrdiff_t func; - lua_lock(L); - api_check(L, k == NULL || !isLua(L->ci), - "cannot use continuations inside hooks"); - api_checknelems(L, nargs+1); - api_check(L, L->status == LUA_OK, "cannot do calls on non-normal thread"); - checkresults(L, nargs, nresults); - if (errfunc == 0) - func = 0; - else { - StkId o = index2addr(L, errfunc); - api_checkstackindex(L, errfunc, o); - func = savestack(L, o); - } - c.func = L->top - (nargs+1); /* function to be called */ - if (k == NULL || L->nny > 0) { /* no continuation or no yieldable? */ - c.nresults = nresults; /* do a 'conventional' protected call */ - status = luaD_pcall(L, f_call, &c, savestack(L, c.func), func); - } - else { /* prepare continuation (call is already protected by 'resume') */ - CallInfo *ci = L->ci; - ci->u.c.k = k; /* save continuation */ - ci->u.c.ctx = ctx; /* save context */ - /* save information for error recovery */ - ci->extra = savestack(L, c.func); - ci->u.c.old_errfunc = L->errfunc; - L->errfunc = func; - setoah(ci->callstatus, L->allowhook); /* save value of 'allowhook' */ - ci->callstatus |= CIST_YPCALL; /* function can do error recovery */ - luaD_call(L, c.func, nresults); /* do the call */ - ci->callstatus &= ~CIST_YPCALL; - L->errfunc = ci->u.c.old_errfunc; - status = LUA_OK; /* if it is here, there were no errors */ - } - adjustresults(L, nresults); - lua_unlock(L); - return status; -} - - -LUA_API int lua_load (lua_State *L, lua_Reader reader, void *data, - const char *chunkname, const char *mode) { - ZIO z; - int status; - lua_lock(L); - if (!chunkname) chunkname = "?"; - luaZ_init(L, &z, reader, data); - status = luaD_protectedparser(L, &z, chunkname, mode); - if (status == LUA_OK) { /* no errors? */ - LClosure *f = clLvalue(L->top - 1); /* get newly created function */ - if (f->nupvalues >= 1) { /* does it have an upvalue? */ - /* get global table from registry */ - Table *reg = hvalue(&G(L)->l_registry); - const TValue *gt = luaH_getint(reg, LUA_RIDX_GLOBALS); - /* set global table as 1st upvalue of 'f' (may be LUA_ENV) */ - setobj(L, f->upvals[0]->v, gt); - luaC_upvalbarrier(L, f->upvals[0]); - } - } - lua_unlock(L); - return status; -} - - -LUA_API int lua_dump (lua_State *L, lua_Writer writer, void *data, int strip) { - int status; - TValue *o; - lua_lock(L); - api_checknelems(L, 1); - o = L->top - 1; - if (isLfunction(o)) - status = luaU_dump(L, getproto(o), writer, data, strip); - else - status = 1; - lua_unlock(L); - return status; -} - - -LUA_API int lua_status (lua_State *L) { - return L->status; -} - - -/* -** Garbage-collection function -*/ - -LUA_API int lua_gc (lua_State *L, int what, int data) { - int res = 0; - global_State *g; - lua_lock(L); - g = G(L); - switch (what) { - case LUA_GCSTOP: { - g->gcrunning = 0; - break; - } - case LUA_GCRESTART: { - luaE_setdebt(g, 0); - g->gcrunning = 1; - break; - } - case LUA_GCCOLLECT: { - luaC_fullgc(L, 0); - break; - } - case LUA_GCCOUNT: { - /* GC values are expressed in Kbytes: #bytes/2^10 */ - res = cast_int(gettotalbytes(g) >> 10); - break; - } - case LUA_GCCOUNTB: { - res = cast_int(gettotalbytes(g) & 0x3ff); - break; - } - case LUA_GCSTEP: { - l_mem debt = 1; /* =1 to signal that it did an actual step */ - lu_byte oldrunning = g->gcrunning; - g->gcrunning = 1; /* allow GC to run */ - if (data == 0) { - luaE_setdebt(g, -GCSTEPSIZE); /* to do a "small" step */ - luaC_step(L); - } - else { /* add 'data' to total debt */ - debt = cast(l_mem, data) * 1024 + g->GCdebt; - luaE_setdebt(g, debt); - luaC_checkGC(L); - } - g->gcrunning = oldrunning; /* restore previous state */ - if (debt > 0 && g->gcstate == GCSpause) /* end of cycle? */ - res = 1; /* signal it */ - break; - } - case LUA_GCSETPAUSE: { - res = g->gcpause; - g->gcpause = data; - break; - } - case LUA_GCSETSTEPMUL: { - res = g->gcstepmul; - if (data < 40) data = 40; /* avoid ridiculous low values (and 0) */ - g->gcstepmul = data; - break; - } - case LUA_GCISRUNNING: { - res = g->gcrunning; - break; - } - default: res = -1; /* invalid option */ - } - lua_unlock(L); - return res; -} - - - -/* -** miscellaneous functions -*/ - - -LUA_API int lua_error (lua_State *L) { - lua_lock(L); - api_checknelems(L, 1); - luaG_errormsg(L); - /* code unreachable; will unlock when control actually leaves the kernel */ - return 0; /* to avoid warnings */ -} - - -LUA_API int lua_next (lua_State *L, int idx) { - StkId t; - int more; - lua_lock(L); - t = index2addr(L, idx); - api_check(L, ttistable(t), "table expected"); - more = luaH_next(L, hvalue(t), L->top - 1); - if (more) { - api_incr_top(L); - } - else /* no more elements */ - L->top -= 1; /* remove key */ - lua_unlock(L); - return more; -} - - -LUA_API void lua_concat (lua_State *L, int n) { - lua_lock(L); - api_checknelems(L, n); - if (n >= 2) { - luaV_concat(L, n); - } - else if (n == 0) { /* push empty string */ - setsvalue2s(L, L->top, luaS_newlstr(L, "", 0)); - api_incr_top(L); - } - /* else n == 1; nothing to do */ - luaC_checkGC(L); - lua_unlock(L); -} - - -LUA_API void lua_len (lua_State *L, int idx) { - StkId t; - lua_lock(L); - t = index2addr(L, idx); - luaV_objlen(L, L->top, t); - api_incr_top(L); - lua_unlock(L); -} - - -LUA_API lua_Alloc lua_getallocf (lua_State *L, void **ud) { - lua_Alloc f; - lua_lock(L); - if (ud) *ud = G(L)->ud; - f = G(L)->frealloc; - lua_unlock(L); - return f; -} - - -LUA_API void lua_setallocf (lua_State *L, lua_Alloc f, void *ud) { - lua_lock(L); - G(L)->ud = ud; - G(L)->frealloc = f; - lua_unlock(L); -} - - -LUA_API void *lua_newuserdata (lua_State *L, size_t size) { - Udata *u; - lua_lock(L); - u = luaS_newudata(L, size); - setuvalue(L, L->top, u); - api_incr_top(L); - luaC_checkGC(L); - lua_unlock(L); - return getudatamem(u); -} - - - -static const char *aux_upvalue (StkId fi, int n, TValue **val, - CClosure **owner, UpVal **uv) { - switch (ttype(fi)) { - case LUA_TCCL: { /* C closure */ - CClosure *f = clCvalue(fi); - if (!(1 <= n && n <= f->nupvalues)) return NULL; - *val = &f->upvalue[n-1]; - if (owner) *owner = f; - return ""; - } - case LUA_TLCL: { /* Lua closure */ - LClosure *f = clLvalue(fi); - TString *name; - Proto *p = f->p; - if (!(1 <= n && n <= p->sizeupvalues)) return NULL; - *val = f->upvals[n-1]->v; - if (uv) *uv = f->upvals[n - 1]; - name = p->upvalues[n-1].name; - return (name == NULL) ? "(*no name)" : getstr(name); - } - default: return NULL; /* not a closure */ - } -} - - -LUA_API const char *lua_getupvalue (lua_State *L, int funcindex, int n) { - const char *name; - TValue *val = NULL; /* to avoid warnings */ - lua_lock(L); - name = aux_upvalue(index2addr(L, funcindex), n, &val, NULL, NULL); - if (name) { - setobj2s(L, L->top, val); - api_incr_top(L); - } - lua_unlock(L); - return name; -} - - -LUA_API const char *lua_setupvalue (lua_State *L, int funcindex, int n) { - const char *name; - TValue *val = NULL; /* to avoid warnings */ - CClosure *owner = NULL; - UpVal *uv = NULL; - StkId fi; - lua_lock(L); - fi = index2addr(L, funcindex); - api_checknelems(L, 1); - name = aux_upvalue(fi, n, &val, &owner, &uv); - if (name) { - L->top--; - setobj(L, val, L->top); - if (owner) { luaC_barrier(L, owner, L->top); } - else if (uv) { luaC_upvalbarrier(L, uv); } - } - lua_unlock(L); - return name; -} - - -static UpVal **getupvalref (lua_State *L, int fidx, int n) { - LClosure *f; - StkId fi = index2addr(L, fidx); - api_check(L, ttisLclosure(fi), "Lua function expected"); - f = clLvalue(fi); - api_check(L, (1 <= n && n <= f->p->sizeupvalues), "invalid upvalue index"); - return &f->upvals[n - 1]; /* get its upvalue pointer */ -} - - -LUA_API void *lua_upvalueid (lua_State *L, int fidx, int n) { - StkId fi = index2addr(L, fidx); - switch (ttype(fi)) { - case LUA_TLCL: { /* lua closure */ - return *getupvalref(L, fidx, n); - } - case LUA_TCCL: { /* C closure */ - CClosure *f = clCvalue(fi); - api_check(L, 1 <= n && n <= f->nupvalues, "invalid upvalue index"); - return &f->upvalue[n - 1]; - } - default: { - api_check(L, 0, "closure expected"); - return NULL; - } - } -} - - -LUA_API void lua_upvaluejoin (lua_State *L, int fidx1, int n1, - int fidx2, int n2) { - UpVal **up1 = getupvalref(L, fidx1, n1); - UpVal **up2 = getupvalref(L, fidx2, n2); - if (*up1 == *up2) - return; - luaC_upvdeccount(L, *up1); - *up1 = *up2; - (*up1)->refcount++; - if (upisopen(*up1)) (*up1)->u.open.touched = 1; - luaC_upvalbarrier(L, *up1); -} - - diff --git a/lib/lua-5.3/src/lapi.h b/lib/lua-5.3/src/lapi.h deleted file mode 100644 index 8e16ad5..0000000 --- a/lib/lua-5.3/src/lapi.h +++ /dev/null @@ -1,24 +0,0 @@ -/* -** $Id: lapi.h,v 2.9.1.1 2017/04/19 17:20:42 roberto Exp $ -** Auxiliary functions from Lua API -** See Copyright Notice in lua.h -*/ - -#ifndef lapi_h -#define lapi_h - - -#include "llimits.h" -#include "lstate.h" - -#define api_incr_top(L) {L->top++; api_check(L, L->top <= L->ci->top, \ - "stack overflow");} - -#define adjustresults(L,nres) \ - { if ((nres) == LUA_MULTRET && L->ci->top < L->top) L->ci->top = L->top; } - -#define api_checknelems(L,n) api_check(L, (n) < (L->top - L->ci->func), \ - "not enough elements in the stack") - - -#endif diff --git a/lib/lua-5.3/src/lauxlib.c b/lib/lua-5.3/src/lauxlib.c deleted file mode 100644 index ac68bd3..0000000 --- a/lib/lua-5.3/src/lauxlib.c +++ /dev/null @@ -1,1048 +0,0 @@ -/* -** $Id: lauxlib.c,v 1.289.1.1 2017/04/19 17:20:42 roberto Exp $ -** Auxiliary functions for building Lua libraries -** See Copyright Notice in lua.h -*/ - -#define lauxlib_c -#define LUA_LIB - -#include "lprefix.h" - - -#include -#include -#include -#include -#include - - -/* -** This file uses only the official API of Lua. -** Any function declared here could be written as an application function. -*/ - -#include "lua.h" - -#include "lauxlib.h" - - -/* -** {====================================================== -** Traceback -** ======================================================= -*/ - - -#define LEVELS1 10 /* size of the first part of the stack */ -#define LEVELS2 11 /* size of the second part of the stack */ - - - -/* -** search for 'objidx' in table at index -1. -** return 1 + string at top if find a good name. -*/ -static int findfield (lua_State *L, int objidx, int level) { - if (level == 0 || !lua_istable(L, -1)) - return 0; /* not found */ - lua_pushnil(L); /* start 'next' loop */ - while (lua_next(L, -2)) { /* for each pair in table */ - if (lua_type(L, -2) == LUA_TSTRING) { /* ignore non-string keys */ - if (lua_rawequal(L, objidx, -1)) { /* found object? */ - lua_pop(L, 1); /* remove value (but keep name) */ - return 1; - } - else if (findfield(L, objidx, level - 1)) { /* try recursively */ - lua_remove(L, -2); /* remove table (but keep name) */ - lua_pushliteral(L, "."); - lua_insert(L, -2); /* place '.' between the two names */ - lua_concat(L, 3); - return 1; - } - } - lua_pop(L, 1); /* remove value */ - } - return 0; /* not found */ -} - - -/* -** Search for a name for a function in all loaded modules -*/ -static int pushglobalfuncname (lua_State *L, lua_Debug *ar) { - int top = lua_gettop(L); - lua_getinfo(L, "f", ar); /* push function */ - lua_getfield(L, LUA_REGISTRYINDEX, LUA_LOADED_TABLE); - if (findfield(L, top + 1, 2)) { - const char *name = lua_tostring(L, -1); - if (strncmp(name, "_G.", 3) == 0) { /* name start with '_G.'? */ - lua_pushstring(L, name + 3); /* push name without prefix */ - lua_remove(L, -2); /* remove original name */ - } - lua_copy(L, -1, top + 1); /* move name to proper place */ - lua_pop(L, 2); /* remove pushed values */ - return 1; - } - else { - lua_settop(L, top); /* remove function and global table */ - return 0; - } -} - - -static void pushfuncname (lua_State *L, lua_Debug *ar) { - if (pushglobalfuncname(L, ar)) { /* try first a global name */ - lua_pushfstring(L, "function '%s'", lua_tostring(L, -1)); - lua_remove(L, -2); /* remove name */ - } - else if (*ar->namewhat != '\0') /* is there a name from code? */ - lua_pushfstring(L, "%s '%s'", ar->namewhat, ar->name); /* use it */ - else if (*ar->what == 'm') /* main? */ - lua_pushliteral(L, "main chunk"); - else if (*ar->what != 'C') /* for Lua functions, use */ - lua_pushfstring(L, "function <%s:%d>", ar->short_src, ar->linedefined); - else /* nothing left... */ - lua_pushliteral(L, "?"); -} - - -static int lastlevel (lua_State *L) { - lua_Debug ar; - int li = 1, le = 1; - /* find an upper bound */ - while (lua_getstack(L, le, &ar)) { li = le; le *= 2; } - /* do a binary search */ - while (li < le) { - int m = (li + le)/2; - if (lua_getstack(L, m, &ar)) li = m + 1; - else le = m; - } - return le - 1; -} - - -LUALIB_API void luaL_traceback (lua_State *L, lua_State *L1, - const char *msg, int level) { - lua_Debug ar; - int top = lua_gettop(L); - int last = lastlevel(L1); - int n1 = (last - level > LEVELS1 + LEVELS2) ? LEVELS1 : -1; - if (msg) - lua_pushfstring(L, "%s\n", msg); - luaL_checkstack(L, 10, NULL); - lua_pushliteral(L, "stack traceback:"); - while (lua_getstack(L1, level++, &ar)) { - if (n1-- == 0) { /* too many levels? */ - lua_pushliteral(L, "\n\t..."); /* add a '...' */ - level = last - LEVELS2 + 1; /* and skip to last ones */ - } - else { - lua_getinfo(L1, "Slnt", &ar); - lua_pushfstring(L, "\n\t%s:", ar.short_src); - if (ar.currentline > 0) - lua_pushfstring(L, "%d:", ar.currentline); - lua_pushliteral(L, " in "); - pushfuncname(L, &ar); - if (ar.istailcall) - lua_pushliteral(L, "\n\t(...tail calls...)"); - lua_concat(L, lua_gettop(L) - top); - } - } - lua_concat(L, lua_gettop(L) - top); -} - -/* }====================================================== */ - - -/* -** {====================================================== -** Error-report functions -** ======================================================= -*/ - -LUALIB_API int luaL_argerror (lua_State *L, int arg, const char *extramsg) { - lua_Debug ar; - if (!lua_getstack(L, 0, &ar)) /* no stack frame? */ - return luaL_error(L, "bad argument #%d (%s)", arg, extramsg); - lua_getinfo(L, "n", &ar); - if (strcmp(ar.namewhat, "method") == 0) { - arg--; /* do not count 'self' */ - if (arg == 0) /* error is in the self argument itself? */ - return luaL_error(L, "calling '%s' on bad self (%s)", - ar.name, extramsg); - } - if (ar.name == NULL) - ar.name = (pushglobalfuncname(L, &ar)) ? lua_tostring(L, -1) : "?"; - return luaL_error(L, "bad argument #%d to '%s' (%s)", - arg, ar.name, extramsg); -} - - -static int typeerror (lua_State *L, int arg, const char *tname) { - const char *msg; - const char *typearg; /* name for the type of the actual argument */ - if (luaL_getmetafield(L, arg, "__name") == LUA_TSTRING) - typearg = lua_tostring(L, -1); /* use the given type name */ - else if (lua_type(L, arg) == LUA_TLIGHTUSERDATA) - typearg = "light userdata"; /* special name for messages */ - else - typearg = luaL_typename(L, arg); /* standard name */ - msg = lua_pushfstring(L, "%s expected, got %s", tname, typearg); - return luaL_argerror(L, arg, msg); -} - - -static void tag_error (lua_State *L, int arg, int tag) { - typeerror(L, arg, lua_typename(L, tag)); -} - - -/* -** The use of 'lua_pushfstring' ensures this function does not -** need reserved stack space when called. -*/ -LUALIB_API void luaL_where (lua_State *L, int level) { - lua_Debug ar; - if (lua_getstack(L, level, &ar)) { /* check function at level */ - lua_getinfo(L, "Sl", &ar); /* get info about it */ - if (ar.currentline > 0) { /* is there info? */ - lua_pushfstring(L, "%s:%d: ", ar.short_src, ar.currentline); - return; - } - } - lua_pushfstring(L, ""); /* else, no information available... */ -} - - -/* -** Again, the use of 'lua_pushvfstring' ensures this function does -** not need reserved stack space when called. (At worst, it generates -** an error with "stack overflow" instead of the given message.) -*/ -LUALIB_API int luaL_error (lua_State *L, const char *fmt, ...) { - va_list argp; - va_start(argp, fmt); - luaL_where(L, 1); - lua_pushvfstring(L, fmt, argp); - va_end(argp); - lua_concat(L, 2); - return lua_error(L); -} - - -LUALIB_API int luaL_fileresult (lua_State *L, int stat, const char *fname) { - int en = errno; /* calls to Lua API may change this value */ - if (stat) { - lua_pushboolean(L, 1); - return 1; - } - else { - lua_pushnil(L); - if (fname) - lua_pushfstring(L, "%s: %s", fname, strerror(en)); - else - lua_pushstring(L, strerror(en)); - lua_pushinteger(L, en); - return 3; - } -} - - -#if !defined(l_inspectstat) /* { */ - -#if defined(LUA_USE_POSIX) - -#include - -/* -** use appropriate macros to interpret 'pclose' return status -*/ -#define l_inspectstat(stat,what) \ - if (WIFEXITED(stat)) { stat = WEXITSTATUS(stat); } \ - else if (WIFSIGNALED(stat)) { stat = WTERMSIG(stat); what = "signal"; } - -#else - -#define l_inspectstat(stat,what) /* no op */ - -#endif - -#endif /* } */ - - -LUALIB_API int luaL_execresult (lua_State *L, int stat) { - const char *what = "exit"; /* type of termination */ - if (stat == -1) /* error? */ - return luaL_fileresult(L, 0, NULL); - else { - l_inspectstat(stat, what); /* interpret result */ - if (*what == 'e' && stat == 0) /* successful termination? */ - lua_pushboolean(L, 1); - else - lua_pushnil(L); - lua_pushstring(L, what); - lua_pushinteger(L, stat); - return 3; /* return true/nil,what,code */ - } -} - -/* }====================================================== */ - - -/* -** {====================================================== -** Userdata's metatable manipulation -** ======================================================= -*/ - -LUALIB_API int luaL_newmetatable (lua_State *L, const char *tname) { - if (luaL_getmetatable(L, tname) != LUA_TNIL) /* name already in use? */ - return 0; /* leave previous value on top, but return 0 */ - lua_pop(L, 1); - lua_createtable(L, 0, 2); /* create metatable */ - lua_pushstring(L, tname); - lua_setfield(L, -2, "__name"); /* metatable.__name = tname */ - lua_pushvalue(L, -1); - lua_setfield(L, LUA_REGISTRYINDEX, tname); /* registry.name = metatable */ - return 1; -} - - -LUALIB_API void luaL_setmetatable (lua_State *L, const char *tname) { - luaL_getmetatable(L, tname); - lua_setmetatable(L, -2); -} - - -LUALIB_API void *luaL_testudata (lua_State *L, int ud, const char *tname) { - void *p = lua_touserdata(L, ud); - if (p != NULL) { /* value is a userdata? */ - if (lua_getmetatable(L, ud)) { /* does it have a metatable? */ - luaL_getmetatable(L, tname); /* get correct metatable */ - if (!lua_rawequal(L, -1, -2)) /* not the same? */ - p = NULL; /* value is a userdata with wrong metatable */ - lua_pop(L, 2); /* remove both metatables */ - return p; - } - } - return NULL; /* value is not a userdata with a metatable */ -} - - -LUALIB_API void *luaL_checkudata (lua_State *L, int ud, const char *tname) { - void *p = luaL_testudata(L, ud, tname); - if (p == NULL) typeerror(L, ud, tname); - return p; -} - -/* }====================================================== */ - - -/* -** {====================================================== -** Argument check functions -** ======================================================= -*/ - -LUALIB_API int luaL_checkoption (lua_State *L, int arg, const char *def, - const char *const lst[]) { - const char *name = (def) ? luaL_optstring(L, arg, def) : - luaL_checkstring(L, arg); - int i; - for (i=0; lst[i]; i++) - if (strcmp(lst[i], name) == 0) - return i; - return luaL_argerror(L, arg, - lua_pushfstring(L, "invalid option '%s'", name)); -} - - -/* -** Ensures the stack has at least 'space' extra slots, raising an error -** if it cannot fulfill the request. (The error handling needs a few -** extra slots to format the error message. In case of an error without -** this extra space, Lua will generate the same 'stack overflow' error, -** but without 'msg'.) -*/ -LUALIB_API void luaL_checkstack (lua_State *L, int space, const char *msg) { - if (!lua_checkstack(L, space)) { - if (msg) - luaL_error(L, "stack overflow (%s)", msg); - else - luaL_error(L, "stack overflow"); - } -} - - -LUALIB_API void luaL_checktype (lua_State *L, int arg, int t) { - if (lua_type(L, arg) != t) - tag_error(L, arg, t); -} - - -LUALIB_API void luaL_checkany (lua_State *L, int arg) { - if (lua_type(L, arg) == LUA_TNONE) - luaL_argerror(L, arg, "value expected"); -} - - -LUALIB_API const char *luaL_checklstring (lua_State *L, int arg, size_t *len) { - const char *s = lua_tolstring(L, arg, len); - if (!s) tag_error(L, arg, LUA_TSTRING); - return s; -} - - -LUALIB_API const char *luaL_optlstring (lua_State *L, int arg, - const char *def, size_t *len) { - if (lua_isnoneornil(L, arg)) { - if (len) - *len = (def ? strlen(def) : 0); - return def; - } - else return luaL_checklstring(L, arg, len); -} - - -LUALIB_API lua_Number luaL_checknumber (lua_State *L, int arg) { - int isnum; - lua_Number d = lua_tonumberx(L, arg, &isnum); - if (!isnum) - tag_error(L, arg, LUA_TNUMBER); - return d; -} - - -LUALIB_API lua_Number luaL_optnumber (lua_State *L, int arg, lua_Number def) { - return luaL_opt(L, luaL_checknumber, arg, def); -} - - -static void interror (lua_State *L, int arg) { - if (lua_isnumber(L, arg)) - luaL_argerror(L, arg, "number has no integer representation"); - else - tag_error(L, arg, LUA_TNUMBER); -} - - -LUALIB_API lua_Integer luaL_checkinteger (lua_State *L, int arg) { - int isnum; - lua_Integer d = lua_tointegerx(L, arg, &isnum); - if (!isnum) { - interror(L, arg); - } - return d; -} - - -LUALIB_API lua_Integer luaL_optinteger (lua_State *L, int arg, - lua_Integer def) { - return luaL_opt(L, luaL_checkinteger, arg, def); -} - -/* }====================================================== */ - - -/* -** {====================================================== -** Generic Buffer manipulation -** ======================================================= -*/ - -/* userdata to box arbitrary data */ -typedef struct UBox { - void *box; - size_t bsize; -} UBox; - - -static void *resizebox (lua_State *L, int idx, size_t newsize) { - void *ud; - lua_Alloc allocf = lua_getallocf(L, &ud); - UBox *box = (UBox *)lua_touserdata(L, idx); - void *temp = allocf(ud, box->box, box->bsize, newsize); - if (temp == NULL && newsize > 0) { /* allocation error? */ - resizebox(L, idx, 0); /* free buffer */ - luaL_error(L, "not enough memory for buffer allocation"); - } - box->box = temp; - box->bsize = newsize; - return temp; -} - - -static int boxgc (lua_State *L) { - resizebox(L, 1, 0); - return 0; -} - - -static void *newbox (lua_State *L, size_t newsize) { - UBox *box = (UBox *)lua_newuserdata(L, sizeof(UBox)); - box->box = NULL; - box->bsize = 0; - if (luaL_newmetatable(L, "LUABOX")) { /* creating metatable? */ - lua_pushcfunction(L, boxgc); - lua_setfield(L, -2, "__gc"); /* metatable.__gc = boxgc */ - } - lua_setmetatable(L, -2); - return resizebox(L, -1, newsize); -} - - -/* -** check whether buffer is using a userdata on the stack as a temporary -** buffer -*/ -#define buffonstack(B) ((B)->b != (B)->initb) - - -/* -** returns a pointer to a free area with at least 'sz' bytes -*/ -LUALIB_API char *luaL_prepbuffsize (luaL_Buffer *B, size_t sz) { - lua_State *L = B->L; - if (B->size - B->n < sz) { /* not enough space? */ - char *newbuff; - size_t newsize = B->size * 2; /* double buffer size */ - if (newsize - B->n < sz) /* not big enough? */ - newsize = B->n + sz; - if (newsize < B->n || newsize - B->n < sz) - luaL_error(L, "buffer too large"); - /* create larger buffer */ - if (buffonstack(B)) - newbuff = (char *)resizebox(L, -1, newsize); - else { /* no buffer yet */ - newbuff = (char *)newbox(L, newsize); - memcpy(newbuff, B->b, B->n * sizeof(char)); /* copy original content */ - } - B->b = newbuff; - B->size = newsize; - } - return &B->b[B->n]; -} - - -LUALIB_API void luaL_addlstring (luaL_Buffer *B, const char *s, size_t l) { - if (l > 0) { /* avoid 'memcpy' when 's' can be NULL */ - char *b = luaL_prepbuffsize(B, l); - memcpy(b, s, l * sizeof(char)); - luaL_addsize(B, l); - } -} - - -LUALIB_API void luaL_addstring (luaL_Buffer *B, const char *s) { - luaL_addlstring(B, s, strlen(s)); -} - - -LUALIB_API void luaL_pushresult (luaL_Buffer *B) { - lua_State *L = B->L; - lua_pushlstring(L, B->b, B->n); - if (buffonstack(B)) { - resizebox(L, -2, 0); /* delete old buffer */ - lua_remove(L, -2); /* remove its header from the stack */ - } -} - - -LUALIB_API void luaL_pushresultsize (luaL_Buffer *B, size_t sz) { - luaL_addsize(B, sz); - luaL_pushresult(B); -} - - -LUALIB_API void luaL_addvalue (luaL_Buffer *B) { - lua_State *L = B->L; - size_t l; - const char *s = lua_tolstring(L, -1, &l); - if (buffonstack(B)) - lua_insert(L, -2); /* put value below buffer */ - luaL_addlstring(B, s, l); - lua_remove(L, (buffonstack(B)) ? -2 : -1); /* remove value */ -} - - -LUALIB_API void luaL_buffinit (lua_State *L, luaL_Buffer *B) { - B->L = L; - B->b = B->initb; - B->n = 0; - B->size = LUAL_BUFFERSIZE; -} - - -LUALIB_API char *luaL_buffinitsize (lua_State *L, luaL_Buffer *B, size_t sz) { - luaL_buffinit(L, B); - return luaL_prepbuffsize(B, sz); -} - -/* }====================================================== */ - - -/* -** {====================================================== -** Reference system -** ======================================================= -*/ - -/* index of free-list header */ -#define freelist 0 - - -LUALIB_API int luaL_ref (lua_State *L, int t) { - int ref; - if (lua_isnil(L, -1)) { - lua_pop(L, 1); /* remove from stack */ - return LUA_REFNIL; /* 'nil' has a unique fixed reference */ - } - t = lua_absindex(L, t); - lua_rawgeti(L, t, freelist); /* get first free element */ - ref = (int)lua_tointeger(L, -1); /* ref = t[freelist] */ - lua_pop(L, 1); /* remove it from stack */ - if (ref != 0) { /* any free element? */ - lua_rawgeti(L, t, ref); /* remove it from list */ - lua_rawseti(L, t, freelist); /* (t[freelist] = t[ref]) */ - } - else /* no free elements */ - ref = (int)lua_rawlen(L, t) + 1; /* get a new reference */ - lua_rawseti(L, t, ref); - return ref; -} - - -LUALIB_API void luaL_unref (lua_State *L, int t, int ref) { - if (ref >= 0) { - t = lua_absindex(L, t); - lua_rawgeti(L, t, freelist); - lua_rawseti(L, t, ref); /* t[ref] = t[freelist] */ - lua_pushinteger(L, ref); - lua_rawseti(L, t, freelist); /* t[freelist] = ref */ - } -} - -/* }====================================================== */ - - -/* -** {====================================================== -** Load functions -** ======================================================= -*/ - -typedef struct LoadF { - int n; /* number of pre-read characters */ - FILE *f; /* file being read */ - char buff[BUFSIZ]; /* area for reading file */ -} LoadF; - - -static const char *getF (lua_State *L, void *ud, size_t *size) { - LoadF *lf = (LoadF *)ud; - (void)L; /* not used */ - if (lf->n > 0) { /* are there pre-read characters to be read? */ - *size = lf->n; /* return them (chars already in buffer) */ - lf->n = 0; /* no more pre-read characters */ - } - else { /* read a block from file */ - /* 'fread' can return > 0 *and* set the EOF flag. If next call to - 'getF' called 'fread', it might still wait for user input. - The next check avoids this problem. */ - if (feof(lf->f)) return NULL; - *size = fread(lf->buff, 1, sizeof(lf->buff), lf->f); /* read block */ - } - return lf->buff; -} - - -static int errfile (lua_State *L, const char *what, int fnameindex) { - const char *serr = strerror(errno); - const char *filename = lua_tostring(L, fnameindex) + 1; - lua_pushfstring(L, "cannot %s %s: %s", what, filename, serr); - lua_remove(L, fnameindex); - return LUA_ERRFILE; -} - - -static int skipBOM (LoadF *lf) { - const char *p = "\xEF\xBB\xBF"; /* UTF-8 BOM mark */ - int c; - lf->n = 0; - do { - c = getc(lf->f); - if (c == EOF || c != *(const unsigned char *)p++) return c; - lf->buff[lf->n++] = c; /* to be read by the parser */ - } while (*p != '\0'); - lf->n = 0; /* prefix matched; discard it */ - return getc(lf->f); /* return next character */ -} - - -/* -** reads the first character of file 'f' and skips an optional BOM mark -** in its beginning plus its first line if it starts with '#'. Returns -** true if it skipped the first line. In any case, '*cp' has the -** first "valid" character of the file (after the optional BOM and -** a first-line comment). -*/ -static int skipcomment (LoadF *lf, int *cp) { - int c = *cp = skipBOM(lf); - if (c == '#') { /* first line is a comment (Unix exec. file)? */ - do { /* skip first line */ - c = getc(lf->f); - } while (c != EOF && c != '\n'); - *cp = getc(lf->f); /* skip end-of-line, if present */ - return 1; /* there was a comment */ - } - else return 0; /* no comment */ -} - - -LUALIB_API int luaL_loadfilex (lua_State *L, const char *filename, - const char *mode) { - LoadF lf; - int status, readstatus; - int c; - int fnameindex = lua_gettop(L) + 1; /* index of filename on the stack */ - if (filename == NULL) { - lua_pushliteral(L, "=stdin"); - lf.f = stdin; - } - else { - lua_pushfstring(L, "@%s", filename); - lf.f = fopen(filename, "r"); - if (lf.f == NULL) return errfile(L, "open", fnameindex); - } - if (skipcomment(&lf, &c)) /* read initial portion */ - lf.buff[lf.n++] = '\n'; /* add line to correct line numbers */ - if (c == LUA_SIGNATURE[0] && filename) { /* binary file? */ - lf.f = freopen(filename, "rb", lf.f); /* reopen in binary mode */ - if (lf.f == NULL) return errfile(L, "reopen", fnameindex); - skipcomment(&lf, &c); /* re-read initial portion */ - } - if (c != EOF) - lf.buff[lf.n++] = c; /* 'c' is the first character of the stream */ - status = lua_load(L, getF, &lf, lua_tostring(L, -1), mode); - readstatus = ferror(lf.f); - if (filename) fclose(lf.f); /* close file (even in case of errors) */ - if (readstatus) { - lua_settop(L, fnameindex); /* ignore results from 'lua_load' */ - return errfile(L, "read", fnameindex); - } - lua_remove(L, fnameindex); - return status; -} - - -typedef struct LoadS { - const char *s; - size_t size; -} LoadS; - - -static const char *getS (lua_State *L, void *ud, size_t *size) { - LoadS *ls = (LoadS *)ud; - (void)L; /* not used */ - if (ls->size == 0) return NULL; - *size = ls->size; - ls->size = 0; - return ls->s; -} - - -LUALIB_API int luaL_loadbufferx (lua_State *L, const char *buff, size_t size, - const char *name, const char *mode) { - LoadS ls; - ls.s = buff; - ls.size = size; - return lua_load(L, getS, &ls, name, mode); -} - - -LUALIB_API int luaL_loadstring (lua_State *L, const char *s) { - return luaL_loadbuffer(L, s, strlen(s), s); -} - -/* }====================================================== */ - - - -LUALIB_API int luaL_getmetafield (lua_State *L, int obj, const char *event) { - if (!lua_getmetatable(L, obj)) /* no metatable? */ - return LUA_TNIL; - else { - int tt; - lua_pushstring(L, event); - tt = lua_rawget(L, -2); - if (tt == LUA_TNIL) /* is metafield nil? */ - lua_pop(L, 2); /* remove metatable and metafield */ - else - lua_remove(L, -2); /* remove only metatable */ - return tt; /* return metafield type */ - } -} - - -LUALIB_API int luaL_callmeta (lua_State *L, int obj, const char *event) { - obj = lua_absindex(L, obj); - if (luaL_getmetafield(L, obj, event) == LUA_TNIL) /* no metafield? */ - return 0; - lua_pushvalue(L, obj); - lua_call(L, 1, 1); - return 1; -} - - -LUALIB_API lua_Integer luaL_len (lua_State *L, int idx) { - lua_Integer l; - int isnum; - lua_len(L, idx); - l = lua_tointegerx(L, -1, &isnum); - if (!isnum) - luaL_error(L, "object length is not an integer"); - lua_pop(L, 1); /* remove object */ - return l; -} - - -LUALIB_API const char *luaL_tolstring (lua_State *L, int idx, size_t *len) { - if (luaL_callmeta(L, idx, "__tostring")) { /* metafield? */ - if (!lua_isstring(L, -1)) - luaL_error(L, "'__tostring' must return a string"); - } - else { - switch (lua_type(L, idx)) { - case LUA_TNUMBER: { - if (lua_isinteger(L, idx)) - lua_pushfstring(L, "%I", (LUAI_UACINT)lua_tointeger(L, idx)); - else - lua_pushfstring(L, "%f", (LUAI_UACNUMBER)lua_tonumber(L, idx)); - break; - } - case LUA_TSTRING: - lua_pushvalue(L, idx); - break; - case LUA_TBOOLEAN: - lua_pushstring(L, (lua_toboolean(L, idx) ? "true" : "false")); - break; - case LUA_TNIL: - lua_pushliteral(L, "nil"); - break; - default: { - int tt = luaL_getmetafield(L, idx, "__name"); /* try name */ - const char *kind = (tt == LUA_TSTRING) ? lua_tostring(L, -1) : - luaL_typename(L, idx); - lua_pushfstring(L, "%s: %p", kind, lua_topointer(L, idx)); - if (tt != LUA_TNIL) - lua_remove(L, -2); /* remove '__name' */ - break; - } - } - } - return lua_tolstring(L, -1, len); -} - - -/* -** {====================================================== -** Compatibility with 5.1 module functions -** ======================================================= -*/ -#if defined(LUA_COMPAT_MODULE) - -static const char *luaL_findtable (lua_State *L, int idx, - const char *fname, int szhint) { - const char *e; - if (idx) lua_pushvalue(L, idx); - do { - e = strchr(fname, '.'); - if (e == NULL) e = fname + strlen(fname); - lua_pushlstring(L, fname, e - fname); - if (lua_rawget(L, -2) == LUA_TNIL) { /* no such field? */ - lua_pop(L, 1); /* remove this nil */ - lua_createtable(L, 0, (*e == '.' ? 1 : szhint)); /* new table for field */ - lua_pushlstring(L, fname, e - fname); - lua_pushvalue(L, -2); - lua_settable(L, -4); /* set new table into field */ - } - else if (!lua_istable(L, -1)) { /* field has a non-table value? */ - lua_pop(L, 2); /* remove table and value */ - return fname; /* return problematic part of the name */ - } - lua_remove(L, -2); /* remove previous table */ - fname = e + 1; - } while (*e == '.'); - return NULL; -} - - -/* -** Count number of elements in a luaL_Reg list. -*/ -static int libsize (const luaL_Reg *l) { - int size = 0; - for (; l && l->name; l++) size++; - return size; -} - - -/* -** Find or create a module table with a given name. The function -** first looks at the LOADED table and, if that fails, try a -** global variable with that name. In any case, leaves on the stack -** the module table. -*/ -LUALIB_API void luaL_pushmodule (lua_State *L, const char *modname, - int sizehint) { - luaL_findtable(L, LUA_REGISTRYINDEX, LUA_LOADED_TABLE, 1); - if (lua_getfield(L, -1, modname) != LUA_TTABLE) { /* no LOADED[modname]? */ - lua_pop(L, 1); /* remove previous result */ - /* try global variable (and create one if it does not exist) */ - lua_pushglobaltable(L); - if (luaL_findtable(L, 0, modname, sizehint) != NULL) - luaL_error(L, "name conflict for module '%s'", modname); - lua_pushvalue(L, -1); - lua_setfield(L, -3, modname); /* LOADED[modname] = new table */ - } - lua_remove(L, -2); /* remove LOADED table */ -} - - -LUALIB_API void luaL_openlib (lua_State *L, const char *libname, - const luaL_Reg *l, int nup) { - luaL_checkversion(L); - if (libname) { - luaL_pushmodule(L, libname, libsize(l)); /* get/create library table */ - lua_insert(L, -(nup + 1)); /* move library table to below upvalues */ - } - if (l) - luaL_setfuncs(L, l, nup); - else - lua_pop(L, nup); /* remove upvalues */ -} - -#endif -/* }====================================================== */ - -/* -** set functions from list 'l' into table at top - 'nup'; each -** function gets the 'nup' elements at the top as upvalues. -** Returns with only the table at the stack. -*/ -LUALIB_API void luaL_setfuncs (lua_State *L, const luaL_Reg *l, int nup) { - luaL_checkstack(L, nup, "too many upvalues"); - for (; l->name != NULL; l++) { /* fill the table with given functions */ - int i; - for (i = 0; i < nup; i++) /* copy upvalues to the top */ - lua_pushvalue(L, -nup); - lua_pushcclosure(L, l->func, nup); /* closure with those upvalues */ - lua_setfield(L, -(nup + 2), l->name); - } - lua_pop(L, nup); /* remove upvalues */ -} - - -/* -** ensure that stack[idx][fname] has a table and push that table -** into the stack -*/ -LUALIB_API int luaL_getsubtable (lua_State *L, int idx, const char *fname) { - if (lua_getfield(L, idx, fname) == LUA_TTABLE) - return 1; /* table already there */ - else { - lua_pop(L, 1); /* remove previous result */ - idx = lua_absindex(L, idx); - lua_newtable(L); - lua_pushvalue(L, -1); /* copy to be left at top */ - lua_setfield(L, idx, fname); /* assign new table to field */ - return 0; /* false, because did not find table there */ - } -} - - -/* -** Stripped-down 'require': After checking "loaded" table, calls 'openf' -** to open a module, registers the result in 'package.loaded' table and, -** if 'glb' is true, also registers the result in the global table. -** Leaves resulting module on the top. -*/ -LUALIB_API void luaL_requiref (lua_State *L, const char *modname, - lua_CFunction openf, int glb) { - luaL_getsubtable(L, LUA_REGISTRYINDEX, LUA_LOADED_TABLE); - lua_getfield(L, -1, modname); /* LOADED[modname] */ - if (!lua_toboolean(L, -1)) { /* package not already loaded? */ - lua_pop(L, 1); /* remove field */ - lua_pushcfunction(L, openf); - lua_pushstring(L, modname); /* argument to open function */ - lua_call(L, 1, 1); /* call 'openf' to open module */ - lua_pushvalue(L, -1); /* make copy of module (call result) */ - lua_setfield(L, -3, modname); /* LOADED[modname] = module */ - } - lua_remove(L, -2); /* remove LOADED table */ - if (glb) { - lua_pushvalue(L, -1); /* copy of module */ - lua_setglobal(L, modname); /* _G[modname] = module */ - } -} - - -LUALIB_API const char *luaL_gsub (lua_State *L, const char *s, const char *p, - const char *r) { - const char *wild; - size_t l = strlen(p); - luaL_Buffer b; - luaL_buffinit(L, &b); - while ((wild = strstr(s, p)) != NULL) { - luaL_addlstring(&b, s, wild - s); /* push prefix */ - luaL_addstring(&b, r); /* push replacement in place of pattern */ - s = wild + l; /* continue after 'p' */ - } - luaL_addstring(&b, s); /* push last suffix */ - luaL_pushresult(&b); - return lua_tostring(L, -1); -} - - -static void *l_alloc (void *ud, void *ptr, size_t osize, size_t nsize) { - (void)ud; (void)osize; /* not used */ - if (nsize == 0) { - free(ptr); - return NULL; - } - else { /* cannot fail when shrinking a block */ - void *newptr = realloc(ptr, nsize); - if (newptr == NULL && ptr != NULL && nsize <= osize) - return ptr; /* keep the original block */ - else /* no fail or not shrinking */ - return newptr; /* use the new block */ - } -} - - -static int panic (lua_State *L) { - lua_writestringerror("PANIC: unprotected error in call to Lua API (%s)\n", - lua_tostring(L, -1)); - return 0; /* return to Lua to abort */ -} - - -LUALIB_API lua_State *luaL_newstate (void) { - lua_State *L = lua_newstate(l_alloc, NULL); - if (L) lua_atpanic(L, &panic); - return L; -} - - -LUALIB_API void luaL_checkversion_ (lua_State *L, lua_Number ver, size_t sz) { - const lua_Number *v = lua_version(L); - if (sz != LUAL_NUMSIZES) /* check numeric types */ - luaL_error(L, "core and library have incompatible numeric types"); - if (v != lua_version(NULL)) - luaL_error(L, "multiple Lua VMs detected"); - else if (*v != ver) - luaL_error(L, "version mismatch: app. needs %f, Lua core provides %f", - (LUAI_UACNUMBER)ver, (LUAI_UACNUMBER)*v); -} - diff --git a/lib/lua-5.3/src/lauxlib.h b/lib/lua-5.3/src/lauxlib.h deleted file mode 100644 index 9857d3a..0000000 --- a/lib/lua-5.3/src/lauxlib.h +++ /dev/null @@ -1,264 +0,0 @@ -/* -** $Id: lauxlib.h,v 1.131.1.1 2017/04/19 17:20:42 roberto Exp $ -** Auxiliary functions for building Lua libraries -** See Copyright Notice in lua.h -*/ - - -#ifndef lauxlib_h -#define lauxlib_h - - -#include -#include - -#include "lua.h" - - - -/* extra error code for 'luaL_loadfilex' */ -#define LUA_ERRFILE (LUA_ERRERR+1) - - -/* key, in the registry, for table of loaded modules */ -#define LUA_LOADED_TABLE "_LOADED" - - -/* key, in the registry, for table of preloaded loaders */ -#define LUA_PRELOAD_TABLE "_PRELOAD" - - -typedef struct luaL_Reg { - const char *name; - lua_CFunction func; -} luaL_Reg; - - -#define LUAL_NUMSIZES (sizeof(lua_Integer)*16 + sizeof(lua_Number)) - -LUALIB_API void (luaL_checkversion_) (lua_State *L, lua_Number ver, size_t sz); -#define luaL_checkversion(L) \ - luaL_checkversion_(L, LUA_VERSION_NUM, LUAL_NUMSIZES) - -LUALIB_API int (luaL_getmetafield) (lua_State *L, int obj, const char *e); -LUALIB_API int (luaL_callmeta) (lua_State *L, int obj, const char *e); -LUALIB_API const char *(luaL_tolstring) (lua_State *L, int idx, size_t *len); -LUALIB_API int (luaL_argerror) (lua_State *L, int arg, const char *extramsg); -LUALIB_API const char *(luaL_checklstring) (lua_State *L, int arg, - size_t *l); -LUALIB_API const char *(luaL_optlstring) (lua_State *L, int arg, - const char *def, size_t *l); -LUALIB_API lua_Number (luaL_checknumber) (lua_State *L, int arg); -LUALIB_API lua_Number (luaL_optnumber) (lua_State *L, int arg, lua_Number def); - -LUALIB_API lua_Integer (luaL_checkinteger) (lua_State *L, int arg); -LUALIB_API lua_Integer (luaL_optinteger) (lua_State *L, int arg, - lua_Integer def); - -LUALIB_API void (luaL_checkstack) (lua_State *L, int sz, const char *msg); -LUALIB_API void (luaL_checktype) (lua_State *L, int arg, int t); -LUALIB_API void (luaL_checkany) (lua_State *L, int arg); - -LUALIB_API int (luaL_newmetatable) (lua_State *L, const char *tname); -LUALIB_API void (luaL_setmetatable) (lua_State *L, const char *tname); -LUALIB_API void *(luaL_testudata) (lua_State *L, int ud, const char *tname); -LUALIB_API void *(luaL_checkudata) (lua_State *L, int ud, const char *tname); - -LUALIB_API void (luaL_where) (lua_State *L, int lvl); -LUALIB_API int (luaL_error) (lua_State *L, const char *fmt, ...); - -LUALIB_API int (luaL_checkoption) (lua_State *L, int arg, const char *def, - const char *const lst[]); - -LUALIB_API int (luaL_fileresult) (lua_State *L, int stat, const char *fname); -LUALIB_API int (luaL_execresult) (lua_State *L, int stat); - -/* predefined references */ -#define LUA_NOREF (-2) -#define LUA_REFNIL (-1) - -LUALIB_API int (luaL_ref) (lua_State *L, int t); -LUALIB_API void (luaL_unref) (lua_State *L, int t, int ref); - -LUALIB_API int (luaL_loadfilex) (lua_State *L, const char *filename, - const char *mode); - -#define luaL_loadfile(L,f) luaL_loadfilex(L,f,NULL) - -LUALIB_API int (luaL_loadbufferx) (lua_State *L, const char *buff, size_t sz, - const char *name, const char *mode); -LUALIB_API int (luaL_loadstring) (lua_State *L, const char *s); - -LUALIB_API lua_State *(luaL_newstate) (void); - -LUALIB_API lua_Integer (luaL_len) (lua_State *L, int idx); - -LUALIB_API const char *(luaL_gsub) (lua_State *L, const char *s, const char *p, - const char *r); - -LUALIB_API void (luaL_setfuncs) (lua_State *L, const luaL_Reg *l, int nup); - -LUALIB_API int (luaL_getsubtable) (lua_State *L, int idx, const char *fname); - -LUALIB_API void (luaL_traceback) (lua_State *L, lua_State *L1, - const char *msg, int level); - -LUALIB_API void (luaL_requiref) (lua_State *L, const char *modname, - lua_CFunction openf, int glb); - -/* -** =============================================================== -** some useful macros -** =============================================================== -*/ - - -#define luaL_newlibtable(L,l) \ - lua_createtable(L, 0, sizeof(l)/sizeof((l)[0]) - 1) - -#define luaL_newlib(L,l) \ - (luaL_checkversion(L), luaL_newlibtable(L,l), luaL_setfuncs(L,l,0)) - -#define luaL_argcheck(L, cond,arg,extramsg) \ - ((void)((cond) || luaL_argerror(L, (arg), (extramsg)))) -#define luaL_checkstring(L,n) (luaL_checklstring(L, (n), NULL)) -#define luaL_optstring(L,n,d) (luaL_optlstring(L, (n), (d), NULL)) - -#define luaL_typename(L,i) lua_typename(L, lua_type(L,(i))) - -#define luaL_dofile(L, fn) \ - (luaL_loadfile(L, fn) || lua_pcall(L, 0, LUA_MULTRET, 0)) - -#define luaL_dostring(L, s) \ - (luaL_loadstring(L, s) || lua_pcall(L, 0, LUA_MULTRET, 0)) - -#define luaL_getmetatable(L,n) (lua_getfield(L, LUA_REGISTRYINDEX, (n))) - -#define luaL_opt(L,f,n,d) (lua_isnoneornil(L,(n)) ? (d) : f(L,(n))) - -#define luaL_loadbuffer(L,s,sz,n) luaL_loadbufferx(L,s,sz,n,NULL) - - -/* -** {====================================================== -** Generic Buffer manipulation -** ======================================================= -*/ - -typedef struct luaL_Buffer { - char *b; /* buffer address */ - size_t size; /* buffer size */ - size_t n; /* number of characters in buffer */ - lua_State *L; - char initb[LUAL_BUFFERSIZE]; /* initial buffer */ -} luaL_Buffer; - - -#define luaL_addchar(B,c) \ - ((void)((B)->n < (B)->size || luaL_prepbuffsize((B), 1)), \ - ((B)->b[(B)->n++] = (c))) - -#define luaL_addsize(B,s) ((B)->n += (s)) - -LUALIB_API void (luaL_buffinit) (lua_State *L, luaL_Buffer *B); -LUALIB_API char *(luaL_prepbuffsize) (luaL_Buffer *B, size_t sz); -LUALIB_API void (luaL_addlstring) (luaL_Buffer *B, const char *s, size_t l); -LUALIB_API void (luaL_addstring) (luaL_Buffer *B, const char *s); -LUALIB_API void (luaL_addvalue) (luaL_Buffer *B); -LUALIB_API void (luaL_pushresult) (luaL_Buffer *B); -LUALIB_API void (luaL_pushresultsize) (luaL_Buffer *B, size_t sz); -LUALIB_API char *(luaL_buffinitsize) (lua_State *L, luaL_Buffer *B, size_t sz); - -#define luaL_prepbuffer(B) luaL_prepbuffsize(B, LUAL_BUFFERSIZE) - -/* }====================================================== */ - - - -/* -** {====================================================== -** File handles for IO library -** ======================================================= -*/ - -/* -** A file handle is a userdata with metatable 'LUA_FILEHANDLE' and -** initial structure 'luaL_Stream' (it may contain other fields -** after that initial structure). -*/ - -#define LUA_FILEHANDLE "FILE*" - - -typedef struct luaL_Stream { - FILE *f; /* stream (NULL for incompletely created streams) */ - lua_CFunction closef; /* to close stream (NULL for closed streams) */ -} luaL_Stream; - -/* }====================================================== */ - - - -/* compatibility with old module system */ -#if defined(LUA_COMPAT_MODULE) - -LUALIB_API void (luaL_pushmodule) (lua_State *L, const char *modname, - int sizehint); -LUALIB_API void (luaL_openlib) (lua_State *L, const char *libname, - const luaL_Reg *l, int nup); - -#define luaL_register(L,n,l) (luaL_openlib(L,(n),(l),0)) - -#endif - - -/* -** {================================================================== -** "Abstraction Layer" for basic report of messages and errors -** =================================================================== -*/ - -/* print a string */ -#if !defined(lua_writestring) -#define lua_writestring(s,l) fwrite((s), sizeof(char), (l), stdout) -#endif - -/* print a newline and flush the output */ -#if !defined(lua_writeline) -#define lua_writeline() (lua_writestring("\n", 1), fflush(stdout)) -#endif - -/* print an error message */ -#if !defined(lua_writestringerror) -#define lua_writestringerror(s,p) \ - (fprintf(stderr, (s), (p)), fflush(stderr)) -#endif - -/* }================================================================== */ - - -/* -** {============================================================ -** Compatibility with deprecated conversions -** ============================================================= -*/ -#if defined(LUA_COMPAT_APIINTCASTS) - -#define luaL_checkunsigned(L,a) ((lua_Unsigned)luaL_checkinteger(L,a)) -#define luaL_optunsigned(L,a,d) \ - ((lua_Unsigned)luaL_optinteger(L,a,(lua_Integer)(d))) - -#define luaL_checkint(L,n) ((int)luaL_checkinteger(L, (n))) -#define luaL_optint(L,n,d) ((int)luaL_optinteger(L, (n), (d))) - -#define luaL_checklong(L,n) ((long)luaL_checkinteger(L, (n))) -#define luaL_optlong(L,n,d) ((long)luaL_optinteger(L, (n), (d))) - -#endif -/* }============================================================ */ - - - -#endif - - diff --git a/lib/lua-5.3/src/lbaselib.c b/lib/lua-5.3/src/lbaselib.c deleted file mode 100644 index 6460e4f..0000000 --- a/lib/lua-5.3/src/lbaselib.c +++ /dev/null @@ -1,498 +0,0 @@ -/* -** $Id: lbaselib.c,v 1.314.1.1 2017/04/19 17:39:34 roberto Exp $ -** Basic library -** See Copyright Notice in lua.h -*/ - -#define lbaselib_c -#define LUA_LIB - -#include "lprefix.h" - - -#include -#include -#include -#include - -#include "lua.h" - -#include "lauxlib.h" -#include "lualib.h" - - -static int luaB_print (lua_State *L) { - int n = lua_gettop(L); /* number of arguments */ - int i; - lua_getglobal(L, "tostring"); - for (i=1; i<=n; i++) { - const char *s; - size_t l; - lua_pushvalue(L, -1); /* function to be called */ - lua_pushvalue(L, i); /* value to print */ - lua_call(L, 1, 1); - s = lua_tolstring(L, -1, &l); /* get result */ - if (s == NULL) - return luaL_error(L, "'tostring' must return a string to 'print'"); - if (i>1) lua_writestring("\t", 1); - lua_writestring(s, l); - lua_pop(L, 1); /* pop result */ - } - lua_writeline(); - return 0; -} - - -#define SPACECHARS " \f\n\r\t\v" - -static const char *b_str2int (const char *s, int base, lua_Integer *pn) { - lua_Unsigned n = 0; - int neg = 0; - s += strspn(s, SPACECHARS); /* skip initial spaces */ - if (*s == '-') { s++; neg = 1; } /* handle signal */ - else if (*s == '+') s++; - if (!isalnum((unsigned char)*s)) /* no digit? */ - return NULL; - do { - int digit = (isdigit((unsigned char)*s)) ? *s - '0' - : (toupper((unsigned char)*s) - 'A') + 10; - if (digit >= base) return NULL; /* invalid numeral */ - n = n * base + digit; - s++; - } while (isalnum((unsigned char)*s)); - s += strspn(s, SPACECHARS); /* skip trailing spaces */ - *pn = (lua_Integer)((neg) ? (0u - n) : n); - return s; -} - - -static int luaB_tonumber (lua_State *L) { - if (lua_isnoneornil(L, 2)) { /* standard conversion? */ - luaL_checkany(L, 1); - if (lua_type(L, 1) == LUA_TNUMBER) { /* already a number? */ - lua_settop(L, 1); /* yes; return it */ - return 1; - } - else { - size_t l; - const char *s = lua_tolstring(L, 1, &l); - if (s != NULL && lua_stringtonumber(L, s) == l + 1) - return 1; /* successful conversion to number */ - /* else not a number */ - } - } - else { - size_t l; - const char *s; - lua_Integer n = 0; /* to avoid warnings */ - lua_Integer base = luaL_checkinteger(L, 2); - luaL_checktype(L, 1, LUA_TSTRING); /* no numbers as strings */ - s = lua_tolstring(L, 1, &l); - luaL_argcheck(L, 2 <= base && base <= 36, 2, "base out of range"); - if (b_str2int(s, (int)base, &n) == s + l) { - lua_pushinteger(L, n); - return 1; - } /* else not a number */ - } /* else not a number */ - lua_pushnil(L); /* not a number */ - return 1; -} - - -static int luaB_error (lua_State *L) { - int level = (int)luaL_optinteger(L, 2, 1); - lua_settop(L, 1); - if (lua_type(L, 1) == LUA_TSTRING && level > 0) { - luaL_where(L, level); /* add extra information */ - lua_pushvalue(L, 1); - lua_concat(L, 2); - } - return lua_error(L); -} - - -static int luaB_getmetatable (lua_State *L) { - luaL_checkany(L, 1); - if (!lua_getmetatable(L, 1)) { - lua_pushnil(L); - return 1; /* no metatable */ - } - luaL_getmetafield(L, 1, "__metatable"); - return 1; /* returns either __metatable field (if present) or metatable */ -} - - -static int luaB_setmetatable (lua_State *L) { - int t = lua_type(L, 2); - luaL_checktype(L, 1, LUA_TTABLE); - luaL_argcheck(L, t == LUA_TNIL || t == LUA_TTABLE, 2, - "nil or table expected"); - if (luaL_getmetafield(L, 1, "__metatable") != LUA_TNIL) - return luaL_error(L, "cannot change a protected metatable"); - lua_settop(L, 2); - lua_setmetatable(L, 1); - return 1; -} - - -static int luaB_rawequal (lua_State *L) { - luaL_checkany(L, 1); - luaL_checkany(L, 2); - lua_pushboolean(L, lua_rawequal(L, 1, 2)); - return 1; -} - - -static int luaB_rawlen (lua_State *L) { - int t = lua_type(L, 1); - luaL_argcheck(L, t == LUA_TTABLE || t == LUA_TSTRING, 1, - "table or string expected"); - lua_pushinteger(L, lua_rawlen(L, 1)); - return 1; -} - - -static int luaB_rawget (lua_State *L) { - luaL_checktype(L, 1, LUA_TTABLE); - luaL_checkany(L, 2); - lua_settop(L, 2); - lua_rawget(L, 1); - return 1; -} - -static int luaB_rawset (lua_State *L) { - luaL_checktype(L, 1, LUA_TTABLE); - luaL_checkany(L, 2); - luaL_checkany(L, 3); - lua_settop(L, 3); - lua_rawset(L, 1); - return 1; -} - - -static int luaB_collectgarbage (lua_State *L) { - static const char *const opts[] = {"stop", "restart", "collect", - "count", "step", "setpause", "setstepmul", - "isrunning", NULL}; - static const int optsnum[] = {LUA_GCSTOP, LUA_GCRESTART, LUA_GCCOLLECT, - LUA_GCCOUNT, LUA_GCSTEP, LUA_GCSETPAUSE, LUA_GCSETSTEPMUL, - LUA_GCISRUNNING}; - int o = optsnum[luaL_checkoption(L, 1, "collect", opts)]; - int ex = (int)luaL_optinteger(L, 2, 0); - int res = lua_gc(L, o, ex); - switch (o) { - case LUA_GCCOUNT: { - int b = lua_gc(L, LUA_GCCOUNTB, 0); - lua_pushnumber(L, (lua_Number)res + ((lua_Number)b/1024)); - return 1; - } - case LUA_GCSTEP: case LUA_GCISRUNNING: { - lua_pushboolean(L, res); - return 1; - } - default: { - lua_pushinteger(L, res); - return 1; - } - } -} - - -static int luaB_type (lua_State *L) { - int t = lua_type(L, 1); - luaL_argcheck(L, t != LUA_TNONE, 1, "value expected"); - lua_pushstring(L, lua_typename(L, t)); - return 1; -} - - -static int pairsmeta (lua_State *L, const char *method, int iszero, - lua_CFunction iter) { - luaL_checkany(L, 1); - if (luaL_getmetafield(L, 1, method) == LUA_TNIL) { /* no metamethod? */ - lua_pushcfunction(L, iter); /* will return generator, */ - lua_pushvalue(L, 1); /* state, */ - if (iszero) lua_pushinteger(L, 0); /* and initial value */ - else lua_pushnil(L); - } - else { - lua_pushvalue(L, 1); /* argument 'self' to metamethod */ - lua_call(L, 1, 3); /* get 3 values from metamethod */ - } - return 3; -} - - -static int luaB_next (lua_State *L) { - luaL_checktype(L, 1, LUA_TTABLE); - lua_settop(L, 2); /* create a 2nd argument if there isn't one */ - if (lua_next(L, 1)) - return 2; - else { - lua_pushnil(L); - return 1; - } -} - - -static int luaB_pairs (lua_State *L) { - return pairsmeta(L, "__pairs", 0, luaB_next); -} - - -/* -** Traversal function for 'ipairs' -*/ -static int ipairsaux (lua_State *L) { - lua_Integer i = luaL_checkinteger(L, 2) + 1; - lua_pushinteger(L, i); - return (lua_geti(L, 1, i) == LUA_TNIL) ? 1 : 2; -} - - -/* -** 'ipairs' function. Returns 'ipairsaux', given "table", 0. -** (The given "table" may not be a table.) -*/ -static int luaB_ipairs (lua_State *L) { -#if defined(LUA_COMPAT_IPAIRS) - return pairsmeta(L, "__ipairs", 1, ipairsaux); -#else - luaL_checkany(L, 1); - lua_pushcfunction(L, ipairsaux); /* iteration function */ - lua_pushvalue(L, 1); /* state */ - lua_pushinteger(L, 0); /* initial value */ - return 3; -#endif -} - - -static int load_aux (lua_State *L, int status, int envidx) { - if (status == LUA_OK) { - if (envidx != 0) { /* 'env' parameter? */ - lua_pushvalue(L, envidx); /* environment for loaded function */ - if (!lua_setupvalue(L, -2, 1)) /* set it as 1st upvalue */ - lua_pop(L, 1); /* remove 'env' if not used by previous call */ - } - return 1; - } - else { /* error (message is on top of the stack) */ - lua_pushnil(L); - lua_insert(L, -2); /* put before error message */ - return 2; /* return nil plus error message */ - } -} - - -static int luaB_loadfile (lua_State *L) { - const char *fname = luaL_optstring(L, 1, NULL); - const char *mode = luaL_optstring(L, 2, NULL); - int env = (!lua_isnone(L, 3) ? 3 : 0); /* 'env' index or 0 if no 'env' */ - int status = luaL_loadfilex(L, fname, mode); - return load_aux(L, status, env); -} - - -/* -** {====================================================== -** Generic Read function -** ======================================================= -*/ - - -/* -** reserved slot, above all arguments, to hold a copy of the returned -** string to avoid it being collected while parsed. 'load' has four -** optional arguments (chunk, source name, mode, and environment). -*/ -#define RESERVEDSLOT 5 - - -/* -** Reader for generic 'load' function: 'lua_load' uses the -** stack for internal stuff, so the reader cannot change the -** stack top. Instead, it keeps its resulting string in a -** reserved slot inside the stack. -*/ -static const char *generic_reader (lua_State *L, void *ud, size_t *size) { - (void)(ud); /* not used */ - luaL_checkstack(L, 2, "too many nested functions"); - lua_pushvalue(L, 1); /* get function */ - lua_call(L, 0, 1); /* call it */ - if (lua_isnil(L, -1)) { - lua_pop(L, 1); /* pop result */ - *size = 0; - return NULL; - } - else if (!lua_isstring(L, -1)) - luaL_error(L, "reader function must return a string"); - lua_replace(L, RESERVEDSLOT); /* save string in reserved slot */ - return lua_tolstring(L, RESERVEDSLOT, size); -} - - -static int luaB_load (lua_State *L) { - int status; - size_t l; - const char *s = lua_tolstring(L, 1, &l); - const char *mode = luaL_optstring(L, 3, "bt"); - int env = (!lua_isnone(L, 4) ? 4 : 0); /* 'env' index or 0 if no 'env' */ - if (s != NULL) { /* loading a string? */ - const char *chunkname = luaL_optstring(L, 2, s); - status = luaL_loadbufferx(L, s, l, chunkname, mode); - } - else { /* loading from a reader function */ - const char *chunkname = luaL_optstring(L, 2, "=(load)"); - luaL_checktype(L, 1, LUA_TFUNCTION); - lua_settop(L, RESERVEDSLOT); /* create reserved slot */ - status = lua_load(L, generic_reader, NULL, chunkname, mode); - } - return load_aux(L, status, env); -} - -/* }====================================================== */ - - -static int dofilecont (lua_State *L, int d1, lua_KContext d2) { - (void)d1; (void)d2; /* only to match 'lua_Kfunction' prototype */ - return lua_gettop(L) - 1; -} - - -static int luaB_dofile (lua_State *L) { - const char *fname = luaL_optstring(L, 1, NULL); - lua_settop(L, 1); - if (luaL_loadfile(L, fname) != LUA_OK) - return lua_error(L); - lua_callk(L, 0, LUA_MULTRET, 0, dofilecont); - return dofilecont(L, 0, 0); -} - - -static int luaB_assert (lua_State *L) { - if (lua_toboolean(L, 1)) /* condition is true? */ - return lua_gettop(L); /* return all arguments */ - else { /* error */ - luaL_checkany(L, 1); /* there must be a condition */ - lua_remove(L, 1); /* remove it */ - lua_pushliteral(L, "assertion failed!"); /* default message */ - lua_settop(L, 1); /* leave only message (default if no other one) */ - return luaB_error(L); /* call 'error' */ - } -} - - -static int luaB_select (lua_State *L) { - int n = lua_gettop(L); - if (lua_type(L, 1) == LUA_TSTRING && *lua_tostring(L, 1) == '#') { - lua_pushinteger(L, n-1); - return 1; - } - else { - lua_Integer i = luaL_checkinteger(L, 1); - if (i < 0) i = n + i; - else if (i > n) i = n; - luaL_argcheck(L, 1 <= i, 1, "index out of range"); - return n - (int)i; - } -} - - -/* -** Continuation function for 'pcall' and 'xpcall'. Both functions -** already pushed a 'true' before doing the call, so in case of success -** 'finishpcall' only has to return everything in the stack minus -** 'extra' values (where 'extra' is exactly the number of items to be -** ignored). -*/ -static int finishpcall (lua_State *L, int status, lua_KContext extra) { - if (status != LUA_OK && status != LUA_YIELD) { /* error? */ - lua_pushboolean(L, 0); /* first result (false) */ - lua_pushvalue(L, -2); /* error message */ - return 2; /* return false, msg */ - } - else - return lua_gettop(L) - (int)extra; /* return all results */ -} - - -static int luaB_pcall (lua_State *L) { - int status; - luaL_checkany(L, 1); - lua_pushboolean(L, 1); /* first result if no errors */ - lua_insert(L, 1); /* put it in place */ - status = lua_pcallk(L, lua_gettop(L) - 2, LUA_MULTRET, 0, 0, finishpcall); - return finishpcall(L, status, 0); -} - - -/* -** Do a protected call with error handling. After 'lua_rotate', the -** stack will have ; so, the function passes -** 2 to 'finishpcall' to skip the 2 first values when returning results. -*/ -static int luaB_xpcall (lua_State *L) { - int status; - int n = lua_gettop(L); - luaL_checktype(L, 2, LUA_TFUNCTION); /* check error function */ - lua_pushboolean(L, 1); /* first result */ - lua_pushvalue(L, 1); /* function */ - lua_rotate(L, 3, 2); /* move them below function's arguments */ - status = lua_pcallk(L, n - 2, LUA_MULTRET, 2, 2, finishpcall); - return finishpcall(L, status, 2); -} - - -static int luaB_tostring (lua_State *L) { - luaL_checkany(L, 1); - luaL_tolstring(L, 1, NULL); - return 1; -} - - -static const luaL_Reg base_funcs[] = { - {"assert", luaB_assert}, - {"collectgarbage", luaB_collectgarbage}, - {"dofile", luaB_dofile}, - {"error", luaB_error}, - {"getmetatable", luaB_getmetatable}, - {"ipairs", luaB_ipairs}, - {"loadfile", luaB_loadfile}, - {"load", luaB_load}, -#if defined(LUA_COMPAT_LOADSTRING) - {"loadstring", luaB_load}, -#endif - {"next", luaB_next}, - {"pairs", luaB_pairs}, - {"pcall", luaB_pcall}, - {"print", luaB_print}, - {"rawequal", luaB_rawequal}, - {"rawlen", luaB_rawlen}, - {"rawget", luaB_rawget}, - {"rawset", luaB_rawset}, - {"select", luaB_select}, - {"setmetatable", luaB_setmetatable}, - {"tonumber", luaB_tonumber}, - {"tostring", luaB_tostring}, - {"type", luaB_type}, - {"xpcall", luaB_xpcall}, - /* placeholders */ - {"_G", NULL}, - {"_VERSION", NULL}, - {NULL, NULL} -}; - - -LUAMOD_API int luaopen_base (lua_State *L) { - /* open lib into global table */ - lua_pushglobaltable(L); - luaL_setfuncs(L, base_funcs, 0); - /* set global _G */ - lua_pushvalue(L, -1); - lua_setfield(L, -2, "_G"); - /* set global _VERSION */ - lua_pushliteral(L, LUA_VERSION); - lua_setfield(L, -2, "_VERSION"); - return 1; -} - diff --git a/lib/lua-5.3/src/lbitlib.c b/lib/lua-5.3/src/lbitlib.c deleted file mode 100644 index 4786c0d..0000000 --- a/lib/lua-5.3/src/lbitlib.c +++ /dev/null @@ -1,233 +0,0 @@ -/* -** $Id: lbitlib.c,v 1.30.1.1 2017/04/19 17:20:42 roberto Exp $ -** Standard library for bitwise operations -** See Copyright Notice in lua.h -*/ - -#define lbitlib_c -#define LUA_LIB - -#include "lprefix.h" - - -#include "lua.h" - -#include "lauxlib.h" -#include "lualib.h" - - -#if defined(LUA_COMPAT_BITLIB) /* { */ - - -#define pushunsigned(L,n) lua_pushinteger(L, (lua_Integer)(n)) -#define checkunsigned(L,i) ((lua_Unsigned)luaL_checkinteger(L,i)) - - -/* number of bits to consider in a number */ -#if !defined(LUA_NBITS) -#define LUA_NBITS 32 -#endif - - -/* -** a lua_Unsigned with its first LUA_NBITS bits equal to 1. (Shift must -** be made in two parts to avoid problems when LUA_NBITS is equal to the -** number of bits in a lua_Unsigned.) -*/ -#define ALLONES (~(((~(lua_Unsigned)0) << (LUA_NBITS - 1)) << 1)) - - -/* macro to trim extra bits */ -#define trim(x) ((x) & ALLONES) - - -/* builds a number with 'n' ones (1 <= n <= LUA_NBITS) */ -#define mask(n) (~((ALLONES << 1) << ((n) - 1))) - - - -static lua_Unsigned andaux (lua_State *L) { - int i, n = lua_gettop(L); - lua_Unsigned r = ~(lua_Unsigned)0; - for (i = 1; i <= n; i++) - r &= checkunsigned(L, i); - return trim(r); -} - - -static int b_and (lua_State *L) { - lua_Unsigned r = andaux(L); - pushunsigned(L, r); - return 1; -} - - -static int b_test (lua_State *L) { - lua_Unsigned r = andaux(L); - lua_pushboolean(L, r != 0); - return 1; -} - - -static int b_or (lua_State *L) { - int i, n = lua_gettop(L); - lua_Unsigned r = 0; - for (i = 1; i <= n; i++) - r |= checkunsigned(L, i); - pushunsigned(L, trim(r)); - return 1; -} - - -static int b_xor (lua_State *L) { - int i, n = lua_gettop(L); - lua_Unsigned r = 0; - for (i = 1; i <= n; i++) - r ^= checkunsigned(L, i); - pushunsigned(L, trim(r)); - return 1; -} - - -static int b_not (lua_State *L) { - lua_Unsigned r = ~checkunsigned(L, 1); - pushunsigned(L, trim(r)); - return 1; -} - - -static int b_shift (lua_State *L, lua_Unsigned r, lua_Integer i) { - if (i < 0) { /* shift right? */ - i = -i; - r = trim(r); - if (i >= LUA_NBITS) r = 0; - else r >>= i; - } - else { /* shift left */ - if (i >= LUA_NBITS) r = 0; - else r <<= i; - r = trim(r); - } - pushunsigned(L, r); - return 1; -} - - -static int b_lshift (lua_State *L) { - return b_shift(L, checkunsigned(L, 1), luaL_checkinteger(L, 2)); -} - - -static int b_rshift (lua_State *L) { - return b_shift(L, checkunsigned(L, 1), -luaL_checkinteger(L, 2)); -} - - -static int b_arshift (lua_State *L) { - lua_Unsigned r = checkunsigned(L, 1); - lua_Integer i = luaL_checkinteger(L, 2); - if (i < 0 || !(r & ((lua_Unsigned)1 << (LUA_NBITS - 1)))) - return b_shift(L, r, -i); - else { /* arithmetic shift for 'negative' number */ - if (i >= LUA_NBITS) r = ALLONES; - else - r = trim((r >> i) | ~(trim(~(lua_Unsigned)0) >> i)); /* add signal bit */ - pushunsigned(L, r); - return 1; - } -} - - -static int b_rot (lua_State *L, lua_Integer d) { - lua_Unsigned r = checkunsigned(L, 1); - int i = d & (LUA_NBITS - 1); /* i = d % NBITS */ - r = trim(r); - if (i != 0) /* avoid undefined shift of LUA_NBITS when i == 0 */ - r = (r << i) | (r >> (LUA_NBITS - i)); - pushunsigned(L, trim(r)); - return 1; -} - - -static int b_lrot (lua_State *L) { - return b_rot(L, luaL_checkinteger(L, 2)); -} - - -static int b_rrot (lua_State *L) { - return b_rot(L, -luaL_checkinteger(L, 2)); -} - - -/* -** get field and width arguments for field-manipulation functions, -** checking whether they are valid. -** ('luaL_error' called without 'return' to avoid later warnings about -** 'width' being used uninitialized.) -*/ -static int fieldargs (lua_State *L, int farg, int *width) { - lua_Integer f = luaL_checkinteger(L, farg); - lua_Integer w = luaL_optinteger(L, farg + 1, 1); - luaL_argcheck(L, 0 <= f, farg, "field cannot be negative"); - luaL_argcheck(L, 0 < w, farg + 1, "width must be positive"); - if (f + w > LUA_NBITS) - luaL_error(L, "trying to access non-existent bits"); - *width = (int)w; - return (int)f; -} - - -static int b_extract (lua_State *L) { - int w; - lua_Unsigned r = trim(checkunsigned(L, 1)); - int f = fieldargs(L, 2, &w); - r = (r >> f) & mask(w); - pushunsigned(L, r); - return 1; -} - - -static int b_replace (lua_State *L) { - int w; - lua_Unsigned r = trim(checkunsigned(L, 1)); - lua_Unsigned v = trim(checkunsigned(L, 2)); - int f = fieldargs(L, 3, &w); - lua_Unsigned m = mask(w); - r = (r & ~(m << f)) | ((v & m) << f); - pushunsigned(L, r); - return 1; -} - - -static const luaL_Reg bitlib[] = { - {"arshift", b_arshift}, - {"band", b_and}, - {"bnot", b_not}, - {"bor", b_or}, - {"bxor", b_xor}, - {"btest", b_test}, - {"extract", b_extract}, - {"lrotate", b_lrot}, - {"lshift", b_lshift}, - {"replace", b_replace}, - {"rrotate", b_rrot}, - {"rshift", b_rshift}, - {NULL, NULL} -}; - - - -LUAMOD_API int luaopen_bit32 (lua_State *L) { - luaL_newlib(L, bitlib); - return 1; -} - - -#else /* }{ */ - - -LUAMOD_API int luaopen_bit32 (lua_State *L) { - return luaL_error(L, "library 'bit32' has been deprecated"); -} - -#endif /* } */ diff --git a/lib/lua-5.3/src/lcode.c b/lib/lua-5.3/src/lcode.c deleted file mode 100644 index dc7271d..0000000 --- a/lib/lua-5.3/src/lcode.c +++ /dev/null @@ -1,1203 +0,0 @@ -/* -** $Id: lcode.c,v 2.112.1.1 2017/04/19 17:20:42 roberto Exp $ -** Code generator for Lua -** See Copyright Notice in lua.h -*/ - -#define lcode_c -#define LUA_CORE - -#include "lprefix.h" - - -#include -#include - -#include "lua.h" - -#include "lcode.h" -#include "ldebug.h" -#include "ldo.h" -#include "lgc.h" -#include "llex.h" -#include "lmem.h" -#include "lobject.h" -#include "lopcodes.h" -#include "lparser.h" -#include "lstring.h" -#include "ltable.h" -#include "lvm.h" - - -/* Maximum number of registers in a Lua function (must fit in 8 bits) */ -#define MAXREGS 255 - - -#define hasjumps(e) ((e)->t != (e)->f) - - -/* -** If expression is a numeric constant, fills 'v' with its value -** and returns 1. Otherwise, returns 0. -*/ -static int tonumeral(const expdesc *e, TValue *v) { - if (hasjumps(e)) - return 0; /* not a numeral */ - switch (e->k) { - case VKINT: - if (v) setivalue(v, e->u.ival); - return 1; - case VKFLT: - if (v) setfltvalue(v, e->u.nval); - return 1; - default: return 0; - } -} - - -/* -** Create a OP_LOADNIL instruction, but try to optimize: if the previous -** instruction is also OP_LOADNIL and ranges are compatible, adjust -** range of previous instruction instead of emitting a new one. (For -** instance, 'local a; local b' will generate a single opcode.) -*/ -void luaK_nil (FuncState *fs, int from, int n) { - Instruction *previous; - int l = from + n - 1; /* last register to set nil */ - if (fs->pc > fs->lasttarget) { /* no jumps to current position? */ - previous = &fs->f->code[fs->pc-1]; - if (GET_OPCODE(*previous) == OP_LOADNIL) { /* previous is LOADNIL? */ - int pfrom = GETARG_A(*previous); /* get previous range */ - int pl = pfrom + GETARG_B(*previous); - if ((pfrom <= from && from <= pl + 1) || - (from <= pfrom && pfrom <= l + 1)) { /* can connect both? */ - if (pfrom < from) from = pfrom; /* from = min(from, pfrom) */ - if (pl > l) l = pl; /* l = max(l, pl) */ - SETARG_A(*previous, from); - SETARG_B(*previous, l - from); - return; - } - } /* else go through */ - } - luaK_codeABC(fs, OP_LOADNIL, from, n - 1, 0); /* else no optimization */ -} - - -/* -** Gets the destination address of a jump instruction. Used to traverse -** a list of jumps. -*/ -static int getjump (FuncState *fs, int pc) { - int offset = GETARG_sBx(fs->f->code[pc]); - if (offset == NO_JUMP) /* point to itself represents end of list */ - return NO_JUMP; /* end of list */ - else - return (pc+1)+offset; /* turn offset into absolute position */ -} - - -/* -** Fix jump instruction at position 'pc' to jump to 'dest'. -** (Jump addresses are relative in Lua) -*/ -static void fixjump (FuncState *fs, int pc, int dest) { - Instruction *jmp = &fs->f->code[pc]; - int offset = dest - (pc + 1); - lua_assert(dest != NO_JUMP); - if (abs(offset) > MAXARG_sBx) - luaX_syntaxerror(fs->ls, "control structure too long"); - SETARG_sBx(*jmp, offset); -} - - -/* -** Concatenate jump-list 'l2' into jump-list 'l1' -*/ -void luaK_concat (FuncState *fs, int *l1, int l2) { - if (l2 == NO_JUMP) return; /* nothing to concatenate? */ - else if (*l1 == NO_JUMP) /* no original list? */ - *l1 = l2; /* 'l1' points to 'l2' */ - else { - int list = *l1; - int next; - while ((next = getjump(fs, list)) != NO_JUMP) /* find last element */ - list = next; - fixjump(fs, list, l2); /* last element links to 'l2' */ - } -} - - -/* -** Create a jump instruction and return its position, so its destination -** can be fixed later (with 'fixjump'). If there are jumps to -** this position (kept in 'jpc'), link them all together so that -** 'patchlistaux' will fix all them directly to the final destination. -*/ -int luaK_jump (FuncState *fs) { - int jpc = fs->jpc; /* save list of jumps to here */ - int j; - fs->jpc = NO_JUMP; /* no more jumps to here */ - j = luaK_codeAsBx(fs, OP_JMP, 0, NO_JUMP); - luaK_concat(fs, &j, jpc); /* keep them on hold */ - return j; -} - - -/* -** Code a 'return' instruction -*/ -void luaK_ret (FuncState *fs, int first, int nret) { - luaK_codeABC(fs, OP_RETURN, first, nret+1, 0); -} - - -/* -** Code a "conditional jump", that is, a test or comparison opcode -** followed by a jump. Return jump position. -*/ -static int condjump (FuncState *fs, OpCode op, int A, int B, int C) { - luaK_codeABC(fs, op, A, B, C); - return luaK_jump(fs); -} - - -/* -** returns current 'pc' and marks it as a jump target (to avoid wrong -** optimizations with consecutive instructions not in the same basic block). -*/ -int luaK_getlabel (FuncState *fs) { - fs->lasttarget = fs->pc; - return fs->pc; -} - - -/* -** Returns the position of the instruction "controlling" a given -** jump (that is, its condition), or the jump itself if it is -** unconditional. -*/ -static Instruction *getjumpcontrol (FuncState *fs, int pc) { - Instruction *pi = &fs->f->code[pc]; - if (pc >= 1 && testTMode(GET_OPCODE(*(pi-1)))) - return pi-1; - else - return pi; -} - - -/* -** Patch destination register for a TESTSET instruction. -** If instruction in position 'node' is not a TESTSET, return 0 ("fails"). -** Otherwise, if 'reg' is not 'NO_REG', set it as the destination -** register. Otherwise, change instruction to a simple 'TEST' (produces -** no register value) -*/ -static int patchtestreg (FuncState *fs, int node, int reg) { - Instruction *i = getjumpcontrol(fs, node); - if (GET_OPCODE(*i) != OP_TESTSET) - return 0; /* cannot patch other instructions */ - if (reg != NO_REG && reg != GETARG_B(*i)) - SETARG_A(*i, reg); - else { - /* no register to put value or register already has the value; - change instruction to simple test */ - *i = CREATE_ABC(OP_TEST, GETARG_B(*i), 0, GETARG_C(*i)); - } - return 1; -} - - -/* -** Traverse a list of tests ensuring no one produces a value -*/ -static void removevalues (FuncState *fs, int list) { - for (; list != NO_JUMP; list = getjump(fs, list)) - patchtestreg(fs, list, NO_REG); -} - - -/* -** Traverse a list of tests, patching their destination address and -** registers: tests producing values jump to 'vtarget' (and put their -** values in 'reg'), other tests jump to 'dtarget'. -*/ -static void patchlistaux (FuncState *fs, int list, int vtarget, int reg, - int dtarget) { - while (list != NO_JUMP) { - int next = getjump(fs, list); - if (patchtestreg(fs, list, reg)) - fixjump(fs, list, vtarget); - else - fixjump(fs, list, dtarget); /* jump to default target */ - list = next; - } -} - - -/* -** Ensure all pending jumps to current position are fixed (jumping -** to current position with no values) and reset list of pending -** jumps -*/ -static void dischargejpc (FuncState *fs) { - patchlistaux(fs, fs->jpc, fs->pc, NO_REG, fs->pc); - fs->jpc = NO_JUMP; -} - - -/* -** Add elements in 'list' to list of pending jumps to "here" -** (current position) -*/ -void luaK_patchtohere (FuncState *fs, int list) { - luaK_getlabel(fs); /* mark "here" as a jump target */ - luaK_concat(fs, &fs->jpc, list); -} - - -/* -** Path all jumps in 'list' to jump to 'target'. -** (The assert means that we cannot fix a jump to a forward address -** because we only know addresses once code is generated.) -*/ -void luaK_patchlist (FuncState *fs, int list, int target) { - if (target == fs->pc) /* 'target' is current position? */ - luaK_patchtohere(fs, list); /* add list to pending jumps */ - else { - lua_assert(target < fs->pc); - patchlistaux(fs, list, target, NO_REG, target); - } -} - - -/* -** Path all jumps in 'list' to close upvalues up to given 'level' -** (The assertion checks that jumps either were closing nothing -** or were closing higher levels, from inner blocks.) -*/ -void luaK_patchclose (FuncState *fs, int list, int level) { - level++; /* argument is +1 to reserve 0 as non-op */ - for (; list != NO_JUMP; list = getjump(fs, list)) { - lua_assert(GET_OPCODE(fs->f->code[list]) == OP_JMP && - (GETARG_A(fs->f->code[list]) == 0 || - GETARG_A(fs->f->code[list]) >= level)); - SETARG_A(fs->f->code[list], level); - } -} - - -/* -** Emit instruction 'i', checking for array sizes and saving also its -** line information. Return 'i' position. -*/ -static int luaK_code (FuncState *fs, Instruction i) { - Proto *f = fs->f; - dischargejpc(fs); /* 'pc' will change */ - /* put new instruction in code array */ - luaM_growvector(fs->ls->L, f->code, fs->pc, f->sizecode, Instruction, - MAX_INT, "opcodes"); - f->code[fs->pc] = i; - /* save corresponding line information */ - luaM_growvector(fs->ls->L, f->lineinfo, fs->pc, f->sizelineinfo, int, - MAX_INT, "opcodes"); - f->lineinfo[fs->pc] = fs->ls->lastline; - return fs->pc++; -} - - -/* -** Format and emit an 'iABC' instruction. (Assertions check consistency -** of parameters versus opcode.) -*/ -int luaK_codeABC (FuncState *fs, OpCode o, int a, int b, int c) { - lua_assert(getOpMode(o) == iABC); - lua_assert(getBMode(o) != OpArgN || b == 0); - lua_assert(getCMode(o) != OpArgN || c == 0); - lua_assert(a <= MAXARG_A && b <= MAXARG_B && c <= MAXARG_C); - return luaK_code(fs, CREATE_ABC(o, a, b, c)); -} - - -/* -** Format and emit an 'iABx' instruction. -*/ -int luaK_codeABx (FuncState *fs, OpCode o, int a, unsigned int bc) { - lua_assert(getOpMode(o) == iABx || getOpMode(o) == iAsBx); - lua_assert(getCMode(o) == OpArgN); - lua_assert(a <= MAXARG_A && bc <= MAXARG_Bx); - return luaK_code(fs, CREATE_ABx(o, a, bc)); -} - - -/* -** Emit an "extra argument" instruction (format 'iAx') -*/ -static int codeextraarg (FuncState *fs, int a) { - lua_assert(a <= MAXARG_Ax); - return luaK_code(fs, CREATE_Ax(OP_EXTRAARG, a)); -} - - -/* -** Emit a "load constant" instruction, using either 'OP_LOADK' -** (if constant index 'k' fits in 18 bits) or an 'OP_LOADKX' -** instruction with "extra argument". -*/ -int luaK_codek (FuncState *fs, int reg, int k) { - if (k <= MAXARG_Bx) - return luaK_codeABx(fs, OP_LOADK, reg, k); - else { - int p = luaK_codeABx(fs, OP_LOADKX, reg, 0); - codeextraarg(fs, k); - return p; - } -} - - -/* -** Check register-stack level, keeping track of its maximum size -** in field 'maxstacksize' -*/ -void luaK_checkstack (FuncState *fs, int n) { - int newstack = fs->freereg + n; - if (newstack > fs->f->maxstacksize) { - if (newstack >= MAXREGS) - luaX_syntaxerror(fs->ls, - "function or expression needs too many registers"); - fs->f->maxstacksize = cast_byte(newstack); - } -} - - -/* -** Reserve 'n' registers in register stack -*/ -void luaK_reserveregs (FuncState *fs, int n) { - luaK_checkstack(fs, n); - fs->freereg += n; -} - - -/* -** Free register 'reg', if it is neither a constant index nor -** a local variable. -) -*/ -static void freereg (FuncState *fs, int reg) { - if (!ISK(reg) && reg >= fs->nactvar) { - fs->freereg--; - lua_assert(reg == fs->freereg); - } -} - - -/* -** Free register used by expression 'e' (if any) -*/ -static void freeexp (FuncState *fs, expdesc *e) { - if (e->k == VNONRELOC) - freereg(fs, e->u.info); -} - - -/* -** Free registers used by expressions 'e1' and 'e2' (if any) in proper -** order. -*/ -static void freeexps (FuncState *fs, expdesc *e1, expdesc *e2) { - int r1 = (e1->k == VNONRELOC) ? e1->u.info : -1; - int r2 = (e2->k == VNONRELOC) ? e2->u.info : -1; - if (r1 > r2) { - freereg(fs, r1); - freereg(fs, r2); - } - else { - freereg(fs, r2); - freereg(fs, r1); - } -} - - -/* -** Add constant 'v' to prototype's list of constants (field 'k'). -** Use scanner's table to cache position of constants in constant list -** and try to reuse constants. Because some values should not be used -** as keys (nil cannot be a key, integer keys can collapse with float -** keys), the caller must provide a useful 'key' for indexing the cache. -*/ -static int addk (FuncState *fs, TValue *key, TValue *v) { - lua_State *L = fs->ls->L; - Proto *f = fs->f; - TValue *idx = luaH_set(L, fs->ls->h, key); /* index scanner table */ - int k, oldsize; - if (ttisinteger(idx)) { /* is there an index there? */ - k = cast_int(ivalue(idx)); - /* correct value? (warning: must distinguish floats from integers!) */ - if (k < fs->nk && ttype(&f->k[k]) == ttype(v) && - luaV_rawequalobj(&f->k[k], v)) - return k; /* reuse index */ - } - /* constant not found; create a new entry */ - oldsize = f->sizek; - k = fs->nk; - /* numerical value does not need GC barrier; - table has no metatable, so it does not need to invalidate cache */ - setivalue(idx, k); - luaM_growvector(L, f->k, k, f->sizek, TValue, MAXARG_Ax, "constants"); - while (oldsize < f->sizek) setnilvalue(&f->k[oldsize++]); - setobj(L, &f->k[k], v); - fs->nk++; - luaC_barrier(L, f, v); - return k; -} - - -/* -** Add a string to list of constants and return its index. -*/ -int luaK_stringK (FuncState *fs, TString *s) { - TValue o; - setsvalue(fs->ls->L, &o, s); - return addk(fs, &o, &o); /* use string itself as key */ -} - - -/* -** Add an integer to list of constants and return its index. -** Integers use userdata as keys to avoid collision with floats with -** same value; conversion to 'void*' is used only for hashing, so there -** are no "precision" problems. -*/ -int luaK_intK (FuncState *fs, lua_Integer n) { - TValue k, o; - setpvalue(&k, cast(void*, cast(size_t, n))); - setivalue(&o, n); - return addk(fs, &k, &o); -} - -/* -** Add a float to list of constants and return its index. -*/ -static int luaK_numberK (FuncState *fs, lua_Number r) { - TValue o; - setfltvalue(&o, r); - return addk(fs, &o, &o); /* use number itself as key */ -} - - -/* -** Add a boolean to list of constants and return its index. -*/ -static int boolK (FuncState *fs, int b) { - TValue o; - setbvalue(&o, b); - return addk(fs, &o, &o); /* use boolean itself as key */ -} - - -/* -** Add nil to list of constants and return its index. -*/ -static int nilK (FuncState *fs) { - TValue k, v; - setnilvalue(&v); - /* cannot use nil as key; instead use table itself to represent nil */ - sethvalue(fs->ls->L, &k, fs->ls->h); - return addk(fs, &k, &v); -} - - -/* -** Fix an expression to return the number of results 'nresults'. -** Either 'e' is a multi-ret expression (function call or vararg) -** or 'nresults' is LUA_MULTRET (as any expression can satisfy that). -*/ -void luaK_setreturns (FuncState *fs, expdesc *e, int nresults) { - if (e->k == VCALL) { /* expression is an open function call? */ - SETARG_C(getinstruction(fs, e), nresults + 1); - } - else if (e->k == VVARARG) { - Instruction *pc = &getinstruction(fs, e); - SETARG_B(*pc, nresults + 1); - SETARG_A(*pc, fs->freereg); - luaK_reserveregs(fs, 1); - } - else lua_assert(nresults == LUA_MULTRET); -} - - -/* -** Fix an expression to return one result. -** If expression is not a multi-ret expression (function call or -** vararg), it already returns one result, so nothing needs to be done. -** Function calls become VNONRELOC expressions (as its result comes -** fixed in the base register of the call), while vararg expressions -** become VRELOCABLE (as OP_VARARG puts its results where it wants). -** (Calls are created returning one result, so that does not need -** to be fixed.) -*/ -void luaK_setoneret (FuncState *fs, expdesc *e) { - if (e->k == VCALL) { /* expression is an open function call? */ - /* already returns 1 value */ - lua_assert(GETARG_C(getinstruction(fs, e)) == 2); - e->k = VNONRELOC; /* result has fixed position */ - e->u.info = GETARG_A(getinstruction(fs, e)); - } - else if (e->k == VVARARG) { - SETARG_B(getinstruction(fs, e), 2); - e->k = VRELOCABLE; /* can relocate its simple result */ - } -} - - -/* -** Ensure that expression 'e' is not a variable. -*/ -void luaK_dischargevars (FuncState *fs, expdesc *e) { - switch (e->k) { - case VLOCAL: { /* already in a register */ - e->k = VNONRELOC; /* becomes a non-relocatable value */ - break; - } - case VUPVAL: { /* move value to some (pending) register */ - e->u.info = luaK_codeABC(fs, OP_GETUPVAL, 0, e->u.info, 0); - e->k = VRELOCABLE; - break; - } - case VINDEXED: { - OpCode op; - freereg(fs, e->u.ind.idx); - if (e->u.ind.vt == VLOCAL) { /* is 't' in a register? */ - freereg(fs, e->u.ind.t); - op = OP_GETTABLE; - } - else { - lua_assert(e->u.ind.vt == VUPVAL); - op = OP_GETTABUP; /* 't' is in an upvalue */ - } - e->u.info = luaK_codeABC(fs, op, 0, e->u.ind.t, e->u.ind.idx); - e->k = VRELOCABLE; - break; - } - case VVARARG: case VCALL: { - luaK_setoneret(fs, e); - break; - } - default: break; /* there is one value available (somewhere) */ - } -} - - -/* -** Ensures expression value is in register 'reg' (and therefore -** 'e' will become a non-relocatable expression). -*/ -static void discharge2reg (FuncState *fs, expdesc *e, int reg) { - luaK_dischargevars(fs, e); - switch (e->k) { - case VNIL: { - luaK_nil(fs, reg, 1); - break; - } - case VFALSE: case VTRUE: { - luaK_codeABC(fs, OP_LOADBOOL, reg, e->k == VTRUE, 0); - break; - } - case VK: { - luaK_codek(fs, reg, e->u.info); - break; - } - case VKFLT: { - luaK_codek(fs, reg, luaK_numberK(fs, e->u.nval)); - break; - } - case VKINT: { - luaK_codek(fs, reg, luaK_intK(fs, e->u.ival)); - break; - } - case VRELOCABLE: { - Instruction *pc = &getinstruction(fs, e); - SETARG_A(*pc, reg); /* instruction will put result in 'reg' */ - break; - } - case VNONRELOC: { - if (reg != e->u.info) - luaK_codeABC(fs, OP_MOVE, reg, e->u.info, 0); - break; - } - default: { - lua_assert(e->k == VJMP); - return; /* nothing to do... */ - } - } - e->u.info = reg; - e->k = VNONRELOC; -} - - -/* -** Ensures expression value is in any register. -*/ -static void discharge2anyreg (FuncState *fs, expdesc *e) { - if (e->k != VNONRELOC) { /* no fixed register yet? */ - luaK_reserveregs(fs, 1); /* get a register */ - discharge2reg(fs, e, fs->freereg-1); /* put value there */ - } -} - - -static int code_loadbool (FuncState *fs, int A, int b, int jump) { - luaK_getlabel(fs); /* those instructions may be jump targets */ - return luaK_codeABC(fs, OP_LOADBOOL, A, b, jump); -} - - -/* -** check whether list has any jump that do not produce a value -** or produce an inverted value -*/ -static int need_value (FuncState *fs, int list) { - for (; list != NO_JUMP; list = getjump(fs, list)) { - Instruction i = *getjumpcontrol(fs, list); - if (GET_OPCODE(i) != OP_TESTSET) return 1; - } - return 0; /* not found */ -} - - -/* -** Ensures final expression result (including results from its jump -** lists) is in register 'reg'. -** If expression has jumps, need to patch these jumps either to -** its final position or to "load" instructions (for those tests -** that do not produce values). -*/ -static void exp2reg (FuncState *fs, expdesc *e, int reg) { - discharge2reg(fs, e, reg); - if (e->k == VJMP) /* expression itself is a test? */ - luaK_concat(fs, &e->t, e->u.info); /* put this jump in 't' list */ - if (hasjumps(e)) { - int final; /* position after whole expression */ - int p_f = NO_JUMP; /* position of an eventual LOAD false */ - int p_t = NO_JUMP; /* position of an eventual LOAD true */ - if (need_value(fs, e->t) || need_value(fs, e->f)) { - int fj = (e->k == VJMP) ? NO_JUMP : luaK_jump(fs); - p_f = code_loadbool(fs, reg, 0, 1); - p_t = code_loadbool(fs, reg, 1, 0); - luaK_patchtohere(fs, fj); - } - final = luaK_getlabel(fs); - patchlistaux(fs, e->f, final, reg, p_f); - patchlistaux(fs, e->t, final, reg, p_t); - } - e->f = e->t = NO_JUMP; - e->u.info = reg; - e->k = VNONRELOC; -} - - -/* -** Ensures final expression result (including results from its jump -** lists) is in next available register. -*/ -void luaK_exp2nextreg (FuncState *fs, expdesc *e) { - luaK_dischargevars(fs, e); - freeexp(fs, e); - luaK_reserveregs(fs, 1); - exp2reg(fs, e, fs->freereg - 1); -} - - -/* -** Ensures final expression result (including results from its jump -** lists) is in some (any) register and return that register. -*/ -int luaK_exp2anyreg (FuncState *fs, expdesc *e) { - luaK_dischargevars(fs, e); - if (e->k == VNONRELOC) { /* expression already has a register? */ - if (!hasjumps(e)) /* no jumps? */ - return e->u.info; /* result is already in a register */ - if (e->u.info >= fs->nactvar) { /* reg. is not a local? */ - exp2reg(fs, e, e->u.info); /* put final result in it */ - return e->u.info; - } - } - luaK_exp2nextreg(fs, e); /* otherwise, use next available register */ - return e->u.info; -} - - -/* -** Ensures final expression result is either in a register or in an -** upvalue. -*/ -void luaK_exp2anyregup (FuncState *fs, expdesc *e) { - if (e->k != VUPVAL || hasjumps(e)) - luaK_exp2anyreg(fs, e); -} - - -/* -** Ensures final expression result is either in a register or it is -** a constant. -*/ -void luaK_exp2val (FuncState *fs, expdesc *e) { - if (hasjumps(e)) - luaK_exp2anyreg(fs, e); - else - luaK_dischargevars(fs, e); -} - - -/* -** Ensures final expression result is in a valid R/K index -** (that is, it is either in a register or in 'k' with an index -** in the range of R/K indices). -** Returns R/K index. -*/ -int luaK_exp2RK (FuncState *fs, expdesc *e) { - luaK_exp2val(fs, e); - switch (e->k) { /* move constants to 'k' */ - case VTRUE: e->u.info = boolK(fs, 1); goto vk; - case VFALSE: e->u.info = boolK(fs, 0); goto vk; - case VNIL: e->u.info = nilK(fs); goto vk; - case VKINT: e->u.info = luaK_intK(fs, e->u.ival); goto vk; - case VKFLT: e->u.info = luaK_numberK(fs, e->u.nval); goto vk; - case VK: - vk: - e->k = VK; - if (e->u.info <= MAXINDEXRK) /* constant fits in 'argC'? */ - return RKASK(e->u.info); - else break; - default: break; - } - /* not a constant in the right range: put it in a register */ - return luaK_exp2anyreg(fs, e); -} - - -/* -** Generate code to store result of expression 'ex' into variable 'var'. -*/ -void luaK_storevar (FuncState *fs, expdesc *var, expdesc *ex) { - switch (var->k) { - case VLOCAL: { - freeexp(fs, ex); - exp2reg(fs, ex, var->u.info); /* compute 'ex' into proper place */ - return; - } - case VUPVAL: { - int e = luaK_exp2anyreg(fs, ex); - luaK_codeABC(fs, OP_SETUPVAL, e, var->u.info, 0); - break; - } - case VINDEXED: { - OpCode op = (var->u.ind.vt == VLOCAL) ? OP_SETTABLE : OP_SETTABUP; - int e = luaK_exp2RK(fs, ex); - luaK_codeABC(fs, op, var->u.ind.t, var->u.ind.idx, e); - break; - } - default: lua_assert(0); /* invalid var kind to store */ - } - freeexp(fs, ex); -} - - -/* -** Emit SELF instruction (convert expression 'e' into 'e:key(e,'). -*/ -void luaK_self (FuncState *fs, expdesc *e, expdesc *key) { - int ereg; - luaK_exp2anyreg(fs, e); - ereg = e->u.info; /* register where 'e' was placed */ - freeexp(fs, e); - e->u.info = fs->freereg; /* base register for op_self */ - e->k = VNONRELOC; /* self expression has a fixed register */ - luaK_reserveregs(fs, 2); /* function and 'self' produced by op_self */ - luaK_codeABC(fs, OP_SELF, e->u.info, ereg, luaK_exp2RK(fs, key)); - freeexp(fs, key); -} - - -/* -** Negate condition 'e' (where 'e' is a comparison). -*/ -static void negatecondition (FuncState *fs, expdesc *e) { - Instruction *pc = getjumpcontrol(fs, e->u.info); - lua_assert(testTMode(GET_OPCODE(*pc)) && GET_OPCODE(*pc) != OP_TESTSET && - GET_OPCODE(*pc) != OP_TEST); - SETARG_A(*pc, !(GETARG_A(*pc))); -} - - -/* -** Emit instruction to jump if 'e' is 'cond' (that is, if 'cond' -** is true, code will jump if 'e' is true.) Return jump position. -** Optimize when 'e' is 'not' something, inverting the condition -** and removing the 'not'. -*/ -static int jumponcond (FuncState *fs, expdesc *e, int cond) { - if (e->k == VRELOCABLE) { - Instruction ie = getinstruction(fs, e); - if (GET_OPCODE(ie) == OP_NOT) { - fs->pc--; /* remove previous OP_NOT */ - return condjump(fs, OP_TEST, GETARG_B(ie), 0, !cond); - } - /* else go through */ - } - discharge2anyreg(fs, e); - freeexp(fs, e); - return condjump(fs, OP_TESTSET, NO_REG, e->u.info, cond); -} - - -/* -** Emit code to go through if 'e' is true, jump otherwise. -*/ -void luaK_goiftrue (FuncState *fs, expdesc *e) { - int pc; /* pc of new jump */ - luaK_dischargevars(fs, e); - switch (e->k) { - case VJMP: { /* condition? */ - negatecondition(fs, e); /* jump when it is false */ - pc = e->u.info; /* save jump position */ - break; - } - case VK: case VKFLT: case VKINT: case VTRUE: { - pc = NO_JUMP; /* always true; do nothing */ - break; - } - default: { - pc = jumponcond(fs, e, 0); /* jump when false */ - break; - } - } - luaK_concat(fs, &e->f, pc); /* insert new jump in false list */ - luaK_patchtohere(fs, e->t); /* true list jumps to here (to go through) */ - e->t = NO_JUMP; -} - - -/* -** Emit code to go through if 'e' is false, jump otherwise. -*/ -void luaK_goiffalse (FuncState *fs, expdesc *e) { - int pc; /* pc of new jump */ - luaK_dischargevars(fs, e); - switch (e->k) { - case VJMP: { - pc = e->u.info; /* already jump if true */ - break; - } - case VNIL: case VFALSE: { - pc = NO_JUMP; /* always false; do nothing */ - break; - } - default: { - pc = jumponcond(fs, e, 1); /* jump if true */ - break; - } - } - luaK_concat(fs, &e->t, pc); /* insert new jump in 't' list */ - luaK_patchtohere(fs, e->f); /* false list jumps to here (to go through) */ - e->f = NO_JUMP; -} - - -/* -** Code 'not e', doing constant folding. -*/ -static void codenot (FuncState *fs, expdesc *e) { - luaK_dischargevars(fs, e); - switch (e->k) { - case VNIL: case VFALSE: { - e->k = VTRUE; /* true == not nil == not false */ - break; - } - case VK: case VKFLT: case VKINT: case VTRUE: { - e->k = VFALSE; /* false == not "x" == not 0.5 == not 1 == not true */ - break; - } - case VJMP: { - negatecondition(fs, e); - break; - } - case VRELOCABLE: - case VNONRELOC: { - discharge2anyreg(fs, e); - freeexp(fs, e); - e->u.info = luaK_codeABC(fs, OP_NOT, 0, e->u.info, 0); - e->k = VRELOCABLE; - break; - } - default: lua_assert(0); /* cannot happen */ - } - /* interchange true and false lists */ - { int temp = e->f; e->f = e->t; e->t = temp; } - removevalues(fs, e->f); /* values are useless when negated */ - removevalues(fs, e->t); -} - - -/* -** Create expression 't[k]'. 't' must have its final result already in a -** register or upvalue. -*/ -void luaK_indexed (FuncState *fs, expdesc *t, expdesc *k) { - lua_assert(!hasjumps(t) && (vkisinreg(t->k) || t->k == VUPVAL)); - t->u.ind.t = t->u.info; /* register or upvalue index */ - t->u.ind.idx = luaK_exp2RK(fs, k); /* R/K index for key */ - t->u.ind.vt = (t->k == VUPVAL) ? VUPVAL : VLOCAL; - t->k = VINDEXED; -} - - -/* -** Return false if folding can raise an error. -** Bitwise operations need operands convertible to integers; division -** operations cannot have 0 as divisor. -*/ -static int validop (int op, TValue *v1, TValue *v2) { - switch (op) { - case LUA_OPBAND: case LUA_OPBOR: case LUA_OPBXOR: - case LUA_OPSHL: case LUA_OPSHR: case LUA_OPBNOT: { /* conversion errors */ - lua_Integer i; - return (tointeger(v1, &i) && tointeger(v2, &i)); - } - case LUA_OPDIV: case LUA_OPIDIV: case LUA_OPMOD: /* division by 0 */ - return (nvalue(v2) != 0); - default: return 1; /* everything else is valid */ - } -} - - -/* -** Try to "constant-fold" an operation; return 1 iff successful. -** (In this case, 'e1' has the final result.) -*/ -static int constfolding (FuncState *fs, int op, expdesc *e1, - const expdesc *e2) { - TValue v1, v2, res; - if (!tonumeral(e1, &v1) || !tonumeral(e2, &v2) || !validop(op, &v1, &v2)) - return 0; /* non-numeric operands or not safe to fold */ - luaO_arith(fs->ls->L, op, &v1, &v2, &res); /* does operation */ - if (ttisinteger(&res)) { - e1->k = VKINT; - e1->u.ival = ivalue(&res); - } - else { /* folds neither NaN nor 0.0 (to avoid problems with -0.0) */ - lua_Number n = fltvalue(&res); - if (luai_numisnan(n) || n == 0) - return 0; - e1->k = VKFLT; - e1->u.nval = n; - } - return 1; -} - - -/* -** Emit code for unary expressions that "produce values" -** (everything but 'not'). -** Expression to produce final result will be encoded in 'e'. -*/ -static void codeunexpval (FuncState *fs, OpCode op, expdesc *e, int line) { - int r = luaK_exp2anyreg(fs, e); /* opcodes operate only on registers */ - freeexp(fs, e); - e->u.info = luaK_codeABC(fs, op, 0, r, 0); /* generate opcode */ - e->k = VRELOCABLE; /* all those operations are relocatable */ - luaK_fixline(fs, line); -} - - -/* -** Emit code for binary expressions that "produce values" -** (everything but logical operators 'and'/'or' and comparison -** operators). -** Expression to produce final result will be encoded in 'e1'. -** Because 'luaK_exp2RK' can free registers, its calls must be -** in "stack order" (that is, first on 'e2', which may have more -** recent registers to be released). -*/ -static void codebinexpval (FuncState *fs, OpCode op, - expdesc *e1, expdesc *e2, int line) { - int rk2 = luaK_exp2RK(fs, e2); /* both operands are "RK" */ - int rk1 = luaK_exp2RK(fs, e1); - freeexps(fs, e1, e2); - e1->u.info = luaK_codeABC(fs, op, 0, rk1, rk2); /* generate opcode */ - e1->k = VRELOCABLE; /* all those operations are relocatable */ - luaK_fixline(fs, line); -} - - -/* -** Emit code for comparisons. -** 'e1' was already put in R/K form by 'luaK_infix'. -*/ -static void codecomp (FuncState *fs, BinOpr opr, expdesc *e1, expdesc *e2) { - int rk1 = (e1->k == VK) ? RKASK(e1->u.info) - : check_exp(e1->k == VNONRELOC, e1->u.info); - int rk2 = luaK_exp2RK(fs, e2); - freeexps(fs, e1, e2); - switch (opr) { - case OPR_NE: { /* '(a ~= b)' ==> 'not (a == b)' */ - e1->u.info = condjump(fs, OP_EQ, 0, rk1, rk2); - break; - } - case OPR_GT: case OPR_GE: { - /* '(a > b)' ==> '(b < a)'; '(a >= b)' ==> '(b <= a)' */ - OpCode op = cast(OpCode, (opr - OPR_NE) + OP_EQ); - e1->u.info = condjump(fs, op, 1, rk2, rk1); /* invert operands */ - break; - } - default: { /* '==', '<', '<=' use their own opcodes */ - OpCode op = cast(OpCode, (opr - OPR_EQ) + OP_EQ); - e1->u.info = condjump(fs, op, 1, rk1, rk2); - break; - } - } - e1->k = VJMP; -} - - -/* -** Apply prefix operation 'op' to expression 'e'. -*/ -void luaK_prefix (FuncState *fs, UnOpr op, expdesc *e, int line) { - static const expdesc ef = {VKINT, {0}, NO_JUMP, NO_JUMP}; - switch (op) { - case OPR_MINUS: case OPR_BNOT: /* use 'ef' as fake 2nd operand */ - if (constfolding(fs, op + LUA_OPUNM, e, &ef)) - break; - /* FALLTHROUGH */ - case OPR_LEN: - codeunexpval(fs, cast(OpCode, op + OP_UNM), e, line); - break; - case OPR_NOT: codenot(fs, e); break; - default: lua_assert(0); - } -} - - -/* -** Process 1st operand 'v' of binary operation 'op' before reading -** 2nd operand. -*/ -void luaK_infix (FuncState *fs, BinOpr op, expdesc *v) { - switch (op) { - case OPR_AND: { - luaK_goiftrue(fs, v); /* go ahead only if 'v' is true */ - break; - } - case OPR_OR: { - luaK_goiffalse(fs, v); /* go ahead only if 'v' is false */ - break; - } - case OPR_CONCAT: { - luaK_exp2nextreg(fs, v); /* operand must be on the 'stack' */ - break; - } - case OPR_ADD: case OPR_SUB: - case OPR_MUL: case OPR_DIV: case OPR_IDIV: - case OPR_MOD: case OPR_POW: - case OPR_BAND: case OPR_BOR: case OPR_BXOR: - case OPR_SHL: case OPR_SHR: { - if (!tonumeral(v, NULL)) - luaK_exp2RK(fs, v); - /* else keep numeral, which may be folded with 2nd operand */ - break; - } - default: { - luaK_exp2RK(fs, v); - break; - } - } -} - - -/* -** Finalize code for binary operation, after reading 2nd operand. -** For '(a .. b .. c)' (which is '(a .. (b .. c))', because -** concatenation is right associative), merge second CONCAT into first -** one. -*/ -void luaK_posfix (FuncState *fs, BinOpr op, - expdesc *e1, expdesc *e2, int line) { - switch (op) { - case OPR_AND: { - lua_assert(e1->t == NO_JUMP); /* list closed by 'luK_infix' */ - luaK_dischargevars(fs, e2); - luaK_concat(fs, &e2->f, e1->f); - *e1 = *e2; - break; - } - case OPR_OR: { - lua_assert(e1->f == NO_JUMP); /* list closed by 'luK_infix' */ - luaK_dischargevars(fs, e2); - luaK_concat(fs, &e2->t, e1->t); - *e1 = *e2; - break; - } - case OPR_CONCAT: { - luaK_exp2val(fs, e2); - if (e2->k == VRELOCABLE && - GET_OPCODE(getinstruction(fs, e2)) == OP_CONCAT) { - lua_assert(e1->u.info == GETARG_B(getinstruction(fs, e2))-1); - freeexp(fs, e1); - SETARG_B(getinstruction(fs, e2), e1->u.info); - e1->k = VRELOCABLE; e1->u.info = e2->u.info; - } - else { - luaK_exp2nextreg(fs, e2); /* operand must be on the 'stack' */ - codebinexpval(fs, OP_CONCAT, e1, e2, line); - } - break; - } - case OPR_ADD: case OPR_SUB: case OPR_MUL: case OPR_DIV: - case OPR_IDIV: case OPR_MOD: case OPR_POW: - case OPR_BAND: case OPR_BOR: case OPR_BXOR: - case OPR_SHL: case OPR_SHR: { - if (!constfolding(fs, op + LUA_OPADD, e1, e2)) - codebinexpval(fs, cast(OpCode, op + OP_ADD), e1, e2, line); - break; - } - case OPR_EQ: case OPR_LT: case OPR_LE: - case OPR_NE: case OPR_GT: case OPR_GE: { - codecomp(fs, op, e1, e2); - break; - } - default: lua_assert(0); - } -} - - -/* -** Change line information associated with current position. -*/ -void luaK_fixline (FuncState *fs, int line) { - fs->f->lineinfo[fs->pc - 1] = line; -} - - -/* -** Emit a SETLIST instruction. -** 'base' is register that keeps table; -** 'nelems' is #table plus those to be stored now; -** 'tostore' is number of values (in registers 'base + 1',...) to add to -** table (or LUA_MULTRET to add up to stack top). -*/ -void luaK_setlist (FuncState *fs, int base, int nelems, int tostore) { - int c = (nelems - 1)/LFIELDS_PER_FLUSH + 1; - int b = (tostore == LUA_MULTRET) ? 0 : tostore; - lua_assert(tostore != 0 && tostore <= LFIELDS_PER_FLUSH); - if (c <= MAXARG_C) - luaK_codeABC(fs, OP_SETLIST, base, b, c); - else if (c <= MAXARG_Ax) { - luaK_codeABC(fs, OP_SETLIST, base, b, 0); - codeextraarg(fs, c); - } - else - luaX_syntaxerror(fs->ls, "constructor too long"); - fs->freereg = base + 1; /* free registers with list values */ -} - diff --git a/lib/lua-5.3/src/lcode.h b/lib/lua-5.3/src/lcode.h deleted file mode 100644 index 882dc9c..0000000 --- a/lib/lua-5.3/src/lcode.h +++ /dev/null @@ -1,88 +0,0 @@ -/* -** $Id: lcode.h,v 1.64.1.1 2017/04/19 17:20:42 roberto Exp $ -** Code generator for Lua -** See Copyright Notice in lua.h -*/ - -#ifndef lcode_h -#define lcode_h - -#include "llex.h" -#include "lobject.h" -#include "lopcodes.h" -#include "lparser.h" - - -/* -** Marks the end of a patch list. It is an invalid value both as an absolute -** address, and as a list link (would link an element to itself). -*/ -#define NO_JUMP (-1) - - -/* -** grep "ORDER OPR" if you change these enums (ORDER OP) -*/ -typedef enum BinOpr { - OPR_ADD, OPR_SUB, OPR_MUL, OPR_MOD, OPR_POW, - OPR_DIV, - OPR_IDIV, - OPR_BAND, OPR_BOR, OPR_BXOR, - OPR_SHL, OPR_SHR, - OPR_CONCAT, - OPR_EQ, OPR_LT, OPR_LE, - OPR_NE, OPR_GT, OPR_GE, - OPR_AND, OPR_OR, - OPR_NOBINOPR -} BinOpr; - - -typedef enum UnOpr { OPR_MINUS, OPR_BNOT, OPR_NOT, OPR_LEN, OPR_NOUNOPR } UnOpr; - - -/* get (pointer to) instruction of given 'expdesc' */ -#define getinstruction(fs,e) ((fs)->f->code[(e)->u.info]) - -#define luaK_codeAsBx(fs,o,A,sBx) luaK_codeABx(fs,o,A,(sBx)+MAXARG_sBx) - -#define luaK_setmultret(fs,e) luaK_setreturns(fs, e, LUA_MULTRET) - -#define luaK_jumpto(fs,t) luaK_patchlist(fs, luaK_jump(fs), t) - -LUAI_FUNC int luaK_codeABx (FuncState *fs, OpCode o, int A, unsigned int Bx); -LUAI_FUNC int luaK_codeABC (FuncState *fs, OpCode o, int A, int B, int C); -LUAI_FUNC int luaK_codek (FuncState *fs, int reg, int k); -LUAI_FUNC void luaK_fixline (FuncState *fs, int line); -LUAI_FUNC void luaK_nil (FuncState *fs, int from, int n); -LUAI_FUNC void luaK_reserveregs (FuncState *fs, int n); -LUAI_FUNC void luaK_checkstack (FuncState *fs, int n); -LUAI_FUNC int luaK_stringK (FuncState *fs, TString *s); -LUAI_FUNC int luaK_intK (FuncState *fs, lua_Integer n); -LUAI_FUNC void luaK_dischargevars (FuncState *fs, expdesc *e); -LUAI_FUNC int luaK_exp2anyreg (FuncState *fs, expdesc *e); -LUAI_FUNC void luaK_exp2anyregup (FuncState *fs, expdesc *e); -LUAI_FUNC void luaK_exp2nextreg (FuncState *fs, expdesc *e); -LUAI_FUNC void luaK_exp2val (FuncState *fs, expdesc *e); -LUAI_FUNC int luaK_exp2RK (FuncState *fs, expdesc *e); -LUAI_FUNC void luaK_self (FuncState *fs, expdesc *e, expdesc *key); -LUAI_FUNC void luaK_indexed (FuncState *fs, expdesc *t, expdesc *k); -LUAI_FUNC void luaK_goiftrue (FuncState *fs, expdesc *e); -LUAI_FUNC void luaK_goiffalse (FuncState *fs, expdesc *e); -LUAI_FUNC void luaK_storevar (FuncState *fs, expdesc *var, expdesc *e); -LUAI_FUNC void luaK_setreturns (FuncState *fs, expdesc *e, int nresults); -LUAI_FUNC void luaK_setoneret (FuncState *fs, expdesc *e); -LUAI_FUNC int luaK_jump (FuncState *fs); -LUAI_FUNC void luaK_ret (FuncState *fs, int first, int nret); -LUAI_FUNC void luaK_patchlist (FuncState *fs, int list, int target); -LUAI_FUNC void luaK_patchtohere (FuncState *fs, int list); -LUAI_FUNC void luaK_patchclose (FuncState *fs, int list, int level); -LUAI_FUNC void luaK_concat (FuncState *fs, int *l1, int l2); -LUAI_FUNC int luaK_getlabel (FuncState *fs); -LUAI_FUNC void luaK_prefix (FuncState *fs, UnOpr op, expdesc *v, int line); -LUAI_FUNC void luaK_infix (FuncState *fs, BinOpr op, expdesc *v); -LUAI_FUNC void luaK_posfix (FuncState *fs, BinOpr op, expdesc *v1, - expdesc *v2, int line); -LUAI_FUNC void luaK_setlist (FuncState *fs, int base, int nelems, int tostore); - - -#endif diff --git a/lib/lua-5.3/src/lcorolib.c b/lib/lua-5.3/src/lcorolib.c deleted file mode 100644 index 0b17af9..0000000 --- a/lib/lua-5.3/src/lcorolib.c +++ /dev/null @@ -1,168 +0,0 @@ -/* -** $Id: lcorolib.c,v 1.10.1.1 2017/04/19 17:20:42 roberto Exp $ -** Coroutine Library -** See Copyright Notice in lua.h -*/ - -#define lcorolib_c -#define LUA_LIB - -#include "lprefix.h" - - -#include - -#include "lua.h" - -#include "lauxlib.h" -#include "lualib.h" - - -static lua_State *getco (lua_State *L) { - lua_State *co = lua_tothread(L, 1); - luaL_argcheck(L, co, 1, "thread expected"); - return co; -} - - -static int auxresume (lua_State *L, lua_State *co, int narg) { - int status; - if (!lua_checkstack(co, narg)) { - lua_pushliteral(L, "too many arguments to resume"); - return -1; /* error flag */ - } - if (lua_status(co) == LUA_OK && lua_gettop(co) == 0) { - lua_pushliteral(L, "cannot resume dead coroutine"); - return -1; /* error flag */ - } - lua_xmove(L, co, narg); - status = lua_resume(co, L, narg); - if (status == LUA_OK || status == LUA_YIELD) { - int nres = lua_gettop(co); - if (!lua_checkstack(L, nres + 1)) { - lua_pop(co, nres); /* remove results anyway */ - lua_pushliteral(L, "too many results to resume"); - return -1; /* error flag */ - } - lua_xmove(co, L, nres); /* move yielded values */ - return nres; - } - else { - lua_xmove(co, L, 1); /* move error message */ - return -1; /* error flag */ - } -} - - -static int luaB_coresume (lua_State *L) { - lua_State *co = getco(L); - int r; - r = auxresume(L, co, lua_gettop(L) - 1); - if (r < 0) { - lua_pushboolean(L, 0); - lua_insert(L, -2); - return 2; /* return false + error message */ - } - else { - lua_pushboolean(L, 1); - lua_insert(L, -(r + 1)); - return r + 1; /* return true + 'resume' returns */ - } -} - - -static int luaB_auxwrap (lua_State *L) { - lua_State *co = lua_tothread(L, lua_upvalueindex(1)); - int r = auxresume(L, co, lua_gettop(L)); - if (r < 0) { - if (lua_type(L, -1) == LUA_TSTRING) { /* error object is a string? */ - luaL_where(L, 1); /* add extra info */ - lua_insert(L, -2); - lua_concat(L, 2); - } - return lua_error(L); /* propagate error */ - } - return r; -} - - -static int luaB_cocreate (lua_State *L) { - lua_State *NL; - luaL_checktype(L, 1, LUA_TFUNCTION); - NL = lua_newthread(L); - lua_pushvalue(L, 1); /* move function to top */ - lua_xmove(L, NL, 1); /* move function from L to NL */ - return 1; -} - - -static int luaB_cowrap (lua_State *L) { - luaB_cocreate(L); - lua_pushcclosure(L, luaB_auxwrap, 1); - return 1; -} - - -static int luaB_yield (lua_State *L) { - return lua_yield(L, lua_gettop(L)); -} - - -static int luaB_costatus (lua_State *L) { - lua_State *co = getco(L); - if (L == co) lua_pushliteral(L, "running"); - else { - switch (lua_status(co)) { - case LUA_YIELD: - lua_pushliteral(L, "suspended"); - break; - case LUA_OK: { - lua_Debug ar; - if (lua_getstack(co, 0, &ar) > 0) /* does it have frames? */ - lua_pushliteral(L, "normal"); /* it is running */ - else if (lua_gettop(co) == 0) - lua_pushliteral(L, "dead"); - else - lua_pushliteral(L, "suspended"); /* initial state */ - break; - } - default: /* some error occurred */ - lua_pushliteral(L, "dead"); - break; - } - } - return 1; -} - - -static int luaB_yieldable (lua_State *L) { - lua_pushboolean(L, lua_isyieldable(L)); - return 1; -} - - -static int luaB_corunning (lua_State *L) { - int ismain = lua_pushthread(L); - lua_pushboolean(L, ismain); - return 2; -} - - -static const luaL_Reg co_funcs[] = { - {"create", luaB_cocreate}, - {"resume", luaB_coresume}, - {"running", luaB_corunning}, - {"status", luaB_costatus}, - {"wrap", luaB_cowrap}, - {"yield", luaB_yield}, - {"isyieldable", luaB_yieldable}, - {NULL, NULL} -}; - - - -LUAMOD_API int luaopen_coroutine (lua_State *L) { - luaL_newlib(L, co_funcs); - return 1; -} - diff --git a/lib/lua-5.3/src/lctype.c b/lib/lua-5.3/src/lctype.c deleted file mode 100644 index f8ad7a2..0000000 --- a/lib/lua-5.3/src/lctype.c +++ /dev/null @@ -1,55 +0,0 @@ -/* -** $Id: lctype.c,v 1.12.1.1 2017/04/19 17:20:42 roberto Exp $ -** 'ctype' functions for Lua -** See Copyright Notice in lua.h -*/ - -#define lctype_c -#define LUA_CORE - -#include "lprefix.h" - - -#include "lctype.h" - -#if !LUA_USE_CTYPE /* { */ - -#include - -LUAI_DDEF const lu_byte luai_ctype_[UCHAR_MAX + 2] = { - 0x00, /* EOZ */ - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0. */ - 0x00, 0x08, 0x08, 0x08, 0x08, 0x08, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 1. */ - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x0c, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, /* 2. */ - 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, - 0x16, 0x16, 0x16, 0x16, 0x16, 0x16, 0x16, 0x16, /* 3. */ - 0x16, 0x16, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, - 0x04, 0x15, 0x15, 0x15, 0x15, 0x15, 0x15, 0x05, /* 4. */ - 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, - 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, /* 5. */ - 0x05, 0x05, 0x05, 0x04, 0x04, 0x04, 0x04, 0x05, - 0x04, 0x15, 0x15, 0x15, 0x15, 0x15, 0x15, 0x05, /* 6. */ - 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, - 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, /* 7. */ - 0x05, 0x05, 0x05, 0x04, 0x04, 0x04, 0x04, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 8. */ - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 9. */ - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* a. */ - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* b. */ - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* c. */ - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* d. */ - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* e. */ - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* f. */ - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -}; - -#endif /* } */ diff --git a/lib/lua-5.3/src/lctype.h b/lib/lua-5.3/src/lctype.h deleted file mode 100644 index b09b21a..0000000 --- a/lib/lua-5.3/src/lctype.h +++ /dev/null @@ -1,95 +0,0 @@ -/* -** $Id: lctype.h,v 1.12.1.1 2013/04/12 18:48:47 roberto Exp $ -** 'ctype' functions for Lua -** See Copyright Notice in lua.h -*/ - -#ifndef lctype_h -#define lctype_h - -#include "lua.h" - - -/* -** WARNING: the functions defined here do not necessarily correspond -** to the similar functions in the standard C ctype.h. They are -** optimized for the specific needs of Lua -*/ - -#if !defined(LUA_USE_CTYPE) - -#if 'A' == 65 && '0' == 48 -/* ASCII case: can use its own tables; faster and fixed */ -#define LUA_USE_CTYPE 0 -#else -/* must use standard C ctype */ -#define LUA_USE_CTYPE 1 -#endif - -#endif - - -#if !LUA_USE_CTYPE /* { */ - -#include - -#include "llimits.h" - - -#define ALPHABIT 0 -#define DIGITBIT 1 -#define PRINTBIT 2 -#define SPACEBIT 3 -#define XDIGITBIT 4 - - -#define MASK(B) (1 << (B)) - - -/* -** add 1 to char to allow index -1 (EOZ) -*/ -#define testprop(c,p) (luai_ctype_[(c)+1] & (p)) - -/* -** 'lalpha' (Lua alphabetic) and 'lalnum' (Lua alphanumeric) both include '_' -*/ -#define lislalpha(c) testprop(c, MASK(ALPHABIT)) -#define lislalnum(c) testprop(c, (MASK(ALPHABIT) | MASK(DIGITBIT))) -#define lisdigit(c) testprop(c, MASK(DIGITBIT)) -#define lisspace(c) testprop(c, MASK(SPACEBIT)) -#define lisprint(c) testprop(c, MASK(PRINTBIT)) -#define lisxdigit(c) testprop(c, MASK(XDIGITBIT)) - -/* -** this 'ltolower' only works for alphabetic characters -*/ -#define ltolower(c) ((c) | ('A' ^ 'a')) - - -/* two more entries for 0 and -1 (EOZ) */ -LUAI_DDEC const lu_byte luai_ctype_[UCHAR_MAX + 2]; - - -#else /* }{ */ - -/* -** use standard C ctypes -*/ - -#include - - -#define lislalpha(c) (isalpha(c) || (c) == '_') -#define lislalnum(c) (isalnum(c) || (c) == '_') -#define lisdigit(c) (isdigit(c)) -#define lisspace(c) (isspace(c)) -#define lisprint(c) (isprint(c)) -#define lisxdigit(c) (isxdigit(c)) - -#define ltolower(c) (tolower(c)) - -#endif /* } */ - -#endif - diff --git a/lib/lua-5.3/src/ldblib.c b/lib/lua-5.3/src/ldblib.c deleted file mode 100644 index 9d29afb..0000000 --- a/lib/lua-5.3/src/ldblib.c +++ /dev/null @@ -1,456 +0,0 @@ -/* -** $Id: ldblib.c,v 1.151.1.1 2017/04/19 17:20:42 roberto Exp $ -** Interface from Lua to its debug API -** See Copyright Notice in lua.h -*/ - -#define ldblib_c -#define LUA_LIB - -#include "lprefix.h" - - -#include -#include -#include - -#include "lua.h" - -#include "lauxlib.h" -#include "lualib.h" - - -/* -** The hook table at registry[&HOOKKEY] maps threads to their current -** hook function. (We only need the unique address of 'HOOKKEY'.) -*/ -static const int HOOKKEY = 0; - - -/* -** If L1 != L, L1 can be in any state, and therefore there are no -** guarantees about its stack space; any push in L1 must be -** checked. -*/ -static void checkstack (lua_State *L, lua_State *L1, int n) { - if (L != L1 && !lua_checkstack(L1, n)) - luaL_error(L, "stack overflow"); -} - - -static int db_getregistry (lua_State *L) { - lua_pushvalue(L, LUA_REGISTRYINDEX); - return 1; -} - - -static int db_getmetatable (lua_State *L) { - luaL_checkany(L, 1); - if (!lua_getmetatable(L, 1)) { - lua_pushnil(L); /* no metatable */ - } - return 1; -} - - -static int db_setmetatable (lua_State *L) { - int t = lua_type(L, 2); - luaL_argcheck(L, t == LUA_TNIL || t == LUA_TTABLE, 2, - "nil or table expected"); - lua_settop(L, 2); - lua_setmetatable(L, 1); - return 1; /* return 1st argument */ -} - - -static int db_getuservalue (lua_State *L) { - if (lua_type(L, 1) != LUA_TUSERDATA) - lua_pushnil(L); - else - lua_getuservalue(L, 1); - return 1; -} - - -static int db_setuservalue (lua_State *L) { - luaL_checktype(L, 1, LUA_TUSERDATA); - luaL_checkany(L, 2); - lua_settop(L, 2); - lua_setuservalue(L, 1); - return 1; -} - - -/* -** Auxiliary function used by several library functions: check for -** an optional thread as function's first argument and set 'arg' with -** 1 if this argument is present (so that functions can skip it to -** access their other arguments) -*/ -static lua_State *getthread (lua_State *L, int *arg) { - if (lua_isthread(L, 1)) { - *arg = 1; - return lua_tothread(L, 1); - } - else { - *arg = 0; - return L; /* function will operate over current thread */ - } -} - - -/* -** Variations of 'lua_settable', used by 'db_getinfo' to put results -** from 'lua_getinfo' into result table. Key is always a string; -** value can be a string, an int, or a boolean. -*/ -static void settabss (lua_State *L, const char *k, const char *v) { - lua_pushstring(L, v); - lua_setfield(L, -2, k); -} - -static void settabsi (lua_State *L, const char *k, int v) { - lua_pushinteger(L, v); - lua_setfield(L, -2, k); -} - -static void settabsb (lua_State *L, const char *k, int v) { - lua_pushboolean(L, v); - lua_setfield(L, -2, k); -} - - -/* -** In function 'db_getinfo', the call to 'lua_getinfo' may push -** results on the stack; later it creates the result table to put -** these objects. Function 'treatstackoption' puts the result from -** 'lua_getinfo' on top of the result table so that it can call -** 'lua_setfield'. -*/ -static void treatstackoption (lua_State *L, lua_State *L1, const char *fname) { - if (L == L1) - lua_rotate(L, -2, 1); /* exchange object and table */ - else - lua_xmove(L1, L, 1); /* move object to the "main" stack */ - lua_setfield(L, -2, fname); /* put object into table */ -} - - -/* -** Calls 'lua_getinfo' and collects all results in a new table. -** L1 needs stack space for an optional input (function) plus -** two optional outputs (function and line table) from function -** 'lua_getinfo'. -*/ -static int db_getinfo (lua_State *L) { - lua_Debug ar; - int arg; - lua_State *L1 = getthread(L, &arg); - const char *options = luaL_optstring(L, arg+2, "flnStu"); - checkstack(L, L1, 3); - if (lua_isfunction(L, arg + 1)) { /* info about a function? */ - options = lua_pushfstring(L, ">%s", options); /* add '>' to 'options' */ - lua_pushvalue(L, arg + 1); /* move function to 'L1' stack */ - lua_xmove(L, L1, 1); - } - else { /* stack level */ - if (!lua_getstack(L1, (int)luaL_checkinteger(L, arg + 1), &ar)) { - lua_pushnil(L); /* level out of range */ - return 1; - } - } - if (!lua_getinfo(L1, options, &ar)) - return luaL_argerror(L, arg+2, "invalid option"); - lua_newtable(L); /* table to collect results */ - if (strchr(options, 'S')) { - settabss(L, "source", ar.source); - settabss(L, "short_src", ar.short_src); - settabsi(L, "linedefined", ar.linedefined); - settabsi(L, "lastlinedefined", ar.lastlinedefined); - settabss(L, "what", ar.what); - } - if (strchr(options, 'l')) - settabsi(L, "currentline", ar.currentline); - if (strchr(options, 'u')) { - settabsi(L, "nups", ar.nups); - settabsi(L, "nparams", ar.nparams); - settabsb(L, "isvararg", ar.isvararg); - } - if (strchr(options, 'n')) { - settabss(L, "name", ar.name); - settabss(L, "namewhat", ar.namewhat); - } - if (strchr(options, 't')) - settabsb(L, "istailcall", ar.istailcall); - if (strchr(options, 'L')) - treatstackoption(L, L1, "activelines"); - if (strchr(options, 'f')) - treatstackoption(L, L1, "func"); - return 1; /* return table */ -} - - -static int db_getlocal (lua_State *L) { - int arg; - lua_State *L1 = getthread(L, &arg); - lua_Debug ar; - const char *name; - int nvar = (int)luaL_checkinteger(L, arg + 2); /* local-variable index */ - if (lua_isfunction(L, arg + 1)) { /* function argument? */ - lua_pushvalue(L, arg + 1); /* push function */ - lua_pushstring(L, lua_getlocal(L, NULL, nvar)); /* push local name */ - return 1; /* return only name (there is no value) */ - } - else { /* stack-level argument */ - int level = (int)luaL_checkinteger(L, arg + 1); - if (!lua_getstack(L1, level, &ar)) /* out of range? */ - return luaL_argerror(L, arg+1, "level out of range"); - checkstack(L, L1, 1); - name = lua_getlocal(L1, &ar, nvar); - if (name) { - lua_xmove(L1, L, 1); /* move local value */ - lua_pushstring(L, name); /* push name */ - lua_rotate(L, -2, 1); /* re-order */ - return 2; - } - else { - lua_pushnil(L); /* no name (nor value) */ - return 1; - } - } -} - - -static int db_setlocal (lua_State *L) { - int arg; - const char *name; - lua_State *L1 = getthread(L, &arg); - lua_Debug ar; - int level = (int)luaL_checkinteger(L, arg + 1); - int nvar = (int)luaL_checkinteger(L, arg + 2); - if (!lua_getstack(L1, level, &ar)) /* out of range? */ - return luaL_argerror(L, arg+1, "level out of range"); - luaL_checkany(L, arg+3); - lua_settop(L, arg+3); - checkstack(L, L1, 1); - lua_xmove(L, L1, 1); - name = lua_setlocal(L1, &ar, nvar); - if (name == NULL) - lua_pop(L1, 1); /* pop value (if not popped by 'lua_setlocal') */ - lua_pushstring(L, name); - return 1; -} - - -/* -** get (if 'get' is true) or set an upvalue from a closure -*/ -static int auxupvalue (lua_State *L, int get) { - const char *name; - int n = (int)luaL_checkinteger(L, 2); /* upvalue index */ - luaL_checktype(L, 1, LUA_TFUNCTION); /* closure */ - name = get ? lua_getupvalue(L, 1, n) : lua_setupvalue(L, 1, n); - if (name == NULL) return 0; - lua_pushstring(L, name); - lua_insert(L, -(get+1)); /* no-op if get is false */ - return get + 1; -} - - -static int db_getupvalue (lua_State *L) { - return auxupvalue(L, 1); -} - - -static int db_setupvalue (lua_State *L) { - luaL_checkany(L, 3); - return auxupvalue(L, 0); -} - - -/* -** Check whether a given upvalue from a given closure exists and -** returns its index -*/ -static int checkupval (lua_State *L, int argf, int argnup) { - int nup = (int)luaL_checkinteger(L, argnup); /* upvalue index */ - luaL_checktype(L, argf, LUA_TFUNCTION); /* closure */ - luaL_argcheck(L, (lua_getupvalue(L, argf, nup) != NULL), argnup, - "invalid upvalue index"); - return nup; -} - - -static int db_upvalueid (lua_State *L) { - int n = checkupval(L, 1, 2); - lua_pushlightuserdata(L, lua_upvalueid(L, 1, n)); - return 1; -} - - -static int db_upvaluejoin (lua_State *L) { - int n1 = checkupval(L, 1, 2); - int n2 = checkupval(L, 3, 4); - luaL_argcheck(L, !lua_iscfunction(L, 1), 1, "Lua function expected"); - luaL_argcheck(L, !lua_iscfunction(L, 3), 3, "Lua function expected"); - lua_upvaluejoin(L, 1, n1, 3, n2); - return 0; -} - - -/* -** Call hook function registered at hook table for the current -** thread (if there is one) -*/ -static void hookf (lua_State *L, lua_Debug *ar) { - static const char *const hooknames[] = - {"call", "return", "line", "count", "tail call"}; - lua_rawgetp(L, LUA_REGISTRYINDEX, &HOOKKEY); - lua_pushthread(L); - if (lua_rawget(L, -2) == LUA_TFUNCTION) { /* is there a hook function? */ - lua_pushstring(L, hooknames[(int)ar->event]); /* push event name */ - if (ar->currentline >= 0) - lua_pushinteger(L, ar->currentline); /* push current line */ - else lua_pushnil(L); - lua_assert(lua_getinfo(L, "lS", ar)); - lua_call(L, 2, 0); /* call hook function */ - } -} - - -/* -** Convert a string mask (for 'sethook') into a bit mask -*/ -static int makemask (const char *smask, int count) { - int mask = 0; - if (strchr(smask, 'c')) mask |= LUA_MASKCALL; - if (strchr(smask, 'r')) mask |= LUA_MASKRET; - if (strchr(smask, 'l')) mask |= LUA_MASKLINE; - if (count > 0) mask |= LUA_MASKCOUNT; - return mask; -} - - -/* -** Convert a bit mask (for 'gethook') into a string mask -*/ -static char *unmakemask (int mask, char *smask) { - int i = 0; - if (mask & LUA_MASKCALL) smask[i++] = 'c'; - if (mask & LUA_MASKRET) smask[i++] = 'r'; - if (mask & LUA_MASKLINE) smask[i++] = 'l'; - smask[i] = '\0'; - return smask; -} - - -static int db_sethook (lua_State *L) { - int arg, mask, count; - lua_Hook func; - lua_State *L1 = getthread(L, &arg); - if (lua_isnoneornil(L, arg+1)) { /* no hook? */ - lua_settop(L, arg+1); - func = NULL; mask = 0; count = 0; /* turn off hooks */ - } - else { - const char *smask = luaL_checkstring(L, arg+2); - luaL_checktype(L, arg+1, LUA_TFUNCTION); - count = (int)luaL_optinteger(L, arg + 3, 0); - func = hookf; mask = makemask(smask, count); - } - if (lua_rawgetp(L, LUA_REGISTRYINDEX, &HOOKKEY) == LUA_TNIL) { - lua_createtable(L, 0, 2); /* create a hook table */ - lua_pushvalue(L, -1); - lua_rawsetp(L, LUA_REGISTRYINDEX, &HOOKKEY); /* set it in position */ - lua_pushstring(L, "k"); - lua_setfield(L, -2, "__mode"); /** hooktable.__mode = "k" */ - lua_pushvalue(L, -1); - lua_setmetatable(L, -2); /* setmetatable(hooktable) = hooktable */ - } - checkstack(L, L1, 1); - lua_pushthread(L1); lua_xmove(L1, L, 1); /* key (thread) */ - lua_pushvalue(L, arg + 1); /* value (hook function) */ - lua_rawset(L, -3); /* hooktable[L1] = new Lua hook */ - lua_sethook(L1, func, mask, count); - return 0; -} - - -static int db_gethook (lua_State *L) { - int arg; - lua_State *L1 = getthread(L, &arg); - char buff[5]; - int mask = lua_gethookmask(L1); - lua_Hook hook = lua_gethook(L1); - if (hook == NULL) /* no hook? */ - lua_pushnil(L); - else if (hook != hookf) /* external hook? */ - lua_pushliteral(L, "external hook"); - else { /* hook table must exist */ - lua_rawgetp(L, LUA_REGISTRYINDEX, &HOOKKEY); - checkstack(L, L1, 1); - lua_pushthread(L1); lua_xmove(L1, L, 1); - lua_rawget(L, -2); /* 1st result = hooktable[L1] */ - lua_remove(L, -2); /* remove hook table */ - } - lua_pushstring(L, unmakemask(mask, buff)); /* 2nd result = mask */ - lua_pushinteger(L, lua_gethookcount(L1)); /* 3rd result = count */ - return 3; -} - - -static int db_debug (lua_State *L) { - for (;;) { - char buffer[250]; - lua_writestringerror("%s", "lua_debug> "); - if (fgets(buffer, sizeof(buffer), stdin) == 0 || - strcmp(buffer, "cont\n") == 0) - return 0; - if (luaL_loadbuffer(L, buffer, strlen(buffer), "=(debug command)") || - lua_pcall(L, 0, 0, 0)) - lua_writestringerror("%s\n", lua_tostring(L, -1)); - lua_settop(L, 0); /* remove eventual returns */ - } -} - - -static int db_traceback (lua_State *L) { - int arg; - lua_State *L1 = getthread(L, &arg); - const char *msg = lua_tostring(L, arg + 1); - if (msg == NULL && !lua_isnoneornil(L, arg + 1)) /* non-string 'msg'? */ - lua_pushvalue(L, arg + 1); /* return it untouched */ - else { - int level = (int)luaL_optinteger(L, arg + 2, (L == L1) ? 1 : 0); - luaL_traceback(L, L1, msg, level); - } - return 1; -} - - -static const luaL_Reg dblib[] = { - {"debug", db_debug}, - {"getuservalue", db_getuservalue}, - {"gethook", db_gethook}, - {"getinfo", db_getinfo}, - {"getlocal", db_getlocal}, - {"getregistry", db_getregistry}, - {"getmetatable", db_getmetatable}, - {"getupvalue", db_getupvalue}, - {"upvaluejoin", db_upvaluejoin}, - {"upvalueid", db_upvalueid}, - {"setuservalue", db_setuservalue}, - {"sethook", db_sethook}, - {"setlocal", db_setlocal}, - {"setmetatable", db_setmetatable}, - {"setupvalue", db_setupvalue}, - {"traceback", db_traceback}, - {NULL, NULL} -}; - - -LUAMOD_API int luaopen_debug (lua_State *L) { - luaL_newlib(L, dblib); - return 1; -} - diff --git a/lib/lua-5.3/src/ldebug.c b/lib/lua-5.3/src/ldebug.c deleted file mode 100644 index bb0e1d4..0000000 --- a/lib/lua-5.3/src/ldebug.c +++ /dev/null @@ -1,700 +0,0 @@ -/* -** $Id: ldebug.c,v 2.121.1.2 2017/07/10 17:21:50 roberto Exp $ -** Debug Interface -** See Copyright Notice in lua.h -*/ - -#define ldebug_c -#define LUA_CORE - -#include "lprefix.h" - - -#include -#include -#include - -#include "lua.h" - -#include "lapi.h" -#include "lcode.h" -#include "ldebug.h" -#include "ldo.h" -#include "lfunc.h" -#include "lobject.h" -#include "lopcodes.h" -#include "lstate.h" -#include "lstring.h" -#include "ltable.h" -#include "ltm.h" -#include "lvm.h" - - - -#define noLuaClosure(f) ((f) == NULL || (f)->c.tt == LUA_TCCL) - - -/* Active Lua function (given call info) */ -#define ci_func(ci) (clLvalue((ci)->func)) - - -static const char *funcnamefromcode (lua_State *L, CallInfo *ci, - const char **name); - - -static int currentpc (CallInfo *ci) { - lua_assert(isLua(ci)); - return pcRel(ci->u.l.savedpc, ci_func(ci)->p); -} - - -static int currentline (CallInfo *ci) { - return getfuncline(ci_func(ci)->p, currentpc(ci)); -} - - -/* -** If function yielded, its 'func' can be in the 'extra' field. The -** next function restores 'func' to its correct value for debugging -** purposes. (It exchanges 'func' and 'extra'; so, when called again, -** after debugging, it also "re-restores" ** 'func' to its altered value. -*/ -static void swapextra (lua_State *L) { - if (L->status == LUA_YIELD) { - CallInfo *ci = L->ci; /* get function that yielded */ - StkId temp = ci->func; /* exchange its 'func' and 'extra' values */ - ci->func = restorestack(L, ci->extra); - ci->extra = savestack(L, temp); - } -} - - -/* -** This function can be called asynchronously (e.g. during a signal). -** Fields 'oldpc', 'basehookcount', and 'hookcount' (set by -** 'resethookcount') are for debug only, and it is no problem if they -** get arbitrary values (causes at most one wrong hook call). 'hookmask' -** is an atomic value. We assume that pointers are atomic too (e.g., gcc -** ensures that for all platforms where it runs). Moreover, 'hook' is -** always checked before being called (see 'luaD_hook'). -*/ -LUA_API void lua_sethook (lua_State *L, lua_Hook func, int mask, int count) { - if (func == NULL || mask == 0) { /* turn off hooks? */ - mask = 0; - func = NULL; - } - if (isLua(L->ci)) - L->oldpc = L->ci->u.l.savedpc; - L->hook = func; - L->basehookcount = count; - resethookcount(L); - L->hookmask = cast_byte(mask); -} - - -LUA_API lua_Hook lua_gethook (lua_State *L) { - return L->hook; -} - - -LUA_API int lua_gethookmask (lua_State *L) { - return L->hookmask; -} - - -LUA_API int lua_gethookcount (lua_State *L) { - return L->basehookcount; -} - - -LUA_API int lua_getstack (lua_State *L, int level, lua_Debug *ar) { - int status; - CallInfo *ci; - if (level < 0) return 0; /* invalid (negative) level */ - lua_lock(L); - for (ci = L->ci; level > 0 && ci != &L->base_ci; ci = ci->previous) - level--; - if (level == 0 && ci != &L->base_ci) { /* level found? */ - status = 1; - ar->i_ci = ci; - } - else status = 0; /* no such level */ - lua_unlock(L); - return status; -} - - -static const char *upvalname (Proto *p, int uv) { - TString *s = check_exp(uv < p->sizeupvalues, p->upvalues[uv].name); - if (s == NULL) return "?"; - else return getstr(s); -} - - -static const char *findvararg (CallInfo *ci, int n, StkId *pos) { - int nparams = clLvalue(ci->func)->p->numparams; - int nvararg = cast_int(ci->u.l.base - ci->func) - nparams; - if (n <= -nvararg) - return NULL; /* no such vararg */ - else { - *pos = ci->func + nparams - n; - return "(*vararg)"; /* generic name for any vararg */ - } -} - - -static const char *findlocal (lua_State *L, CallInfo *ci, int n, - StkId *pos) { - const char *name = NULL; - StkId base; - if (isLua(ci)) { - if (n < 0) /* access to vararg values? */ - return findvararg(ci, n, pos); - else { - base = ci->u.l.base; - name = luaF_getlocalname(ci_func(ci)->p, n, currentpc(ci)); - } - } - else - base = ci->func + 1; - if (name == NULL) { /* no 'standard' name? */ - StkId limit = (ci == L->ci) ? L->top : ci->next->func; - if (limit - base >= n && n > 0) /* is 'n' inside 'ci' stack? */ - name = "(*temporary)"; /* generic name for any valid slot */ - else - return NULL; /* no name */ - } - *pos = base + (n - 1); - return name; -} - - -LUA_API const char *lua_getlocal (lua_State *L, const lua_Debug *ar, int n) { - const char *name; - lua_lock(L); - swapextra(L); - if (ar == NULL) { /* information about non-active function? */ - if (!isLfunction(L->top - 1)) /* not a Lua function? */ - name = NULL; - else /* consider live variables at function start (parameters) */ - name = luaF_getlocalname(clLvalue(L->top - 1)->p, n, 0); - } - else { /* active function; get information through 'ar' */ - StkId pos = NULL; /* to avoid warnings */ - name = findlocal(L, ar->i_ci, n, &pos); - if (name) { - setobj2s(L, L->top, pos); - api_incr_top(L); - } - } - swapextra(L); - lua_unlock(L); - return name; -} - - -LUA_API const char *lua_setlocal (lua_State *L, const lua_Debug *ar, int n) { - StkId pos = NULL; /* to avoid warnings */ - const char *name; - lua_lock(L); - swapextra(L); - name = findlocal(L, ar->i_ci, n, &pos); - if (name) { - setobjs2s(L, pos, L->top - 1); - L->top--; /* pop value */ - } - swapextra(L); - lua_unlock(L); - return name; -} - - -static void funcinfo (lua_Debug *ar, Closure *cl) { - if (noLuaClosure(cl)) { - ar->source = "=[C]"; - ar->linedefined = -1; - ar->lastlinedefined = -1; - ar->what = "C"; - } - else { - Proto *p = cl->l.p; - ar->source = p->source ? getstr(p->source) : "=?"; - ar->linedefined = p->linedefined; - ar->lastlinedefined = p->lastlinedefined; - ar->what = (ar->linedefined == 0) ? "main" : "Lua"; - } - luaO_chunkid(ar->short_src, ar->source, LUA_IDSIZE); -} - - -static void collectvalidlines (lua_State *L, Closure *f) { - if (noLuaClosure(f)) { - setnilvalue(L->top); - api_incr_top(L); - } - else { - int i; - TValue v; - int *lineinfo = f->l.p->lineinfo; - Table *t = luaH_new(L); /* new table to store active lines */ - sethvalue(L, L->top, t); /* push it on stack */ - api_incr_top(L); - setbvalue(&v, 1); /* boolean 'true' to be the value of all indices */ - for (i = 0; i < f->l.p->sizelineinfo; i++) /* for all lines with code */ - luaH_setint(L, t, lineinfo[i], &v); /* table[line] = true */ - } -} - - -static const char *getfuncname (lua_State *L, CallInfo *ci, const char **name) { - if (ci == NULL) /* no 'ci'? */ - return NULL; /* no info */ - else if (ci->callstatus & CIST_FIN) { /* is this a finalizer? */ - *name = "__gc"; - return "metamethod"; /* report it as such */ - } - /* calling function is a known Lua function? */ - else if (!(ci->callstatus & CIST_TAIL) && isLua(ci->previous)) - return funcnamefromcode(L, ci->previous, name); - else return NULL; /* no way to find a name */ -} - - -static int auxgetinfo (lua_State *L, const char *what, lua_Debug *ar, - Closure *f, CallInfo *ci) { - int status = 1; - for (; *what; what++) { - switch (*what) { - case 'S': { - funcinfo(ar, f); - break; - } - case 'l': { - ar->currentline = (ci && isLua(ci)) ? currentline(ci) : -1; - break; - } - case 'u': { - ar->nups = (f == NULL) ? 0 : f->c.nupvalues; - if (noLuaClosure(f)) { - ar->isvararg = 1; - ar->nparams = 0; - } - else { - ar->isvararg = f->l.p->is_vararg; - ar->nparams = f->l.p->numparams; - } - break; - } - case 't': { - ar->istailcall = (ci) ? ci->callstatus & CIST_TAIL : 0; - break; - } - case 'n': { - ar->namewhat = getfuncname(L, ci, &ar->name); - if (ar->namewhat == NULL) { - ar->namewhat = ""; /* not found */ - ar->name = NULL; - } - break; - } - case 'L': - case 'f': /* handled by lua_getinfo */ - break; - default: status = 0; /* invalid option */ - } - } - return status; -} - - -LUA_API int lua_getinfo (lua_State *L, const char *what, lua_Debug *ar) { - int status; - Closure *cl; - CallInfo *ci; - StkId func; - lua_lock(L); - swapextra(L); - if (*what == '>') { - ci = NULL; - func = L->top - 1; - api_check(L, ttisfunction(func), "function expected"); - what++; /* skip the '>' */ - L->top--; /* pop function */ - } - else { - ci = ar->i_ci; - func = ci->func; - lua_assert(ttisfunction(ci->func)); - } - cl = ttisclosure(func) ? clvalue(func) : NULL; - status = auxgetinfo(L, what, ar, cl, ci); - if (strchr(what, 'f')) { - setobjs2s(L, L->top, func); - api_incr_top(L); - } - swapextra(L); /* correct before option 'L', which can raise a mem. error */ - if (strchr(what, 'L')) - collectvalidlines(L, cl); - lua_unlock(L); - return status; -} - - -/* -** {====================================================== -** Symbolic Execution -** ======================================================= -*/ - -static const char *getobjname (Proto *p, int lastpc, int reg, - const char **name); - - -/* -** find a "name" for the RK value 'c' -*/ -static void kname (Proto *p, int pc, int c, const char **name) { - if (ISK(c)) { /* is 'c' a constant? */ - TValue *kvalue = &p->k[INDEXK(c)]; - if (ttisstring(kvalue)) { /* literal constant? */ - *name = svalue(kvalue); /* it is its own name */ - return; - } - /* else no reasonable name found */ - } - else { /* 'c' is a register */ - const char *what = getobjname(p, pc, c, name); /* search for 'c' */ - if (what && *what == 'c') { /* found a constant name? */ - return; /* 'name' already filled */ - } - /* else no reasonable name found */ - } - *name = "?"; /* no reasonable name found */ -} - - -static int filterpc (int pc, int jmptarget) { - if (pc < jmptarget) /* is code conditional (inside a jump)? */ - return -1; /* cannot know who sets that register */ - else return pc; /* current position sets that register */ -} - - -/* -** try to find last instruction before 'lastpc' that modified register 'reg' -*/ -static int findsetreg (Proto *p, int lastpc, int reg) { - int pc; - int setreg = -1; /* keep last instruction that changed 'reg' */ - int jmptarget = 0; /* any code before this address is conditional */ - for (pc = 0; pc < lastpc; pc++) { - Instruction i = p->code[pc]; - OpCode op = GET_OPCODE(i); - int a = GETARG_A(i); - switch (op) { - case OP_LOADNIL: { - int b = GETARG_B(i); - if (a <= reg && reg <= a + b) /* set registers from 'a' to 'a+b' */ - setreg = filterpc(pc, jmptarget); - break; - } - case OP_TFORCALL: { - if (reg >= a + 2) /* affect all regs above its base */ - setreg = filterpc(pc, jmptarget); - break; - } - case OP_CALL: - case OP_TAILCALL: { - if (reg >= a) /* affect all registers above base */ - setreg = filterpc(pc, jmptarget); - break; - } - case OP_JMP: { - int b = GETARG_sBx(i); - int dest = pc + 1 + b; - /* jump is forward and do not skip 'lastpc'? */ - if (pc < dest && dest <= lastpc) { - if (dest > jmptarget) - jmptarget = dest; /* update 'jmptarget' */ - } - break; - } - default: - if (testAMode(op) && reg == a) /* any instruction that set A */ - setreg = filterpc(pc, jmptarget); - break; - } - } - return setreg; -} - - -static const char *getobjname (Proto *p, int lastpc, int reg, - const char **name) { - int pc; - *name = luaF_getlocalname(p, reg + 1, lastpc); - if (*name) /* is a local? */ - return "local"; - /* else try symbolic execution */ - pc = findsetreg(p, lastpc, reg); - if (pc != -1) { /* could find instruction? */ - Instruction i = p->code[pc]; - OpCode op = GET_OPCODE(i); - switch (op) { - case OP_MOVE: { - int b = GETARG_B(i); /* move from 'b' to 'a' */ - if (b < GETARG_A(i)) - return getobjname(p, pc, b, name); /* get name for 'b' */ - break; - } - case OP_GETTABUP: - case OP_GETTABLE: { - int k = GETARG_C(i); /* key index */ - int t = GETARG_B(i); /* table index */ - const char *vn = (op == OP_GETTABLE) /* name of indexed variable */ - ? luaF_getlocalname(p, t + 1, pc) - : upvalname(p, t); - kname(p, pc, k, name); - return (vn && strcmp(vn, LUA_ENV) == 0) ? "global" : "field"; - } - case OP_GETUPVAL: { - *name = upvalname(p, GETARG_B(i)); - return "upvalue"; - } - case OP_LOADK: - case OP_LOADKX: { - int b = (op == OP_LOADK) ? GETARG_Bx(i) - : GETARG_Ax(p->code[pc + 1]); - if (ttisstring(&p->k[b])) { - *name = svalue(&p->k[b]); - return "constant"; - } - break; - } - case OP_SELF: { - int k = GETARG_C(i); /* key index */ - kname(p, pc, k, name); - return "method"; - } - default: break; /* go through to return NULL */ - } - } - return NULL; /* could not find reasonable name */ -} - - -/* -** Try to find a name for a function based on the code that called it. -** (Only works when function was called by a Lua function.) -** Returns what the name is (e.g., "for iterator", "method", -** "metamethod") and sets '*name' to point to the name. -*/ -static const char *funcnamefromcode (lua_State *L, CallInfo *ci, - const char **name) { - TMS tm = (TMS)0; /* (initial value avoids warnings) */ - Proto *p = ci_func(ci)->p; /* calling function */ - int pc = currentpc(ci); /* calling instruction index */ - Instruction i = p->code[pc]; /* calling instruction */ - if (ci->callstatus & CIST_HOOKED) { /* was it called inside a hook? */ - *name = "?"; - return "hook"; - } - switch (GET_OPCODE(i)) { - case OP_CALL: - case OP_TAILCALL: - return getobjname(p, pc, GETARG_A(i), name); /* get function name */ - case OP_TFORCALL: { /* for iterator */ - *name = "for iterator"; - return "for iterator"; - } - /* other instructions can do calls through metamethods */ - case OP_SELF: case OP_GETTABUP: case OP_GETTABLE: - tm = TM_INDEX; - break; - case OP_SETTABUP: case OP_SETTABLE: - tm = TM_NEWINDEX; - break; - case OP_ADD: case OP_SUB: case OP_MUL: case OP_MOD: - case OP_POW: case OP_DIV: case OP_IDIV: case OP_BAND: - case OP_BOR: case OP_BXOR: case OP_SHL: case OP_SHR: { - int offset = cast_int(GET_OPCODE(i)) - cast_int(OP_ADD); /* ORDER OP */ - tm = cast(TMS, offset + cast_int(TM_ADD)); /* ORDER TM */ - break; - } - case OP_UNM: tm = TM_UNM; break; - case OP_BNOT: tm = TM_BNOT; break; - case OP_LEN: tm = TM_LEN; break; - case OP_CONCAT: tm = TM_CONCAT; break; - case OP_EQ: tm = TM_EQ; break; - case OP_LT: tm = TM_LT; break; - case OP_LE: tm = TM_LE; break; - default: - return NULL; /* cannot find a reasonable name */ - } - *name = getstr(G(L)->tmname[tm]); - return "metamethod"; -} - -/* }====================================================== */ - - - -/* -** The subtraction of two potentially unrelated pointers is -** not ISO C, but it should not crash a program; the subsequent -** checks are ISO C and ensure a correct result. -*/ -static int isinstack (CallInfo *ci, const TValue *o) { - ptrdiff_t i = o - ci->u.l.base; - return (0 <= i && i < (ci->top - ci->u.l.base) && ci->u.l.base + i == o); -} - - -/* -** Checks whether value 'o' came from an upvalue. (That can only happen -** with instructions OP_GETTABUP/OP_SETTABUP, which operate directly on -** upvalues.) -*/ -static const char *getupvalname (CallInfo *ci, const TValue *o, - const char **name) { - LClosure *c = ci_func(ci); - int i; - for (i = 0; i < c->nupvalues; i++) { - if (c->upvals[i]->v == o) { - *name = upvalname(c->p, i); - return "upvalue"; - } - } - return NULL; -} - - -static const char *varinfo (lua_State *L, const TValue *o) { - const char *name = NULL; /* to avoid warnings */ - CallInfo *ci = L->ci; - const char *kind = NULL; - if (isLua(ci)) { - kind = getupvalname(ci, o, &name); /* check whether 'o' is an upvalue */ - if (!kind && isinstack(ci, o)) /* no? try a register */ - kind = getobjname(ci_func(ci)->p, currentpc(ci), - cast_int(o - ci->u.l.base), &name); - } - return (kind) ? luaO_pushfstring(L, " (%s '%s')", kind, name) : ""; -} - - -l_noret luaG_typeerror (lua_State *L, const TValue *o, const char *op) { - const char *t = luaT_objtypename(L, o); - luaG_runerror(L, "attempt to %s a %s value%s", op, t, varinfo(L, o)); -} - - -l_noret luaG_concaterror (lua_State *L, const TValue *p1, const TValue *p2) { - if (ttisstring(p1) || cvt2str(p1)) p1 = p2; - luaG_typeerror(L, p1, "concatenate"); -} - - -l_noret luaG_opinterror (lua_State *L, const TValue *p1, - const TValue *p2, const char *msg) { - lua_Number temp; - if (!tonumber(p1, &temp)) /* first operand is wrong? */ - p2 = p1; /* now second is wrong */ - luaG_typeerror(L, p2, msg); -} - - -/* -** Error when both values are convertible to numbers, but not to integers -*/ -l_noret luaG_tointerror (lua_State *L, const TValue *p1, const TValue *p2) { - lua_Integer temp; - if (!tointeger(p1, &temp)) - p2 = p1; - luaG_runerror(L, "number%s has no integer representation", varinfo(L, p2)); -} - - -l_noret luaG_ordererror (lua_State *L, const TValue *p1, const TValue *p2) { - const char *t1 = luaT_objtypename(L, p1); - const char *t2 = luaT_objtypename(L, p2); - if (strcmp(t1, t2) == 0) - luaG_runerror(L, "attempt to compare two %s values", t1); - else - luaG_runerror(L, "attempt to compare %s with %s", t1, t2); -} - - -/* add src:line information to 'msg' */ -const char *luaG_addinfo (lua_State *L, const char *msg, TString *src, - int line) { - char buff[LUA_IDSIZE]; - if (src) - luaO_chunkid(buff, getstr(src), LUA_IDSIZE); - else { /* no source available; use "?" instead */ - buff[0] = '?'; buff[1] = '\0'; - } - return luaO_pushfstring(L, "%s:%d: %s", buff, line, msg); -} - - -l_noret luaG_errormsg (lua_State *L) { - if (L->errfunc != 0) { /* is there an error handling function? */ - StkId errfunc = restorestack(L, L->errfunc); - setobjs2s(L, L->top, L->top - 1); /* move argument */ - setobjs2s(L, L->top - 1, errfunc); /* push function */ - L->top++; /* assume EXTRA_STACK */ - luaD_callnoyield(L, L->top - 2, 1); /* call it */ - } - luaD_throw(L, LUA_ERRRUN); -} - - -l_noret luaG_runerror (lua_State *L, const char *fmt, ...) { - CallInfo *ci = L->ci; - const char *msg; - va_list argp; - luaC_checkGC(L); /* error message uses memory */ - va_start(argp, fmt); - msg = luaO_pushvfstring(L, fmt, argp); /* format message */ - va_end(argp); - if (isLua(ci)) /* if Lua function, add source:line information */ - luaG_addinfo(L, msg, ci_func(ci)->p->source, currentline(ci)); - luaG_errormsg(L); -} - - -void luaG_traceexec (lua_State *L) { - CallInfo *ci = L->ci; - lu_byte mask = L->hookmask; - int counthook = (--L->hookcount == 0 && (mask & LUA_MASKCOUNT)); - if (counthook) - resethookcount(L); /* reset count */ - else if (!(mask & LUA_MASKLINE)) - return; /* no line hook and count != 0; nothing to be done */ - if (ci->callstatus & CIST_HOOKYIELD) { /* called hook last time? */ - ci->callstatus &= ~CIST_HOOKYIELD; /* erase mark */ - return; /* do not call hook again (VM yielded, so it did not move) */ - } - if (counthook) - luaD_hook(L, LUA_HOOKCOUNT, -1); /* call count hook */ - if (mask & LUA_MASKLINE) { - Proto *p = ci_func(ci)->p; - int npc = pcRel(ci->u.l.savedpc, p); - int newline = getfuncline(p, npc); - if (npc == 0 || /* call linehook when enter a new function, */ - ci->u.l.savedpc <= L->oldpc || /* when jump back (loop), or when */ - newline != getfuncline(p, pcRel(L->oldpc, p))) /* enter a new line */ - luaD_hook(L, LUA_HOOKLINE, newline); /* call line hook */ - } - L->oldpc = ci->u.l.savedpc; - if (L->status == LUA_YIELD) { /* did hook yield? */ - if (counthook) - L->hookcount = 1; /* undo decrement to zero */ - ci->u.l.savedpc--; /* undo increment (resume will increment it again) */ - ci->callstatus |= CIST_HOOKYIELD; /* mark that it yielded */ - ci->func = L->top - 1; /* protect stack below results */ - luaD_throw(L, LUA_YIELD); - } -} - diff --git a/lib/lua-5.3/src/ldebug.h b/lib/lua-5.3/src/ldebug.h deleted file mode 100644 index 8cea0ee..0000000 --- a/lib/lua-5.3/src/ldebug.h +++ /dev/null @@ -1,39 +0,0 @@ -/* -** $Id: ldebug.h,v 2.14.1.1 2017/04/19 17:20:42 roberto Exp $ -** Auxiliary functions from Debug Interface module -** See Copyright Notice in lua.h -*/ - -#ifndef ldebug_h -#define ldebug_h - - -#include "lstate.h" - - -#define pcRel(pc, p) (cast(int, (pc) - (p)->code) - 1) - -#define getfuncline(f,pc) (((f)->lineinfo) ? (f)->lineinfo[pc] : -1) - -#define resethookcount(L) (L->hookcount = L->basehookcount) - - -LUAI_FUNC l_noret luaG_typeerror (lua_State *L, const TValue *o, - const char *opname); -LUAI_FUNC l_noret luaG_concaterror (lua_State *L, const TValue *p1, - const TValue *p2); -LUAI_FUNC l_noret luaG_opinterror (lua_State *L, const TValue *p1, - const TValue *p2, - const char *msg); -LUAI_FUNC l_noret luaG_tointerror (lua_State *L, const TValue *p1, - const TValue *p2); -LUAI_FUNC l_noret luaG_ordererror (lua_State *L, const TValue *p1, - const TValue *p2); -LUAI_FUNC l_noret luaG_runerror (lua_State *L, const char *fmt, ...); -LUAI_FUNC const char *luaG_addinfo (lua_State *L, const char *msg, - TString *src, int line); -LUAI_FUNC l_noret luaG_errormsg (lua_State *L); -LUAI_FUNC void luaG_traceexec (lua_State *L); - - -#endif diff --git a/lib/lua-5.3/src/ldo.c b/lib/lua-5.3/src/ldo.c deleted file mode 100644 index 316e45c..0000000 --- a/lib/lua-5.3/src/ldo.c +++ /dev/null @@ -1,802 +0,0 @@ -/* -** $Id: ldo.c,v 2.157.1.1 2017/04/19 17:20:42 roberto Exp $ -** Stack and Call structure of Lua -** See Copyright Notice in lua.h -*/ - -#define ldo_c -#define LUA_CORE - -#include "lprefix.h" - - -#include -#include -#include - -#include "lua.h" - -#include "lapi.h" -#include "ldebug.h" -#include "ldo.h" -#include "lfunc.h" -#include "lgc.h" -#include "lmem.h" -#include "lobject.h" -#include "lopcodes.h" -#include "lparser.h" -#include "lstate.h" -#include "lstring.h" -#include "ltable.h" -#include "ltm.h" -#include "lundump.h" -#include "lvm.h" -#include "lzio.h" - - - -#define errorstatus(s) ((s) > LUA_YIELD) - - -/* -** {====================================================== -** Error-recovery functions -** ======================================================= -*/ - -/* -** LUAI_THROW/LUAI_TRY define how Lua does exception handling. By -** default, Lua handles errors with exceptions when compiling as -** C++ code, with _longjmp/_setjmp when asked to use them, and with -** longjmp/setjmp otherwise. -*/ -#if !defined(LUAI_THROW) /* { */ - -#if defined(__cplusplus) && !defined(LUA_USE_LONGJMP) /* { */ - -/* C++ exceptions */ -#define LUAI_THROW(L,c) throw(c) -#define LUAI_TRY(L,c,a) \ - try { a } catch(...) { if ((c)->status == 0) (c)->status = -1; } -#define luai_jmpbuf int /* dummy variable */ - -#elif defined(LUA_USE_POSIX) /* }{ */ - -/* in POSIX, try _longjmp/_setjmp (more efficient) */ -#define LUAI_THROW(L,c) _longjmp((c)->b, 1) -#define LUAI_TRY(L,c,a) if (_setjmp((c)->b) == 0) { a } -#define luai_jmpbuf jmp_buf - -#else /* }{ */ - -/* ISO C handling with long jumps */ -#define LUAI_THROW(L,c) longjmp((c)->b, 1) -#define LUAI_TRY(L,c,a) if (setjmp((c)->b) == 0) { a } -#define luai_jmpbuf jmp_buf - -#endif /* } */ - -#endif /* } */ - - - -/* chain list of long jump buffers */ -struct lua_longjmp { - struct lua_longjmp *previous; - luai_jmpbuf b; - volatile int status; /* error code */ -}; - - -static void seterrorobj (lua_State *L, int errcode, StkId oldtop) { - switch (errcode) { - case LUA_ERRMEM: { /* memory error? */ - setsvalue2s(L, oldtop, G(L)->memerrmsg); /* reuse preregistered msg. */ - break; - } - case LUA_ERRERR: { - setsvalue2s(L, oldtop, luaS_newliteral(L, "error in error handling")); - break; - } - default: { - setobjs2s(L, oldtop, L->top - 1); /* error message on current top */ - break; - } - } - L->top = oldtop + 1; -} - - -l_noret luaD_throw (lua_State *L, int errcode) { - if (L->errorJmp) { /* thread has an error handler? */ - L->errorJmp->status = errcode; /* set status */ - LUAI_THROW(L, L->errorJmp); /* jump to it */ - } - else { /* thread has no error handler */ - global_State *g = G(L); - L->status = cast_byte(errcode); /* mark it as dead */ - if (g->mainthread->errorJmp) { /* main thread has a handler? */ - setobjs2s(L, g->mainthread->top++, L->top - 1); /* copy error obj. */ - luaD_throw(g->mainthread, errcode); /* re-throw in main thread */ - } - else { /* no handler at all; abort */ - if (g->panic) { /* panic function? */ - seterrorobj(L, errcode, L->top); /* assume EXTRA_STACK */ - if (L->ci->top < L->top) - L->ci->top = L->top; /* pushing msg. can break this invariant */ - lua_unlock(L); - g->panic(L); /* call panic function (last chance to jump out) */ - } - abort(); - } - } -} - - -int luaD_rawrunprotected (lua_State *L, Pfunc f, void *ud) { - unsigned short oldnCcalls = L->nCcalls; - struct lua_longjmp lj; - lj.status = LUA_OK; - lj.previous = L->errorJmp; /* chain new error handler */ - L->errorJmp = &lj; - LUAI_TRY(L, &lj, - (*f)(L, ud); - ); - L->errorJmp = lj.previous; /* restore old error handler */ - L->nCcalls = oldnCcalls; - return lj.status; -} - -/* }====================================================== */ - - -/* -** {================================================================== -** Stack reallocation -** =================================================================== -*/ -static void correctstack (lua_State *L, TValue *oldstack) { - CallInfo *ci; - UpVal *up; - L->top = (L->top - oldstack) + L->stack; - for (up = L->openupval; up != NULL; up = up->u.open.next) - up->v = (up->v - oldstack) + L->stack; - for (ci = L->ci; ci != NULL; ci = ci->previous) { - ci->top = (ci->top - oldstack) + L->stack; - ci->func = (ci->func - oldstack) + L->stack; - if (isLua(ci)) - ci->u.l.base = (ci->u.l.base - oldstack) + L->stack; - } -} - - -/* some space for error handling */ -#define ERRORSTACKSIZE (LUAI_MAXSTACK + 200) - - -void luaD_reallocstack (lua_State *L, int newsize) { - TValue *oldstack = L->stack; - int lim = L->stacksize; - lua_assert(newsize <= LUAI_MAXSTACK || newsize == ERRORSTACKSIZE); - lua_assert(L->stack_last - L->stack == L->stacksize - EXTRA_STACK); - luaM_reallocvector(L, L->stack, L->stacksize, newsize, TValue); - for (; lim < newsize; lim++) - setnilvalue(L->stack + lim); /* erase new segment */ - L->stacksize = newsize; - L->stack_last = L->stack + newsize - EXTRA_STACK; - correctstack(L, oldstack); -} - - -void luaD_growstack (lua_State *L, int n) { - int size = L->stacksize; - if (size > LUAI_MAXSTACK) /* error after extra size? */ - luaD_throw(L, LUA_ERRERR); - else { - int needed = cast_int(L->top - L->stack) + n + EXTRA_STACK; - int newsize = 2 * size; - if (newsize > LUAI_MAXSTACK) newsize = LUAI_MAXSTACK; - if (newsize < needed) newsize = needed; - if (newsize > LUAI_MAXSTACK) { /* stack overflow? */ - luaD_reallocstack(L, ERRORSTACKSIZE); - luaG_runerror(L, "stack overflow"); - } - else - luaD_reallocstack(L, newsize); - } -} - - -static int stackinuse (lua_State *L) { - CallInfo *ci; - StkId lim = L->top; - for (ci = L->ci; ci != NULL; ci = ci->previous) { - if (lim < ci->top) lim = ci->top; - } - lua_assert(lim <= L->stack_last); - return cast_int(lim - L->stack) + 1; /* part of stack in use */ -} - - -void luaD_shrinkstack (lua_State *L) { - int inuse = stackinuse(L); - int goodsize = inuse + (inuse / 8) + 2*EXTRA_STACK; - if (goodsize > LUAI_MAXSTACK) - goodsize = LUAI_MAXSTACK; /* respect stack limit */ - if (L->stacksize > LUAI_MAXSTACK) /* had been handling stack overflow? */ - luaE_freeCI(L); /* free all CIs (list grew because of an error) */ - else - luaE_shrinkCI(L); /* shrink list */ - /* if thread is currently not handling a stack overflow and its - good size is smaller than current size, shrink its stack */ - if (inuse <= (LUAI_MAXSTACK - EXTRA_STACK) && - goodsize < L->stacksize) - luaD_reallocstack(L, goodsize); - else /* don't change stack */ - condmovestack(L,{},{}); /* (change only for debugging) */ -} - - -void luaD_inctop (lua_State *L) { - luaD_checkstack(L, 1); - L->top++; -} - -/* }================================================================== */ - - -/* -** Call a hook for the given event. Make sure there is a hook to be -** called. (Both 'L->hook' and 'L->hookmask', which triggers this -** function, can be changed asynchronously by signals.) -*/ -void luaD_hook (lua_State *L, int event, int line) { - lua_Hook hook = L->hook; - if (hook && L->allowhook) { /* make sure there is a hook */ - CallInfo *ci = L->ci; - ptrdiff_t top = savestack(L, L->top); - ptrdiff_t ci_top = savestack(L, ci->top); - lua_Debug ar; - ar.event = event; - ar.currentline = line; - ar.i_ci = ci; - luaD_checkstack(L, LUA_MINSTACK); /* ensure minimum stack size */ - ci->top = L->top + LUA_MINSTACK; - lua_assert(ci->top <= L->stack_last); - L->allowhook = 0; /* cannot call hooks inside a hook */ - ci->callstatus |= CIST_HOOKED; - lua_unlock(L); - (*hook)(L, &ar); - lua_lock(L); - lua_assert(!L->allowhook); - L->allowhook = 1; - ci->top = restorestack(L, ci_top); - L->top = restorestack(L, top); - ci->callstatus &= ~CIST_HOOKED; - } -} - - -static void callhook (lua_State *L, CallInfo *ci) { - int hook = LUA_HOOKCALL; - ci->u.l.savedpc++; /* hooks assume 'pc' is already incremented */ - if (isLua(ci->previous) && - GET_OPCODE(*(ci->previous->u.l.savedpc - 1)) == OP_TAILCALL) { - ci->callstatus |= CIST_TAIL; - hook = LUA_HOOKTAILCALL; - } - luaD_hook(L, hook, -1); - ci->u.l.savedpc--; /* correct 'pc' */ -} - - -static StkId adjust_varargs (lua_State *L, Proto *p, int actual) { - int i; - int nfixargs = p->numparams; - StkId base, fixed; - /* move fixed parameters to final position */ - fixed = L->top - actual; /* first fixed argument */ - base = L->top; /* final position of first argument */ - for (i = 0; i < nfixargs && i < actual; i++) { - setobjs2s(L, L->top++, fixed + i); - setnilvalue(fixed + i); /* erase original copy (for GC) */ - } - for (; i < nfixargs; i++) - setnilvalue(L->top++); /* complete missing arguments */ - return base; -} - - -/* -** Check whether __call metafield of 'func' is a function. If so, put -** it in stack below original 'func' so that 'luaD_precall' can call -** it. Raise an error if __call metafield is not a function. -*/ -static void tryfuncTM (lua_State *L, StkId func) { - const TValue *tm = luaT_gettmbyobj(L, func, TM_CALL); - StkId p; - if (!ttisfunction(tm)) - luaG_typeerror(L, func, "call"); - /* Open a hole inside the stack at 'func' */ - for (p = L->top; p > func; p--) - setobjs2s(L, p, p-1); - L->top++; /* slot ensured by caller */ - setobj2s(L, func, tm); /* tag method is the new function to be called */ -} - - -/* -** Given 'nres' results at 'firstResult', move 'wanted' of them to 'res'. -** Handle most typical cases (zero results for commands, one result for -** expressions, multiple results for tail calls/single parameters) -** separated. -*/ -static int moveresults (lua_State *L, const TValue *firstResult, StkId res, - int nres, int wanted) { - switch (wanted) { /* handle typical cases separately */ - case 0: break; /* nothing to move */ - case 1: { /* one result needed */ - if (nres == 0) /* no results? */ - firstResult = luaO_nilobject; /* adjust with nil */ - setobjs2s(L, res, firstResult); /* move it to proper place */ - break; - } - case LUA_MULTRET: { - int i; - for (i = 0; i < nres; i++) /* move all results to correct place */ - setobjs2s(L, res + i, firstResult + i); - L->top = res + nres; - return 0; /* wanted == LUA_MULTRET */ - } - default: { - int i; - if (wanted <= nres) { /* enough results? */ - for (i = 0; i < wanted; i++) /* move wanted results to correct place */ - setobjs2s(L, res + i, firstResult + i); - } - else { /* not enough results; use all of them plus nils */ - for (i = 0; i < nres; i++) /* move all results to correct place */ - setobjs2s(L, res + i, firstResult + i); - for (; i < wanted; i++) /* complete wanted number of results */ - setnilvalue(res + i); - } - break; - } - } - L->top = res + wanted; /* top points after the last result */ - return 1; -} - - -/* -** Finishes a function call: calls hook if necessary, removes CallInfo, -** moves current number of results to proper place; returns 0 iff call -** wanted multiple (variable number of) results. -*/ -int luaD_poscall (lua_State *L, CallInfo *ci, StkId firstResult, int nres) { - StkId res; - int wanted = ci->nresults; - if (L->hookmask & (LUA_MASKRET | LUA_MASKLINE)) { - if (L->hookmask & LUA_MASKRET) { - ptrdiff_t fr = savestack(L, firstResult); /* hook may change stack */ - luaD_hook(L, LUA_HOOKRET, -1); - firstResult = restorestack(L, fr); - } - L->oldpc = ci->previous->u.l.savedpc; /* 'oldpc' for caller function */ - } - res = ci->func; /* res == final position of 1st result */ - L->ci = ci->previous; /* back to caller */ - /* move results to proper place */ - return moveresults(L, firstResult, res, nres, wanted); -} - - - -#define next_ci(L) (L->ci = (L->ci->next ? L->ci->next : luaE_extendCI(L))) - - -/* macro to check stack size, preserving 'p' */ -#define checkstackp(L,n,p) \ - luaD_checkstackaux(L, n, \ - ptrdiff_t t__ = savestack(L, p); /* save 'p' */ \ - luaC_checkGC(L), /* stack grow uses memory */ \ - p = restorestack(L, t__)) /* 'pos' part: restore 'p' */ - - -/* -** Prepares a function call: checks the stack, creates a new CallInfo -** entry, fills in the relevant information, calls hook if needed. -** If function is a C function, does the call, too. (Otherwise, leave -** the execution ('luaV_execute') to the caller, to allow stackless -** calls.) Returns true iff function has been executed (C function). -*/ -int luaD_precall (lua_State *L, StkId func, int nresults) { - lua_CFunction f; - CallInfo *ci; - switch (ttype(func)) { - case LUA_TCCL: /* C closure */ - f = clCvalue(func)->f; - goto Cfunc; - case LUA_TLCF: /* light C function */ - f = fvalue(func); - Cfunc: { - int n; /* number of returns */ - checkstackp(L, LUA_MINSTACK, func); /* ensure minimum stack size */ - ci = next_ci(L); /* now 'enter' new function */ - ci->nresults = nresults; - ci->func = func; - ci->top = L->top + LUA_MINSTACK; - lua_assert(ci->top <= L->stack_last); - ci->callstatus = 0; - if (L->hookmask & LUA_MASKCALL) - luaD_hook(L, LUA_HOOKCALL, -1); - lua_unlock(L); - n = (*f)(L); /* do the actual call */ - lua_lock(L); - api_checknelems(L, n); - luaD_poscall(L, ci, L->top - n, n); - return 1; - } - case LUA_TLCL: { /* Lua function: prepare its call */ - StkId base; - Proto *p = clLvalue(func)->p; - int n = cast_int(L->top - func) - 1; /* number of real arguments */ - int fsize = p->maxstacksize; /* frame size */ - checkstackp(L, fsize, func); - if (p->is_vararg) - base = adjust_varargs(L, p, n); - else { /* non vararg function */ - for (; n < p->numparams; n++) - setnilvalue(L->top++); /* complete missing arguments */ - base = func + 1; - } - ci = next_ci(L); /* now 'enter' new function */ - ci->nresults = nresults; - ci->func = func; - ci->u.l.base = base; - L->top = ci->top = base + fsize; - lua_assert(ci->top <= L->stack_last); - ci->u.l.savedpc = p->code; /* starting point */ - ci->callstatus = CIST_LUA; - if (L->hookmask & LUA_MASKCALL) - callhook(L, ci); - return 0; - } - default: { /* not a function */ - checkstackp(L, 1, func); /* ensure space for metamethod */ - tryfuncTM(L, func); /* try to get '__call' metamethod */ - return luaD_precall(L, func, nresults); /* now it must be a function */ - } - } -} - - -/* -** Check appropriate error for stack overflow ("regular" overflow or -** overflow while handling stack overflow). If 'nCalls' is larger than -** LUAI_MAXCCALLS (which means it is handling a "regular" overflow) but -** smaller than 9/8 of LUAI_MAXCCALLS, does not report an error (to -** allow overflow handling to work) -*/ -static void stackerror (lua_State *L) { - if (L->nCcalls == LUAI_MAXCCALLS) - luaG_runerror(L, "C stack overflow"); - else if (L->nCcalls >= (LUAI_MAXCCALLS + (LUAI_MAXCCALLS>>3))) - luaD_throw(L, LUA_ERRERR); /* error while handing stack error */ -} - - -/* -** Call a function (C or Lua). The function to be called is at *func. -** The arguments are on the stack, right after the function. -** When returns, all the results are on the stack, starting at the original -** function position. -*/ -void luaD_call (lua_State *L, StkId func, int nResults) { - if (++L->nCcalls >= LUAI_MAXCCALLS) - stackerror(L); - if (!luaD_precall(L, func, nResults)) /* is a Lua function? */ - luaV_execute(L); /* call it */ - L->nCcalls--; -} - - -/* -** Similar to 'luaD_call', but does not allow yields during the call -*/ -void luaD_callnoyield (lua_State *L, StkId func, int nResults) { - L->nny++; - luaD_call(L, func, nResults); - L->nny--; -} - - -/* -** Completes the execution of an interrupted C function, calling its -** continuation function. -*/ -static void finishCcall (lua_State *L, int status) { - CallInfo *ci = L->ci; - int n; - /* must have a continuation and must be able to call it */ - lua_assert(ci->u.c.k != NULL && L->nny == 0); - /* error status can only happen in a protected call */ - lua_assert((ci->callstatus & CIST_YPCALL) || status == LUA_YIELD); - if (ci->callstatus & CIST_YPCALL) { /* was inside a pcall? */ - ci->callstatus &= ~CIST_YPCALL; /* continuation is also inside it */ - L->errfunc = ci->u.c.old_errfunc; /* with the same error function */ - } - /* finish 'lua_callk'/'lua_pcall'; CIST_YPCALL and 'errfunc' already - handled */ - adjustresults(L, ci->nresults); - lua_unlock(L); - n = (*ci->u.c.k)(L, status, ci->u.c.ctx); /* call continuation function */ - lua_lock(L); - api_checknelems(L, n); - luaD_poscall(L, ci, L->top - n, n); /* finish 'luaD_precall' */ -} - - -/* -** Executes "full continuation" (everything in the stack) of a -** previously interrupted coroutine until the stack is empty (or another -** interruption long-jumps out of the loop). If the coroutine is -** recovering from an error, 'ud' points to the error status, which must -** be passed to the first continuation function (otherwise the default -** status is LUA_YIELD). -*/ -static void unroll (lua_State *L, void *ud) { - if (ud != NULL) /* error status? */ - finishCcall(L, *(int *)ud); /* finish 'lua_pcallk' callee */ - while (L->ci != &L->base_ci) { /* something in the stack */ - if (!isLua(L->ci)) /* C function? */ - finishCcall(L, LUA_YIELD); /* complete its execution */ - else { /* Lua function */ - luaV_finishOp(L); /* finish interrupted instruction */ - luaV_execute(L); /* execute down to higher C 'boundary' */ - } - } -} - - -/* -** Try to find a suspended protected call (a "recover point") for the -** given thread. -*/ -static CallInfo *findpcall (lua_State *L) { - CallInfo *ci; - for (ci = L->ci; ci != NULL; ci = ci->previous) { /* search for a pcall */ - if (ci->callstatus & CIST_YPCALL) - return ci; - } - return NULL; /* no pending pcall */ -} - - -/* -** Recovers from an error in a coroutine. Finds a recover point (if -** there is one) and completes the execution of the interrupted -** 'luaD_pcall'. If there is no recover point, returns zero. -*/ -static int recover (lua_State *L, int status) { - StkId oldtop; - CallInfo *ci = findpcall(L); - if (ci == NULL) return 0; /* no recovery point */ - /* "finish" luaD_pcall */ - oldtop = restorestack(L, ci->extra); - luaF_close(L, oldtop); - seterrorobj(L, status, oldtop); - L->ci = ci; - L->allowhook = getoah(ci->callstatus); /* restore original 'allowhook' */ - L->nny = 0; /* should be zero to be yieldable */ - luaD_shrinkstack(L); - L->errfunc = ci->u.c.old_errfunc; - return 1; /* continue running the coroutine */ -} - - -/* -** Signal an error in the call to 'lua_resume', not in the execution -** of the coroutine itself. (Such errors should not be handled by any -** coroutine error handler and should not kill the coroutine.) -*/ -static int resume_error (lua_State *L, const char *msg, int narg) { - L->top -= narg; /* remove args from the stack */ - setsvalue2s(L, L->top, luaS_new(L, msg)); /* push error message */ - api_incr_top(L); - lua_unlock(L); - return LUA_ERRRUN; -} - - -/* -** Do the work for 'lua_resume' in protected mode. Most of the work -** depends on the status of the coroutine: initial state, suspended -** inside a hook, or regularly suspended (optionally with a continuation -** function), plus erroneous cases: non-suspended coroutine or dead -** coroutine. -*/ -static void resume (lua_State *L, void *ud) { - int n = *(cast(int*, ud)); /* number of arguments */ - StkId firstArg = L->top - n; /* first argument */ - CallInfo *ci = L->ci; - if (L->status == LUA_OK) { /* starting a coroutine? */ - if (!luaD_precall(L, firstArg - 1, LUA_MULTRET)) /* Lua function? */ - luaV_execute(L); /* call it */ - } - else { /* resuming from previous yield */ - lua_assert(L->status == LUA_YIELD); - L->status = LUA_OK; /* mark that it is running (again) */ - ci->func = restorestack(L, ci->extra); - if (isLua(ci)) /* yielded inside a hook? */ - luaV_execute(L); /* just continue running Lua code */ - else { /* 'common' yield */ - if (ci->u.c.k != NULL) { /* does it have a continuation function? */ - lua_unlock(L); - n = (*ci->u.c.k)(L, LUA_YIELD, ci->u.c.ctx); /* call continuation */ - lua_lock(L); - api_checknelems(L, n); - firstArg = L->top - n; /* yield results come from continuation */ - } - luaD_poscall(L, ci, firstArg, n); /* finish 'luaD_precall' */ - } - unroll(L, NULL); /* run continuation */ - } -} - - -LUA_API int lua_resume (lua_State *L, lua_State *from, int nargs) { - int status; - unsigned short oldnny = L->nny; /* save "number of non-yieldable" calls */ - lua_lock(L); - if (L->status == LUA_OK) { /* may be starting a coroutine */ - if (L->ci != &L->base_ci) /* not in base level? */ - return resume_error(L, "cannot resume non-suspended coroutine", nargs); - } - else if (L->status != LUA_YIELD) - return resume_error(L, "cannot resume dead coroutine", nargs); - L->nCcalls = (from) ? from->nCcalls + 1 : 1; - if (L->nCcalls >= LUAI_MAXCCALLS) - return resume_error(L, "C stack overflow", nargs); - luai_userstateresume(L, nargs); - L->nny = 0; /* allow yields */ - api_checknelems(L, (L->status == LUA_OK) ? nargs + 1 : nargs); - status = luaD_rawrunprotected(L, resume, &nargs); - if (status == -1) /* error calling 'lua_resume'? */ - status = LUA_ERRRUN; - else { /* continue running after recoverable errors */ - while (errorstatus(status) && recover(L, status)) { - /* unroll continuation */ - status = luaD_rawrunprotected(L, unroll, &status); - } - if (errorstatus(status)) { /* unrecoverable error? */ - L->status = cast_byte(status); /* mark thread as 'dead' */ - seterrorobj(L, status, L->top); /* push error message */ - L->ci->top = L->top; - } - else lua_assert(status == L->status); /* normal end or yield */ - } - L->nny = oldnny; /* restore 'nny' */ - L->nCcalls--; - lua_assert(L->nCcalls == ((from) ? from->nCcalls : 0)); - lua_unlock(L); - return status; -} - - -LUA_API int lua_isyieldable (lua_State *L) { - return (L->nny == 0); -} - - -LUA_API int lua_yieldk (lua_State *L, int nresults, lua_KContext ctx, - lua_KFunction k) { - CallInfo *ci = L->ci; - luai_userstateyield(L, nresults); - lua_lock(L); - api_checknelems(L, nresults); - if (L->nny > 0) { - if (L != G(L)->mainthread) - luaG_runerror(L, "attempt to yield across a C-call boundary"); - else - luaG_runerror(L, "attempt to yield from outside a coroutine"); - } - L->status = LUA_YIELD; - ci->extra = savestack(L, ci->func); /* save current 'func' */ - if (isLua(ci)) { /* inside a hook? */ - api_check(L, k == NULL, "hooks cannot continue after yielding"); - } - else { - if ((ci->u.c.k = k) != NULL) /* is there a continuation? */ - ci->u.c.ctx = ctx; /* save context */ - ci->func = L->top - nresults - 1; /* protect stack below results */ - luaD_throw(L, LUA_YIELD); - } - lua_assert(ci->callstatus & CIST_HOOKED); /* must be inside a hook */ - lua_unlock(L); - return 0; /* return to 'luaD_hook' */ -} - - -int luaD_pcall (lua_State *L, Pfunc func, void *u, - ptrdiff_t old_top, ptrdiff_t ef) { - int status; - CallInfo *old_ci = L->ci; - lu_byte old_allowhooks = L->allowhook; - unsigned short old_nny = L->nny; - ptrdiff_t old_errfunc = L->errfunc; - L->errfunc = ef; - status = luaD_rawrunprotected(L, func, u); - if (status != LUA_OK) { /* an error occurred? */ - StkId oldtop = restorestack(L, old_top); - luaF_close(L, oldtop); /* close possible pending closures */ - seterrorobj(L, status, oldtop); - L->ci = old_ci; - L->allowhook = old_allowhooks; - L->nny = old_nny; - luaD_shrinkstack(L); - } - L->errfunc = old_errfunc; - return status; -} - - - -/* -** Execute a protected parser. -*/ -struct SParser { /* data to 'f_parser' */ - ZIO *z; - Mbuffer buff; /* dynamic structure used by the scanner */ - Dyndata dyd; /* dynamic structures used by the parser */ - const char *mode; - const char *name; -}; - - -static void checkmode (lua_State *L, const char *mode, const char *x) { - if (mode && strchr(mode, x[0]) == NULL) { - luaO_pushfstring(L, - "attempt to load a %s chunk (mode is '%s')", x, mode); - luaD_throw(L, LUA_ERRSYNTAX); - } -} - - -static void f_parser (lua_State *L, void *ud) { - LClosure *cl; - struct SParser *p = cast(struct SParser *, ud); - int c = zgetc(p->z); /* read first character */ - if (c == LUA_SIGNATURE[0]) { - checkmode(L, p->mode, "binary"); - cl = luaU_undump(L, p->z, p->name); - } - else { - checkmode(L, p->mode, "text"); - cl = luaY_parser(L, p->z, &p->buff, &p->dyd, p->name, c); - } - lua_assert(cl->nupvalues == cl->p->sizeupvalues); - luaF_initupvals(L, cl); -} - - -int luaD_protectedparser (lua_State *L, ZIO *z, const char *name, - const char *mode) { - struct SParser p; - int status; - L->nny++; /* cannot yield during parsing */ - p.z = z; p.name = name; p.mode = mode; - p.dyd.actvar.arr = NULL; p.dyd.actvar.size = 0; - p.dyd.gt.arr = NULL; p.dyd.gt.size = 0; - p.dyd.label.arr = NULL; p.dyd.label.size = 0; - luaZ_initbuffer(L, &p.buff); - status = luaD_pcall(L, f_parser, &p, savestack(L, L->top), L->errfunc); - luaZ_freebuffer(L, &p.buff); - luaM_freearray(L, p.dyd.actvar.arr, p.dyd.actvar.size); - luaM_freearray(L, p.dyd.gt.arr, p.dyd.gt.size); - luaM_freearray(L, p.dyd.label.arr, p.dyd.label.size); - L->nny--; - return status; -} - - diff --git a/lib/lua-5.3/src/ldo.h b/lib/lua-5.3/src/ldo.h deleted file mode 100644 index 3b2983a..0000000 --- a/lib/lua-5.3/src/ldo.h +++ /dev/null @@ -1,58 +0,0 @@ -/* -** $Id: ldo.h,v 2.29.1.1 2017/04/19 17:20:42 roberto Exp $ -** Stack and Call structure of Lua -** See Copyright Notice in lua.h -*/ - -#ifndef ldo_h -#define ldo_h - - -#include "lobject.h" -#include "lstate.h" -#include "lzio.h" - - -/* -** Macro to check stack size and grow stack if needed. Parameters -** 'pre'/'pos' allow the macro to preserve a pointer into the -** stack across reallocations, doing the work only when needed. -** 'condmovestack' is used in heavy tests to force a stack reallocation -** at every check. -*/ -#define luaD_checkstackaux(L,n,pre,pos) \ - if (L->stack_last - L->top <= (n)) \ - { pre; luaD_growstack(L, n); pos; } else { condmovestack(L,pre,pos); } - -/* In general, 'pre'/'pos' are empty (nothing to save) */ -#define luaD_checkstack(L,n) luaD_checkstackaux(L,n,(void)0,(void)0) - - - -#define savestack(L,p) ((char *)(p) - (char *)L->stack) -#define restorestack(L,n) ((TValue *)((char *)L->stack + (n))) - - -/* type of protected functions, to be ran by 'runprotected' */ -typedef void (*Pfunc) (lua_State *L, void *ud); - -LUAI_FUNC int luaD_protectedparser (lua_State *L, ZIO *z, const char *name, - const char *mode); -LUAI_FUNC void luaD_hook (lua_State *L, int event, int line); -LUAI_FUNC int luaD_precall (lua_State *L, StkId func, int nresults); -LUAI_FUNC void luaD_call (lua_State *L, StkId func, int nResults); -LUAI_FUNC void luaD_callnoyield (lua_State *L, StkId func, int nResults); -LUAI_FUNC int luaD_pcall (lua_State *L, Pfunc func, void *u, - ptrdiff_t oldtop, ptrdiff_t ef); -LUAI_FUNC int luaD_poscall (lua_State *L, CallInfo *ci, StkId firstResult, - int nres); -LUAI_FUNC void luaD_reallocstack (lua_State *L, int newsize); -LUAI_FUNC void luaD_growstack (lua_State *L, int n); -LUAI_FUNC void luaD_shrinkstack (lua_State *L); -LUAI_FUNC void luaD_inctop (lua_State *L); - -LUAI_FUNC l_noret luaD_throw (lua_State *L, int errcode); -LUAI_FUNC int luaD_rawrunprotected (lua_State *L, Pfunc f, void *ud); - -#endif - diff --git a/lib/lua-5.3/src/ldump.c b/lib/lua-5.3/src/ldump.c deleted file mode 100644 index f025aca..0000000 --- a/lib/lua-5.3/src/ldump.c +++ /dev/null @@ -1,215 +0,0 @@ -/* -** $Id: ldump.c,v 2.37.1.1 2017/04/19 17:20:42 roberto Exp $ -** save precompiled Lua chunks -** See Copyright Notice in lua.h -*/ - -#define ldump_c -#define LUA_CORE - -#include "lprefix.h" - - -#include - -#include "lua.h" - -#include "lobject.h" -#include "lstate.h" -#include "lundump.h" - - -typedef struct { - lua_State *L; - lua_Writer writer; - void *data; - int strip; - int status; -} DumpState; - - -/* -** All high-level dumps go through DumpVector; you can change it to -** change the endianness of the result -*/ -#define DumpVector(v,n,D) DumpBlock(v,(n)*sizeof((v)[0]),D) - -#define DumpLiteral(s,D) DumpBlock(s, sizeof(s) - sizeof(char), D) - - -static void DumpBlock (const void *b, size_t size, DumpState *D) { - if (D->status == 0 && size > 0) { - lua_unlock(D->L); - D->status = (*D->writer)(D->L, b, size, D->data); - lua_lock(D->L); - } -} - - -#define DumpVar(x,D) DumpVector(&x,1,D) - - -static void DumpByte (int y, DumpState *D) { - lu_byte x = (lu_byte)y; - DumpVar(x, D); -} - - -static void DumpInt (int x, DumpState *D) { - DumpVar(x, D); -} - - -static void DumpNumber (lua_Number x, DumpState *D) { - DumpVar(x, D); -} - - -static void DumpInteger (lua_Integer x, DumpState *D) { - DumpVar(x, D); -} - - -static void DumpString (const TString *s, DumpState *D) { - if (s == NULL) - DumpByte(0, D); - else { - size_t size = tsslen(s) + 1; /* include trailing '\0' */ - const char *str = getstr(s); - if (size < 0xFF) - DumpByte(cast_int(size), D); - else { - DumpByte(0xFF, D); - DumpVar(size, D); - } - DumpVector(str, size - 1, D); /* no need to save '\0' */ - } -} - - -static void DumpCode (const Proto *f, DumpState *D) { - DumpInt(f->sizecode, D); - DumpVector(f->code, f->sizecode, D); -} - - -static void DumpFunction(const Proto *f, TString *psource, DumpState *D); - -static void DumpConstants (const Proto *f, DumpState *D) { - int i; - int n = f->sizek; - DumpInt(n, D); - for (i = 0; i < n; i++) { - const TValue *o = &f->k[i]; - DumpByte(ttype(o), D); - switch (ttype(o)) { - case LUA_TNIL: - break; - case LUA_TBOOLEAN: - DumpByte(bvalue(o), D); - break; - case LUA_TNUMFLT: - DumpNumber(fltvalue(o), D); - break; - case LUA_TNUMINT: - DumpInteger(ivalue(o), D); - break; - case LUA_TSHRSTR: - case LUA_TLNGSTR: - DumpString(tsvalue(o), D); - break; - default: - lua_assert(0); - } - } -} - - -static void DumpProtos (const Proto *f, DumpState *D) { - int i; - int n = f->sizep; - DumpInt(n, D); - for (i = 0; i < n; i++) - DumpFunction(f->p[i], f->source, D); -} - - -static void DumpUpvalues (const Proto *f, DumpState *D) { - int i, n = f->sizeupvalues; - DumpInt(n, D); - for (i = 0; i < n; i++) { - DumpByte(f->upvalues[i].instack, D); - DumpByte(f->upvalues[i].idx, D); - } -} - - -static void DumpDebug (const Proto *f, DumpState *D) { - int i, n; - n = (D->strip) ? 0 : f->sizelineinfo; - DumpInt(n, D); - DumpVector(f->lineinfo, n, D); - n = (D->strip) ? 0 : f->sizelocvars; - DumpInt(n, D); - for (i = 0; i < n; i++) { - DumpString(f->locvars[i].varname, D); - DumpInt(f->locvars[i].startpc, D); - DumpInt(f->locvars[i].endpc, D); - } - n = (D->strip) ? 0 : f->sizeupvalues; - DumpInt(n, D); - for (i = 0; i < n; i++) - DumpString(f->upvalues[i].name, D); -} - - -static void DumpFunction (const Proto *f, TString *psource, DumpState *D) { - if (D->strip || f->source == psource) - DumpString(NULL, D); /* no debug info or same source as its parent */ - else - DumpString(f->source, D); - DumpInt(f->linedefined, D); - DumpInt(f->lastlinedefined, D); - DumpByte(f->numparams, D); - DumpByte(f->is_vararg, D); - DumpByte(f->maxstacksize, D); - DumpCode(f, D); - DumpConstants(f, D); - DumpUpvalues(f, D); - DumpProtos(f, D); - DumpDebug(f, D); -} - - -static void DumpHeader (DumpState *D) { - DumpLiteral(LUA_SIGNATURE, D); - DumpByte(LUAC_VERSION, D); - DumpByte(LUAC_FORMAT, D); - DumpLiteral(LUAC_DATA, D); - DumpByte(sizeof(int), D); - DumpByte(sizeof(size_t), D); - DumpByte(sizeof(Instruction), D); - DumpByte(sizeof(lua_Integer), D); - DumpByte(sizeof(lua_Number), D); - DumpInteger(LUAC_INT, D); - DumpNumber(LUAC_NUM, D); -} - - -/* -** dump Lua function as precompiled chunk -*/ -int luaU_dump(lua_State *L, const Proto *f, lua_Writer w, void *data, - int strip) { - DumpState D; - D.L = L; - D.writer = w; - D.data = data; - D.strip = strip; - D.status = 0; - DumpHeader(&D); - DumpByte(f->sizeupvalues, &D); - DumpFunction(f, NULL, &D); - return D.status; -} - diff --git a/lib/lua-5.3/src/lfunc.c b/lib/lua-5.3/src/lfunc.c deleted file mode 100644 index ccafbb8..0000000 --- a/lib/lua-5.3/src/lfunc.c +++ /dev/null @@ -1,151 +0,0 @@ -/* -** $Id: lfunc.c,v 2.45.1.1 2017/04/19 17:39:34 roberto Exp $ -** Auxiliary functions to manipulate prototypes and closures -** See Copyright Notice in lua.h -*/ - -#define lfunc_c -#define LUA_CORE - -#include "lprefix.h" - - -#include - -#include "lua.h" - -#include "lfunc.h" -#include "lgc.h" -#include "lmem.h" -#include "lobject.h" -#include "lstate.h" - - - -CClosure *luaF_newCclosure (lua_State *L, int n) { - GCObject *o = luaC_newobj(L, LUA_TCCL, sizeCclosure(n)); - CClosure *c = gco2ccl(o); - c->nupvalues = cast_byte(n); - return c; -} - - -LClosure *luaF_newLclosure (lua_State *L, int n) { - GCObject *o = luaC_newobj(L, LUA_TLCL, sizeLclosure(n)); - LClosure *c = gco2lcl(o); - c->p = NULL; - c->nupvalues = cast_byte(n); - while (n--) c->upvals[n] = NULL; - return c; -} - -/* -** fill a closure with new closed upvalues -*/ -void luaF_initupvals (lua_State *L, LClosure *cl) { - int i; - for (i = 0; i < cl->nupvalues; i++) { - UpVal *uv = luaM_new(L, UpVal); - uv->refcount = 1; - uv->v = &uv->u.value; /* make it closed */ - setnilvalue(uv->v); - cl->upvals[i] = uv; - } -} - - -UpVal *luaF_findupval (lua_State *L, StkId level) { - UpVal **pp = &L->openupval; - UpVal *p; - UpVal *uv; - lua_assert(isintwups(L) || L->openupval == NULL); - while (*pp != NULL && (p = *pp)->v >= level) { - lua_assert(upisopen(p)); - if (p->v == level) /* found a corresponding upvalue? */ - return p; /* return it */ - pp = &p->u.open.next; - } - /* not found: create a new upvalue */ - uv = luaM_new(L, UpVal); - uv->refcount = 0; - uv->u.open.next = *pp; /* link it to list of open upvalues */ - uv->u.open.touched = 1; - *pp = uv; - uv->v = level; /* current value lives in the stack */ - if (!isintwups(L)) { /* thread not in list of threads with upvalues? */ - L->twups = G(L)->twups; /* link it to the list */ - G(L)->twups = L; - } - return uv; -} - - -void luaF_close (lua_State *L, StkId level) { - UpVal *uv; - while (L->openupval != NULL && (uv = L->openupval)->v >= level) { - lua_assert(upisopen(uv)); - L->openupval = uv->u.open.next; /* remove from 'open' list */ - if (uv->refcount == 0) /* no references? */ - luaM_free(L, uv); /* free upvalue */ - else { - setobj(L, &uv->u.value, uv->v); /* move value to upvalue slot */ - uv->v = &uv->u.value; /* now current value lives here */ - luaC_upvalbarrier(L, uv); - } - } -} - - -Proto *luaF_newproto (lua_State *L) { - GCObject *o = luaC_newobj(L, LUA_TPROTO, sizeof(Proto)); - Proto *f = gco2p(o); - f->k = NULL; - f->sizek = 0; - f->p = NULL; - f->sizep = 0; - f->code = NULL; - f->cache = NULL; - f->sizecode = 0; - f->lineinfo = NULL; - f->sizelineinfo = 0; - f->upvalues = NULL; - f->sizeupvalues = 0; - f->numparams = 0; - f->is_vararg = 0; - f->maxstacksize = 0; - f->locvars = NULL; - f->sizelocvars = 0; - f->linedefined = 0; - f->lastlinedefined = 0; - f->source = NULL; - return f; -} - - -void luaF_freeproto (lua_State *L, Proto *f) { - luaM_freearray(L, f->code, f->sizecode); - luaM_freearray(L, f->p, f->sizep); - luaM_freearray(L, f->k, f->sizek); - luaM_freearray(L, f->lineinfo, f->sizelineinfo); - luaM_freearray(L, f->locvars, f->sizelocvars); - luaM_freearray(L, f->upvalues, f->sizeupvalues); - luaM_free(L, f); -} - - -/* -** Look for n-th local variable at line 'line' in function 'func'. -** Returns NULL if not found. -*/ -const char *luaF_getlocalname (const Proto *f, int local_number, int pc) { - int i; - for (i = 0; isizelocvars && f->locvars[i].startpc <= pc; i++) { - if (pc < f->locvars[i].endpc) { /* is variable active? */ - local_number--; - if (local_number == 0) - return getstr(f->locvars[i].varname); - } - } - return NULL; /* not found */ -} - diff --git a/lib/lua-5.3/src/lfunc.h b/lib/lua-5.3/src/lfunc.h deleted file mode 100644 index c916e98..0000000 --- a/lib/lua-5.3/src/lfunc.h +++ /dev/null @@ -1,61 +0,0 @@ -/* -** $Id: lfunc.h,v 2.15.1.1 2017/04/19 17:39:34 roberto Exp $ -** Auxiliary functions to manipulate prototypes and closures -** See Copyright Notice in lua.h -*/ - -#ifndef lfunc_h -#define lfunc_h - - -#include "lobject.h" - - -#define sizeCclosure(n) (cast(int, sizeof(CClosure)) + \ - cast(int, sizeof(TValue)*((n)-1))) - -#define sizeLclosure(n) (cast(int, sizeof(LClosure)) + \ - cast(int, sizeof(TValue *)*((n)-1))) - - -/* test whether thread is in 'twups' list */ -#define isintwups(L) (L->twups != L) - - -/* -** maximum number of upvalues in a closure (both C and Lua). (Value -** must fit in a VM register.) -*/ -#define MAXUPVAL 255 - - -/* -** Upvalues for Lua closures -*/ -struct UpVal { - TValue *v; /* points to stack or to its own value */ - lu_mem refcount; /* reference counter */ - union { - struct { /* (when open) */ - UpVal *next; /* linked list */ - int touched; /* mark to avoid cycles with dead threads */ - } open; - TValue value; /* the value (when closed) */ - } u; -}; - -#define upisopen(up) ((up)->v != &(up)->u.value) - - -LUAI_FUNC Proto *luaF_newproto (lua_State *L); -LUAI_FUNC CClosure *luaF_newCclosure (lua_State *L, int nelems); -LUAI_FUNC LClosure *luaF_newLclosure (lua_State *L, int nelems); -LUAI_FUNC void luaF_initupvals (lua_State *L, LClosure *cl); -LUAI_FUNC UpVal *luaF_findupval (lua_State *L, StkId level); -LUAI_FUNC void luaF_close (lua_State *L, StkId level); -LUAI_FUNC void luaF_freeproto (lua_State *L, Proto *f); -LUAI_FUNC const char *luaF_getlocalname (const Proto *func, int local_number, - int pc); - - -#endif diff --git a/lib/lua-5.3/src/lgc.c b/lib/lua-5.3/src/lgc.c deleted file mode 100644 index db4df82..0000000 --- a/lib/lua-5.3/src/lgc.c +++ /dev/null @@ -1,1179 +0,0 @@ -/* -** $Id: lgc.c,v 2.215.1.2 2017/08/31 16:15:27 roberto Exp $ -** Garbage Collector -** See Copyright Notice in lua.h -*/ - -#define lgc_c -#define LUA_CORE - -#include "lprefix.h" - - -#include - -#include "lua.h" - -#include "ldebug.h" -#include "ldo.h" -#include "lfunc.h" -#include "lgc.h" -#include "lmem.h" -#include "lobject.h" -#include "lstate.h" -#include "lstring.h" -#include "ltable.h" -#include "ltm.h" - - -/* -** internal state for collector while inside the atomic phase. The -** collector should never be in this state while running regular code. -*/ -#define GCSinsideatomic (GCSpause + 1) - -/* -** cost of sweeping one element (the size of a small object divided -** by some adjust for the sweep speed) -*/ -#define GCSWEEPCOST ((sizeof(TString) + 4) / 4) - -/* maximum number of elements to sweep in each single step */ -#define GCSWEEPMAX (cast_int((GCSTEPSIZE / GCSWEEPCOST) / 4)) - -/* cost of calling one finalizer */ -#define GCFINALIZECOST GCSWEEPCOST - - -/* -** macro to adjust 'stepmul': 'stepmul' is actually used like -** 'stepmul / STEPMULADJ' (value chosen by tests) -*/ -#define STEPMULADJ 200 - - -/* -** macro to adjust 'pause': 'pause' is actually used like -** 'pause / PAUSEADJ' (value chosen by tests) -*/ -#define PAUSEADJ 100 - - -/* -** 'makewhite' erases all color bits then sets only the current white -** bit -*/ -#define maskcolors (~(bitmask(BLACKBIT) | WHITEBITS)) -#define makewhite(g,x) \ - (x->marked = cast_byte((x->marked & maskcolors) | luaC_white(g))) - -#define white2gray(x) resetbits(x->marked, WHITEBITS) -#define black2gray(x) resetbit(x->marked, BLACKBIT) - - -#define valiswhite(x) (iscollectable(x) && iswhite(gcvalue(x))) - -#define checkdeadkey(n) lua_assert(!ttisdeadkey(gkey(n)) || ttisnil(gval(n))) - - -#define checkconsistency(obj) \ - lua_longassert(!iscollectable(obj) || righttt(obj)) - - -#define markvalue(g,o) { checkconsistency(o); \ - if (valiswhite(o)) reallymarkobject(g,gcvalue(o)); } - -#define markobject(g,t) { if (iswhite(t)) reallymarkobject(g, obj2gco(t)); } - -/* -** mark an object that can be NULL (either because it is really optional, -** or it was stripped as debug info, or inside an uncompleted structure) -*/ -#define markobjectN(g,t) { if (t) markobject(g,t); } - -static void reallymarkobject (global_State *g, GCObject *o); - - -/* -** {====================================================== -** Generic functions -** ======================================================= -*/ - - -/* -** one after last element in a hash array -*/ -#define gnodelast(h) gnode(h, cast(size_t, sizenode(h))) - - -/* -** link collectable object 'o' into list pointed by 'p' -*/ -#define linkgclist(o,p) ((o)->gclist = (p), (p) = obj2gco(o)) - - -/* -** If key is not marked, mark its entry as dead. This allows key to be -** collected, but keeps its entry in the table. A dead node is needed -** when Lua looks up for a key (it may be part of a chain) and when -** traversing a weak table (key might be removed from the table during -** traversal). Other places never manipulate dead keys, because its -** associated nil value is enough to signal that the entry is logically -** empty. -*/ -static void removeentry (Node *n) { - lua_assert(ttisnil(gval(n))); - if (valiswhite(gkey(n))) - setdeadvalue(wgkey(n)); /* unused and unmarked key; remove it */ -} - - -/* -** tells whether a key or value can be cleared from a weak -** table. Non-collectable objects are never removed from weak -** tables. Strings behave as 'values', so are never removed too. for -** other objects: if really collected, cannot keep them; for objects -** being finalized, keep them in keys, but not in values -*/ -static int iscleared (global_State *g, const TValue *o) { - if (!iscollectable(o)) return 0; - else if (ttisstring(o)) { - markobject(g, tsvalue(o)); /* strings are 'values', so are never weak */ - return 0; - } - else return iswhite(gcvalue(o)); -} - - -/* -** barrier that moves collector forward, that is, mark the white object -** being pointed by a black object. (If in sweep phase, clear the black -** object to white [sweep it] to avoid other barrier calls for this -** same object.) -*/ -void luaC_barrier_ (lua_State *L, GCObject *o, GCObject *v) { - global_State *g = G(L); - lua_assert(isblack(o) && iswhite(v) && !isdead(g, v) && !isdead(g, o)); - if (keepinvariant(g)) /* must keep invariant? */ - reallymarkobject(g, v); /* restore invariant */ - else { /* sweep phase */ - lua_assert(issweepphase(g)); - makewhite(g, o); /* mark main obj. as white to avoid other barriers */ - } -} - - -/* -** barrier that moves collector backward, that is, mark the black object -** pointing to a white object as gray again. -*/ -void luaC_barrierback_ (lua_State *L, Table *t) { - global_State *g = G(L); - lua_assert(isblack(t) && !isdead(g, t)); - black2gray(t); /* make table gray (again) */ - linkgclist(t, g->grayagain); -} - - -/* -** barrier for assignments to closed upvalues. Because upvalues are -** shared among closures, it is impossible to know the color of all -** closures pointing to it. So, we assume that the object being assigned -** must be marked. -*/ -void luaC_upvalbarrier_ (lua_State *L, UpVal *uv) { - global_State *g = G(L); - GCObject *o = gcvalue(uv->v); - lua_assert(!upisopen(uv)); /* ensured by macro luaC_upvalbarrier */ - if (keepinvariant(g)) - markobject(g, o); -} - - -void luaC_fix (lua_State *L, GCObject *o) { - global_State *g = G(L); - lua_assert(g->allgc == o); /* object must be 1st in 'allgc' list! */ - white2gray(o); /* they will be gray forever */ - g->allgc = o->next; /* remove object from 'allgc' list */ - o->next = g->fixedgc; /* link it to 'fixedgc' list */ - g->fixedgc = o; -} - - -/* -** create a new collectable object (with given type and size) and link -** it to 'allgc' list. -*/ -GCObject *luaC_newobj (lua_State *L, int tt, size_t sz) { - global_State *g = G(L); - GCObject *o = cast(GCObject *, luaM_newobject(L, novariant(tt), sz)); - o->marked = luaC_white(g); - o->tt = tt; - o->next = g->allgc; - g->allgc = o; - return o; -} - -/* }====================================================== */ - - - -/* -** {====================================================== -** Mark functions -** ======================================================= -*/ - - -/* -** mark an object. Userdata, strings, and closed upvalues are visited -** and turned black here. Other objects are marked gray and added -** to appropriate list to be visited (and turned black) later. (Open -** upvalues are already linked in 'headuv' list.) -*/ -static void reallymarkobject (global_State *g, GCObject *o) { - reentry: - white2gray(o); - switch (o->tt) { - case LUA_TSHRSTR: { - gray2black(o); - g->GCmemtrav += sizelstring(gco2ts(o)->shrlen); - break; - } - case LUA_TLNGSTR: { - gray2black(o); - g->GCmemtrav += sizelstring(gco2ts(o)->u.lnglen); - break; - } - case LUA_TUSERDATA: { - TValue uvalue; - markobjectN(g, gco2u(o)->metatable); /* mark its metatable */ - gray2black(o); - g->GCmemtrav += sizeudata(gco2u(o)); - getuservalue(g->mainthread, gco2u(o), &uvalue); - if (valiswhite(&uvalue)) { /* markvalue(g, &uvalue); */ - o = gcvalue(&uvalue); - goto reentry; - } - break; - } - case LUA_TLCL: { - linkgclist(gco2lcl(o), g->gray); - break; - } - case LUA_TCCL: { - linkgclist(gco2ccl(o), g->gray); - break; - } - case LUA_TTABLE: { - linkgclist(gco2t(o), g->gray); - break; - } - case LUA_TTHREAD: { - linkgclist(gco2th(o), g->gray); - break; - } - case LUA_TPROTO: { - linkgclist(gco2p(o), g->gray); - break; - } - default: lua_assert(0); break; - } -} - - -/* -** mark metamethods for basic types -*/ -static void markmt (global_State *g) { - int i; - for (i=0; i < LUA_NUMTAGS; i++) - markobjectN(g, g->mt[i]); -} - - -/* -** mark all objects in list of being-finalized -*/ -static void markbeingfnz (global_State *g) { - GCObject *o; - for (o = g->tobefnz; o != NULL; o = o->next) - markobject(g, o); -} - - -/* -** Mark all values stored in marked open upvalues from non-marked threads. -** (Values from marked threads were already marked when traversing the -** thread.) Remove from the list threads that no longer have upvalues and -** not-marked threads. -*/ -static void remarkupvals (global_State *g) { - lua_State *thread; - lua_State **p = &g->twups; - while ((thread = *p) != NULL) { - lua_assert(!isblack(thread)); /* threads are never black */ - if (isgray(thread) && thread->openupval != NULL) - p = &thread->twups; /* keep marked thread with upvalues in the list */ - else { /* thread is not marked or without upvalues */ - UpVal *uv; - *p = thread->twups; /* remove thread from the list */ - thread->twups = thread; /* mark that it is out of list */ - for (uv = thread->openupval; uv != NULL; uv = uv->u.open.next) { - if (uv->u.open.touched) { - markvalue(g, uv->v); /* remark upvalue's value */ - uv->u.open.touched = 0; - } - } - } - } -} - - -/* -** mark root set and reset all gray lists, to start a new collection -*/ -static void restartcollection (global_State *g) { - g->gray = g->grayagain = NULL; - g->weak = g->allweak = g->ephemeron = NULL; - markobject(g, g->mainthread); - markvalue(g, &g->l_registry); - markmt(g); - markbeingfnz(g); /* mark any finalizing object left from previous cycle */ -} - -/* }====================================================== */ - - -/* -** {====================================================== -** Traverse functions -** ======================================================= -*/ - -/* -** Traverse a table with weak values and link it to proper list. During -** propagate phase, keep it in 'grayagain' list, to be revisited in the -** atomic phase. In the atomic phase, if table has any white value, -** put it in 'weak' list, to be cleared. -*/ -static void traverseweakvalue (global_State *g, Table *h) { - Node *n, *limit = gnodelast(h); - /* if there is array part, assume it may have white values (it is not - worth traversing it now just to check) */ - int hasclears = (h->sizearray > 0); - for (n = gnode(h, 0); n < limit; n++) { /* traverse hash part */ - checkdeadkey(n); - if (ttisnil(gval(n))) /* entry is empty? */ - removeentry(n); /* remove it */ - else { - lua_assert(!ttisnil(gkey(n))); - markvalue(g, gkey(n)); /* mark key */ - if (!hasclears && iscleared(g, gval(n))) /* is there a white value? */ - hasclears = 1; /* table will have to be cleared */ - } - } - if (g->gcstate == GCSpropagate) - linkgclist(h, g->grayagain); /* must retraverse it in atomic phase */ - else if (hasclears) - linkgclist(h, g->weak); /* has to be cleared later */ -} - - -/* -** Traverse an ephemeron table and link it to proper list. Returns true -** iff any object was marked during this traversal (which implies that -** convergence has to continue). During propagation phase, keep table -** in 'grayagain' list, to be visited again in the atomic phase. In -** the atomic phase, if table has any white->white entry, it has to -** be revisited during ephemeron convergence (as that key may turn -** black). Otherwise, if it has any white key, table has to be cleared -** (in the atomic phase). -*/ -static int traverseephemeron (global_State *g, Table *h) { - int marked = 0; /* true if an object is marked in this traversal */ - int hasclears = 0; /* true if table has white keys */ - int hasww = 0; /* true if table has entry "white-key -> white-value" */ - Node *n, *limit = gnodelast(h); - unsigned int i; - /* traverse array part */ - for (i = 0; i < h->sizearray; i++) { - if (valiswhite(&h->array[i])) { - marked = 1; - reallymarkobject(g, gcvalue(&h->array[i])); - } - } - /* traverse hash part */ - for (n = gnode(h, 0); n < limit; n++) { - checkdeadkey(n); - if (ttisnil(gval(n))) /* entry is empty? */ - removeentry(n); /* remove it */ - else if (iscleared(g, gkey(n))) { /* key is not marked (yet)? */ - hasclears = 1; /* table must be cleared */ - if (valiswhite(gval(n))) /* value not marked yet? */ - hasww = 1; /* white-white entry */ - } - else if (valiswhite(gval(n))) { /* value not marked yet? */ - marked = 1; - reallymarkobject(g, gcvalue(gval(n))); /* mark it now */ - } - } - /* link table into proper list */ - if (g->gcstate == GCSpropagate) - linkgclist(h, g->grayagain); /* must retraverse it in atomic phase */ - else if (hasww) /* table has white->white entries? */ - linkgclist(h, g->ephemeron); /* have to propagate again */ - else if (hasclears) /* table has white keys? */ - linkgclist(h, g->allweak); /* may have to clean white keys */ - return marked; -} - - -static void traversestrongtable (global_State *g, Table *h) { - Node *n, *limit = gnodelast(h); - unsigned int i; - for (i = 0; i < h->sizearray; i++) /* traverse array part */ - markvalue(g, &h->array[i]); - for (n = gnode(h, 0); n < limit; n++) { /* traverse hash part */ - checkdeadkey(n); - if (ttisnil(gval(n))) /* entry is empty? */ - removeentry(n); /* remove it */ - else { - lua_assert(!ttisnil(gkey(n))); - markvalue(g, gkey(n)); /* mark key */ - markvalue(g, gval(n)); /* mark value */ - } - } -} - - -static lu_mem traversetable (global_State *g, Table *h) { - const char *weakkey, *weakvalue; - const TValue *mode = gfasttm(g, h->metatable, TM_MODE); - markobjectN(g, h->metatable); - if (mode && ttisstring(mode) && /* is there a weak mode? */ - ((weakkey = strchr(svalue(mode), 'k')), - (weakvalue = strchr(svalue(mode), 'v')), - (weakkey || weakvalue))) { /* is really weak? */ - black2gray(h); /* keep table gray */ - if (!weakkey) /* strong keys? */ - traverseweakvalue(g, h); - else if (!weakvalue) /* strong values? */ - traverseephemeron(g, h); - else /* all weak */ - linkgclist(h, g->allweak); /* nothing to traverse now */ - } - else /* not weak */ - traversestrongtable(g, h); - return sizeof(Table) + sizeof(TValue) * h->sizearray + - sizeof(Node) * cast(size_t, allocsizenode(h)); -} - - -/* -** Traverse a prototype. (While a prototype is being build, its -** arrays can be larger than needed; the extra slots are filled with -** NULL, so the use of 'markobjectN') -*/ -static int traverseproto (global_State *g, Proto *f) { - int i; - if (f->cache && iswhite(f->cache)) - f->cache = NULL; /* allow cache to be collected */ - markobjectN(g, f->source); - for (i = 0; i < f->sizek; i++) /* mark literals */ - markvalue(g, &f->k[i]); - for (i = 0; i < f->sizeupvalues; i++) /* mark upvalue names */ - markobjectN(g, f->upvalues[i].name); - for (i = 0; i < f->sizep; i++) /* mark nested protos */ - markobjectN(g, f->p[i]); - for (i = 0; i < f->sizelocvars; i++) /* mark local-variable names */ - markobjectN(g, f->locvars[i].varname); - return sizeof(Proto) + sizeof(Instruction) * f->sizecode + - sizeof(Proto *) * f->sizep + - sizeof(TValue) * f->sizek + - sizeof(int) * f->sizelineinfo + - sizeof(LocVar) * f->sizelocvars + - sizeof(Upvaldesc) * f->sizeupvalues; -} - - -static lu_mem traverseCclosure (global_State *g, CClosure *cl) { - int i; - for (i = 0; i < cl->nupvalues; i++) /* mark its upvalues */ - markvalue(g, &cl->upvalue[i]); - return sizeCclosure(cl->nupvalues); -} - -/* -** open upvalues point to values in a thread, so those values should -** be marked when the thread is traversed except in the atomic phase -** (because then the value cannot be changed by the thread and the -** thread may not be traversed again) -*/ -static lu_mem traverseLclosure (global_State *g, LClosure *cl) { - int i; - markobjectN(g, cl->p); /* mark its prototype */ - for (i = 0; i < cl->nupvalues; i++) { /* mark its upvalues */ - UpVal *uv = cl->upvals[i]; - if (uv != NULL) { - if (upisopen(uv) && g->gcstate != GCSinsideatomic) - uv->u.open.touched = 1; /* can be marked in 'remarkupvals' */ - else - markvalue(g, uv->v); - } - } - return sizeLclosure(cl->nupvalues); -} - - -static lu_mem traversethread (global_State *g, lua_State *th) { - StkId o = th->stack; - if (o == NULL) - return 1; /* stack not completely built yet */ - lua_assert(g->gcstate == GCSinsideatomic || - th->openupval == NULL || isintwups(th)); - for (; o < th->top; o++) /* mark live elements in the stack */ - markvalue(g, o); - if (g->gcstate == GCSinsideatomic) { /* final traversal? */ - StkId lim = th->stack + th->stacksize; /* real end of stack */ - for (; o < lim; o++) /* clear not-marked stack slice */ - setnilvalue(o); - /* 'remarkupvals' may have removed thread from 'twups' list */ - if (!isintwups(th) && th->openupval != NULL) { - th->twups = g->twups; /* link it back to the list */ - g->twups = th; - } - } - else if (g->gckind != KGC_EMERGENCY) - luaD_shrinkstack(th); /* do not change stack in emergency cycle */ - return (sizeof(lua_State) + sizeof(TValue) * th->stacksize + - sizeof(CallInfo) * th->nci); -} - - -/* -** traverse one gray object, turning it to black (except for threads, -** which are always gray). -*/ -static void propagatemark (global_State *g) { - lu_mem size; - GCObject *o = g->gray; - lua_assert(isgray(o)); - gray2black(o); - switch (o->tt) { - case LUA_TTABLE: { - Table *h = gco2t(o); - g->gray = h->gclist; /* remove from 'gray' list */ - size = traversetable(g, h); - break; - } - case LUA_TLCL: { - LClosure *cl = gco2lcl(o); - g->gray = cl->gclist; /* remove from 'gray' list */ - size = traverseLclosure(g, cl); - break; - } - case LUA_TCCL: { - CClosure *cl = gco2ccl(o); - g->gray = cl->gclist; /* remove from 'gray' list */ - size = traverseCclosure(g, cl); - break; - } - case LUA_TTHREAD: { - lua_State *th = gco2th(o); - g->gray = th->gclist; /* remove from 'gray' list */ - linkgclist(th, g->grayagain); /* insert into 'grayagain' list */ - black2gray(o); - size = traversethread(g, th); - break; - } - case LUA_TPROTO: { - Proto *p = gco2p(o); - g->gray = p->gclist; /* remove from 'gray' list */ - size = traverseproto(g, p); - break; - } - default: lua_assert(0); return; - } - g->GCmemtrav += size; -} - - -static void propagateall (global_State *g) { - while (g->gray) propagatemark(g); -} - - -static void convergeephemerons (global_State *g) { - int changed; - do { - GCObject *w; - GCObject *next = g->ephemeron; /* get ephemeron list */ - g->ephemeron = NULL; /* tables may return to this list when traversed */ - changed = 0; - while ((w = next) != NULL) { - next = gco2t(w)->gclist; - if (traverseephemeron(g, gco2t(w))) { /* traverse marked some value? */ - propagateall(g); /* propagate changes */ - changed = 1; /* will have to revisit all ephemeron tables */ - } - } - } while (changed); -} - -/* }====================================================== */ - - -/* -** {====================================================== -** Sweep Functions -** ======================================================= -*/ - - -/* -** clear entries with unmarked keys from all weaktables in list 'l' up -** to element 'f' -*/ -static void clearkeys (global_State *g, GCObject *l, GCObject *f) { - for (; l != f; l = gco2t(l)->gclist) { - Table *h = gco2t(l); - Node *n, *limit = gnodelast(h); - for (n = gnode(h, 0); n < limit; n++) { - if (!ttisnil(gval(n)) && (iscleared(g, gkey(n)))) { - setnilvalue(gval(n)); /* remove value ... */ - } - if (ttisnil(gval(n))) /* is entry empty? */ - removeentry(n); /* remove entry from table */ - } - } -} - - -/* -** clear entries with unmarked values from all weaktables in list 'l' up -** to element 'f' -*/ -static void clearvalues (global_State *g, GCObject *l, GCObject *f) { - for (; l != f; l = gco2t(l)->gclist) { - Table *h = gco2t(l); - Node *n, *limit = gnodelast(h); - unsigned int i; - for (i = 0; i < h->sizearray; i++) { - TValue *o = &h->array[i]; - if (iscleared(g, o)) /* value was collected? */ - setnilvalue(o); /* remove value */ - } - for (n = gnode(h, 0); n < limit; n++) { - if (!ttisnil(gval(n)) && iscleared(g, gval(n))) { - setnilvalue(gval(n)); /* remove value ... */ - removeentry(n); /* and remove entry from table */ - } - } - } -} - - -void luaC_upvdeccount (lua_State *L, UpVal *uv) { - lua_assert(uv->refcount > 0); - uv->refcount--; - if (uv->refcount == 0 && !upisopen(uv)) - luaM_free(L, uv); -} - - -static void freeLclosure (lua_State *L, LClosure *cl) { - int i; - for (i = 0; i < cl->nupvalues; i++) { - UpVal *uv = cl->upvals[i]; - if (uv) - luaC_upvdeccount(L, uv); - } - luaM_freemem(L, cl, sizeLclosure(cl->nupvalues)); -} - - -static void freeobj (lua_State *L, GCObject *o) { - switch (o->tt) { - case LUA_TPROTO: luaF_freeproto(L, gco2p(o)); break; - case LUA_TLCL: { - freeLclosure(L, gco2lcl(o)); - break; - } - case LUA_TCCL: { - luaM_freemem(L, o, sizeCclosure(gco2ccl(o)->nupvalues)); - break; - } - case LUA_TTABLE: luaH_free(L, gco2t(o)); break; - case LUA_TTHREAD: luaE_freethread(L, gco2th(o)); break; - case LUA_TUSERDATA: luaM_freemem(L, o, sizeudata(gco2u(o))); break; - case LUA_TSHRSTR: - luaS_remove(L, gco2ts(o)); /* remove it from hash table */ - luaM_freemem(L, o, sizelstring(gco2ts(o)->shrlen)); - break; - case LUA_TLNGSTR: { - luaM_freemem(L, o, sizelstring(gco2ts(o)->u.lnglen)); - break; - } - default: lua_assert(0); - } -} - - -#define sweepwholelist(L,p) sweeplist(L,p,MAX_LUMEM) -static GCObject **sweeplist (lua_State *L, GCObject **p, lu_mem count); - - -/* -** sweep at most 'count' elements from a list of GCObjects erasing dead -** objects, where a dead object is one marked with the old (non current) -** white; change all non-dead objects back to white, preparing for next -** collection cycle. Return where to continue the traversal or NULL if -** list is finished. -*/ -static GCObject **sweeplist (lua_State *L, GCObject **p, lu_mem count) { - global_State *g = G(L); - int ow = otherwhite(g); - int white = luaC_white(g); /* current white */ - while (*p != NULL && count-- > 0) { - GCObject *curr = *p; - int marked = curr->marked; - if (isdeadm(ow, marked)) { /* is 'curr' dead? */ - *p = curr->next; /* remove 'curr' from list */ - freeobj(L, curr); /* erase 'curr' */ - } - else { /* change mark to 'white' */ - curr->marked = cast_byte((marked & maskcolors) | white); - p = &curr->next; /* go to next element */ - } - } - return (*p == NULL) ? NULL : p; -} - - -/* -** sweep a list until a live object (or end of list) -*/ -static GCObject **sweeptolive (lua_State *L, GCObject **p) { - GCObject **old = p; - do { - p = sweeplist(L, p, 1); - } while (p == old); - return p; -} - -/* }====================================================== */ - - -/* -** {====================================================== -** Finalization -** ======================================================= -*/ - -/* -** If possible, shrink string table -*/ -static void checkSizes (lua_State *L, global_State *g) { - if (g->gckind != KGC_EMERGENCY) { - l_mem olddebt = g->GCdebt; - if (g->strt.nuse < g->strt.size / 4) /* string table too big? */ - luaS_resize(L, g->strt.size / 2); /* shrink it a little */ - g->GCestimate += g->GCdebt - olddebt; /* update estimate */ - } -} - - -static GCObject *udata2finalize (global_State *g) { - GCObject *o = g->tobefnz; /* get first element */ - lua_assert(tofinalize(o)); - g->tobefnz = o->next; /* remove it from 'tobefnz' list */ - o->next = g->allgc; /* return it to 'allgc' list */ - g->allgc = o; - resetbit(o->marked, FINALIZEDBIT); /* object is "normal" again */ - if (issweepphase(g)) - makewhite(g, o); /* "sweep" object */ - return o; -} - - -static void dothecall (lua_State *L, void *ud) { - UNUSED(ud); - luaD_callnoyield(L, L->top - 2, 0); -} - - -static void GCTM (lua_State *L, int propagateerrors) { - global_State *g = G(L); - const TValue *tm; - TValue v; - setgcovalue(L, &v, udata2finalize(g)); - tm = luaT_gettmbyobj(L, &v, TM_GC); - if (tm != NULL && ttisfunction(tm)) { /* is there a finalizer? */ - int status; - lu_byte oldah = L->allowhook; - int running = g->gcrunning; - L->allowhook = 0; /* stop debug hooks during GC metamethod */ - g->gcrunning = 0; /* avoid GC steps */ - setobj2s(L, L->top, tm); /* push finalizer... */ - setobj2s(L, L->top + 1, &v); /* ... and its argument */ - L->top += 2; /* and (next line) call the finalizer */ - L->ci->callstatus |= CIST_FIN; /* will run a finalizer */ - status = luaD_pcall(L, dothecall, NULL, savestack(L, L->top - 2), 0); - L->ci->callstatus &= ~CIST_FIN; /* not running a finalizer anymore */ - L->allowhook = oldah; /* restore hooks */ - g->gcrunning = running; /* restore state */ - if (status != LUA_OK && propagateerrors) { /* error while running __gc? */ - if (status == LUA_ERRRUN) { /* is there an error object? */ - const char *msg = (ttisstring(L->top - 1)) - ? svalue(L->top - 1) - : "no message"; - luaO_pushfstring(L, "error in __gc metamethod (%s)", msg); - status = LUA_ERRGCMM; /* error in __gc metamethod */ - } - luaD_throw(L, status); /* re-throw error */ - } - } -} - - -/* -** call a few (up to 'g->gcfinnum') finalizers -*/ -static int runafewfinalizers (lua_State *L) { - global_State *g = G(L); - unsigned int i; - lua_assert(!g->tobefnz || g->gcfinnum > 0); - for (i = 0; g->tobefnz && i < g->gcfinnum; i++) - GCTM(L, 1); /* call one finalizer */ - g->gcfinnum = (!g->tobefnz) ? 0 /* nothing more to finalize? */ - : g->gcfinnum * 2; /* else call a few more next time */ - return i; -} - - -/* -** call all pending finalizers -*/ -static void callallpendingfinalizers (lua_State *L) { - global_State *g = G(L); - while (g->tobefnz) - GCTM(L, 0); -} - - -/* -** find last 'next' field in list 'p' list (to add elements in its end) -*/ -static GCObject **findlast (GCObject **p) { - while (*p != NULL) - p = &(*p)->next; - return p; -} - - -/* -** move all unreachable objects (or 'all' objects) that need -** finalization from list 'finobj' to list 'tobefnz' (to be finalized) -*/ -static void separatetobefnz (global_State *g, int all) { - GCObject *curr; - GCObject **p = &g->finobj; - GCObject **lastnext = findlast(&g->tobefnz); - while ((curr = *p) != NULL) { /* traverse all finalizable objects */ - lua_assert(tofinalize(curr)); - if (!(iswhite(curr) || all)) /* not being collected? */ - p = &curr->next; /* don't bother with it */ - else { - *p = curr->next; /* remove 'curr' from 'finobj' list */ - curr->next = *lastnext; /* link at the end of 'tobefnz' list */ - *lastnext = curr; - lastnext = &curr->next; - } - } -} - - -/* -** if object 'o' has a finalizer, remove it from 'allgc' list (must -** search the list to find it) and link it in 'finobj' list. -*/ -void luaC_checkfinalizer (lua_State *L, GCObject *o, Table *mt) { - global_State *g = G(L); - if (tofinalize(o) || /* obj. is already marked... */ - gfasttm(g, mt, TM_GC) == NULL) /* or has no finalizer? */ - return; /* nothing to be done */ - else { /* move 'o' to 'finobj' list */ - GCObject **p; - if (issweepphase(g)) { - makewhite(g, o); /* "sweep" object 'o' */ - if (g->sweepgc == &o->next) /* should not remove 'sweepgc' object */ - g->sweepgc = sweeptolive(L, g->sweepgc); /* change 'sweepgc' */ - } - /* search for pointer pointing to 'o' */ - for (p = &g->allgc; *p != o; p = &(*p)->next) { /* empty */ } - *p = o->next; /* remove 'o' from 'allgc' list */ - o->next = g->finobj; /* link it in 'finobj' list */ - g->finobj = o; - l_setbit(o->marked, FINALIZEDBIT); /* mark it as such */ - } -} - -/* }====================================================== */ - - - -/* -** {====================================================== -** GC control -** ======================================================= -*/ - - -/* -** Set a reasonable "time" to wait before starting a new GC cycle; cycle -** will start when memory use hits threshold. (Division by 'estimate' -** should be OK: it cannot be zero (because Lua cannot even start with -** less than PAUSEADJ bytes). -*/ -static void setpause (global_State *g) { - l_mem threshold, debt; - l_mem estimate = g->GCestimate / PAUSEADJ; /* adjust 'estimate' */ - lua_assert(estimate > 0); - threshold = (g->gcpause < MAX_LMEM / estimate) /* overflow? */ - ? estimate * g->gcpause /* no overflow */ - : MAX_LMEM; /* overflow; truncate to maximum */ - debt = gettotalbytes(g) - threshold; - luaE_setdebt(g, debt); -} - - -/* -** Enter first sweep phase. -** The call to 'sweeplist' tries to make pointer point to an object -** inside the list (instead of to the header), so that the real sweep do -** not need to skip objects created between "now" and the start of the -** real sweep. -*/ -static void entersweep (lua_State *L) { - global_State *g = G(L); - g->gcstate = GCSswpallgc; - lua_assert(g->sweepgc == NULL); - g->sweepgc = sweeplist(L, &g->allgc, 1); -} - - -void luaC_freeallobjects (lua_State *L) { - global_State *g = G(L); - separatetobefnz(g, 1); /* separate all objects with finalizers */ - lua_assert(g->finobj == NULL); - callallpendingfinalizers(L); - lua_assert(g->tobefnz == NULL); - g->currentwhite = WHITEBITS; /* this "white" makes all objects look dead */ - g->gckind = KGC_NORMAL; - sweepwholelist(L, &g->finobj); - sweepwholelist(L, &g->allgc); - sweepwholelist(L, &g->fixedgc); /* collect fixed objects */ - lua_assert(g->strt.nuse == 0); -} - - -static l_mem atomic (lua_State *L) { - global_State *g = G(L); - l_mem work; - GCObject *origweak, *origall; - GCObject *grayagain = g->grayagain; /* save original list */ - lua_assert(g->ephemeron == NULL && g->weak == NULL); - lua_assert(!iswhite(g->mainthread)); - g->gcstate = GCSinsideatomic; - g->GCmemtrav = 0; /* start counting work */ - markobject(g, L); /* mark running thread */ - /* registry and global metatables may be changed by API */ - markvalue(g, &g->l_registry); - markmt(g); /* mark global metatables */ - /* remark occasional upvalues of (maybe) dead threads */ - remarkupvals(g); - propagateall(g); /* propagate changes */ - work = g->GCmemtrav; /* stop counting (do not recount 'grayagain') */ - g->gray = grayagain; - propagateall(g); /* traverse 'grayagain' list */ - g->GCmemtrav = 0; /* restart counting */ - convergeephemerons(g); - /* at this point, all strongly accessible objects are marked. */ - /* Clear values from weak tables, before checking finalizers */ - clearvalues(g, g->weak, NULL); - clearvalues(g, g->allweak, NULL); - origweak = g->weak; origall = g->allweak; - work += g->GCmemtrav; /* stop counting (objects being finalized) */ - separatetobefnz(g, 0); /* separate objects to be finalized */ - g->gcfinnum = 1; /* there may be objects to be finalized */ - markbeingfnz(g); /* mark objects that will be finalized */ - propagateall(g); /* remark, to propagate 'resurrection' */ - g->GCmemtrav = 0; /* restart counting */ - convergeephemerons(g); - /* at this point, all resurrected objects are marked. */ - /* remove dead objects from weak tables */ - clearkeys(g, g->ephemeron, NULL); /* clear keys from all ephemeron tables */ - clearkeys(g, g->allweak, NULL); /* clear keys from all 'allweak' tables */ - /* clear values from resurrected weak tables */ - clearvalues(g, g->weak, origweak); - clearvalues(g, g->allweak, origall); - luaS_clearcache(g); - g->currentwhite = cast_byte(otherwhite(g)); /* flip current white */ - work += g->GCmemtrav; /* complete counting */ - return work; /* estimate of memory marked by 'atomic' */ -} - - -static lu_mem sweepstep (lua_State *L, global_State *g, - int nextstate, GCObject **nextlist) { - if (g->sweepgc) { - l_mem olddebt = g->GCdebt; - g->sweepgc = sweeplist(L, g->sweepgc, GCSWEEPMAX); - g->GCestimate += g->GCdebt - olddebt; /* update estimate */ - if (g->sweepgc) /* is there still something to sweep? */ - return (GCSWEEPMAX * GCSWEEPCOST); - } - /* else enter next state */ - g->gcstate = nextstate; - g->sweepgc = nextlist; - return 0; -} - - -static lu_mem singlestep (lua_State *L) { - global_State *g = G(L); - switch (g->gcstate) { - case GCSpause: { - g->GCmemtrav = g->strt.size * sizeof(GCObject*); - restartcollection(g); - g->gcstate = GCSpropagate; - return g->GCmemtrav; - } - case GCSpropagate: { - g->GCmemtrav = 0; - lua_assert(g->gray); - propagatemark(g); - if (g->gray == NULL) /* no more gray objects? */ - g->gcstate = GCSatomic; /* finish propagate phase */ - return g->GCmemtrav; /* memory traversed in this step */ - } - case GCSatomic: { - lu_mem work; - propagateall(g); /* make sure gray list is empty */ - work = atomic(L); /* work is what was traversed by 'atomic' */ - entersweep(L); - g->GCestimate = gettotalbytes(g); /* first estimate */; - return work; - } - case GCSswpallgc: { /* sweep "regular" objects */ - return sweepstep(L, g, GCSswpfinobj, &g->finobj); - } - case GCSswpfinobj: { /* sweep objects with finalizers */ - return sweepstep(L, g, GCSswptobefnz, &g->tobefnz); - } - case GCSswptobefnz: { /* sweep objects to be finalized */ - return sweepstep(L, g, GCSswpend, NULL); - } - case GCSswpend: { /* finish sweeps */ - makewhite(g, g->mainthread); /* sweep main thread */ - checkSizes(L, g); - g->gcstate = GCScallfin; - return 0; - } - case GCScallfin: { /* call remaining finalizers */ - if (g->tobefnz && g->gckind != KGC_EMERGENCY) { - int n = runafewfinalizers(L); - return (n * GCFINALIZECOST); - } - else { /* emergency mode or no more finalizers */ - g->gcstate = GCSpause; /* finish collection */ - return 0; - } - } - default: lua_assert(0); return 0; - } -} - - -/* -** advances the garbage collector until it reaches a state allowed -** by 'statemask' -*/ -void luaC_runtilstate (lua_State *L, int statesmask) { - global_State *g = G(L); - while (!testbit(statesmask, g->gcstate)) - singlestep(L); -} - - -/* -** get GC debt and convert it from Kb to 'work units' (avoid zero debt -** and overflows) -*/ -static l_mem getdebt (global_State *g) { - l_mem debt = g->GCdebt; - int stepmul = g->gcstepmul; - if (debt <= 0) return 0; /* minimal debt */ - else { - debt = (debt / STEPMULADJ) + 1; - debt = (debt < MAX_LMEM / stepmul) ? debt * stepmul : MAX_LMEM; - return debt; - } -} - -/* -** performs a basic GC step when collector is running -*/ -void luaC_step (lua_State *L) { - global_State *g = G(L); - l_mem debt = getdebt(g); /* GC deficit (be paid now) */ - if (!g->gcrunning) { /* not running? */ - luaE_setdebt(g, -GCSTEPSIZE * 10); /* avoid being called too often */ - return; - } - do { /* repeat until pause or enough "credit" (negative debt) */ - lu_mem work = singlestep(L); /* perform one single step */ - debt -= work; - } while (debt > -GCSTEPSIZE && g->gcstate != GCSpause); - if (g->gcstate == GCSpause) - setpause(g); /* pause until next cycle */ - else { - debt = (debt / g->gcstepmul) * STEPMULADJ; /* convert 'work units' to Kb */ - luaE_setdebt(g, debt); - runafewfinalizers(L); - } -} - - -/* -** Performs a full GC cycle; if 'isemergency', set a flag to avoid -** some operations which could change the interpreter state in some -** unexpected ways (running finalizers and shrinking some structures). -** Before running the collection, check 'keepinvariant'; if it is true, -** there may be some objects marked as black, so the collector has -** to sweep all objects to turn them back to white (as white has not -** changed, nothing will be collected). -*/ -void luaC_fullgc (lua_State *L, int isemergency) { - global_State *g = G(L); - lua_assert(g->gckind == KGC_NORMAL); - if (isemergency) g->gckind = KGC_EMERGENCY; /* set flag */ - if (keepinvariant(g)) { /* black objects? */ - entersweep(L); /* sweep everything to turn them back to white */ - } - /* finish any pending sweep phase to start a new cycle */ - luaC_runtilstate(L, bitmask(GCSpause)); - luaC_runtilstate(L, ~bitmask(GCSpause)); /* start new collection */ - luaC_runtilstate(L, bitmask(GCScallfin)); /* run up to finalizers */ - /* estimate must be correct after a full GC cycle */ - lua_assert(g->GCestimate == gettotalbytes(g)); - luaC_runtilstate(L, bitmask(GCSpause)); /* finish collection */ - g->gckind = KGC_NORMAL; - setpause(g); -} - -/* }====================================================== */ - - diff --git a/lib/lua-5.3/src/lgc.h b/lib/lua-5.3/src/lgc.h deleted file mode 100644 index 425cd7c..0000000 --- a/lib/lua-5.3/src/lgc.h +++ /dev/null @@ -1,147 +0,0 @@ -/* -** $Id: lgc.h,v 2.91.1.1 2017/04/19 17:39:34 roberto Exp $ -** Garbage Collector -** See Copyright Notice in lua.h -*/ - -#ifndef lgc_h -#define lgc_h - - -#include "lobject.h" -#include "lstate.h" - -/* -** Collectable objects may have one of three colors: white, which -** means the object is not marked; gray, which means the -** object is marked, but its references may be not marked; and -** black, which means that the object and all its references are marked. -** The main invariant of the garbage collector, while marking objects, -** is that a black object can never point to a white one. Moreover, -** any gray object must be in a "gray list" (gray, grayagain, weak, -** allweak, ephemeron) so that it can be visited again before finishing -** the collection cycle. These lists have no meaning when the invariant -** is not being enforced (e.g., sweep phase). -*/ - - - -/* how much to allocate before next GC step */ -#if !defined(GCSTEPSIZE) -/* ~100 small strings */ -#define GCSTEPSIZE (cast_int(100 * sizeof(TString))) -#endif - - -/* -** Possible states of the Garbage Collector -*/ -#define GCSpropagate 0 -#define GCSatomic 1 -#define GCSswpallgc 2 -#define GCSswpfinobj 3 -#define GCSswptobefnz 4 -#define GCSswpend 5 -#define GCScallfin 6 -#define GCSpause 7 - - -#define issweepphase(g) \ - (GCSswpallgc <= (g)->gcstate && (g)->gcstate <= GCSswpend) - - -/* -** macro to tell when main invariant (white objects cannot point to black -** ones) must be kept. During a collection, the sweep -** phase may break the invariant, as objects turned white may point to -** still-black objects. The invariant is restored when sweep ends and -** all objects are white again. -*/ - -#define keepinvariant(g) ((g)->gcstate <= GCSatomic) - - -/* -** some useful bit tricks -*/ -#define resetbits(x,m) ((x) &= cast(lu_byte, ~(m))) -#define setbits(x,m) ((x) |= (m)) -#define testbits(x,m) ((x) & (m)) -#define bitmask(b) (1<<(b)) -#define bit2mask(b1,b2) (bitmask(b1) | bitmask(b2)) -#define l_setbit(x,b) setbits(x, bitmask(b)) -#define resetbit(x,b) resetbits(x, bitmask(b)) -#define testbit(x,b) testbits(x, bitmask(b)) - - -/* Layout for bit use in 'marked' field: */ -#define WHITE0BIT 0 /* object is white (type 0) */ -#define WHITE1BIT 1 /* object is white (type 1) */ -#define BLACKBIT 2 /* object is black */ -#define FINALIZEDBIT 3 /* object has been marked for finalization */ -/* bit 7 is currently used by tests (luaL_checkmemory) */ - -#define WHITEBITS bit2mask(WHITE0BIT, WHITE1BIT) - - -#define iswhite(x) testbits((x)->marked, WHITEBITS) -#define isblack(x) testbit((x)->marked, BLACKBIT) -#define isgray(x) /* neither white nor black */ \ - (!testbits((x)->marked, WHITEBITS | bitmask(BLACKBIT))) - -#define tofinalize(x) testbit((x)->marked, FINALIZEDBIT) - -#define otherwhite(g) ((g)->currentwhite ^ WHITEBITS) -#define isdeadm(ow,m) (!(((m) ^ WHITEBITS) & (ow))) -#define isdead(g,v) isdeadm(otherwhite(g), (v)->marked) - -#define changewhite(x) ((x)->marked ^= WHITEBITS) -#define gray2black(x) l_setbit((x)->marked, BLACKBIT) - -#define luaC_white(g) cast(lu_byte, (g)->currentwhite & WHITEBITS) - - -/* -** Does one step of collection when debt becomes positive. 'pre'/'pos' -** allows some adjustments to be done only when needed. macro -** 'condchangemem' is used only for heavy tests (forcing a full -** GC cycle on every opportunity) -*/ -#define luaC_condGC(L,pre,pos) \ - { if (G(L)->GCdebt > 0) { pre; luaC_step(L); pos;}; \ - condchangemem(L,pre,pos); } - -/* more often than not, 'pre'/'pos' are empty */ -#define luaC_checkGC(L) luaC_condGC(L,(void)0,(void)0) - - -#define luaC_barrier(L,p,v) ( \ - (iscollectable(v) && isblack(p) && iswhite(gcvalue(v))) ? \ - luaC_barrier_(L,obj2gco(p),gcvalue(v)) : cast_void(0)) - -#define luaC_barrierback(L,p,v) ( \ - (iscollectable(v) && isblack(p) && iswhite(gcvalue(v))) ? \ - luaC_barrierback_(L,p) : cast_void(0)) - -#define luaC_objbarrier(L,p,o) ( \ - (isblack(p) && iswhite(o)) ? \ - luaC_barrier_(L,obj2gco(p),obj2gco(o)) : cast_void(0)) - -#define luaC_upvalbarrier(L,uv) ( \ - (iscollectable((uv)->v) && !upisopen(uv)) ? \ - luaC_upvalbarrier_(L,uv) : cast_void(0)) - -LUAI_FUNC void luaC_fix (lua_State *L, GCObject *o); -LUAI_FUNC void luaC_freeallobjects (lua_State *L); -LUAI_FUNC void luaC_step (lua_State *L); -LUAI_FUNC void luaC_runtilstate (lua_State *L, int statesmask); -LUAI_FUNC void luaC_fullgc (lua_State *L, int isemergency); -LUAI_FUNC GCObject *luaC_newobj (lua_State *L, int tt, size_t sz); -LUAI_FUNC void luaC_barrier_ (lua_State *L, GCObject *o, GCObject *v); -LUAI_FUNC void luaC_barrierback_ (lua_State *L, Table *o); -LUAI_FUNC void luaC_upvalbarrier_ (lua_State *L, UpVal *uv); -LUAI_FUNC void luaC_checkfinalizer (lua_State *L, GCObject *o, Table *mt); -LUAI_FUNC void luaC_upvdeccount (lua_State *L, UpVal *uv); - - -#endif diff --git a/lib/lua-5.3/src/linit.c b/lib/lua-5.3/src/linit.c deleted file mode 100644 index 480da52..0000000 --- a/lib/lua-5.3/src/linit.c +++ /dev/null @@ -1,68 +0,0 @@ -/* -** $Id: linit.c,v 1.39.1.1 2017/04/19 17:20:42 roberto Exp $ -** Initialization of libraries for lua.c and other clients -** See Copyright Notice in lua.h -*/ - - -#define linit_c -#define LUA_LIB - -/* -** If you embed Lua in your program and need to open the standard -** libraries, call luaL_openlibs in your program. If you need a -** different set of libraries, copy this file to your project and edit -** it to suit your needs. -** -** You can also *preload* libraries, so that a later 'require' can -** open the library, which is already linked to the application. -** For that, do the following code: -** -** luaL_getsubtable(L, LUA_REGISTRYINDEX, LUA_PRELOAD_TABLE); -** lua_pushcfunction(L, luaopen_modname); -** lua_setfield(L, -2, modname); -** lua_pop(L, 1); // remove PRELOAD table -*/ - -#include "lprefix.h" - - -#include - -#include "lua.h" - -#include "lualib.h" -#include "lauxlib.h" - - -/* -** these libs are loaded by lua.c and are readily available to any Lua -** program -*/ -static const luaL_Reg loadedlibs[] = { - {"_G", luaopen_base}, - {LUA_LOADLIBNAME, luaopen_package}, - {LUA_COLIBNAME, luaopen_coroutine}, - {LUA_TABLIBNAME, luaopen_table}, - {LUA_IOLIBNAME, luaopen_io}, - {LUA_OSLIBNAME, luaopen_os}, - {LUA_STRLIBNAME, luaopen_string}, - {LUA_MATHLIBNAME, luaopen_math}, - {LUA_UTF8LIBNAME, luaopen_utf8}, - {LUA_DBLIBNAME, luaopen_debug}, -#if defined(LUA_COMPAT_BITLIB) - {LUA_BITLIBNAME, luaopen_bit32}, -#endif - {NULL, NULL} -}; - - -LUALIB_API void luaL_openlibs (lua_State *L) { - const luaL_Reg *lib; - /* "require" functions from 'loadedlibs' and set results to global table */ - for (lib = loadedlibs; lib->func; lib++) { - luaL_requiref(L, lib->name, lib->func, 1); - lua_pop(L, 1); /* remove lib */ - } -} - diff --git a/lib/lua-5.3/src/liolib.c b/lib/lua-5.3/src/liolib.c deleted file mode 100644 index 027d4bd..0000000 --- a/lib/lua-5.3/src/liolib.c +++ /dev/null @@ -1,778 +0,0 @@ -/* -** $Id: liolib.c,v 2.151.1.1 2017/04/19 17:29:57 roberto Exp $ -** Standard I/O (and system) library -** See Copyright Notice in lua.h -*/ - -#define liolib_c -#define LUA_LIB - -#include "lprefix.h" - - -#include -#include -#include -#include -#include -#include - -#include "lua.h" - -#include "lauxlib.h" -#include "lualib.h" - - - - -/* -** Change this macro to accept other modes for 'fopen' besides -** the standard ones. -*/ -#if !defined(l_checkmode) - -/* accepted extensions to 'mode' in 'fopen' */ -#if !defined(L_MODEEXT) -#define L_MODEEXT "b" -#endif - -/* Check whether 'mode' matches '[rwa]%+?[L_MODEEXT]*' */ -static int l_checkmode (const char *mode) { - return (*mode != '\0' && strchr("rwa", *(mode++)) != NULL && - (*mode != '+' || (++mode, 1)) && /* skip if char is '+' */ - (strspn(mode, L_MODEEXT) == strlen(mode))); /* check extensions */ -} - -#endif - -/* -** {====================================================== -** l_popen spawns a new process connected to the current -** one through the file streams. -** ======================================================= -*/ - -#if !defined(l_popen) /* { */ - -#if defined(LUA_USE_POSIX) /* { */ - -#define l_popen(L,c,m) (fflush(NULL), popen(c,m)) -#define l_pclose(L,file) (pclose(file)) - -#elif defined(LUA_USE_WINDOWS) /* }{ */ - -#define l_popen(L,c,m) (_popen(c,m)) -#define l_pclose(L,file) (_pclose(file)) - -#else /* }{ */ - -/* ISO C definitions */ -#define l_popen(L,c,m) \ - ((void)((void)c, m), \ - luaL_error(L, "'popen' not supported"), \ - (FILE*)0) -#define l_pclose(L,file) ((void)L, (void)file, -1) - -#endif /* } */ - -#endif /* } */ - -/* }====================================================== */ - - -#if !defined(l_getc) /* { */ - -#if defined(LUA_USE_POSIX) -#define l_getc(f) getc_unlocked(f) -#define l_lockfile(f) flockfile(f) -#define l_unlockfile(f) funlockfile(f) -#else -#define l_getc(f) getc(f) -#define l_lockfile(f) ((void)0) -#define l_unlockfile(f) ((void)0) -#endif - -#endif /* } */ - - -/* -** {====================================================== -** l_fseek: configuration for longer offsets -** ======================================================= -*/ - -#if !defined(l_fseek) /* { */ - -#if defined(LUA_USE_POSIX) /* { */ - -#include - -#define l_fseek(f,o,w) fseeko(f,o,w) -#define l_ftell(f) ftello(f) -#define l_seeknum off_t - -#elif defined(LUA_USE_WINDOWS) && !defined(_CRTIMP_TYPEINFO) \ - && defined(_MSC_VER) && (_MSC_VER >= 1400) /* }{ */ - -/* Windows (but not DDK) and Visual C++ 2005 or higher */ -#define l_fseek(f,o,w) _fseeki64(f,o,w) -#define l_ftell(f) _ftelli64(f) -#define l_seeknum __int64 - -#else /* }{ */ - -/* ISO C definitions */ -#define l_fseek(f,o,w) fseek(f,o,w) -#define l_ftell(f) ftell(f) -#define l_seeknum long - -#endif /* } */ - -#endif /* } */ - -/* }====================================================== */ - - -#define IO_PREFIX "_IO_" -#define IOPREF_LEN (sizeof(IO_PREFIX)/sizeof(char) - 1) -#define IO_INPUT (IO_PREFIX "input") -#define IO_OUTPUT (IO_PREFIX "output") - - -typedef luaL_Stream LStream; - - -#define tolstream(L) ((LStream *)luaL_checkudata(L, 1, LUA_FILEHANDLE)) - -#define isclosed(p) ((p)->closef == NULL) - - -static int io_type (lua_State *L) { - LStream *p; - luaL_checkany(L, 1); - p = (LStream *)luaL_testudata(L, 1, LUA_FILEHANDLE); - if (p == NULL) - lua_pushnil(L); /* not a file */ - else if (isclosed(p)) - lua_pushliteral(L, "closed file"); - else - lua_pushliteral(L, "file"); - return 1; -} - - -static int f_tostring (lua_State *L) { - LStream *p = tolstream(L); - if (isclosed(p)) - lua_pushliteral(L, "file (closed)"); - else - lua_pushfstring(L, "file (%p)", p->f); - return 1; -} - - -static FILE *tofile (lua_State *L) { - LStream *p = tolstream(L); - if (isclosed(p)) - luaL_error(L, "attempt to use a closed file"); - lua_assert(p->f); - return p->f; -} - - -/* -** When creating file handles, always creates a 'closed' file handle -** before opening the actual file; so, if there is a memory error, the -** handle is in a consistent state. -*/ -static LStream *newprefile (lua_State *L) { - LStream *p = (LStream *)lua_newuserdata(L, sizeof(LStream)); - p->closef = NULL; /* mark file handle as 'closed' */ - luaL_setmetatable(L, LUA_FILEHANDLE); - return p; -} - - -/* -** Calls the 'close' function from a file handle. The 'volatile' avoids -** a bug in some versions of the Clang compiler (e.g., clang 3.0 for -** 32 bits). -*/ -static int aux_close (lua_State *L) { - LStream *p = tolstream(L); - volatile lua_CFunction cf = p->closef; - p->closef = NULL; /* mark stream as closed */ - return (*cf)(L); /* close it */ -} - - -static int f_close (lua_State *L) { - tofile(L); /* make sure argument is an open stream */ - return aux_close(L); -} - - -static int io_close (lua_State *L) { - if (lua_isnone(L, 1)) /* no argument? */ - lua_getfield(L, LUA_REGISTRYINDEX, IO_OUTPUT); /* use standard output */ - return f_close(L); -} - - -static int f_gc (lua_State *L) { - LStream *p = tolstream(L); - if (!isclosed(p) && p->f != NULL) - aux_close(L); /* ignore closed and incompletely open files */ - return 0; -} - - -/* -** function to close regular files -*/ -static int io_fclose (lua_State *L) { - LStream *p = tolstream(L); - int res = fclose(p->f); - return luaL_fileresult(L, (res == 0), NULL); -} - - -static LStream *newfile (lua_State *L) { - LStream *p = newprefile(L); - p->f = NULL; - p->closef = &io_fclose; - return p; -} - - -static void opencheck (lua_State *L, const char *fname, const char *mode) { - LStream *p = newfile(L); - p->f = fopen(fname, mode); - if (p->f == NULL) - luaL_error(L, "cannot open file '%s' (%s)", fname, strerror(errno)); -} - - -static int io_open (lua_State *L) { - const char *filename = luaL_checkstring(L, 1); - const char *mode = luaL_optstring(L, 2, "r"); - LStream *p = newfile(L); - const char *md = mode; /* to traverse/check mode */ - luaL_argcheck(L, l_checkmode(md), 2, "invalid mode"); - p->f = fopen(filename, mode); - return (p->f == NULL) ? luaL_fileresult(L, 0, filename) : 1; -} - - -/* -** function to close 'popen' files -*/ -static int io_pclose (lua_State *L) { - LStream *p = tolstream(L); - return luaL_execresult(L, l_pclose(L, p->f)); -} - - -static int io_popen (lua_State *L) { - const char *filename = luaL_checkstring(L, 1); - const char *mode = luaL_optstring(L, 2, "r"); - LStream *p = newprefile(L); - luaL_argcheck(L, ((mode[0] == 'r' || mode[0] == 'w') && mode[1] == '\0'), - 2, "invalid mode"); - p->f = l_popen(L, filename, mode); - p->closef = &io_pclose; - return (p->f == NULL) ? luaL_fileresult(L, 0, filename) : 1; -} - - -static int io_tmpfile (lua_State *L) { - LStream *p = newfile(L); - p->f = tmpfile(); - return (p->f == NULL) ? luaL_fileresult(L, 0, NULL) : 1; -} - - -static FILE *getiofile (lua_State *L, const char *findex) { - LStream *p; - lua_getfield(L, LUA_REGISTRYINDEX, findex); - p = (LStream *)lua_touserdata(L, -1); - if (isclosed(p)) - luaL_error(L, "standard %s file is closed", findex + IOPREF_LEN); - return p->f; -} - - -static int g_iofile (lua_State *L, const char *f, const char *mode) { - if (!lua_isnoneornil(L, 1)) { - const char *filename = lua_tostring(L, 1); - if (filename) - opencheck(L, filename, mode); - else { - tofile(L); /* check that it's a valid file handle */ - lua_pushvalue(L, 1); - } - lua_setfield(L, LUA_REGISTRYINDEX, f); - } - /* return current value */ - lua_getfield(L, LUA_REGISTRYINDEX, f); - return 1; -} - - -static int io_input (lua_State *L) { - return g_iofile(L, IO_INPUT, "r"); -} - - -static int io_output (lua_State *L) { - return g_iofile(L, IO_OUTPUT, "w"); -} - - -static int io_readline (lua_State *L); - - -/* -** maximum number of arguments to 'f:lines'/'io.lines' (it + 3 must fit -** in the limit for upvalues of a closure) -*/ -#define MAXARGLINE 250 - -static void aux_lines (lua_State *L, int toclose) { - int n = lua_gettop(L) - 1; /* number of arguments to read */ - luaL_argcheck(L, n <= MAXARGLINE, MAXARGLINE + 2, "too many arguments"); - lua_pushinteger(L, n); /* number of arguments to read */ - lua_pushboolean(L, toclose); /* close/not close file when finished */ - lua_rotate(L, 2, 2); /* move 'n' and 'toclose' to their positions */ - lua_pushcclosure(L, io_readline, 3 + n); -} - - -static int f_lines (lua_State *L) { - tofile(L); /* check that it's a valid file handle */ - aux_lines(L, 0); - return 1; -} - - -static int io_lines (lua_State *L) { - int toclose; - if (lua_isnone(L, 1)) lua_pushnil(L); /* at least one argument */ - if (lua_isnil(L, 1)) { /* no file name? */ - lua_getfield(L, LUA_REGISTRYINDEX, IO_INPUT); /* get default input */ - lua_replace(L, 1); /* put it at index 1 */ - tofile(L); /* check that it's a valid file handle */ - toclose = 0; /* do not close it after iteration */ - } - else { /* open a new file */ - const char *filename = luaL_checkstring(L, 1); - opencheck(L, filename, "r"); - lua_replace(L, 1); /* put file at index 1 */ - toclose = 1; /* close it after iteration */ - } - aux_lines(L, toclose); - return 1; -} - - -/* -** {====================================================== -** READ -** ======================================================= -*/ - - -/* maximum length of a numeral */ -#if !defined (L_MAXLENNUM) -#define L_MAXLENNUM 200 -#endif - - -/* auxiliary structure used by 'read_number' */ -typedef struct { - FILE *f; /* file being read */ - int c; /* current character (look ahead) */ - int n; /* number of elements in buffer 'buff' */ - char buff[L_MAXLENNUM + 1]; /* +1 for ending '\0' */ -} RN; - - -/* -** Add current char to buffer (if not out of space) and read next one -*/ -static int nextc (RN *rn) { - if (rn->n >= L_MAXLENNUM) { /* buffer overflow? */ - rn->buff[0] = '\0'; /* invalidate result */ - return 0; /* fail */ - } - else { - rn->buff[rn->n++] = rn->c; /* save current char */ - rn->c = l_getc(rn->f); /* read next one */ - return 1; - } -} - - -/* -** Accept current char if it is in 'set' (of size 2) -*/ -static int test2 (RN *rn, const char *set) { - if (rn->c == set[0] || rn->c == set[1]) - return nextc(rn); - else return 0; -} - - -/* -** Read a sequence of (hex)digits -*/ -static int readdigits (RN *rn, int hex) { - int count = 0; - while ((hex ? isxdigit(rn->c) : isdigit(rn->c)) && nextc(rn)) - count++; - return count; -} - - -/* -** Read a number: first reads a valid prefix of a numeral into a buffer. -** Then it calls 'lua_stringtonumber' to check whether the format is -** correct and to convert it to a Lua number -*/ -static int read_number (lua_State *L, FILE *f) { - RN rn; - int count = 0; - int hex = 0; - char decp[2]; - rn.f = f; rn.n = 0; - decp[0] = lua_getlocaledecpoint(); /* get decimal point from locale */ - decp[1] = '.'; /* always accept a dot */ - l_lockfile(rn.f); - do { rn.c = l_getc(rn.f); } while (isspace(rn.c)); /* skip spaces */ - test2(&rn, "-+"); /* optional signal */ - if (test2(&rn, "00")) { - if (test2(&rn, "xX")) hex = 1; /* numeral is hexadecimal */ - else count = 1; /* count initial '0' as a valid digit */ - } - count += readdigits(&rn, hex); /* integral part */ - if (test2(&rn, decp)) /* decimal point? */ - count += readdigits(&rn, hex); /* fractional part */ - if (count > 0 && test2(&rn, (hex ? "pP" : "eE"))) { /* exponent mark? */ - test2(&rn, "-+"); /* exponent signal */ - readdigits(&rn, 0); /* exponent digits */ - } - ungetc(rn.c, rn.f); /* unread look-ahead char */ - l_unlockfile(rn.f); - rn.buff[rn.n] = '\0'; /* finish string */ - if (lua_stringtonumber(L, rn.buff)) /* is this a valid number? */ - return 1; /* ok */ - else { /* invalid format */ - lua_pushnil(L); /* "result" to be removed */ - return 0; /* read fails */ - } -} - - -static int test_eof (lua_State *L, FILE *f) { - int c = getc(f); - ungetc(c, f); /* no-op when c == EOF */ - lua_pushliteral(L, ""); - return (c != EOF); -} - - -static int read_line (lua_State *L, FILE *f, int chop) { - luaL_Buffer b; - int c = '\0'; - luaL_buffinit(L, &b); - while (c != EOF && c != '\n') { /* repeat until end of line */ - char *buff = luaL_prepbuffer(&b); /* preallocate buffer */ - int i = 0; - l_lockfile(f); /* no memory errors can happen inside the lock */ - while (i < LUAL_BUFFERSIZE && (c = l_getc(f)) != EOF && c != '\n') - buff[i++] = c; - l_unlockfile(f); - luaL_addsize(&b, i); - } - if (!chop && c == '\n') /* want a newline and have one? */ - luaL_addchar(&b, c); /* add ending newline to result */ - luaL_pushresult(&b); /* close buffer */ - /* return ok if read something (either a newline or something else) */ - return (c == '\n' || lua_rawlen(L, -1) > 0); -} - - -static void read_all (lua_State *L, FILE *f) { - size_t nr; - luaL_Buffer b; - luaL_buffinit(L, &b); - do { /* read file in chunks of LUAL_BUFFERSIZE bytes */ - char *p = luaL_prepbuffer(&b); - nr = fread(p, sizeof(char), LUAL_BUFFERSIZE, f); - luaL_addsize(&b, nr); - } while (nr == LUAL_BUFFERSIZE); - luaL_pushresult(&b); /* close buffer */ -} - - -static int read_chars (lua_State *L, FILE *f, size_t n) { - size_t nr; /* number of chars actually read */ - char *p; - luaL_Buffer b; - luaL_buffinit(L, &b); - p = luaL_prepbuffsize(&b, n); /* prepare buffer to read whole block */ - nr = fread(p, sizeof(char), n, f); /* try to read 'n' chars */ - luaL_addsize(&b, nr); - luaL_pushresult(&b); /* close buffer */ - return (nr > 0); /* true iff read something */ -} - - -static int g_read (lua_State *L, FILE *f, int first) { - int nargs = lua_gettop(L) - 1; - int success; - int n; - clearerr(f); - if (nargs == 0) { /* no arguments? */ - success = read_line(L, f, 1); - n = first+1; /* to return 1 result */ - } - else { /* ensure stack space for all results and for auxlib's buffer */ - luaL_checkstack(L, nargs+LUA_MINSTACK, "too many arguments"); - success = 1; - for (n = first; nargs-- && success; n++) { - if (lua_type(L, n) == LUA_TNUMBER) { - size_t l = (size_t)luaL_checkinteger(L, n); - success = (l == 0) ? test_eof(L, f) : read_chars(L, f, l); - } - else { - const char *p = luaL_checkstring(L, n); - if (*p == '*') p++; /* skip optional '*' (for compatibility) */ - switch (*p) { - case 'n': /* number */ - success = read_number(L, f); - break; - case 'l': /* line */ - success = read_line(L, f, 1); - break; - case 'L': /* line with end-of-line */ - success = read_line(L, f, 0); - break; - case 'a': /* file */ - read_all(L, f); /* read entire file */ - success = 1; /* always success */ - break; - default: - return luaL_argerror(L, n, "invalid format"); - } - } - } - } - if (ferror(f)) - return luaL_fileresult(L, 0, NULL); - if (!success) { - lua_pop(L, 1); /* remove last result */ - lua_pushnil(L); /* push nil instead */ - } - return n - first; -} - - -static int io_read (lua_State *L) { - return g_read(L, getiofile(L, IO_INPUT), 1); -} - - -static int f_read (lua_State *L) { - return g_read(L, tofile(L), 2); -} - - -static int io_readline (lua_State *L) { - LStream *p = (LStream *)lua_touserdata(L, lua_upvalueindex(1)); - int i; - int n = (int)lua_tointeger(L, lua_upvalueindex(2)); - if (isclosed(p)) /* file is already closed? */ - return luaL_error(L, "file is already closed"); - lua_settop(L , 1); - luaL_checkstack(L, n, "too many arguments"); - for (i = 1; i <= n; i++) /* push arguments to 'g_read' */ - lua_pushvalue(L, lua_upvalueindex(3 + i)); - n = g_read(L, p->f, 2); /* 'n' is number of results */ - lua_assert(n > 0); /* should return at least a nil */ - if (lua_toboolean(L, -n)) /* read at least one value? */ - return n; /* return them */ - else { /* first result is nil: EOF or error */ - if (n > 1) { /* is there error information? */ - /* 2nd result is error message */ - return luaL_error(L, "%s", lua_tostring(L, -n + 1)); - } - if (lua_toboolean(L, lua_upvalueindex(3))) { /* generator created file? */ - lua_settop(L, 0); - lua_pushvalue(L, lua_upvalueindex(1)); - aux_close(L); /* close it */ - } - return 0; - } -} - -/* }====================================================== */ - - -static int g_write (lua_State *L, FILE *f, int arg) { - int nargs = lua_gettop(L) - arg; - int status = 1; - for (; nargs--; arg++) { - if (lua_type(L, arg) == LUA_TNUMBER) { - /* optimization: could be done exactly as for strings */ - int len = lua_isinteger(L, arg) - ? fprintf(f, LUA_INTEGER_FMT, - (LUAI_UACINT)lua_tointeger(L, arg)) - : fprintf(f, LUA_NUMBER_FMT, - (LUAI_UACNUMBER)lua_tonumber(L, arg)); - status = status && (len > 0); - } - else { - size_t l; - const char *s = luaL_checklstring(L, arg, &l); - status = status && (fwrite(s, sizeof(char), l, f) == l); - } - } - if (status) return 1; /* file handle already on stack top */ - else return luaL_fileresult(L, status, NULL); -} - - -static int io_write (lua_State *L) { - return g_write(L, getiofile(L, IO_OUTPUT), 1); -} - - -static int f_write (lua_State *L) { - FILE *f = tofile(L); - lua_pushvalue(L, 1); /* push file at the stack top (to be returned) */ - return g_write(L, f, 2); -} - - -static int f_seek (lua_State *L) { - static const int mode[] = {SEEK_SET, SEEK_CUR, SEEK_END}; - static const char *const modenames[] = {"set", "cur", "end", NULL}; - FILE *f = tofile(L); - int op = luaL_checkoption(L, 2, "cur", modenames); - lua_Integer p3 = luaL_optinteger(L, 3, 0); - l_seeknum offset = (l_seeknum)p3; - luaL_argcheck(L, (lua_Integer)offset == p3, 3, - "not an integer in proper range"); - op = l_fseek(f, offset, mode[op]); - if (op) - return luaL_fileresult(L, 0, NULL); /* error */ - else { - lua_pushinteger(L, (lua_Integer)l_ftell(f)); - return 1; - } -} - - -static int f_setvbuf (lua_State *L) { - static const int mode[] = {_IONBF, _IOFBF, _IOLBF}; - static const char *const modenames[] = {"no", "full", "line", NULL}; - FILE *f = tofile(L); - int op = luaL_checkoption(L, 2, NULL, modenames); - lua_Integer sz = luaL_optinteger(L, 3, LUAL_BUFFERSIZE); - int res = setvbuf(f, NULL, mode[op], (size_t)sz); - return luaL_fileresult(L, res == 0, NULL); -} - - - -static int io_flush (lua_State *L) { - return luaL_fileresult(L, fflush(getiofile(L, IO_OUTPUT)) == 0, NULL); -} - - -static int f_flush (lua_State *L) { - return luaL_fileresult(L, fflush(tofile(L)) == 0, NULL); -} - - -/* -** functions for 'io' library -*/ -static const luaL_Reg iolib[] = { - {"close", io_close}, - {"flush", io_flush}, - {"input", io_input}, - {"lines", io_lines}, - {"open", io_open}, - {"output", io_output}, - {"popen", io_popen}, - {"read", io_read}, - {"tmpfile", io_tmpfile}, - {"type", io_type}, - {"write", io_write}, - {NULL, NULL} -}; - - -/* -** methods for file handles -*/ -static const luaL_Reg flib[] = { - {"close", f_close}, - {"flush", f_flush}, - {"lines", f_lines}, - {"read", f_read}, - {"seek", f_seek}, - {"setvbuf", f_setvbuf}, - {"write", f_write}, - {"__gc", f_gc}, - {"__tostring", f_tostring}, - {NULL, NULL} -}; - - -static void createmeta (lua_State *L) { - luaL_newmetatable(L, LUA_FILEHANDLE); /* create metatable for file handles */ - lua_pushvalue(L, -1); /* push metatable */ - lua_setfield(L, -2, "__index"); /* metatable.__index = metatable */ - luaL_setfuncs(L, flib, 0); /* add file methods to new metatable */ - lua_pop(L, 1); /* pop new metatable */ -} - - -/* -** function to (not) close the standard files stdin, stdout, and stderr -*/ -static int io_noclose (lua_State *L) { - LStream *p = tolstream(L); - p->closef = &io_noclose; /* keep file opened */ - lua_pushnil(L); - lua_pushliteral(L, "cannot close standard file"); - return 2; -} - - -static void createstdfile (lua_State *L, FILE *f, const char *k, - const char *fname) { - LStream *p = newprefile(L); - p->f = f; - p->closef = &io_noclose; - if (k != NULL) { - lua_pushvalue(L, -1); - lua_setfield(L, LUA_REGISTRYINDEX, k); /* add file to registry */ - } - lua_setfield(L, -2, fname); /* add file to module */ -} - - -LUAMOD_API int luaopen_io (lua_State *L) { - luaL_newlib(L, iolib); /* new module */ - createmeta(L); - /* create (and set) default files */ - createstdfile(L, stdin, IO_INPUT, "stdin"); - createstdfile(L, stdout, IO_OUTPUT, "stdout"); - createstdfile(L, stderr, NULL, "stderr"); - return 1; -} - diff --git a/lib/lua-5.3/src/llex.c b/lib/lua-5.3/src/llex.c deleted file mode 100644 index b6d9a46..0000000 --- a/lib/lua-5.3/src/llex.c +++ /dev/null @@ -1,568 +0,0 @@ -/* -** $Id: llex.c,v 2.96.1.1 2017/04/19 17:20:42 roberto Exp $ -** Lexical Analyzer -** See Copyright Notice in lua.h -*/ - -#define llex_c -#define LUA_CORE - -#include "lprefix.h" - - -#include -#include - -#include "lua.h" - -#include "lctype.h" -#include "ldebug.h" -#include "ldo.h" -#include "lgc.h" -#include "llex.h" -#include "lobject.h" -#include "lparser.h" -#include "lstate.h" -#include "lstring.h" -#include "ltable.h" -#include "lzio.h" - - - -#define next(ls) (ls->current = zgetc(ls->z)) - - - -#define currIsNewline(ls) (ls->current == '\n' || ls->current == '\r') - - -/* ORDER RESERVED */ -static const char *const luaX_tokens [] = { - "and", "break", "do", "else", "elseif", - "end", "false", "for", "function", "goto", "if", - "in", "local", "nil", "not", "or", "repeat", - "return", "then", "true", "until", "while", - "//", "..", "...", "==", ">=", "<=", "~=", - "<<", ">>", "::", "", - "", "", "", "" -}; - - -#define save_and_next(ls) (save(ls, ls->current), next(ls)) - - -static l_noret lexerror (LexState *ls, const char *msg, int token); - - -static void save (LexState *ls, int c) { - Mbuffer *b = ls->buff; - if (luaZ_bufflen(b) + 1 > luaZ_sizebuffer(b)) { - size_t newsize; - if (luaZ_sizebuffer(b) >= MAX_SIZE/2) - lexerror(ls, "lexical element too long", 0); - newsize = luaZ_sizebuffer(b) * 2; - luaZ_resizebuffer(ls->L, b, newsize); - } - b->buffer[luaZ_bufflen(b)++] = cast(char, c); -} - - -void luaX_init (lua_State *L) { - int i; - TString *e = luaS_newliteral(L, LUA_ENV); /* create env name */ - luaC_fix(L, obj2gco(e)); /* never collect this name */ - for (i=0; iextra = cast_byte(i+1); /* reserved word */ - } -} - - -const char *luaX_token2str (LexState *ls, int token) { - if (token < FIRST_RESERVED) { /* single-byte symbols? */ - lua_assert(token == cast_uchar(token)); - return luaO_pushfstring(ls->L, "'%c'", token); - } - else { - const char *s = luaX_tokens[token - FIRST_RESERVED]; - if (token < TK_EOS) /* fixed format (symbols and reserved words)? */ - return luaO_pushfstring(ls->L, "'%s'", s); - else /* names, strings, and numerals */ - return s; - } -} - - -static const char *txtToken (LexState *ls, int token) { - switch (token) { - case TK_NAME: case TK_STRING: - case TK_FLT: case TK_INT: - save(ls, '\0'); - return luaO_pushfstring(ls->L, "'%s'", luaZ_buffer(ls->buff)); - default: - return luaX_token2str(ls, token); - } -} - - -static l_noret lexerror (LexState *ls, const char *msg, int token) { - msg = luaG_addinfo(ls->L, msg, ls->source, ls->linenumber); - if (token) - luaO_pushfstring(ls->L, "%s near %s", msg, txtToken(ls, token)); - luaD_throw(ls->L, LUA_ERRSYNTAX); -} - - -l_noret luaX_syntaxerror (LexState *ls, const char *msg) { - lexerror(ls, msg, ls->t.token); -} - - -/* -** creates a new string and anchors it in scanner's table so that -** it will not be collected until the end of the compilation -** (by that time it should be anchored somewhere) -*/ -TString *luaX_newstring (LexState *ls, const char *str, size_t l) { - lua_State *L = ls->L; - TValue *o; /* entry for 'str' */ - TString *ts = luaS_newlstr(L, str, l); /* create new string */ - setsvalue2s(L, L->top++, ts); /* temporarily anchor it in stack */ - o = luaH_set(L, ls->h, L->top - 1); - if (ttisnil(o)) { /* not in use yet? */ - /* boolean value does not need GC barrier; - table has no metatable, so it does not need to invalidate cache */ - setbvalue(o, 1); /* t[string] = true */ - luaC_checkGC(L); - } - else { /* string already present */ - ts = tsvalue(keyfromval(o)); /* re-use value previously stored */ - } - L->top--; /* remove string from stack */ - return ts; -} - - -/* -** increment line number and skips newline sequence (any of -** \n, \r, \n\r, or \r\n) -*/ -static void inclinenumber (LexState *ls) { - int old = ls->current; - lua_assert(currIsNewline(ls)); - next(ls); /* skip '\n' or '\r' */ - if (currIsNewline(ls) && ls->current != old) - next(ls); /* skip '\n\r' or '\r\n' */ - if (++ls->linenumber >= MAX_INT) - lexerror(ls, "chunk has too many lines", 0); -} - - -void luaX_setinput (lua_State *L, LexState *ls, ZIO *z, TString *source, - int firstchar) { - ls->t.token = 0; - ls->L = L; - ls->current = firstchar; - ls->lookahead.token = TK_EOS; /* no look-ahead token */ - ls->z = z; - ls->fs = NULL; - ls->linenumber = 1; - ls->lastline = 1; - ls->source = source; - ls->envn = luaS_newliteral(L, LUA_ENV); /* get env name */ - luaZ_resizebuffer(ls->L, ls->buff, LUA_MINBUFFER); /* initialize buffer */ -} - - - -/* -** ======================================================= -** LEXICAL ANALYZER -** ======================================================= -*/ - - -static int check_next1 (LexState *ls, int c) { - if (ls->current == c) { - next(ls); - return 1; - } - else return 0; -} - - -/* -** Check whether current char is in set 'set' (with two chars) and -** saves it -*/ -static int check_next2 (LexState *ls, const char *set) { - lua_assert(set[2] == '\0'); - if (ls->current == set[0] || ls->current == set[1]) { - save_and_next(ls); - return 1; - } - else return 0; -} - - -/* LUA_NUMBER */ -/* -** this function is quite liberal in what it accepts, as 'luaO_str2num' -** will reject ill-formed numerals. -*/ -static int read_numeral (LexState *ls, SemInfo *seminfo) { - TValue obj; - const char *expo = "Ee"; - int first = ls->current; - lua_assert(lisdigit(ls->current)); - save_and_next(ls); - if (first == '0' && check_next2(ls, "xX")) /* hexadecimal? */ - expo = "Pp"; - for (;;) { - if (check_next2(ls, expo)) /* exponent part? */ - check_next2(ls, "-+"); /* optional exponent sign */ - if (lisxdigit(ls->current)) - save_and_next(ls); - else if (ls->current == '.') - save_and_next(ls); - else break; - } - save(ls, '\0'); - if (luaO_str2num(luaZ_buffer(ls->buff), &obj) == 0) /* format error? */ - lexerror(ls, "malformed number", TK_FLT); - if (ttisinteger(&obj)) { - seminfo->i = ivalue(&obj); - return TK_INT; - } - else { - lua_assert(ttisfloat(&obj)); - seminfo->r = fltvalue(&obj); - return TK_FLT; - } -} - - -/* -** reads a sequence '[=*[' or ']=*]', leaving the last bracket. -** If sequence is well formed, return its number of '='s + 2; otherwise, -** return 1 if there is no '='s or 0 otherwise (an unfinished '[==...'). -*/ -static size_t skip_sep (LexState *ls) { - size_t count = 0; - int s = ls->current; - lua_assert(s == '[' || s == ']'); - save_and_next(ls); - while (ls->current == '=') { - save_and_next(ls); - count++; - } - return (ls->current == s) ? count + 2 - : (count == 0) ? 1 - : 0; - -} - - -static void read_long_string (LexState *ls, SemInfo *seminfo, size_t sep) { - int line = ls->linenumber; /* initial line (for error message) */ - save_and_next(ls); /* skip 2nd '[' */ - if (currIsNewline(ls)) /* string starts with a newline? */ - inclinenumber(ls); /* skip it */ - for (;;) { - switch (ls->current) { - case EOZ: { /* error */ - const char *what = (seminfo ? "string" : "comment"); - const char *msg = luaO_pushfstring(ls->L, - "unfinished long %s (starting at line %d)", what, line); - lexerror(ls, msg, TK_EOS); - break; /* to avoid warnings */ - } - case ']': { - if (skip_sep(ls) == sep) { - save_and_next(ls); /* skip 2nd ']' */ - goto endloop; - } - break; - } - case '\n': case '\r': { - save(ls, '\n'); - inclinenumber(ls); - if (!seminfo) luaZ_resetbuffer(ls->buff); /* avoid wasting space */ - break; - } - default: { - if (seminfo) save_and_next(ls); - else next(ls); - } - } - } endloop: - if (seminfo) - seminfo->ts = luaX_newstring(ls, luaZ_buffer(ls->buff) + sep, - luaZ_bufflen(ls->buff) - 2 * sep); -} - - -static void esccheck (LexState *ls, int c, const char *msg) { - if (!c) { - if (ls->current != EOZ) - save_and_next(ls); /* add current to buffer for error message */ - lexerror(ls, msg, TK_STRING); - } -} - - -static int gethexa (LexState *ls) { - save_and_next(ls); - esccheck (ls, lisxdigit(ls->current), "hexadecimal digit expected"); - return luaO_hexavalue(ls->current); -} - - -static int readhexaesc (LexState *ls) { - int r = gethexa(ls); - r = (r << 4) + gethexa(ls); - luaZ_buffremove(ls->buff, 2); /* remove saved chars from buffer */ - return r; -} - - -static unsigned long readutf8esc (LexState *ls) { - unsigned long r; - int i = 4; /* chars to be removed: '\', 'u', '{', and first digit */ - save_and_next(ls); /* skip 'u' */ - esccheck(ls, ls->current == '{', "missing '{'"); - r = gethexa(ls); /* must have at least one digit */ - while ((save_and_next(ls), lisxdigit(ls->current))) { - i++; - r = (r << 4) + luaO_hexavalue(ls->current); - esccheck(ls, r <= 0x10FFFF, "UTF-8 value too large"); - } - esccheck(ls, ls->current == '}', "missing '}'"); - next(ls); /* skip '}' */ - luaZ_buffremove(ls->buff, i); /* remove saved chars from buffer */ - return r; -} - - -static void utf8esc (LexState *ls) { - char buff[UTF8BUFFSZ]; - int n = luaO_utf8esc(buff, readutf8esc(ls)); - for (; n > 0; n--) /* add 'buff' to string */ - save(ls, buff[UTF8BUFFSZ - n]); -} - - -static int readdecesc (LexState *ls) { - int i; - int r = 0; /* result accumulator */ - for (i = 0; i < 3 && lisdigit(ls->current); i++) { /* read up to 3 digits */ - r = 10*r + ls->current - '0'; - save_and_next(ls); - } - esccheck(ls, r <= UCHAR_MAX, "decimal escape too large"); - luaZ_buffremove(ls->buff, i); /* remove read digits from buffer */ - return r; -} - - -static void read_string (LexState *ls, int del, SemInfo *seminfo) { - save_and_next(ls); /* keep delimiter (for error messages) */ - while (ls->current != del) { - switch (ls->current) { - case EOZ: - lexerror(ls, "unfinished string", TK_EOS); - break; /* to avoid warnings */ - case '\n': - case '\r': - lexerror(ls, "unfinished string", TK_STRING); - break; /* to avoid warnings */ - case '\\': { /* escape sequences */ - int c; /* final character to be saved */ - save_and_next(ls); /* keep '\\' for error messages */ - switch (ls->current) { - case 'a': c = '\a'; goto read_save; - case 'b': c = '\b'; goto read_save; - case 'f': c = '\f'; goto read_save; - case 'n': c = '\n'; goto read_save; - case 'r': c = '\r'; goto read_save; - case 't': c = '\t'; goto read_save; - case 'v': c = '\v'; goto read_save; - case 'x': c = readhexaesc(ls); goto read_save; - case 'u': utf8esc(ls); goto no_save; - case '\n': case '\r': - inclinenumber(ls); c = '\n'; goto only_save; - case '\\': case '\"': case '\'': - c = ls->current; goto read_save; - case EOZ: goto no_save; /* will raise an error next loop */ - case 'z': { /* zap following span of spaces */ - luaZ_buffremove(ls->buff, 1); /* remove '\\' */ - next(ls); /* skip the 'z' */ - while (lisspace(ls->current)) { - if (currIsNewline(ls)) inclinenumber(ls); - else next(ls); - } - goto no_save; - } - default: { - esccheck(ls, lisdigit(ls->current), "invalid escape sequence"); - c = readdecesc(ls); /* digital escape '\ddd' */ - goto only_save; - } - } - read_save: - next(ls); - /* go through */ - only_save: - luaZ_buffremove(ls->buff, 1); /* remove '\\' */ - save(ls, c); - /* go through */ - no_save: break; - } - default: - save_and_next(ls); - } - } - save_and_next(ls); /* skip delimiter */ - seminfo->ts = luaX_newstring(ls, luaZ_buffer(ls->buff) + 1, - luaZ_bufflen(ls->buff) - 2); -} - - -static int llex (LexState *ls, SemInfo *seminfo) { - luaZ_resetbuffer(ls->buff); - for (;;) { - switch (ls->current) { - case '\n': case '\r': { /* line breaks */ - inclinenumber(ls); - break; - } - case ' ': case '\f': case '\t': case '\v': { /* spaces */ - next(ls); - break; - } - case '-': { /* '-' or '--' (comment) */ - next(ls); - if (ls->current != '-') return '-'; - /* else is a comment */ - next(ls); - if (ls->current == '[') { /* long comment? */ - size_t sep = skip_sep(ls); - luaZ_resetbuffer(ls->buff); /* 'skip_sep' may dirty the buffer */ - if (sep >= 2) { - read_long_string(ls, NULL, sep); /* skip long comment */ - luaZ_resetbuffer(ls->buff); /* previous call may dirty the buff. */ - break; - } - } - /* else short comment */ - while (!currIsNewline(ls) && ls->current != EOZ) - next(ls); /* skip until end of line (or end of file) */ - break; - } - case '[': { /* long string or simply '[' */ - size_t sep = skip_sep(ls); - if (sep >= 2) { - read_long_string(ls, seminfo, sep); - return TK_STRING; - } - else if (sep == 0) /* '[=...' missing second bracket */ - lexerror(ls, "invalid long string delimiter", TK_STRING); - return '['; - } - case '=': { - next(ls); - if (check_next1(ls, '=')) return TK_EQ; - else return '='; - } - case '<': { - next(ls); - if (check_next1(ls, '=')) return TK_LE; - else if (check_next1(ls, '<')) return TK_SHL; - else return '<'; - } - case '>': { - next(ls); - if (check_next1(ls, '=')) return TK_GE; - else if (check_next1(ls, '>')) return TK_SHR; - else return '>'; - } - case '/': { - next(ls); - if (check_next1(ls, '/')) return TK_IDIV; - else return '/'; - } - case '~': { - next(ls); - if (check_next1(ls, '=')) return TK_NE; - else return '~'; - } - case ':': { - next(ls); - if (check_next1(ls, ':')) return TK_DBCOLON; - else return ':'; - } - case '"': case '\'': { /* short literal strings */ - read_string(ls, ls->current, seminfo); - return TK_STRING; - } - case '.': { /* '.', '..', '...', or number */ - save_and_next(ls); - if (check_next1(ls, '.')) { - if (check_next1(ls, '.')) - return TK_DOTS; /* '...' */ - else return TK_CONCAT; /* '..' */ - } - else if (!lisdigit(ls->current)) return '.'; - else return read_numeral(ls, seminfo); - } - case '0': case '1': case '2': case '3': case '4': - case '5': case '6': case '7': case '8': case '9': { - return read_numeral(ls, seminfo); - } - case EOZ: { - return TK_EOS; - } - default: { - if (lislalpha(ls->current)) { /* identifier or reserved word? */ - TString *ts; - do { - save_and_next(ls); - } while (lislalnum(ls->current)); - ts = luaX_newstring(ls, luaZ_buffer(ls->buff), - luaZ_bufflen(ls->buff)); - seminfo->ts = ts; - if (isreserved(ts)) /* reserved word? */ - return ts->extra - 1 + FIRST_RESERVED; - else { - return TK_NAME; - } - } - else { /* single-char tokens (+ - / ...) */ - int c = ls->current; - next(ls); - return c; - } - } - } - } -} - - -void luaX_next (LexState *ls) { - ls->lastline = ls->linenumber; - if (ls->lookahead.token != TK_EOS) { /* is there a look-ahead token? */ - ls->t = ls->lookahead; /* use this one */ - ls->lookahead.token = TK_EOS; /* and discharge it */ - } - else - ls->t.token = llex(ls, &ls->t.seminfo); /* read next token */ -} - - -int luaX_lookahead (LexState *ls) { - lua_assert(ls->lookahead.token == TK_EOS); - ls->lookahead.token = llex(ls, &ls->lookahead.seminfo); - return ls->lookahead.token; -} - diff --git a/lib/lua-5.3/src/llex.h b/lib/lua-5.3/src/llex.h deleted file mode 100644 index 2ed0af6..0000000 --- a/lib/lua-5.3/src/llex.h +++ /dev/null @@ -1,85 +0,0 @@ -/* -** $Id: llex.h,v 1.79.1.1 2017/04/19 17:20:42 roberto Exp $ -** Lexical Analyzer -** See Copyright Notice in lua.h -*/ - -#ifndef llex_h -#define llex_h - -#include "lobject.h" -#include "lzio.h" - - -#define FIRST_RESERVED 257 - - -#if !defined(LUA_ENV) -#define LUA_ENV "_ENV" -#endif - - -/* -* WARNING: if you change the order of this enumeration, -* grep "ORDER RESERVED" -*/ -enum RESERVED { - /* terminal symbols denoted by reserved words */ - TK_AND = FIRST_RESERVED, TK_BREAK, - TK_DO, TK_ELSE, TK_ELSEIF, TK_END, TK_FALSE, TK_FOR, TK_FUNCTION, - TK_GOTO, TK_IF, TK_IN, TK_LOCAL, TK_NIL, TK_NOT, TK_OR, TK_REPEAT, - TK_RETURN, TK_THEN, TK_TRUE, TK_UNTIL, TK_WHILE, - /* other terminal symbols */ - TK_IDIV, TK_CONCAT, TK_DOTS, TK_EQ, TK_GE, TK_LE, TK_NE, - TK_SHL, TK_SHR, - TK_DBCOLON, TK_EOS, - TK_FLT, TK_INT, TK_NAME, TK_STRING -}; - -/* number of reserved words */ -#define NUM_RESERVED (cast(int, TK_WHILE-FIRST_RESERVED+1)) - - -typedef union { - lua_Number r; - lua_Integer i; - TString *ts; -} SemInfo; /* semantics information */ - - -typedef struct Token { - int token; - SemInfo seminfo; -} Token; - - -/* state of the lexer plus state of the parser when shared by all - functions */ -typedef struct LexState { - int current; /* current character (charint) */ - int linenumber; /* input line counter */ - int lastline; /* line of last token 'consumed' */ - Token t; /* current token */ - Token lookahead; /* look ahead token */ - struct FuncState *fs; /* current function (parser) */ - struct lua_State *L; - ZIO *z; /* input stream */ - Mbuffer *buff; /* buffer for tokens */ - Table *h; /* to avoid collection/reuse strings */ - struct Dyndata *dyd; /* dynamic structures used by the parser */ - TString *source; /* current source name */ - TString *envn; /* environment variable name */ -} LexState; - - -LUAI_FUNC void luaX_init (lua_State *L); -LUAI_FUNC void luaX_setinput (lua_State *L, LexState *ls, ZIO *z, - TString *source, int firstchar); -LUAI_FUNC TString *luaX_newstring (LexState *ls, const char *str, size_t l); -LUAI_FUNC void luaX_next (LexState *ls); -LUAI_FUNC int luaX_lookahead (LexState *ls); -LUAI_FUNC l_noret luaX_syntaxerror (LexState *ls, const char *s); -LUAI_FUNC const char *luaX_token2str (LexState *ls, int token); - - -#endif diff --git a/lib/lua-5.3/src/llimits.h b/lib/lua-5.3/src/llimits.h deleted file mode 100644 index d1036f6..0000000 --- a/lib/lua-5.3/src/llimits.h +++ /dev/null @@ -1,323 +0,0 @@ -/* -** $Id: llimits.h,v 1.141.1.1 2017/04/19 17:20:42 roberto Exp $ -** Limits, basic types, and some other 'installation-dependent' definitions -** See Copyright Notice in lua.h -*/ - -#ifndef llimits_h -#define llimits_h - - -#include -#include - - -#include "lua.h" - -/* -** 'lu_mem' and 'l_mem' are unsigned/signed integers big enough to count -** the total memory used by Lua (in bytes). Usually, 'size_t' and -** 'ptrdiff_t' should work, but we use 'long' for 16-bit machines. -*/ -#if defined(LUAI_MEM) /* { external definitions? */ -typedef LUAI_UMEM lu_mem; -typedef LUAI_MEM l_mem; -#elif LUAI_BITSINT >= 32 /* }{ */ -typedef size_t lu_mem; -typedef ptrdiff_t l_mem; -#else /* 16-bit ints */ /* }{ */ -typedef unsigned long lu_mem; -typedef long l_mem; -#endif /* } */ - - -/* chars used as small naturals (so that 'char' is reserved for characters) */ -typedef unsigned char lu_byte; - - -/* maximum value for size_t */ -#define MAX_SIZET ((size_t)(~(size_t)0)) - -/* maximum size visible for Lua (must be representable in a lua_Integer */ -#define MAX_SIZE (sizeof(size_t) < sizeof(lua_Integer) ? MAX_SIZET \ - : (size_t)(LUA_MAXINTEGER)) - - -#define MAX_LUMEM ((lu_mem)(~(lu_mem)0)) - -#define MAX_LMEM ((l_mem)(MAX_LUMEM >> 1)) - - -#define MAX_INT INT_MAX /* maximum value of an int */ - - -/* -** conversion of pointer to unsigned integer: -** this is for hashing only; there is no problem if the integer -** cannot hold the whole pointer value -*/ -#define point2uint(p) ((unsigned int)((size_t)(p) & UINT_MAX)) - - - -/* type to ensure maximum alignment */ -#if defined(LUAI_USER_ALIGNMENT_T) -typedef LUAI_USER_ALIGNMENT_T L_Umaxalign; -#else -typedef union { - lua_Number n; - double u; - void *s; - lua_Integer i; - long l; -} L_Umaxalign; -#endif - - - -/* types of 'usual argument conversions' for lua_Number and lua_Integer */ -typedef LUAI_UACNUMBER l_uacNumber; -typedef LUAI_UACINT l_uacInt; - - -/* internal assertions for in-house debugging */ -#if defined(lua_assert) -#define check_exp(c,e) (lua_assert(c), (e)) -/* to avoid problems with conditions too long */ -#define lua_longassert(c) ((c) ? (void)0 : lua_assert(0)) -#else -#define lua_assert(c) ((void)0) -#define check_exp(c,e) (e) -#define lua_longassert(c) ((void)0) -#endif - -/* -** assertion for checking API calls -*/ -#if !defined(luai_apicheck) -#define luai_apicheck(l,e) lua_assert(e) -#endif - -#define api_check(l,e,msg) luai_apicheck(l,(e) && msg) - - -/* macro to avoid warnings about unused variables */ -#if !defined(UNUSED) -#define UNUSED(x) ((void)(x)) -#endif - - -/* type casts (a macro highlights casts in the code) */ -#define cast(t, exp) ((t)(exp)) - -#define cast_void(i) cast(void, (i)) -#define cast_byte(i) cast(lu_byte, (i)) -#define cast_num(i) cast(lua_Number, (i)) -#define cast_int(i) cast(int, (i)) -#define cast_uchar(i) cast(unsigned char, (i)) - - -/* cast a signed lua_Integer to lua_Unsigned */ -#if !defined(l_castS2U) -#define l_castS2U(i) ((lua_Unsigned)(i)) -#endif - -/* -** cast a lua_Unsigned to a signed lua_Integer; this cast is -** not strict ISO C, but two-complement architectures should -** work fine. -*/ -#if !defined(l_castU2S) -#define l_castU2S(i) ((lua_Integer)(i)) -#endif - - -/* -** non-return type -*/ -#if defined(__GNUC__) -#define l_noret void __attribute__((noreturn)) -#elif defined(_MSC_VER) && _MSC_VER >= 1200 -#define l_noret void __declspec(noreturn) -#else -#define l_noret void -#endif - - - -/* -** maximum depth for nested C calls and syntactical nested non-terminals -** in a program. (Value must fit in an unsigned short int.) -*/ -#if !defined(LUAI_MAXCCALLS) -#define LUAI_MAXCCALLS 200 -#endif - - - -/* -** type for virtual-machine instructions; -** must be an unsigned with (at least) 4 bytes (see details in lopcodes.h) -*/ -#if LUAI_BITSINT >= 32 -typedef unsigned int Instruction; -#else -typedef unsigned long Instruction; -#endif - - - -/* -** Maximum length for short strings, that is, strings that are -** internalized. (Cannot be smaller than reserved words or tags for -** metamethods, as these strings must be internalized; -** #("function") = 8, #("__newindex") = 10.) -*/ -#if !defined(LUAI_MAXSHORTLEN) -#define LUAI_MAXSHORTLEN 40 -#endif - - -/* -** Initial size for the string table (must be power of 2). -** The Lua core alone registers ~50 strings (reserved words + -** metaevent keys + a few others). Libraries would typically add -** a few dozens more. -*/ -#if !defined(MINSTRTABSIZE) -#define MINSTRTABSIZE 128 -#endif - - -/* -** Size of cache for strings in the API. 'N' is the number of -** sets (better be a prime) and "M" is the size of each set (M == 1 -** makes a direct cache.) -*/ -#if !defined(STRCACHE_N) -#define STRCACHE_N 53 -#define STRCACHE_M 2 -#endif - - -/* minimum size for string buffer */ -#if !defined(LUA_MINBUFFER) -#define LUA_MINBUFFER 32 -#endif - - -/* -** macros that are executed whenever program enters the Lua core -** ('lua_lock') and leaves the core ('lua_unlock') -*/ -#if !defined(lua_lock) -#define lua_lock(L) ((void) 0) -#define lua_unlock(L) ((void) 0) -#endif - -/* -** macro executed during Lua functions at points where the -** function can yield. -*/ -#if !defined(luai_threadyield) -#define luai_threadyield(L) {lua_unlock(L); lua_lock(L);} -#endif - - -/* -** these macros allow user-specific actions on threads when you defined -** LUAI_EXTRASPACE and need to do something extra when a thread is -** created/deleted/resumed/yielded. -*/ -#if !defined(luai_userstateopen) -#define luai_userstateopen(L) ((void)L) -#endif - -#if !defined(luai_userstateclose) -#define luai_userstateclose(L) ((void)L) -#endif - -#if !defined(luai_userstatethread) -#define luai_userstatethread(L,L1) ((void)L) -#endif - -#if !defined(luai_userstatefree) -#define luai_userstatefree(L,L1) ((void)L) -#endif - -#if !defined(luai_userstateresume) -#define luai_userstateresume(L,n) ((void)L) -#endif - -#if !defined(luai_userstateyield) -#define luai_userstateyield(L,n) ((void)L) -#endif - - - -/* -** The luai_num* macros define the primitive operations over numbers. -*/ - -/* floor division (defined as 'floor(a/b)') */ -#if !defined(luai_numidiv) -#define luai_numidiv(L,a,b) ((void)L, l_floor(luai_numdiv(L,a,b))) -#endif - -/* float division */ -#if !defined(luai_numdiv) -#define luai_numdiv(L,a,b) ((a)/(b)) -#endif - -/* -** modulo: defined as 'a - floor(a/b)*b'; this definition gives NaN when -** 'b' is huge, but the result should be 'a'. 'fmod' gives the result of -** 'a - trunc(a/b)*b', and therefore must be corrected when 'trunc(a/b) -** ~= floor(a/b)'. That happens when the division has a non-integer -** negative result, which is equivalent to the test below. -*/ -#if !defined(luai_nummod) -#define luai_nummod(L,a,b,m) \ - { (m) = l_mathop(fmod)(a,b); if ((m)*(b) < 0) (m) += (b); } -#endif - -/* exponentiation */ -#if !defined(luai_numpow) -#define luai_numpow(L,a,b) ((void)L, l_mathop(pow)(a,b)) -#endif - -/* the others are quite standard operations */ -#if !defined(luai_numadd) -#define luai_numadd(L,a,b) ((a)+(b)) -#define luai_numsub(L,a,b) ((a)-(b)) -#define luai_nummul(L,a,b) ((a)*(b)) -#define luai_numunm(L,a) (-(a)) -#define luai_numeq(a,b) ((a)==(b)) -#define luai_numlt(a,b) ((a)<(b)) -#define luai_numle(a,b) ((a)<=(b)) -#define luai_numisnan(a) (!luai_numeq((a), (a))) -#endif - - - - - -/* -** macro to control inclusion of some hard tests on stack reallocation -*/ -#if !defined(HARDSTACKTESTS) -#define condmovestack(L,pre,pos) ((void)0) -#else -/* realloc stack keeping its size */ -#define condmovestack(L,pre,pos) \ - { int sz_ = (L)->stacksize; pre; luaD_reallocstack((L), sz_); pos; } -#endif - -#if !defined(HARDMEMTESTS) -#define condchangemem(L,pre,pos) ((void)0) -#else -#define condchangemem(L,pre,pos) \ - { if (G(L)->gcrunning) { pre; luaC_fullgc(L, 0); pos; } } -#endif - -#endif diff --git a/lib/lua-5.3/src/lmathlib.c b/lib/lua-5.3/src/lmathlib.c deleted file mode 100644 index 7ef7e59..0000000 --- a/lib/lua-5.3/src/lmathlib.c +++ /dev/null @@ -1,410 +0,0 @@ -/* -** $Id: lmathlib.c,v 1.119.1.1 2017/04/19 17:20:42 roberto Exp $ -** Standard mathematical library -** See Copyright Notice in lua.h -*/ - -#define lmathlib_c -#define LUA_LIB - -#include "lprefix.h" - - -#include -#include - -#include "lua.h" - -#include "lauxlib.h" -#include "lualib.h" - - -#undef PI -#define PI (l_mathop(3.141592653589793238462643383279502884)) - - -#if !defined(l_rand) /* { */ -#if defined(LUA_USE_POSIX) -#define l_rand() random() -#define l_srand(x) srandom(x) -#define L_RANDMAX 2147483647 /* (2^31 - 1), following POSIX */ -#else -#define l_rand() rand() -#define l_srand(x) srand(x) -#define L_RANDMAX RAND_MAX -#endif -#endif /* } */ - - -static int math_abs (lua_State *L) { - if (lua_isinteger(L, 1)) { - lua_Integer n = lua_tointeger(L, 1); - if (n < 0) n = (lua_Integer)(0u - (lua_Unsigned)n); - lua_pushinteger(L, n); - } - else - lua_pushnumber(L, l_mathop(fabs)(luaL_checknumber(L, 1))); - return 1; -} - -static int math_sin (lua_State *L) { - lua_pushnumber(L, l_mathop(sin)(luaL_checknumber(L, 1))); - return 1; -} - -static int math_cos (lua_State *L) { - lua_pushnumber(L, l_mathop(cos)(luaL_checknumber(L, 1))); - return 1; -} - -static int math_tan (lua_State *L) { - lua_pushnumber(L, l_mathop(tan)(luaL_checknumber(L, 1))); - return 1; -} - -static int math_asin (lua_State *L) { - lua_pushnumber(L, l_mathop(asin)(luaL_checknumber(L, 1))); - return 1; -} - -static int math_acos (lua_State *L) { - lua_pushnumber(L, l_mathop(acos)(luaL_checknumber(L, 1))); - return 1; -} - -static int math_atan (lua_State *L) { - lua_Number y = luaL_checknumber(L, 1); - lua_Number x = luaL_optnumber(L, 2, 1); - lua_pushnumber(L, l_mathop(atan2)(y, x)); - return 1; -} - - -static int math_toint (lua_State *L) { - int valid; - lua_Integer n = lua_tointegerx(L, 1, &valid); - if (valid) - lua_pushinteger(L, n); - else { - luaL_checkany(L, 1); - lua_pushnil(L); /* value is not convertible to integer */ - } - return 1; -} - - -static void pushnumint (lua_State *L, lua_Number d) { - lua_Integer n; - if (lua_numbertointeger(d, &n)) /* does 'd' fit in an integer? */ - lua_pushinteger(L, n); /* result is integer */ - else - lua_pushnumber(L, d); /* result is float */ -} - - -static int math_floor (lua_State *L) { - if (lua_isinteger(L, 1)) - lua_settop(L, 1); /* integer is its own floor */ - else { - lua_Number d = l_mathop(floor)(luaL_checknumber(L, 1)); - pushnumint(L, d); - } - return 1; -} - - -static int math_ceil (lua_State *L) { - if (lua_isinteger(L, 1)) - lua_settop(L, 1); /* integer is its own ceil */ - else { - lua_Number d = l_mathop(ceil)(luaL_checknumber(L, 1)); - pushnumint(L, d); - } - return 1; -} - - -static int math_fmod (lua_State *L) { - if (lua_isinteger(L, 1) && lua_isinteger(L, 2)) { - lua_Integer d = lua_tointeger(L, 2); - if ((lua_Unsigned)d + 1u <= 1u) { /* special cases: -1 or 0 */ - luaL_argcheck(L, d != 0, 2, "zero"); - lua_pushinteger(L, 0); /* avoid overflow with 0x80000... / -1 */ - } - else - lua_pushinteger(L, lua_tointeger(L, 1) % d); - } - else - lua_pushnumber(L, l_mathop(fmod)(luaL_checknumber(L, 1), - luaL_checknumber(L, 2))); - return 1; -} - - -/* -** next function does not use 'modf', avoiding problems with 'double*' -** (which is not compatible with 'float*') when lua_Number is not -** 'double'. -*/ -static int math_modf (lua_State *L) { - if (lua_isinteger(L ,1)) { - lua_settop(L, 1); /* number is its own integer part */ - lua_pushnumber(L, 0); /* no fractional part */ - } - else { - lua_Number n = luaL_checknumber(L, 1); - /* integer part (rounds toward zero) */ - lua_Number ip = (n < 0) ? l_mathop(ceil)(n) : l_mathop(floor)(n); - pushnumint(L, ip); - /* fractional part (test needed for inf/-inf) */ - lua_pushnumber(L, (n == ip) ? l_mathop(0.0) : (n - ip)); - } - return 2; -} - - -static int math_sqrt (lua_State *L) { - lua_pushnumber(L, l_mathop(sqrt)(luaL_checknumber(L, 1))); - return 1; -} - - -static int math_ult (lua_State *L) { - lua_Integer a = luaL_checkinteger(L, 1); - lua_Integer b = luaL_checkinteger(L, 2); - lua_pushboolean(L, (lua_Unsigned)a < (lua_Unsigned)b); - return 1; -} - -static int math_log (lua_State *L) { - lua_Number x = luaL_checknumber(L, 1); - lua_Number res; - if (lua_isnoneornil(L, 2)) - res = l_mathop(log)(x); - else { - lua_Number base = luaL_checknumber(L, 2); -#if !defined(LUA_USE_C89) - if (base == l_mathop(2.0)) - res = l_mathop(log2)(x); else -#endif - if (base == l_mathop(10.0)) - res = l_mathop(log10)(x); - else - res = l_mathop(log)(x)/l_mathop(log)(base); - } - lua_pushnumber(L, res); - return 1; -} - -static int math_exp (lua_State *L) { - lua_pushnumber(L, l_mathop(exp)(luaL_checknumber(L, 1))); - return 1; -} - -static int math_deg (lua_State *L) { - lua_pushnumber(L, luaL_checknumber(L, 1) * (l_mathop(180.0) / PI)); - return 1; -} - -static int math_rad (lua_State *L) { - lua_pushnumber(L, luaL_checknumber(L, 1) * (PI / l_mathop(180.0))); - return 1; -} - - -static int math_min (lua_State *L) { - int n = lua_gettop(L); /* number of arguments */ - int imin = 1; /* index of current minimum value */ - int i; - luaL_argcheck(L, n >= 1, 1, "value expected"); - for (i = 2; i <= n; i++) { - if (lua_compare(L, i, imin, LUA_OPLT)) - imin = i; - } - lua_pushvalue(L, imin); - return 1; -} - - -static int math_max (lua_State *L) { - int n = lua_gettop(L); /* number of arguments */ - int imax = 1; /* index of current maximum value */ - int i; - luaL_argcheck(L, n >= 1, 1, "value expected"); - for (i = 2; i <= n; i++) { - if (lua_compare(L, imax, i, LUA_OPLT)) - imax = i; - } - lua_pushvalue(L, imax); - return 1; -} - -/* -** This function uses 'double' (instead of 'lua_Number') to ensure that -** all bits from 'l_rand' can be represented, and that 'RANDMAX + 1.0' -** will keep full precision (ensuring that 'r' is always less than 1.0.) -*/ -static int math_random (lua_State *L) { - lua_Integer low, up; - double r = (double)l_rand() * (1.0 / ((double)L_RANDMAX + 1.0)); - switch (lua_gettop(L)) { /* check number of arguments */ - case 0: { /* no arguments */ - lua_pushnumber(L, (lua_Number)r); /* Number between 0 and 1 */ - return 1; - } - case 1: { /* only upper limit */ - low = 1; - up = luaL_checkinteger(L, 1); - break; - } - case 2: { /* lower and upper limits */ - low = luaL_checkinteger(L, 1); - up = luaL_checkinteger(L, 2); - break; - } - default: return luaL_error(L, "wrong number of arguments"); - } - /* random integer in the interval [low, up] */ - luaL_argcheck(L, low <= up, 1, "interval is empty"); - luaL_argcheck(L, low >= 0 || up <= LUA_MAXINTEGER + low, 1, - "interval too large"); - r *= (double)(up - low) + 1.0; - lua_pushinteger(L, (lua_Integer)r + low); - return 1; -} - - -static int math_randomseed (lua_State *L) { - l_srand((unsigned int)(lua_Integer)luaL_checknumber(L, 1)); - (void)l_rand(); /* discard first value to avoid undesirable correlations */ - return 0; -} - - -static int math_type (lua_State *L) { - if (lua_type(L, 1) == LUA_TNUMBER) { - if (lua_isinteger(L, 1)) - lua_pushliteral(L, "integer"); - else - lua_pushliteral(L, "float"); - } - else { - luaL_checkany(L, 1); - lua_pushnil(L); - } - return 1; -} - - -/* -** {================================================================== -** Deprecated functions (for compatibility only) -** =================================================================== -*/ -#if defined(LUA_COMPAT_MATHLIB) - -static int math_cosh (lua_State *L) { - lua_pushnumber(L, l_mathop(cosh)(luaL_checknumber(L, 1))); - return 1; -} - -static int math_sinh (lua_State *L) { - lua_pushnumber(L, l_mathop(sinh)(luaL_checknumber(L, 1))); - return 1; -} - -static int math_tanh (lua_State *L) { - lua_pushnumber(L, l_mathop(tanh)(luaL_checknumber(L, 1))); - return 1; -} - -static int math_pow (lua_State *L) { - lua_Number x = luaL_checknumber(L, 1); - lua_Number y = luaL_checknumber(L, 2); - lua_pushnumber(L, l_mathop(pow)(x, y)); - return 1; -} - -static int math_frexp (lua_State *L) { - int e; - lua_pushnumber(L, l_mathop(frexp)(luaL_checknumber(L, 1), &e)); - lua_pushinteger(L, e); - return 2; -} - -static int math_ldexp (lua_State *L) { - lua_Number x = luaL_checknumber(L, 1); - int ep = (int)luaL_checkinteger(L, 2); - lua_pushnumber(L, l_mathop(ldexp)(x, ep)); - return 1; -} - -static int math_log10 (lua_State *L) { - lua_pushnumber(L, l_mathop(log10)(luaL_checknumber(L, 1))); - return 1; -} - -#endif -/* }================================================================== */ - - - -static const luaL_Reg mathlib[] = { - {"abs", math_abs}, - {"acos", math_acos}, - {"asin", math_asin}, - {"atan", math_atan}, - {"ceil", math_ceil}, - {"cos", math_cos}, - {"deg", math_deg}, - {"exp", math_exp}, - {"tointeger", math_toint}, - {"floor", math_floor}, - {"fmod", math_fmod}, - {"ult", math_ult}, - {"log", math_log}, - {"max", math_max}, - {"min", math_min}, - {"modf", math_modf}, - {"rad", math_rad}, - {"random", math_random}, - {"randomseed", math_randomseed}, - {"sin", math_sin}, - {"sqrt", math_sqrt}, - {"tan", math_tan}, - {"type", math_type}, -#if defined(LUA_COMPAT_MATHLIB) - {"atan2", math_atan}, - {"cosh", math_cosh}, - {"sinh", math_sinh}, - {"tanh", math_tanh}, - {"pow", math_pow}, - {"frexp", math_frexp}, - {"ldexp", math_ldexp}, - {"log10", math_log10}, -#endif - /* placeholders */ - {"pi", NULL}, - {"huge", NULL}, - {"maxinteger", NULL}, - {"mininteger", NULL}, - {NULL, NULL} -}; - - -/* -** Open math library -*/ -LUAMOD_API int luaopen_math (lua_State *L) { - luaL_newlib(L, mathlib); - lua_pushnumber(L, PI); - lua_setfield(L, -2, "pi"); - lua_pushnumber(L, (lua_Number)HUGE_VAL); - lua_setfield(L, -2, "huge"); - lua_pushinteger(L, LUA_MAXINTEGER); - lua_setfield(L, -2, "maxinteger"); - lua_pushinteger(L, LUA_MININTEGER); - lua_setfield(L, -2, "mininteger"); - return 1; -} - diff --git a/lib/lua-5.3/src/lmem.c b/lib/lua-5.3/src/lmem.c deleted file mode 100644 index 0241cc3..0000000 --- a/lib/lua-5.3/src/lmem.c +++ /dev/null @@ -1,100 +0,0 @@ -/* -** $Id: lmem.c,v 1.91.1.1 2017/04/19 17:20:42 roberto Exp $ -** Interface to Memory Manager -** See Copyright Notice in lua.h -*/ - -#define lmem_c -#define LUA_CORE - -#include "lprefix.h" - - -#include - -#include "lua.h" - -#include "ldebug.h" -#include "ldo.h" -#include "lgc.h" -#include "lmem.h" -#include "lobject.h" -#include "lstate.h" - - - -/* -** About the realloc function: -** void * frealloc (void *ud, void *ptr, size_t osize, size_t nsize); -** ('osize' is the old size, 'nsize' is the new size) -** -** * frealloc(ud, NULL, x, s) creates a new block of size 's' (no -** matter 'x'). -** -** * frealloc(ud, p, x, 0) frees the block 'p' -** (in this specific case, frealloc must return NULL); -** particularly, frealloc(ud, NULL, 0, 0) does nothing -** (which is equivalent to free(NULL) in ISO C) -** -** frealloc returns NULL if it cannot create or reallocate the area -** (any reallocation to an equal or smaller size cannot fail!) -*/ - - - -#define MINSIZEARRAY 4 - - -void *luaM_growaux_ (lua_State *L, void *block, int *size, size_t size_elems, - int limit, const char *what) { - void *newblock; - int newsize; - if (*size >= limit/2) { /* cannot double it? */ - if (*size >= limit) /* cannot grow even a little? */ - luaG_runerror(L, "too many %s (limit is %d)", what, limit); - newsize = limit; /* still have at least one free place */ - } - else { - newsize = (*size)*2; - if (newsize < MINSIZEARRAY) - newsize = MINSIZEARRAY; /* minimum size */ - } - newblock = luaM_reallocv(L, block, *size, newsize, size_elems); - *size = newsize; /* update only when everything else is OK */ - return newblock; -} - - -l_noret luaM_toobig (lua_State *L) { - luaG_runerror(L, "memory allocation error: block too big"); -} - - - -/* -** generic allocation routine. -*/ -void *luaM_realloc_ (lua_State *L, void *block, size_t osize, size_t nsize) { - void *newblock; - global_State *g = G(L); - size_t realosize = (block) ? osize : 0; - lua_assert((realosize == 0) == (block == NULL)); -#if defined(HARDMEMTESTS) - if (nsize > realosize && g->gcrunning) - luaC_fullgc(L, 1); /* force a GC whenever possible */ -#endif - newblock = (*g->frealloc)(g->ud, block, osize, nsize); - if (newblock == NULL && nsize > 0) { - lua_assert(nsize > realosize); /* cannot fail when shrinking a block */ - if (g->version) { /* is state fully built? */ - luaC_fullgc(L, 1); /* try to free some memory... */ - newblock = (*g->frealloc)(g->ud, block, osize, nsize); /* try again */ - } - if (newblock == NULL) - luaD_throw(L, LUA_ERRMEM); - } - lua_assert((nsize == 0) == (newblock == NULL)); - g->GCdebt = (g->GCdebt + nsize) - realosize; - return newblock; -} - diff --git a/lib/lua-5.3/src/lmem.h b/lib/lua-5.3/src/lmem.h deleted file mode 100644 index 357b1e4..0000000 --- a/lib/lua-5.3/src/lmem.h +++ /dev/null @@ -1,69 +0,0 @@ -/* -** $Id: lmem.h,v 1.43.1.1 2017/04/19 17:20:42 roberto Exp $ -** Interface to Memory Manager -** See Copyright Notice in lua.h -*/ - -#ifndef lmem_h -#define lmem_h - - -#include - -#include "llimits.h" -#include "lua.h" - - -/* -** This macro reallocs a vector 'b' from 'on' to 'n' elements, where -** each element has size 'e'. In case of arithmetic overflow of the -** product 'n'*'e', it raises an error (calling 'luaM_toobig'). Because -** 'e' is always constant, it avoids the runtime division MAX_SIZET/(e). -** -** (The macro is somewhat complex to avoid warnings: The 'sizeof' -** comparison avoids a runtime comparison when overflow cannot occur. -** The compiler should be able to optimize the real test by itself, but -** when it does it, it may give a warning about "comparison is always -** false due to limited range of data type"; the +1 tricks the compiler, -** avoiding this warning but also this optimization.) -*/ -#define luaM_reallocv(L,b,on,n,e) \ - (((sizeof(n) >= sizeof(size_t) && cast(size_t, (n)) + 1 > MAX_SIZET/(e)) \ - ? luaM_toobig(L) : cast_void(0)) , \ - luaM_realloc_(L, (b), (on)*(e), (n)*(e))) - -/* -** Arrays of chars do not need any test -*/ -#define luaM_reallocvchar(L,b,on,n) \ - cast(char *, luaM_realloc_(L, (b), (on)*sizeof(char), (n)*sizeof(char))) - -#define luaM_freemem(L, b, s) luaM_realloc_(L, (b), (s), 0) -#define luaM_free(L, b) luaM_realloc_(L, (b), sizeof(*(b)), 0) -#define luaM_freearray(L, b, n) luaM_realloc_(L, (b), (n)*sizeof(*(b)), 0) - -#define luaM_malloc(L,s) luaM_realloc_(L, NULL, 0, (s)) -#define luaM_new(L,t) cast(t *, luaM_malloc(L, sizeof(t))) -#define luaM_newvector(L,n,t) \ - cast(t *, luaM_reallocv(L, NULL, 0, n, sizeof(t))) - -#define luaM_newobject(L,tag,s) luaM_realloc_(L, NULL, tag, (s)) - -#define luaM_growvector(L,v,nelems,size,t,limit,e) \ - if ((nelems)+1 > (size)) \ - ((v)=cast(t *, luaM_growaux_(L,v,&(size),sizeof(t),limit,e))) - -#define luaM_reallocvector(L, v,oldn,n,t) \ - ((v)=cast(t *, luaM_reallocv(L, v, oldn, n, sizeof(t)))) - -LUAI_FUNC l_noret luaM_toobig (lua_State *L); - -/* not to be called directly */ -LUAI_FUNC void *luaM_realloc_ (lua_State *L, void *block, size_t oldsize, - size_t size); -LUAI_FUNC void *luaM_growaux_ (lua_State *L, void *block, int *size, - size_t size_elem, int limit, - const char *what); - -#endif - diff --git a/lib/lua-5.3/src/loadlib.c b/lib/lua-5.3/src/loadlib.c deleted file mode 100644 index 45f44d3..0000000 --- a/lib/lua-5.3/src/loadlib.c +++ /dev/null @@ -1,790 +0,0 @@ -/* -** $Id: loadlib.c,v 1.130.1.1 2017/04/19 17:20:42 roberto Exp $ -** Dynamic library loader for Lua -** See Copyright Notice in lua.h -** -** This module contains an implementation of loadlib for Unix systems -** that have dlfcn, an implementation for Windows, and a stub for other -** systems. -*/ - -#define loadlib_c -#define LUA_LIB - -#include "lprefix.h" - - -#include -#include -#include - -#include "lua.h" - -#include "lauxlib.h" -#include "lualib.h" - - -/* -** LUA_IGMARK is a mark to ignore all before it when building the -** luaopen_ function name. -*/ -#if !defined (LUA_IGMARK) -#define LUA_IGMARK "-" -#endif - - -/* -** LUA_CSUBSEP is the character that replaces dots in submodule names -** when searching for a C loader. -** LUA_LSUBSEP is the character that replaces dots in submodule names -** when searching for a Lua loader. -*/ -#if !defined(LUA_CSUBSEP) -#define LUA_CSUBSEP LUA_DIRSEP -#endif - -#if !defined(LUA_LSUBSEP) -#define LUA_LSUBSEP LUA_DIRSEP -#endif - - -/* prefix for open functions in C libraries */ -#define LUA_POF "luaopen_" - -/* separator for open functions in C libraries */ -#define LUA_OFSEP "_" - - -/* -** unique key for table in the registry that keeps handles -** for all loaded C libraries -*/ -static const int CLIBS = 0; - -#define LIB_FAIL "open" - - -#define setprogdir(L) ((void)0) - - -/* -** system-dependent functions -*/ - -/* -** unload library 'lib' -*/ -static void lsys_unloadlib (void *lib); - -/* -** load C library in file 'path'. If 'seeglb', load with all names in -** the library global. -** Returns the library; in case of error, returns NULL plus an -** error string in the stack. -*/ -static void *lsys_load (lua_State *L, const char *path, int seeglb); - -/* -** Try to find a function named 'sym' in library 'lib'. -** Returns the function; in case of error, returns NULL plus an -** error string in the stack. -*/ -static lua_CFunction lsys_sym (lua_State *L, void *lib, const char *sym); - - - - -#if defined(LUA_USE_DLOPEN) /* { */ -/* -** {======================================================================== -** This is an implementation of loadlib based on the dlfcn interface. -** The dlfcn interface is available in Linux, SunOS, Solaris, IRIX, FreeBSD, -** NetBSD, AIX 4.2, HPUX 11, and probably most other Unix flavors, at least -** as an emulation layer on top of native functions. -** ========================================================================= -*/ - -#include - -/* -** Macro to convert pointer-to-void* to pointer-to-function. This cast -** is undefined according to ISO C, but POSIX assumes that it works. -** (The '__extension__' in gnu compilers is only to avoid warnings.) -*/ -#if defined(__GNUC__) -#define cast_func(p) (__extension__ (lua_CFunction)(p)) -#else -#define cast_func(p) ((lua_CFunction)(p)) -#endif - - -static void lsys_unloadlib (void *lib) { - dlclose(lib); -} - - -static void *lsys_load (lua_State *L, const char *path, int seeglb) { - void *lib = dlopen(path, RTLD_NOW | (seeglb ? RTLD_GLOBAL : RTLD_LOCAL)); - if (lib == NULL) lua_pushstring(L, dlerror()); - return lib; -} - - -static lua_CFunction lsys_sym (lua_State *L, void *lib, const char *sym) { - lua_CFunction f = cast_func(dlsym(lib, sym)); - if (f == NULL) lua_pushstring(L, dlerror()); - return f; -} - -/* }====================================================== */ - - - -#elif defined(LUA_DL_DLL) /* }{ */ -/* -** {====================================================================== -** This is an implementation of loadlib for Windows using native functions. -** ======================================================================= -*/ - -#include - - -/* -** optional flags for LoadLibraryEx -*/ -#if !defined(LUA_LLE_FLAGS) -#define LUA_LLE_FLAGS 0 -#endif - - -#undef setprogdir - - -/* -** Replace in the path (on the top of the stack) any occurrence -** of LUA_EXEC_DIR with the executable's path. -*/ -static void setprogdir (lua_State *L) { - char buff[MAX_PATH + 1]; - char *lb; - DWORD nsize = sizeof(buff)/sizeof(char); - DWORD n = GetModuleFileNameA(NULL, buff, nsize); /* get exec. name */ - if (n == 0 || n == nsize || (lb = strrchr(buff, '\\')) == NULL) - luaL_error(L, "unable to get ModuleFileName"); - else { - *lb = '\0'; /* cut name on the last '\\' to get the path */ - luaL_gsub(L, lua_tostring(L, -1), LUA_EXEC_DIR, buff); - lua_remove(L, -2); /* remove original string */ - } -} - - - - -static void pusherror (lua_State *L) { - int error = GetLastError(); - char buffer[128]; - if (FormatMessageA(FORMAT_MESSAGE_IGNORE_INSERTS | FORMAT_MESSAGE_FROM_SYSTEM, - NULL, error, 0, buffer, sizeof(buffer)/sizeof(char), NULL)) - lua_pushstring(L, buffer); - else - lua_pushfstring(L, "system error %d\n", error); -} - -static void lsys_unloadlib (void *lib) { - FreeLibrary((HMODULE)lib); -} - - -static void *lsys_load (lua_State *L, const char *path, int seeglb) { - HMODULE lib = LoadLibraryExA(path, NULL, LUA_LLE_FLAGS); - (void)(seeglb); /* not used: symbols are 'global' by default */ - if (lib == NULL) pusherror(L); - return lib; -} - - -static lua_CFunction lsys_sym (lua_State *L, void *lib, const char *sym) { - lua_CFunction f = (lua_CFunction)GetProcAddress((HMODULE)lib, sym); - if (f == NULL) pusherror(L); - return f; -} - -/* }====================================================== */ - - -#else /* }{ */ -/* -** {====================================================== -** Fallback for other systems -** ======================================================= -*/ - -#undef LIB_FAIL -#define LIB_FAIL "absent" - - -#define DLMSG "dynamic libraries not enabled; check your Lua installation" - - -static void lsys_unloadlib (void *lib) { - (void)(lib); /* not used */ -} - - -static void *lsys_load (lua_State *L, const char *path, int seeglb) { - (void)(path); (void)(seeglb); /* not used */ - lua_pushliteral(L, DLMSG); - return NULL; -} - - -static lua_CFunction lsys_sym (lua_State *L, void *lib, const char *sym) { - (void)(lib); (void)(sym); /* not used */ - lua_pushliteral(L, DLMSG); - return NULL; -} - -/* }====================================================== */ -#endif /* } */ - - -/* -** {================================================================== -** Set Paths -** =================================================================== -*/ - -/* -** LUA_PATH_VAR and LUA_CPATH_VAR are the names of the environment -** variables that Lua check to set its paths. -*/ -#if !defined(LUA_PATH_VAR) -#define LUA_PATH_VAR "LUA_PATH" -#endif - -#if !defined(LUA_CPATH_VAR) -#define LUA_CPATH_VAR "LUA_CPATH" -#endif - - -#define AUXMARK "\1" /* auxiliary mark */ - - -/* -** return registry.LUA_NOENV as a boolean -*/ -static int noenv (lua_State *L) { - int b; - lua_getfield(L, LUA_REGISTRYINDEX, "LUA_NOENV"); - b = lua_toboolean(L, -1); - lua_pop(L, 1); /* remove value */ - return b; -} - - -/* -** Set a path -*/ -static void setpath (lua_State *L, const char *fieldname, - const char *envname, - const char *dft) { - const char *nver = lua_pushfstring(L, "%s%s", envname, LUA_VERSUFFIX); - const char *path = getenv(nver); /* use versioned name */ - if (path == NULL) /* no environment variable? */ - path = getenv(envname); /* try unversioned name */ - if (path == NULL || noenv(L)) /* no environment variable? */ - lua_pushstring(L, dft); /* use default */ - else { - /* replace ";;" by ";AUXMARK;" and then AUXMARK by default path */ - path = luaL_gsub(L, path, LUA_PATH_SEP LUA_PATH_SEP, - LUA_PATH_SEP AUXMARK LUA_PATH_SEP); - luaL_gsub(L, path, AUXMARK, dft); - lua_remove(L, -2); /* remove result from 1st 'gsub' */ - } - setprogdir(L); - lua_setfield(L, -3, fieldname); /* package[fieldname] = path value */ - lua_pop(L, 1); /* pop versioned variable name */ -} - -/* }================================================================== */ - - -/* -** return registry.CLIBS[path] -*/ -static void *checkclib (lua_State *L, const char *path) { - void *plib; - lua_rawgetp(L, LUA_REGISTRYINDEX, &CLIBS); - lua_getfield(L, -1, path); - plib = lua_touserdata(L, -1); /* plib = CLIBS[path] */ - lua_pop(L, 2); /* pop CLIBS table and 'plib' */ - return plib; -} - - -/* -** registry.CLIBS[path] = plib -- for queries -** registry.CLIBS[#CLIBS + 1] = plib -- also keep a list of all libraries -*/ -static void addtoclib (lua_State *L, const char *path, void *plib) { - lua_rawgetp(L, LUA_REGISTRYINDEX, &CLIBS); - lua_pushlightuserdata(L, plib); - lua_pushvalue(L, -1); - lua_setfield(L, -3, path); /* CLIBS[path] = plib */ - lua_rawseti(L, -2, luaL_len(L, -2) + 1); /* CLIBS[#CLIBS + 1] = plib */ - lua_pop(L, 1); /* pop CLIBS table */ -} - - -/* -** __gc tag method for CLIBS table: calls 'lsys_unloadlib' for all lib -** handles in list CLIBS -*/ -static int gctm (lua_State *L) { - lua_Integer n = luaL_len(L, 1); - for (; n >= 1; n--) { /* for each handle, in reverse order */ - lua_rawgeti(L, 1, n); /* get handle CLIBS[n] */ - lsys_unloadlib(lua_touserdata(L, -1)); - lua_pop(L, 1); /* pop handle */ - } - return 0; -} - - - -/* error codes for 'lookforfunc' */ -#define ERRLIB 1 -#define ERRFUNC 2 - -/* -** Look for a C function named 'sym' in a dynamically loaded library -** 'path'. -** First, check whether the library is already loaded; if not, try -** to load it. -** Then, if 'sym' is '*', return true (as library has been loaded). -** Otherwise, look for symbol 'sym' in the library and push a -** C function with that symbol. -** Return 0 and 'true' or a function in the stack; in case of -** errors, return an error code and an error message in the stack. -*/ -static int lookforfunc (lua_State *L, const char *path, const char *sym) { - void *reg = checkclib(L, path); /* check loaded C libraries */ - if (reg == NULL) { /* must load library? */ - reg = lsys_load(L, path, *sym == '*'); /* global symbols if 'sym'=='*' */ - if (reg == NULL) return ERRLIB; /* unable to load library */ - addtoclib(L, path, reg); - } - if (*sym == '*') { /* loading only library (no function)? */ - lua_pushboolean(L, 1); /* return 'true' */ - return 0; /* no errors */ - } - else { - lua_CFunction f = lsys_sym(L, reg, sym); - if (f == NULL) - return ERRFUNC; /* unable to find function */ - lua_pushcfunction(L, f); /* else create new function */ - return 0; /* no errors */ - } -} - - -static int ll_loadlib (lua_State *L) { - const char *path = luaL_checkstring(L, 1); - const char *init = luaL_checkstring(L, 2); - int stat = lookforfunc(L, path, init); - if (stat == 0) /* no errors? */ - return 1; /* return the loaded function */ - else { /* error; error message is on stack top */ - lua_pushnil(L); - lua_insert(L, -2); - lua_pushstring(L, (stat == ERRLIB) ? LIB_FAIL : "init"); - return 3; /* return nil, error message, and where */ - } -} - - - -/* -** {====================================================== -** 'require' function -** ======================================================= -*/ - - -static int readable (const char *filename) { - FILE *f = fopen(filename, "r"); /* try to open file */ - if (f == NULL) return 0; /* open failed */ - fclose(f); - return 1; -} - - -static const char *pushnexttemplate (lua_State *L, const char *path) { - const char *l; - while (*path == *LUA_PATH_SEP) path++; /* skip separators */ - if (*path == '\0') return NULL; /* no more templates */ - l = strchr(path, *LUA_PATH_SEP); /* find next separator */ - if (l == NULL) l = path + strlen(path); - lua_pushlstring(L, path, l - path); /* template */ - return l; -} - - -static const char *searchpath (lua_State *L, const char *name, - const char *path, - const char *sep, - const char *dirsep) { - luaL_Buffer msg; /* to build error message */ - luaL_buffinit(L, &msg); - if (*sep != '\0') /* non-empty separator? */ - name = luaL_gsub(L, name, sep, dirsep); /* replace it by 'dirsep' */ - while ((path = pushnexttemplate(L, path)) != NULL) { - const char *filename = luaL_gsub(L, lua_tostring(L, -1), - LUA_PATH_MARK, name); - lua_remove(L, -2); /* remove path template */ - if (readable(filename)) /* does file exist and is readable? */ - return filename; /* return that file name */ - lua_pushfstring(L, "\n\tno file '%s'", filename); - lua_remove(L, -2); /* remove file name */ - luaL_addvalue(&msg); /* concatenate error msg. entry */ - } - luaL_pushresult(&msg); /* create error message */ - return NULL; /* not found */ -} - - -static int ll_searchpath (lua_State *L) { - const char *f = searchpath(L, luaL_checkstring(L, 1), - luaL_checkstring(L, 2), - luaL_optstring(L, 3, "."), - luaL_optstring(L, 4, LUA_DIRSEP)); - if (f != NULL) return 1; - else { /* error message is on top of the stack */ - lua_pushnil(L); - lua_insert(L, -2); - return 2; /* return nil + error message */ - } -} - - -static const char *findfile (lua_State *L, const char *name, - const char *pname, - const char *dirsep) { - const char *path; - lua_getfield(L, lua_upvalueindex(1), pname); - path = lua_tostring(L, -1); - if (path == NULL) - luaL_error(L, "'package.%s' must be a string", pname); - return searchpath(L, name, path, ".", dirsep); -} - - -static int checkload (lua_State *L, int stat, const char *filename) { - if (stat) { /* module loaded successfully? */ - lua_pushstring(L, filename); /* will be 2nd argument to module */ - return 2; /* return open function and file name */ - } - else - return luaL_error(L, "error loading module '%s' from file '%s':\n\t%s", - lua_tostring(L, 1), filename, lua_tostring(L, -1)); -} - - -static int searcher_Lua (lua_State *L) { - const char *filename; - const char *name = luaL_checkstring(L, 1); - filename = findfile(L, name, "path", LUA_LSUBSEP); - if (filename == NULL) return 1; /* module not found in this path */ - return checkload(L, (luaL_loadfile(L, filename) == LUA_OK), filename); -} - - -/* -** Try to find a load function for module 'modname' at file 'filename'. -** First, change '.' to '_' in 'modname'; then, if 'modname' has -** the form X-Y (that is, it has an "ignore mark"), build a function -** name "luaopen_X" and look for it. (For compatibility, if that -** fails, it also tries "luaopen_Y".) If there is no ignore mark, -** look for a function named "luaopen_modname". -*/ -static int loadfunc (lua_State *L, const char *filename, const char *modname) { - const char *openfunc; - const char *mark; - modname = luaL_gsub(L, modname, ".", LUA_OFSEP); - mark = strchr(modname, *LUA_IGMARK); - if (mark) { - int stat; - openfunc = lua_pushlstring(L, modname, mark - modname); - openfunc = lua_pushfstring(L, LUA_POF"%s", openfunc); - stat = lookforfunc(L, filename, openfunc); - if (stat != ERRFUNC) return stat; - modname = mark + 1; /* else go ahead and try old-style name */ - } - openfunc = lua_pushfstring(L, LUA_POF"%s", modname); - return lookforfunc(L, filename, openfunc); -} - - -static int searcher_C (lua_State *L) { - const char *name = luaL_checkstring(L, 1); - const char *filename = findfile(L, name, "cpath", LUA_CSUBSEP); - if (filename == NULL) return 1; /* module not found in this path */ - return checkload(L, (loadfunc(L, filename, name) == 0), filename); -} - - -static int searcher_Croot (lua_State *L) { - const char *filename; - const char *name = luaL_checkstring(L, 1); - const char *p = strchr(name, '.'); - int stat; - if (p == NULL) return 0; /* is root */ - lua_pushlstring(L, name, p - name); - filename = findfile(L, lua_tostring(L, -1), "cpath", LUA_CSUBSEP); - if (filename == NULL) return 1; /* root not found */ - if ((stat = loadfunc(L, filename, name)) != 0) { - if (stat != ERRFUNC) - return checkload(L, 0, filename); /* real error */ - else { /* open function not found */ - lua_pushfstring(L, "\n\tno module '%s' in file '%s'", name, filename); - return 1; - } - } - lua_pushstring(L, filename); /* will be 2nd argument to module */ - return 2; -} - - -static int searcher_preload (lua_State *L) { - const char *name = luaL_checkstring(L, 1); - lua_getfield(L, LUA_REGISTRYINDEX, LUA_PRELOAD_TABLE); - if (lua_getfield(L, -1, name) == LUA_TNIL) /* not found? */ - lua_pushfstring(L, "\n\tno field package.preload['%s']", name); - return 1; -} - - -static void findloader (lua_State *L, const char *name) { - int i; - luaL_Buffer msg; /* to build error message */ - luaL_buffinit(L, &msg); - /* push 'package.searchers' to index 3 in the stack */ - if (lua_getfield(L, lua_upvalueindex(1), "searchers") != LUA_TTABLE) - luaL_error(L, "'package.searchers' must be a table"); - /* iterate over available searchers to find a loader */ - for (i = 1; ; i++) { - if (lua_rawgeti(L, 3, i) == LUA_TNIL) { /* no more searchers? */ - lua_pop(L, 1); /* remove nil */ - luaL_pushresult(&msg); /* create error message */ - luaL_error(L, "module '%s' not found:%s", name, lua_tostring(L, -1)); - } - lua_pushstring(L, name); - lua_call(L, 1, 2); /* call it */ - if (lua_isfunction(L, -2)) /* did it find a loader? */ - return; /* module loader found */ - else if (lua_isstring(L, -2)) { /* searcher returned error message? */ - lua_pop(L, 1); /* remove extra return */ - luaL_addvalue(&msg); /* concatenate error message */ - } - else - lua_pop(L, 2); /* remove both returns */ - } -} - - -static int ll_require (lua_State *L) { - const char *name = luaL_checkstring(L, 1); - lua_settop(L, 1); /* LOADED table will be at index 2 */ - lua_getfield(L, LUA_REGISTRYINDEX, LUA_LOADED_TABLE); - lua_getfield(L, 2, name); /* LOADED[name] */ - if (lua_toboolean(L, -1)) /* is it there? */ - return 1; /* package is already loaded */ - /* else must load package */ - lua_pop(L, 1); /* remove 'getfield' result */ - findloader(L, name); - lua_pushstring(L, name); /* pass name as argument to module loader */ - lua_insert(L, -2); /* name is 1st argument (before search data) */ - lua_call(L, 2, 1); /* run loader to load module */ - if (!lua_isnil(L, -1)) /* non-nil return? */ - lua_setfield(L, 2, name); /* LOADED[name] = returned value */ - if (lua_getfield(L, 2, name) == LUA_TNIL) { /* module set no value? */ - lua_pushboolean(L, 1); /* use true as result */ - lua_pushvalue(L, -1); /* extra copy to be returned */ - lua_setfield(L, 2, name); /* LOADED[name] = true */ - } - return 1; -} - -/* }====================================================== */ - - - -/* -** {====================================================== -** 'module' function -** ======================================================= -*/ -#if defined(LUA_COMPAT_MODULE) - -/* -** changes the environment variable of calling function -*/ -static void set_env (lua_State *L) { - lua_Debug ar; - if (lua_getstack(L, 1, &ar) == 0 || - lua_getinfo(L, "f", &ar) == 0 || /* get calling function */ - lua_iscfunction(L, -1)) - luaL_error(L, "'module' not called from a Lua function"); - lua_pushvalue(L, -2); /* copy new environment table to top */ - lua_setupvalue(L, -2, 1); - lua_pop(L, 1); /* remove function */ -} - - -static void dooptions (lua_State *L, int n) { - int i; - for (i = 2; i <= n; i++) { - if (lua_isfunction(L, i)) { /* avoid 'calling' extra info. */ - lua_pushvalue(L, i); /* get option (a function) */ - lua_pushvalue(L, -2); /* module */ - lua_call(L, 1, 0); - } - } -} - - -static void modinit (lua_State *L, const char *modname) { - const char *dot; - lua_pushvalue(L, -1); - lua_setfield(L, -2, "_M"); /* module._M = module */ - lua_pushstring(L, modname); - lua_setfield(L, -2, "_NAME"); - dot = strrchr(modname, '.'); /* look for last dot in module name */ - if (dot == NULL) dot = modname; - else dot++; - /* set _PACKAGE as package name (full module name minus last part) */ - lua_pushlstring(L, modname, dot - modname); - lua_setfield(L, -2, "_PACKAGE"); -} - - -static int ll_module (lua_State *L) { - const char *modname = luaL_checkstring(L, 1); - int lastarg = lua_gettop(L); /* last parameter */ - luaL_pushmodule(L, modname, 1); /* get/create module table */ - /* check whether table already has a _NAME field */ - if (lua_getfield(L, -1, "_NAME") != LUA_TNIL) - lua_pop(L, 1); /* table is an initialized module */ - else { /* no; initialize it */ - lua_pop(L, 1); - modinit(L, modname); - } - lua_pushvalue(L, -1); - set_env(L); - dooptions(L, lastarg); - return 1; -} - - -static int ll_seeall (lua_State *L) { - luaL_checktype(L, 1, LUA_TTABLE); - if (!lua_getmetatable(L, 1)) { - lua_createtable(L, 0, 1); /* create new metatable */ - lua_pushvalue(L, -1); - lua_setmetatable(L, 1); - } - lua_pushglobaltable(L); - lua_setfield(L, -2, "__index"); /* mt.__index = _G */ - return 0; -} - -#endif -/* }====================================================== */ - - - -static const luaL_Reg pk_funcs[] = { - {"loadlib", ll_loadlib}, - {"searchpath", ll_searchpath}, -#if defined(LUA_COMPAT_MODULE) - {"seeall", ll_seeall}, -#endif - /* placeholders */ - {"preload", NULL}, - {"cpath", NULL}, - {"path", NULL}, - {"searchers", NULL}, - {"loaded", NULL}, - {NULL, NULL} -}; - - -static const luaL_Reg ll_funcs[] = { -#if defined(LUA_COMPAT_MODULE) - {"module", ll_module}, -#endif - {"require", ll_require}, - {NULL, NULL} -}; - - -static void createsearcherstable (lua_State *L) { - static const lua_CFunction searchers[] = - {searcher_preload, searcher_Lua, searcher_C, searcher_Croot, NULL}; - int i; - /* create 'searchers' table */ - lua_createtable(L, sizeof(searchers)/sizeof(searchers[0]) - 1, 0); - /* fill it with predefined searchers */ - for (i=0; searchers[i] != NULL; i++) { - lua_pushvalue(L, -2); /* set 'package' as upvalue for all searchers */ - lua_pushcclosure(L, searchers[i], 1); - lua_rawseti(L, -2, i+1); - } -#if defined(LUA_COMPAT_LOADERS) - lua_pushvalue(L, -1); /* make a copy of 'searchers' table */ - lua_setfield(L, -3, "loaders"); /* put it in field 'loaders' */ -#endif - lua_setfield(L, -2, "searchers"); /* put it in field 'searchers' */ -} - - -/* -** create table CLIBS to keep track of loaded C libraries, -** setting a finalizer to close all libraries when closing state. -*/ -static void createclibstable (lua_State *L) { - lua_newtable(L); /* create CLIBS table */ - lua_createtable(L, 0, 1); /* create metatable for CLIBS */ - lua_pushcfunction(L, gctm); - lua_setfield(L, -2, "__gc"); /* set finalizer for CLIBS table */ - lua_setmetatable(L, -2); - lua_rawsetp(L, LUA_REGISTRYINDEX, &CLIBS); /* set CLIBS table in registry */ -} - - -LUAMOD_API int luaopen_package (lua_State *L) { - createclibstable(L); - luaL_newlib(L, pk_funcs); /* create 'package' table */ - createsearcherstable(L); - /* set paths */ - setpath(L, "path", LUA_PATH_VAR, LUA_PATH_DEFAULT); - setpath(L, "cpath", LUA_CPATH_VAR, LUA_CPATH_DEFAULT); - /* store config information */ - lua_pushliteral(L, LUA_DIRSEP "\n" LUA_PATH_SEP "\n" LUA_PATH_MARK "\n" - LUA_EXEC_DIR "\n" LUA_IGMARK "\n"); - lua_setfield(L, -2, "config"); - /* set field 'loaded' */ - luaL_getsubtable(L, LUA_REGISTRYINDEX, LUA_LOADED_TABLE); - lua_setfield(L, -2, "loaded"); - /* set field 'preload' */ - luaL_getsubtable(L, LUA_REGISTRYINDEX, LUA_PRELOAD_TABLE); - lua_setfield(L, -2, "preload"); - lua_pushglobaltable(L); - lua_pushvalue(L, -2); /* set 'package' as upvalue for next lib */ - luaL_setfuncs(L, ll_funcs, 1); /* open lib into global table */ - lua_pop(L, 1); /* pop global table */ - return 1; /* return 'package' table */ -} - diff --git a/lib/lua-5.3/src/lobject.c b/lib/lua-5.3/src/lobject.c deleted file mode 100644 index 355bf58..0000000 --- a/lib/lua-5.3/src/lobject.c +++ /dev/null @@ -1,522 +0,0 @@ -/* -** $Id: lobject.c,v 2.113.1.1 2017/04/19 17:29:57 roberto Exp $ -** Some generic functions over Lua objects -** See Copyright Notice in lua.h -*/ - -#define lobject_c -#define LUA_CORE - -#include "lprefix.h" - - -#include -#include -#include -#include -#include -#include - -#include "lua.h" - -#include "lctype.h" -#include "ldebug.h" -#include "ldo.h" -#include "lmem.h" -#include "lobject.h" -#include "lstate.h" -#include "lstring.h" -#include "lvm.h" - - - -LUAI_DDEF const TValue luaO_nilobject_ = {NILCONSTANT}; - - -/* -** converts an integer to a "floating point byte", represented as -** (eeeeexxx), where the real value is (1xxx) * 2^(eeeee - 1) if -** eeeee != 0 and (xxx) otherwise. -*/ -int luaO_int2fb (unsigned int x) { - int e = 0; /* exponent */ - if (x < 8) return x; - while (x >= (8 << 4)) { /* coarse steps */ - x = (x + 0xf) >> 4; /* x = ceil(x / 16) */ - e += 4; - } - while (x >= (8 << 1)) { /* fine steps */ - x = (x + 1) >> 1; /* x = ceil(x / 2) */ - e++; - } - return ((e+1) << 3) | (cast_int(x) - 8); -} - - -/* converts back */ -int luaO_fb2int (int x) { - return (x < 8) ? x : ((x & 7) + 8) << ((x >> 3) - 1); -} - - -/* -** Computes ceil(log2(x)) -*/ -int luaO_ceillog2 (unsigned int x) { - static const lu_byte log_2[256] = { /* log_2[i] = ceil(log2(i - 1)) */ - 0,1,2,2,3,3,3,3,4,4,4,4,4,4,4,4,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5, - 6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6, - 7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7, - 7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7, - 8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8, - 8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8, - 8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8, - 8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8 - }; - int l = 0; - x--; - while (x >= 256) { l += 8; x >>= 8; } - return l + log_2[x]; -} - - -static lua_Integer intarith (lua_State *L, int op, lua_Integer v1, - lua_Integer v2) { - switch (op) { - case LUA_OPADD: return intop(+, v1, v2); - case LUA_OPSUB:return intop(-, v1, v2); - case LUA_OPMUL:return intop(*, v1, v2); - case LUA_OPMOD: return luaV_mod(L, v1, v2); - case LUA_OPIDIV: return luaV_div(L, v1, v2); - case LUA_OPBAND: return intop(&, v1, v2); - case LUA_OPBOR: return intop(|, v1, v2); - case LUA_OPBXOR: return intop(^, v1, v2); - case LUA_OPSHL: return luaV_shiftl(v1, v2); - case LUA_OPSHR: return luaV_shiftl(v1, -v2); - case LUA_OPUNM: return intop(-, 0, v1); - case LUA_OPBNOT: return intop(^, ~l_castS2U(0), v1); - default: lua_assert(0); return 0; - } -} - - -static lua_Number numarith (lua_State *L, int op, lua_Number v1, - lua_Number v2) { - switch (op) { - case LUA_OPADD: return luai_numadd(L, v1, v2); - case LUA_OPSUB: return luai_numsub(L, v1, v2); - case LUA_OPMUL: return luai_nummul(L, v1, v2); - case LUA_OPDIV: return luai_numdiv(L, v1, v2); - case LUA_OPPOW: return luai_numpow(L, v1, v2); - case LUA_OPIDIV: return luai_numidiv(L, v1, v2); - case LUA_OPUNM: return luai_numunm(L, v1); - case LUA_OPMOD: { - lua_Number m; - luai_nummod(L, v1, v2, m); - return m; - } - default: lua_assert(0); return 0; - } -} - - -void luaO_arith (lua_State *L, int op, const TValue *p1, const TValue *p2, - TValue *res) { - switch (op) { - case LUA_OPBAND: case LUA_OPBOR: case LUA_OPBXOR: - case LUA_OPSHL: case LUA_OPSHR: - case LUA_OPBNOT: { /* operate only on integers */ - lua_Integer i1; lua_Integer i2; - if (tointeger(p1, &i1) && tointeger(p2, &i2)) { - setivalue(res, intarith(L, op, i1, i2)); - return; - } - else break; /* go to the end */ - } - case LUA_OPDIV: case LUA_OPPOW: { /* operate only on floats */ - lua_Number n1; lua_Number n2; - if (tonumber(p1, &n1) && tonumber(p2, &n2)) { - setfltvalue(res, numarith(L, op, n1, n2)); - return; - } - else break; /* go to the end */ - } - default: { /* other operations */ - lua_Number n1; lua_Number n2; - if (ttisinteger(p1) && ttisinteger(p2)) { - setivalue(res, intarith(L, op, ivalue(p1), ivalue(p2))); - return; - } - else if (tonumber(p1, &n1) && tonumber(p2, &n2)) { - setfltvalue(res, numarith(L, op, n1, n2)); - return; - } - else break; /* go to the end */ - } - } - /* could not perform raw operation; try metamethod */ - lua_assert(L != NULL); /* should not fail when folding (compile time) */ - luaT_trybinTM(L, p1, p2, res, cast(TMS, (op - LUA_OPADD) + TM_ADD)); -} - - -int luaO_hexavalue (int c) { - if (lisdigit(c)) return c - '0'; - else return (ltolower(c) - 'a') + 10; -} - - -static int isneg (const char **s) { - if (**s == '-') { (*s)++; return 1; } - else if (**s == '+') (*s)++; - return 0; -} - - - -/* -** {================================================================== -** Lua's implementation for 'lua_strx2number' -** =================================================================== -*/ - -#if !defined(lua_strx2number) - -/* maximum number of significant digits to read (to avoid overflows - even with single floats) */ -#define MAXSIGDIG 30 - -/* -** convert an hexadecimal numeric string to a number, following -** C99 specification for 'strtod' -*/ -static lua_Number lua_strx2number (const char *s, char **endptr) { - int dot = lua_getlocaledecpoint(); - lua_Number r = 0.0; /* result (accumulator) */ - int sigdig = 0; /* number of significant digits */ - int nosigdig = 0; /* number of non-significant digits */ - int e = 0; /* exponent correction */ - int neg; /* 1 if number is negative */ - int hasdot = 0; /* true after seen a dot */ - *endptr = cast(char *, s); /* nothing is valid yet */ - while (lisspace(cast_uchar(*s))) s++; /* skip initial spaces */ - neg = isneg(&s); /* check signal */ - if (!(*s == '0' && (*(s + 1) == 'x' || *(s + 1) == 'X'))) /* check '0x' */ - return 0.0; /* invalid format (no '0x') */ - for (s += 2; ; s++) { /* skip '0x' and read numeral */ - if (*s == dot) { - if (hasdot) break; /* second dot? stop loop */ - else hasdot = 1; - } - else if (lisxdigit(cast_uchar(*s))) { - if (sigdig == 0 && *s == '0') /* non-significant digit (zero)? */ - nosigdig++; - else if (++sigdig <= MAXSIGDIG) /* can read it without overflow? */ - r = (r * cast_num(16.0)) + luaO_hexavalue(*s); - else e++; /* too many digits; ignore, but still count for exponent */ - if (hasdot) e--; /* decimal digit? correct exponent */ - } - else break; /* neither a dot nor a digit */ - } - if (nosigdig + sigdig == 0) /* no digits? */ - return 0.0; /* invalid format */ - *endptr = cast(char *, s); /* valid up to here */ - e *= 4; /* each digit multiplies/divides value by 2^4 */ - if (*s == 'p' || *s == 'P') { /* exponent part? */ - int exp1 = 0; /* exponent value */ - int neg1; /* exponent signal */ - s++; /* skip 'p' */ - neg1 = isneg(&s); /* signal */ - if (!lisdigit(cast_uchar(*s))) - return 0.0; /* invalid; must have at least one digit */ - while (lisdigit(cast_uchar(*s))) /* read exponent */ - exp1 = exp1 * 10 + *(s++) - '0'; - if (neg1) exp1 = -exp1; - e += exp1; - *endptr = cast(char *, s); /* valid up to here */ - } - if (neg) r = -r; - return l_mathop(ldexp)(r, e); -} - -#endif -/* }====================================================== */ - - -/* maximum length of a numeral */ -#if !defined (L_MAXLENNUM) -#define L_MAXLENNUM 200 -#endif - -static const char *l_str2dloc (const char *s, lua_Number *result, int mode) { - char *endptr; - *result = (mode == 'x') ? lua_strx2number(s, &endptr) /* try to convert */ - : lua_str2number(s, &endptr); - if (endptr == s) return NULL; /* nothing recognized? */ - while (lisspace(cast_uchar(*endptr))) endptr++; /* skip trailing spaces */ - return (*endptr == '\0') ? endptr : NULL; /* OK if no trailing characters */ -} - - -/* -** Convert string 's' to a Lua number (put in 'result'). Return NULL -** on fail or the address of the ending '\0' on success. -** 'pmode' points to (and 'mode' contains) special things in the string: -** - 'x'/'X' means an hexadecimal numeral -** - 'n'/'N' means 'inf' or 'nan' (which should be rejected) -** - '.' just optimizes the search for the common case (nothing special) -** This function accepts both the current locale or a dot as the radix -** mark. If the conversion fails, it may mean number has a dot but -** locale accepts something else. In that case, the code copies 's' -** to a buffer (because 's' is read-only), changes the dot to the -** current locale radix mark, and tries to convert again. -*/ -static const char *l_str2d (const char *s, lua_Number *result) { - const char *endptr; - const char *pmode = strpbrk(s, ".xXnN"); - int mode = pmode ? ltolower(cast_uchar(*pmode)) : 0; - if (mode == 'n') /* reject 'inf' and 'nan' */ - return NULL; - endptr = l_str2dloc(s, result, mode); /* try to convert */ - if (endptr == NULL) { /* failed? may be a different locale */ - char buff[L_MAXLENNUM + 1]; - const char *pdot = strchr(s, '.'); - if (strlen(s) > L_MAXLENNUM || pdot == NULL) - return NULL; /* string too long or no dot; fail */ - strcpy(buff, s); /* copy string to buffer */ - buff[pdot - s] = lua_getlocaledecpoint(); /* correct decimal point */ - endptr = l_str2dloc(buff, result, mode); /* try again */ - if (endptr != NULL) - endptr = s + (endptr - buff); /* make relative to 's' */ - } - return endptr; -} - - -#define MAXBY10 cast(lua_Unsigned, LUA_MAXINTEGER / 10) -#define MAXLASTD cast_int(LUA_MAXINTEGER % 10) - -static const char *l_str2int (const char *s, lua_Integer *result) { - lua_Unsigned a = 0; - int empty = 1; - int neg; - while (lisspace(cast_uchar(*s))) s++; /* skip initial spaces */ - neg = isneg(&s); - if (s[0] == '0' && - (s[1] == 'x' || s[1] == 'X')) { /* hex? */ - s += 2; /* skip '0x' */ - for (; lisxdigit(cast_uchar(*s)); s++) { - a = a * 16 + luaO_hexavalue(*s); - empty = 0; - } - } - else { /* decimal */ - for (; lisdigit(cast_uchar(*s)); s++) { - int d = *s - '0'; - if (a >= MAXBY10 && (a > MAXBY10 || d > MAXLASTD + neg)) /* overflow? */ - return NULL; /* do not accept it (as integer) */ - a = a * 10 + d; - empty = 0; - } - } - while (lisspace(cast_uchar(*s))) s++; /* skip trailing spaces */ - if (empty || *s != '\0') return NULL; /* something wrong in the numeral */ - else { - *result = l_castU2S((neg) ? 0u - a : a); - return s; - } -} - - -size_t luaO_str2num (const char *s, TValue *o) { - lua_Integer i; lua_Number n; - const char *e; - if ((e = l_str2int(s, &i)) != NULL) { /* try as an integer */ - setivalue(o, i); - } - else if ((e = l_str2d(s, &n)) != NULL) { /* else try as a float */ - setfltvalue(o, n); - } - else - return 0; /* conversion failed */ - return (e - s) + 1; /* success; return string size */ -} - - -int luaO_utf8esc (char *buff, unsigned long x) { - int n = 1; /* number of bytes put in buffer (backwards) */ - lua_assert(x <= 0x10FFFF); - if (x < 0x80) /* ascii? */ - buff[UTF8BUFFSZ - 1] = cast(char, x); - else { /* need continuation bytes */ - unsigned int mfb = 0x3f; /* maximum that fits in first byte */ - do { /* add continuation bytes */ - buff[UTF8BUFFSZ - (n++)] = cast(char, 0x80 | (x & 0x3f)); - x >>= 6; /* remove added bits */ - mfb >>= 1; /* now there is one less bit available in first byte */ - } while (x > mfb); /* still needs continuation byte? */ - buff[UTF8BUFFSZ - n] = cast(char, (~mfb << 1) | x); /* add first byte */ - } - return n; -} - - -/* maximum length of the conversion of a number to a string */ -#define MAXNUMBER2STR 50 - - -/* -** Convert a number object to a string -*/ -void luaO_tostring (lua_State *L, StkId obj) { - char buff[MAXNUMBER2STR]; - size_t len; - lua_assert(ttisnumber(obj)); - if (ttisinteger(obj)) - len = lua_integer2str(buff, sizeof(buff), ivalue(obj)); - else { - len = lua_number2str(buff, sizeof(buff), fltvalue(obj)); -#if !defined(LUA_COMPAT_FLOATSTRING) - if (buff[strspn(buff, "-0123456789")] == '\0') { /* looks like an int? */ - buff[len++] = lua_getlocaledecpoint(); - buff[len++] = '0'; /* adds '.0' to result */ - } -#endif - } - setsvalue2s(L, obj, luaS_newlstr(L, buff, len)); -} - - -static void pushstr (lua_State *L, const char *str, size_t l) { - setsvalue2s(L, L->top, luaS_newlstr(L, str, l)); - luaD_inctop(L); -} - - -/* -** this function handles only '%d', '%c', '%f', '%p', and '%s' - conventional formats, plus Lua-specific '%I' and '%U' -*/ -const char *luaO_pushvfstring (lua_State *L, const char *fmt, va_list argp) { - int n = 0; - for (;;) { - const char *e = strchr(fmt, '%'); - if (e == NULL) break; - pushstr(L, fmt, e - fmt); - switch (*(e+1)) { - case 's': { /* zero-terminated string */ - const char *s = va_arg(argp, char *); - if (s == NULL) s = "(null)"; - pushstr(L, s, strlen(s)); - break; - } - case 'c': { /* an 'int' as a character */ - char buff = cast(char, va_arg(argp, int)); - if (lisprint(cast_uchar(buff))) - pushstr(L, &buff, 1); - else /* non-printable character; print its code */ - luaO_pushfstring(L, "<\\%d>", cast_uchar(buff)); - break; - } - case 'd': { /* an 'int' */ - setivalue(L->top, va_arg(argp, int)); - goto top2str; - } - case 'I': { /* a 'lua_Integer' */ - setivalue(L->top, cast(lua_Integer, va_arg(argp, l_uacInt))); - goto top2str; - } - case 'f': { /* a 'lua_Number' */ - setfltvalue(L->top, cast_num(va_arg(argp, l_uacNumber))); - top2str: /* convert the top element to a string */ - luaD_inctop(L); - luaO_tostring(L, L->top - 1); - break; - } - case 'p': { /* a pointer */ - char buff[4*sizeof(void *) + 8]; /* should be enough space for a '%p' */ - void *p = va_arg(argp, void *); - int l = lua_pointer2str(buff, sizeof(buff), p); - pushstr(L, buff, l); - break; - } - case 'U': { /* an 'int' as a UTF-8 sequence */ - char buff[UTF8BUFFSZ]; - int l = luaO_utf8esc(buff, cast(long, va_arg(argp, long))); - pushstr(L, buff + UTF8BUFFSZ - l, l); - break; - } - case '%': { - pushstr(L, "%", 1); - break; - } - default: { - luaG_runerror(L, "invalid option '%%%c' to 'lua_pushfstring'", - *(e + 1)); - } - } - n += 2; - fmt = e+2; - } - luaD_checkstack(L, 1); - pushstr(L, fmt, strlen(fmt)); - if (n > 0) luaV_concat(L, n + 1); - return svalue(L->top - 1); -} - - -const char *luaO_pushfstring (lua_State *L, const char *fmt, ...) { - const char *msg; - va_list argp; - va_start(argp, fmt); - msg = luaO_pushvfstring(L, fmt, argp); - va_end(argp); - return msg; -} - - -/* number of chars of a literal string without the ending \0 */ -#define LL(x) (sizeof(x)/sizeof(char) - 1) - -#define RETS "..." -#define PRE "[string \"" -#define POS "\"]" - -#define addstr(a,b,l) ( memcpy(a,b,(l) * sizeof(char)), a += (l) ) - -void luaO_chunkid (char *out, const char *source, size_t bufflen) { - size_t l = strlen(source); - if (*source == '=') { /* 'literal' source */ - if (l <= bufflen) /* small enough? */ - memcpy(out, source + 1, l * sizeof(char)); - else { /* truncate it */ - addstr(out, source + 1, bufflen - 1); - *out = '\0'; - } - } - else if (*source == '@') { /* file name */ - if (l <= bufflen) /* small enough? */ - memcpy(out, source + 1, l * sizeof(char)); - else { /* add '...' before rest of name */ - addstr(out, RETS, LL(RETS)); - bufflen -= LL(RETS); - memcpy(out, source + 1 + l - bufflen, bufflen * sizeof(char)); - } - } - else { /* string; format as [string "source"] */ - const char *nl = strchr(source, '\n'); /* find first new line (if any) */ - addstr(out, PRE, LL(PRE)); /* add prefix */ - bufflen -= LL(PRE RETS POS) + 1; /* save space for prefix+suffix+'\0' */ - if (l < bufflen && nl == NULL) { /* small one-line source? */ - addstr(out, source, l); /* keep it */ - } - else { - if (nl != NULL) l = nl - source; /* stop at first newline */ - if (l > bufflen) l = bufflen; - addstr(out, source, l); - addstr(out, RETS, LL(RETS)); - } - memcpy(out, POS, (LL(POS) + 1) * sizeof(char)); - } -} - diff --git a/lib/lua-5.3/src/lobject.h b/lib/lua-5.3/src/lobject.h deleted file mode 100644 index 2408861..0000000 --- a/lib/lua-5.3/src/lobject.h +++ /dev/null @@ -1,549 +0,0 @@ -/* -** $Id: lobject.h,v 2.117.1.1 2017/04/19 17:39:34 roberto Exp $ -** Type definitions for Lua objects -** See Copyright Notice in lua.h -*/ - - -#ifndef lobject_h -#define lobject_h - - -#include - - -#include "llimits.h" -#include "lua.h" - - -/* -** Extra tags for non-values -*/ -#define LUA_TPROTO LUA_NUMTAGS /* function prototypes */ -#define LUA_TDEADKEY (LUA_NUMTAGS+1) /* removed keys in tables */ - -/* -** number of all possible tags (including LUA_TNONE but excluding DEADKEY) -*/ -#define LUA_TOTALTAGS (LUA_TPROTO + 2) - - -/* -** tags for Tagged Values have the following use of bits: -** bits 0-3: actual tag (a LUA_T* value) -** bits 4-5: variant bits -** bit 6: whether value is collectable -*/ - - -/* -** LUA_TFUNCTION variants: -** 0 - Lua function -** 1 - light C function -** 2 - regular C function (closure) -*/ - -/* Variant tags for functions */ -#define LUA_TLCL (LUA_TFUNCTION | (0 << 4)) /* Lua closure */ -#define LUA_TLCF (LUA_TFUNCTION | (1 << 4)) /* light C function */ -#define LUA_TCCL (LUA_TFUNCTION | (2 << 4)) /* C closure */ - - -/* Variant tags for strings */ -#define LUA_TSHRSTR (LUA_TSTRING | (0 << 4)) /* short strings */ -#define LUA_TLNGSTR (LUA_TSTRING | (1 << 4)) /* long strings */ - - -/* Variant tags for numbers */ -#define LUA_TNUMFLT (LUA_TNUMBER | (0 << 4)) /* float numbers */ -#define LUA_TNUMINT (LUA_TNUMBER | (1 << 4)) /* integer numbers */ - - -/* Bit mark for collectable types */ -#define BIT_ISCOLLECTABLE (1 << 6) - -/* mark a tag as collectable */ -#define ctb(t) ((t) | BIT_ISCOLLECTABLE) - - -/* -** Common type for all collectable objects -*/ -typedef struct GCObject GCObject; - - -/* -** Common Header for all collectable objects (in macro form, to be -** included in other objects) -*/ -#define CommonHeader GCObject *next; lu_byte tt; lu_byte marked - - -/* -** Common type has only the common header -*/ -struct GCObject { - CommonHeader; -}; - - - - -/* -** Tagged Values. This is the basic representation of values in Lua, -** an actual value plus a tag with its type. -*/ - -/* -** Union of all Lua values -*/ -typedef union Value { - GCObject *gc; /* collectable objects */ - void *p; /* light userdata */ - int b; /* booleans */ - lua_CFunction f; /* light C functions */ - lua_Integer i; /* integer numbers */ - lua_Number n; /* float numbers */ -} Value; - - -#define TValuefields Value value_; int tt_ - - -typedef struct lua_TValue { - TValuefields; -} TValue; - - - -/* macro defining a nil value */ -#define NILCONSTANT {NULL}, LUA_TNIL - - -#define val_(o) ((o)->value_) - - -/* raw type tag of a TValue */ -#define rttype(o) ((o)->tt_) - -/* tag with no variants (bits 0-3) */ -#define novariant(x) ((x) & 0x0F) - -/* type tag of a TValue (bits 0-3 for tags + variant bits 4-5) */ -#define ttype(o) (rttype(o) & 0x3F) - -/* type tag of a TValue with no variants (bits 0-3) */ -#define ttnov(o) (novariant(rttype(o))) - - -/* Macros to test type */ -#define checktag(o,t) (rttype(o) == (t)) -#define checktype(o,t) (ttnov(o) == (t)) -#define ttisnumber(o) checktype((o), LUA_TNUMBER) -#define ttisfloat(o) checktag((o), LUA_TNUMFLT) -#define ttisinteger(o) checktag((o), LUA_TNUMINT) -#define ttisnil(o) checktag((o), LUA_TNIL) -#define ttisboolean(o) checktag((o), LUA_TBOOLEAN) -#define ttislightuserdata(o) checktag((o), LUA_TLIGHTUSERDATA) -#define ttisstring(o) checktype((o), LUA_TSTRING) -#define ttisshrstring(o) checktag((o), ctb(LUA_TSHRSTR)) -#define ttislngstring(o) checktag((o), ctb(LUA_TLNGSTR)) -#define ttistable(o) checktag((o), ctb(LUA_TTABLE)) -#define ttisfunction(o) checktype(o, LUA_TFUNCTION) -#define ttisclosure(o) ((rttype(o) & 0x1F) == LUA_TFUNCTION) -#define ttisCclosure(o) checktag((o), ctb(LUA_TCCL)) -#define ttisLclosure(o) checktag((o), ctb(LUA_TLCL)) -#define ttislcf(o) checktag((o), LUA_TLCF) -#define ttisfulluserdata(o) checktag((o), ctb(LUA_TUSERDATA)) -#define ttisthread(o) checktag((o), ctb(LUA_TTHREAD)) -#define ttisdeadkey(o) checktag((o), LUA_TDEADKEY) - - -/* Macros to access values */ -#define ivalue(o) check_exp(ttisinteger(o), val_(o).i) -#define fltvalue(o) check_exp(ttisfloat(o), val_(o).n) -#define nvalue(o) check_exp(ttisnumber(o), \ - (ttisinteger(o) ? cast_num(ivalue(o)) : fltvalue(o))) -#define gcvalue(o) check_exp(iscollectable(o), val_(o).gc) -#define pvalue(o) check_exp(ttislightuserdata(o), val_(o).p) -#define tsvalue(o) check_exp(ttisstring(o), gco2ts(val_(o).gc)) -#define uvalue(o) check_exp(ttisfulluserdata(o), gco2u(val_(o).gc)) -#define clvalue(o) check_exp(ttisclosure(o), gco2cl(val_(o).gc)) -#define clLvalue(o) check_exp(ttisLclosure(o), gco2lcl(val_(o).gc)) -#define clCvalue(o) check_exp(ttisCclosure(o), gco2ccl(val_(o).gc)) -#define fvalue(o) check_exp(ttislcf(o), val_(o).f) -#define hvalue(o) check_exp(ttistable(o), gco2t(val_(o).gc)) -#define bvalue(o) check_exp(ttisboolean(o), val_(o).b) -#define thvalue(o) check_exp(ttisthread(o), gco2th(val_(o).gc)) -/* a dead value may get the 'gc' field, but cannot access its contents */ -#define deadvalue(o) check_exp(ttisdeadkey(o), cast(void *, val_(o).gc)) - -#define l_isfalse(o) (ttisnil(o) || (ttisboolean(o) && bvalue(o) == 0)) - - -#define iscollectable(o) (rttype(o) & BIT_ISCOLLECTABLE) - - -/* Macros for internal tests */ -#define righttt(obj) (ttype(obj) == gcvalue(obj)->tt) - -#define checkliveness(L,obj) \ - lua_longassert(!iscollectable(obj) || \ - (righttt(obj) && (L == NULL || !isdead(G(L),gcvalue(obj))))) - - -/* Macros to set values */ -#define settt_(o,t) ((o)->tt_=(t)) - -#define setfltvalue(obj,x) \ - { TValue *io=(obj); val_(io).n=(x); settt_(io, LUA_TNUMFLT); } - -#define chgfltvalue(obj,x) \ - { TValue *io=(obj); lua_assert(ttisfloat(io)); val_(io).n=(x); } - -#define setivalue(obj,x) \ - { TValue *io=(obj); val_(io).i=(x); settt_(io, LUA_TNUMINT); } - -#define chgivalue(obj,x) \ - { TValue *io=(obj); lua_assert(ttisinteger(io)); val_(io).i=(x); } - -#define setnilvalue(obj) settt_(obj, LUA_TNIL) - -#define setfvalue(obj,x) \ - { TValue *io=(obj); val_(io).f=(x); settt_(io, LUA_TLCF); } - -#define setpvalue(obj,x) \ - { TValue *io=(obj); val_(io).p=(x); settt_(io, LUA_TLIGHTUSERDATA); } - -#define setbvalue(obj,x) \ - { TValue *io=(obj); val_(io).b=(x); settt_(io, LUA_TBOOLEAN); } - -#define setgcovalue(L,obj,x) \ - { TValue *io = (obj); GCObject *i_g=(x); \ - val_(io).gc = i_g; settt_(io, ctb(i_g->tt)); } - -#define setsvalue(L,obj,x) \ - { TValue *io = (obj); TString *x_ = (x); \ - val_(io).gc = obj2gco(x_); settt_(io, ctb(x_->tt)); \ - checkliveness(L,io); } - -#define setuvalue(L,obj,x) \ - { TValue *io = (obj); Udata *x_ = (x); \ - val_(io).gc = obj2gco(x_); settt_(io, ctb(LUA_TUSERDATA)); \ - checkliveness(L,io); } - -#define setthvalue(L,obj,x) \ - { TValue *io = (obj); lua_State *x_ = (x); \ - val_(io).gc = obj2gco(x_); settt_(io, ctb(LUA_TTHREAD)); \ - checkliveness(L,io); } - -#define setclLvalue(L,obj,x) \ - { TValue *io = (obj); LClosure *x_ = (x); \ - val_(io).gc = obj2gco(x_); settt_(io, ctb(LUA_TLCL)); \ - checkliveness(L,io); } - -#define setclCvalue(L,obj,x) \ - { TValue *io = (obj); CClosure *x_ = (x); \ - val_(io).gc = obj2gco(x_); settt_(io, ctb(LUA_TCCL)); \ - checkliveness(L,io); } - -#define sethvalue(L,obj,x) \ - { TValue *io = (obj); Table *x_ = (x); \ - val_(io).gc = obj2gco(x_); settt_(io, ctb(LUA_TTABLE)); \ - checkliveness(L,io); } - -#define setdeadvalue(obj) settt_(obj, LUA_TDEADKEY) - - - -#define setobj(L,obj1,obj2) \ - { TValue *io1=(obj1); *io1 = *(obj2); \ - (void)L; checkliveness(L,io1); } - - -/* -** different types of assignments, according to destination -*/ - -/* from stack to (same) stack */ -#define setobjs2s setobj -/* to stack (not from same stack) */ -#define setobj2s setobj -#define setsvalue2s setsvalue -#define sethvalue2s sethvalue -#define setptvalue2s setptvalue -/* from table to same table */ -#define setobjt2t setobj -/* to new object */ -#define setobj2n setobj -#define setsvalue2n setsvalue - -/* to table (define it as an expression to be used in macros) */ -#define setobj2t(L,o1,o2) ((void)L, *(o1)=*(o2), checkliveness(L,(o1))) - - - - -/* -** {====================================================== -** types and prototypes -** ======================================================= -*/ - - -typedef TValue *StkId; /* index to stack elements */ - - - - -/* -** Header for string value; string bytes follow the end of this structure -** (aligned according to 'UTString'; see next). -*/ -typedef struct TString { - CommonHeader; - lu_byte extra; /* reserved words for short strings; "has hash" for longs */ - lu_byte shrlen; /* length for short strings */ - unsigned int hash; - union { - size_t lnglen; /* length for long strings */ - struct TString *hnext; /* linked list for hash table */ - } u; -} TString; - - -/* -** Ensures that address after this type is always fully aligned. -*/ -typedef union UTString { - L_Umaxalign dummy; /* ensures maximum alignment for strings */ - TString tsv; -} UTString; - - -/* -** Get the actual string (array of bytes) from a 'TString'. -** (Access to 'extra' ensures that value is really a 'TString'.) -*/ -#define getstr(ts) \ - check_exp(sizeof((ts)->extra), cast(char *, (ts)) + sizeof(UTString)) - - -/* get the actual string (array of bytes) from a Lua value */ -#define svalue(o) getstr(tsvalue(o)) - -/* get string length from 'TString *s' */ -#define tsslen(s) ((s)->tt == LUA_TSHRSTR ? (s)->shrlen : (s)->u.lnglen) - -/* get string length from 'TValue *o' */ -#define vslen(o) tsslen(tsvalue(o)) - - -/* -** Header for userdata; memory area follows the end of this structure -** (aligned according to 'UUdata'; see next). -*/ -typedef struct Udata { - CommonHeader; - lu_byte ttuv_; /* user value's tag */ - struct Table *metatable; - size_t len; /* number of bytes */ - union Value user_; /* user value */ -} Udata; - - -/* -** Ensures that address after this type is always fully aligned. -*/ -typedef union UUdata { - L_Umaxalign dummy; /* ensures maximum alignment for 'local' udata */ - Udata uv; -} UUdata; - - -/* -** Get the address of memory block inside 'Udata'. -** (Access to 'ttuv_' ensures that value is really a 'Udata'.) -*/ -#define getudatamem(u) \ - check_exp(sizeof((u)->ttuv_), (cast(char*, (u)) + sizeof(UUdata))) - -#define setuservalue(L,u,o) \ - { const TValue *io=(o); Udata *iu = (u); \ - iu->user_ = io->value_; iu->ttuv_ = rttype(io); \ - checkliveness(L,io); } - - -#define getuservalue(L,u,o) \ - { TValue *io=(o); const Udata *iu = (u); \ - io->value_ = iu->user_; settt_(io, iu->ttuv_); \ - checkliveness(L,io); } - - -/* -** Description of an upvalue for function prototypes -*/ -typedef struct Upvaldesc { - TString *name; /* upvalue name (for debug information) */ - lu_byte instack; /* whether it is in stack (register) */ - lu_byte idx; /* index of upvalue (in stack or in outer function's list) */ -} Upvaldesc; - - -/* -** Description of a local variable for function prototypes -** (used for debug information) -*/ -typedef struct LocVar { - TString *varname; - int startpc; /* first point where variable is active */ - int endpc; /* first point where variable is dead */ -} LocVar; - - -/* -** Function Prototypes -*/ -typedef struct Proto { - CommonHeader; - lu_byte numparams; /* number of fixed parameters */ - lu_byte is_vararg; - lu_byte maxstacksize; /* number of registers needed by this function */ - int sizeupvalues; /* size of 'upvalues' */ - int sizek; /* size of 'k' */ - int sizecode; - int sizelineinfo; - int sizep; /* size of 'p' */ - int sizelocvars; - int linedefined; /* debug information */ - int lastlinedefined; /* debug information */ - TValue *k; /* constants used by the function */ - Instruction *code; /* opcodes */ - struct Proto **p; /* functions defined inside the function */ - int *lineinfo; /* map from opcodes to source lines (debug information) */ - LocVar *locvars; /* information about local variables (debug information) */ - Upvaldesc *upvalues; /* upvalue information */ - struct LClosure *cache; /* last-created closure with this prototype */ - TString *source; /* used for debug information */ - GCObject *gclist; -} Proto; - - - -/* -** Lua Upvalues -*/ -typedef struct UpVal UpVal; - - -/* -** Closures -*/ - -#define ClosureHeader \ - CommonHeader; lu_byte nupvalues; GCObject *gclist - -typedef struct CClosure { - ClosureHeader; - lua_CFunction f; - TValue upvalue[1]; /* list of upvalues */ -} CClosure; - - -typedef struct LClosure { - ClosureHeader; - struct Proto *p; - UpVal *upvals[1]; /* list of upvalues */ -} LClosure; - - -typedef union Closure { - CClosure c; - LClosure l; -} Closure; - - -#define isLfunction(o) ttisLclosure(o) - -#define getproto(o) (clLvalue(o)->p) - - -/* -** Tables -*/ - -typedef union TKey { - struct { - TValuefields; - int next; /* for chaining (offset for next node) */ - } nk; - TValue tvk; -} TKey; - - -/* copy a value into a key without messing up field 'next' */ -#define setnodekey(L,key,obj) \ - { TKey *k_=(key); const TValue *io_=(obj); \ - k_->nk.value_ = io_->value_; k_->nk.tt_ = io_->tt_; \ - (void)L; checkliveness(L,io_); } - - -typedef struct Node { - TValue i_val; - TKey i_key; -} Node; - - -typedef struct Table { - CommonHeader; - lu_byte flags; /* 1<

lsizenode)) - - -/* -** (address of) a fixed nil value -*/ -#define luaO_nilobject (&luaO_nilobject_) - - -LUAI_DDEC const TValue luaO_nilobject_; - -/* size of buffer for 'luaO_utf8esc' function */ -#define UTF8BUFFSZ 8 - -LUAI_FUNC int luaO_int2fb (unsigned int x); -LUAI_FUNC int luaO_fb2int (int x); -LUAI_FUNC int luaO_utf8esc (char *buff, unsigned long x); -LUAI_FUNC int luaO_ceillog2 (unsigned int x); -LUAI_FUNC void luaO_arith (lua_State *L, int op, const TValue *p1, - const TValue *p2, TValue *res); -LUAI_FUNC size_t luaO_str2num (const char *s, TValue *o); -LUAI_FUNC int luaO_hexavalue (int c); -LUAI_FUNC void luaO_tostring (lua_State *L, StkId obj); -LUAI_FUNC const char *luaO_pushvfstring (lua_State *L, const char *fmt, - va_list argp); -LUAI_FUNC const char *luaO_pushfstring (lua_State *L, const char *fmt, ...); -LUAI_FUNC void luaO_chunkid (char *out, const char *source, size_t len); - - -#endif - diff --git a/lib/lua-5.3/src/lopcodes.c b/lib/lua-5.3/src/lopcodes.c deleted file mode 100644 index 5ca3eb2..0000000 --- a/lib/lua-5.3/src/lopcodes.c +++ /dev/null @@ -1,124 +0,0 @@ -/* -** $Id: lopcodes.c,v 1.55.1.1 2017/04/19 17:20:42 roberto Exp $ -** Opcodes for Lua virtual machine -** See Copyright Notice in lua.h -*/ - -#define lopcodes_c -#define LUA_CORE - -#include "lprefix.h" - - -#include - -#include "lopcodes.h" - - -/* ORDER OP */ - -LUAI_DDEF const char *const luaP_opnames[NUM_OPCODES+1] = { - "MOVE", - "LOADK", - "LOADKX", - "LOADBOOL", - "LOADNIL", - "GETUPVAL", - "GETTABUP", - "GETTABLE", - "SETTABUP", - "SETUPVAL", - "SETTABLE", - "NEWTABLE", - "SELF", - "ADD", - "SUB", - "MUL", - "MOD", - "POW", - "DIV", - "IDIV", - "BAND", - "BOR", - "BXOR", - "SHL", - "SHR", - "UNM", - "BNOT", - "NOT", - "LEN", - "CONCAT", - "JMP", - "EQ", - "LT", - "LE", - "TEST", - "TESTSET", - "CALL", - "TAILCALL", - "RETURN", - "FORLOOP", - "FORPREP", - "TFORCALL", - "TFORLOOP", - "SETLIST", - "CLOSURE", - "VARARG", - "EXTRAARG", - NULL -}; - - -#define opmode(t,a,b,c,m) (((t)<<7) | ((a)<<6) | ((b)<<4) | ((c)<<2) | (m)) - -LUAI_DDEF const lu_byte luaP_opmodes[NUM_OPCODES] = { -/* T A B C mode opcode */ - opmode(0, 1, OpArgR, OpArgN, iABC) /* OP_MOVE */ - ,opmode(0, 1, OpArgK, OpArgN, iABx) /* OP_LOADK */ - ,opmode(0, 1, OpArgN, OpArgN, iABx) /* OP_LOADKX */ - ,opmode(0, 1, OpArgU, OpArgU, iABC) /* OP_LOADBOOL */ - ,opmode(0, 1, OpArgU, OpArgN, iABC) /* OP_LOADNIL */ - ,opmode(0, 1, OpArgU, OpArgN, iABC) /* OP_GETUPVAL */ - ,opmode(0, 1, OpArgU, OpArgK, iABC) /* OP_GETTABUP */ - ,opmode(0, 1, OpArgR, OpArgK, iABC) /* OP_GETTABLE */ - ,opmode(0, 0, OpArgK, OpArgK, iABC) /* OP_SETTABUP */ - ,opmode(0, 0, OpArgU, OpArgN, iABC) /* OP_SETUPVAL */ - ,opmode(0, 0, OpArgK, OpArgK, iABC) /* OP_SETTABLE */ - ,opmode(0, 1, OpArgU, OpArgU, iABC) /* OP_NEWTABLE */ - ,opmode(0, 1, OpArgR, OpArgK, iABC) /* OP_SELF */ - ,opmode(0, 1, OpArgK, OpArgK, iABC) /* OP_ADD */ - ,opmode(0, 1, OpArgK, OpArgK, iABC) /* OP_SUB */ - ,opmode(0, 1, OpArgK, OpArgK, iABC) /* OP_MUL */ - ,opmode(0, 1, OpArgK, OpArgK, iABC) /* OP_MOD */ - ,opmode(0, 1, OpArgK, OpArgK, iABC) /* OP_POW */ - ,opmode(0, 1, OpArgK, OpArgK, iABC) /* OP_DIV */ - ,opmode(0, 1, OpArgK, OpArgK, iABC) /* OP_IDIV */ - ,opmode(0, 1, OpArgK, OpArgK, iABC) /* OP_BAND */ - ,opmode(0, 1, OpArgK, OpArgK, iABC) /* OP_BOR */ - ,opmode(0, 1, OpArgK, OpArgK, iABC) /* OP_BXOR */ - ,opmode(0, 1, OpArgK, OpArgK, iABC) /* OP_SHL */ - ,opmode(0, 1, OpArgK, OpArgK, iABC) /* OP_SHR */ - ,opmode(0, 1, OpArgR, OpArgN, iABC) /* OP_UNM */ - ,opmode(0, 1, OpArgR, OpArgN, iABC) /* OP_BNOT */ - ,opmode(0, 1, OpArgR, OpArgN, iABC) /* OP_NOT */ - ,opmode(0, 1, OpArgR, OpArgN, iABC) /* OP_LEN */ - ,opmode(0, 1, OpArgR, OpArgR, iABC) /* OP_CONCAT */ - ,opmode(0, 0, OpArgR, OpArgN, iAsBx) /* OP_JMP */ - ,opmode(1, 0, OpArgK, OpArgK, iABC) /* OP_EQ */ - ,opmode(1, 0, OpArgK, OpArgK, iABC) /* OP_LT */ - ,opmode(1, 0, OpArgK, OpArgK, iABC) /* OP_LE */ - ,opmode(1, 0, OpArgN, OpArgU, iABC) /* OP_TEST */ - ,opmode(1, 1, OpArgR, OpArgU, iABC) /* OP_TESTSET */ - ,opmode(0, 1, OpArgU, OpArgU, iABC) /* OP_CALL */ - ,opmode(0, 1, OpArgU, OpArgU, iABC) /* OP_TAILCALL */ - ,opmode(0, 0, OpArgU, OpArgN, iABC) /* OP_RETURN */ - ,opmode(0, 1, OpArgR, OpArgN, iAsBx) /* OP_FORLOOP */ - ,opmode(0, 1, OpArgR, OpArgN, iAsBx) /* OP_FORPREP */ - ,opmode(0, 0, OpArgN, OpArgU, iABC) /* OP_TFORCALL */ - ,opmode(0, 1, OpArgR, OpArgN, iAsBx) /* OP_TFORLOOP */ - ,opmode(0, 0, OpArgU, OpArgU, iABC) /* OP_SETLIST */ - ,opmode(0, 1, OpArgU, OpArgN, iABx) /* OP_CLOSURE */ - ,opmode(0, 1, OpArgU, OpArgN, iABC) /* OP_VARARG */ - ,opmode(0, 0, OpArgU, OpArgU, iAx) /* OP_EXTRAARG */ -}; - diff --git a/lib/lua-5.3/src/lopcodes.h b/lib/lua-5.3/src/lopcodes.h deleted file mode 100644 index 6feaa1c..0000000 --- a/lib/lua-5.3/src/lopcodes.h +++ /dev/null @@ -1,297 +0,0 @@ -/* -** $Id: lopcodes.h,v 1.149.1.1 2017/04/19 17:20:42 roberto Exp $ -** Opcodes for Lua virtual machine -** See Copyright Notice in lua.h -*/ - -#ifndef lopcodes_h -#define lopcodes_h - -#include "llimits.h" - - -/*=========================================================================== - We assume that instructions are unsigned numbers. - All instructions have an opcode in the first 6 bits. - Instructions can have the following fields: - 'A' : 8 bits - 'B' : 9 bits - 'C' : 9 bits - 'Ax' : 26 bits ('A', 'B', and 'C' together) - 'Bx' : 18 bits ('B' and 'C' together) - 'sBx' : signed Bx - - A signed argument is represented in excess K; that is, the number - value is the unsigned value minus K. K is exactly the maximum value - for that argument (so that -max is represented by 0, and +max is - represented by 2*max), which is half the maximum for the corresponding - unsigned argument. -===========================================================================*/ - - -enum OpMode {iABC, iABx, iAsBx, iAx}; /* basic instruction format */ - - -/* -** size and position of opcode arguments. -*/ -#define SIZE_C 9 -#define SIZE_B 9 -#define SIZE_Bx (SIZE_C + SIZE_B) -#define SIZE_A 8 -#define SIZE_Ax (SIZE_C + SIZE_B + SIZE_A) - -#define SIZE_OP 6 - -#define POS_OP 0 -#define POS_A (POS_OP + SIZE_OP) -#define POS_C (POS_A + SIZE_A) -#define POS_B (POS_C + SIZE_C) -#define POS_Bx POS_C -#define POS_Ax POS_A - - -/* -** limits for opcode arguments. -** we use (signed) int to manipulate most arguments, -** so they must fit in LUAI_BITSINT-1 bits (-1 for sign) -*/ -#if SIZE_Bx < LUAI_BITSINT-1 -#define MAXARG_Bx ((1<>1) /* 'sBx' is signed */ -#else -#define MAXARG_Bx MAX_INT -#define MAXARG_sBx MAX_INT -#endif - -#if SIZE_Ax < LUAI_BITSINT-1 -#define MAXARG_Ax ((1<>POS_OP) & MASK1(SIZE_OP,0))) -#define SET_OPCODE(i,o) ((i) = (((i)&MASK0(SIZE_OP,POS_OP)) | \ - ((cast(Instruction, o)<>pos) & MASK1(size,0))) -#define setarg(i,v,pos,size) ((i) = (((i)&MASK0(size,pos)) | \ - ((cast(Instruction, v)<> RK(C) */ -OP_UNM,/* A B R(A) := -R(B) */ -OP_BNOT,/* A B R(A) := ~R(B) */ -OP_NOT,/* A B R(A) := not R(B) */ -OP_LEN,/* A B R(A) := length of R(B) */ - -OP_CONCAT,/* A B C R(A) := R(B).. ... ..R(C) */ - -OP_JMP,/* A sBx pc+=sBx; if (A) close all upvalues >= R(A - 1) */ -OP_EQ,/* A B C if ((RK(B) == RK(C)) ~= A) then pc++ */ -OP_LT,/* A B C if ((RK(B) < RK(C)) ~= A) then pc++ */ -OP_LE,/* A B C if ((RK(B) <= RK(C)) ~= A) then pc++ */ - -OP_TEST,/* A C if not (R(A) <=> C) then pc++ */ -OP_TESTSET,/* A B C if (R(B) <=> C) then R(A) := R(B) else pc++ */ - -OP_CALL,/* A B C R(A), ... ,R(A+C-2) := R(A)(R(A+1), ... ,R(A+B-1)) */ -OP_TAILCALL,/* A B C return R(A)(R(A+1), ... ,R(A+B-1)) */ -OP_RETURN,/* A B return R(A), ... ,R(A+B-2) (see note) */ - -OP_FORLOOP,/* A sBx R(A)+=R(A+2); - if R(A) > 4) & 3)) -#define getCMode(m) (cast(enum OpArgMask, (luaP_opmodes[m] >> 2) & 3)) -#define testAMode(m) (luaP_opmodes[m] & (1 << 6)) -#define testTMode(m) (luaP_opmodes[m] & (1 << 7)) - - -LUAI_DDEC const char *const luaP_opnames[NUM_OPCODES+1]; /* opcode names */ - - -/* number of list items to accumulate before a SETLIST instruction */ -#define LFIELDS_PER_FLUSH 50 - - -#endif diff --git a/lib/lua-5.3/src/loslib.c b/lib/lua-5.3/src/loslib.c deleted file mode 100644 index de590c6..0000000 --- a/lib/lua-5.3/src/loslib.c +++ /dev/null @@ -1,409 +0,0 @@ -/* -** $Id: loslib.c,v 1.65.1.1 2017/04/19 17:29:57 roberto Exp $ -** Standard Operating System library -** See Copyright Notice in lua.h -*/ - -#define loslib_c -#define LUA_LIB - -#include "lprefix.h" - - -#include -#include -#include -#include -#include - -#include "lua.h" - -#include "lauxlib.h" -#include "lualib.h" - - -/* -** {================================================================== -** List of valid conversion specifiers for the 'strftime' function; -** options are grouped by length; group of length 2 start with '||'. -** =================================================================== -*/ -#if !defined(LUA_STRFTIMEOPTIONS) /* { */ - -/* options for ANSI C 89 (only 1-char options) */ -#define L_STRFTIMEC89 "aAbBcdHIjmMpSUwWxXyYZ%" - -/* options for ISO C 99 and POSIX */ -#define L_STRFTIMEC99 "aAbBcCdDeFgGhHIjmMnprRStTuUVwWxXyYzZ%" \ - "||" "EcECExEXEyEY" "OdOeOHOIOmOMOSOuOUOVOwOWOy" /* two-char options */ - -/* options for Windows */ -#define L_STRFTIMEWIN "aAbBcdHIjmMpSUwWxXyYzZ%" \ - "||" "#c#x#d#H#I#j#m#M#S#U#w#W#y#Y" /* two-char options */ - -#if defined(LUA_USE_WINDOWS) -#define LUA_STRFTIMEOPTIONS L_STRFTIMEWIN -#elif defined(LUA_USE_C89) -#define LUA_STRFTIMEOPTIONS L_STRFTIMEC89 -#else /* C99 specification */ -#define LUA_STRFTIMEOPTIONS L_STRFTIMEC99 -#endif - -#endif /* } */ -/* }================================================================== */ - - -/* -** {================================================================== -** Configuration for time-related stuff -** =================================================================== -*/ - -#if !defined(l_time_t) /* { */ -/* -** type to represent time_t in Lua -*/ -#define l_timet lua_Integer -#define l_pushtime(L,t) lua_pushinteger(L,(lua_Integer)(t)) - -static time_t l_checktime (lua_State *L, int arg) { - lua_Integer t = luaL_checkinteger(L, arg); - luaL_argcheck(L, (time_t)t == t, arg, "time out-of-bounds"); - return (time_t)t; -} - -#endif /* } */ - - -#if !defined(l_gmtime) /* { */ -/* -** By default, Lua uses gmtime/localtime, except when POSIX is available, -** where it uses gmtime_r/localtime_r -*/ - -#if defined(LUA_USE_POSIX) /* { */ - -#define l_gmtime(t,r) gmtime_r(t,r) -#define l_localtime(t,r) localtime_r(t,r) - -#else /* }{ */ - -/* ISO C definitions */ -#define l_gmtime(t,r) ((void)(r)->tm_sec, gmtime(t)) -#define l_localtime(t,r) ((void)(r)->tm_sec, localtime(t)) - -#endif /* } */ - -#endif /* } */ - -/* }================================================================== */ - - -/* -** {================================================================== -** Configuration for 'tmpnam': -** By default, Lua uses tmpnam except when POSIX is available, where -** it uses mkstemp. -** =================================================================== -*/ -#if !defined(lua_tmpnam) /* { */ - -#if defined(LUA_USE_POSIX) /* { */ - -#include - -#define LUA_TMPNAMBUFSIZE 32 - -#if !defined(LUA_TMPNAMTEMPLATE) -#define LUA_TMPNAMTEMPLATE "/tmp/lua_XXXXXX" -#endif - -#define lua_tmpnam(b,e) { \ - strcpy(b, LUA_TMPNAMTEMPLATE); \ - e = mkstemp(b); \ - if (e != -1) close(e); \ - e = (e == -1); } - -#else /* }{ */ - -/* ISO C definitions */ -#define LUA_TMPNAMBUFSIZE L_tmpnam -#define lua_tmpnam(b,e) { e = (tmpnam(b) == NULL); } - -#endif /* } */ - -#endif /* } */ -/* }================================================================== */ - - - - -static int os_execute (lua_State *L) { - const char *cmd = luaL_optstring(L, 1, NULL); - int stat = system(cmd); - if (cmd != NULL) - return luaL_execresult(L, stat); - else { - lua_pushboolean(L, stat); /* true if there is a shell */ - return 1; - } -} - - -static int os_remove (lua_State *L) { - const char *filename = luaL_checkstring(L, 1); - return luaL_fileresult(L, remove(filename) == 0, filename); -} - - -static int os_rename (lua_State *L) { - const char *fromname = luaL_checkstring(L, 1); - const char *toname = luaL_checkstring(L, 2); - return luaL_fileresult(L, rename(fromname, toname) == 0, NULL); -} - - -static int os_tmpname (lua_State *L) { - char buff[LUA_TMPNAMBUFSIZE]; - int err; - lua_tmpnam(buff, err); - if (err) - return luaL_error(L, "unable to generate a unique filename"); - lua_pushstring(L, buff); - return 1; -} - - -static int os_getenv (lua_State *L) { - lua_pushstring(L, getenv(luaL_checkstring(L, 1))); /* if NULL push nil */ - return 1; -} - - -static int os_clock (lua_State *L) { - lua_pushnumber(L, ((lua_Number)clock())/(lua_Number)CLOCKS_PER_SEC); - return 1; -} - - -/* -** {====================================================== -** Time/Date operations -** { year=%Y, month=%m, day=%d, hour=%H, min=%M, sec=%S, -** wday=%w+1, yday=%j, isdst=? } -** ======================================================= -*/ - -static void setfield (lua_State *L, const char *key, int value) { - lua_pushinteger(L, value); - lua_setfield(L, -2, key); -} - -static void setboolfield (lua_State *L, const char *key, int value) { - if (value < 0) /* undefined? */ - return; /* does not set field */ - lua_pushboolean(L, value); - lua_setfield(L, -2, key); -} - - -/* -** Set all fields from structure 'tm' in the table on top of the stack -*/ -static void setallfields (lua_State *L, struct tm *stm) { - setfield(L, "sec", stm->tm_sec); - setfield(L, "min", stm->tm_min); - setfield(L, "hour", stm->tm_hour); - setfield(L, "day", stm->tm_mday); - setfield(L, "month", stm->tm_mon + 1); - setfield(L, "year", stm->tm_year + 1900); - setfield(L, "wday", stm->tm_wday + 1); - setfield(L, "yday", stm->tm_yday + 1); - setboolfield(L, "isdst", stm->tm_isdst); -} - - -static int getboolfield (lua_State *L, const char *key) { - int res; - res = (lua_getfield(L, -1, key) == LUA_TNIL) ? -1 : lua_toboolean(L, -1); - lua_pop(L, 1); - return res; -} - - -/* maximum value for date fields (to avoid arithmetic overflows with 'int') */ -#if !defined(L_MAXDATEFIELD) -#define L_MAXDATEFIELD (INT_MAX / 2) -#endif - -static int getfield (lua_State *L, const char *key, int d, int delta) { - int isnum; - int t = lua_getfield(L, -1, key); /* get field and its type */ - lua_Integer res = lua_tointegerx(L, -1, &isnum); - if (!isnum) { /* field is not an integer? */ - if (t != LUA_TNIL) /* some other value? */ - return luaL_error(L, "field '%s' is not an integer", key); - else if (d < 0) /* absent field; no default? */ - return luaL_error(L, "field '%s' missing in date table", key); - res = d; - } - else { - if (!(-L_MAXDATEFIELD <= res && res <= L_MAXDATEFIELD)) - return luaL_error(L, "field '%s' is out-of-bound", key); - res -= delta; - } - lua_pop(L, 1); - return (int)res; -} - - -static const char *checkoption (lua_State *L, const char *conv, - ptrdiff_t convlen, char *buff) { - const char *option = LUA_STRFTIMEOPTIONS; - int oplen = 1; /* length of options being checked */ - for (; *option != '\0' && oplen <= convlen; option += oplen) { - if (*option == '|') /* next block? */ - oplen++; /* will check options with next length (+1) */ - else if (memcmp(conv, option, oplen) == 0) { /* match? */ - memcpy(buff, conv, oplen); /* copy valid option to buffer */ - buff[oplen] = '\0'; - return conv + oplen; /* return next item */ - } - } - luaL_argerror(L, 1, - lua_pushfstring(L, "invalid conversion specifier '%%%s'", conv)); - return conv; /* to avoid warnings */ -} - - -/* maximum size for an individual 'strftime' item */ -#define SIZETIMEFMT 250 - - -static int os_date (lua_State *L) { - size_t slen; - const char *s = luaL_optlstring(L, 1, "%c", &slen); - time_t t = luaL_opt(L, l_checktime, 2, time(NULL)); - const char *se = s + slen; /* 's' end */ - struct tm tmr, *stm; - if (*s == '!') { /* UTC? */ - stm = l_gmtime(&t, &tmr); - s++; /* skip '!' */ - } - else - stm = l_localtime(&t, &tmr); - if (stm == NULL) /* invalid date? */ - return luaL_error(L, - "time result cannot be represented in this installation"); - if (strcmp(s, "*t") == 0) { - lua_createtable(L, 0, 9); /* 9 = number of fields */ - setallfields(L, stm); - } - else { - char cc[4]; /* buffer for individual conversion specifiers */ - luaL_Buffer b; - cc[0] = '%'; - luaL_buffinit(L, &b); - while (s < se) { - if (*s != '%') /* not a conversion specifier? */ - luaL_addchar(&b, *s++); - else { - size_t reslen; - char *buff = luaL_prepbuffsize(&b, SIZETIMEFMT); - s++; /* skip '%' */ - s = checkoption(L, s, se - s, cc + 1); /* copy specifier to 'cc' */ - reslen = strftime(buff, SIZETIMEFMT, cc, stm); - luaL_addsize(&b, reslen); - } - } - luaL_pushresult(&b); - } - return 1; -} - - -static int os_time (lua_State *L) { - time_t t; - if (lua_isnoneornil(L, 1)) /* called without args? */ - t = time(NULL); /* get current time */ - else { - struct tm ts; - luaL_checktype(L, 1, LUA_TTABLE); - lua_settop(L, 1); /* make sure table is at the top */ - ts.tm_sec = getfield(L, "sec", 0, 0); - ts.tm_min = getfield(L, "min", 0, 0); - ts.tm_hour = getfield(L, "hour", 12, 0); - ts.tm_mday = getfield(L, "day", -1, 0); - ts.tm_mon = getfield(L, "month", -1, 1); - ts.tm_year = getfield(L, "year", -1, 1900); - ts.tm_isdst = getboolfield(L, "isdst"); - t = mktime(&ts); - setallfields(L, &ts); /* update fields with normalized values */ - } - if (t != (time_t)(l_timet)t || t == (time_t)(-1)) - return luaL_error(L, - "time result cannot be represented in this installation"); - l_pushtime(L, t); - return 1; -} - - -static int os_difftime (lua_State *L) { - time_t t1 = l_checktime(L, 1); - time_t t2 = l_checktime(L, 2); - lua_pushnumber(L, (lua_Number)difftime(t1, t2)); - return 1; -} - -/* }====================================================== */ - - -static int os_setlocale (lua_State *L) { - static const int cat[] = {LC_ALL, LC_COLLATE, LC_CTYPE, LC_MONETARY, - LC_NUMERIC, LC_TIME}; - static const char *const catnames[] = {"all", "collate", "ctype", "monetary", - "numeric", "time", NULL}; - const char *l = luaL_optstring(L, 1, NULL); - int op = luaL_checkoption(L, 2, "all", catnames); - lua_pushstring(L, setlocale(cat[op], l)); - return 1; -} - - -static int os_exit (lua_State *L) { - int status; - if (lua_isboolean(L, 1)) - status = (lua_toboolean(L, 1) ? EXIT_SUCCESS : EXIT_FAILURE); - else - status = (int)luaL_optinteger(L, 1, EXIT_SUCCESS); - if (lua_toboolean(L, 2)) - lua_close(L); - if (L) exit(status); /* 'if' to avoid warnings for unreachable 'return' */ - return 0; -} - - -static const luaL_Reg syslib[] = { - {"clock", os_clock}, - {"date", os_date}, - {"difftime", os_difftime}, - {"execute", os_execute}, - {"exit", os_exit}, - {"getenv", os_getenv}, - {"remove", os_remove}, - {"rename", os_rename}, - {"setlocale", os_setlocale}, - {"time", os_time}, - {"tmpname", os_tmpname}, - {NULL, NULL} -}; - -/* }====================================================== */ - - - -LUAMOD_API int luaopen_os (lua_State *L) { - luaL_newlib(L, syslib); - return 1; -} - diff --git a/lib/lua-5.3/src/lparser.c b/lib/lua-5.3/src/lparser.c deleted file mode 100644 index 2f41e00..0000000 --- a/lib/lua-5.3/src/lparser.c +++ /dev/null @@ -1,1653 +0,0 @@ -/* -** $Id: lparser.c,v 2.155.1.2 2017/04/29 18:11:40 roberto Exp $ -** Lua Parser -** See Copyright Notice in lua.h -*/ - -#define lparser_c -#define LUA_CORE - -#include "lprefix.h" - - -#include - -#include "lua.h" - -#include "lcode.h" -#include "ldebug.h" -#include "ldo.h" -#include "lfunc.h" -#include "llex.h" -#include "lmem.h" -#include "lobject.h" -#include "lopcodes.h" -#include "lparser.h" -#include "lstate.h" -#include "lstring.h" -#include "ltable.h" - - - -/* maximum number of local variables per function (must be smaller - than 250, due to the bytecode format) */ -#define MAXVARS 200 - - -#define hasmultret(k) ((k) == VCALL || (k) == VVARARG) - - -/* because all strings are unified by the scanner, the parser - can use pointer equality for string equality */ -#define eqstr(a,b) ((a) == (b)) - - -/* -** nodes for block list (list of active blocks) -*/ -typedef struct BlockCnt { - struct BlockCnt *previous; /* chain */ - int firstlabel; /* index of first label in this block */ - int firstgoto; /* index of first pending goto in this block */ - lu_byte nactvar; /* # active locals outside the block */ - lu_byte upval; /* true if some variable in the block is an upvalue */ - lu_byte isloop; /* true if 'block' is a loop */ -} BlockCnt; - - - -/* -** prototypes for recursive non-terminal functions -*/ -static void statement (LexState *ls); -static void expr (LexState *ls, expdesc *v); - - -/* semantic error */ -static l_noret semerror (LexState *ls, const char *msg) { - ls->t.token = 0; /* remove "near " from final message */ - luaX_syntaxerror(ls, msg); -} - - -static l_noret error_expected (LexState *ls, int token) { - luaX_syntaxerror(ls, - luaO_pushfstring(ls->L, "%s expected", luaX_token2str(ls, token))); -} - - -static l_noret errorlimit (FuncState *fs, int limit, const char *what) { - lua_State *L = fs->ls->L; - const char *msg; - int line = fs->f->linedefined; - const char *where = (line == 0) - ? "main function" - : luaO_pushfstring(L, "function at line %d", line); - msg = luaO_pushfstring(L, "too many %s (limit is %d) in %s", - what, limit, where); - luaX_syntaxerror(fs->ls, msg); -} - - -static void checklimit (FuncState *fs, int v, int l, const char *what) { - if (v > l) errorlimit(fs, l, what); -} - - -static int testnext (LexState *ls, int c) { - if (ls->t.token == c) { - luaX_next(ls); - return 1; - } - else return 0; -} - - -static void check (LexState *ls, int c) { - if (ls->t.token != c) - error_expected(ls, c); -} - - -static void checknext (LexState *ls, int c) { - check(ls, c); - luaX_next(ls); -} - - -#define check_condition(ls,c,msg) { if (!(c)) luaX_syntaxerror(ls, msg); } - - - -static void check_match (LexState *ls, int what, int who, int where) { - if (!testnext(ls, what)) { - if (where == ls->linenumber) - error_expected(ls, what); - else { - luaX_syntaxerror(ls, luaO_pushfstring(ls->L, - "%s expected (to close %s at line %d)", - luaX_token2str(ls, what), luaX_token2str(ls, who), where)); - } - } -} - - -static TString *str_checkname (LexState *ls) { - TString *ts; - check(ls, TK_NAME); - ts = ls->t.seminfo.ts; - luaX_next(ls); - return ts; -} - - -static void init_exp (expdesc *e, expkind k, int i) { - e->f = e->t = NO_JUMP; - e->k = k; - e->u.info = i; -} - - -static void codestring (LexState *ls, expdesc *e, TString *s) { - init_exp(e, VK, luaK_stringK(ls->fs, s)); -} - - -static void checkname (LexState *ls, expdesc *e) { - codestring(ls, e, str_checkname(ls)); -} - - -static int registerlocalvar (LexState *ls, TString *varname) { - FuncState *fs = ls->fs; - Proto *f = fs->f; - int oldsize = f->sizelocvars; - luaM_growvector(ls->L, f->locvars, fs->nlocvars, f->sizelocvars, - LocVar, SHRT_MAX, "local variables"); - while (oldsize < f->sizelocvars) - f->locvars[oldsize++].varname = NULL; - f->locvars[fs->nlocvars].varname = varname; - luaC_objbarrier(ls->L, f, varname); - return fs->nlocvars++; -} - - -static void new_localvar (LexState *ls, TString *name) { - FuncState *fs = ls->fs; - Dyndata *dyd = ls->dyd; - int reg = registerlocalvar(ls, name); - checklimit(fs, dyd->actvar.n + 1 - fs->firstlocal, - MAXVARS, "local variables"); - luaM_growvector(ls->L, dyd->actvar.arr, dyd->actvar.n + 1, - dyd->actvar.size, Vardesc, MAX_INT, "local variables"); - dyd->actvar.arr[dyd->actvar.n++].idx = cast(short, reg); -} - - -static void new_localvarliteral_ (LexState *ls, const char *name, size_t sz) { - new_localvar(ls, luaX_newstring(ls, name, sz)); -} - -#define new_localvarliteral(ls,v) \ - new_localvarliteral_(ls, "" v, (sizeof(v)/sizeof(char))-1) - - -static LocVar *getlocvar (FuncState *fs, int i) { - int idx = fs->ls->dyd->actvar.arr[fs->firstlocal + i].idx; - lua_assert(idx < fs->nlocvars); - return &fs->f->locvars[idx]; -} - - -static void adjustlocalvars (LexState *ls, int nvars) { - FuncState *fs = ls->fs; - fs->nactvar = cast_byte(fs->nactvar + nvars); - for (; nvars; nvars--) { - getlocvar(fs, fs->nactvar - nvars)->startpc = fs->pc; - } -} - - -static void removevars (FuncState *fs, int tolevel) { - fs->ls->dyd->actvar.n -= (fs->nactvar - tolevel); - while (fs->nactvar > tolevel) - getlocvar(fs, --fs->nactvar)->endpc = fs->pc; -} - - -static int searchupvalue (FuncState *fs, TString *name) { - int i; - Upvaldesc *up = fs->f->upvalues; - for (i = 0; i < fs->nups; i++) { - if (eqstr(up[i].name, name)) return i; - } - return -1; /* not found */ -} - - -static int newupvalue (FuncState *fs, TString *name, expdesc *v) { - Proto *f = fs->f; - int oldsize = f->sizeupvalues; - checklimit(fs, fs->nups + 1, MAXUPVAL, "upvalues"); - luaM_growvector(fs->ls->L, f->upvalues, fs->nups, f->sizeupvalues, - Upvaldesc, MAXUPVAL, "upvalues"); - while (oldsize < f->sizeupvalues) - f->upvalues[oldsize++].name = NULL; - f->upvalues[fs->nups].instack = (v->k == VLOCAL); - f->upvalues[fs->nups].idx = cast_byte(v->u.info); - f->upvalues[fs->nups].name = name; - luaC_objbarrier(fs->ls->L, f, name); - return fs->nups++; -} - - -static int searchvar (FuncState *fs, TString *n) { - int i; - for (i = cast_int(fs->nactvar) - 1; i >= 0; i--) { - if (eqstr(n, getlocvar(fs, i)->varname)) - return i; - } - return -1; /* not found */ -} - - -/* - Mark block where variable at given level was defined - (to emit close instructions later). -*/ -static void markupval (FuncState *fs, int level) { - BlockCnt *bl = fs->bl; - while (bl->nactvar > level) - bl = bl->previous; - bl->upval = 1; -} - - -/* - Find variable with given name 'n'. If it is an upvalue, add this - upvalue into all intermediate functions. -*/ -static void singlevaraux (FuncState *fs, TString *n, expdesc *var, int base) { - if (fs == NULL) /* no more levels? */ - init_exp(var, VVOID, 0); /* default is global */ - else { - int v = searchvar(fs, n); /* look up locals at current level */ - if (v >= 0) { /* found? */ - init_exp(var, VLOCAL, v); /* variable is local */ - if (!base) - markupval(fs, v); /* local will be used as an upval */ - } - else { /* not found as local at current level; try upvalues */ - int idx = searchupvalue(fs, n); /* try existing upvalues */ - if (idx < 0) { /* not found? */ - singlevaraux(fs->prev, n, var, 0); /* try upper levels */ - if (var->k == VVOID) /* not found? */ - return; /* it is a global */ - /* else was LOCAL or UPVAL */ - idx = newupvalue(fs, n, var); /* will be a new upvalue */ - } - init_exp(var, VUPVAL, idx); /* new or old upvalue */ - } - } -} - - -static void singlevar (LexState *ls, expdesc *var) { - TString *varname = str_checkname(ls); - FuncState *fs = ls->fs; - singlevaraux(fs, varname, var, 1); - if (var->k == VVOID) { /* global name? */ - expdesc key; - singlevaraux(fs, ls->envn, var, 1); /* get environment variable */ - lua_assert(var->k != VVOID); /* this one must exist */ - codestring(ls, &key, varname); /* key is variable name */ - luaK_indexed(fs, var, &key); /* env[varname] */ - } -} - - -static void adjust_assign (LexState *ls, int nvars, int nexps, expdesc *e) { - FuncState *fs = ls->fs; - int extra = nvars - nexps; - if (hasmultret(e->k)) { - extra++; /* includes call itself */ - if (extra < 0) extra = 0; - luaK_setreturns(fs, e, extra); /* last exp. provides the difference */ - if (extra > 1) luaK_reserveregs(fs, extra-1); - } - else { - if (e->k != VVOID) luaK_exp2nextreg(fs, e); /* close last expression */ - if (extra > 0) { - int reg = fs->freereg; - luaK_reserveregs(fs, extra); - luaK_nil(fs, reg, extra); - } - } - if (nexps > nvars) - ls->fs->freereg -= nexps - nvars; /* remove extra values */ -} - - -static void enterlevel (LexState *ls) { - lua_State *L = ls->L; - ++L->nCcalls; - checklimit(ls->fs, L->nCcalls, LUAI_MAXCCALLS, "C levels"); -} - - -#define leavelevel(ls) ((ls)->L->nCcalls--) - - -static void closegoto (LexState *ls, int g, Labeldesc *label) { - int i; - FuncState *fs = ls->fs; - Labellist *gl = &ls->dyd->gt; - Labeldesc *gt = &gl->arr[g]; - lua_assert(eqstr(gt->name, label->name)); - if (gt->nactvar < label->nactvar) { - TString *vname = getlocvar(fs, gt->nactvar)->varname; - const char *msg = luaO_pushfstring(ls->L, - " at line %d jumps into the scope of local '%s'", - getstr(gt->name), gt->line, getstr(vname)); - semerror(ls, msg); - } - luaK_patchlist(fs, gt->pc, label->pc); - /* remove goto from pending list */ - for (i = g; i < gl->n - 1; i++) - gl->arr[i] = gl->arr[i + 1]; - gl->n--; -} - - -/* -** try to close a goto with existing labels; this solves backward jumps -*/ -static int findlabel (LexState *ls, int g) { - int i; - BlockCnt *bl = ls->fs->bl; - Dyndata *dyd = ls->dyd; - Labeldesc *gt = &dyd->gt.arr[g]; - /* check labels in current block for a match */ - for (i = bl->firstlabel; i < dyd->label.n; i++) { - Labeldesc *lb = &dyd->label.arr[i]; - if (eqstr(lb->name, gt->name)) { /* correct label? */ - if (gt->nactvar > lb->nactvar && - (bl->upval || dyd->label.n > bl->firstlabel)) - luaK_patchclose(ls->fs, gt->pc, lb->nactvar); - closegoto(ls, g, lb); /* close it */ - return 1; - } - } - return 0; /* label not found; cannot close goto */ -} - - -static int newlabelentry (LexState *ls, Labellist *l, TString *name, - int line, int pc) { - int n = l->n; - luaM_growvector(ls->L, l->arr, n, l->size, - Labeldesc, SHRT_MAX, "labels/gotos"); - l->arr[n].name = name; - l->arr[n].line = line; - l->arr[n].nactvar = ls->fs->nactvar; - l->arr[n].pc = pc; - l->n = n + 1; - return n; -} - - -/* -** check whether new label 'lb' matches any pending gotos in current -** block; solves forward jumps -*/ -static void findgotos (LexState *ls, Labeldesc *lb) { - Labellist *gl = &ls->dyd->gt; - int i = ls->fs->bl->firstgoto; - while (i < gl->n) { - if (eqstr(gl->arr[i].name, lb->name)) - closegoto(ls, i, lb); - else - i++; - } -} - - -/* -** export pending gotos to outer level, to check them against -** outer labels; if the block being exited has upvalues, and -** the goto exits the scope of any variable (which can be the -** upvalue), close those variables being exited. -*/ -static void movegotosout (FuncState *fs, BlockCnt *bl) { - int i = bl->firstgoto; - Labellist *gl = &fs->ls->dyd->gt; - /* correct pending gotos to current block and try to close it - with visible labels */ - while (i < gl->n) { - Labeldesc *gt = &gl->arr[i]; - if (gt->nactvar > bl->nactvar) { - if (bl->upval) - luaK_patchclose(fs, gt->pc, bl->nactvar); - gt->nactvar = bl->nactvar; - } - if (!findlabel(fs->ls, i)) - i++; /* move to next one */ - } -} - - -static void enterblock (FuncState *fs, BlockCnt *bl, lu_byte isloop) { - bl->isloop = isloop; - bl->nactvar = fs->nactvar; - bl->firstlabel = fs->ls->dyd->label.n; - bl->firstgoto = fs->ls->dyd->gt.n; - bl->upval = 0; - bl->previous = fs->bl; - fs->bl = bl; - lua_assert(fs->freereg == fs->nactvar); -} - - -/* -** create a label named 'break' to resolve break statements -*/ -static void breaklabel (LexState *ls) { - TString *n = luaS_new(ls->L, "break"); - int l = newlabelentry(ls, &ls->dyd->label, n, 0, ls->fs->pc); - findgotos(ls, &ls->dyd->label.arr[l]); -} - -/* -** generates an error for an undefined 'goto'; choose appropriate -** message when label name is a reserved word (which can only be 'break') -*/ -static l_noret undefgoto (LexState *ls, Labeldesc *gt) { - const char *msg = isreserved(gt->name) - ? "<%s> at line %d not inside a loop" - : "no visible label '%s' for at line %d"; - msg = luaO_pushfstring(ls->L, msg, getstr(gt->name), gt->line); - semerror(ls, msg); -} - - -static void leaveblock (FuncState *fs) { - BlockCnt *bl = fs->bl; - LexState *ls = fs->ls; - if (bl->previous && bl->upval) { - /* create a 'jump to here' to close upvalues */ - int j = luaK_jump(fs); - luaK_patchclose(fs, j, bl->nactvar); - luaK_patchtohere(fs, j); - } - if (bl->isloop) - breaklabel(ls); /* close pending breaks */ - fs->bl = bl->previous; - removevars(fs, bl->nactvar); - lua_assert(bl->nactvar == fs->nactvar); - fs->freereg = fs->nactvar; /* free registers */ - ls->dyd->label.n = bl->firstlabel; /* remove local labels */ - if (bl->previous) /* inner block? */ - movegotosout(fs, bl); /* update pending gotos to outer block */ - else if (bl->firstgoto < ls->dyd->gt.n) /* pending gotos in outer block? */ - undefgoto(ls, &ls->dyd->gt.arr[bl->firstgoto]); /* error */ -} - - -/* -** adds a new prototype into list of prototypes -*/ -static Proto *addprototype (LexState *ls) { - Proto *clp; - lua_State *L = ls->L; - FuncState *fs = ls->fs; - Proto *f = fs->f; /* prototype of current function */ - if (fs->np >= f->sizep) { - int oldsize = f->sizep; - luaM_growvector(L, f->p, fs->np, f->sizep, Proto *, MAXARG_Bx, "functions"); - while (oldsize < f->sizep) - f->p[oldsize++] = NULL; - } - f->p[fs->np++] = clp = luaF_newproto(L); - luaC_objbarrier(L, f, clp); - return clp; -} - - -/* -** codes instruction to create new closure in parent function. -** The OP_CLOSURE instruction must use the last available register, -** so that, if it invokes the GC, the GC knows which registers -** are in use at that time. -*/ -static void codeclosure (LexState *ls, expdesc *v) { - FuncState *fs = ls->fs->prev; - init_exp(v, VRELOCABLE, luaK_codeABx(fs, OP_CLOSURE, 0, fs->np - 1)); - luaK_exp2nextreg(fs, v); /* fix it at the last register */ -} - - -static void open_func (LexState *ls, FuncState *fs, BlockCnt *bl) { - Proto *f; - fs->prev = ls->fs; /* linked list of funcstates */ - fs->ls = ls; - ls->fs = fs; - fs->pc = 0; - fs->lasttarget = 0; - fs->jpc = NO_JUMP; - fs->freereg = 0; - fs->nk = 0; - fs->np = 0; - fs->nups = 0; - fs->nlocvars = 0; - fs->nactvar = 0; - fs->firstlocal = ls->dyd->actvar.n; - fs->bl = NULL; - f = fs->f; - f->source = ls->source; - luaC_objbarrier(ls->L, f, f->source); - f->maxstacksize = 2; /* registers 0/1 are always valid */ - enterblock(fs, bl, 0); -} - - -static void close_func (LexState *ls) { - lua_State *L = ls->L; - FuncState *fs = ls->fs; - Proto *f = fs->f; - luaK_ret(fs, 0, 0); /* final return */ - leaveblock(fs); - luaM_reallocvector(L, f->code, f->sizecode, fs->pc, Instruction); - f->sizecode = fs->pc; - luaM_reallocvector(L, f->lineinfo, f->sizelineinfo, fs->pc, int); - f->sizelineinfo = fs->pc; - luaM_reallocvector(L, f->k, f->sizek, fs->nk, TValue); - f->sizek = fs->nk; - luaM_reallocvector(L, f->p, f->sizep, fs->np, Proto *); - f->sizep = fs->np; - luaM_reallocvector(L, f->locvars, f->sizelocvars, fs->nlocvars, LocVar); - f->sizelocvars = fs->nlocvars; - luaM_reallocvector(L, f->upvalues, f->sizeupvalues, fs->nups, Upvaldesc); - f->sizeupvalues = fs->nups; - lua_assert(fs->bl == NULL); - ls->fs = fs->prev; - luaC_checkGC(L); -} - - - -/*============================================================*/ -/* GRAMMAR RULES */ -/*============================================================*/ - - -/* -** check whether current token is in the follow set of a block. -** 'until' closes syntactical blocks, but do not close scope, -** so it is handled in separate. -*/ -static int block_follow (LexState *ls, int withuntil) { - switch (ls->t.token) { - case TK_ELSE: case TK_ELSEIF: - case TK_END: case TK_EOS: - return 1; - case TK_UNTIL: return withuntil; - default: return 0; - } -} - - -static void statlist (LexState *ls) { - /* statlist -> { stat [';'] } */ - while (!block_follow(ls, 1)) { - if (ls->t.token == TK_RETURN) { - statement(ls); - return; /* 'return' must be last statement */ - } - statement(ls); - } -} - - -static void fieldsel (LexState *ls, expdesc *v) { - /* fieldsel -> ['.' | ':'] NAME */ - FuncState *fs = ls->fs; - expdesc key; - luaK_exp2anyregup(fs, v); - luaX_next(ls); /* skip the dot or colon */ - checkname(ls, &key); - luaK_indexed(fs, v, &key); -} - - -static void yindex (LexState *ls, expdesc *v) { - /* index -> '[' expr ']' */ - luaX_next(ls); /* skip the '[' */ - expr(ls, v); - luaK_exp2val(ls->fs, v); - checknext(ls, ']'); -} - - -/* -** {====================================================================== -** Rules for Constructors -** ======================================================================= -*/ - - -struct ConsControl { - expdesc v; /* last list item read */ - expdesc *t; /* table descriptor */ - int nh; /* total number of 'record' elements */ - int na; /* total number of array elements */ - int tostore; /* number of array elements pending to be stored */ -}; - - -static void recfield (LexState *ls, struct ConsControl *cc) { - /* recfield -> (NAME | '['exp1']') = exp1 */ - FuncState *fs = ls->fs; - int reg = ls->fs->freereg; - expdesc key, val; - int rkkey; - if (ls->t.token == TK_NAME) { - checklimit(fs, cc->nh, MAX_INT, "items in a constructor"); - checkname(ls, &key); - } - else /* ls->t.token == '[' */ - yindex(ls, &key); - cc->nh++; - checknext(ls, '='); - rkkey = luaK_exp2RK(fs, &key); - expr(ls, &val); - luaK_codeABC(fs, OP_SETTABLE, cc->t->u.info, rkkey, luaK_exp2RK(fs, &val)); - fs->freereg = reg; /* free registers */ -} - - -static void closelistfield (FuncState *fs, struct ConsControl *cc) { - if (cc->v.k == VVOID) return; /* there is no list item */ - luaK_exp2nextreg(fs, &cc->v); - cc->v.k = VVOID; - if (cc->tostore == LFIELDS_PER_FLUSH) { - luaK_setlist(fs, cc->t->u.info, cc->na, cc->tostore); /* flush */ - cc->tostore = 0; /* no more items pending */ - } -} - - -static void lastlistfield (FuncState *fs, struct ConsControl *cc) { - if (cc->tostore == 0) return; - if (hasmultret(cc->v.k)) { - luaK_setmultret(fs, &cc->v); - luaK_setlist(fs, cc->t->u.info, cc->na, LUA_MULTRET); - cc->na--; /* do not count last expression (unknown number of elements) */ - } - else { - if (cc->v.k != VVOID) - luaK_exp2nextreg(fs, &cc->v); - luaK_setlist(fs, cc->t->u.info, cc->na, cc->tostore); - } -} - - -static void listfield (LexState *ls, struct ConsControl *cc) { - /* listfield -> exp */ - expr(ls, &cc->v); - checklimit(ls->fs, cc->na, MAX_INT, "items in a constructor"); - cc->na++; - cc->tostore++; -} - - -static void field (LexState *ls, struct ConsControl *cc) { - /* field -> listfield | recfield */ - switch(ls->t.token) { - case TK_NAME: { /* may be 'listfield' or 'recfield' */ - if (luaX_lookahead(ls) != '=') /* expression? */ - listfield(ls, cc); - else - recfield(ls, cc); - break; - } - case '[': { - recfield(ls, cc); - break; - } - default: { - listfield(ls, cc); - break; - } - } -} - - -static void constructor (LexState *ls, expdesc *t) { - /* constructor -> '{' [ field { sep field } [sep] ] '}' - sep -> ',' | ';' */ - FuncState *fs = ls->fs; - int line = ls->linenumber; - int pc = luaK_codeABC(fs, OP_NEWTABLE, 0, 0, 0); - struct ConsControl cc; - cc.na = cc.nh = cc.tostore = 0; - cc.t = t; - init_exp(t, VRELOCABLE, pc); - init_exp(&cc.v, VVOID, 0); /* no value (yet) */ - luaK_exp2nextreg(ls->fs, t); /* fix it at stack top */ - checknext(ls, '{'); - do { - lua_assert(cc.v.k == VVOID || cc.tostore > 0); - if (ls->t.token == '}') break; - closelistfield(fs, &cc); - field(ls, &cc); - } while (testnext(ls, ',') || testnext(ls, ';')); - check_match(ls, '}', '{', line); - lastlistfield(fs, &cc); - SETARG_B(fs->f->code[pc], luaO_int2fb(cc.na)); /* set initial array size */ - SETARG_C(fs->f->code[pc], luaO_int2fb(cc.nh)); /* set initial table size */ -} - -/* }====================================================================== */ - - - -static void parlist (LexState *ls) { - /* parlist -> [ param { ',' param } ] */ - FuncState *fs = ls->fs; - Proto *f = fs->f; - int nparams = 0; - f->is_vararg = 0; - if (ls->t.token != ')') { /* is 'parlist' not empty? */ - do { - switch (ls->t.token) { - case TK_NAME: { /* param -> NAME */ - new_localvar(ls, str_checkname(ls)); - nparams++; - break; - } - case TK_DOTS: { /* param -> '...' */ - luaX_next(ls); - f->is_vararg = 1; /* declared vararg */ - break; - } - default: luaX_syntaxerror(ls, " or '...' expected"); - } - } while (!f->is_vararg && testnext(ls, ',')); - } - adjustlocalvars(ls, nparams); - f->numparams = cast_byte(fs->nactvar); - luaK_reserveregs(fs, fs->nactvar); /* reserve register for parameters */ -} - - -static void body (LexState *ls, expdesc *e, int ismethod, int line) { - /* body -> '(' parlist ')' block END */ - FuncState new_fs; - BlockCnt bl; - new_fs.f = addprototype(ls); - new_fs.f->linedefined = line; - open_func(ls, &new_fs, &bl); - checknext(ls, '('); - if (ismethod) { - new_localvarliteral(ls, "self"); /* create 'self' parameter */ - adjustlocalvars(ls, 1); - } - parlist(ls); - checknext(ls, ')'); - statlist(ls); - new_fs.f->lastlinedefined = ls->linenumber; - check_match(ls, TK_END, TK_FUNCTION, line); - codeclosure(ls, e); - close_func(ls); -} - - -static int explist (LexState *ls, expdesc *v) { - /* explist -> expr { ',' expr } */ - int n = 1; /* at least one expression */ - expr(ls, v); - while (testnext(ls, ',')) { - luaK_exp2nextreg(ls->fs, v); - expr(ls, v); - n++; - } - return n; -} - - -static void funcargs (LexState *ls, expdesc *f, int line) { - FuncState *fs = ls->fs; - expdesc args; - int base, nparams; - switch (ls->t.token) { - case '(': { /* funcargs -> '(' [ explist ] ')' */ - luaX_next(ls); - if (ls->t.token == ')') /* arg list is empty? */ - args.k = VVOID; - else { - explist(ls, &args); - luaK_setmultret(fs, &args); - } - check_match(ls, ')', '(', line); - break; - } - case '{': { /* funcargs -> constructor */ - constructor(ls, &args); - break; - } - case TK_STRING: { /* funcargs -> STRING */ - codestring(ls, &args, ls->t.seminfo.ts); - luaX_next(ls); /* must use 'seminfo' before 'next' */ - break; - } - default: { - luaX_syntaxerror(ls, "function arguments expected"); - } - } - lua_assert(f->k == VNONRELOC); - base = f->u.info; /* base register for call */ - if (hasmultret(args.k)) - nparams = LUA_MULTRET; /* open call */ - else { - if (args.k != VVOID) - luaK_exp2nextreg(fs, &args); /* close last argument */ - nparams = fs->freereg - (base+1); - } - init_exp(f, VCALL, luaK_codeABC(fs, OP_CALL, base, nparams+1, 2)); - luaK_fixline(fs, line); - fs->freereg = base+1; /* call remove function and arguments and leaves - (unless changed) one result */ -} - - - - -/* -** {====================================================================== -** Expression parsing -** ======================================================================= -*/ - - -static void primaryexp (LexState *ls, expdesc *v) { - /* primaryexp -> NAME | '(' expr ')' */ - switch (ls->t.token) { - case '(': { - int line = ls->linenumber; - luaX_next(ls); - expr(ls, v); - check_match(ls, ')', '(', line); - luaK_dischargevars(ls->fs, v); - return; - } - case TK_NAME: { - singlevar(ls, v); - return; - } - default: { - luaX_syntaxerror(ls, "unexpected symbol"); - } - } -} - - -static void suffixedexp (LexState *ls, expdesc *v) { - /* suffixedexp -> - primaryexp { '.' NAME | '[' exp ']' | ':' NAME funcargs | funcargs } */ - FuncState *fs = ls->fs; - int line = ls->linenumber; - primaryexp(ls, v); - for (;;) { - switch (ls->t.token) { - case '.': { /* fieldsel */ - fieldsel(ls, v); - break; - } - case '[': { /* '[' exp1 ']' */ - expdesc key; - luaK_exp2anyregup(fs, v); - yindex(ls, &key); - luaK_indexed(fs, v, &key); - break; - } - case ':': { /* ':' NAME funcargs */ - expdesc key; - luaX_next(ls); - checkname(ls, &key); - luaK_self(fs, v, &key); - funcargs(ls, v, line); - break; - } - case '(': case TK_STRING: case '{': { /* funcargs */ - luaK_exp2nextreg(fs, v); - funcargs(ls, v, line); - break; - } - default: return; - } - } -} - - -static void simpleexp (LexState *ls, expdesc *v) { - /* simpleexp -> FLT | INT | STRING | NIL | TRUE | FALSE | ... | - constructor | FUNCTION body | suffixedexp */ - switch (ls->t.token) { - case TK_FLT: { - init_exp(v, VKFLT, 0); - v->u.nval = ls->t.seminfo.r; - break; - } - case TK_INT: { - init_exp(v, VKINT, 0); - v->u.ival = ls->t.seminfo.i; - break; - } - case TK_STRING: { - codestring(ls, v, ls->t.seminfo.ts); - break; - } - case TK_NIL: { - init_exp(v, VNIL, 0); - break; - } - case TK_TRUE: { - init_exp(v, VTRUE, 0); - break; - } - case TK_FALSE: { - init_exp(v, VFALSE, 0); - break; - } - case TK_DOTS: { /* vararg */ - FuncState *fs = ls->fs; - check_condition(ls, fs->f->is_vararg, - "cannot use '...' outside a vararg function"); - init_exp(v, VVARARG, luaK_codeABC(fs, OP_VARARG, 0, 1, 0)); - break; - } - case '{': { /* constructor */ - constructor(ls, v); - return; - } - case TK_FUNCTION: { - luaX_next(ls); - body(ls, v, 0, ls->linenumber); - return; - } - default: { - suffixedexp(ls, v); - return; - } - } - luaX_next(ls); -} - - -static UnOpr getunopr (int op) { - switch (op) { - case TK_NOT: return OPR_NOT; - case '-': return OPR_MINUS; - case '~': return OPR_BNOT; - case '#': return OPR_LEN; - default: return OPR_NOUNOPR; - } -} - - -static BinOpr getbinopr (int op) { - switch (op) { - case '+': return OPR_ADD; - case '-': return OPR_SUB; - case '*': return OPR_MUL; - case '%': return OPR_MOD; - case '^': return OPR_POW; - case '/': return OPR_DIV; - case TK_IDIV: return OPR_IDIV; - case '&': return OPR_BAND; - case '|': return OPR_BOR; - case '~': return OPR_BXOR; - case TK_SHL: return OPR_SHL; - case TK_SHR: return OPR_SHR; - case TK_CONCAT: return OPR_CONCAT; - case TK_NE: return OPR_NE; - case TK_EQ: return OPR_EQ; - case '<': return OPR_LT; - case TK_LE: return OPR_LE; - case '>': return OPR_GT; - case TK_GE: return OPR_GE; - case TK_AND: return OPR_AND; - case TK_OR: return OPR_OR; - default: return OPR_NOBINOPR; - } -} - - -static const struct { - lu_byte left; /* left priority for each binary operator */ - lu_byte right; /* right priority */ -} priority[] = { /* ORDER OPR */ - {10, 10}, {10, 10}, /* '+' '-' */ - {11, 11}, {11, 11}, /* '*' '%' */ - {14, 13}, /* '^' (right associative) */ - {11, 11}, {11, 11}, /* '/' '//' */ - {6, 6}, {4, 4}, {5, 5}, /* '&' '|' '~' */ - {7, 7}, {7, 7}, /* '<<' '>>' */ - {9, 8}, /* '..' (right associative) */ - {3, 3}, {3, 3}, {3, 3}, /* ==, <, <= */ - {3, 3}, {3, 3}, {3, 3}, /* ~=, >, >= */ - {2, 2}, {1, 1} /* and, or */ -}; - -#define UNARY_PRIORITY 12 /* priority for unary operators */ - - -/* -** subexpr -> (simpleexp | unop subexpr) { binop subexpr } -** where 'binop' is any binary operator with a priority higher than 'limit' -*/ -static BinOpr subexpr (LexState *ls, expdesc *v, int limit) { - BinOpr op; - UnOpr uop; - enterlevel(ls); - uop = getunopr(ls->t.token); - if (uop != OPR_NOUNOPR) { - int line = ls->linenumber; - luaX_next(ls); - subexpr(ls, v, UNARY_PRIORITY); - luaK_prefix(ls->fs, uop, v, line); - } - else simpleexp(ls, v); - /* expand while operators have priorities higher than 'limit' */ - op = getbinopr(ls->t.token); - while (op != OPR_NOBINOPR && priority[op].left > limit) { - expdesc v2; - BinOpr nextop; - int line = ls->linenumber; - luaX_next(ls); - luaK_infix(ls->fs, op, v); - /* read sub-expression with higher priority */ - nextop = subexpr(ls, &v2, priority[op].right); - luaK_posfix(ls->fs, op, v, &v2, line); - op = nextop; - } - leavelevel(ls); - return op; /* return first untreated operator */ -} - - -static void expr (LexState *ls, expdesc *v) { - subexpr(ls, v, 0); -} - -/* }==================================================================== */ - - - -/* -** {====================================================================== -** Rules for Statements -** ======================================================================= -*/ - - -static void block (LexState *ls) { - /* block -> statlist */ - FuncState *fs = ls->fs; - BlockCnt bl; - enterblock(fs, &bl, 0); - statlist(ls); - leaveblock(fs); -} - - -/* -** structure to chain all variables in the left-hand side of an -** assignment -*/ -struct LHS_assign { - struct LHS_assign *prev; - expdesc v; /* variable (global, local, upvalue, or indexed) */ -}; - - -/* -** check whether, in an assignment to an upvalue/local variable, the -** upvalue/local variable is begin used in a previous assignment to a -** table. If so, save original upvalue/local value in a safe place and -** use this safe copy in the previous assignment. -*/ -static void check_conflict (LexState *ls, struct LHS_assign *lh, expdesc *v) { - FuncState *fs = ls->fs; - int extra = fs->freereg; /* eventual position to save local variable */ - int conflict = 0; - for (; lh; lh = lh->prev) { /* check all previous assignments */ - if (lh->v.k == VINDEXED) { /* assigning to a table? */ - /* table is the upvalue/local being assigned now? */ - if (lh->v.u.ind.vt == v->k && lh->v.u.ind.t == v->u.info) { - conflict = 1; - lh->v.u.ind.vt = VLOCAL; - lh->v.u.ind.t = extra; /* previous assignment will use safe copy */ - } - /* index is the local being assigned? (index cannot be upvalue) */ - if (v->k == VLOCAL && lh->v.u.ind.idx == v->u.info) { - conflict = 1; - lh->v.u.ind.idx = extra; /* previous assignment will use safe copy */ - } - } - } - if (conflict) { - /* copy upvalue/local value to a temporary (in position 'extra') */ - OpCode op = (v->k == VLOCAL) ? OP_MOVE : OP_GETUPVAL; - luaK_codeABC(fs, op, extra, v->u.info, 0); - luaK_reserveregs(fs, 1); - } -} - - -static void assignment (LexState *ls, struct LHS_assign *lh, int nvars) { - expdesc e; - check_condition(ls, vkisvar(lh->v.k), "syntax error"); - if (testnext(ls, ',')) { /* assignment -> ',' suffixedexp assignment */ - struct LHS_assign nv; - nv.prev = lh; - suffixedexp(ls, &nv.v); - if (nv.v.k != VINDEXED) - check_conflict(ls, lh, &nv.v); - checklimit(ls->fs, nvars + ls->L->nCcalls, LUAI_MAXCCALLS, - "C levels"); - assignment(ls, &nv, nvars+1); - } - else { /* assignment -> '=' explist */ - int nexps; - checknext(ls, '='); - nexps = explist(ls, &e); - if (nexps != nvars) - adjust_assign(ls, nvars, nexps, &e); - else { - luaK_setoneret(ls->fs, &e); /* close last expression */ - luaK_storevar(ls->fs, &lh->v, &e); - return; /* avoid default */ - } - } - init_exp(&e, VNONRELOC, ls->fs->freereg-1); /* default assignment */ - luaK_storevar(ls->fs, &lh->v, &e); -} - - -static int cond (LexState *ls) { - /* cond -> exp */ - expdesc v; - expr(ls, &v); /* read condition */ - if (v.k == VNIL) v.k = VFALSE; /* 'falses' are all equal here */ - luaK_goiftrue(ls->fs, &v); - return v.f; -} - - -static void gotostat (LexState *ls, int pc) { - int line = ls->linenumber; - TString *label; - int g; - if (testnext(ls, TK_GOTO)) - label = str_checkname(ls); - else { - luaX_next(ls); /* skip break */ - label = luaS_new(ls->L, "break"); - } - g = newlabelentry(ls, &ls->dyd->gt, label, line, pc); - findlabel(ls, g); /* close it if label already defined */ -} - - -/* check for repeated labels on the same block */ -static void checkrepeated (FuncState *fs, Labellist *ll, TString *label) { - int i; - for (i = fs->bl->firstlabel; i < ll->n; i++) { - if (eqstr(label, ll->arr[i].name)) { - const char *msg = luaO_pushfstring(fs->ls->L, - "label '%s' already defined on line %d", - getstr(label), ll->arr[i].line); - semerror(fs->ls, msg); - } - } -} - - -/* skip no-op statements */ -static void skipnoopstat (LexState *ls) { - while (ls->t.token == ';' || ls->t.token == TK_DBCOLON) - statement(ls); -} - - -static void labelstat (LexState *ls, TString *label, int line) { - /* label -> '::' NAME '::' */ - FuncState *fs = ls->fs; - Labellist *ll = &ls->dyd->label; - int l; /* index of new label being created */ - checkrepeated(fs, ll, label); /* check for repeated labels */ - checknext(ls, TK_DBCOLON); /* skip double colon */ - /* create new entry for this label */ - l = newlabelentry(ls, ll, label, line, luaK_getlabel(fs)); - skipnoopstat(ls); /* skip other no-op statements */ - if (block_follow(ls, 0)) { /* label is last no-op statement in the block? */ - /* assume that locals are already out of scope */ - ll->arr[l].nactvar = fs->bl->nactvar; - } - findgotos(ls, &ll->arr[l]); -} - - -static void whilestat (LexState *ls, int line) { - /* whilestat -> WHILE cond DO block END */ - FuncState *fs = ls->fs; - int whileinit; - int condexit; - BlockCnt bl; - luaX_next(ls); /* skip WHILE */ - whileinit = luaK_getlabel(fs); - condexit = cond(ls); - enterblock(fs, &bl, 1); - checknext(ls, TK_DO); - block(ls); - luaK_jumpto(fs, whileinit); - check_match(ls, TK_END, TK_WHILE, line); - leaveblock(fs); - luaK_patchtohere(fs, condexit); /* false conditions finish the loop */ -} - - -static void repeatstat (LexState *ls, int line) { - /* repeatstat -> REPEAT block UNTIL cond */ - int condexit; - FuncState *fs = ls->fs; - int repeat_init = luaK_getlabel(fs); - BlockCnt bl1, bl2; - enterblock(fs, &bl1, 1); /* loop block */ - enterblock(fs, &bl2, 0); /* scope block */ - luaX_next(ls); /* skip REPEAT */ - statlist(ls); - check_match(ls, TK_UNTIL, TK_REPEAT, line); - condexit = cond(ls); /* read condition (inside scope block) */ - if (bl2.upval) /* upvalues? */ - luaK_patchclose(fs, condexit, bl2.nactvar); - leaveblock(fs); /* finish scope */ - luaK_patchlist(fs, condexit, repeat_init); /* close the loop */ - leaveblock(fs); /* finish loop */ -} - - -static int exp1 (LexState *ls) { - expdesc e; - int reg; - expr(ls, &e); - luaK_exp2nextreg(ls->fs, &e); - lua_assert(e.k == VNONRELOC); - reg = e.u.info; - return reg; -} - - -static void forbody (LexState *ls, int base, int line, int nvars, int isnum) { - /* forbody -> DO block */ - BlockCnt bl; - FuncState *fs = ls->fs; - int prep, endfor; - adjustlocalvars(ls, 3); /* control variables */ - checknext(ls, TK_DO); - prep = isnum ? luaK_codeAsBx(fs, OP_FORPREP, base, NO_JUMP) : luaK_jump(fs); - enterblock(fs, &bl, 0); /* scope for declared variables */ - adjustlocalvars(ls, nvars); - luaK_reserveregs(fs, nvars); - block(ls); - leaveblock(fs); /* end of scope for declared variables */ - luaK_patchtohere(fs, prep); - if (isnum) /* numeric for? */ - endfor = luaK_codeAsBx(fs, OP_FORLOOP, base, NO_JUMP); - else { /* generic for */ - luaK_codeABC(fs, OP_TFORCALL, base, 0, nvars); - luaK_fixline(fs, line); - endfor = luaK_codeAsBx(fs, OP_TFORLOOP, base + 2, NO_JUMP); - } - luaK_patchlist(fs, endfor, prep + 1); - luaK_fixline(fs, line); -} - - -static void fornum (LexState *ls, TString *varname, int line) { - /* fornum -> NAME = exp1,exp1[,exp1] forbody */ - FuncState *fs = ls->fs; - int base = fs->freereg; - new_localvarliteral(ls, "(for index)"); - new_localvarliteral(ls, "(for limit)"); - new_localvarliteral(ls, "(for step)"); - new_localvar(ls, varname); - checknext(ls, '='); - exp1(ls); /* initial value */ - checknext(ls, ','); - exp1(ls); /* limit */ - if (testnext(ls, ',')) - exp1(ls); /* optional step */ - else { /* default step = 1 */ - luaK_codek(fs, fs->freereg, luaK_intK(fs, 1)); - luaK_reserveregs(fs, 1); - } - forbody(ls, base, line, 1, 1); -} - - -static void forlist (LexState *ls, TString *indexname) { - /* forlist -> NAME {,NAME} IN explist forbody */ - FuncState *fs = ls->fs; - expdesc e; - int nvars = 4; /* gen, state, control, plus at least one declared var */ - int line; - int base = fs->freereg; - /* create control variables */ - new_localvarliteral(ls, "(for generator)"); - new_localvarliteral(ls, "(for state)"); - new_localvarliteral(ls, "(for control)"); - /* create declared variables */ - new_localvar(ls, indexname); - while (testnext(ls, ',')) { - new_localvar(ls, str_checkname(ls)); - nvars++; - } - checknext(ls, TK_IN); - line = ls->linenumber; - adjust_assign(ls, 3, explist(ls, &e), &e); - luaK_checkstack(fs, 3); /* extra space to call generator */ - forbody(ls, base, line, nvars - 3, 0); -} - - -static void forstat (LexState *ls, int line) { - /* forstat -> FOR (fornum | forlist) END */ - FuncState *fs = ls->fs; - TString *varname; - BlockCnt bl; - enterblock(fs, &bl, 1); /* scope for loop and control variables */ - luaX_next(ls); /* skip 'for' */ - varname = str_checkname(ls); /* first variable name */ - switch (ls->t.token) { - case '=': fornum(ls, varname, line); break; - case ',': case TK_IN: forlist(ls, varname); break; - default: luaX_syntaxerror(ls, "'=' or 'in' expected"); - } - check_match(ls, TK_END, TK_FOR, line); - leaveblock(fs); /* loop scope ('break' jumps to this point) */ -} - - -static void test_then_block (LexState *ls, int *escapelist) { - /* test_then_block -> [IF | ELSEIF] cond THEN block */ - BlockCnt bl; - FuncState *fs = ls->fs; - expdesc v; - int jf; /* instruction to skip 'then' code (if condition is false) */ - luaX_next(ls); /* skip IF or ELSEIF */ - expr(ls, &v); /* read condition */ - checknext(ls, TK_THEN); - if (ls->t.token == TK_GOTO || ls->t.token == TK_BREAK) { - luaK_goiffalse(ls->fs, &v); /* will jump to label if condition is true */ - enterblock(fs, &bl, 0); /* must enter block before 'goto' */ - gotostat(ls, v.t); /* handle goto/break */ - while (testnext(ls, ';')) {} /* skip colons */ - if (block_follow(ls, 0)) { /* 'goto' is the entire block? */ - leaveblock(fs); - return; /* and that is it */ - } - else /* must skip over 'then' part if condition is false */ - jf = luaK_jump(fs); - } - else { /* regular case (not goto/break) */ - luaK_goiftrue(ls->fs, &v); /* skip over block if condition is false */ - enterblock(fs, &bl, 0); - jf = v.f; - } - statlist(ls); /* 'then' part */ - leaveblock(fs); - if (ls->t.token == TK_ELSE || - ls->t.token == TK_ELSEIF) /* followed by 'else'/'elseif'? */ - luaK_concat(fs, escapelist, luaK_jump(fs)); /* must jump over it */ - luaK_patchtohere(fs, jf); -} - - -static void ifstat (LexState *ls, int line) { - /* ifstat -> IF cond THEN block {ELSEIF cond THEN block} [ELSE block] END */ - FuncState *fs = ls->fs; - int escapelist = NO_JUMP; /* exit list for finished parts */ - test_then_block(ls, &escapelist); /* IF cond THEN block */ - while (ls->t.token == TK_ELSEIF) - test_then_block(ls, &escapelist); /* ELSEIF cond THEN block */ - if (testnext(ls, TK_ELSE)) - block(ls); /* 'else' part */ - check_match(ls, TK_END, TK_IF, line); - luaK_patchtohere(fs, escapelist); /* patch escape list to 'if' end */ -} - - -static void localfunc (LexState *ls) { - expdesc b; - FuncState *fs = ls->fs; - new_localvar(ls, str_checkname(ls)); /* new local variable */ - adjustlocalvars(ls, 1); /* enter its scope */ - body(ls, &b, 0, ls->linenumber); /* function created in next register */ - /* debug information will only see the variable after this point! */ - getlocvar(fs, b.u.info)->startpc = fs->pc; -} - - -static void localstat (LexState *ls) { - /* stat -> LOCAL NAME {',' NAME} ['=' explist] */ - int nvars = 0; - int nexps; - expdesc e; - do { - new_localvar(ls, str_checkname(ls)); - nvars++; - } while (testnext(ls, ',')); - if (testnext(ls, '=')) - nexps = explist(ls, &e); - else { - e.k = VVOID; - nexps = 0; - } - adjust_assign(ls, nvars, nexps, &e); - adjustlocalvars(ls, nvars); -} - - -static int funcname (LexState *ls, expdesc *v) { - /* funcname -> NAME {fieldsel} [':' NAME] */ - int ismethod = 0; - singlevar(ls, v); - while (ls->t.token == '.') - fieldsel(ls, v); - if (ls->t.token == ':') { - ismethod = 1; - fieldsel(ls, v); - } - return ismethod; -} - - -static void funcstat (LexState *ls, int line) { - /* funcstat -> FUNCTION funcname body */ - int ismethod; - expdesc v, b; - luaX_next(ls); /* skip FUNCTION */ - ismethod = funcname(ls, &v); - body(ls, &b, ismethod, line); - luaK_storevar(ls->fs, &v, &b); - luaK_fixline(ls->fs, line); /* definition "happens" in the first line */ -} - - -static void exprstat (LexState *ls) { - /* stat -> func | assignment */ - FuncState *fs = ls->fs; - struct LHS_assign v; - suffixedexp(ls, &v.v); - if (ls->t.token == '=' || ls->t.token == ',') { /* stat -> assignment ? */ - v.prev = NULL; - assignment(ls, &v, 1); - } - else { /* stat -> func */ - check_condition(ls, v.v.k == VCALL, "syntax error"); - SETARG_C(getinstruction(fs, &v.v), 1); /* call statement uses no results */ - } -} - - -static void retstat (LexState *ls) { - /* stat -> RETURN [explist] [';'] */ - FuncState *fs = ls->fs; - expdesc e; - int first, nret; /* registers with returned values */ - if (block_follow(ls, 1) || ls->t.token == ';') - first = nret = 0; /* return no values */ - else { - nret = explist(ls, &e); /* optional return values */ - if (hasmultret(e.k)) { - luaK_setmultret(fs, &e); - if (e.k == VCALL && nret == 1) { /* tail call? */ - SET_OPCODE(getinstruction(fs,&e), OP_TAILCALL); - lua_assert(GETARG_A(getinstruction(fs,&e)) == fs->nactvar); - } - first = fs->nactvar; - nret = LUA_MULTRET; /* return all values */ - } - else { - if (nret == 1) /* only one single value? */ - first = luaK_exp2anyreg(fs, &e); - else { - luaK_exp2nextreg(fs, &e); /* values must go to the stack */ - first = fs->nactvar; /* return all active values */ - lua_assert(nret == fs->freereg - first); - } - } - } - luaK_ret(fs, first, nret); - testnext(ls, ';'); /* skip optional semicolon */ -} - - -static void statement (LexState *ls) { - int line = ls->linenumber; /* may be needed for error messages */ - enterlevel(ls); - switch (ls->t.token) { - case ';': { /* stat -> ';' (empty statement) */ - luaX_next(ls); /* skip ';' */ - break; - } - case TK_IF: { /* stat -> ifstat */ - ifstat(ls, line); - break; - } - case TK_WHILE: { /* stat -> whilestat */ - whilestat(ls, line); - break; - } - case TK_DO: { /* stat -> DO block END */ - luaX_next(ls); /* skip DO */ - block(ls); - check_match(ls, TK_END, TK_DO, line); - break; - } - case TK_FOR: { /* stat -> forstat */ - forstat(ls, line); - break; - } - case TK_REPEAT: { /* stat -> repeatstat */ - repeatstat(ls, line); - break; - } - case TK_FUNCTION: { /* stat -> funcstat */ - funcstat(ls, line); - break; - } - case TK_LOCAL: { /* stat -> localstat */ - luaX_next(ls); /* skip LOCAL */ - if (testnext(ls, TK_FUNCTION)) /* local function? */ - localfunc(ls); - else - localstat(ls); - break; - } - case TK_DBCOLON: { /* stat -> label */ - luaX_next(ls); /* skip double colon */ - labelstat(ls, str_checkname(ls), line); - break; - } - case TK_RETURN: { /* stat -> retstat */ - luaX_next(ls); /* skip RETURN */ - retstat(ls); - break; - } - case TK_BREAK: /* stat -> breakstat */ - case TK_GOTO: { /* stat -> 'goto' NAME */ - gotostat(ls, luaK_jump(ls->fs)); - break; - } - default: { /* stat -> func | assignment */ - exprstat(ls); - break; - } - } - lua_assert(ls->fs->f->maxstacksize >= ls->fs->freereg && - ls->fs->freereg >= ls->fs->nactvar); - ls->fs->freereg = ls->fs->nactvar; /* free registers */ - leavelevel(ls); -} - -/* }====================================================================== */ - - -/* -** compiles the main function, which is a regular vararg function with an -** upvalue named LUA_ENV -*/ -static void mainfunc (LexState *ls, FuncState *fs) { - BlockCnt bl; - expdesc v; - open_func(ls, fs, &bl); - fs->f->is_vararg = 1; /* main function is always declared vararg */ - init_exp(&v, VLOCAL, 0); /* create and... */ - newupvalue(fs, ls->envn, &v); /* ...set environment upvalue */ - luaC_objbarrier(ls->L, fs->f, ls->envn); - luaX_next(ls); /* read first token */ - statlist(ls); /* parse main body */ - check(ls, TK_EOS); - close_func(ls); -} - - -LClosure *luaY_parser (lua_State *L, ZIO *z, Mbuffer *buff, - Dyndata *dyd, const char *name, int firstchar) { - LexState lexstate; - FuncState funcstate; - LClosure *cl = luaF_newLclosure(L, 1); /* create main closure */ - setclLvalue(L, L->top, cl); /* anchor it (to avoid being collected) */ - luaD_inctop(L); - lexstate.h = luaH_new(L); /* create table for scanner */ - sethvalue(L, L->top, lexstate.h); /* anchor it */ - luaD_inctop(L); - funcstate.f = cl->p = luaF_newproto(L); - luaC_objbarrier(L, cl, cl->p); - funcstate.f->source = luaS_new(L, name); /* create and anchor TString */ - lua_assert(iswhite(funcstate.f)); /* do not need barrier here */ - lexstate.buff = buff; - lexstate.dyd = dyd; - dyd->actvar.n = dyd->gt.n = dyd->label.n = 0; - luaX_setinput(L, &lexstate, z, funcstate.f->source, firstchar); - mainfunc(&lexstate, &funcstate); - lua_assert(!funcstate.prev && funcstate.nups == 1 && !lexstate.fs); - /* all scopes should be correctly finished */ - lua_assert(dyd->actvar.n == 0 && dyd->gt.n == 0 && dyd->label.n == 0); - L->top--; /* remove scanner's table */ - return cl; /* closure is on the stack, too */ -} - diff --git a/lib/lua-5.3/src/lparser.h b/lib/lua-5.3/src/lparser.h deleted file mode 100644 index f45b23c..0000000 --- a/lib/lua-5.3/src/lparser.h +++ /dev/null @@ -1,133 +0,0 @@ -/* -** $Id: lparser.h,v 1.76.1.1 2017/04/19 17:20:42 roberto Exp $ -** Lua Parser -** See Copyright Notice in lua.h -*/ - -#ifndef lparser_h -#define lparser_h - -#include "llimits.h" -#include "lobject.h" -#include "lzio.h" - - -/* -** Expression and variable descriptor. -** Code generation for variables and expressions can be delayed to allow -** optimizations; An 'expdesc' structure describes a potentially-delayed -** variable/expression. It has a description of its "main" value plus a -** list of conditional jumps that can also produce its value (generated -** by short-circuit operators 'and'/'or'). -*/ - -/* kinds of variables/expressions */ -typedef enum { - VVOID, /* when 'expdesc' describes the last expression a list, - this kind means an empty list (so, no expression) */ - VNIL, /* constant nil */ - VTRUE, /* constant true */ - VFALSE, /* constant false */ - VK, /* constant in 'k'; info = index of constant in 'k' */ - VKFLT, /* floating constant; nval = numerical float value */ - VKINT, /* integer constant; nval = numerical integer value */ - VNONRELOC, /* expression has its value in a fixed register; - info = result register */ - VLOCAL, /* local variable; info = local register */ - VUPVAL, /* upvalue variable; info = index of upvalue in 'upvalues' */ - VINDEXED, /* indexed variable; - ind.vt = whether 't' is register or upvalue; - ind.t = table register or upvalue; - ind.idx = key's R/K index */ - VJMP, /* expression is a test/comparison; - info = pc of corresponding jump instruction */ - VRELOCABLE, /* expression can put result in any register; - info = instruction pc */ - VCALL, /* expression is a function call; info = instruction pc */ - VVARARG /* vararg expression; info = instruction pc */ -} expkind; - - -#define vkisvar(k) (VLOCAL <= (k) && (k) <= VINDEXED) -#define vkisinreg(k) ((k) == VNONRELOC || (k) == VLOCAL) - -typedef struct expdesc { - expkind k; - union { - lua_Integer ival; /* for VKINT */ - lua_Number nval; /* for VKFLT */ - int info; /* for generic use */ - struct { /* for indexed variables (VINDEXED) */ - short idx; /* index (R/K) */ - lu_byte t; /* table (register or upvalue) */ - lu_byte vt; /* whether 't' is register (VLOCAL) or upvalue (VUPVAL) */ - } ind; - } u; - int t; /* patch list of 'exit when true' */ - int f; /* patch list of 'exit when false' */ -} expdesc; - - -/* description of active local variable */ -typedef struct Vardesc { - short idx; /* variable index in stack */ -} Vardesc; - - -/* description of pending goto statements and label statements */ -typedef struct Labeldesc { - TString *name; /* label identifier */ - int pc; /* position in code */ - int line; /* line where it appeared */ - lu_byte nactvar; /* local level where it appears in current block */ -} Labeldesc; - - -/* list of labels or gotos */ -typedef struct Labellist { - Labeldesc *arr; /* array */ - int n; /* number of entries in use */ - int size; /* array size */ -} Labellist; - - -/* dynamic structures used by the parser */ -typedef struct Dyndata { - struct { /* list of active local variables */ - Vardesc *arr; - int n; - int size; - } actvar; - Labellist gt; /* list of pending gotos */ - Labellist label; /* list of active labels */ -} Dyndata; - - -/* control of blocks */ -struct BlockCnt; /* defined in lparser.c */ - - -/* state needed to generate code for a given function */ -typedef struct FuncState { - Proto *f; /* current function header */ - struct FuncState *prev; /* enclosing function */ - struct LexState *ls; /* lexical state */ - struct BlockCnt *bl; /* chain of current blocks */ - int pc; /* next position to code (equivalent to 'ncode') */ - int lasttarget; /* 'label' of last 'jump label' */ - int jpc; /* list of pending jumps to 'pc' */ - int nk; /* number of elements in 'k' */ - int np; /* number of elements in 'p' */ - int firstlocal; /* index of first local var (in Dyndata array) */ - short nlocvars; /* number of elements in 'f->locvars' */ - lu_byte nactvar; /* number of active local variables */ - lu_byte nups; /* number of upvalues */ - lu_byte freereg; /* first free register */ -} FuncState; - - -LUAI_FUNC LClosure *luaY_parser (lua_State *L, ZIO *z, Mbuffer *buff, - Dyndata *dyd, const char *name, int firstchar); - - -#endif diff --git a/lib/lua-5.3/src/lprefix.h b/lib/lua-5.3/src/lprefix.h deleted file mode 100644 index 9a749a3..0000000 --- a/lib/lua-5.3/src/lprefix.h +++ /dev/null @@ -1,45 +0,0 @@ -/* -** $Id: lprefix.h,v 1.2.1.1 2017/04/19 17:20:42 roberto Exp $ -** Definitions for Lua code that must come before any other header file -** See Copyright Notice in lua.h -*/ - -#ifndef lprefix_h -#define lprefix_h - - -/* -** Allows POSIX/XSI stuff -*/ -#if !defined(LUA_USE_C89) /* { */ - -#if !defined(_XOPEN_SOURCE) -#define _XOPEN_SOURCE 600 -#elif _XOPEN_SOURCE == 0 -#undef _XOPEN_SOURCE /* use -D_XOPEN_SOURCE=0 to undefine it */ -#endif - -/* -** Allows manipulation of large files in gcc and some other compilers -*/ -#if !defined(LUA_32BITS) && !defined(_FILE_OFFSET_BITS) -#define _LARGEFILE_SOURCE 1 -#define _FILE_OFFSET_BITS 64 -#endif - -#endif /* } */ - - -/* -** Windows stuff -*/ -#if defined(_WIN32) /* { */ - -#if !defined(_CRT_SECURE_NO_WARNINGS) -#define _CRT_SECURE_NO_WARNINGS /* avoid warnings about ISO C functions */ -#endif - -#endif /* } */ - -#endif - diff --git a/lib/lua-5.3/src/lstate.c b/lib/lua-5.3/src/lstate.c deleted file mode 100644 index c1a7664..0000000 --- a/lib/lua-5.3/src/lstate.c +++ /dev/null @@ -1,347 +0,0 @@ -/* -** $Id: lstate.c,v 2.133.1.1 2017/04/19 17:39:34 roberto Exp $ -** Global State -** See Copyright Notice in lua.h -*/ - -#define lstate_c -#define LUA_CORE - -#include "lprefix.h" - - -#include -#include - -#include "lua.h" - -#include "lapi.h" -#include "ldebug.h" -#include "ldo.h" -#include "lfunc.h" -#include "lgc.h" -#include "llex.h" -#include "lmem.h" -#include "lstate.h" -#include "lstring.h" -#include "ltable.h" -#include "ltm.h" - - -#if !defined(LUAI_GCPAUSE) -#define LUAI_GCPAUSE 200 /* 200% */ -#endif - -#if !defined(LUAI_GCMUL) -#define LUAI_GCMUL 200 /* GC runs 'twice the speed' of memory allocation */ -#endif - - -/* -** a macro to help the creation of a unique random seed when a state is -** created; the seed is used to randomize hashes. -*/ -#if !defined(luai_makeseed) -#include -#define luai_makeseed() cast(unsigned int, time(NULL)) -#endif - - - -/* -** thread state + extra space -*/ -typedef struct LX { - lu_byte extra_[LUA_EXTRASPACE]; - lua_State l; -} LX; - - -/* -** Main thread combines a thread state and the global state -*/ -typedef struct LG { - LX l; - global_State g; -} LG; - - - -#define fromstate(L) (cast(LX *, cast(lu_byte *, (L)) - offsetof(LX, l))) - - -/* -** Compute an initial seed as random as possible. Rely on Address Space -** Layout Randomization (if present) to increase randomness.. -*/ -#define addbuff(b,p,e) \ - { size_t t = cast(size_t, e); \ - memcpy(b + p, &t, sizeof(t)); p += sizeof(t); } - -static unsigned int makeseed (lua_State *L) { - char buff[4 * sizeof(size_t)]; - unsigned int h = luai_makeseed(); - int p = 0; - addbuff(buff, p, L); /* heap variable */ - addbuff(buff, p, &h); /* local variable */ - addbuff(buff, p, luaO_nilobject); /* global variable */ - addbuff(buff, p, &lua_newstate); /* public function */ - lua_assert(p == sizeof(buff)); - return luaS_hash(buff, p, h); -} - - -/* -** set GCdebt to a new value keeping the value (totalbytes + GCdebt) -** invariant (and avoiding underflows in 'totalbytes') -*/ -void luaE_setdebt (global_State *g, l_mem debt) { - l_mem tb = gettotalbytes(g); - lua_assert(tb > 0); - if (debt < tb - MAX_LMEM) - debt = tb - MAX_LMEM; /* will make 'totalbytes == MAX_LMEM' */ - g->totalbytes = tb - debt; - g->GCdebt = debt; -} - - -CallInfo *luaE_extendCI (lua_State *L) { - CallInfo *ci = luaM_new(L, CallInfo); - lua_assert(L->ci->next == NULL); - L->ci->next = ci; - ci->previous = L->ci; - ci->next = NULL; - L->nci++; - return ci; -} - - -/* -** free all CallInfo structures not in use by a thread -*/ -void luaE_freeCI (lua_State *L) { - CallInfo *ci = L->ci; - CallInfo *next = ci->next; - ci->next = NULL; - while ((ci = next) != NULL) { - next = ci->next; - luaM_free(L, ci); - L->nci--; - } -} - - -/* -** free half of the CallInfo structures not in use by a thread -*/ -void luaE_shrinkCI (lua_State *L) { - CallInfo *ci = L->ci; - CallInfo *next2; /* next's next */ - /* while there are two nexts */ - while (ci->next != NULL && (next2 = ci->next->next) != NULL) { - luaM_free(L, ci->next); /* free next */ - L->nci--; - ci->next = next2; /* remove 'next' from the list */ - next2->previous = ci; - ci = next2; /* keep next's next */ - } -} - - -static void stack_init (lua_State *L1, lua_State *L) { - int i; CallInfo *ci; - /* initialize stack array */ - L1->stack = luaM_newvector(L, BASIC_STACK_SIZE, TValue); - L1->stacksize = BASIC_STACK_SIZE; - for (i = 0; i < BASIC_STACK_SIZE; i++) - setnilvalue(L1->stack + i); /* erase new stack */ - L1->top = L1->stack; - L1->stack_last = L1->stack + L1->stacksize - EXTRA_STACK; - /* initialize first ci */ - ci = &L1->base_ci; - ci->next = ci->previous = NULL; - ci->callstatus = 0; - ci->func = L1->top; - setnilvalue(L1->top++); /* 'function' entry for this 'ci' */ - ci->top = L1->top + LUA_MINSTACK; - L1->ci = ci; -} - - -static void freestack (lua_State *L) { - if (L->stack == NULL) - return; /* stack not completely built yet */ - L->ci = &L->base_ci; /* free the entire 'ci' list */ - luaE_freeCI(L); - lua_assert(L->nci == 0); - luaM_freearray(L, L->stack, L->stacksize); /* free stack array */ -} - - -/* -** Create registry table and its predefined values -*/ -static void init_registry (lua_State *L, global_State *g) { - TValue temp; - /* create registry */ - Table *registry = luaH_new(L); - sethvalue(L, &g->l_registry, registry); - luaH_resize(L, registry, LUA_RIDX_LAST, 0); - /* registry[LUA_RIDX_MAINTHREAD] = L */ - setthvalue(L, &temp, L); /* temp = L */ - luaH_setint(L, registry, LUA_RIDX_MAINTHREAD, &temp); - /* registry[LUA_RIDX_GLOBALS] = table of globals */ - sethvalue(L, &temp, luaH_new(L)); /* temp = new table (global table) */ - luaH_setint(L, registry, LUA_RIDX_GLOBALS, &temp); -} - - -/* -** open parts of the state that may cause memory-allocation errors. -** ('g->version' != NULL flags that the state was completely build) -*/ -static void f_luaopen (lua_State *L, void *ud) { - global_State *g = G(L); - UNUSED(ud); - stack_init(L, L); /* init stack */ - init_registry(L, g); - luaS_init(L); - luaT_init(L); - luaX_init(L); - g->gcrunning = 1; /* allow gc */ - g->version = lua_version(NULL); - luai_userstateopen(L); -} - - -/* -** preinitialize a thread with consistent values without allocating -** any memory (to avoid errors) -*/ -static void preinit_thread (lua_State *L, global_State *g) { - G(L) = g; - L->stack = NULL; - L->ci = NULL; - L->nci = 0; - L->stacksize = 0; - L->twups = L; /* thread has no upvalues */ - L->errorJmp = NULL; - L->nCcalls = 0; - L->hook = NULL; - L->hookmask = 0; - L->basehookcount = 0; - L->allowhook = 1; - resethookcount(L); - L->openupval = NULL; - L->nny = 1; - L->status = LUA_OK; - L->errfunc = 0; -} - - -static void close_state (lua_State *L) { - global_State *g = G(L); - luaF_close(L, L->stack); /* close all upvalues for this thread */ - luaC_freeallobjects(L); /* collect all objects */ - if (g->version) /* closing a fully built state? */ - luai_userstateclose(L); - luaM_freearray(L, G(L)->strt.hash, G(L)->strt.size); - freestack(L); - lua_assert(gettotalbytes(g) == sizeof(LG)); - (*g->frealloc)(g->ud, fromstate(L), sizeof(LG), 0); /* free main block */ -} - - -LUA_API lua_State *lua_newthread (lua_State *L) { - global_State *g = G(L); - lua_State *L1; - lua_lock(L); - luaC_checkGC(L); - /* create new thread */ - L1 = &cast(LX *, luaM_newobject(L, LUA_TTHREAD, sizeof(LX)))->l; - L1->marked = luaC_white(g); - L1->tt = LUA_TTHREAD; - /* link it on list 'allgc' */ - L1->next = g->allgc; - g->allgc = obj2gco(L1); - /* anchor it on L stack */ - setthvalue(L, L->top, L1); - api_incr_top(L); - preinit_thread(L1, g); - L1->hookmask = L->hookmask; - L1->basehookcount = L->basehookcount; - L1->hook = L->hook; - resethookcount(L1); - /* initialize L1 extra space */ - memcpy(lua_getextraspace(L1), lua_getextraspace(g->mainthread), - LUA_EXTRASPACE); - luai_userstatethread(L, L1); - stack_init(L1, L); /* init stack */ - lua_unlock(L); - return L1; -} - - -void luaE_freethread (lua_State *L, lua_State *L1) { - LX *l = fromstate(L1); - luaF_close(L1, L1->stack); /* close all upvalues for this thread */ - lua_assert(L1->openupval == NULL); - luai_userstatefree(L, L1); - freestack(L1); - luaM_free(L, l); -} - - -LUA_API lua_State *lua_newstate (lua_Alloc f, void *ud) { - int i; - lua_State *L; - global_State *g; - LG *l = cast(LG *, (*f)(ud, NULL, LUA_TTHREAD, sizeof(LG))); - if (l == NULL) return NULL; - L = &l->l.l; - g = &l->g; - L->next = NULL; - L->tt = LUA_TTHREAD; - g->currentwhite = bitmask(WHITE0BIT); - L->marked = luaC_white(g); - preinit_thread(L, g); - g->frealloc = f; - g->ud = ud; - g->mainthread = L; - g->seed = makeseed(L); - g->gcrunning = 0; /* no GC while building state */ - g->GCestimate = 0; - g->strt.size = g->strt.nuse = 0; - g->strt.hash = NULL; - setnilvalue(&g->l_registry); - g->panic = NULL; - g->version = NULL; - g->gcstate = GCSpause; - g->gckind = KGC_NORMAL; - g->allgc = g->finobj = g->tobefnz = g->fixedgc = NULL; - g->sweepgc = NULL; - g->gray = g->grayagain = NULL; - g->weak = g->ephemeron = g->allweak = NULL; - g->twups = NULL; - g->totalbytes = sizeof(LG); - g->GCdebt = 0; - g->gcfinnum = 0; - g->gcpause = LUAI_GCPAUSE; - g->gcstepmul = LUAI_GCMUL; - for (i=0; i < LUA_NUMTAGS; i++) g->mt[i] = NULL; - if (luaD_rawrunprotected(L, f_luaopen, NULL) != LUA_OK) { - /* memory allocation error: free partial state */ - close_state(L); - L = NULL; - } - return L; -} - - -LUA_API void lua_close (lua_State *L) { - L = G(L)->mainthread; /* only the main thread can be closed */ - lua_lock(L); - close_state(L); -} - - diff --git a/lib/lua-5.3/src/lstate.h b/lib/lua-5.3/src/lstate.h deleted file mode 100644 index 56b3741..0000000 --- a/lib/lua-5.3/src/lstate.h +++ /dev/null @@ -1,253 +0,0 @@ -/* -** $Id: lstate.h,v 2.133.1.1 2017/04/19 17:39:34 roberto Exp $ -** Global State -** See Copyright Notice in lua.h -*/ - -#ifndef lstate_h -#define lstate_h - -#include "lua.h" - -#include "lobject.h" -#include "ltm.h" -#include "lzio.h" - - -/* - -** Some notes about garbage-collected objects: All objects in Lua must -** be kept somehow accessible until being freed, so all objects always -** belong to one (and only one) of these lists, using field 'next' of -** the 'CommonHeader' for the link: -** -** 'allgc': all objects not marked for finalization; -** 'finobj': all objects marked for finalization; -** 'tobefnz': all objects ready to be finalized; -** 'fixedgc': all objects that are not to be collected (currently -** only small strings, such as reserved words). -** -** Moreover, there is another set of lists that control gray objects. -** These lists are linked by fields 'gclist'. (All objects that -** can become gray have such a field. The field is not the same -** in all objects, but it always has this name.) Any gray object -** must belong to one of these lists, and all objects in these lists -** must be gray: -** -** 'gray': regular gray objects, still waiting to be visited. -** 'grayagain': objects that must be revisited at the atomic phase. -** That includes -** - black objects got in a write barrier; -** - all kinds of weak tables during propagation phase; -** - all threads. -** 'weak': tables with weak values to be cleared; -** 'ephemeron': ephemeron tables with white->white entries; -** 'allweak': tables with weak keys and/or weak values to be cleared. -** The last three lists are used only during the atomic phase. - -*/ - - -struct lua_longjmp; /* defined in ldo.c */ - - -/* -** Atomic type (relative to signals) to better ensure that 'lua_sethook' -** is thread safe -*/ -#if !defined(l_signalT) -#include -#define l_signalT sig_atomic_t -#endif - - -/* extra stack space to handle TM calls and some other extras */ -#define EXTRA_STACK 5 - - -#define BASIC_STACK_SIZE (2*LUA_MINSTACK) - - -/* kinds of Garbage Collection */ -#define KGC_NORMAL 0 -#define KGC_EMERGENCY 1 /* gc was forced by an allocation failure */ - - -typedef struct stringtable { - TString **hash; - int nuse; /* number of elements */ - int size; -} stringtable; - - -/* -** Information about a call. -** When a thread yields, 'func' is adjusted to pretend that the -** top function has only the yielded values in its stack; in that -** case, the actual 'func' value is saved in field 'extra'. -** When a function calls another with a continuation, 'extra' keeps -** the function index so that, in case of errors, the continuation -** function can be called with the correct top. -*/ -typedef struct CallInfo { - StkId func; /* function index in the stack */ - StkId top; /* top for this function */ - struct CallInfo *previous, *next; /* dynamic call link */ - union { - struct { /* only for Lua functions */ - StkId base; /* base for this function */ - const Instruction *savedpc; - } l; - struct { /* only for C functions */ - lua_KFunction k; /* continuation in case of yields */ - ptrdiff_t old_errfunc; - lua_KContext ctx; /* context info. in case of yields */ - } c; - } u; - ptrdiff_t extra; - short nresults; /* expected number of results from this function */ - unsigned short callstatus; -} CallInfo; - - -/* -** Bits in CallInfo status -*/ -#define CIST_OAH (1<<0) /* original value of 'allowhook' */ -#define CIST_LUA (1<<1) /* call is running a Lua function */ -#define CIST_HOOKED (1<<2) /* call is running a debug hook */ -#define CIST_FRESH (1<<3) /* call is running on a fresh invocation - of luaV_execute */ -#define CIST_YPCALL (1<<4) /* call is a yieldable protected call */ -#define CIST_TAIL (1<<5) /* call was tail called */ -#define CIST_HOOKYIELD (1<<6) /* last hook called yielded */ -#define CIST_LEQ (1<<7) /* using __lt for __le */ -#define CIST_FIN (1<<8) /* call is running a finalizer */ - -#define isLua(ci) ((ci)->callstatus & CIST_LUA) - -/* assume that CIST_OAH has offset 0 and that 'v' is strictly 0/1 */ -#define setoah(st,v) ((st) = ((st) & ~CIST_OAH) | (v)) -#define getoah(st) ((st) & CIST_OAH) - - -/* -** 'global state', shared by all threads of this state -*/ -typedef struct global_State { - lua_Alloc frealloc; /* function to reallocate memory */ - void *ud; /* auxiliary data to 'frealloc' */ - l_mem totalbytes; /* number of bytes currently allocated - GCdebt */ - l_mem GCdebt; /* bytes allocated not yet compensated by the collector */ - lu_mem GCmemtrav; /* memory traversed by the GC */ - lu_mem GCestimate; /* an estimate of the non-garbage memory in use */ - stringtable strt; /* hash table for strings */ - TValue l_registry; - unsigned int seed; /* randomized seed for hashes */ - lu_byte currentwhite; - lu_byte gcstate; /* state of garbage collector */ - lu_byte gckind; /* kind of GC running */ - lu_byte gcrunning; /* true if GC is running */ - GCObject *allgc; /* list of all collectable objects */ - GCObject **sweepgc; /* current position of sweep in list */ - GCObject *finobj; /* list of collectable objects with finalizers */ - GCObject *gray; /* list of gray objects */ - GCObject *grayagain; /* list of objects to be traversed atomically */ - GCObject *weak; /* list of tables with weak values */ - GCObject *ephemeron; /* list of ephemeron tables (weak keys) */ - GCObject *allweak; /* list of all-weak tables */ - GCObject *tobefnz; /* list of userdata to be GC */ - GCObject *fixedgc; /* list of objects not to be collected */ - struct lua_State *twups; /* list of threads with open upvalues */ - unsigned int gcfinnum; /* number of finalizers to call in each GC step */ - int gcpause; /* size of pause between successive GCs */ - int gcstepmul; /* GC 'granularity' */ - lua_CFunction panic; /* to be called in unprotected errors */ - struct lua_State *mainthread; - const lua_Number *version; /* pointer to version number */ - TString *memerrmsg; /* memory-error message */ - TString *tmname[TM_N]; /* array with tag-method names */ - struct Table *mt[LUA_NUMTAGS]; /* metatables for basic types */ - TString *strcache[STRCACHE_N][STRCACHE_M]; /* cache for strings in API */ -} global_State; - - -/* -** 'per thread' state -*/ -struct lua_State { - CommonHeader; - unsigned short nci; /* number of items in 'ci' list */ - lu_byte status; - StkId top; /* first free slot in the stack */ - global_State *l_G; - CallInfo *ci; /* call info for current function */ - const Instruction *oldpc; /* last pc traced */ - StkId stack_last; /* last free slot in the stack */ - StkId stack; /* stack base */ - UpVal *openupval; /* list of open upvalues in this stack */ - GCObject *gclist; - struct lua_State *twups; /* list of threads with open upvalues */ - struct lua_longjmp *errorJmp; /* current error recover point */ - CallInfo base_ci; /* CallInfo for first level (C calling Lua) */ - volatile lua_Hook hook; - ptrdiff_t errfunc; /* current error handling function (stack index) */ - int stacksize; - int basehookcount; - int hookcount; - unsigned short nny; /* number of non-yieldable calls in stack */ - unsigned short nCcalls; /* number of nested C calls */ - l_signalT hookmask; - lu_byte allowhook; -}; - - -#define G(L) (L->l_G) - - -/* -** Union of all collectable objects (only for conversions) -*/ -union GCUnion { - GCObject gc; /* common header */ - struct TString ts; - struct Udata u; - union Closure cl; - struct Table h; - struct Proto p; - struct lua_State th; /* thread */ -}; - - -#define cast_u(o) cast(union GCUnion *, (o)) - -/* macros to convert a GCObject into a specific value */ -#define gco2ts(o) \ - check_exp(novariant((o)->tt) == LUA_TSTRING, &((cast_u(o))->ts)) -#define gco2u(o) check_exp((o)->tt == LUA_TUSERDATA, &((cast_u(o))->u)) -#define gco2lcl(o) check_exp((o)->tt == LUA_TLCL, &((cast_u(o))->cl.l)) -#define gco2ccl(o) check_exp((o)->tt == LUA_TCCL, &((cast_u(o))->cl.c)) -#define gco2cl(o) \ - check_exp(novariant((o)->tt) == LUA_TFUNCTION, &((cast_u(o))->cl)) -#define gco2t(o) check_exp((o)->tt == LUA_TTABLE, &((cast_u(o))->h)) -#define gco2p(o) check_exp((o)->tt == LUA_TPROTO, &((cast_u(o))->p)) -#define gco2th(o) check_exp((o)->tt == LUA_TTHREAD, &((cast_u(o))->th)) - - -/* macro to convert a Lua object into a GCObject */ -#define obj2gco(v) \ - check_exp(novariant((v)->tt) < LUA_TDEADKEY, (&(cast_u(v)->gc))) - - -/* actual number of total bytes allocated */ -#define gettotalbytes(g) cast(lu_mem, (g)->totalbytes + (g)->GCdebt) - -LUAI_FUNC void luaE_setdebt (global_State *g, l_mem debt); -LUAI_FUNC void luaE_freethread (lua_State *L, lua_State *L1); -LUAI_FUNC CallInfo *luaE_extendCI (lua_State *L); -LUAI_FUNC void luaE_freeCI (lua_State *L); -LUAI_FUNC void luaE_shrinkCI (lua_State *L); - - -#endif - diff --git a/lib/lua-5.3/src/lstring.c b/lib/lua-5.3/src/lstring.c deleted file mode 100644 index 6257f21..0000000 --- a/lib/lua-5.3/src/lstring.c +++ /dev/null @@ -1,248 +0,0 @@ -/* -** $Id: lstring.c,v 2.56.1.1 2017/04/19 17:20:42 roberto Exp $ -** String table (keeps all strings handled by Lua) -** See Copyright Notice in lua.h -*/ - -#define lstring_c -#define LUA_CORE - -#include "lprefix.h" - - -#include - -#include "lua.h" - -#include "ldebug.h" -#include "ldo.h" -#include "lmem.h" -#include "lobject.h" -#include "lstate.h" -#include "lstring.h" - - -#define MEMERRMSG "not enough memory" - - -/* -** Lua will use at most ~(2^LUAI_HASHLIMIT) bytes from a string to -** compute its hash -*/ -#if !defined(LUAI_HASHLIMIT) -#define LUAI_HASHLIMIT 5 -#endif - - -/* -** equality for long strings -*/ -int luaS_eqlngstr (TString *a, TString *b) { - size_t len = a->u.lnglen; - lua_assert(a->tt == LUA_TLNGSTR && b->tt == LUA_TLNGSTR); - return (a == b) || /* same instance or... */ - ((len == b->u.lnglen) && /* equal length and ... */ - (memcmp(getstr(a), getstr(b), len) == 0)); /* equal contents */ -} - - -unsigned int luaS_hash (const char *str, size_t l, unsigned int seed) { - unsigned int h = seed ^ cast(unsigned int, l); - size_t step = (l >> LUAI_HASHLIMIT) + 1; - for (; l >= step; l -= step) - h ^= ((h<<5) + (h>>2) + cast_byte(str[l - 1])); - return h; -} - - -unsigned int luaS_hashlongstr (TString *ts) { - lua_assert(ts->tt == LUA_TLNGSTR); - if (ts->extra == 0) { /* no hash? */ - ts->hash = luaS_hash(getstr(ts), ts->u.lnglen, ts->hash); - ts->extra = 1; /* now it has its hash */ - } - return ts->hash; -} - - -/* -** resizes the string table -*/ -void luaS_resize (lua_State *L, int newsize) { - int i; - stringtable *tb = &G(L)->strt; - if (newsize > tb->size) { /* grow table if needed */ - luaM_reallocvector(L, tb->hash, tb->size, newsize, TString *); - for (i = tb->size; i < newsize; i++) - tb->hash[i] = NULL; - } - for (i = 0; i < tb->size; i++) { /* rehash */ - TString *p = tb->hash[i]; - tb->hash[i] = NULL; - while (p) { /* for each node in the list */ - TString *hnext = p->u.hnext; /* save next */ - unsigned int h = lmod(p->hash, newsize); /* new position */ - p->u.hnext = tb->hash[h]; /* chain it */ - tb->hash[h] = p; - p = hnext; - } - } - if (newsize < tb->size) { /* shrink table if needed */ - /* vanishing slice should be empty */ - lua_assert(tb->hash[newsize] == NULL && tb->hash[tb->size - 1] == NULL); - luaM_reallocvector(L, tb->hash, tb->size, newsize, TString *); - } - tb->size = newsize; -} - - -/* -** Clear API string cache. (Entries cannot be empty, so fill them with -** a non-collectable string.) -*/ -void luaS_clearcache (global_State *g) { - int i, j; - for (i = 0; i < STRCACHE_N; i++) - for (j = 0; j < STRCACHE_M; j++) { - if (iswhite(g->strcache[i][j])) /* will entry be collected? */ - g->strcache[i][j] = g->memerrmsg; /* replace it with something fixed */ - } -} - - -/* -** Initialize the string table and the string cache -*/ -void luaS_init (lua_State *L) { - global_State *g = G(L); - int i, j; - luaS_resize(L, MINSTRTABSIZE); /* initial size of string table */ - /* pre-create memory-error message */ - g->memerrmsg = luaS_newliteral(L, MEMERRMSG); - luaC_fix(L, obj2gco(g->memerrmsg)); /* it should never be collected */ - for (i = 0; i < STRCACHE_N; i++) /* fill cache with valid strings */ - for (j = 0; j < STRCACHE_M; j++) - g->strcache[i][j] = g->memerrmsg; -} - - - -/* -** creates a new string object -*/ -static TString *createstrobj (lua_State *L, size_t l, int tag, unsigned int h) { - TString *ts; - GCObject *o; - size_t totalsize; /* total size of TString object */ - totalsize = sizelstring(l); - o = luaC_newobj(L, tag, totalsize); - ts = gco2ts(o); - ts->hash = h; - ts->extra = 0; - getstr(ts)[l] = '\0'; /* ending 0 */ - return ts; -} - - -TString *luaS_createlngstrobj (lua_State *L, size_t l) { - TString *ts = createstrobj(L, l, LUA_TLNGSTR, G(L)->seed); - ts->u.lnglen = l; - return ts; -} - - -void luaS_remove (lua_State *L, TString *ts) { - stringtable *tb = &G(L)->strt; - TString **p = &tb->hash[lmod(ts->hash, tb->size)]; - while (*p != ts) /* find previous element */ - p = &(*p)->u.hnext; - *p = (*p)->u.hnext; /* remove element from its list */ - tb->nuse--; -} - - -/* -** checks whether short string exists and reuses it or creates a new one -*/ -static TString *internshrstr (lua_State *L, const char *str, size_t l) { - TString *ts; - global_State *g = G(L); - unsigned int h = luaS_hash(str, l, g->seed); - TString **list = &g->strt.hash[lmod(h, g->strt.size)]; - lua_assert(str != NULL); /* otherwise 'memcmp'/'memcpy' are undefined */ - for (ts = *list; ts != NULL; ts = ts->u.hnext) { - if (l == ts->shrlen && - (memcmp(str, getstr(ts), l * sizeof(char)) == 0)) { - /* found! */ - if (isdead(g, ts)) /* dead (but not collected yet)? */ - changewhite(ts); /* resurrect it */ - return ts; - } - } - if (g->strt.nuse >= g->strt.size && g->strt.size <= MAX_INT/2) { - luaS_resize(L, g->strt.size * 2); - list = &g->strt.hash[lmod(h, g->strt.size)]; /* recompute with new size */ - } - ts = createstrobj(L, l, LUA_TSHRSTR, h); - memcpy(getstr(ts), str, l * sizeof(char)); - ts->shrlen = cast_byte(l); - ts->u.hnext = *list; - *list = ts; - g->strt.nuse++; - return ts; -} - - -/* -** new string (with explicit length) -*/ -TString *luaS_newlstr (lua_State *L, const char *str, size_t l) { - if (l <= LUAI_MAXSHORTLEN) /* short string? */ - return internshrstr(L, str, l); - else { - TString *ts; - if (l >= (MAX_SIZE - sizeof(TString))/sizeof(char)) - luaM_toobig(L); - ts = luaS_createlngstrobj(L, l); - memcpy(getstr(ts), str, l * sizeof(char)); - return ts; - } -} - - -/* -** Create or reuse a zero-terminated string, first checking in the -** cache (using the string address as a key). The cache can contain -** only zero-terminated strings, so it is safe to use 'strcmp' to -** check hits. -*/ -TString *luaS_new (lua_State *L, const char *str) { - unsigned int i = point2uint(str) % STRCACHE_N; /* hash */ - int j; - TString **p = G(L)->strcache[i]; - for (j = 0; j < STRCACHE_M; j++) { - if (strcmp(str, getstr(p[j])) == 0) /* hit? */ - return p[j]; /* that is it */ - } - /* normal route */ - for (j = STRCACHE_M - 1; j > 0; j--) - p[j] = p[j - 1]; /* move out last element */ - /* new element is first in the list */ - p[0] = luaS_newlstr(L, str, strlen(str)); - return p[0]; -} - - -Udata *luaS_newudata (lua_State *L, size_t s) { - Udata *u; - GCObject *o; - if (s > MAX_SIZE - sizeof(Udata)) - luaM_toobig(L); - o = luaC_newobj(L, LUA_TUSERDATA, sizeludata(s)); - u = gco2u(o); - u->len = s; - u->metatable = NULL; - setuservalue(L, u, luaO_nilobject); - return u; -} - diff --git a/lib/lua-5.3/src/lstring.h b/lib/lua-5.3/src/lstring.h deleted file mode 100644 index d612abd..0000000 --- a/lib/lua-5.3/src/lstring.h +++ /dev/null @@ -1,49 +0,0 @@ -/* -** $Id: lstring.h,v 1.61.1.1 2017/04/19 17:20:42 roberto Exp $ -** String table (keep all strings handled by Lua) -** See Copyright Notice in lua.h -*/ - -#ifndef lstring_h -#define lstring_h - -#include "lgc.h" -#include "lobject.h" -#include "lstate.h" - - -#define sizelstring(l) (sizeof(union UTString) + ((l) + 1) * sizeof(char)) - -#define sizeludata(l) (sizeof(union UUdata) + (l)) -#define sizeudata(u) sizeludata((u)->len) - -#define luaS_newliteral(L, s) (luaS_newlstr(L, "" s, \ - (sizeof(s)/sizeof(char))-1)) - - -/* -** test whether a string is a reserved word -*/ -#define isreserved(s) ((s)->tt == LUA_TSHRSTR && (s)->extra > 0) - - -/* -** equality for short strings, which are always internalized -*/ -#define eqshrstr(a,b) check_exp((a)->tt == LUA_TSHRSTR, (a) == (b)) - - -LUAI_FUNC unsigned int luaS_hash (const char *str, size_t l, unsigned int seed); -LUAI_FUNC unsigned int luaS_hashlongstr (TString *ts); -LUAI_FUNC int luaS_eqlngstr (TString *a, TString *b); -LUAI_FUNC void luaS_resize (lua_State *L, int newsize); -LUAI_FUNC void luaS_clearcache (global_State *g); -LUAI_FUNC void luaS_init (lua_State *L); -LUAI_FUNC void luaS_remove (lua_State *L, TString *ts); -LUAI_FUNC Udata *luaS_newudata (lua_State *L, size_t s); -LUAI_FUNC TString *luaS_newlstr (lua_State *L, const char *str, size_t l); -LUAI_FUNC TString *luaS_new (lua_State *L, const char *str); -LUAI_FUNC TString *luaS_createlngstrobj (lua_State *L, size_t l); - - -#endif diff --git a/lib/lua-5.3/src/lstrlib.c b/lib/lua-5.3/src/lstrlib.c deleted file mode 100644 index b4bed7e..0000000 --- a/lib/lua-5.3/src/lstrlib.c +++ /dev/null @@ -1,1584 +0,0 @@ -/* -** $Id: lstrlib.c,v 1.254.1.1 2017/04/19 17:29:57 roberto Exp $ -** Standard library for string operations and pattern-matching -** See Copyright Notice in lua.h -*/ - -#define lstrlib_c -#define LUA_LIB - -#include "lprefix.h" - - -#include -#include -#include -#include -#include -#include -#include -#include - -#include "lua.h" - -#include "lauxlib.h" -#include "lualib.h" - - -/* -** maximum number of captures that a pattern can do during -** pattern-matching. This limit is arbitrary, but must fit in -** an unsigned char. -*/ -#if !defined(LUA_MAXCAPTURES) -#define LUA_MAXCAPTURES 32 -#endif - - -/* macro to 'unsign' a character */ -#define uchar(c) ((unsigned char)(c)) - - -/* -** Some sizes are better limited to fit in 'int', but must also fit in -** 'size_t'. (We assume that 'lua_Integer' cannot be smaller than 'int'.) -*/ -#define MAX_SIZET ((size_t)(~(size_t)0)) - -#define MAXSIZE \ - (sizeof(size_t) < sizeof(int) ? MAX_SIZET : (size_t)(INT_MAX)) - - - - -static int str_len (lua_State *L) { - size_t l; - luaL_checklstring(L, 1, &l); - lua_pushinteger(L, (lua_Integer)l); - return 1; -} - - -/* translate a relative string position: negative means back from end */ -static lua_Integer posrelat (lua_Integer pos, size_t len) { - if (pos >= 0) return pos; - else if (0u - (size_t)pos > len) return 0; - else return (lua_Integer)len + pos + 1; -} - - -static int str_sub (lua_State *L) { - size_t l; - const char *s = luaL_checklstring(L, 1, &l); - lua_Integer start = posrelat(luaL_checkinteger(L, 2), l); - lua_Integer end = posrelat(luaL_optinteger(L, 3, -1), l); - if (start < 1) start = 1; - if (end > (lua_Integer)l) end = l; - if (start <= end) - lua_pushlstring(L, s + start - 1, (size_t)(end - start) + 1); - else lua_pushliteral(L, ""); - return 1; -} - - -static int str_reverse (lua_State *L) { - size_t l, i; - luaL_Buffer b; - const char *s = luaL_checklstring(L, 1, &l); - char *p = luaL_buffinitsize(L, &b, l); - for (i = 0; i < l; i++) - p[i] = s[l - i - 1]; - luaL_pushresultsize(&b, l); - return 1; -} - - -static int str_lower (lua_State *L) { - size_t l; - size_t i; - luaL_Buffer b; - const char *s = luaL_checklstring(L, 1, &l); - char *p = luaL_buffinitsize(L, &b, l); - for (i=0; i MAXSIZE / n) /* may overflow? */ - return luaL_error(L, "resulting string too large"); - else { - size_t totallen = (size_t)n * l + (size_t)(n - 1) * lsep; - luaL_Buffer b; - char *p = luaL_buffinitsize(L, &b, totallen); - while (n-- > 1) { /* first n-1 copies (followed by separator) */ - memcpy(p, s, l * sizeof(char)); p += l; - if (lsep > 0) { /* empty 'memcpy' is not that cheap */ - memcpy(p, sep, lsep * sizeof(char)); - p += lsep; - } - } - memcpy(p, s, l * sizeof(char)); /* last copy (not followed by separator) */ - luaL_pushresultsize(&b, totallen); - } - return 1; -} - - -static int str_byte (lua_State *L) { - size_t l; - const char *s = luaL_checklstring(L, 1, &l); - lua_Integer posi = posrelat(luaL_optinteger(L, 2, 1), l); - lua_Integer pose = posrelat(luaL_optinteger(L, 3, posi), l); - int n, i; - if (posi < 1) posi = 1; - if (pose > (lua_Integer)l) pose = l; - if (posi > pose) return 0; /* empty interval; return no values */ - if (pose - posi >= INT_MAX) /* arithmetic overflow? */ - return luaL_error(L, "string slice too long"); - n = (int)(pose - posi) + 1; - luaL_checkstack(L, n, "string slice too long"); - for (i=0; i= ms->level || ms->capture[l].len == CAP_UNFINISHED) - return luaL_error(ms->L, "invalid capture index %%%d", l + 1); - return l; -} - - -static int capture_to_close (MatchState *ms) { - int level = ms->level; - for (level--; level>=0; level--) - if (ms->capture[level].len == CAP_UNFINISHED) return level; - return luaL_error(ms->L, "invalid pattern capture"); -} - - -static const char *classend (MatchState *ms, const char *p) { - switch (*p++) { - case L_ESC: { - if (p == ms->p_end) - luaL_error(ms->L, "malformed pattern (ends with '%%')"); - return p+1; - } - case '[': { - if (*p == '^') p++; - do { /* look for a ']' */ - if (p == ms->p_end) - luaL_error(ms->L, "malformed pattern (missing ']')"); - if (*(p++) == L_ESC && p < ms->p_end) - p++; /* skip escapes (e.g. '%]') */ - } while (*p != ']'); - return p+1; - } - default: { - return p; - } - } -} - - -static int match_class (int c, int cl) { - int res; - switch (tolower(cl)) { - case 'a' : res = isalpha(c); break; - case 'c' : res = iscntrl(c); break; - case 'd' : res = isdigit(c); break; - case 'g' : res = isgraph(c); break; - case 'l' : res = islower(c); break; - case 'p' : res = ispunct(c); break; - case 's' : res = isspace(c); break; - case 'u' : res = isupper(c); break; - case 'w' : res = isalnum(c); break; - case 'x' : res = isxdigit(c); break; - case 'z' : res = (c == 0); break; /* deprecated option */ - default: return (cl == c); - } - return (islower(cl) ? res : !res); -} - - -static int matchbracketclass (int c, const char *p, const char *ec) { - int sig = 1; - if (*(p+1) == '^') { - sig = 0; - p++; /* skip the '^' */ - } - while (++p < ec) { - if (*p == L_ESC) { - p++; - if (match_class(c, uchar(*p))) - return sig; - } - else if ((*(p+1) == '-') && (p+2 < ec)) { - p+=2; - if (uchar(*(p-2)) <= c && c <= uchar(*p)) - return sig; - } - else if (uchar(*p) == c) return sig; - } - return !sig; -} - - -static int singlematch (MatchState *ms, const char *s, const char *p, - const char *ep) { - if (s >= ms->src_end) - return 0; - else { - int c = uchar(*s); - switch (*p) { - case '.': return 1; /* matches any char */ - case L_ESC: return match_class(c, uchar(*(p+1))); - case '[': return matchbracketclass(c, p, ep-1); - default: return (uchar(*p) == c); - } - } -} - - -static const char *matchbalance (MatchState *ms, const char *s, - const char *p) { - if (p >= ms->p_end - 1) - luaL_error(ms->L, "malformed pattern (missing arguments to '%%b')"); - if (*s != *p) return NULL; - else { - int b = *p; - int e = *(p+1); - int cont = 1; - while (++s < ms->src_end) { - if (*s == e) { - if (--cont == 0) return s+1; - } - else if (*s == b) cont++; - } - } - return NULL; /* string ends out of balance */ -} - - -static const char *max_expand (MatchState *ms, const char *s, - const char *p, const char *ep) { - ptrdiff_t i = 0; /* counts maximum expand for item */ - while (singlematch(ms, s + i, p, ep)) - i++; - /* keeps trying to match with the maximum repetitions */ - while (i>=0) { - const char *res = match(ms, (s+i), ep+1); - if (res) return res; - i--; /* else didn't match; reduce 1 repetition to try again */ - } - return NULL; -} - - -static const char *min_expand (MatchState *ms, const char *s, - const char *p, const char *ep) { - for (;;) { - const char *res = match(ms, s, ep+1); - if (res != NULL) - return res; - else if (singlematch(ms, s, p, ep)) - s++; /* try with one more repetition */ - else return NULL; - } -} - - -static const char *start_capture (MatchState *ms, const char *s, - const char *p, int what) { - const char *res; - int level = ms->level; - if (level >= LUA_MAXCAPTURES) luaL_error(ms->L, "too many captures"); - ms->capture[level].init = s; - ms->capture[level].len = what; - ms->level = level+1; - if ((res=match(ms, s, p)) == NULL) /* match failed? */ - ms->level--; /* undo capture */ - return res; -} - - -static const char *end_capture (MatchState *ms, const char *s, - const char *p) { - int l = capture_to_close(ms); - const char *res; - ms->capture[l].len = s - ms->capture[l].init; /* close capture */ - if ((res = match(ms, s, p)) == NULL) /* match failed? */ - ms->capture[l].len = CAP_UNFINISHED; /* undo capture */ - return res; -} - - -static const char *match_capture (MatchState *ms, const char *s, int l) { - size_t len; - l = check_capture(ms, l); - len = ms->capture[l].len; - if ((size_t)(ms->src_end-s) >= len && - memcmp(ms->capture[l].init, s, len) == 0) - return s+len; - else return NULL; -} - - -static const char *match (MatchState *ms, const char *s, const char *p) { - if (ms->matchdepth-- == 0) - luaL_error(ms->L, "pattern too complex"); - init: /* using goto's to optimize tail recursion */ - if (p != ms->p_end) { /* end of pattern? */ - switch (*p) { - case '(': { /* start capture */ - if (*(p + 1) == ')') /* position capture? */ - s = start_capture(ms, s, p + 2, CAP_POSITION); - else - s = start_capture(ms, s, p + 1, CAP_UNFINISHED); - break; - } - case ')': { /* end capture */ - s = end_capture(ms, s, p + 1); - break; - } - case '$': { - if ((p + 1) != ms->p_end) /* is the '$' the last char in pattern? */ - goto dflt; /* no; go to default */ - s = (s == ms->src_end) ? s : NULL; /* check end of string */ - break; - } - case L_ESC: { /* escaped sequences not in the format class[*+?-]? */ - switch (*(p + 1)) { - case 'b': { /* balanced string? */ - s = matchbalance(ms, s, p + 2); - if (s != NULL) { - p += 4; goto init; /* return match(ms, s, p + 4); */ - } /* else fail (s == NULL) */ - break; - } - case 'f': { /* frontier? */ - const char *ep; char previous; - p += 2; - if (*p != '[') - luaL_error(ms->L, "missing '[' after '%%f' in pattern"); - ep = classend(ms, p); /* points to what is next */ - previous = (s == ms->src_init) ? '\0' : *(s - 1); - if (!matchbracketclass(uchar(previous), p, ep - 1) && - matchbracketclass(uchar(*s), p, ep - 1)) { - p = ep; goto init; /* return match(ms, s, ep); */ - } - s = NULL; /* match failed */ - break; - } - case '0': case '1': case '2': case '3': - case '4': case '5': case '6': case '7': - case '8': case '9': { /* capture results (%0-%9)? */ - s = match_capture(ms, s, uchar(*(p + 1))); - if (s != NULL) { - p += 2; goto init; /* return match(ms, s, p + 2) */ - } - break; - } - default: goto dflt; - } - break; - } - default: dflt: { /* pattern class plus optional suffix */ - const char *ep = classend(ms, p); /* points to optional suffix */ - /* does not match at least once? */ - if (!singlematch(ms, s, p, ep)) { - if (*ep == '*' || *ep == '?' || *ep == '-') { /* accept empty? */ - p = ep + 1; goto init; /* return match(ms, s, ep + 1); */ - } - else /* '+' or no suffix */ - s = NULL; /* fail */ - } - else { /* matched once */ - switch (*ep) { /* handle optional suffix */ - case '?': { /* optional */ - const char *res; - if ((res = match(ms, s + 1, ep + 1)) != NULL) - s = res; - else { - p = ep + 1; goto init; /* else return match(ms, s, ep + 1); */ - } - break; - } - case '+': /* 1 or more repetitions */ - s++; /* 1 match already done */ - /* FALLTHROUGH */ - case '*': /* 0 or more repetitions */ - s = max_expand(ms, s, p, ep); - break; - case '-': /* 0 or more repetitions (minimum) */ - s = min_expand(ms, s, p, ep); - break; - default: /* no suffix */ - s++; p = ep; goto init; /* return match(ms, s + 1, ep); */ - } - } - break; - } - } - } - ms->matchdepth++; - return s; -} - - - -static const char *lmemfind (const char *s1, size_t l1, - const char *s2, size_t l2) { - if (l2 == 0) return s1; /* empty strings are everywhere */ - else if (l2 > l1) return NULL; /* avoids a negative 'l1' */ - else { - const char *init; /* to search for a '*s2' inside 's1' */ - l2--; /* 1st char will be checked by 'memchr' */ - l1 = l1-l2; /* 's2' cannot be found after that */ - while (l1 > 0 && (init = (const char *)memchr(s1, *s2, l1)) != NULL) { - init++; /* 1st char is already checked */ - if (memcmp(init, s2+1, l2) == 0) - return init-1; - else { /* correct 'l1' and 's1' to try again */ - l1 -= init-s1; - s1 = init; - } - } - return NULL; /* not found */ - } -} - - -static void push_onecapture (MatchState *ms, int i, const char *s, - const char *e) { - if (i >= ms->level) { - if (i == 0) /* ms->level == 0, too */ - lua_pushlstring(ms->L, s, e - s); /* add whole match */ - else - luaL_error(ms->L, "invalid capture index %%%d", i + 1); - } - else { - ptrdiff_t l = ms->capture[i].len; - if (l == CAP_UNFINISHED) luaL_error(ms->L, "unfinished capture"); - if (l == CAP_POSITION) - lua_pushinteger(ms->L, (ms->capture[i].init - ms->src_init) + 1); - else - lua_pushlstring(ms->L, ms->capture[i].init, l); - } -} - - -static int push_captures (MatchState *ms, const char *s, const char *e) { - int i; - int nlevels = (ms->level == 0 && s) ? 1 : ms->level; - luaL_checkstack(ms->L, nlevels, "too many captures"); - for (i = 0; i < nlevels; i++) - push_onecapture(ms, i, s, e); - return nlevels; /* number of strings pushed */ -} - - -/* check whether pattern has no special characters */ -static int nospecials (const char *p, size_t l) { - size_t upto = 0; - do { - if (strpbrk(p + upto, SPECIALS)) - return 0; /* pattern has a special character */ - upto += strlen(p + upto) + 1; /* may have more after \0 */ - } while (upto <= l); - return 1; /* no special chars found */ -} - - -static void prepstate (MatchState *ms, lua_State *L, - const char *s, size_t ls, const char *p, size_t lp) { - ms->L = L; - ms->matchdepth = MAXCCALLS; - ms->src_init = s; - ms->src_end = s + ls; - ms->p_end = p + lp; -} - - -static void reprepstate (MatchState *ms) { - ms->level = 0; - lua_assert(ms->matchdepth == MAXCCALLS); -} - - -static int str_find_aux (lua_State *L, int find) { - size_t ls, lp; - const char *s = luaL_checklstring(L, 1, &ls); - const char *p = luaL_checklstring(L, 2, &lp); - lua_Integer init = posrelat(luaL_optinteger(L, 3, 1), ls); - if (init < 1) init = 1; - else if (init > (lua_Integer)ls + 1) { /* start after string's end? */ - lua_pushnil(L); /* cannot find anything */ - return 1; - } - /* explicit request or no special characters? */ - if (find && (lua_toboolean(L, 4) || nospecials(p, lp))) { - /* do a plain search */ - const char *s2 = lmemfind(s + init - 1, ls - (size_t)init + 1, p, lp); - if (s2) { - lua_pushinteger(L, (s2 - s) + 1); - lua_pushinteger(L, (s2 - s) + lp); - return 2; - } - } - else { - MatchState ms; - const char *s1 = s + init - 1; - int anchor = (*p == '^'); - if (anchor) { - p++; lp--; /* skip anchor character */ - } - prepstate(&ms, L, s, ls, p, lp); - do { - const char *res; - reprepstate(&ms); - if ((res=match(&ms, s1, p)) != NULL) { - if (find) { - lua_pushinteger(L, (s1 - s) + 1); /* start */ - lua_pushinteger(L, res - s); /* end */ - return push_captures(&ms, NULL, 0) + 2; - } - else - return push_captures(&ms, s1, res); - } - } while (s1++ < ms.src_end && !anchor); - } - lua_pushnil(L); /* not found */ - return 1; -} - - -static int str_find (lua_State *L) { - return str_find_aux(L, 1); -} - - -static int str_match (lua_State *L) { - return str_find_aux(L, 0); -} - - -/* state for 'gmatch' */ -typedef struct GMatchState { - const char *src; /* current position */ - const char *p; /* pattern */ - const char *lastmatch; /* end of last match */ - MatchState ms; /* match state */ -} GMatchState; - - -static int gmatch_aux (lua_State *L) { - GMatchState *gm = (GMatchState *)lua_touserdata(L, lua_upvalueindex(3)); - const char *src; - gm->ms.L = L; - for (src = gm->src; src <= gm->ms.src_end; src++) { - const char *e; - reprepstate(&gm->ms); - if ((e = match(&gm->ms, src, gm->p)) != NULL && e != gm->lastmatch) { - gm->src = gm->lastmatch = e; - return push_captures(&gm->ms, src, e); - } - } - return 0; /* not found */ -} - - -static int gmatch (lua_State *L) { - size_t ls, lp; - const char *s = luaL_checklstring(L, 1, &ls); - const char *p = luaL_checklstring(L, 2, &lp); - GMatchState *gm; - lua_settop(L, 2); /* keep them on closure to avoid being collected */ - gm = (GMatchState *)lua_newuserdata(L, sizeof(GMatchState)); - prepstate(&gm->ms, L, s, ls, p, lp); - gm->src = s; gm->p = p; gm->lastmatch = NULL; - lua_pushcclosure(L, gmatch_aux, 3); - return 1; -} - - -static void add_s (MatchState *ms, luaL_Buffer *b, const char *s, - const char *e) { - size_t l, i; - lua_State *L = ms->L; - const char *news = lua_tolstring(L, 3, &l); - for (i = 0; i < l; i++) { - if (news[i] != L_ESC) - luaL_addchar(b, news[i]); - else { - i++; /* skip ESC */ - if (!isdigit(uchar(news[i]))) { - if (news[i] != L_ESC) - luaL_error(L, "invalid use of '%c' in replacement string", L_ESC); - luaL_addchar(b, news[i]); - } - else if (news[i] == '0') - luaL_addlstring(b, s, e - s); - else { - push_onecapture(ms, news[i] - '1', s, e); - luaL_tolstring(L, -1, NULL); /* if number, convert it to string */ - lua_remove(L, -2); /* remove original value */ - luaL_addvalue(b); /* add capture to accumulated result */ - } - } - } -} - - -static void add_value (MatchState *ms, luaL_Buffer *b, const char *s, - const char *e, int tr) { - lua_State *L = ms->L; - switch (tr) { - case LUA_TFUNCTION: { - int n; - lua_pushvalue(L, 3); - n = push_captures(ms, s, e); - lua_call(L, n, 1); - break; - } - case LUA_TTABLE: { - push_onecapture(ms, 0, s, e); - lua_gettable(L, 3); - break; - } - default: { /* LUA_TNUMBER or LUA_TSTRING */ - add_s(ms, b, s, e); - return; - } - } - if (!lua_toboolean(L, -1)) { /* nil or false? */ - lua_pop(L, 1); - lua_pushlstring(L, s, e - s); /* keep original text */ - } - else if (!lua_isstring(L, -1)) - luaL_error(L, "invalid replacement value (a %s)", luaL_typename(L, -1)); - luaL_addvalue(b); /* add result to accumulator */ -} - - -static int str_gsub (lua_State *L) { - size_t srcl, lp; - const char *src = luaL_checklstring(L, 1, &srcl); /* subject */ - const char *p = luaL_checklstring(L, 2, &lp); /* pattern */ - const char *lastmatch = NULL; /* end of last match */ - int tr = lua_type(L, 3); /* replacement type */ - lua_Integer max_s = luaL_optinteger(L, 4, srcl + 1); /* max replacements */ - int anchor = (*p == '^'); - lua_Integer n = 0; /* replacement count */ - MatchState ms; - luaL_Buffer b; - luaL_argcheck(L, tr == LUA_TNUMBER || tr == LUA_TSTRING || - tr == LUA_TFUNCTION || tr == LUA_TTABLE, 3, - "string/function/table expected"); - luaL_buffinit(L, &b); - if (anchor) { - p++; lp--; /* skip anchor character */ - } - prepstate(&ms, L, src, srcl, p, lp); - while (n < max_s) { - const char *e; - reprepstate(&ms); /* (re)prepare state for new match */ - if ((e = match(&ms, src, p)) != NULL && e != lastmatch) { /* match? */ - n++; - add_value(&ms, &b, src, e, tr); /* add replacement to buffer */ - src = lastmatch = e; - } - else if (src < ms.src_end) /* otherwise, skip one character */ - luaL_addchar(&b, *src++); - else break; /* end of subject */ - if (anchor) break; - } - luaL_addlstring(&b, src, ms.src_end-src); - luaL_pushresult(&b); - lua_pushinteger(L, n); /* number of substitutions */ - return 2; -} - -/* }====================================================== */ - - - -/* -** {====================================================== -** STRING FORMAT -** ======================================================= -*/ - -#if !defined(lua_number2strx) /* { */ - -/* -** Hexadecimal floating-point formatter -*/ - -#include - -#define SIZELENMOD (sizeof(LUA_NUMBER_FRMLEN)/sizeof(char)) - - -/* -** Number of bits that goes into the first digit. It can be any value -** between 1 and 4; the following definition tries to align the number -** to nibble boundaries by making what is left after that first digit a -** multiple of 4. -*/ -#define L_NBFD ((l_mathlim(MANT_DIG) - 1)%4 + 1) - - -/* -** Add integer part of 'x' to buffer and return new 'x' -*/ -static lua_Number adddigit (char *buff, int n, lua_Number x) { - lua_Number dd = l_mathop(floor)(x); /* get integer part from 'x' */ - int d = (int)dd; - buff[n] = (d < 10 ? d + '0' : d - 10 + 'a'); /* add to buffer */ - return x - dd; /* return what is left */ -} - - -static int num2straux (char *buff, int sz, lua_Number x) { - /* if 'inf' or 'NaN', format it like '%g' */ - if (x != x || x == (lua_Number)HUGE_VAL || x == -(lua_Number)HUGE_VAL) - return l_sprintf(buff, sz, LUA_NUMBER_FMT, (LUAI_UACNUMBER)x); - else if (x == 0) { /* can be -0... */ - /* create "0" or "-0" followed by exponent */ - return l_sprintf(buff, sz, LUA_NUMBER_FMT "x0p+0", (LUAI_UACNUMBER)x); - } - else { - int e; - lua_Number m = l_mathop(frexp)(x, &e); /* 'x' fraction and exponent */ - int n = 0; /* character count */ - if (m < 0) { /* is number negative? */ - buff[n++] = '-'; /* add signal */ - m = -m; /* make it positive */ - } - buff[n++] = '0'; buff[n++] = 'x'; /* add "0x" */ - m = adddigit(buff, n++, m * (1 << L_NBFD)); /* add first digit */ - e -= L_NBFD; /* this digit goes before the radix point */ - if (m > 0) { /* more digits? */ - buff[n++] = lua_getlocaledecpoint(); /* add radix point */ - do { /* add as many digits as needed */ - m = adddigit(buff, n++, m * 16); - } while (m > 0); - } - n += l_sprintf(buff + n, sz - n, "p%+d", e); /* add exponent */ - lua_assert(n < sz); - return n; - } -} - - -static int lua_number2strx (lua_State *L, char *buff, int sz, - const char *fmt, lua_Number x) { - int n = num2straux(buff, sz, x); - if (fmt[SIZELENMOD] == 'A') { - int i; - for (i = 0; i < n; i++) - buff[i] = toupper(uchar(buff[i])); - } - else if (fmt[SIZELENMOD] != 'a') - return luaL_error(L, "modifiers for format '%%a'/'%%A' not implemented"); - return n; -} - -#endif /* } */ - - -/* -** Maximum size of each formatted item. This maximum size is produced -** by format('%.99f', -maxfloat), and is equal to 99 + 3 ('-', '.', -** and '\0') + number of decimal digits to represent maxfloat (which -** is maximum exponent + 1). (99+3+1 then rounded to 120 for "extra -** expenses", such as locale-dependent stuff) -*/ -#define MAX_ITEM (120 + l_mathlim(MAX_10_EXP)) - - -/* valid flags in a format specification */ -#define FLAGS "-+ #0" - -/* -** maximum size of each format specification (such as "%-099.99d") -*/ -#define MAX_FORMAT 32 - - -static void addquoted (luaL_Buffer *b, const char *s, size_t len) { - luaL_addchar(b, '"'); - while (len--) { - if (*s == '"' || *s == '\\' || *s == '\n') { - luaL_addchar(b, '\\'); - luaL_addchar(b, *s); - } - else if (iscntrl(uchar(*s))) { - char buff[10]; - if (!isdigit(uchar(*(s+1)))) - l_sprintf(buff, sizeof(buff), "\\%d", (int)uchar(*s)); - else - l_sprintf(buff, sizeof(buff), "\\%03d", (int)uchar(*s)); - luaL_addstring(b, buff); - } - else - luaL_addchar(b, *s); - s++; - } - luaL_addchar(b, '"'); -} - - -/* -** Ensures the 'buff' string uses a dot as the radix character. -*/ -static void checkdp (char *buff, int nb) { - if (memchr(buff, '.', nb) == NULL) { /* no dot? */ - char point = lua_getlocaledecpoint(); /* try locale point */ - char *ppoint = (char *)memchr(buff, point, nb); - if (ppoint) *ppoint = '.'; /* change it to a dot */ - } -} - - -static void addliteral (lua_State *L, luaL_Buffer *b, int arg) { - switch (lua_type(L, arg)) { - case LUA_TSTRING: { - size_t len; - const char *s = lua_tolstring(L, arg, &len); - addquoted(b, s, len); - break; - } - case LUA_TNUMBER: { - char *buff = luaL_prepbuffsize(b, MAX_ITEM); - int nb; - if (!lua_isinteger(L, arg)) { /* float? */ - lua_Number n = lua_tonumber(L, arg); /* write as hexa ('%a') */ - nb = lua_number2strx(L, buff, MAX_ITEM, "%" LUA_NUMBER_FRMLEN "a", n); - checkdp(buff, nb); /* ensure it uses a dot */ - } - else { /* integers */ - lua_Integer n = lua_tointeger(L, arg); - const char *format = (n == LUA_MININTEGER) /* corner case? */ - ? "0x%" LUA_INTEGER_FRMLEN "x" /* use hexa */ - : LUA_INTEGER_FMT; /* else use default format */ - nb = l_sprintf(buff, MAX_ITEM, format, (LUAI_UACINT)n); - } - luaL_addsize(b, nb); - break; - } - case LUA_TNIL: case LUA_TBOOLEAN: { - luaL_tolstring(L, arg, NULL); - luaL_addvalue(b); - break; - } - default: { - luaL_argerror(L, arg, "value has no literal form"); - } - } -} - - -static const char *scanformat (lua_State *L, const char *strfrmt, char *form) { - const char *p = strfrmt; - while (*p != '\0' && strchr(FLAGS, *p) != NULL) p++; /* skip flags */ - if ((size_t)(p - strfrmt) >= sizeof(FLAGS)/sizeof(char)) - luaL_error(L, "invalid format (repeated flags)"); - if (isdigit(uchar(*p))) p++; /* skip width */ - if (isdigit(uchar(*p))) p++; /* (2 digits at most) */ - if (*p == '.') { - p++; - if (isdigit(uchar(*p))) p++; /* skip precision */ - if (isdigit(uchar(*p))) p++; /* (2 digits at most) */ - } - if (isdigit(uchar(*p))) - luaL_error(L, "invalid format (width or precision too long)"); - *(form++) = '%'; - memcpy(form, strfrmt, ((p - strfrmt) + 1) * sizeof(char)); - form += (p - strfrmt) + 1; - *form = '\0'; - return p; -} - - -/* -** add length modifier into formats -*/ -static void addlenmod (char *form, const char *lenmod) { - size_t l = strlen(form); - size_t lm = strlen(lenmod); - char spec = form[l - 1]; - strcpy(form + l - 1, lenmod); - form[l + lm - 1] = spec; - form[l + lm] = '\0'; -} - - -static int str_format (lua_State *L) { - int top = lua_gettop(L); - int arg = 1; - size_t sfl; - const char *strfrmt = luaL_checklstring(L, arg, &sfl); - const char *strfrmt_end = strfrmt+sfl; - luaL_Buffer b; - luaL_buffinit(L, &b); - while (strfrmt < strfrmt_end) { - if (*strfrmt != L_ESC) - luaL_addchar(&b, *strfrmt++); - else if (*++strfrmt == L_ESC) - luaL_addchar(&b, *strfrmt++); /* %% */ - else { /* format item */ - char form[MAX_FORMAT]; /* to store the format ('%...') */ - char *buff = luaL_prepbuffsize(&b, MAX_ITEM); /* to put formatted item */ - int nb = 0; /* number of bytes in added item */ - if (++arg > top) - luaL_argerror(L, arg, "no value"); - strfrmt = scanformat(L, strfrmt, form); - switch (*strfrmt++) { - case 'c': { - nb = l_sprintf(buff, MAX_ITEM, form, (int)luaL_checkinteger(L, arg)); - break; - } - case 'd': case 'i': - case 'o': case 'u': case 'x': case 'X': { - lua_Integer n = luaL_checkinteger(L, arg); - addlenmod(form, LUA_INTEGER_FRMLEN); - nb = l_sprintf(buff, MAX_ITEM, form, (LUAI_UACINT)n); - break; - } - case 'a': case 'A': - addlenmod(form, LUA_NUMBER_FRMLEN); - nb = lua_number2strx(L, buff, MAX_ITEM, form, - luaL_checknumber(L, arg)); - break; - case 'e': case 'E': case 'f': - case 'g': case 'G': { - lua_Number n = luaL_checknumber(L, arg); - addlenmod(form, LUA_NUMBER_FRMLEN); - nb = l_sprintf(buff, MAX_ITEM, form, (LUAI_UACNUMBER)n); - break; - } - case 'q': { - addliteral(L, &b, arg); - break; - } - case 's': { - size_t l; - const char *s = luaL_tolstring(L, arg, &l); - if (form[2] == '\0') /* no modifiers? */ - luaL_addvalue(&b); /* keep entire string */ - else { - luaL_argcheck(L, l == strlen(s), arg, "string contains zeros"); - if (!strchr(form, '.') && l >= 100) { - /* no precision and string is too long to be formatted */ - luaL_addvalue(&b); /* keep entire string */ - } - else { /* format the string into 'buff' */ - nb = l_sprintf(buff, MAX_ITEM, form, s); - lua_pop(L, 1); /* remove result from 'luaL_tolstring' */ - } - } - break; - } - default: { /* also treat cases 'pnLlh' */ - return luaL_error(L, "invalid option '%%%c' to 'format'", - *(strfrmt - 1)); - } - } - lua_assert(nb < MAX_ITEM); - luaL_addsize(&b, nb); - } - } - luaL_pushresult(&b); - return 1; -} - -/* }====================================================== */ - - -/* -** {====================================================== -** PACK/UNPACK -** ======================================================= -*/ - - -/* value used for padding */ -#if !defined(LUAL_PACKPADBYTE) -#define LUAL_PACKPADBYTE 0x00 -#endif - -/* maximum size for the binary representation of an integer */ -#define MAXINTSIZE 16 - -/* number of bits in a character */ -#define NB CHAR_BIT - -/* mask for one character (NB 1's) */ -#define MC ((1 << NB) - 1) - -/* size of a lua_Integer */ -#define SZINT ((int)sizeof(lua_Integer)) - - -/* dummy union to get native endianness */ -static const union { - int dummy; - char little; /* true iff machine is little endian */ -} nativeendian = {1}; - - -/* dummy structure to get native alignment requirements */ -struct cD { - char c; - union { double d; void *p; lua_Integer i; lua_Number n; } u; -}; - -#define MAXALIGN (offsetof(struct cD, u)) - - -/* -** Union for serializing floats -*/ -typedef union Ftypes { - float f; - double d; - lua_Number n; - char buff[5 * sizeof(lua_Number)]; /* enough for any float type */ -} Ftypes; - - -/* -** information to pack/unpack stuff -*/ -typedef struct Header { - lua_State *L; - int islittle; - int maxalign; -} Header; - - -/* -** options for pack/unpack -*/ -typedef enum KOption { - Kint, /* signed integers */ - Kuint, /* unsigned integers */ - Kfloat, /* floating-point numbers */ - Kchar, /* fixed-length strings */ - Kstring, /* strings with prefixed length */ - Kzstr, /* zero-terminated strings */ - Kpadding, /* padding */ - Kpaddalign, /* padding for alignment */ - Knop /* no-op (configuration or spaces) */ -} KOption; - - -/* -** Read an integer numeral from string 'fmt' or return 'df' if -** there is no numeral -*/ -static int digit (int c) { return '0' <= c && c <= '9'; } - -static int getnum (const char **fmt, int df) { - if (!digit(**fmt)) /* no number? */ - return df; /* return default value */ - else { - int a = 0; - do { - a = a*10 + (*((*fmt)++) - '0'); - } while (digit(**fmt) && a <= ((int)MAXSIZE - 9)/10); - return a; - } -} - - -/* -** Read an integer numeral and raises an error if it is larger -** than the maximum size for integers. -*/ -static int getnumlimit (Header *h, const char **fmt, int df) { - int sz = getnum(fmt, df); - if (sz > MAXINTSIZE || sz <= 0) - return luaL_error(h->L, "integral size (%d) out of limits [1,%d]", - sz, MAXINTSIZE); - return sz; -} - - -/* -** Initialize Header -*/ -static void initheader (lua_State *L, Header *h) { - h->L = L; - h->islittle = nativeendian.little; - h->maxalign = 1; -} - - -/* -** Read and classify next option. 'size' is filled with option's size. -*/ -static KOption getoption (Header *h, const char **fmt, int *size) { - int opt = *((*fmt)++); - *size = 0; /* default */ - switch (opt) { - case 'b': *size = sizeof(char); return Kint; - case 'B': *size = sizeof(char); return Kuint; - case 'h': *size = sizeof(short); return Kint; - case 'H': *size = sizeof(short); return Kuint; - case 'l': *size = sizeof(long); return Kint; - case 'L': *size = sizeof(long); return Kuint; - case 'j': *size = sizeof(lua_Integer); return Kint; - case 'J': *size = sizeof(lua_Integer); return Kuint; - case 'T': *size = sizeof(size_t); return Kuint; - case 'f': *size = sizeof(float); return Kfloat; - case 'd': *size = sizeof(double); return Kfloat; - case 'n': *size = sizeof(lua_Number); return Kfloat; - case 'i': *size = getnumlimit(h, fmt, sizeof(int)); return Kint; - case 'I': *size = getnumlimit(h, fmt, sizeof(int)); return Kuint; - case 's': *size = getnumlimit(h, fmt, sizeof(size_t)); return Kstring; - case 'c': - *size = getnum(fmt, -1); - if (*size == -1) - luaL_error(h->L, "missing size for format option 'c'"); - return Kchar; - case 'z': return Kzstr; - case 'x': *size = 1; return Kpadding; - case 'X': return Kpaddalign; - case ' ': break; - case '<': h->islittle = 1; break; - case '>': h->islittle = 0; break; - case '=': h->islittle = nativeendian.little; break; - case '!': h->maxalign = getnumlimit(h, fmt, MAXALIGN); break; - default: luaL_error(h->L, "invalid format option '%c'", opt); - } - return Knop; -} - - -/* -** Read, classify, and fill other details about the next option. -** 'psize' is filled with option's size, 'notoalign' with its -** alignment requirements. -** Local variable 'size' gets the size to be aligned. (Kpadal option -** always gets its full alignment, other options are limited by -** the maximum alignment ('maxalign'). Kchar option needs no alignment -** despite its size. -*/ -static KOption getdetails (Header *h, size_t totalsize, - const char **fmt, int *psize, int *ntoalign) { - KOption opt = getoption(h, fmt, psize); - int align = *psize; /* usually, alignment follows size */ - if (opt == Kpaddalign) { /* 'X' gets alignment from following option */ - if (**fmt == '\0' || getoption(h, fmt, &align) == Kchar || align == 0) - luaL_argerror(h->L, 1, "invalid next option for option 'X'"); - } - if (align <= 1 || opt == Kchar) /* need no alignment? */ - *ntoalign = 0; - else { - if (align > h->maxalign) /* enforce maximum alignment */ - align = h->maxalign; - if ((align & (align - 1)) != 0) /* is 'align' not a power of 2? */ - luaL_argerror(h->L, 1, "format asks for alignment not power of 2"); - *ntoalign = (align - (int)(totalsize & (align - 1))) & (align - 1); - } - return opt; -} - - -/* -** Pack integer 'n' with 'size' bytes and 'islittle' endianness. -** The final 'if' handles the case when 'size' is larger than -** the size of a Lua integer, correcting the extra sign-extension -** bytes if necessary (by default they would be zeros). -*/ -static void packint (luaL_Buffer *b, lua_Unsigned n, - int islittle, int size, int neg) { - char *buff = luaL_prepbuffsize(b, size); - int i; - buff[islittle ? 0 : size - 1] = (char)(n & MC); /* first byte */ - for (i = 1; i < size; i++) { - n >>= NB; - buff[islittle ? i : size - 1 - i] = (char)(n & MC); - } - if (neg && size > SZINT) { /* negative number need sign extension? */ - for (i = SZINT; i < size; i++) /* correct extra bytes */ - buff[islittle ? i : size - 1 - i] = (char)MC; - } - luaL_addsize(b, size); /* add result to buffer */ -} - - -/* -** Copy 'size' bytes from 'src' to 'dest', correcting endianness if -** given 'islittle' is different from native endianness. -*/ -static void copywithendian (volatile char *dest, volatile const char *src, - int size, int islittle) { - if (islittle == nativeendian.little) { - while (size-- != 0) - *(dest++) = *(src++); - } - else { - dest += size - 1; - while (size-- != 0) - *(dest--) = *(src++); - } -} - - -static int str_pack (lua_State *L) { - luaL_Buffer b; - Header h; - const char *fmt = luaL_checkstring(L, 1); /* format string */ - int arg = 1; /* current argument to pack */ - size_t totalsize = 0; /* accumulate total size of result */ - initheader(L, &h); - lua_pushnil(L); /* mark to separate arguments from string buffer */ - luaL_buffinit(L, &b); - while (*fmt != '\0') { - int size, ntoalign; - KOption opt = getdetails(&h, totalsize, &fmt, &size, &ntoalign); - totalsize += ntoalign + size; - while (ntoalign-- > 0) - luaL_addchar(&b, LUAL_PACKPADBYTE); /* fill alignment */ - arg++; - switch (opt) { - case Kint: { /* signed integers */ - lua_Integer n = luaL_checkinteger(L, arg); - if (size < SZINT) { /* need overflow check? */ - lua_Integer lim = (lua_Integer)1 << ((size * NB) - 1); - luaL_argcheck(L, -lim <= n && n < lim, arg, "integer overflow"); - } - packint(&b, (lua_Unsigned)n, h.islittle, size, (n < 0)); - break; - } - case Kuint: { /* unsigned integers */ - lua_Integer n = luaL_checkinteger(L, arg); - if (size < SZINT) /* need overflow check? */ - luaL_argcheck(L, (lua_Unsigned)n < ((lua_Unsigned)1 << (size * NB)), - arg, "unsigned overflow"); - packint(&b, (lua_Unsigned)n, h.islittle, size, 0); - break; - } - case Kfloat: { /* floating-point options */ - volatile Ftypes u; - char *buff = luaL_prepbuffsize(&b, size); - lua_Number n = luaL_checknumber(L, arg); /* get argument */ - if (size == sizeof(u.f)) u.f = (float)n; /* copy it into 'u' */ - else if (size == sizeof(u.d)) u.d = (double)n; - else u.n = n; - /* move 'u' to final result, correcting endianness if needed */ - copywithendian(buff, u.buff, size, h.islittle); - luaL_addsize(&b, size); - break; - } - case Kchar: { /* fixed-size string */ - size_t len; - const char *s = luaL_checklstring(L, arg, &len); - luaL_argcheck(L, len <= (size_t)size, arg, - "string longer than given size"); - luaL_addlstring(&b, s, len); /* add string */ - while (len++ < (size_t)size) /* pad extra space */ - luaL_addchar(&b, LUAL_PACKPADBYTE); - break; - } - case Kstring: { /* strings with length count */ - size_t len; - const char *s = luaL_checklstring(L, arg, &len); - luaL_argcheck(L, size >= (int)sizeof(size_t) || - len < ((size_t)1 << (size * NB)), - arg, "string length does not fit in given size"); - packint(&b, (lua_Unsigned)len, h.islittle, size, 0); /* pack length */ - luaL_addlstring(&b, s, len); - totalsize += len; - break; - } - case Kzstr: { /* zero-terminated string */ - size_t len; - const char *s = luaL_checklstring(L, arg, &len); - luaL_argcheck(L, strlen(s) == len, arg, "string contains zeros"); - luaL_addlstring(&b, s, len); - luaL_addchar(&b, '\0'); /* add zero at the end */ - totalsize += len + 1; - break; - } - case Kpadding: luaL_addchar(&b, LUAL_PACKPADBYTE); /* FALLTHROUGH */ - case Kpaddalign: case Knop: - arg--; /* undo increment */ - break; - } - } - luaL_pushresult(&b); - return 1; -} - - -static int str_packsize (lua_State *L) { - Header h; - const char *fmt = luaL_checkstring(L, 1); /* format string */ - size_t totalsize = 0; /* accumulate total size of result */ - initheader(L, &h); - while (*fmt != '\0') { - int size, ntoalign; - KOption opt = getdetails(&h, totalsize, &fmt, &size, &ntoalign); - size += ntoalign; /* total space used by option */ - luaL_argcheck(L, totalsize <= MAXSIZE - size, 1, - "format result too large"); - totalsize += size; - switch (opt) { - case Kstring: /* strings with length count */ - case Kzstr: /* zero-terminated string */ - luaL_argerror(L, 1, "variable-length format"); - /* call never return, but to avoid warnings: *//* FALLTHROUGH */ - default: break; - } - } - lua_pushinteger(L, (lua_Integer)totalsize); - return 1; -} - - -/* -** Unpack an integer with 'size' bytes and 'islittle' endianness. -** If size is smaller than the size of a Lua integer and integer -** is signed, must do sign extension (propagating the sign to the -** higher bits); if size is larger than the size of a Lua integer, -** it must check the unread bytes to see whether they do not cause an -** overflow. -*/ -static lua_Integer unpackint (lua_State *L, const char *str, - int islittle, int size, int issigned) { - lua_Unsigned res = 0; - int i; - int limit = (size <= SZINT) ? size : SZINT; - for (i = limit - 1; i >= 0; i--) { - res <<= NB; - res |= (lua_Unsigned)(unsigned char)str[islittle ? i : size - 1 - i]; - } - if (size < SZINT) { /* real size smaller than lua_Integer? */ - if (issigned) { /* needs sign extension? */ - lua_Unsigned mask = (lua_Unsigned)1 << (size*NB - 1); - res = ((res ^ mask) - mask); /* do sign extension */ - } - } - else if (size > SZINT) { /* must check unread bytes */ - int mask = (!issigned || (lua_Integer)res >= 0) ? 0 : MC; - for (i = limit; i < size; i++) { - if ((unsigned char)str[islittle ? i : size - 1 - i] != mask) - luaL_error(L, "%d-byte integer does not fit into Lua Integer", size); - } - } - return (lua_Integer)res; -} - - -static int str_unpack (lua_State *L) { - Header h; - const char *fmt = luaL_checkstring(L, 1); - size_t ld; - const char *data = luaL_checklstring(L, 2, &ld); - size_t pos = (size_t)posrelat(luaL_optinteger(L, 3, 1), ld) - 1; - int n = 0; /* number of results */ - luaL_argcheck(L, pos <= ld, 3, "initial position out of string"); - initheader(L, &h); - while (*fmt != '\0') { - int size, ntoalign; - KOption opt = getdetails(&h, pos, &fmt, &size, &ntoalign); - if ((size_t)ntoalign + size > ~pos || pos + ntoalign + size > ld) - luaL_argerror(L, 2, "data string too short"); - pos += ntoalign; /* skip alignment */ - /* stack space for item + next position */ - luaL_checkstack(L, 2, "too many results"); - n++; - switch (opt) { - case Kint: - case Kuint: { - lua_Integer res = unpackint(L, data + pos, h.islittle, size, - (opt == Kint)); - lua_pushinteger(L, res); - break; - } - case Kfloat: { - volatile Ftypes u; - lua_Number num; - copywithendian(u.buff, data + pos, size, h.islittle); - if (size == sizeof(u.f)) num = (lua_Number)u.f; - else if (size == sizeof(u.d)) num = (lua_Number)u.d; - else num = u.n; - lua_pushnumber(L, num); - break; - } - case Kchar: { - lua_pushlstring(L, data + pos, size); - break; - } - case Kstring: { - size_t len = (size_t)unpackint(L, data + pos, h.islittle, size, 0); - luaL_argcheck(L, pos + len + size <= ld, 2, "data string too short"); - lua_pushlstring(L, data + pos + size, len); - pos += len; /* skip string */ - break; - } - case Kzstr: { - size_t len = (int)strlen(data + pos); - lua_pushlstring(L, data + pos, len); - pos += len + 1; /* skip string plus final '\0' */ - break; - } - case Kpaddalign: case Kpadding: case Knop: - n--; /* undo increment */ - break; - } - pos += size; - } - lua_pushinteger(L, pos + 1); /* next position */ - return n + 1; -} - -/* }====================================================== */ - - -static const luaL_Reg strlib[] = { - {"byte", str_byte}, - {"char", str_char}, - {"dump", str_dump}, - {"find", str_find}, - {"format", str_format}, - {"gmatch", gmatch}, - {"gsub", str_gsub}, - {"len", str_len}, - {"lower", str_lower}, - {"match", str_match}, - {"rep", str_rep}, - {"reverse", str_reverse}, - {"sub", str_sub}, - {"upper", str_upper}, - {"pack", str_pack}, - {"packsize", str_packsize}, - {"unpack", str_unpack}, - {NULL, NULL} -}; - - -static void createmetatable (lua_State *L) { - lua_createtable(L, 0, 1); /* table to be metatable for strings */ - lua_pushliteral(L, ""); /* dummy string */ - lua_pushvalue(L, -2); /* copy table */ - lua_setmetatable(L, -2); /* set table as metatable for strings */ - lua_pop(L, 1); /* pop dummy string */ - lua_pushvalue(L, -2); /* get string library */ - lua_setfield(L, -2, "__index"); /* metatable.__index = string */ - lua_pop(L, 1); /* pop metatable */ -} - - -/* -** Open string library -*/ -LUAMOD_API int luaopen_string (lua_State *L) { - luaL_newlib(L, strlib); - createmetatable(L); - return 1; -} - diff --git a/lib/lua-5.3/src/ltable.c b/lib/lua-5.3/src/ltable.c deleted file mode 100644 index ea4fe7f..0000000 --- a/lib/lua-5.3/src/ltable.c +++ /dev/null @@ -1,688 +0,0 @@ -/* -** $Id: ltable.c,v 2.118.1.4 2018/06/08 16:22:51 roberto Exp $ -** Lua tables (hash) -** See Copyright Notice in lua.h -*/ - -#define ltable_c -#define LUA_CORE - -#include "lprefix.h" - - -/* -** Implementation of tables (aka arrays, objects, or hash tables). -** Tables keep its elements in two parts: an array part and a hash part. -** Non-negative integer keys are all candidates to be kept in the array -** part. The actual size of the array is the largest 'n' such that -** more than half the slots between 1 and n are in use. -** Hash uses a mix of chained scatter table with Brent's variation. -** A main invariant of these tables is that, if an element is not -** in its main position (i.e. the 'original' position that its hash gives -** to it), then the colliding element is in its own main position. -** Hence even when the load factor reaches 100%, performance remains good. -*/ - -#include -#include - -#include "lua.h" - -#include "ldebug.h" -#include "ldo.h" -#include "lgc.h" -#include "lmem.h" -#include "lobject.h" -#include "lstate.h" -#include "lstring.h" -#include "ltable.h" -#include "lvm.h" - - -/* -** Maximum size of array part (MAXASIZE) is 2^MAXABITS. MAXABITS is -** the largest integer such that MAXASIZE fits in an unsigned int. -*/ -#define MAXABITS cast_int(sizeof(int) * CHAR_BIT - 1) -#define MAXASIZE (1u << MAXABITS) - -/* -** Maximum size of hash part is 2^MAXHBITS. MAXHBITS is the largest -** integer such that 2^MAXHBITS fits in a signed int. (Note that the -** maximum number of elements in a table, 2^MAXABITS + 2^MAXHBITS, still -** fits comfortably in an unsigned int.) -*/ -#define MAXHBITS (MAXABITS - 1) - - -#define hashpow2(t,n) (gnode(t, lmod((n), sizenode(t)))) - -#define hashstr(t,str) hashpow2(t, (str)->hash) -#define hashboolean(t,p) hashpow2(t, p) -#define hashint(t,i) hashpow2(t, i) - - -/* -** for some types, it is better to avoid modulus by power of 2, as -** they tend to have many 2 factors. -*/ -#define hashmod(t,n) (gnode(t, ((n) % ((sizenode(t)-1)|1)))) - - -#define hashpointer(t,p) hashmod(t, point2uint(p)) - - -#define dummynode (&dummynode_) - -static const Node dummynode_ = { - {NILCONSTANT}, /* value */ - {{NILCONSTANT, 0}} /* key */ -}; - - -/* -** Hash for floating-point numbers. -** The main computation should be just -** n = frexp(n, &i); return (n * INT_MAX) + i -** but there are some numerical subtleties. -** In a two-complement representation, INT_MAX does not has an exact -** representation as a float, but INT_MIN does; because the absolute -** value of 'frexp' is smaller than 1 (unless 'n' is inf/NaN), the -** absolute value of the product 'frexp * -INT_MIN' is smaller or equal -** to INT_MAX. Next, the use of 'unsigned int' avoids overflows when -** adding 'i'; the use of '~u' (instead of '-u') avoids problems with -** INT_MIN. -*/ -#if !defined(l_hashfloat) -static int l_hashfloat (lua_Number n) { - int i; - lua_Integer ni; - n = l_mathop(frexp)(n, &i) * -cast_num(INT_MIN); - if (!lua_numbertointeger(n, &ni)) { /* is 'n' inf/-inf/NaN? */ - lua_assert(luai_numisnan(n) || l_mathop(fabs)(n) == cast_num(HUGE_VAL)); - return 0; - } - else { /* normal case */ - unsigned int u = cast(unsigned int, i) + cast(unsigned int, ni); - return cast_int(u <= cast(unsigned int, INT_MAX) ? u : ~u); - } -} -#endif - - -/* -** returns the 'main' position of an element in a table (that is, the index -** of its hash value) -*/ -static Node *mainposition (const Table *t, const TValue *key) { - switch (ttype(key)) { - case LUA_TNUMINT: - return hashint(t, ivalue(key)); - case LUA_TNUMFLT: - return hashmod(t, l_hashfloat(fltvalue(key))); - case LUA_TSHRSTR: - return hashstr(t, tsvalue(key)); - case LUA_TLNGSTR: - return hashpow2(t, luaS_hashlongstr(tsvalue(key))); - case LUA_TBOOLEAN: - return hashboolean(t, bvalue(key)); - case LUA_TLIGHTUSERDATA: - return hashpointer(t, pvalue(key)); - case LUA_TLCF: - return hashpointer(t, fvalue(key)); - default: - lua_assert(!ttisdeadkey(key)); - return hashpointer(t, gcvalue(key)); - } -} - - -/* -** returns the index for 'key' if 'key' is an appropriate key to live in -** the array part of the table, 0 otherwise. -*/ -static unsigned int arrayindex (const TValue *key) { - if (ttisinteger(key)) { - lua_Integer k = ivalue(key); - if (0 < k && (lua_Unsigned)k <= MAXASIZE) - return cast(unsigned int, k); /* 'key' is an appropriate array index */ - } - return 0; /* 'key' did not match some condition */ -} - - -/* -** returns the index of a 'key' for table traversals. First goes all -** elements in the array part, then elements in the hash part. The -** beginning of a traversal is signaled by 0. -*/ -static unsigned int findindex (lua_State *L, Table *t, StkId key) { - unsigned int i; - if (ttisnil(key)) return 0; /* first iteration */ - i = arrayindex(key); - if (i != 0 && i <= t->sizearray) /* is 'key' inside array part? */ - return i; /* yes; that's the index */ - else { - int nx; - Node *n = mainposition(t, key); - for (;;) { /* check whether 'key' is somewhere in the chain */ - /* key may be dead already, but it is ok to use it in 'next' */ - if (luaV_rawequalobj(gkey(n), key) || - (ttisdeadkey(gkey(n)) && iscollectable(key) && - deadvalue(gkey(n)) == gcvalue(key))) { - i = cast_int(n - gnode(t, 0)); /* key index in hash table */ - /* hash elements are numbered after array ones */ - return (i + 1) + t->sizearray; - } - nx = gnext(n); - if (nx == 0) - luaG_runerror(L, "invalid key to 'next'"); /* key not found */ - else n += nx; - } - } -} - - -int luaH_next (lua_State *L, Table *t, StkId key) { - unsigned int i = findindex(L, t, key); /* find original element */ - for (; i < t->sizearray; i++) { /* try first array part */ - if (!ttisnil(&t->array[i])) { /* a non-nil value? */ - setivalue(key, i + 1); - setobj2s(L, key+1, &t->array[i]); - return 1; - } - } - for (i -= t->sizearray; cast_int(i) < sizenode(t); i++) { /* hash part */ - if (!ttisnil(gval(gnode(t, i)))) { /* a non-nil value? */ - setobj2s(L, key, gkey(gnode(t, i))); - setobj2s(L, key+1, gval(gnode(t, i))); - return 1; - } - } - return 0; /* no more elements */ -} - - -/* -** {============================================================= -** Rehash -** ============================================================== -*/ - -/* -** Compute the optimal size for the array part of table 't'. 'nums' is a -** "count array" where 'nums[i]' is the number of integers in the table -** between 2^(i - 1) + 1 and 2^i. 'pna' enters with the total number of -** integer keys in the table and leaves with the number of keys that -** will go to the array part; return the optimal size. -*/ -static unsigned int computesizes (unsigned int nums[], unsigned int *pna) { - int i; - unsigned int twotoi; /* 2^i (candidate for optimal size) */ - unsigned int a = 0; /* number of elements smaller than 2^i */ - unsigned int na = 0; /* number of elements to go to array part */ - unsigned int optimal = 0; /* optimal size for array part */ - /* loop while keys can fill more than half of total size */ - for (i = 0, twotoi = 1; - twotoi > 0 && *pna > twotoi / 2; - i++, twotoi *= 2) { - if (nums[i] > 0) { - a += nums[i]; - if (a > twotoi/2) { /* more than half elements present? */ - optimal = twotoi; /* optimal size (till now) */ - na = a; /* all elements up to 'optimal' will go to array part */ - } - } - } - lua_assert((optimal == 0 || optimal / 2 < na) && na <= optimal); - *pna = na; - return optimal; -} - - -static int countint (const TValue *key, unsigned int *nums) { - unsigned int k = arrayindex(key); - if (k != 0) { /* is 'key' an appropriate array index? */ - nums[luaO_ceillog2(k)]++; /* count as such */ - return 1; - } - else - return 0; -} - - -/* -** Count keys in array part of table 't': Fill 'nums[i]' with -** number of keys that will go into corresponding slice and return -** total number of non-nil keys. -*/ -static unsigned int numusearray (const Table *t, unsigned int *nums) { - int lg; - unsigned int ttlg; /* 2^lg */ - unsigned int ause = 0; /* summation of 'nums' */ - unsigned int i = 1; /* count to traverse all array keys */ - /* traverse each slice */ - for (lg = 0, ttlg = 1; lg <= MAXABITS; lg++, ttlg *= 2) { - unsigned int lc = 0; /* counter */ - unsigned int lim = ttlg; - if (lim > t->sizearray) { - lim = t->sizearray; /* adjust upper limit */ - if (i > lim) - break; /* no more elements to count */ - } - /* count elements in range (2^(lg - 1), 2^lg] */ - for (; i <= lim; i++) { - if (!ttisnil(&t->array[i-1])) - lc++; - } - nums[lg] += lc; - ause += lc; - } - return ause; -} - - -static int numusehash (const Table *t, unsigned int *nums, unsigned int *pna) { - int totaluse = 0; /* total number of elements */ - int ause = 0; /* elements added to 'nums' (can go to array part) */ - int i = sizenode(t); - while (i--) { - Node *n = &t->node[i]; - if (!ttisnil(gval(n))) { - ause += countint(gkey(n), nums); - totaluse++; - } - } - *pna += ause; - return totaluse; -} - - -static void setarrayvector (lua_State *L, Table *t, unsigned int size) { - unsigned int i; - luaM_reallocvector(L, t->array, t->sizearray, size, TValue); - for (i=t->sizearray; iarray[i]); - t->sizearray = size; -} - - -static void setnodevector (lua_State *L, Table *t, unsigned int size) { - if (size == 0) { /* no elements to hash part? */ - t->node = cast(Node *, dummynode); /* use common 'dummynode' */ - t->lsizenode = 0; - t->lastfree = NULL; /* signal that it is using dummy node */ - } - else { - int i; - int lsize = luaO_ceillog2(size); - if (lsize > MAXHBITS) - luaG_runerror(L, "table overflow"); - size = twoto(lsize); - t->node = luaM_newvector(L, size, Node); - for (i = 0; i < (int)size; i++) { - Node *n = gnode(t, i); - gnext(n) = 0; - setnilvalue(wgkey(n)); - setnilvalue(gval(n)); - } - t->lsizenode = cast_byte(lsize); - t->lastfree = gnode(t, size); /* all positions are free */ - } -} - - -typedef struct { - Table *t; - unsigned int nhsize; -} AuxsetnodeT; - - -static void auxsetnode (lua_State *L, void *ud) { - AuxsetnodeT *asn = cast(AuxsetnodeT *, ud); - setnodevector(L, asn->t, asn->nhsize); -} - - -void luaH_resize (lua_State *L, Table *t, unsigned int nasize, - unsigned int nhsize) { - unsigned int i; - int j; - AuxsetnodeT asn; - unsigned int oldasize = t->sizearray; - int oldhsize = allocsizenode(t); - Node *nold = t->node; /* save old hash ... */ - if (nasize > oldasize) /* array part must grow? */ - setarrayvector(L, t, nasize); - /* create new hash part with appropriate size */ - asn.t = t; asn.nhsize = nhsize; - if (luaD_rawrunprotected(L, auxsetnode, &asn) != LUA_OK) { /* mem. error? */ - setarrayvector(L, t, oldasize); /* array back to its original size */ - luaD_throw(L, LUA_ERRMEM); /* rethrow memory error */ - } - if (nasize < oldasize) { /* array part must shrink? */ - t->sizearray = nasize; - /* re-insert elements from vanishing slice */ - for (i=nasize; iarray[i])) - luaH_setint(L, t, i + 1, &t->array[i]); - } - /* shrink array */ - luaM_reallocvector(L, t->array, oldasize, nasize, TValue); - } - /* re-insert elements from hash part */ - for (j = oldhsize - 1; j >= 0; j--) { - Node *old = nold + j; - if (!ttisnil(gval(old))) { - /* doesn't need barrier/invalidate cache, as entry was - already present in the table */ - setobjt2t(L, luaH_set(L, t, gkey(old)), gval(old)); - } - } - if (oldhsize > 0) /* not the dummy node? */ - luaM_freearray(L, nold, cast(size_t, oldhsize)); /* free old hash */ -} - - -void luaH_resizearray (lua_State *L, Table *t, unsigned int nasize) { - int nsize = allocsizenode(t); - luaH_resize(L, t, nasize, nsize); -} - -/* -** nums[i] = number of keys 'k' where 2^(i - 1) < k <= 2^i -*/ -static void rehash (lua_State *L, Table *t, const TValue *ek) { - unsigned int asize; /* optimal size for array part */ - unsigned int na; /* number of keys in the array part */ - unsigned int nums[MAXABITS + 1]; - int i; - int totaluse; - for (i = 0; i <= MAXABITS; i++) nums[i] = 0; /* reset counts */ - na = numusearray(t, nums); /* count keys in array part */ - totaluse = na; /* all those keys are integer keys */ - totaluse += numusehash(t, nums, &na); /* count keys in hash part */ - /* count extra key */ - na += countint(ek, nums); - totaluse++; - /* compute new size for array part */ - asize = computesizes(nums, &na); - /* resize the table to new computed sizes */ - luaH_resize(L, t, asize, totaluse - na); -} - - - -/* -** }============================================================= -*/ - - -Table *luaH_new (lua_State *L) { - GCObject *o = luaC_newobj(L, LUA_TTABLE, sizeof(Table)); - Table *t = gco2t(o); - t->metatable = NULL; - t->flags = cast_byte(~0); - t->array = NULL; - t->sizearray = 0; - setnodevector(L, t, 0); - return t; -} - - -void luaH_free (lua_State *L, Table *t) { - if (!isdummy(t)) - luaM_freearray(L, t->node, cast(size_t, sizenode(t))); - luaM_freearray(L, t->array, t->sizearray); - luaM_free(L, t); -} - - -static Node *getfreepos (Table *t) { - if (!isdummy(t)) { - while (t->lastfree > t->node) { - t->lastfree--; - if (ttisnil(gkey(t->lastfree))) - return t->lastfree; - } - } - return NULL; /* could not find a free place */ -} - - - -/* -** inserts a new key into a hash table; first, check whether key's main -** position is free. If not, check whether colliding node is in its main -** position or not: if it is not, move colliding node to an empty place and -** put new key in its main position; otherwise (colliding node is in its main -** position), new key goes to an empty position. -*/ -TValue *luaH_newkey (lua_State *L, Table *t, const TValue *key) { - Node *mp; - TValue aux; - if (ttisnil(key)) luaG_runerror(L, "table index is nil"); - else if (ttisfloat(key)) { - lua_Integer k; - if (luaV_tointeger(key, &k, 0)) { /* does index fit in an integer? */ - setivalue(&aux, k); - key = &aux; /* insert it as an integer */ - } - else if (luai_numisnan(fltvalue(key))) - luaG_runerror(L, "table index is NaN"); - } - mp = mainposition(t, key); - if (!ttisnil(gval(mp)) || isdummy(t)) { /* main position is taken? */ - Node *othern; - Node *f = getfreepos(t); /* get a free place */ - if (f == NULL) { /* cannot find a free place? */ - rehash(L, t, key); /* grow table */ - /* whatever called 'newkey' takes care of TM cache */ - return luaH_set(L, t, key); /* insert key into grown table */ - } - lua_assert(!isdummy(t)); - othern = mainposition(t, gkey(mp)); - if (othern != mp) { /* is colliding node out of its main position? */ - /* yes; move colliding node into free position */ - while (othern + gnext(othern) != mp) /* find previous */ - othern += gnext(othern); - gnext(othern) = cast_int(f - othern); /* rechain to point to 'f' */ - *f = *mp; /* copy colliding node into free pos. (mp->next also goes) */ - if (gnext(mp) != 0) { - gnext(f) += cast_int(mp - f); /* correct 'next' */ - gnext(mp) = 0; /* now 'mp' is free */ - } - setnilvalue(gval(mp)); - } - else { /* colliding node is in its own main position */ - /* new node will go into free position */ - if (gnext(mp) != 0) - gnext(f) = cast_int((mp + gnext(mp)) - f); /* chain new position */ - else lua_assert(gnext(f) == 0); - gnext(mp) = cast_int(f - mp); - mp = f; - } - } - setnodekey(L, &mp->i_key, key); - luaC_barrierback(L, t, key); - lua_assert(ttisnil(gval(mp))); - return gval(mp); -} - - -/* -** search function for integers -*/ -const TValue *luaH_getint (Table *t, lua_Integer key) { - /* (1 <= key && key <= t->sizearray) */ - if (l_castS2U(key) - 1 < t->sizearray) - return &t->array[key - 1]; - else { - Node *n = hashint(t, key); - for (;;) { /* check whether 'key' is somewhere in the chain */ - if (ttisinteger(gkey(n)) && ivalue(gkey(n)) == key) - return gval(n); /* that's it */ - else { - int nx = gnext(n); - if (nx == 0) break; - n += nx; - } - } - return luaO_nilobject; - } -} - - -/* -** search function for short strings -*/ -const TValue *luaH_getshortstr (Table *t, TString *key) { - Node *n = hashstr(t, key); - lua_assert(key->tt == LUA_TSHRSTR); - for (;;) { /* check whether 'key' is somewhere in the chain */ - const TValue *k = gkey(n); - if (ttisshrstring(k) && eqshrstr(tsvalue(k), key)) - return gval(n); /* that's it */ - else { - int nx = gnext(n); - if (nx == 0) - return luaO_nilobject; /* not found */ - n += nx; - } - } -} - - -/* -** "Generic" get version. (Not that generic: not valid for integers, -** which may be in array part, nor for floats with integral values.) -*/ -static const TValue *getgeneric (Table *t, const TValue *key) { - Node *n = mainposition(t, key); - for (;;) { /* check whether 'key' is somewhere in the chain */ - if (luaV_rawequalobj(gkey(n), key)) - return gval(n); /* that's it */ - else { - int nx = gnext(n); - if (nx == 0) - return luaO_nilobject; /* not found */ - n += nx; - } - } -} - - -const TValue *luaH_getstr (Table *t, TString *key) { - if (key->tt == LUA_TSHRSTR) - return luaH_getshortstr(t, key); - else { /* for long strings, use generic case */ - TValue ko; - setsvalue(cast(lua_State *, NULL), &ko, key); - return getgeneric(t, &ko); - } -} - - -/* -** main search function -*/ -const TValue *luaH_get (Table *t, const TValue *key) { - switch (ttype(key)) { - case LUA_TSHRSTR: return luaH_getshortstr(t, tsvalue(key)); - case LUA_TNUMINT: return luaH_getint(t, ivalue(key)); - case LUA_TNIL: return luaO_nilobject; - case LUA_TNUMFLT: { - lua_Integer k; - if (luaV_tointeger(key, &k, 0)) /* index is int? */ - return luaH_getint(t, k); /* use specialized version */ - /* else... */ - } /* FALLTHROUGH */ - default: - return getgeneric(t, key); - } -} - - -/* -** beware: when using this function you probably need to check a GC -** barrier and invalidate the TM cache. -*/ -TValue *luaH_set (lua_State *L, Table *t, const TValue *key) { - const TValue *p = luaH_get(t, key); - if (p != luaO_nilobject) - return cast(TValue *, p); - else return luaH_newkey(L, t, key); -} - - -void luaH_setint (lua_State *L, Table *t, lua_Integer key, TValue *value) { - const TValue *p = luaH_getint(t, key); - TValue *cell; - if (p != luaO_nilobject) - cell = cast(TValue *, p); - else { - TValue k; - setivalue(&k, key); - cell = luaH_newkey(L, t, &k); - } - setobj2t(L, cell, value); -} - - -static lua_Unsigned unbound_search (Table *t, lua_Unsigned j) { - lua_Unsigned i = j; /* i is zero or a present index */ - j++; - /* find 'i' and 'j' such that i is present and j is not */ - while (!ttisnil(luaH_getint(t, j))) { - i = j; - if (j > l_castS2U(LUA_MAXINTEGER) / 2) { /* overflow? */ - /* table was built with bad purposes: resort to linear search */ - i = 1; - while (!ttisnil(luaH_getint(t, i))) i++; - return i - 1; - } - j *= 2; - } - /* now do a binary search between them */ - while (j - i > 1) { - lua_Unsigned m = (i+j)/2; - if (ttisnil(luaH_getint(t, m))) j = m; - else i = m; - } - return i; -} - - -/* -** Try to find a boundary in table 't'. A 'boundary' is an integer index -** such that t[i] is non-nil and t[i+1] is nil (and 0 if t[1] is nil). -*/ -lua_Unsigned luaH_getn (Table *t) { - unsigned int j = t->sizearray; - if (j > 0 && ttisnil(&t->array[j - 1])) { - /* there is a boundary in the array part: (binary) search for it */ - unsigned int i = 0; - while (j - i > 1) { - unsigned int m = (i+j)/2; - if (ttisnil(&t->array[m - 1])) j = m; - else i = m; - } - return i; - } - /* else must find a boundary in hash part */ - else if (isdummy(t)) /* hash part is empty? */ - return j; /* that is easy... */ - else return unbound_search(t, j); -} - - - -#if defined(LUA_DEBUG) - -Node *luaH_mainposition (const Table *t, const TValue *key) { - return mainposition(t, key); -} - -int luaH_isdummy (const Table *t) { return isdummy(t); } - -#endif diff --git a/lib/lua-5.3/src/ltable.h b/lib/lua-5.3/src/ltable.h deleted file mode 100644 index 92db0ac..0000000 --- a/lib/lua-5.3/src/ltable.h +++ /dev/null @@ -1,66 +0,0 @@ -/* -** $Id: ltable.h,v 2.23.1.2 2018/05/24 19:39:05 roberto Exp $ -** Lua tables (hash) -** See Copyright Notice in lua.h -*/ - -#ifndef ltable_h -#define ltable_h - -#include "lobject.h" - - -#define gnode(t,i) (&(t)->node[i]) -#define gval(n) (&(n)->i_val) -#define gnext(n) ((n)->i_key.nk.next) - - -/* 'const' to avoid wrong writings that can mess up field 'next' */ -#define gkey(n) cast(const TValue*, (&(n)->i_key.tvk)) - -/* -** writable version of 'gkey'; allows updates to individual fields, -** but not to the whole (which has incompatible type) -*/ -#define wgkey(n) (&(n)->i_key.nk) - -#define invalidateTMcache(t) ((t)->flags = 0) - - -/* true when 't' is using 'dummynode' as its hash part */ -#define isdummy(t) ((t)->lastfree == NULL) - - -/* allocated size for hash nodes */ -#define allocsizenode(t) (isdummy(t) ? 0 : sizenode(t)) - - -/* returns the key, given the value of a table entry */ -#define keyfromval(v) \ - (gkey(cast(Node *, cast(char *, (v)) - offsetof(Node, i_val)))) - - -LUAI_FUNC const TValue *luaH_getint (Table *t, lua_Integer key); -LUAI_FUNC void luaH_setint (lua_State *L, Table *t, lua_Integer key, - TValue *value); -LUAI_FUNC const TValue *luaH_getshortstr (Table *t, TString *key); -LUAI_FUNC const TValue *luaH_getstr (Table *t, TString *key); -LUAI_FUNC const TValue *luaH_get (Table *t, const TValue *key); -LUAI_FUNC TValue *luaH_newkey (lua_State *L, Table *t, const TValue *key); -LUAI_FUNC TValue *luaH_set (lua_State *L, Table *t, const TValue *key); -LUAI_FUNC Table *luaH_new (lua_State *L); -LUAI_FUNC void luaH_resize (lua_State *L, Table *t, unsigned int nasize, - unsigned int nhsize); -LUAI_FUNC void luaH_resizearray (lua_State *L, Table *t, unsigned int nasize); -LUAI_FUNC void luaH_free (lua_State *L, Table *t); -LUAI_FUNC int luaH_next (lua_State *L, Table *t, StkId key); -LUAI_FUNC lua_Unsigned luaH_getn (Table *t); - - -#if defined(LUA_DEBUG) -LUAI_FUNC Node *luaH_mainposition (const Table *t, const TValue *key); -LUAI_FUNC int luaH_isdummy (const Table *t); -#endif - - -#endif diff --git a/lib/lua-5.3/src/ltablib.c b/lib/lua-5.3/src/ltablib.c deleted file mode 100644 index c534957..0000000 --- a/lib/lua-5.3/src/ltablib.c +++ /dev/null @@ -1,450 +0,0 @@ -/* -** $Id: ltablib.c,v 1.93.1.1 2017/04/19 17:20:42 roberto Exp $ -** Library for Table Manipulation -** See Copyright Notice in lua.h -*/ - -#define ltablib_c -#define LUA_LIB - -#include "lprefix.h" - - -#include -#include -#include - -#include "lua.h" - -#include "lauxlib.h" -#include "lualib.h" - - -/* -** Operations that an object must define to mimic a table -** (some functions only need some of them) -*/ -#define TAB_R 1 /* read */ -#define TAB_W 2 /* write */ -#define TAB_L 4 /* length */ -#define TAB_RW (TAB_R | TAB_W) /* read/write */ - - -#define aux_getn(L,n,w) (checktab(L, n, (w) | TAB_L), luaL_len(L, n)) - - -static int checkfield (lua_State *L, const char *key, int n) { - lua_pushstring(L, key); - return (lua_rawget(L, -n) != LUA_TNIL); -} - - -/* -** Check that 'arg' either is a table or can behave like one (that is, -** has a metatable with the required metamethods) -*/ -static void checktab (lua_State *L, int arg, int what) { - if (lua_type(L, arg) != LUA_TTABLE) { /* is it not a table? */ - int n = 1; /* number of elements to pop */ - if (lua_getmetatable(L, arg) && /* must have metatable */ - (!(what & TAB_R) || checkfield(L, "__index", ++n)) && - (!(what & TAB_W) || checkfield(L, "__newindex", ++n)) && - (!(what & TAB_L) || checkfield(L, "__len", ++n))) { - lua_pop(L, n); /* pop metatable and tested metamethods */ - } - else - luaL_checktype(L, arg, LUA_TTABLE); /* force an error */ - } -} - - -#if defined(LUA_COMPAT_MAXN) -static int maxn (lua_State *L) { - lua_Number max = 0; - luaL_checktype(L, 1, LUA_TTABLE); - lua_pushnil(L); /* first key */ - while (lua_next(L, 1)) { - lua_pop(L, 1); /* remove value */ - if (lua_type(L, -1) == LUA_TNUMBER) { - lua_Number v = lua_tonumber(L, -1); - if (v > max) max = v; - } - } - lua_pushnumber(L, max); - return 1; -} -#endif - - -static int tinsert (lua_State *L) { - lua_Integer e = aux_getn(L, 1, TAB_RW) + 1; /* first empty element */ - lua_Integer pos; /* where to insert new element */ - switch (lua_gettop(L)) { - case 2: { /* called with only 2 arguments */ - pos = e; /* insert new element at the end */ - break; - } - case 3: { - lua_Integer i; - pos = luaL_checkinteger(L, 2); /* 2nd argument is the position */ - luaL_argcheck(L, 1 <= pos && pos <= e, 2, "position out of bounds"); - for (i = e; i > pos; i--) { /* move up elements */ - lua_geti(L, 1, i - 1); - lua_seti(L, 1, i); /* t[i] = t[i - 1] */ - } - break; - } - default: { - return luaL_error(L, "wrong number of arguments to 'insert'"); - } - } - lua_seti(L, 1, pos); /* t[pos] = v */ - return 0; -} - - -static int tremove (lua_State *L) { - lua_Integer size = aux_getn(L, 1, TAB_RW); - lua_Integer pos = luaL_optinteger(L, 2, size); - if (pos != size) /* validate 'pos' if given */ - luaL_argcheck(L, 1 <= pos && pos <= size + 1, 1, "position out of bounds"); - lua_geti(L, 1, pos); /* result = t[pos] */ - for ( ; pos < size; pos++) { - lua_geti(L, 1, pos + 1); - lua_seti(L, 1, pos); /* t[pos] = t[pos + 1] */ - } - lua_pushnil(L); - lua_seti(L, 1, pos); /* t[pos] = nil */ - return 1; -} - - -/* -** Copy elements (1[f], ..., 1[e]) into (tt[t], tt[t+1], ...). Whenever -** possible, copy in increasing order, which is better for rehashing. -** "possible" means destination after original range, or smaller -** than origin, or copying to another table. -*/ -static int tmove (lua_State *L) { - lua_Integer f = luaL_checkinteger(L, 2); - lua_Integer e = luaL_checkinteger(L, 3); - lua_Integer t = luaL_checkinteger(L, 4); - int tt = !lua_isnoneornil(L, 5) ? 5 : 1; /* destination table */ - checktab(L, 1, TAB_R); - checktab(L, tt, TAB_W); - if (e >= f) { /* otherwise, nothing to move */ - lua_Integer n, i; - luaL_argcheck(L, f > 0 || e < LUA_MAXINTEGER + f, 3, - "too many elements to move"); - n = e - f + 1; /* number of elements to move */ - luaL_argcheck(L, t <= LUA_MAXINTEGER - n + 1, 4, - "destination wrap around"); - if (t > e || t <= f || (tt != 1 && !lua_compare(L, 1, tt, LUA_OPEQ))) { - for (i = 0; i < n; i++) { - lua_geti(L, 1, f + i); - lua_seti(L, tt, t + i); - } - } - else { - for (i = n - 1; i >= 0; i--) { - lua_geti(L, 1, f + i); - lua_seti(L, tt, t + i); - } - } - } - lua_pushvalue(L, tt); /* return destination table */ - return 1; -} - - -static void addfield (lua_State *L, luaL_Buffer *b, lua_Integer i) { - lua_geti(L, 1, i); - if (!lua_isstring(L, -1)) - luaL_error(L, "invalid value (%s) at index %d in table for 'concat'", - luaL_typename(L, -1), i); - luaL_addvalue(b); -} - - -static int tconcat (lua_State *L) { - luaL_Buffer b; - lua_Integer last = aux_getn(L, 1, TAB_R); - size_t lsep; - const char *sep = luaL_optlstring(L, 2, "", &lsep); - lua_Integer i = luaL_optinteger(L, 3, 1); - last = luaL_optinteger(L, 4, last); - luaL_buffinit(L, &b); - for (; i < last; i++) { - addfield(L, &b, i); - luaL_addlstring(&b, sep, lsep); - } - if (i == last) /* add last value (if interval was not empty) */ - addfield(L, &b, i); - luaL_pushresult(&b); - return 1; -} - - -/* -** {====================================================== -** Pack/unpack -** ======================================================= -*/ - -static int pack (lua_State *L) { - int i; - int n = lua_gettop(L); /* number of elements to pack */ - lua_createtable(L, n, 1); /* create result table */ - lua_insert(L, 1); /* put it at index 1 */ - for (i = n; i >= 1; i--) /* assign elements */ - lua_seti(L, 1, i); - lua_pushinteger(L, n); - lua_setfield(L, 1, "n"); /* t.n = number of elements */ - return 1; /* return table */ -} - - -static int unpack (lua_State *L) { - lua_Unsigned n; - lua_Integer i = luaL_optinteger(L, 2, 1); - lua_Integer e = luaL_opt(L, luaL_checkinteger, 3, luaL_len(L, 1)); - if (i > e) return 0; /* empty range */ - n = (lua_Unsigned)e - i; /* number of elements minus 1 (avoid overflows) */ - if (n >= (unsigned int)INT_MAX || !lua_checkstack(L, (int)(++n))) - return luaL_error(L, "too many results to unpack"); - for (; i < e; i++) { /* push arg[i..e - 1] (to avoid overflows) */ - lua_geti(L, 1, i); - } - lua_geti(L, 1, e); /* push last element */ - return (int)n; -} - -/* }====================================================== */ - - - -/* -** {====================================================== -** Quicksort -** (based on 'Algorithms in MODULA-3', Robert Sedgewick; -** Addison-Wesley, 1993.) -** ======================================================= -*/ - - -/* type for array indices */ -typedef unsigned int IdxT; - - -/* -** Produce a "random" 'unsigned int' to randomize pivot choice. This -** macro is used only when 'sort' detects a big imbalance in the result -** of a partition. (If you don't want/need this "randomness", ~0 is a -** good choice.) -*/ -#if !defined(l_randomizePivot) /* { */ - -#include - -/* size of 'e' measured in number of 'unsigned int's */ -#define sof(e) (sizeof(e) / sizeof(unsigned int)) - -/* -** Use 'time' and 'clock' as sources of "randomness". Because we don't -** know the types 'clock_t' and 'time_t', we cannot cast them to -** anything without risking overflows. A safe way to use their values -** is to copy them to an array of a known type and use the array values. -*/ -static unsigned int l_randomizePivot (void) { - clock_t c = clock(); - time_t t = time(NULL); - unsigned int buff[sof(c) + sof(t)]; - unsigned int i, rnd = 0; - memcpy(buff, &c, sof(c) * sizeof(unsigned int)); - memcpy(buff + sof(c), &t, sof(t) * sizeof(unsigned int)); - for (i = 0; i < sof(buff); i++) - rnd += buff[i]; - return rnd; -} - -#endif /* } */ - - -/* arrays larger than 'RANLIMIT' may use randomized pivots */ -#define RANLIMIT 100u - - -static void set2 (lua_State *L, IdxT i, IdxT j) { - lua_seti(L, 1, i); - lua_seti(L, 1, j); -} - - -/* -** Return true iff value at stack index 'a' is less than the value at -** index 'b' (according to the order of the sort). -*/ -static int sort_comp (lua_State *L, int a, int b) { - if (lua_isnil(L, 2)) /* no function? */ - return lua_compare(L, a, b, LUA_OPLT); /* a < b */ - else { /* function */ - int res; - lua_pushvalue(L, 2); /* push function */ - lua_pushvalue(L, a-1); /* -1 to compensate function */ - lua_pushvalue(L, b-2); /* -2 to compensate function and 'a' */ - lua_call(L, 2, 1); /* call function */ - res = lua_toboolean(L, -1); /* get result */ - lua_pop(L, 1); /* pop result */ - return res; - } -} - - -/* -** Does the partition: Pivot P is at the top of the stack. -** precondition: a[lo] <= P == a[up-1] <= a[up], -** so it only needs to do the partition from lo + 1 to up - 2. -** Pos-condition: a[lo .. i - 1] <= a[i] == P <= a[i + 1 .. up] -** returns 'i'. -*/ -static IdxT partition (lua_State *L, IdxT lo, IdxT up) { - IdxT i = lo; /* will be incremented before first use */ - IdxT j = up - 1; /* will be decremented before first use */ - /* loop invariant: a[lo .. i] <= P <= a[j .. up] */ - for (;;) { - /* next loop: repeat ++i while a[i] < P */ - while (lua_geti(L, 1, ++i), sort_comp(L, -1, -2)) { - if (i == up - 1) /* a[i] < P but a[up - 1] == P ?? */ - luaL_error(L, "invalid order function for sorting"); - lua_pop(L, 1); /* remove a[i] */ - } - /* after the loop, a[i] >= P and a[lo .. i - 1] < P */ - /* next loop: repeat --j while P < a[j] */ - while (lua_geti(L, 1, --j), sort_comp(L, -3, -1)) { - if (j < i) /* j < i but a[j] > P ?? */ - luaL_error(L, "invalid order function for sorting"); - lua_pop(L, 1); /* remove a[j] */ - } - /* after the loop, a[j] <= P and a[j + 1 .. up] >= P */ - if (j < i) { /* no elements out of place? */ - /* a[lo .. i - 1] <= P <= a[j + 1 .. i .. up] */ - lua_pop(L, 1); /* pop a[j] */ - /* swap pivot (a[up - 1]) with a[i] to satisfy pos-condition */ - set2(L, up - 1, i); - return i; - } - /* otherwise, swap a[i] - a[j] to restore invariant and repeat */ - set2(L, i, j); - } -} - - -/* -** Choose an element in the middle (2nd-3th quarters) of [lo,up] -** "randomized" by 'rnd' -*/ -static IdxT choosePivot (IdxT lo, IdxT up, unsigned int rnd) { - IdxT r4 = (up - lo) / 4; /* range/4 */ - IdxT p = rnd % (r4 * 2) + (lo + r4); - lua_assert(lo + r4 <= p && p <= up - r4); - return p; -} - - -/* -** QuickSort algorithm (recursive function) -*/ -static void auxsort (lua_State *L, IdxT lo, IdxT up, - unsigned int rnd) { - while (lo < up) { /* loop for tail recursion */ - IdxT p; /* Pivot index */ - IdxT n; /* to be used later */ - /* sort elements 'lo', 'p', and 'up' */ - lua_geti(L, 1, lo); - lua_geti(L, 1, up); - if (sort_comp(L, -1, -2)) /* a[up] < a[lo]? */ - set2(L, lo, up); /* swap a[lo] - a[up] */ - else - lua_pop(L, 2); /* remove both values */ - if (up - lo == 1) /* only 2 elements? */ - return; /* already sorted */ - if (up - lo < RANLIMIT || rnd == 0) /* small interval or no randomize? */ - p = (lo + up)/2; /* middle element is a good pivot */ - else /* for larger intervals, it is worth a random pivot */ - p = choosePivot(lo, up, rnd); - lua_geti(L, 1, p); - lua_geti(L, 1, lo); - if (sort_comp(L, -2, -1)) /* a[p] < a[lo]? */ - set2(L, p, lo); /* swap a[p] - a[lo] */ - else { - lua_pop(L, 1); /* remove a[lo] */ - lua_geti(L, 1, up); - if (sort_comp(L, -1, -2)) /* a[up] < a[p]? */ - set2(L, p, up); /* swap a[up] - a[p] */ - else - lua_pop(L, 2); - } - if (up - lo == 2) /* only 3 elements? */ - return; /* already sorted */ - lua_geti(L, 1, p); /* get middle element (Pivot) */ - lua_pushvalue(L, -1); /* push Pivot */ - lua_geti(L, 1, up - 1); /* push a[up - 1] */ - set2(L, p, up - 1); /* swap Pivot (a[p]) with a[up - 1] */ - p = partition(L, lo, up); - /* a[lo .. p - 1] <= a[p] == P <= a[p + 1 .. up] */ - if (p - lo < up - p) { /* lower interval is smaller? */ - auxsort(L, lo, p - 1, rnd); /* call recursively for lower interval */ - n = p - lo; /* size of smaller interval */ - lo = p + 1; /* tail call for [p + 1 .. up] (upper interval) */ - } - else { - auxsort(L, p + 1, up, rnd); /* call recursively for upper interval */ - n = up - p; /* size of smaller interval */ - up = p - 1; /* tail call for [lo .. p - 1] (lower interval) */ - } - if ((up - lo) / 128 > n) /* partition too imbalanced? */ - rnd = l_randomizePivot(); /* try a new randomization */ - } /* tail call auxsort(L, lo, up, rnd) */ -} - - -static int sort (lua_State *L) { - lua_Integer n = aux_getn(L, 1, TAB_RW); - if (n > 1) { /* non-trivial interval? */ - luaL_argcheck(L, n < INT_MAX, 1, "array too big"); - if (!lua_isnoneornil(L, 2)) /* is there a 2nd argument? */ - luaL_checktype(L, 2, LUA_TFUNCTION); /* must be a function */ - lua_settop(L, 2); /* make sure there are two arguments */ - auxsort(L, 1, (IdxT)n, 0); - } - return 0; -} - -/* }====================================================== */ - - -static const luaL_Reg tab_funcs[] = { - {"concat", tconcat}, -#if defined(LUA_COMPAT_MAXN) - {"maxn", maxn}, -#endif - {"insert", tinsert}, - {"pack", pack}, - {"unpack", unpack}, - {"remove", tremove}, - {"move", tmove}, - {"sort", sort}, - {NULL, NULL} -}; - - -LUAMOD_API int luaopen_table (lua_State *L) { - luaL_newlib(L, tab_funcs); -#if defined(LUA_COMPAT_UNPACK) - /* _G.unpack = table.unpack */ - lua_getfield(L, -1, "unpack"); - lua_setglobal(L, "unpack"); -#endif - return 1; -} - diff --git a/lib/lua-5.3/src/ltm.c b/lib/lua-5.3/src/ltm.c deleted file mode 100644 index 0e7c713..0000000 --- a/lib/lua-5.3/src/ltm.c +++ /dev/null @@ -1,165 +0,0 @@ -/* -** $Id: ltm.c,v 2.38.1.1 2017/04/19 17:39:34 roberto Exp $ -** Tag methods -** See Copyright Notice in lua.h -*/ - -#define ltm_c -#define LUA_CORE - -#include "lprefix.h" - - -#include - -#include "lua.h" - -#include "ldebug.h" -#include "ldo.h" -#include "lobject.h" -#include "lstate.h" -#include "lstring.h" -#include "ltable.h" -#include "ltm.h" -#include "lvm.h" - - -static const char udatatypename[] = "userdata"; - -LUAI_DDEF const char *const luaT_typenames_[LUA_TOTALTAGS] = { - "no value", - "nil", "boolean", udatatypename, "number", - "string", "table", "function", udatatypename, "thread", - "proto" /* this last case is used for tests only */ -}; - - -void luaT_init (lua_State *L) { - static const char *const luaT_eventname[] = { /* ORDER TM */ - "__index", "__newindex", - "__gc", "__mode", "__len", "__eq", - "__add", "__sub", "__mul", "__mod", "__pow", - "__div", "__idiv", - "__band", "__bor", "__bxor", "__shl", "__shr", - "__unm", "__bnot", "__lt", "__le", - "__concat", "__call" - }; - int i; - for (i=0; itmname[i] = luaS_new(L, luaT_eventname[i]); - luaC_fix(L, obj2gco(G(L)->tmname[i])); /* never collect these names */ - } -} - - -/* -** function to be used with macro "fasttm": optimized for absence of -** tag methods -*/ -const TValue *luaT_gettm (Table *events, TMS event, TString *ename) { - const TValue *tm = luaH_getshortstr(events, ename); - lua_assert(event <= TM_EQ); - if (ttisnil(tm)) { /* no tag method? */ - events->flags |= cast_byte(1u<metatable; - break; - case LUA_TUSERDATA: - mt = uvalue(o)->metatable; - break; - default: - mt = G(L)->mt[ttnov(o)]; - } - return (mt ? luaH_getshortstr(mt, G(L)->tmname[event]) : luaO_nilobject); -} - - -/* -** Return the name of the type of an object. For tables and userdata -** with metatable, use their '__name' metafield, if present. -*/ -const char *luaT_objtypename (lua_State *L, const TValue *o) { - Table *mt; - if ((ttistable(o) && (mt = hvalue(o)->metatable) != NULL) || - (ttisfulluserdata(o) && (mt = uvalue(o)->metatable) != NULL)) { - const TValue *name = luaH_getshortstr(mt, luaS_new(L, "__name")); - if (ttisstring(name)) /* is '__name' a string? */ - return getstr(tsvalue(name)); /* use it as type name */ - } - return ttypename(ttnov(o)); /* else use standard type name */ -} - - -void luaT_callTM (lua_State *L, const TValue *f, const TValue *p1, - const TValue *p2, TValue *p3, int hasres) { - ptrdiff_t result = savestack(L, p3); - StkId func = L->top; - setobj2s(L, func, f); /* push function (assume EXTRA_STACK) */ - setobj2s(L, func + 1, p1); /* 1st argument */ - setobj2s(L, func + 2, p2); /* 2nd argument */ - L->top += 3; - if (!hasres) /* no result? 'p3' is third argument */ - setobj2s(L, L->top++, p3); /* 3rd argument */ - /* metamethod may yield only when called from Lua code */ - if (isLua(L->ci)) - luaD_call(L, func, hasres); - else - luaD_callnoyield(L, func, hasres); - if (hasres) { /* if has result, move it to its place */ - p3 = restorestack(L, result); - setobjs2s(L, p3, --L->top); - } -} - - -int luaT_callbinTM (lua_State *L, const TValue *p1, const TValue *p2, - StkId res, TMS event) { - const TValue *tm = luaT_gettmbyobj(L, p1, event); /* try first operand */ - if (ttisnil(tm)) - tm = luaT_gettmbyobj(L, p2, event); /* try second operand */ - if (ttisnil(tm)) return 0; - luaT_callTM(L, tm, p1, p2, res, 1); - return 1; -} - - -void luaT_trybinTM (lua_State *L, const TValue *p1, const TValue *p2, - StkId res, TMS event) { - if (!luaT_callbinTM(L, p1, p2, res, event)) { - switch (event) { - case TM_CONCAT: - luaG_concaterror(L, p1, p2); - /* call never returns, but to avoid warnings: *//* FALLTHROUGH */ - case TM_BAND: case TM_BOR: case TM_BXOR: - case TM_SHL: case TM_SHR: case TM_BNOT: { - lua_Number dummy; - if (tonumber(p1, &dummy) && tonumber(p2, &dummy)) - luaG_tointerror(L, p1, p2); - else - luaG_opinterror(L, p1, p2, "perform bitwise operation on"); - } - /* calls never return, but to avoid warnings: *//* FALLTHROUGH */ - default: - luaG_opinterror(L, p1, p2, "perform arithmetic on"); - } - } -} - - -int luaT_callorderTM (lua_State *L, const TValue *p1, const TValue *p2, - TMS event) { - if (!luaT_callbinTM(L, p1, p2, L->top, event)) - return -1; /* no metamethod */ - else - return !l_isfalse(L->top); -} - diff --git a/lib/lua-5.3/src/ltm.h b/lib/lua-5.3/src/ltm.h deleted file mode 100644 index 8170688..0000000 --- a/lib/lua-5.3/src/ltm.h +++ /dev/null @@ -1,76 +0,0 @@ -/* -** $Id: ltm.h,v 2.22.1.1 2017/04/19 17:20:42 roberto Exp $ -** Tag methods -** See Copyright Notice in lua.h -*/ - -#ifndef ltm_h -#define ltm_h - - -#include "lobject.h" - - -/* -* WARNING: if you change the order of this enumeration, -* grep "ORDER TM" and "ORDER OP" -*/ -typedef enum { - TM_INDEX, - TM_NEWINDEX, - TM_GC, - TM_MODE, - TM_LEN, - TM_EQ, /* last tag method with fast access */ - TM_ADD, - TM_SUB, - TM_MUL, - TM_MOD, - TM_POW, - TM_DIV, - TM_IDIV, - TM_BAND, - TM_BOR, - TM_BXOR, - TM_SHL, - TM_SHR, - TM_UNM, - TM_BNOT, - TM_LT, - TM_LE, - TM_CONCAT, - TM_CALL, - TM_N /* number of elements in the enum */ -} TMS; - - - -#define gfasttm(g,et,e) ((et) == NULL ? NULL : \ - ((et)->flags & (1u<<(e))) ? NULL : luaT_gettm(et, e, (g)->tmname[e])) - -#define fasttm(l,et,e) gfasttm(G(l), et, e) - -#define ttypename(x) luaT_typenames_[(x) + 1] - -LUAI_DDEC const char *const luaT_typenames_[LUA_TOTALTAGS]; - - -LUAI_FUNC const char *luaT_objtypename (lua_State *L, const TValue *o); - -LUAI_FUNC const TValue *luaT_gettm (Table *events, TMS event, TString *ename); -LUAI_FUNC const TValue *luaT_gettmbyobj (lua_State *L, const TValue *o, - TMS event); -LUAI_FUNC void luaT_init (lua_State *L); - -LUAI_FUNC void luaT_callTM (lua_State *L, const TValue *f, const TValue *p1, - const TValue *p2, TValue *p3, int hasres); -LUAI_FUNC int luaT_callbinTM (lua_State *L, const TValue *p1, const TValue *p2, - StkId res, TMS event); -LUAI_FUNC void luaT_trybinTM (lua_State *L, const TValue *p1, const TValue *p2, - StkId res, TMS event); -LUAI_FUNC int luaT_callorderTM (lua_State *L, const TValue *p1, - const TValue *p2, TMS event); - - - -#endif diff --git a/lib/lua-5.3/src/lua.c b/lib/lua-5.3/src/lua.c deleted file mode 100644 index ca5b298..0000000 --- a/lib/lua-5.3/src/lua.c +++ /dev/null @@ -1,612 +0,0 @@ -/* -** $Id: lua.c,v 1.230.1.1 2017/04/19 17:29:57 roberto Exp $ -** Lua stand-alone interpreter -** See Copyright Notice in lua.h -*/ - -#define lua_c - -#include "lprefix.h" - - -#include -#include -#include -#include - -#include "lua.h" - -#include "lauxlib.h" -#include "lualib.h" - - - -#if !defined(LUA_PROMPT) -#define LUA_PROMPT "> " -#define LUA_PROMPT2 ">> " -#endif - -#if !defined(LUA_PROGNAME) -#define LUA_PROGNAME "lua" -#endif - -#if !defined(LUA_MAXINPUT) -#define LUA_MAXINPUT 512 -#endif - -#if !defined(LUA_INIT_VAR) -#define LUA_INIT_VAR "LUA_INIT" -#endif - -#define LUA_INITVARVERSION LUA_INIT_VAR LUA_VERSUFFIX - - -/* -** lua_stdin_is_tty detects whether the standard input is a 'tty' (that -** is, whether we're running lua interactively). -*/ -#if !defined(lua_stdin_is_tty) /* { */ - -#if defined(LUA_USE_POSIX) /* { */ - -#include -#define lua_stdin_is_tty() isatty(0) - -#elif defined(LUA_USE_WINDOWS) /* }{ */ - -#include -#include - -#define lua_stdin_is_tty() _isatty(_fileno(stdin)) - -#else /* }{ */ - -/* ISO C definition */ -#define lua_stdin_is_tty() 1 /* assume stdin is a tty */ - -#endif /* } */ - -#endif /* } */ - - -/* -** lua_readline defines how to show a prompt and then read a line from -** the standard input. -** lua_saveline defines how to "save" a read line in a "history". -** lua_freeline defines how to free a line read by lua_readline. -*/ -#if !defined(lua_readline) /* { */ - -#if defined(LUA_USE_READLINE) /* { */ - -#include -#include -#define lua_readline(L,b,p) ((void)L, ((b)=readline(p)) != NULL) -#define lua_saveline(L,line) ((void)L, add_history(line)) -#define lua_freeline(L,b) ((void)L, free(b)) - -#else /* }{ */ - -#define lua_readline(L,b,p) \ - ((void)L, fputs(p, stdout), fflush(stdout), /* show prompt */ \ - fgets(b, LUA_MAXINPUT, stdin) != NULL) /* get line */ -#define lua_saveline(L,line) { (void)L; (void)line; } -#define lua_freeline(L,b) { (void)L; (void)b; } - -#endif /* } */ - -#endif /* } */ - - - - -static lua_State *globalL = NULL; - -static const char *progname = LUA_PROGNAME; - - -/* -** Hook set by signal function to stop the interpreter. -*/ -static void lstop (lua_State *L, lua_Debug *ar) { - (void)ar; /* unused arg. */ - lua_sethook(L, NULL, 0, 0); /* reset hook */ - luaL_error(L, "interrupted!"); -} - - -/* -** Function to be called at a C signal. Because a C signal cannot -** just change a Lua state (as there is no proper synchronization), -** this function only sets a hook that, when called, will stop the -** interpreter. -*/ -static void laction (int i) { - signal(i, SIG_DFL); /* if another SIGINT happens, terminate process */ - lua_sethook(globalL, lstop, LUA_MASKCALL | LUA_MASKRET | LUA_MASKCOUNT, 1); -} - - -static void print_usage (const char *badoption) { - lua_writestringerror("%s: ", progname); - if (badoption[1] == 'e' || badoption[1] == 'l') - lua_writestringerror("'%s' needs argument\n", badoption); - else - lua_writestringerror("unrecognized option '%s'\n", badoption); - lua_writestringerror( - "usage: %s [options] [script [args]]\n" - "Available options are:\n" - " -e stat execute string 'stat'\n" - " -i enter interactive mode after executing 'script'\n" - " -l name require library 'name' into global 'name'\n" - " -v show version information\n" - " -E ignore environment variables\n" - " -- stop handling options\n" - " - stop handling options and execute stdin\n" - , - progname); -} - - -/* -** Prints an error message, adding the program name in front of it -** (if present) -*/ -static void l_message (const char *pname, const char *msg) { - if (pname) lua_writestringerror("%s: ", pname); - lua_writestringerror("%s\n", msg); -} - - -/* -** Check whether 'status' is not OK and, if so, prints the error -** message on the top of the stack. It assumes that the error object -** is a string, as it was either generated by Lua or by 'msghandler'. -*/ -static int report (lua_State *L, int status) { - if (status != LUA_OK) { - const char *msg = lua_tostring(L, -1); - l_message(progname, msg); - lua_pop(L, 1); /* remove message */ - } - return status; -} - - -/* -** Message handler used to run all chunks -*/ -static int msghandler (lua_State *L) { - const char *msg = lua_tostring(L, 1); - if (msg == NULL) { /* is error object not a string? */ - if (luaL_callmeta(L, 1, "__tostring") && /* does it have a metamethod */ - lua_type(L, -1) == LUA_TSTRING) /* that produces a string? */ - return 1; /* that is the message */ - else - msg = lua_pushfstring(L, "(error object is a %s value)", - luaL_typename(L, 1)); - } - luaL_traceback(L, L, msg, 1); /* append a standard traceback */ - return 1; /* return the traceback */ -} - - -/* -** Interface to 'lua_pcall', which sets appropriate message function -** and C-signal handler. Used to run all chunks. -*/ -static int docall (lua_State *L, int narg, int nres) { - int status; - int base = lua_gettop(L) - narg; /* function index */ - lua_pushcfunction(L, msghandler); /* push message handler */ - lua_insert(L, base); /* put it under function and args */ - globalL = L; /* to be available to 'laction' */ - signal(SIGINT, laction); /* set C-signal handler */ - status = lua_pcall(L, narg, nres, base); - signal(SIGINT, SIG_DFL); /* reset C-signal handler */ - lua_remove(L, base); /* remove message handler from the stack */ - return status; -} - - -static void print_version (void) { - lua_writestring(LUA_COPYRIGHT, strlen(LUA_COPYRIGHT)); - lua_writeline(); -} - - -/* -** Create the 'arg' table, which stores all arguments from the -** command line ('argv'). It should be aligned so that, at index 0, -** it has 'argv[script]', which is the script name. The arguments -** to the script (everything after 'script') go to positive indices; -** other arguments (before the script name) go to negative indices. -** If there is no script name, assume interpreter's name as base. -*/ -static void createargtable (lua_State *L, char **argv, int argc, int script) { - int i, narg; - if (script == argc) script = 0; /* no script name? */ - narg = argc - (script + 1); /* number of positive indices */ - lua_createtable(L, narg, script + 1); - for (i = 0; i < argc; i++) { - lua_pushstring(L, argv[i]); - lua_rawseti(L, -2, i - script); - } - lua_setglobal(L, "arg"); -} - - -static int dochunk (lua_State *L, int status) { - if (status == LUA_OK) status = docall(L, 0, 0); - return report(L, status); -} - - -static int dofile (lua_State *L, const char *name) { - return dochunk(L, luaL_loadfile(L, name)); -} - - -static int dostring (lua_State *L, const char *s, const char *name) { - return dochunk(L, luaL_loadbuffer(L, s, strlen(s), name)); -} - - -/* -** Calls 'require(name)' and stores the result in a global variable -** with the given name. -*/ -static int dolibrary (lua_State *L, const char *name) { - int status; - lua_getglobal(L, "require"); - lua_pushstring(L, name); - status = docall(L, 1, 1); /* call 'require(name)' */ - if (status == LUA_OK) - lua_setglobal(L, name); /* global[name] = require return */ - return report(L, status); -} - - -/* -** Returns the string to be used as a prompt by the interpreter. -*/ -static const char *get_prompt (lua_State *L, int firstline) { - const char *p; - lua_getglobal(L, firstline ? "_PROMPT" : "_PROMPT2"); - p = lua_tostring(L, -1); - if (p == NULL) p = (firstline ? LUA_PROMPT : LUA_PROMPT2); - return p; -} - -/* mark in error messages for incomplete statements */ -#define EOFMARK "" -#define marklen (sizeof(EOFMARK)/sizeof(char) - 1) - - -/* -** Check whether 'status' signals a syntax error and the error -** message at the top of the stack ends with the above mark for -** incomplete statements. -*/ -static int incomplete (lua_State *L, int status) { - if (status == LUA_ERRSYNTAX) { - size_t lmsg; - const char *msg = lua_tolstring(L, -1, &lmsg); - if (lmsg >= marklen && strcmp(msg + lmsg - marklen, EOFMARK) == 0) { - lua_pop(L, 1); - return 1; - } - } - return 0; /* else... */ -} - - -/* -** Prompt the user, read a line, and push it into the Lua stack. -*/ -static int pushline (lua_State *L, int firstline) { - char buffer[LUA_MAXINPUT]; - char *b = buffer; - size_t l; - const char *prmt = get_prompt(L, firstline); - int readstatus = lua_readline(L, b, prmt); - if (readstatus == 0) - return 0; /* no input (prompt will be popped by caller) */ - lua_pop(L, 1); /* remove prompt */ - l = strlen(b); - if (l > 0 && b[l-1] == '\n') /* line ends with newline? */ - b[--l] = '\0'; /* remove it */ - if (firstline && b[0] == '=') /* for compatibility with 5.2, ... */ - lua_pushfstring(L, "return %s", b + 1); /* change '=' to 'return' */ - else - lua_pushlstring(L, b, l); - lua_freeline(L, b); - return 1; -} - - -/* -** Try to compile line on the stack as 'return ;'; on return, stack -** has either compiled chunk or original line (if compilation failed). -*/ -static int addreturn (lua_State *L) { - const char *line = lua_tostring(L, -1); /* original line */ - const char *retline = lua_pushfstring(L, "return %s;", line); - int status = luaL_loadbuffer(L, retline, strlen(retline), "=stdin"); - if (status == LUA_OK) { - lua_remove(L, -2); /* remove modified line */ - if (line[0] != '\0') /* non empty? */ - lua_saveline(L, line); /* keep history */ - } - else - lua_pop(L, 2); /* pop result from 'luaL_loadbuffer' and modified line */ - return status; -} - - -/* -** Read multiple lines until a complete Lua statement -*/ -static int multiline (lua_State *L) { - for (;;) { /* repeat until gets a complete statement */ - size_t len; - const char *line = lua_tolstring(L, 1, &len); /* get what it has */ - int status = luaL_loadbuffer(L, line, len, "=stdin"); /* try it */ - if (!incomplete(L, status) || !pushline(L, 0)) { - lua_saveline(L, line); /* keep history */ - return status; /* cannot or should not try to add continuation line */ - } - lua_pushliteral(L, "\n"); /* add newline... */ - lua_insert(L, -2); /* ...between the two lines */ - lua_concat(L, 3); /* join them */ - } -} - - -/* -** Read a line and try to load (compile) it first as an expression (by -** adding "return " in front of it) and second as a statement. Return -** the final status of load/call with the resulting function (if any) -** in the top of the stack. -*/ -static int loadline (lua_State *L) { - int status; - lua_settop(L, 0); - if (!pushline(L, 1)) - return -1; /* no input */ - if ((status = addreturn(L)) != LUA_OK) /* 'return ...' did not work? */ - status = multiline(L); /* try as command, maybe with continuation lines */ - lua_remove(L, 1); /* remove line from the stack */ - lua_assert(lua_gettop(L) == 1); - return status; -} - - -/* -** Prints (calling the Lua 'print' function) any values on the stack -*/ -static void l_print (lua_State *L) { - int n = lua_gettop(L); - if (n > 0) { /* any result to be printed? */ - luaL_checkstack(L, LUA_MINSTACK, "too many results to print"); - lua_getglobal(L, "print"); - lua_insert(L, 1); - if (lua_pcall(L, n, 0, 0) != LUA_OK) - l_message(progname, lua_pushfstring(L, "error calling 'print' (%s)", - lua_tostring(L, -1))); - } -} - - -/* -** Do the REPL: repeatedly read (load) a line, evaluate (call) it, and -** print any results. -*/ -static void doREPL (lua_State *L) { - int status; - const char *oldprogname = progname; - progname = NULL; /* no 'progname' on errors in interactive mode */ - while ((status = loadline(L)) != -1) { - if (status == LUA_OK) - status = docall(L, 0, LUA_MULTRET); - if (status == LUA_OK) l_print(L); - else report(L, status); - } - lua_settop(L, 0); /* clear stack */ - lua_writeline(); - progname = oldprogname; -} - - -/* -** Push on the stack the contents of table 'arg' from 1 to #arg -*/ -static int pushargs (lua_State *L) { - int i, n; - if (lua_getglobal(L, "arg") != LUA_TTABLE) - luaL_error(L, "'arg' is not a table"); - n = (int)luaL_len(L, -1); - luaL_checkstack(L, n + 3, "too many arguments to script"); - for (i = 1; i <= n; i++) - lua_rawgeti(L, -i, i); - lua_remove(L, -i); /* remove table from the stack */ - return n; -} - - -static int handle_script (lua_State *L, char **argv) { - int status; - const char *fname = argv[0]; - if (strcmp(fname, "-") == 0 && strcmp(argv[-1], "--") != 0) - fname = NULL; /* stdin */ - status = luaL_loadfile(L, fname); - if (status == LUA_OK) { - int n = pushargs(L); /* push arguments to script */ - status = docall(L, n, LUA_MULTRET); - } - return report(L, status); -} - - - -/* bits of various argument indicators in 'args' */ -#define has_error 1 /* bad option */ -#define has_i 2 /* -i */ -#define has_v 4 /* -v */ -#define has_e 8 /* -e */ -#define has_E 16 /* -E */ - -/* -** Traverses all arguments from 'argv', returning a mask with those -** needed before running any Lua code (or an error code if it finds -** any invalid argument). 'first' returns the first not-handled argument -** (either the script name or a bad argument in case of error). -*/ -static int collectargs (char **argv, int *first) { - int args = 0; - int i; - for (i = 1; argv[i] != NULL; i++) { - *first = i; - if (argv[i][0] != '-') /* not an option? */ - return args; /* stop handling options */ - switch (argv[i][1]) { /* else check option */ - case '-': /* '--' */ - if (argv[i][2] != '\0') /* extra characters after '--'? */ - return has_error; /* invalid option */ - *first = i + 1; - return args; - case '\0': /* '-' */ - return args; /* script "name" is '-' */ - case 'E': - if (argv[i][2] != '\0') /* extra characters after 1st? */ - return has_error; /* invalid option */ - args |= has_E; - break; - case 'i': - args |= has_i; /* (-i implies -v) *//* FALLTHROUGH */ - case 'v': - if (argv[i][2] != '\0') /* extra characters after 1st? */ - return has_error; /* invalid option */ - args |= has_v; - break; - case 'e': - args |= has_e; /* FALLTHROUGH */ - case 'l': /* both options need an argument */ - if (argv[i][2] == '\0') { /* no concatenated argument? */ - i++; /* try next 'argv' */ - if (argv[i] == NULL || argv[i][0] == '-') - return has_error; /* no next argument or it is another option */ - } - break; - default: /* invalid option */ - return has_error; - } - } - *first = i; /* no script name */ - return args; -} - - -/* -** Processes options 'e' and 'l', which involve running Lua code. -** Returns 0 if some code raises an error. -*/ -static int runargs (lua_State *L, char **argv, int n) { - int i; - for (i = 1; i < n; i++) { - int option = argv[i][1]; - lua_assert(argv[i][0] == '-'); /* already checked */ - if (option == 'e' || option == 'l') { - int status; - const char *extra = argv[i] + 2; /* both options need an argument */ - if (*extra == '\0') extra = argv[++i]; - lua_assert(extra != NULL); - status = (option == 'e') - ? dostring(L, extra, "=(command line)") - : dolibrary(L, extra); - if (status != LUA_OK) return 0; - } - } - return 1; -} - - - -static int handle_luainit (lua_State *L) { - const char *name = "=" LUA_INITVARVERSION; - const char *init = getenv(name + 1); - if (init == NULL) { - name = "=" LUA_INIT_VAR; - init = getenv(name + 1); /* try alternative name */ - } - if (init == NULL) return LUA_OK; - else if (init[0] == '@') - return dofile(L, init+1); - else - return dostring(L, init, name); -} - - -/* -** Main body of stand-alone interpreter (to be called in protected mode). -** Reads the options and handles them all. -*/ -static int pmain (lua_State *L) { - int argc = (int)lua_tointeger(L, 1); - char **argv = (char **)lua_touserdata(L, 2); - int script; - int args = collectargs(argv, &script); - luaL_checkversion(L); /* check that interpreter has correct version */ - if (argv[0] && argv[0][0]) progname = argv[0]; - if (args == has_error) { /* bad arg? */ - print_usage(argv[script]); /* 'script' has index of bad arg. */ - return 0; - } - if (args & has_v) /* option '-v'? */ - print_version(); - if (args & has_E) { /* option '-E'? */ - lua_pushboolean(L, 1); /* signal for libraries to ignore env. vars. */ - lua_setfield(L, LUA_REGISTRYINDEX, "LUA_NOENV"); - } - luaL_openlibs(L); /* open standard libraries */ - createargtable(L, argv, argc, script); /* create table 'arg' */ - if (!(args & has_E)) { /* no option '-E'? */ - if (handle_luainit(L) != LUA_OK) /* run LUA_INIT */ - return 0; /* error running LUA_INIT */ - } - if (!runargs(L, argv, script)) /* execute arguments -e and -l */ - return 0; /* something failed */ - if (script < argc && /* execute main script (if there is one) */ - handle_script(L, argv + script) != LUA_OK) - return 0; - if (args & has_i) /* -i option? */ - doREPL(L); /* do read-eval-print loop */ - else if (script == argc && !(args & (has_e | has_v))) { /* no arguments? */ - if (lua_stdin_is_tty()) { /* running in interactive mode? */ - print_version(); - doREPL(L); /* do read-eval-print loop */ - } - else dofile(L, NULL); /* executes stdin as a file */ - } - lua_pushboolean(L, 1); /* signal no errors */ - return 1; -} - - -int main (int argc, char **argv) { - int status, result; - lua_State *L = luaL_newstate(); /* create state */ - if (L == NULL) { - l_message(argv[0], "cannot create state: not enough memory"); - return EXIT_FAILURE; - } - lua_pushcfunction(L, &pmain); /* to call 'pmain' in protected mode */ - lua_pushinteger(L, argc); /* 1st argument */ - lua_pushlightuserdata(L, argv); /* 2nd argument */ - status = lua_pcall(L, 2, 1, 0); /* do the call */ - result = lua_toboolean(L, -1); /* get result */ - report(L, status); - lua_close(L); - return (result && status == LUA_OK) ? EXIT_SUCCESS : EXIT_FAILURE; -} - diff --git a/lib/lua-5.3/src/lua.h b/lib/lua-5.3/src/lua.h deleted file mode 100644 index 9394c5e..0000000 --- a/lib/lua-5.3/src/lua.h +++ /dev/null @@ -1,485 +0,0 @@ -/* -** Lua - A Scripting Language -** Lua.org, PUC-Rio, Brazil (http://www.lua.org) -** See Copyright Notice at the end of this file -*/ - - -#ifndef lua_h -#define lua_h - -#include -#include - - -#include "luaconf.h" - - -#define LUA_VERSION_MAJOR "5" -#define LUA_VERSION_MINOR "3" -#define LUA_VERSION_NUM 503 -#define LUA_VERSION_RELEASE "6" - -#define LUA_VERSION "Lua " LUA_VERSION_MAJOR "." LUA_VERSION_MINOR -#define LUA_RELEASE LUA_VERSION "." LUA_VERSION_RELEASE -#define LUA_COPYRIGHT LUA_RELEASE " Copyright (C) 1994-2020 Lua.org, PUC-Rio" -#define LUA_AUTHORS "R. Ierusalimschy, L. H. de Figueiredo, W. Celes" - - -/* mark for precompiled code ('Lua') */ -#define LUA_SIGNATURE "\x1bLua" - -/* option for multiple returns in 'lua_pcall' and 'lua_call' */ -#define LUA_MULTRET (-1) - - -/* -** Pseudo-indices -** (-LUAI_MAXSTACK is the minimum valid index; we keep some free empty -** space after that to help overflow detection) -*/ -#define LUA_REGISTRYINDEX (-LUAI_MAXSTACK - 1000) -#define lua_upvalueindex(i) (LUA_REGISTRYINDEX - (i)) - - -/* thread status */ -#define LUA_OK 0 -#define LUA_YIELD 1 -#define LUA_ERRRUN 2 -#define LUA_ERRSYNTAX 3 -#define LUA_ERRMEM 4 -#define LUA_ERRGCMM 5 -#define LUA_ERRERR 6 - - -typedef struct lua_State lua_State; - - -/* -** basic types -*/ -#define LUA_TNONE (-1) - -#define LUA_TNIL 0 -#define LUA_TBOOLEAN 1 -#define LUA_TLIGHTUSERDATA 2 -#define LUA_TNUMBER 3 -#define LUA_TSTRING 4 -#define LUA_TTABLE 5 -#define LUA_TFUNCTION 6 -#define LUA_TUSERDATA 7 -#define LUA_TTHREAD 8 - -#define LUA_NUMTAGS 9 - - - -/* minimum Lua stack available to a C function */ -#define LUA_MINSTACK 20 - - -/* predefined values in the registry */ -#define LUA_RIDX_MAINTHREAD 1 -#define LUA_RIDX_GLOBALS 2 -#define LUA_RIDX_LAST LUA_RIDX_GLOBALS - - -/* type of numbers in Lua */ -typedef LUA_NUMBER lua_Number; - - -/* type for integer functions */ -typedef LUA_INTEGER lua_Integer; - -/* unsigned integer type */ -typedef LUA_UNSIGNED lua_Unsigned; - -/* type for continuation-function contexts */ -typedef LUA_KCONTEXT lua_KContext; - - -/* -** Type for C functions registered with Lua -*/ -typedef int (*lua_CFunction) (lua_State *L); - -/* -** Type for continuation functions -*/ -typedef int (*lua_KFunction) (lua_State *L, int status, lua_KContext ctx); - - -/* -** Type for functions that read/write blocks when loading/dumping Lua chunks -*/ -typedef const char * (*lua_Reader) (lua_State *L, void *ud, size_t *sz); - -typedef int (*lua_Writer) (lua_State *L, const void *p, size_t sz, void *ud); - - -/* -** Type for memory-allocation functions -*/ -typedef void * (*lua_Alloc) (void *ud, void *ptr, size_t osize, size_t nsize); - - - -/* -** generic extra include file -*/ -#if defined(LUA_USER_H) -#include LUA_USER_H -#endif - - -/* -** RCS ident string -*/ -extern const char lua_ident[]; - - -/* -** state manipulation -*/ -LUA_API lua_State *(lua_newstate) (lua_Alloc f, void *ud); -LUA_API void (lua_close) (lua_State *L); -LUA_API lua_State *(lua_newthread) (lua_State *L); - -LUA_API lua_CFunction (lua_atpanic) (lua_State *L, lua_CFunction panicf); - - -LUA_API const lua_Number *(lua_version) (lua_State *L); - - -/* -** basic stack manipulation -*/ -LUA_API int (lua_absindex) (lua_State *L, int idx); -LUA_API int (lua_gettop) (lua_State *L); -LUA_API void (lua_settop) (lua_State *L, int idx); -LUA_API void (lua_pushvalue) (lua_State *L, int idx); -LUA_API void (lua_rotate) (lua_State *L, int idx, int n); -LUA_API void (lua_copy) (lua_State *L, int fromidx, int toidx); -LUA_API int (lua_checkstack) (lua_State *L, int n); - -LUA_API void (lua_xmove) (lua_State *from, lua_State *to, int n); - - -/* -** access functions (stack -> C) -*/ - -LUA_API int (lua_isnumber) (lua_State *L, int idx); -LUA_API int (lua_isstring) (lua_State *L, int idx); -LUA_API int (lua_iscfunction) (lua_State *L, int idx); -LUA_API int (lua_isinteger) (lua_State *L, int idx); -LUA_API int (lua_isuserdata) (lua_State *L, int idx); -LUA_API int (lua_type) (lua_State *L, int idx); -LUA_API const char *(lua_typename) (lua_State *L, int tp); - -LUA_API lua_Number (lua_tonumberx) (lua_State *L, int idx, int *isnum); -LUA_API lua_Integer (lua_tointegerx) (lua_State *L, int idx, int *isnum); -LUA_API int (lua_toboolean) (lua_State *L, int idx); -LUA_API const char *(lua_tolstring) (lua_State *L, int idx, size_t *len); -LUA_API size_t (lua_rawlen) (lua_State *L, int idx); -LUA_API lua_CFunction (lua_tocfunction) (lua_State *L, int idx); -LUA_API void *(lua_touserdata) (lua_State *L, int idx); -LUA_API lua_State *(lua_tothread) (lua_State *L, int idx); -LUA_API const void *(lua_topointer) (lua_State *L, int idx); - - -/* -** Comparison and arithmetic functions -*/ - -#define LUA_OPADD 0 /* ORDER TM, ORDER OP */ -#define LUA_OPSUB 1 -#define LUA_OPMUL 2 -#define LUA_OPMOD 3 -#define LUA_OPPOW 4 -#define LUA_OPDIV 5 -#define LUA_OPIDIV 6 -#define LUA_OPBAND 7 -#define LUA_OPBOR 8 -#define LUA_OPBXOR 9 -#define LUA_OPSHL 10 -#define LUA_OPSHR 11 -#define LUA_OPUNM 12 -#define LUA_OPBNOT 13 - -LUA_API void (lua_arith) (lua_State *L, int op); - -#define LUA_OPEQ 0 -#define LUA_OPLT 1 -#define LUA_OPLE 2 - -LUA_API int (lua_rawequal) (lua_State *L, int idx1, int idx2); -LUA_API int (lua_compare) (lua_State *L, int idx1, int idx2, int op); - - -/* -** push functions (C -> stack) -*/ -LUA_API void (lua_pushnil) (lua_State *L); -LUA_API void (lua_pushnumber) (lua_State *L, lua_Number n); -LUA_API void (lua_pushinteger) (lua_State *L, lua_Integer n); -LUA_API const char *(lua_pushlstring) (lua_State *L, const char *s, size_t len); -LUA_API const char *(lua_pushstring) (lua_State *L, const char *s); -LUA_API const char *(lua_pushvfstring) (lua_State *L, const char *fmt, - va_list argp); -LUA_API const char *(lua_pushfstring) (lua_State *L, const char *fmt, ...); -LUA_API void (lua_pushcclosure) (lua_State *L, lua_CFunction fn, int n); -LUA_API void (lua_pushboolean) (lua_State *L, int b); -LUA_API void (lua_pushlightuserdata) (lua_State *L, void *p); -LUA_API int (lua_pushthread) (lua_State *L); - - -/* -** get functions (Lua -> stack) -*/ -LUA_API int (lua_getglobal) (lua_State *L, const char *name); -LUA_API int (lua_gettable) (lua_State *L, int idx); -LUA_API int (lua_getfield) (lua_State *L, int idx, const char *k); -LUA_API int (lua_geti) (lua_State *L, int idx, lua_Integer n); -LUA_API int (lua_rawget) (lua_State *L, int idx); -LUA_API int (lua_rawgeti) (lua_State *L, int idx, lua_Integer n); -LUA_API int (lua_rawgetp) (lua_State *L, int idx, const void *p); - -LUA_API void (lua_createtable) (lua_State *L, int narr, int nrec); -LUA_API void *(lua_newuserdata) (lua_State *L, size_t sz); -LUA_API int (lua_getmetatable) (lua_State *L, int objindex); -LUA_API int (lua_getuservalue) (lua_State *L, int idx); - - -/* -** set functions (stack -> Lua) -*/ -LUA_API void (lua_setglobal) (lua_State *L, const char *name); -LUA_API void (lua_settable) (lua_State *L, int idx); -LUA_API void (lua_setfield) (lua_State *L, int idx, const char *k); -LUA_API void (lua_seti) (lua_State *L, int idx, lua_Integer n); -LUA_API void (lua_rawset) (lua_State *L, int idx); -LUA_API void (lua_rawseti) (lua_State *L, int idx, lua_Integer n); -LUA_API void (lua_rawsetp) (lua_State *L, int idx, const void *p); -LUA_API int (lua_setmetatable) (lua_State *L, int objindex); -LUA_API void (lua_setuservalue) (lua_State *L, int idx); - - -/* -** 'load' and 'call' functions (load and run Lua code) -*/ -LUA_API void (lua_callk) (lua_State *L, int nargs, int nresults, - lua_KContext ctx, lua_KFunction k); -#define lua_call(L,n,r) lua_callk(L, (n), (r), 0, NULL) - -LUA_API int (lua_pcallk) (lua_State *L, int nargs, int nresults, int errfunc, - lua_KContext ctx, lua_KFunction k); -#define lua_pcall(L,n,r,f) lua_pcallk(L, (n), (r), (f), 0, NULL) - -LUA_API int (lua_load) (lua_State *L, lua_Reader reader, void *dt, - const char *chunkname, const char *mode); - -LUA_API int (lua_dump) (lua_State *L, lua_Writer writer, void *data, int strip); - - -/* -** coroutine functions -*/ -LUA_API int (lua_yieldk) (lua_State *L, int nresults, lua_KContext ctx, - lua_KFunction k); -LUA_API int (lua_resume) (lua_State *L, lua_State *from, int narg); -LUA_API int (lua_status) (lua_State *L); -LUA_API int (lua_isyieldable) (lua_State *L); - -#define lua_yield(L,n) lua_yieldk(L, (n), 0, NULL) - - -/* -** garbage-collection function and options -*/ - -#define LUA_GCSTOP 0 -#define LUA_GCRESTART 1 -#define LUA_GCCOLLECT 2 -#define LUA_GCCOUNT 3 -#define LUA_GCCOUNTB 4 -#define LUA_GCSTEP 5 -#define LUA_GCSETPAUSE 6 -#define LUA_GCSETSTEPMUL 7 -#define LUA_GCISRUNNING 9 - -LUA_API int (lua_gc) (lua_State *L, int what, int data); - - -/* -** miscellaneous functions -*/ - -LUA_API int (lua_error) (lua_State *L); - -LUA_API int (lua_next) (lua_State *L, int idx); - -LUA_API void (lua_concat) (lua_State *L, int n); -LUA_API void (lua_len) (lua_State *L, int idx); - -LUA_API size_t (lua_stringtonumber) (lua_State *L, const char *s); - -LUA_API lua_Alloc (lua_getallocf) (lua_State *L, void **ud); -LUA_API void (lua_setallocf) (lua_State *L, lua_Alloc f, void *ud); - - - -/* -** {============================================================== -** some useful macros -** =============================================================== -*/ - -#define lua_getextraspace(L) ((void *)((char *)(L) - LUA_EXTRASPACE)) - -#define lua_tonumber(L,i) lua_tonumberx(L,(i),NULL) -#define lua_tointeger(L,i) lua_tointegerx(L,(i),NULL) - -#define lua_pop(L,n) lua_settop(L, -(n)-1) - -#define lua_newtable(L) lua_createtable(L, 0, 0) - -#define lua_register(L,n,f) (lua_pushcfunction(L, (f)), lua_setglobal(L, (n))) - -#define lua_pushcfunction(L,f) lua_pushcclosure(L, (f), 0) - -#define lua_isfunction(L,n) (lua_type(L, (n)) == LUA_TFUNCTION) -#define lua_istable(L,n) (lua_type(L, (n)) == LUA_TTABLE) -#define lua_islightuserdata(L,n) (lua_type(L, (n)) == LUA_TLIGHTUSERDATA) -#define lua_isnil(L,n) (lua_type(L, (n)) == LUA_TNIL) -#define lua_isboolean(L,n) (lua_type(L, (n)) == LUA_TBOOLEAN) -#define lua_isthread(L,n) (lua_type(L, (n)) == LUA_TTHREAD) -#define lua_isnone(L,n) (lua_type(L, (n)) == LUA_TNONE) -#define lua_isnoneornil(L, n) (lua_type(L, (n)) <= 0) - -#define lua_pushliteral(L, s) lua_pushstring(L, "" s) - -#define lua_pushglobaltable(L) \ - ((void)lua_rawgeti(L, LUA_REGISTRYINDEX, LUA_RIDX_GLOBALS)) - -#define lua_tostring(L,i) lua_tolstring(L, (i), NULL) - - -#define lua_insert(L,idx) lua_rotate(L, (idx), 1) - -#define lua_remove(L,idx) (lua_rotate(L, (idx), -1), lua_pop(L, 1)) - -#define lua_replace(L,idx) (lua_copy(L, -1, (idx)), lua_pop(L, 1)) - -/* }============================================================== */ - - -/* -** {============================================================== -** compatibility macros for unsigned conversions -** =============================================================== -*/ -#if defined(LUA_COMPAT_APIINTCASTS) - -#define lua_pushunsigned(L,n) lua_pushinteger(L, (lua_Integer)(n)) -#define lua_tounsignedx(L,i,is) ((lua_Unsigned)lua_tointegerx(L,i,is)) -#define lua_tounsigned(L,i) lua_tounsignedx(L,(i),NULL) - -#endif -/* }============================================================== */ - -/* -** {====================================================================== -** Debug API -** ======================================================================= -*/ - - -/* -** Event codes -*/ -#define LUA_HOOKCALL 0 -#define LUA_HOOKRET 1 -#define LUA_HOOKLINE 2 -#define LUA_HOOKCOUNT 3 -#define LUA_HOOKTAILCALL 4 - - -/* -** Event masks -*/ -#define LUA_MASKCALL (1 << LUA_HOOKCALL) -#define LUA_MASKRET (1 << LUA_HOOKRET) -#define LUA_MASKLINE (1 << LUA_HOOKLINE) -#define LUA_MASKCOUNT (1 << LUA_HOOKCOUNT) - -typedef struct lua_Debug lua_Debug; /* activation record */ - - -/* Functions to be called by the debugger in specific events */ -typedef void (*lua_Hook) (lua_State *L, lua_Debug *ar); - - -LUA_API int (lua_getstack) (lua_State *L, int level, lua_Debug *ar); -LUA_API int (lua_getinfo) (lua_State *L, const char *what, lua_Debug *ar); -LUA_API const char *(lua_getlocal) (lua_State *L, const lua_Debug *ar, int n); -LUA_API const char *(lua_setlocal) (lua_State *L, const lua_Debug *ar, int n); -LUA_API const char *(lua_getupvalue) (lua_State *L, int funcindex, int n); -LUA_API const char *(lua_setupvalue) (lua_State *L, int funcindex, int n); - -LUA_API void *(lua_upvalueid) (lua_State *L, int fidx, int n); -LUA_API void (lua_upvaluejoin) (lua_State *L, int fidx1, int n1, - int fidx2, int n2); - -LUA_API void (lua_sethook) (lua_State *L, lua_Hook func, int mask, int count); -LUA_API lua_Hook (lua_gethook) (lua_State *L); -LUA_API int (lua_gethookmask) (lua_State *L); -LUA_API int (lua_gethookcount) (lua_State *L); - - -struct lua_Debug { - int event; - const char *name; /* (n) */ - const char *namewhat; /* (n) 'global', 'local', 'field', 'method' */ - const char *what; /* (S) 'Lua', 'C', 'main', 'tail' */ - const char *source; /* (S) */ - int currentline; /* (l) */ - int linedefined; /* (S) */ - int lastlinedefined; /* (S) */ - unsigned char nups; /* (u) number of upvalues */ - unsigned char nparams;/* (u) number of parameters */ - char isvararg; /* (u) */ - char istailcall; /* (t) */ - char short_src[LUA_IDSIZE]; /* (S) */ - /* private part */ - struct CallInfo *i_ci; /* active function */ -}; - -/* }====================================================================== */ - - -/****************************************************************************** -* Copyright (C) 1994-2020 Lua.org, PUC-Rio. -* -* Permission is hereby granted, free of charge, to any person obtaining -* a copy of this software and associated documentation files (the -* "Software"), to deal in the Software without restriction, including -* without limitation the rights to use, copy, modify, merge, publish, -* distribute, sublicense, and/or sell copies of the Software, and to -* permit persons to whom the Software is furnished to do so, subject to -* the following conditions: -* -* The above copyright notice and this permission notice shall be -* included in all copies or substantial portions of the Software. -* -* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, -* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF -* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. -* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY -* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, -* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE -* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. -******************************************************************************/ - - -#endif diff --git a/lib/lua-5.3/src/lua.hpp b/lib/lua-5.3/src/lua.hpp deleted file mode 100644 index ec417f5..0000000 --- a/lib/lua-5.3/src/lua.hpp +++ /dev/null @@ -1,9 +0,0 @@ -// lua.hpp -// Lua header files for C++ -// <> not supplied automatically because Lua also compiles as C++ - -extern "C" { -#include "lua.h" -#include "lualib.h" -#include "lauxlib.h" -} diff --git a/lib/lua-5.3/src/luac.c b/lib/lua-5.3/src/luac.c deleted file mode 100644 index 549ad39..0000000 --- a/lib/lua-5.3/src/luac.c +++ /dev/null @@ -1,450 +0,0 @@ -/* -** $Id: luac.c,v 1.76 2018/06/19 01:32:02 lhf Exp $ -** Lua compiler (saves bytecodes to files; also lists bytecodes) -** See Copyright Notice in lua.h -*/ - -#define luac_c -#define LUA_CORE - -#include "lprefix.h" - -#include -#include -#include -#include -#include - -#include "lua.h" -#include "lauxlib.h" - -#include "lobject.h" -#include "lstate.h" -#include "lundump.h" - -static void PrintFunction(const Proto* f, int full); -#define luaU_print PrintFunction - -#define PROGNAME "luac" /* default program name */ -#define OUTPUT PROGNAME ".out" /* default output file */ - -static int listing=0; /* list bytecodes? */ -static int dumping=1; /* dump bytecodes? */ -static int stripping=0; /* strip debug information? */ -static char Output[]={ OUTPUT }; /* default output file name */ -static const char* output=Output; /* actual output file name */ -static const char* progname=PROGNAME; /* actual program name */ - -static void fatal(const char* message) -{ - fprintf(stderr,"%s: %s\n",progname,message); - exit(EXIT_FAILURE); -} - -static void cannot(const char* what) -{ - fprintf(stderr,"%s: cannot %s %s: %s\n",progname,what,output,strerror(errno)); - exit(EXIT_FAILURE); -} - -static void usage(const char* message) -{ - if (*message=='-') - fprintf(stderr,"%s: unrecognized option '%s'\n",progname,message); - else - fprintf(stderr,"%s: %s\n",progname,message); - fprintf(stderr, - "usage: %s [options] [filenames]\n" - "Available options are:\n" - " -l list (use -l -l for full listing)\n" - " -o name output to file 'name' (default is \"%s\")\n" - " -p parse only\n" - " -s strip debug information\n" - " -v show version information\n" - " -- stop handling options\n" - " - stop handling options and process stdin\n" - ,progname,Output); - exit(EXIT_FAILURE); -} - -#define IS(s) (strcmp(argv[i],s)==0) - -static int doargs(int argc, char* argv[]) -{ - int i; - int version=0; - if (argv[0]!=NULL && *argv[0]!=0) progname=argv[0]; - for (i=1; itop+(i)) - -static const Proto* combine(lua_State* L, int n) -{ - if (n==1) - return toproto(L,-1); - else - { - Proto* f; - int i=n; - if (lua_load(L,reader,&i,"=(" PROGNAME ")",NULL)!=LUA_OK) fatal(lua_tostring(L,-1)); - f=toproto(L,-1); - for (i=0; ip[i]=toproto(L,i-n-1); - if (f->p[i]->sizeupvalues>0) f->p[i]->upvalues[0].instack=0; - } - f->sizelineinfo=0; - return f; - } -} - -static int writer(lua_State* L, const void* p, size_t size, void* u) -{ - UNUSED(L); - return (fwrite(p,size,1,(FILE*)u)!=1) && (size!=0); -} - -static int pmain(lua_State* L) -{ - int argc=(int)lua_tointeger(L,1); - char** argv=(char**)lua_touserdata(L,2); - const Proto* f; - int i; - if (!lua_checkstack(L,argc)) fatal("too many input files"); - for (i=0; i1); - if (dumping) - { - FILE* D= (output==NULL) ? stdout : fopen(output,"wb"); - if (D==NULL) cannot("open"); - lua_lock(L); - luaU_dump(L,f,writer,D,stripping); - lua_unlock(L); - if (ferror(D)) cannot("write"); - if (fclose(D)) cannot("close"); - } - return 0; -} - -int main(int argc, char* argv[]) -{ - lua_State* L; - int i=doargs(argc,argv); - argc-=i; argv+=i; - if (argc<=0) usage("no input files given"); - L=luaL_newstate(); - if (L==NULL) fatal("cannot create state: not enough memory"); - lua_pushcfunction(L,&pmain); - lua_pushinteger(L,argc); - lua_pushlightuserdata(L,argv); - if (lua_pcall(L,2,0,0)!=LUA_OK) fatal(lua_tostring(L,-1)); - lua_close(L); - return EXIT_SUCCESS; -} - -/* -** $Id: luac.c,v 1.76 2018/06/19 01:32:02 lhf Exp $ -** print bytecodes -** See Copyright Notice in lua.h -*/ - -#include -#include - -#define luac_c -#define LUA_CORE - -#include "ldebug.h" -#include "lobject.h" -#include "lopcodes.h" - -#define VOID(p) ((const void*)(p)) - -static void PrintString(const TString* ts) -{ - const char* s=getstr(ts); - size_t i,n=tsslen(ts); - printf("%c",'"'); - for (i=0; ik[i]; - switch (ttype(o)) - { - case LUA_TNIL: - printf("nil"); - break; - case LUA_TBOOLEAN: - printf(bvalue(o) ? "true" : "false"); - break; - case LUA_TNUMFLT: - { - char buff[100]; - sprintf(buff,LUA_NUMBER_FMT,fltvalue(o)); - printf("%s",buff); - if (buff[strspn(buff,"-0123456789")]=='\0') printf(".0"); - break; - } - case LUA_TNUMINT: - printf(LUA_INTEGER_FMT,ivalue(o)); - break; - case LUA_TSHRSTR: case LUA_TLNGSTR: - PrintString(tsvalue(o)); - break; - default: /* cannot happen */ - printf("? type=%d",ttype(o)); - break; - } -} - -#define UPVALNAME(x) ((f->upvalues[x].name) ? getstr(f->upvalues[x].name) : "-") -#define MYK(x) (-1-(x)) - -static void PrintCode(const Proto* f) -{ - const Instruction* code=f->code; - int pc,n=f->sizecode; - for (pc=0; pc0) printf("[%d]\t",line); else printf("[-]\t"); - printf("%-9s\t",luaP_opnames[o]); - switch (getOpMode(o)) - { - case iABC: - printf("%d",a); - if (getBMode(o)!=OpArgN) printf(" %d",ISK(b) ? (MYK(INDEXK(b))) : b); - if (getCMode(o)!=OpArgN) printf(" %d",ISK(c) ? (MYK(INDEXK(c))) : c); - break; - case iABx: - printf("%d",a); - if (getBMode(o)==OpArgK) printf(" %d",MYK(bx)); - if (getBMode(o)==OpArgU) printf(" %d",bx); - break; - case iAsBx: - printf("%d %d",a,sbx); - break; - case iAx: - printf("%d",MYK(ax)); - break; - } - switch (o) - { - case OP_LOADK: - printf("\t; "); PrintConstant(f,bx); - break; - case OP_GETUPVAL: - case OP_SETUPVAL: - printf("\t; %s",UPVALNAME(b)); - break; - case OP_GETTABUP: - printf("\t; %s",UPVALNAME(b)); - if (ISK(c)) { printf(" "); PrintConstant(f,INDEXK(c)); } - break; - case OP_SETTABUP: - printf("\t; %s",UPVALNAME(a)); - if (ISK(b)) { printf(" "); PrintConstant(f,INDEXK(b)); } - if (ISK(c)) { printf(" "); PrintConstant(f,INDEXK(c)); } - break; - case OP_GETTABLE: - case OP_SELF: - if (ISK(c)) { printf("\t; "); PrintConstant(f,INDEXK(c)); } - break; - case OP_SETTABLE: - case OP_ADD: - case OP_SUB: - case OP_MUL: - case OP_MOD: - case OP_POW: - case OP_DIV: - case OP_IDIV: - case OP_BAND: - case OP_BOR: - case OP_BXOR: - case OP_SHL: - case OP_SHR: - case OP_EQ: - case OP_LT: - case OP_LE: - if (ISK(b) || ISK(c)) - { - printf("\t; "); - if (ISK(b)) PrintConstant(f,INDEXK(b)); else printf("-"); - printf(" "); - if (ISK(c)) PrintConstant(f,INDEXK(c)); else printf("-"); - } - break; - case OP_JMP: - case OP_FORLOOP: - case OP_FORPREP: - case OP_TFORLOOP: - printf("\t; to %d",sbx+pc+2); - break; - case OP_CLOSURE: - printf("\t; %p",VOID(f->p[bx])); - break; - case OP_SETLIST: - if (c==0) printf("\t; %d",(int)code[++pc]); else printf("\t; %d",c); - break; - case OP_EXTRAARG: - printf("\t; "); PrintConstant(f,ax); - break; - default: - break; - } - printf("\n"); - } -} - -#define SS(x) ((x==1)?"":"s") -#define S(x) (int)(x),SS(x) - -static void PrintHeader(const Proto* f) -{ - const char* s=f->source ? getstr(f->source) : "=?"; - if (*s=='@' || *s=='=') - s++; - else if (*s==LUA_SIGNATURE[0]) - s="(bstring)"; - else - s="(string)"; - printf("\n%s <%s:%d,%d> (%d instruction%s at %p)\n", - (f->linedefined==0)?"main":"function",s, - f->linedefined,f->lastlinedefined, - S(f->sizecode),VOID(f)); - printf("%d%s param%s, %d slot%s, %d upvalue%s, ", - (int)(f->numparams),f->is_vararg?"+":"",SS(f->numparams), - S(f->maxstacksize),S(f->sizeupvalues)); - printf("%d local%s, %d constant%s, %d function%s\n", - S(f->sizelocvars),S(f->sizek),S(f->sizep)); -} - -static void PrintDebug(const Proto* f) -{ - int i,n; - n=f->sizek; - printf("constants (%d) for %p:\n",n,VOID(f)); - for (i=0; isizelocvars; - printf("locals (%d) for %p:\n",n,VOID(f)); - for (i=0; ilocvars[i].varname),f->locvars[i].startpc+1,f->locvars[i].endpc+1); - } - n=f->sizeupvalues; - printf("upvalues (%d) for %p:\n",n,VOID(f)); - for (i=0; iupvalues[i].instack,f->upvalues[i].idx); - } -} - -static void PrintFunction(const Proto* f, int full) -{ - int i,n=f->sizep; - PrintHeader(f); - PrintCode(f); - if (full) PrintDebug(f); - for (i=0; ip[i],full); -} diff --git a/lib/lua-5.3/src/luaconf.h b/lib/lua-5.3/src/luaconf.h deleted file mode 100644 index 9eeeea6..0000000 --- a/lib/lua-5.3/src/luaconf.h +++ /dev/null @@ -1,790 +0,0 @@ -/* -** $Id: luaconf.h,v 1.259.1.1 2017/04/19 17:29:57 roberto Exp $ -** Configuration file for Lua -** See Copyright Notice in lua.h -*/ - - -#ifndef luaconf_h -#define luaconf_h - -#include -#include - - -/* -** =================================================================== -** Search for "@@" to find all configurable definitions. -** =================================================================== -*/ - - -/* -** {==================================================================== -** System Configuration: macros to adapt (if needed) Lua to some -** particular platform, for instance compiling it with 32-bit numbers or -** restricting it to C89. -** ===================================================================== -*/ - -/* -@@ LUA_32BITS enables Lua with 32-bit integers and 32-bit floats. You -** can also define LUA_32BITS in the make file, but changing here you -** ensure that all software connected to Lua will be compiled with the -** same configuration. -*/ -/* #define LUA_32BITS */ - - -/* -@@ LUA_USE_C89 controls the use of non-ISO-C89 features. -** Define it if you want Lua to avoid the use of a few C99 features -** or Windows-specific features on Windows. -*/ -/* #define LUA_USE_C89 */ - - -/* -** By default, Lua on Windows use (some) specific Windows features -*/ -#if !defined(LUA_USE_C89) && defined(_WIN32) && !defined(_WIN32_WCE) -#define LUA_USE_WINDOWS /* enable goodies for regular Windows */ -#endif - - -#if defined(LUA_USE_WINDOWS) -#define LUA_DL_DLL /* enable support for DLL */ -#define LUA_USE_C89 /* broadly, Windows is C89 */ -#endif - - -#if defined(LUA_USE_LINUX) -#define LUA_USE_POSIX -#define LUA_USE_DLOPEN /* needs an extra library: -ldl */ -#define LUA_USE_READLINE /* needs some extra libraries */ -#endif - - -#if defined(LUA_USE_MACOSX) -#define LUA_USE_POSIX -#define LUA_USE_DLOPEN /* MacOS does not need -ldl */ -#define LUA_USE_READLINE /* needs an extra library: -lreadline */ -#endif - - -/* -@@ LUA_C89_NUMBERS ensures that Lua uses the largest types available for -** C89 ('long' and 'double'); Windows always has '__int64', so it does -** not need to use this case. -*/ -#if defined(LUA_USE_C89) && !defined(LUA_USE_WINDOWS) -#define LUA_C89_NUMBERS -#endif - - - -/* -@@ LUAI_BITSINT defines the (minimum) number of bits in an 'int'. -*/ -/* avoid undefined shifts */ -#if ((INT_MAX >> 15) >> 15) >= 1 -#define LUAI_BITSINT 32 -#else -/* 'int' always must have at least 16 bits */ -#define LUAI_BITSINT 16 -#endif - - -/* -@@ LUA_INT_TYPE defines the type for Lua integers. -@@ LUA_FLOAT_TYPE defines the type for Lua floats. -** Lua should work fine with any mix of these options (if supported -** by your C compiler). The usual configurations are 64-bit integers -** and 'double' (the default), 32-bit integers and 'float' (for -** restricted platforms), and 'long'/'double' (for C compilers not -** compliant with C99, which may not have support for 'long long'). -*/ - -/* predefined options for LUA_INT_TYPE */ -#define LUA_INT_INT 1 -#define LUA_INT_LONG 2 -#define LUA_INT_LONGLONG 3 - -/* predefined options for LUA_FLOAT_TYPE */ -#define LUA_FLOAT_FLOAT 1 -#define LUA_FLOAT_DOUBLE 2 -#define LUA_FLOAT_LONGDOUBLE 3 - -#if defined(LUA_32BITS) /* { */ -/* -** 32-bit integers and 'float' -*/ -#if LUAI_BITSINT >= 32 /* use 'int' if big enough */ -#define LUA_INT_TYPE LUA_INT_INT -#else /* otherwise use 'long' */ -#define LUA_INT_TYPE LUA_INT_LONG -#endif -#define LUA_FLOAT_TYPE LUA_FLOAT_FLOAT - -#elif defined(LUA_C89_NUMBERS) /* }{ */ -/* -** largest types available for C89 ('long' and 'double') -*/ -#define LUA_INT_TYPE LUA_INT_LONG -#define LUA_FLOAT_TYPE LUA_FLOAT_DOUBLE - -#endif /* } */ - - -/* -** default configuration for 64-bit Lua ('long long' and 'double') -*/ -#if !defined(LUA_INT_TYPE) -#define LUA_INT_TYPE LUA_INT_LONGLONG -#endif - -#if !defined(LUA_FLOAT_TYPE) -#define LUA_FLOAT_TYPE LUA_FLOAT_DOUBLE -#endif - -/* }================================================================== */ - - - - -/* -** {================================================================== -** Configuration for Paths. -** =================================================================== -*/ - -/* -** LUA_PATH_SEP is the character that separates templates in a path. -** LUA_PATH_MARK is the string that marks the substitution points in a -** template. -** LUA_EXEC_DIR in a Windows path is replaced by the executable's -** directory. -*/ -#define LUA_PATH_SEP ";" -#define LUA_PATH_MARK "?" -#define LUA_EXEC_DIR "!" - - -/* -@@ LUA_PATH_DEFAULT is the default path that Lua uses to look for -** Lua libraries. -@@ LUA_CPATH_DEFAULT is the default path that Lua uses to look for -** C libraries. -** CHANGE them if your machine has a non-conventional directory -** hierarchy or if you want to install your libraries in -** non-conventional directories. -*/ -#define LUA_VDIR LUA_VERSION_MAJOR "." LUA_VERSION_MINOR -#if defined(_WIN32) /* { */ -/* -** In Windows, any exclamation mark ('!') in the path is replaced by the -** path of the directory of the executable file of the current process. -*/ -#define LUA_LDIR "!\\lua\\" -#define LUA_CDIR "!\\" -#define LUA_SHRDIR "!\\..\\share\\lua\\" LUA_VDIR "\\" -#define LUA_PATH_DEFAULT \ - LUA_LDIR"?.lua;" LUA_LDIR"?\\init.lua;" \ - LUA_CDIR"?.lua;" LUA_CDIR"?\\init.lua;" \ - LUA_SHRDIR"?.lua;" LUA_SHRDIR"?\\init.lua;" \ - ".\\?.lua;" ".\\?\\init.lua" -#define LUA_CPATH_DEFAULT \ - LUA_CDIR"?.dll;" \ - LUA_CDIR"..\\lib\\lua\\" LUA_VDIR "\\?.dll;" \ - LUA_CDIR"loadall.dll;" ".\\?.dll" - -#else /* }{ */ - -#define LUA_ROOT "/usr/local/" -#define LUA_LDIR LUA_ROOT "share/lua/" LUA_VDIR "/" -#define LUA_CDIR LUA_ROOT "lib/lua/" LUA_VDIR "/" -#define LUA_PATH_DEFAULT \ - LUA_LDIR"?.lua;" LUA_LDIR"?/init.lua;" \ - LUA_CDIR"?.lua;" LUA_CDIR"?/init.lua;" \ - "./?.lua;" "./?/init.lua" -#define LUA_CPATH_DEFAULT \ - LUA_CDIR"?.so;" LUA_CDIR"loadall.so;" "./?.so" -#endif /* } */ - - -/* -@@ LUA_DIRSEP is the directory separator (for submodules). -** CHANGE it if your machine does not use "/" as the directory separator -** and is not Windows. (On Windows Lua automatically uses "\".) -*/ -#if defined(_WIN32) -#define LUA_DIRSEP "\\" -#else -#define LUA_DIRSEP "/" -#endif - -/* }================================================================== */ - - -/* -** {================================================================== -** Marks for exported symbols in the C code -** =================================================================== -*/ - -/* -@@ LUA_API is a mark for all core API functions. -@@ LUALIB_API is a mark for all auxiliary library functions. -@@ LUAMOD_API is a mark for all standard library opening functions. -** CHANGE them if you need to define those functions in some special way. -** For instance, if you want to create one Windows DLL with the core and -** the libraries, you may want to use the following definition (define -** LUA_BUILD_AS_DLL to get it). -*/ -#if defined(LUA_BUILD_AS_DLL) /* { */ - -#if defined(LUA_CORE) || defined(LUA_LIB) /* { */ -#define LUA_API __declspec(dllexport) -#else /* }{ */ -#define LUA_API __declspec(dllimport) -#endif /* } */ - -#else /* }{ */ - -#define LUA_API extern - -#endif /* } */ - - -/* more often than not the libs go together with the core */ -#define LUALIB_API LUA_API -#define LUAMOD_API LUALIB_API - - -/* -@@ LUAI_FUNC is a mark for all extern functions that are not to be -** exported to outside modules. -@@ LUAI_DDEF and LUAI_DDEC are marks for all extern (const) variables -** that are not to be exported to outside modules (LUAI_DDEF for -** definitions and LUAI_DDEC for declarations). -** CHANGE them if you need to mark them in some special way. Elf/gcc -** (versions 3.2 and later) mark them as "hidden" to optimize access -** when Lua is compiled as a shared library. Not all elf targets support -** this attribute. Unfortunately, gcc does not offer a way to check -** whether the target offers that support, and those without support -** give a warning about it. To avoid these warnings, change to the -** default definition. -*/ -#if defined(__GNUC__) && ((__GNUC__*100 + __GNUC_MINOR__) >= 302) && \ - defined(__ELF__) /* { */ -#define LUAI_FUNC __attribute__((visibility("hidden"))) extern -#else /* }{ */ -#define LUAI_FUNC extern -#endif /* } */ - -#define LUAI_DDEC LUAI_FUNC -#define LUAI_DDEF /* empty */ - -/* }================================================================== */ - - -/* -** {================================================================== -** Compatibility with previous versions -** =================================================================== -*/ - -/* -@@ LUA_COMPAT_5_2 controls other macros for compatibility with Lua 5.2. -@@ LUA_COMPAT_5_1 controls other macros for compatibility with Lua 5.1. -** You can define it to get all options, or change specific options -** to fit your specific needs. -*/ -#if defined(LUA_COMPAT_5_2) /* { */ - -/* -@@ LUA_COMPAT_MATHLIB controls the presence of several deprecated -** functions in the mathematical library. -*/ -#define LUA_COMPAT_MATHLIB - -/* -@@ LUA_COMPAT_BITLIB controls the presence of library 'bit32'. -*/ -#define LUA_COMPAT_BITLIB - -/* -@@ LUA_COMPAT_IPAIRS controls the effectiveness of the __ipairs metamethod. -*/ -#define LUA_COMPAT_IPAIRS - -/* -@@ LUA_COMPAT_APIINTCASTS controls the presence of macros for -** manipulating other integer types (lua_pushunsigned, lua_tounsigned, -** luaL_checkint, luaL_checklong, etc.) -*/ -#define LUA_COMPAT_APIINTCASTS - -#endif /* } */ - - -#if defined(LUA_COMPAT_5_1) /* { */ - -/* Incompatibilities from 5.2 -> 5.3 */ -#define LUA_COMPAT_MATHLIB -#define LUA_COMPAT_APIINTCASTS - -/* -@@ LUA_COMPAT_UNPACK controls the presence of global 'unpack'. -** You can replace it with 'table.unpack'. -*/ -#define LUA_COMPAT_UNPACK - -/* -@@ LUA_COMPAT_LOADERS controls the presence of table 'package.loaders'. -** You can replace it with 'package.searchers'. -*/ -#define LUA_COMPAT_LOADERS - -/* -@@ macro 'lua_cpcall' emulates deprecated function lua_cpcall. -** You can call your C function directly (with light C functions). -*/ -#define lua_cpcall(L,f,u) \ - (lua_pushcfunction(L, (f)), \ - lua_pushlightuserdata(L,(u)), \ - lua_pcall(L,1,0,0)) - - -/* -@@ LUA_COMPAT_LOG10 defines the function 'log10' in the math library. -** You can rewrite 'log10(x)' as 'log(x, 10)'. -*/ -#define LUA_COMPAT_LOG10 - -/* -@@ LUA_COMPAT_LOADSTRING defines the function 'loadstring' in the base -** library. You can rewrite 'loadstring(s)' as 'load(s)'. -*/ -#define LUA_COMPAT_LOADSTRING - -/* -@@ LUA_COMPAT_MAXN defines the function 'maxn' in the table library. -*/ -#define LUA_COMPAT_MAXN - -/* -@@ The following macros supply trivial compatibility for some -** changes in the API. The macros themselves document how to -** change your code to avoid using them. -*/ -#define lua_strlen(L,i) lua_rawlen(L, (i)) - -#define lua_objlen(L,i) lua_rawlen(L, (i)) - -#define lua_equal(L,idx1,idx2) lua_compare(L,(idx1),(idx2),LUA_OPEQ) -#define lua_lessthan(L,idx1,idx2) lua_compare(L,(idx1),(idx2),LUA_OPLT) - -/* -@@ LUA_COMPAT_MODULE controls compatibility with previous -** module functions 'module' (Lua) and 'luaL_register' (C). -*/ -#define LUA_COMPAT_MODULE - -#endif /* } */ - - -/* -@@ LUA_COMPAT_FLOATSTRING makes Lua format integral floats without a -@@ a float mark ('.0'). -** This macro is not on by default even in compatibility mode, -** because this is not really an incompatibility. -*/ -/* #define LUA_COMPAT_FLOATSTRING */ - -/* }================================================================== */ - - - -/* -** {================================================================== -** Configuration for Numbers. -** Change these definitions if no predefined LUA_FLOAT_* / LUA_INT_* -** satisfy your needs. -** =================================================================== -*/ - -/* -@@ LUA_NUMBER is the floating-point type used by Lua. -@@ LUAI_UACNUMBER is the result of a 'default argument promotion' -@@ over a floating number. -@@ l_mathlim(x) corrects limit name 'x' to the proper float type -** by prefixing it with one of FLT/DBL/LDBL. -@@ LUA_NUMBER_FRMLEN is the length modifier for writing floats. -@@ LUA_NUMBER_FMT is the format for writing floats. -@@ lua_number2str converts a float to a string. -@@ l_mathop allows the addition of an 'l' or 'f' to all math operations. -@@ l_floor takes the floor of a float. -@@ lua_str2number converts a decimal numeric string to a number. -*/ - - -/* The following definitions are good for most cases here */ - -#define l_floor(x) (l_mathop(floor)(x)) - -#define lua_number2str(s,sz,n) \ - l_sprintf((s), sz, LUA_NUMBER_FMT, (LUAI_UACNUMBER)(n)) - -/* -@@ lua_numbertointeger converts a float number to an integer, or -** returns 0 if float is not within the range of a lua_Integer. -** (The range comparisons are tricky because of rounding. The tests -** here assume a two-complement representation, where MININTEGER always -** has an exact representation as a float; MAXINTEGER may not have one, -** and therefore its conversion to float may have an ill-defined value.) -*/ -#define lua_numbertointeger(n,p) \ - ((n) >= (LUA_NUMBER)(LUA_MININTEGER) && \ - (n) < -(LUA_NUMBER)(LUA_MININTEGER) && \ - (*(p) = (LUA_INTEGER)(n), 1)) - - -/* now the variable definitions */ - -#if LUA_FLOAT_TYPE == LUA_FLOAT_FLOAT /* { single float */ - -#define LUA_NUMBER float - -#define l_mathlim(n) (FLT_##n) - -#define LUAI_UACNUMBER double - -#define LUA_NUMBER_FRMLEN "" -#define LUA_NUMBER_FMT "%.7g" - -#define l_mathop(op) op##f - -#define lua_str2number(s,p) strtof((s), (p)) - - -#elif LUA_FLOAT_TYPE == LUA_FLOAT_LONGDOUBLE /* }{ long double */ - -#define LUA_NUMBER long double - -#define l_mathlim(n) (LDBL_##n) - -#define LUAI_UACNUMBER long double - -#define LUA_NUMBER_FRMLEN "L" -#define LUA_NUMBER_FMT "%.19Lg" - -#define l_mathop(op) op##l - -#define lua_str2number(s,p) strtold((s), (p)) - -#elif LUA_FLOAT_TYPE == LUA_FLOAT_DOUBLE /* }{ double */ - -#define LUA_NUMBER double - -#define l_mathlim(n) (DBL_##n) - -#define LUAI_UACNUMBER double - -#define LUA_NUMBER_FRMLEN "" -#define LUA_NUMBER_FMT "%.14g" - -#define l_mathop(op) op - -#define lua_str2number(s,p) strtod((s), (p)) - -#else /* }{ */ - -#error "numeric float type not defined" - -#endif /* } */ - - - -/* -@@ LUA_INTEGER is the integer type used by Lua. -** -@@ LUA_UNSIGNED is the unsigned version of LUA_INTEGER. -** -@@ LUAI_UACINT is the result of a 'default argument promotion' -@@ over a lUA_INTEGER. -@@ LUA_INTEGER_FRMLEN is the length modifier for reading/writing integers. -@@ LUA_INTEGER_FMT is the format for writing integers. -@@ LUA_MAXINTEGER is the maximum value for a LUA_INTEGER. -@@ LUA_MININTEGER is the minimum value for a LUA_INTEGER. -@@ lua_integer2str converts an integer to a string. -*/ - - -/* The following definitions are good for most cases here */ - -#define LUA_INTEGER_FMT "%" LUA_INTEGER_FRMLEN "d" - -#define LUAI_UACINT LUA_INTEGER - -#define lua_integer2str(s,sz,n) \ - l_sprintf((s), sz, LUA_INTEGER_FMT, (LUAI_UACINT)(n)) - -/* -** use LUAI_UACINT here to avoid problems with promotions (which -** can turn a comparison between unsigneds into a signed comparison) -*/ -#define LUA_UNSIGNED unsigned LUAI_UACINT - - -/* now the variable definitions */ - -#if LUA_INT_TYPE == LUA_INT_INT /* { int */ - -#define LUA_INTEGER int -#define LUA_INTEGER_FRMLEN "" - -#define LUA_MAXINTEGER INT_MAX -#define LUA_MININTEGER INT_MIN - -#elif LUA_INT_TYPE == LUA_INT_LONG /* }{ long */ - -#define LUA_INTEGER long -#define LUA_INTEGER_FRMLEN "l" - -#define LUA_MAXINTEGER LONG_MAX -#define LUA_MININTEGER LONG_MIN - -#elif LUA_INT_TYPE == LUA_INT_LONGLONG /* }{ long long */ - -/* use presence of macro LLONG_MAX as proxy for C99 compliance */ -#if defined(LLONG_MAX) /* { */ -/* use ISO C99 stuff */ - -#define LUA_INTEGER long long -#define LUA_INTEGER_FRMLEN "ll" - -#define LUA_MAXINTEGER LLONG_MAX -#define LUA_MININTEGER LLONG_MIN - -#elif defined(LUA_USE_WINDOWS) /* }{ */ -/* in Windows, can use specific Windows types */ - -#define LUA_INTEGER __int64 -#define LUA_INTEGER_FRMLEN "I64" - -#define LUA_MAXINTEGER _I64_MAX -#define LUA_MININTEGER _I64_MIN - -#else /* }{ */ - -#error "Compiler does not support 'long long'. Use option '-DLUA_32BITS' \ - or '-DLUA_C89_NUMBERS' (see file 'luaconf.h' for details)" - -#endif /* } */ - -#else /* }{ */ - -#error "numeric integer type not defined" - -#endif /* } */ - -/* }================================================================== */ - - -/* -** {================================================================== -** Dependencies with C99 and other C details -** =================================================================== -*/ - -/* -@@ l_sprintf is equivalent to 'snprintf' or 'sprintf' in C89. -** (All uses in Lua have only one format item.) -*/ -#if !defined(LUA_USE_C89) -#define l_sprintf(s,sz,f,i) snprintf(s,sz,f,i) -#else -#define l_sprintf(s,sz,f,i) ((void)(sz), sprintf(s,f,i)) -#endif - - -/* -@@ lua_strx2number converts an hexadecimal numeric string to a number. -** In C99, 'strtod' does that conversion. Otherwise, you can -** leave 'lua_strx2number' undefined and Lua will provide its own -** implementation. -*/ -#if !defined(LUA_USE_C89) -#define lua_strx2number(s,p) lua_str2number(s,p) -#endif - - -/* -@@ lua_pointer2str converts a pointer to a readable string in a -** non-specified way. -*/ -#define lua_pointer2str(buff,sz,p) l_sprintf(buff,sz,"%p",p) - - -/* -@@ lua_number2strx converts a float to an hexadecimal numeric string. -** In C99, 'sprintf' (with format specifiers '%a'/'%A') does that. -** Otherwise, you can leave 'lua_number2strx' undefined and Lua will -** provide its own implementation. -*/ -#if !defined(LUA_USE_C89) -#define lua_number2strx(L,b,sz,f,n) \ - ((void)L, l_sprintf(b,sz,f,(LUAI_UACNUMBER)(n))) -#endif - - -/* -** 'strtof' and 'opf' variants for math functions are not valid in -** C89. Otherwise, the macro 'HUGE_VALF' is a good proxy for testing the -** availability of these variants. ('math.h' is already included in -** all files that use these macros.) -*/ -#if defined(LUA_USE_C89) || (defined(HUGE_VAL) && !defined(HUGE_VALF)) -#undef l_mathop /* variants not available */ -#undef lua_str2number -#define l_mathop(op) (lua_Number)op /* no variant */ -#define lua_str2number(s,p) ((lua_Number)strtod((s), (p))) -#endif - - -/* -@@ LUA_KCONTEXT is the type of the context ('ctx') for continuation -** functions. It must be a numerical type; Lua will use 'intptr_t' if -** available, otherwise it will use 'ptrdiff_t' (the nearest thing to -** 'intptr_t' in C89) -*/ -#define LUA_KCONTEXT ptrdiff_t - -#if !defined(LUA_USE_C89) && defined(__STDC_VERSION__) && \ - __STDC_VERSION__ >= 199901L -#include -#if defined(INTPTR_MAX) /* even in C99 this type is optional */ -#undef LUA_KCONTEXT -#define LUA_KCONTEXT intptr_t -#endif -#endif - - -/* -@@ lua_getlocaledecpoint gets the locale "radix character" (decimal point). -** Change that if you do not want to use C locales. (Code using this -** macro must include header 'locale.h'.) -*/ -#if !defined(lua_getlocaledecpoint) -#define lua_getlocaledecpoint() (localeconv()->decimal_point[0]) -#endif - -/* }================================================================== */ - - -/* -** {================================================================== -** Language Variations -** ===================================================================== -*/ - -/* -@@ LUA_NOCVTN2S/LUA_NOCVTS2N control how Lua performs some -** coercions. Define LUA_NOCVTN2S to turn off automatic coercion from -** numbers to strings. Define LUA_NOCVTS2N to turn off automatic -** coercion from strings to numbers. -*/ -/* #define LUA_NOCVTN2S */ -/* #define LUA_NOCVTS2N */ - - -/* -@@ LUA_USE_APICHECK turns on several consistency checks on the C API. -** Define it as a help when debugging C code. -*/ -#if defined(LUA_USE_APICHECK) -#include -#define luai_apicheck(l,e) assert(e) -#endif - -/* }================================================================== */ - - -/* -** {================================================================== -** Macros that affect the API and must be stable (that is, must be the -** same when you compile Lua and when you compile code that links to -** Lua). You probably do not want/need to change them. -** ===================================================================== -*/ - -/* -@@ LUAI_MAXSTACK limits the size of the Lua stack. -** CHANGE it if you need a different limit. This limit is arbitrary; -** its only purpose is to stop Lua from consuming unlimited stack -** space (and to reserve some numbers for pseudo-indices). -*/ -#if LUAI_BITSINT >= 32 -#define LUAI_MAXSTACK 1000000 -#else -#define LUAI_MAXSTACK 15000 -#endif - - -/* -@@ LUA_EXTRASPACE defines the size of a raw memory area associated with -** a Lua state with very fast access. -** CHANGE it if you need a different size. -*/ -#define LUA_EXTRASPACE (sizeof(void *)) - - -/* -@@ LUA_IDSIZE gives the maximum size for the description of the source -@@ of a function in debug information. -** CHANGE it if you want a different size. -*/ -#define LUA_IDSIZE 60 - - -/* -@@ LUAL_BUFFERSIZE is the buffer size used by the lauxlib buffer system. -** CHANGE it if it uses too much C-stack space. (For long double, -** 'string.format("%.99f", -1e4932)' needs 5034 bytes, so a -** smaller buffer would force a memory allocation for each call to -** 'string.format'.) -*/ -#if LUA_FLOAT_TYPE == LUA_FLOAT_LONGDOUBLE -#define LUAL_BUFFERSIZE 8192 -#else -#define LUAL_BUFFERSIZE ((int)(0x80 * sizeof(void*) * sizeof(lua_Integer))) -#endif - -/* }================================================================== */ - - -/* -@@ LUA_QL describes how error messages quote program elements. -** Lua does not use these macros anymore; they are here for -** compatibility only. -*/ -#define LUA_QL(x) "'" x "'" -#define LUA_QS LUA_QL("%s") - - - - -/* =================================================================== */ - -/* -** Local configuration. You can use this space to add your redefinitions -** without modifying the main part of the file. -*/ - - - - - -#endif - diff --git a/lib/lua-5.3/src/lualib.h b/lib/lua-5.3/src/lualib.h deleted file mode 100644 index f5304aa..0000000 --- a/lib/lua-5.3/src/lualib.h +++ /dev/null @@ -1,61 +0,0 @@ -/* -** $Id: lualib.h,v 1.45.1.1 2017/04/19 17:20:42 roberto Exp $ -** Lua standard libraries -** See Copyright Notice in lua.h -*/ - - -#ifndef lualib_h -#define lualib_h - -#include "lua.h" - - -/* version suffix for environment variable names */ -#define LUA_VERSUFFIX "_" LUA_VERSION_MAJOR "_" LUA_VERSION_MINOR - - -LUAMOD_API int (luaopen_base) (lua_State *L); - -#define LUA_COLIBNAME "coroutine" -LUAMOD_API int (luaopen_coroutine) (lua_State *L); - -#define LUA_TABLIBNAME "table" -LUAMOD_API int (luaopen_table) (lua_State *L); - -#define LUA_IOLIBNAME "io" -LUAMOD_API int (luaopen_io) (lua_State *L); - -#define LUA_OSLIBNAME "os" -LUAMOD_API int (luaopen_os) (lua_State *L); - -#define LUA_STRLIBNAME "string" -LUAMOD_API int (luaopen_string) (lua_State *L); - -#define LUA_UTF8LIBNAME "utf8" -LUAMOD_API int (luaopen_utf8) (lua_State *L); - -#define LUA_BITLIBNAME "bit32" -LUAMOD_API int (luaopen_bit32) (lua_State *L); - -#define LUA_MATHLIBNAME "math" -LUAMOD_API int (luaopen_math) (lua_State *L); - -#define LUA_DBLIBNAME "debug" -LUAMOD_API int (luaopen_debug) (lua_State *L); - -#define LUA_LOADLIBNAME "package" -LUAMOD_API int (luaopen_package) (lua_State *L); - - -/* open all previous libraries */ -LUALIB_API void (luaL_openlibs) (lua_State *L); - - - -#if !defined(lua_assert) -#define lua_assert(x) ((void)0) -#endif - - -#endif diff --git a/lib/lua-5.3/src/lundump.c b/lib/lua-5.3/src/lundump.c deleted file mode 100644 index edf9eb8..0000000 --- a/lib/lua-5.3/src/lundump.c +++ /dev/null @@ -1,287 +0,0 @@ -/* -** $Id: lundump.c,v 2.44.1.1 2017/04/19 17:20:42 roberto Exp $ -** load precompiled Lua chunks -** See Copyright Notice in lua.h -*/ - -#define lundump_c -#define LUA_CORE - -#include "lprefix.h" - - -#include - -#include "lua.h" - -#include "ldebug.h" -#include "ldo.h" -#include "lfunc.h" -#include "lmem.h" -#include "lobject.h" -#include "lstring.h" -#include "lundump.h" -#include "lzio.h" - - -#if !defined(luai_verifycode) -#define luai_verifycode(L,b,f) /* empty */ -#endif - - -typedef struct { - lua_State *L; - ZIO *Z; - const char *name; -} LoadState; - - -static l_noret error(LoadState *S, const char *why) { - luaO_pushfstring(S->L, "%s: %s precompiled chunk", S->name, why); - luaD_throw(S->L, LUA_ERRSYNTAX); -} - - -/* -** All high-level loads go through LoadVector; you can change it to -** adapt to the endianness of the input -*/ -#define LoadVector(S,b,n) LoadBlock(S,b,(n)*sizeof((b)[0])) - -static void LoadBlock (LoadState *S, void *b, size_t size) { - if (luaZ_read(S->Z, b, size) != 0) - error(S, "truncated"); -} - - -#define LoadVar(S,x) LoadVector(S,&x,1) - - -static lu_byte LoadByte (LoadState *S) { - lu_byte x; - LoadVar(S, x); - return x; -} - - -static int LoadInt (LoadState *S) { - int x; - LoadVar(S, x); - return x; -} - - -static lua_Number LoadNumber (LoadState *S) { - lua_Number x; - LoadVar(S, x); - return x; -} - - -static lua_Integer LoadInteger (LoadState *S) { - lua_Integer x; - LoadVar(S, x); - return x; -} - - -static TString *LoadString (LoadState *S, Proto *p) { - lua_State *L = S->L; - size_t size = LoadByte(S); - TString *ts; - if (size == 0xFF) - LoadVar(S, size); - if (size == 0) - return NULL; - else if (--size <= LUAI_MAXSHORTLEN) { /* short string? */ - char buff[LUAI_MAXSHORTLEN]; - LoadVector(S, buff, size); - ts = luaS_newlstr(L, buff, size); - } - else { /* long string */ - ts = luaS_createlngstrobj(L, size); - setsvalue2s(L, L->top, ts); /* anchor it ('loadVector' can GC) */ - luaD_inctop(L); - LoadVector(S, getstr(ts), size); /* load directly in final place */ - L->top--; /* pop string */ - } - luaC_objbarrier(L, p, ts); - return ts; -} - - -static void LoadCode (LoadState *S, Proto *f) { - int n = LoadInt(S); - f->code = luaM_newvector(S->L, n, Instruction); - f->sizecode = n; - LoadVector(S, f->code, n); -} - - -static void LoadFunction(LoadState *S, Proto *f, TString *psource); - - -static void LoadConstants (LoadState *S, Proto *f) { - int i; - int n = LoadInt(S); - f->k = luaM_newvector(S->L, n, TValue); - f->sizek = n; - for (i = 0; i < n; i++) - setnilvalue(&f->k[i]); - for (i = 0; i < n; i++) { - TValue *o = &f->k[i]; - int t = LoadByte(S); - switch (t) { - case LUA_TNIL: - setnilvalue(o); - break; - case LUA_TBOOLEAN: - setbvalue(o, LoadByte(S)); - break; - case LUA_TNUMFLT: - setfltvalue(o, LoadNumber(S)); - break; - case LUA_TNUMINT: - setivalue(o, LoadInteger(S)); - break; - case LUA_TSHRSTR: - case LUA_TLNGSTR: - setsvalue2n(S->L, o, LoadString(S, f)); - break; - default: - lua_assert(0); - } - } -} - - -static void LoadProtos (LoadState *S, Proto *f) { - int i; - int n = LoadInt(S); - f->p = luaM_newvector(S->L, n, Proto *); - f->sizep = n; - for (i = 0; i < n; i++) - f->p[i] = NULL; - for (i = 0; i < n; i++) { - f->p[i] = luaF_newproto(S->L); - luaC_objbarrier(S->L, f, f->p[i]); - LoadFunction(S, f->p[i], f->source); - } -} - - -static void LoadUpvalues (LoadState *S, Proto *f) { - int i, n; - n = LoadInt(S); - f->upvalues = luaM_newvector(S->L, n, Upvaldesc); - f->sizeupvalues = n; - for (i = 0; i < n; i++) - f->upvalues[i].name = NULL; - for (i = 0; i < n; i++) { - f->upvalues[i].instack = LoadByte(S); - f->upvalues[i].idx = LoadByte(S); - } -} - - -static void LoadDebug (LoadState *S, Proto *f) { - int i, n; - n = LoadInt(S); - f->lineinfo = luaM_newvector(S->L, n, int); - f->sizelineinfo = n; - LoadVector(S, f->lineinfo, n); - n = LoadInt(S); - f->locvars = luaM_newvector(S->L, n, LocVar); - f->sizelocvars = n; - for (i = 0; i < n; i++) - f->locvars[i].varname = NULL; - for (i = 0; i < n; i++) { - f->locvars[i].varname = LoadString(S, f); - f->locvars[i].startpc = LoadInt(S); - f->locvars[i].endpc = LoadInt(S); - } - n = LoadInt(S); - for (i = 0; i < n; i++) - f->upvalues[i].name = LoadString(S, f); -} - - -static void LoadFunction (LoadState *S, Proto *f, TString *psource) { - f->source = LoadString(S, f); - if (f->source == NULL) /* no source in dump? */ - f->source = psource; /* reuse parent's source */ - f->linedefined = LoadInt(S); - f->lastlinedefined = LoadInt(S); - f->numparams = LoadByte(S); - f->is_vararg = LoadByte(S); - f->maxstacksize = LoadByte(S); - LoadCode(S, f); - LoadConstants(S, f); - LoadUpvalues(S, f); - LoadProtos(S, f); - LoadDebug(S, f); -} - - -static void checkliteral (LoadState *S, const char *s, const char *msg) { - char buff[sizeof(LUA_SIGNATURE) + sizeof(LUAC_DATA)]; /* larger than both */ - size_t len = strlen(s); - LoadVector(S, buff, len); - if (memcmp(s, buff, len) != 0) - error(S, msg); -} - - -static void fchecksize (LoadState *S, size_t size, const char *tname) { - if (LoadByte(S) != size) - error(S, luaO_pushfstring(S->L, "%s size mismatch in", tname)); -} - - -#define checksize(S,t) fchecksize(S,sizeof(t),#t) - -static void checkHeader (LoadState *S) { - checkliteral(S, LUA_SIGNATURE + 1, "not a"); /* 1st char already checked */ - if (LoadByte(S) != LUAC_VERSION) - error(S, "version mismatch in"); - if (LoadByte(S) != LUAC_FORMAT) - error(S, "format mismatch in"); - checkliteral(S, LUAC_DATA, "corrupted"); - checksize(S, int); - checksize(S, size_t); - checksize(S, Instruction); - checksize(S, lua_Integer); - checksize(S, lua_Number); - if (LoadInteger(S) != LUAC_INT) - error(S, "endianness mismatch in"); - if (LoadNumber(S) != LUAC_NUM) - error(S, "float format mismatch in"); -} - - -/* -** load precompiled chunk -*/ -LClosure *luaU_undump(lua_State *L, ZIO *Z, const char *name) { - LoadState S; - LClosure *cl; - if (*name == '@' || *name == '=') - S.name = name + 1; - else if (*name == LUA_SIGNATURE[0]) - S.name = "binary string"; - else - S.name = name; - S.L = L; - S.Z = Z; - checkHeader(&S); - cl = luaF_newLclosure(L, LoadByte(&S)); - setclLvalue(L, L->top, cl); - luaD_inctop(L); - cl->p = luaF_newproto(L); - luaC_objbarrier(L, cl, cl->p); - LoadFunction(&S, cl->p, NULL); - lua_assert(cl->nupvalues == cl->p->sizeupvalues); - luai_verifycode(L, buff, cl->p); - return cl; -} - diff --git a/lib/lua-5.3/src/lundump.h b/lib/lua-5.3/src/lundump.h deleted file mode 100644 index ce492d6..0000000 --- a/lib/lua-5.3/src/lundump.h +++ /dev/null @@ -1,32 +0,0 @@ -/* -** $Id: lundump.h,v 1.45.1.1 2017/04/19 17:20:42 roberto Exp $ -** load precompiled Lua chunks -** See Copyright Notice in lua.h -*/ - -#ifndef lundump_h -#define lundump_h - -#include "llimits.h" -#include "lobject.h" -#include "lzio.h" - - -/* data to catch conversion errors */ -#define LUAC_DATA "\x19\x93\r\n\x1a\n" - -#define LUAC_INT 0x5678 -#define LUAC_NUM cast_num(370.5) - -#define MYINT(s) (s[0]-'0') -#define LUAC_VERSION (MYINT(LUA_VERSION_MAJOR)*16+MYINT(LUA_VERSION_MINOR)) -#define LUAC_FORMAT 0 /* this is the official format */ - -/* load one chunk; from lundump.c */ -LUAI_FUNC LClosure* luaU_undump (lua_State* L, ZIO* Z, const char* name); - -/* dump one chunk; from ldump.c */ -LUAI_FUNC int luaU_dump (lua_State* L, const Proto* f, lua_Writer w, - void* data, int strip); - -#endif diff --git a/lib/lua-5.3/src/lutf8lib.c b/lib/lua-5.3/src/lutf8lib.c deleted file mode 100644 index 10bd238..0000000 --- a/lib/lua-5.3/src/lutf8lib.c +++ /dev/null @@ -1,256 +0,0 @@ -/* -** $Id: lutf8lib.c,v 1.16.1.1 2017/04/19 17:29:57 roberto Exp $ -** Standard library for UTF-8 manipulation -** See Copyright Notice in lua.h -*/ - -#define lutf8lib_c -#define LUA_LIB - -#include "lprefix.h" - - -#include -#include -#include -#include - -#include "lua.h" - -#include "lauxlib.h" -#include "lualib.h" - -#define MAXUNICODE 0x10FFFF - -#define iscont(p) ((*(p) & 0xC0) == 0x80) - - -/* from strlib */ -/* translate a relative string position: negative means back from end */ -static lua_Integer u_posrelat (lua_Integer pos, size_t len) { - if (pos >= 0) return pos; - else if (0u - (size_t)pos > len) return 0; - else return (lua_Integer)len + pos + 1; -} - - -/* -** Decode one UTF-8 sequence, returning NULL if byte sequence is invalid. -*/ -static const char *utf8_decode (const char *o, int *val) { - static const unsigned int limits[] = {0xFF, 0x7F, 0x7FF, 0xFFFF}; - const unsigned char *s = (const unsigned char *)o; - unsigned int c = s[0]; - unsigned int res = 0; /* final result */ - if (c < 0x80) /* ascii? */ - res = c; - else { - int count = 0; /* to count number of continuation bytes */ - while (c & 0x40) { /* still have continuation bytes? */ - int cc = s[++count]; /* read next byte */ - if ((cc & 0xC0) != 0x80) /* not a continuation byte? */ - return NULL; /* invalid byte sequence */ - res = (res << 6) | (cc & 0x3F); /* add lower 6 bits from cont. byte */ - c <<= 1; /* to test next bit */ - } - res |= ((c & 0x7F) << (count * 5)); /* add first byte */ - if (count > 3 || res > MAXUNICODE || res <= limits[count]) - return NULL; /* invalid byte sequence */ - s += count; /* skip continuation bytes read */ - } - if (val) *val = res; - return (const char *)s + 1; /* +1 to include first byte */ -} - - -/* -** utf8len(s [, i [, j]]) --> number of characters that start in the -** range [i,j], or nil + current position if 's' is not well formed in -** that interval -*/ -static int utflen (lua_State *L) { - int n = 0; - size_t len; - const char *s = luaL_checklstring(L, 1, &len); - lua_Integer posi = u_posrelat(luaL_optinteger(L, 2, 1), len); - lua_Integer posj = u_posrelat(luaL_optinteger(L, 3, -1), len); - luaL_argcheck(L, 1 <= posi && --posi <= (lua_Integer)len, 2, - "initial position out of string"); - luaL_argcheck(L, --posj < (lua_Integer)len, 3, - "final position out of string"); - while (posi <= posj) { - const char *s1 = utf8_decode(s + posi, NULL); - if (s1 == NULL) { /* conversion error? */ - lua_pushnil(L); /* return nil ... */ - lua_pushinteger(L, posi + 1); /* ... and current position */ - return 2; - } - posi = s1 - s; - n++; - } - lua_pushinteger(L, n); - return 1; -} - - -/* -** codepoint(s, [i, [j]]) -> returns codepoints for all characters -** that start in the range [i,j] -*/ -static int codepoint (lua_State *L) { - size_t len; - const char *s = luaL_checklstring(L, 1, &len); - lua_Integer posi = u_posrelat(luaL_optinteger(L, 2, 1), len); - lua_Integer pose = u_posrelat(luaL_optinteger(L, 3, posi), len); - int n; - const char *se; - luaL_argcheck(L, posi >= 1, 2, "out of range"); - luaL_argcheck(L, pose <= (lua_Integer)len, 3, "out of range"); - if (posi > pose) return 0; /* empty interval; return no values */ - if (pose - posi >= INT_MAX) /* (lua_Integer -> int) overflow? */ - return luaL_error(L, "string slice too long"); - n = (int)(pose - posi) + 1; - luaL_checkstack(L, n, "string slice too long"); - n = 0; - se = s + pose; - for (s += posi - 1; s < se;) { - int code; - s = utf8_decode(s, &code); - if (s == NULL) - return luaL_error(L, "invalid UTF-8 code"); - lua_pushinteger(L, code); - n++; - } - return n; -} - - -static void pushutfchar (lua_State *L, int arg) { - lua_Integer code = luaL_checkinteger(L, arg); - luaL_argcheck(L, 0 <= code && code <= MAXUNICODE, arg, "value out of range"); - lua_pushfstring(L, "%U", (long)code); -} - - -/* -** utfchar(n1, n2, ...) -> char(n1)..char(n2)... -*/ -static int utfchar (lua_State *L) { - int n = lua_gettop(L); /* number of arguments */ - if (n == 1) /* optimize common case of single char */ - pushutfchar(L, 1); - else { - int i; - luaL_Buffer b; - luaL_buffinit(L, &b); - for (i = 1; i <= n; i++) { - pushutfchar(L, i); - luaL_addvalue(&b); - } - luaL_pushresult(&b); - } - return 1; -} - - -/* -** offset(s, n, [i]) -> index where n-th character counting from -** position 'i' starts; 0 means character at 'i'. -*/ -static int byteoffset (lua_State *L) { - size_t len; - const char *s = luaL_checklstring(L, 1, &len); - lua_Integer n = luaL_checkinteger(L, 2); - lua_Integer posi = (n >= 0) ? 1 : len + 1; - posi = u_posrelat(luaL_optinteger(L, 3, posi), len); - luaL_argcheck(L, 1 <= posi && --posi <= (lua_Integer)len, 3, - "position out of range"); - if (n == 0) { - /* find beginning of current byte sequence */ - while (posi > 0 && iscont(s + posi)) posi--; - } - else { - if (iscont(s + posi)) - return luaL_error(L, "initial position is a continuation byte"); - if (n < 0) { - while (n < 0 && posi > 0) { /* move back */ - do { /* find beginning of previous character */ - posi--; - } while (posi > 0 && iscont(s + posi)); - n++; - } - } - else { - n--; /* do not move for 1st character */ - while (n > 0 && posi < (lua_Integer)len) { - do { /* find beginning of next character */ - posi++; - } while (iscont(s + posi)); /* (cannot pass final '\0') */ - n--; - } - } - } - if (n == 0) /* did it find given character? */ - lua_pushinteger(L, posi + 1); - else /* no such character */ - lua_pushnil(L); - return 1; -} - - -static int iter_aux (lua_State *L) { - size_t len; - const char *s = luaL_checklstring(L, 1, &len); - lua_Integer n = lua_tointeger(L, 2) - 1; - if (n < 0) /* first iteration? */ - n = 0; /* start from here */ - else if (n < (lua_Integer)len) { - n++; /* skip current byte */ - while (iscont(s + n)) n++; /* and its continuations */ - } - if (n >= (lua_Integer)len) - return 0; /* no more codepoints */ - else { - int code; - const char *next = utf8_decode(s + n, &code); - if (next == NULL || iscont(next)) - return luaL_error(L, "invalid UTF-8 code"); - lua_pushinteger(L, n + 1); - lua_pushinteger(L, code); - return 2; - } -} - - -static int iter_codes (lua_State *L) { - luaL_checkstring(L, 1); - lua_pushcfunction(L, iter_aux); - lua_pushvalue(L, 1); - lua_pushinteger(L, 0); - return 3; -} - - -/* pattern to match a single UTF-8 character */ -#define UTF8PATT "[\0-\x7F\xC2-\xF4][\x80-\xBF]*" - - -static const luaL_Reg funcs[] = { - {"offset", byteoffset}, - {"codepoint", codepoint}, - {"char", utfchar}, - {"len", utflen}, - {"codes", iter_codes}, - /* placeholders */ - {"charpattern", NULL}, - {NULL, NULL} -}; - - -LUAMOD_API int luaopen_utf8 (lua_State *L) { - luaL_newlib(L, funcs); - lua_pushlstring(L, UTF8PATT, sizeof(UTF8PATT)/sizeof(char) - 1); - lua_setfield(L, -2, "charpattern"); - return 1; -} - diff --git a/lib/lua-5.3/src/lvm.c b/lib/lua-5.3/src/lvm.c deleted file mode 100644 index cc43d87..0000000 --- a/lib/lua-5.3/src/lvm.c +++ /dev/null @@ -1,1322 +0,0 @@ -/* -** $Id: lvm.c,v 2.268.1.1 2017/04/19 17:39:34 roberto Exp $ -** Lua virtual machine -** See Copyright Notice in lua.h -*/ - -#define lvm_c -#define LUA_CORE - -#include "lprefix.h" - -#include -#include -#include -#include -#include -#include - -#include "lua.h" - -#include "ldebug.h" -#include "ldo.h" -#include "lfunc.h" -#include "lgc.h" -#include "lobject.h" -#include "lopcodes.h" -#include "lstate.h" -#include "lstring.h" -#include "ltable.h" -#include "ltm.h" -#include "lvm.h" - - -/* limit for table tag-method chains (to avoid loops) */ -#define MAXTAGLOOP 2000 - - - -/* -** 'l_intfitsf' checks whether a given integer can be converted to a -** float without rounding. Used in comparisons. Left undefined if -** all integers fit in a float precisely. -*/ -#if !defined(l_intfitsf) - -/* number of bits in the mantissa of a float */ -#define NBM (l_mathlim(MANT_DIG)) - -/* -** Check whether some integers may not fit in a float, that is, whether -** (maxinteger >> NBM) > 0 (that implies (1 << NBM) <= maxinteger). -** (The shifts are done in parts to avoid shifting by more than the size -** of an integer. In a worst case, NBM == 113 for long double and -** sizeof(integer) == 32.) -*/ -#if ((((LUA_MAXINTEGER >> (NBM / 4)) >> (NBM / 4)) >> (NBM / 4)) \ - >> (NBM - (3 * (NBM / 4)))) > 0 - -#define l_intfitsf(i) \ - (-((lua_Integer)1 << NBM) <= (i) && (i) <= ((lua_Integer)1 << NBM)) - -#endif - -#endif - - - -/* -** Try to convert a value to a float. The float case is already handled -** by the macro 'tonumber'. -*/ -int luaV_tonumber_ (const TValue *obj, lua_Number *n) { - TValue v; - if (ttisinteger(obj)) { - *n = cast_num(ivalue(obj)); - return 1; - } - else if (cvt2num(obj) && /* string convertible to number? */ - luaO_str2num(svalue(obj), &v) == vslen(obj) + 1) { - *n = nvalue(&v); /* convert result of 'luaO_str2num' to a float */ - return 1; - } - else - return 0; /* conversion failed */ -} - - -/* -** try to convert a value to an integer, rounding according to 'mode': -** mode == 0: accepts only integral values -** mode == 1: takes the floor of the number -** mode == 2: takes the ceil of the number -*/ -int luaV_tointeger (const TValue *obj, lua_Integer *p, int mode) { - TValue v; - again: - if (ttisfloat(obj)) { - lua_Number n = fltvalue(obj); - lua_Number f = l_floor(n); - if (n != f) { /* not an integral value? */ - if (mode == 0) return 0; /* fails if mode demands integral value */ - else if (mode > 1) /* needs ceil? */ - f += 1; /* convert floor to ceil (remember: n != f) */ - } - return lua_numbertointeger(f, p); - } - else if (ttisinteger(obj)) { - *p = ivalue(obj); - return 1; - } - else if (cvt2num(obj) && - luaO_str2num(svalue(obj), &v) == vslen(obj) + 1) { - obj = &v; - goto again; /* convert result from 'luaO_str2num' to an integer */ - } - return 0; /* conversion failed */ -} - - -/* -** Try to convert a 'for' limit to an integer, preserving the -** semantics of the loop. -** (The following explanation assumes a non-negative step; it is valid -** for negative steps mutatis mutandis.) -** If the limit can be converted to an integer, rounding down, that is -** it. -** Otherwise, check whether the limit can be converted to a number. If -** the number is too large, it is OK to set the limit as LUA_MAXINTEGER, -** which means no limit. If the number is too negative, the loop -** should not run, because any initial integer value is larger than the -** limit. So, it sets the limit to LUA_MININTEGER. 'stopnow' corrects -** the extreme case when the initial value is LUA_MININTEGER, in which -** case the LUA_MININTEGER limit would still run the loop once. -*/ -static int forlimit (const TValue *obj, lua_Integer *p, lua_Integer step, - int *stopnow) { - *stopnow = 0; /* usually, let loops run */ - if (!luaV_tointeger(obj, p, (step < 0 ? 2 : 1))) { /* not fit in integer? */ - lua_Number n; /* try to convert to float */ - if (!tonumber(obj, &n)) /* cannot convert to float? */ - return 0; /* not a number */ - if (luai_numlt(0, n)) { /* if true, float is larger than max integer */ - *p = LUA_MAXINTEGER; - if (step < 0) *stopnow = 1; - } - else { /* float is smaller than min integer */ - *p = LUA_MININTEGER; - if (step >= 0) *stopnow = 1; - } - } - return 1; -} - - -/* -** Finish the table access 'val = t[key]'. -** if 'slot' is NULL, 't' is not a table; otherwise, 'slot' points to -** t[k] entry (which must be nil). -*/ -void luaV_finishget (lua_State *L, const TValue *t, TValue *key, StkId val, - const TValue *slot) { - int loop; /* counter to avoid infinite loops */ - const TValue *tm; /* metamethod */ - for (loop = 0; loop < MAXTAGLOOP; loop++) { - if (slot == NULL) { /* 't' is not a table? */ - lua_assert(!ttistable(t)); - tm = luaT_gettmbyobj(L, t, TM_INDEX); - if (ttisnil(tm)) - luaG_typeerror(L, t, "index"); /* no metamethod */ - /* else will try the metamethod */ - } - else { /* 't' is a table */ - lua_assert(ttisnil(slot)); - tm = fasttm(L, hvalue(t)->metatable, TM_INDEX); /* table's metamethod */ - if (tm == NULL) { /* no metamethod? */ - setnilvalue(val); /* result is nil */ - return; - } - /* else will try the metamethod */ - } - if (ttisfunction(tm)) { /* is metamethod a function? */ - luaT_callTM(L, tm, t, key, val, 1); /* call it */ - return; - } - t = tm; /* else try to access 'tm[key]' */ - if (luaV_fastget(L,t,key,slot,luaH_get)) { /* fast track? */ - setobj2s(L, val, slot); /* done */ - return; - } - /* else repeat (tail call 'luaV_finishget') */ - } - luaG_runerror(L, "'__index' chain too long; possible loop"); -} - - -/* -** Finish a table assignment 't[key] = val'. -** If 'slot' is NULL, 't' is not a table. Otherwise, 'slot' points -** to the entry 't[key]', or to 'luaO_nilobject' if there is no such -** entry. (The value at 'slot' must be nil, otherwise 'luaV_fastset' -** would have done the job.) -*/ -void luaV_finishset (lua_State *L, const TValue *t, TValue *key, - StkId val, const TValue *slot) { - int loop; /* counter to avoid infinite loops */ - for (loop = 0; loop < MAXTAGLOOP; loop++) { - const TValue *tm; /* '__newindex' metamethod */ - if (slot != NULL) { /* is 't' a table? */ - Table *h = hvalue(t); /* save 't' table */ - lua_assert(ttisnil(slot)); /* old value must be nil */ - tm = fasttm(L, h->metatable, TM_NEWINDEX); /* get metamethod */ - if (tm == NULL) { /* no metamethod? */ - if (slot == luaO_nilobject) /* no previous entry? */ - slot = luaH_newkey(L, h, key); /* create one */ - /* no metamethod and (now) there is an entry with given key */ - setobj2t(L, cast(TValue *, slot), val); /* set its new value */ - invalidateTMcache(h); - luaC_barrierback(L, h, val); - return; - } - /* else will try the metamethod */ - } - else { /* not a table; check metamethod */ - if (ttisnil(tm = luaT_gettmbyobj(L, t, TM_NEWINDEX))) - luaG_typeerror(L, t, "index"); - } - /* try the metamethod */ - if (ttisfunction(tm)) { - luaT_callTM(L, tm, t, key, val, 0); - return; - } - t = tm; /* else repeat assignment over 'tm' */ - if (luaV_fastset(L, t, key, slot, luaH_get, val)) - return; /* done */ - /* else loop */ - } - luaG_runerror(L, "'__newindex' chain too long; possible loop"); -} - - -/* -** Compare two strings 'ls' x 'rs', returning an integer smaller-equal- -** -larger than zero if 'ls' is smaller-equal-larger than 'rs'. -** The code is a little tricky because it allows '\0' in the strings -** and it uses 'strcoll' (to respect locales) for each segments -** of the strings. -*/ -static int l_strcmp (const TString *ls, const TString *rs) { - const char *l = getstr(ls); - size_t ll = tsslen(ls); - const char *r = getstr(rs); - size_t lr = tsslen(rs); - for (;;) { /* for each segment */ - int temp = strcoll(l, r); - if (temp != 0) /* not equal? */ - return temp; /* done */ - else { /* strings are equal up to a '\0' */ - size_t len = strlen(l); /* index of first '\0' in both strings */ - if (len == lr) /* 'rs' is finished? */ - return (len == ll) ? 0 : 1; /* check 'ls' */ - else if (len == ll) /* 'ls' is finished? */ - return -1; /* 'ls' is smaller than 'rs' ('rs' is not finished) */ - /* both strings longer than 'len'; go on comparing after the '\0' */ - len++; - l += len; ll -= len; r += len; lr -= len; - } - } -} - - -/* -** Check whether integer 'i' is less than float 'f'. If 'i' has an -** exact representation as a float ('l_intfitsf'), compare numbers as -** floats. Otherwise, if 'f' is outside the range for integers, result -** is trivial. Otherwise, compare them as integers. (When 'i' has no -** float representation, either 'f' is "far away" from 'i' or 'f' has -** no precision left for a fractional part; either way, how 'f' is -** truncated is irrelevant.) When 'f' is NaN, comparisons must result -** in false. -*/ -static int LTintfloat (lua_Integer i, lua_Number f) { -#if defined(l_intfitsf) - if (!l_intfitsf(i)) { - if (f >= -cast_num(LUA_MININTEGER)) /* -minint == maxint + 1 */ - return 1; /* f >= maxint + 1 > i */ - else if (f > cast_num(LUA_MININTEGER)) /* minint < f <= maxint ? */ - return (i < cast(lua_Integer, f)); /* compare them as integers */ - else /* f <= minint <= i (or 'f' is NaN) --> not(i < f) */ - return 0; - } -#endif - return luai_numlt(cast_num(i), f); /* compare them as floats */ -} - - -/* -** Check whether integer 'i' is less than or equal to float 'f'. -** See comments on previous function. -*/ -static int LEintfloat (lua_Integer i, lua_Number f) { -#if defined(l_intfitsf) - if (!l_intfitsf(i)) { - if (f >= -cast_num(LUA_MININTEGER)) /* -minint == maxint + 1 */ - return 1; /* f >= maxint + 1 > i */ - else if (f >= cast_num(LUA_MININTEGER)) /* minint <= f <= maxint ? */ - return (i <= cast(lua_Integer, f)); /* compare them as integers */ - else /* f < minint <= i (or 'f' is NaN) --> not(i <= f) */ - return 0; - } -#endif - return luai_numle(cast_num(i), f); /* compare them as floats */ -} - - -/* -** Return 'l < r', for numbers. -*/ -static int LTnum (const TValue *l, const TValue *r) { - if (ttisinteger(l)) { - lua_Integer li = ivalue(l); - if (ttisinteger(r)) - return li < ivalue(r); /* both are integers */ - else /* 'l' is int and 'r' is float */ - return LTintfloat(li, fltvalue(r)); /* l < r ? */ - } - else { - lua_Number lf = fltvalue(l); /* 'l' must be float */ - if (ttisfloat(r)) - return luai_numlt(lf, fltvalue(r)); /* both are float */ - else if (luai_numisnan(lf)) /* 'r' is int and 'l' is float */ - return 0; /* NaN < i is always false */ - else /* without NaN, (l < r) <--> not(r <= l) */ - return !LEintfloat(ivalue(r), lf); /* not (r <= l) ? */ - } -} - - -/* -** Return 'l <= r', for numbers. -*/ -static int LEnum (const TValue *l, const TValue *r) { - if (ttisinteger(l)) { - lua_Integer li = ivalue(l); - if (ttisinteger(r)) - return li <= ivalue(r); /* both are integers */ - else /* 'l' is int and 'r' is float */ - return LEintfloat(li, fltvalue(r)); /* l <= r ? */ - } - else { - lua_Number lf = fltvalue(l); /* 'l' must be float */ - if (ttisfloat(r)) - return luai_numle(lf, fltvalue(r)); /* both are float */ - else if (luai_numisnan(lf)) /* 'r' is int and 'l' is float */ - return 0; /* NaN <= i is always false */ - else /* without NaN, (l <= r) <--> not(r < l) */ - return !LTintfloat(ivalue(r), lf); /* not (r < l) ? */ - } -} - - -/* -** Main operation less than; return 'l < r'. -*/ -int luaV_lessthan (lua_State *L, const TValue *l, const TValue *r) { - int res; - if (ttisnumber(l) && ttisnumber(r)) /* both operands are numbers? */ - return LTnum(l, r); - else if (ttisstring(l) && ttisstring(r)) /* both are strings? */ - return l_strcmp(tsvalue(l), tsvalue(r)) < 0; - else if ((res = luaT_callorderTM(L, l, r, TM_LT)) < 0) /* no metamethod? */ - luaG_ordererror(L, l, r); /* error */ - return res; -} - - -/* -** Main operation less than or equal to; return 'l <= r'. If it needs -** a metamethod and there is no '__le', try '__lt', based on -** l <= r iff !(r < l) (assuming a total order). If the metamethod -** yields during this substitution, the continuation has to know -** about it (to negate the result of r= 0) /* try 'le' */ - return res; - else { /* try 'lt': */ - L->ci->callstatus |= CIST_LEQ; /* mark it is doing 'lt' for 'le' */ - res = luaT_callorderTM(L, r, l, TM_LT); - L->ci->callstatus ^= CIST_LEQ; /* clear mark */ - if (res < 0) - luaG_ordererror(L, l, r); - return !res; /* result is negated */ - } -} - - -/* -** Main operation for equality of Lua values; return 't1 == t2'. -** L == NULL means raw equality (no metamethods) -*/ -int luaV_equalobj (lua_State *L, const TValue *t1, const TValue *t2) { - const TValue *tm; - if (ttype(t1) != ttype(t2)) { /* not the same variant? */ - if (ttnov(t1) != ttnov(t2) || ttnov(t1) != LUA_TNUMBER) - return 0; /* only numbers can be equal with different variants */ - else { /* two numbers with different variants */ - lua_Integer i1, i2; /* compare them as integers */ - return (tointeger(t1, &i1) && tointeger(t2, &i2) && i1 == i2); - } - } - /* values have same type and same variant */ - switch (ttype(t1)) { - case LUA_TNIL: return 1; - case LUA_TNUMINT: return (ivalue(t1) == ivalue(t2)); - case LUA_TNUMFLT: return luai_numeq(fltvalue(t1), fltvalue(t2)); - case LUA_TBOOLEAN: return bvalue(t1) == bvalue(t2); /* true must be 1 !! */ - case LUA_TLIGHTUSERDATA: return pvalue(t1) == pvalue(t2); - case LUA_TLCF: return fvalue(t1) == fvalue(t2); - case LUA_TSHRSTR: return eqshrstr(tsvalue(t1), tsvalue(t2)); - case LUA_TLNGSTR: return luaS_eqlngstr(tsvalue(t1), tsvalue(t2)); - case LUA_TUSERDATA: { - if (uvalue(t1) == uvalue(t2)) return 1; - else if (L == NULL) return 0; - tm = fasttm(L, uvalue(t1)->metatable, TM_EQ); - if (tm == NULL) - tm = fasttm(L, uvalue(t2)->metatable, TM_EQ); - break; /* will try TM */ - } - case LUA_TTABLE: { - if (hvalue(t1) == hvalue(t2)) return 1; - else if (L == NULL) return 0; - tm = fasttm(L, hvalue(t1)->metatable, TM_EQ); - if (tm == NULL) - tm = fasttm(L, hvalue(t2)->metatable, TM_EQ); - break; /* will try TM */ - } - default: - return gcvalue(t1) == gcvalue(t2); - } - if (tm == NULL) /* no TM? */ - return 0; /* objects are different */ - luaT_callTM(L, tm, t1, t2, L->top, 1); /* call TM */ - return !l_isfalse(L->top); -} - - -/* macro used by 'luaV_concat' to ensure that element at 'o' is a string */ -#define tostring(L,o) \ - (ttisstring(o) || (cvt2str(o) && (luaO_tostring(L, o), 1))) - -#define isemptystr(o) (ttisshrstring(o) && tsvalue(o)->shrlen == 0) - -/* copy strings in stack from top - n up to top - 1 to buffer */ -static void copy2buff (StkId top, int n, char *buff) { - size_t tl = 0; /* size already copied */ - do { - size_t l = vslen(top - n); /* length of string being copied */ - memcpy(buff + tl, svalue(top - n), l * sizeof(char)); - tl += l; - } while (--n > 0); -} - - -/* -** Main operation for concatenation: concat 'total' values in the stack, -** from 'L->top - total' up to 'L->top - 1'. -*/ -void luaV_concat (lua_State *L, int total) { - lua_assert(total >= 2); - do { - StkId top = L->top; - int n = 2; /* number of elements handled in this pass (at least 2) */ - if (!(ttisstring(top-2) || cvt2str(top-2)) || !tostring(L, top-1)) - luaT_trybinTM(L, top-2, top-1, top-2, TM_CONCAT); - else if (isemptystr(top - 1)) /* second operand is empty? */ - cast_void(tostring(L, top - 2)); /* result is first operand */ - else if (isemptystr(top - 2)) { /* first operand is an empty string? */ - setobjs2s(L, top - 2, top - 1); /* result is second op. */ - } - else { - /* at least two non-empty string values; get as many as possible */ - size_t tl = vslen(top - 1); - TString *ts; - /* collect total length and number of strings */ - for (n = 1; n < total && tostring(L, top - n - 1); n++) { - size_t l = vslen(top - n - 1); - if (l >= (MAX_SIZE/sizeof(char)) - tl) - luaG_runerror(L, "string length overflow"); - tl += l; - } - if (tl <= LUAI_MAXSHORTLEN) { /* is result a short string? */ - char buff[LUAI_MAXSHORTLEN]; - copy2buff(top, n, buff); /* copy strings to buffer */ - ts = luaS_newlstr(L, buff, tl); - } - else { /* long string; copy strings directly to final result */ - ts = luaS_createlngstrobj(L, tl); - copy2buff(top, n, getstr(ts)); - } - setsvalue2s(L, top - n, ts); /* create result */ - } - total -= n-1; /* got 'n' strings to create 1 new */ - L->top -= n-1; /* popped 'n' strings and pushed one */ - } while (total > 1); /* repeat until only 1 result left */ -} - - -/* -** Main operation 'ra' = #rb'. -*/ -void luaV_objlen (lua_State *L, StkId ra, const TValue *rb) { - const TValue *tm; - switch (ttype(rb)) { - case LUA_TTABLE: { - Table *h = hvalue(rb); - tm = fasttm(L, h->metatable, TM_LEN); - if (tm) break; /* metamethod? break switch to call it */ - setivalue(ra, luaH_getn(h)); /* else primitive len */ - return; - } - case LUA_TSHRSTR: { - setivalue(ra, tsvalue(rb)->shrlen); - return; - } - case LUA_TLNGSTR: { - setivalue(ra, tsvalue(rb)->u.lnglen); - return; - } - default: { /* try metamethod */ - tm = luaT_gettmbyobj(L, rb, TM_LEN); - if (ttisnil(tm)) /* no metamethod? */ - luaG_typeerror(L, rb, "get length of"); - break; - } - } - luaT_callTM(L, tm, rb, rb, ra, 1); -} - - -/* -** Integer division; return 'm // n', that is, floor(m/n). -** C division truncates its result (rounds towards zero). -** 'floor(q) == trunc(q)' when 'q >= 0' or when 'q' is integer, -** otherwise 'floor(q) == trunc(q) - 1'. -*/ -lua_Integer luaV_div (lua_State *L, lua_Integer m, lua_Integer n) { - if (l_castS2U(n) + 1u <= 1u) { /* special cases: -1 or 0 */ - if (n == 0) - luaG_runerror(L, "attempt to divide by zero"); - return intop(-, 0, m); /* n==-1; avoid overflow with 0x80000...//-1 */ - } - else { - lua_Integer q = m / n; /* perform C division */ - if ((m ^ n) < 0 && m % n != 0) /* 'm/n' would be negative non-integer? */ - q -= 1; /* correct result for different rounding */ - return q; - } -} - - -/* -** Integer modulus; return 'm % n'. (Assume that C '%' with -** negative operands follows C99 behavior. See previous comment -** about luaV_div.) -*/ -lua_Integer luaV_mod (lua_State *L, lua_Integer m, lua_Integer n) { - if (l_castS2U(n) + 1u <= 1u) { /* special cases: -1 or 0 */ - if (n == 0) - luaG_runerror(L, "attempt to perform 'n%%0'"); - return 0; /* m % -1 == 0; avoid overflow with 0x80000...%-1 */ - } - else { - lua_Integer r = m % n; - if (r != 0 && (m ^ n) < 0) /* 'm/n' would be non-integer negative? */ - r += n; /* correct result for different rounding */ - return r; - } -} - - -/* number of bits in an integer */ -#define NBITS cast_int(sizeof(lua_Integer) * CHAR_BIT) - -/* -** Shift left operation. (Shift right just negates 'y'.) -*/ -lua_Integer luaV_shiftl (lua_Integer x, lua_Integer y) { - if (y < 0) { /* shift right? */ - if (y <= -NBITS) return 0; - else return intop(>>, x, -y); - } - else { /* shift left */ - if (y >= NBITS) return 0; - else return intop(<<, x, y); - } -} - - -/* -** check whether cached closure in prototype 'p' may be reused, that is, -** whether there is a cached closure with the same upvalues needed by -** new closure to be created. -*/ -static LClosure *getcached (Proto *p, UpVal **encup, StkId base) { - LClosure *c = p->cache; - if (c != NULL) { /* is there a cached closure? */ - int nup = p->sizeupvalues; - Upvaldesc *uv = p->upvalues; - int i; - for (i = 0; i < nup; i++) { /* check whether it has right upvalues */ - TValue *v = uv[i].instack ? base + uv[i].idx : encup[uv[i].idx]->v; - if (c->upvals[i]->v != v) - return NULL; /* wrong upvalue; cannot reuse closure */ - } - } - return c; /* return cached closure (or NULL if no cached closure) */ -} - - -/* -** create a new Lua closure, push it in the stack, and initialize -** its upvalues. Note that the closure is not cached if prototype is -** already black (which means that 'cache' was already cleared by the -** GC). -*/ -static void pushclosure (lua_State *L, Proto *p, UpVal **encup, StkId base, - StkId ra) { - int nup = p->sizeupvalues; - Upvaldesc *uv = p->upvalues; - int i; - LClosure *ncl = luaF_newLclosure(L, nup); - ncl->p = p; - setclLvalue(L, ra, ncl); /* anchor new closure in stack */ - for (i = 0; i < nup; i++) { /* fill in its upvalues */ - if (uv[i].instack) /* upvalue refers to local variable? */ - ncl->upvals[i] = luaF_findupval(L, base + uv[i].idx); - else /* get upvalue from enclosing function */ - ncl->upvals[i] = encup[uv[i].idx]; - ncl->upvals[i]->refcount++; - /* new closure is white, so we do not need a barrier here */ - } - if (!isblack(p)) /* cache will not break GC invariant? */ - p->cache = ncl; /* save it on cache for reuse */ -} - - -/* -** finish execution of an opcode interrupted by an yield -*/ -void luaV_finishOp (lua_State *L) { - CallInfo *ci = L->ci; - StkId base = ci->u.l.base; - Instruction inst = *(ci->u.l.savedpc - 1); /* interrupted instruction */ - OpCode op = GET_OPCODE(inst); - switch (op) { /* finish its execution */ - case OP_ADD: case OP_SUB: case OP_MUL: case OP_DIV: case OP_IDIV: - case OP_BAND: case OP_BOR: case OP_BXOR: case OP_SHL: case OP_SHR: - case OP_MOD: case OP_POW: - case OP_UNM: case OP_BNOT: case OP_LEN: - case OP_GETTABUP: case OP_GETTABLE: case OP_SELF: { - setobjs2s(L, base + GETARG_A(inst), --L->top); - break; - } - case OP_LE: case OP_LT: case OP_EQ: { - int res = !l_isfalse(L->top - 1); - L->top--; - if (ci->callstatus & CIST_LEQ) { /* "<=" using "<" instead? */ - lua_assert(op == OP_LE); - ci->callstatus ^= CIST_LEQ; /* clear mark */ - res = !res; /* negate result */ - } - lua_assert(GET_OPCODE(*ci->u.l.savedpc) == OP_JMP); - if (res != GETARG_A(inst)) /* condition failed? */ - ci->u.l.savedpc++; /* skip jump instruction */ - break; - } - case OP_CONCAT: { - StkId top = L->top - 1; /* top when 'luaT_trybinTM' was called */ - int b = GETARG_B(inst); /* first element to concatenate */ - int total = cast_int(top - 1 - (base + b)); /* yet to concatenate */ - setobj2s(L, top - 2, top); /* put TM result in proper position */ - if (total > 1) { /* are there elements to concat? */ - L->top = top - 1; /* top is one after last element (at top-2) */ - luaV_concat(L, total); /* concat them (may yield again) */ - } - /* move final result to final position */ - setobj2s(L, ci->u.l.base + GETARG_A(inst), L->top - 1); - L->top = ci->top; /* restore top */ - break; - } - case OP_TFORCALL: { - lua_assert(GET_OPCODE(*ci->u.l.savedpc) == OP_TFORLOOP); - L->top = ci->top; /* correct top */ - break; - } - case OP_CALL: { - if (GETARG_C(inst) - 1 >= 0) /* nresults >= 0? */ - L->top = ci->top; /* adjust results */ - break; - } - case OP_TAILCALL: case OP_SETTABUP: case OP_SETTABLE: - break; - default: lua_assert(0); - } -} - - - - -/* -** {================================================================== -** Function 'luaV_execute': main interpreter loop -** =================================================================== -*/ - - -/* -** some macros for common tasks in 'luaV_execute' -*/ - - -#define RA(i) (base+GETARG_A(i)) -#define RB(i) check_exp(getBMode(GET_OPCODE(i)) == OpArgR, base+GETARG_B(i)) -#define RC(i) check_exp(getCMode(GET_OPCODE(i)) == OpArgR, base+GETARG_C(i)) -#define RKB(i) check_exp(getBMode(GET_OPCODE(i)) == OpArgK, \ - ISK(GETARG_B(i)) ? k+INDEXK(GETARG_B(i)) : base+GETARG_B(i)) -#define RKC(i) check_exp(getCMode(GET_OPCODE(i)) == OpArgK, \ - ISK(GETARG_C(i)) ? k+INDEXK(GETARG_C(i)) : base+GETARG_C(i)) - - -/* execute a jump instruction */ -#define dojump(ci,i,e) \ - { int a = GETARG_A(i); \ - if (a != 0) luaF_close(L, ci->u.l.base + a - 1); \ - ci->u.l.savedpc += GETARG_sBx(i) + e; } - -/* for test instructions, execute the jump instruction that follows it */ -#define donextjump(ci) { i = *ci->u.l.savedpc; dojump(ci, i, 1); } - - -#define Protect(x) { {x;}; base = ci->u.l.base; } - -#define checkGC(L,c) \ - { luaC_condGC(L, L->top = (c), /* limit of live values */ \ - Protect(L->top = ci->top)); /* restore top */ \ - luai_threadyield(L); } - - -/* fetch an instruction and prepare its execution */ -#define vmfetch() { \ - i = *(ci->u.l.savedpc++); \ - if (L->hookmask & (LUA_MASKLINE | LUA_MASKCOUNT)) \ - Protect(luaG_traceexec(L)); \ - ra = RA(i); /* WARNING: any stack reallocation invalidates 'ra' */ \ - lua_assert(base == ci->u.l.base); \ - lua_assert(base <= L->top && L->top < L->stack + L->stacksize); \ -} - -#define vmdispatch(o) switch(o) -#define vmcase(l) case l: -#define vmbreak break - - -/* -** copy of 'luaV_gettable', but protecting the call to potential -** metamethod (which can reallocate the stack) -*/ -#define gettableProtected(L,t,k,v) { const TValue *slot; \ - if (luaV_fastget(L,t,k,slot,luaH_get)) { setobj2s(L, v, slot); } \ - else Protect(luaV_finishget(L,t,k,v,slot)); } - - -/* same for 'luaV_settable' */ -#define settableProtected(L,t,k,v) { const TValue *slot; \ - if (!luaV_fastset(L,t,k,slot,luaH_get,v)) \ - Protect(luaV_finishset(L,t,k,v,slot)); } - - - -void luaV_execute (lua_State *L) { - CallInfo *ci = L->ci; - LClosure *cl; - TValue *k; - StkId base; - ci->callstatus |= CIST_FRESH; /* fresh invocation of 'luaV_execute" */ - newframe: /* reentry point when frame changes (call/return) */ - lua_assert(ci == L->ci); - cl = clLvalue(ci->func); /* local reference to function's closure */ - k = cl->p->k; /* local reference to function's constant table */ - base = ci->u.l.base; /* local copy of function's base */ - /* main loop of interpreter */ - for (;;) { - Instruction i; - StkId ra; - vmfetch(); - vmdispatch (GET_OPCODE(i)) { - vmcase(OP_MOVE) { - setobjs2s(L, ra, RB(i)); - vmbreak; - } - vmcase(OP_LOADK) { - TValue *rb = k + GETARG_Bx(i); - setobj2s(L, ra, rb); - vmbreak; - } - vmcase(OP_LOADKX) { - TValue *rb; - lua_assert(GET_OPCODE(*ci->u.l.savedpc) == OP_EXTRAARG); - rb = k + GETARG_Ax(*ci->u.l.savedpc++); - setobj2s(L, ra, rb); - vmbreak; - } - vmcase(OP_LOADBOOL) { - setbvalue(ra, GETARG_B(i)); - if (GETARG_C(i)) ci->u.l.savedpc++; /* skip next instruction (if C) */ - vmbreak; - } - vmcase(OP_LOADNIL) { - int b = GETARG_B(i); - do { - setnilvalue(ra++); - } while (b--); - vmbreak; - } - vmcase(OP_GETUPVAL) { - int b = GETARG_B(i); - setobj2s(L, ra, cl->upvals[b]->v); - vmbreak; - } - vmcase(OP_GETTABUP) { - TValue *upval = cl->upvals[GETARG_B(i)]->v; - TValue *rc = RKC(i); - gettableProtected(L, upval, rc, ra); - vmbreak; - } - vmcase(OP_GETTABLE) { - StkId rb = RB(i); - TValue *rc = RKC(i); - gettableProtected(L, rb, rc, ra); - vmbreak; - } - vmcase(OP_SETTABUP) { - TValue *upval = cl->upvals[GETARG_A(i)]->v; - TValue *rb = RKB(i); - TValue *rc = RKC(i); - settableProtected(L, upval, rb, rc); - vmbreak; - } - vmcase(OP_SETUPVAL) { - UpVal *uv = cl->upvals[GETARG_B(i)]; - setobj(L, uv->v, ra); - luaC_upvalbarrier(L, uv); - vmbreak; - } - vmcase(OP_SETTABLE) { - TValue *rb = RKB(i); - TValue *rc = RKC(i); - settableProtected(L, ra, rb, rc); - vmbreak; - } - vmcase(OP_NEWTABLE) { - int b = GETARG_B(i); - int c = GETARG_C(i); - Table *t = luaH_new(L); - sethvalue(L, ra, t); - if (b != 0 || c != 0) - luaH_resize(L, t, luaO_fb2int(b), luaO_fb2int(c)); - checkGC(L, ra + 1); - vmbreak; - } - vmcase(OP_SELF) { - const TValue *aux; - StkId rb = RB(i); - TValue *rc = RKC(i); - TString *key = tsvalue(rc); /* key must be a string */ - setobjs2s(L, ra + 1, rb); - if (luaV_fastget(L, rb, key, aux, luaH_getstr)) { - setobj2s(L, ra, aux); - } - else Protect(luaV_finishget(L, rb, rc, ra, aux)); - vmbreak; - } - vmcase(OP_ADD) { - TValue *rb = RKB(i); - TValue *rc = RKC(i); - lua_Number nb; lua_Number nc; - if (ttisinteger(rb) && ttisinteger(rc)) { - lua_Integer ib = ivalue(rb); lua_Integer ic = ivalue(rc); - setivalue(ra, intop(+, ib, ic)); - } - else if (tonumber(rb, &nb) && tonumber(rc, &nc)) { - setfltvalue(ra, luai_numadd(L, nb, nc)); - } - else { Protect(luaT_trybinTM(L, rb, rc, ra, TM_ADD)); } - vmbreak; - } - vmcase(OP_SUB) { - TValue *rb = RKB(i); - TValue *rc = RKC(i); - lua_Number nb; lua_Number nc; - if (ttisinteger(rb) && ttisinteger(rc)) { - lua_Integer ib = ivalue(rb); lua_Integer ic = ivalue(rc); - setivalue(ra, intop(-, ib, ic)); - } - else if (tonumber(rb, &nb) && tonumber(rc, &nc)) { - setfltvalue(ra, luai_numsub(L, nb, nc)); - } - else { Protect(luaT_trybinTM(L, rb, rc, ra, TM_SUB)); } - vmbreak; - } - vmcase(OP_MUL) { - TValue *rb = RKB(i); - TValue *rc = RKC(i); - lua_Number nb; lua_Number nc; - if (ttisinteger(rb) && ttisinteger(rc)) { - lua_Integer ib = ivalue(rb); lua_Integer ic = ivalue(rc); - setivalue(ra, intop(*, ib, ic)); - } - else if (tonumber(rb, &nb) && tonumber(rc, &nc)) { - setfltvalue(ra, luai_nummul(L, nb, nc)); - } - else { Protect(luaT_trybinTM(L, rb, rc, ra, TM_MUL)); } - vmbreak; - } - vmcase(OP_DIV) { /* float division (always with floats) */ - TValue *rb = RKB(i); - TValue *rc = RKC(i); - lua_Number nb; lua_Number nc; - if (tonumber(rb, &nb) && tonumber(rc, &nc)) { - setfltvalue(ra, luai_numdiv(L, nb, nc)); - } - else { Protect(luaT_trybinTM(L, rb, rc, ra, TM_DIV)); } - vmbreak; - } - vmcase(OP_BAND) { - TValue *rb = RKB(i); - TValue *rc = RKC(i); - lua_Integer ib; lua_Integer ic; - if (tointeger(rb, &ib) && tointeger(rc, &ic)) { - setivalue(ra, intop(&, ib, ic)); - } - else { Protect(luaT_trybinTM(L, rb, rc, ra, TM_BAND)); } - vmbreak; - } - vmcase(OP_BOR) { - TValue *rb = RKB(i); - TValue *rc = RKC(i); - lua_Integer ib; lua_Integer ic; - if (tointeger(rb, &ib) && tointeger(rc, &ic)) { - setivalue(ra, intop(|, ib, ic)); - } - else { Protect(luaT_trybinTM(L, rb, rc, ra, TM_BOR)); } - vmbreak; - } - vmcase(OP_BXOR) { - TValue *rb = RKB(i); - TValue *rc = RKC(i); - lua_Integer ib; lua_Integer ic; - if (tointeger(rb, &ib) && tointeger(rc, &ic)) { - setivalue(ra, intop(^, ib, ic)); - } - else { Protect(luaT_trybinTM(L, rb, rc, ra, TM_BXOR)); } - vmbreak; - } - vmcase(OP_SHL) { - TValue *rb = RKB(i); - TValue *rc = RKC(i); - lua_Integer ib; lua_Integer ic; - if (tointeger(rb, &ib) && tointeger(rc, &ic)) { - setivalue(ra, luaV_shiftl(ib, ic)); - } - else { Protect(luaT_trybinTM(L, rb, rc, ra, TM_SHL)); } - vmbreak; - } - vmcase(OP_SHR) { - TValue *rb = RKB(i); - TValue *rc = RKC(i); - lua_Integer ib; lua_Integer ic; - if (tointeger(rb, &ib) && tointeger(rc, &ic)) { - setivalue(ra, luaV_shiftl(ib, -ic)); - } - else { Protect(luaT_trybinTM(L, rb, rc, ra, TM_SHR)); } - vmbreak; - } - vmcase(OP_MOD) { - TValue *rb = RKB(i); - TValue *rc = RKC(i); - lua_Number nb; lua_Number nc; - if (ttisinteger(rb) && ttisinteger(rc)) { - lua_Integer ib = ivalue(rb); lua_Integer ic = ivalue(rc); - setivalue(ra, luaV_mod(L, ib, ic)); - } - else if (tonumber(rb, &nb) && tonumber(rc, &nc)) { - lua_Number m; - luai_nummod(L, nb, nc, m); - setfltvalue(ra, m); - } - else { Protect(luaT_trybinTM(L, rb, rc, ra, TM_MOD)); } - vmbreak; - } - vmcase(OP_IDIV) { /* floor division */ - TValue *rb = RKB(i); - TValue *rc = RKC(i); - lua_Number nb; lua_Number nc; - if (ttisinteger(rb) && ttisinteger(rc)) { - lua_Integer ib = ivalue(rb); lua_Integer ic = ivalue(rc); - setivalue(ra, luaV_div(L, ib, ic)); - } - else if (tonumber(rb, &nb) && tonumber(rc, &nc)) { - setfltvalue(ra, luai_numidiv(L, nb, nc)); - } - else { Protect(luaT_trybinTM(L, rb, rc, ra, TM_IDIV)); } - vmbreak; - } - vmcase(OP_POW) { - TValue *rb = RKB(i); - TValue *rc = RKC(i); - lua_Number nb; lua_Number nc; - if (tonumber(rb, &nb) && tonumber(rc, &nc)) { - setfltvalue(ra, luai_numpow(L, nb, nc)); - } - else { Protect(luaT_trybinTM(L, rb, rc, ra, TM_POW)); } - vmbreak; - } - vmcase(OP_UNM) { - TValue *rb = RB(i); - lua_Number nb; - if (ttisinteger(rb)) { - lua_Integer ib = ivalue(rb); - setivalue(ra, intop(-, 0, ib)); - } - else if (tonumber(rb, &nb)) { - setfltvalue(ra, luai_numunm(L, nb)); - } - else { - Protect(luaT_trybinTM(L, rb, rb, ra, TM_UNM)); - } - vmbreak; - } - vmcase(OP_BNOT) { - TValue *rb = RB(i); - lua_Integer ib; - if (tointeger(rb, &ib)) { - setivalue(ra, intop(^, ~l_castS2U(0), ib)); - } - else { - Protect(luaT_trybinTM(L, rb, rb, ra, TM_BNOT)); - } - vmbreak; - } - vmcase(OP_NOT) { - TValue *rb = RB(i); - int res = l_isfalse(rb); /* next assignment may change this value */ - setbvalue(ra, res); - vmbreak; - } - vmcase(OP_LEN) { - Protect(luaV_objlen(L, ra, RB(i))); - vmbreak; - } - vmcase(OP_CONCAT) { - int b = GETARG_B(i); - int c = GETARG_C(i); - StkId rb; - L->top = base + c + 1; /* mark the end of concat operands */ - Protect(luaV_concat(L, c - b + 1)); - ra = RA(i); /* 'luaV_concat' may invoke TMs and move the stack */ - rb = base + b; - setobjs2s(L, ra, rb); - checkGC(L, (ra >= rb ? ra + 1 : rb)); - L->top = ci->top; /* restore top */ - vmbreak; - } - vmcase(OP_JMP) { - dojump(ci, i, 0); - vmbreak; - } - vmcase(OP_EQ) { - TValue *rb = RKB(i); - TValue *rc = RKC(i); - Protect( - if (luaV_equalobj(L, rb, rc) != GETARG_A(i)) - ci->u.l.savedpc++; - else - donextjump(ci); - ) - vmbreak; - } - vmcase(OP_LT) { - Protect( - if (luaV_lessthan(L, RKB(i), RKC(i)) != GETARG_A(i)) - ci->u.l.savedpc++; - else - donextjump(ci); - ) - vmbreak; - } - vmcase(OP_LE) { - Protect( - if (luaV_lessequal(L, RKB(i), RKC(i)) != GETARG_A(i)) - ci->u.l.savedpc++; - else - donextjump(ci); - ) - vmbreak; - } - vmcase(OP_TEST) { - if (GETARG_C(i) ? l_isfalse(ra) : !l_isfalse(ra)) - ci->u.l.savedpc++; - else - donextjump(ci); - vmbreak; - } - vmcase(OP_TESTSET) { - TValue *rb = RB(i); - if (GETARG_C(i) ? l_isfalse(rb) : !l_isfalse(rb)) - ci->u.l.savedpc++; - else { - setobjs2s(L, ra, rb); - donextjump(ci); - } - vmbreak; - } - vmcase(OP_CALL) { - int b = GETARG_B(i); - int nresults = GETARG_C(i) - 1; - if (b != 0) L->top = ra+b; /* else previous instruction set top */ - if (luaD_precall(L, ra, nresults)) { /* C function? */ - if (nresults >= 0) - L->top = ci->top; /* adjust results */ - Protect((void)0); /* update 'base' */ - } - else { /* Lua function */ - ci = L->ci; - goto newframe; /* restart luaV_execute over new Lua function */ - } - vmbreak; - } - vmcase(OP_TAILCALL) { - int b = GETARG_B(i); - if (b != 0) L->top = ra+b; /* else previous instruction set top */ - lua_assert(GETARG_C(i) - 1 == LUA_MULTRET); - if (luaD_precall(L, ra, LUA_MULTRET)) { /* C function? */ - Protect((void)0); /* update 'base' */ - } - else { - /* tail call: put called frame (n) in place of caller one (o) */ - CallInfo *nci = L->ci; /* called frame */ - CallInfo *oci = nci->previous; /* caller frame */ - StkId nfunc = nci->func; /* called function */ - StkId ofunc = oci->func; /* caller function */ - /* last stack slot filled by 'precall' */ - StkId lim = nci->u.l.base + getproto(nfunc)->numparams; - int aux; - /* close all upvalues from previous call */ - if (cl->p->sizep > 0) luaF_close(L, oci->u.l.base); - /* move new frame into old one */ - for (aux = 0; nfunc + aux < lim; aux++) - setobjs2s(L, ofunc + aux, nfunc + aux); - oci->u.l.base = ofunc + (nci->u.l.base - nfunc); /* correct base */ - oci->top = L->top = ofunc + (L->top - nfunc); /* correct top */ - oci->u.l.savedpc = nci->u.l.savedpc; - oci->callstatus |= CIST_TAIL; /* function was tail called */ - ci = L->ci = oci; /* remove new frame */ - lua_assert(L->top == oci->u.l.base + getproto(ofunc)->maxstacksize); - goto newframe; /* restart luaV_execute over new Lua function */ - } - vmbreak; - } - vmcase(OP_RETURN) { - int b = GETARG_B(i); - if (cl->p->sizep > 0) luaF_close(L, base); - b = luaD_poscall(L, ci, ra, (b != 0 ? b - 1 : cast_int(L->top - ra))); - if (ci->callstatus & CIST_FRESH) /* local 'ci' still from callee */ - return; /* external invocation: return */ - else { /* invocation via reentry: continue execution */ - ci = L->ci; - if (b) L->top = ci->top; - lua_assert(isLua(ci)); - lua_assert(GET_OPCODE(*((ci)->u.l.savedpc - 1)) == OP_CALL); - goto newframe; /* restart luaV_execute over new Lua function */ - } - } - vmcase(OP_FORLOOP) { - if (ttisinteger(ra)) { /* integer loop? */ - lua_Integer step = ivalue(ra + 2); - lua_Integer idx = intop(+, ivalue(ra), step); /* increment index */ - lua_Integer limit = ivalue(ra + 1); - if ((0 < step) ? (idx <= limit) : (limit <= idx)) { - ci->u.l.savedpc += GETARG_sBx(i); /* jump back */ - chgivalue(ra, idx); /* update internal index... */ - setivalue(ra + 3, idx); /* ...and external index */ - } - } - else { /* floating loop */ - lua_Number step = fltvalue(ra + 2); - lua_Number idx = luai_numadd(L, fltvalue(ra), step); /* inc. index */ - lua_Number limit = fltvalue(ra + 1); - if (luai_numlt(0, step) ? luai_numle(idx, limit) - : luai_numle(limit, idx)) { - ci->u.l.savedpc += GETARG_sBx(i); /* jump back */ - chgfltvalue(ra, idx); /* update internal index... */ - setfltvalue(ra + 3, idx); /* ...and external index */ - } - } - vmbreak; - } - vmcase(OP_FORPREP) { - TValue *init = ra; - TValue *plimit = ra + 1; - TValue *pstep = ra + 2; - lua_Integer ilimit; - int stopnow; - if (ttisinteger(init) && ttisinteger(pstep) && - forlimit(plimit, &ilimit, ivalue(pstep), &stopnow)) { - /* all values are integer */ - lua_Integer initv = (stopnow ? 0 : ivalue(init)); - setivalue(plimit, ilimit); - setivalue(init, intop(-, initv, ivalue(pstep))); - } - else { /* try making all values floats */ - lua_Number ninit; lua_Number nlimit; lua_Number nstep; - if (!tonumber(plimit, &nlimit)) - luaG_runerror(L, "'for' limit must be a number"); - setfltvalue(plimit, nlimit); - if (!tonumber(pstep, &nstep)) - luaG_runerror(L, "'for' step must be a number"); - setfltvalue(pstep, nstep); - if (!tonumber(init, &ninit)) - luaG_runerror(L, "'for' initial value must be a number"); - setfltvalue(init, luai_numsub(L, ninit, nstep)); - } - ci->u.l.savedpc += GETARG_sBx(i); - vmbreak; - } - vmcase(OP_TFORCALL) { - StkId cb = ra + 3; /* call base */ - setobjs2s(L, cb+2, ra+2); - setobjs2s(L, cb+1, ra+1); - setobjs2s(L, cb, ra); - L->top = cb + 3; /* func. + 2 args (state and index) */ - Protect(luaD_call(L, cb, GETARG_C(i))); - L->top = ci->top; - i = *(ci->u.l.savedpc++); /* go to next instruction */ - ra = RA(i); - lua_assert(GET_OPCODE(i) == OP_TFORLOOP); - goto l_tforloop; - } - vmcase(OP_TFORLOOP) { - l_tforloop: - if (!ttisnil(ra + 1)) { /* continue loop? */ - setobjs2s(L, ra, ra + 1); /* save control variable */ - ci->u.l.savedpc += GETARG_sBx(i); /* jump back */ - } - vmbreak; - } - vmcase(OP_SETLIST) { - int n = GETARG_B(i); - int c = GETARG_C(i); - unsigned int last; - Table *h; - if (n == 0) n = cast_int(L->top - ra) - 1; - if (c == 0) { - lua_assert(GET_OPCODE(*ci->u.l.savedpc) == OP_EXTRAARG); - c = GETARG_Ax(*ci->u.l.savedpc++); - } - h = hvalue(ra); - last = ((c-1)*LFIELDS_PER_FLUSH) + n; - if (last > h->sizearray) /* needs more space? */ - luaH_resizearray(L, h, last); /* preallocate it at once */ - for (; n > 0; n--) { - TValue *val = ra+n; - luaH_setint(L, h, last--, val); - luaC_barrierback(L, h, val); - } - L->top = ci->top; /* correct top (in case of previous open call) */ - vmbreak; - } - vmcase(OP_CLOSURE) { - Proto *p = cl->p->p[GETARG_Bx(i)]; - LClosure *ncl = getcached(p, cl->upvals, base); /* cached closure */ - if (ncl == NULL) /* no match? */ - pushclosure(L, p, cl->upvals, base, ra); /* create a new one */ - else - setclLvalue(L, ra, ncl); /* push cashed closure */ - checkGC(L, ra + 1); - vmbreak; - } - vmcase(OP_VARARG) { - int b = GETARG_B(i) - 1; /* required results */ - int j; - int n = cast_int(base - ci->func) - cl->p->numparams - 1; - if (n < 0) /* less arguments than parameters? */ - n = 0; /* no vararg arguments */ - if (b < 0) { /* B == 0? */ - b = n; /* get all var. arguments */ - Protect(luaD_checkstack(L, n)); - ra = RA(i); /* previous call may change the stack */ - L->top = ra + n; - } - for (j = 0; j < b && j < n; j++) - setobjs2s(L, ra + j, base - n + j); - for (; j < b; j++) /* complete required results with nil */ - setnilvalue(ra + j); - vmbreak; - } - vmcase(OP_EXTRAARG) { - lua_assert(0); - vmbreak; - } - } - } -} - -/* }================================================================== */ - diff --git a/lib/lua-5.3/src/lvm.h b/lib/lua-5.3/src/lvm.h deleted file mode 100644 index a8f954f..0000000 --- a/lib/lua-5.3/src/lvm.h +++ /dev/null @@ -1,113 +0,0 @@ -/* -** $Id: lvm.h,v 2.41.1.1 2017/04/19 17:20:42 roberto Exp $ -** Lua virtual machine -** See Copyright Notice in lua.h -*/ - -#ifndef lvm_h -#define lvm_h - - -#include "ldo.h" -#include "lobject.h" -#include "ltm.h" - - -#if !defined(LUA_NOCVTN2S) -#define cvt2str(o) ttisnumber(o) -#else -#define cvt2str(o) 0 /* no conversion from numbers to strings */ -#endif - - -#if !defined(LUA_NOCVTS2N) -#define cvt2num(o) ttisstring(o) -#else -#define cvt2num(o) 0 /* no conversion from strings to numbers */ -#endif - - -/* -** You can define LUA_FLOORN2I if you want to convert floats to integers -** by flooring them (instead of raising an error if they are not -** integral values) -*/ -#if !defined(LUA_FLOORN2I) -#define LUA_FLOORN2I 0 -#endif - - -#define tonumber(o,n) \ - (ttisfloat(o) ? (*(n) = fltvalue(o), 1) : luaV_tonumber_(o,n)) - -#define tointeger(o,i) \ - (ttisinteger(o) ? (*(i) = ivalue(o), 1) : luaV_tointeger(o,i,LUA_FLOORN2I)) - -#define intop(op,v1,v2) l_castU2S(l_castS2U(v1) op l_castS2U(v2)) - -#define luaV_rawequalobj(t1,t2) luaV_equalobj(NULL,t1,t2) - - -/* -** fast track for 'gettable': if 't' is a table and 't[k]' is not nil, -** return 1 with 'slot' pointing to 't[k]' (final result). Otherwise, -** return 0 (meaning it will have to check metamethod) with 'slot' -** pointing to a nil 't[k]' (if 't' is a table) or NULL (otherwise). -** 'f' is the raw get function to use. -*/ -#define luaV_fastget(L,t,k,slot,f) \ - (!ttistable(t) \ - ? (slot = NULL, 0) /* not a table; 'slot' is NULL and result is 0 */ \ - : (slot = f(hvalue(t), k), /* else, do raw access */ \ - !ttisnil(slot))) /* result not nil? */ - -/* -** standard implementation for 'gettable' -*/ -#define luaV_gettable(L,t,k,v) { const TValue *slot; \ - if (luaV_fastget(L,t,k,slot,luaH_get)) { setobj2s(L, v, slot); } \ - else luaV_finishget(L,t,k,v,slot); } - - -/* -** Fast track for set table. If 't' is a table and 't[k]' is not nil, -** call GC barrier, do a raw 't[k]=v', and return true; otherwise, -** return false with 'slot' equal to NULL (if 't' is not a table) or -** 'nil'. (This is needed by 'luaV_finishget'.) Note that, if the macro -** returns true, there is no need to 'invalidateTMcache', because the -** call is not creating a new entry. -*/ -#define luaV_fastset(L,t,k,slot,f,v) \ - (!ttistable(t) \ - ? (slot = NULL, 0) \ - : (slot = f(hvalue(t), k), \ - ttisnil(slot) ? 0 \ - : (luaC_barrierback(L, hvalue(t), v), \ - setobj2t(L, cast(TValue *,slot), v), \ - 1))) - - -#define luaV_settable(L,t,k,v) { const TValue *slot; \ - if (!luaV_fastset(L,t,k,slot,luaH_get,v)) \ - luaV_finishset(L,t,k,v,slot); } - - - -LUAI_FUNC int luaV_equalobj (lua_State *L, const TValue *t1, const TValue *t2); -LUAI_FUNC int luaV_lessthan (lua_State *L, const TValue *l, const TValue *r); -LUAI_FUNC int luaV_lessequal (lua_State *L, const TValue *l, const TValue *r); -LUAI_FUNC int luaV_tonumber_ (const TValue *obj, lua_Number *n); -LUAI_FUNC int luaV_tointeger (const TValue *obj, lua_Integer *p, int mode); -LUAI_FUNC void luaV_finishget (lua_State *L, const TValue *t, TValue *key, - StkId val, const TValue *slot); -LUAI_FUNC void luaV_finishset (lua_State *L, const TValue *t, TValue *key, - StkId val, const TValue *slot); -LUAI_FUNC void luaV_finishOp (lua_State *L); -LUAI_FUNC void luaV_execute (lua_State *L); -LUAI_FUNC void luaV_concat (lua_State *L, int total); -LUAI_FUNC lua_Integer luaV_div (lua_State *L, lua_Integer x, lua_Integer y); -LUAI_FUNC lua_Integer luaV_mod (lua_State *L, lua_Integer x, lua_Integer y); -LUAI_FUNC lua_Integer luaV_shiftl (lua_Integer x, lua_Integer y); -LUAI_FUNC void luaV_objlen (lua_State *L, StkId ra, const TValue *rb); - -#endif diff --git a/lib/lua-5.3/src/lzio.c b/lib/lua-5.3/src/lzio.c deleted file mode 100644 index 6f79094..0000000 --- a/lib/lua-5.3/src/lzio.c +++ /dev/null @@ -1,68 +0,0 @@ -/* -** $Id: lzio.c,v 1.37.1.1 2017/04/19 17:20:42 roberto Exp $ -** Buffered streams -** See Copyright Notice in lua.h -*/ - -#define lzio_c -#define LUA_CORE - -#include "lprefix.h" - - -#include - -#include "lua.h" - -#include "llimits.h" -#include "lmem.h" -#include "lstate.h" -#include "lzio.h" - - -int luaZ_fill (ZIO *z) { - size_t size; - lua_State *L = z->L; - const char *buff; - lua_unlock(L); - buff = z->reader(L, z->data, &size); - lua_lock(L); - if (buff == NULL || size == 0) - return EOZ; - z->n = size - 1; /* discount char being returned */ - z->p = buff; - return cast_uchar(*(z->p++)); -} - - -void luaZ_init (lua_State *L, ZIO *z, lua_Reader reader, void *data) { - z->L = L; - z->reader = reader; - z->data = data; - z->n = 0; - z->p = NULL; -} - - -/* --------------------------------------------------------------- read --- */ -size_t luaZ_read (ZIO *z, void *b, size_t n) { - while (n) { - size_t m; - if (z->n == 0) { /* no bytes in buffer? */ - if (luaZ_fill(z) == EOZ) /* try to read more */ - return n; /* no more input; return number of missing bytes */ - else { - z->n++; /* luaZ_fill consumed first byte; put it back */ - z->p--; - } - } - m = (n <= z->n) ? n : z->n; /* min. between n and z->n */ - memcpy(b, z->p, m); - z->n -= m; - z->p += m; - b = (char *)b + m; - n -= m; - } - return 0; -} - diff --git a/lib/lua-5.3/src/lzio.h b/lib/lua-5.3/src/lzio.h deleted file mode 100644 index d897870..0000000 --- a/lib/lua-5.3/src/lzio.h +++ /dev/null @@ -1,66 +0,0 @@ -/* -** $Id: lzio.h,v 1.31.1.1 2017/04/19 17:20:42 roberto Exp $ -** Buffered streams -** See Copyright Notice in lua.h -*/ - - -#ifndef lzio_h -#define lzio_h - -#include "lua.h" - -#include "lmem.h" - - -#define EOZ (-1) /* end of stream */ - -typedef struct Zio ZIO; - -#define zgetc(z) (((z)->n--)>0 ? cast_uchar(*(z)->p++) : luaZ_fill(z)) - - -typedef struct Mbuffer { - char *buffer; - size_t n; - size_t buffsize; -} Mbuffer; - -#define luaZ_initbuffer(L, buff) ((buff)->buffer = NULL, (buff)->buffsize = 0) - -#define luaZ_buffer(buff) ((buff)->buffer) -#define luaZ_sizebuffer(buff) ((buff)->buffsize) -#define luaZ_bufflen(buff) ((buff)->n) - -#define luaZ_buffremove(buff,i) ((buff)->n -= (i)) -#define luaZ_resetbuffer(buff) ((buff)->n = 0) - - -#define luaZ_resizebuffer(L, buff, size) \ - ((buff)->buffer = luaM_reallocvchar(L, (buff)->buffer, \ - (buff)->buffsize, size), \ - (buff)->buffsize = size) - -#define luaZ_freebuffer(L, buff) luaZ_resizebuffer(L, buff, 0) - - -LUAI_FUNC void luaZ_init (lua_State *L, ZIO *z, lua_Reader reader, - void *data); -LUAI_FUNC size_t luaZ_read (ZIO* z, void *b, size_t n); /* read next n bytes */ - - - -/* --------- Private Part ------------------ */ - -struct Zio { - size_t n; /* bytes still unread */ - const char *p; /* current position in buffer */ - lua_Reader reader; /* reader function */ - void *data; /* additional data */ - lua_State *L; /* Lua state (for reader) */ -}; - - -LUAI_FUNC int luaZ_fill (ZIO *z); - -#endif diff --git a/lib/lua-5.4/Makefile b/lib/lua-5.4/Makefile deleted file mode 100644 index 8efa2eb..0000000 --- a/lib/lua-5.4/Makefile +++ /dev/null @@ -1,106 +0,0 @@ -# Makefile for installing Lua -# See doc/readme.html for installation and customization instructions. - -# == CHANGE THE SETTINGS BELOW TO SUIT YOUR ENVIRONMENT ======================= - -# Your platform. See PLATS for possible values. -PLAT= guess - -# Where to install. The installation starts in the src and doc directories, -# so take care if INSTALL_TOP is not an absolute path. See the local target. -# You may want to make INSTALL_LMOD and INSTALL_CMOD consistent with -# LUA_ROOT, LUA_LDIR, and LUA_CDIR in luaconf.h. -INSTALL_TOP= /usr/local -INSTALL_BIN= $(INSTALL_TOP)/bin -INSTALL_INC= $(INSTALL_TOP)/include -INSTALL_LIB= $(INSTALL_TOP)/lib -INSTALL_MAN= $(INSTALL_TOP)/man/man1 -INSTALL_LMOD= $(INSTALL_TOP)/share/lua/$V -INSTALL_CMOD= $(INSTALL_TOP)/lib/lua/$V - -# How to install. If your install program does not support "-p", then -# you may have to run ranlib on the installed liblua.a. -INSTALL= install -p -INSTALL_EXEC= $(INSTALL) -m 0755 -INSTALL_DATA= $(INSTALL) -m 0644 -# -# If you don't have "install" you can use "cp" instead. -# INSTALL= cp -p -# INSTALL_EXEC= $(INSTALL) -# INSTALL_DATA= $(INSTALL) - -# Other utilities. -MKDIR= mkdir -p -RM= rm -f - -# == END OF USER SETTINGS -- NO NEED TO CHANGE ANYTHING BELOW THIS LINE ======= - -# Convenience platforms targets. -PLATS= guess aix bsd c89 freebsd generic ios linux linux-readline macosx mingw posix solaris - -# What to install. -TO_BIN= lua luac -TO_INC= lua.h luaconf.h lualib.h lauxlib.h lua.hpp -TO_LIB= liblua.a -TO_MAN= lua.1 luac.1 - -# Lua version and release. -V= 5.4 -R= $V.6 - -# Targets start here. -all: $(PLAT) - -$(PLATS) help test clean: - @cd src && $(MAKE) $@ - -install: dummy - cd src && $(MKDIR) $(INSTALL_BIN) $(INSTALL_INC) $(INSTALL_LIB) $(INSTALL_MAN) $(INSTALL_LMOD) $(INSTALL_CMOD) - cd src && $(INSTALL_EXEC) $(TO_BIN) $(INSTALL_BIN) - cd src && $(INSTALL_DATA) $(TO_INC) $(INSTALL_INC) - cd src && $(INSTALL_DATA) $(TO_LIB) $(INSTALL_LIB) - cd doc && $(INSTALL_DATA) $(TO_MAN) $(INSTALL_MAN) - -uninstall: - cd src && cd $(INSTALL_BIN) && $(RM) $(TO_BIN) - cd src && cd $(INSTALL_INC) && $(RM) $(TO_INC) - cd src && cd $(INSTALL_LIB) && $(RM) $(TO_LIB) - cd doc && cd $(INSTALL_MAN) && $(RM) $(TO_MAN) - -local: - $(MAKE) install INSTALL_TOP=../install - -# make may get confused with install/ if it does not support .PHONY. -dummy: - -# Echo config parameters. -echo: - @cd src && $(MAKE) -s echo - @echo "PLAT= $(PLAT)" - @echo "V= $V" - @echo "R= $R" - @echo "TO_BIN= $(TO_BIN)" - @echo "TO_INC= $(TO_INC)" - @echo "TO_LIB= $(TO_LIB)" - @echo "TO_MAN= $(TO_MAN)" - @echo "INSTALL_TOP= $(INSTALL_TOP)" - @echo "INSTALL_BIN= $(INSTALL_BIN)" - @echo "INSTALL_INC= $(INSTALL_INC)" - @echo "INSTALL_LIB= $(INSTALL_LIB)" - @echo "INSTALL_MAN= $(INSTALL_MAN)" - @echo "INSTALL_LMOD= $(INSTALL_LMOD)" - @echo "INSTALL_CMOD= $(INSTALL_CMOD)" - @echo "INSTALL_EXEC= $(INSTALL_EXEC)" - @echo "INSTALL_DATA= $(INSTALL_DATA)" - -# Echo pkg-config data. -pc: - @echo "version=$R" - @echo "prefix=$(INSTALL_TOP)" - @echo "libdir=$(INSTALL_LIB)" - @echo "includedir=$(INSTALL_INC)" - -# Targets that do not create files (not all makes understand .PHONY). -.PHONY: all $(PLATS) help test clean install uninstall local dummy echo pc - -# (end of Makefile) diff --git a/lib/lua-5.4/README b/lib/lua-5.4/README deleted file mode 100644 index 1ae9716..0000000 --- a/lib/lua-5.4/README +++ /dev/null @@ -1,6 +0,0 @@ - -This is Lua 5.4.6, released on 02 May 2023. - -For installation instructions, license details, and -further information about Lua, see doc/readme.html. - diff --git a/lib/lua-5.4/license b/lib/lua-5.4/license deleted file mode 100644 index 00425ce..0000000 --- a/lib/lua-5.4/license +++ /dev/null @@ -1,7 +0,0 @@ -Copyright © 1994–2021 Lua.org, PUC-Rio. - -Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: - -The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. diff --git a/lib/lua-5.4/src/Makefile b/lib/lua-5.4/src/Makefile deleted file mode 100644 index b771196..0000000 --- a/lib/lua-5.4/src/Makefile +++ /dev/null @@ -1,225 +0,0 @@ -# Makefile for building Lua -# See ../doc/readme.html for installation and customization instructions. - -# == CHANGE THE SETTINGS BELOW TO SUIT YOUR ENVIRONMENT ======================= - -# Your platform. See PLATS for possible values. -PLAT= guess - -CC= gcc -std=gnu99 -CFLAGS= -O2 -Wall -Wextra -DLUA_COMPAT_5_3 $(SYSCFLAGS) $(MYCFLAGS) -LDFLAGS= $(SYSLDFLAGS) $(MYLDFLAGS) -LIBS= -lm $(SYSLIBS) $(MYLIBS) - -AR= ar rcu -RANLIB= ranlib -RM= rm -f -UNAME= uname - -SYSCFLAGS= -SYSLDFLAGS= -SYSLIBS= - -MYCFLAGS= -MYLDFLAGS= -MYLIBS= -MYOBJS= - -# Special flags for compiler modules; -Os reduces code size. -CMCFLAGS= - -# == END OF USER SETTINGS -- NO NEED TO CHANGE ANYTHING BELOW THIS LINE ======= - -PLATS= guess aix bsd c89 freebsd generic ios linux linux-readline macosx mingw posix solaris - -LUA_A= liblua.a -CORE_O= lapi.o lcode.o lctype.o ldebug.o ldo.o ldump.o lfunc.o lgc.o llex.o lmem.o lobject.o lopcodes.o lparser.o lstate.o lstring.o ltable.o ltm.o lundump.o lvm.o lzio.o -LIB_O= lauxlib.o lbaselib.o lcorolib.o ldblib.o liolib.o lmathlib.o loadlib.o loslib.o lstrlib.o ltablib.o lutf8lib.o linit.o -BASE_O= $(CORE_O) $(LIB_O) $(MYOBJS) - -LUA_T= lua -LUA_O= lua.o - -LUAC_T= luac -LUAC_O= luac.o - -ALL_O= $(BASE_O) $(LUA_O) $(LUAC_O) -ALL_T= $(LUA_A) $(LUA_T) $(LUAC_T) -ALL_A= $(LUA_A) - -# Targets start here. -default: $(PLAT) - -all: $(ALL_T) - -o: $(ALL_O) - -a: $(ALL_A) - -$(LUA_A): $(BASE_O) - $(AR) $@ $(BASE_O) - $(RANLIB) $@ - -$(LUA_T): $(LUA_O) $(LUA_A) - $(CC) -o $@ $(LDFLAGS) $(LUA_O) $(LUA_A) $(LIBS) - -$(LUAC_T): $(LUAC_O) $(LUA_A) - $(CC) -o $@ $(LDFLAGS) $(LUAC_O) $(LUA_A) $(LIBS) - -test: - ./$(LUA_T) -v - -clean: - $(RM) $(ALL_T) $(ALL_O) - -depend: - @$(CC) $(CFLAGS) -MM l*.c - -echo: - @echo "PLAT= $(PLAT)" - @echo "CC= $(CC)" - @echo "CFLAGS= $(CFLAGS)" - @echo "LDFLAGS= $(LDFLAGS)" - @echo "LIBS= $(LIBS)" - @echo "AR= $(AR)" - @echo "RANLIB= $(RANLIB)" - @echo "RM= $(RM)" - @echo "UNAME= $(UNAME)" - -# Convenience targets for popular platforms. -ALL= all - -help: - @echo "Do 'make PLATFORM' where PLATFORM is one of these:" - @echo " $(PLATS)" - @echo "See doc/readme.html for complete instructions." - -guess: - @echo Guessing `$(UNAME)` - @$(MAKE) `$(UNAME)` - -AIX aix: - $(MAKE) $(ALL) CC="xlc" CFLAGS="-O2 -DLUA_USE_POSIX -DLUA_USE_DLOPEN" SYSLIBS="-ldl" SYSLDFLAGS="-brtl -bexpall" - -bsd: - $(MAKE) $(ALL) SYSCFLAGS="-DLUA_USE_POSIX -DLUA_USE_DLOPEN" SYSLIBS="-Wl,-E" - -c89: - $(MAKE) $(ALL) SYSCFLAGS="-DLUA_USE_C89" CC="gcc -std=c89" - @echo '' - @echo '*** C89 does not guarantee 64-bit integers for Lua.' - @echo '*** Make sure to compile all external Lua libraries' - @echo '*** with LUA_USE_C89 to ensure consistency' - @echo '' - -FreeBSD NetBSD OpenBSD freebsd: - $(MAKE) $(ALL) SYSCFLAGS="-DLUA_USE_LINUX -DLUA_USE_READLINE -I/usr/include/edit" SYSLIBS="-Wl,-E -ledit" CC="cc" - -generic: $(ALL) - -ios: - $(MAKE) $(ALL) SYSCFLAGS="-DLUA_USE_IOS" - -Linux linux: linux-noreadline - -linux-noreadline: - $(MAKE) $(ALL) SYSCFLAGS="-DLUA_USE_LINUX" SYSLIBS="-Wl,-E -ldl" - -linux-readline: - $(MAKE) $(ALL) SYSCFLAGS="-DLUA_USE_LINUX -DLUA_USE_READLINE" SYSLIBS="-Wl,-E -ldl -lreadline" - -Darwin macos macosx: - $(MAKE) $(ALL) SYSCFLAGS="-DLUA_USE_MACOSX -DLUA_USE_READLINE" SYSLIBS="-lreadline" - -mingw: - $(MAKE) "LUA_A=lua54.dll" "LUA_T=lua.exe" \ - "AR=$(CC) -shared -o" "RANLIB=strip --strip-unneeded" \ - "SYSCFLAGS=-DLUA_BUILD_AS_DLL" "SYSLIBS=" "SYSLDFLAGS=-s" lua.exe - $(MAKE) "LUAC_T=luac.exe" luac.exe - -posix: - $(MAKE) $(ALL) SYSCFLAGS="-DLUA_USE_POSIX" - -SunOS solaris: - $(MAKE) $(ALL) SYSCFLAGS="-DLUA_USE_POSIX -DLUA_USE_DLOPEN -D_REENTRANT" SYSLIBS="-ldl" - -# Targets that do not create files (not all makes understand .PHONY). -.PHONY: all $(PLATS) help test clean default o a depend echo - -# Compiler modules may use special flags. -llex.o: - $(CC) $(CFLAGS) $(CMCFLAGS) -c llex.c - -lparser.o: - $(CC) $(CFLAGS) $(CMCFLAGS) -c lparser.c - -lcode.o: - $(CC) $(CFLAGS) $(CMCFLAGS) -c lcode.c - -# DO NOT DELETE - -lapi.o: lapi.c lprefix.h lua.h luaconf.h lapi.h llimits.h lstate.h \ - lobject.h ltm.h lzio.h lmem.h ldebug.h ldo.h lfunc.h lgc.h lstring.h \ - ltable.h lundump.h lvm.h -lauxlib.o: lauxlib.c lprefix.h lua.h luaconf.h lauxlib.h -lbaselib.o: lbaselib.c lprefix.h lua.h luaconf.h lauxlib.h lualib.h -lcode.o: lcode.c lprefix.h lua.h luaconf.h lcode.h llex.h lobject.h \ - llimits.h lzio.h lmem.h lopcodes.h lparser.h ldebug.h lstate.h ltm.h \ - ldo.h lgc.h lstring.h ltable.h lvm.h -lcorolib.o: lcorolib.c lprefix.h lua.h luaconf.h lauxlib.h lualib.h -lctype.o: lctype.c lprefix.h lctype.h lua.h luaconf.h llimits.h -ldblib.o: ldblib.c lprefix.h lua.h luaconf.h lauxlib.h lualib.h -ldebug.o: ldebug.c lprefix.h lua.h luaconf.h lapi.h llimits.h lstate.h \ - lobject.h ltm.h lzio.h lmem.h lcode.h llex.h lopcodes.h lparser.h \ - ldebug.h ldo.h lfunc.h lstring.h lgc.h ltable.h lvm.h -ldo.o: ldo.c lprefix.h lua.h luaconf.h lapi.h llimits.h lstate.h \ - lobject.h ltm.h lzio.h lmem.h ldebug.h ldo.h lfunc.h lgc.h lopcodes.h \ - lparser.h lstring.h ltable.h lundump.h lvm.h -ldump.o: ldump.c lprefix.h lua.h luaconf.h lobject.h llimits.h lstate.h \ - ltm.h lzio.h lmem.h lundump.h -lfunc.o: lfunc.c lprefix.h lua.h luaconf.h ldebug.h lstate.h lobject.h \ - llimits.h ltm.h lzio.h lmem.h ldo.h lfunc.h lgc.h -lgc.o: lgc.c lprefix.h lua.h luaconf.h ldebug.h lstate.h lobject.h \ - llimits.h ltm.h lzio.h lmem.h ldo.h lfunc.h lgc.h lstring.h ltable.h -linit.o: linit.c lprefix.h lua.h luaconf.h lualib.h lauxlib.h -liolib.o: liolib.c lprefix.h lua.h luaconf.h lauxlib.h lualib.h -llex.o: llex.c lprefix.h lua.h luaconf.h lctype.h llimits.h ldebug.h \ - lstate.h lobject.h ltm.h lzio.h lmem.h ldo.h lgc.h llex.h lparser.h \ - lstring.h ltable.h -lmathlib.o: lmathlib.c lprefix.h lua.h luaconf.h lauxlib.h lualib.h -lmem.o: lmem.c lprefix.h lua.h luaconf.h ldebug.h lstate.h lobject.h \ - llimits.h ltm.h lzio.h lmem.h ldo.h lgc.h -loadlib.o: loadlib.c lprefix.h lua.h luaconf.h lauxlib.h lualib.h -lobject.o: lobject.c lprefix.h lua.h luaconf.h lctype.h llimits.h \ - ldebug.h lstate.h lobject.h ltm.h lzio.h lmem.h ldo.h lstring.h lgc.h \ - lvm.h -lopcodes.o: lopcodes.c lprefix.h lopcodes.h llimits.h lua.h luaconf.h -loslib.o: loslib.c lprefix.h lua.h luaconf.h lauxlib.h lualib.h -lparser.o: lparser.c lprefix.h lua.h luaconf.h lcode.h llex.h lobject.h \ - llimits.h lzio.h lmem.h lopcodes.h lparser.h ldebug.h lstate.h ltm.h \ - ldo.h lfunc.h lstring.h lgc.h ltable.h -lstate.o: lstate.c lprefix.h lua.h luaconf.h lapi.h llimits.h lstate.h \ - lobject.h ltm.h lzio.h lmem.h ldebug.h ldo.h lfunc.h lgc.h llex.h \ - lstring.h ltable.h -lstring.o: lstring.c lprefix.h lua.h luaconf.h ldebug.h lstate.h \ - lobject.h llimits.h ltm.h lzio.h lmem.h ldo.h lstring.h lgc.h -lstrlib.o: lstrlib.c lprefix.h lua.h luaconf.h lauxlib.h lualib.h -ltable.o: ltable.c lprefix.h lua.h luaconf.h ldebug.h lstate.h lobject.h \ - llimits.h ltm.h lzio.h lmem.h ldo.h lgc.h lstring.h ltable.h lvm.h -ltablib.o: ltablib.c lprefix.h lua.h luaconf.h lauxlib.h lualib.h -ltm.o: ltm.c lprefix.h lua.h luaconf.h ldebug.h lstate.h lobject.h \ - llimits.h ltm.h lzio.h lmem.h ldo.h lgc.h lstring.h ltable.h lvm.h -lua.o: lua.c lprefix.h lua.h luaconf.h lauxlib.h lualib.h -luac.o: luac.c lprefix.h lua.h luaconf.h lauxlib.h ldebug.h lstate.h \ - lobject.h llimits.h ltm.h lzio.h lmem.h lopcodes.h lopnames.h lundump.h -lundump.o: lundump.c lprefix.h lua.h luaconf.h ldebug.h lstate.h \ - lobject.h llimits.h ltm.h lzio.h lmem.h ldo.h lfunc.h lstring.h lgc.h \ - lundump.h -lutf8lib.o: lutf8lib.c lprefix.h lua.h luaconf.h lauxlib.h lualib.h -lvm.o: lvm.c lprefix.h lua.h luaconf.h ldebug.h lstate.h lobject.h \ - llimits.h ltm.h lzio.h lmem.h ldo.h lfunc.h lgc.h lopcodes.h lstring.h \ - ltable.h lvm.h ljumptab.h -lzio.o: lzio.c lprefix.h lua.h luaconf.h llimits.h lmem.h lstate.h \ - lobject.h ltm.h lzio.h - -# (end of Makefile) diff --git a/lib/lua-5.4/src/lapi.c b/lib/lua-5.4/src/lapi.c deleted file mode 100644 index 34e64af..0000000 --- a/lib/lua-5.4/src/lapi.c +++ /dev/null @@ -1,1463 +0,0 @@ -/* -** $Id: lapi.c $ -** Lua API -** See Copyright Notice in lua.h -*/ - -#define lapi_c -#define LUA_CORE - -#include "lprefix.h" - - -#include -#include -#include - -#include "lua.h" - -#include "lapi.h" -#include "ldebug.h" -#include "ldo.h" -#include "lfunc.h" -#include "lgc.h" -#include "lmem.h" -#include "lobject.h" -#include "lstate.h" -#include "lstring.h" -#include "ltable.h" -#include "ltm.h" -#include "lundump.h" -#include "lvm.h" - - - -const char lua_ident[] = - "$LuaVersion: " LUA_COPYRIGHT " $" - "$LuaAuthors: " LUA_AUTHORS " $"; - - - -/* -** Test for a valid index (one that is not the 'nilvalue'). -** '!ttisnil(o)' implies 'o != &G(L)->nilvalue', so it is not needed. -** However, it covers the most common cases in a faster way. -*/ -#define isvalid(L, o) (!ttisnil(o) || o != &G(L)->nilvalue) - - -/* test for pseudo index */ -#define ispseudo(i) ((i) <= LUA_REGISTRYINDEX) - -/* test for upvalue */ -#define isupvalue(i) ((i) < LUA_REGISTRYINDEX) - - -/* -** Convert an acceptable index to a pointer to its respective value. -** Non-valid indices return the special nil value 'G(L)->nilvalue'. -*/ -static TValue *index2value (lua_State *L, int idx) { - CallInfo *ci = L->ci; - if (idx > 0) { - StkId o = ci->func.p + idx; - api_check(L, idx <= ci->top.p - (ci->func.p + 1), "unacceptable index"); - if (o >= L->top.p) return &G(L)->nilvalue; - else return s2v(o); - } - else if (!ispseudo(idx)) { /* negative index */ - api_check(L, idx != 0 && -idx <= L->top.p - (ci->func.p + 1), - "invalid index"); - return s2v(L->top.p + idx); - } - else if (idx == LUA_REGISTRYINDEX) - return &G(L)->l_registry; - else { /* upvalues */ - idx = LUA_REGISTRYINDEX - idx; - api_check(L, idx <= MAXUPVAL + 1, "upvalue index too large"); - if (ttisCclosure(s2v(ci->func.p))) { /* C closure? */ - CClosure *func = clCvalue(s2v(ci->func.p)); - return (idx <= func->nupvalues) ? &func->upvalue[idx-1] - : &G(L)->nilvalue; - } - else { /* light C function or Lua function (through a hook)?) */ - api_check(L, ttislcf(s2v(ci->func.p)), "caller not a C function"); - return &G(L)->nilvalue; /* no upvalues */ - } - } -} - - - -/* -** Convert a valid actual index (not a pseudo-index) to its address. -*/ -l_sinline StkId index2stack (lua_State *L, int idx) { - CallInfo *ci = L->ci; - if (idx > 0) { - StkId o = ci->func.p + idx; - api_check(L, o < L->top.p, "invalid index"); - return o; - } - else { /* non-positive index */ - api_check(L, idx != 0 && -idx <= L->top.p - (ci->func.p + 1), - "invalid index"); - api_check(L, !ispseudo(idx), "invalid index"); - return L->top.p + idx; - } -} - - -LUA_API int lua_checkstack (lua_State *L, int n) { - int res; - CallInfo *ci; - lua_lock(L); - ci = L->ci; - api_check(L, n >= 0, "negative 'n'"); - if (L->stack_last.p - L->top.p > n) /* stack large enough? */ - res = 1; /* yes; check is OK */ - else /* need to grow stack */ - res = luaD_growstack(L, n, 0); - if (res && ci->top.p < L->top.p + n) - ci->top.p = L->top.p + n; /* adjust frame top */ - lua_unlock(L); - return res; -} - - -LUA_API void lua_xmove (lua_State *from, lua_State *to, int n) { - int i; - if (from == to) return; - lua_lock(to); - api_checknelems(from, n); - api_check(from, G(from) == G(to), "moving among independent states"); - api_check(from, to->ci->top.p - to->top.p >= n, "stack overflow"); - from->top.p -= n; - for (i = 0; i < n; i++) { - setobjs2s(to, to->top.p, from->top.p + i); - to->top.p++; /* stack already checked by previous 'api_check' */ - } - lua_unlock(to); -} - - -LUA_API lua_CFunction lua_atpanic (lua_State *L, lua_CFunction panicf) { - lua_CFunction old; - lua_lock(L); - old = G(L)->panic; - G(L)->panic = panicf; - lua_unlock(L); - return old; -} - - -LUA_API lua_Number lua_version (lua_State *L) { - UNUSED(L); - return LUA_VERSION_NUM; -} - - - -/* -** basic stack manipulation -*/ - - -/* -** convert an acceptable stack index into an absolute index -*/ -LUA_API int lua_absindex (lua_State *L, int idx) { - return (idx > 0 || ispseudo(idx)) - ? idx - : cast_int(L->top.p - L->ci->func.p) + idx; -} - - -LUA_API int lua_gettop (lua_State *L) { - return cast_int(L->top.p - (L->ci->func.p + 1)); -} - - -LUA_API void lua_settop (lua_State *L, int idx) { - CallInfo *ci; - StkId func, newtop; - ptrdiff_t diff; /* difference for new top */ - lua_lock(L); - ci = L->ci; - func = ci->func.p; - if (idx >= 0) { - api_check(L, idx <= ci->top.p - (func + 1), "new top too large"); - diff = ((func + 1) + idx) - L->top.p; - for (; diff > 0; diff--) - setnilvalue(s2v(L->top.p++)); /* clear new slots */ - } - else { - api_check(L, -(idx+1) <= (L->top.p - (func + 1)), "invalid new top"); - diff = idx + 1; /* will "subtract" index (as it is negative) */ - } - api_check(L, L->tbclist.p < L->top.p, "previous pop of an unclosed slot"); - newtop = L->top.p + diff; - if (diff < 0 && L->tbclist.p >= newtop) { - lua_assert(hastocloseCfunc(ci->nresults)); - newtop = luaF_close(L, newtop, CLOSEKTOP, 0); - } - L->top.p = newtop; /* correct top only after closing any upvalue */ - lua_unlock(L); -} - - -LUA_API void lua_closeslot (lua_State *L, int idx) { - StkId level; - lua_lock(L); - level = index2stack(L, idx); - api_check(L, hastocloseCfunc(L->ci->nresults) && L->tbclist.p == level, - "no variable to close at given level"); - level = luaF_close(L, level, CLOSEKTOP, 0); - setnilvalue(s2v(level)); - lua_unlock(L); -} - - -/* -** Reverse the stack segment from 'from' to 'to' -** (auxiliary to 'lua_rotate') -** Note that we move(copy) only the value inside the stack. -** (We do not move additional fields that may exist.) -*/ -l_sinline void reverse (lua_State *L, StkId from, StkId to) { - for (; from < to; from++, to--) { - TValue temp; - setobj(L, &temp, s2v(from)); - setobjs2s(L, from, to); - setobj2s(L, to, &temp); - } -} - - -/* -** Let x = AB, where A is a prefix of length 'n'. Then, -** rotate x n == BA. But BA == (A^r . B^r)^r. -*/ -LUA_API void lua_rotate (lua_State *L, int idx, int n) { - StkId p, t, m; - lua_lock(L); - t = L->top.p - 1; /* end of stack segment being rotated */ - p = index2stack(L, idx); /* start of segment */ - api_check(L, (n >= 0 ? n : -n) <= (t - p + 1), "invalid 'n'"); - m = (n >= 0 ? t - n : p - n - 1); /* end of prefix */ - reverse(L, p, m); /* reverse the prefix with length 'n' */ - reverse(L, m + 1, t); /* reverse the suffix */ - reverse(L, p, t); /* reverse the entire segment */ - lua_unlock(L); -} - - -LUA_API void lua_copy (lua_State *L, int fromidx, int toidx) { - TValue *fr, *to; - lua_lock(L); - fr = index2value(L, fromidx); - to = index2value(L, toidx); - api_check(L, isvalid(L, to), "invalid index"); - setobj(L, to, fr); - if (isupvalue(toidx)) /* function upvalue? */ - luaC_barrier(L, clCvalue(s2v(L->ci->func.p)), fr); - /* LUA_REGISTRYINDEX does not need gc barrier - (collector revisits it before finishing collection) */ - lua_unlock(L); -} - - -LUA_API void lua_pushvalue (lua_State *L, int idx) { - lua_lock(L); - setobj2s(L, L->top.p, index2value(L, idx)); - api_incr_top(L); - lua_unlock(L); -} - - - -/* -** access functions (stack -> C) -*/ - - -LUA_API int lua_type (lua_State *L, int idx) { - const TValue *o = index2value(L, idx); - return (isvalid(L, o) ? ttype(o) : LUA_TNONE); -} - - -LUA_API const char *lua_typename (lua_State *L, int t) { - UNUSED(L); - api_check(L, LUA_TNONE <= t && t < LUA_NUMTYPES, "invalid type"); - return ttypename(t); -} - - -LUA_API int lua_iscfunction (lua_State *L, int idx) { - const TValue *o = index2value(L, idx); - return (ttislcf(o) || (ttisCclosure(o))); -} - - -LUA_API int lua_isinteger (lua_State *L, int idx) { - const TValue *o = index2value(L, idx); - return ttisinteger(o); -} - - -LUA_API int lua_isnumber (lua_State *L, int idx) { - lua_Number n; - const TValue *o = index2value(L, idx); - return tonumber(o, &n); -} - - -LUA_API int lua_isstring (lua_State *L, int idx) { - const TValue *o = index2value(L, idx); - return (ttisstring(o) || cvt2str(o)); -} - - -LUA_API int lua_isuserdata (lua_State *L, int idx) { - const TValue *o = index2value(L, idx); - return (ttisfulluserdata(o) || ttislightuserdata(o)); -} - - -LUA_API int lua_rawequal (lua_State *L, int index1, int index2) { - const TValue *o1 = index2value(L, index1); - const TValue *o2 = index2value(L, index2); - return (isvalid(L, o1) && isvalid(L, o2)) ? luaV_rawequalobj(o1, o2) : 0; -} - - -LUA_API void lua_arith (lua_State *L, int op) { - lua_lock(L); - if (op != LUA_OPUNM && op != LUA_OPBNOT) - api_checknelems(L, 2); /* all other operations expect two operands */ - else { /* for unary operations, add fake 2nd operand */ - api_checknelems(L, 1); - setobjs2s(L, L->top.p, L->top.p - 1); - api_incr_top(L); - } - /* first operand at top - 2, second at top - 1; result go to top - 2 */ - luaO_arith(L, op, s2v(L->top.p - 2), s2v(L->top.p - 1), L->top.p - 2); - L->top.p--; /* remove second operand */ - lua_unlock(L); -} - - -LUA_API int lua_compare (lua_State *L, int index1, int index2, int op) { - const TValue *o1; - const TValue *o2; - int i = 0; - lua_lock(L); /* may call tag method */ - o1 = index2value(L, index1); - o2 = index2value(L, index2); - if (isvalid(L, o1) && isvalid(L, o2)) { - switch (op) { - case LUA_OPEQ: i = luaV_equalobj(L, o1, o2); break; - case LUA_OPLT: i = luaV_lessthan(L, o1, o2); break; - case LUA_OPLE: i = luaV_lessequal(L, o1, o2); break; - default: api_check(L, 0, "invalid option"); - } - } - lua_unlock(L); - return i; -} - - -LUA_API size_t lua_stringtonumber (lua_State *L, const char *s) { - size_t sz = luaO_str2num(s, s2v(L->top.p)); - if (sz != 0) - api_incr_top(L); - return sz; -} - - -LUA_API lua_Number lua_tonumberx (lua_State *L, int idx, int *pisnum) { - lua_Number n = 0; - const TValue *o = index2value(L, idx); - int isnum = tonumber(o, &n); - if (pisnum) - *pisnum = isnum; - return n; -} - - -LUA_API lua_Integer lua_tointegerx (lua_State *L, int idx, int *pisnum) { - lua_Integer res = 0; - const TValue *o = index2value(L, idx); - int isnum = tointeger(o, &res); - if (pisnum) - *pisnum = isnum; - return res; -} - - -LUA_API int lua_toboolean (lua_State *L, int idx) { - const TValue *o = index2value(L, idx); - return !l_isfalse(o); -} - - -LUA_API const char *lua_tolstring (lua_State *L, int idx, size_t *len) { - TValue *o; - lua_lock(L); - o = index2value(L, idx); - if (!ttisstring(o)) { - if (!cvt2str(o)) { /* not convertible? */ - if (len != NULL) *len = 0; - lua_unlock(L); - return NULL; - } - luaO_tostring(L, o); - luaC_checkGC(L); - o = index2value(L, idx); /* previous call may reallocate the stack */ - } - if (len != NULL) - *len = vslen(o); - lua_unlock(L); - return svalue(o); -} - - -LUA_API lua_Unsigned lua_rawlen (lua_State *L, int idx) { - const TValue *o = index2value(L, idx); - switch (ttypetag(o)) { - case LUA_VSHRSTR: return tsvalue(o)->shrlen; - case LUA_VLNGSTR: return tsvalue(o)->u.lnglen; - case LUA_VUSERDATA: return uvalue(o)->len; - case LUA_VTABLE: return luaH_getn(hvalue(o)); - default: return 0; - } -} - - -LUA_API lua_CFunction lua_tocfunction (lua_State *L, int idx) { - const TValue *o = index2value(L, idx); - if (ttislcf(o)) return fvalue(o); - else if (ttisCclosure(o)) - return clCvalue(o)->f; - else return NULL; /* not a C function */ -} - - -l_sinline void *touserdata (const TValue *o) { - switch (ttype(o)) { - case LUA_TUSERDATA: return getudatamem(uvalue(o)); - case LUA_TLIGHTUSERDATA: return pvalue(o); - default: return NULL; - } -} - - -LUA_API void *lua_touserdata (lua_State *L, int idx) { - const TValue *o = index2value(L, idx); - return touserdata(o); -} - - -LUA_API lua_State *lua_tothread (lua_State *L, int idx) { - const TValue *o = index2value(L, idx); - return (!ttisthread(o)) ? NULL : thvalue(o); -} - - -/* -** Returns a pointer to the internal representation of an object. -** Note that ANSI C does not allow the conversion of a pointer to -** function to a 'void*', so the conversion here goes through -** a 'size_t'. (As the returned pointer is only informative, this -** conversion should not be a problem.) -*/ -LUA_API const void *lua_topointer (lua_State *L, int idx) { - const TValue *o = index2value(L, idx); - switch (ttypetag(o)) { - case LUA_VLCF: return cast_voidp(cast_sizet(fvalue(o))); - case LUA_VUSERDATA: case LUA_VLIGHTUSERDATA: - return touserdata(o); - default: { - if (iscollectable(o)) - return gcvalue(o); - else - return NULL; - } - } -} - - - -/* -** push functions (C -> stack) -*/ - - -LUA_API void lua_pushnil (lua_State *L) { - lua_lock(L); - setnilvalue(s2v(L->top.p)); - api_incr_top(L); - lua_unlock(L); -} - - -LUA_API void lua_pushnumber (lua_State *L, lua_Number n) { - lua_lock(L); - setfltvalue(s2v(L->top.p), n); - api_incr_top(L); - lua_unlock(L); -} - - -LUA_API void lua_pushinteger (lua_State *L, lua_Integer n) { - lua_lock(L); - setivalue(s2v(L->top.p), n); - api_incr_top(L); - lua_unlock(L); -} - - -/* -** Pushes on the stack a string with given length. Avoid using 's' when -** 'len' == 0 (as 's' can be NULL in that case), due to later use of -** 'memcmp' and 'memcpy'. -*/ -LUA_API const char *lua_pushlstring (lua_State *L, const char *s, size_t len) { - TString *ts; - lua_lock(L); - ts = (len == 0) ? luaS_new(L, "") : luaS_newlstr(L, s, len); - setsvalue2s(L, L->top.p, ts); - api_incr_top(L); - luaC_checkGC(L); - lua_unlock(L); - return getstr(ts); -} - - -LUA_API const char *lua_pushstring (lua_State *L, const char *s) { - lua_lock(L); - if (s == NULL) - setnilvalue(s2v(L->top.p)); - else { - TString *ts; - ts = luaS_new(L, s); - setsvalue2s(L, L->top.p, ts); - s = getstr(ts); /* internal copy's address */ - } - api_incr_top(L); - luaC_checkGC(L); - lua_unlock(L); - return s; -} - - -LUA_API const char *lua_pushvfstring (lua_State *L, const char *fmt, - va_list argp) { - const char *ret; - lua_lock(L); - ret = luaO_pushvfstring(L, fmt, argp); - luaC_checkGC(L); - lua_unlock(L); - return ret; -} - - -LUA_API const char *lua_pushfstring (lua_State *L, const char *fmt, ...) { - const char *ret; - va_list argp; - lua_lock(L); - va_start(argp, fmt); - ret = luaO_pushvfstring(L, fmt, argp); - va_end(argp); - luaC_checkGC(L); - lua_unlock(L); - return ret; -} - - -LUA_API void lua_pushcclosure (lua_State *L, lua_CFunction fn, int n) { - lua_lock(L); - if (n == 0) { - setfvalue(s2v(L->top.p), fn); - api_incr_top(L); - } - else { - CClosure *cl; - api_checknelems(L, n); - api_check(L, n <= MAXUPVAL, "upvalue index too large"); - cl = luaF_newCclosure(L, n); - cl->f = fn; - L->top.p -= n; - while (n--) { - setobj2n(L, &cl->upvalue[n], s2v(L->top.p + n)); - /* does not need barrier because closure is white */ - lua_assert(iswhite(cl)); - } - setclCvalue(L, s2v(L->top.p), cl); - api_incr_top(L); - luaC_checkGC(L); - } - lua_unlock(L); -} - - -LUA_API void lua_pushboolean (lua_State *L, int b) { - lua_lock(L); - if (b) - setbtvalue(s2v(L->top.p)); - else - setbfvalue(s2v(L->top.p)); - api_incr_top(L); - lua_unlock(L); -} - - -LUA_API void lua_pushlightuserdata (lua_State *L, void *p) { - lua_lock(L); - setpvalue(s2v(L->top.p), p); - api_incr_top(L); - lua_unlock(L); -} - - -LUA_API int lua_pushthread (lua_State *L) { - lua_lock(L); - setthvalue(L, s2v(L->top.p), L); - api_incr_top(L); - lua_unlock(L); - return (G(L)->mainthread == L); -} - - - -/* -** get functions (Lua -> stack) -*/ - - -l_sinline int auxgetstr (lua_State *L, const TValue *t, const char *k) { - const TValue *slot; - TString *str = luaS_new(L, k); - if (luaV_fastget(L, t, str, slot, luaH_getstr)) { - setobj2s(L, L->top.p, slot); - api_incr_top(L); - } - else { - setsvalue2s(L, L->top.p, str); - api_incr_top(L); - luaV_finishget(L, t, s2v(L->top.p - 1), L->top.p - 1, slot); - } - lua_unlock(L); - return ttype(s2v(L->top.p - 1)); -} - - -/* -** Get the global table in the registry. Since all predefined -** indices in the registry were inserted right when the registry -** was created and never removed, they must always be in the array -** part of the registry. -*/ -#define getGtable(L) \ - (&hvalue(&G(L)->l_registry)->array[LUA_RIDX_GLOBALS - 1]) - - -LUA_API int lua_getglobal (lua_State *L, const char *name) { - const TValue *G; - lua_lock(L); - G = getGtable(L); - return auxgetstr(L, G, name); -} - - -LUA_API int lua_gettable (lua_State *L, int idx) { - const TValue *slot; - TValue *t; - lua_lock(L); - t = index2value(L, idx); - if (luaV_fastget(L, t, s2v(L->top.p - 1), slot, luaH_get)) { - setobj2s(L, L->top.p - 1, slot); - } - else - luaV_finishget(L, t, s2v(L->top.p - 1), L->top.p - 1, slot); - lua_unlock(L); - return ttype(s2v(L->top.p - 1)); -} - - -LUA_API int lua_getfield (lua_State *L, int idx, const char *k) { - lua_lock(L); - return auxgetstr(L, index2value(L, idx), k); -} - - -LUA_API int lua_geti (lua_State *L, int idx, lua_Integer n) { - TValue *t; - const TValue *slot; - lua_lock(L); - t = index2value(L, idx); - if (luaV_fastgeti(L, t, n, slot)) { - setobj2s(L, L->top.p, slot); - } - else { - TValue aux; - setivalue(&aux, n); - luaV_finishget(L, t, &aux, L->top.p, slot); - } - api_incr_top(L); - lua_unlock(L); - return ttype(s2v(L->top.p - 1)); -} - - -l_sinline int finishrawget (lua_State *L, const TValue *val) { - if (isempty(val)) /* avoid copying empty items to the stack */ - setnilvalue(s2v(L->top.p)); - else - setobj2s(L, L->top.p, val); - api_incr_top(L); - lua_unlock(L); - return ttype(s2v(L->top.p - 1)); -} - - -static Table *gettable (lua_State *L, int idx) { - TValue *t = index2value(L, idx); - api_check(L, ttistable(t), "table expected"); - return hvalue(t); -} - - -LUA_API int lua_rawget (lua_State *L, int idx) { - Table *t; - const TValue *val; - lua_lock(L); - api_checknelems(L, 1); - t = gettable(L, idx); - val = luaH_get(t, s2v(L->top.p - 1)); - L->top.p--; /* remove key */ - return finishrawget(L, val); -} - - -LUA_API int lua_rawgeti (lua_State *L, int idx, lua_Integer n) { - Table *t; - lua_lock(L); - t = gettable(L, idx); - return finishrawget(L, luaH_getint(t, n)); -} - - -LUA_API int lua_rawgetp (lua_State *L, int idx, const void *p) { - Table *t; - TValue k; - lua_lock(L); - t = gettable(L, idx); - setpvalue(&k, cast_voidp(p)); - return finishrawget(L, luaH_get(t, &k)); -} - - -LUA_API void lua_createtable (lua_State *L, int narray, int nrec) { - Table *t; - lua_lock(L); - t = luaH_new(L); - sethvalue2s(L, L->top.p, t); - api_incr_top(L); - if (narray > 0 || nrec > 0) - luaH_resize(L, t, narray, nrec); - luaC_checkGC(L); - lua_unlock(L); -} - - -LUA_API int lua_getmetatable (lua_State *L, int objindex) { - const TValue *obj; - Table *mt; - int res = 0; - lua_lock(L); - obj = index2value(L, objindex); - switch (ttype(obj)) { - case LUA_TTABLE: - mt = hvalue(obj)->metatable; - break; - case LUA_TUSERDATA: - mt = uvalue(obj)->metatable; - break; - default: - mt = G(L)->mt[ttype(obj)]; - break; - } - if (mt != NULL) { - sethvalue2s(L, L->top.p, mt); - api_incr_top(L); - res = 1; - } - lua_unlock(L); - return res; -} - - -LUA_API int lua_getiuservalue (lua_State *L, int idx, int n) { - TValue *o; - int t; - lua_lock(L); - o = index2value(L, idx); - api_check(L, ttisfulluserdata(o), "full userdata expected"); - if (n <= 0 || n > uvalue(o)->nuvalue) { - setnilvalue(s2v(L->top.p)); - t = LUA_TNONE; - } - else { - setobj2s(L, L->top.p, &uvalue(o)->uv[n - 1].uv); - t = ttype(s2v(L->top.p)); - } - api_incr_top(L); - lua_unlock(L); - return t; -} - - -/* -** set functions (stack -> Lua) -*/ - -/* -** t[k] = value at the top of the stack (where 'k' is a string) -*/ -static void auxsetstr (lua_State *L, const TValue *t, const char *k) { - const TValue *slot; - TString *str = luaS_new(L, k); - api_checknelems(L, 1); - if (luaV_fastget(L, t, str, slot, luaH_getstr)) { - luaV_finishfastset(L, t, slot, s2v(L->top.p - 1)); - L->top.p--; /* pop value */ - } - else { - setsvalue2s(L, L->top.p, str); /* push 'str' (to make it a TValue) */ - api_incr_top(L); - luaV_finishset(L, t, s2v(L->top.p - 1), s2v(L->top.p - 2), slot); - L->top.p -= 2; /* pop value and key */ - } - lua_unlock(L); /* lock done by caller */ -} - - -LUA_API void lua_setglobal (lua_State *L, const char *name) { - const TValue *G; - lua_lock(L); /* unlock done in 'auxsetstr' */ - G = getGtable(L); - auxsetstr(L, G, name); -} - - -LUA_API void lua_settable (lua_State *L, int idx) { - TValue *t; - const TValue *slot; - lua_lock(L); - api_checknelems(L, 2); - t = index2value(L, idx); - if (luaV_fastget(L, t, s2v(L->top.p - 2), slot, luaH_get)) { - luaV_finishfastset(L, t, slot, s2v(L->top.p - 1)); - } - else - luaV_finishset(L, t, s2v(L->top.p - 2), s2v(L->top.p - 1), slot); - L->top.p -= 2; /* pop index and value */ - lua_unlock(L); -} - - -LUA_API void lua_setfield (lua_State *L, int idx, const char *k) { - lua_lock(L); /* unlock done in 'auxsetstr' */ - auxsetstr(L, index2value(L, idx), k); -} - - -LUA_API void lua_seti (lua_State *L, int idx, lua_Integer n) { - TValue *t; - const TValue *slot; - lua_lock(L); - api_checknelems(L, 1); - t = index2value(L, idx); - if (luaV_fastgeti(L, t, n, slot)) { - luaV_finishfastset(L, t, slot, s2v(L->top.p - 1)); - } - else { - TValue aux; - setivalue(&aux, n); - luaV_finishset(L, t, &aux, s2v(L->top.p - 1), slot); - } - L->top.p--; /* pop value */ - lua_unlock(L); -} - - -static void aux_rawset (lua_State *L, int idx, TValue *key, int n) { - Table *t; - lua_lock(L); - api_checknelems(L, n); - t = gettable(L, idx); - luaH_set(L, t, key, s2v(L->top.p - 1)); - invalidateTMcache(t); - luaC_barrierback(L, obj2gco(t), s2v(L->top.p - 1)); - L->top.p -= n; - lua_unlock(L); -} - - -LUA_API void lua_rawset (lua_State *L, int idx) { - aux_rawset(L, idx, s2v(L->top.p - 2), 2); -} - - -LUA_API void lua_rawsetp (lua_State *L, int idx, const void *p) { - TValue k; - setpvalue(&k, cast_voidp(p)); - aux_rawset(L, idx, &k, 1); -} - - -LUA_API void lua_rawseti (lua_State *L, int idx, lua_Integer n) { - Table *t; - lua_lock(L); - api_checknelems(L, 1); - t = gettable(L, idx); - luaH_setint(L, t, n, s2v(L->top.p - 1)); - luaC_barrierback(L, obj2gco(t), s2v(L->top.p - 1)); - L->top.p--; - lua_unlock(L); -} - - -LUA_API int lua_setmetatable (lua_State *L, int objindex) { - TValue *obj; - Table *mt; - lua_lock(L); - api_checknelems(L, 1); - obj = index2value(L, objindex); - if (ttisnil(s2v(L->top.p - 1))) - mt = NULL; - else { - api_check(L, ttistable(s2v(L->top.p - 1)), "table expected"); - mt = hvalue(s2v(L->top.p - 1)); - } - switch (ttype(obj)) { - case LUA_TTABLE: { - hvalue(obj)->metatable = mt; - if (mt) { - luaC_objbarrier(L, gcvalue(obj), mt); - luaC_checkfinalizer(L, gcvalue(obj), mt); - } - break; - } - case LUA_TUSERDATA: { - uvalue(obj)->metatable = mt; - if (mt) { - luaC_objbarrier(L, uvalue(obj), mt); - luaC_checkfinalizer(L, gcvalue(obj), mt); - } - break; - } - default: { - G(L)->mt[ttype(obj)] = mt; - break; - } - } - L->top.p--; - lua_unlock(L); - return 1; -} - - -LUA_API int lua_setiuservalue (lua_State *L, int idx, int n) { - TValue *o; - int res; - lua_lock(L); - api_checknelems(L, 1); - o = index2value(L, idx); - api_check(L, ttisfulluserdata(o), "full userdata expected"); - if (!(cast_uint(n) - 1u < cast_uint(uvalue(o)->nuvalue))) - res = 0; /* 'n' not in [1, uvalue(o)->nuvalue] */ - else { - setobj(L, &uvalue(o)->uv[n - 1].uv, s2v(L->top.p - 1)); - luaC_barrierback(L, gcvalue(o), s2v(L->top.p - 1)); - res = 1; - } - L->top.p--; - lua_unlock(L); - return res; -} - - -/* -** 'load' and 'call' functions (run Lua code) -*/ - - -#define checkresults(L,na,nr) \ - api_check(L, (nr) == LUA_MULTRET \ - || (L->ci->top.p - L->top.p >= (nr) - (na)), \ - "results from function overflow current stack size") - - -LUA_API void lua_callk (lua_State *L, int nargs, int nresults, - lua_KContext ctx, lua_KFunction k) { - StkId func; - lua_lock(L); - api_check(L, k == NULL || !isLua(L->ci), - "cannot use continuations inside hooks"); - api_checknelems(L, nargs+1); - api_check(L, L->status == LUA_OK, "cannot do calls on non-normal thread"); - checkresults(L, nargs, nresults); - func = L->top.p - (nargs+1); - if (k != NULL && yieldable(L)) { /* need to prepare continuation? */ - L->ci->u.c.k = k; /* save continuation */ - L->ci->u.c.ctx = ctx; /* save context */ - luaD_call(L, func, nresults); /* do the call */ - } - else /* no continuation or no yieldable */ - luaD_callnoyield(L, func, nresults); /* just do the call */ - adjustresults(L, nresults); - lua_unlock(L); -} - - - -/* -** Execute a protected call. -*/ -struct CallS { /* data to 'f_call' */ - StkId func; - int nresults; -}; - - -static void f_call (lua_State *L, void *ud) { - struct CallS *c = cast(struct CallS *, ud); - luaD_callnoyield(L, c->func, c->nresults); -} - - - -LUA_API int lua_pcallk (lua_State *L, int nargs, int nresults, int errfunc, - lua_KContext ctx, lua_KFunction k) { - struct CallS c; - int status; - ptrdiff_t func; - lua_lock(L); - api_check(L, k == NULL || !isLua(L->ci), - "cannot use continuations inside hooks"); - api_checknelems(L, nargs+1); - api_check(L, L->status == LUA_OK, "cannot do calls on non-normal thread"); - checkresults(L, nargs, nresults); - if (errfunc == 0) - func = 0; - else { - StkId o = index2stack(L, errfunc); - api_check(L, ttisfunction(s2v(o)), "error handler must be a function"); - func = savestack(L, o); - } - c.func = L->top.p - (nargs+1); /* function to be called */ - if (k == NULL || !yieldable(L)) { /* no continuation or no yieldable? */ - c.nresults = nresults; /* do a 'conventional' protected call */ - status = luaD_pcall(L, f_call, &c, savestack(L, c.func), func); - } - else { /* prepare continuation (call is already protected by 'resume') */ - CallInfo *ci = L->ci; - ci->u.c.k = k; /* save continuation */ - ci->u.c.ctx = ctx; /* save context */ - /* save information for error recovery */ - ci->u2.funcidx = cast_int(savestack(L, c.func)); - ci->u.c.old_errfunc = L->errfunc; - L->errfunc = func; - setoah(ci->callstatus, L->allowhook); /* save value of 'allowhook' */ - ci->callstatus |= CIST_YPCALL; /* function can do error recovery */ - luaD_call(L, c.func, nresults); /* do the call */ - ci->callstatus &= ~CIST_YPCALL; - L->errfunc = ci->u.c.old_errfunc; - status = LUA_OK; /* if it is here, there were no errors */ - } - adjustresults(L, nresults); - lua_unlock(L); - return status; -} - - -LUA_API int lua_load (lua_State *L, lua_Reader reader, void *data, - const char *chunkname, const char *mode) { - ZIO z; - int status; - lua_lock(L); - if (!chunkname) chunkname = "?"; - luaZ_init(L, &z, reader, data); - status = luaD_protectedparser(L, &z, chunkname, mode); - if (status == LUA_OK) { /* no errors? */ - LClosure *f = clLvalue(s2v(L->top.p - 1)); /* get new function */ - if (f->nupvalues >= 1) { /* does it have an upvalue? */ - /* get global table from registry */ - const TValue *gt = getGtable(L); - /* set global table as 1st upvalue of 'f' (may be LUA_ENV) */ - setobj(L, f->upvals[0]->v.p, gt); - luaC_barrier(L, f->upvals[0], gt); - } - } - lua_unlock(L); - return status; -} - - -LUA_API int lua_dump (lua_State *L, lua_Writer writer, void *data, int strip) { - int status; - TValue *o; - lua_lock(L); - api_checknelems(L, 1); - o = s2v(L->top.p - 1); - if (isLfunction(o)) - status = luaU_dump(L, getproto(o), writer, data, strip); - else - status = 1; - lua_unlock(L); - return status; -} - - -LUA_API int lua_status (lua_State *L) { - return L->status; -} - - -/* -** Garbage-collection function -*/ -LUA_API int lua_gc (lua_State *L, int what, ...) { - va_list argp; - int res = 0; - global_State *g = G(L); - if (g->gcstp & GCSTPGC) /* internal stop? */ - return -1; /* all options are invalid when stopped */ - lua_lock(L); - va_start(argp, what); - switch (what) { - case LUA_GCSTOP: { - g->gcstp = GCSTPUSR; /* stopped by the user */ - break; - } - case LUA_GCRESTART: { - luaE_setdebt(g, 0); - g->gcstp = 0; /* (GCSTPGC must be already zero here) */ - break; - } - case LUA_GCCOLLECT: { - luaC_fullgc(L, 0); - break; - } - case LUA_GCCOUNT: { - /* GC values are expressed in Kbytes: #bytes/2^10 */ - res = cast_int(gettotalbytes(g) >> 10); - break; - } - case LUA_GCCOUNTB: { - res = cast_int(gettotalbytes(g) & 0x3ff); - break; - } - case LUA_GCSTEP: { - int data = va_arg(argp, int); - l_mem debt = 1; /* =1 to signal that it did an actual step */ - lu_byte oldstp = g->gcstp; - g->gcstp = 0; /* allow GC to run (GCSTPGC must be zero here) */ - if (data == 0) { - luaE_setdebt(g, 0); /* do a basic step */ - luaC_step(L); - } - else { /* add 'data' to total debt */ - debt = cast(l_mem, data) * 1024 + g->GCdebt; - luaE_setdebt(g, debt); - luaC_checkGC(L); - } - g->gcstp = oldstp; /* restore previous state */ - if (debt > 0 && g->gcstate == GCSpause) /* end of cycle? */ - res = 1; /* signal it */ - break; - } - case LUA_GCSETPAUSE: { - int data = va_arg(argp, int); - res = getgcparam(g->gcpause); - setgcparam(g->gcpause, data); - break; - } - case LUA_GCSETSTEPMUL: { - int data = va_arg(argp, int); - res = getgcparam(g->gcstepmul); - setgcparam(g->gcstepmul, data); - break; - } - case LUA_GCISRUNNING: { - res = gcrunning(g); - break; - } - case LUA_GCGEN: { - int minormul = va_arg(argp, int); - int majormul = va_arg(argp, int); - res = isdecGCmodegen(g) ? LUA_GCGEN : LUA_GCINC; - if (minormul != 0) - g->genminormul = minormul; - if (majormul != 0) - setgcparam(g->genmajormul, majormul); - luaC_changemode(L, KGC_GEN); - break; - } - case LUA_GCINC: { - int pause = va_arg(argp, int); - int stepmul = va_arg(argp, int); - int stepsize = va_arg(argp, int); - res = isdecGCmodegen(g) ? LUA_GCGEN : LUA_GCINC; - if (pause != 0) - setgcparam(g->gcpause, pause); - if (stepmul != 0) - setgcparam(g->gcstepmul, stepmul); - if (stepsize != 0) - g->gcstepsize = stepsize; - luaC_changemode(L, KGC_INC); - break; - } - default: res = -1; /* invalid option */ - } - va_end(argp); - lua_unlock(L); - return res; -} - - - -/* -** miscellaneous functions -*/ - - -LUA_API int lua_error (lua_State *L) { - TValue *errobj; - lua_lock(L); - errobj = s2v(L->top.p - 1); - api_checknelems(L, 1); - /* error object is the memory error message? */ - if (ttisshrstring(errobj) && eqshrstr(tsvalue(errobj), G(L)->memerrmsg)) - luaM_error(L); /* raise a memory error */ - else - luaG_errormsg(L); /* raise a regular error */ - /* code unreachable; will unlock when control actually leaves the kernel */ - return 0; /* to avoid warnings */ -} - - -LUA_API int lua_next (lua_State *L, int idx) { - Table *t; - int more; - lua_lock(L); - api_checknelems(L, 1); - t = gettable(L, idx); - more = luaH_next(L, t, L->top.p - 1); - if (more) { - api_incr_top(L); - } - else /* no more elements */ - L->top.p -= 1; /* remove key */ - lua_unlock(L); - return more; -} - - -LUA_API void lua_toclose (lua_State *L, int idx) { - int nresults; - StkId o; - lua_lock(L); - o = index2stack(L, idx); - nresults = L->ci->nresults; - api_check(L, L->tbclist.p < o, "given index below or equal a marked one"); - luaF_newtbcupval(L, o); /* create new to-be-closed upvalue */ - if (!hastocloseCfunc(nresults)) /* function not marked yet? */ - L->ci->nresults = codeNresults(nresults); /* mark it */ - lua_assert(hastocloseCfunc(L->ci->nresults)); - lua_unlock(L); -} - - -LUA_API void lua_concat (lua_State *L, int n) { - lua_lock(L); - api_checknelems(L, n); - if (n > 0) - luaV_concat(L, n); - else { /* nothing to concatenate */ - setsvalue2s(L, L->top.p, luaS_newlstr(L, "", 0)); /* push empty string */ - api_incr_top(L); - } - luaC_checkGC(L); - lua_unlock(L); -} - - -LUA_API void lua_len (lua_State *L, int idx) { - TValue *t; - lua_lock(L); - t = index2value(L, idx); - luaV_objlen(L, L->top.p, t); - api_incr_top(L); - lua_unlock(L); -} - - -LUA_API lua_Alloc lua_getallocf (lua_State *L, void **ud) { - lua_Alloc f; - lua_lock(L); - if (ud) *ud = G(L)->ud; - f = G(L)->frealloc; - lua_unlock(L); - return f; -} - - -LUA_API void lua_setallocf (lua_State *L, lua_Alloc f, void *ud) { - lua_lock(L); - G(L)->ud = ud; - G(L)->frealloc = f; - lua_unlock(L); -} - - -void lua_setwarnf (lua_State *L, lua_WarnFunction f, void *ud) { - lua_lock(L); - G(L)->ud_warn = ud; - G(L)->warnf = f; - lua_unlock(L); -} - - -void lua_warning (lua_State *L, const char *msg, int tocont) { - lua_lock(L); - luaE_warning(L, msg, tocont); - lua_unlock(L); -} - - - -LUA_API void *lua_newuserdatauv (lua_State *L, size_t size, int nuvalue) { - Udata *u; - lua_lock(L); - api_check(L, 0 <= nuvalue && nuvalue < USHRT_MAX, "invalid value"); - u = luaS_newudata(L, size, nuvalue); - setuvalue(L, s2v(L->top.p), u); - api_incr_top(L); - luaC_checkGC(L); - lua_unlock(L); - return getudatamem(u); -} - - - -static const char *aux_upvalue (TValue *fi, int n, TValue **val, - GCObject **owner) { - switch (ttypetag(fi)) { - case LUA_VCCL: { /* C closure */ - CClosure *f = clCvalue(fi); - if (!(cast_uint(n) - 1u < cast_uint(f->nupvalues))) - return NULL; /* 'n' not in [1, f->nupvalues] */ - *val = &f->upvalue[n-1]; - if (owner) *owner = obj2gco(f); - return ""; - } - case LUA_VLCL: { /* Lua closure */ - LClosure *f = clLvalue(fi); - TString *name; - Proto *p = f->p; - if (!(cast_uint(n) - 1u < cast_uint(p->sizeupvalues))) - return NULL; /* 'n' not in [1, p->sizeupvalues] */ - *val = f->upvals[n-1]->v.p; - if (owner) *owner = obj2gco(f->upvals[n - 1]); - name = p->upvalues[n-1].name; - return (name == NULL) ? "(no name)" : getstr(name); - } - default: return NULL; /* not a closure */ - } -} - - -LUA_API const char *lua_getupvalue (lua_State *L, int funcindex, int n) { - const char *name; - TValue *val = NULL; /* to avoid warnings */ - lua_lock(L); - name = aux_upvalue(index2value(L, funcindex), n, &val, NULL); - if (name) { - setobj2s(L, L->top.p, val); - api_incr_top(L); - } - lua_unlock(L); - return name; -} - - -LUA_API const char *lua_setupvalue (lua_State *L, int funcindex, int n) { - const char *name; - TValue *val = NULL; /* to avoid warnings */ - GCObject *owner = NULL; /* to avoid warnings */ - TValue *fi; - lua_lock(L); - fi = index2value(L, funcindex); - api_checknelems(L, 1); - name = aux_upvalue(fi, n, &val, &owner); - if (name) { - L->top.p--; - setobj(L, val, s2v(L->top.p)); - luaC_barrier(L, owner, val); - } - lua_unlock(L); - return name; -} - - -static UpVal **getupvalref (lua_State *L, int fidx, int n, LClosure **pf) { - static const UpVal *const nullup = NULL; - LClosure *f; - TValue *fi = index2value(L, fidx); - api_check(L, ttisLclosure(fi), "Lua function expected"); - f = clLvalue(fi); - if (pf) *pf = f; - if (1 <= n && n <= f->p->sizeupvalues) - return &f->upvals[n - 1]; /* get its upvalue pointer */ - else - return (UpVal**)&nullup; -} - - -LUA_API void *lua_upvalueid (lua_State *L, int fidx, int n) { - TValue *fi = index2value(L, fidx); - switch (ttypetag(fi)) { - case LUA_VLCL: { /* lua closure */ - return *getupvalref(L, fidx, n, NULL); - } - case LUA_VCCL: { /* C closure */ - CClosure *f = clCvalue(fi); - if (1 <= n && n <= f->nupvalues) - return &f->upvalue[n - 1]; - /* else */ - } /* FALLTHROUGH */ - case LUA_VLCF: - return NULL; /* light C functions have no upvalues */ - default: { - api_check(L, 0, "function expected"); - return NULL; - } - } -} - - -LUA_API void lua_upvaluejoin (lua_State *L, int fidx1, int n1, - int fidx2, int n2) { - LClosure *f1; - UpVal **up1 = getupvalref(L, fidx1, n1, &f1); - UpVal **up2 = getupvalref(L, fidx2, n2, NULL); - api_check(L, *up1 != NULL && *up2 != NULL, "invalid upvalue index"); - *up1 = *up2; - luaC_objbarrier(L, f1, *up1); -} - - diff --git a/lib/lua-5.4/src/lapi.h b/lib/lua-5.4/src/lapi.h deleted file mode 100644 index a742427..0000000 --- a/lib/lua-5.4/src/lapi.h +++ /dev/null @@ -1,52 +0,0 @@ -/* -** $Id: lapi.h $ -** Auxiliary functions from Lua API -** See Copyright Notice in lua.h -*/ - -#ifndef lapi_h -#define lapi_h - - -#include "llimits.h" -#include "lstate.h" - - -/* Increments 'L->top.p', checking for stack overflows */ -#define api_incr_top(L) {L->top.p++; \ - api_check(L, L->top.p <= L->ci->top.p, \ - "stack overflow");} - - -/* -** If a call returns too many multiple returns, the callee may not have -** stack space to accommodate all results. In this case, this macro -** increases its stack space ('L->ci->top.p'). -*/ -#define adjustresults(L,nres) \ - { if ((nres) <= LUA_MULTRET && L->ci->top.p < L->top.p) \ - L->ci->top.p = L->top.p; } - - -/* Ensure the stack has at least 'n' elements */ -#define api_checknelems(L,n) \ - api_check(L, (n) < (L->top.p - L->ci->func.p), \ - "not enough elements in the stack") - - -/* -** To reduce the overhead of returning from C functions, the presence of -** to-be-closed variables in these functions is coded in the CallInfo's -** field 'nresults', in a way that functions with no to-be-closed variables -** with zero, one, or "all" wanted results have no overhead. Functions -** with other number of wanted results, as well as functions with -** variables to be closed, have an extra check. -*/ - -#define hastocloseCfunc(n) ((n) < LUA_MULTRET) - -/* Map [-1, inf) (range of 'nresults') into (-inf, -2] */ -#define codeNresults(n) (-(n) - 3) -#define decodeNresults(n) (-(n) - 3) - -#endif diff --git a/lib/lua-5.4/src/lauxlib.c b/lib/lua-5.4/src/lauxlib.c deleted file mode 100644 index 4ca6c65..0000000 --- a/lib/lua-5.4/src/lauxlib.c +++ /dev/null @@ -1,1112 +0,0 @@ -/* -** $Id: lauxlib.c $ -** Auxiliary functions for building Lua libraries -** See Copyright Notice in lua.h -*/ - -#define lauxlib_c -#define LUA_LIB - -#include "lprefix.h" - - -#include -#include -#include -#include -#include - - -/* -** This file uses only the official API of Lua. -** Any function declared here could be written as an application function. -*/ - -#include "lua.h" - -#include "lauxlib.h" - - -#if !defined(MAX_SIZET) -/* maximum value for size_t */ -#define MAX_SIZET ((size_t)(~(size_t)0)) -#endif - - -/* -** {====================================================== -** Traceback -** ======================================================= -*/ - - -#define LEVELS1 10 /* size of the first part of the stack */ -#define LEVELS2 11 /* size of the second part of the stack */ - - - -/* -** Search for 'objidx' in table at index -1. ('objidx' must be an -** absolute index.) Return 1 + string at top if it found a good name. -*/ -static int findfield (lua_State *L, int objidx, int level) { - if (level == 0 || !lua_istable(L, -1)) - return 0; /* not found */ - lua_pushnil(L); /* start 'next' loop */ - while (lua_next(L, -2)) { /* for each pair in table */ - if (lua_type(L, -2) == LUA_TSTRING) { /* ignore non-string keys */ - if (lua_rawequal(L, objidx, -1)) { /* found object? */ - lua_pop(L, 1); /* remove value (but keep name) */ - return 1; - } - else if (findfield(L, objidx, level - 1)) { /* try recursively */ - /* stack: lib_name, lib_table, field_name (top) */ - lua_pushliteral(L, "."); /* place '.' between the two names */ - lua_replace(L, -3); /* (in the slot occupied by table) */ - lua_concat(L, 3); /* lib_name.field_name */ - return 1; - } - } - lua_pop(L, 1); /* remove value */ - } - return 0; /* not found */ -} - - -/* -** Search for a name for a function in all loaded modules -*/ -static int pushglobalfuncname (lua_State *L, lua_Debug *ar) { - int top = lua_gettop(L); - lua_getinfo(L, "f", ar); /* push function */ - lua_getfield(L, LUA_REGISTRYINDEX, LUA_LOADED_TABLE); - if (findfield(L, top + 1, 2)) { - const char *name = lua_tostring(L, -1); - if (strncmp(name, LUA_GNAME ".", 3) == 0) { /* name start with '_G.'? */ - lua_pushstring(L, name + 3); /* push name without prefix */ - lua_remove(L, -2); /* remove original name */ - } - lua_copy(L, -1, top + 1); /* copy name to proper place */ - lua_settop(L, top + 1); /* remove table "loaded" and name copy */ - return 1; - } - else { - lua_settop(L, top); /* remove function and global table */ - return 0; - } -} - - -static void pushfuncname (lua_State *L, lua_Debug *ar) { - if (pushglobalfuncname(L, ar)) { /* try first a global name */ - lua_pushfstring(L, "function '%s'", lua_tostring(L, -1)); - lua_remove(L, -2); /* remove name */ - } - else if (*ar->namewhat != '\0') /* is there a name from code? */ - lua_pushfstring(L, "%s '%s'", ar->namewhat, ar->name); /* use it */ - else if (*ar->what == 'm') /* main? */ - lua_pushliteral(L, "main chunk"); - else if (*ar->what != 'C') /* for Lua functions, use */ - lua_pushfstring(L, "function <%s:%d>", ar->short_src, ar->linedefined); - else /* nothing left... */ - lua_pushliteral(L, "?"); -} - - -static int lastlevel (lua_State *L) { - lua_Debug ar; - int li = 1, le = 1; - /* find an upper bound */ - while (lua_getstack(L, le, &ar)) { li = le; le *= 2; } - /* do a binary search */ - while (li < le) { - int m = (li + le)/2; - if (lua_getstack(L, m, &ar)) li = m + 1; - else le = m; - } - return le - 1; -} - - -LUALIB_API void luaL_traceback (lua_State *L, lua_State *L1, - const char *msg, int level) { - luaL_Buffer b; - lua_Debug ar; - int last = lastlevel(L1); - int limit2show = (last - level > LEVELS1 + LEVELS2) ? LEVELS1 : -1; - luaL_buffinit(L, &b); - if (msg) { - luaL_addstring(&b, msg); - luaL_addchar(&b, '\n'); - } - luaL_addstring(&b, "stack traceback:"); - while (lua_getstack(L1, level++, &ar)) { - if (limit2show-- == 0) { /* too many levels? */ - int n = last - level - LEVELS2 + 1; /* number of levels to skip */ - lua_pushfstring(L, "\n\t...\t(skipping %d levels)", n); - luaL_addvalue(&b); /* add warning about skip */ - level += n; /* and skip to last levels */ - } - else { - lua_getinfo(L1, "Slnt", &ar); - if (ar.currentline <= 0) - lua_pushfstring(L, "\n\t%s: in ", ar.short_src); - else - lua_pushfstring(L, "\n\t%s:%d: in ", ar.short_src, ar.currentline); - luaL_addvalue(&b); - pushfuncname(L, &ar); - luaL_addvalue(&b); - if (ar.istailcall) - luaL_addstring(&b, "\n\t(...tail calls...)"); - } - } - luaL_pushresult(&b); -} - -/* }====================================================== */ - - -/* -** {====================================================== -** Error-report functions -** ======================================================= -*/ - -LUALIB_API int luaL_argerror (lua_State *L, int arg, const char *extramsg) { - lua_Debug ar; - if (!lua_getstack(L, 0, &ar)) /* no stack frame? */ - return luaL_error(L, "bad argument #%d (%s)", arg, extramsg); - lua_getinfo(L, "n", &ar); - if (strcmp(ar.namewhat, "method") == 0) { - arg--; /* do not count 'self' */ - if (arg == 0) /* error is in the self argument itself? */ - return luaL_error(L, "calling '%s' on bad self (%s)", - ar.name, extramsg); - } - if (ar.name == NULL) - ar.name = (pushglobalfuncname(L, &ar)) ? lua_tostring(L, -1) : "?"; - return luaL_error(L, "bad argument #%d to '%s' (%s)", - arg, ar.name, extramsg); -} - - -LUALIB_API int luaL_typeerror (lua_State *L, int arg, const char *tname) { - const char *msg; - const char *typearg; /* name for the type of the actual argument */ - if (luaL_getmetafield(L, arg, "__name") == LUA_TSTRING) - typearg = lua_tostring(L, -1); /* use the given type name */ - else if (lua_type(L, arg) == LUA_TLIGHTUSERDATA) - typearg = "light userdata"; /* special name for messages */ - else - typearg = luaL_typename(L, arg); /* standard name */ - msg = lua_pushfstring(L, "%s expected, got %s", tname, typearg); - return luaL_argerror(L, arg, msg); -} - - -static void tag_error (lua_State *L, int arg, int tag) { - luaL_typeerror(L, arg, lua_typename(L, tag)); -} - - -/* -** The use of 'lua_pushfstring' ensures this function does not -** need reserved stack space when called. -*/ -LUALIB_API void luaL_where (lua_State *L, int level) { - lua_Debug ar; - if (lua_getstack(L, level, &ar)) { /* check function at level */ - lua_getinfo(L, "Sl", &ar); /* get info about it */ - if (ar.currentline > 0) { /* is there info? */ - lua_pushfstring(L, "%s:%d: ", ar.short_src, ar.currentline); - return; - } - } - lua_pushfstring(L, ""); /* else, no information available... */ -} - - -/* -** Again, the use of 'lua_pushvfstring' ensures this function does -** not need reserved stack space when called. (At worst, it generates -** an error with "stack overflow" instead of the given message.) -*/ -LUALIB_API int luaL_error (lua_State *L, const char *fmt, ...) { - va_list argp; - va_start(argp, fmt); - luaL_where(L, 1); - lua_pushvfstring(L, fmt, argp); - va_end(argp); - lua_concat(L, 2); - return lua_error(L); -} - - -LUALIB_API int luaL_fileresult (lua_State *L, int stat, const char *fname) { - int en = errno; /* calls to Lua API may change this value */ - if (stat) { - lua_pushboolean(L, 1); - return 1; - } - else { - luaL_pushfail(L); - if (fname) - lua_pushfstring(L, "%s: %s", fname, strerror(en)); - else - lua_pushstring(L, strerror(en)); - lua_pushinteger(L, en); - return 3; - } -} - - -#if !defined(l_inspectstat) /* { */ - -#if defined(LUA_USE_POSIX) - -#include - -/* -** use appropriate macros to interpret 'pclose' return status -*/ -#define l_inspectstat(stat,what) \ - if (WIFEXITED(stat)) { stat = WEXITSTATUS(stat); } \ - else if (WIFSIGNALED(stat)) { stat = WTERMSIG(stat); what = "signal"; } - -#else - -#define l_inspectstat(stat,what) /* no op */ - -#endif - -#endif /* } */ - - -LUALIB_API int luaL_execresult (lua_State *L, int stat) { - if (stat != 0 && errno != 0) /* error with an 'errno'? */ - return luaL_fileresult(L, 0, NULL); - else { - const char *what = "exit"; /* type of termination */ - l_inspectstat(stat, what); /* interpret result */ - if (*what == 'e' && stat == 0) /* successful termination? */ - lua_pushboolean(L, 1); - else - luaL_pushfail(L); - lua_pushstring(L, what); - lua_pushinteger(L, stat); - return 3; /* return true/fail,what,code */ - } -} - -/* }====================================================== */ - - - -/* -** {====================================================== -** Userdata's metatable manipulation -** ======================================================= -*/ - -LUALIB_API int luaL_newmetatable (lua_State *L, const char *tname) { - if (luaL_getmetatable(L, tname) != LUA_TNIL) /* name already in use? */ - return 0; /* leave previous value on top, but return 0 */ - lua_pop(L, 1); - lua_createtable(L, 0, 2); /* create metatable */ - lua_pushstring(L, tname); - lua_setfield(L, -2, "__name"); /* metatable.__name = tname */ - lua_pushvalue(L, -1); - lua_setfield(L, LUA_REGISTRYINDEX, tname); /* registry.name = metatable */ - return 1; -} - - -LUALIB_API void luaL_setmetatable (lua_State *L, const char *tname) { - luaL_getmetatable(L, tname); - lua_setmetatable(L, -2); -} - - -LUALIB_API void *luaL_testudata (lua_State *L, int ud, const char *tname) { - void *p = lua_touserdata(L, ud); - if (p != NULL) { /* value is a userdata? */ - if (lua_getmetatable(L, ud)) { /* does it have a metatable? */ - luaL_getmetatable(L, tname); /* get correct metatable */ - if (!lua_rawequal(L, -1, -2)) /* not the same? */ - p = NULL; /* value is a userdata with wrong metatable */ - lua_pop(L, 2); /* remove both metatables */ - return p; - } - } - return NULL; /* value is not a userdata with a metatable */ -} - - -LUALIB_API void *luaL_checkudata (lua_State *L, int ud, const char *tname) { - void *p = luaL_testudata(L, ud, tname); - luaL_argexpected(L, p != NULL, ud, tname); - return p; -} - -/* }====================================================== */ - - -/* -** {====================================================== -** Argument check functions -** ======================================================= -*/ - -LUALIB_API int luaL_checkoption (lua_State *L, int arg, const char *def, - const char *const lst[]) { - const char *name = (def) ? luaL_optstring(L, arg, def) : - luaL_checkstring(L, arg); - int i; - for (i=0; lst[i]; i++) - if (strcmp(lst[i], name) == 0) - return i; - return luaL_argerror(L, arg, - lua_pushfstring(L, "invalid option '%s'", name)); -} - - -/* -** Ensures the stack has at least 'space' extra slots, raising an error -** if it cannot fulfill the request. (The error handling needs a few -** extra slots to format the error message. In case of an error without -** this extra space, Lua will generate the same 'stack overflow' error, -** but without 'msg'.) -*/ -LUALIB_API void luaL_checkstack (lua_State *L, int space, const char *msg) { - if (l_unlikely(!lua_checkstack(L, space))) { - if (msg) - luaL_error(L, "stack overflow (%s)", msg); - else - luaL_error(L, "stack overflow"); - } -} - - -LUALIB_API void luaL_checktype (lua_State *L, int arg, int t) { - if (l_unlikely(lua_type(L, arg) != t)) - tag_error(L, arg, t); -} - - -LUALIB_API void luaL_checkany (lua_State *L, int arg) { - if (l_unlikely(lua_type(L, arg) == LUA_TNONE)) - luaL_argerror(L, arg, "value expected"); -} - - -LUALIB_API const char *luaL_checklstring (lua_State *L, int arg, size_t *len) { - const char *s = lua_tolstring(L, arg, len); - if (l_unlikely(!s)) tag_error(L, arg, LUA_TSTRING); - return s; -} - - -LUALIB_API const char *luaL_optlstring (lua_State *L, int arg, - const char *def, size_t *len) { - if (lua_isnoneornil(L, arg)) { - if (len) - *len = (def ? strlen(def) : 0); - return def; - } - else return luaL_checklstring(L, arg, len); -} - - -LUALIB_API lua_Number luaL_checknumber (lua_State *L, int arg) { - int isnum; - lua_Number d = lua_tonumberx(L, arg, &isnum); - if (l_unlikely(!isnum)) - tag_error(L, arg, LUA_TNUMBER); - return d; -} - - -LUALIB_API lua_Number luaL_optnumber (lua_State *L, int arg, lua_Number def) { - return luaL_opt(L, luaL_checknumber, arg, def); -} - - -static void interror (lua_State *L, int arg) { - if (lua_isnumber(L, arg)) - luaL_argerror(L, arg, "number has no integer representation"); - else - tag_error(L, arg, LUA_TNUMBER); -} - - -LUALIB_API lua_Integer luaL_checkinteger (lua_State *L, int arg) { - int isnum; - lua_Integer d = lua_tointegerx(L, arg, &isnum); - if (l_unlikely(!isnum)) { - interror(L, arg); - } - return d; -} - - -LUALIB_API lua_Integer luaL_optinteger (lua_State *L, int arg, - lua_Integer def) { - return luaL_opt(L, luaL_checkinteger, arg, def); -} - -/* }====================================================== */ - - -/* -** {====================================================== -** Generic Buffer manipulation -** ======================================================= -*/ - -/* userdata to box arbitrary data */ -typedef struct UBox { - void *box; - size_t bsize; -} UBox; - - -static void *resizebox (lua_State *L, int idx, size_t newsize) { - void *ud; - lua_Alloc allocf = lua_getallocf(L, &ud); - UBox *box = (UBox *)lua_touserdata(L, idx); - void *temp = allocf(ud, box->box, box->bsize, newsize); - if (l_unlikely(temp == NULL && newsize > 0)) { /* allocation error? */ - lua_pushliteral(L, "not enough memory"); - lua_error(L); /* raise a memory error */ - } - box->box = temp; - box->bsize = newsize; - return temp; -} - - -static int boxgc (lua_State *L) { - resizebox(L, 1, 0); - return 0; -} - - -static const luaL_Reg boxmt[] = { /* box metamethods */ - {"__gc", boxgc}, - {"__close", boxgc}, - {NULL, NULL} -}; - - -static void newbox (lua_State *L) { - UBox *box = (UBox *)lua_newuserdatauv(L, sizeof(UBox), 0); - box->box = NULL; - box->bsize = 0; - if (luaL_newmetatable(L, "_UBOX*")) /* creating metatable? */ - luaL_setfuncs(L, boxmt, 0); /* set its metamethods */ - lua_setmetatable(L, -2); -} - - -/* -** check whether buffer is using a userdata on the stack as a temporary -** buffer -*/ -#define buffonstack(B) ((B)->b != (B)->init.b) - - -/* -** Whenever buffer is accessed, slot 'idx' must either be a box (which -** cannot be NULL) or it is a placeholder for the buffer. -*/ -#define checkbufferlevel(B,idx) \ - lua_assert(buffonstack(B) ? lua_touserdata(B->L, idx) != NULL \ - : lua_touserdata(B->L, idx) == (void*)B) - - -/* -** Compute new size for buffer 'B', enough to accommodate extra 'sz' -** bytes. (The test for "not big enough" also gets the case when the -** computation of 'newsize' overflows.) -*/ -static size_t newbuffsize (luaL_Buffer *B, size_t sz) { - size_t newsize = (B->size / 2) * 3; /* buffer size * 1.5 */ - if (l_unlikely(MAX_SIZET - sz < B->n)) /* overflow in (B->n + sz)? */ - return luaL_error(B->L, "buffer too large"); - if (newsize < B->n + sz) /* not big enough? */ - newsize = B->n + sz; - return newsize; -} - - -/* -** Returns a pointer to a free area with at least 'sz' bytes in buffer -** 'B'. 'boxidx' is the relative position in the stack where is the -** buffer's box or its placeholder. -*/ -static char *prepbuffsize (luaL_Buffer *B, size_t sz, int boxidx) { - checkbufferlevel(B, boxidx); - if (B->size - B->n >= sz) /* enough space? */ - return B->b + B->n; - else { - lua_State *L = B->L; - char *newbuff; - size_t newsize = newbuffsize(B, sz); - /* create larger buffer */ - if (buffonstack(B)) /* buffer already has a box? */ - newbuff = (char *)resizebox(L, boxidx, newsize); /* resize it */ - else { /* no box yet */ - lua_remove(L, boxidx); /* remove placeholder */ - newbox(L); /* create a new box */ - lua_insert(L, boxidx); /* move box to its intended position */ - lua_toclose(L, boxidx); - newbuff = (char *)resizebox(L, boxidx, newsize); - memcpy(newbuff, B->b, B->n * sizeof(char)); /* copy original content */ - } - B->b = newbuff; - B->size = newsize; - return newbuff + B->n; - } -} - -/* -** returns a pointer to a free area with at least 'sz' bytes -*/ -LUALIB_API char *luaL_prepbuffsize (luaL_Buffer *B, size_t sz) { - return prepbuffsize(B, sz, -1); -} - - -LUALIB_API void luaL_addlstring (luaL_Buffer *B, const char *s, size_t l) { - if (l > 0) { /* avoid 'memcpy' when 's' can be NULL */ - char *b = prepbuffsize(B, l, -1); - memcpy(b, s, l * sizeof(char)); - luaL_addsize(B, l); - } -} - - -LUALIB_API void luaL_addstring (luaL_Buffer *B, const char *s) { - luaL_addlstring(B, s, strlen(s)); -} - - -LUALIB_API void luaL_pushresult (luaL_Buffer *B) { - lua_State *L = B->L; - checkbufferlevel(B, -1); - lua_pushlstring(L, B->b, B->n); - if (buffonstack(B)) - lua_closeslot(L, -2); /* close the box */ - lua_remove(L, -2); /* remove box or placeholder from the stack */ -} - - -LUALIB_API void luaL_pushresultsize (luaL_Buffer *B, size_t sz) { - luaL_addsize(B, sz); - luaL_pushresult(B); -} - - -/* -** 'luaL_addvalue' is the only function in the Buffer system where the -** box (if existent) is not on the top of the stack. So, instead of -** calling 'luaL_addlstring', it replicates the code using -2 as the -** last argument to 'prepbuffsize', signaling that the box is (or will -** be) below the string being added to the buffer. (Box creation can -** trigger an emergency GC, so we should not remove the string from the -** stack before we have the space guaranteed.) -*/ -LUALIB_API void luaL_addvalue (luaL_Buffer *B) { - lua_State *L = B->L; - size_t len; - const char *s = lua_tolstring(L, -1, &len); - char *b = prepbuffsize(B, len, -2); - memcpy(b, s, len * sizeof(char)); - luaL_addsize(B, len); - lua_pop(L, 1); /* pop string */ -} - - -LUALIB_API void luaL_buffinit (lua_State *L, luaL_Buffer *B) { - B->L = L; - B->b = B->init.b; - B->n = 0; - B->size = LUAL_BUFFERSIZE; - lua_pushlightuserdata(L, (void*)B); /* push placeholder */ -} - - -LUALIB_API char *luaL_buffinitsize (lua_State *L, luaL_Buffer *B, size_t sz) { - luaL_buffinit(L, B); - return prepbuffsize(B, sz, -1); -} - -/* }====================================================== */ - - -/* -** {====================================================== -** Reference system -** ======================================================= -*/ - -/* index of free-list header (after the predefined values) */ -#define freelist (LUA_RIDX_LAST + 1) - -/* -** The previously freed references form a linked list: -** t[freelist] is the index of a first free index, or zero if list is -** empty; t[t[freelist]] is the index of the second element; etc. -*/ -LUALIB_API int luaL_ref (lua_State *L, int t) { - int ref; - if (lua_isnil(L, -1)) { - lua_pop(L, 1); /* remove from stack */ - return LUA_REFNIL; /* 'nil' has a unique fixed reference */ - } - t = lua_absindex(L, t); - if (lua_rawgeti(L, t, freelist) == LUA_TNIL) { /* first access? */ - ref = 0; /* list is empty */ - lua_pushinteger(L, 0); /* initialize as an empty list */ - lua_rawseti(L, t, freelist); /* ref = t[freelist] = 0 */ - } - else { /* already initialized */ - lua_assert(lua_isinteger(L, -1)); - ref = (int)lua_tointeger(L, -1); /* ref = t[freelist] */ - } - lua_pop(L, 1); /* remove element from stack */ - if (ref != 0) { /* any free element? */ - lua_rawgeti(L, t, ref); /* remove it from list */ - lua_rawseti(L, t, freelist); /* (t[freelist] = t[ref]) */ - } - else /* no free elements */ - ref = (int)lua_rawlen(L, t) + 1; /* get a new reference */ - lua_rawseti(L, t, ref); - return ref; -} - - -LUALIB_API void luaL_unref (lua_State *L, int t, int ref) { - if (ref >= 0) { - t = lua_absindex(L, t); - lua_rawgeti(L, t, freelist); - lua_assert(lua_isinteger(L, -1)); - lua_rawseti(L, t, ref); /* t[ref] = t[freelist] */ - lua_pushinteger(L, ref); - lua_rawseti(L, t, freelist); /* t[freelist] = ref */ - } -} - -/* }====================================================== */ - - -/* -** {====================================================== -** Load functions -** ======================================================= -*/ - -typedef struct LoadF { - int n; /* number of pre-read characters */ - FILE *f; /* file being read */ - char buff[BUFSIZ]; /* area for reading file */ -} LoadF; - - -static const char *getF (lua_State *L, void *ud, size_t *size) { - LoadF *lf = (LoadF *)ud; - (void)L; /* not used */ - if (lf->n > 0) { /* are there pre-read characters to be read? */ - *size = lf->n; /* return them (chars already in buffer) */ - lf->n = 0; /* no more pre-read characters */ - } - else { /* read a block from file */ - /* 'fread' can return > 0 *and* set the EOF flag. If next call to - 'getF' called 'fread', it might still wait for user input. - The next check avoids this problem. */ - if (feof(lf->f)) return NULL; - *size = fread(lf->buff, 1, sizeof(lf->buff), lf->f); /* read block */ - } - return lf->buff; -} - - -static int errfile (lua_State *L, const char *what, int fnameindex) { - const char *serr = strerror(errno); - const char *filename = lua_tostring(L, fnameindex) + 1; - lua_pushfstring(L, "cannot %s %s: %s", what, filename, serr); - lua_remove(L, fnameindex); - return LUA_ERRFILE; -} - - -/* -** Skip an optional BOM at the start of a stream. If there is an -** incomplete BOM (the first character is correct but the rest is -** not), returns the first character anyway to force an error -** (as no chunk can start with 0xEF). -*/ -static int skipBOM (FILE *f) { - int c = getc(f); /* read first character */ - if (c == 0xEF && getc(f) == 0xBB && getc(f) == 0xBF) /* correct BOM? */ - return getc(f); /* ignore BOM and return next char */ - else /* no (valid) BOM */ - return c; /* return first character */ -} - - -/* -** reads the first character of file 'f' and skips an optional BOM mark -** in its beginning plus its first line if it starts with '#'. Returns -** true if it skipped the first line. In any case, '*cp' has the -** first "valid" character of the file (after the optional BOM and -** a first-line comment). -*/ -static int skipcomment (FILE *f, int *cp) { - int c = *cp = skipBOM(f); - if (c == '#') { /* first line is a comment (Unix exec. file)? */ - do { /* skip first line */ - c = getc(f); - } while (c != EOF && c != '\n'); - *cp = getc(f); /* next character after comment, if present */ - return 1; /* there was a comment */ - } - else return 0; /* no comment */ -} - - -LUALIB_API int luaL_loadfilex (lua_State *L, const char *filename, - const char *mode) { - LoadF lf; - int status, readstatus; - int c; - int fnameindex = lua_gettop(L) + 1; /* index of filename on the stack */ - if (filename == NULL) { - lua_pushliteral(L, "=stdin"); - lf.f = stdin; - } - else { - lua_pushfstring(L, "@%s", filename); - lf.f = fopen(filename, "r"); - if (lf.f == NULL) return errfile(L, "open", fnameindex); - } - lf.n = 0; - if (skipcomment(lf.f, &c)) /* read initial portion */ - lf.buff[lf.n++] = '\n'; /* add newline to correct line numbers */ - if (c == LUA_SIGNATURE[0]) { /* binary file? */ - lf.n = 0; /* remove possible newline */ - if (filename) { /* "real" file? */ - lf.f = freopen(filename, "rb", lf.f); /* reopen in binary mode */ - if (lf.f == NULL) return errfile(L, "reopen", fnameindex); - skipcomment(lf.f, &c); /* re-read initial portion */ - } - } - if (c != EOF) - lf.buff[lf.n++] = c; /* 'c' is the first character of the stream */ - status = lua_load(L, getF, &lf, lua_tostring(L, -1), mode); - readstatus = ferror(lf.f); - if (filename) fclose(lf.f); /* close file (even in case of errors) */ - if (readstatus) { - lua_settop(L, fnameindex); /* ignore results from 'lua_load' */ - return errfile(L, "read", fnameindex); - } - lua_remove(L, fnameindex); - return status; -} - - -typedef struct LoadS { - const char *s; - size_t size; -} LoadS; - - -static const char *getS (lua_State *L, void *ud, size_t *size) { - LoadS *ls = (LoadS *)ud; - (void)L; /* not used */ - if (ls->size == 0) return NULL; - *size = ls->size; - ls->size = 0; - return ls->s; -} - - -LUALIB_API int luaL_loadbufferx (lua_State *L, const char *buff, size_t size, - const char *name, const char *mode) { - LoadS ls; - ls.s = buff; - ls.size = size; - return lua_load(L, getS, &ls, name, mode); -} - - -LUALIB_API int luaL_loadstring (lua_State *L, const char *s) { - return luaL_loadbuffer(L, s, strlen(s), s); -} - -/* }====================================================== */ - - - -LUALIB_API int luaL_getmetafield (lua_State *L, int obj, const char *event) { - if (!lua_getmetatable(L, obj)) /* no metatable? */ - return LUA_TNIL; - else { - int tt; - lua_pushstring(L, event); - tt = lua_rawget(L, -2); - if (tt == LUA_TNIL) /* is metafield nil? */ - lua_pop(L, 2); /* remove metatable and metafield */ - else - lua_remove(L, -2); /* remove only metatable */ - return tt; /* return metafield type */ - } -} - - -LUALIB_API int luaL_callmeta (lua_State *L, int obj, const char *event) { - obj = lua_absindex(L, obj); - if (luaL_getmetafield(L, obj, event) == LUA_TNIL) /* no metafield? */ - return 0; - lua_pushvalue(L, obj); - lua_call(L, 1, 1); - return 1; -} - - -LUALIB_API lua_Integer luaL_len (lua_State *L, int idx) { - lua_Integer l; - int isnum; - lua_len(L, idx); - l = lua_tointegerx(L, -1, &isnum); - if (l_unlikely(!isnum)) - luaL_error(L, "object length is not an integer"); - lua_pop(L, 1); /* remove object */ - return l; -} - - -LUALIB_API const char *luaL_tolstring (lua_State *L, int idx, size_t *len) { - idx = lua_absindex(L,idx); - if (luaL_callmeta(L, idx, "__tostring")) { /* metafield? */ - if (!lua_isstring(L, -1)) - luaL_error(L, "'__tostring' must return a string"); - } - else { - switch (lua_type(L, idx)) { - case LUA_TNUMBER: { - if (lua_isinteger(L, idx)) - lua_pushfstring(L, "%I", (LUAI_UACINT)lua_tointeger(L, idx)); - else - lua_pushfstring(L, "%f", (LUAI_UACNUMBER)lua_tonumber(L, idx)); - break; - } - case LUA_TSTRING: - lua_pushvalue(L, idx); - break; - case LUA_TBOOLEAN: - lua_pushstring(L, (lua_toboolean(L, idx) ? "true" : "false")); - break; - case LUA_TNIL: - lua_pushliteral(L, "nil"); - break; - default: { - int tt = luaL_getmetafield(L, idx, "__name"); /* try name */ - const char *kind = (tt == LUA_TSTRING) ? lua_tostring(L, -1) : - luaL_typename(L, idx); - lua_pushfstring(L, "%s: %p", kind, lua_topointer(L, idx)); - if (tt != LUA_TNIL) - lua_remove(L, -2); /* remove '__name' */ - break; - } - } - } - return lua_tolstring(L, -1, len); -} - - -/* -** set functions from list 'l' into table at top - 'nup'; each -** function gets the 'nup' elements at the top as upvalues. -** Returns with only the table at the stack. -*/ -LUALIB_API void luaL_setfuncs (lua_State *L, const luaL_Reg *l, int nup) { - luaL_checkstack(L, nup, "too many upvalues"); - for (; l->name != NULL; l++) { /* fill the table with given functions */ - if (l->func == NULL) /* place holder? */ - lua_pushboolean(L, 0); - else { - int i; - for (i = 0; i < nup; i++) /* copy upvalues to the top */ - lua_pushvalue(L, -nup); - lua_pushcclosure(L, l->func, nup); /* closure with those upvalues */ - } - lua_setfield(L, -(nup + 2), l->name); - } - lua_pop(L, nup); /* remove upvalues */ -} - - -/* -** ensure that stack[idx][fname] has a table and push that table -** into the stack -*/ -LUALIB_API int luaL_getsubtable (lua_State *L, int idx, const char *fname) { - if (lua_getfield(L, idx, fname) == LUA_TTABLE) - return 1; /* table already there */ - else { - lua_pop(L, 1); /* remove previous result */ - idx = lua_absindex(L, idx); - lua_newtable(L); - lua_pushvalue(L, -1); /* copy to be left at top */ - lua_setfield(L, idx, fname); /* assign new table to field */ - return 0; /* false, because did not find table there */ - } -} - - -/* -** Stripped-down 'require': After checking "loaded" table, calls 'openf' -** to open a module, registers the result in 'package.loaded' table and, -** if 'glb' is true, also registers the result in the global table. -** Leaves resulting module on the top. -*/ -LUALIB_API void luaL_requiref (lua_State *L, const char *modname, - lua_CFunction openf, int glb) { - luaL_getsubtable(L, LUA_REGISTRYINDEX, LUA_LOADED_TABLE); - lua_getfield(L, -1, modname); /* LOADED[modname] */ - if (!lua_toboolean(L, -1)) { /* package not already loaded? */ - lua_pop(L, 1); /* remove field */ - lua_pushcfunction(L, openf); - lua_pushstring(L, modname); /* argument to open function */ - lua_call(L, 1, 1); /* call 'openf' to open module */ - lua_pushvalue(L, -1); /* make copy of module (call result) */ - lua_setfield(L, -3, modname); /* LOADED[modname] = module */ - } - lua_remove(L, -2); /* remove LOADED table */ - if (glb) { - lua_pushvalue(L, -1); /* copy of module */ - lua_setglobal(L, modname); /* _G[modname] = module */ - } -} - - -LUALIB_API void luaL_addgsub (luaL_Buffer *b, const char *s, - const char *p, const char *r) { - const char *wild; - size_t l = strlen(p); - while ((wild = strstr(s, p)) != NULL) { - luaL_addlstring(b, s, wild - s); /* push prefix */ - luaL_addstring(b, r); /* push replacement in place of pattern */ - s = wild + l; /* continue after 'p' */ - } - luaL_addstring(b, s); /* push last suffix */ -} - - -LUALIB_API const char *luaL_gsub (lua_State *L, const char *s, - const char *p, const char *r) { - luaL_Buffer b; - luaL_buffinit(L, &b); - luaL_addgsub(&b, s, p, r); - luaL_pushresult(&b); - return lua_tostring(L, -1); -} - - -static void *l_alloc (void *ud, void *ptr, size_t osize, size_t nsize) { - (void)ud; (void)osize; /* not used */ - if (nsize == 0) { - free(ptr); - return NULL; - } - else - return realloc(ptr, nsize); -} - - -static int panic (lua_State *L) { - const char *msg = lua_tostring(L, -1); - if (msg == NULL) msg = "error object is not a string"; - lua_writestringerror("PANIC: unprotected error in call to Lua API (%s)\n", - msg); - return 0; /* return to Lua to abort */ -} - - -/* -** Warning functions: -** warnfoff: warning system is off -** warnfon: ready to start a new message -** warnfcont: previous message is to be continued -*/ -static void warnfoff (void *ud, const char *message, int tocont); -static void warnfon (void *ud, const char *message, int tocont); -static void warnfcont (void *ud, const char *message, int tocont); - - -/* -** Check whether message is a control message. If so, execute the -** control or ignore it if unknown. -*/ -static int checkcontrol (lua_State *L, const char *message, int tocont) { - if (tocont || *(message++) != '@') /* not a control message? */ - return 0; - else { - if (strcmp(message, "off") == 0) - lua_setwarnf(L, warnfoff, L); /* turn warnings off */ - else if (strcmp(message, "on") == 0) - lua_setwarnf(L, warnfon, L); /* turn warnings on */ - return 1; /* it was a control message */ - } -} - - -static void warnfoff (void *ud, const char *message, int tocont) { - checkcontrol((lua_State *)ud, message, tocont); -} - - -/* -** Writes the message and handle 'tocont', finishing the message -** if needed and setting the next warn function. -*/ -static void warnfcont (void *ud, const char *message, int tocont) { - lua_State *L = (lua_State *)ud; - lua_writestringerror("%s", message); /* write message */ - if (tocont) /* not the last part? */ - lua_setwarnf(L, warnfcont, L); /* to be continued */ - else { /* last part */ - lua_writestringerror("%s", "\n"); /* finish message with end-of-line */ - lua_setwarnf(L, warnfon, L); /* next call is a new message */ - } -} - - -static void warnfon (void *ud, const char *message, int tocont) { - if (checkcontrol((lua_State *)ud, message, tocont)) /* control message? */ - return; /* nothing else to be done */ - lua_writestringerror("%s", "Lua warning: "); /* start a new warning */ - warnfcont(ud, message, tocont); /* finish processing */ -} - - -LUALIB_API lua_State *luaL_newstate (void) { - lua_State *L = lua_newstate(l_alloc, NULL); - if (l_likely(L)) { - lua_atpanic(L, &panic); - lua_setwarnf(L, warnfoff, L); /* default is warnings off */ - } - return L; -} - - -LUALIB_API void luaL_checkversion_ (lua_State *L, lua_Number ver, size_t sz) { - lua_Number v = lua_version(L); - if (sz != LUAL_NUMSIZES) /* check numeric types */ - luaL_error(L, "core and library have incompatible numeric types"); - else if (v != ver) - luaL_error(L, "version mismatch: app. needs %f, Lua core provides %f", - (LUAI_UACNUMBER)ver, (LUAI_UACNUMBER)v); -} - diff --git a/lib/lua-5.4/src/lauxlib.h b/lib/lua-5.4/src/lauxlib.h deleted file mode 100644 index 5b977e2..0000000 --- a/lib/lua-5.4/src/lauxlib.h +++ /dev/null @@ -1,301 +0,0 @@ -/* -** $Id: lauxlib.h $ -** Auxiliary functions for building Lua libraries -** See Copyright Notice in lua.h -*/ - - -#ifndef lauxlib_h -#define lauxlib_h - - -#include -#include - -#include "luaconf.h" -#include "lua.h" - - -/* global table */ -#define LUA_GNAME "_G" - - -typedef struct luaL_Buffer luaL_Buffer; - - -/* extra error code for 'luaL_loadfilex' */ -#define LUA_ERRFILE (LUA_ERRERR+1) - - -/* key, in the registry, for table of loaded modules */ -#define LUA_LOADED_TABLE "_LOADED" - - -/* key, in the registry, for table of preloaded loaders */ -#define LUA_PRELOAD_TABLE "_PRELOAD" - - -typedef struct luaL_Reg { - const char *name; - lua_CFunction func; -} luaL_Reg; - - -#define LUAL_NUMSIZES (sizeof(lua_Integer)*16 + sizeof(lua_Number)) - -LUALIB_API void (luaL_checkversion_) (lua_State *L, lua_Number ver, size_t sz); -#define luaL_checkversion(L) \ - luaL_checkversion_(L, LUA_VERSION_NUM, LUAL_NUMSIZES) - -LUALIB_API int (luaL_getmetafield) (lua_State *L, int obj, const char *e); -LUALIB_API int (luaL_callmeta) (lua_State *L, int obj, const char *e); -LUALIB_API const char *(luaL_tolstring) (lua_State *L, int idx, size_t *len); -LUALIB_API int (luaL_argerror) (lua_State *L, int arg, const char *extramsg); -LUALIB_API int (luaL_typeerror) (lua_State *L, int arg, const char *tname); -LUALIB_API const char *(luaL_checklstring) (lua_State *L, int arg, - size_t *l); -LUALIB_API const char *(luaL_optlstring) (lua_State *L, int arg, - const char *def, size_t *l); -LUALIB_API lua_Number (luaL_checknumber) (lua_State *L, int arg); -LUALIB_API lua_Number (luaL_optnumber) (lua_State *L, int arg, lua_Number def); - -LUALIB_API lua_Integer (luaL_checkinteger) (lua_State *L, int arg); -LUALIB_API lua_Integer (luaL_optinteger) (lua_State *L, int arg, - lua_Integer def); - -LUALIB_API void (luaL_checkstack) (lua_State *L, int sz, const char *msg); -LUALIB_API void (luaL_checktype) (lua_State *L, int arg, int t); -LUALIB_API void (luaL_checkany) (lua_State *L, int arg); - -LUALIB_API int (luaL_newmetatable) (lua_State *L, const char *tname); -LUALIB_API void (luaL_setmetatable) (lua_State *L, const char *tname); -LUALIB_API void *(luaL_testudata) (lua_State *L, int ud, const char *tname); -LUALIB_API void *(luaL_checkudata) (lua_State *L, int ud, const char *tname); - -LUALIB_API void (luaL_where) (lua_State *L, int lvl); -LUALIB_API int (luaL_error) (lua_State *L, const char *fmt, ...); - -LUALIB_API int (luaL_checkoption) (lua_State *L, int arg, const char *def, - const char *const lst[]); - -LUALIB_API int (luaL_fileresult) (lua_State *L, int stat, const char *fname); -LUALIB_API int (luaL_execresult) (lua_State *L, int stat); - - -/* predefined references */ -#define LUA_NOREF (-2) -#define LUA_REFNIL (-1) - -LUALIB_API int (luaL_ref) (lua_State *L, int t); -LUALIB_API void (luaL_unref) (lua_State *L, int t, int ref); - -LUALIB_API int (luaL_loadfilex) (lua_State *L, const char *filename, - const char *mode); - -#define luaL_loadfile(L,f) luaL_loadfilex(L,f,NULL) - -LUALIB_API int (luaL_loadbufferx) (lua_State *L, const char *buff, size_t sz, - const char *name, const char *mode); -LUALIB_API int (luaL_loadstring) (lua_State *L, const char *s); - -LUALIB_API lua_State *(luaL_newstate) (void); - -LUALIB_API lua_Integer (luaL_len) (lua_State *L, int idx); - -LUALIB_API void (luaL_addgsub) (luaL_Buffer *b, const char *s, - const char *p, const char *r); -LUALIB_API const char *(luaL_gsub) (lua_State *L, const char *s, - const char *p, const char *r); - -LUALIB_API void (luaL_setfuncs) (lua_State *L, const luaL_Reg *l, int nup); - -LUALIB_API int (luaL_getsubtable) (lua_State *L, int idx, const char *fname); - -LUALIB_API void (luaL_traceback) (lua_State *L, lua_State *L1, - const char *msg, int level); - -LUALIB_API void (luaL_requiref) (lua_State *L, const char *modname, - lua_CFunction openf, int glb); - -/* -** =============================================================== -** some useful macros -** =============================================================== -*/ - - -#define luaL_newlibtable(L,l) \ - lua_createtable(L, 0, sizeof(l)/sizeof((l)[0]) - 1) - -#define luaL_newlib(L,l) \ - (luaL_checkversion(L), luaL_newlibtable(L,l), luaL_setfuncs(L,l,0)) - -#define luaL_argcheck(L, cond,arg,extramsg) \ - ((void)(luai_likely(cond) || luaL_argerror(L, (arg), (extramsg)))) - -#define luaL_argexpected(L,cond,arg,tname) \ - ((void)(luai_likely(cond) || luaL_typeerror(L, (arg), (tname)))) - -#define luaL_checkstring(L,n) (luaL_checklstring(L, (n), NULL)) -#define luaL_optstring(L,n,d) (luaL_optlstring(L, (n), (d), NULL)) - -#define luaL_typename(L,i) lua_typename(L, lua_type(L,(i))) - -#define luaL_dofile(L, fn) \ - (luaL_loadfile(L, fn) || lua_pcall(L, 0, LUA_MULTRET, 0)) - -#define luaL_dostring(L, s) \ - (luaL_loadstring(L, s) || lua_pcall(L, 0, LUA_MULTRET, 0)) - -#define luaL_getmetatable(L,n) (lua_getfield(L, LUA_REGISTRYINDEX, (n))) - -#define luaL_opt(L,f,n,d) (lua_isnoneornil(L,(n)) ? (d) : f(L,(n))) - -#define luaL_loadbuffer(L,s,sz,n) luaL_loadbufferx(L,s,sz,n,NULL) - - -/* -** Perform arithmetic operations on lua_Integer values with wrap-around -** semantics, as the Lua core does. -*/ -#define luaL_intop(op,v1,v2) \ - ((lua_Integer)((lua_Unsigned)(v1) op (lua_Unsigned)(v2))) - - -/* push the value used to represent failure/error */ -#define luaL_pushfail(L) lua_pushnil(L) - - -/* -** Internal assertions for in-house debugging -*/ -#if !defined(lua_assert) - -#if defined LUAI_ASSERT - #include - #define lua_assert(c) assert(c) -#else - #define lua_assert(c) ((void)0) -#endif - -#endif - - - -/* -** {====================================================== -** Generic Buffer manipulation -** ======================================================= -*/ - -struct luaL_Buffer { - char *b; /* buffer address */ - size_t size; /* buffer size */ - size_t n; /* number of characters in buffer */ - lua_State *L; - union { - LUAI_MAXALIGN; /* ensure maximum alignment for buffer */ - char b[LUAL_BUFFERSIZE]; /* initial buffer */ - } init; -}; - - -#define luaL_bufflen(bf) ((bf)->n) -#define luaL_buffaddr(bf) ((bf)->b) - - -#define luaL_addchar(B,c) \ - ((void)((B)->n < (B)->size || luaL_prepbuffsize((B), 1)), \ - ((B)->b[(B)->n++] = (c))) - -#define luaL_addsize(B,s) ((B)->n += (s)) - -#define luaL_buffsub(B,s) ((B)->n -= (s)) - -LUALIB_API void (luaL_buffinit) (lua_State *L, luaL_Buffer *B); -LUALIB_API char *(luaL_prepbuffsize) (luaL_Buffer *B, size_t sz); -LUALIB_API void (luaL_addlstring) (luaL_Buffer *B, const char *s, size_t l); -LUALIB_API void (luaL_addstring) (luaL_Buffer *B, const char *s); -LUALIB_API void (luaL_addvalue) (luaL_Buffer *B); -LUALIB_API void (luaL_pushresult) (luaL_Buffer *B); -LUALIB_API void (luaL_pushresultsize) (luaL_Buffer *B, size_t sz); -LUALIB_API char *(luaL_buffinitsize) (lua_State *L, luaL_Buffer *B, size_t sz); - -#define luaL_prepbuffer(B) luaL_prepbuffsize(B, LUAL_BUFFERSIZE) - -/* }====================================================== */ - - - -/* -** {====================================================== -** File handles for IO library -** ======================================================= -*/ - -/* -** A file handle is a userdata with metatable 'LUA_FILEHANDLE' and -** initial structure 'luaL_Stream' (it may contain other fields -** after that initial structure). -*/ - -#define LUA_FILEHANDLE "FILE*" - - -typedef struct luaL_Stream { - FILE *f; /* stream (NULL for incompletely created streams) */ - lua_CFunction closef; /* to close stream (NULL for closed streams) */ -} luaL_Stream; - -/* }====================================================== */ - -/* -** {================================================================== -** "Abstraction Layer" for basic report of messages and errors -** =================================================================== -*/ - -/* print a string */ -#if !defined(lua_writestring) -#define lua_writestring(s,l) fwrite((s), sizeof(char), (l), stdout) -#endif - -/* print a newline and flush the output */ -#if !defined(lua_writeline) -#define lua_writeline() (lua_writestring("\n", 1), fflush(stdout)) -#endif - -/* print an error message */ -#if !defined(lua_writestringerror) -#define lua_writestringerror(s,p) \ - (fprintf(stderr, (s), (p)), fflush(stderr)) -#endif - -/* }================================================================== */ - - -/* -** {============================================================ -** Compatibility with deprecated conversions -** ============================================================= -*/ -#if defined(LUA_COMPAT_APIINTCASTS) - -#define luaL_checkunsigned(L,a) ((lua_Unsigned)luaL_checkinteger(L,a)) -#define luaL_optunsigned(L,a,d) \ - ((lua_Unsigned)luaL_optinteger(L,a,(lua_Integer)(d))) - -#define luaL_checkint(L,n) ((int)luaL_checkinteger(L, (n))) -#define luaL_optint(L,n,d) ((int)luaL_optinteger(L, (n), (d))) - -#define luaL_checklong(L,n) ((long)luaL_checkinteger(L, (n))) -#define luaL_optlong(L,n,d) ((long)luaL_optinteger(L, (n), (d))) - -#endif -/* }============================================================ */ - - - -#endif - - diff --git a/lib/lua-5.4/src/lbaselib.c b/lib/lua-5.4/src/lbaselib.c deleted file mode 100644 index 1d60c9d..0000000 --- a/lib/lua-5.4/src/lbaselib.c +++ /dev/null @@ -1,549 +0,0 @@ -/* -** $Id: lbaselib.c $ -** Basic library -** See Copyright Notice in lua.h -*/ - -#define lbaselib_c -#define LUA_LIB - -#include "lprefix.h" - - -#include -#include -#include -#include - -#include "lua.h" - -#include "lauxlib.h" -#include "lualib.h" - - -static int luaB_print (lua_State *L) { - int n = lua_gettop(L); /* number of arguments */ - int i; - for (i = 1; i <= n; i++) { /* for each argument */ - size_t l; - const char *s = luaL_tolstring(L, i, &l); /* convert it to string */ - if (i > 1) /* not the first element? */ - lua_writestring("\t", 1); /* add a tab before it */ - lua_writestring(s, l); /* print it */ - lua_pop(L, 1); /* pop result */ - } - lua_writeline(); - return 0; -} - - -/* -** Creates a warning with all given arguments. -** Check first for errors; otherwise an error may interrupt -** the composition of a warning, leaving it unfinished. -*/ -static int luaB_warn (lua_State *L) { - int n = lua_gettop(L); /* number of arguments */ - int i; - luaL_checkstring(L, 1); /* at least one argument */ - for (i = 2; i <= n; i++) - luaL_checkstring(L, i); /* make sure all arguments are strings */ - for (i = 1; i < n; i++) /* compose warning */ - lua_warning(L, lua_tostring(L, i), 1); - lua_warning(L, lua_tostring(L, n), 0); /* close warning */ - return 0; -} - - -#define SPACECHARS " \f\n\r\t\v" - -static const char *b_str2int (const char *s, int base, lua_Integer *pn) { - lua_Unsigned n = 0; - int neg = 0; - s += strspn(s, SPACECHARS); /* skip initial spaces */ - if (*s == '-') { s++; neg = 1; } /* handle sign */ - else if (*s == '+') s++; - if (!isalnum((unsigned char)*s)) /* no digit? */ - return NULL; - do { - int digit = (isdigit((unsigned char)*s)) ? *s - '0' - : (toupper((unsigned char)*s) - 'A') + 10; - if (digit >= base) return NULL; /* invalid numeral */ - n = n * base + digit; - s++; - } while (isalnum((unsigned char)*s)); - s += strspn(s, SPACECHARS); /* skip trailing spaces */ - *pn = (lua_Integer)((neg) ? (0u - n) : n); - return s; -} - - -static int luaB_tonumber (lua_State *L) { - if (lua_isnoneornil(L, 2)) { /* standard conversion? */ - if (lua_type(L, 1) == LUA_TNUMBER) { /* already a number? */ - lua_settop(L, 1); /* yes; return it */ - return 1; - } - else { - size_t l; - const char *s = lua_tolstring(L, 1, &l); - if (s != NULL && lua_stringtonumber(L, s) == l + 1) - return 1; /* successful conversion to number */ - /* else not a number */ - luaL_checkany(L, 1); /* (but there must be some parameter) */ - } - } - else { - size_t l; - const char *s; - lua_Integer n = 0; /* to avoid warnings */ - lua_Integer base = luaL_checkinteger(L, 2); - luaL_checktype(L, 1, LUA_TSTRING); /* no numbers as strings */ - s = lua_tolstring(L, 1, &l); - luaL_argcheck(L, 2 <= base && base <= 36, 2, "base out of range"); - if (b_str2int(s, (int)base, &n) == s + l) { - lua_pushinteger(L, n); - return 1; - } /* else not a number */ - } /* else not a number */ - luaL_pushfail(L); /* not a number */ - return 1; -} - - -static int luaB_error (lua_State *L) { - int level = (int)luaL_optinteger(L, 2, 1); - lua_settop(L, 1); - if (lua_type(L, 1) == LUA_TSTRING && level > 0) { - luaL_where(L, level); /* add extra information */ - lua_pushvalue(L, 1); - lua_concat(L, 2); - } - return lua_error(L); -} - - -static int luaB_getmetatable (lua_State *L) { - luaL_checkany(L, 1); - if (!lua_getmetatable(L, 1)) { - lua_pushnil(L); - return 1; /* no metatable */ - } - luaL_getmetafield(L, 1, "__metatable"); - return 1; /* returns either __metatable field (if present) or metatable */ -} - - -static int luaB_setmetatable (lua_State *L) { - int t = lua_type(L, 2); - luaL_checktype(L, 1, LUA_TTABLE); - luaL_argexpected(L, t == LUA_TNIL || t == LUA_TTABLE, 2, "nil or table"); - if (l_unlikely(luaL_getmetafield(L, 1, "__metatable") != LUA_TNIL)) - return luaL_error(L, "cannot change a protected metatable"); - lua_settop(L, 2); - lua_setmetatable(L, 1); - return 1; -} - - -static int luaB_rawequal (lua_State *L) { - luaL_checkany(L, 1); - luaL_checkany(L, 2); - lua_pushboolean(L, lua_rawequal(L, 1, 2)); - return 1; -} - - -static int luaB_rawlen (lua_State *L) { - int t = lua_type(L, 1); - luaL_argexpected(L, t == LUA_TTABLE || t == LUA_TSTRING, 1, - "table or string"); - lua_pushinteger(L, lua_rawlen(L, 1)); - return 1; -} - - -static int luaB_rawget (lua_State *L) { - luaL_checktype(L, 1, LUA_TTABLE); - luaL_checkany(L, 2); - lua_settop(L, 2); - lua_rawget(L, 1); - return 1; -} - -static int luaB_rawset (lua_State *L) { - luaL_checktype(L, 1, LUA_TTABLE); - luaL_checkany(L, 2); - luaL_checkany(L, 3); - lua_settop(L, 3); - lua_rawset(L, 1); - return 1; -} - - -static int pushmode (lua_State *L, int oldmode) { - if (oldmode == -1) - luaL_pushfail(L); /* invalid call to 'lua_gc' */ - else - lua_pushstring(L, (oldmode == LUA_GCINC) ? "incremental" - : "generational"); - return 1; -} - - -/* -** check whether call to 'lua_gc' was valid (not inside a finalizer) -*/ -#define checkvalres(res) { if (res == -1) break; } - -static int luaB_collectgarbage (lua_State *L) { - static const char *const opts[] = {"stop", "restart", "collect", - "count", "step", "setpause", "setstepmul", - "isrunning", "generational", "incremental", NULL}; - static const int optsnum[] = {LUA_GCSTOP, LUA_GCRESTART, LUA_GCCOLLECT, - LUA_GCCOUNT, LUA_GCSTEP, LUA_GCSETPAUSE, LUA_GCSETSTEPMUL, - LUA_GCISRUNNING, LUA_GCGEN, LUA_GCINC}; - int o = optsnum[luaL_checkoption(L, 1, "collect", opts)]; - switch (o) { - case LUA_GCCOUNT: { - int k = lua_gc(L, o); - int b = lua_gc(L, LUA_GCCOUNTB); - checkvalres(k); - lua_pushnumber(L, (lua_Number)k + ((lua_Number)b/1024)); - return 1; - } - case LUA_GCSTEP: { - int step = (int)luaL_optinteger(L, 2, 0); - int res = lua_gc(L, o, step); - checkvalres(res); - lua_pushboolean(L, res); - return 1; - } - case LUA_GCSETPAUSE: - case LUA_GCSETSTEPMUL: { - int p = (int)luaL_optinteger(L, 2, 0); - int previous = lua_gc(L, o, p); - checkvalres(previous); - lua_pushinteger(L, previous); - return 1; - } - case LUA_GCISRUNNING: { - int res = lua_gc(L, o); - checkvalres(res); - lua_pushboolean(L, res); - return 1; - } - case LUA_GCGEN: { - int minormul = (int)luaL_optinteger(L, 2, 0); - int majormul = (int)luaL_optinteger(L, 3, 0); - return pushmode(L, lua_gc(L, o, minormul, majormul)); - } - case LUA_GCINC: { - int pause = (int)luaL_optinteger(L, 2, 0); - int stepmul = (int)luaL_optinteger(L, 3, 0); - int stepsize = (int)luaL_optinteger(L, 4, 0); - return pushmode(L, lua_gc(L, o, pause, stepmul, stepsize)); - } - default: { - int res = lua_gc(L, o); - checkvalres(res); - lua_pushinteger(L, res); - return 1; - } - } - luaL_pushfail(L); /* invalid call (inside a finalizer) */ - return 1; -} - - -static int luaB_type (lua_State *L) { - int t = lua_type(L, 1); - luaL_argcheck(L, t != LUA_TNONE, 1, "value expected"); - lua_pushstring(L, lua_typename(L, t)); - return 1; -} - - -static int luaB_next (lua_State *L) { - luaL_checktype(L, 1, LUA_TTABLE); - lua_settop(L, 2); /* create a 2nd argument if there isn't one */ - if (lua_next(L, 1)) - return 2; - else { - lua_pushnil(L); - return 1; - } -} - - -static int pairscont (lua_State *L, int status, lua_KContext k) { - (void)L; (void)status; (void)k; /* unused */ - return 3; -} - -static int luaB_pairs (lua_State *L) { - luaL_checkany(L, 1); - if (luaL_getmetafield(L, 1, "__pairs") == LUA_TNIL) { /* no metamethod? */ - lua_pushcfunction(L, luaB_next); /* will return generator, */ - lua_pushvalue(L, 1); /* state, */ - lua_pushnil(L); /* and initial value */ - } - else { - lua_pushvalue(L, 1); /* argument 'self' to metamethod */ - lua_callk(L, 1, 3, 0, pairscont); /* get 3 values from metamethod */ - } - return 3; -} - - -/* -** Traversal function for 'ipairs' -*/ -static int ipairsaux (lua_State *L) { - lua_Integer i = luaL_checkinteger(L, 2); - i = luaL_intop(+, i, 1); - lua_pushinteger(L, i); - return (lua_geti(L, 1, i) == LUA_TNIL) ? 1 : 2; -} - - -/* -** 'ipairs' function. Returns 'ipairsaux', given "table", 0. -** (The given "table" may not be a table.) -*/ -static int luaB_ipairs (lua_State *L) { - luaL_checkany(L, 1); - lua_pushcfunction(L, ipairsaux); /* iteration function */ - lua_pushvalue(L, 1); /* state */ - lua_pushinteger(L, 0); /* initial value */ - return 3; -} - - -static int load_aux (lua_State *L, int status, int envidx) { - if (l_likely(status == LUA_OK)) { - if (envidx != 0) { /* 'env' parameter? */ - lua_pushvalue(L, envidx); /* environment for loaded function */ - if (!lua_setupvalue(L, -2, 1)) /* set it as 1st upvalue */ - lua_pop(L, 1); /* remove 'env' if not used by previous call */ - } - return 1; - } - else { /* error (message is on top of the stack) */ - luaL_pushfail(L); - lua_insert(L, -2); /* put before error message */ - return 2; /* return fail plus error message */ - } -} - - -static int luaB_loadfile (lua_State *L) { - const char *fname = luaL_optstring(L, 1, NULL); - const char *mode = luaL_optstring(L, 2, NULL); - int env = (!lua_isnone(L, 3) ? 3 : 0); /* 'env' index or 0 if no 'env' */ - int status = luaL_loadfilex(L, fname, mode); - return load_aux(L, status, env); -} - - -/* -** {====================================================== -** Generic Read function -** ======================================================= -*/ - - -/* -** reserved slot, above all arguments, to hold a copy of the returned -** string to avoid it being collected while parsed. 'load' has four -** optional arguments (chunk, source name, mode, and environment). -*/ -#define RESERVEDSLOT 5 - - -/* -** Reader for generic 'load' function: 'lua_load' uses the -** stack for internal stuff, so the reader cannot change the -** stack top. Instead, it keeps its resulting string in a -** reserved slot inside the stack. -*/ -static const char *generic_reader (lua_State *L, void *ud, size_t *size) { - (void)(ud); /* not used */ - luaL_checkstack(L, 2, "too many nested functions"); - lua_pushvalue(L, 1); /* get function */ - lua_call(L, 0, 1); /* call it */ - if (lua_isnil(L, -1)) { - lua_pop(L, 1); /* pop result */ - *size = 0; - return NULL; - } - else if (l_unlikely(!lua_isstring(L, -1))) - luaL_error(L, "reader function must return a string"); - lua_replace(L, RESERVEDSLOT); /* save string in reserved slot */ - return lua_tolstring(L, RESERVEDSLOT, size); -} - - -static int luaB_load (lua_State *L) { - int status; - size_t l; - const char *s = lua_tolstring(L, 1, &l); - const char *mode = luaL_optstring(L, 3, "bt"); - int env = (!lua_isnone(L, 4) ? 4 : 0); /* 'env' index or 0 if no 'env' */ - if (s != NULL) { /* loading a string? */ - const char *chunkname = luaL_optstring(L, 2, s); - status = luaL_loadbufferx(L, s, l, chunkname, mode); - } - else { /* loading from a reader function */ - const char *chunkname = luaL_optstring(L, 2, "=(load)"); - luaL_checktype(L, 1, LUA_TFUNCTION); - lua_settop(L, RESERVEDSLOT); /* create reserved slot */ - status = lua_load(L, generic_reader, NULL, chunkname, mode); - } - return load_aux(L, status, env); -} - -/* }====================================================== */ - - -static int dofilecont (lua_State *L, int d1, lua_KContext d2) { - (void)d1; (void)d2; /* only to match 'lua_Kfunction' prototype */ - return lua_gettop(L) - 1; -} - - -static int luaB_dofile (lua_State *L) { - const char *fname = luaL_optstring(L, 1, NULL); - lua_settop(L, 1); - if (l_unlikely(luaL_loadfile(L, fname) != LUA_OK)) - return lua_error(L); - lua_callk(L, 0, LUA_MULTRET, 0, dofilecont); - return dofilecont(L, 0, 0); -} - - -static int luaB_assert (lua_State *L) { - if (l_likely(lua_toboolean(L, 1))) /* condition is true? */ - return lua_gettop(L); /* return all arguments */ - else { /* error */ - luaL_checkany(L, 1); /* there must be a condition */ - lua_remove(L, 1); /* remove it */ - lua_pushliteral(L, "assertion failed!"); /* default message */ - lua_settop(L, 1); /* leave only message (default if no other one) */ - return luaB_error(L); /* call 'error' */ - } -} - - -static int luaB_select (lua_State *L) { - int n = lua_gettop(L); - if (lua_type(L, 1) == LUA_TSTRING && *lua_tostring(L, 1) == '#') { - lua_pushinteger(L, n-1); - return 1; - } - else { - lua_Integer i = luaL_checkinteger(L, 1); - if (i < 0) i = n + i; - else if (i > n) i = n; - luaL_argcheck(L, 1 <= i, 1, "index out of range"); - return n - (int)i; - } -} - - -/* -** Continuation function for 'pcall' and 'xpcall'. Both functions -** already pushed a 'true' before doing the call, so in case of success -** 'finishpcall' only has to return everything in the stack minus -** 'extra' values (where 'extra' is exactly the number of items to be -** ignored). -*/ -static int finishpcall (lua_State *L, int status, lua_KContext extra) { - if (l_unlikely(status != LUA_OK && status != LUA_YIELD)) { /* error? */ - lua_pushboolean(L, 0); /* first result (false) */ - lua_pushvalue(L, -2); /* error message */ - return 2; /* return false, msg */ - } - else - return lua_gettop(L) - (int)extra; /* return all results */ -} - - -static int luaB_pcall (lua_State *L) { - int status; - luaL_checkany(L, 1); - lua_pushboolean(L, 1); /* first result if no errors */ - lua_insert(L, 1); /* put it in place */ - status = lua_pcallk(L, lua_gettop(L) - 2, LUA_MULTRET, 0, 0, finishpcall); - return finishpcall(L, status, 0); -} - - -/* -** Do a protected call with error handling. After 'lua_rotate', the -** stack will have ; so, the function passes -** 2 to 'finishpcall' to skip the 2 first values when returning results. -*/ -static int luaB_xpcall (lua_State *L) { - int status; - int n = lua_gettop(L); - luaL_checktype(L, 2, LUA_TFUNCTION); /* check error function */ - lua_pushboolean(L, 1); /* first result */ - lua_pushvalue(L, 1); /* function */ - lua_rotate(L, 3, 2); /* move them below function's arguments */ - status = lua_pcallk(L, n - 2, LUA_MULTRET, 2, 2, finishpcall); - return finishpcall(L, status, 2); -} - - -static int luaB_tostring (lua_State *L) { - luaL_checkany(L, 1); - luaL_tolstring(L, 1, NULL); - return 1; -} - - -static const luaL_Reg base_funcs[] = { - {"assert", luaB_assert}, - {"collectgarbage", luaB_collectgarbage}, - {"dofile", luaB_dofile}, - {"error", luaB_error}, - {"getmetatable", luaB_getmetatable}, - {"ipairs", luaB_ipairs}, - {"loadfile", luaB_loadfile}, - {"load", luaB_load}, - {"next", luaB_next}, - {"pairs", luaB_pairs}, - {"pcall", luaB_pcall}, - {"print", luaB_print}, - {"warn", luaB_warn}, - {"rawequal", luaB_rawequal}, - {"rawlen", luaB_rawlen}, - {"rawget", luaB_rawget}, - {"rawset", luaB_rawset}, - {"select", luaB_select}, - {"setmetatable", luaB_setmetatable}, - {"tonumber", luaB_tonumber}, - {"tostring", luaB_tostring}, - {"type", luaB_type}, - {"xpcall", luaB_xpcall}, - /* placeholders */ - {LUA_GNAME, NULL}, - {"_VERSION", NULL}, - {NULL, NULL} -}; - - -LUAMOD_API int luaopen_base (lua_State *L) { - /* open lib into global table */ - lua_pushglobaltable(L); - luaL_setfuncs(L, base_funcs, 0); - /* set global _G */ - lua_pushvalue(L, -1); - lua_setfield(L, -2, LUA_GNAME); - /* set global _VERSION */ - lua_pushliteral(L, LUA_VERSION); - lua_setfield(L, -2, "_VERSION"); - return 1; -} - diff --git a/lib/lua-5.4/src/lcode.c b/lib/lua-5.4/src/lcode.c deleted file mode 100644 index 1a371ca..0000000 --- a/lib/lua-5.4/src/lcode.c +++ /dev/null @@ -1,1871 +0,0 @@ -/* -** $Id: lcode.c $ -** Code generator for Lua -** See Copyright Notice in lua.h -*/ - -#define lcode_c -#define LUA_CORE - -#include "lprefix.h" - - -#include -#include -#include -#include - -#include "lua.h" - -#include "lcode.h" -#include "ldebug.h" -#include "ldo.h" -#include "lgc.h" -#include "llex.h" -#include "lmem.h" -#include "lobject.h" -#include "lopcodes.h" -#include "lparser.h" -#include "lstring.h" -#include "ltable.h" -#include "lvm.h" - - -/* Maximum number of registers in a Lua function (must fit in 8 bits) */ -#define MAXREGS 255 - - -#define hasjumps(e) ((e)->t != (e)->f) - - -static int codesJ (FuncState *fs, OpCode o, int sj, int k); - - - -/* semantic error */ -l_noret luaK_semerror (LexState *ls, const char *msg) { - ls->t.token = 0; /* remove "near " from final message */ - luaX_syntaxerror(ls, msg); -} - - -/* -** If expression is a numeric constant, fills 'v' with its value -** and returns 1. Otherwise, returns 0. -*/ -static int tonumeral (const expdesc *e, TValue *v) { - if (hasjumps(e)) - return 0; /* not a numeral */ - switch (e->k) { - case VKINT: - if (v) setivalue(v, e->u.ival); - return 1; - case VKFLT: - if (v) setfltvalue(v, e->u.nval); - return 1; - default: return 0; - } -} - - -/* -** Get the constant value from a constant expression -*/ -static TValue *const2val (FuncState *fs, const expdesc *e) { - lua_assert(e->k == VCONST); - return &fs->ls->dyd->actvar.arr[e->u.info].k; -} - - -/* -** If expression is a constant, fills 'v' with its value -** and returns 1. Otherwise, returns 0. -*/ -int luaK_exp2const (FuncState *fs, const expdesc *e, TValue *v) { - if (hasjumps(e)) - return 0; /* not a constant */ - switch (e->k) { - case VFALSE: - setbfvalue(v); - return 1; - case VTRUE: - setbtvalue(v); - return 1; - case VNIL: - setnilvalue(v); - return 1; - case VKSTR: { - setsvalue(fs->ls->L, v, e->u.strval); - return 1; - } - case VCONST: { - setobj(fs->ls->L, v, const2val(fs, e)); - return 1; - } - default: return tonumeral(e, v); - } -} - - -/* -** Return the previous instruction of the current code. If there -** may be a jump target between the current instruction and the -** previous one, return an invalid instruction (to avoid wrong -** optimizations). -*/ -static Instruction *previousinstruction (FuncState *fs) { - static const Instruction invalidinstruction = ~(Instruction)0; - if (fs->pc > fs->lasttarget) - return &fs->f->code[fs->pc - 1]; /* previous instruction */ - else - return cast(Instruction*, &invalidinstruction); -} - - -/* -** Create a OP_LOADNIL instruction, but try to optimize: if the previous -** instruction is also OP_LOADNIL and ranges are compatible, adjust -** range of previous instruction instead of emitting a new one. (For -** instance, 'local a; local b' will generate a single opcode.) -*/ -void luaK_nil (FuncState *fs, int from, int n) { - int l = from + n - 1; /* last register to set nil */ - Instruction *previous = previousinstruction(fs); - if (GET_OPCODE(*previous) == OP_LOADNIL) { /* previous is LOADNIL? */ - int pfrom = GETARG_A(*previous); /* get previous range */ - int pl = pfrom + GETARG_B(*previous); - if ((pfrom <= from && from <= pl + 1) || - (from <= pfrom && pfrom <= l + 1)) { /* can connect both? */ - if (pfrom < from) from = pfrom; /* from = min(from, pfrom) */ - if (pl > l) l = pl; /* l = max(l, pl) */ - SETARG_A(*previous, from); - SETARG_B(*previous, l - from); - return; - } /* else go through */ - } - luaK_codeABC(fs, OP_LOADNIL, from, n - 1, 0); /* else no optimization */ -} - - -/* -** Gets the destination address of a jump instruction. Used to traverse -** a list of jumps. -*/ -static int getjump (FuncState *fs, int pc) { - int offset = GETARG_sJ(fs->f->code[pc]); - if (offset == NO_JUMP) /* point to itself represents end of list */ - return NO_JUMP; /* end of list */ - else - return (pc+1)+offset; /* turn offset into absolute position */ -} - - -/* -** Fix jump instruction at position 'pc' to jump to 'dest'. -** (Jump addresses are relative in Lua) -*/ -static void fixjump (FuncState *fs, int pc, int dest) { - Instruction *jmp = &fs->f->code[pc]; - int offset = dest - (pc + 1); - lua_assert(dest != NO_JUMP); - if (!(-OFFSET_sJ <= offset && offset <= MAXARG_sJ - OFFSET_sJ)) - luaX_syntaxerror(fs->ls, "control structure too long"); - lua_assert(GET_OPCODE(*jmp) == OP_JMP); - SETARG_sJ(*jmp, offset); -} - - -/* -** Concatenate jump-list 'l2' into jump-list 'l1' -*/ -void luaK_concat (FuncState *fs, int *l1, int l2) { - if (l2 == NO_JUMP) return; /* nothing to concatenate? */ - else if (*l1 == NO_JUMP) /* no original list? */ - *l1 = l2; /* 'l1' points to 'l2' */ - else { - int list = *l1; - int next; - while ((next = getjump(fs, list)) != NO_JUMP) /* find last element */ - list = next; - fixjump(fs, list, l2); /* last element links to 'l2' */ - } -} - - -/* -** Create a jump instruction and return its position, so its destination -** can be fixed later (with 'fixjump'). -*/ -int luaK_jump (FuncState *fs) { - return codesJ(fs, OP_JMP, NO_JUMP, 0); -} - - -/* -** Code a 'return' instruction -*/ -void luaK_ret (FuncState *fs, int first, int nret) { - OpCode op; - switch (nret) { - case 0: op = OP_RETURN0; break; - case 1: op = OP_RETURN1; break; - default: op = OP_RETURN; break; - } - luaK_codeABC(fs, op, first, nret + 1, 0); -} - - -/* -** Code a "conditional jump", that is, a test or comparison opcode -** followed by a jump. Return jump position. -*/ -static int condjump (FuncState *fs, OpCode op, int A, int B, int C, int k) { - luaK_codeABCk(fs, op, A, B, C, k); - return luaK_jump(fs); -} - - -/* -** returns current 'pc' and marks it as a jump target (to avoid wrong -** optimizations with consecutive instructions not in the same basic block). -*/ -int luaK_getlabel (FuncState *fs) { - fs->lasttarget = fs->pc; - return fs->pc; -} - - -/* -** Returns the position of the instruction "controlling" a given -** jump (that is, its condition), or the jump itself if it is -** unconditional. -*/ -static Instruction *getjumpcontrol (FuncState *fs, int pc) { - Instruction *pi = &fs->f->code[pc]; - if (pc >= 1 && testTMode(GET_OPCODE(*(pi-1)))) - return pi-1; - else - return pi; -} - - -/* -** Patch destination register for a TESTSET instruction. -** If instruction in position 'node' is not a TESTSET, return 0 ("fails"). -** Otherwise, if 'reg' is not 'NO_REG', set it as the destination -** register. Otherwise, change instruction to a simple 'TEST' (produces -** no register value) -*/ -static int patchtestreg (FuncState *fs, int node, int reg) { - Instruction *i = getjumpcontrol(fs, node); - if (GET_OPCODE(*i) != OP_TESTSET) - return 0; /* cannot patch other instructions */ - if (reg != NO_REG && reg != GETARG_B(*i)) - SETARG_A(*i, reg); - else { - /* no register to put value or register already has the value; - change instruction to simple test */ - *i = CREATE_ABCk(OP_TEST, GETARG_B(*i), 0, 0, GETARG_k(*i)); - } - return 1; -} - - -/* -** Traverse a list of tests ensuring no one produces a value -*/ -static void removevalues (FuncState *fs, int list) { - for (; list != NO_JUMP; list = getjump(fs, list)) - patchtestreg(fs, list, NO_REG); -} - - -/* -** Traverse a list of tests, patching their destination address and -** registers: tests producing values jump to 'vtarget' (and put their -** values in 'reg'), other tests jump to 'dtarget'. -*/ -static void patchlistaux (FuncState *fs, int list, int vtarget, int reg, - int dtarget) { - while (list != NO_JUMP) { - int next = getjump(fs, list); - if (patchtestreg(fs, list, reg)) - fixjump(fs, list, vtarget); - else - fixjump(fs, list, dtarget); /* jump to default target */ - list = next; - } -} - - -/* -** Path all jumps in 'list' to jump to 'target'. -** (The assert means that we cannot fix a jump to a forward address -** because we only know addresses once code is generated.) -*/ -void luaK_patchlist (FuncState *fs, int list, int target) { - lua_assert(target <= fs->pc); - patchlistaux(fs, list, target, NO_REG, target); -} - - -void luaK_patchtohere (FuncState *fs, int list) { - int hr = luaK_getlabel(fs); /* mark "here" as a jump target */ - luaK_patchlist(fs, list, hr); -} - - -/* limit for difference between lines in relative line info. */ -#define LIMLINEDIFF 0x80 - - -/* -** Save line info for a new instruction. If difference from last line -** does not fit in a byte, of after that many instructions, save a new -** absolute line info; (in that case, the special value 'ABSLINEINFO' -** in 'lineinfo' signals the existence of this absolute information.) -** Otherwise, store the difference from last line in 'lineinfo'. -*/ -static void savelineinfo (FuncState *fs, Proto *f, int line) { - int linedif = line - fs->previousline; - int pc = fs->pc - 1; /* last instruction coded */ - if (abs(linedif) >= LIMLINEDIFF || fs->iwthabs++ >= MAXIWTHABS) { - luaM_growvector(fs->ls->L, f->abslineinfo, fs->nabslineinfo, - f->sizeabslineinfo, AbsLineInfo, MAX_INT, "lines"); - f->abslineinfo[fs->nabslineinfo].pc = pc; - f->abslineinfo[fs->nabslineinfo++].line = line; - linedif = ABSLINEINFO; /* signal that there is absolute information */ - fs->iwthabs = 1; /* restart counter */ - } - luaM_growvector(fs->ls->L, f->lineinfo, pc, f->sizelineinfo, ls_byte, - MAX_INT, "opcodes"); - f->lineinfo[pc] = linedif; - fs->previousline = line; /* last line saved */ -} - - -/* -** Remove line information from the last instruction. -** If line information for that instruction is absolute, set 'iwthabs' -** above its max to force the new (replacing) instruction to have -** absolute line info, too. -*/ -static void removelastlineinfo (FuncState *fs) { - Proto *f = fs->f; - int pc = fs->pc - 1; /* last instruction coded */ - if (f->lineinfo[pc] != ABSLINEINFO) { /* relative line info? */ - fs->previousline -= f->lineinfo[pc]; /* correct last line saved */ - fs->iwthabs--; /* undo previous increment */ - } - else { /* absolute line information */ - lua_assert(f->abslineinfo[fs->nabslineinfo - 1].pc == pc); - fs->nabslineinfo--; /* remove it */ - fs->iwthabs = MAXIWTHABS + 1; /* force next line info to be absolute */ - } -} - - -/* -** Remove the last instruction created, correcting line information -** accordingly. -*/ -static void removelastinstruction (FuncState *fs) { - removelastlineinfo(fs); - fs->pc--; -} - - -/* -** Emit instruction 'i', checking for array sizes and saving also its -** line information. Return 'i' position. -*/ -int luaK_code (FuncState *fs, Instruction i) { - Proto *f = fs->f; - /* put new instruction in code array */ - luaM_growvector(fs->ls->L, f->code, fs->pc, f->sizecode, Instruction, - MAX_INT, "opcodes"); - f->code[fs->pc++] = i; - savelineinfo(fs, f, fs->ls->lastline); - return fs->pc - 1; /* index of new instruction */ -} - - -/* -** Format and emit an 'iABC' instruction. (Assertions check consistency -** of parameters versus opcode.) -*/ -int luaK_codeABCk (FuncState *fs, OpCode o, int a, int b, int c, int k) { - lua_assert(getOpMode(o) == iABC); - lua_assert(a <= MAXARG_A && b <= MAXARG_B && - c <= MAXARG_C && (k & ~1) == 0); - return luaK_code(fs, CREATE_ABCk(o, a, b, c, k)); -} - - -/* -** Format and emit an 'iABx' instruction. -*/ -int luaK_codeABx (FuncState *fs, OpCode o, int a, unsigned int bc) { - lua_assert(getOpMode(o) == iABx); - lua_assert(a <= MAXARG_A && bc <= MAXARG_Bx); - return luaK_code(fs, CREATE_ABx(o, a, bc)); -} - - -/* -** Format and emit an 'iAsBx' instruction. -*/ -int luaK_codeAsBx (FuncState *fs, OpCode o, int a, int bc) { - unsigned int b = bc + OFFSET_sBx; - lua_assert(getOpMode(o) == iAsBx); - lua_assert(a <= MAXARG_A && b <= MAXARG_Bx); - return luaK_code(fs, CREATE_ABx(o, a, b)); -} - - -/* -** Format and emit an 'isJ' instruction. -*/ -static int codesJ (FuncState *fs, OpCode o, int sj, int k) { - unsigned int j = sj + OFFSET_sJ; - lua_assert(getOpMode(o) == isJ); - lua_assert(j <= MAXARG_sJ && (k & ~1) == 0); - return luaK_code(fs, CREATE_sJ(o, j, k)); -} - - -/* -** Emit an "extra argument" instruction (format 'iAx') -*/ -static int codeextraarg (FuncState *fs, int a) { - lua_assert(a <= MAXARG_Ax); - return luaK_code(fs, CREATE_Ax(OP_EXTRAARG, a)); -} - - -/* -** Emit a "load constant" instruction, using either 'OP_LOADK' -** (if constant index 'k' fits in 18 bits) or an 'OP_LOADKX' -** instruction with "extra argument". -*/ -static int luaK_codek (FuncState *fs, int reg, int k) { - if (k <= MAXARG_Bx) - return luaK_codeABx(fs, OP_LOADK, reg, k); - else { - int p = luaK_codeABx(fs, OP_LOADKX, reg, 0); - codeextraarg(fs, k); - return p; - } -} - - -/* -** Check register-stack level, keeping track of its maximum size -** in field 'maxstacksize' -*/ -void luaK_checkstack (FuncState *fs, int n) { - int newstack = fs->freereg + n; - if (newstack > fs->f->maxstacksize) { - if (newstack >= MAXREGS) - luaX_syntaxerror(fs->ls, - "function or expression needs too many registers"); - fs->f->maxstacksize = cast_byte(newstack); - } -} - - -/* -** Reserve 'n' registers in register stack -*/ -void luaK_reserveregs (FuncState *fs, int n) { - luaK_checkstack(fs, n); - fs->freereg += n; -} - - -/* -** Free register 'reg', if it is neither a constant index nor -** a local variable. -) -*/ -static void freereg (FuncState *fs, int reg) { - if (reg >= luaY_nvarstack(fs)) { - fs->freereg--; - lua_assert(reg == fs->freereg); - } -} - - -/* -** Free two registers in proper order -*/ -static void freeregs (FuncState *fs, int r1, int r2) { - if (r1 > r2) { - freereg(fs, r1); - freereg(fs, r2); - } - else { - freereg(fs, r2); - freereg(fs, r1); - } -} - - -/* -** Free register used by expression 'e' (if any) -*/ -static void freeexp (FuncState *fs, expdesc *e) { - if (e->k == VNONRELOC) - freereg(fs, e->u.info); -} - - -/* -** Free registers used by expressions 'e1' and 'e2' (if any) in proper -** order. -*/ -static void freeexps (FuncState *fs, expdesc *e1, expdesc *e2) { - int r1 = (e1->k == VNONRELOC) ? e1->u.info : -1; - int r2 = (e2->k == VNONRELOC) ? e2->u.info : -1; - freeregs(fs, r1, r2); -} - - -/* -** Add constant 'v' to prototype's list of constants (field 'k'). -** Use scanner's table to cache position of constants in constant list -** and try to reuse constants. Because some values should not be used -** as keys (nil cannot be a key, integer keys can collapse with float -** keys), the caller must provide a useful 'key' for indexing the cache. -** Note that all functions share the same table, so entering or exiting -** a function can make some indices wrong. -*/ -static int addk (FuncState *fs, TValue *key, TValue *v) { - TValue val; - lua_State *L = fs->ls->L; - Proto *f = fs->f; - const TValue *idx = luaH_get(fs->ls->h, key); /* query scanner table */ - int k, oldsize; - if (ttisinteger(idx)) { /* is there an index there? */ - k = cast_int(ivalue(idx)); - /* correct value? (warning: must distinguish floats from integers!) */ - if (k < fs->nk && ttypetag(&f->k[k]) == ttypetag(v) && - luaV_rawequalobj(&f->k[k], v)) - return k; /* reuse index */ - } - /* constant not found; create a new entry */ - oldsize = f->sizek; - k = fs->nk; - /* numerical value does not need GC barrier; - table has no metatable, so it does not need to invalidate cache */ - setivalue(&val, k); - luaH_finishset(L, fs->ls->h, key, idx, &val); - luaM_growvector(L, f->k, k, f->sizek, TValue, MAXARG_Ax, "constants"); - while (oldsize < f->sizek) setnilvalue(&f->k[oldsize++]); - setobj(L, &f->k[k], v); - fs->nk++; - luaC_barrier(L, f, v); - return k; -} - - -/* -** Add a string to list of constants and return its index. -*/ -static int stringK (FuncState *fs, TString *s) { - TValue o; - setsvalue(fs->ls->L, &o, s); - return addk(fs, &o, &o); /* use string itself as key */ -} - - -/* -** Add an integer to list of constants and return its index. -*/ -static int luaK_intK (FuncState *fs, lua_Integer n) { - TValue o; - setivalue(&o, n); - return addk(fs, &o, &o); /* use integer itself as key */ -} - -/* -** Add a float to list of constants and return its index. Floats -** with integral values need a different key, to avoid collision -** with actual integers. To that, we add to the number its smaller -** power-of-two fraction that is still significant in its scale. -** For doubles, that would be 1/2^52. -** (This method is not bulletproof: there may be another float -** with that value, and for floats larger than 2^53 the result is -** still an integer. At worst, this only wastes an entry with -** a duplicate.) -*/ -static int luaK_numberK (FuncState *fs, lua_Number r) { - TValue o; - lua_Integer ik; - setfltvalue(&o, r); - if (!luaV_flttointeger(r, &ik, F2Ieq)) /* not an integral value? */ - return addk(fs, &o, &o); /* use number itself as key */ - else { /* must build an alternative key */ - const int nbm = l_floatatt(MANT_DIG); - const lua_Number q = l_mathop(ldexp)(l_mathop(1.0), -nbm + 1); - const lua_Number k = (ik == 0) ? q : r + r*q; /* new key */ - TValue kv; - setfltvalue(&kv, k); - /* result is not an integral value, unless value is too large */ - lua_assert(!luaV_flttointeger(k, &ik, F2Ieq) || - l_mathop(fabs)(r) >= l_mathop(1e6)); - return addk(fs, &kv, &o); - } -} - - -/* -** Add a false to list of constants and return its index. -*/ -static int boolF (FuncState *fs) { - TValue o; - setbfvalue(&o); - return addk(fs, &o, &o); /* use boolean itself as key */ -} - - -/* -** Add a true to list of constants and return its index. -*/ -static int boolT (FuncState *fs) { - TValue o; - setbtvalue(&o); - return addk(fs, &o, &o); /* use boolean itself as key */ -} - - -/* -** Add nil to list of constants and return its index. -*/ -static int nilK (FuncState *fs) { - TValue k, v; - setnilvalue(&v); - /* cannot use nil as key; instead use table itself to represent nil */ - sethvalue(fs->ls->L, &k, fs->ls->h); - return addk(fs, &k, &v); -} - - -/* -** Check whether 'i' can be stored in an 'sC' operand. Equivalent to -** (0 <= int2sC(i) && int2sC(i) <= MAXARG_C) but without risk of -** overflows in the hidden addition inside 'int2sC'. -*/ -static int fitsC (lua_Integer i) { - return (l_castS2U(i) + OFFSET_sC <= cast_uint(MAXARG_C)); -} - - -/* -** Check whether 'i' can be stored in an 'sBx' operand. -*/ -static int fitsBx (lua_Integer i) { - return (-OFFSET_sBx <= i && i <= MAXARG_Bx - OFFSET_sBx); -} - - -void luaK_int (FuncState *fs, int reg, lua_Integer i) { - if (fitsBx(i)) - luaK_codeAsBx(fs, OP_LOADI, reg, cast_int(i)); - else - luaK_codek(fs, reg, luaK_intK(fs, i)); -} - - -static void luaK_float (FuncState *fs, int reg, lua_Number f) { - lua_Integer fi; - if (luaV_flttointeger(f, &fi, F2Ieq) && fitsBx(fi)) - luaK_codeAsBx(fs, OP_LOADF, reg, cast_int(fi)); - else - luaK_codek(fs, reg, luaK_numberK(fs, f)); -} - - -/* -** Convert a constant in 'v' into an expression description 'e' -*/ -static void const2exp (TValue *v, expdesc *e) { - switch (ttypetag(v)) { - case LUA_VNUMINT: - e->k = VKINT; e->u.ival = ivalue(v); - break; - case LUA_VNUMFLT: - e->k = VKFLT; e->u.nval = fltvalue(v); - break; - case LUA_VFALSE: - e->k = VFALSE; - break; - case LUA_VTRUE: - e->k = VTRUE; - break; - case LUA_VNIL: - e->k = VNIL; - break; - case LUA_VSHRSTR: case LUA_VLNGSTR: - e->k = VKSTR; e->u.strval = tsvalue(v); - break; - default: lua_assert(0); - } -} - - -/* -** Fix an expression to return the number of results 'nresults'. -** 'e' must be a multi-ret expression (function call or vararg). -*/ -void luaK_setreturns (FuncState *fs, expdesc *e, int nresults) { - Instruction *pc = &getinstruction(fs, e); - if (e->k == VCALL) /* expression is an open function call? */ - SETARG_C(*pc, nresults + 1); - else { - lua_assert(e->k == VVARARG); - SETARG_C(*pc, nresults + 1); - SETARG_A(*pc, fs->freereg); - luaK_reserveregs(fs, 1); - } -} - - -/* -** Convert a VKSTR to a VK -*/ -static void str2K (FuncState *fs, expdesc *e) { - lua_assert(e->k == VKSTR); - e->u.info = stringK(fs, e->u.strval); - e->k = VK; -} - - -/* -** Fix an expression to return one result. -** If expression is not a multi-ret expression (function call or -** vararg), it already returns one result, so nothing needs to be done. -** Function calls become VNONRELOC expressions (as its result comes -** fixed in the base register of the call), while vararg expressions -** become VRELOC (as OP_VARARG puts its results where it wants). -** (Calls are created returning one result, so that does not need -** to be fixed.) -*/ -void luaK_setoneret (FuncState *fs, expdesc *e) { - if (e->k == VCALL) { /* expression is an open function call? */ - /* already returns 1 value */ - lua_assert(GETARG_C(getinstruction(fs, e)) == 2); - e->k = VNONRELOC; /* result has fixed position */ - e->u.info = GETARG_A(getinstruction(fs, e)); - } - else if (e->k == VVARARG) { - SETARG_C(getinstruction(fs, e), 2); - e->k = VRELOC; /* can relocate its simple result */ - } -} - - -/* -** Ensure that expression 'e' is not a variable (nor a ). -** (Expression still may have jump lists.) -*/ -void luaK_dischargevars (FuncState *fs, expdesc *e) { - switch (e->k) { - case VCONST: { - const2exp(const2val(fs, e), e); - break; - } - case VLOCAL: { /* already in a register */ - e->u.info = e->u.var.ridx; - e->k = VNONRELOC; /* becomes a non-relocatable value */ - break; - } - case VUPVAL: { /* move value to some (pending) register */ - e->u.info = luaK_codeABC(fs, OP_GETUPVAL, 0, e->u.info, 0); - e->k = VRELOC; - break; - } - case VINDEXUP: { - e->u.info = luaK_codeABC(fs, OP_GETTABUP, 0, e->u.ind.t, e->u.ind.idx); - e->k = VRELOC; - break; - } - case VINDEXI: { - freereg(fs, e->u.ind.t); - e->u.info = luaK_codeABC(fs, OP_GETI, 0, e->u.ind.t, e->u.ind.idx); - e->k = VRELOC; - break; - } - case VINDEXSTR: { - freereg(fs, e->u.ind.t); - e->u.info = luaK_codeABC(fs, OP_GETFIELD, 0, e->u.ind.t, e->u.ind.idx); - e->k = VRELOC; - break; - } - case VINDEXED: { - freeregs(fs, e->u.ind.t, e->u.ind.idx); - e->u.info = luaK_codeABC(fs, OP_GETTABLE, 0, e->u.ind.t, e->u.ind.idx); - e->k = VRELOC; - break; - } - case VVARARG: case VCALL: { - luaK_setoneret(fs, e); - break; - } - default: break; /* there is one value available (somewhere) */ - } -} - - -/* -** Ensure expression value is in register 'reg', making 'e' a -** non-relocatable expression. -** (Expression still may have jump lists.) -*/ -static void discharge2reg (FuncState *fs, expdesc *e, int reg) { - luaK_dischargevars(fs, e); - switch (e->k) { - case VNIL: { - luaK_nil(fs, reg, 1); - break; - } - case VFALSE: { - luaK_codeABC(fs, OP_LOADFALSE, reg, 0, 0); - break; - } - case VTRUE: { - luaK_codeABC(fs, OP_LOADTRUE, reg, 0, 0); - break; - } - case VKSTR: { - str2K(fs, e); - } /* FALLTHROUGH */ - case VK: { - luaK_codek(fs, reg, e->u.info); - break; - } - case VKFLT: { - luaK_float(fs, reg, e->u.nval); - break; - } - case VKINT: { - luaK_int(fs, reg, e->u.ival); - break; - } - case VRELOC: { - Instruction *pc = &getinstruction(fs, e); - SETARG_A(*pc, reg); /* instruction will put result in 'reg' */ - break; - } - case VNONRELOC: { - if (reg != e->u.info) - luaK_codeABC(fs, OP_MOVE, reg, e->u.info, 0); - break; - } - default: { - lua_assert(e->k == VJMP); - return; /* nothing to do... */ - } - } - e->u.info = reg; - e->k = VNONRELOC; -} - - -/* -** Ensure expression value is in a register, making 'e' a -** non-relocatable expression. -** (Expression still may have jump lists.) -*/ -static void discharge2anyreg (FuncState *fs, expdesc *e) { - if (e->k != VNONRELOC) { /* no fixed register yet? */ - luaK_reserveregs(fs, 1); /* get a register */ - discharge2reg(fs, e, fs->freereg-1); /* put value there */ - } -} - - -static int code_loadbool (FuncState *fs, int A, OpCode op) { - luaK_getlabel(fs); /* those instructions may be jump targets */ - return luaK_codeABC(fs, op, A, 0, 0); -} - - -/* -** check whether list has any jump that do not produce a value -** or produce an inverted value -*/ -static int need_value (FuncState *fs, int list) { - for (; list != NO_JUMP; list = getjump(fs, list)) { - Instruction i = *getjumpcontrol(fs, list); - if (GET_OPCODE(i) != OP_TESTSET) return 1; - } - return 0; /* not found */ -} - - -/* -** Ensures final expression result (which includes results from its -** jump lists) is in register 'reg'. -** If expression has jumps, need to patch these jumps either to -** its final position or to "load" instructions (for those tests -** that do not produce values). -*/ -static void exp2reg (FuncState *fs, expdesc *e, int reg) { - discharge2reg(fs, e, reg); - if (e->k == VJMP) /* expression itself is a test? */ - luaK_concat(fs, &e->t, e->u.info); /* put this jump in 't' list */ - if (hasjumps(e)) { - int final; /* position after whole expression */ - int p_f = NO_JUMP; /* position of an eventual LOAD false */ - int p_t = NO_JUMP; /* position of an eventual LOAD true */ - if (need_value(fs, e->t) || need_value(fs, e->f)) { - int fj = (e->k == VJMP) ? NO_JUMP : luaK_jump(fs); - p_f = code_loadbool(fs, reg, OP_LFALSESKIP); /* skip next inst. */ - p_t = code_loadbool(fs, reg, OP_LOADTRUE); - /* jump around these booleans if 'e' is not a test */ - luaK_patchtohere(fs, fj); - } - final = luaK_getlabel(fs); - patchlistaux(fs, e->f, final, reg, p_f); - patchlistaux(fs, e->t, final, reg, p_t); - } - e->f = e->t = NO_JUMP; - e->u.info = reg; - e->k = VNONRELOC; -} - - -/* -** Ensures final expression result is in next available register. -*/ -void luaK_exp2nextreg (FuncState *fs, expdesc *e) { - luaK_dischargevars(fs, e); - freeexp(fs, e); - luaK_reserveregs(fs, 1); - exp2reg(fs, e, fs->freereg - 1); -} - - -/* -** Ensures final expression result is in some (any) register -** and return that register. -*/ -int luaK_exp2anyreg (FuncState *fs, expdesc *e) { - luaK_dischargevars(fs, e); - if (e->k == VNONRELOC) { /* expression already has a register? */ - if (!hasjumps(e)) /* no jumps? */ - return e->u.info; /* result is already in a register */ - if (e->u.info >= luaY_nvarstack(fs)) { /* reg. is not a local? */ - exp2reg(fs, e, e->u.info); /* put final result in it */ - return e->u.info; - } - /* else expression has jumps and cannot change its register - to hold the jump values, because it is a local variable. - Go through to the default case. */ - } - luaK_exp2nextreg(fs, e); /* default: use next available register */ - return e->u.info; -} - - -/* -** Ensures final expression result is either in a register -** or in an upvalue. -*/ -void luaK_exp2anyregup (FuncState *fs, expdesc *e) { - if (e->k != VUPVAL || hasjumps(e)) - luaK_exp2anyreg(fs, e); -} - - -/* -** Ensures final expression result is either in a register -** or it is a constant. -*/ -void luaK_exp2val (FuncState *fs, expdesc *e) { - if (hasjumps(e)) - luaK_exp2anyreg(fs, e); - else - luaK_dischargevars(fs, e); -} - - -/* -** Try to make 'e' a K expression with an index in the range of R/K -** indices. Return true iff succeeded. -*/ -static int luaK_exp2K (FuncState *fs, expdesc *e) { - if (!hasjumps(e)) { - int info; - switch (e->k) { /* move constants to 'k' */ - case VTRUE: info = boolT(fs); break; - case VFALSE: info = boolF(fs); break; - case VNIL: info = nilK(fs); break; - case VKINT: info = luaK_intK(fs, e->u.ival); break; - case VKFLT: info = luaK_numberK(fs, e->u.nval); break; - case VKSTR: info = stringK(fs, e->u.strval); break; - case VK: info = e->u.info; break; - default: return 0; /* not a constant */ - } - if (info <= MAXINDEXRK) { /* does constant fit in 'argC'? */ - e->k = VK; /* make expression a 'K' expression */ - e->u.info = info; - return 1; - } - } - /* else, expression doesn't fit; leave it unchanged */ - return 0; -} - - -/* -** Ensures final expression result is in a valid R/K index -** (that is, it is either in a register or in 'k' with an index -** in the range of R/K indices). -** Returns 1 iff expression is K. -*/ -int luaK_exp2RK (FuncState *fs, expdesc *e) { - if (luaK_exp2K(fs, e)) - return 1; - else { /* not a constant in the right range: put it in a register */ - luaK_exp2anyreg(fs, e); - return 0; - } -} - - -static void codeABRK (FuncState *fs, OpCode o, int a, int b, - expdesc *ec) { - int k = luaK_exp2RK(fs, ec); - luaK_codeABCk(fs, o, a, b, ec->u.info, k); -} - - -/* -** Generate code to store result of expression 'ex' into variable 'var'. -*/ -void luaK_storevar (FuncState *fs, expdesc *var, expdesc *ex) { - switch (var->k) { - case VLOCAL: { - freeexp(fs, ex); - exp2reg(fs, ex, var->u.var.ridx); /* compute 'ex' into proper place */ - return; - } - case VUPVAL: { - int e = luaK_exp2anyreg(fs, ex); - luaK_codeABC(fs, OP_SETUPVAL, e, var->u.info, 0); - break; - } - case VINDEXUP: { - codeABRK(fs, OP_SETTABUP, var->u.ind.t, var->u.ind.idx, ex); - break; - } - case VINDEXI: { - codeABRK(fs, OP_SETI, var->u.ind.t, var->u.ind.idx, ex); - break; - } - case VINDEXSTR: { - codeABRK(fs, OP_SETFIELD, var->u.ind.t, var->u.ind.idx, ex); - break; - } - case VINDEXED: { - codeABRK(fs, OP_SETTABLE, var->u.ind.t, var->u.ind.idx, ex); - break; - } - default: lua_assert(0); /* invalid var kind to store */ - } - freeexp(fs, ex); -} - - -/* -** Emit SELF instruction (convert expression 'e' into 'e:key(e,'). -*/ -void luaK_self (FuncState *fs, expdesc *e, expdesc *key) { - int ereg; - luaK_exp2anyreg(fs, e); - ereg = e->u.info; /* register where 'e' was placed */ - freeexp(fs, e); - e->u.info = fs->freereg; /* base register for op_self */ - e->k = VNONRELOC; /* self expression has a fixed register */ - luaK_reserveregs(fs, 2); /* function and 'self' produced by op_self */ - codeABRK(fs, OP_SELF, e->u.info, ereg, key); - freeexp(fs, key); -} - - -/* -** Negate condition 'e' (where 'e' is a comparison). -*/ -static void negatecondition (FuncState *fs, expdesc *e) { - Instruction *pc = getjumpcontrol(fs, e->u.info); - lua_assert(testTMode(GET_OPCODE(*pc)) && GET_OPCODE(*pc) != OP_TESTSET && - GET_OPCODE(*pc) != OP_TEST); - SETARG_k(*pc, (GETARG_k(*pc) ^ 1)); -} - - -/* -** Emit instruction to jump if 'e' is 'cond' (that is, if 'cond' -** is true, code will jump if 'e' is true.) Return jump position. -** Optimize when 'e' is 'not' something, inverting the condition -** and removing the 'not'. -*/ -static int jumponcond (FuncState *fs, expdesc *e, int cond) { - if (e->k == VRELOC) { - Instruction ie = getinstruction(fs, e); - if (GET_OPCODE(ie) == OP_NOT) { - removelastinstruction(fs); /* remove previous OP_NOT */ - return condjump(fs, OP_TEST, GETARG_B(ie), 0, 0, !cond); - } - /* else go through */ - } - discharge2anyreg(fs, e); - freeexp(fs, e); - return condjump(fs, OP_TESTSET, NO_REG, e->u.info, 0, cond); -} - - -/* -** Emit code to go through if 'e' is true, jump otherwise. -*/ -void luaK_goiftrue (FuncState *fs, expdesc *e) { - int pc; /* pc of new jump */ - luaK_dischargevars(fs, e); - switch (e->k) { - case VJMP: { /* condition? */ - negatecondition(fs, e); /* jump when it is false */ - pc = e->u.info; /* save jump position */ - break; - } - case VK: case VKFLT: case VKINT: case VKSTR: case VTRUE: { - pc = NO_JUMP; /* always true; do nothing */ - break; - } - default: { - pc = jumponcond(fs, e, 0); /* jump when false */ - break; - } - } - luaK_concat(fs, &e->f, pc); /* insert new jump in false list */ - luaK_patchtohere(fs, e->t); /* true list jumps to here (to go through) */ - e->t = NO_JUMP; -} - - -/* -** Emit code to go through if 'e' is false, jump otherwise. -*/ -void luaK_goiffalse (FuncState *fs, expdesc *e) { - int pc; /* pc of new jump */ - luaK_dischargevars(fs, e); - switch (e->k) { - case VJMP: { - pc = e->u.info; /* already jump if true */ - break; - } - case VNIL: case VFALSE: { - pc = NO_JUMP; /* always false; do nothing */ - break; - } - default: { - pc = jumponcond(fs, e, 1); /* jump if true */ - break; - } - } - luaK_concat(fs, &e->t, pc); /* insert new jump in 't' list */ - luaK_patchtohere(fs, e->f); /* false list jumps to here (to go through) */ - e->f = NO_JUMP; -} - - -/* -** Code 'not e', doing constant folding. -*/ -static void codenot (FuncState *fs, expdesc *e) { - switch (e->k) { - case VNIL: case VFALSE: { - e->k = VTRUE; /* true == not nil == not false */ - break; - } - case VK: case VKFLT: case VKINT: case VKSTR: case VTRUE: { - e->k = VFALSE; /* false == not "x" == not 0.5 == not 1 == not true */ - break; - } - case VJMP: { - negatecondition(fs, e); - break; - } - case VRELOC: - case VNONRELOC: { - discharge2anyreg(fs, e); - freeexp(fs, e); - e->u.info = luaK_codeABC(fs, OP_NOT, 0, e->u.info, 0); - e->k = VRELOC; - break; - } - default: lua_assert(0); /* cannot happen */ - } - /* interchange true and false lists */ - { int temp = e->f; e->f = e->t; e->t = temp; } - removevalues(fs, e->f); /* values are useless when negated */ - removevalues(fs, e->t); -} - - -/* -** Check whether expression 'e' is a small literal string -*/ -static int isKstr (FuncState *fs, expdesc *e) { - return (e->k == VK && !hasjumps(e) && e->u.info <= MAXARG_B && - ttisshrstring(&fs->f->k[e->u.info])); -} - -/* -** Check whether expression 'e' is a literal integer. -*/ -int luaK_isKint (expdesc *e) { - return (e->k == VKINT && !hasjumps(e)); -} - - -/* -** Check whether expression 'e' is a literal integer in -** proper range to fit in register C -*/ -static int isCint (expdesc *e) { - return luaK_isKint(e) && (l_castS2U(e->u.ival) <= l_castS2U(MAXARG_C)); -} - - -/* -** Check whether expression 'e' is a literal integer in -** proper range to fit in register sC -*/ -static int isSCint (expdesc *e) { - return luaK_isKint(e) && fitsC(e->u.ival); -} - - -/* -** Check whether expression 'e' is a literal integer or float in -** proper range to fit in a register (sB or sC). -*/ -static int isSCnumber (expdesc *e, int *pi, int *isfloat) { - lua_Integer i; - if (e->k == VKINT) - i = e->u.ival; - else if (e->k == VKFLT && luaV_flttointeger(e->u.nval, &i, F2Ieq)) - *isfloat = 1; - else - return 0; /* not a number */ - if (!hasjumps(e) && fitsC(i)) { - *pi = int2sC(cast_int(i)); - return 1; - } - else - return 0; -} - - -/* -** Create expression 't[k]'. 't' must have its final result already in a -** register or upvalue. Upvalues can only be indexed by literal strings. -** Keys can be literal strings in the constant table or arbitrary -** values in registers. -*/ -void luaK_indexed (FuncState *fs, expdesc *t, expdesc *k) { - if (k->k == VKSTR) - str2K(fs, k); - lua_assert(!hasjumps(t) && - (t->k == VLOCAL || t->k == VNONRELOC || t->k == VUPVAL)); - if (t->k == VUPVAL && !isKstr(fs, k)) /* upvalue indexed by non 'Kstr'? */ - luaK_exp2anyreg(fs, t); /* put it in a register */ - if (t->k == VUPVAL) { - t->u.ind.t = t->u.info; /* upvalue index */ - t->u.ind.idx = k->u.info; /* literal string */ - t->k = VINDEXUP; - } - else { - /* register index of the table */ - t->u.ind.t = (t->k == VLOCAL) ? t->u.var.ridx: t->u.info; - if (isKstr(fs, k)) { - t->u.ind.idx = k->u.info; /* literal string */ - t->k = VINDEXSTR; - } - else if (isCint(k)) { - t->u.ind.idx = cast_int(k->u.ival); /* int. constant in proper range */ - t->k = VINDEXI; - } - else { - t->u.ind.idx = luaK_exp2anyreg(fs, k); /* register */ - t->k = VINDEXED; - } - } -} - - -/* -** Return false if folding can raise an error. -** Bitwise operations need operands convertible to integers; division -** operations cannot have 0 as divisor. -*/ -static int validop (int op, TValue *v1, TValue *v2) { - switch (op) { - case LUA_OPBAND: case LUA_OPBOR: case LUA_OPBXOR: - case LUA_OPSHL: case LUA_OPSHR: case LUA_OPBNOT: { /* conversion errors */ - lua_Integer i; - return (luaV_tointegerns(v1, &i, LUA_FLOORN2I) && - luaV_tointegerns(v2, &i, LUA_FLOORN2I)); - } - case LUA_OPDIV: case LUA_OPIDIV: case LUA_OPMOD: /* division by 0 */ - return (nvalue(v2) != 0); - default: return 1; /* everything else is valid */ - } -} - - -/* -** Try to "constant-fold" an operation; return 1 iff successful. -** (In this case, 'e1' has the final result.) -*/ -static int constfolding (FuncState *fs, int op, expdesc *e1, - const expdesc *e2) { - TValue v1, v2, res; - if (!tonumeral(e1, &v1) || !tonumeral(e2, &v2) || !validop(op, &v1, &v2)) - return 0; /* non-numeric operands or not safe to fold */ - luaO_rawarith(fs->ls->L, op, &v1, &v2, &res); /* does operation */ - if (ttisinteger(&res)) { - e1->k = VKINT; - e1->u.ival = ivalue(&res); - } - else { /* folds neither NaN nor 0.0 (to avoid problems with -0.0) */ - lua_Number n = fltvalue(&res); - if (luai_numisnan(n) || n == 0) - return 0; - e1->k = VKFLT; - e1->u.nval = n; - } - return 1; -} - - -/* -** Convert a BinOpr to an OpCode (ORDER OPR - ORDER OP) -*/ -l_sinline OpCode binopr2op (BinOpr opr, BinOpr baser, OpCode base) { - lua_assert(baser <= opr && - ((baser == OPR_ADD && opr <= OPR_SHR) || - (baser == OPR_LT && opr <= OPR_LE))); - return cast(OpCode, (cast_int(opr) - cast_int(baser)) + cast_int(base)); -} - - -/* -** Convert a UnOpr to an OpCode (ORDER OPR - ORDER OP) -*/ -l_sinline OpCode unopr2op (UnOpr opr) { - return cast(OpCode, (cast_int(opr) - cast_int(OPR_MINUS)) + - cast_int(OP_UNM)); -} - - -/* -** Convert a BinOpr to a tag method (ORDER OPR - ORDER TM) -*/ -l_sinline TMS binopr2TM (BinOpr opr) { - lua_assert(OPR_ADD <= opr && opr <= OPR_SHR); - return cast(TMS, (cast_int(opr) - cast_int(OPR_ADD)) + cast_int(TM_ADD)); -} - - -/* -** Emit code for unary expressions that "produce values" -** (everything but 'not'). -** Expression to produce final result will be encoded in 'e'. -*/ -static void codeunexpval (FuncState *fs, OpCode op, expdesc *e, int line) { - int r = luaK_exp2anyreg(fs, e); /* opcodes operate only on registers */ - freeexp(fs, e); - e->u.info = luaK_codeABC(fs, op, 0, r, 0); /* generate opcode */ - e->k = VRELOC; /* all those operations are relocatable */ - luaK_fixline(fs, line); -} - - -/* -** Emit code for binary expressions that "produce values" -** (everything but logical operators 'and'/'or' and comparison -** operators). -** Expression to produce final result will be encoded in 'e1'. -*/ -static void finishbinexpval (FuncState *fs, expdesc *e1, expdesc *e2, - OpCode op, int v2, int flip, int line, - OpCode mmop, TMS event) { - int v1 = luaK_exp2anyreg(fs, e1); - int pc = luaK_codeABCk(fs, op, 0, v1, v2, 0); - freeexps(fs, e1, e2); - e1->u.info = pc; - e1->k = VRELOC; /* all those operations are relocatable */ - luaK_fixline(fs, line); - luaK_codeABCk(fs, mmop, v1, v2, event, flip); /* to call metamethod */ - luaK_fixline(fs, line); -} - - -/* -** Emit code for binary expressions that "produce values" over -** two registers. -*/ -static void codebinexpval (FuncState *fs, BinOpr opr, - expdesc *e1, expdesc *e2, int line) { - OpCode op = binopr2op(opr, OPR_ADD, OP_ADD); - int v2 = luaK_exp2anyreg(fs, e2); /* make sure 'e2' is in a register */ - /* 'e1' must be already in a register or it is a constant */ - lua_assert((VNIL <= e1->k && e1->k <= VKSTR) || - e1->k == VNONRELOC || e1->k == VRELOC); - lua_assert(OP_ADD <= op && op <= OP_SHR); - finishbinexpval(fs, e1, e2, op, v2, 0, line, OP_MMBIN, binopr2TM(opr)); -} - - -/* -** Code binary operators with immediate operands. -*/ -static void codebini (FuncState *fs, OpCode op, - expdesc *e1, expdesc *e2, int flip, int line, - TMS event) { - int v2 = int2sC(cast_int(e2->u.ival)); /* immediate operand */ - lua_assert(e2->k == VKINT); - finishbinexpval(fs, e1, e2, op, v2, flip, line, OP_MMBINI, event); -} - - -/* -** Code binary operators with K operand. -*/ -static void codebinK (FuncState *fs, BinOpr opr, - expdesc *e1, expdesc *e2, int flip, int line) { - TMS event = binopr2TM(opr); - int v2 = e2->u.info; /* K index */ - OpCode op = binopr2op(opr, OPR_ADD, OP_ADDK); - finishbinexpval(fs, e1, e2, op, v2, flip, line, OP_MMBINK, event); -} - - -/* Try to code a binary operator negating its second operand. -** For the metamethod, 2nd operand must keep its original value. -*/ -static int finishbinexpneg (FuncState *fs, expdesc *e1, expdesc *e2, - OpCode op, int line, TMS event) { - if (!luaK_isKint(e2)) - return 0; /* not an integer constant */ - else { - lua_Integer i2 = e2->u.ival; - if (!(fitsC(i2) && fitsC(-i2))) - return 0; /* not in the proper range */ - else { /* operating a small integer constant */ - int v2 = cast_int(i2); - finishbinexpval(fs, e1, e2, op, int2sC(-v2), 0, line, OP_MMBINI, event); - /* correct metamethod argument */ - SETARG_B(fs->f->code[fs->pc - 1], int2sC(v2)); - return 1; /* successfully coded */ - } - } -} - - -static void swapexps (expdesc *e1, expdesc *e2) { - expdesc temp = *e1; *e1 = *e2; *e2 = temp; /* swap 'e1' and 'e2' */ -} - - -/* -** Code binary operators with no constant operand. -*/ -static void codebinNoK (FuncState *fs, BinOpr opr, - expdesc *e1, expdesc *e2, int flip, int line) { - if (flip) - swapexps(e1, e2); /* back to original order */ - codebinexpval(fs, opr, e1, e2, line); /* use standard operators */ -} - - -/* -** Code arithmetic operators ('+', '-', ...). If second operand is a -** constant in the proper range, use variant opcodes with K operands. -*/ -static void codearith (FuncState *fs, BinOpr opr, - expdesc *e1, expdesc *e2, int flip, int line) { - if (tonumeral(e2, NULL) && luaK_exp2K(fs, e2)) /* K operand? */ - codebinK(fs, opr, e1, e2, flip, line); - else /* 'e2' is neither an immediate nor a K operand */ - codebinNoK(fs, opr, e1, e2, flip, line); -} - - -/* -** Code commutative operators ('+', '*'). If first operand is a -** numeric constant, change order of operands to try to use an -** immediate or K operator. -*/ -static void codecommutative (FuncState *fs, BinOpr op, - expdesc *e1, expdesc *e2, int line) { - int flip = 0; - if (tonumeral(e1, NULL)) { /* is first operand a numeric constant? */ - swapexps(e1, e2); /* change order */ - flip = 1; - } - if (op == OPR_ADD && isSCint(e2)) /* immediate operand? */ - codebini(fs, OP_ADDI, e1, e2, flip, line, TM_ADD); - else - codearith(fs, op, e1, e2, flip, line); -} - - -/* -** Code bitwise operations; they are all commutative, so the function -** tries to put an integer constant as the 2nd operand (a K operand). -*/ -static void codebitwise (FuncState *fs, BinOpr opr, - expdesc *e1, expdesc *e2, int line) { - int flip = 0; - if (e1->k == VKINT) { - swapexps(e1, e2); /* 'e2' will be the constant operand */ - flip = 1; - } - if (e2->k == VKINT && luaK_exp2K(fs, e2)) /* K operand? */ - codebinK(fs, opr, e1, e2, flip, line); - else /* no constants */ - codebinNoK(fs, opr, e1, e2, flip, line); -} - - -/* -** Emit code for order comparisons. When using an immediate operand, -** 'isfloat' tells whether the original value was a float. -*/ -static void codeorder (FuncState *fs, BinOpr opr, expdesc *e1, expdesc *e2) { - int r1, r2; - int im; - int isfloat = 0; - OpCode op; - if (isSCnumber(e2, &im, &isfloat)) { - /* use immediate operand */ - r1 = luaK_exp2anyreg(fs, e1); - r2 = im; - op = binopr2op(opr, OPR_LT, OP_LTI); - } - else if (isSCnumber(e1, &im, &isfloat)) { - /* transform (A < B) to (B > A) and (A <= B) to (B >= A) */ - r1 = luaK_exp2anyreg(fs, e2); - r2 = im; - op = binopr2op(opr, OPR_LT, OP_GTI); - } - else { /* regular case, compare two registers */ - r1 = luaK_exp2anyreg(fs, e1); - r2 = luaK_exp2anyreg(fs, e2); - op = binopr2op(opr, OPR_LT, OP_LT); - } - freeexps(fs, e1, e2); - e1->u.info = condjump(fs, op, r1, r2, isfloat, 1); - e1->k = VJMP; -} - - -/* -** Emit code for equality comparisons ('==', '~='). -** 'e1' was already put as RK by 'luaK_infix'. -*/ -static void codeeq (FuncState *fs, BinOpr opr, expdesc *e1, expdesc *e2) { - int r1, r2; - int im; - int isfloat = 0; /* not needed here, but kept for symmetry */ - OpCode op; - if (e1->k != VNONRELOC) { - lua_assert(e1->k == VK || e1->k == VKINT || e1->k == VKFLT); - swapexps(e1, e2); - } - r1 = luaK_exp2anyreg(fs, e1); /* 1st expression must be in register */ - if (isSCnumber(e2, &im, &isfloat)) { - op = OP_EQI; - r2 = im; /* immediate operand */ - } - else if (luaK_exp2RK(fs, e2)) { /* 2nd expression is constant? */ - op = OP_EQK; - r2 = e2->u.info; /* constant index */ - } - else { - op = OP_EQ; /* will compare two registers */ - r2 = luaK_exp2anyreg(fs, e2); - } - freeexps(fs, e1, e2); - e1->u.info = condjump(fs, op, r1, r2, isfloat, (opr == OPR_EQ)); - e1->k = VJMP; -} - - -/* -** Apply prefix operation 'op' to expression 'e'. -*/ -void luaK_prefix (FuncState *fs, UnOpr opr, expdesc *e, int line) { - static const expdesc ef = {VKINT, {0}, NO_JUMP, NO_JUMP}; - luaK_dischargevars(fs, e); - switch (opr) { - case OPR_MINUS: case OPR_BNOT: /* use 'ef' as fake 2nd operand */ - if (constfolding(fs, opr + LUA_OPUNM, e, &ef)) - break; - /* else */ /* FALLTHROUGH */ - case OPR_LEN: - codeunexpval(fs, unopr2op(opr), e, line); - break; - case OPR_NOT: codenot(fs, e); break; - default: lua_assert(0); - } -} - - -/* -** Process 1st operand 'v' of binary operation 'op' before reading -** 2nd operand. -*/ -void luaK_infix (FuncState *fs, BinOpr op, expdesc *v) { - luaK_dischargevars(fs, v); - switch (op) { - case OPR_AND: { - luaK_goiftrue(fs, v); /* go ahead only if 'v' is true */ - break; - } - case OPR_OR: { - luaK_goiffalse(fs, v); /* go ahead only if 'v' is false */ - break; - } - case OPR_CONCAT: { - luaK_exp2nextreg(fs, v); /* operand must be on the stack */ - break; - } - case OPR_ADD: case OPR_SUB: - case OPR_MUL: case OPR_DIV: case OPR_IDIV: - case OPR_MOD: case OPR_POW: - case OPR_BAND: case OPR_BOR: case OPR_BXOR: - case OPR_SHL: case OPR_SHR: { - if (!tonumeral(v, NULL)) - luaK_exp2anyreg(fs, v); - /* else keep numeral, which may be folded or used as an immediate - operand */ - break; - } - case OPR_EQ: case OPR_NE: { - if (!tonumeral(v, NULL)) - luaK_exp2RK(fs, v); - /* else keep numeral, which may be an immediate operand */ - break; - } - case OPR_LT: case OPR_LE: - case OPR_GT: case OPR_GE: { - int dummy, dummy2; - if (!isSCnumber(v, &dummy, &dummy2)) - luaK_exp2anyreg(fs, v); - /* else keep numeral, which may be an immediate operand */ - break; - } - default: lua_assert(0); - } -} - -/* -** Create code for '(e1 .. e2)'. -** For '(e1 .. e2.1 .. e2.2)' (which is '(e1 .. (e2.1 .. e2.2))', -** because concatenation is right associative), merge both CONCATs. -*/ -static void codeconcat (FuncState *fs, expdesc *e1, expdesc *e2, int line) { - Instruction *ie2 = previousinstruction(fs); - if (GET_OPCODE(*ie2) == OP_CONCAT) { /* is 'e2' a concatenation? */ - int n = GETARG_B(*ie2); /* # of elements concatenated in 'e2' */ - lua_assert(e1->u.info + 1 == GETARG_A(*ie2)); - freeexp(fs, e2); - SETARG_A(*ie2, e1->u.info); /* correct first element ('e1') */ - SETARG_B(*ie2, n + 1); /* will concatenate one more element */ - } - else { /* 'e2' is not a concatenation */ - luaK_codeABC(fs, OP_CONCAT, e1->u.info, 2, 0); /* new concat opcode */ - freeexp(fs, e2); - luaK_fixline(fs, line); - } -} - - -/* -** Finalize code for binary operation, after reading 2nd operand. -*/ -void luaK_posfix (FuncState *fs, BinOpr opr, - expdesc *e1, expdesc *e2, int line) { - luaK_dischargevars(fs, e2); - if (foldbinop(opr) && constfolding(fs, opr + LUA_OPADD, e1, e2)) - return; /* done by folding */ - switch (opr) { - case OPR_AND: { - lua_assert(e1->t == NO_JUMP); /* list closed by 'luaK_infix' */ - luaK_concat(fs, &e2->f, e1->f); - *e1 = *e2; - break; - } - case OPR_OR: { - lua_assert(e1->f == NO_JUMP); /* list closed by 'luaK_infix' */ - luaK_concat(fs, &e2->t, e1->t); - *e1 = *e2; - break; - } - case OPR_CONCAT: { /* e1 .. e2 */ - luaK_exp2nextreg(fs, e2); - codeconcat(fs, e1, e2, line); - break; - } - case OPR_ADD: case OPR_MUL: { - codecommutative(fs, opr, e1, e2, line); - break; - } - case OPR_SUB: { - if (finishbinexpneg(fs, e1, e2, OP_ADDI, line, TM_SUB)) - break; /* coded as (r1 + -I) */ - /* ELSE */ - } /* FALLTHROUGH */ - case OPR_DIV: case OPR_IDIV: case OPR_MOD: case OPR_POW: { - codearith(fs, opr, e1, e2, 0, line); - break; - } - case OPR_BAND: case OPR_BOR: case OPR_BXOR: { - codebitwise(fs, opr, e1, e2, line); - break; - } - case OPR_SHL: { - if (isSCint(e1)) { - swapexps(e1, e2); - codebini(fs, OP_SHLI, e1, e2, 1, line, TM_SHL); /* I << r2 */ - } - else if (finishbinexpneg(fs, e1, e2, OP_SHRI, line, TM_SHL)) { - /* coded as (r1 >> -I) */; - } - else /* regular case (two registers) */ - codebinexpval(fs, opr, e1, e2, line); - break; - } - case OPR_SHR: { - if (isSCint(e2)) - codebini(fs, OP_SHRI, e1, e2, 0, line, TM_SHR); /* r1 >> I */ - else /* regular case (two registers) */ - codebinexpval(fs, opr, e1, e2, line); - break; - } - case OPR_EQ: case OPR_NE: { - codeeq(fs, opr, e1, e2); - break; - } - case OPR_GT: case OPR_GE: { - /* '(a > b)' <=> '(b < a)'; '(a >= b)' <=> '(b <= a)' */ - swapexps(e1, e2); - opr = cast(BinOpr, (opr - OPR_GT) + OPR_LT); - } /* FALLTHROUGH */ - case OPR_LT: case OPR_LE: { - codeorder(fs, opr, e1, e2); - break; - } - default: lua_assert(0); - } -} - - -/* -** Change line information associated with current position, by removing -** previous info and adding it again with new line. -*/ -void luaK_fixline (FuncState *fs, int line) { - removelastlineinfo(fs); - savelineinfo(fs, fs->f, line); -} - - -void luaK_settablesize (FuncState *fs, int pc, int ra, int asize, int hsize) { - Instruction *inst = &fs->f->code[pc]; - int rb = (hsize != 0) ? luaO_ceillog2(hsize) + 1 : 0; /* hash size */ - int extra = asize / (MAXARG_C + 1); /* higher bits of array size */ - int rc = asize % (MAXARG_C + 1); /* lower bits of array size */ - int k = (extra > 0); /* true iff needs extra argument */ - *inst = CREATE_ABCk(OP_NEWTABLE, ra, rb, rc, k); - *(inst + 1) = CREATE_Ax(OP_EXTRAARG, extra); -} - - -/* -** Emit a SETLIST instruction. -** 'base' is register that keeps table; -** 'nelems' is #table plus those to be stored now; -** 'tostore' is number of values (in registers 'base + 1',...) to add to -** table (or LUA_MULTRET to add up to stack top). -*/ -void luaK_setlist (FuncState *fs, int base, int nelems, int tostore) { - lua_assert(tostore != 0 && tostore <= LFIELDS_PER_FLUSH); - if (tostore == LUA_MULTRET) - tostore = 0; - if (nelems <= MAXARG_C) - luaK_codeABC(fs, OP_SETLIST, base, tostore, nelems); - else { - int extra = nelems / (MAXARG_C + 1); - nelems %= (MAXARG_C + 1); - luaK_codeABCk(fs, OP_SETLIST, base, tostore, nelems, 1); - codeextraarg(fs, extra); - } - fs->freereg = base + 1; /* free registers with list values */ -} - - -/* -** return the final target of a jump (skipping jumps to jumps) -*/ -static int finaltarget (Instruction *code, int i) { - int count; - for (count = 0; count < 100; count++) { /* avoid infinite loops */ - Instruction pc = code[i]; - if (GET_OPCODE(pc) != OP_JMP) - break; - else - i += GETARG_sJ(pc) + 1; - } - return i; -} - - -/* -** Do a final pass over the code of a function, doing small peephole -** optimizations and adjustments. -*/ -void luaK_finish (FuncState *fs) { - int i; - Proto *p = fs->f; - for (i = 0; i < fs->pc; i++) { - Instruction *pc = &p->code[i]; - lua_assert(i == 0 || isOT(*(pc - 1)) == isIT(*pc)); - switch (GET_OPCODE(*pc)) { - case OP_RETURN0: case OP_RETURN1: { - if (!(fs->needclose || p->is_vararg)) - break; /* no extra work */ - /* else use OP_RETURN to do the extra work */ - SET_OPCODE(*pc, OP_RETURN); - } /* FALLTHROUGH */ - case OP_RETURN: case OP_TAILCALL: { - if (fs->needclose) - SETARG_k(*pc, 1); /* signal that it needs to close */ - if (p->is_vararg) - SETARG_C(*pc, p->numparams + 1); /* signal that it is vararg */ - break; - } - case OP_JMP: { - int target = finaltarget(p->code, i); - fixjump(fs, i, target); - break; - } - default: break; - } - } -} diff --git a/lib/lua-5.4/src/lcode.h b/lib/lua-5.4/src/lcode.h deleted file mode 100644 index 3265824..0000000 --- a/lib/lua-5.4/src/lcode.h +++ /dev/null @@ -1,104 +0,0 @@ -/* -** $Id: lcode.h $ -** Code generator for Lua -** See Copyright Notice in lua.h -*/ - -#ifndef lcode_h -#define lcode_h - -#include "llex.h" -#include "lobject.h" -#include "lopcodes.h" -#include "lparser.h" - - -/* -** Marks the end of a patch list. It is an invalid value both as an absolute -** address, and as a list link (would link an element to itself). -*/ -#define NO_JUMP (-1) - - -/* -** grep "ORDER OPR" if you change these enums (ORDER OP) -*/ -typedef enum BinOpr { - /* arithmetic operators */ - OPR_ADD, OPR_SUB, OPR_MUL, OPR_MOD, OPR_POW, - OPR_DIV, OPR_IDIV, - /* bitwise operators */ - OPR_BAND, OPR_BOR, OPR_BXOR, - OPR_SHL, OPR_SHR, - /* string operator */ - OPR_CONCAT, - /* comparison operators */ - OPR_EQ, OPR_LT, OPR_LE, - OPR_NE, OPR_GT, OPR_GE, - /* logical operators */ - OPR_AND, OPR_OR, - OPR_NOBINOPR -} BinOpr; - - -/* true if operation is foldable (that is, it is arithmetic or bitwise) */ -#define foldbinop(op) ((op) <= OPR_SHR) - - -#define luaK_codeABC(fs,o,a,b,c) luaK_codeABCk(fs,o,a,b,c,0) - - -typedef enum UnOpr { OPR_MINUS, OPR_BNOT, OPR_NOT, OPR_LEN, OPR_NOUNOPR } UnOpr; - - -/* get (pointer to) instruction of given 'expdesc' */ -#define getinstruction(fs,e) ((fs)->f->code[(e)->u.info]) - - -#define luaK_setmultret(fs,e) luaK_setreturns(fs, e, LUA_MULTRET) - -#define luaK_jumpto(fs,t) luaK_patchlist(fs, luaK_jump(fs), t) - -LUAI_FUNC int luaK_code (FuncState *fs, Instruction i); -LUAI_FUNC int luaK_codeABx (FuncState *fs, OpCode o, int A, unsigned int Bx); -LUAI_FUNC int luaK_codeAsBx (FuncState *fs, OpCode o, int A, int Bx); -LUAI_FUNC int luaK_codeABCk (FuncState *fs, OpCode o, int A, - int B, int C, int k); -LUAI_FUNC int luaK_isKint (expdesc *e); -LUAI_FUNC int luaK_exp2const (FuncState *fs, const expdesc *e, TValue *v); -LUAI_FUNC void luaK_fixline (FuncState *fs, int line); -LUAI_FUNC void luaK_nil (FuncState *fs, int from, int n); -LUAI_FUNC void luaK_reserveregs (FuncState *fs, int n); -LUAI_FUNC void luaK_checkstack (FuncState *fs, int n); -LUAI_FUNC void luaK_int (FuncState *fs, int reg, lua_Integer n); -LUAI_FUNC void luaK_dischargevars (FuncState *fs, expdesc *e); -LUAI_FUNC int luaK_exp2anyreg (FuncState *fs, expdesc *e); -LUAI_FUNC void luaK_exp2anyregup (FuncState *fs, expdesc *e); -LUAI_FUNC void luaK_exp2nextreg (FuncState *fs, expdesc *e); -LUAI_FUNC void luaK_exp2val (FuncState *fs, expdesc *e); -LUAI_FUNC int luaK_exp2RK (FuncState *fs, expdesc *e); -LUAI_FUNC void luaK_self (FuncState *fs, expdesc *e, expdesc *key); -LUAI_FUNC void luaK_indexed (FuncState *fs, expdesc *t, expdesc *k); -LUAI_FUNC void luaK_goiftrue (FuncState *fs, expdesc *e); -LUAI_FUNC void luaK_goiffalse (FuncState *fs, expdesc *e); -LUAI_FUNC void luaK_storevar (FuncState *fs, expdesc *var, expdesc *e); -LUAI_FUNC void luaK_setreturns (FuncState *fs, expdesc *e, int nresults); -LUAI_FUNC void luaK_setoneret (FuncState *fs, expdesc *e); -LUAI_FUNC int luaK_jump (FuncState *fs); -LUAI_FUNC void luaK_ret (FuncState *fs, int first, int nret); -LUAI_FUNC void luaK_patchlist (FuncState *fs, int list, int target); -LUAI_FUNC void luaK_patchtohere (FuncState *fs, int list); -LUAI_FUNC void luaK_concat (FuncState *fs, int *l1, int l2); -LUAI_FUNC int luaK_getlabel (FuncState *fs); -LUAI_FUNC void luaK_prefix (FuncState *fs, UnOpr op, expdesc *v, int line); -LUAI_FUNC void luaK_infix (FuncState *fs, BinOpr op, expdesc *v); -LUAI_FUNC void luaK_posfix (FuncState *fs, BinOpr op, expdesc *v1, - expdesc *v2, int line); -LUAI_FUNC void luaK_settablesize (FuncState *fs, int pc, - int ra, int asize, int hsize); -LUAI_FUNC void luaK_setlist (FuncState *fs, int base, int nelems, int tostore); -LUAI_FUNC void luaK_finish (FuncState *fs); -LUAI_FUNC l_noret luaK_semerror (LexState *ls, const char *msg); - - -#endif diff --git a/lib/lua-5.4/src/lcorolib.c b/lib/lua-5.4/src/lcorolib.c deleted file mode 100644 index c64adf0..0000000 --- a/lib/lua-5.4/src/lcorolib.c +++ /dev/null @@ -1,210 +0,0 @@ -/* -** $Id: lcorolib.c $ -** Coroutine Library -** See Copyright Notice in lua.h -*/ - -#define lcorolib_c -#define LUA_LIB - -#include "lprefix.h" - - -#include - -#include "lua.h" - -#include "lauxlib.h" -#include "lualib.h" - - -static lua_State *getco (lua_State *L) { - lua_State *co = lua_tothread(L, 1); - luaL_argexpected(L, co, 1, "thread"); - return co; -} - - -/* -** Resumes a coroutine. Returns the number of results for non-error -** cases or -1 for errors. -*/ -static int auxresume (lua_State *L, lua_State *co, int narg) { - int status, nres; - if (l_unlikely(!lua_checkstack(co, narg))) { - lua_pushliteral(L, "too many arguments to resume"); - return -1; /* error flag */ - } - lua_xmove(L, co, narg); - status = lua_resume(co, L, narg, &nres); - if (l_likely(status == LUA_OK || status == LUA_YIELD)) { - if (l_unlikely(!lua_checkstack(L, nres + 1))) { - lua_pop(co, nres); /* remove results anyway */ - lua_pushliteral(L, "too many results to resume"); - return -1; /* error flag */ - } - lua_xmove(co, L, nres); /* move yielded values */ - return nres; - } - else { - lua_xmove(co, L, 1); /* move error message */ - return -1; /* error flag */ - } -} - - -static int luaB_coresume (lua_State *L) { - lua_State *co = getco(L); - int r; - r = auxresume(L, co, lua_gettop(L) - 1); - if (l_unlikely(r < 0)) { - lua_pushboolean(L, 0); - lua_insert(L, -2); - return 2; /* return false + error message */ - } - else { - lua_pushboolean(L, 1); - lua_insert(L, -(r + 1)); - return r + 1; /* return true + 'resume' returns */ - } -} - - -static int luaB_auxwrap (lua_State *L) { - lua_State *co = lua_tothread(L, lua_upvalueindex(1)); - int r = auxresume(L, co, lua_gettop(L)); - if (l_unlikely(r < 0)) { /* error? */ - int stat = lua_status(co); - if (stat != LUA_OK && stat != LUA_YIELD) { /* error in the coroutine? */ - stat = lua_closethread(co, L); /* close its tbc variables */ - lua_assert(stat != LUA_OK); - lua_xmove(co, L, 1); /* move error message to the caller */ - } - if (stat != LUA_ERRMEM && /* not a memory error and ... */ - lua_type(L, -1) == LUA_TSTRING) { /* ... error object is a string? */ - luaL_where(L, 1); /* add extra info, if available */ - lua_insert(L, -2); - lua_concat(L, 2); - } - return lua_error(L); /* propagate error */ - } - return r; -} - - -static int luaB_cocreate (lua_State *L) { - lua_State *NL; - luaL_checktype(L, 1, LUA_TFUNCTION); - NL = lua_newthread(L); - lua_pushvalue(L, 1); /* move function to top */ - lua_xmove(L, NL, 1); /* move function from L to NL */ - return 1; -} - - -static int luaB_cowrap (lua_State *L) { - luaB_cocreate(L); - lua_pushcclosure(L, luaB_auxwrap, 1); - return 1; -} - - -static int luaB_yield (lua_State *L) { - return lua_yield(L, lua_gettop(L)); -} - - -#define COS_RUN 0 -#define COS_DEAD 1 -#define COS_YIELD 2 -#define COS_NORM 3 - - -static const char *const statname[] = - {"running", "dead", "suspended", "normal"}; - - -static int auxstatus (lua_State *L, lua_State *co) { - if (L == co) return COS_RUN; - else { - switch (lua_status(co)) { - case LUA_YIELD: - return COS_YIELD; - case LUA_OK: { - lua_Debug ar; - if (lua_getstack(co, 0, &ar)) /* does it have frames? */ - return COS_NORM; /* it is running */ - else if (lua_gettop(co) == 0) - return COS_DEAD; - else - return COS_YIELD; /* initial state */ - } - default: /* some error occurred */ - return COS_DEAD; - } - } -} - - -static int luaB_costatus (lua_State *L) { - lua_State *co = getco(L); - lua_pushstring(L, statname[auxstatus(L, co)]); - return 1; -} - - -static int luaB_yieldable (lua_State *L) { - lua_State *co = lua_isnone(L, 1) ? L : getco(L); - lua_pushboolean(L, lua_isyieldable(co)); - return 1; -} - - -static int luaB_corunning (lua_State *L) { - int ismain = lua_pushthread(L); - lua_pushboolean(L, ismain); - return 2; -} - - -static int luaB_close (lua_State *L) { - lua_State *co = getco(L); - int status = auxstatus(L, co); - switch (status) { - case COS_DEAD: case COS_YIELD: { - status = lua_closethread(co, L); - if (status == LUA_OK) { - lua_pushboolean(L, 1); - return 1; - } - else { - lua_pushboolean(L, 0); - lua_xmove(co, L, 1); /* move error message */ - return 2; - } - } - default: /* normal or running coroutine */ - return luaL_error(L, "cannot close a %s coroutine", statname[status]); - } -} - - -static const luaL_Reg co_funcs[] = { - {"create", luaB_cocreate}, - {"resume", luaB_coresume}, - {"running", luaB_corunning}, - {"status", luaB_costatus}, - {"wrap", luaB_cowrap}, - {"yield", luaB_yield}, - {"isyieldable", luaB_yieldable}, - {"close", luaB_close}, - {NULL, NULL} -}; - - - -LUAMOD_API int luaopen_coroutine (lua_State *L) { - luaL_newlib(L, co_funcs); - return 1; -} - diff --git a/lib/lua-5.4/src/lctype.c b/lib/lua-5.4/src/lctype.c deleted file mode 100644 index 9542280..0000000 --- a/lib/lua-5.4/src/lctype.c +++ /dev/null @@ -1,64 +0,0 @@ -/* -** $Id: lctype.c $ -** 'ctype' functions for Lua -** See Copyright Notice in lua.h -*/ - -#define lctype_c -#define LUA_CORE - -#include "lprefix.h" - - -#include "lctype.h" - -#if !LUA_USE_CTYPE /* { */ - -#include - - -#if defined (LUA_UCID) /* accept UniCode IDentifiers? */ -/* consider all non-ascii codepoints to be alphabetic */ -#define NONA 0x01 -#else -#define NONA 0x00 /* default */ -#endif - - -LUAI_DDEF const lu_byte luai_ctype_[UCHAR_MAX + 2] = { - 0x00, /* EOZ */ - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0. */ - 0x00, 0x08, 0x08, 0x08, 0x08, 0x08, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 1. */ - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x0c, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, /* 2. */ - 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, - 0x16, 0x16, 0x16, 0x16, 0x16, 0x16, 0x16, 0x16, /* 3. */ - 0x16, 0x16, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, - 0x04, 0x15, 0x15, 0x15, 0x15, 0x15, 0x15, 0x05, /* 4. */ - 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, - 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, /* 5. */ - 0x05, 0x05, 0x05, 0x04, 0x04, 0x04, 0x04, 0x05, - 0x04, 0x15, 0x15, 0x15, 0x15, 0x15, 0x15, 0x05, /* 6. */ - 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, - 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, /* 7. */ - 0x05, 0x05, 0x05, 0x04, 0x04, 0x04, 0x04, 0x00, - NONA, NONA, NONA, NONA, NONA, NONA, NONA, NONA, /* 8. */ - NONA, NONA, NONA, NONA, NONA, NONA, NONA, NONA, - NONA, NONA, NONA, NONA, NONA, NONA, NONA, NONA, /* 9. */ - NONA, NONA, NONA, NONA, NONA, NONA, NONA, NONA, - NONA, NONA, NONA, NONA, NONA, NONA, NONA, NONA, /* a. */ - NONA, NONA, NONA, NONA, NONA, NONA, NONA, NONA, - NONA, NONA, NONA, NONA, NONA, NONA, NONA, NONA, /* b. */ - NONA, NONA, NONA, NONA, NONA, NONA, NONA, NONA, - 0x00, 0x00, NONA, NONA, NONA, NONA, NONA, NONA, /* c. */ - NONA, NONA, NONA, NONA, NONA, NONA, NONA, NONA, - NONA, NONA, NONA, NONA, NONA, NONA, NONA, NONA, /* d. */ - NONA, NONA, NONA, NONA, NONA, NONA, NONA, NONA, - NONA, NONA, NONA, NONA, NONA, NONA, NONA, NONA, /* e. */ - NONA, NONA, NONA, NONA, NONA, NONA, NONA, NONA, - NONA, NONA, NONA, NONA, NONA, 0x00, 0x00, 0x00, /* f. */ - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 -}; - -#endif /* } */ diff --git a/lib/lua-5.4/src/lctype.h b/lib/lua-5.4/src/lctype.h deleted file mode 100644 index 864e190..0000000 --- a/lib/lua-5.4/src/lctype.h +++ /dev/null @@ -1,101 +0,0 @@ -/* -** $Id: lctype.h $ -** 'ctype' functions for Lua -** See Copyright Notice in lua.h -*/ - -#ifndef lctype_h -#define lctype_h - -#include "lua.h" - - -/* -** WARNING: the functions defined here do not necessarily correspond -** to the similar functions in the standard C ctype.h. They are -** optimized for the specific needs of Lua. -*/ - -#if !defined(LUA_USE_CTYPE) - -#if 'A' == 65 && '0' == 48 -/* ASCII case: can use its own tables; faster and fixed */ -#define LUA_USE_CTYPE 0 -#else -/* must use standard C ctype */ -#define LUA_USE_CTYPE 1 -#endif - -#endif - - -#if !LUA_USE_CTYPE /* { */ - -#include - -#include "llimits.h" - - -#define ALPHABIT 0 -#define DIGITBIT 1 -#define PRINTBIT 2 -#define SPACEBIT 3 -#define XDIGITBIT 4 - - -#define MASK(B) (1 << (B)) - - -/* -** add 1 to char to allow index -1 (EOZ) -*/ -#define testprop(c,p) (luai_ctype_[(c)+1] & (p)) - -/* -** 'lalpha' (Lua alphabetic) and 'lalnum' (Lua alphanumeric) both include '_' -*/ -#define lislalpha(c) testprop(c, MASK(ALPHABIT)) -#define lislalnum(c) testprop(c, (MASK(ALPHABIT) | MASK(DIGITBIT))) -#define lisdigit(c) testprop(c, MASK(DIGITBIT)) -#define lisspace(c) testprop(c, MASK(SPACEBIT)) -#define lisprint(c) testprop(c, MASK(PRINTBIT)) -#define lisxdigit(c) testprop(c, MASK(XDIGITBIT)) - - -/* -** In ASCII, this 'ltolower' is correct for alphabetic characters and -** for '.'. That is enough for Lua needs. ('check_exp' ensures that -** the character either is an upper-case letter or is unchanged by -** the transformation, which holds for lower-case letters and '.'.) -*/ -#define ltolower(c) \ - check_exp(('A' <= (c) && (c) <= 'Z') || (c) == ((c) | ('A' ^ 'a')), \ - (c) | ('A' ^ 'a')) - - -/* one entry for each character and for -1 (EOZ) */ -LUAI_DDEC(const lu_byte luai_ctype_[UCHAR_MAX + 2];) - - -#else /* }{ */ - -/* -** use standard C ctypes -*/ - -#include - - -#define lislalpha(c) (isalpha(c) || (c) == '_') -#define lislalnum(c) (isalnum(c) || (c) == '_') -#define lisdigit(c) (isdigit(c)) -#define lisspace(c) (isspace(c)) -#define lisprint(c) (isprint(c)) -#define lisxdigit(c) (isxdigit(c)) - -#define ltolower(c) (tolower(c)) - -#endif /* } */ - -#endif - diff --git a/lib/lua-5.4/src/ldblib.c b/lib/lua-5.4/src/ldblib.c deleted file mode 100644 index 6dcbaa9..0000000 --- a/lib/lua-5.4/src/ldblib.c +++ /dev/null @@ -1,483 +0,0 @@ -/* -** $Id: ldblib.c $ -** Interface from Lua to its debug API -** See Copyright Notice in lua.h -*/ - -#define ldblib_c -#define LUA_LIB - -#include "lprefix.h" - - -#include -#include -#include - -#include "lua.h" - -#include "lauxlib.h" -#include "lualib.h" - - -/* -** The hook table at registry[HOOKKEY] maps threads to their current -** hook function. -*/ -static const char *const HOOKKEY = "_HOOKKEY"; - - -/* -** If L1 != L, L1 can be in any state, and therefore there are no -** guarantees about its stack space; any push in L1 must be -** checked. -*/ -static void checkstack (lua_State *L, lua_State *L1, int n) { - if (l_unlikely(L != L1 && !lua_checkstack(L1, n))) - luaL_error(L, "stack overflow"); -} - - -static int db_getregistry (lua_State *L) { - lua_pushvalue(L, LUA_REGISTRYINDEX); - return 1; -} - - -static int db_getmetatable (lua_State *L) { - luaL_checkany(L, 1); - if (!lua_getmetatable(L, 1)) { - lua_pushnil(L); /* no metatable */ - } - return 1; -} - - -static int db_setmetatable (lua_State *L) { - int t = lua_type(L, 2); - luaL_argexpected(L, t == LUA_TNIL || t == LUA_TTABLE, 2, "nil or table"); - lua_settop(L, 2); - lua_setmetatable(L, 1); - return 1; /* return 1st argument */ -} - - -static int db_getuservalue (lua_State *L) { - int n = (int)luaL_optinteger(L, 2, 1); - if (lua_type(L, 1) != LUA_TUSERDATA) - luaL_pushfail(L); - else if (lua_getiuservalue(L, 1, n) != LUA_TNONE) { - lua_pushboolean(L, 1); - return 2; - } - return 1; -} - - -static int db_setuservalue (lua_State *L) { - int n = (int)luaL_optinteger(L, 3, 1); - luaL_checktype(L, 1, LUA_TUSERDATA); - luaL_checkany(L, 2); - lua_settop(L, 2); - if (!lua_setiuservalue(L, 1, n)) - luaL_pushfail(L); - return 1; -} - - -/* -** Auxiliary function used by several library functions: check for -** an optional thread as function's first argument and set 'arg' with -** 1 if this argument is present (so that functions can skip it to -** access their other arguments) -*/ -static lua_State *getthread (lua_State *L, int *arg) { - if (lua_isthread(L, 1)) { - *arg = 1; - return lua_tothread(L, 1); - } - else { - *arg = 0; - return L; /* function will operate over current thread */ - } -} - - -/* -** Variations of 'lua_settable', used by 'db_getinfo' to put results -** from 'lua_getinfo' into result table. Key is always a string; -** value can be a string, an int, or a boolean. -*/ -static void settabss (lua_State *L, const char *k, const char *v) { - lua_pushstring(L, v); - lua_setfield(L, -2, k); -} - -static void settabsi (lua_State *L, const char *k, int v) { - lua_pushinteger(L, v); - lua_setfield(L, -2, k); -} - -static void settabsb (lua_State *L, const char *k, int v) { - lua_pushboolean(L, v); - lua_setfield(L, -2, k); -} - - -/* -** In function 'db_getinfo', the call to 'lua_getinfo' may push -** results on the stack; later it creates the result table to put -** these objects. Function 'treatstackoption' puts the result from -** 'lua_getinfo' on top of the result table so that it can call -** 'lua_setfield'. -*/ -static void treatstackoption (lua_State *L, lua_State *L1, const char *fname) { - if (L == L1) - lua_rotate(L, -2, 1); /* exchange object and table */ - else - lua_xmove(L1, L, 1); /* move object to the "main" stack */ - lua_setfield(L, -2, fname); /* put object into table */ -} - - -/* -** Calls 'lua_getinfo' and collects all results in a new table. -** L1 needs stack space for an optional input (function) plus -** two optional outputs (function and line table) from function -** 'lua_getinfo'. -*/ -static int db_getinfo (lua_State *L) { - lua_Debug ar; - int arg; - lua_State *L1 = getthread(L, &arg); - const char *options = luaL_optstring(L, arg+2, "flnSrtu"); - checkstack(L, L1, 3); - luaL_argcheck(L, options[0] != '>', arg + 2, "invalid option '>'"); - if (lua_isfunction(L, arg + 1)) { /* info about a function? */ - options = lua_pushfstring(L, ">%s", options); /* add '>' to 'options' */ - lua_pushvalue(L, arg + 1); /* move function to 'L1' stack */ - lua_xmove(L, L1, 1); - } - else { /* stack level */ - if (!lua_getstack(L1, (int)luaL_checkinteger(L, arg + 1), &ar)) { - luaL_pushfail(L); /* level out of range */ - return 1; - } - } - if (!lua_getinfo(L1, options, &ar)) - return luaL_argerror(L, arg+2, "invalid option"); - lua_newtable(L); /* table to collect results */ - if (strchr(options, 'S')) { - lua_pushlstring(L, ar.source, ar.srclen); - lua_setfield(L, -2, "source"); - settabss(L, "short_src", ar.short_src); - settabsi(L, "linedefined", ar.linedefined); - settabsi(L, "lastlinedefined", ar.lastlinedefined); - settabss(L, "what", ar.what); - } - if (strchr(options, 'l')) - settabsi(L, "currentline", ar.currentline); - if (strchr(options, 'u')) { - settabsi(L, "nups", ar.nups); - settabsi(L, "nparams", ar.nparams); - settabsb(L, "isvararg", ar.isvararg); - } - if (strchr(options, 'n')) { - settabss(L, "name", ar.name); - settabss(L, "namewhat", ar.namewhat); - } - if (strchr(options, 'r')) { - settabsi(L, "ftransfer", ar.ftransfer); - settabsi(L, "ntransfer", ar.ntransfer); - } - if (strchr(options, 't')) - settabsb(L, "istailcall", ar.istailcall); - if (strchr(options, 'L')) - treatstackoption(L, L1, "activelines"); - if (strchr(options, 'f')) - treatstackoption(L, L1, "func"); - return 1; /* return table */ -} - - -static int db_getlocal (lua_State *L) { - int arg; - lua_State *L1 = getthread(L, &arg); - int nvar = (int)luaL_checkinteger(L, arg + 2); /* local-variable index */ - if (lua_isfunction(L, arg + 1)) { /* function argument? */ - lua_pushvalue(L, arg + 1); /* push function */ - lua_pushstring(L, lua_getlocal(L, NULL, nvar)); /* push local name */ - return 1; /* return only name (there is no value) */ - } - else { /* stack-level argument */ - lua_Debug ar; - const char *name; - int level = (int)luaL_checkinteger(L, arg + 1); - if (l_unlikely(!lua_getstack(L1, level, &ar))) /* out of range? */ - return luaL_argerror(L, arg+1, "level out of range"); - checkstack(L, L1, 1); - name = lua_getlocal(L1, &ar, nvar); - if (name) { - lua_xmove(L1, L, 1); /* move local value */ - lua_pushstring(L, name); /* push name */ - lua_rotate(L, -2, 1); /* re-order */ - return 2; - } - else { - luaL_pushfail(L); /* no name (nor value) */ - return 1; - } - } -} - - -static int db_setlocal (lua_State *L) { - int arg; - const char *name; - lua_State *L1 = getthread(L, &arg); - lua_Debug ar; - int level = (int)luaL_checkinteger(L, arg + 1); - int nvar = (int)luaL_checkinteger(L, arg + 2); - if (l_unlikely(!lua_getstack(L1, level, &ar))) /* out of range? */ - return luaL_argerror(L, arg+1, "level out of range"); - luaL_checkany(L, arg+3); - lua_settop(L, arg+3); - checkstack(L, L1, 1); - lua_xmove(L, L1, 1); - name = lua_setlocal(L1, &ar, nvar); - if (name == NULL) - lua_pop(L1, 1); /* pop value (if not popped by 'lua_setlocal') */ - lua_pushstring(L, name); - return 1; -} - - -/* -** get (if 'get' is true) or set an upvalue from a closure -*/ -static int auxupvalue (lua_State *L, int get) { - const char *name; - int n = (int)luaL_checkinteger(L, 2); /* upvalue index */ - luaL_checktype(L, 1, LUA_TFUNCTION); /* closure */ - name = get ? lua_getupvalue(L, 1, n) : lua_setupvalue(L, 1, n); - if (name == NULL) return 0; - lua_pushstring(L, name); - lua_insert(L, -(get+1)); /* no-op if get is false */ - return get + 1; -} - - -static int db_getupvalue (lua_State *L) { - return auxupvalue(L, 1); -} - - -static int db_setupvalue (lua_State *L) { - luaL_checkany(L, 3); - return auxupvalue(L, 0); -} - - -/* -** Check whether a given upvalue from a given closure exists and -** returns its index -*/ -static void *checkupval (lua_State *L, int argf, int argnup, int *pnup) { - void *id; - int nup = (int)luaL_checkinteger(L, argnup); /* upvalue index */ - luaL_checktype(L, argf, LUA_TFUNCTION); /* closure */ - id = lua_upvalueid(L, argf, nup); - if (pnup) { - luaL_argcheck(L, id != NULL, argnup, "invalid upvalue index"); - *pnup = nup; - } - return id; -} - - -static int db_upvalueid (lua_State *L) { - void *id = checkupval(L, 1, 2, NULL); - if (id != NULL) - lua_pushlightuserdata(L, id); - else - luaL_pushfail(L); - return 1; -} - - -static int db_upvaluejoin (lua_State *L) { - int n1, n2; - checkupval(L, 1, 2, &n1); - checkupval(L, 3, 4, &n2); - luaL_argcheck(L, !lua_iscfunction(L, 1), 1, "Lua function expected"); - luaL_argcheck(L, !lua_iscfunction(L, 3), 3, "Lua function expected"); - lua_upvaluejoin(L, 1, n1, 3, n2); - return 0; -} - - -/* -** Call hook function registered at hook table for the current -** thread (if there is one) -*/ -static void hookf (lua_State *L, lua_Debug *ar) { - static const char *const hooknames[] = - {"call", "return", "line", "count", "tail call"}; - lua_getfield(L, LUA_REGISTRYINDEX, HOOKKEY); - lua_pushthread(L); - if (lua_rawget(L, -2) == LUA_TFUNCTION) { /* is there a hook function? */ - lua_pushstring(L, hooknames[(int)ar->event]); /* push event name */ - if (ar->currentline >= 0) - lua_pushinteger(L, ar->currentline); /* push current line */ - else lua_pushnil(L); - lua_assert(lua_getinfo(L, "lS", ar)); - lua_call(L, 2, 0); /* call hook function */ - } -} - - -/* -** Convert a string mask (for 'sethook') into a bit mask -*/ -static int makemask (const char *smask, int count) { - int mask = 0; - if (strchr(smask, 'c')) mask |= LUA_MASKCALL; - if (strchr(smask, 'r')) mask |= LUA_MASKRET; - if (strchr(smask, 'l')) mask |= LUA_MASKLINE; - if (count > 0) mask |= LUA_MASKCOUNT; - return mask; -} - - -/* -** Convert a bit mask (for 'gethook') into a string mask -*/ -static char *unmakemask (int mask, char *smask) { - int i = 0; - if (mask & LUA_MASKCALL) smask[i++] = 'c'; - if (mask & LUA_MASKRET) smask[i++] = 'r'; - if (mask & LUA_MASKLINE) smask[i++] = 'l'; - smask[i] = '\0'; - return smask; -} - - -static int db_sethook (lua_State *L) { - int arg, mask, count; - lua_Hook func; - lua_State *L1 = getthread(L, &arg); - if (lua_isnoneornil(L, arg+1)) { /* no hook? */ - lua_settop(L, arg+1); - func = NULL; mask = 0; count = 0; /* turn off hooks */ - } - else { - const char *smask = luaL_checkstring(L, arg+2); - luaL_checktype(L, arg+1, LUA_TFUNCTION); - count = (int)luaL_optinteger(L, arg + 3, 0); - func = hookf; mask = makemask(smask, count); - } - if (!luaL_getsubtable(L, LUA_REGISTRYINDEX, HOOKKEY)) { - /* table just created; initialize it */ - lua_pushliteral(L, "k"); - lua_setfield(L, -2, "__mode"); /** hooktable.__mode = "k" */ - lua_pushvalue(L, -1); - lua_setmetatable(L, -2); /* metatable(hooktable) = hooktable */ - } - checkstack(L, L1, 1); - lua_pushthread(L1); lua_xmove(L1, L, 1); /* key (thread) */ - lua_pushvalue(L, arg + 1); /* value (hook function) */ - lua_rawset(L, -3); /* hooktable[L1] = new Lua hook */ - lua_sethook(L1, func, mask, count); - return 0; -} - - -static int db_gethook (lua_State *L) { - int arg; - lua_State *L1 = getthread(L, &arg); - char buff[5]; - int mask = lua_gethookmask(L1); - lua_Hook hook = lua_gethook(L1); - if (hook == NULL) { /* no hook? */ - luaL_pushfail(L); - return 1; - } - else if (hook != hookf) /* external hook? */ - lua_pushliteral(L, "external hook"); - else { /* hook table must exist */ - lua_getfield(L, LUA_REGISTRYINDEX, HOOKKEY); - checkstack(L, L1, 1); - lua_pushthread(L1); lua_xmove(L1, L, 1); - lua_rawget(L, -2); /* 1st result = hooktable[L1] */ - lua_remove(L, -2); /* remove hook table */ - } - lua_pushstring(L, unmakemask(mask, buff)); /* 2nd result = mask */ - lua_pushinteger(L, lua_gethookcount(L1)); /* 3rd result = count */ - return 3; -} - - -static int db_debug (lua_State *L) { - for (;;) { - char buffer[250]; - lua_writestringerror("%s", "lua_debug> "); - if (fgets(buffer, sizeof(buffer), stdin) == NULL || - strcmp(buffer, "cont\n") == 0) - return 0; - if (luaL_loadbuffer(L, buffer, strlen(buffer), "=(debug command)") || - lua_pcall(L, 0, 0, 0)) - lua_writestringerror("%s\n", luaL_tolstring(L, -1, NULL)); - lua_settop(L, 0); /* remove eventual returns */ - } -} - - -static int db_traceback (lua_State *L) { - int arg; - lua_State *L1 = getthread(L, &arg); - const char *msg = lua_tostring(L, arg + 1); - if (msg == NULL && !lua_isnoneornil(L, arg + 1)) /* non-string 'msg'? */ - lua_pushvalue(L, arg + 1); /* return it untouched */ - else { - int level = (int)luaL_optinteger(L, arg + 2, (L == L1) ? 1 : 0); - luaL_traceback(L, L1, msg, level); - } - return 1; -} - - -static int db_setcstacklimit (lua_State *L) { - int limit = (int)luaL_checkinteger(L, 1); - int res = lua_setcstacklimit(L, limit); - lua_pushinteger(L, res); - return 1; -} - - -static const luaL_Reg dblib[] = { - {"debug", db_debug}, - {"getuservalue", db_getuservalue}, - {"gethook", db_gethook}, - {"getinfo", db_getinfo}, - {"getlocal", db_getlocal}, - {"getregistry", db_getregistry}, - {"getmetatable", db_getmetatable}, - {"getupvalue", db_getupvalue}, - {"upvaluejoin", db_upvaluejoin}, - {"upvalueid", db_upvalueid}, - {"setuservalue", db_setuservalue}, - {"sethook", db_sethook}, - {"setlocal", db_setlocal}, - {"setmetatable", db_setmetatable}, - {"setupvalue", db_setupvalue}, - {"traceback", db_traceback}, - {"setcstacklimit", db_setcstacklimit}, - {NULL, NULL} -}; - - -LUAMOD_API int luaopen_debug (lua_State *L) { - luaL_newlib(L, dblib); - return 1; -} - diff --git a/lib/lua-5.4/src/ldebug.c b/lib/lua-5.4/src/ldebug.c deleted file mode 100644 index 28b1caa..0000000 --- a/lib/lua-5.4/src/ldebug.c +++ /dev/null @@ -1,924 +0,0 @@ -/* -** $Id: ldebug.c $ -** Debug Interface -** See Copyright Notice in lua.h -*/ - -#define ldebug_c -#define LUA_CORE - -#include "lprefix.h" - - -#include -#include -#include - -#include "lua.h" - -#include "lapi.h" -#include "lcode.h" -#include "ldebug.h" -#include "ldo.h" -#include "lfunc.h" -#include "lobject.h" -#include "lopcodes.h" -#include "lstate.h" -#include "lstring.h" -#include "ltable.h" -#include "ltm.h" -#include "lvm.h" - - - -#define noLuaClosure(f) ((f) == NULL || (f)->c.tt == LUA_VCCL) - - -static const char *funcnamefromcall (lua_State *L, CallInfo *ci, - const char **name); - - -static int currentpc (CallInfo *ci) { - lua_assert(isLua(ci)); - return pcRel(ci->u.l.savedpc, ci_func(ci)->p); -} - - -/* -** Get a "base line" to find the line corresponding to an instruction. -** Base lines are regularly placed at MAXIWTHABS intervals, so usually -** an integer division gets the right place. When the source file has -** large sequences of empty/comment lines, it may need extra entries, -** so the original estimate needs a correction. -** If the original estimate is -1, the initial 'if' ensures that the -** 'while' will run at least once. -** The assertion that the estimate is a lower bound for the correct base -** is valid as long as the debug info has been generated with the same -** value for MAXIWTHABS or smaller. (Previous releases use a little -** smaller value.) -*/ -static int getbaseline (const Proto *f, int pc, int *basepc) { - if (f->sizeabslineinfo == 0 || pc < f->abslineinfo[0].pc) { - *basepc = -1; /* start from the beginning */ - return f->linedefined; - } - else { - int i = cast_uint(pc) / MAXIWTHABS - 1; /* get an estimate */ - /* estimate must be a lower bound of the correct base */ - lua_assert(i < 0 || - (i < f->sizeabslineinfo && f->abslineinfo[i].pc <= pc)); - while (i + 1 < f->sizeabslineinfo && pc >= f->abslineinfo[i + 1].pc) - i++; /* low estimate; adjust it */ - *basepc = f->abslineinfo[i].pc; - return f->abslineinfo[i].line; - } -} - - -/* -** Get the line corresponding to instruction 'pc' in function 'f'; -** first gets a base line and from there does the increments until -** the desired instruction. -*/ -int luaG_getfuncline (const Proto *f, int pc) { - if (f->lineinfo == NULL) /* no debug information? */ - return -1; - else { - int basepc; - int baseline = getbaseline(f, pc, &basepc); - while (basepc++ < pc) { /* walk until given instruction */ - lua_assert(f->lineinfo[basepc] != ABSLINEINFO); - baseline += f->lineinfo[basepc]; /* correct line */ - } - return baseline; - } -} - - -static int getcurrentline (CallInfo *ci) { - return luaG_getfuncline(ci_func(ci)->p, currentpc(ci)); -} - - -/* -** Set 'trap' for all active Lua frames. -** This function can be called during a signal, under "reasonable" -** assumptions. A new 'ci' is completely linked in the list before it -** becomes part of the "active" list, and we assume that pointers are -** atomic; see comment in next function. -** (A compiler doing interprocedural optimizations could, theoretically, -** reorder memory writes in such a way that the list could be -** temporarily broken while inserting a new element. We simply assume it -** has no good reasons to do that.) -*/ -static void settraps (CallInfo *ci) { - for (; ci != NULL; ci = ci->previous) - if (isLua(ci)) - ci->u.l.trap = 1; -} - - -/* -** This function can be called during a signal, under "reasonable" -** assumptions. -** Fields 'basehookcount' and 'hookcount' (set by 'resethookcount') -** are for debug only, and it is no problem if they get arbitrary -** values (causes at most one wrong hook call). 'hookmask' is an atomic -** value. We assume that pointers are atomic too (e.g., gcc ensures that -** for all platforms where it runs). Moreover, 'hook' is always checked -** before being called (see 'luaD_hook'). -*/ -LUA_API void lua_sethook (lua_State *L, lua_Hook func, int mask, int count) { - if (func == NULL || mask == 0) { /* turn off hooks? */ - mask = 0; - func = NULL; - } - L->hook = func; - L->basehookcount = count; - resethookcount(L); - L->hookmask = cast_byte(mask); - if (mask) - settraps(L->ci); /* to trace inside 'luaV_execute' */ -} - - -LUA_API lua_Hook lua_gethook (lua_State *L) { - return L->hook; -} - - -LUA_API int lua_gethookmask (lua_State *L) { - return L->hookmask; -} - - -LUA_API int lua_gethookcount (lua_State *L) { - return L->basehookcount; -} - - -LUA_API int lua_getstack (lua_State *L, int level, lua_Debug *ar) { - int status; - CallInfo *ci; - if (level < 0) return 0; /* invalid (negative) level */ - lua_lock(L); - for (ci = L->ci; level > 0 && ci != &L->base_ci; ci = ci->previous) - level--; - if (level == 0 && ci != &L->base_ci) { /* level found? */ - status = 1; - ar->i_ci = ci; - } - else status = 0; /* no such level */ - lua_unlock(L); - return status; -} - - -static const char *upvalname (const Proto *p, int uv) { - TString *s = check_exp(uv < p->sizeupvalues, p->upvalues[uv].name); - if (s == NULL) return "?"; - else return getstr(s); -} - - -static const char *findvararg (CallInfo *ci, int n, StkId *pos) { - if (clLvalue(s2v(ci->func.p))->p->is_vararg) { - int nextra = ci->u.l.nextraargs; - if (n >= -nextra) { /* 'n' is negative */ - *pos = ci->func.p - nextra - (n + 1); - return "(vararg)"; /* generic name for any vararg */ - } - } - return NULL; /* no such vararg */ -} - - -const char *luaG_findlocal (lua_State *L, CallInfo *ci, int n, StkId *pos) { - StkId base = ci->func.p + 1; - const char *name = NULL; - if (isLua(ci)) { - if (n < 0) /* access to vararg values? */ - return findvararg(ci, n, pos); - else - name = luaF_getlocalname(ci_func(ci)->p, n, currentpc(ci)); - } - if (name == NULL) { /* no 'standard' name? */ - StkId limit = (ci == L->ci) ? L->top.p : ci->next->func.p; - if (limit - base >= n && n > 0) { /* is 'n' inside 'ci' stack? */ - /* generic name for any valid slot */ - name = isLua(ci) ? "(temporary)" : "(C temporary)"; - } - else - return NULL; /* no name */ - } - if (pos) - *pos = base + (n - 1); - return name; -} - - -LUA_API const char *lua_getlocal (lua_State *L, const lua_Debug *ar, int n) { - const char *name; - lua_lock(L); - if (ar == NULL) { /* information about non-active function? */ - if (!isLfunction(s2v(L->top.p - 1))) /* not a Lua function? */ - name = NULL; - else /* consider live variables at function start (parameters) */ - name = luaF_getlocalname(clLvalue(s2v(L->top.p - 1))->p, n, 0); - } - else { /* active function; get information through 'ar' */ - StkId pos = NULL; /* to avoid warnings */ - name = luaG_findlocal(L, ar->i_ci, n, &pos); - if (name) { - setobjs2s(L, L->top.p, pos); - api_incr_top(L); - } - } - lua_unlock(L); - return name; -} - - -LUA_API const char *lua_setlocal (lua_State *L, const lua_Debug *ar, int n) { - StkId pos = NULL; /* to avoid warnings */ - const char *name; - lua_lock(L); - name = luaG_findlocal(L, ar->i_ci, n, &pos); - if (name) { - setobjs2s(L, pos, L->top.p - 1); - L->top.p--; /* pop value */ - } - lua_unlock(L); - return name; -} - - -static void funcinfo (lua_Debug *ar, Closure *cl) { - if (noLuaClosure(cl)) { - ar->source = "=[C]"; - ar->srclen = LL("=[C]"); - ar->linedefined = -1; - ar->lastlinedefined = -1; - ar->what = "C"; - } - else { - const Proto *p = cl->l.p; - if (p->source) { - ar->source = getstr(p->source); - ar->srclen = tsslen(p->source); - } - else { - ar->source = "=?"; - ar->srclen = LL("=?"); - } - ar->linedefined = p->linedefined; - ar->lastlinedefined = p->lastlinedefined; - ar->what = (ar->linedefined == 0) ? "main" : "Lua"; - } - luaO_chunkid(ar->short_src, ar->source, ar->srclen); -} - - -static int nextline (const Proto *p, int currentline, int pc) { - if (p->lineinfo[pc] != ABSLINEINFO) - return currentline + p->lineinfo[pc]; - else - return luaG_getfuncline(p, pc); -} - - -static void collectvalidlines (lua_State *L, Closure *f) { - if (noLuaClosure(f)) { - setnilvalue(s2v(L->top.p)); - api_incr_top(L); - } - else { - int i; - TValue v; - const Proto *p = f->l.p; - int currentline = p->linedefined; - Table *t = luaH_new(L); /* new table to store active lines */ - sethvalue2s(L, L->top.p, t); /* push it on stack */ - api_incr_top(L); - setbtvalue(&v); /* boolean 'true' to be the value of all indices */ - if (!p->is_vararg) /* regular function? */ - i = 0; /* consider all instructions */ - else { /* vararg function */ - lua_assert(GET_OPCODE(p->code[0]) == OP_VARARGPREP); - currentline = nextline(p, currentline, 0); - i = 1; /* skip first instruction (OP_VARARGPREP) */ - } - for (; i < p->sizelineinfo; i++) { /* for each instruction */ - currentline = nextline(p, currentline, i); /* get its line */ - luaH_setint(L, t, currentline, &v); /* table[line] = true */ - } - } -} - - -static const char *getfuncname (lua_State *L, CallInfo *ci, const char **name) { - /* calling function is a known function? */ - if (ci != NULL && !(ci->callstatus & CIST_TAIL)) - return funcnamefromcall(L, ci->previous, name); - else return NULL; /* no way to find a name */ -} - - -static int auxgetinfo (lua_State *L, const char *what, lua_Debug *ar, - Closure *f, CallInfo *ci) { - int status = 1; - for (; *what; what++) { - switch (*what) { - case 'S': { - funcinfo(ar, f); - break; - } - case 'l': { - ar->currentline = (ci && isLua(ci)) ? getcurrentline(ci) : -1; - break; - } - case 'u': { - ar->nups = (f == NULL) ? 0 : f->c.nupvalues; - if (noLuaClosure(f)) { - ar->isvararg = 1; - ar->nparams = 0; - } - else { - ar->isvararg = f->l.p->is_vararg; - ar->nparams = f->l.p->numparams; - } - break; - } - case 't': { - ar->istailcall = (ci) ? ci->callstatus & CIST_TAIL : 0; - break; - } - case 'n': { - ar->namewhat = getfuncname(L, ci, &ar->name); - if (ar->namewhat == NULL) { - ar->namewhat = ""; /* not found */ - ar->name = NULL; - } - break; - } - case 'r': { - if (ci == NULL || !(ci->callstatus & CIST_TRAN)) - ar->ftransfer = ar->ntransfer = 0; - else { - ar->ftransfer = ci->u2.transferinfo.ftransfer; - ar->ntransfer = ci->u2.transferinfo.ntransfer; - } - break; - } - case 'L': - case 'f': /* handled by lua_getinfo */ - break; - default: status = 0; /* invalid option */ - } - } - return status; -} - - -LUA_API int lua_getinfo (lua_State *L, const char *what, lua_Debug *ar) { - int status; - Closure *cl; - CallInfo *ci; - TValue *func; - lua_lock(L); - if (*what == '>') { - ci = NULL; - func = s2v(L->top.p - 1); - api_check(L, ttisfunction(func), "function expected"); - what++; /* skip the '>' */ - L->top.p--; /* pop function */ - } - else { - ci = ar->i_ci; - func = s2v(ci->func.p); - lua_assert(ttisfunction(func)); - } - cl = ttisclosure(func) ? clvalue(func) : NULL; - status = auxgetinfo(L, what, ar, cl, ci); - if (strchr(what, 'f')) { - setobj2s(L, L->top.p, func); - api_incr_top(L); - } - if (strchr(what, 'L')) - collectvalidlines(L, cl); - lua_unlock(L); - return status; -} - - -/* -** {====================================================== -** Symbolic Execution -** ======================================================= -*/ - -static const char *getobjname (const Proto *p, int lastpc, int reg, - const char **name); - - -/* -** Find a "name" for the constant 'c'. -*/ -static void kname (const Proto *p, int c, const char **name) { - TValue *kvalue = &p->k[c]; - *name = (ttisstring(kvalue)) ? svalue(kvalue) : "?"; -} - - -/* -** Find a "name" for the register 'c'. -*/ -static void rname (const Proto *p, int pc, int c, const char **name) { - const char *what = getobjname(p, pc, c, name); /* search for 'c' */ - if (!(what && *what == 'c')) /* did not find a constant name? */ - *name = "?"; -} - - -/* -** Find a "name" for a 'C' value in an RK instruction. -*/ -static void rkname (const Proto *p, int pc, Instruction i, const char **name) { - int c = GETARG_C(i); /* key index */ - if (GETARG_k(i)) /* is 'c' a constant? */ - kname(p, c, name); - else /* 'c' is a register */ - rname(p, pc, c, name); -} - - -static int filterpc (int pc, int jmptarget) { - if (pc < jmptarget) /* is code conditional (inside a jump)? */ - return -1; /* cannot know who sets that register */ - else return pc; /* current position sets that register */ -} - - -/* -** Try to find last instruction before 'lastpc' that modified register 'reg'. -*/ -static int findsetreg (const Proto *p, int lastpc, int reg) { - int pc; - int setreg = -1; /* keep last instruction that changed 'reg' */ - int jmptarget = 0; /* any code before this address is conditional */ - if (testMMMode(GET_OPCODE(p->code[lastpc]))) - lastpc--; /* previous instruction was not actually executed */ - for (pc = 0; pc < lastpc; pc++) { - Instruction i = p->code[pc]; - OpCode op = GET_OPCODE(i); - int a = GETARG_A(i); - int change; /* true if current instruction changed 'reg' */ - switch (op) { - case OP_LOADNIL: { /* set registers from 'a' to 'a+b' */ - int b = GETARG_B(i); - change = (a <= reg && reg <= a + b); - break; - } - case OP_TFORCALL: { /* affect all regs above its base */ - change = (reg >= a + 2); - break; - } - case OP_CALL: - case OP_TAILCALL: { /* affect all registers above base */ - change = (reg >= a); - break; - } - case OP_JMP: { /* doesn't change registers, but changes 'jmptarget' */ - int b = GETARG_sJ(i); - int dest = pc + 1 + b; - /* jump does not skip 'lastpc' and is larger than current one? */ - if (dest <= lastpc && dest > jmptarget) - jmptarget = dest; /* update 'jmptarget' */ - change = 0; - break; - } - default: /* any instruction that sets A */ - change = (testAMode(op) && reg == a); - break; - } - if (change) - setreg = filterpc(pc, jmptarget); - } - return setreg; -} - - -/* -** Check whether table being indexed by instruction 'i' is the -** environment '_ENV' -*/ -static const char *gxf (const Proto *p, int pc, Instruction i, int isup) { - int t = GETARG_B(i); /* table index */ - const char *name; /* name of indexed variable */ - if (isup) /* is an upvalue? */ - name = upvalname(p, t); - else - getobjname(p, pc, t, &name); - return (name && strcmp(name, LUA_ENV) == 0) ? "global" : "field"; -} - - -static const char *getobjname (const Proto *p, int lastpc, int reg, - const char **name) { - int pc; - *name = luaF_getlocalname(p, reg + 1, lastpc); - if (*name) /* is a local? */ - return "local"; - /* else try symbolic execution */ - pc = findsetreg(p, lastpc, reg); - if (pc != -1) { /* could find instruction? */ - Instruction i = p->code[pc]; - OpCode op = GET_OPCODE(i); - switch (op) { - case OP_MOVE: { - int b = GETARG_B(i); /* move from 'b' to 'a' */ - if (b < GETARG_A(i)) - return getobjname(p, pc, b, name); /* get name for 'b' */ - break; - } - case OP_GETTABUP: { - int k = GETARG_C(i); /* key index */ - kname(p, k, name); - return gxf(p, pc, i, 1); - } - case OP_GETTABLE: { - int k = GETARG_C(i); /* key index */ - rname(p, pc, k, name); - return gxf(p, pc, i, 0); - } - case OP_GETI: { - *name = "integer index"; - return "field"; - } - case OP_GETFIELD: { - int k = GETARG_C(i); /* key index */ - kname(p, k, name); - return gxf(p, pc, i, 0); - } - case OP_GETUPVAL: { - *name = upvalname(p, GETARG_B(i)); - return "upvalue"; - } - case OP_LOADK: - case OP_LOADKX: { - int b = (op == OP_LOADK) ? GETARG_Bx(i) - : GETARG_Ax(p->code[pc + 1]); - if (ttisstring(&p->k[b])) { - *name = svalue(&p->k[b]); - return "constant"; - } - break; - } - case OP_SELF: { - rkname(p, pc, i, name); - return "method"; - } - default: break; /* go through to return NULL */ - } - } - return NULL; /* could not find reasonable name */ -} - - -/* -** Try to find a name for a function based on the code that called it. -** (Only works when function was called by a Lua function.) -** Returns what the name is (e.g., "for iterator", "method", -** "metamethod") and sets '*name' to point to the name. -*/ -static const char *funcnamefromcode (lua_State *L, const Proto *p, - int pc, const char **name) { - TMS tm = (TMS)0; /* (initial value avoids warnings) */ - Instruction i = p->code[pc]; /* calling instruction */ - switch (GET_OPCODE(i)) { - case OP_CALL: - case OP_TAILCALL: - return getobjname(p, pc, GETARG_A(i), name); /* get function name */ - case OP_TFORCALL: { /* for iterator */ - *name = "for iterator"; - return "for iterator"; - } - /* other instructions can do calls through metamethods */ - case OP_SELF: case OP_GETTABUP: case OP_GETTABLE: - case OP_GETI: case OP_GETFIELD: - tm = TM_INDEX; - break; - case OP_SETTABUP: case OP_SETTABLE: case OP_SETI: case OP_SETFIELD: - tm = TM_NEWINDEX; - break; - case OP_MMBIN: case OP_MMBINI: case OP_MMBINK: { - tm = cast(TMS, GETARG_C(i)); - break; - } - case OP_UNM: tm = TM_UNM; break; - case OP_BNOT: tm = TM_BNOT; break; - case OP_LEN: tm = TM_LEN; break; - case OP_CONCAT: tm = TM_CONCAT; break; - case OP_EQ: tm = TM_EQ; break; - /* no cases for OP_EQI and OP_EQK, as they don't call metamethods */ - case OP_LT: case OP_LTI: case OP_GTI: tm = TM_LT; break; - case OP_LE: case OP_LEI: case OP_GEI: tm = TM_LE; break; - case OP_CLOSE: case OP_RETURN: tm = TM_CLOSE; break; - default: - return NULL; /* cannot find a reasonable name */ - } - *name = getstr(G(L)->tmname[tm]) + 2; - return "metamethod"; -} - - -/* -** Try to find a name for a function based on how it was called. -*/ -static const char *funcnamefromcall (lua_State *L, CallInfo *ci, - const char **name) { - if (ci->callstatus & CIST_HOOKED) { /* was it called inside a hook? */ - *name = "?"; - return "hook"; - } - else if (ci->callstatus & CIST_FIN) { /* was it called as a finalizer? */ - *name = "__gc"; - return "metamethod"; /* report it as such */ - } - else if (isLua(ci)) - return funcnamefromcode(L, ci_func(ci)->p, currentpc(ci), name); - else - return NULL; -} - -/* }====================================================== */ - - - -/* -** Check whether pointer 'o' points to some value in the stack frame of -** the current function and, if so, returns its index. Because 'o' may -** not point to a value in this stack, we cannot compare it with the -** region boundaries (undefined behavior in ISO C). -*/ -static int instack (CallInfo *ci, const TValue *o) { - int pos; - StkId base = ci->func.p + 1; - for (pos = 0; base + pos < ci->top.p; pos++) { - if (o == s2v(base + pos)) - return pos; - } - return -1; /* not found */ -} - - -/* -** Checks whether value 'o' came from an upvalue. (That can only happen -** with instructions OP_GETTABUP/OP_SETTABUP, which operate directly on -** upvalues.) -*/ -static const char *getupvalname (CallInfo *ci, const TValue *o, - const char **name) { - LClosure *c = ci_func(ci); - int i; - for (i = 0; i < c->nupvalues; i++) { - if (c->upvals[i]->v.p == o) { - *name = upvalname(c->p, i); - return "upvalue"; - } - } - return NULL; -} - - -static const char *formatvarinfo (lua_State *L, const char *kind, - const char *name) { - if (kind == NULL) - return ""; /* no information */ - else - return luaO_pushfstring(L, " (%s '%s')", kind, name); -} - -/* -** Build a string with a "description" for the value 'o', such as -** "variable 'x'" or "upvalue 'y'". -*/ -static const char *varinfo (lua_State *L, const TValue *o) { - CallInfo *ci = L->ci; - const char *name = NULL; /* to avoid warnings */ - const char *kind = NULL; - if (isLua(ci)) { - kind = getupvalname(ci, o, &name); /* check whether 'o' is an upvalue */ - if (!kind) { /* not an upvalue? */ - int reg = instack(ci, o); /* try a register */ - if (reg >= 0) /* is 'o' a register? */ - kind = getobjname(ci_func(ci)->p, currentpc(ci), reg, &name); - } - } - return formatvarinfo(L, kind, name); -} - - -/* -** Raise a type error -*/ -static l_noret typeerror (lua_State *L, const TValue *o, const char *op, - const char *extra) { - const char *t = luaT_objtypename(L, o); - luaG_runerror(L, "attempt to %s a %s value%s", op, t, extra); -} - - -/* -** Raise a type error with "standard" information about the faulty -** object 'o' (using 'varinfo'). -*/ -l_noret luaG_typeerror (lua_State *L, const TValue *o, const char *op) { - typeerror(L, o, op, varinfo(L, o)); -} - - -/* -** Raise an error for calling a non-callable object. Try to find a name -** for the object based on how it was called ('funcnamefromcall'); if it -** cannot get a name there, try 'varinfo'. -*/ -l_noret luaG_callerror (lua_State *L, const TValue *o) { - CallInfo *ci = L->ci; - const char *name = NULL; /* to avoid warnings */ - const char *kind = funcnamefromcall(L, ci, &name); - const char *extra = kind ? formatvarinfo(L, kind, name) : varinfo(L, o); - typeerror(L, o, "call", extra); -} - - -l_noret luaG_forerror (lua_State *L, const TValue *o, const char *what) { - luaG_runerror(L, "bad 'for' %s (number expected, got %s)", - what, luaT_objtypename(L, o)); -} - - -l_noret luaG_concaterror (lua_State *L, const TValue *p1, const TValue *p2) { - if (ttisstring(p1) || cvt2str(p1)) p1 = p2; - luaG_typeerror(L, p1, "concatenate"); -} - - -l_noret luaG_opinterror (lua_State *L, const TValue *p1, - const TValue *p2, const char *msg) { - if (!ttisnumber(p1)) /* first operand is wrong? */ - p2 = p1; /* now second is wrong */ - luaG_typeerror(L, p2, msg); -} - - -/* -** Error when both values are convertible to numbers, but not to integers -*/ -l_noret luaG_tointerror (lua_State *L, const TValue *p1, const TValue *p2) { - lua_Integer temp; - if (!luaV_tointegerns(p1, &temp, LUA_FLOORN2I)) - p2 = p1; - luaG_runerror(L, "number%s has no integer representation", varinfo(L, p2)); -} - - -l_noret luaG_ordererror (lua_State *L, const TValue *p1, const TValue *p2) { - const char *t1 = luaT_objtypename(L, p1); - const char *t2 = luaT_objtypename(L, p2); - if (strcmp(t1, t2) == 0) - luaG_runerror(L, "attempt to compare two %s values", t1); - else - luaG_runerror(L, "attempt to compare %s with %s", t1, t2); -} - - -/* add src:line information to 'msg' */ -const char *luaG_addinfo (lua_State *L, const char *msg, TString *src, - int line) { - char buff[LUA_IDSIZE]; - if (src) - luaO_chunkid(buff, getstr(src), tsslen(src)); - else { /* no source available; use "?" instead */ - buff[0] = '?'; buff[1] = '\0'; - } - return luaO_pushfstring(L, "%s:%d: %s", buff, line, msg); -} - - -l_noret luaG_errormsg (lua_State *L) { - if (L->errfunc != 0) { /* is there an error handling function? */ - StkId errfunc = restorestack(L, L->errfunc); - lua_assert(ttisfunction(s2v(errfunc))); - setobjs2s(L, L->top.p, L->top.p - 1); /* move argument */ - setobjs2s(L, L->top.p - 1, errfunc); /* push function */ - L->top.p++; /* assume EXTRA_STACK */ - luaD_callnoyield(L, L->top.p - 2, 1); /* call it */ - } - luaD_throw(L, LUA_ERRRUN); -} - - -l_noret luaG_runerror (lua_State *L, const char *fmt, ...) { - CallInfo *ci = L->ci; - const char *msg; - va_list argp; - luaC_checkGC(L); /* error message uses memory */ - va_start(argp, fmt); - msg = luaO_pushvfstring(L, fmt, argp); /* format message */ - va_end(argp); - if (isLua(ci)) { /* if Lua function, add source:line information */ - luaG_addinfo(L, msg, ci_func(ci)->p->source, getcurrentline(ci)); - setobjs2s(L, L->top.p - 2, L->top.p - 1); /* remove 'msg' */ - L->top.p--; - } - luaG_errormsg(L); -} - - -/* -** Check whether new instruction 'newpc' is in a different line from -** previous instruction 'oldpc'. More often than not, 'newpc' is only -** one or a few instructions after 'oldpc' (it must be after, see -** caller), so try to avoid calling 'luaG_getfuncline'. If they are -** too far apart, there is a good chance of a ABSLINEINFO in the way, -** so it goes directly to 'luaG_getfuncline'. -*/ -static int changedline (const Proto *p, int oldpc, int newpc) { - if (p->lineinfo == NULL) /* no debug information? */ - return 0; - if (newpc - oldpc < MAXIWTHABS / 2) { /* not too far apart? */ - int delta = 0; /* line difference */ - int pc = oldpc; - for (;;) { - int lineinfo = p->lineinfo[++pc]; - if (lineinfo == ABSLINEINFO) - break; /* cannot compute delta; fall through */ - delta += lineinfo; - if (pc == newpc) - return (delta != 0); /* delta computed successfully */ - } - } - /* either instructions are too far apart or there is an absolute line - info in the way; compute line difference explicitly */ - return (luaG_getfuncline(p, oldpc) != luaG_getfuncline(p, newpc)); -} - - -/* -** Traces the execution of a Lua function. Called before the execution -** of each opcode, when debug is on. 'L->oldpc' stores the last -** instruction traced, to detect line changes. When entering a new -** function, 'npci' will be zero and will test as a new line whatever -** the value of 'oldpc'. Some exceptional conditions may return to -** a function without setting 'oldpc'. In that case, 'oldpc' may be -** invalid; if so, use zero as a valid value. (A wrong but valid 'oldpc' -** at most causes an extra call to a line hook.) -** This function is not "Protected" when called, so it should correct -** 'L->top.p' before calling anything that can run the GC. -*/ -int luaG_traceexec (lua_State *L, const Instruction *pc) { - CallInfo *ci = L->ci; - lu_byte mask = L->hookmask; - const Proto *p = ci_func(ci)->p; - int counthook; - if (!(mask & (LUA_MASKLINE | LUA_MASKCOUNT))) { /* no hooks? */ - ci->u.l.trap = 0; /* don't need to stop again */ - return 0; /* turn off 'trap' */ - } - pc++; /* reference is always next instruction */ - ci->u.l.savedpc = pc; /* save 'pc' */ - counthook = (--L->hookcount == 0 && (mask & LUA_MASKCOUNT)); - if (counthook) - resethookcount(L); /* reset count */ - else if (!(mask & LUA_MASKLINE)) - return 1; /* no line hook and count != 0; nothing to be done now */ - if (ci->callstatus & CIST_HOOKYIELD) { /* called hook last time? */ - ci->callstatus &= ~CIST_HOOKYIELD; /* erase mark */ - return 1; /* do not call hook again (VM yielded, so it did not move) */ - } - if (!isIT(*(ci->u.l.savedpc - 1))) /* top not being used? */ - L->top.p = ci->top.p; /* correct top */ - if (counthook) - luaD_hook(L, LUA_HOOKCOUNT, -1, 0, 0); /* call count hook */ - if (mask & LUA_MASKLINE) { - /* 'L->oldpc' may be invalid; use zero in this case */ - int oldpc = (L->oldpc < p->sizecode) ? L->oldpc : 0; - int npci = pcRel(pc, p); - if (npci <= oldpc || /* call hook when jump back (loop), */ - changedline(p, oldpc, npci)) { /* or when enter new line */ - int newline = luaG_getfuncline(p, npci); - luaD_hook(L, LUA_HOOKLINE, newline, 0, 0); /* call line hook */ - } - L->oldpc = npci; /* 'pc' of last call to line hook */ - } - if (L->status == LUA_YIELD) { /* did hook yield? */ - if (counthook) - L->hookcount = 1; /* undo decrement to zero */ - ci->u.l.savedpc--; /* undo increment (resume will increment it again) */ - ci->callstatus |= CIST_HOOKYIELD; /* mark that it yielded */ - luaD_throw(L, LUA_YIELD); - } - return 1; /* keep 'trap' on */ -} - diff --git a/lib/lua-5.4/src/ldebug.h b/lib/lua-5.4/src/ldebug.h deleted file mode 100644 index 2c3074c..0000000 --- a/lib/lua-5.4/src/ldebug.h +++ /dev/null @@ -1,63 +0,0 @@ -/* -** $Id: ldebug.h $ -** Auxiliary functions from Debug Interface module -** See Copyright Notice in lua.h -*/ - -#ifndef ldebug_h -#define ldebug_h - - -#include "lstate.h" - - -#define pcRel(pc, p) (cast_int((pc) - (p)->code) - 1) - - -/* Active Lua function (given call info) */ -#define ci_func(ci) (clLvalue(s2v((ci)->func.p))) - - -#define resethookcount(L) (L->hookcount = L->basehookcount) - -/* -** mark for entries in 'lineinfo' array that has absolute information in -** 'abslineinfo' array -*/ -#define ABSLINEINFO (-0x80) - - -/* -** MAXimum number of successive Instructions WiTHout ABSolute line -** information. (A power of two allows fast divisions.) -*/ -#if !defined(MAXIWTHABS) -#define MAXIWTHABS 128 -#endif - - -LUAI_FUNC int luaG_getfuncline (const Proto *f, int pc); -LUAI_FUNC const char *luaG_findlocal (lua_State *L, CallInfo *ci, int n, - StkId *pos); -LUAI_FUNC l_noret luaG_typeerror (lua_State *L, const TValue *o, - const char *opname); -LUAI_FUNC l_noret luaG_callerror (lua_State *L, const TValue *o); -LUAI_FUNC l_noret luaG_forerror (lua_State *L, const TValue *o, - const char *what); -LUAI_FUNC l_noret luaG_concaterror (lua_State *L, const TValue *p1, - const TValue *p2); -LUAI_FUNC l_noret luaG_opinterror (lua_State *L, const TValue *p1, - const TValue *p2, - const char *msg); -LUAI_FUNC l_noret luaG_tointerror (lua_State *L, const TValue *p1, - const TValue *p2); -LUAI_FUNC l_noret luaG_ordererror (lua_State *L, const TValue *p1, - const TValue *p2); -LUAI_FUNC l_noret luaG_runerror (lua_State *L, const char *fmt, ...); -LUAI_FUNC const char *luaG_addinfo (lua_State *L, const char *msg, - TString *src, int line); -LUAI_FUNC l_noret luaG_errormsg (lua_State *L); -LUAI_FUNC int luaG_traceexec (lua_State *L, const Instruction *pc); - - -#endif diff --git a/lib/lua-5.4/src/ldo.c b/lib/lua-5.4/src/ldo.c deleted file mode 100644 index 2a0017c..0000000 --- a/lib/lua-5.4/src/ldo.c +++ /dev/null @@ -1,1024 +0,0 @@ -/* -** $Id: ldo.c $ -** Stack and Call structure of Lua -** See Copyright Notice in lua.h -*/ - -#define ldo_c -#define LUA_CORE - -#include "lprefix.h" - - -#include -#include -#include - -#include "lua.h" - -#include "lapi.h" -#include "ldebug.h" -#include "ldo.h" -#include "lfunc.h" -#include "lgc.h" -#include "lmem.h" -#include "lobject.h" -#include "lopcodes.h" -#include "lparser.h" -#include "lstate.h" -#include "lstring.h" -#include "ltable.h" -#include "ltm.h" -#include "lundump.h" -#include "lvm.h" -#include "lzio.h" - - - -#define errorstatus(s) ((s) > LUA_YIELD) - - -/* -** {====================================================== -** Error-recovery functions -** ======================================================= -*/ - -/* -** LUAI_THROW/LUAI_TRY define how Lua does exception handling. By -** default, Lua handles errors with exceptions when compiling as -** C++ code, with _longjmp/_setjmp when asked to use them, and with -** longjmp/setjmp otherwise. -*/ -#if !defined(LUAI_THROW) /* { */ - -#if defined(__cplusplus) && !defined(LUA_USE_LONGJMP) /* { */ - -/* C++ exceptions */ -#define LUAI_THROW(L,c) throw(c) -#define LUAI_TRY(L,c,a) \ - try { a } catch(...) { if ((c)->status == 0) (c)->status = -1; } -#define luai_jmpbuf int /* dummy variable */ - -#elif defined(LUA_USE_POSIX) /* }{ */ - -/* in POSIX, try _longjmp/_setjmp (more efficient) */ -#define LUAI_THROW(L,c) _longjmp((c)->b, 1) -#define LUAI_TRY(L,c,a) if (_setjmp((c)->b) == 0) { a } -#define luai_jmpbuf jmp_buf - -#else /* }{ */ - -/* ISO C handling with long jumps */ -#define LUAI_THROW(L,c) longjmp((c)->b, 1) -#define LUAI_TRY(L,c,a) if (setjmp((c)->b) == 0) { a } -#define luai_jmpbuf jmp_buf - -#endif /* } */ - -#endif /* } */ - - - -/* chain list of long jump buffers */ -struct lua_longjmp { - struct lua_longjmp *previous; - luai_jmpbuf b; - volatile int status; /* error code */ -}; - - -void luaD_seterrorobj (lua_State *L, int errcode, StkId oldtop) { - switch (errcode) { - case LUA_ERRMEM: { /* memory error? */ - setsvalue2s(L, oldtop, G(L)->memerrmsg); /* reuse preregistered msg. */ - break; - } - case LUA_ERRERR: { - setsvalue2s(L, oldtop, luaS_newliteral(L, "error in error handling")); - break; - } - case LUA_OK: { /* special case only for closing upvalues */ - setnilvalue(s2v(oldtop)); /* no error message */ - break; - } - default: { - lua_assert(errorstatus(errcode)); /* real error */ - setobjs2s(L, oldtop, L->top.p - 1); /* error message on current top */ - break; - } - } - L->top.p = oldtop + 1; -} - - -l_noret luaD_throw (lua_State *L, int errcode) { - if (L->errorJmp) { /* thread has an error handler? */ - L->errorJmp->status = errcode; /* set status */ - LUAI_THROW(L, L->errorJmp); /* jump to it */ - } - else { /* thread has no error handler */ - global_State *g = G(L); - errcode = luaE_resetthread(L, errcode); /* close all upvalues */ - if (g->mainthread->errorJmp) { /* main thread has a handler? */ - setobjs2s(L, g->mainthread->top.p++, L->top.p - 1); /* copy error obj. */ - luaD_throw(g->mainthread, errcode); /* re-throw in main thread */ - } - else { /* no handler at all; abort */ - if (g->panic) { /* panic function? */ - lua_unlock(L); - g->panic(L); /* call panic function (last chance to jump out) */ - } - abort(); - } - } -} - - -int luaD_rawrunprotected (lua_State *L, Pfunc f, void *ud) { - l_uint32 oldnCcalls = L->nCcalls; - struct lua_longjmp lj; - lj.status = LUA_OK; - lj.previous = L->errorJmp; /* chain new error handler */ - L->errorJmp = &lj; - LUAI_TRY(L, &lj, - (*f)(L, ud); - ); - L->errorJmp = lj.previous; /* restore old error handler */ - L->nCcalls = oldnCcalls; - return lj.status; -} - -/* }====================================================== */ - - -/* -** {================================================================== -** Stack reallocation -** =================================================================== -*/ - - -/* -** Change all pointers to the stack into offsets. -*/ -static void relstack (lua_State *L) { - CallInfo *ci; - UpVal *up; - L->top.offset = savestack(L, L->top.p); - L->tbclist.offset = savestack(L, L->tbclist.p); - for (up = L->openupval; up != NULL; up = up->u.open.next) - up->v.offset = savestack(L, uplevel(up)); - for (ci = L->ci; ci != NULL; ci = ci->previous) { - ci->top.offset = savestack(L, ci->top.p); - ci->func.offset = savestack(L, ci->func.p); - } -} - - -/* -** Change back all offsets into pointers. -*/ -static void correctstack (lua_State *L) { - CallInfo *ci; - UpVal *up; - L->top.p = restorestack(L, L->top.offset); - L->tbclist.p = restorestack(L, L->tbclist.offset); - for (up = L->openupval; up != NULL; up = up->u.open.next) - up->v.p = s2v(restorestack(L, up->v.offset)); - for (ci = L->ci; ci != NULL; ci = ci->previous) { - ci->top.p = restorestack(L, ci->top.offset); - ci->func.p = restorestack(L, ci->func.offset); - if (isLua(ci)) - ci->u.l.trap = 1; /* signal to update 'trap' in 'luaV_execute' */ - } -} - - -/* some space for error handling */ -#define ERRORSTACKSIZE (LUAI_MAXSTACK + 200) - -/* -** Reallocate the stack to a new size, correcting all pointers into it. -** In ISO C, any pointer use after the pointer has been deallocated is -** undefined behavior. So, before the reallocation, all pointers are -** changed to offsets, and after the reallocation they are changed back -** to pointers. As during the reallocation the pointers are invalid, the -** reallocation cannot run emergency collections. -** -** In case of allocation error, raise an error or return false according -** to 'raiseerror'. -*/ -int luaD_reallocstack (lua_State *L, int newsize, int raiseerror) { - int oldsize = stacksize(L); - int i; - StkId newstack; - int oldgcstop = G(L)->gcstopem; - lua_assert(newsize <= LUAI_MAXSTACK || newsize == ERRORSTACKSIZE); - relstack(L); /* change pointers to offsets */ - G(L)->gcstopem = 1; /* stop emergency collection */ - newstack = luaM_reallocvector(L, L->stack.p, oldsize + EXTRA_STACK, - newsize + EXTRA_STACK, StackValue); - G(L)->gcstopem = oldgcstop; /* restore emergency collection */ - if (l_unlikely(newstack == NULL)) { /* reallocation failed? */ - correctstack(L); /* change offsets back to pointers */ - if (raiseerror) - luaM_error(L); - else return 0; /* do not raise an error */ - } - L->stack.p = newstack; - correctstack(L); /* change offsets back to pointers */ - L->stack_last.p = L->stack.p + newsize; - for (i = oldsize + EXTRA_STACK; i < newsize + EXTRA_STACK; i++) - setnilvalue(s2v(newstack + i)); /* erase new segment */ - return 1; -} - - -/* -** Try to grow the stack by at least 'n' elements. When 'raiseerror' -** is true, raises any error; otherwise, return 0 in case of errors. -*/ -int luaD_growstack (lua_State *L, int n, int raiseerror) { - int size = stacksize(L); - if (l_unlikely(size > LUAI_MAXSTACK)) { - /* if stack is larger than maximum, thread is already using the - extra space reserved for errors, that is, thread is handling - a stack error; cannot grow further than that. */ - lua_assert(stacksize(L) == ERRORSTACKSIZE); - if (raiseerror) - luaD_throw(L, LUA_ERRERR); /* error inside message handler */ - return 0; /* if not 'raiseerror', just signal it */ - } - else if (n < LUAI_MAXSTACK) { /* avoids arithmetic overflows */ - int newsize = 2 * size; /* tentative new size */ - int needed = cast_int(L->top.p - L->stack.p) + n; - if (newsize > LUAI_MAXSTACK) /* cannot cross the limit */ - newsize = LUAI_MAXSTACK; - if (newsize < needed) /* but must respect what was asked for */ - newsize = needed; - if (l_likely(newsize <= LUAI_MAXSTACK)) - return luaD_reallocstack(L, newsize, raiseerror); - } - /* else stack overflow */ - /* add extra size to be able to handle the error message */ - luaD_reallocstack(L, ERRORSTACKSIZE, raiseerror); - if (raiseerror) - luaG_runerror(L, "stack overflow"); - return 0; -} - - -/* -** Compute how much of the stack is being used, by computing the -** maximum top of all call frames in the stack and the current top. -*/ -static int stackinuse (lua_State *L) { - CallInfo *ci; - int res; - StkId lim = L->top.p; - for (ci = L->ci; ci != NULL; ci = ci->previous) { - if (lim < ci->top.p) lim = ci->top.p; - } - lua_assert(lim <= L->stack_last.p + EXTRA_STACK); - res = cast_int(lim - L->stack.p) + 1; /* part of stack in use */ - if (res < LUA_MINSTACK) - res = LUA_MINSTACK; /* ensure a minimum size */ - return res; -} - - -/* -** If stack size is more than 3 times the current use, reduce that size -** to twice the current use. (So, the final stack size is at most 2/3 the -** previous size, and half of its entries are empty.) -** As a particular case, if stack was handling a stack overflow and now -** it is not, 'max' (limited by LUAI_MAXSTACK) will be smaller than -** stacksize (equal to ERRORSTACKSIZE in this case), and so the stack -** will be reduced to a "regular" size. -*/ -void luaD_shrinkstack (lua_State *L) { - int inuse = stackinuse(L); - int max = (inuse > LUAI_MAXSTACK / 3) ? LUAI_MAXSTACK : inuse * 3; - /* if thread is currently not handling a stack overflow and its - size is larger than maximum "reasonable" size, shrink it */ - if (inuse <= LUAI_MAXSTACK && stacksize(L) > max) { - int nsize = (inuse > LUAI_MAXSTACK / 2) ? LUAI_MAXSTACK : inuse * 2; - luaD_reallocstack(L, nsize, 0); /* ok if that fails */ - } - else /* don't change stack */ - condmovestack(L,{},{}); /* (change only for debugging) */ - luaE_shrinkCI(L); /* shrink CI list */ -} - - -void luaD_inctop (lua_State *L) { - luaD_checkstack(L, 1); - L->top.p++; -} - -/* }================================================================== */ - - -/* -** Call a hook for the given event. Make sure there is a hook to be -** called. (Both 'L->hook' and 'L->hookmask', which trigger this -** function, can be changed asynchronously by signals.) -*/ -void luaD_hook (lua_State *L, int event, int line, - int ftransfer, int ntransfer) { - lua_Hook hook = L->hook; - if (hook && L->allowhook) { /* make sure there is a hook */ - int mask = CIST_HOOKED; - CallInfo *ci = L->ci; - ptrdiff_t top = savestack(L, L->top.p); /* preserve original 'top' */ - ptrdiff_t ci_top = savestack(L, ci->top.p); /* idem for 'ci->top' */ - lua_Debug ar; - ar.event = event; - ar.currentline = line; - ar.i_ci = ci; - if (ntransfer != 0) { - mask |= CIST_TRAN; /* 'ci' has transfer information */ - ci->u2.transferinfo.ftransfer = ftransfer; - ci->u2.transferinfo.ntransfer = ntransfer; - } - if (isLua(ci) && L->top.p < ci->top.p) - L->top.p = ci->top.p; /* protect entire activation register */ - luaD_checkstack(L, LUA_MINSTACK); /* ensure minimum stack size */ - if (ci->top.p < L->top.p + LUA_MINSTACK) - ci->top.p = L->top.p + LUA_MINSTACK; - L->allowhook = 0; /* cannot call hooks inside a hook */ - ci->callstatus |= mask; - lua_unlock(L); - (*hook)(L, &ar); - lua_lock(L); - lua_assert(!L->allowhook); - L->allowhook = 1; - ci->top.p = restorestack(L, ci_top); - L->top.p = restorestack(L, top); - ci->callstatus &= ~mask; - } -} - - -/* -** Executes a call hook for Lua functions. This function is called -** whenever 'hookmask' is not zero, so it checks whether call hooks are -** active. -*/ -void luaD_hookcall (lua_State *L, CallInfo *ci) { - L->oldpc = 0; /* set 'oldpc' for new function */ - if (L->hookmask & LUA_MASKCALL) { /* is call hook on? */ - int event = (ci->callstatus & CIST_TAIL) ? LUA_HOOKTAILCALL - : LUA_HOOKCALL; - Proto *p = ci_func(ci)->p; - ci->u.l.savedpc++; /* hooks assume 'pc' is already incremented */ - luaD_hook(L, event, -1, 1, p->numparams); - ci->u.l.savedpc--; /* correct 'pc' */ - } -} - - -/* -** Executes a return hook for Lua and C functions and sets/corrects -** 'oldpc'. (Note that this correction is needed by the line hook, so it -** is done even when return hooks are off.) -*/ -static void rethook (lua_State *L, CallInfo *ci, int nres) { - if (L->hookmask & LUA_MASKRET) { /* is return hook on? */ - StkId firstres = L->top.p - nres; /* index of first result */ - int delta = 0; /* correction for vararg functions */ - int ftransfer; - if (isLua(ci)) { - Proto *p = ci_func(ci)->p; - if (p->is_vararg) - delta = ci->u.l.nextraargs + p->numparams + 1; - } - ci->func.p += delta; /* if vararg, back to virtual 'func' */ - ftransfer = cast(unsigned short, firstres - ci->func.p); - luaD_hook(L, LUA_HOOKRET, -1, ftransfer, nres); /* call it */ - ci->func.p -= delta; - } - if (isLua(ci = ci->previous)) - L->oldpc = pcRel(ci->u.l.savedpc, ci_func(ci)->p); /* set 'oldpc' */ -} - - -/* -** Check whether 'func' has a '__call' metafield. If so, put it in the -** stack, below original 'func', so that 'luaD_precall' can call it. Raise -** an error if there is no '__call' metafield. -*/ -StkId luaD_tryfuncTM (lua_State *L, StkId func) { - const TValue *tm; - StkId p; - checkstackGCp(L, 1, func); /* space for metamethod */ - tm = luaT_gettmbyobj(L, s2v(func), TM_CALL); /* (after previous GC) */ - if (l_unlikely(ttisnil(tm))) - luaG_callerror(L, s2v(func)); /* nothing to call */ - for (p = L->top.p; p > func; p--) /* open space for metamethod */ - setobjs2s(L, p, p-1); - L->top.p++; /* stack space pre-allocated by the caller */ - setobj2s(L, func, tm); /* metamethod is the new function to be called */ - return func; -} - - -/* -** Given 'nres' results at 'firstResult', move 'wanted' of them to 'res'. -** Handle most typical cases (zero results for commands, one result for -** expressions, multiple results for tail calls/single parameters) -** separated. -*/ -l_sinline void moveresults (lua_State *L, StkId res, int nres, int wanted) { - StkId firstresult; - int i; - switch (wanted) { /* handle typical cases separately */ - case 0: /* no values needed */ - L->top.p = res; - return; - case 1: /* one value needed */ - if (nres == 0) /* no results? */ - setnilvalue(s2v(res)); /* adjust with nil */ - else /* at least one result */ - setobjs2s(L, res, L->top.p - nres); /* move it to proper place */ - L->top.p = res + 1; - return; - case LUA_MULTRET: - wanted = nres; /* we want all results */ - break; - default: /* two/more results and/or to-be-closed variables */ - if (hastocloseCfunc(wanted)) { /* to-be-closed variables? */ - L->ci->callstatus |= CIST_CLSRET; /* in case of yields */ - L->ci->u2.nres = nres; - res = luaF_close(L, res, CLOSEKTOP, 1); - L->ci->callstatus &= ~CIST_CLSRET; - if (L->hookmask) { /* if needed, call hook after '__close's */ - ptrdiff_t savedres = savestack(L, res); - rethook(L, L->ci, nres); - res = restorestack(L, savedres); /* hook can move stack */ - } - wanted = decodeNresults(wanted); - if (wanted == LUA_MULTRET) - wanted = nres; /* we want all results */ - } - break; - } - /* generic case */ - firstresult = L->top.p - nres; /* index of first result */ - if (nres > wanted) /* extra results? */ - nres = wanted; /* don't need them */ - for (i = 0; i < nres; i++) /* move all results to correct place */ - setobjs2s(L, res + i, firstresult + i); - for (; i < wanted; i++) /* complete wanted number of results */ - setnilvalue(s2v(res + i)); - L->top.p = res + wanted; /* top points after the last result */ -} - - -/* -** Finishes a function call: calls hook if necessary, moves current -** number of results to proper place, and returns to previous call -** info. If function has to close variables, hook must be called after -** that. -*/ -void luaD_poscall (lua_State *L, CallInfo *ci, int nres) { - int wanted = ci->nresults; - if (l_unlikely(L->hookmask && !hastocloseCfunc(wanted))) - rethook(L, ci, nres); - /* move results to proper place */ - moveresults(L, ci->func.p, nres, wanted); - /* function cannot be in any of these cases when returning */ - lua_assert(!(ci->callstatus & - (CIST_HOOKED | CIST_YPCALL | CIST_FIN | CIST_TRAN | CIST_CLSRET))); - L->ci = ci->previous; /* back to caller (after closing variables) */ -} - - - -#define next_ci(L) (L->ci->next ? L->ci->next : luaE_extendCI(L)) - - -l_sinline CallInfo *prepCallInfo (lua_State *L, StkId func, int nret, - int mask, StkId top) { - CallInfo *ci = L->ci = next_ci(L); /* new frame */ - ci->func.p = func; - ci->nresults = nret; - ci->callstatus = mask; - ci->top.p = top; - return ci; -} - - -/* -** precall for C functions -*/ -l_sinline int precallC (lua_State *L, StkId func, int nresults, - lua_CFunction f) { - int n; /* number of returns */ - CallInfo *ci; - checkstackGCp(L, LUA_MINSTACK, func); /* ensure minimum stack size */ - L->ci = ci = prepCallInfo(L, func, nresults, CIST_C, - L->top.p + LUA_MINSTACK); - lua_assert(ci->top.p <= L->stack_last.p); - if (l_unlikely(L->hookmask & LUA_MASKCALL)) { - int narg = cast_int(L->top.p - func) - 1; - luaD_hook(L, LUA_HOOKCALL, -1, 1, narg); - } - lua_unlock(L); - n = (*f)(L); /* do the actual call */ - lua_lock(L); - api_checknelems(L, n); - luaD_poscall(L, ci, n); - return n; -} - - -/* -** Prepare a function for a tail call, building its call info on top -** of the current call info. 'narg1' is the number of arguments plus 1 -** (so that it includes the function itself). Return the number of -** results, if it was a C function, or -1 for a Lua function. -*/ -int luaD_pretailcall (lua_State *L, CallInfo *ci, StkId func, - int narg1, int delta) { - retry: - switch (ttypetag(s2v(func))) { - case LUA_VCCL: /* C closure */ - return precallC(L, func, LUA_MULTRET, clCvalue(s2v(func))->f); - case LUA_VLCF: /* light C function */ - return precallC(L, func, LUA_MULTRET, fvalue(s2v(func))); - case LUA_VLCL: { /* Lua function */ - Proto *p = clLvalue(s2v(func))->p; - int fsize = p->maxstacksize; /* frame size */ - int nfixparams = p->numparams; - int i; - checkstackGCp(L, fsize - delta, func); - ci->func.p -= delta; /* restore 'func' (if vararg) */ - for (i = 0; i < narg1; i++) /* move down function and arguments */ - setobjs2s(L, ci->func.p + i, func + i); - func = ci->func.p; /* moved-down function */ - for (; narg1 <= nfixparams; narg1++) - setnilvalue(s2v(func + narg1)); /* complete missing arguments */ - ci->top.p = func + 1 + fsize; /* top for new function */ - lua_assert(ci->top.p <= L->stack_last.p); - ci->u.l.savedpc = p->code; /* starting point */ - ci->callstatus |= CIST_TAIL; - L->top.p = func + narg1; /* set top */ - return -1; - } - default: { /* not a function */ - func = luaD_tryfuncTM(L, func); /* try to get '__call' metamethod */ - /* return luaD_pretailcall(L, ci, func, narg1 + 1, delta); */ - narg1++; - goto retry; /* try again */ - } - } -} - - -/* -** Prepares the call to a function (C or Lua). For C functions, also do -** the call. The function to be called is at '*func'. The arguments -** are on the stack, right after the function. Returns the CallInfo -** to be executed, if it was a Lua function. Otherwise (a C function) -** returns NULL, with all the results on the stack, starting at the -** original function position. -*/ -CallInfo *luaD_precall (lua_State *L, StkId func, int nresults) { - retry: - switch (ttypetag(s2v(func))) { - case LUA_VCCL: /* C closure */ - precallC(L, func, nresults, clCvalue(s2v(func))->f); - return NULL; - case LUA_VLCF: /* light C function */ - precallC(L, func, nresults, fvalue(s2v(func))); - return NULL; - case LUA_VLCL: { /* Lua function */ - CallInfo *ci; - Proto *p = clLvalue(s2v(func))->p; - int narg = cast_int(L->top.p - func) - 1; /* number of real arguments */ - int nfixparams = p->numparams; - int fsize = p->maxstacksize; /* frame size */ - checkstackGCp(L, fsize, func); - L->ci = ci = prepCallInfo(L, func, nresults, 0, func + 1 + fsize); - ci->u.l.savedpc = p->code; /* starting point */ - for (; narg < nfixparams; narg++) - setnilvalue(s2v(L->top.p++)); /* complete missing arguments */ - lua_assert(ci->top.p <= L->stack_last.p); - return ci; - } - default: { /* not a function */ - func = luaD_tryfuncTM(L, func); /* try to get '__call' metamethod */ - /* return luaD_precall(L, func, nresults); */ - goto retry; /* try again with metamethod */ - } - } -} - - -/* -** Call a function (C or Lua) through C. 'inc' can be 1 (increment -** number of recursive invocations in the C stack) or nyci (the same -** plus increment number of non-yieldable calls). -** This function can be called with some use of EXTRA_STACK, so it should -** check the stack before doing anything else. 'luaD_precall' already -** does that. -*/ -l_sinline void ccall (lua_State *L, StkId func, int nResults, l_uint32 inc) { - CallInfo *ci; - L->nCcalls += inc; - if (l_unlikely(getCcalls(L) >= LUAI_MAXCCALLS)) { - checkstackp(L, 0, func); /* free any use of EXTRA_STACK */ - luaE_checkcstack(L); - } - if ((ci = luaD_precall(L, func, nResults)) != NULL) { /* Lua function? */ - ci->callstatus = CIST_FRESH; /* mark that it is a "fresh" execute */ - luaV_execute(L, ci); /* call it */ - } - L->nCcalls -= inc; -} - - -/* -** External interface for 'ccall' -*/ -void luaD_call (lua_State *L, StkId func, int nResults) { - ccall(L, func, nResults, 1); -} - - -/* -** Similar to 'luaD_call', but does not allow yields during the call. -*/ -void luaD_callnoyield (lua_State *L, StkId func, int nResults) { - ccall(L, func, nResults, nyci); -} - - -/* -** Finish the job of 'lua_pcallk' after it was interrupted by an yield. -** (The caller, 'finishCcall', does the final call to 'adjustresults'.) -** The main job is to complete the 'luaD_pcall' called by 'lua_pcallk'. -** If a '__close' method yields here, eventually control will be back -** to 'finishCcall' (when that '__close' method finally returns) and -** 'finishpcallk' will run again and close any still pending '__close' -** methods. Similarly, if a '__close' method errs, 'precover' calls -** 'unroll' which calls ''finishCcall' and we are back here again, to -** close any pending '__close' methods. -** Note that, up to the call to 'luaF_close', the corresponding -** 'CallInfo' is not modified, so that this repeated run works like the -** first one (except that it has at least one less '__close' to do). In -** particular, field CIST_RECST preserves the error status across these -** multiple runs, changing only if there is a new error. -*/ -static int finishpcallk (lua_State *L, CallInfo *ci) { - int status = getcistrecst(ci); /* get original status */ - if (l_likely(status == LUA_OK)) /* no error? */ - status = LUA_YIELD; /* was interrupted by an yield */ - else { /* error */ - StkId func = restorestack(L, ci->u2.funcidx); - L->allowhook = getoah(ci->callstatus); /* restore 'allowhook' */ - func = luaF_close(L, func, status, 1); /* can yield or raise an error */ - luaD_seterrorobj(L, status, func); - luaD_shrinkstack(L); /* restore stack size in case of overflow */ - setcistrecst(ci, LUA_OK); /* clear original status */ - } - ci->callstatus &= ~CIST_YPCALL; - L->errfunc = ci->u.c.old_errfunc; - /* if it is here, there were errors or yields; unlike 'lua_pcallk', - do not change status */ - return status; -} - - -/* -** Completes the execution of a C function interrupted by an yield. -** The interruption must have happened while the function was either -** closing its tbc variables in 'moveresults' or executing -** 'lua_callk'/'lua_pcallk'. In the first case, it just redoes -** 'luaD_poscall'. In the second case, the call to 'finishpcallk' -** finishes the interrupted execution of 'lua_pcallk'. After that, it -** calls the continuation of the interrupted function and finally it -** completes the job of the 'luaD_call' that called the function. In -** the call to 'adjustresults', we do not know the number of results -** of the function called by 'lua_callk'/'lua_pcallk', so we are -** conservative and use LUA_MULTRET (always adjust). -*/ -static void finishCcall (lua_State *L, CallInfo *ci) { - int n; /* actual number of results from C function */ - if (ci->callstatus & CIST_CLSRET) { /* was returning? */ - lua_assert(hastocloseCfunc(ci->nresults)); - n = ci->u2.nres; /* just redo 'luaD_poscall' */ - /* don't need to reset CIST_CLSRET, as it will be set again anyway */ - } - else { - int status = LUA_YIELD; /* default if there were no errors */ - /* must have a continuation and must be able to call it */ - lua_assert(ci->u.c.k != NULL && yieldable(L)); - if (ci->callstatus & CIST_YPCALL) /* was inside a 'lua_pcallk'? */ - status = finishpcallk(L, ci); /* finish it */ - adjustresults(L, LUA_MULTRET); /* finish 'lua_callk' */ - lua_unlock(L); - n = (*ci->u.c.k)(L, status, ci->u.c.ctx); /* call continuation */ - lua_lock(L); - api_checknelems(L, n); - } - luaD_poscall(L, ci, n); /* finish 'luaD_call' */ -} - - -/* -** Executes "full continuation" (everything in the stack) of a -** previously interrupted coroutine until the stack is empty (or another -** interruption long-jumps out of the loop). -*/ -static void unroll (lua_State *L, void *ud) { - CallInfo *ci; - UNUSED(ud); - while ((ci = L->ci) != &L->base_ci) { /* something in the stack */ - if (!isLua(ci)) /* C function? */ - finishCcall(L, ci); /* complete its execution */ - else { /* Lua function */ - luaV_finishOp(L); /* finish interrupted instruction */ - luaV_execute(L, ci); /* execute down to higher C 'boundary' */ - } - } -} - - -/* -** Try to find a suspended protected call (a "recover point") for the -** given thread. -*/ -static CallInfo *findpcall (lua_State *L) { - CallInfo *ci; - for (ci = L->ci; ci != NULL; ci = ci->previous) { /* search for a pcall */ - if (ci->callstatus & CIST_YPCALL) - return ci; - } - return NULL; /* no pending pcall */ -} - - -/* -** Signal an error in the call to 'lua_resume', not in the execution -** of the coroutine itself. (Such errors should not be handled by any -** coroutine error handler and should not kill the coroutine.) -*/ -static int resume_error (lua_State *L, const char *msg, int narg) { - L->top.p -= narg; /* remove args from the stack */ - setsvalue2s(L, L->top.p, luaS_new(L, msg)); /* push error message */ - api_incr_top(L); - lua_unlock(L); - return LUA_ERRRUN; -} - - -/* -** Do the work for 'lua_resume' in protected mode. Most of the work -** depends on the status of the coroutine: initial state, suspended -** inside a hook, or regularly suspended (optionally with a continuation -** function), plus erroneous cases: non-suspended coroutine or dead -** coroutine. -*/ -static void resume (lua_State *L, void *ud) { - int n = *(cast(int*, ud)); /* number of arguments */ - StkId firstArg = L->top.p - n; /* first argument */ - CallInfo *ci = L->ci; - if (L->status == LUA_OK) /* starting a coroutine? */ - ccall(L, firstArg - 1, LUA_MULTRET, 0); /* just call its body */ - else { /* resuming from previous yield */ - lua_assert(L->status == LUA_YIELD); - L->status = LUA_OK; /* mark that it is running (again) */ - if (isLua(ci)) { /* yielded inside a hook? */ - L->top.p = firstArg; /* discard arguments */ - luaV_execute(L, ci); /* just continue running Lua code */ - } - else { /* 'common' yield */ - if (ci->u.c.k != NULL) { /* does it have a continuation function? */ - lua_unlock(L); - n = (*ci->u.c.k)(L, LUA_YIELD, ci->u.c.ctx); /* call continuation */ - lua_lock(L); - api_checknelems(L, n); - } - luaD_poscall(L, ci, n); /* finish 'luaD_call' */ - } - unroll(L, NULL); /* run continuation */ - } -} - - -/* -** Unrolls a coroutine in protected mode while there are recoverable -** errors, that is, errors inside a protected call. (Any error -** interrupts 'unroll', and this loop protects it again so it can -** continue.) Stops with a normal end (status == LUA_OK), an yield -** (status == LUA_YIELD), or an unprotected error ('findpcall' doesn't -** find a recover point). -*/ -static int precover (lua_State *L, int status) { - CallInfo *ci; - while (errorstatus(status) && (ci = findpcall(L)) != NULL) { - L->ci = ci; /* go down to recovery functions */ - setcistrecst(ci, status); /* status to finish 'pcall' */ - status = luaD_rawrunprotected(L, unroll, NULL); - } - return status; -} - - -LUA_API int lua_resume (lua_State *L, lua_State *from, int nargs, - int *nresults) { - int status; - lua_lock(L); - if (L->status == LUA_OK) { /* may be starting a coroutine */ - if (L->ci != &L->base_ci) /* not in base level? */ - return resume_error(L, "cannot resume non-suspended coroutine", nargs); - else if (L->top.p - (L->ci->func.p + 1) == nargs) /* no function? */ - return resume_error(L, "cannot resume dead coroutine", nargs); - } - else if (L->status != LUA_YIELD) /* ended with errors? */ - return resume_error(L, "cannot resume dead coroutine", nargs); - L->nCcalls = (from) ? getCcalls(from) : 0; - if (getCcalls(L) >= LUAI_MAXCCALLS) - return resume_error(L, "C stack overflow", nargs); - L->nCcalls++; - luai_userstateresume(L, nargs); - api_checknelems(L, (L->status == LUA_OK) ? nargs + 1 : nargs); - status = luaD_rawrunprotected(L, resume, &nargs); - /* continue running after recoverable errors */ - status = precover(L, status); - if (l_likely(!errorstatus(status))) - lua_assert(status == L->status); /* normal end or yield */ - else { /* unrecoverable error */ - L->status = cast_byte(status); /* mark thread as 'dead' */ - luaD_seterrorobj(L, status, L->top.p); /* push error message */ - L->ci->top.p = L->top.p; - } - *nresults = (status == LUA_YIELD) ? L->ci->u2.nyield - : cast_int(L->top.p - (L->ci->func.p + 1)); - lua_unlock(L); - return status; -} - - -LUA_API int lua_isyieldable (lua_State *L) { - return yieldable(L); -} - - -LUA_API int lua_yieldk (lua_State *L, int nresults, lua_KContext ctx, - lua_KFunction k) { - CallInfo *ci; - luai_userstateyield(L, nresults); - lua_lock(L); - ci = L->ci; - api_checknelems(L, nresults); - if (l_unlikely(!yieldable(L))) { - if (L != G(L)->mainthread) - luaG_runerror(L, "attempt to yield across a C-call boundary"); - else - luaG_runerror(L, "attempt to yield from outside a coroutine"); - } - L->status = LUA_YIELD; - ci->u2.nyield = nresults; /* save number of results */ - if (isLua(ci)) { /* inside a hook? */ - lua_assert(!isLuacode(ci)); - api_check(L, nresults == 0, "hooks cannot yield values"); - api_check(L, k == NULL, "hooks cannot continue after yielding"); - } - else { - if ((ci->u.c.k = k) != NULL) /* is there a continuation? */ - ci->u.c.ctx = ctx; /* save context */ - luaD_throw(L, LUA_YIELD); - } - lua_assert(ci->callstatus & CIST_HOOKED); /* must be inside a hook */ - lua_unlock(L); - return 0; /* return to 'luaD_hook' */ -} - - -/* -** Auxiliary structure to call 'luaF_close' in protected mode. -*/ -struct CloseP { - StkId level; - int status; -}; - - -/* -** Auxiliary function to call 'luaF_close' in protected mode. -*/ -static void closepaux (lua_State *L, void *ud) { - struct CloseP *pcl = cast(struct CloseP *, ud); - luaF_close(L, pcl->level, pcl->status, 0); -} - - -/* -** Calls 'luaF_close' in protected mode. Return the original status -** or, in case of errors, the new status. -*/ -int luaD_closeprotected (lua_State *L, ptrdiff_t level, int status) { - CallInfo *old_ci = L->ci; - lu_byte old_allowhooks = L->allowhook; - for (;;) { /* keep closing upvalues until no more errors */ - struct CloseP pcl; - pcl.level = restorestack(L, level); pcl.status = status; - status = luaD_rawrunprotected(L, &closepaux, &pcl); - if (l_likely(status == LUA_OK)) /* no more errors? */ - return pcl.status; - else { /* an error occurred; restore saved state and repeat */ - L->ci = old_ci; - L->allowhook = old_allowhooks; - } - } -} - - -/* -** Call the C function 'func' in protected mode, restoring basic -** thread information ('allowhook', etc.) and in particular -** its stack level in case of errors. -*/ -int luaD_pcall (lua_State *L, Pfunc func, void *u, - ptrdiff_t old_top, ptrdiff_t ef) { - int status; - CallInfo *old_ci = L->ci; - lu_byte old_allowhooks = L->allowhook; - ptrdiff_t old_errfunc = L->errfunc; - L->errfunc = ef; - status = luaD_rawrunprotected(L, func, u); - if (l_unlikely(status != LUA_OK)) { /* an error occurred? */ - L->ci = old_ci; - L->allowhook = old_allowhooks; - status = luaD_closeprotected(L, old_top, status); - luaD_seterrorobj(L, status, restorestack(L, old_top)); - luaD_shrinkstack(L); /* restore stack size in case of overflow */ - } - L->errfunc = old_errfunc; - return status; -} - - - -/* -** Execute a protected parser. -*/ -struct SParser { /* data to 'f_parser' */ - ZIO *z; - Mbuffer buff; /* dynamic structure used by the scanner */ - Dyndata dyd; /* dynamic structures used by the parser */ - const char *mode; - const char *name; -}; - - -static void checkmode (lua_State *L, const char *mode, const char *x) { - if (mode && strchr(mode, x[0]) == NULL) { - luaO_pushfstring(L, - "attempt to load a %s chunk (mode is '%s')", x, mode); - luaD_throw(L, LUA_ERRSYNTAX); - } -} - - -static void f_parser (lua_State *L, void *ud) { - LClosure *cl; - struct SParser *p = cast(struct SParser *, ud); - int c = zgetc(p->z); /* read first character */ - if (c == LUA_SIGNATURE[0]) { - checkmode(L, p->mode, "binary"); - cl = luaU_undump(L, p->z, p->name); - } - else { - checkmode(L, p->mode, "text"); - cl = luaY_parser(L, p->z, &p->buff, &p->dyd, p->name, c); - } - lua_assert(cl->nupvalues == cl->p->sizeupvalues); - luaF_initupvals(L, cl); -} - - -int luaD_protectedparser (lua_State *L, ZIO *z, const char *name, - const char *mode) { - struct SParser p; - int status; - incnny(L); /* cannot yield during parsing */ - p.z = z; p.name = name; p.mode = mode; - p.dyd.actvar.arr = NULL; p.dyd.actvar.size = 0; - p.dyd.gt.arr = NULL; p.dyd.gt.size = 0; - p.dyd.label.arr = NULL; p.dyd.label.size = 0; - luaZ_initbuffer(L, &p.buff); - status = luaD_pcall(L, f_parser, &p, savestack(L, L->top.p), L->errfunc); - luaZ_freebuffer(L, &p.buff); - luaM_freearray(L, p.dyd.actvar.arr, p.dyd.actvar.size); - luaM_freearray(L, p.dyd.gt.arr, p.dyd.gt.size); - luaM_freearray(L, p.dyd.label.arr, p.dyd.label.size); - decnny(L); - return status; -} - - diff --git a/lib/lua-5.4/src/ldo.h b/lib/lua-5.4/src/ldo.h deleted file mode 100644 index 1aa446a..0000000 --- a/lib/lua-5.4/src/ldo.h +++ /dev/null @@ -1,88 +0,0 @@ -/* -** $Id: ldo.h $ -** Stack and Call structure of Lua -** See Copyright Notice in lua.h -*/ - -#ifndef ldo_h -#define ldo_h - - -#include "llimits.h" -#include "lobject.h" -#include "lstate.h" -#include "lzio.h" - - -/* -** Macro to check stack size and grow stack if needed. Parameters -** 'pre'/'pos' allow the macro to preserve a pointer into the -** stack across reallocations, doing the work only when needed. -** It also allows the running of one GC step when the stack is -** reallocated. -** 'condmovestack' is used in heavy tests to force a stack reallocation -** at every check. -*/ -#define luaD_checkstackaux(L,n,pre,pos) \ - if (l_unlikely(L->stack_last.p - L->top.p <= (n))) \ - { pre; luaD_growstack(L, n, 1); pos; } \ - else { condmovestack(L,pre,pos); } - -/* In general, 'pre'/'pos' are empty (nothing to save) */ -#define luaD_checkstack(L,n) luaD_checkstackaux(L,n,(void)0,(void)0) - - - -#define savestack(L,pt) (cast_charp(pt) - cast_charp(L->stack.p)) -#define restorestack(L,n) cast(StkId, cast_charp(L->stack.p) + (n)) - - -/* macro to check stack size, preserving 'p' */ -#define checkstackp(L,n,p) \ - luaD_checkstackaux(L, n, \ - ptrdiff_t t__ = savestack(L, p), /* save 'p' */ \ - p = restorestack(L, t__)) /* 'pos' part: restore 'p' */ - - -/* macro to check stack size and GC, preserving 'p' */ -#define checkstackGCp(L,n,p) \ - luaD_checkstackaux(L, n, \ - ptrdiff_t t__ = savestack(L, p); /* save 'p' */ \ - luaC_checkGC(L), /* stack grow uses memory */ \ - p = restorestack(L, t__)) /* 'pos' part: restore 'p' */ - - -/* macro to check stack size and GC */ -#define checkstackGC(L,fsize) \ - luaD_checkstackaux(L, (fsize), luaC_checkGC(L), (void)0) - - -/* type of protected functions, to be ran by 'runprotected' */ -typedef void (*Pfunc) (lua_State *L, void *ud); - -LUAI_FUNC void luaD_seterrorobj (lua_State *L, int errcode, StkId oldtop); -LUAI_FUNC int luaD_protectedparser (lua_State *L, ZIO *z, const char *name, - const char *mode); -LUAI_FUNC void luaD_hook (lua_State *L, int event, int line, - int fTransfer, int nTransfer); -LUAI_FUNC void luaD_hookcall (lua_State *L, CallInfo *ci); -LUAI_FUNC int luaD_pretailcall (lua_State *L, CallInfo *ci, StkId func, - int narg1, int delta); -LUAI_FUNC CallInfo *luaD_precall (lua_State *L, StkId func, int nResults); -LUAI_FUNC void luaD_call (lua_State *L, StkId func, int nResults); -LUAI_FUNC void luaD_callnoyield (lua_State *L, StkId func, int nResults); -LUAI_FUNC StkId luaD_tryfuncTM (lua_State *L, StkId func); -LUAI_FUNC int luaD_closeprotected (lua_State *L, ptrdiff_t level, int status); -LUAI_FUNC int luaD_pcall (lua_State *L, Pfunc func, void *u, - ptrdiff_t oldtop, ptrdiff_t ef); -LUAI_FUNC void luaD_poscall (lua_State *L, CallInfo *ci, int nres); -LUAI_FUNC int luaD_reallocstack (lua_State *L, int newsize, int raiseerror); -LUAI_FUNC int luaD_growstack (lua_State *L, int n, int raiseerror); -LUAI_FUNC void luaD_shrinkstack (lua_State *L); -LUAI_FUNC void luaD_inctop (lua_State *L); - -LUAI_FUNC l_noret luaD_throw (lua_State *L, int errcode); -LUAI_FUNC int luaD_rawrunprotected (lua_State *L, Pfunc f, void *ud); - -#endif - diff --git a/lib/lua-5.4/src/ldump.c b/lib/lua-5.4/src/ldump.c deleted file mode 100644 index f231691..0000000 --- a/lib/lua-5.4/src/ldump.c +++ /dev/null @@ -1,230 +0,0 @@ -/* -** $Id: ldump.c $ -** save precompiled Lua chunks -** See Copyright Notice in lua.h -*/ - -#define ldump_c -#define LUA_CORE - -#include "lprefix.h" - - -#include -#include - -#include "lua.h" - -#include "lobject.h" -#include "lstate.h" -#include "lundump.h" - - -typedef struct { - lua_State *L; - lua_Writer writer; - void *data; - int strip; - int status; -} DumpState; - - -/* -** All high-level dumps go through dumpVector; you can change it to -** change the endianness of the result -*/ -#define dumpVector(D,v,n) dumpBlock(D,v,(n)*sizeof((v)[0])) - -#define dumpLiteral(D, s) dumpBlock(D,s,sizeof(s) - sizeof(char)) - - -static void dumpBlock (DumpState *D, const void *b, size_t size) { - if (D->status == 0 && size > 0) { - lua_unlock(D->L); - D->status = (*D->writer)(D->L, b, size, D->data); - lua_lock(D->L); - } -} - - -#define dumpVar(D,x) dumpVector(D,&x,1) - - -static void dumpByte (DumpState *D, int y) { - lu_byte x = (lu_byte)y; - dumpVar(D, x); -} - - -/* -** 'dumpSize' buffer size: each byte can store up to 7 bits. (The "+6" -** rounds up the division.) -*/ -#define DIBS ((sizeof(size_t) * CHAR_BIT + 6) / 7) - -static void dumpSize (DumpState *D, size_t x) { - lu_byte buff[DIBS]; - int n = 0; - do { - buff[DIBS - (++n)] = x & 0x7f; /* fill buffer in reverse order */ - x >>= 7; - } while (x != 0); - buff[DIBS - 1] |= 0x80; /* mark last byte */ - dumpVector(D, buff + DIBS - n, n); -} - - -static void dumpInt (DumpState *D, int x) { - dumpSize(D, x); -} - - -static void dumpNumber (DumpState *D, lua_Number x) { - dumpVar(D, x); -} - - -static void dumpInteger (DumpState *D, lua_Integer x) { - dumpVar(D, x); -} - - -static void dumpString (DumpState *D, const TString *s) { - if (s == NULL) - dumpSize(D, 0); - else { - size_t size = tsslen(s); - const char *str = getstr(s); - dumpSize(D, size + 1); - dumpVector(D, str, size); - } -} - - -static void dumpCode (DumpState *D, const Proto *f) { - dumpInt(D, f->sizecode); - dumpVector(D, f->code, f->sizecode); -} - - -static void dumpFunction(DumpState *D, const Proto *f, TString *psource); - -static void dumpConstants (DumpState *D, const Proto *f) { - int i; - int n = f->sizek; - dumpInt(D, n); - for (i = 0; i < n; i++) { - const TValue *o = &f->k[i]; - int tt = ttypetag(o); - dumpByte(D, tt); - switch (tt) { - case LUA_VNUMFLT: - dumpNumber(D, fltvalue(o)); - break; - case LUA_VNUMINT: - dumpInteger(D, ivalue(o)); - break; - case LUA_VSHRSTR: - case LUA_VLNGSTR: - dumpString(D, tsvalue(o)); - break; - default: - lua_assert(tt == LUA_VNIL || tt == LUA_VFALSE || tt == LUA_VTRUE); - } - } -} - - -static void dumpProtos (DumpState *D, const Proto *f) { - int i; - int n = f->sizep; - dumpInt(D, n); - for (i = 0; i < n; i++) - dumpFunction(D, f->p[i], f->source); -} - - -static void dumpUpvalues (DumpState *D, const Proto *f) { - int i, n = f->sizeupvalues; - dumpInt(D, n); - for (i = 0; i < n; i++) { - dumpByte(D, f->upvalues[i].instack); - dumpByte(D, f->upvalues[i].idx); - dumpByte(D, f->upvalues[i].kind); - } -} - - -static void dumpDebug (DumpState *D, const Proto *f) { - int i, n; - n = (D->strip) ? 0 : f->sizelineinfo; - dumpInt(D, n); - dumpVector(D, f->lineinfo, n); - n = (D->strip) ? 0 : f->sizeabslineinfo; - dumpInt(D, n); - for (i = 0; i < n; i++) { - dumpInt(D, f->abslineinfo[i].pc); - dumpInt(D, f->abslineinfo[i].line); - } - n = (D->strip) ? 0 : f->sizelocvars; - dumpInt(D, n); - for (i = 0; i < n; i++) { - dumpString(D, f->locvars[i].varname); - dumpInt(D, f->locvars[i].startpc); - dumpInt(D, f->locvars[i].endpc); - } - n = (D->strip) ? 0 : f->sizeupvalues; - dumpInt(D, n); - for (i = 0; i < n; i++) - dumpString(D, f->upvalues[i].name); -} - - -static void dumpFunction (DumpState *D, const Proto *f, TString *psource) { - if (D->strip || f->source == psource) - dumpString(D, NULL); /* no debug info or same source as its parent */ - else - dumpString(D, f->source); - dumpInt(D, f->linedefined); - dumpInt(D, f->lastlinedefined); - dumpByte(D, f->numparams); - dumpByte(D, f->is_vararg); - dumpByte(D, f->maxstacksize); - dumpCode(D, f); - dumpConstants(D, f); - dumpUpvalues(D, f); - dumpProtos(D, f); - dumpDebug(D, f); -} - - -static void dumpHeader (DumpState *D) { - dumpLiteral(D, LUA_SIGNATURE); - dumpByte(D, LUAC_VERSION); - dumpByte(D, LUAC_FORMAT); - dumpLiteral(D, LUAC_DATA); - dumpByte(D, sizeof(Instruction)); - dumpByte(D, sizeof(lua_Integer)); - dumpByte(D, sizeof(lua_Number)); - dumpInteger(D, LUAC_INT); - dumpNumber(D, LUAC_NUM); -} - - -/* -** dump Lua function as precompiled chunk -*/ -int luaU_dump(lua_State *L, const Proto *f, lua_Writer w, void *data, - int strip) { - DumpState D; - D.L = L; - D.writer = w; - D.data = data; - D.strip = strip; - D.status = 0; - dumpHeader(&D); - dumpByte(&D, f->sizeupvalues); - dumpFunction(&D, f, NULL); - return D.status; -} - diff --git a/lib/lua-5.4/src/lfunc.c b/lib/lua-5.4/src/lfunc.c deleted file mode 100644 index 0945f24..0000000 --- a/lib/lua-5.4/src/lfunc.c +++ /dev/null @@ -1,294 +0,0 @@ -/* -** $Id: lfunc.c $ -** Auxiliary functions to manipulate prototypes and closures -** See Copyright Notice in lua.h -*/ - -#define lfunc_c -#define LUA_CORE - -#include "lprefix.h" - - -#include - -#include "lua.h" - -#include "ldebug.h" -#include "ldo.h" -#include "lfunc.h" -#include "lgc.h" -#include "lmem.h" -#include "lobject.h" -#include "lstate.h" - - - -CClosure *luaF_newCclosure (lua_State *L, int nupvals) { - GCObject *o = luaC_newobj(L, LUA_VCCL, sizeCclosure(nupvals)); - CClosure *c = gco2ccl(o); - c->nupvalues = cast_byte(nupvals); - return c; -} - - -LClosure *luaF_newLclosure (lua_State *L, int nupvals) { - GCObject *o = luaC_newobj(L, LUA_VLCL, sizeLclosure(nupvals)); - LClosure *c = gco2lcl(o); - c->p = NULL; - c->nupvalues = cast_byte(nupvals); - while (nupvals--) c->upvals[nupvals] = NULL; - return c; -} - - -/* -** fill a closure with new closed upvalues -*/ -void luaF_initupvals (lua_State *L, LClosure *cl) { - int i; - for (i = 0; i < cl->nupvalues; i++) { - GCObject *o = luaC_newobj(L, LUA_VUPVAL, sizeof(UpVal)); - UpVal *uv = gco2upv(o); - uv->v.p = &uv->u.value; /* make it closed */ - setnilvalue(uv->v.p); - cl->upvals[i] = uv; - luaC_objbarrier(L, cl, uv); - } -} - - -/* -** Create a new upvalue at the given level, and link it to the list of -** open upvalues of 'L' after entry 'prev'. -**/ -static UpVal *newupval (lua_State *L, StkId level, UpVal **prev) { - GCObject *o = luaC_newobj(L, LUA_VUPVAL, sizeof(UpVal)); - UpVal *uv = gco2upv(o); - UpVal *next = *prev; - uv->v.p = s2v(level); /* current value lives in the stack */ - uv->u.open.next = next; /* link it to list of open upvalues */ - uv->u.open.previous = prev; - if (next) - next->u.open.previous = &uv->u.open.next; - *prev = uv; - if (!isintwups(L)) { /* thread not in list of threads with upvalues? */ - L->twups = G(L)->twups; /* link it to the list */ - G(L)->twups = L; - } - return uv; -} - - -/* -** Find and reuse, or create if it does not exist, an upvalue -** at the given level. -*/ -UpVal *luaF_findupval (lua_State *L, StkId level) { - UpVal **pp = &L->openupval; - UpVal *p; - lua_assert(isintwups(L) || L->openupval == NULL); - while ((p = *pp) != NULL && uplevel(p) >= level) { /* search for it */ - lua_assert(!isdead(G(L), p)); - if (uplevel(p) == level) /* corresponding upvalue? */ - return p; /* return it */ - pp = &p->u.open.next; - } - /* not found: create a new upvalue after 'pp' */ - return newupval(L, level, pp); -} - - -/* -** Call closing method for object 'obj' with error message 'err'. The -** boolean 'yy' controls whether the call is yieldable. -** (This function assumes EXTRA_STACK.) -*/ -static void callclosemethod (lua_State *L, TValue *obj, TValue *err, int yy) { - StkId top = L->top.p; - const TValue *tm = luaT_gettmbyobj(L, obj, TM_CLOSE); - setobj2s(L, top, tm); /* will call metamethod... */ - setobj2s(L, top + 1, obj); /* with 'self' as the 1st argument */ - setobj2s(L, top + 2, err); /* and error msg. as 2nd argument */ - L->top.p = top + 3; /* add function and arguments */ - if (yy) - luaD_call(L, top, 0); - else - luaD_callnoyield(L, top, 0); -} - - -/* -** Check whether object at given level has a close metamethod and raise -** an error if not. -*/ -static void checkclosemth (lua_State *L, StkId level) { - const TValue *tm = luaT_gettmbyobj(L, s2v(level), TM_CLOSE); - if (ttisnil(tm)) { /* no metamethod? */ - int idx = cast_int(level - L->ci->func.p); /* variable index */ - const char *vname = luaG_findlocal(L, L->ci, idx, NULL); - if (vname == NULL) vname = "?"; - luaG_runerror(L, "variable '%s' got a non-closable value", vname); - } -} - - -/* -** Prepare and call a closing method. -** If status is CLOSEKTOP, the call to the closing method will be pushed -** at the top of the stack. Otherwise, values can be pushed right after -** the 'level' of the upvalue being closed, as everything after that -** won't be used again. -*/ -static void prepcallclosemth (lua_State *L, StkId level, int status, int yy) { - TValue *uv = s2v(level); /* value being closed */ - TValue *errobj; - if (status == CLOSEKTOP) - errobj = &G(L)->nilvalue; /* error object is nil */ - else { /* 'luaD_seterrorobj' will set top to level + 2 */ - errobj = s2v(level + 1); /* error object goes after 'uv' */ - luaD_seterrorobj(L, status, level + 1); /* set error object */ - } - callclosemethod(L, uv, errobj, yy); -} - - -/* -** Maximum value for deltas in 'tbclist', dependent on the type -** of delta. (This macro assumes that an 'L' is in scope where it -** is used.) -*/ -#define MAXDELTA \ - ((256ul << ((sizeof(L->stack.p->tbclist.delta) - 1) * 8)) - 1) - - -/* -** Insert a variable in the list of to-be-closed variables. -*/ -void luaF_newtbcupval (lua_State *L, StkId level) { - lua_assert(level > L->tbclist.p); - if (l_isfalse(s2v(level))) - return; /* false doesn't need to be closed */ - checkclosemth(L, level); /* value must have a close method */ - while (cast_uint(level - L->tbclist.p) > MAXDELTA) { - L->tbclist.p += MAXDELTA; /* create a dummy node at maximum delta */ - L->tbclist.p->tbclist.delta = 0; - } - level->tbclist.delta = cast(unsigned short, level - L->tbclist.p); - L->tbclist.p = level; -} - - -void luaF_unlinkupval (UpVal *uv) { - lua_assert(upisopen(uv)); - *uv->u.open.previous = uv->u.open.next; - if (uv->u.open.next) - uv->u.open.next->u.open.previous = uv->u.open.previous; -} - - -/* -** Close all upvalues up to the given stack level. -*/ -void luaF_closeupval (lua_State *L, StkId level) { - UpVal *uv; - StkId upl; /* stack index pointed by 'uv' */ - while ((uv = L->openupval) != NULL && (upl = uplevel(uv)) >= level) { - TValue *slot = &uv->u.value; /* new position for value */ - lua_assert(uplevel(uv) < L->top.p); - luaF_unlinkupval(uv); /* remove upvalue from 'openupval' list */ - setobj(L, slot, uv->v.p); /* move value to upvalue slot */ - uv->v.p = slot; /* now current value lives here */ - if (!iswhite(uv)) { /* neither white nor dead? */ - nw2black(uv); /* closed upvalues cannot be gray */ - luaC_barrier(L, uv, slot); - } - } -} - - -/* -** Remove first element from the tbclist plus its dummy nodes. -*/ -static void poptbclist (lua_State *L) { - StkId tbc = L->tbclist.p; - lua_assert(tbc->tbclist.delta > 0); /* first element cannot be dummy */ - tbc -= tbc->tbclist.delta; - while (tbc > L->stack.p && tbc->tbclist.delta == 0) - tbc -= MAXDELTA; /* remove dummy nodes */ - L->tbclist.p = tbc; -} - - -/* -** Close all upvalues and to-be-closed variables up to the given stack -** level. Return restored 'level'. -*/ -StkId luaF_close (lua_State *L, StkId level, int status, int yy) { - ptrdiff_t levelrel = savestack(L, level); - luaF_closeupval(L, level); /* first, close the upvalues */ - while (L->tbclist.p >= level) { /* traverse tbc's down to that level */ - StkId tbc = L->tbclist.p; /* get variable index */ - poptbclist(L); /* remove it from list */ - prepcallclosemth(L, tbc, status, yy); /* close variable */ - level = restorestack(L, levelrel); - } - return level; -} - - -Proto *luaF_newproto (lua_State *L) { - GCObject *o = luaC_newobj(L, LUA_VPROTO, sizeof(Proto)); - Proto *f = gco2p(o); - f->k = NULL; - f->sizek = 0; - f->p = NULL; - f->sizep = 0; - f->code = NULL; - f->sizecode = 0; - f->lineinfo = NULL; - f->sizelineinfo = 0; - f->abslineinfo = NULL; - f->sizeabslineinfo = 0; - f->upvalues = NULL; - f->sizeupvalues = 0; - f->numparams = 0; - f->is_vararg = 0; - f->maxstacksize = 0; - f->locvars = NULL; - f->sizelocvars = 0; - f->linedefined = 0; - f->lastlinedefined = 0; - f->source = NULL; - return f; -} - - -void luaF_freeproto (lua_State *L, Proto *f) { - luaM_freearray(L, f->code, f->sizecode); - luaM_freearray(L, f->p, f->sizep); - luaM_freearray(L, f->k, f->sizek); - luaM_freearray(L, f->lineinfo, f->sizelineinfo); - luaM_freearray(L, f->abslineinfo, f->sizeabslineinfo); - luaM_freearray(L, f->locvars, f->sizelocvars); - luaM_freearray(L, f->upvalues, f->sizeupvalues); - luaM_free(L, f); -} - - -/* -** Look for n-th local variable at line 'line' in function 'func'. -** Returns NULL if not found. -*/ -const char *luaF_getlocalname (const Proto *f, int local_number, int pc) { - int i; - for (i = 0; isizelocvars && f->locvars[i].startpc <= pc; i++) { - if (pc < f->locvars[i].endpc) { /* is variable active? */ - local_number--; - if (local_number == 0) - return getstr(f->locvars[i].varname); - } - } - return NULL; /* not found */ -} - diff --git a/lib/lua-5.4/src/lfunc.h b/lib/lua-5.4/src/lfunc.h deleted file mode 100644 index 3be265e..0000000 --- a/lib/lua-5.4/src/lfunc.h +++ /dev/null @@ -1,64 +0,0 @@ -/* -** $Id: lfunc.h $ -** Auxiliary functions to manipulate prototypes and closures -** See Copyright Notice in lua.h -*/ - -#ifndef lfunc_h -#define lfunc_h - - -#include "lobject.h" - - -#define sizeCclosure(n) (cast_int(offsetof(CClosure, upvalue)) + \ - cast_int(sizeof(TValue)) * (n)) - -#define sizeLclosure(n) (cast_int(offsetof(LClosure, upvals)) + \ - cast_int(sizeof(TValue *)) * (n)) - - -/* test whether thread is in 'twups' list */ -#define isintwups(L) (L->twups != L) - - -/* -** maximum number of upvalues in a closure (both C and Lua). (Value -** must fit in a VM register.) -*/ -#define MAXUPVAL 255 - - -#define upisopen(up) ((up)->v.p != &(up)->u.value) - - -#define uplevel(up) check_exp(upisopen(up), cast(StkId, (up)->v.p)) - - -/* -** maximum number of misses before giving up the cache of closures -** in prototypes -*/ -#define MAXMISS 10 - - - -/* special status to close upvalues preserving the top of the stack */ -#define CLOSEKTOP (-1) - - -LUAI_FUNC Proto *luaF_newproto (lua_State *L); -LUAI_FUNC CClosure *luaF_newCclosure (lua_State *L, int nupvals); -LUAI_FUNC LClosure *luaF_newLclosure (lua_State *L, int nupvals); -LUAI_FUNC void luaF_initupvals (lua_State *L, LClosure *cl); -LUAI_FUNC UpVal *luaF_findupval (lua_State *L, StkId level); -LUAI_FUNC void luaF_newtbcupval (lua_State *L, StkId level); -LUAI_FUNC void luaF_closeupval (lua_State *L, StkId level); -LUAI_FUNC StkId luaF_close (lua_State *L, StkId level, int status, int yy); -LUAI_FUNC void luaF_unlinkupval (UpVal *uv); -LUAI_FUNC void luaF_freeproto (lua_State *L, Proto *f); -LUAI_FUNC const char *luaF_getlocalname (const Proto *func, int local_number, - int pc); - - -#endif diff --git a/lib/lua-5.4/src/lgc.c b/lib/lua-5.4/src/lgc.c deleted file mode 100644 index a3094ff..0000000 --- a/lib/lua-5.4/src/lgc.c +++ /dev/null @@ -1,1739 +0,0 @@ -/* -** $Id: lgc.c $ -** Garbage Collector -** See Copyright Notice in lua.h -*/ - -#define lgc_c -#define LUA_CORE - -#include "lprefix.h" - -#include -#include - - -#include "lua.h" - -#include "ldebug.h" -#include "ldo.h" -#include "lfunc.h" -#include "lgc.h" -#include "lmem.h" -#include "lobject.h" -#include "lstate.h" -#include "lstring.h" -#include "ltable.h" -#include "ltm.h" - - -/* -** Maximum number of elements to sweep in each single step. -** (Large enough to dissipate fixed overheads but small enough -** to allow small steps for the collector.) -*/ -#define GCSWEEPMAX 100 - -/* -** Maximum number of finalizers to call in each single step. -*/ -#define GCFINMAX 10 - - -/* -** Cost of calling one finalizer. -*/ -#define GCFINALIZECOST 50 - - -/* -** The equivalent, in bytes, of one unit of "work" (visiting a slot, -** sweeping an object, etc.) -*/ -#define WORK2MEM sizeof(TValue) - - -/* -** macro to adjust 'pause': 'pause' is actually used like -** 'pause / PAUSEADJ' (value chosen by tests) -*/ -#define PAUSEADJ 100 - - -/* mask with all color bits */ -#define maskcolors (bitmask(BLACKBIT) | WHITEBITS) - -/* mask with all GC bits */ -#define maskgcbits (maskcolors | AGEBITS) - - -/* macro to erase all color bits then set only the current white bit */ -#define makewhite(g,x) \ - (x->marked = cast_byte((x->marked & ~maskcolors) | luaC_white(g))) - -/* make an object gray (neither white nor black) */ -#define set2gray(x) resetbits(x->marked, maskcolors) - - -/* make an object black (coming from any color) */ -#define set2black(x) \ - (x->marked = cast_byte((x->marked & ~WHITEBITS) | bitmask(BLACKBIT))) - - -#define valiswhite(x) (iscollectable(x) && iswhite(gcvalue(x))) - -#define keyiswhite(n) (keyiscollectable(n) && iswhite(gckey(n))) - - -/* -** Protected access to objects in values -*/ -#define gcvalueN(o) (iscollectable(o) ? gcvalue(o) : NULL) - - -#define markvalue(g,o) { checkliveness(g->mainthread,o); \ - if (valiswhite(o)) reallymarkobject(g,gcvalue(o)); } - -#define markkey(g, n) { if keyiswhite(n) reallymarkobject(g,gckey(n)); } - -#define markobject(g,t) { if (iswhite(t)) reallymarkobject(g, obj2gco(t)); } - -/* -** mark an object that can be NULL (either because it is really optional, -** or it was stripped as debug info, or inside an uncompleted structure) -*/ -#define markobjectN(g,t) { if (t) markobject(g,t); } - -static void reallymarkobject (global_State *g, GCObject *o); -static lu_mem atomic (lua_State *L); -static void entersweep (lua_State *L); - - -/* -** {====================================================== -** Generic functions -** ======================================================= -*/ - - -/* -** one after last element in a hash array -*/ -#define gnodelast(h) gnode(h, cast_sizet(sizenode(h))) - - -static GCObject **getgclist (GCObject *o) { - switch (o->tt) { - case LUA_VTABLE: return &gco2t(o)->gclist; - case LUA_VLCL: return &gco2lcl(o)->gclist; - case LUA_VCCL: return &gco2ccl(o)->gclist; - case LUA_VTHREAD: return &gco2th(o)->gclist; - case LUA_VPROTO: return &gco2p(o)->gclist; - case LUA_VUSERDATA: { - Udata *u = gco2u(o); - lua_assert(u->nuvalue > 0); - return &u->gclist; - } - default: lua_assert(0); return 0; - } -} - - -/* -** Link a collectable object 'o' with a known type into the list 'p'. -** (Must be a macro to access the 'gclist' field in different types.) -*/ -#define linkgclist(o,p) linkgclist_(obj2gco(o), &(o)->gclist, &(p)) - -static void linkgclist_ (GCObject *o, GCObject **pnext, GCObject **list) { - lua_assert(!isgray(o)); /* cannot be in a gray list */ - *pnext = *list; - *list = o; - set2gray(o); /* now it is */ -} - - -/* -** Link a generic collectable object 'o' into the list 'p'. -*/ -#define linkobjgclist(o,p) linkgclist_(obj2gco(o), getgclist(o), &(p)) - - - -/* -** Clear keys for empty entries in tables. If entry is empty, mark its -** entry as dead. This allows the collection of the key, but keeps its -** entry in the table: its removal could break a chain and could break -** a table traversal. Other places never manipulate dead keys, because -** its associated empty value is enough to signal that the entry is -** logically empty. -*/ -static void clearkey (Node *n) { - lua_assert(isempty(gval(n))); - if (keyiscollectable(n)) - setdeadkey(n); /* unused key; remove it */ -} - - -/* -** tells whether a key or value can be cleared from a weak -** table. Non-collectable objects are never removed from weak -** tables. Strings behave as 'values', so are never removed too. for -** other objects: if really collected, cannot keep them; for objects -** being finalized, keep them in keys, but not in values -*/ -static int iscleared (global_State *g, const GCObject *o) { - if (o == NULL) return 0; /* non-collectable value */ - else if (novariant(o->tt) == LUA_TSTRING) { - markobject(g, o); /* strings are 'values', so are never weak */ - return 0; - } - else return iswhite(o); -} - - -/* -** Barrier that moves collector forward, that is, marks the white object -** 'v' being pointed by the black object 'o'. In the generational -** mode, 'v' must also become old, if 'o' is old; however, it cannot -** be changed directly to OLD, because it may still point to non-old -** objects. So, it is marked as OLD0. In the next cycle it will become -** OLD1, and in the next it will finally become OLD (regular old). By -** then, any object it points to will also be old. If called in the -** incremental sweep phase, it clears the black object to white (sweep -** it) to avoid other barrier calls for this same object. (That cannot -** be done is generational mode, as its sweep does not distinguish -** whites from deads.) -*/ -void luaC_barrier_ (lua_State *L, GCObject *o, GCObject *v) { - global_State *g = G(L); - lua_assert(isblack(o) && iswhite(v) && !isdead(g, v) && !isdead(g, o)); - if (keepinvariant(g)) { /* must keep invariant? */ - reallymarkobject(g, v); /* restore invariant */ - if (isold(o)) { - lua_assert(!isold(v)); /* white object could not be old */ - setage(v, G_OLD0); /* restore generational invariant */ - } - } - else { /* sweep phase */ - lua_assert(issweepphase(g)); - if (g->gckind == KGC_INC) /* incremental mode? */ - makewhite(g, o); /* mark 'o' as white to avoid other barriers */ - } -} - - -/* -** barrier that moves collector backward, that is, mark the black object -** pointing to a white object as gray again. -*/ -void luaC_barrierback_ (lua_State *L, GCObject *o) { - global_State *g = G(L); - lua_assert(isblack(o) && !isdead(g, o)); - lua_assert((g->gckind == KGC_GEN) == (isold(o) && getage(o) != G_TOUCHED1)); - if (getage(o) == G_TOUCHED2) /* already in gray list? */ - set2gray(o); /* make it gray to become touched1 */ - else /* link it in 'grayagain' and paint it gray */ - linkobjgclist(o, g->grayagain); - if (isold(o)) /* generational mode? */ - setage(o, G_TOUCHED1); /* touched in current cycle */ -} - - -void luaC_fix (lua_State *L, GCObject *o) { - global_State *g = G(L); - lua_assert(g->allgc == o); /* object must be 1st in 'allgc' list! */ - set2gray(o); /* they will be gray forever */ - setage(o, G_OLD); /* and old forever */ - g->allgc = o->next; /* remove object from 'allgc' list */ - o->next = g->fixedgc; /* link it to 'fixedgc' list */ - g->fixedgc = o; -} - - -/* -** create a new collectable object (with given type, size, and offset) -** and link it to 'allgc' list. -*/ -GCObject *luaC_newobjdt (lua_State *L, int tt, size_t sz, size_t offset) { - global_State *g = G(L); - char *p = cast_charp(luaM_newobject(L, novariant(tt), sz)); - GCObject *o = cast(GCObject *, p + offset); - o->marked = luaC_white(g); - o->tt = tt; - o->next = g->allgc; - g->allgc = o; - return o; -} - - -GCObject *luaC_newobj (lua_State *L, int tt, size_t sz) { - return luaC_newobjdt(L, tt, sz, 0); -} - -/* }====================================================== */ - - - -/* -** {====================================================== -** Mark functions -** ======================================================= -*/ - - -/* -** Mark an object. Userdata with no user values, strings, and closed -** upvalues are visited and turned black here. Open upvalues are -** already indirectly linked through their respective threads in the -** 'twups' list, so they don't go to the gray list; nevertheless, they -** are kept gray to avoid barriers, as their values will be revisited -** by the thread or by 'remarkupvals'. Other objects are added to the -** gray list to be visited (and turned black) later. Both userdata and -** upvalues can call this function recursively, but this recursion goes -** for at most two levels: An upvalue cannot refer to another upvalue -** (only closures can), and a userdata's metatable must be a table. -*/ -static void reallymarkobject (global_State *g, GCObject *o) { - switch (o->tt) { - case LUA_VSHRSTR: - case LUA_VLNGSTR: { - set2black(o); /* nothing to visit */ - break; - } - case LUA_VUPVAL: { - UpVal *uv = gco2upv(o); - if (upisopen(uv)) - set2gray(uv); /* open upvalues are kept gray */ - else - set2black(uv); /* closed upvalues are visited here */ - markvalue(g, uv->v.p); /* mark its content */ - break; - } - case LUA_VUSERDATA: { - Udata *u = gco2u(o); - if (u->nuvalue == 0) { /* no user values? */ - markobjectN(g, u->metatable); /* mark its metatable */ - set2black(u); /* nothing else to mark */ - break; - } - /* else... */ - } /* FALLTHROUGH */ - case LUA_VLCL: case LUA_VCCL: case LUA_VTABLE: - case LUA_VTHREAD: case LUA_VPROTO: { - linkobjgclist(o, g->gray); /* to be visited later */ - break; - } - default: lua_assert(0); break; - } -} - - -/* -** mark metamethods for basic types -*/ -static void markmt (global_State *g) { - int i; - for (i=0; i < LUA_NUMTAGS; i++) - markobjectN(g, g->mt[i]); -} - - -/* -** mark all objects in list of being-finalized -*/ -static lu_mem markbeingfnz (global_State *g) { - GCObject *o; - lu_mem count = 0; - for (o = g->tobefnz; o != NULL; o = o->next) { - count++; - markobject(g, o); - } - return count; -} - - -/* -** For each non-marked thread, simulates a barrier between each open -** upvalue and its value. (If the thread is collected, the value will be -** assigned to the upvalue, but then it can be too late for the barrier -** to act. The "barrier" does not need to check colors: A non-marked -** thread must be young; upvalues cannot be older than their threads; so -** any visited upvalue must be young too.) Also removes the thread from -** the list, as it was already visited. Removes also threads with no -** upvalues, as they have nothing to be checked. (If the thread gets an -** upvalue later, it will be linked in the list again.) -*/ -static int remarkupvals (global_State *g) { - lua_State *thread; - lua_State **p = &g->twups; - int work = 0; /* estimate of how much work was done here */ - while ((thread = *p) != NULL) { - work++; - if (!iswhite(thread) && thread->openupval != NULL) - p = &thread->twups; /* keep marked thread with upvalues in the list */ - else { /* thread is not marked or without upvalues */ - UpVal *uv; - lua_assert(!isold(thread) || thread->openupval == NULL); - *p = thread->twups; /* remove thread from the list */ - thread->twups = thread; /* mark that it is out of list */ - for (uv = thread->openupval; uv != NULL; uv = uv->u.open.next) { - lua_assert(getage(uv) <= getage(thread)); - work++; - if (!iswhite(uv)) { /* upvalue already visited? */ - lua_assert(upisopen(uv) && isgray(uv)); - markvalue(g, uv->v.p); /* mark its value */ - } - } - } - } - return work; -} - - -static void cleargraylists (global_State *g) { - g->gray = g->grayagain = NULL; - g->weak = g->allweak = g->ephemeron = NULL; -} - - -/* -** mark root set and reset all gray lists, to start a new collection -*/ -static void restartcollection (global_State *g) { - cleargraylists(g); - markobject(g, g->mainthread); - markvalue(g, &g->l_registry); - markmt(g); - markbeingfnz(g); /* mark any finalizing object left from previous cycle */ -} - -/* }====================================================== */ - - -/* -** {====================================================== -** Traverse functions -** ======================================================= -*/ - - -/* -** Check whether object 'o' should be kept in the 'grayagain' list for -** post-processing by 'correctgraylist'. (It could put all old objects -** in the list and leave all the work to 'correctgraylist', but it is -** more efficient to avoid adding elements that will be removed.) Only -** TOUCHED1 objects need to be in the list. TOUCHED2 doesn't need to go -** back to a gray list, but then it must become OLD. (That is what -** 'correctgraylist' does when it finds a TOUCHED2 object.) -*/ -static void genlink (global_State *g, GCObject *o) { - lua_assert(isblack(o)); - if (getage(o) == G_TOUCHED1) { /* touched in this cycle? */ - linkobjgclist(o, g->grayagain); /* link it back in 'grayagain' */ - } /* everything else do not need to be linked back */ - else if (getage(o) == G_TOUCHED2) - changeage(o, G_TOUCHED2, G_OLD); /* advance age */ -} - - -/* -** Traverse a table with weak values and link it to proper list. During -** propagate phase, keep it in 'grayagain' list, to be revisited in the -** atomic phase. In the atomic phase, if table has any white value, -** put it in 'weak' list, to be cleared. -*/ -static void traverseweakvalue (global_State *g, Table *h) { - Node *n, *limit = gnodelast(h); - /* if there is array part, assume it may have white values (it is not - worth traversing it now just to check) */ - int hasclears = (h->alimit > 0); - for (n = gnode(h, 0); n < limit; n++) { /* traverse hash part */ - if (isempty(gval(n))) /* entry is empty? */ - clearkey(n); /* clear its key */ - else { - lua_assert(!keyisnil(n)); - markkey(g, n); - if (!hasclears && iscleared(g, gcvalueN(gval(n)))) /* a white value? */ - hasclears = 1; /* table will have to be cleared */ - } - } - if (g->gcstate == GCSatomic && hasclears) - linkgclist(h, g->weak); /* has to be cleared later */ - else - linkgclist(h, g->grayagain); /* must retraverse it in atomic phase */ -} - - -/* -** Traverse an ephemeron table and link it to proper list. Returns true -** iff any object was marked during this traversal (which implies that -** convergence has to continue). During propagation phase, keep table -** in 'grayagain' list, to be visited again in the atomic phase. In -** the atomic phase, if table has any white->white entry, it has to -** be revisited during ephemeron convergence (as that key may turn -** black). Otherwise, if it has any white key, table has to be cleared -** (in the atomic phase). In generational mode, some tables -** must be kept in some gray list for post-processing; this is done -** by 'genlink'. -*/ -static int traverseephemeron (global_State *g, Table *h, int inv) { - int marked = 0; /* true if an object is marked in this traversal */ - int hasclears = 0; /* true if table has white keys */ - int hasww = 0; /* true if table has entry "white-key -> white-value" */ - unsigned int i; - unsigned int asize = luaH_realasize(h); - unsigned int nsize = sizenode(h); - /* traverse array part */ - for (i = 0; i < asize; i++) { - if (valiswhite(&h->array[i])) { - marked = 1; - reallymarkobject(g, gcvalue(&h->array[i])); - } - } - /* traverse hash part; if 'inv', traverse descending - (see 'convergeephemerons') */ - for (i = 0; i < nsize; i++) { - Node *n = inv ? gnode(h, nsize - 1 - i) : gnode(h, i); - if (isempty(gval(n))) /* entry is empty? */ - clearkey(n); /* clear its key */ - else if (iscleared(g, gckeyN(n))) { /* key is not marked (yet)? */ - hasclears = 1; /* table must be cleared */ - if (valiswhite(gval(n))) /* value not marked yet? */ - hasww = 1; /* white-white entry */ - } - else if (valiswhite(gval(n))) { /* value not marked yet? */ - marked = 1; - reallymarkobject(g, gcvalue(gval(n))); /* mark it now */ - } - } - /* link table into proper list */ - if (g->gcstate == GCSpropagate) - linkgclist(h, g->grayagain); /* must retraverse it in atomic phase */ - else if (hasww) /* table has white->white entries? */ - linkgclist(h, g->ephemeron); /* have to propagate again */ - else if (hasclears) /* table has white keys? */ - linkgclist(h, g->allweak); /* may have to clean white keys */ - else - genlink(g, obj2gco(h)); /* check whether collector still needs to see it */ - return marked; -} - - -static void traversestrongtable (global_State *g, Table *h) { - Node *n, *limit = gnodelast(h); - unsigned int i; - unsigned int asize = luaH_realasize(h); - for (i = 0; i < asize; i++) /* traverse array part */ - markvalue(g, &h->array[i]); - for (n = gnode(h, 0); n < limit; n++) { /* traverse hash part */ - if (isempty(gval(n))) /* entry is empty? */ - clearkey(n); /* clear its key */ - else { - lua_assert(!keyisnil(n)); - markkey(g, n); - markvalue(g, gval(n)); - } - } - genlink(g, obj2gco(h)); -} - - -static lu_mem traversetable (global_State *g, Table *h) { - const char *weakkey, *weakvalue; - const TValue *mode = gfasttm(g, h->metatable, TM_MODE); - markobjectN(g, h->metatable); - if (mode && ttisstring(mode) && /* is there a weak mode? */ - (cast_void(weakkey = strchr(svalue(mode), 'k')), - cast_void(weakvalue = strchr(svalue(mode), 'v')), - (weakkey || weakvalue))) { /* is really weak? */ - if (!weakkey) /* strong keys? */ - traverseweakvalue(g, h); - else if (!weakvalue) /* strong values? */ - traverseephemeron(g, h, 0); - else /* all weak */ - linkgclist(h, g->allweak); /* nothing to traverse now */ - } - else /* not weak */ - traversestrongtable(g, h); - return 1 + h->alimit + 2 * allocsizenode(h); -} - - -static int traverseudata (global_State *g, Udata *u) { - int i; - markobjectN(g, u->metatable); /* mark its metatable */ - for (i = 0; i < u->nuvalue; i++) - markvalue(g, &u->uv[i].uv); - genlink(g, obj2gco(u)); - return 1 + u->nuvalue; -} - - -/* -** Traverse a prototype. (While a prototype is being build, its -** arrays can be larger than needed; the extra slots are filled with -** NULL, so the use of 'markobjectN') -*/ -static int traverseproto (global_State *g, Proto *f) { - int i; - markobjectN(g, f->source); - for (i = 0; i < f->sizek; i++) /* mark literals */ - markvalue(g, &f->k[i]); - for (i = 0; i < f->sizeupvalues; i++) /* mark upvalue names */ - markobjectN(g, f->upvalues[i].name); - for (i = 0; i < f->sizep; i++) /* mark nested protos */ - markobjectN(g, f->p[i]); - for (i = 0; i < f->sizelocvars; i++) /* mark local-variable names */ - markobjectN(g, f->locvars[i].varname); - return 1 + f->sizek + f->sizeupvalues + f->sizep + f->sizelocvars; -} - - -static int traverseCclosure (global_State *g, CClosure *cl) { - int i; - for (i = 0; i < cl->nupvalues; i++) /* mark its upvalues */ - markvalue(g, &cl->upvalue[i]); - return 1 + cl->nupvalues; -} - -/* -** Traverse a Lua closure, marking its prototype and its upvalues. -** (Both can be NULL while closure is being created.) -*/ -static int traverseLclosure (global_State *g, LClosure *cl) { - int i; - markobjectN(g, cl->p); /* mark its prototype */ - for (i = 0; i < cl->nupvalues; i++) { /* visit its upvalues */ - UpVal *uv = cl->upvals[i]; - markobjectN(g, uv); /* mark upvalue */ - } - return 1 + cl->nupvalues; -} - - -/* -** Traverse a thread, marking the elements in the stack up to its top -** and cleaning the rest of the stack in the final traversal. That -** ensures that the entire stack have valid (non-dead) objects. -** Threads have no barriers. In gen. mode, old threads must be visited -** at every cycle, because they might point to young objects. In inc. -** mode, the thread can still be modified before the end of the cycle, -** and therefore it must be visited again in the atomic phase. To ensure -** these visits, threads must return to a gray list if they are not new -** (which can only happen in generational mode) or if the traverse is in -** the propagate phase (which can only happen in incremental mode). -*/ -static int traversethread (global_State *g, lua_State *th) { - UpVal *uv; - StkId o = th->stack.p; - if (isold(th) || g->gcstate == GCSpropagate) - linkgclist(th, g->grayagain); /* insert into 'grayagain' list */ - if (o == NULL) - return 1; /* stack not completely built yet */ - lua_assert(g->gcstate == GCSatomic || - th->openupval == NULL || isintwups(th)); - for (; o < th->top.p; o++) /* mark live elements in the stack */ - markvalue(g, s2v(o)); - for (uv = th->openupval; uv != NULL; uv = uv->u.open.next) - markobject(g, uv); /* open upvalues cannot be collected */ - if (g->gcstate == GCSatomic) { /* final traversal? */ - for (; o < th->stack_last.p + EXTRA_STACK; o++) - setnilvalue(s2v(o)); /* clear dead stack slice */ - /* 'remarkupvals' may have removed thread from 'twups' list */ - if (!isintwups(th) && th->openupval != NULL) { - th->twups = g->twups; /* link it back to the list */ - g->twups = th; - } - } - else if (!g->gcemergency) - luaD_shrinkstack(th); /* do not change stack in emergency cycle */ - return 1 + stacksize(th); -} - - -/* -** traverse one gray object, turning it to black. -*/ -static lu_mem propagatemark (global_State *g) { - GCObject *o = g->gray; - nw2black(o); - g->gray = *getgclist(o); /* remove from 'gray' list */ - switch (o->tt) { - case LUA_VTABLE: return traversetable(g, gco2t(o)); - case LUA_VUSERDATA: return traverseudata(g, gco2u(o)); - case LUA_VLCL: return traverseLclosure(g, gco2lcl(o)); - case LUA_VCCL: return traverseCclosure(g, gco2ccl(o)); - case LUA_VPROTO: return traverseproto(g, gco2p(o)); - case LUA_VTHREAD: return traversethread(g, gco2th(o)); - default: lua_assert(0); return 0; - } -} - - -static lu_mem propagateall (global_State *g) { - lu_mem tot = 0; - while (g->gray) - tot += propagatemark(g); - return tot; -} - - -/* -** Traverse all ephemeron tables propagating marks from keys to values. -** Repeat until it converges, that is, nothing new is marked. 'dir' -** inverts the direction of the traversals, trying to speed up -** convergence on chains in the same table. -** -*/ -static void convergeephemerons (global_State *g) { - int changed; - int dir = 0; - do { - GCObject *w; - GCObject *next = g->ephemeron; /* get ephemeron list */ - g->ephemeron = NULL; /* tables may return to this list when traversed */ - changed = 0; - while ((w = next) != NULL) { /* for each ephemeron table */ - Table *h = gco2t(w); - next = h->gclist; /* list is rebuilt during loop */ - nw2black(h); /* out of the list (for now) */ - if (traverseephemeron(g, h, dir)) { /* marked some value? */ - propagateall(g); /* propagate changes */ - changed = 1; /* will have to revisit all ephemeron tables */ - } - } - dir = !dir; /* invert direction next time */ - } while (changed); /* repeat until no more changes */ -} - -/* }====================================================== */ - - -/* -** {====================================================== -** Sweep Functions -** ======================================================= -*/ - - -/* -** clear entries with unmarked keys from all weaktables in list 'l' -*/ -static void clearbykeys (global_State *g, GCObject *l) { - for (; l; l = gco2t(l)->gclist) { - Table *h = gco2t(l); - Node *limit = gnodelast(h); - Node *n; - for (n = gnode(h, 0); n < limit; n++) { - if (iscleared(g, gckeyN(n))) /* unmarked key? */ - setempty(gval(n)); /* remove entry */ - if (isempty(gval(n))) /* is entry empty? */ - clearkey(n); /* clear its key */ - } - } -} - - -/* -** clear entries with unmarked values from all weaktables in list 'l' up -** to element 'f' -*/ -static void clearbyvalues (global_State *g, GCObject *l, GCObject *f) { - for (; l != f; l = gco2t(l)->gclist) { - Table *h = gco2t(l); - Node *n, *limit = gnodelast(h); - unsigned int i; - unsigned int asize = luaH_realasize(h); - for (i = 0; i < asize; i++) { - TValue *o = &h->array[i]; - if (iscleared(g, gcvalueN(o))) /* value was collected? */ - setempty(o); /* remove entry */ - } - for (n = gnode(h, 0); n < limit; n++) { - if (iscleared(g, gcvalueN(gval(n)))) /* unmarked value? */ - setempty(gval(n)); /* remove entry */ - if (isempty(gval(n))) /* is entry empty? */ - clearkey(n); /* clear its key */ - } - } -} - - -static void freeupval (lua_State *L, UpVal *uv) { - if (upisopen(uv)) - luaF_unlinkupval(uv); - luaM_free(L, uv); -} - - -static void freeobj (lua_State *L, GCObject *o) { - switch (o->tt) { - case LUA_VPROTO: - luaF_freeproto(L, gco2p(o)); - break; - case LUA_VUPVAL: - freeupval(L, gco2upv(o)); - break; - case LUA_VLCL: { - LClosure *cl = gco2lcl(o); - luaM_freemem(L, cl, sizeLclosure(cl->nupvalues)); - break; - } - case LUA_VCCL: { - CClosure *cl = gco2ccl(o); - luaM_freemem(L, cl, sizeCclosure(cl->nupvalues)); - break; - } - case LUA_VTABLE: - luaH_free(L, gco2t(o)); - break; - case LUA_VTHREAD: - luaE_freethread(L, gco2th(o)); - break; - case LUA_VUSERDATA: { - Udata *u = gco2u(o); - luaM_freemem(L, o, sizeudata(u->nuvalue, u->len)); - break; - } - case LUA_VSHRSTR: { - TString *ts = gco2ts(o); - luaS_remove(L, ts); /* remove it from hash table */ - luaM_freemem(L, ts, sizelstring(ts->shrlen)); - break; - } - case LUA_VLNGSTR: { - TString *ts = gco2ts(o); - luaM_freemem(L, ts, sizelstring(ts->u.lnglen)); - break; - } - default: lua_assert(0); - } -} - - -/* -** sweep at most 'countin' elements from a list of GCObjects erasing dead -** objects, where a dead object is one marked with the old (non current) -** white; change all non-dead objects back to white, preparing for next -** collection cycle. Return where to continue the traversal or NULL if -** list is finished. ('*countout' gets the number of elements traversed.) -*/ -static GCObject **sweeplist (lua_State *L, GCObject **p, int countin, - int *countout) { - global_State *g = G(L); - int ow = otherwhite(g); - int i; - int white = luaC_white(g); /* current white */ - for (i = 0; *p != NULL && i < countin; i++) { - GCObject *curr = *p; - int marked = curr->marked; - if (isdeadm(ow, marked)) { /* is 'curr' dead? */ - *p = curr->next; /* remove 'curr' from list */ - freeobj(L, curr); /* erase 'curr' */ - } - else { /* change mark to 'white' */ - curr->marked = cast_byte((marked & ~maskgcbits) | white); - p = &curr->next; /* go to next element */ - } - } - if (countout) - *countout = i; /* number of elements traversed */ - return (*p == NULL) ? NULL : p; -} - - -/* -** sweep a list until a live object (or end of list) -*/ -static GCObject **sweeptolive (lua_State *L, GCObject **p) { - GCObject **old = p; - do { - p = sweeplist(L, p, 1, NULL); - } while (p == old); - return p; -} - -/* }====================================================== */ - - -/* -** {====================================================== -** Finalization -** ======================================================= -*/ - -/* -** If possible, shrink string table. -*/ -static void checkSizes (lua_State *L, global_State *g) { - if (!g->gcemergency) { - if (g->strt.nuse < g->strt.size / 4) { /* string table too big? */ - l_mem olddebt = g->GCdebt; - luaS_resize(L, g->strt.size / 2); - g->GCestimate += g->GCdebt - olddebt; /* correct estimate */ - } - } -} - - -/* -** Get the next udata to be finalized from the 'tobefnz' list, and -** link it back into the 'allgc' list. -*/ -static GCObject *udata2finalize (global_State *g) { - GCObject *o = g->tobefnz; /* get first element */ - lua_assert(tofinalize(o)); - g->tobefnz = o->next; /* remove it from 'tobefnz' list */ - o->next = g->allgc; /* return it to 'allgc' list */ - g->allgc = o; - resetbit(o->marked, FINALIZEDBIT); /* object is "normal" again */ - if (issweepphase(g)) - makewhite(g, o); /* "sweep" object */ - else if (getage(o) == G_OLD1) - g->firstold1 = o; /* it is the first OLD1 object in the list */ - return o; -} - - -static void dothecall (lua_State *L, void *ud) { - UNUSED(ud); - luaD_callnoyield(L, L->top.p - 2, 0); -} - - -static void GCTM (lua_State *L) { - global_State *g = G(L); - const TValue *tm; - TValue v; - lua_assert(!g->gcemergency); - setgcovalue(L, &v, udata2finalize(g)); - tm = luaT_gettmbyobj(L, &v, TM_GC); - if (!notm(tm)) { /* is there a finalizer? */ - int status; - lu_byte oldah = L->allowhook; - int oldgcstp = g->gcstp; - g->gcstp |= GCSTPGC; /* avoid GC steps */ - L->allowhook = 0; /* stop debug hooks during GC metamethod */ - setobj2s(L, L->top.p++, tm); /* push finalizer... */ - setobj2s(L, L->top.p++, &v); /* ... and its argument */ - L->ci->callstatus |= CIST_FIN; /* will run a finalizer */ - status = luaD_pcall(L, dothecall, NULL, savestack(L, L->top.p - 2), 0); - L->ci->callstatus &= ~CIST_FIN; /* not running a finalizer anymore */ - L->allowhook = oldah; /* restore hooks */ - g->gcstp = oldgcstp; /* restore state */ - if (l_unlikely(status != LUA_OK)) { /* error while running __gc? */ - luaE_warnerror(L, "__gc"); - L->top.p--; /* pops error object */ - } - } -} - - -/* -** Call a few finalizers -*/ -static int runafewfinalizers (lua_State *L, int n) { - global_State *g = G(L); - int i; - for (i = 0; i < n && g->tobefnz; i++) - GCTM(L); /* call one finalizer */ - return i; -} - - -/* -** call all pending finalizers -*/ -static void callallpendingfinalizers (lua_State *L) { - global_State *g = G(L); - while (g->tobefnz) - GCTM(L); -} - - -/* -** find last 'next' field in list 'p' list (to add elements in its end) -*/ -static GCObject **findlast (GCObject **p) { - while (*p != NULL) - p = &(*p)->next; - return p; -} - - -/* -** Move all unreachable objects (or 'all' objects) that need -** finalization from list 'finobj' to list 'tobefnz' (to be finalized). -** (Note that objects after 'finobjold1' cannot be white, so they -** don't need to be traversed. In incremental mode, 'finobjold1' is NULL, -** so the whole list is traversed.) -*/ -static void separatetobefnz (global_State *g, int all) { - GCObject *curr; - GCObject **p = &g->finobj; - GCObject **lastnext = findlast(&g->tobefnz); - while ((curr = *p) != g->finobjold1) { /* traverse all finalizable objects */ - lua_assert(tofinalize(curr)); - if (!(iswhite(curr) || all)) /* not being collected? */ - p = &curr->next; /* don't bother with it */ - else { - if (curr == g->finobjsur) /* removing 'finobjsur'? */ - g->finobjsur = curr->next; /* correct it */ - *p = curr->next; /* remove 'curr' from 'finobj' list */ - curr->next = *lastnext; /* link at the end of 'tobefnz' list */ - *lastnext = curr; - lastnext = &curr->next; - } - } -} - - -/* -** If pointer 'p' points to 'o', move it to the next element. -*/ -static void checkpointer (GCObject **p, GCObject *o) { - if (o == *p) - *p = o->next; -} - - -/* -** Correct pointers to objects inside 'allgc' list when -** object 'o' is being removed from the list. -*/ -static void correctpointers (global_State *g, GCObject *o) { - checkpointer(&g->survival, o); - checkpointer(&g->old1, o); - checkpointer(&g->reallyold, o); - checkpointer(&g->firstold1, o); -} - - -/* -** if object 'o' has a finalizer, remove it from 'allgc' list (must -** search the list to find it) and link it in 'finobj' list. -*/ -void luaC_checkfinalizer (lua_State *L, GCObject *o, Table *mt) { - global_State *g = G(L); - if (tofinalize(o) || /* obj. is already marked... */ - gfasttm(g, mt, TM_GC) == NULL || /* or has no finalizer... */ - (g->gcstp & GCSTPCLS)) /* or closing state? */ - return; /* nothing to be done */ - else { /* move 'o' to 'finobj' list */ - GCObject **p; - if (issweepphase(g)) { - makewhite(g, o); /* "sweep" object 'o' */ - if (g->sweepgc == &o->next) /* should not remove 'sweepgc' object */ - g->sweepgc = sweeptolive(L, g->sweepgc); /* change 'sweepgc' */ - } - else - correctpointers(g, o); - /* search for pointer pointing to 'o' */ - for (p = &g->allgc; *p != o; p = &(*p)->next) { /* empty */ } - *p = o->next; /* remove 'o' from 'allgc' list */ - o->next = g->finobj; /* link it in 'finobj' list */ - g->finobj = o; - l_setbit(o->marked, FINALIZEDBIT); /* mark it as such */ - } -} - -/* }====================================================== */ - - -/* -** {====================================================== -** Generational Collector -** ======================================================= -*/ - - -/* -** Set the "time" to wait before starting a new GC cycle; cycle will -** start when memory use hits the threshold of ('estimate' * pause / -** PAUSEADJ). (Division by 'estimate' should be OK: it cannot be zero, -** because Lua cannot even start with less than PAUSEADJ bytes). -*/ -static void setpause (global_State *g) { - l_mem threshold, debt; - int pause = getgcparam(g->gcpause); - l_mem estimate = g->GCestimate / PAUSEADJ; /* adjust 'estimate' */ - lua_assert(estimate > 0); - threshold = (pause < MAX_LMEM / estimate) /* overflow? */ - ? estimate * pause /* no overflow */ - : MAX_LMEM; /* overflow; truncate to maximum */ - debt = gettotalbytes(g) - threshold; - if (debt > 0) debt = 0; - luaE_setdebt(g, debt); -} - - -/* -** Sweep a list of objects to enter generational mode. Deletes dead -** objects and turns the non dead to old. All non-dead threads---which -** are now old---must be in a gray list. Everything else is not in a -** gray list. Open upvalues are also kept gray. -*/ -static void sweep2old (lua_State *L, GCObject **p) { - GCObject *curr; - global_State *g = G(L); - while ((curr = *p) != NULL) { - if (iswhite(curr)) { /* is 'curr' dead? */ - lua_assert(isdead(g, curr)); - *p = curr->next; /* remove 'curr' from list */ - freeobj(L, curr); /* erase 'curr' */ - } - else { /* all surviving objects become old */ - setage(curr, G_OLD); - if (curr->tt == LUA_VTHREAD) { /* threads must be watched */ - lua_State *th = gco2th(curr); - linkgclist(th, g->grayagain); /* insert into 'grayagain' list */ - } - else if (curr->tt == LUA_VUPVAL && upisopen(gco2upv(curr))) - set2gray(curr); /* open upvalues are always gray */ - else /* everything else is black */ - nw2black(curr); - p = &curr->next; /* go to next element */ - } - } -} - - -/* -** Sweep for generational mode. Delete dead objects. (Because the -** collection is not incremental, there are no "new white" objects -** during the sweep. So, any white object must be dead.) For -** non-dead objects, advance their ages and clear the color of -** new objects. (Old objects keep their colors.) -** The ages of G_TOUCHED1 and G_TOUCHED2 objects cannot be advanced -** here, because these old-generation objects are usually not swept -** here. They will all be advanced in 'correctgraylist'. That function -** will also remove objects turned white here from any gray list. -*/ -static GCObject **sweepgen (lua_State *L, global_State *g, GCObject **p, - GCObject *limit, GCObject **pfirstold1) { - static const lu_byte nextage[] = { - G_SURVIVAL, /* from G_NEW */ - G_OLD1, /* from G_SURVIVAL */ - G_OLD1, /* from G_OLD0 */ - G_OLD, /* from G_OLD1 */ - G_OLD, /* from G_OLD (do not change) */ - G_TOUCHED1, /* from G_TOUCHED1 (do not change) */ - G_TOUCHED2 /* from G_TOUCHED2 (do not change) */ - }; - int white = luaC_white(g); - GCObject *curr; - while ((curr = *p) != limit) { - if (iswhite(curr)) { /* is 'curr' dead? */ - lua_assert(!isold(curr) && isdead(g, curr)); - *p = curr->next; /* remove 'curr' from list */ - freeobj(L, curr); /* erase 'curr' */ - } - else { /* correct mark and age */ - if (getage(curr) == G_NEW) { /* new objects go back to white */ - int marked = curr->marked & ~maskgcbits; /* erase GC bits */ - curr->marked = cast_byte(marked | G_SURVIVAL | white); - } - else { /* all other objects will be old, and so keep their color */ - setage(curr, nextage[getage(curr)]); - if (getage(curr) == G_OLD1 && *pfirstold1 == NULL) - *pfirstold1 = curr; /* first OLD1 object in the list */ - } - p = &curr->next; /* go to next element */ - } - } - return p; -} - - -/* -** Traverse a list making all its elements white and clearing their -** age. In incremental mode, all objects are 'new' all the time, -** except for fixed strings (which are always old). -*/ -static void whitelist (global_State *g, GCObject *p) { - int white = luaC_white(g); - for (; p != NULL; p = p->next) - p->marked = cast_byte((p->marked & ~maskgcbits) | white); -} - - -/* -** Correct a list of gray objects. Return pointer to where rest of the -** list should be linked. -** Because this correction is done after sweeping, young objects might -** be turned white and still be in the list. They are only removed. -** 'TOUCHED1' objects are advanced to 'TOUCHED2' and remain on the list; -** Non-white threads also remain on the list; 'TOUCHED2' objects become -** regular old; they and anything else are removed from the list. -*/ -static GCObject **correctgraylist (GCObject **p) { - GCObject *curr; - while ((curr = *p) != NULL) { - GCObject **next = getgclist(curr); - if (iswhite(curr)) - goto remove; /* remove all white objects */ - else if (getage(curr) == G_TOUCHED1) { /* touched in this cycle? */ - lua_assert(isgray(curr)); - nw2black(curr); /* make it black, for next barrier */ - changeage(curr, G_TOUCHED1, G_TOUCHED2); - goto remain; /* keep it in the list and go to next element */ - } - else if (curr->tt == LUA_VTHREAD) { - lua_assert(isgray(curr)); - goto remain; /* keep non-white threads on the list */ - } - else { /* everything else is removed */ - lua_assert(isold(curr)); /* young objects should be white here */ - if (getage(curr) == G_TOUCHED2) /* advance from TOUCHED2... */ - changeage(curr, G_TOUCHED2, G_OLD); /* ... to OLD */ - nw2black(curr); /* make object black (to be removed) */ - goto remove; - } - remove: *p = *next; continue; - remain: p = next; continue; - } - return p; -} - - -/* -** Correct all gray lists, coalescing them into 'grayagain'. -*/ -static void correctgraylists (global_State *g) { - GCObject **list = correctgraylist(&g->grayagain); - *list = g->weak; g->weak = NULL; - list = correctgraylist(list); - *list = g->allweak; g->allweak = NULL; - list = correctgraylist(list); - *list = g->ephemeron; g->ephemeron = NULL; - correctgraylist(list); -} - - -/* -** Mark black 'OLD1' objects when starting a new young collection. -** Gray objects are already in some gray list, and so will be visited -** in the atomic step. -*/ -static void markold (global_State *g, GCObject *from, GCObject *to) { - GCObject *p; - for (p = from; p != to; p = p->next) { - if (getage(p) == G_OLD1) { - lua_assert(!iswhite(p)); - changeage(p, G_OLD1, G_OLD); /* now they are old */ - if (isblack(p)) - reallymarkobject(g, p); - } - } -} - - -/* -** Finish a young-generation collection. -*/ -static void finishgencycle (lua_State *L, global_State *g) { - correctgraylists(g); - checkSizes(L, g); - g->gcstate = GCSpropagate; /* skip restart */ - if (!g->gcemergency) - callallpendingfinalizers(L); -} - - -/* -** Does a young collection. First, mark 'OLD1' objects. Then does the -** atomic step. Then, sweep all lists and advance pointers. Finally, -** finish the collection. -*/ -static void youngcollection (lua_State *L, global_State *g) { - GCObject **psurvival; /* to point to first non-dead survival object */ - GCObject *dummy; /* dummy out parameter to 'sweepgen' */ - lua_assert(g->gcstate == GCSpropagate); - if (g->firstold1) { /* are there regular OLD1 objects? */ - markold(g, g->firstold1, g->reallyold); /* mark them */ - g->firstold1 = NULL; /* no more OLD1 objects (for now) */ - } - markold(g, g->finobj, g->finobjrold); - markold(g, g->tobefnz, NULL); - atomic(L); - - /* sweep nursery and get a pointer to its last live element */ - g->gcstate = GCSswpallgc; - psurvival = sweepgen(L, g, &g->allgc, g->survival, &g->firstold1); - /* sweep 'survival' */ - sweepgen(L, g, psurvival, g->old1, &g->firstold1); - g->reallyold = g->old1; - g->old1 = *psurvival; /* 'survival' survivals are old now */ - g->survival = g->allgc; /* all news are survivals */ - - /* repeat for 'finobj' lists */ - dummy = NULL; /* no 'firstold1' optimization for 'finobj' lists */ - psurvival = sweepgen(L, g, &g->finobj, g->finobjsur, &dummy); - /* sweep 'survival' */ - sweepgen(L, g, psurvival, g->finobjold1, &dummy); - g->finobjrold = g->finobjold1; - g->finobjold1 = *psurvival; /* 'survival' survivals are old now */ - g->finobjsur = g->finobj; /* all news are survivals */ - - sweepgen(L, g, &g->tobefnz, NULL, &dummy); - finishgencycle(L, g); -} - - -/* -** Clears all gray lists, sweeps objects, and prepare sublists to enter -** generational mode. The sweeps remove dead objects and turn all -** surviving objects to old. Threads go back to 'grayagain'; everything -** else is turned black (not in any gray list). -*/ -static void atomic2gen (lua_State *L, global_State *g) { - cleargraylists(g); - /* sweep all elements making them old */ - g->gcstate = GCSswpallgc; - sweep2old(L, &g->allgc); - /* everything alive now is old */ - g->reallyold = g->old1 = g->survival = g->allgc; - g->firstold1 = NULL; /* there are no OLD1 objects anywhere */ - - /* repeat for 'finobj' lists */ - sweep2old(L, &g->finobj); - g->finobjrold = g->finobjold1 = g->finobjsur = g->finobj; - - sweep2old(L, &g->tobefnz); - - g->gckind = KGC_GEN; - g->lastatomic = 0; - g->GCestimate = gettotalbytes(g); /* base for memory control */ - finishgencycle(L, g); -} - - -/* -** Set debt for the next minor collection, which will happen when -** memory grows 'genminormul'%. -*/ -static void setminordebt (global_State *g) { - luaE_setdebt(g, -(cast(l_mem, (gettotalbytes(g) / 100)) * g->genminormul)); -} - - -/* -** Enter generational mode. Must go until the end of an atomic cycle -** to ensure that all objects are correctly marked and weak tables -** are cleared. Then, turn all objects into old and finishes the -** collection. -*/ -static lu_mem entergen (lua_State *L, global_State *g) { - lu_mem numobjs; - luaC_runtilstate(L, bitmask(GCSpause)); /* prepare to start a new cycle */ - luaC_runtilstate(L, bitmask(GCSpropagate)); /* start new cycle */ - numobjs = atomic(L); /* propagates all and then do the atomic stuff */ - atomic2gen(L, g); - setminordebt(g); /* set debt assuming next cycle will be minor */ - return numobjs; -} - - -/* -** Enter incremental mode. Turn all objects white, make all -** intermediate lists point to NULL (to avoid invalid pointers), -** and go to the pause state. -*/ -static void enterinc (global_State *g) { - whitelist(g, g->allgc); - g->reallyold = g->old1 = g->survival = NULL; - whitelist(g, g->finobj); - whitelist(g, g->tobefnz); - g->finobjrold = g->finobjold1 = g->finobjsur = NULL; - g->gcstate = GCSpause; - g->gckind = KGC_INC; - g->lastatomic = 0; -} - - -/* -** Change collector mode to 'newmode'. -*/ -void luaC_changemode (lua_State *L, int newmode) { - global_State *g = G(L); - if (newmode != g->gckind) { - if (newmode == KGC_GEN) /* entering generational mode? */ - entergen(L, g); - else - enterinc(g); /* entering incremental mode */ - } - g->lastatomic = 0; -} - - -/* -** Does a full collection in generational mode. -*/ -static lu_mem fullgen (lua_State *L, global_State *g) { - enterinc(g); - return entergen(L, g); -} - - -/* -** Does a major collection after last collection was a "bad collection". -** -** When the program is building a big structure, it allocates lots of -** memory but generates very little garbage. In those scenarios, -** the generational mode just wastes time doing small collections, and -** major collections are frequently what we call a "bad collection", a -** collection that frees too few objects. To avoid the cost of switching -** between generational mode and the incremental mode needed for full -** (major) collections, the collector tries to stay in incremental mode -** after a bad collection, and to switch back to generational mode only -** after a "good" collection (one that traverses less than 9/8 objects -** of the previous one). -** The collector must choose whether to stay in incremental mode or to -** switch back to generational mode before sweeping. At this point, it -** does not know the real memory in use, so it cannot use memory to -** decide whether to return to generational mode. Instead, it uses the -** number of objects traversed (returned by 'atomic') as a proxy. The -** field 'g->lastatomic' keeps this count from the last collection. -** ('g->lastatomic != 0' also means that the last collection was bad.) -*/ -static void stepgenfull (lua_State *L, global_State *g) { - lu_mem newatomic; /* count of traversed objects */ - lu_mem lastatomic = g->lastatomic; /* count from last collection */ - if (g->gckind == KGC_GEN) /* still in generational mode? */ - enterinc(g); /* enter incremental mode */ - luaC_runtilstate(L, bitmask(GCSpropagate)); /* start new cycle */ - newatomic = atomic(L); /* mark everybody */ - if (newatomic < lastatomic + (lastatomic >> 3)) { /* good collection? */ - atomic2gen(L, g); /* return to generational mode */ - setminordebt(g); - } - else { /* another bad collection; stay in incremental mode */ - g->GCestimate = gettotalbytes(g); /* first estimate */; - entersweep(L); - luaC_runtilstate(L, bitmask(GCSpause)); /* finish collection */ - setpause(g); - g->lastatomic = newatomic; - } -} - - -/* -** Does a generational "step". -** Usually, this means doing a minor collection and setting the debt to -** make another collection when memory grows 'genminormul'% larger. -** -** However, there are exceptions. If memory grows 'genmajormul'% -** larger than it was at the end of the last major collection (kept -** in 'g->GCestimate'), the function does a major collection. At the -** end, it checks whether the major collection was able to free a -** decent amount of memory (at least half the growth in memory since -** previous major collection). If so, the collector keeps its state, -** and the next collection will probably be minor again. Otherwise, -** we have what we call a "bad collection". In that case, set the field -** 'g->lastatomic' to signal that fact, so that the next collection will -** go to 'stepgenfull'. -** -** 'GCdebt <= 0' means an explicit call to GC step with "size" zero; -** in that case, do a minor collection. -*/ -static void genstep (lua_State *L, global_State *g) { - if (g->lastatomic != 0) /* last collection was a bad one? */ - stepgenfull(L, g); /* do a full step */ - else { - lu_mem majorbase = g->GCestimate; /* memory after last major collection */ - lu_mem majorinc = (majorbase / 100) * getgcparam(g->genmajormul); - if (g->GCdebt > 0 && gettotalbytes(g) > majorbase + majorinc) { - lu_mem numobjs = fullgen(L, g); /* do a major collection */ - if (gettotalbytes(g) < majorbase + (majorinc / 2)) { - /* collected at least half of memory growth since last major - collection; keep doing minor collections. */ - lua_assert(g->lastatomic == 0); - } - else { /* bad collection */ - g->lastatomic = numobjs; /* signal that last collection was bad */ - setpause(g); /* do a long wait for next (major) collection */ - } - } - else { /* regular case; do a minor collection */ - youngcollection(L, g); - setminordebt(g); - g->GCestimate = majorbase; /* preserve base value */ - } - } - lua_assert(isdecGCmodegen(g)); -} - -/* }====================================================== */ - - -/* -** {====================================================== -** GC control -** ======================================================= -*/ - - -/* -** Enter first sweep phase. -** The call to 'sweeptolive' makes the pointer point to an object -** inside the list (instead of to the header), so that the real sweep do -** not need to skip objects created between "now" and the start of the -** real sweep. -*/ -static void entersweep (lua_State *L) { - global_State *g = G(L); - g->gcstate = GCSswpallgc; - lua_assert(g->sweepgc == NULL); - g->sweepgc = sweeptolive(L, &g->allgc); -} - - -/* -** Delete all objects in list 'p' until (but not including) object -** 'limit'. -*/ -static void deletelist (lua_State *L, GCObject *p, GCObject *limit) { - while (p != limit) { - GCObject *next = p->next; - freeobj(L, p); - p = next; - } -} - - -/* -** Call all finalizers of the objects in the given Lua state, and -** then free all objects, except for the main thread. -*/ -void luaC_freeallobjects (lua_State *L) { - global_State *g = G(L); - g->gcstp = GCSTPCLS; /* no extra finalizers after here */ - luaC_changemode(L, KGC_INC); - separatetobefnz(g, 1); /* separate all objects with finalizers */ - lua_assert(g->finobj == NULL); - callallpendingfinalizers(L); - deletelist(L, g->allgc, obj2gco(g->mainthread)); - lua_assert(g->finobj == NULL); /* no new finalizers */ - deletelist(L, g->fixedgc, NULL); /* collect fixed objects */ - lua_assert(g->strt.nuse == 0); -} - - -static lu_mem atomic (lua_State *L) { - global_State *g = G(L); - lu_mem work = 0; - GCObject *origweak, *origall; - GCObject *grayagain = g->grayagain; /* save original list */ - g->grayagain = NULL; - lua_assert(g->ephemeron == NULL && g->weak == NULL); - lua_assert(!iswhite(g->mainthread)); - g->gcstate = GCSatomic; - markobject(g, L); /* mark running thread */ - /* registry and global metatables may be changed by API */ - markvalue(g, &g->l_registry); - markmt(g); /* mark global metatables */ - work += propagateall(g); /* empties 'gray' list */ - /* remark occasional upvalues of (maybe) dead threads */ - work += remarkupvals(g); - work += propagateall(g); /* propagate changes */ - g->gray = grayagain; - work += propagateall(g); /* traverse 'grayagain' list */ - convergeephemerons(g); - /* at this point, all strongly accessible objects are marked. */ - /* Clear values from weak tables, before checking finalizers */ - clearbyvalues(g, g->weak, NULL); - clearbyvalues(g, g->allweak, NULL); - origweak = g->weak; origall = g->allweak; - separatetobefnz(g, 0); /* separate objects to be finalized */ - work += markbeingfnz(g); /* mark objects that will be finalized */ - work += propagateall(g); /* remark, to propagate 'resurrection' */ - convergeephemerons(g); - /* at this point, all resurrected objects are marked. */ - /* remove dead objects from weak tables */ - clearbykeys(g, g->ephemeron); /* clear keys from all ephemeron tables */ - clearbykeys(g, g->allweak); /* clear keys from all 'allweak' tables */ - /* clear values from resurrected weak tables */ - clearbyvalues(g, g->weak, origweak); - clearbyvalues(g, g->allweak, origall); - luaS_clearcache(g); - g->currentwhite = cast_byte(otherwhite(g)); /* flip current white */ - lua_assert(g->gray == NULL); - return work; /* estimate of slots marked by 'atomic' */ -} - - -static int sweepstep (lua_State *L, global_State *g, - int nextstate, GCObject **nextlist) { - if (g->sweepgc) { - l_mem olddebt = g->GCdebt; - int count; - g->sweepgc = sweeplist(L, g->sweepgc, GCSWEEPMAX, &count); - g->GCestimate += g->GCdebt - olddebt; /* update estimate */ - return count; - } - else { /* enter next state */ - g->gcstate = nextstate; - g->sweepgc = nextlist; - return 0; /* no work done */ - } -} - - -static lu_mem singlestep (lua_State *L) { - global_State *g = G(L); - lu_mem work; - lua_assert(!g->gcstopem); /* collector is not reentrant */ - g->gcstopem = 1; /* no emergency collections while collecting */ - switch (g->gcstate) { - case GCSpause: { - restartcollection(g); - g->gcstate = GCSpropagate; - work = 1; - break; - } - case GCSpropagate: { - if (g->gray == NULL) { /* no more gray objects? */ - g->gcstate = GCSenteratomic; /* finish propagate phase */ - work = 0; - } - else - work = propagatemark(g); /* traverse one gray object */ - break; - } - case GCSenteratomic: { - work = atomic(L); /* work is what was traversed by 'atomic' */ - entersweep(L); - g->GCestimate = gettotalbytes(g); /* first estimate */; - break; - } - case GCSswpallgc: { /* sweep "regular" objects */ - work = sweepstep(L, g, GCSswpfinobj, &g->finobj); - break; - } - case GCSswpfinobj: { /* sweep objects with finalizers */ - work = sweepstep(L, g, GCSswptobefnz, &g->tobefnz); - break; - } - case GCSswptobefnz: { /* sweep objects to be finalized */ - work = sweepstep(L, g, GCSswpend, NULL); - break; - } - case GCSswpend: { /* finish sweeps */ - checkSizes(L, g); - g->gcstate = GCScallfin; - work = 0; - break; - } - case GCScallfin: { /* call remaining finalizers */ - if (g->tobefnz && !g->gcemergency) { - g->gcstopem = 0; /* ok collections during finalizers */ - work = runafewfinalizers(L, GCFINMAX) * GCFINALIZECOST; - } - else { /* emergency mode or no more finalizers */ - g->gcstate = GCSpause; /* finish collection */ - work = 0; - } - break; - } - default: lua_assert(0); return 0; - } - g->gcstopem = 0; - return work; -} - - -/* -** advances the garbage collector until it reaches a state allowed -** by 'statemask' -*/ -void luaC_runtilstate (lua_State *L, int statesmask) { - global_State *g = G(L); - while (!testbit(statesmask, g->gcstate)) - singlestep(L); -} - - - -/* -** Performs a basic incremental step. The debt and step size are -** converted from bytes to "units of work"; then the function loops -** running single steps until adding that many units of work or -** finishing a cycle (pause state). Finally, it sets the debt that -** controls when next step will be performed. -*/ -static void incstep (lua_State *L, global_State *g) { - int stepmul = (getgcparam(g->gcstepmul) | 1); /* avoid division by 0 */ - l_mem debt = (g->GCdebt / WORK2MEM) * stepmul; - l_mem stepsize = (g->gcstepsize <= log2maxs(l_mem)) - ? ((cast(l_mem, 1) << g->gcstepsize) / WORK2MEM) * stepmul - : MAX_LMEM; /* overflow; keep maximum value */ - do { /* repeat until pause or enough "credit" (negative debt) */ - lu_mem work = singlestep(L); /* perform one single step */ - debt -= work; - } while (debt > -stepsize && g->gcstate != GCSpause); - if (g->gcstate == GCSpause) - setpause(g); /* pause until next cycle */ - else { - debt = (debt / stepmul) * WORK2MEM; /* convert 'work units' to bytes */ - luaE_setdebt(g, debt); - } -} - -/* -** Performs a basic GC step if collector is running. (If collector is -** not running, set a reasonable debt to avoid it being called at -** every single check.) -*/ -void luaC_step (lua_State *L) { - global_State *g = G(L); - if (!gcrunning(g)) /* not running? */ - luaE_setdebt(g, -2000); - else { - if(isdecGCmodegen(g)) - genstep(L, g); - else - incstep(L, g); - } -} - - -/* -** Perform a full collection in incremental mode. -** Before running the collection, check 'keepinvariant'; if it is true, -** there may be some objects marked as black, so the collector has -** to sweep all objects to turn them back to white (as white has not -** changed, nothing will be collected). -*/ -static void fullinc (lua_State *L, global_State *g) { - if (keepinvariant(g)) /* black objects? */ - entersweep(L); /* sweep everything to turn them back to white */ - /* finish any pending sweep phase to start a new cycle */ - luaC_runtilstate(L, bitmask(GCSpause)); - luaC_runtilstate(L, bitmask(GCScallfin)); /* run up to finalizers */ - /* estimate must be correct after a full GC cycle */ - lua_assert(g->GCestimate == gettotalbytes(g)); - luaC_runtilstate(L, bitmask(GCSpause)); /* finish collection */ - setpause(g); -} - - -/* -** Performs a full GC cycle; if 'isemergency', set a flag to avoid -** some operations which could change the interpreter state in some -** unexpected ways (running finalizers and shrinking some structures). -*/ -void luaC_fullgc (lua_State *L, int isemergency) { - global_State *g = G(L); - lua_assert(!g->gcemergency); - g->gcemergency = isemergency; /* set flag */ - if (g->gckind == KGC_INC) - fullinc(L, g); - else - fullgen(L, g); - g->gcemergency = 0; -} - -/* }====================================================== */ - - diff --git a/lib/lua-5.4/src/lgc.h b/lib/lua-5.4/src/lgc.h deleted file mode 100644 index 538f6ed..0000000 --- a/lib/lua-5.4/src/lgc.h +++ /dev/null @@ -1,202 +0,0 @@ -/* -** $Id: lgc.h $ -** Garbage Collector -** See Copyright Notice in lua.h -*/ - -#ifndef lgc_h -#define lgc_h - - -#include "lobject.h" -#include "lstate.h" - -/* -** Collectable objects may have one of three colors: white, which means -** the object is not marked; gray, which means the object is marked, but -** its references may be not marked; and black, which means that the -** object and all its references are marked. The main invariant of the -** garbage collector, while marking objects, is that a black object can -** never point to a white one. Moreover, any gray object must be in a -** "gray list" (gray, grayagain, weak, allweak, ephemeron) so that it -** can be visited again before finishing the collection cycle. (Open -** upvalues are an exception to this rule.) These lists have no meaning -** when the invariant is not being enforced (e.g., sweep phase). -*/ - - -/* -** Possible states of the Garbage Collector -*/ -#define GCSpropagate 0 -#define GCSenteratomic 1 -#define GCSatomic 2 -#define GCSswpallgc 3 -#define GCSswpfinobj 4 -#define GCSswptobefnz 5 -#define GCSswpend 6 -#define GCScallfin 7 -#define GCSpause 8 - - -#define issweepphase(g) \ - (GCSswpallgc <= (g)->gcstate && (g)->gcstate <= GCSswpend) - - -/* -** macro to tell when main invariant (white objects cannot point to black -** ones) must be kept. During a collection, the sweep -** phase may break the invariant, as objects turned white may point to -** still-black objects. The invariant is restored when sweep ends and -** all objects are white again. -*/ - -#define keepinvariant(g) ((g)->gcstate <= GCSatomic) - - -/* -** some useful bit tricks -*/ -#define resetbits(x,m) ((x) &= cast_byte(~(m))) -#define setbits(x,m) ((x) |= (m)) -#define testbits(x,m) ((x) & (m)) -#define bitmask(b) (1<<(b)) -#define bit2mask(b1,b2) (bitmask(b1) | bitmask(b2)) -#define l_setbit(x,b) setbits(x, bitmask(b)) -#define resetbit(x,b) resetbits(x, bitmask(b)) -#define testbit(x,b) testbits(x, bitmask(b)) - - -/* -** Layout for bit use in 'marked' field. First three bits are -** used for object "age" in generational mode. Last bit is used -** by tests. -*/ -#define WHITE0BIT 3 /* object is white (type 0) */ -#define WHITE1BIT 4 /* object is white (type 1) */ -#define BLACKBIT 5 /* object is black */ -#define FINALIZEDBIT 6 /* object has been marked for finalization */ - -#define TESTBIT 7 - - - -#define WHITEBITS bit2mask(WHITE0BIT, WHITE1BIT) - - -#define iswhite(x) testbits((x)->marked, WHITEBITS) -#define isblack(x) testbit((x)->marked, BLACKBIT) -#define isgray(x) /* neither white nor black */ \ - (!testbits((x)->marked, WHITEBITS | bitmask(BLACKBIT))) - -#define tofinalize(x) testbit((x)->marked, FINALIZEDBIT) - -#define otherwhite(g) ((g)->currentwhite ^ WHITEBITS) -#define isdeadm(ow,m) ((m) & (ow)) -#define isdead(g,v) isdeadm(otherwhite(g), (v)->marked) - -#define changewhite(x) ((x)->marked ^= WHITEBITS) -#define nw2black(x) \ - check_exp(!iswhite(x), l_setbit((x)->marked, BLACKBIT)) - -#define luaC_white(g) cast_byte((g)->currentwhite & WHITEBITS) - - -/* object age in generational mode */ -#define G_NEW 0 /* created in current cycle */ -#define G_SURVIVAL 1 /* created in previous cycle */ -#define G_OLD0 2 /* marked old by frw. barrier in this cycle */ -#define G_OLD1 3 /* first full cycle as old */ -#define G_OLD 4 /* really old object (not to be visited) */ -#define G_TOUCHED1 5 /* old object touched this cycle */ -#define G_TOUCHED2 6 /* old object touched in previous cycle */ - -#define AGEBITS 7 /* all age bits (111) */ - -#define getage(o) ((o)->marked & AGEBITS) -#define setage(o,a) ((o)->marked = cast_byte(((o)->marked & (~AGEBITS)) | a)) -#define isold(o) (getage(o) > G_SURVIVAL) - -#define changeage(o,f,t) \ - check_exp(getage(o) == (f), (o)->marked ^= ((f)^(t))) - - -/* Default Values for GC parameters */ -#define LUAI_GENMAJORMUL 100 -#define LUAI_GENMINORMUL 20 - -/* wait memory to double before starting new cycle */ -#define LUAI_GCPAUSE 200 - -/* -** some gc parameters are stored divided by 4 to allow a maximum value -** up to 1023 in a 'lu_byte'. -*/ -#define getgcparam(p) ((p) * 4) -#define setgcparam(p,v) ((p) = (v) / 4) - -#define LUAI_GCMUL 100 - -/* how much to allocate before next GC step (log2) */ -#define LUAI_GCSTEPSIZE 13 /* 8 KB */ - - -/* -** Check whether the declared GC mode is generational. While in -** generational mode, the collector can go temporarily to incremental -** mode to improve performance. This is signaled by 'g->lastatomic != 0'. -*/ -#define isdecGCmodegen(g) (g->gckind == KGC_GEN || g->lastatomic != 0) - - -/* -** Control when GC is running: -*/ -#define GCSTPUSR 1 /* bit true when GC stopped by user */ -#define GCSTPGC 2 /* bit true when GC stopped by itself */ -#define GCSTPCLS 4 /* bit true when closing Lua state */ -#define gcrunning(g) ((g)->gcstp == 0) - - -/* -** Does one step of collection when debt becomes positive. 'pre'/'pos' -** allows some adjustments to be done only when needed. macro -** 'condchangemem' is used only for heavy tests (forcing a full -** GC cycle on every opportunity) -*/ -#define luaC_condGC(L,pre,pos) \ - { if (G(L)->GCdebt > 0) { pre; luaC_step(L); pos;}; \ - condchangemem(L,pre,pos); } - -/* more often than not, 'pre'/'pos' are empty */ -#define luaC_checkGC(L) luaC_condGC(L,(void)0,(void)0) - - -#define luaC_objbarrier(L,p,o) ( \ - (isblack(p) && iswhite(o)) ? \ - luaC_barrier_(L,obj2gco(p),obj2gco(o)) : cast_void(0)) - -#define luaC_barrier(L,p,v) ( \ - iscollectable(v) ? luaC_objbarrier(L,p,gcvalue(v)) : cast_void(0)) - -#define luaC_objbarrierback(L,p,o) ( \ - (isblack(p) && iswhite(o)) ? luaC_barrierback_(L,p) : cast_void(0)) - -#define luaC_barrierback(L,p,v) ( \ - iscollectable(v) ? luaC_objbarrierback(L, p, gcvalue(v)) : cast_void(0)) - -LUAI_FUNC void luaC_fix (lua_State *L, GCObject *o); -LUAI_FUNC void luaC_freeallobjects (lua_State *L); -LUAI_FUNC void luaC_step (lua_State *L); -LUAI_FUNC void luaC_runtilstate (lua_State *L, int statesmask); -LUAI_FUNC void luaC_fullgc (lua_State *L, int isemergency); -LUAI_FUNC GCObject *luaC_newobj (lua_State *L, int tt, size_t sz); -LUAI_FUNC GCObject *luaC_newobjdt (lua_State *L, int tt, size_t sz, - size_t offset); -LUAI_FUNC void luaC_barrier_ (lua_State *L, GCObject *o, GCObject *v); -LUAI_FUNC void luaC_barrierback_ (lua_State *L, GCObject *o); -LUAI_FUNC void luaC_checkfinalizer (lua_State *L, GCObject *o, Table *mt); -LUAI_FUNC void luaC_changemode (lua_State *L, int newmode); - - -#endif diff --git a/lib/lua-5.4/src/linit.c b/lib/lua-5.4/src/linit.c deleted file mode 100644 index 69808f8..0000000 --- a/lib/lua-5.4/src/linit.c +++ /dev/null @@ -1,65 +0,0 @@ -/* -** $Id: linit.c $ -** Initialization of libraries for lua.c and other clients -** See Copyright Notice in lua.h -*/ - - -#define linit_c -#define LUA_LIB - -/* -** If you embed Lua in your program and need to open the standard -** libraries, call luaL_openlibs in your program. If you need a -** different set of libraries, copy this file to your project and edit -** it to suit your needs. -** -** You can also *preload* libraries, so that a later 'require' can -** open the library, which is already linked to the application. -** For that, do the following code: -** -** luaL_getsubtable(L, LUA_REGISTRYINDEX, LUA_PRELOAD_TABLE); -** lua_pushcfunction(L, luaopen_modname); -** lua_setfield(L, -2, modname); -** lua_pop(L, 1); // remove PRELOAD table -*/ - -#include "lprefix.h" - - -#include - -#include "lua.h" - -#include "lualib.h" -#include "lauxlib.h" - - -/* -** these libs are loaded by lua.c and are readily available to any Lua -** program -*/ -static const luaL_Reg loadedlibs[] = { - {LUA_GNAME, luaopen_base}, - {LUA_LOADLIBNAME, luaopen_package}, - {LUA_COLIBNAME, luaopen_coroutine}, - {LUA_TABLIBNAME, luaopen_table}, - {LUA_IOLIBNAME, luaopen_io}, - {LUA_OSLIBNAME, luaopen_os}, - {LUA_STRLIBNAME, luaopen_string}, - {LUA_MATHLIBNAME, luaopen_math}, - {LUA_UTF8LIBNAME, luaopen_utf8}, - {LUA_DBLIBNAME, luaopen_debug}, - {NULL, NULL} -}; - - -LUALIB_API void luaL_openlibs (lua_State *L) { - const luaL_Reg *lib; - /* "require" functions from 'loadedlibs' and set results to global table */ - for (lib = loadedlibs; lib->func; lib++) { - luaL_requiref(L, lib->name, lib->func, 1); - lua_pop(L, 1); /* remove lib */ - } -} - diff --git a/lib/lua-5.4/src/liolib.c b/lib/lua-5.4/src/liolib.c deleted file mode 100644 index b08397d..0000000 --- a/lib/lua-5.4/src/liolib.c +++ /dev/null @@ -1,828 +0,0 @@ -/* -** $Id: liolib.c $ -** Standard I/O (and system) library -** See Copyright Notice in lua.h -*/ - -#define liolib_c -#define LUA_LIB - -#include "lprefix.h" - - -#include -#include -#include -#include -#include -#include - -#include "lua.h" - -#include "lauxlib.h" -#include "lualib.h" - - - - -/* -** Change this macro to accept other modes for 'fopen' besides -** the standard ones. -*/ -#if !defined(l_checkmode) - -/* accepted extensions to 'mode' in 'fopen' */ -#if !defined(L_MODEEXT) -#define L_MODEEXT "b" -#endif - -/* Check whether 'mode' matches '[rwa]%+?[L_MODEEXT]*' */ -static int l_checkmode (const char *mode) { - return (*mode != '\0' && strchr("rwa", *(mode++)) != NULL && - (*mode != '+' || ((void)(++mode), 1)) && /* skip if char is '+' */ - (strspn(mode, L_MODEEXT) == strlen(mode))); /* check extensions */ -} - -#endif - -/* -** {====================================================== -** l_popen spawns a new process connected to the current -** one through the file streams. -** ======================================================= -*/ - -#if !defined(l_popen) /* { */ - -#if defined(LUA_USE_POSIX) /* { */ - -#define l_popen(L,c,m) (fflush(NULL), popen(c,m)) -#define l_pclose(L,file) (pclose(file)) - -#elif defined(LUA_USE_WINDOWS) /* }{ */ - -#define l_popen(L,c,m) (_popen(c,m)) -#define l_pclose(L,file) (_pclose(file)) - -#if !defined(l_checkmodep) -/* Windows accepts "[rw][bt]?" as valid modes */ -#define l_checkmodep(m) ((m[0] == 'r' || m[0] == 'w') && \ - (m[1] == '\0' || ((m[1] == 'b' || m[1] == 't') && m[2] == '\0'))) -#endif - -#else /* }{ */ - -/* ISO C definitions */ -#define l_popen(L,c,m) \ - ((void)c, (void)m, \ - luaL_error(L, "'popen' not supported"), \ - (FILE*)0) -#define l_pclose(L,file) ((void)L, (void)file, -1) - -#endif /* } */ - -#endif /* } */ - - -#if !defined(l_checkmodep) -/* By default, Lua accepts only "r" or "w" as valid modes */ -#define l_checkmodep(m) ((m[0] == 'r' || m[0] == 'w') && m[1] == '\0') -#endif - -/* }====================================================== */ - - -#if !defined(l_getc) /* { */ - -#if defined(LUA_USE_POSIX) -#define l_getc(f) getc_unlocked(f) -#define l_lockfile(f) flockfile(f) -#define l_unlockfile(f) funlockfile(f) -#else -#define l_getc(f) getc(f) -#define l_lockfile(f) ((void)0) -#define l_unlockfile(f) ((void)0) -#endif - -#endif /* } */ - - -/* -** {====================================================== -** l_fseek: configuration for longer offsets -** ======================================================= -*/ - -#if !defined(l_fseek) /* { */ - -#if defined(LUA_USE_POSIX) /* { */ - -#include - -#define l_fseek(f,o,w) fseeko(f,o,w) -#define l_ftell(f) ftello(f) -#define l_seeknum off_t - -#elif defined(LUA_USE_WINDOWS) && !defined(_CRTIMP_TYPEINFO) \ - && defined(_MSC_VER) && (_MSC_VER >= 1400) /* }{ */ - -/* Windows (but not DDK) and Visual C++ 2005 or higher */ -#define l_fseek(f,o,w) _fseeki64(f,o,w) -#define l_ftell(f) _ftelli64(f) -#define l_seeknum __int64 - -#else /* }{ */ - -/* ISO C definitions */ -#define l_fseek(f,o,w) fseek(f,o,w) -#define l_ftell(f) ftell(f) -#define l_seeknum long - -#endif /* } */ - -#endif /* } */ - -/* }====================================================== */ - - - -#define IO_PREFIX "_IO_" -#define IOPREF_LEN (sizeof(IO_PREFIX)/sizeof(char) - 1) -#define IO_INPUT (IO_PREFIX "input") -#define IO_OUTPUT (IO_PREFIX "output") - - -typedef luaL_Stream LStream; - - -#define tolstream(L) ((LStream *)luaL_checkudata(L, 1, LUA_FILEHANDLE)) - -#define isclosed(p) ((p)->closef == NULL) - - -static int io_type (lua_State *L) { - LStream *p; - luaL_checkany(L, 1); - p = (LStream *)luaL_testudata(L, 1, LUA_FILEHANDLE); - if (p == NULL) - luaL_pushfail(L); /* not a file */ - else if (isclosed(p)) - lua_pushliteral(L, "closed file"); - else - lua_pushliteral(L, "file"); - return 1; -} - - -static int f_tostring (lua_State *L) { - LStream *p = tolstream(L); - if (isclosed(p)) - lua_pushliteral(L, "file (closed)"); - else - lua_pushfstring(L, "file (%p)", p->f); - return 1; -} - - -static FILE *tofile (lua_State *L) { - LStream *p = tolstream(L); - if (l_unlikely(isclosed(p))) - luaL_error(L, "attempt to use a closed file"); - lua_assert(p->f); - return p->f; -} - - -/* -** When creating file handles, always creates a 'closed' file handle -** before opening the actual file; so, if there is a memory error, the -** handle is in a consistent state. -*/ -static LStream *newprefile (lua_State *L) { - LStream *p = (LStream *)lua_newuserdatauv(L, sizeof(LStream), 0); - p->closef = NULL; /* mark file handle as 'closed' */ - luaL_setmetatable(L, LUA_FILEHANDLE); - return p; -} - - -/* -** Calls the 'close' function from a file handle. The 'volatile' avoids -** a bug in some versions of the Clang compiler (e.g., clang 3.0 for -** 32 bits). -*/ -static int aux_close (lua_State *L) { - LStream *p = tolstream(L); - volatile lua_CFunction cf = p->closef; - p->closef = NULL; /* mark stream as closed */ - return (*cf)(L); /* close it */ -} - - -static int f_close (lua_State *L) { - tofile(L); /* make sure argument is an open stream */ - return aux_close(L); -} - - -static int io_close (lua_State *L) { - if (lua_isnone(L, 1)) /* no argument? */ - lua_getfield(L, LUA_REGISTRYINDEX, IO_OUTPUT); /* use default output */ - return f_close(L); -} - - -static int f_gc (lua_State *L) { - LStream *p = tolstream(L); - if (!isclosed(p) && p->f != NULL) - aux_close(L); /* ignore closed and incompletely open files */ - return 0; -} - - -/* -** function to close regular files -*/ -static int io_fclose (lua_State *L) { - LStream *p = tolstream(L); - int res = fclose(p->f); - return luaL_fileresult(L, (res == 0), NULL); -} - - -static LStream *newfile (lua_State *L) { - LStream *p = newprefile(L); - p->f = NULL; - p->closef = &io_fclose; - return p; -} - - -static void opencheck (lua_State *L, const char *fname, const char *mode) { - LStream *p = newfile(L); - p->f = fopen(fname, mode); - if (l_unlikely(p->f == NULL)) - luaL_error(L, "cannot open file '%s' (%s)", fname, strerror(errno)); -} - - -static int io_open (lua_State *L) { - const char *filename = luaL_checkstring(L, 1); - const char *mode = luaL_optstring(L, 2, "r"); - LStream *p = newfile(L); - const char *md = mode; /* to traverse/check mode */ - luaL_argcheck(L, l_checkmode(md), 2, "invalid mode"); - p->f = fopen(filename, mode); - return (p->f == NULL) ? luaL_fileresult(L, 0, filename) : 1; -} - - -/* -** function to close 'popen' files -*/ -static int io_pclose (lua_State *L) { - LStream *p = tolstream(L); - errno = 0; - return luaL_execresult(L, l_pclose(L, p->f)); -} - - -static int io_popen (lua_State *L) { - const char *filename = luaL_checkstring(L, 1); - const char *mode = luaL_optstring(L, 2, "r"); - LStream *p = newprefile(L); - luaL_argcheck(L, l_checkmodep(mode), 2, "invalid mode"); - p->f = l_popen(L, filename, mode); - p->closef = &io_pclose; - return (p->f == NULL) ? luaL_fileresult(L, 0, filename) : 1; -} - - -static int io_tmpfile (lua_State *L) { - LStream *p = newfile(L); - p->f = tmpfile(); - return (p->f == NULL) ? luaL_fileresult(L, 0, NULL) : 1; -} - - -static FILE *getiofile (lua_State *L, const char *findex) { - LStream *p; - lua_getfield(L, LUA_REGISTRYINDEX, findex); - p = (LStream *)lua_touserdata(L, -1); - if (l_unlikely(isclosed(p))) - luaL_error(L, "default %s file is closed", findex + IOPREF_LEN); - return p->f; -} - - -static int g_iofile (lua_State *L, const char *f, const char *mode) { - if (!lua_isnoneornil(L, 1)) { - const char *filename = lua_tostring(L, 1); - if (filename) - opencheck(L, filename, mode); - else { - tofile(L); /* check that it's a valid file handle */ - lua_pushvalue(L, 1); - } - lua_setfield(L, LUA_REGISTRYINDEX, f); - } - /* return current value */ - lua_getfield(L, LUA_REGISTRYINDEX, f); - return 1; -} - - -static int io_input (lua_State *L) { - return g_iofile(L, IO_INPUT, "r"); -} - - -static int io_output (lua_State *L) { - return g_iofile(L, IO_OUTPUT, "w"); -} - - -static int io_readline (lua_State *L); - - -/* -** maximum number of arguments to 'f:lines'/'io.lines' (it + 3 must fit -** in the limit for upvalues of a closure) -*/ -#define MAXARGLINE 250 - -/* -** Auxiliary function to create the iteration function for 'lines'. -** The iteration function is a closure over 'io_readline', with -** the following upvalues: -** 1) The file being read (first value in the stack) -** 2) the number of arguments to read -** 3) a boolean, true iff file has to be closed when finished ('toclose') -** *) a variable number of format arguments (rest of the stack) -*/ -static void aux_lines (lua_State *L, int toclose) { - int n = lua_gettop(L) - 1; /* number of arguments to read */ - luaL_argcheck(L, n <= MAXARGLINE, MAXARGLINE + 2, "too many arguments"); - lua_pushvalue(L, 1); /* file */ - lua_pushinteger(L, n); /* number of arguments to read */ - lua_pushboolean(L, toclose); /* close/not close file when finished */ - lua_rotate(L, 2, 3); /* move the three values to their positions */ - lua_pushcclosure(L, io_readline, 3 + n); -} - - -static int f_lines (lua_State *L) { - tofile(L); /* check that it's a valid file handle */ - aux_lines(L, 0); - return 1; -} - - -/* -** Return an iteration function for 'io.lines'. If file has to be -** closed, also returns the file itself as a second result (to be -** closed as the state at the exit of a generic for). -*/ -static int io_lines (lua_State *L) { - int toclose; - if (lua_isnone(L, 1)) lua_pushnil(L); /* at least one argument */ - if (lua_isnil(L, 1)) { /* no file name? */ - lua_getfield(L, LUA_REGISTRYINDEX, IO_INPUT); /* get default input */ - lua_replace(L, 1); /* put it at index 1 */ - tofile(L); /* check that it's a valid file handle */ - toclose = 0; /* do not close it after iteration */ - } - else { /* open a new file */ - const char *filename = luaL_checkstring(L, 1); - opencheck(L, filename, "r"); - lua_replace(L, 1); /* put file at index 1 */ - toclose = 1; /* close it after iteration */ - } - aux_lines(L, toclose); /* push iteration function */ - if (toclose) { - lua_pushnil(L); /* state */ - lua_pushnil(L); /* control */ - lua_pushvalue(L, 1); /* file is the to-be-closed variable (4th result) */ - return 4; - } - else - return 1; -} - - -/* -** {====================================================== -** READ -** ======================================================= -*/ - - -/* maximum length of a numeral */ -#if !defined (L_MAXLENNUM) -#define L_MAXLENNUM 200 -#endif - - -/* auxiliary structure used by 'read_number' */ -typedef struct { - FILE *f; /* file being read */ - int c; /* current character (look ahead) */ - int n; /* number of elements in buffer 'buff' */ - char buff[L_MAXLENNUM + 1]; /* +1 for ending '\0' */ -} RN; - - -/* -** Add current char to buffer (if not out of space) and read next one -*/ -static int nextc (RN *rn) { - if (l_unlikely(rn->n >= L_MAXLENNUM)) { /* buffer overflow? */ - rn->buff[0] = '\0'; /* invalidate result */ - return 0; /* fail */ - } - else { - rn->buff[rn->n++] = rn->c; /* save current char */ - rn->c = l_getc(rn->f); /* read next one */ - return 1; - } -} - - -/* -** Accept current char if it is in 'set' (of size 2) -*/ -static int test2 (RN *rn, const char *set) { - if (rn->c == set[0] || rn->c == set[1]) - return nextc(rn); - else return 0; -} - - -/* -** Read a sequence of (hex)digits -*/ -static int readdigits (RN *rn, int hex) { - int count = 0; - while ((hex ? isxdigit(rn->c) : isdigit(rn->c)) && nextc(rn)) - count++; - return count; -} - - -/* -** Read a number: first reads a valid prefix of a numeral into a buffer. -** Then it calls 'lua_stringtonumber' to check whether the format is -** correct and to convert it to a Lua number. -*/ -static int read_number (lua_State *L, FILE *f) { - RN rn; - int count = 0; - int hex = 0; - char decp[2]; - rn.f = f; rn.n = 0; - decp[0] = lua_getlocaledecpoint(); /* get decimal point from locale */ - decp[1] = '.'; /* always accept a dot */ - l_lockfile(rn.f); - do { rn.c = l_getc(rn.f); } while (isspace(rn.c)); /* skip spaces */ - test2(&rn, "-+"); /* optional sign */ - if (test2(&rn, "00")) { - if (test2(&rn, "xX")) hex = 1; /* numeral is hexadecimal */ - else count = 1; /* count initial '0' as a valid digit */ - } - count += readdigits(&rn, hex); /* integral part */ - if (test2(&rn, decp)) /* decimal point? */ - count += readdigits(&rn, hex); /* fractional part */ - if (count > 0 && test2(&rn, (hex ? "pP" : "eE"))) { /* exponent mark? */ - test2(&rn, "-+"); /* exponent sign */ - readdigits(&rn, 0); /* exponent digits */ - } - ungetc(rn.c, rn.f); /* unread look-ahead char */ - l_unlockfile(rn.f); - rn.buff[rn.n] = '\0'; /* finish string */ - if (l_likely(lua_stringtonumber(L, rn.buff))) - return 1; /* ok, it is a valid number */ - else { /* invalid format */ - lua_pushnil(L); /* "result" to be removed */ - return 0; /* read fails */ - } -} - - -static int test_eof (lua_State *L, FILE *f) { - int c = getc(f); - ungetc(c, f); /* no-op when c == EOF */ - lua_pushliteral(L, ""); - return (c != EOF); -} - - -static int read_line (lua_State *L, FILE *f, int chop) { - luaL_Buffer b; - int c; - luaL_buffinit(L, &b); - do { /* may need to read several chunks to get whole line */ - char *buff = luaL_prepbuffer(&b); /* preallocate buffer space */ - int i = 0; - l_lockfile(f); /* no memory errors can happen inside the lock */ - while (i < LUAL_BUFFERSIZE && (c = l_getc(f)) != EOF && c != '\n') - buff[i++] = c; /* read up to end of line or buffer limit */ - l_unlockfile(f); - luaL_addsize(&b, i); - } while (c != EOF && c != '\n'); /* repeat until end of line */ - if (!chop && c == '\n') /* want a newline and have one? */ - luaL_addchar(&b, c); /* add ending newline to result */ - luaL_pushresult(&b); /* close buffer */ - /* return ok if read something (either a newline or something else) */ - return (c == '\n' || lua_rawlen(L, -1) > 0); -} - - -static void read_all (lua_State *L, FILE *f) { - size_t nr; - luaL_Buffer b; - luaL_buffinit(L, &b); - do { /* read file in chunks of LUAL_BUFFERSIZE bytes */ - char *p = luaL_prepbuffer(&b); - nr = fread(p, sizeof(char), LUAL_BUFFERSIZE, f); - luaL_addsize(&b, nr); - } while (nr == LUAL_BUFFERSIZE); - luaL_pushresult(&b); /* close buffer */ -} - - -static int read_chars (lua_State *L, FILE *f, size_t n) { - size_t nr; /* number of chars actually read */ - char *p; - luaL_Buffer b; - luaL_buffinit(L, &b); - p = luaL_prepbuffsize(&b, n); /* prepare buffer to read whole block */ - nr = fread(p, sizeof(char), n, f); /* try to read 'n' chars */ - luaL_addsize(&b, nr); - luaL_pushresult(&b); /* close buffer */ - return (nr > 0); /* true iff read something */ -} - - -static int g_read (lua_State *L, FILE *f, int first) { - int nargs = lua_gettop(L) - 1; - int n, success; - clearerr(f); - if (nargs == 0) { /* no arguments? */ - success = read_line(L, f, 1); - n = first + 1; /* to return 1 result */ - } - else { - /* ensure stack space for all results and for auxlib's buffer */ - luaL_checkstack(L, nargs+LUA_MINSTACK, "too many arguments"); - success = 1; - for (n = first; nargs-- && success; n++) { - if (lua_type(L, n) == LUA_TNUMBER) { - size_t l = (size_t)luaL_checkinteger(L, n); - success = (l == 0) ? test_eof(L, f) : read_chars(L, f, l); - } - else { - const char *p = luaL_checkstring(L, n); - if (*p == '*') p++; /* skip optional '*' (for compatibility) */ - switch (*p) { - case 'n': /* number */ - success = read_number(L, f); - break; - case 'l': /* line */ - success = read_line(L, f, 1); - break; - case 'L': /* line with end-of-line */ - success = read_line(L, f, 0); - break; - case 'a': /* file */ - read_all(L, f); /* read entire file */ - success = 1; /* always success */ - break; - default: - return luaL_argerror(L, n, "invalid format"); - } - } - } - } - if (ferror(f)) - return luaL_fileresult(L, 0, NULL); - if (!success) { - lua_pop(L, 1); /* remove last result */ - luaL_pushfail(L); /* push nil instead */ - } - return n - first; -} - - -static int io_read (lua_State *L) { - return g_read(L, getiofile(L, IO_INPUT), 1); -} - - -static int f_read (lua_State *L) { - return g_read(L, tofile(L), 2); -} - - -/* -** Iteration function for 'lines'. -*/ -static int io_readline (lua_State *L) { - LStream *p = (LStream *)lua_touserdata(L, lua_upvalueindex(1)); - int i; - int n = (int)lua_tointeger(L, lua_upvalueindex(2)); - if (isclosed(p)) /* file is already closed? */ - return luaL_error(L, "file is already closed"); - lua_settop(L , 1); - luaL_checkstack(L, n, "too many arguments"); - for (i = 1; i <= n; i++) /* push arguments to 'g_read' */ - lua_pushvalue(L, lua_upvalueindex(3 + i)); - n = g_read(L, p->f, 2); /* 'n' is number of results */ - lua_assert(n > 0); /* should return at least a nil */ - if (lua_toboolean(L, -n)) /* read at least one value? */ - return n; /* return them */ - else { /* first result is false: EOF or error */ - if (n > 1) { /* is there error information? */ - /* 2nd result is error message */ - return luaL_error(L, "%s", lua_tostring(L, -n + 1)); - } - if (lua_toboolean(L, lua_upvalueindex(3))) { /* generator created file? */ - lua_settop(L, 0); /* clear stack */ - lua_pushvalue(L, lua_upvalueindex(1)); /* push file at index 1 */ - aux_close(L); /* close it */ - } - return 0; - } -} - -/* }====================================================== */ - - -static int g_write (lua_State *L, FILE *f, int arg) { - int nargs = lua_gettop(L) - arg; - int status = 1; - for (; nargs--; arg++) { - if (lua_type(L, arg) == LUA_TNUMBER) { - /* optimization: could be done exactly as for strings */ - int len = lua_isinteger(L, arg) - ? fprintf(f, LUA_INTEGER_FMT, - (LUAI_UACINT)lua_tointeger(L, arg)) - : fprintf(f, LUA_NUMBER_FMT, - (LUAI_UACNUMBER)lua_tonumber(L, arg)); - status = status && (len > 0); - } - else { - size_t l; - const char *s = luaL_checklstring(L, arg, &l); - status = status && (fwrite(s, sizeof(char), l, f) == l); - } - } - if (l_likely(status)) - return 1; /* file handle already on stack top */ - else return luaL_fileresult(L, status, NULL); -} - - -static int io_write (lua_State *L) { - return g_write(L, getiofile(L, IO_OUTPUT), 1); -} - - -static int f_write (lua_State *L) { - FILE *f = tofile(L); - lua_pushvalue(L, 1); /* push file at the stack top (to be returned) */ - return g_write(L, f, 2); -} - - -static int f_seek (lua_State *L) { - static const int mode[] = {SEEK_SET, SEEK_CUR, SEEK_END}; - static const char *const modenames[] = {"set", "cur", "end", NULL}; - FILE *f = tofile(L); - int op = luaL_checkoption(L, 2, "cur", modenames); - lua_Integer p3 = luaL_optinteger(L, 3, 0); - l_seeknum offset = (l_seeknum)p3; - luaL_argcheck(L, (lua_Integer)offset == p3, 3, - "not an integer in proper range"); - op = l_fseek(f, offset, mode[op]); - if (l_unlikely(op)) - return luaL_fileresult(L, 0, NULL); /* error */ - else { - lua_pushinteger(L, (lua_Integer)l_ftell(f)); - return 1; - } -} - - -static int f_setvbuf (lua_State *L) { - static const int mode[] = {_IONBF, _IOFBF, _IOLBF}; - static const char *const modenames[] = {"no", "full", "line", NULL}; - FILE *f = tofile(L); - int op = luaL_checkoption(L, 2, NULL, modenames); - lua_Integer sz = luaL_optinteger(L, 3, LUAL_BUFFERSIZE); - int res = setvbuf(f, NULL, mode[op], (size_t)sz); - return luaL_fileresult(L, res == 0, NULL); -} - - - -static int io_flush (lua_State *L) { - return luaL_fileresult(L, fflush(getiofile(L, IO_OUTPUT)) == 0, NULL); -} - - -static int f_flush (lua_State *L) { - return luaL_fileresult(L, fflush(tofile(L)) == 0, NULL); -} - - -/* -** functions for 'io' library -*/ -static const luaL_Reg iolib[] = { - {"close", io_close}, - {"flush", io_flush}, - {"input", io_input}, - {"lines", io_lines}, - {"open", io_open}, - {"output", io_output}, - {"popen", io_popen}, - {"read", io_read}, - {"tmpfile", io_tmpfile}, - {"type", io_type}, - {"write", io_write}, - {NULL, NULL} -}; - - -/* -** methods for file handles -*/ -static const luaL_Reg meth[] = { - {"read", f_read}, - {"write", f_write}, - {"lines", f_lines}, - {"flush", f_flush}, - {"seek", f_seek}, - {"close", f_close}, - {"setvbuf", f_setvbuf}, - {NULL, NULL} -}; - - -/* -** metamethods for file handles -*/ -static const luaL_Reg metameth[] = { - {"__index", NULL}, /* place holder */ - {"__gc", f_gc}, - {"__close", f_gc}, - {"__tostring", f_tostring}, - {NULL, NULL} -}; - - -static void createmeta (lua_State *L) { - luaL_newmetatable(L, LUA_FILEHANDLE); /* metatable for file handles */ - luaL_setfuncs(L, metameth, 0); /* add metamethods to new metatable */ - luaL_newlibtable(L, meth); /* create method table */ - luaL_setfuncs(L, meth, 0); /* add file methods to method table */ - lua_setfield(L, -2, "__index"); /* metatable.__index = method table */ - lua_pop(L, 1); /* pop metatable */ -} - - -/* -** function to (not) close the standard files stdin, stdout, and stderr -*/ -static int io_noclose (lua_State *L) { - LStream *p = tolstream(L); - p->closef = &io_noclose; /* keep file opened */ - luaL_pushfail(L); - lua_pushliteral(L, "cannot close standard file"); - return 2; -} - - -static void createstdfile (lua_State *L, FILE *f, const char *k, - const char *fname) { - LStream *p = newprefile(L); - p->f = f; - p->closef = &io_noclose; - if (k != NULL) { - lua_pushvalue(L, -1); - lua_setfield(L, LUA_REGISTRYINDEX, k); /* add file to registry */ - } - lua_setfield(L, -2, fname); /* add file to module */ -} - - -LUAMOD_API int luaopen_io (lua_State *L) { - luaL_newlib(L, iolib); /* new module */ - createmeta(L); - /* create (and set) default files */ - createstdfile(L, stdin, IO_INPUT, "stdin"); - createstdfile(L, stdout, IO_OUTPUT, "stdout"); - createstdfile(L, stderr, NULL, "stderr"); - return 1; -} - diff --git a/lib/lua-5.4/src/ljumptab.h b/lib/lua-5.4/src/ljumptab.h deleted file mode 100644 index 8306f25..0000000 --- a/lib/lua-5.4/src/ljumptab.h +++ /dev/null @@ -1,112 +0,0 @@ -/* -** $Id: ljumptab.h $ -** Jump Table for the Lua interpreter -** See Copyright Notice in lua.h -*/ - - -#undef vmdispatch -#undef vmcase -#undef vmbreak - -#define vmdispatch(x) goto *disptab[x]; - -#define vmcase(l) L_##l: - -#define vmbreak vmfetch(); vmdispatch(GET_OPCODE(i)); - - -static const void *const disptab[NUM_OPCODES] = { - -#if 0 -** you can update the following list with this command: -** -** sed -n '/^OP_/\!d; s/OP_/\&\&L_OP_/ ; s/,.*/,/ ; s/\/.*// ; p' lopcodes.h -** -#endif - -&&L_OP_MOVE, -&&L_OP_LOADI, -&&L_OP_LOADF, -&&L_OP_LOADK, -&&L_OP_LOADKX, -&&L_OP_LOADFALSE, -&&L_OP_LFALSESKIP, -&&L_OP_LOADTRUE, -&&L_OP_LOADNIL, -&&L_OP_GETUPVAL, -&&L_OP_SETUPVAL, -&&L_OP_GETTABUP, -&&L_OP_GETTABLE, -&&L_OP_GETI, -&&L_OP_GETFIELD, -&&L_OP_SETTABUP, -&&L_OP_SETTABLE, -&&L_OP_SETI, -&&L_OP_SETFIELD, -&&L_OP_NEWTABLE, -&&L_OP_SELF, -&&L_OP_ADDI, -&&L_OP_ADDK, -&&L_OP_SUBK, -&&L_OP_MULK, -&&L_OP_MODK, -&&L_OP_POWK, -&&L_OP_DIVK, -&&L_OP_IDIVK, -&&L_OP_BANDK, -&&L_OP_BORK, -&&L_OP_BXORK, -&&L_OP_SHRI, -&&L_OP_SHLI, -&&L_OP_ADD, -&&L_OP_SUB, -&&L_OP_MUL, -&&L_OP_MOD, -&&L_OP_POW, -&&L_OP_DIV, -&&L_OP_IDIV, -&&L_OP_BAND, -&&L_OP_BOR, -&&L_OP_BXOR, -&&L_OP_SHL, -&&L_OP_SHR, -&&L_OP_MMBIN, -&&L_OP_MMBINI, -&&L_OP_MMBINK, -&&L_OP_UNM, -&&L_OP_BNOT, -&&L_OP_NOT, -&&L_OP_LEN, -&&L_OP_CONCAT, -&&L_OP_CLOSE, -&&L_OP_TBC, -&&L_OP_JMP, -&&L_OP_EQ, -&&L_OP_LT, -&&L_OP_LE, -&&L_OP_EQK, -&&L_OP_EQI, -&&L_OP_LTI, -&&L_OP_LEI, -&&L_OP_GTI, -&&L_OP_GEI, -&&L_OP_TEST, -&&L_OP_TESTSET, -&&L_OP_CALL, -&&L_OP_TAILCALL, -&&L_OP_RETURN, -&&L_OP_RETURN0, -&&L_OP_RETURN1, -&&L_OP_FORLOOP, -&&L_OP_FORPREP, -&&L_OP_TFORPREP, -&&L_OP_TFORCALL, -&&L_OP_TFORLOOP, -&&L_OP_SETLIST, -&&L_OP_CLOSURE, -&&L_OP_VARARG, -&&L_OP_VARARGPREP, -&&L_OP_EXTRAARG - -}; diff --git a/lib/lua-5.4/src/llex.c b/lib/lua-5.4/src/llex.c deleted file mode 100644 index 5fc39a5..0000000 --- a/lib/lua-5.4/src/llex.c +++ /dev/null @@ -1,581 +0,0 @@ -/* -** $Id: llex.c $ -** Lexical Analyzer -** See Copyright Notice in lua.h -*/ - -#define llex_c -#define LUA_CORE - -#include "lprefix.h" - - -#include -#include - -#include "lua.h" - -#include "lctype.h" -#include "ldebug.h" -#include "ldo.h" -#include "lgc.h" -#include "llex.h" -#include "lobject.h" -#include "lparser.h" -#include "lstate.h" -#include "lstring.h" -#include "ltable.h" -#include "lzio.h" - - - -#define next(ls) (ls->current = zgetc(ls->z)) - - - -#define currIsNewline(ls) (ls->current == '\n' || ls->current == '\r') - - -/* ORDER RESERVED */ -static const char *const luaX_tokens [] = { - "and", "break", "do", "else", "elseif", - "end", "false", "for", "function", "goto", "if", - "in", "local", "nil", "not", "or", "repeat", - "return", "then", "true", "until", "while", - "//", "..", "...", "==", ">=", "<=", "~=", - "<<", ">>", "::", "", - "", "", "", "" -}; - - -#define save_and_next(ls) (save(ls, ls->current), next(ls)) - - -static l_noret lexerror (LexState *ls, const char *msg, int token); - - -static void save (LexState *ls, int c) { - Mbuffer *b = ls->buff; - if (luaZ_bufflen(b) + 1 > luaZ_sizebuffer(b)) { - size_t newsize; - if (luaZ_sizebuffer(b) >= MAX_SIZE/2) - lexerror(ls, "lexical element too long", 0); - newsize = luaZ_sizebuffer(b) * 2; - luaZ_resizebuffer(ls->L, b, newsize); - } - b->buffer[luaZ_bufflen(b)++] = cast_char(c); -} - - -void luaX_init (lua_State *L) { - int i; - TString *e = luaS_newliteral(L, LUA_ENV); /* create env name */ - luaC_fix(L, obj2gco(e)); /* never collect this name */ - for (i=0; iextra = cast_byte(i+1); /* reserved word */ - } -} - - -const char *luaX_token2str (LexState *ls, int token) { - if (token < FIRST_RESERVED) { /* single-byte symbols? */ - if (lisprint(token)) - return luaO_pushfstring(ls->L, "'%c'", token); - else /* control character */ - return luaO_pushfstring(ls->L, "'<\\%d>'", token); - } - else { - const char *s = luaX_tokens[token - FIRST_RESERVED]; - if (token < TK_EOS) /* fixed format (symbols and reserved words)? */ - return luaO_pushfstring(ls->L, "'%s'", s); - else /* names, strings, and numerals */ - return s; - } -} - - -static const char *txtToken (LexState *ls, int token) { - switch (token) { - case TK_NAME: case TK_STRING: - case TK_FLT: case TK_INT: - save(ls, '\0'); - return luaO_pushfstring(ls->L, "'%s'", luaZ_buffer(ls->buff)); - default: - return luaX_token2str(ls, token); - } -} - - -static l_noret lexerror (LexState *ls, const char *msg, int token) { - msg = luaG_addinfo(ls->L, msg, ls->source, ls->linenumber); - if (token) - luaO_pushfstring(ls->L, "%s near %s", msg, txtToken(ls, token)); - luaD_throw(ls->L, LUA_ERRSYNTAX); -} - - -l_noret luaX_syntaxerror (LexState *ls, const char *msg) { - lexerror(ls, msg, ls->t.token); -} - - -/* -** Creates a new string and anchors it in scanner's table so that it -** will not be collected until the end of the compilation; by that time -** it should be anchored somewhere. It also internalizes long strings, -** ensuring there is only one copy of each unique string. The table -** here is used as a set: the string enters as the key, while its value -** is irrelevant. We use the string itself as the value only because it -** is a TValue readily available. Later, the code generation can change -** this value. -*/ -TString *luaX_newstring (LexState *ls, const char *str, size_t l) { - lua_State *L = ls->L; - TString *ts = luaS_newlstr(L, str, l); /* create new string */ - const TValue *o = luaH_getstr(ls->h, ts); - if (!ttisnil(o)) /* string already present? */ - ts = keystrval(nodefromval(o)); /* get saved copy */ - else { /* not in use yet */ - TValue *stv = s2v(L->top.p++); /* reserve stack space for string */ - setsvalue(L, stv, ts); /* temporarily anchor the string */ - luaH_finishset(L, ls->h, stv, o, stv); /* t[string] = string */ - /* table is not a metatable, so it does not need to invalidate cache */ - luaC_checkGC(L); - L->top.p--; /* remove string from stack */ - } - return ts; -} - - -/* -** increment line number and skips newline sequence (any of -** \n, \r, \n\r, or \r\n) -*/ -static void inclinenumber (LexState *ls) { - int old = ls->current; - lua_assert(currIsNewline(ls)); - next(ls); /* skip '\n' or '\r' */ - if (currIsNewline(ls) && ls->current != old) - next(ls); /* skip '\n\r' or '\r\n' */ - if (++ls->linenumber >= MAX_INT) - lexerror(ls, "chunk has too many lines", 0); -} - - -void luaX_setinput (lua_State *L, LexState *ls, ZIO *z, TString *source, - int firstchar) { - ls->t.token = 0; - ls->L = L; - ls->current = firstchar; - ls->lookahead.token = TK_EOS; /* no look-ahead token */ - ls->z = z; - ls->fs = NULL; - ls->linenumber = 1; - ls->lastline = 1; - ls->source = source; - ls->envn = luaS_newliteral(L, LUA_ENV); /* get env name */ - luaZ_resizebuffer(ls->L, ls->buff, LUA_MINBUFFER); /* initialize buffer */ -} - - - -/* -** ======================================================= -** LEXICAL ANALYZER -** ======================================================= -*/ - - -static int check_next1 (LexState *ls, int c) { - if (ls->current == c) { - next(ls); - return 1; - } - else return 0; -} - - -/* -** Check whether current char is in set 'set' (with two chars) and -** saves it -*/ -static int check_next2 (LexState *ls, const char *set) { - lua_assert(set[2] == '\0'); - if (ls->current == set[0] || ls->current == set[1]) { - save_and_next(ls); - return 1; - } - else return 0; -} - - -/* LUA_NUMBER */ -/* -** This function is quite liberal in what it accepts, as 'luaO_str2num' -** will reject ill-formed numerals. Roughly, it accepts the following -** pattern: -** -** %d(%x|%.|([Ee][+-]?))* | 0[Xx](%x|%.|([Pp][+-]?))* -** -** The only tricky part is to accept [+-] only after a valid exponent -** mark, to avoid reading '3-4' or '0xe+1' as a single number. -** -** The caller might have already read an initial dot. -*/ -static int read_numeral (LexState *ls, SemInfo *seminfo) { - TValue obj; - const char *expo = "Ee"; - int first = ls->current; - lua_assert(lisdigit(ls->current)); - save_and_next(ls); - if (first == '0' && check_next2(ls, "xX")) /* hexadecimal? */ - expo = "Pp"; - for (;;) { - if (check_next2(ls, expo)) /* exponent mark? */ - check_next2(ls, "-+"); /* optional exponent sign */ - else if (lisxdigit(ls->current) || ls->current == '.') /* '%x|%.' */ - save_and_next(ls); - else break; - } - if (lislalpha(ls->current)) /* is numeral touching a letter? */ - save_and_next(ls); /* force an error */ - save(ls, '\0'); - if (luaO_str2num(luaZ_buffer(ls->buff), &obj) == 0) /* format error? */ - lexerror(ls, "malformed number", TK_FLT); - if (ttisinteger(&obj)) { - seminfo->i = ivalue(&obj); - return TK_INT; - } - else { - lua_assert(ttisfloat(&obj)); - seminfo->r = fltvalue(&obj); - return TK_FLT; - } -} - - -/* -** read a sequence '[=*[' or ']=*]', leaving the last bracket. If -** sequence is well formed, return its number of '='s + 2; otherwise, -** return 1 if it is a single bracket (no '='s and no 2nd bracket); -** otherwise (an unfinished '[==...') return 0. -*/ -static size_t skip_sep (LexState *ls) { - size_t count = 0; - int s = ls->current; - lua_assert(s == '[' || s == ']'); - save_and_next(ls); - while (ls->current == '=') { - save_and_next(ls); - count++; - } - return (ls->current == s) ? count + 2 - : (count == 0) ? 1 - : 0; -} - - -static void read_long_string (LexState *ls, SemInfo *seminfo, size_t sep) { - int line = ls->linenumber; /* initial line (for error message) */ - save_and_next(ls); /* skip 2nd '[' */ - if (currIsNewline(ls)) /* string starts with a newline? */ - inclinenumber(ls); /* skip it */ - for (;;) { - switch (ls->current) { - case EOZ: { /* error */ - const char *what = (seminfo ? "string" : "comment"); - const char *msg = luaO_pushfstring(ls->L, - "unfinished long %s (starting at line %d)", what, line); - lexerror(ls, msg, TK_EOS); - break; /* to avoid warnings */ - } - case ']': { - if (skip_sep(ls) == sep) { - save_and_next(ls); /* skip 2nd ']' */ - goto endloop; - } - break; - } - case '\n': case '\r': { - save(ls, '\n'); - inclinenumber(ls); - if (!seminfo) luaZ_resetbuffer(ls->buff); /* avoid wasting space */ - break; - } - default: { - if (seminfo) save_and_next(ls); - else next(ls); - } - } - } endloop: - if (seminfo) - seminfo->ts = luaX_newstring(ls, luaZ_buffer(ls->buff) + sep, - luaZ_bufflen(ls->buff) - 2 * sep); -} - - -static void esccheck (LexState *ls, int c, const char *msg) { - if (!c) { - if (ls->current != EOZ) - save_and_next(ls); /* add current to buffer for error message */ - lexerror(ls, msg, TK_STRING); - } -} - - -static int gethexa (LexState *ls) { - save_and_next(ls); - esccheck (ls, lisxdigit(ls->current), "hexadecimal digit expected"); - return luaO_hexavalue(ls->current); -} - - -static int readhexaesc (LexState *ls) { - int r = gethexa(ls); - r = (r << 4) + gethexa(ls); - luaZ_buffremove(ls->buff, 2); /* remove saved chars from buffer */ - return r; -} - - -static unsigned long readutf8esc (LexState *ls) { - unsigned long r; - int i = 4; /* chars to be removed: '\', 'u', '{', and first digit */ - save_and_next(ls); /* skip 'u' */ - esccheck(ls, ls->current == '{', "missing '{'"); - r = gethexa(ls); /* must have at least one digit */ - while (cast_void(save_and_next(ls)), lisxdigit(ls->current)) { - i++; - esccheck(ls, r <= (0x7FFFFFFFu >> 4), "UTF-8 value too large"); - r = (r << 4) + luaO_hexavalue(ls->current); - } - esccheck(ls, ls->current == '}', "missing '}'"); - next(ls); /* skip '}' */ - luaZ_buffremove(ls->buff, i); /* remove saved chars from buffer */ - return r; -} - - -static void utf8esc (LexState *ls) { - char buff[UTF8BUFFSZ]; - int n = luaO_utf8esc(buff, readutf8esc(ls)); - for (; n > 0; n--) /* add 'buff' to string */ - save(ls, buff[UTF8BUFFSZ - n]); -} - - -static int readdecesc (LexState *ls) { - int i; - int r = 0; /* result accumulator */ - for (i = 0; i < 3 && lisdigit(ls->current); i++) { /* read up to 3 digits */ - r = 10*r + ls->current - '0'; - save_and_next(ls); - } - esccheck(ls, r <= UCHAR_MAX, "decimal escape too large"); - luaZ_buffremove(ls->buff, i); /* remove read digits from buffer */ - return r; -} - - -static void read_string (LexState *ls, int del, SemInfo *seminfo) { - save_and_next(ls); /* keep delimiter (for error messages) */ - while (ls->current != del) { - switch (ls->current) { - case EOZ: - lexerror(ls, "unfinished string", TK_EOS); - break; /* to avoid warnings */ - case '\n': - case '\r': - lexerror(ls, "unfinished string", TK_STRING); - break; /* to avoid warnings */ - case '\\': { /* escape sequences */ - int c; /* final character to be saved */ - save_and_next(ls); /* keep '\\' for error messages */ - switch (ls->current) { - case 'a': c = '\a'; goto read_save; - case 'b': c = '\b'; goto read_save; - case 'f': c = '\f'; goto read_save; - case 'n': c = '\n'; goto read_save; - case 'r': c = '\r'; goto read_save; - case 't': c = '\t'; goto read_save; - case 'v': c = '\v'; goto read_save; - case 'x': c = readhexaesc(ls); goto read_save; - case 'u': utf8esc(ls); goto no_save; - case '\n': case '\r': - inclinenumber(ls); c = '\n'; goto only_save; - case '\\': case '\"': case '\'': - c = ls->current; goto read_save; - case EOZ: goto no_save; /* will raise an error next loop */ - case 'z': { /* zap following span of spaces */ - luaZ_buffremove(ls->buff, 1); /* remove '\\' */ - next(ls); /* skip the 'z' */ - while (lisspace(ls->current)) { - if (currIsNewline(ls)) inclinenumber(ls); - else next(ls); - } - goto no_save; - } - default: { - esccheck(ls, lisdigit(ls->current), "invalid escape sequence"); - c = readdecesc(ls); /* digital escape '\ddd' */ - goto only_save; - } - } - read_save: - next(ls); - /* go through */ - only_save: - luaZ_buffremove(ls->buff, 1); /* remove '\\' */ - save(ls, c); - /* go through */ - no_save: break; - } - default: - save_and_next(ls); - } - } - save_and_next(ls); /* skip delimiter */ - seminfo->ts = luaX_newstring(ls, luaZ_buffer(ls->buff) + 1, - luaZ_bufflen(ls->buff) - 2); -} - - -static int llex (LexState *ls, SemInfo *seminfo) { - luaZ_resetbuffer(ls->buff); - for (;;) { - switch (ls->current) { - case '\n': case '\r': { /* line breaks */ - inclinenumber(ls); - break; - } - case ' ': case '\f': case '\t': case '\v': { /* spaces */ - next(ls); - break; - } - case '-': { /* '-' or '--' (comment) */ - next(ls); - if (ls->current != '-') return '-'; - /* else is a comment */ - next(ls); - if (ls->current == '[') { /* long comment? */ - size_t sep = skip_sep(ls); - luaZ_resetbuffer(ls->buff); /* 'skip_sep' may dirty the buffer */ - if (sep >= 2) { - read_long_string(ls, NULL, sep); /* skip long comment */ - luaZ_resetbuffer(ls->buff); /* previous call may dirty the buff. */ - break; - } - } - /* else short comment */ - while (!currIsNewline(ls) && ls->current != EOZ) - next(ls); /* skip until end of line (or end of file) */ - break; - } - case '[': { /* long string or simply '[' */ - size_t sep = skip_sep(ls); - if (sep >= 2) { - read_long_string(ls, seminfo, sep); - return TK_STRING; - } - else if (sep == 0) /* '[=...' missing second bracket? */ - lexerror(ls, "invalid long string delimiter", TK_STRING); - return '['; - } - case '=': { - next(ls); - if (check_next1(ls, '=')) return TK_EQ; /* '==' */ - else return '='; - } - case '<': { - next(ls); - if (check_next1(ls, '=')) return TK_LE; /* '<=' */ - else if (check_next1(ls, '<')) return TK_SHL; /* '<<' */ - else return '<'; - } - case '>': { - next(ls); - if (check_next1(ls, '=')) return TK_GE; /* '>=' */ - else if (check_next1(ls, '>')) return TK_SHR; /* '>>' */ - else return '>'; - } - case '/': { - next(ls); - if (check_next1(ls, '/')) return TK_IDIV; /* '//' */ - else return '/'; - } - case '~': { - next(ls); - if (check_next1(ls, '=')) return TK_NE; /* '~=' */ - else return '~'; - } - case ':': { - next(ls); - if (check_next1(ls, ':')) return TK_DBCOLON; /* '::' */ - else return ':'; - } - case '"': case '\'': { /* short literal strings */ - read_string(ls, ls->current, seminfo); - return TK_STRING; - } - case '.': { /* '.', '..', '...', or number */ - save_and_next(ls); - if (check_next1(ls, '.')) { - if (check_next1(ls, '.')) - return TK_DOTS; /* '...' */ - else return TK_CONCAT; /* '..' */ - } - else if (!lisdigit(ls->current)) return '.'; - else return read_numeral(ls, seminfo); - } - case '0': case '1': case '2': case '3': case '4': - case '5': case '6': case '7': case '8': case '9': { - return read_numeral(ls, seminfo); - } - case EOZ: { - return TK_EOS; - } - default: { - if (lislalpha(ls->current)) { /* identifier or reserved word? */ - TString *ts; - do { - save_and_next(ls); - } while (lislalnum(ls->current)); - ts = luaX_newstring(ls, luaZ_buffer(ls->buff), - luaZ_bufflen(ls->buff)); - seminfo->ts = ts; - if (isreserved(ts)) /* reserved word? */ - return ts->extra - 1 + FIRST_RESERVED; - else { - return TK_NAME; - } - } - else { /* single-char tokens ('+', '*', '%', '{', '}', ...) */ - int c = ls->current; - next(ls); - return c; - } - } - } - } -} - - -void luaX_next (LexState *ls) { - ls->lastline = ls->linenumber; - if (ls->lookahead.token != TK_EOS) { /* is there a look-ahead token? */ - ls->t = ls->lookahead; /* use this one */ - ls->lookahead.token = TK_EOS; /* and discharge it */ - } - else - ls->t.token = llex(ls, &ls->t.seminfo); /* read next token */ -} - - -int luaX_lookahead (LexState *ls) { - lua_assert(ls->lookahead.token == TK_EOS); - ls->lookahead.token = llex(ls, &ls->lookahead.seminfo); - return ls->lookahead.token; -} - diff --git a/lib/lua-5.4/src/llex.h b/lib/lua-5.4/src/llex.h deleted file mode 100644 index 389d2f8..0000000 --- a/lib/lua-5.4/src/llex.h +++ /dev/null @@ -1,91 +0,0 @@ -/* -** $Id: llex.h $ -** Lexical Analyzer -** See Copyright Notice in lua.h -*/ - -#ifndef llex_h -#define llex_h - -#include - -#include "lobject.h" -#include "lzio.h" - - -/* -** Single-char tokens (terminal symbols) are represented by their own -** numeric code. Other tokens start at the following value. -*/ -#define FIRST_RESERVED (UCHAR_MAX + 1) - - -#if !defined(LUA_ENV) -#define LUA_ENV "_ENV" -#endif - - -/* -* WARNING: if you change the order of this enumeration, -* grep "ORDER RESERVED" -*/ -enum RESERVED { - /* terminal symbols denoted by reserved words */ - TK_AND = FIRST_RESERVED, TK_BREAK, - TK_DO, TK_ELSE, TK_ELSEIF, TK_END, TK_FALSE, TK_FOR, TK_FUNCTION, - TK_GOTO, TK_IF, TK_IN, TK_LOCAL, TK_NIL, TK_NOT, TK_OR, TK_REPEAT, - TK_RETURN, TK_THEN, TK_TRUE, TK_UNTIL, TK_WHILE, - /* other terminal symbols */ - TK_IDIV, TK_CONCAT, TK_DOTS, TK_EQ, TK_GE, TK_LE, TK_NE, - TK_SHL, TK_SHR, - TK_DBCOLON, TK_EOS, - TK_FLT, TK_INT, TK_NAME, TK_STRING -}; - -/* number of reserved words */ -#define NUM_RESERVED (cast_int(TK_WHILE-FIRST_RESERVED + 1)) - - -typedef union { - lua_Number r; - lua_Integer i; - TString *ts; -} SemInfo; /* semantics information */ - - -typedef struct Token { - int token; - SemInfo seminfo; -} Token; - - -/* state of the lexer plus state of the parser when shared by all - functions */ -typedef struct LexState { - int current; /* current character (charint) */ - int linenumber; /* input line counter */ - int lastline; /* line of last token 'consumed' */ - Token t; /* current token */ - Token lookahead; /* look ahead token */ - struct FuncState *fs; /* current function (parser) */ - struct lua_State *L; - ZIO *z; /* input stream */ - Mbuffer *buff; /* buffer for tokens */ - Table *h; /* to avoid collection/reuse strings */ - struct Dyndata *dyd; /* dynamic structures used by the parser */ - TString *source; /* current source name */ - TString *envn; /* environment variable name */ -} LexState; - - -LUAI_FUNC void luaX_init (lua_State *L); -LUAI_FUNC void luaX_setinput (lua_State *L, LexState *ls, ZIO *z, - TString *source, int firstchar); -LUAI_FUNC TString *luaX_newstring (LexState *ls, const char *str, size_t l); -LUAI_FUNC void luaX_next (LexState *ls); -LUAI_FUNC int luaX_lookahead (LexState *ls); -LUAI_FUNC l_noret luaX_syntaxerror (LexState *ls, const char *s); -LUAI_FUNC const char *luaX_token2str (LexState *ls, int token); - - -#endif diff --git a/lib/lua-5.4/src/llimits.h b/lib/lua-5.4/src/llimits.h deleted file mode 100644 index 1c826f7..0000000 --- a/lib/lua-5.4/src/llimits.h +++ /dev/null @@ -1,380 +0,0 @@ -/* -** $Id: llimits.h $ -** Limits, basic types, and some other 'installation-dependent' definitions -** See Copyright Notice in lua.h -*/ - -#ifndef llimits_h -#define llimits_h - - -#include -#include - - -#include "lua.h" - - -/* -** 'lu_mem' and 'l_mem' are unsigned/signed integers big enough to count -** the total memory used by Lua (in bytes). Usually, 'size_t' and -** 'ptrdiff_t' should work, but we use 'long' for 16-bit machines. -*/ -#if defined(LUAI_MEM) /* { external definitions? */ -typedef LUAI_UMEM lu_mem; -typedef LUAI_MEM l_mem; -#elif LUAI_IS32INT /* }{ */ -typedef size_t lu_mem; -typedef ptrdiff_t l_mem; -#else /* 16-bit ints */ /* }{ */ -typedef unsigned long lu_mem; -typedef long l_mem; -#endif /* } */ - - -/* chars used as small naturals (so that 'char' is reserved for characters) */ -typedef unsigned char lu_byte; -typedef signed char ls_byte; - - -/* maximum value for size_t */ -#define MAX_SIZET ((size_t)(~(size_t)0)) - -/* maximum size visible for Lua (must be representable in a lua_Integer) */ -#define MAX_SIZE (sizeof(size_t) < sizeof(lua_Integer) ? MAX_SIZET \ - : (size_t)(LUA_MAXINTEGER)) - - -#define MAX_LUMEM ((lu_mem)(~(lu_mem)0)) - -#define MAX_LMEM ((l_mem)(MAX_LUMEM >> 1)) - - -#define MAX_INT INT_MAX /* maximum value of an int */ - - -/* -** floor of the log2 of the maximum signed value for integral type 't'. -** (That is, maximum 'n' such that '2^n' fits in the given signed type.) -*/ -#define log2maxs(t) (sizeof(t) * 8 - 2) - - -/* -** test whether an unsigned value is a power of 2 (or zero) -*/ -#define ispow2(x) (((x) & ((x) - 1)) == 0) - - -/* number of chars of a literal string without the ending \0 */ -#define LL(x) (sizeof(x)/sizeof(char) - 1) - - -/* -** conversion of pointer to unsigned integer: this is for hashing only; -** there is no problem if the integer cannot hold the whole pointer -** value. (In strict ISO C this may cause undefined behavior, but no -** actual machine seems to bother.) -*/ -#if !defined(LUA_USE_C89) && defined(__STDC_VERSION__) && \ - __STDC_VERSION__ >= 199901L -#include -#if defined(UINTPTR_MAX) /* even in C99 this type is optional */ -#define L_P2I uintptr_t -#else /* no 'intptr'? */ -#define L_P2I uintmax_t /* use the largest available integer */ -#endif -#else /* C89 option */ -#define L_P2I size_t -#endif - -#define point2uint(p) ((unsigned int)((L_P2I)(p) & UINT_MAX)) - - - -/* types of 'usual argument conversions' for lua_Number and lua_Integer */ -typedef LUAI_UACNUMBER l_uacNumber; -typedef LUAI_UACINT l_uacInt; - - -/* -** Internal assertions for in-house debugging -*/ -#if defined LUAI_ASSERT -#undef NDEBUG -#include -#define lua_assert(c) assert(c) -#endif - -#if defined(lua_assert) -#define check_exp(c,e) (lua_assert(c), (e)) -/* to avoid problems with conditions too long */ -#define lua_longassert(c) ((c) ? (void)0 : lua_assert(0)) -#else -#define lua_assert(c) ((void)0) -#define check_exp(c,e) (e) -#define lua_longassert(c) ((void)0) -#endif - -/* -** assertion for checking API calls -*/ -#if !defined(luai_apicheck) -#define luai_apicheck(l,e) ((void)l, lua_assert(e)) -#endif - -#define api_check(l,e,msg) luai_apicheck(l,(e) && msg) - - -/* macro to avoid warnings about unused variables */ -#if !defined(UNUSED) -#define UNUSED(x) ((void)(x)) -#endif - - -/* type casts (a macro highlights casts in the code) */ -#define cast(t, exp) ((t)(exp)) - -#define cast_void(i) cast(void, (i)) -#define cast_voidp(i) cast(void *, (i)) -#define cast_num(i) cast(lua_Number, (i)) -#define cast_int(i) cast(int, (i)) -#define cast_uint(i) cast(unsigned int, (i)) -#define cast_byte(i) cast(lu_byte, (i)) -#define cast_uchar(i) cast(unsigned char, (i)) -#define cast_char(i) cast(char, (i)) -#define cast_charp(i) cast(char *, (i)) -#define cast_sizet(i) cast(size_t, (i)) - - -/* cast a signed lua_Integer to lua_Unsigned */ -#if !defined(l_castS2U) -#define l_castS2U(i) ((lua_Unsigned)(i)) -#endif - -/* -** cast a lua_Unsigned to a signed lua_Integer; this cast is -** not strict ISO C, but two-complement architectures should -** work fine. -*/ -#if !defined(l_castU2S) -#define l_castU2S(i) ((lua_Integer)(i)) -#endif - - -/* -** non-return type -*/ -#if !defined(l_noret) - -#if defined(__GNUC__) -#define l_noret void __attribute__((noreturn)) -#elif defined(_MSC_VER) && _MSC_VER >= 1200 -#define l_noret void __declspec(noreturn) -#else -#define l_noret void -#endif - -#endif - - -/* -** Inline functions -*/ -#if !defined(LUA_USE_C89) -#define l_inline inline -#elif defined(__GNUC__) -#define l_inline __inline__ -#else -#define l_inline /* empty */ -#endif - -#define l_sinline static l_inline - - -/* -** type for virtual-machine instructions; -** must be an unsigned with (at least) 4 bytes (see details in lopcodes.h) -*/ -#if LUAI_IS32INT -typedef unsigned int l_uint32; -#else -typedef unsigned long l_uint32; -#endif - -typedef l_uint32 Instruction; - - - -/* -** Maximum length for short strings, that is, strings that are -** internalized. (Cannot be smaller than reserved words or tags for -** metamethods, as these strings must be internalized; -** #("function") = 8, #("__newindex") = 10.) -*/ -#if !defined(LUAI_MAXSHORTLEN) -#define LUAI_MAXSHORTLEN 40 -#endif - - -/* -** Initial size for the string table (must be power of 2). -** The Lua core alone registers ~50 strings (reserved words + -** metaevent keys + a few others). Libraries would typically add -** a few dozens more. -*/ -#if !defined(MINSTRTABSIZE) -#define MINSTRTABSIZE 128 -#endif - - -/* -** Size of cache for strings in the API. 'N' is the number of -** sets (better be a prime) and "M" is the size of each set (M == 1 -** makes a direct cache.) -*/ -#if !defined(STRCACHE_N) -#define STRCACHE_N 53 -#define STRCACHE_M 2 -#endif - - -/* minimum size for string buffer */ -#if !defined(LUA_MINBUFFER) -#define LUA_MINBUFFER 32 -#endif - - -/* -** Maximum depth for nested C calls, syntactical nested non-terminals, -** and other features implemented through recursion in C. (Value must -** fit in a 16-bit unsigned integer. It must also be compatible with -** the size of the C stack.) -*/ -#if !defined(LUAI_MAXCCALLS) -#define LUAI_MAXCCALLS 200 -#endif - - -/* -** macros that are executed whenever program enters the Lua core -** ('lua_lock') and leaves the core ('lua_unlock') -*/ -#if !defined(lua_lock) -#define lua_lock(L) ((void) 0) -#define lua_unlock(L) ((void) 0) -#endif - -/* -** macro executed during Lua functions at points where the -** function can yield. -*/ -#if !defined(luai_threadyield) -#define luai_threadyield(L) {lua_unlock(L); lua_lock(L);} -#endif - - -/* -** these macros allow user-specific actions when a thread is -** created/deleted/resumed/yielded. -*/ -#if !defined(luai_userstateopen) -#define luai_userstateopen(L) ((void)L) -#endif - -#if !defined(luai_userstateclose) -#define luai_userstateclose(L) ((void)L) -#endif - -#if !defined(luai_userstatethread) -#define luai_userstatethread(L,L1) ((void)L) -#endif - -#if !defined(luai_userstatefree) -#define luai_userstatefree(L,L1) ((void)L) -#endif - -#if !defined(luai_userstateresume) -#define luai_userstateresume(L,n) ((void)L) -#endif - -#if !defined(luai_userstateyield) -#define luai_userstateyield(L,n) ((void)L) -#endif - - - -/* -** The luai_num* macros define the primitive operations over numbers. -*/ - -/* floor division (defined as 'floor(a/b)') */ -#if !defined(luai_numidiv) -#define luai_numidiv(L,a,b) ((void)L, l_floor(luai_numdiv(L,a,b))) -#endif - -/* float division */ -#if !defined(luai_numdiv) -#define luai_numdiv(L,a,b) ((a)/(b)) -#endif - -/* -** modulo: defined as 'a - floor(a/b)*b'; the direct computation -** using this definition has several problems with rounding errors, -** so it is better to use 'fmod'. 'fmod' gives the result of -** 'a - trunc(a/b)*b', and therefore must be corrected when -** 'trunc(a/b) ~= floor(a/b)'. That happens when the division has a -** non-integer negative result: non-integer result is equivalent to -** a non-zero remainder 'm'; negative result is equivalent to 'a' and -** 'b' with different signs, or 'm' and 'b' with different signs -** (as the result 'm' of 'fmod' has the same sign of 'a'). -*/ -#if !defined(luai_nummod) -#define luai_nummod(L,a,b,m) \ - { (void)L; (m) = l_mathop(fmod)(a,b); \ - if (((m) > 0) ? (b) < 0 : ((m) < 0 && (b) > 0)) (m) += (b); } -#endif - -/* exponentiation */ -#if !defined(luai_numpow) -#define luai_numpow(L,a,b) \ - ((void)L, (b == 2) ? (a)*(a) : l_mathop(pow)(a,b)) -#endif - -/* the others are quite standard operations */ -#if !defined(luai_numadd) -#define luai_numadd(L,a,b) ((a)+(b)) -#define luai_numsub(L,a,b) ((a)-(b)) -#define luai_nummul(L,a,b) ((a)*(b)) -#define luai_numunm(L,a) (-(a)) -#define luai_numeq(a,b) ((a)==(b)) -#define luai_numlt(a,b) ((a)<(b)) -#define luai_numle(a,b) ((a)<=(b)) -#define luai_numgt(a,b) ((a)>(b)) -#define luai_numge(a,b) ((a)>=(b)) -#define luai_numisnan(a) (!luai_numeq((a), (a))) -#endif - - - - - -/* -** macro to control inclusion of some hard tests on stack reallocation -*/ -#if !defined(HARDSTACKTESTS) -#define condmovestack(L,pre,pos) ((void)0) -#else -/* realloc stack keeping its size */ -#define condmovestack(L,pre,pos) \ - { int sz_ = stacksize(L); pre; luaD_reallocstack((L), sz_, 0); pos; } -#endif - -#if !defined(HARDMEMTESTS) -#define condchangemem(L,pre,pos) ((void)0) -#else -#define condchangemem(L,pre,pos) \ - { if (gcrunning(G(L))) { pre; luaC_fullgc(L, 0); pos; } } -#endif - -#endif diff --git a/lib/lua-5.4/src/lmathlib.c b/lib/lua-5.4/src/lmathlib.c deleted file mode 100644 index d0b1e1e..0000000 --- a/lib/lua-5.4/src/lmathlib.c +++ /dev/null @@ -1,764 +0,0 @@ -/* -** $Id: lmathlib.c $ -** Standard mathematical library -** See Copyright Notice in lua.h -*/ - -#define lmathlib_c -#define LUA_LIB - -#include "lprefix.h" - - -#include -#include -#include -#include -#include - -#include "lua.h" - -#include "lauxlib.h" -#include "lualib.h" - - -#undef PI -#define PI (l_mathop(3.141592653589793238462643383279502884)) - - -static int math_abs (lua_State *L) { - if (lua_isinteger(L, 1)) { - lua_Integer n = lua_tointeger(L, 1); - if (n < 0) n = (lua_Integer)(0u - (lua_Unsigned)n); - lua_pushinteger(L, n); - } - else - lua_pushnumber(L, l_mathop(fabs)(luaL_checknumber(L, 1))); - return 1; -} - -static int math_sin (lua_State *L) { - lua_pushnumber(L, l_mathop(sin)(luaL_checknumber(L, 1))); - return 1; -} - -static int math_cos (lua_State *L) { - lua_pushnumber(L, l_mathop(cos)(luaL_checknumber(L, 1))); - return 1; -} - -static int math_tan (lua_State *L) { - lua_pushnumber(L, l_mathop(tan)(luaL_checknumber(L, 1))); - return 1; -} - -static int math_asin (lua_State *L) { - lua_pushnumber(L, l_mathop(asin)(luaL_checknumber(L, 1))); - return 1; -} - -static int math_acos (lua_State *L) { - lua_pushnumber(L, l_mathop(acos)(luaL_checknumber(L, 1))); - return 1; -} - -static int math_atan (lua_State *L) { - lua_Number y = luaL_checknumber(L, 1); - lua_Number x = luaL_optnumber(L, 2, 1); - lua_pushnumber(L, l_mathop(atan2)(y, x)); - return 1; -} - - -static int math_toint (lua_State *L) { - int valid; - lua_Integer n = lua_tointegerx(L, 1, &valid); - if (l_likely(valid)) - lua_pushinteger(L, n); - else { - luaL_checkany(L, 1); - luaL_pushfail(L); /* value is not convertible to integer */ - } - return 1; -} - - -static void pushnumint (lua_State *L, lua_Number d) { - lua_Integer n; - if (lua_numbertointeger(d, &n)) /* does 'd' fit in an integer? */ - lua_pushinteger(L, n); /* result is integer */ - else - lua_pushnumber(L, d); /* result is float */ -} - - -static int math_floor (lua_State *L) { - if (lua_isinteger(L, 1)) - lua_settop(L, 1); /* integer is its own floor */ - else { - lua_Number d = l_mathop(floor)(luaL_checknumber(L, 1)); - pushnumint(L, d); - } - return 1; -} - - -static int math_ceil (lua_State *L) { - if (lua_isinteger(L, 1)) - lua_settop(L, 1); /* integer is its own ceil */ - else { - lua_Number d = l_mathop(ceil)(luaL_checknumber(L, 1)); - pushnumint(L, d); - } - return 1; -} - - -static int math_fmod (lua_State *L) { - if (lua_isinteger(L, 1) && lua_isinteger(L, 2)) { - lua_Integer d = lua_tointeger(L, 2); - if ((lua_Unsigned)d + 1u <= 1u) { /* special cases: -1 or 0 */ - luaL_argcheck(L, d != 0, 2, "zero"); - lua_pushinteger(L, 0); /* avoid overflow with 0x80000... / -1 */ - } - else - lua_pushinteger(L, lua_tointeger(L, 1) % d); - } - else - lua_pushnumber(L, l_mathop(fmod)(luaL_checknumber(L, 1), - luaL_checknumber(L, 2))); - return 1; -} - - -/* -** next function does not use 'modf', avoiding problems with 'double*' -** (which is not compatible with 'float*') when lua_Number is not -** 'double'. -*/ -static int math_modf (lua_State *L) { - if (lua_isinteger(L ,1)) { - lua_settop(L, 1); /* number is its own integer part */ - lua_pushnumber(L, 0); /* no fractional part */ - } - else { - lua_Number n = luaL_checknumber(L, 1); - /* integer part (rounds toward zero) */ - lua_Number ip = (n < 0) ? l_mathop(ceil)(n) : l_mathop(floor)(n); - pushnumint(L, ip); - /* fractional part (test needed for inf/-inf) */ - lua_pushnumber(L, (n == ip) ? l_mathop(0.0) : (n - ip)); - } - return 2; -} - - -static int math_sqrt (lua_State *L) { - lua_pushnumber(L, l_mathop(sqrt)(luaL_checknumber(L, 1))); - return 1; -} - - -static int math_ult (lua_State *L) { - lua_Integer a = luaL_checkinteger(L, 1); - lua_Integer b = luaL_checkinteger(L, 2); - lua_pushboolean(L, (lua_Unsigned)a < (lua_Unsigned)b); - return 1; -} - -static int math_log (lua_State *L) { - lua_Number x = luaL_checknumber(L, 1); - lua_Number res; - if (lua_isnoneornil(L, 2)) - res = l_mathop(log)(x); - else { - lua_Number base = luaL_checknumber(L, 2); -#if !defined(LUA_USE_C89) - if (base == l_mathop(2.0)) - res = l_mathop(log2)(x); - else -#endif - if (base == l_mathop(10.0)) - res = l_mathop(log10)(x); - else - res = l_mathop(log)(x)/l_mathop(log)(base); - } - lua_pushnumber(L, res); - return 1; -} - -static int math_exp (lua_State *L) { - lua_pushnumber(L, l_mathop(exp)(luaL_checknumber(L, 1))); - return 1; -} - -static int math_deg (lua_State *L) { - lua_pushnumber(L, luaL_checknumber(L, 1) * (l_mathop(180.0) / PI)); - return 1; -} - -static int math_rad (lua_State *L) { - lua_pushnumber(L, luaL_checknumber(L, 1) * (PI / l_mathop(180.0))); - return 1; -} - - -static int math_min (lua_State *L) { - int n = lua_gettop(L); /* number of arguments */ - int imin = 1; /* index of current minimum value */ - int i; - luaL_argcheck(L, n >= 1, 1, "value expected"); - for (i = 2; i <= n; i++) { - if (lua_compare(L, i, imin, LUA_OPLT)) - imin = i; - } - lua_pushvalue(L, imin); - return 1; -} - - -static int math_max (lua_State *L) { - int n = lua_gettop(L); /* number of arguments */ - int imax = 1; /* index of current maximum value */ - int i; - luaL_argcheck(L, n >= 1, 1, "value expected"); - for (i = 2; i <= n; i++) { - if (lua_compare(L, imax, i, LUA_OPLT)) - imax = i; - } - lua_pushvalue(L, imax); - return 1; -} - - -static int math_type (lua_State *L) { - if (lua_type(L, 1) == LUA_TNUMBER) - lua_pushstring(L, (lua_isinteger(L, 1)) ? "integer" : "float"); - else { - luaL_checkany(L, 1); - luaL_pushfail(L); - } - return 1; -} - - - -/* -** {================================================================== -** Pseudo-Random Number Generator based on 'xoshiro256**'. -** =================================================================== -*/ - -/* number of binary digits in the mantissa of a float */ -#define FIGS l_floatatt(MANT_DIG) - -#if FIGS > 64 -/* there are only 64 random bits; use them all */ -#undef FIGS -#define FIGS 64 -#endif - - -/* -** LUA_RAND32 forces the use of 32-bit integers in the implementation -** of the PRN generator (mainly for testing). -*/ -#if !defined(LUA_RAND32) && !defined(Rand64) - -/* try to find an integer type with at least 64 bits */ - -#if ((ULONG_MAX >> 31) >> 31) >= 3 - -/* 'long' has at least 64 bits */ -#define Rand64 unsigned long - -#elif !defined(LUA_USE_C89) && defined(LLONG_MAX) - -/* there is a 'long long' type (which must have at least 64 bits) */ -#define Rand64 unsigned long long - -#elif ((LUA_MAXUNSIGNED >> 31) >> 31) >= 3 - -/* 'lua_Unsigned' has at least 64 bits */ -#define Rand64 lua_Unsigned - -#endif - -#endif - - -#if defined(Rand64) /* { */ - -/* -** Standard implementation, using 64-bit integers. -** If 'Rand64' has more than 64 bits, the extra bits do not interfere -** with the 64 initial bits, except in a right shift. Moreover, the -** final result has to discard the extra bits. -*/ - -/* avoid using extra bits when needed */ -#define trim64(x) ((x) & 0xffffffffffffffffu) - - -/* rotate left 'x' by 'n' bits */ -static Rand64 rotl (Rand64 x, int n) { - return (x << n) | (trim64(x) >> (64 - n)); -} - -static Rand64 nextrand (Rand64 *state) { - Rand64 state0 = state[0]; - Rand64 state1 = state[1]; - Rand64 state2 = state[2] ^ state0; - Rand64 state3 = state[3] ^ state1; - Rand64 res = rotl(state1 * 5, 7) * 9; - state[0] = state0 ^ state3; - state[1] = state1 ^ state2; - state[2] = state2 ^ (state1 << 17); - state[3] = rotl(state3, 45); - return res; -} - - -/* must take care to not shift stuff by more than 63 slots */ - - -/* -** Convert bits from a random integer into a float in the -** interval [0,1), getting the higher FIG bits from the -** random unsigned integer and converting that to a float. -*/ - -/* must throw out the extra (64 - FIGS) bits */ -#define shift64_FIG (64 - FIGS) - -/* to scale to [0, 1), multiply by scaleFIG = 2^(-FIGS) */ -#define scaleFIG (l_mathop(0.5) / ((Rand64)1 << (FIGS - 1))) - -static lua_Number I2d (Rand64 x) { - return (lua_Number)(trim64(x) >> shift64_FIG) * scaleFIG; -} - -/* convert a 'Rand64' to a 'lua_Unsigned' */ -#define I2UInt(x) ((lua_Unsigned)trim64(x)) - -/* convert a 'lua_Unsigned' to a 'Rand64' */ -#define Int2I(x) ((Rand64)(x)) - - -#else /* no 'Rand64' }{ */ - -/* get an integer with at least 32 bits */ -#if LUAI_IS32INT -typedef unsigned int lu_int32; -#else -typedef unsigned long lu_int32; -#endif - - -/* -** Use two 32-bit integers to represent a 64-bit quantity. -*/ -typedef struct Rand64 { - lu_int32 h; /* higher half */ - lu_int32 l; /* lower half */ -} Rand64; - - -/* -** If 'lu_int32' has more than 32 bits, the extra bits do not interfere -** with the 32 initial bits, except in a right shift and comparisons. -** Moreover, the final result has to discard the extra bits. -*/ - -/* avoid using extra bits when needed */ -#define trim32(x) ((x) & 0xffffffffu) - - -/* -** basic operations on 'Rand64' values -*/ - -/* build a new Rand64 value */ -static Rand64 packI (lu_int32 h, lu_int32 l) { - Rand64 result; - result.h = h; - result.l = l; - return result; -} - -/* return i << n */ -static Rand64 Ishl (Rand64 i, int n) { - lua_assert(n > 0 && n < 32); - return packI((i.h << n) | (trim32(i.l) >> (32 - n)), i.l << n); -} - -/* i1 ^= i2 */ -static void Ixor (Rand64 *i1, Rand64 i2) { - i1->h ^= i2.h; - i1->l ^= i2.l; -} - -/* return i1 + i2 */ -static Rand64 Iadd (Rand64 i1, Rand64 i2) { - Rand64 result = packI(i1.h + i2.h, i1.l + i2.l); - if (trim32(result.l) < trim32(i1.l)) /* carry? */ - result.h++; - return result; -} - -/* return i * 5 */ -static Rand64 times5 (Rand64 i) { - return Iadd(Ishl(i, 2), i); /* i * 5 == (i << 2) + i */ -} - -/* return i * 9 */ -static Rand64 times9 (Rand64 i) { - return Iadd(Ishl(i, 3), i); /* i * 9 == (i << 3) + i */ -} - -/* return 'i' rotated left 'n' bits */ -static Rand64 rotl (Rand64 i, int n) { - lua_assert(n > 0 && n < 32); - return packI((i.h << n) | (trim32(i.l) >> (32 - n)), - (trim32(i.h) >> (32 - n)) | (i.l << n)); -} - -/* for offsets larger than 32, rotate right by 64 - offset */ -static Rand64 rotl1 (Rand64 i, int n) { - lua_assert(n > 32 && n < 64); - n = 64 - n; - return packI((trim32(i.h) >> n) | (i.l << (32 - n)), - (i.h << (32 - n)) | (trim32(i.l) >> n)); -} - -/* -** implementation of 'xoshiro256**' algorithm on 'Rand64' values -*/ -static Rand64 nextrand (Rand64 *state) { - Rand64 res = times9(rotl(times5(state[1]), 7)); - Rand64 t = Ishl(state[1], 17); - Ixor(&state[2], state[0]); - Ixor(&state[3], state[1]); - Ixor(&state[1], state[2]); - Ixor(&state[0], state[3]); - Ixor(&state[2], t); - state[3] = rotl1(state[3], 45); - return res; -} - - -/* -** Converts a 'Rand64' into a float. -*/ - -/* an unsigned 1 with proper type */ -#define UONE ((lu_int32)1) - - -#if FIGS <= 32 - -/* 2^(-FIGS) */ -#define scaleFIG (l_mathop(0.5) / (UONE << (FIGS - 1))) - -/* -** get up to 32 bits from higher half, shifting right to -** throw out the extra bits. -*/ -static lua_Number I2d (Rand64 x) { - lua_Number h = (lua_Number)(trim32(x.h) >> (32 - FIGS)); - return h * scaleFIG; -} - -#else /* 32 < FIGS <= 64 */ - -/* must take care to not shift stuff by more than 31 slots */ - -/* 2^(-FIGS) = 1.0 / 2^30 / 2^3 / 2^(FIGS-33) */ -#define scaleFIG \ - (l_mathop(1.0) / (UONE << 30) / l_mathop(8.0) / (UONE << (FIGS - 33))) - -/* -** use FIGS - 32 bits from lower half, throwing out the other -** (32 - (FIGS - 32)) = (64 - FIGS) bits -*/ -#define shiftLOW (64 - FIGS) - -/* -** higher 32 bits go after those (FIGS - 32) bits: shiftHI = 2^(FIGS - 32) -*/ -#define shiftHI ((lua_Number)(UONE << (FIGS - 33)) * l_mathop(2.0)) - - -static lua_Number I2d (Rand64 x) { - lua_Number h = (lua_Number)trim32(x.h) * shiftHI; - lua_Number l = (lua_Number)(trim32(x.l) >> shiftLOW); - return (h + l) * scaleFIG; -} - -#endif - - -/* convert a 'Rand64' to a 'lua_Unsigned' */ -static lua_Unsigned I2UInt (Rand64 x) { - return (((lua_Unsigned)trim32(x.h) << 31) << 1) | (lua_Unsigned)trim32(x.l); -} - -/* convert a 'lua_Unsigned' to a 'Rand64' */ -static Rand64 Int2I (lua_Unsigned n) { - return packI((lu_int32)((n >> 31) >> 1), (lu_int32)n); -} - -#endif /* } */ - - -/* -** A state uses four 'Rand64' values. -*/ -typedef struct { - Rand64 s[4]; -} RanState; - - -/* -** Project the random integer 'ran' into the interval [0, n]. -** Because 'ran' has 2^B possible values, the projection can only be -** uniform when the size of the interval is a power of 2 (exact -** division). Otherwise, to get a uniform projection into [0, n], we -** first compute 'lim', the smallest Mersenne number not smaller than -** 'n'. We then project 'ran' into the interval [0, lim]. If the result -** is inside [0, n], we are done. Otherwise, we try with another 'ran', -** until we have a result inside the interval. -*/ -static lua_Unsigned project (lua_Unsigned ran, lua_Unsigned n, - RanState *state) { - if ((n & (n + 1)) == 0) /* is 'n + 1' a power of 2? */ - return ran & n; /* no bias */ - else { - lua_Unsigned lim = n; - /* compute the smallest (2^b - 1) not smaller than 'n' */ - lim |= (lim >> 1); - lim |= (lim >> 2); - lim |= (lim >> 4); - lim |= (lim >> 8); - lim |= (lim >> 16); -#if (LUA_MAXUNSIGNED >> 31) >= 3 - lim |= (lim >> 32); /* integer type has more than 32 bits */ -#endif - lua_assert((lim & (lim + 1)) == 0 /* 'lim + 1' is a power of 2, */ - && lim >= n /* not smaller than 'n', */ - && (lim >> 1) < n); /* and it is the smallest one */ - while ((ran &= lim) > n) /* project 'ran' into [0..lim] */ - ran = I2UInt(nextrand(state->s)); /* not inside [0..n]? try again */ - return ran; - } -} - - -static int math_random (lua_State *L) { - lua_Integer low, up; - lua_Unsigned p; - RanState *state = (RanState *)lua_touserdata(L, lua_upvalueindex(1)); - Rand64 rv = nextrand(state->s); /* next pseudo-random value */ - switch (lua_gettop(L)) { /* check number of arguments */ - case 0: { /* no arguments */ - lua_pushnumber(L, I2d(rv)); /* float between 0 and 1 */ - return 1; - } - case 1: { /* only upper limit */ - low = 1; - up = luaL_checkinteger(L, 1); - if (up == 0) { /* single 0 as argument? */ - lua_pushinteger(L, I2UInt(rv)); /* full random integer */ - return 1; - } - break; - } - case 2: { /* lower and upper limits */ - low = luaL_checkinteger(L, 1); - up = luaL_checkinteger(L, 2); - break; - } - default: return luaL_error(L, "wrong number of arguments"); - } - /* random integer in the interval [low, up] */ - luaL_argcheck(L, low <= up, 1, "interval is empty"); - /* project random integer into the interval [0, up - low] */ - p = project(I2UInt(rv), (lua_Unsigned)up - (lua_Unsigned)low, state); - lua_pushinteger(L, p + (lua_Unsigned)low); - return 1; -} - - -static void setseed (lua_State *L, Rand64 *state, - lua_Unsigned n1, lua_Unsigned n2) { - int i; - state[0] = Int2I(n1); - state[1] = Int2I(0xff); /* avoid a zero state */ - state[2] = Int2I(n2); - state[3] = Int2I(0); - for (i = 0; i < 16; i++) - nextrand(state); /* discard initial values to "spread" seed */ - lua_pushinteger(L, n1); - lua_pushinteger(L, n2); -} - - -/* -** Set a "random" seed. To get some randomness, use the current time -** and the address of 'L' (in case the machine does address space layout -** randomization). -*/ -static void randseed (lua_State *L, RanState *state) { - lua_Unsigned seed1 = (lua_Unsigned)time(NULL); - lua_Unsigned seed2 = (lua_Unsigned)(size_t)L; - setseed(L, state->s, seed1, seed2); -} - - -static int math_randomseed (lua_State *L) { - RanState *state = (RanState *)lua_touserdata(L, lua_upvalueindex(1)); - if (lua_isnone(L, 1)) { - randseed(L, state); - } - else { - lua_Integer n1 = luaL_checkinteger(L, 1); - lua_Integer n2 = luaL_optinteger(L, 2, 0); - setseed(L, state->s, n1, n2); - } - return 2; /* return seeds */ -} - - -static const luaL_Reg randfuncs[] = { - {"random", math_random}, - {"randomseed", math_randomseed}, - {NULL, NULL} -}; - - -/* -** Register the random functions and initialize their state. -*/ -static void setrandfunc (lua_State *L) { - RanState *state = (RanState *)lua_newuserdatauv(L, sizeof(RanState), 0); - randseed(L, state); /* initialize with a "random" seed */ - lua_pop(L, 2); /* remove pushed seeds */ - luaL_setfuncs(L, randfuncs, 1); -} - -/* }================================================================== */ - - -/* -** {================================================================== -** Deprecated functions (for compatibility only) -** =================================================================== -*/ -#if defined(LUA_COMPAT_MATHLIB) - -static int math_cosh (lua_State *L) { - lua_pushnumber(L, l_mathop(cosh)(luaL_checknumber(L, 1))); - return 1; -} - -static int math_sinh (lua_State *L) { - lua_pushnumber(L, l_mathop(sinh)(luaL_checknumber(L, 1))); - return 1; -} - -static int math_tanh (lua_State *L) { - lua_pushnumber(L, l_mathop(tanh)(luaL_checknumber(L, 1))); - return 1; -} - -static int math_pow (lua_State *L) { - lua_Number x = luaL_checknumber(L, 1); - lua_Number y = luaL_checknumber(L, 2); - lua_pushnumber(L, l_mathop(pow)(x, y)); - return 1; -} - -static int math_frexp (lua_State *L) { - int e; - lua_pushnumber(L, l_mathop(frexp)(luaL_checknumber(L, 1), &e)); - lua_pushinteger(L, e); - return 2; -} - -static int math_ldexp (lua_State *L) { - lua_Number x = luaL_checknumber(L, 1); - int ep = (int)luaL_checkinteger(L, 2); - lua_pushnumber(L, l_mathop(ldexp)(x, ep)); - return 1; -} - -static int math_log10 (lua_State *L) { - lua_pushnumber(L, l_mathop(log10)(luaL_checknumber(L, 1))); - return 1; -} - -#endif -/* }================================================================== */ - - - -static const luaL_Reg mathlib[] = { - {"abs", math_abs}, - {"acos", math_acos}, - {"asin", math_asin}, - {"atan", math_atan}, - {"ceil", math_ceil}, - {"cos", math_cos}, - {"deg", math_deg}, - {"exp", math_exp}, - {"tointeger", math_toint}, - {"floor", math_floor}, - {"fmod", math_fmod}, - {"ult", math_ult}, - {"log", math_log}, - {"max", math_max}, - {"min", math_min}, - {"modf", math_modf}, - {"rad", math_rad}, - {"sin", math_sin}, - {"sqrt", math_sqrt}, - {"tan", math_tan}, - {"type", math_type}, -#if defined(LUA_COMPAT_MATHLIB) - {"atan2", math_atan}, - {"cosh", math_cosh}, - {"sinh", math_sinh}, - {"tanh", math_tanh}, - {"pow", math_pow}, - {"frexp", math_frexp}, - {"ldexp", math_ldexp}, - {"log10", math_log10}, -#endif - /* placeholders */ - {"random", NULL}, - {"randomseed", NULL}, - {"pi", NULL}, - {"huge", NULL}, - {"maxinteger", NULL}, - {"mininteger", NULL}, - {NULL, NULL} -}; - - -/* -** Open math library -*/ -LUAMOD_API int luaopen_math (lua_State *L) { - luaL_newlib(L, mathlib); - lua_pushnumber(L, PI); - lua_setfield(L, -2, "pi"); - lua_pushnumber(L, (lua_Number)HUGE_VAL); - lua_setfield(L, -2, "huge"); - lua_pushinteger(L, LUA_MAXINTEGER); - lua_setfield(L, -2, "maxinteger"); - lua_pushinteger(L, LUA_MININTEGER); - lua_setfield(L, -2, "mininteger"); - setrandfunc(L); - return 1; -} - diff --git a/lib/lua-5.4/src/lmem.c b/lib/lua-5.4/src/lmem.c deleted file mode 100644 index 9800a86..0000000 --- a/lib/lua-5.4/src/lmem.c +++ /dev/null @@ -1,215 +0,0 @@ -/* -** $Id: lmem.c $ -** Interface to Memory Manager -** See Copyright Notice in lua.h -*/ - -#define lmem_c -#define LUA_CORE - -#include "lprefix.h" - - -#include - -#include "lua.h" - -#include "ldebug.h" -#include "ldo.h" -#include "lgc.h" -#include "lmem.h" -#include "lobject.h" -#include "lstate.h" - - - -/* -** About the realloc function: -** void *frealloc (void *ud, void *ptr, size_t osize, size_t nsize); -** ('osize' is the old size, 'nsize' is the new size) -** -** - frealloc(ud, p, x, 0) frees the block 'p' and returns NULL. -** Particularly, frealloc(ud, NULL, 0, 0) does nothing, -** which is equivalent to free(NULL) in ISO C. -** -** - frealloc(ud, NULL, x, s) creates a new block of size 's' -** (no matter 'x'). Returns NULL if it cannot create the new block. -** -** - otherwise, frealloc(ud, b, x, y) reallocates the block 'b' from -** size 'x' to size 'y'. Returns NULL if it cannot reallocate the -** block to the new size. -*/ - - -/* -** Macro to call the allocation function. -*/ -#define callfrealloc(g,block,os,ns) ((*g->frealloc)(g->ud, block, os, ns)) - - -/* -** When an allocation fails, it will try again after an emergency -** collection, except when it cannot run a collection. The GC should -** not be called while the state is not fully built, as the collector -** is not yet fully initialized. Also, it should not be called when -** 'gcstopem' is true, because then the interpreter is in the middle of -** a collection step. -*/ -#define cantryagain(g) (completestate(g) && !g->gcstopem) - - - - -#if defined(EMERGENCYGCTESTS) -/* -** First allocation will fail except when freeing a block (frees never -** fail) and when it cannot try again; this fail will trigger 'tryagain' -** and a full GC cycle at every allocation. -*/ -static void *firsttry (global_State *g, void *block, size_t os, size_t ns) { - if (ns > 0 && cantryagain(g)) - return NULL; /* fail */ - else /* normal allocation */ - return callfrealloc(g, block, os, ns); -} -#else -#define firsttry(g,block,os,ns) callfrealloc(g, block, os, ns) -#endif - - - - - -/* -** {================================================================== -** Functions to allocate/deallocate arrays for the Parser -** =================================================================== -*/ - -/* -** Minimum size for arrays during parsing, to avoid overhead of -** reallocating to size 1, then 2, and then 4. All these arrays -** will be reallocated to exact sizes or erased when parsing ends. -*/ -#define MINSIZEARRAY 4 - - -void *luaM_growaux_ (lua_State *L, void *block, int nelems, int *psize, - int size_elems, int limit, const char *what) { - void *newblock; - int size = *psize; - if (nelems + 1 <= size) /* does one extra element still fit? */ - return block; /* nothing to be done */ - if (size >= limit / 2) { /* cannot double it? */ - if (l_unlikely(size >= limit)) /* cannot grow even a little? */ - luaG_runerror(L, "too many %s (limit is %d)", what, limit); - size = limit; /* still have at least one free place */ - } - else { - size *= 2; - if (size < MINSIZEARRAY) - size = MINSIZEARRAY; /* minimum size */ - } - lua_assert(nelems + 1 <= size && size <= limit); - /* 'limit' ensures that multiplication will not overflow */ - newblock = luaM_saferealloc_(L, block, cast_sizet(*psize) * size_elems, - cast_sizet(size) * size_elems); - *psize = size; /* update only when everything else is OK */ - return newblock; -} - - -/* -** In prototypes, the size of the array is also its number of -** elements (to save memory). So, if it cannot shrink an array -** to its number of elements, the only option is to raise an -** error. -*/ -void *luaM_shrinkvector_ (lua_State *L, void *block, int *size, - int final_n, int size_elem) { - void *newblock; - size_t oldsize = cast_sizet((*size) * size_elem); - size_t newsize = cast_sizet(final_n * size_elem); - lua_assert(newsize <= oldsize); - newblock = luaM_saferealloc_(L, block, oldsize, newsize); - *size = final_n; - return newblock; -} - -/* }================================================================== */ - - -l_noret luaM_toobig (lua_State *L) { - luaG_runerror(L, "memory allocation error: block too big"); -} - - -/* -** Free memory -*/ -void luaM_free_ (lua_State *L, void *block, size_t osize) { - global_State *g = G(L); - lua_assert((osize == 0) == (block == NULL)); - callfrealloc(g, block, osize, 0); - g->GCdebt -= osize; -} - - -/* -** In case of allocation fail, this function will do an emergency -** collection to free some memory and then try the allocation again. -*/ -static void *tryagain (lua_State *L, void *block, - size_t osize, size_t nsize) { - global_State *g = G(L); - if (cantryagain(g)) { - luaC_fullgc(L, 1); /* try to free some memory... */ - return callfrealloc(g, block, osize, nsize); /* try again */ - } - else return NULL; /* cannot run an emergency collection */ -} - - -/* -** Generic allocation routine. -*/ -void *luaM_realloc_ (lua_State *L, void *block, size_t osize, size_t nsize) { - void *newblock; - global_State *g = G(L); - lua_assert((osize == 0) == (block == NULL)); - newblock = firsttry(g, block, osize, nsize); - if (l_unlikely(newblock == NULL && nsize > 0)) { - newblock = tryagain(L, block, osize, nsize); - if (newblock == NULL) /* still no memory? */ - return NULL; /* do not update 'GCdebt' */ - } - lua_assert((nsize == 0) == (newblock == NULL)); - g->GCdebt = (g->GCdebt + nsize) - osize; - return newblock; -} - - -void *luaM_saferealloc_ (lua_State *L, void *block, size_t osize, - size_t nsize) { - void *newblock = luaM_realloc_(L, block, osize, nsize); - if (l_unlikely(newblock == NULL && nsize > 0)) /* allocation failed? */ - luaM_error(L); - return newblock; -} - - -void *luaM_malloc_ (lua_State *L, size_t size, int tag) { - if (size == 0) - return NULL; /* that's all */ - else { - global_State *g = G(L); - void *newblock = firsttry(g, NULL, tag, size); - if (l_unlikely(newblock == NULL)) { - newblock = tryagain(L, NULL, tag, size); - if (newblock == NULL) - luaM_error(L); - } - g->GCdebt += size; - return newblock; - } -} diff --git a/lib/lua-5.4/src/lmem.h b/lib/lua-5.4/src/lmem.h deleted file mode 100644 index 8c75a44..0000000 --- a/lib/lua-5.4/src/lmem.h +++ /dev/null @@ -1,93 +0,0 @@ -/* -** $Id: lmem.h $ -** Interface to Memory Manager -** See Copyright Notice in lua.h -*/ - -#ifndef lmem_h -#define lmem_h - - -#include - -#include "llimits.h" -#include "lua.h" - - -#define luaM_error(L) luaD_throw(L, LUA_ERRMEM) - - -/* -** This macro tests whether it is safe to multiply 'n' by the size of -** type 't' without overflows. Because 'e' is always constant, it avoids -** the runtime division MAX_SIZET/(e). -** (The macro is somewhat complex to avoid warnings: The 'sizeof' -** comparison avoids a runtime comparison when overflow cannot occur. -** The compiler should be able to optimize the real test by itself, but -** when it does it, it may give a warning about "comparison is always -** false due to limited range of data type"; the +1 tricks the compiler, -** avoiding this warning but also this optimization.) -*/ -#define luaM_testsize(n,e) \ - (sizeof(n) >= sizeof(size_t) && cast_sizet((n)) + 1 > MAX_SIZET/(e)) - -#define luaM_checksize(L,n,e) \ - (luaM_testsize(n,e) ? luaM_toobig(L) : cast_void(0)) - - -/* -** Computes the minimum between 'n' and 'MAX_SIZET/sizeof(t)', so that -** the result is not larger than 'n' and cannot overflow a 'size_t' -** when multiplied by the size of type 't'. (Assumes that 'n' is an -** 'int' or 'unsigned int' and that 'int' is not larger than 'size_t'.) -*/ -#define luaM_limitN(n,t) \ - ((cast_sizet(n) <= MAX_SIZET/sizeof(t)) ? (n) : \ - cast_uint((MAX_SIZET/sizeof(t)))) - - -/* -** Arrays of chars do not need any test -*/ -#define luaM_reallocvchar(L,b,on,n) \ - cast_charp(luaM_saferealloc_(L, (b), (on)*sizeof(char), (n)*sizeof(char))) - -#define luaM_freemem(L, b, s) luaM_free_(L, (b), (s)) -#define luaM_free(L, b) luaM_free_(L, (b), sizeof(*(b))) -#define luaM_freearray(L, b, n) luaM_free_(L, (b), (n)*sizeof(*(b))) - -#define luaM_new(L,t) cast(t*, luaM_malloc_(L, sizeof(t), 0)) -#define luaM_newvector(L,n,t) cast(t*, luaM_malloc_(L, (n)*sizeof(t), 0)) -#define luaM_newvectorchecked(L,n,t) \ - (luaM_checksize(L,n,sizeof(t)), luaM_newvector(L,n,t)) - -#define luaM_newobject(L,tag,s) luaM_malloc_(L, (s), tag) - -#define luaM_growvector(L,v,nelems,size,t,limit,e) \ - ((v)=cast(t *, luaM_growaux_(L,v,nelems,&(size),sizeof(t), \ - luaM_limitN(limit,t),e))) - -#define luaM_reallocvector(L, v,oldn,n,t) \ - (cast(t *, luaM_realloc_(L, v, cast_sizet(oldn) * sizeof(t), \ - cast_sizet(n) * sizeof(t)))) - -#define luaM_shrinkvector(L,v,size,fs,t) \ - ((v)=cast(t *, luaM_shrinkvector_(L, v, &(size), fs, sizeof(t)))) - -LUAI_FUNC l_noret luaM_toobig (lua_State *L); - -/* not to be called directly */ -LUAI_FUNC void *luaM_realloc_ (lua_State *L, void *block, size_t oldsize, - size_t size); -LUAI_FUNC void *luaM_saferealloc_ (lua_State *L, void *block, size_t oldsize, - size_t size); -LUAI_FUNC void luaM_free_ (lua_State *L, void *block, size_t osize); -LUAI_FUNC void *luaM_growaux_ (lua_State *L, void *block, int nelems, - int *size, int size_elem, int limit, - const char *what); -LUAI_FUNC void *luaM_shrinkvector_ (lua_State *L, void *block, int *nelem, - int final_n, int size_elem); -LUAI_FUNC void *luaM_malloc_ (lua_State *L, size_t size, int tag); - -#endif - diff --git a/lib/lua-5.4/src/loadlib.c b/lib/lua-5.4/src/loadlib.c deleted file mode 100644 index d792dff..0000000 --- a/lib/lua-5.4/src/loadlib.c +++ /dev/null @@ -1,767 +0,0 @@ -/* -** $Id: loadlib.c $ -** Dynamic library loader for Lua -** See Copyright Notice in lua.h -** -** This module contains an implementation of loadlib for Unix systems -** that have dlfcn, an implementation for Windows, and a stub for other -** systems. -*/ - -#define loadlib_c -#define LUA_LIB - -#include "lprefix.h" - - -#include -#include -#include - -#include "lua.h" - -#include "lauxlib.h" -#include "lualib.h" - - -/* -** LUA_IGMARK is a mark to ignore all before it when building the -** luaopen_ function name. -*/ -#if !defined (LUA_IGMARK) -#define LUA_IGMARK "-" -#endif - - -/* -** LUA_CSUBSEP is the character that replaces dots in submodule names -** when searching for a C loader. -** LUA_LSUBSEP is the character that replaces dots in submodule names -** when searching for a Lua loader. -*/ -#if !defined(LUA_CSUBSEP) -#define LUA_CSUBSEP LUA_DIRSEP -#endif - -#if !defined(LUA_LSUBSEP) -#define LUA_LSUBSEP LUA_DIRSEP -#endif - - -/* prefix for open functions in C libraries */ -#define LUA_POF "luaopen_" - -/* separator for open functions in C libraries */ -#define LUA_OFSEP "_" - - -/* -** key for table in the registry that keeps handles -** for all loaded C libraries -*/ -static const char *const CLIBS = "_CLIBS"; - -#define LIB_FAIL "open" - - -#define setprogdir(L) ((void)0) - - -/* -** Special type equivalent to '(void*)' for functions in gcc -** (to suppress warnings when converting function pointers) -*/ -typedef void (*voidf)(void); - - -/* -** system-dependent functions -*/ - -/* -** unload library 'lib' -*/ -static void lsys_unloadlib (void *lib); - -/* -** load C library in file 'path'. If 'seeglb', load with all names in -** the library global. -** Returns the library; in case of error, returns NULL plus an -** error string in the stack. -*/ -static void *lsys_load (lua_State *L, const char *path, int seeglb); - -/* -** Try to find a function named 'sym' in library 'lib'. -** Returns the function; in case of error, returns NULL plus an -** error string in the stack. -*/ -static lua_CFunction lsys_sym (lua_State *L, void *lib, const char *sym); - - - - -#if defined(LUA_USE_DLOPEN) /* { */ -/* -** {======================================================================== -** This is an implementation of loadlib based on the dlfcn interface. -** The dlfcn interface is available in Linux, SunOS, Solaris, IRIX, FreeBSD, -** NetBSD, AIX 4.2, HPUX 11, and probably most other Unix flavors, at least -** as an emulation layer on top of native functions. -** ========================================================================= -*/ - -#include - -/* -** Macro to convert pointer-to-void* to pointer-to-function. This cast -** is undefined according to ISO C, but POSIX assumes that it works. -** (The '__extension__' in gnu compilers is only to avoid warnings.) -*/ -#if defined(__GNUC__) -#define cast_func(p) (__extension__ (lua_CFunction)(p)) -#else -#define cast_func(p) ((lua_CFunction)(p)) -#endif - - -static void lsys_unloadlib (void *lib) { - dlclose(lib); -} - - -static void *lsys_load (lua_State *L, const char *path, int seeglb) { - void *lib = dlopen(path, RTLD_NOW | (seeglb ? RTLD_GLOBAL : RTLD_LOCAL)); - if (l_unlikely(lib == NULL)) - lua_pushstring(L, dlerror()); - return lib; -} - - -static lua_CFunction lsys_sym (lua_State *L, void *lib, const char *sym) { - lua_CFunction f = cast_func(dlsym(lib, sym)); - if (l_unlikely(f == NULL)) - lua_pushstring(L, dlerror()); - return f; -} - -/* }====================================================== */ - - - -#elif defined(LUA_DL_DLL) /* }{ */ -/* -** {====================================================================== -** This is an implementation of loadlib for Windows using native functions. -** ======================================================================= -*/ - -#include - - -/* -** optional flags for LoadLibraryEx -*/ -#if !defined(LUA_LLE_FLAGS) -#define LUA_LLE_FLAGS 0 -#endif - - -#undef setprogdir - - -/* -** Replace in the path (on the top of the stack) any occurrence -** of LUA_EXEC_DIR with the executable's path. -*/ -static void setprogdir (lua_State *L) { - char buff[MAX_PATH + 1]; - char *lb; - DWORD nsize = sizeof(buff)/sizeof(char); - DWORD n = GetModuleFileNameA(NULL, buff, nsize); /* get exec. name */ - if (n == 0 || n == nsize || (lb = strrchr(buff, '\\')) == NULL) - luaL_error(L, "unable to get ModuleFileName"); - else { - *lb = '\0'; /* cut name on the last '\\' to get the path */ - luaL_gsub(L, lua_tostring(L, -1), LUA_EXEC_DIR, buff); - lua_remove(L, -2); /* remove original string */ - } -} - - - - -static void pusherror (lua_State *L) { - int error = GetLastError(); - char buffer[128]; - if (FormatMessageA(FORMAT_MESSAGE_IGNORE_INSERTS | FORMAT_MESSAGE_FROM_SYSTEM, - NULL, error, 0, buffer, sizeof(buffer)/sizeof(char), NULL)) - lua_pushstring(L, buffer); - else - lua_pushfstring(L, "system error %d\n", error); -} - -static void lsys_unloadlib (void *lib) { - FreeLibrary((HMODULE)lib); -} - - -static void *lsys_load (lua_State *L, const char *path, int seeglb) { - HMODULE lib = LoadLibraryExA(path, NULL, LUA_LLE_FLAGS); - (void)(seeglb); /* not used: symbols are 'global' by default */ - if (lib == NULL) pusherror(L); - return lib; -} - - -static lua_CFunction lsys_sym (lua_State *L, void *lib, const char *sym) { - lua_CFunction f = (lua_CFunction)(voidf)GetProcAddress((HMODULE)lib, sym); - if (f == NULL) pusherror(L); - return f; -} - -/* }====================================================== */ - - -#else /* }{ */ -/* -** {====================================================== -** Fallback for other systems -** ======================================================= -*/ - -#undef LIB_FAIL -#define LIB_FAIL "absent" - - -#define DLMSG "dynamic libraries not enabled; check your Lua installation" - - -static void lsys_unloadlib (void *lib) { - (void)(lib); /* not used */ -} - - -static void *lsys_load (lua_State *L, const char *path, int seeglb) { - (void)(path); (void)(seeglb); /* not used */ - lua_pushliteral(L, DLMSG); - return NULL; -} - - -static lua_CFunction lsys_sym (lua_State *L, void *lib, const char *sym) { - (void)(lib); (void)(sym); /* not used */ - lua_pushliteral(L, DLMSG); - return NULL; -} - -/* }====================================================== */ -#endif /* } */ - - -/* -** {================================================================== -** Set Paths -** =================================================================== -*/ - -/* -** LUA_PATH_VAR and LUA_CPATH_VAR are the names of the environment -** variables that Lua check to set its paths. -*/ -#if !defined(LUA_PATH_VAR) -#define LUA_PATH_VAR "LUA_PATH" -#endif - -#if !defined(LUA_CPATH_VAR) -#define LUA_CPATH_VAR "LUA_CPATH" -#endif - - - -/* -** return registry.LUA_NOENV as a boolean -*/ -static int noenv (lua_State *L) { - int b; - lua_getfield(L, LUA_REGISTRYINDEX, "LUA_NOENV"); - b = lua_toboolean(L, -1); - lua_pop(L, 1); /* remove value */ - return b; -} - - -/* -** Set a path -*/ -static void setpath (lua_State *L, const char *fieldname, - const char *envname, - const char *dft) { - const char *dftmark; - const char *nver = lua_pushfstring(L, "%s%s", envname, LUA_VERSUFFIX); - const char *path = getenv(nver); /* try versioned name */ - if (path == NULL) /* no versioned environment variable? */ - path = getenv(envname); /* try unversioned name */ - if (path == NULL || noenv(L)) /* no environment variable? */ - lua_pushstring(L, dft); /* use default */ - else if ((dftmark = strstr(path, LUA_PATH_SEP LUA_PATH_SEP)) == NULL) - lua_pushstring(L, path); /* nothing to change */ - else { /* path contains a ";;": insert default path in its place */ - size_t len = strlen(path); - luaL_Buffer b; - luaL_buffinit(L, &b); - if (path < dftmark) { /* is there a prefix before ';;'? */ - luaL_addlstring(&b, path, dftmark - path); /* add it */ - luaL_addchar(&b, *LUA_PATH_SEP); - } - luaL_addstring(&b, dft); /* add default */ - if (dftmark < path + len - 2) { /* is there a suffix after ';;'? */ - luaL_addchar(&b, *LUA_PATH_SEP); - luaL_addlstring(&b, dftmark + 2, (path + len - 2) - dftmark); - } - luaL_pushresult(&b); - } - setprogdir(L); - lua_setfield(L, -3, fieldname); /* package[fieldname] = path value */ - lua_pop(L, 1); /* pop versioned variable name ('nver') */ -} - -/* }================================================================== */ - - -/* -** return registry.CLIBS[path] -*/ -static void *checkclib (lua_State *L, const char *path) { - void *plib; - lua_getfield(L, LUA_REGISTRYINDEX, CLIBS); - lua_getfield(L, -1, path); - plib = lua_touserdata(L, -1); /* plib = CLIBS[path] */ - lua_pop(L, 2); /* pop CLIBS table and 'plib' */ - return plib; -} - - -/* -** registry.CLIBS[path] = plib -- for queries -** registry.CLIBS[#CLIBS + 1] = plib -- also keep a list of all libraries -*/ -static void addtoclib (lua_State *L, const char *path, void *plib) { - lua_getfield(L, LUA_REGISTRYINDEX, CLIBS); - lua_pushlightuserdata(L, plib); - lua_pushvalue(L, -1); - lua_setfield(L, -3, path); /* CLIBS[path] = plib */ - lua_rawseti(L, -2, luaL_len(L, -2) + 1); /* CLIBS[#CLIBS + 1] = plib */ - lua_pop(L, 1); /* pop CLIBS table */ -} - - -/* -** __gc tag method for CLIBS table: calls 'lsys_unloadlib' for all lib -** handles in list CLIBS -*/ -static int gctm (lua_State *L) { - lua_Integer n = luaL_len(L, 1); - for (; n >= 1; n--) { /* for each handle, in reverse order */ - lua_rawgeti(L, 1, n); /* get handle CLIBS[n] */ - lsys_unloadlib(lua_touserdata(L, -1)); - lua_pop(L, 1); /* pop handle */ - } - return 0; -} - - - -/* error codes for 'lookforfunc' */ -#define ERRLIB 1 -#define ERRFUNC 2 - -/* -** Look for a C function named 'sym' in a dynamically loaded library -** 'path'. -** First, check whether the library is already loaded; if not, try -** to load it. -** Then, if 'sym' is '*', return true (as library has been loaded). -** Otherwise, look for symbol 'sym' in the library and push a -** C function with that symbol. -** Return 0 and 'true' or a function in the stack; in case of -** errors, return an error code and an error message in the stack. -*/ -static int lookforfunc (lua_State *L, const char *path, const char *sym) { - void *reg = checkclib(L, path); /* check loaded C libraries */ - if (reg == NULL) { /* must load library? */ - reg = lsys_load(L, path, *sym == '*'); /* global symbols if 'sym'=='*' */ - if (reg == NULL) return ERRLIB; /* unable to load library */ - addtoclib(L, path, reg); - } - if (*sym == '*') { /* loading only library (no function)? */ - lua_pushboolean(L, 1); /* return 'true' */ - return 0; /* no errors */ - } - else { - lua_CFunction f = lsys_sym(L, reg, sym); - if (f == NULL) - return ERRFUNC; /* unable to find function */ - lua_pushcfunction(L, f); /* else create new function */ - return 0; /* no errors */ - } -} - - -static int ll_loadlib (lua_State *L) { - const char *path = luaL_checkstring(L, 1); - const char *init = luaL_checkstring(L, 2); - int stat = lookforfunc(L, path, init); - if (l_likely(stat == 0)) /* no errors? */ - return 1; /* return the loaded function */ - else { /* error; error message is on stack top */ - luaL_pushfail(L); - lua_insert(L, -2); - lua_pushstring(L, (stat == ERRLIB) ? LIB_FAIL : "init"); - return 3; /* return fail, error message, and where */ - } -} - - - -/* -** {====================================================== -** 'require' function -** ======================================================= -*/ - - -static int readable (const char *filename) { - FILE *f = fopen(filename, "r"); /* try to open file */ - if (f == NULL) return 0; /* open failed */ - fclose(f); - return 1; -} - - -/* -** Get the next name in '*path' = 'name1;name2;name3;...', changing -** the ending ';' to '\0' to create a zero-terminated string. Return -** NULL when list ends. -*/ -static const char *getnextfilename (char **path, char *end) { - char *sep; - char *name = *path; - if (name == end) - return NULL; /* no more names */ - else if (*name == '\0') { /* from previous iteration? */ - *name = *LUA_PATH_SEP; /* restore separator */ - name++; /* skip it */ - } - sep = strchr(name, *LUA_PATH_SEP); /* find next separator */ - if (sep == NULL) /* separator not found? */ - sep = end; /* name goes until the end */ - *sep = '\0'; /* finish file name */ - *path = sep; /* will start next search from here */ - return name; -} - - -/* -** Given a path such as ";blabla.so;blublu.so", pushes the string -** -** no file 'blabla.so' -** no file 'blublu.so' -*/ -static void pusherrornotfound (lua_State *L, const char *path) { - luaL_Buffer b; - luaL_buffinit(L, &b); - luaL_addstring(&b, "no file '"); - luaL_addgsub(&b, path, LUA_PATH_SEP, "'\n\tno file '"); - luaL_addstring(&b, "'"); - luaL_pushresult(&b); -} - - -static const char *searchpath (lua_State *L, const char *name, - const char *path, - const char *sep, - const char *dirsep) { - luaL_Buffer buff; - char *pathname; /* path with name inserted */ - char *endpathname; /* its end */ - const char *filename; - /* separator is non-empty and appears in 'name'? */ - if (*sep != '\0' && strchr(name, *sep) != NULL) - name = luaL_gsub(L, name, sep, dirsep); /* replace it by 'dirsep' */ - luaL_buffinit(L, &buff); - /* add path to the buffer, replacing marks ('?') with the file name */ - luaL_addgsub(&buff, path, LUA_PATH_MARK, name); - luaL_addchar(&buff, '\0'); - pathname = luaL_buffaddr(&buff); /* writable list of file names */ - endpathname = pathname + luaL_bufflen(&buff) - 1; - while ((filename = getnextfilename(&pathname, endpathname)) != NULL) { - if (readable(filename)) /* does file exist and is readable? */ - return lua_pushstring(L, filename); /* save and return name */ - } - luaL_pushresult(&buff); /* push path to create error message */ - pusherrornotfound(L, lua_tostring(L, -1)); /* create error message */ - return NULL; /* not found */ -} - - -static int ll_searchpath (lua_State *L) { - const char *f = searchpath(L, luaL_checkstring(L, 1), - luaL_checkstring(L, 2), - luaL_optstring(L, 3, "."), - luaL_optstring(L, 4, LUA_DIRSEP)); - if (f != NULL) return 1; - else { /* error message is on top of the stack */ - luaL_pushfail(L); - lua_insert(L, -2); - return 2; /* return fail + error message */ - } -} - - -static const char *findfile (lua_State *L, const char *name, - const char *pname, - const char *dirsep) { - const char *path; - lua_getfield(L, lua_upvalueindex(1), pname); - path = lua_tostring(L, -1); - if (l_unlikely(path == NULL)) - luaL_error(L, "'package.%s' must be a string", pname); - return searchpath(L, name, path, ".", dirsep); -} - - -static int checkload (lua_State *L, int stat, const char *filename) { - if (l_likely(stat)) { /* module loaded successfully? */ - lua_pushstring(L, filename); /* will be 2nd argument to module */ - return 2; /* return open function and file name */ - } - else - return luaL_error(L, "error loading module '%s' from file '%s':\n\t%s", - lua_tostring(L, 1), filename, lua_tostring(L, -1)); -} - - -static int searcher_Lua (lua_State *L) { - const char *filename; - const char *name = luaL_checkstring(L, 1); - filename = findfile(L, name, "path", LUA_LSUBSEP); - if (filename == NULL) return 1; /* module not found in this path */ - return checkload(L, (luaL_loadfile(L, filename) == LUA_OK), filename); -} - - -/* -** Try to find a load function for module 'modname' at file 'filename'. -** First, change '.' to '_' in 'modname'; then, if 'modname' has -** the form X-Y (that is, it has an "ignore mark"), build a function -** name "luaopen_X" and look for it. (For compatibility, if that -** fails, it also tries "luaopen_Y".) If there is no ignore mark, -** look for a function named "luaopen_modname". -*/ -static int loadfunc (lua_State *L, const char *filename, const char *modname) { - const char *openfunc; - const char *mark; - modname = luaL_gsub(L, modname, ".", LUA_OFSEP); - mark = strchr(modname, *LUA_IGMARK); - if (mark) { - int stat; - openfunc = lua_pushlstring(L, modname, mark - modname); - openfunc = lua_pushfstring(L, LUA_POF"%s", openfunc); - stat = lookforfunc(L, filename, openfunc); - if (stat != ERRFUNC) return stat; - modname = mark + 1; /* else go ahead and try old-style name */ - } - openfunc = lua_pushfstring(L, LUA_POF"%s", modname); - return lookforfunc(L, filename, openfunc); -} - - -static int searcher_C (lua_State *L) { - const char *name = luaL_checkstring(L, 1); - const char *filename = findfile(L, name, "cpath", LUA_CSUBSEP); - if (filename == NULL) return 1; /* module not found in this path */ - return checkload(L, (loadfunc(L, filename, name) == 0), filename); -} - - -static int searcher_Croot (lua_State *L) { - const char *filename; - const char *name = luaL_checkstring(L, 1); - const char *p = strchr(name, '.'); - int stat; - if (p == NULL) return 0; /* is root */ - lua_pushlstring(L, name, p - name); - filename = findfile(L, lua_tostring(L, -1), "cpath", LUA_CSUBSEP); - if (filename == NULL) return 1; /* root not found */ - if ((stat = loadfunc(L, filename, name)) != 0) { - if (stat != ERRFUNC) - return checkload(L, 0, filename); /* real error */ - else { /* open function not found */ - lua_pushfstring(L, "no module '%s' in file '%s'", name, filename); - return 1; - } - } - lua_pushstring(L, filename); /* will be 2nd argument to module */ - return 2; -} - - -static int searcher_preload (lua_State *L) { - const char *name = luaL_checkstring(L, 1); - lua_getfield(L, LUA_REGISTRYINDEX, LUA_PRELOAD_TABLE); - if (lua_getfield(L, -1, name) == LUA_TNIL) { /* not found? */ - lua_pushfstring(L, "no field package.preload['%s']", name); - return 1; - } - else { - lua_pushliteral(L, ":preload:"); - return 2; - } -} - - -static void findloader (lua_State *L, const char *name) { - int i; - luaL_Buffer msg; /* to build error message */ - /* push 'package.searchers' to index 3 in the stack */ - if (l_unlikely(lua_getfield(L, lua_upvalueindex(1), "searchers") - != LUA_TTABLE)) - luaL_error(L, "'package.searchers' must be a table"); - luaL_buffinit(L, &msg); - /* iterate over available searchers to find a loader */ - for (i = 1; ; i++) { - luaL_addstring(&msg, "\n\t"); /* error-message prefix */ - if (l_unlikely(lua_rawgeti(L, 3, i) == LUA_TNIL)) { /* no more searchers? */ - lua_pop(L, 1); /* remove nil */ - luaL_buffsub(&msg, 2); /* remove prefix */ - luaL_pushresult(&msg); /* create error message */ - luaL_error(L, "module '%s' not found:%s", name, lua_tostring(L, -1)); - } - lua_pushstring(L, name); - lua_call(L, 1, 2); /* call it */ - if (lua_isfunction(L, -2)) /* did it find a loader? */ - return; /* module loader found */ - else if (lua_isstring(L, -2)) { /* searcher returned error message? */ - lua_pop(L, 1); /* remove extra return */ - luaL_addvalue(&msg); /* concatenate error message */ - } - else { /* no error message */ - lua_pop(L, 2); /* remove both returns */ - luaL_buffsub(&msg, 2); /* remove prefix */ - } - } -} - - -static int ll_require (lua_State *L) { - const char *name = luaL_checkstring(L, 1); - lua_settop(L, 1); /* LOADED table will be at index 2 */ - lua_getfield(L, LUA_REGISTRYINDEX, LUA_LOADED_TABLE); - lua_getfield(L, 2, name); /* LOADED[name] */ - if (lua_toboolean(L, -1)) /* is it there? */ - return 1; /* package is already loaded */ - /* else must load package */ - lua_pop(L, 1); /* remove 'getfield' result */ - findloader(L, name); - lua_rotate(L, -2, 1); /* function <-> loader data */ - lua_pushvalue(L, 1); /* name is 1st argument to module loader */ - lua_pushvalue(L, -3); /* loader data is 2nd argument */ - /* stack: ...; loader data; loader function; mod. name; loader data */ - lua_call(L, 2, 1); /* run loader to load module */ - /* stack: ...; loader data; result from loader */ - if (!lua_isnil(L, -1)) /* non-nil return? */ - lua_setfield(L, 2, name); /* LOADED[name] = returned value */ - else - lua_pop(L, 1); /* pop nil */ - if (lua_getfield(L, 2, name) == LUA_TNIL) { /* module set no value? */ - lua_pushboolean(L, 1); /* use true as result */ - lua_copy(L, -1, -2); /* replace loader result */ - lua_setfield(L, 2, name); /* LOADED[name] = true */ - } - lua_rotate(L, -2, 1); /* loader data <-> module result */ - return 2; /* return module result and loader data */ -} - -/* }====================================================== */ - - - - -static const luaL_Reg pk_funcs[] = { - {"loadlib", ll_loadlib}, - {"searchpath", ll_searchpath}, - /* placeholders */ - {"preload", NULL}, - {"cpath", NULL}, - {"path", NULL}, - {"searchers", NULL}, - {"loaded", NULL}, - {NULL, NULL} -}; - - -static const luaL_Reg ll_funcs[] = { - {"require", ll_require}, - {NULL, NULL} -}; - - -static void createsearcherstable (lua_State *L) { - static const lua_CFunction searchers[] = { - searcher_preload, - searcher_Lua, - searcher_C, - searcher_Croot, - NULL - }; - int i; - /* create 'searchers' table */ - lua_createtable(L, sizeof(searchers)/sizeof(searchers[0]) - 1, 0); - /* fill it with predefined searchers */ - for (i=0; searchers[i] != NULL; i++) { - lua_pushvalue(L, -2); /* set 'package' as upvalue for all searchers */ - lua_pushcclosure(L, searchers[i], 1); - lua_rawseti(L, -2, i+1); - } - lua_setfield(L, -2, "searchers"); /* put it in field 'searchers' */ -} - - -/* -** create table CLIBS to keep track of loaded C libraries, -** setting a finalizer to close all libraries when closing state. -*/ -static void createclibstable (lua_State *L) { - luaL_getsubtable(L, LUA_REGISTRYINDEX, CLIBS); /* create CLIBS table */ - lua_createtable(L, 0, 1); /* create metatable for CLIBS */ - lua_pushcfunction(L, gctm); - lua_setfield(L, -2, "__gc"); /* set finalizer for CLIBS table */ - lua_setmetatable(L, -2); -} - - -LUAMOD_API int luaopen_package (lua_State *L) { - createclibstable(L); - luaL_newlib(L, pk_funcs); /* create 'package' table */ - createsearcherstable(L); - /* set paths */ - setpath(L, "path", LUA_PATH_VAR, LUA_PATH_DEFAULT); - setpath(L, "cpath", LUA_CPATH_VAR, LUA_CPATH_DEFAULT); - /* store config information */ - lua_pushliteral(L, LUA_DIRSEP "\n" LUA_PATH_SEP "\n" LUA_PATH_MARK "\n" - LUA_EXEC_DIR "\n" LUA_IGMARK "\n"); - lua_setfield(L, -2, "config"); - /* set field 'loaded' */ - luaL_getsubtable(L, LUA_REGISTRYINDEX, LUA_LOADED_TABLE); - lua_setfield(L, -2, "loaded"); - /* set field 'preload' */ - luaL_getsubtable(L, LUA_REGISTRYINDEX, LUA_PRELOAD_TABLE); - lua_setfield(L, -2, "preload"); - lua_pushglobaltable(L); - lua_pushvalue(L, -2); /* set 'package' as upvalue for next lib */ - luaL_setfuncs(L, ll_funcs, 1); /* open lib into global table */ - lua_pop(L, 1); /* pop global table */ - return 1; /* return 'package' table */ -} - diff --git a/lib/lua-5.4/src/lobject.c b/lib/lua-5.4/src/lobject.c deleted file mode 100644 index f73ffc6..0000000 --- a/lib/lua-5.4/src/lobject.c +++ /dev/null @@ -1,602 +0,0 @@ -/* -** $Id: lobject.c $ -** Some generic functions over Lua objects -** See Copyright Notice in lua.h -*/ - -#define lobject_c -#define LUA_CORE - -#include "lprefix.h" - - -#include -#include -#include -#include -#include -#include - -#include "lua.h" - -#include "lctype.h" -#include "ldebug.h" -#include "ldo.h" -#include "lmem.h" -#include "lobject.h" -#include "lstate.h" -#include "lstring.h" -#include "lvm.h" - - -/* -** Computes ceil(log2(x)) -*/ -int luaO_ceillog2 (unsigned int x) { - static const lu_byte log_2[256] = { /* log_2[i] = ceil(log2(i - 1)) */ - 0,1,2,2,3,3,3,3,4,4,4,4,4,4,4,4,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5, - 6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6, - 7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7, - 7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7, - 8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8, - 8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8, - 8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8, - 8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8 - }; - int l = 0; - x--; - while (x >= 256) { l += 8; x >>= 8; } - return l + log_2[x]; -} - - -static lua_Integer intarith (lua_State *L, int op, lua_Integer v1, - lua_Integer v2) { - switch (op) { - case LUA_OPADD: return intop(+, v1, v2); - case LUA_OPSUB:return intop(-, v1, v2); - case LUA_OPMUL:return intop(*, v1, v2); - case LUA_OPMOD: return luaV_mod(L, v1, v2); - case LUA_OPIDIV: return luaV_idiv(L, v1, v2); - case LUA_OPBAND: return intop(&, v1, v2); - case LUA_OPBOR: return intop(|, v1, v2); - case LUA_OPBXOR: return intop(^, v1, v2); - case LUA_OPSHL: return luaV_shiftl(v1, v2); - case LUA_OPSHR: return luaV_shiftr(v1, v2); - case LUA_OPUNM: return intop(-, 0, v1); - case LUA_OPBNOT: return intop(^, ~l_castS2U(0), v1); - default: lua_assert(0); return 0; - } -} - - -static lua_Number numarith (lua_State *L, int op, lua_Number v1, - lua_Number v2) { - switch (op) { - case LUA_OPADD: return luai_numadd(L, v1, v2); - case LUA_OPSUB: return luai_numsub(L, v1, v2); - case LUA_OPMUL: return luai_nummul(L, v1, v2); - case LUA_OPDIV: return luai_numdiv(L, v1, v2); - case LUA_OPPOW: return luai_numpow(L, v1, v2); - case LUA_OPIDIV: return luai_numidiv(L, v1, v2); - case LUA_OPUNM: return luai_numunm(L, v1); - case LUA_OPMOD: return luaV_modf(L, v1, v2); - default: lua_assert(0); return 0; - } -} - - -int luaO_rawarith (lua_State *L, int op, const TValue *p1, const TValue *p2, - TValue *res) { - switch (op) { - case LUA_OPBAND: case LUA_OPBOR: case LUA_OPBXOR: - case LUA_OPSHL: case LUA_OPSHR: - case LUA_OPBNOT: { /* operate only on integers */ - lua_Integer i1; lua_Integer i2; - if (tointegerns(p1, &i1) && tointegerns(p2, &i2)) { - setivalue(res, intarith(L, op, i1, i2)); - return 1; - } - else return 0; /* fail */ - } - case LUA_OPDIV: case LUA_OPPOW: { /* operate only on floats */ - lua_Number n1; lua_Number n2; - if (tonumberns(p1, n1) && tonumberns(p2, n2)) { - setfltvalue(res, numarith(L, op, n1, n2)); - return 1; - } - else return 0; /* fail */ - } - default: { /* other operations */ - lua_Number n1; lua_Number n2; - if (ttisinteger(p1) && ttisinteger(p2)) { - setivalue(res, intarith(L, op, ivalue(p1), ivalue(p2))); - return 1; - } - else if (tonumberns(p1, n1) && tonumberns(p2, n2)) { - setfltvalue(res, numarith(L, op, n1, n2)); - return 1; - } - else return 0; /* fail */ - } - } -} - - -void luaO_arith (lua_State *L, int op, const TValue *p1, const TValue *p2, - StkId res) { - if (!luaO_rawarith(L, op, p1, p2, s2v(res))) { - /* could not perform raw operation; try metamethod */ - luaT_trybinTM(L, p1, p2, res, cast(TMS, (op - LUA_OPADD) + TM_ADD)); - } -} - - -int luaO_hexavalue (int c) { - if (lisdigit(c)) return c - '0'; - else return (ltolower(c) - 'a') + 10; -} - - -static int isneg (const char **s) { - if (**s == '-') { (*s)++; return 1; } - else if (**s == '+') (*s)++; - return 0; -} - - - -/* -** {================================================================== -** Lua's implementation for 'lua_strx2number' -** =================================================================== -*/ - -#if !defined(lua_strx2number) - -/* maximum number of significant digits to read (to avoid overflows - even with single floats) */ -#define MAXSIGDIG 30 - -/* -** convert a hexadecimal numeric string to a number, following -** C99 specification for 'strtod' -*/ -static lua_Number lua_strx2number (const char *s, char **endptr) { - int dot = lua_getlocaledecpoint(); - lua_Number r = l_mathop(0.0); /* result (accumulator) */ - int sigdig = 0; /* number of significant digits */ - int nosigdig = 0; /* number of non-significant digits */ - int e = 0; /* exponent correction */ - int neg; /* 1 if number is negative */ - int hasdot = 0; /* true after seen a dot */ - *endptr = cast_charp(s); /* nothing is valid yet */ - while (lisspace(cast_uchar(*s))) s++; /* skip initial spaces */ - neg = isneg(&s); /* check sign */ - if (!(*s == '0' && (*(s + 1) == 'x' || *(s + 1) == 'X'))) /* check '0x' */ - return l_mathop(0.0); /* invalid format (no '0x') */ - for (s += 2; ; s++) { /* skip '0x' and read numeral */ - if (*s == dot) { - if (hasdot) break; /* second dot? stop loop */ - else hasdot = 1; - } - else if (lisxdigit(cast_uchar(*s))) { - if (sigdig == 0 && *s == '0') /* non-significant digit (zero)? */ - nosigdig++; - else if (++sigdig <= MAXSIGDIG) /* can read it without overflow? */ - r = (r * l_mathop(16.0)) + luaO_hexavalue(*s); - else e++; /* too many digits; ignore, but still count for exponent */ - if (hasdot) e--; /* decimal digit? correct exponent */ - } - else break; /* neither a dot nor a digit */ - } - if (nosigdig + sigdig == 0) /* no digits? */ - return l_mathop(0.0); /* invalid format */ - *endptr = cast_charp(s); /* valid up to here */ - e *= 4; /* each digit multiplies/divides value by 2^4 */ - if (*s == 'p' || *s == 'P') { /* exponent part? */ - int exp1 = 0; /* exponent value */ - int neg1; /* exponent sign */ - s++; /* skip 'p' */ - neg1 = isneg(&s); /* sign */ - if (!lisdigit(cast_uchar(*s))) - return l_mathop(0.0); /* invalid; must have at least one digit */ - while (lisdigit(cast_uchar(*s))) /* read exponent */ - exp1 = exp1 * 10 + *(s++) - '0'; - if (neg1) exp1 = -exp1; - e += exp1; - *endptr = cast_charp(s); /* valid up to here */ - } - if (neg) r = -r; - return l_mathop(ldexp)(r, e); -} - -#endif -/* }====================================================== */ - - -/* maximum length of a numeral to be converted to a number */ -#if !defined (L_MAXLENNUM) -#define L_MAXLENNUM 200 -#endif - -/* -** Convert string 's' to a Lua number (put in 'result'). Return NULL on -** fail or the address of the ending '\0' on success. ('mode' == 'x') -** means a hexadecimal numeral. -*/ -static const char *l_str2dloc (const char *s, lua_Number *result, int mode) { - char *endptr; - *result = (mode == 'x') ? lua_strx2number(s, &endptr) /* try to convert */ - : lua_str2number(s, &endptr); - if (endptr == s) return NULL; /* nothing recognized? */ - while (lisspace(cast_uchar(*endptr))) endptr++; /* skip trailing spaces */ - return (*endptr == '\0') ? endptr : NULL; /* OK iff no trailing chars */ -} - - -/* -** Convert string 's' to a Lua number (put in 'result') handling the -** current locale. -** This function accepts both the current locale or a dot as the radix -** mark. If the conversion fails, it may mean number has a dot but -** locale accepts something else. In that case, the code copies 's' -** to a buffer (because 's' is read-only), changes the dot to the -** current locale radix mark, and tries to convert again. -** The variable 'mode' checks for special characters in the string: -** - 'n' means 'inf' or 'nan' (which should be rejected) -** - 'x' means a hexadecimal numeral -** - '.' just optimizes the search for the common case (no special chars) -*/ -static const char *l_str2d (const char *s, lua_Number *result) { - const char *endptr; - const char *pmode = strpbrk(s, ".xXnN"); /* look for special chars */ - int mode = pmode ? ltolower(cast_uchar(*pmode)) : 0; - if (mode == 'n') /* reject 'inf' and 'nan' */ - return NULL; - endptr = l_str2dloc(s, result, mode); /* try to convert */ - if (endptr == NULL) { /* failed? may be a different locale */ - char buff[L_MAXLENNUM + 1]; - const char *pdot = strchr(s, '.'); - if (pdot == NULL || strlen(s) > L_MAXLENNUM) - return NULL; /* string too long or no dot; fail */ - strcpy(buff, s); /* copy string to buffer */ - buff[pdot - s] = lua_getlocaledecpoint(); /* correct decimal point */ - endptr = l_str2dloc(buff, result, mode); /* try again */ - if (endptr != NULL) - endptr = s + (endptr - buff); /* make relative to 's' */ - } - return endptr; -} - - -#define MAXBY10 cast(lua_Unsigned, LUA_MAXINTEGER / 10) -#define MAXLASTD cast_int(LUA_MAXINTEGER % 10) - -static const char *l_str2int (const char *s, lua_Integer *result) { - lua_Unsigned a = 0; - int empty = 1; - int neg; - while (lisspace(cast_uchar(*s))) s++; /* skip initial spaces */ - neg = isneg(&s); - if (s[0] == '0' && - (s[1] == 'x' || s[1] == 'X')) { /* hex? */ - s += 2; /* skip '0x' */ - for (; lisxdigit(cast_uchar(*s)); s++) { - a = a * 16 + luaO_hexavalue(*s); - empty = 0; - } - } - else { /* decimal */ - for (; lisdigit(cast_uchar(*s)); s++) { - int d = *s - '0'; - if (a >= MAXBY10 && (a > MAXBY10 || d > MAXLASTD + neg)) /* overflow? */ - return NULL; /* do not accept it (as integer) */ - a = a * 10 + d; - empty = 0; - } - } - while (lisspace(cast_uchar(*s))) s++; /* skip trailing spaces */ - if (empty || *s != '\0') return NULL; /* something wrong in the numeral */ - else { - *result = l_castU2S((neg) ? 0u - a : a); - return s; - } -} - - -size_t luaO_str2num (const char *s, TValue *o) { - lua_Integer i; lua_Number n; - const char *e; - if ((e = l_str2int(s, &i)) != NULL) { /* try as an integer */ - setivalue(o, i); - } - else if ((e = l_str2d(s, &n)) != NULL) { /* else try as a float */ - setfltvalue(o, n); - } - else - return 0; /* conversion failed */ - return (e - s) + 1; /* success; return string size */ -} - - -int luaO_utf8esc (char *buff, unsigned long x) { - int n = 1; /* number of bytes put in buffer (backwards) */ - lua_assert(x <= 0x7FFFFFFFu); - if (x < 0x80) /* ascii? */ - buff[UTF8BUFFSZ - 1] = cast_char(x); - else { /* need continuation bytes */ - unsigned int mfb = 0x3f; /* maximum that fits in first byte */ - do { /* add continuation bytes */ - buff[UTF8BUFFSZ - (n++)] = cast_char(0x80 | (x & 0x3f)); - x >>= 6; /* remove added bits */ - mfb >>= 1; /* now there is one less bit available in first byte */ - } while (x > mfb); /* still needs continuation byte? */ - buff[UTF8BUFFSZ - n] = cast_char((~mfb << 1) | x); /* add first byte */ - } - return n; -} - - -/* -** Maximum length of the conversion of a number to a string. Must be -** enough to accommodate both LUA_INTEGER_FMT and LUA_NUMBER_FMT. -** (For a long long int, this is 19 digits plus a sign and a final '\0', -** adding to 21. For a long double, it can go to a sign, 33 digits, -** the dot, an exponent letter, an exponent sign, 5 exponent digits, -** and a final '\0', adding to 43.) -*/ -#define MAXNUMBER2STR 44 - - -/* -** Convert a number object to a string, adding it to a buffer -*/ -static int tostringbuff (TValue *obj, char *buff) { - int len; - lua_assert(ttisnumber(obj)); - if (ttisinteger(obj)) - len = lua_integer2str(buff, MAXNUMBER2STR, ivalue(obj)); - else { - len = lua_number2str(buff, MAXNUMBER2STR, fltvalue(obj)); - if (buff[strspn(buff, "-0123456789")] == '\0') { /* looks like an int? */ - buff[len++] = lua_getlocaledecpoint(); - buff[len++] = '0'; /* adds '.0' to result */ - } - } - return len; -} - - -/* -** Convert a number object to a Lua string, replacing the value at 'obj' -*/ -void luaO_tostring (lua_State *L, TValue *obj) { - char buff[MAXNUMBER2STR]; - int len = tostringbuff(obj, buff); - setsvalue(L, obj, luaS_newlstr(L, buff, len)); -} - - - - -/* -** {================================================================== -** 'luaO_pushvfstring' -** =================================================================== -*/ - -/* -** Size for buffer space used by 'luaO_pushvfstring'. It should be -** (LUA_IDSIZE + MAXNUMBER2STR) + a minimal space for basic messages, -** so that 'luaG_addinfo' can work directly on the buffer. -*/ -#define BUFVFS (LUA_IDSIZE + MAXNUMBER2STR + 95) - -/* buffer used by 'luaO_pushvfstring' */ -typedef struct BuffFS { - lua_State *L; - int pushed; /* true if there is a part of the result on the stack */ - int blen; /* length of partial string in 'space' */ - char space[BUFVFS]; /* holds last part of the result */ -} BuffFS; - - -/* -** Push given string to the stack, as part of the result, and -** join it to previous partial result if there is one. -** It may call 'luaV_concat' while using one slot from EXTRA_STACK. -** This call cannot invoke metamethods, as both operands must be -** strings. It can, however, raise an error if the result is too -** long. In that case, 'luaV_concat' frees the extra slot before -** raising the error. -*/ -static void pushstr (BuffFS *buff, const char *str, size_t lstr) { - lua_State *L = buff->L; - setsvalue2s(L, L->top.p, luaS_newlstr(L, str, lstr)); - L->top.p++; /* may use one slot from EXTRA_STACK */ - if (!buff->pushed) /* no previous string on the stack? */ - buff->pushed = 1; /* now there is one */ - else /* join previous string with new one */ - luaV_concat(L, 2); -} - - -/* -** empty the buffer space into the stack -*/ -static void clearbuff (BuffFS *buff) { - pushstr(buff, buff->space, buff->blen); /* push buffer contents */ - buff->blen = 0; /* space now is empty */ -} - - -/* -** Get a space of size 'sz' in the buffer. If buffer has not enough -** space, empty it. 'sz' must fit in an empty buffer. -*/ -static char *getbuff (BuffFS *buff, int sz) { - lua_assert(buff->blen <= BUFVFS); lua_assert(sz <= BUFVFS); - if (sz > BUFVFS - buff->blen) /* not enough space? */ - clearbuff(buff); - return buff->space + buff->blen; -} - - -#define addsize(b,sz) ((b)->blen += (sz)) - - -/* -** Add 'str' to the buffer. If string is larger than the buffer space, -** push the string directly to the stack. -*/ -static void addstr2buff (BuffFS *buff, const char *str, size_t slen) { - if (slen <= BUFVFS) { /* does string fit into buffer? */ - char *bf = getbuff(buff, cast_int(slen)); - memcpy(bf, str, slen); /* add string to buffer */ - addsize(buff, cast_int(slen)); - } - else { /* string larger than buffer */ - clearbuff(buff); /* string comes after buffer's content */ - pushstr(buff, str, slen); /* push string */ - } -} - - -/* -** Add a numeral to the buffer. -*/ -static void addnum2buff (BuffFS *buff, TValue *num) { - char *numbuff = getbuff(buff, MAXNUMBER2STR); - int len = tostringbuff(num, numbuff); /* format number into 'numbuff' */ - addsize(buff, len); -} - - -/* -** this function handles only '%d', '%c', '%f', '%p', '%s', and '%%' - conventional formats, plus Lua-specific '%I' and '%U' -*/ -const char *luaO_pushvfstring (lua_State *L, const char *fmt, va_list argp) { - BuffFS buff; /* holds last part of the result */ - const char *e; /* points to next '%' */ - buff.pushed = buff.blen = 0; - buff.L = L; - while ((e = strchr(fmt, '%')) != NULL) { - addstr2buff(&buff, fmt, e - fmt); /* add 'fmt' up to '%' */ - switch (*(e + 1)) { /* conversion specifier */ - case 's': { /* zero-terminated string */ - const char *s = va_arg(argp, char *); - if (s == NULL) s = "(null)"; - addstr2buff(&buff, s, strlen(s)); - break; - } - case 'c': { /* an 'int' as a character */ - char c = cast_uchar(va_arg(argp, int)); - addstr2buff(&buff, &c, sizeof(char)); - break; - } - case 'd': { /* an 'int' */ - TValue num; - setivalue(&num, va_arg(argp, int)); - addnum2buff(&buff, &num); - break; - } - case 'I': { /* a 'lua_Integer' */ - TValue num; - setivalue(&num, cast(lua_Integer, va_arg(argp, l_uacInt))); - addnum2buff(&buff, &num); - break; - } - case 'f': { /* a 'lua_Number' */ - TValue num; - setfltvalue(&num, cast_num(va_arg(argp, l_uacNumber))); - addnum2buff(&buff, &num); - break; - } - case 'p': { /* a pointer */ - const int sz = 3 * sizeof(void*) + 8; /* enough space for '%p' */ - char *bf = getbuff(&buff, sz); - void *p = va_arg(argp, void *); - int len = lua_pointer2str(bf, sz, p); - addsize(&buff, len); - break; - } - case 'U': { /* a 'long' as a UTF-8 sequence */ - char bf[UTF8BUFFSZ]; - int len = luaO_utf8esc(bf, va_arg(argp, long)); - addstr2buff(&buff, bf + UTF8BUFFSZ - len, len); - break; - } - case '%': { - addstr2buff(&buff, "%", 1); - break; - } - default: { - luaG_runerror(L, "invalid option '%%%c' to 'lua_pushfstring'", - *(e + 1)); - } - } - fmt = e + 2; /* skip '%' and the specifier */ - } - addstr2buff(&buff, fmt, strlen(fmt)); /* rest of 'fmt' */ - clearbuff(&buff); /* empty buffer into the stack */ - lua_assert(buff.pushed == 1); - return svalue(s2v(L->top.p - 1)); -} - - -const char *luaO_pushfstring (lua_State *L, const char *fmt, ...) { - const char *msg; - va_list argp; - va_start(argp, fmt); - msg = luaO_pushvfstring(L, fmt, argp); - va_end(argp); - return msg; -} - -/* }================================================================== */ - - -#define RETS "..." -#define PRE "[string \"" -#define POS "\"]" - -#define addstr(a,b,l) ( memcpy(a,b,(l) * sizeof(char)), a += (l) ) - -void luaO_chunkid (char *out, const char *source, size_t srclen) { - size_t bufflen = LUA_IDSIZE; /* free space in buffer */ - if (*source == '=') { /* 'literal' source */ - if (srclen <= bufflen) /* small enough? */ - memcpy(out, source + 1, srclen * sizeof(char)); - else { /* truncate it */ - addstr(out, source + 1, bufflen - 1); - *out = '\0'; - } - } - else if (*source == '@') { /* file name */ - if (srclen <= bufflen) /* small enough? */ - memcpy(out, source + 1, srclen * sizeof(char)); - else { /* add '...' before rest of name */ - addstr(out, RETS, LL(RETS)); - bufflen -= LL(RETS); - memcpy(out, source + 1 + srclen - bufflen, bufflen * sizeof(char)); - } - } - else { /* string; format as [string "source"] */ - const char *nl = strchr(source, '\n'); /* find first new line (if any) */ - addstr(out, PRE, LL(PRE)); /* add prefix */ - bufflen -= LL(PRE RETS POS) + 1; /* save space for prefix+suffix+'\0' */ - if (srclen < bufflen && nl == NULL) { /* small one-line source? */ - addstr(out, source, srclen); /* keep it */ - } - else { - if (nl != NULL) srclen = nl - source; /* stop at first newline */ - if (srclen > bufflen) srclen = bufflen; - addstr(out, source, srclen); - addstr(out, RETS, LL(RETS)); - } - memcpy(out, POS, (LL(POS) + 1) * sizeof(char)); - } -} - diff --git a/lib/lua-5.4/src/lobject.h b/lib/lua-5.4/src/lobject.h deleted file mode 100644 index 556608e..0000000 --- a/lib/lua-5.4/src/lobject.h +++ /dev/null @@ -1,815 +0,0 @@ -/* -** $Id: lobject.h $ -** Type definitions for Lua objects -** See Copyright Notice in lua.h -*/ - - -#ifndef lobject_h -#define lobject_h - - -#include - - -#include "llimits.h" -#include "lua.h" - - -/* -** Extra types for collectable non-values -*/ -#define LUA_TUPVAL LUA_NUMTYPES /* upvalues */ -#define LUA_TPROTO (LUA_NUMTYPES+1) /* function prototypes */ -#define LUA_TDEADKEY (LUA_NUMTYPES+2) /* removed keys in tables */ - - - -/* -** number of all possible types (including LUA_TNONE but excluding DEADKEY) -*/ -#define LUA_TOTALTYPES (LUA_TPROTO + 2) - - -/* -** tags for Tagged Values have the following use of bits: -** bits 0-3: actual tag (a LUA_T* constant) -** bits 4-5: variant bits -** bit 6: whether value is collectable -*/ - -/* add variant bits to a type */ -#define makevariant(t,v) ((t) | ((v) << 4)) - - - -/* -** Union of all Lua values -*/ -typedef union Value { - struct GCObject *gc; /* collectable objects */ - void *p; /* light userdata */ - lua_CFunction f; /* light C functions */ - lua_Integer i; /* integer numbers */ - lua_Number n; /* float numbers */ - /* not used, but may avoid warnings for uninitialized value */ - lu_byte ub; -} Value; - - -/* -** Tagged Values. This is the basic representation of values in Lua: -** an actual value plus a tag with its type. -*/ - -#define TValuefields Value value_; lu_byte tt_ - -typedef struct TValue { - TValuefields; -} TValue; - - -#define val_(o) ((o)->value_) -#define valraw(o) (val_(o)) - - -/* raw type tag of a TValue */ -#define rawtt(o) ((o)->tt_) - -/* tag with no variants (bits 0-3) */ -#define novariant(t) ((t) & 0x0F) - -/* type tag of a TValue (bits 0-3 for tags + variant bits 4-5) */ -#define withvariant(t) ((t) & 0x3F) -#define ttypetag(o) withvariant(rawtt(o)) - -/* type of a TValue */ -#define ttype(o) (novariant(rawtt(o))) - - -/* Macros to test type */ -#define checktag(o,t) (rawtt(o) == (t)) -#define checktype(o,t) (ttype(o) == (t)) - - -/* Macros for internal tests */ - -/* collectable object has the same tag as the original value */ -#define righttt(obj) (ttypetag(obj) == gcvalue(obj)->tt) - -/* -** Any value being manipulated by the program either is non -** collectable, or the collectable object has the right tag -** and it is not dead. The option 'L == NULL' allows other -** macros using this one to be used where L is not available. -*/ -#define checkliveness(L,obj) \ - ((void)L, lua_longassert(!iscollectable(obj) || \ - (righttt(obj) && (L == NULL || !isdead(G(L),gcvalue(obj)))))) - - -/* Macros to set values */ - -/* set a value's tag */ -#define settt_(o,t) ((o)->tt_=(t)) - - -/* main macro to copy values (from 'obj2' to 'obj1') */ -#define setobj(L,obj1,obj2) \ - { TValue *io1=(obj1); const TValue *io2=(obj2); \ - io1->value_ = io2->value_; settt_(io1, io2->tt_); \ - checkliveness(L,io1); lua_assert(!isnonstrictnil(io1)); } - -/* -** Different types of assignments, according to source and destination. -** (They are mostly equal now, but may be different in the future.) -*/ - -/* from stack to stack */ -#define setobjs2s(L,o1,o2) setobj(L,s2v(o1),s2v(o2)) -/* to stack (not from same stack) */ -#define setobj2s(L,o1,o2) setobj(L,s2v(o1),o2) -/* from table to same table */ -#define setobjt2t setobj -/* to new object */ -#define setobj2n setobj -/* to table */ -#define setobj2t setobj - - -/* -** Entries in a Lua stack. Field 'tbclist' forms a list of all -** to-be-closed variables active in this stack. Dummy entries are -** used when the distance between two tbc variables does not fit -** in an unsigned short. They are represented by delta==0, and -** their real delta is always the maximum value that fits in -** that field. -*/ -typedef union StackValue { - TValue val; - struct { - TValuefields; - unsigned short delta; - } tbclist; -} StackValue; - - -/* index to stack elements */ -typedef StackValue *StkId; - - -/* -** When reallocating the stack, change all pointers to the stack into -** proper offsets. -*/ -typedef union { - StkId p; /* actual pointer */ - ptrdiff_t offset; /* used while the stack is being reallocated */ -} StkIdRel; - - -/* convert a 'StackValue' to a 'TValue' */ -#define s2v(o) (&(o)->val) - - - -/* -** {================================================================== -** Nil -** =================================================================== -*/ - -/* Standard nil */ -#define LUA_VNIL makevariant(LUA_TNIL, 0) - -/* Empty slot (which might be different from a slot containing nil) */ -#define LUA_VEMPTY makevariant(LUA_TNIL, 1) - -/* Value returned for a key not found in a table (absent key) */ -#define LUA_VABSTKEY makevariant(LUA_TNIL, 2) - - -/* macro to test for (any kind of) nil */ -#define ttisnil(v) checktype((v), LUA_TNIL) - - -/* macro to test for a standard nil */ -#define ttisstrictnil(o) checktag((o), LUA_VNIL) - - -#define setnilvalue(obj) settt_(obj, LUA_VNIL) - - -#define isabstkey(v) checktag((v), LUA_VABSTKEY) - - -/* -** macro to detect non-standard nils (used only in assertions) -*/ -#define isnonstrictnil(v) (ttisnil(v) && !ttisstrictnil(v)) - - -/* -** By default, entries with any kind of nil are considered empty. -** (In any definition, values associated with absent keys must also -** be accepted as empty.) -*/ -#define isempty(v) ttisnil(v) - - -/* macro defining a value corresponding to an absent key */ -#define ABSTKEYCONSTANT {NULL}, LUA_VABSTKEY - - -/* mark an entry as empty */ -#define setempty(v) settt_(v, LUA_VEMPTY) - - - -/* }================================================================== */ - - -/* -** {================================================================== -** Booleans -** =================================================================== -*/ - - -#define LUA_VFALSE makevariant(LUA_TBOOLEAN, 0) -#define LUA_VTRUE makevariant(LUA_TBOOLEAN, 1) - -#define ttisboolean(o) checktype((o), LUA_TBOOLEAN) -#define ttisfalse(o) checktag((o), LUA_VFALSE) -#define ttistrue(o) checktag((o), LUA_VTRUE) - - -#define l_isfalse(o) (ttisfalse(o) || ttisnil(o)) - - -#define setbfvalue(obj) settt_(obj, LUA_VFALSE) -#define setbtvalue(obj) settt_(obj, LUA_VTRUE) - -/* }================================================================== */ - - -/* -** {================================================================== -** Threads -** =================================================================== -*/ - -#define LUA_VTHREAD makevariant(LUA_TTHREAD, 0) - -#define ttisthread(o) checktag((o), ctb(LUA_VTHREAD)) - -#define thvalue(o) check_exp(ttisthread(o), gco2th(val_(o).gc)) - -#define setthvalue(L,obj,x) \ - { TValue *io = (obj); lua_State *x_ = (x); \ - val_(io).gc = obj2gco(x_); settt_(io, ctb(LUA_VTHREAD)); \ - checkliveness(L,io); } - -#define setthvalue2s(L,o,t) setthvalue(L,s2v(o),t) - -/* }================================================================== */ - - -/* -** {================================================================== -** Collectable Objects -** =================================================================== -*/ - -/* -** Common Header for all collectable objects (in macro form, to be -** included in other objects) -*/ -#define CommonHeader struct GCObject *next; lu_byte tt; lu_byte marked - - -/* Common type for all collectable objects */ -typedef struct GCObject { - CommonHeader; -} GCObject; - - -/* Bit mark for collectable types */ -#define BIT_ISCOLLECTABLE (1 << 6) - -#define iscollectable(o) (rawtt(o) & BIT_ISCOLLECTABLE) - -/* mark a tag as collectable */ -#define ctb(t) ((t) | BIT_ISCOLLECTABLE) - -#define gcvalue(o) check_exp(iscollectable(o), val_(o).gc) - -#define gcvalueraw(v) ((v).gc) - -#define setgcovalue(L,obj,x) \ - { TValue *io = (obj); GCObject *i_g=(x); \ - val_(io).gc = i_g; settt_(io, ctb(i_g->tt)); } - -/* }================================================================== */ - - -/* -** {================================================================== -** Numbers -** =================================================================== -*/ - -/* Variant tags for numbers */ -#define LUA_VNUMINT makevariant(LUA_TNUMBER, 0) /* integer numbers */ -#define LUA_VNUMFLT makevariant(LUA_TNUMBER, 1) /* float numbers */ - -#define ttisnumber(o) checktype((o), LUA_TNUMBER) -#define ttisfloat(o) checktag((o), LUA_VNUMFLT) -#define ttisinteger(o) checktag((o), LUA_VNUMINT) - -#define nvalue(o) check_exp(ttisnumber(o), \ - (ttisinteger(o) ? cast_num(ivalue(o)) : fltvalue(o))) -#define fltvalue(o) check_exp(ttisfloat(o), val_(o).n) -#define ivalue(o) check_exp(ttisinteger(o), val_(o).i) - -#define fltvalueraw(v) ((v).n) -#define ivalueraw(v) ((v).i) - -#define setfltvalue(obj,x) \ - { TValue *io=(obj); val_(io).n=(x); settt_(io, LUA_VNUMFLT); } - -#define chgfltvalue(obj,x) \ - { TValue *io=(obj); lua_assert(ttisfloat(io)); val_(io).n=(x); } - -#define setivalue(obj,x) \ - { TValue *io=(obj); val_(io).i=(x); settt_(io, LUA_VNUMINT); } - -#define chgivalue(obj,x) \ - { TValue *io=(obj); lua_assert(ttisinteger(io)); val_(io).i=(x); } - -/* }================================================================== */ - - -/* -** {================================================================== -** Strings -** =================================================================== -*/ - -/* Variant tags for strings */ -#define LUA_VSHRSTR makevariant(LUA_TSTRING, 0) /* short strings */ -#define LUA_VLNGSTR makevariant(LUA_TSTRING, 1) /* long strings */ - -#define ttisstring(o) checktype((o), LUA_TSTRING) -#define ttisshrstring(o) checktag((o), ctb(LUA_VSHRSTR)) -#define ttislngstring(o) checktag((o), ctb(LUA_VLNGSTR)) - -#define tsvalueraw(v) (gco2ts((v).gc)) - -#define tsvalue(o) check_exp(ttisstring(o), gco2ts(val_(o).gc)) - -#define setsvalue(L,obj,x) \ - { TValue *io = (obj); TString *x_ = (x); \ - val_(io).gc = obj2gco(x_); settt_(io, ctb(x_->tt)); \ - checkliveness(L,io); } - -/* set a string to the stack */ -#define setsvalue2s(L,o,s) setsvalue(L,s2v(o),s) - -/* set a string to a new object */ -#define setsvalue2n setsvalue - - -/* -** Header for a string value. -*/ -typedef struct TString { - CommonHeader; - lu_byte extra; /* reserved words for short strings; "has hash" for longs */ - lu_byte shrlen; /* length for short strings */ - unsigned int hash; - union { - size_t lnglen; /* length for long strings */ - struct TString *hnext; /* linked list for hash table */ - } u; - char contents[1]; -} TString; - - - -/* -** Get the actual string (array of bytes) from a 'TString'. -*/ -#define getstr(ts) ((ts)->contents) - - -/* get the actual string (array of bytes) from a Lua value */ -#define svalue(o) getstr(tsvalue(o)) - -/* get string length from 'TString *s' */ -#define tsslen(s) ((s)->tt == LUA_VSHRSTR ? (s)->shrlen : (s)->u.lnglen) - -/* get string length from 'TValue *o' */ -#define vslen(o) tsslen(tsvalue(o)) - -/* }================================================================== */ - - -/* -** {================================================================== -** Userdata -** =================================================================== -*/ - - -/* -** Light userdata should be a variant of userdata, but for compatibility -** reasons they are also different types. -*/ -#define LUA_VLIGHTUSERDATA makevariant(LUA_TLIGHTUSERDATA, 0) - -#define LUA_VUSERDATA makevariant(LUA_TUSERDATA, 0) - -#define ttislightuserdata(o) checktag((o), LUA_VLIGHTUSERDATA) -#define ttisfulluserdata(o) checktag((o), ctb(LUA_VUSERDATA)) - -#define pvalue(o) check_exp(ttislightuserdata(o), val_(o).p) -#define uvalue(o) check_exp(ttisfulluserdata(o), gco2u(val_(o).gc)) - -#define pvalueraw(v) ((v).p) - -#define setpvalue(obj,x) \ - { TValue *io=(obj); val_(io).p=(x); settt_(io, LUA_VLIGHTUSERDATA); } - -#define setuvalue(L,obj,x) \ - { TValue *io = (obj); Udata *x_ = (x); \ - val_(io).gc = obj2gco(x_); settt_(io, ctb(LUA_VUSERDATA)); \ - checkliveness(L,io); } - - -/* Ensures that addresses after this type are always fully aligned. */ -typedef union UValue { - TValue uv; - LUAI_MAXALIGN; /* ensures maximum alignment for udata bytes */ -} UValue; - - -/* -** Header for userdata with user values; -** memory area follows the end of this structure. -*/ -typedef struct Udata { - CommonHeader; - unsigned short nuvalue; /* number of user values */ - size_t len; /* number of bytes */ - struct Table *metatable; - GCObject *gclist; - UValue uv[1]; /* user values */ -} Udata; - - -/* -** Header for userdata with no user values. These userdata do not need -** to be gray during GC, and therefore do not need a 'gclist' field. -** To simplify, the code always use 'Udata' for both kinds of userdata, -** making sure it never accesses 'gclist' on userdata with no user values. -** This structure here is used only to compute the correct size for -** this representation. (The 'bindata' field in its end ensures correct -** alignment for binary data following this header.) -*/ -typedef struct Udata0 { - CommonHeader; - unsigned short nuvalue; /* number of user values */ - size_t len; /* number of bytes */ - struct Table *metatable; - union {LUAI_MAXALIGN;} bindata; -} Udata0; - - -/* compute the offset of the memory area of a userdata */ -#define udatamemoffset(nuv) \ - ((nuv) == 0 ? offsetof(Udata0, bindata) \ - : offsetof(Udata, uv) + (sizeof(UValue) * (nuv))) - -/* get the address of the memory block inside 'Udata' */ -#define getudatamem(u) (cast_charp(u) + udatamemoffset((u)->nuvalue)) - -/* compute the size of a userdata */ -#define sizeudata(nuv,nb) (udatamemoffset(nuv) + (nb)) - -/* }================================================================== */ - - -/* -** {================================================================== -** Prototypes -** =================================================================== -*/ - -#define LUA_VPROTO makevariant(LUA_TPROTO, 0) - - -/* -** Description of an upvalue for function prototypes -*/ -typedef struct Upvaldesc { - TString *name; /* upvalue name (for debug information) */ - lu_byte instack; /* whether it is in stack (register) */ - lu_byte idx; /* index of upvalue (in stack or in outer function's list) */ - lu_byte kind; /* kind of corresponding variable */ -} Upvaldesc; - - -/* -** Description of a local variable for function prototypes -** (used for debug information) -*/ -typedef struct LocVar { - TString *varname; - int startpc; /* first point where variable is active */ - int endpc; /* first point where variable is dead */ -} LocVar; - - -/* -** Associates the absolute line source for a given instruction ('pc'). -** The array 'lineinfo' gives, for each instruction, the difference in -** lines from the previous instruction. When that difference does not -** fit into a byte, Lua saves the absolute line for that instruction. -** (Lua also saves the absolute line periodically, to speed up the -** computation of a line number: we can use binary search in the -** absolute-line array, but we must traverse the 'lineinfo' array -** linearly to compute a line.) -*/ -typedef struct AbsLineInfo { - int pc; - int line; -} AbsLineInfo; - -/* -** Function Prototypes -*/ -typedef struct Proto { - CommonHeader; - lu_byte numparams; /* number of fixed (named) parameters */ - lu_byte is_vararg; - lu_byte maxstacksize; /* number of registers needed by this function */ - int sizeupvalues; /* size of 'upvalues' */ - int sizek; /* size of 'k' */ - int sizecode; - int sizelineinfo; - int sizep; /* size of 'p' */ - int sizelocvars; - int sizeabslineinfo; /* size of 'abslineinfo' */ - int linedefined; /* debug information */ - int lastlinedefined; /* debug information */ - TValue *k; /* constants used by the function */ - Instruction *code; /* opcodes */ - struct Proto **p; /* functions defined inside the function */ - Upvaldesc *upvalues; /* upvalue information */ - ls_byte *lineinfo; /* information about source lines (debug information) */ - AbsLineInfo *abslineinfo; /* idem */ - LocVar *locvars; /* information about local variables (debug information) */ - TString *source; /* used for debug information */ - GCObject *gclist; -} Proto; - -/* }================================================================== */ - - -/* -** {================================================================== -** Functions -** =================================================================== -*/ - -#define LUA_VUPVAL makevariant(LUA_TUPVAL, 0) - - -/* Variant tags for functions */ -#define LUA_VLCL makevariant(LUA_TFUNCTION, 0) /* Lua closure */ -#define LUA_VLCF makevariant(LUA_TFUNCTION, 1) /* light C function */ -#define LUA_VCCL makevariant(LUA_TFUNCTION, 2) /* C closure */ - -#define ttisfunction(o) checktype(o, LUA_TFUNCTION) -#define ttisLclosure(o) checktag((o), ctb(LUA_VLCL)) -#define ttislcf(o) checktag((o), LUA_VLCF) -#define ttisCclosure(o) checktag((o), ctb(LUA_VCCL)) -#define ttisclosure(o) (ttisLclosure(o) || ttisCclosure(o)) - - -#define isLfunction(o) ttisLclosure(o) - -#define clvalue(o) check_exp(ttisclosure(o), gco2cl(val_(o).gc)) -#define clLvalue(o) check_exp(ttisLclosure(o), gco2lcl(val_(o).gc)) -#define fvalue(o) check_exp(ttislcf(o), val_(o).f) -#define clCvalue(o) check_exp(ttisCclosure(o), gco2ccl(val_(o).gc)) - -#define fvalueraw(v) ((v).f) - -#define setclLvalue(L,obj,x) \ - { TValue *io = (obj); LClosure *x_ = (x); \ - val_(io).gc = obj2gco(x_); settt_(io, ctb(LUA_VLCL)); \ - checkliveness(L,io); } - -#define setclLvalue2s(L,o,cl) setclLvalue(L,s2v(o),cl) - -#define setfvalue(obj,x) \ - { TValue *io=(obj); val_(io).f=(x); settt_(io, LUA_VLCF); } - -#define setclCvalue(L,obj,x) \ - { TValue *io = (obj); CClosure *x_ = (x); \ - val_(io).gc = obj2gco(x_); settt_(io, ctb(LUA_VCCL)); \ - checkliveness(L,io); } - - -/* -** Upvalues for Lua closures -*/ -typedef struct UpVal { - CommonHeader; - union { - TValue *p; /* points to stack or to its own value */ - ptrdiff_t offset; /* used while the stack is being reallocated */ - } v; - union { - struct { /* (when open) */ - struct UpVal *next; /* linked list */ - struct UpVal **previous; - } open; - TValue value; /* the value (when closed) */ - } u; -} UpVal; - - - -#define ClosureHeader \ - CommonHeader; lu_byte nupvalues; GCObject *gclist - -typedef struct CClosure { - ClosureHeader; - lua_CFunction f; - TValue upvalue[1]; /* list of upvalues */ -} CClosure; - - -typedef struct LClosure { - ClosureHeader; - struct Proto *p; - UpVal *upvals[1]; /* list of upvalues */ -} LClosure; - - -typedef union Closure { - CClosure c; - LClosure l; -} Closure; - - -#define getproto(o) (clLvalue(o)->p) - -/* }================================================================== */ - - -/* -** {================================================================== -** Tables -** =================================================================== -*/ - -#define LUA_VTABLE makevariant(LUA_TTABLE, 0) - -#define ttistable(o) checktag((o), ctb(LUA_VTABLE)) - -#define hvalue(o) check_exp(ttistable(o), gco2t(val_(o).gc)) - -#define sethvalue(L,obj,x) \ - { TValue *io = (obj); Table *x_ = (x); \ - val_(io).gc = obj2gco(x_); settt_(io, ctb(LUA_VTABLE)); \ - checkliveness(L,io); } - -#define sethvalue2s(L,o,h) sethvalue(L,s2v(o),h) - - -/* -** Nodes for Hash tables: A pack of two TValue's (key-value pairs) -** plus a 'next' field to link colliding entries. The distribution -** of the key's fields ('key_tt' and 'key_val') not forming a proper -** 'TValue' allows for a smaller size for 'Node' both in 4-byte -** and 8-byte alignments. -*/ -typedef union Node { - struct NodeKey { - TValuefields; /* fields for value */ - lu_byte key_tt; /* key type */ - int next; /* for chaining */ - Value key_val; /* key value */ - } u; - TValue i_val; /* direct access to node's value as a proper 'TValue' */ -} Node; - - -/* copy a value into a key */ -#define setnodekey(L,node,obj) \ - { Node *n_=(node); const TValue *io_=(obj); \ - n_->u.key_val = io_->value_; n_->u.key_tt = io_->tt_; \ - checkliveness(L,io_); } - - -/* copy a value from a key */ -#define getnodekey(L,obj,node) \ - { TValue *io_=(obj); const Node *n_=(node); \ - io_->value_ = n_->u.key_val; io_->tt_ = n_->u.key_tt; \ - checkliveness(L,io_); } - - -/* -** About 'alimit': if 'isrealasize(t)' is true, then 'alimit' is the -** real size of 'array'. Otherwise, the real size of 'array' is the -** smallest power of two not smaller than 'alimit' (or zero iff 'alimit' -** is zero); 'alimit' is then used as a hint for #t. -*/ - -#define BITRAS (1 << 7) -#define isrealasize(t) (!((t)->flags & BITRAS)) -#define setrealasize(t) ((t)->flags &= cast_byte(~BITRAS)) -#define setnorealasize(t) ((t)->flags |= BITRAS) - - -typedef struct Table { - CommonHeader; - lu_byte flags; /* 1<

u.key_tt) -#define keyval(node) ((node)->u.key_val) - -#define keyisnil(node) (keytt(node) == LUA_TNIL) -#define keyisinteger(node) (keytt(node) == LUA_VNUMINT) -#define keyival(node) (keyval(node).i) -#define keyisshrstr(node) (keytt(node) == ctb(LUA_VSHRSTR)) -#define keystrval(node) (gco2ts(keyval(node).gc)) - -#define setnilkey(node) (keytt(node) = LUA_TNIL) - -#define keyiscollectable(n) (keytt(n) & BIT_ISCOLLECTABLE) - -#define gckey(n) (keyval(n).gc) -#define gckeyN(n) (keyiscollectable(n) ? gckey(n) : NULL) - - -/* -** Dead keys in tables have the tag DEADKEY but keep their original -** gcvalue. This distinguishes them from regular keys but allows them to -** be found when searched in a special way. ('next' needs that to find -** keys removed from a table during a traversal.) -*/ -#define setdeadkey(node) (keytt(node) = LUA_TDEADKEY) -#define keyisdead(node) (keytt(node) == LUA_TDEADKEY) - -/* }================================================================== */ - - - -/* -** 'module' operation for hashing (size is always a power of 2) -*/ -#define lmod(s,size) \ - (check_exp((size&(size-1))==0, (cast_int((s) & ((size)-1))))) - - -#define twoto(x) (1<<(x)) -#define sizenode(t) (twoto((t)->lsizenode)) - - -/* size of buffer for 'luaO_utf8esc' function */ -#define UTF8BUFFSZ 8 - -LUAI_FUNC int luaO_utf8esc (char *buff, unsigned long x); -LUAI_FUNC int luaO_ceillog2 (unsigned int x); -LUAI_FUNC int luaO_rawarith (lua_State *L, int op, const TValue *p1, - const TValue *p2, TValue *res); -LUAI_FUNC void luaO_arith (lua_State *L, int op, const TValue *p1, - const TValue *p2, StkId res); -LUAI_FUNC size_t luaO_str2num (const char *s, TValue *o); -LUAI_FUNC int luaO_hexavalue (int c); -LUAI_FUNC void luaO_tostring (lua_State *L, TValue *obj); -LUAI_FUNC const char *luaO_pushvfstring (lua_State *L, const char *fmt, - va_list argp); -LUAI_FUNC const char *luaO_pushfstring (lua_State *L, const char *fmt, ...); -LUAI_FUNC void luaO_chunkid (char *out, const char *source, size_t srclen); - - -#endif - diff --git a/lib/lua-5.4/src/lopcodes.c b/lib/lua-5.4/src/lopcodes.c deleted file mode 100644 index c67aa22..0000000 --- a/lib/lua-5.4/src/lopcodes.c +++ /dev/null @@ -1,104 +0,0 @@ -/* -** $Id: lopcodes.c $ -** Opcodes for Lua virtual machine -** See Copyright Notice in lua.h -*/ - -#define lopcodes_c -#define LUA_CORE - -#include "lprefix.h" - - -#include "lopcodes.h" - - -/* ORDER OP */ - -LUAI_DDEF const lu_byte luaP_opmodes[NUM_OPCODES] = { -/* MM OT IT T A mode opcode */ - opmode(0, 0, 0, 0, 1, iABC) /* OP_MOVE */ - ,opmode(0, 0, 0, 0, 1, iAsBx) /* OP_LOADI */ - ,opmode(0, 0, 0, 0, 1, iAsBx) /* OP_LOADF */ - ,opmode(0, 0, 0, 0, 1, iABx) /* OP_LOADK */ - ,opmode(0, 0, 0, 0, 1, iABx) /* OP_LOADKX */ - ,opmode(0, 0, 0, 0, 1, iABC) /* OP_LOADFALSE */ - ,opmode(0, 0, 0, 0, 1, iABC) /* OP_LFALSESKIP */ - ,opmode(0, 0, 0, 0, 1, iABC) /* OP_LOADTRUE */ - ,opmode(0, 0, 0, 0, 1, iABC) /* OP_LOADNIL */ - ,opmode(0, 0, 0, 0, 1, iABC) /* OP_GETUPVAL */ - ,opmode(0, 0, 0, 0, 0, iABC) /* OP_SETUPVAL */ - ,opmode(0, 0, 0, 0, 1, iABC) /* OP_GETTABUP */ - ,opmode(0, 0, 0, 0, 1, iABC) /* OP_GETTABLE */ - ,opmode(0, 0, 0, 0, 1, iABC) /* OP_GETI */ - ,opmode(0, 0, 0, 0, 1, iABC) /* OP_GETFIELD */ - ,opmode(0, 0, 0, 0, 0, iABC) /* OP_SETTABUP */ - ,opmode(0, 0, 0, 0, 0, iABC) /* OP_SETTABLE */ - ,opmode(0, 0, 0, 0, 0, iABC) /* OP_SETI */ - ,opmode(0, 0, 0, 0, 0, iABC) /* OP_SETFIELD */ - ,opmode(0, 0, 0, 0, 1, iABC) /* OP_NEWTABLE */ - ,opmode(0, 0, 0, 0, 1, iABC) /* OP_SELF */ - ,opmode(0, 0, 0, 0, 1, iABC) /* OP_ADDI */ - ,opmode(0, 0, 0, 0, 1, iABC) /* OP_ADDK */ - ,opmode(0, 0, 0, 0, 1, iABC) /* OP_SUBK */ - ,opmode(0, 0, 0, 0, 1, iABC) /* OP_MULK */ - ,opmode(0, 0, 0, 0, 1, iABC) /* OP_MODK */ - ,opmode(0, 0, 0, 0, 1, iABC) /* OP_POWK */ - ,opmode(0, 0, 0, 0, 1, iABC) /* OP_DIVK */ - ,opmode(0, 0, 0, 0, 1, iABC) /* OP_IDIVK */ - ,opmode(0, 0, 0, 0, 1, iABC) /* OP_BANDK */ - ,opmode(0, 0, 0, 0, 1, iABC) /* OP_BORK */ - ,opmode(0, 0, 0, 0, 1, iABC) /* OP_BXORK */ - ,opmode(0, 0, 0, 0, 1, iABC) /* OP_SHRI */ - ,opmode(0, 0, 0, 0, 1, iABC) /* OP_SHLI */ - ,opmode(0, 0, 0, 0, 1, iABC) /* OP_ADD */ - ,opmode(0, 0, 0, 0, 1, iABC) /* OP_SUB */ - ,opmode(0, 0, 0, 0, 1, iABC) /* OP_MUL */ - ,opmode(0, 0, 0, 0, 1, iABC) /* OP_MOD */ - ,opmode(0, 0, 0, 0, 1, iABC) /* OP_POW */ - ,opmode(0, 0, 0, 0, 1, iABC) /* OP_DIV */ - ,opmode(0, 0, 0, 0, 1, iABC) /* OP_IDIV */ - ,opmode(0, 0, 0, 0, 1, iABC) /* OP_BAND */ - ,opmode(0, 0, 0, 0, 1, iABC) /* OP_BOR */ - ,opmode(0, 0, 0, 0, 1, iABC) /* OP_BXOR */ - ,opmode(0, 0, 0, 0, 1, iABC) /* OP_SHL */ - ,opmode(0, 0, 0, 0, 1, iABC) /* OP_SHR */ - ,opmode(1, 0, 0, 0, 0, iABC) /* OP_MMBIN */ - ,opmode(1, 0, 0, 0, 0, iABC) /* OP_MMBINI*/ - ,opmode(1, 0, 0, 0, 0, iABC) /* OP_MMBINK*/ - ,opmode(0, 0, 0, 0, 1, iABC) /* OP_UNM */ - ,opmode(0, 0, 0, 0, 1, iABC) /* OP_BNOT */ - ,opmode(0, 0, 0, 0, 1, iABC) /* OP_NOT */ - ,opmode(0, 0, 0, 0, 1, iABC) /* OP_LEN */ - ,opmode(0, 0, 0, 0, 1, iABC) /* OP_CONCAT */ - ,opmode(0, 0, 0, 0, 0, iABC) /* OP_CLOSE */ - ,opmode(0, 0, 0, 0, 0, iABC) /* OP_TBC */ - ,opmode(0, 0, 0, 0, 0, isJ) /* OP_JMP */ - ,opmode(0, 0, 0, 1, 0, iABC) /* OP_EQ */ - ,opmode(0, 0, 0, 1, 0, iABC) /* OP_LT */ - ,opmode(0, 0, 0, 1, 0, iABC) /* OP_LE */ - ,opmode(0, 0, 0, 1, 0, iABC) /* OP_EQK */ - ,opmode(0, 0, 0, 1, 0, iABC) /* OP_EQI */ - ,opmode(0, 0, 0, 1, 0, iABC) /* OP_LTI */ - ,opmode(0, 0, 0, 1, 0, iABC) /* OP_LEI */ - ,opmode(0, 0, 0, 1, 0, iABC) /* OP_GTI */ - ,opmode(0, 0, 0, 1, 0, iABC) /* OP_GEI */ - ,opmode(0, 0, 0, 1, 0, iABC) /* OP_TEST */ - ,opmode(0, 0, 0, 1, 1, iABC) /* OP_TESTSET */ - ,opmode(0, 1, 1, 0, 1, iABC) /* OP_CALL */ - ,opmode(0, 1, 1, 0, 1, iABC) /* OP_TAILCALL */ - ,opmode(0, 0, 1, 0, 0, iABC) /* OP_RETURN */ - ,opmode(0, 0, 0, 0, 0, iABC) /* OP_RETURN0 */ - ,opmode(0, 0, 0, 0, 0, iABC) /* OP_RETURN1 */ - ,opmode(0, 0, 0, 0, 1, iABx) /* OP_FORLOOP */ - ,opmode(0, 0, 0, 0, 1, iABx) /* OP_FORPREP */ - ,opmode(0, 0, 0, 0, 0, iABx) /* OP_TFORPREP */ - ,opmode(0, 0, 0, 0, 0, iABC) /* OP_TFORCALL */ - ,opmode(0, 0, 0, 0, 1, iABx) /* OP_TFORLOOP */ - ,opmode(0, 0, 1, 0, 0, iABC) /* OP_SETLIST */ - ,opmode(0, 0, 0, 0, 1, iABx) /* OP_CLOSURE */ - ,opmode(0, 1, 0, 0, 1, iABC) /* OP_VARARG */ - ,opmode(0, 0, 1, 0, 1, iABC) /* OP_VARARGPREP */ - ,opmode(0, 0, 0, 0, 0, iAx) /* OP_EXTRAARG */ -}; - diff --git a/lib/lua-5.4/src/lopcodes.h b/lib/lua-5.4/src/lopcodes.h deleted file mode 100644 index 4c55145..0000000 --- a/lib/lua-5.4/src/lopcodes.h +++ /dev/null @@ -1,405 +0,0 @@ -/* -** $Id: lopcodes.h $ -** Opcodes for Lua virtual machine -** See Copyright Notice in lua.h -*/ - -#ifndef lopcodes_h -#define lopcodes_h - -#include "llimits.h" - - -/*=========================================================================== - We assume that instructions are unsigned 32-bit integers. - All instructions have an opcode in the first 7 bits. - Instructions can have the following formats: - - 3 3 2 2 2 2 2 2 2 2 2 2 1 1 1 1 1 1 1 1 1 1 0 0 0 0 0 0 0 0 0 0 - 1 0 9 8 7 6 5 4 3 2 1 0 9 8 7 6 5 4 3 2 1 0 9 8 7 6 5 4 3 2 1 0 -iABC C(8) | B(8) |k| A(8) | Op(7) | -iABx Bx(17) | A(8) | Op(7) | -iAsBx sBx (signed)(17) | A(8) | Op(7) | -iAx Ax(25) | Op(7) | -isJ sJ (signed)(25) | Op(7) | - - A signed argument is represented in excess K: the represented value is - the written unsigned value minus K, where K is half the maximum for the - corresponding unsigned argument. -===========================================================================*/ - - -enum OpMode {iABC, iABx, iAsBx, iAx, isJ}; /* basic instruction formats */ - - -/* -** size and position of opcode arguments. -*/ -#define SIZE_C 8 -#define SIZE_B 8 -#define SIZE_Bx (SIZE_C + SIZE_B + 1) -#define SIZE_A 8 -#define SIZE_Ax (SIZE_Bx + SIZE_A) -#define SIZE_sJ (SIZE_Bx + SIZE_A) - -#define SIZE_OP 7 - -#define POS_OP 0 - -#define POS_A (POS_OP + SIZE_OP) -#define POS_k (POS_A + SIZE_A) -#define POS_B (POS_k + 1) -#define POS_C (POS_B + SIZE_B) - -#define POS_Bx POS_k - -#define POS_Ax POS_A - -#define POS_sJ POS_A - - -/* -** limits for opcode arguments. -** we use (signed) 'int' to manipulate most arguments, -** so they must fit in ints. -*/ - -/* Check whether type 'int' has at least 'b' bits ('b' < 32) */ -#define L_INTHASBITS(b) ((UINT_MAX >> ((b) - 1)) >= 1) - - -#if L_INTHASBITS(SIZE_Bx) -#define MAXARG_Bx ((1<>1) /* 'sBx' is signed */ - - -#if L_INTHASBITS(SIZE_Ax) -#define MAXARG_Ax ((1<> 1) - - -#define MAXARG_A ((1<> 1) - -#define int2sC(i) ((i) + OFFSET_sC) -#define sC2int(i) ((i) - OFFSET_sC) - - -/* creates a mask with 'n' 1 bits at position 'p' */ -#define MASK1(n,p) ((~((~(Instruction)0)<<(n)))<<(p)) - -/* creates a mask with 'n' 0 bits at position 'p' */ -#define MASK0(n,p) (~MASK1(n,p)) - -/* -** the following macros help to manipulate instructions -*/ - -#define GET_OPCODE(i) (cast(OpCode, ((i)>>POS_OP) & MASK1(SIZE_OP,0))) -#define SET_OPCODE(i,o) ((i) = (((i)&MASK0(SIZE_OP,POS_OP)) | \ - ((cast(Instruction, o)<>(pos)) & MASK1(size,0))) -#define setarg(i,v,pos,size) ((i) = (((i)&MASK0(size,pos)) | \ - ((cast(Instruction, v)<> sC */ -OP_SHLI,/* A B sC R[A] := sC << R[B] */ - -OP_ADD,/* A B C R[A] := R[B] + R[C] */ -OP_SUB,/* A B C R[A] := R[B] - R[C] */ -OP_MUL,/* A B C R[A] := R[B] * R[C] */ -OP_MOD,/* A B C R[A] := R[B] % R[C] */ -OP_POW,/* A B C R[A] := R[B] ^ R[C] */ -OP_DIV,/* A B C R[A] := R[B] / R[C] */ -OP_IDIV,/* A B C R[A] := R[B] // R[C] */ - -OP_BAND,/* A B C R[A] := R[B] & R[C] */ -OP_BOR,/* A B C R[A] := R[B] | R[C] */ -OP_BXOR,/* A B C R[A] := R[B] ~ R[C] */ -OP_SHL,/* A B C R[A] := R[B] << R[C] */ -OP_SHR,/* A B C R[A] := R[B] >> R[C] */ - -OP_MMBIN,/* A B C call C metamethod over R[A] and R[B] (*) */ -OP_MMBINI,/* A sB C k call C metamethod over R[A] and sB */ -OP_MMBINK,/* A B C k call C metamethod over R[A] and K[B] */ - -OP_UNM,/* A B R[A] := -R[B] */ -OP_BNOT,/* A B R[A] := ~R[B] */ -OP_NOT,/* A B R[A] := not R[B] */ -OP_LEN,/* A B R[A] := #R[B] (length operator) */ - -OP_CONCAT,/* A B R[A] := R[A].. ... ..R[A + B - 1] */ - -OP_CLOSE,/* A close all upvalues >= R[A] */ -OP_TBC,/* A mark variable A "to be closed" */ -OP_JMP,/* sJ pc += sJ */ -OP_EQ,/* A B k if ((R[A] == R[B]) ~= k) then pc++ */ -OP_LT,/* A B k if ((R[A] < R[B]) ~= k) then pc++ */ -OP_LE,/* A B k if ((R[A] <= R[B]) ~= k) then pc++ */ - -OP_EQK,/* A B k if ((R[A] == K[B]) ~= k) then pc++ */ -OP_EQI,/* A sB k if ((R[A] == sB) ~= k) then pc++ */ -OP_LTI,/* A sB k if ((R[A] < sB) ~= k) then pc++ */ -OP_LEI,/* A sB k if ((R[A] <= sB) ~= k) then pc++ */ -OP_GTI,/* A sB k if ((R[A] > sB) ~= k) then pc++ */ -OP_GEI,/* A sB k if ((R[A] >= sB) ~= k) then pc++ */ - -OP_TEST,/* A k if (not R[A] == k) then pc++ */ -OP_TESTSET,/* A B k if (not R[B] == k) then pc++ else R[A] := R[B] (*) */ - -OP_CALL,/* A B C R[A], ... ,R[A+C-2] := R[A](R[A+1], ... ,R[A+B-1]) */ -OP_TAILCALL,/* A B C k return R[A](R[A+1], ... ,R[A+B-1]) */ - -OP_RETURN,/* A B C k return R[A], ... ,R[A+B-2] (see note) */ -OP_RETURN0,/* return */ -OP_RETURN1,/* A return R[A] */ - -OP_FORLOOP,/* A Bx update counters; if loop continues then pc-=Bx; */ -OP_FORPREP,/* A Bx ; - if not to run then pc+=Bx+1; */ - -OP_TFORPREP,/* A Bx create upvalue for R[A + 3]; pc+=Bx */ -OP_TFORCALL,/* A C R[A+4], ... ,R[A+3+C] := R[A](R[A+1], R[A+2]); */ -OP_TFORLOOP,/* A Bx if R[A+2] ~= nil then { R[A]=R[A+2]; pc -= Bx } */ - -OP_SETLIST,/* A B C k R[A][C+i] := R[A+i], 1 <= i <= B */ - -OP_CLOSURE,/* A Bx R[A] := closure(KPROTO[Bx]) */ - -OP_VARARG,/* A C R[A], R[A+1], ..., R[A+C-2] = vararg */ - -OP_VARARGPREP,/*A (adjust vararg parameters) */ - -OP_EXTRAARG/* Ax extra (larger) argument for previous opcode */ -} OpCode; - - -#define NUM_OPCODES ((int)(OP_EXTRAARG) + 1) - - - -/*=========================================================================== - Notes: - - (*) Opcode OP_LFALSESKIP is used to convert a condition to a boolean - value, in a code equivalent to (not cond ? false : true). (It - produces false and skips the next instruction producing true.) - - (*) Opcodes OP_MMBIN and variants follow each arithmetic and - bitwise opcode. If the operation succeeds, it skips this next - opcode. Otherwise, this opcode calls the corresponding metamethod. - - (*) Opcode OP_TESTSET is used in short-circuit expressions that need - both to jump and to produce a value, such as (a = b or c). - - (*) In OP_CALL, if (B == 0) then B = top - A. If (C == 0), then - 'top' is set to last_result+1, so next open instruction (OP_CALL, - OP_RETURN*, OP_SETLIST) may use 'top'. - - (*) In OP_VARARG, if (C == 0) then use actual number of varargs and - set top (like in OP_CALL with C == 0). - - (*) In OP_RETURN, if (B == 0) then return up to 'top'. - - (*) In OP_LOADKX and OP_NEWTABLE, the next instruction is always - OP_EXTRAARG. - - (*) In OP_SETLIST, if (B == 0) then real B = 'top'; if k, then - real C = EXTRAARG _ C (the bits of EXTRAARG concatenated with the - bits of C). - - (*) In OP_NEWTABLE, B is log2 of the hash size (which is always a - power of 2) plus 1, or zero for size zero. If not k, the array size - is C. Otherwise, the array size is EXTRAARG _ C. - - (*) For comparisons, k specifies what condition the test should accept - (true or false). - - (*) In OP_MMBINI/OP_MMBINK, k means the arguments were flipped - (the constant is the first operand). - - (*) All 'skips' (pc++) assume that next instruction is a jump. - - (*) In instructions OP_RETURN/OP_TAILCALL, 'k' specifies that the - function builds upvalues, which may need to be closed. C > 0 means - the function is vararg, so that its 'func' must be corrected before - returning; in this case, (C - 1) is its number of fixed parameters. - - (*) In comparisons with an immediate operand, C signals whether the - original operand was a float. (It must be corrected in case of - metamethods.) - -===========================================================================*/ - - -/* -** masks for instruction properties. The format is: -** bits 0-2: op mode -** bit 3: instruction set register A -** bit 4: operator is a test (next instruction must be a jump) -** bit 5: instruction uses 'L->top' set by previous instruction (when B == 0) -** bit 6: instruction sets 'L->top' for next instruction (when C == 0) -** bit 7: instruction is an MM instruction (call a metamethod) -*/ - -LUAI_DDEC(const lu_byte luaP_opmodes[NUM_OPCODES];) - -#define getOpMode(m) (cast(enum OpMode, luaP_opmodes[m] & 7)) -#define testAMode(m) (luaP_opmodes[m] & (1 << 3)) -#define testTMode(m) (luaP_opmodes[m] & (1 << 4)) -#define testITMode(m) (luaP_opmodes[m] & (1 << 5)) -#define testOTMode(m) (luaP_opmodes[m] & (1 << 6)) -#define testMMMode(m) (luaP_opmodes[m] & (1 << 7)) - -/* "out top" (set top for next instruction) */ -#define isOT(i) \ - ((testOTMode(GET_OPCODE(i)) && GETARG_C(i) == 0) || \ - GET_OPCODE(i) == OP_TAILCALL) - -/* "in top" (uses top from previous instruction) */ -#define isIT(i) (testITMode(GET_OPCODE(i)) && GETARG_B(i) == 0) - -#define opmode(mm,ot,it,t,a,m) \ - (((mm) << 7) | ((ot) << 6) | ((it) << 5) | ((t) << 4) | ((a) << 3) | (m)) - - -/* number of list items to accumulate before a SETLIST instruction */ -#define LFIELDS_PER_FLUSH 50 - -#endif diff --git a/lib/lua-5.4/src/lopnames.h b/lib/lua-5.4/src/lopnames.h deleted file mode 100644 index 965cec9..0000000 --- a/lib/lua-5.4/src/lopnames.h +++ /dev/null @@ -1,103 +0,0 @@ -/* -** $Id: lopnames.h $ -** Opcode names -** See Copyright Notice in lua.h -*/ - -#if !defined(lopnames_h) -#define lopnames_h - -#include - - -/* ORDER OP */ - -static const char *const opnames[] = { - "MOVE", - "LOADI", - "LOADF", - "LOADK", - "LOADKX", - "LOADFALSE", - "LFALSESKIP", - "LOADTRUE", - "LOADNIL", - "GETUPVAL", - "SETUPVAL", - "GETTABUP", - "GETTABLE", - "GETI", - "GETFIELD", - "SETTABUP", - "SETTABLE", - "SETI", - "SETFIELD", - "NEWTABLE", - "SELF", - "ADDI", - "ADDK", - "SUBK", - "MULK", - "MODK", - "POWK", - "DIVK", - "IDIVK", - "BANDK", - "BORK", - "BXORK", - "SHRI", - "SHLI", - "ADD", - "SUB", - "MUL", - "MOD", - "POW", - "DIV", - "IDIV", - "BAND", - "BOR", - "BXOR", - "SHL", - "SHR", - "MMBIN", - "MMBINI", - "MMBINK", - "UNM", - "BNOT", - "NOT", - "LEN", - "CONCAT", - "CLOSE", - "TBC", - "JMP", - "EQ", - "LT", - "LE", - "EQK", - "EQI", - "LTI", - "LEI", - "GTI", - "GEI", - "TEST", - "TESTSET", - "CALL", - "TAILCALL", - "RETURN", - "RETURN0", - "RETURN1", - "FORLOOP", - "FORPREP", - "TFORPREP", - "TFORCALL", - "TFORLOOP", - "SETLIST", - "CLOSURE", - "VARARG", - "VARARGPREP", - "EXTRAARG", - NULL -}; - -#endif - diff --git a/lib/lua-5.4/src/loslib.c b/lib/lua-5.4/src/loslib.c deleted file mode 100644 index ad5a927..0000000 --- a/lib/lua-5.4/src/loslib.c +++ /dev/null @@ -1,428 +0,0 @@ -/* -** $Id: loslib.c $ -** Standard Operating System library -** See Copyright Notice in lua.h -*/ - -#define loslib_c -#define LUA_LIB - -#include "lprefix.h" - - -#include -#include -#include -#include -#include - -#include "lua.h" - -#include "lauxlib.h" -#include "lualib.h" - - -/* -** {================================================================== -** List of valid conversion specifiers for the 'strftime' function; -** options are grouped by length; group of length 2 start with '||'. -** =================================================================== -*/ -#if !defined(LUA_STRFTIMEOPTIONS) /* { */ - -#if defined(LUA_USE_WINDOWS) -#define LUA_STRFTIMEOPTIONS "aAbBcdHIjmMpSUwWxXyYzZ%" \ - "||" "#c#x#d#H#I#j#m#M#S#U#w#W#y#Y" /* two-char options */ -#elif defined(LUA_USE_C89) /* ANSI C 89 (only 1-char options) */ -#define LUA_STRFTIMEOPTIONS "aAbBcdHIjmMpSUwWxXyYZ%" -#else /* C99 specification */ -#define LUA_STRFTIMEOPTIONS "aAbBcCdDeFgGhHIjmMnprRStTuUVwWxXyYzZ%" \ - "||" "EcECExEXEyEY" "OdOeOHOIOmOMOSOuOUOVOwOWOy" /* two-char options */ -#endif - -#endif /* } */ -/* }================================================================== */ - - -/* -** {================================================================== -** Configuration for time-related stuff -** =================================================================== -*/ - -/* -** type to represent time_t in Lua -*/ -#if !defined(LUA_NUMTIME) /* { */ - -#define l_timet lua_Integer -#define l_pushtime(L,t) lua_pushinteger(L,(lua_Integer)(t)) -#define l_gettime(L,arg) luaL_checkinteger(L, arg) - -#else /* }{ */ - -#define l_timet lua_Number -#define l_pushtime(L,t) lua_pushnumber(L,(lua_Number)(t)) -#define l_gettime(L,arg) luaL_checknumber(L, arg) - -#endif /* } */ - - -#if !defined(l_gmtime) /* { */ -/* -** By default, Lua uses gmtime/localtime, except when POSIX is available, -** where it uses gmtime_r/localtime_r -*/ - -#if defined(LUA_USE_POSIX) /* { */ - -#define l_gmtime(t,r) gmtime_r(t,r) -#define l_localtime(t,r) localtime_r(t,r) - -#else /* }{ */ - -/* ISO C definitions */ -#define l_gmtime(t,r) ((void)(r)->tm_sec, gmtime(t)) -#define l_localtime(t,r) ((void)(r)->tm_sec, localtime(t)) - -#endif /* } */ - -#endif /* } */ - -/* }================================================================== */ - - -/* -** {================================================================== -** Configuration for 'tmpnam': -** By default, Lua uses tmpnam except when POSIX is available, where -** it uses mkstemp. -** =================================================================== -*/ -#if !defined(lua_tmpnam) /* { */ - -#if defined(LUA_USE_POSIX) /* { */ - -#include - -#define LUA_TMPNAMBUFSIZE 32 - -#if !defined(LUA_TMPNAMTEMPLATE) -#define LUA_TMPNAMTEMPLATE "/tmp/lua_XXXXXX" -#endif - -#define lua_tmpnam(b,e) { \ - strcpy(b, LUA_TMPNAMTEMPLATE); \ - e = mkstemp(b); \ - if (e != -1) close(e); \ - e = (e == -1); } - -#else /* }{ */ - -/* ISO C definitions */ -#define LUA_TMPNAMBUFSIZE L_tmpnam -#define lua_tmpnam(b,e) { e = (tmpnam(b) == NULL); } - -#endif /* } */ - -#endif /* } */ -/* }================================================================== */ - - -#if !defined(l_system) -#if defined(LUA_USE_IOS) -/* Despite claiming to be ISO C, iOS does not implement 'system'. */ -#define l_system(cmd) ((cmd) == NULL ? 0 : -1) -#else -#define l_system(cmd) system(cmd) /* default definition */ -#endif -#endif - - -static int os_execute (lua_State *L) { - const char *cmd = luaL_optstring(L, 1, NULL); - int stat; - errno = 0; - stat = l_system(cmd); - if (cmd != NULL) - return luaL_execresult(L, stat); - else { - lua_pushboolean(L, stat); /* true if there is a shell */ - return 1; - } -} - - -static int os_remove (lua_State *L) { - const char *filename = luaL_checkstring(L, 1); - return luaL_fileresult(L, remove(filename) == 0, filename); -} - - -static int os_rename (lua_State *L) { - const char *fromname = luaL_checkstring(L, 1); - const char *toname = luaL_checkstring(L, 2); - return luaL_fileresult(L, rename(fromname, toname) == 0, NULL); -} - - -static int os_tmpname (lua_State *L) { - char buff[LUA_TMPNAMBUFSIZE]; - int err; - lua_tmpnam(buff, err); - if (l_unlikely(err)) - return luaL_error(L, "unable to generate a unique filename"); - lua_pushstring(L, buff); - return 1; -} - - -static int os_getenv (lua_State *L) { - lua_pushstring(L, getenv(luaL_checkstring(L, 1))); /* if NULL push nil */ - return 1; -} - - -static int os_clock (lua_State *L) { - lua_pushnumber(L, ((lua_Number)clock())/(lua_Number)CLOCKS_PER_SEC); - return 1; -} - - -/* -** {====================================================== -** Time/Date operations -** { year=%Y, month=%m, day=%d, hour=%H, min=%M, sec=%S, -** wday=%w+1, yday=%j, isdst=? } -** ======================================================= -*/ - -/* -** About the overflow check: an overflow cannot occur when time -** is represented by a lua_Integer, because either lua_Integer is -** large enough to represent all int fields or it is not large enough -** to represent a time that cause a field to overflow. However, if -** times are represented as doubles and lua_Integer is int, then the -** time 0x1.e1853b0d184f6p+55 would cause an overflow when adding 1900 -** to compute the year. -*/ -static void setfield (lua_State *L, const char *key, int value, int delta) { - #if (defined(LUA_NUMTIME) && LUA_MAXINTEGER <= INT_MAX) - if (l_unlikely(value > LUA_MAXINTEGER - delta)) - luaL_error(L, "field '%s' is out-of-bound", key); - #endif - lua_pushinteger(L, (lua_Integer)value + delta); - lua_setfield(L, -2, key); -} - - -static void setboolfield (lua_State *L, const char *key, int value) { - if (value < 0) /* undefined? */ - return; /* does not set field */ - lua_pushboolean(L, value); - lua_setfield(L, -2, key); -} - - -/* -** Set all fields from structure 'tm' in the table on top of the stack -*/ -static void setallfields (lua_State *L, struct tm *stm) { - setfield(L, "year", stm->tm_year, 1900); - setfield(L, "month", stm->tm_mon, 1); - setfield(L, "day", stm->tm_mday, 0); - setfield(L, "hour", stm->tm_hour, 0); - setfield(L, "min", stm->tm_min, 0); - setfield(L, "sec", stm->tm_sec, 0); - setfield(L, "yday", stm->tm_yday, 1); - setfield(L, "wday", stm->tm_wday, 1); - setboolfield(L, "isdst", stm->tm_isdst); -} - - -static int getboolfield (lua_State *L, const char *key) { - int res; - res = (lua_getfield(L, -1, key) == LUA_TNIL) ? -1 : lua_toboolean(L, -1); - lua_pop(L, 1); - return res; -} - - -static int getfield (lua_State *L, const char *key, int d, int delta) { - int isnum; - int t = lua_getfield(L, -1, key); /* get field and its type */ - lua_Integer res = lua_tointegerx(L, -1, &isnum); - if (!isnum) { /* field is not an integer? */ - if (l_unlikely(t != LUA_TNIL)) /* some other value? */ - return luaL_error(L, "field '%s' is not an integer", key); - else if (l_unlikely(d < 0)) /* absent field; no default? */ - return luaL_error(L, "field '%s' missing in date table", key); - res = d; - } - else { - if (!(res >= 0 ? res - delta <= INT_MAX : INT_MIN + delta <= res)) - return luaL_error(L, "field '%s' is out-of-bound", key); - res -= delta; - } - lua_pop(L, 1); - return (int)res; -} - - -static const char *checkoption (lua_State *L, const char *conv, - ptrdiff_t convlen, char *buff) { - const char *option = LUA_STRFTIMEOPTIONS; - int oplen = 1; /* length of options being checked */ - for (; *option != '\0' && oplen <= convlen; option += oplen) { - if (*option == '|') /* next block? */ - oplen++; /* will check options with next length (+1) */ - else if (memcmp(conv, option, oplen) == 0) { /* match? */ - memcpy(buff, conv, oplen); /* copy valid option to buffer */ - buff[oplen] = '\0'; - return conv + oplen; /* return next item */ - } - } - luaL_argerror(L, 1, - lua_pushfstring(L, "invalid conversion specifier '%%%s'", conv)); - return conv; /* to avoid warnings */ -} - - -static time_t l_checktime (lua_State *L, int arg) { - l_timet t = l_gettime(L, arg); - luaL_argcheck(L, (time_t)t == t, arg, "time out-of-bounds"); - return (time_t)t; -} - - -/* maximum size for an individual 'strftime' item */ -#define SIZETIMEFMT 250 - - -static int os_date (lua_State *L) { - size_t slen; - const char *s = luaL_optlstring(L, 1, "%c", &slen); - time_t t = luaL_opt(L, l_checktime, 2, time(NULL)); - const char *se = s + slen; /* 's' end */ - struct tm tmr, *stm; - if (*s == '!') { /* UTC? */ - stm = l_gmtime(&t, &tmr); - s++; /* skip '!' */ - } - else - stm = l_localtime(&t, &tmr); - if (stm == NULL) /* invalid date? */ - return luaL_error(L, - "date result cannot be represented in this installation"); - if (strcmp(s, "*t") == 0) { - lua_createtable(L, 0, 9); /* 9 = number of fields */ - setallfields(L, stm); - } - else { - char cc[4]; /* buffer for individual conversion specifiers */ - luaL_Buffer b; - cc[0] = '%'; - luaL_buffinit(L, &b); - while (s < se) { - if (*s != '%') /* not a conversion specifier? */ - luaL_addchar(&b, *s++); - else { - size_t reslen; - char *buff = luaL_prepbuffsize(&b, SIZETIMEFMT); - s++; /* skip '%' */ - s = checkoption(L, s, se - s, cc + 1); /* copy specifier to 'cc' */ - reslen = strftime(buff, SIZETIMEFMT, cc, stm); - luaL_addsize(&b, reslen); - } - } - luaL_pushresult(&b); - } - return 1; -} - - -static int os_time (lua_State *L) { - time_t t; - if (lua_isnoneornil(L, 1)) /* called without args? */ - t = time(NULL); /* get current time */ - else { - struct tm ts; - luaL_checktype(L, 1, LUA_TTABLE); - lua_settop(L, 1); /* make sure table is at the top */ - ts.tm_year = getfield(L, "year", -1, 1900); - ts.tm_mon = getfield(L, "month", -1, 1); - ts.tm_mday = getfield(L, "day", -1, 0); - ts.tm_hour = getfield(L, "hour", 12, 0); - ts.tm_min = getfield(L, "min", 0, 0); - ts.tm_sec = getfield(L, "sec", 0, 0); - ts.tm_isdst = getboolfield(L, "isdst"); - t = mktime(&ts); - setallfields(L, &ts); /* update fields with normalized values */ - } - if (t != (time_t)(l_timet)t || t == (time_t)(-1)) - return luaL_error(L, - "time result cannot be represented in this installation"); - l_pushtime(L, t); - return 1; -} - - -static int os_difftime (lua_State *L) { - time_t t1 = l_checktime(L, 1); - time_t t2 = l_checktime(L, 2); - lua_pushnumber(L, (lua_Number)difftime(t1, t2)); - return 1; -} - -/* }====================================================== */ - - -static int os_setlocale (lua_State *L) { - static const int cat[] = {LC_ALL, LC_COLLATE, LC_CTYPE, LC_MONETARY, - LC_NUMERIC, LC_TIME}; - static const char *const catnames[] = {"all", "collate", "ctype", "monetary", - "numeric", "time", NULL}; - const char *l = luaL_optstring(L, 1, NULL); - int op = luaL_checkoption(L, 2, "all", catnames); - lua_pushstring(L, setlocale(cat[op], l)); - return 1; -} - - -static int os_exit (lua_State *L) { - int status; - if (lua_isboolean(L, 1)) - status = (lua_toboolean(L, 1) ? EXIT_SUCCESS : EXIT_FAILURE); - else - status = (int)luaL_optinteger(L, 1, EXIT_SUCCESS); - if (lua_toboolean(L, 2)) - lua_close(L); - if (L) exit(status); /* 'if' to avoid warnings for unreachable 'return' */ - return 0; -} - - -static const luaL_Reg syslib[] = { - {"clock", os_clock}, - {"date", os_date}, - {"difftime", os_difftime}, - {"execute", os_execute}, - {"exit", os_exit}, - {"getenv", os_getenv}, - {"remove", os_remove}, - {"rename", os_rename}, - {"setlocale", os_setlocale}, - {"time", os_time}, - {"tmpname", os_tmpname}, - {NULL, NULL} -}; - -/* }====================================================== */ - - - -LUAMOD_API int luaopen_os (lua_State *L) { - luaL_newlib(L, syslib); - return 1; -} - diff --git a/lib/lua-5.4/src/lparser.c b/lib/lua-5.4/src/lparser.c deleted file mode 100644 index b745f23..0000000 --- a/lib/lua-5.4/src/lparser.c +++ /dev/null @@ -1,1967 +0,0 @@ -/* -** $Id: lparser.c $ -** Lua Parser -** See Copyright Notice in lua.h -*/ - -#define lparser_c -#define LUA_CORE - -#include "lprefix.h" - - -#include -#include - -#include "lua.h" - -#include "lcode.h" -#include "ldebug.h" -#include "ldo.h" -#include "lfunc.h" -#include "llex.h" -#include "lmem.h" -#include "lobject.h" -#include "lopcodes.h" -#include "lparser.h" -#include "lstate.h" -#include "lstring.h" -#include "ltable.h" - - - -/* maximum number of local variables per function (must be smaller - than 250, due to the bytecode format) */ -#define MAXVARS 200 - - -#define hasmultret(k) ((k) == VCALL || (k) == VVARARG) - - -/* because all strings are unified by the scanner, the parser - can use pointer equality for string equality */ -#define eqstr(a,b) ((a) == (b)) - - -/* -** nodes for block list (list of active blocks) -*/ -typedef struct BlockCnt { - struct BlockCnt *previous; /* chain */ - int firstlabel; /* index of first label in this block */ - int firstgoto; /* index of first pending goto in this block */ - lu_byte nactvar; /* # active locals outside the block */ - lu_byte upval; /* true if some variable in the block is an upvalue */ - lu_byte isloop; /* true if 'block' is a loop */ - lu_byte insidetbc; /* true if inside the scope of a to-be-closed var. */ -} BlockCnt; - - - -/* -** prototypes for recursive non-terminal functions -*/ -static void statement (LexState *ls); -static void expr (LexState *ls, expdesc *v); - - -static l_noret error_expected (LexState *ls, int token) { - luaX_syntaxerror(ls, - luaO_pushfstring(ls->L, "%s expected", luaX_token2str(ls, token))); -} - - -static l_noret errorlimit (FuncState *fs, int limit, const char *what) { - lua_State *L = fs->ls->L; - const char *msg; - int line = fs->f->linedefined; - const char *where = (line == 0) - ? "main function" - : luaO_pushfstring(L, "function at line %d", line); - msg = luaO_pushfstring(L, "too many %s (limit is %d) in %s", - what, limit, where); - luaX_syntaxerror(fs->ls, msg); -} - - -static void checklimit (FuncState *fs, int v, int l, const char *what) { - if (v > l) errorlimit(fs, l, what); -} - - -/* -** Test whether next token is 'c'; if so, skip it. -*/ -static int testnext (LexState *ls, int c) { - if (ls->t.token == c) { - luaX_next(ls); - return 1; - } - else return 0; -} - - -/* -** Check that next token is 'c'. -*/ -static void check (LexState *ls, int c) { - if (ls->t.token != c) - error_expected(ls, c); -} - - -/* -** Check that next token is 'c' and skip it. -*/ -static void checknext (LexState *ls, int c) { - check(ls, c); - luaX_next(ls); -} - - -#define check_condition(ls,c,msg) { if (!(c)) luaX_syntaxerror(ls, msg); } - - -/* -** Check that next token is 'what' and skip it. In case of error, -** raise an error that the expected 'what' should match a 'who' -** in line 'where' (if that is not the current line). -*/ -static void check_match (LexState *ls, int what, int who, int where) { - if (l_unlikely(!testnext(ls, what))) { - if (where == ls->linenumber) /* all in the same line? */ - error_expected(ls, what); /* do not need a complex message */ - else { - luaX_syntaxerror(ls, luaO_pushfstring(ls->L, - "%s expected (to close %s at line %d)", - luaX_token2str(ls, what), luaX_token2str(ls, who), where)); - } - } -} - - -static TString *str_checkname (LexState *ls) { - TString *ts; - check(ls, TK_NAME); - ts = ls->t.seminfo.ts; - luaX_next(ls); - return ts; -} - - -static void init_exp (expdesc *e, expkind k, int i) { - e->f = e->t = NO_JUMP; - e->k = k; - e->u.info = i; -} - - -static void codestring (expdesc *e, TString *s) { - e->f = e->t = NO_JUMP; - e->k = VKSTR; - e->u.strval = s; -} - - -static void codename (LexState *ls, expdesc *e) { - codestring(e, str_checkname(ls)); -} - - -/* -** Register a new local variable in the active 'Proto' (for debug -** information). -*/ -static int registerlocalvar (LexState *ls, FuncState *fs, TString *varname) { - Proto *f = fs->f; - int oldsize = f->sizelocvars; - luaM_growvector(ls->L, f->locvars, fs->ndebugvars, f->sizelocvars, - LocVar, SHRT_MAX, "local variables"); - while (oldsize < f->sizelocvars) - f->locvars[oldsize++].varname = NULL; - f->locvars[fs->ndebugvars].varname = varname; - f->locvars[fs->ndebugvars].startpc = fs->pc; - luaC_objbarrier(ls->L, f, varname); - return fs->ndebugvars++; -} - - -/* -** Create a new local variable with the given 'name'. Return its index -** in the function. -*/ -static int new_localvar (LexState *ls, TString *name) { - lua_State *L = ls->L; - FuncState *fs = ls->fs; - Dyndata *dyd = ls->dyd; - Vardesc *var; - checklimit(fs, dyd->actvar.n + 1 - fs->firstlocal, - MAXVARS, "local variables"); - luaM_growvector(L, dyd->actvar.arr, dyd->actvar.n + 1, - dyd->actvar.size, Vardesc, USHRT_MAX, "local variables"); - var = &dyd->actvar.arr[dyd->actvar.n++]; - var->vd.kind = VDKREG; /* default */ - var->vd.name = name; - return dyd->actvar.n - 1 - fs->firstlocal; -} - -#define new_localvarliteral(ls,v) \ - new_localvar(ls, \ - luaX_newstring(ls, "" v, (sizeof(v)/sizeof(char)) - 1)); - - - -/* -** Return the "variable description" (Vardesc) of a given variable. -** (Unless noted otherwise, all variables are referred to by their -** compiler indices.) -*/ -static Vardesc *getlocalvardesc (FuncState *fs, int vidx) { - return &fs->ls->dyd->actvar.arr[fs->firstlocal + vidx]; -} - - -/* -** Convert 'nvar', a compiler index level, to its corresponding -** register. For that, search for the highest variable below that level -** that is in a register and uses its register index ('ridx') plus one. -*/ -static int reglevel (FuncState *fs, int nvar) { - while (nvar-- > 0) { - Vardesc *vd = getlocalvardesc(fs, nvar); /* get previous variable */ - if (vd->vd.kind != RDKCTC) /* is in a register? */ - return vd->vd.ridx + 1; - } - return 0; /* no variables in registers */ -} - - -/* -** Return the number of variables in the register stack for the given -** function. -*/ -int luaY_nvarstack (FuncState *fs) { - return reglevel(fs, fs->nactvar); -} - - -/* -** Get the debug-information entry for current variable 'vidx'. -*/ -static LocVar *localdebuginfo (FuncState *fs, int vidx) { - Vardesc *vd = getlocalvardesc(fs, vidx); - if (vd->vd.kind == RDKCTC) - return NULL; /* no debug info. for constants */ - else { - int idx = vd->vd.pidx; - lua_assert(idx < fs->ndebugvars); - return &fs->f->locvars[idx]; - } -} - - -/* -** Create an expression representing variable 'vidx' -*/ -static void init_var (FuncState *fs, expdesc *e, int vidx) { - e->f = e->t = NO_JUMP; - e->k = VLOCAL; - e->u.var.vidx = vidx; - e->u.var.ridx = getlocalvardesc(fs, vidx)->vd.ridx; -} - - -/* -** Raises an error if variable described by 'e' is read only -*/ -static void check_readonly (LexState *ls, expdesc *e) { - FuncState *fs = ls->fs; - TString *varname = NULL; /* to be set if variable is const */ - switch (e->k) { - case VCONST: { - varname = ls->dyd->actvar.arr[e->u.info].vd.name; - break; - } - case VLOCAL: { - Vardesc *vardesc = getlocalvardesc(fs, e->u.var.vidx); - if (vardesc->vd.kind != VDKREG) /* not a regular variable? */ - varname = vardesc->vd.name; - break; - } - case VUPVAL: { - Upvaldesc *up = &fs->f->upvalues[e->u.info]; - if (up->kind != VDKREG) - varname = up->name; - break; - } - default: - return; /* other cases cannot be read-only */ - } - if (varname) { - const char *msg = luaO_pushfstring(ls->L, - "attempt to assign to const variable '%s'", getstr(varname)); - luaK_semerror(ls, msg); /* error */ - } -} - - -/* -** Start the scope for the last 'nvars' created variables. -*/ -static void adjustlocalvars (LexState *ls, int nvars) { - FuncState *fs = ls->fs; - int reglevel = luaY_nvarstack(fs); - int i; - for (i = 0; i < nvars; i++) { - int vidx = fs->nactvar++; - Vardesc *var = getlocalvardesc(fs, vidx); - var->vd.ridx = reglevel++; - var->vd.pidx = registerlocalvar(ls, fs, var->vd.name); - } -} - - -/* -** Close the scope for all variables up to level 'tolevel'. -** (debug info.) -*/ -static void removevars (FuncState *fs, int tolevel) { - fs->ls->dyd->actvar.n -= (fs->nactvar - tolevel); - while (fs->nactvar > tolevel) { - LocVar *var = localdebuginfo(fs, --fs->nactvar); - if (var) /* does it have debug information? */ - var->endpc = fs->pc; - } -} - - -/* -** Search the upvalues of the function 'fs' for one -** with the given 'name'. -*/ -static int searchupvalue (FuncState *fs, TString *name) { - int i; - Upvaldesc *up = fs->f->upvalues; - for (i = 0; i < fs->nups; i++) { - if (eqstr(up[i].name, name)) return i; - } - return -1; /* not found */ -} - - -static Upvaldesc *allocupvalue (FuncState *fs) { - Proto *f = fs->f; - int oldsize = f->sizeupvalues; - checklimit(fs, fs->nups + 1, MAXUPVAL, "upvalues"); - luaM_growvector(fs->ls->L, f->upvalues, fs->nups, f->sizeupvalues, - Upvaldesc, MAXUPVAL, "upvalues"); - while (oldsize < f->sizeupvalues) - f->upvalues[oldsize++].name = NULL; - return &f->upvalues[fs->nups++]; -} - - -static int newupvalue (FuncState *fs, TString *name, expdesc *v) { - Upvaldesc *up = allocupvalue(fs); - FuncState *prev = fs->prev; - if (v->k == VLOCAL) { - up->instack = 1; - up->idx = v->u.var.ridx; - up->kind = getlocalvardesc(prev, v->u.var.vidx)->vd.kind; - lua_assert(eqstr(name, getlocalvardesc(prev, v->u.var.vidx)->vd.name)); - } - else { - up->instack = 0; - up->idx = cast_byte(v->u.info); - up->kind = prev->f->upvalues[v->u.info].kind; - lua_assert(eqstr(name, prev->f->upvalues[v->u.info].name)); - } - up->name = name; - luaC_objbarrier(fs->ls->L, fs->f, name); - return fs->nups - 1; -} - - -/* -** Look for an active local variable with the name 'n' in the -** function 'fs'. If found, initialize 'var' with it and return -** its expression kind; otherwise return -1. -*/ -static int searchvar (FuncState *fs, TString *n, expdesc *var) { - int i; - for (i = cast_int(fs->nactvar) - 1; i >= 0; i--) { - Vardesc *vd = getlocalvardesc(fs, i); - if (eqstr(n, vd->vd.name)) { /* found? */ - if (vd->vd.kind == RDKCTC) /* compile-time constant? */ - init_exp(var, VCONST, fs->firstlocal + i); - else /* real variable */ - init_var(fs, var, i); - return var->k; - } - } - return -1; /* not found */ -} - - -/* -** Mark block where variable at given level was defined -** (to emit close instructions later). -*/ -static void markupval (FuncState *fs, int level) { - BlockCnt *bl = fs->bl; - while (bl->nactvar > level) - bl = bl->previous; - bl->upval = 1; - fs->needclose = 1; -} - - -/* -** Mark that current block has a to-be-closed variable. -*/ -static void marktobeclosed (FuncState *fs) { - BlockCnt *bl = fs->bl; - bl->upval = 1; - bl->insidetbc = 1; - fs->needclose = 1; -} - - -/* -** Find a variable with the given name 'n'. If it is an upvalue, add -** this upvalue into all intermediate functions. If it is a global, set -** 'var' as 'void' as a flag. -*/ -static void singlevaraux (FuncState *fs, TString *n, expdesc *var, int base) { - if (fs == NULL) /* no more levels? */ - init_exp(var, VVOID, 0); /* default is global */ - else { - int v = searchvar(fs, n, var); /* look up locals at current level */ - if (v >= 0) { /* found? */ - if (v == VLOCAL && !base) - markupval(fs, var->u.var.vidx); /* local will be used as an upval */ - } - else { /* not found as local at current level; try upvalues */ - int idx = searchupvalue(fs, n); /* try existing upvalues */ - if (idx < 0) { /* not found? */ - singlevaraux(fs->prev, n, var, 0); /* try upper levels */ - if (var->k == VLOCAL || var->k == VUPVAL) /* local or upvalue? */ - idx = newupvalue(fs, n, var); /* will be a new upvalue */ - else /* it is a global or a constant */ - return; /* don't need to do anything at this level */ - } - init_exp(var, VUPVAL, idx); /* new or old upvalue */ - } - } -} - - -/* -** Find a variable with the given name 'n', handling global variables -** too. -*/ -static void singlevar (LexState *ls, expdesc *var) { - TString *varname = str_checkname(ls); - FuncState *fs = ls->fs; - singlevaraux(fs, varname, var, 1); - if (var->k == VVOID) { /* global name? */ - expdesc key; - singlevaraux(fs, ls->envn, var, 1); /* get environment variable */ - lua_assert(var->k != VVOID); /* this one must exist */ - luaK_exp2anyregup(fs, var); /* but could be a constant */ - codestring(&key, varname); /* key is variable name */ - luaK_indexed(fs, var, &key); /* env[varname] */ - } -} - - -/* -** Adjust the number of results from an expression list 'e' with 'nexps' -** expressions to 'nvars' values. -*/ -static void adjust_assign (LexState *ls, int nvars, int nexps, expdesc *e) { - FuncState *fs = ls->fs; - int needed = nvars - nexps; /* extra values needed */ - if (hasmultret(e->k)) { /* last expression has multiple returns? */ - int extra = needed + 1; /* discount last expression itself */ - if (extra < 0) - extra = 0; - luaK_setreturns(fs, e, extra); /* last exp. provides the difference */ - } - else { - if (e->k != VVOID) /* at least one expression? */ - luaK_exp2nextreg(fs, e); /* close last expression */ - if (needed > 0) /* missing values? */ - luaK_nil(fs, fs->freereg, needed); /* complete with nils */ - } - if (needed > 0) - luaK_reserveregs(fs, needed); /* registers for extra values */ - else /* adding 'needed' is actually a subtraction */ - fs->freereg += needed; /* remove extra values */ -} - - -#define enterlevel(ls) luaE_incCstack(ls->L) - - -#define leavelevel(ls) ((ls)->L->nCcalls--) - - -/* -** Generates an error that a goto jumps into the scope of some -** local variable. -*/ -static l_noret jumpscopeerror (LexState *ls, Labeldesc *gt) { - const char *varname = getstr(getlocalvardesc(ls->fs, gt->nactvar)->vd.name); - const char *msg = " at line %d jumps into the scope of local '%s'"; - msg = luaO_pushfstring(ls->L, msg, getstr(gt->name), gt->line, varname); - luaK_semerror(ls, msg); /* raise the error */ -} - - -/* -** Solves the goto at index 'g' to given 'label' and removes it -** from the list of pending gotos. -** If it jumps into the scope of some variable, raises an error. -*/ -static void solvegoto (LexState *ls, int g, Labeldesc *label) { - int i; - Labellist *gl = &ls->dyd->gt; /* list of gotos */ - Labeldesc *gt = &gl->arr[g]; /* goto to be resolved */ - lua_assert(eqstr(gt->name, label->name)); - if (l_unlikely(gt->nactvar < label->nactvar)) /* enter some scope? */ - jumpscopeerror(ls, gt); - luaK_patchlist(ls->fs, gt->pc, label->pc); - for (i = g; i < gl->n - 1; i++) /* remove goto from pending list */ - gl->arr[i] = gl->arr[i + 1]; - gl->n--; -} - - -/* -** Search for an active label with the given name. -*/ -static Labeldesc *findlabel (LexState *ls, TString *name) { - int i; - Dyndata *dyd = ls->dyd; - /* check labels in current function for a match */ - for (i = ls->fs->firstlabel; i < dyd->label.n; i++) { - Labeldesc *lb = &dyd->label.arr[i]; - if (eqstr(lb->name, name)) /* correct label? */ - return lb; - } - return NULL; /* label not found */ -} - - -/* -** Adds a new label/goto in the corresponding list. -*/ -static int newlabelentry (LexState *ls, Labellist *l, TString *name, - int line, int pc) { - int n = l->n; - luaM_growvector(ls->L, l->arr, n, l->size, - Labeldesc, SHRT_MAX, "labels/gotos"); - l->arr[n].name = name; - l->arr[n].line = line; - l->arr[n].nactvar = ls->fs->nactvar; - l->arr[n].close = 0; - l->arr[n].pc = pc; - l->n = n + 1; - return n; -} - - -static int newgotoentry (LexState *ls, TString *name, int line, int pc) { - return newlabelentry(ls, &ls->dyd->gt, name, line, pc); -} - - -/* -** Solves forward jumps. Check whether new label 'lb' matches any -** pending gotos in current block and solves them. Return true -** if any of the gotos need to close upvalues. -*/ -static int solvegotos (LexState *ls, Labeldesc *lb) { - Labellist *gl = &ls->dyd->gt; - int i = ls->fs->bl->firstgoto; - int needsclose = 0; - while (i < gl->n) { - if (eqstr(gl->arr[i].name, lb->name)) { - needsclose |= gl->arr[i].close; - solvegoto(ls, i, lb); /* will remove 'i' from the list */ - } - else - i++; - } - return needsclose; -} - - -/* -** Create a new label with the given 'name' at the given 'line'. -** 'last' tells whether label is the last non-op statement in its -** block. Solves all pending gotos to this new label and adds -** a close instruction if necessary. -** Returns true iff it added a close instruction. -*/ -static int createlabel (LexState *ls, TString *name, int line, - int last) { - FuncState *fs = ls->fs; - Labellist *ll = &ls->dyd->label; - int l = newlabelentry(ls, ll, name, line, luaK_getlabel(fs)); - if (last) { /* label is last no-op statement in the block? */ - /* assume that locals are already out of scope */ - ll->arr[l].nactvar = fs->bl->nactvar; - } - if (solvegotos(ls, &ll->arr[l])) { /* need close? */ - luaK_codeABC(fs, OP_CLOSE, luaY_nvarstack(fs), 0, 0); - return 1; - } - return 0; -} - - -/* -** Adjust pending gotos to outer level of a block. -*/ -static void movegotosout (FuncState *fs, BlockCnt *bl) { - int i; - Labellist *gl = &fs->ls->dyd->gt; - /* correct pending gotos to current block */ - for (i = bl->firstgoto; i < gl->n; i++) { /* for each pending goto */ - Labeldesc *gt = &gl->arr[i]; - /* leaving a variable scope? */ - if (reglevel(fs, gt->nactvar) > reglevel(fs, bl->nactvar)) - gt->close |= bl->upval; /* jump may need a close */ - gt->nactvar = bl->nactvar; /* update goto level */ - } -} - - -static void enterblock (FuncState *fs, BlockCnt *bl, lu_byte isloop) { - bl->isloop = isloop; - bl->nactvar = fs->nactvar; - bl->firstlabel = fs->ls->dyd->label.n; - bl->firstgoto = fs->ls->dyd->gt.n; - bl->upval = 0; - bl->insidetbc = (fs->bl != NULL && fs->bl->insidetbc); - bl->previous = fs->bl; - fs->bl = bl; - lua_assert(fs->freereg == luaY_nvarstack(fs)); -} - - -/* -** generates an error for an undefined 'goto'. -*/ -static l_noret undefgoto (LexState *ls, Labeldesc *gt) { - const char *msg; - if (eqstr(gt->name, luaS_newliteral(ls->L, "break"))) { - msg = "break outside loop at line %d"; - msg = luaO_pushfstring(ls->L, msg, gt->line); - } - else { - msg = "no visible label '%s' for at line %d"; - msg = luaO_pushfstring(ls->L, msg, getstr(gt->name), gt->line); - } - luaK_semerror(ls, msg); -} - - -static void leaveblock (FuncState *fs) { - BlockCnt *bl = fs->bl; - LexState *ls = fs->ls; - int hasclose = 0; - int stklevel = reglevel(fs, bl->nactvar); /* level outside the block */ - removevars(fs, bl->nactvar); /* remove block locals */ - lua_assert(bl->nactvar == fs->nactvar); /* back to level on entry */ - if (bl->isloop) /* has to fix pending breaks? */ - hasclose = createlabel(ls, luaS_newliteral(ls->L, "break"), 0, 0); - if (!hasclose && bl->previous && bl->upval) /* still need a 'close'? */ - luaK_codeABC(fs, OP_CLOSE, stklevel, 0, 0); - fs->freereg = stklevel; /* free registers */ - ls->dyd->label.n = bl->firstlabel; /* remove local labels */ - fs->bl = bl->previous; /* current block now is previous one */ - if (bl->previous) /* was it a nested block? */ - movegotosout(fs, bl); /* update pending gotos to enclosing block */ - else { - if (bl->firstgoto < ls->dyd->gt.n) /* still pending gotos? */ - undefgoto(ls, &ls->dyd->gt.arr[bl->firstgoto]); /* error */ - } -} - - -/* -** adds a new prototype into list of prototypes -*/ -static Proto *addprototype (LexState *ls) { - Proto *clp; - lua_State *L = ls->L; - FuncState *fs = ls->fs; - Proto *f = fs->f; /* prototype of current function */ - if (fs->np >= f->sizep) { - int oldsize = f->sizep; - luaM_growvector(L, f->p, fs->np, f->sizep, Proto *, MAXARG_Bx, "functions"); - while (oldsize < f->sizep) - f->p[oldsize++] = NULL; - } - f->p[fs->np++] = clp = luaF_newproto(L); - luaC_objbarrier(L, f, clp); - return clp; -} - - -/* -** codes instruction to create new closure in parent function. -** The OP_CLOSURE instruction uses the last available register, -** so that, if it invokes the GC, the GC knows which registers -** are in use at that time. - -*/ -static void codeclosure (LexState *ls, expdesc *v) { - FuncState *fs = ls->fs->prev; - init_exp(v, VRELOC, luaK_codeABx(fs, OP_CLOSURE, 0, fs->np - 1)); - luaK_exp2nextreg(fs, v); /* fix it at the last register */ -} - - -static void open_func (LexState *ls, FuncState *fs, BlockCnt *bl) { - Proto *f = fs->f; - fs->prev = ls->fs; /* linked list of funcstates */ - fs->ls = ls; - ls->fs = fs; - fs->pc = 0; - fs->previousline = f->linedefined; - fs->iwthabs = 0; - fs->lasttarget = 0; - fs->freereg = 0; - fs->nk = 0; - fs->nabslineinfo = 0; - fs->np = 0; - fs->nups = 0; - fs->ndebugvars = 0; - fs->nactvar = 0; - fs->needclose = 0; - fs->firstlocal = ls->dyd->actvar.n; - fs->firstlabel = ls->dyd->label.n; - fs->bl = NULL; - f->source = ls->source; - luaC_objbarrier(ls->L, f, f->source); - f->maxstacksize = 2; /* registers 0/1 are always valid */ - enterblock(fs, bl, 0); -} - - -static void close_func (LexState *ls) { - lua_State *L = ls->L; - FuncState *fs = ls->fs; - Proto *f = fs->f; - luaK_ret(fs, luaY_nvarstack(fs), 0); /* final return */ - leaveblock(fs); - lua_assert(fs->bl == NULL); - luaK_finish(fs); - luaM_shrinkvector(L, f->code, f->sizecode, fs->pc, Instruction); - luaM_shrinkvector(L, f->lineinfo, f->sizelineinfo, fs->pc, ls_byte); - luaM_shrinkvector(L, f->abslineinfo, f->sizeabslineinfo, - fs->nabslineinfo, AbsLineInfo); - luaM_shrinkvector(L, f->k, f->sizek, fs->nk, TValue); - luaM_shrinkvector(L, f->p, f->sizep, fs->np, Proto *); - luaM_shrinkvector(L, f->locvars, f->sizelocvars, fs->ndebugvars, LocVar); - luaM_shrinkvector(L, f->upvalues, f->sizeupvalues, fs->nups, Upvaldesc); - ls->fs = fs->prev; - luaC_checkGC(L); -} - - - -/*============================================================*/ -/* GRAMMAR RULES */ -/*============================================================*/ - - -/* -** check whether current token is in the follow set of a block. -** 'until' closes syntactical blocks, but do not close scope, -** so it is handled in separate. -*/ -static int block_follow (LexState *ls, int withuntil) { - switch (ls->t.token) { - case TK_ELSE: case TK_ELSEIF: - case TK_END: case TK_EOS: - return 1; - case TK_UNTIL: return withuntil; - default: return 0; - } -} - - -static void statlist (LexState *ls) { - /* statlist -> { stat [';'] } */ - while (!block_follow(ls, 1)) { - if (ls->t.token == TK_RETURN) { - statement(ls); - return; /* 'return' must be last statement */ - } - statement(ls); - } -} - - -static void fieldsel (LexState *ls, expdesc *v) { - /* fieldsel -> ['.' | ':'] NAME */ - FuncState *fs = ls->fs; - expdesc key; - luaK_exp2anyregup(fs, v); - luaX_next(ls); /* skip the dot or colon */ - codename(ls, &key); - luaK_indexed(fs, v, &key); -} - - -static void yindex (LexState *ls, expdesc *v) { - /* index -> '[' expr ']' */ - luaX_next(ls); /* skip the '[' */ - expr(ls, v); - luaK_exp2val(ls->fs, v); - checknext(ls, ']'); -} - - -/* -** {====================================================================== -** Rules for Constructors -** ======================================================================= -*/ - - -typedef struct ConsControl { - expdesc v; /* last list item read */ - expdesc *t; /* table descriptor */ - int nh; /* total number of 'record' elements */ - int na; /* number of array elements already stored */ - int tostore; /* number of array elements pending to be stored */ -} ConsControl; - - -static void recfield (LexState *ls, ConsControl *cc) { - /* recfield -> (NAME | '['exp']') = exp */ - FuncState *fs = ls->fs; - int reg = ls->fs->freereg; - expdesc tab, key, val; - if (ls->t.token == TK_NAME) { - checklimit(fs, cc->nh, MAX_INT, "items in a constructor"); - codename(ls, &key); - } - else /* ls->t.token == '[' */ - yindex(ls, &key); - cc->nh++; - checknext(ls, '='); - tab = *cc->t; - luaK_indexed(fs, &tab, &key); - expr(ls, &val); - luaK_storevar(fs, &tab, &val); - fs->freereg = reg; /* free registers */ -} - - -static void closelistfield (FuncState *fs, ConsControl *cc) { - if (cc->v.k == VVOID) return; /* there is no list item */ - luaK_exp2nextreg(fs, &cc->v); - cc->v.k = VVOID; - if (cc->tostore == LFIELDS_PER_FLUSH) { - luaK_setlist(fs, cc->t->u.info, cc->na, cc->tostore); /* flush */ - cc->na += cc->tostore; - cc->tostore = 0; /* no more items pending */ - } -} - - -static void lastlistfield (FuncState *fs, ConsControl *cc) { - if (cc->tostore == 0) return; - if (hasmultret(cc->v.k)) { - luaK_setmultret(fs, &cc->v); - luaK_setlist(fs, cc->t->u.info, cc->na, LUA_MULTRET); - cc->na--; /* do not count last expression (unknown number of elements) */ - } - else { - if (cc->v.k != VVOID) - luaK_exp2nextreg(fs, &cc->v); - luaK_setlist(fs, cc->t->u.info, cc->na, cc->tostore); - } - cc->na += cc->tostore; -} - - -static void listfield (LexState *ls, ConsControl *cc) { - /* listfield -> exp */ - expr(ls, &cc->v); - cc->tostore++; -} - - -static void field (LexState *ls, ConsControl *cc) { - /* field -> listfield | recfield */ - switch(ls->t.token) { - case TK_NAME: { /* may be 'listfield' or 'recfield' */ - if (luaX_lookahead(ls) != '=') /* expression? */ - listfield(ls, cc); - else - recfield(ls, cc); - break; - } - case '[': { - recfield(ls, cc); - break; - } - default: { - listfield(ls, cc); - break; - } - } -} - - -static void constructor (LexState *ls, expdesc *t) { - /* constructor -> '{' [ field { sep field } [sep] ] '}' - sep -> ',' | ';' */ - FuncState *fs = ls->fs; - int line = ls->linenumber; - int pc = luaK_codeABC(fs, OP_NEWTABLE, 0, 0, 0); - ConsControl cc; - luaK_code(fs, 0); /* space for extra arg. */ - cc.na = cc.nh = cc.tostore = 0; - cc.t = t; - init_exp(t, VNONRELOC, fs->freereg); /* table will be at stack top */ - luaK_reserveregs(fs, 1); - init_exp(&cc.v, VVOID, 0); /* no value (yet) */ - checknext(ls, '{'); - do { - lua_assert(cc.v.k == VVOID || cc.tostore > 0); - if (ls->t.token == '}') break; - closelistfield(fs, &cc); - field(ls, &cc); - } while (testnext(ls, ',') || testnext(ls, ';')); - check_match(ls, '}', '{', line); - lastlistfield(fs, &cc); - luaK_settablesize(fs, pc, t->u.info, cc.na, cc.nh); -} - -/* }====================================================================== */ - - -static void setvararg (FuncState *fs, int nparams) { - fs->f->is_vararg = 1; - luaK_codeABC(fs, OP_VARARGPREP, nparams, 0, 0); -} - - -static void parlist (LexState *ls) { - /* parlist -> [ {NAME ','} (NAME | '...') ] */ - FuncState *fs = ls->fs; - Proto *f = fs->f; - int nparams = 0; - int isvararg = 0; - if (ls->t.token != ')') { /* is 'parlist' not empty? */ - do { - switch (ls->t.token) { - case TK_NAME: { - new_localvar(ls, str_checkname(ls)); - nparams++; - break; - } - case TK_DOTS: { - luaX_next(ls); - isvararg = 1; - break; - } - default: luaX_syntaxerror(ls, " or '...' expected"); - } - } while (!isvararg && testnext(ls, ',')); - } - adjustlocalvars(ls, nparams); - f->numparams = cast_byte(fs->nactvar); - if (isvararg) - setvararg(fs, f->numparams); /* declared vararg */ - luaK_reserveregs(fs, fs->nactvar); /* reserve registers for parameters */ -} - - -static void body (LexState *ls, expdesc *e, int ismethod, int line) { - /* body -> '(' parlist ')' block END */ - FuncState new_fs; - BlockCnt bl; - new_fs.f = addprototype(ls); - new_fs.f->linedefined = line; - open_func(ls, &new_fs, &bl); - checknext(ls, '('); - if (ismethod) { - new_localvarliteral(ls, "self"); /* create 'self' parameter */ - adjustlocalvars(ls, 1); - } - parlist(ls); - checknext(ls, ')'); - statlist(ls); - new_fs.f->lastlinedefined = ls->linenumber; - check_match(ls, TK_END, TK_FUNCTION, line); - codeclosure(ls, e); - close_func(ls); -} - - -static int explist (LexState *ls, expdesc *v) { - /* explist -> expr { ',' expr } */ - int n = 1; /* at least one expression */ - expr(ls, v); - while (testnext(ls, ',')) { - luaK_exp2nextreg(ls->fs, v); - expr(ls, v); - n++; - } - return n; -} - - -static void funcargs (LexState *ls, expdesc *f, int line) { - FuncState *fs = ls->fs; - expdesc args; - int base, nparams; - switch (ls->t.token) { - case '(': { /* funcargs -> '(' [ explist ] ')' */ - luaX_next(ls); - if (ls->t.token == ')') /* arg list is empty? */ - args.k = VVOID; - else { - explist(ls, &args); - if (hasmultret(args.k)) - luaK_setmultret(fs, &args); - } - check_match(ls, ')', '(', line); - break; - } - case '{': { /* funcargs -> constructor */ - constructor(ls, &args); - break; - } - case TK_STRING: { /* funcargs -> STRING */ - codestring(&args, ls->t.seminfo.ts); - luaX_next(ls); /* must use 'seminfo' before 'next' */ - break; - } - default: { - luaX_syntaxerror(ls, "function arguments expected"); - } - } - lua_assert(f->k == VNONRELOC); - base = f->u.info; /* base register for call */ - if (hasmultret(args.k)) - nparams = LUA_MULTRET; /* open call */ - else { - if (args.k != VVOID) - luaK_exp2nextreg(fs, &args); /* close last argument */ - nparams = fs->freereg - (base+1); - } - init_exp(f, VCALL, luaK_codeABC(fs, OP_CALL, base, nparams+1, 2)); - luaK_fixline(fs, line); - fs->freereg = base+1; /* call remove function and arguments and leaves - (unless changed) one result */ -} - - - - -/* -** {====================================================================== -** Expression parsing -** ======================================================================= -*/ - - -static void primaryexp (LexState *ls, expdesc *v) { - /* primaryexp -> NAME | '(' expr ')' */ - switch (ls->t.token) { - case '(': { - int line = ls->linenumber; - luaX_next(ls); - expr(ls, v); - check_match(ls, ')', '(', line); - luaK_dischargevars(ls->fs, v); - return; - } - case TK_NAME: { - singlevar(ls, v); - return; - } - default: { - luaX_syntaxerror(ls, "unexpected symbol"); - } - } -} - - -static void suffixedexp (LexState *ls, expdesc *v) { - /* suffixedexp -> - primaryexp { '.' NAME | '[' exp ']' | ':' NAME funcargs | funcargs } */ - FuncState *fs = ls->fs; - int line = ls->linenumber; - primaryexp(ls, v); - for (;;) { - switch (ls->t.token) { - case '.': { /* fieldsel */ - fieldsel(ls, v); - break; - } - case '[': { /* '[' exp ']' */ - expdesc key; - luaK_exp2anyregup(fs, v); - yindex(ls, &key); - luaK_indexed(fs, v, &key); - break; - } - case ':': { /* ':' NAME funcargs */ - expdesc key; - luaX_next(ls); - codename(ls, &key); - luaK_self(fs, v, &key); - funcargs(ls, v, line); - break; - } - case '(': case TK_STRING: case '{': { /* funcargs */ - luaK_exp2nextreg(fs, v); - funcargs(ls, v, line); - break; - } - default: return; - } - } -} - - -static void simpleexp (LexState *ls, expdesc *v) { - /* simpleexp -> FLT | INT | STRING | NIL | TRUE | FALSE | ... | - constructor | FUNCTION body | suffixedexp */ - switch (ls->t.token) { - case TK_FLT: { - init_exp(v, VKFLT, 0); - v->u.nval = ls->t.seminfo.r; - break; - } - case TK_INT: { - init_exp(v, VKINT, 0); - v->u.ival = ls->t.seminfo.i; - break; - } - case TK_STRING: { - codestring(v, ls->t.seminfo.ts); - break; - } - case TK_NIL: { - init_exp(v, VNIL, 0); - break; - } - case TK_TRUE: { - init_exp(v, VTRUE, 0); - break; - } - case TK_FALSE: { - init_exp(v, VFALSE, 0); - break; - } - case TK_DOTS: { /* vararg */ - FuncState *fs = ls->fs; - check_condition(ls, fs->f->is_vararg, - "cannot use '...' outside a vararg function"); - init_exp(v, VVARARG, luaK_codeABC(fs, OP_VARARG, 0, 0, 1)); - break; - } - case '{': { /* constructor */ - constructor(ls, v); - return; - } - case TK_FUNCTION: { - luaX_next(ls); - body(ls, v, 0, ls->linenumber); - return; - } - default: { - suffixedexp(ls, v); - return; - } - } - luaX_next(ls); -} - - -static UnOpr getunopr (int op) { - switch (op) { - case TK_NOT: return OPR_NOT; - case '-': return OPR_MINUS; - case '~': return OPR_BNOT; - case '#': return OPR_LEN; - default: return OPR_NOUNOPR; - } -} - - -static BinOpr getbinopr (int op) { - switch (op) { - case '+': return OPR_ADD; - case '-': return OPR_SUB; - case '*': return OPR_MUL; - case '%': return OPR_MOD; - case '^': return OPR_POW; - case '/': return OPR_DIV; - case TK_IDIV: return OPR_IDIV; - case '&': return OPR_BAND; - case '|': return OPR_BOR; - case '~': return OPR_BXOR; - case TK_SHL: return OPR_SHL; - case TK_SHR: return OPR_SHR; - case TK_CONCAT: return OPR_CONCAT; - case TK_NE: return OPR_NE; - case TK_EQ: return OPR_EQ; - case '<': return OPR_LT; - case TK_LE: return OPR_LE; - case '>': return OPR_GT; - case TK_GE: return OPR_GE; - case TK_AND: return OPR_AND; - case TK_OR: return OPR_OR; - default: return OPR_NOBINOPR; - } -} - - -/* -** Priority table for binary operators. -*/ -static const struct { - lu_byte left; /* left priority for each binary operator */ - lu_byte right; /* right priority */ -} priority[] = { /* ORDER OPR */ - {10, 10}, {10, 10}, /* '+' '-' */ - {11, 11}, {11, 11}, /* '*' '%' */ - {14, 13}, /* '^' (right associative) */ - {11, 11}, {11, 11}, /* '/' '//' */ - {6, 6}, {4, 4}, {5, 5}, /* '&' '|' '~' */ - {7, 7}, {7, 7}, /* '<<' '>>' */ - {9, 8}, /* '..' (right associative) */ - {3, 3}, {3, 3}, {3, 3}, /* ==, <, <= */ - {3, 3}, {3, 3}, {3, 3}, /* ~=, >, >= */ - {2, 2}, {1, 1} /* and, or */ -}; - -#define UNARY_PRIORITY 12 /* priority for unary operators */ - - -/* -** subexpr -> (simpleexp | unop subexpr) { binop subexpr } -** where 'binop' is any binary operator with a priority higher than 'limit' -*/ -static BinOpr subexpr (LexState *ls, expdesc *v, int limit) { - BinOpr op; - UnOpr uop; - enterlevel(ls); - uop = getunopr(ls->t.token); - if (uop != OPR_NOUNOPR) { /* prefix (unary) operator? */ - int line = ls->linenumber; - luaX_next(ls); /* skip operator */ - subexpr(ls, v, UNARY_PRIORITY); - luaK_prefix(ls->fs, uop, v, line); - } - else simpleexp(ls, v); - /* expand while operators have priorities higher than 'limit' */ - op = getbinopr(ls->t.token); - while (op != OPR_NOBINOPR && priority[op].left > limit) { - expdesc v2; - BinOpr nextop; - int line = ls->linenumber; - luaX_next(ls); /* skip operator */ - luaK_infix(ls->fs, op, v); - /* read sub-expression with higher priority */ - nextop = subexpr(ls, &v2, priority[op].right); - luaK_posfix(ls->fs, op, v, &v2, line); - op = nextop; - } - leavelevel(ls); - return op; /* return first untreated operator */ -} - - -static void expr (LexState *ls, expdesc *v) { - subexpr(ls, v, 0); -} - -/* }==================================================================== */ - - - -/* -** {====================================================================== -** Rules for Statements -** ======================================================================= -*/ - - -static void block (LexState *ls) { - /* block -> statlist */ - FuncState *fs = ls->fs; - BlockCnt bl; - enterblock(fs, &bl, 0); - statlist(ls); - leaveblock(fs); -} - - -/* -** structure to chain all variables in the left-hand side of an -** assignment -*/ -struct LHS_assign { - struct LHS_assign *prev; - expdesc v; /* variable (global, local, upvalue, or indexed) */ -}; - - -/* -** check whether, in an assignment to an upvalue/local variable, the -** upvalue/local variable is begin used in a previous assignment to a -** table. If so, save original upvalue/local value in a safe place and -** use this safe copy in the previous assignment. -*/ -static void check_conflict (LexState *ls, struct LHS_assign *lh, expdesc *v) { - FuncState *fs = ls->fs; - int extra = fs->freereg; /* eventual position to save local variable */ - int conflict = 0; - for (; lh; lh = lh->prev) { /* check all previous assignments */ - if (vkisindexed(lh->v.k)) { /* assignment to table field? */ - if (lh->v.k == VINDEXUP) { /* is table an upvalue? */ - if (v->k == VUPVAL && lh->v.u.ind.t == v->u.info) { - conflict = 1; /* table is the upvalue being assigned now */ - lh->v.k = VINDEXSTR; - lh->v.u.ind.t = extra; /* assignment will use safe copy */ - } - } - else { /* table is a register */ - if (v->k == VLOCAL && lh->v.u.ind.t == v->u.var.ridx) { - conflict = 1; /* table is the local being assigned now */ - lh->v.u.ind.t = extra; /* assignment will use safe copy */ - } - /* is index the local being assigned? */ - if (lh->v.k == VINDEXED && v->k == VLOCAL && - lh->v.u.ind.idx == v->u.var.ridx) { - conflict = 1; - lh->v.u.ind.idx = extra; /* previous assignment will use safe copy */ - } - } - } - } - if (conflict) { - /* copy upvalue/local value to a temporary (in position 'extra') */ - if (v->k == VLOCAL) - luaK_codeABC(fs, OP_MOVE, extra, v->u.var.ridx, 0); - else - luaK_codeABC(fs, OP_GETUPVAL, extra, v->u.info, 0); - luaK_reserveregs(fs, 1); - } -} - -/* -** Parse and compile a multiple assignment. The first "variable" -** (a 'suffixedexp') was already read by the caller. -** -** assignment -> suffixedexp restassign -** restassign -> ',' suffixedexp restassign | '=' explist -*/ -static void restassign (LexState *ls, struct LHS_assign *lh, int nvars) { - expdesc e; - check_condition(ls, vkisvar(lh->v.k), "syntax error"); - check_readonly(ls, &lh->v); - if (testnext(ls, ',')) { /* restassign -> ',' suffixedexp restassign */ - struct LHS_assign nv; - nv.prev = lh; - suffixedexp(ls, &nv.v); - if (!vkisindexed(nv.v.k)) - check_conflict(ls, lh, &nv.v); - enterlevel(ls); /* control recursion depth */ - restassign(ls, &nv, nvars+1); - leavelevel(ls); - } - else { /* restassign -> '=' explist */ - int nexps; - checknext(ls, '='); - nexps = explist(ls, &e); - if (nexps != nvars) - adjust_assign(ls, nvars, nexps, &e); - else { - luaK_setoneret(ls->fs, &e); /* close last expression */ - luaK_storevar(ls->fs, &lh->v, &e); - return; /* avoid default */ - } - } - init_exp(&e, VNONRELOC, ls->fs->freereg-1); /* default assignment */ - luaK_storevar(ls->fs, &lh->v, &e); -} - - -static int cond (LexState *ls) { - /* cond -> exp */ - expdesc v; - expr(ls, &v); /* read condition */ - if (v.k == VNIL) v.k = VFALSE; /* 'falses' are all equal here */ - luaK_goiftrue(ls->fs, &v); - return v.f; -} - - -static void gotostat (LexState *ls) { - FuncState *fs = ls->fs; - int line = ls->linenumber; - TString *name = str_checkname(ls); /* label's name */ - Labeldesc *lb = findlabel(ls, name); - if (lb == NULL) /* no label? */ - /* forward jump; will be resolved when the label is declared */ - newgotoentry(ls, name, line, luaK_jump(fs)); - else { /* found a label */ - /* backward jump; will be resolved here */ - int lblevel = reglevel(fs, lb->nactvar); /* label level */ - if (luaY_nvarstack(fs) > lblevel) /* leaving the scope of a variable? */ - luaK_codeABC(fs, OP_CLOSE, lblevel, 0, 0); - /* create jump and link it to the label */ - luaK_patchlist(fs, luaK_jump(fs), lb->pc); - } -} - - -/* -** Break statement. Semantically equivalent to "goto break". -*/ -static void breakstat (LexState *ls) { - int line = ls->linenumber; - luaX_next(ls); /* skip break */ - newgotoentry(ls, luaS_newliteral(ls->L, "break"), line, luaK_jump(ls->fs)); -} - - -/* -** Check whether there is already a label with the given 'name'. -*/ -static void checkrepeated (LexState *ls, TString *name) { - Labeldesc *lb = findlabel(ls, name); - if (l_unlikely(lb != NULL)) { /* already defined? */ - const char *msg = "label '%s' already defined on line %d"; - msg = luaO_pushfstring(ls->L, msg, getstr(name), lb->line); - luaK_semerror(ls, msg); /* error */ - } -} - - -static void labelstat (LexState *ls, TString *name, int line) { - /* label -> '::' NAME '::' */ - checknext(ls, TK_DBCOLON); /* skip double colon */ - while (ls->t.token == ';' || ls->t.token == TK_DBCOLON) - statement(ls); /* skip other no-op statements */ - checkrepeated(ls, name); /* check for repeated labels */ - createlabel(ls, name, line, block_follow(ls, 0)); -} - - -static void whilestat (LexState *ls, int line) { - /* whilestat -> WHILE cond DO block END */ - FuncState *fs = ls->fs; - int whileinit; - int condexit; - BlockCnt bl; - luaX_next(ls); /* skip WHILE */ - whileinit = luaK_getlabel(fs); - condexit = cond(ls); - enterblock(fs, &bl, 1); - checknext(ls, TK_DO); - block(ls); - luaK_jumpto(fs, whileinit); - check_match(ls, TK_END, TK_WHILE, line); - leaveblock(fs); - luaK_patchtohere(fs, condexit); /* false conditions finish the loop */ -} - - -static void repeatstat (LexState *ls, int line) { - /* repeatstat -> REPEAT block UNTIL cond */ - int condexit; - FuncState *fs = ls->fs; - int repeat_init = luaK_getlabel(fs); - BlockCnt bl1, bl2; - enterblock(fs, &bl1, 1); /* loop block */ - enterblock(fs, &bl2, 0); /* scope block */ - luaX_next(ls); /* skip REPEAT */ - statlist(ls); - check_match(ls, TK_UNTIL, TK_REPEAT, line); - condexit = cond(ls); /* read condition (inside scope block) */ - leaveblock(fs); /* finish scope */ - if (bl2.upval) { /* upvalues? */ - int exit = luaK_jump(fs); /* normal exit must jump over fix */ - luaK_patchtohere(fs, condexit); /* repetition must close upvalues */ - luaK_codeABC(fs, OP_CLOSE, reglevel(fs, bl2.nactvar), 0, 0); - condexit = luaK_jump(fs); /* repeat after closing upvalues */ - luaK_patchtohere(fs, exit); /* normal exit comes to here */ - } - luaK_patchlist(fs, condexit, repeat_init); /* close the loop */ - leaveblock(fs); /* finish loop */ -} - - -/* -** Read an expression and generate code to put its results in next -** stack slot. -** -*/ -static void exp1 (LexState *ls) { - expdesc e; - expr(ls, &e); - luaK_exp2nextreg(ls->fs, &e); - lua_assert(e.k == VNONRELOC); -} - - -/* -** Fix for instruction at position 'pc' to jump to 'dest'. -** (Jump addresses are relative in Lua). 'back' true means -** a back jump. -*/ -static void fixforjump (FuncState *fs, int pc, int dest, int back) { - Instruction *jmp = &fs->f->code[pc]; - int offset = dest - (pc + 1); - if (back) - offset = -offset; - if (l_unlikely(offset > MAXARG_Bx)) - luaX_syntaxerror(fs->ls, "control structure too long"); - SETARG_Bx(*jmp, offset); -} - - -/* -** Generate code for a 'for' loop. -*/ -static void forbody (LexState *ls, int base, int line, int nvars, int isgen) { - /* forbody -> DO block */ - static const OpCode forprep[2] = {OP_FORPREP, OP_TFORPREP}; - static const OpCode forloop[2] = {OP_FORLOOP, OP_TFORLOOP}; - BlockCnt bl; - FuncState *fs = ls->fs; - int prep, endfor; - checknext(ls, TK_DO); - prep = luaK_codeABx(fs, forprep[isgen], base, 0); - enterblock(fs, &bl, 0); /* scope for declared variables */ - adjustlocalvars(ls, nvars); - luaK_reserveregs(fs, nvars); - block(ls); - leaveblock(fs); /* end of scope for declared variables */ - fixforjump(fs, prep, luaK_getlabel(fs), 0); - if (isgen) { /* generic for? */ - luaK_codeABC(fs, OP_TFORCALL, base, 0, nvars); - luaK_fixline(fs, line); - } - endfor = luaK_codeABx(fs, forloop[isgen], base, 0); - fixforjump(fs, endfor, prep + 1, 1); - luaK_fixline(fs, line); -} - - -static void fornum (LexState *ls, TString *varname, int line) { - /* fornum -> NAME = exp,exp[,exp] forbody */ - FuncState *fs = ls->fs; - int base = fs->freereg; - new_localvarliteral(ls, "(for state)"); - new_localvarliteral(ls, "(for state)"); - new_localvarliteral(ls, "(for state)"); - new_localvar(ls, varname); - checknext(ls, '='); - exp1(ls); /* initial value */ - checknext(ls, ','); - exp1(ls); /* limit */ - if (testnext(ls, ',')) - exp1(ls); /* optional step */ - else { /* default step = 1 */ - luaK_int(fs, fs->freereg, 1); - luaK_reserveregs(fs, 1); - } - adjustlocalvars(ls, 3); /* control variables */ - forbody(ls, base, line, 1, 0); -} - - -static void forlist (LexState *ls, TString *indexname) { - /* forlist -> NAME {,NAME} IN explist forbody */ - FuncState *fs = ls->fs; - expdesc e; - int nvars = 5; /* gen, state, control, toclose, 'indexname' */ - int line; - int base = fs->freereg; - /* create control variables */ - new_localvarliteral(ls, "(for state)"); - new_localvarliteral(ls, "(for state)"); - new_localvarliteral(ls, "(for state)"); - new_localvarliteral(ls, "(for state)"); - /* create declared variables */ - new_localvar(ls, indexname); - while (testnext(ls, ',')) { - new_localvar(ls, str_checkname(ls)); - nvars++; - } - checknext(ls, TK_IN); - line = ls->linenumber; - adjust_assign(ls, 4, explist(ls, &e), &e); - adjustlocalvars(ls, 4); /* control variables */ - marktobeclosed(fs); /* last control var. must be closed */ - luaK_checkstack(fs, 3); /* extra space to call generator */ - forbody(ls, base, line, nvars - 4, 1); -} - - -static void forstat (LexState *ls, int line) { - /* forstat -> FOR (fornum | forlist) END */ - FuncState *fs = ls->fs; - TString *varname; - BlockCnt bl; - enterblock(fs, &bl, 1); /* scope for loop and control variables */ - luaX_next(ls); /* skip 'for' */ - varname = str_checkname(ls); /* first variable name */ - switch (ls->t.token) { - case '=': fornum(ls, varname, line); break; - case ',': case TK_IN: forlist(ls, varname); break; - default: luaX_syntaxerror(ls, "'=' or 'in' expected"); - } - check_match(ls, TK_END, TK_FOR, line); - leaveblock(fs); /* loop scope ('break' jumps to this point) */ -} - - -static void test_then_block (LexState *ls, int *escapelist) { - /* test_then_block -> [IF | ELSEIF] cond THEN block */ - BlockCnt bl; - FuncState *fs = ls->fs; - expdesc v; - int jf; /* instruction to skip 'then' code (if condition is false) */ - luaX_next(ls); /* skip IF or ELSEIF */ - expr(ls, &v); /* read condition */ - checknext(ls, TK_THEN); - if (ls->t.token == TK_BREAK) { /* 'if x then break' ? */ - int line = ls->linenumber; - luaK_goiffalse(ls->fs, &v); /* will jump if condition is true */ - luaX_next(ls); /* skip 'break' */ - enterblock(fs, &bl, 0); /* must enter block before 'goto' */ - newgotoentry(ls, luaS_newliteral(ls->L, "break"), line, v.t); - while (testnext(ls, ';')) {} /* skip semicolons */ - if (block_follow(ls, 0)) { /* jump is the entire block? */ - leaveblock(fs); - return; /* and that is it */ - } - else /* must skip over 'then' part if condition is false */ - jf = luaK_jump(fs); - } - else { /* regular case (not a break) */ - luaK_goiftrue(ls->fs, &v); /* skip over block if condition is false */ - enterblock(fs, &bl, 0); - jf = v.f; - } - statlist(ls); /* 'then' part */ - leaveblock(fs); - if (ls->t.token == TK_ELSE || - ls->t.token == TK_ELSEIF) /* followed by 'else'/'elseif'? */ - luaK_concat(fs, escapelist, luaK_jump(fs)); /* must jump over it */ - luaK_patchtohere(fs, jf); -} - - -static void ifstat (LexState *ls, int line) { - /* ifstat -> IF cond THEN block {ELSEIF cond THEN block} [ELSE block] END */ - FuncState *fs = ls->fs; - int escapelist = NO_JUMP; /* exit list for finished parts */ - test_then_block(ls, &escapelist); /* IF cond THEN block */ - while (ls->t.token == TK_ELSEIF) - test_then_block(ls, &escapelist); /* ELSEIF cond THEN block */ - if (testnext(ls, TK_ELSE)) - block(ls); /* 'else' part */ - check_match(ls, TK_END, TK_IF, line); - luaK_patchtohere(fs, escapelist); /* patch escape list to 'if' end */ -} - - -static void localfunc (LexState *ls) { - expdesc b; - FuncState *fs = ls->fs; - int fvar = fs->nactvar; /* function's variable index */ - new_localvar(ls, str_checkname(ls)); /* new local variable */ - adjustlocalvars(ls, 1); /* enter its scope */ - body(ls, &b, 0, ls->linenumber); /* function created in next register */ - /* debug information will only see the variable after this point! */ - localdebuginfo(fs, fvar)->startpc = fs->pc; -} - - -static int getlocalattribute (LexState *ls) { - /* ATTRIB -> ['<' Name '>'] */ - if (testnext(ls, '<')) { - const char *attr = getstr(str_checkname(ls)); - checknext(ls, '>'); - if (strcmp(attr, "const") == 0) - return RDKCONST; /* read-only variable */ - else if (strcmp(attr, "close") == 0) - return RDKTOCLOSE; /* to-be-closed variable */ - else - luaK_semerror(ls, - luaO_pushfstring(ls->L, "unknown attribute '%s'", attr)); - } - return VDKREG; /* regular variable */ -} - - -static void checktoclose (FuncState *fs, int level) { - if (level != -1) { /* is there a to-be-closed variable? */ - marktobeclosed(fs); - luaK_codeABC(fs, OP_TBC, reglevel(fs, level), 0, 0); - } -} - - -static void localstat (LexState *ls) { - /* stat -> LOCAL NAME ATTRIB { ',' NAME ATTRIB } ['=' explist] */ - FuncState *fs = ls->fs; - int toclose = -1; /* index of to-be-closed variable (if any) */ - Vardesc *var; /* last variable */ - int vidx, kind; /* index and kind of last variable */ - int nvars = 0; - int nexps; - expdesc e; - do { - vidx = new_localvar(ls, str_checkname(ls)); - kind = getlocalattribute(ls); - getlocalvardesc(fs, vidx)->vd.kind = kind; - if (kind == RDKTOCLOSE) { /* to-be-closed? */ - if (toclose != -1) /* one already present? */ - luaK_semerror(ls, "multiple to-be-closed variables in local list"); - toclose = fs->nactvar + nvars; - } - nvars++; - } while (testnext(ls, ',')); - if (testnext(ls, '=')) - nexps = explist(ls, &e); - else { - e.k = VVOID; - nexps = 0; - } - var = getlocalvardesc(fs, vidx); /* get last variable */ - if (nvars == nexps && /* no adjustments? */ - var->vd.kind == RDKCONST && /* last variable is const? */ - luaK_exp2const(fs, &e, &var->k)) { /* compile-time constant? */ - var->vd.kind = RDKCTC; /* variable is a compile-time constant */ - adjustlocalvars(ls, nvars - 1); /* exclude last variable */ - fs->nactvar++; /* but count it */ - } - else { - adjust_assign(ls, nvars, nexps, &e); - adjustlocalvars(ls, nvars); - } - checktoclose(fs, toclose); -} - - -static int funcname (LexState *ls, expdesc *v) { - /* funcname -> NAME {fieldsel} [':' NAME] */ - int ismethod = 0; - singlevar(ls, v); - while (ls->t.token == '.') - fieldsel(ls, v); - if (ls->t.token == ':') { - ismethod = 1; - fieldsel(ls, v); - } - return ismethod; -} - - -static void funcstat (LexState *ls, int line) { - /* funcstat -> FUNCTION funcname body */ - int ismethod; - expdesc v, b; - luaX_next(ls); /* skip FUNCTION */ - ismethod = funcname(ls, &v); - body(ls, &b, ismethod, line); - check_readonly(ls, &v); - luaK_storevar(ls->fs, &v, &b); - luaK_fixline(ls->fs, line); /* definition "happens" in the first line */ -} - - -static void exprstat (LexState *ls) { - /* stat -> func | assignment */ - FuncState *fs = ls->fs; - struct LHS_assign v; - suffixedexp(ls, &v.v); - if (ls->t.token == '=' || ls->t.token == ',') { /* stat -> assignment ? */ - v.prev = NULL; - restassign(ls, &v, 1); - } - else { /* stat -> func */ - Instruction *inst; - check_condition(ls, v.v.k == VCALL, "syntax error"); - inst = &getinstruction(fs, &v.v); - SETARG_C(*inst, 1); /* call statement uses no results */ - } -} - - -static void retstat (LexState *ls) { - /* stat -> RETURN [explist] [';'] */ - FuncState *fs = ls->fs; - expdesc e; - int nret; /* number of values being returned */ - int first = luaY_nvarstack(fs); /* first slot to be returned */ - if (block_follow(ls, 1) || ls->t.token == ';') - nret = 0; /* return no values */ - else { - nret = explist(ls, &e); /* optional return values */ - if (hasmultret(e.k)) { - luaK_setmultret(fs, &e); - if (e.k == VCALL && nret == 1 && !fs->bl->insidetbc) { /* tail call? */ - SET_OPCODE(getinstruction(fs,&e), OP_TAILCALL); - lua_assert(GETARG_A(getinstruction(fs,&e)) == luaY_nvarstack(fs)); - } - nret = LUA_MULTRET; /* return all values */ - } - else { - if (nret == 1) /* only one single value? */ - first = luaK_exp2anyreg(fs, &e); /* can use original slot */ - else { /* values must go to the top of the stack */ - luaK_exp2nextreg(fs, &e); - lua_assert(nret == fs->freereg - first); - } - } - } - luaK_ret(fs, first, nret); - testnext(ls, ';'); /* skip optional semicolon */ -} - - -static void statement (LexState *ls) { - int line = ls->linenumber; /* may be needed for error messages */ - enterlevel(ls); - switch (ls->t.token) { - case ';': { /* stat -> ';' (empty statement) */ - luaX_next(ls); /* skip ';' */ - break; - } - case TK_IF: { /* stat -> ifstat */ - ifstat(ls, line); - break; - } - case TK_WHILE: { /* stat -> whilestat */ - whilestat(ls, line); - break; - } - case TK_DO: { /* stat -> DO block END */ - luaX_next(ls); /* skip DO */ - block(ls); - check_match(ls, TK_END, TK_DO, line); - break; - } - case TK_FOR: { /* stat -> forstat */ - forstat(ls, line); - break; - } - case TK_REPEAT: { /* stat -> repeatstat */ - repeatstat(ls, line); - break; - } - case TK_FUNCTION: { /* stat -> funcstat */ - funcstat(ls, line); - break; - } - case TK_LOCAL: { /* stat -> localstat */ - luaX_next(ls); /* skip LOCAL */ - if (testnext(ls, TK_FUNCTION)) /* local function? */ - localfunc(ls); - else - localstat(ls); - break; - } - case TK_DBCOLON: { /* stat -> label */ - luaX_next(ls); /* skip double colon */ - labelstat(ls, str_checkname(ls), line); - break; - } - case TK_RETURN: { /* stat -> retstat */ - luaX_next(ls); /* skip RETURN */ - retstat(ls); - break; - } - case TK_BREAK: { /* stat -> breakstat */ - breakstat(ls); - break; - } - case TK_GOTO: { /* stat -> 'goto' NAME */ - luaX_next(ls); /* skip 'goto' */ - gotostat(ls); - break; - } - default: { /* stat -> func | assignment */ - exprstat(ls); - break; - } - } - lua_assert(ls->fs->f->maxstacksize >= ls->fs->freereg && - ls->fs->freereg >= luaY_nvarstack(ls->fs)); - ls->fs->freereg = luaY_nvarstack(ls->fs); /* free registers */ - leavelevel(ls); -} - -/* }====================================================================== */ - - -/* -** compiles the main function, which is a regular vararg function with an -** upvalue named LUA_ENV -*/ -static void mainfunc (LexState *ls, FuncState *fs) { - BlockCnt bl; - Upvaldesc *env; - open_func(ls, fs, &bl); - setvararg(fs, 0); /* main function is always declared vararg */ - env = allocupvalue(fs); /* ...set environment upvalue */ - env->instack = 1; - env->idx = 0; - env->kind = VDKREG; - env->name = ls->envn; - luaC_objbarrier(ls->L, fs->f, env->name); - luaX_next(ls); /* read first token */ - statlist(ls); /* parse main body */ - check(ls, TK_EOS); - close_func(ls); -} - - -LClosure *luaY_parser (lua_State *L, ZIO *z, Mbuffer *buff, - Dyndata *dyd, const char *name, int firstchar) { - LexState lexstate; - FuncState funcstate; - LClosure *cl = luaF_newLclosure(L, 1); /* create main closure */ - setclLvalue2s(L, L->top.p, cl); /* anchor it (to avoid being collected) */ - luaD_inctop(L); - lexstate.h = luaH_new(L); /* create table for scanner */ - sethvalue2s(L, L->top.p, lexstate.h); /* anchor it */ - luaD_inctop(L); - funcstate.f = cl->p = luaF_newproto(L); - luaC_objbarrier(L, cl, cl->p); - funcstate.f->source = luaS_new(L, name); /* create and anchor TString */ - luaC_objbarrier(L, funcstate.f, funcstate.f->source); - lexstate.buff = buff; - lexstate.dyd = dyd; - dyd->actvar.n = dyd->gt.n = dyd->label.n = 0; - luaX_setinput(L, &lexstate, z, funcstate.f->source, firstchar); - mainfunc(&lexstate, &funcstate); - lua_assert(!funcstate.prev && funcstate.nups == 1 && !lexstate.fs); - /* all scopes should be correctly finished */ - lua_assert(dyd->actvar.n == 0 && dyd->gt.n == 0 && dyd->label.n == 0); - L->top.p--; /* remove scanner's table */ - return cl; /* closure is on the stack, too */ -} - diff --git a/lib/lua-5.4/src/lparser.h b/lib/lua-5.4/src/lparser.h deleted file mode 100644 index 5e4500f..0000000 --- a/lib/lua-5.4/src/lparser.h +++ /dev/null @@ -1,171 +0,0 @@ -/* -** $Id: lparser.h $ -** Lua Parser -** See Copyright Notice in lua.h -*/ - -#ifndef lparser_h -#define lparser_h - -#include "llimits.h" -#include "lobject.h" -#include "lzio.h" - - -/* -** Expression and variable descriptor. -** Code generation for variables and expressions can be delayed to allow -** optimizations; An 'expdesc' structure describes a potentially-delayed -** variable/expression. It has a description of its "main" value plus a -** list of conditional jumps that can also produce its value (generated -** by short-circuit operators 'and'/'or'). -*/ - -/* kinds of variables/expressions */ -typedef enum { - VVOID, /* when 'expdesc' describes the last expression of a list, - this kind means an empty list (so, no expression) */ - VNIL, /* constant nil */ - VTRUE, /* constant true */ - VFALSE, /* constant false */ - VK, /* constant in 'k'; info = index of constant in 'k' */ - VKFLT, /* floating constant; nval = numerical float value */ - VKINT, /* integer constant; ival = numerical integer value */ - VKSTR, /* string constant; strval = TString address; - (string is fixed by the lexer) */ - VNONRELOC, /* expression has its value in a fixed register; - info = result register */ - VLOCAL, /* local variable; var.ridx = register index; - var.vidx = relative index in 'actvar.arr' */ - VUPVAL, /* upvalue variable; info = index of upvalue in 'upvalues' */ - VCONST, /* compile-time variable; - info = absolute index in 'actvar.arr' */ - VINDEXED, /* indexed variable; - ind.t = table register; - ind.idx = key's R index */ - VINDEXUP, /* indexed upvalue; - ind.t = table upvalue; - ind.idx = key's K index */ - VINDEXI, /* indexed variable with constant integer; - ind.t = table register; - ind.idx = key's value */ - VINDEXSTR, /* indexed variable with literal string; - ind.t = table register; - ind.idx = key's K index */ - VJMP, /* expression is a test/comparison; - info = pc of corresponding jump instruction */ - VRELOC, /* expression can put result in any register; - info = instruction pc */ - VCALL, /* expression is a function call; info = instruction pc */ - VVARARG /* vararg expression; info = instruction pc */ -} expkind; - - -#define vkisvar(k) (VLOCAL <= (k) && (k) <= VINDEXSTR) -#define vkisindexed(k) (VINDEXED <= (k) && (k) <= VINDEXSTR) - - -typedef struct expdesc { - expkind k; - union { - lua_Integer ival; /* for VKINT */ - lua_Number nval; /* for VKFLT */ - TString *strval; /* for VKSTR */ - int info; /* for generic use */ - struct { /* for indexed variables */ - short idx; /* index (R or "long" K) */ - lu_byte t; /* table (register or upvalue) */ - } ind; - struct { /* for local variables */ - lu_byte ridx; /* register holding the variable */ - unsigned short vidx; /* compiler index (in 'actvar.arr') */ - } var; - } u; - int t; /* patch list of 'exit when true' */ - int f; /* patch list of 'exit when false' */ -} expdesc; - - -/* kinds of variables */ -#define VDKREG 0 /* regular */ -#define RDKCONST 1 /* constant */ -#define RDKTOCLOSE 2 /* to-be-closed */ -#define RDKCTC 3 /* compile-time constant */ - -/* description of an active local variable */ -typedef union Vardesc { - struct { - TValuefields; /* constant value (if it is a compile-time constant) */ - lu_byte kind; - lu_byte ridx; /* register holding the variable */ - short pidx; /* index of the variable in the Proto's 'locvars' array */ - TString *name; /* variable name */ - } vd; - TValue k; /* constant value (if any) */ -} Vardesc; - - - -/* description of pending goto statements and label statements */ -typedef struct Labeldesc { - TString *name; /* label identifier */ - int pc; /* position in code */ - int line; /* line where it appeared */ - lu_byte nactvar; /* number of active variables in that position */ - lu_byte close; /* goto that escapes upvalues */ -} Labeldesc; - - -/* list of labels or gotos */ -typedef struct Labellist { - Labeldesc *arr; /* array */ - int n; /* number of entries in use */ - int size; /* array size */ -} Labellist; - - -/* dynamic structures used by the parser */ -typedef struct Dyndata { - struct { /* list of all active local variables */ - Vardesc *arr; - int n; - int size; - } actvar; - Labellist gt; /* list of pending gotos */ - Labellist label; /* list of active labels */ -} Dyndata; - - -/* control of blocks */ -struct BlockCnt; /* defined in lparser.c */ - - -/* state needed to generate code for a given function */ -typedef struct FuncState { - Proto *f; /* current function header */ - struct FuncState *prev; /* enclosing function */ - struct LexState *ls; /* lexical state */ - struct BlockCnt *bl; /* chain of current blocks */ - int pc; /* next position to code (equivalent to 'ncode') */ - int lasttarget; /* 'label' of last 'jump label' */ - int previousline; /* last line that was saved in 'lineinfo' */ - int nk; /* number of elements in 'k' */ - int np; /* number of elements in 'p' */ - int nabslineinfo; /* number of elements in 'abslineinfo' */ - int firstlocal; /* index of first local var (in Dyndata array) */ - int firstlabel; /* index of first label (in 'dyd->label->arr') */ - short ndebugvars; /* number of elements in 'f->locvars' */ - lu_byte nactvar; /* number of active local variables */ - lu_byte nups; /* number of upvalues */ - lu_byte freereg; /* first free register */ - lu_byte iwthabs; /* instructions issued since last absolute line info */ - lu_byte needclose; /* function needs to close upvalues when returning */ -} FuncState; - - -LUAI_FUNC int luaY_nvarstack (FuncState *fs); -LUAI_FUNC LClosure *luaY_parser (lua_State *L, ZIO *z, Mbuffer *buff, - Dyndata *dyd, const char *name, int firstchar); - - -#endif diff --git a/lib/lua-5.4/src/lprefix.h b/lib/lua-5.4/src/lprefix.h deleted file mode 100644 index 484f2ad..0000000 --- a/lib/lua-5.4/src/lprefix.h +++ /dev/null @@ -1,45 +0,0 @@ -/* -** $Id: lprefix.h $ -** Definitions for Lua code that must come before any other header file -** See Copyright Notice in lua.h -*/ - -#ifndef lprefix_h -#define lprefix_h - - -/* -** Allows POSIX/XSI stuff -*/ -#if !defined(LUA_USE_C89) /* { */ - -#if !defined(_XOPEN_SOURCE) -#define _XOPEN_SOURCE 600 -#elif _XOPEN_SOURCE == 0 -#undef _XOPEN_SOURCE /* use -D_XOPEN_SOURCE=0 to undefine it */ -#endif - -/* -** Allows manipulation of large files in gcc and some other compilers -*/ -#if !defined(LUA_32BITS) && !defined(_FILE_OFFSET_BITS) -#define _LARGEFILE_SOURCE 1 -#define _FILE_OFFSET_BITS 64 -#endif - -#endif /* } */ - - -/* -** Windows stuff -*/ -#if defined(_WIN32) /* { */ - -#if !defined(_CRT_SECURE_NO_WARNINGS) -#define _CRT_SECURE_NO_WARNINGS /* avoid warnings about ISO C functions */ -#endif - -#endif /* } */ - -#endif - diff --git a/lib/lua-5.4/src/lstate.c b/lib/lua-5.4/src/lstate.c deleted file mode 100644 index 1e925e5..0000000 --- a/lib/lua-5.4/src/lstate.c +++ /dev/null @@ -1,445 +0,0 @@ -/* -** $Id: lstate.c $ -** Global State -** See Copyright Notice in lua.h -*/ - -#define lstate_c -#define LUA_CORE - -#include "lprefix.h" - - -#include -#include - -#include "lua.h" - -#include "lapi.h" -#include "ldebug.h" -#include "ldo.h" -#include "lfunc.h" -#include "lgc.h" -#include "llex.h" -#include "lmem.h" -#include "lstate.h" -#include "lstring.h" -#include "ltable.h" -#include "ltm.h" - - - -/* -** thread state + extra space -*/ -typedef struct LX { - lu_byte extra_[LUA_EXTRASPACE]; - lua_State l; -} LX; - - -/* -** Main thread combines a thread state and the global state -*/ -typedef struct LG { - LX l; - global_State g; -} LG; - - - -#define fromstate(L) (cast(LX *, cast(lu_byte *, (L)) - offsetof(LX, l))) - - -/* -** A macro to create a "random" seed when a state is created; -** the seed is used to randomize string hashes. -*/ -#if !defined(luai_makeseed) - -#include - -/* -** Compute an initial seed with some level of randomness. -** Rely on Address Space Layout Randomization (if present) and -** current time. -*/ -#define addbuff(b,p,e) \ - { size_t t = cast_sizet(e); \ - memcpy(b + p, &t, sizeof(t)); p += sizeof(t); } - -static unsigned int luai_makeseed (lua_State *L) { - char buff[3 * sizeof(size_t)]; - unsigned int h = cast_uint(time(NULL)); - int p = 0; - addbuff(buff, p, L); /* heap variable */ - addbuff(buff, p, &h); /* local variable */ - addbuff(buff, p, &lua_newstate); /* public function */ - lua_assert(p == sizeof(buff)); - return luaS_hash(buff, p, h); -} - -#endif - - -/* -** set GCdebt to a new value keeping the value (totalbytes + GCdebt) -** invariant (and avoiding underflows in 'totalbytes') -*/ -void luaE_setdebt (global_State *g, l_mem debt) { - l_mem tb = gettotalbytes(g); - lua_assert(tb > 0); - if (debt < tb - MAX_LMEM) - debt = tb - MAX_LMEM; /* will make 'totalbytes == MAX_LMEM' */ - g->totalbytes = tb - debt; - g->GCdebt = debt; -} - - -LUA_API int lua_setcstacklimit (lua_State *L, unsigned int limit) { - UNUSED(L); UNUSED(limit); - return LUAI_MAXCCALLS; /* warning?? */ -} - - -CallInfo *luaE_extendCI (lua_State *L) { - CallInfo *ci; - lua_assert(L->ci->next == NULL); - ci = luaM_new(L, CallInfo); - lua_assert(L->ci->next == NULL); - L->ci->next = ci; - ci->previous = L->ci; - ci->next = NULL; - ci->u.l.trap = 0; - L->nci++; - return ci; -} - - -/* -** free all CallInfo structures not in use by a thread -*/ -void luaE_freeCI (lua_State *L) { - CallInfo *ci = L->ci; - CallInfo *next = ci->next; - ci->next = NULL; - while ((ci = next) != NULL) { - next = ci->next; - luaM_free(L, ci); - L->nci--; - } -} - - -/* -** free half of the CallInfo structures not in use by a thread, -** keeping the first one. -*/ -void luaE_shrinkCI (lua_State *L) { - CallInfo *ci = L->ci->next; /* first free CallInfo */ - CallInfo *next; - if (ci == NULL) - return; /* no extra elements */ - while ((next = ci->next) != NULL) { /* two extra elements? */ - CallInfo *next2 = next->next; /* next's next */ - ci->next = next2; /* remove next from the list */ - L->nci--; - luaM_free(L, next); /* free next */ - if (next2 == NULL) - break; /* no more elements */ - else { - next2->previous = ci; - ci = next2; /* continue */ - } - } -} - - -/* -** Called when 'getCcalls(L)' larger or equal to LUAI_MAXCCALLS. -** If equal, raises an overflow error. If value is larger than -** LUAI_MAXCCALLS (which means it is handling an overflow) but -** not much larger, does not report an error (to allow overflow -** handling to work). -*/ -void luaE_checkcstack (lua_State *L) { - if (getCcalls(L) == LUAI_MAXCCALLS) - luaG_runerror(L, "C stack overflow"); - else if (getCcalls(L) >= (LUAI_MAXCCALLS / 10 * 11)) - luaD_throw(L, LUA_ERRERR); /* error while handling stack error */ -} - - -LUAI_FUNC void luaE_incCstack (lua_State *L) { - L->nCcalls++; - if (l_unlikely(getCcalls(L) >= LUAI_MAXCCALLS)) - luaE_checkcstack(L); -} - - -static void stack_init (lua_State *L1, lua_State *L) { - int i; CallInfo *ci; - /* initialize stack array */ - L1->stack.p = luaM_newvector(L, BASIC_STACK_SIZE + EXTRA_STACK, StackValue); - L1->tbclist.p = L1->stack.p; - for (i = 0; i < BASIC_STACK_SIZE + EXTRA_STACK; i++) - setnilvalue(s2v(L1->stack.p + i)); /* erase new stack */ - L1->top.p = L1->stack.p; - L1->stack_last.p = L1->stack.p + BASIC_STACK_SIZE; - /* initialize first ci */ - ci = &L1->base_ci; - ci->next = ci->previous = NULL; - ci->callstatus = CIST_C; - ci->func.p = L1->top.p; - ci->u.c.k = NULL; - ci->nresults = 0; - setnilvalue(s2v(L1->top.p)); /* 'function' entry for this 'ci' */ - L1->top.p++; - ci->top.p = L1->top.p + LUA_MINSTACK; - L1->ci = ci; -} - - -static void freestack (lua_State *L) { - if (L->stack.p == NULL) - return; /* stack not completely built yet */ - L->ci = &L->base_ci; /* free the entire 'ci' list */ - luaE_freeCI(L); - lua_assert(L->nci == 0); - luaM_freearray(L, L->stack.p, stacksize(L) + EXTRA_STACK); /* free stack */ -} - - -/* -** Create registry table and its predefined values -*/ -static void init_registry (lua_State *L, global_State *g) { - /* create registry */ - Table *registry = luaH_new(L); - sethvalue(L, &g->l_registry, registry); - luaH_resize(L, registry, LUA_RIDX_LAST, 0); - /* registry[LUA_RIDX_MAINTHREAD] = L */ - setthvalue(L, ®istry->array[LUA_RIDX_MAINTHREAD - 1], L); - /* registry[LUA_RIDX_GLOBALS] = new table (table of globals) */ - sethvalue(L, ®istry->array[LUA_RIDX_GLOBALS - 1], luaH_new(L)); -} - - -/* -** open parts of the state that may cause memory-allocation errors. -*/ -static void f_luaopen (lua_State *L, void *ud) { - global_State *g = G(L); - UNUSED(ud); - stack_init(L, L); /* init stack */ - init_registry(L, g); - luaS_init(L); - luaT_init(L); - luaX_init(L); - g->gcstp = 0; /* allow gc */ - setnilvalue(&g->nilvalue); /* now state is complete */ - luai_userstateopen(L); -} - - -/* -** preinitialize a thread with consistent values without allocating -** any memory (to avoid errors) -*/ -static void preinit_thread (lua_State *L, global_State *g) { - G(L) = g; - L->stack.p = NULL; - L->ci = NULL; - L->nci = 0; - L->twups = L; /* thread has no upvalues */ - L->nCcalls = 0; - L->errorJmp = NULL; - L->hook = NULL; - L->hookmask = 0; - L->basehookcount = 0; - L->allowhook = 1; - resethookcount(L); - L->openupval = NULL; - L->status = LUA_OK; - L->errfunc = 0; - L->oldpc = 0; -} - - -static void close_state (lua_State *L) { - global_State *g = G(L); - if (!completestate(g)) /* closing a partially built state? */ - luaC_freeallobjects(L); /* just collect its objects */ - else { /* closing a fully built state */ - L->ci = &L->base_ci; /* unwind CallInfo list */ - luaD_closeprotected(L, 1, LUA_OK); /* close all upvalues */ - luaC_freeallobjects(L); /* collect all objects */ - luai_userstateclose(L); - } - luaM_freearray(L, G(L)->strt.hash, G(L)->strt.size); - freestack(L); - lua_assert(gettotalbytes(g) == sizeof(LG)); - (*g->frealloc)(g->ud, fromstate(L), sizeof(LG), 0); /* free main block */ -} - - -LUA_API lua_State *lua_newthread (lua_State *L) { - global_State *g = G(L); - GCObject *o; - lua_State *L1; - lua_lock(L); - luaC_checkGC(L); - /* create new thread */ - o = luaC_newobjdt(L, LUA_TTHREAD, sizeof(LX), offsetof(LX, l)); - L1 = gco2th(o); - /* anchor it on L stack */ - setthvalue2s(L, L->top.p, L1); - api_incr_top(L); - preinit_thread(L1, g); - L1->hookmask = L->hookmask; - L1->basehookcount = L->basehookcount; - L1->hook = L->hook; - resethookcount(L1); - /* initialize L1 extra space */ - memcpy(lua_getextraspace(L1), lua_getextraspace(g->mainthread), - LUA_EXTRASPACE); - luai_userstatethread(L, L1); - stack_init(L1, L); /* init stack */ - lua_unlock(L); - return L1; -} - - -void luaE_freethread (lua_State *L, lua_State *L1) { - LX *l = fromstate(L1); - luaF_closeupval(L1, L1->stack.p); /* close all upvalues */ - lua_assert(L1->openupval == NULL); - luai_userstatefree(L, L1); - freestack(L1); - luaM_free(L, l); -} - - -int luaE_resetthread (lua_State *L, int status) { - CallInfo *ci = L->ci = &L->base_ci; /* unwind CallInfo list */ - setnilvalue(s2v(L->stack.p)); /* 'function' entry for basic 'ci' */ - ci->func.p = L->stack.p; - ci->callstatus = CIST_C; - if (status == LUA_YIELD) - status = LUA_OK; - L->status = LUA_OK; /* so it can run __close metamethods */ - status = luaD_closeprotected(L, 1, status); - if (status != LUA_OK) /* errors? */ - luaD_seterrorobj(L, status, L->stack.p + 1); - else - L->top.p = L->stack.p + 1; - ci->top.p = L->top.p + LUA_MINSTACK; - luaD_reallocstack(L, cast_int(ci->top.p - L->stack.p), 0); - return status; -} - - -LUA_API int lua_closethread (lua_State *L, lua_State *from) { - int status; - lua_lock(L); - L->nCcalls = (from) ? getCcalls(from) : 0; - status = luaE_resetthread(L, L->status); - lua_unlock(L); - return status; -} - - -/* -** Deprecated! Use 'lua_closethread' instead. -*/ -LUA_API int lua_resetthread (lua_State *L) { - return lua_closethread(L, NULL); -} - - -LUA_API lua_State *lua_newstate (lua_Alloc f, void *ud) { - int i; - lua_State *L; - global_State *g; - LG *l = cast(LG *, (*f)(ud, NULL, LUA_TTHREAD, sizeof(LG))); - if (l == NULL) return NULL; - L = &l->l.l; - g = &l->g; - L->tt = LUA_VTHREAD; - g->currentwhite = bitmask(WHITE0BIT); - L->marked = luaC_white(g); - preinit_thread(L, g); - g->allgc = obj2gco(L); /* by now, only object is the main thread */ - L->next = NULL; - incnny(L); /* main thread is always non yieldable */ - g->frealloc = f; - g->ud = ud; - g->warnf = NULL; - g->ud_warn = NULL; - g->mainthread = L; - g->seed = luai_makeseed(L); - g->gcstp = GCSTPGC; /* no GC while building state */ - g->strt.size = g->strt.nuse = 0; - g->strt.hash = NULL; - setnilvalue(&g->l_registry); - g->panic = NULL; - g->gcstate = GCSpause; - g->gckind = KGC_INC; - g->gcstopem = 0; - g->gcemergency = 0; - g->finobj = g->tobefnz = g->fixedgc = NULL; - g->firstold1 = g->survival = g->old1 = g->reallyold = NULL; - g->finobjsur = g->finobjold1 = g->finobjrold = NULL; - g->sweepgc = NULL; - g->gray = g->grayagain = NULL; - g->weak = g->ephemeron = g->allweak = NULL; - g->twups = NULL; - g->totalbytes = sizeof(LG); - g->GCdebt = 0; - g->lastatomic = 0; - setivalue(&g->nilvalue, 0); /* to signal that state is not yet built */ - setgcparam(g->gcpause, LUAI_GCPAUSE); - setgcparam(g->gcstepmul, LUAI_GCMUL); - g->gcstepsize = LUAI_GCSTEPSIZE; - setgcparam(g->genmajormul, LUAI_GENMAJORMUL); - g->genminormul = LUAI_GENMINORMUL; - for (i=0; i < LUA_NUMTAGS; i++) g->mt[i] = NULL; - if (luaD_rawrunprotected(L, f_luaopen, NULL) != LUA_OK) { - /* memory allocation error: free partial state */ - close_state(L); - L = NULL; - } - return L; -} - - -LUA_API void lua_close (lua_State *L) { - lua_lock(L); - L = G(L)->mainthread; /* only the main thread can be closed */ - close_state(L); -} - - -void luaE_warning (lua_State *L, const char *msg, int tocont) { - lua_WarnFunction wf = G(L)->warnf; - if (wf != NULL) - wf(G(L)->ud_warn, msg, tocont); -} - - -/* -** Generate a warning from an error message -*/ -void luaE_warnerror (lua_State *L, const char *where) { - TValue *errobj = s2v(L->top.p - 1); /* error object */ - const char *msg = (ttisstring(errobj)) - ? svalue(errobj) - : "error object is not a string"; - /* produce warning "error in %s (%s)" (where, msg) */ - luaE_warning(L, "error in ", 1); - luaE_warning(L, where, 1); - luaE_warning(L, " (", 1); - luaE_warning(L, msg, 1); - luaE_warning(L, ")", 0); -} - diff --git a/lib/lua-5.4/src/lstate.h b/lib/lua-5.4/src/lstate.h deleted file mode 100644 index 8bf6600..0000000 --- a/lib/lua-5.4/src/lstate.h +++ /dev/null @@ -1,409 +0,0 @@ -/* -** $Id: lstate.h $ -** Global State -** See Copyright Notice in lua.h -*/ - -#ifndef lstate_h -#define lstate_h - -#include "lua.h" - - -/* Some header files included here need this definition */ -typedef struct CallInfo CallInfo; - - -#include "lobject.h" -#include "ltm.h" -#include "lzio.h" - - -/* -** Some notes about garbage-collected objects: All objects in Lua must -** be kept somehow accessible until being freed, so all objects always -** belong to one (and only one) of these lists, using field 'next' of -** the 'CommonHeader' for the link: -** -** 'allgc': all objects not marked for finalization; -** 'finobj': all objects marked for finalization; -** 'tobefnz': all objects ready to be finalized; -** 'fixedgc': all objects that are not to be collected (currently -** only small strings, such as reserved words). -** -** For the generational collector, some of these lists have marks for -** generations. Each mark points to the first element in the list for -** that particular generation; that generation goes until the next mark. -** -** 'allgc' -> 'survival': new objects; -** 'survival' -> 'old': objects that survived one collection; -** 'old1' -> 'reallyold': objects that became old in last collection; -** 'reallyold' -> NULL: objects old for more than one cycle. -** -** 'finobj' -> 'finobjsur': new objects marked for finalization; -** 'finobjsur' -> 'finobjold1': survived """"; -** 'finobjold1' -> 'finobjrold': just old """"; -** 'finobjrold' -> NULL: really old """". -** -** All lists can contain elements older than their main ages, due -** to 'luaC_checkfinalizer' and 'udata2finalize', which move -** objects between the normal lists and the "marked for finalization" -** lists. Moreover, barriers can age young objects in young lists as -** OLD0, which then become OLD1. However, a list never contains -** elements younger than their main ages. -** -** The generational collector also uses a pointer 'firstold1', which -** points to the first OLD1 object in the list. It is used to optimize -** 'markold'. (Potentially OLD1 objects can be anywhere between 'allgc' -** and 'reallyold', but often the list has no OLD1 objects or they are -** after 'old1'.) Note the difference between it and 'old1': -** 'firstold1': no OLD1 objects before this point; there can be all -** ages after it. -** 'old1': no objects younger than OLD1 after this point. -*/ - -/* -** Moreover, there is another set of lists that control gray objects. -** These lists are linked by fields 'gclist'. (All objects that -** can become gray have such a field. The field is not the same -** in all objects, but it always has this name.) Any gray object -** must belong to one of these lists, and all objects in these lists -** must be gray (with two exceptions explained below): -** -** 'gray': regular gray objects, still waiting to be visited. -** 'grayagain': objects that must be revisited at the atomic phase. -** That includes -** - black objects got in a write barrier; -** - all kinds of weak tables during propagation phase; -** - all threads. -** 'weak': tables with weak values to be cleared; -** 'ephemeron': ephemeron tables with white->white entries; -** 'allweak': tables with weak keys and/or weak values to be cleared. -** -** The exceptions to that "gray rule" are: -** - TOUCHED2 objects in generational mode stay in a gray list (because -** they must be visited again at the end of the cycle), but they are -** marked black because assignments to them must activate barriers (to -** move them back to TOUCHED1). -** - Open upvales are kept gray to avoid barriers, but they stay out -** of gray lists. (They don't even have a 'gclist' field.) -*/ - - - -/* -** About 'nCcalls': This count has two parts: the lower 16 bits counts -** the number of recursive invocations in the C stack; the higher -** 16 bits counts the number of non-yieldable calls in the stack. -** (They are together so that we can change and save both with one -** instruction.) -*/ - - -/* true if this thread does not have non-yieldable calls in the stack */ -#define yieldable(L) (((L)->nCcalls & 0xffff0000) == 0) - -/* real number of C calls */ -#define getCcalls(L) ((L)->nCcalls & 0xffff) - - -/* Increment the number of non-yieldable calls */ -#define incnny(L) ((L)->nCcalls += 0x10000) - -/* Decrement the number of non-yieldable calls */ -#define decnny(L) ((L)->nCcalls -= 0x10000) - -/* Non-yieldable call increment */ -#define nyci (0x10000 | 1) - - - - -struct lua_longjmp; /* defined in ldo.c */ - - -/* -** Atomic type (relative to signals) to better ensure that 'lua_sethook' -** is thread safe -*/ -#if !defined(l_signalT) -#include -#define l_signalT sig_atomic_t -#endif - - -/* -** Extra stack space to handle TM calls and some other extras. This -** space is not included in 'stack_last'. It is used only to avoid stack -** checks, either because the element will be promptly popped or because -** there will be a stack check soon after the push. Function frames -** never use this extra space, so it does not need to be kept clean. -*/ -#define EXTRA_STACK 5 - - -#define BASIC_STACK_SIZE (2*LUA_MINSTACK) - -#define stacksize(th) cast_int((th)->stack_last.p - (th)->stack.p) - - -/* kinds of Garbage Collection */ -#define KGC_INC 0 /* incremental gc */ -#define KGC_GEN 1 /* generational gc */ - - -typedef struct stringtable { - TString **hash; - int nuse; /* number of elements */ - int size; -} stringtable; - - -/* -** Information about a call. -** About union 'u': -** - field 'l' is used only for Lua functions; -** - field 'c' is used only for C functions. -** About union 'u2': -** - field 'funcidx' is used only by C functions while doing a -** protected call; -** - field 'nyield' is used only while a function is "doing" an -** yield (from the yield until the next resume); -** - field 'nres' is used only while closing tbc variables when -** returning from a function; -** - field 'transferinfo' is used only during call/returnhooks, -** before the function starts or after it ends. -*/ -struct CallInfo { - StkIdRel func; /* function index in the stack */ - StkIdRel top; /* top for this function */ - struct CallInfo *previous, *next; /* dynamic call link */ - union { - struct { /* only for Lua functions */ - const Instruction *savedpc; - volatile l_signalT trap; - int nextraargs; /* # of extra arguments in vararg functions */ - } l; - struct { /* only for C functions */ - lua_KFunction k; /* continuation in case of yields */ - ptrdiff_t old_errfunc; - lua_KContext ctx; /* context info. in case of yields */ - } c; - } u; - union { - int funcidx; /* called-function index */ - int nyield; /* number of values yielded */ - int nres; /* number of values returned */ - struct { /* info about transferred values (for call/return hooks) */ - unsigned short ftransfer; /* offset of first value transferred */ - unsigned short ntransfer; /* number of values transferred */ - } transferinfo; - } u2; - short nresults; /* expected number of results from this function */ - unsigned short callstatus; -}; - - -/* -** Bits in CallInfo status -*/ -#define CIST_OAH (1<<0) /* original value of 'allowhook' */ -#define CIST_C (1<<1) /* call is running a C function */ -#define CIST_FRESH (1<<2) /* call is on a fresh "luaV_execute" frame */ -#define CIST_HOOKED (1<<3) /* call is running a debug hook */ -#define CIST_YPCALL (1<<4) /* doing a yieldable protected call */ -#define CIST_TAIL (1<<5) /* call was tail called */ -#define CIST_HOOKYIELD (1<<6) /* last hook called yielded */ -#define CIST_FIN (1<<7) /* function "called" a finalizer */ -#define CIST_TRAN (1<<8) /* 'ci' has transfer information */ -#define CIST_CLSRET (1<<9) /* function is closing tbc variables */ -/* Bits 10-12 are used for CIST_RECST (see below) */ -#define CIST_RECST 10 -#if defined(LUA_COMPAT_LT_LE) -#define CIST_LEQ (1<<13) /* using __lt for __le */ -#endif - - -/* -** Field CIST_RECST stores the "recover status", used to keep the error -** status while closing to-be-closed variables in coroutines, so that -** Lua can correctly resume after an yield from a __close method called -** because of an error. (Three bits are enough for error status.) -*/ -#define getcistrecst(ci) (((ci)->callstatus >> CIST_RECST) & 7) -#define setcistrecst(ci,st) \ - check_exp(((st) & 7) == (st), /* status must fit in three bits */ \ - ((ci)->callstatus = ((ci)->callstatus & ~(7 << CIST_RECST)) \ - | ((st) << CIST_RECST))) - - -/* active function is a Lua function */ -#define isLua(ci) (!((ci)->callstatus & CIST_C)) - -/* call is running Lua code (not a hook) */ -#define isLuacode(ci) (!((ci)->callstatus & (CIST_C | CIST_HOOKED))) - -/* assume that CIST_OAH has offset 0 and that 'v' is strictly 0/1 */ -#define setoah(st,v) ((st) = ((st) & ~CIST_OAH) | (v)) -#define getoah(st) ((st) & CIST_OAH) - - -/* -** 'global state', shared by all threads of this state -*/ -typedef struct global_State { - lua_Alloc frealloc; /* function to reallocate memory */ - void *ud; /* auxiliary data to 'frealloc' */ - l_mem totalbytes; /* number of bytes currently allocated - GCdebt */ - l_mem GCdebt; /* bytes allocated not yet compensated by the collector */ - lu_mem GCestimate; /* an estimate of the non-garbage memory in use */ - lu_mem lastatomic; /* see function 'genstep' in file 'lgc.c' */ - stringtable strt; /* hash table for strings */ - TValue l_registry; - TValue nilvalue; /* a nil value */ - unsigned int seed; /* randomized seed for hashes */ - lu_byte currentwhite; - lu_byte gcstate; /* state of garbage collector */ - lu_byte gckind; /* kind of GC running */ - lu_byte gcstopem; /* stops emergency collections */ - lu_byte genminormul; /* control for minor generational collections */ - lu_byte genmajormul; /* control for major generational collections */ - lu_byte gcstp; /* control whether GC is running */ - lu_byte gcemergency; /* true if this is an emergency collection */ - lu_byte gcpause; /* size of pause between successive GCs */ - lu_byte gcstepmul; /* GC "speed" */ - lu_byte gcstepsize; /* (log2 of) GC granularity */ - GCObject *allgc; /* list of all collectable objects */ - GCObject **sweepgc; /* current position of sweep in list */ - GCObject *finobj; /* list of collectable objects with finalizers */ - GCObject *gray; /* list of gray objects */ - GCObject *grayagain; /* list of objects to be traversed atomically */ - GCObject *weak; /* list of tables with weak values */ - GCObject *ephemeron; /* list of ephemeron tables (weak keys) */ - GCObject *allweak; /* list of all-weak tables */ - GCObject *tobefnz; /* list of userdata to be GC */ - GCObject *fixedgc; /* list of objects not to be collected */ - /* fields for generational collector */ - GCObject *survival; /* start of objects that survived one GC cycle */ - GCObject *old1; /* start of old1 objects */ - GCObject *reallyold; /* objects more than one cycle old ("really old") */ - GCObject *firstold1; /* first OLD1 object in the list (if any) */ - GCObject *finobjsur; /* list of survival objects with finalizers */ - GCObject *finobjold1; /* list of old1 objects with finalizers */ - GCObject *finobjrold; /* list of really old objects with finalizers */ - struct lua_State *twups; /* list of threads with open upvalues */ - lua_CFunction panic; /* to be called in unprotected errors */ - struct lua_State *mainthread; - TString *memerrmsg; /* message for memory-allocation errors */ - TString *tmname[TM_N]; /* array with tag-method names */ - struct Table *mt[LUA_NUMTYPES]; /* metatables for basic types */ - TString *strcache[STRCACHE_N][STRCACHE_M]; /* cache for strings in API */ - lua_WarnFunction warnf; /* warning function */ - void *ud_warn; /* auxiliary data to 'warnf' */ -} global_State; - - -/* -** 'per thread' state -*/ -struct lua_State { - CommonHeader; - lu_byte status; - lu_byte allowhook; - unsigned short nci; /* number of items in 'ci' list */ - StkIdRel top; /* first free slot in the stack */ - global_State *l_G; - CallInfo *ci; /* call info for current function */ - StkIdRel stack_last; /* end of stack (last element + 1) */ - StkIdRel stack; /* stack base */ - UpVal *openupval; /* list of open upvalues in this stack */ - StkIdRel tbclist; /* list of to-be-closed variables */ - GCObject *gclist; - struct lua_State *twups; /* list of threads with open upvalues */ - struct lua_longjmp *errorJmp; /* current error recover point */ - CallInfo base_ci; /* CallInfo for first level (C calling Lua) */ - volatile lua_Hook hook; - ptrdiff_t errfunc; /* current error handling function (stack index) */ - l_uint32 nCcalls; /* number of nested (non-yieldable | C) calls */ - int oldpc; /* last pc traced */ - int basehookcount; - int hookcount; - volatile l_signalT hookmask; -}; - - -#define G(L) (L->l_G) - -/* -** 'g->nilvalue' being a nil value flags that the state was completely -** build. -*/ -#define completestate(g) ttisnil(&g->nilvalue) - - -/* -** Union of all collectable objects (only for conversions) -** ISO C99, 6.5.2.3 p.5: -** "if a union contains several structures that share a common initial -** sequence [...], and if the union object currently contains one -** of these structures, it is permitted to inspect the common initial -** part of any of them anywhere that a declaration of the complete type -** of the union is visible." -*/ -union GCUnion { - GCObject gc; /* common header */ - struct TString ts; - struct Udata u; - union Closure cl; - struct Table h; - struct Proto p; - struct lua_State th; /* thread */ - struct UpVal upv; -}; - - -/* -** ISO C99, 6.7.2.1 p.14: -** "A pointer to a union object, suitably converted, points to each of -** its members [...], and vice versa." -*/ -#define cast_u(o) cast(union GCUnion *, (o)) - -/* macros to convert a GCObject into a specific value */ -#define gco2ts(o) \ - check_exp(novariant((o)->tt) == LUA_TSTRING, &((cast_u(o))->ts)) -#define gco2u(o) check_exp((o)->tt == LUA_VUSERDATA, &((cast_u(o))->u)) -#define gco2lcl(o) check_exp((o)->tt == LUA_VLCL, &((cast_u(o))->cl.l)) -#define gco2ccl(o) check_exp((o)->tt == LUA_VCCL, &((cast_u(o))->cl.c)) -#define gco2cl(o) \ - check_exp(novariant((o)->tt) == LUA_TFUNCTION, &((cast_u(o))->cl)) -#define gco2t(o) check_exp((o)->tt == LUA_VTABLE, &((cast_u(o))->h)) -#define gco2p(o) check_exp((o)->tt == LUA_VPROTO, &((cast_u(o))->p)) -#define gco2th(o) check_exp((o)->tt == LUA_VTHREAD, &((cast_u(o))->th)) -#define gco2upv(o) check_exp((o)->tt == LUA_VUPVAL, &((cast_u(o))->upv)) - - -/* -** macro to convert a Lua object into a GCObject -** (The access to 'tt' tries to ensure that 'v' is actually a Lua object.) -*/ -#define obj2gco(v) check_exp((v)->tt >= LUA_TSTRING, &(cast_u(v)->gc)) - - -/* actual number of total bytes allocated */ -#define gettotalbytes(g) cast(lu_mem, (g)->totalbytes + (g)->GCdebt) - -LUAI_FUNC void luaE_setdebt (global_State *g, l_mem debt); -LUAI_FUNC void luaE_freethread (lua_State *L, lua_State *L1); -LUAI_FUNC CallInfo *luaE_extendCI (lua_State *L); -LUAI_FUNC void luaE_freeCI (lua_State *L); -LUAI_FUNC void luaE_shrinkCI (lua_State *L); -LUAI_FUNC void luaE_checkcstack (lua_State *L); -LUAI_FUNC void luaE_incCstack (lua_State *L); -LUAI_FUNC void luaE_warning (lua_State *L, const char *msg, int tocont); -LUAI_FUNC void luaE_warnerror (lua_State *L, const char *where); -LUAI_FUNC int luaE_resetthread (lua_State *L, int status); - - -#endif - diff --git a/lib/lua-5.4/src/lstring.c b/lib/lua-5.4/src/lstring.c deleted file mode 100644 index 13dcaf4..0000000 --- a/lib/lua-5.4/src/lstring.c +++ /dev/null @@ -1,273 +0,0 @@ -/* -** $Id: lstring.c $ -** String table (keeps all strings handled by Lua) -** See Copyright Notice in lua.h -*/ - -#define lstring_c -#define LUA_CORE - -#include "lprefix.h" - - -#include - -#include "lua.h" - -#include "ldebug.h" -#include "ldo.h" -#include "lmem.h" -#include "lobject.h" -#include "lstate.h" -#include "lstring.h" - - -/* -** Maximum size for string table. -*/ -#define MAXSTRTB cast_int(luaM_limitN(MAX_INT, TString*)) - - -/* -** equality for long strings -*/ -int luaS_eqlngstr (TString *a, TString *b) { - size_t len = a->u.lnglen; - lua_assert(a->tt == LUA_VLNGSTR && b->tt == LUA_VLNGSTR); - return (a == b) || /* same instance or... */ - ((len == b->u.lnglen) && /* equal length and ... */ - (memcmp(getstr(a), getstr(b), len) == 0)); /* equal contents */ -} - - -unsigned int luaS_hash (const char *str, size_t l, unsigned int seed) { - unsigned int h = seed ^ cast_uint(l); - for (; l > 0; l--) - h ^= ((h<<5) + (h>>2) + cast_byte(str[l - 1])); - return h; -} - - -unsigned int luaS_hashlongstr (TString *ts) { - lua_assert(ts->tt == LUA_VLNGSTR); - if (ts->extra == 0) { /* no hash? */ - size_t len = ts->u.lnglen; - ts->hash = luaS_hash(getstr(ts), len, ts->hash); - ts->extra = 1; /* now it has its hash */ - } - return ts->hash; -} - - -static void tablerehash (TString **vect, int osize, int nsize) { - int i; - for (i = osize; i < nsize; i++) /* clear new elements */ - vect[i] = NULL; - for (i = 0; i < osize; i++) { /* rehash old part of the array */ - TString *p = vect[i]; - vect[i] = NULL; - while (p) { /* for each string in the list */ - TString *hnext = p->u.hnext; /* save next */ - unsigned int h = lmod(p->hash, nsize); /* new position */ - p->u.hnext = vect[h]; /* chain it into array */ - vect[h] = p; - p = hnext; - } - } -} - - -/* -** Resize the string table. If allocation fails, keep the current size. -** (This can degrade performance, but any non-zero size should work -** correctly.) -*/ -void luaS_resize (lua_State *L, int nsize) { - stringtable *tb = &G(L)->strt; - int osize = tb->size; - TString **newvect; - if (nsize < osize) /* shrinking table? */ - tablerehash(tb->hash, osize, nsize); /* depopulate shrinking part */ - newvect = luaM_reallocvector(L, tb->hash, osize, nsize, TString*); - if (l_unlikely(newvect == NULL)) { /* reallocation failed? */ - if (nsize < osize) /* was it shrinking table? */ - tablerehash(tb->hash, nsize, osize); /* restore to original size */ - /* leave table as it was */ - } - else { /* allocation succeeded */ - tb->hash = newvect; - tb->size = nsize; - if (nsize > osize) - tablerehash(newvect, osize, nsize); /* rehash for new size */ - } -} - - -/* -** Clear API string cache. (Entries cannot be empty, so fill them with -** a non-collectable string.) -*/ -void luaS_clearcache (global_State *g) { - int i, j; - for (i = 0; i < STRCACHE_N; i++) - for (j = 0; j < STRCACHE_M; j++) { - if (iswhite(g->strcache[i][j])) /* will entry be collected? */ - g->strcache[i][j] = g->memerrmsg; /* replace it with something fixed */ - } -} - - -/* -** Initialize the string table and the string cache -*/ -void luaS_init (lua_State *L) { - global_State *g = G(L); - int i, j; - stringtable *tb = &G(L)->strt; - tb->hash = luaM_newvector(L, MINSTRTABSIZE, TString*); - tablerehash(tb->hash, 0, MINSTRTABSIZE); /* clear array */ - tb->size = MINSTRTABSIZE; - /* pre-create memory-error message */ - g->memerrmsg = luaS_newliteral(L, MEMERRMSG); - luaC_fix(L, obj2gco(g->memerrmsg)); /* it should never be collected */ - for (i = 0; i < STRCACHE_N; i++) /* fill cache with valid strings */ - for (j = 0; j < STRCACHE_M; j++) - g->strcache[i][j] = g->memerrmsg; -} - - - -/* -** creates a new string object -*/ -static TString *createstrobj (lua_State *L, size_t l, int tag, unsigned int h) { - TString *ts; - GCObject *o; - size_t totalsize; /* total size of TString object */ - totalsize = sizelstring(l); - o = luaC_newobj(L, tag, totalsize); - ts = gco2ts(o); - ts->hash = h; - ts->extra = 0; - getstr(ts)[l] = '\0'; /* ending 0 */ - return ts; -} - - -TString *luaS_createlngstrobj (lua_State *L, size_t l) { - TString *ts = createstrobj(L, l, LUA_VLNGSTR, G(L)->seed); - ts->u.lnglen = l; - return ts; -} - - -void luaS_remove (lua_State *L, TString *ts) { - stringtable *tb = &G(L)->strt; - TString **p = &tb->hash[lmod(ts->hash, tb->size)]; - while (*p != ts) /* find previous element */ - p = &(*p)->u.hnext; - *p = (*p)->u.hnext; /* remove element from its list */ - tb->nuse--; -} - - -static void growstrtab (lua_State *L, stringtable *tb) { - if (l_unlikely(tb->nuse == MAX_INT)) { /* too many strings? */ - luaC_fullgc(L, 1); /* try to free some... */ - if (tb->nuse == MAX_INT) /* still too many? */ - luaM_error(L); /* cannot even create a message... */ - } - if (tb->size <= MAXSTRTB / 2) /* can grow string table? */ - luaS_resize(L, tb->size * 2); -} - - -/* -** Checks whether short string exists and reuses it or creates a new one. -*/ -static TString *internshrstr (lua_State *L, const char *str, size_t l) { - TString *ts; - global_State *g = G(L); - stringtable *tb = &g->strt; - unsigned int h = luaS_hash(str, l, g->seed); - TString **list = &tb->hash[lmod(h, tb->size)]; - lua_assert(str != NULL); /* otherwise 'memcmp'/'memcpy' are undefined */ - for (ts = *list; ts != NULL; ts = ts->u.hnext) { - if (l == ts->shrlen && (memcmp(str, getstr(ts), l * sizeof(char)) == 0)) { - /* found! */ - if (isdead(g, ts)) /* dead (but not collected yet)? */ - changewhite(ts); /* resurrect it */ - return ts; - } - } - /* else must create a new string */ - if (tb->nuse >= tb->size) { /* need to grow string table? */ - growstrtab(L, tb); - list = &tb->hash[lmod(h, tb->size)]; /* rehash with new size */ - } - ts = createstrobj(L, l, LUA_VSHRSTR, h); - memcpy(getstr(ts), str, l * sizeof(char)); - ts->shrlen = cast_byte(l); - ts->u.hnext = *list; - *list = ts; - tb->nuse++; - return ts; -} - - -/* -** new string (with explicit length) -*/ -TString *luaS_newlstr (lua_State *L, const char *str, size_t l) { - if (l <= LUAI_MAXSHORTLEN) /* short string? */ - return internshrstr(L, str, l); - else { - TString *ts; - if (l_unlikely(l >= (MAX_SIZE - sizeof(TString))/sizeof(char))) - luaM_toobig(L); - ts = luaS_createlngstrobj(L, l); - memcpy(getstr(ts), str, l * sizeof(char)); - return ts; - } -} - - -/* -** Create or reuse a zero-terminated string, first checking in the -** cache (using the string address as a key). The cache can contain -** only zero-terminated strings, so it is safe to use 'strcmp' to -** check hits. -*/ -TString *luaS_new (lua_State *L, const char *str) { - unsigned int i = point2uint(str) % STRCACHE_N; /* hash */ - int j; - TString **p = G(L)->strcache[i]; - for (j = 0; j < STRCACHE_M; j++) { - if (strcmp(str, getstr(p[j])) == 0) /* hit? */ - return p[j]; /* that is it */ - } - /* normal route */ - for (j = STRCACHE_M - 1; j > 0; j--) - p[j] = p[j - 1]; /* move out last element */ - /* new element is first in the list */ - p[0] = luaS_newlstr(L, str, strlen(str)); - return p[0]; -} - - -Udata *luaS_newudata (lua_State *L, size_t s, int nuvalue) { - Udata *u; - int i; - GCObject *o; - if (l_unlikely(s > MAX_SIZE - udatamemoffset(nuvalue))) - luaM_toobig(L); - o = luaC_newobj(L, LUA_VUSERDATA, sizeudata(nuvalue, s)); - u = gco2u(o); - u->len = s; - u->nuvalue = nuvalue; - u->metatable = NULL; - for (i = 0; i < nuvalue; i++) - setnilvalue(&u->uv[i].uv); - return u; -} - diff --git a/lib/lua-5.4/src/lstring.h b/lib/lua-5.4/src/lstring.h deleted file mode 100644 index 450c239..0000000 --- a/lib/lua-5.4/src/lstring.h +++ /dev/null @@ -1,57 +0,0 @@ -/* -** $Id: lstring.h $ -** String table (keep all strings handled by Lua) -** See Copyright Notice in lua.h -*/ - -#ifndef lstring_h -#define lstring_h - -#include "lgc.h" -#include "lobject.h" -#include "lstate.h" - - -/* -** Memory-allocation error message must be preallocated (it cannot -** be created after memory is exhausted) -*/ -#define MEMERRMSG "not enough memory" - - -/* -** Size of a TString: Size of the header plus space for the string -** itself (including final '\0'). -*/ -#define sizelstring(l) (offsetof(TString, contents) + ((l) + 1) * sizeof(char)) - -#define luaS_newliteral(L, s) (luaS_newlstr(L, "" s, \ - (sizeof(s)/sizeof(char))-1)) - - -/* -** test whether a string is a reserved word -*/ -#define isreserved(s) ((s)->tt == LUA_VSHRSTR && (s)->extra > 0) - - -/* -** equality for short strings, which are always internalized -*/ -#define eqshrstr(a,b) check_exp((a)->tt == LUA_VSHRSTR, (a) == (b)) - - -LUAI_FUNC unsigned int luaS_hash (const char *str, size_t l, unsigned int seed); -LUAI_FUNC unsigned int luaS_hashlongstr (TString *ts); -LUAI_FUNC int luaS_eqlngstr (TString *a, TString *b); -LUAI_FUNC void luaS_resize (lua_State *L, int newsize); -LUAI_FUNC void luaS_clearcache (global_State *g); -LUAI_FUNC void luaS_init (lua_State *L); -LUAI_FUNC void luaS_remove (lua_State *L, TString *ts); -LUAI_FUNC Udata *luaS_newudata (lua_State *L, size_t s, int nuvalue); -LUAI_FUNC TString *luaS_newlstr (lua_State *L, const char *str, size_t l); -LUAI_FUNC TString *luaS_new (lua_State *L, const char *str); -LUAI_FUNC TString *luaS_createlngstrobj (lua_State *L, size_t l); - - -#endif diff --git a/lib/lua-5.4/src/lstrlib.c b/lib/lua-5.4/src/lstrlib.c deleted file mode 100644 index 0316716..0000000 --- a/lib/lua-5.4/src/lstrlib.c +++ /dev/null @@ -1,1874 +0,0 @@ -/* -** $Id: lstrlib.c $ -** Standard library for string operations and pattern-matching -** See Copyright Notice in lua.h -*/ - -#define lstrlib_c -#define LUA_LIB - -#include "lprefix.h" - - -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include "lua.h" - -#include "lauxlib.h" -#include "lualib.h" - - -/* -** maximum number of captures that a pattern can do during -** pattern-matching. This limit is arbitrary, but must fit in -** an unsigned char. -*/ -#if !defined(LUA_MAXCAPTURES) -#define LUA_MAXCAPTURES 32 -#endif - - -/* macro to 'unsign' a character */ -#define uchar(c) ((unsigned char)(c)) - - -/* -** Some sizes are better limited to fit in 'int', but must also fit in -** 'size_t'. (We assume that 'lua_Integer' cannot be smaller than 'int'.) -*/ -#define MAX_SIZET ((size_t)(~(size_t)0)) - -#define MAXSIZE \ - (sizeof(size_t) < sizeof(int) ? MAX_SIZET : (size_t)(INT_MAX)) - - - - -static int str_len (lua_State *L) { - size_t l; - luaL_checklstring(L, 1, &l); - lua_pushinteger(L, (lua_Integer)l); - return 1; -} - - -/* -** translate a relative initial string position -** (negative means back from end): clip result to [1, inf). -** The length of any string in Lua must fit in a lua_Integer, -** so there are no overflows in the casts. -** The inverted comparison avoids a possible overflow -** computing '-pos'. -*/ -static size_t posrelatI (lua_Integer pos, size_t len) { - if (pos > 0) - return (size_t)pos; - else if (pos == 0) - return 1; - else if (pos < -(lua_Integer)len) /* inverted comparison */ - return 1; /* clip to 1 */ - else return len + (size_t)pos + 1; -} - - -/* -** Gets an optional ending string position from argument 'arg', -** with default value 'def'. -** Negative means back from end: clip result to [0, len] -*/ -static size_t getendpos (lua_State *L, int arg, lua_Integer def, - size_t len) { - lua_Integer pos = luaL_optinteger(L, arg, def); - if (pos > (lua_Integer)len) - return len; - else if (pos >= 0) - return (size_t)pos; - else if (pos < -(lua_Integer)len) - return 0; - else return len + (size_t)pos + 1; -} - - -static int str_sub (lua_State *L) { - size_t l; - const char *s = luaL_checklstring(L, 1, &l); - size_t start = posrelatI(luaL_checkinteger(L, 2), l); - size_t end = getendpos(L, 3, -1, l); - if (start <= end) - lua_pushlstring(L, s + start - 1, (end - start) + 1); - else lua_pushliteral(L, ""); - return 1; -} - - -static int str_reverse (lua_State *L) { - size_t l, i; - luaL_Buffer b; - const char *s = luaL_checklstring(L, 1, &l); - char *p = luaL_buffinitsize(L, &b, l); - for (i = 0; i < l; i++) - p[i] = s[l - i - 1]; - luaL_pushresultsize(&b, l); - return 1; -} - - -static int str_lower (lua_State *L) { - size_t l; - size_t i; - luaL_Buffer b; - const char *s = luaL_checklstring(L, 1, &l); - char *p = luaL_buffinitsize(L, &b, l); - for (i=0; i MAXSIZE / n)) - return luaL_error(L, "resulting string too large"); - else { - size_t totallen = (size_t)n * l + (size_t)(n - 1) * lsep; - luaL_Buffer b; - char *p = luaL_buffinitsize(L, &b, totallen); - while (n-- > 1) { /* first n-1 copies (followed by separator) */ - memcpy(p, s, l * sizeof(char)); p += l; - if (lsep > 0) { /* empty 'memcpy' is not that cheap */ - memcpy(p, sep, lsep * sizeof(char)); - p += lsep; - } - } - memcpy(p, s, l * sizeof(char)); /* last copy (not followed by separator) */ - luaL_pushresultsize(&b, totallen); - } - return 1; -} - - -static int str_byte (lua_State *L) { - size_t l; - const char *s = luaL_checklstring(L, 1, &l); - lua_Integer pi = luaL_optinteger(L, 2, 1); - size_t posi = posrelatI(pi, l); - size_t pose = getendpos(L, 3, pi, l); - int n, i; - if (posi > pose) return 0; /* empty interval; return no values */ - if (l_unlikely(pose - posi >= (size_t)INT_MAX)) /* arithmetic overflow? */ - return luaL_error(L, "string slice too long"); - n = (int)(pose - posi) + 1; - luaL_checkstack(L, n, "string slice too long"); - for (i=0; iinit) { - state->init = 1; - luaL_buffinit(L, &state->B); - } - luaL_addlstring(&state->B, (const char *)b, size); - return 0; -} - - -static int str_dump (lua_State *L) { - struct str_Writer state; - int strip = lua_toboolean(L, 2); - luaL_checktype(L, 1, LUA_TFUNCTION); - lua_settop(L, 1); /* ensure function is on the top of the stack */ - state.init = 0; - if (l_unlikely(lua_dump(L, writer, &state, strip) != 0)) - return luaL_error(L, "unable to dump given function"); - luaL_pushresult(&state.B); - return 1; -} - - - -/* -** {====================================================== -** METAMETHODS -** ======================================================= -*/ - -#if defined(LUA_NOCVTS2N) /* { */ - -/* no coercion from strings to numbers */ - -static const luaL_Reg stringmetamethods[] = { - {"__index", NULL}, /* placeholder */ - {NULL, NULL} -}; - -#else /* }{ */ - -static int tonum (lua_State *L, int arg) { - if (lua_type(L, arg) == LUA_TNUMBER) { /* already a number? */ - lua_pushvalue(L, arg); - return 1; - } - else { /* check whether it is a numerical string */ - size_t len; - const char *s = lua_tolstring(L, arg, &len); - return (s != NULL && lua_stringtonumber(L, s) == len + 1); - } -} - - -static void trymt (lua_State *L, const char *mtname) { - lua_settop(L, 2); /* back to the original arguments */ - if (l_unlikely(lua_type(L, 2) == LUA_TSTRING || - !luaL_getmetafield(L, 2, mtname))) - luaL_error(L, "attempt to %s a '%s' with a '%s'", mtname + 2, - luaL_typename(L, -2), luaL_typename(L, -1)); - lua_insert(L, -3); /* put metamethod before arguments */ - lua_call(L, 2, 1); /* call metamethod */ -} - - -static int arith (lua_State *L, int op, const char *mtname) { - if (tonum(L, 1) && tonum(L, 2)) - lua_arith(L, op); /* result will be on the top */ - else - trymt(L, mtname); - return 1; -} - - -static int arith_add (lua_State *L) { - return arith(L, LUA_OPADD, "__add"); -} - -static int arith_sub (lua_State *L) { - return arith(L, LUA_OPSUB, "__sub"); -} - -static int arith_mul (lua_State *L) { - return arith(L, LUA_OPMUL, "__mul"); -} - -static int arith_mod (lua_State *L) { - return arith(L, LUA_OPMOD, "__mod"); -} - -static int arith_pow (lua_State *L) { - return arith(L, LUA_OPPOW, "__pow"); -} - -static int arith_div (lua_State *L) { - return arith(L, LUA_OPDIV, "__div"); -} - -static int arith_idiv (lua_State *L) { - return arith(L, LUA_OPIDIV, "__idiv"); -} - -static int arith_unm (lua_State *L) { - return arith(L, LUA_OPUNM, "__unm"); -} - - -static const luaL_Reg stringmetamethods[] = { - {"__add", arith_add}, - {"__sub", arith_sub}, - {"__mul", arith_mul}, - {"__mod", arith_mod}, - {"__pow", arith_pow}, - {"__div", arith_div}, - {"__idiv", arith_idiv}, - {"__unm", arith_unm}, - {"__index", NULL}, /* placeholder */ - {NULL, NULL} -}; - -#endif /* } */ - -/* }====================================================== */ - -/* -** {====================================================== -** PATTERN MATCHING -** ======================================================= -*/ - - -#define CAP_UNFINISHED (-1) -#define CAP_POSITION (-2) - - -typedef struct MatchState { - const char *src_init; /* init of source string */ - const char *src_end; /* end ('\0') of source string */ - const char *p_end; /* end ('\0') of pattern */ - lua_State *L; - int matchdepth; /* control for recursive depth (to avoid C stack overflow) */ - unsigned char level; /* total number of captures (finished or unfinished) */ - struct { - const char *init; - ptrdiff_t len; - } capture[LUA_MAXCAPTURES]; -} MatchState; - - -/* recursive function */ -static const char *match (MatchState *ms, const char *s, const char *p); - - -/* maximum recursion depth for 'match' */ -#if !defined(MAXCCALLS) -#define MAXCCALLS 200 -#endif - - -#define L_ESC '%' -#define SPECIALS "^$*+?.([%-" - - -static int check_capture (MatchState *ms, int l) { - l -= '1'; - if (l_unlikely(l < 0 || l >= ms->level || - ms->capture[l].len == CAP_UNFINISHED)) - return luaL_error(ms->L, "invalid capture index %%%d", l + 1); - return l; -} - - -static int capture_to_close (MatchState *ms) { - int level = ms->level; - for (level--; level>=0; level--) - if (ms->capture[level].len == CAP_UNFINISHED) return level; - return luaL_error(ms->L, "invalid pattern capture"); -} - - -static const char *classend (MatchState *ms, const char *p) { - switch (*p++) { - case L_ESC: { - if (l_unlikely(p == ms->p_end)) - luaL_error(ms->L, "malformed pattern (ends with '%%')"); - return p+1; - } - case '[': { - if (*p == '^') p++; - do { /* look for a ']' */ - if (l_unlikely(p == ms->p_end)) - luaL_error(ms->L, "malformed pattern (missing ']')"); - if (*(p++) == L_ESC && p < ms->p_end) - p++; /* skip escapes (e.g. '%]') */ - } while (*p != ']'); - return p+1; - } - default: { - return p; - } - } -} - - -static int match_class (int c, int cl) { - int res; - switch (tolower(cl)) { - case 'a' : res = isalpha(c); break; - case 'c' : res = iscntrl(c); break; - case 'd' : res = isdigit(c); break; - case 'g' : res = isgraph(c); break; - case 'l' : res = islower(c); break; - case 'p' : res = ispunct(c); break; - case 's' : res = isspace(c); break; - case 'u' : res = isupper(c); break; - case 'w' : res = isalnum(c); break; - case 'x' : res = isxdigit(c); break; - case 'z' : res = (c == 0); break; /* deprecated option */ - default: return (cl == c); - } - return (islower(cl) ? res : !res); -} - - -static int matchbracketclass (int c, const char *p, const char *ec) { - int sig = 1; - if (*(p+1) == '^') { - sig = 0; - p++; /* skip the '^' */ - } - while (++p < ec) { - if (*p == L_ESC) { - p++; - if (match_class(c, uchar(*p))) - return sig; - } - else if ((*(p+1) == '-') && (p+2 < ec)) { - p+=2; - if (uchar(*(p-2)) <= c && c <= uchar(*p)) - return sig; - } - else if (uchar(*p) == c) return sig; - } - return !sig; -} - - -static int singlematch (MatchState *ms, const char *s, const char *p, - const char *ep) { - if (s >= ms->src_end) - return 0; - else { - int c = uchar(*s); - switch (*p) { - case '.': return 1; /* matches any char */ - case L_ESC: return match_class(c, uchar(*(p+1))); - case '[': return matchbracketclass(c, p, ep-1); - default: return (uchar(*p) == c); - } - } -} - - -static const char *matchbalance (MatchState *ms, const char *s, - const char *p) { - if (l_unlikely(p >= ms->p_end - 1)) - luaL_error(ms->L, "malformed pattern (missing arguments to '%%b')"); - if (*s != *p) return NULL; - else { - int b = *p; - int e = *(p+1); - int cont = 1; - while (++s < ms->src_end) { - if (*s == e) { - if (--cont == 0) return s+1; - } - else if (*s == b) cont++; - } - } - return NULL; /* string ends out of balance */ -} - - -static const char *max_expand (MatchState *ms, const char *s, - const char *p, const char *ep) { - ptrdiff_t i = 0; /* counts maximum expand for item */ - while (singlematch(ms, s + i, p, ep)) - i++; - /* keeps trying to match with the maximum repetitions */ - while (i>=0) { - const char *res = match(ms, (s+i), ep+1); - if (res) return res; - i--; /* else didn't match; reduce 1 repetition to try again */ - } - return NULL; -} - - -static const char *min_expand (MatchState *ms, const char *s, - const char *p, const char *ep) { - for (;;) { - const char *res = match(ms, s, ep+1); - if (res != NULL) - return res; - else if (singlematch(ms, s, p, ep)) - s++; /* try with one more repetition */ - else return NULL; - } -} - - -static const char *start_capture (MatchState *ms, const char *s, - const char *p, int what) { - const char *res; - int level = ms->level; - if (level >= LUA_MAXCAPTURES) luaL_error(ms->L, "too many captures"); - ms->capture[level].init = s; - ms->capture[level].len = what; - ms->level = level+1; - if ((res=match(ms, s, p)) == NULL) /* match failed? */ - ms->level--; /* undo capture */ - return res; -} - - -static const char *end_capture (MatchState *ms, const char *s, - const char *p) { - int l = capture_to_close(ms); - const char *res; - ms->capture[l].len = s - ms->capture[l].init; /* close capture */ - if ((res = match(ms, s, p)) == NULL) /* match failed? */ - ms->capture[l].len = CAP_UNFINISHED; /* undo capture */ - return res; -} - - -static const char *match_capture (MatchState *ms, const char *s, int l) { - size_t len; - l = check_capture(ms, l); - len = ms->capture[l].len; - if ((size_t)(ms->src_end-s) >= len && - memcmp(ms->capture[l].init, s, len) == 0) - return s+len; - else return NULL; -} - - -static const char *match (MatchState *ms, const char *s, const char *p) { - if (l_unlikely(ms->matchdepth-- == 0)) - luaL_error(ms->L, "pattern too complex"); - init: /* using goto to optimize tail recursion */ - if (p != ms->p_end) { /* end of pattern? */ - switch (*p) { - case '(': { /* start capture */ - if (*(p + 1) == ')') /* position capture? */ - s = start_capture(ms, s, p + 2, CAP_POSITION); - else - s = start_capture(ms, s, p + 1, CAP_UNFINISHED); - break; - } - case ')': { /* end capture */ - s = end_capture(ms, s, p + 1); - break; - } - case '$': { - if ((p + 1) != ms->p_end) /* is the '$' the last char in pattern? */ - goto dflt; /* no; go to default */ - s = (s == ms->src_end) ? s : NULL; /* check end of string */ - break; - } - case L_ESC: { /* escaped sequences not in the format class[*+?-]? */ - switch (*(p + 1)) { - case 'b': { /* balanced string? */ - s = matchbalance(ms, s, p + 2); - if (s != NULL) { - p += 4; goto init; /* return match(ms, s, p + 4); */ - } /* else fail (s == NULL) */ - break; - } - case 'f': { /* frontier? */ - const char *ep; char previous; - p += 2; - if (l_unlikely(*p != '[')) - luaL_error(ms->L, "missing '[' after '%%f' in pattern"); - ep = classend(ms, p); /* points to what is next */ - previous = (s == ms->src_init) ? '\0' : *(s - 1); - if (!matchbracketclass(uchar(previous), p, ep - 1) && - matchbracketclass(uchar(*s), p, ep - 1)) { - p = ep; goto init; /* return match(ms, s, ep); */ - } - s = NULL; /* match failed */ - break; - } - case '0': case '1': case '2': case '3': - case '4': case '5': case '6': case '7': - case '8': case '9': { /* capture results (%0-%9)? */ - s = match_capture(ms, s, uchar(*(p + 1))); - if (s != NULL) { - p += 2; goto init; /* return match(ms, s, p + 2) */ - } - break; - } - default: goto dflt; - } - break; - } - default: dflt: { /* pattern class plus optional suffix */ - const char *ep = classend(ms, p); /* points to optional suffix */ - /* does not match at least once? */ - if (!singlematch(ms, s, p, ep)) { - if (*ep == '*' || *ep == '?' || *ep == '-') { /* accept empty? */ - p = ep + 1; goto init; /* return match(ms, s, ep + 1); */ - } - else /* '+' or no suffix */ - s = NULL; /* fail */ - } - else { /* matched once */ - switch (*ep) { /* handle optional suffix */ - case '?': { /* optional */ - const char *res; - if ((res = match(ms, s + 1, ep + 1)) != NULL) - s = res; - else { - p = ep + 1; goto init; /* else return match(ms, s, ep + 1); */ - } - break; - } - case '+': /* 1 or more repetitions */ - s++; /* 1 match already done */ - /* FALLTHROUGH */ - case '*': /* 0 or more repetitions */ - s = max_expand(ms, s, p, ep); - break; - case '-': /* 0 or more repetitions (minimum) */ - s = min_expand(ms, s, p, ep); - break; - default: /* no suffix */ - s++; p = ep; goto init; /* return match(ms, s + 1, ep); */ - } - } - break; - } - } - } - ms->matchdepth++; - return s; -} - - - -static const char *lmemfind (const char *s1, size_t l1, - const char *s2, size_t l2) { - if (l2 == 0) return s1; /* empty strings are everywhere */ - else if (l2 > l1) return NULL; /* avoids a negative 'l1' */ - else { - const char *init; /* to search for a '*s2' inside 's1' */ - l2--; /* 1st char will be checked by 'memchr' */ - l1 = l1-l2; /* 's2' cannot be found after that */ - while (l1 > 0 && (init = (const char *)memchr(s1, *s2, l1)) != NULL) { - init++; /* 1st char is already checked */ - if (memcmp(init, s2+1, l2) == 0) - return init-1; - else { /* correct 'l1' and 's1' to try again */ - l1 -= init-s1; - s1 = init; - } - } - return NULL; /* not found */ - } -} - - -/* -** get information about the i-th capture. If there are no captures -** and 'i==0', return information about the whole match, which -** is the range 's'..'e'. If the capture is a string, return -** its length and put its address in '*cap'. If it is an integer -** (a position), push it on the stack and return CAP_POSITION. -*/ -static size_t get_onecapture (MatchState *ms, int i, const char *s, - const char *e, const char **cap) { - if (i >= ms->level) { - if (l_unlikely(i != 0)) - luaL_error(ms->L, "invalid capture index %%%d", i + 1); - *cap = s; - return e - s; - } - else { - ptrdiff_t capl = ms->capture[i].len; - *cap = ms->capture[i].init; - if (l_unlikely(capl == CAP_UNFINISHED)) - luaL_error(ms->L, "unfinished capture"); - else if (capl == CAP_POSITION) - lua_pushinteger(ms->L, (ms->capture[i].init - ms->src_init) + 1); - return capl; - } -} - - -/* -** Push the i-th capture on the stack. -*/ -static void push_onecapture (MatchState *ms, int i, const char *s, - const char *e) { - const char *cap; - ptrdiff_t l = get_onecapture(ms, i, s, e, &cap); - if (l != CAP_POSITION) - lua_pushlstring(ms->L, cap, l); - /* else position was already pushed */ -} - - -static int push_captures (MatchState *ms, const char *s, const char *e) { - int i; - int nlevels = (ms->level == 0 && s) ? 1 : ms->level; - luaL_checkstack(ms->L, nlevels, "too many captures"); - for (i = 0; i < nlevels; i++) - push_onecapture(ms, i, s, e); - return nlevels; /* number of strings pushed */ -} - - -/* check whether pattern has no special characters */ -static int nospecials (const char *p, size_t l) { - size_t upto = 0; - do { - if (strpbrk(p + upto, SPECIALS)) - return 0; /* pattern has a special character */ - upto += strlen(p + upto) + 1; /* may have more after \0 */ - } while (upto <= l); - return 1; /* no special chars found */ -} - - -static void prepstate (MatchState *ms, lua_State *L, - const char *s, size_t ls, const char *p, size_t lp) { - ms->L = L; - ms->matchdepth = MAXCCALLS; - ms->src_init = s; - ms->src_end = s + ls; - ms->p_end = p + lp; -} - - -static void reprepstate (MatchState *ms) { - ms->level = 0; - lua_assert(ms->matchdepth == MAXCCALLS); -} - - -static int str_find_aux (lua_State *L, int find) { - size_t ls, lp; - const char *s = luaL_checklstring(L, 1, &ls); - const char *p = luaL_checklstring(L, 2, &lp); - size_t init = posrelatI(luaL_optinteger(L, 3, 1), ls) - 1; - if (init > ls) { /* start after string's end? */ - luaL_pushfail(L); /* cannot find anything */ - return 1; - } - /* explicit request or no special characters? */ - if (find && (lua_toboolean(L, 4) || nospecials(p, lp))) { - /* do a plain search */ - const char *s2 = lmemfind(s + init, ls - init, p, lp); - if (s2) { - lua_pushinteger(L, (s2 - s) + 1); - lua_pushinteger(L, (s2 - s) + lp); - return 2; - } - } - else { - MatchState ms; - const char *s1 = s + init; - int anchor = (*p == '^'); - if (anchor) { - p++; lp--; /* skip anchor character */ - } - prepstate(&ms, L, s, ls, p, lp); - do { - const char *res; - reprepstate(&ms); - if ((res=match(&ms, s1, p)) != NULL) { - if (find) { - lua_pushinteger(L, (s1 - s) + 1); /* start */ - lua_pushinteger(L, res - s); /* end */ - return push_captures(&ms, NULL, 0) + 2; - } - else - return push_captures(&ms, s1, res); - } - } while (s1++ < ms.src_end && !anchor); - } - luaL_pushfail(L); /* not found */ - return 1; -} - - -static int str_find (lua_State *L) { - return str_find_aux(L, 1); -} - - -static int str_match (lua_State *L) { - return str_find_aux(L, 0); -} - - -/* state for 'gmatch' */ -typedef struct GMatchState { - const char *src; /* current position */ - const char *p; /* pattern */ - const char *lastmatch; /* end of last match */ - MatchState ms; /* match state */ -} GMatchState; - - -static int gmatch_aux (lua_State *L) { - GMatchState *gm = (GMatchState *)lua_touserdata(L, lua_upvalueindex(3)); - const char *src; - gm->ms.L = L; - for (src = gm->src; src <= gm->ms.src_end; src++) { - const char *e; - reprepstate(&gm->ms); - if ((e = match(&gm->ms, src, gm->p)) != NULL && e != gm->lastmatch) { - gm->src = gm->lastmatch = e; - return push_captures(&gm->ms, src, e); - } - } - return 0; /* not found */ -} - - -static int gmatch (lua_State *L) { - size_t ls, lp; - const char *s = luaL_checklstring(L, 1, &ls); - const char *p = luaL_checklstring(L, 2, &lp); - size_t init = posrelatI(luaL_optinteger(L, 3, 1), ls) - 1; - GMatchState *gm; - lua_settop(L, 2); /* keep strings on closure to avoid being collected */ - gm = (GMatchState *)lua_newuserdatauv(L, sizeof(GMatchState), 0); - if (init > ls) /* start after string's end? */ - init = ls + 1; /* avoid overflows in 's + init' */ - prepstate(&gm->ms, L, s, ls, p, lp); - gm->src = s + init; gm->p = p; gm->lastmatch = NULL; - lua_pushcclosure(L, gmatch_aux, 3); - return 1; -} - - -static void add_s (MatchState *ms, luaL_Buffer *b, const char *s, - const char *e) { - size_t l; - lua_State *L = ms->L; - const char *news = lua_tolstring(L, 3, &l); - const char *p; - while ((p = (char *)memchr(news, L_ESC, l)) != NULL) { - luaL_addlstring(b, news, p - news); - p++; /* skip ESC */ - if (*p == L_ESC) /* '%%' */ - luaL_addchar(b, *p); - else if (*p == '0') /* '%0' */ - luaL_addlstring(b, s, e - s); - else if (isdigit(uchar(*p))) { /* '%n' */ - const char *cap; - ptrdiff_t resl = get_onecapture(ms, *p - '1', s, e, &cap); - if (resl == CAP_POSITION) - luaL_addvalue(b); /* add position to accumulated result */ - else - luaL_addlstring(b, cap, resl); - } - else - luaL_error(L, "invalid use of '%c' in replacement string", L_ESC); - l -= p + 1 - news; - news = p + 1; - } - luaL_addlstring(b, news, l); -} - - -/* -** Add the replacement value to the string buffer 'b'. -** Return true if the original string was changed. (Function calls and -** table indexing resulting in nil or false do not change the subject.) -*/ -static int add_value (MatchState *ms, luaL_Buffer *b, const char *s, - const char *e, int tr) { - lua_State *L = ms->L; - switch (tr) { - case LUA_TFUNCTION: { /* call the function */ - int n; - lua_pushvalue(L, 3); /* push the function */ - n = push_captures(ms, s, e); /* all captures as arguments */ - lua_call(L, n, 1); /* call it */ - break; - } - case LUA_TTABLE: { /* index the table */ - push_onecapture(ms, 0, s, e); /* first capture is the index */ - lua_gettable(L, 3); - break; - } - default: { /* LUA_TNUMBER or LUA_TSTRING */ - add_s(ms, b, s, e); /* add value to the buffer */ - return 1; /* something changed */ - } - } - if (!lua_toboolean(L, -1)) { /* nil or false? */ - lua_pop(L, 1); /* remove value */ - luaL_addlstring(b, s, e - s); /* keep original text */ - return 0; /* no changes */ - } - else if (l_unlikely(!lua_isstring(L, -1))) - return luaL_error(L, "invalid replacement value (a %s)", - luaL_typename(L, -1)); - else { - luaL_addvalue(b); /* add result to accumulator */ - return 1; /* something changed */ - } -} - - -static int str_gsub (lua_State *L) { - size_t srcl, lp; - const char *src = luaL_checklstring(L, 1, &srcl); /* subject */ - const char *p = luaL_checklstring(L, 2, &lp); /* pattern */ - const char *lastmatch = NULL; /* end of last match */ - int tr = lua_type(L, 3); /* replacement type */ - lua_Integer max_s = luaL_optinteger(L, 4, srcl + 1); /* max replacements */ - int anchor = (*p == '^'); - lua_Integer n = 0; /* replacement count */ - int changed = 0; /* change flag */ - MatchState ms; - luaL_Buffer b; - luaL_argexpected(L, tr == LUA_TNUMBER || tr == LUA_TSTRING || - tr == LUA_TFUNCTION || tr == LUA_TTABLE, 3, - "string/function/table"); - luaL_buffinit(L, &b); - if (anchor) { - p++; lp--; /* skip anchor character */ - } - prepstate(&ms, L, src, srcl, p, lp); - while (n < max_s) { - const char *e; - reprepstate(&ms); /* (re)prepare state for new match */ - if ((e = match(&ms, src, p)) != NULL && e != lastmatch) { /* match? */ - n++; - changed = add_value(&ms, &b, src, e, tr) | changed; - src = lastmatch = e; - } - else if (src < ms.src_end) /* otherwise, skip one character */ - luaL_addchar(&b, *src++); - else break; /* end of subject */ - if (anchor) break; - } - if (!changed) /* no changes? */ - lua_pushvalue(L, 1); /* return original string */ - else { /* something changed */ - luaL_addlstring(&b, src, ms.src_end-src); - luaL_pushresult(&b); /* create and return new string */ - } - lua_pushinteger(L, n); /* number of substitutions */ - return 2; -} - -/* }====================================================== */ - - - -/* -** {====================================================== -** STRING FORMAT -** ======================================================= -*/ - -#if !defined(lua_number2strx) /* { */ - -/* -** Hexadecimal floating-point formatter -*/ - -#define SIZELENMOD (sizeof(LUA_NUMBER_FRMLEN)/sizeof(char)) - - -/* -** Number of bits that goes into the first digit. It can be any value -** between 1 and 4; the following definition tries to align the number -** to nibble boundaries by making what is left after that first digit a -** multiple of 4. -*/ -#define L_NBFD ((l_floatatt(MANT_DIG) - 1)%4 + 1) - - -/* -** Add integer part of 'x' to buffer and return new 'x' -*/ -static lua_Number adddigit (char *buff, int n, lua_Number x) { - lua_Number dd = l_mathop(floor)(x); /* get integer part from 'x' */ - int d = (int)dd; - buff[n] = (d < 10 ? d + '0' : d - 10 + 'a'); /* add to buffer */ - return x - dd; /* return what is left */ -} - - -static int num2straux (char *buff, int sz, lua_Number x) { - /* if 'inf' or 'NaN', format it like '%g' */ - if (x != x || x == (lua_Number)HUGE_VAL || x == -(lua_Number)HUGE_VAL) - return l_sprintf(buff, sz, LUA_NUMBER_FMT, (LUAI_UACNUMBER)x); - else if (x == 0) { /* can be -0... */ - /* create "0" or "-0" followed by exponent */ - return l_sprintf(buff, sz, LUA_NUMBER_FMT "x0p+0", (LUAI_UACNUMBER)x); - } - else { - int e; - lua_Number m = l_mathop(frexp)(x, &e); /* 'x' fraction and exponent */ - int n = 0; /* character count */ - if (m < 0) { /* is number negative? */ - buff[n++] = '-'; /* add sign */ - m = -m; /* make it positive */ - } - buff[n++] = '0'; buff[n++] = 'x'; /* add "0x" */ - m = adddigit(buff, n++, m * (1 << L_NBFD)); /* add first digit */ - e -= L_NBFD; /* this digit goes before the radix point */ - if (m > 0) { /* more digits? */ - buff[n++] = lua_getlocaledecpoint(); /* add radix point */ - do { /* add as many digits as needed */ - m = adddigit(buff, n++, m * 16); - } while (m > 0); - } - n += l_sprintf(buff + n, sz - n, "p%+d", e); /* add exponent */ - lua_assert(n < sz); - return n; - } -} - - -static int lua_number2strx (lua_State *L, char *buff, int sz, - const char *fmt, lua_Number x) { - int n = num2straux(buff, sz, x); - if (fmt[SIZELENMOD] == 'A') { - int i; - for (i = 0; i < n; i++) - buff[i] = toupper(uchar(buff[i])); - } - else if (l_unlikely(fmt[SIZELENMOD] != 'a')) - return luaL_error(L, "modifiers for format '%%a'/'%%A' not implemented"); - return n; -} - -#endif /* } */ - - -/* -** Maximum size for items formatted with '%f'. This size is produced -** by format('%.99f', -maxfloat), and is equal to 99 + 3 ('-', '.', -** and '\0') + number of decimal digits to represent maxfloat (which -** is maximum exponent + 1). (99+3+1, adding some extra, 110) -*/ -#define MAX_ITEMF (110 + l_floatatt(MAX_10_EXP)) - - -/* -** All formats except '%f' do not need that large limit. The other -** float formats use exponents, so that they fit in the 99 limit for -** significant digits; 's' for large strings and 'q' add items directly -** to the buffer; all integer formats also fit in the 99 limit. The -** worst case are floats: they may need 99 significant digits, plus -** '0x', '-', '.', 'e+XXXX', and '\0'. Adding some extra, 120. -*/ -#define MAX_ITEM 120 - - -/* valid flags in a format specification */ -#if !defined(L_FMTFLAGSF) - -/* valid flags for a, A, e, E, f, F, g, and G conversions */ -#define L_FMTFLAGSF "-+#0 " - -/* valid flags for o, x, and X conversions */ -#define L_FMTFLAGSX "-#0" - -/* valid flags for d and i conversions */ -#define L_FMTFLAGSI "-+0 " - -/* valid flags for u conversions */ -#define L_FMTFLAGSU "-0" - -/* valid flags for c, p, and s conversions */ -#define L_FMTFLAGSC "-" - -#endif - - -/* -** Maximum size of each format specification (such as "%-099.99d"): -** Initial '%', flags (up to 5), width (2), period, precision (2), -** length modifier (8), conversion specifier, and final '\0', plus some -** extra. -*/ -#define MAX_FORMAT 32 - - -static void addquoted (luaL_Buffer *b, const char *s, size_t len) { - luaL_addchar(b, '"'); - while (len--) { - if (*s == '"' || *s == '\\' || *s == '\n') { - luaL_addchar(b, '\\'); - luaL_addchar(b, *s); - } - else if (iscntrl(uchar(*s))) { - char buff[10]; - if (!isdigit(uchar(*(s+1)))) - l_sprintf(buff, sizeof(buff), "\\%d", (int)uchar(*s)); - else - l_sprintf(buff, sizeof(buff), "\\%03d", (int)uchar(*s)); - luaL_addstring(b, buff); - } - else - luaL_addchar(b, *s); - s++; - } - luaL_addchar(b, '"'); -} - - -/* -** Serialize a floating-point number in such a way that it can be -** scanned back by Lua. Use hexadecimal format for "common" numbers -** (to preserve precision); inf, -inf, and NaN are handled separately. -** (NaN cannot be expressed as a numeral, so we write '(0/0)' for it.) -*/ -static int quotefloat (lua_State *L, char *buff, lua_Number n) { - const char *s; /* for the fixed representations */ - if (n == (lua_Number)HUGE_VAL) /* inf? */ - s = "1e9999"; - else if (n == -(lua_Number)HUGE_VAL) /* -inf? */ - s = "-1e9999"; - else if (n != n) /* NaN? */ - s = "(0/0)"; - else { /* format number as hexadecimal */ - int nb = lua_number2strx(L, buff, MAX_ITEM, - "%" LUA_NUMBER_FRMLEN "a", n); - /* ensures that 'buff' string uses a dot as the radix character */ - if (memchr(buff, '.', nb) == NULL) { /* no dot? */ - char point = lua_getlocaledecpoint(); /* try locale point */ - char *ppoint = (char *)memchr(buff, point, nb); - if (ppoint) *ppoint = '.'; /* change it to a dot */ - } - return nb; - } - /* for the fixed representations */ - return l_sprintf(buff, MAX_ITEM, "%s", s); -} - - -static void addliteral (lua_State *L, luaL_Buffer *b, int arg) { - switch (lua_type(L, arg)) { - case LUA_TSTRING: { - size_t len; - const char *s = lua_tolstring(L, arg, &len); - addquoted(b, s, len); - break; - } - case LUA_TNUMBER: { - char *buff = luaL_prepbuffsize(b, MAX_ITEM); - int nb; - if (!lua_isinteger(L, arg)) /* float? */ - nb = quotefloat(L, buff, lua_tonumber(L, arg)); - else { /* integers */ - lua_Integer n = lua_tointeger(L, arg); - const char *format = (n == LUA_MININTEGER) /* corner case? */ - ? "0x%" LUA_INTEGER_FRMLEN "x" /* use hex */ - : LUA_INTEGER_FMT; /* else use default format */ - nb = l_sprintf(buff, MAX_ITEM, format, (LUAI_UACINT)n); - } - luaL_addsize(b, nb); - break; - } - case LUA_TNIL: case LUA_TBOOLEAN: { - luaL_tolstring(L, arg, NULL); - luaL_addvalue(b); - break; - } - default: { - luaL_argerror(L, arg, "value has no literal form"); - } - } -} - - -static const char *get2digits (const char *s) { - if (isdigit(uchar(*s))) { - s++; - if (isdigit(uchar(*s))) s++; /* (2 digits at most) */ - } - return s; -} - - -/* -** Check whether a conversion specification is valid. When called, -** first character in 'form' must be '%' and last character must -** be a valid conversion specifier. 'flags' are the accepted flags; -** 'precision' signals whether to accept a precision. -*/ -static void checkformat (lua_State *L, const char *form, const char *flags, - int precision) { - const char *spec = form + 1; /* skip '%' */ - spec += strspn(spec, flags); /* skip flags */ - if (*spec != '0') { /* a width cannot start with '0' */ - spec = get2digits(spec); /* skip width */ - if (*spec == '.' && precision) { - spec++; - spec = get2digits(spec); /* skip precision */ - } - } - if (!isalpha(uchar(*spec))) /* did not go to the end? */ - luaL_error(L, "invalid conversion specification: '%s'", form); -} - - -/* -** Get a conversion specification and copy it to 'form'. -** Return the address of its last character. -*/ -static const char *getformat (lua_State *L, const char *strfrmt, - char *form) { - /* spans flags, width, and precision ('0' is included as a flag) */ - size_t len = strspn(strfrmt, L_FMTFLAGSF "123456789."); - len++; /* adds following character (should be the specifier) */ - /* still needs space for '%', '\0', plus a length modifier */ - if (len >= MAX_FORMAT - 10) - luaL_error(L, "invalid format (too long)"); - *(form++) = '%'; - memcpy(form, strfrmt, len * sizeof(char)); - *(form + len) = '\0'; - return strfrmt + len - 1; -} - - -/* -** add length modifier into formats -*/ -static void addlenmod (char *form, const char *lenmod) { - size_t l = strlen(form); - size_t lm = strlen(lenmod); - char spec = form[l - 1]; - strcpy(form + l - 1, lenmod); - form[l + lm - 1] = spec; - form[l + lm] = '\0'; -} - - -static int str_format (lua_State *L) { - int top = lua_gettop(L); - int arg = 1; - size_t sfl; - const char *strfrmt = luaL_checklstring(L, arg, &sfl); - const char *strfrmt_end = strfrmt+sfl; - const char *flags; - luaL_Buffer b; - luaL_buffinit(L, &b); - while (strfrmt < strfrmt_end) { - if (*strfrmt != L_ESC) - luaL_addchar(&b, *strfrmt++); - else if (*++strfrmt == L_ESC) - luaL_addchar(&b, *strfrmt++); /* %% */ - else { /* format item */ - char form[MAX_FORMAT]; /* to store the format ('%...') */ - int maxitem = MAX_ITEM; /* maximum length for the result */ - char *buff = luaL_prepbuffsize(&b, maxitem); /* to put result */ - int nb = 0; /* number of bytes in result */ - if (++arg > top) - return luaL_argerror(L, arg, "no value"); - strfrmt = getformat(L, strfrmt, form); - switch (*strfrmt++) { - case 'c': { - checkformat(L, form, L_FMTFLAGSC, 0); - nb = l_sprintf(buff, maxitem, form, (int)luaL_checkinteger(L, arg)); - break; - } - case 'd': case 'i': - flags = L_FMTFLAGSI; - goto intcase; - case 'u': - flags = L_FMTFLAGSU; - goto intcase; - case 'o': case 'x': case 'X': - flags = L_FMTFLAGSX; - intcase: { - lua_Integer n = luaL_checkinteger(L, arg); - checkformat(L, form, flags, 1); - addlenmod(form, LUA_INTEGER_FRMLEN); - nb = l_sprintf(buff, maxitem, form, (LUAI_UACINT)n); - break; - } - case 'a': case 'A': - checkformat(L, form, L_FMTFLAGSF, 1); - addlenmod(form, LUA_NUMBER_FRMLEN); - nb = lua_number2strx(L, buff, maxitem, form, - luaL_checknumber(L, arg)); - break; - case 'f': - maxitem = MAX_ITEMF; /* extra space for '%f' */ - buff = luaL_prepbuffsize(&b, maxitem); - /* FALLTHROUGH */ - case 'e': case 'E': case 'g': case 'G': { - lua_Number n = luaL_checknumber(L, arg); - checkformat(L, form, L_FMTFLAGSF, 1); - addlenmod(form, LUA_NUMBER_FRMLEN); - nb = l_sprintf(buff, maxitem, form, (LUAI_UACNUMBER)n); - break; - } - case 'p': { - const void *p = lua_topointer(L, arg); - checkformat(L, form, L_FMTFLAGSC, 0); - if (p == NULL) { /* avoid calling 'printf' with argument NULL */ - p = "(null)"; /* result */ - form[strlen(form) - 1] = 's'; /* format it as a string */ - } - nb = l_sprintf(buff, maxitem, form, p); - break; - } - case 'q': { - if (form[2] != '\0') /* modifiers? */ - return luaL_error(L, "specifier '%%q' cannot have modifiers"); - addliteral(L, &b, arg); - break; - } - case 's': { - size_t l; - const char *s = luaL_tolstring(L, arg, &l); - if (form[2] == '\0') /* no modifiers? */ - luaL_addvalue(&b); /* keep entire string */ - else { - luaL_argcheck(L, l == strlen(s), arg, "string contains zeros"); - checkformat(L, form, L_FMTFLAGSC, 1); - if (strchr(form, '.') == NULL && l >= 100) { - /* no precision and string is too long to be formatted */ - luaL_addvalue(&b); /* keep entire string */ - } - else { /* format the string into 'buff' */ - nb = l_sprintf(buff, maxitem, form, s); - lua_pop(L, 1); /* remove result from 'luaL_tolstring' */ - } - } - break; - } - default: { /* also treat cases 'pnLlh' */ - return luaL_error(L, "invalid conversion '%s' to 'format'", form); - } - } - lua_assert(nb < maxitem); - luaL_addsize(&b, nb); - } - } - luaL_pushresult(&b); - return 1; -} - -/* }====================================================== */ - - -/* -** {====================================================== -** PACK/UNPACK -** ======================================================= -*/ - - -/* value used for padding */ -#if !defined(LUAL_PACKPADBYTE) -#define LUAL_PACKPADBYTE 0x00 -#endif - -/* maximum size for the binary representation of an integer */ -#define MAXINTSIZE 16 - -/* number of bits in a character */ -#define NB CHAR_BIT - -/* mask for one character (NB 1's) */ -#define MC ((1 << NB) - 1) - -/* size of a lua_Integer */ -#define SZINT ((int)sizeof(lua_Integer)) - - -/* dummy union to get native endianness */ -static const union { - int dummy; - char little; /* true iff machine is little endian */ -} nativeendian = {1}; - - -/* -** information to pack/unpack stuff -*/ -typedef struct Header { - lua_State *L; - int islittle; - int maxalign; -} Header; - - -/* -** options for pack/unpack -*/ -typedef enum KOption { - Kint, /* signed integers */ - Kuint, /* unsigned integers */ - Kfloat, /* single-precision floating-point numbers */ - Knumber, /* Lua "native" floating-point numbers */ - Kdouble, /* double-precision floating-point numbers */ - Kchar, /* fixed-length strings */ - Kstring, /* strings with prefixed length */ - Kzstr, /* zero-terminated strings */ - Kpadding, /* padding */ - Kpaddalign, /* padding for alignment */ - Knop /* no-op (configuration or spaces) */ -} KOption; - - -/* -** Read an integer numeral from string 'fmt' or return 'df' if -** there is no numeral -*/ -static int digit (int c) { return '0' <= c && c <= '9'; } - -static int getnum (const char **fmt, int df) { - if (!digit(**fmt)) /* no number? */ - return df; /* return default value */ - else { - int a = 0; - do { - a = a*10 + (*((*fmt)++) - '0'); - } while (digit(**fmt) && a <= ((int)MAXSIZE - 9)/10); - return a; - } -} - - -/* -** Read an integer numeral and raises an error if it is larger -** than the maximum size for integers. -*/ -static int getnumlimit (Header *h, const char **fmt, int df) { - int sz = getnum(fmt, df); - if (l_unlikely(sz > MAXINTSIZE || sz <= 0)) - return luaL_error(h->L, "integral size (%d) out of limits [1,%d]", - sz, MAXINTSIZE); - return sz; -} - - -/* -** Initialize Header -*/ -static void initheader (lua_State *L, Header *h) { - h->L = L; - h->islittle = nativeendian.little; - h->maxalign = 1; -} - - -/* -** Read and classify next option. 'size' is filled with option's size. -*/ -static KOption getoption (Header *h, const char **fmt, int *size) { - /* dummy structure to get native alignment requirements */ - struct cD { char c; union { LUAI_MAXALIGN; } u; }; - int opt = *((*fmt)++); - *size = 0; /* default */ - switch (opt) { - case 'b': *size = sizeof(char); return Kint; - case 'B': *size = sizeof(char); return Kuint; - case 'h': *size = sizeof(short); return Kint; - case 'H': *size = sizeof(short); return Kuint; - case 'l': *size = sizeof(long); return Kint; - case 'L': *size = sizeof(long); return Kuint; - case 'j': *size = sizeof(lua_Integer); return Kint; - case 'J': *size = sizeof(lua_Integer); return Kuint; - case 'T': *size = sizeof(size_t); return Kuint; - case 'f': *size = sizeof(float); return Kfloat; - case 'n': *size = sizeof(lua_Number); return Knumber; - case 'd': *size = sizeof(double); return Kdouble; - case 'i': *size = getnumlimit(h, fmt, sizeof(int)); return Kint; - case 'I': *size = getnumlimit(h, fmt, sizeof(int)); return Kuint; - case 's': *size = getnumlimit(h, fmt, sizeof(size_t)); return Kstring; - case 'c': - *size = getnum(fmt, -1); - if (l_unlikely(*size == -1)) - luaL_error(h->L, "missing size for format option 'c'"); - return Kchar; - case 'z': return Kzstr; - case 'x': *size = 1; return Kpadding; - case 'X': return Kpaddalign; - case ' ': break; - case '<': h->islittle = 1; break; - case '>': h->islittle = 0; break; - case '=': h->islittle = nativeendian.little; break; - case '!': { - const int maxalign = offsetof(struct cD, u); - h->maxalign = getnumlimit(h, fmt, maxalign); - break; - } - default: luaL_error(h->L, "invalid format option '%c'", opt); - } - return Knop; -} - - -/* -** Read, classify, and fill other details about the next option. -** 'psize' is filled with option's size, 'notoalign' with its -** alignment requirements. -** Local variable 'size' gets the size to be aligned. (Kpadal option -** always gets its full alignment, other options are limited by -** the maximum alignment ('maxalign'). Kchar option needs no alignment -** despite its size. -*/ -static KOption getdetails (Header *h, size_t totalsize, - const char **fmt, int *psize, int *ntoalign) { - KOption opt = getoption(h, fmt, psize); - int align = *psize; /* usually, alignment follows size */ - if (opt == Kpaddalign) { /* 'X' gets alignment from following option */ - if (**fmt == '\0' || getoption(h, fmt, &align) == Kchar || align == 0) - luaL_argerror(h->L, 1, "invalid next option for option 'X'"); - } - if (align <= 1 || opt == Kchar) /* need no alignment? */ - *ntoalign = 0; - else { - if (align > h->maxalign) /* enforce maximum alignment */ - align = h->maxalign; - if (l_unlikely((align & (align - 1)) != 0)) /* not a power of 2? */ - luaL_argerror(h->L, 1, "format asks for alignment not power of 2"); - *ntoalign = (align - (int)(totalsize & (align - 1))) & (align - 1); - } - return opt; -} - - -/* -** Pack integer 'n' with 'size' bytes and 'islittle' endianness. -** The final 'if' handles the case when 'size' is larger than -** the size of a Lua integer, correcting the extra sign-extension -** bytes if necessary (by default they would be zeros). -*/ -static void packint (luaL_Buffer *b, lua_Unsigned n, - int islittle, int size, int neg) { - char *buff = luaL_prepbuffsize(b, size); - int i; - buff[islittle ? 0 : size - 1] = (char)(n & MC); /* first byte */ - for (i = 1; i < size; i++) { - n >>= NB; - buff[islittle ? i : size - 1 - i] = (char)(n & MC); - } - if (neg && size > SZINT) { /* negative number need sign extension? */ - for (i = SZINT; i < size; i++) /* correct extra bytes */ - buff[islittle ? i : size - 1 - i] = (char)MC; - } - luaL_addsize(b, size); /* add result to buffer */ -} - - -/* -** Copy 'size' bytes from 'src' to 'dest', correcting endianness if -** given 'islittle' is different from native endianness. -*/ -static void copywithendian (char *dest, const char *src, - int size, int islittle) { - if (islittle == nativeendian.little) - memcpy(dest, src, size); - else { - dest += size - 1; - while (size-- != 0) - *(dest--) = *(src++); - } -} - - -static int str_pack (lua_State *L) { - luaL_Buffer b; - Header h; - const char *fmt = luaL_checkstring(L, 1); /* format string */ - int arg = 1; /* current argument to pack */ - size_t totalsize = 0; /* accumulate total size of result */ - initheader(L, &h); - lua_pushnil(L); /* mark to separate arguments from string buffer */ - luaL_buffinit(L, &b); - while (*fmt != '\0') { - int size, ntoalign; - KOption opt = getdetails(&h, totalsize, &fmt, &size, &ntoalign); - totalsize += ntoalign + size; - while (ntoalign-- > 0) - luaL_addchar(&b, LUAL_PACKPADBYTE); /* fill alignment */ - arg++; - switch (opt) { - case Kint: { /* signed integers */ - lua_Integer n = luaL_checkinteger(L, arg); - if (size < SZINT) { /* need overflow check? */ - lua_Integer lim = (lua_Integer)1 << ((size * NB) - 1); - luaL_argcheck(L, -lim <= n && n < lim, arg, "integer overflow"); - } - packint(&b, (lua_Unsigned)n, h.islittle, size, (n < 0)); - break; - } - case Kuint: { /* unsigned integers */ - lua_Integer n = luaL_checkinteger(L, arg); - if (size < SZINT) /* need overflow check? */ - luaL_argcheck(L, (lua_Unsigned)n < ((lua_Unsigned)1 << (size * NB)), - arg, "unsigned overflow"); - packint(&b, (lua_Unsigned)n, h.islittle, size, 0); - break; - } - case Kfloat: { /* C float */ - float f = (float)luaL_checknumber(L, arg); /* get argument */ - char *buff = luaL_prepbuffsize(&b, sizeof(f)); - /* move 'f' to final result, correcting endianness if needed */ - copywithendian(buff, (char *)&f, sizeof(f), h.islittle); - luaL_addsize(&b, size); - break; - } - case Knumber: { /* Lua float */ - lua_Number f = luaL_checknumber(L, arg); /* get argument */ - char *buff = luaL_prepbuffsize(&b, sizeof(f)); - /* move 'f' to final result, correcting endianness if needed */ - copywithendian(buff, (char *)&f, sizeof(f), h.islittle); - luaL_addsize(&b, size); - break; - } - case Kdouble: { /* C double */ - double f = (double)luaL_checknumber(L, arg); /* get argument */ - char *buff = luaL_prepbuffsize(&b, sizeof(f)); - /* move 'f' to final result, correcting endianness if needed */ - copywithendian(buff, (char *)&f, sizeof(f), h.islittle); - luaL_addsize(&b, size); - break; - } - case Kchar: { /* fixed-size string */ - size_t len; - const char *s = luaL_checklstring(L, arg, &len); - luaL_argcheck(L, len <= (size_t)size, arg, - "string longer than given size"); - luaL_addlstring(&b, s, len); /* add string */ - while (len++ < (size_t)size) /* pad extra space */ - luaL_addchar(&b, LUAL_PACKPADBYTE); - break; - } - case Kstring: { /* strings with length count */ - size_t len; - const char *s = luaL_checklstring(L, arg, &len); - luaL_argcheck(L, size >= (int)sizeof(size_t) || - len < ((size_t)1 << (size * NB)), - arg, "string length does not fit in given size"); - packint(&b, (lua_Unsigned)len, h.islittle, size, 0); /* pack length */ - luaL_addlstring(&b, s, len); - totalsize += len; - break; - } - case Kzstr: { /* zero-terminated string */ - size_t len; - const char *s = luaL_checklstring(L, arg, &len); - luaL_argcheck(L, strlen(s) == len, arg, "string contains zeros"); - luaL_addlstring(&b, s, len); - luaL_addchar(&b, '\0'); /* add zero at the end */ - totalsize += len + 1; - break; - } - case Kpadding: luaL_addchar(&b, LUAL_PACKPADBYTE); /* FALLTHROUGH */ - case Kpaddalign: case Knop: - arg--; /* undo increment */ - break; - } - } - luaL_pushresult(&b); - return 1; -} - - -static int str_packsize (lua_State *L) { - Header h; - const char *fmt = luaL_checkstring(L, 1); /* format string */ - size_t totalsize = 0; /* accumulate total size of result */ - initheader(L, &h); - while (*fmt != '\0') { - int size, ntoalign; - KOption opt = getdetails(&h, totalsize, &fmt, &size, &ntoalign); - luaL_argcheck(L, opt != Kstring && opt != Kzstr, 1, - "variable-length format"); - size += ntoalign; /* total space used by option */ - luaL_argcheck(L, totalsize <= MAXSIZE - size, 1, - "format result too large"); - totalsize += size; - } - lua_pushinteger(L, (lua_Integer)totalsize); - return 1; -} - - -/* -** Unpack an integer with 'size' bytes and 'islittle' endianness. -** If size is smaller than the size of a Lua integer and integer -** is signed, must do sign extension (propagating the sign to the -** higher bits); if size is larger than the size of a Lua integer, -** it must check the unread bytes to see whether they do not cause an -** overflow. -*/ -static lua_Integer unpackint (lua_State *L, const char *str, - int islittle, int size, int issigned) { - lua_Unsigned res = 0; - int i; - int limit = (size <= SZINT) ? size : SZINT; - for (i = limit - 1; i >= 0; i--) { - res <<= NB; - res |= (lua_Unsigned)(unsigned char)str[islittle ? i : size - 1 - i]; - } - if (size < SZINT) { /* real size smaller than lua_Integer? */ - if (issigned) { /* needs sign extension? */ - lua_Unsigned mask = (lua_Unsigned)1 << (size*NB - 1); - res = ((res ^ mask) - mask); /* do sign extension */ - } - } - else if (size > SZINT) { /* must check unread bytes */ - int mask = (!issigned || (lua_Integer)res >= 0) ? 0 : MC; - for (i = limit; i < size; i++) { - if (l_unlikely((unsigned char)str[islittle ? i : size - 1 - i] != mask)) - luaL_error(L, "%d-byte integer does not fit into Lua Integer", size); - } - } - return (lua_Integer)res; -} - - -static int str_unpack (lua_State *L) { - Header h; - const char *fmt = luaL_checkstring(L, 1); - size_t ld; - const char *data = luaL_checklstring(L, 2, &ld); - size_t pos = posrelatI(luaL_optinteger(L, 3, 1), ld) - 1; - int n = 0; /* number of results */ - luaL_argcheck(L, pos <= ld, 3, "initial position out of string"); - initheader(L, &h); - while (*fmt != '\0') { - int size, ntoalign; - KOption opt = getdetails(&h, pos, &fmt, &size, &ntoalign); - luaL_argcheck(L, (size_t)ntoalign + size <= ld - pos, 2, - "data string too short"); - pos += ntoalign; /* skip alignment */ - /* stack space for item + next position */ - luaL_checkstack(L, 2, "too many results"); - n++; - switch (opt) { - case Kint: - case Kuint: { - lua_Integer res = unpackint(L, data + pos, h.islittle, size, - (opt == Kint)); - lua_pushinteger(L, res); - break; - } - case Kfloat: { - float f; - copywithendian((char *)&f, data + pos, sizeof(f), h.islittle); - lua_pushnumber(L, (lua_Number)f); - break; - } - case Knumber: { - lua_Number f; - copywithendian((char *)&f, data + pos, sizeof(f), h.islittle); - lua_pushnumber(L, f); - break; - } - case Kdouble: { - double f; - copywithendian((char *)&f, data + pos, sizeof(f), h.islittle); - lua_pushnumber(L, (lua_Number)f); - break; - } - case Kchar: { - lua_pushlstring(L, data + pos, size); - break; - } - case Kstring: { - size_t len = (size_t)unpackint(L, data + pos, h.islittle, size, 0); - luaL_argcheck(L, len <= ld - pos - size, 2, "data string too short"); - lua_pushlstring(L, data + pos + size, len); - pos += len; /* skip string */ - break; - } - case Kzstr: { - size_t len = strlen(data + pos); - luaL_argcheck(L, pos + len < ld, 2, - "unfinished string for format 'z'"); - lua_pushlstring(L, data + pos, len); - pos += len + 1; /* skip string plus final '\0' */ - break; - } - case Kpaddalign: case Kpadding: case Knop: - n--; /* undo increment */ - break; - } - pos += size; - } - lua_pushinteger(L, pos + 1); /* next position */ - return n + 1; -} - -/* }====================================================== */ - - -static const luaL_Reg strlib[] = { - {"byte", str_byte}, - {"char", str_char}, - {"dump", str_dump}, - {"find", str_find}, - {"format", str_format}, - {"gmatch", gmatch}, - {"gsub", str_gsub}, - {"len", str_len}, - {"lower", str_lower}, - {"match", str_match}, - {"rep", str_rep}, - {"reverse", str_reverse}, - {"sub", str_sub}, - {"upper", str_upper}, - {"pack", str_pack}, - {"packsize", str_packsize}, - {"unpack", str_unpack}, - {NULL, NULL} -}; - - -static void createmetatable (lua_State *L) { - /* table to be metatable for strings */ - luaL_newlibtable(L, stringmetamethods); - luaL_setfuncs(L, stringmetamethods, 0); - lua_pushliteral(L, ""); /* dummy string */ - lua_pushvalue(L, -2); /* copy table */ - lua_setmetatable(L, -2); /* set table as metatable for strings */ - lua_pop(L, 1); /* pop dummy string */ - lua_pushvalue(L, -2); /* get string library */ - lua_setfield(L, -2, "__index"); /* metatable.__index = string */ - lua_pop(L, 1); /* pop metatable */ -} - - -/* -** Open string library -*/ -LUAMOD_API int luaopen_string (lua_State *L) { - luaL_newlib(L, strlib); - createmetatable(L); - return 1; -} - diff --git a/lib/lua-5.4/src/ltable.c b/lib/lua-5.4/src/ltable.c deleted file mode 100644 index 3c690c5..0000000 --- a/lib/lua-5.4/src/ltable.c +++ /dev/null @@ -1,980 +0,0 @@ -/* -** $Id: ltable.c $ -** Lua tables (hash) -** See Copyright Notice in lua.h -*/ - -#define ltable_c -#define LUA_CORE - -#include "lprefix.h" - - -/* -** Implementation of tables (aka arrays, objects, or hash tables). -** Tables keep its elements in two parts: an array part and a hash part. -** Non-negative integer keys are all candidates to be kept in the array -** part. The actual size of the array is the largest 'n' such that -** more than half the slots between 1 and n are in use. -** Hash uses a mix of chained scatter table with Brent's variation. -** A main invariant of these tables is that, if an element is not -** in its main position (i.e. the 'original' position that its hash gives -** to it), then the colliding element is in its own main position. -** Hence even when the load factor reaches 100%, performance remains good. -*/ - -#include -#include - -#include "lua.h" - -#include "ldebug.h" -#include "ldo.h" -#include "lgc.h" -#include "lmem.h" -#include "lobject.h" -#include "lstate.h" -#include "lstring.h" -#include "ltable.h" -#include "lvm.h" - - -/* -** MAXABITS is the largest integer such that MAXASIZE fits in an -** unsigned int. -*/ -#define MAXABITS cast_int(sizeof(int) * CHAR_BIT - 1) - - -/* -** MAXASIZE is the maximum size of the array part. It is the minimum -** between 2^MAXABITS and the maximum size that, measured in bytes, -** fits in a 'size_t'. -*/ -#define MAXASIZE luaM_limitN(1u << MAXABITS, TValue) - -/* -** MAXHBITS is the largest integer such that 2^MAXHBITS fits in a -** signed int. -*/ -#define MAXHBITS (MAXABITS - 1) - - -/* -** MAXHSIZE is the maximum size of the hash part. It is the minimum -** between 2^MAXHBITS and the maximum size such that, measured in bytes, -** it fits in a 'size_t'. -*/ -#define MAXHSIZE luaM_limitN(1u << MAXHBITS, Node) - - -/* -** When the original hash value is good, hashing by a power of 2 -** avoids the cost of '%'. -*/ -#define hashpow2(t,n) (gnode(t, lmod((n), sizenode(t)))) - -/* -** for other types, it is better to avoid modulo by power of 2, as -** they can have many 2 factors. -*/ -#define hashmod(t,n) (gnode(t, ((n) % ((sizenode(t)-1)|1)))) - - -#define hashstr(t,str) hashpow2(t, (str)->hash) -#define hashboolean(t,p) hashpow2(t, p) - - -#define hashpointer(t,p) hashmod(t, point2uint(p)) - - -#define dummynode (&dummynode_) - -static const Node dummynode_ = { - {{NULL}, LUA_VEMPTY, /* value's value and type */ - LUA_VNIL, 0, {NULL}} /* key type, next, and key value */ -}; - - -static const TValue absentkey = {ABSTKEYCONSTANT}; - - -/* -** Hash for integers. To allow a good hash, use the remainder operator -** ('%'). If integer fits as a non-negative int, compute an int -** remainder, which is faster. Otherwise, use an unsigned-integer -** remainder, which uses all bits and ensures a non-negative result. -*/ -static Node *hashint (const Table *t, lua_Integer i) { - lua_Unsigned ui = l_castS2U(i); - if (ui <= cast_uint(INT_MAX)) - return hashmod(t, cast_int(ui)); - else - return hashmod(t, ui); -} - - -/* -** Hash for floating-point numbers. -** The main computation should be just -** n = frexp(n, &i); return (n * INT_MAX) + i -** but there are some numerical subtleties. -** In a two-complement representation, INT_MAX does not has an exact -** representation as a float, but INT_MIN does; because the absolute -** value of 'frexp' is smaller than 1 (unless 'n' is inf/NaN), the -** absolute value of the product 'frexp * -INT_MIN' is smaller or equal -** to INT_MAX. Next, the use of 'unsigned int' avoids overflows when -** adding 'i'; the use of '~u' (instead of '-u') avoids problems with -** INT_MIN. -*/ -#if !defined(l_hashfloat) -static int l_hashfloat (lua_Number n) { - int i; - lua_Integer ni; - n = l_mathop(frexp)(n, &i) * -cast_num(INT_MIN); - if (!lua_numbertointeger(n, &ni)) { /* is 'n' inf/-inf/NaN? */ - lua_assert(luai_numisnan(n) || l_mathop(fabs)(n) == cast_num(HUGE_VAL)); - return 0; - } - else { /* normal case */ - unsigned int u = cast_uint(i) + cast_uint(ni); - return cast_int(u <= cast_uint(INT_MAX) ? u : ~u); - } -} -#endif - - -/* -** returns the 'main' position of an element in a table (that is, -** the index of its hash value). -*/ -static Node *mainpositionTV (const Table *t, const TValue *key) { - switch (ttypetag(key)) { - case LUA_VNUMINT: { - lua_Integer i = ivalue(key); - return hashint(t, i); - } - case LUA_VNUMFLT: { - lua_Number n = fltvalue(key); - return hashmod(t, l_hashfloat(n)); - } - case LUA_VSHRSTR: { - TString *ts = tsvalue(key); - return hashstr(t, ts); - } - case LUA_VLNGSTR: { - TString *ts = tsvalue(key); - return hashpow2(t, luaS_hashlongstr(ts)); - } - case LUA_VFALSE: - return hashboolean(t, 0); - case LUA_VTRUE: - return hashboolean(t, 1); - case LUA_VLIGHTUSERDATA: { - void *p = pvalue(key); - return hashpointer(t, p); - } - case LUA_VLCF: { - lua_CFunction f = fvalue(key); - return hashpointer(t, f); - } - default: { - GCObject *o = gcvalue(key); - return hashpointer(t, o); - } - } -} - - -l_sinline Node *mainpositionfromnode (const Table *t, Node *nd) { - TValue key; - getnodekey(cast(lua_State *, NULL), &key, nd); - return mainpositionTV(t, &key); -} - - -/* -** Check whether key 'k1' is equal to the key in node 'n2'. This -** equality is raw, so there are no metamethods. Floats with integer -** values have been normalized, so integers cannot be equal to -** floats. It is assumed that 'eqshrstr' is simply pointer equality, so -** that short strings are handled in the default case. -** A true 'deadok' means to accept dead keys as equal to their original -** values. All dead keys are compared in the default case, by pointer -** identity. (Only collectable objects can produce dead keys.) Note that -** dead long strings are also compared by identity. -** Once a key is dead, its corresponding value may be collected, and -** then another value can be created with the same address. If this -** other value is given to 'next', 'equalkey' will signal a false -** positive. In a regular traversal, this situation should never happen, -** as all keys given to 'next' came from the table itself, and therefore -** could not have been collected. Outside a regular traversal, we -** have garbage in, garbage out. What is relevant is that this false -** positive does not break anything. (In particular, 'next' will return -** some other valid item on the table or nil.) -*/ -static int equalkey (const TValue *k1, const Node *n2, int deadok) { - if ((rawtt(k1) != keytt(n2)) && /* not the same variants? */ - !(deadok && keyisdead(n2) && iscollectable(k1))) - return 0; /* cannot be same key */ - switch (keytt(n2)) { - case LUA_VNIL: case LUA_VFALSE: case LUA_VTRUE: - return 1; - case LUA_VNUMINT: - return (ivalue(k1) == keyival(n2)); - case LUA_VNUMFLT: - return luai_numeq(fltvalue(k1), fltvalueraw(keyval(n2))); - case LUA_VLIGHTUSERDATA: - return pvalue(k1) == pvalueraw(keyval(n2)); - case LUA_VLCF: - return fvalue(k1) == fvalueraw(keyval(n2)); - case ctb(LUA_VLNGSTR): - return luaS_eqlngstr(tsvalue(k1), keystrval(n2)); - default: - return gcvalue(k1) == gcvalueraw(keyval(n2)); - } -} - - -/* -** True if value of 'alimit' is equal to the real size of the array -** part of table 't'. (Otherwise, the array part must be larger than -** 'alimit'.) -*/ -#define limitequalsasize(t) (isrealasize(t) || ispow2((t)->alimit)) - - -/* -** Returns the real size of the 'array' array -*/ -LUAI_FUNC unsigned int luaH_realasize (const Table *t) { - if (limitequalsasize(t)) - return t->alimit; /* this is the size */ - else { - unsigned int size = t->alimit; - /* compute the smallest power of 2 not smaller than 'n' */ - size |= (size >> 1); - size |= (size >> 2); - size |= (size >> 4); - size |= (size >> 8); -#if (UINT_MAX >> 14) > 3 /* unsigned int has more than 16 bits */ - size |= (size >> 16); -#if (UINT_MAX >> 30) > 3 - size |= (size >> 32); /* unsigned int has more than 32 bits */ -#endif -#endif - size++; - lua_assert(ispow2(size) && size/2 < t->alimit && t->alimit < size); - return size; - } -} - - -/* -** Check whether real size of the array is a power of 2. -** (If it is not, 'alimit' cannot be changed to any other value -** without changing the real size.) -*/ -static int ispow2realasize (const Table *t) { - return (!isrealasize(t) || ispow2(t->alimit)); -} - - -static unsigned int setlimittosize (Table *t) { - t->alimit = luaH_realasize(t); - setrealasize(t); - return t->alimit; -} - - -#define limitasasize(t) check_exp(isrealasize(t), t->alimit) - - - -/* -** "Generic" get version. (Not that generic: not valid for integers, -** which may be in array part, nor for floats with integral values.) -** See explanation about 'deadok' in function 'equalkey'. -*/ -static const TValue *getgeneric (Table *t, const TValue *key, int deadok) { - Node *n = mainpositionTV(t, key); - for (;;) { /* check whether 'key' is somewhere in the chain */ - if (equalkey(key, n, deadok)) - return gval(n); /* that's it */ - else { - int nx = gnext(n); - if (nx == 0) - return &absentkey; /* not found */ - n += nx; - } - } -} - - -/* -** returns the index for 'k' if 'k' is an appropriate key to live in -** the array part of a table, 0 otherwise. -*/ -static unsigned int arrayindex (lua_Integer k) { - if (l_castS2U(k) - 1u < MAXASIZE) /* 'k' in [1, MAXASIZE]? */ - return cast_uint(k); /* 'key' is an appropriate array index */ - else - return 0; -} - - -/* -** returns the index of a 'key' for table traversals. First goes all -** elements in the array part, then elements in the hash part. The -** beginning of a traversal is signaled by 0. -*/ -static unsigned int findindex (lua_State *L, Table *t, TValue *key, - unsigned int asize) { - unsigned int i; - if (ttisnil(key)) return 0; /* first iteration */ - i = ttisinteger(key) ? arrayindex(ivalue(key)) : 0; - if (i - 1u < asize) /* is 'key' inside array part? */ - return i; /* yes; that's the index */ - else { - const TValue *n = getgeneric(t, key, 1); - if (l_unlikely(isabstkey(n))) - luaG_runerror(L, "invalid key to 'next'"); /* key not found */ - i = cast_int(nodefromval(n) - gnode(t, 0)); /* key index in hash table */ - /* hash elements are numbered after array ones */ - return (i + 1) + asize; - } -} - - -int luaH_next (lua_State *L, Table *t, StkId key) { - unsigned int asize = luaH_realasize(t); - unsigned int i = findindex(L, t, s2v(key), asize); /* find original key */ - for (; i < asize; i++) { /* try first array part */ - if (!isempty(&t->array[i])) { /* a non-empty entry? */ - setivalue(s2v(key), i + 1); - setobj2s(L, key + 1, &t->array[i]); - return 1; - } - } - for (i -= asize; cast_int(i) < sizenode(t); i++) { /* hash part */ - if (!isempty(gval(gnode(t, i)))) { /* a non-empty entry? */ - Node *n = gnode(t, i); - getnodekey(L, s2v(key), n); - setobj2s(L, key + 1, gval(n)); - return 1; - } - } - return 0; /* no more elements */ -} - - -static void freehash (lua_State *L, Table *t) { - if (!isdummy(t)) - luaM_freearray(L, t->node, cast_sizet(sizenode(t))); -} - - -/* -** {============================================================= -** Rehash -** ============================================================== -*/ - -/* -** Compute the optimal size for the array part of table 't'. 'nums' is a -** "count array" where 'nums[i]' is the number of integers in the table -** between 2^(i - 1) + 1 and 2^i. 'pna' enters with the total number of -** integer keys in the table and leaves with the number of keys that -** will go to the array part; return the optimal size. (The condition -** 'twotoi > 0' in the for loop stops the loop if 'twotoi' overflows.) -*/ -static unsigned int computesizes (unsigned int nums[], unsigned int *pna) { - int i; - unsigned int twotoi; /* 2^i (candidate for optimal size) */ - unsigned int a = 0; /* number of elements smaller than 2^i */ - unsigned int na = 0; /* number of elements to go to array part */ - unsigned int optimal = 0; /* optimal size for array part */ - /* loop while keys can fill more than half of total size */ - for (i = 0, twotoi = 1; - twotoi > 0 && *pna > twotoi / 2; - i++, twotoi *= 2) { - a += nums[i]; - if (a > twotoi/2) { /* more than half elements present? */ - optimal = twotoi; /* optimal size (till now) */ - na = a; /* all elements up to 'optimal' will go to array part */ - } - } - lua_assert((optimal == 0 || optimal / 2 < na) && na <= optimal); - *pna = na; - return optimal; -} - - -static int countint (lua_Integer key, unsigned int *nums) { - unsigned int k = arrayindex(key); - if (k != 0) { /* is 'key' an appropriate array index? */ - nums[luaO_ceillog2(k)]++; /* count as such */ - return 1; - } - else - return 0; -} - - -/* -** Count keys in array part of table 't': Fill 'nums[i]' with -** number of keys that will go into corresponding slice and return -** total number of non-nil keys. -*/ -static unsigned int numusearray (const Table *t, unsigned int *nums) { - int lg; - unsigned int ttlg; /* 2^lg */ - unsigned int ause = 0; /* summation of 'nums' */ - unsigned int i = 1; /* count to traverse all array keys */ - unsigned int asize = limitasasize(t); /* real array size */ - /* traverse each slice */ - for (lg = 0, ttlg = 1; lg <= MAXABITS; lg++, ttlg *= 2) { - unsigned int lc = 0; /* counter */ - unsigned int lim = ttlg; - if (lim > asize) { - lim = asize; /* adjust upper limit */ - if (i > lim) - break; /* no more elements to count */ - } - /* count elements in range (2^(lg - 1), 2^lg] */ - for (; i <= lim; i++) { - if (!isempty(&t->array[i-1])) - lc++; - } - nums[lg] += lc; - ause += lc; - } - return ause; -} - - -static int numusehash (const Table *t, unsigned int *nums, unsigned int *pna) { - int totaluse = 0; /* total number of elements */ - int ause = 0; /* elements added to 'nums' (can go to array part) */ - int i = sizenode(t); - while (i--) { - Node *n = &t->node[i]; - if (!isempty(gval(n))) { - if (keyisinteger(n)) - ause += countint(keyival(n), nums); - totaluse++; - } - } - *pna += ause; - return totaluse; -} - - -/* -** Creates an array for the hash part of a table with the given -** size, or reuses the dummy node if size is zero. -** The computation for size overflow is in two steps: the first -** comparison ensures that the shift in the second one does not -** overflow. -*/ -static void setnodevector (lua_State *L, Table *t, unsigned int size) { - if (size == 0) { /* no elements to hash part? */ - t->node = cast(Node *, dummynode); /* use common 'dummynode' */ - t->lsizenode = 0; - t->lastfree = NULL; /* signal that it is using dummy node */ - } - else { - int i; - int lsize = luaO_ceillog2(size); - if (lsize > MAXHBITS || (1u << lsize) > MAXHSIZE) - luaG_runerror(L, "table overflow"); - size = twoto(lsize); - t->node = luaM_newvector(L, size, Node); - for (i = 0; i < cast_int(size); i++) { - Node *n = gnode(t, i); - gnext(n) = 0; - setnilkey(n); - setempty(gval(n)); - } - t->lsizenode = cast_byte(lsize); - t->lastfree = gnode(t, size); /* all positions are free */ - } -} - - -/* -** (Re)insert all elements from the hash part of 'ot' into table 't'. -*/ -static void reinsert (lua_State *L, Table *ot, Table *t) { - int j; - int size = sizenode(ot); - for (j = 0; j < size; j++) { - Node *old = gnode(ot, j); - if (!isempty(gval(old))) { - /* doesn't need barrier/invalidate cache, as entry was - already present in the table */ - TValue k; - getnodekey(L, &k, old); - luaH_set(L, t, &k, gval(old)); - } - } -} - - -/* -** Exchange the hash part of 't1' and 't2'. -*/ -static void exchangehashpart (Table *t1, Table *t2) { - lu_byte lsizenode = t1->lsizenode; - Node *node = t1->node; - Node *lastfree = t1->lastfree; - t1->lsizenode = t2->lsizenode; - t1->node = t2->node; - t1->lastfree = t2->lastfree; - t2->lsizenode = lsizenode; - t2->node = node; - t2->lastfree = lastfree; -} - - -/* -** Resize table 't' for the new given sizes. Both allocations (for -** the hash part and for the array part) can fail, which creates some -** subtleties. If the first allocation, for the hash part, fails, an -** error is raised and that is it. Otherwise, it copies the elements from -** the shrinking part of the array (if it is shrinking) into the new -** hash. Then it reallocates the array part. If that fails, the table -** is in its original state; the function frees the new hash part and then -** raises the allocation error. Otherwise, it sets the new hash part -** into the table, initializes the new part of the array (if any) with -** nils and reinserts the elements of the old hash back into the new -** parts of the table. -*/ -void luaH_resize (lua_State *L, Table *t, unsigned int newasize, - unsigned int nhsize) { - unsigned int i; - Table newt; /* to keep the new hash part */ - unsigned int oldasize = setlimittosize(t); - TValue *newarray; - /* create new hash part with appropriate size into 'newt' */ - setnodevector(L, &newt, nhsize); - if (newasize < oldasize) { /* will array shrink? */ - t->alimit = newasize; /* pretend array has new size... */ - exchangehashpart(t, &newt); /* and new hash */ - /* re-insert into the new hash the elements from vanishing slice */ - for (i = newasize; i < oldasize; i++) { - if (!isempty(&t->array[i])) - luaH_setint(L, t, i + 1, &t->array[i]); - } - t->alimit = oldasize; /* restore current size... */ - exchangehashpart(t, &newt); /* and hash (in case of errors) */ - } - /* allocate new array */ - newarray = luaM_reallocvector(L, t->array, oldasize, newasize, TValue); - if (l_unlikely(newarray == NULL && newasize > 0)) { /* allocation failed? */ - freehash(L, &newt); /* release new hash part */ - luaM_error(L); /* raise error (with array unchanged) */ - } - /* allocation ok; initialize new part of the array */ - exchangehashpart(t, &newt); /* 't' has the new hash ('newt' has the old) */ - t->array = newarray; /* set new array part */ - t->alimit = newasize; - for (i = oldasize; i < newasize; i++) /* clear new slice of the array */ - setempty(&t->array[i]); - /* re-insert elements from old hash part into new parts */ - reinsert(L, &newt, t); /* 'newt' now has the old hash */ - freehash(L, &newt); /* free old hash part */ -} - - -void luaH_resizearray (lua_State *L, Table *t, unsigned int nasize) { - int nsize = allocsizenode(t); - luaH_resize(L, t, nasize, nsize); -} - -/* -** nums[i] = number of keys 'k' where 2^(i - 1) < k <= 2^i -*/ -static void rehash (lua_State *L, Table *t, const TValue *ek) { - unsigned int asize; /* optimal size for array part */ - unsigned int na; /* number of keys in the array part */ - unsigned int nums[MAXABITS + 1]; - int i; - int totaluse; - for (i = 0; i <= MAXABITS; i++) nums[i] = 0; /* reset counts */ - setlimittosize(t); - na = numusearray(t, nums); /* count keys in array part */ - totaluse = na; /* all those keys are integer keys */ - totaluse += numusehash(t, nums, &na); /* count keys in hash part */ - /* count extra key */ - if (ttisinteger(ek)) - na += countint(ivalue(ek), nums); - totaluse++; - /* compute new size for array part */ - asize = computesizes(nums, &na); - /* resize the table to new computed sizes */ - luaH_resize(L, t, asize, totaluse - na); -} - - - -/* -** }============================================================= -*/ - - -Table *luaH_new (lua_State *L) { - GCObject *o = luaC_newobj(L, LUA_VTABLE, sizeof(Table)); - Table *t = gco2t(o); - t->metatable = NULL; - t->flags = cast_byte(maskflags); /* table has no metamethod fields */ - t->array = NULL; - t->alimit = 0; - setnodevector(L, t, 0); - return t; -} - - -void luaH_free (lua_State *L, Table *t) { - freehash(L, t); - luaM_freearray(L, t->array, luaH_realasize(t)); - luaM_free(L, t); -} - - -static Node *getfreepos (Table *t) { - if (!isdummy(t)) { - while (t->lastfree > t->node) { - t->lastfree--; - if (keyisnil(t->lastfree)) - return t->lastfree; - } - } - return NULL; /* could not find a free place */ -} - - - -/* -** inserts a new key into a hash table; first, check whether key's main -** position is free. If not, check whether colliding node is in its main -** position or not: if it is not, move colliding node to an empty place and -** put new key in its main position; otherwise (colliding node is in its main -** position), new key goes to an empty position. -*/ -void luaH_newkey (lua_State *L, Table *t, const TValue *key, TValue *value) { - Node *mp; - TValue aux; - if (l_unlikely(ttisnil(key))) - luaG_runerror(L, "table index is nil"); - else if (ttisfloat(key)) { - lua_Number f = fltvalue(key); - lua_Integer k; - if (luaV_flttointeger(f, &k, F2Ieq)) { /* does key fit in an integer? */ - setivalue(&aux, k); - key = &aux; /* insert it as an integer */ - } - else if (l_unlikely(luai_numisnan(f))) - luaG_runerror(L, "table index is NaN"); - } - if (ttisnil(value)) - return; /* do not insert nil values */ - mp = mainpositionTV(t, key); - if (!isempty(gval(mp)) || isdummy(t)) { /* main position is taken? */ - Node *othern; - Node *f = getfreepos(t); /* get a free place */ - if (f == NULL) { /* cannot find a free place? */ - rehash(L, t, key); /* grow table */ - /* whatever called 'newkey' takes care of TM cache */ - luaH_set(L, t, key, value); /* insert key into grown table */ - return; - } - lua_assert(!isdummy(t)); - othern = mainpositionfromnode(t, mp); - if (othern != mp) { /* is colliding node out of its main position? */ - /* yes; move colliding node into free position */ - while (othern + gnext(othern) != mp) /* find previous */ - othern += gnext(othern); - gnext(othern) = cast_int(f - othern); /* rechain to point to 'f' */ - *f = *mp; /* copy colliding node into free pos. (mp->next also goes) */ - if (gnext(mp) != 0) { - gnext(f) += cast_int(mp - f); /* correct 'next' */ - gnext(mp) = 0; /* now 'mp' is free */ - } - setempty(gval(mp)); - } - else { /* colliding node is in its own main position */ - /* new node will go into free position */ - if (gnext(mp) != 0) - gnext(f) = cast_int((mp + gnext(mp)) - f); /* chain new position */ - else lua_assert(gnext(f) == 0); - gnext(mp) = cast_int(f - mp); - mp = f; - } - } - setnodekey(L, mp, key); - luaC_barrierback(L, obj2gco(t), key); - lua_assert(isempty(gval(mp))); - setobj2t(L, gval(mp), value); -} - - -/* -** Search function for integers. If integer is inside 'alimit', get it -** directly from the array part. Otherwise, if 'alimit' is not equal to -** the real size of the array, key still can be in the array part. In -** this case, try to avoid a call to 'luaH_realasize' when key is just -** one more than the limit (so that it can be incremented without -** changing the real size of the array). -*/ -const TValue *luaH_getint (Table *t, lua_Integer key) { - if (l_castS2U(key) - 1u < t->alimit) /* 'key' in [1, t->alimit]? */ - return &t->array[key - 1]; - else if (!limitequalsasize(t) && /* key still may be in the array part? */ - (l_castS2U(key) == t->alimit + 1 || - l_castS2U(key) - 1u < luaH_realasize(t))) { - t->alimit = cast_uint(key); /* probably '#t' is here now */ - return &t->array[key - 1]; - } - else { - Node *n = hashint(t, key); - for (;;) { /* check whether 'key' is somewhere in the chain */ - if (keyisinteger(n) && keyival(n) == key) - return gval(n); /* that's it */ - else { - int nx = gnext(n); - if (nx == 0) break; - n += nx; - } - } - return &absentkey; - } -} - - -/* -** search function for short strings -*/ -const TValue *luaH_getshortstr (Table *t, TString *key) { - Node *n = hashstr(t, key); - lua_assert(key->tt == LUA_VSHRSTR); - for (;;) { /* check whether 'key' is somewhere in the chain */ - if (keyisshrstr(n) && eqshrstr(keystrval(n), key)) - return gval(n); /* that's it */ - else { - int nx = gnext(n); - if (nx == 0) - return &absentkey; /* not found */ - n += nx; - } - } -} - - -const TValue *luaH_getstr (Table *t, TString *key) { - if (key->tt == LUA_VSHRSTR) - return luaH_getshortstr(t, key); - else { /* for long strings, use generic case */ - TValue ko; - setsvalue(cast(lua_State *, NULL), &ko, key); - return getgeneric(t, &ko, 0); - } -} - - -/* -** main search function -*/ -const TValue *luaH_get (Table *t, const TValue *key) { - switch (ttypetag(key)) { - case LUA_VSHRSTR: return luaH_getshortstr(t, tsvalue(key)); - case LUA_VNUMINT: return luaH_getint(t, ivalue(key)); - case LUA_VNIL: return &absentkey; - case LUA_VNUMFLT: { - lua_Integer k; - if (luaV_flttointeger(fltvalue(key), &k, F2Ieq)) /* integral index? */ - return luaH_getint(t, k); /* use specialized version */ - /* else... */ - } /* FALLTHROUGH */ - default: - return getgeneric(t, key, 0); - } -} - - -/* -** Finish a raw "set table" operation, where 'slot' is where the value -** should have been (the result of a previous "get table"). -** Beware: when using this function you probably need to check a GC -** barrier and invalidate the TM cache. -*/ -void luaH_finishset (lua_State *L, Table *t, const TValue *key, - const TValue *slot, TValue *value) { - if (isabstkey(slot)) - luaH_newkey(L, t, key, value); - else - setobj2t(L, cast(TValue *, slot), value); -} - - -/* -** beware: when using this function you probably need to check a GC -** barrier and invalidate the TM cache. -*/ -void luaH_set (lua_State *L, Table *t, const TValue *key, TValue *value) { - const TValue *slot = luaH_get(t, key); - luaH_finishset(L, t, key, slot, value); -} - - -void luaH_setint (lua_State *L, Table *t, lua_Integer key, TValue *value) { - const TValue *p = luaH_getint(t, key); - if (isabstkey(p)) { - TValue k; - setivalue(&k, key); - luaH_newkey(L, t, &k, value); - } - else - setobj2t(L, cast(TValue *, p), value); -} - - -/* -** Try to find a boundary in the hash part of table 't'. From the -** caller, we know that 'j' is zero or present and that 'j + 1' is -** present. We want to find a larger key that is absent from the -** table, so that we can do a binary search between the two keys to -** find a boundary. We keep doubling 'j' until we get an absent index. -** If the doubling would overflow, we try LUA_MAXINTEGER. If it is -** absent, we are ready for the binary search. ('j', being max integer, -** is larger or equal to 'i', but it cannot be equal because it is -** absent while 'i' is present; so 'j > i'.) Otherwise, 'j' is a -** boundary. ('j + 1' cannot be a present integer key because it is -** not a valid integer in Lua.) -*/ -static lua_Unsigned hash_search (Table *t, lua_Unsigned j) { - lua_Unsigned i; - if (j == 0) j++; /* the caller ensures 'j + 1' is present */ - do { - i = j; /* 'i' is a present index */ - if (j <= l_castS2U(LUA_MAXINTEGER) / 2) - j *= 2; - else { - j = LUA_MAXINTEGER; - if (isempty(luaH_getint(t, j))) /* t[j] not present? */ - break; /* 'j' now is an absent index */ - else /* weird case */ - return j; /* well, max integer is a boundary... */ - } - } while (!isempty(luaH_getint(t, j))); /* repeat until an absent t[j] */ - /* i < j && t[i] present && t[j] absent */ - while (j - i > 1u) { /* do a binary search between them */ - lua_Unsigned m = (i + j) / 2; - if (isempty(luaH_getint(t, m))) j = m; - else i = m; - } - return i; -} - - -static unsigned int binsearch (const TValue *array, unsigned int i, - unsigned int j) { - while (j - i > 1u) { /* binary search */ - unsigned int m = (i + j) / 2; - if (isempty(&array[m - 1])) j = m; - else i = m; - } - return i; -} - - -/* -** Try to find a boundary in table 't'. (A 'boundary' is an integer index -** such that t[i] is present and t[i+1] is absent, or 0 if t[1] is absent -** and 'maxinteger' if t[maxinteger] is present.) -** (In the next explanation, we use Lua indices, that is, with base 1. -** The code itself uses base 0 when indexing the array part of the table.) -** The code starts with 'limit = t->alimit', a position in the array -** part that may be a boundary. -** -** (1) If 't[limit]' is empty, there must be a boundary before it. -** As a common case (e.g., after 't[#t]=nil'), check whether 'limit-1' -** is present. If so, it is a boundary. Otherwise, do a binary search -** between 0 and limit to find a boundary. In both cases, try to -** use this boundary as the new 'alimit', as a hint for the next call. -** -** (2) If 't[limit]' is not empty and the array has more elements -** after 'limit', try to find a boundary there. Again, try first -** the special case (which should be quite frequent) where 'limit+1' -** is empty, so that 'limit' is a boundary. Otherwise, check the -** last element of the array part. If it is empty, there must be a -** boundary between the old limit (present) and the last element -** (absent), which is found with a binary search. (This boundary always -** can be a new limit.) -** -** (3) The last case is when there are no elements in the array part -** (limit == 0) or its last element (the new limit) is present. -** In this case, must check the hash part. If there is no hash part -** or 'limit+1' is absent, 'limit' is a boundary. Otherwise, call -** 'hash_search' to find a boundary in the hash part of the table. -** (In those cases, the boundary is not inside the array part, and -** therefore cannot be used as a new limit.) -*/ -lua_Unsigned luaH_getn (Table *t) { - unsigned int limit = t->alimit; - if (limit > 0 && isempty(&t->array[limit - 1])) { /* (1)? */ - /* there must be a boundary before 'limit' */ - if (limit >= 2 && !isempty(&t->array[limit - 2])) { - /* 'limit - 1' is a boundary; can it be a new limit? */ - if (ispow2realasize(t) && !ispow2(limit - 1)) { - t->alimit = limit - 1; - setnorealasize(t); /* now 'alimit' is not the real size */ - } - return limit - 1; - } - else { /* must search for a boundary in [0, limit] */ - unsigned int boundary = binsearch(t->array, 0, limit); - /* can this boundary represent the real size of the array? */ - if (ispow2realasize(t) && boundary > luaH_realasize(t) / 2) { - t->alimit = boundary; /* use it as the new limit */ - setnorealasize(t); - } - return boundary; - } - } - /* 'limit' is zero or present in table */ - if (!limitequalsasize(t)) { /* (2)? */ - /* 'limit' > 0 and array has more elements after 'limit' */ - if (isempty(&t->array[limit])) /* 'limit + 1' is empty? */ - return limit; /* this is the boundary */ - /* else, try last element in the array */ - limit = luaH_realasize(t); - if (isempty(&t->array[limit - 1])) { /* empty? */ - /* there must be a boundary in the array after old limit, - and it must be a valid new limit */ - unsigned int boundary = binsearch(t->array, t->alimit, limit); - t->alimit = boundary; - return boundary; - } - /* else, new limit is present in the table; check the hash part */ - } - /* (3) 'limit' is the last element and either is zero or present in table */ - lua_assert(limit == luaH_realasize(t) && - (limit == 0 || !isempty(&t->array[limit - 1]))); - if (isdummy(t) || isempty(luaH_getint(t, cast(lua_Integer, limit + 1)))) - return limit; /* 'limit + 1' is absent */ - else /* 'limit + 1' is also present */ - return hash_search(t, limit); -} - - - -#if defined(LUA_DEBUG) - -/* export these functions for the test library */ - -Node *luaH_mainposition (const Table *t, const TValue *key) { - return mainpositionTV(t, key); -} - -#endif diff --git a/lib/lua-5.4/src/ltable.h b/lib/lua-5.4/src/ltable.h deleted file mode 100644 index 75dd9e2..0000000 --- a/lib/lua-5.4/src/ltable.h +++ /dev/null @@ -1,65 +0,0 @@ -/* -** $Id: ltable.h $ -** Lua tables (hash) -** See Copyright Notice in lua.h -*/ - -#ifndef ltable_h -#define ltable_h - -#include "lobject.h" - - -#define gnode(t,i) (&(t)->node[i]) -#define gval(n) (&(n)->i_val) -#define gnext(n) ((n)->u.next) - - -/* -** Clear all bits of fast-access metamethods, which means that the table -** may have any of these metamethods. (First access that fails after the -** clearing will set the bit again.) -*/ -#define invalidateTMcache(t) ((t)->flags &= ~maskflags) - - -/* true when 't' is using 'dummynode' as its hash part */ -#define isdummy(t) ((t)->lastfree == NULL) - - -/* allocated size for hash nodes */ -#define allocsizenode(t) (isdummy(t) ? 0 : sizenode(t)) - - -/* returns the Node, given the value of a table entry */ -#define nodefromval(v) cast(Node *, (v)) - - -LUAI_FUNC const TValue *luaH_getint (Table *t, lua_Integer key); -LUAI_FUNC void luaH_setint (lua_State *L, Table *t, lua_Integer key, - TValue *value); -LUAI_FUNC const TValue *luaH_getshortstr (Table *t, TString *key); -LUAI_FUNC const TValue *luaH_getstr (Table *t, TString *key); -LUAI_FUNC const TValue *luaH_get (Table *t, const TValue *key); -LUAI_FUNC void luaH_newkey (lua_State *L, Table *t, const TValue *key, - TValue *value); -LUAI_FUNC void luaH_set (lua_State *L, Table *t, const TValue *key, - TValue *value); -LUAI_FUNC void luaH_finishset (lua_State *L, Table *t, const TValue *key, - const TValue *slot, TValue *value); -LUAI_FUNC Table *luaH_new (lua_State *L); -LUAI_FUNC void luaH_resize (lua_State *L, Table *t, unsigned int nasize, - unsigned int nhsize); -LUAI_FUNC void luaH_resizearray (lua_State *L, Table *t, unsigned int nasize); -LUAI_FUNC void luaH_free (lua_State *L, Table *t); -LUAI_FUNC int luaH_next (lua_State *L, Table *t, StkId key); -LUAI_FUNC lua_Unsigned luaH_getn (Table *t); -LUAI_FUNC unsigned int luaH_realasize (const Table *t); - - -#if defined(LUA_DEBUG) -LUAI_FUNC Node *luaH_mainposition (const Table *t, const TValue *key); -#endif - - -#endif diff --git a/lib/lua-5.4/src/ltablib.c b/lib/lua-5.4/src/ltablib.c deleted file mode 100644 index e6bc4d0..0000000 --- a/lib/lua-5.4/src/ltablib.c +++ /dev/null @@ -1,430 +0,0 @@ -/* -** $Id: ltablib.c $ -** Library for Table Manipulation -** See Copyright Notice in lua.h -*/ - -#define ltablib_c -#define LUA_LIB - -#include "lprefix.h" - - -#include -#include -#include - -#include "lua.h" - -#include "lauxlib.h" -#include "lualib.h" - - -/* -** Operations that an object must define to mimic a table -** (some functions only need some of them) -*/ -#define TAB_R 1 /* read */ -#define TAB_W 2 /* write */ -#define TAB_L 4 /* length */ -#define TAB_RW (TAB_R | TAB_W) /* read/write */ - - -#define aux_getn(L,n,w) (checktab(L, n, (w) | TAB_L), luaL_len(L, n)) - - -static int checkfield (lua_State *L, const char *key, int n) { - lua_pushstring(L, key); - return (lua_rawget(L, -n) != LUA_TNIL); -} - - -/* -** Check that 'arg' either is a table or can behave like one (that is, -** has a metatable with the required metamethods) -*/ -static void checktab (lua_State *L, int arg, int what) { - if (lua_type(L, arg) != LUA_TTABLE) { /* is it not a table? */ - int n = 1; /* number of elements to pop */ - if (lua_getmetatable(L, arg) && /* must have metatable */ - (!(what & TAB_R) || checkfield(L, "__index", ++n)) && - (!(what & TAB_W) || checkfield(L, "__newindex", ++n)) && - (!(what & TAB_L) || checkfield(L, "__len", ++n))) { - lua_pop(L, n); /* pop metatable and tested metamethods */ - } - else - luaL_checktype(L, arg, LUA_TTABLE); /* force an error */ - } -} - - -static int tinsert (lua_State *L) { - lua_Integer pos; /* where to insert new element */ - lua_Integer e = aux_getn(L, 1, TAB_RW); - e = luaL_intop(+, e, 1); /* first empty element */ - switch (lua_gettop(L)) { - case 2: { /* called with only 2 arguments */ - pos = e; /* insert new element at the end */ - break; - } - case 3: { - lua_Integer i; - pos = luaL_checkinteger(L, 2); /* 2nd argument is the position */ - /* check whether 'pos' is in [1, e] */ - luaL_argcheck(L, (lua_Unsigned)pos - 1u < (lua_Unsigned)e, 2, - "position out of bounds"); - for (i = e; i > pos; i--) { /* move up elements */ - lua_geti(L, 1, i - 1); - lua_seti(L, 1, i); /* t[i] = t[i - 1] */ - } - break; - } - default: { - return luaL_error(L, "wrong number of arguments to 'insert'"); - } - } - lua_seti(L, 1, pos); /* t[pos] = v */ - return 0; -} - - -static int tremove (lua_State *L) { - lua_Integer size = aux_getn(L, 1, TAB_RW); - lua_Integer pos = luaL_optinteger(L, 2, size); - if (pos != size) /* validate 'pos' if given */ - /* check whether 'pos' is in [1, size + 1] */ - luaL_argcheck(L, (lua_Unsigned)pos - 1u <= (lua_Unsigned)size, 2, - "position out of bounds"); - lua_geti(L, 1, pos); /* result = t[pos] */ - for ( ; pos < size; pos++) { - lua_geti(L, 1, pos + 1); - lua_seti(L, 1, pos); /* t[pos] = t[pos + 1] */ - } - lua_pushnil(L); - lua_seti(L, 1, pos); /* remove entry t[pos] */ - return 1; -} - - -/* -** Copy elements (1[f], ..., 1[e]) into (tt[t], tt[t+1], ...). Whenever -** possible, copy in increasing order, which is better for rehashing. -** "possible" means destination after original range, or smaller -** than origin, or copying to another table. -*/ -static int tmove (lua_State *L) { - lua_Integer f = luaL_checkinteger(L, 2); - lua_Integer e = luaL_checkinteger(L, 3); - lua_Integer t = luaL_checkinteger(L, 4); - int tt = !lua_isnoneornil(L, 5) ? 5 : 1; /* destination table */ - checktab(L, 1, TAB_R); - checktab(L, tt, TAB_W); - if (e >= f) { /* otherwise, nothing to move */ - lua_Integer n, i; - luaL_argcheck(L, f > 0 || e < LUA_MAXINTEGER + f, 3, - "too many elements to move"); - n = e - f + 1; /* number of elements to move */ - luaL_argcheck(L, t <= LUA_MAXINTEGER - n + 1, 4, - "destination wrap around"); - if (t > e || t <= f || (tt != 1 && !lua_compare(L, 1, tt, LUA_OPEQ))) { - for (i = 0; i < n; i++) { - lua_geti(L, 1, f + i); - lua_seti(L, tt, t + i); - } - } - else { - for (i = n - 1; i >= 0; i--) { - lua_geti(L, 1, f + i); - lua_seti(L, tt, t + i); - } - } - } - lua_pushvalue(L, tt); /* return destination table */ - return 1; -} - - -static void addfield (lua_State *L, luaL_Buffer *b, lua_Integer i) { - lua_geti(L, 1, i); - if (l_unlikely(!lua_isstring(L, -1))) - luaL_error(L, "invalid value (%s) at index %I in table for 'concat'", - luaL_typename(L, -1), (LUAI_UACINT)i); - luaL_addvalue(b); -} - - -static int tconcat (lua_State *L) { - luaL_Buffer b; - lua_Integer last = aux_getn(L, 1, TAB_R); - size_t lsep; - const char *sep = luaL_optlstring(L, 2, "", &lsep); - lua_Integer i = luaL_optinteger(L, 3, 1); - last = luaL_optinteger(L, 4, last); - luaL_buffinit(L, &b); - for (; i < last; i++) { - addfield(L, &b, i); - luaL_addlstring(&b, sep, lsep); - } - if (i == last) /* add last value (if interval was not empty) */ - addfield(L, &b, i); - luaL_pushresult(&b); - return 1; -} - - -/* -** {====================================================== -** Pack/unpack -** ======================================================= -*/ - -static int tpack (lua_State *L) { - int i; - int n = lua_gettop(L); /* number of elements to pack */ - lua_createtable(L, n, 1); /* create result table */ - lua_insert(L, 1); /* put it at index 1 */ - for (i = n; i >= 1; i--) /* assign elements */ - lua_seti(L, 1, i); - lua_pushinteger(L, n); - lua_setfield(L, 1, "n"); /* t.n = number of elements */ - return 1; /* return table */ -} - - -static int tunpack (lua_State *L) { - lua_Unsigned n; - lua_Integer i = luaL_optinteger(L, 2, 1); - lua_Integer e = luaL_opt(L, luaL_checkinteger, 3, luaL_len(L, 1)); - if (i > e) return 0; /* empty range */ - n = (lua_Unsigned)e - i; /* number of elements minus 1 (avoid overflows) */ - if (l_unlikely(n >= (unsigned int)INT_MAX || - !lua_checkstack(L, (int)(++n)))) - return luaL_error(L, "too many results to unpack"); - for (; i < e; i++) { /* push arg[i..e - 1] (to avoid overflows) */ - lua_geti(L, 1, i); - } - lua_geti(L, 1, e); /* push last element */ - return (int)n; -} - -/* }====================================================== */ - - - -/* -** {====================================================== -** Quicksort -** (based on 'Algorithms in MODULA-3', Robert Sedgewick; -** Addison-Wesley, 1993.) -** ======================================================= -*/ - - -/* type for array indices */ -typedef unsigned int IdxT; - - -/* -** Produce a "random" 'unsigned int' to randomize pivot choice. This -** macro is used only when 'sort' detects a big imbalance in the result -** of a partition. (If you don't want/need this "randomness", ~0 is a -** good choice.) -*/ -#if !defined(l_randomizePivot) /* { */ - -#include - -/* size of 'e' measured in number of 'unsigned int's */ -#define sof(e) (sizeof(e) / sizeof(unsigned int)) - -/* -** Use 'time' and 'clock' as sources of "randomness". Because we don't -** know the types 'clock_t' and 'time_t', we cannot cast them to -** anything without risking overflows. A safe way to use their values -** is to copy them to an array of a known type and use the array values. -*/ -static unsigned int l_randomizePivot (void) { - clock_t c = clock(); - time_t t = time(NULL); - unsigned int buff[sof(c) + sof(t)]; - unsigned int i, rnd = 0; - memcpy(buff, &c, sof(c) * sizeof(unsigned int)); - memcpy(buff + sof(c), &t, sof(t) * sizeof(unsigned int)); - for (i = 0; i < sof(buff); i++) - rnd += buff[i]; - return rnd; -} - -#endif /* } */ - - -/* arrays larger than 'RANLIMIT' may use randomized pivots */ -#define RANLIMIT 100u - - -static void set2 (lua_State *L, IdxT i, IdxT j) { - lua_seti(L, 1, i); - lua_seti(L, 1, j); -} - - -/* -** Return true iff value at stack index 'a' is less than the value at -** index 'b' (according to the order of the sort). -*/ -static int sort_comp (lua_State *L, int a, int b) { - if (lua_isnil(L, 2)) /* no function? */ - return lua_compare(L, a, b, LUA_OPLT); /* a < b */ - else { /* function */ - int res; - lua_pushvalue(L, 2); /* push function */ - lua_pushvalue(L, a-1); /* -1 to compensate function */ - lua_pushvalue(L, b-2); /* -2 to compensate function and 'a' */ - lua_call(L, 2, 1); /* call function */ - res = lua_toboolean(L, -1); /* get result */ - lua_pop(L, 1); /* pop result */ - return res; - } -} - - -/* -** Does the partition: Pivot P is at the top of the stack. -** precondition: a[lo] <= P == a[up-1] <= a[up], -** so it only needs to do the partition from lo + 1 to up - 2. -** Pos-condition: a[lo .. i - 1] <= a[i] == P <= a[i + 1 .. up] -** returns 'i'. -*/ -static IdxT partition (lua_State *L, IdxT lo, IdxT up) { - IdxT i = lo; /* will be incremented before first use */ - IdxT j = up - 1; /* will be decremented before first use */ - /* loop invariant: a[lo .. i] <= P <= a[j .. up] */ - for (;;) { - /* next loop: repeat ++i while a[i] < P */ - while ((void)lua_geti(L, 1, ++i), sort_comp(L, -1, -2)) { - if (l_unlikely(i == up - 1)) /* a[i] < P but a[up - 1] == P ?? */ - luaL_error(L, "invalid order function for sorting"); - lua_pop(L, 1); /* remove a[i] */ - } - /* after the loop, a[i] >= P and a[lo .. i - 1] < P */ - /* next loop: repeat --j while P < a[j] */ - while ((void)lua_geti(L, 1, --j), sort_comp(L, -3, -1)) { - if (l_unlikely(j < i)) /* j < i but a[j] > P ?? */ - luaL_error(L, "invalid order function for sorting"); - lua_pop(L, 1); /* remove a[j] */ - } - /* after the loop, a[j] <= P and a[j + 1 .. up] >= P */ - if (j < i) { /* no elements out of place? */ - /* a[lo .. i - 1] <= P <= a[j + 1 .. i .. up] */ - lua_pop(L, 1); /* pop a[j] */ - /* swap pivot (a[up - 1]) with a[i] to satisfy pos-condition */ - set2(L, up - 1, i); - return i; - } - /* otherwise, swap a[i] - a[j] to restore invariant and repeat */ - set2(L, i, j); - } -} - - -/* -** Choose an element in the middle (2nd-3th quarters) of [lo,up] -** "randomized" by 'rnd' -*/ -static IdxT choosePivot (IdxT lo, IdxT up, unsigned int rnd) { - IdxT r4 = (up - lo) / 4; /* range/4 */ - IdxT p = rnd % (r4 * 2) + (lo + r4); - lua_assert(lo + r4 <= p && p <= up - r4); - return p; -} - - -/* -** Quicksort algorithm (recursive function) -*/ -static void auxsort (lua_State *L, IdxT lo, IdxT up, - unsigned int rnd) { - while (lo < up) { /* loop for tail recursion */ - IdxT p; /* Pivot index */ - IdxT n; /* to be used later */ - /* sort elements 'lo', 'p', and 'up' */ - lua_geti(L, 1, lo); - lua_geti(L, 1, up); - if (sort_comp(L, -1, -2)) /* a[up] < a[lo]? */ - set2(L, lo, up); /* swap a[lo] - a[up] */ - else - lua_pop(L, 2); /* remove both values */ - if (up - lo == 1) /* only 2 elements? */ - return; /* already sorted */ - if (up - lo < RANLIMIT || rnd == 0) /* small interval or no randomize? */ - p = (lo + up)/2; /* middle element is a good pivot */ - else /* for larger intervals, it is worth a random pivot */ - p = choosePivot(lo, up, rnd); - lua_geti(L, 1, p); - lua_geti(L, 1, lo); - if (sort_comp(L, -2, -1)) /* a[p] < a[lo]? */ - set2(L, p, lo); /* swap a[p] - a[lo] */ - else { - lua_pop(L, 1); /* remove a[lo] */ - lua_geti(L, 1, up); - if (sort_comp(L, -1, -2)) /* a[up] < a[p]? */ - set2(L, p, up); /* swap a[up] - a[p] */ - else - lua_pop(L, 2); - } - if (up - lo == 2) /* only 3 elements? */ - return; /* already sorted */ - lua_geti(L, 1, p); /* get middle element (Pivot) */ - lua_pushvalue(L, -1); /* push Pivot */ - lua_geti(L, 1, up - 1); /* push a[up - 1] */ - set2(L, p, up - 1); /* swap Pivot (a[p]) with a[up - 1] */ - p = partition(L, lo, up); - /* a[lo .. p - 1] <= a[p] == P <= a[p + 1 .. up] */ - if (p - lo < up - p) { /* lower interval is smaller? */ - auxsort(L, lo, p - 1, rnd); /* call recursively for lower interval */ - n = p - lo; /* size of smaller interval */ - lo = p + 1; /* tail call for [p + 1 .. up] (upper interval) */ - } - else { - auxsort(L, p + 1, up, rnd); /* call recursively for upper interval */ - n = up - p; /* size of smaller interval */ - up = p - 1; /* tail call for [lo .. p - 1] (lower interval) */ - } - if ((up - lo) / 128 > n) /* partition too imbalanced? */ - rnd = l_randomizePivot(); /* try a new randomization */ - } /* tail call auxsort(L, lo, up, rnd) */ -} - - -static int sort (lua_State *L) { - lua_Integer n = aux_getn(L, 1, TAB_RW); - if (n > 1) { /* non-trivial interval? */ - luaL_argcheck(L, n < INT_MAX, 1, "array too big"); - if (!lua_isnoneornil(L, 2)) /* is there a 2nd argument? */ - luaL_checktype(L, 2, LUA_TFUNCTION); /* must be a function */ - lua_settop(L, 2); /* make sure there are two arguments */ - auxsort(L, 1, (IdxT)n, 0); - } - return 0; -} - -/* }====================================================== */ - - -static const luaL_Reg tab_funcs[] = { - {"concat", tconcat}, - {"insert", tinsert}, - {"pack", tpack}, - {"unpack", tunpack}, - {"remove", tremove}, - {"move", tmove}, - {"sort", sort}, - {NULL, NULL} -}; - - -LUAMOD_API int luaopen_table (lua_State *L) { - luaL_newlib(L, tab_funcs); - return 1; -} - diff --git a/lib/lua-5.4/src/ltm.c b/lib/lua-5.4/src/ltm.c deleted file mode 100644 index 07a0608..0000000 --- a/lib/lua-5.4/src/ltm.c +++ /dev/null @@ -1,271 +0,0 @@ -/* -** $Id: ltm.c $ -** Tag methods -** See Copyright Notice in lua.h -*/ - -#define ltm_c -#define LUA_CORE - -#include "lprefix.h" - - -#include - -#include "lua.h" - -#include "ldebug.h" -#include "ldo.h" -#include "lgc.h" -#include "lobject.h" -#include "lstate.h" -#include "lstring.h" -#include "ltable.h" -#include "ltm.h" -#include "lvm.h" - - -static const char udatatypename[] = "userdata"; - -LUAI_DDEF const char *const luaT_typenames_[LUA_TOTALTYPES] = { - "no value", - "nil", "boolean", udatatypename, "number", - "string", "table", "function", udatatypename, "thread", - "upvalue", "proto" /* these last cases are used for tests only */ -}; - - -void luaT_init (lua_State *L) { - static const char *const luaT_eventname[] = { /* ORDER TM */ - "__index", "__newindex", - "__gc", "__mode", "__len", "__eq", - "__add", "__sub", "__mul", "__mod", "__pow", - "__div", "__idiv", - "__band", "__bor", "__bxor", "__shl", "__shr", - "__unm", "__bnot", "__lt", "__le", - "__concat", "__call", "__close" - }; - int i; - for (i=0; itmname[i] = luaS_new(L, luaT_eventname[i]); - luaC_fix(L, obj2gco(G(L)->tmname[i])); /* never collect these names */ - } -} - - -/* -** function to be used with macro "fasttm": optimized for absence of -** tag methods -*/ -const TValue *luaT_gettm (Table *events, TMS event, TString *ename) { - const TValue *tm = luaH_getshortstr(events, ename); - lua_assert(event <= TM_EQ); - if (notm(tm)) { /* no tag method? */ - events->flags |= cast_byte(1u<metatable; - break; - case LUA_TUSERDATA: - mt = uvalue(o)->metatable; - break; - default: - mt = G(L)->mt[ttype(o)]; - } - return (mt ? luaH_getshortstr(mt, G(L)->tmname[event]) : &G(L)->nilvalue); -} - - -/* -** Return the name of the type of an object. For tables and userdata -** with metatable, use their '__name' metafield, if present. -*/ -const char *luaT_objtypename (lua_State *L, const TValue *o) { - Table *mt; - if ((ttistable(o) && (mt = hvalue(o)->metatable) != NULL) || - (ttisfulluserdata(o) && (mt = uvalue(o)->metatable) != NULL)) { - const TValue *name = luaH_getshortstr(mt, luaS_new(L, "__name")); - if (ttisstring(name)) /* is '__name' a string? */ - return getstr(tsvalue(name)); /* use it as type name */ - } - return ttypename(ttype(o)); /* else use standard type name */ -} - - -void luaT_callTM (lua_State *L, const TValue *f, const TValue *p1, - const TValue *p2, const TValue *p3) { - StkId func = L->top.p; - setobj2s(L, func, f); /* push function (assume EXTRA_STACK) */ - setobj2s(L, func + 1, p1); /* 1st argument */ - setobj2s(L, func + 2, p2); /* 2nd argument */ - setobj2s(L, func + 3, p3); /* 3rd argument */ - L->top.p = func + 4; - /* metamethod may yield only when called from Lua code */ - if (isLuacode(L->ci)) - luaD_call(L, func, 0); - else - luaD_callnoyield(L, func, 0); -} - - -void luaT_callTMres (lua_State *L, const TValue *f, const TValue *p1, - const TValue *p2, StkId res) { - ptrdiff_t result = savestack(L, res); - StkId func = L->top.p; - setobj2s(L, func, f); /* push function (assume EXTRA_STACK) */ - setobj2s(L, func + 1, p1); /* 1st argument */ - setobj2s(L, func + 2, p2); /* 2nd argument */ - L->top.p += 3; - /* metamethod may yield only when called from Lua code */ - if (isLuacode(L->ci)) - luaD_call(L, func, 1); - else - luaD_callnoyield(L, func, 1); - res = restorestack(L, result); - setobjs2s(L, res, --L->top.p); /* move result to its place */ -} - - -static int callbinTM (lua_State *L, const TValue *p1, const TValue *p2, - StkId res, TMS event) { - const TValue *tm = luaT_gettmbyobj(L, p1, event); /* try first operand */ - if (notm(tm)) - tm = luaT_gettmbyobj(L, p2, event); /* try second operand */ - if (notm(tm)) return 0; - luaT_callTMres(L, tm, p1, p2, res); - return 1; -} - - -void luaT_trybinTM (lua_State *L, const TValue *p1, const TValue *p2, - StkId res, TMS event) { - if (l_unlikely(!callbinTM(L, p1, p2, res, event))) { - switch (event) { - case TM_BAND: case TM_BOR: case TM_BXOR: - case TM_SHL: case TM_SHR: case TM_BNOT: { - if (ttisnumber(p1) && ttisnumber(p2)) - luaG_tointerror(L, p1, p2); - else - luaG_opinterror(L, p1, p2, "perform bitwise operation on"); - } - /* calls never return, but to avoid warnings: *//* FALLTHROUGH */ - default: - luaG_opinterror(L, p1, p2, "perform arithmetic on"); - } - } -} - - -void luaT_tryconcatTM (lua_State *L) { - StkId top = L->top.p; - if (l_unlikely(!callbinTM(L, s2v(top - 2), s2v(top - 1), top - 2, - TM_CONCAT))) - luaG_concaterror(L, s2v(top - 2), s2v(top - 1)); -} - - -void luaT_trybinassocTM (lua_State *L, const TValue *p1, const TValue *p2, - int flip, StkId res, TMS event) { - if (flip) - luaT_trybinTM(L, p2, p1, res, event); - else - luaT_trybinTM(L, p1, p2, res, event); -} - - -void luaT_trybiniTM (lua_State *L, const TValue *p1, lua_Integer i2, - int flip, StkId res, TMS event) { - TValue aux; - setivalue(&aux, i2); - luaT_trybinassocTM(L, p1, &aux, flip, res, event); -} - - -/* -** Calls an order tag method. -** For lessequal, LUA_COMPAT_LT_LE keeps compatibility with old -** behavior: if there is no '__le', try '__lt', based on l <= r iff -** !(r < l) (assuming a total order). If the metamethod yields during -** this substitution, the continuation has to know about it (to negate -** the result of rtop.p, event)) /* try original event */ - return !l_isfalse(s2v(L->top.p)); -#if defined(LUA_COMPAT_LT_LE) - else if (event == TM_LE) { - /* try '!(p2 < p1)' for '(p1 <= p2)' */ - L->ci->callstatus |= CIST_LEQ; /* mark it is doing 'lt' for 'le' */ - if (callbinTM(L, p2, p1, L->top.p, TM_LT)) { - L->ci->callstatus ^= CIST_LEQ; /* clear mark */ - return l_isfalse(s2v(L->top.p)); - } - /* else error will remove this 'ci'; no need to clear mark */ - } -#endif - luaG_ordererror(L, p1, p2); /* no metamethod found */ - return 0; /* to avoid warnings */ -} - - -int luaT_callorderiTM (lua_State *L, const TValue *p1, int v2, - int flip, int isfloat, TMS event) { - TValue aux; const TValue *p2; - if (isfloat) { - setfltvalue(&aux, cast_num(v2)); - } - else - setivalue(&aux, v2); - if (flip) { /* arguments were exchanged? */ - p2 = p1; p1 = &aux; /* correct them */ - } - else - p2 = &aux; - return luaT_callorderTM(L, p1, p2, event); -} - - -void luaT_adjustvarargs (lua_State *L, int nfixparams, CallInfo *ci, - const Proto *p) { - int i; - int actual = cast_int(L->top.p - ci->func.p) - 1; /* number of arguments */ - int nextra = actual - nfixparams; /* number of extra arguments */ - ci->u.l.nextraargs = nextra; - luaD_checkstack(L, p->maxstacksize + 1); - /* copy function to the top of the stack */ - setobjs2s(L, L->top.p++, ci->func.p); - /* move fixed parameters to the top of the stack */ - for (i = 1; i <= nfixparams; i++) { - setobjs2s(L, L->top.p++, ci->func.p + i); - setnilvalue(s2v(ci->func.p + i)); /* erase original parameter (for GC) */ - } - ci->func.p += actual + 1; - ci->top.p += actual + 1; - lua_assert(L->top.p <= ci->top.p && ci->top.p <= L->stack_last.p); -} - - -void luaT_getvarargs (lua_State *L, CallInfo *ci, StkId where, int wanted) { - int i; - int nextra = ci->u.l.nextraargs; - if (wanted < 0) { - wanted = nextra; /* get all extra arguments available */ - checkstackGCp(L, nextra, where); /* ensure stack space */ - L->top.p = where + nextra; /* next instruction will need top */ - } - for (i = 0; i < wanted && i < nextra; i++) - setobjs2s(L, where + i, ci->func.p - nextra + i); - for (; i < wanted; i++) /* complete required results with nil */ - setnilvalue(s2v(where + i)); -} - diff --git a/lib/lua-5.4/src/ltm.h b/lib/lua-5.4/src/ltm.h deleted file mode 100644 index c309e2a..0000000 --- a/lib/lua-5.4/src/ltm.h +++ /dev/null @@ -1,104 +0,0 @@ -/* -** $Id: ltm.h $ -** Tag methods -** See Copyright Notice in lua.h -*/ - -#ifndef ltm_h -#define ltm_h - - -#include "lobject.h" -#include "lstate.h" - - -/* -* WARNING: if you change the order of this enumeration, -* grep "ORDER TM" and "ORDER OP" -*/ -typedef enum { - TM_INDEX, - TM_NEWINDEX, - TM_GC, - TM_MODE, - TM_LEN, - TM_EQ, /* last tag method with fast access */ - TM_ADD, - TM_SUB, - TM_MUL, - TM_MOD, - TM_POW, - TM_DIV, - TM_IDIV, - TM_BAND, - TM_BOR, - TM_BXOR, - TM_SHL, - TM_SHR, - TM_UNM, - TM_BNOT, - TM_LT, - TM_LE, - TM_CONCAT, - TM_CALL, - TM_CLOSE, - TM_N /* number of elements in the enum */ -} TMS; - - -/* -** Mask with 1 in all fast-access methods. A 1 in any of these bits -** in the flag of a (meta)table means the metatable does not have the -** corresponding metamethod field. (Bit 7 of the flag is used for -** 'isrealasize'.) -*/ -#define maskflags (~(~0u << (TM_EQ + 1))) - - -/* -** Test whether there is no tagmethod. -** (Because tagmethods use raw accesses, the result may be an "empty" nil.) -*/ -#define notm(tm) ttisnil(tm) - - -#define gfasttm(g,et,e) ((et) == NULL ? NULL : \ - ((et)->flags & (1u<<(e))) ? NULL : luaT_gettm(et, e, (g)->tmname[e])) - -#define fasttm(l,et,e) gfasttm(G(l), et, e) - -#define ttypename(x) luaT_typenames_[(x) + 1] - -LUAI_DDEC(const char *const luaT_typenames_[LUA_TOTALTYPES];) - - -LUAI_FUNC const char *luaT_objtypename (lua_State *L, const TValue *o); - -LUAI_FUNC const TValue *luaT_gettm (Table *events, TMS event, TString *ename); -LUAI_FUNC const TValue *luaT_gettmbyobj (lua_State *L, const TValue *o, - TMS event); -LUAI_FUNC void luaT_init (lua_State *L); - -LUAI_FUNC void luaT_callTM (lua_State *L, const TValue *f, const TValue *p1, - const TValue *p2, const TValue *p3); -LUAI_FUNC void luaT_callTMres (lua_State *L, const TValue *f, - const TValue *p1, const TValue *p2, StkId p3); -LUAI_FUNC void luaT_trybinTM (lua_State *L, const TValue *p1, const TValue *p2, - StkId res, TMS event); -LUAI_FUNC void luaT_tryconcatTM (lua_State *L); -LUAI_FUNC void luaT_trybinassocTM (lua_State *L, const TValue *p1, - const TValue *p2, int inv, StkId res, TMS event); -LUAI_FUNC void luaT_trybiniTM (lua_State *L, const TValue *p1, lua_Integer i2, - int inv, StkId res, TMS event); -LUAI_FUNC int luaT_callorderTM (lua_State *L, const TValue *p1, - const TValue *p2, TMS event); -LUAI_FUNC int luaT_callorderiTM (lua_State *L, const TValue *p1, int v2, - int inv, int isfloat, TMS event); - -LUAI_FUNC void luaT_adjustvarargs (lua_State *L, int nfixparams, - CallInfo *ci, const Proto *p); -LUAI_FUNC void luaT_getvarargs (lua_State *L, CallInfo *ci, - StkId where, int wanted); - - -#endif diff --git a/lib/lua-5.4/src/lua.c b/lib/lua-5.4/src/lua.c deleted file mode 100644 index 0ff8845..0000000 --- a/lib/lua-5.4/src/lua.c +++ /dev/null @@ -1,679 +0,0 @@ -/* -** $Id: lua.c $ -** Lua stand-alone interpreter -** See Copyright Notice in lua.h -*/ - -#define lua_c - -#include "lprefix.h" - - -#include -#include -#include - -#include - -#include "lua.h" - -#include "lauxlib.h" -#include "lualib.h" - - -#if !defined(LUA_PROGNAME) -#define LUA_PROGNAME "lua" -#endif - -#if !defined(LUA_INIT_VAR) -#define LUA_INIT_VAR "LUA_INIT" -#endif - -#define LUA_INITVARVERSION LUA_INIT_VAR LUA_VERSUFFIX - - -static lua_State *globalL = NULL; - -static const char *progname = LUA_PROGNAME; - - -#if defined(LUA_USE_POSIX) /* { */ - -/* -** Use 'sigaction' when available. -*/ -static void setsignal (int sig, void (*handler)(int)) { - struct sigaction sa; - sa.sa_handler = handler; - sa.sa_flags = 0; - sigemptyset(&sa.sa_mask); /* do not mask any signal */ - sigaction(sig, &sa, NULL); -} - -#else /* }{ */ - -#define setsignal signal - -#endif /* } */ - - -/* -** Hook set by signal function to stop the interpreter. -*/ -static void lstop (lua_State *L, lua_Debug *ar) { - (void)ar; /* unused arg. */ - lua_sethook(L, NULL, 0, 0); /* reset hook */ - luaL_error(L, "interrupted!"); -} - - -/* -** Function to be called at a C signal. Because a C signal cannot -** just change a Lua state (as there is no proper synchronization), -** this function only sets a hook that, when called, will stop the -** interpreter. -*/ -static void laction (int i) { - int flag = LUA_MASKCALL | LUA_MASKRET | LUA_MASKLINE | LUA_MASKCOUNT; - setsignal(i, SIG_DFL); /* if another SIGINT happens, terminate process */ - lua_sethook(globalL, lstop, flag, 1); -} - - -static void print_usage (const char *badoption) { - lua_writestringerror("%s: ", progname); - if (badoption[1] == 'e' || badoption[1] == 'l') - lua_writestringerror("'%s' needs argument\n", badoption); - else - lua_writestringerror("unrecognized option '%s'\n", badoption); - lua_writestringerror( - "usage: %s [options] [script [args]]\n" - "Available options are:\n" - " -e stat execute string 'stat'\n" - " -i enter interactive mode after executing 'script'\n" - " -l mod require library 'mod' into global 'mod'\n" - " -l g=mod require library 'mod' into global 'g'\n" - " -v show version information\n" - " -E ignore environment variables\n" - " -W turn warnings on\n" - " -- stop handling options\n" - " - stop handling options and execute stdin\n" - , - progname); -} - - -/* -** Prints an error message, adding the program name in front of it -** (if present) -*/ -static void l_message (const char *pname, const char *msg) { - if (pname) lua_writestringerror("%s: ", pname); - lua_writestringerror("%s\n", msg); -} - - -/* -** Check whether 'status' is not OK and, if so, prints the error -** message on the top of the stack. It assumes that the error object -** is a string, as it was either generated by Lua or by 'msghandler'. -*/ -static int report (lua_State *L, int status) { - if (status != LUA_OK) { - const char *msg = lua_tostring(L, -1); - l_message(progname, msg); - lua_pop(L, 1); /* remove message */ - } - return status; -} - - -/* -** Message handler used to run all chunks -*/ -static int msghandler (lua_State *L) { - const char *msg = lua_tostring(L, 1); - if (msg == NULL) { /* is error object not a string? */ - if (luaL_callmeta(L, 1, "__tostring") && /* does it have a metamethod */ - lua_type(L, -1) == LUA_TSTRING) /* that produces a string? */ - return 1; /* that is the message */ - else - msg = lua_pushfstring(L, "(error object is a %s value)", - luaL_typename(L, 1)); - } - luaL_traceback(L, L, msg, 1); /* append a standard traceback */ - return 1; /* return the traceback */ -} - - -/* -** Interface to 'lua_pcall', which sets appropriate message function -** and C-signal handler. Used to run all chunks. -*/ -static int docall (lua_State *L, int narg, int nres) { - int status; - int base = lua_gettop(L) - narg; /* function index */ - lua_pushcfunction(L, msghandler); /* push message handler */ - lua_insert(L, base); /* put it under function and args */ - globalL = L; /* to be available to 'laction' */ - setsignal(SIGINT, laction); /* set C-signal handler */ - status = lua_pcall(L, narg, nres, base); - setsignal(SIGINT, SIG_DFL); /* reset C-signal handler */ - lua_remove(L, base); /* remove message handler from the stack */ - return status; -} - - -static void print_version (void) { - lua_writestring(LUA_COPYRIGHT, strlen(LUA_COPYRIGHT)); - lua_writeline(); -} - - -/* -** Create the 'arg' table, which stores all arguments from the -** command line ('argv'). It should be aligned so that, at index 0, -** it has 'argv[script]', which is the script name. The arguments -** to the script (everything after 'script') go to positive indices; -** other arguments (before the script name) go to negative indices. -** If there is no script name, assume interpreter's name as base. -** (If there is no interpreter's name either, 'script' is -1, so -** table sizes are zero.) -*/ -static void createargtable (lua_State *L, char **argv, int argc, int script) { - int i, narg; - narg = argc - (script + 1); /* number of positive indices */ - lua_createtable(L, narg, script + 1); - for (i = 0; i < argc; i++) { - lua_pushstring(L, argv[i]); - lua_rawseti(L, -2, i - script); - } - lua_setglobal(L, "arg"); -} - - -static int dochunk (lua_State *L, int status) { - if (status == LUA_OK) status = docall(L, 0, 0); - return report(L, status); -} - - -static int dofile (lua_State *L, const char *name) { - return dochunk(L, luaL_loadfile(L, name)); -} - - -static int dostring (lua_State *L, const char *s, const char *name) { - return dochunk(L, luaL_loadbuffer(L, s, strlen(s), name)); -} - - -/* -** Receives 'globname[=modname]' and runs 'globname = require(modname)'. -*/ -static int dolibrary (lua_State *L, char *globname) { - int status; - char *modname = strchr(globname, '='); - if (modname == NULL) /* no explicit name? */ - modname = globname; /* module name is equal to global name */ - else { - *modname = '\0'; /* global name ends here */ - modname++; /* module name starts after the '=' */ - } - lua_getglobal(L, "require"); - lua_pushstring(L, modname); - status = docall(L, 1, 1); /* call 'require(modname)' */ - if (status == LUA_OK) - lua_setglobal(L, globname); /* globname = require(modname) */ - return report(L, status); -} - - -/* -** Push on the stack the contents of table 'arg' from 1 to #arg -*/ -static int pushargs (lua_State *L) { - int i, n; - if (lua_getglobal(L, "arg") != LUA_TTABLE) - luaL_error(L, "'arg' is not a table"); - n = (int)luaL_len(L, -1); - luaL_checkstack(L, n + 3, "too many arguments to script"); - for (i = 1; i <= n; i++) - lua_rawgeti(L, -i, i); - lua_remove(L, -i); /* remove table from the stack */ - return n; -} - - -static int handle_script (lua_State *L, char **argv) { - int status; - const char *fname = argv[0]; - if (strcmp(fname, "-") == 0 && strcmp(argv[-1], "--") != 0) - fname = NULL; /* stdin */ - status = luaL_loadfile(L, fname); - if (status == LUA_OK) { - int n = pushargs(L); /* push arguments to script */ - status = docall(L, n, LUA_MULTRET); - } - return report(L, status); -} - - -/* bits of various argument indicators in 'args' */ -#define has_error 1 /* bad option */ -#define has_i 2 /* -i */ -#define has_v 4 /* -v */ -#define has_e 8 /* -e */ -#define has_E 16 /* -E */ - - -/* -** Traverses all arguments from 'argv', returning a mask with those -** needed before running any Lua code or an error code if it finds any -** invalid argument. In case of error, 'first' is the index of the bad -** argument. Otherwise, 'first' is -1 if there is no program name, -** 0 if there is no script name, or the index of the script name. -*/ -static int collectargs (char **argv, int *first) { - int args = 0; - int i; - if (argv[0] != NULL) { /* is there a program name? */ - if (argv[0][0]) /* not empty? */ - progname = argv[0]; /* save it */ - } - else { /* no program name */ - *first = -1; - return 0; - } - for (i = 1; argv[i] != NULL; i++) { /* handle arguments */ - *first = i; - if (argv[i][0] != '-') /* not an option? */ - return args; /* stop handling options */ - switch (argv[i][1]) { /* else check option */ - case '-': /* '--' */ - if (argv[i][2] != '\0') /* extra characters after '--'? */ - return has_error; /* invalid option */ - *first = i + 1; - return args; - case '\0': /* '-' */ - return args; /* script "name" is '-' */ - case 'E': - if (argv[i][2] != '\0') /* extra characters? */ - return has_error; /* invalid option */ - args |= has_E; - break; - case 'W': - if (argv[i][2] != '\0') /* extra characters? */ - return has_error; /* invalid option */ - break; - case 'i': - args |= has_i; /* (-i implies -v) *//* FALLTHROUGH */ - case 'v': - if (argv[i][2] != '\0') /* extra characters? */ - return has_error; /* invalid option */ - args |= has_v; - break; - case 'e': - args |= has_e; /* FALLTHROUGH */ - case 'l': /* both options need an argument */ - if (argv[i][2] == '\0') { /* no concatenated argument? */ - i++; /* try next 'argv' */ - if (argv[i] == NULL || argv[i][0] == '-') - return has_error; /* no next argument or it is another option */ - } - break; - default: /* invalid option */ - return has_error; - } - } - *first = 0; /* no script name */ - return args; -} - - -/* -** Processes options 'e' and 'l', which involve running Lua code, and -** 'W', which also affects the state. -** Returns 0 if some code raises an error. -*/ -static int runargs (lua_State *L, char **argv, int n) { - int i; - for (i = 1; i < n; i++) { - int option = argv[i][1]; - lua_assert(argv[i][0] == '-'); /* already checked */ - switch (option) { - case 'e': case 'l': { - int status; - char *extra = argv[i] + 2; /* both options need an argument */ - if (*extra == '\0') extra = argv[++i]; - lua_assert(extra != NULL); - status = (option == 'e') - ? dostring(L, extra, "=(command line)") - : dolibrary(L, extra); - if (status != LUA_OK) return 0; - break; - } - case 'W': - lua_warning(L, "@on", 0); /* warnings on */ - break; - } - } - return 1; -} - - -static int handle_luainit (lua_State *L) { - const char *name = "=" LUA_INITVARVERSION; - const char *init = getenv(name + 1); - if (init == NULL) { - name = "=" LUA_INIT_VAR; - init = getenv(name + 1); /* try alternative name */ - } - if (init == NULL) return LUA_OK; - else if (init[0] == '@') - return dofile(L, init+1); - else - return dostring(L, init, name); -} - - -/* -** {================================================================== -** Read-Eval-Print Loop (REPL) -** =================================================================== -*/ - -#if !defined(LUA_PROMPT) -#define LUA_PROMPT "> " -#define LUA_PROMPT2 ">> " -#endif - -#if !defined(LUA_MAXINPUT) -#define LUA_MAXINPUT 512 -#endif - - -/* -** lua_stdin_is_tty detects whether the standard input is a 'tty' (that -** is, whether we're running lua interactively). -*/ -#if !defined(lua_stdin_is_tty) /* { */ - -#if defined(LUA_USE_POSIX) /* { */ - -#include -#define lua_stdin_is_tty() isatty(0) - -#elif defined(LUA_USE_WINDOWS) /* }{ */ - -#include -#include - -#define lua_stdin_is_tty() _isatty(_fileno(stdin)) - -#else /* }{ */ - -/* ISO C definition */ -#define lua_stdin_is_tty() 1 /* assume stdin is a tty */ - -#endif /* } */ - -#endif /* } */ - - -/* -** lua_readline defines how to show a prompt and then read a line from -** the standard input. -** lua_saveline defines how to "save" a read line in a "history". -** lua_freeline defines how to free a line read by lua_readline. -*/ -#if !defined(lua_readline) /* { */ - -#if defined(LUA_USE_READLINE) /* { */ - -#include -#include -#define lua_initreadline(L) ((void)L, rl_readline_name="lua") -#define lua_readline(L,b,p) ((void)L, ((b)=readline(p)) != NULL) -#define lua_saveline(L,line) ((void)L, add_history(line)) -#define lua_freeline(L,b) ((void)L, free(b)) - -#else /* }{ */ - -#define lua_initreadline(L) ((void)L) -#define lua_readline(L,b,p) \ - ((void)L, fputs(p, stdout), fflush(stdout), /* show prompt */ \ - fgets(b, LUA_MAXINPUT, stdin) != NULL) /* get line */ -#define lua_saveline(L,line) { (void)L; (void)line; } -#define lua_freeline(L,b) { (void)L; (void)b; } - -#endif /* } */ - -#endif /* } */ - - -/* -** Return the string to be used as a prompt by the interpreter. Leave -** the string (or nil, if using the default value) on the stack, to keep -** it anchored. -*/ -static const char *get_prompt (lua_State *L, int firstline) { - if (lua_getglobal(L, firstline ? "_PROMPT" : "_PROMPT2") == LUA_TNIL) - return (firstline ? LUA_PROMPT : LUA_PROMPT2); /* use the default */ - else { /* apply 'tostring' over the value */ - const char *p = luaL_tolstring(L, -1, NULL); - lua_remove(L, -2); /* remove original value */ - return p; - } -} - -/* mark in error messages for incomplete statements */ -#define EOFMARK "" -#define marklen (sizeof(EOFMARK)/sizeof(char) - 1) - - -/* -** Check whether 'status' signals a syntax error and the error -** message at the top of the stack ends with the above mark for -** incomplete statements. -*/ -static int incomplete (lua_State *L, int status) { - if (status == LUA_ERRSYNTAX) { - size_t lmsg; - const char *msg = lua_tolstring(L, -1, &lmsg); - if (lmsg >= marklen && strcmp(msg + lmsg - marklen, EOFMARK) == 0) { - lua_pop(L, 1); - return 1; - } - } - return 0; /* else... */ -} - - -/* -** Prompt the user, read a line, and push it into the Lua stack. -*/ -static int pushline (lua_State *L, int firstline) { - char buffer[LUA_MAXINPUT]; - char *b = buffer; - size_t l; - const char *prmt = get_prompt(L, firstline); - int readstatus = lua_readline(L, b, prmt); - if (readstatus == 0) - return 0; /* no input (prompt will be popped by caller) */ - lua_pop(L, 1); /* remove prompt */ - l = strlen(b); - if (l > 0 && b[l-1] == '\n') /* line ends with newline? */ - b[--l] = '\0'; /* remove it */ - if (firstline && b[0] == '=') /* for compatibility with 5.2, ... */ - lua_pushfstring(L, "return %s", b + 1); /* change '=' to 'return' */ - else - lua_pushlstring(L, b, l); - lua_freeline(L, b); - return 1; -} - - -/* -** Try to compile line on the stack as 'return ;'; on return, stack -** has either compiled chunk or original line (if compilation failed). -*/ -static int addreturn (lua_State *L) { - const char *line = lua_tostring(L, -1); /* original line */ - const char *retline = lua_pushfstring(L, "return %s;", line); - int status = luaL_loadbuffer(L, retline, strlen(retline), "=stdin"); - if (status == LUA_OK) { - lua_remove(L, -2); /* remove modified line */ - if (line[0] != '\0') /* non empty? */ - lua_saveline(L, line); /* keep history */ - } - else - lua_pop(L, 2); /* pop result from 'luaL_loadbuffer' and modified line */ - return status; -} - - -/* -** Read multiple lines until a complete Lua statement -*/ -static int multiline (lua_State *L) { - for (;;) { /* repeat until gets a complete statement */ - size_t len; - const char *line = lua_tolstring(L, 1, &len); /* get what it has */ - int status = luaL_loadbuffer(L, line, len, "=stdin"); /* try it */ - if (!incomplete(L, status) || !pushline(L, 0)) { - lua_saveline(L, line); /* keep history */ - return status; /* cannot or should not try to add continuation line */ - } - lua_pushliteral(L, "\n"); /* add newline... */ - lua_insert(L, -2); /* ...between the two lines */ - lua_concat(L, 3); /* join them */ - } -} - - -/* -** Read a line and try to load (compile) it first as an expression (by -** adding "return " in front of it) and second as a statement. Return -** the final status of load/call with the resulting function (if any) -** in the top of the stack. -*/ -static int loadline (lua_State *L) { - int status; - lua_settop(L, 0); - if (!pushline(L, 1)) - return -1; /* no input */ - if ((status = addreturn(L)) != LUA_OK) /* 'return ...' did not work? */ - status = multiline(L); /* try as command, maybe with continuation lines */ - lua_remove(L, 1); /* remove line from the stack */ - lua_assert(lua_gettop(L) == 1); - return status; -} - - -/* -** Prints (calling the Lua 'print' function) any values on the stack -*/ -static void l_print (lua_State *L) { - int n = lua_gettop(L); - if (n > 0) { /* any result to be printed? */ - luaL_checkstack(L, LUA_MINSTACK, "too many results to print"); - lua_getglobal(L, "print"); - lua_insert(L, 1); - if (lua_pcall(L, n, 0, 0) != LUA_OK) - l_message(progname, lua_pushfstring(L, "error calling 'print' (%s)", - lua_tostring(L, -1))); - } -} - - -/* -** Do the REPL: repeatedly read (load) a line, evaluate (call) it, and -** print any results. -*/ -static void doREPL (lua_State *L) { - int status; - const char *oldprogname = progname; - progname = NULL; /* no 'progname' on errors in interactive mode */ - lua_initreadline(L); - while ((status = loadline(L)) != -1) { - if (status == LUA_OK) - status = docall(L, 0, LUA_MULTRET); - if (status == LUA_OK) l_print(L); - else report(L, status); - } - lua_settop(L, 0); /* clear stack */ - lua_writeline(); - progname = oldprogname; -} - -/* }================================================================== */ - - -/* -** Main body of stand-alone interpreter (to be called in protected mode). -** Reads the options and handles them all. -*/ -static int pmain (lua_State *L) { - int argc = (int)lua_tointeger(L, 1); - char **argv = (char **)lua_touserdata(L, 2); - int script; - int args = collectargs(argv, &script); - int optlim = (script > 0) ? script : argc; /* first argv not an option */ - luaL_checkversion(L); /* check that interpreter has correct version */ - if (args == has_error) { /* bad arg? */ - print_usage(argv[script]); /* 'script' has index of bad arg. */ - return 0; - } - if (args & has_v) /* option '-v'? */ - print_version(); - if (args & has_E) { /* option '-E'? */ - lua_pushboolean(L, 1); /* signal for libraries to ignore env. vars. */ - lua_setfield(L, LUA_REGISTRYINDEX, "LUA_NOENV"); - } - luaL_openlibs(L); /* open standard libraries */ - createargtable(L, argv, argc, script); /* create table 'arg' */ - lua_gc(L, LUA_GCRESTART); /* start GC... */ - lua_gc(L, LUA_GCGEN, 0, 0); /* ...in generational mode */ - if (!(args & has_E)) { /* no option '-E'? */ - if (handle_luainit(L) != LUA_OK) /* run LUA_INIT */ - return 0; /* error running LUA_INIT */ - } - if (!runargs(L, argv, optlim)) /* execute arguments -e and -l */ - return 0; /* something failed */ - if (script > 0) { /* execute main script (if there is one) */ - if (handle_script(L, argv + script) != LUA_OK) - return 0; /* interrupt in case of error */ - } - if (args & has_i) /* -i option? */ - doREPL(L); /* do read-eval-print loop */ - else if (script < 1 && !(args & (has_e | has_v))) { /* no active option? */ - if (lua_stdin_is_tty()) { /* running in interactive mode? */ - print_version(); - doREPL(L); /* do read-eval-print loop */ - } - else dofile(L, NULL); /* executes stdin as a file */ - } - lua_pushboolean(L, 1); /* signal no errors */ - return 1; -} - - -int main (int argc, char **argv) { - int status, result; - lua_State *L = luaL_newstate(); /* create state */ - if (L == NULL) { - l_message(argv[0], "cannot create state: not enough memory"); - return EXIT_FAILURE; - } - lua_gc(L, LUA_GCSTOP); /* stop GC while building state */ - lua_pushcfunction(L, &pmain); /* to call 'pmain' in protected mode */ - lua_pushinteger(L, argc); /* 1st argument */ - lua_pushlightuserdata(L, argv); /* 2nd argument */ - status = lua_pcall(L, 2, 1, 0); /* do the call */ - result = lua_toboolean(L, -1); /* get result */ - report(L, status); - lua_close(L); - return (result && status == LUA_OK) ? EXIT_SUCCESS : EXIT_FAILURE; -} - diff --git a/lib/lua-5.4/src/lua.h b/lib/lua-5.4/src/lua.h deleted file mode 100644 index fd16cf8..0000000 --- a/lib/lua-5.4/src/lua.h +++ /dev/null @@ -1,523 +0,0 @@ -/* -** $Id: lua.h $ -** Lua - A Scripting Language -** Lua.org, PUC-Rio, Brazil (http://www.lua.org) -** See Copyright Notice at the end of this file -*/ - - -#ifndef lua_h -#define lua_h - -#include -#include - - -#include "luaconf.h" - - -#define LUA_VERSION_MAJOR "5" -#define LUA_VERSION_MINOR "4" -#define LUA_VERSION_RELEASE "6" - -#define LUA_VERSION_NUM 504 -#define LUA_VERSION_RELEASE_NUM (LUA_VERSION_NUM * 100 + 6) - -#define LUA_VERSION "Lua " LUA_VERSION_MAJOR "." LUA_VERSION_MINOR -#define LUA_RELEASE LUA_VERSION "." LUA_VERSION_RELEASE -#define LUA_COPYRIGHT LUA_RELEASE " Copyright (C) 1994-2023 Lua.org, PUC-Rio" -#define LUA_AUTHORS "R. Ierusalimschy, L. H. de Figueiredo, W. Celes" - - -/* mark for precompiled code ('Lua') */ -#define LUA_SIGNATURE "\x1bLua" - -/* option for multiple returns in 'lua_pcall' and 'lua_call' */ -#define LUA_MULTRET (-1) - - -/* -** Pseudo-indices -** (-LUAI_MAXSTACK is the minimum valid index; we keep some free empty -** space after that to help overflow detection) -*/ -#define LUA_REGISTRYINDEX (-LUAI_MAXSTACK - 1000) -#define lua_upvalueindex(i) (LUA_REGISTRYINDEX - (i)) - - -/* thread status */ -#define LUA_OK 0 -#define LUA_YIELD 1 -#define LUA_ERRRUN 2 -#define LUA_ERRSYNTAX 3 -#define LUA_ERRMEM 4 -#define LUA_ERRERR 5 - - -typedef struct lua_State lua_State; - - -/* -** basic types -*/ -#define LUA_TNONE (-1) - -#define LUA_TNIL 0 -#define LUA_TBOOLEAN 1 -#define LUA_TLIGHTUSERDATA 2 -#define LUA_TNUMBER 3 -#define LUA_TSTRING 4 -#define LUA_TTABLE 5 -#define LUA_TFUNCTION 6 -#define LUA_TUSERDATA 7 -#define LUA_TTHREAD 8 - -#define LUA_NUMTYPES 9 - - - -/* minimum Lua stack available to a C function */ -#define LUA_MINSTACK 20 - - -/* predefined values in the registry */ -#define LUA_RIDX_MAINTHREAD 1 -#define LUA_RIDX_GLOBALS 2 -#define LUA_RIDX_LAST LUA_RIDX_GLOBALS - - -/* type of numbers in Lua */ -typedef LUA_NUMBER lua_Number; - - -/* type for integer functions */ -typedef LUA_INTEGER lua_Integer; - -/* unsigned integer type */ -typedef LUA_UNSIGNED lua_Unsigned; - -/* type for continuation-function contexts */ -typedef LUA_KCONTEXT lua_KContext; - - -/* -** Type for C functions registered with Lua -*/ -typedef int (*lua_CFunction) (lua_State *L); - -/* -** Type for continuation functions -*/ -typedef int (*lua_KFunction) (lua_State *L, int status, lua_KContext ctx); - - -/* -** Type for functions that read/write blocks when loading/dumping Lua chunks -*/ -typedef const char * (*lua_Reader) (lua_State *L, void *ud, size_t *sz); - -typedef int (*lua_Writer) (lua_State *L, const void *p, size_t sz, void *ud); - - -/* -** Type for memory-allocation functions -*/ -typedef void * (*lua_Alloc) (void *ud, void *ptr, size_t osize, size_t nsize); - - -/* -** Type for warning functions -*/ -typedef void (*lua_WarnFunction) (void *ud, const char *msg, int tocont); - - -/* -** Type used by the debug API to collect debug information -*/ -typedef struct lua_Debug lua_Debug; - - -/* -** Functions to be called by the debugger in specific events -*/ -typedef void (*lua_Hook) (lua_State *L, lua_Debug *ar); - - -/* -** generic extra include file -*/ -#if defined(LUA_USER_H) -#include LUA_USER_H -#endif - - -/* -** RCS ident string -*/ -extern const char lua_ident[]; - - -/* -** state manipulation -*/ -LUA_API lua_State *(lua_newstate) (lua_Alloc f, void *ud); -LUA_API void (lua_close) (lua_State *L); -LUA_API lua_State *(lua_newthread) (lua_State *L); -LUA_API int (lua_closethread) (lua_State *L, lua_State *from); -LUA_API int (lua_resetthread) (lua_State *L); /* Deprecated! */ - -LUA_API lua_CFunction (lua_atpanic) (lua_State *L, lua_CFunction panicf); - - -LUA_API lua_Number (lua_version) (lua_State *L); - - -/* -** basic stack manipulation -*/ -LUA_API int (lua_absindex) (lua_State *L, int idx); -LUA_API int (lua_gettop) (lua_State *L); -LUA_API void (lua_settop) (lua_State *L, int idx); -LUA_API void (lua_pushvalue) (lua_State *L, int idx); -LUA_API void (lua_rotate) (lua_State *L, int idx, int n); -LUA_API void (lua_copy) (lua_State *L, int fromidx, int toidx); -LUA_API int (lua_checkstack) (lua_State *L, int n); - -LUA_API void (lua_xmove) (lua_State *from, lua_State *to, int n); - - -/* -** access functions (stack -> C) -*/ - -LUA_API int (lua_isnumber) (lua_State *L, int idx); -LUA_API int (lua_isstring) (lua_State *L, int idx); -LUA_API int (lua_iscfunction) (lua_State *L, int idx); -LUA_API int (lua_isinteger) (lua_State *L, int idx); -LUA_API int (lua_isuserdata) (lua_State *L, int idx); -LUA_API int (lua_type) (lua_State *L, int idx); -LUA_API const char *(lua_typename) (lua_State *L, int tp); - -LUA_API lua_Number (lua_tonumberx) (lua_State *L, int idx, int *isnum); -LUA_API lua_Integer (lua_tointegerx) (lua_State *L, int idx, int *isnum); -LUA_API int (lua_toboolean) (lua_State *L, int idx); -LUA_API const char *(lua_tolstring) (lua_State *L, int idx, size_t *len); -LUA_API lua_Unsigned (lua_rawlen) (lua_State *L, int idx); -LUA_API lua_CFunction (lua_tocfunction) (lua_State *L, int idx); -LUA_API void *(lua_touserdata) (lua_State *L, int idx); -LUA_API lua_State *(lua_tothread) (lua_State *L, int idx); -LUA_API const void *(lua_topointer) (lua_State *L, int idx); - - -/* -** Comparison and arithmetic functions -*/ - -#define LUA_OPADD 0 /* ORDER TM, ORDER OP */ -#define LUA_OPSUB 1 -#define LUA_OPMUL 2 -#define LUA_OPMOD 3 -#define LUA_OPPOW 4 -#define LUA_OPDIV 5 -#define LUA_OPIDIV 6 -#define LUA_OPBAND 7 -#define LUA_OPBOR 8 -#define LUA_OPBXOR 9 -#define LUA_OPSHL 10 -#define LUA_OPSHR 11 -#define LUA_OPUNM 12 -#define LUA_OPBNOT 13 - -LUA_API void (lua_arith) (lua_State *L, int op); - -#define LUA_OPEQ 0 -#define LUA_OPLT 1 -#define LUA_OPLE 2 - -LUA_API int (lua_rawequal) (lua_State *L, int idx1, int idx2); -LUA_API int (lua_compare) (lua_State *L, int idx1, int idx2, int op); - - -/* -** push functions (C -> stack) -*/ -LUA_API void (lua_pushnil) (lua_State *L); -LUA_API void (lua_pushnumber) (lua_State *L, lua_Number n); -LUA_API void (lua_pushinteger) (lua_State *L, lua_Integer n); -LUA_API const char *(lua_pushlstring) (lua_State *L, const char *s, size_t len); -LUA_API const char *(lua_pushstring) (lua_State *L, const char *s); -LUA_API const char *(lua_pushvfstring) (lua_State *L, const char *fmt, - va_list argp); -LUA_API const char *(lua_pushfstring) (lua_State *L, const char *fmt, ...); -LUA_API void (lua_pushcclosure) (lua_State *L, lua_CFunction fn, int n); -LUA_API void (lua_pushboolean) (lua_State *L, int b); -LUA_API void (lua_pushlightuserdata) (lua_State *L, void *p); -LUA_API int (lua_pushthread) (lua_State *L); - - -/* -** get functions (Lua -> stack) -*/ -LUA_API int (lua_getglobal) (lua_State *L, const char *name); -LUA_API int (lua_gettable) (lua_State *L, int idx); -LUA_API int (lua_getfield) (lua_State *L, int idx, const char *k); -LUA_API int (lua_geti) (lua_State *L, int idx, lua_Integer n); -LUA_API int (lua_rawget) (lua_State *L, int idx); -LUA_API int (lua_rawgeti) (lua_State *L, int idx, lua_Integer n); -LUA_API int (lua_rawgetp) (lua_State *L, int idx, const void *p); - -LUA_API void (lua_createtable) (lua_State *L, int narr, int nrec); -LUA_API void *(lua_newuserdatauv) (lua_State *L, size_t sz, int nuvalue); -LUA_API int (lua_getmetatable) (lua_State *L, int objindex); -LUA_API int (lua_getiuservalue) (lua_State *L, int idx, int n); - - -/* -** set functions (stack -> Lua) -*/ -LUA_API void (lua_setglobal) (lua_State *L, const char *name); -LUA_API void (lua_settable) (lua_State *L, int idx); -LUA_API void (lua_setfield) (lua_State *L, int idx, const char *k); -LUA_API void (lua_seti) (lua_State *L, int idx, lua_Integer n); -LUA_API void (lua_rawset) (lua_State *L, int idx); -LUA_API void (lua_rawseti) (lua_State *L, int idx, lua_Integer n); -LUA_API void (lua_rawsetp) (lua_State *L, int idx, const void *p); -LUA_API int (lua_setmetatable) (lua_State *L, int objindex); -LUA_API int (lua_setiuservalue) (lua_State *L, int idx, int n); - - -/* -** 'load' and 'call' functions (load and run Lua code) -*/ -LUA_API void (lua_callk) (lua_State *L, int nargs, int nresults, - lua_KContext ctx, lua_KFunction k); -#define lua_call(L,n,r) lua_callk(L, (n), (r), 0, NULL) - -LUA_API int (lua_pcallk) (lua_State *L, int nargs, int nresults, int errfunc, - lua_KContext ctx, lua_KFunction k); -#define lua_pcall(L,n,r,f) lua_pcallk(L, (n), (r), (f), 0, NULL) - -LUA_API int (lua_load) (lua_State *L, lua_Reader reader, void *dt, - const char *chunkname, const char *mode); - -LUA_API int (lua_dump) (lua_State *L, lua_Writer writer, void *data, int strip); - - -/* -** coroutine functions -*/ -LUA_API int (lua_yieldk) (lua_State *L, int nresults, lua_KContext ctx, - lua_KFunction k); -LUA_API int (lua_resume) (lua_State *L, lua_State *from, int narg, - int *nres); -LUA_API int (lua_status) (lua_State *L); -LUA_API int (lua_isyieldable) (lua_State *L); - -#define lua_yield(L,n) lua_yieldk(L, (n), 0, NULL) - - -/* -** Warning-related functions -*/ -LUA_API void (lua_setwarnf) (lua_State *L, lua_WarnFunction f, void *ud); -LUA_API void (lua_warning) (lua_State *L, const char *msg, int tocont); - - -/* -** garbage-collection function and options -*/ - -#define LUA_GCSTOP 0 -#define LUA_GCRESTART 1 -#define LUA_GCCOLLECT 2 -#define LUA_GCCOUNT 3 -#define LUA_GCCOUNTB 4 -#define LUA_GCSTEP 5 -#define LUA_GCSETPAUSE 6 -#define LUA_GCSETSTEPMUL 7 -#define LUA_GCISRUNNING 9 -#define LUA_GCGEN 10 -#define LUA_GCINC 11 - -LUA_API int (lua_gc) (lua_State *L, int what, ...); - - -/* -** miscellaneous functions -*/ - -LUA_API int (lua_error) (lua_State *L); - -LUA_API int (lua_next) (lua_State *L, int idx); - -LUA_API void (lua_concat) (lua_State *L, int n); -LUA_API void (lua_len) (lua_State *L, int idx); - -LUA_API size_t (lua_stringtonumber) (lua_State *L, const char *s); - -LUA_API lua_Alloc (lua_getallocf) (lua_State *L, void **ud); -LUA_API void (lua_setallocf) (lua_State *L, lua_Alloc f, void *ud); - -LUA_API void (lua_toclose) (lua_State *L, int idx); -LUA_API void (lua_closeslot) (lua_State *L, int idx); - - -/* -** {============================================================== -** some useful macros -** =============================================================== -*/ - -#define lua_getextraspace(L) ((void *)((char *)(L) - LUA_EXTRASPACE)) - -#define lua_tonumber(L,i) lua_tonumberx(L,(i),NULL) -#define lua_tointeger(L,i) lua_tointegerx(L,(i),NULL) - -#define lua_pop(L,n) lua_settop(L, -(n)-1) - -#define lua_newtable(L) lua_createtable(L, 0, 0) - -#define lua_register(L,n,f) (lua_pushcfunction(L, (f)), lua_setglobal(L, (n))) - -#define lua_pushcfunction(L,f) lua_pushcclosure(L, (f), 0) - -#define lua_isfunction(L,n) (lua_type(L, (n)) == LUA_TFUNCTION) -#define lua_istable(L,n) (lua_type(L, (n)) == LUA_TTABLE) -#define lua_islightuserdata(L,n) (lua_type(L, (n)) == LUA_TLIGHTUSERDATA) -#define lua_isnil(L,n) (lua_type(L, (n)) == LUA_TNIL) -#define lua_isboolean(L,n) (lua_type(L, (n)) == LUA_TBOOLEAN) -#define lua_isthread(L,n) (lua_type(L, (n)) == LUA_TTHREAD) -#define lua_isnone(L,n) (lua_type(L, (n)) == LUA_TNONE) -#define lua_isnoneornil(L, n) (lua_type(L, (n)) <= 0) - -#define lua_pushliteral(L, s) lua_pushstring(L, "" s) - -#define lua_pushglobaltable(L) \ - ((void)lua_rawgeti(L, LUA_REGISTRYINDEX, LUA_RIDX_GLOBALS)) - -#define lua_tostring(L,i) lua_tolstring(L, (i), NULL) - - -#define lua_insert(L,idx) lua_rotate(L, (idx), 1) - -#define lua_remove(L,idx) (lua_rotate(L, (idx), -1), lua_pop(L, 1)) - -#define lua_replace(L,idx) (lua_copy(L, -1, (idx)), lua_pop(L, 1)) - -/* }============================================================== */ - - -/* -** {============================================================== -** compatibility macros -** =============================================================== -*/ -#if defined(LUA_COMPAT_APIINTCASTS) - -#define lua_pushunsigned(L,n) lua_pushinteger(L, (lua_Integer)(n)) -#define lua_tounsignedx(L,i,is) ((lua_Unsigned)lua_tointegerx(L,i,is)) -#define lua_tounsigned(L,i) lua_tounsignedx(L,(i),NULL) - -#endif - -#define lua_newuserdata(L,s) lua_newuserdatauv(L,s,1) -#define lua_getuservalue(L,idx) lua_getiuservalue(L,idx,1) -#define lua_setuservalue(L,idx) lua_setiuservalue(L,idx,1) - -#define LUA_NUMTAGS LUA_NUMTYPES - -/* }============================================================== */ - -/* -** {====================================================================== -** Debug API -** ======================================================================= -*/ - - -/* -** Event codes -*/ -#define LUA_HOOKCALL 0 -#define LUA_HOOKRET 1 -#define LUA_HOOKLINE 2 -#define LUA_HOOKCOUNT 3 -#define LUA_HOOKTAILCALL 4 - - -/* -** Event masks -*/ -#define LUA_MASKCALL (1 << LUA_HOOKCALL) -#define LUA_MASKRET (1 << LUA_HOOKRET) -#define LUA_MASKLINE (1 << LUA_HOOKLINE) -#define LUA_MASKCOUNT (1 << LUA_HOOKCOUNT) - - -LUA_API int (lua_getstack) (lua_State *L, int level, lua_Debug *ar); -LUA_API int (lua_getinfo) (lua_State *L, const char *what, lua_Debug *ar); -LUA_API const char *(lua_getlocal) (lua_State *L, const lua_Debug *ar, int n); -LUA_API const char *(lua_setlocal) (lua_State *L, const lua_Debug *ar, int n); -LUA_API const char *(lua_getupvalue) (lua_State *L, int funcindex, int n); -LUA_API const char *(lua_setupvalue) (lua_State *L, int funcindex, int n); - -LUA_API void *(lua_upvalueid) (lua_State *L, int fidx, int n); -LUA_API void (lua_upvaluejoin) (lua_State *L, int fidx1, int n1, - int fidx2, int n2); - -LUA_API void (lua_sethook) (lua_State *L, lua_Hook func, int mask, int count); -LUA_API lua_Hook (lua_gethook) (lua_State *L); -LUA_API int (lua_gethookmask) (lua_State *L); -LUA_API int (lua_gethookcount) (lua_State *L); - -LUA_API int (lua_setcstacklimit) (lua_State *L, unsigned int limit); - -struct lua_Debug { - int event; - const char *name; /* (n) */ - const char *namewhat; /* (n) 'global', 'local', 'field', 'method' */ - const char *what; /* (S) 'Lua', 'C', 'main', 'tail' */ - const char *source; /* (S) */ - size_t srclen; /* (S) */ - int currentline; /* (l) */ - int linedefined; /* (S) */ - int lastlinedefined; /* (S) */ - unsigned char nups; /* (u) number of upvalues */ - unsigned char nparams;/* (u) number of parameters */ - char isvararg; /* (u) */ - char istailcall; /* (t) */ - unsigned short ftransfer; /* (r) index of first value transferred */ - unsigned short ntransfer; /* (r) number of transferred values */ - char short_src[LUA_IDSIZE]; /* (S) */ - /* private part */ - struct CallInfo *i_ci; /* active function */ -}; - -/* }====================================================================== */ - - -/****************************************************************************** -* Copyright (C) 1994-2023 Lua.org, PUC-Rio. -* -* Permission is hereby granted, free of charge, to any person obtaining -* a copy of this software and associated documentation files (the -* "Software"), to deal in the Software without restriction, including -* without limitation the rights to use, copy, modify, merge, publish, -* distribute, sublicense, and/or sell copies of the Software, and to -* permit persons to whom the Software is furnished to do so, subject to -* the following conditions: -* -* The above copyright notice and this permission notice shall be -* included in all copies or substantial portions of the Software. -* -* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, -* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF -* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. -* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY -* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, -* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE -* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. -******************************************************************************/ - - -#endif diff --git a/lib/lua-5.4/src/lua.hpp b/lib/lua-5.4/src/lua.hpp deleted file mode 100644 index ec417f5..0000000 --- a/lib/lua-5.4/src/lua.hpp +++ /dev/null @@ -1,9 +0,0 @@ -// lua.hpp -// Lua header files for C++ -// <> not supplied automatically because Lua also compiles as C++ - -extern "C" { -#include "lua.h" -#include "lualib.h" -#include "lauxlib.h" -} diff --git a/lib/lua-5.4/src/luac.c b/lib/lua-5.4/src/luac.c deleted file mode 100644 index 5f4a141..0000000 --- a/lib/lua-5.4/src/luac.c +++ /dev/null @@ -1,723 +0,0 @@ -/* -** $Id: luac.c $ -** Lua compiler (saves bytecodes to files; also lists bytecodes) -** See Copyright Notice in lua.h -*/ - -#define luac_c -#define LUA_CORE - -#include "lprefix.h" - -#include -#include -#include -#include -#include - -#include "lua.h" -#include "lauxlib.h" - -#include "ldebug.h" -#include "lobject.h" -#include "lopcodes.h" -#include "lopnames.h" -#include "lstate.h" -#include "lundump.h" - -static void PrintFunction(const Proto* f, int full); -#define luaU_print PrintFunction - -#define PROGNAME "luac" /* default program name */ -#define OUTPUT PROGNAME ".out" /* default output file */ - -static int listing=0; /* list bytecodes? */ -static int dumping=1; /* dump bytecodes? */ -static int stripping=0; /* strip debug information? */ -static char Output[]={ OUTPUT }; /* default output file name */ -static const char* output=Output; /* actual output file name */ -static const char* progname=PROGNAME; /* actual program name */ -static TString **tmname; - -static void fatal(const char* message) -{ - fprintf(stderr,"%s: %s\n",progname,message); - exit(EXIT_FAILURE); -} - -static void cannot(const char* what) -{ - fprintf(stderr,"%s: cannot %s %s: %s\n",progname,what,output,strerror(errno)); - exit(EXIT_FAILURE); -} - -static void usage(const char* message) -{ - if (*message=='-') - fprintf(stderr,"%s: unrecognized option '%s'\n",progname,message); - else - fprintf(stderr,"%s: %s\n",progname,message); - fprintf(stderr, - "usage: %s [options] [filenames]\n" - "Available options are:\n" - " -l list (use -l -l for full listing)\n" - " -o name output to file 'name' (default is \"%s\")\n" - " -p parse only\n" - " -s strip debug information\n" - " -v show version information\n" - " -- stop handling options\n" - " - stop handling options and process stdin\n" - ,progname,Output); - exit(EXIT_FAILURE); -} - -#define IS(s) (strcmp(argv[i],s)==0) - -static int doargs(int argc, char* argv[]) -{ - int i; - int version=0; - if (argv[0]!=NULL && *argv[0]!=0) progname=argv[0]; - for (i=1; itop.p+(i))) - -static const Proto* combine(lua_State* L, int n) -{ - if (n==1) - return toproto(L,-1); - else - { - Proto* f; - int i=n; - if (lua_load(L,reader,&i,"=(" PROGNAME ")",NULL)!=LUA_OK) fatal(lua_tostring(L,-1)); - f=toproto(L,-1); - for (i=0; ip[i]=toproto(L,i-n-1); - if (f->p[i]->sizeupvalues>0) f->p[i]->upvalues[0].instack=0; - } - return f; - } -} - -static int writer(lua_State* L, const void* p, size_t size, void* u) -{ - UNUSED(L); - return (fwrite(p,size,1,(FILE*)u)!=1) && (size!=0); -} - -static int pmain(lua_State* L) -{ - int argc=(int)lua_tointeger(L,1); - char** argv=(char**)lua_touserdata(L,2); - const Proto* f; - int i; - tmname=G(L)->tmname; - if (!lua_checkstack(L,argc)) fatal("too many input files"); - for (i=0; i1); - if (dumping) - { - FILE* D= (output==NULL) ? stdout : fopen(output,"wb"); - if (D==NULL) cannot("open"); - lua_lock(L); - luaU_dump(L,f,writer,D,stripping); - lua_unlock(L); - if (ferror(D)) cannot("write"); - if (fclose(D)) cannot("close"); - } - return 0; -} - -int main(int argc, char* argv[]) -{ - lua_State* L; - int i=doargs(argc,argv); - argc-=i; argv+=i; - if (argc<=0) usage("no input files given"); - L=luaL_newstate(); - if (L==NULL) fatal("cannot create state: not enough memory"); - lua_pushcfunction(L,&pmain); - lua_pushinteger(L,argc); - lua_pushlightuserdata(L,argv); - if (lua_pcall(L,2,0,0)!=LUA_OK) fatal(lua_tostring(L,-1)); - lua_close(L); - return EXIT_SUCCESS; -} - -/* -** print bytecodes -*/ - -#define UPVALNAME(x) ((f->upvalues[x].name) ? getstr(f->upvalues[x].name) : "-") -#define VOID(p) ((const void*)(p)) -#define eventname(i) (getstr(tmname[i])) - -static void PrintString(const TString* ts) -{ - const char* s=getstr(ts); - size_t i,n=tsslen(ts); - printf("\""); - for (i=0; ik[i]; - switch (ttypetag(o)) - { - case LUA_VNIL: - printf("N"); - break; - case LUA_VFALSE: - case LUA_VTRUE: - printf("B"); - break; - case LUA_VNUMFLT: - printf("F"); - break; - case LUA_VNUMINT: - printf("I"); - break; - case LUA_VSHRSTR: - case LUA_VLNGSTR: - printf("S"); - break; - default: /* cannot happen */ - printf("?%d",ttypetag(o)); - break; - } - printf("\t"); -} - -static void PrintConstant(const Proto* f, int i) -{ - const TValue* o=&f->k[i]; - switch (ttypetag(o)) - { - case LUA_VNIL: - printf("nil"); - break; - case LUA_VFALSE: - printf("false"); - break; - case LUA_VTRUE: - printf("true"); - break; - case LUA_VNUMFLT: - { - char buff[100]; - sprintf(buff,LUA_NUMBER_FMT,fltvalue(o)); - printf("%s",buff); - if (buff[strspn(buff,"-0123456789")]=='\0') printf(".0"); - break; - } - case LUA_VNUMINT: - printf(LUA_INTEGER_FMT,ivalue(o)); - break; - case LUA_VSHRSTR: - case LUA_VLNGSTR: - PrintString(tsvalue(o)); - break; - default: /* cannot happen */ - printf("?%d",ttypetag(o)); - break; - } -} - -#define COMMENT "\t; " -#define EXTRAARG GETARG_Ax(code[pc+1]) -#define EXTRAARGC (EXTRAARG*(MAXARG_C+1)) -#define ISK (isk ? "k" : "") - -static void PrintCode(const Proto* f) -{ - const Instruction* code=f->code; - int pc,n=f->sizecode; - for (pc=0; pc0) printf("[%d]\t",line); else printf("[-]\t"); - printf("%-9s\t",opnames[o]); - switch (o) - { - case OP_MOVE: - printf("%d %d",a,b); - break; - case OP_LOADI: - printf("%d %d",a,sbx); - break; - case OP_LOADF: - printf("%d %d",a,sbx); - break; - case OP_LOADK: - printf("%d %d",a,bx); - printf(COMMENT); PrintConstant(f,bx); - break; - case OP_LOADKX: - printf("%d",a); - printf(COMMENT); PrintConstant(f,EXTRAARG); - break; - case OP_LOADFALSE: - printf("%d",a); - break; - case OP_LFALSESKIP: - printf("%d",a); - break; - case OP_LOADTRUE: - printf("%d",a); - break; - case OP_LOADNIL: - printf("%d %d",a,b); - printf(COMMENT "%d out",b+1); - break; - case OP_GETUPVAL: - printf("%d %d",a,b); - printf(COMMENT "%s",UPVALNAME(b)); - break; - case OP_SETUPVAL: - printf("%d %d",a,b); - printf(COMMENT "%s",UPVALNAME(b)); - break; - case OP_GETTABUP: - printf("%d %d %d",a,b,c); - printf(COMMENT "%s",UPVALNAME(b)); - printf(" "); PrintConstant(f,c); - break; - case OP_GETTABLE: - printf("%d %d %d",a,b,c); - break; - case OP_GETI: - printf("%d %d %d",a,b,c); - break; - case OP_GETFIELD: - printf("%d %d %d",a,b,c); - printf(COMMENT); PrintConstant(f,c); - break; - case OP_SETTABUP: - printf("%d %d %d%s",a,b,c,ISK); - printf(COMMENT "%s",UPVALNAME(a)); - printf(" "); PrintConstant(f,b); - if (isk) { printf(" "); PrintConstant(f,c); } - break; - case OP_SETTABLE: - printf("%d %d %d%s",a,b,c,ISK); - if (isk) { printf(COMMENT); PrintConstant(f,c); } - break; - case OP_SETI: - printf("%d %d %d%s",a,b,c,ISK); - if (isk) { printf(COMMENT); PrintConstant(f,c); } - break; - case OP_SETFIELD: - printf("%d %d %d%s",a,b,c,ISK); - printf(COMMENT); PrintConstant(f,b); - if (isk) { printf(" "); PrintConstant(f,c); } - break; - case OP_NEWTABLE: - printf("%d %d %d",a,b,c); - printf(COMMENT "%d",c+EXTRAARGC); - break; - case OP_SELF: - printf("%d %d %d%s",a,b,c,ISK); - if (isk) { printf(COMMENT); PrintConstant(f,c); } - break; - case OP_ADDI: - printf("%d %d %d",a,b,sc); - break; - case OP_ADDK: - printf("%d %d %d",a,b,c); - printf(COMMENT); PrintConstant(f,c); - break; - case OP_SUBK: - printf("%d %d %d",a,b,c); - printf(COMMENT); PrintConstant(f,c); - break; - case OP_MULK: - printf("%d %d %d",a,b,c); - printf(COMMENT); PrintConstant(f,c); - break; - case OP_MODK: - printf("%d %d %d",a,b,c); - printf(COMMENT); PrintConstant(f,c); - break; - case OP_POWK: - printf("%d %d %d",a,b,c); - printf(COMMENT); PrintConstant(f,c); - break; - case OP_DIVK: - printf("%d %d %d",a,b,c); - printf(COMMENT); PrintConstant(f,c); - break; - case OP_IDIVK: - printf("%d %d %d",a,b,c); - printf(COMMENT); PrintConstant(f,c); - break; - case OP_BANDK: - printf("%d %d %d",a,b,c); - printf(COMMENT); PrintConstant(f,c); - break; - case OP_BORK: - printf("%d %d %d",a,b,c); - printf(COMMENT); PrintConstant(f,c); - break; - case OP_BXORK: - printf("%d %d %d",a,b,c); - printf(COMMENT); PrintConstant(f,c); - break; - case OP_SHRI: - printf("%d %d %d",a,b,sc); - break; - case OP_SHLI: - printf("%d %d %d",a,b,sc); - break; - case OP_ADD: - printf("%d %d %d",a,b,c); - break; - case OP_SUB: - printf("%d %d %d",a,b,c); - break; - case OP_MUL: - printf("%d %d %d",a,b,c); - break; - case OP_MOD: - printf("%d %d %d",a,b,c); - break; - case OP_POW: - printf("%d %d %d",a,b,c); - break; - case OP_DIV: - printf("%d %d %d",a,b,c); - break; - case OP_IDIV: - printf("%d %d %d",a,b,c); - break; - case OP_BAND: - printf("%d %d %d",a,b,c); - break; - case OP_BOR: - printf("%d %d %d",a,b,c); - break; - case OP_BXOR: - printf("%d %d %d",a,b,c); - break; - case OP_SHL: - printf("%d %d %d",a,b,c); - break; - case OP_SHR: - printf("%d %d %d",a,b,c); - break; - case OP_MMBIN: - printf("%d %d %d",a,b,c); - printf(COMMENT "%s",eventname(c)); - break; - case OP_MMBINI: - printf("%d %d %d %d",a,sb,c,isk); - printf(COMMENT "%s",eventname(c)); - if (isk) printf(" flip"); - break; - case OP_MMBINK: - printf("%d %d %d %d",a,b,c,isk); - printf(COMMENT "%s ",eventname(c)); PrintConstant(f,b); - if (isk) printf(" flip"); - break; - case OP_UNM: - printf("%d %d",a,b); - break; - case OP_BNOT: - printf("%d %d",a,b); - break; - case OP_NOT: - printf("%d %d",a,b); - break; - case OP_LEN: - printf("%d %d",a,b); - break; - case OP_CONCAT: - printf("%d %d",a,b); - break; - case OP_CLOSE: - printf("%d",a); - break; - case OP_TBC: - printf("%d",a); - break; - case OP_JMP: - printf("%d",GETARG_sJ(i)); - printf(COMMENT "to %d",GETARG_sJ(i)+pc+2); - break; - case OP_EQ: - printf("%d %d %d",a,b,isk); - break; - case OP_LT: - printf("%d %d %d",a,b,isk); - break; - case OP_LE: - printf("%d %d %d",a,b,isk); - break; - case OP_EQK: - printf("%d %d %d",a,b,isk); - printf(COMMENT); PrintConstant(f,b); - break; - case OP_EQI: - printf("%d %d %d",a,sb,isk); - break; - case OP_LTI: - printf("%d %d %d",a,sb,isk); - break; - case OP_LEI: - printf("%d %d %d",a,sb,isk); - break; - case OP_GTI: - printf("%d %d %d",a,sb,isk); - break; - case OP_GEI: - printf("%d %d %d",a,sb,isk); - break; - case OP_TEST: - printf("%d %d",a,isk); - break; - case OP_TESTSET: - printf("%d %d %d",a,b,isk); - break; - case OP_CALL: - printf("%d %d %d",a,b,c); - printf(COMMENT); - if (b==0) printf("all in "); else printf("%d in ",b-1); - if (c==0) printf("all out"); else printf("%d out",c-1); - break; - case OP_TAILCALL: - printf("%d %d %d%s",a,b,c,ISK); - printf(COMMENT "%d in",b-1); - break; - case OP_RETURN: - printf("%d %d %d%s",a,b,c,ISK); - printf(COMMENT); - if (b==0) printf("all out"); else printf("%d out",b-1); - break; - case OP_RETURN0: - break; - case OP_RETURN1: - printf("%d",a); - break; - case OP_FORLOOP: - printf("%d %d",a,bx); - printf(COMMENT "to %d",pc-bx+2); - break; - case OP_FORPREP: - printf("%d %d",a,bx); - printf(COMMENT "exit to %d",pc+bx+3); - break; - case OP_TFORPREP: - printf("%d %d",a,bx); - printf(COMMENT "to %d",pc+bx+2); - break; - case OP_TFORCALL: - printf("%d %d",a,c); - break; - case OP_TFORLOOP: - printf("%d %d",a,bx); - printf(COMMENT "to %d",pc-bx+2); - break; - case OP_SETLIST: - printf("%d %d %d",a,b,c); - if (isk) printf(COMMENT "%d",c+EXTRAARGC); - break; - case OP_CLOSURE: - printf("%d %d",a,bx); - printf(COMMENT "%p",VOID(f->p[bx])); - break; - case OP_VARARG: - printf("%d %d",a,c); - printf(COMMENT); - if (c==0) printf("all out"); else printf("%d out",c-1); - break; - case OP_VARARGPREP: - printf("%d",a); - break; - case OP_EXTRAARG: - printf("%d",ax); - break; -#if 0 - default: - printf("%d %d %d",a,b,c); - printf(COMMENT "not handled"); - break; -#endif - } - printf("\n"); - } -} - - -#define SS(x) ((x==1)?"":"s") -#define S(x) (int)(x),SS(x) - -static void PrintHeader(const Proto* f) -{ - const char* s=f->source ? getstr(f->source) : "=?"; - if (*s=='@' || *s=='=') - s++; - else if (*s==LUA_SIGNATURE[0]) - s="(bstring)"; - else - s="(string)"; - printf("\n%s <%s:%d,%d> (%d instruction%s at %p)\n", - (f->linedefined==0)?"main":"function",s, - f->linedefined,f->lastlinedefined, - S(f->sizecode),VOID(f)); - printf("%d%s param%s, %d slot%s, %d upvalue%s, ", - (int)(f->numparams),f->is_vararg?"+":"",SS(f->numparams), - S(f->maxstacksize),S(f->sizeupvalues)); - printf("%d local%s, %d constant%s, %d function%s\n", - S(f->sizelocvars),S(f->sizek),S(f->sizep)); -} - -static void PrintDebug(const Proto* f) -{ - int i,n; - n=f->sizek; - printf("constants (%d) for %p:\n",n,VOID(f)); - for (i=0; isizelocvars; - printf("locals (%d) for %p:\n",n,VOID(f)); - for (i=0; ilocvars[i].varname),f->locvars[i].startpc+1,f->locvars[i].endpc+1); - } - n=f->sizeupvalues; - printf("upvalues (%d) for %p:\n",n,VOID(f)); - for (i=0; iupvalues[i].instack,f->upvalues[i].idx); - } -} - -static void PrintFunction(const Proto* f, int full) -{ - int i,n=f->sizep; - PrintHeader(f); - PrintCode(f); - if (full) PrintDebug(f); - for (i=0; ip[i],full); -} diff --git a/lib/lua-5.4/src/luaconf.h b/lib/lua-5.4/src/luaconf.h deleted file mode 100644 index 137103e..0000000 --- a/lib/lua-5.4/src/luaconf.h +++ /dev/null @@ -1,793 +0,0 @@ -/* -** $Id: luaconf.h $ -** Configuration file for Lua -** See Copyright Notice in lua.h -*/ - - -#ifndef luaconf_h -#define luaconf_h - -#include -#include - - -/* -** =================================================================== -** General Configuration File for Lua -** -** Some definitions here can be changed externally, through the compiler -** (e.g., with '-D' options): They are commented out or protected -** by '#if !defined' guards. However, several other definitions -** should be changed directly here, either because they affect the -** Lua ABI (by making the changes here, you ensure that all software -** connected to Lua, such as C libraries, will be compiled with the same -** configuration); or because they are seldom changed. -** -** Search for "@@" to find all configurable definitions. -** =================================================================== -*/ - - -/* -** {==================================================================== -** System Configuration: macros to adapt (if needed) Lua to some -** particular platform, for instance restricting it to C89. -** ===================================================================== -*/ - -/* -@@ LUA_USE_C89 controls the use of non-ISO-C89 features. -** Define it if you want Lua to avoid the use of a few C99 features -** or Windows-specific features on Windows. -*/ -/* #define LUA_USE_C89 */ - - -/* -** By default, Lua on Windows use (some) specific Windows features -*/ -#if !defined(LUA_USE_C89) && defined(_WIN32) && !defined(_WIN32_WCE) -#define LUA_USE_WINDOWS /* enable goodies for regular Windows */ -#endif - - -#if defined(LUA_USE_WINDOWS) -#define LUA_DL_DLL /* enable support for DLL */ -#define LUA_USE_C89 /* broadly, Windows is C89 */ -#endif - - -#if defined(LUA_USE_LINUX) -#define LUA_USE_POSIX -#define LUA_USE_DLOPEN /* needs an extra library: -ldl */ -#endif - - -#if defined(LUA_USE_MACOSX) -#define LUA_USE_POSIX -#define LUA_USE_DLOPEN /* MacOS does not need -ldl */ -#endif - - -#if defined(LUA_USE_IOS) -#define LUA_USE_POSIX -#define LUA_USE_DLOPEN -#endif - - -/* -@@ LUAI_IS32INT is true iff 'int' has (at least) 32 bits. -*/ -#define LUAI_IS32INT ((UINT_MAX >> 30) >= 3) - -/* }================================================================== */ - - - -/* -** {================================================================== -** Configuration for Number types. These options should not be -** set externally, because any other code connected to Lua must -** use the same configuration. -** =================================================================== -*/ - -/* -@@ LUA_INT_TYPE defines the type for Lua integers. -@@ LUA_FLOAT_TYPE defines the type for Lua floats. -** Lua should work fine with any mix of these options supported -** by your C compiler. The usual configurations are 64-bit integers -** and 'double' (the default), 32-bit integers and 'float' (for -** restricted platforms), and 'long'/'double' (for C compilers not -** compliant with C99, which may not have support for 'long long'). -*/ - -/* predefined options for LUA_INT_TYPE */ -#define LUA_INT_INT 1 -#define LUA_INT_LONG 2 -#define LUA_INT_LONGLONG 3 - -/* predefined options for LUA_FLOAT_TYPE */ -#define LUA_FLOAT_FLOAT 1 -#define LUA_FLOAT_DOUBLE 2 -#define LUA_FLOAT_LONGDOUBLE 3 - - -/* Default configuration ('long long' and 'double', for 64-bit Lua) */ -#define LUA_INT_DEFAULT LUA_INT_LONGLONG -#define LUA_FLOAT_DEFAULT LUA_FLOAT_DOUBLE - - -/* -@@ LUA_32BITS enables Lua with 32-bit integers and 32-bit floats. -*/ -#define LUA_32BITS 0 - - -/* -@@ LUA_C89_NUMBERS ensures that Lua uses the largest types available for -** C89 ('long' and 'double'); Windows always has '__int64', so it does -** not need to use this case. -*/ -#if defined(LUA_USE_C89) && !defined(LUA_USE_WINDOWS) -#define LUA_C89_NUMBERS 1 -#else -#define LUA_C89_NUMBERS 0 -#endif - - -#if LUA_32BITS /* { */ -/* -** 32-bit integers and 'float' -*/ -#if LUAI_IS32INT /* use 'int' if big enough */ -#define LUA_INT_TYPE LUA_INT_INT -#else /* otherwise use 'long' */ -#define LUA_INT_TYPE LUA_INT_LONG -#endif -#define LUA_FLOAT_TYPE LUA_FLOAT_FLOAT - -#elif LUA_C89_NUMBERS /* }{ */ -/* -** largest types available for C89 ('long' and 'double') -*/ -#define LUA_INT_TYPE LUA_INT_LONG -#define LUA_FLOAT_TYPE LUA_FLOAT_DOUBLE - -#else /* }{ */ -/* use defaults */ - -#define LUA_INT_TYPE LUA_INT_DEFAULT -#define LUA_FLOAT_TYPE LUA_FLOAT_DEFAULT - -#endif /* } */ - - -/* }================================================================== */ - - - -/* -** {================================================================== -** Configuration for Paths. -** =================================================================== -*/ - -/* -** LUA_PATH_SEP is the character that separates templates in a path. -** LUA_PATH_MARK is the string that marks the substitution points in a -** template. -** LUA_EXEC_DIR in a Windows path is replaced by the executable's -** directory. -*/ -#define LUA_PATH_SEP ";" -#define LUA_PATH_MARK "?" -#define LUA_EXEC_DIR "!" - - -/* -@@ LUA_PATH_DEFAULT is the default path that Lua uses to look for -** Lua libraries. -@@ LUA_CPATH_DEFAULT is the default path that Lua uses to look for -** C libraries. -** CHANGE them if your machine has a non-conventional directory -** hierarchy or if you want to install your libraries in -** non-conventional directories. -*/ - -#define LUA_VDIR LUA_VERSION_MAJOR "." LUA_VERSION_MINOR -#if defined(_WIN32) /* { */ -/* -** In Windows, any exclamation mark ('!') in the path is replaced by the -** path of the directory of the executable file of the current process. -*/ -#define LUA_LDIR "!\\lua\\" -#define LUA_CDIR "!\\" -#define LUA_SHRDIR "!\\..\\share\\lua\\" LUA_VDIR "\\" - -#if !defined(LUA_PATH_DEFAULT) -#define LUA_PATH_DEFAULT \ - LUA_LDIR"?.lua;" LUA_LDIR"?\\init.lua;" \ - LUA_CDIR"?.lua;" LUA_CDIR"?\\init.lua;" \ - LUA_SHRDIR"?.lua;" LUA_SHRDIR"?\\init.lua;" \ - ".\\?.lua;" ".\\?\\init.lua" -#endif - -#if !defined(LUA_CPATH_DEFAULT) -#define LUA_CPATH_DEFAULT \ - LUA_CDIR"?.dll;" \ - LUA_CDIR"..\\lib\\lua\\" LUA_VDIR "\\?.dll;" \ - LUA_CDIR"loadall.dll;" ".\\?.dll" -#endif - -#else /* }{ */ - -#define LUA_ROOT "/usr/local/" -#define LUA_LDIR LUA_ROOT "share/lua/" LUA_VDIR "/" -#define LUA_CDIR LUA_ROOT "lib/lua/" LUA_VDIR "/" - -#if !defined(LUA_PATH_DEFAULT) -#define LUA_PATH_DEFAULT \ - LUA_LDIR"?.lua;" LUA_LDIR"?/init.lua;" \ - LUA_CDIR"?.lua;" LUA_CDIR"?/init.lua;" \ - "./?.lua;" "./?/init.lua" -#endif - -#if !defined(LUA_CPATH_DEFAULT) -#define LUA_CPATH_DEFAULT \ - LUA_CDIR"?.so;" LUA_CDIR"loadall.so;" "./?.so" -#endif - -#endif /* } */ - - -/* -@@ LUA_DIRSEP is the directory separator (for submodules). -** CHANGE it if your machine does not use "/" as the directory separator -** and is not Windows. (On Windows Lua automatically uses "\".) -*/ -#if !defined(LUA_DIRSEP) - -#if defined(_WIN32) -#define LUA_DIRSEP "\\" -#else -#define LUA_DIRSEP "/" -#endif - -#endif - -/* }================================================================== */ - - -/* -** {================================================================== -** Marks for exported symbols in the C code -** =================================================================== -*/ - -/* -@@ LUA_API is a mark for all core API functions. -@@ LUALIB_API is a mark for all auxiliary library functions. -@@ LUAMOD_API is a mark for all standard library opening functions. -** CHANGE them if you need to define those functions in some special way. -** For instance, if you want to create one Windows DLL with the core and -** the libraries, you may want to use the following definition (define -** LUA_BUILD_AS_DLL to get it). -*/ -#if defined(LUA_BUILD_AS_DLL) /* { */ - -#if defined(LUA_CORE) || defined(LUA_LIB) /* { */ -#define LUA_API __declspec(dllexport) -#else /* }{ */ -#define LUA_API __declspec(dllimport) -#endif /* } */ - -#else /* }{ */ - -#define LUA_API extern - -#endif /* } */ - - -/* -** More often than not the libs go together with the core. -*/ -#define LUALIB_API LUA_API -#define LUAMOD_API LUA_API - - -/* -@@ LUAI_FUNC is a mark for all extern functions that are not to be -** exported to outside modules. -@@ LUAI_DDEF and LUAI_DDEC are marks for all extern (const) variables, -** none of which to be exported to outside modules (LUAI_DDEF for -** definitions and LUAI_DDEC for declarations). -** CHANGE them if you need to mark them in some special way. Elf/gcc -** (versions 3.2 and later) mark them as "hidden" to optimize access -** when Lua is compiled as a shared library. Not all elf targets support -** this attribute. Unfortunately, gcc does not offer a way to check -** whether the target offers that support, and those without support -** give a warning about it. To avoid these warnings, change to the -** default definition. -*/ -#if defined(__GNUC__) && ((__GNUC__*100 + __GNUC_MINOR__) >= 302) && \ - defined(__ELF__) /* { */ -#define LUAI_FUNC __attribute__((visibility("internal"))) extern -#else /* }{ */ -#define LUAI_FUNC extern -#endif /* } */ - -#define LUAI_DDEC(dec) LUAI_FUNC dec -#define LUAI_DDEF /* empty */ - -/* }================================================================== */ - - -/* -** {================================================================== -** Compatibility with previous versions -** =================================================================== -*/ - -/* -@@ LUA_COMPAT_5_3 controls other macros for compatibility with Lua 5.3. -** You can define it to get all options, or change specific options -** to fit your specific needs. -*/ -#if defined(LUA_COMPAT_5_3) /* { */ - -/* -@@ LUA_COMPAT_MATHLIB controls the presence of several deprecated -** functions in the mathematical library. -** (These functions were already officially removed in 5.3; -** nevertheless they are still available here.) -*/ -#define LUA_COMPAT_MATHLIB - -/* -@@ LUA_COMPAT_APIINTCASTS controls the presence of macros for -** manipulating other integer types (lua_pushunsigned, lua_tounsigned, -** luaL_checkint, luaL_checklong, etc.) -** (These macros were also officially removed in 5.3, but they are still -** available here.) -*/ -#define LUA_COMPAT_APIINTCASTS - - -/* -@@ LUA_COMPAT_LT_LE controls the emulation of the '__le' metamethod -** using '__lt'. -*/ -#define LUA_COMPAT_LT_LE - - -/* -@@ The following macros supply trivial compatibility for some -** changes in the API. The macros themselves document how to -** change your code to avoid using them. -** (Once more, these macros were officially removed in 5.3, but they are -** still available here.) -*/ -#define lua_strlen(L,i) lua_rawlen(L, (i)) - -#define lua_objlen(L,i) lua_rawlen(L, (i)) - -#define lua_equal(L,idx1,idx2) lua_compare(L,(idx1),(idx2),LUA_OPEQ) -#define lua_lessthan(L,idx1,idx2) lua_compare(L,(idx1),(idx2),LUA_OPLT) - -#endif /* } */ - -/* }================================================================== */ - - - -/* -** {================================================================== -** Configuration for Numbers (low-level part). -** Change these definitions if no predefined LUA_FLOAT_* / LUA_INT_* -** satisfy your needs. -** =================================================================== -*/ - -/* -@@ LUAI_UACNUMBER is the result of a 'default argument promotion' -@@ over a floating number. -@@ l_floatatt(x) corrects float attribute 'x' to the proper float type -** by prefixing it with one of FLT/DBL/LDBL. -@@ LUA_NUMBER_FRMLEN is the length modifier for writing floats. -@@ LUA_NUMBER_FMT is the format for writing floats. -@@ lua_number2str converts a float to a string. -@@ l_mathop allows the addition of an 'l' or 'f' to all math operations. -@@ l_floor takes the floor of a float. -@@ lua_str2number converts a decimal numeral to a number. -*/ - - -/* The following definitions are good for most cases here */ - -#define l_floor(x) (l_mathop(floor)(x)) - -#define lua_number2str(s,sz,n) \ - l_sprintf((s), sz, LUA_NUMBER_FMT, (LUAI_UACNUMBER)(n)) - -/* -@@ lua_numbertointeger converts a float number with an integral value -** to an integer, or returns 0 if float is not within the range of -** a lua_Integer. (The range comparisons are tricky because of -** rounding. The tests here assume a two-complement representation, -** where MININTEGER always has an exact representation as a float; -** MAXINTEGER may not have one, and therefore its conversion to float -** may have an ill-defined value.) -*/ -#define lua_numbertointeger(n,p) \ - ((n) >= (LUA_NUMBER)(LUA_MININTEGER) && \ - (n) < -(LUA_NUMBER)(LUA_MININTEGER) && \ - (*(p) = (LUA_INTEGER)(n), 1)) - - -/* now the variable definitions */ - -#if LUA_FLOAT_TYPE == LUA_FLOAT_FLOAT /* { single float */ - -#define LUA_NUMBER float - -#define l_floatatt(n) (FLT_##n) - -#define LUAI_UACNUMBER double - -#define LUA_NUMBER_FRMLEN "" -#define LUA_NUMBER_FMT "%.7g" - -#define l_mathop(op) op##f - -#define lua_str2number(s,p) strtof((s), (p)) - - -#elif LUA_FLOAT_TYPE == LUA_FLOAT_LONGDOUBLE /* }{ long double */ - -#define LUA_NUMBER long double - -#define l_floatatt(n) (LDBL_##n) - -#define LUAI_UACNUMBER long double - -#define LUA_NUMBER_FRMLEN "L" -#define LUA_NUMBER_FMT "%.19Lg" - -#define l_mathop(op) op##l - -#define lua_str2number(s,p) strtold((s), (p)) - -#elif LUA_FLOAT_TYPE == LUA_FLOAT_DOUBLE /* }{ double */ - -#define LUA_NUMBER double - -#define l_floatatt(n) (DBL_##n) - -#define LUAI_UACNUMBER double - -#define LUA_NUMBER_FRMLEN "" -#define LUA_NUMBER_FMT "%.14g" - -#define l_mathop(op) op - -#define lua_str2number(s,p) strtod((s), (p)) - -#else /* }{ */ - -#error "numeric float type not defined" - -#endif /* } */ - - - -/* -@@ LUA_UNSIGNED is the unsigned version of LUA_INTEGER. -@@ LUAI_UACINT is the result of a 'default argument promotion' -@@ over a LUA_INTEGER. -@@ LUA_INTEGER_FRMLEN is the length modifier for reading/writing integers. -@@ LUA_INTEGER_FMT is the format for writing integers. -@@ LUA_MAXINTEGER is the maximum value for a LUA_INTEGER. -@@ LUA_MININTEGER is the minimum value for a LUA_INTEGER. -@@ LUA_MAXUNSIGNED is the maximum value for a LUA_UNSIGNED. -@@ lua_integer2str converts an integer to a string. -*/ - - -/* The following definitions are good for most cases here */ - -#define LUA_INTEGER_FMT "%" LUA_INTEGER_FRMLEN "d" - -#define LUAI_UACINT LUA_INTEGER - -#define lua_integer2str(s,sz,n) \ - l_sprintf((s), sz, LUA_INTEGER_FMT, (LUAI_UACINT)(n)) - -/* -** use LUAI_UACINT here to avoid problems with promotions (which -** can turn a comparison between unsigneds into a signed comparison) -*/ -#define LUA_UNSIGNED unsigned LUAI_UACINT - - -/* now the variable definitions */ - -#if LUA_INT_TYPE == LUA_INT_INT /* { int */ - -#define LUA_INTEGER int -#define LUA_INTEGER_FRMLEN "" - -#define LUA_MAXINTEGER INT_MAX -#define LUA_MININTEGER INT_MIN - -#define LUA_MAXUNSIGNED UINT_MAX - -#elif LUA_INT_TYPE == LUA_INT_LONG /* }{ long */ - -#define LUA_INTEGER long -#define LUA_INTEGER_FRMLEN "l" - -#define LUA_MAXINTEGER LONG_MAX -#define LUA_MININTEGER LONG_MIN - -#define LUA_MAXUNSIGNED ULONG_MAX - -#elif LUA_INT_TYPE == LUA_INT_LONGLONG /* }{ long long */ - -/* use presence of macro LLONG_MAX as proxy for C99 compliance */ -#if defined(LLONG_MAX) /* { */ -/* use ISO C99 stuff */ - -#define LUA_INTEGER long long -#define LUA_INTEGER_FRMLEN "ll" - -#define LUA_MAXINTEGER LLONG_MAX -#define LUA_MININTEGER LLONG_MIN - -#define LUA_MAXUNSIGNED ULLONG_MAX - -#elif defined(LUA_USE_WINDOWS) /* }{ */ -/* in Windows, can use specific Windows types */ - -#define LUA_INTEGER __int64 -#define LUA_INTEGER_FRMLEN "I64" - -#define LUA_MAXINTEGER _I64_MAX -#define LUA_MININTEGER _I64_MIN - -#define LUA_MAXUNSIGNED _UI64_MAX - -#else /* }{ */ - -#error "Compiler does not support 'long long'. Use option '-DLUA_32BITS' \ - or '-DLUA_C89_NUMBERS' (see file 'luaconf.h' for details)" - -#endif /* } */ - -#else /* }{ */ - -#error "numeric integer type not defined" - -#endif /* } */ - -/* }================================================================== */ - - -/* -** {================================================================== -** Dependencies with C99 and other C details -** =================================================================== -*/ - -/* -@@ l_sprintf is equivalent to 'snprintf' or 'sprintf' in C89. -** (All uses in Lua have only one format item.) -*/ -#if !defined(LUA_USE_C89) -#define l_sprintf(s,sz,f,i) snprintf(s,sz,f,i) -#else -#define l_sprintf(s,sz,f,i) ((void)(sz), sprintf(s,f,i)) -#endif - - -/* -@@ lua_strx2number converts a hexadecimal numeral to a number. -** In C99, 'strtod' does that conversion. Otherwise, you can -** leave 'lua_strx2number' undefined and Lua will provide its own -** implementation. -*/ -#if !defined(LUA_USE_C89) -#define lua_strx2number(s,p) lua_str2number(s,p) -#endif - - -/* -@@ lua_pointer2str converts a pointer to a readable string in a -** non-specified way. -*/ -#define lua_pointer2str(buff,sz,p) l_sprintf(buff,sz,"%p",p) - - -/* -@@ lua_number2strx converts a float to a hexadecimal numeral. -** In C99, 'sprintf' (with format specifiers '%a'/'%A') does that. -** Otherwise, you can leave 'lua_number2strx' undefined and Lua will -** provide its own implementation. -*/ -#if !defined(LUA_USE_C89) -#define lua_number2strx(L,b,sz,f,n) \ - ((void)L, l_sprintf(b,sz,f,(LUAI_UACNUMBER)(n))) -#endif - - -/* -** 'strtof' and 'opf' variants for math functions are not valid in -** C89. Otherwise, the macro 'HUGE_VALF' is a good proxy for testing the -** availability of these variants. ('math.h' is already included in -** all files that use these macros.) -*/ -#if defined(LUA_USE_C89) || (defined(HUGE_VAL) && !defined(HUGE_VALF)) -#undef l_mathop /* variants not available */ -#undef lua_str2number -#define l_mathop(op) (lua_Number)op /* no variant */ -#define lua_str2number(s,p) ((lua_Number)strtod((s), (p))) -#endif - - -/* -@@ LUA_KCONTEXT is the type of the context ('ctx') for continuation -** functions. It must be a numerical type; Lua will use 'intptr_t' if -** available, otherwise it will use 'ptrdiff_t' (the nearest thing to -** 'intptr_t' in C89) -*/ -#define LUA_KCONTEXT ptrdiff_t - -#if !defined(LUA_USE_C89) && defined(__STDC_VERSION__) && \ - __STDC_VERSION__ >= 199901L -#include -#if defined(INTPTR_MAX) /* even in C99 this type is optional */ -#undef LUA_KCONTEXT -#define LUA_KCONTEXT intptr_t -#endif -#endif - - -/* -@@ lua_getlocaledecpoint gets the locale "radix character" (decimal point). -** Change that if you do not want to use C locales. (Code using this -** macro must include the header 'locale.h'.) -*/ -#if !defined(lua_getlocaledecpoint) -#define lua_getlocaledecpoint() (localeconv()->decimal_point[0]) -#endif - - -/* -** macros to improve jump prediction, used mostly for error handling -** and debug facilities. (Some macros in the Lua API use these macros. -** Define LUA_NOBUILTIN if you do not want '__builtin_expect' in your -** code.) -*/ -#if !defined(luai_likely) - -#if defined(__GNUC__) && !defined(LUA_NOBUILTIN) -#define luai_likely(x) (__builtin_expect(((x) != 0), 1)) -#define luai_unlikely(x) (__builtin_expect(((x) != 0), 0)) -#else -#define luai_likely(x) (x) -#define luai_unlikely(x) (x) -#endif - -#endif - - -#if defined(LUA_CORE) || defined(LUA_LIB) -/* shorter names for Lua's own use */ -#define l_likely(x) luai_likely(x) -#define l_unlikely(x) luai_unlikely(x) -#endif - - - -/* }================================================================== */ - - -/* -** {================================================================== -** Language Variations -** ===================================================================== -*/ - -/* -@@ LUA_NOCVTN2S/LUA_NOCVTS2N control how Lua performs some -** coercions. Define LUA_NOCVTN2S to turn off automatic coercion from -** numbers to strings. Define LUA_NOCVTS2N to turn off automatic -** coercion from strings to numbers. -*/ -/* #define LUA_NOCVTN2S */ -/* #define LUA_NOCVTS2N */ - - -/* -@@ LUA_USE_APICHECK turns on several consistency checks on the C API. -** Define it as a help when debugging C code. -*/ -#if defined(LUA_USE_APICHECK) -#include -#define luai_apicheck(l,e) assert(e) -#endif - -/* }================================================================== */ - - -/* -** {================================================================== -** Macros that affect the API and must be stable (that is, must be the -** same when you compile Lua and when you compile code that links to -** Lua). -** ===================================================================== -*/ - -/* -@@ LUAI_MAXSTACK limits the size of the Lua stack. -** CHANGE it if you need a different limit. This limit is arbitrary; -** its only purpose is to stop Lua from consuming unlimited stack -** space (and to reserve some numbers for pseudo-indices). -** (It must fit into max(size_t)/32 and max(int)/2.) -*/ -#if LUAI_IS32INT -#define LUAI_MAXSTACK 1000000 -#else -#define LUAI_MAXSTACK 15000 -#endif - - -/* -@@ LUA_EXTRASPACE defines the size of a raw memory area associated with -** a Lua state with very fast access. -** CHANGE it if you need a different size. -*/ -#define LUA_EXTRASPACE (sizeof(void *)) - - -/* -@@ LUA_IDSIZE gives the maximum size for the description of the source -** of a function in debug information. -** CHANGE it if you want a different size. -*/ -#define LUA_IDSIZE 60 - - -/* -@@ LUAL_BUFFERSIZE is the initial buffer size used by the lauxlib -** buffer system. -*/ -#define LUAL_BUFFERSIZE ((int)(16 * sizeof(void*) * sizeof(lua_Number))) - - -/* -@@ LUAI_MAXALIGN defines fields that, when used in a union, ensure -** maximum alignment for the other items in that union. -*/ -#define LUAI_MAXALIGN lua_Number n; double u; void *s; lua_Integer i; long l - -/* }================================================================== */ - - - - - -/* =================================================================== */ - -/* -** Local configuration. You can use this space to add your redefinitions -** without modifying the main part of the file. -*/ - - - - - -#endif - diff --git a/lib/lua-5.4/src/lualib.h b/lib/lua-5.4/src/lualib.h deleted file mode 100644 index 2625529..0000000 --- a/lib/lua-5.4/src/lualib.h +++ /dev/null @@ -1,52 +0,0 @@ -/* -** $Id: lualib.h $ -** Lua standard libraries -** See Copyright Notice in lua.h -*/ - - -#ifndef lualib_h -#define lualib_h - -#include "lua.h" - - -/* version suffix for environment variable names */ -#define LUA_VERSUFFIX "_" LUA_VERSION_MAJOR "_" LUA_VERSION_MINOR - - -LUAMOD_API int (luaopen_base) (lua_State *L); - -#define LUA_COLIBNAME "coroutine" -LUAMOD_API int (luaopen_coroutine) (lua_State *L); - -#define LUA_TABLIBNAME "table" -LUAMOD_API int (luaopen_table) (lua_State *L); - -#define LUA_IOLIBNAME "io" -LUAMOD_API int (luaopen_io) (lua_State *L); - -#define LUA_OSLIBNAME "os" -LUAMOD_API int (luaopen_os) (lua_State *L); - -#define LUA_STRLIBNAME "string" -LUAMOD_API int (luaopen_string) (lua_State *L); - -#define LUA_UTF8LIBNAME "utf8" -LUAMOD_API int (luaopen_utf8) (lua_State *L); - -#define LUA_MATHLIBNAME "math" -LUAMOD_API int (luaopen_math) (lua_State *L); - -#define LUA_DBLIBNAME "debug" -LUAMOD_API int (luaopen_debug) (lua_State *L); - -#define LUA_LOADLIBNAME "package" -LUAMOD_API int (luaopen_package) (lua_State *L); - - -/* open all previous libraries */ -LUALIB_API void (luaL_openlibs) (lua_State *L); - - -#endif diff --git a/lib/lua-5.4/src/lundump.c b/lib/lua-5.4/src/lundump.c deleted file mode 100644 index 02aed64..0000000 --- a/lib/lua-5.4/src/lundump.c +++ /dev/null @@ -1,335 +0,0 @@ -/* -** $Id: lundump.c $ -** load precompiled Lua chunks -** See Copyright Notice in lua.h -*/ - -#define lundump_c -#define LUA_CORE - -#include "lprefix.h" - - -#include -#include - -#include "lua.h" - -#include "ldebug.h" -#include "ldo.h" -#include "lfunc.h" -#include "lmem.h" -#include "lobject.h" -#include "lstring.h" -#include "lundump.h" -#include "lzio.h" - - -#if !defined(luai_verifycode) -#define luai_verifycode(L,f) /* empty */ -#endif - - -typedef struct { - lua_State *L; - ZIO *Z; - const char *name; -} LoadState; - - -static l_noret error (LoadState *S, const char *why) { - luaO_pushfstring(S->L, "%s: bad binary format (%s)", S->name, why); - luaD_throw(S->L, LUA_ERRSYNTAX); -} - - -/* -** All high-level loads go through loadVector; you can change it to -** adapt to the endianness of the input -*/ -#define loadVector(S,b,n) loadBlock(S,b,(n)*sizeof((b)[0])) - -static void loadBlock (LoadState *S, void *b, size_t size) { - if (luaZ_read(S->Z, b, size) != 0) - error(S, "truncated chunk"); -} - - -#define loadVar(S,x) loadVector(S,&x,1) - - -static lu_byte loadByte (LoadState *S) { - int b = zgetc(S->Z); - if (b == EOZ) - error(S, "truncated chunk"); - return cast_byte(b); -} - - -static size_t loadUnsigned (LoadState *S, size_t limit) { - size_t x = 0; - int b; - limit >>= 7; - do { - b = loadByte(S); - if (x >= limit) - error(S, "integer overflow"); - x = (x << 7) | (b & 0x7f); - } while ((b & 0x80) == 0); - return x; -} - - -static size_t loadSize (LoadState *S) { - return loadUnsigned(S, ~(size_t)0); -} - - -static int loadInt (LoadState *S) { - return cast_int(loadUnsigned(S, INT_MAX)); -} - - -static lua_Number loadNumber (LoadState *S) { - lua_Number x; - loadVar(S, x); - return x; -} - - -static lua_Integer loadInteger (LoadState *S) { - lua_Integer x; - loadVar(S, x); - return x; -} - - -/* -** Load a nullable string into prototype 'p'. -*/ -static TString *loadStringN (LoadState *S, Proto *p) { - lua_State *L = S->L; - TString *ts; - size_t size = loadSize(S); - if (size == 0) /* no string? */ - return NULL; - else if (--size <= LUAI_MAXSHORTLEN) { /* short string? */ - char buff[LUAI_MAXSHORTLEN]; - loadVector(S, buff, size); /* load string into buffer */ - ts = luaS_newlstr(L, buff, size); /* create string */ - } - else { /* long string */ - ts = luaS_createlngstrobj(L, size); /* create string */ - setsvalue2s(L, L->top.p, ts); /* anchor it ('loadVector' can GC) */ - luaD_inctop(L); - loadVector(S, getstr(ts), size); /* load directly in final place */ - L->top.p--; /* pop string */ - } - luaC_objbarrier(L, p, ts); - return ts; -} - - -/* -** Load a non-nullable string into prototype 'p'. -*/ -static TString *loadString (LoadState *S, Proto *p) { - TString *st = loadStringN(S, p); - if (st == NULL) - error(S, "bad format for constant string"); - return st; -} - - -static void loadCode (LoadState *S, Proto *f) { - int n = loadInt(S); - f->code = luaM_newvectorchecked(S->L, n, Instruction); - f->sizecode = n; - loadVector(S, f->code, n); -} - - -static void loadFunction(LoadState *S, Proto *f, TString *psource); - - -static void loadConstants (LoadState *S, Proto *f) { - int i; - int n = loadInt(S); - f->k = luaM_newvectorchecked(S->L, n, TValue); - f->sizek = n; - for (i = 0; i < n; i++) - setnilvalue(&f->k[i]); - for (i = 0; i < n; i++) { - TValue *o = &f->k[i]; - int t = loadByte(S); - switch (t) { - case LUA_VNIL: - setnilvalue(o); - break; - case LUA_VFALSE: - setbfvalue(o); - break; - case LUA_VTRUE: - setbtvalue(o); - break; - case LUA_VNUMFLT: - setfltvalue(o, loadNumber(S)); - break; - case LUA_VNUMINT: - setivalue(o, loadInteger(S)); - break; - case LUA_VSHRSTR: - case LUA_VLNGSTR: - setsvalue2n(S->L, o, loadString(S, f)); - break; - default: lua_assert(0); - } - } -} - - -static void loadProtos (LoadState *S, Proto *f) { - int i; - int n = loadInt(S); - f->p = luaM_newvectorchecked(S->L, n, Proto *); - f->sizep = n; - for (i = 0; i < n; i++) - f->p[i] = NULL; - for (i = 0; i < n; i++) { - f->p[i] = luaF_newproto(S->L); - luaC_objbarrier(S->L, f, f->p[i]); - loadFunction(S, f->p[i], f->source); - } -} - - -/* -** Load the upvalues for a function. The names must be filled first, -** because the filling of the other fields can raise read errors and -** the creation of the error message can call an emergency collection; -** in that case all prototypes must be consistent for the GC. -*/ -static void loadUpvalues (LoadState *S, Proto *f) { - int i, n; - n = loadInt(S); - f->upvalues = luaM_newvectorchecked(S->L, n, Upvaldesc); - f->sizeupvalues = n; - for (i = 0; i < n; i++) /* make array valid for GC */ - f->upvalues[i].name = NULL; - for (i = 0; i < n; i++) { /* following calls can raise errors */ - f->upvalues[i].instack = loadByte(S); - f->upvalues[i].idx = loadByte(S); - f->upvalues[i].kind = loadByte(S); - } -} - - -static void loadDebug (LoadState *S, Proto *f) { - int i, n; - n = loadInt(S); - f->lineinfo = luaM_newvectorchecked(S->L, n, ls_byte); - f->sizelineinfo = n; - loadVector(S, f->lineinfo, n); - n = loadInt(S); - f->abslineinfo = luaM_newvectorchecked(S->L, n, AbsLineInfo); - f->sizeabslineinfo = n; - for (i = 0; i < n; i++) { - f->abslineinfo[i].pc = loadInt(S); - f->abslineinfo[i].line = loadInt(S); - } - n = loadInt(S); - f->locvars = luaM_newvectorchecked(S->L, n, LocVar); - f->sizelocvars = n; - for (i = 0; i < n; i++) - f->locvars[i].varname = NULL; - for (i = 0; i < n; i++) { - f->locvars[i].varname = loadStringN(S, f); - f->locvars[i].startpc = loadInt(S); - f->locvars[i].endpc = loadInt(S); - } - n = loadInt(S); - if (n != 0) /* does it have debug information? */ - n = f->sizeupvalues; /* must be this many */ - for (i = 0; i < n; i++) - f->upvalues[i].name = loadStringN(S, f); -} - - -static void loadFunction (LoadState *S, Proto *f, TString *psource) { - f->source = loadStringN(S, f); - if (f->source == NULL) /* no source in dump? */ - f->source = psource; /* reuse parent's source */ - f->linedefined = loadInt(S); - f->lastlinedefined = loadInt(S); - f->numparams = loadByte(S); - f->is_vararg = loadByte(S); - f->maxstacksize = loadByte(S); - loadCode(S, f); - loadConstants(S, f); - loadUpvalues(S, f); - loadProtos(S, f); - loadDebug(S, f); -} - - -static void checkliteral (LoadState *S, const char *s, const char *msg) { - char buff[sizeof(LUA_SIGNATURE) + sizeof(LUAC_DATA)]; /* larger than both */ - size_t len = strlen(s); - loadVector(S, buff, len); - if (memcmp(s, buff, len) != 0) - error(S, msg); -} - - -static void fchecksize (LoadState *S, size_t size, const char *tname) { - if (loadByte(S) != size) - error(S, luaO_pushfstring(S->L, "%s size mismatch", tname)); -} - - -#define checksize(S,t) fchecksize(S,sizeof(t),#t) - -static void checkHeader (LoadState *S) { - /* skip 1st char (already read and checked) */ - checkliteral(S, &LUA_SIGNATURE[1], "not a binary chunk"); - if (loadByte(S) != LUAC_VERSION) - error(S, "version mismatch"); - if (loadByte(S) != LUAC_FORMAT) - error(S, "format mismatch"); - checkliteral(S, LUAC_DATA, "corrupted chunk"); - checksize(S, Instruction); - checksize(S, lua_Integer); - checksize(S, lua_Number); - if (loadInteger(S) != LUAC_INT) - error(S, "integer format mismatch"); - if (loadNumber(S) != LUAC_NUM) - error(S, "float format mismatch"); -} - - -/* -** Load precompiled chunk. -*/ -LClosure *luaU_undump(lua_State *L, ZIO *Z, const char *name) { - LoadState S; - LClosure *cl; - if (*name == '@' || *name == '=') - S.name = name + 1; - else if (*name == LUA_SIGNATURE[0]) - S.name = "binary string"; - else - S.name = name; - S.L = L; - S.Z = Z; - checkHeader(&S); - cl = luaF_newLclosure(L, loadByte(&S)); - setclLvalue2s(L, L->top.p, cl); - luaD_inctop(L); - cl->p = luaF_newproto(L); - luaC_objbarrier(L, cl, cl->p); - loadFunction(&S, cl->p, NULL); - lua_assert(cl->nupvalues == cl->p->sizeupvalues); - luai_verifycode(L, cl->p); - return cl; -} - diff --git a/lib/lua-5.4/src/lundump.h b/lib/lua-5.4/src/lundump.h deleted file mode 100644 index f3748a9..0000000 --- a/lib/lua-5.4/src/lundump.h +++ /dev/null @@ -1,36 +0,0 @@ -/* -** $Id: lundump.h $ -** load precompiled Lua chunks -** See Copyright Notice in lua.h -*/ - -#ifndef lundump_h -#define lundump_h - -#include "llimits.h" -#include "lobject.h" -#include "lzio.h" - - -/* data to catch conversion errors */ -#define LUAC_DATA "\x19\x93\r\n\x1a\n" - -#define LUAC_INT 0x5678 -#define LUAC_NUM cast_num(370.5) - -/* -** Encode major-minor version in one byte, one nibble for each -*/ -#define MYINT(s) (s[0]-'0') /* assume one-digit numerals */ -#define LUAC_VERSION (MYINT(LUA_VERSION_MAJOR)*16+MYINT(LUA_VERSION_MINOR)) - -#define LUAC_FORMAT 0 /* this is the official format */ - -/* load one chunk; from lundump.c */ -LUAI_FUNC LClosure* luaU_undump (lua_State* L, ZIO* Z, const char* name); - -/* dump one chunk; from ldump.c */ -LUAI_FUNC int luaU_dump (lua_State* L, const Proto* f, lua_Writer w, - void* data, int strip); - -#endif diff --git a/lib/lua-5.4/src/lutf8lib.c b/lib/lua-5.4/src/lutf8lib.c deleted file mode 100644 index 3a5b9bc..0000000 --- a/lib/lua-5.4/src/lutf8lib.c +++ /dev/null @@ -1,291 +0,0 @@ -/* -** $Id: lutf8lib.c $ -** Standard library for UTF-8 manipulation -** See Copyright Notice in lua.h -*/ - -#define lutf8lib_c -#define LUA_LIB - -#include "lprefix.h" - - -#include -#include -#include -#include - -#include "lua.h" - -#include "lauxlib.h" -#include "lualib.h" - - -#define MAXUNICODE 0x10FFFFu - -#define MAXUTF 0x7FFFFFFFu - - -#define MSGInvalid "invalid UTF-8 code" - -/* -** Integer type for decoded UTF-8 values; MAXUTF needs 31 bits. -*/ -#if (UINT_MAX >> 30) >= 1 -typedef unsigned int utfint; -#else -typedef unsigned long utfint; -#endif - - -#define iscont(c) (((c) & 0xC0) == 0x80) -#define iscontp(p) iscont(*(p)) - - -/* from strlib */ -/* translate a relative string position: negative means back from end */ -static lua_Integer u_posrelat (lua_Integer pos, size_t len) { - if (pos >= 0) return pos; - else if (0u - (size_t)pos > len) return 0; - else return (lua_Integer)len + pos + 1; -} - - -/* -** Decode one UTF-8 sequence, returning NULL if byte sequence is -** invalid. The array 'limits' stores the minimum value for each -** sequence length, to check for overlong representations. Its first -** entry forces an error for non-ascii bytes with no continuation -** bytes (count == 0). -*/ -static const char *utf8_decode (const char *s, utfint *val, int strict) { - static const utfint limits[] = - {~(utfint)0, 0x80, 0x800, 0x10000u, 0x200000u, 0x4000000u}; - unsigned int c = (unsigned char)s[0]; - utfint res = 0; /* final result */ - if (c < 0x80) /* ascii? */ - res = c; - else { - int count = 0; /* to count number of continuation bytes */ - for (; c & 0x40; c <<= 1) { /* while it needs continuation bytes... */ - unsigned int cc = (unsigned char)s[++count]; /* read next byte */ - if (!iscont(cc)) /* not a continuation byte? */ - return NULL; /* invalid byte sequence */ - res = (res << 6) | (cc & 0x3F); /* add lower 6 bits from cont. byte */ - } - res |= ((utfint)(c & 0x7F) << (count * 5)); /* add first byte */ - if (count > 5 || res > MAXUTF || res < limits[count]) - return NULL; /* invalid byte sequence */ - s += count; /* skip continuation bytes read */ - } - if (strict) { - /* check for invalid code points; too large or surrogates */ - if (res > MAXUNICODE || (0xD800u <= res && res <= 0xDFFFu)) - return NULL; - } - if (val) *val = res; - return s + 1; /* +1 to include first byte */ -} - - -/* -** utf8len(s [, i [, j [, lax]]]) --> number of characters that -** start in the range [i,j], or nil + current position if 's' is not -** well formed in that interval -*/ -static int utflen (lua_State *L) { - lua_Integer n = 0; /* counter for the number of characters */ - size_t len; /* string length in bytes */ - const char *s = luaL_checklstring(L, 1, &len); - lua_Integer posi = u_posrelat(luaL_optinteger(L, 2, 1), len); - lua_Integer posj = u_posrelat(luaL_optinteger(L, 3, -1), len); - int lax = lua_toboolean(L, 4); - luaL_argcheck(L, 1 <= posi && --posi <= (lua_Integer)len, 2, - "initial position out of bounds"); - luaL_argcheck(L, --posj < (lua_Integer)len, 3, - "final position out of bounds"); - while (posi <= posj) { - const char *s1 = utf8_decode(s + posi, NULL, !lax); - if (s1 == NULL) { /* conversion error? */ - luaL_pushfail(L); /* return fail ... */ - lua_pushinteger(L, posi + 1); /* ... and current position */ - return 2; - } - posi = s1 - s; - n++; - } - lua_pushinteger(L, n); - return 1; -} - - -/* -** codepoint(s, [i, [j [, lax]]]) -> returns codepoints for all -** characters that start in the range [i,j] -*/ -static int codepoint (lua_State *L) { - size_t len; - const char *s = luaL_checklstring(L, 1, &len); - lua_Integer posi = u_posrelat(luaL_optinteger(L, 2, 1), len); - lua_Integer pose = u_posrelat(luaL_optinteger(L, 3, posi), len); - int lax = lua_toboolean(L, 4); - int n; - const char *se; - luaL_argcheck(L, posi >= 1, 2, "out of bounds"); - luaL_argcheck(L, pose <= (lua_Integer)len, 3, "out of bounds"); - if (posi > pose) return 0; /* empty interval; return no values */ - if (pose - posi >= INT_MAX) /* (lua_Integer -> int) overflow? */ - return luaL_error(L, "string slice too long"); - n = (int)(pose - posi) + 1; /* upper bound for number of returns */ - luaL_checkstack(L, n, "string slice too long"); - n = 0; /* count the number of returns */ - se = s + pose; /* string end */ - for (s += posi - 1; s < se;) { - utfint code; - s = utf8_decode(s, &code, !lax); - if (s == NULL) - return luaL_error(L, MSGInvalid); - lua_pushinteger(L, code); - n++; - } - return n; -} - - -static void pushutfchar (lua_State *L, int arg) { - lua_Unsigned code = (lua_Unsigned)luaL_checkinteger(L, arg); - luaL_argcheck(L, code <= MAXUTF, arg, "value out of range"); - lua_pushfstring(L, "%U", (long)code); -} - - -/* -** utfchar(n1, n2, ...) -> char(n1)..char(n2)... -*/ -static int utfchar (lua_State *L) { - int n = lua_gettop(L); /* number of arguments */ - if (n == 1) /* optimize common case of single char */ - pushutfchar(L, 1); - else { - int i; - luaL_Buffer b; - luaL_buffinit(L, &b); - for (i = 1; i <= n; i++) { - pushutfchar(L, i); - luaL_addvalue(&b); - } - luaL_pushresult(&b); - } - return 1; -} - - -/* -** offset(s, n, [i]) -> index where n-th character counting from -** position 'i' starts; 0 means character at 'i'. -*/ -static int byteoffset (lua_State *L) { - size_t len; - const char *s = luaL_checklstring(L, 1, &len); - lua_Integer n = luaL_checkinteger(L, 2); - lua_Integer posi = (n >= 0) ? 1 : len + 1; - posi = u_posrelat(luaL_optinteger(L, 3, posi), len); - luaL_argcheck(L, 1 <= posi && --posi <= (lua_Integer)len, 3, - "position out of bounds"); - if (n == 0) { - /* find beginning of current byte sequence */ - while (posi > 0 && iscontp(s + posi)) posi--; - } - else { - if (iscontp(s + posi)) - return luaL_error(L, "initial position is a continuation byte"); - if (n < 0) { - while (n < 0 && posi > 0) { /* move back */ - do { /* find beginning of previous character */ - posi--; - } while (posi > 0 && iscontp(s + posi)); - n++; - } - } - else { - n--; /* do not move for 1st character */ - while (n > 0 && posi < (lua_Integer)len) { - do { /* find beginning of next character */ - posi++; - } while (iscontp(s + posi)); /* (cannot pass final '\0') */ - n--; - } - } - } - if (n == 0) /* did it find given character? */ - lua_pushinteger(L, posi + 1); - else /* no such character */ - luaL_pushfail(L); - return 1; -} - - -static int iter_aux (lua_State *L, int strict) { - size_t len; - const char *s = luaL_checklstring(L, 1, &len); - lua_Unsigned n = (lua_Unsigned)lua_tointeger(L, 2); - if (n < len) { - while (iscontp(s + n)) n++; /* go to next character */ - } - if (n >= len) /* (also handles original 'n' being negative) */ - return 0; /* no more codepoints */ - else { - utfint code; - const char *next = utf8_decode(s + n, &code, strict); - if (next == NULL || iscontp(next)) - return luaL_error(L, MSGInvalid); - lua_pushinteger(L, n + 1); - lua_pushinteger(L, code); - return 2; - } -} - - -static int iter_auxstrict (lua_State *L) { - return iter_aux(L, 1); -} - -static int iter_auxlax (lua_State *L) { - return iter_aux(L, 0); -} - - -static int iter_codes (lua_State *L) { - int lax = lua_toboolean(L, 2); - const char *s = luaL_checkstring(L, 1); - luaL_argcheck(L, !iscontp(s), 1, MSGInvalid); - lua_pushcfunction(L, lax ? iter_auxlax : iter_auxstrict); - lua_pushvalue(L, 1); - lua_pushinteger(L, 0); - return 3; -} - - -/* pattern to match a single UTF-8 character */ -#define UTF8PATT "[\0-\x7F\xC2-\xFD][\x80-\xBF]*" - - -static const luaL_Reg funcs[] = { - {"offset", byteoffset}, - {"codepoint", codepoint}, - {"char", utfchar}, - {"len", utflen}, - {"codes", iter_codes}, - /* placeholders */ - {"charpattern", NULL}, - {NULL, NULL} -}; - - -LUAMOD_API int luaopen_utf8 (lua_State *L) { - luaL_newlib(L, funcs); - lua_pushlstring(L, UTF8PATT, sizeof(UTF8PATT)/sizeof(char) - 1); - lua_setfield(L, -2, "charpattern"); - return 1; -} - diff --git a/lib/lua-5.4/src/lvm.c b/lib/lua-5.4/src/lvm.c deleted file mode 100644 index 8493a77..0000000 --- a/lib/lua-5.4/src/lvm.c +++ /dev/null @@ -1,1901 +0,0 @@ -/* -** $Id: lvm.c $ -** Lua virtual machine -** See Copyright Notice in lua.h -*/ - -#define lvm_c -#define LUA_CORE - -#include "lprefix.h" - -#include -#include -#include -#include -#include -#include - -#include "lua.h" - -#include "ldebug.h" -#include "ldo.h" -#include "lfunc.h" -#include "lgc.h" -#include "lobject.h" -#include "lopcodes.h" -#include "lstate.h" -#include "lstring.h" -#include "ltable.h" -#include "ltm.h" -#include "lvm.h" - - -/* -** By default, use jump tables in the main interpreter loop on gcc -** and compatible compilers. -*/ -#if !defined(LUA_USE_JUMPTABLE) -#if defined(__GNUC__) -#define LUA_USE_JUMPTABLE 1 -#else -#define LUA_USE_JUMPTABLE 0 -#endif -#endif - - - -/* limit for table tag-method chains (to avoid infinite loops) */ -#define MAXTAGLOOP 2000 - - -/* -** 'l_intfitsf' checks whether a given integer is in the range that -** can be converted to a float without rounding. Used in comparisons. -*/ - -/* number of bits in the mantissa of a float */ -#define NBM (l_floatatt(MANT_DIG)) - -/* -** Check whether some integers may not fit in a float, testing whether -** (maxinteger >> NBM) > 0. (That implies (1 << NBM) <= maxinteger.) -** (The shifts are done in parts, to avoid shifting by more than the size -** of an integer. In a worst case, NBM == 113 for long double and -** sizeof(long) == 32.) -*/ -#if ((((LUA_MAXINTEGER >> (NBM / 4)) >> (NBM / 4)) >> (NBM / 4)) \ - >> (NBM - (3 * (NBM / 4)))) > 0 - -/* limit for integers that fit in a float */ -#define MAXINTFITSF ((lua_Unsigned)1 << NBM) - -/* check whether 'i' is in the interval [-MAXINTFITSF, MAXINTFITSF] */ -#define l_intfitsf(i) ((MAXINTFITSF + l_castS2U(i)) <= (2 * MAXINTFITSF)) - -#else /* all integers fit in a float precisely */ - -#define l_intfitsf(i) 1 - -#endif - - -/* -** Try to convert a value from string to a number value. -** If the value is not a string or is a string not representing -** a valid numeral (or if coercions from strings to numbers -** are disabled via macro 'cvt2num'), do not modify 'result' -** and return 0. -*/ -static int l_strton (const TValue *obj, TValue *result) { - lua_assert(obj != result); - if (!cvt2num(obj)) /* is object not a string? */ - return 0; - else - return (luaO_str2num(svalue(obj), result) == vslen(obj) + 1); -} - - -/* -** Try to convert a value to a float. The float case is already handled -** by the macro 'tonumber'. -*/ -int luaV_tonumber_ (const TValue *obj, lua_Number *n) { - TValue v; - if (ttisinteger(obj)) { - *n = cast_num(ivalue(obj)); - return 1; - } - else if (l_strton(obj, &v)) { /* string coercible to number? */ - *n = nvalue(&v); /* convert result of 'luaO_str2num' to a float */ - return 1; - } - else - return 0; /* conversion failed */ -} - - -/* -** try to convert a float to an integer, rounding according to 'mode'. -*/ -int luaV_flttointeger (lua_Number n, lua_Integer *p, F2Imod mode) { - lua_Number f = l_floor(n); - if (n != f) { /* not an integral value? */ - if (mode == F2Ieq) return 0; /* fails if mode demands integral value */ - else if (mode == F2Iceil) /* needs ceil? */ - f += 1; /* convert floor to ceil (remember: n != f) */ - } - return lua_numbertointeger(f, p); -} - - -/* -** try to convert a value to an integer, rounding according to 'mode', -** without string coercion. -** ("Fast track" handled by macro 'tointegerns'.) -*/ -int luaV_tointegerns (const TValue *obj, lua_Integer *p, F2Imod mode) { - if (ttisfloat(obj)) - return luaV_flttointeger(fltvalue(obj), p, mode); - else if (ttisinteger(obj)) { - *p = ivalue(obj); - return 1; - } - else - return 0; -} - - -/* -** try to convert a value to an integer. -*/ -int luaV_tointeger (const TValue *obj, lua_Integer *p, F2Imod mode) { - TValue v; - if (l_strton(obj, &v)) /* does 'obj' point to a numerical string? */ - obj = &v; /* change it to point to its corresponding number */ - return luaV_tointegerns(obj, p, mode); -} - - -/* -** Try to convert a 'for' limit to an integer, preserving the semantics -** of the loop. Return true if the loop must not run; otherwise, '*p' -** gets the integer limit. -** (The following explanation assumes a positive step; it is valid for -** negative steps mutatis mutandis.) -** If the limit is an integer or can be converted to an integer, -** rounding down, that is the limit. -** Otherwise, check whether the limit can be converted to a float. If -** the float is too large, clip it to LUA_MAXINTEGER. If the float -** is too negative, the loop should not run, because any initial -** integer value is greater than such limit; so, the function returns -** true to signal that. (For this latter case, no integer limit would be -** correct; even a limit of LUA_MININTEGER would run the loop once for -** an initial value equal to LUA_MININTEGER.) -*/ -static int forlimit (lua_State *L, lua_Integer init, const TValue *lim, - lua_Integer *p, lua_Integer step) { - if (!luaV_tointeger(lim, p, (step < 0 ? F2Iceil : F2Ifloor))) { - /* not coercible to in integer */ - lua_Number flim; /* try to convert to float */ - if (!tonumber(lim, &flim)) /* cannot convert to float? */ - luaG_forerror(L, lim, "limit"); - /* else 'flim' is a float out of integer bounds */ - if (luai_numlt(0, flim)) { /* if it is positive, it is too large */ - if (step < 0) return 1; /* initial value must be less than it */ - *p = LUA_MAXINTEGER; /* truncate */ - } - else { /* it is less than min integer */ - if (step > 0) return 1; /* initial value must be greater than it */ - *p = LUA_MININTEGER; /* truncate */ - } - } - return (step > 0 ? init > *p : init < *p); /* not to run? */ -} - - -/* -** Prepare a numerical for loop (opcode OP_FORPREP). -** Return true to skip the loop. Otherwise, -** after preparation, stack will be as follows: -** ra : internal index (safe copy of the control variable) -** ra + 1 : loop counter (integer loops) or limit (float loops) -** ra + 2 : step -** ra + 3 : control variable -*/ -static int forprep (lua_State *L, StkId ra) { - TValue *pinit = s2v(ra); - TValue *plimit = s2v(ra + 1); - TValue *pstep = s2v(ra + 2); - if (ttisinteger(pinit) && ttisinteger(pstep)) { /* integer loop? */ - lua_Integer init = ivalue(pinit); - lua_Integer step = ivalue(pstep); - lua_Integer limit; - if (step == 0) - luaG_runerror(L, "'for' step is zero"); - setivalue(s2v(ra + 3), init); /* control variable */ - if (forlimit(L, init, plimit, &limit, step)) - return 1; /* skip the loop */ - else { /* prepare loop counter */ - lua_Unsigned count; - if (step > 0) { /* ascending loop? */ - count = l_castS2U(limit) - l_castS2U(init); - if (step != 1) /* avoid division in the too common case */ - count /= l_castS2U(step); - } - else { /* step < 0; descending loop */ - count = l_castS2U(init) - l_castS2U(limit); - /* 'step+1' avoids negating 'mininteger' */ - count /= l_castS2U(-(step + 1)) + 1u; - } - /* store the counter in place of the limit (which won't be - needed anymore) */ - setivalue(plimit, l_castU2S(count)); - } - } - else { /* try making all values floats */ - lua_Number init; lua_Number limit; lua_Number step; - if (l_unlikely(!tonumber(plimit, &limit))) - luaG_forerror(L, plimit, "limit"); - if (l_unlikely(!tonumber(pstep, &step))) - luaG_forerror(L, pstep, "step"); - if (l_unlikely(!tonumber(pinit, &init))) - luaG_forerror(L, pinit, "initial value"); - if (step == 0) - luaG_runerror(L, "'for' step is zero"); - if (luai_numlt(0, step) ? luai_numlt(limit, init) - : luai_numlt(init, limit)) - return 1; /* skip the loop */ - else { - /* make sure internal values are all floats */ - setfltvalue(plimit, limit); - setfltvalue(pstep, step); - setfltvalue(s2v(ra), init); /* internal index */ - setfltvalue(s2v(ra + 3), init); /* control variable */ - } - } - return 0; -} - - -/* -** Execute a step of a float numerical for loop, returning -** true iff the loop must continue. (The integer case is -** written online with opcode OP_FORLOOP, for performance.) -*/ -static int floatforloop (StkId ra) { - lua_Number step = fltvalue(s2v(ra + 2)); - lua_Number limit = fltvalue(s2v(ra + 1)); - lua_Number idx = fltvalue(s2v(ra)); /* internal index */ - idx = luai_numadd(L, idx, step); /* increment index */ - if (luai_numlt(0, step) ? luai_numle(idx, limit) - : luai_numle(limit, idx)) { - chgfltvalue(s2v(ra), idx); /* update internal index */ - setfltvalue(s2v(ra + 3), idx); /* and control variable */ - return 1; /* jump back */ - } - else - return 0; /* finish the loop */ -} - - -/* -** Finish the table access 'val = t[key]'. -** if 'slot' is NULL, 't' is not a table; otherwise, 'slot' points to -** t[k] entry (which must be empty). -*/ -void luaV_finishget (lua_State *L, const TValue *t, TValue *key, StkId val, - const TValue *slot) { - int loop; /* counter to avoid infinite loops */ - const TValue *tm; /* metamethod */ - for (loop = 0; loop < MAXTAGLOOP; loop++) { - if (slot == NULL) { /* 't' is not a table? */ - lua_assert(!ttistable(t)); - tm = luaT_gettmbyobj(L, t, TM_INDEX); - if (l_unlikely(notm(tm))) - luaG_typeerror(L, t, "index"); /* no metamethod */ - /* else will try the metamethod */ - } - else { /* 't' is a table */ - lua_assert(isempty(slot)); - tm = fasttm(L, hvalue(t)->metatable, TM_INDEX); /* table's metamethod */ - if (tm == NULL) { /* no metamethod? */ - setnilvalue(s2v(val)); /* result is nil */ - return; - } - /* else will try the metamethod */ - } - if (ttisfunction(tm)) { /* is metamethod a function? */ - luaT_callTMres(L, tm, t, key, val); /* call it */ - return; - } - t = tm; /* else try to access 'tm[key]' */ - if (luaV_fastget(L, t, key, slot, luaH_get)) { /* fast track? */ - setobj2s(L, val, slot); /* done */ - return; - } - /* else repeat (tail call 'luaV_finishget') */ - } - luaG_runerror(L, "'__index' chain too long; possible loop"); -} - - -/* -** Finish a table assignment 't[key] = val'. -** If 'slot' is NULL, 't' is not a table. Otherwise, 'slot' points -** to the entry 't[key]', or to a value with an absent key if there -** is no such entry. (The value at 'slot' must be empty, otherwise -** 'luaV_fastget' would have done the job.) -*/ -void luaV_finishset (lua_State *L, const TValue *t, TValue *key, - TValue *val, const TValue *slot) { - int loop; /* counter to avoid infinite loops */ - for (loop = 0; loop < MAXTAGLOOP; loop++) { - const TValue *tm; /* '__newindex' metamethod */ - if (slot != NULL) { /* is 't' a table? */ - Table *h = hvalue(t); /* save 't' table */ - lua_assert(isempty(slot)); /* slot must be empty */ - tm = fasttm(L, h->metatable, TM_NEWINDEX); /* get metamethod */ - if (tm == NULL) { /* no metamethod? */ - luaH_finishset(L, h, key, slot, val); /* set new value */ - invalidateTMcache(h); - luaC_barrierback(L, obj2gco(h), val); - return; - } - /* else will try the metamethod */ - } - else { /* not a table; check metamethod */ - tm = luaT_gettmbyobj(L, t, TM_NEWINDEX); - if (l_unlikely(notm(tm))) - luaG_typeerror(L, t, "index"); - } - /* try the metamethod */ - if (ttisfunction(tm)) { - luaT_callTM(L, tm, t, key, val); - return; - } - t = tm; /* else repeat assignment over 'tm' */ - if (luaV_fastget(L, t, key, slot, luaH_get)) { - luaV_finishfastset(L, t, slot, val); - return; /* done */ - } - /* else 'return luaV_finishset(L, t, key, val, slot)' (loop) */ - } - luaG_runerror(L, "'__newindex' chain too long; possible loop"); -} - - -/* -** Compare two strings 'ls' x 'rs', returning an integer less-equal- -** -greater than zero if 'ls' is less-equal-greater than 'rs'. -** The code is a little tricky because it allows '\0' in the strings -** and it uses 'strcoll' (to respect locales) for each segments -** of the strings. -*/ -static int l_strcmp (const TString *ls, const TString *rs) { - const char *l = getstr(ls); - size_t ll = tsslen(ls); - const char *r = getstr(rs); - size_t lr = tsslen(rs); - for (;;) { /* for each segment */ - int temp = strcoll(l, r); - if (temp != 0) /* not equal? */ - return temp; /* done */ - else { /* strings are equal up to a '\0' */ - size_t len = strlen(l); /* index of first '\0' in both strings */ - if (len == lr) /* 'rs' is finished? */ - return (len == ll) ? 0 : 1; /* check 'ls' */ - else if (len == ll) /* 'ls' is finished? */ - return -1; /* 'ls' is less than 'rs' ('rs' is not finished) */ - /* both strings longer than 'len'; go on comparing after the '\0' */ - len++; - l += len; ll -= len; r += len; lr -= len; - } - } -} - - -/* -** Check whether integer 'i' is less than float 'f'. If 'i' has an -** exact representation as a float ('l_intfitsf'), compare numbers as -** floats. Otherwise, use the equivalence 'i < f <=> i < ceil(f)'. -** If 'ceil(f)' is out of integer range, either 'f' is greater than -** all integers or less than all integers. -** (The test with 'l_intfitsf' is only for performance; the else -** case is correct for all values, but it is slow due to the conversion -** from float to int.) -** When 'f' is NaN, comparisons must result in false. -*/ -l_sinline int LTintfloat (lua_Integer i, lua_Number f) { - if (l_intfitsf(i)) - return luai_numlt(cast_num(i), f); /* compare them as floats */ - else { /* i < f <=> i < ceil(f) */ - lua_Integer fi; - if (luaV_flttointeger(f, &fi, F2Iceil)) /* fi = ceil(f) */ - return i < fi; /* compare them as integers */ - else /* 'f' is either greater or less than all integers */ - return f > 0; /* greater? */ - } -} - - -/* -** Check whether integer 'i' is less than or equal to float 'f'. -** See comments on previous function. -*/ -l_sinline int LEintfloat (lua_Integer i, lua_Number f) { - if (l_intfitsf(i)) - return luai_numle(cast_num(i), f); /* compare them as floats */ - else { /* i <= f <=> i <= floor(f) */ - lua_Integer fi; - if (luaV_flttointeger(f, &fi, F2Ifloor)) /* fi = floor(f) */ - return i <= fi; /* compare them as integers */ - else /* 'f' is either greater or less than all integers */ - return f > 0; /* greater? */ - } -} - - -/* -** Check whether float 'f' is less than integer 'i'. -** See comments on previous function. -*/ -l_sinline int LTfloatint (lua_Number f, lua_Integer i) { - if (l_intfitsf(i)) - return luai_numlt(f, cast_num(i)); /* compare them as floats */ - else { /* f < i <=> floor(f) < i */ - lua_Integer fi; - if (luaV_flttointeger(f, &fi, F2Ifloor)) /* fi = floor(f) */ - return fi < i; /* compare them as integers */ - else /* 'f' is either greater or less than all integers */ - return f < 0; /* less? */ - } -} - - -/* -** Check whether float 'f' is less than or equal to integer 'i'. -** See comments on previous function. -*/ -l_sinline int LEfloatint (lua_Number f, lua_Integer i) { - if (l_intfitsf(i)) - return luai_numle(f, cast_num(i)); /* compare them as floats */ - else { /* f <= i <=> ceil(f) <= i */ - lua_Integer fi; - if (luaV_flttointeger(f, &fi, F2Iceil)) /* fi = ceil(f) */ - return fi <= i; /* compare them as integers */ - else /* 'f' is either greater or less than all integers */ - return f < 0; /* less? */ - } -} - - -/* -** Return 'l < r', for numbers. -*/ -l_sinline int LTnum (const TValue *l, const TValue *r) { - lua_assert(ttisnumber(l) && ttisnumber(r)); - if (ttisinteger(l)) { - lua_Integer li = ivalue(l); - if (ttisinteger(r)) - return li < ivalue(r); /* both are integers */ - else /* 'l' is int and 'r' is float */ - return LTintfloat(li, fltvalue(r)); /* l < r ? */ - } - else { - lua_Number lf = fltvalue(l); /* 'l' must be float */ - if (ttisfloat(r)) - return luai_numlt(lf, fltvalue(r)); /* both are float */ - else /* 'l' is float and 'r' is int */ - return LTfloatint(lf, ivalue(r)); - } -} - - -/* -** Return 'l <= r', for numbers. -*/ -l_sinline int LEnum (const TValue *l, const TValue *r) { - lua_assert(ttisnumber(l) && ttisnumber(r)); - if (ttisinteger(l)) { - lua_Integer li = ivalue(l); - if (ttisinteger(r)) - return li <= ivalue(r); /* both are integers */ - else /* 'l' is int and 'r' is float */ - return LEintfloat(li, fltvalue(r)); /* l <= r ? */ - } - else { - lua_Number lf = fltvalue(l); /* 'l' must be float */ - if (ttisfloat(r)) - return luai_numle(lf, fltvalue(r)); /* both are float */ - else /* 'l' is float and 'r' is int */ - return LEfloatint(lf, ivalue(r)); - } -} - - -/* -** return 'l < r' for non-numbers. -*/ -static int lessthanothers (lua_State *L, const TValue *l, const TValue *r) { - lua_assert(!ttisnumber(l) || !ttisnumber(r)); - if (ttisstring(l) && ttisstring(r)) /* both are strings? */ - return l_strcmp(tsvalue(l), tsvalue(r)) < 0; - else - return luaT_callorderTM(L, l, r, TM_LT); -} - - -/* -** Main operation less than; return 'l < r'. -*/ -int luaV_lessthan (lua_State *L, const TValue *l, const TValue *r) { - if (ttisnumber(l) && ttisnumber(r)) /* both operands are numbers? */ - return LTnum(l, r); - else return lessthanothers(L, l, r); -} - - -/* -** return 'l <= r' for non-numbers. -*/ -static int lessequalothers (lua_State *L, const TValue *l, const TValue *r) { - lua_assert(!ttisnumber(l) || !ttisnumber(r)); - if (ttisstring(l) && ttisstring(r)) /* both are strings? */ - return l_strcmp(tsvalue(l), tsvalue(r)) <= 0; - else - return luaT_callorderTM(L, l, r, TM_LE); -} - - -/* -** Main operation less than or equal to; return 'l <= r'. -*/ -int luaV_lessequal (lua_State *L, const TValue *l, const TValue *r) { - if (ttisnumber(l) && ttisnumber(r)) /* both operands are numbers? */ - return LEnum(l, r); - else return lessequalothers(L, l, r); -} - - -/* -** Main operation for equality of Lua values; return 't1 == t2'. -** L == NULL means raw equality (no metamethods) -*/ -int luaV_equalobj (lua_State *L, const TValue *t1, const TValue *t2) { - const TValue *tm; - if (ttypetag(t1) != ttypetag(t2)) { /* not the same variant? */ - if (ttype(t1) != ttype(t2) || ttype(t1) != LUA_TNUMBER) - return 0; /* only numbers can be equal with different variants */ - else { /* two numbers with different variants */ - /* One of them is an integer. If the other does not have an - integer value, they cannot be equal; otherwise, compare their - integer values. */ - lua_Integer i1, i2; - return (luaV_tointegerns(t1, &i1, F2Ieq) && - luaV_tointegerns(t2, &i2, F2Ieq) && - i1 == i2); - } - } - /* values have same type and same variant */ - switch (ttypetag(t1)) { - case LUA_VNIL: case LUA_VFALSE: case LUA_VTRUE: return 1; - case LUA_VNUMINT: return (ivalue(t1) == ivalue(t2)); - case LUA_VNUMFLT: return luai_numeq(fltvalue(t1), fltvalue(t2)); - case LUA_VLIGHTUSERDATA: return pvalue(t1) == pvalue(t2); - case LUA_VLCF: return fvalue(t1) == fvalue(t2); - case LUA_VSHRSTR: return eqshrstr(tsvalue(t1), tsvalue(t2)); - case LUA_VLNGSTR: return luaS_eqlngstr(tsvalue(t1), tsvalue(t2)); - case LUA_VUSERDATA: { - if (uvalue(t1) == uvalue(t2)) return 1; - else if (L == NULL) return 0; - tm = fasttm(L, uvalue(t1)->metatable, TM_EQ); - if (tm == NULL) - tm = fasttm(L, uvalue(t2)->metatable, TM_EQ); - break; /* will try TM */ - } - case LUA_VTABLE: { - if (hvalue(t1) == hvalue(t2)) return 1; - else if (L == NULL) return 0; - tm = fasttm(L, hvalue(t1)->metatable, TM_EQ); - if (tm == NULL) - tm = fasttm(L, hvalue(t2)->metatable, TM_EQ); - break; /* will try TM */ - } - default: - return gcvalue(t1) == gcvalue(t2); - } - if (tm == NULL) /* no TM? */ - return 0; /* objects are different */ - else { - luaT_callTMres(L, tm, t1, t2, L->top.p); /* call TM */ - return !l_isfalse(s2v(L->top.p)); - } -} - - -/* macro used by 'luaV_concat' to ensure that element at 'o' is a string */ -#define tostring(L,o) \ - (ttisstring(o) || (cvt2str(o) && (luaO_tostring(L, o), 1))) - -#define isemptystr(o) (ttisshrstring(o) && tsvalue(o)->shrlen == 0) - -/* copy strings in stack from top - n up to top - 1 to buffer */ -static void copy2buff (StkId top, int n, char *buff) { - size_t tl = 0; /* size already copied */ - do { - size_t l = vslen(s2v(top - n)); /* length of string being copied */ - memcpy(buff + tl, svalue(s2v(top - n)), l * sizeof(char)); - tl += l; - } while (--n > 0); -} - - -/* -** Main operation for concatenation: concat 'total' values in the stack, -** from 'L->top.p - total' up to 'L->top.p - 1'. -*/ -void luaV_concat (lua_State *L, int total) { - if (total == 1) - return; /* "all" values already concatenated */ - do { - StkId top = L->top.p; - int n = 2; /* number of elements handled in this pass (at least 2) */ - if (!(ttisstring(s2v(top - 2)) || cvt2str(s2v(top - 2))) || - !tostring(L, s2v(top - 1))) - luaT_tryconcatTM(L); /* may invalidate 'top' */ - else if (isemptystr(s2v(top - 1))) /* second operand is empty? */ - cast_void(tostring(L, s2v(top - 2))); /* result is first operand */ - else if (isemptystr(s2v(top - 2))) { /* first operand is empty string? */ - setobjs2s(L, top - 2, top - 1); /* result is second op. */ - } - else { - /* at least two non-empty string values; get as many as possible */ - size_t tl = vslen(s2v(top - 1)); - TString *ts; - /* collect total length and number of strings */ - for (n = 1; n < total && tostring(L, s2v(top - n - 1)); n++) { - size_t l = vslen(s2v(top - n - 1)); - if (l_unlikely(l >= (MAX_SIZE/sizeof(char)) - tl)) { - L->top.p = top - total; /* pop strings to avoid wasting stack */ - luaG_runerror(L, "string length overflow"); - } - tl += l; - } - if (tl <= LUAI_MAXSHORTLEN) { /* is result a short string? */ - char buff[LUAI_MAXSHORTLEN]; - copy2buff(top, n, buff); /* copy strings to buffer */ - ts = luaS_newlstr(L, buff, tl); - } - else { /* long string; copy strings directly to final result */ - ts = luaS_createlngstrobj(L, tl); - copy2buff(top, n, getstr(ts)); - } - setsvalue2s(L, top - n, ts); /* create result */ - } - total -= n - 1; /* got 'n' strings to create one new */ - L->top.p -= n - 1; /* popped 'n' strings and pushed one */ - } while (total > 1); /* repeat until only 1 result left */ -} - - -/* -** Main operation 'ra = #rb'. -*/ -void luaV_objlen (lua_State *L, StkId ra, const TValue *rb) { - const TValue *tm; - switch (ttypetag(rb)) { - case LUA_VTABLE: { - Table *h = hvalue(rb); - tm = fasttm(L, h->metatable, TM_LEN); - if (tm) break; /* metamethod? break switch to call it */ - setivalue(s2v(ra), luaH_getn(h)); /* else primitive len */ - return; - } - case LUA_VSHRSTR: { - setivalue(s2v(ra), tsvalue(rb)->shrlen); - return; - } - case LUA_VLNGSTR: { - setivalue(s2v(ra), tsvalue(rb)->u.lnglen); - return; - } - default: { /* try metamethod */ - tm = luaT_gettmbyobj(L, rb, TM_LEN); - if (l_unlikely(notm(tm))) /* no metamethod? */ - luaG_typeerror(L, rb, "get length of"); - break; - } - } - luaT_callTMres(L, tm, rb, rb, ra); -} - - -/* -** Integer division; return 'm // n', that is, floor(m/n). -** C division truncates its result (rounds towards zero). -** 'floor(q) == trunc(q)' when 'q >= 0' or when 'q' is integer, -** otherwise 'floor(q) == trunc(q) - 1'. -*/ -lua_Integer luaV_idiv (lua_State *L, lua_Integer m, lua_Integer n) { - if (l_unlikely(l_castS2U(n) + 1u <= 1u)) { /* special cases: -1 or 0 */ - if (n == 0) - luaG_runerror(L, "attempt to divide by zero"); - return intop(-, 0, m); /* n==-1; avoid overflow with 0x80000...//-1 */ - } - else { - lua_Integer q = m / n; /* perform C division */ - if ((m ^ n) < 0 && m % n != 0) /* 'm/n' would be negative non-integer? */ - q -= 1; /* correct result for different rounding */ - return q; - } -} - - -/* -** Integer modulus; return 'm % n'. (Assume that C '%' with -** negative operands follows C99 behavior. See previous comment -** about luaV_idiv.) -*/ -lua_Integer luaV_mod (lua_State *L, lua_Integer m, lua_Integer n) { - if (l_unlikely(l_castS2U(n) + 1u <= 1u)) { /* special cases: -1 or 0 */ - if (n == 0) - luaG_runerror(L, "attempt to perform 'n%%0'"); - return 0; /* m % -1 == 0; avoid overflow with 0x80000...%-1 */ - } - else { - lua_Integer r = m % n; - if (r != 0 && (r ^ n) < 0) /* 'm/n' would be non-integer negative? */ - r += n; /* correct result for different rounding */ - return r; - } -} - - -/* -** Float modulus -*/ -lua_Number luaV_modf (lua_State *L, lua_Number m, lua_Number n) { - lua_Number r; - luai_nummod(L, m, n, r); - return r; -} - - -/* number of bits in an integer */ -#define NBITS cast_int(sizeof(lua_Integer) * CHAR_BIT) - - -/* -** Shift left operation. (Shift right just negates 'y'.) -*/ -lua_Integer luaV_shiftl (lua_Integer x, lua_Integer y) { - if (y < 0) { /* shift right? */ - if (y <= -NBITS) return 0; - else return intop(>>, x, -y); - } - else { /* shift left */ - if (y >= NBITS) return 0; - else return intop(<<, x, y); - } -} - - -/* -** create a new Lua closure, push it in the stack, and initialize -** its upvalues. -*/ -static void pushclosure (lua_State *L, Proto *p, UpVal **encup, StkId base, - StkId ra) { - int nup = p->sizeupvalues; - Upvaldesc *uv = p->upvalues; - int i; - LClosure *ncl = luaF_newLclosure(L, nup); - ncl->p = p; - setclLvalue2s(L, ra, ncl); /* anchor new closure in stack */ - for (i = 0; i < nup; i++) { /* fill in its upvalues */ - if (uv[i].instack) /* upvalue refers to local variable? */ - ncl->upvals[i] = luaF_findupval(L, base + uv[i].idx); - else /* get upvalue from enclosing function */ - ncl->upvals[i] = encup[uv[i].idx]; - luaC_objbarrier(L, ncl, ncl->upvals[i]); - } -} - - -/* -** finish execution of an opcode interrupted by a yield -*/ -void luaV_finishOp (lua_State *L) { - CallInfo *ci = L->ci; - StkId base = ci->func.p + 1; - Instruction inst = *(ci->u.l.savedpc - 1); /* interrupted instruction */ - OpCode op = GET_OPCODE(inst); - switch (op) { /* finish its execution */ - case OP_MMBIN: case OP_MMBINI: case OP_MMBINK: { - setobjs2s(L, base + GETARG_A(*(ci->u.l.savedpc - 2)), --L->top.p); - break; - } - case OP_UNM: case OP_BNOT: case OP_LEN: - case OP_GETTABUP: case OP_GETTABLE: case OP_GETI: - case OP_GETFIELD: case OP_SELF: { - setobjs2s(L, base + GETARG_A(inst), --L->top.p); - break; - } - case OP_LT: case OP_LE: - case OP_LTI: case OP_LEI: - case OP_GTI: case OP_GEI: - case OP_EQ: { /* note that 'OP_EQI'/'OP_EQK' cannot yield */ - int res = !l_isfalse(s2v(L->top.p - 1)); - L->top.p--; -#if defined(LUA_COMPAT_LT_LE) - if (ci->callstatus & CIST_LEQ) { /* "<=" using "<" instead? */ - ci->callstatus ^= CIST_LEQ; /* clear mark */ - res = !res; /* negate result */ - } -#endif - lua_assert(GET_OPCODE(*ci->u.l.savedpc) == OP_JMP); - if (res != GETARG_k(inst)) /* condition failed? */ - ci->u.l.savedpc++; /* skip jump instruction */ - break; - } - case OP_CONCAT: { - StkId top = L->top.p - 1; /* top when 'luaT_tryconcatTM' was called */ - int a = GETARG_A(inst); /* first element to concatenate */ - int total = cast_int(top - 1 - (base + a)); /* yet to concatenate */ - setobjs2s(L, top - 2, top); /* put TM result in proper position */ - L->top.p = top - 1; /* top is one after last element (at top-2) */ - luaV_concat(L, total); /* concat them (may yield again) */ - break; - } - case OP_CLOSE: { /* yielded closing variables */ - ci->u.l.savedpc--; /* repeat instruction to close other vars. */ - break; - } - case OP_RETURN: { /* yielded closing variables */ - StkId ra = base + GETARG_A(inst); - /* adjust top to signal correct number of returns, in case the - return is "up to top" ('isIT') */ - L->top.p = ra + ci->u2.nres; - /* repeat instruction to close other vars. and complete the return */ - ci->u.l.savedpc--; - break; - } - default: { - /* only these other opcodes can yield */ - lua_assert(op == OP_TFORCALL || op == OP_CALL || - op == OP_TAILCALL || op == OP_SETTABUP || op == OP_SETTABLE || - op == OP_SETI || op == OP_SETFIELD); - break; - } - } -} - - - - -/* -** {================================================================== -** Macros for arithmetic/bitwise/comparison opcodes in 'luaV_execute' -** =================================================================== -*/ - -#define l_addi(L,a,b) intop(+, a, b) -#define l_subi(L,a,b) intop(-, a, b) -#define l_muli(L,a,b) intop(*, a, b) -#define l_band(a,b) intop(&, a, b) -#define l_bor(a,b) intop(|, a, b) -#define l_bxor(a,b) intop(^, a, b) - -#define l_lti(a,b) (a < b) -#define l_lei(a,b) (a <= b) -#define l_gti(a,b) (a > b) -#define l_gei(a,b) (a >= b) - - -/* -** Arithmetic operations with immediate operands. 'iop' is the integer -** operation, 'fop' is the float operation. -*/ -#define op_arithI(L,iop,fop) { \ - StkId ra = RA(i); \ - TValue *v1 = vRB(i); \ - int imm = GETARG_sC(i); \ - if (ttisinteger(v1)) { \ - lua_Integer iv1 = ivalue(v1); \ - pc++; setivalue(s2v(ra), iop(L, iv1, imm)); \ - } \ - else if (ttisfloat(v1)) { \ - lua_Number nb = fltvalue(v1); \ - lua_Number fimm = cast_num(imm); \ - pc++; setfltvalue(s2v(ra), fop(L, nb, fimm)); \ - }} - - -/* -** Auxiliary function for arithmetic operations over floats and others -** with two register operands. -*/ -#define op_arithf_aux(L,v1,v2,fop) { \ - lua_Number n1; lua_Number n2; \ - if (tonumberns(v1, n1) && tonumberns(v2, n2)) { \ - pc++; setfltvalue(s2v(ra), fop(L, n1, n2)); \ - }} - - -/* -** Arithmetic operations over floats and others with register operands. -*/ -#define op_arithf(L,fop) { \ - StkId ra = RA(i); \ - TValue *v1 = vRB(i); \ - TValue *v2 = vRC(i); \ - op_arithf_aux(L, v1, v2, fop); } - - -/* -** Arithmetic operations with K operands for floats. -*/ -#define op_arithfK(L,fop) { \ - StkId ra = RA(i); \ - TValue *v1 = vRB(i); \ - TValue *v2 = KC(i); lua_assert(ttisnumber(v2)); \ - op_arithf_aux(L, v1, v2, fop); } - - -/* -** Arithmetic operations over integers and floats. -*/ -#define op_arith_aux(L,v1,v2,iop,fop) { \ - StkId ra = RA(i); \ - if (ttisinteger(v1) && ttisinteger(v2)) { \ - lua_Integer i1 = ivalue(v1); lua_Integer i2 = ivalue(v2); \ - pc++; setivalue(s2v(ra), iop(L, i1, i2)); \ - } \ - else op_arithf_aux(L, v1, v2, fop); } - - -/* -** Arithmetic operations with register operands. -*/ -#define op_arith(L,iop,fop) { \ - TValue *v1 = vRB(i); \ - TValue *v2 = vRC(i); \ - op_arith_aux(L, v1, v2, iop, fop); } - - -/* -** Arithmetic operations with K operands. -*/ -#define op_arithK(L,iop,fop) { \ - TValue *v1 = vRB(i); \ - TValue *v2 = KC(i); lua_assert(ttisnumber(v2)); \ - op_arith_aux(L, v1, v2, iop, fop); } - - -/* -** Bitwise operations with constant operand. -*/ -#define op_bitwiseK(L,op) { \ - StkId ra = RA(i); \ - TValue *v1 = vRB(i); \ - TValue *v2 = KC(i); \ - lua_Integer i1; \ - lua_Integer i2 = ivalue(v2); \ - if (tointegerns(v1, &i1)) { \ - pc++; setivalue(s2v(ra), op(i1, i2)); \ - }} - - -/* -** Bitwise operations with register operands. -*/ -#define op_bitwise(L,op) { \ - StkId ra = RA(i); \ - TValue *v1 = vRB(i); \ - TValue *v2 = vRC(i); \ - lua_Integer i1; lua_Integer i2; \ - if (tointegerns(v1, &i1) && tointegerns(v2, &i2)) { \ - pc++; setivalue(s2v(ra), op(i1, i2)); \ - }} - - -/* -** Order operations with register operands. 'opn' actually works -** for all numbers, but the fast track improves performance for -** integers. -*/ -#define op_order(L,opi,opn,other) { \ - StkId ra = RA(i); \ - int cond; \ - TValue *rb = vRB(i); \ - if (ttisinteger(s2v(ra)) && ttisinteger(rb)) { \ - lua_Integer ia = ivalue(s2v(ra)); \ - lua_Integer ib = ivalue(rb); \ - cond = opi(ia, ib); \ - } \ - else if (ttisnumber(s2v(ra)) && ttisnumber(rb)) \ - cond = opn(s2v(ra), rb); \ - else \ - Protect(cond = other(L, s2v(ra), rb)); \ - docondjump(); } - - -/* -** Order operations with immediate operand. (Immediate operand is -** always small enough to have an exact representation as a float.) -*/ -#define op_orderI(L,opi,opf,inv,tm) { \ - StkId ra = RA(i); \ - int cond; \ - int im = GETARG_sB(i); \ - if (ttisinteger(s2v(ra))) \ - cond = opi(ivalue(s2v(ra)), im); \ - else if (ttisfloat(s2v(ra))) { \ - lua_Number fa = fltvalue(s2v(ra)); \ - lua_Number fim = cast_num(im); \ - cond = opf(fa, fim); \ - } \ - else { \ - int isf = GETARG_C(i); \ - Protect(cond = luaT_callorderiTM(L, s2v(ra), im, inv, isf, tm)); \ - } \ - docondjump(); } - -/* }================================================================== */ - - -/* -** {================================================================== -** Function 'luaV_execute': main interpreter loop -** =================================================================== -*/ - -/* -** some macros for common tasks in 'luaV_execute' -*/ - - -#define RA(i) (base+GETARG_A(i)) -#define RB(i) (base+GETARG_B(i)) -#define vRB(i) s2v(RB(i)) -#define KB(i) (k+GETARG_B(i)) -#define RC(i) (base+GETARG_C(i)) -#define vRC(i) s2v(RC(i)) -#define KC(i) (k+GETARG_C(i)) -#define RKC(i) ((TESTARG_k(i)) ? k + GETARG_C(i) : s2v(base + GETARG_C(i))) - - - -#define updatetrap(ci) (trap = ci->u.l.trap) - -#define updatebase(ci) (base = ci->func.p + 1) - - -#define updatestack(ci) \ - { if (l_unlikely(trap)) { updatebase(ci); ra = RA(i); } } - - -/* -** Execute a jump instruction. The 'updatetrap' allows signals to stop -** tight loops. (Without it, the local copy of 'trap' could never change.) -*/ -#define dojump(ci,i,e) { pc += GETARG_sJ(i) + e; updatetrap(ci); } - - -/* for test instructions, execute the jump instruction that follows it */ -#define donextjump(ci) { Instruction ni = *pc; dojump(ci, ni, 1); } - -/* -** do a conditional jump: skip next instruction if 'cond' is not what -** was expected (parameter 'k'), else do next instruction, which must -** be a jump. -*/ -#define docondjump() if (cond != GETARG_k(i)) pc++; else donextjump(ci); - - -/* -** Correct global 'pc'. -*/ -#define savepc(L) (ci->u.l.savedpc = pc) - - -/* -** Whenever code can raise errors, the global 'pc' and the global -** 'top' must be correct to report occasional errors. -*/ -#define savestate(L,ci) (savepc(L), L->top.p = ci->top.p) - - -/* -** Protect code that, in general, can raise errors, reallocate the -** stack, and change the hooks. -*/ -#define Protect(exp) (savestate(L,ci), (exp), updatetrap(ci)) - -/* special version that does not change the top */ -#define ProtectNT(exp) (savepc(L), (exp), updatetrap(ci)) - -/* -** Protect code that can only raise errors. (That is, it cannot change -** the stack or hooks.) -*/ -#define halfProtect(exp) (savestate(L,ci), (exp)) - -/* 'c' is the limit of live values in the stack */ -#define checkGC(L,c) \ - { luaC_condGC(L, (savepc(L), L->top.p = (c)), \ - updatetrap(ci)); \ - luai_threadyield(L); } - - -/* fetch an instruction and prepare its execution */ -#define vmfetch() { \ - if (l_unlikely(trap)) { /* stack reallocation or hooks? */ \ - trap = luaG_traceexec(L, pc); /* handle hooks */ \ - updatebase(ci); /* correct stack */ \ - } \ - i = *(pc++); \ -} - -#define vmdispatch(o) switch(o) -#define vmcase(l) case l: -#define vmbreak break - - -void luaV_execute (lua_State *L, CallInfo *ci) { - LClosure *cl; - TValue *k; - StkId base; - const Instruction *pc; - int trap; -#if LUA_USE_JUMPTABLE -#include "ljumptab.h" -#endif - startfunc: - trap = L->hookmask; - returning: /* trap already set */ - cl = clLvalue(s2v(ci->func.p)); - k = cl->p->k; - pc = ci->u.l.savedpc; - if (l_unlikely(trap)) { - if (pc == cl->p->code) { /* first instruction (not resuming)? */ - if (cl->p->is_vararg) - trap = 0; /* hooks will start after VARARGPREP instruction */ - else /* check 'call' hook */ - luaD_hookcall(L, ci); - } - ci->u.l.trap = 1; /* assume trap is on, for now */ - } - base = ci->func.p + 1; - /* main loop of interpreter */ - for (;;) { - Instruction i; /* instruction being executed */ - vmfetch(); - #if 0 - /* low-level line tracing for debugging Lua */ - printf("line: %d\n", luaG_getfuncline(cl->p, pcRel(pc, cl->p))); - #endif - lua_assert(base == ci->func.p + 1); - lua_assert(base <= L->top.p && L->top.p <= L->stack_last.p); - /* invalidate top for instructions not expecting it */ - lua_assert(isIT(i) || (cast_void(L->top.p = base), 1)); - vmdispatch (GET_OPCODE(i)) { - vmcase(OP_MOVE) { - StkId ra = RA(i); - setobjs2s(L, ra, RB(i)); - vmbreak; - } - vmcase(OP_LOADI) { - StkId ra = RA(i); - lua_Integer b = GETARG_sBx(i); - setivalue(s2v(ra), b); - vmbreak; - } - vmcase(OP_LOADF) { - StkId ra = RA(i); - int b = GETARG_sBx(i); - setfltvalue(s2v(ra), cast_num(b)); - vmbreak; - } - vmcase(OP_LOADK) { - StkId ra = RA(i); - TValue *rb = k + GETARG_Bx(i); - setobj2s(L, ra, rb); - vmbreak; - } - vmcase(OP_LOADKX) { - StkId ra = RA(i); - TValue *rb; - rb = k + GETARG_Ax(*pc); pc++; - setobj2s(L, ra, rb); - vmbreak; - } - vmcase(OP_LOADFALSE) { - StkId ra = RA(i); - setbfvalue(s2v(ra)); - vmbreak; - } - vmcase(OP_LFALSESKIP) { - StkId ra = RA(i); - setbfvalue(s2v(ra)); - pc++; /* skip next instruction */ - vmbreak; - } - vmcase(OP_LOADTRUE) { - StkId ra = RA(i); - setbtvalue(s2v(ra)); - vmbreak; - } - vmcase(OP_LOADNIL) { - StkId ra = RA(i); - int b = GETARG_B(i); - do { - setnilvalue(s2v(ra++)); - } while (b--); - vmbreak; - } - vmcase(OP_GETUPVAL) { - StkId ra = RA(i); - int b = GETARG_B(i); - setobj2s(L, ra, cl->upvals[b]->v.p); - vmbreak; - } - vmcase(OP_SETUPVAL) { - StkId ra = RA(i); - UpVal *uv = cl->upvals[GETARG_B(i)]; - setobj(L, uv->v.p, s2v(ra)); - luaC_barrier(L, uv, s2v(ra)); - vmbreak; - } - vmcase(OP_GETTABUP) { - StkId ra = RA(i); - const TValue *slot; - TValue *upval = cl->upvals[GETARG_B(i)]->v.p; - TValue *rc = KC(i); - TString *key = tsvalue(rc); /* key must be a string */ - if (luaV_fastget(L, upval, key, slot, luaH_getshortstr)) { - setobj2s(L, ra, slot); - } - else - Protect(luaV_finishget(L, upval, rc, ra, slot)); - vmbreak; - } - vmcase(OP_GETTABLE) { - StkId ra = RA(i); - const TValue *slot; - TValue *rb = vRB(i); - TValue *rc = vRC(i); - lua_Unsigned n; - if (ttisinteger(rc) /* fast track for integers? */ - ? (cast_void(n = ivalue(rc)), luaV_fastgeti(L, rb, n, slot)) - : luaV_fastget(L, rb, rc, slot, luaH_get)) { - setobj2s(L, ra, slot); - } - else - Protect(luaV_finishget(L, rb, rc, ra, slot)); - vmbreak; - } - vmcase(OP_GETI) { - StkId ra = RA(i); - const TValue *slot; - TValue *rb = vRB(i); - int c = GETARG_C(i); - if (luaV_fastgeti(L, rb, c, slot)) { - setobj2s(L, ra, slot); - } - else { - TValue key; - setivalue(&key, c); - Protect(luaV_finishget(L, rb, &key, ra, slot)); - } - vmbreak; - } - vmcase(OP_GETFIELD) { - StkId ra = RA(i); - const TValue *slot; - TValue *rb = vRB(i); - TValue *rc = KC(i); - TString *key = tsvalue(rc); /* key must be a string */ - if (luaV_fastget(L, rb, key, slot, luaH_getshortstr)) { - setobj2s(L, ra, slot); - } - else - Protect(luaV_finishget(L, rb, rc, ra, slot)); - vmbreak; - } - vmcase(OP_SETTABUP) { - const TValue *slot; - TValue *upval = cl->upvals[GETARG_A(i)]->v.p; - TValue *rb = KB(i); - TValue *rc = RKC(i); - TString *key = tsvalue(rb); /* key must be a string */ - if (luaV_fastget(L, upval, key, slot, luaH_getshortstr)) { - luaV_finishfastset(L, upval, slot, rc); - } - else - Protect(luaV_finishset(L, upval, rb, rc, slot)); - vmbreak; - } - vmcase(OP_SETTABLE) { - StkId ra = RA(i); - const TValue *slot; - TValue *rb = vRB(i); /* key (table is in 'ra') */ - TValue *rc = RKC(i); /* value */ - lua_Unsigned n; - if (ttisinteger(rb) /* fast track for integers? */ - ? (cast_void(n = ivalue(rb)), luaV_fastgeti(L, s2v(ra), n, slot)) - : luaV_fastget(L, s2v(ra), rb, slot, luaH_get)) { - luaV_finishfastset(L, s2v(ra), slot, rc); - } - else - Protect(luaV_finishset(L, s2v(ra), rb, rc, slot)); - vmbreak; - } - vmcase(OP_SETI) { - StkId ra = RA(i); - const TValue *slot; - int c = GETARG_B(i); - TValue *rc = RKC(i); - if (luaV_fastgeti(L, s2v(ra), c, slot)) { - luaV_finishfastset(L, s2v(ra), slot, rc); - } - else { - TValue key; - setivalue(&key, c); - Protect(luaV_finishset(L, s2v(ra), &key, rc, slot)); - } - vmbreak; - } - vmcase(OP_SETFIELD) { - StkId ra = RA(i); - const TValue *slot; - TValue *rb = KB(i); - TValue *rc = RKC(i); - TString *key = tsvalue(rb); /* key must be a string */ - if (luaV_fastget(L, s2v(ra), key, slot, luaH_getshortstr)) { - luaV_finishfastset(L, s2v(ra), slot, rc); - } - else - Protect(luaV_finishset(L, s2v(ra), rb, rc, slot)); - vmbreak; - } - vmcase(OP_NEWTABLE) { - StkId ra = RA(i); - int b = GETARG_B(i); /* log2(hash size) + 1 */ - int c = GETARG_C(i); /* array size */ - Table *t; - if (b > 0) - b = 1 << (b - 1); /* size is 2^(b - 1) */ - lua_assert((!TESTARG_k(i)) == (GETARG_Ax(*pc) == 0)); - if (TESTARG_k(i)) /* non-zero extra argument? */ - c += GETARG_Ax(*pc) * (MAXARG_C + 1); /* add it to size */ - pc++; /* skip extra argument */ - L->top.p = ra + 1; /* correct top in case of emergency GC */ - t = luaH_new(L); /* memory allocation */ - sethvalue2s(L, ra, t); - if (b != 0 || c != 0) - luaH_resize(L, t, c, b); /* idem */ - checkGC(L, ra + 1); - vmbreak; - } - vmcase(OP_SELF) { - StkId ra = RA(i); - const TValue *slot; - TValue *rb = vRB(i); - TValue *rc = RKC(i); - TString *key = tsvalue(rc); /* key must be a string */ - setobj2s(L, ra + 1, rb); - if (luaV_fastget(L, rb, key, slot, luaH_getstr)) { - setobj2s(L, ra, slot); - } - else - Protect(luaV_finishget(L, rb, rc, ra, slot)); - vmbreak; - } - vmcase(OP_ADDI) { - op_arithI(L, l_addi, luai_numadd); - vmbreak; - } - vmcase(OP_ADDK) { - op_arithK(L, l_addi, luai_numadd); - vmbreak; - } - vmcase(OP_SUBK) { - op_arithK(L, l_subi, luai_numsub); - vmbreak; - } - vmcase(OP_MULK) { - op_arithK(L, l_muli, luai_nummul); - vmbreak; - } - vmcase(OP_MODK) { - savestate(L, ci); /* in case of division by 0 */ - op_arithK(L, luaV_mod, luaV_modf); - vmbreak; - } - vmcase(OP_POWK) { - op_arithfK(L, luai_numpow); - vmbreak; - } - vmcase(OP_DIVK) { - op_arithfK(L, luai_numdiv); - vmbreak; - } - vmcase(OP_IDIVK) { - savestate(L, ci); /* in case of division by 0 */ - op_arithK(L, luaV_idiv, luai_numidiv); - vmbreak; - } - vmcase(OP_BANDK) { - op_bitwiseK(L, l_band); - vmbreak; - } - vmcase(OP_BORK) { - op_bitwiseK(L, l_bor); - vmbreak; - } - vmcase(OP_BXORK) { - op_bitwiseK(L, l_bxor); - vmbreak; - } - vmcase(OP_SHRI) { - StkId ra = RA(i); - TValue *rb = vRB(i); - int ic = GETARG_sC(i); - lua_Integer ib; - if (tointegerns(rb, &ib)) { - pc++; setivalue(s2v(ra), luaV_shiftl(ib, -ic)); - } - vmbreak; - } - vmcase(OP_SHLI) { - StkId ra = RA(i); - TValue *rb = vRB(i); - int ic = GETARG_sC(i); - lua_Integer ib; - if (tointegerns(rb, &ib)) { - pc++; setivalue(s2v(ra), luaV_shiftl(ic, ib)); - } - vmbreak; - } - vmcase(OP_ADD) { - op_arith(L, l_addi, luai_numadd); - vmbreak; - } - vmcase(OP_SUB) { - op_arith(L, l_subi, luai_numsub); - vmbreak; - } - vmcase(OP_MUL) { - op_arith(L, l_muli, luai_nummul); - vmbreak; - } - vmcase(OP_MOD) { - savestate(L, ci); /* in case of division by 0 */ - op_arith(L, luaV_mod, luaV_modf); - vmbreak; - } - vmcase(OP_POW) { - op_arithf(L, luai_numpow); - vmbreak; - } - vmcase(OP_DIV) { /* float division (always with floats) */ - op_arithf(L, luai_numdiv); - vmbreak; - } - vmcase(OP_IDIV) { /* floor division */ - savestate(L, ci); /* in case of division by 0 */ - op_arith(L, luaV_idiv, luai_numidiv); - vmbreak; - } - vmcase(OP_BAND) { - op_bitwise(L, l_band); - vmbreak; - } - vmcase(OP_BOR) { - op_bitwise(L, l_bor); - vmbreak; - } - vmcase(OP_BXOR) { - op_bitwise(L, l_bxor); - vmbreak; - } - vmcase(OP_SHR) { - op_bitwise(L, luaV_shiftr); - vmbreak; - } - vmcase(OP_SHL) { - op_bitwise(L, luaV_shiftl); - vmbreak; - } - vmcase(OP_MMBIN) { - StkId ra = RA(i); - Instruction pi = *(pc - 2); /* original arith. expression */ - TValue *rb = vRB(i); - TMS tm = (TMS)GETARG_C(i); - StkId result = RA(pi); - lua_assert(OP_ADD <= GET_OPCODE(pi) && GET_OPCODE(pi) <= OP_SHR); - Protect(luaT_trybinTM(L, s2v(ra), rb, result, tm)); - vmbreak; - } - vmcase(OP_MMBINI) { - StkId ra = RA(i); - Instruction pi = *(pc - 2); /* original arith. expression */ - int imm = GETARG_sB(i); - TMS tm = (TMS)GETARG_C(i); - int flip = GETARG_k(i); - StkId result = RA(pi); - Protect(luaT_trybiniTM(L, s2v(ra), imm, flip, result, tm)); - vmbreak; - } - vmcase(OP_MMBINK) { - StkId ra = RA(i); - Instruction pi = *(pc - 2); /* original arith. expression */ - TValue *imm = KB(i); - TMS tm = (TMS)GETARG_C(i); - int flip = GETARG_k(i); - StkId result = RA(pi); - Protect(luaT_trybinassocTM(L, s2v(ra), imm, flip, result, tm)); - vmbreak; - } - vmcase(OP_UNM) { - StkId ra = RA(i); - TValue *rb = vRB(i); - lua_Number nb; - if (ttisinteger(rb)) { - lua_Integer ib = ivalue(rb); - setivalue(s2v(ra), intop(-, 0, ib)); - } - else if (tonumberns(rb, nb)) { - setfltvalue(s2v(ra), luai_numunm(L, nb)); - } - else - Protect(luaT_trybinTM(L, rb, rb, ra, TM_UNM)); - vmbreak; - } - vmcase(OP_BNOT) { - StkId ra = RA(i); - TValue *rb = vRB(i); - lua_Integer ib; - if (tointegerns(rb, &ib)) { - setivalue(s2v(ra), intop(^, ~l_castS2U(0), ib)); - } - else - Protect(luaT_trybinTM(L, rb, rb, ra, TM_BNOT)); - vmbreak; - } - vmcase(OP_NOT) { - StkId ra = RA(i); - TValue *rb = vRB(i); - if (l_isfalse(rb)) - setbtvalue(s2v(ra)); - else - setbfvalue(s2v(ra)); - vmbreak; - } - vmcase(OP_LEN) { - StkId ra = RA(i); - Protect(luaV_objlen(L, ra, vRB(i))); - vmbreak; - } - vmcase(OP_CONCAT) { - StkId ra = RA(i); - int n = GETARG_B(i); /* number of elements to concatenate */ - L->top.p = ra + n; /* mark the end of concat operands */ - ProtectNT(luaV_concat(L, n)); - checkGC(L, L->top.p); /* 'luaV_concat' ensures correct top */ - vmbreak; - } - vmcase(OP_CLOSE) { - StkId ra = RA(i); - Protect(luaF_close(L, ra, LUA_OK, 1)); - vmbreak; - } - vmcase(OP_TBC) { - StkId ra = RA(i); - /* create new to-be-closed upvalue */ - halfProtect(luaF_newtbcupval(L, ra)); - vmbreak; - } - vmcase(OP_JMP) { - dojump(ci, i, 0); - vmbreak; - } - vmcase(OP_EQ) { - StkId ra = RA(i); - int cond; - TValue *rb = vRB(i); - Protect(cond = luaV_equalobj(L, s2v(ra), rb)); - docondjump(); - vmbreak; - } - vmcase(OP_LT) { - op_order(L, l_lti, LTnum, lessthanothers); - vmbreak; - } - vmcase(OP_LE) { - op_order(L, l_lei, LEnum, lessequalothers); - vmbreak; - } - vmcase(OP_EQK) { - StkId ra = RA(i); - TValue *rb = KB(i); - /* basic types do not use '__eq'; we can use raw equality */ - int cond = luaV_rawequalobj(s2v(ra), rb); - docondjump(); - vmbreak; - } - vmcase(OP_EQI) { - StkId ra = RA(i); - int cond; - int im = GETARG_sB(i); - if (ttisinteger(s2v(ra))) - cond = (ivalue(s2v(ra)) == im); - else if (ttisfloat(s2v(ra))) - cond = luai_numeq(fltvalue(s2v(ra)), cast_num(im)); - else - cond = 0; /* other types cannot be equal to a number */ - docondjump(); - vmbreak; - } - vmcase(OP_LTI) { - op_orderI(L, l_lti, luai_numlt, 0, TM_LT); - vmbreak; - } - vmcase(OP_LEI) { - op_orderI(L, l_lei, luai_numle, 0, TM_LE); - vmbreak; - } - vmcase(OP_GTI) { - op_orderI(L, l_gti, luai_numgt, 1, TM_LT); - vmbreak; - } - vmcase(OP_GEI) { - op_orderI(L, l_gei, luai_numge, 1, TM_LE); - vmbreak; - } - vmcase(OP_TEST) { - StkId ra = RA(i); - int cond = !l_isfalse(s2v(ra)); - docondjump(); - vmbreak; - } - vmcase(OP_TESTSET) { - StkId ra = RA(i); - TValue *rb = vRB(i); - if (l_isfalse(rb) == GETARG_k(i)) - pc++; - else { - setobj2s(L, ra, rb); - donextjump(ci); - } - vmbreak; - } - vmcase(OP_CALL) { - StkId ra = RA(i); - CallInfo *newci; - int b = GETARG_B(i); - int nresults = GETARG_C(i) - 1; - if (b != 0) /* fixed number of arguments? */ - L->top.p = ra + b; /* top signals number of arguments */ - /* else previous instruction set top */ - savepc(L); /* in case of errors */ - if ((newci = luaD_precall(L, ra, nresults)) == NULL) - updatetrap(ci); /* C call; nothing else to be done */ - else { /* Lua call: run function in this same C frame */ - ci = newci; - goto startfunc; - } - vmbreak; - } - vmcase(OP_TAILCALL) { - StkId ra = RA(i); - int b = GETARG_B(i); /* number of arguments + 1 (function) */ - int n; /* number of results when calling a C function */ - int nparams1 = GETARG_C(i); - /* delta is virtual 'func' - real 'func' (vararg functions) */ - int delta = (nparams1) ? ci->u.l.nextraargs + nparams1 : 0; - if (b != 0) - L->top.p = ra + b; - else /* previous instruction set top */ - b = cast_int(L->top.p - ra); - savepc(ci); /* several calls here can raise errors */ - if (TESTARG_k(i)) { - luaF_closeupval(L, base); /* close upvalues from current call */ - lua_assert(L->tbclist.p < base); /* no pending tbc variables */ - lua_assert(base == ci->func.p + 1); - } - if ((n = luaD_pretailcall(L, ci, ra, b, delta)) < 0) /* Lua function? */ - goto startfunc; /* execute the callee */ - else { /* C function? */ - ci->func.p -= delta; /* restore 'func' (if vararg) */ - luaD_poscall(L, ci, n); /* finish caller */ - updatetrap(ci); /* 'luaD_poscall' can change hooks */ - goto ret; /* caller returns after the tail call */ - } - } - vmcase(OP_RETURN) { - StkId ra = RA(i); - int n = GETARG_B(i) - 1; /* number of results */ - int nparams1 = GETARG_C(i); - if (n < 0) /* not fixed? */ - n = cast_int(L->top.p - ra); /* get what is available */ - savepc(ci); - if (TESTARG_k(i)) { /* may there be open upvalues? */ - ci->u2.nres = n; /* save number of returns */ - if (L->top.p < ci->top.p) - L->top.p = ci->top.p; - luaF_close(L, base, CLOSEKTOP, 1); - updatetrap(ci); - updatestack(ci); - } - if (nparams1) /* vararg function? */ - ci->func.p -= ci->u.l.nextraargs + nparams1; - L->top.p = ra + n; /* set call for 'luaD_poscall' */ - luaD_poscall(L, ci, n); - updatetrap(ci); /* 'luaD_poscall' can change hooks */ - goto ret; - } - vmcase(OP_RETURN0) { - if (l_unlikely(L->hookmask)) { - StkId ra = RA(i); - L->top.p = ra; - savepc(ci); - luaD_poscall(L, ci, 0); /* no hurry... */ - trap = 1; - } - else { /* do the 'poscall' here */ - int nres; - L->ci = ci->previous; /* back to caller */ - L->top.p = base - 1; - for (nres = ci->nresults; l_unlikely(nres > 0); nres--) - setnilvalue(s2v(L->top.p++)); /* all results are nil */ - } - goto ret; - } - vmcase(OP_RETURN1) { - if (l_unlikely(L->hookmask)) { - StkId ra = RA(i); - L->top.p = ra + 1; - savepc(ci); - luaD_poscall(L, ci, 1); /* no hurry... */ - trap = 1; - } - else { /* do the 'poscall' here */ - int nres = ci->nresults; - L->ci = ci->previous; /* back to caller */ - if (nres == 0) - L->top.p = base - 1; /* asked for no results */ - else { - StkId ra = RA(i); - setobjs2s(L, base - 1, ra); /* at least this result */ - L->top.p = base; - for (; l_unlikely(nres > 1); nres--) - setnilvalue(s2v(L->top.p++)); /* complete missing results */ - } - } - ret: /* return from a Lua function */ - if (ci->callstatus & CIST_FRESH) - return; /* end this frame */ - else { - ci = ci->previous; - goto returning; /* continue running caller in this frame */ - } - } - vmcase(OP_FORLOOP) { - StkId ra = RA(i); - if (ttisinteger(s2v(ra + 2))) { /* integer loop? */ - lua_Unsigned count = l_castS2U(ivalue(s2v(ra + 1))); - if (count > 0) { /* still more iterations? */ - lua_Integer step = ivalue(s2v(ra + 2)); - lua_Integer idx = ivalue(s2v(ra)); /* internal index */ - chgivalue(s2v(ra + 1), count - 1); /* update counter */ - idx = intop(+, idx, step); /* add step to index */ - chgivalue(s2v(ra), idx); /* update internal index */ - setivalue(s2v(ra + 3), idx); /* and control variable */ - pc -= GETARG_Bx(i); /* jump back */ - } - } - else if (floatforloop(ra)) /* float loop */ - pc -= GETARG_Bx(i); /* jump back */ - updatetrap(ci); /* allows a signal to break the loop */ - vmbreak; - } - vmcase(OP_FORPREP) { - StkId ra = RA(i); - savestate(L, ci); /* in case of errors */ - if (forprep(L, ra)) - pc += GETARG_Bx(i) + 1; /* skip the loop */ - vmbreak; - } - vmcase(OP_TFORPREP) { - StkId ra = RA(i); - /* create to-be-closed upvalue (if needed) */ - halfProtect(luaF_newtbcupval(L, ra + 3)); - pc += GETARG_Bx(i); - i = *(pc++); /* go to next instruction */ - lua_assert(GET_OPCODE(i) == OP_TFORCALL && ra == RA(i)); - goto l_tforcall; - } - vmcase(OP_TFORCALL) { - l_tforcall: { - StkId ra = RA(i); - /* 'ra' has the iterator function, 'ra + 1' has the state, - 'ra + 2' has the control variable, and 'ra + 3' has the - to-be-closed variable. The call will use the stack after - these values (starting at 'ra + 4') - */ - /* push function, state, and control variable */ - memcpy(ra + 4, ra, 3 * sizeof(*ra)); - L->top.p = ra + 4 + 3; - ProtectNT(luaD_call(L, ra + 4, GETARG_C(i))); /* do the call */ - updatestack(ci); /* stack may have changed */ - i = *(pc++); /* go to next instruction */ - lua_assert(GET_OPCODE(i) == OP_TFORLOOP && ra == RA(i)); - goto l_tforloop; - }} - vmcase(OP_TFORLOOP) { - l_tforloop: { - StkId ra = RA(i); - if (!ttisnil(s2v(ra + 4))) { /* continue loop? */ - setobjs2s(L, ra + 2, ra + 4); /* save control variable */ - pc -= GETARG_Bx(i); /* jump back */ - } - vmbreak; - }} - vmcase(OP_SETLIST) { - StkId ra = RA(i); - int n = GETARG_B(i); - unsigned int last = GETARG_C(i); - Table *h = hvalue(s2v(ra)); - if (n == 0) - n = cast_int(L->top.p - ra) - 1; /* get up to the top */ - else - L->top.p = ci->top.p; /* correct top in case of emergency GC */ - last += n; - if (TESTARG_k(i)) { - last += GETARG_Ax(*pc) * (MAXARG_C + 1); - pc++; - } - if (last > luaH_realasize(h)) /* needs more space? */ - luaH_resizearray(L, h, last); /* preallocate it at once */ - for (; n > 0; n--) { - TValue *val = s2v(ra + n); - setobj2t(L, &h->array[last - 1], val); - last--; - luaC_barrierback(L, obj2gco(h), val); - } - vmbreak; - } - vmcase(OP_CLOSURE) { - StkId ra = RA(i); - Proto *p = cl->p->p[GETARG_Bx(i)]; - halfProtect(pushclosure(L, p, cl->upvals, base, ra)); - checkGC(L, ra + 1); - vmbreak; - } - vmcase(OP_VARARG) { - StkId ra = RA(i); - int n = GETARG_C(i) - 1; /* required results */ - Protect(luaT_getvarargs(L, ci, ra, n)); - vmbreak; - } - vmcase(OP_VARARGPREP) { - ProtectNT(luaT_adjustvarargs(L, GETARG_A(i), ci, cl->p)); - if (l_unlikely(trap)) { /* previous "Protect" updated trap */ - luaD_hookcall(L, ci); - L->oldpc = 1; /* next opcode will be seen as a "new" line */ - } - updatebase(ci); /* function has new base after adjustment */ - vmbreak; - } - vmcase(OP_EXTRAARG) { - lua_assert(0); - vmbreak; - } - } - } -} - -/* }================================================================== */ diff --git a/lib/lua-5.4/src/lvm.h b/lib/lua-5.4/src/lvm.h deleted file mode 100644 index dba1ad2..0000000 --- a/lib/lua-5.4/src/lvm.h +++ /dev/null @@ -1,141 +0,0 @@ -/* -** $Id: lvm.h $ -** Lua virtual machine -** See Copyright Notice in lua.h -*/ - -#ifndef lvm_h -#define lvm_h - - -#include "ldo.h" -#include "lobject.h" -#include "ltm.h" - - -#if !defined(LUA_NOCVTN2S) -#define cvt2str(o) ttisnumber(o) -#else -#define cvt2str(o) 0 /* no conversion from numbers to strings */ -#endif - - -#if !defined(LUA_NOCVTS2N) -#define cvt2num(o) ttisstring(o) -#else -#define cvt2num(o) 0 /* no conversion from strings to numbers */ -#endif - - -/* -** You can define LUA_FLOORN2I if you want to convert floats to integers -** by flooring them (instead of raising an error if they are not -** integral values) -*/ -#if !defined(LUA_FLOORN2I) -#define LUA_FLOORN2I F2Ieq -#endif - - -/* -** Rounding modes for float->integer coercion - */ -typedef enum { - F2Ieq, /* no rounding; accepts only integral values */ - F2Ifloor, /* takes the floor of the number */ - F2Iceil /* takes the ceil of the number */ -} F2Imod; - - -/* convert an object to a float (including string coercion) */ -#define tonumber(o,n) \ - (ttisfloat(o) ? (*(n) = fltvalue(o), 1) : luaV_tonumber_(o,n)) - - -/* convert an object to a float (without string coercion) */ -#define tonumberns(o,n) \ - (ttisfloat(o) ? ((n) = fltvalue(o), 1) : \ - (ttisinteger(o) ? ((n) = cast_num(ivalue(o)), 1) : 0)) - - -/* convert an object to an integer (including string coercion) */ -#define tointeger(o,i) \ - (l_likely(ttisinteger(o)) ? (*(i) = ivalue(o), 1) \ - : luaV_tointeger(o,i,LUA_FLOORN2I)) - - -/* convert an object to an integer (without string coercion) */ -#define tointegerns(o,i) \ - (l_likely(ttisinteger(o)) ? (*(i) = ivalue(o), 1) \ - : luaV_tointegerns(o,i,LUA_FLOORN2I)) - - -#define intop(op,v1,v2) l_castU2S(l_castS2U(v1) op l_castS2U(v2)) - -#define luaV_rawequalobj(t1,t2) luaV_equalobj(NULL,t1,t2) - - -/* -** fast track for 'gettable': if 't' is a table and 't[k]' is present, -** return 1 with 'slot' pointing to 't[k]' (position of final result). -** Otherwise, return 0 (meaning it will have to check metamethod) -** with 'slot' pointing to an empty 't[k]' (if 't' is a table) or NULL -** (otherwise). 'f' is the raw get function to use. -*/ -#define luaV_fastget(L,t,k,slot,f) \ - (!ttistable(t) \ - ? (slot = NULL, 0) /* not a table; 'slot' is NULL and result is 0 */ \ - : (slot = f(hvalue(t), k), /* else, do raw access */ \ - !isempty(slot))) /* result not empty? */ - - -/* -** Special case of 'luaV_fastget' for integers, inlining the fast case -** of 'luaH_getint'. -*/ -#define luaV_fastgeti(L,t,k,slot) \ - (!ttistable(t) \ - ? (slot = NULL, 0) /* not a table; 'slot' is NULL and result is 0 */ \ - : (slot = (l_castS2U(k) - 1u < hvalue(t)->alimit) \ - ? &hvalue(t)->array[k - 1] : luaH_getint(hvalue(t), k), \ - !isempty(slot))) /* result not empty? */ - - -/* -** Finish a fast set operation (when fast get succeeds). In that case, -** 'slot' points to the place to put the value. -*/ -#define luaV_finishfastset(L,t,slot,v) \ - { setobj2t(L, cast(TValue *,slot), v); \ - luaC_barrierback(L, gcvalue(t), v); } - - -/* -** Shift right is the same as shift left with a negative 'y' -*/ -#define luaV_shiftr(x,y) luaV_shiftl(x,intop(-, 0, y)) - - - -LUAI_FUNC int luaV_equalobj (lua_State *L, const TValue *t1, const TValue *t2); -LUAI_FUNC int luaV_lessthan (lua_State *L, const TValue *l, const TValue *r); -LUAI_FUNC int luaV_lessequal (lua_State *L, const TValue *l, const TValue *r); -LUAI_FUNC int luaV_tonumber_ (const TValue *obj, lua_Number *n); -LUAI_FUNC int luaV_tointeger (const TValue *obj, lua_Integer *p, F2Imod mode); -LUAI_FUNC int luaV_tointegerns (const TValue *obj, lua_Integer *p, - F2Imod mode); -LUAI_FUNC int luaV_flttointeger (lua_Number n, lua_Integer *p, F2Imod mode); -LUAI_FUNC void luaV_finishget (lua_State *L, const TValue *t, TValue *key, - StkId val, const TValue *slot); -LUAI_FUNC void luaV_finishset (lua_State *L, const TValue *t, TValue *key, - TValue *val, const TValue *slot); -LUAI_FUNC void luaV_finishOp (lua_State *L); -LUAI_FUNC void luaV_execute (lua_State *L, CallInfo *ci); -LUAI_FUNC void luaV_concat (lua_State *L, int total); -LUAI_FUNC lua_Integer luaV_idiv (lua_State *L, lua_Integer x, lua_Integer y); -LUAI_FUNC lua_Integer luaV_mod (lua_State *L, lua_Integer x, lua_Integer y); -LUAI_FUNC lua_Number luaV_modf (lua_State *L, lua_Number x, lua_Number y); -LUAI_FUNC lua_Integer luaV_shiftl (lua_Integer x, lua_Integer y); -LUAI_FUNC void luaV_objlen (lua_State *L, StkId ra, const TValue *rb); - -#endif diff --git a/lib/lua-5.4/src/lzio.c b/lib/lua-5.4/src/lzio.c deleted file mode 100644 index cd0a02d..0000000 --- a/lib/lua-5.4/src/lzio.c +++ /dev/null @@ -1,68 +0,0 @@ -/* -** $Id: lzio.c $ -** Buffered streams -** See Copyright Notice in lua.h -*/ - -#define lzio_c -#define LUA_CORE - -#include "lprefix.h" - - -#include - -#include "lua.h" - -#include "llimits.h" -#include "lmem.h" -#include "lstate.h" -#include "lzio.h" - - -int luaZ_fill (ZIO *z) { - size_t size; - lua_State *L = z->L; - const char *buff; - lua_unlock(L); - buff = z->reader(L, z->data, &size); - lua_lock(L); - if (buff == NULL || size == 0) - return EOZ; - z->n = size - 1; /* discount char being returned */ - z->p = buff; - return cast_uchar(*(z->p++)); -} - - -void luaZ_init (lua_State *L, ZIO *z, lua_Reader reader, void *data) { - z->L = L; - z->reader = reader; - z->data = data; - z->n = 0; - z->p = NULL; -} - - -/* --------------------------------------------------------------- read --- */ -size_t luaZ_read (ZIO *z, void *b, size_t n) { - while (n) { - size_t m; - if (z->n == 0) { /* no bytes in buffer? */ - if (luaZ_fill(z) == EOZ) /* try to read more */ - return n; /* no more input; return number of missing bytes */ - else { - z->n++; /* luaZ_fill consumed first byte; put it back */ - z->p--; - } - } - m = (n <= z->n) ? n : z->n; /* min. between n and z->n */ - memcpy(b, z->p, m); - z->n -= m; - z->p += m; - b = (char *)b + m; - n -= m; - } - return 0; -} - diff --git a/lib/lua-5.4/src/lzio.h b/lib/lua-5.4/src/lzio.h deleted file mode 100644 index 38f397f..0000000 --- a/lib/lua-5.4/src/lzio.h +++ /dev/null @@ -1,66 +0,0 @@ -/* -** $Id: lzio.h $ -** Buffered streams -** See Copyright Notice in lua.h -*/ - - -#ifndef lzio_h -#define lzio_h - -#include "lua.h" - -#include "lmem.h" - - -#define EOZ (-1) /* end of stream */ - -typedef struct Zio ZIO; - -#define zgetc(z) (((z)->n--)>0 ? cast_uchar(*(z)->p++) : luaZ_fill(z)) - - -typedef struct Mbuffer { - char *buffer; - size_t n; - size_t buffsize; -} Mbuffer; - -#define luaZ_initbuffer(L, buff) ((buff)->buffer = NULL, (buff)->buffsize = 0) - -#define luaZ_buffer(buff) ((buff)->buffer) -#define luaZ_sizebuffer(buff) ((buff)->buffsize) -#define luaZ_bufflen(buff) ((buff)->n) - -#define luaZ_buffremove(buff,i) ((buff)->n -= (i)) -#define luaZ_resetbuffer(buff) ((buff)->n = 0) - - -#define luaZ_resizebuffer(L, buff, size) \ - ((buff)->buffer = luaM_reallocvchar(L, (buff)->buffer, \ - (buff)->buffsize, size), \ - (buff)->buffsize = size) - -#define luaZ_freebuffer(L, buff) luaZ_resizebuffer(L, buff, 0) - - -LUAI_FUNC void luaZ_init (lua_State *L, ZIO *z, lua_Reader reader, - void *data); -LUAI_FUNC size_t luaZ_read (ZIO* z, void *b, size_t n); /* read next n bytes */ - - - -/* --------- Private Part ------------------ */ - -struct Zio { - size_t n; /* bytes still unread */ - const char *p; /* current position in buffer */ - lua_Reader reader; /* reader function */ - void *data; /* additional data */ - lua_State *L; /* Lua state (for reader) */ -}; - - -LUAI_FUNC int luaZ_fill (ZIO *z); - -#endif diff --git a/makefile b/makefile index 6053dd0..6a478c7 100644 --- a/makefile +++ b/makefile @@ -1,10 +1,10 @@ .PHONY: docs test: - zig build test --summary failures -Dversion=lua_51 - zig build test --summary failures -Dversion=lua_52 - zig build test --summary failures -Dversion=lua_53 - zig build test --summary failures -Dversion=lua_54 + zig build test --summary failures -Dversion=lua51 + zig build test --summary failures -Dversion=lua52 + zig build test --summary failures -Dversion=lua53 + zig build test --summary failures -Dversion=lua54 zig build test --summary failures -Dversion=luau zig build install-example-interpreter diff --git a/src/ziglua-5.1/lib.zig b/src/ziglua-5.1/lib.zig index 3d9311f..8531d24 100644 --- a/src/ziglua-5.1/lib.zig +++ b/src/ziglua-5.1/lib.zig @@ -4,9 +4,9 @@ const std = @import("std"); const c = @cImport({ - @cInclude("lua/lua.h"); - @cInclude("lua/lualib.h"); - @cInclude("lua/lauxlib.h"); + @cInclude("lua.h"); + @cInclude("lualib.h"); + @cInclude("lauxlib.h"); }); const Allocator = std.mem.Allocator; diff --git a/src/ziglua-5.1/tests.zig b/src/ziglua-5.1/tests.zig index 3d7a54f..db03397 100644 --- a/src/ziglua-5.1/tests.zig +++ b/src/ziglua-5.1/tests.zig @@ -1,6 +1,6 @@ const std = @import("std"); const testing = std.testing; -const ziglua = @import("lib.zig"); +const ziglua = @import("ziglua"); const AllocFn = ziglua.AllocFn; const Buffer = ziglua.Buffer; diff --git a/src/ziglua-5.2/lib.zig b/src/ziglua-5.2/lib.zig index ce0354a..b88b1e3 100644 --- a/src/ziglua-5.2/lib.zig +++ b/src/ziglua-5.2/lib.zig @@ -4,9 +4,9 @@ const std = @import("std"); const c = @cImport({ - @cInclude("lua/lua.h"); - @cInclude("lua/lualib.h"); - @cInclude("lua/lauxlib.h"); + @cInclude("lua.h"); + @cInclude("lualib.h"); + @cInclude("lauxlib.h"); }); const Allocator = std.mem.Allocator; diff --git a/src/ziglua-5.2/tests.zig b/src/ziglua-5.2/tests.zig index 9b18fce..09d5b82 100644 --- a/src/ziglua-5.2/tests.zig +++ b/src/ziglua-5.2/tests.zig @@ -1,6 +1,6 @@ const std = @import("std"); const testing = std.testing; -const ziglua = @import("lib.zig"); +const ziglua = @import("ziglua"); const AllocFn = ziglua.AllocFn; const Buffer = ziglua.Buffer; diff --git a/src/ziglua-5.3/lib.zig b/src/ziglua-5.3/lib.zig index bd7b957..cdd2b4d 100644 --- a/src/ziglua-5.3/lib.zig +++ b/src/ziglua-5.3/lib.zig @@ -4,9 +4,9 @@ const std = @import("std"); const c = @cImport({ - @cInclude("lua/lua.h"); - @cInclude("lua/lualib.h"); - @cInclude("lua/lauxlib.h"); + @cInclude("lua.h"); + @cInclude("lualib.h"); + @cInclude("lauxlib.h"); }); const Allocator = std.mem.Allocator; diff --git a/src/ziglua-5.3/tests.zig b/src/ziglua-5.3/tests.zig index a6b3b87..f3e407d 100644 --- a/src/ziglua-5.3/tests.zig +++ b/src/ziglua-5.3/tests.zig @@ -1,6 +1,6 @@ const std = @import("std"); const testing = std.testing; -const ziglua = @import("lib.zig"); +const ziglua = @import("ziglua"); const AllocFn = ziglua.AllocFn; const Buffer = ziglua.Buffer; diff --git a/src/ziglua-5.4/lib.zig b/src/ziglua-5.4/lib.zig index 11f61dc..3bbe264 100644 --- a/src/ziglua-5.4/lib.zig +++ b/src/ziglua-5.4/lib.zig @@ -4,9 +4,9 @@ const std = @import("std"); const c = @cImport({ - @cInclude("lua/lua.h"); - @cInclude("lua/lualib.h"); - @cInclude("lua/lauxlib.h"); + @cInclude("lua.h"); + @cInclude("lualib.h"); + @cInclude("lauxlib.h"); }); const Allocator = std.mem.Allocator; diff --git a/src/ziglua-5.4/tests.zig b/src/ziglua-5.4/tests.zig index 9fa0e4f..007ef60 100644 --- a/src/ziglua-5.4/tests.zig +++ b/src/ziglua-5.4/tests.zig @@ -1,6 +1,6 @@ const std = @import("std"); const testing = std.testing; -const ziglua = @import("lib.zig"); +const ziglua = @import("ziglua"); const AllocFn = ziglua.AllocFn; const Buffer = ziglua.Buffer; From d81547a9ab904644cf3c3f30ebaa411242637437 Mon Sep 17 00:00:00 2001 From: Nathan Craddock Date: Tue, 9 Jan 2024 15:38:12 -0700 Subject: [PATCH 3/5] Remove vendored Luau library --- build.zig | 134 +- build.zig.zon | 7 +- lib/luau/Ast/include/Luau/Ast.h | 1369 ------ lib/luau/Ast/include/Luau/Confusables.h | 9 - lib/luau/Ast/include/Luau/Lexer.h | 268 -- lib/luau/Ast/include/Luau/Location.h | 66 - lib/luau/Ast/include/Luau/ParseOptions.h | 21 - lib/luau/Ast/include/Luau/ParseResult.h | 71 - lib/luau/Ast/include/Luau/Parser.h | 416 -- lib/luau/Ast/include/Luau/StringUtils.h | 36 - lib/luau/Ast/include/Luau/TimeTrace.h | 231 - lib/luau/Ast/src/Ast.cpp | 1006 ---- lib/luau/Ast/src/Confusables.cpp | 1818 -------- lib/luau/Ast/src/Lexer.cpp | 1318 ------ lib/luau/Ast/src/Location.cpp | 101 - lib/luau/Ast/src/Parser.cpp | 3154 ------------- lib/luau/Ast/src/StringUtils.cpp | 297 -- lib/luau/Ast/src/TimeTrace.cpp | 264 -- lib/luau/Common/include/Luau/Bytecode.h | 604 --- lib/luau/Common/include/Luau/BytecodeUtils.h | 42 - lib/luau/Common/include/Luau/Common.h | 137 - lib/luau/Common/include/Luau/DenseHash.h | 666 --- .../Common/include/Luau/ExperimentalFlags.h | 29 - .../Compiler/include/Luau/BytecodeBuilder.h | 292 -- lib/luau/Compiler/include/Luau/Compiler.h | 71 - lib/luau/Compiler/include/luacode.h | 42 - lib/luau/Compiler/src/BuiltinFolding.cpp | 502 -- lib/luau/Compiler/src/BuiltinFolding.h | 15 - lib/luau/Compiler/src/Builtins.cpp | 467 -- lib/luau/Compiler/src/Builtins.h | 60 - lib/luau/Compiler/src/BytecodeBuilder.cpp | 2446 ---------- lib/luau/Compiler/src/Compiler.cpp | 4103 ----------------- lib/luau/Compiler/src/ConstantFolding.cpp | 469 -- lib/luau/Compiler/src/ConstantFolding.h | 51 - lib/luau/Compiler/src/CostModel.cpp | 416 -- lib/luau/Compiler/src/CostModel.h | 22 - lib/luau/Compiler/src/TableShape.cpp | 158 - lib/luau/Compiler/src/TableShape.h | 21 - lib/luau/Compiler/src/Types.cpp | 233 - lib/luau/Compiler/src/Types.h | 14 - lib/luau/Compiler/src/ValueTracking.cpp | 103 - lib/luau/Compiler/src/ValueTracking.h | 42 - lib/luau/Compiler/src/lcode.cpp | 29 - lib/luau/LICENSE.txt | 22 - lib/luau/VM/include/lua.h | 480 -- lib/luau/VM/include/luaconf.h | 150 - lib/luau/VM/include/lualib.h | 144 - lib/luau/VM/src/lapi.cpp | 1495 ------ lib/luau/VM/src/lapi.h | 8 - lib/luau/VM/src/laux.cpp | 586 --- lib/luau/VM/src/lbaselib.cpp | 480 -- lib/luau/VM/src/lbitlib.cpp | 251 - lib/luau/VM/src/lbuffer.cpp | 24 - lib/luau/VM/src/lbuffer.h | 13 - lib/luau/VM/src/lbuflib.cpp | 309 -- lib/luau/VM/src/lbuiltins.cpp | 1638 ------- lib/luau/VM/src/lbuiltins.h | 9 - lib/luau/VM/src/lbytecode.h | 6 - lib/luau/VM/src/lcommon.h | 48 - lib/luau/VM/src/lcorolib.cpp | 256 - lib/luau/VM/src/ldblib.cpp | 166 - lib/luau/VM/src/ldebug.cpp | 582 --- lib/luau/VM/src/ldebug.h | 33 - lib/luau/VM/src/ldo.cpp | 602 --- lib/luau/VM/src/ldo.h | 55 - lib/luau/VM/src/lfunc.cpp | 197 - lib/luau/VM/src/lfunc.h | 20 - lib/luau/VM/src/lgc.cpp | 1256 ----- lib/luau/VM/src/lgc.h | 143 - lib/luau/VM/src/lgcdebug.cpp | 897 ---- lib/luau/VM/src/linit.cpp | 88 - lib/luau/VM/src/lmathlib.cpp | 441 -- lib/luau/VM/src/lmem.cpp | 649 --- lib/luau/VM/src/lmem.h | 32 - lib/luau/VM/src/lnumprint.cpp | 366 -- lib/luau/VM/src/lnumutils.h | 69 - lib/luau/VM/src/lobject.cpp | 154 - lib/luau/VM/src/lobject.h | 502 -- lib/luau/VM/src/loslib.cpp | 225 - lib/luau/VM/src/lperf.cpp | 63 - lib/luau/VM/src/lstate.cpp | 244 - lib/luau/VM/src/lstate.h | 304 -- lib/luau/VM/src/lstring.cpp | 193 - lib/luau/VM/src/lstring.h | 29 - lib/luau/VM/src/lstrlib.cpp | 1665 ------- lib/luau/VM/src/ltable.cpp | 859 ---- lib/luau/VM/src/ltable.h | 35 - lib/luau/VM/src/ltablib.cpp | 606 --- lib/luau/VM/src/ltm.cpp | 158 - lib/luau/VM/src/ltm.h | 60 - lib/luau/VM/src/ludata.cpp | 43 - lib/luau/VM/src/ludata.h | 16 - lib/luau/VM/src/lutf8lib.cpp | 298 -- lib/luau/VM/src/lvm.h | 34 - lib/luau/VM/src/lvmexecute.cpp | 3097 ------------- lib/luau/VM/src/lvmload.cpp | 424 -- lib/luau/VM/src/lvmutils.cpp | 619 --- src/zigluau/lib.zig | 7 +- src/zigluau/tests.zig | 2 +- 99 files changed, 78 insertions(+), 42694 deletions(-) delete mode 100644 lib/luau/Ast/include/Luau/Ast.h delete mode 100644 lib/luau/Ast/include/Luau/Confusables.h delete mode 100644 lib/luau/Ast/include/Luau/Lexer.h delete mode 100644 lib/luau/Ast/include/Luau/Location.h delete mode 100644 lib/luau/Ast/include/Luau/ParseOptions.h delete mode 100644 lib/luau/Ast/include/Luau/ParseResult.h delete mode 100644 lib/luau/Ast/include/Luau/Parser.h delete mode 100644 lib/luau/Ast/include/Luau/StringUtils.h delete mode 100644 lib/luau/Ast/include/Luau/TimeTrace.h delete mode 100644 lib/luau/Ast/src/Ast.cpp delete mode 100644 lib/luau/Ast/src/Confusables.cpp delete mode 100644 lib/luau/Ast/src/Lexer.cpp delete mode 100644 lib/luau/Ast/src/Location.cpp delete mode 100644 lib/luau/Ast/src/Parser.cpp delete mode 100644 lib/luau/Ast/src/StringUtils.cpp delete mode 100644 lib/luau/Ast/src/TimeTrace.cpp delete mode 100644 lib/luau/Common/include/Luau/Bytecode.h delete mode 100644 lib/luau/Common/include/Luau/BytecodeUtils.h delete mode 100644 lib/luau/Common/include/Luau/Common.h delete mode 100644 lib/luau/Common/include/Luau/DenseHash.h delete mode 100644 lib/luau/Common/include/Luau/ExperimentalFlags.h delete mode 100644 lib/luau/Compiler/include/Luau/BytecodeBuilder.h delete mode 100644 lib/luau/Compiler/include/Luau/Compiler.h delete mode 100644 lib/luau/Compiler/include/luacode.h delete mode 100644 lib/luau/Compiler/src/BuiltinFolding.cpp delete mode 100644 lib/luau/Compiler/src/BuiltinFolding.h delete mode 100644 lib/luau/Compiler/src/Builtins.cpp delete mode 100644 lib/luau/Compiler/src/Builtins.h delete mode 100644 lib/luau/Compiler/src/BytecodeBuilder.cpp delete mode 100644 lib/luau/Compiler/src/Compiler.cpp delete mode 100644 lib/luau/Compiler/src/ConstantFolding.cpp delete mode 100644 lib/luau/Compiler/src/ConstantFolding.h delete mode 100644 lib/luau/Compiler/src/CostModel.cpp delete mode 100644 lib/luau/Compiler/src/CostModel.h delete mode 100644 lib/luau/Compiler/src/TableShape.cpp delete mode 100644 lib/luau/Compiler/src/TableShape.h delete mode 100644 lib/luau/Compiler/src/Types.cpp delete mode 100644 lib/luau/Compiler/src/Types.h delete mode 100644 lib/luau/Compiler/src/ValueTracking.cpp delete mode 100644 lib/luau/Compiler/src/ValueTracking.h delete mode 100644 lib/luau/Compiler/src/lcode.cpp delete mode 100644 lib/luau/LICENSE.txt delete mode 100644 lib/luau/VM/include/lua.h delete mode 100644 lib/luau/VM/include/luaconf.h delete mode 100644 lib/luau/VM/include/lualib.h delete mode 100644 lib/luau/VM/src/lapi.cpp delete mode 100644 lib/luau/VM/src/lapi.h delete mode 100644 lib/luau/VM/src/laux.cpp delete mode 100644 lib/luau/VM/src/lbaselib.cpp delete mode 100644 lib/luau/VM/src/lbitlib.cpp delete mode 100644 lib/luau/VM/src/lbuffer.cpp delete mode 100644 lib/luau/VM/src/lbuffer.h delete mode 100644 lib/luau/VM/src/lbuflib.cpp delete mode 100644 lib/luau/VM/src/lbuiltins.cpp delete mode 100644 lib/luau/VM/src/lbuiltins.h delete mode 100644 lib/luau/VM/src/lbytecode.h delete mode 100644 lib/luau/VM/src/lcommon.h delete mode 100644 lib/luau/VM/src/lcorolib.cpp delete mode 100644 lib/luau/VM/src/ldblib.cpp delete mode 100644 lib/luau/VM/src/ldebug.cpp delete mode 100644 lib/luau/VM/src/ldebug.h delete mode 100644 lib/luau/VM/src/ldo.cpp delete mode 100644 lib/luau/VM/src/ldo.h delete mode 100644 lib/luau/VM/src/lfunc.cpp delete mode 100644 lib/luau/VM/src/lfunc.h delete mode 100644 lib/luau/VM/src/lgc.cpp delete mode 100644 lib/luau/VM/src/lgc.h delete mode 100644 lib/luau/VM/src/lgcdebug.cpp delete mode 100644 lib/luau/VM/src/linit.cpp delete mode 100644 lib/luau/VM/src/lmathlib.cpp delete mode 100644 lib/luau/VM/src/lmem.cpp delete mode 100644 lib/luau/VM/src/lmem.h delete mode 100644 lib/luau/VM/src/lnumprint.cpp delete mode 100644 lib/luau/VM/src/lnumutils.h delete mode 100644 lib/luau/VM/src/lobject.cpp delete mode 100644 lib/luau/VM/src/lobject.h delete mode 100644 lib/luau/VM/src/loslib.cpp delete mode 100644 lib/luau/VM/src/lperf.cpp delete mode 100644 lib/luau/VM/src/lstate.cpp delete mode 100644 lib/luau/VM/src/lstate.h delete mode 100644 lib/luau/VM/src/lstring.cpp delete mode 100644 lib/luau/VM/src/lstring.h delete mode 100644 lib/luau/VM/src/lstrlib.cpp delete mode 100644 lib/luau/VM/src/ltable.cpp delete mode 100644 lib/luau/VM/src/ltable.h delete mode 100644 lib/luau/VM/src/ltablib.cpp delete mode 100644 lib/luau/VM/src/ltm.cpp delete mode 100644 lib/luau/VM/src/ltm.h delete mode 100644 lib/luau/VM/src/ludata.cpp delete mode 100644 lib/luau/VM/src/ludata.h delete mode 100644 lib/luau/VM/src/lutf8lib.cpp delete mode 100644 lib/luau/VM/src/lvm.h delete mode 100644 lib/luau/VM/src/lvmexecute.cpp delete mode 100644 lib/luau/VM/src/lvmload.cpp delete mode 100644 lib/luau/VM/src/lvmutils.cpp diff --git a/build.zig b/build.zig index 064abde..9f99f5f 100644 --- a/build.zig +++ b/build.zig @@ -35,11 +35,20 @@ pub fn build(b: *Build) void { }); const lib = switch (lua_version) { - .luau => buildLuau(b, target, optimize, shared), + .luau => buildLuau(b, target, optimize, upstream, shared), else => buildLua(b, target, optimize, upstream, lua_version, shared), }; - ziglua.addIncludePath(upstream.path("src")); + switch (lua_version) { + .luau => { + ziglua.addIncludePath(upstream.path("Common/include")); + ziglua.addIncludePath(upstream.path("Compiler/include")); + ziglua.addIncludePath(upstream.path("Ast/include")); + ziglua.addIncludePath(upstream.path("VM/include")); + }, + else => ziglua.addIncludePath(upstream.path("src")), + } + ziglua.linkLibrary(lib); // Tests @@ -89,7 +98,6 @@ pub fn build(b: *Build) void { } fn buildLua(b: *Build, target: Build.ResolvedTarget, optimize: std.builtin.OptimizeMode, upstream: *Build.Dependency, lua_version: LuaVersion, shared: bool) *Step.Compile { - const lib_opts = .{ .name = "lua", .target = target, @@ -141,7 +149,7 @@ fn buildLua(b: *Build, target: Build.ResolvedTarget, optimize: std.builtin.Optim } /// Luau has diverged enough from Lua (C++, project structure, ...) that it is easier to separate the build logic -fn buildLuau(b: *Build, target: Build.ResolvedTarget, optimize: std.builtin.OptimizeMode, shared: bool) *Step.Compile { +fn buildLuau(b: *Build, target: Build.ResolvedTarget, optimize: std.builtin.OptimizeMode, upstream: *Build.Dependency, shared: bool) *Step.Compile { const lib_opts = .{ .name = "luau", .target = target, @@ -153,11 +161,10 @@ fn buildLuau(b: *Build, target: Build.ResolvedTarget, optimize: std.builtin.Opti else b.addStaticLibrary(lib_opts); - const lib_dir = "lib/luau/VM"; - lib.addIncludePath(.{ .path = "lib/luau/Common/include" }); - lib.addIncludePath(.{ .path = "lib/luau/Compiler/include" }); - lib.addIncludePath(.{ .path = "lib/luau/Ast/include" }); - lib.addIncludePath(.{ .path = b.pathJoin(&.{ lib_dir, "include" }) }); + lib.addIncludePath(upstream.path("Common/include")); + lib.addIncludePath(upstream.path("Compiler/include")); + lib.addIncludePath(upstream.path("Ast/include")); + lib.addIncludePath(upstream.path("VM/include")); const flags = [_][]const u8{ "-DLUA_USE_LONGJMP=1", @@ -167,16 +174,11 @@ fn buildLuau(b: *Build, target: Build.ResolvedTarget, optimize: std.builtin.Opti }; for (luau_source_files) |file| { - lib.addCSourceFile(.{ .file = .{ .path = file }, .flags = &flags }); + lib.addCSourceFile(.{ .file = upstream.path(file), .flags = &flags }); } lib.addCSourceFile(.{ .file = .{ .path = "src/zigluau/luau.cpp" }, .flags = &flags }); lib.linkLibCpp(); - lib.installHeader("lib/luau/VM/include/lua.h", "lua.h"); - lib.installHeader("lib/luau/VM/include/lualib.h", "lualib.h"); - lib.installHeader("lib/luau/VM/include/luaconf.h", "luaconf.h"); - lib.installHeader("lib/luau/Compiler/include/luacode.h", "luacode.h"); - return lib; } @@ -319,55 +321,55 @@ const lua_54_source_files = [_][]const u8{ }; const luau_source_files = [_][]const u8{ - "lib/luau/Compiler/src/BuiltinFolding.cpp", - "lib/luau/Compiler/src/Builtins.cpp", - "lib/luau/Compiler/src/BytecodeBuilder.cpp", - "lib/luau/Compiler/src/Compiler.cpp", - "lib/luau/Compiler/src/ConstantFolding.cpp", - "lib/luau/Compiler/src/CostModel.cpp", - "lib/luau/Compiler/src/TableShape.cpp", - "lib/luau/Compiler/src/Types.cpp", - "lib/luau/Compiler/src/ValueTracking.cpp", - "lib/luau/Compiler/src/lcode.cpp", - - "lib/luau/VM/src/lapi.cpp", - "lib/luau/VM/src/laux.cpp", - "lib/luau/VM/src/lbaselib.cpp", - "lib/luau/VM/src/lbitlib.cpp", - "lib/luau/VM/src/lbuffer.cpp", - "lib/luau/VM/src/lbuflib.cpp", - "lib/luau/VM/src/lbuiltins.cpp", - "lib/luau/VM/src/lcorolib.cpp", - "lib/luau/VM/src/ldblib.cpp", - "lib/luau/VM/src/ldebug.cpp", - "lib/luau/VM/src/ldo.cpp", - "lib/luau/VM/src/lfunc.cpp", - "lib/luau/VM/src/lgc.cpp", - "lib/luau/VM/src/lgcdebug.cpp", - "lib/luau/VM/src/linit.cpp", - "lib/luau/VM/src/lmathlib.cpp", - "lib/luau/VM/src/lmem.cpp", - "lib/luau/VM/src/lnumprint.cpp", - "lib/luau/VM/src/lobject.cpp", - "lib/luau/VM/src/loslib.cpp", - "lib/luau/VM/src/lperf.cpp", - "lib/luau/VM/src/lstate.cpp", - "lib/luau/VM/src/lstring.cpp", - "lib/luau/VM/src/lstrlib.cpp", - "lib/luau/VM/src/ltable.cpp", - "lib/luau/VM/src/ltablib.cpp", - "lib/luau/VM/src/ltm.cpp", - "lib/luau/VM/src/ludata.cpp", - "lib/luau/VM/src/lutf8lib.cpp", - "lib/luau/VM/src/lvmexecute.cpp", - "lib/luau/VM/src/lvmload.cpp", - "lib/luau/VM/src/lvmutils.cpp", - - "lib/luau/Ast/src/Ast.cpp", - "lib/luau/Ast/src/Confusables.cpp", - "lib/luau/Ast/src/Lexer.cpp", - "lib/luau/Ast/src/Location.cpp", - "lib/luau/Ast/src/Parser.cpp", - "lib/luau/Ast/src/StringUtils.cpp", - "lib/luau/Ast/src/TimeTrace.cpp", + "Compiler/src/BuiltinFolding.cpp", + "Compiler/src/Builtins.cpp", + "Compiler/src/BytecodeBuilder.cpp", + "Compiler/src/Compiler.cpp", + "Compiler/src/ConstantFolding.cpp", + "Compiler/src/CostModel.cpp", + "Compiler/src/TableShape.cpp", + "Compiler/src/Types.cpp", + "Compiler/src/ValueTracking.cpp", + "Compiler/src/lcode.cpp", + + "VM/src/lapi.cpp", + "VM/src/laux.cpp", + "VM/src/lbaselib.cpp", + "VM/src/lbitlib.cpp", + "VM/src/lbuffer.cpp", + "VM/src/lbuflib.cpp", + "VM/src/lbuiltins.cpp", + "VM/src/lcorolib.cpp", + "VM/src/ldblib.cpp", + "VM/src/ldebug.cpp", + "VM/src/ldo.cpp", + "VM/src/lfunc.cpp", + "VM/src/lgc.cpp", + "VM/src/lgcdebug.cpp", + "VM/src/linit.cpp", + "VM/src/lmathlib.cpp", + "VM/src/lmem.cpp", + "VM/src/lnumprint.cpp", + "VM/src/lobject.cpp", + "VM/src/loslib.cpp", + "VM/src/lperf.cpp", + "VM/src/lstate.cpp", + "VM/src/lstring.cpp", + "VM/src/lstrlib.cpp", + "VM/src/ltable.cpp", + "VM/src/ltablib.cpp", + "VM/src/ltm.cpp", + "VM/src/ludata.cpp", + "VM/src/lutf8lib.cpp", + "VM/src/lvmexecute.cpp", + "VM/src/lvmload.cpp", + "VM/src/lvmutils.cpp", + + "Ast/src/Ast.cpp", + "Ast/src/Confusables.cpp", + "Ast/src/Lexer.cpp", + "Ast/src/Location.cpp", + "Ast/src/Parser.cpp", + "Ast/src/StringUtils.cpp", + "Ast/src/TimeTrace.cpp", }; diff --git a/build.zig.zon b/build.zig.zon index a0df66b..431b843 100644 --- a/build.zig.zon +++ b/build.zig.zon @@ -1,7 +1,7 @@ .{ .name = "ziglua", .version = "0.1.0", - .paths = .{ "" }, + .paths = .{""}, .dependencies = .{ .lua51 = .{ @@ -23,5 +23,10 @@ .url = "https://www.lua.org/ftp/lua-5.4.6.tar.gz", .hash = "1220f93ada1fa077ab096bf88a5b159ad421dbf6a478edec78ddb186d0c21d3476d9", }, + + .luau = .{ + .url = "https://github.com/luau-lang/luau/archive/refs/tags/0.607.tar.gz", + .hash = "122003818ff2aa912db37d4bbda314ff9ff70d03d9243af4b639490be98e2bfa7cb6", + }, }, } diff --git a/lib/luau/Ast/include/Luau/Ast.h b/lib/luau/Ast/include/Luau/Ast.h deleted file mode 100644 index 2abda78..0000000 --- a/lib/luau/Ast/include/Luau/Ast.h +++ /dev/null @@ -1,1369 +0,0 @@ -// This file is part of the Luau programming language and is licensed under MIT License; see LICENSE.txt for details -#pragma once - -#include "Luau/Location.h" - -#include -#include -#include -#include - -#include -#include - -namespace Luau -{ - -struct AstName -{ - const char* value; - - AstName() - : value(nullptr) - { - } - - explicit AstName(const char* value) - : value(value) - { - } - - bool operator==(const AstName& rhs) const - { - return value == rhs.value; - } - - bool operator!=(const AstName& rhs) const - { - return value != rhs.value; - } - - bool operator==(const char* rhs) const - { - return value && strcmp(value, rhs) == 0; - } - - bool operator!=(const char* rhs) const - { - return !value || strcmp(value, rhs) != 0; - } - - bool operator<(const AstName& rhs) const - { - return (value && rhs.value) ? strcmp(value, rhs.value) < 0 : value < rhs.value; - } -}; - -class AstType; -class AstVisitor; -class AstStat; -class AstStatBlock; -class AstExpr; -class AstTypePack; - -struct AstLocal -{ - AstName name; - Location location; - AstLocal* shadow; - size_t functionDepth; - size_t loopDepth; - - AstType* annotation; - - AstLocal(const AstName& name, const Location& location, AstLocal* shadow, size_t functionDepth, size_t loopDepth, AstType* annotation) - : name(name) - , location(location) - , shadow(shadow) - , functionDepth(functionDepth) - , loopDepth(loopDepth) - , annotation(annotation) - { - } -}; - -template -struct AstArray -{ - T* data; - size_t size; - - const T* begin() const - { - return data; - } - - const T* end() const - { - return data + size; - } - - std::reverse_iterator rbegin() const - { - return std::make_reverse_iterator(end()); - } - - std::reverse_iterator rend() const - { - return std::make_reverse_iterator(begin()); - } -}; - -struct AstTypeList -{ - AstArray types; - // Null indicates no tail, not an untyped tail. - AstTypePack* tailType = nullptr; -}; - -using AstArgumentName = std::pair; // TODO: remove and replace when we get a common struct for this pair instead of AstName - -struct AstGenericType -{ - AstName name; - Location location; - AstType* defaultValue = nullptr; -}; - -struct AstGenericTypePack -{ - AstName name; - Location location; - AstTypePack* defaultValue = nullptr; -}; - -extern int gAstRttiIndex; - -template -struct AstRtti -{ - static const int value; -}; - -template -const int AstRtti::value = ++gAstRttiIndex; - -#define LUAU_RTTI(Class) \ - static int ClassIndex() \ - { \ - return AstRtti::value; \ - } - -class AstNode -{ -public: - explicit AstNode(int classIndex, const Location& location) - : classIndex(classIndex) - , location(location) - { - } - - virtual void visit(AstVisitor* visitor) = 0; - - virtual AstExpr* asExpr() - { - return nullptr; - } - virtual AstStat* asStat() - { - return nullptr; - } - virtual AstType* asType() - { - return nullptr; - } - - template - bool is() const - { - return classIndex == T::ClassIndex(); - } - template - T* as() - { - return classIndex == T::ClassIndex() ? static_cast(this) : nullptr; - } - template - const T* as() const - { - return classIndex == T::ClassIndex() ? static_cast(this) : nullptr; - } - - const int classIndex; - Location location; -}; - -class AstExpr : public AstNode -{ -public: - explicit AstExpr(int classIndex, const Location& location) - : AstNode(classIndex, location) - { - } - - AstExpr* asExpr() override - { - return this; - } -}; - -class AstStat : public AstNode -{ -public: - explicit AstStat(int classIndex, const Location& location) - : AstNode(classIndex, location) - , hasSemicolon(false) - { - } - - AstStat* asStat() override - { - return this; - } - - bool hasSemicolon; -}; - -class AstExprGroup : public AstExpr -{ -public: - LUAU_RTTI(AstExprGroup) - - explicit AstExprGroup(const Location& location, AstExpr* expr); - - void visit(AstVisitor* visitor) override; - - AstExpr* expr; -}; - -class AstExprConstantNil : public AstExpr -{ -public: - LUAU_RTTI(AstExprConstantNil) - - explicit AstExprConstantNil(const Location& location); - - void visit(AstVisitor* visitor) override; -}; - -class AstExprConstantBool : public AstExpr -{ -public: - LUAU_RTTI(AstExprConstantBool) - - AstExprConstantBool(const Location& location, bool value); - - void visit(AstVisitor* visitor) override; - - bool value; -}; - -enum class ConstantNumberParseResult -{ - Ok, - Imprecise, - Malformed, - BinOverflow, - HexOverflow, -}; - -class AstExprConstantNumber : public AstExpr -{ -public: - LUAU_RTTI(AstExprConstantNumber) - - AstExprConstantNumber(const Location& location, double value, ConstantNumberParseResult parseResult = ConstantNumberParseResult::Ok); - - void visit(AstVisitor* visitor) override; - - double value; - ConstantNumberParseResult parseResult; -}; - -class AstExprConstantString : public AstExpr -{ -public: - LUAU_RTTI(AstExprConstantString) - - enum QuoteStyle - { - Quoted, - Unquoted - }; - - AstExprConstantString(const Location& location, const AstArray& value, QuoteStyle quoteStyle = Quoted); - - void visit(AstVisitor* visitor) override; - - AstArray value; - QuoteStyle quoteStyle = Quoted; -}; - -class AstExprLocal : public AstExpr -{ -public: - LUAU_RTTI(AstExprLocal) - - AstExprLocal(const Location& location, AstLocal* local, bool upvalue); - - void visit(AstVisitor* visitor) override; - - AstLocal* local; - bool upvalue; -}; - -class AstExprGlobal : public AstExpr -{ -public: - LUAU_RTTI(AstExprGlobal) - - AstExprGlobal(const Location& location, const AstName& name); - - void visit(AstVisitor* visitor) override; - - AstName name; -}; - -class AstExprVarargs : public AstExpr -{ -public: - LUAU_RTTI(AstExprVarargs) - - AstExprVarargs(const Location& location); - - void visit(AstVisitor* visitor) override; -}; - -class AstExprCall : public AstExpr -{ -public: - LUAU_RTTI(AstExprCall) - - AstExprCall(const Location& location, AstExpr* func, const AstArray& args, bool self, const Location& argLocation); - - void visit(AstVisitor* visitor) override; - - AstExpr* func; - AstArray args; - bool self; - Location argLocation; -}; - -class AstExprIndexName : public AstExpr -{ -public: - LUAU_RTTI(AstExprIndexName) - - AstExprIndexName( - const Location& location, AstExpr* expr, const AstName& index, const Location& indexLocation, const Position& opPosition, char op); - - void visit(AstVisitor* visitor) override; - - AstExpr* expr; - AstName index; - Location indexLocation; - Position opPosition; - char op = '.'; -}; - -class AstExprIndexExpr : public AstExpr -{ -public: - LUAU_RTTI(AstExprIndexExpr) - - AstExprIndexExpr(const Location& location, AstExpr* expr, AstExpr* index); - - void visit(AstVisitor* visitor) override; - - AstExpr* expr; - AstExpr* index; -}; - -class AstExprFunction : public AstExpr -{ -public: - LUAU_RTTI(AstExprFunction) - - AstExprFunction(const Location& location, const AstArray& generics, const AstArray& genericPacks, - AstLocal* self, const AstArray& args, bool vararg, const Location& varargLocation, AstStatBlock* body, size_t functionDepth, - const AstName& debugname, const std::optional& returnAnnotation = {}, AstTypePack* varargAnnotation = nullptr, - bool DEPRECATED_hasEnd = false, const std::optional& argLocation = std::nullopt); - - void visit(AstVisitor* visitor) override; - - AstArray generics; - AstArray genericPacks; - AstLocal* self; - AstArray args; - std::optional returnAnnotation; - bool vararg = false; - Location varargLocation; - AstTypePack* varargAnnotation; - - AstStatBlock* body; - - size_t functionDepth; - - AstName debugname; - - // TODO clip with FFlag::LuauClipExtraHasEndProps - bool DEPRECATED_hasEnd = false; - std::optional argLocation; -}; - -class AstExprTable : public AstExpr -{ -public: - LUAU_RTTI(AstExprTable) - - struct Item - { - enum Kind - { - List, // foo, in which case key is a nullptr - Record, // foo=bar, in which case key is a AstExprConstantString - General, // [foo]=bar - }; - - Kind kind; - - AstExpr* key; // can be nullptr! - AstExpr* value; - }; - - AstExprTable(const Location& location, const AstArray& items); - - void visit(AstVisitor* visitor) override; - - AstArray items; -}; - -class AstExprUnary : public AstExpr -{ -public: - LUAU_RTTI(AstExprUnary) - - enum Op - { - Not, - Minus, - Len - }; - - AstExprUnary(const Location& location, Op op, AstExpr* expr); - - void visit(AstVisitor* visitor) override; - - Op op; - AstExpr* expr; -}; - -std::string toString(AstExprUnary::Op op); - -class AstExprBinary : public AstExpr -{ -public: - LUAU_RTTI(AstExprBinary) - - enum Op - { - Add, - Sub, - Mul, - Div, - FloorDiv, - Mod, - Pow, - Concat, - CompareNe, - CompareEq, - CompareLt, - CompareLe, - CompareGt, - CompareGe, - And, - Or, - - Op__Count - }; - - AstExprBinary(const Location& location, Op op, AstExpr* left, AstExpr* right); - - void visit(AstVisitor* visitor) override; - - Op op; - AstExpr* left; - AstExpr* right; -}; - -std::string toString(AstExprBinary::Op op); - -class AstExprTypeAssertion : public AstExpr -{ -public: - LUAU_RTTI(AstExprTypeAssertion) - - AstExprTypeAssertion(const Location& location, AstExpr* expr, AstType* annotation); - - void visit(AstVisitor* visitor) override; - - AstExpr* expr; - AstType* annotation; -}; - -class AstExprIfElse : public AstExpr -{ -public: - LUAU_RTTI(AstExprIfElse) - - AstExprIfElse(const Location& location, AstExpr* condition, bool hasThen, AstExpr* trueExpr, bool hasElse, AstExpr* falseExpr); - - void visit(AstVisitor* visitor) override; - - AstExpr* condition; - bool hasThen; - AstExpr* trueExpr; - bool hasElse; - AstExpr* falseExpr; -}; - -class AstExprInterpString : public AstExpr -{ -public: - LUAU_RTTI(AstExprInterpString) - - AstExprInterpString(const Location& location, const AstArray>& strings, const AstArray& expressions); - - void visit(AstVisitor* visitor) override; - - /// An interpolated string such as `foo{bar}baz` is represented as - /// an array of strings for "foo" and "bar", and an array of expressions for "baz". - /// `strings` will always have one more element than `expressions`. - AstArray> strings; - AstArray expressions; -}; - -class AstStatBlock : public AstStat -{ -public: - LUAU_RTTI(AstStatBlock) - - AstStatBlock(const Location& location, const AstArray& body, bool hasEnd = true); - - void visit(AstVisitor* visitor) override; - - AstArray body; - - /* Indicates whether or not this block has been terminated in a - * syntactically valid way. - * - * This is usually but not always done with the 'end' keyword. AstStatIf - * and AstStatRepeat are the two main exceptions to this. - * - * The 'then' clause of an if statement can properly be closed by the - * keywords 'else' or 'elseif'. A 'repeat' loop's body is closed with the - * 'until' keyword. - */ - bool hasEnd = false; -}; - -class AstStatIf : public AstStat -{ -public: - LUAU_RTTI(AstStatIf) - - AstStatIf(const Location& location, AstExpr* condition, AstStatBlock* thenbody, AstStat* elsebody, const std::optional& thenLocation, - const std::optional& elseLocation, bool DEPRECATED_hasEnd); - - void visit(AstVisitor* visitor) override; - - AstExpr* condition; - AstStatBlock* thenbody; - AstStat* elsebody; - - std::optional thenLocation; - - // Active for 'elseif' as well - std::optional elseLocation; - - // TODO clip with FFlag::LuauClipExtraHasEndProps - bool DEPRECATED_hasEnd = false; -}; - -class AstStatWhile : public AstStat -{ -public: - LUAU_RTTI(AstStatWhile) - - AstStatWhile(const Location& location, AstExpr* condition, AstStatBlock* body, bool hasDo, const Location& doLocation, bool DEPRECATED_hasEnd); - - void visit(AstVisitor* visitor) override; - - AstExpr* condition; - AstStatBlock* body; - - bool hasDo = false; - Location doLocation; - - // TODO clip with FFlag::LuauClipExtraHasEndProps - bool DEPRECATED_hasEnd = false; -}; - -class AstStatRepeat : public AstStat -{ -public: - LUAU_RTTI(AstStatRepeat) - - AstStatRepeat(const Location& location, AstExpr* condition, AstStatBlock* body, bool DEPRECATED_hasUntil); - - void visit(AstVisitor* visitor) override; - - AstExpr* condition; - AstStatBlock* body; - - bool DEPRECATED_hasUntil = false; -}; - -class AstStatBreak : public AstStat -{ -public: - LUAU_RTTI(AstStatBreak) - - AstStatBreak(const Location& location); - - void visit(AstVisitor* visitor) override; -}; - -class AstStatContinue : public AstStat -{ -public: - LUAU_RTTI(AstStatContinue) - - AstStatContinue(const Location& location); - - void visit(AstVisitor* visitor) override; -}; - -class AstStatReturn : public AstStat -{ -public: - LUAU_RTTI(AstStatReturn) - - AstStatReturn(const Location& location, const AstArray& list); - - void visit(AstVisitor* visitor) override; - - AstArray list; -}; - -class AstStatExpr : public AstStat -{ -public: - LUAU_RTTI(AstStatExpr) - - AstStatExpr(const Location& location, AstExpr* expr); - - void visit(AstVisitor* visitor) override; - - AstExpr* expr; -}; - -class AstStatLocal : public AstStat -{ -public: - LUAU_RTTI(AstStatLocal) - - AstStatLocal(const Location& location, const AstArray& vars, const AstArray& values, - const std::optional& equalsSignLocation); - - void visit(AstVisitor* visitor) override; - - AstArray vars; - AstArray values; - - std::optional equalsSignLocation; -}; - -class AstStatFor : public AstStat -{ -public: - LUAU_RTTI(AstStatFor) - - AstStatFor(const Location& location, AstLocal* var, AstExpr* from, AstExpr* to, AstExpr* step, AstStatBlock* body, bool hasDo, - const Location& doLocation, bool DEPRECATED_hasEnd); - - void visit(AstVisitor* visitor) override; - - AstLocal* var; - AstExpr* from; - AstExpr* to; - AstExpr* step; - AstStatBlock* body; - - bool hasDo = false; - Location doLocation; - - // TODO clip with FFlag::LuauClipExtraHasEndProps - bool DEPRECATED_hasEnd = false; -}; - -class AstStatForIn : public AstStat -{ -public: - LUAU_RTTI(AstStatForIn) - - AstStatForIn(const Location& location, const AstArray& vars, const AstArray& values, AstStatBlock* body, bool hasIn, - const Location& inLocation, bool hasDo, const Location& doLocation, bool DEPRECATED_hasEnd); - - void visit(AstVisitor* visitor) override; - - AstArray vars; - AstArray values; - AstStatBlock* body; - - bool hasIn = false; - Location inLocation; - - bool hasDo = false; - Location doLocation; - - // TODO clip with FFlag::LuauClipExtraHasEndProps - bool DEPRECATED_hasEnd = false; -}; - -class AstStatAssign : public AstStat -{ -public: - LUAU_RTTI(AstStatAssign) - - AstStatAssign(const Location& location, const AstArray& vars, const AstArray& values); - - void visit(AstVisitor* visitor) override; - - AstArray vars; - AstArray values; -}; - -class AstStatCompoundAssign : public AstStat -{ -public: - LUAU_RTTI(AstStatCompoundAssign) - - AstStatCompoundAssign(const Location& location, AstExprBinary::Op op, AstExpr* var, AstExpr* value); - - void visit(AstVisitor* visitor) override; - - AstExprBinary::Op op; - AstExpr* var; - AstExpr* value; -}; - -class AstStatFunction : public AstStat -{ -public: - LUAU_RTTI(AstStatFunction) - - AstStatFunction(const Location& location, AstExpr* name, AstExprFunction* func); - - void visit(AstVisitor* visitor) override; - - AstExpr* name; - AstExprFunction* func; -}; - -class AstStatLocalFunction : public AstStat -{ -public: - LUAU_RTTI(AstStatLocalFunction) - - AstStatLocalFunction(const Location& location, AstLocal* name, AstExprFunction* func); - - void visit(AstVisitor* visitor) override; - - AstLocal* name; - AstExprFunction* func; -}; - -class AstStatTypeAlias : public AstStat -{ -public: - LUAU_RTTI(AstStatTypeAlias) - - AstStatTypeAlias(const Location& location, const AstName& name, const Location& nameLocation, const AstArray& generics, - const AstArray& genericPacks, AstType* type, bool exported); - - void visit(AstVisitor* visitor) override; - - AstName name; - Location nameLocation; - AstArray generics; - AstArray genericPacks; - AstType* type; - bool exported; -}; - -class AstStatDeclareGlobal : public AstStat -{ -public: - LUAU_RTTI(AstStatDeclareGlobal) - - AstStatDeclareGlobal(const Location& location, const AstName& name, AstType* type); - - void visit(AstVisitor* visitor) override; - - AstName name; - AstType* type; -}; - -class AstStatDeclareFunction : public AstStat -{ -public: - LUAU_RTTI(AstStatDeclareFunction) - - AstStatDeclareFunction(const Location& location, const AstName& name, const AstArray& generics, - const AstArray& genericPacks, const AstTypeList& params, const AstArray& paramNames, - const AstTypeList& retTypes); - - AstStatDeclareFunction(const Location& location, const AstName& name, const AstArray& generics, - const AstArray& genericPacks, const AstTypeList& params, const AstArray& paramNames, - const AstTypeList& retTypes, bool checkedFunction); - - - void visit(AstVisitor* visitor) override; - - AstName name; - AstArray generics; - AstArray genericPacks; - AstTypeList params; - AstArray paramNames; - AstTypeList retTypes; - bool checkedFunction; -}; - -struct AstDeclaredClassProp -{ - AstName name; - AstType* ty = nullptr; - bool isMethod = false; -}; - -struct AstTableIndexer -{ - AstType* indexType; - AstType* resultType; - Location location; -}; - -class AstStatDeclareClass : public AstStat -{ -public: - LUAU_RTTI(AstStatDeclareClass) - - AstStatDeclareClass(const Location& location, const AstName& name, std::optional superName, const AstArray& props, - AstTableIndexer* indexer = nullptr); - - void visit(AstVisitor* visitor) override; - - AstName name; - std::optional superName; - - AstArray props; - AstTableIndexer* indexer; -}; - -class AstType : public AstNode -{ -public: - AstType(int classIndex, const Location& location) - : AstNode(classIndex, location) - { - } - - AstType* asType() override - { - return this; - } -}; - -// Don't have Luau::Variant available, it's a bit of an overhead, but a plain struct is nice to use -struct AstTypeOrPack -{ - AstType* type = nullptr; - AstTypePack* typePack = nullptr; -}; - -class AstTypeReference : public AstType -{ -public: - LUAU_RTTI(AstTypeReference) - - AstTypeReference(const Location& location, std::optional prefix, AstName name, std::optional prefixLocation, - const Location& nameLocation, bool hasParameterList = false, const AstArray& parameters = {}); - - void visit(AstVisitor* visitor) override; - - bool hasParameterList; - std::optional prefix; - std::optional prefixLocation; - AstName name; - Location nameLocation; - AstArray parameters; -}; - -struct AstTableProp -{ - AstName name; - Location location; - AstType* type; -}; - -class AstTypeTable : public AstType -{ -public: - LUAU_RTTI(AstTypeTable) - - AstTypeTable(const Location& location, const AstArray& props, AstTableIndexer* indexer = nullptr); - - void visit(AstVisitor* visitor) override; - - AstArray props; - AstTableIndexer* indexer; -}; - -class AstTypeFunction : public AstType -{ -public: - LUAU_RTTI(AstTypeFunction) - - AstTypeFunction(const Location& location, const AstArray& generics, const AstArray& genericPacks, - const AstTypeList& argTypes, const AstArray>& argNames, const AstTypeList& returnTypes); - - AstTypeFunction(const Location& location, const AstArray& generics, const AstArray& genericPacks, - const AstTypeList& argTypes, const AstArray>& argNames, const AstTypeList& returnTypes, bool checkedFunction); - - void visit(AstVisitor* visitor) override; - - AstArray generics; - AstArray genericPacks; - AstTypeList argTypes; - AstArray> argNames; - AstTypeList returnTypes; - bool checkedFunction; -}; - -class AstTypeTypeof : public AstType -{ -public: - LUAU_RTTI(AstTypeTypeof) - - AstTypeTypeof(const Location& location, AstExpr* expr); - - void visit(AstVisitor* visitor) override; - - AstExpr* expr; -}; - -class AstTypeUnion : public AstType -{ -public: - LUAU_RTTI(AstTypeUnion) - - AstTypeUnion(const Location& location, const AstArray& types); - - void visit(AstVisitor* visitor) override; - - AstArray types; -}; - -class AstTypeIntersection : public AstType -{ -public: - LUAU_RTTI(AstTypeIntersection) - - AstTypeIntersection(const Location& location, const AstArray& types); - - void visit(AstVisitor* visitor) override; - - AstArray types; -}; - -class AstExprError : public AstExpr -{ -public: - LUAU_RTTI(AstExprError) - - AstExprError(const Location& location, const AstArray& expressions, unsigned messageIndex); - - void visit(AstVisitor* visitor) override; - - AstArray expressions; - unsigned messageIndex; -}; - -class AstStatError : public AstStat -{ -public: - LUAU_RTTI(AstStatError) - - AstStatError(const Location& location, const AstArray& expressions, const AstArray& statements, unsigned messageIndex); - - void visit(AstVisitor* visitor) override; - - AstArray expressions; - AstArray statements; - unsigned messageIndex; -}; - -class AstTypeError : public AstType -{ -public: - LUAU_RTTI(AstTypeError) - - AstTypeError(const Location& location, const AstArray& types, bool isMissing, unsigned messageIndex); - - void visit(AstVisitor* visitor) override; - - AstArray types; - bool isMissing; - unsigned messageIndex; -}; - -class AstTypeSingletonBool : public AstType -{ -public: - LUAU_RTTI(AstTypeSingletonBool) - - AstTypeSingletonBool(const Location& location, bool value); - - void visit(AstVisitor* visitor) override; - - bool value; -}; - -class AstTypeSingletonString : public AstType -{ -public: - LUAU_RTTI(AstTypeSingletonString) - - AstTypeSingletonString(const Location& location, const AstArray& value); - - void visit(AstVisitor* visitor) override; - - const AstArray value; -}; - -class AstTypePack : public AstNode -{ -public: - AstTypePack(int classIndex, const Location& location) - : AstNode(classIndex, location) - { - } -}; - -class AstTypePackExplicit : public AstTypePack -{ -public: - LUAU_RTTI(AstTypePackExplicit) - - AstTypePackExplicit(const Location& location, AstTypeList typeList); - - void visit(AstVisitor* visitor) override; - - AstTypeList typeList; -}; - -class AstTypePackVariadic : public AstTypePack -{ -public: - LUAU_RTTI(AstTypePackVariadic) - - AstTypePackVariadic(const Location& location, AstType* variadicType); - - void visit(AstVisitor* visitor) override; - - AstType* variadicType; -}; - -class AstTypePackGeneric : public AstTypePack -{ -public: - LUAU_RTTI(AstTypePackGeneric) - - AstTypePackGeneric(const Location& location, AstName name); - - void visit(AstVisitor* visitor) override; - - AstName genericName; -}; - -class AstVisitor -{ -public: - virtual ~AstVisitor() {} - - virtual bool visit(class AstNode*) - { - return true; - } - - virtual bool visit(class AstExpr* node) - { - return visit(static_cast(node)); - } - - virtual bool visit(class AstExprGroup* node) - { - return visit(static_cast(node)); - } - virtual bool visit(class AstExprConstantNil* node) - { - return visit(static_cast(node)); - } - virtual bool visit(class AstExprConstantBool* node) - { - return visit(static_cast(node)); - } - virtual bool visit(class AstExprConstantNumber* node) - { - return visit(static_cast(node)); - } - virtual bool visit(class AstExprConstantString* node) - { - return visit(static_cast(node)); - } - virtual bool visit(class AstExprLocal* node) - { - return visit(static_cast(node)); - } - virtual bool visit(class AstExprGlobal* node) - { - return visit(static_cast(node)); - } - virtual bool visit(class AstExprVarargs* node) - { - return visit(static_cast(node)); - } - virtual bool visit(class AstExprCall* node) - { - return visit(static_cast(node)); - } - virtual bool visit(class AstExprIndexName* node) - { - return visit(static_cast(node)); - } - virtual bool visit(class AstExprIndexExpr* node) - { - return visit(static_cast(node)); - } - virtual bool visit(class AstExprFunction* node) - { - return visit(static_cast(node)); - } - virtual bool visit(class AstExprTable* node) - { - return visit(static_cast(node)); - } - virtual bool visit(class AstExprUnary* node) - { - return visit(static_cast(node)); - } - virtual bool visit(class AstExprBinary* node) - { - return visit(static_cast(node)); - } - virtual bool visit(class AstExprTypeAssertion* node) - { - return visit(static_cast(node)); - } - virtual bool visit(class AstExprIfElse* node) - { - return visit(static_cast(node)); - } - virtual bool visit(class AstExprInterpString* node) - { - return visit(static_cast(node)); - } - virtual bool visit(class AstExprError* node) - { - return visit(static_cast(node)); - } - - virtual bool visit(class AstStat* node) - { - return visit(static_cast(node)); - } - - virtual bool visit(class AstStatBlock* node) - { - return visit(static_cast(node)); - } - virtual bool visit(class AstStatIf* node) - { - return visit(static_cast(node)); - } - virtual bool visit(class AstStatWhile* node) - { - return visit(static_cast(node)); - } - virtual bool visit(class AstStatRepeat* node) - { - return visit(static_cast(node)); - } - virtual bool visit(class AstStatBreak* node) - { - return visit(static_cast(node)); - } - virtual bool visit(class AstStatContinue* node) - { - return visit(static_cast(node)); - } - virtual bool visit(class AstStatReturn* node) - { - return visit(static_cast(node)); - } - virtual bool visit(class AstStatExpr* node) - { - return visit(static_cast(node)); - } - virtual bool visit(class AstStatLocal* node) - { - return visit(static_cast(node)); - } - virtual bool visit(class AstStatFor* node) - { - return visit(static_cast(node)); - } - virtual bool visit(class AstStatForIn* node) - { - return visit(static_cast(node)); - } - virtual bool visit(class AstStatAssign* node) - { - return visit(static_cast(node)); - } - virtual bool visit(class AstStatCompoundAssign* node) - { - return visit(static_cast(node)); - } - virtual bool visit(class AstStatFunction* node) - { - return visit(static_cast(node)); - } - virtual bool visit(class AstStatLocalFunction* node) - { - return visit(static_cast(node)); - } - virtual bool visit(class AstStatTypeAlias* node) - { - return visit(static_cast(node)); - } - virtual bool visit(class AstStatDeclareFunction* node) - { - return visit(static_cast(node)); - } - virtual bool visit(class AstStatDeclareGlobal* node) - { - return visit(static_cast(node)); - } - virtual bool visit(class AstStatDeclareClass* node) - { - return visit(static_cast(node)); - } - virtual bool visit(class AstStatError* node) - { - return visit(static_cast(node)); - } - - // By default visiting type annotations is disabled; override this in your visitor if you need to! - virtual bool visit(class AstType* node) - { - return false; - } - - virtual bool visit(class AstTypeReference* node) - { - return visit(static_cast(node)); - } - virtual bool visit(class AstTypeTable* node) - { - return visit(static_cast(node)); - } - virtual bool visit(class AstTypeFunction* node) - { - return visit(static_cast(node)); - } - virtual bool visit(class AstTypeTypeof* node) - { - return visit(static_cast(node)); - } - virtual bool visit(class AstTypeUnion* node) - { - return visit(static_cast(node)); - } - virtual bool visit(class AstTypeIntersection* node) - { - return visit(static_cast(node)); - } - virtual bool visit(class AstTypeSingletonBool* node) - { - return visit(static_cast(node)); - } - virtual bool visit(class AstTypeSingletonString* node) - { - return visit(static_cast(node)); - } - virtual bool visit(class AstTypeError* node) - { - return visit(static_cast(node)); - } - - virtual bool visit(class AstTypePack* node) - { - return false; - } - virtual bool visit(class AstTypePackExplicit* node) - { - return visit(static_cast(node)); - } - virtual bool visit(class AstTypePackVariadic* node) - { - return visit(static_cast(node)); - } - virtual bool visit(class AstTypePackGeneric* node) - { - return visit(static_cast(node)); - } -}; - -AstName getIdentifier(AstExpr*); -Location getLocation(const AstTypeList& typeList); - -template // AstNode, AstExpr, AstLocal, etc -Location getLocation(AstArray array) -{ - if (0 == array.size) - return {}; - - return Location{array.data[0]->location.begin, array.data[array.size - 1]->location.end}; -} - -#undef LUAU_RTTI - -} // namespace Luau - -namespace std -{ - -template<> -struct hash -{ - size_t operator()(const Luau::AstName& value) const - { - // note: since operator== uses pointer identity, hashing function uses it as well - // the hasher is the same as DenseHashPointer (DenseHash.h) - return (uintptr_t(value.value) >> 4) ^ (uintptr_t(value.value) >> 9); - } -}; - -} // namespace std diff --git a/lib/luau/Ast/include/Luau/Confusables.h b/lib/luau/Ast/include/Luau/Confusables.h deleted file mode 100644 index 13f3497..0000000 --- a/lib/luau/Ast/include/Luau/Confusables.h +++ /dev/null @@ -1,9 +0,0 @@ -// This file is part of the Luau programming language and is licensed under MIT License; see LICENSE.txt for details -#pragma once - -#include - -namespace Luau -{ -const char* findConfusable(uint32_t codepoint); -} diff --git a/lib/luau/Ast/include/Luau/Lexer.h b/lib/luau/Ast/include/Luau/Lexer.h deleted file mode 100644 index e111030..0000000 --- a/lib/luau/Ast/include/Luau/Lexer.h +++ /dev/null @@ -1,268 +0,0 @@ -// This file is part of the Luau programming language and is licensed under MIT License; see LICENSE.txt for details -#pragma once - -#include "Luau/Ast.h" -#include "Luau/Location.h" -#include "Luau/DenseHash.h" -#include "Luau/Common.h" - -#include - -namespace Luau -{ - -class Allocator -{ -public: - Allocator(); - Allocator(Allocator&&); - - Allocator& operator=(Allocator&&) = delete; - - ~Allocator(); - - void* allocate(size_t size); - - template - T* alloc(Args&&... args) - { - static_assert(std::is_trivially_destructible::value, "Objects allocated with this allocator will never have their destructors run!"); - - T* t = static_cast(allocate(sizeof(T))); - new (t) T(std::forward(args)...); - return t; - } - -private: - struct Page - { - Page* next; - - char data[8192]; - }; - - Page* root; - size_t offset; -}; - -struct Lexeme -{ - enum Type - { - Eof = 0, - - // 1..255 means actual character values - Char_END = 256, - - Equal, - LessEqual, - GreaterEqual, - NotEqual, - Dot2, - Dot3, - SkinnyArrow, - DoubleColon, - FloorDiv, - - InterpStringBegin, - InterpStringMid, - InterpStringEnd, - // An interpolated string with no expressions (like `x`) - InterpStringSimple, - - AddAssign, - SubAssign, - MulAssign, - DivAssign, - FloorDivAssign, - ModAssign, - PowAssign, - ConcatAssign, - - RawString, - QuotedString, - Number, - Name, - - Comment, - BlockComment, - - BrokenString, - BrokenComment, - BrokenUnicode, - BrokenInterpDoubleBrace, - Error, - - Reserved_BEGIN, - ReservedAnd = Reserved_BEGIN, - ReservedBreak, - ReservedDo, - ReservedElse, - ReservedElseif, - ReservedEnd, - ReservedFalse, - ReservedFor, - ReservedFunction, - ReservedIf, - ReservedIn, - ReservedLocal, - ReservedNil, - ReservedNot, - ReservedOr, - ReservedRepeat, - ReservedReturn, - ReservedThen, - ReservedTrue, - ReservedUntil, - ReservedWhile, - ReservedChecked, - Reserved_END - }; - - Type type; - Location location; - unsigned int length; - - union - { - const char* data; // String, Number, Comment - const char* name; // Name - unsigned int codepoint; // BrokenUnicode - }; - - Lexeme(const Location& location, Type type); - Lexeme(const Location& location, char character); - Lexeme(const Location& location, Type type, const char* data, size_t size); - Lexeme(const Location& location, Type type, const char* name); - - std::string toString() const; -}; - -class AstNameTable -{ -public: - AstNameTable(Allocator& allocator); - - AstName addStatic(const char* name, Lexeme::Type type = Lexeme::Name); - - std::pair getOrAddWithType(const char* name, size_t length); - std::pair getWithType(const char* name, size_t length) const; - - AstName getOrAdd(const char* name); - AstName get(const char* name) const; - -private: - struct Entry - { - AstName value; - uint32_t length; - Lexeme::Type type; - - bool operator==(const Entry& other) const; - }; - - struct EntryHash - { - size_t operator()(const Entry& e) const; - }; - - DenseHashSet data; - - Allocator& allocator; -}; - -class Lexer -{ -public: - Lexer(const char* buffer, std::size_t bufferSize, AstNameTable& names); - - void setSkipComments(bool skip); - void setReadNames(bool read); - - const Location& previousLocation() const - { - return prevLocation; - } - - const Lexeme& next(); - const Lexeme& next(bool skipComments, bool updatePrevLocation); - void nextline(); - - Lexeme lookahead(); - - const Lexeme& current() const - { - return lexeme; - } - - static bool isReserved(const std::string& word); - - static bool fixupQuotedString(std::string& data); - static void fixupMultilineString(std::string& data); - -private: - char peekch() const; - char peekch(unsigned int lookahead) const; - - Position position() const; - - // consume() assumes current character is not a newline for performance; when that is not known, consumeAny() should be used instead. - void consume(); - void consumeAny(); - - Lexeme readCommentBody(); - - // Given a sequence [===[ or ]===], returns: - // 1. number of equal signs (or 0 if none present) between the brackets - // 2. -1 if this is not a long comment/string separator - // 3. -N if this is a malformed separator - // Does *not* consume the closing brace. - int skipLongSeparator(); - - Lexeme readLongString(const Position& start, int sep, Lexeme::Type ok, Lexeme::Type broken); - Lexeme readQuotedString(); - - Lexeme readInterpolatedStringBegin(); - Lexeme readInterpolatedStringSection(Position start, Lexeme::Type formatType, Lexeme::Type endType); - - void readBackslashInString(); - - std::pair readName(); - - Lexeme readNumber(const Position& start, unsigned int startOffset); - - Lexeme readUtf8Error(); - Lexeme readNext(); - - const char* buffer; - std::size_t bufferSize; - - unsigned int offset; - - unsigned int line; - unsigned int lineOffset; - - Lexeme lexeme; - - Location prevLocation; - - AstNameTable& names; - - bool skipComments; - bool readNames; - - enum class BraceType - { - InterpolatedString, - Normal - }; - - std::vector braceStack; -}; - -inline bool isSpace(char ch) -{ - return ch == ' ' || ch == '\t' || ch == '\r' || ch == '\n' || ch == '\v' || ch == '\f'; -} - -} // namespace Luau diff --git a/lib/luau/Ast/include/Luau/Location.h b/lib/luau/Ast/include/Luau/Location.h deleted file mode 100644 index 3fc8921..0000000 --- a/lib/luau/Ast/include/Luau/Location.h +++ /dev/null @@ -1,66 +0,0 @@ -// This file is part of the Luau programming language and is licensed under MIT License; see LICENSE.txt for details -#pragma once - -namespace Luau -{ - -struct Position -{ - unsigned int line, column; - - Position(unsigned int line, unsigned int column) - : line(line) - , column(column) - { - } - - bool operator==(const Position& rhs) const; - bool operator!=(const Position& rhs) const; - bool operator<(const Position& rhs) const; - bool operator>(const Position& rhs) const; - bool operator<=(const Position& rhs) const; - bool operator>=(const Position& rhs) const; - - void shift(const Position& start, const Position& oldEnd, const Position& newEnd); -}; - -struct Location -{ - Position begin, end; - - Location() - : begin(0, 0) - , end(0, 0) - { - } - - Location(const Position& begin, const Position& end) - : begin(begin) - , end(end) - { - } - - Location(const Position& begin, unsigned int length) - : begin(begin) - , end(begin.line, begin.column + length) - { - } - - Location(const Location& begin, const Location& end) - : begin(begin.begin) - , end(end.end) - { - } - - bool operator==(const Location& rhs) const; - bool operator!=(const Location& rhs) const; - - bool encloses(const Location& l) const; - bool overlaps(const Location& l) const; - bool contains(const Position& p) const; - bool containsClosed(const Position& p) const; - void extend(const Location& other); - void shift(const Position& start, const Position& oldEnd, const Position& newEnd); -}; - -} // namespace Luau diff --git a/lib/luau/Ast/include/Luau/ParseOptions.h b/lib/luau/Ast/include/Luau/ParseOptions.h deleted file mode 100644 index 01f2a74..0000000 --- a/lib/luau/Ast/include/Luau/ParseOptions.h +++ /dev/null @@ -1,21 +0,0 @@ -// This file is part of the Luau programming language and is licensed under MIT License; see LICENSE.txt for details -#pragma once - -namespace Luau -{ - -enum class Mode -{ - NoCheck, // Do not perform any inference - Nonstrict, // Unannotated symbols are any - Strict, // Unannotated symbols are inferred - Definition, // Type definition module, has special parsing rules -}; - -struct ParseOptions -{ - bool allowDeclarationSyntax = false; - bool captureComments = false; -}; - -} // namespace Luau diff --git a/lib/luau/Ast/include/Luau/ParseResult.h b/lib/luau/Ast/include/Luau/ParseResult.h deleted file mode 100644 index 9c0a952..0000000 --- a/lib/luau/Ast/include/Luau/ParseResult.h +++ /dev/null @@ -1,71 +0,0 @@ -// This file is part of the Luau programming language and is licensed under MIT License; see LICENSE.txt for details -#pragma once - -#include "Luau/Common.h" -#include "Luau/Location.h" -#include "Luau/Lexer.h" -#include "Luau/StringUtils.h" - -namespace Luau -{ - -class AstStatBlock; - -class ParseError : public std::exception -{ -public: - ParseError(const Location& location, const std::string& message); - - virtual const char* what() const throw(); - - const Location& getLocation() const; - const std::string& getMessage() const; - - static LUAU_NORETURN void raise(const Location& location, const char* format, ...) LUAU_PRINTF_ATTR(2, 3); - -private: - Location location; - std::string message; -}; - -class ParseErrors : public std::exception -{ -public: - ParseErrors(std::vector errors); - - virtual const char* what() const throw(); - - const std::vector& getErrors() const; - -private: - std::vector errors; - std::string message; -}; - -struct HotComment -{ - bool header; - Location location; - std::string content; -}; - -struct Comment -{ - Lexeme::Type type; // Comment, BlockComment, or BrokenComment - Location location; -}; - -struct ParseResult -{ - AstStatBlock* root; - size_t lines = 0; - - std::vector hotcomments; - std::vector errors; - - std::vector commentLocations; -}; - -static constexpr const char* kParseNameError = "%error-id%"; - -} // namespace Luau diff --git a/lib/luau/Ast/include/Luau/Parser.h b/lib/luau/Ast/include/Luau/Parser.h deleted file mode 100644 index 96e9639..0000000 --- a/lib/luau/Ast/include/Luau/Parser.h +++ /dev/null @@ -1,416 +0,0 @@ -// This file is part of the Luau programming language and is licensed under MIT License; see LICENSE.txt for details -#pragma once - -#include "Luau/Ast.h" -#include "Luau/Lexer.h" -#include "Luau/ParseOptions.h" -#include "Luau/ParseResult.h" -#include "Luau/StringUtils.h" -#include "Luau/DenseHash.h" -#include "Luau/Common.h" - -#include -#include -#include - -namespace Luau -{ - -template -class TempVector -{ -public: - explicit TempVector(std::vector& storage); - - ~TempVector(); - - const T& operator[](std::size_t index) const; - - const T& front() const; - - const T& back() const; - - bool empty() const; - - std::size_t size() const; - - void push_back(const T& item); - - typename std::vector::const_iterator begin() const - { - return storage.begin() + offset; - } - typename std::vector::const_iterator end() const - { - return storage.begin() + offset + size_; - } - -private: - std::vector& storage; - size_t offset; - size_t size_; -}; - -class Parser -{ -public: - static ParseResult parse( - const char* buffer, std::size_t bufferSize, AstNameTable& names, Allocator& allocator, ParseOptions options = ParseOptions()); - -private: - struct Name; - struct Binding; - - Parser(const char* buffer, std::size_t bufferSize, AstNameTable& names, Allocator& allocator, const ParseOptions& options); - - bool blockFollow(const Lexeme& l); - - AstStatBlock* parseChunk(); - - // chunk ::= {stat [`;']} [laststat [`;']] - // block ::= chunk - AstStatBlock* parseBlock(); - - AstStatBlock* parseBlockNoScope(); - - // stat ::= - // varlist `=' explist | - // functioncall | - // do block end | - // while exp do block end | - // repeat block until exp | - // if exp then block {elseif exp then block} [else block] end | - // for Name `=' exp `,' exp [`,' exp] do block end | - // for namelist in explist do block end | - // function funcname funcbody | - // local function Name funcbody | - // local namelist [`=' explist] - // laststat ::= return [explist] | break - AstStat* parseStat(); - - // if exp then block {elseif exp then block} [else block] end - AstStat* parseIf(); - - // while exp do block end - AstStat* parseWhile(); - - // repeat block until exp - AstStat* parseRepeat(); - - // do block end - AstStat* parseDo(); - - // break - AstStat* parseBreak(); - - // continue - AstStat* parseContinue(const Location& start); - - // for Name `=' exp `,' exp [`,' exp] do block end | - // for namelist in explist do block end | - AstStat* parseFor(); - - // funcname ::= Name {`.' Name} [`:' Name] - AstExpr* parseFunctionName(Location start, bool& hasself, AstName& debugname); - - // function funcname funcbody - AstStat* parseFunctionStat(); - - // local function Name funcbody | - // local namelist [`=' explist] - AstStat* parseLocal(); - - // return [explist] - AstStat* parseReturn(); - - // type Name `=' Type - AstStat* parseTypeAlias(const Location& start, bool exported); - - AstDeclaredClassProp parseDeclaredClassMethod(); - - // `declare global' Name: Type | - // `declare function' Name`(' [parlist] `)' [`:` Type] - AstStat* parseDeclaration(const Location& start); - - // varlist `=' explist - AstStat* parseAssignment(AstExpr* initial); - - // var [`+=' | `-=' | `*=' | `/=' | `%=' | `^=' | `..='] exp - AstStat* parseCompoundAssignment(AstExpr* initial, AstExprBinary::Op op); - - std::pair> prepareFunctionArguments(const Location& start, bool hasself, const TempVector& args); - - // funcbodyhead ::= `(' [namelist [`,' `...'] | `...'] `)' [`:` Type] - // funcbody ::= funcbodyhead block end - std::pair parseFunctionBody( - bool hasself, const Lexeme& matchFunction, const AstName& debugname, const Name* localName); - - // explist ::= {exp `,'} exp - void parseExprList(TempVector& result); - - // binding ::= Name [`:` Type] - Binding parseBinding(); - - // bindinglist ::= (binding | `...') {`,' bindinglist} - // Returns the location of the vararg ..., or std::nullopt if the function is not vararg. - std::tuple parseBindingList(TempVector& result, bool allowDot3 = false); - - AstType* parseOptionalType(); - - // TypeList ::= Type [`,' TypeList] - // ReturnType ::= Type | `(' TypeList `)' - // TableProp ::= Name `:' Type - // TableIndexer ::= `[' Type `]' `:' Type - // PropList ::= (TableProp | TableIndexer) [`,' PropList] - // Type - // ::= Name - // | `nil` - // | `{' [PropList] `}' - // | `(' [TypeList] `)' `->` ReturnType - - // Returns the variadic annotation, if it exists. - AstTypePack* parseTypeList(TempVector& result, TempVector>& resultNames); - - std::optional parseOptionalReturnType(); - std::pair parseReturnType(); - - AstTableIndexer* parseTableIndexer(); - - AstTypeOrPack parseFunctionType(bool allowPack, bool isCheckedFunction = false); - AstType* parseFunctionTypeTail(const Lexeme& begin, AstArray generics, AstArray genericPacks, - AstArray params, AstArray> paramNames, AstTypePack* varargAnnotation, - bool isCheckedFunction = false); - - AstType* parseTableType(bool inDeclarationContext = false); - AstTypeOrPack parseSimpleType(bool allowPack, bool inDeclarationContext = false); - - AstTypeOrPack parseTypeOrPack(); - AstType* parseType(bool inDeclarationContext = false); - - AstTypePack* parseTypePack(); - AstTypePack* parseVariadicArgumentTypePack(); - - AstType* parseTypeSuffix(AstType* type, const Location& begin); - - static std::optional parseUnaryOp(const Lexeme& l); - static std::optional parseBinaryOp(const Lexeme& l); - static std::optional parseCompoundOp(const Lexeme& l); - - struct BinaryOpPriority - { - unsigned char left, right; - }; - - std::optional checkUnaryConfusables(); - std::optional checkBinaryConfusables(const BinaryOpPriority binaryPriority[], unsigned int limit); - - // subexpr -> (asexp | unop subexpr) { binop subexpr } - // where `binop' is any binary operator with a priority higher than `limit' - AstExpr* parseExpr(unsigned int limit = 0); - - // NAME - AstExpr* parseNameExpr(const char* context = nullptr); - - // prefixexp -> NAME | '(' expr ')' - AstExpr* parsePrefixExpr(); - - // primaryexp -> prefixexp { `.' NAME | `[' exp `]' | `:' NAME funcargs | funcargs } - AstExpr* parsePrimaryExpr(bool asStatement); - - // asexp -> simpleexp [`::' Type] - AstExpr* parseAssertionExpr(); - - // simpleexp -> NUMBER | STRING | NIL | true | false | ... | constructor | FUNCTION body | primaryexp - AstExpr* parseSimpleExpr(); - - // args ::= `(' [explist] `)' | tableconstructor | String - AstExpr* parseFunctionArgs(AstExpr* func, bool self); - - // tableconstructor ::= `{' [fieldlist] `}' - // fieldlist ::= field {fieldsep field} [fieldsep] - // field ::= `[' exp `]' `=' exp | Name `=' exp | exp - // fieldsep ::= `,' | `;' - AstExpr* parseTableConstructor(); - - // TODO: Add grammar rules here? - AstExpr* parseIfElseExpr(); - - // stringinterp ::= exp { exp} - AstExpr* parseInterpString(); - - // Name - std::optional parseNameOpt(const char* context = nullptr); - Name parseName(const char* context = nullptr); - Name parseIndexName(const char* context, const Position& previous); - - // `<' namelist `>' - std::pair, AstArray> parseGenericTypeList(bool withDefaultValues); - - // `<' Type[, ...] `>' - AstArray parseTypeParams(); - - std::optional> parseCharArray(); - AstExpr* parseString(); - AstExpr* parseNumber(); - - AstLocal* pushLocal(const Binding& binding); - - unsigned int saveLocals(); - - void restoreLocals(unsigned int offset); - - // check that parser is at lexeme/symbol, move to next lexeme/symbol on success, report failure and continue on failure - bool expectAndConsume(char value, const char* context = nullptr); - bool expectAndConsume(Lexeme::Type type, const char* context = nullptr); - void expectAndConsumeFail(Lexeme::Type type, const char* context); - - struct MatchLexeme - { - MatchLexeme(const Lexeme& l) - : type(l.type) - , position(l.location.begin) - { - } - - Lexeme::Type type; - Position position; - }; - - bool expectMatchAndConsume(char value, const MatchLexeme& begin, bool searchForMissing = false); - void expectMatchAndConsumeFail(Lexeme::Type type, const MatchLexeme& begin, const char* extra = nullptr); - bool expectMatchAndConsumeRecover(char value, const MatchLexeme& begin, bool searchForMissing); - - bool expectMatchEndAndConsume(Lexeme::Type type, const MatchLexeme& begin); - void expectMatchEndAndConsumeFail(Lexeme::Type type, const MatchLexeme& begin); - - template - AstArray copy(const T* data, std::size_t size); - - template - AstArray copy(const TempVector& data); - - template - AstArray copy(std::initializer_list data); - - AstArray copy(const std::string& data); - - void incrementRecursionCounter(const char* context); - - void report(const Location& location, const char* format, va_list args); - void report(const Location& location, const char* format, ...) LUAU_PRINTF_ATTR(3, 4); - - void reportNameError(const char* context); - - AstStatError* reportStatError(const Location& location, const AstArray& expressions, const AstArray& statements, - const char* format, ...) LUAU_PRINTF_ATTR(5, 6); - AstExprError* reportExprError(const Location& location, const AstArray& expressions, const char* format, ...) LUAU_PRINTF_ATTR(4, 5); - AstTypeError* reportTypeError(const Location& location, const AstArray& types, const char* format, ...) LUAU_PRINTF_ATTR(4, 5); - // `parseErrorLocation` is associated with the parser error - // `astErrorLocation` is associated with the AstTypeError created - // It can be useful to have different error locations so that the parse error can include the next lexeme, while the AstTypeError can precisely - // define the location (possibly of zero size) where a type annotation is expected. - AstTypeError* reportMissingTypeError(const Location& parseErrorLocation, const Location& astErrorLocation, const char* format, ...) - LUAU_PRINTF_ATTR(4, 5); - - AstExpr* reportFunctionArgsError(AstExpr* func, bool self); - void reportAmbiguousCallError(); - - void nextLexeme(); - - struct Function - { - bool vararg; - unsigned int loopDepth; - - Function() - : vararg(false) - , loopDepth(0) - { - } - }; - - struct Local - { - AstLocal* local; - unsigned int offset; - - Local() - : local(nullptr) - , offset(0) - { - } - }; - - struct Name - { - AstName name; - Location location; - - Name(const AstName& name, const Location& location) - : name(name) - , location(location) - { - } - }; - - struct Binding - { - Name name; - AstType* annotation; - - explicit Binding(const Name& name, AstType* annotation = nullptr) - : name(name) - , annotation(annotation) - { - } - }; - - ParseOptions options; - - Lexer lexer; - Allocator& allocator; - - std::vector commentLocations; - std::vector hotcomments; - - bool hotcommentHeader = true; - - unsigned int recursionCounter; - - AstName nameSelf; - AstName nameNumber; - AstName nameError; - AstName nameNil; - - MatchLexeme endMismatchSuspect; - - std::vector functionStack; - - DenseHashMap localMap; - std::vector localStack; - - std::vector parseErrors; - - std::vector matchRecoveryStopOnToken; - - std::vector scratchStat; - std::vector> scratchString; - std::vector scratchExpr; - std::vector scratchExprAux; - std::vector scratchName; - std::vector scratchPackName; - std::vector scratchBinding; - std::vector scratchLocal; - std::vector scratchTableTypeProps; - std::vector scratchType; - std::vector scratchTypeOrPack; - std::vector scratchDeclaredClassProps; - std::vector scratchItem; - std::vector scratchArgName; - std::vector scratchGenericTypes; - std::vector scratchGenericTypePacks; - std::vector> scratchOptArgName; - std::string scratchData; -}; - -} // namespace Luau diff --git a/lib/luau/Ast/include/Luau/StringUtils.h b/lib/luau/Ast/include/Luau/StringUtils.h deleted file mode 100644 index 6345fde..0000000 --- a/lib/luau/Ast/include/Luau/StringUtils.h +++ /dev/null @@ -1,36 +0,0 @@ -// This file is part of the Luau programming language and is licensed under MIT License; see LICENSE.txt for details -#pragma once - -#include "Luau/Common.h" - -#include -#include - -#include - -namespace Luau -{ - -std::string format(const char* fmt, ...) LUAU_PRINTF_ATTR(1, 2); -std::string vformat(const char* fmt, va_list args); - -void formatAppend(std::string& str, const char* fmt, ...) LUAU_PRINTF_ATTR(2, 3); -void vformatAppend(std::string& ret, const char* fmt, va_list args); - -std::string join(const std::vector& segments, std::string_view delimiter); -std::string join(const std::vector& segments, std::string_view delimiter); - -std::vector split(std::string_view s, char delimiter); - -// Computes the Damerau-Levenshtein distance of A and B. -// https://en.wikipedia.org/wiki/Damerau-Levenshtein_distance#Distance_with_adjacent_transpositions -size_t editDistance(std::string_view a, std::string_view b); - -bool startsWith(std::string_view lhs, std::string_view rhs); -bool equalsLower(std::string_view lhs, std::string_view rhs); - -size_t hashRange(const char* data, size_t size); - -std::string escape(std::string_view s, bool escapeForInterpString = false); -bool isIdentifier(std::string_view s); -} // namespace Luau diff --git a/lib/luau/Ast/include/Luau/TimeTrace.h b/lib/luau/Ast/include/Luau/TimeTrace.h deleted file mode 100644 index 2f7daf2..0000000 --- a/lib/luau/Ast/include/Luau/TimeTrace.h +++ /dev/null @@ -1,231 +0,0 @@ -// This file is part of the Luau programming language and is licensed under MIT License; see LICENSE.txt for details -#pragma once - -#include "Luau/Common.h" - -#include -#include - -#include - -LUAU_FASTFLAG(DebugLuauTimeTracing) - -namespace Luau -{ -namespace TimeTrace -{ -double getClock(); -uint32_t getClockMicroseconds(); -} // namespace TimeTrace -} // namespace Luau - -#if defined(LUAU_ENABLE_TIME_TRACE) - -namespace Luau -{ -namespace TimeTrace -{ -struct Token -{ - const char* name; - const char* category; -}; - -enum class EventType : uint8_t -{ - Enter, - Leave, - - ArgName, - ArgValue, -}; - -struct Event -{ - EventType type; - uint16_t token; - - union - { - uint32_t microsec; // 1 hour trace limit - uint32_t dataPos; - } data; -}; - -struct GlobalContext; -struct ThreadContext; - -std::shared_ptr getGlobalContext(); - -uint16_t createToken(GlobalContext& context, const char* name, const char* category); -uint32_t createThread(GlobalContext& context, ThreadContext* threadContext); -void releaseThread(GlobalContext& context, ThreadContext* threadContext); -void flushEvents(GlobalContext& context, uint32_t threadId, const std::vector& events, const std::vector& data); - -struct ThreadContext -{ - ThreadContext() - : globalContext(getGlobalContext()) - { - threadId = createThread(*globalContext, this); - } - - ~ThreadContext() - { - if (!events.empty()) - flushEvents(); - - releaseThread(*globalContext, this); - } - - void flushEvents() - { - static uint16_t flushToken = createToken(*globalContext, "flushEvents", "TimeTrace"); - - events.push_back({EventType::Enter, flushToken, {getClockMicroseconds()}}); - - TimeTrace::flushEvents(*globalContext, threadId, events, data); - - events.clear(); - data.clear(); - - events.push_back({EventType::Leave, 0, {getClockMicroseconds()}}); - } - - void eventEnter(uint16_t token) - { - eventEnter(token, getClockMicroseconds()); - } - - void eventEnter(uint16_t token, uint32_t microsec) - { - events.push_back({EventType::Enter, token, {microsec}}); - } - - void eventLeave() - { - eventLeave(getClockMicroseconds()); - } - - void eventLeave(uint32_t microsec) - { - events.push_back({EventType::Leave, 0, {microsec}}); - - if (events.size() > kEventFlushLimit) - flushEvents(); - } - - void eventArgument(const char* name, const char* value) - { - uint32_t pos = uint32_t(data.size()); - data.insert(data.end(), name, name + strlen(name) + 1); - events.push_back({EventType::ArgName, 0, {pos}}); - - pos = uint32_t(data.size()); - data.insert(data.end(), value, value + strlen(value) + 1); - events.push_back({EventType::ArgValue, 0, {pos}}); - } - - std::shared_ptr globalContext; - uint32_t threadId; - std::vector events; - std::vector data; - - static constexpr size_t kEventFlushLimit = 8192; -}; - -ThreadContext& getThreadContext(); - -struct Scope -{ - explicit Scope(uint16_t token) - : context(getThreadContext()) - { - if (!FFlag::DebugLuauTimeTracing) - return; - - context.eventEnter(token); - } - - ~Scope() - { - if (!FFlag::DebugLuauTimeTracing) - return; - - context.eventLeave(); - } - - ThreadContext& context; -}; - -struct OptionalTailScope -{ - explicit OptionalTailScope(uint16_t token, uint32_t threshold) - : context(getThreadContext()) - , token(token) - , threshold(threshold) - { - if (!FFlag::DebugLuauTimeTracing) - return; - - pos = uint32_t(context.events.size()); - microsec = getClockMicroseconds(); - } - - ~OptionalTailScope() - { - if (!FFlag::DebugLuauTimeTracing) - return; - - if (pos == context.events.size()) - { - uint32_t curr = getClockMicroseconds(); - - if (curr - microsec > threshold) - { - context.eventEnter(token, microsec); - context.eventLeave(curr); - } - } - } - - ThreadContext& context; - uint16_t token; - uint32_t threshold; - uint32_t microsec; - uint32_t pos; -}; - -LUAU_NOINLINE uint16_t createScopeData(const char* name, const char* category); - -} // namespace TimeTrace -} // namespace Luau - -// Regular scope -#define LUAU_TIMETRACE_SCOPE(name, category) \ - static uint16_t lttScopeStatic = Luau::TimeTrace::createScopeData(name, category); \ - Luau::TimeTrace::Scope lttScope(lttScopeStatic) - -// A scope without nested scopes that may be skipped if the time it took is less than the threshold -#define LUAU_TIMETRACE_OPTIONAL_TAIL_SCOPE(name, category, microsec) \ - static uint16_t lttScopeStaticOptTail = Luau::TimeTrace::createScopeData(name, category); \ - Luau::TimeTrace::OptionalTailScope lttScope(lttScopeStaticOptTail, microsec) - -// Extra key/value data can be added to regular scopes -#define LUAU_TIMETRACE_ARGUMENT(name, value) \ - do \ - { \ - if (FFlag::DebugLuauTimeTracing) \ - lttScope.context.eventArgument(name, value); \ - } while (false) - -#else - -#define LUAU_TIMETRACE_SCOPE(name, category) -#define LUAU_TIMETRACE_OPTIONAL_TAIL_SCOPE(name, category, microsec) -#define LUAU_TIMETRACE_ARGUMENT(name, value) \ - do \ - { \ - } while (false) - -#endif diff --git a/lib/luau/Ast/src/Ast.cpp b/lib/luau/Ast/src/Ast.cpp deleted file mode 100644 index 9a6ca4d..0000000 --- a/lib/luau/Ast/src/Ast.cpp +++ /dev/null @@ -1,1006 +0,0 @@ -// This file is part of the Luau programming language and is licensed under MIT License; see LICENSE.txt for details -#include "Luau/Ast.h" - -#include "Luau/Common.h" - - -namespace Luau -{ - -static void visitTypeList(AstVisitor* visitor, const AstTypeList& list) -{ - for (AstType* ty : list.types) - ty->visit(visitor); - - if (list.tailType) - list.tailType->visit(visitor); -} - -int gAstRttiIndex = 0; - -AstExprGroup::AstExprGroup(const Location& location, AstExpr* expr) - : AstExpr(ClassIndex(), location) - , expr(expr) -{ -} - -void AstExprGroup::visit(AstVisitor* visitor) -{ - if (visitor->visit(this)) - expr->visit(visitor); -} - -AstExprConstantNil::AstExprConstantNil(const Location& location) - : AstExpr(ClassIndex(), location) -{ -} - -void AstExprConstantNil::visit(AstVisitor* visitor) -{ - visitor->visit(this); -} - -AstExprConstantBool::AstExprConstantBool(const Location& location, bool value) - : AstExpr(ClassIndex(), location) - , value(value) -{ -} - -void AstExprConstantBool::visit(AstVisitor* visitor) -{ - visitor->visit(this); -} - -AstExprConstantNumber::AstExprConstantNumber(const Location& location, double value, ConstantNumberParseResult parseResult) - : AstExpr(ClassIndex(), location) - , value(value) - , parseResult(parseResult) -{ -} - -void AstExprConstantNumber::visit(AstVisitor* visitor) -{ - visitor->visit(this); -} - -AstExprConstantString::AstExprConstantString(const Location& location, const AstArray& value, QuoteStyle quoteStyle) - : AstExpr(ClassIndex(), location) - , value(value) - , quoteStyle(quoteStyle) -{ -} - -void AstExprConstantString::visit(AstVisitor* visitor) -{ - visitor->visit(this); -} - -AstExprLocal::AstExprLocal(const Location& location, AstLocal* local, bool upvalue) - : AstExpr(ClassIndex(), location) - , local(local) - , upvalue(upvalue) -{ -} - -void AstExprLocal::visit(AstVisitor* visitor) -{ - visitor->visit(this); -} - -AstExprGlobal::AstExprGlobal(const Location& location, const AstName& name) - : AstExpr(ClassIndex(), location) - , name(name) -{ -} - -void AstExprGlobal::visit(AstVisitor* visitor) -{ - visitor->visit(this); -} - -AstExprVarargs::AstExprVarargs(const Location& location) - : AstExpr(ClassIndex(), location) -{ -} - -void AstExprVarargs::visit(AstVisitor* visitor) -{ - visitor->visit(this); -} - -AstExprCall::AstExprCall(const Location& location, AstExpr* func, const AstArray& args, bool self, const Location& argLocation) - : AstExpr(ClassIndex(), location) - , func(func) - , args(args) - , self(self) - , argLocation(argLocation) -{ -} - -void AstExprCall::visit(AstVisitor* visitor) -{ - if (visitor->visit(this)) - { - func->visit(visitor); - - for (AstExpr* arg : args) - arg->visit(visitor); - } -} - -AstExprIndexName::AstExprIndexName( - const Location& location, AstExpr* expr, const AstName& index, const Location& indexLocation, const Position& opPosition, char op) - : AstExpr(ClassIndex(), location) - , expr(expr) - , index(index) - , indexLocation(indexLocation) - , opPosition(opPosition) - , op(op) -{ -} - -void AstExprIndexName::visit(AstVisitor* visitor) -{ - if (visitor->visit(this)) - expr->visit(visitor); -} - -AstExprIndexExpr::AstExprIndexExpr(const Location& location, AstExpr* expr, AstExpr* index) - : AstExpr(ClassIndex(), location) - , expr(expr) - , index(index) -{ -} - -void AstExprIndexExpr::visit(AstVisitor* visitor) -{ - if (visitor->visit(this)) - { - expr->visit(visitor); - index->visit(visitor); - } -} - -AstExprFunction::AstExprFunction(const Location& location, const AstArray& generics, const AstArray& genericPacks, - AstLocal* self, const AstArray& args, bool vararg, const Location& varargLocation, AstStatBlock* body, size_t functionDepth, - const AstName& debugname, const std::optional& returnAnnotation, AstTypePack* varargAnnotation, bool DEPRECATED_hasEnd, - const std::optional& argLocation) - : AstExpr(ClassIndex(), location) - , generics(generics) - , genericPacks(genericPacks) - , self(self) - , args(args) - , returnAnnotation(returnAnnotation) - , vararg(vararg) - , varargLocation(varargLocation) - , varargAnnotation(varargAnnotation) - , body(body) - , functionDepth(functionDepth) - , debugname(debugname) - , DEPRECATED_hasEnd(DEPRECATED_hasEnd) - , argLocation(argLocation) -{ -} - -void AstExprFunction::visit(AstVisitor* visitor) -{ - if (visitor->visit(this)) - { - for (AstLocal* arg : args) - { - if (arg->annotation) - arg->annotation->visit(visitor); - } - - if (varargAnnotation) - varargAnnotation->visit(visitor); - - if (returnAnnotation) - visitTypeList(visitor, *returnAnnotation); - - body->visit(visitor); - } -} - -AstExprTable::AstExprTable(const Location& location, const AstArray& items) - : AstExpr(ClassIndex(), location) - , items(items) -{ -} - -void AstExprTable::visit(AstVisitor* visitor) -{ - if (visitor->visit(this)) - { - for (const Item& item : items) - { - if (item.key) - item.key->visit(visitor); - - item.value->visit(visitor); - } - } -} - -AstExprUnary::AstExprUnary(const Location& location, Op op, AstExpr* expr) - : AstExpr(ClassIndex(), location) - , op(op) - , expr(expr) -{ -} - -void AstExprUnary::visit(AstVisitor* visitor) -{ - if (visitor->visit(this)) - expr->visit(visitor); -} - -std::string toString(AstExprUnary::Op op) -{ - switch (op) - { - case AstExprUnary::Minus: - return "-"; - case AstExprUnary::Not: - return "not"; - case AstExprUnary::Len: - return "#"; - default: - LUAU_ASSERT(false); - return ""; // MSVC requires this even though the switch/case is exhaustive - } -} - -AstExprBinary::AstExprBinary(const Location& location, Op op, AstExpr* left, AstExpr* right) - : AstExpr(ClassIndex(), location) - , op(op) - , left(left) - , right(right) -{ -} - -void AstExprBinary::visit(AstVisitor* visitor) -{ - if (visitor->visit(this)) - { - left->visit(visitor); - right->visit(visitor); - } -} - -std::string toString(AstExprBinary::Op op) -{ - switch (op) - { - case AstExprBinary::Add: - return "+"; - case AstExprBinary::Sub: - return "-"; - case AstExprBinary::Mul: - return "*"; - case AstExprBinary::Div: - return "/"; - case AstExprBinary::FloorDiv: - return "//"; - case AstExprBinary::Mod: - return "%"; - case AstExprBinary::Pow: - return "^"; - case AstExprBinary::Concat: - return ".."; - case AstExprBinary::CompareNe: - return "~="; - case AstExprBinary::CompareEq: - return "=="; - case AstExprBinary::CompareLt: - return "<"; - case AstExprBinary::CompareLe: - return "<="; - case AstExprBinary::CompareGt: - return ">"; - case AstExprBinary::CompareGe: - return ">="; - case AstExprBinary::And: - return "and"; - case AstExprBinary::Or: - return "or"; - default: - LUAU_ASSERT(false); - return ""; // MSVC requires this even though the switch/case is exhaustive - } -} - -AstExprTypeAssertion::AstExprTypeAssertion(const Location& location, AstExpr* expr, AstType* annotation) - : AstExpr(ClassIndex(), location) - , expr(expr) - , annotation(annotation) -{ -} - -void AstExprTypeAssertion::visit(AstVisitor* visitor) -{ - if (visitor->visit(this)) - { - expr->visit(visitor); - annotation->visit(visitor); - } -} - -AstExprIfElse::AstExprIfElse(const Location& location, AstExpr* condition, bool hasThen, AstExpr* trueExpr, bool hasElse, AstExpr* falseExpr) - : AstExpr(ClassIndex(), location) - , condition(condition) - , hasThen(hasThen) - , trueExpr(trueExpr) - , hasElse(hasElse) - , falseExpr(falseExpr) -{ -} - -void AstExprIfElse::visit(AstVisitor* visitor) -{ - if (visitor->visit(this)) - { - condition->visit(visitor); - trueExpr->visit(visitor); - falseExpr->visit(visitor); - } -} - -AstExprError::AstExprError(const Location& location, const AstArray& expressions, unsigned messageIndex) - : AstExpr(ClassIndex(), location) - , expressions(expressions) - , messageIndex(messageIndex) -{ -} - -AstExprInterpString::AstExprInterpString(const Location& location, const AstArray>& strings, const AstArray& expressions) - : AstExpr(ClassIndex(), location) - , strings(strings) - , expressions(expressions) -{ -} - -void AstExprInterpString::visit(AstVisitor* visitor) -{ - if (visitor->visit(this)) - { - for (AstExpr* expr : expressions) - expr->visit(visitor); - } -} - -void AstExprError::visit(AstVisitor* visitor) -{ - if (visitor->visit(this)) - { - for (AstExpr* expression : expressions) - expression->visit(visitor); - } -} - -AstStatBlock::AstStatBlock(const Location& location, const AstArray& body, bool hasEnd) - : AstStat(ClassIndex(), location) - , body(body) - , hasEnd(hasEnd) -{ -} - -void AstStatBlock::visit(AstVisitor* visitor) -{ - if (visitor->visit(this)) - { - for (AstStat* stat : body) - stat->visit(visitor); - } -} - -AstStatIf::AstStatIf(const Location& location, AstExpr* condition, AstStatBlock* thenbody, AstStat* elsebody, - const std::optional& thenLocation, const std::optional& elseLocation, bool DEPRECATED_hasEnd) - : AstStat(ClassIndex(), location) - , condition(condition) - , thenbody(thenbody) - , elsebody(elsebody) - , thenLocation(thenLocation) - , elseLocation(elseLocation) - , DEPRECATED_hasEnd(DEPRECATED_hasEnd) -{ -} - -void AstStatIf::visit(AstVisitor* visitor) -{ - if (visitor->visit(this)) - { - condition->visit(visitor); - thenbody->visit(visitor); - - if (elsebody) - elsebody->visit(visitor); - } -} - -AstStatWhile::AstStatWhile(const Location& location, AstExpr* condition, AstStatBlock* body, bool hasDo, const Location& doLocation, bool DEPRECATED_hasEnd) - : AstStat(ClassIndex(), location) - , condition(condition) - , body(body) - , hasDo(hasDo) - , doLocation(doLocation) - , DEPRECATED_hasEnd(DEPRECATED_hasEnd) -{ -} - -void AstStatWhile::visit(AstVisitor* visitor) -{ - if (visitor->visit(this)) - { - condition->visit(visitor); - body->visit(visitor); - } -} - -AstStatRepeat::AstStatRepeat(const Location& location, AstExpr* condition, AstStatBlock* body, bool DEPRECATED_hasUntil) - : AstStat(ClassIndex(), location) - , condition(condition) - , body(body) - , DEPRECATED_hasUntil(DEPRECATED_hasUntil) -{ -} - -void AstStatRepeat::visit(AstVisitor* visitor) -{ - if (visitor->visit(this)) - { - body->visit(visitor); - condition->visit(visitor); - } -} - -AstStatBreak::AstStatBreak(const Location& location) - : AstStat(ClassIndex(), location) -{ -} - -void AstStatBreak::visit(AstVisitor* visitor) -{ - visitor->visit(this); -} - -AstStatContinue::AstStatContinue(const Location& location) - : AstStat(ClassIndex(), location) -{ -} - -void AstStatContinue::visit(AstVisitor* visitor) -{ - visitor->visit(this); -} - -AstStatReturn::AstStatReturn(const Location& location, const AstArray& list) - : AstStat(ClassIndex(), location) - , list(list) -{ -} - -void AstStatReturn::visit(AstVisitor* visitor) -{ - if (visitor->visit(this)) - { - for (AstExpr* expr : list) - expr->visit(visitor); - } -} - -AstStatExpr::AstStatExpr(const Location& location, AstExpr* expr) - : AstStat(ClassIndex(), location) - , expr(expr) -{ -} - -void AstStatExpr::visit(AstVisitor* visitor) -{ - if (visitor->visit(this)) - expr->visit(visitor); -} - -AstStatLocal::AstStatLocal( - const Location& location, const AstArray& vars, const AstArray& values, const std::optional& equalsSignLocation) - : AstStat(ClassIndex(), location) - , vars(vars) - , values(values) - , equalsSignLocation(equalsSignLocation) -{ -} - -void AstStatLocal::visit(AstVisitor* visitor) -{ - if (visitor->visit(this)) - { - for (AstLocal* var : vars) - { - if (var->annotation) - var->annotation->visit(visitor); - } - - for (AstExpr* expr : values) - expr->visit(visitor); - } -} - -AstStatFor::AstStatFor(const Location& location, AstLocal* var, AstExpr* from, AstExpr* to, AstExpr* step, AstStatBlock* body, bool hasDo, - const Location& doLocation, bool DEPRECATED_hasEnd) - : AstStat(ClassIndex(), location) - , var(var) - , from(from) - , to(to) - , step(step) - , body(body) - , hasDo(hasDo) - , doLocation(doLocation) - , DEPRECATED_hasEnd(DEPRECATED_hasEnd) -{ -} - -void AstStatFor::visit(AstVisitor* visitor) -{ - if (visitor->visit(this)) - { - if (var->annotation) - var->annotation->visit(visitor); - - from->visit(visitor); - to->visit(visitor); - - if (step) - step->visit(visitor); - - body->visit(visitor); - } -} - -AstStatForIn::AstStatForIn(const Location& location, const AstArray& vars, const AstArray& values, AstStatBlock* body, - bool hasIn, const Location& inLocation, bool hasDo, const Location& doLocation, bool DEPRECATED_hasEnd) - : AstStat(ClassIndex(), location) - , vars(vars) - , values(values) - , body(body) - , hasIn(hasIn) - , inLocation(inLocation) - , hasDo(hasDo) - , doLocation(doLocation) - , DEPRECATED_hasEnd(DEPRECATED_hasEnd) -{ -} - -void AstStatForIn::visit(AstVisitor* visitor) -{ - if (visitor->visit(this)) - { - for (AstLocal* var : vars) - { - if (var->annotation) - var->annotation->visit(visitor); - } - - for (AstExpr* expr : values) - expr->visit(visitor); - - body->visit(visitor); - } -} - -AstStatAssign::AstStatAssign(const Location& location, const AstArray& vars, const AstArray& values) - : AstStat(ClassIndex(), location) - , vars(vars) - , values(values) -{ -} - -void AstStatAssign::visit(AstVisitor* visitor) -{ - if (visitor->visit(this)) - { - for (AstExpr* lvalue : vars) - lvalue->visit(visitor); - - for (AstExpr* expr : values) - expr->visit(visitor); - } -} - -AstStatCompoundAssign::AstStatCompoundAssign(const Location& location, AstExprBinary::Op op, AstExpr* var, AstExpr* value) - : AstStat(ClassIndex(), location) - , op(op) - , var(var) - , value(value) -{ -} - -void AstStatCompoundAssign::visit(AstVisitor* visitor) -{ - if (visitor->visit(this)) - { - var->visit(visitor); - value->visit(visitor); - } -} - -AstStatFunction::AstStatFunction(const Location& location, AstExpr* name, AstExprFunction* func) - : AstStat(ClassIndex(), location) - , name(name) - , func(func) -{ -} - -void AstStatFunction::visit(AstVisitor* visitor) -{ - if (visitor->visit(this)) - { - name->visit(visitor); - func->visit(visitor); - } -} - -AstStatLocalFunction::AstStatLocalFunction(const Location& location, AstLocal* name, AstExprFunction* func) - : AstStat(ClassIndex(), location) - , name(name) - , func(func) -{ -} - -void AstStatLocalFunction::visit(AstVisitor* visitor) -{ - if (visitor->visit(this)) - func->visit(visitor); -} - -AstStatTypeAlias::AstStatTypeAlias(const Location& location, const AstName& name, const Location& nameLocation, - const AstArray& generics, const AstArray& genericPacks, AstType* type, bool exported) - : AstStat(ClassIndex(), location) - , name(name) - , nameLocation(nameLocation) - , generics(generics) - , genericPacks(genericPacks) - , type(type) - , exported(exported) -{ -} - -void AstStatTypeAlias::visit(AstVisitor* visitor) -{ - if (visitor->visit(this)) - { - for (const AstGenericType& el : generics) - { - if (el.defaultValue) - el.defaultValue->visit(visitor); - } - - for (const AstGenericTypePack& el : genericPacks) - { - if (el.defaultValue) - el.defaultValue->visit(visitor); - } - - type->visit(visitor); - } -} - -AstStatDeclareGlobal::AstStatDeclareGlobal(const Location& location, const AstName& name, AstType* type) - : AstStat(ClassIndex(), location) - , name(name) - , type(type) -{ -} - -void AstStatDeclareGlobal::visit(AstVisitor* visitor) -{ - if (visitor->visit(this)) - type->visit(visitor); -} - -AstStatDeclareFunction::AstStatDeclareFunction(const Location& location, const AstName& name, const AstArray& generics, - const AstArray& genericPacks, const AstTypeList& params, const AstArray& paramNames, - const AstTypeList& retTypes) - : AstStat(ClassIndex(), location) - , name(name) - , generics(generics) - , genericPacks(genericPacks) - , params(params) - , paramNames(paramNames) - , retTypes(retTypes) - , checkedFunction(false) -{ -} - -AstStatDeclareFunction::AstStatDeclareFunction(const Location& location, const AstName& name, const AstArray& generics, - const AstArray& genericPacks, const AstTypeList& params, const AstArray& paramNames, - const AstTypeList& retTypes, bool checkedFunction) - : AstStat(ClassIndex(), location) - , name(name) - , generics(generics) - , genericPacks(genericPacks) - , params(params) - , paramNames(paramNames) - , retTypes(retTypes) - , checkedFunction(checkedFunction) -{ -} - -void AstStatDeclareFunction::visit(AstVisitor* visitor) -{ - if (visitor->visit(this)) - { - visitTypeList(visitor, params); - visitTypeList(visitor, retTypes); - } -} - -AstStatDeclareClass::AstStatDeclareClass(const Location& location, const AstName& name, std::optional superName, - const AstArray& props, AstTableIndexer* indexer) - : AstStat(ClassIndex(), location) - , name(name) - , superName(superName) - , props(props) - , indexer(indexer) -{ -} - -void AstStatDeclareClass::visit(AstVisitor* visitor) -{ - if (visitor->visit(this)) - { - for (const AstDeclaredClassProp& prop : props) - prop.ty->visit(visitor); - } -} - -AstStatError::AstStatError( - const Location& location, const AstArray& expressions, const AstArray& statements, unsigned messageIndex) - : AstStat(ClassIndex(), location) - , expressions(expressions) - , statements(statements) - , messageIndex(messageIndex) -{ -} - -void AstStatError::visit(AstVisitor* visitor) -{ - if (visitor->visit(this)) - { - for (AstNode* expression : expressions) - expression->visit(visitor); - - for (AstNode* statement : statements) - statement->visit(visitor); - } -} - -AstTypeReference::AstTypeReference(const Location& location, std::optional prefix, AstName name, std::optional prefixLocation, - const Location& nameLocation, bool hasParameterList, const AstArray& parameters) - : AstType(ClassIndex(), location) - , hasParameterList(hasParameterList) - , prefix(prefix) - , prefixLocation(prefixLocation) - , name(name) - , nameLocation(nameLocation) - , parameters(parameters) -{ -} - -void AstTypeReference::visit(AstVisitor* visitor) -{ - if (visitor->visit(this)) - { - for (const AstTypeOrPack& param : parameters) - { - if (param.type) - param.type->visit(visitor); - else - param.typePack->visit(visitor); - } - } -} - -AstTypeTable::AstTypeTable(const Location& location, const AstArray& props, AstTableIndexer* indexer) - : AstType(ClassIndex(), location) - , props(props) - , indexer(indexer) -{ -} - -void AstTypeTable::visit(AstVisitor* visitor) -{ - if (visitor->visit(this)) - { - for (const AstTableProp& prop : props) - prop.type->visit(visitor); - - if (indexer) - { - indexer->indexType->visit(visitor); - indexer->resultType->visit(visitor); - } - } -} - -AstTypeFunction::AstTypeFunction(const Location& location, const AstArray& generics, const AstArray& genericPacks, - const AstTypeList& argTypes, const AstArray>& argNames, const AstTypeList& returnTypes) - : AstType(ClassIndex(), location) - , generics(generics) - , genericPacks(genericPacks) - , argTypes(argTypes) - , argNames(argNames) - , returnTypes(returnTypes) - , checkedFunction(false) -{ - LUAU_ASSERT(argNames.size == 0 || argNames.size == argTypes.types.size); -} - -AstTypeFunction::AstTypeFunction(const Location& location, const AstArray& generics, const AstArray& genericPacks, - const AstTypeList& argTypes, const AstArray>& argNames, const AstTypeList& returnTypes, bool checkedFunction) - : AstType(ClassIndex(), location) - , generics(generics) - , genericPacks(genericPacks) - , argTypes(argTypes) - , argNames(argNames) - , returnTypes(returnTypes) - , checkedFunction(checkedFunction) -{ - LUAU_ASSERT(argNames.size == 0 || argNames.size == argTypes.types.size); -} - -void AstTypeFunction::visit(AstVisitor* visitor) -{ - if (visitor->visit(this)) - { - visitTypeList(visitor, argTypes); - visitTypeList(visitor, returnTypes); - } -} - -AstTypeTypeof::AstTypeTypeof(const Location& location, AstExpr* expr) - : AstType(ClassIndex(), location) - , expr(expr) -{ -} - -void AstTypeTypeof::visit(AstVisitor* visitor) -{ - if (visitor->visit(this)) - expr->visit(visitor); -} - -AstTypeUnion::AstTypeUnion(const Location& location, const AstArray& types) - : AstType(ClassIndex(), location) - , types(types) -{ -} - -void AstTypeUnion::visit(AstVisitor* visitor) -{ - if (visitor->visit(this)) - { - for (AstType* type : types) - type->visit(visitor); - } -} - -AstTypeIntersection::AstTypeIntersection(const Location& location, const AstArray& types) - : AstType(ClassIndex(), location) - , types(types) -{ -} - -void AstTypeIntersection::visit(AstVisitor* visitor) -{ - if (visitor->visit(this)) - { - for (AstType* type : types) - type->visit(visitor); - } -} - -AstTypeSingletonBool::AstTypeSingletonBool(const Location& location, bool value) - : AstType(ClassIndex(), location) - , value(value) -{ -} - -void AstTypeSingletonBool::visit(AstVisitor* visitor) -{ - visitor->visit(this); -} - -AstTypeSingletonString::AstTypeSingletonString(const Location& location, const AstArray& value) - : AstType(ClassIndex(), location) - , value(value) -{ -} - -void AstTypeSingletonString::visit(AstVisitor* visitor) -{ - visitor->visit(this); -} - -AstTypeError::AstTypeError(const Location& location, const AstArray& types, bool isMissing, unsigned messageIndex) - : AstType(ClassIndex(), location) - , types(types) - , isMissing(isMissing) - , messageIndex(messageIndex) -{ -} - -void AstTypeError::visit(AstVisitor* visitor) -{ - if (visitor->visit(this)) - { - for (AstType* type : types) - type->visit(visitor); - } -} - -AstTypePackExplicit::AstTypePackExplicit(const Location& location, AstTypeList typeList) - : AstTypePack(ClassIndex(), location) - , typeList(typeList) -{ -} - -void AstTypePackExplicit::visit(AstVisitor* visitor) -{ - if (visitor->visit(this)) - { - for (AstType* type : typeList.types) - type->visit(visitor); - - if (typeList.tailType) - typeList.tailType->visit(visitor); - } -} - -AstTypePackVariadic::AstTypePackVariadic(const Location& location, AstType* variadicType) - : AstTypePack(ClassIndex(), location) - , variadicType(variadicType) -{ -} - -void AstTypePackVariadic::visit(AstVisitor* visitor) -{ - if (visitor->visit(this)) - variadicType->visit(visitor); -} - -AstTypePackGeneric::AstTypePackGeneric(const Location& location, AstName name) - : AstTypePack(ClassIndex(), location) - , genericName(name) -{ -} - -void AstTypePackGeneric::visit(AstVisitor* visitor) -{ - visitor->visit(this); -} - -AstName getIdentifier(AstExpr* node) -{ - if (AstExprGlobal* expr = node->as()) - return expr->name; - - if (AstExprLocal* expr = node->as()) - return expr->local->name; - - return AstName(); -} - -Location getLocation(const AstTypeList& typeList) -{ - Location result; - if (typeList.types.size) - { - result = Location{typeList.types.data[0]->location, typeList.types.data[typeList.types.size - 1]->location}; - } - if (typeList.tailType) - result.end = typeList.tailType->location.end; - - return result; -} - -} // namespace Luau diff --git a/lib/luau/Ast/src/Confusables.cpp b/lib/luau/Ast/src/Confusables.cpp deleted file mode 100644 index 1c79215..0000000 --- a/lib/luau/Ast/src/Confusables.cpp +++ /dev/null @@ -1,1818 +0,0 @@ -// This file is part of the Luau programming language and is licensed under MIT License; see LICENSE.txt for details -#include "Luau/Confusables.h" - -#include -#include - -namespace Luau -{ - -struct Confusable -{ - unsigned codepoint : 24; - char text[5]; -}; - -// Derived from http://www.unicode.org/Public/security/10.0.0/confusables.txt; sorted by codepoint -// clang-format off -static const Confusable kConfusables[] = -{ - {34, "\""}, // MA#* ( " → '' ) QUOTATION MARK → APOSTROPHE, APOSTROPHE# # Converted to a quote. - {48, "O"}, // MA# ( 0 → O ) DIGIT ZERO → LATIN CAPITAL LETTER O# - {49, "l"}, // MA# ( 1 → l ) DIGIT ONE → LATIN SMALL LETTER L# - {73, "l"}, // MA# ( I → l ) LATIN CAPITAL LETTER I → LATIN SMALL LETTER L# - {96, "'"}, // MA#* ( ` → ' ) GRAVE ACCENT → APOSTROPHE# →ˋ→→`→→‘→ - {109, "rn"}, // MA# ( m → rn ) LATIN SMALL LETTER M → LATIN SMALL LETTER R, LATIN SMALL LETTER N# - {124, "l"}, // MA#* ( | → l ) VERTICAL LINE → LATIN SMALL LETTER L# - {160, " "}, // MA#* (   → ) NO-BREAK SPACE → SPACE# - {180, "'"}, // MA#* ( ´ → ' ) ACUTE ACCENT → APOSTROPHE# →΄→→ʹ→ - {184, ","}, // MA#* ( ¸ → , ) CEDILLA → COMMA# - {198, "AE"}, // MA# ( Æ → AE ) LATIN CAPITAL LETTER AE → LATIN CAPITAL LETTER A, LATIN CAPITAL LETTER E# - {215, "x"}, // MA#* ( × → x ) MULTIPLICATION SIGN → LATIN SMALL LETTER X# - {230, "ae"}, // MA# ( æ → ae ) LATIN SMALL LETTER AE → LATIN SMALL LETTER A, LATIN SMALL LETTER E# - {305, "i"}, // MA# ( ı → i ) LATIN SMALL LETTER DOTLESS I → LATIN SMALL LETTER I# - {306, "lJ"}, // MA# ( IJ → lJ ) LATIN CAPITAL LIGATURE IJ → LATIN SMALL LETTER L, LATIN CAPITAL LETTER J# →IJ→ - {307, "ij"}, // MA# ( ij → ij ) LATIN SMALL LIGATURE IJ → LATIN SMALL LETTER I, LATIN SMALL LETTER J# - {329, "'n"}, // MA# ( ʼn → 'n ) LATIN SMALL LETTER N PRECEDED BY APOSTROPHE → APOSTROPHE, LATIN SMALL LETTER N# →ʼn→ - {338, "OE"}, // MA# ( Œ → OE ) LATIN CAPITAL LIGATURE OE → LATIN CAPITAL LETTER O, LATIN CAPITAL LETTER E# - {339, "oe"}, // MA# ( œ → oe ) LATIN SMALL LIGATURE OE → LATIN SMALL LETTER O, LATIN SMALL LETTER E# - {383, "f"}, // MA# ( ſ → f ) LATIN SMALL LETTER LONG S → LATIN SMALL LETTER F# - {385, "'B"}, // MA# ( Ɓ → 'B ) LATIN CAPITAL LETTER B WITH HOOK → APOSTROPHE, LATIN CAPITAL LETTER B# →ʽB→ - {388, "b"}, // MA# ( Ƅ → b ) LATIN CAPITAL LETTER TONE SIX → LATIN SMALL LETTER B# - {391, "C'"}, // MA# ( Ƈ → C' ) LATIN CAPITAL LETTER C WITH HOOK → LATIN CAPITAL LETTER C, APOSTROPHE# →Cʽ→ - {394, "'D"}, // MA# ( Ɗ → 'D ) LATIN CAPITAL LETTER D WITH HOOK → APOSTROPHE, LATIN CAPITAL LETTER D# →ʽD→ - {397, "g"}, // MA# ( ƍ → g ) LATIN SMALL LETTER TURNED DELTA → LATIN SMALL LETTER G# - {403, "G'"}, // MA# ( Ɠ → G' ) LATIN CAPITAL LETTER G WITH HOOK → LATIN CAPITAL LETTER G, APOSTROPHE# →Gʽ→ - {406, "l"}, // MA# ( Ɩ → l ) LATIN CAPITAL LETTER IOTA → LATIN SMALL LETTER L# - {408, "K'"}, // MA# ( Ƙ → K' ) LATIN CAPITAL LETTER K WITH HOOK → LATIN CAPITAL LETTER K, APOSTROPHE# →Kʽ→ - {416, "O'"}, // MA# ( Ơ → O' ) LATIN CAPITAL LETTER O WITH HORN → LATIN CAPITAL LETTER O, APOSTROPHE# →Oʼ→ - {417, "o'"}, // MA# ( ơ → o' ) LATIN SMALL LETTER O WITH HORN → LATIN SMALL LETTER O, APOSTROPHE# →oʼ→ - {420, "'P"}, // MA# ( Ƥ → 'P ) LATIN CAPITAL LETTER P WITH HOOK → APOSTROPHE, LATIN CAPITAL LETTER P# →ʽP→ - {422, "R"}, // MA# ( Ʀ → R ) LATIN LETTER YR → LATIN CAPITAL LETTER R# - {423, "2"}, // MA# ( Ƨ → 2 ) LATIN CAPITAL LETTER TONE TWO → DIGIT TWO# - {428, "'T"}, // MA# ( Ƭ → 'T ) LATIN CAPITAL LETTER T WITH HOOK → APOSTROPHE, LATIN CAPITAL LETTER T# →ʽT→ - {435, "'Y"}, // MA# ( Ƴ → 'Y ) LATIN CAPITAL LETTER Y WITH HOOK → APOSTROPHE, LATIN CAPITAL LETTER Y# →ʽY→ - {439, "3"}, // MA# ( Ʒ → 3 ) LATIN CAPITAL LETTER EZH → DIGIT THREE# - {444, "5"}, // MA# ( Ƽ → 5 ) LATIN CAPITAL LETTER TONE FIVE → DIGIT FIVE# - {445, "s"}, // MA# ( ƽ → s ) LATIN SMALL LETTER TONE FIVE → LATIN SMALL LETTER S# - {448, "l"}, // MA# ( ǀ → l ) LATIN LETTER DENTAL CLICK → LATIN SMALL LETTER L# - {449, "ll"}, // MA# ( ǁ → ll ) LATIN LETTER LATERAL CLICK → LATIN SMALL LETTER L, LATIN SMALL LETTER L# →‖→→∥→→||→ - {451, "!"}, // MA# ( ǃ → ! ) LATIN LETTER RETROFLEX CLICK → EXCLAMATION MARK# - {455, "LJ"}, // MA# ( LJ → LJ ) LATIN CAPITAL LETTER LJ → LATIN CAPITAL LETTER L, LATIN CAPITAL LETTER J# - {456, "Lj"}, // MA# ( Lj → Lj ) LATIN CAPITAL LETTER L WITH SMALL LETTER J → LATIN CAPITAL LETTER L, LATIN SMALL LETTER J# - {457, "lj"}, // MA# ( lj → lj ) LATIN SMALL LETTER LJ → LATIN SMALL LETTER L, LATIN SMALL LETTER J# - {458, "NJ"}, // MA# ( NJ → NJ ) LATIN CAPITAL LETTER NJ → LATIN CAPITAL LETTER N, LATIN CAPITAL LETTER J# - {459, "Nj"}, // MA# ( Nj → Nj ) LATIN CAPITAL LETTER N WITH SMALL LETTER J → LATIN CAPITAL LETTER N, LATIN SMALL LETTER J# - {460, "nj"}, // MA# ( nj → nj ) LATIN SMALL LETTER NJ → LATIN SMALL LETTER N, LATIN SMALL LETTER J# - {497, "DZ"}, // MA# ( DZ → DZ ) LATIN CAPITAL LETTER DZ → LATIN CAPITAL LETTER D, LATIN CAPITAL LETTER Z# - {498, "Dz"}, // MA# ( Dz → Dz ) LATIN CAPITAL LETTER D WITH SMALL LETTER Z → LATIN CAPITAL LETTER D, LATIN SMALL LETTER Z# - {499, "dz"}, // MA# ( dz → dz ) LATIN SMALL LETTER DZ → LATIN SMALL LETTER D, LATIN SMALL LETTER Z# - {540, "3"}, // MA# ( Ȝ → 3 ) LATIN CAPITAL LETTER YOGH → DIGIT THREE# →Ʒ→ - {546, "8"}, // MA# ( Ȣ → 8 ) LATIN CAPITAL LETTER OU → DIGIT EIGHT# - {547, "8"}, // MA# ( ȣ → 8 ) LATIN SMALL LETTER OU → DIGIT EIGHT# - {577, "?"}, // MA# ( Ɂ → ? ) LATIN CAPITAL LETTER GLOTTAL STOP → QUESTION MARK# →ʔ→ - {593, "a"}, // MA# ( ɑ → a ) LATIN SMALL LETTER ALPHA → LATIN SMALL LETTER A# - {609, "g"}, // MA# ( ɡ → g ) LATIN SMALL LETTER SCRIPT G → LATIN SMALL LETTER G# - {611, "y"}, // MA# ( ɣ → y ) LATIN SMALL LETTER GAMMA → LATIN SMALL LETTER Y# →γ→ - {617, "i"}, // MA# ( ɩ → i ) LATIN SMALL LETTER IOTA → LATIN SMALL LETTER I# - {618, "i"}, // MA# ( ɪ → i ) LATIN LETTER SMALL CAPITAL I → LATIN SMALL LETTER I# →ı→ - {623, "w"}, // MA# ( ɯ → w ) LATIN SMALL LETTER TURNED M → LATIN SMALL LETTER W# - {651, "u"}, // MA# ( ʋ → u ) LATIN SMALL LETTER V WITH HOOK → LATIN SMALL LETTER U# - {655, "y"}, // MA# ( ʏ → y ) LATIN LETTER SMALL CAPITAL Y → LATIN SMALL LETTER Y# →ү→→γ→ - {660, "?"}, // MA# ( ʔ → ? ) LATIN LETTER GLOTTAL STOP → QUESTION MARK# - {675, "dz"}, // MA# ( ʣ → dz ) LATIN SMALL LETTER DZ DIGRAPH → LATIN SMALL LETTER D, LATIN SMALL LETTER Z# - {678, "ts"}, // MA# ( ʦ → ts ) LATIN SMALL LETTER TS DIGRAPH → LATIN SMALL LETTER T, LATIN SMALL LETTER S# - {682, "ls"}, // MA# ( ʪ → ls ) LATIN SMALL LETTER LS DIGRAPH → LATIN SMALL LETTER L, LATIN SMALL LETTER S# - {683, "lz"}, // MA# ( ʫ → lz ) LATIN SMALL LETTER LZ DIGRAPH → LATIN SMALL LETTER L, LATIN SMALL LETTER Z# - {697, "'"}, // MA# ( ʹ → ' ) MODIFIER LETTER PRIME → APOSTROPHE# - {698, "\""}, // MA# ( ʺ → '' ) MODIFIER LETTER DOUBLE PRIME → APOSTROPHE, APOSTROPHE# →"→# Converted to a quote. - {699, "'"}, // MA# ( ʻ → ' ) MODIFIER LETTER TURNED COMMA → APOSTROPHE# →‘→ - {700, "'"}, // MA# ( ʼ → ' ) MODIFIER LETTER APOSTROPHE → APOSTROPHE# →′→ - {701, "'"}, // MA# ( ʽ → ' ) MODIFIER LETTER REVERSED COMMA → APOSTROPHE# →‘→ - {702, "'"}, // MA# ( ʾ → ' ) MODIFIER LETTER RIGHT HALF RING → APOSTROPHE# →ʼ→→′→ - {706, "<"}, // MA#* ( ˂ → < ) MODIFIER LETTER LEFT ARROWHEAD → LESS-THAN SIGN# - {707, ">"}, // MA#* ( ˃ → > ) MODIFIER LETTER RIGHT ARROWHEAD → GREATER-THAN SIGN# - {708, "^"}, // MA#* ( ˄ → ^ ) MODIFIER LETTER UP ARROWHEAD → CIRCUMFLEX ACCENT# - {710, "^"}, // MA# ( ˆ → ^ ) MODIFIER LETTER CIRCUMFLEX ACCENT → CIRCUMFLEX ACCENT# - {712, "'"}, // MA# ( ˈ → ' ) MODIFIER LETTER VERTICAL LINE → APOSTROPHE# - {714, "'"}, // MA# ( ˊ → ' ) MODIFIER LETTER ACUTE ACCENT → APOSTROPHE# →ʹ→→′→ - {715, "'"}, // MA# ( ˋ → ' ) MODIFIER LETTER GRAVE ACCENT → APOSTROPHE# →`→→‘→ - {720, ":"}, // MA# ( ː → : ) MODIFIER LETTER TRIANGULAR COLON → COLON# - {727, "-"}, // MA#* ( ˗ → - ) MODIFIER LETTER MINUS SIGN → HYPHEN-MINUS# - {731, "i"}, // MA#* ( ˛ → i ) OGONEK → LATIN SMALL LETTER I# →ͺ→→ι→→ι→ - {732, "~"}, // MA#* ( ˜ → ~ ) SMALL TILDE → TILDE# - {733, "\""}, // MA#* ( ˝ → '' ) DOUBLE ACUTE ACCENT → APOSTROPHE, APOSTROPHE# →"→# Converted to a quote. - {750, "\""}, // MA# ( ˮ → '' ) MODIFIER LETTER DOUBLE APOSTROPHE → APOSTROPHE, APOSTROPHE# →″→→"→# Converted to a quote. - {756, "'"}, // MA#* ( ˴ → ' ) MODIFIER LETTER MIDDLE GRAVE ACCENT → APOSTROPHE# →ˋ→→`→→‘→ - {758, "\""}, // MA#* ( ˶ → '' ) MODIFIER LETTER MIDDLE DOUBLE ACUTE ACCENT → APOSTROPHE, APOSTROPHE# →˝→→"→# Converted to a quote. - {760, ":"}, // MA#* ( ˸ → : ) MODIFIER LETTER RAISED COLON → COLON# - {884, "'"}, // MA# ( ʹ → ' ) GREEK NUMERAL SIGN → APOSTROPHE# →′→ - {890, "i"}, // MA#* ( ͺ → i ) GREEK YPOGEGRAMMENI → LATIN SMALL LETTER I# →ι→→ι→ - {894, ";"}, // MA#* ( ; → ; ) GREEK QUESTION MARK → SEMICOLON# - {895, "J"}, // MA# ( Ϳ → J ) GREEK CAPITAL LETTER YOT → LATIN CAPITAL LETTER J# - {900, "'"}, // MA#* ( ΄ → ' ) GREEK TONOS → APOSTROPHE# →ʹ→ - {913, "A"}, // MA# ( Α → A ) GREEK CAPITAL LETTER ALPHA → LATIN CAPITAL LETTER A# - {914, "B"}, // MA# ( Β → B ) GREEK CAPITAL LETTER BETA → LATIN CAPITAL LETTER B# - {917, "E"}, // MA# ( Ε → E ) GREEK CAPITAL LETTER EPSILON → LATIN CAPITAL LETTER E# - {918, "Z"}, // MA# ( Ζ → Z ) GREEK CAPITAL LETTER ZETA → LATIN CAPITAL LETTER Z# - {919, "H"}, // MA# ( Η → H ) GREEK CAPITAL LETTER ETA → LATIN CAPITAL LETTER H# - {921, "l"}, // MA# ( Ι → l ) GREEK CAPITAL LETTER IOTA → LATIN SMALL LETTER L# - {922, "K"}, // MA# ( Κ → K ) GREEK CAPITAL LETTER KAPPA → LATIN CAPITAL LETTER K# - {924, "M"}, // MA# ( Μ → M ) GREEK CAPITAL LETTER MU → LATIN CAPITAL LETTER M# - {925, "N"}, // MA# ( Ν → N ) GREEK CAPITAL LETTER NU → LATIN CAPITAL LETTER N# - {927, "O"}, // MA# ( Ο → O ) GREEK CAPITAL LETTER OMICRON → LATIN CAPITAL LETTER O# - {929, "P"}, // MA# ( Ρ → P ) GREEK CAPITAL LETTER RHO → LATIN CAPITAL LETTER P# - {932, "T"}, // MA# ( Τ → T ) GREEK CAPITAL LETTER TAU → LATIN CAPITAL LETTER T# - {933, "Y"}, // MA# ( Υ → Y ) GREEK CAPITAL LETTER UPSILON → LATIN CAPITAL LETTER Y# - {935, "X"}, // MA# ( Χ → X ) GREEK CAPITAL LETTER CHI → LATIN CAPITAL LETTER X# - {945, "a"}, // MA# ( α → a ) GREEK SMALL LETTER ALPHA → LATIN SMALL LETTER A# - {947, "y"}, // MA# ( γ → y ) GREEK SMALL LETTER GAMMA → LATIN SMALL LETTER Y# - {953, "i"}, // MA# ( ι → i ) GREEK SMALL LETTER IOTA → LATIN SMALL LETTER I# - {957, "v"}, // MA# ( ν → v ) GREEK SMALL LETTER NU → LATIN SMALL LETTER V# - {959, "o"}, // MA# ( ο → o ) GREEK SMALL LETTER OMICRON → LATIN SMALL LETTER O# - {961, "p"}, // MA# ( ρ → p ) GREEK SMALL LETTER RHO → LATIN SMALL LETTER P# - {963, "o"}, // MA# ( σ → o ) GREEK SMALL LETTER SIGMA → LATIN SMALL LETTER O# - {965, "u"}, // MA# ( υ → u ) GREEK SMALL LETTER UPSILON → LATIN SMALL LETTER U# →ʋ→ - {978, "Y"}, // MA# ( ϒ → Y ) GREEK UPSILON WITH HOOK SYMBOL → LATIN CAPITAL LETTER Y# - {988, "F"}, // MA# ( Ϝ → F ) GREEK LETTER DIGAMMA → LATIN CAPITAL LETTER F# - {1000, "2"}, // MA# ( Ϩ → 2 ) COPTIC CAPITAL LETTER HORI → DIGIT TWO# →Ƨ→ - {1009, "p"}, // MA# ( ϱ → p ) GREEK RHO SYMBOL → LATIN SMALL LETTER P# →ρ→ - {1010, "c"}, // MA# ( ϲ → c ) GREEK LUNATE SIGMA SYMBOL → LATIN SMALL LETTER C# - {1011, "j"}, // MA# ( ϳ → j ) GREEK LETTER YOT → LATIN SMALL LETTER J# - {1017, "C"}, // MA# ( Ϲ → C ) GREEK CAPITAL LUNATE SIGMA SYMBOL → LATIN CAPITAL LETTER C# - {1018, "M"}, // MA# ( Ϻ → M ) GREEK CAPITAL LETTER SAN → LATIN CAPITAL LETTER M# - {1029, "S"}, // MA# ( Ѕ → S ) CYRILLIC CAPITAL LETTER DZE → LATIN CAPITAL LETTER S# - {1030, "l"}, // MA# ( І → l ) CYRILLIC CAPITAL LETTER BYELORUSSIAN-UKRAINIAN I → LATIN SMALL LETTER L# - {1032, "J"}, // MA# ( Ј → J ) CYRILLIC CAPITAL LETTER JE → LATIN CAPITAL LETTER J# - {1040, "A"}, // MA# ( А → A ) CYRILLIC CAPITAL LETTER A → LATIN CAPITAL LETTER A# - {1042, "B"}, // MA# ( В → B ) CYRILLIC CAPITAL LETTER VE → LATIN CAPITAL LETTER B# - {1045, "E"}, // MA# ( Е → E ) CYRILLIC CAPITAL LETTER IE → LATIN CAPITAL LETTER E# - {1047, "3"}, // MA# ( З → 3 ) CYRILLIC CAPITAL LETTER ZE → DIGIT THREE# - {1050, "K"}, // MA# ( К → K ) CYRILLIC CAPITAL LETTER KA → LATIN CAPITAL LETTER K# - {1052, "M"}, // MA# ( М → M ) CYRILLIC CAPITAL LETTER EM → LATIN CAPITAL LETTER M# - {1053, "H"}, // MA# ( Н → H ) CYRILLIC CAPITAL LETTER EN → LATIN CAPITAL LETTER H# - {1054, "O"}, // MA# ( О → O ) CYRILLIC CAPITAL LETTER O → LATIN CAPITAL LETTER O# - {1056, "P"}, // MA# ( Р → P ) CYRILLIC CAPITAL LETTER ER → LATIN CAPITAL LETTER P# - {1057, "C"}, // MA# ( С → C ) CYRILLIC CAPITAL LETTER ES → LATIN CAPITAL LETTER C# - {1058, "T"}, // MA# ( Т → T ) CYRILLIC CAPITAL LETTER TE → LATIN CAPITAL LETTER T# - {1059, "Y"}, // MA# ( У → Y ) CYRILLIC CAPITAL LETTER U → LATIN CAPITAL LETTER Y# - {1061, "X"}, // MA# ( Х → X ) CYRILLIC CAPITAL LETTER HA → LATIN CAPITAL LETTER X# - {1067, "bl"}, // MA# ( Ы → bl ) CYRILLIC CAPITAL LETTER YERU → LATIN SMALL LETTER B, LATIN SMALL LETTER L# →ЬІ→→Ь1→ - {1068, "b"}, // MA# ( Ь → b ) CYRILLIC CAPITAL LETTER SOFT SIGN → LATIN SMALL LETTER B# →Ƅ→ - {1070, "lO"}, // MA# ( Ю → lO ) CYRILLIC CAPITAL LETTER YU → LATIN SMALL LETTER L, LATIN CAPITAL LETTER O# →IO→ - {1072, "a"}, // MA# ( а → a ) CYRILLIC SMALL LETTER A → LATIN SMALL LETTER A# - {1073, "6"}, // MA# ( б → 6 ) CYRILLIC SMALL LETTER BE → DIGIT SIX# - {1075, "r"}, // MA# ( г → r ) CYRILLIC SMALL LETTER GHE → LATIN SMALL LETTER R# - {1077, "e"}, // MA# ( е → e ) CYRILLIC SMALL LETTER IE → LATIN SMALL LETTER E# - {1086, "o"}, // MA# ( о → o ) CYRILLIC SMALL LETTER O → LATIN SMALL LETTER O# - {1088, "p"}, // MA# ( р → p ) CYRILLIC SMALL LETTER ER → LATIN SMALL LETTER P# - {1089, "c"}, // MA# ( с → c ) CYRILLIC SMALL LETTER ES → LATIN SMALL LETTER C# - {1091, "y"}, // MA# ( у → y ) CYRILLIC SMALL LETTER U → LATIN SMALL LETTER Y# - {1093, "x"}, // MA# ( х → x ) CYRILLIC SMALL LETTER HA → LATIN SMALL LETTER X# - {1109, "s"}, // MA# ( ѕ → s ) CYRILLIC SMALL LETTER DZE → LATIN SMALL LETTER S# - {1110, "i"}, // MA# ( і → i ) CYRILLIC SMALL LETTER BYELORUSSIAN-UKRAINIAN I → LATIN SMALL LETTER I# - {1112, "j"}, // MA# ( ј → j ) CYRILLIC SMALL LETTER JE → LATIN SMALL LETTER J# - {1121, "w"}, // MA# ( ѡ → w ) CYRILLIC SMALL LETTER OMEGA → LATIN SMALL LETTER W# - {1140, "V"}, // MA# ( Ѵ → V ) CYRILLIC CAPITAL LETTER IZHITSA → LATIN CAPITAL LETTER V# - {1141, "v"}, // MA# ( ѵ → v ) CYRILLIC SMALL LETTER IZHITSA → LATIN SMALL LETTER V# - {1169, "r'"}, // MA# ( ґ → r' ) CYRILLIC SMALL LETTER GHE WITH UPTURN → LATIN SMALL LETTER R, APOSTROPHE# →гˈ→ - {1198, "Y"}, // MA# ( Ү → Y ) CYRILLIC CAPITAL LETTER STRAIGHT U → LATIN CAPITAL LETTER Y# - {1199, "y"}, // MA# ( ү → y ) CYRILLIC SMALL LETTER STRAIGHT U → LATIN SMALL LETTER Y# →γ→ - {1211, "h"}, // MA# ( һ → h ) CYRILLIC SMALL LETTER SHHA → LATIN SMALL LETTER H# - {1213, "e"}, // MA# ( ҽ → e ) CYRILLIC SMALL LETTER ABKHASIAN CHE → LATIN SMALL LETTER E# - {1216, "l"}, // MA# ( Ӏ → l ) CYRILLIC LETTER PALOCHKA → LATIN SMALL LETTER L# - {1231, "i"}, // MA# ( ӏ → i ) CYRILLIC SMALL LETTER PALOCHKA → LATIN SMALL LETTER I# →ı→ - {1236, "AE"}, // MA# ( Ӕ → AE ) CYRILLIC CAPITAL LIGATURE A IE → LATIN CAPITAL LETTER A, LATIN CAPITAL LETTER E# →Æ→ - {1237, "ae"}, // MA# ( ӕ → ae ) CYRILLIC SMALL LIGATURE A IE → LATIN SMALL LETTER A, LATIN SMALL LETTER E# →ае→ - {1248, "3"}, // MA# ( Ӡ → 3 ) CYRILLIC CAPITAL LETTER ABKHASIAN DZE → DIGIT THREE# →Ʒ→ - {1281, "d"}, // MA# ( ԁ → d ) CYRILLIC SMALL LETTER KOMI DE → LATIN SMALL LETTER D# - {1292, "G"}, // MA# ( Ԍ → G ) CYRILLIC CAPITAL LETTER KOMI SJE → LATIN CAPITAL LETTER G# - {1307, "q"}, // MA# ( ԛ → q ) CYRILLIC SMALL LETTER QA → LATIN SMALL LETTER Q# - {1308, "W"}, // MA# ( Ԝ → W ) CYRILLIC CAPITAL LETTER WE → LATIN CAPITAL LETTER W# - {1309, "w"}, // MA# ( ԝ → w ) CYRILLIC SMALL LETTER WE → LATIN SMALL LETTER W# - {1357, "U"}, // MA# ( Ս → U ) ARMENIAN CAPITAL LETTER SEH → LATIN CAPITAL LETTER U# - {1359, "S"}, // MA# ( Տ → S ) ARMENIAN CAPITAL LETTER TIWN → LATIN CAPITAL LETTER S# - {1365, "O"}, // MA# ( Օ → O ) ARMENIAN CAPITAL LETTER OH → LATIN CAPITAL LETTER O# - {1370, "'"}, // MA#* ( ՚ → ' ) ARMENIAN APOSTROPHE → APOSTROPHE# →’→ - {1373, "'"}, // MA#* ( ՝ → ' ) ARMENIAN COMMA → APOSTROPHE# →ˋ→→`→→‘→ - {1377, "w"}, // MA# ( ա → w ) ARMENIAN SMALL LETTER AYB → LATIN SMALL LETTER W# →ɯ→ - {1379, "q"}, // MA# ( գ → q ) ARMENIAN SMALL LETTER GIM → LATIN SMALL LETTER Q# - {1382, "q"}, // MA# ( զ → q ) ARMENIAN SMALL LETTER ZA → LATIN SMALL LETTER Q# - {1392, "h"}, // MA# ( հ → h ) ARMENIAN SMALL LETTER HO → LATIN SMALL LETTER H# - {1400, "n"}, // MA# ( ո → n ) ARMENIAN SMALL LETTER VO → LATIN SMALL LETTER N# - {1404, "n"}, // MA# ( ռ → n ) ARMENIAN SMALL LETTER RA → LATIN SMALL LETTER N# - {1405, "u"}, // MA# ( ս → u ) ARMENIAN SMALL LETTER SEH → LATIN SMALL LETTER U# - {1409, "g"}, // MA# ( ց → g ) ARMENIAN SMALL LETTER CO → LATIN SMALL LETTER G# - {1412, "f"}, // MA# ( ք → f ) ARMENIAN SMALL LETTER KEH → LATIN SMALL LETTER F# - {1413, "o"}, // MA# ( օ → o ) ARMENIAN SMALL LETTER OH → LATIN SMALL LETTER O# - {1417, ":"}, // MA#* ( ։ → : ) ARMENIAN FULL STOP → COLON# - {1472, "l"}, // MA#* ( ‎׀‎ → l ) HEBREW PUNCTUATION PASEQ → LATIN SMALL LETTER L# →|→ - {1475, ":"}, // MA#* ( ‎׃‎ → : ) HEBREW PUNCTUATION SOF PASUQ → COLON# - {1493, "l"}, // MA# ( ‎ו‎ → l ) HEBREW LETTER VAV → LATIN SMALL LETTER L# - {1496, "v"}, // MA# ( ‎ט‎ → v ) HEBREW LETTER TET → LATIN SMALL LETTER V# - {1497, "'"}, // MA# ( ‎י‎ → ' ) HEBREW LETTER YOD → APOSTROPHE# - {1503, "l"}, // MA# ( ‎ן‎ → l ) HEBREW LETTER FINAL NUN → LATIN SMALL LETTER L# - {1505, "o"}, // MA# ( ‎ס‎ → o ) HEBREW LETTER SAMEKH → LATIN SMALL LETTER O# - {1520, "ll"}, // MA# ( ‎װ‎ → ll ) HEBREW LIGATURE YIDDISH DOUBLE VAV → LATIN SMALL LETTER L, LATIN SMALL LETTER L# →‎וו‎→ - {1521, "l'"}, // MA# ( ‎ױ‎ → l' ) HEBREW LIGATURE YIDDISH VAV YOD → LATIN SMALL LETTER L, APOSTROPHE# →‎וי‎→ - {1522, "\""}, // MA# ( ‎ײ‎ → '' ) HEBREW LIGATURE YIDDISH DOUBLE YOD → APOSTROPHE, APOSTROPHE# →‎יי‎→# Converted to a quote. - {1523, "'"}, // MA#* ( ‎׳‎ → ' ) HEBREW PUNCTUATION GERESH → APOSTROPHE# - {1524, "\""}, // MA#* ( ‎״‎ → '' ) HEBREW PUNCTUATION GERSHAYIM → APOSTROPHE, APOSTROPHE# →"→# Converted to a quote. - {1549, ","}, // MA#* ( ‎؍‎ → , ) ARABIC DATE SEPARATOR → COMMA# →‎٫‎→ - {1575, "l"}, // MA# ( ‎ا‎ → l ) ARABIC LETTER ALEF → LATIN SMALL LETTER L# →1→ - {1607, "o"}, // MA# ( ‎ه‎ → o ) ARABIC LETTER HEH → LATIN SMALL LETTER O# - {1632, "."}, // MA# ( ‎٠‎ → . ) ARABIC-INDIC DIGIT ZERO → FULL STOP# - {1633, "l"}, // MA# ( ‎١‎ → l ) ARABIC-INDIC DIGIT ONE → LATIN SMALL LETTER L# →1→ - {1637, "o"}, // MA# ( ‎٥‎ → o ) ARABIC-INDIC DIGIT FIVE → LATIN SMALL LETTER O# - {1639, "V"}, // MA# ( ‎٧‎ → V ) ARABIC-INDIC DIGIT SEVEN → LATIN CAPITAL LETTER V# - {1643, ","}, // MA#* ( ‎٫‎ → , ) ARABIC DECIMAL SEPARATOR → COMMA# - {1645, "*"}, // MA#* ( ‎٭‎ → * ) ARABIC FIVE POINTED STAR → ASTERISK# - {1726, "o"}, // MA# ( ‎ھ‎ → o ) ARABIC LETTER HEH DOACHASHMEE → LATIN SMALL LETTER O# →‎ه‎→ - {1729, "o"}, // MA# ( ‎ہ‎ → o ) ARABIC LETTER HEH GOAL → LATIN SMALL LETTER O# →‎ه‎→ - {1748, "-"}, // MA#* ( ‎۔‎ → - ) ARABIC FULL STOP → HYPHEN-MINUS# →‐→ - {1749, "o"}, // MA# ( ‎ە‎ → o ) ARABIC LETTER AE → LATIN SMALL LETTER O# →‎ه‎→ - {1776, "."}, // MA# ( ۰ → . ) EXTENDED ARABIC-INDIC DIGIT ZERO → FULL STOP# →‎٠‎→ - {1777, "l"}, // MA# ( ۱ → l ) EXTENDED ARABIC-INDIC DIGIT ONE → LATIN SMALL LETTER L# →1→ - {1781, "o"}, // MA# ( ۵ → o ) EXTENDED ARABIC-INDIC DIGIT FIVE → LATIN SMALL LETTER O# →‎٥‎→ - {1783, "V"}, // MA# ( ۷ → V ) EXTENDED ARABIC-INDIC DIGIT SEVEN → LATIN CAPITAL LETTER V# →‎٧‎→ - {1793, "."}, // MA#* ( ‎܁‎ → . ) SYRIAC SUPRALINEAR FULL STOP → FULL STOP# - {1794, "."}, // MA#* ( ‎܂‎ → . ) SYRIAC SUBLINEAR FULL STOP → FULL STOP# - {1795, ":"}, // MA#* ( ‎܃‎ → : ) SYRIAC SUPRALINEAR COLON → COLON# - {1796, ":"}, // MA#* ( ‎܄‎ → : ) SYRIAC SUBLINEAR COLON → COLON# - {1984, "O"}, // MA# ( ‎߀‎ → O ) NKO DIGIT ZERO → LATIN CAPITAL LETTER O# →0→ - {1994, "l"}, // MA# ( ‎ߊ‎ → l ) NKO LETTER A → LATIN SMALL LETTER L# →∣→→ǀ→ - {2036, "'"}, // MA# ( ‎ߴ‎ → ' ) NKO HIGH TONE APOSTROPHE → APOSTROPHE# →’→ - {2037, "'"}, // MA# ( ‎ߵ‎ → ' ) NKO LOW TONE APOSTROPHE → APOSTROPHE# →‘→ - {2042, "_"}, // MA# ( ‎ߺ‎ → _ ) NKO LAJANYALAN → LOW LINE# - {2307, ":"}, // MA# ( ः → : ) DEVANAGARI SIGN VISARGA → COLON# - {2406, "o"}, // MA# ( ० → o ) DEVANAGARI DIGIT ZERO → LATIN SMALL LETTER O# - {2429, "?"}, // MA# ( ॽ → ? ) DEVANAGARI LETTER GLOTTAL STOP → QUESTION MARK# - {2534, "O"}, // MA# ( ০ → O ) BENGALI DIGIT ZERO → LATIN CAPITAL LETTER O# →0→ - {2538, "8"}, // MA# ( ৪ → 8 ) BENGALI DIGIT FOUR → DIGIT EIGHT# - {2541, "9"}, // MA# ( ৭ → 9 ) BENGALI DIGIT SEVEN → DIGIT NINE# - {2662, "o"}, // MA# ( ੦ → o ) GURMUKHI DIGIT ZERO → LATIN SMALL LETTER O# - {2663, "9"}, // MA# ( ੧ → 9 ) GURMUKHI DIGIT ONE → DIGIT NINE# - {2666, "8"}, // MA# ( ੪ → 8 ) GURMUKHI DIGIT FOUR → DIGIT EIGHT# - {2691, ":"}, // MA# ( ઃ → : ) GUJARATI SIGN VISARGA → COLON# - {2790, "o"}, // MA# ( ૦ → o ) GUJARATI DIGIT ZERO → LATIN SMALL LETTER O# - {2819, "8"}, // MA# ( ଃ → 8 ) ORIYA SIGN VISARGA → DIGIT EIGHT# - {2848, "O"}, // MA# ( ଠ → O ) ORIYA LETTER TTHA → LATIN CAPITAL LETTER O# →୦→→0→ - {2918, "O"}, // MA# ( ୦ → O ) ORIYA DIGIT ZERO → LATIN CAPITAL LETTER O# →0→ - {2920, "9"}, // MA# ( ୨ → 9 ) ORIYA DIGIT TWO → DIGIT NINE# - {3046, "o"}, // MA# ( ௦ → o ) TAMIL DIGIT ZERO → LATIN SMALL LETTER O# - {3074, "o"}, // MA# ( ం → o ) TELUGU SIGN ANUSVARA → LATIN SMALL LETTER O# - {3174, "o"}, // MA# ( ౦ → o ) TELUGU DIGIT ZERO → LATIN SMALL LETTER O# - {3202, "o"}, // MA# ( ಂ → o ) KANNADA SIGN ANUSVARA → LATIN SMALL LETTER O# - {3302, "o"}, // MA# ( ೦ → o ) KANNADA DIGIT ZERO → LATIN SMALL LETTER O# →౦→ - {3330, "o"}, // MA# ( ം → o ) MALAYALAM SIGN ANUSVARA → LATIN SMALL LETTER O# - {3360, "o"}, // MA# ( ഠ → o ) MALAYALAM LETTER TTHA → LATIN SMALL LETTER O# - {3430, "o"}, // MA# ( ൦ → o ) MALAYALAM DIGIT ZERO → LATIN SMALL LETTER O# - {3437, "9"}, // MA# ( ൭ → 9 ) MALAYALAM DIGIT SEVEN → DIGIT NINE# - {3458, "o"}, // MA# ( ං → o ) SINHALA SIGN ANUSVARAYA → LATIN SMALL LETTER O# - {3664, "o"}, // MA# ( ๐ → o ) THAI DIGIT ZERO → LATIN SMALL LETTER O# - {3792, "o"}, // MA# ( ໐ → o ) LAO DIGIT ZERO → LATIN SMALL LETTER O# - {4125, "o"}, // MA# ( ဝ → o ) MYANMAR LETTER WA → LATIN SMALL LETTER O# - {4160, "o"}, // MA# ( ၀ → o ) MYANMAR DIGIT ZERO → LATIN SMALL LETTER O# - {4327, "y"}, // MA# ( ყ → y ) GEORGIAN LETTER QAR → LATIN SMALL LETTER Y# - {4351, "o"}, // MA# ( ჿ → o ) GEORGIAN LETTER LABIAL SIGN → LATIN SMALL LETTER O# - {4608, "U"}, // MA# ( ሀ → U ) ETHIOPIC SYLLABLE HA → LATIN CAPITAL LETTER U# →Ս→ - {4816, "O"}, // MA# ( ዐ → O ) ETHIOPIC SYLLABLE PHARYNGEAL A → LATIN CAPITAL LETTER O# →Օ→ - {5024, "D"}, // MA# ( Ꭰ → D ) CHEROKEE LETTER A → LATIN CAPITAL LETTER D# - {5025, "R"}, // MA# ( Ꭱ → R ) CHEROKEE LETTER E → LATIN CAPITAL LETTER R# - {5026, "T"}, // MA# ( Ꭲ → T ) CHEROKEE LETTER I → LATIN CAPITAL LETTER T# - {5028, "O'"}, // MA# ( Ꭴ → O' ) CHEROKEE LETTER U → LATIN CAPITAL LETTER O, APOSTROPHE# →Ơ→→Oʼ→ - {5029, "i"}, // MA# ( Ꭵ → i ) CHEROKEE LETTER V → LATIN SMALL LETTER I# - {5033, "Y"}, // MA# ( Ꭹ → Y ) CHEROKEE LETTER GI → LATIN CAPITAL LETTER Y# - {5034, "A"}, // MA# ( Ꭺ → A ) CHEROKEE LETTER GO → LATIN CAPITAL LETTER A# - {5035, "J"}, // MA# ( Ꭻ → J ) CHEROKEE LETTER GU → LATIN CAPITAL LETTER J# - {5036, "E"}, // MA# ( Ꭼ → E ) CHEROKEE LETTER GV → LATIN CAPITAL LETTER E# - {5038, "?"}, // MA# ( Ꭾ → ? ) CHEROKEE LETTER HE → QUESTION MARK# →Ɂ→→ʔ→ - {5043, "W"}, // MA# ( Ꮃ → W ) CHEROKEE LETTER LA → LATIN CAPITAL LETTER W# - {5047, "M"}, // MA# ( Ꮇ → M ) CHEROKEE LETTER LU → LATIN CAPITAL LETTER M# - {5051, "H"}, // MA# ( Ꮋ → H ) CHEROKEE LETTER MI → LATIN CAPITAL LETTER H# - {5053, "Y"}, // MA# ( Ꮍ → Y ) CHEROKEE LETTER MU → LATIN CAPITAL LETTER Y# →Ꭹ→ - {5056, "G"}, // MA# ( Ꮐ → G ) CHEROKEE LETTER NAH → LATIN CAPITAL LETTER G# - {5058, "h"}, // MA# ( Ꮒ → h ) CHEROKEE LETTER NI → LATIN SMALL LETTER H# - {5059, "Z"}, // MA# ( Ꮓ → Z ) CHEROKEE LETTER NO → LATIN CAPITAL LETTER Z# - {5070, "4"}, // MA# ( Ꮞ → 4 ) CHEROKEE LETTER SE → DIGIT FOUR# - {5071, "b"}, // MA# ( Ꮟ → b ) CHEROKEE LETTER SI → LATIN SMALL LETTER B# - {5074, "R"}, // MA# ( Ꮢ → R ) CHEROKEE LETTER SV → LATIN CAPITAL LETTER R# - {5076, "W"}, // MA# ( Ꮤ → W ) CHEROKEE LETTER TA → LATIN CAPITAL LETTER W# - {5077, "S"}, // MA# ( Ꮥ → S ) CHEROKEE LETTER DE → LATIN CAPITAL LETTER S# - {5081, "V"}, // MA# ( Ꮩ → V ) CHEROKEE LETTER DO → LATIN CAPITAL LETTER V# - {5082, "S"}, // MA# ( Ꮪ → S ) CHEROKEE LETTER DU → LATIN CAPITAL LETTER S# - {5086, "L"}, // MA# ( Ꮮ → L ) CHEROKEE LETTER TLE → LATIN CAPITAL LETTER L# - {5087, "C"}, // MA# ( Ꮯ → C ) CHEROKEE LETTER TLI → LATIN CAPITAL LETTER C# - {5090, "P"}, // MA# ( Ꮲ → P ) CHEROKEE LETTER TLV → LATIN CAPITAL LETTER P# - {5094, "K"}, // MA# ( Ꮶ → K ) CHEROKEE LETTER TSO → LATIN CAPITAL LETTER K# - {5095, "d"}, // MA# ( Ꮷ → d ) CHEROKEE LETTER TSU → LATIN SMALL LETTER D# - {5102, "6"}, // MA# ( Ꮾ → 6 ) CHEROKEE LETTER WV → DIGIT SIX# - {5107, "G"}, // MA# ( Ᏻ → G ) CHEROKEE LETTER YU → LATIN CAPITAL LETTER G# - {5108, "B"}, // MA# ( Ᏼ → B ) CHEROKEE LETTER YV → LATIN CAPITAL LETTER B# - {5120, "="}, // MA#* ( ᐀ → = ) CANADIAN SYLLABICS HYPHEN → EQUALS SIGN# - {5167, "V"}, // MA# ( ᐯ → V ) CANADIAN SYLLABICS PE → LATIN CAPITAL LETTER V# - {5171, ">"}, // MA# ( ᐳ → > ) CANADIAN SYLLABICS PO → GREATER-THAN SIGN# - {5176, "<"}, // MA# ( ᐸ → < ) CANADIAN SYLLABICS PA → LESS-THAN SIGN# - {5194, "'"}, // MA# ( ᑊ → ' ) CANADIAN SYLLABICS WEST-CREE P → APOSTROPHE# →ˈ→ - {5196, "U"}, // MA# ( ᑌ → U ) CANADIAN SYLLABICS TE → LATIN CAPITAL LETTER U# - {5223, "U'"}, // MA# ( ᑧ → U' ) CANADIAN SYLLABICS TTE → LATIN CAPITAL LETTER U, APOSTROPHE# →ᑌᑊ→→ᑌ'→ - {5229, "P"}, // MA# ( ᑭ → P ) CANADIAN SYLLABICS KI → LATIN CAPITAL LETTER P# - {5231, "d"}, // MA# ( ᑯ → d ) CANADIAN SYLLABICS KO → LATIN SMALL LETTER D# - {5254, "P'"}, // MA# ( ᒆ → P' ) CANADIAN SYLLABICS SOUTH-SLAVEY KIH → LATIN CAPITAL LETTER P, APOSTROPHE# →ᑭᑊ→ - {5255, "d'"}, // MA# ( ᒇ → d' ) CANADIAN SYLLABICS SOUTH-SLAVEY KOH → LATIN SMALL LETTER D, APOSTROPHE# →ᑯᑊ→ - {5261, "J"}, // MA# ( ᒍ → J ) CANADIAN SYLLABICS CO → LATIN CAPITAL LETTER J# - {5290, "L"}, // MA# ( ᒪ → L ) CANADIAN SYLLABICS MA → LATIN CAPITAL LETTER L# - {5311, "2"}, // MA# ( ᒿ → 2 ) CANADIAN SYLLABICS SAYISI M → DIGIT TWO# - {5441, "x"}, // MA# ( ᕁ → x ) CANADIAN SYLLABICS SAYISI YI → LATIN SMALL LETTER X# →᙮→ - {5500, "H"}, // MA# ( ᕼ → H ) CANADIAN SYLLABICS NUNAVUT H → LATIN CAPITAL LETTER H# - {5501, "x"}, // MA# ( ᕽ → x ) CANADIAN SYLLABICS HK → LATIN SMALL LETTER X# →ᕁ→→᙮→ - {5511, "R"}, // MA# ( ᖇ → R ) CANADIAN SYLLABICS TLHI → LATIN CAPITAL LETTER R# - {5551, "b"}, // MA# ( ᖯ → b ) CANADIAN SYLLABICS AIVILIK B → LATIN SMALL LETTER B# - {5556, "F"}, // MA# ( ᖴ → F ) CANADIAN SYLLABICS BLACKFOOT WE → LATIN CAPITAL LETTER F# - {5573, "A"}, // MA# ( ᗅ → A ) CANADIAN SYLLABICS CARRIER GHO → LATIN CAPITAL LETTER A# - {5598, "D"}, // MA# ( ᗞ → D ) CANADIAN SYLLABICS CARRIER THE → LATIN CAPITAL LETTER D# - {5610, "D"}, // MA# ( ᗪ → D ) CANADIAN SYLLABICS CARRIER PE → LATIN CAPITAL LETTER D# →ᗞ→ - {5616, "M"}, // MA# ( ᗰ → M ) CANADIAN SYLLABICS CARRIER GO → LATIN CAPITAL LETTER M# - {5623, "B"}, // MA# ( ᗷ → B ) CANADIAN SYLLABICS CARRIER KHE → LATIN CAPITAL LETTER B# - {5741, "X"}, // MA#* ( ᙭ → X ) CANADIAN SYLLABICS CHI SIGN → LATIN CAPITAL LETTER X# - {5742, "x"}, // MA#* ( ᙮ → x ) CANADIAN SYLLABICS FULL STOP → LATIN SMALL LETTER X# - {5760, " "}, // MA#* (   → ) OGHAM SPACE MARK → SPACE# - {5810, "<"}, // MA# ( ᚲ → < ) RUNIC LETTER KAUNA → LESS-THAN SIGN# - {5815, "X"}, // MA# ( ᚷ → X ) RUNIC LETTER GEBO GYFU G → LATIN CAPITAL LETTER X# - {5825, "l"}, // MA# ( ᛁ → l ) RUNIC LETTER ISAZ IS ISS I → LATIN SMALL LETTER L# →I→ - {5836, "'"}, // MA# ( ᛌ → ' ) RUNIC LETTER SHORT-TWIG-SOL S → APOSTROPHE# - {5845, "K"}, // MA# ( ᛕ → K ) RUNIC LETTER OPEN-P → LATIN CAPITAL LETTER K# - {5846, "M"}, // MA# ( ᛖ → M ) RUNIC LETTER EHWAZ EH E → LATIN CAPITAL LETTER M# - {5868, ":"}, // MA#* ( ᛬ → : ) RUNIC MULTIPLE PUNCTUATION → COLON# - {5869, "+"}, // MA#* ( ᛭ → + ) RUNIC CROSS PUNCTUATION → PLUS SIGN# - {5941, "/"}, // MA#* ( ᜵ → / ) PHILIPPINE SINGLE PUNCTUATION → SOLIDUS# - {6147, ":"}, // MA#* ( ᠃ → : ) MONGOLIAN FULL STOP → COLON# - {6153, ":"}, // MA#* ( ᠉ → : ) MONGOLIAN MANCHU FULL STOP → COLON# - {7379, "\""}, // MA#* ( ᳓ → '' ) VEDIC SIGN NIHSHVASA → APOSTROPHE, APOSTROPHE# →″→→"→# Converted to a quote. - {7428, "c"}, // MA# ( ᴄ → c ) LATIN LETTER SMALL CAPITAL C → LATIN SMALL LETTER C# - {7439, "o"}, // MA# ( ᴏ → o ) LATIN LETTER SMALL CAPITAL O → LATIN SMALL LETTER O# - {7441, "o"}, // MA# ( ᴑ → o ) LATIN SMALL LETTER SIDEWAYS O → LATIN SMALL LETTER O# - {7452, "u"}, // MA# ( ᴜ → u ) LATIN LETTER SMALL CAPITAL U → LATIN SMALL LETTER U# - {7456, "v"}, // MA# ( ᴠ → v ) LATIN LETTER SMALL CAPITAL V → LATIN SMALL LETTER V# - {7457, "w"}, // MA# ( ᴡ → w ) LATIN LETTER SMALL CAPITAL W → LATIN SMALL LETTER W# - {7458, "z"}, // MA# ( ᴢ → z ) LATIN LETTER SMALL CAPITAL Z → LATIN SMALL LETTER Z# - {7462, "r"}, // MA# ( ᴦ → r ) GREEK LETTER SMALL CAPITAL GAMMA → LATIN SMALL LETTER R# →г→ - {7531, "ue"}, // MA# ( ᵫ → ue ) LATIN SMALL LETTER UE → LATIN SMALL LETTER U, LATIN SMALL LETTER E# - {7555, "g"}, // MA# ( ᶃ → g ) LATIN SMALL LETTER G WITH PALATAL HOOK → LATIN SMALL LETTER G# - {7564, "y"}, // MA# ( ᶌ → y ) LATIN SMALL LETTER V WITH PALATAL HOOK → LATIN SMALL LETTER Y# - {7837, "f"}, // MA# ( ẝ → f ) LATIN SMALL LETTER LONG S WITH HIGH STROKE → LATIN SMALL LETTER F# - {7935, "y"}, // MA# ( ỿ → y ) LATIN SMALL LETTER Y WITH LOOP → LATIN SMALL LETTER Y# - {8125, "'"}, // MA#* ( ᾽ → ' ) GREEK KORONIS → APOSTROPHE# →’→ - {8126, "i"}, // MA# ( ι → i ) GREEK PROSGEGRAMMENI → LATIN SMALL LETTER I# →ι→ - {8127, "'"}, // MA#* ( ᾿ → ' ) GREEK PSILI → APOSTROPHE# →’→ - {8128, "~"}, // MA#* ( ῀ → ~ ) GREEK PERISPOMENI → TILDE# →˜→ - {8175, "'"}, // MA#* ( ` → ' ) GREEK VARIA → APOSTROPHE# →ˋ→→`→→‘→ - {8189, "'"}, // MA#* ( ´ → ' ) GREEK OXIA → APOSTROPHE# →´→→΄→→ʹ→ - {8190, "'"}, // MA#* ( ῾ → ' ) GREEK DASIA → APOSTROPHE# →‛→→′→ - {8192, " "}, // MA#* (   → ) EN QUAD → SPACE# - {8193, " "}, // MA#* (   → ) EM QUAD → SPACE# - {8194, " "}, // MA#* (   → ) EN SPACE → SPACE# - {8195, " "}, // MA#* (   → ) EM SPACE → SPACE# - {8196, " "}, // MA#* (   → ) THREE-PER-EM SPACE → SPACE# - {8197, " "}, // MA#* (   → ) FOUR-PER-EM SPACE → SPACE# - {8198, " "}, // MA#* (   → ) SIX-PER-EM SPACE → SPACE# - {8199, " "}, // MA#* (   → ) FIGURE SPACE → SPACE# - {8200, " "}, // MA#* (   → ) PUNCTUATION SPACE → SPACE# - {8201, " "}, // MA#* (   → ) THIN SPACE → SPACE# - {8202, " "}, // MA#* (   → ) HAIR SPACE → SPACE# - {8208, "-"}, // MA#* ( ‐ → - ) HYPHEN → HYPHEN-MINUS# - {8209, "-"}, // MA#* ( ‑ → - ) NON-BREAKING HYPHEN → HYPHEN-MINUS# - {8210, "-"}, // MA#* ( ‒ → - ) FIGURE DASH → HYPHEN-MINUS# - {8211, "-"}, // MA#* ( – → - ) EN DASH → HYPHEN-MINUS# - {8214, "ll"}, // MA#* ( ‖ → ll ) DOUBLE VERTICAL LINE → LATIN SMALL LETTER L, LATIN SMALL LETTER L# →∥→→||→ - {8216, "'"}, // MA#* ( ‘ → ' ) LEFT SINGLE QUOTATION MARK → APOSTROPHE# - {8217, "'"}, // MA#* ( ’ → ' ) RIGHT SINGLE QUOTATION MARK → APOSTROPHE# - {8218, ","}, // MA#* ( ‚ → , ) SINGLE LOW-9 QUOTATION MARK → COMMA# - {8219, "'"}, // MA#* ( ‛ → ' ) SINGLE HIGH-REVERSED-9 QUOTATION MARK → APOSTROPHE# →′→ - {8220, "\""}, // MA#* ( “ → '' ) LEFT DOUBLE QUOTATION MARK → APOSTROPHE, APOSTROPHE# →"→# Converted to a quote. - {8221, "\""}, // MA#* ( ” → '' ) RIGHT DOUBLE QUOTATION MARK → APOSTROPHE, APOSTROPHE# →"→# Converted to a quote. - {8223, "\""}, // MA#* ( ‟ → '' ) DOUBLE HIGH-REVERSED-9 QUOTATION MARK → APOSTROPHE, APOSTROPHE# →“→→"→# Converted to a quote. - {8228, "."}, // MA#* ( ․ → . ) ONE DOT LEADER → FULL STOP# - {8229, ".."}, // MA#* ( ‥ → .. ) TWO DOT LEADER → FULL STOP, FULL STOP# - {8230, "..."}, // MA#* ( … → ... ) HORIZONTAL ELLIPSIS → FULL STOP, FULL STOP, FULL STOP# - {8232, " "}, // MA#* ( → ) LINE SEPARATOR → SPACE# - {8233, " "}, // MA#* ( → ) PARAGRAPH SEPARATOR → SPACE# - {8239, " "}, // MA#* (   → ) NARROW NO-BREAK SPACE → SPACE# - {8242, "'"}, // MA#* ( ′ → ' ) PRIME → APOSTROPHE# - {8243, "\""}, // MA#* ( ″ → '' ) DOUBLE PRIME → APOSTROPHE, APOSTROPHE# →"→# Converted to a quote. - {8244, "'''"}, // MA#* ( ‴ → ''' ) TRIPLE PRIME → APOSTROPHE, APOSTROPHE, APOSTROPHE# →′′′→ - {8245, "'"}, // MA#* ( ‵ → ' ) REVERSED PRIME → APOSTROPHE# →ʽ→→‘→ - {8246, "\""}, // MA#* ( ‶ → '' ) REVERSED DOUBLE PRIME → APOSTROPHE, APOSTROPHE# →‵‵→# Converted to a quote. - {8247, "'''"}, // MA#* ( ‷ → ''' ) REVERSED TRIPLE PRIME → APOSTROPHE, APOSTROPHE, APOSTROPHE# →‵‵‵→ - {8249, "<"}, // MA#* ( ‹ → < ) SINGLE LEFT-POINTING ANGLE QUOTATION MARK → LESS-THAN SIGN# - {8250, ">"}, // MA#* ( › → > ) SINGLE RIGHT-POINTING ANGLE QUOTATION MARK → GREATER-THAN SIGN# - {8252, "!!"}, // MA#* ( ‼ → !! ) DOUBLE EXCLAMATION MARK → EXCLAMATION MARK, EXCLAMATION MARK# - {8257, "/"}, // MA#* ( ⁁ → / ) CARET INSERTION POINT → SOLIDUS# - {8259, "-"}, // MA#* ( ⁃ → - ) HYPHEN BULLET → HYPHEN-MINUS# →‐→ - {8260, "/"}, // MA#* ( ⁄ → / ) FRACTION SLASH → SOLIDUS# - {8263, "??"}, // MA#* ( ⁇ → ?? ) DOUBLE QUESTION MARK → QUESTION MARK, QUESTION MARK# - {8264, "?!"}, // MA#* ( ⁈ → ?! ) QUESTION EXCLAMATION MARK → QUESTION MARK, EXCLAMATION MARK# - {8265, "!?"}, // MA#* ( ⁉ → !? ) EXCLAMATION QUESTION MARK → EXCLAMATION MARK, QUESTION MARK# - {8270, "*"}, // MA#* ( ⁎ → * ) LOW ASTERISK → ASTERISK# - {8275, "~"}, // MA#* ( ⁓ → ~ ) SWUNG DASH → TILDE# - {8279, "''''"}, // MA#* ( ⁗ → '''' ) QUADRUPLE PRIME → APOSTROPHE, APOSTROPHE, APOSTROPHE, APOSTROPHE# →′′′′→ - {8282, ":"}, // MA#* ( ⁚ → : ) TWO DOT PUNCTUATION → COLON# - {8287, " "}, // MA#* (   → ) MEDIUM MATHEMATICAL SPACE → SPACE# - {8360, "Rs"}, // MA#* ( ₨ → Rs ) RUPEE SIGN → LATIN CAPITAL LETTER R, LATIN SMALL LETTER S# - {8374, "lt"}, // MA#* ( ₶ → lt ) LIVRE TOURNOIS SIGN → LATIN SMALL LETTER L, LATIN SMALL LETTER T# - {8448, "a/c"}, // MA#* ( ℀ → a/c ) ACCOUNT OF → LATIN SMALL LETTER A, SOLIDUS, LATIN SMALL LETTER C# - {8449, "a/s"}, // MA#* ( ℁ → a/s ) ADDRESSED TO THE SUBJECT → LATIN SMALL LETTER A, SOLIDUS, LATIN SMALL LETTER S# - {8450, "C"}, // MA# ( ℂ → C ) DOUBLE-STRUCK CAPITAL C → LATIN CAPITAL LETTER C# - {8453, "c/o"}, // MA#* ( ℅ → c/o ) CARE OF → LATIN SMALL LETTER C, SOLIDUS, LATIN SMALL LETTER O# - {8454, "c/u"}, // MA#* ( ℆ → c/u ) CADA UNA → LATIN SMALL LETTER C, SOLIDUS, LATIN SMALL LETTER U# - {8458, "g"}, // MA# ( ℊ → g ) SCRIPT SMALL G → LATIN SMALL LETTER G# - {8459, "H"}, // MA# ( ℋ → H ) SCRIPT CAPITAL H → LATIN CAPITAL LETTER H# - {8460, "H"}, // MA# ( ℌ → H ) BLACK-LETTER CAPITAL H → LATIN CAPITAL LETTER H# - {8461, "H"}, // MA# ( ℍ → H ) DOUBLE-STRUCK CAPITAL H → LATIN CAPITAL LETTER H# - {8462, "h"}, // MA# ( ℎ → h ) PLANCK CONSTANT → LATIN SMALL LETTER H# - {8464, "l"}, // MA# ( ℐ → l ) SCRIPT CAPITAL I → LATIN SMALL LETTER L# →I→ - {8465, "l"}, // MA# ( ℑ → l ) BLACK-LETTER CAPITAL I → LATIN SMALL LETTER L# →I→ - {8466, "L"}, // MA# ( ℒ → L ) SCRIPT CAPITAL L → LATIN CAPITAL LETTER L# - {8467, "l"}, // MA# ( ℓ → l ) SCRIPT SMALL L → LATIN SMALL LETTER L# - {8469, "N"}, // MA# ( ℕ → N ) DOUBLE-STRUCK CAPITAL N → LATIN CAPITAL LETTER N# - {8470, "No"}, // MA#* ( № → No ) NUMERO SIGN → LATIN CAPITAL LETTER N, LATIN SMALL LETTER O# - {8473, "P"}, // MA# ( ℙ → P ) DOUBLE-STRUCK CAPITAL P → LATIN CAPITAL LETTER P# - {8474, "Q"}, // MA# ( ℚ → Q ) DOUBLE-STRUCK CAPITAL Q → LATIN CAPITAL LETTER Q# - {8475, "R"}, // MA# ( ℛ → R ) SCRIPT CAPITAL R → LATIN CAPITAL LETTER R# - {8476, "R"}, // MA# ( ℜ → R ) BLACK-LETTER CAPITAL R → LATIN CAPITAL LETTER R# - {8477, "R"}, // MA# ( ℝ → R ) DOUBLE-STRUCK CAPITAL R → LATIN CAPITAL LETTER R# - {8481, "TEL"}, // MA#* ( ℡ → TEL ) TELEPHONE SIGN → LATIN CAPITAL LETTER T, LATIN CAPITAL LETTER E, LATIN CAPITAL LETTER L# - {8484, "Z"}, // MA# ( ℤ → Z ) DOUBLE-STRUCK CAPITAL Z → LATIN CAPITAL LETTER Z# - {8488, "Z"}, // MA# ( ℨ → Z ) BLACK-LETTER CAPITAL Z → LATIN CAPITAL LETTER Z# - {8490, "K"}, // MA# ( K → K ) KELVIN SIGN → LATIN CAPITAL LETTER K# - {8492, "B"}, // MA# ( ℬ → B ) SCRIPT CAPITAL B → LATIN CAPITAL LETTER B# - {8493, "C"}, // MA# ( ℭ → C ) BLACK-LETTER CAPITAL C → LATIN CAPITAL LETTER C# - {8494, "e"}, // MA# ( ℮ → e ) ESTIMATED SYMBOL → LATIN SMALL LETTER E# - {8495, "e"}, // MA# ( ℯ → e ) SCRIPT SMALL E → LATIN SMALL LETTER E# - {8496, "E"}, // MA# ( ℰ → E ) SCRIPT CAPITAL E → LATIN CAPITAL LETTER E# - {8497, "F"}, // MA# ( ℱ → F ) SCRIPT CAPITAL F → LATIN CAPITAL LETTER F# - {8499, "M"}, // MA# ( ℳ → M ) SCRIPT CAPITAL M → LATIN CAPITAL LETTER M# - {8500, "o"}, // MA# ( ℴ → o ) SCRIPT SMALL O → LATIN SMALL LETTER O# - {8505, "i"}, // MA# ( ℹ → i ) INFORMATION SOURCE → LATIN SMALL LETTER I# - {8507, "FAX"}, // MA#* ( ℻ → FAX ) FACSIMILE SIGN → LATIN CAPITAL LETTER F, LATIN CAPITAL LETTER A, LATIN CAPITAL LETTER X# - {8509, "y"}, // MA# ( ℽ → y ) DOUBLE-STRUCK SMALL GAMMA → LATIN SMALL LETTER Y# →γ→ - {8517, "D"}, // MA# ( ⅅ → D ) DOUBLE-STRUCK ITALIC CAPITAL D → LATIN CAPITAL LETTER D# - {8518, "d"}, // MA# ( ⅆ → d ) DOUBLE-STRUCK ITALIC SMALL D → LATIN SMALL LETTER D# - {8519, "e"}, // MA# ( ⅇ → e ) DOUBLE-STRUCK ITALIC SMALL E → LATIN SMALL LETTER E# - {8520, "i"}, // MA# ( ⅈ → i ) DOUBLE-STRUCK ITALIC SMALL I → LATIN SMALL LETTER I# - {8521, "j"}, // MA# ( ⅉ → j ) DOUBLE-STRUCK ITALIC SMALL J → LATIN SMALL LETTER J# - {8544, "l"}, // MA# ( Ⅰ → l ) ROMAN NUMERAL ONE → LATIN SMALL LETTER L# →Ӏ→ - {8545, "ll"}, // MA# ( Ⅱ → ll ) ROMAN NUMERAL TWO → LATIN SMALL LETTER L, LATIN SMALL LETTER L# →II→ - {8546, "lll"}, // MA# ( Ⅲ → lll ) ROMAN NUMERAL THREE → LATIN SMALL LETTER L, LATIN SMALL LETTER L, LATIN SMALL LETTER L# →III→ - {8547, "lV"}, // MA# ( Ⅳ → lV ) ROMAN NUMERAL FOUR → LATIN SMALL LETTER L, LATIN CAPITAL LETTER V# →IV→ - {8548, "V"}, // MA# ( Ⅴ → V ) ROMAN NUMERAL FIVE → LATIN CAPITAL LETTER V# - {8549, "Vl"}, // MA# ( Ⅵ → Vl ) ROMAN NUMERAL SIX → LATIN CAPITAL LETTER V, LATIN SMALL LETTER L# →VI→ - {8550, "Vll"}, // MA# ( Ⅶ → Vll ) ROMAN NUMERAL SEVEN → LATIN CAPITAL LETTER V, LATIN SMALL LETTER L, LATIN SMALL LETTER L# →VII→ - {8551, "Vlll"}, // MA# ( Ⅷ → Vlll ) ROMAN NUMERAL EIGHT → LATIN CAPITAL LETTER V, LATIN SMALL LETTER L, LATIN SMALL LETTER L, LATIN SMALL LETTER L# →VIII→ - {8552, "lX"}, // MA# ( Ⅸ → lX ) ROMAN NUMERAL NINE → LATIN SMALL LETTER L, LATIN CAPITAL LETTER X# →IX→ - {8553, "X"}, // MA# ( Ⅹ → X ) ROMAN NUMERAL TEN → LATIN CAPITAL LETTER X# - {8554, "Xl"}, // MA# ( Ⅺ → Xl ) ROMAN NUMERAL ELEVEN → LATIN CAPITAL LETTER X, LATIN SMALL LETTER L# →XI→ - {8555, "Xll"}, // MA# ( Ⅻ → Xll ) ROMAN NUMERAL TWELVE → LATIN CAPITAL LETTER X, LATIN SMALL LETTER L, LATIN SMALL LETTER L# →XII→ - {8556, "L"}, // MA# ( Ⅼ → L ) ROMAN NUMERAL FIFTY → LATIN CAPITAL LETTER L# - {8557, "C"}, // MA# ( Ⅽ → C ) ROMAN NUMERAL ONE HUNDRED → LATIN CAPITAL LETTER C# - {8558, "D"}, // MA# ( Ⅾ → D ) ROMAN NUMERAL FIVE HUNDRED → LATIN CAPITAL LETTER D# - {8559, "M"}, // MA# ( Ⅿ → M ) ROMAN NUMERAL ONE THOUSAND → LATIN CAPITAL LETTER M# - {8560, "i"}, // MA# ( ⅰ → i ) SMALL ROMAN NUMERAL ONE → LATIN SMALL LETTER I# - {8561, "ii"}, // MA# ( ⅱ → ii ) SMALL ROMAN NUMERAL TWO → LATIN SMALL LETTER I, LATIN SMALL LETTER I# - {8562, "iii"}, // MA# ( ⅲ → iii ) SMALL ROMAN NUMERAL THREE → LATIN SMALL LETTER I, LATIN SMALL LETTER I, LATIN SMALL LETTER I# - {8563, "iv"}, // MA# ( ⅳ → iv ) SMALL ROMAN NUMERAL FOUR → LATIN SMALL LETTER I, LATIN SMALL LETTER V# - {8564, "v"}, // MA# ( ⅴ → v ) SMALL ROMAN NUMERAL FIVE → LATIN SMALL LETTER V# - {8565, "vi"}, // MA# ( ⅵ → vi ) SMALL ROMAN NUMERAL SIX → LATIN SMALL LETTER V, LATIN SMALL LETTER I# - {8566, "vii"}, // MA# ( ⅶ → vii ) SMALL ROMAN NUMERAL SEVEN → LATIN SMALL LETTER V, LATIN SMALL LETTER I, LATIN SMALL LETTER I# - {8567, "viii"}, // MA# ( ⅷ → viii ) SMALL ROMAN NUMERAL EIGHT → LATIN SMALL LETTER V, LATIN SMALL LETTER I, LATIN SMALL LETTER I, LATIN SMALL LETTER I# - {8568, "ix"}, // MA# ( ⅸ → ix ) SMALL ROMAN NUMERAL NINE → LATIN SMALL LETTER I, LATIN SMALL LETTER X# - {8569, "x"}, // MA# ( ⅹ → x ) SMALL ROMAN NUMERAL TEN → LATIN SMALL LETTER X# - {8570, "xi"}, // MA# ( ⅺ → xi ) SMALL ROMAN NUMERAL ELEVEN → LATIN SMALL LETTER X, LATIN SMALL LETTER I# - {8571, "xii"}, // MA# ( ⅻ → xii ) SMALL ROMAN NUMERAL TWELVE → LATIN SMALL LETTER X, LATIN SMALL LETTER I, LATIN SMALL LETTER I# - {8572, "l"}, // MA# ( ⅼ → l ) SMALL ROMAN NUMERAL FIFTY → LATIN SMALL LETTER L# - {8573, "c"}, // MA# ( ⅽ → c ) SMALL ROMAN NUMERAL ONE HUNDRED → LATIN SMALL LETTER C# - {8574, "d"}, // MA# ( ⅾ → d ) SMALL ROMAN NUMERAL FIVE HUNDRED → LATIN SMALL LETTER D# - {8575, "rn"}, // MA# ( ⅿ → rn ) SMALL ROMAN NUMERAL ONE THOUSAND → LATIN SMALL LETTER R, LATIN SMALL LETTER N# →m→ - {8722, "-"}, // MA#* ( − → - ) MINUS SIGN → HYPHEN-MINUS# - {8725, "/"}, // MA#* ( ∕ → / ) DIVISION SLASH → SOLIDUS# - {8726, "\\"}, // MA#* ( ∖ → \ ) SET MINUS → REVERSE SOLIDUS# - {8727, "*"}, // MA#* ( ∗ → * ) ASTERISK OPERATOR → ASTERISK# - {8734, "oo"}, // MA#* ( ∞ → oo ) INFINITY → LATIN SMALL LETTER O, LATIN SMALL LETTER O# →ꝏ→ - {8739, "l"}, // MA#* ( ∣ → l ) DIVIDES → LATIN SMALL LETTER L# →ǀ→ - {8741, "ll"}, // MA#* ( ∥ → ll ) PARALLEL TO → LATIN SMALL LETTER L, LATIN SMALL LETTER L# →||→ - {8744, "v"}, // MA#* ( ∨ → v ) LOGICAL OR → LATIN SMALL LETTER V# - {8746, "U"}, // MA#* ( ∪ → U ) UNION → LATIN CAPITAL LETTER U# →ᑌ→ - {8758, ":"}, // MA#* ( ∶ → : ) RATIO → COLON# - {8764, "~"}, // MA#* ( ∼ → ~ ) TILDE OPERATOR → TILDE# - {8810, "<<"}, // MA#* ( ≪ → << ) MUCH LESS-THAN → LESS-THAN SIGN, LESS-THAN SIGN# - {8811, ">>"}, // MA#* ( ≫ → >> ) MUCH GREATER-THAN → GREATER-THAN SIGN, GREATER-THAN SIGN# - {8868, "T"}, // MA#* ( ⊤ → T ) DOWN TACK → LATIN CAPITAL LETTER T# - {8897, "v"}, // MA#* ( ⋁ → v ) N-ARY LOGICAL OR → LATIN SMALL LETTER V# →∨→ - {8899, "U"}, // MA#* ( ⋃ → U ) N-ARY UNION → LATIN CAPITAL LETTER U# →∪→→ᑌ→ - {8920, "<<<"}, // MA#* ( ⋘ → <<< ) VERY MUCH LESS-THAN → LESS-THAN SIGN, LESS-THAN SIGN, LESS-THAN SIGN# - {8921, ">>>"}, // MA#* ( ⋙ → >>> ) VERY MUCH GREATER-THAN → GREATER-THAN SIGN, GREATER-THAN SIGN, GREATER-THAN SIGN# - {8959, "E"}, // MA#* ( ⋿ → E ) Z NOTATION BAG MEMBERSHIP → LATIN CAPITAL LETTER E# - {9075, "i"}, // MA#* ( ⍳ → i ) APL FUNCTIONAL SYMBOL IOTA → LATIN SMALL LETTER I# →ι→ - {9076, "p"}, // MA#* ( ⍴ → p ) APL FUNCTIONAL SYMBOL RHO → LATIN SMALL LETTER P# →ρ→ - {9082, "a"}, // MA#* ( ⍺ → a ) APL FUNCTIONAL SYMBOL ALPHA → LATIN SMALL LETTER A# →α→ - {9213, "l"}, // MA#* ( ⏽ → l ) POWER ON SYMBOL → LATIN SMALL LETTER L# →I→ - {9290, "\\\\"}, // MA#* ( ⑊ → \\ ) OCR DOUBLE BACKSLASH → REVERSE SOLIDUS, REVERSE SOLIDUS# - {9332, "(l)"}, // MA#* ( ⑴ → (l) ) PARENTHESIZED DIGIT ONE → LEFT PARENTHESIS, LATIN SMALL LETTER L, RIGHT PARENTHESIS# →(1)→ - {9333, "(2)"}, // MA#* ( ⑵ → (2) ) PARENTHESIZED DIGIT TWO → LEFT PARENTHESIS, DIGIT TWO, RIGHT PARENTHESIS# - {9334, "(3)"}, // MA#* ( ⑶ → (3) ) PARENTHESIZED DIGIT THREE → LEFT PARENTHESIS, DIGIT THREE, RIGHT PARENTHESIS# - {9335, "(4)"}, // MA#* ( ⑷ → (4) ) PARENTHESIZED DIGIT FOUR → LEFT PARENTHESIS, DIGIT FOUR, RIGHT PARENTHESIS# - {9336, "(5)"}, // MA#* ( ⑸ → (5) ) PARENTHESIZED DIGIT FIVE → LEFT PARENTHESIS, DIGIT FIVE, RIGHT PARENTHESIS# - {9337, "(6)"}, // MA#* ( ⑹ → (6) ) PARENTHESIZED DIGIT SIX → LEFT PARENTHESIS, DIGIT SIX, RIGHT PARENTHESIS# - {9338, "(7)"}, // MA#* ( ⑺ → (7) ) PARENTHESIZED DIGIT SEVEN → LEFT PARENTHESIS, DIGIT SEVEN, RIGHT PARENTHESIS# - {9339, "(8)"}, // MA#* ( ⑻ → (8) ) PARENTHESIZED DIGIT EIGHT → LEFT PARENTHESIS, DIGIT EIGHT, RIGHT PARENTHESIS# - {9340, "(9)"}, // MA#* ( ⑼ → (9) ) PARENTHESIZED DIGIT NINE → LEFT PARENTHESIS, DIGIT NINE, RIGHT PARENTHESIS# - {9341, "(lO)"}, // MA#* ( ⑽ → (lO) ) PARENTHESIZED NUMBER TEN → LEFT PARENTHESIS, LATIN SMALL LETTER L, LATIN CAPITAL LETTER O, RIGHT PARENTHESIS# →(10)→ - {9342, "(ll)"}, // MA#* ( ⑾ → (ll) ) PARENTHESIZED NUMBER ELEVEN → LEFT PARENTHESIS, LATIN SMALL LETTER L, LATIN SMALL LETTER L, RIGHT PARENTHESIS# →(11)→ - {9343, "(l2)"}, // MA#* ( ⑿ → (l2) ) PARENTHESIZED NUMBER TWELVE → LEFT PARENTHESIS, LATIN SMALL LETTER L, DIGIT TWO, RIGHT PARENTHESIS# →(12)→ - {9344, "(l3)"}, // MA#* ( ⒀ → (l3) ) PARENTHESIZED NUMBER THIRTEEN → LEFT PARENTHESIS, LATIN SMALL LETTER L, DIGIT THREE, RIGHT PARENTHESIS# →(13)→ - {9345, "(l4)"}, // MA#* ( ⒁ → (l4) ) PARENTHESIZED NUMBER FOURTEEN → LEFT PARENTHESIS, LATIN SMALL LETTER L, DIGIT FOUR, RIGHT PARENTHESIS# →(14)→ - {9346, "(l5)"}, // MA#* ( ⒂ → (l5) ) PARENTHESIZED NUMBER FIFTEEN → LEFT PARENTHESIS, LATIN SMALL LETTER L, DIGIT FIVE, RIGHT PARENTHESIS# →(15)→ - {9347, "(l6)"}, // MA#* ( ⒃ → (l6) ) PARENTHESIZED NUMBER SIXTEEN → LEFT PARENTHESIS, LATIN SMALL LETTER L, DIGIT SIX, RIGHT PARENTHESIS# →(16)→ - {9348, "(l7)"}, // MA#* ( ⒄ → (l7) ) PARENTHESIZED NUMBER SEVENTEEN → LEFT PARENTHESIS, LATIN SMALL LETTER L, DIGIT SEVEN, RIGHT PARENTHESIS# →(17)→ - {9349, "(l8)"}, // MA#* ( ⒅ → (l8) ) PARENTHESIZED NUMBER EIGHTEEN → LEFT PARENTHESIS, LATIN SMALL LETTER L, DIGIT EIGHT, RIGHT PARENTHESIS# →(18)→ - {9350, "(l9)"}, // MA#* ( ⒆ → (l9) ) PARENTHESIZED NUMBER NINETEEN → LEFT PARENTHESIS, LATIN SMALL LETTER L, DIGIT NINE, RIGHT PARENTHESIS# →(19)→ - {9351, "(2O)"}, // MA#* ( ⒇ → (2O) ) PARENTHESIZED NUMBER TWENTY → LEFT PARENTHESIS, DIGIT TWO, LATIN CAPITAL LETTER O, RIGHT PARENTHESIS# →(20)→ - {9352, "l."}, // MA#* ( ⒈ → l. ) DIGIT ONE FULL STOP → LATIN SMALL LETTER L, FULL STOP# →1.→ - {9353, "2."}, // MA#* ( ⒉ → 2. ) DIGIT TWO FULL STOP → DIGIT TWO, FULL STOP# - {9354, "3."}, // MA#* ( ⒊ → 3. ) DIGIT THREE FULL STOP → DIGIT THREE, FULL STOP# - {9355, "4."}, // MA#* ( ⒋ → 4. ) DIGIT FOUR FULL STOP → DIGIT FOUR, FULL STOP# - {9356, "5."}, // MA#* ( ⒌ → 5. ) DIGIT FIVE FULL STOP → DIGIT FIVE, FULL STOP# - {9357, "6."}, // MA#* ( ⒍ → 6. ) DIGIT SIX FULL STOP → DIGIT SIX, FULL STOP# - {9358, "7."}, // MA#* ( ⒎ → 7. ) DIGIT SEVEN FULL STOP → DIGIT SEVEN, FULL STOP# - {9359, "8."}, // MA#* ( ⒏ → 8. ) DIGIT EIGHT FULL STOP → DIGIT EIGHT, FULL STOP# - {9360, "9."}, // MA#* ( ⒐ → 9. ) DIGIT NINE FULL STOP → DIGIT NINE, FULL STOP# - {9361, "lO."}, // MA#* ( ⒑ → lO. ) NUMBER TEN FULL STOP → LATIN SMALL LETTER L, LATIN CAPITAL LETTER O, FULL STOP# →10.→ - {9362, "ll."}, // MA#* ( ⒒ → ll. ) NUMBER ELEVEN FULL STOP → LATIN SMALL LETTER L, LATIN SMALL LETTER L, FULL STOP# →11.→ - {9363, "l2."}, // MA#* ( ⒓ → l2. ) NUMBER TWELVE FULL STOP → LATIN SMALL LETTER L, DIGIT TWO, FULL STOP# →12.→ - {9364, "l3."}, // MA#* ( ⒔ → l3. ) NUMBER THIRTEEN FULL STOP → LATIN SMALL LETTER L, DIGIT THREE, FULL STOP# →13.→ - {9365, "l4."}, // MA#* ( ⒕ → l4. ) NUMBER FOURTEEN FULL STOP → LATIN SMALL LETTER L, DIGIT FOUR, FULL STOP# →14.→ - {9366, "l5."}, // MA#* ( ⒖ → l5. ) NUMBER FIFTEEN FULL STOP → LATIN SMALL LETTER L, DIGIT FIVE, FULL STOP# →15.→ - {9367, "l6."}, // MA#* ( ⒗ → l6. ) NUMBER SIXTEEN FULL STOP → LATIN SMALL LETTER L, DIGIT SIX, FULL STOP# →16.→ - {9368, "l7."}, // MA#* ( ⒘ → l7. ) NUMBER SEVENTEEN FULL STOP → LATIN SMALL LETTER L, DIGIT SEVEN, FULL STOP# →17.→ - {9369, "l8."}, // MA#* ( ⒙ → l8. ) NUMBER EIGHTEEN FULL STOP → LATIN SMALL LETTER L, DIGIT EIGHT, FULL STOP# →18.→ - {9370, "l9."}, // MA#* ( ⒚ → l9. ) NUMBER NINETEEN FULL STOP → LATIN SMALL LETTER L, DIGIT NINE, FULL STOP# →19.→ - {9371, "2O."}, // MA#* ( ⒛ → 2O. ) NUMBER TWENTY FULL STOP → DIGIT TWO, LATIN CAPITAL LETTER O, FULL STOP# →20.→ - {9372, "(a)"}, // MA#* ( ⒜ → (a) ) PARENTHESIZED LATIN SMALL LETTER A → LEFT PARENTHESIS, LATIN SMALL LETTER A, RIGHT PARENTHESIS# - {9373, "(b)"}, // MA#* ( ⒝ → (b) ) PARENTHESIZED LATIN SMALL LETTER B → LEFT PARENTHESIS, LATIN SMALL LETTER B, RIGHT PARENTHESIS# - {9374, "(c)"}, // MA#* ( ⒞ → (c) ) PARENTHESIZED LATIN SMALL LETTER C → LEFT PARENTHESIS, LATIN SMALL LETTER C, RIGHT PARENTHESIS# - {9375, "(d)"}, // MA#* ( ⒟ → (d) ) PARENTHESIZED LATIN SMALL LETTER D → LEFT PARENTHESIS, LATIN SMALL LETTER D, RIGHT PARENTHESIS# - {9376, "(e)"}, // MA#* ( ⒠ → (e) ) PARENTHESIZED LATIN SMALL LETTER E → LEFT PARENTHESIS, LATIN SMALL LETTER E, RIGHT PARENTHESIS# - {9377, "(f)"}, // MA#* ( ⒡ → (f) ) PARENTHESIZED LATIN SMALL LETTER F → LEFT PARENTHESIS, LATIN SMALL LETTER F, RIGHT PARENTHESIS# - {9378, "(g)"}, // MA#* ( ⒢ → (g) ) PARENTHESIZED LATIN SMALL LETTER G → LEFT PARENTHESIS, LATIN SMALL LETTER G, RIGHT PARENTHESIS# - {9379, "(h)"}, // MA#* ( ⒣ → (h) ) PARENTHESIZED LATIN SMALL LETTER H → LEFT PARENTHESIS, LATIN SMALL LETTER H, RIGHT PARENTHESIS# - {9380, "(i)"}, // MA#* ( ⒤ → (i) ) PARENTHESIZED LATIN SMALL LETTER I → LEFT PARENTHESIS, LATIN SMALL LETTER I, RIGHT PARENTHESIS# - {9381, "(j)"}, // MA#* ( ⒥ → (j) ) PARENTHESIZED LATIN SMALL LETTER J → LEFT PARENTHESIS, LATIN SMALL LETTER J, RIGHT PARENTHESIS# - {9382, "(k)"}, // MA#* ( ⒦ → (k) ) PARENTHESIZED LATIN SMALL LETTER K → LEFT PARENTHESIS, LATIN SMALL LETTER K, RIGHT PARENTHESIS# - {9383, "(l)"}, // MA#* ( ⒧ → (l) ) PARENTHESIZED LATIN SMALL LETTER L → LEFT PARENTHESIS, LATIN SMALL LETTER L, RIGHT PARENTHESIS# - {9384, "(rn)"}, // MA#* ( ⒨ → (rn) ) PARENTHESIZED LATIN SMALL LETTER M → LEFT PARENTHESIS, LATIN SMALL LETTER R, LATIN SMALL LETTER N, RIGHT PARENTHESIS# →(m)→ - {9385, "(n)"}, // MA#* ( ⒩ → (n) ) PARENTHESIZED LATIN SMALL LETTER N → LEFT PARENTHESIS, LATIN SMALL LETTER N, RIGHT PARENTHESIS# - {9386, "(o)"}, // MA#* ( ⒪ → (o) ) PARENTHESIZED LATIN SMALL LETTER O → LEFT PARENTHESIS, LATIN SMALL LETTER O, RIGHT PARENTHESIS# - {9387, "(p)"}, // MA#* ( ⒫ → (p) ) PARENTHESIZED LATIN SMALL LETTER P → LEFT PARENTHESIS, LATIN SMALL LETTER P, RIGHT PARENTHESIS# - {9388, "(q)"}, // MA#* ( ⒬ → (q) ) PARENTHESIZED LATIN SMALL LETTER Q → LEFT PARENTHESIS, LATIN SMALL LETTER Q, RIGHT PARENTHESIS# - {9389, "(r)"}, // MA#* ( ⒭ → (r) ) PARENTHESIZED LATIN SMALL LETTER R → LEFT PARENTHESIS, LATIN SMALL LETTER R, RIGHT PARENTHESIS# - {9390, "(s)"}, // MA#* ( ⒮ → (s) ) PARENTHESIZED LATIN SMALL LETTER S → LEFT PARENTHESIS, LATIN SMALL LETTER S, RIGHT PARENTHESIS# - {9391, "(t)"}, // MA#* ( ⒯ → (t) ) PARENTHESIZED LATIN SMALL LETTER T → LEFT PARENTHESIS, LATIN SMALL LETTER T, RIGHT PARENTHESIS# - {9392, "(u)"}, // MA#* ( ⒰ → (u) ) PARENTHESIZED LATIN SMALL LETTER U → LEFT PARENTHESIS, LATIN SMALL LETTER U, RIGHT PARENTHESIS# - {9393, "(v)"}, // MA#* ( ⒱ → (v) ) PARENTHESIZED LATIN SMALL LETTER V → LEFT PARENTHESIS, LATIN SMALL LETTER V, RIGHT PARENTHESIS# - {9394, "(w)"}, // MA#* ( ⒲ → (w) ) PARENTHESIZED LATIN SMALL LETTER W → LEFT PARENTHESIS, LATIN SMALL LETTER W, RIGHT PARENTHESIS# - {9395, "(x)"}, // MA#* ( ⒳ → (x) ) PARENTHESIZED LATIN SMALL LETTER X → LEFT PARENTHESIS, LATIN SMALL LETTER X, RIGHT PARENTHESIS# - {9396, "(y)"}, // MA#* ( ⒴ → (y) ) PARENTHESIZED LATIN SMALL LETTER Y → LEFT PARENTHESIS, LATIN SMALL LETTER Y, RIGHT PARENTHESIS# - {9397, "(z)"}, // MA#* ( ⒵ → (z) ) PARENTHESIZED LATIN SMALL LETTER Z → LEFT PARENTHESIS, LATIN SMALL LETTER Z, RIGHT PARENTHESIS# - {9585, "/"}, // MA#* ( ╱ → / ) BOX DRAWINGS LIGHT DIAGONAL UPPER RIGHT TO LOWER LEFT → SOLIDUS# - {9587, "X"}, // MA#* ( ╳ → X ) BOX DRAWINGS LIGHT DIAGONAL CROSS → LATIN CAPITAL LETTER X# - {10088, "("}, // MA#* ( ❨ → ( ) MEDIUM LEFT PARENTHESIS ORNAMENT → LEFT PARENTHESIS# - {10089, ")"}, // MA#* ( ❩ → ) ) MEDIUM RIGHT PARENTHESIS ORNAMENT → RIGHT PARENTHESIS# - {10094, "<"}, // MA#* ( ❮ → < ) HEAVY LEFT-POINTING ANGLE QUOTATION MARK ORNAMENT → LESS-THAN SIGN# →‹→ - {10095, ">"}, // MA#* ( ❯ → > ) HEAVY RIGHT-POINTING ANGLE QUOTATION MARK ORNAMENT → GREATER-THAN SIGN# →›→ - {10098, "("}, // MA#* ( ❲ → ( ) LIGHT LEFT TORTOISE SHELL BRACKET ORNAMENT → LEFT PARENTHESIS# →〔→ - {10099, ")"}, // MA#* ( ❳ → ) ) LIGHT RIGHT TORTOISE SHELL BRACKET ORNAMENT → RIGHT PARENTHESIS# →〕→ - {10100, "{"}, // MA#* ( ❴ → { ) MEDIUM LEFT CURLY BRACKET ORNAMENT → LEFT CURLY BRACKET# - {10101, "}"}, // MA#* ( ❵ → } ) MEDIUM RIGHT CURLY BRACKET ORNAMENT → RIGHT CURLY BRACKET# - {10133, "+"}, // MA#* ( ➕ → + ) HEAVY PLUS SIGN → PLUS SIGN# - {10134, "-"}, // MA#* ( ➖ → - ) HEAVY MINUS SIGN → HYPHEN-MINUS# →−→ - {10187, "/"}, // MA#* ( ⟋ → / ) MATHEMATICAL RISING DIAGONAL → SOLIDUS# - {10189, "\\"}, // MA#* ( ⟍ → \ ) MATHEMATICAL FALLING DIAGONAL → REVERSE SOLIDUS# - {10201, "T"}, // MA#* ( ⟙ → T ) LARGE DOWN TACK → LATIN CAPITAL LETTER T# - {10539, "x"}, // MA#* ( ⤫ → x ) RISING DIAGONAL CROSSING FALLING DIAGONAL → LATIN SMALL LETTER X# - {10540, "x"}, // MA#* ( ⤬ → x ) FALLING DIAGONAL CROSSING RISING DIAGONAL → LATIN SMALL LETTER X# - {10741, "\\"}, // MA#* ( ⧵ → \ ) REVERSE SOLIDUS OPERATOR → REVERSE SOLIDUS# - {10744, "/"}, // MA#* ( ⧸ → / ) BIG SOLIDUS → SOLIDUS# - {10745, "\\"}, // MA#* ( ⧹ → \ ) BIG REVERSE SOLIDUS → REVERSE SOLIDUS# - {10784, ">>"}, // MA#* ( ⨠ → >> ) Z NOTATION SCHEMA PIPING → GREATER-THAN SIGN, GREATER-THAN SIGN# →≫→ - {10799, "x"}, // MA#* ( ⨯ → x ) VECTOR OR CROSS PRODUCT → LATIN SMALL LETTER X# →×→ - {10868, "::="}, // MA#* ( ⩴ → ::= ) DOUBLE COLON EQUAL → COLON, COLON, EQUALS SIGN# - {10869, "=="}, // MA#* ( ⩵ → == ) TWO CONSECUTIVE EQUALS SIGNS → EQUALS SIGN, EQUALS SIGN# - {10870, "==="}, // MA#* ( ⩶ → === ) THREE CONSECUTIVE EQUALS SIGNS → EQUALS SIGN, EQUALS SIGN, EQUALS SIGN# - {10917, "><"}, // MA#* ( ⪥ → >< ) GREATER-THAN BESIDE LESS-THAN → GREATER-THAN SIGN, LESS-THAN SIGN# - {11003, "///"}, // MA#* ( ⫻ → /// ) TRIPLE SOLIDUS BINARY RELATION → SOLIDUS, SOLIDUS, SOLIDUS# - {11005, "//"}, // MA#* ( ⫽ → // ) DOUBLE SOLIDUS OPERATOR → SOLIDUS, SOLIDUS# - {11397, "r"}, // MA# ( ⲅ → r ) COPTIC SMALL LETTER GAMMA → LATIN SMALL LETTER R# →г→ - {11406, "H"}, // MA# ( Ⲏ → H ) COPTIC CAPITAL LETTER HATE → LATIN CAPITAL LETTER H# →Η→ - {11410, "l"}, // MA# ( Ⲓ → l ) COPTIC CAPITAL LETTER IAUDA → LATIN SMALL LETTER L# →Ӏ→ - {11412, "K"}, // MA# ( Ⲕ → K ) COPTIC CAPITAL LETTER KAPA → LATIN CAPITAL LETTER K# →Κ→ - {11416, "M"}, // MA# ( Ⲙ → M ) COPTIC CAPITAL LETTER MI → LATIN CAPITAL LETTER M# - {11418, "N"}, // MA# ( Ⲛ → N ) COPTIC CAPITAL LETTER NI → LATIN CAPITAL LETTER N# - {11422, "O"}, // MA# ( Ⲟ → O ) COPTIC CAPITAL LETTER O → LATIN CAPITAL LETTER O# - {11423, "o"}, // MA# ( ⲟ → o ) COPTIC SMALL LETTER O → LATIN SMALL LETTER O# - {11426, "P"}, // MA# ( Ⲣ → P ) COPTIC CAPITAL LETTER RO → LATIN CAPITAL LETTER P# - {11427, "p"}, // MA# ( ⲣ → p ) COPTIC SMALL LETTER RO → LATIN SMALL LETTER P# →ρ→ - {11428, "C"}, // MA# ( Ⲥ → C ) COPTIC CAPITAL LETTER SIMA → LATIN CAPITAL LETTER C# →Ϲ→ - {11429, "c"}, // MA# ( ⲥ → c ) COPTIC SMALL LETTER SIMA → LATIN SMALL LETTER C# →ϲ→ - {11430, "T"}, // MA# ( Ⲧ → T ) COPTIC CAPITAL LETTER TAU → LATIN CAPITAL LETTER T# - {11432, "Y"}, // MA# ( Ⲩ → Y ) COPTIC CAPITAL LETTER UA → LATIN CAPITAL LETTER Y# - {11436, "X"}, // MA# ( Ⲭ → X ) COPTIC CAPITAL LETTER KHI → LATIN CAPITAL LETTER X# →Х→ - {11450, "-"}, // MA# ( Ⲻ → - ) COPTIC CAPITAL LETTER DIALECT-P NI → HYPHEN-MINUS# →‒→ - {11462, "/"}, // MA# ( Ⳇ → / ) COPTIC CAPITAL LETTER OLD COPTIC ESH → SOLIDUS# - {11466, "9"}, // MA# ( Ⳋ → 9 ) COPTIC CAPITAL LETTER DIALECT-P HORI → DIGIT NINE# - {11468, "3"}, // MA# ( Ⳍ → 3 ) COPTIC CAPITAL LETTER OLD COPTIC HORI → DIGIT THREE# →Ȝ→→Ʒ→ - {11472, "L"}, // MA# ( Ⳑ → L ) COPTIC CAPITAL LETTER L-SHAPED HA → LATIN CAPITAL LETTER L# - {11474, "6"}, // MA# ( Ⳓ → 6 ) COPTIC CAPITAL LETTER OLD COPTIC HEI → DIGIT SIX# - {11513, "\\\\"}, // MA#* ( ⳹ → \\ ) COPTIC OLD NUBIAN FULL STOP → REVERSE SOLIDUS, REVERSE SOLIDUS# - {11576, "V"}, // MA# ( ⴸ → V ) TIFINAGH LETTER YADH → LATIN CAPITAL LETTER V# - {11577, "E"}, // MA# ( ⴹ → E ) TIFINAGH LETTER YADD → LATIN CAPITAL LETTER E# - {11599, "l"}, // MA# ( ⵏ → l ) TIFINAGH LETTER YAN → LATIN SMALL LETTER L# →Ӏ→ - {11601, "!"}, // MA# ( ⵑ → ! ) TIFINAGH LETTER TUAREG YANG → EXCLAMATION MARK# - {11604, "O"}, // MA# ( ⵔ → O ) TIFINAGH LETTER YAR → LATIN CAPITAL LETTER O# - {11605, "Q"}, // MA# ( ⵕ → Q ) TIFINAGH LETTER YARR → LATIN CAPITAL LETTER Q# - {11613, "X"}, // MA# ( ⵝ → X ) TIFINAGH LETTER YATH → LATIN CAPITAL LETTER X# - {11816, "(("}, // MA#* ( ⸨ → (( ) LEFT DOUBLE PARENTHESIS → LEFT PARENTHESIS, LEFT PARENTHESIS# - {11817, "))"}, // MA#* ( ⸩ → )) ) RIGHT DOUBLE PARENTHESIS → RIGHT PARENTHESIS, RIGHT PARENTHESIS# - {11840, "="}, // MA#* ( ⹀ → = ) DOUBLE HYPHEN → EQUALS SIGN# - {12034, "\\"}, // MA#* ( ⼂ → \ ) KANGXI RADICAL DOT → REVERSE SOLIDUS# - {12035, "/"}, // MA#* ( ⼃ → / ) KANGXI RADICAL SLASH → SOLIDUS# - {12291, "\""}, // MA#* ( 〃 → '' ) DITTO MARK → APOSTROPHE, APOSTROPHE# →″→→"→# Converted to a quote. - {12295, "O"}, // MA# ( 〇 → O ) IDEOGRAPHIC NUMBER ZERO → LATIN CAPITAL LETTER O# - {12308, "("}, // MA#* ( 〔 → ( ) LEFT TORTOISE SHELL BRACKET → LEFT PARENTHESIS# - {12309, ")"}, // MA#* ( 〕 → ) ) RIGHT TORTOISE SHELL BRACKET → RIGHT PARENTHESIS# - {12339, "/"}, // MA# ( 〳 → / ) VERTICAL KANA REPEAT MARK UPPER HALF → SOLIDUS# - {12448, "="}, // MA#* ( ゠ → = ) KATAKANA-HIRAGANA DOUBLE HYPHEN → EQUALS SIGN# - {12494, "/"}, // MA# ( ノ → / ) KATAKANA LETTER NO → SOLIDUS# →⼃→ - {12755, "/"}, // MA#* ( ㇓ → / ) CJK STROKE SP → SOLIDUS# →⼃→ - {12756, "\\"}, // MA#* ( ㇔ → \ ) CJK STROKE D → REVERSE SOLIDUS# →⼂→ - {20022, "\\"}, // MA# ( 丶 → \ ) CJK UNIFIED IDEOGRAPH-4E36 → REVERSE SOLIDUS# →⼂→ - {20031, "/"}, // MA# ( 丿 → / ) CJK UNIFIED IDEOGRAPH-4E3F → SOLIDUS# →⼃→ - {42192, "B"}, // MA# ( ꓐ → B ) LISU LETTER BA → LATIN CAPITAL LETTER B# - {42193, "P"}, // MA# ( ꓑ → P ) LISU LETTER PA → LATIN CAPITAL LETTER P# - {42194, "d"}, // MA# ( ꓒ → d ) LISU LETTER PHA → LATIN SMALL LETTER D# - {42195, "D"}, // MA# ( ꓓ → D ) LISU LETTER DA → LATIN CAPITAL LETTER D# - {42196, "T"}, // MA# ( ꓔ → T ) LISU LETTER TA → LATIN CAPITAL LETTER T# - {42198, "G"}, // MA# ( ꓖ → G ) LISU LETTER GA → LATIN CAPITAL LETTER G# - {42199, "K"}, // MA# ( ꓗ → K ) LISU LETTER KA → LATIN CAPITAL LETTER K# - {42201, "J"}, // MA# ( ꓙ → J ) LISU LETTER JA → LATIN CAPITAL LETTER J# - {42202, "C"}, // MA# ( ꓚ → C ) LISU LETTER CA → LATIN CAPITAL LETTER C# - {42204, "Z"}, // MA# ( ꓜ → Z ) LISU LETTER DZA → LATIN CAPITAL LETTER Z# - {42205, "F"}, // MA# ( ꓝ → F ) LISU LETTER TSA → LATIN CAPITAL LETTER F# - {42207, "M"}, // MA# ( ꓟ → M ) LISU LETTER MA → LATIN CAPITAL LETTER M# - {42208, "N"}, // MA# ( ꓠ → N ) LISU LETTER NA → LATIN CAPITAL LETTER N# - {42209, "L"}, // MA# ( ꓡ → L ) LISU LETTER LA → LATIN CAPITAL LETTER L# - {42210, "S"}, // MA# ( ꓢ → S ) LISU LETTER SA → LATIN CAPITAL LETTER S# - {42211, "R"}, // MA# ( ꓣ → R ) LISU LETTER ZHA → LATIN CAPITAL LETTER R# - {42214, "V"}, // MA# ( ꓦ → V ) LISU LETTER HA → LATIN CAPITAL LETTER V# - {42215, "H"}, // MA# ( ꓧ → H ) LISU LETTER XA → LATIN CAPITAL LETTER H# - {42218, "W"}, // MA# ( ꓪ → W ) LISU LETTER WA → LATIN CAPITAL LETTER W# - {42219, "X"}, // MA# ( ꓫ → X ) LISU LETTER SHA → LATIN CAPITAL LETTER X# - {42220, "Y"}, // MA# ( ꓬ → Y ) LISU LETTER YA → LATIN CAPITAL LETTER Y# - {42222, "A"}, // MA# ( ꓮ → A ) LISU LETTER A → LATIN CAPITAL LETTER A# - {42224, "E"}, // MA# ( ꓰ → E ) LISU LETTER E → LATIN CAPITAL LETTER E# - {42226, "l"}, // MA# ( ꓲ → l ) LISU LETTER I → LATIN SMALL LETTER L# →I→ - {42227, "O"}, // MA# ( ꓳ → O ) LISU LETTER O → LATIN CAPITAL LETTER O# - {42228, "U"}, // MA# ( ꓴ → U ) LISU LETTER U → LATIN CAPITAL LETTER U# - {42232, "."}, // MA# ( ꓸ → . ) LISU LETTER TONE MYA TI → FULL STOP# - {42233, ","}, // MA# ( ꓹ → , ) LISU LETTER TONE NA PO → COMMA# - {42234, ".."}, // MA# ( ꓺ → .. ) LISU LETTER TONE MYA CYA → FULL STOP, FULL STOP# - {42235, ".,"}, // MA# ( ꓻ → ., ) LISU LETTER TONE MYA BO → FULL STOP, COMMA# - {42237, ":"}, // MA# ( ꓽ → : ) LISU LETTER TONE MYA JEU → COLON# - {42238, "-."}, // MA#* ( ꓾ → -. ) LISU PUNCTUATION COMMA → HYPHEN-MINUS, FULL STOP# - {42239, "="}, // MA#* ( ꓿ → = ) LISU PUNCTUATION FULL STOP → EQUALS SIGN# - {42510, "."}, // MA#* ( ꘎ → . ) VAI FULL STOP → FULL STOP# - {42564, "2"}, // MA# ( Ꙅ → 2 ) CYRILLIC CAPITAL LETTER REVERSED DZE → DIGIT TWO# →Ƨ→ - {42567, "i"}, // MA# ( ꙇ → i ) CYRILLIC SMALL LETTER IOTA → LATIN SMALL LETTER I# →ι→ - {42648, "OO"}, // MA# ( Ꚙ → OO ) CYRILLIC CAPITAL LETTER DOUBLE O → LATIN CAPITAL LETTER O, LATIN CAPITAL LETTER O# - {42649, "oo"}, // MA# ( ꚙ → oo ) CYRILLIC SMALL LETTER DOUBLE O → LATIN SMALL LETTER O, LATIN SMALL LETTER O# - {42719, "V"}, // MA# ( ꛟ → V ) BAMUM LETTER KO → LATIN CAPITAL LETTER V# - {42731, "?"}, // MA# ( ꛫ → ? ) BAMUM LETTER NTUU → QUESTION MARK# →ʔ→ - {42735, "2"}, // MA# ( ꛯ → 2 ) BAMUM LETTER KOGHOM → DIGIT TWO# →Ƨ→ - {42792, "T3"}, // MA# ( Ꜩ → T3 ) LATIN CAPITAL LETTER TZ → LATIN CAPITAL LETTER T, DIGIT THREE# →TƷ→ - {42801, "s"}, // MA# ( ꜱ → s ) LATIN LETTER SMALL CAPITAL S → LATIN SMALL LETTER S# - {42802, "AA"}, // MA# ( Ꜳ → AA ) LATIN CAPITAL LETTER AA → LATIN CAPITAL LETTER A, LATIN CAPITAL LETTER A# - {42803, "aa"}, // MA# ( ꜳ → aa ) LATIN SMALL LETTER AA → LATIN SMALL LETTER A, LATIN SMALL LETTER A# - {42804, "AO"}, // MA# ( Ꜵ → AO ) LATIN CAPITAL LETTER AO → LATIN CAPITAL LETTER A, LATIN CAPITAL LETTER O# - {42805, "ao"}, // MA# ( ꜵ → ao ) LATIN SMALL LETTER AO → LATIN SMALL LETTER A, LATIN SMALL LETTER O# - {42806, "AU"}, // MA# ( Ꜷ → AU ) LATIN CAPITAL LETTER AU → LATIN CAPITAL LETTER A, LATIN CAPITAL LETTER U# - {42807, "au"}, // MA# ( ꜷ → au ) LATIN SMALL LETTER AU → LATIN SMALL LETTER A, LATIN SMALL LETTER U# - {42808, "AV"}, // MA# ( Ꜹ → AV ) LATIN CAPITAL LETTER AV → LATIN CAPITAL LETTER A, LATIN CAPITAL LETTER V# - {42809, "av"}, // MA# ( ꜹ → av ) LATIN SMALL LETTER AV → LATIN SMALL LETTER A, LATIN SMALL LETTER V# - {42810, "AV"}, // MA# ( Ꜻ → AV ) LATIN CAPITAL LETTER AV WITH HORIZONTAL BAR → LATIN CAPITAL LETTER A, LATIN CAPITAL LETTER V# - {42811, "av"}, // MA# ( ꜻ → av ) LATIN SMALL LETTER AV WITH HORIZONTAL BAR → LATIN SMALL LETTER A, LATIN SMALL LETTER V# - {42812, "AY"}, // MA# ( Ꜽ → AY ) LATIN CAPITAL LETTER AY → LATIN CAPITAL LETTER A, LATIN CAPITAL LETTER Y# - {42813, "ay"}, // MA# ( ꜽ → ay ) LATIN SMALL LETTER AY → LATIN SMALL LETTER A, LATIN SMALL LETTER Y# - {42830, "OO"}, // MA# ( Ꝏ → OO ) LATIN CAPITAL LETTER OO → LATIN CAPITAL LETTER O, LATIN CAPITAL LETTER O# - {42831, "oo"}, // MA# ( ꝏ → oo ) LATIN SMALL LETTER OO → LATIN SMALL LETTER O, LATIN SMALL LETTER O# - {42842, "2"}, // MA# ( Ꝛ → 2 ) LATIN CAPITAL LETTER R ROTUNDA → DIGIT TWO# - {42858, "3"}, // MA# ( Ꝫ → 3 ) LATIN CAPITAL LETTER ET → DIGIT THREE# - {42862, "9"}, // MA# ( Ꝯ → 9 ) LATIN CAPITAL LETTER CON → DIGIT NINE# - {42871, "tf"}, // MA# ( ꝷ → tf ) LATIN SMALL LETTER TUM → LATIN SMALL LETTER T, LATIN SMALL LETTER F# - {42872, "&"}, // MA# ( ꝸ → & ) LATIN SMALL LETTER UM → AMPERSAND# - {42889, ":"}, // MA#* ( ꞉ → : ) MODIFIER LETTER COLON → COLON# - {42892, "'"}, // MA# ( ꞌ → ' ) LATIN SMALL LETTER SALTILLO → APOSTROPHE# - {42904, "F"}, // MA# ( Ꞙ → F ) LATIN CAPITAL LETTER F WITH STROKE → LATIN CAPITAL LETTER F# - {42905, "f"}, // MA# ( ꞙ → f ) LATIN SMALL LETTER F WITH STROKE → LATIN SMALL LETTER F# - {42911, "u"}, // MA# ( ꞟ → u ) LATIN SMALL LETTER VOLAPUK UE → LATIN SMALL LETTER U# - {42923, "3"}, // MA# ( Ɜ → 3 ) LATIN CAPITAL LETTER REVERSED OPEN E → DIGIT THREE# - {42930, "J"}, // MA# ( Ʝ → J ) LATIN CAPITAL LETTER J WITH CROSSED-TAIL → LATIN CAPITAL LETTER J# - {42931, "X"}, // MA# ( Ꭓ → X ) LATIN CAPITAL LETTER CHI → LATIN CAPITAL LETTER X# - {42932, "B"}, // MA# ( Ꞵ → B ) LATIN CAPITAL LETTER BETA → LATIN CAPITAL LETTER B# - {43826, "e"}, // MA# ( ꬲ → e ) LATIN SMALL LETTER BLACKLETTER E → LATIN SMALL LETTER E# - {43829, "f"}, // MA# ( ꬵ → f ) LATIN SMALL LETTER LENIS F → LATIN SMALL LETTER F# - {43837, "o"}, // MA# ( ꬽ → o ) LATIN SMALL LETTER BLACKLETTER O → LATIN SMALL LETTER O# - {43847, "r"}, // MA# ( ꭇ → r ) LATIN SMALL LETTER R WITHOUT HANDLE → LATIN SMALL LETTER R# - {43848, "r"}, // MA# ( ꭈ → r ) LATIN SMALL LETTER DOUBLE R → LATIN SMALL LETTER R# - {43854, "u"}, // MA# ( ꭎ → u ) LATIN SMALL LETTER U WITH SHORT RIGHT LEG → LATIN SMALL LETTER U# - {43858, "u"}, // MA# ( ꭒ → u ) LATIN SMALL LETTER U WITH LEFT HOOK → LATIN SMALL LETTER U# - {43866, "y"}, // MA# ( ꭚ → y ) LATIN SMALL LETTER Y WITH SHORT RIGHT LEG → LATIN SMALL LETTER Y# - {43875, "uo"}, // MA# ( ꭣ → uo ) LATIN SMALL LETTER UO → LATIN SMALL LETTER U, LATIN SMALL LETTER O# - {43893, "i"}, // MA# ( ꭵ → i ) CHEROKEE SMALL LETTER V → LATIN SMALL LETTER I# - {43905, "r"}, // MA# ( ꮁ → r ) CHEROKEE SMALL LETTER HU → LATIN SMALL LETTER R# →ᴦ→→г→ - {43907, "w"}, // MA# ( ꮃ → w ) CHEROKEE SMALL LETTER LA → LATIN SMALL LETTER W# →ᴡ→ - {43923, "z"}, // MA# ( ꮓ → z ) CHEROKEE SMALL LETTER NO → LATIN SMALL LETTER Z# →ᴢ→ - {43945, "v"}, // MA# ( ꮩ → v ) CHEROKEE SMALL LETTER DO → LATIN SMALL LETTER V# →ᴠ→ - {43946, "s"}, // MA# ( ꮪ → s ) CHEROKEE SMALL LETTER DU → LATIN SMALL LETTER S# →ꜱ→ - {43951, "c"}, // MA# ( ꮯ → c ) CHEROKEE SMALL LETTER TLI → LATIN SMALL LETTER C# →ᴄ→ - {64256, "ff"}, // MA# ( ff → ff ) LATIN SMALL LIGATURE FF → LATIN SMALL LETTER F, LATIN SMALL LETTER F# - {64257, "fi"}, // MA# ( fi → fi ) LATIN SMALL LIGATURE FI → LATIN SMALL LETTER F, LATIN SMALL LETTER I# - {64258, "fl"}, // MA# ( fl → fl ) LATIN SMALL LIGATURE FL → LATIN SMALL LETTER F, LATIN SMALL LETTER L# - {64259, "ffi"}, // MA# ( ffi → ffi ) LATIN SMALL LIGATURE FFI → LATIN SMALL LETTER F, LATIN SMALL LETTER F, LATIN SMALL LETTER I# - {64260, "ffl"}, // MA# ( ffl → ffl ) LATIN SMALL LIGATURE FFL → LATIN SMALL LETTER F, LATIN SMALL LETTER F, LATIN SMALL LETTER L# - {64262, "st"}, // MA# ( st → st ) LATIN SMALL LIGATURE ST → LATIN SMALL LETTER S, LATIN SMALL LETTER T# - {64422, "o"}, // MA# ( ‎ﮦ‎ → o ) ARABIC LETTER HEH GOAL ISOLATED FORM → LATIN SMALL LETTER O# →‎ه‎→ - {64423, "o"}, // MA# ( ‎ﮧ‎ → o ) ARABIC LETTER HEH GOAL FINAL FORM → LATIN SMALL LETTER O# →‎ہ‎→→‎ه‎→ - {64424, "o"}, // MA# ( ‎ﮨ‎ → o ) ARABIC LETTER HEH GOAL INITIAL FORM → LATIN SMALL LETTER O# →‎ہ‎→→‎ه‎→ - {64425, "o"}, // MA# ( ‎ﮩ‎ → o ) ARABIC LETTER HEH GOAL MEDIAL FORM → LATIN SMALL LETTER O# →‎ہ‎→→‎ه‎→ - {64426, "o"}, // MA# ( ‎ﮪ‎ → o ) ARABIC LETTER HEH DOACHASHMEE ISOLATED FORM → LATIN SMALL LETTER O# →‎ه‎→ - {64427, "o"}, // MA# ( ‎ﮫ‎ → o ) ARABIC LETTER HEH DOACHASHMEE FINAL FORM → LATIN SMALL LETTER O# →‎ﻪ‎→→‎ه‎→ - {64428, "o"}, // MA# ( ‎ﮬ‎ → o ) ARABIC LETTER HEH DOACHASHMEE INITIAL FORM → LATIN SMALL LETTER O# →‎ﻫ‎→→‎ه‎→ - {64429, "o"}, // MA# ( ‎ﮭ‎ → o ) ARABIC LETTER HEH DOACHASHMEE MEDIAL FORM → LATIN SMALL LETTER O# →‎ﻬ‎→→‎ه‎→ - {64830, "("}, // MA#* ( ﴾ → ( ) ORNATE LEFT PARENTHESIS → LEFT PARENTHESIS# - {64831, ")"}, // MA#* ( ﴿ → ) ) ORNATE RIGHT PARENTHESIS → RIGHT PARENTHESIS# - {65072, ":"}, // MA#* ( ︰ → : ) PRESENTATION FORM FOR VERTICAL TWO DOT LEADER → COLON# - {65101, "_"}, // MA# ( ﹍ → _ ) DASHED LOW LINE → LOW LINE# - {65102, "_"}, // MA# ( ﹎ → _ ) CENTRELINE LOW LINE → LOW LINE# - {65103, "_"}, // MA# ( ﹏ → _ ) WAVY LOW LINE → LOW LINE# - {65112, "-"}, // MA#* ( ﹘ → - ) SMALL EM DASH → HYPHEN-MINUS# - {65128, "\\"}, // MA#* ( ﹨ → \ ) SMALL REVERSE SOLIDUS → REVERSE SOLIDUS# →∖→ - {65165, "l"}, // MA# ( ‎ﺍ‎ → l ) ARABIC LETTER ALEF ISOLATED FORM → LATIN SMALL LETTER L# →‎ا‎→→1→ - {65166, "l"}, // MA# ( ‎ﺎ‎ → l ) ARABIC LETTER ALEF FINAL FORM → LATIN SMALL LETTER L# →‎ا‎→→1→ - {65257, "o"}, // MA# ( ‎ﻩ‎ → o ) ARABIC LETTER HEH ISOLATED FORM → LATIN SMALL LETTER O# →‎ه‎→ - {65258, "o"}, // MA# ( ‎ﻪ‎ → o ) ARABIC LETTER HEH FINAL FORM → LATIN SMALL LETTER O# →‎ه‎→ - {65259, "o"}, // MA# ( ‎ﻫ‎ → o ) ARABIC LETTER HEH INITIAL FORM → LATIN SMALL LETTER O# →‎ه‎→ - {65260, "o"}, // MA# ( ‎ﻬ‎ → o ) ARABIC LETTER HEH MEDIAL FORM → LATIN SMALL LETTER O# →‎ه‎→ - {65281, "!"}, // MA#* ( ! → ! ) FULLWIDTH EXCLAMATION MARK → EXCLAMATION MARK# →ǃ→ - {65282, "\""}, // MA#* ( " → '' ) FULLWIDTH QUOTATION MARK → APOSTROPHE, APOSTROPHE# →”→→"→# Converted to a quote. - {65287, "'"}, // MA#* ( ' → ' ) FULLWIDTH APOSTROPHE → APOSTROPHE# →’→ - {65306, ":"}, // MA#* ( : → : ) FULLWIDTH COLON → COLON# →︰→ - {65313, "A"}, // MA# ( A → A ) FULLWIDTH LATIN CAPITAL LETTER A → LATIN CAPITAL LETTER A# →А→ - {65314, "B"}, // MA# ( B → B ) FULLWIDTH LATIN CAPITAL LETTER B → LATIN CAPITAL LETTER B# →Β→ - {65315, "C"}, // MA# ( C → C ) FULLWIDTH LATIN CAPITAL LETTER C → LATIN CAPITAL LETTER C# →С→ - {65317, "E"}, // MA# ( E → E ) FULLWIDTH LATIN CAPITAL LETTER E → LATIN CAPITAL LETTER E# →Ε→ - {65320, "H"}, // MA# ( H → H ) FULLWIDTH LATIN CAPITAL LETTER H → LATIN CAPITAL LETTER H# →Η→ - {65321, "l"}, // MA# ( I → l ) FULLWIDTH LATIN CAPITAL LETTER I → LATIN SMALL LETTER L# →Ӏ→ - {65322, "J"}, // MA# ( J → J ) FULLWIDTH LATIN CAPITAL LETTER J → LATIN CAPITAL LETTER J# →Ј→ - {65323, "K"}, // MA# ( K → K ) FULLWIDTH LATIN CAPITAL LETTER K → LATIN CAPITAL LETTER K# →Κ→ - {65325, "M"}, // MA# ( M → M ) FULLWIDTH LATIN CAPITAL LETTER M → LATIN CAPITAL LETTER M# →Μ→ - {65326, "N"}, // MA# ( N → N ) FULLWIDTH LATIN CAPITAL LETTER N → LATIN CAPITAL LETTER N# →Ν→ - {65327, "O"}, // MA# ( O → O ) FULLWIDTH LATIN CAPITAL LETTER O → LATIN CAPITAL LETTER O# →О→ - {65328, "P"}, // MA# ( P → P ) FULLWIDTH LATIN CAPITAL LETTER P → LATIN CAPITAL LETTER P# →Р→ - {65331, "S"}, // MA# ( S → S ) FULLWIDTH LATIN CAPITAL LETTER S → LATIN CAPITAL LETTER S# →Ѕ→ - {65332, "T"}, // MA# ( T → T ) FULLWIDTH LATIN CAPITAL LETTER T → LATIN CAPITAL LETTER T# →Т→ - {65336, "X"}, // MA# ( X → X ) FULLWIDTH LATIN CAPITAL LETTER X → LATIN CAPITAL LETTER X# →Х→ - {65337, "Y"}, // MA# ( Y → Y ) FULLWIDTH LATIN CAPITAL LETTER Y → LATIN CAPITAL LETTER Y# →Υ→ - {65338, "Z"}, // MA# ( Z → Z ) FULLWIDTH LATIN CAPITAL LETTER Z → LATIN CAPITAL LETTER Z# →Ζ→ - {65339, "("}, // MA#* ( [ → ( ) FULLWIDTH LEFT SQUARE BRACKET → LEFT PARENTHESIS# →〔→ - {65340, "\\"}, // MA#* ( \ → \ ) FULLWIDTH REVERSE SOLIDUS → REVERSE SOLIDUS# →∖→ - {65341, ")"}, // MA#* ( ] → ) ) FULLWIDTH RIGHT SQUARE BRACKET → RIGHT PARENTHESIS# →〕→ - {65344, "'"}, // MA#* ( ` → ' ) FULLWIDTH GRAVE ACCENT → APOSTROPHE# →‘→ - {65345, "a"}, // MA# ( a → a ) FULLWIDTH LATIN SMALL LETTER A → LATIN SMALL LETTER A# →а→ - {65347, "c"}, // MA# ( c → c ) FULLWIDTH LATIN SMALL LETTER C → LATIN SMALL LETTER C# →с→ - {65349, "e"}, // MA# ( e → e ) FULLWIDTH LATIN SMALL LETTER E → LATIN SMALL LETTER E# →е→ - {65351, "g"}, // MA# ( g → g ) FULLWIDTH LATIN SMALL LETTER G → LATIN SMALL LETTER G# →ɡ→ - {65352, "h"}, // MA# ( h → h ) FULLWIDTH LATIN SMALL LETTER H → LATIN SMALL LETTER H# →һ→ - {65353, "i"}, // MA# ( i → i ) FULLWIDTH LATIN SMALL LETTER I → LATIN SMALL LETTER I# →і→ - {65354, "j"}, // MA# ( j → j ) FULLWIDTH LATIN SMALL LETTER J → LATIN SMALL LETTER J# →ϳ→ - {65356, "l"}, // MA# ( l → l ) FULLWIDTH LATIN SMALL LETTER L → LATIN SMALL LETTER L# →Ⅰ→→Ӏ→ - {65359, "o"}, // MA# ( o → o ) FULLWIDTH LATIN SMALL LETTER O → LATIN SMALL LETTER O# →о→ - {65360, "p"}, // MA# ( p → p ) FULLWIDTH LATIN SMALL LETTER P → LATIN SMALL LETTER P# →р→ - {65363, "s"}, // MA# ( s → s ) FULLWIDTH LATIN SMALL LETTER S → LATIN SMALL LETTER S# →ѕ→ - {65366, "v"}, // MA# ( v → v ) FULLWIDTH LATIN SMALL LETTER V → LATIN SMALL LETTER V# →ν→ - {65368, "x"}, // MA# ( x → x ) FULLWIDTH LATIN SMALL LETTER X → LATIN SMALL LETTER X# →х→ - {65369, "y"}, // MA# ( y → y ) FULLWIDTH LATIN SMALL LETTER Y → LATIN SMALL LETTER Y# →у→ - {65512, "l"}, // MA#* ( │ → l ) HALFWIDTH FORMS LIGHT VERTICAL → LATIN SMALL LETTER L# →|→ - {66178, "B"}, // MA# ( 𐊂 → B ) LYCIAN LETTER B → LATIN CAPITAL LETTER B# - {66182, "E"}, // MA# ( 𐊆 → E ) LYCIAN LETTER I → LATIN CAPITAL LETTER E# - {66183, "F"}, // MA# ( 𐊇 → F ) LYCIAN LETTER W → LATIN CAPITAL LETTER F# - {66186, "l"}, // MA# ( 𐊊 → l ) LYCIAN LETTER J → LATIN SMALL LETTER L# →I→ - {66192, "X"}, // MA# ( 𐊐 → X ) LYCIAN LETTER MM → LATIN CAPITAL LETTER X# - {66194, "O"}, // MA# ( 𐊒 → O ) LYCIAN LETTER U → LATIN CAPITAL LETTER O# - {66197, "P"}, // MA# ( 𐊕 → P ) LYCIAN LETTER R → LATIN CAPITAL LETTER P# - {66198, "S"}, // MA# ( 𐊖 → S ) LYCIAN LETTER S → LATIN CAPITAL LETTER S# - {66199, "T"}, // MA# ( 𐊗 → T ) LYCIAN LETTER T → LATIN CAPITAL LETTER T# - {66203, "+"}, // MA# ( 𐊛 → + ) LYCIAN LETTER H → PLUS SIGN# - {66208, "A"}, // MA# ( 𐊠 → A ) CARIAN LETTER A → LATIN CAPITAL LETTER A# - {66209, "B"}, // MA# ( 𐊡 → B ) CARIAN LETTER P2 → LATIN CAPITAL LETTER B# - {66210, "C"}, // MA# ( 𐊢 → C ) CARIAN LETTER D → LATIN CAPITAL LETTER C# - {66213, "F"}, // MA# ( 𐊥 → F ) CARIAN LETTER R → LATIN CAPITAL LETTER F# - {66219, "O"}, // MA# ( 𐊫 → O ) CARIAN LETTER O → LATIN CAPITAL LETTER O# - {66224, "M"}, // MA# ( 𐊰 → M ) CARIAN LETTER S → LATIN CAPITAL LETTER M# - {66225, "T"}, // MA# ( 𐊱 → T ) CARIAN LETTER C-18 → LATIN CAPITAL LETTER T# - {66226, "Y"}, // MA# ( 𐊲 → Y ) CARIAN LETTER U → LATIN CAPITAL LETTER Y# - {66228, "X"}, // MA# ( 𐊴 → X ) CARIAN LETTER X → LATIN CAPITAL LETTER X# - {66255, "H"}, // MA# ( 𐋏 → H ) CARIAN LETTER E2 → LATIN CAPITAL LETTER H# - {66293, "Z"}, // MA#* ( 𐋵 → Z ) COPTIC EPACT NUMBER THREE HUNDRED → LATIN CAPITAL LETTER Z# - {66305, "B"}, // MA# ( 𐌁 → B ) OLD ITALIC LETTER BE → LATIN CAPITAL LETTER B# - {66306, "C"}, // MA# ( 𐌂 → C ) OLD ITALIC LETTER KE → LATIN CAPITAL LETTER C# - {66313, "l"}, // MA# ( 𐌉 → l ) OLD ITALIC LETTER I → LATIN SMALL LETTER L# →I→ - {66321, "M"}, // MA# ( 𐌑 → M ) OLD ITALIC LETTER SHE → LATIN CAPITAL LETTER M# - {66325, "T"}, // MA# ( 𐌕 → T ) OLD ITALIC LETTER TE → LATIN CAPITAL LETTER T# - {66327, "X"}, // MA# ( 𐌗 → X ) OLD ITALIC LETTER EKS → LATIN CAPITAL LETTER X# - {66330, "8"}, // MA# ( 𐌚 → 8 ) OLD ITALIC LETTER EF → DIGIT EIGHT# - {66335, "*"}, // MA# ( 𐌟 → * ) OLD ITALIC LETTER ESS → ASTERISK# - {66336, "l"}, // MA#* ( 𐌠 → l ) OLD ITALIC NUMERAL ONE → LATIN SMALL LETTER L# →𐌉→→I→ - {66338, "X"}, // MA#* ( 𐌢 → X ) OLD ITALIC NUMERAL TEN → LATIN CAPITAL LETTER X# →𐌗→ - {66564, "O"}, // MA# ( 𐐄 → O ) DESERET CAPITAL LETTER LONG O → LATIN CAPITAL LETTER O# - {66581, "C"}, // MA# ( 𐐕 → C ) DESERET CAPITAL LETTER CHEE → LATIN CAPITAL LETTER C# - {66587, "L"}, // MA# ( 𐐛 → L ) DESERET CAPITAL LETTER ETH → LATIN CAPITAL LETTER L# - {66592, "S"}, // MA# ( 𐐠 → S ) DESERET CAPITAL LETTER ZHEE → LATIN CAPITAL LETTER S# - {66604, "o"}, // MA# ( 𐐬 → o ) DESERET SMALL LETTER LONG O → LATIN SMALL LETTER O# - {66621, "c"}, // MA# ( 𐐽 → c ) DESERET SMALL LETTER CHEE → LATIN SMALL LETTER C# - {66632, "s"}, // MA# ( 𐑈 → s ) DESERET SMALL LETTER ZHEE → LATIN SMALL LETTER S# - {66740, "R"}, // MA# ( 𐒴 → R ) OSAGE CAPITAL LETTER BRA → LATIN CAPITAL LETTER R# →Ʀ→ - {66754, "O"}, // MA# ( 𐓂 → O ) OSAGE CAPITAL LETTER O → LATIN CAPITAL LETTER O# - {66766, "U"}, // MA# ( 𐓎 → U ) OSAGE CAPITAL LETTER U → LATIN CAPITAL LETTER U# - {66770, "7"}, // MA# ( 𐓒 → 7 ) OSAGE CAPITAL LETTER ZA → DIGIT SEVEN# - {66794, "o"}, // MA# ( 𐓪 → o ) OSAGE SMALL LETTER O → LATIN SMALL LETTER O# - {66806, "u"}, // MA# ( 𐓶 → u ) OSAGE SMALL LETTER U → LATIN SMALL LETTER U# →ᴜ→ - {66835, "N"}, // MA# ( 𐔓 → N ) ELBASAN LETTER NE → LATIN CAPITAL LETTER N# - {66838, "O"}, // MA# ( 𐔖 → O ) ELBASAN LETTER O → LATIN CAPITAL LETTER O# - {66840, "K"}, // MA# ( 𐔘 → K ) ELBASAN LETTER QE → LATIN CAPITAL LETTER K# - {66844, "C"}, // MA# ( 𐔜 → C ) ELBASAN LETTER SHE → LATIN CAPITAL LETTER C# - {66845, "V"}, // MA# ( 𐔝 → V ) ELBASAN LETTER TE → LATIN CAPITAL LETTER V# - {66853, "F"}, // MA# ( 𐔥 → F ) ELBASAN LETTER GHE → LATIN CAPITAL LETTER F# - {66854, "L"}, // MA# ( 𐔦 → L ) ELBASAN LETTER GHAMMA → LATIN CAPITAL LETTER L# - {66855, "X"}, // MA# ( 𐔧 → X ) ELBASAN LETTER KHE → LATIN CAPITAL LETTER X# - {68176, "."}, // MA#* ( ‎𐩐‎ → . ) KHAROSHTHI PUNCTUATION DOT → FULL STOP# - {70864, "O"}, // MA# ( 𑓐 → O ) TIRHUTA DIGIT ZERO → LATIN CAPITAL LETTER O# →০→→0→ - {71424, "rn"}, // MA# ( 𑜀 → rn ) AHOM LETTER KA → LATIN SMALL LETTER R, LATIN SMALL LETTER N# →m→ - {71430, "v"}, // MA# ( 𑜆 → v ) AHOM LETTER PA → LATIN SMALL LETTER V# - {71434, "w"}, // MA# ( 𑜊 → w ) AHOM LETTER JA → LATIN SMALL LETTER W# - {71438, "w"}, // MA# ( 𑜎 → w ) AHOM LETTER LA → LATIN SMALL LETTER W# - {71439, "w"}, // MA# ( 𑜏 → w ) AHOM LETTER SA → LATIN SMALL LETTER W# - {71840, "V"}, // MA# ( 𑢠 → V ) WARANG CITI CAPITAL LETTER NGAA → LATIN CAPITAL LETTER V# - {71842, "F"}, // MA# ( 𑢢 → F ) WARANG CITI CAPITAL LETTER WI → LATIN CAPITAL LETTER F# - {71843, "L"}, // MA# ( 𑢣 → L ) WARANG CITI CAPITAL LETTER YU → LATIN CAPITAL LETTER L# - {71844, "Y"}, // MA# ( 𑢤 → Y ) WARANG CITI CAPITAL LETTER YA → LATIN CAPITAL LETTER Y# - {71846, "E"}, // MA# ( 𑢦 → E ) WARANG CITI CAPITAL LETTER II → LATIN CAPITAL LETTER E# - {71849, "Z"}, // MA# ( 𑢩 → Z ) WARANG CITI CAPITAL LETTER O → LATIN CAPITAL LETTER Z# - {71852, "9"}, // MA# ( 𑢬 → 9 ) WARANG CITI CAPITAL LETTER KO → DIGIT NINE# - {71854, "E"}, // MA# ( 𑢮 → E ) WARANG CITI CAPITAL LETTER YUJ → LATIN CAPITAL LETTER E# - {71855, "4"}, // MA# ( 𑢯 → 4 ) WARANG CITI CAPITAL LETTER UC → DIGIT FOUR# - {71858, "L"}, // MA# ( 𑢲 → L ) WARANG CITI CAPITAL LETTER TTE → LATIN CAPITAL LETTER L# - {71861, "O"}, // MA# ( 𑢵 → O ) WARANG CITI CAPITAL LETTER AT → LATIN CAPITAL LETTER O# - {71864, "U"}, // MA# ( 𑢸 → U ) WARANG CITI CAPITAL LETTER PU → LATIN CAPITAL LETTER U# - {71867, "5"}, // MA# ( 𑢻 → 5 ) WARANG CITI CAPITAL LETTER HORR → DIGIT FIVE# - {71868, "T"}, // MA# ( 𑢼 → T ) WARANG CITI CAPITAL LETTER HAR → LATIN CAPITAL LETTER T# - {71872, "v"}, // MA# ( 𑣀 → v ) WARANG CITI SMALL LETTER NGAA → LATIN SMALL LETTER V# - {71873, "s"}, // MA# ( 𑣁 → s ) WARANG CITI SMALL LETTER A → LATIN SMALL LETTER S# - {71874, "F"}, // MA# ( 𑣂 → F ) WARANG CITI SMALL LETTER WI → LATIN CAPITAL LETTER F# - {71875, "i"}, // MA# ( 𑣃 → i ) WARANG CITI SMALL LETTER YU → LATIN SMALL LETTER I# →ι→ - {71876, "z"}, // MA# ( 𑣄 → z ) WARANG CITI SMALL LETTER YA → LATIN SMALL LETTER Z# - {71878, "7"}, // MA# ( 𑣆 → 7 ) WARANG CITI SMALL LETTER II → DIGIT SEVEN# - {71880, "o"}, // MA# ( 𑣈 → o ) WARANG CITI SMALL LETTER E → LATIN SMALL LETTER O# - {71882, "3"}, // MA# ( 𑣊 → 3 ) WARANG CITI SMALL LETTER ANG → DIGIT THREE# - {71884, "9"}, // MA# ( 𑣌 → 9 ) WARANG CITI SMALL LETTER KO → DIGIT NINE# - {71893, "6"}, // MA# ( 𑣕 → 6 ) WARANG CITI SMALL LETTER AT → DIGIT SIX# - {71894, "9"}, // MA# ( 𑣖 → 9 ) WARANG CITI SMALL LETTER AM → DIGIT NINE# - {71895, "o"}, // MA# ( 𑣗 → o ) WARANG CITI SMALL LETTER BU → LATIN SMALL LETTER O# - {71896, "u"}, // MA# ( 𑣘 → u ) WARANG CITI SMALL LETTER PU → LATIN SMALL LETTER U# →υ→→ʋ→ - {71900, "y"}, // MA# ( 𑣜 → y ) WARANG CITI SMALL LETTER HAR → LATIN SMALL LETTER Y# →ɣ→→γ→ - {71904, "O"}, // MA# ( 𑣠 → O ) WARANG CITI DIGIT ZERO → LATIN CAPITAL LETTER O# →0→ - {71907, "rn"}, // MA# ( 𑣣 → rn ) WARANG CITI DIGIT THREE → LATIN SMALL LETTER R, LATIN SMALL LETTER N# →m→ - {71909, "Z"}, // MA# ( 𑣥 → Z ) WARANG CITI DIGIT FIVE → LATIN CAPITAL LETTER Z# - {71910, "W"}, // MA# ( 𑣦 → W ) WARANG CITI DIGIT SIX → LATIN CAPITAL LETTER W# - {71913, "C"}, // MA# ( 𑣩 → C ) WARANG CITI DIGIT NINE → LATIN CAPITAL LETTER C# - {71916, "X"}, // MA#* ( 𑣬 → X ) WARANG CITI NUMBER THIRTY → LATIN CAPITAL LETTER X# - {71919, "W"}, // MA#* ( 𑣯 → W ) WARANG CITI NUMBER SIXTY → LATIN CAPITAL LETTER W# - {71922, "C"}, // MA#* ( 𑣲 → C ) WARANG CITI NUMBER NINETY → LATIN CAPITAL LETTER C# - {93960, "V"}, // MA# ( 𖼈 → V ) MIAO LETTER VA → LATIN CAPITAL LETTER V# - {93962, "T"}, // MA# ( 𖼊 → T ) MIAO LETTER TA → LATIN CAPITAL LETTER T# - {93974, "L"}, // MA# ( 𖼖 → L ) MIAO LETTER LA → LATIN CAPITAL LETTER L# - {93992, "l"}, // MA# ( 𖼨 → l ) MIAO LETTER GHA → LATIN SMALL LETTER L# →I→ - {94005, "R"}, // MA# ( 𖼵 → R ) MIAO LETTER ZHA → LATIN CAPITAL LETTER R# - {94010, "S"}, // MA# ( 𖼺 → S ) MIAO LETTER SA → LATIN CAPITAL LETTER S# - {94011, "3"}, // MA# ( 𖼻 → 3 ) MIAO LETTER ZA → DIGIT THREE# →Ʒ→ - {94015, ">"}, // MA# ( 𖼿 → > ) MIAO LETTER ARCHAIC ZZA → GREATER-THAN SIGN# - {94016, "A"}, // MA# ( 𖽀 → A ) MIAO LETTER ZZYA → LATIN CAPITAL LETTER A# - {94018, "U"}, // MA# ( 𖽂 → U ) MIAO LETTER WA → LATIN CAPITAL LETTER U# - {94019, "Y"}, // MA# ( 𖽃 → Y ) MIAO LETTER AH → LATIN CAPITAL LETTER Y# - {94033, "'"}, // MA# ( 𖽑 → ' ) MIAO SIGN ASPIRATION → APOSTROPHE# →ʼ→→′→ - {94034, "'"}, // MA# ( 𖽒 → ' ) MIAO SIGN REFORMED VOICING → APOSTROPHE# →ʻ→→‘→ - {119060, "{"}, // MA#* ( 𝄔 → { ) MUSICAL SYMBOL BRACE → LEFT CURLY BRACKET# - {119149, "."}, // MA# ( 𝅭 → . ) MUSICAL SYMBOL COMBINING AUGMENTATION DOT → FULL STOP# - {119302, "3"}, // MA#* ( 𝈆 → 3 ) GREEK VOCAL NOTATION SYMBOL-7 → DIGIT THREE# - {119309, "V"}, // MA#* ( 𝈍 → V ) GREEK VOCAL NOTATION SYMBOL-14 → LATIN CAPITAL LETTER V# - {119311, "\\"}, // MA#* ( 𝈏 → \ ) GREEK VOCAL NOTATION SYMBOL-16 → REVERSE SOLIDUS# - {119314, "7"}, // MA#* ( 𝈒 → 7 ) GREEK VOCAL NOTATION SYMBOL-19 → DIGIT SEVEN# - {119315, "F"}, // MA#* ( 𝈓 → F ) GREEK VOCAL NOTATION SYMBOL-20 → LATIN CAPITAL LETTER F# →Ϝ→ - {119318, "R"}, // MA#* ( 𝈖 → R ) GREEK VOCAL NOTATION SYMBOL-23 → LATIN CAPITAL LETTER R# - {119338, "L"}, // MA#* ( 𝈪 → L ) GREEK INSTRUMENTAL NOTATION SYMBOL-23 → LATIN CAPITAL LETTER L# - {119350, "<"}, // MA#* ( 𝈶 → < ) GREEK INSTRUMENTAL NOTATION SYMBOL-40 → LESS-THAN SIGN# - {119351, ">"}, // MA#* ( 𝈷 → > ) GREEK INSTRUMENTAL NOTATION SYMBOL-42 → GREATER-THAN SIGN# - {119354, "/"}, // MA#* ( 𝈺 → / ) GREEK INSTRUMENTAL NOTATION SYMBOL-47 → SOLIDUS# - {119355, "\\"}, // MA#* ( 𝈻 → \ ) GREEK INSTRUMENTAL NOTATION SYMBOL-48 → REVERSE SOLIDUS# →𝈏→ - {119808, "A"}, // MA# ( 𝐀 → A ) MATHEMATICAL BOLD CAPITAL A → LATIN CAPITAL LETTER A# - {119809, "B"}, // MA# ( 𝐁 → B ) MATHEMATICAL BOLD CAPITAL B → LATIN CAPITAL LETTER B# - {119810, "C"}, // MA# ( 𝐂 → C ) MATHEMATICAL BOLD CAPITAL C → LATIN CAPITAL LETTER C# - {119811, "D"}, // MA# ( 𝐃 → D ) MATHEMATICAL BOLD CAPITAL D → LATIN CAPITAL LETTER D# - {119812, "E"}, // MA# ( 𝐄 → E ) MATHEMATICAL BOLD CAPITAL E → LATIN CAPITAL LETTER E# - {119813, "F"}, // MA# ( 𝐅 → F ) MATHEMATICAL BOLD CAPITAL F → LATIN CAPITAL LETTER F# - {119814, "G"}, // MA# ( 𝐆 → G ) MATHEMATICAL BOLD CAPITAL G → LATIN CAPITAL LETTER G# - {119815, "H"}, // MA# ( 𝐇 → H ) MATHEMATICAL BOLD CAPITAL H → LATIN CAPITAL LETTER H# - {119816, "l"}, // MA# ( 𝐈 → l ) MATHEMATICAL BOLD CAPITAL I → LATIN SMALL LETTER L# →I→ - {119817, "J"}, // MA# ( 𝐉 → J ) MATHEMATICAL BOLD CAPITAL J → LATIN CAPITAL LETTER J# - {119818, "K"}, // MA# ( 𝐊 → K ) MATHEMATICAL BOLD CAPITAL K → LATIN CAPITAL LETTER K# - {119819, "L"}, // MA# ( 𝐋 → L ) MATHEMATICAL BOLD CAPITAL L → LATIN CAPITAL LETTER L# - {119820, "M"}, // MA# ( 𝐌 → M ) MATHEMATICAL BOLD CAPITAL M → LATIN CAPITAL LETTER M# - {119821, "N"}, // MA# ( 𝐍 → N ) MATHEMATICAL BOLD CAPITAL N → LATIN CAPITAL LETTER N# - {119822, "O"}, // MA# ( 𝐎 → O ) MATHEMATICAL BOLD CAPITAL O → LATIN CAPITAL LETTER O# - {119823, "P"}, // MA# ( 𝐏 → P ) MATHEMATICAL BOLD CAPITAL P → LATIN CAPITAL LETTER P# - {119824, "Q"}, // MA# ( 𝐐 → Q ) MATHEMATICAL BOLD CAPITAL Q → LATIN CAPITAL LETTER Q# - {119825, "R"}, // MA# ( 𝐑 → R ) MATHEMATICAL BOLD CAPITAL R → LATIN CAPITAL LETTER R# - {119826, "S"}, // MA# ( 𝐒 → S ) MATHEMATICAL BOLD CAPITAL S → LATIN CAPITAL LETTER S# - {119827, "T"}, // MA# ( 𝐓 → T ) MATHEMATICAL BOLD CAPITAL T → LATIN CAPITAL LETTER T# - {119828, "U"}, // MA# ( 𝐔 → U ) MATHEMATICAL BOLD CAPITAL U → LATIN CAPITAL LETTER U# - {119829, "V"}, // MA# ( 𝐕 → V ) MATHEMATICAL BOLD CAPITAL V → LATIN CAPITAL LETTER V# - {119830, "W"}, // MA# ( 𝐖 → W ) MATHEMATICAL BOLD CAPITAL W → LATIN CAPITAL LETTER W# - {119831, "X"}, // MA# ( 𝐗 → X ) MATHEMATICAL BOLD CAPITAL X → LATIN CAPITAL LETTER X# - {119832, "Y"}, // MA# ( 𝐘 → Y ) MATHEMATICAL BOLD CAPITAL Y → LATIN CAPITAL LETTER Y# - {119833, "Z"}, // MA# ( 𝐙 → Z ) MATHEMATICAL BOLD CAPITAL Z → LATIN CAPITAL LETTER Z# - {119834, "a"}, // MA# ( 𝐚 → a ) MATHEMATICAL BOLD SMALL A → LATIN SMALL LETTER A# - {119835, "b"}, // MA# ( 𝐛 → b ) MATHEMATICAL BOLD SMALL B → LATIN SMALL LETTER B# - {119836, "c"}, // MA# ( 𝐜 → c ) MATHEMATICAL BOLD SMALL C → LATIN SMALL LETTER C# - {119837, "d"}, // MA# ( 𝐝 → d ) MATHEMATICAL BOLD SMALL D → LATIN SMALL LETTER D# - {119838, "e"}, // MA# ( 𝐞 → e ) MATHEMATICAL BOLD SMALL E → LATIN SMALL LETTER E# - {119839, "f"}, // MA# ( 𝐟 → f ) MATHEMATICAL BOLD SMALL F → LATIN SMALL LETTER F# - {119840, "g"}, // MA# ( 𝐠 → g ) MATHEMATICAL BOLD SMALL G → LATIN SMALL LETTER G# - {119841, "h"}, // MA# ( 𝐡 → h ) MATHEMATICAL BOLD SMALL H → LATIN SMALL LETTER H# - {119842, "i"}, // MA# ( 𝐢 → i ) MATHEMATICAL BOLD SMALL I → LATIN SMALL LETTER I# - {119843, "j"}, // MA# ( 𝐣 → j ) MATHEMATICAL BOLD SMALL J → LATIN SMALL LETTER J# - {119844, "k"}, // MA# ( 𝐤 → k ) MATHEMATICAL BOLD SMALL K → LATIN SMALL LETTER K# - {119845, "l"}, // MA# ( 𝐥 → l ) MATHEMATICAL BOLD SMALL L → LATIN SMALL LETTER L# - {119846, "rn"}, // MA# ( 𝐦 → rn ) MATHEMATICAL BOLD SMALL M → LATIN SMALL LETTER R, LATIN SMALL LETTER N# →m→ - {119847, "n"}, // MA# ( 𝐧 → n ) MATHEMATICAL BOLD SMALL N → LATIN SMALL LETTER N# - {119848, "o"}, // MA# ( 𝐨 → o ) MATHEMATICAL BOLD SMALL O → LATIN SMALL LETTER O# - {119849, "p"}, // MA# ( 𝐩 → p ) MATHEMATICAL BOLD SMALL P → LATIN SMALL LETTER P# - {119850, "q"}, // MA# ( 𝐪 → q ) MATHEMATICAL BOLD SMALL Q → LATIN SMALL LETTER Q# - {119851, "r"}, // MA# ( 𝐫 → r ) MATHEMATICAL BOLD SMALL R → LATIN SMALL LETTER R# - {119852, "s"}, // MA# ( 𝐬 → s ) MATHEMATICAL BOLD SMALL S → LATIN SMALL LETTER S# - {119853, "t"}, // MA# ( 𝐭 → t ) MATHEMATICAL BOLD SMALL T → LATIN SMALL LETTER T# - {119854, "u"}, // MA# ( 𝐮 → u ) MATHEMATICAL BOLD SMALL U → LATIN SMALL LETTER U# - {119855, "v"}, // MA# ( 𝐯 → v ) MATHEMATICAL BOLD SMALL V → LATIN SMALL LETTER V# - {119856, "w"}, // MA# ( 𝐰 → w ) MATHEMATICAL BOLD SMALL W → LATIN SMALL LETTER W# - {119857, "x"}, // MA# ( 𝐱 → x ) MATHEMATICAL BOLD SMALL X → LATIN SMALL LETTER X# - {119858, "y"}, // MA# ( 𝐲 → y ) MATHEMATICAL BOLD SMALL Y → LATIN SMALL LETTER Y# - {119859, "z"}, // MA# ( 𝐳 → z ) MATHEMATICAL BOLD SMALL Z → LATIN SMALL LETTER Z# - {119860, "A"}, // MA# ( 𝐴 → A ) MATHEMATICAL ITALIC CAPITAL A → LATIN CAPITAL LETTER A# - {119861, "B"}, // MA# ( 𝐵 → B ) MATHEMATICAL ITALIC CAPITAL B → LATIN CAPITAL LETTER B# - {119862, "C"}, // MA# ( 𝐶 → C ) MATHEMATICAL ITALIC CAPITAL C → LATIN CAPITAL LETTER C# - {119863, "D"}, // MA# ( 𝐷 → D ) MATHEMATICAL ITALIC CAPITAL D → LATIN CAPITAL LETTER D# - {119864, "E"}, // MA# ( 𝐸 → E ) MATHEMATICAL ITALIC CAPITAL E → LATIN CAPITAL LETTER E# - {119865, "F"}, // MA# ( 𝐹 → F ) MATHEMATICAL ITALIC CAPITAL F → LATIN CAPITAL LETTER F# - {119866, "G"}, // MA# ( 𝐺 → G ) MATHEMATICAL ITALIC CAPITAL G → LATIN CAPITAL LETTER G# - {119867, "H"}, // MA# ( 𝐻 → H ) MATHEMATICAL ITALIC CAPITAL H → LATIN CAPITAL LETTER H# - {119868, "l"}, // MA# ( 𝐼 → l ) MATHEMATICAL ITALIC CAPITAL I → LATIN SMALL LETTER L# →I→ - {119869, "J"}, // MA# ( 𝐽 → J ) MATHEMATICAL ITALIC CAPITAL J → LATIN CAPITAL LETTER J# - {119870, "K"}, // MA# ( 𝐾 → K ) MATHEMATICAL ITALIC CAPITAL K → LATIN CAPITAL LETTER K# - {119871, "L"}, // MA# ( 𝐿 → L ) MATHEMATICAL ITALIC CAPITAL L → LATIN CAPITAL LETTER L# - {119872, "M"}, // MA# ( 𝑀 → M ) MATHEMATICAL ITALIC CAPITAL M → LATIN CAPITAL LETTER M# - {119873, "N"}, // MA# ( 𝑁 → N ) MATHEMATICAL ITALIC CAPITAL N → LATIN CAPITAL LETTER N# - {119874, "O"}, // MA# ( 𝑂 → O ) MATHEMATICAL ITALIC CAPITAL O → LATIN CAPITAL LETTER O# - {119875, "P"}, // MA# ( 𝑃 → P ) MATHEMATICAL ITALIC CAPITAL P → LATIN CAPITAL LETTER P# - {119876, "Q"}, // MA# ( 𝑄 → Q ) MATHEMATICAL ITALIC CAPITAL Q → LATIN CAPITAL LETTER Q# - {119877, "R"}, // MA# ( 𝑅 → R ) MATHEMATICAL ITALIC CAPITAL R → LATIN CAPITAL LETTER R# - {119878, "S"}, // MA# ( 𝑆 → S ) MATHEMATICAL ITALIC CAPITAL S → LATIN CAPITAL LETTER S# - {119879, "T"}, // MA# ( 𝑇 → T ) MATHEMATICAL ITALIC CAPITAL T → LATIN CAPITAL LETTER T# - {119880, "U"}, // MA# ( 𝑈 → U ) MATHEMATICAL ITALIC CAPITAL U → LATIN CAPITAL LETTER U# - {119881, "V"}, // MA# ( 𝑉 → V ) MATHEMATICAL ITALIC CAPITAL V → LATIN CAPITAL LETTER V# - {119882, "W"}, // MA# ( 𝑊 → W ) MATHEMATICAL ITALIC CAPITAL W → LATIN CAPITAL LETTER W# - {119883, "X"}, // MA# ( 𝑋 → X ) MATHEMATICAL ITALIC CAPITAL X → LATIN CAPITAL LETTER X# - {119884, "Y"}, // MA# ( 𝑌 → Y ) MATHEMATICAL ITALIC CAPITAL Y → LATIN CAPITAL LETTER Y# - {119885, "Z"}, // MA# ( 𝑍 → Z ) MATHEMATICAL ITALIC CAPITAL Z → LATIN CAPITAL LETTER Z# - {119886, "a"}, // MA# ( 𝑎 → a ) MATHEMATICAL ITALIC SMALL A → LATIN SMALL LETTER A# - {119887, "b"}, // MA# ( 𝑏 → b ) MATHEMATICAL ITALIC SMALL B → LATIN SMALL LETTER B# - {119888, "c"}, // MA# ( 𝑐 → c ) MATHEMATICAL ITALIC SMALL C → LATIN SMALL LETTER C# - {119889, "d"}, // MA# ( 𝑑 → d ) MATHEMATICAL ITALIC SMALL D → LATIN SMALL LETTER D# - {119890, "e"}, // MA# ( 𝑒 → e ) MATHEMATICAL ITALIC SMALL E → LATIN SMALL LETTER E# - {119891, "f"}, // MA# ( 𝑓 → f ) MATHEMATICAL ITALIC SMALL F → LATIN SMALL LETTER F# - {119892, "g"}, // MA# ( 𝑔 → g ) MATHEMATICAL ITALIC SMALL G → LATIN SMALL LETTER G# - {119894, "i"}, // MA# ( 𝑖 → i ) MATHEMATICAL ITALIC SMALL I → LATIN SMALL LETTER I# - {119895, "j"}, // MA# ( 𝑗 → j ) MATHEMATICAL ITALIC SMALL J → LATIN SMALL LETTER J# - {119896, "k"}, // MA# ( 𝑘 → k ) MATHEMATICAL ITALIC SMALL K → LATIN SMALL LETTER K# - {119897, "l"}, // MA# ( 𝑙 → l ) MATHEMATICAL ITALIC SMALL L → LATIN SMALL LETTER L# - {119898, "rn"}, // MA# ( 𝑚 → rn ) MATHEMATICAL ITALIC SMALL M → LATIN SMALL LETTER R, LATIN SMALL LETTER N# →m→ - {119899, "n"}, // MA# ( 𝑛 → n ) MATHEMATICAL ITALIC SMALL N → LATIN SMALL LETTER N# - {119900, "o"}, // MA# ( 𝑜 → o ) MATHEMATICAL ITALIC SMALL O → LATIN SMALL LETTER O# - {119901, "p"}, // MA# ( 𝑝 → p ) MATHEMATICAL ITALIC SMALL P → LATIN SMALL LETTER P# - {119902, "q"}, // MA# ( 𝑞 → q ) MATHEMATICAL ITALIC SMALL Q → LATIN SMALL LETTER Q# - {119903, "r"}, // MA# ( 𝑟 → r ) MATHEMATICAL ITALIC SMALL R → LATIN SMALL LETTER R# - {119904, "s"}, // MA# ( 𝑠 → s ) MATHEMATICAL ITALIC SMALL S → LATIN SMALL LETTER S# - {119905, "t"}, // MA# ( 𝑡 → t ) MATHEMATICAL ITALIC SMALL T → LATIN SMALL LETTER T# - {119906, "u"}, // MA# ( 𝑢 → u ) MATHEMATICAL ITALIC SMALL U → LATIN SMALL LETTER U# - {119907, "v"}, // MA# ( 𝑣 → v ) MATHEMATICAL ITALIC SMALL V → LATIN SMALL LETTER V# - {119908, "w"}, // MA# ( 𝑤 → w ) MATHEMATICAL ITALIC SMALL W → LATIN SMALL LETTER W# - {119909, "x"}, // MA# ( 𝑥 → x ) MATHEMATICAL ITALIC SMALL X → LATIN SMALL LETTER X# - {119910, "y"}, // MA# ( 𝑦 → y ) MATHEMATICAL ITALIC SMALL Y → LATIN SMALL LETTER Y# - {119911, "z"}, // MA# ( 𝑧 → z ) MATHEMATICAL ITALIC SMALL Z → LATIN SMALL LETTER Z# - {119912, "A"}, // MA# ( 𝑨 → A ) MATHEMATICAL BOLD ITALIC CAPITAL A → LATIN CAPITAL LETTER A# - {119913, "B"}, // MA# ( 𝑩 → B ) MATHEMATICAL BOLD ITALIC CAPITAL B → LATIN CAPITAL LETTER B# - {119914, "C"}, // MA# ( 𝑪 → C ) MATHEMATICAL BOLD ITALIC CAPITAL C → LATIN CAPITAL LETTER C# - {119915, "D"}, // MA# ( 𝑫 → D ) MATHEMATICAL BOLD ITALIC CAPITAL D → LATIN CAPITAL LETTER D# - {119916, "E"}, // MA# ( 𝑬 → E ) MATHEMATICAL BOLD ITALIC CAPITAL E → LATIN CAPITAL LETTER E# - {119917, "F"}, // MA# ( 𝑭 → F ) MATHEMATICAL BOLD ITALIC CAPITAL F → LATIN CAPITAL LETTER F# - {119918, "G"}, // MA# ( 𝑮 → G ) MATHEMATICAL BOLD ITALIC CAPITAL G → LATIN CAPITAL LETTER G# - {119919, "H"}, // MA# ( 𝑯 → H ) MATHEMATICAL BOLD ITALIC CAPITAL H → LATIN CAPITAL LETTER H# - {119920, "l"}, // MA# ( 𝑰 → l ) MATHEMATICAL BOLD ITALIC CAPITAL I → LATIN SMALL LETTER L# →I→ - {119921, "J"}, // MA# ( 𝑱 → J ) MATHEMATICAL BOLD ITALIC CAPITAL J → LATIN CAPITAL LETTER J# - {119922, "K"}, // MA# ( 𝑲 → K ) MATHEMATICAL BOLD ITALIC CAPITAL K → LATIN CAPITAL LETTER K# - {119923, "L"}, // MA# ( 𝑳 → L ) MATHEMATICAL BOLD ITALIC CAPITAL L → LATIN CAPITAL LETTER L# - {119924, "M"}, // MA# ( 𝑴 → M ) MATHEMATICAL BOLD ITALIC CAPITAL M → LATIN CAPITAL LETTER M# - {119925, "N"}, // MA# ( 𝑵 → N ) MATHEMATICAL BOLD ITALIC CAPITAL N → LATIN CAPITAL LETTER N# - {119926, "O"}, // MA# ( 𝑶 → O ) MATHEMATICAL BOLD ITALIC CAPITAL O → LATIN CAPITAL LETTER O# - {119927, "P"}, // MA# ( 𝑷 → P ) MATHEMATICAL BOLD ITALIC CAPITAL P → LATIN CAPITAL LETTER P# - {119928, "Q"}, // MA# ( 𝑸 → Q ) MATHEMATICAL BOLD ITALIC CAPITAL Q → LATIN CAPITAL LETTER Q# - {119929, "R"}, // MA# ( 𝑹 → R ) MATHEMATICAL BOLD ITALIC CAPITAL R → LATIN CAPITAL LETTER R# - {119930, "S"}, // MA# ( 𝑺 → S ) MATHEMATICAL BOLD ITALIC CAPITAL S → LATIN CAPITAL LETTER S# - {119931, "T"}, // MA# ( 𝑻 → T ) MATHEMATICAL BOLD ITALIC CAPITAL T → LATIN CAPITAL LETTER T# - {119932, "U"}, // MA# ( 𝑼 → U ) MATHEMATICAL BOLD ITALIC CAPITAL U → LATIN CAPITAL LETTER U# - {119933, "V"}, // MA# ( 𝑽 → V ) MATHEMATICAL BOLD ITALIC CAPITAL V → LATIN CAPITAL LETTER V# - {119934, "W"}, // MA# ( 𝑾 → W ) MATHEMATICAL BOLD ITALIC CAPITAL W → LATIN CAPITAL LETTER W# - {119935, "X"}, // MA# ( 𝑿 → X ) MATHEMATICAL BOLD ITALIC CAPITAL X → LATIN CAPITAL LETTER X# - {119936, "Y"}, // MA# ( 𝒀 → Y ) MATHEMATICAL BOLD ITALIC CAPITAL Y → LATIN CAPITAL LETTER Y# - {119937, "Z"}, // MA# ( 𝒁 → Z ) MATHEMATICAL BOLD ITALIC CAPITAL Z → LATIN CAPITAL LETTER Z# - {119938, "a"}, // MA# ( 𝒂 → a ) MATHEMATICAL BOLD ITALIC SMALL A → LATIN SMALL LETTER A# - {119939, "b"}, // MA# ( 𝒃 → b ) MATHEMATICAL BOLD ITALIC SMALL B → LATIN SMALL LETTER B# - {119940, "c"}, // MA# ( 𝒄 → c ) MATHEMATICAL BOLD ITALIC SMALL C → LATIN SMALL LETTER C# - {119941, "d"}, // MA# ( 𝒅 → d ) MATHEMATICAL BOLD ITALIC SMALL D → LATIN SMALL LETTER D# - {119942, "e"}, // MA# ( 𝒆 → e ) MATHEMATICAL BOLD ITALIC SMALL E → LATIN SMALL LETTER E# - {119943, "f"}, // MA# ( 𝒇 → f ) MATHEMATICAL BOLD ITALIC SMALL F → LATIN SMALL LETTER F# - {119944, "g"}, // MA# ( 𝒈 → g ) MATHEMATICAL BOLD ITALIC SMALL G → LATIN SMALL LETTER G# - {119945, "h"}, // MA# ( 𝒉 → h ) MATHEMATICAL BOLD ITALIC SMALL H → LATIN SMALL LETTER H# - {119946, "i"}, // MA# ( 𝒊 → i ) MATHEMATICAL BOLD ITALIC SMALL I → LATIN SMALL LETTER I# - {119947, "j"}, // MA# ( 𝒋 → j ) MATHEMATICAL BOLD ITALIC SMALL J → LATIN SMALL LETTER J# - {119948, "k"}, // MA# ( 𝒌 → k ) MATHEMATICAL BOLD ITALIC SMALL K → LATIN SMALL LETTER K# - {119949, "l"}, // MA# ( 𝒍 → l ) MATHEMATICAL BOLD ITALIC SMALL L → LATIN SMALL LETTER L# - {119950, "rn"}, // MA# ( 𝒎 → rn ) MATHEMATICAL BOLD ITALIC SMALL M → LATIN SMALL LETTER R, LATIN SMALL LETTER N# →m→ - {119951, "n"}, // MA# ( 𝒏 → n ) MATHEMATICAL BOLD ITALIC SMALL N → LATIN SMALL LETTER N# - {119952, "o"}, // MA# ( 𝒐 → o ) MATHEMATICAL BOLD ITALIC SMALL O → LATIN SMALL LETTER O# - {119953, "p"}, // MA# ( 𝒑 → p ) MATHEMATICAL BOLD ITALIC SMALL P → LATIN SMALL LETTER P# - {119954, "q"}, // MA# ( 𝒒 → q ) MATHEMATICAL BOLD ITALIC SMALL Q → LATIN SMALL LETTER Q# - {119955, "r"}, // MA# ( 𝒓 → r ) MATHEMATICAL BOLD ITALIC SMALL R → LATIN SMALL LETTER R# - {119956, "s"}, // MA# ( 𝒔 → s ) MATHEMATICAL BOLD ITALIC SMALL S → LATIN SMALL LETTER S# - {119957, "t"}, // MA# ( 𝒕 → t ) MATHEMATICAL BOLD ITALIC SMALL T → LATIN SMALL LETTER T# - {119958, "u"}, // MA# ( 𝒖 → u ) MATHEMATICAL BOLD ITALIC SMALL U → LATIN SMALL LETTER U# - {119959, "v"}, // MA# ( 𝒗 → v ) MATHEMATICAL BOLD ITALIC SMALL V → LATIN SMALL LETTER V# - {119960, "w"}, // MA# ( 𝒘 → w ) MATHEMATICAL BOLD ITALIC SMALL W → LATIN SMALL LETTER W# - {119961, "x"}, // MA# ( 𝒙 → x ) MATHEMATICAL BOLD ITALIC SMALL X → LATIN SMALL LETTER X# - {119962, "y"}, // MA# ( 𝒚 → y ) MATHEMATICAL BOLD ITALIC SMALL Y → LATIN SMALL LETTER Y# - {119963, "z"}, // MA# ( 𝒛 → z ) MATHEMATICAL BOLD ITALIC SMALL Z → LATIN SMALL LETTER Z# - {119964, "A"}, // MA# ( 𝒜 → A ) MATHEMATICAL SCRIPT CAPITAL A → LATIN CAPITAL LETTER A# - {119966, "C"}, // MA# ( 𝒞 → C ) MATHEMATICAL SCRIPT CAPITAL C → LATIN CAPITAL LETTER C# - {119967, "D"}, // MA# ( 𝒟 → D ) MATHEMATICAL SCRIPT CAPITAL D → LATIN CAPITAL LETTER D# - {119970, "G"}, // MA# ( 𝒢 → G ) MATHEMATICAL SCRIPT CAPITAL G → LATIN CAPITAL LETTER G# - {119973, "J"}, // MA# ( 𝒥 → J ) MATHEMATICAL SCRIPT CAPITAL J → LATIN CAPITAL LETTER J# - {119974, "K"}, // MA# ( 𝒦 → K ) MATHEMATICAL SCRIPT CAPITAL K → LATIN CAPITAL LETTER K# - {119977, "N"}, // MA# ( 𝒩 → N ) MATHEMATICAL SCRIPT CAPITAL N → LATIN CAPITAL LETTER N# - {119978, "O"}, // MA# ( 𝒪 → O ) MATHEMATICAL SCRIPT CAPITAL O → LATIN CAPITAL LETTER O# - {119979, "P"}, // MA# ( 𝒫 → P ) MATHEMATICAL SCRIPT CAPITAL P → LATIN CAPITAL LETTER P# - {119980, "Q"}, // MA# ( 𝒬 → Q ) MATHEMATICAL SCRIPT CAPITAL Q → LATIN CAPITAL LETTER Q# - {119982, "S"}, // MA# ( 𝒮 → S ) MATHEMATICAL SCRIPT CAPITAL S → LATIN CAPITAL LETTER S# - {119983, "T"}, // MA# ( 𝒯 → T ) MATHEMATICAL SCRIPT CAPITAL T → LATIN CAPITAL LETTER T# - {119984, "U"}, // MA# ( 𝒰 → U ) MATHEMATICAL SCRIPT CAPITAL U → LATIN CAPITAL LETTER U# - {119985, "V"}, // MA# ( 𝒱 → V ) MATHEMATICAL SCRIPT CAPITAL V → LATIN CAPITAL LETTER V# - {119986, "W"}, // MA# ( 𝒲 → W ) MATHEMATICAL SCRIPT CAPITAL W → LATIN CAPITAL LETTER W# - {119987, "X"}, // MA# ( 𝒳 → X ) MATHEMATICAL SCRIPT CAPITAL X → LATIN CAPITAL LETTER X# - {119988, "Y"}, // MA# ( 𝒴 → Y ) MATHEMATICAL SCRIPT CAPITAL Y → LATIN CAPITAL LETTER Y# - {119989, "Z"}, // MA# ( 𝒵 → Z ) MATHEMATICAL SCRIPT CAPITAL Z → LATIN CAPITAL LETTER Z# - {119990, "a"}, // MA# ( 𝒶 → a ) MATHEMATICAL SCRIPT SMALL A → LATIN SMALL LETTER A# - {119991, "b"}, // MA# ( 𝒷 → b ) MATHEMATICAL SCRIPT SMALL B → LATIN SMALL LETTER B# - {119992, "c"}, // MA# ( 𝒸 → c ) MATHEMATICAL SCRIPT SMALL C → LATIN SMALL LETTER C# - {119993, "d"}, // MA# ( 𝒹 → d ) MATHEMATICAL SCRIPT SMALL D → LATIN SMALL LETTER D# - {119995, "f"}, // MA# ( 𝒻 → f ) MATHEMATICAL SCRIPT SMALL F → LATIN SMALL LETTER F# - {119997, "h"}, // MA# ( 𝒽 → h ) MATHEMATICAL SCRIPT SMALL H → LATIN SMALL LETTER H# - {119998, "i"}, // MA# ( 𝒾 → i ) MATHEMATICAL SCRIPT SMALL I → LATIN SMALL LETTER I# - {119999, "j"}, // MA# ( 𝒿 → j ) MATHEMATICAL SCRIPT SMALL J → LATIN SMALL LETTER J# - {120000, "k"}, // MA# ( 𝓀 → k ) MATHEMATICAL SCRIPT SMALL K → LATIN SMALL LETTER K# - {120001, "l"}, // MA# ( 𝓁 → l ) MATHEMATICAL SCRIPT SMALL L → LATIN SMALL LETTER L# - {120002, "rn"}, // MA# ( 𝓂 → rn ) MATHEMATICAL SCRIPT SMALL M → LATIN SMALL LETTER R, LATIN SMALL LETTER N# →m→ - {120003, "n"}, // MA# ( 𝓃 → n ) MATHEMATICAL SCRIPT SMALL N → LATIN SMALL LETTER N# - {120005, "p"}, // MA# ( 𝓅 → p ) MATHEMATICAL SCRIPT SMALL P → LATIN SMALL LETTER P# - {120006, "q"}, // MA# ( 𝓆 → q ) MATHEMATICAL SCRIPT SMALL Q → LATIN SMALL LETTER Q# - {120007, "r"}, // MA# ( 𝓇 → r ) MATHEMATICAL SCRIPT SMALL R → LATIN SMALL LETTER R# - {120008, "s"}, // MA# ( 𝓈 → s ) MATHEMATICAL SCRIPT SMALL S → LATIN SMALL LETTER S# - {120009, "t"}, // MA# ( 𝓉 → t ) MATHEMATICAL SCRIPT SMALL T → LATIN SMALL LETTER T# - {120010, "u"}, // MA# ( 𝓊 → u ) MATHEMATICAL SCRIPT SMALL U → LATIN SMALL LETTER U# - {120011, "v"}, // MA# ( 𝓋 → v ) MATHEMATICAL SCRIPT SMALL V → LATIN SMALL LETTER V# - {120012, "w"}, // MA# ( 𝓌 → w ) MATHEMATICAL SCRIPT SMALL W → LATIN SMALL LETTER W# - {120013, "x"}, // MA# ( 𝓍 → x ) MATHEMATICAL SCRIPT SMALL X → LATIN SMALL LETTER X# - {120014, "y"}, // MA# ( 𝓎 → y ) MATHEMATICAL SCRIPT SMALL Y → LATIN SMALL LETTER Y# - {120015, "z"}, // MA# ( 𝓏 → z ) MATHEMATICAL SCRIPT SMALL Z → LATIN SMALL LETTER Z# - {120016, "A"}, // MA# ( 𝓐 → A ) MATHEMATICAL BOLD SCRIPT CAPITAL A → LATIN CAPITAL LETTER A# - {120017, "B"}, // MA# ( 𝓑 → B ) MATHEMATICAL BOLD SCRIPT CAPITAL B → LATIN CAPITAL LETTER B# - {120018, "C"}, // MA# ( 𝓒 → C ) MATHEMATICAL BOLD SCRIPT CAPITAL C → LATIN CAPITAL LETTER C# - {120019, "D"}, // MA# ( 𝓓 → D ) MATHEMATICAL BOLD SCRIPT CAPITAL D → LATIN CAPITAL LETTER D# - {120020, "E"}, // MA# ( 𝓔 → E ) MATHEMATICAL BOLD SCRIPT CAPITAL E → LATIN CAPITAL LETTER E# - {120021, "F"}, // MA# ( 𝓕 → F ) MATHEMATICAL BOLD SCRIPT CAPITAL F → LATIN CAPITAL LETTER F# - {120022, "G"}, // MA# ( 𝓖 → G ) MATHEMATICAL BOLD SCRIPT CAPITAL G → LATIN CAPITAL LETTER G# - {120023, "H"}, // MA# ( 𝓗 → H ) MATHEMATICAL BOLD SCRIPT CAPITAL H → LATIN CAPITAL LETTER H# - {120024, "l"}, // MA# ( 𝓘 → l ) MATHEMATICAL BOLD SCRIPT CAPITAL I → LATIN SMALL LETTER L# →I→ - {120025, "J"}, // MA# ( 𝓙 → J ) MATHEMATICAL BOLD SCRIPT CAPITAL J → LATIN CAPITAL LETTER J# - {120026, "K"}, // MA# ( 𝓚 → K ) MATHEMATICAL BOLD SCRIPT CAPITAL K → LATIN CAPITAL LETTER K# - {120027, "L"}, // MA# ( 𝓛 → L ) MATHEMATICAL BOLD SCRIPT CAPITAL L → LATIN CAPITAL LETTER L# - {120028, "M"}, // MA# ( 𝓜 → M ) MATHEMATICAL BOLD SCRIPT CAPITAL M → LATIN CAPITAL LETTER M# - {120029, "N"}, // MA# ( 𝓝 → N ) MATHEMATICAL BOLD SCRIPT CAPITAL N → LATIN CAPITAL LETTER N# - {120030, "O"}, // MA# ( 𝓞 → O ) MATHEMATICAL BOLD SCRIPT CAPITAL O → LATIN CAPITAL LETTER O# - {120031, "P"}, // MA# ( 𝓟 → P ) MATHEMATICAL BOLD SCRIPT CAPITAL P → LATIN CAPITAL LETTER P# - {120032, "Q"}, // MA# ( 𝓠 → Q ) MATHEMATICAL BOLD SCRIPT CAPITAL Q → LATIN CAPITAL LETTER Q# - {120033, "R"}, // MA# ( 𝓡 → R ) MATHEMATICAL BOLD SCRIPT CAPITAL R → LATIN CAPITAL LETTER R# - {120034, "S"}, // MA# ( 𝓢 → S ) MATHEMATICAL BOLD SCRIPT CAPITAL S → LATIN CAPITAL LETTER S# - {120035, "T"}, // MA# ( 𝓣 → T ) MATHEMATICAL BOLD SCRIPT CAPITAL T → LATIN CAPITAL LETTER T# - {120036, "U"}, // MA# ( 𝓤 → U ) MATHEMATICAL BOLD SCRIPT CAPITAL U → LATIN CAPITAL LETTER U# - {120037, "V"}, // MA# ( 𝓥 → V ) MATHEMATICAL BOLD SCRIPT CAPITAL V → LATIN CAPITAL LETTER V# - {120038, "W"}, // MA# ( 𝓦 → W ) MATHEMATICAL BOLD SCRIPT CAPITAL W → LATIN CAPITAL LETTER W# - {120039, "X"}, // MA# ( 𝓧 → X ) MATHEMATICAL BOLD SCRIPT CAPITAL X → LATIN CAPITAL LETTER X# - {120040, "Y"}, // MA# ( 𝓨 → Y ) MATHEMATICAL BOLD SCRIPT CAPITAL Y → LATIN CAPITAL LETTER Y# - {120041, "Z"}, // MA# ( 𝓩 → Z ) MATHEMATICAL BOLD SCRIPT CAPITAL Z → LATIN CAPITAL LETTER Z# - {120042, "a"}, // MA# ( 𝓪 → a ) MATHEMATICAL BOLD SCRIPT SMALL A → LATIN SMALL LETTER A# - {120043, "b"}, // MA# ( 𝓫 → b ) MATHEMATICAL BOLD SCRIPT SMALL B → LATIN SMALL LETTER B# - {120044, "c"}, // MA# ( 𝓬 → c ) MATHEMATICAL BOLD SCRIPT SMALL C → LATIN SMALL LETTER C# - {120045, "d"}, // MA# ( 𝓭 → d ) MATHEMATICAL BOLD SCRIPT SMALL D → LATIN SMALL LETTER D# - {120046, "e"}, // MA# ( 𝓮 → e ) MATHEMATICAL BOLD SCRIPT SMALL E → LATIN SMALL LETTER E# - {120047, "f"}, // MA# ( 𝓯 → f ) MATHEMATICAL BOLD SCRIPT SMALL F → LATIN SMALL LETTER F# - {120048, "g"}, // MA# ( 𝓰 → g ) MATHEMATICAL BOLD SCRIPT SMALL G → LATIN SMALL LETTER G# - {120049, "h"}, // MA# ( 𝓱 → h ) MATHEMATICAL BOLD SCRIPT SMALL H → LATIN SMALL LETTER H# - {120050, "i"}, // MA# ( 𝓲 → i ) MATHEMATICAL BOLD SCRIPT SMALL I → LATIN SMALL LETTER I# - {120051, "j"}, // MA# ( 𝓳 → j ) MATHEMATICAL BOLD SCRIPT SMALL J → LATIN SMALL LETTER J# - {120052, "k"}, // MA# ( 𝓴 → k ) MATHEMATICAL BOLD SCRIPT SMALL K → LATIN SMALL LETTER K# - {120053, "l"}, // MA# ( 𝓵 → l ) MATHEMATICAL BOLD SCRIPT SMALL L → LATIN SMALL LETTER L# - {120054, "rn"}, // MA# ( 𝓶 → rn ) MATHEMATICAL BOLD SCRIPT SMALL M → LATIN SMALL LETTER R, LATIN SMALL LETTER N# →m→ - {120055, "n"}, // MA# ( 𝓷 → n ) MATHEMATICAL BOLD SCRIPT SMALL N → LATIN SMALL LETTER N# - {120056, "o"}, // MA# ( 𝓸 → o ) MATHEMATICAL BOLD SCRIPT SMALL O → LATIN SMALL LETTER O# - {120057, "p"}, // MA# ( 𝓹 → p ) MATHEMATICAL BOLD SCRIPT SMALL P → LATIN SMALL LETTER P# - {120058, "q"}, // MA# ( 𝓺 → q ) MATHEMATICAL BOLD SCRIPT SMALL Q → LATIN SMALL LETTER Q# - {120059, "r"}, // MA# ( 𝓻 → r ) MATHEMATICAL BOLD SCRIPT SMALL R → LATIN SMALL LETTER R# - {120060, "s"}, // MA# ( 𝓼 → s ) MATHEMATICAL BOLD SCRIPT SMALL S → LATIN SMALL LETTER S# - {120061, "t"}, // MA# ( 𝓽 → t ) MATHEMATICAL BOLD SCRIPT SMALL T → LATIN SMALL LETTER T# - {120062, "u"}, // MA# ( 𝓾 → u ) MATHEMATICAL BOLD SCRIPT SMALL U → LATIN SMALL LETTER U# - {120063, "v"}, // MA# ( 𝓿 → v ) MATHEMATICAL BOLD SCRIPT SMALL V → LATIN SMALL LETTER V# - {120064, "w"}, // MA# ( 𝔀 → w ) MATHEMATICAL BOLD SCRIPT SMALL W → LATIN SMALL LETTER W# - {120065, "x"}, // MA# ( 𝔁 → x ) MATHEMATICAL BOLD SCRIPT SMALL X → LATIN SMALL LETTER X# - {120066, "y"}, // MA# ( 𝔂 → y ) MATHEMATICAL BOLD SCRIPT SMALL Y → LATIN SMALL LETTER Y# - {120067, "z"}, // MA# ( 𝔃 → z ) MATHEMATICAL BOLD SCRIPT SMALL Z → LATIN SMALL LETTER Z# - {120068, "A"}, // MA# ( 𝔄 → A ) MATHEMATICAL FRAKTUR CAPITAL A → LATIN CAPITAL LETTER A# - {120069, "B"}, // MA# ( 𝔅 → B ) MATHEMATICAL FRAKTUR CAPITAL B → LATIN CAPITAL LETTER B# - {120071, "D"}, // MA# ( 𝔇 → D ) MATHEMATICAL FRAKTUR CAPITAL D → LATIN CAPITAL LETTER D# - {120072, "E"}, // MA# ( 𝔈 → E ) MATHEMATICAL FRAKTUR CAPITAL E → LATIN CAPITAL LETTER E# - {120073, "F"}, // MA# ( 𝔉 → F ) MATHEMATICAL FRAKTUR CAPITAL F → LATIN CAPITAL LETTER F# - {120074, "G"}, // MA# ( 𝔊 → G ) MATHEMATICAL FRAKTUR CAPITAL G → LATIN CAPITAL LETTER G# - {120077, "J"}, // MA# ( 𝔍 → J ) MATHEMATICAL FRAKTUR CAPITAL J → LATIN CAPITAL LETTER J# - {120078, "K"}, // MA# ( 𝔎 → K ) MATHEMATICAL FRAKTUR CAPITAL K → LATIN CAPITAL LETTER K# - {120079, "L"}, // MA# ( 𝔏 → L ) MATHEMATICAL FRAKTUR CAPITAL L → LATIN CAPITAL LETTER L# - {120080, "M"}, // MA# ( 𝔐 → M ) MATHEMATICAL FRAKTUR CAPITAL M → LATIN CAPITAL LETTER M# - {120081, "N"}, // MA# ( 𝔑 → N ) MATHEMATICAL FRAKTUR CAPITAL N → LATIN CAPITAL LETTER N# - {120082, "O"}, // MA# ( 𝔒 → O ) MATHEMATICAL FRAKTUR CAPITAL O → LATIN CAPITAL LETTER O# - {120083, "P"}, // MA# ( 𝔓 → P ) MATHEMATICAL FRAKTUR CAPITAL P → LATIN CAPITAL LETTER P# - {120084, "Q"}, // MA# ( 𝔔 → Q ) MATHEMATICAL FRAKTUR CAPITAL Q → LATIN CAPITAL LETTER Q# - {120086, "S"}, // MA# ( 𝔖 → S ) MATHEMATICAL FRAKTUR CAPITAL S → LATIN CAPITAL LETTER S# - {120087, "T"}, // MA# ( 𝔗 → T ) MATHEMATICAL FRAKTUR CAPITAL T → LATIN CAPITAL LETTER T# - {120088, "U"}, // MA# ( 𝔘 → U ) MATHEMATICAL FRAKTUR CAPITAL U → LATIN CAPITAL LETTER U# - {120089, "V"}, // MA# ( 𝔙 → V ) MATHEMATICAL FRAKTUR CAPITAL V → LATIN CAPITAL LETTER V# - {120090, "W"}, // MA# ( 𝔚 → W ) MATHEMATICAL FRAKTUR CAPITAL W → LATIN CAPITAL LETTER W# - {120091, "X"}, // MA# ( 𝔛 → X ) MATHEMATICAL FRAKTUR CAPITAL X → LATIN CAPITAL LETTER X# - {120092, "Y"}, // MA# ( 𝔜 → Y ) MATHEMATICAL FRAKTUR CAPITAL Y → LATIN CAPITAL LETTER Y# - {120094, "a"}, // MA# ( 𝔞 → a ) MATHEMATICAL FRAKTUR SMALL A → LATIN SMALL LETTER A# - {120095, "b"}, // MA# ( 𝔟 → b ) MATHEMATICAL FRAKTUR SMALL B → LATIN SMALL LETTER B# - {120096, "c"}, // MA# ( 𝔠 → c ) MATHEMATICAL FRAKTUR SMALL C → LATIN SMALL LETTER C# - {120097, "d"}, // MA# ( 𝔡 → d ) MATHEMATICAL FRAKTUR SMALL D → LATIN SMALL LETTER D# - {120098, "e"}, // MA# ( 𝔢 → e ) MATHEMATICAL FRAKTUR SMALL E → LATIN SMALL LETTER E# - {120099, "f"}, // MA# ( 𝔣 → f ) MATHEMATICAL FRAKTUR SMALL F → LATIN SMALL LETTER F# - {120100, "g"}, // MA# ( 𝔤 → g ) MATHEMATICAL FRAKTUR SMALL G → LATIN SMALL LETTER G# - {120101, "h"}, // MA# ( 𝔥 → h ) MATHEMATICAL FRAKTUR SMALL H → LATIN SMALL LETTER H# - {120102, "i"}, // MA# ( 𝔦 → i ) MATHEMATICAL FRAKTUR SMALL I → LATIN SMALL LETTER I# - {120103, "j"}, // MA# ( 𝔧 → j ) MATHEMATICAL FRAKTUR SMALL J → LATIN SMALL LETTER J# - {120104, "k"}, // MA# ( 𝔨 → k ) MATHEMATICAL FRAKTUR SMALL K → LATIN SMALL LETTER K# - {120105, "l"}, // MA# ( 𝔩 → l ) MATHEMATICAL FRAKTUR SMALL L → LATIN SMALL LETTER L# - {120106, "rn"}, // MA# ( 𝔪 → rn ) MATHEMATICAL FRAKTUR SMALL M → LATIN SMALL LETTER R, LATIN SMALL LETTER N# →m→ - {120107, "n"}, // MA# ( 𝔫 → n ) MATHEMATICAL FRAKTUR SMALL N → LATIN SMALL LETTER N# - {120108, "o"}, // MA# ( 𝔬 → o ) MATHEMATICAL FRAKTUR SMALL O → LATIN SMALL LETTER O# - {120109, "p"}, // MA# ( 𝔭 → p ) MATHEMATICAL FRAKTUR SMALL P → LATIN SMALL LETTER P# - {120110, "q"}, // MA# ( 𝔮 → q ) MATHEMATICAL FRAKTUR SMALL Q → LATIN SMALL LETTER Q# - {120111, "r"}, // MA# ( 𝔯 → r ) MATHEMATICAL FRAKTUR SMALL R → LATIN SMALL LETTER R# - {120112, "s"}, // MA# ( 𝔰 → s ) MATHEMATICAL FRAKTUR SMALL S → LATIN SMALL LETTER S# - {120113, "t"}, // MA# ( 𝔱 → t ) MATHEMATICAL FRAKTUR SMALL T → LATIN SMALL LETTER T# - {120114, "u"}, // MA# ( 𝔲 → u ) MATHEMATICAL FRAKTUR SMALL U → LATIN SMALL LETTER U# - {120115, "v"}, // MA# ( 𝔳 → v ) MATHEMATICAL FRAKTUR SMALL V → LATIN SMALL LETTER V# - {120116, "w"}, // MA# ( 𝔴 → w ) MATHEMATICAL FRAKTUR SMALL W → LATIN SMALL LETTER W# - {120117, "x"}, // MA# ( 𝔵 → x ) MATHEMATICAL FRAKTUR SMALL X → LATIN SMALL LETTER X# - {120118, "y"}, // MA# ( 𝔶 → y ) MATHEMATICAL FRAKTUR SMALL Y → LATIN SMALL LETTER Y# - {120119, "z"}, // MA# ( 𝔷 → z ) MATHEMATICAL FRAKTUR SMALL Z → LATIN SMALL LETTER Z# - {120120, "A"}, // MA# ( 𝔸 → A ) MATHEMATICAL DOUBLE-STRUCK CAPITAL A → LATIN CAPITAL LETTER A# - {120121, "B"}, // MA# ( 𝔹 → B ) MATHEMATICAL DOUBLE-STRUCK CAPITAL B → LATIN CAPITAL LETTER B# - {120123, "D"}, // MA# ( 𝔻 → D ) MATHEMATICAL DOUBLE-STRUCK CAPITAL D → LATIN CAPITAL LETTER D# - {120124, "E"}, // MA# ( 𝔼 → E ) MATHEMATICAL DOUBLE-STRUCK CAPITAL E → LATIN CAPITAL LETTER E# - {120125, "F"}, // MA# ( 𝔽 → F ) MATHEMATICAL DOUBLE-STRUCK CAPITAL F → LATIN CAPITAL LETTER F# - {120126, "G"}, // MA# ( 𝔾 → G ) MATHEMATICAL DOUBLE-STRUCK CAPITAL G → LATIN CAPITAL LETTER G# - {120128, "l"}, // MA# ( 𝕀 → l ) MATHEMATICAL DOUBLE-STRUCK CAPITAL I → LATIN SMALL LETTER L# →I→ - {120129, "J"}, // MA# ( 𝕁 → J ) MATHEMATICAL DOUBLE-STRUCK CAPITAL J → LATIN CAPITAL LETTER J# - {120130, "K"}, // MA# ( 𝕂 → K ) MATHEMATICAL DOUBLE-STRUCK CAPITAL K → LATIN CAPITAL LETTER K# - {120131, "L"}, // MA# ( 𝕃 → L ) MATHEMATICAL DOUBLE-STRUCK CAPITAL L → LATIN CAPITAL LETTER L# - {120132, "M"}, // MA# ( 𝕄 → M ) MATHEMATICAL DOUBLE-STRUCK CAPITAL M → LATIN CAPITAL LETTER M# - {120134, "O"}, // MA# ( 𝕆 → O ) MATHEMATICAL DOUBLE-STRUCK CAPITAL O → LATIN CAPITAL LETTER O# - {120138, "S"}, // MA# ( 𝕊 → S ) MATHEMATICAL DOUBLE-STRUCK CAPITAL S → LATIN CAPITAL LETTER S# - {120139, "T"}, // MA# ( 𝕋 → T ) MATHEMATICAL DOUBLE-STRUCK CAPITAL T → LATIN CAPITAL LETTER T# - {120140, "U"}, // MA# ( 𝕌 → U ) MATHEMATICAL DOUBLE-STRUCK CAPITAL U → LATIN CAPITAL LETTER U# - {120141, "V"}, // MA# ( 𝕍 → V ) MATHEMATICAL DOUBLE-STRUCK CAPITAL V → LATIN CAPITAL LETTER V# - {120142, "W"}, // MA# ( 𝕎 → W ) MATHEMATICAL DOUBLE-STRUCK CAPITAL W → LATIN CAPITAL LETTER W# - {120143, "X"}, // MA# ( 𝕏 → X ) MATHEMATICAL DOUBLE-STRUCK CAPITAL X → LATIN CAPITAL LETTER X# - {120144, "Y"}, // MA# ( 𝕐 → Y ) MATHEMATICAL DOUBLE-STRUCK CAPITAL Y → LATIN CAPITAL LETTER Y# - {120146, "a"}, // MA# ( 𝕒 → a ) MATHEMATICAL DOUBLE-STRUCK SMALL A → LATIN SMALL LETTER A# - {120147, "b"}, // MA# ( 𝕓 → b ) MATHEMATICAL DOUBLE-STRUCK SMALL B → LATIN SMALL LETTER B# - {120148, "c"}, // MA# ( 𝕔 → c ) MATHEMATICAL DOUBLE-STRUCK SMALL C → LATIN SMALL LETTER C# - {120149, "d"}, // MA# ( 𝕕 → d ) MATHEMATICAL DOUBLE-STRUCK SMALL D → LATIN SMALL LETTER D# - {120150, "e"}, // MA# ( 𝕖 → e ) MATHEMATICAL DOUBLE-STRUCK SMALL E → LATIN SMALL LETTER E# - {120151, "f"}, // MA# ( 𝕗 → f ) MATHEMATICAL DOUBLE-STRUCK SMALL F → LATIN SMALL LETTER F# - {120152, "g"}, // MA# ( 𝕘 → g ) MATHEMATICAL DOUBLE-STRUCK SMALL G → LATIN SMALL LETTER G# - {120153, "h"}, // MA# ( 𝕙 → h ) MATHEMATICAL DOUBLE-STRUCK SMALL H → LATIN SMALL LETTER H# - {120154, "i"}, // MA# ( 𝕚 → i ) MATHEMATICAL DOUBLE-STRUCK SMALL I → LATIN SMALL LETTER I# - {120155, "j"}, // MA# ( 𝕛 → j ) MATHEMATICAL DOUBLE-STRUCK SMALL J → LATIN SMALL LETTER J# - {120156, "k"}, // MA# ( 𝕜 → k ) MATHEMATICAL DOUBLE-STRUCK SMALL K → LATIN SMALL LETTER K# - {120157, "l"}, // MA# ( 𝕝 → l ) MATHEMATICAL DOUBLE-STRUCK SMALL L → LATIN SMALL LETTER L# - {120158, "rn"}, // MA# ( 𝕞 → rn ) MATHEMATICAL DOUBLE-STRUCK SMALL M → LATIN SMALL LETTER R, LATIN SMALL LETTER N# →m→ - {120159, "n"}, // MA# ( 𝕟 → n ) MATHEMATICAL DOUBLE-STRUCK SMALL N → LATIN SMALL LETTER N# - {120160, "o"}, // MA# ( 𝕠 → o ) MATHEMATICAL DOUBLE-STRUCK SMALL O → LATIN SMALL LETTER O# - {120161, "p"}, // MA# ( 𝕡 → p ) MATHEMATICAL DOUBLE-STRUCK SMALL P → LATIN SMALL LETTER P# - {120162, "q"}, // MA# ( 𝕢 → q ) MATHEMATICAL DOUBLE-STRUCK SMALL Q → LATIN SMALL LETTER Q# - {120163, "r"}, // MA# ( 𝕣 → r ) MATHEMATICAL DOUBLE-STRUCK SMALL R → LATIN SMALL LETTER R# - {120164, "s"}, // MA# ( 𝕤 → s ) MATHEMATICAL DOUBLE-STRUCK SMALL S → LATIN SMALL LETTER S# - {120165, "t"}, // MA# ( 𝕥 → t ) MATHEMATICAL DOUBLE-STRUCK SMALL T → LATIN SMALL LETTER T# - {120166, "u"}, // MA# ( 𝕦 → u ) MATHEMATICAL DOUBLE-STRUCK SMALL U → LATIN SMALL LETTER U# - {120167, "v"}, // MA# ( 𝕧 → v ) MATHEMATICAL DOUBLE-STRUCK SMALL V → LATIN SMALL LETTER V# - {120168, "w"}, // MA# ( 𝕨 → w ) MATHEMATICAL DOUBLE-STRUCK SMALL W → LATIN SMALL LETTER W# - {120169, "x"}, // MA# ( 𝕩 → x ) MATHEMATICAL DOUBLE-STRUCK SMALL X → LATIN SMALL LETTER X# - {120170, "y"}, // MA# ( 𝕪 → y ) MATHEMATICAL DOUBLE-STRUCK SMALL Y → LATIN SMALL LETTER Y# - {120171, "z"}, // MA# ( 𝕫 → z ) MATHEMATICAL DOUBLE-STRUCK SMALL Z → LATIN SMALL LETTER Z# - {120172, "A"}, // MA# ( 𝕬 → A ) MATHEMATICAL BOLD FRAKTUR CAPITAL A → LATIN CAPITAL LETTER A# - {120173, "B"}, // MA# ( 𝕭 → B ) MATHEMATICAL BOLD FRAKTUR CAPITAL B → LATIN CAPITAL LETTER B# - {120174, "C"}, // MA# ( 𝕮 → C ) MATHEMATICAL BOLD FRAKTUR CAPITAL C → LATIN CAPITAL LETTER C# - {120175, "D"}, // MA# ( 𝕯 → D ) MATHEMATICAL BOLD FRAKTUR CAPITAL D → LATIN CAPITAL LETTER D# - {120176, "E"}, // MA# ( 𝕰 → E ) MATHEMATICAL BOLD FRAKTUR CAPITAL E → LATIN CAPITAL LETTER E# - {120177, "F"}, // MA# ( 𝕱 → F ) MATHEMATICAL BOLD FRAKTUR CAPITAL F → LATIN CAPITAL LETTER F# - {120178, "G"}, // MA# ( 𝕲 → G ) MATHEMATICAL BOLD FRAKTUR CAPITAL G → LATIN CAPITAL LETTER G# - {120179, "H"}, // MA# ( 𝕳 → H ) MATHEMATICAL BOLD FRAKTUR CAPITAL H → LATIN CAPITAL LETTER H# - {120180, "l"}, // MA# ( 𝕴 → l ) MATHEMATICAL BOLD FRAKTUR CAPITAL I → LATIN SMALL LETTER L# →I→ - {120181, "J"}, // MA# ( 𝕵 → J ) MATHEMATICAL BOLD FRAKTUR CAPITAL J → LATIN CAPITAL LETTER J# - {120182, "K"}, // MA# ( 𝕶 → K ) MATHEMATICAL BOLD FRAKTUR CAPITAL K → LATIN CAPITAL LETTER K# - {120183, "L"}, // MA# ( 𝕷 → L ) MATHEMATICAL BOLD FRAKTUR CAPITAL L → LATIN CAPITAL LETTER L# - {120184, "M"}, // MA# ( 𝕸 → M ) MATHEMATICAL BOLD FRAKTUR CAPITAL M → LATIN CAPITAL LETTER M# - {120185, "N"}, // MA# ( 𝕹 → N ) MATHEMATICAL BOLD FRAKTUR CAPITAL N → LATIN CAPITAL LETTER N# - {120186, "O"}, // MA# ( 𝕺 → O ) MATHEMATICAL BOLD FRAKTUR CAPITAL O → LATIN CAPITAL LETTER O# - {120187, "P"}, // MA# ( 𝕻 → P ) MATHEMATICAL BOLD FRAKTUR CAPITAL P → LATIN CAPITAL LETTER P# - {120188, "Q"}, // MA# ( 𝕼 → Q ) MATHEMATICAL BOLD FRAKTUR CAPITAL Q → LATIN CAPITAL LETTER Q# - {120189, "R"}, // MA# ( 𝕽 → R ) MATHEMATICAL BOLD FRAKTUR CAPITAL R → LATIN CAPITAL LETTER R# - {120190, "S"}, // MA# ( 𝕾 → S ) MATHEMATICAL BOLD FRAKTUR CAPITAL S → LATIN CAPITAL LETTER S# - {120191, "T"}, // MA# ( 𝕿 → T ) MATHEMATICAL BOLD FRAKTUR CAPITAL T → LATIN CAPITAL LETTER T# - {120192, "U"}, // MA# ( 𝖀 → U ) MATHEMATICAL BOLD FRAKTUR CAPITAL U → LATIN CAPITAL LETTER U# - {120193, "V"}, // MA# ( 𝖁 → V ) MATHEMATICAL BOLD FRAKTUR CAPITAL V → LATIN CAPITAL LETTER V# - {120194, "W"}, // MA# ( 𝖂 → W ) MATHEMATICAL BOLD FRAKTUR CAPITAL W → LATIN CAPITAL LETTER W# - {120195, "X"}, // MA# ( 𝖃 → X ) MATHEMATICAL BOLD FRAKTUR CAPITAL X → LATIN CAPITAL LETTER X# - {120196, "Y"}, // MA# ( 𝖄 → Y ) MATHEMATICAL BOLD FRAKTUR CAPITAL Y → LATIN CAPITAL LETTER Y# - {120197, "Z"}, // MA# ( 𝖅 → Z ) MATHEMATICAL BOLD FRAKTUR CAPITAL Z → LATIN CAPITAL LETTER Z# - {120198, "a"}, // MA# ( 𝖆 → a ) MATHEMATICAL BOLD FRAKTUR SMALL A → LATIN SMALL LETTER A# - {120199, "b"}, // MA# ( 𝖇 → b ) MATHEMATICAL BOLD FRAKTUR SMALL B → LATIN SMALL LETTER B# - {120200, "c"}, // MA# ( 𝖈 → c ) MATHEMATICAL BOLD FRAKTUR SMALL C → LATIN SMALL LETTER C# - {120201, "d"}, // MA# ( 𝖉 → d ) MATHEMATICAL BOLD FRAKTUR SMALL D → LATIN SMALL LETTER D# - {120202, "e"}, // MA# ( 𝖊 → e ) MATHEMATICAL BOLD FRAKTUR SMALL E → LATIN SMALL LETTER E# - {120203, "f"}, // MA# ( 𝖋 → f ) MATHEMATICAL BOLD FRAKTUR SMALL F → LATIN SMALL LETTER F# - {120204, "g"}, // MA# ( 𝖌 → g ) MATHEMATICAL BOLD FRAKTUR SMALL G → LATIN SMALL LETTER G# - {120205, "h"}, // MA# ( 𝖍 → h ) MATHEMATICAL BOLD FRAKTUR SMALL H → LATIN SMALL LETTER H# - {120206, "i"}, // MA# ( 𝖎 → i ) MATHEMATICAL BOLD FRAKTUR SMALL I → LATIN SMALL LETTER I# - {120207, "j"}, // MA# ( 𝖏 → j ) MATHEMATICAL BOLD FRAKTUR SMALL J → LATIN SMALL LETTER J# - {120208, "k"}, // MA# ( 𝖐 → k ) MATHEMATICAL BOLD FRAKTUR SMALL K → LATIN SMALL LETTER K# - {120209, "l"}, // MA# ( 𝖑 → l ) MATHEMATICAL BOLD FRAKTUR SMALL L → LATIN SMALL LETTER L# - {120210, "rn"}, // MA# ( 𝖒 → rn ) MATHEMATICAL BOLD FRAKTUR SMALL M → LATIN SMALL LETTER R, LATIN SMALL LETTER N# →m→ - {120211, "n"}, // MA# ( 𝖓 → n ) MATHEMATICAL BOLD FRAKTUR SMALL N → LATIN SMALL LETTER N# - {120212, "o"}, // MA# ( 𝖔 → o ) MATHEMATICAL BOLD FRAKTUR SMALL O → LATIN SMALL LETTER O# - {120213, "p"}, // MA# ( 𝖕 → p ) MATHEMATICAL BOLD FRAKTUR SMALL P → LATIN SMALL LETTER P# - {120214, "q"}, // MA# ( 𝖖 → q ) MATHEMATICAL BOLD FRAKTUR SMALL Q → LATIN SMALL LETTER Q# - {120215, "r"}, // MA# ( 𝖗 → r ) MATHEMATICAL BOLD FRAKTUR SMALL R → LATIN SMALL LETTER R# - {120216, "s"}, // MA# ( 𝖘 → s ) MATHEMATICAL BOLD FRAKTUR SMALL S → LATIN SMALL LETTER S# - {120217, "t"}, // MA# ( 𝖙 → t ) MATHEMATICAL BOLD FRAKTUR SMALL T → LATIN SMALL LETTER T# - {120218, "u"}, // MA# ( 𝖚 → u ) MATHEMATICAL BOLD FRAKTUR SMALL U → LATIN SMALL LETTER U# - {120219, "v"}, // MA# ( 𝖛 → v ) MATHEMATICAL BOLD FRAKTUR SMALL V → LATIN SMALL LETTER V# - {120220, "w"}, // MA# ( 𝖜 → w ) MATHEMATICAL BOLD FRAKTUR SMALL W → LATIN SMALL LETTER W# - {120221, "x"}, // MA# ( 𝖝 → x ) MATHEMATICAL BOLD FRAKTUR SMALL X → LATIN SMALL LETTER X# - {120222, "y"}, // MA# ( 𝖞 → y ) MATHEMATICAL BOLD FRAKTUR SMALL Y → LATIN SMALL LETTER Y# - {120223, "z"}, // MA# ( 𝖟 → z ) MATHEMATICAL BOLD FRAKTUR SMALL Z → LATIN SMALL LETTER Z# - {120224, "A"}, // MA# ( 𝖠 → A ) MATHEMATICAL SANS-SERIF CAPITAL A → LATIN CAPITAL LETTER A# - {120225, "B"}, // MA# ( 𝖡 → B ) MATHEMATICAL SANS-SERIF CAPITAL B → LATIN CAPITAL LETTER B# - {120226, "C"}, // MA# ( 𝖢 → C ) MATHEMATICAL SANS-SERIF CAPITAL C → LATIN CAPITAL LETTER C# - {120227, "D"}, // MA# ( 𝖣 → D ) MATHEMATICAL SANS-SERIF CAPITAL D → LATIN CAPITAL LETTER D# - {120228, "E"}, // MA# ( 𝖤 → E ) MATHEMATICAL SANS-SERIF CAPITAL E → LATIN CAPITAL LETTER E# - {120229, "F"}, // MA# ( 𝖥 → F ) MATHEMATICAL SANS-SERIF CAPITAL F → LATIN CAPITAL LETTER F# - {120230, "G"}, // MA# ( 𝖦 → G ) MATHEMATICAL SANS-SERIF CAPITAL G → LATIN CAPITAL LETTER G# - {120231, "H"}, // MA# ( 𝖧 → H ) MATHEMATICAL SANS-SERIF CAPITAL H → LATIN CAPITAL LETTER H# - {120232, "l"}, // MA# ( 𝖨 → l ) MATHEMATICAL SANS-SERIF CAPITAL I → LATIN SMALL LETTER L# →I→ - {120233, "J"}, // MA# ( 𝖩 → J ) MATHEMATICAL SANS-SERIF CAPITAL J → LATIN CAPITAL LETTER J# - {120234, "K"}, // MA# ( 𝖪 → K ) MATHEMATICAL SANS-SERIF CAPITAL K → LATIN CAPITAL LETTER K# - {120235, "L"}, // MA# ( 𝖫 → L ) MATHEMATICAL SANS-SERIF CAPITAL L → LATIN CAPITAL LETTER L# - {120236, "M"}, // MA# ( 𝖬 → M ) MATHEMATICAL SANS-SERIF CAPITAL M → LATIN CAPITAL LETTER M# - {120237, "N"}, // MA# ( 𝖭 → N ) MATHEMATICAL SANS-SERIF CAPITAL N → LATIN CAPITAL LETTER N# - {120238, "O"}, // MA# ( 𝖮 → O ) MATHEMATICAL SANS-SERIF CAPITAL O → LATIN CAPITAL LETTER O# - {120239, "P"}, // MA# ( 𝖯 → P ) MATHEMATICAL SANS-SERIF CAPITAL P → LATIN CAPITAL LETTER P# - {120240, "Q"}, // MA# ( 𝖰 → Q ) MATHEMATICAL SANS-SERIF CAPITAL Q → LATIN CAPITAL LETTER Q# - {120241, "R"}, // MA# ( 𝖱 → R ) MATHEMATICAL SANS-SERIF CAPITAL R → LATIN CAPITAL LETTER R# - {120242, "S"}, // MA# ( 𝖲 → S ) MATHEMATICAL SANS-SERIF CAPITAL S → LATIN CAPITAL LETTER S# - {120243, "T"}, // MA# ( 𝖳 → T ) MATHEMATICAL SANS-SERIF CAPITAL T → LATIN CAPITAL LETTER T# - {120244, "U"}, // MA# ( 𝖴 → U ) MATHEMATICAL SANS-SERIF CAPITAL U → LATIN CAPITAL LETTER U# - {120245, "V"}, // MA# ( 𝖵 → V ) MATHEMATICAL SANS-SERIF CAPITAL V → LATIN CAPITAL LETTER V# - {120246, "W"}, // MA# ( 𝖶 → W ) MATHEMATICAL SANS-SERIF CAPITAL W → LATIN CAPITAL LETTER W# - {120247, "X"}, // MA# ( 𝖷 → X ) MATHEMATICAL SANS-SERIF CAPITAL X → LATIN CAPITAL LETTER X# - {120248, "Y"}, // MA# ( 𝖸 → Y ) MATHEMATICAL SANS-SERIF CAPITAL Y → LATIN CAPITAL LETTER Y# - {120249, "Z"}, // MA# ( 𝖹 → Z ) MATHEMATICAL SANS-SERIF CAPITAL Z → LATIN CAPITAL LETTER Z# - {120250, "a"}, // MA# ( 𝖺 → a ) MATHEMATICAL SANS-SERIF SMALL A → LATIN SMALL LETTER A# - {120251, "b"}, // MA# ( 𝖻 → b ) MATHEMATICAL SANS-SERIF SMALL B → LATIN SMALL LETTER B# - {120252, "c"}, // MA# ( 𝖼 → c ) MATHEMATICAL SANS-SERIF SMALL C → LATIN SMALL LETTER C# - {120253, "d"}, // MA# ( 𝖽 → d ) MATHEMATICAL SANS-SERIF SMALL D → LATIN SMALL LETTER D# - {120254, "e"}, // MA# ( 𝖾 → e ) MATHEMATICAL SANS-SERIF SMALL E → LATIN SMALL LETTER E# - {120255, "f"}, // MA# ( 𝖿 → f ) MATHEMATICAL SANS-SERIF SMALL F → LATIN SMALL LETTER F# - {120256, "g"}, // MA# ( 𝗀 → g ) MATHEMATICAL SANS-SERIF SMALL G → LATIN SMALL LETTER G# - {120257, "h"}, // MA# ( 𝗁 → h ) MATHEMATICAL SANS-SERIF SMALL H → LATIN SMALL LETTER H# - {120258, "i"}, // MA# ( 𝗂 → i ) MATHEMATICAL SANS-SERIF SMALL I → LATIN SMALL LETTER I# - {120259, "j"}, // MA# ( 𝗃 → j ) MATHEMATICAL SANS-SERIF SMALL J → LATIN SMALL LETTER J# - {120260, "k"}, // MA# ( 𝗄 → k ) MATHEMATICAL SANS-SERIF SMALL K → LATIN SMALL LETTER K# - {120261, "l"}, // MA# ( 𝗅 → l ) MATHEMATICAL SANS-SERIF SMALL L → LATIN SMALL LETTER L# - {120262, "rn"}, // MA# ( 𝗆 → rn ) MATHEMATICAL SANS-SERIF SMALL M → LATIN SMALL LETTER R, LATIN SMALL LETTER N# →m→ - {120263, "n"}, // MA# ( 𝗇 → n ) MATHEMATICAL SANS-SERIF SMALL N → LATIN SMALL LETTER N# - {120264, "o"}, // MA# ( 𝗈 → o ) MATHEMATICAL SANS-SERIF SMALL O → LATIN SMALL LETTER O# - {120265, "p"}, // MA# ( 𝗉 → p ) MATHEMATICAL SANS-SERIF SMALL P → LATIN SMALL LETTER P# - {120266, "q"}, // MA# ( 𝗊 → q ) MATHEMATICAL SANS-SERIF SMALL Q → LATIN SMALL LETTER Q# - {120267, "r"}, // MA# ( 𝗋 → r ) MATHEMATICAL SANS-SERIF SMALL R → LATIN SMALL LETTER R# - {120268, "s"}, // MA# ( 𝗌 → s ) MATHEMATICAL SANS-SERIF SMALL S → LATIN SMALL LETTER S# - {120269, "t"}, // MA# ( 𝗍 → t ) MATHEMATICAL SANS-SERIF SMALL T → LATIN SMALL LETTER T# - {120270, "u"}, // MA# ( 𝗎 → u ) MATHEMATICAL SANS-SERIF SMALL U → LATIN SMALL LETTER U# - {120271, "v"}, // MA# ( 𝗏 → v ) MATHEMATICAL SANS-SERIF SMALL V → LATIN SMALL LETTER V# - {120272, "w"}, // MA# ( 𝗐 → w ) MATHEMATICAL SANS-SERIF SMALL W → LATIN SMALL LETTER W# - {120273, "x"}, // MA# ( 𝗑 → x ) MATHEMATICAL SANS-SERIF SMALL X → LATIN SMALL LETTER X# - {120274, "y"}, // MA# ( 𝗒 → y ) MATHEMATICAL SANS-SERIF SMALL Y → LATIN SMALL LETTER Y# - {120275, "z"}, // MA# ( 𝗓 → z ) MATHEMATICAL SANS-SERIF SMALL Z → LATIN SMALL LETTER Z# - {120276, "A"}, // MA# ( 𝗔 → A ) MATHEMATICAL SANS-SERIF BOLD CAPITAL A → LATIN CAPITAL LETTER A# - {120277, "B"}, // MA# ( 𝗕 → B ) MATHEMATICAL SANS-SERIF BOLD CAPITAL B → LATIN CAPITAL LETTER B# - {120278, "C"}, // MA# ( 𝗖 → C ) MATHEMATICAL SANS-SERIF BOLD CAPITAL C → LATIN CAPITAL LETTER C# - {120279, "D"}, // MA# ( 𝗗 → D ) MATHEMATICAL SANS-SERIF BOLD CAPITAL D → LATIN CAPITAL LETTER D# - {120280, "E"}, // MA# ( 𝗘 → E ) MATHEMATICAL SANS-SERIF BOLD CAPITAL E → LATIN CAPITAL LETTER E# - {120281, "F"}, // MA# ( 𝗙 → F ) MATHEMATICAL SANS-SERIF BOLD CAPITAL F → LATIN CAPITAL LETTER F# - {120282, "G"}, // MA# ( 𝗚 → G ) MATHEMATICAL SANS-SERIF BOLD CAPITAL G → LATIN CAPITAL LETTER G# - {120283, "H"}, // MA# ( 𝗛 → H ) MATHEMATICAL SANS-SERIF BOLD CAPITAL H → LATIN CAPITAL LETTER H# - {120284, "l"}, // MA# ( 𝗜 → l ) MATHEMATICAL SANS-SERIF BOLD CAPITAL I → LATIN SMALL LETTER L# →I→ - {120285, "J"}, // MA# ( 𝗝 → J ) MATHEMATICAL SANS-SERIF BOLD CAPITAL J → LATIN CAPITAL LETTER J# - {120286, "K"}, // MA# ( 𝗞 → K ) MATHEMATICAL SANS-SERIF BOLD CAPITAL K → LATIN CAPITAL LETTER K# - {120287, "L"}, // MA# ( 𝗟 → L ) MATHEMATICAL SANS-SERIF BOLD CAPITAL L → LATIN CAPITAL LETTER L# - {120288, "M"}, // MA# ( 𝗠 → M ) MATHEMATICAL SANS-SERIF BOLD CAPITAL M → LATIN CAPITAL LETTER M# - {120289, "N"}, // MA# ( 𝗡 → N ) MATHEMATICAL SANS-SERIF BOLD CAPITAL N → LATIN CAPITAL LETTER N# - {120290, "O"}, // MA# ( 𝗢 → O ) MATHEMATICAL SANS-SERIF BOLD CAPITAL O → LATIN CAPITAL LETTER O# - {120291, "P"}, // MA# ( 𝗣 → P ) MATHEMATICAL SANS-SERIF BOLD CAPITAL P → LATIN CAPITAL LETTER P# - {120292, "Q"}, // MA# ( 𝗤 → Q ) MATHEMATICAL SANS-SERIF BOLD CAPITAL Q → LATIN CAPITAL LETTER Q# - {120293, "R"}, // MA# ( 𝗥 → R ) MATHEMATICAL SANS-SERIF BOLD CAPITAL R → LATIN CAPITAL LETTER R# - {120294, "S"}, // MA# ( 𝗦 → S ) MATHEMATICAL SANS-SERIF BOLD CAPITAL S → LATIN CAPITAL LETTER S# - {120295, "T"}, // MA# ( 𝗧 → T ) MATHEMATICAL SANS-SERIF BOLD CAPITAL T → LATIN CAPITAL LETTER T# - {120296, "U"}, // MA# ( 𝗨 → U ) MATHEMATICAL SANS-SERIF BOLD CAPITAL U → LATIN CAPITAL LETTER U# - {120297, "V"}, // MA# ( 𝗩 → V ) MATHEMATICAL SANS-SERIF BOLD CAPITAL V → LATIN CAPITAL LETTER V# - {120298, "W"}, // MA# ( 𝗪 → W ) MATHEMATICAL SANS-SERIF BOLD CAPITAL W → LATIN CAPITAL LETTER W# - {120299, "X"}, // MA# ( 𝗫 → X ) MATHEMATICAL SANS-SERIF BOLD CAPITAL X → LATIN CAPITAL LETTER X# - {120300, "Y"}, // MA# ( 𝗬 → Y ) MATHEMATICAL SANS-SERIF BOLD CAPITAL Y → LATIN CAPITAL LETTER Y# - {120301, "Z"}, // MA# ( 𝗭 → Z ) MATHEMATICAL SANS-SERIF BOLD CAPITAL Z → LATIN CAPITAL LETTER Z# - {120302, "a"}, // MA# ( 𝗮 → a ) MATHEMATICAL SANS-SERIF BOLD SMALL A → LATIN SMALL LETTER A# - {120303, "b"}, // MA# ( 𝗯 → b ) MATHEMATICAL SANS-SERIF BOLD SMALL B → LATIN SMALL LETTER B# - {120304, "c"}, // MA# ( 𝗰 → c ) MATHEMATICAL SANS-SERIF BOLD SMALL C → LATIN SMALL LETTER C# - {120305, "d"}, // MA# ( 𝗱 → d ) MATHEMATICAL SANS-SERIF BOLD SMALL D → LATIN SMALL LETTER D# - {120306, "e"}, // MA# ( 𝗲 → e ) MATHEMATICAL SANS-SERIF BOLD SMALL E → LATIN SMALL LETTER E# - {120307, "f"}, // MA# ( 𝗳 → f ) MATHEMATICAL SANS-SERIF BOLD SMALL F → LATIN SMALL LETTER F# - {120308, "g"}, // MA# ( 𝗴 → g ) MATHEMATICAL SANS-SERIF BOLD SMALL G → LATIN SMALL LETTER G# - {120309, "h"}, // MA# ( 𝗵 → h ) MATHEMATICAL SANS-SERIF BOLD SMALL H → LATIN SMALL LETTER H# - {120310, "i"}, // MA# ( 𝗶 → i ) MATHEMATICAL SANS-SERIF BOLD SMALL I → LATIN SMALL LETTER I# - {120311, "j"}, // MA# ( 𝗷 → j ) MATHEMATICAL SANS-SERIF BOLD SMALL J → LATIN SMALL LETTER J# - {120312, "k"}, // MA# ( 𝗸 → k ) MATHEMATICAL SANS-SERIF BOLD SMALL K → LATIN SMALL LETTER K# - {120313, "l"}, // MA# ( 𝗹 → l ) MATHEMATICAL SANS-SERIF BOLD SMALL L → LATIN SMALL LETTER L# - {120314, "rn"}, // MA# ( 𝗺 → rn ) MATHEMATICAL SANS-SERIF BOLD SMALL M → LATIN SMALL LETTER R, LATIN SMALL LETTER N# →m→ - {120315, "n"}, // MA# ( 𝗻 → n ) MATHEMATICAL SANS-SERIF BOLD SMALL N → LATIN SMALL LETTER N# - {120316, "o"}, // MA# ( 𝗼 → o ) MATHEMATICAL SANS-SERIF BOLD SMALL O → LATIN SMALL LETTER O# - {120317, "p"}, // MA# ( 𝗽 → p ) MATHEMATICAL SANS-SERIF BOLD SMALL P → LATIN SMALL LETTER P# - {120318, "q"}, // MA# ( 𝗾 → q ) MATHEMATICAL SANS-SERIF BOLD SMALL Q → LATIN SMALL LETTER Q# - {120319, "r"}, // MA# ( 𝗿 → r ) MATHEMATICAL SANS-SERIF BOLD SMALL R → LATIN SMALL LETTER R# - {120320, "s"}, // MA# ( 𝘀 → s ) MATHEMATICAL SANS-SERIF BOLD SMALL S → LATIN SMALL LETTER S# - {120321, "t"}, // MA# ( 𝘁 → t ) MATHEMATICAL SANS-SERIF BOLD SMALL T → LATIN SMALL LETTER T# - {120322, "u"}, // MA# ( 𝘂 → u ) MATHEMATICAL SANS-SERIF BOLD SMALL U → LATIN SMALL LETTER U# - {120323, "v"}, // MA# ( 𝘃 → v ) MATHEMATICAL SANS-SERIF BOLD SMALL V → LATIN SMALL LETTER V# - {120324, "w"}, // MA# ( 𝘄 → w ) MATHEMATICAL SANS-SERIF BOLD SMALL W → LATIN SMALL LETTER W# - {120325, "x"}, // MA# ( 𝘅 → x ) MATHEMATICAL SANS-SERIF BOLD SMALL X → LATIN SMALL LETTER X# - {120326, "y"}, // MA# ( 𝘆 → y ) MATHEMATICAL SANS-SERIF BOLD SMALL Y → LATIN SMALL LETTER Y# - {120327, "z"}, // MA# ( 𝘇 → z ) MATHEMATICAL SANS-SERIF BOLD SMALL Z → LATIN SMALL LETTER Z# - {120328, "A"}, // MA# ( 𝘈 → A ) MATHEMATICAL SANS-SERIF ITALIC CAPITAL A → LATIN CAPITAL LETTER A# - {120329, "B"}, // MA# ( 𝘉 → B ) MATHEMATICAL SANS-SERIF ITALIC CAPITAL B → LATIN CAPITAL LETTER B# - {120330, "C"}, // MA# ( 𝘊 → C ) MATHEMATICAL SANS-SERIF ITALIC CAPITAL C → LATIN CAPITAL LETTER C# - {120331, "D"}, // MA# ( 𝘋 → D ) MATHEMATICAL SANS-SERIF ITALIC CAPITAL D → LATIN CAPITAL LETTER D# - {120332, "E"}, // MA# ( 𝘌 → E ) MATHEMATICAL SANS-SERIF ITALIC CAPITAL E → LATIN CAPITAL LETTER E# - {120333, "F"}, // MA# ( 𝘍 → F ) MATHEMATICAL SANS-SERIF ITALIC CAPITAL F → LATIN CAPITAL LETTER F# - {120334, "G"}, // MA# ( 𝘎 → G ) MATHEMATICAL SANS-SERIF ITALIC CAPITAL G → LATIN CAPITAL LETTER G# - {120335, "H"}, // MA# ( 𝘏 → H ) MATHEMATICAL SANS-SERIF ITALIC CAPITAL H → LATIN CAPITAL LETTER H# - {120336, "l"}, // MA# ( 𝘐 → l ) MATHEMATICAL SANS-SERIF ITALIC CAPITAL I → LATIN SMALL LETTER L# →I→ - {120337, "J"}, // MA# ( 𝘑 → J ) MATHEMATICAL SANS-SERIF ITALIC CAPITAL J → LATIN CAPITAL LETTER J# - {120338, "K"}, // MA# ( 𝘒 → K ) MATHEMATICAL SANS-SERIF ITALIC CAPITAL K → LATIN CAPITAL LETTER K# - {120339, "L"}, // MA# ( 𝘓 → L ) MATHEMATICAL SANS-SERIF ITALIC CAPITAL L → LATIN CAPITAL LETTER L# - {120340, "M"}, // MA# ( 𝘔 → M ) MATHEMATICAL SANS-SERIF ITALIC CAPITAL M → LATIN CAPITAL LETTER M# - {120341, "N"}, // MA# ( 𝘕 → N ) MATHEMATICAL SANS-SERIF ITALIC CAPITAL N → LATIN CAPITAL LETTER N# - {120342, "O"}, // MA# ( 𝘖 → O ) MATHEMATICAL SANS-SERIF ITALIC CAPITAL O → LATIN CAPITAL LETTER O# - {120343, "P"}, // MA# ( 𝘗 → P ) MATHEMATICAL SANS-SERIF ITALIC CAPITAL P → LATIN CAPITAL LETTER P# - {120344, "Q"}, // MA# ( 𝘘 → Q ) MATHEMATICAL SANS-SERIF ITALIC CAPITAL Q → LATIN CAPITAL LETTER Q# - {120345, "R"}, // MA# ( 𝘙 → R ) MATHEMATICAL SANS-SERIF ITALIC CAPITAL R → LATIN CAPITAL LETTER R# - {120346, "S"}, // MA# ( 𝘚 → S ) MATHEMATICAL SANS-SERIF ITALIC CAPITAL S → LATIN CAPITAL LETTER S# - {120347, "T"}, // MA# ( 𝘛 → T ) MATHEMATICAL SANS-SERIF ITALIC CAPITAL T → LATIN CAPITAL LETTER T# - {120348, "U"}, // MA# ( 𝘜 → U ) MATHEMATICAL SANS-SERIF ITALIC CAPITAL U → LATIN CAPITAL LETTER U# - {120349, "V"}, // MA# ( 𝘝 → V ) MATHEMATICAL SANS-SERIF ITALIC CAPITAL V → LATIN CAPITAL LETTER V# - {120350, "W"}, // MA# ( 𝘞 → W ) MATHEMATICAL SANS-SERIF ITALIC CAPITAL W → LATIN CAPITAL LETTER W# - {120351, "X"}, // MA# ( 𝘟 → X ) MATHEMATICAL SANS-SERIF ITALIC CAPITAL X → LATIN CAPITAL LETTER X# - {120352, "Y"}, // MA# ( 𝘠 → Y ) MATHEMATICAL SANS-SERIF ITALIC CAPITAL Y → LATIN CAPITAL LETTER Y# - {120353, "Z"}, // MA# ( 𝘡 → Z ) MATHEMATICAL SANS-SERIF ITALIC CAPITAL Z → LATIN CAPITAL LETTER Z# - {120354, "a"}, // MA# ( 𝘢 → a ) MATHEMATICAL SANS-SERIF ITALIC SMALL A → LATIN SMALL LETTER A# - {120355, "b"}, // MA# ( 𝘣 → b ) MATHEMATICAL SANS-SERIF ITALIC SMALL B → LATIN SMALL LETTER B# - {120356, "c"}, // MA# ( 𝘤 → c ) MATHEMATICAL SANS-SERIF ITALIC SMALL C → LATIN SMALL LETTER C# - {120357, "d"}, // MA# ( 𝘥 → d ) MATHEMATICAL SANS-SERIF ITALIC SMALL D → LATIN SMALL LETTER D# - {120358, "e"}, // MA# ( 𝘦 → e ) MATHEMATICAL SANS-SERIF ITALIC SMALL E → LATIN SMALL LETTER E# - {120359, "f"}, // MA# ( 𝘧 → f ) MATHEMATICAL SANS-SERIF ITALIC SMALL F → LATIN SMALL LETTER F# - {120360, "g"}, // MA# ( 𝘨 → g ) MATHEMATICAL SANS-SERIF ITALIC SMALL G → LATIN SMALL LETTER G# - {120361, "h"}, // MA# ( 𝘩 → h ) MATHEMATICAL SANS-SERIF ITALIC SMALL H → LATIN SMALL LETTER H# - {120362, "i"}, // MA# ( 𝘪 → i ) MATHEMATICAL SANS-SERIF ITALIC SMALL I → LATIN SMALL LETTER I# - {120363, "j"}, // MA# ( 𝘫 → j ) MATHEMATICAL SANS-SERIF ITALIC SMALL J → LATIN SMALL LETTER J# - {120364, "k"}, // MA# ( 𝘬 → k ) MATHEMATICAL SANS-SERIF ITALIC SMALL K → LATIN SMALL LETTER K# - {120365, "l"}, // MA# ( 𝘭 → l ) MATHEMATICAL SANS-SERIF ITALIC SMALL L → LATIN SMALL LETTER L# - {120366, "rn"}, // MA# ( 𝘮 → rn ) MATHEMATICAL SANS-SERIF ITALIC SMALL M → LATIN SMALL LETTER R, LATIN SMALL LETTER N# →m→ - {120367, "n"}, // MA# ( 𝘯 → n ) MATHEMATICAL SANS-SERIF ITALIC SMALL N → LATIN SMALL LETTER N# - {120368, "o"}, // MA# ( 𝘰 → o ) MATHEMATICAL SANS-SERIF ITALIC SMALL O → LATIN SMALL LETTER O# - {120369, "p"}, // MA# ( 𝘱 → p ) MATHEMATICAL SANS-SERIF ITALIC SMALL P → LATIN SMALL LETTER P# - {120370, "q"}, // MA# ( 𝘲 → q ) MATHEMATICAL SANS-SERIF ITALIC SMALL Q → LATIN SMALL LETTER Q# - {120371, "r"}, // MA# ( 𝘳 → r ) MATHEMATICAL SANS-SERIF ITALIC SMALL R → LATIN SMALL LETTER R# - {120372, "s"}, // MA# ( 𝘴 → s ) MATHEMATICAL SANS-SERIF ITALIC SMALL S → LATIN SMALL LETTER S# - {120373, "t"}, // MA# ( 𝘵 → t ) MATHEMATICAL SANS-SERIF ITALIC SMALL T → LATIN SMALL LETTER T# - {120374, "u"}, // MA# ( 𝘶 → u ) MATHEMATICAL SANS-SERIF ITALIC SMALL U → LATIN SMALL LETTER U# - {120375, "v"}, // MA# ( 𝘷 → v ) MATHEMATICAL SANS-SERIF ITALIC SMALL V → LATIN SMALL LETTER V# - {120376, "w"}, // MA# ( 𝘸 → w ) MATHEMATICAL SANS-SERIF ITALIC SMALL W → LATIN SMALL LETTER W# - {120377, "x"}, // MA# ( 𝘹 → x ) MATHEMATICAL SANS-SERIF ITALIC SMALL X → LATIN SMALL LETTER X# - {120378, "y"}, // MA# ( 𝘺 → y ) MATHEMATICAL SANS-SERIF ITALIC SMALL Y → LATIN SMALL LETTER Y# - {120379, "z"}, // MA# ( 𝘻 → z ) MATHEMATICAL SANS-SERIF ITALIC SMALL Z → LATIN SMALL LETTER Z# - {120380, "A"}, // MA# ( 𝘼 → A ) MATHEMATICAL SANS-SERIF BOLD ITALIC CAPITAL A → LATIN CAPITAL LETTER A# - {120381, "B"}, // MA# ( 𝘽 → B ) MATHEMATICAL SANS-SERIF BOLD ITALIC CAPITAL B → LATIN CAPITAL LETTER B# - {120382, "C"}, // MA# ( 𝘾 → C ) MATHEMATICAL SANS-SERIF BOLD ITALIC CAPITAL C → LATIN CAPITAL LETTER C# - {120383, "D"}, // MA# ( 𝘿 → D ) MATHEMATICAL SANS-SERIF BOLD ITALIC CAPITAL D → LATIN CAPITAL LETTER D# - {120384, "E"}, // MA# ( 𝙀 → E ) MATHEMATICAL SANS-SERIF BOLD ITALIC CAPITAL E → LATIN CAPITAL LETTER E# - {120385, "F"}, // MA# ( 𝙁 → F ) MATHEMATICAL SANS-SERIF BOLD ITALIC CAPITAL F → LATIN CAPITAL LETTER F# - {120386, "G"}, // MA# ( 𝙂 → G ) MATHEMATICAL SANS-SERIF BOLD ITALIC CAPITAL G → LATIN CAPITAL LETTER G# - {120387, "H"}, // MA# ( 𝙃 → H ) MATHEMATICAL SANS-SERIF BOLD ITALIC CAPITAL H → LATIN CAPITAL LETTER H# - {120388, "l"}, // MA# ( 𝙄 → l ) MATHEMATICAL SANS-SERIF BOLD ITALIC CAPITAL I → LATIN SMALL LETTER L# →I→ - {120389, "J"}, // MA# ( 𝙅 → J ) MATHEMATICAL SANS-SERIF BOLD ITALIC CAPITAL J → LATIN CAPITAL LETTER J# - {120390, "K"}, // MA# ( 𝙆 → K ) MATHEMATICAL SANS-SERIF BOLD ITALIC CAPITAL K → LATIN CAPITAL LETTER K# - {120391, "L"}, // MA# ( 𝙇 → L ) MATHEMATICAL SANS-SERIF BOLD ITALIC CAPITAL L → LATIN CAPITAL LETTER L# - {120392, "M"}, // MA# ( 𝙈 → M ) MATHEMATICAL SANS-SERIF BOLD ITALIC CAPITAL M → LATIN CAPITAL LETTER M# - {120393, "N"}, // MA# ( 𝙉 → N ) MATHEMATICAL SANS-SERIF BOLD ITALIC CAPITAL N → LATIN CAPITAL LETTER N# - {120394, "O"}, // MA# ( 𝙊 → O ) MATHEMATICAL SANS-SERIF BOLD ITALIC CAPITAL O → LATIN CAPITAL LETTER O# - {120395, "P"}, // MA# ( 𝙋 → P ) MATHEMATICAL SANS-SERIF BOLD ITALIC CAPITAL P → LATIN CAPITAL LETTER P# - {120396, "Q"}, // MA# ( 𝙌 → Q ) MATHEMATICAL SANS-SERIF BOLD ITALIC CAPITAL Q → LATIN CAPITAL LETTER Q# - {120397, "R"}, // MA# ( 𝙍 → R ) MATHEMATICAL SANS-SERIF BOLD ITALIC CAPITAL R → LATIN CAPITAL LETTER R# - {120398, "S"}, // MA# ( 𝙎 → S ) MATHEMATICAL SANS-SERIF BOLD ITALIC CAPITAL S → LATIN CAPITAL LETTER S# - {120399, "T"}, // MA# ( 𝙏 → T ) MATHEMATICAL SANS-SERIF BOLD ITALIC CAPITAL T → LATIN CAPITAL LETTER T# - {120400, "U"}, // MA# ( 𝙐 → U ) MATHEMATICAL SANS-SERIF BOLD ITALIC CAPITAL U → LATIN CAPITAL LETTER U# - {120401, "V"}, // MA# ( 𝙑 → V ) MATHEMATICAL SANS-SERIF BOLD ITALIC CAPITAL V → LATIN CAPITAL LETTER V# - {120402, "W"}, // MA# ( 𝙒 → W ) MATHEMATICAL SANS-SERIF BOLD ITALIC CAPITAL W → LATIN CAPITAL LETTER W# - {120403, "X"}, // MA# ( 𝙓 → X ) MATHEMATICAL SANS-SERIF BOLD ITALIC CAPITAL X → LATIN CAPITAL LETTER X# - {120404, "Y"}, // MA# ( 𝙔 → Y ) MATHEMATICAL SANS-SERIF BOLD ITALIC CAPITAL Y → LATIN CAPITAL LETTER Y# - {120405, "Z"}, // MA# ( 𝙕 → Z ) MATHEMATICAL SANS-SERIF BOLD ITALIC CAPITAL Z → LATIN CAPITAL LETTER Z# - {120406, "a"}, // MA# ( 𝙖 → a ) MATHEMATICAL SANS-SERIF BOLD ITALIC SMALL A → LATIN SMALL LETTER A# - {120407, "b"}, // MA# ( 𝙗 → b ) MATHEMATICAL SANS-SERIF BOLD ITALIC SMALL B → LATIN SMALL LETTER B# - {120408, "c"}, // MA# ( 𝙘 → c ) MATHEMATICAL SANS-SERIF BOLD ITALIC SMALL C → LATIN SMALL LETTER C# - {120409, "d"}, // MA# ( 𝙙 → d ) MATHEMATICAL SANS-SERIF BOLD ITALIC SMALL D → LATIN SMALL LETTER D# - {120410, "e"}, // MA# ( 𝙚 → e ) MATHEMATICAL SANS-SERIF BOLD ITALIC SMALL E → LATIN SMALL LETTER E# - {120411, "f"}, // MA# ( 𝙛 → f ) MATHEMATICAL SANS-SERIF BOLD ITALIC SMALL F → LATIN SMALL LETTER F# - {120412, "g"}, // MA# ( 𝙜 → g ) MATHEMATICAL SANS-SERIF BOLD ITALIC SMALL G → LATIN SMALL LETTER G# - {120413, "h"}, // MA# ( 𝙝 → h ) MATHEMATICAL SANS-SERIF BOLD ITALIC SMALL H → LATIN SMALL LETTER H# - {120414, "i"}, // MA# ( 𝙞 → i ) MATHEMATICAL SANS-SERIF BOLD ITALIC SMALL I → LATIN SMALL LETTER I# - {120415, "j"}, // MA# ( 𝙟 → j ) MATHEMATICAL SANS-SERIF BOLD ITALIC SMALL J → LATIN SMALL LETTER J# - {120416, "k"}, // MA# ( 𝙠 → k ) MATHEMATICAL SANS-SERIF BOLD ITALIC SMALL K → LATIN SMALL LETTER K# - {120417, "l"}, // MA# ( 𝙡 → l ) MATHEMATICAL SANS-SERIF BOLD ITALIC SMALL L → LATIN SMALL LETTER L# - {120418, "rn"}, // MA# ( 𝙢 → rn ) MATHEMATICAL SANS-SERIF BOLD ITALIC SMALL M → LATIN SMALL LETTER R, LATIN SMALL LETTER N# →m→ - {120419, "n"}, // MA# ( 𝙣 → n ) MATHEMATICAL SANS-SERIF BOLD ITALIC SMALL N → LATIN SMALL LETTER N# - {120420, "o"}, // MA# ( 𝙤 → o ) MATHEMATICAL SANS-SERIF BOLD ITALIC SMALL O → LATIN SMALL LETTER O# - {120421, "p"}, // MA# ( 𝙥 → p ) MATHEMATICAL SANS-SERIF BOLD ITALIC SMALL P → LATIN SMALL LETTER P# - {120422, "q"}, // MA# ( 𝙦 → q ) MATHEMATICAL SANS-SERIF BOLD ITALIC SMALL Q → LATIN SMALL LETTER Q# - {120423, "r"}, // MA# ( 𝙧 → r ) MATHEMATICAL SANS-SERIF BOLD ITALIC SMALL R → LATIN SMALL LETTER R# - {120424, "s"}, // MA# ( 𝙨 → s ) MATHEMATICAL SANS-SERIF BOLD ITALIC SMALL S → LATIN SMALL LETTER S# - {120425, "t"}, // MA# ( 𝙩 → t ) MATHEMATICAL SANS-SERIF BOLD ITALIC SMALL T → LATIN SMALL LETTER T# - {120426, "u"}, // MA# ( 𝙪 → u ) MATHEMATICAL SANS-SERIF BOLD ITALIC SMALL U → LATIN SMALL LETTER U# - {120427, "v"}, // MA# ( 𝙫 → v ) MATHEMATICAL SANS-SERIF BOLD ITALIC SMALL V → LATIN SMALL LETTER V# - {120428, "w"}, // MA# ( 𝙬 → w ) MATHEMATICAL SANS-SERIF BOLD ITALIC SMALL W → LATIN SMALL LETTER W# - {120429, "x"}, // MA# ( 𝙭 → x ) MATHEMATICAL SANS-SERIF BOLD ITALIC SMALL X → LATIN SMALL LETTER X# - {120430, "y"}, // MA# ( 𝙮 → y ) MATHEMATICAL SANS-SERIF BOLD ITALIC SMALL Y → LATIN SMALL LETTER Y# - {120431, "z"}, // MA# ( 𝙯 → z ) MATHEMATICAL SANS-SERIF BOLD ITALIC SMALL Z → LATIN SMALL LETTER Z# - {120432, "A"}, // MA# ( 𝙰 → A ) MATHEMATICAL MONOSPACE CAPITAL A → LATIN CAPITAL LETTER A# - {120433, "B"}, // MA# ( 𝙱 → B ) MATHEMATICAL MONOSPACE CAPITAL B → LATIN CAPITAL LETTER B# - {120434, "C"}, // MA# ( 𝙲 → C ) MATHEMATICAL MONOSPACE CAPITAL C → LATIN CAPITAL LETTER C# - {120435, "D"}, // MA# ( 𝙳 → D ) MATHEMATICAL MONOSPACE CAPITAL D → LATIN CAPITAL LETTER D# - {120436, "E"}, // MA# ( 𝙴 → E ) MATHEMATICAL MONOSPACE CAPITAL E → LATIN CAPITAL LETTER E# - {120437, "F"}, // MA# ( 𝙵 → F ) MATHEMATICAL MONOSPACE CAPITAL F → LATIN CAPITAL LETTER F# - {120438, "G"}, // MA# ( 𝙶 → G ) MATHEMATICAL MONOSPACE CAPITAL G → LATIN CAPITAL LETTER G# - {120439, "H"}, // MA# ( 𝙷 → H ) MATHEMATICAL MONOSPACE CAPITAL H → LATIN CAPITAL LETTER H# - {120440, "l"}, // MA# ( 𝙸 → l ) MATHEMATICAL MONOSPACE CAPITAL I → LATIN SMALL LETTER L# →I→ - {120441, "J"}, // MA# ( 𝙹 → J ) MATHEMATICAL MONOSPACE CAPITAL J → LATIN CAPITAL LETTER J# - {120442, "K"}, // MA# ( 𝙺 → K ) MATHEMATICAL MONOSPACE CAPITAL K → LATIN CAPITAL LETTER K# - {120443, "L"}, // MA# ( 𝙻 → L ) MATHEMATICAL MONOSPACE CAPITAL L → LATIN CAPITAL LETTER L# - {120444, "M"}, // MA# ( 𝙼 → M ) MATHEMATICAL MONOSPACE CAPITAL M → LATIN CAPITAL LETTER M# - {120445, "N"}, // MA# ( 𝙽 → N ) MATHEMATICAL MONOSPACE CAPITAL N → LATIN CAPITAL LETTER N# - {120446, "O"}, // MA# ( 𝙾 → O ) MATHEMATICAL MONOSPACE CAPITAL O → LATIN CAPITAL LETTER O# - {120447, "P"}, // MA# ( 𝙿 → P ) MATHEMATICAL MONOSPACE CAPITAL P → LATIN CAPITAL LETTER P# - {120448, "Q"}, // MA# ( 𝚀 → Q ) MATHEMATICAL MONOSPACE CAPITAL Q → LATIN CAPITAL LETTER Q# - {120449, "R"}, // MA# ( 𝚁 → R ) MATHEMATICAL MONOSPACE CAPITAL R → LATIN CAPITAL LETTER R# - {120450, "S"}, // MA# ( 𝚂 → S ) MATHEMATICAL MONOSPACE CAPITAL S → LATIN CAPITAL LETTER S# - {120451, "T"}, // MA# ( 𝚃 → T ) MATHEMATICAL MONOSPACE CAPITAL T → LATIN CAPITAL LETTER T# - {120452, "U"}, // MA# ( 𝚄 → U ) MATHEMATICAL MONOSPACE CAPITAL U → LATIN CAPITAL LETTER U# - {120453, "V"}, // MA# ( 𝚅 → V ) MATHEMATICAL MONOSPACE CAPITAL V → LATIN CAPITAL LETTER V# - {120454, "W"}, // MA# ( 𝚆 → W ) MATHEMATICAL MONOSPACE CAPITAL W → LATIN CAPITAL LETTER W# - {120455, "X"}, // MA# ( 𝚇 → X ) MATHEMATICAL MONOSPACE CAPITAL X → LATIN CAPITAL LETTER X# - {120456, "Y"}, // MA# ( 𝚈 → Y ) MATHEMATICAL MONOSPACE CAPITAL Y → LATIN CAPITAL LETTER Y# - {120457, "Z"}, // MA# ( 𝚉 → Z ) MATHEMATICAL MONOSPACE CAPITAL Z → LATIN CAPITAL LETTER Z# - {120458, "a"}, // MA# ( 𝚊 → a ) MATHEMATICAL MONOSPACE SMALL A → LATIN SMALL LETTER A# - {120459, "b"}, // MA# ( 𝚋 → b ) MATHEMATICAL MONOSPACE SMALL B → LATIN SMALL LETTER B# - {120460, "c"}, // MA# ( 𝚌 → c ) MATHEMATICAL MONOSPACE SMALL C → LATIN SMALL LETTER C# - {120461, "d"}, // MA# ( 𝚍 → d ) MATHEMATICAL MONOSPACE SMALL D → LATIN SMALL LETTER D# - {120462, "e"}, // MA# ( 𝚎 → e ) MATHEMATICAL MONOSPACE SMALL E → LATIN SMALL LETTER E# - {120463, "f"}, // MA# ( 𝚏 → f ) MATHEMATICAL MONOSPACE SMALL F → LATIN SMALL LETTER F# - {120464, "g"}, // MA# ( 𝚐 → g ) MATHEMATICAL MONOSPACE SMALL G → LATIN SMALL LETTER G# - {120465, "h"}, // MA# ( 𝚑 → h ) MATHEMATICAL MONOSPACE SMALL H → LATIN SMALL LETTER H# - {120466, "i"}, // MA# ( 𝚒 → i ) MATHEMATICAL MONOSPACE SMALL I → LATIN SMALL LETTER I# - {120467, "j"}, // MA# ( 𝚓 → j ) MATHEMATICAL MONOSPACE SMALL J → LATIN SMALL LETTER J# - {120468, "k"}, // MA# ( 𝚔 → k ) MATHEMATICAL MONOSPACE SMALL K → LATIN SMALL LETTER K# - {120469, "l"}, // MA# ( 𝚕 → l ) MATHEMATICAL MONOSPACE SMALL L → LATIN SMALL LETTER L# - {120470, "rn"}, // MA# ( 𝚖 → rn ) MATHEMATICAL MONOSPACE SMALL M → LATIN SMALL LETTER R, LATIN SMALL LETTER N# →m→ - {120471, "n"}, // MA# ( 𝚗 → n ) MATHEMATICAL MONOSPACE SMALL N → LATIN SMALL LETTER N# - {120472, "o"}, // MA# ( 𝚘 → o ) MATHEMATICAL MONOSPACE SMALL O → LATIN SMALL LETTER O# - {120473, "p"}, // MA# ( 𝚙 → p ) MATHEMATICAL MONOSPACE SMALL P → LATIN SMALL LETTER P# - {120474, "q"}, // MA# ( 𝚚 → q ) MATHEMATICAL MONOSPACE SMALL Q → LATIN SMALL LETTER Q# - {120475, "r"}, // MA# ( 𝚛 → r ) MATHEMATICAL MONOSPACE SMALL R → LATIN SMALL LETTER R# - {120476, "s"}, // MA# ( 𝚜 → s ) MATHEMATICAL MONOSPACE SMALL S → LATIN SMALL LETTER S# - {120477, "t"}, // MA# ( 𝚝 → t ) MATHEMATICAL MONOSPACE SMALL T → LATIN SMALL LETTER T# - {120478, "u"}, // MA# ( 𝚞 → u ) MATHEMATICAL MONOSPACE SMALL U → LATIN SMALL LETTER U# - {120479, "v"}, // MA# ( 𝚟 → v ) MATHEMATICAL MONOSPACE SMALL V → LATIN SMALL LETTER V# - {120480, "w"}, // MA# ( 𝚠 → w ) MATHEMATICAL MONOSPACE SMALL W → LATIN SMALL LETTER W# - {120481, "x"}, // MA# ( 𝚡 → x ) MATHEMATICAL MONOSPACE SMALL X → LATIN SMALL LETTER X# - {120482, "y"}, // MA# ( 𝚢 → y ) MATHEMATICAL MONOSPACE SMALL Y → LATIN SMALL LETTER Y# - {120483, "z"}, // MA# ( 𝚣 → z ) MATHEMATICAL MONOSPACE SMALL Z → LATIN SMALL LETTER Z# - {120484, "i"}, // MA# ( 𝚤 → i ) MATHEMATICAL ITALIC SMALL DOTLESS I → LATIN SMALL LETTER I# →ı→ - {120488, "A"}, // MA# ( 𝚨 → A ) MATHEMATICAL BOLD CAPITAL ALPHA → LATIN CAPITAL LETTER A# →𝐀→ - {120489, "B"}, // MA# ( 𝚩 → B ) MATHEMATICAL BOLD CAPITAL BETA → LATIN CAPITAL LETTER B# →Β→ - {120492, "E"}, // MA# ( 𝚬 → E ) MATHEMATICAL BOLD CAPITAL EPSILON → LATIN CAPITAL LETTER E# →𝐄→ - {120493, "Z"}, // MA# ( 𝚭 → Z ) MATHEMATICAL BOLD CAPITAL ZETA → LATIN CAPITAL LETTER Z# →Ζ→ - {120494, "H"}, // MA# ( 𝚮 → H ) MATHEMATICAL BOLD CAPITAL ETA → LATIN CAPITAL LETTER H# →Η→ - {120496, "l"}, // MA# ( 𝚰 → l ) MATHEMATICAL BOLD CAPITAL IOTA → LATIN SMALL LETTER L# →Ι→ - {120497, "K"}, // MA# ( 𝚱 → K ) MATHEMATICAL BOLD CAPITAL KAPPA → LATIN CAPITAL LETTER K# →Κ→ - {120499, "M"}, // MA# ( 𝚳 → M ) MATHEMATICAL BOLD CAPITAL MU → LATIN CAPITAL LETTER M# →𝐌→ - {120500, "N"}, // MA# ( 𝚴 → N ) MATHEMATICAL BOLD CAPITAL NU → LATIN CAPITAL LETTER N# →𝐍→ - {120502, "O"}, // MA# ( 𝚶 → O ) MATHEMATICAL BOLD CAPITAL OMICRON → LATIN CAPITAL LETTER O# →𝐎→ - {120504, "P"}, // MA# ( 𝚸 → P ) MATHEMATICAL BOLD CAPITAL RHO → LATIN CAPITAL LETTER P# →𝐏→ - {120507, "T"}, // MA# ( 𝚻 → T ) MATHEMATICAL BOLD CAPITAL TAU → LATIN CAPITAL LETTER T# →Τ→ - {120508, "Y"}, // MA# ( 𝚼 → Y ) MATHEMATICAL BOLD CAPITAL UPSILON → LATIN CAPITAL LETTER Y# →Υ→ - {120510, "X"}, // MA# ( 𝚾 → X ) MATHEMATICAL BOLD CAPITAL CHI → LATIN CAPITAL LETTER X# →Χ→ - {120514, "a"}, // MA# ( 𝛂 → a ) MATHEMATICAL BOLD SMALL ALPHA → LATIN SMALL LETTER A# →α→ - {120516, "y"}, // MA# ( 𝛄 → y ) MATHEMATICAL BOLD SMALL GAMMA → LATIN SMALL LETTER Y# →γ→ - {120522, "i"}, // MA# ( 𝛊 → i ) MATHEMATICAL BOLD SMALL IOTA → LATIN SMALL LETTER I# →ι→ - {120526, "v"}, // MA# ( 𝛎 → v ) MATHEMATICAL BOLD SMALL NU → LATIN SMALL LETTER V# →ν→ - {120528, "o"}, // MA# ( 𝛐 → o ) MATHEMATICAL BOLD SMALL OMICRON → LATIN SMALL LETTER O# →𝐨→ - {120530, "p"}, // MA# ( 𝛒 → p ) MATHEMATICAL BOLD SMALL RHO → LATIN SMALL LETTER P# →ρ→ - {120532, "o"}, // MA# ( 𝛔 → o ) MATHEMATICAL BOLD SMALL SIGMA → LATIN SMALL LETTER O# →σ→ - {120534, "u"}, // MA# ( 𝛖 → u ) MATHEMATICAL BOLD SMALL UPSILON → LATIN SMALL LETTER U# →υ→→ʋ→ - {120544, "p"}, // MA# ( 𝛠 → p ) MATHEMATICAL BOLD RHO SYMBOL → LATIN SMALL LETTER P# →ρ→ - {120546, "A"}, // MA# ( 𝛢 → A ) MATHEMATICAL ITALIC CAPITAL ALPHA → LATIN CAPITAL LETTER A# →Α→ - {120547, "B"}, // MA# ( 𝛣 → B ) MATHEMATICAL ITALIC CAPITAL BETA → LATIN CAPITAL LETTER B# →Β→ - {120550, "E"}, // MA# ( 𝛦 → E ) MATHEMATICAL ITALIC CAPITAL EPSILON → LATIN CAPITAL LETTER E# →Ε→ - {120551, "Z"}, // MA# ( 𝛧 → Z ) MATHEMATICAL ITALIC CAPITAL ZETA → LATIN CAPITAL LETTER Z# →𝑍→ - {120552, "H"}, // MA# ( 𝛨 → H ) MATHEMATICAL ITALIC CAPITAL ETA → LATIN CAPITAL LETTER H# →Η→ - {120554, "l"}, // MA# ( 𝛪 → l ) MATHEMATICAL ITALIC CAPITAL IOTA → LATIN SMALL LETTER L# →Ι→ - {120555, "K"}, // MA# ( 𝛫 → K ) MATHEMATICAL ITALIC CAPITAL KAPPA → LATIN CAPITAL LETTER K# →𝐾→ - {120557, "M"}, // MA# ( 𝛭 → M ) MATHEMATICAL ITALIC CAPITAL MU → LATIN CAPITAL LETTER M# →𝑀→ - {120558, "N"}, // MA# ( 𝛮 → N ) MATHEMATICAL ITALIC CAPITAL NU → LATIN CAPITAL LETTER N# →𝑁→ - {120560, "O"}, // MA# ( 𝛰 → O ) MATHEMATICAL ITALIC CAPITAL OMICRON → LATIN CAPITAL LETTER O# →𝑂→ - {120562, "P"}, // MA# ( 𝛲 → P ) MATHEMATICAL ITALIC CAPITAL RHO → LATIN CAPITAL LETTER P# →Ρ→ - {120565, "T"}, // MA# ( 𝛵 → T ) MATHEMATICAL ITALIC CAPITAL TAU → LATIN CAPITAL LETTER T# →Τ→ - {120566, "Y"}, // MA# ( 𝛶 → Y ) MATHEMATICAL ITALIC CAPITAL UPSILON → LATIN CAPITAL LETTER Y# →Υ→ - {120568, "X"}, // MA# ( 𝛸 → X ) MATHEMATICAL ITALIC CAPITAL CHI → LATIN CAPITAL LETTER X# →Χ→ - {120572, "a"}, // MA# ( 𝛼 → a ) MATHEMATICAL ITALIC SMALL ALPHA → LATIN SMALL LETTER A# →α→ - {120574, "y"}, // MA# ( 𝛾 → y ) MATHEMATICAL ITALIC SMALL GAMMA → LATIN SMALL LETTER Y# →γ→ - {120580, "i"}, // MA# ( 𝜄 → i ) MATHEMATICAL ITALIC SMALL IOTA → LATIN SMALL LETTER I# →ι→ - {120584, "v"}, // MA# ( 𝜈 → v ) MATHEMATICAL ITALIC SMALL NU → LATIN SMALL LETTER V# →ν→ - {120586, "o"}, // MA# ( 𝜊 → o ) MATHEMATICAL ITALIC SMALL OMICRON → LATIN SMALL LETTER O# →𝑜→ - {120588, "p"}, // MA# ( 𝜌 → p ) MATHEMATICAL ITALIC SMALL RHO → LATIN SMALL LETTER P# →ρ→ - {120590, "o"}, // MA# ( 𝜎 → o ) MATHEMATICAL ITALIC SMALL SIGMA → LATIN SMALL LETTER O# →σ→ - {120592, "u"}, // MA# ( 𝜐 → u ) MATHEMATICAL ITALIC SMALL UPSILON → LATIN SMALL LETTER U# →υ→→ʋ→ - {120602, "p"}, // MA# ( 𝜚 → p ) MATHEMATICAL ITALIC RHO SYMBOL → LATIN SMALL LETTER P# →ρ→ - {120604, "A"}, // MA# ( 𝜜 → A ) MATHEMATICAL BOLD ITALIC CAPITAL ALPHA → LATIN CAPITAL LETTER A# →Α→ - {120605, "B"}, // MA# ( 𝜝 → B ) MATHEMATICAL BOLD ITALIC CAPITAL BETA → LATIN CAPITAL LETTER B# →Β→ - {120608, "E"}, // MA# ( 𝜠 → E ) MATHEMATICAL BOLD ITALIC CAPITAL EPSILON → LATIN CAPITAL LETTER E# →Ε→ - {120609, "Z"}, // MA# ( 𝜡 → Z ) MATHEMATICAL BOLD ITALIC CAPITAL ZETA → LATIN CAPITAL LETTER Z# →Ζ→ - {120610, "H"}, // MA# ( 𝜢 → H ) MATHEMATICAL BOLD ITALIC CAPITAL ETA → LATIN CAPITAL LETTER H# →𝑯→ - {120612, "l"}, // MA# ( 𝜤 → l ) MATHEMATICAL BOLD ITALIC CAPITAL IOTA → LATIN SMALL LETTER L# →Ι→ - {120613, "K"}, // MA# ( 𝜥 → K ) MATHEMATICAL BOLD ITALIC CAPITAL KAPPA → LATIN CAPITAL LETTER K# →𝑲→ - {120615, "M"}, // MA# ( 𝜧 → M ) MATHEMATICAL BOLD ITALIC CAPITAL MU → LATIN CAPITAL LETTER M# →𝑴→ - {120616, "N"}, // MA# ( 𝜨 → N ) MATHEMATICAL BOLD ITALIC CAPITAL NU → LATIN CAPITAL LETTER N# →𝑵→ - {120618, "O"}, // MA# ( 𝜪 → O ) MATHEMATICAL BOLD ITALIC CAPITAL OMICRON → LATIN CAPITAL LETTER O# →𝑶→ - {120620, "P"}, // MA# ( 𝜬 → P ) MATHEMATICAL BOLD ITALIC CAPITAL RHO → LATIN CAPITAL LETTER P# →Ρ→ - {120623, "T"}, // MA# ( 𝜯 → T ) MATHEMATICAL BOLD ITALIC CAPITAL TAU → LATIN CAPITAL LETTER T# →Τ→ - {120624, "Y"}, // MA# ( 𝜰 → Y ) MATHEMATICAL BOLD ITALIC CAPITAL UPSILON → LATIN CAPITAL LETTER Y# →Υ→ - {120626, "X"}, // MA# ( 𝜲 → X ) MATHEMATICAL BOLD ITALIC CAPITAL CHI → LATIN CAPITAL LETTER X# →𝑿→ - {120630, "a"}, // MA# ( 𝜶 → a ) MATHEMATICAL BOLD ITALIC SMALL ALPHA → LATIN SMALL LETTER A# →α→ - {120632, "y"}, // MA# ( 𝜸 → y ) MATHEMATICAL BOLD ITALIC SMALL GAMMA → LATIN SMALL LETTER Y# →γ→ - {120638, "i"}, // MA# ( 𝜾 → i ) MATHEMATICAL BOLD ITALIC SMALL IOTA → LATIN SMALL LETTER I# →ι→ - {120642, "v"}, // MA# ( 𝝂 → v ) MATHEMATICAL BOLD ITALIC SMALL NU → LATIN SMALL LETTER V# →ν→ - {120644, "o"}, // MA# ( 𝝄 → o ) MATHEMATICAL BOLD ITALIC SMALL OMICRON → LATIN SMALL LETTER O# →𝒐→ - {120646, "p"}, // MA# ( 𝝆 → p ) MATHEMATICAL BOLD ITALIC SMALL RHO → LATIN SMALL LETTER P# →ρ→ - {120648, "o"}, // MA# ( 𝝈 → o ) MATHEMATICAL BOLD ITALIC SMALL SIGMA → LATIN SMALL LETTER O# →σ→ - {120650, "u"}, // MA# ( 𝝊 → u ) MATHEMATICAL BOLD ITALIC SMALL UPSILON → LATIN SMALL LETTER U# →υ→→ʋ→ - {120660, "p"}, // MA# ( 𝝔 → p ) MATHEMATICAL BOLD ITALIC RHO SYMBOL → LATIN SMALL LETTER P# →ρ→ - {120662, "A"}, // MA# ( 𝝖 → A ) MATHEMATICAL SANS-SERIF BOLD CAPITAL ALPHA → LATIN CAPITAL LETTER A# →Α→ - {120663, "B"}, // MA# ( 𝝗 → B ) MATHEMATICAL SANS-SERIF BOLD CAPITAL BETA → LATIN CAPITAL LETTER B# →Β→ - {120666, "E"}, // MA# ( 𝝚 → E ) MATHEMATICAL SANS-SERIF BOLD CAPITAL EPSILON → LATIN CAPITAL LETTER E# →Ε→ - {120667, "Z"}, // MA# ( 𝝛 → Z ) MATHEMATICAL SANS-SERIF BOLD CAPITAL ZETA → LATIN CAPITAL LETTER Z# →Ζ→ - {120668, "H"}, // MA# ( 𝝜 → H ) MATHEMATICAL SANS-SERIF BOLD CAPITAL ETA → LATIN CAPITAL LETTER H# →Η→ - {120670, "l"}, // MA# ( 𝝞 → l ) MATHEMATICAL SANS-SERIF BOLD CAPITAL IOTA → LATIN SMALL LETTER L# →Ι→ - {120671, "K"}, // MA# ( 𝝟 → K ) MATHEMATICAL SANS-SERIF BOLD CAPITAL KAPPA → LATIN CAPITAL LETTER K# →Κ→ - {120673, "M"}, // MA# ( 𝝡 → M ) MATHEMATICAL SANS-SERIF BOLD CAPITAL MU → LATIN CAPITAL LETTER M# →Μ→ - {120674, "N"}, // MA# ( 𝝢 → N ) MATHEMATICAL SANS-SERIF BOLD CAPITAL NU → LATIN CAPITAL LETTER N# →Ν→ - {120676, "O"}, // MA# ( 𝝤 → O ) MATHEMATICAL SANS-SERIF BOLD CAPITAL OMICRON → LATIN CAPITAL LETTER O# →Ο→ - {120678, "P"}, // MA# ( 𝝦 → P ) MATHEMATICAL SANS-SERIF BOLD CAPITAL RHO → LATIN CAPITAL LETTER P# →Ρ→ - {120681, "T"}, // MA# ( 𝝩 → T ) MATHEMATICAL SANS-SERIF BOLD CAPITAL TAU → LATIN CAPITAL LETTER T# →Τ→ - {120682, "Y"}, // MA# ( 𝝪 → Y ) MATHEMATICAL SANS-SERIF BOLD CAPITAL UPSILON → LATIN CAPITAL LETTER Y# →Υ→ - {120684, "X"}, // MA# ( 𝝬 → X ) MATHEMATICAL SANS-SERIF BOLD CAPITAL CHI → LATIN CAPITAL LETTER X# →Χ→ - {120688, "a"}, // MA# ( 𝝰 → a ) MATHEMATICAL SANS-SERIF BOLD SMALL ALPHA → LATIN SMALL LETTER A# →α→ - {120690, "y"}, // MA# ( 𝝲 → y ) MATHEMATICAL SANS-SERIF BOLD SMALL GAMMA → LATIN SMALL LETTER Y# →γ→ - {120696, "i"}, // MA# ( 𝝸 → i ) MATHEMATICAL SANS-SERIF BOLD SMALL IOTA → LATIN SMALL LETTER I# →ι→ - {120700, "v"}, // MA# ( 𝝼 → v ) MATHEMATICAL SANS-SERIF BOLD SMALL NU → LATIN SMALL LETTER V# →ν→ - {120702, "o"}, // MA# ( 𝝾 → o ) MATHEMATICAL SANS-SERIF BOLD SMALL OMICRON → LATIN SMALL LETTER O# →ο→ - {120704, "p"}, // MA# ( 𝞀 → p ) MATHEMATICAL SANS-SERIF BOLD SMALL RHO → LATIN SMALL LETTER P# →ρ→ - {120706, "o"}, // MA# ( 𝞂 → o ) MATHEMATICAL SANS-SERIF BOLD SMALL SIGMA → LATIN SMALL LETTER O# →σ→ - {120708, "u"}, // MA# ( 𝞄 → u ) MATHEMATICAL SANS-SERIF BOLD SMALL UPSILON → LATIN SMALL LETTER U# →υ→→ʋ→ - {120718, "p"}, // MA# ( 𝞎 → p ) MATHEMATICAL SANS-SERIF BOLD RHO SYMBOL → LATIN SMALL LETTER P# →ρ→ - {120720, "A"}, // MA# ( 𝞐 → A ) MATHEMATICAL SANS-SERIF BOLD ITALIC CAPITAL ALPHA → LATIN CAPITAL LETTER A# →Α→ - {120721, "B"}, // MA# ( 𝞑 → B ) MATHEMATICAL SANS-SERIF BOLD ITALIC CAPITAL BETA → LATIN CAPITAL LETTER B# →Β→ - {120724, "E"}, // MA# ( 𝞔 → E ) MATHEMATICAL SANS-SERIF BOLD ITALIC CAPITAL EPSILON → LATIN CAPITAL LETTER E# →Ε→ - {120725, "Z"}, // MA# ( 𝞕 → Z ) MATHEMATICAL SANS-SERIF BOLD ITALIC CAPITAL ZETA → LATIN CAPITAL LETTER Z# →Ζ→ - {120726, "H"}, // MA# ( 𝞖 → H ) MATHEMATICAL SANS-SERIF BOLD ITALIC CAPITAL ETA → LATIN CAPITAL LETTER H# →Η→ - {120728, "l"}, // MA# ( 𝞘 → l ) MATHEMATICAL SANS-SERIF BOLD ITALIC CAPITAL IOTA → LATIN SMALL LETTER L# →Ι→ - {120729, "K"}, // MA# ( 𝞙 → K ) MATHEMATICAL SANS-SERIF BOLD ITALIC CAPITAL KAPPA → LATIN CAPITAL LETTER K# →Κ→ - {120731, "M"}, // MA# ( 𝞛 → M ) MATHEMATICAL SANS-SERIF BOLD ITALIC CAPITAL MU → LATIN CAPITAL LETTER M# →Μ→ - {120732, "N"}, // MA# ( 𝞜 → N ) MATHEMATICAL SANS-SERIF BOLD ITALIC CAPITAL NU → LATIN CAPITAL LETTER N# →Ν→ - {120734, "O"}, // MA# ( 𝞞 → O ) MATHEMATICAL SANS-SERIF BOLD ITALIC CAPITAL OMICRON → LATIN CAPITAL LETTER O# →Ο→ - {120736, "P"}, // MA# ( 𝞠 → P ) MATHEMATICAL SANS-SERIF BOLD ITALIC CAPITAL RHO → LATIN CAPITAL LETTER P# →Ρ→ - {120739, "T"}, // MA# ( 𝞣 → T ) MATHEMATICAL SANS-SERIF BOLD ITALIC CAPITAL TAU → LATIN CAPITAL LETTER T# →Τ→ - {120740, "Y"}, // MA# ( 𝞤 → Y ) MATHEMATICAL SANS-SERIF BOLD ITALIC CAPITAL UPSILON → LATIN CAPITAL LETTER Y# →Υ→ - {120742, "X"}, // MA# ( 𝞦 → X ) MATHEMATICAL SANS-SERIF BOLD ITALIC CAPITAL CHI → LATIN CAPITAL LETTER X# →Χ→ - {120746, "a"}, // MA# ( 𝞪 → a ) MATHEMATICAL SANS-SERIF BOLD ITALIC SMALL ALPHA → LATIN SMALL LETTER A# →α→ - {120748, "y"}, // MA# ( 𝞬 → y ) MATHEMATICAL SANS-SERIF BOLD ITALIC SMALL GAMMA → LATIN SMALL LETTER Y# →γ→ - {120754, "i"}, // MA# ( 𝞲 → i ) MATHEMATICAL SANS-SERIF BOLD ITALIC SMALL IOTA → LATIN SMALL LETTER I# →ι→ - {120758, "v"}, // MA# ( 𝞶 → v ) MATHEMATICAL SANS-SERIF BOLD ITALIC SMALL NU → LATIN SMALL LETTER V# →ν→ - {120760, "o"}, // MA# ( 𝞸 → o ) MATHEMATICAL SANS-SERIF BOLD ITALIC SMALL OMICRON → LATIN SMALL LETTER O# →ο→ - {120762, "p"}, // MA# ( 𝞺 → p ) MATHEMATICAL SANS-SERIF BOLD ITALIC SMALL RHO → LATIN SMALL LETTER P# →ρ→ - {120764, "o"}, // MA# ( 𝞼 → o ) MATHEMATICAL SANS-SERIF BOLD ITALIC SMALL SIGMA → LATIN SMALL LETTER O# →σ→ - {120766, "u"}, // MA# ( 𝞾 → u ) MATHEMATICAL SANS-SERIF BOLD ITALIC SMALL UPSILON → LATIN SMALL LETTER U# →υ→→ʋ→ - {120776, "p"}, // MA# ( 𝟈 → p ) MATHEMATICAL SANS-SERIF BOLD ITALIC RHO SYMBOL → LATIN SMALL LETTER P# →ρ→ - {120778, "F"}, // MA# ( 𝟊 → F ) MATHEMATICAL BOLD CAPITAL DIGAMMA → LATIN CAPITAL LETTER F# →Ϝ→ - {120782, "O"}, // MA# ( 𝟎 → O ) MATHEMATICAL BOLD DIGIT ZERO → LATIN CAPITAL LETTER O# →0→ - {120783, "l"}, // MA# ( 𝟏 → l ) MATHEMATICAL BOLD DIGIT ONE → LATIN SMALL LETTER L# →1→ - {120784, "2"}, // MA# ( 𝟐 → 2 ) MATHEMATICAL BOLD DIGIT TWO → DIGIT TWO# - {120785, "3"}, // MA# ( 𝟑 → 3 ) MATHEMATICAL BOLD DIGIT THREE → DIGIT THREE# - {120786, "4"}, // MA# ( 𝟒 → 4 ) MATHEMATICAL BOLD DIGIT FOUR → DIGIT FOUR# - {120787, "5"}, // MA# ( 𝟓 → 5 ) MATHEMATICAL BOLD DIGIT FIVE → DIGIT FIVE# - {120788, "6"}, // MA# ( 𝟔 → 6 ) MATHEMATICAL BOLD DIGIT SIX → DIGIT SIX# - {120789, "7"}, // MA# ( 𝟕 → 7 ) MATHEMATICAL BOLD DIGIT SEVEN → DIGIT SEVEN# - {120790, "8"}, // MA# ( 𝟖 → 8 ) MATHEMATICAL BOLD DIGIT EIGHT → DIGIT EIGHT# - {120791, "9"}, // MA# ( 𝟗 → 9 ) MATHEMATICAL BOLD DIGIT NINE → DIGIT NINE# - {120792, "O"}, // MA# ( 𝟘 → O ) MATHEMATICAL DOUBLE-STRUCK DIGIT ZERO → LATIN CAPITAL LETTER O# →0→ - {120793, "l"}, // MA# ( 𝟙 → l ) MATHEMATICAL DOUBLE-STRUCK DIGIT ONE → LATIN SMALL LETTER L# →1→ - {120794, "2"}, // MA# ( 𝟚 → 2 ) MATHEMATICAL DOUBLE-STRUCK DIGIT TWO → DIGIT TWO# - {120795, "3"}, // MA# ( 𝟛 → 3 ) MATHEMATICAL DOUBLE-STRUCK DIGIT THREE → DIGIT THREE# - {120796, "4"}, // MA# ( 𝟜 → 4 ) MATHEMATICAL DOUBLE-STRUCK DIGIT FOUR → DIGIT FOUR# - {120797, "5"}, // MA# ( 𝟝 → 5 ) MATHEMATICAL DOUBLE-STRUCK DIGIT FIVE → DIGIT FIVE# - {120798, "6"}, // MA# ( 𝟞 → 6 ) MATHEMATICAL DOUBLE-STRUCK DIGIT SIX → DIGIT SIX# - {120799, "7"}, // MA# ( 𝟟 → 7 ) MATHEMATICAL DOUBLE-STRUCK DIGIT SEVEN → DIGIT SEVEN# - {120800, "8"}, // MA# ( 𝟠 → 8 ) MATHEMATICAL DOUBLE-STRUCK DIGIT EIGHT → DIGIT EIGHT# - {120801, "9"}, // MA# ( 𝟡 → 9 ) MATHEMATICAL DOUBLE-STRUCK DIGIT NINE → DIGIT NINE# - {120802, "O"}, // MA# ( 𝟢 → O ) MATHEMATICAL SANS-SERIF DIGIT ZERO → LATIN CAPITAL LETTER O# →0→ - {120803, "l"}, // MA# ( 𝟣 → l ) MATHEMATICAL SANS-SERIF DIGIT ONE → LATIN SMALL LETTER L# →1→ - {120804, "2"}, // MA# ( 𝟤 → 2 ) MATHEMATICAL SANS-SERIF DIGIT TWO → DIGIT TWO# - {120805, "3"}, // MA# ( 𝟥 → 3 ) MATHEMATICAL SANS-SERIF DIGIT THREE → DIGIT THREE# - {120806, "4"}, // MA# ( 𝟦 → 4 ) MATHEMATICAL SANS-SERIF DIGIT FOUR → DIGIT FOUR# - {120807, "5"}, // MA# ( 𝟧 → 5 ) MATHEMATICAL SANS-SERIF DIGIT FIVE → DIGIT FIVE# - {120808, "6"}, // MA# ( 𝟨 → 6 ) MATHEMATICAL SANS-SERIF DIGIT SIX → DIGIT SIX# - {120809, "7"}, // MA# ( 𝟩 → 7 ) MATHEMATICAL SANS-SERIF DIGIT SEVEN → DIGIT SEVEN# - {120810, "8"}, // MA# ( 𝟪 → 8 ) MATHEMATICAL SANS-SERIF DIGIT EIGHT → DIGIT EIGHT# - {120811, "9"}, // MA# ( 𝟫 → 9 ) MATHEMATICAL SANS-SERIF DIGIT NINE → DIGIT NINE# - {120812, "O"}, // MA# ( 𝟬 → O ) MATHEMATICAL SANS-SERIF BOLD DIGIT ZERO → LATIN CAPITAL LETTER O# →0→ - {120813, "l"}, // MA# ( 𝟭 → l ) MATHEMATICAL SANS-SERIF BOLD DIGIT ONE → LATIN SMALL LETTER L# →1→ - {120814, "2"}, // MA# ( 𝟮 → 2 ) MATHEMATICAL SANS-SERIF BOLD DIGIT TWO → DIGIT TWO# - {120815, "3"}, // MA# ( 𝟯 → 3 ) MATHEMATICAL SANS-SERIF BOLD DIGIT THREE → DIGIT THREE# - {120816, "4"}, // MA# ( 𝟰 → 4 ) MATHEMATICAL SANS-SERIF BOLD DIGIT FOUR → DIGIT FOUR# - {120817, "5"}, // MA# ( 𝟱 → 5 ) MATHEMATICAL SANS-SERIF BOLD DIGIT FIVE → DIGIT FIVE# - {120818, "6"}, // MA# ( 𝟲 → 6 ) MATHEMATICAL SANS-SERIF BOLD DIGIT SIX → DIGIT SIX# - {120819, "7"}, // MA# ( 𝟳 → 7 ) MATHEMATICAL SANS-SERIF BOLD DIGIT SEVEN → DIGIT SEVEN# - {120820, "8"}, // MA# ( 𝟴 → 8 ) MATHEMATICAL SANS-SERIF BOLD DIGIT EIGHT → DIGIT EIGHT# - {120821, "9"}, // MA# ( 𝟵 → 9 ) MATHEMATICAL SANS-SERIF BOLD DIGIT NINE → DIGIT NINE# - {120822, "O"}, // MA# ( 𝟶 → O ) MATHEMATICAL MONOSPACE DIGIT ZERO → LATIN CAPITAL LETTER O# →0→ - {120823, "l"}, // MA# ( 𝟷 → l ) MATHEMATICAL MONOSPACE DIGIT ONE → LATIN SMALL LETTER L# →1→ - {120824, "2"}, // MA# ( 𝟸 → 2 ) MATHEMATICAL MONOSPACE DIGIT TWO → DIGIT TWO# - {120825, "3"}, // MA# ( 𝟹 → 3 ) MATHEMATICAL MONOSPACE DIGIT THREE → DIGIT THREE# - {120826, "4"}, // MA# ( 𝟺 → 4 ) MATHEMATICAL MONOSPACE DIGIT FOUR → DIGIT FOUR# - {120827, "5"}, // MA# ( 𝟻 → 5 ) MATHEMATICAL MONOSPACE DIGIT FIVE → DIGIT FIVE# - {120828, "6"}, // MA# ( 𝟼 → 6 ) MATHEMATICAL MONOSPACE DIGIT SIX → DIGIT SIX# - {120829, "7"}, // MA# ( 𝟽 → 7 ) MATHEMATICAL MONOSPACE DIGIT SEVEN → DIGIT SEVEN# - {120830, "8"}, // MA# ( 𝟾 → 8 ) MATHEMATICAL MONOSPACE DIGIT EIGHT → DIGIT EIGHT# - {120831, "9"}, // MA# ( 𝟿 → 9 ) MATHEMATICAL MONOSPACE DIGIT NINE → DIGIT NINE# - {125127, "l"}, // MA#* ( ‎𞣇‎ → l ) MENDE KIKAKUI DIGIT ONE → LATIN SMALL LETTER L# - {125131, "8"}, // MA#* ( ‎𞣋‎ → 8 ) MENDE KIKAKUI DIGIT FIVE → DIGIT EIGHT# - {126464, "l"}, // MA# ( ‎𞸀‎ → l ) ARABIC MATHEMATICAL ALEF → LATIN SMALL LETTER L# →‎ا‎→→1→ - {126500, "o"}, // MA# ( ‎𞸤‎ → o ) ARABIC MATHEMATICAL INITIAL HEH → LATIN SMALL LETTER O# →‎ه‎→ - {126564, "o"}, // MA# ( ‎𞹤‎ → o ) ARABIC MATHEMATICAL STRETCHED HEH → LATIN SMALL LETTER O# →‎ه‎→ - {126592, "l"}, // MA# ( ‎𞺀‎ → l ) ARABIC MATHEMATICAL LOOPED ALEF → LATIN SMALL LETTER L# →‎ا‎→→1→ - {126596, "o"}, // MA# ( ‎𞺄‎ → o ) ARABIC MATHEMATICAL LOOPED HEH → LATIN SMALL LETTER O# →‎ه‎→ - {127232, "O."}, // MA#* ( 🄀 → O. ) DIGIT ZERO FULL STOP → LATIN CAPITAL LETTER O, FULL STOP# →0.→ - {127233, "O,"}, // MA#* ( 🄁 → O, ) DIGIT ZERO COMMA → LATIN CAPITAL LETTER O, COMMA# →0,→ - {127234, "l,"}, // MA#* ( 🄂 → l, ) DIGIT ONE COMMA → LATIN SMALL LETTER L, COMMA# →1,→ - {127235, "2,"}, // MA#* ( 🄃 → 2, ) DIGIT TWO COMMA → DIGIT TWO, COMMA# - {127236, "3,"}, // MA#* ( 🄄 → 3, ) DIGIT THREE COMMA → DIGIT THREE, COMMA# - {127237, "4,"}, // MA#* ( 🄅 → 4, ) DIGIT FOUR COMMA → DIGIT FOUR, COMMA# - {127238, "5,"}, // MA#* ( 🄆 → 5, ) DIGIT FIVE COMMA → DIGIT FIVE, COMMA# - {127239, "6,"}, // MA#* ( 🄇 → 6, ) DIGIT SIX COMMA → DIGIT SIX, COMMA# - {127240, "7,"}, // MA#* ( 🄈 → 7, ) DIGIT SEVEN COMMA → DIGIT SEVEN, COMMA# - {127241, "8,"}, // MA#* ( 🄉 → 8, ) DIGIT EIGHT COMMA → DIGIT EIGHT, COMMA# - {127242, "9,"}, // MA#* ( 🄊 → 9, ) DIGIT NINE COMMA → DIGIT NINE, COMMA# - {127248, "(A)"}, // MA#* ( 🄐 → (A) ) PARENTHESIZED LATIN CAPITAL LETTER A → LEFT PARENTHESIS, LATIN CAPITAL LETTER A, RIGHT PARENTHESIS# - {127249, "(B)"}, // MA#* ( 🄑 → (B) ) PARENTHESIZED LATIN CAPITAL LETTER B → LEFT PARENTHESIS, LATIN CAPITAL LETTER B, RIGHT PARENTHESIS# - {127250, "(C)"}, // MA#* ( 🄒 → (C) ) PARENTHESIZED LATIN CAPITAL LETTER C → LEFT PARENTHESIS, LATIN CAPITAL LETTER C, RIGHT PARENTHESIS# - {127251, "(D)"}, // MA#* ( 🄓 → (D) ) PARENTHESIZED LATIN CAPITAL LETTER D → LEFT PARENTHESIS, LATIN CAPITAL LETTER D, RIGHT PARENTHESIS# - {127252, "(E)"}, // MA#* ( 🄔 → (E) ) PARENTHESIZED LATIN CAPITAL LETTER E → LEFT PARENTHESIS, LATIN CAPITAL LETTER E, RIGHT PARENTHESIS# - {127253, "(F)"}, // MA#* ( 🄕 → (F) ) PARENTHESIZED LATIN CAPITAL LETTER F → LEFT PARENTHESIS, LATIN CAPITAL LETTER F, RIGHT PARENTHESIS# - {127254, "(G)"}, // MA#* ( 🄖 → (G) ) PARENTHESIZED LATIN CAPITAL LETTER G → LEFT PARENTHESIS, LATIN CAPITAL LETTER G, RIGHT PARENTHESIS# - {127255, "(H)"}, // MA#* ( 🄗 → (H) ) PARENTHESIZED LATIN CAPITAL LETTER H → LEFT PARENTHESIS, LATIN CAPITAL LETTER H, RIGHT PARENTHESIS# - {127256, "(l)"}, // MA#* ( 🄘 → (l) ) PARENTHESIZED LATIN CAPITAL LETTER I → LEFT PARENTHESIS, LATIN SMALL LETTER L, RIGHT PARENTHESIS# →(I)→ - {127257, "(J)"}, // MA#* ( 🄙 → (J) ) PARENTHESIZED LATIN CAPITAL LETTER J → LEFT PARENTHESIS, LATIN CAPITAL LETTER J, RIGHT PARENTHESIS# - {127258, "(K)"}, // MA#* ( 🄚 → (K) ) PARENTHESIZED LATIN CAPITAL LETTER K → LEFT PARENTHESIS, LATIN CAPITAL LETTER K, RIGHT PARENTHESIS# - {127259, "(L)"}, // MA#* ( 🄛 → (L) ) PARENTHESIZED LATIN CAPITAL LETTER L → LEFT PARENTHESIS, LATIN CAPITAL LETTER L, RIGHT PARENTHESIS# - {127260, "(M)"}, // MA#* ( 🄜 → (M) ) PARENTHESIZED LATIN CAPITAL LETTER M → LEFT PARENTHESIS, LATIN CAPITAL LETTER M, RIGHT PARENTHESIS# - {127261, "(N)"}, // MA#* ( 🄝 → (N) ) PARENTHESIZED LATIN CAPITAL LETTER N → LEFT PARENTHESIS, LATIN CAPITAL LETTER N, RIGHT PARENTHESIS# - {127262, "(O)"}, // MA#* ( 🄞 → (O) ) PARENTHESIZED LATIN CAPITAL LETTER O → LEFT PARENTHESIS, LATIN CAPITAL LETTER O, RIGHT PARENTHESIS# - {127263, "(P)"}, // MA#* ( 🄟 → (P) ) PARENTHESIZED LATIN CAPITAL LETTER P → LEFT PARENTHESIS, LATIN CAPITAL LETTER P, RIGHT PARENTHESIS# - {127264, "(Q)"}, // MA#* ( 🄠 → (Q) ) PARENTHESIZED LATIN CAPITAL LETTER Q → LEFT PARENTHESIS, LATIN CAPITAL LETTER Q, RIGHT PARENTHESIS# - {127265, "(R)"}, // MA#* ( 🄡 → (R) ) PARENTHESIZED LATIN CAPITAL LETTER R → LEFT PARENTHESIS, LATIN CAPITAL LETTER R, RIGHT PARENTHESIS# - {127266, "(S)"}, // MA#* ( 🄢 → (S) ) PARENTHESIZED LATIN CAPITAL LETTER S → LEFT PARENTHESIS, LATIN CAPITAL LETTER S, RIGHT PARENTHESIS# - {127267, "(T)"}, // MA#* ( 🄣 → (T) ) PARENTHESIZED LATIN CAPITAL LETTER T → LEFT PARENTHESIS, LATIN CAPITAL LETTER T, RIGHT PARENTHESIS# - {127268, "(U)"}, // MA#* ( 🄤 → (U) ) PARENTHESIZED LATIN CAPITAL LETTER U → LEFT PARENTHESIS, LATIN CAPITAL LETTER U, RIGHT PARENTHESIS# - {127269, "(V)"}, // MA#* ( 🄥 → (V) ) PARENTHESIZED LATIN CAPITAL LETTER V → LEFT PARENTHESIS, LATIN CAPITAL LETTER V, RIGHT PARENTHESIS# - {127270, "(W)"}, // MA#* ( 🄦 → (W) ) PARENTHESIZED LATIN CAPITAL LETTER W → LEFT PARENTHESIS, LATIN CAPITAL LETTER W, RIGHT PARENTHESIS# - {127271, "(X)"}, // MA#* ( 🄧 → (X) ) PARENTHESIZED LATIN CAPITAL LETTER X → LEFT PARENTHESIS, LATIN CAPITAL LETTER X, RIGHT PARENTHESIS# - {127272, "(Y)"}, // MA#* ( 🄨 → (Y) ) PARENTHESIZED LATIN CAPITAL LETTER Y → LEFT PARENTHESIS, LATIN CAPITAL LETTER Y, RIGHT PARENTHESIS# - {127273, "(Z)"}, // MA#* ( 🄩 → (Z) ) PARENTHESIZED LATIN CAPITAL LETTER Z → LEFT PARENTHESIS, LATIN CAPITAL LETTER Z, RIGHT PARENTHESIS# - {127274, "(S)"}, // MA#* ( 🄪 → (S) ) TORTOISE SHELL BRACKETED LATIN CAPITAL LETTER S → LEFT PARENTHESIS, LATIN CAPITAL LETTER S, RIGHT PARENTHESIS# →〔S〕→ - {128768, "QE"}, // MA#* ( 🜀 → QE ) ALCHEMICAL SYMBOL FOR QUINTESSENCE → LATIN CAPITAL LETTER Q, LATIN CAPITAL LETTER E# - {128775, "AR"}, // MA#* ( 🜇 → AR ) ALCHEMICAL SYMBOL FOR AQUA REGIA-2 → LATIN CAPITAL LETTER A, LATIN CAPITAL LETTER R# - {128844, "C"}, // MA#* ( 🝌 → C ) ALCHEMICAL SYMBOL FOR CALX → LATIN CAPITAL LETTER C# - {128860, "sss"}, // MA#* ( 🝜 → sss ) ALCHEMICAL SYMBOL FOR STRATUM SUPER STRATUM → LATIN SMALL LETTER S, LATIN SMALL LETTER S, LATIN SMALL LETTER S# - {128872, "T"}, // MA#* ( 🝨 → T ) ALCHEMICAL SYMBOL FOR CRUCIBLE-4 → LATIN CAPITAL LETTER T# - {128875, "MB"}, // MA#* ( 🝫 → MB ) ALCHEMICAL SYMBOL FOR BATH OF MARY → LATIN CAPITAL LETTER M, LATIN CAPITAL LETTER B# - {128876, "VB"}, // MA#* ( 🝬 → VB ) ALCHEMICAL SYMBOL FOR BATH OF VAPOURS → LATIN CAPITAL LETTER V, LATIN CAPITAL LETTER B# -}; -// clang-format on - -const char* findConfusable(uint32_t codepoint) -{ - auto it = std::lower_bound(std::begin(kConfusables), std::end(kConfusables), codepoint, [](const Confusable& lhs, uint32_t rhs) { - return lhs.codepoint < rhs; - }); - - return (it != std::end(kConfusables) && it->codepoint == codepoint) ? it->text : nullptr; -} - -} // namespace Luau diff --git a/lib/luau/Ast/src/Lexer.cpp b/lib/luau/Ast/src/Lexer.cpp deleted file mode 100644 index 96653a5..0000000 --- a/lib/luau/Ast/src/Lexer.cpp +++ /dev/null @@ -1,1318 +0,0 @@ -// This file is part of the Luau programming language and is licensed under MIT License; see LICENSE.txt for details -#include "Luau/Lexer.h" - -#include "Luau/Common.h" -#include "Luau/Confusables.h" -#include "Luau/StringUtils.h" - -#include - -LUAU_FASTFLAGVARIABLE(LuauLexerLookaheadRemembersBraceType, false) -LUAU_FASTFLAGVARIABLE(LuauCheckedFunctionSyntax, false) - -namespace Luau -{ - -Allocator::Allocator() - : root(static_cast(operator new(sizeof(Page)))) - , offset(0) -{ - root->next = nullptr; -} - -Allocator::Allocator(Allocator&& rhs) - : root(rhs.root) - , offset(rhs.offset) -{ - rhs.root = nullptr; - rhs.offset = 0; -} - -Allocator::~Allocator() -{ - Page* page = root; - - while (page) - { - Page* next = page->next; - - operator delete(page); - - page = next; - } -} - -void* Allocator::allocate(size_t size) -{ - constexpr size_t align = alignof(void*) > alignof(double) ? alignof(void*) : alignof(double); - - if (root) - { - uintptr_t data = reinterpret_cast(root->data); - uintptr_t result = (data + offset + align - 1) & ~(align - 1); - if (result + size <= data + sizeof(root->data)) - { - offset = result - data + size; - return reinterpret_cast(result); - } - } - - // allocate new page - size_t pageSize = size > sizeof(root->data) ? size : sizeof(root->data); - void* pageData = operator new(offsetof(Page, data) + pageSize); - - Page* page = static_cast(pageData); - - page->next = root; - - root = page; - offset = size; - - return page->data; -} - -Lexeme::Lexeme(const Location& location, Type type) - : type(type) - , location(location) - , length(0) - , data(nullptr) -{ -} - -Lexeme::Lexeme(const Location& location, char character) - : type(static_cast(static_cast(character))) - , location(location) - , length(0) - , data(nullptr) -{ -} - -Lexeme::Lexeme(const Location& location, Type type, const char* data, size_t size) - : type(type) - , location(location) - , length(unsigned(size)) - , data(data) -{ - LUAU_ASSERT(type == RawString || type == QuotedString || type == InterpStringBegin || type == InterpStringMid || type == InterpStringEnd || - type == InterpStringSimple || type == BrokenInterpDoubleBrace || type == Number || type == Comment || type == BlockComment); -} - -Lexeme::Lexeme(const Location& location, Type type, const char* name) - : type(type) - , location(location) - , length(0) - , name(name) -{ - LUAU_ASSERT(type == Name || (type >= Reserved_BEGIN && type < Lexeme::Reserved_END)); -} - -static const char* kReserved[] = {"and", "break", "do", "else", "elseif", "end", "false", "for", "function", "if", "in", "local", "nil", "not", "or", - "repeat", "return", "then", "true", "until", "while", "@checked"}; - -std::string Lexeme::toString() const -{ - switch (type) - { - case Eof: - return ""; - - case Equal: - return "'=='"; - - case LessEqual: - return "'<='"; - - case GreaterEqual: - return "'>='"; - - case NotEqual: - return "'~='"; - - case Dot2: - return "'..'"; - - case Dot3: - return "'...'"; - - case SkinnyArrow: - return "'->'"; - - case DoubleColon: - return "'::'"; - - case FloorDiv: - return "'//'"; - - case AddAssign: - return "'+='"; - - case SubAssign: - return "'-='"; - - case MulAssign: - return "'*='"; - - case DivAssign: - return "'/='"; - - case FloorDivAssign: - return "'//='"; - - case ModAssign: - return "'%='"; - - case PowAssign: - return "'^='"; - - case ConcatAssign: - return "'..='"; - - case RawString: - case QuotedString: - return data ? format("\"%.*s\"", length, data) : "string"; - - case InterpStringBegin: - return data ? format("`%.*s{", length, data) : "the beginning of an interpolated string"; - - case InterpStringMid: - return data ? format("}%.*s{", length, data) : "the middle of an interpolated string"; - - case InterpStringEnd: - return data ? format("}%.*s`", length, data) : "the end of an interpolated string"; - - case InterpStringSimple: - return data ? format("`%.*s`", length, data) : "interpolated string"; - - case Number: - return data ? format("'%.*s'", length, data) : "number"; - - case Name: - return name ? format("'%s'", name) : "identifier"; - - case Comment: - return "comment"; - - case BrokenString: - return "malformed string"; - - case BrokenComment: - return "unfinished comment"; - - case BrokenInterpDoubleBrace: - return "'{{', which is invalid (did you mean '\\{'?)"; - - case BrokenUnicode: - if (codepoint) - { - if (const char* confusable = findConfusable(codepoint)) - return format("Unicode character U+%x (did you mean '%s'?)", codepoint, confusable); - - return format("Unicode character U+%x", codepoint); - } - else - { - return "invalid UTF-8 sequence"; - } - - default: - if (type < Char_END) - return format("'%c'", type); - else if (type >= Reserved_BEGIN && type < Reserved_END) - return format("'%s'", kReserved[type - Reserved_BEGIN]); - else - return ""; - } -} - -bool AstNameTable::Entry::operator==(const Entry& other) const -{ - return length == other.length && memcmp(value.value, other.value.value, length) == 0; -} - -size_t AstNameTable::EntryHash::operator()(const Entry& e) const -{ - // FNV1a - uint32_t hash = 2166136261; - - for (size_t i = 0; i < e.length; ++i) - { - hash ^= uint8_t(e.value.value[i]); - hash *= 16777619; - } - - return hash; -} - -AstNameTable::AstNameTable(Allocator& allocator) - : data({AstName(""), 0, Lexeme::Eof}, 128) - , allocator(allocator) -{ - static_assert(sizeof(kReserved) / sizeof(kReserved[0]) == Lexeme::Reserved_END - Lexeme::Reserved_BEGIN); - - for (int i = Lexeme::Reserved_BEGIN; i < Lexeme::Reserved_END; ++i) - addStatic(kReserved[i - Lexeme::Reserved_BEGIN], static_cast(i)); -} - -AstName AstNameTable::addStatic(const char* name, Lexeme::Type type) -{ - AstNameTable::Entry entry = {AstName(name), uint32_t(strlen(name)), type}; - - LUAU_ASSERT(!data.contains(entry)); - data.insert(entry); - - return entry.value; -} - -std::pair AstNameTable::getOrAddWithType(const char* name, size_t length) -{ - AstNameTable::Entry key = {AstName(name), uint32_t(length), Lexeme::Eof}; - const Entry& entry = data.insert(key); - - // entry already was inserted - if (entry.type != Lexeme::Eof) - return std::make_pair(entry.value, entry.type); - - // we just inserted an entry with a non-owned pointer into the map - // we need to correct it, *but* we need to be careful about not disturbing the hash value - char* nameData = static_cast(allocator.allocate(length + 1)); - memcpy(nameData, name, length); - nameData[length] = 0; - - const_cast(entry).value = AstName(nameData); - const_cast(entry).type = Lexeme::Name; - - return std::make_pair(entry.value, entry.type); -} - -std::pair AstNameTable::getWithType(const char* name, size_t length) const -{ - if (const Entry* entry = data.find({AstName(name), uint32_t(length), Lexeme::Eof})) - { - return std::make_pair(entry->value, entry->type); - } - return std::make_pair(AstName(), Lexeme::Name); -} - -AstName AstNameTable::getOrAdd(const char* name) -{ - return getOrAddWithType(name, strlen(name)).first; -} - -AstName AstNameTable::get(const char* name) const -{ - return getWithType(name, strlen(name)).first; -} - -inline bool isAlpha(char ch) -{ - // use or trick to convert to lower case and unsigned comparison to do range check - return unsigned((ch | ' ') - 'a') < 26; -} - -inline bool isDigit(char ch) -{ - return unsigned(ch - '0') < 10; -} - -inline bool isHexDigit(char ch) -{ - // use or trick to convert to lower case and unsigned comparison to do range check - return unsigned(ch - '0') < 10 || unsigned((ch | ' ') - 'a') < 6; -} - -inline bool isNewline(char ch) -{ - return ch == '\n'; -} - -static char unescape(char ch) -{ - switch (ch) - { - case 'a': - return '\a'; - case 'b': - return '\b'; - case 'f': - return '\f'; - case 'n': - return '\n'; - case 'r': - return '\r'; - case 't': - return '\t'; - case 'v': - return '\v'; - default: - return ch; - } -} - -Lexer::Lexer(const char* buffer, size_t bufferSize, AstNameTable& names) - : buffer(buffer) - , bufferSize(bufferSize) - , offset(0) - , line(0) - , lineOffset(0) - , lexeme(Location(Position(0, 0), 0), Lexeme::Eof) - , names(names) - , skipComments(false) - , readNames(true) -{ -} - -void Lexer::setSkipComments(bool skip) -{ - skipComments = skip; -} - -void Lexer::setReadNames(bool read) -{ - readNames = read; -} - -const Lexeme& Lexer::next() -{ - return next(this->skipComments, true); -} - -const Lexeme& Lexer::next(bool skipComments, bool updatePrevLocation) -{ - // in skipComments mode we reject valid comments - do - { - // consume whitespace before the token - while (isSpace(peekch())) - consumeAny(); - - if (updatePrevLocation) - prevLocation = lexeme.location; - - lexeme = readNext(); - updatePrevLocation = false; - } while (skipComments && (lexeme.type == Lexeme::Comment || lexeme.type == Lexeme::BlockComment)); - - return lexeme; -} - -void Lexer::nextline() -{ - while (peekch() != 0 && peekch() != '\r' && !isNewline(peekch())) - consume(); - - next(); -} - -Lexeme Lexer::lookahead() -{ - unsigned int currentOffset = offset; - unsigned int currentLine = line; - unsigned int currentLineOffset = lineOffset; - Lexeme currentLexeme = lexeme; - Location currentPrevLocation = prevLocation; - size_t currentBraceStackSize = braceStack.size(); - BraceType currentBraceType = braceStack.empty() ? BraceType::Normal : braceStack.back(); - - Lexeme result = next(); - - offset = currentOffset; - line = currentLine; - lineOffset = currentLineOffset; - lexeme = currentLexeme; - prevLocation = currentPrevLocation; - if (FFlag::LuauLexerLookaheadRemembersBraceType) - { - if (braceStack.size() < currentBraceStackSize) - braceStack.push_back(currentBraceType); - else if (braceStack.size() > currentBraceStackSize) - braceStack.pop_back(); - } - - return result; -} - -bool Lexer::isReserved(const std::string& word) -{ - for (int i = Lexeme::Reserved_BEGIN; i < Lexeme::Reserved_END; ++i) - if (word == kReserved[i - Lexeme::Reserved_BEGIN]) - return true; - - return false; -} - -LUAU_FORCEINLINE -char Lexer::peekch() const -{ - return (offset < bufferSize) ? buffer[offset] : 0; -} - -LUAU_FORCEINLINE -char Lexer::peekch(unsigned int lookahead) const -{ - return (offset + lookahead < bufferSize) ? buffer[offset + lookahead] : 0; -} - -Position Lexer::position() const -{ - return Position(line, offset - lineOffset); -} - -LUAU_FORCEINLINE -void Lexer::consume() -{ - // consume() assumes current character is known to not be a newline; use consumeAny if this is not guaranteed - LUAU_ASSERT(!isNewline(buffer[offset])); - - offset++; -} - -LUAU_FORCEINLINE -void Lexer::consumeAny() -{ - if (isNewline(buffer[offset])) - { - line++; - lineOffset = offset + 1; - } - - offset++; -} - -Lexeme Lexer::readCommentBody() -{ - Position start = position(); - - LUAU_ASSERT(peekch(0) == '-' && peekch(1) == '-'); - consume(); - consume(); - - size_t startOffset = offset; - - if (peekch() == '[') - { - int sep = skipLongSeparator(); - - if (sep >= 0) - { - return readLongString(start, sep, Lexeme::BlockComment, Lexeme::BrokenComment); - } - } - - // fall back to single-line comment - while (peekch() != 0 && peekch() != '\r' && !isNewline(peekch())) - consume(); - - return Lexeme(Location(start, position()), Lexeme::Comment, &buffer[startOffset], offset - startOffset); -} - -// Given a sequence [===[ or ]===], returns: -// 1. number of equal signs (or 0 if none present) between the brackets -// 2. -1 if this is not a long comment/string separator -// 3. -N if this is a malformed separator -// Does *not* consume the closing brace. -int Lexer::skipLongSeparator() -{ - char start = peekch(); - - LUAU_ASSERT(start == '[' || start == ']'); - consume(); - - int count = 0; - - while (peekch() == '=') - { - consume(); - count++; - } - - return (start == peekch()) ? count : (-count) - 1; -} - -Lexeme Lexer::readLongString(const Position& start, int sep, Lexeme::Type ok, Lexeme::Type broken) -{ - // skip (second) [ - LUAU_ASSERT(peekch() == '['); - consume(); - - unsigned int startOffset = offset; - - while (peekch()) - { - if (peekch() == ']') - { - if (skipLongSeparator() == sep) - { - LUAU_ASSERT(peekch() == ']'); - consume(); // skip (second) ] - - unsigned int endOffset = offset - sep - 2; - LUAU_ASSERT(endOffset >= startOffset); - - return Lexeme(Location(start, position()), ok, &buffer[startOffset], endOffset - startOffset); - } - } - else - { - consumeAny(); - } - } - - return Lexeme(Location(start, position()), broken); -} - -void Lexer::readBackslashInString() -{ - LUAU_ASSERT(peekch() == '\\'); - consume(); - switch (peekch()) - { - case '\r': - consume(); - if (peekch() == '\n') - consumeAny(); - break; - - case 0: - break; - - case 'z': - consume(); - while (isSpace(peekch())) - consumeAny(); - break; - - default: - consumeAny(); - } -} - -Lexeme Lexer::readQuotedString() -{ - Position start = position(); - - char delimiter = peekch(); - LUAU_ASSERT(delimiter == '\'' || delimiter == '"'); - consume(); - - unsigned int startOffset = offset; - - while (peekch() != delimiter) - { - switch (peekch()) - { - case 0: - case '\r': - case '\n': - return Lexeme(Location(start, position()), Lexeme::BrokenString); - - case '\\': - readBackslashInString(); - break; - - default: - consume(); - } - } - - consume(); - - return Lexeme(Location(start, position()), Lexeme::QuotedString, &buffer[startOffset], offset - startOffset - 1); -} - -Lexeme Lexer::readInterpolatedStringBegin() -{ - LUAU_ASSERT(peekch() == '`'); - - Position start = position(); - consume(); - - return readInterpolatedStringSection(start, Lexeme::InterpStringBegin, Lexeme::InterpStringSimple); -} - -Lexeme Lexer::readInterpolatedStringSection(Position start, Lexeme::Type formatType, Lexeme::Type endType) -{ - unsigned int startOffset = offset; - - while (peekch() != '`') - { - switch (peekch()) - { - case 0: - case '\r': - case '\n': - return Lexeme(Location(start, position()), Lexeme::BrokenString); - - case '\\': - // Allow for \u{}, which would otherwise be consumed by looking for { - if (peekch(1) == 'u' && peekch(2) == '{') - { - consume(); // backslash - consume(); // u - consume(); // { - break; - } - - readBackslashInString(); - break; - - case '{': - { - braceStack.push_back(BraceType::InterpolatedString); - - if (peekch(1) == '{') - { - Lexeme brokenDoubleBrace = - Lexeme(Location(start, position()), Lexeme::BrokenInterpDoubleBrace, &buffer[startOffset], offset - startOffset); - consume(); - consume(); - return brokenDoubleBrace; - } - - consume(); - return Lexeme(Location(start, position()), formatType, &buffer[startOffset], offset - startOffset - 1); - } - - default: - consume(); - } - } - - consume(); - - return Lexeme(Location(start, position()), endType, &buffer[startOffset], offset - startOffset - 1); -} - -Lexeme Lexer::readNumber(const Position& start, unsigned int startOffset) -{ - LUAU_ASSERT(isDigit(peekch())); - - // This function does not do the number parsing - it only skips a number-like pattern. - // It uses the same logic as Lua stock lexer; the resulting string is later converted - // to a number with proper verification. - do - { - consume(); - } while (isDigit(peekch()) || peekch() == '.' || peekch() == '_'); - - if (peekch() == 'e' || peekch() == 'E') - { - consume(); - - if (peekch() == '+' || peekch() == '-') - consume(); - } - - while (isAlpha(peekch()) || isDigit(peekch()) || peekch() == '_') - consume(); - - return Lexeme(Location(start, position()), Lexeme::Number, &buffer[startOffset], offset - startOffset); -} - -std::pair Lexer::readName() -{ - LUAU_ASSERT(isAlpha(peekch()) || peekch() == '_' || peekch() == '@'); - - unsigned int startOffset = offset; - - do - consume(); - while (isAlpha(peekch()) || isDigit(peekch()) || peekch() == '_'); - - return readNames ? names.getOrAddWithType(&buffer[startOffset], offset - startOffset) - : names.getWithType(&buffer[startOffset], offset - startOffset); -} - -Lexeme Lexer::readNext() -{ - Position start = position(); - - switch (peekch()) - { - case 0: - return Lexeme(Location(start, 0), Lexeme::Eof); - - case '-': - { - if (peekch(1) == '>') - { - consume(); - consume(); - return Lexeme(Location(start, 2), Lexeme::SkinnyArrow); - } - else if (peekch(1) == '=') - { - consume(); - consume(); - return Lexeme(Location(start, 2), Lexeme::SubAssign); - } - else if (peekch(1) == '-') - { - return readCommentBody(); - } - else - { - consume(); - return Lexeme(Location(start, 1), '-'); - } - } - - case '[': - { - int sep = skipLongSeparator(); - - if (sep >= 0) - { - return readLongString(start, sep, Lexeme::RawString, Lexeme::BrokenString); - } - else if (sep == -1) - { - return Lexeme(Location(start, 1), '['); - } - else - { - return Lexeme(Location(start, position()), Lexeme::BrokenString); - } - } - - case '{': - { - consume(); - - if (!braceStack.empty()) - braceStack.push_back(BraceType::Normal); - - return Lexeme(Location(start, 1), '{'); - } - - case '}': - { - consume(); - - if (braceStack.empty()) - { - return Lexeme(Location(start, 1), '}'); - } - - const BraceType braceStackTop = braceStack.back(); - braceStack.pop_back(); - - if (braceStackTop != BraceType::InterpolatedString) - { - return Lexeme(Location(start, 1), '}'); - } - - return readInterpolatedStringSection(position(), Lexeme::InterpStringMid, Lexeme::InterpStringEnd); - } - - case '=': - { - consume(); - - if (peekch() == '=') - { - consume(); - return Lexeme(Location(start, 2), Lexeme::Equal); - } - else - return Lexeme(Location(start, 1), '='); - } - - case '<': - { - consume(); - - if (peekch() == '=') - { - consume(); - return Lexeme(Location(start, 2), Lexeme::LessEqual); - } - else - return Lexeme(Location(start, 1), '<'); - } - - case '>': - { - consume(); - - if (peekch() == '=') - { - consume(); - return Lexeme(Location(start, 2), Lexeme::GreaterEqual); - } - else - return Lexeme(Location(start, 1), '>'); - } - - case '~': - { - consume(); - - if (peekch() == '=') - { - consume(); - return Lexeme(Location(start, 2), Lexeme::NotEqual); - } - else - return Lexeme(Location(start, 1), '~'); - } - - case '"': - case '\'': - return readQuotedString(); - - case '`': - return readInterpolatedStringBegin(); - - case '.': - consume(); - - if (peekch() == '.') - { - consume(); - - if (peekch() == '.') - { - consume(); - - return Lexeme(Location(start, 3), Lexeme::Dot3); - } - else if (peekch() == '=') - { - consume(); - - return Lexeme(Location(start, 3), Lexeme::ConcatAssign); - } - else - return Lexeme(Location(start, 2), Lexeme::Dot2); - } - else - { - if (isDigit(peekch())) - { - return readNumber(start, offset - 1); - } - else - return Lexeme(Location(start, 1), '.'); - } - - case '+': - consume(); - - if (peekch() == '=') - { - consume(); - return Lexeme(Location(start, 2), Lexeme::AddAssign); - } - else - return Lexeme(Location(start, 1), '+'); - - case '/': - { - consume(); - - char ch = peekch(); - - if (ch == '=') - { - consume(); - return Lexeme(Location(start, 2), Lexeme::DivAssign); - } - else if (ch == '/') - { - consume(); - - if (peekch() == '=') - { - consume(); - return Lexeme(Location(start, 3), Lexeme::FloorDivAssign); - } - else - return Lexeme(Location(start, 2), Lexeme::FloorDiv); - } - else - return Lexeme(Location(start, 1), '/'); - } - - case '*': - consume(); - - if (peekch() == '=') - { - consume(); - return Lexeme(Location(start, 2), Lexeme::MulAssign); - } - else - return Lexeme(Location(start, 1), '*'); - - case '%': - consume(); - - if (peekch() == '=') - { - consume(); - return Lexeme(Location(start, 2), Lexeme::ModAssign); - } - else - return Lexeme(Location(start, 1), '%'); - - case '^': - consume(); - - if (peekch() == '=') - { - consume(); - return Lexeme(Location(start, 2), Lexeme::PowAssign); - } - else - return Lexeme(Location(start, 1), '^'); - - case ':': - { - consume(); - if (peekch() == ':') - { - consume(); - return Lexeme(Location(start, 2), Lexeme::DoubleColon); - } - else - return Lexeme(Location(start, 1), ':'); - } - - case '(': - case ')': - case ']': - case ';': - case ',': - case '#': - case '?': - case '&': - case '|': - { - char ch = peekch(); - consume(); - - return Lexeme(Location(start, 1), ch); - } - case '@': - { - if (FFlag::LuauCheckedFunctionSyntax) - { - // We're trying to lex the token @checked - LUAU_ASSERT(peekch() == '@'); - - std::pair maybeChecked = readName(); - if (maybeChecked.second != Lexeme::ReservedChecked) - return Lexeme(Location(start, position()), Lexeme::Error); - - return Lexeme(Location(start, position()), maybeChecked.second, maybeChecked.first.value); - } - } - default: - if (isDigit(peekch())) - { - return readNumber(start, offset); - } - else if (isAlpha(peekch()) || peekch() == '_') - { - std::pair name = readName(); - - return Lexeme(Location(start, position()), name.second, name.first.value); - } - else if (peekch() & 0x80) - { - return readUtf8Error(); - } - else - { - char ch = peekch(); - consume(); - - return Lexeme(Location(start, 1), ch); - } - } -} - -LUAU_NOINLINE Lexeme Lexer::readUtf8Error() -{ - Position start = position(); - uint32_t codepoint = 0; - int size = 0; - - if ((peekch() & 0b10000000) == 0b00000000) - { - size = 1; - codepoint = peekch() & 0x7F; - } - else if ((peekch() & 0b11100000) == 0b11000000) - { - size = 2; - codepoint = peekch() & 0b11111; - } - else if ((peekch() & 0b11110000) == 0b11100000) - { - size = 3; - codepoint = peekch() & 0b1111; - } - else if ((peekch() & 0b11111000) == 0b11110000) - { - size = 4; - codepoint = peekch() & 0b111; - } - else - { - consume(); - return Lexeme(Location(start, position()), Lexeme::BrokenUnicode); - } - - consume(); - - for (int i = 1; i < size; ++i) - { - if ((peekch() & 0b11000000) != 0b10000000) - return Lexeme(Location(start, position()), Lexeme::BrokenUnicode); - - codepoint = codepoint << 6; - codepoint |= (peekch() & 0b00111111); - consume(); - } - - Lexeme result(Location(start, position()), Lexeme::BrokenUnicode); - result.codepoint = codepoint; - return result; -} - -static size_t toUtf8(char* data, unsigned int code) -{ - // U+0000..U+007F - if (code < 0x80) - { - data[0] = char(code); - return 1; - } - // U+0080..U+07FF - else if (code < 0x800) - { - data[0] = char(0xC0 | (code >> 6)); - data[1] = char(0x80 | (code & 0x3F)); - return 2; - } - // U+0800..U+FFFF - else if (code < 0x10000) - { - data[0] = char(0xE0 | (code >> 12)); - data[1] = char(0x80 | ((code >> 6) & 0x3F)); - data[2] = char(0x80 | (code & 0x3F)); - return 3; - } - // U+10000..U+10FFFF - else if (code < 0x110000) - { - data[0] = char(0xF0 | (code >> 18)); - data[1] = char(0x80 | ((code >> 12) & 0x3F)); - data[2] = char(0x80 | ((code >> 6) & 0x3F)); - data[3] = char(0x80 | (code & 0x3F)); - return 4; - } - else - { - return 0; - } -} - -bool Lexer::fixupQuotedString(std::string& data) -{ - if (data.empty() || data.find('\\') == std::string::npos) - return true; - - size_t size = data.size(); - size_t write = 0; - - for (size_t i = 0; i < size;) - { - if (data[i] != '\\') - { - data[write++] = data[i]; - i++; - continue; - } - - if (i + 1 == size) - return false; - - char escape = data[i + 1]; - i += 2; // skip \e - - switch (escape) - { - case '\n': - data[write++] = '\n'; - break; - - case '\r': - data[write++] = '\n'; - if (i < size && data[i] == '\n') - i++; - break; - - case 0: - return false; - - case 'x': - { - // hex escape codes are exactly 2 hex digits long - if (i + 2 > size) - return false; - - unsigned int code = 0; - - for (int j = 0; j < 2; ++j) - { - char ch = data[i + j]; - if (!isHexDigit(ch)) - return false; - - // use or trick to convert to lower case - code = 16 * code + (isDigit(ch) ? ch - '0' : (ch | ' ') - 'a' + 10); - } - - data[write++] = char(code); - i += 2; - break; - } - - case 'z': - { - while (i < size && isSpace(data[i])) - i++; - break; - } - - case 'u': - { - // unicode escape codes are at least 3 characters including braces - if (i + 3 > size) - return false; - - if (data[i] != '{') - return false; - i++; - - if (data[i] == '}') - return false; - - unsigned int code = 0; - - for (int j = 0; j < 16; ++j) - { - if (i == size) - return false; - - char ch = data[i]; - - if (ch == '}') - break; - - if (!isHexDigit(ch)) - return false; - - // use or trick to convert to lower case - code = 16 * code + (isDigit(ch) ? ch - '0' : (ch | ' ') - 'a' + 10); - i++; - } - - if (i == size || data[i] != '}') - return false; - i++; - - size_t utf8 = toUtf8(&data[write], code); - if (utf8 == 0) - return false; - - write += utf8; - break; - } - - default: - { - if (isDigit(escape)) - { - unsigned int code = escape - '0'; - - for (int j = 0; j < 2; ++j) - { - if (i == size || !isDigit(data[i])) - break; - - code = 10 * code + (data[i] - '0'); - i++; - } - - if (code > UCHAR_MAX) - return false; - - data[write++] = char(code); - } - else - { - data[write++] = unescape(escape); - } - } - } - } - - LUAU_ASSERT(write <= size); - data.resize(write); - - return true; -} - -void Lexer::fixupMultilineString(std::string& data) -{ - if (data.empty()) - return; - - // Lua rules for multiline strings are as follows: - // - standalone \r, \r\n, \n\r and \n are all considered newlines - // - first newline in the multiline string is skipped - // - all other newlines are normalized to \n - - // Since our lexer just treats \n as newlines, we apply a simplified set of rules that is sufficient to get normalized newlines for Windows/Unix: - // - \r\n and \n are considered newlines - // - first newline is skipped - // - newlines are normalized to \n - - // This makes the string parsing behavior consistent with general lexing behavior - a standalone \r isn't considered a new line from the line - // tracking perspective - - const char* src = data.c_str(); - char* dst = &data[0]; - - // skip leading newline - if (src[0] == '\r' && src[1] == '\n') - { - src += 2; - } - else if (src[0] == '\n') - { - src += 1; - } - - // parse the rest of the string, converting newlines as we go - while (*src) - { - if (src[0] == '\r' && src[1] == '\n') - { - *dst++ = '\n'; - src += 2; - } - else // note, this handles \n by just writing it without changes - { - *dst++ = *src; - src += 1; - } - } - - data.resize(dst - &data[0]); -} - -} // namespace Luau diff --git a/lib/luau/Ast/src/Location.cpp b/lib/luau/Ast/src/Location.cpp deleted file mode 100644 index c2c66d9..0000000 --- a/lib/luau/Ast/src/Location.cpp +++ /dev/null @@ -1,101 +0,0 @@ -// This file is part of the Luau programming language and is licensed under MIT License; see LICENSE.txt for details -#include "Luau/Location.h" - -namespace Luau -{ - -bool Position::operator==(const Position& rhs) const -{ - return this->column == rhs.column && this->line == rhs.line; -} - -bool Position::operator!=(const Position& rhs) const -{ - return !(*this == rhs); -} - -bool Position::operator<(const Position& rhs) const -{ - if (line == rhs.line) - return column < rhs.column; - else - return line < rhs.line; -} - -bool Position::operator>(const Position& rhs) const -{ - if (line == rhs.line) - return column > rhs.column; - else - return line > rhs.line; -} - -bool Position::operator<=(const Position& rhs) const -{ - return *this == rhs || *this < rhs; -} - -bool Position::operator>=(const Position& rhs) const -{ - return *this == rhs || *this > rhs; -} - -void Position::shift(const Position& start, const Position& oldEnd, const Position& newEnd) -{ - if (*this >= start) - { - if (this->line > oldEnd.line) - this->line += (newEnd.line - oldEnd.line); - else - { - this->line = newEnd.line; - this->column += (newEnd.column - oldEnd.column); - } - } -} - -bool Location::operator==(const Location& rhs) const -{ - return this->begin == rhs.begin && this->end == rhs.end; -} - -bool Location::operator!=(const Location& rhs) const -{ - return !(*this == rhs); -} - -bool Location::encloses(const Location& l) const -{ - return begin <= l.begin && end >= l.end; -} - -bool Location::overlaps(const Location& l) const -{ - return (begin <= l.begin && end >= l.begin) || (begin <= l.end && end >= l.end) || (begin >= l.begin && end <= l.end); -} - -bool Location::contains(const Position& p) const -{ - return begin <= p && p < end; -} - -bool Location::containsClosed(const Position& p) const -{ - return begin <= p && p <= end; -} - -void Location::extend(const Location& other) -{ - if (other.begin < begin) - begin = other.begin; - if (other.end > end) - end = other.end; -} - -void Location::shift(const Position& start, const Position& oldEnd, const Position& newEnd) -{ - begin.shift(start, oldEnd, newEnd); - end.shift(start, oldEnd, newEnd); -} - -} // namespace Luau diff --git a/lib/luau/Ast/src/Parser.cpp b/lib/luau/Ast/src/Parser.cpp deleted file mode 100644 index e4b840b..0000000 --- a/lib/luau/Ast/src/Parser.cpp +++ /dev/null @@ -1,3154 +0,0 @@ -// This file is part of the Luau programming language and is licensed under MIT License; see LICENSE.txt for details -#include "Luau/Parser.h" - -#include "Luau/Common.h" -#include "Luau/TimeTrace.h" - -#include - -#include -#include - -LUAU_FASTINTVARIABLE(LuauRecursionLimit, 1000) -LUAU_FASTINTVARIABLE(LuauTypeLengthLimit, 1000) -LUAU_FASTINTVARIABLE(LuauParseErrorLimit, 100) - -// Warning: If you are introducing new syntax, ensure that it is behind a separate -// flag so that we don't break production games by reverting syntax changes. -// See docs/SyntaxChanges.md for an explanation. -LUAU_FASTFLAGVARIABLE(LuauClipExtraHasEndProps, false) -LUAU_FASTFLAG(LuauCheckedFunctionSyntax) - -namespace Luau -{ - -ParseError::ParseError(const Location& location, const std::string& message) - : location(location) - , message(message) -{ -} - -const char* ParseError::what() const throw() -{ - return message.c_str(); -} - -const Location& ParseError::getLocation() const -{ - return location; -} - -const std::string& ParseError::getMessage() const -{ - return message; -} - -// LUAU_NOINLINE is used to limit the stack cost of this function due to std::string object / exception plumbing -LUAU_NOINLINE void ParseError::raise(const Location& location, const char* format, ...) -{ - va_list args; - va_start(args, format); - std::string message = vformat(format, args); - va_end(args); - - throw ParseError(location, message); -} - -ParseErrors::ParseErrors(std::vector errors) - : errors(std::move(errors)) -{ - LUAU_ASSERT(!this->errors.empty()); - - if (this->errors.size() == 1) - message = this->errors.front().what(); - else - message = format("%d parse errors", int(this->errors.size())); -} - -const char* ParseErrors::what() const throw() -{ - return message.c_str(); -} - -const std::vector& ParseErrors::getErrors() const -{ - return errors; -} - -template -TempVector::TempVector(std::vector& storage) - : storage(storage) - , offset(storage.size()) - , size_(0) -{ -} - -template -TempVector::~TempVector() -{ - LUAU_ASSERT(storage.size() == offset + size_); - storage.erase(storage.begin() + offset, storage.end()); -} - -template -const T& TempVector::operator[](size_t index) const -{ - LUAU_ASSERT(index < size_); - return storage[offset + index]; -} - -template -const T& TempVector::front() const -{ - LUAU_ASSERT(size_ > 0); - return storage[offset]; -} - -template -const T& TempVector::back() const -{ - LUAU_ASSERT(size_ > 0); - return storage.back(); -} - -template -bool TempVector::empty() const -{ - return size_ == 0; -} - -template -size_t TempVector::size() const -{ - return size_; -} - -template -void TempVector::push_back(const T& item) -{ - LUAU_ASSERT(storage.size() == offset + size_); - storage.push_back(item); - size_++; -} - -static bool shouldParseTypePack(Lexer& lexer) -{ - if (lexer.current().type == Lexeme::Dot3) - return true; - else if (lexer.current().type == Lexeme::Name && lexer.lookahead().type == Lexeme::Dot3) - return true; - - return false; -} - -ParseResult Parser::parse(const char* buffer, size_t bufferSize, AstNameTable& names, Allocator& allocator, ParseOptions options) -{ - LUAU_TIMETRACE_SCOPE("Parser::parse", "Parser"); - - Parser p(buffer, bufferSize, names, allocator, options); - - try - { - AstStatBlock* root = p.parseChunk(); - size_t lines = p.lexer.current().location.end.line + (bufferSize > 0 && buffer[bufferSize - 1] != '\n'); - - return ParseResult{root, lines, std::move(p.hotcomments), std::move(p.parseErrors), std::move(p.commentLocations)}; - } - catch (ParseError& err) - { - // when catching a fatal error, append it to the list of non-fatal errors and return - p.parseErrors.push_back(err); - - return ParseResult{nullptr, 0, {}, p.parseErrors}; - } -} - -Parser::Parser(const char* buffer, size_t bufferSize, AstNameTable& names, Allocator& allocator, const ParseOptions& options) - : options(options) - , lexer(buffer, bufferSize, names) - , allocator(allocator) - , recursionCounter(0) - , endMismatchSuspect(Lexeme(Location(), Lexeme::Eof)) - , localMap(AstName()) -{ - Function top; - top.vararg = true; - - functionStack.reserve(8); - functionStack.push_back(top); - - nameSelf = names.addStatic("self"); - nameNumber = names.addStatic("number"); - nameError = names.addStatic(kParseNameError); - nameNil = names.getOrAdd("nil"); // nil is a reserved keyword - - matchRecoveryStopOnToken.assign(Lexeme::Type::Reserved_END, 0); - matchRecoveryStopOnToken[Lexeme::Type::Eof] = 1; - - // required for lookahead() to work across a comment boundary and for nextLexeme() to work when captureComments is false - lexer.setSkipComments(true); - - // read first lexeme (any hot comments get .header = true) - LUAU_ASSERT(hotcommentHeader); - nextLexeme(); - - // all hot comments parsed after the first non-comment lexeme are special in that they don't affect type checking / linting mode - hotcommentHeader = false; - - // preallocate some buffers that are very likely to grow anyway; this works around std::vector's inefficient growth policy for small arrays - localStack.reserve(16); - scratchStat.reserve(16); - scratchExpr.reserve(16); - scratchLocal.reserve(16); - scratchBinding.reserve(16); -} - -bool Parser::blockFollow(const Lexeme& l) -{ - return l.type == Lexeme::Eof || l.type == Lexeme::ReservedElse || l.type == Lexeme::ReservedElseif || l.type == Lexeme::ReservedEnd || - l.type == Lexeme::ReservedUntil; -} - -AstStatBlock* Parser::parseChunk() -{ - AstStatBlock* result = parseBlock(); - - if (lexer.current().type != Lexeme::Eof) - expectAndConsumeFail(Lexeme::Eof, nullptr); - - return result; -} - -// chunk ::= {stat [`;']} [laststat [`;']] -// block ::= chunk -AstStatBlock* Parser::parseBlock() -{ - unsigned int localsBegin = saveLocals(); - - AstStatBlock* result = parseBlockNoScope(); - - restoreLocals(localsBegin); - - return result; -} - -static bool isStatLast(AstStat* stat) -{ - return stat->is() || stat->is() || stat->is(); -} - -AstStatBlock* Parser::parseBlockNoScope() -{ - TempVector body(scratchStat); - - const Position prevPosition = lexer.previousLocation().end; - - while (!blockFollow(lexer.current())) - { - unsigned int oldRecursionCount = recursionCounter; - - incrementRecursionCounter("block"); - - AstStat* stat = parseStat(); - - recursionCounter = oldRecursionCount; - - if (lexer.current().type == ';') - { - nextLexeme(); - stat->hasSemicolon = true; - } - - body.push_back(stat); - - if (isStatLast(stat)) - break; - } - - const Location location = Location(prevPosition, lexer.current().location.begin); - - return allocator.alloc(location, copy(body)); -} - -// stat ::= -// varlist `=' explist | -// functioncall | -// do block end | -// while exp do block end | -// repeat block until exp | -// if exp then block {elseif exp then block} [else block] end | -// for binding `=' exp `,' exp [`,' exp] do block end | -// for namelist in explist do block end | -// function funcname funcbody | -// local function Name funcbody | -// local namelist [`=' explist] -// laststat ::= return [explist] | break -AstStat* Parser::parseStat() -{ - // guess the type from the token type - switch (lexer.current().type) - { - case Lexeme::ReservedIf: - return parseIf(); - case Lexeme::ReservedWhile: - return parseWhile(); - case Lexeme::ReservedDo: - return parseDo(); - case Lexeme::ReservedFor: - return parseFor(); - case Lexeme::ReservedRepeat: - return parseRepeat(); - case Lexeme::ReservedFunction: - return parseFunctionStat(); - case Lexeme::ReservedLocal: - return parseLocal(); - case Lexeme::ReservedReturn: - return parseReturn(); - case Lexeme::ReservedBreak: - return parseBreak(); - default:; - } - - Location start = lexer.current().location; - - // we need to disambiguate a few cases, primarily assignment (lvalue = ...) vs statements-that-are calls - AstExpr* expr = parsePrimaryExpr(/* asStatement= */ true); - - if (expr->is()) - return allocator.alloc(expr->location, expr); - - // if the next token is , or =, it's an assignment (, means it's an assignment with multiple variables) - if (lexer.current().type == ',' || lexer.current().type == '=') - return parseAssignment(expr); - - // if the next token is a compound assignment operator, it's a compound assignment (these don't support multiple variables) - if (std::optional op = parseCompoundOp(lexer.current())) - return parseCompoundAssignment(expr, *op); - - // we know this isn't a call or an assignment; therefore it must be a context-sensitive keyword such as `type` or `continue` - AstName ident = getIdentifier(expr); - - if (ident == "type") - return parseTypeAlias(expr->location, /* exported= */ false); - - if (ident == "export" && lexer.current().type == Lexeme::Name && AstName(lexer.current().name) == "type") - { - nextLexeme(); - return parseTypeAlias(expr->location, /* exported= */ true); - } - - if (ident == "continue") - return parseContinue(expr->location); - - if (options.allowDeclarationSyntax) - { - if (ident == "declare") - return parseDeclaration(expr->location); - } - - // skip unexpected symbol if lexer couldn't advance at all (statements are parsed in a loop) - if (start == lexer.current().location) - nextLexeme(); - - return reportStatError(expr->location, copy({expr}), {}, "Incomplete statement: expected assignment or a function call"); -} - -// if exp then block {elseif exp then block} [else block] end -AstStat* Parser::parseIf() -{ - Location start = lexer.current().location; - - nextLexeme(); // if / elseif - - AstExpr* cond = parseExpr(); - - Lexeme matchThen = lexer.current(); - std::optional thenLocation; - if (expectAndConsume(Lexeme::ReservedThen, "if statement")) - thenLocation = matchThen.location; - - AstStatBlock* thenbody = parseBlock(); - - AstStat* elsebody = nullptr; - Location end = start; - std::optional elseLocation; - bool DEPRECATED_hasEnd = false; - - if (lexer.current().type == Lexeme::ReservedElseif) - { - if (FFlag::LuauClipExtraHasEndProps) - thenbody->hasEnd = true; - unsigned int oldRecursionCount = recursionCounter; - incrementRecursionCounter("elseif"); - elseLocation = lexer.current().location; - elsebody = parseIf(); - end = elsebody->location; - DEPRECATED_hasEnd = elsebody->as()->DEPRECATED_hasEnd; - recursionCounter = oldRecursionCount; - } - else - { - Lexeme matchThenElse = matchThen; - - if (lexer.current().type == Lexeme::ReservedElse) - { - if (FFlag::LuauClipExtraHasEndProps) - thenbody->hasEnd = true; - elseLocation = lexer.current().location; - matchThenElse = lexer.current(); - nextLexeme(); - - elsebody = parseBlock(); - elsebody->location.begin = matchThenElse.location.end; - } - - end = lexer.current().location; - - bool hasEnd = expectMatchEndAndConsume(Lexeme::ReservedEnd, matchThenElse); - DEPRECATED_hasEnd = hasEnd; - - if (FFlag::LuauClipExtraHasEndProps) - { - if (elsebody) - { - if (AstStatBlock* elseBlock = elsebody->as()) - elseBlock->hasEnd = hasEnd; - } - else - thenbody->hasEnd = hasEnd; - } - } - - return allocator.alloc(Location(start, end), cond, thenbody, elsebody, thenLocation, elseLocation, DEPRECATED_hasEnd); -} - -// while exp do block end -AstStat* Parser::parseWhile() -{ - Location start = lexer.current().location; - - nextLexeme(); // while - - AstExpr* cond = parseExpr(); - - Lexeme matchDo = lexer.current(); - bool hasDo = expectAndConsume(Lexeme::ReservedDo, "while loop"); - - functionStack.back().loopDepth++; - - AstStatBlock* body = parseBlock(); - - functionStack.back().loopDepth--; - - Location end = lexer.current().location; - - bool hasEnd = expectMatchEndAndConsume(Lexeme::ReservedEnd, matchDo); - if (FFlag::LuauClipExtraHasEndProps) - body->hasEnd = hasEnd; - - return allocator.alloc(Location(start, end), cond, body, hasDo, matchDo.location, hasEnd); -} - -// repeat block until exp -AstStat* Parser::parseRepeat() -{ - Location start = lexer.current().location; - - Lexeme matchRepeat = lexer.current(); - nextLexeme(); // repeat - - unsigned int localsBegin = saveLocals(); - - functionStack.back().loopDepth++; - - AstStatBlock* body = parseBlockNoScope(); - - functionStack.back().loopDepth--; - - bool hasUntil = expectMatchEndAndConsume(Lexeme::ReservedUntil, matchRepeat); - if (FFlag::LuauClipExtraHasEndProps) - body->hasEnd = hasUntil; - - AstExpr* cond = parseExpr(); - - restoreLocals(localsBegin); - - return allocator.alloc(Location(start, cond->location), cond, body, hasUntil); -} - -// do block end -AstStat* Parser::parseDo() -{ - Location start = lexer.current().location; - - Lexeme matchDo = lexer.current(); - nextLexeme(); // do - - AstStatBlock* body = parseBlock(); - - body->location.begin = start.begin; - - body->hasEnd = expectMatchEndAndConsume(Lexeme::ReservedEnd, matchDo); - - return body; -} - -// break -AstStat* Parser::parseBreak() -{ - Location start = lexer.current().location; - - nextLexeme(); // break - - if (functionStack.back().loopDepth == 0) - return reportStatError(start, {}, copy({allocator.alloc(start)}), "break statement must be inside a loop"); - - return allocator.alloc(start); -} - -// continue -AstStat* Parser::parseContinue(const Location& start) -{ - if (functionStack.back().loopDepth == 0) - return reportStatError(start, {}, copy({allocator.alloc(start)}), "continue statement must be inside a loop"); - - // note: the token is already parsed for us! - - return allocator.alloc(start); -} - -// for binding `=' exp `,' exp [`,' exp] do block end | -// for bindinglist in explist do block end | -AstStat* Parser::parseFor() -{ - Location start = lexer.current().location; - - nextLexeme(); // for - - Binding varname = parseBinding(); - - if (lexer.current().type == '=') - { - nextLexeme(); - - AstExpr* from = parseExpr(); - - expectAndConsume(',', "index range"); - - AstExpr* to = parseExpr(); - - AstExpr* step = nullptr; - - if (lexer.current().type == ',') - { - nextLexeme(); - - step = parseExpr(); - } - - Lexeme matchDo = lexer.current(); - bool hasDo = expectAndConsume(Lexeme::ReservedDo, "for loop"); - - unsigned int localsBegin = saveLocals(); - - functionStack.back().loopDepth++; - - AstLocal* var = pushLocal(varname); - - AstStatBlock* body = parseBlock(); - - functionStack.back().loopDepth--; - - restoreLocals(localsBegin); - - Location end = lexer.current().location; - - bool hasEnd = expectMatchEndAndConsume(Lexeme::ReservedEnd, matchDo); - if (FFlag::LuauClipExtraHasEndProps) - body->hasEnd = hasEnd; - - return allocator.alloc(Location(start, end), var, from, to, step, body, hasDo, matchDo.location, hasEnd); - } - else - { - TempVector names(scratchBinding); - names.push_back(varname); - - if (lexer.current().type == ',') - { - nextLexeme(); - - parseBindingList(names); - } - - Location inLocation = lexer.current().location; - bool hasIn = expectAndConsume(Lexeme::ReservedIn, "for loop"); - - TempVector values(scratchExpr); - parseExprList(values); - - Lexeme matchDo = lexer.current(); - bool hasDo = expectAndConsume(Lexeme::ReservedDo, "for loop"); - - unsigned int localsBegin = saveLocals(); - - functionStack.back().loopDepth++; - - TempVector vars(scratchLocal); - - for (size_t i = 0; i < names.size(); ++i) - vars.push_back(pushLocal(names[i])); - - AstStatBlock* body = parseBlock(); - - functionStack.back().loopDepth--; - - restoreLocals(localsBegin); - - Location end = lexer.current().location; - - bool hasEnd = expectMatchEndAndConsume(Lexeme::ReservedEnd, matchDo); - if (FFlag::LuauClipExtraHasEndProps) - body->hasEnd = hasEnd; - - return allocator.alloc( - Location(start, end), copy(vars), copy(values), body, hasIn, inLocation, hasDo, matchDo.location, hasEnd); - } -} - -// funcname ::= Name {`.' Name} [`:' Name] -AstExpr* Parser::parseFunctionName(Location start, bool& hasself, AstName& debugname) -{ - if (lexer.current().type == Lexeme::Name) - debugname = AstName(lexer.current().name); - - // parse funcname into a chain of indexing operators - AstExpr* expr = parseNameExpr("function name"); - - unsigned int oldRecursionCount = recursionCounter; - - while (lexer.current().type == '.') - { - Position opPosition = lexer.current().location.begin; - nextLexeme(); - - Name name = parseName("field name"); - - // while we could concatenate the name chain, for now let's just write the short name - debugname = name.name; - - expr = allocator.alloc(Location(start, name.location), expr, name.name, name.location, opPosition, '.'); - - // note: while the parser isn't recursive here, we're generating recursive structures of unbounded depth - incrementRecursionCounter("function name"); - } - - recursionCounter = oldRecursionCount; - - // finish with : - if (lexer.current().type == ':') - { - Position opPosition = lexer.current().location.begin; - nextLexeme(); - - Name name = parseName("method name"); - - // while we could concatenate the name chain, for now let's just write the short name - debugname = name.name; - - expr = allocator.alloc(Location(start, name.location), expr, name.name, name.location, opPosition, ':'); - - hasself = true; - } - - return expr; -} - -// function funcname funcbody -AstStat* Parser::parseFunctionStat() -{ - Location start = lexer.current().location; - - Lexeme matchFunction = lexer.current(); - nextLexeme(); - - bool hasself = false; - AstName debugname; - AstExpr* expr = parseFunctionName(start, hasself, debugname); - - matchRecoveryStopOnToken[Lexeme::ReservedEnd]++; - - AstExprFunction* body = parseFunctionBody(hasself, matchFunction, debugname, nullptr).first; - - matchRecoveryStopOnToken[Lexeme::ReservedEnd]--; - - return allocator.alloc(Location(start, body->location), expr, body); -} - -// local function Name funcbody | -// local bindinglist [`=' explist] -AstStat* Parser::parseLocal() -{ - Location start = lexer.current().location; - - nextLexeme(); // local - - if (lexer.current().type == Lexeme::ReservedFunction) - { - Lexeme matchFunction = lexer.current(); - nextLexeme(); - - // matchFunction is only used for diagnostics; to make it suitable for detecting missed indentation between - // `local function` and `end`, we patch the token to begin at the column where `local` starts - if (matchFunction.location.begin.line == start.begin.line) - matchFunction.location.begin.column = start.begin.column; - - Name name = parseName("variable name"); - - matchRecoveryStopOnToken[Lexeme::ReservedEnd]++; - - auto [body, var] = parseFunctionBody(false, matchFunction, name.name, &name); - - matchRecoveryStopOnToken[Lexeme::ReservedEnd]--; - - Location location{start.begin, body->location.end}; - - return allocator.alloc(location, var, body); - } - else - { - matchRecoveryStopOnToken['=']++; - - TempVector names(scratchBinding); - parseBindingList(names); - - matchRecoveryStopOnToken['=']--; - - TempVector vars(scratchLocal); - - TempVector values(scratchExpr); - - std::optional equalsSignLocation; - - if (lexer.current().type == '=') - { - equalsSignLocation = lexer.current().location; - - nextLexeme(); - - parseExprList(values); - } - - for (size_t i = 0; i < names.size(); ++i) - vars.push_back(pushLocal(names[i])); - - Location end = values.empty() ? lexer.previousLocation() : values.back()->location; - - return allocator.alloc(Location(start, end), copy(vars), copy(values), equalsSignLocation); - } -} - -// return [explist] -AstStat* Parser::parseReturn() -{ - Location start = lexer.current().location; - - nextLexeme(); - - TempVector list(scratchExpr); - - if (!blockFollow(lexer.current()) && lexer.current().type != ';') - parseExprList(list); - - Location end = list.empty() ? start : list.back()->location; - - return allocator.alloc(Location(start, end), copy(list)); -} - -// type Name [`<' varlist `>'] `=' Type -AstStat* Parser::parseTypeAlias(const Location& start, bool exported) -{ - // note: `type` token is already parsed for us, so we just need to parse the rest - - std::optional name = parseNameOpt("type name"); - - // Use error name if the name is missing - if (!name) - name = Name(nameError, lexer.current().location); - - auto [generics, genericPacks] = parseGenericTypeList(/* withDefaultValues= */ true); - - expectAndConsume('=', "type alias"); - - AstType* type = parseType(); - - return allocator.alloc(Location(start, type->location), name->name, name->location, generics, genericPacks, type, exported); -} - -AstDeclaredClassProp Parser::parseDeclaredClassMethod() -{ - nextLexeme(); - Location start = lexer.current().location; - Name fnName = parseName("function name"); - - // TODO: generic method declarations CLI-39909 - AstArray generics; - AstArray genericPacks; - generics.size = 0; - generics.data = nullptr; - genericPacks.size = 0; - genericPacks.data = nullptr; - - MatchLexeme matchParen = lexer.current(); - expectAndConsume('(', "function parameter list start"); - - TempVector args(scratchBinding); - - bool vararg = false; - Location varargLocation; - AstTypePack* varargAnnotation = nullptr; - if (lexer.current().type != ')') - std::tie(vararg, varargLocation, varargAnnotation) = parseBindingList(args, /* allowDot3 */ true); - - expectMatchAndConsume(')', matchParen); - - AstTypeList retTypes = parseOptionalReturnType().value_or(AstTypeList{copy(nullptr, 0), nullptr}); - Location end = lexer.current().location; - - TempVector vars(scratchType); - TempVector> varNames(scratchOptArgName); - - if (args.size() == 0 || args[0].name.name != "self" || args[0].annotation != nullptr) - { - return AstDeclaredClassProp{ - fnName.name, reportTypeError(Location(start, end), {}, "'self' must be present as the unannotated first parameter"), true}; - } - - // Skip the first index. - for (size_t i = 1; i < args.size(); ++i) - { - varNames.push_back(AstArgumentName{args[i].name.name, args[i].name.location}); - - if (args[i].annotation) - vars.push_back(args[i].annotation); - else - vars.push_back(reportTypeError(Location(start, end), {}, "All declaration parameters aside from 'self' must be annotated")); - } - - if (vararg && !varargAnnotation) - report(start, "All declaration parameters aside from 'self' must be annotated"); - - AstType* fnType = allocator.alloc( - Location(start, end), generics, genericPacks, AstTypeList{copy(vars), varargAnnotation}, copy(varNames), retTypes); - - return AstDeclaredClassProp{fnName.name, fnType, true}; -} - -AstStat* Parser::parseDeclaration(const Location& start) -{ - // `declare` token is already parsed at this point - if (lexer.current().type == Lexeme::ReservedFunction) - { - nextLexeme(); - bool checkedFunction = false; - if (FFlag::LuauCheckedFunctionSyntax && lexer.current().type == Lexeme::ReservedChecked) - { - checkedFunction = true; - nextLexeme(); - } - - Name globalName = parseName("global function name"); - auto [generics, genericPacks] = parseGenericTypeList(/* withDefaultValues= */ false); - - MatchLexeme matchParen = lexer.current(); - - expectAndConsume('(', "global function declaration"); - - TempVector args(scratchBinding); - - bool vararg = false; - Location varargLocation; - AstTypePack* varargAnnotation = nullptr; - - if (lexer.current().type != ')') - std::tie(vararg, varargLocation, varargAnnotation) = parseBindingList(args, /* allowDot3= */ true); - - expectMatchAndConsume(')', matchParen); - - AstTypeList retTypes = parseOptionalReturnType().value_or(AstTypeList{copy(nullptr, 0)}); - Location end = lexer.current().location; - - TempVector vars(scratchType); - TempVector varNames(scratchArgName); - - for (size_t i = 0; i < args.size(); ++i) - { - if (!args[i].annotation) - return reportStatError(Location(start, end), {}, {}, "All declaration parameters must be annotated"); - - vars.push_back(args[i].annotation); - varNames.push_back({args[i].name.name, args[i].name.location}); - } - - if (vararg && !varargAnnotation) - return reportStatError(Location(start, end), {}, {}, "All declaration parameters must be annotated"); - - return allocator.alloc(Location(start, end), globalName.name, generics, genericPacks, - AstTypeList{copy(vars), varargAnnotation}, copy(varNames), retTypes, checkedFunction); - } - else if (AstName(lexer.current().name) == "class") - { - nextLexeme(); - Location classStart = lexer.current().location; - Name className = parseName("class name"); - std::optional superName = std::nullopt; - - if (AstName(lexer.current().name) == "extends") - { - nextLexeme(); - superName = parseName("superclass name").name; - } - - TempVector props(scratchDeclaredClassProps); - AstTableIndexer* indexer = nullptr; - - while (lexer.current().type != Lexeme::ReservedEnd) - { - // There are two possibilities: Either it's a property or a function. - if (lexer.current().type == Lexeme::ReservedFunction) - { - props.push_back(parseDeclaredClassMethod()); - } - else if (lexer.current().type == '[' && (lexer.lookahead().type == Lexeme::RawString || - lexer.lookahead().type == Lexeme::QuotedString)) - { - const Lexeme begin = lexer.current(); - nextLexeme(); // [ - - std::optional> chars = parseCharArray(); - - expectMatchAndConsume(']', begin); - expectAndConsume(':', "property type annotation"); - AstType* type = parseType(); - - // since AstName contains a char*, it can't contain null - bool containsNull = chars && (strnlen(chars->data, chars->size) < chars->size); - - if (chars && !containsNull) - props.push_back(AstDeclaredClassProp{AstName(chars->data), type, false}); - else - report(begin.location, "String literal contains malformed escape sequence or \\0"); - } - else if (lexer.current().type == '[') - { - if (indexer) - { - // maybe we don't need to parse the entire badIndexer... - // however, we either have { or [ to lint, not the entire table type or the bad indexer. - AstTableIndexer* badIndexer = parseTableIndexer(); - - // we lose all additional indexer expressions from the AST after error recovery here - report(badIndexer->location, "Cannot have more than one class indexer"); - } - else - { - indexer = parseTableIndexer(); - } - } - else - { - Name propName = parseName("property name"); - expectAndConsume(':', "property type annotation"); - AstType* propType = parseType(); - props.push_back(AstDeclaredClassProp{propName.name, propType, false}); - } - } - - Location classEnd = lexer.current().location; - nextLexeme(); // skip past `end` - - return allocator.alloc(Location(classStart, classEnd), className.name, superName, copy(props), indexer); - } - else if (std::optional globalName = parseNameOpt("global variable name")) - { - expectAndConsume(':', "global variable declaration"); - - AstType* type = parseType(/* in declaration context */ true); - return allocator.alloc(Location(start, type->location), globalName->name, type); - } - else - { - return reportStatError(start, {}, {}, "declare must be followed by an identifier, 'function', or 'class'"); - } -} - -static bool isExprLValue(AstExpr* expr) -{ - return expr->is() || expr->is() || expr->is() || expr->is(); -} - -// varlist `=' explist -AstStat* Parser::parseAssignment(AstExpr* initial) -{ - if (!isExprLValue(initial)) - initial = reportExprError(initial->location, copy({initial}), "Assigned expression must be a variable or a field"); - - TempVector vars(scratchExpr); - vars.push_back(initial); - - while (lexer.current().type == ',') - { - nextLexeme(); - - AstExpr* expr = parsePrimaryExpr(/* asStatement= */ true); - - if (!isExprLValue(expr)) - expr = reportExprError(expr->location, copy({expr}), "Assigned expression must be a variable or a field"); - - vars.push_back(expr); - } - - expectAndConsume('=', "assignment"); - - TempVector values(scratchExprAux); - parseExprList(values); - - return allocator.alloc(Location(initial->location, values.back()->location), copy(vars), copy(values)); -} - -// var [`+=' | `-=' | `*=' | `/=' | `%=' | `^=' | `..='] exp -AstStat* Parser::parseCompoundAssignment(AstExpr* initial, AstExprBinary::Op op) -{ - if (!isExprLValue(initial)) - { - initial = reportExprError(initial->location, copy({initial}), "Assigned expression must be a variable or a field"); - } - - nextLexeme(); - - AstExpr* value = parseExpr(); - - return allocator.alloc(Location(initial->location, value->location), op, initial, value); -} - -std::pair> Parser::prepareFunctionArguments(const Location& start, bool hasself, const TempVector& args) -{ - AstLocal* self = nullptr; - - if (hasself) - self = pushLocal(Binding(Name(nameSelf, start), nullptr)); - - TempVector vars(scratchLocal); - - for (size_t i = 0; i < args.size(); ++i) - vars.push_back(pushLocal(args[i])); - - return {self, copy(vars)}; -} - -// funcbody ::= `(' [parlist] `)' [`:' ReturnType] block end -// parlist ::= bindinglist [`,' `...'] | `...' -std::pair Parser::parseFunctionBody( - bool hasself, const Lexeme& matchFunction, const AstName& debugname, const Name* localName) -{ - Location start = matchFunction.location; - - auto [generics, genericPacks] = parseGenericTypeList(/* withDefaultValues= */ false); - - MatchLexeme matchParen = lexer.current(); - expectAndConsume('(', "function"); - - TempVector args(scratchBinding); - - bool vararg = false; - Location varargLocation; - AstTypePack* varargAnnotation = nullptr; - - if (lexer.current().type != ')') - std::tie(vararg, varargLocation, varargAnnotation) = parseBindingList(args, /* allowDot3= */ true); - - std::optional argLocation; - - if (matchParen.type == Lexeme::Type('(') && lexer.current().type == Lexeme::Type(')')) - argLocation = Location(matchParen.position, lexer.current().location.end); - - expectMatchAndConsume(')', matchParen, true); - - std::optional typelist = parseOptionalReturnType(); - - AstLocal* funLocal = nullptr; - - if (localName) - funLocal = pushLocal(Binding(*localName, nullptr)); - - unsigned int localsBegin = saveLocals(); - - Function fun; - fun.vararg = vararg; - - functionStack.emplace_back(fun); - - auto [self, vars] = prepareFunctionArguments(start, hasself, args); - - AstStatBlock* body = parseBlock(); - - functionStack.pop_back(); - - restoreLocals(localsBegin); - - Location end = lexer.current().location; - - bool hasEnd = expectMatchEndAndConsume(Lexeme::ReservedEnd, matchFunction); - if (FFlag::LuauClipExtraHasEndProps) - body->hasEnd = hasEnd; - - return {allocator.alloc(Location(start, end), generics, genericPacks, self, vars, vararg, varargLocation, body, - functionStack.size(), debugname, typelist, varargAnnotation, hasEnd, argLocation), - funLocal}; -} - -// explist ::= {exp `,'} exp -void Parser::parseExprList(TempVector& result) -{ - result.push_back(parseExpr()); - - while (lexer.current().type == ',') - { - nextLexeme(); - - if (lexer.current().type == ')') - { - report(lexer.current().location, "Expected expression after ',' but got ')' instead"); - break; - } - - result.push_back(parseExpr()); - } -} - -Parser::Binding Parser::parseBinding() -{ - std::optional name = parseNameOpt("variable name"); - - // Use placeholder if the name is missing - if (!name) - name = Name(nameError, lexer.current().location); - - AstType* annotation = parseOptionalType(); - - return Binding(*name, annotation); -} - -// bindinglist ::= (binding | `...') [`,' bindinglist] -std::tuple Parser::parseBindingList(TempVector& result, bool allowDot3) -{ - while (true) - { - if (lexer.current().type == Lexeme::Dot3 && allowDot3) - { - Location varargLocation = lexer.current().location; - nextLexeme(); - - AstTypePack* tailAnnotation = nullptr; - if (lexer.current().type == ':') - { - nextLexeme(); - tailAnnotation = parseVariadicArgumentTypePack(); - } - - return {true, varargLocation, tailAnnotation}; - } - - result.push_back(parseBinding()); - - if (lexer.current().type != ',') - break; - nextLexeme(); - } - - return {false, Location(), nullptr}; -} - -AstType* Parser::parseOptionalType() -{ - if (lexer.current().type == ':') - { - nextLexeme(); - return parseType(); - } - else - return nullptr; -} - -// TypeList ::= Type [`,' TypeList] | ...Type -AstTypePack* Parser::parseTypeList(TempVector& result, TempVector>& resultNames) -{ - while (true) - { - if (shouldParseTypePack(lexer)) - return parseTypePack(); - - if (lexer.current().type == Lexeme::Name && lexer.lookahead().type == ':') - { - // Fill in previous argument names with empty slots - while (resultNames.size() < result.size()) - resultNames.push_back({}); - - resultNames.push_back(AstArgumentName{AstName(lexer.current().name), lexer.current().location}); - nextLexeme(); - - expectAndConsume(':'); - } - else if (!resultNames.empty()) - { - // If we have a type with named arguments, provide elements for all types - resultNames.push_back({}); - } - - result.push_back(parseType()); - if (lexer.current().type != ',') - break; - - nextLexeme(); - - if (lexer.current().type == ')') - { - report(lexer.current().location, "Expected type after ',' but got ')' instead"); - break; - } - } - - return nullptr; -} - -std::optional Parser::parseOptionalReturnType() -{ - if (lexer.current().type == ':' || lexer.current().type == Lexeme::SkinnyArrow) - { - if (lexer.current().type == Lexeme::SkinnyArrow) - report(lexer.current().location, "Function return type annotations are written after ':' instead of '->'"); - - nextLexeme(); - - unsigned int oldRecursionCount = recursionCounter; - - auto [_location, result] = parseReturnType(); - - // At this point, if we find a , character, it indicates that there are multiple return types - // in this type annotation, but the list wasn't wrapped in parentheses. - if (lexer.current().type == ',') - { - report(lexer.current().location, "Expected a statement, got ','; did you forget to wrap the list of return types in parentheses?"); - - nextLexeme(); - } - - recursionCounter = oldRecursionCount; - - return result; - } - - return std::nullopt; -} - -// ReturnType ::= Type | `(' TypeList `)' -std::pair Parser::parseReturnType() -{ - incrementRecursionCounter("type annotation"); - - Lexeme begin = lexer.current(); - - if (lexer.current().type != '(') - { - if (shouldParseTypePack(lexer)) - { - AstTypePack* typePack = parseTypePack(); - - return {typePack->location, AstTypeList{{}, typePack}}; - } - else - { - AstType* type = parseType(); - - return {type->location, AstTypeList{copy(&type, 1), nullptr}}; - } - } - - nextLexeme(); - - Location innerBegin = lexer.current().location; - - matchRecoveryStopOnToken[Lexeme::SkinnyArrow]++; - - TempVector result(scratchType); - TempVector> resultNames(scratchOptArgName); - AstTypePack* varargAnnotation = nullptr; - - // possibly () -> ReturnType - if (lexer.current().type != ')') - varargAnnotation = parseTypeList(result, resultNames); - - const Location location{begin.location, lexer.current().location}; - - expectMatchAndConsume(')', begin, true); - - matchRecoveryStopOnToken[Lexeme::SkinnyArrow]--; - - if (lexer.current().type != Lexeme::SkinnyArrow && resultNames.empty()) - { - // If it turns out that it's just '(A)', it's possible that there are unions/intersections to follow, so fold over it. - if (result.size() == 1) - { - AstType* returnType = parseTypeSuffix(result[0], innerBegin); - - // If parseType parses nothing, then returnType->location.end only points at the last non-type-pack - // type to successfully parse. We need the span of the whole annotation. - Position endPos = result.size() == 1 ? location.end : returnType->location.end; - - return {Location{location.begin, endPos}, AstTypeList{copy(&returnType, 1), varargAnnotation}}; - } - - return {location, AstTypeList{copy(result), varargAnnotation}}; - } - - AstType* tail = parseFunctionTypeTail(begin, {}, {}, copy(result), copy(resultNames), varargAnnotation); - - return {Location{location, tail->location}, AstTypeList{copy(&tail, 1), varargAnnotation}}; -} - -// TableIndexer ::= `[' Type `]' `:' Type -AstTableIndexer* Parser::parseTableIndexer() -{ - const Lexeme begin = lexer.current(); - nextLexeme(); // [ - - AstType* index = parseType(); - - expectMatchAndConsume(']', begin); - - expectAndConsume(':', "table field"); - - AstType* result = parseType(); - - return allocator.alloc(AstTableIndexer{index, result, Location(begin.location, result->location)}); -} - -// TableProp ::= Name `:' Type -// TablePropOrIndexer ::= TableProp | TableIndexer -// PropList ::= TablePropOrIndexer {fieldsep TablePropOrIndexer} [fieldsep] -// TableType ::= `{' PropList `}' -AstType* Parser::parseTableType(bool inDeclarationContext) -{ - incrementRecursionCounter("type annotation"); - - TempVector props(scratchTableTypeProps); - AstTableIndexer* indexer = nullptr; - - Location start = lexer.current().location; - - MatchLexeme matchBrace = lexer.current(); - expectAndConsume('{', "table type"); - - while (lexer.current().type != '}') - { - if (lexer.current().type == '[' && (lexer.lookahead().type == Lexeme::RawString || lexer.lookahead().type == Lexeme::QuotedString)) - { - const Lexeme begin = lexer.current(); - nextLexeme(); // [ - std::optional> chars = parseCharArray(); - - expectMatchAndConsume(']', begin); - expectAndConsume(':', "table field"); - - AstType* type = parseType(); - - // since AstName contains a char*, it can't contain null - bool containsNull = chars && (strnlen(chars->data, chars->size) < chars->size); - - if (chars && !containsNull) - props.push_back({AstName(chars->data), begin.location, type}); - else - report(begin.location, "String literal contains malformed escape sequence or \\0"); - } - else if (lexer.current().type == '[') - { - if (indexer) - { - // maybe we don't need to parse the entire badIndexer... - // however, we either have { or [ to lint, not the entire table type or the bad indexer. - AstTableIndexer* badIndexer = parseTableIndexer(); - - // we lose all additional indexer expressions from the AST after error recovery here - report(badIndexer->location, "Cannot have more than one table indexer"); - } - else - { - indexer = parseTableIndexer(); - } - } - else if (props.empty() && !indexer && !(lexer.current().type == Lexeme::Name && lexer.lookahead().type == ':')) - { - AstType* type = parseType(); - - // array-like table type: {T} desugars into {[number]: T} - AstType* index = allocator.alloc(type->location, std::nullopt, nameNumber, std::nullopt, type->location); - indexer = allocator.alloc(AstTableIndexer{index, type, type->location}); - - break; - } - else - { - std::optional name = parseNameOpt("table field"); - - if (!name) - break; - - expectAndConsume(':', "table field"); - - AstType* type = parseType(inDeclarationContext); - - props.push_back({name->name, name->location, type}); - } - - if (lexer.current().type == ',' || lexer.current().type == ';') - { - nextLexeme(); - } - else - { - if (lexer.current().type != '}') - break; - } - } - - Location end = lexer.current().location; - - if (!expectMatchAndConsume('}', matchBrace)) - end = lexer.previousLocation(); - - return allocator.alloc(Location(start, end), copy(props), indexer); -} - -// ReturnType ::= Type | `(' TypeList `)' -// FunctionType ::= [`<' varlist `>'] `(' [TypeList] `)' `->` ReturnType -AstTypeOrPack Parser::parseFunctionType(bool allowPack, bool isCheckedFunction) -{ - incrementRecursionCounter("type annotation"); - - bool forceFunctionType = lexer.current().type == '<'; - - Lexeme begin = lexer.current(); - - auto [generics, genericPacks] = parseGenericTypeList(/* withDefaultValues= */ false); - - Lexeme parameterStart = lexer.current(); - - expectAndConsume('(', "function parameters"); - - matchRecoveryStopOnToken[Lexeme::SkinnyArrow]++; - - TempVector params(scratchType); - TempVector> names(scratchOptArgName); - AstTypePack* varargAnnotation = nullptr; - - if (lexer.current().type != ')') - varargAnnotation = parseTypeList(params, names); - - expectMatchAndConsume(')', parameterStart, true); - - matchRecoveryStopOnToken[Lexeme::SkinnyArrow]--; - - AstArray paramTypes = copy(params); - - if (!names.empty()) - forceFunctionType = true; - - bool returnTypeIntroducer = lexer.current().type == Lexeme::SkinnyArrow || lexer.current().type == ':'; - - // Not a function at all. Just a parenthesized type. Or maybe a type pack with a single element - if (params.size() == 1 && !varargAnnotation && !forceFunctionType && !returnTypeIntroducer) - { - if (allowPack) - return {{}, allocator.alloc(begin.location, AstTypeList{paramTypes, nullptr})}; - else - return {params[0], {}}; - } - - if (!forceFunctionType && !returnTypeIntroducer && allowPack) - return {{}, allocator.alloc(begin.location, AstTypeList{paramTypes, varargAnnotation})}; - - AstArray> paramNames = copy(names); - - return {parseFunctionTypeTail(begin, generics, genericPacks, paramTypes, paramNames, varargAnnotation, isCheckedFunction), {}}; -} - -AstType* Parser::parseFunctionTypeTail(const Lexeme& begin, AstArray generics, AstArray genericPacks, - AstArray params, AstArray> paramNames, AstTypePack* varargAnnotation, bool isCheckedFunction) -{ - incrementRecursionCounter("type annotation"); - - if (lexer.current().type == ':') - { - report(lexer.current().location, "Return types in function type annotations are written after '->' instead of ':'"); - lexer.next(); - } - // Users occasionally write '()' as the 'unit' type when they actually want to use 'nil', here we'll try to give a more specific error - else if (lexer.current().type != Lexeme::SkinnyArrow && generics.size == 0 && genericPacks.size == 0 && params.size == 0) - { - report(Location(begin.location, lexer.previousLocation()), "Expected '->' after '()' when parsing function type; did you mean 'nil'?"); - - return allocator.alloc(begin.location, std::nullopt, nameNil, std::nullopt, begin.location); - } - else - { - expectAndConsume(Lexeme::SkinnyArrow, "function type"); - } - - auto [endLocation, returnTypeList] = parseReturnType(); - - AstTypeList paramTypes = AstTypeList{params, varargAnnotation}; - return allocator.alloc( - Location(begin.location, endLocation), generics, genericPacks, paramTypes, paramNames, returnTypeList, isCheckedFunction); -} - -// Type ::= -// nil | -// Name[`.' Name] [`<' namelist `>'] | -// `{' [PropList] `}' | -// `(' [TypeList] `)' `->` ReturnType -// `typeof` Type -AstType* Parser::parseTypeSuffix(AstType* type, const Location& begin) -{ - TempVector parts(scratchType); - parts.push_back(type); - - incrementRecursionCounter("type annotation"); - - bool isUnion = false; - bool isIntersection = false; - bool hasOptional = false; - - Location location = begin; - - while (true) - { - Lexeme::Type c = lexer.current().type; - if (c == '|') - { - nextLexeme(); - - unsigned int oldRecursionCount = recursionCounter; - parts.push_back(parseSimpleType(/* allowPack= */ false).type); - recursionCounter = oldRecursionCount; - - isUnion = true; - } - else if (c == '?') - { - Location loc = lexer.current().location; - nextLexeme(); - - if (!hasOptional) - parts.push_back(allocator.alloc(loc, std::nullopt, nameNil, std::nullopt, loc)); - - isUnion = true; - hasOptional = true; - } - else if (c == '&') - { - nextLexeme(); - - unsigned int oldRecursionCount = recursionCounter; - parts.push_back(parseSimpleType(/* allowPack= */ false).type); - recursionCounter = oldRecursionCount; - - isIntersection = true; - } - else if (c == Lexeme::Dot3) - { - report(lexer.current().location, "Unexpected '...' after type annotation"); - nextLexeme(); - } - else - break; - - if (parts.size() > unsigned(FInt::LuauTypeLengthLimit) + hasOptional) - ParseError::raise(parts.back()->location, "Exceeded allowed type length; simplify your type annotation to make the code compile"); - } - - if (parts.size() == 1) - return type; - - if (isUnion && isIntersection) - { - return reportTypeError(Location(begin, parts.back()->location), copy(parts), - "Mixing union and intersection types is not allowed; consider wrapping in parentheses."); - } - - location.end = parts.back()->location.end; - - if (isUnion) - return allocator.alloc(location, copy(parts)); - - if (isIntersection) - return allocator.alloc(location, copy(parts)); - - LUAU_ASSERT(false); - ParseError::raise(begin, "Composite type was not an intersection or union."); -} - -AstTypeOrPack Parser::parseTypeOrPack() -{ - unsigned int oldRecursionCount = recursionCounter; - // recursion counter is incremented in parseSimpleType - - Location begin = lexer.current().location; - - auto [type, typePack] = parseSimpleType(/* allowPack= */ true); - - if (typePack) - { - LUAU_ASSERT(!type); - return {{}, typePack}; - } - - recursionCounter = oldRecursionCount; - - return {parseTypeSuffix(type, begin), {}}; -} - -AstType* Parser::parseType(bool inDeclarationContext) -{ - unsigned int oldRecursionCount = recursionCounter; - // recursion counter is incremented in parseSimpleType - - Location begin = lexer.current().location; - - AstType* type = parseSimpleType(/* allowPack= */ false, /* in declaration context */ inDeclarationContext).type; - - recursionCounter = oldRecursionCount; - - return parseTypeSuffix(type, begin); -} - -// Type ::= nil | Name[`.' Name] [ `<' Type [`,' ...] `>' ] | `typeof' `(' expr `)' | `{' [PropList] `}' -// | [`<' varlist `>'] `(' [TypeList] `)' `->` ReturnType -AstTypeOrPack Parser::parseSimpleType(bool allowPack, bool inDeclarationContext) -{ - incrementRecursionCounter("type annotation"); - - Location start = lexer.current().location; - - if (lexer.current().type == Lexeme::ReservedNil) - { - nextLexeme(); - return {allocator.alloc(start, std::nullopt, nameNil, std::nullopt, start), {}}; - } - else if (lexer.current().type == Lexeme::ReservedTrue) - { - nextLexeme(); - return {allocator.alloc(start, true)}; - } - else if (lexer.current().type == Lexeme::ReservedFalse) - { - nextLexeme(); - return {allocator.alloc(start, false)}; - } - else if (lexer.current().type == Lexeme::RawString || lexer.current().type == Lexeme::QuotedString) - { - if (std::optional> value = parseCharArray()) - { - AstArray svalue = *value; - return {allocator.alloc(start, svalue)}; - } - else - return {reportTypeError(start, {}, "String literal contains malformed escape sequence")}; - } - else if (lexer.current().type == Lexeme::InterpStringBegin || lexer.current().type == Lexeme::InterpStringSimple) - { - parseInterpString(); - - return {reportTypeError(start, {}, "Interpolated string literals cannot be used as types")}; - } - else if (lexer.current().type == Lexeme::BrokenString) - { - nextLexeme(); - return {reportTypeError(start, {}, "Malformed string; did you forget to finish it?")}; - } - else if (lexer.current().type == Lexeme::Name) - { - std::optional prefix; - std::optional prefixLocation; - Name name = parseName("type name"); - - if (lexer.current().type == '.') - { - Position pointPosition = lexer.current().location.begin; - nextLexeme(); - - prefix = name.name; - prefixLocation = name.location; - name = parseIndexName("field name", pointPosition); - } - else if (lexer.current().type == Lexeme::Dot3) - { - report(lexer.current().location, "Unexpected '...' after type name; type pack is not allowed in this context"); - nextLexeme(); - } - else if (name.name == "typeof") - { - Lexeme typeofBegin = lexer.current(); - expectAndConsume('(', "typeof type"); - - AstExpr* expr = parseExpr(); - - Location end = lexer.current().location; - - expectMatchAndConsume(')', typeofBegin); - - return {allocator.alloc(Location(start, end), expr), {}}; - } - - bool hasParameters = false; - AstArray parameters{}; - - if (lexer.current().type == '<') - { - hasParameters = true; - parameters = parseTypeParams(); - } - - Location end = lexer.previousLocation(); - - return { - allocator.alloc(Location(start, end), prefix, name.name, prefixLocation, name.location, hasParameters, parameters), {}}; - } - else if (lexer.current().type == '{') - { - return {parseTableType(/* inDeclarationContext */ inDeclarationContext), {}}; - } - else if (FFlag::LuauCheckedFunctionSyntax && inDeclarationContext && lexer.current().type == Lexeme::ReservedChecked) - { - LUAU_ASSERT(FFlag::LuauCheckedFunctionSyntax); - nextLexeme(); - return parseFunctionType(allowPack, /* isCheckedFunction */ true); - } - else if (lexer.current().type == '(' || lexer.current().type == '<') - { - return parseFunctionType(allowPack); - } - else if (lexer.current().type == Lexeme::ReservedFunction) - { - nextLexeme(); - - return {reportTypeError(start, {}, - "Using 'function' as a type annotation is not supported, consider replacing with a function type annotation e.g. '(...any) -> " - "...any'"), - {}}; - } - else - { - // For a missing type annotation, capture 'space' between last token and the next one - Location astErrorlocation(lexer.previousLocation().end, start.begin); - // The parse error includes the next lexeme to make it easier to display where the error is (e.g. in an IDE or a CLI error message). - // Including the current lexeme also makes the parse error consistent with other parse errors returned by Luau. - Location parseErrorLocation(lexer.previousLocation().end, start.end); - return {reportMissingTypeError(parseErrorLocation, astErrorlocation, "Expected type, got %s", lexer.current().toString().c_str()), {}}; - } -} - -AstTypePack* Parser::parseVariadicArgumentTypePack() -{ - // Generic: a... - if (lexer.current().type == Lexeme::Name && lexer.lookahead().type == Lexeme::Dot3) - { - Name name = parseName("generic name"); - Location end = lexer.current().location; - - // This will not fail because of the lookahead guard. - expectAndConsume(Lexeme::Dot3, "generic type pack annotation"); - return allocator.alloc(Location(name.location, end), name.name); - } - // Variadic: T - else - { - AstType* variadicAnnotation = parseType(); - return allocator.alloc(variadicAnnotation->location, variadicAnnotation); - } -} - -AstTypePack* Parser::parseTypePack() -{ - // Variadic: ...T - if (lexer.current().type == Lexeme::Dot3) - { - Location start = lexer.current().location; - nextLexeme(); - AstType* varargTy = parseType(); - return allocator.alloc(Location(start, varargTy->location), varargTy); - } - // Generic: a... - else if (lexer.current().type == Lexeme::Name && lexer.lookahead().type == Lexeme::Dot3) - { - Name name = parseName("generic name"); - Location end = lexer.current().location; - - // This will not fail because of the lookahead guard. - expectAndConsume(Lexeme::Dot3, "generic type pack annotation"); - return allocator.alloc(Location(name.location, end), name.name); - } - - // TODO: shouldParseTypePack can be removed and parseTypePack can be called unconditionally instead - LUAU_ASSERT(!"parseTypePack can't be called if shouldParseTypePack() returned false"); - return nullptr; -} - -std::optional Parser::parseUnaryOp(const Lexeme& l) -{ - if (l.type == Lexeme::ReservedNot) - return AstExprUnary::Not; - else if (l.type == '-') - return AstExprUnary::Minus; - else if (l.type == '#') - return AstExprUnary::Len; - else - return std::nullopt; -} - -std::optional Parser::parseBinaryOp(const Lexeme& l) -{ - if (l.type == '+') - return AstExprBinary::Add; - else if (l.type == '-') - return AstExprBinary::Sub; - else if (l.type == '*') - return AstExprBinary::Mul; - else if (l.type == '/') - return AstExprBinary::Div; - else if (l.type == Lexeme::FloorDiv) - return AstExprBinary::FloorDiv; - else if (l.type == '%') - return AstExprBinary::Mod; - else if (l.type == '^') - return AstExprBinary::Pow; - else if (l.type == Lexeme::Dot2) - return AstExprBinary::Concat; - else if (l.type == Lexeme::NotEqual) - return AstExprBinary::CompareNe; - else if (l.type == Lexeme::Equal) - return AstExprBinary::CompareEq; - else if (l.type == '<') - return AstExprBinary::CompareLt; - else if (l.type == Lexeme::LessEqual) - return AstExprBinary::CompareLe; - else if (l.type == '>') - return AstExprBinary::CompareGt; - else if (l.type == Lexeme::GreaterEqual) - return AstExprBinary::CompareGe; - else if (l.type == Lexeme::ReservedAnd) - return AstExprBinary::And; - else if (l.type == Lexeme::ReservedOr) - return AstExprBinary::Or; - else - return std::nullopt; -} - -std::optional Parser::parseCompoundOp(const Lexeme& l) -{ - if (l.type == Lexeme::AddAssign) - return AstExprBinary::Add; - else if (l.type == Lexeme::SubAssign) - return AstExprBinary::Sub; - else if (l.type == Lexeme::MulAssign) - return AstExprBinary::Mul; - else if (l.type == Lexeme::DivAssign) - return AstExprBinary::Div; - else if (l.type == Lexeme::FloorDivAssign) - return AstExprBinary::FloorDiv; - else if (l.type == Lexeme::ModAssign) - return AstExprBinary::Mod; - else if (l.type == Lexeme::PowAssign) - return AstExprBinary::Pow; - else if (l.type == Lexeme::ConcatAssign) - return AstExprBinary::Concat; - else - return std::nullopt; -} - -std::optional Parser::checkUnaryConfusables() -{ - const Lexeme& curr = lexer.current(); - - // early-out: need to check if this is a possible confusable quickly - if (curr.type != '!') - return {}; - - // slow path: possible confusable - Location start = curr.location; - - if (curr.type == '!') - { - report(start, "Unexpected '!'; did you mean 'not'?"); - return AstExprUnary::Not; - } - - return {}; -} - -std::optional Parser::checkBinaryConfusables(const BinaryOpPriority binaryPriority[], unsigned int limit) -{ - const Lexeme& curr = lexer.current(); - - // early-out: need to check if this is a possible confusable quickly - if (curr.type != '&' && curr.type != '|' && curr.type != '!') - return {}; - - // slow path: possible confusable - Location start = curr.location; - Lexeme next = lexer.lookahead(); - - if (curr.type == '&' && next.type == '&' && curr.location.end == next.location.begin && binaryPriority[AstExprBinary::And].left > limit) - { - nextLexeme(); - report(Location(start, next.location), "Unexpected '&&'; did you mean 'and'?"); - return AstExprBinary::And; - } - else if (curr.type == '|' && next.type == '|' && curr.location.end == next.location.begin && binaryPriority[AstExprBinary::Or].left > limit) - { - nextLexeme(); - report(Location(start, next.location), "Unexpected '||'; did you mean 'or'?"); - return AstExprBinary::Or; - } - else if (curr.type == '!' && next.type == '=' && curr.location.end == next.location.begin && - binaryPriority[AstExprBinary::CompareNe].left > limit) - { - nextLexeme(); - report(Location(start, next.location), "Unexpected '!='; did you mean '~='?"); - return AstExprBinary::CompareNe; - } - - return std::nullopt; -} - -// subexpr -> (asexp | unop subexpr) { binop subexpr } -// where `binop' is any binary operator with a priority higher than `limit' -AstExpr* Parser::parseExpr(unsigned int limit) -{ - static const BinaryOpPriority binaryPriority[] = { - {6, 6}, {6, 6}, {7, 7}, {7, 7}, {7, 7}, {7, 7}, // `+' `-' `*' `/' `//' `%' - {10, 9}, {5, 4}, // power and concat (right associative) - {3, 3}, {3, 3}, // equality and inequality - {3, 3}, {3, 3}, {3, 3}, {3, 3}, // order - {2, 2}, {1, 1} // logical (and/or) - }; - static_assert(sizeof(binaryPriority) / sizeof(binaryPriority[0]) == size_t(AstExprBinary::Op__Count), "binaryPriority needs an entry per op"); - - unsigned int oldRecursionCount = recursionCounter; - - // this handles recursive calls to parseSubExpr/parseExpr - incrementRecursionCounter("expression"); - - const unsigned int unaryPriority = 8; - - Location start = lexer.current().location; - - AstExpr* expr; - - std::optional uop = parseUnaryOp(lexer.current()); - - if (!uop) - uop = checkUnaryConfusables(); - - if (uop) - { - nextLexeme(); - - AstExpr* subexpr = parseExpr(unaryPriority); - - expr = allocator.alloc(Location(start, subexpr->location), *uop, subexpr); - } - else - { - expr = parseAssertionExpr(); - } - - // expand while operators have priorities higher than `limit' - std::optional op = parseBinaryOp(lexer.current()); - - if (!op) - op = checkBinaryConfusables(binaryPriority, limit); - - while (op && binaryPriority[*op].left > limit) - { - nextLexeme(); - - // read sub-expression with higher priority - AstExpr* next = parseExpr(binaryPriority[*op].right); - - expr = allocator.alloc(Location(start, next->location), *op, expr, next); - op = parseBinaryOp(lexer.current()); - - if (!op) - op = checkBinaryConfusables(binaryPriority, limit); - - // note: while the parser isn't recursive here, we're generating recursive structures of unbounded depth - incrementRecursionCounter("expression"); - } - - recursionCounter = oldRecursionCount; - - return expr; -} - -// NAME -AstExpr* Parser::parseNameExpr(const char* context) -{ - std::optional name = parseNameOpt(context); - - if (!name) - return allocator.alloc(lexer.current().location, copy({}), unsigned(parseErrors.size() - 1)); - - AstLocal* const* value = localMap.find(name->name); - - if (value && *value) - { - AstLocal* local = *value; - - return allocator.alloc(name->location, local, local->functionDepth != functionStack.size() - 1); - } - - return allocator.alloc(name->location, name->name); -} - -// prefixexp -> NAME | '(' expr ')' -AstExpr* Parser::parsePrefixExpr() -{ - if (lexer.current().type == '(') - { - Position start = lexer.current().location.begin; - - MatchLexeme matchParen = lexer.current(); - nextLexeme(); - - AstExpr* expr = parseExpr(); - - Position end = lexer.current().location.end; - - if (lexer.current().type != ')') - { - const char* suggestion = (lexer.current().type == '=') ? "; did you mean to use '{' when defining a table?" : nullptr; - - expectMatchAndConsumeFail(static_cast(')'), matchParen, suggestion); - - end = lexer.previousLocation().end; - } - else - { - nextLexeme(); - } - - return allocator.alloc(Location(start, end), expr); - } - else - { - return parseNameExpr("expression"); - } -} - -// primaryexp -> prefixexp { `.' NAME | `[' exp `]' | `:' NAME funcargs | funcargs } -AstExpr* Parser::parsePrimaryExpr(bool asStatement) -{ - Position start = lexer.current().location.begin; - - AstExpr* expr = parsePrefixExpr(); - - unsigned int oldRecursionCount = recursionCounter; - - while (true) - { - if (lexer.current().type == '.') - { - Position opPosition = lexer.current().location.begin; - nextLexeme(); - - Name index = parseIndexName(nullptr, opPosition); - - expr = allocator.alloc(Location(start, index.location.end), expr, index.name, index.location, opPosition, '.'); - } - else if (lexer.current().type == '[') - { - MatchLexeme matchBracket = lexer.current(); - nextLexeme(); - - AstExpr* index = parseExpr(); - - Position end = lexer.current().location.end; - - expectMatchAndConsume(']', matchBracket); - - expr = allocator.alloc(Location(start, end), expr, index); - } - else if (lexer.current().type == ':') - { - Position opPosition = lexer.current().location.begin; - nextLexeme(); - - Name index = parseIndexName("method name", opPosition); - AstExpr* func = allocator.alloc(Location(start, index.location.end), expr, index.name, index.location, opPosition, ':'); - - expr = parseFunctionArgs(func, true); - } - else if (lexer.current().type == '(') - { - // This error is handled inside 'parseFunctionArgs' as well, but for better error recovery we need to break out the current loop here - if (!asStatement && expr->location.end.line != lexer.current().location.begin.line) - { - reportAmbiguousCallError(); - break; - } - - expr = parseFunctionArgs(expr, false); - } - else if (lexer.current().type == '{' || lexer.current().type == Lexeme::RawString || lexer.current().type == Lexeme::QuotedString) - { - expr = parseFunctionArgs(expr, false); - } - else - { - break; - } - - // note: while the parser isn't recursive here, we're generating recursive structures of unbounded depth - incrementRecursionCounter("expression"); - } - - recursionCounter = oldRecursionCount; - - return expr; -} - -// asexp -> simpleexp [`::' Type] -AstExpr* Parser::parseAssertionExpr() -{ - Location start = lexer.current().location; - AstExpr* expr = parseSimpleExpr(); - - if (lexer.current().type == Lexeme::DoubleColon) - { - nextLexeme(); - AstType* annotation = parseType(); - return allocator.alloc(Location(start, annotation->location), expr, annotation); - } - else - return expr; -} - -static ConstantNumberParseResult parseInteger(double& result, const char* data, int base) -{ - LUAU_ASSERT(base == 2 || base == 16); - - char* end = nullptr; - unsigned long long value = strtoull(data, &end, base); - - if (*end != 0) - return ConstantNumberParseResult::Malformed; - - result = double(value); - - if (value == ULLONG_MAX && errno == ERANGE) - { - // 'errno' might have been set before we called 'strtoull', but we don't want the overhead of resetting a TLS variable on each call - // so we only reset it when we get a result that might be an out-of-range error and parse again to make sure - errno = 0; - value = strtoull(data, &end, base); - - if (errno == ERANGE) - return base == 2 ? ConstantNumberParseResult::BinOverflow : ConstantNumberParseResult::HexOverflow; - } - - if (value >= (1ull << 53) && static_cast(result) != value) - return ConstantNumberParseResult::Imprecise; - - return ConstantNumberParseResult::Ok; -} - -static ConstantNumberParseResult parseDouble(double& result, const char* data) -{ - // binary literal - if (data[0] == '0' && (data[1] == 'b' || data[1] == 'B') && data[2]) - return parseInteger(result, data + 2, 2); - - // hexadecimal literal - if (data[0] == '0' && (data[1] == 'x' || data[1] == 'X') && data[2]) - return parseInteger(result, data, 16); // pass in '0x' prefix, it's handled by 'strtoull' - - char* end = nullptr; - double value = strtod(data, &end); - - // trailing non-numeric characters - if (*end != 0) - return ConstantNumberParseResult::Malformed; - - result = value; - - // for linting, we detect integer constants that are parsed imprecisely - // since the check is expensive we only perform it when the number is larger than the precise integer range - if (value >= double(1ull << 53) && strspn(data, "0123456789") == strlen(data)) - { - char repr[512]; - snprintf(repr, sizeof(repr), "%.0f", value); - - if (strcmp(repr, data) != 0) - return ConstantNumberParseResult::Imprecise; - } - - return ConstantNumberParseResult::Ok; -} - -// simpleexp -> NUMBER | STRING | NIL | true | false | ... | constructor | FUNCTION body | primaryexp -AstExpr* Parser::parseSimpleExpr() -{ - Location start = lexer.current().location; - - if (lexer.current().type == Lexeme::ReservedNil) - { - nextLexeme(); - - return allocator.alloc(start); - } - else if (lexer.current().type == Lexeme::ReservedTrue) - { - nextLexeme(); - - return allocator.alloc(start, true); - } - else if (lexer.current().type == Lexeme::ReservedFalse) - { - nextLexeme(); - - return allocator.alloc(start, false); - } - else if (lexer.current().type == Lexeme::ReservedFunction) - { - Lexeme matchFunction = lexer.current(); - nextLexeme(); - - return parseFunctionBody(false, matchFunction, AstName(), nullptr).first; - } - else if (lexer.current().type == Lexeme::Number) - { - return parseNumber(); - } - else if (lexer.current().type == Lexeme::RawString || lexer.current().type == Lexeme::QuotedString || - lexer.current().type == Lexeme::InterpStringSimple) - { - return parseString(); - } - else if (lexer.current().type == Lexeme::InterpStringBegin) - { - return parseInterpString(); - } - else if (lexer.current().type == Lexeme::BrokenString) - { - nextLexeme(); - return reportExprError(start, {}, "Malformed string; did you forget to finish it?"); - } - else if (lexer.current().type == Lexeme::BrokenInterpDoubleBrace) - { - nextLexeme(); - return reportExprError(start, {}, "Double braces are not permitted within interpolated strings; did you mean '\\{'?"); - } - else if (lexer.current().type == Lexeme::Dot3) - { - if (functionStack.back().vararg) - { - nextLexeme(); - - return allocator.alloc(start); - } - else - { - nextLexeme(); - - return reportExprError(start, {}, "Cannot use '...' outside of a vararg function"); - } - } - else if (lexer.current().type == '{') - { - return parseTableConstructor(); - } - else if (lexer.current().type == Lexeme::ReservedIf) - { - return parseIfElseExpr(); - } - else - { - return parsePrimaryExpr(/* asStatement= */ false); - } -} - -// args ::= `(' [explist] `)' | tableconstructor | String -AstExpr* Parser::parseFunctionArgs(AstExpr* func, bool self) -{ - if (lexer.current().type == '(') - { - Position argStart = lexer.current().location.end; - if (func->location.end.line != lexer.current().location.begin.line) - reportAmbiguousCallError(); - - MatchLexeme matchParen = lexer.current(); - nextLexeme(); - - TempVector args(scratchExpr); - - if (lexer.current().type != ')') - parseExprList(args); - - Location end = lexer.current().location; - Position argEnd = end.end; - - expectMatchAndConsume(')', matchParen); - - return allocator.alloc(Location(func->location, end), func, copy(args), self, Location(argStart, argEnd)); - } - else if (lexer.current().type == '{') - { - Position argStart = lexer.current().location.end; - AstExpr* expr = parseTableConstructor(); - Position argEnd = lexer.previousLocation().end; - - return allocator.alloc(Location(func->location, expr->location), func, copy(&expr, 1), self, Location(argStart, argEnd)); - } - else if (lexer.current().type == Lexeme::RawString || lexer.current().type == Lexeme::QuotedString) - { - Location argLocation = lexer.current().location; - AstExpr* expr = parseString(); - - return allocator.alloc(Location(func->location, expr->location), func, copy(&expr, 1), self, argLocation); - } - else - { - return reportFunctionArgsError(func, self); - } -} - -LUAU_NOINLINE AstExpr* Parser::reportFunctionArgsError(AstExpr* func, bool self) -{ - if (self && lexer.current().location.begin.line != func->location.end.line) - { - return reportExprError(func->location, copy({func}), "Expected function call arguments after '('"); - } - else - { - return reportExprError(Location(func->location.begin, lexer.current().location.begin), copy({func}), - "Expected '(', '{' or when parsing function call, got %s", lexer.current().toString().c_str()); - } -} - -LUAU_NOINLINE void Parser::reportAmbiguousCallError() -{ - report(lexer.current().location, "Ambiguous syntax: this looks like an argument list for a function call, but could also be a start of " - "new statement; use ';' to separate statements"); -} - -// tableconstructor ::= `{' [fieldlist] `}' -// fieldlist ::= field {fieldsep field} [fieldsep] -// field ::= `[' exp `]' `=' exp | Name `=' exp | exp -// fieldsep ::= `,' | `;' -AstExpr* Parser::parseTableConstructor() -{ - TempVector items(scratchItem); - - Location start = lexer.current().location; - - MatchLexeme matchBrace = lexer.current(); - expectAndConsume('{', "table literal"); - unsigned lastElementIndent = 0; - - while (lexer.current().type != '}') - { - lastElementIndent = lexer.current().location.begin.column; - - if (lexer.current().type == '[') - { - MatchLexeme matchLocationBracket = lexer.current(); - nextLexeme(); - - AstExpr* key = parseExpr(); - - expectMatchAndConsume(']', matchLocationBracket); - - expectAndConsume('=', "table field"); - - AstExpr* value = parseExpr(); - - items.push_back({AstExprTable::Item::General, key, value}); - } - else if (lexer.current().type == Lexeme::Name && lexer.lookahead().type == '=') - { - Name name = parseName("table field"); - - expectAndConsume('=', "table field"); - - AstArray nameString; - nameString.data = const_cast(name.name.value); - nameString.size = strlen(name.name.value); - - AstExpr* key = allocator.alloc(name.location, nameString, AstExprConstantString::Unquoted); - AstExpr* value = parseExpr(); - - if (AstExprFunction* func = value->as()) - func->debugname = name.name; - - items.push_back({AstExprTable::Item::Record, key, value}); - } - else - { - AstExpr* expr = parseExpr(); - - items.push_back({AstExprTable::Item::List, nullptr, expr}); - } - - if (lexer.current().type == ',' || lexer.current().type == ';') - { - nextLexeme(); - } - else if ((lexer.current().type == '[' || lexer.current().type == Lexeme::Name) && lexer.current().location.begin.column == lastElementIndent) - { - report(lexer.current().location, "Expected ',' after table constructor element"); - } - else if (lexer.current().type != '}') - { - break; - } - } - - Location end = lexer.current().location; - - if (!expectMatchAndConsume('}', matchBrace)) - end = lexer.previousLocation(); - - return allocator.alloc(Location(start, end), copy(items)); -} - -AstExpr* Parser::parseIfElseExpr() -{ - bool hasElse = false; - Location start = lexer.current().location; - - nextLexeme(); // skip if / elseif - - AstExpr* condition = parseExpr(); - - bool hasThen = expectAndConsume(Lexeme::ReservedThen, "if then else expression"); - - AstExpr* trueExpr = parseExpr(); - AstExpr* falseExpr = nullptr; - - if (lexer.current().type == Lexeme::ReservedElseif) - { - unsigned int oldRecursionCount = recursionCounter; - incrementRecursionCounter("expression"); - hasElse = true; - falseExpr = parseIfElseExpr(); - recursionCounter = oldRecursionCount; - } - else - { - hasElse = expectAndConsume(Lexeme::ReservedElse, "if then else expression"); - falseExpr = parseExpr(); - } - - Location end = falseExpr->location; - - return allocator.alloc(Location(start, end), condition, hasThen, trueExpr, hasElse, falseExpr); -} - -// Name -std::optional Parser::parseNameOpt(const char* context) -{ - if (lexer.current().type != Lexeme::Name) - { - reportNameError(context); - - return {}; - } - - Name result(AstName(lexer.current().name), lexer.current().location); - - nextLexeme(); - - return result; -} - -Parser::Name Parser::parseName(const char* context) -{ - if (std::optional name = parseNameOpt(context)) - return *name; - - Location location = lexer.current().location; - location.end = location.begin; - - return Name(nameError, location); -} - -Parser::Name Parser::parseIndexName(const char* context, const Position& previous) -{ - if (std::optional name = parseNameOpt(context)) - return *name; - - // If we have a reserved keyword next at the same line, assume it's an incomplete name - if (lexer.current().type >= Lexeme::Reserved_BEGIN && lexer.current().type < Lexeme::Reserved_END && - lexer.current().location.begin.line == previous.line) - { - Name result(AstName(lexer.current().name), lexer.current().location); - - nextLexeme(); - - return result; - } - - Location location = lexer.current().location; - location.end = location.begin; - - return Name(nameError, location); -} - -std::pair, AstArray> Parser::parseGenericTypeList(bool withDefaultValues) -{ - TempVector names{scratchGenericTypes}; - TempVector namePacks{scratchGenericTypePacks}; - - if (lexer.current().type == '<') - { - Lexeme begin = lexer.current(); - nextLexeme(); - - bool seenPack = false; - bool seenDefault = false; - - while (true) - { - Location nameLocation = lexer.current().location; - AstName name = parseName().name; - if (lexer.current().type == Lexeme::Dot3 || seenPack) - { - seenPack = true; - - if (lexer.current().type != Lexeme::Dot3) - report(lexer.current().location, "Generic types come before generic type packs"); - else - nextLexeme(); - - if (withDefaultValues && lexer.current().type == '=') - { - seenDefault = true; - nextLexeme(); - - if (shouldParseTypePack(lexer)) - { - AstTypePack* typePack = parseTypePack(); - - namePacks.push_back({name, nameLocation, typePack}); - } - else - { - auto [type, typePack] = parseTypeOrPack(); - - if (type) - report(type->location, "Expected type pack after '=', got type"); - - namePacks.push_back({name, nameLocation, typePack}); - } - } - else - { - if (seenDefault) - report(lexer.current().location, "Expected default type pack after type pack name"); - - namePacks.push_back({name, nameLocation, nullptr}); - } - } - else - { - if (withDefaultValues && lexer.current().type == '=') - { - seenDefault = true; - nextLexeme(); - - AstType* defaultType = parseType(); - - names.push_back({name, nameLocation, defaultType}); - } - else - { - if (seenDefault) - report(lexer.current().location, "Expected default type after type name"); - - names.push_back({name, nameLocation, nullptr}); - } - } - - if (lexer.current().type == ',') - { - nextLexeme(); - - if (lexer.current().type == '>') - { - report(lexer.current().location, "Expected type after ',' but got '>' instead"); - break; - } - } - else - break; - } - - expectMatchAndConsume('>', begin); - } - - AstArray generics = copy(names); - AstArray genericPacks = copy(namePacks); - return {generics, genericPacks}; -} - -AstArray Parser::parseTypeParams() -{ - TempVector parameters{scratchTypeOrPack}; - - if (lexer.current().type == '<') - { - Lexeme begin = lexer.current(); - nextLexeme(); - - while (true) - { - if (shouldParseTypePack(lexer)) - { - AstTypePack* typePack = parseTypePack(); - - parameters.push_back({{}, typePack}); - } - else if (lexer.current().type == '(') - { - auto [type, typePack] = parseTypeOrPack(); - - if (typePack) - parameters.push_back({{}, typePack}); - else - parameters.push_back({type, {}}); - } - else if (lexer.current().type == '>' && parameters.empty()) - { - break; - } - else - { - parameters.push_back({parseType(), {}}); - } - - if (lexer.current().type == ',') - nextLexeme(); - else - break; - } - - expectMatchAndConsume('>', begin); - } - - return copy(parameters); -} - -std::optional> Parser::parseCharArray() -{ - LUAU_ASSERT(lexer.current().type == Lexeme::QuotedString || lexer.current().type == Lexeme::RawString || - lexer.current().type == Lexeme::InterpStringSimple); - - scratchData.assign(lexer.current().data, lexer.current().length); - - if (lexer.current().type == Lexeme::QuotedString || lexer.current().type == Lexeme::InterpStringSimple) - { - if (!Lexer::fixupQuotedString(scratchData)) - { - nextLexeme(); - return std::nullopt; - } - } - else - { - Lexer::fixupMultilineString(scratchData); - } - - AstArray value = copy(scratchData); - nextLexeme(); - return value; -} - -AstExpr* Parser::parseString() -{ - Location location = lexer.current().location; - if (std::optional> value = parseCharArray()) - return allocator.alloc(location, *value); - else - return reportExprError(location, {}, "String literal contains malformed escape sequence"); -} - -AstExpr* Parser::parseInterpString() -{ - TempVector> strings(scratchString); - TempVector expressions(scratchExpr); - - Location startLocation = lexer.current().location; - Location endLocation; - - do - { - Lexeme currentLexeme = lexer.current(); - LUAU_ASSERT(currentLexeme.type == Lexeme::InterpStringBegin || currentLexeme.type == Lexeme::InterpStringMid || - currentLexeme.type == Lexeme::InterpStringEnd || currentLexeme.type == Lexeme::InterpStringSimple); - - endLocation = currentLexeme.location; - - scratchData.assign(currentLexeme.data, currentLexeme.length); - - if (!Lexer::fixupQuotedString(scratchData)) - { - nextLexeme(); - return reportExprError(Location{startLocation, endLocation}, {}, "Interpolated string literal contains malformed escape sequence"); - } - - AstArray chars = copy(scratchData); - - nextLexeme(); - - strings.push_back(chars); - - if (currentLexeme.type == Lexeme::InterpStringEnd || currentLexeme.type == Lexeme::InterpStringSimple) - { - break; - } - - bool errorWhileChecking = false; - - switch (lexer.current().type) - { - case Lexeme::InterpStringMid: - case Lexeme::InterpStringEnd: - { - errorWhileChecking = true; - nextLexeme(); - expressions.push_back(reportExprError(endLocation, {}, "Malformed interpolated string, expected expression inside '{}'")); - break; - } - case Lexeme::BrokenString: - { - errorWhileChecking = true; - nextLexeme(); - expressions.push_back(reportExprError(endLocation, {}, "Malformed interpolated string; did you forget to add a '`'?")); - break; - } - default: - expressions.push_back(parseExpr()); - } - - if (errorWhileChecking) - { - break; - } - - switch (lexer.current().type) - { - case Lexeme::InterpStringBegin: - case Lexeme::InterpStringMid: - case Lexeme::InterpStringEnd: - break; - case Lexeme::BrokenInterpDoubleBrace: - nextLexeme(); - return reportExprError(endLocation, {}, "Double braces are not permitted within interpolated strings; did you mean '\\{'?"); - case Lexeme::BrokenString: - nextLexeme(); - return reportExprError(endLocation, {}, "Malformed interpolated string; did you forget to add a '}'?"); - default: - return reportExprError(endLocation, {}, "Malformed interpolated string, got %s", lexer.current().toString().c_str()); - } - } while (true); - - AstArray> stringsArray = copy(strings); - AstArray expressionsArray = copy(expressions); - return allocator.alloc(Location{startLocation, endLocation}, stringsArray, expressionsArray); -} - -AstExpr* Parser::parseNumber() -{ - Location start = lexer.current().location; - - scratchData.assign(lexer.current().data, lexer.current().length); - - // Remove all internal _ - they don't hold any meaning and this allows parsing code to just pass the string pointer to strtod et al - if (scratchData.find('_') != std::string::npos) - { - scratchData.erase(std::remove(scratchData.begin(), scratchData.end(), '_'), scratchData.end()); - } - - double value = 0; - ConstantNumberParseResult result = parseDouble(value, scratchData.c_str()); - nextLexeme(); - - if (result == ConstantNumberParseResult::Malformed) - return reportExprError(start, {}, "Malformed number"); - - return allocator.alloc(start, value, result); -} - -AstLocal* Parser::pushLocal(const Binding& binding) -{ - const Name& name = binding.name; - AstLocal*& local = localMap[name.name]; - - local = allocator.alloc( - name.name, name.location, /* shadow= */ local, functionStack.size() - 1, functionStack.back().loopDepth, binding.annotation); - - localStack.push_back(local); - - return local; -} - -unsigned int Parser::saveLocals() -{ - return unsigned(localStack.size()); -} - -void Parser::restoreLocals(unsigned int offset) -{ - for (size_t i = localStack.size(); i > offset; --i) - { - AstLocal* l = localStack[i - 1]; - - localMap[l->name] = l->shadow; - } - - localStack.resize(offset); -} - -bool Parser::expectAndConsume(char value, const char* context) -{ - return expectAndConsume(static_cast(static_cast(value)), context); -} - -bool Parser::expectAndConsume(Lexeme::Type type, const char* context) -{ - if (lexer.current().type != type) - { - expectAndConsumeFail(type, context); - - // check if this is an extra token and the expected token is next - if (lexer.lookahead().type == type) - { - // skip invalid and consume expected - nextLexeme(); - nextLexeme(); - } - - return false; - } - else - { - nextLexeme(); - return true; - } -} - -// LUAU_NOINLINE is used to limit the stack cost of this function due to std::string objects, and to increase caller performance since this code is -// cold -LUAU_NOINLINE void Parser::expectAndConsumeFail(Lexeme::Type type, const char* context) -{ - std::string typeString = Lexeme(Location(Position(0, 0), 0), type).toString(); - std::string currLexemeString = lexer.current().toString(); - - if (context) - report(lexer.current().location, "Expected %s when parsing %s, got %s", typeString.c_str(), context, currLexemeString.c_str()); - else - report(lexer.current().location, "Expected %s, got %s", typeString.c_str(), currLexemeString.c_str()); -} - -bool Parser::expectMatchAndConsume(char value, const MatchLexeme& begin, bool searchForMissing) -{ - Lexeme::Type type = static_cast(static_cast(value)); - - if (lexer.current().type != type) - { - expectMatchAndConsumeFail(type, begin); - - return expectMatchAndConsumeRecover(value, begin, searchForMissing); - } - else - { - nextLexeme(); - - return true; - } -} - -LUAU_NOINLINE bool Parser::expectMatchAndConsumeRecover(char value, const MatchLexeme& begin, bool searchForMissing) -{ - Lexeme::Type type = static_cast(static_cast(value)); - - if (searchForMissing) - { - // previous location is taken because 'current' lexeme is already the next token - unsigned currentLine = lexer.previousLocation().end.line; - - // search to the end of the line for expected token - // we will also stop if we hit a token that can be handled by parsing function above the current one - Lexeme::Type lexemeType = lexer.current().type; - - while (currentLine == lexer.current().location.begin.line && lexemeType != type && matchRecoveryStopOnToken[lexemeType] == 0) - { - nextLexeme(); - lexemeType = lexer.current().type; - } - - if (lexemeType == type) - { - nextLexeme(); - - return true; - } - } - else - { - // check if this is an extra token and the expected token is next - if (lexer.lookahead().type == type) - { - // skip invalid and consume expected - nextLexeme(); - nextLexeme(); - - return true; - } - } - - return false; -} - -// LUAU_NOINLINE is used to limit the stack cost of this function due to std::string objects, and to increase caller performance since this code is -// cold -LUAU_NOINLINE void Parser::expectMatchAndConsumeFail(Lexeme::Type type, const MatchLexeme& begin, const char* extra) -{ - std::string typeString = Lexeme(Location(Position(0, 0), 0), type).toString(); - std::string matchString = Lexeme(Location(Position(0, 0), 0), begin.type).toString(); - - if (lexer.current().location.begin.line == begin.position.line) - report(lexer.current().location, "Expected %s (to close %s at column %d), got %s%s", typeString.c_str(), matchString.c_str(), - begin.position.column + 1, lexer.current().toString().c_str(), extra ? extra : ""); - else - report(lexer.current().location, "Expected %s (to close %s at line %d), got %s%s", typeString.c_str(), matchString.c_str(), - begin.position.line + 1, lexer.current().toString().c_str(), extra ? extra : ""); -} - -bool Parser::expectMatchEndAndConsume(Lexeme::Type type, const MatchLexeme& begin) -{ - if (lexer.current().type != type) - { - expectMatchEndAndConsumeFail(type, begin); - - // check if this is an extra token and the expected token is next - if (lexer.lookahead().type == type) - { - // skip invalid and consume expected - nextLexeme(); - nextLexeme(); - - return true; - } - - return false; - } - else - { - // If the token matches on a different line and a different column, it suggests misleading indentation - // This can be used to pinpoint the problem location for a possible future *actual* mismatch - if (lexer.current().location.begin.line != begin.position.line && lexer.current().location.begin.column != begin.position.column && - endMismatchSuspect.position.line < begin.position.line) // Only replace the previous suspect with more recent suspects - { - endMismatchSuspect = begin; - } - - nextLexeme(); - - return true; - } -} - -// LUAU_NOINLINE is used to limit the stack cost of this function due to std::string objects, and to increase caller performance since this code is -// cold -LUAU_NOINLINE void Parser::expectMatchEndAndConsumeFail(Lexeme::Type type, const MatchLexeme& begin) -{ - if (endMismatchSuspect.type != Lexeme::Eof && endMismatchSuspect.position.line > begin.position.line) - { - std::string matchString = Lexeme(Location(Position(0, 0), 0), endMismatchSuspect.type).toString(); - std::string suggestion = format("; did you forget to close %s at line %d?", matchString.c_str(), endMismatchSuspect.position.line + 1); - - expectMatchAndConsumeFail(type, begin, suggestion.c_str()); - } - else - { - expectMatchAndConsumeFail(type, begin); - } -} - -template -AstArray Parser::copy(const T* data, size_t size) -{ - AstArray result; - - result.data = size ? static_cast(allocator.allocate(sizeof(T) * size)) : nullptr; - result.size = size; - - // This is equivalent to std::uninitialized_copy, but without the exception guarantee - // since our types don't have destructors - for (size_t i = 0; i < size; ++i) - new (result.data + i) T(data[i]); - - return result; -} - -template -AstArray Parser::copy(const TempVector& data) -{ - return copy(data.empty() ? nullptr : &data[0], data.size()); -} - -template -AstArray Parser::copy(std::initializer_list data) -{ - return copy(data.size() == 0 ? nullptr : data.begin(), data.size()); -} - -AstArray Parser::copy(const std::string& data) -{ - AstArray result = copy(data.c_str(), data.size() + 1); - - result.size = data.size(); - - return result; -} - -void Parser::incrementRecursionCounter(const char* context) -{ - recursionCounter++; - - if (recursionCounter > unsigned(FInt::LuauRecursionLimit)) - { - ParseError::raise(lexer.current().location, "Exceeded allowed recursion depth; simplify your %s to make the code compile", context); - } -} - -void Parser::report(const Location& location, const char* format, va_list args) -{ - // To reduce number of errors reported to user for incomplete statements, we skip multiple errors at the same location - // For example, consider 'local a = (((b + ' where multiple tokens haven't been written yet - if (!parseErrors.empty() && location == parseErrors.back().getLocation()) - return; - - std::string message = vformat(format, args); - - // when limited to a single error, behave as if the error recovery is disabled - if (FInt::LuauParseErrorLimit == 1) - throw ParseError(location, message); - - parseErrors.emplace_back(location, message); - - if (parseErrors.size() >= unsigned(FInt::LuauParseErrorLimit)) - ParseError::raise(location, "Reached error limit (%d)", int(FInt::LuauParseErrorLimit)); -} - -void Parser::report(const Location& location, const char* format, ...) -{ - va_list args; - va_start(args, format); - report(location, format, args); - va_end(args); -} - -LUAU_NOINLINE void Parser::reportNameError(const char* context) -{ - if (context) - report(lexer.current().location, "Expected identifier when parsing %s, got %s", context, lexer.current().toString().c_str()); - else - report(lexer.current().location, "Expected identifier, got %s", lexer.current().toString().c_str()); -} - -AstStatError* Parser::reportStatError( - const Location& location, const AstArray& expressions, const AstArray& statements, const char* format, ...) -{ - va_list args; - va_start(args, format); - report(location, format, args); - va_end(args); - - return allocator.alloc(location, expressions, statements, unsigned(parseErrors.size() - 1)); -} - -AstExprError* Parser::reportExprError(const Location& location, const AstArray& expressions, const char* format, ...) -{ - va_list args; - va_start(args, format); - report(location, format, args); - va_end(args); - - return allocator.alloc(location, expressions, unsigned(parseErrors.size() - 1)); -} - -AstTypeError* Parser::reportTypeError(const Location& location, const AstArray& types, const char* format, ...) -{ - va_list args; - va_start(args, format); - report(location, format, args); - va_end(args); - - return allocator.alloc(location, types, false, unsigned(parseErrors.size() - 1)); -} - -AstTypeError* Parser::reportMissingTypeError(const Location& parseErrorLocation, const Location& astErrorLocation, const char* format, ...) -{ - va_list args; - va_start(args, format); - report(parseErrorLocation, format, args); - va_end(args); - - return allocator.alloc(astErrorLocation, AstArray{}, true, unsigned(parseErrors.size() - 1)); -} - -void Parser::nextLexeme() -{ - Lexeme::Type type = lexer.next(/* skipComments= */ false, true).type; - - while (type == Lexeme::BrokenComment || type == Lexeme::Comment || type == Lexeme::BlockComment) - { - const Lexeme& lexeme = lexer.current(); - - if (options.captureComments) - commentLocations.push_back(Comment{lexeme.type, lexeme.location}); - - // Subtlety: Broken comments are weird because we record them as comments AND pass them to the parser as a lexeme. - // The parser will turn this into a proper syntax error. - if (lexeme.type == Lexeme::BrokenComment) - return; - - // Comments starting with ! are called "hot comments" and contain directives for type checking / linting / compiling - if (lexeme.type == Lexeme::Comment && lexeme.length && lexeme.data[0] == '!') - { - const char* text = lexeme.data; - - unsigned int end = lexeme.length; - while (end > 0 && isSpace(text[end - 1])) - --end; - - hotcomments.push_back({hotcommentHeader, lexeme.location, std::string(text + 1, text + end)}); - } - - type = lexer.next(/* skipComments= */ false, /* updatePrevLocation= */ false).type; - } -} - -} // namespace Luau diff --git a/lib/luau/Ast/src/StringUtils.cpp b/lib/luau/Ast/src/StringUtils.cpp deleted file mode 100644 index d7099a3..0000000 --- a/lib/luau/Ast/src/StringUtils.cpp +++ /dev/null @@ -1,297 +0,0 @@ -// This file is part of the Luau programming language and is licensed under MIT License; see LICENSE.txt for details -#include "Luau/StringUtils.h" - -#include "Luau/Common.h" - -#include -#include -#include -#include -#include - -namespace Luau -{ - -void vformatAppend(std::string& ret, const char* fmt, va_list args) -{ - va_list argscopy; - va_copy(argscopy, args); -#ifdef _MSC_VER - int actualSize = _vscprintf(fmt, argscopy); -#else - int actualSize = vsnprintf(NULL, 0, fmt, argscopy); -#endif - va_end(argscopy); - - if (actualSize <= 0) - return; - - size_t sz = ret.size(); - ret.resize(sz + actualSize); - vsnprintf(&ret[0] + sz, actualSize + 1, fmt, args); -} - -std::string format(const char* fmt, ...) -{ - std::string result; - va_list args; - va_start(args, fmt); - vformatAppend(result, fmt, args); - va_end(args); - return result; -} - -void formatAppend(std::string& str, const char* fmt, ...) -{ - va_list args; - va_start(args, fmt); - vformatAppend(str, fmt, args); - va_end(args); -} - -std::string vformat(const char* fmt, va_list args) -{ - std::string ret; - vformatAppend(ret, fmt, args); - return ret; -} - -template -static std::string joinImpl(const std::vector& segments, std::string_view delimiter) -{ - if (segments.empty()) - return ""; - - size_t len = (segments.size() - 1) * delimiter.size(); - for (const auto& sv : segments) - len += sv.size(); - - std::string result; - result.resize(len); - char* dest = const_cast(result.data()); // This const_cast is only necessary until C++17 - - auto it = segments.begin(); - memcpy(dest, it->data(), it->size()); - dest += it->size(); - ++it; - for (; it != segments.end(); ++it) - { - memcpy(dest, delimiter.data(), delimiter.size()); - dest += delimiter.size(); - memcpy(dest, it->data(), it->size()); - dest += it->size(); - } - - LUAU_ASSERT(dest == result.data() + len); - - return result; -} - -std::string join(const std::vector& segments, std::string_view delimiter) -{ - return joinImpl(segments, delimiter); -} - -std::string join(const std::vector& segments, std::string_view delimiter) -{ - return joinImpl(segments, delimiter); -} - -std::vector split(std::string_view s, char delimiter) -{ - std::vector result; - - while (!s.empty()) - { - auto index = s.find(delimiter); - if (index == std::string::npos) - { - result.push_back(s); - break; - } - result.push_back(s.substr(0, index)); - s.remove_prefix(index + 1); - } - - return result; -} - -size_t editDistance(std::string_view a, std::string_view b) -{ - // When there are matching prefix and suffix, they end up computing as zero cost, effectively making it no-op. We drop these characters. - while (!a.empty() && !b.empty() && a.front() == b.front()) - { - a.remove_prefix(1); - b.remove_prefix(1); - } - - while (!a.empty() && !b.empty() && a.back() == b.back()) - { - a.remove_suffix(1); - b.remove_suffix(1); - } - - // Since we know the edit distance is the difference of the length of A and B discounting the matching prefixes and suffixes, - // it is therefore pointless to run the rest of this function to find that out. We immediately infer this size and return it. - if (a.empty()) - return b.size(); - if (b.empty()) - return a.size(); - - size_t maxDistance = a.size() + b.size(); - - std::vector distances((a.size() + 2) * (b.size() + 2), 0); - auto getPos = [b](size_t x, size_t y) -> size_t { - return (x * (b.size() + 2)) + y; - }; - - distances[0] = maxDistance; - - for (size_t x = 0; x <= a.size(); ++x) - { - distances[getPos(x + 1, 0)] = maxDistance; - distances[getPos(x + 1, 1)] = x; - } - - for (size_t y = 0; y <= b.size(); ++y) - { - distances[getPos(0, y + 1)] = maxDistance; - distances[getPos(1, y + 1)] = y; - } - - std::array seenCharToRow; - seenCharToRow.fill(0); - - for (size_t x = 1; x <= a.size(); ++x) - { - size_t lastMatchedY = 0; - - for (size_t y = 1; y <= b.size(); ++y) - { - // The value of b[N] can be negative with unicode characters - unsigned char bSeenCharIndex = static_cast(b[y - 1]); - size_t x1 = seenCharToRow[bSeenCharIndex]; - size_t y1 = lastMatchedY; - - size_t cost = 1; - if (a[x - 1] == b[y - 1]) - { - cost = 0; - lastMatchedY = y; - } - - size_t transposition = distances[getPos(x1, y1)] + (x - x1 - 1) + 1 + (y - y1 - 1); - size_t substitution = distances[getPos(x, y)] + cost; - size_t insertion = distances[getPos(x, y + 1)] + 1; - size_t deletion = distances[getPos(x + 1, y)] + 1; - - // It's more performant to use std::min(size_t, size_t) rather than the initializer_list overload. - // Until proven otherwise, please do not change this. - distances[getPos(x + 1, y + 1)] = std::min(std::min(insertion, deletion), std::min(substitution, transposition)); - } - - // The value of a[N] can be negative with unicode characters - unsigned char aSeenCharIndex = static_cast(a[x - 1]); - seenCharToRow[aSeenCharIndex] = x; - } - - return distances[getPos(a.size() + 1, b.size() + 1)]; -} - -bool startsWith(std::string_view haystack, std::string_view needle) -{ - // ::starts_with is C++20 - return haystack.size() >= needle.size() && haystack.substr(0, needle.size()) == needle; -} - -bool equalsLower(std::string_view lhs, std::string_view rhs) -{ - if (lhs.size() != rhs.size()) - return false; - - for (size_t i = 0; i < lhs.size(); ++i) - if (tolower(uint8_t(lhs[i])) != tolower(uint8_t(rhs[i]))) - return false; - - return true; -} - -size_t hashRange(const char* data, size_t size) -{ - // FNV-1a - uint32_t hash = 2166136261; - - for (size_t i = 0; i < size; ++i) - { - hash ^= uint8_t(data[i]); - hash *= 16777619; - } - - return hash; -} - -bool isIdentifier(std::string_view s) -{ - return (s.find_first_not_of("abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ01234567890_") == std::string::npos); -} - -std::string escape(std::string_view s, bool escapeForInterpString) -{ - std::string r; - r.reserve(s.size() + 50); // arbitrary number to guess how many characters we'll be inserting - - for (uint8_t c : s) - { - if (c >= ' ' && c != '\\' && c != '\'' && c != '\"' && c != '`' && c != '{') - r += c; - else - { - r += '\\'; - - if (escapeForInterpString && (c == '`' || c == '{')) - { - r += c; - continue; - } - - switch (c) - { - case '\a': - r += 'a'; - break; - case '\b': - r += 'b'; - break; - case '\f': - r += 'f'; - break; - case '\n': - r += 'n'; - break; - case '\r': - r += 'r'; - break; - case '\t': - r += 't'; - break; - case '\v': - r += 'v'; - break; - case '\'': - r += '\''; - break; - case '\"': - r += '\"'; - break; - case '\\': - r += '\\'; - break; - default: - Luau::formatAppend(r, "%03u", c); - } - } - } - - return r; -} -} // namespace Luau diff --git a/lib/luau/Ast/src/TimeTrace.cpp b/lib/luau/Ast/src/TimeTrace.cpp deleted file mode 100644 index bc3f353..0000000 --- a/lib/luau/Ast/src/TimeTrace.cpp +++ /dev/null @@ -1,264 +0,0 @@ -// This file is part of the Luau programming language and is licensed under MIT License; see LICENSE.txt for details -#include "Luau/TimeTrace.h" - -#include "Luau/StringUtils.h" - -#include -#include - -#include - -#ifdef _WIN32 -#ifndef WIN32_LEAN_AND_MEAN -#define WIN32_LEAN_AND_MEAN -#endif -#ifndef NOMINMAX -#define NOMINMAX -#endif -#include -#endif - -#ifdef __APPLE__ -#include -#include -#endif - -#include - -LUAU_FASTFLAGVARIABLE(DebugLuauTimeTracing, false) -namespace Luau -{ -namespace TimeTrace -{ -static double getClockPeriod() -{ -#if defined(_WIN32) - LARGE_INTEGER result = {}; - QueryPerformanceFrequency(&result); - return 1.0 / double(result.QuadPart); -#elif defined(__APPLE__) - mach_timebase_info_data_t result = {}; - mach_timebase_info(&result); - return double(result.numer) / double(result.denom) * 1e-9; -#elif defined(__linux__) - return 1e-9; -#else - return 1.0 / double(CLOCKS_PER_SEC); -#endif -} - -static double getClockTimestamp() -{ -#if defined(_WIN32) - LARGE_INTEGER result = {}; - QueryPerformanceCounter(&result); - return double(result.QuadPart); -#elif defined(__APPLE__) - return double(mach_absolute_time()); -#elif defined(__linux__) - timespec now; - clock_gettime(CLOCK_MONOTONIC, &now); - return now.tv_sec * 1e9 + now.tv_nsec; -#else - return double(clock()); -#endif -} - -double getClock() -{ - static double period = getClockPeriod(); - static double start = getClockTimestamp(); - - return (getClockTimestamp() - start) * period; -} - -uint32_t getClockMicroseconds() -{ - static double period = getClockPeriod() * 1e6; - static double start = getClockTimestamp(); - - return uint32_t((getClockTimestamp() - start) * period); -} -} // namespace TimeTrace -} // namespace Luau - -#if defined(LUAU_ENABLE_TIME_TRACE) - -namespace Luau -{ -namespace TimeTrace -{ -struct GlobalContext -{ - ~GlobalContext() - { - if (traceFile) - fclose(traceFile); - } - - std::mutex mutex; - std::vector threads; - uint32_t nextThreadId = 0; - std::vector tokens; - FILE* traceFile = nullptr; - -private: - friend std::shared_ptr getGlobalContext(); - GlobalContext() = default; -}; - -std::shared_ptr getGlobalContext() -{ - static std::shared_ptr context = std::shared_ptr{new GlobalContext}; - return context; -} - -uint16_t createToken(GlobalContext& context, const char* name, const char* category) -{ - std::scoped_lock lock(context.mutex); - - LUAU_ASSERT(context.tokens.size() < 64 * 1024); - - context.tokens.push_back({name, category}); - return uint16_t(context.tokens.size() - 1); -} - -uint32_t createThread(GlobalContext& context, ThreadContext* threadContext) -{ - std::scoped_lock lock(context.mutex); - - context.threads.push_back(threadContext); - - return ++context.nextThreadId; -} - -void releaseThread(GlobalContext& context, ThreadContext* threadContext) -{ - std::scoped_lock lock(context.mutex); - - if (auto it = std::find(context.threads.begin(), context.threads.end(), threadContext); it != context.threads.end()) - context.threads.erase(it); -} - -void flushEvents(GlobalContext& context, uint32_t threadId, const std::vector& events, const std::vector& data) -{ - std::scoped_lock lock(context.mutex); - - if (!context.traceFile) - { - context.traceFile = fopen("trace.json", "w"); - - if (!context.traceFile) - return; - - fprintf(context.traceFile, "[\n"); - } - - std::string temp; - const unsigned tempReserve = 64 * 1024; - temp.reserve(tempReserve); - - const char* rawData = data.data(); - - // Formatting state - bool unfinishedEnter = false; - bool unfinishedArgs = false; - - for (const Event& ev : events) - { - switch (ev.type) - { - case EventType::Enter: - { - if (unfinishedArgs) - { - formatAppend(temp, "}"); - unfinishedArgs = false; - } - - if (unfinishedEnter) - { - formatAppend(temp, "},\n"); - unfinishedEnter = false; - } - - Token& token = context.tokens[ev.token]; - - formatAppend(temp, R"({"name": "%s", "cat": "%s", "ph": "B", "ts": %u, "pid": 0, "tid": %u)", token.name, token.category, - ev.data.microsec, threadId); - unfinishedEnter = true; - } - break; - case EventType::Leave: - if (unfinishedArgs) - { - formatAppend(temp, "}"); - unfinishedArgs = false; - } - if (unfinishedEnter) - { - formatAppend(temp, "},\n"); - unfinishedEnter = false; - } - - formatAppend(temp, - R"({"ph": "E", "ts": %u, "pid": 0, "tid": %u},)" - "\n", - ev.data.microsec, threadId); - break; - case EventType::ArgName: - LUAU_ASSERT(unfinishedEnter); - - if (!unfinishedArgs) - { - formatAppend(temp, R"(, "args": { "%s": )", rawData + ev.data.dataPos); - unfinishedArgs = true; - } - else - { - formatAppend(temp, R"(, "%s": )", rawData + ev.data.dataPos); - } - break; - case EventType::ArgValue: - LUAU_ASSERT(unfinishedArgs); - formatAppend(temp, R"("%s")", rawData + ev.data.dataPos); - break; - } - - // Don't want to hit the string capacity and reallocate - if (temp.size() > tempReserve - 1024) - { - fwrite(temp.data(), 1, temp.size(), context.traceFile); - temp.clear(); - } - } - - if (unfinishedArgs) - { - formatAppend(temp, "}"); - unfinishedArgs = false; - } - if (unfinishedEnter) - { - formatAppend(temp, "},\n"); - unfinishedEnter = false; - } - - fwrite(temp.data(), 1, temp.size(), context.traceFile); - fflush(context.traceFile); -} - -ThreadContext& getThreadContext() -{ - thread_local ThreadContext context; - return context; -} - -uint16_t createScopeData(const char* name, const char* category) -{ - return createToken(*Luau::TimeTrace::getGlobalContext(), name, category); -} -} // namespace TimeTrace -} // namespace Luau - -#endif diff --git a/lib/luau/Common/include/Luau/Bytecode.h b/lib/luau/Common/include/Luau/Bytecode.h deleted file mode 100644 index e3c2067..0000000 --- a/lib/luau/Common/include/Luau/Bytecode.h +++ /dev/null @@ -1,604 +0,0 @@ -// This file is part of the Luau programming language and is licensed under MIT License; see LICENSE.txt for details -#pragma once - -// clang-format off - -// This header contains the bytecode definition for Luau interpreter -// Creating the bytecode is outside the scope of this file and is handled by bytecode builder (BytecodeBuilder.h) and bytecode compiler (Compiler.h) -// Note that ALL enums declared in this file are order-sensitive since the values are baked into bytecode that needs to be processed by legacy clients. - -// # Bytecode definitions -// Bytecode instructions are using "word code" - each instruction is one or many 32-bit words. -// The first word in the instruction is always the instruction header, and *must* contain the opcode (enum below) in the least significant byte. -// -// Instruction word can be encoded using one of the following encodings: -// ABC - least-significant byte for the opcode, followed by three bytes, A, B and C; each byte declares a register index, small index into some other table or an unsigned integral value -// AD - least-significant byte for the opcode, followed by A byte, followed by D half-word (16-bit integer). D is a signed integer that commonly specifies constant table index or jump offset -// E - least-significant byte for the opcode, followed by E (24-bit integer). E is a signed integer that commonly specifies a jump offset -// -// Instruction word is sometimes followed by one extra word, indicated as AUX - this is just a 32-bit word and is decoded according to the specification for each opcode. -// For each opcode the encoding is *static* - that is, based on the opcode you know a-priory how large the instruction is, with the exception of NEWCLOSURE - -// # Bytecode indices -// Bytecode instructions commonly refer to integer values that define offsets or indices for various entities. For each type, there's a maximum encodable value. -// Note that in some cases, the compiler will set a lower limit than the maximum encodable value is to prevent fragile code into bumping against the limits whenever we change the compilation details. -// Additionally, in some specific instructions such as ANDK, the limit on the encoded value is smaller; this means that if a value is larger, a different instruction must be selected. -// -// Registers: 0-254. Registers refer to the values on the function's stack frame, including arguments. -// Upvalues: 0-199. Upvalues refer to the values stored in the closure object. -// Constants: 0-2^23-1. Constants are stored in a table allocated with each proto; to allow for future bytecode tweaks the encodable value is limited to 23 bits. -// Closures: 0-2^15-1. Closures are created from child protos via a child index; the limit is for the number of closures immediately referenced in each function. -// Jumps: -2^23..2^23. Jump offsets are specified in word increments, so jumping over an instruction may sometimes require an offset of 2 or more. Note that for jump instructions with AUX, the AUX word is included as part of the jump offset. - -// # Bytecode versions -// Bytecode serialized format embeds a version number, that dictates both the serialized form as well as the allowed instructions. As long as the bytecode version falls into supported -// range (indicated by LBC_BYTECODE_MIN / LBC_BYTECODE_MAX) and was produced by Luau compiler, it should load and execute correctly. -// -// Note that Luau runtime doesn't provide indefinite bytecode compatibility: support for older versions gets removed over time. As such, bytecode isn't a durable storage format and it's expected -// that Luau users can recompile bytecode from source on Luau version upgrades if necessary. - -// # Bytecode version history -// -// Note: due to limitations of the versioning scheme, some bytecode blobs that carry version 2 are using features from version 3. Starting from version 3, version should be sufficient to indicate bytecode compatibility. -// -// Version 1: Baseline version for the open-source release. Supported until 0.521. -// Version 2: Adds Proto::linedefined. Supported until 0.544. -// Version 3: Adds FORGPREP/JUMPXEQK* and enhances AUX encoding for FORGLOOP. Removes FORGLOOP_NEXT/INEXT and JUMPIFEQK/JUMPIFNOTEQK. Currently supported. -// Version 4: Adds Proto::flags, typeinfo, and floor division opcodes IDIV/IDIVK. Currently supported. -// Version 5: Adds SUBRK/DIVRK and vector constants. Currently supported. - -// Bytecode opcode, part of the instruction header -enum LuauOpcode -{ - // NOP: noop - LOP_NOP, - - // BREAK: debugger break - LOP_BREAK, - - // LOADNIL: sets register to nil - // A: target register - LOP_LOADNIL, - - // LOADB: sets register to boolean and jumps to a given short offset (used to compile comparison results into a boolean) - // A: target register - // B: value (0/1) - // C: jump offset - LOP_LOADB, - - // LOADN: sets register to a number literal - // A: target register - // D: value (-32768..32767) - LOP_LOADN, - - // LOADK: sets register to an entry from the constant table from the proto (number/vector/string) - // A: target register - // D: constant table index (0..32767) - LOP_LOADK, - - // MOVE: move (copy) value from one register to another - // A: target register - // B: source register - LOP_MOVE, - - // GETGLOBAL: load value from global table using constant string as a key - // A: target register - // C: predicted slot index (based on hash) - // AUX: constant table index - LOP_GETGLOBAL, - - // SETGLOBAL: set value in global table using constant string as a key - // A: source register - // C: predicted slot index (based on hash) - // AUX: constant table index - LOP_SETGLOBAL, - - // GETUPVAL: load upvalue from the upvalue table for the current function - // A: target register - // B: upvalue index - LOP_GETUPVAL, - - // SETUPVAL: store value into the upvalue table for the current function - // A: target register - // B: upvalue index - LOP_SETUPVAL, - - // CLOSEUPVALS: close (migrate to heap) all upvalues that were captured for registers >= target - // A: target register - LOP_CLOSEUPVALS, - - // GETIMPORT: load imported global table global from the constant table - // A: target register - // D: constant table index (0..32767); we assume that imports are loaded into the constant table - // AUX: 3 10-bit indices of constant strings that, combined, constitute an import path; length of the path is set by the top 2 bits (1,2,3) - LOP_GETIMPORT, - - // GETTABLE: load value from table into target register using key from register - // A: target register - // B: table register - // C: index register - LOP_GETTABLE, - - // SETTABLE: store source register into table using key from register - // A: source register - // B: table register - // C: index register - LOP_SETTABLE, - - // GETTABLEKS: load value from table into target register using constant string as a key - // A: target register - // B: table register - // C: predicted slot index (based on hash) - // AUX: constant table index - LOP_GETTABLEKS, - - // SETTABLEKS: store source register into table using constant string as a key - // A: source register - // B: table register - // C: predicted slot index (based on hash) - // AUX: constant table index - LOP_SETTABLEKS, - - // GETTABLEN: load value from table into target register using small integer index as a key - // A: target register - // B: table register - // C: index-1 (index is 1..256) - LOP_GETTABLEN, - - // SETTABLEN: store source register into table using small integer index as a key - // A: source register - // B: table register - // C: index-1 (index is 1..256) - LOP_SETTABLEN, - - // NEWCLOSURE: create closure from a child proto; followed by a CAPTURE instruction for each upvalue - // A: target register - // D: child proto index (0..32767) - LOP_NEWCLOSURE, - - // NAMECALL: prepare to call specified method by name by loading function from source register using constant index into target register and copying source register into target register + 1 - // A: target register - // B: source register - // C: predicted slot index (based on hash) - // AUX: constant table index - // Note that this instruction must be followed directly by CALL; it prepares the arguments - // This instruction is roughly equivalent to GETTABLEKS + MOVE pair, but we need a special instruction to support custom __namecall metamethod - LOP_NAMECALL, - - // CALL: call specified function - // A: register where the function object lives, followed by arguments; results are placed starting from the same register - // B: argument count + 1, or 0 to preserve all arguments up to top (MULTRET) - // C: result count + 1, or 0 to preserve all values and adjust top (MULTRET) - LOP_CALL, - - // RETURN: returns specified values from the function - // A: register where the returned values start - // B: number of returned values + 1, or 0 to return all values up to top (MULTRET) - LOP_RETURN, - - // JUMP: jumps to target offset - // D: jump offset (-32768..32767; 0 means "next instruction" aka "don't jump") - LOP_JUMP, - - // JUMPBACK: jumps to target offset; this is equivalent to JUMP but is used as a safepoint to be able to interrupt while/repeat loops - // D: jump offset (-32768..32767; 0 means "next instruction" aka "don't jump") - LOP_JUMPBACK, - - // JUMPIF: jumps to target offset if register is not nil/false - // A: source register - // D: jump offset (-32768..32767; 0 means "next instruction" aka "don't jump") - LOP_JUMPIF, - - // JUMPIFNOT: jumps to target offset if register is nil/false - // A: source register - // D: jump offset (-32768..32767; 0 means "next instruction" aka "don't jump") - LOP_JUMPIFNOT, - - // JUMPIFEQ, JUMPIFLE, JUMPIFLT, JUMPIFNOTEQ, JUMPIFNOTLE, JUMPIFNOTLT: jumps to target offset if the comparison is true (or false, for NOT variants) - // A: source register 1 - // D: jump offset (-32768..32767; 1 means "next instruction" aka "don't jump") - // AUX: source register 2 - LOP_JUMPIFEQ, - LOP_JUMPIFLE, - LOP_JUMPIFLT, - LOP_JUMPIFNOTEQ, - LOP_JUMPIFNOTLE, - LOP_JUMPIFNOTLT, - - // ADD, SUB, MUL, DIV, MOD, POW: compute arithmetic operation between two source registers and put the result into target register - // A: target register - // B: source register 1 - // C: source register 2 - LOP_ADD, - LOP_SUB, - LOP_MUL, - LOP_DIV, - LOP_MOD, - LOP_POW, - - // ADDK, SUBK, MULK, DIVK, MODK, POWK: compute arithmetic operation between the source register and a constant and put the result into target register - // A: target register - // B: source register - // C: constant table index (0..255); must refer to a number - LOP_ADDK, - LOP_SUBK, - LOP_MULK, - LOP_DIVK, - LOP_MODK, - LOP_POWK, - - // AND, OR: perform `and` or `or` operation (selecting first or second register based on whether the first one is truthy) and put the result into target register - // A: target register - // B: source register 1 - // C: source register 2 - LOP_AND, - LOP_OR, - - // ANDK, ORK: perform `and` or `or` operation (selecting source register or constant based on whether the source register is truthy) and put the result into target register - // A: target register - // B: source register - // C: constant table index (0..255) - LOP_ANDK, - LOP_ORK, - - // CONCAT: concatenate all strings between B and C (inclusive) and put the result into A - // A: target register - // B: source register start - // C: source register end - LOP_CONCAT, - - // NOT, MINUS, LENGTH: compute unary operation for source register and put the result into target register - // A: target register - // B: source register - LOP_NOT, - LOP_MINUS, - LOP_LENGTH, - - // NEWTABLE: create table in target register - // A: target register - // B: table size, stored as 0 for v=0 and ceil(log2(v))+1 for v!=0 - // AUX: array size - LOP_NEWTABLE, - - // DUPTABLE: duplicate table using the constant table template to target register - // A: target register - // D: constant table index (0..32767) - LOP_DUPTABLE, - - // SETLIST: set a list of values to table in target register - // A: target register - // B: source register start - // C: value count + 1, or 0 to use all values up to top (MULTRET) - // AUX: table index to start from - LOP_SETLIST, - - // FORNPREP: prepare a numeric for loop, jump over the loop if first iteration doesn't need to run - // A: target register; numeric for loops assume a register layout [limit, step, index, variable] - // D: jump offset (-32768..32767) - // limit/step are immutable, index isn't visible to user code since it's copied into variable - LOP_FORNPREP, - - // FORNLOOP: adjust loop variables for one iteration, jump back to the loop header if loop needs to continue - // A: target register; see FORNPREP for register layout - // D: jump offset (-32768..32767) - LOP_FORNLOOP, - - // FORGLOOP: adjust loop variables for one iteration of a generic for loop, jump back to the loop header if loop needs to continue - // A: target register; generic for loops assume a register layout [generator, state, index, variables...] - // D: jump offset (-32768..32767) - // AUX: variable count (1..255) in the low 8 bits, high bit indicates whether to use ipairs-style traversal in the fast path - // loop variables are adjusted by calling generator(state, index) and expecting it to return a tuple that's copied to the user variables - // the first variable is then copied into index; generator/state are immutable, index isn't visible to user code - LOP_FORGLOOP, - - // FORGPREP_INEXT: prepare FORGLOOP with 2 output variables (no AUX encoding), assuming generator is luaB_inext, and jump to FORGLOOP - // A: target register (see FORGLOOP for register layout) - LOP_FORGPREP_INEXT, - - // removed in v3 - LOP_DEP_FORGLOOP_INEXT, - - // FORGPREP_NEXT: prepare FORGLOOP with 2 output variables (no AUX encoding), assuming generator is luaB_next, and jump to FORGLOOP - // A: target register (see FORGLOOP for register layout) - LOP_FORGPREP_NEXT, - - // NATIVECALL: start executing new function in native code - // this is a pseudo-instruction that is never emitted by bytecode compiler, but can be constructed at runtime to accelerate native code dispatch - LOP_NATIVECALL, - - // GETVARARGS: copy variables into the target register from vararg storage for current function - // A: target register - // B: variable count + 1, or 0 to copy all variables and adjust top (MULTRET) - LOP_GETVARARGS, - - // DUPCLOSURE: create closure from a pre-created function object (reusing it unless environments diverge) - // A: target register - // D: constant table index (0..32767) - LOP_DUPCLOSURE, - - // PREPVARARGS: prepare stack for variadic functions so that GETVARARGS works correctly - // A: number of fixed arguments - LOP_PREPVARARGS, - - // LOADKX: sets register to an entry from the constant table from the proto (number/string) - // A: target register - // AUX: constant table index - LOP_LOADKX, - - // JUMPX: jumps to the target offset; like JUMPBACK, supports interruption - // E: jump offset (-2^23..2^23; 0 means "next instruction" aka "don't jump") - LOP_JUMPX, - - // FASTCALL: perform a fast call of a built-in function - // A: builtin function id (see LuauBuiltinFunction) - // C: jump offset to get to following CALL - // FASTCALL is followed by one of (GETIMPORT, MOVE, GETUPVAL) instructions and by CALL instruction - // This is necessary so that if FASTCALL can't perform the call inline, it can continue normal execution - // If FASTCALL *can* perform the call, it jumps over the instructions *and* over the next CALL - // Note that FASTCALL will read the actual call arguments, such as argument/result registers and counts, from the CALL instruction - LOP_FASTCALL, - - // COVERAGE: update coverage information stored in the instruction - // E: hit count for the instruction (0..2^23-1) - // The hit count is incremented by VM every time the instruction is executed, and saturates at 2^23-1 - LOP_COVERAGE, - - // CAPTURE: capture a local or an upvalue as an upvalue into a newly created closure; only valid after NEWCLOSURE - // A: capture type, see LuauCaptureType - // B: source register (for VAL/REF) or upvalue index (for UPVAL/UPREF) - LOP_CAPTURE, - - // SUBRK, DIVRK: compute arithmetic operation between the constant and a source register and put the result into target register - // A: target register - // B: source register - // C: constant table index (0..255); must refer to a number - LOP_SUBRK, - LOP_DIVRK, - - // FASTCALL1: perform a fast call of a built-in function using 1 register argument - // A: builtin function id (see LuauBuiltinFunction) - // B: source argument register - // C: jump offset to get to following CALL - LOP_FASTCALL1, - - // FASTCALL2: perform a fast call of a built-in function using 2 register arguments - // A: builtin function id (see LuauBuiltinFunction) - // B: source argument register - // C: jump offset to get to following CALL - // AUX: source register 2 in least-significant byte - LOP_FASTCALL2, - - // FASTCALL2K: perform a fast call of a built-in function using 1 register argument and 1 constant argument - // A: builtin function id (see LuauBuiltinFunction) - // B: source argument register - // C: jump offset to get to following CALL - // AUX: constant index - LOP_FASTCALL2K, - - // FORGPREP: prepare loop variables for a generic for loop, jump to the loop backedge unconditionally - // A: target register; generic for loops assume a register layout [generator, state, index, variables...] - // D: jump offset (-32768..32767) - LOP_FORGPREP, - - // JUMPXEQKNIL, JUMPXEQKB: jumps to target offset if the comparison with constant is true (or false, see AUX) - // A: source register 1 - // D: jump offset (-32768..32767; 1 means "next instruction" aka "don't jump") - // AUX: constant value (for boolean) in low bit, NOT flag (that flips comparison result) in high bit - LOP_JUMPXEQKNIL, - LOP_JUMPXEQKB, - - // JUMPXEQKN, JUMPXEQKS: jumps to target offset if the comparison with constant is true (or false, see AUX) - // A: source register 1 - // D: jump offset (-32768..32767; 1 means "next instruction" aka "don't jump") - // AUX: constant table index in low 24 bits, NOT flag (that flips comparison result) in high bit - LOP_JUMPXEQKN, - LOP_JUMPXEQKS, - - // IDIV: compute floor division between two source registers and put the result into target register - // A: target register - // B: source register 1 - // C: source register 2 - LOP_IDIV, - - // IDIVK compute floor division between the source register and a constant and put the result into target register - // A: target register - // B: source register - // C: constant table index (0..255) - LOP_IDIVK, - - // Enum entry for number of opcodes, not a valid opcode by itself! - LOP__COUNT -}; - -// Bytecode instruction header: it's always a 32-bit integer, with low byte (first byte in little endian) containing the opcode -// Some instruction types require more data and have more 32-bit integers following the header -#define LUAU_INSN_OP(insn) ((insn) & 0xff) - -// ABC encoding: three 8-bit values, containing registers or small numbers -#define LUAU_INSN_A(insn) (((insn) >> 8) & 0xff) -#define LUAU_INSN_B(insn) (((insn) >> 16) & 0xff) -#define LUAU_INSN_C(insn) (((insn) >> 24) & 0xff) - -// AD encoding: one 8-bit value, one signed 16-bit value -#define LUAU_INSN_D(insn) (int32_t(insn) >> 16) - -// E encoding: one signed 24-bit value -#define LUAU_INSN_E(insn) (int32_t(insn) >> 8) - -// Bytecode tags, used internally for bytecode encoded as a string -enum LuauBytecodeTag -{ - // Bytecode version; runtime supports [MIN, MAX], compiler emits TARGET by default but may emit a higher version when flags are enabled - LBC_VERSION_MIN = 3, - LBC_VERSION_MAX = 5, - LBC_VERSION_TARGET = 4, - // Type encoding version - LBC_TYPE_VERSION = 1, - // Types of constant table entries - LBC_CONSTANT_NIL = 0, - LBC_CONSTANT_BOOLEAN, - LBC_CONSTANT_NUMBER, - LBC_CONSTANT_STRING, - LBC_CONSTANT_IMPORT, - LBC_CONSTANT_TABLE, - LBC_CONSTANT_CLOSURE, - LBC_CONSTANT_VECTOR, -}; - -// Type table tags -enum LuauBytecodeType -{ - LBC_TYPE_NIL = 0, - LBC_TYPE_BOOLEAN, - LBC_TYPE_NUMBER, - LBC_TYPE_STRING, - LBC_TYPE_TABLE, - LBC_TYPE_FUNCTION, - LBC_TYPE_THREAD, - LBC_TYPE_USERDATA, - LBC_TYPE_VECTOR, - LBC_TYPE_BUFFER, - - LBC_TYPE_ANY = 15, - LBC_TYPE_OPTIONAL_BIT = 1 << 7, - - LBC_TYPE_INVALID = 256, -}; - -// Builtin function ids, used in LOP_FASTCALL -enum LuauBuiltinFunction -{ - LBF_NONE = 0, - - // assert() - LBF_ASSERT, - - // math. - LBF_MATH_ABS, - LBF_MATH_ACOS, - LBF_MATH_ASIN, - LBF_MATH_ATAN2, - LBF_MATH_ATAN, - LBF_MATH_CEIL, - LBF_MATH_COSH, - LBF_MATH_COS, - LBF_MATH_DEG, - LBF_MATH_EXP, - LBF_MATH_FLOOR, - LBF_MATH_FMOD, - LBF_MATH_FREXP, - LBF_MATH_LDEXP, - LBF_MATH_LOG10, - LBF_MATH_LOG, - LBF_MATH_MAX, - LBF_MATH_MIN, - LBF_MATH_MODF, - LBF_MATH_POW, - LBF_MATH_RAD, - LBF_MATH_SINH, - LBF_MATH_SIN, - LBF_MATH_SQRT, - LBF_MATH_TANH, - LBF_MATH_TAN, - - // bit32. - LBF_BIT32_ARSHIFT, - LBF_BIT32_BAND, - LBF_BIT32_BNOT, - LBF_BIT32_BOR, - LBF_BIT32_BXOR, - LBF_BIT32_BTEST, - LBF_BIT32_EXTRACT, - LBF_BIT32_LROTATE, - LBF_BIT32_LSHIFT, - LBF_BIT32_REPLACE, - LBF_BIT32_RROTATE, - LBF_BIT32_RSHIFT, - - // type() - LBF_TYPE, - - // string. - LBF_STRING_BYTE, - LBF_STRING_CHAR, - LBF_STRING_LEN, - - // typeof() - LBF_TYPEOF, - - // string. - LBF_STRING_SUB, - - // math. - LBF_MATH_CLAMP, - LBF_MATH_SIGN, - LBF_MATH_ROUND, - - // raw* - LBF_RAWSET, - LBF_RAWGET, - LBF_RAWEQUAL, - - // table. - LBF_TABLE_INSERT, - LBF_TABLE_UNPACK, - - // vector ctor - LBF_VECTOR, - - // bit32.count - LBF_BIT32_COUNTLZ, - LBF_BIT32_COUNTRZ, - - // select(_, ...) - LBF_SELECT_VARARG, - - // rawlen - LBF_RAWLEN, - - // bit32.extract(_, k, k) - LBF_BIT32_EXTRACTK, - - // get/setmetatable - LBF_GETMETATABLE, - LBF_SETMETATABLE, - - // tonumber/tostring - LBF_TONUMBER, - LBF_TOSTRING, - - // bit32.byteswap(n) - LBF_BIT32_BYTESWAP, - - // buffer. - LBF_BUFFER_READI8, - LBF_BUFFER_READU8, - LBF_BUFFER_WRITEU8, - LBF_BUFFER_READI16, - LBF_BUFFER_READU16, - LBF_BUFFER_WRITEU16, - LBF_BUFFER_READI32, - LBF_BUFFER_READU32, - LBF_BUFFER_WRITEU32, - LBF_BUFFER_READF32, - LBF_BUFFER_WRITEF32, - LBF_BUFFER_READF64, - LBF_BUFFER_WRITEF64, -}; - -// Capture type, used in LOP_CAPTURE -enum LuauCaptureType -{ - LCT_VAL = 0, - LCT_REF, - LCT_UPVAL, -}; - -// Proto flag bitmask, stored in Proto::flags -enum LuauProtoFlag -{ - // used to tag main proto for modules with --!native - LPF_NATIVE_MODULE = 1 << 0, - // used to tag individual protos as not profitable to compile natively - LPF_NATIVE_COLD = 1 << 1, -}; diff --git a/lib/luau/Common/include/Luau/BytecodeUtils.h b/lib/luau/Common/include/Luau/BytecodeUtils.h deleted file mode 100644 index 957c804..0000000 --- a/lib/luau/Common/include/Luau/BytecodeUtils.h +++ /dev/null @@ -1,42 +0,0 @@ -// This file is part of the Luau programming language and is licensed under MIT License; see LICENSE.txt for details -#pragma once - -#include "Luau/Bytecode.h" - -namespace Luau -{ - -inline int getOpLength(LuauOpcode op) -{ - switch (op) - { - case LOP_GETGLOBAL: - case LOP_SETGLOBAL: - case LOP_GETIMPORT: - case LOP_GETTABLEKS: - case LOP_SETTABLEKS: - case LOP_NAMECALL: - case LOP_JUMPIFEQ: - case LOP_JUMPIFLE: - case LOP_JUMPIFLT: - case LOP_JUMPIFNOTEQ: - case LOP_JUMPIFNOTLE: - case LOP_JUMPIFNOTLT: - case LOP_NEWTABLE: - case LOP_SETLIST: - case LOP_FORGLOOP: - case LOP_LOADKX: - case LOP_FASTCALL2: - case LOP_FASTCALL2K: - case LOP_JUMPXEQKNIL: - case LOP_JUMPXEQKB: - case LOP_JUMPXEQKN: - case LOP_JUMPXEQKS: - return 2; - - default: - return 1; - } -} - -} // namespace Luau diff --git a/lib/luau/Common/include/Luau/Common.h b/lib/luau/Common/include/Luau/Common.h deleted file mode 100644 index 31b416f..0000000 --- a/lib/luau/Common/include/Luau/Common.h +++ /dev/null @@ -1,137 +0,0 @@ -// This file is part of the Luau programming language and is licensed under MIT License; see LICENSE.txt for details -#pragma once - -// Compiler codegen control macros -#ifdef _MSC_VER -#define LUAU_NORETURN __declspec(noreturn) -#define LUAU_NOINLINE __declspec(noinline) -#define LUAU_FORCEINLINE __forceinline -#define LUAU_LIKELY(x) x -#define LUAU_UNLIKELY(x) x -#define LUAU_UNREACHABLE() __assume(false) -#define LUAU_DEBUGBREAK() __debugbreak() -#else -#define LUAU_NORETURN __attribute__((__noreturn__)) -#define LUAU_NOINLINE __attribute__((noinline)) -#define LUAU_FORCEINLINE inline __attribute__((always_inline)) -#define LUAU_LIKELY(x) __builtin_expect(x, 1) -#define LUAU_UNLIKELY(x) __builtin_expect(x, 0) -#define LUAU_UNREACHABLE() __builtin_unreachable() -#define LUAU_DEBUGBREAK() __builtin_trap() -#endif - -#if defined(__BYTE_ORDER__) && __BYTE_ORDER__ == __ORDER_BIG_ENDIAN__ -#define LUAU_BIG_ENDIAN -#endif - -namespace Luau -{ - -using AssertHandler = int (*)(const char* expression, const char* file, int line, const char* function); - -inline AssertHandler& assertHandler() -{ - static AssertHandler handler = nullptr; - return handler; -} - -// We want 'inline' to correctly link this function declared in the header -// But we also want to prevent compiler from inlining this function when optimization and assertions are enabled together -// Reason for that is that compilation times can increase significantly in such a configuration -LUAU_NOINLINE inline int assertCallHandler(const char* expression, const char* file, int line, const char* function) -{ - if (AssertHandler handler = assertHandler()) - return handler(expression, file, line, function); - - return 1; -} - -} // namespace Luau - -#if !defined(NDEBUG) || defined(LUAU_ENABLE_ASSERT) -#define LUAU_ASSERT(expr) ((void)(!!(expr) || (Luau::assertCallHandler(#expr, __FILE__, __LINE__, __FUNCTION__) && (LUAU_DEBUGBREAK(), 0)))) -#define LUAU_ASSERTENABLED -#else -#define LUAU_ASSERT(expr) (void)sizeof(!!(expr)) -#endif - -namespace Luau -{ - -template -struct FValue -{ - static FValue* list; - - T value; - bool dynamic; - const char* name; - FValue* next; - - FValue(const char* name, T def, bool dynamic) - : value(def) - , dynamic(dynamic) - , name(name) - , next(list) - { - list = this; - } - - operator T() const - { - return value; - } -}; - -template -FValue* FValue::list = nullptr; - -} // namespace Luau - -#define LUAU_FASTFLAG(flag) \ - namespace FFlag \ - { \ - extern Luau::FValue flag; \ - } -#define LUAU_FASTFLAGVARIABLE(flag, def) \ - namespace FFlag \ - { \ - Luau::FValue flag(#flag, def, false); \ - } -#define LUAU_FASTINT(flag) \ - namespace FInt \ - { \ - extern Luau::FValue flag; \ - } -#define LUAU_FASTINTVARIABLE(flag, def) \ - namespace FInt \ - { \ - Luau::FValue flag(#flag, def, false); \ - } - -#define LUAU_DYNAMIC_FASTFLAG(flag) \ - namespace DFFlag \ - { \ - extern Luau::FValue flag; \ - } -#define LUAU_DYNAMIC_FASTFLAGVARIABLE(flag, def) \ - namespace DFFlag \ - { \ - Luau::FValue flag(#flag, def, true); \ - } -#define LUAU_DYNAMIC_FASTINT(flag) \ - namespace DFInt \ - { \ - extern Luau::FValue flag; \ - } -#define LUAU_DYNAMIC_FASTINTVARIABLE(flag, def) \ - namespace DFInt \ - { \ - Luau::FValue flag(#flag, def, true); \ - } - -#if defined(__GNUC__) -#define LUAU_PRINTF_ATTR(fmt, arg) __attribute__((format(printf, fmt, arg))) -#else -#define LUAU_PRINTF_ATTR(fmt, arg) -#endif diff --git a/lib/luau/Common/include/Luau/DenseHash.h b/lib/luau/Common/include/Luau/DenseHash.h deleted file mode 100644 index 8f1fc8b..0000000 --- a/lib/luau/Common/include/Luau/DenseHash.h +++ /dev/null @@ -1,666 +0,0 @@ -// This file is part of the Luau programming language and is licensed under MIT License; see LICENSE.txt for details -#pragma once - -#include "Luau/Common.h" - -#include -#include -#include -#include -#include - -namespace Luau -{ - -struct DenseHashPointer -{ - size_t operator()(const void* key) const - { - return (uintptr_t(key) >> 4) ^ (uintptr_t(key) >> 9); - } -}; - -// Internal implementation of DenseHashSet and DenseHashMap -namespace detail -{ - -template -using DenseHashDefault = std::conditional_t, DenseHashPointer, std::hash>; - -template -class DenseHashTable -{ -public: - class const_iterator; - class iterator; - - explicit DenseHashTable(const Key& empty_key, size_t buckets = 0) - : data(nullptr) - , capacity(0) - , count(0) - , empty_key(empty_key) - { - // validate that equality operator is at least somewhat functional - LUAU_ASSERT(eq(empty_key, empty_key)); - // buckets has to be power-of-two or zero - LUAU_ASSERT((buckets & (buckets - 1)) == 0); - - if (buckets) - { - data = static_cast(::operator new(sizeof(Item) * buckets)); - capacity = buckets; - - ItemInterface::fill(data, buckets, empty_key); - } - } - - ~DenseHashTable() - { - if (data) - destroy(); - } - - DenseHashTable(const DenseHashTable& other) - : data(nullptr) - , capacity(0) - , count(other.count) - , empty_key(other.empty_key) - { - if (other.capacity) - { - data = static_cast(::operator new(sizeof(Item) * other.capacity)); - - for (size_t i = 0; i < other.capacity; ++i) - { - new (&data[i]) Item(other.data[i]); - capacity = i + 1; // if Item copy throws, capacity will note the number of initialized objects for destroy() to clean up - } - } - } - - DenseHashTable(DenseHashTable&& other) - : data(other.data) - , capacity(other.capacity) - , count(other.count) - , empty_key(other.empty_key) - { - other.data = nullptr; - other.capacity = 0; - other.count = 0; - } - - DenseHashTable& operator=(DenseHashTable&& other) - { - if (this != &other) - { - if (data) - destroy(); - - data = other.data; - capacity = other.capacity; - count = other.count; - empty_key = other.empty_key; - - other.data = nullptr; - other.capacity = 0; - other.count = 0; - } - - return *this; - } - - DenseHashTable& operator=(const DenseHashTable& other) - { - if (this != &other) - { - DenseHashTable copy(other); - *this = std::move(copy); - } - - return *this; - } - - void clear() - { - if (count == 0) - return; - - if (capacity > 32) - { - destroy(); - } - else - { - ItemInterface::destroy(data, capacity); - ItemInterface::fill(data, capacity, empty_key); - } - - count = 0; - } - - void destroy() - { - ItemInterface::destroy(data, capacity); - - ::operator delete(data); - data = nullptr; - - capacity = 0; - } - - Item* insert_unsafe(const Key& key) - { - // It is invalid to insert empty_key into the table since it acts as a "entry does not exist" marker - LUAU_ASSERT(!eq(key, empty_key)); - - size_t hashmod = capacity - 1; - size_t bucket = hasher(key) & hashmod; - - for (size_t probe = 0; probe <= hashmod; ++probe) - { - Item& probe_item = data[bucket]; - - // Element does not exist, insert here - if (eq(ItemInterface::getKey(probe_item), empty_key)) - { - ItemInterface::setKey(probe_item, key); - count++; - return &probe_item; - } - - // Element already exists - if (eq(ItemInterface::getKey(probe_item), key)) - { - return &probe_item; - } - - // Hash collision, quadratic probing - bucket = (bucket + probe + 1) & hashmod; - } - - // Hash table is full - this should not happen - LUAU_ASSERT(false); - return NULL; - } - - const Item* find(const Key& key) const - { - if (count == 0) - return 0; - if (eq(key, empty_key)) - return 0; - - size_t hashmod = capacity - 1; - size_t bucket = hasher(key) & hashmod; - - for (size_t probe = 0; probe <= hashmod; ++probe) - { - const Item& probe_item = data[bucket]; - - // Element exists - if (eq(ItemInterface::getKey(probe_item), key)) - return &probe_item; - - // Element does not exist - if (eq(ItemInterface::getKey(probe_item), empty_key)) - return NULL; - - // Hash collision, quadratic probing - bucket = (bucket + probe + 1) & hashmod; - } - - // Hash table is full - this should not happen - LUAU_ASSERT(false); - return NULL; - } - - void rehash() - { - size_t newsize = capacity == 0 ? 16 : capacity * 2; - - DenseHashTable newtable(empty_key, newsize); - - for (size_t i = 0; i < capacity; ++i) - { - const Key& key = ItemInterface::getKey(data[i]); - - if (!eq(key, empty_key)) - { - Item* item = newtable.insert_unsafe(key); - *item = std::move(data[i]); - } - } - - LUAU_ASSERT(count == newtable.count); - - std::swap(data, newtable.data); - std::swap(capacity, newtable.capacity); - } - - void rehash_if_full(const Key& key) - { - if (count >= capacity * 3 / 4 && !find(key)) - { - rehash(); - } - } - - const_iterator begin() const - { - size_t start = 0; - - while (start < capacity && eq(ItemInterface::getKey(data[start]), empty_key)) - start++; - - return const_iterator(this, start); - } - - const_iterator end() const - { - return const_iterator(this, capacity); - } - - iterator begin() - { - size_t start = 0; - - while (start < capacity && eq(ItemInterface::getKey(data[start]), empty_key)) - start++; - - return iterator(this, start); - } - - iterator end() - { - return iterator(this, capacity); - } - - size_t size() const - { - return count; - } - - class const_iterator - { - public: - using value_type = Item; - using reference = Item&; - using pointer = Item*; - using difference_type = ptrdiff_t; - using iterator_category = std::forward_iterator_tag; - - const_iterator() - : set(0) - , index(0) - { - } - - const_iterator(const DenseHashTable* set, size_t index) - : set(set) - , index(index) - { - } - - const Item& operator*() const - { - return set->data[index]; - } - - const Item* operator->() const - { - return &set->data[index]; - } - - bool operator==(const const_iterator& other) const - { - return set == other.set && index == other.index; - } - - bool operator!=(const const_iterator& other) const - { - return set != other.set || index != other.index; - } - - const_iterator& operator++() - { - size_t size = set->capacity; - - do - { - index++; - } while (index < size && set->eq(ItemInterface::getKey(set->data[index]), set->empty_key)); - - return *this; - } - - const_iterator operator++(int) - { - const_iterator res = *this; - ++*this; - return res; - } - - private: - const DenseHashTable* set; - size_t index; - }; - - class iterator - { - public: - using value_type = MutableItem; - using reference = MutableItem&; - using pointer = MutableItem*; - using difference_type = ptrdiff_t; - using iterator_category = std::forward_iterator_tag; - - iterator() - : set(0) - , index(0) - { - } - - iterator(DenseHashTable* set, size_t index) - : set(set) - , index(index) - { - } - - MutableItem& operator*() const - { - return *reinterpret_cast(&set->data[index]); - } - - MutableItem* operator->() const - { - return reinterpret_cast(&set->data[index]); - } - - bool operator==(const iterator& other) const - { - return set == other.set && index == other.index; - } - - bool operator!=(const iterator& other) const - { - return set != other.set || index != other.index; - } - - iterator& operator++() - { - size_t size = set->capacity; - - do - { - index++; - } while (index < size && set->eq(ItemInterface::getKey(set->data[index]), set->empty_key)); - - return *this; - } - - iterator operator++(int) - { - iterator res = *this; - ++*this; - return res; - } - - private: - DenseHashTable* set; - size_t index; - }; - -private: - Item* data; - size_t capacity; - size_t count; - Key empty_key; - Hash hasher; - Eq eq; -}; - -template -struct ItemInterfaceSet -{ - static const Key& getKey(const Key& item) - { - return item; - } - - static void setKey(Key& item, const Key& key) - { - item = key; - } - - static void fill(Key* data, size_t count, const Key& key) - { - for (size_t i = 0; i < count; ++i) - new (&data[i]) Key(key); - } - - static void destroy(Key* data, size_t count) - { - for (size_t i = 0; i < count; ++i) - data[i].~Key(); - } -}; - -template -struct ItemInterfaceMap -{ - static const Key& getKey(const std::pair& item) - { - return item.first; - } - - static void setKey(std::pair& item, const Key& key) - { - item.first = key; - } - - static void fill(std::pair* data, size_t count, const Key& key) - { - for (size_t i = 0; i < count; ++i) - { - new (&data[i].first) Key(key); - new (&data[i].second) Value(); - } - } - - static void destroy(std::pair* data, size_t count) - { - for (size_t i = 0; i < count; ++i) - { - data[i].first.~Key(); - data[i].second.~Value(); - } - } -}; - -} // namespace detail - -// This is a faster alternative of unordered_set, but it does not implement the same interface (i.e. it does not support erasing) -template, typename Eq = std::equal_to> -class DenseHashSet -{ - typedef detail::DenseHashTable, Hash, Eq> Impl; - Impl impl; - -public: - typedef typename Impl::const_iterator const_iterator; - typedef typename Impl::iterator iterator; - - explicit DenseHashSet(const Key& empty_key, size_t buckets = 0) - : impl(empty_key, buckets) - { - } - - void clear() - { - impl.clear(); - } - - const Key& insert(const Key& key) - { - impl.rehash_if_full(key); - return *impl.insert_unsafe(key); - } - - const Key* find(const Key& key) const - { - return impl.find(key); - } - - bool contains(const Key& key) const - { - return impl.find(key) != 0; - } - - size_t size() const - { - return impl.size(); - } - - bool empty() const - { - return impl.size() == 0; - } - - const_iterator begin() const - { - return impl.begin(); - } - - const_iterator end() const - { - return impl.end(); - } - - iterator begin() - { - return impl.begin(); - } - - iterator end() - { - return impl.end(); - } - - bool operator==(const DenseHashSet& other) const - { - if (size() != other.size()) - return false; - - for (const Key& k : *this) - { - if (!other.contains(k)) - return false; - } - - return true; - } - - bool operator!=(const DenseHashSet& other) const - { - return !(*this == other); - } -}; - -// This is a faster alternative of unordered_map, but it does not implement the same interface (i.e. it does not support erasing and has -// contains() instead of find()) -template, typename Eq = std::equal_to> -class DenseHashMap -{ - typedef detail::DenseHashTable, std::pair, detail::ItemInterfaceMap, Hash, Eq> Impl; - Impl impl; - -public: - typedef typename Impl::const_iterator const_iterator; - typedef typename Impl::iterator iterator; - - explicit DenseHashMap(const Key& empty_key, size_t buckets = 0) - : impl(empty_key, buckets) - { - } - - void clear() - { - impl.clear(); - } - - // Note: this reference is invalidated by any insert operation (i.e. operator[]) - Value& operator[](const Key& key) - { - impl.rehash_if_full(key); - return impl.insert_unsafe(key)->second; - } - - // Note: this pointer is invalidated by any insert operation (i.e. operator[]) - const Value* find(const Key& key) const - { - const std::pair* result = impl.find(key); - - return result ? &result->second : NULL; - } - - // Note: this pointer is invalidated by any insert operation (i.e. operator[]) - Value* find(const Key& key) - { - const std::pair* result = impl.find(key); - - return result ? const_cast(&result->second) : NULL; - } - - bool contains(const Key& key) const - { - return impl.find(key) != 0; - } - - std::pair try_insert(const Key& key, const Value& value) - { - impl.rehash_if_full(key); - - size_t before = impl.size(); - std::pair* slot = impl.insert_unsafe(key); - - // Value is fresh if container count has increased - bool fresh = impl.size() > before; - - if (fresh) - slot->second = value; - - return std::make_pair(std::ref(slot->second), fresh); - } - - size_t size() const - { - return impl.size(); - } - - bool empty() const - { - return impl.size() == 0; - } - - const_iterator begin() const - { - return impl.begin(); - } - - const_iterator end() const - { - return impl.end(); - } - - iterator begin() - { - return impl.begin(); - } - - iterator end() - { - return impl.end(); - } -}; - -} // namespace Luau diff --git a/lib/luau/Common/include/Luau/ExperimentalFlags.h b/lib/luau/Common/include/Luau/ExperimentalFlags.h deleted file mode 100644 index 7372cc0..0000000 --- a/lib/luau/Common/include/Luau/ExperimentalFlags.h +++ /dev/null @@ -1,29 +0,0 @@ -// This file is part of the Luau programming language and is licensed under MIT License; see LICENSE.txt for details -#pragma once - -#include - -namespace Luau -{ - -inline bool isFlagExperimental(const char* flag) -{ - // Flags in this list are disabled by default in various command-line tools. They may have behavior that is not fully final, - // or critical bugs that are found after the code has been submitted. - static const char* const kList[] = { - "LuauInstantiateInSubtyping", // requires some fixes to lua-apps code - "LuauTinyControlFlowAnalysis", // waiting for updates to packages depended by internal builtin plugins - "LuauFixIndexerSubtypingOrdering", // requires some small fixes to lua-apps code since this fixes a false negative - "LuauUpdatedRequireByStringSemantics", // requires some small fixes to fully implement some proposed changes - // makes sure we always have at least one entry - nullptr, - }; - - for (const char* item : kList) - if (item && strcmp(item, flag) == 0) - return true; - - return false; -} - -} // namespace Luau diff --git a/lib/luau/Compiler/include/Luau/BytecodeBuilder.h b/lib/luau/Compiler/include/Luau/BytecodeBuilder.h deleted file mode 100644 index 99bac8a..0000000 --- a/lib/luau/Compiler/include/Luau/BytecodeBuilder.h +++ /dev/null @@ -1,292 +0,0 @@ -// This file is part of the Luau programming language and is licensed under MIT License; see LICENSE.txt for details -#pragma once - -#include "Luau/Bytecode.h" -#include "Luau/DenseHash.h" -#include "Luau/StringUtils.h" - -#include - -namespace Luau -{ - -class BytecodeEncoder -{ -public: - virtual ~BytecodeEncoder() {} - - virtual void encode(uint32_t* data, size_t count) = 0; -}; - -class BytecodeBuilder -{ -public: - // BytecodeBuilder does *not* copy the data passed via StringRef; instead, it keeps the ref around until finalize() - // Please be careful with the lifetime of the data that's being passed because of this. - // The safe and correct pattern is to only build StringRefs out of pieces of AST (AstName or AstArray<>) that are backed by AstAllocator. - // Note that you must finalize() the builder before the Allocator backing the Ast is destroyed. - struct StringRef - { - // To construct a StringRef, use sref() from Compiler.cpp. - const char* data = nullptr; - size_t length = 0; - - bool operator==(const StringRef& other) const; - }; - - struct TableShape - { - static const unsigned int kMaxLength = 32; - - int32_t keys[kMaxLength]; - unsigned int length = 0; - - bool operator==(const TableShape& other) const; - }; - - BytecodeBuilder(BytecodeEncoder* encoder = 0); - - uint32_t beginFunction(uint8_t numparams, bool isvararg = false); - void endFunction(uint8_t maxstacksize, uint8_t numupvalues, uint8_t flags = 0); - - void setMainFunction(uint32_t fid); - - int32_t addConstantNil(); - int32_t addConstantBoolean(bool value); - int32_t addConstantNumber(double value); - int32_t addConstantVector(float x, float y, float z, float w); - int32_t addConstantString(StringRef value); - int32_t addImport(uint32_t iid); - int32_t addConstantTable(const TableShape& shape); - int32_t addConstantClosure(uint32_t fid); - - int16_t addChildFunction(uint32_t fid); - - void emitABC(LuauOpcode op, uint8_t a, uint8_t b, uint8_t c); - void emitAD(LuauOpcode op, uint8_t a, int16_t d); - void emitE(LuauOpcode op, int32_t e); - void emitAux(uint32_t aux); - - size_t emitLabel(); - - [[nodiscard]] bool patchJumpD(size_t jumpLabel, size_t targetLabel); - [[nodiscard]] bool patchSkipC(size_t jumpLabel, size_t targetLabel); - - void foldJumps(); - void expandJumps(); - - void setFunctionTypeInfo(std::string value); - - void setDebugFunctionName(StringRef name); - void setDebugFunctionLineDefined(int line); - void setDebugLine(int line); - void pushDebugLocal(StringRef name, uint8_t reg, uint32_t startpc, uint32_t endpc); - void pushDebugUpval(StringRef name); - - size_t getInstructionCount() const; - size_t getTotalInstructionCount() const; - uint32_t getDebugPC() const; - - void addDebugRemark(const char* format, ...) LUAU_PRINTF_ATTR(2, 3); - - void finalize(); - - enum DumpFlags - { - Dump_Code = 1 << 0, - Dump_Lines = 1 << 1, - Dump_Source = 1 << 2, - Dump_Locals = 1 << 3, - Dump_Remarks = 1 << 4, - }; - - void setDumpFlags(uint32_t flags) - { - dumpFlags = flags; - dumpFunctionPtr = &BytecodeBuilder::dumpCurrentFunction; - } - - void setDumpSource(const std::string& source); - - bool needsDebugRemarks() const - { - return (dumpFlags & Dump_Remarks) != 0; - } - - const std::string& getBytecode() const - { - LUAU_ASSERT(!bytecode.empty()); // did you forget to call finalize? - return bytecode; - } - - std::string dumpFunction(uint32_t id) const; - std::string dumpEverything() const; - std::string dumpSourceRemarks() const; - std::string dumpTypeInfo() const; - - void annotateInstruction(std::string& result, uint32_t fid, uint32_t instpos) const; - - static uint32_t getImportId(int32_t id0); - static uint32_t getImportId(int32_t id0, int32_t id1); - static uint32_t getImportId(int32_t id0, int32_t id1, int32_t id2); - - static int decomposeImportId(uint32_t ids, int32_t& id0, int32_t& id1, int32_t& id2); - - static uint32_t getStringHash(StringRef key); - - static std::string getError(const std::string& message); - - static uint8_t getVersion(); - static uint8_t getTypeEncodingVersion(); - -private: - struct Constant - { - enum Type - { - Type_Nil, - Type_Boolean, - Type_Number, - Type_Vector, - Type_String, - Type_Import, - Type_Table, - Type_Closure, - }; - - Type type; - union - { - bool valueBoolean; - double valueNumber; - float valueVector[4]; - unsigned int valueString; // index into string table - uint32_t valueImport; // 10-10-10-2 encoded import id - uint32_t valueTable; // index into tableShapes[] - uint32_t valueClosure; // index of function in global list - }; - }; - - struct ConstantKey - { - Constant::Type type; - // Note: this stores value* from Constant; when type is Type_Number, this stores the same bits as double does but in uint64_t. - // For Type_Vector, x and y are stored in 'value' and z and w are stored in 'extra'. - uint64_t value; - uint64_t extra = 0; - - bool operator==(const ConstantKey& key) const - { - return type == key.type && value == key.value && extra == key.extra; - } - }; - - struct Function - { - std::string data; - - uint8_t maxstacksize = 0; - uint8_t numparams = 0; - uint8_t numupvalues = 0; - bool isvararg = false; - - unsigned int debugname = 0; - int debuglinedefined = 0; - - std::string dump; - std::string dumpname; - std::vector dumpinstoffs; - std::string typeinfo; - }; - - struct DebugLocal - { - unsigned int name; - - uint8_t reg; - uint32_t startpc; - uint32_t endpc; - }; - - struct DebugUpval - { - unsigned int name; - }; - - struct Jump - { - uint32_t source; - uint32_t target; - }; - - struct StringRefHash - { - size_t operator()(const StringRef& v) const; - }; - - struct ConstantKeyHash - { - size_t operator()(const ConstantKey& key) const; - }; - - struct TableShapeHash - { - size_t operator()(const TableShape& v) const; - }; - - std::vector functions; - uint32_t currentFunction = ~0u; - uint32_t mainFunction = ~0u; - - size_t totalInstructionCount = 0; - std::vector insns; - std::vector lines; - std::vector constants; - std::vector protos; - std::vector jumps; - - std::vector tableShapes; - - bool hasLongJumps = false; - - DenseHashMap constantMap; - DenseHashMap tableShapeMap; - DenseHashMap protoMap; - - int debugLine = 0; - - std::vector debugLocals; - std::vector debugUpvals; - - DenseHashMap stringTable; - std::vector debugStrings; - - std::vector> debugRemarks; - std::string debugRemarkBuffer; - - BytecodeEncoder* encoder = nullptr; - std::string bytecode; - - uint32_t dumpFlags = 0; - std::vector dumpSource; - std::vector> dumpRemarks; - - std::string (BytecodeBuilder::*dumpFunctionPtr)(std::vector&) const = nullptr; - - void validate() const; - void validateInstructions() const; - void validateVariadic() const; - - std::string dumpCurrentFunction(std::vector& dumpinstoffs) const; - void dumpConstant(std::string& result, int k) const; - void dumpInstruction(const uint32_t* opcode, std::string& output, int targetLabel) const; - - void writeFunction(std::string& ss, uint32_t id, uint8_t flags) const; - void writeLineInfo(std::string& ss) const; - void writeStringTable(std::string& ss) const; - - int32_t addConstant(const ConstantKey& key, const Constant& value); - unsigned int addStringTableEntry(StringRef value); -}; - -} // namespace Luau diff --git a/lib/luau/Compiler/include/Luau/Compiler.h b/lib/luau/Compiler/include/Luau/Compiler.h deleted file mode 100644 index 9a661db..0000000 --- a/lib/luau/Compiler/include/Luau/Compiler.h +++ /dev/null @@ -1,71 +0,0 @@ -// This file is part of the Luau programming language and is licensed under MIT License; see LICENSE.txt for details -#pragma once - -#include "Luau/ParseOptions.h" -#include "Luau/Location.h" -#include "Luau/StringUtils.h" -#include "Luau/Common.h" - -namespace Luau -{ -class AstNameTable; -struct ParseResult; -class BytecodeBuilder; -class BytecodeEncoder; - -// Note: this structure is duplicated in luacode.h, don't forget to change these in sync! -struct CompileOptions -{ - // 0 - no optimization - // 1 - baseline optimization level that doesn't prevent debuggability - // 2 - includes optimizations that harm debuggability such as inlining - int optimizationLevel = 1; - - // 0 - no debugging support - // 1 - line info & function names only; sufficient for backtraces - // 2 - full debug info with local & upvalue names; necessary for debugger - int debugLevel = 1; - - // 0 - no code coverage support - // 1 - statement coverage - // 2 - statement and expression coverage (verbose) - int coverageLevel = 0; - - // global builtin to construct vectors; disabled by default - const char* vectorLib = nullptr; - const char* vectorCtor = nullptr; - - // vector type name for type tables; disabled by default - const char* vectorType = nullptr; - - // null-terminated array of globals that are mutable; disables the import optimization for fields accessed through these - const char* const* mutableGlobals = nullptr; -}; - -class CompileError : public std::exception -{ -public: - CompileError(const Location& location, const std::string& message); - - virtual ~CompileError() throw(); - - virtual const char* what() const throw(); - - const Location& getLocation() const; - - static LUAU_NORETURN void raise(const Location& location, const char* format, ...) LUAU_PRINTF_ATTR(2, 3); - -private: - Location location; - std::string message; -}; - -// compiles bytecode into bytecode builder using either a pre-parsed AST or parsing it from source; throws on errors -void compileOrThrow(BytecodeBuilder& bytecode, const ParseResult& parseResult, const AstNameTable& names, const CompileOptions& options = {}); -void compileOrThrow(BytecodeBuilder& bytecode, const std::string& source, const CompileOptions& options = {}, const ParseOptions& parseOptions = {}); - -// compiles bytecode into a bytecode blob, that either contains the valid bytecode or an encoded error that luau_load can decode -std::string compile( - const std::string& source, const CompileOptions& options = {}, const ParseOptions& parseOptions = {}, BytecodeEncoder* encoder = nullptr); - -} // namespace Luau diff --git a/lib/luau/Compiler/include/luacode.h b/lib/luau/Compiler/include/luacode.h deleted file mode 100644 index 60cdeee..0000000 --- a/lib/luau/Compiler/include/luacode.h +++ /dev/null @@ -1,42 +0,0 @@ -// This file is part of the Luau programming language and is licensed under MIT License; see LICENSE.txt for details -#pragma once - -#include - -// Can be used to reconfigure visibility/exports for public APIs -#ifndef LUACODE_API -#define LUACODE_API extern -#endif - -typedef struct lua_CompileOptions lua_CompileOptions; - -struct lua_CompileOptions -{ - // 0 - no optimization - // 1 - baseline optimization level that doesn't prevent debuggability - // 2 - includes optimizations that harm debuggability such as inlining - int optimizationLevel; // default=1 - - // 0 - no debugging support - // 1 - line info & function names only; sufficient for backtraces - // 2 - full debug info with local & upvalue names; necessary for debugger - int debugLevel; // default=1 - - // 0 - no code coverage support - // 1 - statement coverage - // 2 - statement and expression coverage (verbose) - int coverageLevel; // default=0 - - // global builtin to construct vectors; disabled by default - const char* vectorLib; - const char* vectorCtor; - - // vector type name for type tables; disabled by default - const char* vectorType; - - // null-terminated array of globals that are mutable; disables the import optimization for fields accessed through these - const char* const* mutableGlobals; -}; - -// compile source to bytecode; when source compilation fails, the resulting bytecode contains the encoded error. use free() to destroy -LUACODE_API char* luau_compile(const char* source, size_t size, lua_CompileOptions* options, size_t* outsize); diff --git a/lib/luau/Compiler/src/BuiltinFolding.cpp b/lib/luau/Compiler/src/BuiltinFolding.cpp deleted file mode 100644 index 2f372cd..0000000 --- a/lib/luau/Compiler/src/BuiltinFolding.cpp +++ /dev/null @@ -1,502 +0,0 @@ -// This file is part of the Luau programming language and is licensed under MIT License; see LICENSE.txt for details -#include "BuiltinFolding.h" - -#include "Luau/Bytecode.h" - -#include - -LUAU_FASTFLAGVARIABLE(LuauVectorLiterals, false) - -namespace Luau -{ -namespace Compile -{ - -const double kPi = 3.14159265358979323846; -const double kRadDeg = kPi / 180.0; - -static Constant cvar() -{ - return Constant(); -} - -static Constant cbool(bool v) -{ - Constant res = {Constant::Type_Boolean}; - res.valueBoolean = v; - return res; -} - -static Constant cnum(double v) -{ - Constant res = {Constant::Type_Number}; - res.valueNumber = v; - return res; -} - -static Constant cvector(double x, double y, double z, double w) -{ - Constant res = {Constant::Type_Vector}; - res.valueVector[0] = (float)x; - res.valueVector[1] = (float)y; - res.valueVector[2] = (float)z; - res.valueVector[3] = (float)w; - return res; -} - -static Constant cstring(const char* v) -{ - Constant res = {Constant::Type_String}; - res.stringLength = unsigned(strlen(v)); - res.valueString = v; - return res; -} - -static Constant ctype(const Constant& c) -{ - LUAU_ASSERT(c.type != Constant::Type_Unknown); - - switch (c.type) - { - case Constant::Type_Nil: - return cstring("nil"); - - case Constant::Type_Boolean: - return cstring("boolean"); - - case Constant::Type_Number: - return cstring("number"); - - case Constant::Type_Vector: - return cstring("vector"); - - case Constant::Type_String: - return cstring("string"); - - default: - LUAU_ASSERT(!"Unsupported constant type"); - return cvar(); - } -} - -static uint32_t bit32(double v) -{ - // convert through signed 64-bit integer to match runtime behavior and gracefully truncate negative integers - return uint32_t(int64_t(v)); -} - -Constant foldBuiltin(int bfid, const Constant* args, size_t count) -{ - switch (bfid) - { - case LBF_MATH_ABS: - if (count == 1 && args[0].type == Constant::Type_Number) - return cnum(fabs(args[0].valueNumber)); - break; - - case LBF_MATH_ACOS: - if (count == 1 && args[0].type == Constant::Type_Number) - return cnum(acos(args[0].valueNumber)); - break; - - case LBF_MATH_ASIN: - if (count == 1 && args[0].type == Constant::Type_Number) - return cnum(asin(args[0].valueNumber)); - break; - - case LBF_MATH_ATAN2: - if (count == 2 && args[0].type == Constant::Type_Number && args[1].type == Constant::Type_Number) - return cnum(atan2(args[0].valueNumber, args[1].valueNumber)); - break; - - case LBF_MATH_ATAN: - if (count == 1 && args[0].type == Constant::Type_Number) - return cnum(atan(args[0].valueNumber)); - break; - - case LBF_MATH_CEIL: - if (count == 1 && args[0].type == Constant::Type_Number) - return cnum(ceil(args[0].valueNumber)); - break; - - case LBF_MATH_COSH: - if (count == 1 && args[0].type == Constant::Type_Number) - return cnum(cosh(args[0].valueNumber)); - break; - - case LBF_MATH_COS: - if (count == 1 && args[0].type == Constant::Type_Number) - return cnum(cos(args[0].valueNumber)); - break; - - case LBF_MATH_DEG: - if (count == 1 && args[0].type == Constant::Type_Number) - return cnum(args[0].valueNumber / kRadDeg); - break; - - case LBF_MATH_EXP: - if (count == 1 && args[0].type == Constant::Type_Number) - return cnum(exp(args[0].valueNumber)); - break; - - case LBF_MATH_FLOOR: - if (count == 1 && args[0].type == Constant::Type_Number) - return cnum(floor(args[0].valueNumber)); - break; - - case LBF_MATH_FMOD: - if (count == 2 && args[0].type == Constant::Type_Number && args[1].type == Constant::Type_Number) - return cnum(fmod(args[0].valueNumber, args[1].valueNumber)); - break; - - // Note: FREXP isn't folded since it returns multiple values - - case LBF_MATH_LDEXP: - if (count == 2 && args[0].type == Constant::Type_Number && args[1].type == Constant::Type_Number) - return cnum(ldexp(args[0].valueNumber, int(args[1].valueNumber))); - break; - - case LBF_MATH_LOG10: - if (count == 1 && args[0].type == Constant::Type_Number) - return cnum(log10(args[0].valueNumber)); - break; - - case LBF_MATH_LOG: - if (count == 1 && args[0].type == Constant::Type_Number) - return cnum(log(args[0].valueNumber)); - else if (count == 2 && args[0].type == Constant::Type_Number && args[1].type == Constant::Type_Number) - { - if (args[1].valueNumber == 2.0) - return cnum(log2(args[0].valueNumber)); - else if (args[1].valueNumber == 10.0) - return cnum(log10(args[0].valueNumber)); - else - return cnum(log(args[0].valueNumber) / log(args[1].valueNumber)); - } - break; - - case LBF_MATH_MAX: - if (count >= 1 && args[0].type == Constant::Type_Number) - { - double r = args[0].valueNumber; - - for (size_t i = 1; i < count; ++i) - { - if (args[i].type != Constant::Type_Number) - return cvar(); - - double a = args[i].valueNumber; - - r = (a > r) ? a : r; - } - - return cnum(r); - } - break; - - case LBF_MATH_MIN: - if (count >= 1 && args[0].type == Constant::Type_Number) - { - double r = args[0].valueNumber; - - for (size_t i = 1; i < count; ++i) - { - if (args[i].type != Constant::Type_Number) - return cvar(); - - double a = args[i].valueNumber; - - r = (a < r) ? a : r; - } - - return cnum(r); - } - break; - - // Note: MODF isn't folded since it returns multiple values - - case LBF_MATH_POW: - if (count == 2 && args[0].type == Constant::Type_Number && args[1].type == Constant::Type_Number) - return cnum(pow(args[0].valueNumber, args[1].valueNumber)); - break; - - case LBF_MATH_RAD: - if (count == 1 && args[0].type == Constant::Type_Number) - return cnum(args[0].valueNumber * kRadDeg); - break; - - case LBF_MATH_SINH: - if (count == 1 && args[0].type == Constant::Type_Number) - return cnum(sinh(args[0].valueNumber)); - break; - - case LBF_MATH_SIN: - if (count == 1 && args[0].type == Constant::Type_Number) - return cnum(sin(args[0].valueNumber)); - break; - - case LBF_MATH_SQRT: - if (count == 1 && args[0].type == Constant::Type_Number) - return cnum(sqrt(args[0].valueNumber)); - break; - - case LBF_MATH_TANH: - if (count == 1 && args[0].type == Constant::Type_Number) - return cnum(tanh(args[0].valueNumber)); - break; - - case LBF_MATH_TAN: - if (count == 1 && args[0].type == Constant::Type_Number) - return cnum(tan(args[0].valueNumber)); - break; - - case LBF_BIT32_ARSHIFT: - if (count == 2 && args[0].type == Constant::Type_Number && args[1].type == Constant::Type_Number) - { - uint32_t u = bit32(args[0].valueNumber); - int s = int(args[1].valueNumber); - - if (unsigned(s) < 32) - return cnum(double(uint32_t(int32_t(u) >> s))); - } - break; - - case LBF_BIT32_BAND: - if (count >= 1 && args[0].type == Constant::Type_Number) - { - uint32_t r = bit32(args[0].valueNumber); - - for (size_t i = 1; i < count; ++i) - { - if (args[i].type != Constant::Type_Number) - return cvar(); - - r &= bit32(args[i].valueNumber); - } - - return cnum(double(r)); - } - break; - - case LBF_BIT32_BNOT: - if (count == 1 && args[0].type == Constant::Type_Number) - return cnum(double(uint32_t(~bit32(args[0].valueNumber)))); - break; - - case LBF_BIT32_BOR: - if (count >= 1 && args[0].type == Constant::Type_Number) - { - uint32_t r = bit32(args[0].valueNumber); - - for (size_t i = 1; i < count; ++i) - { - if (args[i].type != Constant::Type_Number) - return cvar(); - - r |= bit32(args[i].valueNumber); - } - - return cnum(double(r)); - } - break; - - case LBF_BIT32_BXOR: - if (count >= 1 && args[0].type == Constant::Type_Number) - { - uint32_t r = bit32(args[0].valueNumber); - - for (size_t i = 1; i < count; ++i) - { - if (args[i].type != Constant::Type_Number) - return cvar(); - - r ^= bit32(args[i].valueNumber); - } - - return cnum(double(r)); - } - break; - - case LBF_BIT32_BTEST: - if (count >= 1 && args[0].type == Constant::Type_Number) - { - uint32_t r = bit32(args[0].valueNumber); - - for (size_t i = 1; i < count; ++i) - { - if (args[i].type != Constant::Type_Number) - return cvar(); - - r &= bit32(args[i].valueNumber); - } - - return cbool(r != 0); - } - break; - - case LBF_BIT32_EXTRACT: - if (count >= 2 && args[0].type == Constant::Type_Number && args[1].type == Constant::Type_Number && - (count == 2 || args[2].type == Constant::Type_Number)) - { - uint32_t u = bit32(args[0].valueNumber); - int f = int(args[1].valueNumber); - int w = count == 2 ? 1 : int(args[2].valueNumber); - - if (f >= 0 && w > 0 && f + w <= 32) - { - uint32_t m = ~(0xfffffffeu << (w - 1)); - - return cnum(double((u >> f) & m)); - } - } - break; - - case LBF_BIT32_LROTATE: - if (count == 2 && args[0].type == Constant::Type_Number && args[1].type == Constant::Type_Number) - { - uint32_t u = bit32(args[0].valueNumber); - int s = int(args[1].valueNumber); - - return cnum(double((u << (s & 31)) | (u >> ((32 - s) & 31)))); - } - break; - - case LBF_BIT32_LSHIFT: - if (count == 2 && args[0].type == Constant::Type_Number && args[1].type == Constant::Type_Number) - { - uint32_t u = bit32(args[0].valueNumber); - int s = int(args[1].valueNumber); - - if (unsigned(s) < 32) - return cnum(double(u << s)); - } - break; - - case LBF_BIT32_REPLACE: - if (count >= 3 && args[0].type == Constant::Type_Number && args[1].type == Constant::Type_Number && args[2].type == Constant::Type_Number && - (count == 3 || args[3].type == Constant::Type_Number)) - { - uint32_t n = bit32(args[0].valueNumber); - uint32_t v = bit32(args[1].valueNumber); - int f = int(args[2].valueNumber); - int w = count == 3 ? 1 : int(args[3].valueNumber); - - if (f >= 0 && w > 0 && f + w <= 32) - { - uint32_t m = ~(0xfffffffeu << (w - 1)); - - return cnum(double((n & ~(m << f)) | ((v & m) << f))); - } - } - break; - - case LBF_BIT32_RROTATE: - if (count == 2 && args[0].type == Constant::Type_Number && args[1].type == Constant::Type_Number) - { - uint32_t u = bit32(args[0].valueNumber); - int s = int(args[1].valueNumber); - - return cnum(double((u >> (s & 31)) | (u << ((32 - s) & 31)))); - } - break; - - case LBF_BIT32_RSHIFT: - if (count == 2 && args[0].type == Constant::Type_Number && args[1].type == Constant::Type_Number) - { - uint32_t u = bit32(args[0].valueNumber); - int s = int(args[1].valueNumber); - - if (unsigned(s) < 32) - return cnum(double(u >> s)); - } - break; - - case LBF_TYPE: - if (count == 1 && args[0].type != Constant::Type_Unknown) - return ctype(args[0]); - break; - - case LBF_STRING_BYTE: - if (count == 1 && args[0].type == Constant::Type_String) - { - if (args[0].stringLength > 0) - return cnum(double(uint8_t(args[0].valueString[0]))); - } - else if (count == 2 && args[0].type == Constant::Type_String && args[1].type == Constant::Type_Number) - { - int i = int(args[1].valueNumber); - - if (i > 0 && unsigned(i) <= args[0].stringLength) - return cnum(double(uint8_t(args[0].valueString[i - 1]))); - } - break; - - case LBF_STRING_LEN: - if (count == 1 && args[0].type == Constant::Type_String) - return cnum(double(args[0].stringLength)); - break; - - case LBF_TYPEOF: - if (count == 1 && args[0].type != Constant::Type_Unknown) - return ctype(args[0]); - break; - - case LBF_MATH_CLAMP: - if (count == 3 && args[0].type == Constant::Type_Number && args[1].type == Constant::Type_Number && args[2].type == Constant::Type_Number) - { - double min = args[1].valueNumber; - double max = args[2].valueNumber; - - if (min <= max) - { - double v = args[0].valueNumber; - v = v < min ? min : v; - v = v > max ? max : v; - - return cnum(v); - } - } - break; - - case LBF_MATH_SIGN: - if (count == 1 && args[0].type == Constant::Type_Number) - { - double v = args[0].valueNumber; - - return cnum(v > 0.0 ? 1.0 : v < 0.0 ? -1.0 : 0.0); - } - break; - - case LBF_MATH_ROUND: - if (count == 1 && args[0].type == Constant::Type_Number) - return cnum(round(args[0].valueNumber)); - break; - - case LBF_VECTOR: - if (FFlag::LuauVectorLiterals && count >= 3 && args[0].type == Constant::Type_Number && args[1].type == Constant::Type_Number && - args[2].type == Constant::Type_Number) - { - if (count == 3) - return cvector(args[0].valueNumber, args[1].valueNumber, args[2].valueNumber, 0.0); - else if (count == 4 && args[3].type == Constant::Type_Number) - return cvector(args[0].valueNumber, args[1].valueNumber, args[2].valueNumber, args[3].valueNumber); - } - break; - } - - return cvar(); -} - -Constant foldBuiltinMath(AstName index) -{ - if (index == "pi") - return cnum(kPi); - - if (index == "huge") - return cnum(HUGE_VAL); - - return cvar(); -} - -} // namespace Compile -} // namespace Luau diff --git a/lib/luau/Compiler/src/BuiltinFolding.h b/lib/luau/Compiler/src/BuiltinFolding.h deleted file mode 100644 index dd1ca8c..0000000 --- a/lib/luau/Compiler/src/BuiltinFolding.h +++ /dev/null @@ -1,15 +0,0 @@ -// This file is part of the Luau programming language and is licensed under MIT License; see LICENSE.txt for details -#pragma once - -#include "ConstantFolding.h" - -namespace Luau -{ -namespace Compile -{ - -Constant foldBuiltin(int bfid, const Constant* args, size_t count); -Constant foldBuiltinMath(AstName index); - -} // namespace Compile -} // namespace Luau diff --git a/lib/luau/Compiler/src/Builtins.cpp b/lib/luau/Compiler/src/Builtins.cpp deleted file mode 100644 index 407b76a..0000000 --- a/lib/luau/Compiler/src/Builtins.cpp +++ /dev/null @@ -1,467 +0,0 @@ -// This file is part of the Luau programming language and is licensed under MIT License; see LICENSE.txt for details -#include "Builtins.h" - -#include "Luau/Bytecode.h" -#include "Luau/Compiler.h" - -LUAU_FASTFLAGVARIABLE(LuauBit32ByteswapBuiltin, false) - -LUAU_FASTFLAGVARIABLE(LuauBufferBuiltins, false) - -namespace Luau -{ -namespace Compile -{ - -Builtin getBuiltin(AstExpr* node, const DenseHashMap& globals, const DenseHashMap& variables) -{ - if (AstExprLocal* expr = node->as()) - { - const Variable* v = variables.find(expr->local); - - return v && !v->written && v->init ? getBuiltin(v->init, globals, variables) : Builtin(); - } - else if (AstExprIndexName* expr = node->as()) - { - if (AstExprGlobal* object = expr->expr->as()) - { - return getGlobalState(globals, object->name) == Global::Default ? Builtin{object->name, expr->index} : Builtin(); - } - else - { - return Builtin(); - } - } - else if (AstExprGlobal* expr = node->as()) - { - return getGlobalState(globals, expr->name) == Global::Default ? Builtin{AstName(), expr->name} : Builtin(); - } - else - { - return Builtin(); - } -} - -static int getBuiltinFunctionId(const Builtin& builtin, const CompileOptions& options) -{ - if (builtin.isGlobal("assert")) - return LBF_ASSERT; - - if (builtin.isGlobal("type")) - return LBF_TYPE; - - if (builtin.isGlobal("typeof")) - return LBF_TYPEOF; - - if (builtin.isGlobal("rawset")) - return LBF_RAWSET; - if (builtin.isGlobal("rawget")) - return LBF_RAWGET; - if (builtin.isGlobal("rawequal")) - return LBF_RAWEQUAL; - if (builtin.isGlobal("rawlen")) - return LBF_RAWLEN; - - if (builtin.isGlobal("unpack")) - return LBF_TABLE_UNPACK; - - if (builtin.isGlobal("select")) - return LBF_SELECT_VARARG; - - if (builtin.isGlobal("getmetatable")) - return LBF_GETMETATABLE; - if (builtin.isGlobal("setmetatable")) - return LBF_SETMETATABLE; - - if (builtin.isGlobal("tonumber")) - return LBF_TONUMBER; - if (builtin.isGlobal("tostring")) - return LBF_TOSTRING; - - if (builtin.object == "math") - { - if (builtin.method == "abs") - return LBF_MATH_ABS; - if (builtin.method == "acos") - return LBF_MATH_ACOS; - if (builtin.method == "asin") - return LBF_MATH_ASIN; - if (builtin.method == "atan2") - return LBF_MATH_ATAN2; - if (builtin.method == "atan") - return LBF_MATH_ATAN; - if (builtin.method == "ceil") - return LBF_MATH_CEIL; - if (builtin.method == "cosh") - return LBF_MATH_COSH; - if (builtin.method == "cos") - return LBF_MATH_COS; - if (builtin.method == "deg") - return LBF_MATH_DEG; - if (builtin.method == "exp") - return LBF_MATH_EXP; - if (builtin.method == "floor") - return LBF_MATH_FLOOR; - if (builtin.method == "fmod") - return LBF_MATH_FMOD; - if (builtin.method == "frexp") - return LBF_MATH_FREXP; - if (builtin.method == "ldexp") - return LBF_MATH_LDEXP; - if (builtin.method == "log10") - return LBF_MATH_LOG10; - if (builtin.method == "log") - return LBF_MATH_LOG; - if (builtin.method == "max") - return LBF_MATH_MAX; - if (builtin.method == "min") - return LBF_MATH_MIN; - if (builtin.method == "modf") - return LBF_MATH_MODF; - if (builtin.method == "pow") - return LBF_MATH_POW; - if (builtin.method == "rad") - return LBF_MATH_RAD; - if (builtin.method == "sinh") - return LBF_MATH_SINH; - if (builtin.method == "sin") - return LBF_MATH_SIN; - if (builtin.method == "sqrt") - return LBF_MATH_SQRT; - if (builtin.method == "tanh") - return LBF_MATH_TANH; - if (builtin.method == "tan") - return LBF_MATH_TAN; - if (builtin.method == "clamp") - return LBF_MATH_CLAMP; - if (builtin.method == "sign") - return LBF_MATH_SIGN; - if (builtin.method == "round") - return LBF_MATH_ROUND; - } - - if (builtin.object == "bit32") - { - if (builtin.method == "arshift") - return LBF_BIT32_ARSHIFT; - if (builtin.method == "band") - return LBF_BIT32_BAND; - if (builtin.method == "bnot") - return LBF_BIT32_BNOT; - if (builtin.method == "bor") - return LBF_BIT32_BOR; - if (builtin.method == "bxor") - return LBF_BIT32_BXOR; - if (builtin.method == "btest") - return LBF_BIT32_BTEST; - if (builtin.method == "extract") - return LBF_BIT32_EXTRACT; - if (builtin.method == "lrotate") - return LBF_BIT32_LROTATE; - if (builtin.method == "lshift") - return LBF_BIT32_LSHIFT; - if (builtin.method == "replace") - return LBF_BIT32_REPLACE; - if (builtin.method == "rrotate") - return LBF_BIT32_RROTATE; - if (builtin.method == "rshift") - return LBF_BIT32_RSHIFT; - if (builtin.method == "countlz") - return LBF_BIT32_COUNTLZ; - if (builtin.method == "countrz") - return LBF_BIT32_COUNTRZ; - if (FFlag::LuauBit32ByteswapBuiltin && builtin.method == "byteswap") - return LBF_BIT32_BYTESWAP; - } - - if (builtin.object == "string") - { - if (builtin.method == "byte") - return LBF_STRING_BYTE; - if (builtin.method == "char") - return LBF_STRING_CHAR; - if (builtin.method == "len") - return LBF_STRING_LEN; - if (builtin.method == "sub") - return LBF_STRING_SUB; - } - - if (builtin.object == "table") - { - if (builtin.method == "insert") - return LBF_TABLE_INSERT; - if (builtin.method == "unpack") - return LBF_TABLE_UNPACK; - } - - if (FFlag::LuauBufferBuiltins && builtin.object == "buffer") - { - if (builtin.method == "readi8") - return LBF_BUFFER_READI8; - if (builtin.method == "readu8") - return LBF_BUFFER_READU8; - if (builtin.method == "writei8" || builtin.method == "writeu8") - return LBF_BUFFER_WRITEU8; - if (builtin.method == "readi16") - return LBF_BUFFER_READI16; - if (builtin.method == "readu16") - return LBF_BUFFER_READU16; - if (builtin.method == "writei16" || builtin.method == "writeu16") - return LBF_BUFFER_WRITEU16; - if (builtin.method == "readi32") - return LBF_BUFFER_READI32; - if (builtin.method == "readu32") - return LBF_BUFFER_READU32; - if (builtin.method == "writei32" || builtin.method == "writeu32") - return LBF_BUFFER_WRITEU32; - if (builtin.method == "readf32") - return LBF_BUFFER_READF32; - if (builtin.method == "writef32") - return LBF_BUFFER_WRITEF32; - if (builtin.method == "readf64") - return LBF_BUFFER_READF64; - if (builtin.method == "writef64") - return LBF_BUFFER_WRITEF64; - } - - if (options.vectorCtor) - { - if (options.vectorLib) - { - if (builtin.isMethod(options.vectorLib, options.vectorCtor)) - return LBF_VECTOR; - } - else - { - if (builtin.isGlobal(options.vectorCtor)) - return LBF_VECTOR; - } - } - - return -1; -} - -struct BuiltinVisitor : AstVisitor -{ - DenseHashMap& result; - - const DenseHashMap& globals; - const DenseHashMap& variables; - - const CompileOptions& options; - - BuiltinVisitor(DenseHashMap& result, const DenseHashMap& globals, - const DenseHashMap& variables, const CompileOptions& options) - : result(result) - , globals(globals) - , variables(variables) - , options(options) - { - } - - bool visit(AstExprCall* node) override - { - Builtin builtin = node->self ? Builtin() : getBuiltin(node->func, globals, variables); - if (builtin.empty()) - return true; - - int bfid = getBuiltinFunctionId(builtin, options); - - // getBuiltinFunctionId optimistically assumes all select() calls are builtin but actually the second argument must be a vararg - if (bfid == LBF_SELECT_VARARG && !(node->args.size == 2 && node->args.data[1]->is())) - bfid = -1; - - if (bfid >= 0) - result[node] = bfid; - - return true; // propagate to nested calls - } -}; - -void analyzeBuiltins(DenseHashMap& result, const DenseHashMap& globals, - const DenseHashMap& variables, const CompileOptions& options, AstNode* root) -{ - BuiltinVisitor visitor{result, globals, variables, options}; - root->visit(&visitor); -} - -BuiltinInfo getBuiltinInfo(int bfid) -{ - switch (LuauBuiltinFunction(bfid)) - { - case LBF_NONE: - return {-1, -1}; - - case LBF_ASSERT: - return {-1, -1}; // assert() returns all values when first value is truthy - - case LBF_MATH_ABS: - case LBF_MATH_ACOS: - case LBF_MATH_ASIN: - return {1, 1, BuiltinInfo::Flag_NoneSafe}; - - case LBF_MATH_ATAN2: - return {2, 1, BuiltinInfo::Flag_NoneSafe}; - - case LBF_MATH_ATAN: - case LBF_MATH_CEIL: - case LBF_MATH_COSH: - case LBF_MATH_COS: - case LBF_MATH_DEG: - case LBF_MATH_EXP: - case LBF_MATH_FLOOR: - return {1, 1, BuiltinInfo::Flag_NoneSafe}; - - case LBF_MATH_FMOD: - return {2, 1, BuiltinInfo::Flag_NoneSafe}; - - case LBF_MATH_FREXP: - return {1, 2, BuiltinInfo::Flag_NoneSafe}; - - case LBF_MATH_LDEXP: - return {2, 1, BuiltinInfo::Flag_NoneSafe}; - - case LBF_MATH_LOG10: - return {1, 1, BuiltinInfo::Flag_NoneSafe}; - - case LBF_MATH_LOG: - return {-1, 1}; // 1 or 2 parameters - - case LBF_MATH_MAX: - case LBF_MATH_MIN: - return {-1, 1}; // variadic - - case LBF_MATH_MODF: - return {1, 2, BuiltinInfo::Flag_NoneSafe}; - - case LBF_MATH_POW: - return {2, 1, BuiltinInfo::Flag_NoneSafe}; - - case LBF_MATH_RAD: - case LBF_MATH_SINH: - case LBF_MATH_SIN: - case LBF_MATH_SQRT: - case LBF_MATH_TANH: - case LBF_MATH_TAN: - return {1, 1, BuiltinInfo::Flag_NoneSafe}; - - case LBF_BIT32_ARSHIFT: - return {2, 1, BuiltinInfo::Flag_NoneSafe}; - - case LBF_BIT32_BAND: - return {-1, 1}; // variadic - - case LBF_BIT32_BNOT: - return {1, 1, BuiltinInfo::Flag_NoneSafe}; - - case LBF_BIT32_BOR: - case LBF_BIT32_BXOR: - case LBF_BIT32_BTEST: - return {-1, 1}; // variadic - - case LBF_BIT32_EXTRACT: - return {-1, 1}; // 2 or 3 parameters - - case LBF_BIT32_LROTATE: - case LBF_BIT32_LSHIFT: - return {2, 1, BuiltinInfo::Flag_NoneSafe}; - - case LBF_BIT32_REPLACE: - return {-1, 1}; // 3 or 4 parameters - - case LBF_BIT32_RROTATE: - case LBF_BIT32_RSHIFT: - return {2, 1, BuiltinInfo::Flag_NoneSafe}; - - case LBF_TYPE: - return {1, 1}; - - case LBF_STRING_BYTE: - return {-1, -1}; // 1, 2 or 3 parameters - - case LBF_STRING_CHAR: - return {-1, 1}; // variadic - - case LBF_STRING_LEN: - return {1, 1, BuiltinInfo::Flag_NoneSafe}; - - case LBF_TYPEOF: - return {1, 1}; - - case LBF_STRING_SUB: - return {-1, 1}; // 2 or 3 parameters - - case LBF_MATH_CLAMP: - return {3, 1, BuiltinInfo::Flag_NoneSafe}; - - case LBF_MATH_SIGN: - case LBF_MATH_ROUND: - return {1, 1, BuiltinInfo::Flag_NoneSafe}; - - case LBF_RAWSET: - return {3, 1}; - - case LBF_RAWGET: - case LBF_RAWEQUAL: - return {2, 1}; - - case LBF_TABLE_INSERT: - return {-1, 0}; // 2 or 3 parameters - - case LBF_TABLE_UNPACK: - return {-1, -1}; // 1, 2 or 3 parameters - - case LBF_VECTOR: - return {-1, 1}; // 3 or 4 parameters in some configurations - - case LBF_BIT32_COUNTLZ: - case LBF_BIT32_COUNTRZ: - return {1, 1, BuiltinInfo::Flag_NoneSafe}; - - case LBF_SELECT_VARARG: - return {-1, -1}; // variadic - - case LBF_RAWLEN: - return {1, 1, BuiltinInfo::Flag_NoneSafe}; - - case LBF_BIT32_EXTRACTK: - return {3, 1, BuiltinInfo::Flag_NoneSafe}; - - case LBF_GETMETATABLE: - return {1, 1}; - - case LBF_SETMETATABLE: - return {2, 1}; - - case LBF_TONUMBER: - return {-1, 1}; // 1 or 2 parameters - - case LBF_TOSTRING: - return {1, 1}; - - case LBF_BIT32_BYTESWAP: - return {1, 1, BuiltinInfo::Flag_NoneSafe}; - - case LBF_BUFFER_READI8: - case LBF_BUFFER_READU8: - case LBF_BUFFER_READI16: - case LBF_BUFFER_READU16: - case LBF_BUFFER_READI32: - case LBF_BUFFER_READU32: - case LBF_BUFFER_READF32: - case LBF_BUFFER_READF64: - return {2, 1, BuiltinInfo::Flag_NoneSafe}; - - case LBF_BUFFER_WRITEU8: - case LBF_BUFFER_WRITEU16: - case LBF_BUFFER_WRITEU32: - case LBF_BUFFER_WRITEF32: - case LBF_BUFFER_WRITEF64: - return {3, 0, BuiltinInfo::Flag_NoneSafe}; - }; - - LUAU_UNREACHABLE(); -} - -} // namespace Compile -} // namespace Luau diff --git a/lib/luau/Compiler/src/Builtins.h b/lib/luau/Compiler/src/Builtins.h deleted file mode 100644 index 2d78324..0000000 --- a/lib/luau/Compiler/src/Builtins.h +++ /dev/null @@ -1,60 +0,0 @@ -// This file is part of the Luau programming language and is licensed under MIT License; see LICENSE.txt for details -#pragma once - -#include "ValueTracking.h" - -namespace Luau -{ -struct CompileOptions; -} - -namespace Luau -{ -namespace Compile -{ - -struct Builtin -{ - AstName object; - AstName method; - - bool empty() const - { - return object == AstName() && method == AstName(); - } - - bool isGlobal(const char* name) const - { - return object == AstName() && method == name; - } - - bool isMethod(const char* table, const char* name) const - { - return object == table && method == name; - } -}; - -Builtin getBuiltin(AstExpr* node, const DenseHashMap& globals, const DenseHashMap& variables); - -void analyzeBuiltins(DenseHashMap& result, const DenseHashMap& globals, - const DenseHashMap& variables, const CompileOptions& options, AstNode* root); - -struct BuiltinInfo -{ - enum Flags - { - // none-safe builtins are builtins that have the same behavior for arguments that are nil or none - // this allows the compiler to compile calls to builtins more efficiently in certain cases - // for example, math.abs(x()) may compile x() as if it returns one value; if it returns no values, abs() will get nil instead of none - Flag_NoneSafe = 1 << 0, - }; - - int params; - int results; - unsigned int flags; -}; - -BuiltinInfo getBuiltinInfo(int bfid); - -} // namespace Compile -} // namespace Luau diff --git a/lib/luau/Compiler/src/BytecodeBuilder.cpp b/lib/luau/Compiler/src/BytecodeBuilder.cpp deleted file mode 100644 index 703ccee..0000000 --- a/lib/luau/Compiler/src/BytecodeBuilder.cpp +++ /dev/null @@ -1,2446 +0,0 @@ -// This file is part of the Luau programming language and is licensed under MIT License; see LICENSE.txt for details -#include "Luau/BytecodeBuilder.h" - -#include "Luau/BytecodeUtils.h" -#include "Luau/StringUtils.h" - -#include -#include - -LUAU_FASTFLAG(LuauVectorLiterals) -LUAU_FASTFLAG(LuauCompileRevK) - -namespace Luau -{ - -static_assert(LBC_VERSION_TARGET >= LBC_VERSION_MIN && LBC_VERSION_TARGET <= LBC_VERSION_MAX, "Invalid bytecode version setup"); -static_assert(LBC_VERSION_MAX <= 127, "Bytecode version should be 7-bit so that we can extend the serialization to use varint transparently"); - -static const uint32_t kMaxConstantCount = 1 << 23; -static const uint32_t kMaxClosureCount = 1 << 15; - -static const int kMaxJumpDistance = 1 << 23; - -static int log2(int v) -{ - LUAU_ASSERT(v); - - int r = 0; - - while (v >= (2 << r)) - r++; - - return r; -} - -static void writeByte(std::string& ss, unsigned char value) -{ - ss.append(reinterpret_cast(&value), sizeof(value)); -} - -static void writeInt(std::string& ss, int value) -{ - ss.append(reinterpret_cast(&value), sizeof(value)); -} - -static void writeFloat(std::string& ss, float value) -{ - ss.append(reinterpret_cast(&value), sizeof(value)); -} - -static void writeDouble(std::string& ss, double value) -{ - ss.append(reinterpret_cast(&value), sizeof(value)); -} - -static void writeVarInt(std::string& ss, unsigned int value) -{ - do - { - writeByte(ss, (value & 127) | ((value > 127) << 7)); - value >>= 7; - } while (value); -} - -inline bool isJumpD(LuauOpcode op) -{ - switch (op) - { - case LOP_JUMP: - case LOP_JUMPIF: - case LOP_JUMPIFNOT: - case LOP_JUMPIFEQ: - case LOP_JUMPIFLE: - case LOP_JUMPIFLT: - case LOP_JUMPIFNOTEQ: - case LOP_JUMPIFNOTLE: - case LOP_JUMPIFNOTLT: - case LOP_FORNPREP: - case LOP_FORNLOOP: - case LOP_FORGPREP: - case LOP_FORGLOOP: - case LOP_FORGPREP_INEXT: - case LOP_FORGPREP_NEXT: - case LOP_JUMPBACK: - case LOP_JUMPXEQKNIL: - case LOP_JUMPXEQKB: - case LOP_JUMPXEQKN: - case LOP_JUMPXEQKS: - return true; - - default: - return false; - } -} - -inline bool isSkipC(LuauOpcode op) -{ - switch (op) - { - case LOP_LOADB: - return true; - - default: - return false; - } -} - -inline bool isFastCall(LuauOpcode op) -{ - switch (op) - { - case LOP_FASTCALL: - case LOP_FASTCALL1: - case LOP_FASTCALL2: - case LOP_FASTCALL2K: - return true; - - default: - return false; - } -} - -static int getJumpTarget(uint32_t insn, uint32_t pc) -{ - LuauOpcode op = LuauOpcode(LUAU_INSN_OP(insn)); - - if (isJumpD(op)) - return int(pc + LUAU_INSN_D(insn) + 1); - else if (isFastCall(op)) - return int(pc + LUAU_INSN_C(insn) + 2); - else if (isSkipC(op) && LUAU_INSN_C(insn)) - return int(pc + LUAU_INSN_C(insn) + 1); - else if (op == LOP_JUMPX) - return int(pc + LUAU_INSN_E(insn) + 1); - else - return -1; -} - -bool BytecodeBuilder::StringRef::operator==(const StringRef& other) const -{ - return (data && other.data) ? (length == other.length && memcmp(data, other.data, length) == 0) : (data == other.data); -} - -bool BytecodeBuilder::TableShape::operator==(const TableShape& other) const -{ - return length == other.length && memcmp(keys, other.keys, length * sizeof(keys[0])) == 0; -} - -size_t BytecodeBuilder::StringRefHash::operator()(const StringRef& v) const -{ - return hashRange(v.data, v.length); -} - -size_t BytecodeBuilder::ConstantKeyHash::operator()(const ConstantKey& key) const -{ - if (key.type == Constant::Type_Vector) - { - uint32_t i[4]; - static_assert(sizeof(key.value) + sizeof(key.extra) == sizeof(i), "Expecting vector to have four 32-bit components"); - memcpy(i, &key.value, sizeof(i)); - - // scramble bits to make sure that integer coordinates have entropy in lower bits - i[0] ^= i[0] >> 17; - i[1] ^= i[1] >> 17; - i[2] ^= i[2] >> 17; - i[3] ^= i[3] >> 17; - - // Optimized Spatial Hashing for Collision Detection of Deformable Objects - uint32_t h = (i[0] * 73856093) ^ (i[1] * 19349663) ^ (i[2] * 83492791) ^ (i[3] * 39916801); - - return size_t(h); - } - else - { - // finalizer from MurmurHash64B - const uint32_t m = 0x5bd1e995; - - uint32_t h1 = uint32_t(key.value); - uint32_t h2 = uint32_t(key.value >> 32) ^ (key.type * m); - - h1 ^= h2 >> 18; - h1 *= m; - h2 ^= h1 >> 22; - h2 *= m; - h1 ^= h2 >> 17; - h1 *= m; - h2 ^= h1 >> 19; - h2 *= m; - - // ... truncated to 32-bit output (normally hash is equal to (uint64_t(h1) << 32) | h2, but we only really need the lower 32-bit half) - return size_t(h2); - } -} - -size_t BytecodeBuilder::TableShapeHash::operator()(const TableShape& v) const -{ - // FNV-1a inspired hash (note that we feed integers instead of bytes) - uint32_t hash = 2166136261; - - for (size_t i = 0; i < v.length; ++i) - { - hash ^= v.keys[i]; - hash *= 16777619; - } - - return hash; -} - -BytecodeBuilder::BytecodeBuilder(BytecodeEncoder* encoder) - : constantMap({Constant::Type_Nil, ~0ull}) - , tableShapeMap(TableShape()) - , protoMap(~0u) - , stringTable({nullptr, 0}) - , encoder(encoder) -{ - LUAU_ASSERT(stringTable.find(StringRef{"", 0}) == nullptr); - - // preallocate some buffers that are very likely to grow anyway; this works around std::vector's inefficient growth policy for small arrays - insns.reserve(32); - lines.reserve(32); - constants.reserve(16); - protos.reserve(16); - functions.reserve(8); -} - -uint32_t BytecodeBuilder::beginFunction(uint8_t numparams, bool isvararg) -{ - LUAU_ASSERT(currentFunction == ~0u); - - uint32_t id = uint32_t(functions.size()); - - Function func; - func.numparams = numparams; - func.isvararg = isvararg; - - functions.push_back(func); - - currentFunction = id; - - hasLongJumps = false; - debugLine = 0; - - return id; -} - -void BytecodeBuilder::endFunction(uint8_t maxstacksize, uint8_t numupvalues, uint8_t flags) -{ - LUAU_ASSERT(currentFunction != ~0u); - - Function& func = functions[currentFunction]; - - func.maxstacksize = maxstacksize; - func.numupvalues = numupvalues; - -#ifdef LUAU_ASSERTENABLED - validate(); -#endif - - // this call is indirect to make sure we only gain link time dependency on dumpCurrentFunction when needed - if (dumpFunctionPtr) - func.dump = (this->*dumpFunctionPtr)(func.dumpinstoffs); - - // very approximate: 4 bytes per instruction for code, 1 byte for debug line, and 1-2 bytes for aux data like constants plus overhead - func.data.reserve(32 + insns.size() * 7); - - if (encoder) - encoder->encode(insns.data(), insns.size()); - - writeFunction(func.data, currentFunction, flags); - - currentFunction = ~0u; - - totalInstructionCount += insns.size(); - insns.clear(); - lines.clear(); - constants.clear(); - protos.clear(); - jumps.clear(); - tableShapes.clear(); - - debugLocals.clear(); - debugUpvals.clear(); - - constantMap.clear(); - tableShapeMap.clear(); - protoMap.clear(); - - debugRemarks.clear(); - debugRemarkBuffer.clear(); -} - -void BytecodeBuilder::setMainFunction(uint32_t fid) -{ - LUAU_ASSERT(fid < functions.size()); - - mainFunction = fid; -} - -int32_t BytecodeBuilder::addConstant(const ConstantKey& key, const Constant& value) -{ - if (int32_t* cache = constantMap.find(key)) - return *cache; - - uint32_t id = uint32_t(constants.size()); - - if (id >= kMaxConstantCount) - return -1; - - constantMap[key] = int32_t(id); - constants.push_back(value); - - return int32_t(id); -} - -unsigned int BytecodeBuilder::addStringTableEntry(StringRef value) -{ - unsigned int& index = stringTable[value]; - - // note: bytecode serialization format uses 1-based table indices, 0 is reserved to mean nil - if (index == 0) - { - index = uint32_t(stringTable.size()); - - if ((dumpFlags & Dump_Code) != 0) - debugStrings.push_back(value); - } - - return index; -} - -int32_t BytecodeBuilder::addConstantNil() -{ - Constant c = {Constant::Type_Nil}; - - ConstantKey k = {Constant::Type_Nil}; - return addConstant(k, c); -} - -int32_t BytecodeBuilder::addConstantBoolean(bool value) -{ - Constant c = {Constant::Type_Boolean}; - c.valueBoolean = value; - - ConstantKey k = {Constant::Type_Boolean, value}; - return addConstant(k, c); -} - -int32_t BytecodeBuilder::addConstantNumber(double value) -{ - Constant c = {Constant::Type_Number}; - c.valueNumber = value; - - ConstantKey k = {Constant::Type_Number}; - static_assert(sizeof(k.value) == sizeof(value), "Expecting double to be 64-bit"); - memcpy(&k.value, &value, sizeof(value)); - - return addConstant(k, c); -} - -int32_t BytecodeBuilder::addConstantVector(float x, float y, float z, float w) -{ - Constant c = {Constant::Type_Vector}; - c.valueVector[0] = x; - c.valueVector[1] = y; - c.valueVector[2] = z; - c.valueVector[3] = w; - - ConstantKey k = {Constant::Type_Vector}; - static_assert( - sizeof(k.value) == sizeof(x) + sizeof(y) && sizeof(k.extra) == sizeof(z) + sizeof(w), "Expecting vector to have four 32-bit components"); - memcpy(&k.value, &x, sizeof(x)); - memcpy((char*)&k.value + sizeof(x), &y, sizeof(y)); - memcpy(&k.extra, &z, sizeof(z)); - memcpy((char*)&k.extra + sizeof(z), &w, sizeof(w)); - - return addConstant(k, c); -} - -int32_t BytecodeBuilder::addConstantString(StringRef value) -{ - unsigned int index = addStringTableEntry(value); - - Constant c = {Constant::Type_String}; - c.valueString = index; - - ConstantKey k = {Constant::Type_String, index}; - - return addConstant(k, c); -} - -int32_t BytecodeBuilder::addImport(uint32_t iid) -{ - Constant c = {Constant::Type_Import}; - c.valueImport = iid; - - ConstantKey k = {Constant::Type_Import, iid}; - - return addConstant(k, c); -} - -int32_t BytecodeBuilder::addConstantTable(const TableShape& shape) -{ - if (int32_t* cache = tableShapeMap.find(shape)) - return *cache; - - uint32_t id = uint32_t(constants.size()); - - if (id >= kMaxConstantCount) - return -1; - - Constant value = {Constant::Type_Table}; - value.valueTable = uint32_t(tableShapes.size()); - - tableShapeMap[shape] = int32_t(id); - tableShapes.push_back(shape); - constants.push_back(value); - - return int32_t(id); -} - -int32_t BytecodeBuilder::addConstantClosure(uint32_t fid) -{ - Constant c = {Constant::Type_Closure}; - c.valueClosure = fid; - - ConstantKey k = {Constant::Type_Closure, fid}; - - return addConstant(k, c); -} - -int16_t BytecodeBuilder::addChildFunction(uint32_t fid) -{ - if (int16_t* cache = protoMap.find(fid)) - return *cache; - - uint32_t id = uint32_t(protos.size()); - - if (id >= kMaxClosureCount) - return -1; - - protoMap[fid] = int16_t(id); - protos.push_back(fid); - - return int16_t(id); -} - -void BytecodeBuilder::emitABC(LuauOpcode op, uint8_t a, uint8_t b, uint8_t c) -{ - uint32_t insn = uint32_t(op) | (a << 8) | (b << 16) | (c << 24); - - insns.push_back(insn); - lines.push_back(debugLine); -} - -void BytecodeBuilder::emitAD(LuauOpcode op, uint8_t a, int16_t d) -{ - uint32_t insn = uint32_t(op) | (a << 8) | (uint16_t(d) << 16); - - insns.push_back(insn); - lines.push_back(debugLine); -} - -void BytecodeBuilder::emitE(LuauOpcode op, int32_t e) -{ - uint32_t insn = uint32_t(op) | (uint32_t(e) << 8); - - insns.push_back(insn); - lines.push_back(debugLine); -} - -void BytecodeBuilder::emitAux(uint32_t aux) -{ - insns.push_back(aux); - lines.push_back(debugLine); -} - -size_t BytecodeBuilder::emitLabel() -{ - return insns.size(); -} - -bool BytecodeBuilder::patchJumpD(size_t jumpLabel, size_t targetLabel) -{ - LUAU_ASSERT(jumpLabel < insns.size()); - - unsigned int jumpInsn = insns[jumpLabel]; - (void)jumpInsn; - - LUAU_ASSERT(isJumpD(LuauOpcode(LUAU_INSN_OP(jumpInsn)))); - LUAU_ASSERT(LUAU_INSN_D(jumpInsn) == 0); - - LUAU_ASSERT(targetLabel <= insns.size()); - - int offset = int(targetLabel) - int(jumpLabel) - 1; - - if (int16_t(offset) == offset) - { - insns[jumpLabel] |= uint16_t(offset) << 16; - } - else if (abs(offset) < kMaxJumpDistance) - { - // our jump doesn't fit into 16 bits; we will need to repatch the bytecode sequence with jump trampolines, see expandJumps - hasLongJumps = true; - } - else - { - return false; - } - - jumps.push_back({uint32_t(jumpLabel), uint32_t(targetLabel)}); - return true; -} - -bool BytecodeBuilder::patchSkipC(size_t jumpLabel, size_t targetLabel) -{ - LUAU_ASSERT(jumpLabel < insns.size()); - - unsigned int jumpInsn = insns[jumpLabel]; - (void)jumpInsn; - - LUAU_ASSERT(isSkipC(LuauOpcode(LUAU_INSN_OP(jumpInsn))) || isFastCall(LuauOpcode(LUAU_INSN_OP(jumpInsn)))); - LUAU_ASSERT(LUAU_INSN_C(jumpInsn) == 0); - - int offset = int(targetLabel) - int(jumpLabel) - 1; - - if (uint8_t(offset) != offset) - { - return false; - } - - insns[jumpLabel] |= offset << 24; - return true; -} - -void BytecodeBuilder::setFunctionTypeInfo(std::string value) -{ - functions[currentFunction].typeinfo = std::move(value); -} - -void BytecodeBuilder::setDebugFunctionName(StringRef name) -{ - unsigned int index = addStringTableEntry(name); - - functions[currentFunction].debugname = index; - - if (dumpFunctionPtr) - functions[currentFunction].dumpname = std::string(name.data, name.length); -} - -void BytecodeBuilder::setDebugFunctionLineDefined(int line) -{ - functions[currentFunction].debuglinedefined = line; -} - -void BytecodeBuilder::setDebugLine(int line) -{ - debugLine = line; -} - -void BytecodeBuilder::pushDebugLocal(StringRef name, uint8_t reg, uint32_t startpc, uint32_t endpc) -{ - unsigned int index = addStringTableEntry(name); - - DebugLocal local; - local.name = index; - local.reg = reg; - local.startpc = startpc; - local.endpc = endpc; - - debugLocals.push_back(local); -} - -void BytecodeBuilder::pushDebugUpval(StringRef name) -{ - unsigned int index = addStringTableEntry(name); - - DebugUpval upval; - upval.name = index; - - debugUpvals.push_back(upval); -} - -size_t BytecodeBuilder::getInstructionCount() const -{ - return insns.size(); -} - -size_t BytecodeBuilder::getTotalInstructionCount() const -{ - return totalInstructionCount; -} - -uint32_t BytecodeBuilder::getDebugPC() const -{ - return uint32_t(insns.size()); -} - -void BytecodeBuilder::addDebugRemark(const char* format, ...) -{ - if ((dumpFlags & Dump_Remarks) == 0) - return; - - size_t offset = debugRemarkBuffer.size(); - - va_list args; - va_start(args, format); - vformatAppend(debugRemarkBuffer, format, args); - va_end(args); - - // we null-terminate all remarks to avoid storing remark length - debugRemarkBuffer += '\0'; - - debugRemarks.emplace_back(uint32_t(insns.size()), uint32_t(offset)); - dumpRemarks.emplace_back(debugLine, debugRemarkBuffer.c_str() + offset); -} - -void BytecodeBuilder::finalize() -{ - LUAU_ASSERT(bytecode.empty()); - - // preallocate space for bytecode blob - size_t capacity = 16; - - for (auto& p : stringTable) - capacity += p.first.length + 2; - - for (const Function& func : functions) - capacity += func.data.size(); - - bytecode.reserve(capacity); - - // assemble final bytecode blob - uint8_t version = getVersion(); - LUAU_ASSERT(version >= LBC_VERSION_MIN && version <= LBC_VERSION_MAX); - - bytecode = char(version); - - uint8_t typesversion = getTypeEncodingVersion(); - LUAU_ASSERT(typesversion == 1); - writeByte(bytecode, typesversion); - - writeStringTable(bytecode); - - writeVarInt(bytecode, uint32_t(functions.size())); - - for (const Function& func : functions) - bytecode += func.data; - - LUAU_ASSERT(mainFunction < functions.size()); - writeVarInt(bytecode, mainFunction); -} - -void BytecodeBuilder::writeFunction(std::string& ss, uint32_t id, uint8_t flags) const -{ - LUAU_ASSERT(id < functions.size()); - const Function& func = functions[id]; - - // header - writeByte(ss, func.maxstacksize); - writeByte(ss, func.numparams); - writeByte(ss, func.numupvalues); - writeByte(ss, func.isvararg); - - writeByte(ss, flags); - - writeVarInt(ss, uint32_t(func.typeinfo.size())); - ss.append(func.typeinfo); - - // instructions - writeVarInt(ss, uint32_t(insns.size())); - - for (uint32_t insn : insns) - writeInt(ss, insn); - - // constants - writeVarInt(ss, uint32_t(constants.size())); - - for (const Constant& c : constants) - { - switch (c.type) - { - case Constant::Type_Nil: - writeByte(ss, LBC_CONSTANT_NIL); - break; - - case Constant::Type_Boolean: - writeByte(ss, LBC_CONSTANT_BOOLEAN); - writeByte(ss, c.valueBoolean); - break; - - case Constant::Type_Number: - writeByte(ss, LBC_CONSTANT_NUMBER); - writeDouble(ss, c.valueNumber); - break; - - case Constant::Type_Vector: - writeByte(ss, LBC_CONSTANT_VECTOR); - writeFloat(ss, c.valueVector[0]); - writeFloat(ss, c.valueVector[1]); - writeFloat(ss, c.valueVector[2]); - writeFloat(ss, c.valueVector[3]); - break; - - case Constant::Type_String: - writeByte(ss, LBC_CONSTANT_STRING); - writeVarInt(ss, c.valueString); - break; - - case Constant::Type_Import: - writeByte(ss, LBC_CONSTANT_IMPORT); - writeInt(ss, c.valueImport); - break; - - case Constant::Type_Table: - { - const TableShape& shape = tableShapes[c.valueTable]; - writeByte(ss, LBC_CONSTANT_TABLE); - writeVarInt(ss, uint32_t(shape.length)); - for (unsigned int i = 0; i < shape.length; ++i) - writeVarInt(ss, shape.keys[i]); - break; - } - - case Constant::Type_Closure: - writeByte(ss, LBC_CONSTANT_CLOSURE); - writeVarInt(ss, c.valueClosure); - break; - - default: - LUAU_ASSERT(!"Unsupported constant type"); - } - } - - // child protos - writeVarInt(ss, uint32_t(protos.size())); - - for (uint32_t child : protos) - writeVarInt(ss, child); - - // debug info - writeVarInt(ss, func.debuglinedefined); - writeVarInt(ss, func.debugname); - - bool hasLines = true; - - for (int line : lines) - if (line == 0) - { - hasLines = false; - break; - } - - if (hasLines) - { - writeByte(ss, 1); - - writeLineInfo(ss); - } - else - { - writeByte(ss, 0); - } - - bool hasDebug = !debugLocals.empty() || !debugUpvals.empty(); - - if (hasDebug) - { - writeByte(ss, 1); - - writeVarInt(ss, uint32_t(debugLocals.size())); - - for (const DebugLocal& l : debugLocals) - { - writeVarInt(ss, l.name); - writeVarInt(ss, l.startpc); - writeVarInt(ss, l.endpc); - writeByte(ss, l.reg); - } - - writeVarInt(ss, uint32_t(debugUpvals.size())); - - for (const DebugUpval& l : debugUpvals) - { - writeVarInt(ss, l.name); - } - } - else - { - writeByte(ss, 0); - } -} - -void BytecodeBuilder::writeLineInfo(std::string& ss) const -{ - LUAU_ASSERT(!lines.empty()); - - // this function encodes lines inside each span as a 8-bit delta to span baseline - // span is always a power of two; depending on the line info input, it may need to be as low as 1 - int span = 1 << 24; - - // first pass: determine span length - for (size_t offset = 0; offset < lines.size(); offset += span) - { - size_t next = offset; - - int min = lines[offset]; - int max = lines[offset]; - - for (; next < lines.size() && next < offset + span; ++next) - { - min = std::min(min, lines[next]); - max = std::max(max, lines[next]); - - if (max - min > 255) - break; - } - - if (next < lines.size() && next - offset < size_t(span)) - { - // since not all lines in the range fit in 8b delta, we need to shrink the span - // next iteration will need to reprocess some lines again since span changed - span = 1 << log2(int(next - offset)); - } - } - - // second pass: compute span base - int baselineOne = 0; - std::vector baselineScratch; - int* baseline = &baselineOne; - size_t baselineSize = (lines.size() - 1) / span + 1; - - if (baselineSize > 1) - { - // avoid heap allocation for single-element baseline which is most functions (<256 lines) - baselineScratch.resize(baselineSize); - baseline = baselineScratch.data(); - } - - for (size_t offset = 0; offset < lines.size(); offset += span) - { - size_t next = offset; - - int min = lines[offset]; - - for (; next < lines.size() && next < offset + span; ++next) - min = std::min(min, lines[next]); - - baseline[offset / span] = min; - } - - // third pass: write resulting data - int logspan = log2(span); - - writeByte(ss, uint8_t(logspan)); - - uint8_t lastOffset = 0; - - for (size_t i = 0; i < lines.size(); ++i) - { - int delta = lines[i] - baseline[i >> logspan]; - LUAU_ASSERT(delta >= 0 && delta <= 255); - - writeByte(ss, uint8_t(delta) - lastOffset); - lastOffset = uint8_t(delta); - } - - int lastLine = 0; - - for (size_t i = 0; i < baselineSize; ++i) - { - writeInt(ss, baseline[i] - lastLine); - lastLine = baseline[i]; - } -} - -void BytecodeBuilder::writeStringTable(std::string& ss) const -{ - std::vector strings(stringTable.size()); - - for (auto& p : stringTable) - { - LUAU_ASSERT(p.second > 0 && p.second <= strings.size()); - strings[p.second - 1] = p.first; - } - - writeVarInt(ss, uint32_t(strings.size())); - - for (auto& s : strings) - { - writeVarInt(ss, uint32_t(s.length)); - ss.append(s.data, s.length); - } -} - -uint32_t BytecodeBuilder::getImportId(int32_t id0) -{ - LUAU_ASSERT(unsigned(id0) < 1024); - - return (1u << 30) | (id0 << 20); -} - -uint32_t BytecodeBuilder::getImportId(int32_t id0, int32_t id1) -{ - LUAU_ASSERT(unsigned(id0 | id1) < 1024); - - return (2u << 30) | (id0 << 20) | (id1 << 10); -} - -uint32_t BytecodeBuilder::getImportId(int32_t id0, int32_t id1, int32_t id2) -{ - LUAU_ASSERT(unsigned(id0 | id1 | id2) < 1024); - - return (3u << 30) | (id0 << 20) | (id1 << 10) | id2; -} - -int BytecodeBuilder::decomposeImportId(uint32_t ids, int32_t& id0, int32_t& id1, int32_t& id2) -{ - int count = ids >> 30; - id0 = count > 0 ? int(ids >> 20) & 1023 : -1; - id1 = count > 1 ? int(ids >> 10) & 1023 : -1; - id2 = count > 2 ? int(ids) & 1023 : -1; - return count; -} - -uint32_t BytecodeBuilder::getStringHash(StringRef key) -{ - // This hashing algorithm should match luaS_hash defined in VM/lstring.cpp for short inputs; we can't use that code directly to keep compiler and - // VM independent in terms of compilation/linking. The resulting string hashes are embedded into bytecode binary and result in a better initial - // guess for the field hashes which improves performance during initial code execution. We omit the long string processing here for simplicity, as - // it doesn't really matter on long identifiers. - const char* str = key.data; - size_t len = key.length; - - unsigned int h = unsigned(len); - - // original Lua 5.1 hash for compatibility (exact match when len<32) - for (size_t i = len; i > 0; --i) - h ^= (h << 5) + (h >> 2) + (uint8_t)str[i - 1]; - - return h; -} - -void BytecodeBuilder::foldJumps() -{ - // if our function has long jumps, some processing below can make jump instructions not-jumps (e.g. JUMP->RETURN) - // it's safer to skip this processing - if (hasLongJumps) - return; - - for (Jump& jump : jumps) - { - uint32_t jumpLabel = jump.source; - - uint32_t jumpInsn = insns[jumpLabel]; - - // follow jump target through forward unconditional jumps - // we only follow forward jumps to make sure the process terminates - uint32_t targetLabel = jumpLabel + 1 + LUAU_INSN_D(jumpInsn); - LUAU_ASSERT(targetLabel < insns.size()); - uint32_t targetInsn = insns[targetLabel]; - - while (LUAU_INSN_OP(targetInsn) == LOP_JUMP && LUAU_INSN_D(targetInsn) >= 0) - { - targetLabel = targetLabel + 1 + LUAU_INSN_D(targetInsn); - LUAU_ASSERT(targetLabel < insns.size()); - targetInsn = insns[targetLabel]; - } - - int offset = int(targetLabel) - int(jumpLabel) - 1; - - // for unconditional jumps to RETURN, we can replace JUMP with RETURN - if (LUAU_INSN_OP(jumpInsn) == LOP_JUMP && LUAU_INSN_OP(targetInsn) == LOP_RETURN) - { - insns[jumpLabel] = targetInsn; - lines[jumpLabel] = lines[targetLabel]; - } - else if (int16_t(offset) == offset) - { - insns[jumpLabel] &= 0xffff; - insns[jumpLabel] |= uint16_t(offset) << 16; - } - - jump.target = targetLabel; - } -} - -void BytecodeBuilder::expandJumps() -{ - if (!hasLongJumps) - return; - - // we have some jump instructions that couldn't be patched which means their offset didn't fit into 16 bits - // our strategy for replacing instructions is as follows: instead of - // OP jumpoffset - // we will synthesize a jump trampoline before our instruction (note that jump offsets are relative to next instruction): - // JUMP +1 - // JUMPX jumpoffset - // OP -2 - // the idea is that during forward execution, we will jump over JUMPX into OP; if OP decides to jump, it will jump to JUMPX - // JUMPX can carry a 24-bit jump offset - - // jump trampolines expand the code size, which can increase existing jump distances. - // because of this, we may need to expand jumps that previously fit into 16-bit just fine. - // the worst-case expansion is 3x, so to be conservative we will repatch all jumps that have an offset >= 32767/3 - const int kMaxJumpDistanceConservative = 32767 / 3; - - // we will need to process jumps in order - std::sort(jumps.begin(), jumps.end(), [](const Jump& lhs, const Jump& rhs) { - return lhs.source < rhs.source; - }); - - // first, let's add jump thunks for every jump with a distance that's too big - // we will create new instruction buffers, with remap table keeping track of the moves: remap[oldpc] = newpc - std::vector remap(insns.size()); - - std::vector newinsns; - std::vector newlines; - - LUAU_ASSERT(insns.size() == lines.size()); - newinsns.reserve(insns.size()); - newlines.reserve(insns.size()); - - size_t currentJump = 0; - size_t pendingTrampolines = 0; - - for (size_t i = 0; i < insns.size();) - { - uint8_t op = LUAU_INSN_OP(insns[i]); - LUAU_ASSERT(op < LOP__COUNT); - - if (currentJump < jumps.size() && jumps[currentJump].source == i) - { - int offset = int(jumps[currentJump].target) - int(jumps[currentJump].source) - 1; - - if (abs(offset) > kMaxJumpDistanceConservative) - { - // insert jump trampoline as described above; we keep JUMPX offset uninitialized in this pass - newinsns.push_back(LOP_JUMP | (1 << 16)); - newinsns.push_back(LOP_JUMPX); - - newlines.push_back(lines[i]); - newlines.push_back(lines[i]); - - pendingTrampolines++; - } - - currentJump++; - } - - int oplen = getOpLength(LuauOpcode(op)); - - // copy instruction and line info to the new stream - for (int j = 0; j < oplen; ++j) - { - remap[i] = uint32_t(newinsns.size()); - - newinsns.push_back(insns[i]); - newlines.push_back(lines[i]); - - i++; - } - } - - LUAU_ASSERT(currentJump == jumps.size()); - LUAU_ASSERT(pendingTrampolines > 0); - - // now we need to recompute offsets for jump instructions - we could not do this in the first pass because the offsets are between *target* - // instructions - for (Jump& jump : jumps) - { - int offset = int(jump.target) - int(jump.source) - 1; - int newoffset = int(remap[jump.target]) - int(remap[jump.source]) - 1; - - if (abs(offset) > kMaxJumpDistanceConservative) - { - // fix up jump trampoline - uint32_t& insnt = newinsns[remap[jump.source] - 1]; - uint32_t& insnj = newinsns[remap[jump.source]]; - - LUAU_ASSERT(LUAU_INSN_OP(insnt) == LOP_JUMPX); - - // patch JUMPX to JUMPX to target location; note that newoffset is the offset of the jump *relative to OP*, so we need to add 1 to make it - // relative to JUMPX - insnt &= 0xff; - insnt |= uint32_t(newoffset + 1) << 8; - - // patch OP to OP -2 - insnj &= 0xffff; - insnj |= uint16_t(-2) << 16; - - pendingTrampolines--; - } - else - { - uint32_t& insn = newinsns[remap[jump.source]]; - - // make sure jump instruction had the correct offset before we started - LUAU_ASSERT(LUAU_INSN_D(insn) == offset); - - // patch instruction with the new offset - LUAU_ASSERT(int16_t(newoffset) == newoffset); - - insn &= 0xffff; - insn |= uint16_t(newoffset) << 16; - } - } - - LUAU_ASSERT(pendingTrampolines == 0); - - // this was hard, but we're done. - insns.swap(newinsns); - lines.swap(newlines); -} - -std::string BytecodeBuilder::getError(const std::string& message) -{ - // 0 acts as a special marker for error bytecode (it's equal to LBC_VERSION_TARGET for valid bytecode blobs) - std::string result; - result += char(0); - result += message; - - return result; -} - -uint8_t BytecodeBuilder::getVersion() -{ - // This function usually returns LBC_VERSION_TARGET but may sometimes return a higher number (within LBC_VERSION_MIN/MAX) under fast flags - return (FFlag::LuauVectorLiterals || FFlag::LuauCompileRevK) ? 5 : LBC_VERSION_TARGET; -} - -uint8_t BytecodeBuilder::getTypeEncodingVersion() -{ - return LBC_TYPE_VERSION; -} - -#ifdef LUAU_ASSERTENABLED -void BytecodeBuilder::validate() const -{ - validateInstructions(); - validateVariadic(); -} - -void BytecodeBuilder::validateInstructions() const -{ -#define VREG(v) LUAU_ASSERT(unsigned(v) < func.maxstacksize) -#define VREGRANGE(v, count) LUAU_ASSERT(unsigned(v + (count < 0 ? 0 : count)) <= func.maxstacksize) -#define VUPVAL(v) LUAU_ASSERT(unsigned(v) < func.numupvalues) -#define VCONST(v, kind) LUAU_ASSERT(unsigned(v) < constants.size() && constants[v].type == Constant::Type_##kind) -#define VCONSTANY(v) LUAU_ASSERT(unsigned(v) < constants.size()) -#define VJUMP(v) LUAU_ASSERT(size_t(i + 1 + v) < insns.size() && insnvalid[i + 1 + v]) - - LUAU_ASSERT(currentFunction != ~0u); - - const Function& func = functions[currentFunction]; - - // tag instruction offsets so that we can validate jumps - std::vector insnvalid(insns.size(), 0); - - for (size_t i = 0; i < insns.size();) - { - uint32_t insn = insns[i]; - LuauOpcode op = LuauOpcode(LUAU_INSN_OP(insn)); - - insnvalid[i] = true; - - i += getOpLength(op); - LUAU_ASSERT(i <= insns.size()); - } - - std::vector openCaptures; - - // validate individual instructions - for (size_t i = 0; i < insns.size();) - { - uint32_t insn = insns[i]; - LuauOpcode op = LuauOpcode(LUAU_INSN_OP(insn)); - - switch (op) - { - case LOP_LOADNIL: - VREG(LUAU_INSN_A(insn)); - break; - - case LOP_LOADB: - VREG(LUAU_INSN_A(insn)); - LUAU_ASSERT(LUAU_INSN_B(insn) == 0 || LUAU_INSN_B(insn) == 1); - VJUMP(LUAU_INSN_C(insn)); - break; - - case LOP_LOADN: - VREG(LUAU_INSN_A(insn)); - break; - - case LOP_LOADK: - VREG(LUAU_INSN_A(insn)); - VCONSTANY(LUAU_INSN_D(insn)); - break; - - case LOP_MOVE: - VREG(LUAU_INSN_A(insn)); - VREG(LUAU_INSN_B(insn)); - break; - - case LOP_GETGLOBAL: - case LOP_SETGLOBAL: - VREG(LUAU_INSN_A(insn)); - VCONST(insns[i + 1], String); - break; - - case LOP_GETUPVAL: - case LOP_SETUPVAL: - VREG(LUAU_INSN_A(insn)); - VUPVAL(LUAU_INSN_B(insn)); - break; - - case LOP_CLOSEUPVALS: - VREG(LUAU_INSN_A(insn)); - while (openCaptures.size() && openCaptures.back() >= LUAU_INSN_A(insn)) - openCaptures.pop_back(); - break; - - case LOP_GETIMPORT: - { - VREG(LUAU_INSN_A(insn)); - VCONST(LUAU_INSN_D(insn), Import); - uint32_t id = insns[i + 1]; - LUAU_ASSERT((id >> 30) != 0); // import chain with length 1-3 - for (unsigned int j = 0; j < (id >> 30); ++j) - VCONST((id >> (20 - 10 * j)) & 1023, String); - } - break; - - case LOP_GETTABLE: - case LOP_SETTABLE: - VREG(LUAU_INSN_A(insn)); - VREG(LUAU_INSN_B(insn)); - VREG(LUAU_INSN_C(insn)); - break; - - case LOP_GETTABLEKS: - case LOP_SETTABLEKS: - VREG(LUAU_INSN_A(insn)); - VREG(LUAU_INSN_B(insn)); - VCONST(insns[i + 1], String); - break; - - case LOP_GETTABLEN: - case LOP_SETTABLEN: - VREG(LUAU_INSN_A(insn)); - VREG(LUAU_INSN_B(insn)); - break; - - case LOP_NEWCLOSURE: - { - VREG(LUAU_INSN_A(insn)); - LUAU_ASSERT(unsigned(LUAU_INSN_D(insn)) < protos.size()); - LUAU_ASSERT(protos[LUAU_INSN_D(insn)] < functions.size()); - unsigned int numupvalues = functions[protos[LUAU_INSN_D(insn)]].numupvalues; - - for (unsigned int j = 0; j < numupvalues; ++j) - { - LUAU_ASSERT(i + 1 + j < insns.size()); - uint32_t cinsn = insns[i + 1 + j]; - LUAU_ASSERT(LUAU_INSN_OP(cinsn) == LOP_CAPTURE); - } - } - break; - - case LOP_NAMECALL: - VREG(LUAU_INSN_A(insn)); - VREG(LUAU_INSN_B(insn)); - VCONST(insns[i + 1], String); - LUAU_ASSERT(LUAU_INSN_OP(insns[i + 2]) == LOP_CALL); - break; - - case LOP_CALL: - { - int nparams = LUAU_INSN_B(insn) - 1; - int nresults = LUAU_INSN_C(insn) - 1; - VREG(LUAU_INSN_A(insn)); - VREGRANGE(LUAU_INSN_A(insn) + 1, nparams); // 1..nparams - VREGRANGE(LUAU_INSN_A(insn), nresults); // 1..nresults - } - break; - - case LOP_RETURN: - { - int nresults = LUAU_INSN_B(insn) - 1; - VREGRANGE(LUAU_INSN_A(insn), nresults); // 0..nresults-1 - } - break; - - case LOP_JUMP: - VJUMP(LUAU_INSN_D(insn)); - break; - - case LOP_JUMPIF: - case LOP_JUMPIFNOT: - VREG(LUAU_INSN_A(insn)); - VJUMP(LUAU_INSN_D(insn)); - break; - - case LOP_JUMPIFEQ: - case LOP_JUMPIFLE: - case LOP_JUMPIFLT: - case LOP_JUMPIFNOTEQ: - case LOP_JUMPIFNOTLE: - case LOP_JUMPIFNOTLT: - VREG(LUAU_INSN_A(insn)); - VREG(insns[i + 1]); - VJUMP(LUAU_INSN_D(insn)); - break; - - case LOP_JUMPXEQKNIL: - case LOP_JUMPXEQKB: - VREG(LUAU_INSN_A(insn)); - VJUMP(LUAU_INSN_D(insn)); - break; - - case LOP_JUMPXEQKN: - VREG(LUAU_INSN_A(insn)); - VCONST(insns[i + 1] & 0xffffff, Number); - VJUMP(LUAU_INSN_D(insn)); - break; - - case LOP_JUMPXEQKS: - VREG(LUAU_INSN_A(insn)); - VCONST(insns[i + 1] & 0xffffff, String); - VJUMP(LUAU_INSN_D(insn)); - break; - - case LOP_ADD: - case LOP_SUB: - case LOP_MUL: - case LOP_DIV: - case LOP_IDIV: - case LOP_MOD: - case LOP_POW: - VREG(LUAU_INSN_A(insn)); - VREG(LUAU_INSN_B(insn)); - VREG(LUAU_INSN_C(insn)); - break; - - case LOP_ADDK: - case LOP_SUBK: - case LOP_MULK: - case LOP_DIVK: - case LOP_IDIVK: - case LOP_MODK: - case LOP_POWK: - VREG(LUAU_INSN_A(insn)); - VREG(LUAU_INSN_B(insn)); - VCONST(LUAU_INSN_C(insn), Number); - break; - - case LOP_SUBRK: - case LOP_DIVRK: - VREG(LUAU_INSN_A(insn)); - VCONST(LUAU_INSN_B(insn), Number); - VREG(LUAU_INSN_C(insn)); - break; - - case LOP_AND: - case LOP_OR: - VREG(LUAU_INSN_A(insn)); - VREG(LUAU_INSN_B(insn)); - VREG(LUAU_INSN_C(insn)); - break; - - case LOP_ANDK: - case LOP_ORK: - VREG(LUAU_INSN_A(insn)); - VREG(LUAU_INSN_B(insn)); - VCONSTANY(LUAU_INSN_C(insn)); - break; - - case LOP_CONCAT: - VREG(LUAU_INSN_A(insn)); - VREG(LUAU_INSN_B(insn)); - VREG(LUAU_INSN_C(insn)); - LUAU_ASSERT(LUAU_INSN_B(insn) <= LUAU_INSN_C(insn)); - break; - - case LOP_NOT: - case LOP_MINUS: - case LOP_LENGTH: - VREG(LUAU_INSN_A(insn)); - VREG(LUAU_INSN_B(insn)); - break; - - case LOP_NEWTABLE: - VREG(LUAU_INSN_A(insn)); - break; - - case LOP_DUPTABLE: - VREG(LUAU_INSN_A(insn)); - VCONST(LUAU_INSN_D(insn), Table); - break; - - case LOP_SETLIST: - { - int count = LUAU_INSN_C(insn) - 1; - VREG(LUAU_INSN_A(insn)); - VREGRANGE(LUAU_INSN_B(insn), count); - } - break; - - case LOP_FORNPREP: - case LOP_FORNLOOP: - // for loop protocol: A, A+1, A+2 are used for iteration - VREG(LUAU_INSN_A(insn) + 2); - VJUMP(LUAU_INSN_D(insn)); - break; - - case LOP_FORGPREP: - // forg loop protocol: A, A+1, A+2 are used for iteration protocol; A+3, ... are loop variables - VREG(LUAU_INSN_A(insn) + 2 + 1); - VJUMP(LUAU_INSN_D(insn)); - break; - - case LOP_FORGLOOP: - // forg loop protocol: A, A+1, A+2 are used for iteration protocol; A+3, ... are loop variables - VREG(LUAU_INSN_A(insn) + 2 + uint8_t(insns[i + 1])); - VJUMP(LUAU_INSN_D(insn)); - LUAU_ASSERT(uint8_t(insns[i + 1]) >= 1); - break; - - case LOP_FORGPREP_INEXT: - case LOP_FORGPREP_NEXT: - VREG(LUAU_INSN_A(insn) + 4); // forg loop protocol: A, A+1, A+2 are used for iteration protocol; A+3, A+4 are loop variables - VJUMP(LUAU_INSN_D(insn)); - break; - - case LOP_GETVARARGS: - { - int nresults = LUAU_INSN_B(insn) - 1; - VREGRANGE(LUAU_INSN_A(insn), nresults); // 0..nresults-1 - } - break; - - case LOP_DUPCLOSURE: - { - VREG(LUAU_INSN_A(insn)); - VCONST(LUAU_INSN_D(insn), Closure); - unsigned int proto = constants[LUAU_INSN_D(insn)].valueClosure; - LUAU_ASSERT(proto < functions.size()); - unsigned int numupvalues = functions[proto].numupvalues; - - for (unsigned int j = 0; j < numupvalues; ++j) - { - LUAU_ASSERT(i + 1 + j < insns.size()); - uint32_t cinsn = insns[i + 1 + j]; - LUAU_ASSERT(LUAU_INSN_OP(cinsn) == LOP_CAPTURE); - LUAU_ASSERT(LUAU_INSN_A(cinsn) == LCT_VAL || LUAU_INSN_A(cinsn) == LCT_UPVAL); - } - } - break; - - case LOP_PREPVARARGS: - LUAU_ASSERT(LUAU_INSN_A(insn) == func.numparams); - LUAU_ASSERT(func.isvararg); - break; - - case LOP_BREAK: - break; - - case LOP_JUMPBACK: - VJUMP(LUAU_INSN_D(insn)); - break; - - case LOP_LOADKX: - VREG(LUAU_INSN_A(insn)); - VCONSTANY(insns[i + 1]); - break; - - case LOP_JUMPX: - VJUMP(LUAU_INSN_E(insn)); - break; - - case LOP_FASTCALL: - VJUMP(LUAU_INSN_C(insn)); - LUAU_ASSERT(LUAU_INSN_OP(insns[i + 1 + LUAU_INSN_C(insn)]) == LOP_CALL); - break; - - case LOP_FASTCALL1: - VREG(LUAU_INSN_B(insn)); - VJUMP(LUAU_INSN_C(insn)); - LUAU_ASSERT(LUAU_INSN_OP(insns[i + 1 + LUAU_INSN_C(insn)]) == LOP_CALL); - break; - - case LOP_FASTCALL2: - VREG(LUAU_INSN_B(insn)); - VJUMP(LUAU_INSN_C(insn)); - LUAU_ASSERT(LUAU_INSN_OP(insns[i + 1 + LUAU_INSN_C(insn)]) == LOP_CALL); - VREG(insns[i + 1]); - break; - - case LOP_FASTCALL2K: - VREG(LUAU_INSN_B(insn)); - VJUMP(LUAU_INSN_C(insn)); - LUAU_ASSERT(LUAU_INSN_OP(insns[i + 1 + LUAU_INSN_C(insn)]) == LOP_CALL); - VCONSTANY(insns[i + 1]); - break; - - case LOP_COVERAGE: - break; - - case LOP_CAPTURE: - switch (LUAU_INSN_A(insn)) - { - case LCT_VAL: - VREG(LUAU_INSN_B(insn)); - break; - - case LCT_REF: - VREG(LUAU_INSN_B(insn)); - openCaptures.push_back(LUAU_INSN_B(insn)); - break; - - case LCT_UPVAL: - VUPVAL(LUAU_INSN_B(insn)); - break; - - default: - LUAU_ASSERT(!"Unsupported capture type"); - } - break; - - default: - LUAU_ASSERT(!"Unsupported opcode"); - } - - i += getOpLength(op); - LUAU_ASSERT(i <= insns.size()); - } - - // all CAPTURE REF instructions must have a CLOSEUPVALS instruction after them in the bytecode stream - // this doesn't guarantee safety as it doesn't perform basic block based analysis, but if this fails - // then the bytecode is definitely unsafe to run since the compiler won't generate backwards branches - // except for loop edges - LUAU_ASSERT(openCaptures.empty()); - -#undef VREG -#undef VREGEND -#undef VUPVAL -#undef VCONST -#undef VCONSTANY -#undef VJUMP -} - -void BytecodeBuilder::validateVariadic() const -{ - // validate MULTRET sequences: instructions that produce a variadic sequence and consume one must come in pairs - // we classify instructions into four groups: producers, consumers, neutral and others - // any producer (an instruction that produces more than one value) must be followed by 0 or more neutral instructions - // and a consumer (that consumes more than one value); these form a variadic sequence. - // except for producer, no instruction in the variadic sequence may be a jump target. - // from the execution perspective, producer adjusts L->top to point to one past the last result, neutral instructions - // leave L->top unmodified, and consumer adjusts L->top back to the stack frame end. - // consumers invalidate all values after L->top after they execute (which we currently don't validate) - bool variadicSeq = false; - - std::vector insntargets(insns.size(), 0); - - for (size_t i = 0; i < insns.size();) - { - uint32_t insn = insns[i]; - LuauOpcode op = LuauOpcode(LUAU_INSN_OP(insn)); - - int target = getJumpTarget(insn, uint32_t(i)); - - if (target >= 0 && !isFastCall(op)) - { - LUAU_ASSERT(unsigned(target) < insns.size()); - - insntargets[target] = true; - } - - i += getOpLength(op); - LUAU_ASSERT(i <= insns.size()); - } - - for (size_t i = 0; i < insns.size();) - { - uint32_t insn = insns[i]; - LuauOpcode op = LuauOpcode(LUAU_INSN_OP(insn)); - - if (variadicSeq) - { - // no instruction inside the sequence, including the consumer, may be a jump target - // this guarantees uninterrupted L->top adjustment flow - LUAU_ASSERT(!insntargets[i]); - } - - if (op == LOP_CALL) - { - // note: calls may end one variadic sequence and start a new one - - if (LUAU_INSN_B(insn) == 0) - { - // consumer instruction ens a variadic sequence - LUAU_ASSERT(variadicSeq); - variadicSeq = false; - } - else - { - // CALL is not a neutral instruction so it can't be present in a variadic sequence unless it's a consumer - LUAU_ASSERT(!variadicSeq); - } - - if (LUAU_INSN_C(insn) == 0) - { - // producer instruction starts a variadic sequence - LUAU_ASSERT(!variadicSeq); - variadicSeq = true; - } - } - else if (op == LOP_GETVARARGS && LUAU_INSN_B(insn) == 0) - { - // producer instruction starts a variadic sequence - LUAU_ASSERT(!variadicSeq); - variadicSeq = true; - } - else if ((op == LOP_RETURN && LUAU_INSN_B(insn) == 0) || (op == LOP_SETLIST && LUAU_INSN_C(insn) == 0)) - { - // consumer instruction ends a variadic sequence - LUAU_ASSERT(variadicSeq); - variadicSeq = false; - } - else if (op == LOP_FASTCALL) - { - int callTarget = int(i + LUAU_INSN_C(insn) + 1); - LUAU_ASSERT(unsigned(callTarget) < insns.size() && LUAU_INSN_OP(insns[callTarget]) == LOP_CALL); - - if (LUAU_INSN_B(insns[callTarget]) == 0) - { - // consumer instruction ends a variadic sequence; however, we can't terminate it yet because future analysis of CALL will do it - // during FASTCALL fallback, the instructions between this and CALL consumer are going to be executed before L->top so they must - // be neutral; as such, we will defer termination of variadic sequence until CALL analysis - LUAU_ASSERT(variadicSeq); - } - else - { - // FASTCALL is not a neutral instruction so it can't be present in a variadic sequence unless it's linked to CALL consumer - LUAU_ASSERT(!variadicSeq); - } - - // note: if FASTCALL is linked to a CALL producer, the instructions between FASTCALL and CALL are technically not part of an executed - // variadic sequence since they are never executed if FASTCALL does anything, so it's okay to skip their validation until CALL - // (we can't simply start a variadic sequence here because that would trigger assertions during linked CALL validation) - } - else if (op == LOP_CLOSEUPVALS || op == LOP_NAMECALL || op == LOP_GETIMPORT || op == LOP_MOVE || op == LOP_GETUPVAL || op == LOP_GETGLOBAL || - op == LOP_GETTABLEKS || op == LOP_COVERAGE) - { - // instructions inside a variadic sequence must be neutral (can't change L->top) - // while there are many neutral instructions like this, here we check that the instruction is one of the few - // that we'd expect to exist in FASTCALL fallback sequences or between consecutive CALLs for encoding reasons - } - else - { - LUAU_ASSERT(!variadicSeq); - } - - i += getOpLength(op); - LUAU_ASSERT(i <= insns.size()); - } - - LUAU_ASSERT(!variadicSeq); -} -#endif - -static bool printableStringConstant(const char* str, size_t len) -{ - for (size_t i = 0; i < len; ++i) - { - if (unsigned(str[i]) < ' ') - return false; - } - - return true; -} - -void BytecodeBuilder::dumpConstant(std::string& result, int k) const -{ - LUAU_ASSERT(unsigned(k) < constants.size()); - const Constant& data = constants[k]; - - switch (data.type) - { - case Constant::Type_Nil: - formatAppend(result, "nil"); - break; - case Constant::Type_Boolean: - formatAppend(result, "%s", data.valueBoolean ? "true" : "false"); - break; - case Constant::Type_Number: - formatAppend(result, "%.17g", data.valueNumber); - break; - case Constant::Type_Vector: - // 3-vectors is the most common configuration, so truncate to three components if possible - if (data.valueVector[3] == 0.0) - formatAppend(result, "%.9g, %.9g, %.9g", data.valueVector[0], data.valueVector[1], data.valueVector[2]); - else - formatAppend(result, "%.9g, %.9g, %.9g, %.9g", data.valueVector[0], data.valueVector[1], data.valueVector[2], data.valueVector[3]); - break; - case Constant::Type_String: - { - const StringRef& str = debugStrings[data.valueString - 1]; - - if (printableStringConstant(str.data, str.length)) - { - if (str.length < 32) - formatAppend(result, "'%.*s'", int(str.length), str.data); - else - formatAppend(result, "'%.*s'...", 32, str.data); - } - break; - } - case Constant::Type_Import: - { - int id0 = -1, id1 = -1, id2 = -1; - if (int count = decomposeImportId(data.valueImport, id0, id1, id2)) - { - { - const Constant& id = constants[id0]; - LUAU_ASSERT(id.type == Constant::Type_String && id.valueString <= debugStrings.size()); - - const StringRef& str = debugStrings[id.valueString - 1]; - formatAppend(result, "%.*s", int(str.length), str.data); - } - - if (count > 1) - { - const Constant& id = constants[id1]; - LUAU_ASSERT(id.type == Constant::Type_String && id.valueString <= debugStrings.size()); - - const StringRef& str = debugStrings[id.valueString - 1]; - formatAppend(result, ".%.*s", int(str.length), str.data); - } - - if (count > 2) - { - const Constant& id = constants[id2]; - LUAU_ASSERT(id.type == Constant::Type_String && id.valueString <= debugStrings.size()); - - const StringRef& str = debugStrings[id.valueString - 1]; - formatAppend(result, ".%.*s", int(str.length), str.data); - } - } - break; - } - case Constant::Type_Table: - formatAppend(result, "{...}"); - break; - case Constant::Type_Closure: - { - const Function& func = functions[data.valueClosure]; - - if (!func.dumpname.empty()) - formatAppend(result, "'%s'", func.dumpname.c_str()); - break; - } - } -} - -void BytecodeBuilder::dumpInstruction(const uint32_t* code, std::string& result, int targetLabel) const -{ - uint32_t insn = *code++; - - switch (LUAU_INSN_OP(insn)) - { - case LOP_LOADNIL: - formatAppend(result, "LOADNIL R%d\n", LUAU_INSN_A(insn)); - break; - - case LOP_LOADB: - if (LUAU_INSN_C(insn)) - formatAppend(result, "LOADB R%d %d +%d\n", LUAU_INSN_A(insn), LUAU_INSN_B(insn), LUAU_INSN_C(insn)); - else - formatAppend(result, "LOADB R%d %d\n", LUAU_INSN_A(insn), LUAU_INSN_B(insn)); - break; - - case LOP_LOADN: - formatAppend(result, "LOADN R%d %d\n", LUAU_INSN_A(insn), LUAU_INSN_D(insn)); - break; - - case LOP_LOADK: - formatAppend(result, "LOADK R%d K%d [", LUAU_INSN_A(insn), LUAU_INSN_D(insn)); - dumpConstant(result, LUAU_INSN_D(insn)); - result.append("]\n"); - break; - - case LOP_MOVE: - formatAppend(result, "MOVE R%d R%d\n", LUAU_INSN_A(insn), LUAU_INSN_B(insn)); - break; - - case LOP_GETGLOBAL: - formatAppend(result, "GETGLOBAL R%d K%d [", LUAU_INSN_A(insn), *code); - dumpConstant(result, *code); - result.append("]\n"); - code++; - break; - - case LOP_SETGLOBAL: - formatAppend(result, "SETGLOBAL R%d K%d [", LUAU_INSN_A(insn), *code); - dumpConstant(result, *code); - result.append("]\n"); - code++; - break; - - case LOP_GETUPVAL: - formatAppend(result, "GETUPVAL R%d %d\n", LUAU_INSN_A(insn), LUAU_INSN_B(insn)); - break; - - case LOP_SETUPVAL: - formatAppend(result, "SETUPVAL R%d %d\n", LUAU_INSN_A(insn), LUAU_INSN_B(insn)); - break; - - case LOP_CLOSEUPVALS: - formatAppend(result, "CLOSEUPVALS R%d\n", LUAU_INSN_A(insn)); - break; - - case LOP_GETIMPORT: - formatAppend(result, "GETIMPORT R%d %d [", LUAU_INSN_A(insn), LUAU_INSN_D(insn)); - dumpConstant(result, LUAU_INSN_D(insn)); - result.append("]\n"); - code++; // AUX - break; - - case LOP_GETTABLE: - formatAppend(result, "GETTABLE R%d R%d R%d\n", LUAU_INSN_A(insn), LUAU_INSN_B(insn), LUAU_INSN_C(insn)); - break; - - case LOP_SETTABLE: - formatAppend(result, "SETTABLE R%d R%d R%d\n", LUAU_INSN_A(insn), LUAU_INSN_B(insn), LUAU_INSN_C(insn)); - break; - - case LOP_GETTABLEKS: - formatAppend(result, "GETTABLEKS R%d R%d K%d [", LUAU_INSN_A(insn), LUAU_INSN_B(insn), *code); - dumpConstant(result, *code); - result.append("]\n"); - code++; - break; - - case LOP_SETTABLEKS: - formatAppend(result, "SETTABLEKS R%d R%d K%d [", LUAU_INSN_A(insn), LUAU_INSN_B(insn), *code); - dumpConstant(result, *code); - result.append("]\n"); - code++; - break; - - case LOP_GETTABLEN: - formatAppend(result, "GETTABLEN R%d R%d %d\n", LUAU_INSN_A(insn), LUAU_INSN_B(insn), LUAU_INSN_C(insn) + 1); - break; - - case LOP_SETTABLEN: - formatAppend(result, "SETTABLEN R%d R%d %d\n", LUAU_INSN_A(insn), LUAU_INSN_B(insn), LUAU_INSN_C(insn) + 1); - break; - - case LOP_NEWCLOSURE: - formatAppend(result, "NEWCLOSURE R%d P%d\n", LUAU_INSN_A(insn), LUAU_INSN_D(insn)); - break; - - case LOP_NAMECALL: - formatAppend(result, "NAMECALL R%d R%d K%d [", LUAU_INSN_A(insn), LUAU_INSN_B(insn), *code); - dumpConstant(result, *code); - result.append("]\n"); - code++; - break; - - case LOP_CALL: - formatAppend(result, "CALL R%d %d %d\n", LUAU_INSN_A(insn), LUAU_INSN_B(insn) - 1, LUAU_INSN_C(insn) - 1); - break; - - case LOP_RETURN: - formatAppend(result, "RETURN R%d %d\n", LUAU_INSN_A(insn), LUAU_INSN_B(insn) - 1); - break; - - case LOP_JUMP: - formatAppend(result, "JUMP L%d\n", targetLabel); - break; - - case LOP_JUMPIF: - formatAppend(result, "JUMPIF R%d L%d\n", LUAU_INSN_A(insn), targetLabel); - break; - - case LOP_JUMPIFNOT: - formatAppend(result, "JUMPIFNOT R%d L%d\n", LUAU_INSN_A(insn), targetLabel); - break; - - case LOP_JUMPIFEQ: - formatAppend(result, "JUMPIFEQ R%d R%d L%d\n", LUAU_INSN_A(insn), *code++, targetLabel); - break; - - case LOP_JUMPIFLE: - formatAppend(result, "JUMPIFLE R%d R%d L%d\n", LUAU_INSN_A(insn), *code++, targetLabel); - break; - - case LOP_JUMPIFLT: - formatAppend(result, "JUMPIFLT R%d R%d L%d\n", LUAU_INSN_A(insn), *code++, targetLabel); - break; - - case LOP_JUMPIFNOTEQ: - formatAppend(result, "JUMPIFNOTEQ R%d R%d L%d\n", LUAU_INSN_A(insn), *code++, targetLabel); - break; - - case LOP_JUMPIFNOTLE: - formatAppend(result, "JUMPIFNOTLE R%d R%d L%d\n", LUAU_INSN_A(insn), *code++, targetLabel); - break; - - case LOP_JUMPIFNOTLT: - formatAppend(result, "JUMPIFNOTLT R%d R%d L%d\n", LUAU_INSN_A(insn), *code++, targetLabel); - break; - - case LOP_ADD: - formatAppend(result, "ADD R%d R%d R%d\n", LUAU_INSN_A(insn), LUAU_INSN_B(insn), LUAU_INSN_C(insn)); - break; - - case LOP_SUB: - formatAppend(result, "SUB R%d R%d R%d\n", LUAU_INSN_A(insn), LUAU_INSN_B(insn), LUAU_INSN_C(insn)); - break; - - case LOP_MUL: - formatAppend(result, "MUL R%d R%d R%d\n", LUAU_INSN_A(insn), LUAU_INSN_B(insn), LUAU_INSN_C(insn)); - break; - - case LOP_DIV: - formatAppend(result, "DIV R%d R%d R%d\n", LUAU_INSN_A(insn), LUAU_INSN_B(insn), LUAU_INSN_C(insn)); - break; - - case LOP_IDIV: - formatAppend(result, "IDIV R%d R%d R%d\n", LUAU_INSN_A(insn), LUAU_INSN_B(insn), LUAU_INSN_C(insn)); - break; - - case LOP_MOD: - formatAppend(result, "MOD R%d R%d R%d\n", LUAU_INSN_A(insn), LUAU_INSN_B(insn), LUAU_INSN_C(insn)); - break; - - case LOP_POW: - formatAppend(result, "POW R%d R%d R%d\n", LUAU_INSN_A(insn), LUAU_INSN_B(insn), LUAU_INSN_C(insn)); - break; - - case LOP_ADDK: - formatAppend(result, "ADDK R%d R%d K%d [", LUAU_INSN_A(insn), LUAU_INSN_B(insn), LUAU_INSN_C(insn)); - dumpConstant(result, LUAU_INSN_C(insn)); - result.append("]\n"); - break; - - case LOP_SUBK: - formatAppend(result, "SUBK R%d R%d K%d [", LUAU_INSN_A(insn), LUAU_INSN_B(insn), LUAU_INSN_C(insn)); - dumpConstant(result, LUAU_INSN_C(insn)); - result.append("]\n"); - break; - - case LOP_MULK: - formatAppend(result, "MULK R%d R%d K%d [", LUAU_INSN_A(insn), LUAU_INSN_B(insn), LUAU_INSN_C(insn)); - dumpConstant(result, LUAU_INSN_C(insn)); - result.append("]\n"); - break; - - case LOP_DIVK: - formatAppend(result, "DIVK R%d R%d K%d [", LUAU_INSN_A(insn), LUAU_INSN_B(insn), LUAU_INSN_C(insn)); - dumpConstant(result, LUAU_INSN_C(insn)); - result.append("]\n"); - break; - - case LOP_IDIVK: - formatAppend(result, "IDIVK R%d R%d K%d [", LUAU_INSN_A(insn), LUAU_INSN_B(insn), LUAU_INSN_C(insn)); - dumpConstant(result, LUAU_INSN_C(insn)); - result.append("]\n"); - break; - - case LOP_MODK: - formatAppend(result, "MODK R%d R%d K%d [", LUAU_INSN_A(insn), LUAU_INSN_B(insn), LUAU_INSN_C(insn)); - dumpConstant(result, LUAU_INSN_C(insn)); - result.append("]\n"); - break; - - case LOP_POWK: - formatAppend(result, "POWK R%d R%d K%d [", LUAU_INSN_A(insn), LUAU_INSN_B(insn), LUAU_INSN_C(insn)); - dumpConstant(result, LUAU_INSN_C(insn)); - result.append("]\n"); - break; - - case LOP_SUBRK: - formatAppend(result, "SUBRK R%d K%d [", LUAU_INSN_A(insn), LUAU_INSN_B(insn)); - dumpConstant(result, LUAU_INSN_B(insn)); - formatAppend(result, "] R%d\n", LUAU_INSN_C(insn)); - break; - - case LOP_DIVRK: - formatAppend(result, "DIVRK R%d K%d [", LUAU_INSN_A(insn), LUAU_INSN_B(insn)); - dumpConstant(result, LUAU_INSN_B(insn)); - formatAppend(result, "] R%d\n", LUAU_INSN_C(insn)); - break; - - case LOP_AND: - formatAppend(result, "AND R%d R%d R%d\n", LUAU_INSN_A(insn), LUAU_INSN_B(insn), LUAU_INSN_C(insn)); - break; - - case LOP_OR: - formatAppend(result, "OR R%d R%d R%d\n", LUAU_INSN_A(insn), LUAU_INSN_B(insn), LUAU_INSN_C(insn)); - break; - - case LOP_ANDK: - formatAppend(result, "ANDK R%d R%d K%d [", LUAU_INSN_A(insn), LUAU_INSN_B(insn), LUAU_INSN_C(insn)); - dumpConstant(result, LUAU_INSN_C(insn)); - result.append("]\n"); - break; - - case LOP_ORK: - formatAppend(result, "ORK R%d R%d K%d [", LUAU_INSN_A(insn), LUAU_INSN_B(insn), LUAU_INSN_C(insn)); - dumpConstant(result, LUAU_INSN_C(insn)); - result.append("]\n"); - break; - - case LOP_CONCAT: - formatAppend(result, "CONCAT R%d R%d R%d\n", LUAU_INSN_A(insn), LUAU_INSN_B(insn), LUAU_INSN_C(insn)); - break; - - case LOP_NOT: - formatAppend(result, "NOT R%d R%d\n", LUAU_INSN_A(insn), LUAU_INSN_B(insn)); - break; - - case LOP_MINUS: - formatAppend(result, "MINUS R%d R%d\n", LUAU_INSN_A(insn), LUAU_INSN_B(insn)); - break; - - case LOP_LENGTH: - formatAppend(result, "LENGTH R%d R%d\n", LUAU_INSN_A(insn), LUAU_INSN_B(insn)); - break; - - case LOP_NEWTABLE: - formatAppend(result, "NEWTABLE R%d %d %d\n", LUAU_INSN_A(insn), LUAU_INSN_B(insn) == 0 ? 0 : 1 << (LUAU_INSN_B(insn) - 1), *code++); - break; - - case LOP_DUPTABLE: - formatAppend(result, "DUPTABLE R%d %d\n", LUAU_INSN_A(insn), LUAU_INSN_D(insn)); - break; - - case LOP_SETLIST: - formatAppend(result, "SETLIST R%d R%d %d [%d]\n", LUAU_INSN_A(insn), LUAU_INSN_B(insn), LUAU_INSN_C(insn) - 1, *code++); - break; - - case LOP_FORNPREP: - formatAppend(result, "FORNPREP R%d L%d\n", LUAU_INSN_A(insn), targetLabel); - break; - - case LOP_FORNLOOP: - formatAppend(result, "FORNLOOP R%d L%d\n", LUAU_INSN_A(insn), targetLabel); - break; - - case LOP_FORGPREP: - formatAppend(result, "FORGPREP R%d L%d\n", LUAU_INSN_A(insn), targetLabel); - break; - - case LOP_FORGLOOP: - formatAppend(result, "FORGLOOP R%d L%d %d%s\n", LUAU_INSN_A(insn), targetLabel, uint8_t(*code), int(*code) < 0 ? " [inext]" : ""); - code++; - break; - - case LOP_FORGPREP_INEXT: - formatAppend(result, "FORGPREP_INEXT R%d L%d\n", LUAU_INSN_A(insn), targetLabel); - break; - - case LOP_FORGPREP_NEXT: - formatAppend(result, "FORGPREP_NEXT R%d L%d\n", LUAU_INSN_A(insn), targetLabel); - break; - - case LOP_GETVARARGS: - formatAppend(result, "GETVARARGS R%d %d\n", LUAU_INSN_A(insn), LUAU_INSN_B(insn) - 1); - break; - - case LOP_DUPCLOSURE: - formatAppend(result, "DUPCLOSURE R%d K%d [", LUAU_INSN_A(insn), LUAU_INSN_D(insn)); - dumpConstant(result, LUAU_INSN_D(insn)); - result.append("]\n"); - break; - - case LOP_BREAK: - formatAppend(result, "BREAK\n"); - break; - - case LOP_JUMPBACK: - formatAppend(result, "JUMPBACK L%d\n", targetLabel); - break; - - case LOP_LOADKX: - formatAppend(result, "LOADKX R%d K%d [", LUAU_INSN_A(insn), *code); - dumpConstant(result, *code); - result.append("]\n"); - code++; - break; - - case LOP_JUMPX: - formatAppend(result, "JUMPX L%d\n", targetLabel); - break; - - case LOP_FASTCALL: - formatAppend(result, "FASTCALL %d L%d\n", LUAU_INSN_A(insn), targetLabel); - break; - - case LOP_FASTCALL1: - formatAppend(result, "FASTCALL1 %d R%d L%d\n", LUAU_INSN_A(insn), LUAU_INSN_B(insn), targetLabel); - break; - - case LOP_FASTCALL2: - formatAppend(result, "FASTCALL2 %d R%d R%d L%d\n", LUAU_INSN_A(insn), LUAU_INSN_B(insn), *code, targetLabel); - code++; - break; - - case LOP_FASTCALL2K: - formatAppend(result, "FASTCALL2K %d R%d K%d L%d [", LUAU_INSN_A(insn), LUAU_INSN_B(insn), *code, targetLabel); - dumpConstant(result, *code); - result.append("]\n"); - code++; - break; - - case LOP_COVERAGE: - formatAppend(result, "COVERAGE\n"); - break; - - case LOP_CAPTURE: - formatAppend(result, "CAPTURE %s %c%d\n", - LUAU_INSN_A(insn) == LCT_UPVAL ? "UPVAL" - : LUAU_INSN_A(insn) == LCT_REF ? "REF" - : LUAU_INSN_A(insn) == LCT_VAL ? "VAL" - : "", - LUAU_INSN_A(insn) == LCT_UPVAL ? 'U' : 'R', LUAU_INSN_B(insn)); - break; - - case LOP_JUMPXEQKNIL: - formatAppend(result, "JUMPXEQKNIL R%d L%d%s\n", LUAU_INSN_A(insn), targetLabel, *code >> 31 ? " NOT" : ""); - code++; - break; - - case LOP_JUMPXEQKB: - formatAppend(result, "JUMPXEQKB R%d %d L%d%s\n", LUAU_INSN_A(insn), *code & 1, targetLabel, *code >> 31 ? " NOT" : ""); - code++; - break; - - case LOP_JUMPXEQKN: - formatAppend(result, "JUMPXEQKN R%d K%d L%d%s [", LUAU_INSN_A(insn), *code & 0xffffff, targetLabel, *code >> 31 ? " NOT" : ""); - dumpConstant(result, *code & 0xffffff); - result.append("]\n"); - code++; - break; - - case LOP_JUMPXEQKS: - formatAppend(result, "JUMPXEQKS R%d K%d L%d%s [", LUAU_INSN_A(insn), *code & 0xffffff, targetLabel, *code >> 31 ? " NOT" : ""); - dumpConstant(result, *code & 0xffffff); - result.append("]\n"); - code++; - break; - - default: - LUAU_ASSERT(!"Unsupported opcode"); - } -} - -std::string BytecodeBuilder::dumpCurrentFunction(std::vector& dumpinstoffs) const -{ - if ((dumpFlags & Dump_Code) == 0) - return std::string(); - - int lastLine = -1; - size_t nextRemark = 0; - - std::string result; - - if (dumpFlags & Dump_Locals) - { - for (size_t i = 0; i < debugLocals.size(); ++i) - { - const DebugLocal& l = debugLocals[i]; - - LUAU_ASSERT(l.startpc < l.endpc); - LUAU_ASSERT(l.startpc < lines.size()); - LUAU_ASSERT(l.endpc <= lines.size()); // endpc is exclusive in the debug info, but it's more intuitive to print inclusive data - - // it would be nice to emit name as well but it requires reverse lookup through stringtable - formatAppend(result, "local %d: reg %d, start pc %d line %d, end pc %d line %d\n", int(i), l.reg, l.startpc, lines[l.startpc], - l.endpc - 1, lines[l.endpc - 1]); - } - } - - std::vector labels(insns.size(), -1); - - // annotate valid jump targets with 0 - for (size_t i = 0; i < insns.size();) - { - int target = getJumpTarget(insns[i], uint32_t(i)); - - if (target >= 0) - { - LUAU_ASSERT(size_t(target) < insns.size()); - labels[target] = 0; - } - - i += getOpLength(LuauOpcode(LUAU_INSN_OP(insns[i]))); - LUAU_ASSERT(i <= insns.size()); - } - - int nextLabel = 0; - - // compute label ids (sequential integers for all jump targets) - for (size_t i = 0; i < labels.size(); ++i) - if (labels[i] == 0) - labels[i] = nextLabel++; - - dumpinstoffs.resize(insns.size() + 1, -1); - - for (size_t i = 0; i < insns.size();) - { - const uint32_t* code = &insns[i]; - uint8_t op = LUAU_INSN_OP(*code); - - dumpinstoffs[i] = int(result.size()); - - if (op == LOP_PREPVARARGS) - { - // Don't emit function header in bytecode - it's used for call dispatching and doesn't contain "interesting" information - i++; - continue; - } - - if (dumpFlags & Dump_Remarks) - { - while (nextRemark < debugRemarks.size() && debugRemarks[nextRemark].first == i) - { - formatAppend(result, "REMARK %s\n", debugRemarkBuffer.c_str() + debugRemarks[nextRemark].second); - nextRemark++; - } - } - - if (dumpFlags & Dump_Source) - { - int line = lines[i]; - - if (line > 0 && line != lastLine) - { - LUAU_ASSERT(size_t(line - 1) < dumpSource.size()); - formatAppend(result, "%5d: %s\n", line, dumpSource[line - 1].c_str()); - lastLine = line; - } - } - - if (dumpFlags & Dump_Lines) - formatAppend(result, "%d: ", lines[i]); - - if (labels[i] != -1) - formatAppend(result, "L%d: ", labels[i]); - - int target = getJumpTarget(*code, uint32_t(i)); - - dumpInstruction(code, result, target >= 0 ? labels[target] : -1); - - i += getOpLength(LuauOpcode(op)); - LUAU_ASSERT(i <= insns.size()); - } - - dumpinstoffs[insns.size()] = int(result.size()); - - return result; -} - -void BytecodeBuilder::setDumpSource(const std::string& source) -{ - dumpSource.clear(); - - size_t pos = 0; - - while (pos != std::string::npos) - { - size_t next = source.find('\n', pos); - - if (next == std::string::npos) - { - dumpSource.push_back(source.substr(pos)); - pos = next; - } - else - { - dumpSource.push_back(source.substr(pos, next - pos)); - pos = next + 1; - } - - if (!dumpSource.back().empty() && dumpSource.back().back() == '\r') - dumpSource.back().pop_back(); - } -} - -std::string BytecodeBuilder::dumpFunction(uint32_t id) const -{ - LUAU_ASSERT(id < functions.size()); - - return functions[id].dump; -} - -std::string BytecodeBuilder::dumpEverything() const -{ - std::string result; - - for (size_t i = 0; i < functions.size(); ++i) - { - std::string debugname = functions[i].dumpname.empty() ? "??" : functions[i].dumpname; - - formatAppend(result, "Function %d (%s):\n", int(i), debugname.c_str()); - - result += functions[i].dump; - result += "\n"; - } - - return result; -} - -std::string BytecodeBuilder::dumpSourceRemarks() const -{ - std::string result; - - size_t nextRemark = 0; - - std::vector> remarks = dumpRemarks; - std::sort(remarks.begin(), remarks.end()); - - for (size_t i = 0; i < dumpSource.size(); ++i) - { - const std::string& line = dumpSource[i]; - - size_t indent = 0; - while (indent < line.length() && (line[indent] == ' ' || line[indent] == '\t')) - indent++; - - while (nextRemark < remarks.size() && remarks[nextRemark].first == int(i + 1)) - { - formatAppend(result, "%.*s-- remark: %s\n", int(indent), line.c_str(), remarks[nextRemark].second.c_str()); - nextRemark++; - - // skip duplicate remarks (due to inlining/unrolling) - while (nextRemark < remarks.size() && remarks[nextRemark] == remarks[nextRemark - 1]) - nextRemark++; - } - - result += line; - - if (i + 1 < dumpSource.size()) - result += '\n'; - } - - return result; -} - -static const char* getBaseTypeString(uint8_t type) -{ - uint8_t tag = type & ~LBC_TYPE_OPTIONAL_BIT; - switch (tag) - { - case LBC_TYPE_NIL: - return "nil"; - case LBC_TYPE_BOOLEAN: - return "boolean"; - case LBC_TYPE_NUMBER: - return "number"; - case LBC_TYPE_STRING: - return "string"; - case LBC_TYPE_TABLE: - return "table"; - case LBC_TYPE_FUNCTION: - return "function"; - case LBC_TYPE_THREAD: - return "thread"; - case LBC_TYPE_USERDATA: - return "userdata"; - case LBC_TYPE_VECTOR: - return "vector"; - case LBC_TYPE_BUFFER: - return "buffer"; - case LBC_TYPE_ANY: - return "any"; - } - - LUAU_ASSERT(!"Unhandled type in getBaseTypeString"); - return nullptr; -} - -std::string BytecodeBuilder::dumpTypeInfo() const -{ - std::string result; - - for (size_t i = 0; i < functions.size(); ++i) - { - const std::string& typeinfo = functions[i].typeinfo; - if (typeinfo.empty()) - continue; - - uint8_t encodedType = typeinfo[0]; - - LUAU_ASSERT(encodedType == LBC_TYPE_FUNCTION); - - formatAppend(result, "%zu: function(", i); - - LUAU_ASSERT(typeinfo.size() >= 2); - - uint8_t numparams = typeinfo[1]; - - LUAU_ASSERT(size_t(1 + numparams - 1) < typeinfo.size()); - - for (uint8_t i = 0; i < numparams; ++i) - { - uint8_t et = typeinfo[2 + i]; - const char* optional = (et & LBC_TYPE_OPTIONAL_BIT) ? "?" : ""; - formatAppend(result, "%s%s", getBaseTypeString(et), optional); - - if (i + 1 != numparams) - formatAppend(result, ", "); - } - - formatAppend(result, ")\n"); - } - - return result; -} - -void BytecodeBuilder::annotateInstruction(std::string& result, uint32_t fid, uint32_t instpos) const -{ - if ((dumpFlags & Dump_Code) == 0) - return; - - LUAU_ASSERT(fid < functions.size()); - - const Function& function = functions[fid]; - const std::string& dump = function.dump; - const std::vector& dumpinstoffs = function.dumpinstoffs; - - uint32_t next = instpos + 1; - - LUAU_ASSERT(next < dumpinstoffs.size()); - - // Skip locations of multi-dword instructions - while (next < dumpinstoffs.size() && dumpinstoffs[next] == -1) - next++; - - formatAppend(result, "%.*s", dumpinstoffs[next] - dumpinstoffs[instpos], dump.data() + dumpinstoffs[instpos]); -} - -} // namespace Luau diff --git a/lib/luau/Compiler/src/Compiler.cpp b/lib/luau/Compiler/src/Compiler.cpp deleted file mode 100644 index 4363a74..0000000 --- a/lib/luau/Compiler/src/Compiler.cpp +++ /dev/null @@ -1,4103 +0,0 @@ -// This file is part of the Luau programming language and is licensed under MIT License; see LICENSE.txt for details -#include "Luau/Compiler.h" - -#include "Luau/Parser.h" -#include "Luau/BytecodeBuilder.h" -#include "Luau/Common.h" -#include "Luau/TimeTrace.h" - -#include "Builtins.h" -#include "ConstantFolding.h" -#include "CostModel.h" -#include "TableShape.h" -#include "Types.h" -#include "ValueTracking.h" - -#include -#include -#include - -#include - -LUAU_FASTINTVARIABLE(LuauCompileLoopUnrollThreshold, 25) -LUAU_FASTINTVARIABLE(LuauCompileLoopUnrollThresholdMaxBoost, 300) - -LUAU_FASTINTVARIABLE(LuauCompileInlineThreshold, 25) -LUAU_FASTINTVARIABLE(LuauCompileInlineThresholdMaxBoost, 300) -LUAU_FASTINTVARIABLE(LuauCompileInlineDepth, 5) - -LUAU_FASTFLAGVARIABLE(LuauCompileRevK, false) - -namespace Luau -{ - -using namespace Luau::Compile; - -static const uint32_t kMaxRegisterCount = 255; -static const uint32_t kMaxUpvalueCount = 200; -static const uint32_t kMaxLocalCount = 200; -static const uint32_t kMaxInstructionCount = 1'000'000'000; - -static const uint8_t kInvalidReg = 255; - -CompileError::CompileError(const Location& location, const std::string& message) - : location(location) - , message(message) -{ -} - -CompileError::~CompileError() throw() {} - -const char* CompileError::what() const throw() -{ - return message.c_str(); -} - -const Location& CompileError::getLocation() const -{ - return location; -} - -// NOINLINE is used to limit the stack cost of this function due to std::string object / exception plumbing -LUAU_NOINLINE void CompileError::raise(const Location& location, const char* format, ...) -{ - va_list args; - va_start(args, format); - std::string message = vformat(format, args); - va_end(args); - - throw CompileError(location, message); -} - -static BytecodeBuilder::StringRef sref(AstName name) -{ - LUAU_ASSERT(name.value); - return {name.value, strlen(name.value)}; -} - -static BytecodeBuilder::StringRef sref(AstArray data) -{ - LUAU_ASSERT(data.data); - return {data.data, data.size}; -} - -static BytecodeBuilder::StringRef sref(AstArray data) -{ - LUAU_ASSERT(data.data); - return {data.data, data.size}; -} - -struct Compiler -{ - struct RegScope; - - Compiler(BytecodeBuilder& bytecode, const CompileOptions& options) - : bytecode(bytecode) - , options(options) - , functions(nullptr) - , locals(nullptr) - , globals(AstName()) - , variables(nullptr) - , constants(nullptr) - , locstants(nullptr) - , tableShapes(nullptr) - , builtins(nullptr) - , typeMap(nullptr) - { - // preallocate some buffers that are very likely to grow anyway; this works around std::vector's inefficient growth policy for small arrays - localStack.reserve(16); - upvals.reserve(16); - } - - int getLocalReg(AstLocal* local) - { - Local* l = locals.find(local); - - return l && l->allocated ? l->reg : -1; - } - - uint8_t getUpval(AstLocal* local) - { - for (size_t uid = 0; uid < upvals.size(); ++uid) - if (upvals[uid] == local) - return uint8_t(uid); - - if (upvals.size() >= kMaxUpvalueCount) - CompileError::raise( - local->location, "Out of upvalue registers when trying to allocate %s: exceeded limit %d", local->name.value, kMaxUpvalueCount); - - // mark local as captured so that closeLocals emits LOP_CLOSEUPVALS accordingly - Variable* v = variables.find(local); - - if (v && v->written) - locals[local].captured = true; - - upvals.push_back(local); - - return uint8_t(upvals.size() - 1); - } - - // true iff all execution paths through node subtree result in return/break/continue - // note: because this function doesn't visit loop nodes, it (correctly) only detects break/continue that refer to the outer control flow - bool alwaysTerminates(AstStat* node) - { - if (AstStatBlock* stat = node->as()) - return stat->body.size > 0 && alwaysTerminates(stat->body.data[stat->body.size - 1]); - else if (node->is()) - return true; - else if (node->is() || node->is()) - return true; - else if (AstStatIf* stat = node->as()) - return stat->elsebody && alwaysTerminates(stat->thenbody) && alwaysTerminates(stat->elsebody); - else - return false; - } - - void emitLoadK(uint8_t target, int32_t cid) - { - LUAU_ASSERT(cid >= 0); - - if (cid < 32768) - { - bytecode.emitAD(LOP_LOADK, target, int16_t(cid)); - } - else - { - bytecode.emitAD(LOP_LOADKX, target, 0); - bytecode.emitAux(cid); - } - } - - AstExprFunction* getFunctionExpr(AstExpr* node) - { - if (AstExprLocal* expr = node->as()) - { - Variable* lv = variables.find(expr->local); - - if (!lv || lv->written || !lv->init) - return nullptr; - - return getFunctionExpr(lv->init); - } - else if (AstExprGroup* expr = node->as()) - return getFunctionExpr(expr->expr); - else if (AstExprTypeAssertion* expr = node->as()) - return getFunctionExpr(expr->expr); - else - return node->as(); - } - - uint32_t compileFunction(AstExprFunction* func, uint8_t protoflags) - { - LUAU_TIMETRACE_SCOPE("Compiler::compileFunction", "Compiler"); - - if (func->debugname.value) - LUAU_TIMETRACE_ARGUMENT("name", func->debugname.value); - - LUAU_ASSERT(!functions.contains(func)); - LUAU_ASSERT(regTop == 0 && stackSize == 0 && localStack.empty() && upvals.empty()); - - RegScope rs(this); - - bool self = func->self != 0; - uint32_t fid = bytecode.beginFunction(uint8_t(self + func->args.size), func->vararg); - - setDebugLine(func); - - // note: we move types out of typeMap which is safe because compileFunction is only called once per function - if (std::string* funcType = typeMap.find(func)) - bytecode.setFunctionTypeInfo(std::move(*funcType)); - - if (func->vararg) - bytecode.emitABC(LOP_PREPVARARGS, uint8_t(self + func->args.size), 0, 0); - - uint8_t args = allocReg(func, self + unsigned(func->args.size)); - - if (func->self) - pushLocal(func->self, args); - - for (size_t i = 0; i < func->args.size; ++i) - pushLocal(func->args.data[i], uint8_t(args + self + i)); - - AstStatBlock* stat = func->body; - - for (size_t i = 0; i < stat->body.size; ++i) - compileStat(stat->body.data[i]); - - // valid function bytecode must always end with RETURN - // we elide this if we're guaranteed to hit a RETURN statement regardless of the control flow - if (!alwaysTerminates(stat)) - { - setDebugLineEnd(stat); - closeLocals(0); - - bytecode.emitABC(LOP_RETURN, 0, 1, 0); - } - - // constant folding may remove some upvalue refs from bytecode, so this puts them back - if (options.optimizationLevel >= 1 && options.debugLevel >= 2) - gatherConstUpvals(func); - - bytecode.setDebugFunctionLineDefined(func->location.begin.line + 1); - - if (options.debugLevel >= 1 && func->debugname.value) - bytecode.setDebugFunctionName(sref(func->debugname)); - - if (options.debugLevel >= 2 && !upvals.empty()) - { - for (AstLocal* l : upvals) - bytecode.pushDebugUpval(sref(l->name)); - } - - if (options.optimizationLevel >= 1) - bytecode.foldJumps(); - - bytecode.expandJumps(); - - popLocals(0); - - if (bytecode.getInstructionCount() > kMaxInstructionCount) - CompileError::raise(func->location, "Exceeded function instruction limit; split the function into parts to compile"); - - // top-level code only executes once so it can be marked as cold if it has no loops; code with loops might be profitable to compile natively - if (func->functionDepth == 0 && !hasLoops) - protoflags |= LPF_NATIVE_COLD; - - bytecode.endFunction(uint8_t(stackSize), uint8_t(upvals.size()), protoflags); - - Function& f = functions[func]; - f.id = fid; - f.upvals = upvals; - - // record information for inlining - if (options.optimizationLevel >= 2 && !func->vararg && !func->self && !getfenvUsed && !setfenvUsed) - { - f.canInline = true; - f.stackSize = stackSize; - f.costModel = modelCost(func->body, func->args.data, func->args.size, builtins); - - // track functions that only ever return a single value so that we can convert multret calls to fixedret calls - if (alwaysTerminates(func->body)) - { - ReturnVisitor returnVisitor(this); - stat->visit(&returnVisitor); - f.returnsOne = returnVisitor.returnsOne; - } - } - - upvals.clear(); // note: instead of std::move above, we copy & clear to preserve capacity for future pushes - stackSize = 0; - hasLoops = false; - - return fid; - } - - // returns true if node can return multiple values; may conservatively return true even if expr is known to return just a single value - bool isExprMultRet(AstExpr* node) - { - AstExprCall* expr = node->as(); - if (!expr) - return node->is(); - - // conservative version, optimized for compilation throughput - if (options.optimizationLevel <= 1) - return true; - - // handles builtin calls that can be constant-folded - // without this we may omit some optimizations eg compiling fast calls without use of FASTCALL2K - if (isConstant(expr)) - return false; - - // handles builtin calls that can't be constant-folded but are known to return one value - // note: optimizationLevel check is technically redundant but it's important that we never optimize based on builtins in O1 - if (options.optimizationLevel >= 2) - if (int* bfid = builtins.find(expr)) - return getBuiltinInfo(*bfid).results != 1; - - // handles local function calls where we know only one argument is returned - AstExprFunction* func = getFunctionExpr(expr->func); - Function* fi = func ? functions.find(func) : nullptr; - - if (fi && fi->returnsOne) - return false; - - // unrecognized call, so we conservatively assume multret - return true; - } - - // note: this doesn't just clobber target (assuming it's temp), but also clobbers *all* allocated registers >= target! - // this is important to be able to support "multret" semantics due to Lua call frame structure - bool compileExprTempMultRet(AstExpr* node, uint8_t target) - { - if (AstExprCall* expr = node->as()) - { - // Optimization: convert multret calls that always return one value to fixedret calls; this facilitates inlining/constant folding - if (options.optimizationLevel >= 2 && !isExprMultRet(node)) - { - compileExprTemp(node, target); - return false; - } - - // We temporarily swap out regTop to have targetTop work correctly... - // This is a crude hack but it's necessary for correctness :( - RegScope rs(this, target); - compileExprCall(expr, target, /* targetCount= */ 0, /* targetTop= */ true, /* multRet= */ true); - return true; - } - else if (AstExprVarargs* expr = node->as()) - { - // We temporarily swap out regTop to have targetTop work correctly... - // This is a crude hack but it's necessary for correctness :( - RegScope rs(this, target); - compileExprVarargs(expr, target, /* targetCount= */ 0, /* multRet= */ true); - return true; - } - else - { - compileExprTemp(node, target); - return false; - } - } - - // note: this doesn't just clobber target (assuming it's temp), but also clobbers *all* allocated registers >= target! - // this is important to be able to emit code that takes fewer registers and runs faster - void compileExprTempTop(AstExpr* node, uint8_t target) - { - // We temporarily swap out regTop to have targetTop work correctly... - // This is a crude hack but it's necessary for performance :( - // It makes sure that nested call expressions can use targetTop optimization and don't need to have too many registers - RegScope rs(this, target + 1); - compileExprTemp(node, target); - } - - void compileExprVarargs(AstExprVarargs* expr, uint8_t target, uint8_t targetCount, bool multRet = false) - { - LUAU_ASSERT(!multRet || unsigned(target + targetCount) == regTop); - - setDebugLine(expr); // normally compileExpr sets up line info, but compileExprVarargs can be called directly - - bytecode.emitABC(LOP_GETVARARGS, target, multRet ? 0 : uint8_t(targetCount + 1), 0); - } - - void compileExprSelectVararg(AstExprCall* expr, uint8_t target, uint8_t targetCount, bool targetTop, bool multRet, uint8_t regs) - { - LUAU_ASSERT(targetCount == 1); - LUAU_ASSERT(!expr->self); - LUAU_ASSERT(expr->args.size == 2 && expr->args.data[1]->is()); - - AstExpr* arg = expr->args.data[0]; - - uint8_t argreg; - - if (int reg = getExprLocalReg(arg); reg >= 0) - argreg = uint8_t(reg); - else - { - argreg = uint8_t(regs + 1); - compileExprTempTop(arg, argreg); - } - - size_t fastcallLabel = bytecode.emitLabel(); - - bytecode.emitABC(LOP_FASTCALL1, LBF_SELECT_VARARG, argreg, 0); - - // note, these instructions are normally not executed and are used as a fallback for FASTCALL - // we can't use TempTop variant here because we need to make sure the arguments we already computed aren't overwritten - compileExprTemp(expr->func, regs); - - if (argreg != regs + 1) - bytecode.emitABC(LOP_MOVE, uint8_t(regs + 1), argreg, 0); - - bytecode.emitABC(LOP_GETVARARGS, uint8_t(regs + 2), 0, 0); - - size_t callLabel = bytecode.emitLabel(); - if (!bytecode.patchSkipC(fastcallLabel, callLabel)) - CompileError::raise(expr->func->location, "Exceeded jump distance limit; simplify the code to compile"); - - // note, this is always multCall (last argument is variadic) - bytecode.emitABC(LOP_CALL, regs, 0, multRet ? 0 : uint8_t(targetCount + 1)); - - // if we didn't output results directly to target, we need to move them - if (!targetTop) - { - for (size_t i = 0; i < targetCount; ++i) - bytecode.emitABC(LOP_MOVE, uint8_t(target + i), uint8_t(regs + i), 0); - } - } - - void compileExprFastcallN( - AstExprCall* expr, uint8_t target, uint8_t targetCount, bool targetTop, bool multRet, uint8_t regs, int bfid, int bfK = -1) - { - LUAU_ASSERT(!expr->self); - LUAU_ASSERT(expr->args.size >= 1); - LUAU_ASSERT(expr->args.size <= 2 || (bfid == LBF_BIT32_EXTRACTK && expr->args.size == 3)); - LUAU_ASSERT(bfid == LBF_BIT32_EXTRACTK ? bfK >= 0 : bfK < 0); - - LuauOpcode opc = expr->args.size == 1 ? LOP_FASTCALL1 : (bfK >= 0 || isConstant(expr->args.data[1])) ? LOP_FASTCALL2K : LOP_FASTCALL2; - - uint32_t args[3] = {}; - - for (size_t i = 0; i < expr->args.size; ++i) - { - if (i > 0 && opc == LOP_FASTCALL2K) - { - int32_t cid = getConstantIndex(expr->args.data[i]); - if (cid < 0) - CompileError::raise(expr->location, "Exceeded constant limit; simplify the code to compile"); - - args[i] = cid; - } - else if (int reg = getExprLocalReg(expr->args.data[i]); reg >= 0) - { - args[i] = uint8_t(reg); - } - else - { - args[i] = uint8_t(regs + 1 + i); - compileExprTempTop(expr->args.data[i], uint8_t(args[i])); - } - } - - size_t fastcallLabel = bytecode.emitLabel(); - - bytecode.emitABC(opc, uint8_t(bfid), uint8_t(args[0]), 0); - if (opc != LOP_FASTCALL1) - bytecode.emitAux(bfK >= 0 ? bfK : args[1]); - - // Set up a traditional Lua stack for the subsequent LOP_CALL. - // Note, as with other instructions that immediately follow FASTCALL, these are normally not executed and are used as a fallback for - // these FASTCALL variants. - for (size_t i = 0; i < expr->args.size; ++i) - { - if (i > 0 && opc == LOP_FASTCALL2K) - emitLoadK(uint8_t(regs + 1 + i), args[i]); - else if (args[i] != regs + 1 + i) - bytecode.emitABC(LOP_MOVE, uint8_t(regs + 1 + i), uint8_t(args[i]), 0); - } - - // note, these instructions are normally not executed and are used as a fallback for FASTCALL - // we can't use TempTop variant here because we need to make sure the arguments we already computed aren't overwritten - compileExprTemp(expr->func, regs); - - size_t callLabel = bytecode.emitLabel(); - - // FASTCALL will skip over the instructions needed to compute function and jump over CALL which must immediately follow the instruction - // sequence after FASTCALL - if (!bytecode.patchSkipC(fastcallLabel, callLabel)) - CompileError::raise(expr->func->location, "Exceeded jump distance limit; simplify the code to compile"); - - bytecode.emitABC(LOP_CALL, regs, uint8_t(expr->args.size + 1), multRet ? 0 : uint8_t(targetCount + 1)); - - // if we didn't output results directly to target, we need to move them - if (!targetTop) - { - for (size_t i = 0; i < targetCount; ++i) - bytecode.emitABC(LOP_MOVE, uint8_t(target + i), uint8_t(regs + i), 0); - } - } - - bool tryCompileInlinedCall(AstExprCall* expr, AstExprFunction* func, uint8_t target, uint8_t targetCount, bool multRet, int thresholdBase, - int thresholdMaxBoost, int depthLimit) - { - Function* fi = functions.find(func); - LUAU_ASSERT(fi); - - // make sure we have enough register space - if (regTop > 128 || fi->stackSize > 32) - { - bytecode.addDebugRemark("inlining failed: high register pressure"); - return false; - } - - // we should ideally aggregate the costs during recursive inlining, but for now simply limit the depth - if (int(inlineFrames.size()) >= depthLimit) - { - bytecode.addDebugRemark("inlining failed: too many inlined frames"); - return false; - } - - // compiling recursive inlining is difficult because we share constant/variable state but need to bind variables to different registers - for (InlineFrame& frame : inlineFrames) - if (frame.func == func) - { - bytecode.addDebugRemark("inlining failed: can't inline recursive calls"); - return false; - } - - // we can't inline multret functions because the caller expects L->top to be adjusted: - // - inlined return compiles to a JUMP, and we don't have an instruction that adjusts L->top arbitrarily - // - even if we did, right now all L->top adjustments are immediately consumed by the next instruction, and for now we want to preserve that - // - additionally, we can't easily compile multret expressions into designated target as computed call arguments will get clobbered - if (multRet) - { - bytecode.addDebugRemark("inlining failed: can't convert fixed returns to multret"); - return false; - } - - // compute constant bitvector for all arguments to feed the cost model - bool varc[8] = {}; - for (size_t i = 0; i < func->args.size && i < expr->args.size && i < 8; ++i) - varc[i] = isConstant(expr->args.data[i]); - - // if the last argument only returns a single value, all following arguments are nil - if (expr->args.size != 0 && !isExprMultRet(expr->args.data[expr->args.size - 1])) - for (size_t i = expr->args.size; i < func->args.size && i < 8; ++i) - varc[i] = true; - - // we use a dynamic cost threshold that's based on the fixed limit boosted by the cost advantage we gain due to inlining - int inlinedCost = computeCost(fi->costModel, varc, std::min(int(func->args.size), 8)); - int baselineCost = computeCost(fi->costModel, nullptr, 0) + 3; - int inlineProfit = (inlinedCost == 0) ? thresholdMaxBoost : std::min(thresholdMaxBoost, 100 * baselineCost / inlinedCost); - - int threshold = thresholdBase * inlineProfit / 100; - - if (inlinedCost > threshold) - { - bytecode.addDebugRemark("inlining failed: too expensive (cost %d, profit %.2fx)", inlinedCost, double(inlineProfit) / 100); - return false; - } - - bytecode.addDebugRemark( - "inlining succeeded (cost %d, profit %.2fx, depth %d)", inlinedCost, double(inlineProfit) / 100, int(inlineFrames.size())); - - compileInlinedCall(expr, func, target, targetCount); - return true; - } - - void compileInlinedCall(AstExprCall* expr, AstExprFunction* func, uint8_t target, uint8_t targetCount) - { - RegScope rs(this); - - size_t oldLocals = localStack.size(); - - std::vector args; - args.reserve(func->args.size); - - // evaluate all arguments; note that we don't emit code for constant arguments (relying on constant folding) - // note that compiler state (variable registers/values) does not change here - we defer that to a separate loop below to handle nested calls - for (size_t i = 0; i < func->args.size; ++i) - { - AstLocal* var = func->args.data[i]; - AstExpr* arg = i < expr->args.size ? expr->args.data[i] : nullptr; - - if (i + 1 == expr->args.size && func->args.size > expr->args.size && isExprMultRet(arg)) - { - // if the last argument can return multiple values, we need to compute all of them into the remaining arguments - unsigned int tail = unsigned(func->args.size - expr->args.size) + 1; - uint8_t reg = allocReg(arg, tail); - - if (AstExprCall* expr = arg->as()) - compileExprCall(expr, reg, tail, /* targetTop= */ true); - else if (AstExprVarargs* expr = arg->as()) - compileExprVarargs(expr, reg, tail); - else - LUAU_ASSERT(!"Unexpected expression type"); - - for (size_t j = i; j < func->args.size; ++j) - args.push_back({func->args.data[j], uint8_t(reg + (j - i))}); - - // all remaining function arguments have been allocated and assigned to - break; - } - else if (Variable* vv = variables.find(var); vv && vv->written) - { - // if the argument is mutated, we need to allocate a fresh register even if it's a constant - uint8_t reg = allocReg(arg, 1); - - if (arg) - compileExprTemp(arg, reg); - else - bytecode.emitABC(LOP_LOADNIL, reg, 0, 0); - - args.push_back({var, reg}); - } - else if (arg == nullptr) - { - // since the argument is not mutated, we can simply fold the value into the expressions that need it - args.push_back({var, kInvalidReg, {Constant::Type_Nil}}); - } - else if (const Constant* cv = constants.find(arg); cv && cv->type != Constant::Type_Unknown) - { - // since the argument is not mutated, we can simply fold the value into the expressions that need it - args.push_back({var, kInvalidReg, *cv}); - } - else - { - AstExprLocal* le = getExprLocal(arg); - Variable* lv = le ? variables.find(le->local) : nullptr; - - // if the argument is a local that isn't mutated, we will simply reuse the existing register - if (int reg = le ? getExprLocalReg(le) : -1; reg >= 0 && (!lv || !lv->written)) - { - args.push_back({var, uint8_t(reg)}); - } - else - { - uint8_t temp = allocReg(arg, 1); - compileExprTemp(arg, temp); - - args.push_back({var, temp}); - } - } - } - - // evaluate extra expressions for side effects - for (size_t i = func->args.size; i < expr->args.size; ++i) - compileExprSide(expr->args.data[i]); - - // apply all evaluated arguments to the compiler state - // note: locals use current startpc for debug info, although some of them have been computed earlier; this is similar to compileStatLocal - for (InlineArg& arg : args) - { - if (arg.value.type == Constant::Type_Unknown) - { - pushLocal(arg.local, arg.reg); - } - else - { - locstants[arg.local] = arg.value; - } - } - - // the inline frame will be used to compile return statements as well as to reject recursive inlining attempts - inlineFrames.push_back({func, oldLocals, target, targetCount}); - - // fold constant values updated above into expressions in the function body - foldConstants(constants, variables, locstants, builtinsFold, builtinsFoldMathK, func->body); - - bool usedFallthrough = false; - - for (size_t i = 0; i < func->body->body.size; ++i) - { - AstStat* stat = func->body->body.data[i]; - - if (AstStatReturn* ret = stat->as()) - { - // Optimization: use fallthrough when compiling return at the end of the function to avoid an extra JUMP - compileInlineReturn(ret, /* fallthrough= */ true); - // TODO: This doesn't work when return is part of control flow; ideally we would track the state somehow and generalize this - usedFallthrough = true; - break; - } - else - compileStat(stat); - } - - // for the fallthrough path we need to ensure we clear out target registers - if (!usedFallthrough && !alwaysTerminates(func->body)) - { - for (size_t i = 0; i < targetCount; ++i) - bytecode.emitABC(LOP_LOADNIL, uint8_t(target + i), 0, 0); - - closeLocals(oldLocals); - } - - popLocals(oldLocals); - - size_t returnLabel = bytecode.emitLabel(); - patchJumps(expr, inlineFrames.back().returnJumps, returnLabel); - - inlineFrames.pop_back(); - - // clean up constant state for future inlining attempts - for (size_t i = 0; i < func->args.size; ++i) - { - AstLocal* local = func->args.data[i]; - - if (Constant* var = locstants.find(local)) - var->type = Constant::Type_Unknown; - } - - foldConstants(constants, variables, locstants, builtinsFold, builtinsFoldMathK, func->body); - } - - void compileExprCall(AstExprCall* expr, uint8_t target, uint8_t targetCount, bool targetTop = false, bool multRet = false) - { - LUAU_ASSERT(!targetTop || unsigned(target + targetCount) == regTop); - - setDebugLine(expr); // normally compileExpr sets up line info, but compileExprCall can be called directly - - // try inlining the function - if (options.optimizationLevel >= 2 && !expr->self) - { - AstExprFunction* func = getFunctionExpr(expr->func); - Function* fi = func ? functions.find(func) : nullptr; - - if (fi && fi->canInline && - tryCompileInlinedCall(expr, func, target, targetCount, multRet, FInt::LuauCompileInlineThreshold, - FInt::LuauCompileInlineThresholdMaxBoost, FInt::LuauCompileInlineDepth)) - return; - - // add a debug remark for cases when we didn't even call tryCompileInlinedCall - if (func && !(fi && fi->canInline)) - { - if (func->vararg) - bytecode.addDebugRemark("inlining failed: function is variadic"); - else if (!fi) - bytecode.addDebugRemark("inlining failed: can't inline recursive calls"); - else if (getfenvUsed || setfenvUsed) - bytecode.addDebugRemark("inlining failed: module uses getfenv/setfenv"); - } - } - - RegScope rs(this); - - unsigned int regCount = std::max(unsigned(1 + expr->self + expr->args.size), unsigned(targetCount)); - - // Optimization: if target points to the top of the stack, we can start the call at oldTop - 1 and won't need MOVE at the end - uint8_t regs = targetTop ? allocReg(expr, regCount - targetCount) - targetCount : allocReg(expr, regCount); - - uint8_t selfreg = 0; - - int bfid = -1; - - if (options.optimizationLevel >= 1 && !expr->self) - if (const int* id = builtins.find(expr)) - bfid = *id; - - if (bfid >= 0 && bytecode.needsDebugRemarks()) - { - Builtin builtin = getBuiltin(expr->func, globals, variables); - bool lastMult = expr->args.size > 0 && isExprMultRet(expr->args.data[expr->args.size - 1]); - - if (builtin.object.value) - bytecode.addDebugRemark("builtin %s.%s/%d%s", builtin.object.value, builtin.method.value, int(expr->args.size), lastMult ? "+" : ""); - else if (builtin.method.value) - bytecode.addDebugRemark("builtin %s/%d%s", builtin.method.value, int(expr->args.size), lastMult ? "+" : ""); - } - - if (bfid == LBF_SELECT_VARARG) - { - // Optimization: compile select(_, ...) as FASTCALL1; the builtin will read variadic arguments directly - // note: for now we restrict this to single-return expressions since our runtime code doesn't deal with general cases - if (multRet == false && targetCount == 1) - return compileExprSelectVararg(expr, target, targetCount, targetTop, multRet, regs); - else - bfid = -1; - } - - // Optimization: for bit32.extract with constant in-range f/w we compile using FASTCALL2K and a special builtin - if (bfid == LBF_BIT32_EXTRACT && expr->args.size == 3 && isConstant(expr->args.data[1]) && isConstant(expr->args.data[2])) - { - Constant fc = getConstant(expr->args.data[1]); - Constant wc = getConstant(expr->args.data[2]); - - int fi = fc.type == Constant::Type_Number ? int(fc.valueNumber) : -1; - int wi = wc.type == Constant::Type_Number ? int(wc.valueNumber) : -1; - - if (fi >= 0 && wi > 0 && fi + wi <= 32) - { - int fwp = fi | ((wi - 1) << 5); - int32_t cid = bytecode.addConstantNumber(fwp); - if (cid < 0) - CompileError::raise(expr->location, "Exceeded constant limit; simplify the code to compile"); - - return compileExprFastcallN(expr, target, targetCount, targetTop, multRet, regs, LBF_BIT32_EXTRACTK, cid); - } - } - - // Optimization: for 1/2 argument fast calls use specialized opcodes - if (bfid >= 0 && expr->args.size >= 1 && expr->args.size <= 2) - { - if (!isExprMultRet(expr->args.data[expr->args.size - 1])) - return compileExprFastcallN(expr, target, targetCount, targetTop, multRet, regs, bfid); - else if (options.optimizationLevel >= 2) - { - // when a builtin is none-safe with matching arity, even if the last expression returns 0 or >1 arguments, - // we can rely on the behavior of the function being the same (none-safe means nil and none are interchangeable) - BuiltinInfo info = getBuiltinInfo(bfid); - if (int(expr->args.size) == info.params && (info.flags & BuiltinInfo::Flag_NoneSafe) != 0) - return compileExprFastcallN(expr, target, targetCount, targetTop, multRet, regs, bfid); - } - } - - if (expr->self) - { - AstExprIndexName* fi = expr->func->as(); - LUAU_ASSERT(fi); - - // Optimization: use local register directly in NAMECALL if possible - if (int reg = getExprLocalReg(fi->expr); reg >= 0) - { - selfreg = uint8_t(reg); - } - else - { - // Note: to be able to compile very deeply nested self call chains (obj:method1():method2():...), we need to be able to do this in - // finite stack space NAMECALL will happily move object from regs to regs+1 but we need to compute it into regs so that - // compileExprTempTop doesn't increase stack usage for every recursive call - selfreg = regs; - - compileExprTempTop(fi->expr, selfreg); - } - } - else if (bfid < 0) - { - compileExprTempTop(expr->func, regs); - } - - bool multCall = false; - - for (size_t i = 0; i < expr->args.size; ++i) - if (i + 1 == expr->args.size) - multCall = compileExprTempMultRet(expr->args.data[i], uint8_t(regs + 1 + expr->self + i)); - else - compileExprTempTop(expr->args.data[i], uint8_t(regs + 1 + expr->self + i)); - - setDebugLineEnd(expr->func); - - if (expr->self) - { - AstExprIndexName* fi = expr->func->as(); - LUAU_ASSERT(fi); - - setDebugLine(fi->indexLocation); - - BytecodeBuilder::StringRef iname = sref(fi->index); - int32_t cid = bytecode.addConstantString(iname); - if (cid < 0) - CompileError::raise(fi->location, "Exceeded constant limit; simplify the code to compile"); - - bytecode.emitABC(LOP_NAMECALL, regs, selfreg, uint8_t(BytecodeBuilder::getStringHash(iname))); - bytecode.emitAux(cid); - } - else if (bfid >= 0) - { - size_t fastcallLabel = bytecode.emitLabel(); - bytecode.emitABC(LOP_FASTCALL, uint8_t(bfid), 0, 0); - - // note, these instructions are normally not executed and are used as a fallback for FASTCALL - // we can't use TempTop variant here because we need to make sure the arguments we already computed aren't overwritten - compileExprTemp(expr->func, regs); - - size_t callLabel = bytecode.emitLabel(); - - // FASTCALL will skip over the instructions needed to compute function and jump over CALL which must immediately follow the instruction - // sequence after FASTCALL - if (!bytecode.patchSkipC(fastcallLabel, callLabel)) - CompileError::raise(expr->func->location, "Exceeded jump distance limit; simplify the code to compile"); - } - - bytecode.emitABC(LOP_CALL, regs, multCall ? 0 : uint8_t(expr->self + expr->args.size + 1), multRet ? 0 : uint8_t(targetCount + 1)); - - // if we didn't output results directly to target, we need to move them - if (!targetTop) - { - for (size_t i = 0; i < targetCount; ++i) - bytecode.emitABC(LOP_MOVE, uint8_t(target + i), uint8_t(regs + i), 0); - } - } - - bool shouldShareClosure(AstExprFunction* func) - { - const Function* f = functions.find(func); - if (!f) - return false; - - for (AstLocal* uv : f->upvals) - { - Variable* ul = variables.find(uv); - - if (!ul) - return false; - - if (ul->written) - return false; - - // it's technically safe to share closures whenever all upvalues are immutable - // this is because of a runtime equality check in DUPCLOSURE. - // however, this results in frequent deoptimization and increases the set of reachable objects, making some temporary objects permanent - // instead we apply a heuristic: we share closures if they refer to top-level upvalues, or closures that refer to top-level upvalues - // this will only deoptimize (outside of fenv changes) if top level code is executed twice with different results. - if (uv->functionDepth != 0 || uv->loopDepth != 0) - { - AstExprFunction* uf = ul->init ? ul->init->as() : nullptr; - if (!uf) - return false; - - if (uf != func && !shouldShareClosure(uf)) - return false; - } - } - - return true; - } - - void compileExprFunction(AstExprFunction* expr, uint8_t target) - { - RegScope rs(this); - - const Function* f = functions.find(expr); - LUAU_ASSERT(f); - - // when the closure has upvalues we'll use this to create the closure at runtime - // when the closure has no upvalues, we use constant closures that technically don't rely on the child function list - // however, it's still important to add the child function because debugger relies on the function hierarchy when setting breakpoints - int16_t pid = bytecode.addChildFunction(f->id); - if (pid < 0) - CompileError::raise(expr->location, "Exceeded closure limit; simplify the code to compile"); - - // we use a scratch vector to reduce allocations; this is safe since compileExprFunction is not reentrant - captures.clear(); - captures.reserve(f->upvals.size()); - - for (AstLocal* uv : f->upvals) - { - LUAU_ASSERT(uv->functionDepth < expr->functionDepth); - - if (int reg = getLocalReg(uv); reg >= 0) - { - // note: we can't check if uv is an upvalue in the current frame because inlining can migrate from upvalues to locals - Variable* ul = variables.find(uv); - bool immutable = !ul || !ul->written; - - captures.push_back({immutable ? LCT_VAL : LCT_REF, uint8_t(reg)}); - } - else if (const Constant* uc = locstants.find(uv); uc && uc->type != Constant::Type_Unknown) - { - // inlining can result in an upvalue capture of a constant, in which case we can't capture without a temporary register - uint8_t reg = allocReg(expr, 1); - compileExprConstant(expr, uc, reg); - - captures.push_back({LCT_VAL, reg}); - } - else - { - LUAU_ASSERT(uv->functionDepth < expr->functionDepth - 1); - - // get upvalue from parent frame - // note: this will add uv to the current upvalue list if necessary - uint8_t uid = getUpval(uv); - - captures.push_back({LCT_UPVAL, uid}); - } - } - - // Optimization: when closure has no upvalues, or upvalues are safe to share, instead of allocating it every time we can share closure - // objects (this breaks assumptions about function identity which can lead to setfenv not working as expected, so we disable this when it - // is used) - int16_t shared = -1; - - if (options.optimizationLevel >= 1 && shouldShareClosure(expr) && !setfenvUsed) - { - int32_t cid = bytecode.addConstantClosure(f->id); - - if (cid >= 0 && cid < 32768) - shared = int16_t(cid); - } - - if (shared < 0) - bytecode.addDebugRemark("allocation: closure with %d upvalues", int(captures.size())); - - if (shared >= 0) - bytecode.emitAD(LOP_DUPCLOSURE, target, shared); - else - bytecode.emitAD(LOP_NEWCLOSURE, target, pid); - - for (const Capture& c : captures) - bytecode.emitABC(LOP_CAPTURE, uint8_t(c.type), c.data, 0); - } - - LuauOpcode getUnaryOp(AstExprUnary::Op op) - { - switch (op) - { - case AstExprUnary::Not: - return LOP_NOT; - - case AstExprUnary::Minus: - return LOP_MINUS; - - case AstExprUnary::Len: - return LOP_LENGTH; - - default: - LUAU_ASSERT(!"Unexpected unary operation"); - return LOP_NOP; - } - } - - LuauOpcode getBinaryOpArith(AstExprBinary::Op op, bool k = false) - { - switch (op) - { - case AstExprBinary::Add: - return k ? LOP_ADDK : LOP_ADD; - - case AstExprBinary::Sub: - return k ? LOP_SUBK : LOP_SUB; - - case AstExprBinary::Mul: - return k ? LOP_MULK : LOP_MUL; - - case AstExprBinary::Div: - return k ? LOP_DIVK : LOP_DIV; - - case AstExprBinary::FloorDiv: - return k ? LOP_IDIVK : LOP_IDIV; - - case AstExprBinary::Mod: - return k ? LOP_MODK : LOP_MOD; - - case AstExprBinary::Pow: - return k ? LOP_POWK : LOP_POW; - - default: - LUAU_ASSERT(!"Unexpected binary operation"); - return LOP_NOP; - } - } - - LuauOpcode getJumpOpCompare(AstExprBinary::Op op, bool not_ = false) - { - switch (op) - { - case AstExprBinary::CompareNe: - return not_ ? LOP_JUMPIFEQ : LOP_JUMPIFNOTEQ; - - case AstExprBinary::CompareEq: - return not_ ? LOP_JUMPIFNOTEQ : LOP_JUMPIFEQ; - - case AstExprBinary::CompareLt: - case AstExprBinary::CompareGt: - return not_ ? LOP_JUMPIFNOTLT : LOP_JUMPIFLT; - - case AstExprBinary::CompareLe: - case AstExprBinary::CompareGe: - return not_ ? LOP_JUMPIFNOTLE : LOP_JUMPIFLE; - - default: - LUAU_ASSERT(!"Unexpected binary operation"); - return LOP_NOP; - } - } - - bool isConstant(AstExpr* node) - { - const Constant* cv = constants.find(node); - - return cv && cv->type != Constant::Type_Unknown; - } - - bool isConstantTrue(AstExpr* node) - { - const Constant* cv = constants.find(node); - - return cv && cv->type != Constant::Type_Unknown && cv->isTruthful(); - } - - bool isConstantFalse(AstExpr* node) - { - const Constant* cv = constants.find(node); - - return cv && cv->type != Constant::Type_Unknown && !cv->isTruthful(); - } - - bool isConstantVector(AstExpr* node) - { - const Constant* cv = constants.find(node); - - return cv && cv->type == Constant::Type_Vector; - } - - Constant getConstant(AstExpr* node) - { - const Constant* cv = constants.find(node); - - return cv ? *cv : Constant{Constant::Type_Unknown}; - } - - size_t compileCompareJump(AstExprBinary* expr, bool not_ = false) - { - RegScope rs(this); - - bool isEq = (expr->op == AstExprBinary::CompareEq || expr->op == AstExprBinary::CompareNe); - AstExpr* left = expr->left; - AstExpr* right = expr->right; - - bool operandIsConstant = isConstant(right); - if (isEq && !operandIsConstant) - { - operandIsConstant = isConstant(left); - if (operandIsConstant) - std::swap(left, right); - } - - // disable fast path for vectors because supporting it would require a new opcode - if (operandIsConstant && isConstantVector(right)) - operandIsConstant = false; - - uint8_t rl = compileExprAuto(left, rs); - - if (isEq && operandIsConstant) - { - const Constant* cv = constants.find(right); - LUAU_ASSERT(cv && cv->type != Constant::Type_Unknown); - - LuauOpcode opc = LOP_NOP; - int32_t cid = -1; - uint32_t flip = (expr->op == AstExprBinary::CompareEq) == not_ ? 0x80000000 : 0; - - switch (cv->type) - { - case Constant::Type_Nil: - opc = LOP_JUMPXEQKNIL; - cid = 0; - break; - - case Constant::Type_Boolean: - opc = LOP_JUMPXEQKB; - cid = cv->valueBoolean; - break; - - case Constant::Type_Number: - opc = LOP_JUMPXEQKN; - cid = getConstantIndex(right); - break; - - case Constant::Type_String: - opc = LOP_JUMPXEQKS; - cid = getConstantIndex(right); - break; - - default: - LUAU_ASSERT(!"Unexpected constant type"); - } - - if (cid < 0) - CompileError::raise(expr->location, "Exceeded constant limit; simplify the code to compile"); - - size_t jumpLabel = bytecode.emitLabel(); - - bytecode.emitAD(opc, rl, 0); - bytecode.emitAux(cid | flip); - - return jumpLabel; - } - else - { - LuauOpcode opc = getJumpOpCompare(expr->op, not_); - - uint8_t rr = compileExprAuto(right, rs); - - size_t jumpLabel = bytecode.emitLabel(); - - if (expr->op == AstExprBinary::CompareGt || expr->op == AstExprBinary::CompareGe) - { - bytecode.emitAD(opc, rr, 0); - bytecode.emitAux(rl); - } - else - { - bytecode.emitAD(opc, rl, 0); - bytecode.emitAux(rr); - } - - return jumpLabel; - } - } - - int32_t getConstantNumber(AstExpr* node) - { - const Constant* c = constants.find(node); - - if (c && c->type == Constant::Type_Number) - { - int cid = bytecode.addConstantNumber(c->valueNumber); - if (cid < 0) - CompileError::raise(node->location, "Exceeded constant limit; simplify the code to compile"); - - return cid; - } - - return -1; - } - - int32_t getConstantIndex(AstExpr* node) - { - const Constant* c = constants.find(node); - - if (!c || c->type == Constant::Type_Unknown) - return -1; - - int cid = -1; - - switch (c->type) - { - case Constant::Type_Nil: - cid = bytecode.addConstantNil(); - break; - - case Constant::Type_Boolean: - cid = bytecode.addConstantBoolean(c->valueBoolean); - break; - - case Constant::Type_Number: - cid = bytecode.addConstantNumber(c->valueNumber); - break; - - case Constant::Type_Vector: - cid = bytecode.addConstantVector(c->valueVector[0], c->valueVector[1], c->valueVector[2], c->valueVector[3]); - break; - - case Constant::Type_String: - cid = bytecode.addConstantString(sref(c->getString())); - break; - - default: - LUAU_ASSERT(!"Unexpected constant type"); - return -1; - } - - if (cid < 0) - CompileError::raise(node->location, "Exceeded constant limit; simplify the code to compile"); - - return cid; - } - - // compile expr to target temp register - // if the expr (or not expr if onlyTruth is false) is truthy, jump via skipJump - // if the expr (or not expr if onlyTruth is false) is falsy, fall through (target isn't guaranteed to be updated in this case) - // if target is omitted, then the jump behavior is the same - skipJump or fallthrough depending on the truthiness of the expression - void compileConditionValue(AstExpr* node, const uint8_t* target, std::vector& skipJump, bool onlyTruth) - { - // Optimization: we don't need to compute constant values - if (const Constant* cv = constants.find(node); cv && cv->type != Constant::Type_Unknown) - { - // note that we only need to compute the value if it's truthy; otherwise we cal fall through - if (cv->isTruthful() == onlyTruth) - { - if (target) - compileExprTemp(node, *target); - - skipJump.push_back(bytecode.emitLabel()); - bytecode.emitAD(LOP_JUMP, 0, 0); - } - return; - } - - if (AstExprBinary* expr = node->as()) - { - switch (expr->op) - { - case AstExprBinary::And: - case AstExprBinary::Or: - { - // disambiguation: there's 4 cases (we only need truthy or falsy results based on onlyTruth) - // onlyTruth = 1: a and b transforms to a ? b : dontcare - // onlyTruth = 1: a or b transforms to a ? a : b - // onlyTruth = 0: a and b transforms to !a ? a : b - // onlyTruth = 0: a or b transforms to !a ? b : dontcare - if (onlyTruth == (expr->op == AstExprBinary::And)) - { - // we need to compile the left hand side, and skip to "dontcare" (aka fallthrough of the entire statement) if it's not the same as - // onlyTruth if it's the same then the result of the expression is the right hand side because of this, we *never* care about the - // result of the left hand side - std::vector elseJump; - compileConditionValue(expr->left, nullptr, elseJump, !onlyTruth); - - // fallthrough indicates that we need to compute & return the right hand side - // we use compileConditionValue again to process any extra and/or statements directly - compileConditionValue(expr->right, target, skipJump, onlyTruth); - - size_t elseLabel = bytecode.emitLabel(); - - patchJumps(expr, elseJump, elseLabel); - } - else - { - // we need to compute the left hand side first; note that we will jump to skipJump if we know the answer - compileConditionValue(expr->left, target, skipJump, onlyTruth); - - // we will fall through if computing the left hand didn't give us an "interesting" result - // we still use compileConditionValue to recursively optimize any and/or/compare statements - compileConditionValue(expr->right, target, skipJump, onlyTruth); - } - return; - } - break; - - case AstExprBinary::CompareNe: - case AstExprBinary::CompareEq: - case AstExprBinary::CompareLt: - case AstExprBinary::CompareLe: - case AstExprBinary::CompareGt: - case AstExprBinary::CompareGe: - { - if (target) - { - // since target is a temp register, we'll initialize it to 1, and then jump if the comparison is true - // if the comparison is false, we'll fallthrough and target will still be 1 but target has unspecified value for falsy results - // when we only care about falsy values instead of truthy values, the process is the same but with flipped conditionals - bytecode.emitABC(LOP_LOADB, *target, onlyTruth ? 1 : 0, 0); - } - - size_t jumpLabel = compileCompareJump(expr, /* not= */ !onlyTruth); - - skipJump.push_back(jumpLabel); - return; - } - break; - - // fall-through to default path below - default:; - } - } - - if (AstExprUnary* expr = node->as()) - { - // if we *do* need to compute the target, we'd have to inject "not" ops on every return path - // this is possible but cumbersome; so for now we only optimize not expression when we *don't* need the value - if (!target && expr->op == AstExprUnary::Not) - { - compileConditionValue(expr->expr, target, skipJump, !onlyTruth); - return; - } - } - - if (AstExprGroup* expr = node->as()) - { - compileConditionValue(expr->expr, target, skipJump, onlyTruth); - return; - } - - RegScope rs(this); - uint8_t reg; - - if (target) - { - reg = *target; - compileExprTemp(node, reg); - } - else - { - reg = compileExprAuto(node, rs); - } - - skipJump.push_back(bytecode.emitLabel()); - bytecode.emitAD(onlyTruth ? LOP_JUMPIF : LOP_JUMPIFNOT, reg, 0); - } - - // checks if compiling the expression as a condition value generates code that's faster than using compileExpr - bool isConditionFast(AstExpr* node) - { - const Constant* cv = constants.find(node); - - if (cv && cv->type != Constant::Type_Unknown) - return true; - - if (AstExprBinary* expr = node->as()) - { - switch (expr->op) - { - case AstExprBinary::And: - case AstExprBinary::Or: - return true; - - case AstExprBinary::CompareNe: - case AstExprBinary::CompareEq: - case AstExprBinary::CompareLt: - case AstExprBinary::CompareLe: - case AstExprBinary::CompareGt: - case AstExprBinary::CompareGe: - return true; - - default: - return false; - } - } - - if (AstExprGroup* expr = node->as()) - return isConditionFast(expr->expr); - - return false; - } - - void compileExprAndOr(AstExprBinary* expr, uint8_t target, bool targetTemp) - { - bool and_ = (expr->op == AstExprBinary::And); - - RegScope rs(this); - - // Optimization: when left hand side is a constant, we can emit left hand side or right hand side - if (const Constant* cl = constants.find(expr->left); cl && cl->type != Constant::Type_Unknown) - { - compileExpr(and_ == cl->isTruthful() ? expr->right : expr->left, target, targetTemp); - return; - } - - // Note: two optimizations below can lead to inefficient codegen when the left hand side is a condition - if (!isConditionFast(expr->left)) - { - // Optimization: when right hand side is a local variable, we can use AND/OR - if (int reg = getExprLocalReg(expr->right); reg >= 0) - { - uint8_t lr = compileExprAuto(expr->left, rs); - uint8_t rr = uint8_t(reg); - - bytecode.emitABC(and_ ? LOP_AND : LOP_OR, target, lr, rr); - return; - } - - // Optimization: when right hand side is a constant, we can use ANDK/ORK - int32_t cid = getConstantIndex(expr->right); - - if (cid >= 0 && cid <= 255) - { - uint8_t lr = compileExprAuto(expr->left, rs); - - bytecode.emitABC(and_ ? LOP_ANDK : LOP_ORK, target, lr, uint8_t(cid)); - return; - } - } - - // Optimization: if target is a temp register, we can clobber it which allows us to compute the result directly into it - // If it's not a temp register, then something like `a = a > 1 or a + 2` may clobber `a` while evaluating left hand side, and `a+2` will break - uint8_t reg = targetTemp ? target : allocReg(expr, 1); - - std::vector skipJump; - compileConditionValue(expr->left, ®, skipJump, /* onlyTruth= */ !and_); - - compileExprTemp(expr->right, reg); - - size_t moveLabel = bytecode.emitLabel(); - - patchJumps(expr, skipJump, moveLabel); - - if (target != reg) - bytecode.emitABC(LOP_MOVE, target, reg, 0); - } - - void compileExprUnary(AstExprUnary* expr, uint8_t target) - { - RegScope rs(this); - - uint8_t re = compileExprAuto(expr->expr, rs); - - bytecode.emitABC(getUnaryOp(expr->op), target, re, 0); - } - - static void unrollConcats(std::vector& args) - { - for (;;) - { - AstExprBinary* be = args.back()->as(); - - if (!be || be->op != AstExprBinary::Concat) - break; - - args.back() = be->left; - args.push_back(be->right); - } - } - - void compileExprBinary(AstExprBinary* expr, uint8_t target, bool targetTemp) - { - RegScope rs(this); - - switch (expr->op) - { - case AstExprBinary::Add: - case AstExprBinary::Sub: - case AstExprBinary::Mul: - case AstExprBinary::Div: - case AstExprBinary::FloorDiv: - case AstExprBinary::Mod: - case AstExprBinary::Pow: - { - int32_t rc = getConstantNumber(expr->right); - - if (rc >= 0 && rc <= 255) - { - uint8_t rl = compileExprAuto(expr->left, rs); - - bytecode.emitABC(getBinaryOpArith(expr->op, /* k= */ true), target, rl, uint8_t(rc)); - } - else - { - if (FFlag::LuauCompileRevK && (expr->op == AstExprBinary::Sub || expr->op == AstExprBinary::Div)) - { - int32_t lc = getConstantNumber(expr->left); - - if (lc >= 0 && lc <= 255) - { - uint8_t rr = compileExprAuto(expr->right, rs); - LuauOpcode op = (expr->op == AstExprBinary::Sub) ? LOP_SUBRK : LOP_DIVRK; - - bytecode.emitABC(op, target, uint8_t(lc), uint8_t(rr)); - return; - } - } - - uint8_t rl = compileExprAuto(expr->left, rs); - uint8_t rr = compileExprAuto(expr->right, rs); - - bytecode.emitABC(getBinaryOpArith(expr->op), target, rl, rr); - } - } - break; - - case AstExprBinary::Concat: - { - std::vector args = {expr->left, expr->right}; - - // unroll the tree of concats down the right hand side to be able to do multiple ops - unrollConcats(args); - - uint8_t regs = allocReg(expr, unsigned(args.size())); - - for (size_t i = 0; i < args.size(); ++i) - compileExprTemp(args[i], uint8_t(regs + i)); - - bytecode.emitABC(LOP_CONCAT, target, regs, uint8_t(regs + args.size() - 1)); - } - break; - - case AstExprBinary::CompareNe: - case AstExprBinary::CompareEq: - case AstExprBinary::CompareLt: - case AstExprBinary::CompareLe: - case AstExprBinary::CompareGt: - case AstExprBinary::CompareGe: - { - size_t jumpLabel = compileCompareJump(expr); - - // note: this skips over the next LOADB instruction because of "1" in the C slot - bytecode.emitABC(LOP_LOADB, target, 0, 1); - - size_t thenLabel = bytecode.emitLabel(); - - bytecode.emitABC(LOP_LOADB, target, 1, 0); - - patchJump(expr, jumpLabel, thenLabel); - } - break; - - case AstExprBinary::And: - case AstExprBinary::Or: - { - compileExprAndOr(expr, target, targetTemp); - } - break; - - default: - LUAU_ASSERT(!"Unexpected binary operation"); - } - } - - void compileExprIfElseAndOr(bool and_, uint8_t creg, AstExpr* other, uint8_t target) - { - int32_t cid = getConstantIndex(other); - - if (cid >= 0 && cid <= 255) - { - bytecode.emitABC(and_ ? LOP_ANDK : LOP_ORK, target, creg, uint8_t(cid)); - } - else - { - RegScope rs(this); - uint8_t oreg = compileExprAuto(other, rs); - - bytecode.emitABC(and_ ? LOP_AND : LOP_OR, target, creg, oreg); - } - } - - void compileExprIfElse(AstExprIfElse* expr, uint8_t target, bool targetTemp) - { - if (isConstant(expr->condition)) - { - if (isConstantTrue(expr->condition)) - { - compileExpr(expr->trueExpr, target, targetTemp); - } - else - { - compileExpr(expr->falseExpr, target, targetTemp); - } - } - else - { - // Optimization: convert some if..then..else expressions into and/or when the other side has no side effects and is very cheap to compute - // if v then v else e => v or e - // if v then e else v => v and e - if (int creg = getExprLocalReg(expr->condition); creg >= 0) - { - if (creg == getExprLocalReg(expr->trueExpr) && (getExprLocalReg(expr->falseExpr) >= 0 || isConstant(expr->falseExpr))) - return compileExprIfElseAndOr(/* and_= */ false, uint8_t(creg), expr->falseExpr, target); - else if (creg == getExprLocalReg(expr->falseExpr) && (getExprLocalReg(expr->trueExpr) >= 0 || isConstant(expr->trueExpr))) - return compileExprIfElseAndOr(/* and_= */ true, uint8_t(creg), expr->trueExpr, target); - } - - std::vector elseJump; - compileConditionValue(expr->condition, nullptr, elseJump, false); - compileExpr(expr->trueExpr, target, targetTemp); - - // Jump over else expression evaluation - size_t thenLabel = bytecode.emitLabel(); - bytecode.emitAD(LOP_JUMP, 0, 0); - - size_t elseLabel = bytecode.emitLabel(); - compileExpr(expr->falseExpr, target, targetTemp); - size_t endLabel = bytecode.emitLabel(); - - patchJumps(expr, elseJump, elseLabel); - patchJump(expr, thenLabel, endLabel); - } - } - - void compileExprInterpString(AstExprInterpString* expr, uint8_t target, bool targetTemp) - { - size_t formatCapacity = 0; - for (AstArray string : expr->strings) - { - formatCapacity += string.size + std::count(string.data, string.data + string.size, '%'); - } - - std::string formatString; - formatString.reserve(formatCapacity); - - size_t stringsLeft = expr->strings.size; - - for (AstArray string : expr->strings) - { - if (memchr(string.data, '%', string.size)) - { - for (size_t characterIndex = 0; characterIndex < string.size; ++characterIndex) - { - char character = string.data[characterIndex]; - formatString.push_back(character); - - if (character == '%') - formatString.push_back('%'); - } - } - else - formatString.append(string.data, string.size); - - stringsLeft--; - - if (stringsLeft > 0) - formatString += "%*"; - } - - size_t formatStringSize = formatString.size(); - - // We can't use formatStringRef.data() directly, because short strings don't have their data - // pinned in memory, so when interpFormatStrings grows, these pointers will move and become invalid. - std::unique_ptr formatStringPtr(new char[formatStringSize]); - memcpy(formatStringPtr.get(), formatString.data(), formatStringSize); - - AstArray formatStringArray{formatStringPtr.get(), formatStringSize}; - interpStrings.emplace_back(std::move(formatStringPtr)); // invalidates formatStringPtr, but keeps formatStringArray intact - - int32_t formatStringIndex = bytecode.addConstantString(sref(formatStringArray)); - if (formatStringIndex < 0) - CompileError::raise(expr->location, "Exceeded constant limit; simplify the code to compile"); - - RegScope rs(this); - - uint8_t baseReg = allocReg(expr, unsigned(2 + expr->expressions.size)); - - emitLoadK(baseReg, formatStringIndex); - - for (size_t index = 0; index < expr->expressions.size; ++index) - compileExprTempTop(expr->expressions.data[index], uint8_t(baseReg + 2 + index)); - - BytecodeBuilder::StringRef formatMethod = sref(AstName("format")); - - int32_t formatMethodIndex = bytecode.addConstantString(formatMethod); - if (formatMethodIndex < 0) - CompileError::raise(expr->location, "Exceeded constant limit; simplify the code to compile"); - - bytecode.emitABC(LOP_NAMECALL, baseReg, baseReg, uint8_t(BytecodeBuilder::getStringHash(formatMethod))); - bytecode.emitAux(formatMethodIndex); - bytecode.emitABC(LOP_CALL, baseReg, uint8_t(expr->expressions.size + 2), 2); - bytecode.emitABC(LOP_MOVE, target, baseReg, 0); - } - - static uint8_t encodeHashSize(unsigned int hashSize) - { - size_t hashSizeLog2 = 0; - while ((1u << hashSizeLog2) < hashSize) - hashSizeLog2++; - - return hashSize == 0 ? 0 : uint8_t(hashSizeLog2 + 1); - } - - void compileExprTable(AstExprTable* expr, uint8_t target, bool targetTemp) - { - // Optimization: if the table is empty, we can compute it directly into the target - if (expr->items.size == 0) - { - TableShape shape = tableShapes[expr]; - - bytecode.addDebugRemark("allocation: table hash %d", shape.hashSize); - - bytecode.emitABC(LOP_NEWTABLE, target, encodeHashSize(shape.hashSize), 0); - bytecode.emitAux(shape.arraySize); - return; - } - - unsigned int arraySize = 0; - unsigned int hashSize = 0; - unsigned int recordSize = 0; - unsigned int indexSize = 0; - - for (size_t i = 0; i < expr->items.size; ++i) - { - const AstExprTable::Item& item = expr->items.data[i]; - - arraySize += (item.kind == AstExprTable::Item::List); - hashSize += (item.kind != AstExprTable::Item::List); - recordSize += (item.kind == AstExprTable::Item::Record); - } - - // Optimization: allocate sequential explicitly specified numeric indices ([1]) as arrays - if (arraySize == 0 && hashSize > 0) - { - for (size_t i = 0; i < expr->items.size; ++i) - { - const AstExprTable::Item& item = expr->items.data[i]; - LUAU_ASSERT(item.key); // no list portion => all items have keys - - const Constant* ckey = constants.find(item.key); - - indexSize += (ckey && ckey->type == Constant::Type_Number && ckey->valueNumber == double(indexSize + 1)); - } - - // we only perform the optimization if we don't have any other []-keys - // technically it's "safe" to do this even if we have other keys, but doing so changes iteration order and may break existing code - if (hashSize == recordSize + indexSize) - hashSize = recordSize; - else - indexSize = 0; - } - - int encodedHashSize = encodeHashSize(hashSize); - - RegScope rs(this); - - // Optimization: if target is a temp register, we can clobber it which allows us to compute the result directly into it - uint8_t reg = targetTemp ? target : allocReg(expr, 1); - - // Optimization: when all items are record fields, use template tables to compile expression - if (arraySize == 0 && indexSize == 0 && hashSize == recordSize && recordSize >= 1 && recordSize <= BytecodeBuilder::TableShape::kMaxLength) - { - BytecodeBuilder::TableShape shape; - - for (size_t i = 0; i < expr->items.size; ++i) - { - const AstExprTable::Item& item = expr->items.data[i]; - LUAU_ASSERT(item.kind == AstExprTable::Item::Record); - - AstExprConstantString* ckey = item.key->as(); - LUAU_ASSERT(ckey); - - int cid = bytecode.addConstantString(sref(ckey->value)); - if (cid < 0) - CompileError::raise(ckey->location, "Exceeded constant limit; simplify the code to compile"); - - LUAU_ASSERT(shape.length < BytecodeBuilder::TableShape::kMaxLength); - shape.keys[shape.length++] = int16_t(cid); - } - - int32_t tid = bytecode.addConstantTable(shape); - if (tid < 0) - CompileError::raise(expr->location, "Exceeded constant limit; simplify the code to compile"); - - bytecode.addDebugRemark("allocation: table template %d", hashSize); - - if (tid < 32768) - { - bytecode.emitAD(LOP_DUPTABLE, reg, int16_t(tid)); - } - else - { - bytecode.emitABC(LOP_NEWTABLE, reg, uint8_t(encodedHashSize), 0); - bytecode.emitAux(0); - } - } - else - { - // Optimization: instead of allocating one extra element when the last element of the table literal is ..., let SETLIST allocate the - // correct amount of storage - const AstExprTable::Item* last = expr->items.size > 0 ? &expr->items.data[expr->items.size - 1] : nullptr; - - bool trailingVarargs = last && last->kind == AstExprTable::Item::List && last->value->is(); - LUAU_ASSERT(!trailingVarargs || arraySize > 0); - - unsigned int arrayAllocation = arraySize - trailingVarargs + indexSize; - - if (hashSize == 0) - bytecode.addDebugRemark("allocation: table array %d", arrayAllocation); - else if (arrayAllocation == 0) - bytecode.addDebugRemark("allocation: table hash %d", hashSize); - else - bytecode.addDebugRemark("allocation: table hash %d array %d", hashSize, arrayAllocation); - - bytecode.emitABC(LOP_NEWTABLE, reg, uint8_t(encodedHashSize), 0); - bytecode.emitAux(arrayAllocation); - } - - unsigned int arrayChunkSize = std::min(16u, arraySize); - uint8_t arrayChunkReg = allocReg(expr, arrayChunkSize); - unsigned int arrayChunkCurrent = 0; - - unsigned int arrayIndex = 1; - bool multRet = false; - - for (size_t i = 0; i < expr->items.size; ++i) - { - const AstExprTable::Item& item = expr->items.data[i]; - - AstExpr* key = item.key; - AstExpr* value = item.value; - - // some key/value pairs don't require us to compile the expressions, so we need to setup the line info here - setDebugLine(value); - - if (options.coverageLevel >= 2) - { - bytecode.emitABC(LOP_COVERAGE, 0, 0, 0); - } - - // flush array chunk on overflow or before hash keys to maintain insertion order - if (arrayChunkCurrent > 0 && (key || arrayChunkCurrent == arrayChunkSize)) - { - bytecode.emitABC(LOP_SETLIST, reg, arrayChunkReg, uint8_t(arrayChunkCurrent + 1)); - bytecode.emitAux(arrayIndex); - arrayIndex += arrayChunkCurrent; - arrayChunkCurrent = 0; - } - - // items with a key are set one by one via SETTABLE/SETTABLEKS/SETTABLEN - if (key) - { - RegScope rsi(this); - - LValue lv = compileLValueIndex(reg, key, rsi); - uint8_t rv = compileExprAuto(value, rsi); - - compileAssign(lv, rv); - } - // items without a key are set using SETLIST so that we can initialize large arrays quickly - else - { - uint8_t temp = uint8_t(arrayChunkReg + arrayChunkCurrent); - - if (i + 1 == expr->items.size) - multRet = compileExprTempMultRet(value, temp); - else - compileExprTempTop(value, temp); - - arrayChunkCurrent++; - } - } - - // flush last array chunk; note that this needs multret handling if the last expression was multret - if (arrayChunkCurrent) - { - bytecode.emitABC(LOP_SETLIST, reg, arrayChunkReg, multRet ? 0 : uint8_t(arrayChunkCurrent + 1)); - bytecode.emitAux(arrayIndex); - } - - if (target != reg) - bytecode.emitABC(LOP_MOVE, target, reg, 0); - } - - bool canImport(AstExprGlobal* expr) - { - return options.optimizationLevel >= 1 && getGlobalState(globals, expr->name) != Global::Written; - } - - bool canImportChain(AstExprGlobal* expr) - { - return options.optimizationLevel >= 1 && getGlobalState(globals, expr->name) == Global::Default; - } - - void compileExprIndexName(AstExprIndexName* expr, uint8_t target) - { - setDebugLine(expr); // normally compileExpr sets up line info, but compileExprIndexName can be called directly - - // Optimization: index chains that start from global variables can be compiled into GETIMPORT statement - AstExprGlobal* importRoot = 0; - AstExprIndexName* import1 = 0; - AstExprIndexName* import2 = 0; - - if (AstExprIndexName* index = expr->expr->as()) - { - importRoot = index->expr->as(); - import1 = index; - import2 = expr; - } - else - { - importRoot = expr->expr->as(); - import1 = expr; - } - - if (importRoot && canImportChain(importRoot)) - { - int32_t id0 = bytecode.addConstantString(sref(importRoot->name)); - int32_t id1 = bytecode.addConstantString(sref(import1->index)); - int32_t id2 = import2 ? bytecode.addConstantString(sref(import2->index)) : -1; - - if (id0 < 0 || id1 < 0 || (import2 && id2 < 0)) - CompileError::raise(expr->location, "Exceeded constant limit; simplify the code to compile"); - - // Note: GETIMPORT encoding is limited to 10 bits per object id component - if (id0 < 1024 && id1 < 1024 && id2 < 1024) - { - uint32_t iid = import2 ? BytecodeBuilder::getImportId(id0, id1, id2) : BytecodeBuilder::getImportId(id0, id1); - int32_t cid = bytecode.addImport(iid); - - if (cid >= 0 && cid < 32768) - { - bytecode.emitAD(LOP_GETIMPORT, target, int16_t(cid)); - bytecode.emitAux(iid); - return; - } - } - } - - RegScope rs(this); - uint8_t reg = compileExprAuto(expr->expr, rs); - - setDebugLine(expr->indexLocation); - - BytecodeBuilder::StringRef iname = sref(expr->index); - int32_t cid = bytecode.addConstantString(iname); - if (cid < 0) - CompileError::raise(expr->location, "Exceeded constant limit; simplify the code to compile"); - - bytecode.emitABC(LOP_GETTABLEKS, target, reg, uint8_t(BytecodeBuilder::getStringHash(iname))); - bytecode.emitAux(cid); - } - - void compileExprIndexExpr(AstExprIndexExpr* expr, uint8_t target) - { - RegScope rs(this); - - Constant cv = getConstant(expr->index); - - if (cv.type == Constant::Type_Number && cv.valueNumber >= 1 && cv.valueNumber <= 256 && double(int(cv.valueNumber)) == cv.valueNumber) - { - uint8_t i = uint8_t(int(cv.valueNumber) - 1); - - uint8_t rt = compileExprAuto(expr->expr, rs); - - setDebugLine(expr->index); - - bytecode.emitABC(LOP_GETTABLEN, target, rt, i); - } - else if (cv.type == Constant::Type_String) - { - BytecodeBuilder::StringRef iname = sref(cv.getString()); - int32_t cid = bytecode.addConstantString(iname); - if (cid < 0) - CompileError::raise(expr->location, "Exceeded constant limit; simplify the code to compile"); - - uint8_t rt = compileExprAuto(expr->expr, rs); - - setDebugLine(expr->index); - - bytecode.emitABC(LOP_GETTABLEKS, target, rt, uint8_t(BytecodeBuilder::getStringHash(iname))); - bytecode.emitAux(cid); - } - else - { - uint8_t rt = compileExprAuto(expr->expr, rs); - uint8_t ri = compileExprAuto(expr->index, rs); - - bytecode.emitABC(LOP_GETTABLE, target, rt, ri); - } - } - - void compileExprGlobal(AstExprGlobal* expr, uint8_t target) - { - // Optimization: builtin globals can be retrieved using GETIMPORT - if (canImport(expr)) - { - int32_t id0 = bytecode.addConstantString(sref(expr->name)); - if (id0 < 0) - CompileError::raise(expr->location, "Exceeded constant limit; simplify the code to compile"); - - // Note: GETIMPORT encoding is limited to 10 bits per object id component - if (id0 < 1024) - { - uint32_t iid = BytecodeBuilder::getImportId(id0); - int32_t cid = bytecode.addImport(iid); - - if (cid >= 0 && cid < 32768) - { - bytecode.emitAD(LOP_GETIMPORT, target, int16_t(cid)); - bytecode.emitAux(iid); - return; - } - } - } - - BytecodeBuilder::StringRef gname = sref(expr->name); - int32_t cid = bytecode.addConstantString(gname); - if (cid < 0) - CompileError::raise(expr->location, "Exceeded constant limit; simplify the code to compile"); - - bytecode.emitABC(LOP_GETGLOBAL, target, 0, uint8_t(BytecodeBuilder::getStringHash(gname))); - bytecode.emitAux(cid); - } - - void compileExprConstant(AstExpr* node, const Constant* cv, uint8_t target) - { - switch (cv->type) - { - case Constant::Type_Nil: - bytecode.emitABC(LOP_LOADNIL, target, 0, 0); - break; - - case Constant::Type_Boolean: - bytecode.emitABC(LOP_LOADB, target, cv->valueBoolean, 0); - break; - - case Constant::Type_Number: - { - double d = cv->valueNumber; - - if (d >= std::numeric_limits::min() && d <= std::numeric_limits::max() && double(int16_t(d)) == d && - !(d == 0.0 && signbit(d))) - { - // short number encoding: doesn't require a table entry lookup - bytecode.emitAD(LOP_LOADN, target, int16_t(d)); - } - else - { - // long number encoding: use generic constant path - int32_t cid = bytecode.addConstantNumber(d); - if (cid < 0) - CompileError::raise(node->location, "Exceeded constant limit; simplify the code to compile"); - - emitLoadK(target, cid); - } - } - break; - - case Constant::Type_Vector: - { - int32_t cid = bytecode.addConstantVector(cv->valueVector[0], cv->valueVector[1], cv->valueVector[2], cv->valueVector[3]); - emitLoadK(target, cid); - } - break; - - case Constant::Type_String: - { - int32_t cid = bytecode.addConstantString(sref(cv->getString())); - if (cid < 0) - CompileError::raise(node->location, "Exceeded constant limit; simplify the code to compile"); - - emitLoadK(target, cid); - } - break; - - default: - LUAU_ASSERT(!"Unexpected constant type"); - } - } - - void compileExpr(AstExpr* node, uint8_t target, bool targetTemp = false) - { - setDebugLine(node); - - if (options.coverageLevel >= 2 && needsCoverage(node)) - { - bytecode.emitABC(LOP_COVERAGE, 0, 0, 0); - } - - // Optimization: if expression has a constant value, we can emit it directly - if (const Constant* cv = constants.find(node); cv && cv->type != Constant::Type_Unknown) - { - compileExprConstant(node, cv, target); - return; - } - - if (AstExprGroup* expr = node->as()) - { - compileExpr(expr->expr, target, targetTemp); - } - else if (node->is()) - { - bytecode.emitABC(LOP_LOADNIL, target, 0, 0); - } - else if (AstExprConstantBool* expr = node->as()) - { - bytecode.emitABC(LOP_LOADB, target, expr->value, 0); - } - else if (AstExprConstantNumber* expr = node->as()) - { - int32_t cid = bytecode.addConstantNumber(expr->value); - if (cid < 0) - CompileError::raise(expr->location, "Exceeded constant limit; simplify the code to compile"); - - emitLoadK(target, cid); - } - else if (AstExprConstantString* expr = node->as()) - { - int32_t cid = bytecode.addConstantString(sref(expr->value)); - if (cid < 0) - CompileError::raise(expr->location, "Exceeded constant limit; simplify the code to compile"); - - emitLoadK(target, cid); - } - else if (AstExprLocal* expr = node->as()) - { - // note: this can't check expr->upvalue because upvalues may be upgraded to locals during inlining - if (int reg = getExprLocalReg(expr); reg >= 0) - { - // Optimization: we don't need to move if target happens to be in the same register - if (options.optimizationLevel == 0 || target != reg) - bytecode.emitABC(LOP_MOVE, target, uint8_t(reg), 0); - } - else - { - LUAU_ASSERT(expr->upvalue); - uint8_t uid = getUpval(expr->local); - - bytecode.emitABC(LOP_GETUPVAL, target, uid, 0); - } - } - else if (AstExprGlobal* expr = node->as()) - { - compileExprGlobal(expr, target); - } - else if (AstExprVarargs* expr = node->as()) - { - compileExprVarargs(expr, target, /* targetCount= */ 1); - } - else if (AstExprCall* expr = node->as()) - { - // Optimization: when targeting temporary registers, we can compile call in a special mode that doesn't require extra register moves - if (targetTemp && target == regTop - 1) - compileExprCall(expr, target, 1, /* targetTop= */ true); - else - compileExprCall(expr, target, /* targetCount= */ 1); - } - else if (AstExprIndexName* expr = node->as()) - { - compileExprIndexName(expr, target); - } - else if (AstExprIndexExpr* expr = node->as()) - { - compileExprIndexExpr(expr, target); - } - else if (AstExprFunction* expr = node->as()) - { - compileExprFunction(expr, target); - } - else if (AstExprTable* expr = node->as()) - { - compileExprTable(expr, target, targetTemp); - } - else if (AstExprUnary* expr = node->as()) - { - compileExprUnary(expr, target); - } - else if (AstExprBinary* expr = node->as()) - { - compileExprBinary(expr, target, targetTemp); - } - else if (AstExprTypeAssertion* expr = node->as()) - { - compileExpr(expr->expr, target, targetTemp); - } - else if (AstExprIfElse* expr = node->as()) - { - compileExprIfElse(expr, target, targetTemp); - } - else if (AstExprInterpString* interpString = node->as()) - { - compileExprInterpString(interpString, target, targetTemp); - } - else - { - LUAU_ASSERT(!"Unknown expression type"); - } - } - - void compileExprTemp(AstExpr* node, uint8_t target) - { - return compileExpr(node, target, /* targetTemp= */ true); - } - - uint8_t compileExprAuto(AstExpr* node, RegScope&) - { - // Optimization: directly return locals instead of copying them to a temporary - if (int reg = getExprLocalReg(node); reg >= 0) - return uint8_t(reg); - - // note: the register is owned by the parent scope - uint8_t reg = allocReg(node, 1); - - compileExprTemp(node, reg); - - return reg; - } - - void compileExprSide(AstExpr* node) - { - // Optimization: some expressions never carry side effects so we don't need to emit any code - if (node->is() || node->is() || node->is() || node->is() || isConstant(node)) - return; - - // note: the remark is omitted for calls as it's fairly noisy due to inlining - if (!node->is()) - bytecode.addDebugRemark("expression only compiled for side effects"); - - RegScope rsi(this); - compileExprAuto(node, rsi); - } - - // initializes target..target+targetCount-1 range using expression - // if expression is a call/vararg, we assume it returns all values, otherwise we fill the rest with nil - // assumes target register range can be clobbered and is at the top of the register space if targetTop = true - void compileExprTempN(AstExpr* node, uint8_t target, uint8_t targetCount, bool targetTop) - { - // we assume that target range is at the top of the register space and can be clobbered - // this is what allows us to compile the last call expression - if it's a call - using targetTop=true - LUAU_ASSERT(!targetTop || unsigned(target + targetCount) == regTop); - - if (AstExprCall* expr = node->as()) - { - compileExprCall(expr, target, targetCount, targetTop); - } - else if (AstExprVarargs* expr = node->as()) - { - compileExprVarargs(expr, target, targetCount); - } - else - { - compileExprTemp(node, target); - - for (size_t i = 1; i < targetCount; ++i) - bytecode.emitABC(LOP_LOADNIL, uint8_t(target + i), 0, 0); - } - } - - // initializes target..target+targetCount-1 range using expressions from the list - // if list has fewer expressions, and last expression is multret, we assume it returns the rest of the values - // if list has fewer expressions, and last expression isn't multret, we fill the rest with nil - // assumes target register range can be clobbered and is at the top of the register space if targetTop = true - void compileExprListTemp(const AstArray& list, uint8_t target, uint8_t targetCount, bool targetTop) - { - // we assume that target range is at the top of the register space and can be clobbered - // this is what allows us to compile the last call expression - if it's a call - using targetTop=true - LUAU_ASSERT(!targetTop || unsigned(target + targetCount) == regTop); - - if (list.size == targetCount) - { - for (size_t i = 0; i < list.size; ++i) - compileExprTemp(list.data[i], uint8_t(target + i)); - } - else if (list.size > targetCount) - { - for (size_t i = 0; i < targetCount; ++i) - compileExprTemp(list.data[i], uint8_t(target + i)); - - // evaluate extra expressions for side effects - for (size_t i = targetCount; i < list.size; ++i) - compileExprSide(list.data[i]); - } - else if (list.size > 0) - { - for (size_t i = 0; i < list.size - 1; ++i) - compileExprTemp(list.data[i], uint8_t(target + i)); - - compileExprTempN(list.data[list.size - 1], uint8_t(target + list.size - 1), uint8_t(targetCount - (list.size - 1)), targetTop); - } - else - { - for (size_t i = 0; i < targetCount; ++i) - bytecode.emitABC(LOP_LOADNIL, uint8_t(target + i), 0, 0); - } - } - - struct LValue - { - enum Kind - { - Kind_Local, - Kind_Upvalue, - Kind_Global, - Kind_IndexName, - Kind_IndexNumber, - Kind_IndexExpr, - }; - - Kind kind; - uint8_t reg; // register for local (Local) or table (Index*) - uint8_t upval; - uint8_t index; // register for index in IndexExpr - uint8_t number; // index-1 (0-255) in IndexNumber - BytecodeBuilder::StringRef name; - Location location; - }; - - LValue compileLValueIndex(uint8_t reg, AstExpr* index, RegScope& rs) - { - Constant cv = getConstant(index); - - if (cv.type == Constant::Type_Number && cv.valueNumber >= 1 && cv.valueNumber <= 256 && double(int(cv.valueNumber)) == cv.valueNumber) - { - LValue result = {LValue::Kind_IndexNumber}; - result.reg = reg; - result.number = uint8_t(int(cv.valueNumber) - 1); - result.location = index->location; - - return result; - } - else if (cv.type == Constant::Type_String) - { - LValue result = {LValue::Kind_IndexName}; - result.reg = reg; - result.name = sref(cv.getString()); - result.location = index->location; - - return result; - } - else - { - LValue result = {LValue::Kind_IndexExpr}; - result.reg = reg; - result.index = compileExprAuto(index, rs); - result.location = index->location; - - return result; - } - } - - LValue compileLValue(AstExpr* node, RegScope& rs) - { - setDebugLine(node); - - if (AstExprLocal* expr = node->as()) - { - // note: this can't check expr->upvalue because upvalues may be upgraded to locals during inlining - if (int reg = getExprLocalReg(expr); reg >= 0) - { - LValue result = {LValue::Kind_Local}; - result.reg = uint8_t(reg); - result.location = node->location; - - return result; - } - else - { - LUAU_ASSERT(expr->upvalue); - - LValue result = {LValue::Kind_Upvalue}; - result.upval = getUpval(expr->local); - result.location = node->location; - - return result; - } - } - else if (AstExprGlobal* expr = node->as()) - { - LValue result = {LValue::Kind_Global}; - result.name = sref(expr->name); - result.location = node->location; - - return result; - } - else if (AstExprIndexName* expr = node->as()) - { - LValue result = {LValue::Kind_IndexName}; - result.reg = compileExprAuto(expr->expr, rs); - result.name = sref(expr->index); - result.location = node->location; - - return result; - } - else if (AstExprIndexExpr* expr = node->as()) - { - uint8_t reg = compileExprAuto(expr->expr, rs); - - return compileLValueIndex(reg, expr->index, rs); - } - else - { - LUAU_ASSERT(!"Unknown assignment expression"); - - return LValue(); - } - } - - void compileLValueUse(const LValue& lv, uint8_t reg, bool set) - { - setDebugLine(lv.location); - - switch (lv.kind) - { - case LValue::Kind_Local: - if (set) - bytecode.emitABC(LOP_MOVE, lv.reg, reg, 0); - else - bytecode.emitABC(LOP_MOVE, reg, lv.reg, 0); - break; - - case LValue::Kind_Upvalue: - bytecode.emitABC(set ? LOP_SETUPVAL : LOP_GETUPVAL, reg, lv.upval, 0); - break; - - case LValue::Kind_Global: - { - int32_t cid = bytecode.addConstantString(lv.name); - if (cid < 0) - CompileError::raise(lv.location, "Exceeded constant limit; simplify the code to compile"); - - bytecode.emitABC(set ? LOP_SETGLOBAL : LOP_GETGLOBAL, reg, 0, uint8_t(BytecodeBuilder::getStringHash(lv.name))); - bytecode.emitAux(cid); - } - break; - - case LValue::Kind_IndexName: - { - int32_t cid = bytecode.addConstantString(lv.name); - if (cid < 0) - CompileError::raise(lv.location, "Exceeded constant limit; simplify the code to compile"); - - bytecode.emitABC(set ? LOP_SETTABLEKS : LOP_GETTABLEKS, reg, lv.reg, uint8_t(BytecodeBuilder::getStringHash(lv.name))); - bytecode.emitAux(cid); - } - break; - - case LValue::Kind_IndexNumber: - bytecode.emitABC(set ? LOP_SETTABLEN : LOP_GETTABLEN, reg, lv.reg, lv.number); - break; - - case LValue::Kind_IndexExpr: - bytecode.emitABC(set ? LOP_SETTABLE : LOP_GETTABLE, reg, lv.reg, lv.index); - break; - - default: - LUAU_ASSERT(!"Unknown lvalue kind"); - } - } - - void compileAssign(const LValue& lv, uint8_t source) - { - compileLValueUse(lv, source, /* set= */ true); - } - - AstExprLocal* getExprLocal(AstExpr* node) - { - if (AstExprLocal* expr = node->as()) - return expr; - else if (AstExprGroup* expr = node->as()) - return getExprLocal(expr->expr); - else if (AstExprTypeAssertion* expr = node->as()) - return getExprLocal(expr->expr); - else - return nullptr; - } - - int getExprLocalReg(AstExpr* node) - { - if (AstExprLocal* expr = getExprLocal(node)) - { - // note: this can't check expr->upvalue because upvalues may be upgraded to locals during inlining - Local* l = locals.find(expr->local); - - return l && l->allocated ? l->reg : -1; - } - else - return -1; - } - - bool isStatBreak(AstStat* node) - { - if (AstStatBlock* stat = node->as()) - return stat->body.size == 1 && stat->body.data[0]->is(); - - return node->is(); - } - - AstStatContinue* extractStatContinue(AstStatBlock* block) - { - if (block->body.size == 1) - return block->body.data[0]->as(); - else - return nullptr; - } - - void compileStatIf(AstStatIf* stat) - { - // Optimization: condition is always false => we only need the else body - if (isConstantFalse(stat->condition)) - { - if (stat->elsebody) - compileStat(stat->elsebody); - return; - } - - // Optimization: condition is always false but isn't a constant => we only need the else body and condition's side effects - if (AstExprBinary* cand = stat->condition->as(); cand && cand->op == AstExprBinary::And && isConstantFalse(cand->right)) - { - compileExprSide(cand->left); - if (stat->elsebody) - compileStat(stat->elsebody); - return; - } - - // Optimization: body is a "break" statement with no "else" => we can directly break out of the loop in "then" case - if (!stat->elsebody && isStatBreak(stat->thenbody) && !areLocalsCaptured(loops.back().localOffset)) - { - // fallthrough = continue with the loop as usual - std::vector elseJump; - compileConditionValue(stat->condition, nullptr, elseJump, true); - - for (size_t jump : elseJump) - loopJumps.push_back({LoopJump::Break, jump}); - return; - } - - AstStatContinue* continueStatement = extractStatContinue(stat->thenbody); - - // Optimization: body is a "continue" statement with no "else" => we can directly continue in "then" case - if (!stat->elsebody && continueStatement != nullptr && !areLocalsCaptured(loops.back().localOffsetContinue)) - { - // track continue statement for repeat..until validation (validateContinueUntil) - if (!loops.back().continueUsed) - loops.back().continueUsed = continueStatement; - - // fallthrough = proceed with the loop body as usual - std::vector elseJump; - compileConditionValue(stat->condition, nullptr, elseJump, true); - - for (size_t jump : elseJump) - loopJumps.push_back({LoopJump::Continue, jump}); - return; - } - - std::vector elseJump; - compileConditionValue(stat->condition, nullptr, elseJump, false); - - compileStat(stat->thenbody); - - if (stat->elsebody && elseJump.size() > 0) - { - // we don't need to skip past "else" body if "then" ends with return/break/continue - // this is important because, if "else" also ends with return, we may *not* have any statement to skip to! - if (alwaysTerminates(stat->thenbody)) - { - size_t elseLabel = bytecode.emitLabel(); - - compileStat(stat->elsebody); - - patchJumps(stat, elseJump, elseLabel); - } - else - { - size_t thenLabel = bytecode.emitLabel(); - - bytecode.emitAD(LOP_JUMP, 0, 0); - - size_t elseLabel = bytecode.emitLabel(); - - compileStat(stat->elsebody); - - size_t endLabel = bytecode.emitLabel(); - - patchJumps(stat, elseJump, elseLabel); - patchJump(stat, thenLabel, endLabel); - } - } - else - { - size_t endLabel = bytecode.emitLabel(); - - patchJumps(stat, elseJump, endLabel); - } - } - - void compileStatWhile(AstStatWhile* stat) - { - // Optimization: condition is always false => there's no loop! - if (isConstantFalse(stat->condition)) - return; - - size_t oldJumps = loopJumps.size(); - size_t oldLocals = localStack.size(); - - loops.push_back({oldLocals, oldLocals, nullptr}); - hasLoops = true; - - size_t loopLabel = bytecode.emitLabel(); - - std::vector elseJump; - compileConditionValue(stat->condition, nullptr, elseJump, false); - - compileStat(stat->body); - - size_t contLabel = bytecode.emitLabel(); - - size_t backLabel = bytecode.emitLabel(); - - setDebugLine(stat->condition); - - // Note: this is using JUMPBACK, not JUMP, since JUMPBACK is interruptible and we want all loops to have at least one interruptible - // instruction - bytecode.emitAD(LOP_JUMPBACK, 0, 0); - - size_t endLabel = bytecode.emitLabel(); - - patchJump(stat, backLabel, loopLabel); - patchJumps(stat, elseJump, endLabel); - - patchLoopJumps(stat, oldJumps, endLabel, contLabel); - loopJumps.resize(oldJumps); - - loops.pop_back(); - } - - void compileStatRepeat(AstStatRepeat* stat) - { - size_t oldJumps = loopJumps.size(); - size_t oldLocals = localStack.size(); - - loops.push_back({oldLocals, oldLocals, nullptr}); - hasLoops = true; - - size_t loopLabel = bytecode.emitLabel(); - - // note: we "inline" compileStatBlock here so that we can close/pop locals after evaluating condition - // this is necessary because condition can access locals declared inside the repeat..until body - AstStatBlock* body = stat->body; - - RegScope rs(this); - - bool continueValidated = false; - - for (size_t i = 0; i < body->body.size; ++i) - { - compileStat(body->body.data[i]); - - // continue statement inside the repeat..until loop should not close upvalues defined directly in the loop body - // (but it must still close upvalues defined in more nested blocks) - // this is because the upvalues defined inside the loop body may be captured by a closure defined in the until - // expression that continue will jump to. - loops.back().localOffsetContinue = localStack.size(); - - // if continue was called from this statement, any local defined after this in the loop body should not be accessed by until condition - // it is sufficient to check this condition once, as if this holds for the first continue, it must hold for all subsequent continues. - if (loops.back().continueUsed && !continueValidated) - { - validateContinueUntil(loops.back().continueUsed, stat->condition, body, i + 1); - continueValidated = true; - } - } - - size_t contLabel = bytecode.emitLabel(); - - size_t endLabel; - - setDebugLine(stat->condition); - - if (isConstantTrue(stat->condition)) - { - closeLocals(oldLocals); - - endLabel = bytecode.emitLabel(); - } - else - { - std::vector skipJump; - compileConditionValue(stat->condition, nullptr, skipJump, true); - - // we close locals *after* we compute loop conditionals because during computation of condition it's (in theory) possible that user code - // mutates them - closeLocals(oldLocals); - - size_t backLabel = bytecode.emitLabel(); - - // Note: this is using JUMPBACK, not JUMP, since JUMPBACK is interruptible and we want all loops to have at least one interruptible - // instruction - bytecode.emitAD(LOP_JUMPBACK, 0, 0); - - size_t skipLabel = bytecode.emitLabel(); - - // we need to close locals *again* after the loop ends because the first closeLocals would be jumped over on the last iteration - closeLocals(oldLocals); - - endLabel = bytecode.emitLabel(); - - patchJump(stat, backLabel, loopLabel); - patchJumps(stat, skipJump, skipLabel); - } - - popLocals(oldLocals); - - patchLoopJumps(stat, oldJumps, endLabel, contLabel); - loopJumps.resize(oldJumps); - - loops.pop_back(); - } - - void compileInlineReturn(AstStatReturn* stat, bool fallthrough) - { - setDebugLine(stat); // normally compileStat sets up line info, but compileInlineReturn can be called directly - - InlineFrame frame = inlineFrames.back(); - - compileExprListTemp(stat->list, frame.target, frame.targetCount, /* targetTop= */ false); - - closeLocals(frame.localOffset); - - if (!fallthrough) - { - size_t jumpLabel = bytecode.emitLabel(); - bytecode.emitAD(LOP_JUMP, 0, 0); - - inlineFrames.back().returnJumps.push_back(jumpLabel); - } - } - - void compileStatReturn(AstStatReturn* stat) - { - RegScope rs(this); - - uint8_t temp = 0; - bool consecutive = false; - bool multRet = false; - - // Optimization: return locals directly instead of copying them into a temporary - // this is very important for a single return value and occasionally effective for multiple values - if (int reg = stat->list.size > 0 ? getExprLocalReg(stat->list.data[0]) : -1; reg >= 0) - { - temp = uint8_t(reg); - consecutive = true; - - for (size_t i = 1; i < stat->list.size; ++i) - if (getExprLocalReg(stat->list.data[i]) != int(temp + i)) - { - consecutive = false; - break; - } - } - - if (!consecutive && stat->list.size > 0) - { - temp = allocReg(stat, unsigned(stat->list.size)); - - // Note: if the last element is a function call or a vararg specifier, then we need to somehow return all values that that call returned - for (size_t i = 0; i < stat->list.size; ++i) - if (i + 1 == stat->list.size) - multRet = compileExprTempMultRet(stat->list.data[i], uint8_t(temp + i)); - else - compileExprTempTop(stat->list.data[i], uint8_t(temp + i)); - } - - closeLocals(0); - - bytecode.emitABC(LOP_RETURN, uint8_t(temp), multRet ? 0 : uint8_t(stat->list.size + 1), 0); - } - - bool areLocalsRedundant(AstStatLocal* stat) - { - // Extra expressions may have side effects - if (stat->values.size > stat->vars.size) - return false; - - for (AstLocal* local : stat->vars) - { - Variable* v = variables.find(local); - - if (!v || !v->constant) - return false; - } - - return true; - } - - void compileStatLocal(AstStatLocal* stat) - { - // Optimization: we don't need to allocate and assign const locals, since their uses will be constant-folded - if (options.optimizationLevel >= 1 && options.debugLevel <= 1 && areLocalsRedundant(stat)) - return; - - // Optimization: for 1-1 local assignments, we can reuse the register *if* neither local is mutated - if (options.optimizationLevel >= 1 && stat->vars.size == 1 && stat->values.size == 1) - { - if (AstExprLocal* re = getExprLocal(stat->values.data[0])) - { - Variable* lv = variables.find(stat->vars.data[0]); - Variable* rv = variables.find(re->local); - - if (int reg = getExprLocalReg(re); reg >= 0 && (!lv || !lv->written) && (!rv || !rv->written)) - { - pushLocal(stat->vars.data[0], uint8_t(reg)); - return; - } - } - } - - // note: allocReg in this case allocates into parent block register - note that we don't have RegScope here - uint8_t vars = allocReg(stat, unsigned(stat->vars.size)); - - compileExprListTemp(stat->values, vars, uint8_t(stat->vars.size), /* targetTop= */ true); - - for (size_t i = 0; i < stat->vars.size; ++i) - pushLocal(stat->vars.data[i], uint8_t(vars + i)); - } - - bool tryCompileUnrolledFor(AstStatFor* stat, int thresholdBase, int thresholdMaxBoost) - { - Constant one = {Constant::Type_Number}; - one.valueNumber = 1.0; - - Constant fromc = getConstant(stat->from); - Constant toc = getConstant(stat->to); - Constant stepc = stat->step ? getConstant(stat->step) : one; - - int tripCount = (fromc.type == Constant::Type_Number && toc.type == Constant::Type_Number && stepc.type == Constant::Type_Number) - ? getTripCount(fromc.valueNumber, toc.valueNumber, stepc.valueNumber) - : -1; - - if (tripCount < 0) - { - bytecode.addDebugRemark("loop unroll failed: invalid iteration count"); - return false; - } - - if (tripCount > thresholdBase) - { - bytecode.addDebugRemark("loop unroll failed: too many iterations (%d)", tripCount); - return false; - } - - if (Variable* lv = variables.find(stat->var); lv && lv->written) - { - bytecode.addDebugRemark("loop unroll failed: mutable loop variable"); - return false; - } - - AstLocal* var = stat->var; - uint64_t costModel = modelCost(stat->body, &var, 1, builtins); - - // we use a dynamic cost threshold that's based on the fixed limit boosted by the cost advantage we gain due to unrolling - bool varc = true; - int unrolledCost = computeCost(costModel, &varc, 1) * tripCount; - int baselineCost = (computeCost(costModel, nullptr, 0) + 1) * tripCount; - int unrollProfit = (unrolledCost == 0) ? thresholdMaxBoost : std::min(thresholdMaxBoost, 100 * baselineCost / unrolledCost); - - int threshold = thresholdBase * unrollProfit / 100; - - if (unrolledCost > threshold) - { - bytecode.addDebugRemark( - "loop unroll failed: too expensive (iterations %d, cost %d, profit %.2fx)", tripCount, unrolledCost, double(unrollProfit) / 100); - return false; - } - - bytecode.addDebugRemark("loop unroll succeeded (iterations %d, cost %d, profit %.2fx)", tripCount, unrolledCost, double(unrollProfit) / 100); - - compileUnrolledFor(stat, tripCount, fromc.valueNumber, stepc.valueNumber); - return true; - } - - void compileUnrolledFor(AstStatFor* stat, int tripCount, double from, double step) - { - AstLocal* var = stat->var; - - size_t oldLocals = localStack.size(); - size_t oldJumps = loopJumps.size(); - - loops.push_back({oldLocals, oldLocals, nullptr}); - - for (int iv = 0; iv < tripCount; ++iv) - { - // we need to re-fold constants in the loop body with the new value; this reuses computed constant values elsewhere in the tree - locstants[var].type = Constant::Type_Number; - locstants[var].valueNumber = from + iv * step; - - foldConstants(constants, variables, locstants, builtinsFold, builtinsFoldMathK, stat); - - size_t iterJumps = loopJumps.size(); - - compileStat(stat->body); - - // all continue jumps need to go to the next iteration - size_t contLabel = bytecode.emitLabel(); - - for (size_t i = iterJumps; i < loopJumps.size(); ++i) - if (loopJumps[i].type == LoopJump::Continue) - patchJump(stat, loopJumps[i].label, contLabel); - } - - // all break jumps need to go past the loop - size_t endLabel = bytecode.emitLabel(); - - for (size_t i = oldJumps; i < loopJumps.size(); ++i) - if (loopJumps[i].type == LoopJump::Break) - patchJump(stat, loopJumps[i].label, endLabel); - - loopJumps.resize(oldJumps); - - loops.pop_back(); - - // clean up fold state in case we need to recompile - normally we compile the loop body once, but due to inlining we may need to do it again - locstants[var].type = Constant::Type_Unknown; - - foldConstants(constants, variables, locstants, builtinsFold, builtinsFoldMathK, stat); - } - - void compileStatFor(AstStatFor* stat) - { - RegScope rs(this); - - // Optimization: small loops can be unrolled when it is profitable - if (options.optimizationLevel >= 2 && isConstant(stat->to) && isConstant(stat->from) && (!stat->step || isConstant(stat->step))) - if (tryCompileUnrolledFor(stat, FInt::LuauCompileLoopUnrollThreshold, FInt::LuauCompileLoopUnrollThresholdMaxBoost)) - return; - - size_t oldLocals = localStack.size(); - size_t oldJumps = loopJumps.size(); - - loops.push_back({oldLocals, oldLocals, nullptr}); - hasLoops = true; - - // register layout: limit, step, index - uint8_t regs = allocReg(stat, 3); - - // if the iteration index is assigned from within the loop, we need to protect the internal index from the assignment - // to do that, we will copy the index into an actual local variable on each iteration - // this makes sure the code inside the loop can't interfere with the iteration process (other than modifying the table we're iterating - // through) - uint8_t varreg = regs + 2; - - if (Variable* il = variables.find(stat->var); il && il->written) - varreg = allocReg(stat, 1); - - compileExprTemp(stat->from, uint8_t(regs + 2)); - compileExprTemp(stat->to, uint8_t(regs + 0)); - - if (stat->step) - compileExprTemp(stat->step, uint8_t(regs + 1)); - else - bytecode.emitABC(LOP_LOADN, uint8_t(regs + 1), 1, 0); - - size_t forLabel = bytecode.emitLabel(); - - bytecode.emitAD(LOP_FORNPREP, regs, 0); - - size_t loopLabel = bytecode.emitLabel(); - - if (varreg != regs + 2) - bytecode.emitABC(LOP_MOVE, varreg, regs + 2, 0); - - pushLocal(stat->var, varreg); - - compileStat(stat->body); - - closeLocals(oldLocals); - popLocals(oldLocals); - - setDebugLine(stat); - - size_t contLabel = bytecode.emitLabel(); - - size_t backLabel = bytecode.emitLabel(); - - bytecode.emitAD(LOP_FORNLOOP, regs, 0); - - size_t endLabel = bytecode.emitLabel(); - - patchJump(stat, forLabel, endLabel); - patchJump(stat, backLabel, loopLabel); - - patchLoopJumps(stat, oldJumps, endLabel, contLabel); - loopJumps.resize(oldJumps); - - loops.pop_back(); - } - - void compileStatForIn(AstStatForIn* stat) - { - RegScope rs(this); - - size_t oldLocals = localStack.size(); - size_t oldJumps = loopJumps.size(); - - loops.push_back({oldLocals, oldLocals, nullptr}); - hasLoops = true; - - // register layout: generator, state, index, variables... - uint8_t regs = allocReg(stat, 3); - - // this puts initial values of (generator, state, index) into the loop registers - compileExprListTemp(stat->values, regs, 3, /* targetTop= */ true); - - // note that we reserve at least 2 variables; this allows our fast path to assume that we need 2 variables instead of 1 or 2 - uint8_t vars = allocReg(stat, std::max(unsigned(stat->vars.size), 2u)); - LUAU_ASSERT(vars == regs + 3); - - LuauOpcode skipOp = LOP_FORGPREP; - - // Optimization: when we iterate via pairs/ipairs, we generate special bytecode that optimizes the traversal using internal iteration index - // These instructions dynamically check if generator is equal to next/inext and bail out - // They assume that the generator produces 2 variables, which is why we allocate at least 2 above (see vars assignment) - if (options.optimizationLevel >= 1 && stat->vars.size <= 2) - { - if (stat->values.size == 1 && stat->values.data[0]->is()) - { - Builtin builtin = getBuiltin(stat->values.data[0]->as()->func, globals, variables); - - if (builtin.isGlobal("ipairs")) // for .. in ipairs(t) - skipOp = LOP_FORGPREP_INEXT; - else if (builtin.isGlobal("pairs")) // for .. in pairs(t) - skipOp = LOP_FORGPREP_NEXT; - } - else if (stat->values.size == 2) - { - Builtin builtin = getBuiltin(stat->values.data[0], globals, variables); - - if (builtin.isGlobal("next")) // for .. in next,t - skipOp = LOP_FORGPREP_NEXT; - } - } - - // first iteration jumps into FORGLOOP instruction, but for ipairs/pairs it does extra preparation that makes the cost of an extra instruction - // worthwhile - size_t skipLabel = bytecode.emitLabel(); - - bytecode.emitAD(skipOp, regs, 0); - - size_t loopLabel = bytecode.emitLabel(); - - for (size_t i = 0; i < stat->vars.size; ++i) - pushLocal(stat->vars.data[i], uint8_t(vars + i)); - - compileStat(stat->body); - - closeLocals(oldLocals); - popLocals(oldLocals); - - setDebugLine(stat); - - size_t contLabel = bytecode.emitLabel(); - - size_t backLabel = bytecode.emitLabel(); - - // FORGLOOP uses aux to encode variable count and fast path flag for ipairs traversal in the high bit - bytecode.emitAD(LOP_FORGLOOP, regs, 0); - bytecode.emitAux((skipOp == LOP_FORGPREP_INEXT ? 0x80000000 : 0) | uint32_t(stat->vars.size)); - - size_t endLabel = bytecode.emitLabel(); - - patchJump(stat, skipLabel, backLabel); - patchJump(stat, backLabel, loopLabel); - - patchLoopJumps(stat, oldJumps, endLabel, contLabel); - loopJumps.resize(oldJumps); - - loops.pop_back(); - } - - struct Assignment - { - LValue lvalue; - - uint8_t conflictReg = kInvalidReg; - uint8_t valueReg = kInvalidReg; - }; - - // This function analyzes assignments and marks assignment conflicts: cases when a variable is assigned on lhs - // but subsequently used on the rhs, assuming assignments are performed in order. Note that it's also possible - // for a variable to conflict on the lhs, if it's used in an lvalue expression after it's assigned. - // When conflicts are found, Assignment::conflictReg is allocated and that's where assignment is performed instead, - // until the final fixup in compileStatAssign. Assignment::valueReg is allocated by compileStatAssign as well. - // - // Per Lua manual, section 3.3.3 (Assignments), the proper assignment order is only guaranteed to hold for syntactic access: - // - // Note that this guarantee covers only accesses syntactically inside the assignment statement. If a function or a metamethod called - // during the assignment changes the value of a variable, Lua gives no guarantees about the order of that access. - // - // As such, we currently don't check if an assigned local is captured, which may mean it gets reassigned during a function call. - void resolveAssignConflicts(AstStat* stat, std::vector& vars, const AstArray& values) - { - struct Visitor : AstVisitor - { - Compiler* self; - - std::bitset<256> conflict; - std::bitset<256> assigned; - - Visitor(Compiler* self) - : self(self) - { - } - - bool visit(AstExprLocal* node) override - { - int reg = self->getLocalReg(node->local); - - if (reg >= 0 && assigned[reg]) - conflict[reg] = true; - - return true; - } - }; - - Visitor visitor(this); - - // mark any registers that are used *after* assignment as conflicting - - // first we go through assignments to locals, since they are performed before assignments to other l-values - for (size_t i = 0; i < vars.size(); ++i) - { - const LValue& li = vars[i].lvalue; - - if (li.kind == LValue::Kind_Local) - { - if (i < values.size) - values.data[i]->visit(&visitor); - - visitor.assigned[li.reg] = true; - } - } - - // and now we handle all other l-values - for (size_t i = 0; i < vars.size(); ++i) - { - const LValue& li = vars[i].lvalue; - - if (li.kind != LValue::Kind_Local && i < values.size) - values.data[i]->visit(&visitor); - } - - // mark any registers used in trailing expressions as conflicting as well - for (size_t i = vars.size(); i < values.size; ++i) - values.data[i]->visit(&visitor); - - // mark any registers used on left hand side that are also assigned anywhere as conflicting - // this is order-independent because we evaluate all right hand side arguments into registers before doing table assignments - for (const Assignment& var : vars) - { - const LValue& li = var.lvalue; - - if ((li.kind == LValue::Kind_IndexName || li.kind == LValue::Kind_IndexNumber || li.kind == LValue::Kind_IndexExpr) && - visitor.assigned[li.reg]) - visitor.conflict[li.reg] = true; - - if (li.kind == LValue::Kind_IndexExpr && visitor.assigned[li.index]) - visitor.conflict[li.index] = true; - } - - // for any conflicting var, we need to allocate a temporary register where the assignment is performed, so that we can move the value later - for (Assignment& var : vars) - { - const LValue& li = var.lvalue; - - if (li.kind == LValue::Kind_Local && visitor.conflict[li.reg]) - var.conflictReg = allocReg(stat, 1); - } - } - - void compileStatAssign(AstStatAssign* stat) - { - RegScope rs(this); - - // Optimization: one to one assignments don't require complex conflict resolution machinery - if (stat->vars.size == 1 && stat->values.size == 1) - { - LValue var = compileLValue(stat->vars.data[0], rs); - - // Optimization: assign to locals directly - if (var.kind == LValue::Kind_Local) - { - compileExpr(stat->values.data[0], var.reg); - } - else - { - uint8_t reg = compileExprAuto(stat->values.data[0], rs); - - setDebugLine(stat->vars.data[0]); - compileAssign(var, reg); - } - return; - } - - // compute all l-values: note that this doesn't assign anything yet but it allocates registers and computes complex expressions on the - // left hand side - for example, in "a[expr] = foo" expr will get evaluated here - std::vector vars(stat->vars.size); - - for (size_t i = 0; i < stat->vars.size; ++i) - vars[i].lvalue = compileLValue(stat->vars.data[i], rs); - - // perform conflict resolution: if any expression refers to a local that is assigned before evaluating it, we assign to a temporary - // register after this, vars[i].conflictReg is set for locals that need to be assigned in the second pass - resolveAssignConflicts(stat, vars, stat->values); - - // compute rhs into (mostly) fresh registers - // note that when the lhs assigment is a local, we evaluate directly into that register - // this is possible because resolveAssignConflicts renamed conflicting locals into temporaries - // after this, vars[i].valueReg is set to a register with the value for *all* vars, but some have already been assigned - for (size_t i = 0; i < stat->vars.size && i < stat->values.size; ++i) - { - AstExpr* value = stat->values.data[i]; - - if (i + 1 == stat->values.size && stat->vars.size > stat->values.size) - { - // allocate a consecutive range of regs for all remaining vars and compute everything into temps - // note, this also handles trailing nils - uint8_t rest = uint8_t(stat->vars.size - stat->values.size + 1); - uint8_t temp = allocReg(stat, rest); - - compileExprTempN(value, temp, rest, /* targetTop= */ true); - - for (size_t j = i; j < stat->vars.size; ++j) - vars[j].valueReg = uint8_t(temp + (j - i)); - } - else - { - Assignment& var = vars[i]; - - // if target is a local, use compileExpr directly to target - if (var.lvalue.kind == LValue::Kind_Local) - { - var.valueReg = (var.conflictReg == kInvalidReg) ? var.lvalue.reg : var.conflictReg; - - compileExpr(stat->values.data[i], var.valueReg); - } - else - { - var.valueReg = compileExprAuto(stat->values.data[i], rs); - } - } - } - - // compute expressions with side effects - for (size_t i = stat->vars.size; i < stat->values.size; ++i) - compileExprSide(stat->values.data[i]); - - // almost done... let's assign everything left to right, noting that locals were either written-to directly, or will be written-to in a - // separate pass to avoid conflicts - for (const Assignment& var : vars) - { - LUAU_ASSERT(var.valueReg != kInvalidReg); - - if (var.lvalue.kind != LValue::Kind_Local) - { - setDebugLine(var.lvalue.location); - compileAssign(var.lvalue, var.valueReg); - } - } - - // all regular local writes are done by the prior loops by computing result directly into target, so this just handles conflicts OR - // local copies from temporary registers in multret context, since in that case we have to allocate consecutive temporaries - for (const Assignment& var : vars) - { - if (var.lvalue.kind == LValue::Kind_Local && var.valueReg != var.lvalue.reg) - bytecode.emitABC(LOP_MOVE, var.lvalue.reg, var.valueReg, 0); - } - } - - void compileStatCompoundAssign(AstStatCompoundAssign* stat) - { - RegScope rs(this); - - LValue var = compileLValue(stat->var, rs); - - // Optimization: assign to locals directly - uint8_t target = (var.kind == LValue::Kind_Local) ? var.reg : allocReg(stat, 1); - - switch (stat->op) - { - case AstExprBinary::Add: - case AstExprBinary::Sub: - case AstExprBinary::Mul: - case AstExprBinary::Div: - case AstExprBinary::FloorDiv: - case AstExprBinary::Mod: - case AstExprBinary::Pow: - { - if (var.kind != LValue::Kind_Local) - compileLValueUse(var, target, /* set= */ false); - - int32_t rc = getConstantNumber(stat->value); - - if (rc >= 0 && rc <= 255) - { - bytecode.emitABC(getBinaryOpArith(stat->op, /* k= */ true), target, target, uint8_t(rc)); - } - else - { - uint8_t rr = compileExprAuto(stat->value, rs); - - bytecode.emitABC(getBinaryOpArith(stat->op), target, target, rr); - } - } - break; - - case AstExprBinary::Concat: - { - std::vector args = {stat->value}; - - // unroll the tree of concats down the right hand side to be able to do multiple ops - unrollConcats(args); - - uint8_t regs = allocReg(stat, unsigned(1 + args.size())); - - compileLValueUse(var, regs, /* set= */ false); - - for (size_t i = 0; i < args.size(); ++i) - compileExprTemp(args[i], uint8_t(regs + 1 + i)); - - bytecode.emitABC(LOP_CONCAT, target, regs, uint8_t(regs + args.size())); - } - break; - - default: - LUAU_ASSERT(!"Unexpected compound assignment operation"); - } - - if (var.kind != LValue::Kind_Local) - compileAssign(var, target); - } - - void compileStatFunction(AstStatFunction* stat) - { - // Optimization: compile value expresion directly into target local register - if (int reg = getExprLocalReg(stat->name); reg >= 0) - { - compileExpr(stat->func, uint8_t(reg)); - return; - } - - RegScope rs(this); - uint8_t reg = allocReg(stat, 1); - - compileExprTemp(stat->func, reg); - - LValue var = compileLValue(stat->name, rs); - compileAssign(var, reg); - } - - void compileStat(AstStat* node) - { - setDebugLine(node); - - if (options.coverageLevel >= 1 && needsCoverage(node)) - { - bytecode.emitABC(LOP_COVERAGE, 0, 0, 0); - } - - if (AstStatBlock* stat = node->as()) - { - RegScope rs(this); - - size_t oldLocals = localStack.size(); - - for (size_t i = 0; i < stat->body.size; ++i) - compileStat(stat->body.data[i]); - - closeLocals(oldLocals); - - popLocals(oldLocals); - } - else if (AstStatIf* stat = node->as()) - { - compileStatIf(stat); - } - else if (AstStatWhile* stat = node->as()) - { - compileStatWhile(stat); - } - else if (AstStatRepeat* stat = node->as()) - { - compileStatRepeat(stat); - } - else if (node->is()) - { - LUAU_ASSERT(!loops.empty()); - - // before exiting out of the loop, we need to close all local variables that were captured in closures since loop start - // normally they are closed by the enclosing blocks, including the loop block, but we're skipping that here - closeLocals(loops.back().localOffset); - - size_t label = bytecode.emitLabel(); - - bytecode.emitAD(LOP_JUMP, 0, 0); - - loopJumps.push_back({LoopJump::Break, label}); - } - else if (AstStatContinue* stat = node->as()) - { - LUAU_ASSERT(!loops.empty()); - - // track continue statement for repeat..until validation (validateContinueUntil) - if (!loops.back().continueUsed) - loops.back().continueUsed = stat; - - // before continuing, we need to close all local variables that were captured in closures since loop start - // normally they are closed by the enclosing blocks, including the loop block, but we're skipping that here - closeLocals(loops.back().localOffsetContinue); - - size_t label = bytecode.emitLabel(); - - bytecode.emitAD(LOP_JUMP, 0, 0); - - loopJumps.push_back({LoopJump::Continue, label}); - } - else if (AstStatReturn* stat = node->as()) - { - if (options.optimizationLevel >= 2 && !inlineFrames.empty()) - compileInlineReturn(stat, /* fallthrough= */ false); - else - compileStatReturn(stat); - } - else if (AstStatExpr* stat = node->as()) - { - // Optimization: since we don't need to read anything from the stack, we can compile the call to not return anything which saves register - // moves - if (AstExprCall* expr = stat->expr->as()) - { - uint8_t target = uint8_t(regTop); - - compileExprCall(expr, target, /* targetCount= */ 0); - } - else - { - compileExprSide(stat->expr); - } - } - else if (AstStatLocal* stat = node->as()) - { - compileStatLocal(stat); - } - else if (AstStatFor* stat = node->as()) - { - compileStatFor(stat); - } - else if (AstStatForIn* stat = node->as()) - { - compileStatForIn(stat); - } - else if (AstStatAssign* stat = node->as()) - { - compileStatAssign(stat); - } - else if (AstStatCompoundAssign* stat = node->as()) - { - compileStatCompoundAssign(stat); - } - else if (AstStatFunction* stat = node->as()) - { - compileStatFunction(stat); - } - else if (AstStatLocalFunction* stat = node->as()) - { - uint8_t var = allocReg(stat, 1); - - pushLocal(stat->name, var); - compileExprFunction(stat->func, var); - - Local& l = locals[stat->name]; - - // we *have* to pushLocal before we compile the function, since the function may refer to the local as an upvalue - // however, this means the debugpc for the local is at an instruction where the local value hasn't been computed yet - // to fix this we just move the debugpc after the local value is established - l.debugpc = bytecode.getDebugPC(); - } - else if (node->is()) - { - // do nothing - } - else - { - LUAU_ASSERT(!"Unknown statement type"); - } - } - - void validateContinueUntil(AstStat* cont, AstExpr* condition, AstStatBlock* body, size_t start) - { - UndefinedLocalVisitor visitor(this); - - for (size_t i = start; i < body->body.size; ++i) - { - if (AstStatLocal* stat = body->body.data[i]->as()) - { - for (AstLocal* local : stat->vars) - visitor.locals.insert(local); - } - else if (AstStatLocalFunction* stat = body->body.data[i]->as()) - { - visitor.locals.insert(stat->name); - } - } - - condition->visit(&visitor); - - if (visitor.undef) - CompileError::raise(condition->location, - "Local %s used in the repeat..until condition is undefined because continue statement on line %d jumps over it", - visitor.undef->name.value, cont->location.begin.line + 1); - } - - void gatherConstUpvals(AstExprFunction* func) - { - ConstUpvalueVisitor visitor(this); - func->body->visit(&visitor); - - for (AstLocal* local : visitor.upvals) - getUpval(local); - } - - void pushLocal(AstLocal* local, uint8_t reg) - { - if (localStack.size() >= kMaxLocalCount) - CompileError::raise( - local->location, "Out of local registers when trying to allocate %s: exceeded limit %d", local->name.value, kMaxLocalCount); - - localStack.push_back(local); - - Local& l = locals[local]; - - LUAU_ASSERT(!l.allocated); - - l.reg = reg; - l.allocated = true; - l.debugpc = bytecode.getDebugPC(); - } - - bool areLocalsCaptured(size_t start) - { - LUAU_ASSERT(start <= localStack.size()); - - for (size_t i = start; i < localStack.size(); ++i) - { - Local* l = locals.find(localStack[i]); - LUAU_ASSERT(l); - - if (l->captured) - return true; - } - - return false; - } - - void closeLocals(size_t start) - { - LUAU_ASSERT(start <= localStack.size()); - - bool captured = false; - uint8_t captureReg = 255; - - for (size_t i = start; i < localStack.size(); ++i) - { - Local* l = locals.find(localStack[i]); - LUAU_ASSERT(l); - - if (l->captured) - { - captured = true; - captureReg = std::min(captureReg, l->reg); - } - } - - if (captured) - { - bytecode.emitABC(LOP_CLOSEUPVALS, captureReg, 0, 0); - } - } - - void popLocals(size_t start) - { - LUAU_ASSERT(start <= localStack.size()); - - for (size_t i = start; i < localStack.size(); ++i) - { - Local* l = locals.find(localStack[i]); - LUAU_ASSERT(l); - LUAU_ASSERT(l->allocated); - - l->allocated = false; - - if (options.debugLevel >= 2) - { - uint32_t debugpc = bytecode.getDebugPC(); - - bytecode.pushDebugLocal(sref(localStack[i]->name), l->reg, l->debugpc, debugpc); - } - } - - localStack.resize(start); - } - - void patchJump(AstNode* node, size_t label, size_t target) - { - if (!bytecode.patchJumpD(label, target)) - CompileError::raise(node->location, "Exceeded jump distance limit; simplify the code to compile"); - } - - void patchJumps(AstNode* node, std::vector& labels, size_t target) - { - for (size_t l : labels) - patchJump(node, l, target); - } - - void patchLoopJumps(AstNode* node, size_t oldJumps, size_t endLabel, size_t contLabel) - { - LUAU_ASSERT(oldJumps <= loopJumps.size()); - - for (size_t i = oldJumps; i < loopJumps.size(); ++i) - { - const LoopJump& lj = loopJumps[i]; - - switch (lj.type) - { - case LoopJump::Break: - patchJump(node, lj.label, endLabel); - break; - - case LoopJump::Continue: - patchJump(node, lj.label, contLabel); - break; - - default: - LUAU_ASSERT(!"Unknown loop jump type"); - } - } - } - - uint8_t allocReg(AstNode* node, unsigned int count) - { - unsigned int top = regTop; - if (top + count > kMaxRegisterCount) - CompileError::raise(node->location, "Out of registers when trying to allocate %d registers: exceeded limit %d", count, kMaxRegisterCount); - - regTop += count; - stackSize = std::max(stackSize, regTop); - - return uint8_t(top); - } - - void setDebugLine(AstNode* node) - { - if (options.debugLevel >= 1) - bytecode.setDebugLine(node->location.begin.line + 1); - } - - void setDebugLine(const Location& location) - { - if (options.debugLevel >= 1) - bytecode.setDebugLine(location.begin.line + 1); - } - - void setDebugLineEnd(AstNode* node) - { - if (options.debugLevel >= 1) - bytecode.setDebugLine(node->location.end.line + 1); - } - - bool needsCoverage(AstNode* node) - { - return !node->is() && !node->is(); - } - - struct FenvVisitor : AstVisitor - { - bool& getfenvUsed; - bool& setfenvUsed; - - FenvVisitor(bool& getfenvUsed, bool& setfenvUsed) - : getfenvUsed(getfenvUsed) - , setfenvUsed(setfenvUsed) - { - } - - bool visit(AstExprGlobal* node) override - { - if (node->name == "getfenv") - getfenvUsed = true; - if (node->name == "setfenv") - setfenvUsed = true; - - return false; - } - }; - - struct FunctionVisitor : AstVisitor - { - Compiler* self; - std::vector& functions; - bool hasTypes = false; - - FunctionVisitor(Compiler* self, std::vector& functions) - : self(self) - , functions(functions) - { - // preallocate the result; this works around std::vector's inefficient growth policy for small arrays - functions.reserve(16); - } - - bool visit(AstExprFunction* node) override - { - node->body->visit(this); - - for (AstLocal* arg : node->args) - hasTypes |= arg->annotation != nullptr; - - // this makes sure all functions that are used when compiling this one have been already added to the vector - functions.push_back(node); - - return false; - } - }; - - struct UndefinedLocalVisitor : AstVisitor - { - UndefinedLocalVisitor(Compiler* self) - : self(self) - , undef(nullptr) - , locals(nullptr) - { - } - - void check(AstLocal* local) - { - if (!undef && locals.contains(local)) - undef = local; - } - - bool visit(AstExprLocal* node) override - { - if (!node->upvalue) - check(node->local); - - return false; - } - - bool visit(AstExprFunction* node) override - { - const Function* f = self->functions.find(node); - LUAU_ASSERT(f); - - for (AstLocal* uv : f->upvals) - { - LUAU_ASSERT(uv->functionDepth < node->functionDepth); - - if (uv->functionDepth == node->functionDepth - 1) - check(uv); - } - - return false; - } - - Compiler* self; - AstLocal* undef; - DenseHashSet locals; - }; - - struct ConstUpvalueVisitor : AstVisitor - { - ConstUpvalueVisitor(Compiler* self) - : self(self) - { - } - - bool visit(AstExprLocal* node) override - { - if (node->upvalue && self->isConstant(node)) - { - upvals.push_back(node->local); - } - - return false; - } - - bool visit(AstExprFunction* node) override - { - // short-circuits the traversal to make it faster - return false; - } - - Compiler* self; - std::vector upvals; - }; - - struct ReturnVisitor : AstVisitor - { - Compiler* self; - bool returnsOne = true; - - ReturnVisitor(Compiler* self) - : self(self) - { - } - - bool visit(AstExpr* expr) override - { - return false; - } - - bool visit(AstStatReturn* stat) override - { - returnsOne &= stat->list.size == 1 && !self->isExprMultRet(stat->list.data[0]); - - return false; - } - }; - - struct RegScope - { - RegScope(Compiler* self) - : self(self) - , oldTop(self->regTop) - { - } - - // This ctor is useful to forcefully adjust the stack frame in case we know that registers after a certain point are scratch and can be - // discarded - RegScope(Compiler* self, unsigned int top) - : self(self) - , oldTop(self->regTop) - { - LUAU_ASSERT(top <= self->regTop); - self->regTop = top; - } - - ~RegScope() - { - self->regTop = oldTop; - } - - Compiler* self; - unsigned int oldTop; - }; - - struct Function - { - uint32_t id; - std::vector upvals; - - uint64_t costModel = 0; - unsigned int stackSize = 0; - bool canInline = false; - bool returnsOne = false; - }; - - struct Local - { - uint8_t reg = 0; - bool allocated = false; - bool captured = false; - uint32_t debugpc = 0; - }; - - struct LoopJump - { - enum Type - { - Break, - Continue - }; - - Type type; - size_t label; - }; - - struct Loop - { - size_t localOffset; - size_t localOffsetContinue; - - AstStatContinue* continueUsed; - }; - - struct InlineArg - { - AstLocal* local; - - uint8_t reg; - Constant value; - }; - - struct InlineFrame - { - AstExprFunction* func; - - size_t localOffset; - - uint8_t target; - uint8_t targetCount; - - std::vector returnJumps; - }; - - struct Capture - { - LuauCaptureType type; - uint8_t data; - }; - - BytecodeBuilder& bytecode; - - CompileOptions options; - - DenseHashMap functions; - DenseHashMap locals; - DenseHashMap globals; - DenseHashMap variables; - DenseHashMap constants; - DenseHashMap locstants; - DenseHashMap tableShapes; - DenseHashMap builtins; - DenseHashMap typeMap; - - const DenseHashMap* builtinsFold = nullptr; - bool builtinsFoldMathK = false; - - // compileFunction state, gets reset for every function - unsigned int regTop = 0; - unsigned int stackSize = 0; - bool hasLoops = false; - - bool getfenvUsed = false; - bool setfenvUsed = false; - - std::vector localStack; - std::vector upvals; - std::vector loopJumps; - std::vector loops; - std::vector inlineFrames; - std::vector captures; - std::vector> interpStrings; -}; - -void compileOrThrow(BytecodeBuilder& bytecode, const ParseResult& parseResult, const AstNameTable& names, const CompileOptions& inputOptions) -{ - LUAU_TIMETRACE_SCOPE("compileOrThrow", "Compiler"); - - LUAU_ASSERT(parseResult.root); - LUAU_ASSERT(parseResult.errors.empty()); - - CompileOptions options = inputOptions; - uint8_t mainFlags = 0; - - for (const HotComment& hc : parseResult.hotcomments) - { - if (hc.header && hc.content.compare(0, 9, "optimize ") == 0) - options.optimizationLevel = std::max(0, std::min(2, atoi(hc.content.c_str() + 9))); - - if (hc.header && hc.content == "native") - { - mainFlags |= LPF_NATIVE_MODULE; - options.optimizationLevel = 2; // note: this might be removed in the future in favor of --!optimize - } - } - - AstStatBlock* root = parseResult.root; - - Compiler compiler(bytecode, options); - - // since access to some global objects may result in values that change over time, we block imports from non-readonly tables - assignMutable(compiler.globals, names, options.mutableGlobals); - - // this pass analyzes mutability of locals/globals and associates locals with their initial values - trackValues(compiler.globals, compiler.variables, root); - - // this visitor tracks calls to getfenv/setfenv and disables some optimizations when they are found - if (options.optimizationLevel >= 1 && (names.get("getfenv").value || names.get("setfenv").value)) - { - Compiler::FenvVisitor fenvVisitor(compiler.getfenvUsed, compiler.setfenvUsed); - root->visit(&fenvVisitor); - } - - // builtin folding is enabled on optimization level 2 since we can't deoptimize folding at runtime - if (options.optimizationLevel >= 2 && (!compiler.getfenvUsed && !compiler.setfenvUsed)) - { - compiler.builtinsFold = &compiler.builtins; - - if (AstName math = names.get("math"); math.value && getGlobalState(compiler.globals, math) == Global::Default) - compiler.builtinsFoldMathK = true; - } - - if (options.optimizationLevel >= 1) - { - // this pass tracks which calls are builtins and can be compiled more efficiently - analyzeBuiltins(compiler.builtins, compiler.globals, compiler.variables, options, root); - - // this pass analyzes constantness of expressions - foldConstants(compiler.constants, compiler.variables, compiler.locstants, compiler.builtinsFold, compiler.builtinsFoldMathK, root); - - // this pass analyzes table assignments to estimate table shapes for initially empty tables - predictTableShapes(compiler.tableShapes, root); - } - - // gathers all functions with the invariant that all function references are to functions earlier in the list - // for example, function foo() return function() end end will result in two vector entries, [0] = anonymous and [1] = foo - std::vector functions; - Compiler::FunctionVisitor functionVisitor(&compiler, functions); - root->visit(&functionVisitor); - - // computes type information for all functions based on type annotations - if (functionVisitor.hasTypes) - buildTypeMap(compiler.typeMap, root, options.vectorType); - - for (AstExprFunction* expr : functions) - compiler.compileFunction(expr, 0); - - AstExprFunction main(root->location, /*generics= */ AstArray(), /*genericPacks= */ AstArray(), - /* self= */ nullptr, AstArray(), /* vararg= */ true, /* varargLocation= */ Luau::Location(), root, /* functionDepth= */ 0, - /* debugname= */ AstName()); - uint32_t mainid = compiler.compileFunction(&main, mainFlags); - - const Compiler::Function* mainf = compiler.functions.find(&main); - LUAU_ASSERT(mainf && mainf->upvals.empty()); - - bytecode.setMainFunction(mainid); - bytecode.finalize(); -} - -void compileOrThrow(BytecodeBuilder& bytecode, const std::string& source, const CompileOptions& options, const ParseOptions& parseOptions) -{ - Allocator allocator; - AstNameTable names(allocator); - ParseResult result = Parser::parse(source.c_str(), source.size(), names, allocator, parseOptions); - - if (!result.errors.empty()) - throw ParseErrors(result.errors); - - compileOrThrow(bytecode, result, names, options); -} - -std::string compile(const std::string& source, const CompileOptions& options, const ParseOptions& parseOptions, BytecodeEncoder* encoder) -{ - LUAU_TIMETRACE_SCOPE("compile", "Compiler"); - - Allocator allocator; - AstNameTable names(allocator); - ParseResult result = Parser::parse(source.c_str(), source.size(), names, allocator, parseOptions); - - if (!result.errors.empty()) - { - // Users of this function expect only a single error message - const Luau::ParseError& parseError = result.errors.front(); - std::string error = format(":%d: %s", parseError.getLocation().begin.line + 1, parseError.what()); - - return BytecodeBuilder::getError(error); - } - - try - { - BytecodeBuilder bcb(encoder); - compileOrThrow(bcb, result, names, options); - - return bcb.getBytecode(); - } - catch (CompileError& e) - { - std::string error = format(":%d: %s", e.getLocation().begin.line + 1, e.what()); - return BytecodeBuilder::getError(error); - } -} - -} // namespace Luau diff --git a/lib/luau/Compiler/src/ConstantFolding.cpp b/lib/luau/Compiler/src/ConstantFolding.cpp deleted file mode 100644 index 3b3f9dd..0000000 --- a/lib/luau/Compiler/src/ConstantFolding.cpp +++ /dev/null @@ -1,469 +0,0 @@ -// This file is part of the Luau programming language and is licensed under MIT License; see LICENSE.txt for details -#include "ConstantFolding.h" - -#include "BuiltinFolding.h" - -#include -#include - -namespace Luau -{ -namespace Compile -{ - -static bool constantsEqual(const Constant& la, const Constant& ra) -{ - LUAU_ASSERT(la.type != Constant::Type_Unknown && ra.type != Constant::Type_Unknown); - - switch (la.type) - { - case Constant::Type_Nil: - return ra.type == Constant::Type_Nil; - - case Constant::Type_Boolean: - return ra.type == Constant::Type_Boolean && la.valueBoolean == ra.valueBoolean; - - case Constant::Type_Number: - return ra.type == Constant::Type_Number && la.valueNumber == ra.valueNumber; - - case Constant::Type_Vector: - return ra.type == Constant::Type_Vector && la.valueVector[0] == ra.valueVector[0] && la.valueVector[1] == ra.valueVector[1] && - la.valueVector[2] == ra.valueVector[2] && la.valueVector[3] == ra.valueVector[3]; - - case Constant::Type_String: - return ra.type == Constant::Type_String && la.stringLength == ra.stringLength && memcmp(la.valueString, ra.valueString, la.stringLength) == 0; - - default: - LUAU_ASSERT(!"Unexpected constant type in comparison"); - return false; - } -} - -static void foldUnary(Constant& result, AstExprUnary::Op op, const Constant& arg) -{ - switch (op) - { - case AstExprUnary::Not: - if (arg.type != Constant::Type_Unknown) - { - result.type = Constant::Type_Boolean; - result.valueBoolean = !arg.isTruthful(); - } - break; - - case AstExprUnary::Minus: - if (arg.type == Constant::Type_Number) - { - result.type = Constant::Type_Number; - result.valueNumber = -arg.valueNumber; - } - break; - - case AstExprUnary::Len: - if (arg.type == Constant::Type_String) - { - result.type = Constant::Type_Number; - result.valueNumber = double(arg.stringLength); - } - break; - - default: - LUAU_ASSERT(!"Unexpected unary operation"); - } -} - -static void foldBinary(Constant& result, AstExprBinary::Op op, const Constant& la, const Constant& ra) -{ - switch (op) - { - case AstExprBinary::Add: - if (la.type == Constant::Type_Number && ra.type == Constant::Type_Number) - { - result.type = Constant::Type_Number; - result.valueNumber = la.valueNumber + ra.valueNumber; - } - break; - - case AstExprBinary::Sub: - if (la.type == Constant::Type_Number && ra.type == Constant::Type_Number) - { - result.type = Constant::Type_Number; - result.valueNumber = la.valueNumber - ra.valueNumber; - } - break; - - case AstExprBinary::Mul: - if (la.type == Constant::Type_Number && ra.type == Constant::Type_Number) - { - result.type = Constant::Type_Number; - result.valueNumber = la.valueNumber * ra.valueNumber; - } - break; - - case AstExprBinary::Div: - if (la.type == Constant::Type_Number && ra.type == Constant::Type_Number) - { - result.type = Constant::Type_Number; - result.valueNumber = la.valueNumber / ra.valueNumber; - } - break; - - case AstExprBinary::FloorDiv: - if (la.type == Constant::Type_Number && ra.type == Constant::Type_Number) - { - result.type = Constant::Type_Number; - result.valueNumber = floor(la.valueNumber / ra.valueNumber); - } - break; - - case AstExprBinary::Mod: - if (la.type == Constant::Type_Number && ra.type == Constant::Type_Number) - { - result.type = Constant::Type_Number; - result.valueNumber = la.valueNumber - floor(la.valueNumber / ra.valueNumber) * ra.valueNumber; - } - break; - - case AstExprBinary::Pow: - if (la.type == Constant::Type_Number && ra.type == Constant::Type_Number) - { - result.type = Constant::Type_Number; - result.valueNumber = pow(la.valueNumber, ra.valueNumber); - } - break; - - case AstExprBinary::Concat: - break; - - case AstExprBinary::CompareNe: - if (la.type != Constant::Type_Unknown && ra.type != Constant::Type_Unknown) - { - result.type = Constant::Type_Boolean; - result.valueBoolean = !constantsEqual(la, ra); - } - break; - - case AstExprBinary::CompareEq: - if (la.type != Constant::Type_Unknown && ra.type != Constant::Type_Unknown) - { - result.type = Constant::Type_Boolean; - result.valueBoolean = constantsEqual(la, ra); - } - break; - - case AstExprBinary::CompareLt: - if (la.type == Constant::Type_Number && ra.type == Constant::Type_Number) - { - result.type = Constant::Type_Boolean; - result.valueBoolean = la.valueNumber < ra.valueNumber; - } - break; - - case AstExprBinary::CompareLe: - if (la.type == Constant::Type_Number && ra.type == Constant::Type_Number) - { - result.type = Constant::Type_Boolean; - result.valueBoolean = la.valueNumber <= ra.valueNumber; - } - break; - - case AstExprBinary::CompareGt: - if (la.type == Constant::Type_Number && ra.type == Constant::Type_Number) - { - result.type = Constant::Type_Boolean; - result.valueBoolean = la.valueNumber > ra.valueNumber; - } - break; - - case AstExprBinary::CompareGe: - if (la.type == Constant::Type_Number && ra.type == Constant::Type_Number) - { - result.type = Constant::Type_Boolean; - result.valueBoolean = la.valueNumber >= ra.valueNumber; - } - break; - - case AstExprBinary::And: - if (la.type != Constant::Type_Unknown) - { - result = la.isTruthful() ? ra : la; - } - break; - - case AstExprBinary::Or: - if (la.type != Constant::Type_Unknown) - { - result = la.isTruthful() ? la : ra; - } - break; - - default: - LUAU_ASSERT(!"Unexpected binary operation"); - } -} - -struct ConstantVisitor : AstVisitor -{ - DenseHashMap& constants; - DenseHashMap& variables; - DenseHashMap& locals; - - const DenseHashMap* builtins; - bool foldMathK = false; - - bool wasEmpty = false; - - std::vector builtinArgs; - - ConstantVisitor(DenseHashMap& constants, DenseHashMap& variables, - DenseHashMap& locals, const DenseHashMap* builtins, bool foldMathK) - : constants(constants) - , variables(variables) - , locals(locals) - , builtins(builtins) - , foldMathK(foldMathK) - { - // since we do a single pass over the tree, if the initial state was empty we don't need to clear out old entries - wasEmpty = constants.empty() && locals.empty(); - } - - Constant analyze(AstExpr* node) - { - Constant result; - result.type = Constant::Type_Unknown; - - if (AstExprGroup* expr = node->as()) - { - result = analyze(expr->expr); - } - else if (node->is()) - { - result.type = Constant::Type_Nil; - } - else if (AstExprConstantBool* expr = node->as()) - { - result.type = Constant::Type_Boolean; - result.valueBoolean = expr->value; - } - else if (AstExprConstantNumber* expr = node->as()) - { - result.type = Constant::Type_Number; - result.valueNumber = expr->value; - } - else if (AstExprConstantString* expr = node->as()) - { - result.type = Constant::Type_String; - result.valueString = expr->value.data; - result.stringLength = unsigned(expr->value.size); - } - else if (AstExprLocal* expr = node->as()) - { - const Constant* l = locals.find(expr->local); - - if (l) - result = *l; - } - else if (node->is()) - { - // nope - } - else if (node->is()) - { - // nope - } - else if (AstExprCall* expr = node->as()) - { - analyze(expr->func); - - if (const int* bfid = builtins ? builtins->find(expr) : nullptr) - { - // since recursive calls to analyze() may reuse the vector we need to be careful and preserve existing contents - size_t offset = builtinArgs.size(); - bool canFold = true; - - builtinArgs.reserve(offset + expr->args.size); - - for (size_t i = 0; i < expr->args.size; ++i) - { - Constant ac = analyze(expr->args.data[i]); - - if (ac.type == Constant::Type_Unknown) - canFold = false; - else - builtinArgs.push_back(ac); - } - - if (canFold) - { - LUAU_ASSERT(builtinArgs.size() == offset + expr->args.size); - result = foldBuiltin(*bfid, builtinArgs.data() + offset, expr->args.size); - } - - builtinArgs.resize(offset); - } - else - { - for (size_t i = 0; i < expr->args.size; ++i) - analyze(expr->args.data[i]); - } - } - else if (AstExprIndexName* expr = node->as()) - { - analyze(expr->expr); - - if (foldMathK) - { - if (AstExprGlobal* eg = expr->expr->as(); eg && eg->name == "math") - { - result = foldBuiltinMath(expr->index); - } - } - } - else if (AstExprIndexExpr* expr = node->as()) - { - analyze(expr->expr); - analyze(expr->index); - } - else if (AstExprFunction* expr = node->as()) - { - // this is necessary to propagate constant information in all child functions - expr->body->visit(this); - } - else if (AstExprTable* expr = node->as()) - { - for (size_t i = 0; i < expr->items.size; ++i) - { - const AstExprTable::Item& item = expr->items.data[i]; - - if (item.key) - analyze(item.key); - - analyze(item.value); - } - } - else if (AstExprUnary* expr = node->as()) - { - Constant arg = analyze(expr->expr); - - if (arg.type != Constant::Type_Unknown) - foldUnary(result, expr->op, arg); - } - else if (AstExprBinary* expr = node->as()) - { - Constant la = analyze(expr->left); - Constant ra = analyze(expr->right); - - // note: ra doesn't need to be constant to fold and/or - if (la.type != Constant::Type_Unknown) - foldBinary(result, expr->op, la, ra); - } - else if (AstExprTypeAssertion* expr = node->as()) - { - Constant arg = analyze(expr->expr); - - result = arg; - } - else if (AstExprIfElse* expr = node->as()) - { - Constant cond = analyze(expr->condition); - Constant trueExpr = analyze(expr->trueExpr); - Constant falseExpr = analyze(expr->falseExpr); - - if (cond.type != Constant::Type_Unknown) - result = cond.isTruthful() ? trueExpr : falseExpr; - } - else if (AstExprInterpString* expr = node->as()) - { - for (AstExpr* expression : expr->expressions) - analyze(expression); - } - else - { - LUAU_ASSERT(!"Unknown expression type"); - } - - recordConstant(constants, node, result); - - return result; - } - - template - void recordConstant(DenseHashMap& map, T key, const Constant& value) - { - if (value.type != Constant::Type_Unknown) - map[key] = value; - else if (wasEmpty) - ; - else if (Constant* old = map.find(key)) - old->type = Constant::Type_Unknown; - } - - void recordValue(AstLocal* local, const Constant& value) - { - // note: we rely on trackValues to have been run before us - Variable* v = variables.find(local); - LUAU_ASSERT(v); - - if (!v->written) - { - v->constant = (value.type != Constant::Type_Unknown); - recordConstant(locals, local, value); - } - } - - bool visit(AstExpr* node) override - { - // note: we short-circuit the visitor traversal through any expression trees by returning false - // recursive traversal is happening inside analyze() which makes it easier to get the resulting value of the subexpression - analyze(node); - - return false; - } - - bool visit(AstStatLocal* node) override - { - // all values that align wrt indexing are simple - we just match them 1-1 - for (size_t i = 0; i < node->vars.size && i < node->values.size; ++i) - { - Constant arg = analyze(node->values.data[i]); - - recordValue(node->vars.data[i], arg); - } - - if (node->vars.size > node->values.size) - { - // if we have trailing variables, then depending on whether the last value is capable of returning multiple values - // (aka call or varargs), we either don't know anything about these vars, or we know they're nil - AstExpr* last = node->values.size ? node->values.data[node->values.size - 1] : nullptr; - bool multRet = last && (last->is() || last->is()); - - if (!multRet) - { - for (size_t i = node->values.size; i < node->vars.size; ++i) - { - Constant nil = {Constant::Type_Nil}; - recordValue(node->vars.data[i], nil); - } - } - } - else - { - // we can have more values than variables; in this case we still need to analyze them to make sure we do constant propagation inside - // them - for (size_t i = node->vars.size; i < node->values.size; ++i) - analyze(node->values.data[i]); - } - - return false; - } -}; - -void foldConstants(DenseHashMap& constants, DenseHashMap& variables, - DenseHashMap& locals, const DenseHashMap* builtins, bool foldMathK, AstNode* root) -{ - ConstantVisitor visitor{constants, variables, locals, builtins, foldMathK}; - root->visit(&visitor); -} - -} // namespace Compile -} // namespace Luau diff --git a/lib/luau/Compiler/src/ConstantFolding.h b/lib/luau/Compiler/src/ConstantFolding.h deleted file mode 100644 index b22b0bf..0000000 --- a/lib/luau/Compiler/src/ConstantFolding.h +++ /dev/null @@ -1,51 +0,0 @@ -// This file is part of the Luau programming language and is licensed under MIT License; see LICENSE.txt for details -#pragma once - -#include "ValueTracking.h" - -namespace Luau -{ -namespace Compile -{ - -struct Constant -{ - enum Type - { - Type_Unknown, - Type_Nil, - Type_Boolean, - Type_Number, - Type_Vector, - Type_String, - }; - - Type type = Type_Unknown; - unsigned int stringLength = 0; - - union - { - bool valueBoolean; - double valueNumber; - float valueVector[4]; - const char* valueString = nullptr; // length stored in stringLength - }; - - bool isTruthful() const - { - LUAU_ASSERT(type != Type_Unknown); - return type != Type_Nil && !(type == Type_Boolean && valueBoolean == false); - } - - AstArray getString() const - { - LUAU_ASSERT(type == Type_String); - return {valueString, stringLength}; - } -}; - -void foldConstants(DenseHashMap& constants, DenseHashMap& variables, - DenseHashMap& locals, const DenseHashMap* builtins, bool foldMathK, AstNode* root); - -} // namespace Compile -} // namespace Luau diff --git a/lib/luau/Compiler/src/CostModel.cpp b/lib/luau/Compiler/src/CostModel.cpp deleted file mode 100644 index 04adf3e..0000000 --- a/lib/luau/Compiler/src/CostModel.cpp +++ /dev/null @@ -1,416 +0,0 @@ -// This file is part of the Luau programming language and is licensed under MIT License; see LICENSE.txt for details -#include "CostModel.h" - -#include "Luau/Common.h" -#include "Luau/DenseHash.h" - -#include - -namespace Luau -{ -namespace Compile -{ - -inline uint64_t parallelAddSat(uint64_t x, uint64_t y) -{ - uint64_t r = x + y; - uint64_t s = r & 0x8080808080808080ull; // saturation mask - - return (r ^ s) | (s - (s >> 7)); -} - -static uint64_t parallelMulSat(uint64_t a, int b) -{ - int bs = (b < 127) ? b : 127; - - // multiply every other value by b, yielding 14-bit products - uint64_t l = bs * ((a >> 0) & 0x007f007f007f007full); - uint64_t h = bs * ((a >> 8) & 0x007f007f007f007full); - - // each product is 14-bit, so adding 32768-128 sets high bit iff the sum is 128 or larger without an overflow - uint64_t ls = l + 0x7f807f807f807f80ull; - uint64_t hs = h + 0x7f807f807f807f80ull; - - // we now merge saturation bits as well as low 7-bits of each product into one - uint64_t s = (hs & 0x8000800080008000ull) | ((ls & 0x8000800080008000ull) >> 8); - uint64_t r = ((h & 0x007f007f007f007full) << 8) | (l & 0x007f007f007f007full); - - // the low bits are now correct for values that didn't saturate, and we simply need to mask them if high bit is 1 - return r | (s - (s >> 7)); -} - -inline bool getNumber(AstExpr* node, double& result) -{ - // since constant model doesn't use constant folding atm, we perform the basic extraction that's sufficient to handle positive/negative literals - if (AstExprConstantNumber* ne = node->as()) - { - result = ne->value; - return true; - } - - if (AstExprUnary* ue = node->as(); ue && ue->op == AstExprUnary::Minus) - if (AstExprConstantNumber* ne = ue->expr->as()) - { - result = -ne->value; - return true; - } - - return false; -} - -struct Cost -{ - static const uint64_t kLiteral = ~0ull; - - // cost model: 8 bytes, where first byte is the baseline cost, and the next 7 bytes are discounts for when variable #i is constant - uint64_t model; - // constant mask: 8-byte 0xff mask; equal to all ff's for literals, for variables only byte #i (1+) is set to align with model - uint64_t constant; - - Cost(int cost = 0, uint64_t constant = 0) - : model(cost < 0x7f ? cost : 0x7f) - , constant(constant) - { - } - - Cost operator+(const Cost& other) const - { - Cost result; - result.model = parallelAddSat(model, other.model); - return result; - } - - Cost& operator+=(const Cost& other) - { - model = parallelAddSat(model, other.model); - constant = 0; - return *this; - } - - Cost operator*(int other) const - { - Cost result; - result.model = parallelMulSat(model, other); - return result; - } - - static Cost fold(const Cost& x, const Cost& y) - { - uint64_t newmodel = parallelAddSat(x.model, y.model); - uint64_t newconstant = x.constant & y.constant; - - // the extra cost for folding is 1; the discount is 1 for the variable that is shared by x&y (or whichever one is used in x/y if the other is - // literal) - uint64_t extra = (newconstant == kLiteral) ? 0 : (1 | (0x0101010101010101ull & newconstant)); - - Cost result; - result.model = parallelAddSat(newmodel, extra); - result.constant = newconstant; - - return result; - } -}; - -struct CostVisitor : AstVisitor -{ - const DenseHashMap& builtins; - - DenseHashMap vars; - Cost result; - - CostVisitor(const DenseHashMap& builtins) - : builtins(builtins) - , vars(nullptr) - { - } - - Cost model(AstExpr* node) - { - if (AstExprGroup* expr = node->as()) - { - return model(expr->expr); - } - else if (node->is() || node->is() || node->is() || - node->is()) - { - return Cost(0, Cost::kLiteral); - } - else if (AstExprLocal* expr = node->as()) - { - const uint64_t* i = vars.find(expr->local); - - return Cost(0, i ? *i : 0); // locals typically don't require extra instructions to compute - } - else if (node->is()) - { - return 1; - } - else if (node->is()) - { - return 3; - } - else if (AstExprCall* expr = node->as()) - { - // builtin cost modeling is different from regular calls because we use FASTCALL to compile these - // thus we use a cheaper baseline, don't account for function, and assume constant/local copy is free - bool builtin = builtins.find(expr) != nullptr; - bool builtinShort = builtin && expr->args.size <= 2; // FASTCALL1/2 - - Cost cost = builtin ? 2 : 3; - - if (!builtin) - cost += model(expr->func); - - for (size_t i = 0; i < expr->args.size; ++i) - { - Cost ac = model(expr->args.data[i]); - // for constants/locals we still need to copy them to the argument list - cost += ac.model == 0 && !builtinShort ? Cost(1) : ac; - } - - return cost; - } - else if (AstExprIndexName* expr = node->as()) - { - return model(expr->expr) + 1; - } - else if (AstExprIndexExpr* expr = node->as()) - { - return model(expr->expr) + model(expr->index) + 1; - } - else if (AstExprFunction* expr = node->as()) - { - return 10; // high baseline cost due to allocation - } - else if (AstExprTable* expr = node->as()) - { - Cost cost = 10; // high baseline cost due to allocation - - for (size_t i = 0; i < expr->items.size; ++i) - { - const AstExprTable::Item& item = expr->items.data[i]; - - if (item.key) - cost += model(item.key); - - cost += model(item.value); - cost += 1; - } - - return cost; - } - else if (AstExprUnary* expr = node->as()) - { - return Cost::fold(model(expr->expr), Cost(0, Cost::kLiteral)); - } - else if (AstExprBinary* expr = node->as()) - { - return Cost::fold(model(expr->left), model(expr->right)); - } - else if (AstExprTypeAssertion* expr = node->as()) - { - return model(expr->expr); - } - else if (AstExprIfElse* expr = node->as()) - { - return model(expr->condition) + model(expr->trueExpr) + model(expr->falseExpr) + 2; - } - else if (AstExprInterpString* expr = node->as()) - { - // Baseline cost of string.format - Cost cost = 3; - - for (AstExpr* innerExpression : expr->expressions) - cost += model(innerExpression); - - return cost; - } - else - { - LUAU_ASSERT(!"Unknown expression type"); - return {}; - } - } - - void assign(AstExpr* expr) - { - // variable assignments reset variable mask, so that further uses of this variable aren't discounted - // this doesn't work perfectly with backwards control flow like loops, but is good enough for a single pass - if (AstExprLocal* lv = expr->as()) - if (uint64_t* i = vars.find(lv->local)) - *i = 0; - } - - void loop(AstStatBlock* body, Cost iterCost, int factor = 3) - { - Cost before = result; - - result = Cost(); - body->visit(this); - - result = before + (result + iterCost) * factor; - } - - bool visit(AstExpr* node) override - { - // note: we short-circuit the visitor traversal through any expression trees by returning false - // recursive traversal is happening inside model() which makes it easier to get the resulting value of the subexpression - result += model(node); - - return false; - } - - bool visit(AstStatFor* node) override - { - result += model(node->from); - result += model(node->to); - - if (node->step) - result += model(node->step); - - int tripCount = -1; - double from, to, step = 1; - if (getNumber(node->from, from) && getNumber(node->to, to) && (!node->step || getNumber(node->step, step))) - tripCount = getTripCount(from, to, step); - - loop(node->body, 1, tripCount < 0 ? 3 : tripCount); - return false; - } - - bool visit(AstStatForIn* node) override - { - for (size_t i = 0; i < node->values.size; ++i) - result += model(node->values.data[i]); - - loop(node->body, 1); - return false; - } - - bool visit(AstStatWhile* node) override - { - Cost condition = model(node->condition); - - loop(node->body, condition); - return false; - } - - bool visit(AstStatRepeat* node) override - { - Cost condition = model(node->condition); - - loop(node->body, condition); - return false; - } - - bool visit(AstStatIf* node) override - { - // unconditional 'else' may require a jump after the 'if' body - // note: this ignores cases when 'then' always terminates and also assumes comparison requires an extra instruction which may be false - result += 1 + (node->elsebody && !node->elsebody->is()); - - return true; - } - - bool visit(AstStatLocal* node) override - { - for (size_t i = 0; i < node->values.size; ++i) - { - Cost arg = model(node->values.data[i]); - - // propagate constant mask from expression through variables - if (arg.constant && i < node->vars.size) - vars[node->vars.data[i]] = arg.constant; - - result += arg; - } - - return false; - } - - bool visit(AstStatAssign* node) override - { - for (size_t i = 0; i < node->vars.size; ++i) - assign(node->vars.data[i]); - - for (size_t i = 0; i < node->vars.size || i < node->values.size; ++i) - { - Cost ac; - if (i < node->vars.size) - ac += model(node->vars.data[i]); - if (i < node->values.size) - ac += model(node->values.data[i]); - // local->local or constant->local assignment is not free - result += ac.model == 0 ? Cost(1) : ac; - } - - return false; - } - - bool visit(AstStatCompoundAssign* node) override - { - assign(node->var); - - // if lhs is not a local, setting it requires an extra table operation - result += node->var->is() ? 1 : 2; - - return true; - } - - bool visit(AstStatBreak* node) override - { - result += 1; - - return false; - } - - bool visit(AstStatContinue* node) override - { - result += 1; - - return false; - } -}; - -uint64_t modelCost(AstNode* root, AstLocal* const* vars, size_t varCount, const DenseHashMap& builtins) -{ - CostVisitor visitor{builtins}; - for (size_t i = 0; i < varCount && i < 7; ++i) - visitor.vars[vars[i]] = 0xffull << (i * 8 + 8); - - root->visit(&visitor); - - return visitor.result.model; -} - -int computeCost(uint64_t model, const bool* varsConst, size_t varCount) -{ - int cost = int(model & 0x7f); - - // don't apply discounts to what is likely a saturated sum - if (cost == 0x7f) - return cost; - - for (size_t i = 0; i < varCount && i < 7; ++i) - cost -= int((model >> (i * 8 + 8)) & 0x7f) * varsConst[i]; - - return cost; -} - -int getTripCount(double from, double to, double step) -{ - // we compute trip count in integers because that way we know that the loop math (repeated addition) is precise - int fromi = (from >= -32767 && from <= 32767 && double(int(from)) == from) ? int(from) : INT_MIN; - int toi = (to >= -32767 && to <= 32767 && double(int(to)) == to) ? int(to) : INT_MIN; - int stepi = (step >= -32767 && step <= 32767 && double(int(step)) == step) ? int(step) : INT_MIN; - - if (fromi == INT_MIN || toi == INT_MIN || stepi == INT_MIN || stepi == 0) - return -1; - - if ((stepi < 0 && toi > fromi) || (stepi > 0 && toi < fromi)) - return 0; - - return (toi - fromi) / stepi + 1; -} - -} // namespace Compile -} // namespace Luau diff --git a/lib/luau/Compiler/src/CostModel.h b/lib/luau/Compiler/src/CostModel.h deleted file mode 100644 index e8f3e16..0000000 --- a/lib/luau/Compiler/src/CostModel.h +++ /dev/null @@ -1,22 +0,0 @@ -// This file is part of the Luau programming language and is licensed under MIT License; see LICENSE.txt for details -#pragma once - -#include "Luau/Ast.h" -#include "Luau/DenseHash.h" - -namespace Luau -{ -namespace Compile -{ - -// cost model: 8 bytes, where first byte is the baseline cost, and the next 7 bytes are discounts for when variable #i is constant -uint64_t modelCost(AstNode* root, AstLocal* const* vars, size_t varCount, const DenseHashMap& builtins); - -// cost is computed as B - sum(Di * Ci), where B is baseline cost, Di is the discount for each variable and Ci is 1 when variable #i is constant -int computeCost(uint64_t model, const bool* varsConst, size_t varCount); - -// get loop trip count or -1 if we can't compute it precisely -int getTripCount(double from, double to, double step); - -} // namespace Compile -} // namespace Luau diff --git a/lib/luau/Compiler/src/TableShape.cpp b/lib/luau/Compiler/src/TableShape.cpp deleted file mode 100644 index 5a866e8..0000000 --- a/lib/luau/Compiler/src/TableShape.cpp +++ /dev/null @@ -1,158 +0,0 @@ -// This file is part of the Luau programming language and is licensed under MIT License; see LICENSE.txt for details -#include "TableShape.h" - -namespace Luau -{ -namespace Compile -{ - -// conservative limit for the loop bound that establishes table array size -static const int kMaxLoopBound = 16; - -static AstExprTable* getTableHint(AstExpr* expr) -{ - // unadorned table literal - if (AstExprTable* table = expr->as()) - return table; - - // setmetatable(table literal, ...) - if (AstExprCall* call = expr->as(); call && !call->self && call->args.size == 2) - if (AstExprGlobal* func = call->func->as(); func && func->name == "setmetatable") - if (AstExprTable* table = call->args.data[0]->as()) - return table; - - return nullptr; -} - -struct ShapeVisitor : AstVisitor -{ - struct Hasher - { - size_t operator()(const std::pair& p) const - { - return DenseHashPointer()(p.first) ^ std::hash()(p.second); - } - }; - - DenseHashMap& shapes; - - DenseHashMap tables; - DenseHashSet, Hasher> fields; - - DenseHashMap loops; // iterator => upper bound for 1..k - - ShapeVisitor(DenseHashMap& shapes) - : shapes(shapes) - , tables(nullptr) - , fields(std::pair()) - , loops(nullptr) - { - } - - void assignField(AstExpr* expr, AstName index) - { - if (AstExprLocal* lv = expr->as()) - { - if (AstExprTable** table = tables.find(lv->local)) - { - std::pair field = {*table, index}; - - if (!fields.contains(field)) - { - fields.insert(field); - shapes[*table].hashSize += 1; - } - } - } - } - - void assignField(AstExpr* expr, AstExpr* index) - { - AstExprLocal* lv = expr->as(); - if (!lv) - return; - - AstExprTable** table = tables.find(lv->local); - if (!table) - return; - - if (AstExprConstantNumber* number = index->as()) - { - TableShape& shape = shapes[*table]; - - if (number->value == double(shape.arraySize + 1)) - shape.arraySize += 1; - } - else if (AstExprLocal* iter = index->as()) - { - if (const unsigned int* bound = loops.find(iter->local)) - { - TableShape& shape = shapes[*table]; - - if (shape.arraySize == 0) - shape.arraySize = *bound; - } - } - } - - void assign(AstExpr* var) - { - if (AstExprIndexName* index = var->as()) - { - assignField(index->expr, index->index); - } - else if (AstExprIndexExpr* index = var->as()) - { - assignField(index->expr, index->index); - } - } - - bool visit(AstStatLocal* node) override - { - // track local -> table association so that we can update table size prediction in assignField - if (node->vars.size == 1 && node->values.size == 1) - if (AstExprTable* table = getTableHint(node->values.data[0]); table && table->items.size == 0) - tables[node->vars.data[0]] = table; - - return true; - } - - bool visit(AstStatAssign* node) override - { - for (size_t i = 0; i < node->vars.size; ++i) - assign(node->vars.data[i]); - - for (size_t i = 0; i < node->values.size; ++i) - node->values.data[i]->visit(this); - - return false; - } - - bool visit(AstStatFunction* node) override - { - assign(node->name); - node->func->visit(this); - - return false; - } - - bool visit(AstStatFor* node) override - { - AstExprConstantNumber* from = node->from->as(); - AstExprConstantNumber* to = node->to->as(); - - if (from && to && from->value == 1.0 && to->value >= 1.0 && to->value <= double(kMaxLoopBound) && !node->step) - loops[node->var] = unsigned(to->value); - - return true; - } -}; - -void predictTableShapes(DenseHashMap& shapes, AstNode* root) -{ - ShapeVisitor visitor{shapes}; - root->visit(&visitor); -} - -} // namespace Compile -} // namespace Luau diff --git a/lib/luau/Compiler/src/TableShape.h b/lib/luau/Compiler/src/TableShape.h deleted file mode 100644 index f30853a..0000000 --- a/lib/luau/Compiler/src/TableShape.h +++ /dev/null @@ -1,21 +0,0 @@ -// This file is part of the Luau programming language and is licensed under MIT License; see LICENSE.txt for details -#pragma once - -#include "Luau/Ast.h" -#include "Luau/DenseHash.h" - -namespace Luau -{ -namespace Compile -{ - -struct TableShape -{ - unsigned int arraySize = 0; - unsigned int hashSize = 0; -}; - -void predictTableShapes(DenseHashMap& shapes, AstNode* root); - -} // namespace Compile -} // namespace Luau diff --git a/lib/luau/Compiler/src/Types.cpp b/lib/luau/Compiler/src/Types.cpp deleted file mode 100644 index bb89cd1..0000000 --- a/lib/luau/Compiler/src/Types.cpp +++ /dev/null @@ -1,233 +0,0 @@ -// This file is part of the Luau programming language and is licensed under MIT License; see LICENSE.txt for details -#include "Types.h" - -#include "Luau/BytecodeBuilder.h" - -LUAU_FASTFLAGVARIABLE(LuauCompileBufferAnnotation, false) - -namespace Luau -{ - -static bool isGeneric(AstName name, const AstArray& generics) -{ - for (const AstGenericType& gt : generics) - if (gt.name == name) - return true; - - return false; -} - -static LuauBytecodeType getPrimitiveType(AstName name) -{ - if (name == "nil") - return LBC_TYPE_NIL; - else if (name == "boolean") - return LBC_TYPE_BOOLEAN; - else if (name == "number") - return LBC_TYPE_NUMBER; - else if (name == "string") - return LBC_TYPE_STRING; - else if (name == "thread") - return LBC_TYPE_THREAD; - else if (FFlag::LuauCompileBufferAnnotation && name == "buffer") - return LBC_TYPE_BUFFER; - else if (name == "any" || name == "unknown") - return LBC_TYPE_ANY; - else - return LBC_TYPE_INVALID; -} - -static LuauBytecodeType getType(AstType* ty, const AstArray& generics, const DenseHashMap& typeAliases, - bool resolveAliases, const char* vectorType) -{ - if (AstTypeReference* ref = ty->as()) - { - if (ref->prefix) - return LBC_TYPE_ANY; - - if (AstStatTypeAlias* const* alias = typeAliases.find(ref->name); alias && *alias) - { - // note: we only resolve aliases to the depth of 1 to avoid dealing with recursive aliases - if (resolveAliases) - return getType((*alias)->type, (*alias)->generics, typeAliases, /* resolveAliases= */ false, vectorType); - else - return LBC_TYPE_ANY; - } - - if (isGeneric(ref->name, generics)) - return LBC_TYPE_ANY; - - if (vectorType && ref->name == vectorType) - return LBC_TYPE_VECTOR; - - if (LuauBytecodeType prim = getPrimitiveType(ref->name); prim != LBC_TYPE_INVALID) - return prim; - - // not primitive or alias or generic => host-provided, we assume userdata for now - return LBC_TYPE_USERDATA; - } - else if (AstTypeTable* table = ty->as()) - { - return LBC_TYPE_TABLE; - } - else if (AstTypeFunction* func = ty->as()) - { - return LBC_TYPE_FUNCTION; - } - else if (AstTypeUnion* un = ty->as()) - { - bool optional = false; - LuauBytecodeType type = LBC_TYPE_INVALID; - - for (AstType* ty : un->types) - { - LuauBytecodeType et = getType(ty, generics, typeAliases, resolveAliases, vectorType); - - if (et == LBC_TYPE_NIL) - { - optional = true; - continue; - } - - if (type == LBC_TYPE_INVALID) - { - type = et; - continue; - } - - if (type != et) - return LBC_TYPE_ANY; - } - - if (type == LBC_TYPE_INVALID) - return LBC_TYPE_ANY; - - return LuauBytecodeType(type | (optional && (type != LBC_TYPE_ANY) ? LBC_TYPE_OPTIONAL_BIT : 0)); - } - else if (AstTypeIntersection* inter = ty->as()) - { - return LBC_TYPE_ANY; - } - - return LBC_TYPE_ANY; -} - -static std::string getFunctionType(const AstExprFunction* func, const DenseHashMap& typeAliases, const char* vectorType) -{ - bool self = func->self != 0; - - std::string typeInfo; - typeInfo.reserve(func->args.size + self + 2); - - typeInfo.push_back(LBC_TYPE_FUNCTION); - typeInfo.push_back(uint8_t(self + func->args.size)); - - if (self) - typeInfo.push_back(LBC_TYPE_TABLE); - - bool haveNonAnyParam = false; - for (AstLocal* arg : func->args) - { - LuauBytecodeType ty = - arg->annotation ? getType(arg->annotation, func->generics, typeAliases, /* resolveAliases= */ true, vectorType) : LBC_TYPE_ANY; - - if (ty != LBC_TYPE_ANY) - haveNonAnyParam = true; - - typeInfo.push_back(ty); - } - - // If all parameters simplify to any, we can just omit type info for this function - if (!haveNonAnyParam) - return {}; - - return typeInfo; -} - -struct TypeMapVisitor : AstVisitor -{ - DenseHashMap& typeMap; - const char* vectorType; - - DenseHashMap typeAliases; - std::vector> typeAliasStack; - - TypeMapVisitor(DenseHashMap& typeMap, const char* vectorType) - : typeMap(typeMap) - , vectorType(vectorType) - , typeAliases(AstName()) - { - } - - size_t pushTypeAliases(AstStatBlock* block) - { - size_t aliasStackTop = typeAliasStack.size(); - - for (AstStat* stat : block->body) - if (AstStatTypeAlias* alias = stat->as()) - { - AstStatTypeAlias*& prevAlias = typeAliases[alias->name]; - - typeAliasStack.push_back(std::make_pair(alias->name, prevAlias)); - prevAlias = alias; - } - - return aliasStackTop; - } - - void popTypeAliases(size_t aliasStackTop) - { - while (typeAliasStack.size() > aliasStackTop) - { - std::pair& top = typeAliasStack.back(); - - typeAliases[top.first] = top.second; - typeAliasStack.pop_back(); - } - } - - bool visit(AstStatBlock* node) override - { - size_t aliasStackTop = pushTypeAliases(node); - - for (AstStat* stat : node->body) - stat->visit(this); - - popTypeAliases(aliasStackTop); - - return false; - } - - // repeat..until scoping rules are such that condition (along with any possible functions declared in it) has aliases from repeat body in scope - bool visit(AstStatRepeat* node) override - { - size_t aliasStackTop = pushTypeAliases(node->body); - - for (AstStat* stat : node->body->body) - stat->visit(this); - - node->condition->visit(this); - - popTypeAliases(aliasStackTop); - - return false; - } - - bool visit(AstExprFunction* node) override - { - std::string type = getFunctionType(node, typeAliases, vectorType); - - if (!type.empty()) - typeMap[node] = std::move(type); - - return true; - } -}; - -void buildTypeMap(DenseHashMap& typeMap, AstNode* root, const char* vectorType) -{ - TypeMapVisitor visitor(typeMap, vectorType); - root->visit(&visitor); -} - -} // namespace Luau diff --git a/lib/luau/Compiler/src/Types.h b/lib/luau/Compiler/src/Types.h deleted file mode 100644 index 62f9e91..0000000 --- a/lib/luau/Compiler/src/Types.h +++ /dev/null @@ -1,14 +0,0 @@ -// This file is part of the Luau programming language and is licensed under MIT License; see LICENSE.txt for details -#pragma once - -#include "Luau/Ast.h" -#include "Luau/DenseHash.h" - -#include - -namespace Luau -{ - -void buildTypeMap(DenseHashMap& typeMap, AstNode* root, const char* vectorType); - -} // namespace Luau diff --git a/lib/luau/Compiler/src/ValueTracking.cpp b/lib/luau/Compiler/src/ValueTracking.cpp deleted file mode 100644 index 616fca9..0000000 --- a/lib/luau/Compiler/src/ValueTracking.cpp +++ /dev/null @@ -1,103 +0,0 @@ -// This file is part of the Luau programming language and is licensed under MIT License; see LICENSE.txt for details -#include "ValueTracking.h" - -#include "Luau/Lexer.h" - -namespace Luau -{ -namespace Compile -{ - -struct ValueVisitor : AstVisitor -{ - DenseHashMap& globals; - DenseHashMap& variables; - - ValueVisitor(DenseHashMap& globals, DenseHashMap& variables) - : globals(globals) - , variables(variables) - { - } - - void assign(AstExpr* var) - { - if (AstExprLocal* lv = var->as()) - { - variables[lv->local].written = true; - } - else if (AstExprGlobal* gv = var->as()) - { - globals[gv->name] = Global::Written; - } - else - { - // we need to be able to track assignments in all expressions, including crazy ones like t[function() t = nil end] = 5 - var->visit(this); - } - } - - bool visit(AstStatLocal* node) override - { - for (size_t i = 0; i < node->vars.size && i < node->values.size; ++i) - variables[node->vars.data[i]].init = node->values.data[i]; - - for (size_t i = node->values.size; i < node->vars.size; ++i) - variables[node->vars.data[i]].init = nullptr; - - return true; - } - - bool visit(AstStatAssign* node) override - { - for (size_t i = 0; i < node->vars.size; ++i) - assign(node->vars.data[i]); - - for (size_t i = 0; i < node->values.size; ++i) - node->values.data[i]->visit(this); - - return false; - } - - bool visit(AstStatCompoundAssign* node) override - { - assign(node->var); - node->value->visit(this); - - return false; - } - - bool visit(AstStatLocalFunction* node) override - { - variables[node->name].init = node->func; - - return true; - } - - bool visit(AstStatFunction* node) override - { - assign(node->name); - node->func->visit(this); - - return false; - } -}; - -void assignMutable(DenseHashMap& globals, const AstNameTable& names, const char* const* mutableGlobals) -{ - if (AstName name = names.get("_G"); name.value) - globals[name] = Global::Mutable; - - if (mutableGlobals) - for (const char* const* ptr = mutableGlobals; *ptr; ++ptr) - if (AstName name = names.get(*ptr); name.value) - globals[name] = Global::Mutable; -} - -void trackValues(DenseHashMap& globals, DenseHashMap& variables, AstNode* root) -{ - ValueVisitor visitor{globals, variables}; - root->visit(&visitor); -} - -} // namespace Compile -} // namespace Luau diff --git a/lib/luau/Compiler/src/ValueTracking.h b/lib/luau/Compiler/src/ValueTracking.h deleted file mode 100644 index f8ecc6b..0000000 --- a/lib/luau/Compiler/src/ValueTracking.h +++ /dev/null @@ -1,42 +0,0 @@ -// This file is part of the Luau programming language and is licensed under MIT License; see LICENSE.txt for details -#pragma once - -#include "Luau/Ast.h" -#include "Luau/DenseHash.h" - -namespace Luau -{ -class AstNameTable; -} - -namespace Luau -{ -namespace Compile -{ - -enum class Global -{ - Default = 0, - Mutable, // builtin that has contents unknown at compile time, blocks GETIMPORT for chains - Written, // written in the code which means we can't reason about the value -}; - -struct Variable -{ - AstExpr* init = nullptr; // initial value of the variable; filled by trackValues - bool written = false; // is the variable ever assigned to? filled by trackValues - bool constant = false; // is the variable's value a compile-time constant? filled by constantFold -}; - -void assignMutable(DenseHashMap& globals, const AstNameTable& names, const char* const* mutableGlobals); -void trackValues(DenseHashMap& globals, DenseHashMap& variables, AstNode* root); - -inline Global getGlobalState(const DenseHashMap& globals, AstName name) -{ - const Global* it = globals.find(name); - - return it ? *it : Global::Default; -} - -} // namespace Compile -} // namespace Luau diff --git a/lib/luau/Compiler/src/lcode.cpp b/lib/luau/Compiler/src/lcode.cpp deleted file mode 100644 index ee150b1..0000000 --- a/lib/luau/Compiler/src/lcode.cpp +++ /dev/null @@ -1,29 +0,0 @@ -// This file is part of the Luau programming language and is licensed under MIT License; see LICENSE.txt for details -#include "luacode.h" - -#include "Luau/Compiler.h" - -#include - -char* luau_compile(const char* source, size_t size, lua_CompileOptions* options, size_t* outsize) -{ - LUAU_ASSERT(outsize); - - Luau::CompileOptions opts; - - if (options) - { - static_assert(sizeof(lua_CompileOptions) == sizeof(Luau::CompileOptions), "C and C++ interface must match"); - memcpy(static_cast(&opts), options, sizeof(opts)); - } - - std::string result = compile(std::string(source, size), opts); - - char* copy = static_cast(malloc(result.size())); - if (!copy) - return nullptr; - - memcpy(copy, result.data(), result.size()); - *outsize = result.size(); - return copy; -} diff --git a/lib/luau/LICENSE.txt b/lib/luau/LICENSE.txt deleted file mode 100644 index 34496ce..0000000 --- a/lib/luau/LICENSE.txt +++ /dev/null @@ -1,22 +0,0 @@ -MIT License - -Copyright (c) 2019-2023 Roblox Corporation -Copyright (c) 1994–2019 Lua.org, PUC-Rio. - -Permission is hereby granted, free of charge, to any person obtaining a copy of -this software and associated documentation files (the "Software"), to deal in -the Software without restriction, including without limitation the rights to -use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies -of the Software, and to permit persons to whom the Software is furnished to do -so, subject to the following conditions: - -The above copyright notice and this permission notice shall be included in all -copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE -SOFTWARE. diff --git a/lib/luau/VM/include/lua.h b/lib/luau/VM/include/lua.h deleted file mode 100644 index 0390de7..0000000 --- a/lib/luau/VM/include/lua.h +++ /dev/null @@ -1,480 +0,0 @@ -// This file is part of the Luau programming language and is licensed under MIT License; see LICENSE.txt for details -// This code is based on Lua 5.x implementation licensed under MIT License; see lua_LICENSE.txt for details -#pragma once - -#include -#include -#include - -#include "luaconf.h" - - - - -// option for multiple returns in `lua_pcall' and `lua_call' -#define LUA_MULTRET (-1) - -/* -** pseudo-indices -*/ -#define LUA_REGISTRYINDEX (-LUAI_MAXCSTACK - 2000) -#define LUA_ENVIRONINDEX (-LUAI_MAXCSTACK - 2001) -#define LUA_GLOBALSINDEX (-LUAI_MAXCSTACK - 2002) -#define lua_upvalueindex(i) (LUA_GLOBALSINDEX - (i)) -#define lua_ispseudo(i) ((i) <= LUA_REGISTRYINDEX) - -// thread status; 0 is OK -enum lua_Status -{ - LUA_OK = 0, - LUA_YIELD, - LUA_ERRRUN, - LUA_ERRSYNTAX, // legacy error code, preserved for compatibility - LUA_ERRMEM, - LUA_ERRERR, - LUA_BREAK, // yielded for a debug breakpoint -}; - -enum lua_CoStatus -{ - LUA_CORUN = 0, // running - LUA_COSUS, // suspended - LUA_CONOR, // 'normal' (it resumed another coroutine) - LUA_COFIN, // finished - LUA_COERR, // finished with error -}; - -typedef struct lua_State lua_State; - -typedef int (*lua_CFunction)(lua_State* L); -typedef int (*lua_Continuation)(lua_State* L, int status); - -/* -** prototype for memory-allocation functions -*/ - -typedef void* (*lua_Alloc)(void* ud, void* ptr, size_t osize, size_t nsize); - -// non-return type -#define l_noret void LUA_NORETURN - -/* -** basic types -*/ -#define LUA_TNONE (-1) - -/* - * WARNING: if you change the order of this enumeration, - * grep "ORDER TYPE" - */ -// clang-format off -enum lua_Type -{ - LUA_TNIL = 0, // must be 0 due to lua_isnoneornil - LUA_TBOOLEAN = 1, // must be 1 due to l_isfalse - - - LUA_TLIGHTUSERDATA, - LUA_TNUMBER, - LUA_TVECTOR, - - LUA_TSTRING, // all types above this must be value types, all types below this must be GC types - see iscollectable - - - LUA_TTABLE, - LUA_TFUNCTION, - LUA_TUSERDATA, - LUA_TTHREAD, - LUA_TBUFFER, - - // values below this line are used in GCObject tags but may never show up in TValue type tags - LUA_TPROTO, - LUA_TUPVAL, - LUA_TDEADKEY, - - // the count of TValue type tags - LUA_T_COUNT = LUA_TPROTO -}; -// clang-format on - -// type of numbers in Luau -typedef double lua_Number; - -// type for integer functions -typedef int lua_Integer; - -// unsigned integer type -typedef unsigned lua_Unsigned; - -/* -** state manipulation -*/ -LUA_API lua_State* lua_newstate(lua_Alloc f, void* ud); -LUA_API void lua_close(lua_State* L); -LUA_API lua_State* lua_newthread(lua_State* L); -LUA_API lua_State* lua_mainthread(lua_State* L); -LUA_API void lua_resetthread(lua_State* L); -LUA_API int lua_isthreadreset(lua_State* L); - -/* -** basic stack manipulation -*/ -LUA_API int lua_absindex(lua_State* L, int idx); -LUA_API int lua_gettop(lua_State* L); -LUA_API void lua_settop(lua_State* L, int idx); -LUA_API void lua_pushvalue(lua_State* L, int idx); -LUA_API void lua_remove(lua_State* L, int idx); -LUA_API void lua_insert(lua_State* L, int idx); -LUA_API void lua_replace(lua_State* L, int idx); -LUA_API int lua_checkstack(lua_State* L, int sz); -LUA_API void lua_rawcheckstack(lua_State* L, int sz); // allows for unlimited stack frames - -LUA_API void lua_xmove(lua_State* from, lua_State* to, int n); -LUA_API void lua_xpush(lua_State* from, lua_State* to, int idx); - -/* -** access functions (stack -> C) -*/ - -LUA_API int lua_isnumber(lua_State* L, int idx); -LUA_API int lua_isstring(lua_State* L, int idx); -LUA_API int lua_iscfunction(lua_State* L, int idx); -LUA_API int lua_isLfunction(lua_State* L, int idx); -LUA_API int lua_isuserdata(lua_State* L, int idx); -LUA_API int lua_type(lua_State* L, int idx); -LUA_API const char* lua_typename(lua_State* L, int tp); - -LUA_API int lua_equal(lua_State* L, int idx1, int idx2); -LUA_API int lua_rawequal(lua_State* L, int idx1, int idx2); -LUA_API int lua_lessthan(lua_State* L, int idx1, int idx2); - -LUA_API double lua_tonumberx(lua_State* L, int idx, int* isnum); -LUA_API int lua_tointegerx(lua_State* L, int idx, int* isnum); -LUA_API unsigned lua_tounsignedx(lua_State* L, int idx, int* isnum); -LUA_API const float* lua_tovector(lua_State* L, int idx); -LUA_API int lua_toboolean(lua_State* L, int idx); -LUA_API const char* lua_tolstring(lua_State* L, int idx, size_t* len); -LUA_API const char* lua_tostringatom(lua_State* L, int idx, int* atom); -LUA_API const char* lua_namecallatom(lua_State* L, int* atom); -LUA_API int lua_objlen(lua_State* L, int idx); -LUA_API lua_CFunction lua_tocfunction(lua_State* L, int idx); -LUA_API void* lua_tolightuserdata(lua_State* L, int idx); -LUA_API void* lua_tolightuserdatatagged(lua_State* L, int idx, int tag); -LUA_API void* lua_touserdata(lua_State* L, int idx); -LUA_API void* lua_touserdatatagged(lua_State* L, int idx, int tag); -LUA_API int lua_userdatatag(lua_State* L, int idx); -LUA_API int lua_lightuserdatatag(lua_State* L, int idx); -LUA_API lua_State* lua_tothread(lua_State* L, int idx); -LUA_API void* lua_tobuffer(lua_State* L, int idx, size_t* len); -LUA_API const void* lua_topointer(lua_State* L, int idx); - -/* -** push functions (C -> stack) -*/ -LUA_API void lua_pushnil(lua_State* L); -LUA_API void lua_pushnumber(lua_State* L, double n); -LUA_API void lua_pushinteger(lua_State* L, int n); -LUA_API void lua_pushunsigned(lua_State* L, unsigned n); -#if LUA_VECTOR_SIZE == 4 -LUA_API void lua_pushvector(lua_State* L, float x, float y, float z, float w); -#else -LUA_API void lua_pushvector(lua_State* L, float x, float y, float z); -#endif -LUA_API void lua_pushlstring(lua_State* L, const char* s, size_t l); -LUA_API void lua_pushstring(lua_State* L, const char* s); -LUA_API const char* lua_pushvfstring(lua_State* L, const char* fmt, va_list argp); -LUA_API LUA_PRINTF_ATTR(2, 3) const char* lua_pushfstringL(lua_State* L, const char* fmt, ...); -LUA_API void lua_pushcclosurek(lua_State* L, lua_CFunction fn, const char* debugname, int nup, lua_Continuation cont); -LUA_API void lua_pushboolean(lua_State* L, int b); -LUA_API int lua_pushthread(lua_State* L); - -LUA_API void lua_pushlightuserdatatagged(lua_State* L, void* p, int tag); -LUA_API void* lua_newuserdatatagged(lua_State* L, size_t sz, int tag); -LUA_API void* lua_newuserdatadtor(lua_State* L, size_t sz, void (*dtor)(void*)); - -LUA_API void* lua_newbuffer(lua_State* L, size_t sz); - -/* -** get functions (Lua -> stack) -*/ -LUA_API int lua_gettable(lua_State* L, int idx); -LUA_API int lua_getfield(lua_State* L, int idx, const char* k); -LUA_API int lua_rawgetfield(lua_State* L, int idx, const char* k); -LUA_API int lua_rawget(lua_State* L, int idx); -LUA_API int lua_rawgeti(lua_State* L, int idx, int n); -LUA_API void lua_createtable(lua_State* L, int narr, int nrec); - -LUA_API void lua_setreadonly(lua_State* L, int idx, int enabled); -LUA_API int lua_getreadonly(lua_State* L, int idx); -LUA_API void lua_setsafeenv(lua_State* L, int idx, int enabled); - -LUA_API int lua_getmetatable(lua_State* L, int objindex); -LUA_API void lua_getfenv(lua_State* L, int idx); - -/* -** set functions (stack -> Lua) -*/ -LUA_API void lua_settable(lua_State* L, int idx); -LUA_API void lua_setfield(lua_State* L, int idx, const char* k); -LUA_API void lua_rawsetfield(lua_State* L, int idx, const char* k); -LUA_API void lua_rawset(lua_State* L, int idx); -LUA_API void lua_rawseti(lua_State* L, int idx, int n); -LUA_API int lua_setmetatable(lua_State* L, int objindex); -LUA_API int lua_setfenv(lua_State* L, int idx); - -/* -** `load' and `call' functions (load and run Luau bytecode) -*/ -LUA_API int luau_load(lua_State* L, const char* chunkname, const char* data, size_t size, int env); -LUA_API void lua_call(lua_State* L, int nargs, int nresults); -LUA_API int lua_pcall(lua_State* L, int nargs, int nresults, int errfunc); - -/* -** coroutine functions -*/ -LUA_API int lua_yield(lua_State* L, int nresults); -LUA_API int lua_break(lua_State* L); -LUA_API int lua_resume(lua_State* L, lua_State* from, int narg); -LUA_API int lua_resumeerror(lua_State* L, lua_State* from); -LUA_API int lua_status(lua_State* L); -LUA_API int lua_isyieldable(lua_State* L); -LUA_API void* lua_getthreaddata(lua_State* L); -LUA_API void lua_setthreaddata(lua_State* L, void* data); -LUA_API int lua_costatus(lua_State* L, lua_State* co); - -/* -** garbage-collection function and options -*/ - -enum lua_GCOp -{ - // stop and resume incremental garbage collection - LUA_GCSTOP, - LUA_GCRESTART, - - // run a full GC cycle; not recommended for latency sensitive applications - LUA_GCCOLLECT, - - // return the heap size in KB and the remainder in bytes - LUA_GCCOUNT, - LUA_GCCOUNTB, - - // return 1 if GC is active (not stopped); note that GC may not be actively collecting even if it's running - LUA_GCISRUNNING, - - /* - ** perform an explicit GC step, with the step size specified in KB - ** - ** garbage collection is handled by 'assists' that perform some amount of GC work matching pace of allocation - ** explicit GC steps allow to perform some amount of work at custom points to offset the need for GC assists - ** note that GC might also be paused for some duration (until bytes allocated meet the threshold) - ** if an explicit step is performed during this pause, it will trigger the start of the next collection cycle - */ - LUA_GCSTEP, - - /* - ** tune GC parameters G (goal), S (step multiplier) and step size (usually best left ignored) - ** - ** garbage collection is incremental and tries to maintain the heap size to balance memory and performance overhead - ** this overhead is determined by G (goal) which is the ratio between total heap size and the amount of live data in it - ** G is specified in percentages; by default G=200% which means that the heap is allowed to grow to ~2x the size of live data. - ** - ** collector tries to collect S% of allocated bytes by interrupting the application after step size bytes were allocated. - ** when S is too small, collector may not be able to catch up and the effective goal that can be reached will be larger. - ** S is specified in percentages; by default S=200% which means that collector will run at ~2x the pace of allocations. - ** - ** it is recommended to set S in the interval [100 / (G - 100), 100 + 100 / (G - 100))] with a minimum value of 150%; for example: - ** - for G=200%, S should be in the interval [150%, 200%] - ** - for G=150%, S should be in the interval [200%, 300%] - ** - for G=125%, S should be in the interval [400%, 500%] - */ - LUA_GCSETGOAL, - LUA_GCSETSTEPMUL, - LUA_GCSETSTEPSIZE, -}; - -LUA_API int lua_gc(lua_State* L, int what, int data); - -/* -** memory statistics -** all allocated bytes are attributed to the memory category of the running thread (0..LUA_MEMORY_CATEGORIES-1) -*/ - -LUA_API void lua_setmemcat(lua_State* L, int category); -LUA_API size_t lua_totalbytes(lua_State* L, int category); - -/* -** miscellaneous functions -*/ - -LUA_API l_noret lua_error(lua_State* L); - -LUA_API int lua_next(lua_State* L, int idx); -LUA_API int lua_rawiter(lua_State* L, int idx, int iter); - -LUA_API void lua_concat(lua_State* L, int n); - -LUA_API uintptr_t lua_encodepointer(lua_State* L, uintptr_t p); - -LUA_API double lua_clock(); - -LUA_API void lua_setuserdatatag(lua_State* L, int idx, int tag); - -typedef void (*lua_Destructor)(lua_State* L, void* userdata); - -LUA_API void lua_setuserdatadtor(lua_State* L, int tag, lua_Destructor dtor); -LUA_API lua_Destructor lua_getuserdatadtor(lua_State* L, int tag); - -LUA_API void lua_setlightuserdataname(lua_State* L, int tag, const char* name); -LUA_API const char* lua_getlightuserdataname(lua_State* L, int tag); - -LUA_API void lua_clonefunction(lua_State* L, int idx); - -LUA_API void lua_cleartable(lua_State* L, int idx); - -LUA_API lua_Alloc lua_getallocf(lua_State* L, void** ud); - -/* -** reference system, can be used to pin objects -*/ -#define LUA_NOREF -1 -#define LUA_REFNIL 0 - -LUA_API int lua_ref(lua_State* L, int idx); -LUA_API void lua_unref(lua_State* L, int ref); - -#define lua_getref(L, ref) lua_rawgeti(L, LUA_REGISTRYINDEX, (ref)) - -/* -** =============================================================== -** some useful macros -** =============================================================== -*/ -#define lua_tonumber(L, i) lua_tonumberx(L, i, NULL) -#define lua_tointeger(L, i) lua_tointegerx(L, i, NULL) -#define lua_tounsigned(L, i) lua_tounsignedx(L, i, NULL) - -#define lua_pop(L, n) lua_settop(L, -(n)-1) - -#define lua_newtable(L) lua_createtable(L, 0, 0) -#define lua_newuserdata(L, s) lua_newuserdatatagged(L, s, 0) - -#define lua_strlen(L, i) lua_objlen(L, (i)) - -#define lua_isfunction(L, n) (lua_type(L, (n)) == LUA_TFUNCTION) -#define lua_istable(L, n) (lua_type(L, (n)) == LUA_TTABLE) -#define lua_islightuserdata(L, n) (lua_type(L, (n)) == LUA_TLIGHTUSERDATA) -#define lua_isnil(L, n) (lua_type(L, (n)) == LUA_TNIL) -#define lua_isboolean(L, n) (lua_type(L, (n)) == LUA_TBOOLEAN) -#define lua_isvector(L, n) (lua_type(L, (n)) == LUA_TVECTOR) -#define lua_isthread(L, n) (lua_type(L, (n)) == LUA_TTHREAD) -#define lua_isbuffer(L, n) (lua_type(L, (n)) == LUA_TBUFFER) -#define lua_isnone(L, n) (lua_type(L, (n)) == LUA_TNONE) -#define lua_isnoneornil(L, n) (lua_type(L, (n)) <= LUA_TNIL) - -#define lua_pushliteral(L, s) lua_pushlstring(L, "" s, (sizeof(s) / sizeof(char)) - 1) -#define lua_pushcfunction(L, fn, debugname) lua_pushcclosurek(L, fn, debugname, 0, NULL) -#define lua_pushcclosure(L, fn, debugname, nup) lua_pushcclosurek(L, fn, debugname, nup, NULL) -#define lua_pushlightuserdata(L, p) lua_pushlightuserdatatagged(L, p, 0) - -#define lua_setglobal(L, s) lua_setfield(L, LUA_GLOBALSINDEX, (s)) -#define lua_getglobal(L, s) lua_getfield(L, LUA_GLOBALSINDEX, (s)) - -#define lua_tostring(L, i) lua_tolstring(L, (i), NULL) - -#define lua_pushfstring(L, fmt, ...) lua_pushfstringL(L, fmt, ##__VA_ARGS__) - -/* -** {====================================================================== -** Debug API -** ======================================================================= -*/ - -typedef struct lua_Debug lua_Debug; // activation record - -// Functions to be called by the debugger in specific events -typedef void (*lua_Hook)(lua_State* L, lua_Debug* ar); - -LUA_API int lua_stackdepth(lua_State* L); -LUA_API int lua_getinfo(lua_State* L, int level, const char* what, lua_Debug* ar); -LUA_API int lua_getargument(lua_State* L, int level, int n); -LUA_API const char* lua_getlocal(lua_State* L, int level, int n); -LUA_API const char* lua_setlocal(lua_State* L, int level, int n); -LUA_API const char* lua_getupvalue(lua_State* L, int funcindex, int n); -LUA_API const char* lua_setupvalue(lua_State* L, int funcindex, int n); - -LUA_API void lua_singlestep(lua_State* L, int enabled); -LUA_API int lua_breakpoint(lua_State* L, int funcindex, int line, int enabled); - -typedef void (*lua_Coverage)(void* context, const char* function, int linedefined, int depth, const int* hits, size_t size); - -LUA_API void lua_getcoverage(lua_State* L, int funcindex, void* context, lua_Coverage callback); - -// Warning: this function is not thread-safe since it stores the result in a shared global array! Only use for debugging. -LUA_API const char* lua_debugtrace(lua_State* L); - -struct lua_Debug -{ - const char* name; // (n) - const char* what; // (s) `Lua', `C', `main', `tail' - const char* source; // (s) - const char* short_src; // (s) - int linedefined; // (s) - int currentline; // (l) - unsigned char nupvals; // (u) number of upvalues - unsigned char nparams; // (a) number of parameters - char isvararg; // (a) - void* userdata; // only valid in luau_callhook - - char ssbuf[LUA_IDSIZE]; -}; - -// }====================================================================== - -/* Callbacks that can be used to reconfigure behavior of the VM dynamically. - * These are shared between all coroutines. - * - * Note: interrupt is safe to set from an arbitrary thread but all other callbacks - * can only be changed when the VM is not running any code */ -struct lua_Callbacks -{ - void* userdata; // arbitrary userdata pointer that is never overwritten by Luau - - void (*interrupt)(lua_State* L, int gc); // gets called at safepoints (loop back edges, call/ret, gc) if set - void (*panic)(lua_State* L, int errcode); // gets called when an unprotected error is raised (if longjmp is used) - - void (*userthread)(lua_State* LP, lua_State* L); // gets called when L is created (LP == parent) or destroyed (LP == NULL) - int16_t (*useratom)(const char* s, size_t l); // gets called when a string is created; returned atom can be retrieved via tostringatom - - void (*debugbreak)(lua_State* L, lua_Debug* ar); // gets called when BREAK instruction is encountered - void (*debugstep)(lua_State* L, lua_Debug* ar); // gets called after each instruction in single step mode - void (*debuginterrupt)(lua_State* L, lua_Debug* ar); // gets called when thread execution is interrupted by break in another thread - void (*debugprotectederror)(lua_State* L); // gets called when protected call results in an error -}; -typedef struct lua_Callbacks lua_Callbacks; - -LUA_API lua_Callbacks* lua_callbacks(lua_State* L); - -/****************************************************************************** - * Copyright (c) 2019-2023 Roblox Corporation - * Copyright (C) 1994-2008 Lua.org, PUC-Rio. All rights reserved. - * - * Permission is hereby granted, free of charge, to any person obtaining - * a copy of this software and associated documentation files (the - * "Software"), to deal in the Software without restriction, including - * without limitation the rights to use, copy, modify, merge, publish, - * distribute, sublicense, and/or sell copies of the Software, and to - * permit persons to whom the Software is furnished to do so, subject to - * the following conditions: - * - * The above copyright notice and this permission notice shall be - * included in all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, - * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF - * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. - * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY - * CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, - * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE - * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. - ******************************************************************************/ diff --git a/lib/luau/VM/include/luaconf.h b/lib/luau/VM/include/luaconf.h deleted file mode 100644 index 910e259..0000000 --- a/lib/luau/VM/include/luaconf.h +++ /dev/null @@ -1,150 +0,0 @@ -// This file is part of the Luau programming language and is licensed under MIT License; see LICENSE.txt for details -// This code is based on Lua 5.x implementation licensed under MIT License; see lua_LICENSE.txt for details -#pragma once - -// When debugging complex issues, consider enabling one of these: -// This will reallocate the stack very aggressively at every opportunity; use this with asan to catch stale stack pointers -// #define HARDSTACKTESTS 1 -// This will call GC validation very aggressively at every incremental GC step; use this with caution as it's SLOW -// #define HARDMEMTESTS 1 -// This will call GC validation very aggressively at every GC opportunity; use this with caution as it's VERY SLOW -// #define HARDMEMTESTS 2 - -// To force MSVC2017+ to generate SSE2 code for some stdlib functions we need to locally enable /fp:fast -// Note that /fp:fast changes the semantics of floating point comparisons so this is only safe to do for functions without ones -#if defined(_MSC_VER) && !defined(__clang__) -#define LUAU_FASTMATH_BEGIN __pragma(float_control(precise, off, push)) -#define LUAU_FASTMATH_END __pragma(float_control(pop)) -#else -#define LUAU_FASTMATH_BEGIN -#define LUAU_FASTMATH_END -#endif - -// Some functions like floor/ceil have SSE4.1 equivalents but we currently support systems without SSE4.1 -// Note that we only need to do this when SSE4.1 support is not guaranteed by compiler settings, as otherwise compiler will optimize these for us. -#if (defined(__x86_64__) || defined(_M_X64)) && !defined(__SSE4_1__) && !defined(__AVX__) -#if defined(_MSC_VER) && !defined(__clang__) -#define LUAU_TARGET_SSE41 -#elif defined(__GNUC__) && defined(__has_attribute) -#if __has_attribute(target) -#define LUAU_TARGET_SSE41 __attribute__((target("sse4.1"))) -#endif -#endif -#endif - -// Used on functions that have a printf-like interface to validate them statically -#if defined(__GNUC__) -#define LUA_PRINTF_ATTR(fmt, arg) __attribute__((format(printf, fmt, arg))) -#else -#define LUA_PRINTF_ATTR(fmt, arg) -#endif - -#ifdef _MSC_VER -#define LUA_NORETURN __declspec(noreturn) -#else -#define LUA_NORETURN __attribute__((__noreturn__)) -#endif - -// Can be used to reconfigure visibility/exports for public APIs -#ifndef LUA_API -#define LUA_API extern -#endif - -#define LUALIB_API LUA_API - -// Can be used to reconfigure visibility for internal APIs -#if defined(__GNUC__) -#define LUAI_FUNC __attribute__((visibility("hidden"))) extern -#define LUAI_DATA LUAI_FUNC -#else -#define LUAI_FUNC extern -#define LUAI_DATA extern -#endif - -// Can be used to reconfigure internal error handling to use longjmp instead of C++ EH -#ifndef LUA_USE_LONGJMP -#define LUA_USE_LONGJMP 0 -#endif - -// LUA_IDSIZE gives the maximum size for the description of the source -#ifndef LUA_IDSIZE -#define LUA_IDSIZE 256 -#endif - -// LUA_MINSTACK is the guaranteed number of Lua stack slots available to a C function -#ifndef LUA_MINSTACK -#define LUA_MINSTACK 20 -#endif - -// LUAI_MAXCSTACK limits the number of Lua stack slots that a C function can use -#ifndef LUAI_MAXCSTACK -#define LUAI_MAXCSTACK 8000 -#endif - -// LUAI_MAXCALLS limits the number of nested calls -#ifndef LUAI_MAXCALLS -#define LUAI_MAXCALLS 20000 -#endif - -// LUAI_MAXCCALLS is the maximum depth for nested C calls; this limit depends on native stack size -#ifndef LUAI_MAXCCALLS -#define LUAI_MAXCCALLS 200 -#endif - -// buffer size used for on-stack string operations; this limit depends on native stack size -#ifndef LUA_BUFFERSIZE -#define LUA_BUFFERSIZE 512 -#endif - -// number of valid Lua userdata tags -#ifndef LUA_UTAG_LIMIT -#define LUA_UTAG_LIMIT 128 -#endif - -// number of valid Lua lightuserdata tags -#ifndef LUA_LUTAG_LIMIT -#define LUA_LUTAG_LIMIT 128 -#endif - -// upper bound for number of size classes used by page allocator -#ifndef LUA_SIZECLASSES -#define LUA_SIZECLASSES 32 -#endif - -// available number of separate memory categories -#ifndef LUA_MEMORY_CATEGORIES -#define LUA_MEMORY_CATEGORIES 256 -#endif - -// minimum size for the string table (must be power of 2) -#ifndef LUA_MINSTRTABSIZE -#define LUA_MINSTRTABSIZE 32 -#endif - -// maximum number of captures supported by pattern matching -#ifndef LUA_MAXCAPTURES -#define LUA_MAXCAPTURES 32 -#endif - -// }================================================================== - -/* -@@ LUAI_USER_ALIGNMENT_T is a type that requires maximum alignment. -** CHANGE it if your system requires alignments larger than double. (For -** instance, if your system supports long doubles and they must be -** aligned in 16-byte boundaries, then you should add long double in the -** union.) Probably you do not need to change this. -*/ -#define LUAI_USER_ALIGNMENT_T \ - union \ - { \ - double u; \ - void* s; \ - long l; \ - } - -#ifndef LUA_VECTOR_SIZE -#define LUA_VECTOR_SIZE 3 // must be 3 or 4 -#endif - -#define LUA_EXTRA_SIZE (LUA_VECTOR_SIZE - 2) diff --git a/lib/luau/VM/include/lualib.h b/lib/luau/VM/include/lualib.h deleted file mode 100644 index 367a028..0000000 --- a/lib/luau/VM/include/lualib.h +++ /dev/null @@ -1,144 +0,0 @@ -// This file is part of the Luau programming language and is licensed under MIT License; see LICENSE.txt for details -// This code is based on Lua 5.x implementation licensed under MIT License; see lua_LICENSE.txt for details -#pragma once - -#include "lua.h" - -#define luaL_error(L, fmt, ...) luaL_errorL(L, fmt, ##__VA_ARGS__) -#define luaL_typeerror(L, narg, tname) luaL_typeerrorL(L, narg, tname) -#define luaL_argerror(L, narg, extramsg) luaL_argerrorL(L, narg, extramsg) - -struct luaL_Reg -{ - const char* name; - lua_CFunction func; -}; -typedef struct luaL_Reg luaL_Reg; - -LUALIB_API void luaL_register(lua_State* L, const char* libname, const luaL_Reg* l); -LUALIB_API int luaL_getmetafield(lua_State* L, int obj, const char* e); -LUALIB_API int luaL_callmeta(lua_State* L, int obj, const char* e); -LUALIB_API l_noret luaL_typeerrorL(lua_State* L, int narg, const char* tname); -LUALIB_API l_noret luaL_argerrorL(lua_State* L, int narg, const char* extramsg); -LUALIB_API const char* luaL_checklstring(lua_State* L, int numArg, size_t* l); -LUALIB_API const char* luaL_optlstring(lua_State* L, int numArg, const char* def, size_t* l); -LUALIB_API double luaL_checknumber(lua_State* L, int numArg); -LUALIB_API double luaL_optnumber(lua_State* L, int nArg, double def); - -LUALIB_API int luaL_checkboolean(lua_State* L, int narg); -LUALIB_API int luaL_optboolean(lua_State* L, int narg, int def); - -LUALIB_API int luaL_checkinteger(lua_State* L, int numArg); -LUALIB_API int luaL_optinteger(lua_State* L, int nArg, int def); -LUALIB_API unsigned luaL_checkunsigned(lua_State* L, int numArg); -LUALIB_API unsigned luaL_optunsigned(lua_State* L, int numArg, unsigned def); - -LUALIB_API const float* luaL_checkvector(lua_State* L, int narg); -LUALIB_API const float* luaL_optvector(lua_State* L, int narg, const float* def); - -LUALIB_API void luaL_checkstack(lua_State* L, int sz, const char* msg); -LUALIB_API void luaL_checktype(lua_State* L, int narg, int t); -LUALIB_API void luaL_checkany(lua_State* L, int narg); - -LUALIB_API int luaL_newmetatable(lua_State* L, const char* tname); -LUALIB_API void* luaL_checkudata(lua_State* L, int ud, const char* tname); - -LUALIB_API void* luaL_checkbuffer(lua_State* L, int narg, size_t* len); - -LUALIB_API void luaL_where(lua_State* L, int lvl); -LUALIB_API LUA_PRINTF_ATTR(2, 3) l_noret luaL_errorL(lua_State* L, const char* fmt, ...); - -LUALIB_API int luaL_checkoption(lua_State* L, int narg, const char* def, const char* const lst[]); - -LUALIB_API const char* luaL_tolstring(lua_State* L, int idx, size_t* len); - -LUALIB_API lua_State* luaL_newstate(void); - -LUALIB_API const char* luaL_findtable(lua_State* L, int idx, const char* fname, int szhint); - -LUALIB_API const char* luaL_typename(lua_State* L, int idx); - -/* -** =============================================================== -** some useful macros -** =============================================================== -*/ - -#define luaL_argcheck(L, cond, arg, extramsg) ((void)((cond) ? (void)0 : luaL_argerror(L, arg, extramsg))) -#define luaL_argexpected(L, cond, arg, tname) ((void)((cond) ? (void)0 : luaL_typeerror(L, arg, tname))) - -#define luaL_checkstring(L, n) (luaL_checklstring(L, (n), NULL)) -#define luaL_optstring(L, n, d) (luaL_optlstring(L, (n), (d), NULL)) - -#define luaL_getmetatable(L, n) (lua_getfield(L, LUA_REGISTRYINDEX, (n))) - -#define luaL_opt(L, f, n, d) (lua_isnoneornil(L, (n)) ? (d) : f(L, (n))) - -// generic buffer manipulation - -struct luaL_Strbuf -{ - char* p; // current position in buffer - char* end; // end of the current buffer - lua_State* L; - struct TString* storage; - char buffer[LUA_BUFFERSIZE]; -}; -typedef struct luaL_Strbuf luaL_Strbuf; - -// compatibility typedef: this type is called luaL_Buffer in Lua headers -// renamed to luaL_Strbuf to reduce confusion with internal VM buffer type -typedef struct luaL_Strbuf luaL_Buffer; - -// when internal buffer storage is exhausted, a mutable string value 'storage' will be placed on the stack -// in general, functions expect the mutable string buffer to be placed on top of the stack (top-1) -// with the exception of luaL_addvalue that expects the value at the top and string buffer further away (top-2) - -#define luaL_addchar(B, c) ((void)((B)->p < (B)->end || luaL_prepbuffsize(B, 1)), (*(B)->p++ = (char)(c))) -#define luaL_addstring(B, s) luaL_addlstring(B, s, strlen(s)) - -LUALIB_API void luaL_buffinit(lua_State* L, luaL_Strbuf* B); -LUALIB_API char* luaL_buffinitsize(lua_State* L, luaL_Strbuf* B, size_t size); -LUALIB_API char* luaL_prepbuffsize(luaL_Buffer* B, size_t size); -LUALIB_API void luaL_addlstring(luaL_Strbuf* B, const char* s, size_t l); -LUALIB_API void luaL_addvalue(luaL_Strbuf* B); -LUALIB_API void luaL_addvalueany(luaL_Strbuf* B, int idx); -LUALIB_API void luaL_pushresult(luaL_Strbuf* B); -LUALIB_API void luaL_pushresultsize(luaL_Strbuf* B, size_t size); - -// builtin libraries -LUALIB_API int luaopen_base(lua_State* L); - -#define LUA_COLIBNAME "coroutine" -LUALIB_API int luaopen_coroutine(lua_State* L); - -#define LUA_TABLIBNAME "table" -LUALIB_API int luaopen_table(lua_State* L); - -#define LUA_OSLIBNAME "os" -LUALIB_API int luaopen_os(lua_State* L); - -#define LUA_STRLIBNAME "string" -LUALIB_API int luaopen_string(lua_State* L); - -#define LUA_BITLIBNAME "bit32" -LUALIB_API int luaopen_bit32(lua_State* L); - -#define LUA_BUFFERLIBNAME "buffer" -LUALIB_API int luaopen_buffer(lua_State* L); - -#define LUA_UTF8LIBNAME "utf8" -LUALIB_API int luaopen_utf8(lua_State* L); - -#define LUA_MATHLIBNAME "math" -LUALIB_API int luaopen_math(lua_State* L); - -#define LUA_DBLIBNAME "debug" -LUALIB_API int luaopen_debug(lua_State* L); - -// open all builtin libraries -LUALIB_API void luaL_openlibs(lua_State* L); - -// sandbox libraries and globals -LUALIB_API void luaL_sandbox(lua_State* L); -LUALIB_API void luaL_sandboxthread(lua_State* L); diff --git a/lib/luau/VM/src/lapi.cpp b/lib/luau/VM/src/lapi.cpp deleted file mode 100644 index 58c767f..0000000 --- a/lib/luau/VM/src/lapi.cpp +++ /dev/null @@ -1,1495 +0,0 @@ -// This file is part of the Luau programming language and is licensed under MIT License; see LICENSE.txt for details -// This code is based on Lua 5.x implementation licensed under MIT License; see lua_LICENSE.txt for details -#include "lapi.h" - -#include "lstate.h" -#include "lstring.h" -#include "ltable.h" -#include "lfunc.h" -#include "lgc.h" -#include "ldo.h" -#include "ludata.h" -#include "lvm.h" -#include "lnumutils.h" -#include "lbuffer.h" - -#include - -/* - * This file contains most implementations of core Lua APIs from lua.h. - * - * These implementations should use api_check macros to verify that stack and type contracts hold; it's the callers - * responsibility to, for example, pass a valid table index to lua_rawgetfield. Generally errors should only be raised - * for conditions caller can't predict such as an out-of-memory error. - * - * The caller is expected to handle stack reservation (by using less than LUA_MINSTACK slots or by calling lua_checkstack). - * To ensure this is handled correctly, use api_incr_top(L) when pushing values to the stack. - * - * Functions that push any collectable objects to the stack *should* call luaC_threadbarrier. Failure to do this can result - * in stack references that point to dead objects since black threads don't get rescanned. - * - * Functions that push newly created objects to the stack *should* call luaC_checkGC in addition to luaC_threadbarrier. - * Failure to do this can result in OOM since GC may never run. - * - * Note that luaC_checkGC may mark the thread and paint it black; functions that call both before pushing objects must - * therefore call luaC_checkGC before luaC_threadbarrier to guarantee the object is pushed to a gray thread. - */ - -const char* lua_ident = "$Lua: Lua 5.1.4 Copyright (C) 1994-2008 Lua.org, PUC-Rio $\n" - "$Authors: R. Ierusalimschy, L. H. de Figueiredo & W. Celes $\n" - "$URL: www.lua.org $\n"; - -const char* luau_ident = "$Luau: Copyright (C) 2019-2023 Roblox Corporation $\n" - "$URL: luau-lang.org $\n"; - -#define api_checknelems(L, n) api_check(L, (n) <= (L->top - L->base)) - -#define api_checkvalidindex(L, i) api_check(L, (i) != luaO_nilobject) - -#define api_incr_top(L) \ - { \ - api_check(L, L->top < L->ci->top); \ - L->top++; \ - } - -#define api_update_top(L, p) \ - { \ - api_check(L, p >= L->base && p < L->ci->top); \ - L->top = p; \ - } - -#define updateatom(L, ts) \ - { \ - if (ts->atom == ATOM_UNDEF) \ - ts->atom = L->global->cb.useratom ? L->global->cb.useratom(ts->data, ts->len) : -1; \ - } - -static Table* getcurrenv(lua_State* L) -{ - if (L->ci == L->base_ci) // no enclosing function? - return L->gt; // use global table as environment - else - return curr_func(L)->env; -} - -static LUAU_NOINLINE TValue* pseudo2addr(lua_State* L, int idx) -{ - api_check(L, lua_ispseudo(idx)); - switch (idx) - { // pseudo-indices - case LUA_REGISTRYINDEX: - return registry(L); - case LUA_ENVIRONINDEX: - { - sethvalue(L, &L->global->pseudotemp, getcurrenv(L)); - return &L->global->pseudotemp; - } - case LUA_GLOBALSINDEX: - { - sethvalue(L, &L->global->pseudotemp, L->gt); - return &L->global->pseudotemp; - } - default: - { - Closure* func = curr_func(L); - idx = LUA_GLOBALSINDEX - idx; - return (idx <= func->nupvalues) ? &func->c.upvals[idx - 1] : cast_to(TValue*, luaO_nilobject); - } - } -} - -static LUAU_FORCEINLINE TValue* index2addr(lua_State* L, int idx) -{ - if (idx > 0) - { - TValue* o = L->base + (idx - 1); - api_check(L, idx <= L->ci->top - L->base); - if (o >= L->top) - return cast_to(TValue*, luaO_nilobject); - else - return o; - } - else if (idx > LUA_REGISTRYINDEX) - { - api_check(L, idx != 0 && -idx <= L->top - L->base); - return L->top + idx; - } - else - { - return pseudo2addr(L, idx); - } -} - -const TValue* luaA_toobject(lua_State* L, int idx) -{ - StkId p = index2addr(L, idx); - return (p == luaO_nilobject) ? NULL : p; -} - -void luaA_pushobject(lua_State* L, const TValue* o) -{ - setobj2s(L, L->top, o); - api_incr_top(L); -} - -int lua_checkstack(lua_State* L, int size) -{ - int res = 1; - if (size > LUAI_MAXCSTACK || (L->top - L->base + size) > LUAI_MAXCSTACK) - res = 0; // stack overflow - else if (size > 0) - { - luaD_checkstack(L, size); - expandstacklimit(L, L->top + size); - } - return res; -} - -void lua_rawcheckstack(lua_State* L, int size) -{ - luaD_checkstack(L, size); - expandstacklimit(L, L->top + size); -} - -void lua_xmove(lua_State* from, lua_State* to, int n) -{ - if (from == to) - return; - api_checknelems(from, n); - api_check(from, from->global == to->global); - api_check(from, to->ci->top - to->top >= n); - luaC_threadbarrier(to); - - StkId ttop = to->top; - StkId ftop = from->top - n; - for (int i = 0; i < n; i++) - setobj2s(to, ttop + i, ftop + i); - - from->top = ftop; - to->top = ttop + n; -} - -void lua_xpush(lua_State* from, lua_State* to, int idx) -{ - api_check(from, from->global == to->global); - luaC_threadbarrier(to); - setobj2s(to, to->top, index2addr(from, idx)); - api_incr_top(to); -} - -lua_State* lua_newthread(lua_State* L) -{ - luaC_checkGC(L); - luaC_threadbarrier(L); - lua_State* L1 = luaE_newthread(L); - setthvalue(L, L->top, L1); - api_incr_top(L); - global_State* g = L->global; - if (g->cb.userthread) - g->cb.userthread(L, L1); - return L1; -} - -lua_State* lua_mainthread(lua_State* L) -{ - return L->global->mainthread; -} - -/* -** basic stack manipulation -*/ - -int lua_absindex(lua_State* L, int idx) -{ - api_check(L, (idx > 0 && idx <= L->top - L->base) || (idx < 0 && -idx <= L->top - L->base) || lua_ispseudo(idx)); - return idx > 0 || lua_ispseudo(idx) ? idx : cast_int(L->top - L->base) + idx + 1; -} - -int lua_gettop(lua_State* L) -{ - return cast_int(L->top - L->base); -} - -void lua_settop(lua_State* L, int idx) -{ - if (idx >= 0) - { - api_check(L, idx <= L->stack_last - L->base); - while (L->top < L->base + idx) - setnilvalue(L->top++); - L->top = L->base + idx; - } - else - { - api_check(L, -(idx + 1) <= (L->top - L->base)); - L->top += idx + 1; // `subtract' index (index is negative) - } -} - -void lua_remove(lua_State* L, int idx) -{ - StkId p = index2addr(L, idx); - api_checkvalidindex(L, p); - while (++p < L->top) - setobj2s(L, p - 1, p); - L->top--; -} - -void lua_insert(lua_State* L, int idx) -{ - luaC_threadbarrier(L); - StkId p = index2addr(L, idx); - api_checkvalidindex(L, p); - for (StkId q = L->top; q > p; q--) - setobj2s(L, q, q - 1); - setobj2s(L, p, L->top); -} - -void lua_replace(lua_State* L, int idx) -{ - api_checknelems(L, 1); - luaC_threadbarrier(L); - StkId o = index2addr(L, idx); - api_checkvalidindex(L, o); - if (idx == LUA_ENVIRONINDEX) - { - api_check(L, L->ci != L->base_ci); - Closure* func = curr_func(L); - api_check(L, ttistable(L->top - 1)); - func->env = hvalue(L->top - 1); - luaC_barrier(L, func, L->top - 1); - } - else if (idx == LUA_GLOBALSINDEX) - { - api_check(L, ttistable(L->top - 1)); - L->gt = hvalue(L->top - 1); - } - else - { - setobj(L, o, L->top - 1); - if (idx < LUA_GLOBALSINDEX) // function upvalue? - luaC_barrier(L, curr_func(L), L->top - 1); - } - L->top--; -} - -void lua_pushvalue(lua_State* L, int idx) -{ - luaC_threadbarrier(L); - StkId o = index2addr(L, idx); - setobj2s(L, L->top, o); - api_incr_top(L); -} - -/* -** access functions (stack -> C) -*/ - -int lua_type(lua_State* L, int idx) -{ - StkId o = index2addr(L, idx); - return (o == luaO_nilobject) ? LUA_TNONE : ttype(o); -} - -const char* lua_typename(lua_State* L, int t) -{ - return (t == LUA_TNONE) ? "no value" : luaT_typenames[t]; -} - -int lua_iscfunction(lua_State* L, int idx) -{ - StkId o = index2addr(L, idx); - return iscfunction(o); -} - -int lua_isLfunction(lua_State* L, int idx) -{ - StkId o = index2addr(L, idx); - return isLfunction(o); -} - -int lua_isnumber(lua_State* L, int idx) -{ - TValue n; - const TValue* o = index2addr(L, idx); - return tonumber(o, &n); -} - -int lua_isstring(lua_State* L, int idx) -{ - int t = lua_type(L, idx); - return (t == LUA_TSTRING || t == LUA_TNUMBER); -} - -int lua_isuserdata(lua_State* L, int idx) -{ - const TValue* o = index2addr(L, idx); - return (ttisuserdata(o) || ttislightuserdata(o)); -} - -int lua_rawequal(lua_State* L, int index1, int index2) -{ - StkId o1 = index2addr(L, index1); - StkId o2 = index2addr(L, index2); - return (o1 == luaO_nilobject || o2 == luaO_nilobject) ? 0 : luaO_rawequalObj(o1, o2); -} - -int lua_equal(lua_State* L, int index1, int index2) -{ - StkId o1, o2; - int i; - o1 = index2addr(L, index1); - o2 = index2addr(L, index2); - i = (o1 == luaO_nilobject || o2 == luaO_nilobject) ? 0 : equalobj(L, o1, o2); - return i; -} - -int lua_lessthan(lua_State* L, int index1, int index2) -{ - StkId o1, o2; - int i; - o1 = index2addr(L, index1); - o2 = index2addr(L, index2); - i = (o1 == luaO_nilobject || o2 == luaO_nilobject) ? 0 : luaV_lessthan(L, o1, o2); - return i; -} - -double lua_tonumberx(lua_State* L, int idx, int* isnum) -{ - TValue n; - const TValue* o = index2addr(L, idx); - if (tonumber(o, &n)) - { - if (isnum) - *isnum = 1; - return nvalue(o); - } - else - { - if (isnum) - *isnum = 0; - return 0; - } -} - -int lua_tointegerx(lua_State* L, int idx, int* isnum) -{ - TValue n; - const TValue* o = index2addr(L, idx); - if (tonumber(o, &n)) - { - int res; - double num = nvalue(o); - luai_num2int(res, num); - if (isnum) - *isnum = 1; - return res; - } - else - { - if (isnum) - *isnum = 0; - return 0; - } -} - -unsigned lua_tounsignedx(lua_State* L, int idx, int* isnum) -{ - TValue n; - const TValue* o = index2addr(L, idx); - if (tonumber(o, &n)) - { - unsigned res; - double num = nvalue(o); - luai_num2unsigned(res, num); - if (isnum) - *isnum = 1; - return res; - } - else - { - if (isnum) - *isnum = 0; - return 0; - } -} - -int lua_toboolean(lua_State* L, int idx) -{ - const TValue* o = index2addr(L, idx); - return !l_isfalse(o); -} - -const char* lua_tolstring(lua_State* L, int idx, size_t* len) -{ - StkId o = index2addr(L, idx); - if (!ttisstring(o)) - { - luaC_threadbarrier(L); - if (!luaV_tostring(L, o)) - { // conversion failed? - if (len != NULL) - *len = 0; - return NULL; - } - luaC_checkGC(L); - o = index2addr(L, idx); // previous call may reallocate the stack - } - if (len != NULL) - *len = tsvalue(o)->len; - return svalue(o); -} - -const char* lua_tostringatom(lua_State* L, int idx, int* atom) -{ - StkId o = index2addr(L, idx); - if (!ttisstring(o)) - return NULL; - TString* s = tsvalue(o); - if (atom) - { - updateatom(L, s); - *atom = s->atom; - } - return getstr(s); -} - -const char* lua_namecallatom(lua_State* L, int* atom) -{ - TString* s = L->namecall; - if (!s) - return NULL; - if (atom) - { - updateatom(L, s); - *atom = s->atom; - } - return getstr(s); -} - -const float* lua_tovector(lua_State* L, int idx) -{ - StkId o = index2addr(L, idx); - if (!ttisvector(o)) - return NULL; - return vvalue(o); -} - -int lua_objlen(lua_State* L, int idx) -{ - StkId o = index2addr(L, idx); - switch (ttype(o)) - { - case LUA_TSTRING: - return tsvalue(o)->len; - case LUA_TUSERDATA: - return uvalue(o)->len; - case LUA_TBUFFER: - return bufvalue(o)->len; - case LUA_TTABLE: - return luaH_getn(hvalue(o)); - default: - return 0; - } -} - -lua_CFunction lua_tocfunction(lua_State* L, int idx) -{ - StkId o = index2addr(L, idx); - return (!iscfunction(o)) ? NULL : cast_to(lua_CFunction, clvalue(o)->c.f); -} - -void* lua_tolightuserdata(lua_State* L, int idx) -{ - StkId o = index2addr(L, idx); - return (!ttislightuserdata(o)) ? NULL : pvalue(o); -} - -void* lua_tolightuserdatatagged(lua_State* L, int idx, int tag) -{ - StkId o = index2addr(L, idx); - return (!ttislightuserdata(o) || lightuserdatatag(o) != tag) ? NULL : pvalue(o); -} - -void* lua_touserdata(lua_State* L, int idx) -{ - StkId o = index2addr(L, idx); - if (ttisuserdata(o)) - return uvalue(o)->data; - else if (ttislightuserdata(o)) - return pvalue(o); - else - return NULL; -} - -void* lua_touserdatatagged(lua_State* L, int idx, int tag) -{ - StkId o = index2addr(L, idx); - return (ttisuserdata(o) && uvalue(o)->tag == tag) ? uvalue(o)->data : NULL; -} - -int lua_userdatatag(lua_State* L, int idx) -{ - StkId o = index2addr(L, idx); - if (ttisuserdata(o)) - return uvalue(o)->tag; - return -1; -} - -int lua_lightuserdatatag(lua_State* L, int idx) -{ - StkId o = index2addr(L, idx); - if (ttislightuserdata(o)) - return lightuserdatatag(o); - return -1; -} - -lua_State* lua_tothread(lua_State* L, int idx) -{ - StkId o = index2addr(L, idx); - return (!ttisthread(o)) ? NULL : thvalue(o); -} - -void* lua_tobuffer(lua_State* L, int idx, size_t* len) -{ - StkId o = index2addr(L, idx); - - if (!ttisbuffer(o)) - return NULL; - - Buffer* b = bufvalue(o); - - if (len) - *len = b->len; - - return b->data; -} - -const void* lua_topointer(lua_State* L, int idx) -{ - StkId o = index2addr(L, idx); - switch (ttype(o)) - { - case LUA_TUSERDATA: - return uvalue(o)->data; - case LUA_TLIGHTUSERDATA: - return pvalue(o); - default: - return iscollectable(o) ? gcvalue(o) : NULL; - } -} - -/* -** push functions (C -> stack) -*/ - -void lua_pushnil(lua_State* L) -{ - setnilvalue(L->top); - api_incr_top(L); -} - -void lua_pushnumber(lua_State* L, double n) -{ - setnvalue(L->top, n); - api_incr_top(L); -} - -void lua_pushinteger(lua_State* L, int n) -{ - setnvalue(L->top, cast_num(n)); - api_incr_top(L); -} - -void lua_pushunsigned(lua_State* L, unsigned u) -{ - setnvalue(L->top, cast_num(u)); - api_incr_top(L); -} - -#if LUA_VECTOR_SIZE == 4 -void lua_pushvector(lua_State* L, float x, float y, float z, float w) -{ - setvvalue(L->top, x, y, z, w); - api_incr_top(L); -} -#else -void lua_pushvector(lua_State* L, float x, float y, float z) -{ - setvvalue(L->top, x, y, z, 0.0f); - api_incr_top(L); -} -#endif - -void lua_pushlstring(lua_State* L, const char* s, size_t len) -{ - luaC_checkGC(L); - luaC_threadbarrier(L); - setsvalue(L, L->top, luaS_newlstr(L, s, len)); - api_incr_top(L); -} - -void lua_pushstring(lua_State* L, const char* s) -{ - if (s == NULL) - lua_pushnil(L); - else - lua_pushlstring(L, s, strlen(s)); -} - -const char* lua_pushvfstring(lua_State* L, const char* fmt, va_list argp) -{ - luaC_checkGC(L); - luaC_threadbarrier(L); - const char* ret = luaO_pushvfstring(L, fmt, argp); - return ret; -} - -const char* lua_pushfstringL(lua_State* L, const char* fmt, ...) -{ - luaC_checkGC(L); - luaC_threadbarrier(L); - va_list argp; - va_start(argp, fmt); - const char* ret = luaO_pushvfstring(L, fmt, argp); - va_end(argp); - return ret; -} - -void lua_pushcclosurek(lua_State* L, lua_CFunction fn, const char* debugname, int nup, lua_Continuation cont) -{ - luaC_checkGC(L); - luaC_threadbarrier(L); - api_checknelems(L, nup); - Closure* cl = luaF_newCclosure(L, nup, getcurrenv(L)); - cl->c.f = fn; - cl->c.cont = cont; - cl->c.debugname = debugname; - L->top -= nup; - while (nup--) - setobj2n(L, &cl->c.upvals[nup], L->top + nup); - setclvalue(L, L->top, cl); - LUAU_ASSERT(iswhite(obj2gco(cl))); - api_incr_top(L); -} - -void lua_pushboolean(lua_State* L, int b) -{ - setbvalue(L->top, (b != 0)); // ensure that true is 1 - api_incr_top(L); -} - -void lua_pushlightuserdatatagged(lua_State* L, void* p, int tag) -{ - api_check(L, unsigned(tag) < LUA_LUTAG_LIMIT); - setpvalue(L->top, p, tag); - api_incr_top(L); -} - -int lua_pushthread(lua_State* L) -{ - luaC_threadbarrier(L); - setthvalue(L, L->top, L); - api_incr_top(L); - return L->global->mainthread == L; -} - -/* -** get functions (Lua -> stack) -*/ - -int lua_gettable(lua_State* L, int idx) -{ - luaC_threadbarrier(L); - StkId t = index2addr(L, idx); - api_checkvalidindex(L, t); - luaV_gettable(L, t, L->top - 1, L->top - 1); - return ttype(L->top - 1); -} - -int lua_getfield(lua_State* L, int idx, const char* k) -{ - luaC_threadbarrier(L); - StkId t = index2addr(L, idx); - api_checkvalidindex(L, t); - TValue key; - setsvalue(L, &key, luaS_new(L, k)); - luaV_gettable(L, t, &key, L->top); - api_incr_top(L); - return ttype(L->top - 1); -} - -int lua_rawgetfield(lua_State* L, int idx, const char* k) -{ - luaC_threadbarrier(L); - StkId t = index2addr(L, idx); - api_check(L, ttistable(t)); - TValue key; - setsvalue(L, &key, luaS_new(L, k)); - setobj2s(L, L->top, luaH_getstr(hvalue(t), tsvalue(&key))); - api_incr_top(L); - return ttype(L->top - 1); -} - -int lua_rawget(lua_State* L, int idx) -{ - luaC_threadbarrier(L); - StkId t = index2addr(L, idx); - api_check(L, ttistable(t)); - setobj2s(L, L->top - 1, luaH_get(hvalue(t), L->top - 1)); - return ttype(L->top - 1); -} - -int lua_rawgeti(lua_State* L, int idx, int n) -{ - luaC_threadbarrier(L); - StkId t = index2addr(L, idx); - api_check(L, ttistable(t)); - setobj2s(L, L->top, luaH_getnum(hvalue(t), n)); - api_incr_top(L); - return ttype(L->top - 1); -} - -void lua_createtable(lua_State* L, int narray, int nrec) -{ - luaC_checkGC(L); - luaC_threadbarrier(L); - sethvalue(L, L->top, luaH_new(L, narray, nrec)); - api_incr_top(L); -} - -void lua_setreadonly(lua_State* L, int objindex, int enabled) -{ - const TValue* o = index2addr(L, objindex); - api_check(L, ttistable(o)); - Table* t = hvalue(o); - api_check(L, t != hvalue(registry(L))); - t->readonly = bool(enabled); -} - -int lua_getreadonly(lua_State* L, int objindex) -{ - const TValue* o = index2addr(L, objindex); - api_check(L, ttistable(o)); - Table* t = hvalue(o); - int res = t->readonly; - return res; -} - -void lua_setsafeenv(lua_State* L, int objindex, int enabled) -{ - const TValue* o = index2addr(L, objindex); - api_check(L, ttistable(o)); - Table* t = hvalue(o); - t->safeenv = bool(enabled); -} - -int lua_getmetatable(lua_State* L, int objindex) -{ - luaC_threadbarrier(L); - Table* mt = NULL; - const TValue* obj = index2addr(L, objindex); - switch (ttype(obj)) - { - case LUA_TTABLE: - mt = hvalue(obj)->metatable; - break; - case LUA_TUSERDATA: - mt = uvalue(obj)->metatable; - break; - default: - mt = L->global->mt[ttype(obj)]; - break; - } - if (mt) - { - sethvalue(L, L->top, mt); - api_incr_top(L); - } - return mt != NULL; -} - -void lua_getfenv(lua_State* L, int idx) -{ - luaC_threadbarrier(L); - StkId o = index2addr(L, idx); - api_checkvalidindex(L, o); - switch (ttype(o)) - { - case LUA_TFUNCTION: - sethvalue(L, L->top, clvalue(o)->env); - break; - case LUA_TTHREAD: - sethvalue(L, L->top, thvalue(o)->gt); - break; - default: - setnilvalue(L->top); - break; - } - api_incr_top(L); -} - -/* -** set functions (stack -> Lua) -*/ - -void lua_settable(lua_State* L, int idx) -{ - api_checknelems(L, 2); - StkId t = index2addr(L, idx); - api_checkvalidindex(L, t); - luaV_settable(L, t, L->top - 2, L->top - 1); - L->top -= 2; // pop index and value -} - -void lua_setfield(lua_State* L, int idx, const char* k) -{ - api_checknelems(L, 1); - StkId t = index2addr(L, idx); - api_checkvalidindex(L, t); - TValue key; - setsvalue(L, &key, luaS_new(L, k)); - luaV_settable(L, t, &key, L->top - 1); - L->top--; -} - -void lua_rawsetfield(lua_State* L, int idx, const char* k) -{ - api_checknelems(L, 1); - StkId t = index2addr(L, idx); - api_check(L, ttistable(t)); - if (hvalue(t)->readonly) - luaG_readonlyerror(L); - setobj2t(L, luaH_setstr(L, hvalue(t), luaS_new(L, k)), L->top - 1); - luaC_barriert(L, hvalue(t), L->top - 1); - L->top--; -} - -void lua_rawset(lua_State* L, int idx) -{ - api_checknelems(L, 2); - StkId t = index2addr(L, idx); - api_check(L, ttistable(t)); - if (hvalue(t)->readonly) - luaG_readonlyerror(L); - setobj2t(L, luaH_set(L, hvalue(t), L->top - 2), L->top - 1); - luaC_barriert(L, hvalue(t), L->top - 1); - L->top -= 2; -} - -void lua_rawseti(lua_State* L, int idx, int n) -{ - api_checknelems(L, 1); - StkId o = index2addr(L, idx); - api_check(L, ttistable(o)); - if (hvalue(o)->readonly) - luaG_readonlyerror(L); - setobj2t(L, luaH_setnum(L, hvalue(o), n), L->top - 1); - luaC_barriert(L, hvalue(o), L->top - 1); - L->top--; -} - -int lua_setmetatable(lua_State* L, int objindex) -{ - api_checknelems(L, 1); - TValue* obj = index2addr(L, objindex); - api_checkvalidindex(L, obj); - Table* mt = NULL; - if (!ttisnil(L->top - 1)) - { - api_check(L, ttistable(L->top - 1)); - mt = hvalue(L->top - 1); - } - switch (ttype(obj)) - { - case LUA_TTABLE: - { - if (hvalue(obj)->readonly) - luaG_readonlyerror(L); - hvalue(obj)->metatable = mt; - if (mt) - luaC_objbarrier(L, hvalue(obj), mt); - break; - } - case LUA_TUSERDATA: - { - uvalue(obj)->metatable = mt; - if (mt) - luaC_objbarrier(L, uvalue(obj), mt); - break; - } - default: - { - L->global->mt[ttype(obj)] = mt; - break; - } - } - L->top--; - return 1; -} - -int lua_setfenv(lua_State* L, int idx) -{ - int res = 1; - api_checknelems(L, 1); - StkId o = index2addr(L, idx); - api_checkvalidindex(L, o); - api_check(L, ttistable(L->top - 1)); - switch (ttype(o)) - { - case LUA_TFUNCTION: - clvalue(o)->env = hvalue(L->top - 1); - break; - case LUA_TTHREAD: - thvalue(o)->gt = hvalue(L->top - 1); - break; - default: - res = 0; - break; - } - if (res) - { - luaC_objbarrier(L, &gcvalue(o)->gch, hvalue(L->top - 1)); - } - L->top--; - return res; -} - -/* -** `load' and `call' functions (run Lua code) -*/ - -#define adjustresults(L, nres) \ - { \ - if (nres == LUA_MULTRET && L->top >= L->ci->top) \ - L->ci->top = L->top; \ - } - -#define checkresults(L, na, nr) api_check(L, (nr) == LUA_MULTRET || (L->ci->top - L->top >= (nr) - (na))) - -void lua_call(lua_State* L, int nargs, int nresults) -{ - StkId func; - api_checknelems(L, nargs + 1); - api_check(L, L->status == 0); - checkresults(L, nargs, nresults); - func = L->top - (nargs + 1); - - luaD_call(L, func, nresults); - - adjustresults(L, nresults); -} - -/* -** Execute a protected call. -*/ -struct CallS -{ // data to `f_call' - StkId func; - int nresults; -}; - -static void f_call(lua_State* L, void* ud) -{ - struct CallS* c = cast_to(struct CallS*, ud); - luaD_call(L, c->func, c->nresults); -} - -int lua_pcall(lua_State* L, int nargs, int nresults, int errfunc) -{ - api_checknelems(L, nargs + 1); - api_check(L, L->status == 0); - checkresults(L, nargs, nresults); - ptrdiff_t func = 0; - if (errfunc != 0) - { - StkId o = index2addr(L, errfunc); - api_checkvalidindex(L, o); - func = savestack(L, o); - } - struct CallS c; - c.func = L->top - (nargs + 1); // function to be called - c.nresults = nresults; - - int status = luaD_pcall(L, f_call, &c, savestack(L, c.func), func); - - adjustresults(L, nresults); - return status; -} - -int lua_status(lua_State* L) -{ - return L->status; -} - -int lua_costatus(lua_State* L, lua_State* co) -{ - if (co == L) - return LUA_CORUN; - if (co->status == LUA_YIELD) - return LUA_COSUS; - if (co->status == LUA_BREAK) - return LUA_CONOR; - if (co->status != 0) // some error occurred - return LUA_COERR; - if (co->ci != co->base_ci) // does it have frames? - return LUA_CONOR; - if (co->top == co->base) - return LUA_COFIN; - return LUA_COSUS; // initial state -} - -void* lua_getthreaddata(lua_State* L) -{ - return L->userdata; -} - -void lua_setthreaddata(lua_State* L, void* data) -{ - L->userdata = data; -} - -/* -** Garbage-collection function -*/ - -int lua_gc(lua_State* L, int what, int data) -{ - int res = 0; - condhardmemtests(luaC_validate(L), 1); - global_State* g = L->global; - switch (what) - { - case LUA_GCSTOP: - { - g->GCthreshold = SIZE_MAX; - break; - } - case LUA_GCRESTART: - { - g->GCthreshold = g->totalbytes; - break; - } - case LUA_GCCOLLECT: - { - luaC_fullgc(L); - break; - } - case LUA_GCCOUNT: - { - // GC values are expressed in Kbytes: #bytes/2^10 - res = cast_int(g->totalbytes >> 10); - break; - } - case LUA_GCCOUNTB: - { - res = cast_int(g->totalbytes & 1023); - break; - } - case LUA_GCISRUNNING: - { - res = (g->GCthreshold != SIZE_MAX); - break; - } - case LUA_GCSTEP: - { - size_t amount = (cast_to(size_t, data) << 10); - ptrdiff_t oldcredit = g->gcstate == GCSpause ? 0 : g->GCthreshold - g->totalbytes; - - // temporarily adjust the threshold so that we can perform GC work - if (amount <= g->totalbytes) - g->GCthreshold = g->totalbytes - amount; - else - g->GCthreshold = 0; - -#ifdef LUAI_GCMETRICS - double startmarktime = g->gcmetrics.currcycle.marktime; - double startsweeptime = g->gcmetrics.currcycle.sweeptime; -#endif - - // track how much work the loop will actually perform - size_t actualwork = 0; - - while (g->GCthreshold <= g->totalbytes) - { - size_t stepsize = luaC_step(L, false); - - actualwork += stepsize; - - if (g->gcstate == GCSpause) - { // end of cycle? - res = 1; // signal it - break; - } - } - -#ifdef LUAI_GCMETRICS - // record explicit step statistics - GCCycleMetrics* cyclemetrics = g->gcstate == GCSpause ? &g->gcmetrics.lastcycle : &g->gcmetrics.currcycle; - - double totalmarktime = cyclemetrics->marktime - startmarktime; - double totalsweeptime = cyclemetrics->sweeptime - startsweeptime; - - if (totalmarktime > 0.0) - { - cyclemetrics->markexplicitsteps++; - - if (totalmarktime > cyclemetrics->markmaxexplicittime) - cyclemetrics->markmaxexplicittime = totalmarktime; - } - - if (totalsweeptime > 0.0) - { - cyclemetrics->sweepexplicitsteps++; - - if (totalsweeptime > cyclemetrics->sweepmaxexplicittime) - cyclemetrics->sweepmaxexplicittime = totalsweeptime; - } -#endif - - // if cycle hasn't finished, advance threshold forward for the amount of extra work performed - if (g->gcstate != GCSpause) - { - // if a new cycle was triggered by explicit step, old 'credit' of GC work is 0 - ptrdiff_t newthreshold = g->totalbytes + actualwork + oldcredit; - g->GCthreshold = newthreshold < 0 ? 0 : newthreshold; - } - break; - } - case LUA_GCSETGOAL: - { - res = g->gcgoal; - g->gcgoal = data; - break; - } - case LUA_GCSETSTEPMUL: - { - res = g->gcstepmul; - g->gcstepmul = data; - break; - } - case LUA_GCSETSTEPSIZE: - { - // GC values are expressed in Kbytes: #bytes/2^10 - res = g->gcstepsize >> 10; - g->gcstepsize = data << 10; - break; - } - default: - res = -1; // invalid option - } - return res; -} - -/* -** miscellaneous functions -*/ - -l_noret lua_error(lua_State* L) -{ - api_checknelems(L, 1); - - luaD_throw(L, LUA_ERRRUN); -} - -int lua_next(lua_State* L, int idx) -{ - luaC_threadbarrier(L); - StkId t = index2addr(L, idx); - api_check(L, ttistable(t)); - int more = luaH_next(L, hvalue(t), L->top - 1); - if (more) - { - api_incr_top(L); - } - else // no more elements - L->top -= 1; // remove key - return more; -} - -int lua_rawiter(lua_State* L, int idx, int iter) -{ - luaC_threadbarrier(L); - StkId t = index2addr(L, idx); - api_check(L, ttistable(t)); - api_check(L, iter >= 0); - - Table* h = hvalue(t); - int sizearray = h->sizearray; - - // first we advance iter through the array portion - for (; unsigned(iter) < unsigned(sizearray); ++iter) - { - TValue* e = &h->array[iter]; - - if (!ttisnil(e)) - { - StkId top = L->top; - setnvalue(top + 0, double(iter + 1)); - setobj2s(L, top + 1, e); - api_update_top(L, top + 2); - return iter + 1; - } - } - - int sizenode = 1 << h->lsizenode; - - // then we advance iter through the hash portion - for (; unsigned(iter - sizearray) < unsigned(sizenode); ++iter) - { - LuaNode* n = &h->node[iter - sizearray]; - - if (!ttisnil(gval(n))) - { - StkId top = L->top; - getnodekey(L, top + 0, n); - setobj2s(L, top + 1, gval(n)); - api_update_top(L, top + 2); - return iter + 1; - } - } - - // traversal finished - return -1; -} - -void lua_concat(lua_State* L, int n) -{ - api_checknelems(L, n); - if (n >= 2) - { - luaC_checkGC(L); - luaC_threadbarrier(L); - luaV_concat(L, n, cast_int(L->top - L->base) - 1); - L->top -= (n - 1); - } - else if (n == 0) - { // push empty string - luaC_threadbarrier(L); - setsvalue(L, L->top, luaS_newlstr(L, "", 0)); - api_incr_top(L); - } - // else n == 1; nothing to do -} - -void* lua_newuserdatatagged(lua_State* L, size_t sz, int tag) -{ - api_check(L, unsigned(tag) < LUA_UTAG_LIMIT || tag == UTAG_PROXY); - luaC_checkGC(L); - luaC_threadbarrier(L); - Udata* u = luaU_newudata(L, sz, tag); - setuvalue(L, L->top, u); - api_incr_top(L); - return u->data; -} - -void* lua_newuserdatadtor(lua_State* L, size_t sz, void (*dtor)(void*)) -{ - luaC_checkGC(L); - luaC_threadbarrier(L); - // make sure sz + sizeof(dtor) doesn't overflow; luaU_newdata will reject SIZE_MAX correctly - size_t as = sz < SIZE_MAX - sizeof(dtor) ? sz + sizeof(dtor) : SIZE_MAX; - Udata* u = luaU_newudata(L, as, UTAG_IDTOR); - memcpy(&u->data + sz, &dtor, sizeof(dtor)); - setuvalue(L, L->top, u); - api_incr_top(L); - return u->data; -} - -void* lua_newbuffer(lua_State* L, size_t sz) -{ - luaC_checkGC(L); - luaC_threadbarrier(L); - Buffer* b = luaB_newbuffer(L, sz); - setbufvalue(L, L->top, b); - api_incr_top(L); - return b->data; -} - -static const char* aux_upvalue(StkId fi, int n, TValue** val) -{ - Closure* f; - if (!ttisfunction(fi)) - return NULL; - f = clvalue(fi); - if (f->isC) - { - if (!(1 <= n && n <= f->nupvalues)) - return NULL; - *val = &f->c.upvals[n - 1]; - return ""; - } - else - { - Proto* p = f->l.p; - if (!(1 <= n && n <= p->nups)) // not a valid upvalue - return NULL; - TValue* r = &f->l.uprefs[n - 1]; - *val = ttisupval(r) ? upvalue(r)->v : r; - if (!(1 <= n && n <= p->sizeupvalues)) // don't have a name for this upvalue - return ""; - return getstr(p->upvalues[n - 1]); - } -} - -const char* lua_getupvalue(lua_State* L, int funcindex, int n) -{ - luaC_threadbarrier(L); - TValue* val; - const char* name = aux_upvalue(index2addr(L, funcindex), n, &val); - if (name) - { - setobj2s(L, L->top, val); - api_incr_top(L); - } - return name; -} - -const char* lua_setupvalue(lua_State* L, int funcindex, int n) -{ - api_checknelems(L, 1); - StkId fi = index2addr(L, funcindex); - TValue* val; - const char* name = aux_upvalue(fi, n, &val); - if (name) - { - L->top--; - setobj(L, val, L->top); - luaC_barrier(L, clvalue(fi), L->top); - } - return name; -} - -uintptr_t lua_encodepointer(lua_State* L, uintptr_t p) -{ - global_State* g = L->global; - return uintptr_t((g->ptrenckey[0] * p + g->ptrenckey[2]) ^ (g->ptrenckey[1] * p + g->ptrenckey[3])); -} - -int lua_ref(lua_State* L, int idx) -{ - api_check(L, idx != LUA_REGISTRYINDEX); // idx is a stack index for value - int ref = LUA_REFNIL; - global_State* g = L->global; - StkId p = index2addr(L, idx); - if (!ttisnil(p)) - { - Table* reg = hvalue(registry(L)); - - if (g->registryfree != 0) - { // reuse existing slot - ref = g->registryfree; - } - else - { // no free elements - ref = luaH_getn(reg); - ref++; // create new reference - } - - TValue* slot = luaH_setnum(L, reg, ref); - if (g->registryfree != 0) - g->registryfree = int(nvalue(slot)); - setobj2t(L, slot, p); - luaC_barriert(L, reg, p); - } - return ref; -} - -void lua_unref(lua_State* L, int ref) -{ - if (ref <= LUA_REFNIL) - return; - - global_State* g = L->global; - Table* reg = hvalue(registry(L)); - TValue* slot = luaH_setnum(L, reg, ref); - setnvalue(slot, g->registryfree); // NB: no barrier needed because value isn't collectable - g->registryfree = ref; -} - -void lua_setuserdatatag(lua_State* L, int idx, int tag) -{ - api_check(L, unsigned(tag) < LUA_UTAG_LIMIT); - StkId o = index2addr(L, idx); - api_check(L, ttisuserdata(o)); - uvalue(o)->tag = uint8_t(tag); -} - -void lua_setuserdatadtor(lua_State* L, int tag, lua_Destructor dtor) -{ - api_check(L, unsigned(tag) < LUA_UTAG_LIMIT); - L->global->udatagc[tag] = dtor; -} - -lua_Destructor lua_getuserdatadtor(lua_State* L, int tag) -{ - api_check(L, unsigned(tag) < LUA_UTAG_LIMIT); - return L->global->udatagc[tag]; -} - -void lua_setlightuserdataname(lua_State* L, int tag, const char* name) -{ - api_check(L, unsigned(tag) < LUA_LUTAG_LIMIT); - api_check(L, !L->global->lightuserdataname[tag]); // renaming not supported - if (!L->global->lightuserdataname[tag]) - { - L->global->lightuserdataname[tag] = luaS_new(L, name); - luaS_fix(L->global->lightuserdataname[tag]); // never collect these names - } -} - -const char* lua_getlightuserdataname(lua_State* L, int tag) -{ - api_check(L, unsigned(tag) < LUA_LUTAG_LIMIT); - const TString* name = L->global->lightuserdataname[tag]; - return name ? getstr(name) : nullptr; -} - -void lua_clonefunction(lua_State* L, int idx) -{ - luaC_checkGC(L); - luaC_threadbarrier(L); - StkId p = index2addr(L, idx); - api_check(L, isLfunction(p)); - Closure* cl = clvalue(p); - Closure* newcl = luaF_newLclosure(L, cl->nupvalues, L->gt, cl->l.p); - for (int i = 0; i < cl->nupvalues; ++i) - setobj2n(L, &newcl->l.uprefs[i], &cl->l.uprefs[i]); - setclvalue(L, L->top, newcl); - api_incr_top(L); -} - -void lua_cleartable(lua_State* L, int idx) -{ - StkId t = index2addr(L, idx); - api_check(L, ttistable(t)); - Table* tt = hvalue(t); - if (tt->readonly) - luaG_readonlyerror(L); - luaH_clear(tt); -} - -lua_Callbacks* lua_callbacks(lua_State* L) -{ - return &L->global->cb; -} - -void lua_setmemcat(lua_State* L, int category) -{ - api_check(L, unsigned(category) < LUA_MEMORY_CATEGORIES); - L->activememcat = uint8_t(category); -} - -size_t lua_totalbytes(lua_State* L, int category) -{ - api_check(L, category < LUA_MEMORY_CATEGORIES); - return category < 0 ? L->global->totalbytes : L->global->memcatbytes[category]; -} - -lua_Alloc lua_getallocf(lua_State* L, void** ud) -{ - lua_Alloc f = L->global->frealloc; - if (ud) - *ud = L->global->ud; - return f; -} diff --git a/lib/luau/VM/src/lapi.h b/lib/luau/VM/src/lapi.h deleted file mode 100644 index b727218..0000000 --- a/lib/luau/VM/src/lapi.h +++ /dev/null @@ -1,8 +0,0 @@ -// This file is part of the Luau programming language and is licensed under MIT License; see LICENSE.txt for details -// This code is based on Lua 5.x implementation licensed under MIT License; see lua_LICENSE.txt for details -#pragma once - -#include "lobject.h" - -LUAI_FUNC const TValue* luaA_toobject(lua_State* L, int idx); -LUAI_FUNC void luaA_pushobject(lua_State* L, const TValue* o); diff --git a/lib/luau/VM/src/laux.cpp b/lib/luau/VM/src/laux.cpp deleted file mode 100644 index 4262eb4..0000000 --- a/lib/luau/VM/src/laux.cpp +++ /dev/null @@ -1,586 +0,0 @@ -// This file is part of the Luau programming language and is licensed under MIT License; see LICENSE.txt for details -// This code is based on Lua 5.x implementation licensed under MIT License; see lua_LICENSE.txt for details -#include "lualib.h" - -#include "lobject.h" -#include "lstate.h" -#include "lstring.h" -#include "lapi.h" -#include "lgc.h" -#include "lnumutils.h" - -#include - -// convert a stack index to positive -#define abs_index(L, i) ((i) > 0 || (i) <= LUA_REGISTRYINDEX ? (i) : lua_gettop(L) + (i) + 1) - -/* -** {====================================================== -** Error-report functions -** ======================================================= -*/ - -static const char* currfuncname(lua_State* L) -{ - Closure* cl = L->ci > L->base_ci ? curr_func(L) : NULL; - const char* debugname = cl && cl->isC ? cl->c.debugname + 0 : NULL; - - if (debugname && strcmp(debugname, "__namecall") == 0) - return L->namecall ? getstr(L->namecall) : NULL; - else - return debugname; -} - -l_noret luaL_argerrorL(lua_State* L, int narg, const char* extramsg) -{ - const char* fname = currfuncname(L); - - if (fname) - luaL_error(L, "invalid argument #%d to '%s' (%s)", narg, fname, extramsg); - else - luaL_error(L, "invalid argument #%d (%s)", narg, extramsg); -} - -l_noret luaL_typeerrorL(lua_State* L, int narg, const char* tname) -{ - const char* fname = currfuncname(L); - const TValue* obj = luaA_toobject(L, narg); - - if (obj) - { - if (fname) - luaL_error(L, "invalid argument #%d to '%s' (%s expected, got %s)", narg, fname, tname, luaT_objtypename(L, obj)); - else - luaL_error(L, "invalid argument #%d (%s expected, got %s)", narg, tname, luaT_objtypename(L, obj)); - } - else - { - if (fname) - luaL_error(L, "missing argument #%d to '%s' (%s expected)", narg, fname, tname); - else - luaL_error(L, "missing argument #%d (%s expected)", narg, tname); - } -} - -static l_noret tag_error(lua_State* L, int narg, int tag) -{ - luaL_typeerrorL(L, narg, lua_typename(L, tag)); -} - -void luaL_where(lua_State* L, int level) -{ - lua_Debug ar; - if (lua_getinfo(L, level, "sl", &ar) && ar.currentline > 0) - { - lua_pushfstring(L, "%s:%d: ", ar.short_src, ar.currentline); - return; - } - lua_pushliteral(L, ""); // else, no information available... -} - -l_noret luaL_errorL(lua_State* L, const char* fmt, ...) -{ - va_list argp; - va_start(argp, fmt); - luaL_where(L, 1); - lua_pushvfstring(L, fmt, argp); - va_end(argp); - lua_concat(L, 2); - lua_error(L); -} - -// }====================================================== - -int luaL_checkoption(lua_State* L, int narg, const char* def, const char* const lst[]) -{ - const char* name = (def) ? luaL_optstring(L, narg, def) : luaL_checkstring(L, narg); - int i; - for (i = 0; lst[i]; i++) - if (strcmp(lst[i], name) == 0) - return i; - const char* msg = lua_pushfstring(L, "invalid option '%s'", name); - luaL_argerrorL(L, narg, msg); -} - -int luaL_newmetatable(lua_State* L, const char* tname) -{ - lua_getfield(L, LUA_REGISTRYINDEX, tname); // get registry.name - if (!lua_isnil(L, -1)) // name already in use? - return 0; // leave previous value on top, but return 0 - lua_pop(L, 1); - lua_newtable(L); // create metatable - lua_pushvalue(L, -1); - lua_setfield(L, LUA_REGISTRYINDEX, tname); // registry.name = metatable - return 1; -} - -void* luaL_checkudata(lua_State* L, int ud, const char* tname) -{ - void* p = lua_touserdata(L, ud); - if (p != NULL) - { // value is a userdata? - if (lua_getmetatable(L, ud)) - { // does it have a metatable? - lua_getfield(L, LUA_REGISTRYINDEX, tname); // get correct metatable - if (lua_rawequal(L, -1, -2)) - { // does it have the correct mt? - lua_pop(L, 2); // remove both metatables - return p; - } - } - } - luaL_typeerrorL(L, ud, tname); // else error -} - -void* luaL_checkbuffer(lua_State* L, int narg, size_t* len) -{ - void* b = lua_tobuffer(L, narg, len); - if (!b) - tag_error(L, narg, LUA_TBUFFER); - return b; -} - -void luaL_checkstack(lua_State* L, int space, const char* mes) -{ - if (!lua_checkstack(L, space)) - luaL_error(L, "stack overflow (%s)", mes); -} - -void luaL_checktype(lua_State* L, int narg, int t) -{ - if (lua_type(L, narg) != t) - tag_error(L, narg, t); -} - -void luaL_checkany(lua_State* L, int narg) -{ - if (lua_type(L, narg) == LUA_TNONE) - luaL_error(L, "missing argument #%d", narg); -} - -const char* luaL_checklstring(lua_State* L, int narg, size_t* len) -{ - const char* s = lua_tolstring(L, narg, len); - if (!s) - tag_error(L, narg, LUA_TSTRING); - return s; -} - -const char* luaL_optlstring(lua_State* L, int narg, const char* def, size_t* len) -{ - if (lua_isnoneornil(L, narg)) - { - if (len) - *len = (def ? strlen(def) : 0); - return def; - } - else - return luaL_checklstring(L, narg, len); -} - -double luaL_checknumber(lua_State* L, int narg) -{ - int isnum; - double d = lua_tonumberx(L, narg, &isnum); - if (!isnum) - tag_error(L, narg, LUA_TNUMBER); - return d; -} - -double luaL_optnumber(lua_State* L, int narg, double def) -{ - return luaL_opt(L, luaL_checknumber, narg, def); -} - -int luaL_checkboolean(lua_State* L, int narg) -{ - // This checks specifically for boolean values, ignoring - // all other truthy/falsy values. If the desired result - // is true if value is present then lua_toboolean should - // directly be used instead. - if (!lua_isboolean(L, narg)) - tag_error(L, narg, LUA_TBOOLEAN); - return lua_toboolean(L, narg); -} - -int luaL_optboolean(lua_State* L, int narg, int def) -{ - return luaL_opt(L, luaL_checkboolean, narg, def); -} - -int luaL_checkinteger(lua_State* L, int narg) -{ - int isnum; - int d = lua_tointegerx(L, narg, &isnum); - if (!isnum) - tag_error(L, narg, LUA_TNUMBER); - return d; -} - -int luaL_optinteger(lua_State* L, int narg, int def) -{ - return luaL_opt(L, luaL_checkinteger, narg, def); -} - -unsigned luaL_checkunsigned(lua_State* L, int narg) -{ - int isnum; - unsigned d = lua_tounsignedx(L, narg, &isnum); - if (!isnum) - tag_error(L, narg, LUA_TNUMBER); - return d; -} - -unsigned luaL_optunsigned(lua_State* L, int narg, unsigned def) -{ - return luaL_opt(L, luaL_checkunsigned, narg, def); -} - -const float* luaL_checkvector(lua_State* L, int narg) -{ - const float* v = lua_tovector(L, narg); - if (!v) - tag_error(L, narg, LUA_TVECTOR); - return v; -} - -const float* luaL_optvector(lua_State* L, int narg, const float* def) -{ - return luaL_opt(L, luaL_checkvector, narg, def); -} - -int luaL_getmetafield(lua_State* L, int obj, const char* event) -{ - if (!lua_getmetatable(L, obj)) // no metatable? - return 0; - lua_pushstring(L, event); - lua_rawget(L, -2); - if (lua_isnil(L, -1)) - { - lua_pop(L, 2); // remove metatable and metafield - return 0; - } - else - { - lua_remove(L, -2); // remove only metatable - return 1; - } -} - -int luaL_callmeta(lua_State* L, int obj, const char* event) -{ - obj = abs_index(L, obj); - if (!luaL_getmetafield(L, obj, event)) // no metafield? - return 0; - lua_pushvalue(L, obj); - lua_call(L, 1, 1); - return 1; -} - -static int libsize(const luaL_Reg* l) -{ - int size = 0; - for (; l->name; l++) - size++; - return size; -} - -void luaL_register(lua_State* L, const char* libname, const luaL_Reg* l) -{ - if (libname) - { - int size = libsize(l); - // check whether lib already exists - luaL_findtable(L, LUA_REGISTRYINDEX, "_LOADED", 1); - lua_getfield(L, -1, libname); // get _LOADED[libname] - if (!lua_istable(L, -1)) - { // not found? - lua_pop(L, 1); // remove previous result - // try global variable (and create one if it does not exist) - if (luaL_findtable(L, LUA_GLOBALSINDEX, libname, size) != NULL) - luaL_error(L, "name conflict for module '%s'", libname); - lua_pushvalue(L, -1); - lua_setfield(L, -3, libname); // _LOADED[libname] = new table - } - lua_remove(L, -2); // remove _LOADED table - } - for (; l->name; l++) - { - lua_pushcfunction(L, l->func, l->name); - lua_setfield(L, -2, l->name); - } -} - -const char* luaL_findtable(lua_State* L, int idx, const char* fname, int szhint) -{ - const char* e; - lua_pushvalue(L, idx); - do - { - e = strchr(fname, '.'); - if (e == NULL) - e = fname + strlen(fname); - lua_pushlstring(L, fname, e - fname); - lua_rawget(L, -2); - if (lua_isnil(L, -1)) - { // no such field? - lua_pop(L, 1); // remove this nil - lua_createtable(L, 0, (*e == '.' ? 1 : szhint)); // new table for field - lua_pushlstring(L, fname, e - fname); - lua_pushvalue(L, -2); - lua_settable(L, -4); // set new table into field - } - else if (!lua_istable(L, -1)) - { // field has a non-table value? - lua_pop(L, 2); // remove table and value - return fname; // return problematic part of the name - } - lua_remove(L, -2); // remove previous table - fname = e + 1; - } while (*e == '.'); - return NULL; -} - -const char* luaL_typename(lua_State* L, int idx) -{ - const TValue* obj = luaA_toobject(L, idx); - return obj ? luaT_objtypename(L, obj) : "no value"; -} - -/* -** {====================================================== -** Generic Buffer manipulation -** ======================================================= -*/ - -static size_t getnextbuffersize(lua_State* L, size_t currentsize, size_t desiredsize) -{ - size_t newsize = currentsize + currentsize / 2; - - // check for size overflow - if (SIZE_MAX - desiredsize < currentsize) - luaL_error(L, "buffer too large"); - - // growth factor might not be enough to satisfy the desired size - if (newsize < desiredsize) - newsize = desiredsize; - - return newsize; -} - -static char* extendstrbuf(luaL_Strbuf* B, size_t additionalsize, int boxloc) -{ - lua_State* L = B->L; - - if (B->storage) - LUAU_ASSERT(B->storage == tsvalue(L->top + boxloc)); - - char* base = B->storage ? B->storage->data : B->buffer; - - size_t capacity = B->end - base; - size_t nextsize = getnextbuffersize(B->L, capacity, capacity + additionalsize); - - TString* newStorage = luaS_bufstart(L, nextsize); - - memcpy(newStorage->data, base, B->p - base); - - // place the string storage at the expected position in the stack - if (base == B->buffer) - { - lua_pushnil(L); - lua_insert(L, boxloc); - } - - setsvalue(L, L->top + boxloc, newStorage); - B->p = newStorage->data + (B->p - base); - B->end = newStorage->data + nextsize; - B->storage = newStorage; - - return B->p; -} - -void luaL_buffinit(lua_State* L, luaL_Strbuf* B) -{ - // start with an internal buffer - B->p = B->buffer; - B->end = B->p + LUA_BUFFERSIZE; - - B->L = L; - B->storage = nullptr; -} - -char* luaL_buffinitsize(lua_State* L, luaL_Strbuf* B, size_t size) -{ - luaL_buffinit(L, B); - return luaL_prepbuffsize(B, size); -} - -char* luaL_prepbuffsize(luaL_Strbuf* B, size_t size) -{ - if (size_t(B->end - B->p) < size) - return extendstrbuf(B, size - (B->end - B->p), -1); - return B->p; -} - -void luaL_addlstring(luaL_Strbuf* B, const char* s, size_t len) -{ - if (size_t(B->end - B->p) < len) - extendstrbuf(B, len - (B->end - B->p), -1); - - memcpy(B->p, s, len); - B->p += len; -} - -void luaL_addvalue(luaL_Strbuf* B) -{ - lua_State* L = B->L; - - size_t vl; - if (const char* s = lua_tolstring(L, -1, &vl)) - { - if (size_t(B->end - B->p) < vl) - extendstrbuf(B, vl - (B->end - B->p), -2); - - memcpy(B->p, s, vl); - B->p += vl; - - lua_pop(L, 1); - } -} - -void luaL_addvalueany(luaL_Strbuf* B, int idx) -{ - lua_State* L = B->L; - - switch (lua_type(L, idx)) - { - case LUA_TNONE: - { - LUAU_ASSERT(!"expected value"); - break; - } - case LUA_TNIL: - luaL_addstring(B, "nil"); - break; - case LUA_TBOOLEAN: - if (lua_toboolean(L, idx)) - luaL_addstring(B, "true"); - else - luaL_addstring(B, "false"); - break; - case LUA_TNUMBER: - { - double n = lua_tonumber(L, idx); - char s[LUAI_MAXNUM2STR]; - char* e = luai_num2str(s, n); - luaL_addlstring(B, s, e - s); - break; - } - case LUA_TSTRING: - { - size_t len; - const char* s = lua_tolstring(L, idx, &len); - luaL_addlstring(B, s, len); - break; - } - default: - { - size_t len; - luaL_tolstring(L, idx, &len); - - // note: luaL_addlstring assumes box is stored at top of stack, so we can't call it here - // instead we use luaL_addvalue which will take the string from the top of the stack and add that - luaL_addvalue(B); - } - } -} - -void luaL_pushresult(luaL_Strbuf* B) -{ - lua_State* L = B->L; - - if (TString* storage = B->storage) - { - luaC_checkGC(L); - - // if we finished just at the end of the string buffer, we can convert it to a mutable stirng without a copy - if (B->p == B->end) - { - setsvalue(L, L->top - 1, luaS_buffinish(L, storage)); - } - else - { - setsvalue(L, L->top - 1, luaS_newlstr(L, storage->data, B->p - storage->data)); - } - } - else - { - lua_pushlstring(L, B->buffer, B->p - B->buffer); - } -} - -void luaL_pushresultsize(luaL_Strbuf* B, size_t size) -{ - B->p += size; - luaL_pushresult(B); -} - -// }====================================================== - -const char* luaL_tolstring(lua_State* L, int idx, size_t* len) -{ - if (luaL_callmeta(L, idx, "__tostring")) // is there a metafield? - { - const char* s = lua_tolstring(L, -1, len); - if (!s) - luaL_error(L, "'__tostring' must return a string"); - return s; - } - - switch (lua_type(L, idx)) - { - case LUA_TNIL: - lua_pushliteral(L, "nil"); - break; - case LUA_TBOOLEAN: - lua_pushstring(L, (lua_toboolean(L, idx) ? "true" : "false")); - break; - case LUA_TNUMBER: - { - double n = lua_tonumber(L, idx); - char s[LUAI_MAXNUM2STR]; - char* e = luai_num2str(s, n); - lua_pushlstring(L, s, e - s); - break; - } - case LUA_TVECTOR: - { - const float* v = lua_tovector(L, idx); - - char s[LUAI_MAXNUM2STR * LUA_VECTOR_SIZE]; - char* e = s; - for (int i = 0; i < LUA_VECTOR_SIZE; ++i) - { - if (i != 0) - { - *e++ = ','; - *e++ = ' '; - } - e = luai_num2str(e, v[i]); - } - lua_pushlstring(L, s, e - s); - break; - } - case LUA_TSTRING: - lua_pushvalue(L, idx); - break; - default: - { - const void* ptr = lua_topointer(L, idx); - unsigned long long enc = lua_encodepointer(L, uintptr_t(ptr)); - lua_pushfstring(L, "%s: 0x%016llx", luaL_typename(L, idx), enc); - break; - } - } - return lua_tolstring(L, -1, len); -} diff --git a/lib/luau/VM/src/lbaselib.cpp b/lib/luau/VM/src/lbaselib.cpp deleted file mode 100644 index f4dac61..0000000 --- a/lib/luau/VM/src/lbaselib.cpp +++ /dev/null @@ -1,480 +0,0 @@ -// This file is part of the Luau programming language and is licensed under MIT License; see LICENSE.txt for details -// This code is based on Lua 5.x implementation licensed under MIT License; see lua_LICENSE.txt for details -#include "lualib.h" - -#include "lstate.h" -#include "lapi.h" -#include "ldo.h" -#include "ludata.h" - -#include -#include -#include - -static void writestring(const char* s, size_t l) -{ - fwrite(s, 1, l, stdout); -} - -static int luaB_print(lua_State* L) -{ - int n = lua_gettop(L); // number of arguments - for (int i = 1; i <= n; i++) - { - size_t l; - const char* s = luaL_tolstring(L, i, &l); // convert to string using __tostring et al - if (i > 1) - writestring("\t", 1); - writestring(s, l); - lua_pop(L, 1); // pop result - } - writestring("\n", 1); - return 0; -} - -static int luaB_tonumber(lua_State* L) -{ - int base = luaL_optinteger(L, 2, 10); - if (base == 10) - { // standard conversion - int isnum = 0; - double n = lua_tonumberx(L, 1, &isnum); - if (isnum) - { - lua_pushnumber(L, n); - return 1; - } - luaL_checkany(L, 1); // error if we don't have any argument - } - else - { - const char* s1 = luaL_checkstring(L, 1); - luaL_argcheck(L, 2 <= base && base <= 36, 2, "base out of range"); - char* s2; - unsigned long long n; - n = strtoull(s1, &s2, base); - if (s1 != s2) - { // at least one valid digit? - while (isspace((unsigned char)(*s2))) - s2++; // skip trailing spaces - if (*s2 == '\0') - { // no invalid trailing characters? - lua_pushnumber(L, (double)n); - return 1; - } - } - } - lua_pushnil(L); // else not a number - return 1; -} - -static int luaB_error(lua_State* L) -{ - int level = luaL_optinteger(L, 2, 1); - lua_settop(L, 1); - if (lua_isstring(L, 1) && level > 0) - { // add extra information? - luaL_where(L, level); - lua_pushvalue(L, 1); - lua_concat(L, 2); - } - lua_error(L); -} - -static int luaB_getmetatable(lua_State* L) -{ - luaL_checkany(L, 1); - if (!lua_getmetatable(L, 1)) - { - lua_pushnil(L); - return 1; // no metatable - } - luaL_getmetafield(L, 1, "__metatable"); - return 1; // returns either __metatable field (if present) or metatable -} - -static int luaB_setmetatable(lua_State* L) -{ - int t = lua_type(L, 2); - luaL_checktype(L, 1, LUA_TTABLE); - luaL_argexpected(L, t == LUA_TNIL || t == LUA_TTABLE, 2, "nil or table"); - if (luaL_getmetafield(L, 1, "__metatable")) - luaL_error(L, "cannot change a protected metatable"); - lua_settop(L, 2); - lua_setmetatable(L, 1); - return 1; -} - -static void getfunc(lua_State* L, int opt) -{ - if (lua_isfunction(L, 1)) - lua_pushvalue(L, 1); - else - { - lua_Debug ar; - int level = opt ? luaL_optinteger(L, 1, 1) : luaL_checkinteger(L, 1); - luaL_argcheck(L, level >= 0, 1, "level must be non-negative"); - if (lua_getinfo(L, level, "f", &ar) == 0) - luaL_argerror(L, 1, "invalid level"); - if (lua_isnil(L, -1)) - luaL_error(L, "no function environment for tail call at level %d", level); - } -} - -static int luaB_getfenv(lua_State* L) -{ - getfunc(L, 1); - if (lua_iscfunction(L, -1)) // is a C function? - lua_pushvalue(L, LUA_GLOBALSINDEX); // return the thread's global env. - else - lua_getfenv(L, -1); - lua_setsafeenv(L, -1, false); - return 1; -} - -static int luaB_setfenv(lua_State* L) -{ - luaL_checktype(L, 2, LUA_TTABLE); - getfunc(L, 0); - lua_pushvalue(L, 2); - lua_setsafeenv(L, -1, false); - if (lua_isnumber(L, 1) && lua_tonumber(L, 1) == 0) - { - // change environment of current thread - lua_pushthread(L); - lua_insert(L, -2); - lua_setfenv(L, -2); - return 0; - } - else if (lua_iscfunction(L, -2) || lua_setfenv(L, -2) == 0) - luaL_error(L, "'setfenv' cannot change environment of given object"); - return 1; -} - -static int luaB_rawequal(lua_State* L) -{ - luaL_checkany(L, 1); - luaL_checkany(L, 2); - lua_pushboolean(L, lua_rawequal(L, 1, 2)); - return 1; -} - -static int luaB_rawget(lua_State* L) -{ - luaL_checktype(L, 1, LUA_TTABLE); - luaL_checkany(L, 2); - lua_settop(L, 2); - lua_rawget(L, 1); - return 1; -} - -static int luaB_rawset(lua_State* L) -{ - luaL_checktype(L, 1, LUA_TTABLE); - luaL_checkany(L, 2); - luaL_checkany(L, 3); - lua_settop(L, 3); - lua_rawset(L, 1); - return 1; -} - -static int luaB_rawlen(lua_State* L) -{ - int tt = lua_type(L, 1); - luaL_argcheck(L, tt == LUA_TTABLE || tt == LUA_TSTRING, 1, "table or string expected"); - int len = lua_objlen(L, 1); - lua_pushinteger(L, len); - return 1; -} - -static int luaB_gcinfo(lua_State* L) -{ - lua_pushinteger(L, lua_gc(L, LUA_GCCOUNT, 0)); - return 1; -} - -static int luaB_type(lua_State* L) -{ - luaL_checkany(L, 1); - // resulting name doesn't differentiate between userdata types - lua_pushstring(L, lua_typename(L, lua_type(L, 1))); - return 1; -} - -static int luaB_typeof(lua_State* L) -{ - luaL_checkany(L, 1); - // resulting name returns __type if specified unless the input is a newproxy-created userdata - lua_pushstring(L, luaL_typename(L, 1)); - return 1; -} - -int luaB_next(lua_State* L) -{ - luaL_checktype(L, 1, LUA_TTABLE); - lua_settop(L, 2); // create a 2nd argument if there isn't one - if (lua_next(L, 1)) - return 2; - else - { - lua_pushnil(L); - return 1; - } -} - -static int luaB_pairs(lua_State* L) -{ - luaL_checktype(L, 1, LUA_TTABLE); - lua_pushvalue(L, lua_upvalueindex(1)); // return generator, - lua_pushvalue(L, 1); // state, - lua_pushnil(L); // and initial value - return 3; -} - -int luaB_inext(lua_State* L) -{ - int i = luaL_checkinteger(L, 2); - luaL_checktype(L, 1, LUA_TTABLE); - i++; // next value - lua_pushinteger(L, i); - lua_rawgeti(L, 1, i); - return (lua_isnil(L, -1)) ? 0 : 2; -} - -static int luaB_ipairs(lua_State* L) -{ - luaL_checktype(L, 1, LUA_TTABLE); - lua_pushvalue(L, lua_upvalueindex(1)); // return generator, - lua_pushvalue(L, 1); // state, - lua_pushinteger(L, 0); // and initial value - return 3; -} - -static int luaB_assert(lua_State* L) -{ - luaL_checkany(L, 1); - if (!lua_toboolean(L, 1)) - luaL_error(L, "%s", luaL_optstring(L, 2, "assertion failed!")); - return lua_gettop(L); -} - -static int luaB_select(lua_State* L) -{ - int n = lua_gettop(L); - if (lua_type(L, 1) == LUA_TSTRING && *lua_tostring(L, 1) == '#') - { - lua_pushinteger(L, n - 1); - return 1; - } - else - { - int i = luaL_checkinteger(L, 1); - if (i < 0) - i = n + i; - else if (i > n) - i = n; - luaL_argcheck(L, 1 <= i, 1, "index out of range"); - return n - i; - } -} - -static void luaB_pcallrun(lua_State* L, void* ud) -{ - StkId func = (StkId)ud; - - luaD_call(L, func, LUA_MULTRET); -} - -static int luaB_pcally(lua_State* L) -{ - luaL_checkany(L, 1); - - StkId func = L->base; - - // any errors from this point on are handled by continuation - L->ci->flags |= LUA_CALLINFO_HANDLE; - - // maintain yieldable invariant (baseCcalls <= nCcalls) - L->baseCcalls++; - int status = luaD_pcall(L, luaB_pcallrun, func, savestack(L, func), 0); - L->baseCcalls--; - - // necessary to accomodate functions that return lots of values - expandstacklimit(L, L->top); - - // yielding means we need to propagate yield; resume will call continuation function later - if (status == 0 && (L->status == LUA_YIELD || L->status == LUA_BREAK)) - return -1; // -1 is a marker for yielding from C - - // immediate return (error or success) - lua_rawcheckstack(L, 1); - lua_pushboolean(L, status == 0); - lua_insert(L, 1); - return lua_gettop(L); // return status + all results -} - -static int luaB_pcallcont(lua_State* L, int status) -{ - if (status == 0) - { - lua_rawcheckstack(L, 1); - lua_pushboolean(L, true); - lua_insert(L, 1); // insert status before all results - return lua_gettop(L); - } - else - { - lua_rawcheckstack(L, 1); - lua_pushboolean(L, false); - lua_insert(L, -2); // insert status before error object - return 2; - } -} - -static int luaB_xpcally(lua_State* L) -{ - luaL_checktype(L, 2, LUA_TFUNCTION); - - // swap function & error function - lua_pushvalue(L, 1); - lua_pushvalue(L, 2); - lua_replace(L, 1); - lua_replace(L, 2); - // at this point the stack looks like err, f, args - - // any errors from this point on are handled by continuation - L->ci->flags |= LUA_CALLINFO_HANDLE; - - StkId errf = L->base; - StkId func = L->base + 1; - - // maintain yieldable invariant (baseCcalls <= nCcalls) - L->baseCcalls++; - int status = luaD_pcall(L, luaB_pcallrun, func, savestack(L, func), savestack(L, errf)); - L->baseCcalls--; - - // necessary to accomodate functions that return lots of values - expandstacklimit(L, L->top); - - // yielding means we need to propagate yield; resume will call continuation function later - if (status == 0 && (L->status == LUA_YIELD || L->status == LUA_BREAK)) - return -1; // -1 is a marker for yielding from C - - // immediate return (error or success) - lua_rawcheckstack(L, 1); - lua_pushboolean(L, status == 0); - lua_replace(L, 1); // replace error function with status - return lua_gettop(L); // return status + all results -} - -static void luaB_xpcallerr(lua_State* L, void* ud) -{ - StkId func = (StkId)ud; - - luaD_call(L, func, 1); -} - -static int luaB_xpcallcont(lua_State* L, int status) -{ - if (status == 0) - { - lua_rawcheckstack(L, 1); - lua_pushboolean(L, true); - lua_replace(L, 1); // replace error function with status - return lua_gettop(L); // return status + all results - } - else - { - lua_rawcheckstack(L, 3); - lua_pushboolean(L, false); - lua_pushvalue(L, 1); // push error function on top of the stack - lua_pushvalue(L, -3); // push error object (that was on top of the stack before) - - StkId res = L->top - 3; - StkId errf = L->top - 2; - - // note: we pass res as errfunc as a short cut; if errf generates an error, we'll try to execute res (boolean) and fail - luaD_pcall(L, luaB_xpcallerr, errf, savestack(L, errf), savestack(L, res)); - - return 2; - } -} - -static int luaB_tostring(lua_State* L) -{ - luaL_checkany(L, 1); - luaL_tolstring(L, 1, NULL); - return 1; -} - -static int luaB_newproxy(lua_State* L) -{ - int t = lua_type(L, 1); - luaL_argexpected(L, t == LUA_TNONE || t == LUA_TNIL || t == LUA_TBOOLEAN, 1, "nil or boolean"); - - bool needsmt = lua_toboolean(L, 1); - - lua_newuserdatatagged(L, 0, UTAG_PROXY); - - if (needsmt) - { - lua_newtable(L); - lua_setmetatable(L, -2); - } - - return 1; -} - -static const luaL_Reg base_funcs[] = { - {"assert", luaB_assert}, - {"error", luaB_error}, - {"gcinfo", luaB_gcinfo}, - {"getfenv", luaB_getfenv}, - {"getmetatable", luaB_getmetatable}, - {"next", luaB_next}, - {"newproxy", luaB_newproxy}, - {"print", luaB_print}, - {"rawequal", luaB_rawequal}, - {"rawget", luaB_rawget}, - {"rawset", luaB_rawset}, - {"rawlen", luaB_rawlen}, - {"select", luaB_select}, - {"setfenv", luaB_setfenv}, - {"setmetatable", luaB_setmetatable}, - {"tonumber", luaB_tonumber}, - {"tostring", luaB_tostring}, - {"type", luaB_type}, - {"typeof", luaB_typeof}, - {NULL, NULL}, -}; - -static void auxopen(lua_State* L, const char* name, lua_CFunction f, lua_CFunction u) -{ - lua_pushcfunction(L, u, NULL); - lua_pushcclosure(L, f, name, 1); - lua_setfield(L, -2, name); -} - -int luaopen_base(lua_State* L) -{ - // set global _G - lua_pushvalue(L, LUA_GLOBALSINDEX); - lua_setglobal(L, "_G"); - - // open lib into global table - luaL_register(L, "_G", base_funcs); - lua_pushliteral(L, "Luau"); - lua_setglobal(L, "_VERSION"); // set global _VERSION - - // `ipairs' and `pairs' need auxiliary functions as upvalues - auxopen(L, "ipairs", luaB_ipairs, luaB_inext); - auxopen(L, "pairs", luaB_pairs, luaB_next); - - lua_pushcclosurek(L, luaB_pcally, "pcall", 0, luaB_pcallcont); - lua_setfield(L, -2, "pcall"); - - lua_pushcclosurek(L, luaB_xpcally, "xpcall", 0, luaB_xpcallcont); - lua_setfield(L, -2, "xpcall"); - - return 1; -} diff --git a/lib/luau/VM/src/lbitlib.cpp b/lib/luau/VM/src/lbitlib.cpp deleted file mode 100644 index 627d599..0000000 --- a/lib/luau/VM/src/lbitlib.cpp +++ /dev/null @@ -1,251 +0,0 @@ -// This file is part of the Luau programming language and is licensed under MIT License; see LICENSE.txt for details -// This code is based on Lua 5.x implementation licensed under MIT License; see lua_LICENSE.txt for details -#include "lualib.h" - -#include "lcommon.h" -#include "lnumutils.h" - -LUAU_FASTFLAGVARIABLE(LuauBit32Byteswap, false) - -#define ALLONES ~0u -#define NBITS int(8 * sizeof(unsigned)) - -// macro to trim extra bits -#define trim(x) ((x)&ALLONES) - -// builds a number with 'n' ones (1 <= n <= NBITS) -#define mask(n) (~((ALLONES << 1) << ((n)-1))) - -typedef unsigned b_uint; - -static b_uint andaux(lua_State* L) -{ - int i, n = lua_gettop(L); - b_uint r = ~(b_uint)0; - for (i = 1; i <= n; i++) - r &= luaL_checkunsigned(L, i); - return trim(r); -} - -static int b_and(lua_State* L) -{ - b_uint r = andaux(L); - lua_pushunsigned(L, r); - return 1; -} - -static int b_test(lua_State* L) -{ - b_uint r = andaux(L); - lua_pushboolean(L, r != 0); - return 1; -} - -static int b_or(lua_State* L) -{ - int i, n = lua_gettop(L); - b_uint r = 0; - for (i = 1; i <= n; i++) - r |= luaL_checkunsigned(L, i); - lua_pushunsigned(L, trim(r)); - return 1; -} - -static int b_xor(lua_State* L) -{ - int i, n = lua_gettop(L); - b_uint r = 0; - for (i = 1; i <= n; i++) - r ^= luaL_checkunsigned(L, i); - lua_pushunsigned(L, trim(r)); - return 1; -} - -static int b_not(lua_State* L) -{ - b_uint r = ~luaL_checkunsigned(L, 1); - lua_pushunsigned(L, trim(r)); - return 1; -} - -static int b_shift(lua_State* L, b_uint r, int i) -{ - if (i < 0) - { // shift right? - i = -i; - r = trim(r); - if (i >= NBITS) - r = 0; - else - r >>= i; - } - else - { // shift left - if (i >= NBITS) - r = 0; - else - r <<= i; - r = trim(r); - } - lua_pushunsigned(L, r); - return 1; -} - -static int b_lshift(lua_State* L) -{ - return b_shift(L, luaL_checkunsigned(L, 1), luaL_checkinteger(L, 2)); -} - -static int b_rshift(lua_State* L) -{ - return b_shift(L, luaL_checkunsigned(L, 1), -luaL_checkinteger(L, 2)); -} - -static int b_arshift(lua_State* L) -{ - b_uint r = luaL_checkunsigned(L, 1); - int i = luaL_checkinteger(L, 2); - if (i < 0 || !(r & ((b_uint)1 << (NBITS - 1)))) - return b_shift(L, r, -i); - else - { // arithmetic shift for 'negative' number - if (i >= NBITS) - r = ALLONES; - else - r = trim((r >> i) | ~(~(b_uint)0 >> i)); // add signal bit - lua_pushunsigned(L, r); - return 1; - } -} - -static int b_rot(lua_State* L, int i) -{ - b_uint r = luaL_checkunsigned(L, 1); - i &= (NBITS - 1); // i = i % NBITS - r = trim(r); - if (i != 0) // avoid undefined shift of NBITS when i == 0 - r = (r << i) | (r >> (NBITS - i)); - lua_pushunsigned(L, trim(r)); - return 1; -} - -static int b_lrot(lua_State* L) -{ - return b_rot(L, luaL_checkinteger(L, 2)); -} - -static int b_rrot(lua_State* L) -{ - return b_rot(L, -luaL_checkinteger(L, 2)); -} - -/* -** get field and width arguments for field-manipulation functions, -** checking whether they are valid. -** ('luaL_error' called without 'return' to avoid later warnings about -** 'width' being used uninitialized.) -*/ -static int fieldargs(lua_State* L, int farg, int* width) -{ - int f = luaL_checkinteger(L, farg); - int w = luaL_optinteger(L, farg + 1, 1); - luaL_argcheck(L, 0 <= f, farg, "field cannot be negative"); - luaL_argcheck(L, 0 < w, farg + 1, "width must be positive"); - if (f + w > NBITS) - luaL_error(L, "trying to access non-existent bits"); - *width = w; - return f; -} - -static int b_extract(lua_State* L) -{ - int w; - b_uint r = luaL_checkunsigned(L, 1); - int f = fieldargs(L, 2, &w); - r = (r >> f) & mask(w); - lua_pushunsigned(L, r); - return 1; -} - -static int b_replace(lua_State* L) -{ - int w; - b_uint r = luaL_checkunsigned(L, 1); - b_uint v = luaL_checkunsigned(L, 2); - int f = fieldargs(L, 3, &w); - int m = mask(w); - v &= m; // erase bits outside given width - r = (r & ~(m << f)) | (v << f); - lua_pushunsigned(L, r); - return 1; -} - -static int b_countlz(lua_State* L) -{ - b_uint v = luaL_checkunsigned(L, 1); - - b_uint r = NBITS; - for (int i = 0; i < NBITS; ++i) - if (v & (1u << (NBITS - 1 - i))) - { - r = i; - break; - } - - lua_pushunsigned(L, r); - return 1; -} - -static int b_countrz(lua_State* L) -{ - b_uint v = luaL_checkunsigned(L, 1); - - b_uint r = NBITS; - for (int i = 0; i < NBITS; ++i) - if (v & (1u << i)) - { - r = i; - break; - } - - lua_pushunsigned(L, r); - return 1; -} - -static int b_swap(lua_State* L) -{ - if (!FFlag::LuauBit32Byteswap) - luaL_error(L, "bit32.byteswap isn't enabled"); - - b_uint n = luaL_checkunsigned(L, 1); - n = (n << 24) | ((n << 8) & 0xff0000) | ((n >> 8) & 0xff00) | (n >> 24); - - lua_pushunsigned(L, n); - return 1; -} - -static const luaL_Reg bitlib[] = { - {"arshift", b_arshift}, - {"band", b_and}, - {"bnot", b_not}, - {"bor", b_or}, - {"bxor", b_xor}, - {"btest", b_test}, - {"extract", b_extract}, - {"lrotate", b_lrot}, - {"lshift", b_lshift}, - {"replace", b_replace}, - {"rrotate", b_rrot}, - {"rshift", b_rshift}, - {"countlz", b_countlz}, - {"countrz", b_countrz}, - {"byteswap", b_swap}, - {NULL, NULL}, -}; - -int luaopen_bit32(lua_State* L) -{ - luaL_register(L, LUA_BITLIBNAME, bitlib); - - return 1; -} diff --git a/lib/luau/VM/src/lbuffer.cpp b/lib/luau/VM/src/lbuffer.cpp deleted file mode 100644 index 04e5eec..0000000 --- a/lib/luau/VM/src/lbuffer.cpp +++ /dev/null @@ -1,24 +0,0 @@ -// This file is part of the Luau programming language and is licensed under MIT License; see LICENSE.txt for details -#include "lbuffer.h" - -#include "lgc.h" -#include "lmem.h" - -#include - -Buffer* luaB_newbuffer(lua_State* L, size_t s) -{ - if (s > MAX_BUFFER_SIZE) - luaM_toobig(L); - - Buffer* b = luaM_newgco(L, Buffer, sizebuffer(s), L->activememcat); - luaC_init(L, b, LUA_TBUFFER); - b->len = unsigned(s); - memset(b->data, 0, b->len); - return b; -} - -void luaB_freebuffer(lua_State* L, Buffer* b, lua_Page* page) -{ - luaM_freegco(L, b, sizebuffer(b->len), b->memcat, page); -} diff --git a/lib/luau/VM/src/lbuffer.h b/lib/luau/VM/src/lbuffer.h deleted file mode 100644 index 728e89b..0000000 --- a/lib/luau/VM/src/lbuffer.h +++ /dev/null @@ -1,13 +0,0 @@ -// This file is part of the Luau programming language and is licensed under MIT License; see LICENSE.txt for details -#pragma once - -#include "lobject.h" - -// buffer size limit -#define MAX_BUFFER_SIZE (1 << 30) - -// GCObject size has to be at least 16 bytes, so a minimum of 8 bytes is always reserved -#define sizebuffer(len) (offsetof(Buffer, data) + ((len) < 8 ? 8 : (len))) - -LUAI_FUNC Buffer* luaB_newbuffer(lua_State* L, size_t s); -LUAI_FUNC void luaB_freebuffer(lua_State* L, Buffer* u, struct lua_Page* page); diff --git a/lib/luau/VM/src/lbuflib.cpp b/lib/luau/VM/src/lbuflib.cpp deleted file mode 100644 index 3fb6e16..0000000 --- a/lib/luau/VM/src/lbuflib.cpp +++ /dev/null @@ -1,309 +0,0 @@ -// This file is part of the Luau programming language and is licensed under MIT License; see LICENSE.txt for details -#include "lualib.h" - -#include "lcommon.h" -#include "lbuffer.h" - -#if defined(LUAU_BIG_ENDIAN) -#include -#endif - -#include - -LUAU_FASTFLAGVARIABLE(LuauBufferBetterMsg, false) - -// while C API returns 'size_t' for binary compatibility in case of future extensions, -// in the current implementation, length and offset are limited to 31 bits -// because offset is limited to an integer, a single 64bit comparison can be used and will not overflow -#define isoutofbounds(offset, len, accessize) (uint64_t(unsigned(offset)) + (accessize) > uint64_t(len)) - -static_assert(MAX_BUFFER_SIZE <= INT_MAX, "current implementation can't handle a larger limit"); - -#if defined(LUAU_BIG_ENDIAN) -template -inline T buffer_swapbe(T v) -{ - if (sizeof(T) == 8) - return htole64(v); - else if (sizeof(T) == 4) - return htole32(v); - else if (sizeof(T) == 2) - return htole16(v); - else - return v; -} -#endif - -static int buffer_create(lua_State* L) -{ - int size = luaL_checkinteger(L, 1); - - if (FFlag::LuauBufferBetterMsg) - { - luaL_argcheck(L, size >= 0, 1, "size"); - } - else - { - if (size < 0) - luaL_error(L, "invalid size"); - } - - lua_newbuffer(L, size); - return 1; -} - -static int buffer_fromstring(lua_State* L) -{ - size_t len = 0; - const char* val = luaL_checklstring(L, 1, &len); - - void* data = lua_newbuffer(L, len); - memcpy(data, val, len); - return 1; -} - -static int buffer_tostring(lua_State* L) -{ - size_t len = 0; - void* data = luaL_checkbuffer(L, 1, &len); - - lua_pushlstring(L, (char*)data, len); - return 1; -} - -template -static int buffer_readinteger(lua_State* L) -{ - size_t len = 0; - void* buf = luaL_checkbuffer(L, 1, &len); - int offset = luaL_checkinteger(L, 2); - - if (isoutofbounds(offset, len, sizeof(T))) - luaL_error(L, "buffer access out of bounds"); - - T val; - memcpy(&val, (char*)buf + offset, sizeof(T)); - -#if defined(LUAU_BIG_ENDIAN) - val = buffer_swapbe(val); -#endif - - lua_pushnumber(L, double(val)); - return 1; -} - -template -static int buffer_writeinteger(lua_State* L) -{ - size_t len = 0; - void* buf = luaL_checkbuffer(L, 1, &len); - int offset = luaL_checkinteger(L, 2); - int value = luaL_checkunsigned(L, 3); - - if (isoutofbounds(offset, len, sizeof(T))) - luaL_error(L, "buffer access out of bounds"); - - T val = T(value); - -#if defined(LUAU_BIG_ENDIAN) - val = buffer_swapbe(val); -#endif - - memcpy((char*)buf + offset, &val, sizeof(T)); - return 0; -} - -template -static int buffer_readfp(lua_State* L) -{ - size_t len = 0; - void* buf = luaL_checkbuffer(L, 1, &len); - int offset = luaL_checkinteger(L, 2); - - if (isoutofbounds(offset, len, sizeof(T))) - luaL_error(L, "buffer access out of bounds"); - - T val; - -#if defined(LUAU_BIG_ENDIAN) - static_assert(sizeof(T) == sizeof(StorageType), "type size must match to reinterpret data"); - StorageType tmp; - memcpy(&tmp, (char*)buf + offset, sizeof(tmp)); - tmp = buffer_swapbe(tmp); - - memcpy(&val, &tmp, sizeof(tmp)); -#else - memcpy(&val, (char*)buf + offset, sizeof(T)); -#endif - - lua_pushnumber(L, double(val)); - return 1; -} - -template -static int buffer_writefp(lua_State* L) -{ - size_t len = 0; - void* buf = luaL_checkbuffer(L, 1, &len); - int offset = luaL_checkinteger(L, 2); - double value = luaL_checknumber(L, 3); - - if (isoutofbounds(offset, len, sizeof(T))) - luaL_error(L, "buffer access out of bounds"); - - T val = T(value); - -#if defined(LUAU_BIG_ENDIAN) - static_assert(sizeof(T) == sizeof(StorageType), "type size must match to reinterpret data"); - StorageType tmp; - memcpy(&tmp, &val, sizeof(tmp)); - tmp = buffer_swapbe(tmp); - - memcpy((char*)buf + offset, &tmp, sizeof(tmp)); -#else - memcpy((char*)buf + offset, &val, sizeof(T)); -#endif - - return 0; -} - -static int buffer_readstring(lua_State* L) -{ - size_t len = 0; - void* buf = luaL_checkbuffer(L, 1, &len); - int offset = luaL_checkinteger(L, 2); - int size = luaL_checkinteger(L, 3); - - if (FFlag::LuauBufferBetterMsg) - { - luaL_argcheck(L, size >= 0, 3, "size"); - } - else - { - if (size < 0) - luaL_error(L, "invalid size"); - } - - if (isoutofbounds(offset, len, unsigned(size))) - luaL_error(L, "buffer access out of bounds"); - - lua_pushlstring(L, (char*)buf + offset, size); - return 1; -} - -static int buffer_writestring(lua_State* L) -{ - size_t len = 0; - void* buf = luaL_checkbuffer(L, 1, &len); - int offset = luaL_checkinteger(L, 2); - size_t size = 0; - const char* val = luaL_checklstring(L, 3, &size); - int count = luaL_optinteger(L, 4, int(size)); - - if (FFlag::LuauBufferBetterMsg) - { - luaL_argcheck(L, count >= 0, 4, "count"); - } - else - { - if (count < 0) - luaL_error(L, "invalid count"); - } - - if (size_t(count) > size) - luaL_error(L, "string length overflow"); - - // string size can't exceed INT_MAX at this point - if (isoutofbounds(offset, len, unsigned(count))) - luaL_error(L, "buffer access out of bounds"); - - memcpy((char*)buf + offset, val, count); - return 0; -} - -static int buffer_len(lua_State* L) -{ - size_t len = 0; - luaL_checkbuffer(L, 1, &len); - - lua_pushnumber(L, double(unsigned(len))); - return 1; -} - -static int buffer_copy(lua_State* L) -{ - size_t tlen = 0; - void* tbuf = luaL_checkbuffer(L, 1, &tlen); - int toffset = luaL_checkinteger(L, 2); - - size_t slen = 0; - void* sbuf = luaL_checkbuffer(L, 3, &slen); - int soffset = luaL_optinteger(L, 4, 0); - - int size = luaL_optinteger(L, 5, int(slen) - soffset); - - if (size < 0) - luaL_error(L, "buffer access out of bounds"); - - if (isoutofbounds(soffset, slen, unsigned(size))) - luaL_error(L, "buffer access out of bounds"); - - if (isoutofbounds(toffset, tlen, unsigned(size))) - luaL_error(L, "buffer access out of bounds"); - - memmove((char*)tbuf + toffset, (char*)sbuf + soffset, size); - return 0; -} - -static int buffer_fill(lua_State* L) -{ - size_t len = 0; - void* buf = luaL_checkbuffer(L, 1, &len); - int offset = luaL_checkinteger(L, 2); - unsigned value = luaL_checkunsigned(L, 3); - int size = luaL_optinteger(L, 4, int(len) - offset); - - if (size < 0) - luaL_error(L, "buffer access out of bounds"); - - if (isoutofbounds(offset, len, unsigned(size))) - luaL_error(L, "buffer access out of bounds"); - - memset((char*)buf + offset, value & 0xff, size); - return 0; -} - -static const luaL_Reg bufferlib[] = { - {"create", buffer_create}, - {"fromstring", buffer_fromstring}, - {"tostring", buffer_tostring}, - {"readi8", buffer_readinteger}, - {"readu8", buffer_readinteger}, - {"readi16", buffer_readinteger}, - {"readu16", buffer_readinteger}, - {"readi32", buffer_readinteger}, - {"readu32", buffer_readinteger}, - {"readf32", buffer_readfp}, - {"readf64", buffer_readfp}, - {"writei8", buffer_writeinteger}, - {"writeu8", buffer_writeinteger}, - {"writei16", buffer_writeinteger}, - {"writeu16", buffer_writeinteger}, - {"writei32", buffer_writeinteger}, - {"writeu32", buffer_writeinteger}, - {"writef32", buffer_writefp}, - {"writef64", buffer_writefp}, - {"readstring", buffer_readstring}, - {"writestring", buffer_writestring}, - {"len", buffer_len}, - {"copy", buffer_copy}, - {"fill", buffer_fill}, - {NULL, NULL}, -}; - -int luaopen_buffer(lua_State* L) -{ - luaL_register(L, LUA_BUFFERLIBNAME, bufferlib); - - return 1; -} diff --git a/lib/luau/VM/src/lbuiltins.cpp b/lib/luau/VM/src/lbuiltins.cpp deleted file mode 100644 index e28bb16..0000000 --- a/lib/luau/VM/src/lbuiltins.cpp +++ /dev/null @@ -1,1638 +0,0 @@ -// This file is part of the Luau programming language and is licensed under MIT License; see LICENSE.txt for details -// This code is based on Lua 5.x implementation licensed under MIT License; see lua_LICENSE.txt for details -#include "lbuiltins.h" - -#include "lstate.h" -#include "lstring.h" -#include "ltable.h" -#include "lgc.h" -#include "lnumutils.h" -#include "ldo.h" -#include "lbuffer.h" - -#include -#include - -#ifdef _MSC_VER -#include -#endif - -#ifdef LUAU_TARGET_SSE41 -#include - -#ifndef _MSC_VER -#include // on MSVC this comes from intrin.h -#endif -#endif - -// luauF functions implement FASTCALL instruction that performs a direct execution of some builtin functions from the VM -// The rule of thumb is that FASTCALL functions can not call user code, yield, fail, or reallocate stack. -// If types of the arguments mismatch, luauF_* needs to return -1 and the execution will fall back to the usual call path -// If luauF_* succeeds, it needs to return *all* requested arguments, filling results with nil as appropriate. -// On input, nparams refers to the actual number of arguments (0+), whereas nresults contains LUA_MULTRET for arbitrary returns or 0+ for a -// fixed-length return -// Because of this, and the fact that "extra" returned values will be ignored, implementations below typically check that nresults is <= expected -// number, which covers the LUA_MULTRET case. - -static int luauF_assert(lua_State* L, StkId res, TValue* arg0, int nresults, StkId args, int nparams) -{ - if (nparams >= 1 && nresults == 0 && !l_isfalse(arg0)) - { - return 0; - } - - return -1; -} - -static int luauF_abs(lua_State* L, StkId res, TValue* arg0, int nresults, StkId args, int nparams) -{ - if (nparams >= 1 && nresults <= 1 && ttisnumber(arg0)) - { - double a1 = nvalue(arg0); - setnvalue(res, fabs(a1)); - return 1; - } - - return -1; -} - -static int luauF_acos(lua_State* L, StkId res, TValue* arg0, int nresults, StkId args, int nparams) -{ - if (nparams >= 1 && nresults <= 1 && ttisnumber(arg0)) - { - double a1 = nvalue(arg0); - setnvalue(res, acos(a1)); - return 1; - } - - return -1; -} - -static int luauF_asin(lua_State* L, StkId res, TValue* arg0, int nresults, StkId args, int nparams) -{ - if (nparams >= 1 && nresults <= 1 && ttisnumber(arg0)) - { - double a1 = nvalue(arg0); - setnvalue(res, asin(a1)); - return 1; - } - - return -1; -} - -static int luauF_atan2(lua_State* L, StkId res, TValue* arg0, int nresults, StkId args, int nparams) -{ - if (nparams >= 2 && nresults <= 1 && ttisnumber(arg0) && ttisnumber(args)) - { - double a1 = nvalue(arg0); - double a2 = nvalue(args); - setnvalue(res, atan2(a1, a2)); - return 1; - } - - return -1; -} - -static int luauF_atan(lua_State* L, StkId res, TValue* arg0, int nresults, StkId args, int nparams) -{ - if (nparams >= 1 && nresults <= 1 && ttisnumber(arg0)) - { - double a1 = nvalue(arg0); - setnvalue(res, atan(a1)); - return 1; - } - - return -1; -} - -LUAU_FASTMATH_BEGIN -static int luauF_ceil(lua_State* L, StkId res, TValue* arg0, int nresults, StkId args, int nparams) -{ - if (nparams >= 1 && nresults <= 1 && ttisnumber(arg0)) - { - double a1 = nvalue(arg0); - setnvalue(res, ceil(a1)); - return 1; - } - - return -1; -} -LUAU_FASTMATH_END - -static int luauF_cosh(lua_State* L, StkId res, TValue* arg0, int nresults, StkId args, int nparams) -{ - if (nparams >= 1 && nresults <= 1 && ttisnumber(arg0)) - { - double a1 = nvalue(arg0); - setnvalue(res, cosh(a1)); - return 1; - } - - return -1; -} - -static int luauF_cos(lua_State* L, StkId res, TValue* arg0, int nresults, StkId args, int nparams) -{ - if (nparams >= 1 && nresults <= 1 && ttisnumber(arg0)) - { - double a1 = nvalue(arg0); - setnvalue(res, cos(a1)); - return 1; - } - - return -1; -} - -static int luauF_deg(lua_State* L, StkId res, TValue* arg0, int nresults, StkId args, int nparams) -{ - if (nparams >= 1 && nresults <= 1 && ttisnumber(arg0)) - { - double a1 = nvalue(arg0); - const double rpd = (3.14159265358979323846 / 180.0); - setnvalue(res, a1 / rpd); - return 1; - } - - return -1; -} - -static int luauF_exp(lua_State* L, StkId res, TValue* arg0, int nresults, StkId args, int nparams) -{ - if (nparams >= 1 && nresults <= 1 && ttisnumber(arg0)) - { - double a1 = nvalue(arg0); - setnvalue(res, exp(a1)); - return 1; - } - - return -1; -} - -LUAU_FASTMATH_BEGIN -static int luauF_floor(lua_State* L, StkId res, TValue* arg0, int nresults, StkId args, int nparams) -{ - if (nparams >= 1 && nresults <= 1 && ttisnumber(arg0)) - { - double a1 = nvalue(arg0); - setnvalue(res, floor(a1)); - return 1; - } - - return -1; -} -LUAU_FASTMATH_END - -static int luauF_fmod(lua_State* L, StkId res, TValue* arg0, int nresults, StkId args, int nparams) -{ - if (nparams >= 2 && nresults <= 1 && ttisnumber(arg0) && ttisnumber(args)) - { - double a1 = nvalue(arg0); - double a2 = nvalue(args); - setnvalue(res, fmod(a1, a2)); - return 1; - } - - return -1; -} - -static int luauF_frexp(lua_State* L, StkId res, TValue* arg0, int nresults, StkId args, int nparams) -{ - if (nparams >= 1 && nresults <= 2 && ttisnumber(arg0)) - { - double a1 = nvalue(arg0); - int e; - double f = frexp(a1, &e); - setnvalue(res, f); - setnvalue(res + 1, double(e)); - return 2; - } - - return -1; -} - -static int luauF_ldexp(lua_State* L, StkId res, TValue* arg0, int nresults, StkId args, int nparams) -{ - if (nparams >= 2 && nresults <= 1 && ttisnumber(arg0) && ttisnumber(args)) - { - double a1 = nvalue(arg0); - double a2 = nvalue(args); - setnvalue(res, ldexp(a1, int(a2))); - return 1; - } - - return -1; -} - -static int luauF_log10(lua_State* L, StkId res, TValue* arg0, int nresults, StkId args, int nparams) -{ - if (nparams >= 1 && nresults <= 1 && ttisnumber(arg0)) - { - double a1 = nvalue(arg0); - setnvalue(res, log10(a1)); - return 1; - } - - return -1; -} - -static int luauF_log(lua_State* L, StkId res, TValue* arg0, int nresults, StkId args, int nparams) -{ - if (nparams >= 1 && nresults <= 1 && ttisnumber(arg0)) - { - double a1 = nvalue(arg0); - - if (nparams == 1) - { - setnvalue(res, log(a1)); - return 1; - } - else if (ttisnumber(args)) - { - double a2 = nvalue(args); - - if (a2 == 2.0) - { - setnvalue(res, log2(a1)); - return 1; - } - else if (a2 == 10.0) - { - setnvalue(res, log10(a1)); - return 1; - } - else - { - setnvalue(res, log(a1) / log(a2)); - return 1; - } - } - } - - return -1; -} - -static int luauF_max(lua_State* L, StkId res, TValue* arg0, int nresults, StkId args, int nparams) -{ - if (nparams >= 2 && nresults <= 1 && ttisnumber(arg0) && ttisnumber(args)) - { - double a1 = nvalue(arg0); - double a2 = nvalue(args); - - double r = (a2 > a1) ? a2 : a1; - - for (int i = 3; i <= nparams; ++i) - { - if (!ttisnumber(args + (i - 2))) - return -1; - - double a = nvalue(args + (i - 2)); - - r = (a > r) ? a : r; - } - - setnvalue(res, r); - return 1; - } - - return -1; -} - -static int luauF_min(lua_State* L, StkId res, TValue* arg0, int nresults, StkId args, int nparams) -{ - if (nparams >= 2 && nresults <= 1 && ttisnumber(arg0) && ttisnumber(args)) - { - double a1 = nvalue(arg0); - double a2 = nvalue(args); - - double r = (a2 < a1) ? a2 : a1; - - for (int i = 3; i <= nparams; ++i) - { - if (!ttisnumber(args + (i - 2))) - return -1; - - double a = nvalue(args + (i - 2)); - - r = (a < r) ? a : r; - } - - setnvalue(res, r); - return 1; - } - - return -1; -} - -static int luauF_modf(lua_State* L, StkId res, TValue* arg0, int nresults, StkId args, int nparams) -{ - if (nparams >= 1 && nresults <= 2 && ttisnumber(arg0)) - { - double a1 = nvalue(arg0); - double ip; - double fp = modf(a1, &ip); - setnvalue(res, ip); - setnvalue(res + 1, fp); - return 2; - } - - return -1; -} - -static int luauF_pow(lua_State* L, StkId res, TValue* arg0, int nresults, StkId args, int nparams) -{ - if (nparams >= 2 && nresults <= 1 && ttisnumber(arg0) && ttisnumber(args)) - { - double a1 = nvalue(arg0); - double a2 = nvalue(args); - setnvalue(res, pow(a1, a2)); - return 1; - } - - return -1; -} - -static int luauF_rad(lua_State* L, StkId res, TValue* arg0, int nresults, StkId args, int nparams) -{ - if (nparams >= 1 && nresults <= 1 && ttisnumber(arg0)) - { - double a1 = nvalue(arg0); - const double rpd = (3.14159265358979323846 / 180.0); - setnvalue(res, a1 * rpd); - return 1; - } - - return -1; -} - -static int luauF_sinh(lua_State* L, StkId res, TValue* arg0, int nresults, StkId args, int nparams) -{ - if (nparams >= 1 && nresults <= 1 && ttisnumber(arg0)) - { - double a1 = nvalue(arg0); - setnvalue(res, sinh(a1)); - return 1; - } - - return -1; -} - -static int luauF_sin(lua_State* L, StkId res, TValue* arg0, int nresults, StkId args, int nparams) -{ - if (nparams >= 1 && nresults <= 1 && ttisnumber(arg0)) - { - double a1 = nvalue(arg0); - setnvalue(res, sin(a1)); - return 1; - } - - return -1; -} - -LUAU_FASTMATH_BEGIN -static int luauF_sqrt(lua_State* L, StkId res, TValue* arg0, int nresults, StkId args, int nparams) -{ - if (nparams >= 1 && nresults <= 1 && ttisnumber(arg0)) - { - double a1 = nvalue(arg0); - setnvalue(res, sqrt(a1)); - return 1; - } - - return -1; -} -LUAU_FASTMATH_END - -static int luauF_tanh(lua_State* L, StkId res, TValue* arg0, int nresults, StkId args, int nparams) -{ - if (nparams >= 1 && nresults <= 1 && ttisnumber(arg0)) - { - double a1 = nvalue(arg0); - setnvalue(res, tanh(a1)); - return 1; - } - - return -1; -} - -static int luauF_tan(lua_State* L, StkId res, TValue* arg0, int nresults, StkId args, int nparams) -{ - if (nparams >= 1 && nresults <= 1 && ttisnumber(arg0)) - { - double a1 = nvalue(arg0); - setnvalue(res, tan(a1)); - return 1; - } - - return -1; -} - -static int luauF_arshift(lua_State* L, StkId res, TValue* arg0, int nresults, StkId args, int nparams) -{ - if (nparams >= 2 && nresults <= 1 && ttisnumber(arg0) && ttisnumber(args)) - { - double a1 = nvalue(arg0); - double a2 = nvalue(args); - - unsigned u; - luai_num2unsigned(u, a1); - int s = int(a2); - - // note: we only specialize fast-path that doesn't require further conditionals (negative shifts and shifts greater or equal to bit width can - // be handled generically) - if (unsigned(s) < 32) - { - // note: technically right shift of negative values is UB, but this behavior is getting defined in C++20 and all compilers do the right - // (shift) thing. - uint32_t r = int32_t(u) >> s; - - setnvalue(res, double(r)); - return 1; - } - } - - return -1; -} - -static int luauF_band(lua_State* L, StkId res, TValue* arg0, int nresults, StkId args, int nparams) -{ - if (nparams >= 2 && nresults <= 1 && ttisnumber(arg0) && ttisnumber(args)) - { - double a1 = nvalue(arg0); - double a2 = nvalue(args); - - unsigned u1, u2; - luai_num2unsigned(u1, a1); - luai_num2unsigned(u2, a2); - - uint32_t r = u1 & u2; - - for (int i = 3; i <= nparams; ++i) - { - if (!ttisnumber(args + (i - 2))) - return -1; - - double a = nvalue(args + (i - 2)); - unsigned u; - luai_num2unsigned(u, a); - - r &= u; - } - - setnvalue(res, double(r)); - return 1; - } - - return -1; -} - -static int luauF_bnot(lua_State* L, StkId res, TValue* arg0, int nresults, StkId args, int nparams) -{ - if (nparams >= 1 && nresults <= 1 && ttisnumber(arg0)) - { - double a1 = nvalue(arg0); - unsigned u; - luai_num2unsigned(u, a1); - - uint32_t r = ~u; - - setnvalue(res, double(r)); - return 1; - } - - return -1; -} - -static int luauF_bor(lua_State* L, StkId res, TValue* arg0, int nresults, StkId args, int nparams) -{ - if (nparams >= 2 && nresults <= 1 && ttisnumber(arg0) && ttisnumber(args)) - { - double a1 = nvalue(arg0); - double a2 = nvalue(args); - - unsigned u1, u2; - luai_num2unsigned(u1, a1); - luai_num2unsigned(u2, a2); - - uint32_t r = u1 | u2; - - for (int i = 3; i <= nparams; ++i) - { - if (!ttisnumber(args + (i - 2))) - return -1; - - double a = nvalue(args + (i - 2)); - unsigned u; - luai_num2unsigned(u, a); - - r |= u; - } - - setnvalue(res, double(r)); - return 1; - } - - return -1; -} - -static int luauF_bxor(lua_State* L, StkId res, TValue* arg0, int nresults, StkId args, int nparams) -{ - if (nparams >= 2 && nresults <= 1 && ttisnumber(arg0) && ttisnumber(args)) - { - double a1 = nvalue(arg0); - double a2 = nvalue(args); - - unsigned u1, u2; - luai_num2unsigned(u1, a1); - luai_num2unsigned(u2, a2); - - uint32_t r = u1 ^ u2; - - for (int i = 3; i <= nparams; ++i) - { - if (!ttisnumber(args + (i - 2))) - return -1; - - double a = nvalue(args + (i - 2)); - unsigned u; - luai_num2unsigned(u, a); - - r ^= u; - } - - setnvalue(res, double(r)); - return 1; - } - - return -1; -} - -static int luauF_btest(lua_State* L, StkId res, TValue* arg0, int nresults, StkId args, int nparams) -{ - if (nparams >= 2 && nresults <= 1 && ttisnumber(arg0) && ttisnumber(args)) - { - double a1 = nvalue(arg0); - double a2 = nvalue(args); - - unsigned u1, u2; - luai_num2unsigned(u1, a1); - luai_num2unsigned(u2, a2); - - uint32_t r = u1 & u2; - - for (int i = 3; i <= nparams; ++i) - { - if (!ttisnumber(args + (i - 2))) - return -1; - - double a = nvalue(args + (i - 2)); - unsigned u; - luai_num2unsigned(u, a); - - r &= u; - } - - setbvalue(res, r != 0); - return 1; - } - - return -1; -} - -static int luauF_extract(lua_State* L, StkId res, TValue* arg0, int nresults, StkId args, int nparams) -{ - if (nparams >= 2 && nresults <= 1 && ttisnumber(arg0) && ttisnumber(args)) - { - double a1 = nvalue(arg0); - double a2 = nvalue(args); - - unsigned n; - luai_num2unsigned(n, a1); - int f = int(a2); - - if (nparams == 2) - { - if (unsigned(f) < 32) - { - uint32_t m = 1; - uint32_t r = (n >> f) & m; - - setnvalue(res, double(r)); - return 1; - } - } - else if (ttisnumber(args + 1)) - { - double a3 = nvalue(args + 1); - int w = int(a3); - - if (f >= 0 && w > 0 && f + w <= 32) - { - uint32_t m = ~(0xfffffffeu << (w - 1)); - uint32_t r = (n >> f) & m; - - setnvalue(res, double(r)); - return 1; - } - } - } - - return -1; -} - -static int luauF_lrotate(lua_State* L, StkId res, TValue* arg0, int nresults, StkId args, int nparams) -{ - if (nparams >= 2 && nresults <= 1 && ttisnumber(arg0) && ttisnumber(args)) - { - double a1 = nvalue(arg0); - double a2 = nvalue(args); - - unsigned u; - luai_num2unsigned(u, a1); - int s = int(a2); - - // MSVC doesn't recognize the rotate form that is UB-safe -#ifdef _MSC_VER - uint32_t r = _rotl(u, s); -#else - uint32_t r = (u << (s & 31)) | (u >> ((32 - s) & 31)); -#endif - - setnvalue(res, double(r)); - return 1; - } - - return -1; -} - -static int luauF_lshift(lua_State* L, StkId res, TValue* arg0, int nresults, StkId args, int nparams) -{ - if (nparams >= 2 && nresults <= 1 && ttisnumber(arg0) && ttisnumber(args)) - { - double a1 = nvalue(arg0); - double a2 = nvalue(args); - - unsigned u; - luai_num2unsigned(u, a1); - int s = int(a2); - - // note: we only specialize fast-path that doesn't require further conditionals (negative shifts and shifts greater or equal to bit width can - // be handled generically) - if (unsigned(s) < 32) - { - uint32_t r = u << s; - - setnvalue(res, double(r)); - return 1; - } - } - - return -1; -} - -static int luauF_replace(lua_State* L, StkId res, TValue* arg0, int nresults, StkId args, int nparams) -{ - if (nparams >= 3 && nresults <= 1 && ttisnumber(arg0) && ttisnumber(args) && ttisnumber(args + 1)) - { - double a1 = nvalue(arg0); - double a2 = nvalue(args); - double a3 = nvalue(args + 1); - - unsigned n, v; - luai_num2unsigned(n, a1); - luai_num2unsigned(v, a2); - int f = int(a3); - - if (nparams == 3) - { - if (unsigned(f) < 32) - { - uint32_t m = 1; - uint32_t r = (n & ~(m << f)) | ((v & m) << f); - - setnvalue(res, double(r)); - return 1; - } - } - else if (ttisnumber(args + 2)) - { - double a4 = nvalue(args + 2); - int w = int(a4); - - if (f >= 0 && w > 0 && f + w <= 32) - { - uint32_t m = ~(0xfffffffeu << (w - 1)); - uint32_t r = (n & ~(m << f)) | ((v & m) << f); - - setnvalue(res, double(r)); - return 1; - } - } - } - - return -1; -} - -static int luauF_rrotate(lua_State* L, StkId res, TValue* arg0, int nresults, StkId args, int nparams) -{ - if (nparams >= 2 && nresults <= 1 && ttisnumber(arg0) && ttisnumber(args)) - { - double a1 = nvalue(arg0); - double a2 = nvalue(args); - - unsigned u; - luai_num2unsigned(u, a1); - int s = int(a2); - - // MSVC doesn't recognize the rotate form that is UB-safe -#ifdef _MSC_VER - uint32_t r = _rotr(u, s); -#else - uint32_t r = (u >> (s & 31)) | (u << ((32 - s) & 31)); -#endif - - setnvalue(res, double(r)); - return 1; - } - - return -1; -} - -static int luauF_rshift(lua_State* L, StkId res, TValue* arg0, int nresults, StkId args, int nparams) -{ - if (nparams >= 2 && nresults <= 1 && ttisnumber(arg0) && ttisnumber(args)) - { - double a1 = nvalue(arg0); - double a2 = nvalue(args); - - unsigned u; - luai_num2unsigned(u, a1); - int s = int(a2); - - // note: we only specialize fast-path that doesn't require further conditionals (negative shifts and shifts greater or equal to bit width can - // be handled generically) - if (unsigned(s) < 32) - { - uint32_t r = u >> s; - - setnvalue(res, double(r)); - return 1; - } - } - - return -1; -} - -static int luauF_type(lua_State* L, StkId res, TValue* arg0, int nresults, StkId args, int nparams) -{ - if (nparams >= 1 && nresults <= 1) - { - int tt = ttype(arg0); - TString* ttname = L->global->ttname[tt]; - - setsvalue(L, res, ttname); - return 1; - } - - return -1; -} - -static int luauF_byte(lua_State* L, StkId res, TValue* arg0, int nresults, StkId args, int nparams) -{ - if (nparams >= 2 && ttisstring(arg0) && ttisnumber(args)) - { - TString* ts = tsvalue(arg0); - int i = int(nvalue(args)); - int j = (nparams >= 3) ? (ttisnumber(args + 1) ? int(nvalue(args + 1)) : 0) : i; - - if (i >= 1 && j >= i && j <= int(ts->len)) - { - int c = j - i + 1; - const char* s = getstr(ts); - - // for vararg returns, we only support a single result - // this is because this frees us from concerns about stack space - if (c == (nresults < 0 ? 1 : nresults)) - { - for (int k = 0; k < c; ++k) - { - setnvalue(res + k, uint8_t(s[i + k - 1])); - } - - return c; - } - } - } - - return -1; -} - -static int luauF_char(lua_State* L, StkId res, TValue* arg0, int nresults, StkId args, int nparams) -{ - char buffer[8]; - - if (nparams < int(sizeof(buffer)) && nresults <= 1) - { - if (luaC_needsGC(L)) - return -1; // we can't call luaC_checkGC so fall back to C implementation - - if (nparams >= 1) - { - if (!ttisnumber(arg0)) - return -1; - - int ch = int(nvalue(arg0)); - - if ((unsigned char)(ch) != ch) - return -1; - - buffer[0] = ch; - } - - for (int i = 2; i <= nparams; ++i) - { - if (!ttisnumber(args + (i - 2))) - return -1; - - int ch = int(nvalue(args + (i - 2))); - - if ((unsigned char)(ch) != ch) - return -1; - - buffer[i - 1] = ch; - } - - buffer[nparams] = 0; - - setsvalue(L, res, luaS_newlstr(L, buffer, nparams)); - return 1; - } - - return -1; -} - -static int luauF_len(lua_State* L, StkId res, TValue* arg0, int nresults, StkId args, int nparams) -{ - if (nparams >= 1 && nresults <= 1 && ttisstring(arg0)) - { - TString* ts = tsvalue(arg0); - - setnvalue(res, int(ts->len)); - return 1; - } - - return -1; -} - -static int luauF_typeof(lua_State* L, StkId res, TValue* arg0, int nresults, StkId args, int nparams) -{ - if (nparams >= 1 && nresults <= 1) - { - const TString* ttname = luaT_objtypenamestr(L, arg0); - - setsvalue(L, res, ttname); - return 1; - } - - return -1; -} - -static int luauF_sub(lua_State* L, StkId res, TValue* arg0, int nresults, StkId args, int nparams) -{ - if (nparams >= 3 && nresults <= 1 && ttisstring(arg0) && ttisnumber(args) && ttisnumber(args + 1)) - { - TString* ts = tsvalue(arg0); - int i = int(nvalue(args)); - int j = int(nvalue(args + 1)); - - if (luaC_needsGC(L)) - return -1; // we can't call luaC_checkGC so fall back to C implementation - - if (i >= 1 && j >= i && unsigned(j - 1) < unsigned(ts->len)) - { - setsvalue(L, res, luaS_newlstr(L, getstr(ts) + (i - 1), j - i + 1)); - return 1; - } - } - - return -1; -} - -static int luauF_clamp(lua_State* L, StkId res, TValue* arg0, int nresults, StkId args, int nparams) -{ - if (nparams >= 3 && nresults <= 1 && ttisnumber(arg0) && ttisnumber(args) && ttisnumber(args + 1)) - { - double v = nvalue(arg0); - double min = nvalue(args); - double max = nvalue(args + 1); - - if (min <= max) - { - double r = v < min ? min : v; - r = r > max ? max : r; - - setnvalue(res, r); - return 1; - } - } - - return -1; -} - -static int luauF_sign(lua_State* L, StkId res, TValue* arg0, int nresults, StkId args, int nparams) -{ - if (nparams >= 1 && nresults <= 1 && ttisnumber(arg0)) - { - double v = nvalue(arg0); - setnvalue(res, v > 0.0 ? 1.0 : v < 0.0 ? -1.0 : 0.0); - return 1; - } - - return -1; -} - -LUAU_FASTMATH_BEGIN -static int luauF_round(lua_State* L, StkId res, TValue* arg0, int nresults, StkId args, int nparams) -{ - if (nparams >= 1 && nresults <= 1 && ttisnumber(arg0)) - { - double v = nvalue(arg0); - setnvalue(res, round(v)); - return 1; - } - - return -1; -} -LUAU_FASTMATH_END - -static int luauF_rawequal(lua_State* L, StkId res, TValue* arg0, int nresults, StkId args, int nparams) -{ - if (nparams >= 2 && nresults <= 1) - { - setbvalue(res, luaO_rawequalObj(arg0, args)); - return 1; - } - - return -1; -} - -static int luauF_rawget(lua_State* L, StkId res, TValue* arg0, int nresults, StkId args, int nparams) -{ - if (nparams >= 2 && nresults <= 1 && ttistable(arg0)) - { - setobj2s(L, res, luaH_get(hvalue(arg0), args)); - return 1; - } - - return -1; -} - -static int luauF_rawset(lua_State* L, StkId res, TValue* arg0, int nresults, StkId args, int nparams) -{ - if (nparams >= 3 && nresults <= 1 && ttistable(arg0)) - { - const TValue* key = args; - if (ttisnil(key)) - return -1; - else if (ttisnumber(key) && luai_numisnan(nvalue(key))) - return -1; - else if (ttisvector(key) && luai_vecisnan(vvalue(key))) - return -1; - - Table* t = hvalue(arg0); - if (t->readonly) - return -1; - - setobj2s(L, res, arg0); - setobj2t(L, luaH_set(L, t, args), args + 1); - luaC_barriert(L, t, args + 1); - return 1; - } - - return -1; -} - -static int luauF_tinsert(lua_State* L, StkId res, TValue* arg0, int nresults, StkId args, int nparams) -{ - if (nparams == 2 && nresults <= 0 && ttistable(arg0)) - { - Table* t = hvalue(arg0); - if (t->readonly) - return -1; - - int pos = luaH_getn(t) + 1; - setobj2t(L, luaH_setnum(L, t, pos), args); - luaC_barriert(L, t, args); - return 0; - } - - return -1; -} - -static int luauF_tunpack(lua_State* L, StkId res, TValue* arg0, int nresults, StkId args, int nparams) -{ - if (nparams >= 1 && nresults < 0 && ttistable(arg0)) - { - Table* t = hvalue(arg0); - int n = -1; - - if (nparams == 1) - n = luaH_getn(t); - else if (nparams == 3 && ttisnumber(args) && ttisnumber(args + 1) && nvalue(args) == 1.0) - n = int(nvalue(args + 1)); - - if (n >= 0 && n <= t->sizearray && cast_int(L->stack_last - res) >= n && n + nparams <= LUAI_MAXCSTACK) - { - TValue* array = t->array; - for (int i = 0; i < n; ++i) - setobj2s(L, res + i, array + i); - expandstacklimit(L, res + n); - return n; - } - } - - return -1; -} - -static int luauF_vector(lua_State* L, StkId res, TValue* arg0, int nresults, StkId args, int nparams) -{ - if (nparams >= 3 && nresults <= 1 && ttisnumber(arg0) && ttisnumber(args) && ttisnumber(args + 1)) - { - double x = nvalue(arg0); - double y = nvalue(args); - double z = nvalue(args + 1); - -#if LUA_VECTOR_SIZE == 4 - double w = 0.0; - if (nparams >= 4) - { - if (!ttisnumber(args + 2)) - return -1; - w = nvalue(args + 2); - } - setvvalue(res, float(x), float(y), float(z), float(w)); -#else - setvvalue(res, float(x), float(y), float(z), 0.0f); -#endif - - return 1; - } - - return -1; -} - -static int luauF_countlz(lua_State* L, StkId res, TValue* arg0, int nresults, StkId args, int nparams) -{ - if (nparams >= 1 && nresults <= 1 && ttisnumber(arg0)) - { - double a1 = nvalue(arg0); - - unsigned n; - luai_num2unsigned(n, a1); - -#ifdef _MSC_VER - unsigned long rl; - int r = _BitScanReverse(&rl, n) ? 31 - int(rl) : 32; -#else - int r = n == 0 ? 32 : __builtin_clz(n); -#endif - - setnvalue(res, double(r)); - return 1; - } - - return -1; -} - -static int luauF_countrz(lua_State* L, StkId res, TValue* arg0, int nresults, StkId args, int nparams) -{ - if (nparams >= 1 && nresults <= 1 && ttisnumber(arg0)) - { - double a1 = nvalue(arg0); - - unsigned n; - luai_num2unsigned(n, a1); - -#ifdef _MSC_VER - unsigned long rl; - int r = _BitScanForward(&rl, n) ? int(rl) : 32; -#else - int r = n == 0 ? 32 : __builtin_ctz(n); -#endif - - setnvalue(res, double(r)); - return 1; - } - - return -1; -} - -static int luauF_select(lua_State* L, StkId res, TValue* arg0, int nresults, StkId args, int nparams) -{ - if (nparams == 1 && nresults == 1) - { - int n = cast_int(L->base - L->ci->func) - clvalue(L->ci->func)->l.p->numparams - 1; - - if (ttisnumber(arg0)) - { - int i = int(nvalue(arg0)); - - // i >= 1 && i <= n - if (unsigned(i - 1) < unsigned(n)) - { - setobj2s(L, res, L->base - n + (i - 1)); - return 1; - } - // note: for now we don't handle negative case (wrap around) and defer to fallback - } - else if (ttisstring(arg0) && *svalue(arg0) == '#') - { - setnvalue(res, double(n)); - return 1; - } - } - - return -1; -} - -static int luauF_rawlen(lua_State* L, StkId res, TValue* arg0, int nresults, StkId args, int nparams) -{ - if (nparams >= 1 && nresults <= 1) - { - if (ttistable(arg0)) - { - Table* h = hvalue(arg0); - setnvalue(res, double(luaH_getn(h))); - return 1; - } - else if (ttisstring(arg0)) - { - TString* ts = tsvalue(arg0); - setnvalue(res, double(ts->len)); - return 1; - } - } - - return -1; -} - -static int luauF_extractk(lua_State* L, StkId res, TValue* arg0, int nresults, StkId args, int nparams) -{ - // args is known to contain a number constant with packed in-range f/w - if (nparams >= 2 && nresults <= 1 && ttisnumber(arg0)) - { - double a1 = nvalue(arg0); - double a2 = nvalue(args); - - unsigned n; - luai_num2unsigned(n, a1); - int fw = int(a2); - - int f = fw & 31; - int w1 = fw >> 5; - - uint32_t m = ~(0xfffffffeu << w1); - uint32_t r = (n >> f) & m; - - setnvalue(res, double(r)); - return 1; - } - - return -1; -} - -static int luauF_getmetatable(lua_State* L, StkId res, TValue* arg0, int nresults, StkId args, int nparams) -{ - if (nparams >= 1 && nresults <= 1) - { - Table* mt = NULL; - if (ttistable(arg0)) - mt = hvalue(arg0)->metatable; - else if (ttisuserdata(arg0)) - mt = uvalue(arg0)->metatable; - else - mt = L->global->mt[ttype(arg0)]; - - const TValue* mtv = mt ? luaH_getstr(mt, L->global->tmname[TM_METATABLE]) : luaO_nilobject; - if (!ttisnil(mtv)) - { - setobj2s(L, res, mtv); - return 1; - } - - if (mt) - { - sethvalue(L, res, mt); - return 1; - } - else - { - setnilvalue(res); - return 1; - } - } - - return -1; -} - -static int luauF_setmetatable(lua_State* L, StkId res, TValue* arg0, int nresults, StkId args, int nparams) -{ - // note: setmetatable(_, nil) is rare so we use fallback for it to optimize the fast path - if (nparams >= 2 && nresults <= 1 && ttistable(arg0) && ttistable(args)) - { - Table* t = hvalue(arg0); - if (t->readonly || t->metatable != NULL) - return -1; // note: overwriting non-null metatable is very rare but it requires __metatable check - - Table* mt = hvalue(args); - t->metatable = mt; - luaC_objbarrier(L, t, mt); - - sethvalue(L, res, t); - return 1; - } - - return -1; -} - -static int luauF_tonumber(lua_State* L, StkId res, TValue* arg0, int nresults, StkId args, int nparams) -{ - if (nparams == 1 && nresults <= 1) - { - double num; - - if (ttisnumber(arg0)) - { - setnvalue(res, nvalue(arg0)); - return 1; - } - else if (ttisstring(arg0) && luaO_str2d(svalue(arg0), &num)) - { - setnvalue(res, num); - return 1; - } - else - { - setnilvalue(res); - return 1; - } - } - - return -1; -} - -static int luauF_tostring(lua_State* L, StkId res, TValue* arg0, int nresults, StkId args, int nparams) -{ - if (nparams >= 1 && nresults <= 1) - { - switch (ttype(arg0)) - { - case LUA_TNIL: - { - TString* s = L->global->ttname[LUA_TNIL]; - setsvalue(L, res, s); - return 1; - } - case LUA_TBOOLEAN: - { - TString* s = bvalue(arg0) ? luaS_newliteral(L, "true") : luaS_newliteral(L, "false"); - setsvalue(L, res, s); - return 1; - } - case LUA_TNUMBER: - { - if (luaC_needsGC(L)) - return -1; // we can't call luaC_checkGC so fall back to C implementation - - char s[LUAI_MAXNUM2STR]; - char* e = luai_num2str(s, nvalue(arg0)); - setsvalue(L, res, luaS_newlstr(L, s, e - s)); - return 1; - } - case LUA_TSTRING: - { - setsvalue(L, res, tsvalue(arg0)); - return 1; - } - } - - // fall back to generic C implementation - } - - return -1; -} - -static int luauF_byteswap(lua_State* L, StkId res, TValue* arg0, int nresults, StkId args, int nparams) -{ - if (nparams >= 1 && nresults <= 1 && ttisnumber(arg0)) - { - double a1 = nvalue(arg0); - unsigned n; - luai_num2unsigned(n, a1); - - n = (n << 24) | ((n << 8) & 0xff0000) | ((n >> 8) & 0xff00) | (n >> 24); - - setnvalue(res, double(n)); - return 1; - } - - return -1; -} - -// because offset is limited to an integer, a single 64bit comparison can be used and will not overflow -#define checkoutofbounds(offset, len, accessize) (uint64_t(unsigned(offset)) + (accessize - 1) >= uint64_t(len)) - -template -static int luauF_readinteger(lua_State* L, StkId res, TValue* arg0, int nresults, StkId args, int nparams) -{ -#if !defined(LUAU_BIG_ENDIAN) - if (nparams >= 2 && nresults <= 1 && ttisbuffer(arg0) && ttisnumber(args)) - { - int offset; - luai_num2int(offset, nvalue(args)); - if (checkoutofbounds(offset, bufvalue(arg0)->len, sizeof(T))) - return -1; - - T val; - memcpy(&val, (char*)bufvalue(arg0)->data + unsigned(offset), sizeof(T)); - setnvalue(res, double(val)); - return 1; - } -#endif - - return -1; -} - -template -static int luauF_writeinteger(lua_State* L, StkId res, TValue* arg0, int nresults, StkId args, int nparams) -{ -#if !defined(LUAU_BIG_ENDIAN) - if (nparams >= 3 && nresults <= 0 && ttisbuffer(arg0) && ttisnumber(args) && ttisnumber(args + 1)) - { - int offset; - luai_num2int(offset, nvalue(args)); - if (checkoutofbounds(offset, bufvalue(arg0)->len, sizeof(T))) - return -1; - - unsigned value; - double incoming = nvalue(args + 1); - luai_num2unsigned(value, incoming); - - T val = T(value); - memcpy((char*)bufvalue(arg0)->data + unsigned(offset), &val, sizeof(T)); - return 0; - } -#endif - - return -1; -} - -template -static int luauF_readfp(lua_State* L, StkId res, TValue* arg0, int nresults, StkId args, int nparams) -{ -#if !defined(LUAU_BIG_ENDIAN) - if (nparams >= 2 && nresults <= 1 && ttisbuffer(arg0) && ttisnumber(args)) - { - int offset; - luai_num2int(offset, nvalue(args)); - if (checkoutofbounds(offset, bufvalue(arg0)->len, sizeof(T))) - return -1; - - T val; -#ifdef _MSC_VER - // avoid memcpy path on MSVC because it results in integer stack copy + floating-point ops on stack - val = *(T*)((char*)bufvalue(arg0)->data + unsigned(offset)); -#else - memcpy(&val, (char*)bufvalue(arg0)->data + unsigned(offset), sizeof(T)); -#endif - setnvalue(res, double(val)); - return 1; - } -#endif - - return -1; -} - -template -static int luauF_writefp(lua_State* L, StkId res, TValue* arg0, int nresults, StkId args, int nparams) -{ -#if !defined(LUAU_BIG_ENDIAN) - if (nparams >= 3 && nresults <= 0 && ttisbuffer(arg0) && ttisnumber(args) && ttisnumber(args + 1)) - { - int offset; - luai_num2int(offset, nvalue(args)); - if (checkoutofbounds(offset, bufvalue(arg0)->len, sizeof(T))) - return -1; - - T val = T(nvalue(args + 1)); -#ifdef _MSC_VER - // avoid memcpy path on MSVC because it results in integer stack copy + floating-point ops on stack - *(T*)((char*)bufvalue(arg0)->data + unsigned(offset)) = val; -#else - memcpy((char*)bufvalue(arg0)->data + unsigned(offset), &val, sizeof(T)); -#endif - return 0; - } -#endif - - return -1; -} - -static int luauF_missing(lua_State* L, StkId res, TValue* arg0, int nresults, StkId args, int nparams) -{ - return -1; -} - -#ifdef LUAU_TARGET_SSE41 -template -LUAU_TARGET_SSE41 inline double roundsd_sse41(double v) -{ - __m128d av = _mm_set_sd(v); - __m128d rv = _mm_round_sd(av, av, Rounding | _MM_FROUND_NO_EXC); - return _mm_cvtsd_f64(rv); -} - -LUAU_TARGET_SSE41 static int luauF_floor_sse41(lua_State* L, StkId res, TValue* arg0, int nresults, StkId args, int nparams) -{ - if (nparams >= 1 && nresults <= 1 && ttisnumber(arg0)) - { - double a1 = nvalue(arg0); - setnvalue(res, roundsd_sse41<_MM_FROUND_TO_NEG_INF>(a1)); - return 1; - } - - return -1; -} - -LUAU_TARGET_SSE41 static int luauF_ceil_sse41(lua_State* L, StkId res, TValue* arg0, int nresults, StkId args, int nparams) -{ - if (nparams >= 1 && nresults <= 1 && ttisnumber(arg0)) - { - double a1 = nvalue(arg0); - setnvalue(res, roundsd_sse41<_MM_FROUND_TO_POS_INF>(a1)); - return 1; - } - - return -1; -} - -LUAU_TARGET_SSE41 static int luauF_round_sse41(lua_State* L, StkId res, TValue* arg0, int nresults, StkId args, int nparams) -{ - if (nparams >= 1 && nresults <= 1 && ttisnumber(arg0)) - { - double a1 = nvalue(arg0); - // roundsd only supports bankers rounding natively, so we need to emulate rounding by using truncation - // offset is prevfloat(0.5), which is important so that we round prevfloat(0.5) to 0. - const double offset = 0.49999999999999994; - setnvalue(res, roundsd_sse41<_MM_FROUND_TO_ZERO>(a1 + (a1 < 0 ? -offset : offset))); - return 1; - } - - return -1; -} - -static bool luau_hassse41() -{ - int cpuinfo[4] = {}; -#ifdef _MSC_VER - __cpuid(cpuinfo, 1); -#else - __cpuid(1, cpuinfo[0], cpuinfo[1], cpuinfo[2], cpuinfo[3]); -#endif - - // We requre SSE4.1 support for ROUNDSD - // https://en.wikipedia.org/wiki/CPUID#EAX=1:_Processor_Info_and_Feature_Bits - return (cpuinfo[2] & (1 << 19)) != 0; -} -#endif - -const luau_FastFunction luauF_table[256] = { - NULL, - luauF_assert, - - luauF_abs, - luauF_acos, - luauF_asin, - luauF_atan2, - luauF_atan, - -#ifdef LUAU_TARGET_SSE41 - luau_hassse41() ? luauF_ceil_sse41 : luauF_ceil, -#else - luauF_ceil, -#endif - - luauF_cosh, - luauF_cos, - luauF_deg, - luauF_exp, - -#ifdef LUAU_TARGET_SSE41 - luau_hassse41() ? luauF_floor_sse41 : luauF_floor, -#else - luauF_floor, -#endif - - luauF_fmod, - luauF_frexp, - luauF_ldexp, - luauF_log10, - luauF_log, - luauF_max, - luauF_min, - luauF_modf, - luauF_pow, - luauF_rad, - luauF_sinh, - luauF_sin, - luauF_sqrt, - luauF_tanh, - luauF_tan, - - luauF_arshift, - luauF_band, - luauF_bnot, - luauF_bor, - luauF_bxor, - luauF_btest, - luauF_extract, - luauF_lrotate, - luauF_lshift, - luauF_replace, - luauF_rrotate, - luauF_rshift, - - luauF_type, - - luauF_byte, - luauF_char, - luauF_len, - - luauF_typeof, - - luauF_sub, - - luauF_clamp, - luauF_sign, - -#ifdef LUAU_TARGET_SSE41 - luau_hassse41() ? luauF_round_sse41 : luauF_round, -#else - luauF_round, -#endif - - luauF_rawset, - luauF_rawget, - luauF_rawequal, - - luauF_tinsert, - luauF_tunpack, - - luauF_vector, - - luauF_countlz, - luauF_countrz, - - luauF_select, - - luauF_rawlen, - - luauF_extractk, - - luauF_getmetatable, - luauF_setmetatable, - - luauF_tonumber, - luauF_tostring, - - luauF_byteswap, - - luauF_readinteger, - luauF_readinteger, - luauF_writeinteger, - luauF_readinteger, - luauF_readinteger, - luauF_writeinteger, - luauF_readinteger, - luauF_readinteger, - luauF_writeinteger, - luauF_readfp, - luauF_writefp, - luauF_readfp, - luauF_writefp, - -// When adding builtins, add them above this line; what follows is 64 "dummy" entries with luauF_missing fallback. -// This is important so that older versions of the runtime that don't support newer builtins automatically fall back via luauF_missing. -// Given the builtin addition velocity this should always provide a larger compatibility window than bytecode versions suggest. -#define MISSING8 luauF_missing, luauF_missing, luauF_missing, luauF_missing, luauF_missing, luauF_missing, luauF_missing, luauF_missing - - MISSING8, - MISSING8, - MISSING8, - MISSING8, - MISSING8, - MISSING8, - MISSING8, - MISSING8, - -#undef MISSING8 -}; diff --git a/lib/luau/VM/src/lbuiltins.h b/lib/luau/VM/src/lbuiltins.h deleted file mode 100644 index 44702c9..0000000 --- a/lib/luau/VM/src/lbuiltins.h +++ /dev/null @@ -1,9 +0,0 @@ -// This file is part of the Luau programming language and is licensed under MIT License; see LICENSE.txt for details -// This code is based on Lua 5.x implementation licensed under MIT License; see lua_LICENSE.txt for details -#pragma once - -#include "lobject.h" - -typedef int (*luau_FastFunction)(lua_State* L, StkId res, TValue* arg0, int nresults, StkId args, int nparams); - -extern const luau_FastFunction luauF_table[256]; diff --git a/lib/luau/VM/src/lbytecode.h b/lib/luau/VM/src/lbytecode.h deleted file mode 100644 index da2a611..0000000 --- a/lib/luau/VM/src/lbytecode.h +++ /dev/null @@ -1,6 +0,0 @@ -// This file is part of the Luau programming language and is licensed under MIT License; see LICENSE.txt for details -// This code is based on Lua 5.x implementation licensed under MIT License; see lua_LICENSE.txt for details -#pragma once - -// This is a forwarding header for Luau bytecode definition -#include "Luau/Bytecode.h" diff --git a/lib/luau/VM/src/lcommon.h b/lib/luau/VM/src/lcommon.h deleted file mode 100644 index c9d95c7..0000000 --- a/lib/luau/VM/src/lcommon.h +++ /dev/null @@ -1,48 +0,0 @@ -// This file is part of the Luau programming language and is licensed under MIT License; see LICENSE.txt for details -// This code is based on Lua 5.x implementation licensed under MIT License; see lua_LICENSE.txt for details -#pragma once - -#include -#include - -#include "luaconf.h" - -#include "Luau/Common.h" - -typedef LUAI_USER_ALIGNMENT_T L_Umaxalign; - -// internal assertions for in-house debugging -#define check_exp(c, e) (LUAU_ASSERT(c), (e)) -#define api_check(l, e) LUAU_ASSERT(e) - -#ifndef cast_to -#define cast_to(t, exp) ((t)(exp)) -#endif - -#define cast_byte(i) cast_to(uint8_t, (i)) -#define cast_num(i) cast_to(double, (i)) -#define cast_int(i) cast_to(int, (i)) - -/* -** type for virtual-machine instructions -** must be an unsigned with (at least) 4 bytes (see details in lopcodes.h) -*/ -typedef uint32_t Instruction; - -/* -** macro to control inclusion of some hard tests on stack reallocation -*/ -#if defined(HARDSTACKTESTS) && HARDSTACKTESTS -#define condhardstacktests(x) (x) -#else -#define condhardstacktests(x) ((void)0) -#endif - -/* -** macro to control inclusion of some hard tests on garbage collection -*/ -#if defined(HARDMEMTESTS) && HARDMEMTESTS -#define condhardmemtests(x, l) (HARDMEMTESTS >= l ? (x) : (void)0) -#else -#define condhardmemtests(x, l) ((void)0) -#endif diff --git a/lib/luau/VM/src/lcorolib.cpp b/lib/luau/VM/src/lcorolib.cpp deleted file mode 100644 index 3d39a2d..0000000 --- a/lib/luau/VM/src/lcorolib.cpp +++ /dev/null @@ -1,256 +0,0 @@ -// This file is part of the Luau programming language and is licensed under MIT License; see LICENSE.txt for details -// This code is based on Lua 5.x implementation licensed under MIT License; see lua_LICENSE.txt for details -#include "lualib.h" - -#include "lstate.h" -#include "lvm.h" - -#define CO_STATUS_ERROR -1 -#define CO_STATUS_BREAK -2 - -static const char* const statnames[] = {"running", "suspended", "normal", "dead", "dead"}; // dead appears twice for LUA_COERR and LUA_COFIN - -static int costatus(lua_State* L) -{ - lua_State* co = lua_tothread(L, 1); - luaL_argexpected(L, co, 1, "thread"); - lua_pushstring(L, statnames[lua_costatus(L, co)]); - return 1; -} - -static int auxresume(lua_State* L, lua_State* co, int narg) -{ - // error handling for edge cases - if (co->status != LUA_YIELD) - { - int status = lua_costatus(L, co); - if (status != LUA_COSUS) - { - lua_pushfstring(L, "cannot resume %s coroutine", statnames[status]); - return CO_STATUS_ERROR; - } - } - - if (narg) - { - if (!lua_checkstack(co, narg)) - luaL_error(L, "too many arguments to resume"); - lua_xmove(L, co, narg); - } - - co->singlestep = L->singlestep; - - int status = lua_resume(co, L, narg); - if (status == 0 || status == LUA_YIELD) - { - int nres = cast_int(co->top - co->base); - if (nres) - { - // +1 accounts for true/false status in resumefinish - if (nres + 1 > LUA_MINSTACK && !lua_checkstack(L, nres + 1)) - luaL_error(L, "too many results to resume"); - lua_xmove(co, L, nres); // move yielded values - } - return nres; - } - else if (status == LUA_BREAK) - { - return CO_STATUS_BREAK; - } - else - { - lua_xmove(co, L, 1); // move error message - return CO_STATUS_ERROR; - } -} - -static int interruptThread(lua_State* L, lua_State* co) -{ - // notify the debugger that the thread was suspended - if (L->global->cb.debuginterrupt) - luau_callhook(L, L->global->cb.debuginterrupt, co); - - return lua_break(L); -} - -static int auxresumecont(lua_State* L, lua_State* co) -{ - if (co->status == 0 || co->status == LUA_YIELD) - { - int nres = cast_int(co->top - co->base); - if (!lua_checkstack(L, nres + 1)) - luaL_error(L, "too many results to resume"); - lua_xmove(co, L, nres); // move yielded values - return nres; - } - else - { - lua_rawcheckstack(L, 2); - lua_xmove(co, L, 1); // move error message - return CO_STATUS_ERROR; - } -} - -static int coresumefinish(lua_State* L, int r) -{ - if (r < 0) - { - lua_pushboolean(L, 0); - lua_insert(L, -2); - return 2; // return false + error message - } - else - { - lua_pushboolean(L, 1); - lua_insert(L, -(r + 1)); - return r + 1; // return true + `resume' returns - } -} - -static int coresumey(lua_State* L) -{ - lua_State* co = lua_tothread(L, 1); - luaL_argexpected(L, co, 1, "thread"); - int narg = cast_int(L->top - L->base) - 1; - int r = auxresume(L, co, narg); - - if (r == CO_STATUS_BREAK) - return interruptThread(L, co); - - return coresumefinish(L, r); -} - -static int coresumecont(lua_State* L, int status) -{ - lua_State* co = lua_tothread(L, 1); - luaL_argexpected(L, co, 1, "thread"); - - // if coroutine still hasn't yielded after the break, break current thread again - if (co->status == LUA_BREAK) - return interruptThread(L, co); - - int r = auxresumecont(L, co); - - return coresumefinish(L, r); -} - -static int auxwrapfinish(lua_State* L, int r) -{ - if (r < 0) - { - if (lua_isstring(L, -1)) - { // error object is a string? - luaL_where(L, 1); // add extra info - lua_insert(L, -2); - lua_concat(L, 2); - } - lua_error(L); // propagate error - } - return r; -} - -static int auxwrapy(lua_State* L) -{ - lua_State* co = lua_tothread(L, lua_upvalueindex(1)); - int narg = cast_int(L->top - L->base); - int r = auxresume(L, co, narg); - - if (r == CO_STATUS_BREAK) - return interruptThread(L, co); - - return auxwrapfinish(L, r); -} - -static int auxwrapcont(lua_State* L, int status) -{ - lua_State* co = lua_tothread(L, lua_upvalueindex(1)); - - // if coroutine still hasn't yielded after the break, break current thread again - if (co->status == LUA_BREAK) - return interruptThread(L, co); - - int r = auxresumecont(L, co); - - return auxwrapfinish(L, r); -} - -static int cocreate(lua_State* L) -{ - luaL_checktype(L, 1, LUA_TFUNCTION); - lua_State* NL = lua_newthread(L); - lua_xpush(L, NL, 1); // push function on top of NL - return 1; -} - -static int cowrap(lua_State* L) -{ - cocreate(L); - - lua_pushcclosurek(L, auxwrapy, NULL, 1, auxwrapcont); - return 1; -} - -static int coyield(lua_State* L) -{ - int nres = cast_int(L->top - L->base); - return lua_yield(L, nres); -} - -static int corunning(lua_State* L) -{ - if (lua_pushthread(L)) - lua_pushnil(L); // main thread is not a coroutine - return 1; -} - -static int coyieldable(lua_State* L) -{ - lua_pushboolean(L, lua_isyieldable(L)); - return 1; -} - -static int coclose(lua_State* L) -{ - lua_State* co = lua_tothread(L, 1); - luaL_argexpected(L, co, 1, "thread"); - - int status = lua_costatus(L, co); - if (status != LUA_COFIN && status != LUA_COERR && status != LUA_COSUS) - luaL_error(L, "cannot close %s coroutine", statnames[status]); - - if (co->status == LUA_OK || co->status == LUA_YIELD) - { - lua_pushboolean(L, true); - lua_resetthread(co); - return 1; - } - else - { - lua_pushboolean(L, false); - if (lua_gettop(co)) - lua_xmove(co, L, 1); // move error message - lua_resetthread(co); - return 2; - } -} - -static const luaL_Reg co_funcs[] = { - {"create", cocreate}, - {"running", corunning}, - {"status", costatus}, - {"wrap", cowrap}, - {"yield", coyield}, - {"isyieldable", coyieldable}, - {"close", coclose}, - {NULL, NULL}, -}; - -int luaopen_coroutine(lua_State* L) -{ - luaL_register(L, LUA_COLIBNAME, co_funcs); - - lua_pushcclosurek(L, coresumey, "resume", 0, coresumecont); - lua_setfield(L, -2, "resume"); - - return 1; -} diff --git a/lib/luau/VM/src/ldblib.cpp b/lib/luau/VM/src/ldblib.cpp deleted file mode 100644 index cf564e9..0000000 --- a/lib/luau/VM/src/ldblib.cpp +++ /dev/null @@ -1,166 +0,0 @@ -// This file is part of the Luau programming language and is licensed under MIT License; see LICENSE.txt for details -// This code is based on Lua 5.x implementation licensed under MIT License; see lua_LICENSE.txt for details -#include "lualib.h" - -#include "lvm.h" - -#include -#include -#include - -static lua_State* getthread(lua_State* L, int* arg) -{ - if (lua_isthread(L, 1)) - { - *arg = 1; - return lua_tothread(L, 1); - } - else - { - *arg = 0; - return L; - } -} - -static int db_info(lua_State* L) -{ - int arg; - lua_State* L1 = getthread(L, &arg); - - // If L1 != L, L1 can be in any state, and therefore there are no guarantees about its stack space - if (L != L1) - lua_rawcheckstack(L1, 1); // for 'f' option - - int level; - if (lua_isnumber(L, arg + 1)) - { - level = (int)lua_tointeger(L, arg + 1); - luaL_argcheck(L, level >= 0, arg + 1, "level can't be negative"); - } - else if (arg == 0 && lua_isfunction(L, 1)) - { - // convert absolute index to relative index - level = -lua_gettop(L); - } - else - luaL_argerror(L, arg + 1, "function or level expected"); - - const char* options = luaL_checkstring(L, arg + 2); - - lua_Debug ar; - if (!lua_getinfo(L1, level, options, &ar)) - return 0; - - int results = 0; - bool occurs[26] = {}; - - for (const char* it = options; *it; ++it) - { - if (unsigned(*it - 'a') < 26) - { - if (occurs[*it - 'a']) - luaL_argerror(L, arg + 2, "duplicate option"); - occurs[*it - 'a'] = true; - } - - switch (*it) - { - case 's': - lua_pushstring(L, ar.short_src); - results++; - break; - - case 'l': - lua_pushinteger(L, ar.currentline); - results++; - break; - - case 'n': - lua_pushstring(L, ar.name ? ar.name : ""); - results++; - break; - - case 'f': - if (L1 == L) - lua_pushvalue(L, -1 - results); // function is right before results - else - lua_xmove(L1, L, 1); // function is at top of L1 - results++; - break; - - case 'a': - lua_pushinteger(L, ar.nparams); - lua_pushboolean(L, ar.isvararg); - results += 2; - break; - - default: - luaL_argerror(L, arg + 2, "invalid option"); - } - } - - return results; -} - -static int db_traceback(lua_State* L) -{ - int arg; - lua_State* L1 = getthread(L, &arg); - const char* msg = luaL_optstring(L, arg + 1, NULL); - int level = luaL_optinteger(L, arg + 2, (L == L1) ? 1 : 0); - luaL_argcheck(L, level >= 0, arg + 2, "level can't be negative"); - - luaL_Strbuf buf; - luaL_buffinit(L, &buf); - - if (msg) - { - luaL_addstring(&buf, msg); - luaL_addstring(&buf, "\n"); - } - - lua_Debug ar; - for (int i = level; lua_getinfo(L1, i, "sln", &ar); ++i) - { - if (strcmp(ar.what, "C") == 0) - continue; - - if (ar.source) - luaL_addstring(&buf, ar.short_src); - - if (ar.currentline > 0) - { - char line[32]; // manual conversion for performance - char* lineend = line + sizeof(line); - char* lineptr = lineend; - for (unsigned int r = ar.currentline; r > 0; r /= 10) - *--lineptr = '0' + (r % 10); - - luaL_addchar(&buf, ':'); - luaL_addlstring(&buf, lineptr, lineend - lineptr); - } - - if (ar.name) - { - luaL_addstring(&buf, " function "); - luaL_addstring(&buf, ar.name); - } - - luaL_addchar(&buf, '\n'); - } - - luaL_pushresult(&buf); - return 1; -} - -static const luaL_Reg dblib[] = { - {"info", db_info}, - {"traceback", db_traceback}, - {NULL, NULL}, -}; - -int luaopen_debug(lua_State* L) -{ - luaL_register(L, LUA_DBLIBNAME, dblib); - return 1; -} diff --git a/lib/luau/VM/src/ldebug.cpp b/lib/luau/VM/src/ldebug.cpp deleted file mode 100644 index 844fc6d..0000000 --- a/lib/luau/VM/src/ldebug.cpp +++ /dev/null @@ -1,582 +0,0 @@ -// This file is part of the Luau programming language and is licensed under MIT License; see LICENSE.txt for details -// This code is based on Lua 5.x implementation licensed under MIT License; see lua_LICENSE.txt for details -#include "ldebug.h" - -#include "lapi.h" -#include "lfunc.h" -#include "lmem.h" -#include "lgc.h" -#include "ldo.h" -#include "lbytecode.h" - -#include -#include - -static const char* getfuncname(Closure* f); - -static int currentpc(lua_State* L, CallInfo* ci) -{ - return pcRel(ci->savedpc, ci_func(ci)->l.p); -} - -static int currentline(lua_State* L, CallInfo* ci) -{ - return luaG_getline(ci_func(ci)->l.p, currentpc(L, ci)); -} - -static Proto* getluaproto(CallInfo* ci) -{ - return (isLua(ci) ? cast_to(Proto*, ci_func(ci)->l.p) : NULL); -} - -int lua_getargument(lua_State* L, int level, int n) -{ - if (unsigned(level) >= unsigned(L->ci - L->base_ci)) - return 0; - - CallInfo* ci = L->ci - level; - // changing tables in native functions externally may invalidate safety contracts wrt table state (metatable/size/readonly) - if (ci->flags & LUA_CALLINFO_NATIVE) - return 0; - - Proto* fp = getluaproto(ci); - int res = 0; - - if (fp && n > 0) - { - if (n <= fp->numparams) - { - luaC_threadbarrier(L); - luaA_pushobject(L, ci->base + (n - 1)); - res = 1; - } - else if (fp->is_vararg && n < ci->base - ci->func) - { - luaC_threadbarrier(L); - luaA_pushobject(L, ci->func + n); - res = 1; - } - } - - return res; -} - -const char* lua_getlocal(lua_State* L, int level, int n) -{ - if (unsigned(level) >= unsigned(L->ci - L->base_ci)) - return NULL; - - CallInfo* ci = L->ci - level; - // changing tables in native functions externally may invalidate safety contracts wrt table state (metatable/size/readonly) - if (ci->flags & LUA_CALLINFO_NATIVE) - return NULL; - - Proto* fp = getluaproto(ci); - const LocVar* var = fp ? luaF_getlocal(fp, n, currentpc(L, ci)) : NULL; - if (var) - { - luaC_threadbarrier(L); - luaA_pushobject(L, ci->base + var->reg); - } - const char* name = var ? getstr(var->varname) : NULL; - return name; -} - -const char* lua_setlocal(lua_State* L, int level, int n) -{ - if (unsigned(level) >= unsigned(L->ci - L->base_ci)) - return NULL; - - CallInfo* ci = L->ci - level; - // changing registers in native functions externally may invalidate safety contracts wrt register type tags - if (ci->flags & LUA_CALLINFO_NATIVE) - return NULL; - - Proto* fp = getluaproto(ci); - const LocVar* var = fp ? luaF_getlocal(fp, n, currentpc(L, ci)) : NULL; - if (var) - setobj2s(L, ci->base + var->reg, L->top - 1); - L->top--; // pop value - const char* name = var ? getstr(var->varname) : NULL; - return name; -} - -static Closure* auxgetinfo(lua_State* L, const char* what, lua_Debug* ar, Closure* f, CallInfo* ci) -{ - Closure* cl = NULL; - for (; *what; what++) - { - switch (*what) - { - case 's': - { - if (f->isC) - { - ar->source = "=[C]"; - ar->what = "C"; - ar->linedefined = -1; - ar->short_src = "[C]"; - } - else - { - TString* source = f->l.p->source; - ar->source = getstr(source); - ar->what = "Lua"; - ar->linedefined = f->l.p->linedefined; - ar->short_src = luaO_chunkid(ar->ssbuf, sizeof(ar->ssbuf), getstr(source), source->len); - } - break; - } - case 'l': - { - if (ci) - { - ar->currentline = isLua(ci) ? currentline(L, ci) : -1; - } - else - { - ar->currentline = f->isC ? -1 : f->l.p->linedefined; - } - - break; - } - case 'u': - { - ar->nupvals = f->nupvalues; - break; - } - case 'a': - { - if (f->isC) - { - ar->isvararg = 1; - ar->nparams = 0; - } - else - { - ar->isvararg = f->l.p->is_vararg; - ar->nparams = f->l.p->numparams; - } - break; - } - case 'n': - { - ar->name = ci ? getfuncname(ci_func(ci)) : getfuncname(f); - break; - } - case 'f': - { - cl = f; - break; - } - default:; - } - } - return cl; -} - -int lua_stackdepth(lua_State* L) -{ - return int(L->ci - L->base_ci); -} - -int lua_getinfo(lua_State* L, int level, const char* what, lua_Debug* ar) -{ - Closure* f = NULL; - CallInfo* ci = NULL; - if (level < 0) - { - const TValue* func = luaA_toobject(L, level); - api_check(L, ttisfunction(func)); - f = clvalue(func); - } - else if (unsigned(level) < unsigned(L->ci - L->base_ci)) - { - ci = L->ci - level; - LUAU_ASSERT(ttisfunction(ci->func)); - f = clvalue(ci->func); - } - if (f) - { - // auxgetinfo fills ar and optionally requests to put closure on stack - if (Closure* fcl = auxgetinfo(L, what, ar, f, ci)) - { - luaC_threadbarrier(L); - setclvalue(L, L->top, fcl); - incr_top(L); - } - } - return f ? 1 : 0; -} - -static const char* getfuncname(Closure* cl) -{ - if (cl->isC) - { - if (cl->c.debugname) - { - return cl->c.debugname; - } - } - else - { - Proto* p = cl->l.p; - - if (p->debugname) - { - return getstr(p->debugname); - } - } - return nullptr; -} - -l_noret luaG_typeerrorL(lua_State* L, const TValue* o, const char* op) -{ - const char* t = luaT_objtypename(L, o); - - luaG_runerror(L, "attempt to %s a %s value", op, t); -} - -l_noret luaG_forerrorL(lua_State* L, const TValue* o, const char* what) -{ - const char* t = luaT_objtypename(L, o); - - luaG_runerror(L, "invalid 'for' %s (number expected, got %s)", what, t); -} - -l_noret luaG_concaterror(lua_State* L, StkId p1, StkId p2) -{ - const char* t1 = luaT_objtypename(L, p1); - const char* t2 = luaT_objtypename(L, p2); - - luaG_runerror(L, "attempt to concatenate %s with %s", t1, t2); -} - -l_noret luaG_aritherror(lua_State* L, const TValue* p1, const TValue* p2, TMS op) -{ - const char* t1 = luaT_objtypename(L, p1); - const char* t2 = luaT_objtypename(L, p2); - const char* opname = luaT_eventname[op] + 2; // skip __ from metamethod name - - if (t1 == t2) - luaG_runerror(L, "attempt to perform arithmetic (%s) on %s", opname, t1); - else - luaG_runerror(L, "attempt to perform arithmetic (%s) on %s and %s", opname, t1, t2); -} - -l_noret luaG_ordererror(lua_State* L, const TValue* p1, const TValue* p2, TMS op) -{ - const char* t1 = luaT_objtypename(L, p1); - const char* t2 = luaT_objtypename(L, p2); - const char* opname = (op == TM_LT) ? "<" : (op == TM_LE) ? "<=" : "=="; - - luaG_runerror(L, "attempt to compare %s %s %s", t1, opname, t2); -} - -l_noret luaG_indexerror(lua_State* L, const TValue* p1, const TValue* p2) -{ - const char* t1 = luaT_objtypename(L, p1); - const char* t2 = luaT_objtypename(L, p2); - const TString* key = ttisstring(p2) ? tsvalue(p2) : 0; - - if (key && key->len <= 64) // limit length to make sure we don't generate very long error messages for very long keys - luaG_runerror(L, "attempt to index %s with '%s'", t1, getstr(key)); - else - luaG_runerror(L, "attempt to index %s with %s", t1, t2); -} - -l_noret luaG_methoderror(lua_State* L, const TValue* p1, const TString* p2) -{ - const char* t1 = luaT_objtypename(L, p1); - - luaG_runerror(L, "attempt to call missing method '%s' of %s", getstr(p2), t1); -} - -l_noret luaG_readonlyerror(lua_State* L) -{ - luaG_runerror(L, "attempt to modify a readonly table"); -} - -static void pusherror(lua_State* L, const char* msg) -{ - CallInfo* ci = L->ci; - if (isLua(ci)) - { - TString* source = getluaproto(ci)->source; - char chunkbuf[LUA_IDSIZE]; // add file:line information - const char* chunkid = luaO_chunkid(chunkbuf, sizeof(chunkbuf), getstr(source), source->len); - int line = currentline(L, ci); - luaO_pushfstring(L, "%s:%d: %s", chunkid, line, msg); - } - else - { - lua_pushstring(L, msg); - } -} - -l_noret luaG_runerrorL(lua_State* L, const char* fmt, ...) -{ - va_list argp; - va_start(argp, fmt); - char result[LUA_BUFFERSIZE]; - vsnprintf(result, sizeof(result), fmt, argp); - va_end(argp); - - pusherror(L, result); - luaD_throw(L, LUA_ERRRUN); -} - -void luaG_pusherror(lua_State* L, const char* error) -{ - pusherror(L, error); -} - -void luaG_breakpoint(lua_State* L, Proto* p, int line, bool enable) -{ - // since native code doesn't support breakpoints, we would need to update all call frames with LUAU_CALLINFO_NATIVE that refer to p - if (p->lineinfo && !p->execdata) - { - for (int i = 0; i < p->sizecode; ++i) - { - // note: we keep prologue as is, instead opting to break at the first meaningful instruction - if (LUAU_INSN_OP(p->code[i]) == LOP_PREPVARARGS) - continue; - - if (luaG_getline(p, i) != line) - continue; - - // lazy copy of the original opcode array; done when the first breakpoint is set - if (!p->debuginsn) - { - p->debuginsn = luaM_newarray(L, p->sizecode, uint8_t, p->memcat); - for (int j = 0; j < p->sizecode; ++j) - p->debuginsn[j] = LUAU_INSN_OP(p->code[j]); - } - - uint8_t op = enable ? LOP_BREAK : LUAU_INSN_OP(p->debuginsn[i]); - - // patch just the opcode byte, leave arguments alone - p->code[i] &= ~0xff; - p->code[i] |= op; - LUAU_ASSERT(LUAU_INSN_OP(p->code[i]) == op); - - // note: this is important! - // we only patch the *first* instruction in each proto that's attributed to a given line - // this can be changed, but if requires making patching a bit more nuanced so that we don't patch AUX words - break; - } - } - - for (int i = 0; i < p->sizep; ++i) - { - luaG_breakpoint(L, p->p[i], line, enable); - } -} - -bool luaG_onbreak(lua_State* L) -{ - if (L->ci == L->base_ci) - return false; - - if (!isLua(L->ci)) - return false; - - return LUAU_INSN_OP(*L->ci->savedpc) == LOP_BREAK; -} - -int luaG_getline(Proto* p, int pc) -{ - LUAU_ASSERT(pc >= 0 && pc < p->sizecode); - - if (!p->lineinfo) - return 0; - - return p->abslineinfo[pc >> p->linegaplog2] + p->lineinfo[pc]; -} - -int luaG_isnative(lua_State* L, int level) -{ - if (unsigned(level) >= unsigned(L->ci - L->base_ci)) - return 0; - - CallInfo* ci = L->ci - level; - return (ci->flags & LUA_CALLINFO_NATIVE) != 0 ? 1 : 0; -} - -void lua_singlestep(lua_State* L, int enabled) -{ - L->singlestep = bool(enabled); -} - -static int getmaxline(Proto* p) -{ - int result = -1; - - for (int i = 0; i < p->sizecode; ++i) - { - int line = luaG_getline(p, i); - result = result < line ? line : result; - } - - for (int i = 0; i < p->sizep; ++i) - { - int psize = getmaxline(p->p[i]); - result = result < psize ? psize : result; - } - - return result; -} - -// Find the line number with instructions. If the provided line doesn't have any instruction, it should return the next valid line number. -static int getnextline(Proto* p, int line) -{ - int closest = -1; - - if (p->lineinfo) - { - for (int i = 0; i < p->sizecode; ++i) - { - // note: we keep prologue as is, instead opting to break at the first meaningful instruction - if (LUAU_INSN_OP(p->code[i]) == LOP_PREPVARARGS) - continue; - - int candidate = luaG_getline(p, i); - - if (candidate == line) - return line; - - if (candidate > line && (closest == -1 || candidate < closest)) - closest = candidate; - } - } - - for (int i = 0; i < p->sizep; ++i) - { - int candidate = getnextline(p->p[i], line); - - if (candidate == line) - return line; - - if (candidate > line && (closest == -1 || candidate < closest)) - closest = candidate; - } - - return closest; -} - -int lua_breakpoint(lua_State* L, int funcindex, int line, int enabled) -{ - const TValue* func = luaA_toobject(L, funcindex); - api_check(L, ttisfunction(func) && !clvalue(func)->isC); - - Proto* p = clvalue(func)->l.p; - - // set the breakpoint to the next closest line with valid instructions - int target = getnextline(p, line); - - if (target != -1) - luaG_breakpoint(L, p, target, bool(enabled)); - - return target; -} - -static void getcoverage(Proto* p, int depth, int* buffer, size_t size, void* context, lua_Coverage callback) -{ - memset(buffer, -1, size * sizeof(int)); - - for (int i = 0; i < p->sizecode; ++i) - { - Instruction insn = p->code[i]; - if (LUAU_INSN_OP(insn) != LOP_COVERAGE) - continue; - - int line = luaG_getline(p, i); - int hits = LUAU_INSN_E(insn); - - LUAU_ASSERT(size_t(line) < size); - buffer[line] = buffer[line] < hits ? hits : buffer[line]; - } - - const char* debugname = p->debugname ? getstr(p->debugname) : NULL; - int linedefined = p->linedefined; - - callback(context, debugname, linedefined, depth, buffer, size); - - for (int i = 0; i < p->sizep; ++i) - getcoverage(p->p[i], depth + 1, buffer, size, context, callback); -} - -void lua_getcoverage(lua_State* L, int funcindex, void* context, lua_Coverage callback) -{ - const TValue* func = luaA_toobject(L, funcindex); - api_check(L, ttisfunction(func) && !clvalue(func)->isC); - - Proto* p = clvalue(func)->l.p; - - size_t size = getmaxline(p) + 1; - if (size == 0) - return; - - int* buffer = luaM_newarray(L, size, int, 0); - - getcoverage(p, 0, buffer, size, context, callback); - - luaM_freearray(L, buffer, size, int, 0); -} - -static size_t append(char* buf, size_t bufsize, size_t offset, const char* data) -{ - size_t size = strlen(data); - size_t copy = offset + size >= bufsize ? bufsize - offset - 1 : size; - memcpy(buf + offset, data, copy); - return offset + copy; -} - -const char* lua_debugtrace(lua_State* L) -{ - static char buf[4096]; - - const int limit1 = 10; - const int limit2 = 10; - - int depth = int(L->ci - L->base_ci); - size_t offset = 0; - - lua_Debug ar; - for (int level = 0; lua_getinfo(L, level, "sln", &ar); ++level) - { - if (ar.source) - offset = append(buf, sizeof(buf), offset, ar.short_src); - - if (ar.currentline > 0) - { - char line[32]; - snprintf(line, sizeof(line), ":%d", ar.currentline); - - offset = append(buf, sizeof(buf), offset, line); - } - - if (ar.name) - { - offset = append(buf, sizeof(buf), offset, " function "); - offset = append(buf, sizeof(buf), offset, ar.name); - } - - offset = append(buf, sizeof(buf), offset, "\n"); - - if (depth > limit1 + limit2 && level == limit1 - 1) - { - char skip[32]; - snprintf(skip, sizeof(skip), "... (+%d frames)\n", int(depth - limit1 - limit2)); - - offset = append(buf, sizeof(buf), offset, skip); - - level = depth - limit2 - 1; - } - } - - LUAU_ASSERT(offset < sizeof(buf)); - buf[offset] = '\0'; - - return buf; -} diff --git a/lib/luau/VM/src/ldebug.h b/lib/luau/VM/src/ldebug.h deleted file mode 100644 index 49b1ca8..0000000 --- a/lib/luau/VM/src/ldebug.h +++ /dev/null @@ -1,33 +0,0 @@ -// This file is part of the Luau programming language and is licensed under MIT License; see LICENSE.txt for details -// This code is based on Lua 5.x implementation licensed under MIT License; see lua_LICENSE.txt for details -#pragma once - -#include "lstate.h" - -#define pcRel(pc, p) ((pc) ? cast_to(int, (pc) - (p)->code) - 1 : 0) - -#define luaG_typeerror(L, o, opname) luaG_typeerrorL(L, o, opname) -#define luaG_forerror(L, o, what) luaG_forerrorL(L, o, what) -#define luaG_runerror(L, fmt, ...) luaG_runerrorL(L, fmt, ##__VA_ARGS__) - -#define LUA_MEMERRMSG "not enough memory" -#define LUA_ERRERRMSG "error in error handling" - -LUAI_FUNC l_noret luaG_typeerrorL(lua_State* L, const TValue* o, const char* opname); -LUAI_FUNC l_noret luaG_forerrorL(lua_State* L, const TValue* o, const char* what); -LUAI_FUNC l_noret luaG_concaterror(lua_State* L, StkId p1, StkId p2); -LUAI_FUNC l_noret luaG_aritherror(lua_State* L, const TValue* p1, const TValue* p2, TMS op); -LUAI_FUNC l_noret luaG_ordererror(lua_State* L, const TValue* p1, const TValue* p2, TMS op); -LUAI_FUNC l_noret luaG_indexerror(lua_State* L, const TValue* p1, const TValue* p2); -LUAI_FUNC l_noret luaG_methoderror(lua_State* L, const TValue* p1, const TString* p2); -LUAI_FUNC l_noret luaG_readonlyerror(lua_State* L); - -LUAI_FUNC LUA_PRINTF_ATTR(2, 3) l_noret luaG_runerrorL(lua_State* L, const char* fmt, ...); -LUAI_FUNC void luaG_pusherror(lua_State* L, const char* error); - -LUAI_FUNC void luaG_breakpoint(lua_State* L, Proto* p, int line, bool enable); -LUAI_FUNC bool luaG_onbreak(lua_State* L); - -LUAI_FUNC int luaG_getline(Proto* p, int pc); - -LUAI_FUNC int luaG_isnative(lua_State* L, int level); diff --git a/lib/luau/VM/src/ldo.cpp b/lib/luau/VM/src/ldo.cpp deleted file mode 100644 index d13e98f..0000000 --- a/lib/luau/VM/src/ldo.cpp +++ /dev/null @@ -1,602 +0,0 @@ -// This file is part of the Luau programming language and is licensed under MIT License; see LICENSE.txt for details -// This code is based on Lua 5.x implementation licensed under MIT License; see lua_LICENSE.txt for details -#include "ldo.h" - -#include "lstring.h" -#include "lfunc.h" -#include "lgc.h" -#include "lmem.h" -#include "lvm.h" - -#if LUA_USE_LONGJMP -#include -#include -#else -#include -#endif - -#include - -/* -** {====================================================== -** Error-recovery functions -** ======================================================= -*/ - -#if LUA_USE_LONGJMP -struct lua_jmpbuf -{ - lua_jmpbuf* volatile prev; - volatile int status; - jmp_buf buf; -}; - -// use POSIX versions of setjmp/longjmp if possible: they don't save/restore signal mask and are therefore faster -#if defined(__linux__) || defined(__APPLE__) -#define LUAU_SETJMP(buf) _setjmp(buf) -#define LUAU_LONGJMP(buf, code) _longjmp(buf, code) -#else -#define LUAU_SETJMP(buf) setjmp(buf) -#define LUAU_LONGJMP(buf, code) longjmp(buf, code) -#endif - -int luaD_rawrunprotected(lua_State* L, Pfunc f, void* ud) -{ - lua_jmpbuf jb; - jb.prev = L->global->errorjmp; - jb.status = 0; - L->global->errorjmp = &jb; - - if (LUAU_SETJMP(jb.buf) == 0) - f(L, ud); - - L->global->errorjmp = jb.prev; - return jb.status; -} - -l_noret luaD_throw(lua_State* L, int errcode) -{ - if (lua_jmpbuf* jb = L->global->errorjmp) - { - jb->status = errcode; - LUAU_LONGJMP(jb->buf, 1); - } - - if (L->global->cb.panic) - L->global->cb.panic(L, errcode); - - abort(); -} -#else -class lua_exception : public std::exception -{ -public: - lua_exception(lua_State* L, int status) - : L(L) - , status(status) - { - } - - const char* what() const throw() override - { - // LUA_ERRRUN passes error object on the stack - if (status == LUA_ERRRUN) - if (const char* str = lua_tostring(L, -1)) - return str; - - switch (status) - { - case LUA_ERRRUN: - return "lua_exception: runtime error"; - case LUA_ERRSYNTAX: - return "lua_exception: syntax error"; - case LUA_ERRMEM: - return "lua_exception: " LUA_MEMERRMSG; - case LUA_ERRERR: - return "lua_exception: " LUA_ERRERRMSG; - default: - return "lua_exception: unexpected exception status"; - } - } - - int getStatus() const - { - return status; - } - -private: - lua_State* L; - int status; -}; - -int luaD_rawrunprotected(lua_State* L, Pfunc f, void* ud) -{ - int status = 0; - - try - { - f(L, ud); - return 0; - } - catch (lua_exception& e) - { - // lua_exception means that luaD_throw was called and an exception object is on stack if status is ERRRUN - status = e.getStatus(); - } - catch (std::exception& e) - { - // Luau will never throw this, but this can catch exceptions that escape from C++ implementations of external functions - try - { - // there's no exception object on stack; let's push the error on stack so that error handling below can proceed - luaG_pusherror(L, e.what()); - status = LUA_ERRRUN; - } - catch (std::exception&) - { - // out of memory while allocating error string - status = LUA_ERRMEM; - } - } - - return status; -} - -l_noret luaD_throw(lua_State* L, int errcode) -{ - throw lua_exception(L, errcode); -} -#endif - -// }====================================================== - -static void correctstack(lua_State* L, TValue* oldstack) -{ - L->top = (L->top - oldstack) + L->stack; - for (UpVal* up = L->openupval; up != NULL; up = up->u.open.threadnext) - up->v = (up->v - oldstack) + L->stack; - for (CallInfo* ci = L->base_ci; ci <= L->ci; ci++) - { - ci->top = (ci->top - oldstack) + L->stack; - ci->base = (ci->base - oldstack) + L->stack; - ci->func = (ci->func - oldstack) + L->stack; - } - L->base = (L->base - oldstack) + L->stack; -} - -void luaD_reallocstack(lua_State* L, int newsize) -{ - TValue* oldstack = L->stack; - int realsize = newsize + EXTRA_STACK; - LUAU_ASSERT(L->stack_last - L->stack == L->stacksize - EXTRA_STACK); - luaM_reallocarray(L, L->stack, L->stacksize, realsize, TValue, L->memcat); - TValue* newstack = L->stack; - for (int i = L->stacksize; i < realsize; i++) - setnilvalue(newstack + i); // erase new segment - L->stacksize = realsize; - L->stack_last = newstack + newsize; - correctstack(L, oldstack); -} - -void luaD_reallocCI(lua_State* L, int newsize) -{ - CallInfo* oldci = L->base_ci; - luaM_reallocarray(L, L->base_ci, L->size_ci, newsize, CallInfo, L->memcat); - L->size_ci = newsize; - L->ci = (L->ci - oldci) + L->base_ci; - L->end_ci = L->base_ci + L->size_ci - 1; -} - -void luaD_growstack(lua_State* L, int n) -{ - if (n <= L->stacksize) // double size is enough? - luaD_reallocstack(L, 2 * L->stacksize); - else - luaD_reallocstack(L, L->stacksize + n); -} - -CallInfo* luaD_growCI(lua_State* L) -{ - // allow extra stack space to handle stack overflow in xpcall - const int hardlimit = LUAI_MAXCALLS + (LUAI_MAXCALLS >> 3); - - if (L->size_ci >= hardlimit) - luaD_throw(L, LUA_ERRERR); // error while handling stack error - - int request = L->size_ci * 2; - luaD_reallocCI(L, L->size_ci >= LUAI_MAXCALLS ? hardlimit : request < LUAI_MAXCALLS ? request : LUAI_MAXCALLS); - - if (L->size_ci > LUAI_MAXCALLS) - luaG_runerror(L, "stack overflow"); - - return ++L->ci; -} - -void luaD_checkCstack(lua_State* L) -{ - // allow extra stack space to handle stack overflow in xpcall - const int hardlimit = LUAI_MAXCCALLS + (LUAI_MAXCCALLS >> 3); - - if (L->nCcalls == LUAI_MAXCCALLS) - luaG_runerror(L, "C stack overflow"); - else if (L->nCcalls >= hardlimit) - luaD_throw(L, LUA_ERRERR); // error while handling stack error -} - -/* -** Call a function (C or Lua). The function to be called is at *func. -** The arguments are on the stack, right after the function. -** When returns, all the results are on the stack, starting at the original -** function position. -*/ -void luaD_call(lua_State* L, StkId func, int nresults) -{ - if (++L->nCcalls >= LUAI_MAXCCALLS) - luaD_checkCstack(L); - - ptrdiff_t old_func = savestack(L, func); - - if (luau_precall(L, func, nresults) == PCRLUA) - { // is a Lua function? - L->ci->flags |= LUA_CALLINFO_RETURN; // luau_execute will stop after returning from the stack frame - - bool oldactive = L->isactive; - L->isactive = true; - luaC_threadbarrier(L); - - luau_execute(L); // call it - - if (!oldactive) - L->isactive = false; - } - - if (nresults != LUA_MULTRET) - L->top = restorestack(L, old_func) + nresults; - - L->nCcalls--; - luaC_checkGC(L); -} - -static void seterrorobj(lua_State* L, int errcode, StkId oldtop) -{ - switch (errcode) - { - case LUA_ERRMEM: - { - setsvalue(L, oldtop, luaS_newliteral(L, LUA_MEMERRMSG)); // can not fail because string is pinned in luaopen - break; - } - case LUA_ERRERR: - { - setsvalue(L, oldtop, luaS_newliteral(L, LUA_ERRERRMSG)); // can not fail because string is pinned in luaopen - break; - } - case LUA_ERRSYNTAX: - case LUA_ERRRUN: - { - setobj2s(L, oldtop, L->top - 1); // error message on current top - break; - } - } - L->top = oldtop + 1; -} - -static void resume_continue(lua_State* L) -{ - // unroll Lua/C combined stack, processing continuations - while (L->status == 0 && L->ci > L->base_ci) - { - LUAU_ASSERT(L->baseCcalls == L->nCcalls); - - Closure* cl = curr_func(L); - - if (cl->isC) - { - LUAU_ASSERT(cl->c.cont); - - // C continuation; we expect this to be followed by Lua continuations - int n = cl->c.cont(L, 0); - - // Continuation can break again - if (L->status == LUA_BREAK) - break; - - luau_poscall(L, L->top - n); - } - else - { - // Lua continuation; it terminates at the end of the stack or at another C continuation - luau_execute(L); - } - } -} - -static void resume(lua_State* L, void* ud) -{ - StkId firstArg = cast_to(StkId, ud); - - if (L->status == 0) - { - // start coroutine - LUAU_ASSERT(L->ci == L->base_ci && firstArg >= L->base); - if (firstArg == L->base) - luaG_runerror(L, "cannot resume dead coroutine"); - - if (luau_precall(L, firstArg - 1, LUA_MULTRET) != PCRLUA) - return; - - L->ci->flags |= LUA_CALLINFO_RETURN; - } - else - { - // resume from previous yield or break - LUAU_ASSERT(L->status == LUA_YIELD || L->status == LUA_BREAK); - L->status = 0; - - Closure* cl = curr_func(L); - - if (cl->isC) - { - // if the top stack frame is a C call continuation, resume_continue will handle that case - if (!cl->c.cont) - { - // finish interrupted execution of `OP_CALL' - luau_poscall(L, firstArg); - } - } - else - { - // yielded inside a hook: just continue its execution - L->base = L->ci->base; - } - } - - // run continuations from the stack; typically resumes Lua code and pcalls - resume_continue(L); -} - -static CallInfo* resume_findhandler(lua_State* L) -{ - CallInfo* ci = L->ci; - - while (ci > L->base_ci) - { - if (ci->flags & LUA_CALLINFO_HANDLE) - return ci; - - ci--; - } - - return NULL; -} - -static void resume_handle(lua_State* L, void* ud) -{ - CallInfo* ci = (CallInfo*)ud; - Closure* cl = ci_func(ci); - - LUAU_ASSERT(ci->flags & LUA_CALLINFO_HANDLE); - LUAU_ASSERT(cl->isC && cl->c.cont); - LUAU_ASSERT(L->status != 0); - - // restore nCcalls back to base since this might not have happened during error handling - L->nCcalls = L->baseCcalls; - - // make sure we don't run the handler the second time - ci->flags &= ~LUA_CALLINFO_HANDLE; - - // restore thread status to 0 since we're handling the error - int status = L->status; - L->status = 0; - - // push error object to stack top if it's not already there - if (status != LUA_ERRRUN) - seterrorobj(L, status, L->top); - - // adjust the stack frame for ci to prepare for cont call - L->base = ci->base; - ci->top = L->top; - - // save ci pointer - it will be invalidated by cont call! - ptrdiff_t old_ci = saveci(L, ci); - - // handle the error in continuation; note that this executes on top of original stack! - int n = cl->c.cont(L, status); - - // restore the stack frame to the frame with continuation - L->ci = restoreci(L, old_ci); - - // close eventual pending closures; this means it's now safe to restore stack - luaF_close(L, L->ci->base); - - // finish cont call and restore stack to previous ci top - luau_poscall(L, L->top - n); - - // run remaining continuations from the stack; typically resumes pcalls - resume_continue(L); -} - -static int resume_error(lua_State* L, const char* msg) -{ - L->top = L->ci->base; - setsvalue(L, L->top, luaS_new(L, msg)); - incr_top(L); - return LUA_ERRRUN; -} - -static void resume_finish(lua_State* L, int status) -{ - L->nCcalls = L->baseCcalls; - L->isactive = false; - - if (status != 0) - { // error? - L->status = cast_byte(status); // mark thread as `dead' - seterrorobj(L, status, L->top); - L->ci->top = L->top; - } - else if (L->status == 0) - { - expandstacklimit(L, L->top); - } -} - -int lua_resume(lua_State* L, lua_State* from, int nargs) -{ - int status; - if (L->status != LUA_YIELD && L->status != LUA_BREAK && (L->status != 0 || L->ci != L->base_ci)) - return resume_error(L, "cannot resume non-suspended coroutine"); - - L->nCcalls = from ? from->nCcalls : 0; - if (L->nCcalls >= LUAI_MAXCCALLS) - return resume_error(L, "C stack overflow"); - - L->baseCcalls = ++L->nCcalls; - L->isactive = true; - - luaC_threadbarrier(L); - - status = luaD_rawrunprotected(L, resume, L->top - nargs); - - CallInfo* ch = NULL; - while (status != 0 && (ch = resume_findhandler(L)) != NULL) - { - L->status = cast_byte(status); - status = luaD_rawrunprotected(L, resume_handle, ch); - } - - resume_finish(L, status); - --L->nCcalls; - return L->status; -} - -int lua_resumeerror(lua_State* L, lua_State* from) -{ - int status; - if (L->status != LUA_YIELD && L->status != LUA_BREAK && (L->status != 0 || L->ci != L->base_ci)) - return resume_error(L, "cannot resume non-suspended coroutine"); - - L->nCcalls = from ? from->nCcalls : 0; - if (L->nCcalls >= LUAI_MAXCCALLS) - return resume_error(L, "C stack overflow"); - - L->baseCcalls = ++L->nCcalls; - L->isactive = true; - - luaC_threadbarrier(L); - - status = LUA_ERRRUN; - - CallInfo* ch = NULL; - while (status != 0 && (ch = resume_findhandler(L)) != NULL) - { - L->status = cast_byte(status); - status = luaD_rawrunprotected(L, resume_handle, ch); - } - - resume_finish(L, status); - --L->nCcalls; - return L->status; -} - -int lua_yield(lua_State* L, int nresults) -{ - if (L->nCcalls > L->baseCcalls) - luaG_runerror(L, "attempt to yield across metamethod/C-call boundary"); - L->base = L->top - nresults; // protect stack slots below - L->status = LUA_YIELD; - return -1; -} - -int lua_break(lua_State* L) -{ - if (L->nCcalls > L->baseCcalls) - luaG_runerror(L, "attempt to break across metamethod/C-call boundary"); - L->status = LUA_BREAK; - return -1; -} - -int lua_isyieldable(lua_State* L) -{ - return (L->nCcalls <= L->baseCcalls); -} - -static void callerrfunc(lua_State* L, void* ud) -{ - StkId errfunc = cast_to(StkId, ud); - - setobj2s(L, L->top, L->top - 1); - setobj2s(L, L->top - 1, errfunc); - incr_top(L); - luaD_call(L, L->top - 2, 1); -} - -static void restore_stack_limit(lua_State* L) -{ - LUAU_ASSERT(L->stack_last - L->stack == L->stacksize - EXTRA_STACK); - if (L->size_ci > LUAI_MAXCALLS) - { // there was an overflow? - int inuse = cast_int(L->ci - L->base_ci); - if (inuse + 1 < LUAI_MAXCALLS) // can `undo' overflow? - luaD_reallocCI(L, LUAI_MAXCALLS); - } -} - -int luaD_pcall(lua_State* L, Pfunc func, void* u, ptrdiff_t old_top, ptrdiff_t ef) -{ - unsigned short oldnCcalls = L->nCcalls; - ptrdiff_t old_ci = saveci(L, L->ci); - bool oldactive = L->isactive; - int status = luaD_rawrunprotected(L, func, u); - if (status != 0) - { - int errstatus = status; - - // call user-defined error function (used in xpcall) - if (ef) - { - // push error object to stack top if it's not already there - if (status != LUA_ERRRUN) - seterrorobj(L, status, L->top); - - // if errfunc fails, we fail with "error in error handling" or "not enough memory" - int err = luaD_rawrunprotected(L, callerrfunc, restorestack(L, ef)); - - // in general we preserve the status, except for cases when the error handler fails - // out of memory is treated specially because it's common for it to be cascading, in which case we preserve the code - if (err == 0) - errstatus = LUA_ERRRUN; - else if (status == LUA_ERRMEM && err == LUA_ERRMEM) - errstatus = LUA_ERRMEM; - else - errstatus = status = LUA_ERRERR; - } - - // since the call failed with an error, we might have to reset the 'active' thread state - if (!oldactive) - L->isactive = false; - - bool yieldable = L->nCcalls <= L->baseCcalls; // Inlined logic from 'lua_isyieldable' to avoid potential for an out of line call. - - // restore nCcalls before calling the debugprotectederror callback which may rely on the proper value to have been restored. - L->nCcalls = oldnCcalls; - - // an error occurred, check if we have a protected error callback - if (yieldable && L->global->cb.debugprotectederror) - { - L->global->cb.debugprotectederror(L); - - // debug hook is only allowed to break - if (L->status == LUA_BREAK) - return 0; - } - - StkId oldtop = restorestack(L, old_top); - luaF_close(L, oldtop); // close eventual pending closures - seterrorobj(L, errstatus, oldtop); - L->ci = restoreci(L, old_ci); - L->base = L->ci->base; - restore_stack_limit(L); - } - return status; -} diff --git a/lib/luau/VM/src/ldo.h b/lib/luau/VM/src/ldo.h deleted file mode 100644 index 0f7b42a..0000000 --- a/lib/luau/VM/src/ldo.h +++ /dev/null @@ -1,55 +0,0 @@ -// This file is part of the Luau programming language and is licensed under MIT License; see LICENSE.txt for details -// This code is based on Lua 5.x implementation licensed under MIT License; see lua_LICENSE.txt for details -#pragma once - -#include "lobject.h" -#include "lstate.h" -#include "luaconf.h" -#include "ldebug.h" - -#define luaD_checkstack(L, n) \ - if ((char*)L->stack_last - (char*)L->top <= (n) * (int)sizeof(TValue)) \ - luaD_growstack(L, n); \ - else \ - condhardstacktests(luaD_reallocstack(L, L->stacksize - EXTRA_STACK)); - -#define incr_top(L) \ - { \ - luaD_checkstack(L, 1); \ - L->top++; \ - } - -#define savestack(L, p) ((char*)(p) - (char*)L->stack) -#define restorestack(L, n) ((TValue*)((char*)L->stack + (n))) - -#define expandstacklimit(L, p) \ - { \ - LUAU_ASSERT((p) <= (L)->stack_last); \ - if ((L)->ci->top < (p)) \ - (L)->ci->top = (p); \ - } - -#define incr_ci(L) ((L->ci == L->end_ci) ? luaD_growCI(L) : (condhardstacktests(luaD_reallocCI(L, L->size_ci)), ++L->ci)) - -#define saveci(L, p) ((char*)(p) - (char*)L->base_ci) -#define restoreci(L, n) ((CallInfo*)((char*)L->base_ci + (n))) - -// results from luaD_precall -#define PCRLUA 0 // initiated a call to a Lua function -#define PCRC 1 // did a call to a C function -#define PCRYIELD 2 // C function yielded - -// type of protected functions, to be ran by `runprotected' -typedef void (*Pfunc)(lua_State* L, void* ud); - -LUAI_FUNC CallInfo* luaD_growCI(lua_State* L); - -LUAI_FUNC void luaD_call(lua_State* L, StkId func, int nresults); -LUAI_FUNC int luaD_pcall(lua_State* L, Pfunc func, void* u, ptrdiff_t oldtop, ptrdiff_t ef); -LUAI_FUNC void luaD_reallocCI(lua_State* L, int newsize); -LUAI_FUNC void luaD_reallocstack(lua_State* L, int newsize); -LUAI_FUNC void luaD_growstack(lua_State* L, int n); -LUAI_FUNC void luaD_checkCstack(lua_State* L); - -LUAI_FUNC l_noret luaD_throw(lua_State* L, int errcode); -LUAI_FUNC int luaD_rawrunprotected(lua_State* L, Pfunc f, void* ud); diff --git a/lib/luau/VM/src/lfunc.cpp b/lib/luau/VM/src/lfunc.cpp deleted file mode 100644 index 276598f..0000000 --- a/lib/luau/VM/src/lfunc.cpp +++ /dev/null @@ -1,197 +0,0 @@ -// This file is part of the Luau programming language and is licensed under MIT License; see LICENSE.txt for details -// This code is based on Lua 5.x implementation licensed under MIT License; see lua_LICENSE.txt for details -#include "lfunc.h" - -#include "lstate.h" -#include "lmem.h" -#include "lgc.h" - -Proto* luaF_newproto(lua_State* L) -{ - Proto* f = luaM_newgco(L, Proto, sizeof(Proto), L->activememcat); - luaC_init(L, f, LUA_TPROTO); - f->k = NULL; - f->sizek = 0; - f->p = NULL; - f->sizep = 0; - f->code = NULL; - f->sizecode = 0; - f->sizeupvalues = 0; - f->nups = 0; - f->upvalues = NULL; - f->numparams = 0; - f->is_vararg = 0; - f->maxstacksize = 0; - f->flags = 0; - f->sizelineinfo = 0; - f->linegaplog2 = 0; - f->lineinfo = NULL; - f->abslineinfo = NULL; - f->sizelocvars = 0; - f->locvars = NULL; - f->source = NULL; - f->debugname = NULL; - f->debuginsn = NULL; - f->codeentry = NULL; - f->execdata = NULL; - f->exectarget = 0; - f->typeinfo = NULL; - f->userdata = NULL; - - return f; -} - -Closure* luaF_newLclosure(lua_State* L, int nelems, Table* e, Proto* p) -{ - Closure* c = luaM_newgco(L, Closure, sizeLclosure(nelems), L->activememcat); - luaC_init(L, c, LUA_TFUNCTION); - c->isC = 0; - c->env = e; - c->nupvalues = cast_byte(nelems); - c->stacksize = p->maxstacksize; - c->preload = 0; - c->l.p = p; - for (int i = 0; i < nelems; ++i) - setnilvalue(&c->l.uprefs[i]); - return c; -} - -Closure* luaF_newCclosure(lua_State* L, int nelems, Table* e) -{ - Closure* c = luaM_newgco(L, Closure, sizeCclosure(nelems), L->activememcat); - luaC_init(L, c, LUA_TFUNCTION); - c->isC = 1; - c->env = e; - c->nupvalues = cast_byte(nelems); - c->stacksize = LUA_MINSTACK; - c->preload = 0; - c->c.f = NULL; - c->c.cont = NULL; - c->c.debugname = NULL; - return c; -} - -UpVal* luaF_findupval(lua_State* L, StkId level) -{ - global_State* g = L->global; - UpVal** pp = &L->openupval; - UpVal* p; - while (*pp != NULL && (p = *pp)->v >= level) - { - LUAU_ASSERT(!isdead(g, obj2gco(p))); - LUAU_ASSERT(upisopen(p)); - if (p->v == level) - return p; - - pp = &p->u.open.threadnext; - } - - LUAU_ASSERT(L->isactive); - LUAU_ASSERT(!isblack(obj2gco(L))); // we don't use luaC_threadbarrier because active threads never turn black - - UpVal* uv = luaM_newgco(L, UpVal, sizeof(UpVal), L->activememcat); // not found: create a new one - luaC_init(L, uv, LUA_TUPVAL); - uv->markedopen = 0; - uv->v = level; // current value lives in the stack - - // chain the upvalue in the threads open upvalue list at the proper position - uv->u.open.threadnext = *pp; - *pp = uv; - - // double link the upvalue in the global open upvalue list - uv->u.open.prev = &g->uvhead; - uv->u.open.next = g->uvhead.u.open.next; - uv->u.open.next->u.open.prev = uv; - g->uvhead.u.open.next = uv; - LUAU_ASSERT(uv->u.open.next->u.open.prev == uv && uv->u.open.prev->u.open.next == uv); - - return uv; -} - -void luaF_freeupval(lua_State* L, UpVal* uv, lua_Page* page) -{ - luaM_freegco(L, uv, sizeof(UpVal), uv->memcat, page); // free upvalue -} - -void luaF_close(lua_State* L, StkId level) -{ - global_State* g = L->global; - UpVal* uv; - while (L->openupval != NULL && (uv = L->openupval)->v >= level) - { - GCObject* o = obj2gco(uv); - LUAU_ASSERT(!isblack(o) && upisopen(uv)); - LUAU_ASSERT(!isdead(g, o)); - - // unlink value *before* closing it since value storage overlaps - L->openupval = uv->u.open.threadnext; - - luaF_closeupval(L, uv, /* dead= */ false); - } -} - -void luaF_closeupval(lua_State* L, UpVal* uv, bool dead) -{ - // unlink value from all lists *before* closing it since value storage overlaps - LUAU_ASSERT(uv->u.open.next->u.open.prev == uv && uv->u.open.prev->u.open.next == uv); - uv->u.open.next->u.open.prev = uv->u.open.prev; - uv->u.open.prev->u.open.next = uv->u.open.next; - - if (dead) - return; - - setobj(L, &uv->u.value, uv->v); - uv->v = &uv->u.value; - luaC_upvalclosed(L, uv); -} - -void luaF_freeproto(lua_State* L, Proto* f, lua_Page* page) -{ - luaM_freearray(L, f->code, f->sizecode, Instruction, f->memcat); - luaM_freearray(L, f->p, f->sizep, Proto*, f->memcat); - luaM_freearray(L, f->k, f->sizek, TValue, f->memcat); - if (f->lineinfo) - luaM_freearray(L, f->lineinfo, f->sizelineinfo, uint8_t, f->memcat); - luaM_freearray(L, f->locvars, f->sizelocvars, struct LocVar, f->memcat); - luaM_freearray(L, f->upvalues, f->sizeupvalues, TString*, f->memcat); - if (f->debuginsn) - luaM_freearray(L, f->debuginsn, f->sizecode, uint8_t, f->memcat); - - if (f->execdata) - L->global->ecb.destroy(L, f); - - if (f->typeinfo) - luaM_freearray(L, f->typeinfo, f->numparams + 2, uint8_t, f->memcat); - - luaM_freegco(L, f, sizeof(Proto), f->memcat, page); -} - -void luaF_freeclosure(lua_State* L, Closure* c, lua_Page* page) -{ - int size = c->isC ? sizeCclosure(c->nupvalues) : sizeLclosure(c->nupvalues); - luaM_freegco(L, c, size, c->memcat, page); -} - -const LocVar* luaF_getlocal(const Proto* f, int local_number, int pc) -{ - for (int i = 0; i < f->sizelocvars; i++) - { - if (pc >= f->locvars[i].startpc && pc < f->locvars[i].endpc) - { // is variable active? - local_number--; - if (local_number == 0) - return &f->locvars[i]; - } - } - - return NULL; // not found -} - -const LocVar* luaF_findlocal(const Proto* f, int local_reg, int pc) -{ - for (int i = 0; i < f->sizelocvars; i++) - if (local_reg == f->locvars[i].reg && pc >= f->locvars[i].startpc && pc < f->locvars[i].endpc) - return &f->locvars[i]; - - return NULL; // not found -} diff --git a/lib/luau/VM/src/lfunc.h b/lib/luau/VM/src/lfunc.h deleted file mode 100644 index 679836e..0000000 --- a/lib/luau/VM/src/lfunc.h +++ /dev/null @@ -1,20 +0,0 @@ -// This file is part of the Luau programming language and is licensed under MIT License; see LICENSE.txt for details -// This code is based on Lua 5.x implementation licensed under MIT License; see lua_LICENSE.txt for details -#pragma once - -#include "lobject.h" - -#define sizeCclosure(n) (offsetof(Closure, c.upvals) + sizeof(TValue) * (n)) -#define sizeLclosure(n) (offsetof(Closure, l.uprefs) + sizeof(TValue) * (n)) - -LUAI_FUNC Proto* luaF_newproto(lua_State* L); -LUAI_FUNC Closure* luaF_newLclosure(lua_State* L, int nelems, Table* e, Proto* p); -LUAI_FUNC Closure* luaF_newCclosure(lua_State* L, int nelems, Table* e); -LUAI_FUNC UpVal* luaF_findupval(lua_State* L, StkId level); -LUAI_FUNC void luaF_close(lua_State* L, StkId level); -LUAI_FUNC void luaF_closeupval(lua_State* L, UpVal* uv, bool dead); -LUAI_FUNC void luaF_freeproto(lua_State* L, Proto* f, struct lua_Page* page); -LUAI_FUNC void luaF_freeclosure(lua_State* L, Closure* c, struct lua_Page* page); -LUAI_FUNC void luaF_freeupval(lua_State* L, UpVal* uv, struct lua_Page* page); -LUAI_FUNC const LocVar* luaF_getlocal(const Proto* func, int local_number, int pc); -LUAI_FUNC const LocVar* luaF_findlocal(const Proto* func, int local_reg, int pc); diff --git a/lib/luau/VM/src/lgc.cpp b/lib/luau/VM/src/lgc.cpp deleted file mode 100644 index 4b31580..0000000 --- a/lib/luau/VM/src/lgc.cpp +++ /dev/null @@ -1,1256 +0,0 @@ -// This file is part of the Luau programming language and is licensed under MIT License; see LICENSE.txt for details -// This code is based on Lua 5.x implementation licensed under MIT License; see lua_LICENSE.txt for details -#include "lgc.h" - -#include "lobject.h" -#include "lstate.h" -#include "ltable.h" -#include "lfunc.h" -#include "lstring.h" -#include "ldo.h" -#include "lmem.h" -#include "ludata.h" -#include "lbuffer.h" - -#include - -/* - * Luau uses an incremental non-generational non-moving mark&sweep garbage collector. - * - * The collector runs in three stages: mark, atomic and sweep. Mark and sweep are incremental and try to do a limited amount - * of work every GC step; atomic is ran once per the GC cycle and is indivisible. In either case, the work happens during GC - * steps that are "scheduled" by the GC pacing algorithm - the steps happen either from explicit calls to lua_gc, or after - * the mutator (aka application) allocates some amount of memory, which is known as "GC assist". In either case, GC steps - * can't happen concurrently with other access to VM state. - * - * Current GC stage is stored in global_State::gcstate, and has two additional stages for pause and second-phase mark, explained below. - * - * GC pacer is an algorithm that tries to ensure that GC can always catch up to the application allocating garbage, but do this - * with minimal amount of effort. To configure the pacer Luau provides control over three variables: GC goal, defined as the - * target heap size during atomic phase in relation to live heap size (e.g. 200% goal means the heap's worst case size is double - * the total size of alive objects), step size (how many kilobytes should the application allocate for GC step to trigger), and - * GC multiplier (how much should the GC try to mark relative to how much the application allocated). It's critical that step - * multiplier is significantly above 1, as this is what allows the GC to catch up to the application's allocation rate, and - * GC goal and GC multiplier are linked in subtle ways, described in lua.h comments for LUA_GCSETGOAL. - * - * During mark, GC tries to identify all reachable objects and mark them as reachable, while keeping unreachable objects unmarked. - * During sweep, GC tries to sweep all objects that were not reachable at the end of mark. The atomic phase is needed to ensure - * that all pending marking has completed and all objects that are still marked as unreachable are, in fact, unreachable. - * - * Notably, during mark GC doesn't free any objects, and so the heap size constantly grows; during sweep, GC doesn't do any marking - * work, so it can't immediately free objects that became unreachable after sweeping started. - * - * Every collectable object has one of three colors at any given point in time: white, gray or black. This coloring scheme - * is necessary to implement incremental marking: white objects have not been marked and may be unreachable, black objects - * have been marked and will not be marked again if they stay black, and gray objects have been marked but may contain unmarked - * references. - * - * Objects are allocated as white; however, during sweep, we need to differentiate between objects that remained white in the mark - * phase (these are not reachable and can be freed) and objects that were allocated after the mark phase ended. Because of this, the - * colors are encoded using three bits inside GCheader::marked: white0, white1 and black (so technically we use a four-color scheme: - * any object can be white0, white1, gray or black). All bits are exclusive, and gray objects have all three bits unset. This allows - * us to have the "current" white bit, which is flipped during atomic stage - during sweeping, objects that have the white color from - * the previous mark may be deleted, and all other objects may or may not be reachable, and will be changed to the current white color, - * so that the next mark can start coloring objects from scratch again. - * - * Crucially, the coloring scheme comes with what's known as a tri-color invariant: a black object may never point to a white object. - * - * At the end of atomic stage, the expectation is that there are no gray objects anymore, which means all objects are either black - * (reachable) or white (unreachable = dead). Tri-color invariant is maintained throughout mark and atomic phase. To uphold this - * invariant, every modification of an object needs to check if the object is black and the new referent is white; if so, we - * need to either mark the referent, making it non-white (known as a forward barrier), or mark the object as gray and queue it - * for additional marking (known as a backward barrier). - * - * Luau uses both types of barriers. Forward barriers advance GC progress, since they don't create new outstanding work for GC, - * but they may be expensive when an object is modified many times in succession. Backward barriers are cheaper, as they defer - * most of the work until "later", but they require queueing the object for a rescan which isn't always possible. Table writes usually - * use backward barriers (but switch to forward barriers during second-phase mark), whereas upvalue writes and setmetatable use forward - * barriers. - * - * Since marking is incremental, it needs a way to track progress, which is implemented as a gray set: at any point, objects that - * are gray need to mark their white references, objects that are black have no pending work, and objects that are white have not yet - * been reached. Once the gray set is empty, the work completes; as such, incremental marking is as simple as removing an object from - * the gray set, and turning it to black (which requires turning all its white references to gray). The gray set is implemented as - * an intrusive singly linked list, using `gclist` field in multiple objects (functions, tables, threads and protos). When an object - * doesn't have gclist field, the marking of that object needs to be "immediate", changing the colors of all references in one go. - * - * When a black object is modified, it needs to become gray again. Objects like this are placed on a separate `grayagain` list by a - * barrier - this is important because it allows us to have a mark stage that terminates when the gray set is empty even if the mutator - * is constantly changing existing objects to gray. After mark stage finishes traversing `gray` list, we copy `grayagain` list to `gray` - * once and incrementally mark it again. During this phase of marking, we may get more objects marked as `grayagain`, so after we finish - * emptying out the `gray` list the second time, we finish the mark stage and do final marking of `grayagain` during atomic phase. - * GC works correctly without this second-phase mark (called GCSpropagateagain), but it reduces the time spent during atomic phase. - * - * Sweeping is also incremental, but instead of working at a granularity of an object, it works at a granularity of a page: all GC - * objects are allocated in special pages (see lmem.cpp for details), and sweeper traverses all objects in one page in one incremental - * step, freeing objects that aren't reachable (old white), and recoloring all other objects with the new white to prepare them for next - * mark. During sweeping we don't need to maintain the GC invariant, because our goal is to paint all objects with current white - - * however, some barriers will still trigger (because some reachable objects are still black as sweeping didn't get to them yet), and - * some barriers will proactively mark black objects as white to avoid extra barriers from triggering excessively. - * - * Most references that GC deals with are strong, and as such they fit neatly into the incremental marking scheme. Some, however, are - * weak - notably, tables can be marked as having weak keys/values (using __mode metafield). During incremental marking, we don't know - * for certain if a given object is alive - if it's marked as black, it definitely was reachable during marking, but if it's marked as - * white, we don't know if it's actually unreachable. Because of this, we need to defer weak table handling to the atomic phase; after - * all objects are marked, we traverse all weak tables (that are linked into special weak table lists using `gclist` during marking), - * and remove all entries that have white keys or values. If keys or values are strong, they are marked normally. - * - * The simplified scheme described above isn't fully accurate because of threads, upvalues and strings. - * - * Strings are semantically black (they are initially white, and when the mark stage reaches a string, it changes its color and never - * touches the object again), but they are technically marked as gray - the black bit is never set on a string object. This behavior - * is inherited from Lua 5.1 GC, but doesn't have a clear rationale - effectively, strings are marked as gray but are never part of - * a gray list. - * - * Threads are hard to deal with because for them to fit into the white-gray-black scheme, writes to thread stacks need to have barriers - * that turn the thread from black (already scanned) to gray - but this is very expensive because stack writes are very common. To - * get around this problem, threads have an "active" state which means that a thread is actively executing code. When GC reaches an active - * thread, it keeps it as gray, and rescans it during atomic phase. When a thread is inactive, GC instead paints the thread black. All - * API calls that can write to thread stacks outside of execution (which implies active) uses a thread barrier that checks if the thread is - * black, and if it is it marks it as gray and puts it on a gray list to be rescanned during atomic phase. - * - * Upvalues are special objects that can be closed, in which case they contain the value (acting as a reference cell) and can be dealt - * with using the regular algorithm, or open, in which case they refer to a stack slot in some other thread. These are difficult to deal - * with because the stack writes are not monitored. Because of this open upvalues are treated in a somewhat special way: they are never marked - * as black (doing so would violate the GC invariant), and they are kept in a special global list (global_State::uvhead) which is traversed - * during atomic phase. This is needed because an open upvalue might point to a stack location in a dead thread that never marked the stack - * slot - upvalues like this are identified since they don't have `markedopen` bit set during thread traversal and closed in `clearupvals`. - */ - -#define GC_SWEEPPAGESTEPCOST 16 - -#define GC_INTERRUPT(state) \ - { \ - void (*interrupt)(lua_State*, int) = g->cb.interrupt; \ - if (LUAU_UNLIKELY(!!interrupt)) \ - interrupt(L, state); \ - } - -#define maskmarks cast_byte(~(bitmask(BLACKBIT) | WHITEBITS)) - -#define makewhite(g, x) ((x)->gch.marked = cast_byte(((x)->gch.marked & maskmarks) | luaC_white(g))) - -#define white2gray(x) reset2bits((x)->gch.marked, WHITE0BIT, WHITE1BIT) -#define black2gray(x) resetbit((x)->gch.marked, BLACKBIT) - -#define stringmark(s) reset2bits((s)->marked, WHITE0BIT, WHITE1BIT) - -#define markvalue(g, o) \ - { \ - checkconsistency(o); \ - if (iscollectable(o) && iswhite(gcvalue(o))) \ - reallymarkobject(g, gcvalue(o)); \ - } - -#define markobject(g, t) \ - { \ - if (iswhite(obj2gco(t))) \ - reallymarkobject(g, obj2gco(t)); \ - } - -#ifdef LUAI_GCMETRICS -static void recordGcStateStep(global_State* g, int startgcstate, double seconds, bool assist, size_t work) -{ - switch (startgcstate) - { - case GCSpause: - // record root mark time if we have switched to next state - if (g->gcstate == GCSpropagate) - { - g->gcmetrics.currcycle.marktime += seconds; - - if (assist) - g->gcmetrics.currcycle.markassisttime += seconds; - } - break; - case GCSpropagate: - case GCSpropagateagain: - g->gcmetrics.currcycle.marktime += seconds; - g->gcmetrics.currcycle.markwork += work; - - if (assist) - g->gcmetrics.currcycle.markassisttime += seconds; - break; - case GCSatomic: - g->gcmetrics.currcycle.atomictime += seconds; - break; - case GCSsweep: - g->gcmetrics.currcycle.sweeptime += seconds; - g->gcmetrics.currcycle.sweepwork += work; - - if (assist) - g->gcmetrics.currcycle.sweepassisttime += seconds; - break; - default: - LUAU_ASSERT(!"Unexpected GC state"); - } - - if (assist) - { - g->gcmetrics.stepassisttimeacc += seconds; - g->gcmetrics.currcycle.assistwork += work; - } - else - { - g->gcmetrics.stepexplicittimeacc += seconds; - g->gcmetrics.currcycle.explicitwork += work; - } -} - -static double recordGcDeltaTime(double& timer) -{ - double now = lua_clock(); - double delta = now - timer; - timer = now; - return delta; -} - -static void startGcCycleMetrics(global_State* g) -{ - g->gcmetrics.currcycle.starttimestamp = lua_clock(); - g->gcmetrics.currcycle.pausetime = g->gcmetrics.currcycle.starttimestamp - g->gcmetrics.lastcycle.endtimestamp; -} - -static void finishGcCycleMetrics(global_State* g) -{ - g->gcmetrics.currcycle.endtimestamp = lua_clock(); - g->gcmetrics.currcycle.endtotalsizebytes = g->totalbytes; - - g->gcmetrics.completedcycles++; - g->gcmetrics.lastcycle = g->gcmetrics.currcycle; - g->gcmetrics.currcycle = GCCycleMetrics(); - - g->gcmetrics.currcycle.starttotalsizebytes = g->totalbytes; - g->gcmetrics.currcycle.heaptriggersizebytes = g->GCthreshold; -} -#endif - -static void removeentry(LuaNode* n) -{ - LUAU_ASSERT(ttisnil(gval(n))); - if (iscollectable(gkey(n))) - setttype(gkey(n), LUA_TDEADKEY); // dead key; remove it -} - -static void reallymarkobject(global_State* g, GCObject* o) -{ - LUAU_ASSERT(iswhite(o) && !isdead(g, o)); - white2gray(o); - switch (o->gch.tt) - { - case LUA_TSTRING: - { - return; - } - case LUA_TUSERDATA: - { - Table* mt = gco2u(o)->metatable; - gray2black(o); // udata are never gray - if (mt) - markobject(g, mt); - return; - } - case LUA_TUPVAL: - { - UpVal* uv = gco2uv(o); - markvalue(g, uv->v); - if (!upisopen(uv)) // closed? - gray2black(o); // open upvalues are never black - return; - } - case LUA_TFUNCTION: - { - gco2cl(o)->gclist = g->gray; - g->gray = o; - break; - } - case LUA_TTABLE: - { - gco2h(o)->gclist = g->gray; - g->gray = o; - break; - } - case LUA_TTHREAD: - { - gco2th(o)->gclist = g->gray; - g->gray = o; - break; - } - case LUA_TBUFFER: - { - gray2black(o); // buffers are never gray - return; - } - case LUA_TPROTO: - { - gco2p(o)->gclist = g->gray; - g->gray = o; - break; - } - default: - LUAU_ASSERT(0); - } -} - -static const char* gettablemode(global_State* g, Table* h) -{ - const TValue* mode = gfasttm(g, h->metatable, TM_MODE); - - if (mode && ttisstring(mode)) - return svalue(mode); - - return NULL; -} - -static int traversetable(global_State* g, Table* h) -{ - int i; - int weakkey = 0; - int weakvalue = 0; - if (h->metatable) - markobject(g, cast_to(Table*, h->metatable)); - - // is there a weak mode? - if (const char* modev = gettablemode(g, h)) - { - weakkey = (strchr(modev, 'k') != NULL); - weakvalue = (strchr(modev, 'v') != NULL); - if (weakkey || weakvalue) - { // is really weak? - h->gclist = g->weak; // must be cleared after GC, ... - g->weak = obj2gco(h); // ... so put in the appropriate list - } - } - - if (weakkey && weakvalue) - return 1; - if (!weakvalue) - { - i = h->sizearray; - while (i--) - markvalue(g, &h->array[i]); - } - i = sizenode(h); - while (i--) - { - LuaNode* n = gnode(h, i); - LUAU_ASSERT(ttype(gkey(n)) != LUA_TDEADKEY || ttisnil(gval(n))); - if (ttisnil(gval(n))) - removeentry(n); // remove empty entries - else - { - LUAU_ASSERT(!ttisnil(gkey(n))); - if (!weakkey) - markvalue(g, gkey(n)); - if (!weakvalue) - markvalue(g, gval(n)); - } - } - return weakkey || weakvalue; -} - -/* -** All marks are conditional because a GC may happen while the -** prototype is still being created -*/ -static void traverseproto(global_State* g, Proto* f) -{ - int i; - if (f->source) - stringmark(f->source); - if (f->debugname) - stringmark(f->debugname); - for (i = 0; i < f->sizek; i++) // mark literals - markvalue(g, &f->k[i]); - for (i = 0; i < f->sizeupvalues; i++) - { // mark upvalue names - if (f->upvalues[i]) - stringmark(f->upvalues[i]); - } - for (i = 0; i < f->sizep; i++) - { // mark nested protos - if (f->p[i]) - markobject(g, f->p[i]); - } - for (i = 0; i < f->sizelocvars; i++) - { // mark local-variable names - if (f->locvars[i].varname) - stringmark(f->locvars[i].varname); - } -} - -static void traverseclosure(global_State* g, Closure* cl) -{ - markobject(g, cl->env); - if (cl->isC) - { - int i; - for (i = 0; i < cl->nupvalues; i++) // mark its upvalues - markvalue(g, &cl->c.upvals[i]); - } - else - { - int i; - LUAU_ASSERT(cl->nupvalues == cl->l.p->nups); - markobject(g, cast_to(Proto*, cl->l.p)); - for (i = 0; i < cl->nupvalues; i++) // mark its upvalues - markvalue(g, &cl->l.uprefs[i]); - } -} - -static void traversestack(global_State* g, lua_State* l) -{ - markobject(g, l->gt); - if (l->namecall) - stringmark(l->namecall); - for (StkId o = l->stack; o < l->top; o++) - markvalue(g, o); - for (UpVal* uv = l->openupval; uv; uv = uv->u.open.threadnext) - { - LUAU_ASSERT(upisopen(uv)); - uv->markedopen = 1; - markobject(g, uv); - } -} - -static void clearstack(lua_State* l) -{ - StkId stack_end = l->stack + l->stacksize; - for (StkId o = l->top; o < stack_end; o++) // clear not-marked stack slice - setnilvalue(o); -} - -static void shrinkstack(lua_State* L) -{ - // compute used stack - note that we can't use th->top if we're in the middle of vararg call - StkId lim = L->top; - for (CallInfo* ci = L->base_ci; ci <= L->ci; ci++) - { - LUAU_ASSERT(ci->top <= L->stack_last); - if (lim < ci->top) - lim = ci->top; - } - - // shrink stack and callinfo arrays if we aren't using most of the space - int ci_used = cast_int(L->ci - L->base_ci); // number of `ci' in use - int s_used = cast_int(lim - L->stack); // part of stack in use - if (L->size_ci > LUAI_MAXCALLS) // handling overflow? - return; // do not touch the stacks - if (3 * ci_used < L->size_ci && 2 * BASIC_CI_SIZE < L->size_ci) - luaD_reallocCI(L, L->size_ci / 2); // still big enough... - condhardstacktests(luaD_reallocCI(L, ci_used + 1)); - if (3 * s_used < L->stacksize && 2 * (BASIC_STACK_SIZE + EXTRA_STACK) < L->stacksize) - luaD_reallocstack(L, L->stacksize / 2); // still big enough... - condhardstacktests(luaD_reallocstack(L, s_used)); -} - -/* -** traverse one gray object, turning it to black. -** Returns `quantity' traversed. -*/ -static size_t propagatemark(global_State* g) -{ - GCObject* o = g->gray; - LUAU_ASSERT(isgray(o)); - gray2black(o); - switch (o->gch.tt) - { - case LUA_TTABLE: - { - Table* h = gco2h(o); - g->gray = h->gclist; - if (traversetable(g, h)) // table is weak? - black2gray(o); // keep it gray - return sizeof(Table) + sizeof(TValue) * h->sizearray + sizeof(LuaNode) * sizenode(h); - } - case LUA_TFUNCTION: - { - Closure* cl = gco2cl(o); - g->gray = cl->gclist; - traverseclosure(g, cl); - return cl->isC ? sizeCclosure(cl->nupvalues) : sizeLclosure(cl->nupvalues); - } - case LUA_TTHREAD: - { - lua_State* th = gco2th(o); - g->gray = th->gclist; - - bool active = th->isactive || th == th->global->mainthread; - - traversestack(g, th); - - // active threads will need to be rescanned later to mark new stack writes so we mark them gray again - if (active) - { - th->gclist = g->grayagain; - g->grayagain = o; - - black2gray(o); - } - - // the stack needs to be cleared after the last modification of the thread state before sweep begins - // if the thread is inactive, we might not see the thread in this cycle so we must clear it now - if (!active || g->gcstate == GCSatomic) - clearstack(th); - - // we could shrink stack at any time but we opt to do it during initial mark to do that just once per cycle - if (g->gcstate == GCSpropagate) - shrinkstack(th); - - return sizeof(lua_State) + sizeof(TValue) * th->stacksize + sizeof(CallInfo) * th->size_ci; - } - case LUA_TPROTO: - { - Proto* p = gco2p(o); - g->gray = p->gclist; - traverseproto(g, p); - return sizeof(Proto) + sizeof(Instruction) * p->sizecode + sizeof(Proto*) * p->sizep + sizeof(TValue) * p->sizek + p->sizelineinfo + - sizeof(LocVar) * p->sizelocvars + sizeof(TString*) * p->sizeupvalues; - } - default: - LUAU_ASSERT(0); - return 0; - } -} - -static size_t propagateall(global_State* g) -{ - size_t work = 0; - while (g->gray) - { - work += propagatemark(g); - } - return work; -} - -/* -** The next function tells whether a key or value can be cleared from -** a weak table. Non-collectable objects are never removed from weak -** tables. Strings behave as `values', so are never removed too. for -** other objects: if really collected, cannot keep them. -*/ -static int isobjcleared(GCObject* o) -{ - if (o->gch.tt == LUA_TSTRING) - { - stringmark(&o->ts); // strings are `values', so are never weak - return 0; - } - - return iswhite(o); -} - -#define iscleared(o) (iscollectable(o) && isobjcleared(gcvalue(o))) - -/* -** clear collected entries from weaktables -*/ -static size_t cleartable(lua_State* L, GCObject* l) -{ - size_t work = 0; - while (l) - { - Table* h = gco2h(l); - work += sizeof(Table) + sizeof(TValue) * h->sizearray + sizeof(LuaNode) * sizenode(h); - - int i = h->sizearray; - while (i--) - { - TValue* o = &h->array[i]; - if (iscleared(o)) // value was collected? - setnilvalue(o); // remove value - } - i = sizenode(h); - int activevalues = 0; - while (i--) - { - LuaNode* n = gnode(h, i); - - // non-empty entry? - if (!ttisnil(gval(n))) - { - // can we clear key or value? - if (iscleared(gkey(n)) || iscleared(gval(n))) - { - setnilvalue(gval(n)); // remove value ... - removeentry(n); // remove entry from table - } - else - { - activevalues++; - } - } - } - - if (const char* modev = gettablemode(L->global, h)) - { - // are we allowed to shrink this weak table? - if (strchr(modev, 's')) - { - // shrink at 37.5% occupancy - if (activevalues < sizenode(h) * 3 / 8) - luaH_resizehash(L, h, activevalues); - } - } - - l = h->gclist; - } - return work; -} - -static void freeobj(lua_State* L, GCObject* o, lua_Page* page) -{ - switch (o->gch.tt) - { - case LUA_TPROTO: - luaF_freeproto(L, gco2p(o), page); - break; - case LUA_TFUNCTION: - luaF_freeclosure(L, gco2cl(o), page); - break; - case LUA_TUPVAL: - luaF_freeupval(L, gco2uv(o), page); - break; - case LUA_TTABLE: - luaH_free(L, gco2h(o), page); - break; - case LUA_TTHREAD: - LUAU_ASSERT(gco2th(o) != L && gco2th(o) != L->global->mainthread); - luaE_freethread(L, gco2th(o), page); - break; - case LUA_TSTRING: - luaS_free(L, gco2ts(o), page); - break; - case LUA_TUSERDATA: - luaU_freeudata(L, gco2u(o), page); - break; - case LUA_TBUFFER: - luaB_freebuffer(L, gco2buf(o), page); - break; - default: - LUAU_ASSERT(0); - } -} - -static void shrinkbuffers(lua_State* L) -{ - global_State* g = L->global; - // check size of string hash - if (g->strt.nuse < cast_to(uint32_t, g->strt.size / 4) && g->strt.size > LUA_MINSTRTABSIZE * 2) - luaS_resize(L, g->strt.size / 2); // table is too big -} - -static void shrinkbuffersfull(lua_State* L) -{ - global_State* g = L->global; - // check size of string hash - int hashsize = g->strt.size; - while (g->strt.nuse < cast_to(uint32_t, hashsize / 4) && hashsize > LUA_MINSTRTABSIZE * 2) - hashsize /= 2; - if (hashsize != g->strt.size) - luaS_resize(L, hashsize); // table is too big -} - -static bool deletegco(void* context, lua_Page* page, GCObject* gco) -{ - lua_State* L = (lua_State*)context; - freeobj(L, gco, page); - return true; -} - -void luaC_freeall(lua_State* L) -{ - global_State* g = L->global; - - LUAU_ASSERT(L == g->mainthread); - - luaM_visitgco(L, L, deletegco); - - for (int i = 0; i < g->strt.size; i++) // free all string lists - LUAU_ASSERT(g->strt.hash[i] == NULL); - - LUAU_ASSERT(L->global->strt.nuse == 0); -} - -static void markmt(global_State* g) -{ - int i; - for (i = 0; i < LUA_T_COUNT; i++) - if (g->mt[i]) - markobject(g, g->mt[i]); -} - -// mark root set -static void markroot(lua_State* L) -{ - global_State* g = L->global; - g->gray = NULL; - g->grayagain = NULL; - g->weak = NULL; - markobject(g, g->mainthread); - // make global table be traversed before main stack - markobject(g, g->mainthread->gt); - markvalue(g, registry(L)); - markmt(g); - g->gcstate = GCSpropagate; -} - -static size_t remarkupvals(global_State* g) -{ - size_t work = 0; - - for (UpVal* uv = g->uvhead.u.open.next; uv != &g->uvhead; uv = uv->u.open.next) - { - work += sizeof(UpVal); - - LUAU_ASSERT(upisopen(uv)); - LUAU_ASSERT(uv->u.open.next->u.open.prev == uv && uv->u.open.prev->u.open.next == uv); - LUAU_ASSERT(!isblack(obj2gco(uv))); // open upvalues are never black - - if (isgray(obj2gco(uv))) - markvalue(g, uv->v); - } - - return work; -} - -static size_t clearupvals(lua_State* L) -{ - global_State* g = L->global; - - size_t work = 0; - - for (UpVal* uv = g->uvhead.u.open.next; uv != &g->uvhead;) - { - work += sizeof(UpVal); - - LUAU_ASSERT(upisopen(uv)); - LUAU_ASSERT(uv->u.open.next->u.open.prev == uv && uv->u.open.prev->u.open.next == uv); - LUAU_ASSERT(!isblack(obj2gco(uv))); // open upvalues are never black - LUAU_ASSERT(iswhite(obj2gco(uv)) || !iscollectable(uv->v) || !iswhite(gcvalue(uv->v))); - - if (uv->markedopen) - { - // upvalue is still open (belongs to alive thread) - LUAU_ASSERT(isgray(obj2gco(uv))); - uv->markedopen = 0; // for next cycle - uv = uv->u.open.next; - } - else - { - // upvalue is either dead, or alive but the thread is dead; unlink and close - UpVal* next = uv->u.open.next; - luaF_closeupval(L, uv, /* dead= */ iswhite(obj2gco(uv))); - uv = next; - } - } - - return work; -} - -static size_t atomic(lua_State* L) -{ - global_State* g = L->global; - LUAU_ASSERT(g->gcstate == GCSatomic); - - size_t work = 0; - -#ifdef LUAI_GCMETRICS - double currts = lua_clock(); -#endif - - // remark occasional upvalues of (maybe) dead threads - work += remarkupvals(g); - // traverse objects caught by write barrier and by 'remarkupvals' - work += propagateall(g); - -#ifdef LUAI_GCMETRICS - g->gcmetrics.currcycle.atomictimeupval += recordGcDeltaTime(currts); -#endif - - // remark weak tables - g->gray = g->weak; - g->weak = NULL; - LUAU_ASSERT(!iswhite(obj2gco(g->mainthread))); - markobject(g, L); // mark running thread - markmt(g); // mark basic metatables (again) - work += propagateall(g); - -#ifdef LUAI_GCMETRICS - g->gcmetrics.currcycle.atomictimeweak += recordGcDeltaTime(currts); -#endif - - // remark gray again - g->gray = g->grayagain; - g->grayagain = NULL; - work += propagateall(g); - -#ifdef LUAI_GCMETRICS - g->gcmetrics.currcycle.atomictimegray += recordGcDeltaTime(currts); -#endif - - // remove collected objects from weak tables - work += cleartable(L, g->weak); - g->weak = NULL; - -#ifdef LUAI_GCMETRICS - g->gcmetrics.currcycle.atomictimeclear += recordGcDeltaTime(currts); -#endif - - // close orphaned live upvalues of dead threads and clear dead upvalues - work += clearupvals(L); - -#ifdef LUAI_GCMETRICS - g->gcmetrics.currcycle.atomictimeupval += recordGcDeltaTime(currts); -#endif - - // flip current white - g->currentwhite = cast_byte(otherwhite(g)); - g->sweepgcopage = g->allgcopages; - g->gcstate = GCSsweep; - - return work; -} - -// a version of generic luaM_visitpage specialized for the main sweep stage -static int sweepgcopage(lua_State* L, lua_Page* page) -{ - char* start; - char* end; - int busyBlocks; - int blockSize; - luaM_getpagewalkinfo(page, &start, &end, &busyBlocks, &blockSize); - - LUAU_ASSERT(busyBlocks > 0); - - global_State* g = L->global; - - int deadmask = otherwhite(g); - LUAU_ASSERT(testbit(deadmask, FIXEDBIT)); // make sure we never sweep fixed objects - - int newwhite = luaC_white(g); - - for (char* pos = start; pos != end; pos += blockSize) - { - GCObject* gco = (GCObject*)pos; - - // skip memory blocks that are already freed - if (gco->gch.tt == LUA_TNIL) - continue; - - // is the object alive? - if ((gco->gch.marked ^ WHITEBITS) & deadmask) - { - LUAU_ASSERT(!isdead(g, gco)); - // make it white (for next cycle) - gco->gch.marked = cast_byte((gco->gch.marked & maskmarks) | newwhite); - } - else - { - LUAU_ASSERT(isdead(g, gco)); - freeobj(L, gco, page); - - // if the last block was removed, page would be removed as well - if (--busyBlocks == 0) - return int(pos - start) / blockSize + 1; - } - } - - return int(end - start) / blockSize; -} - -static size_t gcstep(lua_State* L, size_t limit) -{ - size_t cost = 0; - global_State* g = L->global; - switch (g->gcstate) - { - case GCSpause: - { - markroot(L); // start a new collection - LUAU_ASSERT(g->gcstate == GCSpropagate); - break; - } - case GCSpropagate: - { - while (g->gray && cost < limit) - { - cost += propagatemark(g); - } - - if (!g->gray) - { -#ifdef LUAI_GCMETRICS - g->gcmetrics.currcycle.propagatework = g->gcmetrics.currcycle.explicitwork + g->gcmetrics.currcycle.assistwork; -#endif - - // perform one iteration over 'gray again' list - g->gray = g->grayagain; - g->grayagain = NULL; - - g->gcstate = GCSpropagateagain; - } - break; - } - case GCSpropagateagain: - { - while (g->gray && cost < limit) - { - cost += propagatemark(g); - } - - if (!g->gray) // no more `gray' objects - { -#ifdef LUAI_GCMETRICS - g->gcmetrics.currcycle.propagateagainwork = - g->gcmetrics.currcycle.explicitwork + g->gcmetrics.currcycle.assistwork - g->gcmetrics.currcycle.propagatework; -#endif - - g->gcstate = GCSatomic; - } - break; - } - case GCSatomic: - { -#ifdef LUAI_GCMETRICS - g->gcmetrics.currcycle.atomicstarttimestamp = lua_clock(); - g->gcmetrics.currcycle.atomicstarttotalsizebytes = g->totalbytes; -#endif - - g->gcstats.atomicstarttimestamp = lua_clock(); - g->gcstats.atomicstarttotalsizebytes = g->totalbytes; - - cost = atomic(L); // finish mark phase - - LUAU_ASSERT(g->gcstate == GCSsweep); - break; - } - case GCSsweep: - { - while (g->sweepgcopage && cost < limit) - { - lua_Page* next = luaM_getnextgcopage(g->sweepgcopage); // page sweep might destroy the page - - int steps = sweepgcopage(L, g->sweepgcopage); - - g->sweepgcopage = next; - cost += steps * GC_SWEEPPAGESTEPCOST; - } - - // nothing more to sweep? - if (g->sweepgcopage == NULL) - { - // don't forget to visit main thread, it's the only object not allocated in GCO pages - LUAU_ASSERT(!isdead(g, obj2gco(g->mainthread))); - makewhite(g, obj2gco(g->mainthread)); // make it white (for next cycle) - - shrinkbuffers(L); - - g->gcstate = GCSpause; // end collection - } - break; - } - default: - LUAU_ASSERT(!"Unexpected GC state"); - } - return cost; -} - -static int64_t getheaptriggererroroffset(global_State* g) -{ - // adjust for error using Proportional-Integral controller - // https://en.wikipedia.org/wiki/PID_controller - int32_t errorKb = int32_t((g->gcstats.atomicstarttotalsizebytes - g->gcstats.heapgoalsizebytes) / 1024); - - // we use sliding window for the error integral to avoid error sum 'windup' when the desired target cannot be reached - const size_t triggertermcount = sizeof(g->gcstats.triggerterms) / sizeof(g->gcstats.triggerterms[0]); - - int32_t* slot = &g->gcstats.triggerterms[g->gcstats.triggertermpos % triggertermcount]; - int32_t prev = *slot; - *slot = errorKb; - g->gcstats.triggerintegral += errorKb - prev; - g->gcstats.triggertermpos++; - - // controller tuning - // https://en.wikipedia.org/wiki/Ziegler%E2%80%93Nichols_method - const double Ku = 0.9; // ultimate gain (measured) - const double Tu = 2.5; // oscillation period (measured) - - const double Kp = 0.45 * Ku; // proportional gain - const double Ti = 0.8 * Tu; - const double Ki = 0.54 * Ku / Ti; // integral gain - - double proportionalTerm = Kp * errorKb; - double integralTerm = Ki * g->gcstats.triggerintegral; - - double totalTerm = proportionalTerm + integralTerm; - - return int64_t(totalTerm * 1024); -} - -static size_t getheaptrigger(global_State* g, size_t heapgoal) -{ - // adjust threshold based on a guess of how many bytes will be allocated between the cycle start and sweep phase - // our goal is to begin the sweep when used memory has reached the heap goal - const double durationthreshold = 1e-3; - double allocationduration = g->gcstats.atomicstarttimestamp - g->gcstats.endtimestamp; - - // avoid measuring intervals smaller than 1ms - if (allocationduration < durationthreshold) - return heapgoal; - - double allocationrate = (g->gcstats.atomicstarttotalsizebytes - g->gcstats.endtotalsizebytes) / allocationduration; - double markduration = g->gcstats.atomicstarttimestamp - g->gcstats.starttimestamp; - - int64_t expectedgrowth = int64_t(markduration * allocationrate); - int64_t offset = getheaptriggererroroffset(g); - int64_t heaptrigger = heapgoal - (expectedgrowth + offset); - - // clamp the trigger between memory use at the end of the cycle and the heap goal - return heaptrigger < int64_t(g->totalbytes) ? g->totalbytes : (heaptrigger > int64_t(heapgoal) ? heapgoal : size_t(heaptrigger)); -} - -size_t luaC_step(lua_State* L, bool assist) -{ - global_State* g = L->global; - - int lim = g->gcstepsize * g->gcstepmul / 100; // how much to work - LUAU_ASSERT(g->totalbytes >= g->GCthreshold); - size_t debt = g->totalbytes - g->GCthreshold; - - GC_INTERRUPT(0); - - // at the start of the new cycle - if (g->gcstate == GCSpause) - g->gcstats.starttimestamp = lua_clock(); - -#ifdef LUAI_GCMETRICS - if (g->gcstate == GCSpause) - startGcCycleMetrics(g); - - double lasttimestamp = lua_clock(); -#endif - - int lastgcstate = g->gcstate; - - size_t work = gcstep(L, lim); - -#ifdef LUAI_GCMETRICS - recordGcStateStep(g, lastgcstate, lua_clock() - lasttimestamp, assist, work); -#endif - - size_t actualstepsize = work * 100 / g->gcstepmul; - - // at the end of the last cycle - if (g->gcstate == GCSpause) - { - // at the end of a collection cycle, set goal based on gcgoal setting - size_t heapgoal = (g->totalbytes / 100) * g->gcgoal; - size_t heaptrigger = getheaptrigger(g, heapgoal); - - g->GCthreshold = heaptrigger; - - g->gcstats.heapgoalsizebytes = heapgoal; - g->gcstats.endtimestamp = lua_clock(); - g->gcstats.endtotalsizebytes = g->totalbytes; - -#ifdef LUAI_GCMETRICS - finishGcCycleMetrics(g); -#endif - } - else - { - g->GCthreshold = g->totalbytes + actualstepsize; - - // compensate if GC is "behind schedule" (has some debt to pay) - if (g->GCthreshold >= debt) - g->GCthreshold -= debt; - } - - GC_INTERRUPT(lastgcstate); - - return actualstepsize; -} - -void luaC_fullgc(lua_State* L) -{ - global_State* g = L->global; - -#ifdef LUAI_GCMETRICS - if (g->gcstate == GCSpause) - startGcCycleMetrics(g); -#endif - - if (keepinvariant(g)) - { - // reset sweep marks to sweep all elements (returning them to white) - g->sweepgcopage = g->allgcopages; - // reset other collector lists - g->gray = NULL; - g->grayagain = NULL; - g->weak = NULL; - g->gcstate = GCSsweep; - } - LUAU_ASSERT(g->gcstate == GCSpause || g->gcstate == GCSsweep); - // finish any pending sweep phase - while (g->gcstate != GCSpause) - { - LUAU_ASSERT(g->gcstate == GCSsweep); - gcstep(L, SIZE_MAX); - } - - // clear markedopen bits for all open upvalues; these might be stuck from half-finished mark prior to full gc - for (UpVal* uv = g->uvhead.u.open.next; uv != &g->uvhead; uv = uv->u.open.next) - { - LUAU_ASSERT(upisopen(uv)); - uv->markedopen = 0; - } - -#ifdef LUAI_GCMETRICS - finishGcCycleMetrics(g); - startGcCycleMetrics(g); -#endif - - // run a full collection cycle - markroot(L); - while (g->gcstate != GCSpause) - { - gcstep(L, SIZE_MAX); - } - // reclaim as much buffer memory as possible (shrinkbuffers() called during sweep is incremental) - shrinkbuffersfull(L); - - size_t heapgoalsizebytes = (g->totalbytes / 100) * g->gcgoal; - - // trigger cannot be correctly adjusted after a forced full GC. - // we will try to place it so that we can reach the goal based on - // the rate at which we run the GC relative to allocation rate - // and on amount of bytes we need to traverse in propagation stage. - // goal and stepmul are defined in percents - g->GCthreshold = g->totalbytes * (g->gcgoal * g->gcstepmul / 100 - 100) / g->gcstepmul; - - // but it might be impossible to satisfy that directly - if (g->GCthreshold < g->totalbytes) - g->GCthreshold = g->totalbytes; - - g->gcstats.heapgoalsizebytes = heapgoalsizebytes; - -#ifdef LUAI_GCMETRICS - finishGcCycleMetrics(g); -#endif -} - -void luaC_barrierf(lua_State* L, GCObject* o, GCObject* v) -{ - global_State* g = L->global; - LUAU_ASSERT(isblack(o) && iswhite(v) && !isdead(g, v) && !isdead(g, o)); - LUAU_ASSERT(g->gcstate != GCSpause); - // must keep invariant? - if (keepinvariant(g)) - reallymarkobject(g, v); // restore invariant - else // don't mind - makewhite(g, o); // mark as white just to avoid other barriers -} - -void luaC_barriertable(lua_State* L, Table* t, GCObject* v) -{ - global_State* g = L->global; - GCObject* o = obj2gco(t); - - // in the second propagation stage, table assignment barrier works as a forward barrier - if (g->gcstate == GCSpropagateagain) - { - LUAU_ASSERT(isblack(o) && iswhite(v) && !isdead(g, v) && !isdead(g, o)); - reallymarkobject(g, v); - return; - } - - LUAU_ASSERT(isblack(o) && !isdead(g, o)); - LUAU_ASSERT(g->gcstate != GCSpause); - black2gray(o); // make table gray (again) - t->gclist = g->grayagain; - g->grayagain = o; -} - -void luaC_barrierback(lua_State* L, GCObject* o, GCObject** gclist) -{ - global_State* g = L->global; - LUAU_ASSERT(isblack(o) && !isdead(g, o)); - LUAU_ASSERT(g->gcstate != GCSpause); - - black2gray(o); // make object gray (again) - *gclist = g->grayagain; - g->grayagain = o; -} - -void luaC_upvalclosed(lua_State* L, UpVal* uv) -{ - global_State* g = L->global; - GCObject* o = obj2gco(uv); - - LUAU_ASSERT(!upisopen(uv)); // upvalue was closed but needs GC state fixup - - if (isgray(o)) - { - if (keepinvariant(g)) - { - gray2black(o); // closed upvalues need barrier - luaC_barrier(L, uv, uv->v); - } - else - { // sweep phase: sweep it (turning it into white) - makewhite(g, o); - LUAU_ASSERT(g->gcstate != GCSpause); - } - } -} - -// measure the allocation rate in bytes/sec -// returns -1 if allocation rate cannot be measured -int64_t luaC_allocationrate(lua_State* L) -{ - global_State* g = L->global; - const double durationthreshold = 1e-3; // avoid measuring intervals smaller than 1ms - - if (g->gcstate <= GCSatomic) - { - double duration = lua_clock() - g->gcstats.endtimestamp; - - if (duration < durationthreshold) - return -1; - - return int64_t((g->totalbytes - g->gcstats.endtotalsizebytes) / duration); - } - - // totalbytes is unstable during the sweep, use the rate measured at the end of mark phase - double duration = g->gcstats.atomicstarttimestamp - g->gcstats.endtimestamp; - - if (duration < durationthreshold) - return -1; - - return int64_t((g->gcstats.atomicstarttotalsizebytes - g->gcstats.endtotalsizebytes) / duration); -} - -const char* luaC_statename(int state) -{ - switch (state) - { - case GCSpause: - return "pause"; - - case GCSpropagate: - return "mark"; - - case GCSpropagateagain: - return "remark"; - - case GCSatomic: - return "atomic"; - - case GCSsweep: - return "sweep"; - - default: - return NULL; - } -} diff --git a/lib/luau/VM/src/lgc.h b/lib/luau/VM/src/lgc.h deleted file mode 100644 index ba433c6..0000000 --- a/lib/luau/VM/src/lgc.h +++ /dev/null @@ -1,143 +0,0 @@ -// This file is part of the Luau programming language and is licensed under MIT License; see LICENSE.txt for details -// This code is based on Lua 5.x implementation licensed under MIT License; see lua_LICENSE.txt for details -#pragma once - -#include "ldo.h" -#include "lobject.h" -#include "lstate.h" - -/* -** Default settings for GC tunables (settable via lua_gc) -*/ -#define LUAI_GCGOAL 200 // 200% (allow heap to double compared to live heap size) -#define LUAI_GCSTEPMUL 200 // GC runs 'twice the speed' of memory allocation -#define LUAI_GCSTEPSIZE 1 // GC runs every KB of memory allocation - -/* -** Possible states of the Garbage Collector -*/ -#define GCSpause 0 -#define GCSpropagate 1 -#define GCSpropagateagain 2 -#define GCSatomic 3 -#define GCSsweep 4 - -/* -** macro to tell when main invariant (white objects cannot point to black -** ones) must be kept. During a collection, the sweep -** phase may break the invariant, as objects turned white may point to -** still-black objects. The invariant is restored when sweep ends and -** all objects are white again. -*/ -#define keepinvariant(g) ((g)->gcstate == GCSpropagate || (g)->gcstate == GCSpropagateagain || (g)->gcstate == GCSatomic) - -/* -** some useful bit tricks -*/ -#define resetbits(x, m) ((x) &= cast_to(uint8_t, ~(m))) -#define setbits(x, m) ((x) |= (m)) -#define testbits(x, m) ((x) & (m)) -#define bitmask(b) (1 << (b)) -#define bit2mask(b1, b2) (bitmask(b1) | bitmask(b2)) -#define l_setbit(x, b) setbits(x, bitmask(b)) -#define resetbit(x, b) resetbits(x, bitmask(b)) -#define testbit(x, b) testbits(x, bitmask(b)) -#define set2bits(x, b1, b2) setbits(x, (bit2mask(b1, b2))) -#define reset2bits(x, b1, b2) resetbits(x, (bit2mask(b1, b2))) -#define test2bits(x, b1, b2) testbits(x, (bit2mask(b1, b2))) - -/* -** Layout for bit use in `marked' field: -** bit 0 - object is white (type 0) -** bit 1 - object is white (type 1) -** bit 2 - object is black -** bit 3 - object is fixed (should not be collected) -*/ - -#define WHITE0BIT 0 -#define WHITE1BIT 1 -#define BLACKBIT 2 -#define FIXEDBIT 3 -#define WHITEBITS bit2mask(WHITE0BIT, WHITE1BIT) - -#define iswhite(x) test2bits((x)->gch.marked, WHITE0BIT, WHITE1BIT) -#define isblack(x) testbit((x)->gch.marked, BLACKBIT) -#define isgray(x) (!testbits((x)->gch.marked, WHITEBITS | bitmask(BLACKBIT))) -#define isfixed(x) testbit((x)->gch.marked, FIXEDBIT) - -#define otherwhite(g) (g->currentwhite ^ WHITEBITS) -#define isdead(g, v) (((v)->gch.marked & (WHITEBITS | bitmask(FIXEDBIT))) == (otherwhite(g) & WHITEBITS)) - -#define changewhite(x) ((x)->gch.marked ^= WHITEBITS) -#define gray2black(x) l_setbit((x)->gch.marked, BLACKBIT) - -#define luaC_white(g) cast_to(uint8_t, ((g)->currentwhite) & WHITEBITS) - -#define luaC_needsGC(L) (L->global->totalbytes >= L->global->GCthreshold) - -#define luaC_checkGC(L) \ - { \ - condhardstacktests(luaD_reallocstack(L, L->stacksize - EXTRA_STACK)); \ - if (luaC_needsGC(L)) \ - { \ - condhardmemtests(luaC_validate(L), 1); \ - luaC_step(L, true); \ - } \ - else \ - { \ - condhardmemtests(luaC_validate(L), 2); \ - } \ - } - -#define luaC_barrier(L, p, v) \ - { \ - if (iscollectable(v) && isblack(obj2gco(p)) && iswhite(gcvalue(v))) \ - luaC_barrierf(L, obj2gco(p), gcvalue(v)); \ - } - -#define luaC_barriert(L, t, v) \ - { \ - if (iscollectable(v) && isblack(obj2gco(t)) && iswhite(gcvalue(v))) \ - luaC_barriertable(L, t, gcvalue(v)); \ - } - -#define luaC_barrierfast(L, t) \ - { \ - if (isblack(obj2gco(t))) \ - luaC_barrierback(L, obj2gco(t), &t->gclist); \ - } - -#define luaC_objbarrier(L, p, o) \ - { \ - if (isblack(obj2gco(p)) && iswhite(obj2gco(o))) \ - luaC_barrierf(L, obj2gco(p), obj2gco(o)); \ - } - -#define luaC_threadbarrier(L) \ - { \ - if (isblack(obj2gco(L))) \ - luaC_barrierback(L, obj2gco(L), &L->gclist); \ - } - -#define luaC_init(L, o, tt_) \ - { \ - o->marked = luaC_white(L->global); \ - o->tt = tt_; \ - o->memcat = L->activememcat; \ - } - -LUAI_FUNC void luaC_freeall(lua_State* L); -LUAI_FUNC size_t luaC_step(lua_State* L, bool assist); -LUAI_FUNC void luaC_fullgc(lua_State* L); -LUAI_FUNC void luaC_initobj(lua_State* L, GCObject* o, uint8_t tt); -LUAI_FUNC void luaC_upvalclosed(lua_State* L, UpVal* uv); -LUAI_FUNC void luaC_barrierf(lua_State* L, GCObject* o, GCObject* v); -LUAI_FUNC void luaC_barriertable(lua_State* L, Table* t, GCObject* v); -LUAI_FUNC void luaC_barrierback(lua_State* L, GCObject* o, GCObject** gclist); -LUAI_FUNC void luaC_validate(lua_State* L); -LUAI_FUNC void luaC_dump(lua_State* L, void* file, const char* (*categoryName)(lua_State* L, uint8_t memcat)); -LUAI_FUNC void luaC_enumheap(lua_State* L, void* context, - void (*node)(void* context, void* ptr, uint8_t tt, uint8_t memcat, size_t size, const char* name), - void (*edge)(void* context, void* from, void* to, const char* name)); -LUAI_FUNC int64_t luaC_allocationrate(lua_State* L); -LUAI_FUNC const char* luaC_statename(int state); diff --git a/lib/luau/VM/src/lgcdebug.cpp b/lib/luau/VM/src/lgcdebug.cpp deleted file mode 100644 index 48a6d2e..0000000 --- a/lib/luau/VM/src/lgcdebug.cpp +++ /dev/null @@ -1,897 +0,0 @@ -// This file is part of the Luau programming language and is licensed under MIT License; see LICENSE.txt for details -// This code is based on Lua 5.x implementation licensed under MIT License; see lua_LICENSE.txt for details -#include "lgc.h" - -#include "lfunc.h" -#include "lmem.h" -#include "lobject.h" -#include "lstate.h" -#include "lstring.h" -#include "ltable.h" -#include "ludata.h" -#include "lbuffer.h" - -#include -#include - -static void validateobjref(global_State* g, GCObject* f, GCObject* t) -{ - LUAU_ASSERT(!isdead(g, t)); - - if (keepinvariant(g)) - { - // basic incremental invariant: black can't point to white - LUAU_ASSERT(!(isblack(f) && iswhite(t))); - } -} - -static void validateref(global_State* g, GCObject* f, TValue* v) -{ - if (iscollectable(v)) - { - LUAU_ASSERT(ttype(v) == gcvalue(v)->gch.tt); - validateobjref(g, f, gcvalue(v)); - } -} - -static void validatetable(global_State* g, Table* h) -{ - int sizenode = 1 << h->lsizenode; - - LUAU_ASSERT(h->lastfree <= sizenode); - - if (h->metatable) - validateobjref(g, obj2gco(h), obj2gco(h->metatable)); - - for (int i = 0; i < h->sizearray; ++i) - validateref(g, obj2gco(h), &h->array[i]); - - for (int i = 0; i < sizenode; ++i) - { - LuaNode* n = &h->node[i]; - - LUAU_ASSERT(ttype(gkey(n)) != LUA_TDEADKEY || ttisnil(gval(n))); - LUAU_ASSERT(i + gnext(n) >= 0 && i + gnext(n) < sizenode); - - if (!ttisnil(gval(n))) - { - TValue k = {}; - k.tt = gkey(n)->tt; - k.value = gkey(n)->value; - - validateref(g, obj2gco(h), &k); - validateref(g, obj2gco(h), gval(n)); - } - } -} - -static void validateclosure(global_State* g, Closure* cl) -{ - validateobjref(g, obj2gco(cl), obj2gco(cl->env)); - - if (cl->isC) - { - for (int i = 0; i < cl->nupvalues; ++i) - validateref(g, obj2gco(cl), &cl->c.upvals[i]); - } - else - { - LUAU_ASSERT(cl->nupvalues == cl->l.p->nups); - - validateobjref(g, obj2gco(cl), obj2gco(cl->l.p)); - - for (int i = 0; i < cl->nupvalues; ++i) - validateref(g, obj2gco(cl), &cl->l.uprefs[i]); - } -} - -static void validatestack(global_State* g, lua_State* l) -{ - validateobjref(g, obj2gco(l), obj2gco(l->gt)); - - for (CallInfo* ci = l->base_ci; ci <= l->ci; ++ci) - { - LUAU_ASSERT(l->stack <= ci->base); - LUAU_ASSERT(ci->func <= ci->base && ci->base <= ci->top); - LUAU_ASSERT(ci->top <= l->stack_last); - } - - // note: stack refs can violate gc invariant so we only check for liveness - for (StkId o = l->stack; o < l->top; ++o) - checkliveness(g, o); - - if (l->namecall) - validateobjref(g, obj2gco(l), obj2gco(l->namecall)); - - for (UpVal* uv = l->openupval; uv; uv = uv->u.open.threadnext) - { - LUAU_ASSERT(uv->tt == LUA_TUPVAL); - LUAU_ASSERT(upisopen(uv)); - LUAU_ASSERT(uv->u.open.next->u.open.prev == uv && uv->u.open.prev->u.open.next == uv); - LUAU_ASSERT(!isblack(obj2gco(uv))); // open upvalues are never black - } -} - -static void validateproto(global_State* g, Proto* f) -{ - if (f->source) - validateobjref(g, obj2gco(f), obj2gco(f->source)); - - if (f->debugname) - validateobjref(g, obj2gco(f), obj2gco(f->debugname)); - - for (int i = 0; i < f->sizek; ++i) - validateref(g, obj2gco(f), &f->k[i]); - - for (int i = 0; i < f->sizeupvalues; ++i) - if (f->upvalues[i]) - validateobjref(g, obj2gco(f), obj2gco(f->upvalues[i])); - - for (int i = 0; i < f->sizep; ++i) - if (f->p[i]) - validateobjref(g, obj2gco(f), obj2gco(f->p[i])); - - for (int i = 0; i < f->sizelocvars; i++) - if (f->locvars[i].varname) - validateobjref(g, obj2gco(f), obj2gco(f->locvars[i].varname)); -} - -static void validateobj(global_State* g, GCObject* o) -{ - // dead objects can only occur during sweep - if (isdead(g, o)) - { - LUAU_ASSERT(g->gcstate == GCSsweep); - return; - } - - switch (o->gch.tt) - { - case LUA_TSTRING: - break; - - case LUA_TTABLE: - validatetable(g, gco2h(o)); - break; - - case LUA_TFUNCTION: - validateclosure(g, gco2cl(o)); - break; - - case LUA_TUSERDATA: - if (gco2u(o)->metatable) - validateobjref(g, o, obj2gco(gco2u(o)->metatable)); - break; - - case LUA_TTHREAD: - validatestack(g, gco2th(o)); - break; - - case LUA_TBUFFER: - break; - - case LUA_TPROTO: - validateproto(g, gco2p(o)); - break; - - case LUA_TUPVAL: - validateref(g, o, gco2uv(o)->v); - break; - - default: - LUAU_ASSERT(!"unexpected object type"); - } -} - -static void validategraylist(global_State* g, GCObject* o) -{ - if (!keepinvariant(g)) - return; - - while (o) - { - LUAU_ASSERT(isgray(o)); - - switch (o->gch.tt) - { - case LUA_TTABLE: - o = gco2h(o)->gclist; - break; - case LUA_TFUNCTION: - o = gco2cl(o)->gclist; - break; - case LUA_TTHREAD: - o = gco2th(o)->gclist; - break; - case LUA_TPROTO: - o = gco2p(o)->gclist; - break; - default: - LUAU_ASSERT(!"unknown object in gray list"); - return; - } - } -} - -static bool validategco(void* context, lua_Page* page, GCObject* gco) -{ - lua_State* L = (lua_State*)context; - global_State* g = L->global; - - validateobj(g, gco); - return false; -} - -void luaC_validate(lua_State* L) -{ - global_State* g = L->global; - - LUAU_ASSERT(!isdead(g, obj2gco(g->mainthread))); - checkliveness(g, &g->registry); - - for (int i = 0; i < LUA_T_COUNT; ++i) - if (g->mt[i]) - LUAU_ASSERT(!isdead(g, obj2gco(g->mt[i]))); - - validategraylist(g, g->weak); - validategraylist(g, g->gray); - validategraylist(g, g->grayagain); - - validategco(L, NULL, obj2gco(g->mainthread)); - - luaM_visitgco(L, L, validategco); - - for (UpVal* uv = g->uvhead.u.open.next; uv != &g->uvhead; uv = uv->u.open.next) - { - LUAU_ASSERT(uv->tt == LUA_TUPVAL); - LUAU_ASSERT(upisopen(uv)); - LUAU_ASSERT(uv->u.open.next->u.open.prev == uv && uv->u.open.prev->u.open.next == uv); - LUAU_ASSERT(!isblack(obj2gco(uv))); // open upvalues are never black - } -} - -inline bool safejson(char ch) -{ - return unsigned(ch) < 128 && ch >= 32 && ch != '\\' && ch != '\"'; -} - -static void dumpref(FILE* f, GCObject* o) -{ - fprintf(f, "\"%p\"", o); -} - -static void dumprefs(FILE* f, TValue* data, size_t size) -{ - bool first = true; - - for (size_t i = 0; i < size; ++i) - { - if (iscollectable(&data[i])) - { - if (!first) - fputc(',', f); - first = false; - - dumpref(f, gcvalue(&data[i])); - } - } -} - -static void dumpstringdata(FILE* f, const char* data, size_t len) -{ - for (size_t i = 0; i < len; ++i) - fputc(safejson(data[i]) ? data[i] : '?', f); -} - -static void dumpstring(FILE* f, TString* ts) -{ - fprintf(f, "{\"type\":\"string\",\"cat\":%d,\"size\":%d,\"data\":\"", ts->memcat, int(sizestring(ts->len))); - dumpstringdata(f, ts->data, ts->len); - fprintf(f, "\"}"); -} - -static void dumptable(FILE* f, Table* h) -{ - size_t size = sizeof(Table) + (h->node == &luaH_dummynode ? 0 : sizenode(h) * sizeof(LuaNode)) + h->sizearray * sizeof(TValue); - - fprintf(f, "{\"type\":\"table\",\"cat\":%d,\"size\":%d", h->memcat, int(size)); - - if (h->node != &luaH_dummynode) - { - fprintf(f, ",\"pairs\":["); - - bool first = true; - - for (int i = 0; i < sizenode(h); ++i) - { - const LuaNode& n = h->node[i]; - - if (!ttisnil(&n.val) && (iscollectable(&n.key) || iscollectable(&n.val))) - { - if (!first) - fputc(',', f); - first = false; - - if (iscollectable(&n.key)) - dumpref(f, gcvalue(&n.key)); - else - fprintf(f, "null"); - - fputc(',', f); - - if (iscollectable(&n.val)) - dumpref(f, gcvalue(&n.val)); - else - fprintf(f, "null"); - } - } - - fprintf(f, "]"); - } - if (h->sizearray) - { - fprintf(f, ",\"array\":["); - dumprefs(f, h->array, h->sizearray); - fprintf(f, "]"); - } - if (h->metatable) - { - fprintf(f, ",\"metatable\":"); - dumpref(f, obj2gco(h->metatable)); - } - fprintf(f, "}"); -} - -static void dumpclosure(FILE* f, Closure* cl) -{ - fprintf(f, "{\"type\":\"function\",\"cat\":%d,\"size\":%d", cl->memcat, - cl->isC ? int(sizeCclosure(cl->nupvalues)) : int(sizeLclosure(cl->nupvalues))); - - fprintf(f, ",\"env\":"); - dumpref(f, obj2gco(cl->env)); - - if (cl->isC) - { - if (cl->c.debugname) - fprintf(f, ",\"name\":\"%s\"", cl->c.debugname + 0); - - if (cl->nupvalues) - { - fprintf(f, ",\"upvalues\":["); - dumprefs(f, cl->c.upvals, cl->nupvalues); - fprintf(f, "]"); - } - } - else - { - if (cl->l.p->debugname) - fprintf(f, ",\"name\":\"%s\"", getstr(cl->l.p->debugname)); - - fprintf(f, ",\"proto\":"); - dumpref(f, obj2gco(cl->l.p)); - if (cl->nupvalues) - { - fprintf(f, ",\"upvalues\":["); - dumprefs(f, cl->l.uprefs, cl->nupvalues); - fprintf(f, "]"); - } - } - fprintf(f, "}"); -} - -static void dumpudata(FILE* f, Udata* u) -{ - fprintf(f, "{\"type\":\"userdata\",\"cat\":%d,\"size\":%d,\"tag\":%d", u->memcat, int(sizeudata(u->len)), u->tag); - - if (u->metatable) - { - fprintf(f, ",\"metatable\":"); - dumpref(f, obj2gco(u->metatable)); - } - fprintf(f, "}"); -} - -static void dumpthread(FILE* f, lua_State* th) -{ - size_t size = sizeof(lua_State) + sizeof(TValue) * th->stacksize + sizeof(CallInfo) * th->size_ci; - - fprintf(f, "{\"type\":\"thread\",\"cat\":%d,\"size\":%d", th->memcat, int(size)); - - fprintf(f, ",\"env\":"); - dumpref(f, obj2gco(th->gt)); - - Closure* tcl = 0; - for (CallInfo* ci = th->base_ci; ci <= th->ci; ++ci) - { - if (ttisfunction(ci->func)) - { - tcl = clvalue(ci->func); - break; - } - } - - if (tcl && !tcl->isC && tcl->l.p->source) - { - Proto* p = tcl->l.p; - - fprintf(f, ",\"source\":\""); - dumpstringdata(f, p->source->data, p->source->len); - fprintf(f, "\",\"line\":%d", p->linedefined); - } - - if (th->top > th->stack) - { - fprintf(f, ",\"stack\":["); - dumprefs(f, th->stack, th->top - th->stack); - fprintf(f, "]"); - - CallInfo* ci = th->base_ci; - bool first = true; - - fprintf(f, ",\"stacknames\":["); - for (StkId v = th->stack; v < th->top; ++v) - { - if (!iscollectable(v)) - continue; - - while (ci < th->ci && v >= (ci + 1)->func) - ci++; - - if (!first) - fputc(',', f); - first = false; - - if (v == ci->func) - { - Closure* cl = ci_func(ci); - - if (cl->isC) - { - fprintf(f, "\"frame:%s\"", cl->c.debugname ? cl->c.debugname : "[C]"); - } - else - { - Proto* p = cl->l.p; - fprintf(f, "\"frame:"); - if (p->source) - dumpstringdata(f, p->source->data, p->source->len); - fprintf(f, ":%d:%s\"", p->linedefined, p->debugname ? getstr(p->debugname) : ""); - } - } - else if (isLua(ci)) - { - Proto* p = ci_func(ci)->l.p; - int pc = pcRel(ci->savedpc, p); - const LocVar* var = luaF_findlocal(p, int(v - ci->base), pc); - - if (var && var->varname) - fprintf(f, "\"%s\"", getstr(var->varname)); - else - fprintf(f, "null"); - } - else - fprintf(f, "null"); - } - fprintf(f, "]"); - } - fprintf(f, "}"); -} - -static void dumpbuffer(FILE* f, Buffer* b) -{ - fprintf(f, "{\"type\":\"buffer\",\"cat\":%d,\"size\":%d}", b->memcat, int(sizebuffer(b->len))); -} - -static void dumpproto(FILE* f, Proto* p) -{ - size_t size = sizeof(Proto) + sizeof(Instruction) * p->sizecode + sizeof(Proto*) * p->sizep + sizeof(TValue) * p->sizek + p->sizelineinfo + - sizeof(LocVar) * p->sizelocvars + sizeof(TString*) * p->sizeupvalues; - - fprintf(f, "{\"type\":\"proto\",\"cat\":%d,\"size\":%d", p->memcat, int(size)); - - if (p->source) - { - fprintf(f, ",\"source\":\""); - dumpstringdata(f, p->source->data, p->source->len); - fprintf(f, "\",\"line\":%d", p->abslineinfo ? p->abslineinfo[0] : 0); - } - - if (p->sizek) - { - fprintf(f, ",\"constants\":["); - dumprefs(f, p->k, p->sizek); - fprintf(f, "]"); - } - - if (p->sizep) - { - fprintf(f, ",\"protos\":["); - for (int i = 0; i < p->sizep; ++i) - { - if (i != 0) - fputc(',', f); - dumpref(f, obj2gco(p->p[i])); - } - fprintf(f, "]"); - } - - fprintf(f, "}"); -} - -static void dumpupval(FILE* f, UpVal* uv) -{ - fprintf(f, "{\"type\":\"upvalue\",\"cat\":%d,\"size\":%d,\"open\":%s", uv->memcat, int(sizeof(UpVal)), upisopen(uv) ? "true" : "false"); - - if (iscollectable(uv->v)) - { - fprintf(f, ",\"object\":"); - dumpref(f, gcvalue(uv->v)); - } - - fprintf(f, "}"); -} - -static void dumpobj(FILE* f, GCObject* o) -{ - switch (o->gch.tt) - { - case LUA_TSTRING: - return dumpstring(f, gco2ts(o)); - - case LUA_TTABLE: - return dumptable(f, gco2h(o)); - - case LUA_TFUNCTION: - return dumpclosure(f, gco2cl(o)); - - case LUA_TUSERDATA: - return dumpudata(f, gco2u(o)); - - case LUA_TTHREAD: - return dumpthread(f, gco2th(o)); - - case LUA_TBUFFER: - return dumpbuffer(f, gco2buf(o)); - - case LUA_TPROTO: - return dumpproto(f, gco2p(o)); - - case LUA_TUPVAL: - return dumpupval(f, gco2uv(o)); - - default: - LUAU_ASSERT(0); - } -} - -static bool dumpgco(void* context, lua_Page* page, GCObject* gco) -{ - FILE* f = (FILE*)context; - - dumpref(f, gco); - fputc(':', f); - dumpobj(f, gco); - fputc(',', f); - fputc('\n', f); - - return false; -} - -void luaC_dump(lua_State* L, void* file, const char* (*categoryName)(lua_State* L, uint8_t memcat)) -{ - global_State* g = L->global; - FILE* f = static_cast(file); - - fprintf(f, "{\"objects\":{\n"); - - dumpgco(f, NULL, obj2gco(g->mainthread)); - - luaM_visitgco(L, f, dumpgco); - - fprintf(f, "\"0\":{\"type\":\"userdata\",\"cat\":0,\"size\":0}\n"); // to avoid issues with trailing , - fprintf(f, "},\"roots\":{\n"); - fprintf(f, "\"mainthread\":"); - dumpref(f, obj2gco(g->mainthread)); - fprintf(f, ",\"registry\":"); - dumpref(f, gcvalue(&g->registry)); - - fprintf(f, "},\"stats\":{\n"); - - fprintf(f, "\"size\":%d,\n", int(g->totalbytes)); - - fprintf(f, "\"categories\":{\n"); - for (int i = 0; i < LUA_MEMORY_CATEGORIES; i++) - { - if (size_t bytes = g->memcatbytes[i]) - { - if (categoryName) - fprintf(f, "\"%d\":{\"name\":\"%s\", \"size\":%d},\n", i, categoryName(L, i), int(bytes)); - else - fprintf(f, "\"%d\":{\"size\":%d},\n", i, int(bytes)); - } - } - fprintf(f, "\"none\":{}\n"); // to avoid issues with trailing , - fprintf(f, "}\n"); - fprintf(f, "}}\n"); -} - -struct EnumContext -{ - lua_State* L; - void* context; - void (*node)(void* context, void* ptr, uint8_t tt, uint8_t memcat, size_t size, const char* name); - void (*edge)(void* context, void* from, void* to, const char* name); -}; - -static void* enumtopointer(GCObject* gco) -{ - // To match lua_topointer, userdata pointer is represented as a pointer to internal data - return gco->gch.tt == LUA_TUSERDATA ? (void*)gco2u(gco)->data : (void*)gco; -} - -static void enumnode(EnumContext* ctx, GCObject* gco, size_t size, const char* objname) -{ - ctx->node(ctx->context, enumtopointer(gco), gco->gch.tt, gco->gch.memcat, size, objname); -} - -static void enumedge(EnumContext* ctx, GCObject* from, GCObject* to, const char* edgename) -{ - ctx->edge(ctx->context, enumtopointer(from), enumtopointer(to), edgename); -} - -static void enumedges(EnumContext* ctx, GCObject* from, TValue* data, size_t size, const char* edgename) -{ - for (size_t i = 0; i < size; ++i) - { - if (iscollectable(&data[i])) - enumedge(ctx, from, gcvalue(&data[i]), edgename); - } -} - -static void enumstring(EnumContext* ctx, TString* ts) -{ - enumnode(ctx, obj2gco(ts), ts->len, NULL); -} - -static void enumtable(EnumContext* ctx, Table* h) -{ - size_t size = sizeof(Table) + (h->node == &luaH_dummynode ? 0 : sizenode(h) * sizeof(LuaNode)) + h->sizearray * sizeof(TValue); - - // Provide a name for a special registry table - enumnode(ctx, obj2gco(h), size, h == hvalue(registry(ctx->L)) ? "registry" : NULL); - - if (h->node != &luaH_dummynode) - { - bool weakkey = false; - bool weakvalue = false; - - if (const TValue* mode = gfasttm(ctx->L->global, h->metatable, TM_MODE)) - { - if (ttisstring(mode)) - { - weakkey = strchr(svalue(mode), 'k') != NULL; - weakvalue = strchr(svalue(mode), 'v') != NULL; - } - } - - for (int i = 0; i < sizenode(h); ++i) - { - const LuaNode& n = h->node[i]; - - if (!ttisnil(&n.val) && (iscollectable(&n.key) || iscollectable(&n.val))) - { - if (!weakkey && iscollectable(&n.key)) - enumedge(ctx, obj2gco(h), gcvalue(&n.key), "[key]"); - - if (!weakvalue && iscollectable(&n.val)) - { - if (ttisstring(&n.key)) - { - enumedge(ctx, obj2gco(h), gcvalue(&n.val), svalue(&n.key)); - } - else if (ttisnumber(&n.key)) - { - char buf[32]; - snprintf(buf, sizeof(buf), "%.14g", nvalue(&n.key)); - enumedge(ctx, obj2gco(h), gcvalue(&n.val), buf); - } - else - { - char buf[32]; - snprintf(buf, sizeof(buf), "[%s]", getstr(ctx->L->global->ttname[n.key.tt])); - enumedge(ctx, obj2gco(h), gcvalue(&n.val), buf); - } - } - } - } - } - - if (h->sizearray) - enumedges(ctx, obj2gco(h), h->array, h->sizearray, "array"); - - if (h->metatable) - enumedge(ctx, obj2gco(h), obj2gco(h->metatable), "metatable"); -} - -static void enumclosure(EnumContext* ctx, Closure* cl) -{ - if (cl->isC) - { - enumnode(ctx, obj2gco(cl), sizeCclosure(cl->nupvalues), cl->c.debugname); - } - else - { - Proto* p = cl->l.p; - - char buf[LUA_IDSIZE]; - - if (p->source) - snprintf(buf, sizeof(buf), "%s:%d %s", p->debugname ? getstr(p->debugname) : "", p->linedefined, getstr(p->source)); - else - snprintf(buf, sizeof(buf), "%s:%d", p->debugname ? getstr(p->debugname) : "", p->linedefined); - - enumnode(ctx, obj2gco(cl), sizeLclosure(cl->nupvalues), buf); - } - - enumedge(ctx, obj2gco(cl), obj2gco(cl->env), "env"); - - if (cl->isC) - { - if (cl->nupvalues) - enumedges(ctx, obj2gco(cl), cl->c.upvals, cl->nupvalues, "upvalue"); - } - else - { - enumedge(ctx, obj2gco(cl), obj2gco(cl->l.p), "proto"); - - if (cl->nupvalues) - enumedges(ctx, obj2gco(cl), cl->l.uprefs, cl->nupvalues, "upvalue"); - } -} - -static void enumudata(EnumContext* ctx, Udata* u) -{ - const char* name = NULL; - - if (Table* h = u->metatable) - { - if (h->node != &luaH_dummynode) - { - for (int i = 0; i < sizenode(h); ++i) - { - const LuaNode& n = h->node[i]; - - if (ttisstring(&n.key) && ttisstring(&n.val) && strcmp(svalue(&n.key), "__type") == 0) - { - name = svalue(&n.val); - break; - } - } - } - } - - enumnode(ctx, obj2gco(u), sizeudata(u->len), name); - - if (u->metatable) - enumedge(ctx, obj2gco(u), obj2gco(u->metatable), "metatable"); -} - -static void enumthread(EnumContext* ctx, lua_State* th) -{ - size_t size = sizeof(lua_State) + sizeof(TValue) * th->stacksize + sizeof(CallInfo) * th->size_ci; - - Closure* tcl = NULL; - for (CallInfo* ci = th->base_ci; ci <= th->ci; ++ci) - { - if (ttisfunction(ci->func)) - { - tcl = clvalue(ci->func); - break; - } - } - - if (tcl && !tcl->isC && tcl->l.p->source) - { - Proto* p = tcl->l.p; - - char buf[LUA_IDSIZE]; - - if (p->source) - snprintf(buf, sizeof(buf), "%s:%d %s", p->debugname ? getstr(p->debugname) : "", p->linedefined, getstr(p->source)); - else - snprintf(buf, sizeof(buf), "%s:%d", p->debugname ? getstr(p->debugname) : "", p->linedefined); - - enumnode(ctx, obj2gco(th), size, buf); - } - else - { - enumnode(ctx, obj2gco(th), size, NULL); - } - - enumedge(ctx, obj2gco(th), obj2gco(th->gt), "globals"); - - if (th->top > th->stack) - enumedges(ctx, obj2gco(th), th->stack, th->top - th->stack, "stack"); -} - -static void enumbuffer(EnumContext* ctx, Buffer* b) -{ - enumnode(ctx, obj2gco(b), sizebuffer(b->len), NULL); -} - -static void enumproto(EnumContext* ctx, Proto* p) -{ - size_t size = sizeof(Proto) + sizeof(Instruction) * p->sizecode + sizeof(Proto*) * p->sizep + sizeof(TValue) * p->sizek + p->sizelineinfo + - sizeof(LocVar) * p->sizelocvars + sizeof(TString*) * p->sizeupvalues; - - enumnode(ctx, obj2gco(p), size, p->source ? getstr(p->source) : NULL); - - if (p->sizek) - enumedges(ctx, obj2gco(p), p->k, p->sizek, "constants"); - - for (int i = 0; i < p->sizep; ++i) - enumedge(ctx, obj2gco(p), obj2gco(p->p[i]), "protos"); -} - -static void enumupval(EnumContext* ctx, UpVal* uv) -{ - enumnode(ctx, obj2gco(uv), sizeof(UpVal), NULL); - - if (iscollectable(uv->v)) - enumedge(ctx, obj2gco(uv), gcvalue(uv->v), "value"); -} - -static void enumobj(EnumContext* ctx, GCObject* o) -{ - switch (o->gch.tt) - { - case LUA_TSTRING: - return enumstring(ctx, gco2ts(o)); - - case LUA_TTABLE: - return enumtable(ctx, gco2h(o)); - - case LUA_TFUNCTION: - return enumclosure(ctx, gco2cl(o)); - - case LUA_TUSERDATA: - return enumudata(ctx, gco2u(o)); - - case LUA_TTHREAD: - return enumthread(ctx, gco2th(o)); - - case LUA_TBUFFER: - return enumbuffer(ctx, gco2buf(o)); - - case LUA_TPROTO: - return enumproto(ctx, gco2p(o)); - - case LUA_TUPVAL: - return enumupval(ctx, gco2uv(o)); - - default: - LUAU_ASSERT(!"Unknown object tag"); - } -} - -static bool enumgco(void* context, lua_Page* page, GCObject* gco) -{ - enumobj((EnumContext*)context, gco); - return false; -} - -void luaC_enumheap(lua_State* L, void* context, void (*node)(void* context, void* ptr, uint8_t tt, uint8_t memcat, size_t size, const char* name), - void (*edge)(void* context, void* from, void* to, const char* name)) -{ - global_State* g = L->global; - - EnumContext ctx; - ctx.L = L; - ctx.context = context; - ctx.node = node; - ctx.edge = edge; - - enumgco(&ctx, NULL, obj2gco(g->mainthread)); - - luaM_visitgco(L, &ctx, enumgco); -} diff --git a/lib/luau/VM/src/linit.cpp b/lib/luau/VM/src/linit.cpp deleted file mode 100644 index b749195..0000000 --- a/lib/luau/VM/src/linit.cpp +++ /dev/null @@ -1,88 +0,0 @@ -// This file is part of the Luau programming language and is licensed under MIT License; see LICENSE.txt for details -// This code is based on Lua 5.x implementation licensed under MIT License; see lua_LICENSE.txt for details -#include "lualib.h" - -#include - -static const luaL_Reg lualibs[] = { - {"", luaopen_base}, - {LUA_COLIBNAME, luaopen_coroutine}, - {LUA_TABLIBNAME, luaopen_table}, - {LUA_OSLIBNAME, luaopen_os}, - {LUA_STRLIBNAME, luaopen_string}, - {LUA_MATHLIBNAME, luaopen_math}, - {LUA_DBLIBNAME, luaopen_debug}, - {LUA_UTF8LIBNAME, luaopen_utf8}, - {LUA_BITLIBNAME, luaopen_bit32}, - {LUA_BUFFERLIBNAME, luaopen_buffer}, - {NULL, NULL}, -}; - -void luaL_openlibs(lua_State* L) -{ - const luaL_Reg* lib = lualibs; - for (; lib->func; lib++) - { - lua_pushcfunction(L, lib->func, NULL); - lua_pushstring(L, lib->name); - lua_call(L, 1, 0); - } -} - -void luaL_sandbox(lua_State* L) -{ - // set all libraries to read-only - lua_pushnil(L); - while (lua_next(L, LUA_GLOBALSINDEX) != 0) - { - if (lua_istable(L, -1)) - lua_setreadonly(L, -1, true); - - lua_pop(L, 1); - } - - // set all builtin metatables to read-only - lua_pushliteral(L, ""); - lua_getmetatable(L, -1); - lua_setreadonly(L, -1, true); - lua_pop(L, 2); - - // set globals to readonly and activate safeenv since the env is immutable - lua_setreadonly(L, LUA_GLOBALSINDEX, true); - lua_setsafeenv(L, LUA_GLOBALSINDEX, true); -} - -void luaL_sandboxthread(lua_State* L) -{ - // create new global table that proxies reads to original table - lua_newtable(L); - - lua_newtable(L); - lua_pushvalue(L, LUA_GLOBALSINDEX); - lua_setfield(L, -2, "__index"); - lua_setreadonly(L, -1, true); - - lua_setmetatable(L, -2); - - // we can set safeenv now although it's important to set it to false if code is loaded twice into the thread - lua_replace(L, LUA_GLOBALSINDEX); - lua_setsafeenv(L, LUA_GLOBALSINDEX, true); -} - -static void* l_alloc(void* ud, void* ptr, size_t osize, size_t nsize) -{ - (void)ud; - (void)osize; - if (nsize == 0) - { - free(ptr); - return NULL; - } - else - return realloc(ptr, nsize); -} - -lua_State* luaL_newstate(void) -{ - return lua_newstate(l_alloc, NULL); -} diff --git a/lib/luau/VM/src/lmathlib.cpp b/lib/luau/VM/src/lmathlib.cpp deleted file mode 100644 index 5a817f2..0000000 --- a/lib/luau/VM/src/lmathlib.cpp +++ /dev/null @@ -1,441 +0,0 @@ -// This file is part of the Luau programming language and is licensed under MIT License; see LICENSE.txt for details -// This code is based on Lua 5.x implementation licensed under MIT License; see lua_LICENSE.txt for details -#include "lualib.h" - -#include "lstate.h" - -#include -#include - -#undef PI -#define PI (3.14159265358979323846) -#define RADIANS_PER_DEGREE (PI / 180.0) - -#define PCG32_INC 105 - -static uint32_t pcg32_random(uint64_t* state) -{ - uint64_t oldstate = *state; - *state = oldstate * 6364136223846793005ULL + (PCG32_INC | 1); - uint32_t xorshifted = uint32_t(((oldstate >> 18u) ^ oldstate) >> 27u); - uint32_t rot = uint32_t(oldstate >> 59u); - return (xorshifted >> rot) | (xorshifted << ((-int32_t(rot)) & 31)); -} - -static void pcg32_seed(uint64_t* state, uint64_t seed) -{ - *state = 0; - pcg32_random(state); - *state += seed; - pcg32_random(state); -} - -static int math_abs(lua_State* L) -{ - lua_pushnumber(L, fabs(luaL_checknumber(L, 1))); - return 1; -} - -static int math_sin(lua_State* L) -{ - lua_pushnumber(L, sin(luaL_checknumber(L, 1))); - return 1; -} - -static int math_sinh(lua_State* L) -{ - lua_pushnumber(L, sinh(luaL_checknumber(L, 1))); - return 1; -} - -static int math_cos(lua_State* L) -{ - lua_pushnumber(L, cos(luaL_checknumber(L, 1))); - return 1; -} - -static int math_cosh(lua_State* L) -{ - lua_pushnumber(L, cosh(luaL_checknumber(L, 1))); - return 1; -} - -static int math_tan(lua_State* L) -{ - lua_pushnumber(L, tan(luaL_checknumber(L, 1))); - return 1; -} - -static int math_tanh(lua_State* L) -{ - lua_pushnumber(L, tanh(luaL_checknumber(L, 1))); - return 1; -} - -static int math_asin(lua_State* L) -{ - lua_pushnumber(L, asin(luaL_checknumber(L, 1))); - return 1; -} - -static int math_acos(lua_State* L) -{ - lua_pushnumber(L, acos(luaL_checknumber(L, 1))); - return 1; -} - -static int math_atan(lua_State* L) -{ - lua_pushnumber(L, atan(luaL_checknumber(L, 1))); - return 1; -} - -static int math_atan2(lua_State* L) -{ - lua_pushnumber(L, atan2(luaL_checknumber(L, 1), luaL_checknumber(L, 2))); - return 1; -} - -static int math_ceil(lua_State* L) -{ - lua_pushnumber(L, ceil(luaL_checknumber(L, 1))); - return 1; -} - -static int math_floor(lua_State* L) -{ - lua_pushnumber(L, floor(luaL_checknumber(L, 1))); - return 1; -} - -static int math_fmod(lua_State* L) -{ - lua_pushnumber(L, fmod(luaL_checknumber(L, 1), luaL_checknumber(L, 2))); - return 1; -} - -static int math_modf(lua_State* L) -{ - double ip; - double fp = modf(luaL_checknumber(L, 1), &ip); - lua_pushnumber(L, ip); - lua_pushnumber(L, fp); - return 2; -} - -static int math_sqrt(lua_State* L) -{ - lua_pushnumber(L, sqrt(luaL_checknumber(L, 1))); - return 1; -} - -static int math_pow(lua_State* L) -{ - lua_pushnumber(L, pow(luaL_checknumber(L, 1), luaL_checknumber(L, 2))); - return 1; -} - -static int math_log(lua_State* L) -{ - double x = luaL_checknumber(L, 1); - double res; - if (lua_isnoneornil(L, 2)) - res = log(x); - else - { - double base = luaL_checknumber(L, 2); - if (base == 2.0) - res = log2(x); - else if (base == 10.0) - res = log10(x); - else - res = log(x) / log(base); - } - lua_pushnumber(L, res); - return 1; -} - -static int math_log10(lua_State* L) -{ - lua_pushnumber(L, log10(luaL_checknumber(L, 1))); - return 1; -} - -static int math_exp(lua_State* L) -{ - lua_pushnumber(L, exp(luaL_checknumber(L, 1))); - return 1; -} - -static int math_deg(lua_State* L) -{ - lua_pushnumber(L, luaL_checknumber(L, 1) / RADIANS_PER_DEGREE); - return 1; -} - -static int math_rad(lua_State* L) -{ - lua_pushnumber(L, luaL_checknumber(L, 1) * RADIANS_PER_DEGREE); - return 1; -} - -static int math_frexp(lua_State* L) -{ - int e; - lua_pushnumber(L, frexp(luaL_checknumber(L, 1), &e)); - lua_pushinteger(L, e); - return 2; -} - -static int math_ldexp(lua_State* L) -{ - lua_pushnumber(L, ldexp(luaL_checknumber(L, 1), luaL_checkinteger(L, 2))); - return 1; -} - -static int math_min(lua_State* L) -{ - int n = lua_gettop(L); // number of arguments - double dmin = luaL_checknumber(L, 1); - int i; - for (i = 2; i <= n; i++) - { - double d = luaL_checknumber(L, i); - if (d < dmin) - dmin = d; - } - lua_pushnumber(L, dmin); - return 1; -} - -static int math_max(lua_State* L) -{ - int n = lua_gettop(L); // number of arguments - double dmax = luaL_checknumber(L, 1); - int i; - for (i = 2; i <= n; i++) - { - double d = luaL_checknumber(L, i); - if (d > dmax) - dmax = d; - } - lua_pushnumber(L, dmax); - return 1; -} - -static int math_random(lua_State* L) -{ - global_State* g = L->global; - switch (lua_gettop(L)) - { // check number of arguments - case 0: - { // no arguments - // Using ldexp instead of division for speed & clarity. - // See http://mumble.net/~campbell/tmp/random_real.c for details on generating doubles from integer ranges. - uint32_t rl = pcg32_random(&g->rngstate); - uint32_t rh = pcg32_random(&g->rngstate); - double rd = ldexp(double(rl | (uint64_t(rh) << 32)), -64); - lua_pushnumber(L, rd); // number between 0 and 1 - break; - } - case 1: - { // only upper limit - int u = luaL_checkinteger(L, 1); - luaL_argcheck(L, 1 <= u, 1, "interval is empty"); - - uint64_t x = uint64_t(u) * pcg32_random(&g->rngstate); - int r = int(1 + (x >> 32)); - lua_pushinteger(L, r); // int between 1 and `u' - break; - } - case 2: - { // lower and upper limits - int l = luaL_checkinteger(L, 1); - int u = luaL_checkinteger(L, 2); - luaL_argcheck(L, l <= u, 2, "interval is empty"); - - uint32_t ul = uint32_t(u) - uint32_t(l); - luaL_argcheck(L, ul < UINT_MAX, 2, "interval is too large"); // -INT_MIN..INT_MAX interval can result in integer overflow - uint64_t x = uint64_t(ul + 1) * pcg32_random(&g->rngstate); - int r = int(l + (x >> 32)); - lua_pushinteger(L, r); // int between `l' and `u' - break; - } - default: - luaL_error(L, "wrong number of arguments"); - } - return 1; -} - -static int math_randomseed(lua_State* L) -{ - int seed = luaL_checkinteger(L, 1); - - pcg32_seed(&L->global->rngstate, seed); - return 0; -} - -static const unsigned char kPerlinHash[257] = {151, 160, 137, 91, 90, 15, 131, 13, 201, 95, 96, 53, 194, 233, 7, 225, 140, 36, 103, 30, 69, 142, 8, - 99, 37, 240, 21, 10, 23, 190, 6, 148, 247, 120, 234, 75, 0, 26, 197, 62, 94, 252, 219, 203, 117, 35, 11, 32, 57, 177, 33, 88, 237, 149, 56, 87, - 174, 20, 125, 136, 171, 168, 68, 175, 74, 165, 71, 134, 139, 48, 27, 166, 77, 146, 158, 231, 83, 111, 229, 122, 60, 211, 133, 230, 220, 105, 92, - 41, 55, 46, 245, 40, 244, 102, 143, 54, 65, 25, 63, 161, 1, 216, 80, 73, 209, 76, 132, 187, 208, 89, 18, 169, 200, 196, 135, 130, 116, 188, 159, - 86, 164, 100, 109, 198, 173, 186, 3, 64, 52, 217, 226, 250, 124, 123, 5, 202, 38, 147, 118, 126, 255, 82, 85, 212, 207, 206, 59, 227, 47, 16, 58, - 17, 182, 189, 28, 42, 223, 183, 170, 213, 119, 248, 152, 2, 44, 154, 163, 70, 221, 153, 101, 155, 167, 43, 172, 9, 129, 22, 39, 253, 19, 98, 108, - 110, 79, 113, 224, 232, 178, 185, 112, 104, 218, 246, 97, 228, 251, 34, 242, 193, 238, 210, 144, 12, 191, 179, 162, 241, 81, 51, 145, 235, 249, - 14, 239, 107, 49, 192, 214, 31, 181, 199, 106, 157, 184, 84, 204, 176, 115, 121, 50, 45, 127, 4, 150, 254, 138, 236, 205, 93, 222, 114, 67, 29, - 24, 72, 243, 141, 128, 195, 78, 66, 215, 61, 156, 180, 151}; - -const float kPerlinGrad[16][3] = {{1, 1, 0}, {-1, 1, 0}, {1, -1, 0}, {-1, -1, 0}, {1, 0, 1}, {-1, 0, 1}, {1, 0, -1}, {-1, 0, -1}, {0, 1, 1}, - {0, -1, 1}, {0, 1, -1}, {0, -1, -1}, {1, 1, 0}, {0, -1, 1}, {-1, 1, 0}, {0, -1, -1}}; - -inline float perlin_fade(float t) -{ - return t * t * t * (t * (t * 6 - 15) + 10); -} - -inline float perlin_lerp(float t, float a, float b) -{ - return a + t * (b - a); -} - -inline float perlin_grad(int hash, float x, float y, float z) -{ - const float* g = kPerlinGrad[hash & 15]; - return g[0] * x + g[1] * y + g[2] * z; -} - -static float perlin(float x, float y, float z) -{ - float xflr = floorf(x); - float yflr = floorf(y); - float zflr = floorf(z); - - int xi = int(xflr) & 255; - int yi = int(yflr) & 255; - int zi = int(zflr) & 255; - - float xf = x - xflr; - float yf = y - yflr; - float zf = z - zflr; - - float u = perlin_fade(xf); - float v = perlin_fade(yf); - float w = perlin_fade(zf); - - const unsigned char* p = kPerlinHash; - - int a = (p[xi] + yi) & 255; - int aa = (p[a] + zi) & 255; - int ab = (p[a + 1] + zi) & 255; - - int b = (p[xi + 1] + yi) & 255; - int ba = (p[b] + zi) & 255; - int bb = (p[b + 1] + zi) & 255; - - float la = perlin_lerp(u, perlin_grad(p[aa], xf, yf, zf), perlin_grad(p[ba], xf - 1, yf, zf)); - float lb = perlin_lerp(u, perlin_grad(p[ab], xf, yf - 1, zf), perlin_grad(p[bb], xf - 1, yf - 1, zf)); - float la1 = perlin_lerp(u, perlin_grad(p[aa + 1], xf, yf, zf - 1), perlin_grad(p[ba + 1], xf - 1, yf, zf - 1)); - float lb1 = perlin_lerp(u, perlin_grad(p[ab + 1], xf, yf - 1, zf - 1), perlin_grad(p[bb + 1], xf - 1, yf - 1, zf - 1)); - - return perlin_lerp(w, perlin_lerp(v, la, lb), perlin_lerp(v, la1, lb1)); -} - -static int math_noise(lua_State* L) -{ - int nx, ny, nz; - double x = lua_tonumberx(L, 1, &nx); - double y = lua_tonumberx(L, 2, &ny); - double z = lua_tonumberx(L, 3, &nz); - - luaL_argexpected(L, nx, 1, "number"); - luaL_argexpected(L, ny || lua_isnoneornil(L, 2), 2, "number"); - luaL_argexpected(L, nz || lua_isnoneornil(L, 3), 3, "number"); - - double r = perlin((float)x, (float)y, (float)z); - - lua_pushnumber(L, r); - return 1; -} - -static int math_clamp(lua_State* L) -{ - double v = luaL_checknumber(L, 1); - double min = luaL_checknumber(L, 2); - double max = luaL_checknumber(L, 3); - - luaL_argcheck(L, min <= max, 3, "max must be greater than or equal to min"); - - double r = v < min ? min : v; - r = r > max ? max : r; - - lua_pushnumber(L, r); - return 1; -} - -static int math_sign(lua_State* L) -{ - double v = luaL_checknumber(L, 1); - lua_pushnumber(L, v > 0.0 ? 1.0 : v < 0.0 ? -1.0 : 0.0); - return 1; -} - -static int math_round(lua_State* L) -{ - lua_pushnumber(L, round(luaL_checknumber(L, 1))); - return 1; -} - -static const luaL_Reg mathlib[] = { - {"abs", math_abs}, - {"acos", math_acos}, - {"asin", math_asin}, - {"atan2", math_atan2}, - {"atan", math_atan}, - {"ceil", math_ceil}, - {"cosh", math_cosh}, - {"cos", math_cos}, - {"deg", math_deg}, - {"exp", math_exp}, - {"floor", math_floor}, - {"fmod", math_fmod}, - {"frexp", math_frexp}, - {"ldexp", math_ldexp}, - {"log10", math_log10}, - {"log", math_log}, - {"max", math_max}, - {"min", math_min}, - {"modf", math_modf}, - {"pow", math_pow}, - {"rad", math_rad}, - {"random", math_random}, - {"randomseed", math_randomseed}, - {"sinh", math_sinh}, - {"sin", math_sin}, - {"sqrt", math_sqrt}, - {"tanh", math_tanh}, - {"tan", math_tan}, - {"noise", math_noise}, - {"clamp", math_clamp}, - {"sign", math_sign}, - {"round", math_round}, - {NULL, NULL}, -}; - -/* -** Open math library -*/ -int luaopen_math(lua_State* L) -{ - uint64_t seed = uintptr_t(L); - seed ^= time(NULL); - seed ^= clock(); - - pcg32_seed(&L->global->rngstate, seed); - - luaL_register(L, LUA_MATHLIBNAME, mathlib); - lua_pushnumber(L, PI); - lua_setfield(L, -2, "pi"); - lua_pushnumber(L, HUGE_VAL); - lua_setfield(L, -2, "huge"); - return 1; -} diff --git a/lib/luau/VM/src/lmem.cpp b/lib/luau/VM/src/lmem.cpp deleted file mode 100644 index 8b264ef..0000000 --- a/lib/luau/VM/src/lmem.cpp +++ /dev/null @@ -1,649 +0,0 @@ -// This file is part of the Luau programming language and is licensed under MIT License; see LICENSE.txt for details -// This code is based on Lua 5.x implementation licensed under MIT License; see lua_LICENSE.txt for details -#include "lmem.h" - -#include "lstate.h" -#include "ldo.h" -#include "ldebug.h" - -#include - -/* - * Luau heap uses a size-segregated page structure, with individual pages and large allocations - * allocated using system heap (via frealloc callback). - * - * frealloc callback serves as a general, if slow, allocation callback that can allocate, free or - * resize allocations: - * - * void* frealloc(void* ud, void* ptr, size_t oldsize, size_t newsize); - * - * frealloc(ud, NULL, 0, x) creates a new block of size x - * frealloc(ud, p, x, 0) frees the block p (must return NULL) - * frealloc(ud, NULL, 0, 0) does nothing, equivalent to free(NULL) - * - * frealloc returns NULL if it cannot create or reallocate the area - * (any reallocation to an equal or smaller size cannot fail!) - * - * On top of this, Luau implements heap storage which is split into two types of allocations: - * - * - GCO, short for "garbage collected objects" - * - other objects (for example, arrays stored inside table objects) - * - * The heap layout for these two allocation types is a bit different. - * - * All GCO are allocated in pages, which is a block of memory of ~16K in size that has a page header - * (lua_Page). Each page contains 1..N blocks of the same size, where N is selected to fill the page - * completely. This amortizes the allocation cost and increases locality. Each GCO block starts with - * the GC header (GCheader) which contains the object type, mark bits and other GC metadata. If the - * GCO block is free (not used), then it must have the type set to TNIL; in this case the block can - * be part of the per-page free list, the link for that list is stored after the header (freegcolink). - * - * Importantly, the GCO block doesn't have any back references to the page it's allocated in, so it's - * impossible to free it in isolation - GCO blocks are freed by sweeping the pages they belong to, - * using luaM_freegco which must specify the page; this is called by page sweeper that traverses the - * entire page's worth of objects. For this reason it's also important that freed GCO blocks keep the - * GC header intact and accessible (with type = NIL) so that the sweeper can access it. - * - * Some GCOs are too large to fit in a 16K page without excessive fragmentation (the size threshold is - * currently 512 bytes); in this case, we allocate a dedicated small page with just a single block's worth - * storage space, but that requires allocating an extra page header. In effect large GCOs are a little bit - * less memory efficient, but this allows us to uniformly sweep small and large GCOs using page lists. - * - * All GCO pages are linked in a large intrusive linked list (global_State::allgcopages). Additionally, - * for each block size there's a page free list that contains pages that have at least one free block - * (global_State::freegcopages). This free list is used to make sure object allocation is O(1). - * - * Compared to GCOs, regular allocations have two important differences: they can be freed in isolation, - * and they don't start with a GC header. Because of this, each allocation is prefixed with block metadata, - * which contains the pointer to the page for allocated blocks, and the pointer to the next free block - * inside the page for freed blocks. - * For regular allocations that are too large to fit in a page (using the same threshold of 512 bytes), - * we don't allocate a separate page, instead simply using frealloc to allocate a vanilla block of memory. - * - * Just like GCO pages, we store a page free list (global_State::freepages) that allows O(1) allocation; - * there is no global list for non-GCO pages since we never need to traverse them directly. - * - * In both cases, we pick the page by computing the size class from the block size which rounds the block - * size up to reduce the chance that we'll allocate pages that have very few allocated blocks. The size - * class strategy is determined by SizeClassConfig constructor. - * - * Note that when the last block in a page is freed, we immediately free the page with frealloc - the - * memory manager doesn't currently attempt to keep unused memory around. This can result in excessive - * allocation traffic and can be mitigated by adding a page cache in the future. - * - * For both GCO and non-GCO pages, the per-page block allocation combines bump pointer style allocation - * (lua_Page::freeNext) and per-page free list (lua_Page::freeList). We use the bump allocator to allocate - * the contents of the page, and the free list for further reuse; this allows shorter page setup times - * which results in less variance between allocation cost, as well as tighter sweep bounds for newly - * allocated pages. - */ - -#ifndef __has_feature -#define __has_feature(x) 0 -#endif - -#if __has_feature(address_sanitizer) || defined(LUAU_ENABLE_ASAN) -#include -#define ASAN_POISON_MEMORY_REGION(addr, size) __asan_poison_memory_region((addr), (size)) -#define ASAN_UNPOISON_MEMORY_REGION(addr, size) __asan_unpoison_memory_region((addr), (size)) -#else -#define ASAN_POISON_MEMORY_REGION(addr, size) (void)0 -#define ASAN_UNPOISON_MEMORY_REGION(addr, size) (void)0 -#endif - -/* - * The sizes of Luau objects aren't crucial for code correctness, but they are crucial for memory efficiency - * To prevent some of them accidentally growing and us losing memory without realizing it, we're going to lock - * the sizes of all critical structures down. - */ -#if defined(__APPLE__) -#define ABISWITCH(x64, ms32, gcc32) (sizeof(void*) == 8 ? x64 : gcc32) -#elif defined(__i386__) && defined(__MINGW32__) && !defined(__MINGW64__) -#define ABISWITCH(x64, ms32, gcc32) (ms32) -#elif defined(__i386__) && !defined(_MSC_VER) -#define ABISWITCH(x64, ms32, gcc32) (gcc32) -#else -// Android somehow uses a similar ABI to MSVC, *not* to iOS... -#define ABISWITCH(x64, ms32, gcc32) (sizeof(void*) == 8 ? x64 : ms32) -#endif - -#if LUA_VECTOR_SIZE == 4 -static_assert(sizeof(TValue) == ABISWITCH(24, 24, 24), "size mismatch for value"); -static_assert(sizeof(LuaNode) == ABISWITCH(48, 48, 48), "size mismatch for table entry"); -#else -static_assert(sizeof(TValue) == ABISWITCH(16, 16, 16), "size mismatch for value"); -static_assert(sizeof(LuaNode) == ABISWITCH(32, 32, 32), "size mismatch for table entry"); -#endif - -static_assert(offsetof(TString, data) == ABISWITCH(24, 20, 20), "size mismatch for string header"); -static_assert(offsetof(Udata, data) == ABISWITCH(16, 16, 12), "size mismatch for userdata header"); -static_assert(sizeof(Table) == ABISWITCH(48, 32, 32), "size mismatch for table header"); -static_assert(offsetof(Buffer, data) == ABISWITCH(8, 8, 8), "size mismatch for buffer header"); - -const size_t kSizeClasses = LUA_SIZECLASSES; -const size_t kMaxSmallSize = 512; -const size_t kPageSize = 16 * 1024 - 24; // slightly under 16KB since that results in less fragmentation due to heap metadata - -const size_t kBlockHeader = sizeof(double) > sizeof(void*) ? sizeof(double) : sizeof(void*); // suitable for aligning double & void* on all platforms -const size_t kGCOLinkOffset = (sizeof(GCheader) + sizeof(void*) - 1) & ~(sizeof(void*) - 1); // GCO pages contain freelist links after the GC header - -struct SizeClassConfig -{ - int sizeOfClass[kSizeClasses]; - int8_t classForSize[kMaxSmallSize + 1]; - int classCount = 0; - - SizeClassConfig() - { - memset(sizeOfClass, 0, sizeof(sizeOfClass)); - memset(classForSize, -1, sizeof(classForSize)); - - // we use a progressive size class scheme: - // - all size classes are aligned by 8b to satisfy pointer alignment requirements - // - we first allocate sizes classes in multiples of 8 - // - after the first cutoff we allocate size classes in multiples of 16 - // - after the second cutoff we allocate size classes in multiples of 32 - // this balances internal fragmentation vs external fragmentation - for (int size = 8; size < 64; size += 8) - sizeOfClass[classCount++] = size; - - for (int size = 64; size < 256; size += 16) - sizeOfClass[classCount++] = size; - - for (int size = 256; size <= 512; size += 32) - sizeOfClass[classCount++] = size; - - LUAU_ASSERT(size_t(classCount) <= kSizeClasses); - - // fill the lookup table for all classes - for (int klass = 0; klass < classCount; ++klass) - classForSize[sizeOfClass[klass]] = int8_t(klass); - - // fill the gaps in lookup table - for (int size = kMaxSmallSize - 1; size >= 0; --size) - if (classForSize[size] < 0) - classForSize[size] = classForSize[size + 1]; - } -}; - -const SizeClassConfig kSizeClassConfig; - -// size class for a block of size sz; returns -1 for size=0 because empty allocations take no space -#define sizeclass(sz) (size_t((sz)-1) < kMaxSmallSize ? kSizeClassConfig.classForSize[sz] : -1) - -// metadata for a block is stored in the first pointer of the block -#define metadata(block) (*(void**)(block)) -#define freegcolink(block) (*(void**)((char*)block + kGCOLinkOffset)) - -struct lua_Page -{ - // list of pages with free blocks - lua_Page* prev; - lua_Page* next; - - // list of all gco pages - lua_Page* gcolistprev; - lua_Page* gcolistnext; - - int pageSize; // page size in bytes, including page header - int blockSize; // block size in bytes, including block header (for non-GCO) - - void* freeList; // next free block in this page; linked with metadata()/freegcolink() - int freeNext; // next free block offset in this page, in bytes; when negative, freeList is used instead - int busyBlocks; // number of blocks allocated out of this page - - union - { - char data[1]; - double align1; - void* align2; - }; -}; - -l_noret luaM_toobig(lua_State* L) -{ - luaG_runerror(L, "memory allocation error: block too big"); -} - -static lua_Page* newpage(lua_State* L, lua_Page** gcopageset, int pageSize, int blockSize, int blockCount) -{ - global_State* g = L->global; - - LUAU_ASSERT(pageSize - int(offsetof(lua_Page, data)) >= blockSize * blockCount); - - lua_Page* page = (lua_Page*)(*g->frealloc)(g->ud, NULL, 0, pageSize); - if (!page) - luaD_throw(L, LUA_ERRMEM); - - ASAN_POISON_MEMORY_REGION(page->data, blockSize * blockCount); - - // setup page header - page->prev = NULL; - page->next = NULL; - - page->gcolistprev = NULL; - page->gcolistnext = NULL; - - page->pageSize = pageSize; - page->blockSize = blockSize; - - // note: we start with the last block in the page and move downward - // either order would work, but that way we don't need to store the block count in the page - // additionally, GC stores objects in singly linked lists, and this way the GC lists end up in increasing pointer order - page->freeList = NULL; - page->freeNext = (blockCount - 1) * blockSize; - page->busyBlocks = 0; - - if (gcopageset) - { - page->gcolistnext = *gcopageset; - if (page->gcolistnext) - page->gcolistnext->gcolistprev = page; - *gcopageset = page; - } - - return page; -} - -static lua_Page* newclasspage(lua_State* L, lua_Page** freepageset, lua_Page** gcopageset, uint8_t sizeClass, bool storeMetadata) -{ - int blockSize = kSizeClassConfig.sizeOfClass[sizeClass] + (storeMetadata ? kBlockHeader : 0); - int blockCount = (kPageSize - offsetof(lua_Page, data)) / blockSize; - - lua_Page* page = newpage(L, gcopageset, kPageSize, blockSize, blockCount); - - // prepend a page to page freelist (which is empty because we only ever allocate a new page when it is!) - LUAU_ASSERT(!freepageset[sizeClass]); - freepageset[sizeClass] = page; - - return page; -} - -static void freepage(lua_State* L, lua_Page** gcopageset, lua_Page* page) -{ - global_State* g = L->global; - - if (gcopageset) - { - // remove page from alllist - if (page->gcolistnext) - page->gcolistnext->gcolistprev = page->gcolistprev; - - if (page->gcolistprev) - page->gcolistprev->gcolistnext = page->gcolistnext; - else if (*gcopageset == page) - *gcopageset = page->gcolistnext; - } - - // so long - (*g->frealloc)(g->ud, page, page->pageSize, 0); -} - -static void freeclasspage(lua_State* L, lua_Page** freepageset, lua_Page** gcopageset, lua_Page* page, uint8_t sizeClass) -{ - // remove page from freelist - if (page->next) - page->next->prev = page->prev; - - if (page->prev) - page->prev->next = page->next; - else if (freepageset[sizeClass] == page) - freepageset[sizeClass] = page->next; - - freepage(L, gcopageset, page); -} - -static void* newblock(lua_State* L, int sizeClass) -{ - global_State* g = L->global; - lua_Page* page = g->freepages[sizeClass]; - - // slow path: no page in the freelist, allocate a new one - if (!page) - page = newclasspage(L, g->freepages, NULL, sizeClass, true); - - LUAU_ASSERT(!page->prev); - LUAU_ASSERT(page->freeList || page->freeNext >= 0); - LUAU_ASSERT(size_t(page->blockSize) == kSizeClassConfig.sizeOfClass[sizeClass] + kBlockHeader); - - void* block; - - if (page->freeNext >= 0) - { - block = &page->data + page->freeNext; - ASAN_UNPOISON_MEMORY_REGION(block, page->blockSize); - - page->freeNext -= page->blockSize; - page->busyBlocks++; - } - else - { - block = page->freeList; - ASAN_UNPOISON_MEMORY_REGION(block, page->blockSize); - - page->freeList = metadata(block); - page->busyBlocks++; - } - - // the first word in a block point back to the page - metadata(block) = page; - - // if we allocate the last block out of a page, we need to remove it from free list - if (!page->freeList && page->freeNext < 0) - { - g->freepages[sizeClass] = page->next; - if (page->next) - page->next->prev = NULL; - page->next = NULL; - } - - // the user data is right after the metadata - return (char*)block + kBlockHeader; -} - -static void* newgcoblock(lua_State* L, int sizeClass) -{ - global_State* g = L->global; - lua_Page* page = g->freegcopages[sizeClass]; - - // slow path: no page in the freelist, allocate a new one - if (!page) - page = newclasspage(L, g->freegcopages, &g->allgcopages, sizeClass, false); - - LUAU_ASSERT(!page->prev); - LUAU_ASSERT(page->freeList || page->freeNext >= 0); - LUAU_ASSERT(page->blockSize == kSizeClassConfig.sizeOfClass[sizeClass]); - - void* block; - - if (page->freeNext >= 0) - { - block = &page->data + page->freeNext; - ASAN_UNPOISON_MEMORY_REGION(block, page->blockSize); - - page->freeNext -= page->blockSize; - page->busyBlocks++; - } - else - { - block = page->freeList; - ASAN_UNPOISON_MEMORY_REGION((char*)block + sizeof(GCheader), page->blockSize - sizeof(GCheader)); - - // when separate block metadata is not used, free list link is stored inside the block data itself - page->freeList = freegcolink(block); - page->busyBlocks++; - } - - // if we allocate the last block out of a page, we need to remove it from free list - if (!page->freeList && page->freeNext < 0) - { - g->freegcopages[sizeClass] = page->next; - if (page->next) - page->next->prev = NULL; - page->next = NULL; - } - - return block; -} - -static void freeblock(lua_State* L, int sizeClass, void* block) -{ - global_State* g = L->global; - - // the user data is right after the metadata - LUAU_ASSERT(block); - block = (char*)block - kBlockHeader; - - lua_Page* page = (lua_Page*)metadata(block); - LUAU_ASSERT(page && page->busyBlocks > 0); - LUAU_ASSERT(size_t(page->blockSize) == kSizeClassConfig.sizeOfClass[sizeClass] + kBlockHeader); - LUAU_ASSERT(block >= page->data && block < (char*)page + page->pageSize); - - // if the page wasn't in the page free list, it should be now since it got a block! - if (!page->freeList && page->freeNext < 0) - { - LUAU_ASSERT(!page->prev); - LUAU_ASSERT(!page->next); - - page->next = g->freepages[sizeClass]; - if (page->next) - page->next->prev = page; - g->freepages[sizeClass] = page; - } - - // add the block to the free list inside the page - metadata(block) = page->freeList; - page->freeList = block; - - ASAN_POISON_MEMORY_REGION(block, page->blockSize); - - page->busyBlocks--; - - // if it's the last block in the page, we don't need the page - if (page->busyBlocks == 0) - freeclasspage(L, g->freepages, NULL, page, sizeClass); -} - -static void freegcoblock(lua_State* L, int sizeClass, void* block, lua_Page* page) -{ - LUAU_ASSERT(page && page->busyBlocks > 0); - LUAU_ASSERT(page->blockSize == kSizeClassConfig.sizeOfClass[sizeClass]); - LUAU_ASSERT(block >= page->data && block < (char*)page + page->pageSize); - - global_State* g = L->global; - - // if the page wasn't in the page free list, it should be now since it got a block! - if (!page->freeList && page->freeNext < 0) - { - LUAU_ASSERT(!page->prev); - LUAU_ASSERT(!page->next); - - page->next = g->freegcopages[sizeClass]; - if (page->next) - page->next->prev = page; - g->freegcopages[sizeClass] = page; - } - - // when separate block metadata is not used, free list link is stored inside the block data itself - freegcolink(block) = page->freeList; - page->freeList = block; - - ASAN_POISON_MEMORY_REGION((char*)block + sizeof(GCheader), page->blockSize - sizeof(GCheader)); - - page->busyBlocks--; - - // if it's the last block in the page, we don't need the page - if (page->busyBlocks == 0) - freeclasspage(L, g->freegcopages, &g->allgcopages, page, sizeClass); -} - -void* luaM_new_(lua_State* L, size_t nsize, uint8_t memcat) -{ - global_State* g = L->global; - - int nclass = sizeclass(nsize); - - void* block = nclass >= 0 ? newblock(L, nclass) : (*g->frealloc)(g->ud, NULL, 0, nsize); - if (block == NULL && nsize > 0) - luaD_throw(L, LUA_ERRMEM); - - g->totalbytes += nsize; - g->memcatbytes[memcat] += nsize; - - return block; -} - -GCObject* luaM_newgco_(lua_State* L, size_t nsize, uint8_t memcat) -{ - // we need to accommodate space for link for free blocks (freegcolink) - LUAU_ASSERT(nsize >= kGCOLinkOffset + sizeof(void*)); - - global_State* g = L->global; - - int nclass = sizeclass(nsize); - - void* block = NULL; - - if (nclass >= 0) - { - block = newgcoblock(L, nclass); - } - else - { - lua_Page* page = newpage(L, &g->allgcopages, offsetof(lua_Page, data) + int(nsize), int(nsize), 1); - - block = &page->data; - ASAN_UNPOISON_MEMORY_REGION(block, page->blockSize); - - page->freeNext -= page->blockSize; - page->busyBlocks++; - } - - if (block == NULL && nsize > 0) - luaD_throw(L, LUA_ERRMEM); - - g->totalbytes += nsize; - g->memcatbytes[memcat] += nsize; - - return (GCObject*)block; -} - -void luaM_free_(lua_State* L, void* block, size_t osize, uint8_t memcat) -{ - global_State* g = L->global; - LUAU_ASSERT((osize == 0) == (block == NULL)); - - int oclass = sizeclass(osize); - - if (oclass >= 0) - freeblock(L, oclass, block); - else - (*g->frealloc)(g->ud, block, osize, 0); - - g->totalbytes -= osize; - g->memcatbytes[memcat] -= osize; -} - -void luaM_freegco_(lua_State* L, GCObject* block, size_t osize, uint8_t memcat, lua_Page* page) -{ - global_State* g = L->global; - LUAU_ASSERT((osize == 0) == (block == NULL)); - - int oclass = sizeclass(osize); - - if (oclass >= 0) - { - block->gch.tt = LUA_TNIL; - - freegcoblock(L, oclass, block, page); - } - else - { - LUAU_ASSERT(page->busyBlocks == 1); - LUAU_ASSERT(size_t(page->blockSize) == osize); - LUAU_ASSERT((void*)block == page->data); - - freepage(L, &g->allgcopages, page); - } - - g->totalbytes -= osize; - g->memcatbytes[memcat] -= osize; -} - -void* luaM_realloc_(lua_State* L, void* block, size_t osize, size_t nsize, uint8_t memcat) -{ - global_State* g = L->global; - LUAU_ASSERT((osize == 0) == (block == NULL)); - - int nclass = sizeclass(nsize); - int oclass = sizeclass(osize); - void* result; - - // if either block needs to be allocated using a block allocator, we can't use realloc directly - if (nclass >= 0 || oclass >= 0) - { - result = nclass >= 0 ? newblock(L, nclass) : (*g->frealloc)(g->ud, NULL, 0, nsize); - if (result == NULL && nsize > 0) - luaD_throw(L, LUA_ERRMEM); - - if (osize > 0 && nsize > 0) - memcpy(result, block, osize < nsize ? osize : nsize); - - if (oclass >= 0) - freeblock(L, oclass, block); - else - (*g->frealloc)(g->ud, block, osize, 0); - } - else - { - result = (*g->frealloc)(g->ud, block, osize, nsize); - if (result == NULL && nsize > 0) - luaD_throw(L, LUA_ERRMEM); - } - - LUAU_ASSERT((nsize == 0) == (result == NULL)); - g->totalbytes = (g->totalbytes - osize) + nsize; - g->memcatbytes[memcat] += nsize - osize; - return result; -} - -void luaM_getpagewalkinfo(lua_Page* page, char** start, char** end, int* busyBlocks, int* blockSize) -{ - int blockCount = (page->pageSize - offsetof(lua_Page, data)) / page->blockSize; - - LUAU_ASSERT(page->freeNext >= -page->blockSize && page->freeNext <= (blockCount - 1) * page->blockSize); - - char* data = page->data; // silences ubsan when indexing page->data - - *start = data + page->freeNext + page->blockSize; - *end = data + blockCount * page->blockSize; - *busyBlocks = page->busyBlocks; - *blockSize = page->blockSize; -} - -lua_Page* luaM_getnextgcopage(lua_Page* page) -{ - return page->gcolistnext; -} - -void luaM_visitpage(lua_Page* page, void* context, bool (*visitor)(void* context, lua_Page* page, GCObject* gco)) -{ - char* start; - char* end; - int busyBlocks; - int blockSize; - luaM_getpagewalkinfo(page, &start, &end, &busyBlocks, &blockSize); - - for (char* pos = start; pos != end; pos += blockSize) - { - GCObject* gco = (GCObject*)pos; - - // skip memory blocks that are already freed - if (gco->gch.tt == LUA_TNIL) - continue; - - // when true is returned it means that the element was deleted - if (visitor(context, page, gco)) - { - LUAU_ASSERT(busyBlocks > 0); - - // if the last block was removed, page would be removed as well - if (--busyBlocks == 0) - break; - } - } -} - -void luaM_visitgco(lua_State* L, void* context, bool (*visitor)(void* context, lua_Page* page, GCObject* gco)) -{ - global_State* g = L->global; - - for (lua_Page* curr = g->allgcopages; curr;) - { - lua_Page* next = curr->gcolistnext; // block visit might destroy the page - - luaM_visitpage(curr, context, visitor); - - curr = next; - } -} diff --git a/lib/luau/VM/src/lmem.h b/lib/luau/VM/src/lmem.h deleted file mode 100644 index e552d73..0000000 --- a/lib/luau/VM/src/lmem.h +++ /dev/null @@ -1,32 +0,0 @@ -// This file is part of the Luau programming language and is licensed under MIT License; see LICENSE.txt for details -// This code is based on Lua 5.x implementation licensed under MIT License; see lua_LICENSE.txt for details -#pragma once - -#include "lua.h" - -struct lua_Page; -union GCObject; - -#define luaM_newgco(L, t, size, memcat) cast_to(t*, luaM_newgco_(L, size, memcat)) -#define luaM_freegco(L, p, size, memcat, page) luaM_freegco_(L, obj2gco(p), size, memcat, page) - -#define luaM_arraysize_(L, n, e) ((cast_to(size_t, (n)) <= SIZE_MAX / (e)) ? (n) * (e) : (luaM_toobig(L), SIZE_MAX)) - -#define luaM_newarray(L, n, t, memcat) cast_to(t*, luaM_new_(L, luaM_arraysize_(L, n, sizeof(t)), memcat)) -#define luaM_freearray(L, b, n, t, memcat) luaM_free_(L, (b), (n) * sizeof(t), memcat) -#define luaM_reallocarray(L, v, oldn, n, t, memcat) \ - ((v) = cast_to(t*, luaM_realloc_(L, v, (oldn) * sizeof(t), luaM_arraysize_(L, n, sizeof(t)), memcat))) - -LUAI_FUNC void* luaM_new_(lua_State* L, size_t nsize, uint8_t memcat); -LUAI_FUNC GCObject* luaM_newgco_(lua_State* L, size_t nsize, uint8_t memcat); -LUAI_FUNC void luaM_free_(lua_State* L, void* block, size_t osize, uint8_t memcat); -LUAI_FUNC void luaM_freegco_(lua_State* L, GCObject* block, size_t osize, uint8_t memcat, lua_Page* page); -LUAI_FUNC void* luaM_realloc_(lua_State* L, void* block, size_t osize, size_t nsize, uint8_t memcat); - -LUAI_FUNC l_noret luaM_toobig(lua_State* L); - -LUAI_FUNC void luaM_getpagewalkinfo(lua_Page* page, char** start, char** end, int* busyBlocks, int* blockSize); -LUAI_FUNC lua_Page* luaM_getnextgcopage(lua_Page* page); - -LUAI_FUNC void luaM_visitpage(lua_Page* page, void* context, bool (*visitor)(void* context, lua_Page* page, GCObject* gco)); -LUAI_FUNC void luaM_visitgco(lua_State* L, void* context, bool (*visitor)(void* context, lua_Page* page, GCObject* gco)); diff --git a/lib/luau/VM/src/lnumprint.cpp b/lib/luau/VM/src/lnumprint.cpp deleted file mode 100644 index d64e3ca..0000000 --- a/lib/luau/VM/src/lnumprint.cpp +++ /dev/null @@ -1,366 +0,0 @@ -// This file is part of the Luau programming language and is licensed under MIT License; see LICENSE.txt for details -// This code is based on Lua 5.x implementation licensed under MIT License; see lua_LICENSE.txt for details -#include "luaconf.h" -#include "lnumutils.h" - -#include "lcommon.h" - -#include - -#ifdef _MSC_VER -#include -#endif - -// This work is based on: -// Raffaello Giulietti. The Schubfach way to render doubles. 2021 -// https://drive.google.com/file/d/1IEeATSVnEE6TkrHlCYNY2GjaraBjOT4f/edit - -// The code uses the notation from the paper for local variables where appropriate, and refers to paper sections/figures/results. - -// 9.8.2. Precomputed table for 128-bit overestimates of powers of 10 (see figure 3 for table bounds) -// To avoid storing 616 128-bit numbers directly we use a technique inspired by Dragonbox implementation and store 16 consecutive -// powers using a 128-bit baseline and a bitvector with 1-bit scale and 3-bit offset for the delta between each entry and base*5^k -static const int kPow10TableMin = -292; -static const int kPow10TableMax = 324; - -// clang-format off -static const uint64_t kPow5Table[16] = { - 0x8000000000000000, 0xa000000000000000, 0xc800000000000000, 0xfa00000000000000, 0x9c40000000000000, 0xc350000000000000, - 0xf424000000000000, 0x9896800000000000, 0xbebc200000000000, 0xee6b280000000000, 0x9502f90000000000, 0xba43b74000000000, - 0xe8d4a51000000000, 0x9184e72a00000000, 0xb5e620f480000000, 0xe35fa931a0000000, -}; -static const uint64_t kPow10Table[(kPow10TableMax - kPow10TableMin + 1 + 15) / 16][3] = { - {0xff77b1fcbebcdc4f, 0x25e8e89c13bb0f7b, 0x333443443333443b}, {0x8dd01fad907ffc3b, 0xae3da7d97f6792e4, 0xbbb3ab3cb3ba3cbc}, - {0x9d71ac8fada6c9b5, 0x6f773fc3603db4aa, 0x4ba4bc4bb4bb4bcc}, {0xaecc49914078536d, 0x58fae9f773886e19, 0x3ba3bc33b43b43bb}, - {0xc21094364dfb5636, 0x985915fc12f542e5, 0x33b43b43a33b33cb}, {0xd77485cb25823ac7, 0x7d633293366b828c, 0x34b44c444343443c}, - {0xef340a98172aace4, 0x86fb897116c87c35, 0x333343333343334b}, {0x84c8d4dfd2c63f3b, 0x29ecd9f40041e074, 0xccaccbbcbcbb4bbc}, - {0x936b9fcebb25c995, 0xcab10dd900beec35, 0x3ab3ab3ab3bb3bbb}, {0xa3ab66580d5fdaf5, 0xc13e60d0d2e0ebbb, 0x4cc3dc4db4db4dbb}, - {0xb5b5ada8aaff80b8, 0x0d819992132456bb, 0x33b33a34c33b34ab}, {0xc9bcff6034c13052, 0xfc89b393dd02f0b6, 0x33c33b44b43c34bc}, - {0xdff9772470297ebd, 0x59787e2b93bc56f8, 0x43b444444443434c}, {0xf8a95fcf88747d94, 0x75a44c6397ce912b, 0x443334343443343b}, - {0x8a08f0f8bf0f156b, 0x1b8e9ecb641b5900, 0xbbabab3aa3ab4ccc}, {0x993fe2c6d07b7fab, 0xe546a8038efe402a, 0x4cb4bc4db4db4bcc}, - {0xaa242499697392d2, 0xdde50bd1d5d0b9ea, 0x3ba3ba3bb33b33bc}, {0xbce5086492111aea, 0x88f4bb1ca6bcf585, 0x44b44c44c44c43cb}, - {0xd1b71758e219652b, 0xd3c36113404ea4a9, 0x44c44c44c444443b}, {0xe8d4a51000000000, 0x0000000000000000, 0x444444444444444c}, - {0x813f3978f8940984, 0x4000000000000000, 0xcccccccccccccccc}, {0x8f7e32ce7bea5c6f, 0xe4820023a2000000, 0xbba3bc4cc4cc4ccc}, - {0x9f4f2726179a2245, 0x01d762422c946591, 0x4aa3bb3aa3ba3bab}, {0xb0de65388cc8ada8, 0x3b25a55f43294bcc, 0x3ca33b33b44b43bc}, - {0xc45d1df942711d9a, 0x3ba5d0bd324f8395, 0x44c44c34c44b44cb}, {0xda01ee641a708de9, 0xe80e6f4820cc9496, 0x33b33b343333333c}, - {0xf209787bb47d6b84, 0xc0678c5dbd23a49b, 0x443444444443443b}, {0x865b86925b9bc5c2, 0x0b8a2392ba45a9b3, 0xdbccbcccb4cb3bbb}, - {0x952ab45cfa97a0b2, 0xdd945a747bf26184, 0x3bc4bb4ab3ca3cbc}, {0xa59bc234db398c25, 0x43fab9837e699096, 0x3bb3ac3ab3bb33ac}, - {0xb7dcbf5354e9bece, 0x0c11ed6d538aeb30, 0x33b43b43b34c34dc}, {0xcc20ce9bd35c78a5, 0x31ec038df7b441f5, 0x34c44c43c44b44cb}, - {0xe2a0b5dc971f303a, 0x2e44ae64840fd61e, 0x333333333333333c}, {0xfb9b7cd9a4a7443c, 0x169840ef017da3b2, 0x433344443333344c}, - {0x8bab8eefb6409c1a, 0x1ad089b6c2f7548f, 0xdcbdcc3cc4cc4bcb}, {0x9b10a4e5e9913128, 0xca7cf2b4191c8327, 0x3ab3cb3bc3bb4bbb}, - {0xac2820d9623bf429, 0x546345fa9fbdcd45, 0x3bb3cc43c43c43cb}, {0xbf21e44003acdd2c, 0xe0470a63e6bd56c4, 0x44b34a43b44c44bc}, - {0xd433179d9c8cb841, 0x5fa60692a46151ec, 0x43a33a33a333333c}, -}; -// clang-format on - -static const char kDigitTable[] = "0001020304050607080910111213141516171819202122232425262728293031323334353637383940414243444546474849" - "5051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899"; - -// x*y => 128-bit product (lo+hi) -inline uint64_t mul128(uint64_t x, uint64_t y, uint64_t* hi) -{ -#if defined(_MSC_VER) && defined(_M_X64) - return _umul128(x, y, hi); -#elif defined(__SIZEOF_INT128__) - unsigned __int128 r = x; - r *= y; - *hi = uint64_t(r >> 64); - return uint64_t(r); -#else - uint32_t x0 = uint32_t(x), x1 = uint32_t(x >> 32); - uint32_t y0 = uint32_t(y), y1 = uint32_t(y >> 32); - uint64_t p11 = uint64_t(x1) * y1, p01 = uint64_t(x0) * y1; - uint64_t p10 = uint64_t(x1) * y0, p00 = uint64_t(x0) * y0; - uint64_t mid = p10 + (p00 >> 32) + uint32_t(p01); - uint64_t r0 = (mid << 32) | uint32_t(p00); - uint64_t r1 = p11 + (mid >> 32) + (p01 >> 32); - *hi = r1; - return r0; -#endif -} - -// (x*y)>>64 => 128-bit product (lo+hi) -inline uint64_t mul192hi(uint64_t xhi, uint64_t xlo, uint64_t y, uint64_t* hi) -{ - uint64_t z2; - uint64_t z1 = mul128(xhi, y, &z2); - - uint64_t z1c; - uint64_t z0 = mul128(xlo, y, &z1c); - (void)z0; - - z1 += z1c; - z2 += (z1 < z1c); - - *hi = z2; - return z1; -} - -// 9.3. Rounding to odd (+ figure 8 + result 23) -inline uint64_t roundodd(uint64_t ghi, uint64_t glo, uint64_t cp) -{ - uint64_t xhi; - uint64_t xlo = mul128(glo, cp, &xhi); - (void)xlo; - - uint64_t yhi; - uint64_t ylo = mul128(ghi, cp, &yhi); - - uint64_t z = ylo + xhi; - return (yhi + (z < xhi)) | (z > 1); -} - -struct Decimal -{ - uint64_t s; - int k; -}; - -static Decimal schubfach(int exponent, uint64_t fraction) -{ - // Extract c & q such that c*2^q == |v| - uint64_t c = fraction; - int q = exponent - 1023 - 51; - - if (exponent != 0) // normal numbers have implicit leading 1 - { - c |= (1ull << 52); - q--; - } - - // 8.3. Fast path for integers - if (unsigned(-q) < 53 && (c & ((1ull << (-q)) - 1)) == 0) - return {c >> (-q), 0}; - - // 5. Rounding interval - int irr = (c == (1ull << 52) && q != -1074); // Qmin - int out = int(c & 1); - - // 9.8.1. Boundaries for c - uint64_t cbl = 4 * c - 2 + irr; - uint64_t cb = 4 * c; - uint64_t cbr = 4 * c + 2; - - // 9.1. Computing k and h - const int Q = 20; - const int C = 315652; // floor(2^Q * log10(2)) - const int A = -131008; // floor(2^Q * log10(3/4)) - const int C2 = 3483294; // floor(2^Q * log2(10)) - int k = (q * C + (irr ? A : 0)) >> Q; - int h = q + ((-k * C2) >> Q) + 1; // see (9) in 9.9 - - // 9.8.2. Overestimates of powers of 10 - // Recover 10^-k fraction using compact tables generated by tools/numutils.py - // The 128-bit fraction is encoded as 128-bit baseline * power-of-5 * scale + offset - LUAU_ASSERT(-k >= kPow10TableMin && -k <= kPow10TableMax); - int gtoff = -k - kPow10TableMin; - const uint64_t* gt = kPow10Table[gtoff >> 4]; - - uint64_t ghi; - uint64_t glo = mul192hi(gt[0], gt[1], kPow5Table[gtoff & 15], &ghi); - - // Apply 1-bit scale + 3-bit offset; note, offset is intentionally applied without carry, numutils.py validates that this is sufficient - int gterr = (gt[2] >> ((gtoff & 15) * 4)) & 15; - int gtscale = gterr >> 3; - - ghi <<= gtscale; - ghi += (glo >> 63) & gtscale; - glo <<= gtscale; - glo -= (gterr & 7) - 4; - - // 9.9. Boundaries for v - uint64_t vbl = roundodd(ghi, glo, cbl << h); - uint64_t vb = roundodd(ghi, glo, cb << h); - uint64_t vbr = roundodd(ghi, glo, cbr << h); - - // Main algorithm; see figure 7 + figure 9 - uint64_t s = vb / 4; - - if (s >= 10) - { - uint64_t sp = s / 10; - - bool upin = vbl + out <= 40 * sp; - bool wpin = vbr >= 40 * sp + 40 + out; - - if (upin != wpin) - return {sp + wpin, k + 1}; - } - - // Figure 7 contains the algorithm to select between u (s) and w (s+1) - // rup computes the last 4 conditions in that algorithm - // rup is only used when uin == win, but since these branches predict poorly we use branchless selects - bool uin = vbl + out <= 4 * s; - bool win = 4 * s + 4 + out <= vbr; - bool rup = vb >= 4 * s + 2 + 1 - (s & 1); - - return {s + (uin != win ? win : rup), k}; -} - -static char* printspecial(char* buf, int sign, uint64_t fraction) -{ - if (fraction == 0) - { - memcpy(buf, ("-inf") + (1 - sign), 4); - return buf + 3 + sign; - } - else - { - memcpy(buf, "nan", 4); - return buf + 3; - } -} - -static char* printunsignedrev(char* end, uint64_t num) -{ - while (num >= 10000) - { - unsigned int tail = unsigned(num % 10000); - - memcpy(end - 4, &kDigitTable[int(tail / 100) * 2], 2); - memcpy(end - 2, &kDigitTable[int(tail % 100) * 2], 2); - num /= 10000; - end -= 4; - } - - unsigned int rest = unsigned(num); - - while (rest >= 10) - { - memcpy(end - 2, &kDigitTable[int(rest % 100) * 2], 2); - rest /= 100; - end -= 2; - } - - if (rest) - { - end[-1] = '0' + int(rest); - end -= 1; - } - - return end; -} - -static char* printexp(char* buf, int num) -{ - *buf++ = 'e'; - *buf++ = num < 0 ? '-' : '+'; - - int v = num < 0 ? -num : num; - - if (v >= 100) - { - *buf++ = '0' + (v / 100); - v %= 100; - } - - memcpy(buf, &kDigitTable[v * 2], 2); - return buf + 2; -} - -inline char* trimzero(char* end) -{ - while (end[-1] == '0') - end--; - - return end; -} - -// We use fixed-length memcpy/memset since they lower to fast SIMD+scalar writes; the target buffers should have padding space -#define fastmemcpy(dst, src, size, sizefast) check_exp((size) <= sizefast, memcpy(dst, src, sizefast)) -#define fastmemset(dst, val, size, sizefast) check_exp((size) <= sizefast, memset(dst, val, sizefast)) - -char* luai_num2str(char* buf, double n) -{ - // IEEE-754 - union - { - double v; - uint64_t bits; - } v = {n}; - int sign = int(v.bits >> 63); - int exponent = int(v.bits >> 52) & 2047; - uint64_t fraction = v.bits & ((1ull << 52) - 1); - - // specials - if (LUAU_UNLIKELY(exponent == 0x7ff)) - return printspecial(buf, sign, fraction); - - // sign bit - *buf = '-'; - buf += sign; - - // zero - if (exponent == 0 && fraction == 0) - { - buf[0] = '0'; - return buf + 1; - } - - // convert binary to decimal using Schubfach - Decimal d = schubfach(exponent, fraction); - LUAU_ASSERT(d.s < uint64_t(1e17)); - - // print the decimal to a temporary buffer; we'll need to insert the decimal point and figure out the format - char decbuf[40]; - char* decend = decbuf + 20; // significand needs at most 17 digits; the rest of the buffer may be copied using fixed length memcpy - char* dec = printunsignedrev(decend, d.s); - - int declen = int(decend - dec); - LUAU_ASSERT(declen <= 17); - - int dot = declen + d.k; - - // the limits are somewhat arbitrary but changing them may require changing fastmemset/fastmemcpy sizes below - if (dot >= -5 && dot <= 21) - { - // fixed point format - if (dot <= 0) - { - buf[0] = '0'; - buf[1] = '.'; - - fastmemset(buf + 2, '0', -dot, 5); - fastmemcpy(buf + 2 + (-dot), dec, declen, 17); - - return trimzero(buf + 2 + (-dot) + declen); - } - else if (dot == declen) - { - // no dot - fastmemcpy(buf, dec, dot, 17); - - return buf + dot; - } - else if (dot < declen) - { - // dot in the middle - fastmemcpy(buf, dec, dot, 16); - - buf[dot] = '.'; - - fastmemcpy(buf + dot + 1, dec + dot, declen - dot, 16); - - return trimzero(buf + declen + 1); - } - else - { - // no dot, zero padding - fastmemcpy(buf, dec, declen, 17); - fastmemset(buf + declen, '0', dot - declen, 8); - - return buf + dot; - } - } - else - { - // scientific format - buf[0] = dec[0]; - buf[1] = '.'; - fastmemcpy(buf + 2, dec + 1, declen - 1, 16); - - char* exp = trimzero(buf + declen + 1); - - return printexp(exp, dot - 1); - } -} diff --git a/lib/luau/VM/src/lnumutils.h b/lib/luau/VM/src/lnumutils.h deleted file mode 100644 index 38bfb32..0000000 --- a/lib/luau/VM/src/lnumutils.h +++ /dev/null @@ -1,69 +0,0 @@ -// This file is part of the Luau programming language and is licensed under MIT License; see LICENSE.txt for details -// This code is based on Lua 5.x implementation licensed under MIT License; see lua_LICENSE.txt for details -#pragma once - -#include - -#define luai_numadd(a, b) ((a) + (b)) -#define luai_numsub(a, b) ((a) - (b)) -#define luai_nummul(a, b) ((a) * (b)) -#define luai_numdiv(a, b) ((a) / (b)) -#define luai_numpow(a, b) (pow(a, b)) -#define luai_numunm(a) (-(a)) -#define luai_numisnan(a) ((a) != (a)) -#define luai_numeq(a, b) ((a) == (b)) -#define luai_numlt(a, b) ((a) < (b)) -#define luai_numle(a, b) ((a) <= (b)) - -inline bool luai_veceq(const float* a, const float* b) -{ -#if LUA_VECTOR_SIZE == 4 - return a[0] == b[0] && a[1] == b[1] && a[2] == b[2] && a[3] == b[3]; -#else - return a[0] == b[0] && a[1] == b[1] && a[2] == b[2]; -#endif -} - -inline bool luai_vecisnan(const float* a) -{ -#if LUA_VECTOR_SIZE == 4 - return a[0] != a[0] || a[1] != a[1] || a[2] != a[2] || a[3] != a[3]; -#else - return a[0] != a[0] || a[1] != a[1] || a[2] != a[2]; -#endif -} - -LUAU_FASTMATH_BEGIN -inline double luai_nummod(double a, double b) -{ - return a - floor(a / b) * b; -} -LUAU_FASTMATH_END - -LUAU_FASTMATH_BEGIN -inline double luai_numidiv(double a, double b) -{ - return floor(a / b); -} -LUAU_FASTMATH_END - -#define luai_num2int(i, d) ((i) = (int)(d)) - -// On MSVC in 32-bit, double to unsigned cast compiles into a call to __dtoui3, so we invoke x87->int64 conversion path manually -#if defined(_MSC_VER) && defined(_M_IX86) -#define luai_num2unsigned(i, n) \ - { \ - __int64 l; \ - __asm { __asm fld n __asm fistp l} \ - ; \ - i = (unsigned int)l; \ - } -#else -#define luai_num2unsigned(i, n) ((i) = (unsigned)(long long)(n)) -#endif - -#define LUAI_MAXNUM2STR 48 - -LUAI_FUNC char* luai_num2str(char* buf, double n); - -#define luai_str2num(s, p) strtod((s), (p)) diff --git a/lib/luau/VM/src/lobject.cpp b/lib/luau/VM/src/lobject.cpp deleted file mode 100644 index 081e331..0000000 --- a/lib/luau/VM/src/lobject.cpp +++ /dev/null @@ -1,154 +0,0 @@ -// This file is part of the Luau programming language and is licensed under MIT License; see LICENSE.txt for details -// This code is based on Lua 5.x implementation licensed under MIT License; see lua_LICENSE.txt for details -#include "lobject.h" - -#include "lstate.h" -#include "lstring.h" -#include "lgc.h" -#include "ldo.h" -#include "lnumutils.h" - -#include -#include -#include -#include - -const TValue luaO_nilobject_ = {{NULL}, {0}, LUA_TNIL}; - -int luaO_log2(unsigned int x) -{ - static const uint8_t log_2[256] = {0, 1, 2, 2, 3, 3, 3, 3, 4, 4, 4, 4, 4, 4, 4, 4, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 6, 6, 6, 6, 6, - 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, - 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 8, 8, 8, - 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, - 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, - 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8}; - int l = -1; - while (x >= 256) - { - l += 8; - x >>= 8; - } - return l + log_2[x]; -} - -int luaO_rawequalObj(const TValue* t1, const TValue* t2) -{ - if (ttype(t1) != ttype(t2)) - return 0; - else - switch (ttype(t1)) - { - case LUA_TNIL: - return 1; - case LUA_TNUMBER: - return luai_numeq(nvalue(t1), nvalue(t2)); - case LUA_TVECTOR: - return luai_veceq(vvalue(t1), vvalue(t2)); - case LUA_TBOOLEAN: - return bvalue(t1) == bvalue(t2); // boolean true must be 1 !! - case LUA_TLIGHTUSERDATA: - return pvalue(t1) == pvalue(t2) && (!FFlag::TaggedLuData || lightuserdatatag(t1) == lightuserdatatag(t2)); - default: - LUAU_ASSERT(iscollectable(t1)); - return gcvalue(t1) == gcvalue(t2); - } -} - -int luaO_rawequalKey(const TKey* t1, const TValue* t2) -{ - if (ttype(t1) != ttype(t2)) - return 0; - else - switch (ttype(t1)) - { - case LUA_TNIL: - return 1; - case LUA_TNUMBER: - return luai_numeq(nvalue(t1), nvalue(t2)); - case LUA_TVECTOR: - return luai_veceq(vvalue(t1), vvalue(t2)); - case LUA_TBOOLEAN: - return bvalue(t1) == bvalue(t2); // boolean true must be 1 !! - case LUA_TLIGHTUSERDATA: - return pvalue(t1) == pvalue(t2) && (!FFlag::TaggedLuData || lightuserdatatag(t1) == lightuserdatatag(t2)); - default: - LUAU_ASSERT(iscollectable(t1)); - return gcvalue(t1) == gcvalue(t2); - } -} - -int luaO_str2d(const char* s, double* result) -{ - char* endptr; - *result = luai_str2num(s, &endptr); - if (endptr == s) - return 0; // conversion failed - if (*endptr == 'x' || *endptr == 'X') // maybe an hexadecimal constant? - *result = cast_num(strtoul(s, &endptr, 16)); - if (*endptr == '\0') - return 1; // most common case - while (isspace(cast_to(unsigned char, *endptr))) - endptr++; - if (*endptr != '\0') - return 0; // invalid trailing characters? - return 1; -} - -const char* luaO_pushvfstring(lua_State* L, const char* fmt, va_list argp) -{ - char result[LUA_BUFFERSIZE]; - vsnprintf(result, sizeof(result), fmt, argp); - - setsvalue(L, L->top, luaS_new(L, result)); - incr_top(L); - return svalue(L->top - 1); -} - -const char* luaO_pushfstring(lua_State* L, const char* fmt, ...) -{ - const char* msg; - va_list argp; - va_start(argp, fmt); - msg = luaO_pushvfstring(L, fmt, argp); - va_end(argp); - return msg; -} - -const char* luaO_chunkid(char* buf, size_t buflen, const char* source, size_t srclen) -{ - if (*source == '=') - { - if (srclen <= buflen) - return source + 1; - // truncate the part after = - memcpy(buf, source + 1, buflen - 1); - buf[buflen - 1] = '\0'; - } - else if (*source == '@') - { - if (srclen <= buflen) - return source + 1; - // truncate the part after @ - memcpy(buf, "...", 3); - memcpy(buf + 3, source + srclen - (buflen - 4), buflen - 4); - buf[buflen - 1] = '\0'; - } - else - { // buf = [string "string"] - size_t len = strcspn(source, "\n\r"); // stop at first newline - buflen -= sizeof("[string \"...\"]"); - if (len > buflen) - len = buflen; - strcpy(buf, "[string \""); - if (source[len] != '\0') - { // must truncate? - strncat(buf, source, len); - strcat(buf, "..."); - } - else - strcat(buf, source); - strcat(buf, "\"]"); - } - return buf; -} diff --git a/lib/luau/VM/src/lobject.h b/lib/luau/VM/src/lobject.h deleted file mode 100644 index d236f7e..0000000 --- a/lib/luau/VM/src/lobject.h +++ /dev/null @@ -1,502 +0,0 @@ -// This file is part of the Luau programming language and is licensed under MIT License; see LICENSE.txt for details -// This code is based on Lua 5.x implementation licensed under MIT License; see lua_LICENSE.txt for details -#pragma once - -#include "lua.h" -#include "lcommon.h" - -/* -** Union of all collectible objects -*/ -typedef union GCObject GCObject; - -/* -** Common Header for all collectible objects (in macro form, to be included in other objects) -*/ -// clang-format off -#define CommonHeader \ - uint8_t tt; uint8_t marked; uint8_t memcat -// clang-format on - -/* -** Common header in struct form -*/ -typedef struct GCheader -{ - CommonHeader; -} GCheader; - -/* -** Union of all Lua values -*/ -typedef union -{ - GCObject* gc; - void* p; - double n; - int b; - float v[2]; // v[0], v[1] live here; v[2] lives in TValue::extra -} Value; - -/* -** Tagged Values -*/ - -typedef struct lua_TValue -{ - Value value; - int extra[LUA_EXTRA_SIZE]; - int tt; -} TValue; - -// Macros to test type -#define ttisnil(o) (ttype(o) == LUA_TNIL) -#define ttisnumber(o) (ttype(o) == LUA_TNUMBER) -#define ttisstring(o) (ttype(o) == LUA_TSTRING) -#define ttistable(o) (ttype(o) == LUA_TTABLE) -#define ttisfunction(o) (ttype(o) == LUA_TFUNCTION) -#define ttisboolean(o) (ttype(o) == LUA_TBOOLEAN) -#define ttisuserdata(o) (ttype(o) == LUA_TUSERDATA) -#define ttisthread(o) (ttype(o) == LUA_TTHREAD) -#define ttisbuffer(o) (ttype(o) == LUA_TBUFFER) -#define ttislightuserdata(o) (ttype(o) == LUA_TLIGHTUSERDATA) -#define ttisvector(o) (ttype(o) == LUA_TVECTOR) -#define ttisupval(o) (ttype(o) == LUA_TUPVAL) - -// Macros to access values -#define ttype(o) ((o)->tt) -#define gcvalue(o) check_exp(iscollectable(o), (o)->value.gc) -#define pvalue(o) check_exp(ttislightuserdata(o), (o)->value.p) -#define nvalue(o) check_exp(ttisnumber(o), (o)->value.n) -#define vvalue(o) check_exp(ttisvector(o), (o)->value.v) -#define tsvalue(o) check_exp(ttisstring(o), &(o)->value.gc->ts) -#define uvalue(o) check_exp(ttisuserdata(o), &(o)->value.gc->u) -#define clvalue(o) check_exp(ttisfunction(o), &(o)->value.gc->cl) -#define hvalue(o) check_exp(ttistable(o), &(o)->value.gc->h) -#define bvalue(o) check_exp(ttisboolean(o), (o)->value.b) -#define thvalue(o) check_exp(ttisthread(o), &(o)->value.gc->th) -#define bufvalue(o) check_exp(ttisbuffer(o), &(o)->value.gc->buf) -#define upvalue(o) check_exp(ttisupval(o), &(o)->value.gc->uv) - -#define l_isfalse(o) (ttisnil(o) || (ttisboolean(o) && bvalue(o) == 0)) - -#define lightuserdatatag(o) check_exp(ttislightuserdata(o), (o)->extra[0]) - -// Internal tags used by the VM -#define LU_TAG_ITERATOR LUA_UTAG_LIMIT - -/* -** for internal debug only -*/ -#define checkconsistency(obj) LUAU_ASSERT(!iscollectable(obj) || (ttype(obj) == (obj)->value.gc->gch.tt)) - -#define checkliveness(g, obj) LUAU_ASSERT(!iscollectable(obj) || ((ttype(obj) == (obj)->value.gc->gch.tt) && !isdead(g, (obj)->value.gc))) - -// Macros to set values -#define setnilvalue(obj) ((obj)->tt = LUA_TNIL) - -#define setnvalue(obj, x) \ - { \ - TValue* i_o = (obj); \ - i_o->value.n = (x); \ - i_o->tt = LUA_TNUMBER; \ - } - -#if LUA_VECTOR_SIZE == 4 -#define setvvalue(obj, x, y, z, w) \ - { \ - TValue* i_o = (obj); \ - float* i_v = i_o->value.v; \ - i_v[0] = (x); \ - i_v[1] = (y); \ - i_v[2] = (z); \ - i_v[3] = (w); \ - i_o->tt = LUA_TVECTOR; \ - } -#else -#define setvvalue(obj, x, y, z, w) \ - { \ - TValue* i_o = (obj); \ - float* i_v = i_o->value.v; \ - i_v[0] = (x); \ - i_v[1] = (y); \ - i_v[2] = (z); \ - i_o->tt = LUA_TVECTOR; \ - } -#endif - -#define setpvalue(obj, x, tag) \ - { \ - TValue* i_o = (obj); \ - i_o->value.p = (x); \ - i_o->extra[0] = (tag); \ - i_o->tt = LUA_TLIGHTUSERDATA; \ - } - -#define setbvalue(obj, x) \ - { \ - TValue* i_o = (obj); \ - i_o->value.b = (x); \ - i_o->tt = LUA_TBOOLEAN; \ - } - -#define setsvalue(L, obj, x) \ - { \ - TValue* i_o = (obj); \ - i_o->value.gc = cast_to(GCObject*, (x)); \ - i_o->tt = LUA_TSTRING; \ - checkliveness(L->global, i_o); \ - } - -#define setuvalue(L, obj, x) \ - { \ - TValue* i_o = (obj); \ - i_o->value.gc = cast_to(GCObject*, (x)); \ - i_o->tt = LUA_TUSERDATA; \ - checkliveness(L->global, i_o); \ - } - -#define setthvalue(L, obj, x) \ - { \ - TValue* i_o = (obj); \ - i_o->value.gc = cast_to(GCObject*, (x)); \ - i_o->tt = LUA_TTHREAD; \ - checkliveness(L->global, i_o); \ - } - -#define setbufvalue(L, obj, x) \ - { \ - TValue* i_o = (obj); \ - i_o->value.gc = cast_to(GCObject*, (x)); \ - i_o->tt = LUA_TBUFFER; \ - checkliveness(L->global, i_o); \ - } - -#define setclvalue(L, obj, x) \ - { \ - TValue* i_o = (obj); \ - i_o->value.gc = cast_to(GCObject*, (x)); \ - i_o->tt = LUA_TFUNCTION; \ - checkliveness(L->global, i_o); \ - } - -#define sethvalue(L, obj, x) \ - { \ - TValue* i_o = (obj); \ - i_o->value.gc = cast_to(GCObject*, (x)); \ - i_o->tt = LUA_TTABLE; \ - checkliveness(L->global, i_o); \ - } - -#define setptvalue(L, obj, x) \ - { \ - TValue* i_o = (obj); \ - i_o->value.gc = cast_to(GCObject*, (x)); \ - i_o->tt = LUA_TPROTO; \ - checkliveness(L->global, i_o); \ - } - -#define setupvalue(L, obj, x) \ - { \ - TValue* i_o = (obj); \ - i_o->value.gc = cast_to(GCObject*, (x)); \ - i_o->tt = LUA_TUPVAL; \ - checkliveness(L->global, i_o); \ - } - -#define setobj(L, obj1, obj2) \ - { \ - const TValue* o2 = (obj2); \ - TValue* o1 = (obj1); \ - *o1 = *o2; \ - checkliveness(L->global, o1); \ - } - -/* -** different types of sets, according to destination -*/ - -// to stack -#define setobj2s setobj -// from table to same table (no barrier) -#define setobjt2t setobj -// to table (needs barrier) -#define setobj2t setobj -// to new object (no barrier) -#define setobj2n setobj - -#define setttype(obj, tt) (ttype(obj) = (tt)) - -#define iscollectable(o) (ttype(o) >= LUA_TSTRING) - -typedef TValue* StkId; // index to stack elements - -/* -** String headers for string table -*/ -typedef struct TString -{ - CommonHeader; - // 1 byte padding - - int16_t atom; - // 2 byte padding - - TString* next; // next string in the hash table bucket - - unsigned int hash; - unsigned int len; - - char data[1]; // string data is allocated right after the header -} TString; - -#define getstr(ts) (ts)->data -#define svalue(o) getstr(tsvalue(o)) - -typedef struct Udata -{ - CommonHeader; - - uint8_t tag; - - int len; - - struct Table* metatable; - - union - { - char data[1]; // userdata is allocated right after the header - L_Umaxalign dummy; // ensures maximum alignment for data - }; -} Udata; - -typedef struct Buffer -{ - CommonHeader; - - unsigned int len; - - union - { - char data[1]; // buffer is allocated right after the header - L_Umaxalign dummy; // ensures maximum alignment for data - }; -} Buffer; - -/* -** Function Prototypes -*/ -// clang-format off -typedef struct Proto -{ - CommonHeader; - - - uint8_t nups; // number of upvalues - uint8_t numparams; - uint8_t is_vararg; - uint8_t maxstacksize; - uint8_t flags; - - - TValue* k; // constants used by the function - Instruction* code; // function bytecode - struct Proto** p; // functions defined inside the function - const Instruction* codeentry; - - void* execdata; - uintptr_t exectarget; - - - uint8_t* lineinfo; // for each instruction, line number as a delta from baseline - int* abslineinfo; // baseline line info, one entry for each 1<v != &(up)->u.value) - -/* -** Closures -*/ - -typedef struct Closure -{ - CommonHeader; - - uint8_t isC; - uint8_t nupvalues; - uint8_t stacksize; - uint8_t preload; - - GCObject* gclist; - struct Table* env; - - union - { - struct - { - lua_CFunction f; - lua_Continuation cont; - const char* debugname; - TValue upvals[1]; - } c; - - struct - { - struct Proto* p; - TValue uprefs[1]; - } l; - }; -} Closure; - -#define iscfunction(o) (ttype(o) == LUA_TFUNCTION && clvalue(o)->isC) -#define isLfunction(o) (ttype(o) == LUA_TFUNCTION && !clvalue(o)->isC) - -/* -** Tables -*/ - -typedef struct TKey -{ - ::Value value; - int extra[LUA_EXTRA_SIZE]; - unsigned tt : 4; - int next : 28; // for chaining -} TKey; - -typedef struct LuaNode -{ - TValue val; - TKey key; -} LuaNode; - -// copy a value into a key -#define setnodekey(L, node, obj) \ - { \ - LuaNode* n_ = (node); \ - const TValue* i_o = (obj); \ - n_->key.value = i_o->value; \ - memcpy(n_->key.extra, i_o->extra, sizeof(n_->key.extra)); \ - n_->key.tt = i_o->tt; \ - checkliveness(L->global, i_o); \ - } - -// copy a value from a key -#define getnodekey(L, obj, node) \ - { \ - TValue* i_o = (obj); \ - const LuaNode* n_ = (node); \ - i_o->value = n_->key.value; \ - memcpy(i_o->extra, n_->key.extra, sizeof(i_o->extra)); \ - i_o->tt = n_->key.tt; \ - checkliveness(L->global, i_o); \ - } - -// clang-format off -typedef struct Table -{ - CommonHeader; - - - uint8_t tmcache; // 1<

lsizenode)) - -#define luaO_nilobject (&luaO_nilobject_) - -LUAI_DATA const TValue luaO_nilobject_; - -#define ceillog2(x) (luaO_log2((x)-1) + 1) - -LUAI_FUNC int luaO_log2(unsigned int x); -LUAI_FUNC int luaO_rawequalObj(const TValue* t1, const TValue* t2); -LUAI_FUNC int luaO_rawequalKey(const TKey* t1, const TValue* t2); -LUAI_FUNC int luaO_str2d(const char* s, double* result); -LUAI_FUNC const char* luaO_pushvfstring(lua_State* L, const char* fmt, va_list argp); -LUAI_FUNC const char* luaO_pushfstring(lua_State* L, const char* fmt, ...); -LUAI_FUNC const char* luaO_chunkid(char* buf, size_t buflen, const char* source, size_t srclen); - -LUAU_FASTFLAG(TaggedLuData) diff --git a/lib/luau/VM/src/loslib.cpp b/lib/luau/VM/src/loslib.cpp deleted file mode 100644 index a336555..0000000 --- a/lib/luau/VM/src/loslib.cpp +++ /dev/null @@ -1,225 +0,0 @@ -// This file is part of the Luau programming language and is licensed under MIT License; see LICENSE.txt for details -// This code is based on Lua 5.x implementation licensed under MIT License; see lua_LICENSE.txt for details -#include "lualib.h" - -#include "lcommon.h" - -#include -#include - -#define LUA_STRFTIMEOPTIONS "aAbBcdHIjmMpSUwWxXyYzZ%" - -#if defined(_WIN32) -static tm* gmtime_r(const time_t* timep, tm* result) -{ - return gmtime_s(result, timep) == 0 ? result : NULL; -} - -static tm* localtime_r(const time_t* timep, tm* result) -{ - return localtime_s(result, timep) == 0 ? result : NULL; -} -#endif - -static time_t os_timegm(struct tm* timep) -{ - // Julian day number calculation - int day = timep->tm_mday; - int month = timep->tm_mon + 1; - int year = timep->tm_year + 1900; - - // year adjustment, pretend that it starts in March - int a = timep->tm_mon % 12 < 2 ? 1 : 0; - - // also adjust for out-of-range month numbers in input - a -= timep->tm_mon / 12; - - int y = year + 4800 - a; - int m = month + (12 * a) - 3; - - int julianday = day + ((153 * m + 2) / 5) + (365 * y) + (y / 4) - (y / 100) + (y / 400) - 32045; - - const int utcstartasjulianday = 2440588; // Jan 1st 1970 offset in Julian calendar - const int64_t utcstartasjuliansecond = utcstartasjulianday * 86400ll; // same in seconds - - // fail the dates before UTC start - if (julianday < utcstartasjulianday) - return time_t(-1); - - int64_t daysecond = timep->tm_hour * 3600ll + timep->tm_min * 60ll + timep->tm_sec; - int64_t julianseconds = int64_t(julianday) * 86400ull + daysecond; - - if (julianseconds < utcstartasjuliansecond) - return time_t(-1); - - int64_t utc = julianseconds - utcstartasjuliansecond; - return time_t(utc); -} - -static int os_clock(lua_State* L) -{ - lua_pushnumber(L, lua_clock()); - return 1; -} - -/* -** {====================================================== -** Time/Date operations -** { year=%Y, month=%m, day=%d, hour=%H, min=%M, sec=%S, -** wday=%w+1, yday=%j, isdst=? } -** ======================================================= -*/ - -static void setfield(lua_State* L, const char* key, int value) -{ - lua_pushinteger(L, value); - lua_setfield(L, -2, key); -} - -static void setboolfield(lua_State* L, const char* key, int value) -{ - if (value < 0) // undefined? - return; // does not set field - lua_pushboolean(L, value); - lua_setfield(L, -2, key); -} - -static int getboolfield(lua_State* L, const char* key) -{ - int res; - lua_rawgetfield(L, -1, key); - res = lua_isnil(L, -1) ? -1 : lua_toboolean(L, -1); - lua_pop(L, 1); - return res; -} - -static int getfield(lua_State* L, const char* key, int d) -{ - int res; - lua_rawgetfield(L, -1, key); - if (lua_isnumber(L, -1)) - res = (int)lua_tointeger(L, -1); - else - { - if (d < 0) - luaL_error(L, "field '%s' missing in date table", key); - res = d; - } - lua_pop(L, 1); - return res; -} - -static int os_date(lua_State* L) -{ - const char* s = luaL_optstring(L, 1, "%c"); - time_t t = luaL_opt(L, (time_t)luaL_checknumber, 2, time(NULL)); - - struct tm tm; - struct tm* stm; - if (*s == '!') - { // UTC? - stm = gmtime_r(&t, &tm); - s++; // skip `!' - } - else - { - // on Windows, localtime() fails with dates before epoch start so we disallow that - stm = t < 0 ? NULL : localtime_r(&t, &tm); - } - - if (stm == NULL) // invalid date? - { - lua_pushnil(L); - } - else if (strcmp(s, "*t") == 0) - { - lua_createtable(L, 0, 9); // 9 = number of fields - setfield(L, "sec", stm->tm_sec); - setfield(L, "min", stm->tm_min); - setfield(L, "hour", stm->tm_hour); - setfield(L, "day", stm->tm_mday); - setfield(L, "month", stm->tm_mon + 1); - setfield(L, "year", stm->tm_year + 1900); - setfield(L, "wday", stm->tm_wday + 1); - setfield(L, "yday", stm->tm_yday + 1); - setboolfield(L, "isdst", stm->tm_isdst); - } - else - { - char cc[3]; - cc[0] = '%'; - cc[2] = '\0'; - - luaL_Strbuf b; - luaL_buffinit(L, &b); - for (; *s; s++) - { - if (*s != '%' || *(s + 1) == '\0') // no conversion specifier? - { - luaL_addchar(&b, *s); - } - else if (strchr(LUA_STRFTIMEOPTIONS, *(s + 1)) == 0) - { - luaL_argerror(L, 1, "invalid conversion specifier"); - } - else - { - size_t reslen; - char buff[200]; // should be big enough for any conversion result - cc[1] = *(++s); - reslen = strftime(buff, sizeof(buff), cc, stm); - luaL_addlstring(&b, buff, reslen); - } - } - luaL_pushresult(&b); - } - return 1; -} - -static int os_time(lua_State* L) -{ - time_t t; - if (lua_isnoneornil(L, 1)) // called without args? - t = time(NULL); // get current time - else - { - struct tm ts; - luaL_checktype(L, 1, LUA_TTABLE); - lua_settop(L, 1); // make sure table is at the top - ts.tm_sec = getfield(L, "sec", 0); - ts.tm_min = getfield(L, "min", 0); - ts.tm_hour = getfield(L, "hour", 12); - ts.tm_mday = getfield(L, "day", -1); - ts.tm_mon = getfield(L, "month", -1) - 1; - ts.tm_year = getfield(L, "year", -1) - 1900; - ts.tm_isdst = getboolfield(L, "isdst"); - - // Note: upstream Lua uses mktime() here which assumes input is local time, but we prefer UTC for consistency - t = os_timegm(&ts); - } - if (t == (time_t)(-1)) - lua_pushnil(L); - else - lua_pushnumber(L, (double)t); - return 1; -} - -static int os_difftime(lua_State* L) -{ - lua_pushnumber(L, difftime((time_t)(luaL_checknumber(L, 1)), (time_t)(luaL_optnumber(L, 2, 0)))); - return 1; -} - -static const luaL_Reg syslib[] = { - {"clock", os_clock}, - {"date", os_date}, - {"difftime", os_difftime}, - {"time", os_time}, - {NULL, NULL}, -}; - -int luaopen_os(lua_State* L) -{ - luaL_register(L, LUA_OSLIBNAME, syslib); - return 1; -} diff --git a/lib/luau/VM/src/lperf.cpp b/lib/luau/VM/src/lperf.cpp deleted file mode 100644 index 67befee..0000000 --- a/lib/luau/VM/src/lperf.cpp +++ /dev/null @@ -1,63 +0,0 @@ -// This file is part of the Luau programming language and is licensed under MIT License; see LICENSE.txt for details -// This code is based on Lua 5.x implementation licensed under MIT License; see lua_LICENSE.txt for details -#include "lua.h" - -#ifdef _WIN32 -#ifndef WIN32_LEAN_AND_MEAN -#define WIN32_LEAN_AND_MEAN -#endif -#ifndef NOMINMAX -#define NOMINMAX -#endif -#include -#endif - -#ifdef __APPLE__ -#include -#include -#endif - - - -#include - -static double clock_period() -{ -#if defined(_WIN32) - LARGE_INTEGER result = {}; - QueryPerformanceFrequency(&result); - return 1.0 / double(result.QuadPart); -#elif defined(__APPLE__) - mach_timebase_info_data_t result = {}; - mach_timebase_info(&result); - return double(result.numer) / double(result.denom) * 1e-9; -#elif defined(__linux__) - return 1e-9; -#else - return 1.0 / double(CLOCKS_PER_SEC); -#endif -} - -static double clock_timestamp() -{ -#if defined(_WIN32) - LARGE_INTEGER result = {}; - QueryPerformanceCounter(&result); - return double(result.QuadPart); -#elif defined(__APPLE__) - return double(mach_absolute_time()); -#elif defined(__linux__) - timespec now; - clock_gettime(CLOCK_MONOTONIC, &now); - return now.tv_sec * 1e9 + now.tv_nsec; -#else - return double(clock()); -#endif -} - -double lua_clock() -{ - static double period = clock_period(); - - return clock_timestamp() * period; -} diff --git a/lib/luau/VM/src/lstate.cpp b/lib/luau/VM/src/lstate.cpp deleted file mode 100644 index 858f61a..0000000 --- a/lib/luau/VM/src/lstate.cpp +++ /dev/null @@ -1,244 +0,0 @@ -// This file is part of the Luau programming language and is licensed under MIT License; see LICENSE.txt for details -// This code is based on Lua 5.x implementation licensed under MIT License; see lua_LICENSE.txt for details -#include "lstate.h" - -#include "ltable.h" -#include "lstring.h" -#include "lfunc.h" -#include "lmem.h" -#include "lgc.h" -#include "ldo.h" -#include "ldebug.h" - -/* -** Main thread combines a thread state and the global state -*/ -typedef struct LG -{ - lua_State l; - global_State g; -} LG; - -static void stack_init(lua_State* L1, lua_State* L) -{ - // initialize CallInfo array - L1->base_ci = luaM_newarray(L, BASIC_CI_SIZE, CallInfo, L1->memcat); - L1->ci = L1->base_ci; - L1->size_ci = BASIC_CI_SIZE; - L1->end_ci = L1->base_ci + L1->size_ci - 1; - // initialize stack array - L1->stack = luaM_newarray(L, BASIC_STACK_SIZE + EXTRA_STACK, TValue, L1->memcat); - L1->stacksize = BASIC_STACK_SIZE + EXTRA_STACK; - TValue* stack = L1->stack; - for (int i = 0; i < BASIC_STACK_SIZE + EXTRA_STACK; i++) - setnilvalue(stack + i); // erase new stack - L1->top = stack; - L1->stack_last = stack + (L1->stacksize - EXTRA_STACK); - // initialize first ci - L1->ci->func = L1->top; - setnilvalue(L1->top++); // `function' entry for this `ci' - L1->base = L1->ci->base = L1->top; - L1->ci->top = L1->top + LUA_MINSTACK; -} - -static void freestack(lua_State* L, lua_State* L1) -{ - luaM_freearray(L, L1->base_ci, L1->size_ci, CallInfo, L1->memcat); - luaM_freearray(L, L1->stack, L1->stacksize, TValue, L1->memcat); -} - -/* -** open parts that may cause memory-allocation errors -*/ -static void f_luaopen(lua_State* L, void* ud) -{ - global_State* g = L->global; - stack_init(L, L); // init stack - L->gt = luaH_new(L, 0, 2); // table of globals - sethvalue(L, registry(L), luaH_new(L, 0, 2)); // registry - luaS_resize(L, LUA_MINSTRTABSIZE); // initial size of string table - luaT_init(L); - luaS_fix(luaS_newliteral(L, LUA_MEMERRMSG)); // pin to make sure we can always throw this error - luaS_fix(luaS_newliteral(L, LUA_ERRERRMSG)); // pin to make sure we can always throw this error - g->GCthreshold = 4 * g->totalbytes; -} - -static void preinit_state(lua_State* L, global_State* g) -{ - L->global = g; - L->stack = NULL; - L->stacksize = 0; - L->gt = NULL; - L->openupval = NULL; - L->size_ci = 0; - L->nCcalls = L->baseCcalls = 0; - L->status = 0; - L->base_ci = L->ci = NULL; - L->namecall = NULL; - L->cachedslot = 0; - L->singlestep = false; - L->isactive = false; - L->activememcat = 0; - L->userdata = NULL; -} - -static void close_state(lua_State* L) -{ - global_State* g = L->global; - luaF_close(L, L->stack); // close all upvalues for this thread - luaC_freeall(L); // collect all objects - LUAU_ASSERT(g->strt.nuse == 0); - luaM_freearray(L, L->global->strt.hash, L->global->strt.size, TString*, 0); - freestack(L, L); - for (int i = 0; i < LUA_SIZECLASSES; i++) - { - LUAU_ASSERT(g->freepages[i] == NULL); - LUAU_ASSERT(g->freegcopages[i] == NULL); - } - LUAU_ASSERT(g->allgcopages == NULL); - LUAU_ASSERT(g->totalbytes == sizeof(LG)); - LUAU_ASSERT(g->memcatbytes[0] == sizeof(LG)); - for (int i = 1; i < LUA_MEMORY_CATEGORIES; i++) - LUAU_ASSERT(g->memcatbytes[i] == 0); - - if (L->global->ecb.close) - L->global->ecb.close(L); - - (*g->frealloc)(g->ud, L, sizeof(LG), 0); -} - -lua_State* luaE_newthread(lua_State* L) -{ - lua_State* L1 = luaM_newgco(L, lua_State, sizeof(lua_State), L->activememcat); - luaC_init(L, L1, LUA_TTHREAD); - preinit_state(L1, L->global); - L1->activememcat = L->activememcat; // inherit the active memory category - stack_init(L1, L); // init stack - L1->gt = L->gt; // share table of globals - L1->singlestep = L->singlestep; - LUAU_ASSERT(iswhite(obj2gco(L1))); - return L1; -} - -void luaE_freethread(lua_State* L, lua_State* L1, lua_Page* page) -{ - global_State* g = L->global; - if (g->cb.userthread) - g->cb.userthread(NULL, L1); - freestack(L, L1); - luaM_freegco(L, L1, sizeof(lua_State), L1->memcat, page); -} - -void lua_resetthread(lua_State* L) -{ - // close upvalues before clearing anything - luaF_close(L, L->stack); - // clear call frames - CallInfo* ci = L->base_ci; - ci->func = L->stack; - ci->base = ci->func + 1; - ci->top = ci->base + LUA_MINSTACK; - setnilvalue(ci->func); - L->ci = ci; - if (L->size_ci != BASIC_CI_SIZE) - luaD_reallocCI(L, BASIC_CI_SIZE); - // clear thread state - L->status = LUA_OK; - L->base = L->ci->base; - L->top = L->ci->base; - L->nCcalls = L->baseCcalls = 0; - // clear thread stack - if (L->stacksize != BASIC_STACK_SIZE + EXTRA_STACK) - luaD_reallocstack(L, BASIC_STACK_SIZE); - for (int i = 0; i < L->stacksize; i++) - setnilvalue(L->stack + i); -} - -int lua_isthreadreset(lua_State* L) -{ - return L->ci == L->base_ci && L->base == L->top && L->status == LUA_OK; -} - -lua_State* lua_newstate(lua_Alloc f, void* ud) -{ - int i; - lua_State* L; - global_State* g; - void* l = (*f)(ud, NULL, 0, sizeof(LG)); - if (l == NULL) - return NULL; - L = (lua_State*)l; - g = &((LG*)L)->g; - L->tt = LUA_TTHREAD; - L->marked = g->currentwhite = bit2mask(WHITE0BIT, FIXEDBIT); - L->memcat = 0; - preinit_state(L, g); - g->frealloc = f; - g->ud = ud; - g->mainthread = L; - g->uvhead.u.open.prev = &g->uvhead; - g->uvhead.u.open.next = &g->uvhead; - g->GCthreshold = 0; // mark it as unfinished state - g->registryfree = 0; - g->errorjmp = NULL; - g->rngstate = 0; - g->ptrenckey[0] = 1; - g->ptrenckey[1] = 0; - g->ptrenckey[2] = 0; - g->ptrenckey[3] = 0; - g->strt.size = 0; - g->strt.nuse = 0; - g->strt.hash = NULL; - setnilvalue(&g->pseudotemp); - setnilvalue(registry(L)); - g->gcstate = GCSpause; - g->gray = NULL; - g->grayagain = NULL; - g->weak = NULL; - g->totalbytes = sizeof(LG); - g->gcgoal = LUAI_GCGOAL; - g->gcstepmul = LUAI_GCSTEPMUL; - g->gcstepsize = LUAI_GCSTEPSIZE << 10; - for (i = 0; i < LUA_SIZECLASSES; i++) - { - g->freepages[i] = NULL; - g->freegcopages[i] = NULL; - } - g->allgcopages = NULL; - g->sweepgcopage = NULL; - for (i = 0; i < LUA_T_COUNT; i++) - g->mt[i] = NULL; - for (i = 0; i < LUA_UTAG_LIMIT; i++) - g->udatagc[i] = NULL; - for (i = 0; i < LUA_LUTAG_LIMIT; i++) - g->lightuserdataname[i] = NULL; - for (i = 0; i < LUA_MEMORY_CATEGORIES; i++) - g->memcatbytes[i] = 0; - - g->memcatbytes[0] = sizeof(LG); - - g->cb = lua_Callbacks(); - - g->ecb = lua_ExecutionCallbacks(); - - g->gcstats = GCStats(); - -#ifdef LUAI_GCMETRICS - g->gcmetrics = GCMetrics(); -#endif - - if (luaD_rawrunprotected(L, f_luaopen, NULL) != 0) - { - // memory allocation error: free partial state - close_state(L); - L = NULL; - } - return L; -} - -void lua_close(lua_State* L) -{ - L = L->global->mainthread; // only the main thread can be closed - luaF_close(L, L->stack); // close all upvalues for this thread - close_state(L); -} diff --git a/lib/luau/VM/src/lstate.h b/lib/luau/VM/src/lstate.h deleted file mode 100644 index 2c6d35d..0000000 --- a/lib/luau/VM/src/lstate.h +++ /dev/null @@ -1,304 +0,0 @@ -// This file is part of the Luau programming language and is licensed under MIT License; see LICENSE.txt for details -// This code is based on Lua 5.x implementation licensed under MIT License; see lua_LICENSE.txt for details -#pragma once - -#include "lobject.h" -#include "ltm.h" - -// registry -#define registry(L) (&L->global->registry) - -// extra stack space to handle TM calls and some other extras -#define EXTRA_STACK 5 - -#define BASIC_CI_SIZE 8 - -#define BASIC_STACK_SIZE (2 * LUA_MINSTACK) - -// clang-format off -typedef struct stringtable -{ - - TString** hash; - uint32_t nuse; // number of elements - int size; -} stringtable; -// clang-format on - -/* -** informations about a call -** -** the general Lua stack frame structure is as follows: -** - each function gets a stack frame, with function "registers" being stack slots on the frame -** - function arguments are associated with registers 0+ -** - function locals and temporaries follow after; usually locals are a consecutive block per scope, and temporaries are allocated after this, but -*this is up to the compiler -** -** when function doesn't have varargs, the stack layout is as follows: -** ^ (func) ^^ [fixed args] [locals + temporaries] -** where ^ is the 'func' pointer in CallInfo struct, and ^^ is the 'base' pointer (which is what registers are relative to) -** -** when function *does* have varargs, the stack layout is more complex - the runtime has to copy the fixed arguments so that the 0+ addressing still -*works as follows: -** ^ (func) [fixed args] [varargs] ^^ [fixed args] [locals + temporaries] -** -** computing the sizes of these individual blocks works as follows: -** - the number of fixed args is always matching the `numparams` in a function's Proto object; runtime adds `nil` during the call execution as -*necessary -** - the number of variadic args can be computed by evaluating (ci->base - ci->func - 1 - numparams) -** -** the CallInfo structures are allocated as an array, with each subsequent call being *appended* to this array (so if f calls g, CallInfo for g -*immediately follows CallInfo for f) -** the `nresults` field in CallInfo is set by the caller to tell the function how many arguments the caller is expecting on the stack after the -*function returns -** the `flags` field in CallInfo contains internal execution flags that are important for pcall/etc, see LUA_CALLINFO_* -*/ -// clang-format off -typedef struct CallInfo -{ - - StkId base; // base for this function - StkId func; // function index in the stack - StkId top; // top for this function - const Instruction* savedpc; - - int nresults; // expected number of results from this function - unsigned int flags; // call frame flags, see LUA_CALLINFO_* -} CallInfo; -// clang-format on - -#define LUA_CALLINFO_RETURN (1 << 0) // should the interpreter return after returning from this callinfo? first frame must have this set -#define LUA_CALLINFO_HANDLE (1 << 1) // should the error thrown during execution get handled by continuation from this callinfo? func must be C -#define LUA_CALLINFO_NATIVE (1 << 2) // should this function be executed using execution callback for native code - -#define curr_func(L) (clvalue(L->ci->func)) -#define ci_func(ci) (clvalue((ci)->func)) -#define f_isLua(ci) (!ci_func(ci)->isC) -#define isLua(ci) (ttisfunction((ci)->func) && f_isLua(ci)) - -struct GCStats -{ - // data for proportional-integral controller of heap trigger value - int32_t triggerterms[32] = {0}; - uint32_t triggertermpos = 0; - int32_t triggerintegral = 0; - - size_t atomicstarttotalsizebytes = 0; - size_t endtotalsizebytes = 0; - size_t heapgoalsizebytes = 0; - - double starttimestamp = 0; - double atomicstarttimestamp = 0; - double endtimestamp = 0; -}; - -#ifdef LUAI_GCMETRICS -struct GCCycleMetrics -{ - size_t starttotalsizebytes = 0; - size_t heaptriggersizebytes = 0; - - double pausetime = 0.0; // time from end of the last cycle to the start of a new one - - double starttimestamp = 0.0; - double endtimestamp = 0.0; - - double marktime = 0.0; - double markassisttime = 0.0; - double markmaxexplicittime = 0.0; - size_t markexplicitsteps = 0; - size_t markwork = 0; - - double atomicstarttimestamp = 0.0; - size_t atomicstarttotalsizebytes = 0; - double atomictime = 0.0; - - // specific atomic stage parts - double atomictimeupval = 0.0; - double atomictimeweak = 0.0; - double atomictimegray = 0.0; - double atomictimeclear = 0.0; - - double sweeptime = 0.0; - double sweepassisttime = 0.0; - double sweepmaxexplicittime = 0.0; - size_t sweepexplicitsteps = 0; - size_t sweepwork = 0; - - size_t assistwork = 0; - size_t explicitwork = 0; - - size_t propagatework = 0; - size_t propagateagainwork = 0; - - size_t endtotalsizebytes = 0; -}; - -struct GCMetrics -{ - double stepexplicittimeacc = 0.0; - double stepassisttimeacc = 0.0; - - // when cycle is completed, last cycle values are updated - uint64_t completedcycles = 0; - - GCCycleMetrics lastcycle; - GCCycleMetrics currcycle; -}; -#endif - -// Callbacks that can be used to to redirect code execution from Luau bytecode VM to a custom implementation (AoT/JiT/sandboxing/...) -struct lua_ExecutionCallbacks -{ - void* context; - void (*close)(lua_State* L); // called when global VM state is closed - void (*destroy)(lua_State* L, Proto* proto); // called when function is destroyed - int (*enter)(lua_State* L, Proto* proto); // called when function is about to start/resume (when execdata is present), return 0 to exit VM -}; - -/* -** `global state', shared by all threads of this state -*/ -// clang-format off -typedef struct global_State -{ - stringtable strt; // hash table for strings - - - lua_Alloc frealloc; // function to reallocate memory - void* ud; // auxiliary data to `frealloc' - - - uint8_t currentwhite; - uint8_t gcstate; // state of garbage collector - - - GCObject* gray; // list of gray objects - GCObject* grayagain; // list of objects to be traversed atomically - GCObject* weak; // list of weak tables (to be cleared) - - - size_t GCthreshold; // when totalbytes > GCthreshold, run GC step - size_t totalbytes; // number of bytes currently allocated - int gcgoal; // see LUAI_GCGOAL - int gcstepmul; // see LUAI_GCSTEPMUL - int gcstepsize; // see LUAI_GCSTEPSIZE - - struct lua_Page* freepages[LUA_SIZECLASSES]; // free page linked list for each size class for non-collectable objects - struct lua_Page* freegcopages[LUA_SIZECLASSES]; // free page linked list for each size class for collectable objects - struct lua_Page* allgcopages; // page linked list with all pages for all classes - struct lua_Page* sweepgcopage; // position of the sweep in `allgcopages' - - size_t memcatbytes[LUA_MEMORY_CATEGORIES]; // total amount of memory used by each memory category - - - struct lua_State* mainthread; - UpVal uvhead; // head of double-linked list of all open upvalues - struct Table* mt[LUA_T_COUNT]; // metatables for basic types - TString* ttname[LUA_T_COUNT]; // names for basic types - TString* tmname[TM_N]; // array with tag-method names - - TValue pseudotemp; // storage for temporary values used in pseudo2addr - - TValue registry; // registry table, used by lua_ref and LUA_REGISTRYINDEX - int registryfree; // next free slot in registry - - struct lua_jmpbuf* errorjmp; // jump buffer data for longjmp-style error handling - - uint64_t rngstate; // PCG random number generator state - uint64_t ptrenckey[4]; // pointer encoding key for display - - lua_Callbacks cb; - - lua_ExecutionCallbacks ecb; - - void (*udatagc[LUA_UTAG_LIMIT])(lua_State*, void*); // for each userdata tag, a gc callback to be called immediately before freeing memory - - TString* lightuserdataname[LUA_LUTAG_LIMIT]; // names for tagged lightuserdata - - GCStats gcstats; - -#ifdef LUAI_GCMETRICS - GCMetrics gcmetrics; -#endif -} global_State; -// clang-format on - -/* -** `per thread' state -*/ -// clang-format off -struct lua_State -{ - CommonHeader; - uint8_t status; - - uint8_t activememcat; // memory category that is used for new GC object allocations - - bool isactive; // thread is currently executing, stack may be mutated without barriers - bool singlestep; // call debugstep hook after each instruction - - - StkId top; // first free slot in the stack - StkId base; // base of current function - global_State* global; - CallInfo* ci; // call info for current function - StkId stack_last; // last free slot in the stack - StkId stack; // stack base - - - CallInfo* end_ci; // points after end of ci array - CallInfo* base_ci; // array of CallInfo's - - - int stacksize; - int size_ci; // size of array `base_ci' - - - unsigned short nCcalls; // number of nested C calls - unsigned short baseCcalls; // nested C calls when resuming coroutine - - int cachedslot; // when table operations or INDEX/NEWINDEX is invoked from Luau, what is the expected slot for lookup? - - - Table* gt; // table of globals - UpVal* openupval; // list of open upvalues in this stack - GCObject* gclist; - - TString* namecall; // when invoked from Luau using NAMECALL, what method do we need to invoke? - - void* userdata; -}; -// clang-format on - -/* -** Union of all collectible objects -*/ -union GCObject -{ - GCheader gch; - struct TString ts; - struct Udata u; - struct Closure cl; - struct Table h; - struct Proto p; - struct UpVal uv; - struct lua_State th; // thread - struct Buffer buf; -}; - -// macros to convert a GCObject into a specific value -#define gco2ts(o) check_exp((o)->gch.tt == LUA_TSTRING, &((o)->ts)) -#define gco2u(o) check_exp((o)->gch.tt == LUA_TUSERDATA, &((o)->u)) -#define gco2cl(o) check_exp((o)->gch.tt == LUA_TFUNCTION, &((o)->cl)) -#define gco2h(o) check_exp((o)->gch.tt == LUA_TTABLE, &((o)->h)) -#define gco2p(o) check_exp((o)->gch.tt == LUA_TPROTO, &((o)->p)) -#define gco2uv(o) check_exp((o)->gch.tt == LUA_TUPVAL, &((o)->uv)) -#define gco2th(o) check_exp((o)->gch.tt == LUA_TTHREAD, &((o)->th)) -#define gco2buf(o) check_exp((o)->gch.tt == LUA_TBUFFER, &((o)->buf)) - -// macro to convert any Lua object into a GCObject -#define obj2gco(v) check_exp(iscollectable(v), cast_to(GCObject*, (v) + 0)) - -LUAI_FUNC lua_State* luaE_newthread(lua_State* L); -LUAI_FUNC void luaE_freethread(lua_State* L, lua_State* L1, struct lua_Page* page); diff --git a/lib/luau/VM/src/lstring.cpp b/lib/luau/VM/src/lstring.cpp deleted file mode 100644 index e57f6c2..0000000 --- a/lib/luau/VM/src/lstring.cpp +++ /dev/null @@ -1,193 +0,0 @@ -// This file is part of the Luau programming language and is licensed under MIT License; see LICENSE.txt for details -// This code is based on Lua 5.x implementation licensed under MIT License; see lua_LICENSE.txt for details -#include "lstring.h" - -#include "lgc.h" -#include "lmem.h" - -#include - -unsigned int luaS_hash(const char* str, size_t len) -{ - // Note that this hashing algorithm is replicated in BytecodeBuilder.cpp, BytecodeBuilder::getStringHash - unsigned int a = 0, b = 0; - unsigned int h = unsigned(len); - - // hash prefix in 12b chunks (using aligned reads) with ARX based hash (LuaJIT v2.1, lookup3) - // note that we stop at length<32 to maintain compatibility with Lua 5.1 - while (len >= 32) - { -#define rol(x, s) ((x >> s) | (x << (32 - s))) -#define mix(u, v, w) a ^= h, a -= rol(h, u), b ^= a, b -= rol(a, v), h ^= b, h -= rol(b, w) - - // should compile into fast unaligned reads - uint32_t block[3]; - memcpy(block, str, 12); - - a += block[0]; - b += block[1]; - h += block[2]; - mix(14, 11, 25); - str += 12; - len -= 12; - -#undef mix -#undef rol - } - - // original Lua 5.1 hash for compatibility (exact match when len<32) - for (size_t i = len; i > 0; --i) - h ^= (h << 5) + (h >> 2) + (uint8_t)str[i - 1]; - - return h; -} - -void luaS_resize(lua_State* L, int newsize) -{ - TString** newhash = luaM_newarray(L, newsize, TString*, 0); - stringtable* tb = &L->global->strt; - for (int i = 0; i < newsize; i++) - newhash[i] = NULL; - // rehash - for (int i = 0; i < tb->size; i++) - { - TString* p = tb->hash[i]; - while (p) - { // for each node in the list - TString* next = p->next; // save next - unsigned int h = p->hash; - int h1 = lmod(h, newsize); // new position - LUAU_ASSERT(cast_int(h % newsize) == lmod(h, newsize)); - p->next = newhash[h1]; // chain it - newhash[h1] = p; - p = next; - } - } - luaM_freearray(L, tb->hash, tb->size, TString*, 0); - tb->size = newsize; - tb->hash = newhash; -} - -static TString* newlstr(lua_State* L, const char* str, size_t l, unsigned int h) -{ - if (l > MAXSSIZE) - luaM_toobig(L); - - TString* ts = luaM_newgco(L, TString, sizestring(l), L->activememcat); - luaC_init(L, ts, LUA_TSTRING); - ts->atom = ATOM_UNDEF; - ts->hash = h; - ts->len = unsigned(l); - - memcpy(ts->data, str, l); - ts->data[l] = '\0'; // ending 0 - - stringtable* tb = &L->global->strt; - h = lmod(h, tb->size); - ts->next = tb->hash[h]; // chain new entry - tb->hash[h] = ts; - - tb->nuse++; - if (tb->nuse > cast_to(uint32_t, tb->size) && tb->size <= INT_MAX / 2) - luaS_resize(L, tb->size * 2); // too crowded - - return ts; -} - -TString* luaS_bufstart(lua_State* L, size_t size) -{ - if (size > MAXSSIZE) - luaM_toobig(L); - - TString* ts = luaM_newgco(L, TString, sizestring(size), L->activememcat); - luaC_init(L, ts, LUA_TSTRING); - ts->atom = ATOM_UNDEF; - ts->hash = 0; // computed in luaS_buffinish - ts->len = unsigned(size); - - ts->next = NULL; - - return ts; -} - -TString* luaS_buffinish(lua_State* L, TString* ts) -{ - unsigned int h = luaS_hash(ts->data, ts->len); - stringtable* tb = &L->global->strt; - int bucket = lmod(h, tb->size); - - // search if we already have this string in the hash table - for (TString* el = tb->hash[bucket]; el != NULL; el = el->next) - { - if (el->len == ts->len && memcmp(el->data, ts->data, ts->len) == 0) - { - // string may be dead - if (isdead(L->global, obj2gco(el))) - changewhite(obj2gco(el)); - - return el; - } - } - - LUAU_ASSERT(ts->next == NULL); - - ts->hash = h; - ts->data[ts->len] = '\0'; // ending 0 - ts->atom = ATOM_UNDEF; - ts->next = tb->hash[bucket]; // chain new entry - tb->hash[bucket] = ts; - - tb->nuse++; - if (tb->nuse > cast_to(uint32_t, tb->size) && tb->size <= INT_MAX / 2) - luaS_resize(L, tb->size * 2); // too crowded - - return ts; -} - -TString* luaS_newlstr(lua_State* L, const char* str, size_t l) -{ - unsigned int h = luaS_hash(str, l); - for (TString* el = L->global->strt.hash[lmod(h, L->global->strt.size)]; el != NULL; el = el->next) - { - if (el->len == l && (memcmp(str, getstr(el), l) == 0)) - { - // string may be dead - if (isdead(L->global, obj2gco(el))) - changewhite(obj2gco(el)); - return el; - } - } - return newlstr(L, str, l, h); // not found -} - -static bool unlinkstr(lua_State* L, TString* ts) -{ - global_State* g = L->global; - - TString** p = &g->strt.hash[lmod(ts->hash, g->strt.size)]; - - while (TString* curr = *p) - { - if (curr == ts) - { - *p = curr->next; - return true; - } - else - { - p = &curr->next; - } - } - - return false; -} - -void luaS_free(lua_State* L, TString* ts, lua_Page* page) -{ - if (unlinkstr(L, ts)) - L->global->strt.nuse--; - else - LUAU_ASSERT(ts->next == NULL); // orphaned string buffer - - luaM_freegco(L, ts, sizestring(ts->len), ts->memcat, page); -} diff --git a/lib/luau/VM/src/lstring.h b/lib/luau/VM/src/lstring.h deleted file mode 100644 index 41f9df9..0000000 --- a/lib/luau/VM/src/lstring.h +++ /dev/null @@ -1,29 +0,0 @@ -// This file is part of the Luau programming language and is licensed under MIT License; see LICENSE.txt for details -// This code is based on Lua 5.x implementation licensed under MIT License; see lua_LICENSE.txt for details -#pragma once - -#include "lobject.h" -#include "lstate.h" - -// string size limit -#define MAXSSIZE (1 << 30) - -// string atoms are not defined by default; the storage is 16-bit integer -#define ATOM_UNDEF -32768 - -#define sizestring(len) (offsetof(TString, data) + len + 1) - -#define luaS_new(L, s) (luaS_newlstr(L, s, strlen(s))) -#define luaS_newliteral(L, s) (luaS_newlstr(L, "" s, (sizeof(s) / sizeof(char)) - 1)) - -#define luaS_fix(s) l_setbit((s)->marked, FIXEDBIT) - -LUAI_FUNC unsigned int luaS_hash(const char* str, size_t len); - -LUAI_FUNC void luaS_resize(lua_State* L, int newsize); - -LUAI_FUNC TString* luaS_newlstr(lua_State* L, const char* str, size_t l); -LUAI_FUNC void luaS_free(lua_State* L, TString* ts, struct lua_Page* page); - -LUAI_FUNC TString* luaS_bufstart(lua_State* L, size_t size); -LUAI_FUNC TString* luaS_buffinish(lua_State* L, TString* ts); diff --git a/lib/luau/VM/src/lstrlib.cpp b/lib/luau/VM/src/lstrlib.cpp deleted file mode 100644 index 6fa0f53..0000000 --- a/lib/luau/VM/src/lstrlib.cpp +++ /dev/null @@ -1,1665 +0,0 @@ -// This file is part of the Luau programming language and is licensed under MIT License; see LICENSE.txt for details -// This code is based on Lua 5.x implementation licensed under MIT License; see lua_LICENSE.txt for details -#include "lualib.h" - -#include "lstring.h" - -#include -#include -#include - -// macro to `unsign' a character -#define uchar(c) ((unsigned char)(c)) - -static int str_len(lua_State* L) -{ - size_t l; - luaL_checklstring(L, 1, &l); - lua_pushinteger(L, (int)l); - return 1; -} - -static int posrelat(int pos, size_t len) -{ - // relative string position: negative means back from end - if (pos < 0) - pos += (int)len + 1; - return (pos >= 0) ? pos : 0; -} - -static int str_sub(lua_State* L) -{ - size_t l; - const char* s = luaL_checklstring(L, 1, &l); - int start = posrelat(luaL_checkinteger(L, 2), l); - int end = posrelat(luaL_optinteger(L, 3, -1), l); - if (start < 1) - start = 1; - if (end > (int)l) - end = (int)l; - if (start <= end) - lua_pushlstring(L, s + start - 1, end - start + 1); - else - lua_pushliteral(L, ""); - return 1; -} - -static int str_reverse(lua_State* L) -{ - size_t l; - const char* s = luaL_checklstring(L, 1, &l); - luaL_Strbuf b; - char* ptr = luaL_buffinitsize(L, &b, l); - while (l--) - *ptr++ = s[l]; - luaL_pushresultsize(&b, ptr - b.p); - return 1; -} - -static int str_lower(lua_State* L) -{ - size_t l; - const char* s = luaL_checklstring(L, 1, &l); - luaL_Strbuf b; - char* ptr = luaL_buffinitsize(L, &b, l); - for (size_t i = 0; i < l; i++) - *ptr++ = tolower(uchar(s[i])); - luaL_pushresultsize(&b, l); - return 1; -} - -static int str_upper(lua_State* L) -{ - size_t l; - const char* s = luaL_checklstring(L, 1, &l); - luaL_Strbuf b; - char* ptr = luaL_buffinitsize(L, &b, l); - for (size_t i = 0; i < l; i++) - *ptr++ = toupper(uchar(s[i])); - luaL_pushresultsize(&b, l); - return 1; -} - -static int str_rep(lua_State* L) -{ - size_t l; - const char* s = luaL_checklstring(L, 1, &l); - int n = luaL_checkinteger(L, 2); - - if (n <= 0) - { - lua_pushliteral(L, ""); - return 1; - } - - if (l > MAXSSIZE / (size_t)n) // may overflow? - luaL_error(L, "resulting string too large"); - - luaL_Strbuf b; - char* ptr = luaL_buffinitsize(L, &b, l * n); - - const char* start = ptr; - - size_t left = l * n; - size_t step = l; - - memcpy(ptr, s, l); - ptr += l; - left -= l; - - // use the increasing 'pattern' inside our target buffer to fill the next part - while (step < left) - { - memcpy(ptr, start, step); - ptr += step; - left -= step; - step <<= 1; - } - - // fill tail - memcpy(ptr, start, left); - ptr += left; - - luaL_pushresultsize(&b, l * n); - - return 1; -} - -static int str_byte(lua_State* L) -{ - size_t l; - const char* s = luaL_checklstring(L, 1, &l); - int posi = posrelat(luaL_optinteger(L, 2, 1), l); - int pose = posrelat(luaL_optinteger(L, 3, posi), l); - int n, i; - if (posi <= 0) - posi = 1; - if ((size_t)pose > l) - pose = (int)l; - if (posi > pose) - return 0; // empty interval; return no values - n = (int)(pose - posi + 1); - if (posi + n <= pose) // overflow? - luaL_error(L, "string slice too long"); - luaL_checkstack(L, n, "string slice too long"); - for (i = 0; i < n; i++) - lua_pushinteger(L, uchar(s[posi + i - 1])); - return n; -} - -static int str_char(lua_State* L) -{ - int n = lua_gettop(L); // number of arguments - - luaL_Strbuf b; - char* ptr = luaL_buffinitsize(L, &b, n); - - for (int i = 1; i <= n; i++) - { - int c = luaL_checkinteger(L, i); - luaL_argcheck(L, uchar(c) == c, i, "invalid value"); - - *ptr++ = uchar(c); - } - luaL_pushresultsize(&b, n); - return 1; -} - -/* -** {====================================================== -** PATTERN MATCHING -** ======================================================= -*/ - -#define CAP_UNFINISHED (-1) -#define CAP_POSITION (-2) - -typedef struct MatchState -{ - int matchdepth; // control for recursive depth (to avoid C stack overflow) - const char* src_init; // init of source string - const char* src_end; // end ('\0') of source string - const char* p_end; // end ('\0') of pattern - lua_State* L; - int level; // total number of captures (finished or unfinished) - struct - { - const char* init; - ptrdiff_t len; - } capture[LUA_MAXCAPTURES]; -} MatchState; - -// recursive function -static const char* match(MatchState* ms, const char* s, const char* p); - -#define L_ESC '%' -#define SPECIALS "^$*+?.([%-" - -static int check_capture(MatchState* ms, int l) -{ - l -= '1'; - if (l < 0 || l >= ms->level || ms->capture[l].len == CAP_UNFINISHED) - luaL_error(ms->L, "invalid capture index %%%d", l + 1); - return l; -} - -static int capture_to_close(MatchState* ms) -{ - int level = ms->level; - for (level--; level >= 0; level--) - if (ms->capture[level].len == CAP_UNFINISHED) - return level; - luaL_error(ms->L, "invalid pattern capture"); -} - -static const char* classend(MatchState* ms, const char* p) -{ - switch (*p++) - { - case L_ESC: - { - if (p == ms->p_end) - luaL_error(ms->L, "malformed pattern (ends with '%%')"); - return p + 1; - } - case '[': - { - if (*p == '^') - p++; - do - { // look for a `]' - if (p == ms->p_end) - luaL_error(ms->L, "malformed pattern (missing ']')"); - if (*(p++) == L_ESC && p < ms->p_end) - p++; // skip escapes (e.g. `%]') - } while (*p != ']'); - return p + 1; - } - default: - { - return p; - } - } -} - -static int match_class(int c, int cl) -{ - int res; - switch (tolower(cl)) - { - case 'a': - res = isalpha(c); - break; - case 'c': - res = iscntrl(c); - break; - case 'd': - res = isdigit(c); - break; - case 'g': - res = isgraph(c); - break; - case 'l': - res = islower(c); - break; - case 'p': - res = ispunct(c); - break; - case 's': - res = isspace(c); - break; - case 'u': - res = isupper(c); - break; - case 'w': - res = isalnum(c); - break; - case 'x': - res = isxdigit(c); - break; - case 'z': - res = (c == 0); - break; // deprecated option - default: - return (cl == c); - } - return (islower(cl) ? res : !res); -} - -static int matchbracketclass(int c, const char* p, const char* ec) -{ - int sig = 1; - if (*(p + 1) == '^') - { - sig = 0; - p++; // skip the `^' - } - while (++p < ec) - { - if (*p == L_ESC) - { - p++; - if (match_class(c, uchar(*p))) - return sig; - } - else if ((*(p + 1) == '-') && (p + 2 < ec)) - { - p += 2; - if (uchar(*(p - 2)) <= c && c <= uchar(*p)) - return sig; - } - else if (uchar(*p) == c) - return sig; - } - return !sig; -} - -static int singlematch(MatchState* ms, const char* s, const char* p, const char* ep) -{ - if (s >= ms->src_end) - return 0; - else - { - int c = uchar(*s); - switch (*p) - { - case '.': - return 1; // matches any char - case L_ESC: - return match_class(c, uchar(*(p + 1))); - case '[': - return matchbracketclass(c, p, ep - 1); - default: - return (uchar(*p) == c); - } - } -} - -static const char* matchbalance(MatchState* ms, const char* s, const char* p) -{ - if (p >= ms->p_end - 1) - luaL_error(ms->L, "malformed pattern (missing arguments to '%%b')"); - if (*s != *p) - return NULL; - else - { - int b = *p; - int e = *(p + 1); - int cont = 1; - while (++s < ms->src_end) - { - if (*s == e) - { - if (--cont == 0) - return s + 1; - } - else if (*s == b) - cont++; - } - } - return NULL; // string ends out of balance -} - -static const char* max_expand(MatchState* ms, const char* s, const char* p, const char* ep) -{ - ptrdiff_t i = 0; // counts maximum expand for item - while (singlematch(ms, s + i, p, ep)) - i++; - // keeps trying to match with the maximum repetitions - while (i >= 0) - { - const char* res = match(ms, (s + i), ep + 1); - if (res) - return res; - i--; // else didn't match; reduce 1 repetition to try again - } - return NULL; -} - -static const char* min_expand(MatchState* ms, const char* s, const char* p, const char* ep) -{ - for (;;) - { - const char* res = match(ms, s, ep + 1); - if (res != NULL) - return res; - else if (singlematch(ms, s, p, ep)) - s++; // try with one more repetition - else - return NULL; - } -} - -static const char* start_capture(MatchState* ms, const char* s, const char* p, int what) -{ - const char* res; - int level = ms->level; - if (level >= LUA_MAXCAPTURES) - luaL_error(ms->L, "too many captures"); - ms->capture[level].init = s; - ms->capture[level].len = what; - ms->level = level + 1; - if ((res = match(ms, s, p)) == NULL) // match failed? - ms->level--; // undo capture - return res; -} - -static const char* end_capture(MatchState* ms, const char* s, const char* p) -{ - int l = capture_to_close(ms); - const char* res; - ms->capture[l].len = s - ms->capture[l].init; // close capture - if ((res = match(ms, s, p)) == NULL) // match failed? - ms->capture[l].len = CAP_UNFINISHED; // undo capture - return res; -} - -static const char* match_capture(MatchState* ms, const char* s, int l) -{ - size_t len; - l = check_capture(ms, l); - len = ms->capture[l].len; - if ((size_t)(ms->src_end - s) >= len && memcmp(ms->capture[l].init, s, len) == 0) - return s + len; - else - return NULL; -} - -static const char* match(MatchState* ms, const char* s, const char* p) -{ - if (ms->matchdepth-- == 0) - luaL_error(ms->L, "pattern too complex"); -init: // using goto's to optimize tail recursion - if (p != ms->p_end) - { // end of pattern? - switch (*p) - { - case '(': - { // start capture - if (*(p + 1) == ')') // position capture? - s = start_capture(ms, s, p + 2, CAP_POSITION); - else - s = start_capture(ms, s, p + 1, CAP_UNFINISHED); - break; - } - case ')': - { // end capture - s = end_capture(ms, s, p + 1); - break; - } - case '$': - { - if ((p + 1) != ms->p_end) // is the `$' the last char in pattern? - goto dflt; // no; go to default - s = (s == ms->src_end) ? s : NULL; // check end of string - break; - } - case L_ESC: - { // escaped sequences not in the format class[*+?-]? - switch (*(p + 1)) - { - case 'b': - { // balanced string? - s = matchbalance(ms, s, p + 2); - if (s != NULL) - { - p += 4; - goto init; // return match(ms, s, p + 4); - } // else fail (s == NULL) - break; - } - case 'f': - { // frontier? - const char* ep; - char previous; - p += 2; - if (*p != '[') - luaL_error(ms->L, "missing '[' after '%%f' in pattern"); - ep = classend(ms, p); // points to what is next - previous = (s == ms->src_init) ? '\0' : *(s - 1); - if (!matchbracketclass(uchar(previous), p, ep - 1) && matchbracketclass(uchar(*s), p, ep - 1)) - { - p = ep; - goto init; // return match(ms, s, ep); - } - s = NULL; // match failed - break; - } - case '0': - case '1': - case '2': - case '3': - case '4': - case '5': - case '6': - case '7': - case '8': - case '9': - { // capture results (%0-%9)? - s = match_capture(ms, s, uchar(*(p + 1))); - if (s != NULL) - { - p += 2; - goto init; // return match(ms, s, p + 2) - } - break; - } - default: - goto dflt; - } - break; - } - default: - dflt: - { // pattern class plus optional suffix - const char* ep = classend(ms, p); // points to optional suffix - // does not match at least once? - if (!singlematch(ms, s, p, ep)) - { - if (*ep == '*' || *ep == '?' || *ep == '-') - { // accept empty? - p = ep + 1; - goto init; // return match(ms, s, ep + 1); - } - else // '+' or no suffix - s = NULL; // fail - } - else - { // matched once - switch (*ep) - { // handle optional suffix - case '?': - { // optional - const char* res; - if ((res = match(ms, s + 1, ep + 1)) != NULL) - s = res; - else - { - p = ep + 1; - goto init; // else return match(ms, s, ep + 1); - } - break; - } - case '+': // 1 or more repetitions - s++; // 1 match already done - // go through - case '*': // 0 or more repetitions - s = max_expand(ms, s, p, ep); - break; - case '-': // 0 or more repetitions (minimum) - s = min_expand(ms, s, p, ep); - break; - default: // no suffix - s++; - p = ep; - goto init; // return match(ms, s + 1, ep); - } - } - break; - } - } - } - ms->matchdepth++; - return s; -} - -static const char* lmemfind(const char* s1, size_t l1, const char* s2, size_t l2) -{ - if (l2 == 0) - return s1; // empty strings are everywhere - else if (l2 > l1) - return NULL; // avoids a negative `l1' - else - { - const char* init; // to search for a `*s2' inside `s1' - l2--; // 1st char will be checked by `memchr' - l1 = l1 - l2; // `s2' cannot be found after that - while (l1 > 0 && (init = (const char*)memchr(s1, *s2, l1)) != NULL) - { - init++; // 1st char is already checked - if (memcmp(init, s2 + 1, l2) == 0) - return init - 1; - else - { // correct `l1' and `s1' to try again - l1 -= init - s1; - s1 = init; - } - } - return NULL; // not found - } -} - -static void push_onecapture(MatchState* ms, int i, const char* s, const char* e) -{ - if (i >= ms->level) - { - if (i == 0) // ms->level == 0, too - lua_pushlstring(ms->L, s, e - s); // add whole match - else - luaL_error(ms->L, "invalid capture index"); - } - else - { - ptrdiff_t l = ms->capture[i].len; - if (l == CAP_UNFINISHED) - luaL_error(ms->L, "unfinished capture"); - if (l == CAP_POSITION) - lua_pushinteger(ms->L, (int)(ms->capture[i].init - ms->src_init) + 1); - else - lua_pushlstring(ms->L, ms->capture[i].init, l); - } -} - -static int push_captures(MatchState* ms, const char* s, const char* e) -{ - int i; - int nlevels = (ms->level == 0 && s) ? 1 : ms->level; - luaL_checkstack(ms->L, nlevels, "too many captures"); - for (i = 0; i < nlevels; i++) - push_onecapture(ms, i, s, e); - return nlevels; // number of strings pushed -} - -// check whether pattern has no special characters -static int nospecials(const char* p, size_t l) -{ - size_t upto = 0; - do - { - if (strpbrk(p + upto, SPECIALS)) - return 0; // pattern has a special character - upto += strlen(p + upto) + 1; // may have more after \0 - } while (upto <= l); - return 1; // no special chars found -} - -static void prepstate(MatchState* ms, lua_State* L, const char* s, size_t ls, const char* p, size_t lp) -{ - ms->L = L; - ms->matchdepth = LUAI_MAXCCALLS; - ms->src_init = s; - ms->src_end = s + ls; - ms->p_end = p + lp; -} - -static void reprepstate(MatchState* ms) -{ - ms->level = 0; - LUAU_ASSERT(ms->matchdepth == LUAI_MAXCCALLS); -} - -static int str_find_aux(lua_State* L, int find) -{ - size_t ls, lp; - const char* s = luaL_checklstring(L, 1, &ls); - const char* p = luaL_checklstring(L, 2, &lp); - int init = posrelat(luaL_optinteger(L, 3, 1), ls); - if (init < 1) - init = 1; - else if (init > (int)ls + 1) - { // start after string's end? - lua_pushnil(L); // cannot find anything - return 1; - } - // explicit request or no special characters? - if (find && (lua_toboolean(L, 4) || nospecials(p, lp))) - { - // do a plain search - const char* s2 = lmemfind(s + init - 1, ls - init + 1, p, lp); - if (s2) - { - lua_pushinteger(L, (int)(s2 - s + 1)); - lua_pushinteger(L, (int)(s2 - s + lp)); - return 2; - } - } - else - { - MatchState ms; - const char* s1 = s + init - 1; - int anchor = (*p == '^'); - if (anchor) - { - p++; - lp--; // skip anchor character - } - prepstate(&ms, L, s, ls, p, lp); - do - { - const char* res; - reprepstate(&ms); - if ((res = match(&ms, s1, p)) != NULL) - { - if (find) - { - lua_pushinteger(L, (int)(s1 - s + 1)); // start - lua_pushinteger(L, (int)(res - s)); // end - return push_captures(&ms, NULL, 0) + 2; - } - else - return push_captures(&ms, s1, res); - } - } while (s1++ < ms.src_end && !anchor); - } - lua_pushnil(L); // not found - return 1; -} - -static int str_find(lua_State* L) -{ - return str_find_aux(L, 1); -} - -static int str_match(lua_State* L) -{ - return str_find_aux(L, 0); -} - -static int gmatch_aux(lua_State* L) -{ - MatchState ms; - size_t ls, lp; - const char* s = lua_tolstring(L, lua_upvalueindex(1), &ls); - const char* p = lua_tolstring(L, lua_upvalueindex(2), &lp); - const char* src; - prepstate(&ms, L, s, ls, p, lp); - for (src = s + (size_t)lua_tointeger(L, lua_upvalueindex(3)); src <= ms.src_end; src++) - { - const char* e; - reprepstate(&ms); - if ((e = match(&ms, src, p)) != NULL) - { - int newstart = (int)(e - s); - if (e == src) - newstart++; // empty match? go at least one position - lua_pushinteger(L, newstart); - lua_replace(L, lua_upvalueindex(3)); - return push_captures(&ms, src, e); - } - } - return 0; // not found -} - -static int gmatch(lua_State* L) -{ - luaL_checkstring(L, 1); - luaL_checkstring(L, 2); - lua_settop(L, 2); - lua_pushinteger(L, 0); - lua_pushcclosure(L, gmatch_aux, NULL, 3); - return 1; -} - -static void add_s(MatchState* ms, luaL_Strbuf* b, const char* s, const char* e) -{ - size_t l, i; - const char* news = lua_tolstring(ms->L, 3, &l); - - luaL_prepbuffsize(b, l); - - for (i = 0; i < l; i++) - { - if (news[i] != L_ESC) - luaL_addchar(b, news[i]); - else - { - i++; // skip ESC - if (!isdigit(uchar(news[i]))) - { - if (news[i] != L_ESC) - luaL_error(ms->L, "invalid use of '%c' in replacement string", L_ESC); - luaL_addchar(b, news[i]); - } - else if (news[i] == '0') - luaL_addlstring(b, s, e - s); - else - { - push_onecapture(ms, news[i] - '1', s, e); - luaL_addvalue(b); // add capture to accumulated result - } - } - } -} - -static void add_value(MatchState* ms, luaL_Strbuf* b, const char* s, const char* e, int tr) -{ - lua_State* L = ms->L; - switch (tr) - { - case LUA_TFUNCTION: - { - int n; - lua_pushvalue(L, 3); - n = push_captures(ms, s, e); - lua_call(L, n, 1); - break; - } - case LUA_TTABLE: - { - push_onecapture(ms, 0, s, e); - lua_gettable(L, 3); - break; - } - default: - { // LUA_TNUMBER or LUA_TSTRING - add_s(ms, b, s, e); - return; - } - } - if (!lua_toboolean(L, -1)) - { // nil or false? - lua_pop(L, 1); - lua_pushlstring(L, s, e - s); // keep original text - } - else if (!lua_isstring(L, -1)) - luaL_error(L, "invalid replacement value (a %s)", luaL_typename(L, -1)); - luaL_addvalue(b); // add result to accumulator -} - -static int str_gsub(lua_State* L) -{ - size_t srcl, lp; - const char* src = luaL_checklstring(L, 1, &srcl); - const char* p = luaL_checklstring(L, 2, &lp); - int tr = lua_type(L, 3); - int max_s = luaL_optinteger(L, 4, (int)srcl + 1); - int anchor = (*p == '^'); - int n = 0; - MatchState ms; - luaL_Strbuf b; - luaL_argexpected(L, tr == LUA_TNUMBER || tr == LUA_TSTRING || tr == LUA_TFUNCTION || tr == LUA_TTABLE, 3, "string/function/table"); - luaL_buffinit(L, &b); - if (anchor) - { - p++; - lp--; // skip anchor character - } - prepstate(&ms, L, src, srcl, p, lp); - while (n < max_s) - { - const char* e; - reprepstate(&ms); - e = match(&ms, src, p); - if (e) - { - n++; - add_value(&ms, &b, src, e, tr); - } - if (e && e > src) // non empty match? - src = e; // skip it - else if (src < ms.src_end) - luaL_addchar(&b, *src++); - else - break; - if (anchor) - break; - } - luaL_addlstring(&b, src, ms.src_end - src); - luaL_pushresult(&b); - lua_pushinteger(L, n); // number of substitutions - return 2; -} - -// }====================================================== - -// valid flags in a format specification -#define FLAGS "-+ #0" -// maximum size of each formatted item (> len(format('%99.99f', -1e308))) -#define MAX_ITEM 512 -// maximum size of each format specification (such as '%-099.99d') -#define MAX_FORMAT 32 - -static void addquoted(lua_State* L, luaL_Strbuf* b, int arg) -{ - size_t l; - const char* s = luaL_checklstring(L, arg, &l); - - luaL_prepbuffsize(b, l + 2); - - luaL_addchar(b, '"'); - while (l--) - { - switch (*s) - { - case '"': - case '\\': - case '\n': - { - luaL_addchar(b, '\\'); - luaL_addchar(b, *s); - break; - } - case '\r': - { - luaL_addlstring(b, "\\r", 2); - break; - } - case '\0': - { - luaL_addlstring(b, "\\000", 4); - break; - } - default: - { - luaL_addchar(b, *s); - break; - } - } - s++; - } - luaL_addchar(b, '"'); -} - -static const char* scanformat(lua_State* L, const char* strfrmt, char* form, size_t* size) -{ - const char* p = strfrmt; - while (*p != '\0' && strchr(FLAGS, *p) != NULL) - p++; // skip flags - if ((size_t)(p - strfrmt) >= sizeof(FLAGS)) - luaL_error(L, "invalid format (repeated flags)"); - if (isdigit(uchar(*p))) - p++; // skip width - if (isdigit(uchar(*p))) - p++; // (2 digits at most) - if (*p == '.') - { - p++; - if (isdigit(uchar(*p))) - p++; // skip precision - if (isdigit(uchar(*p))) - p++; // (2 digits at most) - } - if (isdigit(uchar(*p))) - luaL_error(L, "invalid format (width or precision too long)"); - *(form++) = '%'; - *size = p - strfrmt + 1; - strncpy(form, strfrmt, *size); - form += *size; - *form = '\0'; - return p; -} - -static void addInt64Format(char form[MAX_FORMAT], char formatIndicator, size_t formatItemSize) -{ - LUAU_ASSERT((formatItemSize + 3) <= MAX_FORMAT); - LUAU_ASSERT(form[0] == '%'); - LUAU_ASSERT(form[formatItemSize] != 0); - LUAU_ASSERT(form[formatItemSize + 1] == 0); - form[formatItemSize + 0] = 'l'; - form[formatItemSize + 1] = 'l'; - form[formatItemSize + 2] = formatIndicator; - form[formatItemSize + 3] = 0; -} - -static int str_format(lua_State* L) -{ - int top = lua_gettop(L); - int arg = 1; - size_t sfl; - const char* strfrmt = luaL_checklstring(L, arg, &sfl); - const char* strfrmt_end = strfrmt + sfl; - luaL_Strbuf b; - luaL_buffinit(L, &b); - while (strfrmt < strfrmt_end) - { - if (*strfrmt != L_ESC) - luaL_addchar(&b, *strfrmt++); - else if (*++strfrmt == L_ESC) - luaL_addchar(&b, *strfrmt++); // %% - else if (*strfrmt == '*') - { - strfrmt++; - if (++arg > top) - luaL_error(L, "missing argument #%d", arg); - - luaL_addvalueany(&b, arg); - } - else - { // format item - char form[MAX_FORMAT]; // to store the format (`%...') - char buff[MAX_ITEM]; // to store the formatted item - if (++arg > top) - luaL_error(L, "missing argument #%d", arg); - size_t formatItemSize = 0; - strfrmt = scanformat(L, strfrmt, form, &formatItemSize); - char formatIndicator = *strfrmt++; - switch (formatIndicator) - { - case 'c': - { - snprintf(buff, sizeof(buff), form, (int)luaL_checknumber(L, arg)); - break; - } - case 'd': - case 'i': - { - addInt64Format(form, formatIndicator, formatItemSize); - snprintf(buff, sizeof(buff), form, (long long)luaL_checknumber(L, arg)); - break; - } - case 'o': - case 'u': - case 'x': - case 'X': - { - double argValue = luaL_checknumber(L, arg); - addInt64Format(form, formatIndicator, formatItemSize); - unsigned long long v = (argValue < 0) ? (unsigned long long)(long long)argValue : (unsigned long long)argValue; - snprintf(buff, sizeof(buff), form, v); - break; - } - case 'e': - case 'E': - case 'f': - case 'g': - case 'G': - { - snprintf(buff, sizeof(buff), form, (double)luaL_checknumber(L, arg)); - break; - } - case 'q': - { - addquoted(L, &b, arg); - continue; // skip the 'luaL_addlstring' at the end - } - case 's': - { - size_t l; - const char* s = luaL_checklstring(L, arg, &l); - // no precision and string is too long to be formatted, or no format necessary to begin with - if (form[2] == '\0' || (!strchr(form, '.') && l >= 100)) - { - luaL_addlstring(&b, s, l); - continue; // skip the `luaL_addlstring' at the end - } - else - { - snprintf(buff, sizeof(buff), form, s); - break; - } - } - case '*': - { - // %* is parsed above, so if we got here we must have %...* - luaL_error(L, "'%%*' does not take a form"); - } - default: - { // also treat cases `pnLlh' - luaL_error(L, "invalid option '%%%c' to 'format'", *(strfrmt - 1)); - } - } - luaL_addlstring(&b, buff, strlen(buff)); - } - } - luaL_pushresult(&b); - return 1; -} - -static int str_split(lua_State* L) -{ - size_t haystackLen; - const char* haystack = luaL_checklstring(L, 1, &haystackLen); - size_t needleLen; - const char* needle = luaL_optlstring(L, 2, ",", &needleLen); - - const char* begin = haystack; - const char* end = haystack + haystackLen; - const char* spanStart = begin; - int numMatches = 0; - - lua_createtable(L, 0, 0); - - if (needleLen == 0) - begin++; - - // Don't iterate the last needleLen - 1 bytes of the string - they are - // impossible to be splits and would let us memcmp past the end of the - // buffer. - for (const char* iter = begin; iter <= end - needleLen; iter++) - { - // Use of memcmp here instead of strncmp is so that we allow embedded - // nulls to be used in either of the haystack or the needle strings. - // Most Lua string APIs allow embedded nulls, and this should be no - // exception. - if (memcmp(iter, needle, needleLen) == 0) - { - lua_pushinteger(L, ++numMatches); - lua_pushlstring(L, spanStart, iter - spanStart); - lua_settable(L, -3); - - spanStart = iter + needleLen; - if (needleLen > 0) - iter += needleLen - 1; - } - } - - if (needleLen > 0) - { - lua_pushinteger(L, ++numMatches); - lua_pushlstring(L, spanStart, end - spanStart); - lua_settable(L, -3); - } - - return 1; -} - -/* -** {====================================================== -** PACK/UNPACK -** ======================================================= -*/ - -// value used for padding -#if !defined(LUAL_PACKPADBYTE) -#define LUAL_PACKPADBYTE 0x00 -#endif - -// maximum size for the binary representation of an integer -#define MAXINTSIZE 16 - -// number of bits in a character -#define NB CHAR_BIT - -// mask for one character (NB 1's) -#define MC ((1 << NB) - 1) - -// internal size of integers used for pack/unpack -#define SZINT (int)sizeof(long long) - -// dummy union to get native endianness -static const union -{ - int dummy; - char little; // true iff machine is little endian -} nativeendian = {1}; - -// assume we need to align for double & pointers -#define MAXALIGN 8 - -/* -** Union for serializing floats -*/ -typedef union Ftypes -{ - float f; - double d; - double n; - char buff[5 * sizeof(double)]; // enough for any float type -} Ftypes; - -/* -** information to pack/unpack stuff -*/ -typedef struct Header -{ - lua_State* L; - int islittle; - int maxalign; -} Header; - -/* -** options for pack/unpack -*/ -typedef enum KOption -{ - Kint, // signed integers - Kuint, // unsigned integers - Kfloat, // floating-point numbers - Kchar, // fixed-length strings - Kstring, // strings with prefixed length - Kzstr, // zero-terminated strings - Kpadding, // padding - Kpaddalign, // padding for alignment - Knop // no-op (configuration or spaces) -} KOption; - -/* -** Read an integer numeral from string 'fmt' or return 'df' if -** there is no numeral -*/ -static int digit(int c) -{ - return '0' <= c && c <= '9'; -} - -static int getnum(Header* h, const char** fmt, int df) -{ - if (!digit(**fmt)) // no number? - return df; // return default value - else - { - int a = 0; - do - { - a = a * 10 + (*((*fmt)++) - '0'); - } while (digit(**fmt) && a <= (INT_MAX - 9) / 10); - if (a > MAXSSIZE || digit(**fmt)) - luaL_error(h->L, "size specifier is too large"); - return a; - } -} - -/* -** Read an integer numeral and raises an error if it is larger -** than the maximum size for integers. -*/ -static int getnumlimit(Header* h, const char** fmt, int df) -{ - int sz = getnum(h, fmt, df); - if (sz > MAXINTSIZE || sz <= 0) - luaL_error(h->L, "integral size (%d) out of limits [1,%d]", sz, MAXINTSIZE); - return sz; -} - -/* -** Initialize Header -*/ -static void initheader(lua_State* L, Header* h) -{ - h->L = L; - h->islittle = nativeendian.little; - h->maxalign = 1; -} - -/* -** Read and classify next option. 'size' is filled with option's size. -*/ -static KOption getoption(Header* h, const char** fmt, int* size) -{ - int opt = *((*fmt)++); - *size = 0; // default - switch (opt) - { - case 'b': - *size = 1; - return Kint; - case 'B': - *size = 1; - return Kuint; - case 'h': - *size = 2; - return Kint; - case 'H': - *size = 2; - return Kuint; - case 'l': - *size = 8; - return Kint; - case 'L': - *size = 8; - return Kuint; - case 'j': - *size = 4; - return Kint; - case 'J': - *size = 4; - return Kuint; - case 'T': - *size = 4; - return Kuint; - case 'f': - *size = 4; - return Kfloat; - case 'd': - *size = 8; - return Kfloat; - case 'n': - *size = 8; - return Kfloat; - case 'i': - *size = getnumlimit(h, fmt, 4); - return Kint; - case 'I': - *size = getnumlimit(h, fmt, 4); - return Kuint; - case 's': - *size = getnumlimit(h, fmt, 4); - return Kstring; - case 'c': - *size = getnum(h, fmt, -1); - if (*size == -1) - luaL_error(h->L, "missing size for format option 'c'"); - return Kchar; - case 'z': - return Kzstr; - case 'x': - *size = 1; - return Kpadding; - case 'X': - return Kpaddalign; - case ' ': - break; - case '<': - h->islittle = 1; - break; - case '>': - h->islittle = 0; - break; - case '=': - h->islittle = nativeendian.little; - break; - case '!': - h->maxalign = getnumlimit(h, fmt, MAXALIGN); - break; - default: - luaL_error(h->L, "invalid format option '%c'", opt); - } - return Knop; -} - -/* -** Read, classify, and fill other details about the next option. -** 'psize' is filled with option's size, 'notoalign' with its -** alignment requirements. -** Local variable 'size' gets the size to be aligned. (Kpadal option -** always gets its full alignment, other options are limited by -** the maximum alignment ('maxalign'). Kchar option needs no alignment -** despite its size. -*/ -static KOption getdetails(Header* h, size_t totalsize, const char** fmt, int* psize, int* ntoalign) -{ - KOption opt = getoption(h, fmt, psize); - int align = *psize; // usually, alignment follows size - if (opt == Kpaddalign) - { // 'X' gets alignment from following option - if (**fmt == '\0' || getoption(h, fmt, &align) == Kchar || align == 0) - luaL_argerror(h->L, 1, "invalid next option for option 'X'"); - } - if (align <= 1 || opt == Kchar) // need no alignment? - *ntoalign = 0; - else - { - if (align > h->maxalign) // enforce maximum alignment - align = h->maxalign; - if ((align & (align - 1)) != 0) // is 'align' not a power of 2? - luaL_argerror(h->L, 1, "format asks for alignment not power of 2"); - *ntoalign = (align - (int)(totalsize & (align - 1))) & (align - 1); - } - return opt; -} - -/* -** Pack integer 'n' with 'size' bytes and 'islittle' endianness. -** The final 'if' handles the case when 'size' is larger than -** the size of a Lua integer, correcting the extra sign-extension -** bytes if necessary (by default they would be zeros). -*/ -static void packint(luaL_Strbuf* b, unsigned long long n, int islittle, int size, int neg) -{ - LUAU_ASSERT(size <= MAXINTSIZE); - char buff[MAXINTSIZE]; - int i; - buff[islittle ? 0 : size - 1] = (char)(n & MC); // first byte - for (i = 1; i < size; i++) - { - n >>= NB; - buff[islittle ? i : size - 1 - i] = (char)(n & MC); - } - if (neg && size > SZINT) - { // negative number need sign extension? - for (i = SZINT; i < size; i++) // correct extra bytes - buff[islittle ? i : size - 1 - i] = (char)MC; - } - luaL_addlstring(b, buff, size); // add result to buffer -} - -/* -** Copy 'size' bytes from 'src' to 'dest', correcting endianness if -** given 'islittle' is different from native endianness. -*/ -static void copywithendian(volatile char* dest, volatile const char* src, int size, int islittle) -{ - if (islittle == nativeendian.little) - { - while (size-- != 0) - *(dest++) = *(src++); - } - else - { - dest += size - 1; - while (size-- != 0) - *(dest--) = *(src++); - } -} - -static int str_pack(lua_State* L) -{ - luaL_Strbuf b; - Header h; - const char* fmt = luaL_checkstring(L, 1); // format string - int arg = 1; // current argument to pack - size_t totalsize = 0; // accumulate total size of result - initheader(L, &h); - lua_pushnil(L); // mark to separate arguments from string buffer - luaL_buffinit(L, &b); - while (*fmt != '\0') - { - int size, ntoalign; - KOption opt = getdetails(&h, totalsize, &fmt, &size, &ntoalign); - totalsize += ntoalign + size; - while (ntoalign-- > 0) - luaL_addchar(&b, LUAL_PACKPADBYTE); // fill alignment - arg++; - switch (opt) - { - case Kint: - { // signed integers - long long n = (long long)luaL_checknumber(L, arg); - if (size < SZINT) - { // need overflow check? - long long lim = (long long)1 << ((size * NB) - 1); - luaL_argcheck(L, -lim <= n && n < lim, arg, "integer overflow"); - } - packint(&b, n, h.islittle, size, (n < 0)); - break; - } - case Kuint: - { // unsigned integers - long long n = (long long)luaL_checknumber(L, arg); - if (size < SZINT) // need overflow check? - luaL_argcheck(L, (unsigned long long)n < ((unsigned long long)1 << (size * NB)), arg, "unsigned overflow"); - packint(&b, (unsigned long long)n, h.islittle, size, 0); - break; - } - case Kfloat: - { // floating-point options - volatile Ftypes u; - char buff[MAXINTSIZE]; - double n = luaL_checknumber(L, arg); // get argument - if (size == sizeof(u.f)) - u.f = (float)n; // copy it into 'u' - else if (size == sizeof(u.d)) - u.d = (double)n; - else - u.n = n; - // move 'u' to final result, correcting endianness if needed - copywithendian(buff, u.buff, size, h.islittle); - luaL_addlstring(&b, buff, size); - break; - } - case Kchar: - { // fixed-size string - size_t len; - const char* s = luaL_checklstring(L, arg, &len); - luaL_argcheck(L, len <= (size_t)size, arg, "string longer than given size"); - luaL_addlstring(&b, s, len); // add string - while (len++ < (size_t)size) // pad extra space - luaL_addchar(&b, LUAL_PACKPADBYTE); - break; - } - case Kstring: - { // strings with length count - size_t len; - const char* s = luaL_checklstring(L, arg, &len); - luaL_argcheck(L, size >= (int)sizeof(size_t) || len < ((size_t)1 << (size * NB)), arg, "string length does not fit in given size"); - packint(&b, len, h.islittle, size, 0); // pack length - luaL_addlstring(&b, s, len); - totalsize += len; - break; - } - case Kzstr: - { // zero-terminated string - size_t len; - const char* s = luaL_checklstring(L, arg, &len); - luaL_argcheck(L, strlen(s) == len, arg, "string contains zeros"); - luaL_addlstring(&b, s, len); - luaL_addchar(&b, '\0'); // add zero at the end - totalsize += len + 1; - break; - } - case Kpadding: - luaL_addchar(&b, LUAL_PACKPADBYTE); // FALLTHROUGH - case Kpaddalign: - case Knop: - arg--; // undo increment - break; - } - } - luaL_pushresult(&b); - return 1; -} - -static int str_packsize(lua_State* L) -{ - Header h; - const char* fmt = luaL_checkstring(L, 1); // format string - int totalsize = 0; // accumulate total size of result - initheader(L, &h); - while (*fmt != '\0') - { - int size, ntoalign; - KOption opt = getdetails(&h, totalsize, &fmt, &size, &ntoalign); - luaL_argcheck(L, opt != Kstring && opt != Kzstr, 1, "variable-length format"); - size += ntoalign; // total space used by option - luaL_argcheck(L, totalsize <= MAXSSIZE - size, 1, "format result too large"); - totalsize += size; - } - lua_pushinteger(L, totalsize); - return 1; -} - -/* -** Unpack an integer with 'size' bytes and 'islittle' endianness. -** If size is smaller than the size of a Lua integer and integer -** is signed, must do sign extension (propagating the sign to the -** higher bits); if size is larger than the size of a Lua integer, -** it must check the unread bytes to see whether they do not cause an -** overflow. -*/ -static long long unpackint(lua_State* L, const char* str, int islittle, int size, int issigned) -{ - unsigned long long res = 0; - int i; - int limit = (size <= SZINT) ? size : SZINT; - for (i = limit - 1; i >= 0; i--) - { - res <<= NB; - res |= (unsigned char)str[islittle ? i : size - 1 - i]; - } - if (size < SZINT) - { // real size smaller than int? - if (issigned) - { // needs sign extension? - unsigned long long mask = (unsigned long long)1 << (size * NB - 1); - res = ((res ^ mask) - mask); // do sign extension - } - } - else if (size > SZINT) - { // must check unread bytes - int mask = (!issigned || (long long)res >= 0) ? 0 : MC; - for (i = limit; i < size; i++) - { - if ((unsigned char)str[islittle ? i : size - 1 - i] != mask) - luaL_error(L, "%d-byte integer does not fit into Lua Integer", size); - } - } - return (long long)res; -} - -static int str_unpack(lua_State* L) -{ - Header h; - const char* fmt = luaL_checkstring(L, 1); - size_t ld; - const char* data = luaL_checklstring(L, 2, &ld); - int pos = posrelat(luaL_optinteger(L, 3, 1), ld) - 1; - if (pos < 0) - pos = 0; - int n = 0; // number of results - luaL_argcheck(L, size_t(pos) <= ld, 3, "initial position out of string"); - initheader(L, &h); - while (*fmt != '\0') - { - int size, ntoalign; - KOption opt = getdetails(&h, pos, &fmt, &size, &ntoalign); - luaL_argcheck(L, (size_t)ntoalign + size <= ld - pos, 2, "data string too short"); - pos += ntoalign; // skip alignment - // stack space for item + next position - luaL_checkstack(L, 2, "too many results"); - n++; - switch (opt) - { - case Kint: - { - long long res = unpackint(L, data + pos, h.islittle, size, true); - lua_pushnumber(L, (double)res); - break; - } - case Kuint: - { - unsigned long long res = unpackint(L, data + pos, h.islittle, size, false); - lua_pushnumber(L, (double)res); - break; - } - case Kfloat: - { - volatile Ftypes u; - double num; - copywithendian(u.buff, data + pos, size, h.islittle); - if (size == sizeof(u.f)) - num = (double)u.f; - else if (size == sizeof(u.d)) - num = (double)u.d; - else - num = u.n; - lua_pushnumber(L, num); - break; - } - case Kchar: - { - lua_pushlstring(L, data + pos, size); - break; - } - case Kstring: - { - size_t len = (size_t)unpackint(L, data + pos, h.islittle, size, 0); - luaL_argcheck(L, len <= ld - pos - size, 2, "data string too short"); - lua_pushlstring(L, data + pos + size, len); - pos += (int)len; // skip string - break; - } - case Kzstr: - { - size_t len = strlen(data + pos); - luaL_argcheck(L, pos + len < ld, 2, "unfinished string for format 'z'"); - lua_pushlstring(L, data + pos, len); - pos += (int)len + 1; // skip string plus final '\0' - break; - } - case Kpaddalign: - case Kpadding: - case Knop: - n--; // undo increment - break; - } - pos += size; - } - lua_pushinteger(L, pos + 1); // next position - return n + 1; -} - -// }====================================================== - -static const luaL_Reg strlib[] = { - {"byte", str_byte}, - {"char", str_char}, - {"find", str_find}, - {"format", str_format}, - {"gmatch", gmatch}, - {"gsub", str_gsub}, - {"len", str_len}, - {"lower", str_lower}, - {"match", str_match}, - {"rep", str_rep}, - {"reverse", str_reverse}, - {"sub", str_sub}, - {"upper", str_upper}, - {"split", str_split}, - {"pack", str_pack}, - {"packsize", str_packsize}, - {"unpack", str_unpack}, - {NULL, NULL}, -}; - -static void createmetatable(lua_State* L) -{ - lua_createtable(L, 0, 1); // create metatable for strings - lua_pushliteral(L, ""); // dummy string - lua_pushvalue(L, -2); - lua_setmetatable(L, -2); // set string metatable - lua_pop(L, 1); // pop dummy string - lua_pushvalue(L, -2); // string library... - lua_setfield(L, -2, "__index"); // ...is the __index metamethod - lua_pop(L, 1); // pop metatable -} - -/* -** Open string library -*/ -int luaopen_string(lua_State* L) -{ - luaL_register(L, LUA_STRLIBNAME, strlib); - createmetatable(L); - - return 1; -} diff --git a/lib/luau/VM/src/ltable.cpp b/lib/luau/VM/src/ltable.cpp deleted file mode 100644 index c963ac8..0000000 --- a/lib/luau/VM/src/ltable.cpp +++ /dev/null @@ -1,859 +0,0 @@ -// This file is part of the Luau programming language and is licensed under MIT License; see LICENSE.txt for details -// This code is based on Lua 5.x implementation licensed under MIT License; see lua_LICENSE.txt for details - -/* - * Implementation of tables (aka arrays, objects, or hash tables). - * - * Tables keep the elements in two parts: an array part and a hash part. - * Integer keys >=1 are all candidates to be kept in the array part. The actual size of the array is the - * largest n such that at least half the slots between 0 and n are in use. - * Hash uses a mix of chained scatter table with Brent's variation. - * - * A main invariant of these tables is that, if an element is not in its main position (i.e. the original - * position that its hash gives to it), then the colliding element is in its own main position. - * Hence even when the load factor reaches 100%, performance remains good. - * - * Table keys can be arbitrary values unless they contain NaN. Keys are hashed and compared using raw equality, - * so even if the key is a userdata with an overridden __eq, it's not used during hash lookups. - * - * Each table has a "boundary", defined as the index k where t[k] ~= nil and t[k+1] == nil. The boundary can be - * computed using a binary search and can be adjusted when the table is modified; crucially, Luau enforces an - * invariant where the boundary must be in the array part - this enforces a consistent iteration order through the - * prefix of the table when using pairs(), and allows to implement algorithms that access elements in 1..#t range - * more efficiently. - */ - -#include "ltable.h" - -#include "lstate.h" -#include "ldebug.h" -#include "lgc.h" -#include "lmem.h" -#include "lnumutils.h" - -#include - -// max size of both array and hash part is 2^MAXBITS -#define MAXBITS 26 -#define MAXSIZE (1 << MAXBITS) - -static_assert(offsetof(LuaNode, val) == 0, "Unexpected Node memory layout, pointer cast in gval2slot is incorrect"); - -// TKey is bitpacked for memory efficiency so we need to validate bit counts for worst case -static_assert(TKey{{NULL}, {0}, LUA_TDEADKEY, 0}.tt == LUA_TDEADKEY, "not enough bits for tt"); -static_assert(TKey{{NULL}, {0}, LUA_TNIL, MAXSIZE - 1}.next == MAXSIZE - 1, "not enough bits for next"); -static_assert(TKey{{NULL}, {0}, LUA_TNIL, -(MAXSIZE - 1)}.next == -(MAXSIZE - 1), "not enough bits for next"); - -// empty hash data points to dummynode so that we can always dereference it -const LuaNode luaH_dummynode = { - {{NULL}, {0}, LUA_TNIL}, // value - {{NULL}, {0}, LUA_TNIL, 0} // key -}; - -#define dummynode (&luaH_dummynode) - -// hash is always reduced mod 2^k -#define hashpow2(t, n) (gnode(t, lmod((n), sizenode(t)))) - -#define hashstr(t, str) hashpow2(t, (str)->hash) -#define hashboolean(t, p) hashpow2(t, p) - -static LuaNode* hashpointer(const Table* t, const void* p) -{ - // we discard the high 32-bit portion of the pointer on 64-bit platforms as it doesn't carry much entropy anyway - unsigned int h = unsigned(uintptr_t(p)); - - // MurmurHash3 32-bit finalizer - h ^= h >> 16; - h *= 0x85ebca6bu; - h ^= h >> 13; - h *= 0xc2b2ae35u; - h ^= h >> 16; - - return hashpow2(t, h); -} - -static LuaNode* hashnum(const Table* t, double n) -{ - static_assert(sizeof(double) == sizeof(unsigned int) * 2, "expected a 8-byte double"); - unsigned int i[2]; - memcpy(i, &n, sizeof(i)); - - // mask out sign bit to make sure -0 and 0 hash to the same value - uint32_t h1 = i[0]; - uint32_t h2 = i[1] & 0x7fffffff; - - // finalizer from MurmurHash64B - const uint32_t m = 0x5bd1e995; - - h1 ^= h2 >> 18; - h1 *= m; - h2 ^= h1 >> 22; - h2 *= m; - h1 ^= h2 >> 17; - h1 *= m; - h2 ^= h1 >> 19; - h2 *= m; - - // ... truncated to 32-bit output (normally hash is equal to (uint64_t(h1) << 32) | h2, but we only really need the lower 32-bit half) - return hashpow2(t, h2); -} - -static LuaNode* hashvec(const Table* t, const float* v) -{ - unsigned int i[LUA_VECTOR_SIZE]; - memcpy(i, v, sizeof(i)); - - // convert -0 to 0 to make sure they hash to the same value - i[0] = (i[0] == 0x80000000) ? 0 : i[0]; - i[1] = (i[1] == 0x80000000) ? 0 : i[1]; - i[2] = (i[2] == 0x80000000) ? 0 : i[2]; - - // scramble bits to make sure that integer coordinates have entropy in lower bits - i[0] ^= i[0] >> 17; - i[1] ^= i[1] >> 17; - i[2] ^= i[2] >> 17; - - // Optimized Spatial Hashing for Collision Detection of Deformable Objects - unsigned int h = (i[0] * 73856093) ^ (i[1] * 19349663) ^ (i[2] * 83492791); - -#if LUA_VECTOR_SIZE == 4 - i[3] = (i[3] == 0x80000000) ? 0 : i[3]; - i[3] ^= i[3] >> 17; - h ^= i[3] * 39916801; -#endif - - return hashpow2(t, h); -} - -/* -** returns the `main' position of an element in a table (that is, the index -** of its hash value) -*/ -static LuaNode* mainposition(const Table* t, const TValue* key) -{ - switch (ttype(key)) - { - case LUA_TNUMBER: - return hashnum(t, nvalue(key)); - case LUA_TVECTOR: - return hashvec(t, vvalue(key)); - case LUA_TSTRING: - return hashstr(t, tsvalue(key)); - case LUA_TBOOLEAN: - return hashboolean(t, bvalue(key)); - case LUA_TLIGHTUSERDATA: - return hashpointer(t, pvalue(key)); - default: - return hashpointer(t, gcvalue(key)); - } -} - -/* -** returns the index for `key' if `key' is an appropriate key to live in -** the array part of the table, -1 otherwise. -*/ -static int arrayindex(double key) -{ - int i; - luai_num2int(i, key); - - return luai_numeq(cast_num(i), key) ? i : -1; -} - -/* -** returns the index of a `key' for table traversals. First goes all -** elements in the array part, then elements in the hash part. The -** beginning of a traversal is signalled by -1. -*/ -static int findindex(lua_State* L, Table* t, StkId key) -{ - int i; - if (ttisnil(key)) - return -1; // first iteration - i = ttisnumber(key) ? arrayindex(nvalue(key)) : -1; - if (0 < i && i <= t->sizearray) // is `key' inside array part? - return i - 1; // yes; that's the index (corrected to C) - else - { - LuaNode* n = mainposition(t, key); - for (;;) - { // check whether `key' is somewhere in the chain - // key may be dead already, but it is ok to use it in `next' - if (luaO_rawequalKey(gkey(n), key) || (ttype(gkey(n)) == LUA_TDEADKEY && iscollectable(key) && gcvalue(gkey(n)) == gcvalue(key))) - { - i = cast_int(n - gnode(t, 0)); // key index in hash table - // hash elements are numbered after array ones - return i + t->sizearray; - } - if (gnext(n) == 0) - break; - n += gnext(n); - } - luaG_runerror(L, "invalid key to 'next'"); // key not found - } -} - -int luaH_next(lua_State* L, Table* t, StkId key) -{ - int i = findindex(L, t, key); // find original element - for (i++; i < t->sizearray; i++) - { // try first array part - if (!ttisnil(&t->array[i])) - { // a non-nil value? - setnvalue(key, cast_num(i + 1)); - setobj2s(L, key + 1, &t->array[i]); - return 1; - } - } - for (i -= t->sizearray; i < sizenode(t); i++) - { // then hash part - if (!ttisnil(gval(gnode(t, i)))) - { // a non-nil value? - getnodekey(L, key, gnode(t, i)); - setobj2s(L, key + 1, gval(gnode(t, i))); - return 1; - } - } - return 0; // no more elements -} - -/* -** {============================================================= -** Rehash -** ============================================================== -*/ - -#define maybesetaboundary(t, boundary) \ - { \ - if (t->aboundary <= 0) \ - t->aboundary = -int(boundary); \ - } - -#define getaboundary(t) (t->aboundary < 0 ? -t->aboundary : t->sizearray) - -static int computesizes(int nums[], int* narray) -{ - int i; - int twotoi; // 2^i - int a = 0; // number of elements smaller than 2^i - int na = 0; // number of elements to go to array part - int n = 0; // optimal size for array part - for (i = 0, twotoi = 1; twotoi / 2 < *narray; i++, twotoi *= 2) - { - if (nums[i] > 0) - { - a += nums[i]; - if (a > twotoi / 2) - { // more than half elements present? - n = twotoi; // optimal size (till now) - na = a; // all elements smaller than n will go to array part - } - } - if (a == *narray) - break; // all elements already counted - } - *narray = n; - LUAU_ASSERT(*narray / 2 <= na && na <= *narray); - return na; -} - -static int countint(double key, int* nums) -{ - int k = arrayindex(key); - if (0 < k && k <= MAXSIZE) - { // is `key' an appropriate array index? - nums[ceillog2(k)]++; // count as such - return 1; - } - else - return 0; -} - -static int numusearray(const Table* t, int* nums) -{ - int lg; - int ttlg; // 2^lg - int ause = 0; // summation of `nums' - int i = 1; // count to traverse all array keys - for (lg = 0, ttlg = 1; lg <= MAXBITS; lg++, ttlg *= 2) - { // for each slice - int lc = 0; // counter - int lim = ttlg; - if (lim > t->sizearray) - { - lim = t->sizearray; // adjust upper limit - if (i > lim) - break; // no more elements to count - } - // count elements in range (2^(lg-1), 2^lg] - for (; i <= lim; i++) - { - if (!ttisnil(&t->array[i - 1])) - lc++; - } - nums[lg] += lc; - ause += lc; - } - return ause; -} - -static int numusehash(const Table* t, int* nums, int* pnasize) -{ - int totaluse = 0; // total number of elements - int ause = 0; // summation of `nums' - int i = sizenode(t); - while (i--) - { - LuaNode* n = &t->node[i]; - if (!ttisnil(gval(n))) - { - if (ttisnumber(gkey(n))) - ause += countint(nvalue(gkey(n)), nums); - totaluse++; - } - } - *pnasize += ause; - return totaluse; -} - -static void setarrayvector(lua_State* L, Table* t, int size) -{ - if (size > MAXSIZE) - luaG_runerror(L, "table overflow"); - luaM_reallocarray(L, t->array, t->sizearray, size, TValue, t->memcat); - TValue* array = t->array; - for (int i = t->sizearray; i < size; i++) - setnilvalue(&array[i]); - t->sizearray = size; -} - -static void setnodevector(lua_State* L, Table* t, int size) -{ - int lsize; - if (size == 0) - { // no elements to hash part? - t->node = cast_to(LuaNode*, dummynode); // use common `dummynode' - lsize = 0; - } - else - { - int i; - lsize = ceillog2(size); - if (lsize > MAXBITS) - luaG_runerror(L, "table overflow"); - size = twoto(lsize); - t->node = luaM_newarray(L, size, LuaNode, t->memcat); - for (i = 0; i < size; i++) - { - LuaNode* n = gnode(t, i); - gnext(n) = 0; - setnilvalue(gkey(n)); - setnilvalue(gval(n)); - } - } - t->lsizenode = cast_byte(lsize); - t->nodemask8 = cast_byte((1 << lsize) - 1); - t->lastfree = size; // all positions are free -} - -static TValue* newkey(lua_State* L, Table* t, const TValue* key); - -static TValue* arrayornewkey(lua_State* L, Table* t, const TValue* key) -{ - if (ttisnumber(key)) - { - int k; - double n = nvalue(key); - luai_num2int(k, n); - if (luai_numeq(cast_num(k), n) && cast_to(unsigned int, k - 1) < cast_to(unsigned int, t->sizearray)) - return &t->array[k - 1]; - } - - return newkey(L, t, key); -} - -static void resize(lua_State* L, Table* t, int nasize, int nhsize) -{ - if (nasize > MAXSIZE || nhsize > MAXSIZE) - luaG_runerror(L, "table overflow"); - int oldasize = t->sizearray; - int oldhsize = t->lsizenode; - LuaNode* nold = t->node; // save old hash ... - if (nasize > oldasize) // array part must grow? - setarrayvector(L, t, nasize); - // create new hash part with appropriate size - setnodevector(L, t, nhsize); - // used for the migration check at the end - LuaNode* nnew = t->node; - if (nasize < oldasize) - { // array part must shrink? - t->sizearray = nasize; - // re-insert elements from vanishing slice - for (int i = nasize; i < oldasize; i++) - { - if (!ttisnil(&t->array[i])) - { - TValue ok; - setnvalue(&ok, cast_num(i + 1)); - setobjt2t(L, newkey(L, t, &ok), &t->array[i]); - } - } - // shrink array - luaM_reallocarray(L, t->array, oldasize, nasize, TValue, t->memcat); - } - // used for the migration check at the end - TValue* anew = t->array; - // re-insert elements from hash part - for (int i = twoto(oldhsize) - 1; i >= 0; i--) - { - LuaNode* old = nold + i; - if (!ttisnil(gval(old))) - { - TValue ok; - getnodekey(L, &ok, old); - setobjt2t(L, arrayornewkey(L, t, &ok), gval(old)); - } - } - - // make sure we haven't recursively rehashed during element migration - LUAU_ASSERT(nnew == t->node); - LUAU_ASSERT(anew == t->array); - - if (nold != dummynode) - luaM_freearray(L, nold, twoto(oldhsize), LuaNode, t->memcat); // free old array -} - -static int adjustasize(Table* t, int size, const TValue* ek) -{ - bool tbound = t->node != dummynode || size < t->sizearray; - int ekindex = ek && ttisnumber(ek) ? arrayindex(nvalue(ek)) : -1; - // move the array size up until the boundary is guaranteed to be inside the array part - while (size + 1 == ekindex || (tbound && !ttisnil(luaH_getnum(t, size + 1)))) - size++; - return size; -} - -void luaH_resizearray(lua_State* L, Table* t, int nasize) -{ - int nsize = (t->node == dummynode) ? 0 : sizenode(t); - int asize = adjustasize(t, nasize, NULL); - resize(L, t, asize, nsize); -} - -void luaH_resizehash(lua_State* L, Table* t, int nhsize) -{ - resize(L, t, t->sizearray, nhsize); -} - -static void rehash(lua_State* L, Table* t, const TValue* ek) -{ - int nums[MAXBITS + 1]; // nums[i] = number of keys between 2^(i-1) and 2^i - for (int i = 0; i <= MAXBITS; i++) - nums[i] = 0; // reset counts - int nasize = numusearray(t, nums); // count keys in array part - int totaluse = nasize; // all those keys are integer keys - totaluse += numusehash(t, nums, &nasize); // count keys in hash part - - // count extra key - if (ttisnumber(ek)) - nasize += countint(nvalue(ek), nums); - totaluse++; - - // compute new size for array part - int na = computesizes(nums, &nasize); - int nh = totaluse - na; - - // enforce the boundary invariant; for performance, only do hash lookups if we must - int nadjusted = adjustasize(t, nasize, ek); - - // count how many extra elements belong to array part instead of hash part - int aextra = nadjusted - nasize; - - if (aextra != 0) - { - // we no longer need to store those extra array elements in hash part - nh -= aextra; - - // because hash nodes are twice as large as array nodes, the memory we saved for hash parts can be used by array part - // this follows the general sparse array part optimization where array is allocated when 50% occupation is reached - nasize = nadjusted + aextra; - - // since the size was changed, it's again important to enforce the boundary invariant at the new size - nasize = adjustasize(t, nasize, ek); - } - - // resize the table to new computed sizes - resize(L, t, nasize, nh); -} - -/* -** }============================================================= -*/ - -Table* luaH_new(lua_State* L, int narray, int nhash) -{ - Table* t = luaM_newgco(L, Table, sizeof(Table), L->activememcat); - luaC_init(L, t, LUA_TTABLE); - t->metatable = NULL; - t->tmcache = cast_byte(~0); - t->array = NULL; - t->sizearray = 0; - t->lastfree = 0; - t->lsizenode = 0; - t->readonly = 0; - t->safeenv = 0; - t->nodemask8 = 0; - t->node = cast_to(LuaNode*, dummynode); - if (narray > 0) - setarrayvector(L, t, narray); - if (nhash > 0) - setnodevector(L, t, nhash); - return t; -} - -void luaH_free(lua_State* L, Table* t, lua_Page* page) -{ - if (t->node != dummynode) - luaM_freearray(L, t->node, sizenode(t), LuaNode, t->memcat); - if (t->array) - luaM_freearray(L, t->array, t->sizearray, TValue, t->memcat); - luaM_freegco(L, t, sizeof(Table), t->memcat, page); -} - -static LuaNode* getfreepos(Table* t) -{ - while (t->lastfree > 0) - { - t->lastfree--; - - LuaNode* n = gnode(t, t->lastfree); - if (ttisnil(gkey(n))) - return n; - } - return NULL; // could not find a free place -} - -/* -** inserts a new key into a hash table; first, check whether key's main -** position is free. If not, check whether colliding node is in its main -** position or not: if it is not, move colliding node to an empty place and -** put new key in its main position; otherwise (colliding node is in its main -** position), new key goes to an empty position. -*/ -static TValue* newkey(lua_State* L, Table* t, const TValue* key) -{ - // enforce boundary invariant - if (ttisnumber(key) && nvalue(key) == t->sizearray + 1) - { - rehash(L, t, key); // grow table - - // after rehash, numeric keys might be located in the new array part, but won't be found in the node part - return arrayornewkey(L, t, key); - } - - LuaNode* mp = mainposition(t, key); - if (!ttisnil(gval(mp)) || mp == dummynode) - { - LuaNode* n = getfreepos(t); // get a free place - if (n == NULL) - { // cannot find a free place? - rehash(L, t, key); // grow table - - // after rehash, numeric keys might be located in the new array part, but won't be found in the node part - return arrayornewkey(L, t, key); - } - LUAU_ASSERT(n != dummynode); - TValue mk; - getnodekey(L, &mk, mp); - LuaNode* othern = mainposition(t, &mk); - if (othern != mp) - { // is colliding node out of its main position? - // yes; move colliding node into free position - while (othern + gnext(othern) != mp) - othern += gnext(othern); // find previous - gnext(othern) = cast_int(n - othern); // redo the chain with `n' in place of `mp' - *n = *mp; // copy colliding node into free pos. (mp->next also goes) - if (gnext(mp) != 0) - { - gnext(n) += cast_int(mp - n); // correct 'next' - gnext(mp) = 0; // now 'mp' is free - } - setnilvalue(gval(mp)); - } - else - { // colliding node is in its own main position - // new node will go into free position - if (gnext(mp) != 0) - gnext(n) = cast_int((mp + gnext(mp)) - n); // chain new position - else - LUAU_ASSERT(gnext(n) == 0); - gnext(mp) = cast_int(n - mp); - mp = n; - } - } - setnodekey(L, mp, key); - luaC_barriert(L, t, key); - LUAU_ASSERT(ttisnil(gval(mp))); - return gval(mp); -} - -/* -** search function for integers -*/ -const TValue* luaH_getnum(Table* t, int key) -{ - // (1 <= key && key <= t->sizearray) - if (cast_to(unsigned int, key - 1) < cast_to(unsigned int, t->sizearray)) - return &t->array[key - 1]; - else if (t->node != dummynode) - { - double nk = cast_num(key); - LuaNode* n = hashnum(t, nk); - for (;;) - { // check whether `key' is somewhere in the chain - if (ttisnumber(gkey(n)) && luai_numeq(nvalue(gkey(n)), nk)) - return gval(n); // that's it - if (gnext(n) == 0) - break; - n += gnext(n); - } - return luaO_nilobject; - } - else - return luaO_nilobject; -} - -/* -** search function for strings -*/ -const TValue* luaH_getstr(Table* t, TString* key) -{ - LuaNode* n = hashstr(t, key); - for (;;) - { // check whether `key' is somewhere in the chain - if (ttisstring(gkey(n)) && tsvalue(gkey(n)) == key) - return gval(n); // that's it - if (gnext(n) == 0) - break; - n += gnext(n); - } - return luaO_nilobject; -} - -/* -** main search function -*/ -const TValue* luaH_get(Table* t, const TValue* key) -{ - switch (ttype(key)) - { - case LUA_TNIL: - return luaO_nilobject; - case LUA_TSTRING: - return luaH_getstr(t, tsvalue(key)); - case LUA_TNUMBER: - { - int k; - double n = nvalue(key); - luai_num2int(k, n); - if (luai_numeq(cast_num(k), nvalue(key))) // index is int? - return luaH_getnum(t, k); // use specialized version - // else go through - } - default: - { - LuaNode* n = mainposition(t, key); - for (;;) - { // check whether `key' is somewhere in the chain - if (luaO_rawequalKey(gkey(n), key)) - return gval(n); // that's it - if (gnext(n) == 0) - break; - n += gnext(n); - } - return luaO_nilobject; - } - } -} - -TValue* luaH_set(lua_State* L, Table* t, const TValue* key) -{ - const TValue* p = luaH_get(t, key); - invalidateTMcache(t); - if (p != luaO_nilobject) - return cast_to(TValue*, p); - else - return luaH_newkey(L, t, key); -} - -TValue* luaH_newkey(lua_State* L, Table* t, const TValue* key) -{ - if (ttisnil(key)) - luaG_runerror(L, "table index is nil"); - else if (ttisnumber(key) && luai_numisnan(nvalue(key))) - luaG_runerror(L, "table index is NaN"); - else if (ttisvector(key) && luai_vecisnan(vvalue(key))) - luaG_runerror(L, "table index contains NaN"); - return newkey(L, t, key); -} - -TValue* luaH_setnum(lua_State* L, Table* t, int key) -{ - // (1 <= key && key <= t->sizearray) - if (cast_to(unsigned int, key - 1) < cast_to(unsigned int, t->sizearray)) - return &t->array[key - 1]; - // hash fallback - const TValue* p = luaH_getnum(t, key); - if (p != luaO_nilobject) - return cast_to(TValue*, p); - else - { - TValue k; - setnvalue(&k, cast_num(key)); - return newkey(L, t, &k); - } -} - -TValue* luaH_setstr(lua_State* L, Table* t, TString* key) -{ - const TValue* p = luaH_getstr(t, key); - invalidateTMcache(t); - if (p != luaO_nilobject) - return cast_to(TValue*, p); - else - { - TValue k; - setsvalue(L, &k, key); - return newkey(L, t, &k); - } -} - -static int updateaboundary(Table* t, int boundary) -{ - if (boundary < t->sizearray && ttisnil(&t->array[boundary - 1])) - { - if (boundary >= 2 && !ttisnil(&t->array[boundary - 2])) - { - maybesetaboundary(t, boundary - 1); - return boundary - 1; - } - } - else if (boundary + 1 < t->sizearray && !ttisnil(&t->array[boundary]) && ttisnil(&t->array[boundary + 1])) - { - maybesetaboundary(t, boundary + 1); - return boundary + 1; - } - - return 0; -} - -/* -** Try to find a boundary in table `t'. A `boundary' is an integer index -** such that t[i] is non-nil and t[i+1] is nil (and 0 if t[1] is nil). -*/ -int luaH_getn(Table* t) -{ - int boundary = getaboundary(t); - - if (boundary > 0) - { - if (!ttisnil(&t->array[t->sizearray - 1]) && t->node == dummynode) - return t->sizearray; // fast-path: the end of the array in `t' already refers to a boundary - if (boundary < t->sizearray && !ttisnil(&t->array[boundary - 1]) && ttisnil(&t->array[boundary])) - return boundary; // fast-path: boundary already refers to a boundary in `t' - - int foundboundary = updateaboundary(t, boundary); - if (foundboundary > 0) - return foundboundary; - } - - int j = t->sizearray; - - if (j > 0 && ttisnil(&t->array[j - 1])) - { - // "branchless" binary search from Array Layouts for Comparison-Based Searching, Paul Khuong, Pat Morin, 2017. - // note that clang is cmov-shy on cmovs around memory operands, so it will compile this to a branchy loop. - TValue* base = t->array; - int rest = j; - while (int half = rest >> 1) - { - base = ttisnil(&base[half]) ? base : base + half; - rest -= half; - } - int boundary = !ttisnil(base) + int(base - t->array); - maybesetaboundary(t, boundary); - return boundary; - } - else - { - // validate boundary invariant - LUAU_ASSERT(t->node == dummynode || ttisnil(luaH_getnum(t, j + 1))); - return j; - } -} - -Table* luaH_clone(lua_State* L, Table* tt) -{ - Table* t = luaM_newgco(L, Table, sizeof(Table), L->activememcat); - luaC_init(L, t, LUA_TTABLE); - t->metatable = tt->metatable; - t->tmcache = tt->tmcache; - t->array = NULL; - t->sizearray = 0; - t->lsizenode = 0; - t->nodemask8 = 0; - t->readonly = 0; - t->safeenv = 0; - t->node = cast_to(LuaNode*, dummynode); - t->lastfree = 0; - - if (tt->sizearray) - { - t->array = luaM_newarray(L, tt->sizearray, TValue, t->memcat); - maybesetaboundary(t, getaboundary(tt)); - t->sizearray = tt->sizearray; - - memcpy(t->array, tt->array, t->sizearray * sizeof(TValue)); - } - - if (tt->node != dummynode) - { - int size = 1 << tt->lsizenode; - t->node = luaM_newarray(L, size, LuaNode, t->memcat); - t->lsizenode = tt->lsizenode; - t->nodemask8 = tt->nodemask8; - memcpy(t->node, tt->node, size * sizeof(LuaNode)); - t->lastfree = tt->lastfree; - } - - return t; -} - -void luaH_clear(Table* tt) -{ - // clear array part - for (int i = 0; i < tt->sizearray; ++i) - { - setnilvalue(&tt->array[i]); - } - - maybesetaboundary(tt, 0); - - // clear hash part - if (tt->node != dummynode) - { - int size = sizenode(tt); - tt->lastfree = size; - for (int i = 0; i < size; ++i) - { - LuaNode* n = gnode(tt, i); - setnilvalue(gkey(n)); - setnilvalue(gval(n)); - gnext(n) = 0; - } - } - - // back to empty -> no tag methods present - tt->tmcache = cast_byte(~0); -} diff --git a/lib/luau/VM/src/ltable.h b/lib/luau/VM/src/ltable.h deleted file mode 100644 index 021f21b..0000000 --- a/lib/luau/VM/src/ltable.h +++ /dev/null @@ -1,35 +0,0 @@ -// This file is part of the Luau programming language and is licensed under MIT License; see LICENSE.txt for details -// This code is based on Lua 5.x implementation licensed under MIT License; see lua_LICENSE.txt for details -#pragma once - -#include "lobject.h" - -#define gnode(t, i) (&(t)->node[i]) -#define gkey(n) (&(n)->key) -#define gval(n) (&(n)->val) -#define gnext(n) ((n)->key.next) - -#define gval2slot(t, v) int(cast_to(LuaNode*, static_cast(v)) - t->node) - -// reset cache of absent metamethods, cache is updated in luaT_gettm -#define invalidateTMcache(t) t->tmcache = 0 - -LUAI_FUNC const TValue* luaH_getnum(Table* t, int key); -LUAI_FUNC TValue* luaH_setnum(lua_State* L, Table* t, int key); -LUAI_FUNC const TValue* luaH_getstr(Table* t, TString* key); -LUAI_FUNC TValue* luaH_setstr(lua_State* L, Table* t, TString* key); -LUAI_FUNC const TValue* luaH_get(Table* t, const TValue* key); -LUAI_FUNC TValue* luaH_set(lua_State* L, Table* t, const TValue* key); -LUAI_FUNC TValue* luaH_newkey(lua_State* L, Table* t, const TValue* key); -LUAI_FUNC Table* luaH_new(lua_State* L, int narray, int lnhash); -LUAI_FUNC void luaH_resizearray(lua_State* L, Table* t, int nasize); -LUAI_FUNC void luaH_resizehash(lua_State* L, Table* t, int nhsize); -LUAI_FUNC void luaH_free(lua_State* L, Table* t, struct lua_Page* page); -LUAI_FUNC int luaH_next(lua_State* L, Table* t, StkId key); -LUAI_FUNC int luaH_getn(Table* t); -LUAI_FUNC Table* luaH_clone(lua_State* L, Table* tt); -LUAI_FUNC void luaH_clear(Table* tt); - -#define luaH_setslot(L, t, slot, key) (invalidateTMcache(t), (slot == luaO_nilobject ? luaH_newkey(L, t, key) : cast_to(TValue*, slot))) - -extern const LuaNode luaH_dummynode; diff --git a/lib/luau/VM/src/ltablib.cpp b/lib/luau/VM/src/ltablib.cpp deleted file mode 100644 index 0b4a685..0000000 --- a/lib/luau/VM/src/ltablib.cpp +++ /dev/null @@ -1,606 +0,0 @@ -// This file is part of the Luau programming language and is licensed under MIT License; see LICENSE.txt for details -// This code is based on Lua 5.x implementation licensed under MIT License; see lua_LICENSE.txt for details -#include "lualib.h" - -#include "lapi.h" -#include "lstate.h" -#include "ltable.h" -#include "lstring.h" -#include "lgc.h" -#include "ldebug.h" -#include "lvm.h" - -static int foreachi(lua_State* L) -{ - luaL_checktype(L, 1, LUA_TTABLE); - luaL_checktype(L, 2, LUA_TFUNCTION); - int i; - int n = lua_objlen(L, 1); - for (i = 1; i <= n; i++) - { - lua_pushvalue(L, 2); // function - lua_pushinteger(L, i); // 1st argument - lua_rawgeti(L, 1, i); // 2nd argument - lua_call(L, 2, 1); - if (!lua_isnil(L, -1)) - return 1; - lua_pop(L, 1); // remove nil result - } - return 0; -} - -static int foreach (lua_State* L) -{ - luaL_checktype(L, 1, LUA_TTABLE); - luaL_checktype(L, 2, LUA_TFUNCTION); - lua_pushnil(L); // first key - while (lua_next(L, 1)) - { - lua_pushvalue(L, 2); // function - lua_pushvalue(L, -3); // key - lua_pushvalue(L, -3); // value - lua_call(L, 2, 1); - if (!lua_isnil(L, -1)) - return 1; - lua_pop(L, 2); // remove value and result - } - return 0; -} - -static int maxn(lua_State* L) -{ - double max = 0; - luaL_checktype(L, 1, LUA_TTABLE); - lua_pushnil(L); // first key - while (lua_next(L, 1)) - { - lua_pop(L, 1); // remove value - if (lua_type(L, -1) == LUA_TNUMBER) - { - double v = lua_tonumber(L, -1); - if (v > max) - max = v; - } - } - lua_pushnumber(L, max); - return 1; -} - -static int getn(lua_State* L) -{ - luaL_checktype(L, 1, LUA_TTABLE); - lua_pushinteger(L, lua_objlen(L, 1)); - return 1; -} - -static void moveelements(lua_State* L, int srct, int dstt, int f, int e, int t) -{ - Table* src = hvalue(L->base + (srct - 1)); - Table* dst = hvalue(L->base + (dstt - 1)); - - if (dst->readonly) - luaG_readonlyerror(L); - - int n = e - f + 1; // number of elements to move - - if (cast_to(unsigned int, f - 1) < cast_to(unsigned int, src->sizearray) && - cast_to(unsigned int, t - 1) < cast_to(unsigned int, dst->sizearray) && - cast_to(unsigned int, f - 1 + n) <= cast_to(unsigned int, src->sizearray) && - cast_to(unsigned int, t - 1 + n) <= cast_to(unsigned int, dst->sizearray)) - { - TValue* srcarray = src->array; - TValue* dstarray = dst->array; - - if (t > e || t <= f || (dstt != srct && dst != src)) - { - for (int i = 0; i < n; ++i) - { - TValue* s = &srcarray[f + i - 1]; - TValue* d = &dstarray[t + i - 1]; - setobj2t(L, d, s); - } - } - else - { - for (int i = n - 1; i >= 0; i--) - { - TValue* s = &srcarray[(f + i) - 1]; - TValue* d = &dstarray[(t + i) - 1]; - setobj2t(L, d, s); - } - } - - luaC_barrierfast(L, dst); - } - else - { - if (t > e || t <= f || dst != src) - { - for (int i = 0; i < n; ++i) - { - lua_rawgeti(L, srct, f + i); - lua_rawseti(L, dstt, t + i); - } - } - else - { - for (int i = n - 1; i >= 0; i--) - { - lua_rawgeti(L, srct, f + i); - lua_rawseti(L, dstt, t + i); - } - } - } -} - -static int tinsert(lua_State* L) -{ - luaL_checktype(L, 1, LUA_TTABLE); - int n = lua_objlen(L, 1); - int pos; // where to insert new element - switch (lua_gettop(L)) - { - case 2: - { // called with only 2 arguments - pos = n + 1; // insert new element at the end - break; - } - case 3: - { - pos = luaL_checkinteger(L, 2); // 2nd argument is the position - - // move up elements if necessary - if (1 <= pos && pos <= n) - moveelements(L, 1, 1, pos, n, pos + 1); - break; - } - default: - { - luaL_error(L, "wrong number of arguments to 'insert'"); - } - } - lua_rawseti(L, 1, pos); // t[pos] = v - return 0; -} - -static int tremove(lua_State* L) -{ - luaL_checktype(L, 1, LUA_TTABLE); - int n = lua_objlen(L, 1); - int pos = luaL_optinteger(L, 2, n); - - if (!(1 <= pos && pos <= n)) // position is outside bounds? - return 0; // nothing to remove - lua_rawgeti(L, 1, pos); // result = t[pos] - - moveelements(L, 1, 1, pos + 1, n, pos); - - lua_pushnil(L); - lua_rawseti(L, 1, n); // t[n] = nil - return 1; -} - -/* -** Copy elements (1[f], ..., 1[e]) into (tt[t], tt[t+1], ...). Whenever -** possible, copy in increasing order, which is better for rehashing. -** "possible" means destination after original range, or smaller -** than origin, or copying to another table. -*/ -static int tmove(lua_State* L) -{ - luaL_checktype(L, 1, LUA_TTABLE); - int f = luaL_checkinteger(L, 2); - int e = luaL_checkinteger(L, 3); - int t = luaL_checkinteger(L, 4); - int tt = !lua_isnoneornil(L, 5) ? 5 : 1; // destination table - luaL_checktype(L, tt, LUA_TTABLE); - - if (e >= f) - { // otherwise, nothing to move - luaL_argcheck(L, f > 0 || e < INT_MAX + f, 3, "too many elements to move"); - int n = e - f + 1; // number of elements to move - luaL_argcheck(L, t <= INT_MAX - n + 1, 4, "destination wrap around"); - - Table* dst = hvalue(L->base + (tt - 1)); - - if (dst->readonly) // also checked in moveelements, but this blocks resizes of r/o tables - luaG_readonlyerror(L); - - if (t > 0 && (t - 1) <= dst->sizearray && (t - 1 + n) > dst->sizearray) - { // grow the destination table array - luaH_resizearray(L, dst, t - 1 + n); - } - - moveelements(L, 1, tt, f, e, t); - } - lua_pushvalue(L, tt); // return destination table - return 1; -} - -static void addfield(lua_State* L, luaL_Strbuf* b, int i) -{ - int tt = lua_rawgeti(L, 1, i); - if (tt != LUA_TSTRING && tt != LUA_TNUMBER) - luaL_error(L, "invalid value (%s) at index %d in table for 'concat'", luaL_typename(L, -1), i); - luaL_addvalue(b); -} - -static int tconcat(lua_State* L) -{ - luaL_Strbuf b; - size_t lsep; - int i, last; - const char* sep = luaL_optlstring(L, 2, "", &lsep); - luaL_checktype(L, 1, LUA_TTABLE); - i = luaL_optinteger(L, 3, 1); - last = luaL_opt(L, luaL_checkinteger, 4, lua_objlen(L, 1)); - luaL_buffinit(L, &b); - for (; i < last; i++) - { - addfield(L, &b, i); - luaL_addlstring(&b, sep, lsep); - } - if (i == last) // add last value (if interval was not empty) - addfield(L, &b, i); - luaL_pushresult(&b); - return 1; -} - -static int tpack(lua_State* L) -{ - int n = lua_gettop(L); // number of elements to pack - lua_createtable(L, n, 1); // create result table - - Table* t = hvalue(L->top - 1); - - for (int i = 0; i < n; ++i) - { - TValue* e = &t->array[i]; - setobj2t(L, e, L->base + i); - } - - // t.n = number of elements - TValue* nv = luaH_setstr(L, t, luaS_newliteral(L, "n")); - setnvalue(nv, n); - - return 1; // return table -} - -static int tunpack(lua_State* L) -{ - luaL_checktype(L, 1, LUA_TTABLE); - Table* t = hvalue(L->base); - - int i = luaL_optinteger(L, 2, 1); - int e = luaL_opt(L, luaL_checkinteger, 3, lua_objlen(L, 1)); - if (i > e) - return 0; // empty range - unsigned n = (unsigned)e - i; // number of elements minus 1 (avoid overflows) - if (n >= (unsigned int)INT_MAX || !lua_checkstack(L, (int)(++n))) - luaL_error(L, "too many results to unpack"); - - // fast-path: direct array-to-stack copy - if (i == 1 && int(n) <= t->sizearray) - { - for (i = 0; i < int(n); i++) - setobj2s(L, L->top + i, &t->array[i]); - L->top += n; - } - else - { - // push arg[i..e - 1] (to avoid overflows) - for (; i < e; i++) - lua_rawgeti(L, 1, i); - lua_rawgeti(L, 1, e); // push last element - } - return (int)n; -} - -typedef int (*SortPredicate)(lua_State* L, const TValue* l, const TValue* r); - -static int sort_func(lua_State* L, const TValue* l, const TValue* r) -{ - LUAU_ASSERT(L->top == L->base + 2); // table, function - - setobj2s(L, L->top, &L->base[1]); - setobj2s(L, L->top + 1, l); - setobj2s(L, L->top + 2, r); - L->top += 3; // safe because of LUA_MINSTACK guarantee - luaD_call(L, L->top - 3, 1); - L->top -= 1; // maintain stack depth - - return !l_isfalse(L->top); -} - -inline void sort_swap(lua_State* L, Table* t, int i, int j) -{ - TValue* arr = t->array; - int n = t->sizearray; - LUAU_ASSERT(unsigned(i) < unsigned(n) && unsigned(j) < unsigned(n)); // contract maintained in sort_less after predicate call - - // no barrier required because both elements are in the array before and after the swap - TValue temp; - setobj2s(L, &temp, &arr[i]); - setobj2t(L, &arr[i], &arr[j]); - setobj2t(L, &arr[j], &temp); -} - -inline int sort_less(lua_State* L, Table* t, int i, int j, SortPredicate pred) -{ - TValue* arr = t->array; - int n = t->sizearray; - LUAU_ASSERT(unsigned(i) < unsigned(n) && unsigned(j) < unsigned(n)); // contract maintained in sort_less after predicate call - - int res = pred(L, &arr[i], &arr[j]); - - // predicate call may resize the table, which is invalid - if (t->sizearray != n) - luaL_error(L, "table modified during sorting"); - - return res; -} - -static void sort_siftheap(lua_State* L, Table* t, int l, int u, SortPredicate pred, int root) -{ - LUAU_ASSERT(l <= u); - int count = u - l + 1; - - // process all elements with two children - while (root * 2 + 2 < count) - { - int left = root * 2 + 1, right = root * 2 + 2; - int next = root; - next = sort_less(L, t, l + next, l + left, pred) ? left : next; - next = sort_less(L, t, l + next, l + right, pred) ? right : next; - - if (next == root) - break; - - sort_swap(L, t, l + root, l + next); - root = next; - } - - // process last element if it has just one child - int lastleft = root * 2 + 1; - if (lastleft == count - 1 && sort_less(L, t, l + root, l + lastleft, pred)) - sort_swap(L, t, l + root, l + lastleft); -} - -static void sort_heap(lua_State* L, Table* t, int l, int u, SortPredicate pred) -{ - LUAU_ASSERT(l <= u); - int count = u - l + 1; - - for (int i = count / 2 - 1; i >= 0; --i) - sort_siftheap(L, t, l, u, pred, i); - - for (int i = count - 1; i > 0; --i) - { - sort_swap(L, t, l, l + i); - sort_siftheap(L, t, l, l + i - 1, pred, 0); - } -} - -static void sort_rec(lua_State* L, Table* t, int l, int u, int limit, SortPredicate pred) -{ - // sort range [l..u] (inclusive, 0-based) - while (l < u) - { - // if the limit has been reached, quick sort is going over the permitted nlogn complexity, so we fall back to heap sort - if (limit == 0) - return sort_heap(L, t, l, u, pred); - - // sort elements a[l], a[(l+u)/2] and a[u] - // note: this simultaneously acts as a small sort and a median selector - if (sort_less(L, t, u, l, pred)) // a[u] < a[l]? - sort_swap(L, t, u, l); // swap a[l] - a[u] - if (u - l == 1) - break; // only 2 elements - int m = l + ((u - l) >> 1); // midpoint - if (sort_less(L, t, m, l, pred)) // a[m]= P - while (sort_less(L, t, ++i, p, pred)) - { - if (i >= u) - luaL_error(L, "invalid order function for sorting"); - } - // repeat --j until a[j] <= P - while (sort_less(L, t, p, --j, pred)) - { - if (j <= l) - luaL_error(L, "invalid order function for sorting"); - } - if (j < i) - break; - sort_swap(L, t, i, j); - } - - // swap pivot a[p] with a[i], which is the new midpoint - sort_swap(L, t, p, i); - - // adjust limit to allow 1.5 log2N recursive steps - limit = (limit >> 1) + (limit >> 2); - - // a[l..i-1] <= a[i] == P <= a[i+1..u] - // sort smaller half recursively; the larger half is sorted in the next loop iteration - if (i - l < u - i) - { - sort_rec(L, t, l, i - 1, limit, pred); - l = i + 1; - } - else - { - sort_rec(L, t, i + 1, u, limit, pred); - u = i - 1; - } - } -} - -static int tsort(lua_State* L) -{ - luaL_checktype(L, 1, LUA_TTABLE); - Table* t = hvalue(L->base); - int n = luaH_getn(t); - if (t->readonly) - luaG_readonlyerror(L); - - SortPredicate pred = luaV_lessthan; - if (!lua_isnoneornil(L, 2)) // is there a 2nd argument? - { - luaL_checktype(L, 2, LUA_TFUNCTION); - pred = sort_func; - } - lua_settop(L, 2); // make sure there are two arguments - - if (n > 0) - sort_rec(L, t, 0, n - 1, n, pred); - return 0; -} - -static int tcreate(lua_State* L) -{ - int size = luaL_checkinteger(L, 1); - if (size < 0) - luaL_argerror(L, 1, "size out of range"); - - if (!lua_isnoneornil(L, 2)) - { - lua_createtable(L, size, 0); - Table* t = hvalue(L->top - 1); - - StkId v = L->base + 1; - - for (int i = 0; i < size; ++i) - { - TValue* e = &t->array[i]; - setobj2t(L, e, v); - } - } - else - { - lua_createtable(L, size, 0); - } - - return 1; -} - -static int tfind(lua_State* L) -{ - luaL_checktype(L, 1, LUA_TTABLE); - luaL_checkany(L, 2); - int init = luaL_optinteger(L, 3, 1); - if (init < 1) - luaL_argerror(L, 3, "index out of range"); - - Table* t = hvalue(L->base); - StkId v = L->base + 1; - - for (int i = init;; ++i) - { - const TValue* e = luaH_getnum(t, i); - if (ttisnil(e)) - break; - - if (equalobj(L, v, e)) - { - lua_pushinteger(L, i); - return 1; - } - } - - lua_pushnil(L); - return 1; -} - -static int tclear(lua_State* L) -{ - luaL_checktype(L, 1, LUA_TTABLE); - - Table* tt = hvalue(L->base); - if (tt->readonly) - luaG_readonlyerror(L); - - luaH_clear(tt); - return 0; -} - -static int tfreeze(lua_State* L) -{ - luaL_checktype(L, 1, LUA_TTABLE); - luaL_argcheck(L, !lua_getreadonly(L, 1), 1, "table is already frozen"); - luaL_argcheck(L, !luaL_getmetafield(L, 1, "__metatable"), 1, "table has a protected metatable"); - - lua_setreadonly(L, 1, true); - - lua_pushvalue(L, 1); - return 1; -} - -static int tisfrozen(lua_State* L) -{ - luaL_checktype(L, 1, LUA_TTABLE); - - lua_pushboolean(L, lua_getreadonly(L, 1)); - return 1; -} - -static int tclone(lua_State* L) -{ - luaL_checktype(L, 1, LUA_TTABLE); - luaL_argcheck(L, !luaL_getmetafield(L, 1, "__metatable"), 1, "table has a protected metatable"); - - Table* tt = luaH_clone(L, hvalue(L->base)); - - TValue v; - sethvalue(L, &v, tt); - luaA_pushobject(L, &v); - - return 1; -} - -static const luaL_Reg tab_funcs[] = { - {"concat", tconcat}, - {"foreach", foreach}, - {"foreachi", foreachi}, - {"getn", getn}, - {"maxn", maxn}, - {"insert", tinsert}, - {"remove", tremove}, - {"sort", tsort}, - {"pack", tpack}, - {"unpack", tunpack}, - {"move", tmove}, - {"create", tcreate}, - {"find", tfind}, - {"clear", tclear}, - {"freeze", tfreeze}, - {"isfrozen", tisfrozen}, - {"clone", tclone}, - {NULL, NULL}, -}; - -int luaopen_table(lua_State* L) -{ - luaL_register(L, LUA_TABLIBNAME, tab_funcs); - - // Lua 5.1 compat - lua_pushcfunction(L, tunpack, "unpack"); - lua_setglobal(L, "unpack"); - - return 1; -} diff --git a/lib/luau/VM/src/ltm.cpp b/lib/luau/VM/src/ltm.cpp deleted file mode 100644 index 3a9fdda..0000000 --- a/lib/luau/VM/src/ltm.cpp +++ /dev/null @@ -1,158 +0,0 @@ -// This file is part of the Luau programming language and is licensed under MIT License; see LICENSE.txt for details -// This code is based on Lua 5.x implementation licensed under MIT License; see lua_LICENSE.txt for details -#include "ltm.h" - -#include "lstate.h" -#include "lstring.h" -#include "ludata.h" -#include "ltable.h" -#include "lgc.h" - -#include - -// clang-format off -const char* const luaT_typenames[] = { - // ORDER TYPE - "nil", - "boolean", - - - "userdata", - "number", - "vector", - - "string", - - - "table", - "function", - "userdata", - "thread", - "buffer", -}; - -const char* const luaT_eventname[] = { - // ORDER TM - - "__index", - "__newindex", - "__mode", - "__namecall", - "__call", - "__iter", - "__len", - - "__eq", - - - "__add", - "__sub", - "__mul", - "__div", - "__idiv", - "__mod", - "__pow", - "__unm", - - - "__lt", - "__le", - "__concat", - "__type", - "__metatable", -}; -// clang-format on - -static_assert(sizeof(luaT_typenames) / sizeof(luaT_typenames[0]) == LUA_T_COUNT, "luaT_typenames size mismatch"); -static_assert(sizeof(luaT_eventname) / sizeof(luaT_eventname[0]) == TM_N, "luaT_eventname size mismatch"); -static_assert(TM_EQ < 8, "fasttm optimization stores a bitfield with metamethods in a byte"); - -void luaT_init(lua_State* L) -{ - int i; - for (i = 0; i < LUA_T_COUNT; i++) - { - L->global->ttname[i] = luaS_new(L, luaT_typenames[i]); - luaS_fix(L->global->ttname[i]); // never collect these names - } - for (i = 0; i < TM_N; i++) - { - L->global->tmname[i] = luaS_new(L, luaT_eventname[i]); - luaS_fix(L->global->tmname[i]); // never collect these names - } -} - -/* -** function to be used with macro "fasttm": optimized for absence of -** tag methods. -*/ -const TValue* luaT_gettm(Table* events, TMS event, TString* ename) -{ - const TValue* tm = luaH_getstr(events, ename); - LUAU_ASSERT(event <= TM_EQ); - if (ttisnil(tm)) - { // no tag method? - events->tmcache |= cast_byte(1u << event); // cache this fact - return NULL; - } - else - return tm; -} - -const TValue* luaT_gettmbyobj(lua_State* L, const TValue* o, TMS event) -{ - /* - NB: Tag-methods were replaced by meta-methods in Lua 5.0, but the - old names are still around (this function, for example). - */ - Table* mt; - switch (ttype(o)) - { - case LUA_TTABLE: - mt = hvalue(o)->metatable; - break; - case LUA_TUSERDATA: - mt = uvalue(o)->metatable; - break; - default: - mt = L->global->mt[ttype(o)]; - } - return (mt ? luaH_getstr(mt, L->global->tmname[event]) : luaO_nilobject); -} - -const TString* luaT_objtypenamestr(lua_State* L, const TValue* o) -{ - if (ttisuserdata(o) && uvalue(o)->tag != UTAG_PROXY && uvalue(o)->metatable) - { - const TValue* type = luaH_getstr(uvalue(o)->metatable, L->global->tmname[TM_TYPE]); - - if (ttisstring(type)) - return tsvalue(type); - } - else if (FFlag::TaggedLuData && ttislightuserdata(o)) - { - int tag = lightuserdatatag(o); - - if (unsigned(tag) < LUA_LUTAG_LIMIT) - { - const TString* name = L->global->lightuserdataname[tag]; - - if (name) - return name; - } - } - else if (Table* mt = L->global->mt[ttype(o)]) - { - const TValue* type = luaH_getstr(mt, L->global->tmname[TM_TYPE]); - - if (ttisstring(type)) - return tsvalue(type); - } - - return L->global->ttname[ttype(o)]; -} - -const char* luaT_objtypename(lua_State* L, const TValue* o) -{ - return getstr(luaT_objtypenamestr(L, o)); -} diff --git a/lib/luau/VM/src/ltm.h b/lib/luau/VM/src/ltm.h deleted file mode 100644 index 7dafd4e..0000000 --- a/lib/luau/VM/src/ltm.h +++ /dev/null @@ -1,60 +0,0 @@ -// This file is part of the Luau programming language and is licensed under MIT License; see LICENSE.txt for details -// This code is based on Lua 5.x implementation licensed under MIT License; see lua_LICENSE.txt for details -#pragma once - -#include "lobject.h" - -/* - * WARNING: if you change the order of this enumeration, - * grep "ORDER TM" - */ -// clang-format off -typedef enum -{ - - TM_INDEX, - TM_NEWINDEX, - TM_MODE, - TM_NAMECALL, - TM_CALL, - TM_ITER, - TM_LEN, - - TM_EQ, // last tag method with `fast' access - - - TM_ADD, - TM_SUB, - TM_MUL, - TM_DIV, - TM_IDIV, - TM_MOD, - TM_POW, - TM_UNM, - - - TM_LT, - TM_LE, - TM_CONCAT, - TM_TYPE, - TM_METATABLE, - - TM_N // number of elements in the enum -} TMS; -// clang-format on - -#define gfasttm(g, et, e) ((et) == NULL ? NULL : ((et)->tmcache & (1u << (e))) ? NULL : luaT_gettm(et, e, (g)->tmname[e])) - -#define fasttm(l, et, e) gfasttm(l->global, et, e) -#define fastnotm(et, e) ((et) == NULL || ((et)->tmcache & (1u << (e)))) - -LUAI_DATA const char* const luaT_typenames[]; -LUAI_DATA const char* const luaT_eventname[]; - -LUAI_FUNC const TValue* luaT_gettm(Table* events, TMS event, TString* ename); -LUAI_FUNC const TValue* luaT_gettmbyobj(lua_State* L, const TValue* o, TMS event); - -LUAI_FUNC const TString* luaT_objtypenamestr(lua_State* L, const TValue* o); -LUAI_FUNC const char* luaT_objtypename(lua_State* L, const TValue* o); - -LUAI_FUNC void luaT_init(lua_State* L); diff --git a/lib/luau/VM/src/ludata.cpp b/lib/luau/VM/src/ludata.cpp deleted file mode 100644 index 13e8702..0000000 --- a/lib/luau/VM/src/ludata.cpp +++ /dev/null @@ -1,43 +0,0 @@ -// This file is part of the Luau programming language and is licensed under MIT License; see LICENSE.txt for details -// This code is based on Lua 5.x implementation licensed under MIT License; see lua_LICENSE.txt for details -#include "ludata.h" - -#include "lgc.h" -#include "lmem.h" - -#include - -Udata* luaU_newudata(lua_State* L, size_t s, int tag) -{ - if (s > INT_MAX - sizeof(Udata)) - luaM_toobig(L); - Udata* u = luaM_newgco(L, Udata, sizeudata(s), L->activememcat); - luaC_init(L, u, LUA_TUSERDATA); - u->len = int(s); - u->metatable = NULL; - LUAU_ASSERT(tag >= 0 && tag <= 255); - u->tag = uint8_t(tag); - return u; -} - -void luaU_freeudata(lua_State* L, Udata* u, lua_Page* page) -{ - if (u->tag < LUA_UTAG_LIMIT) - { - lua_Destructor dtor = L->global->udatagc[u->tag]; - // TODO: access to L here is highly unsafe since this is called during internal GC traversal - // certain operations such as lua_getthreaddata are okay, but by and large this risks crashes on improper use - if (dtor) - dtor(L, u->data); - } - else if (u->tag == UTAG_IDTOR) - { - void (*dtor)(void*) = nullptr; - memcpy(&dtor, &u->data + u->len - sizeof(dtor), sizeof(dtor)); - if (dtor) - dtor(u->data); - } - - - luaM_freegco(L, u, sizeudata(u->len), u->memcat, page); -} diff --git a/lib/luau/VM/src/ludata.h b/lib/luau/VM/src/ludata.h deleted file mode 100644 index 9b7ba26..0000000 --- a/lib/luau/VM/src/ludata.h +++ /dev/null @@ -1,16 +0,0 @@ -// This file is part of the Luau programming language and is licensed under MIT License; see LICENSE.txt for details -// This code is based on Lua 5.x implementation licensed under MIT License; see lua_LICENSE.txt for details -#pragma once - -#include "lobject.h" - -// special tag value is used for user data with inline dtors -#define UTAG_IDTOR LUA_UTAG_LIMIT - -// special tag value is used for newproxy-created user data (all other user data objects are host-exposed) -#define UTAG_PROXY (LUA_UTAG_LIMIT + 1) - -#define sizeudata(len) (offsetof(Udata, data) + len) - -LUAI_FUNC Udata* luaU_newudata(lua_State* L, size_t s, int tag); -LUAI_FUNC void luaU_freeudata(lua_State* L, Udata* u, struct lua_Page* page); diff --git a/lib/luau/VM/src/lutf8lib.cpp b/lib/luau/VM/src/lutf8lib.cpp deleted file mode 100644 index ef99b94..0000000 --- a/lib/luau/VM/src/lutf8lib.cpp +++ /dev/null @@ -1,298 +0,0 @@ -// This file is part of the Luau programming language and is licensed under MIT License; see LICENSE.txt for details -// This code is based on Lua 5.x implementation licensed under MIT License; see lua_LICENSE.txt for details -#include "lualib.h" - -#include "lcommon.h" - -#define MAXUNICODE 0x10FFFF - -#define iscont(p) ((*(p)&0xC0) == 0x80) - -LUAU_DYNAMIC_FASTFLAGVARIABLE(LuauStricterUtf8, false) - -// from strlib -// translate a relative string position: negative means back from end -static int u_posrelat(int pos, size_t len) -{ - if (pos >= 0) - return pos; - else if (0u - (size_t)pos > len) - return 0; - else - return (int)len + pos + 1; -} - -/* -** Decode one UTF-8 sequence, returning NULL if byte sequence is invalid. -*/ -static const char* utf8_decode(const char* o, int* val) -{ - static const unsigned int limits[] = {0xFF, 0x7F, 0x7FF, 0xFFFF}; - const unsigned char* s = (const unsigned char*)o; - unsigned int c = s[0]; - unsigned int res = 0; // final result - if (c < 0x80) // ascii? - res = c; - else - { - int count = 0; // to count number of continuation bytes - while (c & 0x40) - { // still have continuation bytes? - int cc = s[++count]; // read next byte - if ((cc & 0xC0) != 0x80) // not a continuation byte? - return NULL; // invalid byte sequence - res = (res << 6) | (cc & 0x3F); // add lower 6 bits from cont. byte - c <<= 1; // to test next bit - } - res |= ((c & 0x7F) << (count * 5)); // add first byte - if (count > 3 || res > MAXUNICODE || res <= limits[count]) - return NULL; // invalid byte sequence - if (DFFlag::LuauStricterUtf8 && unsigned(res - 0xD800) < 0x800) - return NULL; // surrogate - s += count; // skip continuation bytes read - } - if (val) - *val = res; - return (const char*)s + 1; // +1 to include first byte -} - -/* -** utf8len(s [, i [, j]]) --> number of characters that start in the -** range [i,j], or nil + current position if 's' is not well formed in -** that interval -*/ -static int utflen(lua_State* L) -{ - int n = 0; - size_t len; - const char* s = luaL_checklstring(L, 1, &len); - int posi = u_posrelat(luaL_optinteger(L, 2, 1), len); - int posj = u_posrelat(luaL_optinteger(L, 3, -1), len); - luaL_argcheck(L, 1 <= posi && --posi <= (int)len, 2, "initial position out of string"); - luaL_argcheck(L, --posj < (int)len, 3, "final position out of string"); - while (posi <= posj) - { - const char* s1 = utf8_decode(s + posi, NULL); - if (s1 == NULL) - { // conversion error? - lua_pushnil(L); // return nil ... - lua_pushinteger(L, posi + 1); // ... and current position - return 2; - } - posi = (int)(s1 - s); - n++; - } - lua_pushinteger(L, n); - return 1; -} - -/* -** codepoint(s, [i, [j]]) -> returns codepoints for all characters -** that start in the range [i,j] -*/ -static int codepoint(lua_State* L) -{ - size_t len; - const char* s = luaL_checklstring(L, 1, &len); - int posi = u_posrelat(luaL_optinteger(L, 2, 1), len); - int pose = u_posrelat(luaL_optinteger(L, 3, posi), len); - int n; - const char* se; - luaL_argcheck(L, posi >= 1, 2, "out of range"); - luaL_argcheck(L, pose <= (int)len, 3, "out of range"); - if (posi > pose) - return 0; // empty interval; return no values - if (pose - posi >= INT_MAX) // (int -> int) overflow? - luaL_error(L, "string slice too long"); - n = (int)(pose - posi) + 1; - luaL_checkstack(L, n, "string slice too long"); - n = 0; - se = s + pose; - for (s += posi - 1; s < se;) - { - int code; - s = utf8_decode(s, &code); - if (s == NULL) - luaL_error(L, "invalid UTF-8 code"); - lua_pushinteger(L, code); - n++; - } - return n; -} - -// from Lua 5.3 lobject.h -#define UTF8BUFFSZ 8 - -// from Lua 5.3 lobject.c, copied verbatim + static -static int luaO_utf8esc(char* buff, unsigned long x) -{ - int n = 1; // number of bytes put in buffer (backwards) - LUAU_ASSERT(x <= 0x10FFFF); - if (x < 0x80) // ascii? - buff[UTF8BUFFSZ - 1] = cast_to(char, x); - else - { // need continuation bytes - unsigned int mfb = 0x3f; // maximum that fits in first byte - do - { // add continuation bytes - buff[UTF8BUFFSZ - (n++)] = cast_to(char, 0x80 | (x & 0x3f)); - x >>= 6; // remove added bits - mfb >>= 1; // now there is one less bit available in first byte - } while (x > mfb); // still needs continuation byte? - buff[UTF8BUFFSZ - n] = cast_to(char, (~mfb << 1) | x); // add first byte - } - return n; -} - -// lighter replacement for pushutfchar; doesn't push any string onto the stack -static int buffutfchar(lua_State* L, int arg, char* buff, const char** charstr) -{ - int code = luaL_checkinteger(L, arg); - luaL_argcheck(L, 0 <= code && code <= MAXUNICODE, arg, "value out of range"); - int l = luaO_utf8esc(buff, cast_to(long, code)); - *charstr = buff + UTF8BUFFSZ - l; - return l; -} - -/* -** utfchar(n1, n2, ...) -> char(n1)..char(n2)... -** -** This version avoids the need to make more invasive upgrades elsewhere (like -** implementing the %U escape in lua_pushfstring) and avoids pushing string -** objects for each codepoint in the multi-argument case. -Jovanni -*/ -static int utfchar(lua_State* L) -{ - char buff[UTF8BUFFSZ]; - const char* charstr; - - int n = lua_gettop(L); // number of arguments - if (n == 1) - { // optimize common case of single char - int l = buffutfchar(L, 1, buff, &charstr); - lua_pushlstring(L, charstr, l); - } - else - { - luaL_Strbuf b; - luaL_buffinit(L, &b); - for (int i = 1; i <= n; i++) - { - int l = buffutfchar(L, i, buff, &charstr); - luaL_addlstring(&b, charstr, l); - } - luaL_pushresult(&b); - } - return 1; -} - -/* -** offset(s, n, [i]) -> index where n-th character counting from -** position 'i' starts; 0 means character at 'i'. -*/ -static int byteoffset(lua_State* L) -{ - size_t len; - const char* s = luaL_checklstring(L, 1, &len); - int n = luaL_checkinteger(L, 2); - int posi = (n >= 0) ? 1 : (int)len + 1; - posi = u_posrelat(luaL_optinteger(L, 3, posi), len); - luaL_argcheck(L, 1 <= posi && --posi <= (int)len, 3, "position out of range"); - if (n == 0) - { - // find beginning of current byte sequence - while (posi > 0 && iscont(s + posi)) - posi--; - } - else - { - if (iscont(s + posi)) - luaL_error(L, "initial position is a continuation byte"); - if (n < 0) - { - while (n < 0 && posi > 0) - { // move back - do - { // find beginning of previous character - posi--; - } while (posi > 0 && iscont(s + posi)); - n++; - } - } - else - { - n--; // do not move for 1st character - while (n > 0 && posi < (int)len) - { - do - { // find beginning of next character - posi++; - } while (iscont(s + posi)); // (cannot pass final '\0') - n--; - } - } - } - if (n == 0) // did it find given character? - lua_pushinteger(L, posi + 1); - else // no such character - lua_pushnil(L); - return 1; -} - -static int iter_aux(lua_State* L) -{ - size_t len; - const char* s = luaL_checklstring(L, 1, &len); - int n = lua_tointeger(L, 2) - 1; - if (n < 0) // first iteration? - n = 0; // start from here - else if (n < (int)len) - { - n++; // skip current byte - while (iscont(s + n)) - n++; // and its continuations - } - if (n >= (int)len) - return 0; // no more codepoints - else - { - int code; - const char* next = utf8_decode(s + n, &code); - if (next == NULL || iscont(next)) - luaL_error(L, "invalid UTF-8 code"); - lua_pushinteger(L, n + 1); - lua_pushinteger(L, code); - return 2; - } -} - -static int iter_codes(lua_State* L) -{ - luaL_checkstring(L, 1); - lua_pushcfunction(L, iter_aux, NULL); - lua_pushvalue(L, 1); - lua_pushinteger(L, 0); - return 3; -} - -// pattern to match a single UTF-8 character -#define UTF8PATT "[\0-\x7F\xC2-\xF4][\x80-\xBF]*" - -static const luaL_Reg funcs[] = { - {"offset", byteoffset}, - {"codepoint", codepoint}, - {"char", utfchar}, - {"len", utflen}, - {"codes", iter_codes}, - {NULL, NULL}, -}; - -int luaopen_utf8(lua_State* L) -{ - luaL_register(L, LUA_UTF8LIBNAME, funcs); - - lua_pushlstring(L, UTF8PATT, sizeof(UTF8PATT) / sizeof(char) - 1); - lua_setfield(L, -2, "charpattern"); - - return 1; -} diff --git a/lib/luau/VM/src/lvm.h b/lib/luau/VM/src/lvm.h deleted file mode 100644 index 5ec7bc1..0000000 --- a/lib/luau/VM/src/lvm.h +++ /dev/null @@ -1,34 +0,0 @@ -// This file is part of the Luau programming language and is licensed under MIT License; see LICENSE.txt for details -// This code is based on Lua 5.x implementation licensed under MIT License; see lua_LICENSE.txt for details -#pragma once - -#include "lobject.h" -#include "ltm.h" - -#define tostring(L, o) ((ttype(o) == LUA_TSTRING) || (luaV_tostring(L, o))) - -#define tonumber(o, n) (ttype(o) == LUA_TNUMBER || (((o) = luaV_tonumber(o, n)) != NULL)) - -#define equalobj(L, o1, o2) (ttype(o1) == ttype(o2) && luaV_equalval(L, o1, o2)) - -LUAI_FUNC int luaV_strcmp(const TString* ls, const TString* rs); -LUAI_FUNC int luaV_lessthan(lua_State* L, const TValue* l, const TValue* r); -LUAI_FUNC int luaV_lessequal(lua_State* L, const TValue* l, const TValue* r); -LUAI_FUNC int luaV_equalval(lua_State* L, const TValue* t1, const TValue* t2); -LUAI_FUNC void luaV_doarith(lua_State* L, StkId ra, const TValue* rb, const TValue* rc, TMS op); -LUAI_FUNC void luaV_dolen(lua_State* L, StkId ra, const TValue* rb); -LUAI_FUNC const TValue* luaV_tonumber(const TValue* obj, TValue* n); -LUAI_FUNC const float* luaV_tovector(const TValue* obj); -LUAI_FUNC int luaV_tostring(lua_State* L, StkId obj); -LUAI_FUNC void luaV_gettable(lua_State* L, const TValue* t, TValue* key, StkId val); -LUAI_FUNC void luaV_settable(lua_State* L, const TValue* t, TValue* key, StkId val); -LUAI_FUNC void luaV_concat(lua_State* L, int total, int last); -LUAI_FUNC void luaV_getimport(lua_State* L, Table* env, TValue* k, StkId res, uint32_t id, bool propagatenil); -LUAI_FUNC void luaV_prepareFORN(lua_State* L, StkId plimit, StkId pstep, StkId pinit); -LUAI_FUNC void luaV_callTM(lua_State* L, int nparams, int res); -LUAI_FUNC void luaV_tryfuncTM(lua_State* L, StkId func); - -LUAI_FUNC void luau_execute(lua_State* L); -LUAI_FUNC int luau_precall(lua_State* L, struct lua_TValue* func, int nresults); -LUAI_FUNC void luau_poscall(lua_State* L, StkId first); -LUAI_FUNC void luau_callhook(lua_State* L, lua_Hook hook, void* userdata); diff --git a/lib/luau/VM/src/lvmexecute.cpp b/lib/luau/VM/src/lvmexecute.cpp deleted file mode 100644 index 1c77fa1..0000000 --- a/lib/luau/VM/src/lvmexecute.cpp +++ /dev/null @@ -1,3097 +0,0 @@ -// This file is part of the Luau programming language and is licensed under MIT License; see LICENSE.txt for details -// This code is based on Lua 5.x implementation licensed under MIT License; see lua_LICENSE.txt for details -#include "lvm.h" - -#include "lstate.h" -#include "ltable.h" -#include "lfunc.h" -#include "lstring.h" -#include "lgc.h" -#include "lmem.h" -#include "ldebug.h" -#include "ldo.h" -#include "lbuiltins.h" -#include "lnumutils.h" -#include "lbytecode.h" - -#include - -// Disable c99-designator to avoid the warning in CGOTO dispatch table -#ifdef __clang__ -#if __has_warning("-Wc99-designator") -#pragma clang diagnostic ignored "-Wc99-designator" -#endif -#endif - -// When working with VM code, pay attention to these rules for correctness: -// 1. Many external Lua functions can fail; for them to fail and be able to generate a proper stack, we need to copy pc to L->ci->savedpc before the -// call -// 2. Many external Lua functions can reallocate the stack. This invalidates stack pointers in VM C stack frame, most importantly base, but also -// ra/rb/rc! -// 3. VM_PROTECT macro saves savedpc and restores base for you; most external calls need to be wrapped into that. However, it does NOT restore -// ra/rb/rc! -// 4. When copying an object to any existing object as a field, generally speaking you need to call luaC_barrier! Be careful with all setobj calls -// 5. To make 4 easier to follow, please use setobj2s for copies to stack, setobj2t for writes to tables, and setobj for other copies. -// 6. You can define HARDSTACKTESTS in llimits.h which will aggressively realloc stack; with address sanitizer this should be effective at finding -// stack corruption bugs -// 7. Many external Lua functions can call GC! GC will *not* traverse pointers to new objects that aren't reachable from Lua root. Be careful when -// creating new Lua objects, store them to stack soon. - -// When calling luau_callTM, we usually push the arguments to the top of the stack. -// This is safe to do for complicated reasons: -// - stack guarantees EXTRA_STACK room beyond stack_last (see luaD_reallocstack) -// - stack reallocation copies values past stack_last - -// All external function calls that can cause stack realloc or Lua calls have to be wrapped in VM_PROTECT -// This makes sure that we save the pc (in case the Lua call needs to generate a backtrace) before the call, -// and restores the stack pointer after in case stack gets reallocated -// Should only be used on the slow paths. -#define VM_PROTECT(x) \ - { \ - L->ci->savedpc = pc; \ - { \ - x; \ - }; \ - base = L->base; \ - } - -// Some external functions can cause an error, but never reallocate the stack; for these, VM_PROTECT_PC() is -// a cheaper version of VM_PROTECT that can be called before the external call. -#define VM_PROTECT_PC() L->ci->savedpc = pc - -#define VM_REG(i) (LUAU_ASSERT(unsigned(i) < unsigned(L->top - base)), &base[i]) -#define VM_KV(i) (LUAU_ASSERT(unsigned(i) < unsigned(cl->l.p->sizek)), &k[i]) -#define VM_UV(i) (LUAU_ASSERT(unsigned(i) < unsigned(cl->nupvalues)), &cl->l.uprefs[i]) - -#define VM_PATCH_C(pc, slot) *const_cast(pc) = ((uint8_t(slot) << 24) | (0x00ffffffu & *(pc))) -#define VM_PATCH_E(pc, slot) *const_cast(pc) = ((uint32_t(slot) << 8) | (0x000000ffu & *(pc))) - -#define VM_INTERRUPT() \ - { \ - void (*interrupt)(lua_State*, int) = L->global->cb.interrupt; \ - if (LUAU_UNLIKELY(!!interrupt)) \ - { /* the interrupt hook is called right before we advance pc */ \ - VM_PROTECT(L->ci->savedpc++; interrupt(L, -1)); \ - if (L->status != 0) \ - { \ - L->ci->savedpc--; \ - goto exit; \ - } \ - } \ - } - - -#define VM_DISPATCH_OP(op) &&CASE_##op - - -#define VM_DISPATCH_TABLE() \ - VM_DISPATCH_OP(LOP_NOP), VM_DISPATCH_OP(LOP_BREAK), VM_DISPATCH_OP(LOP_LOADNIL), VM_DISPATCH_OP(LOP_LOADB), VM_DISPATCH_OP(LOP_LOADN), \ - VM_DISPATCH_OP(LOP_LOADK), VM_DISPATCH_OP(LOP_MOVE), VM_DISPATCH_OP(LOP_GETGLOBAL), VM_DISPATCH_OP(LOP_SETGLOBAL), \ - VM_DISPATCH_OP(LOP_GETUPVAL), VM_DISPATCH_OP(LOP_SETUPVAL), VM_DISPATCH_OP(LOP_CLOSEUPVALS), VM_DISPATCH_OP(LOP_GETIMPORT), \ - VM_DISPATCH_OP(LOP_GETTABLE), VM_DISPATCH_OP(LOP_SETTABLE), VM_DISPATCH_OP(LOP_GETTABLEKS), VM_DISPATCH_OP(LOP_SETTABLEKS), \ - VM_DISPATCH_OP(LOP_GETTABLEN), VM_DISPATCH_OP(LOP_SETTABLEN), VM_DISPATCH_OP(LOP_NEWCLOSURE), VM_DISPATCH_OP(LOP_NAMECALL), \ - VM_DISPATCH_OP(LOP_CALL), VM_DISPATCH_OP(LOP_RETURN), VM_DISPATCH_OP(LOP_JUMP), VM_DISPATCH_OP(LOP_JUMPBACK), VM_DISPATCH_OP(LOP_JUMPIF), \ - VM_DISPATCH_OP(LOP_JUMPIFNOT), VM_DISPATCH_OP(LOP_JUMPIFEQ), VM_DISPATCH_OP(LOP_JUMPIFLE), VM_DISPATCH_OP(LOP_JUMPIFLT), \ - VM_DISPATCH_OP(LOP_JUMPIFNOTEQ), VM_DISPATCH_OP(LOP_JUMPIFNOTLE), VM_DISPATCH_OP(LOP_JUMPIFNOTLT), VM_DISPATCH_OP(LOP_ADD), \ - VM_DISPATCH_OP(LOP_SUB), VM_DISPATCH_OP(LOP_MUL), VM_DISPATCH_OP(LOP_DIV), VM_DISPATCH_OP(LOP_MOD), VM_DISPATCH_OP(LOP_POW), \ - VM_DISPATCH_OP(LOP_ADDK), VM_DISPATCH_OP(LOP_SUBK), VM_DISPATCH_OP(LOP_MULK), VM_DISPATCH_OP(LOP_DIVK), VM_DISPATCH_OP(LOP_MODK), \ - VM_DISPATCH_OP(LOP_POWK), VM_DISPATCH_OP(LOP_AND), VM_DISPATCH_OP(LOP_OR), VM_DISPATCH_OP(LOP_ANDK), VM_DISPATCH_OP(LOP_ORK), \ - VM_DISPATCH_OP(LOP_CONCAT), VM_DISPATCH_OP(LOP_NOT), VM_DISPATCH_OP(LOP_MINUS), VM_DISPATCH_OP(LOP_LENGTH), VM_DISPATCH_OP(LOP_NEWTABLE), \ - VM_DISPATCH_OP(LOP_DUPTABLE), VM_DISPATCH_OP(LOP_SETLIST), VM_DISPATCH_OP(LOP_FORNPREP), VM_DISPATCH_OP(LOP_FORNLOOP), \ - VM_DISPATCH_OP(LOP_FORGLOOP), VM_DISPATCH_OP(LOP_FORGPREP_INEXT), VM_DISPATCH_OP(LOP_DEP_FORGLOOP_INEXT), VM_DISPATCH_OP(LOP_FORGPREP_NEXT), \ - VM_DISPATCH_OP(LOP_NATIVECALL), VM_DISPATCH_OP(LOP_GETVARARGS), VM_DISPATCH_OP(LOP_DUPCLOSURE), VM_DISPATCH_OP(LOP_PREPVARARGS), \ - VM_DISPATCH_OP(LOP_LOADKX), VM_DISPATCH_OP(LOP_JUMPX), VM_DISPATCH_OP(LOP_FASTCALL), VM_DISPATCH_OP(LOP_COVERAGE), \ - VM_DISPATCH_OP(LOP_CAPTURE), VM_DISPATCH_OP(LOP_SUBRK), VM_DISPATCH_OP(LOP_DIVRK), VM_DISPATCH_OP(LOP_FASTCALL1), \ - VM_DISPATCH_OP(LOP_FASTCALL2), VM_DISPATCH_OP(LOP_FASTCALL2K), VM_DISPATCH_OP(LOP_FORGPREP), VM_DISPATCH_OP(LOP_JUMPXEQKNIL), \ - VM_DISPATCH_OP(LOP_JUMPXEQKB), VM_DISPATCH_OP(LOP_JUMPXEQKN), VM_DISPATCH_OP(LOP_JUMPXEQKS), VM_DISPATCH_OP(LOP_IDIV), \ - VM_DISPATCH_OP(LOP_IDIVK), - -#if defined(__GNUC__) || defined(__clang__) -#define VM_USE_CGOTO 1 -#else -#define VM_USE_CGOTO 0 -#endif - -/** - * These macros help dispatching Luau opcodes using either case - * statements or computed goto. - * VM_CASE(op) Generates either a case statement or a label - * VM_NEXT() fetch a byte and dispatch or jump to the beginning of the switch statement - * VM_CONTINUE() Use an opcode override to dispatch with computed goto or - * switch statement to skip a LOP_BREAK instruction. - */ -#if VM_USE_CGOTO -#define VM_CASE(op) CASE_##op: -#define VM_NEXT() goto*(SingleStep ? &&dispatch : kDispatchTable[LUAU_INSN_OP(*pc)]) -#define VM_CONTINUE(op) goto* kDispatchTable[uint8_t(op)] -#else -#define VM_CASE(op) case op: -#define VM_NEXT() goto dispatch -#define VM_CONTINUE(op) \ - dispatchOp = uint8_t(op); \ - goto dispatchContinue -#endif - -// Does VM support native execution via ExecutionCallbacks? We mostly assume it does but keep the define to make it easy to quantify the cost. -#define VM_HAS_NATIVE 1 - -LUAU_FASTFLAGVARIABLE(TaggedLuData, false) - -LUAU_NOINLINE void luau_callhook(lua_State* L, lua_Hook hook, void* userdata) -{ - ptrdiff_t base = savestack(L, L->base); - ptrdiff_t top = savestack(L, L->top); - ptrdiff_t ci_top = savestack(L, L->ci->top); - int status = L->status; - - // if the hook is called externally on a paused thread, we need to make sure the paused thread can emit Lua calls - if (status == LUA_YIELD || status == LUA_BREAK) - { - L->status = 0; - L->base = L->ci->base; - } - - // note: the pc expectations of the hook are matching the general "pc points to next instruction" - // however, for the hook to be able to continue execution from the same point, this is called with savedpc at the *current* instruction - // this needs to be called before luaD_checkstack in case it fails to reallocate stack - if (L->ci->savedpc) - L->ci->savedpc++; - - luaD_checkstack(L, LUA_MINSTACK); // ensure minimum stack size - L->ci->top = L->top + LUA_MINSTACK; - LUAU_ASSERT(L->ci->top <= L->stack_last); - - Closure* cl = clvalue(L->ci->func); - - lua_Debug ar; - ar.currentline = cl->isC ? -1 : luaG_getline(cl->l.p, pcRel(L->ci->savedpc, cl->l.p)); - ar.userdata = userdata; - - hook(L, &ar); - - if (L->ci->savedpc) - L->ci->savedpc--; - - L->ci->top = restorestack(L, ci_top); - L->top = restorestack(L, top); - - // note that we only restore the paused state if the hook hasn't yielded by itself - if (status == LUA_YIELD && L->status != LUA_YIELD) - { - L->status = LUA_YIELD; - L->base = restorestack(L, base); - } - else if (status == LUA_BREAK) - { - LUAU_ASSERT(L->status != LUA_BREAK); // hook shouldn't break again - - L->status = LUA_BREAK; - L->base = restorestack(L, base); - } -} - -inline bool luau_skipstep(uint8_t op) -{ - return op == LOP_PREPVARARGS || op == LOP_BREAK; -} - -template -static void luau_execute(lua_State* L) -{ -#if VM_USE_CGOTO - static const void* kDispatchTable[256] = {VM_DISPATCH_TABLE()}; -#endif - - // the critical interpreter state, stored in locals for performance - // the hope is that these map to registers without spilling (which is not true for x86 :/) - Closure* cl; - StkId base; - TValue* k; - const Instruction* pc; - - LUAU_ASSERT(isLua(L->ci)); - LUAU_ASSERT(L->isactive); - LUAU_ASSERT(!isblack(obj2gco(L))); // we don't use luaC_threadbarrier because active threads never turn black - -#if VM_HAS_NATIVE - if ((L->ci->flags & LUA_CALLINFO_NATIVE) && !SingleStep) - { - Proto* p = clvalue(L->ci->func)->l.p; - LUAU_ASSERT(p->execdata); - - if (L->global->ecb.enter(L, p) == 0) - return; - } - -reentry: -#endif - - LUAU_ASSERT(isLua(L->ci)); - - pc = L->ci->savedpc; - cl = clvalue(L->ci->func); - base = L->base; - k = cl->l.p->k; - - VM_NEXT(); // starts the interpreter "loop" - - { - dispatch: - // Note: this code doesn't always execute! on some platforms we use computed goto which bypasses all of this unless we run in single-step mode - // Therefore only ever put assertions here. - LUAU_ASSERT(base == L->base && L->base == L->ci->base); - LUAU_ASSERT(base <= L->top && L->top <= L->stack + L->stacksize); - - // ... and singlestep logic :) - if (SingleStep) - { - if (L->global->cb.debugstep && !luau_skipstep(LUAU_INSN_OP(*pc))) - { - VM_PROTECT(luau_callhook(L, L->global->cb.debugstep, NULL)); - - // allow debugstep hook to put thread into error/yield state - if (L->status != 0) - goto exit; - } - -#if VM_USE_CGOTO - VM_CONTINUE(LUAU_INSN_OP(*pc)); -#endif - } - -#if !VM_USE_CGOTO - size_t dispatchOp = LUAU_INSN_OP(*pc); - - dispatchContinue: - switch (dispatchOp) -#endif - { - VM_CASE(LOP_NOP) - { - Instruction insn = *pc++; - LUAU_ASSERT(insn == 0); - VM_NEXT(); - } - - VM_CASE(LOP_LOADNIL) - { - Instruction insn = *pc++; - StkId ra = VM_REG(LUAU_INSN_A(insn)); - - setnilvalue(ra); - VM_NEXT(); - } - - VM_CASE(LOP_LOADB) - { - Instruction insn = *pc++; - StkId ra = VM_REG(LUAU_INSN_A(insn)); - - setbvalue(ra, LUAU_INSN_B(insn)); - - pc += LUAU_INSN_C(insn); - LUAU_ASSERT(unsigned(pc - cl->l.p->code) < unsigned(cl->l.p->sizecode)); - VM_NEXT(); - } - - VM_CASE(LOP_LOADN) - { - Instruction insn = *pc++; - StkId ra = VM_REG(LUAU_INSN_A(insn)); - - setnvalue(ra, LUAU_INSN_D(insn)); - VM_NEXT(); - } - - VM_CASE(LOP_LOADK) - { - Instruction insn = *pc++; - StkId ra = VM_REG(LUAU_INSN_A(insn)); - TValue* kv = VM_KV(LUAU_INSN_D(insn)); - - setobj2s(L, ra, kv); - VM_NEXT(); - } - - VM_CASE(LOP_MOVE) - { - Instruction insn = *pc++; - StkId ra = VM_REG(LUAU_INSN_A(insn)); - StkId rb = VM_REG(LUAU_INSN_B(insn)); - - setobj2s(L, ra, rb); - VM_NEXT(); - } - - VM_CASE(LOP_GETGLOBAL) - { - Instruction insn = *pc++; - StkId ra = VM_REG(LUAU_INSN_A(insn)); - uint32_t aux = *pc++; - TValue* kv = VM_KV(aux); - LUAU_ASSERT(ttisstring(kv)); - - // fast-path: value is in expected slot - Table* h = cl->env; - int slot = LUAU_INSN_C(insn) & h->nodemask8; - LuaNode* n = &h->node[slot]; - - if (LUAU_LIKELY(ttisstring(gkey(n)) && tsvalue(gkey(n)) == tsvalue(kv)) && !ttisnil(gval(n))) - { - setobj2s(L, ra, gval(n)); - VM_NEXT(); - } - else - { - // slow-path, may invoke Lua calls via __index metamethod - TValue g; - sethvalue(L, &g, h); - L->cachedslot = slot; - VM_PROTECT(luaV_gettable(L, &g, kv, ra)); - // save cachedslot to accelerate future lookups; patches currently executing instruction since pc-2 rolls back two pc++ - VM_PATCH_C(pc - 2, L->cachedslot); - VM_NEXT(); - } - } - - VM_CASE(LOP_SETGLOBAL) - { - Instruction insn = *pc++; - StkId ra = VM_REG(LUAU_INSN_A(insn)); - uint32_t aux = *pc++; - TValue* kv = VM_KV(aux); - LUAU_ASSERT(ttisstring(kv)); - - // fast-path: value is in expected slot - Table* h = cl->env; - int slot = LUAU_INSN_C(insn) & h->nodemask8; - LuaNode* n = &h->node[slot]; - - if (LUAU_LIKELY(ttisstring(gkey(n)) && tsvalue(gkey(n)) == tsvalue(kv) && !ttisnil(gval(n)) && !h->readonly)) - { - setobj2t(L, gval(n), ra); - luaC_barriert(L, h, ra); - VM_NEXT(); - } - else - { - // slow-path, may invoke Lua calls via __newindex metamethod - TValue g; - sethvalue(L, &g, h); - L->cachedslot = slot; - VM_PROTECT(luaV_settable(L, &g, kv, ra)); - // save cachedslot to accelerate future lookups; patches currently executing instruction since pc-2 rolls back two pc++ - VM_PATCH_C(pc - 2, L->cachedslot); - VM_NEXT(); - } - } - - VM_CASE(LOP_GETUPVAL) - { - Instruction insn = *pc++; - StkId ra = VM_REG(LUAU_INSN_A(insn)); - TValue* ur = VM_UV(LUAU_INSN_B(insn)); - TValue* v = ttisupval(ur) ? upvalue(ur)->v : ur; - - setobj2s(L, ra, v); - VM_NEXT(); - } - - VM_CASE(LOP_SETUPVAL) - { - Instruction insn = *pc++; - StkId ra = VM_REG(LUAU_INSN_A(insn)); - TValue* ur = VM_UV(LUAU_INSN_B(insn)); - UpVal* uv = upvalue(ur); - - setobj(L, uv->v, ra); - luaC_barrier(L, uv, ra); - VM_NEXT(); - } - - VM_CASE(LOP_CLOSEUPVALS) - { - Instruction insn = *pc++; - StkId ra = VM_REG(LUAU_INSN_A(insn)); - - if (L->openupval && L->openupval->v >= ra) - luaF_close(L, ra); - VM_NEXT(); - } - - VM_CASE(LOP_GETIMPORT) - { - Instruction insn = *pc++; - StkId ra = VM_REG(LUAU_INSN_A(insn)); - TValue* kv = VM_KV(LUAU_INSN_D(insn)); - - // fast-path: import resolution was successful and closure environment is "safe" for import - if (!ttisnil(kv) && cl->env->safeenv) - { - setobj2s(L, ra, kv); - pc++; // skip over AUX - VM_NEXT(); - } - else - { - uint32_t aux = *pc++; - - VM_PROTECT(luaV_getimport(L, cl->env, k, ra, aux, /* propagatenil= */ false)); - VM_NEXT(); - } - } - - VM_CASE(LOP_GETTABLEKS) - { - Instruction insn = *pc++; - StkId ra = VM_REG(LUAU_INSN_A(insn)); - StkId rb = VM_REG(LUAU_INSN_B(insn)); - uint32_t aux = *pc++; - TValue* kv = VM_KV(aux); - LUAU_ASSERT(ttisstring(kv)); - - // fast-path: built-in table - if (LUAU_LIKELY(ttistable(rb))) - { - Table* h = hvalue(rb); - - int slot = LUAU_INSN_C(insn) & h->nodemask8; - LuaNode* n = &h->node[slot]; - - // fast-path: value is in expected slot - if (LUAU_LIKELY(ttisstring(gkey(n)) && tsvalue(gkey(n)) == tsvalue(kv) && !ttisnil(gval(n)))) - { - setobj2s(L, ra, gval(n)); - VM_NEXT(); - } - else if (!h->metatable) - { - // fast-path: value is not in expected slot, but the table lookup doesn't involve metatable - const TValue* res = luaH_getstr(h, tsvalue(kv)); - - if (res != luaO_nilobject) - { - int cachedslot = gval2slot(h, res); - // save cachedslot to accelerate future lookups; patches currently executing instruction since pc-2 rolls back two pc++ - VM_PATCH_C(pc - 2, cachedslot); - } - - setobj2s(L, ra, res); - VM_NEXT(); - } - else - { - // slow-path, may invoke Lua calls via __index metamethod - L->cachedslot = slot; - VM_PROTECT(luaV_gettable(L, rb, kv, ra)); - // save cachedslot to accelerate future lookups; patches currently executing instruction since pc-2 rolls back two pc++ - VM_PATCH_C(pc - 2, L->cachedslot); - VM_NEXT(); - } - } - else - { - // fast-path: user data with C __index TM - const TValue* fn = 0; - if (ttisuserdata(rb) && (fn = fasttm(L, uvalue(rb)->metatable, TM_INDEX)) && ttisfunction(fn) && clvalue(fn)->isC) - { - // note: it's safe to push arguments past top for complicated reasons (see top of the file) - LUAU_ASSERT(L->top + 3 < L->stack + L->stacksize); - StkId top = L->top; - setobj2s(L, top + 0, fn); - setobj2s(L, top + 1, rb); - setobj2s(L, top + 2, kv); - L->top = top + 3; - - L->cachedslot = LUAU_INSN_C(insn); - VM_PROTECT(luaV_callTM(L, 2, LUAU_INSN_A(insn))); - // save cachedslot to accelerate future lookups; patches currently executing instruction since pc-2 rolls back two pc++ - VM_PATCH_C(pc - 2, L->cachedslot); - VM_NEXT(); - } - else if (ttisvector(rb)) - { - // fast-path: quick case-insensitive comparison with "X"/"Y"/"Z" - const char* name = getstr(tsvalue(kv)); - int ic = (name[0] | ' ') - 'x'; - -#if LUA_VECTOR_SIZE == 4 - // 'w' is before 'x' in ascii, so ic is -1 when indexing with 'w' - if (ic == -1) - ic = 3; -#endif - - if (unsigned(ic) < LUA_VECTOR_SIZE && name[1] == '\0') - { - const float* v = vvalue(rb); // silences ubsan when indexing v[] - setnvalue(ra, v[ic]); - VM_NEXT(); - } - - fn = fasttm(L, L->global->mt[LUA_TVECTOR], TM_INDEX); - - if (fn && ttisfunction(fn) && clvalue(fn)->isC) - { - // note: it's safe to push arguments past top for complicated reasons (see top of the file) - LUAU_ASSERT(L->top + 3 < L->stack + L->stacksize); - StkId top = L->top; - setobj2s(L, top + 0, fn); - setobj2s(L, top + 1, rb); - setobj2s(L, top + 2, kv); - L->top = top + 3; - - L->cachedslot = LUAU_INSN_C(insn); - VM_PROTECT(luaV_callTM(L, 2, LUAU_INSN_A(insn))); - // save cachedslot to accelerate future lookups; patches currently executing instruction since pc-2 rolls back two pc++ - VM_PATCH_C(pc - 2, L->cachedslot); - VM_NEXT(); - } - - // fall through to slow path - } - - // fall through to slow path - } - - // slow-path, may invoke Lua calls via __index metamethod - VM_PROTECT(luaV_gettable(L, rb, kv, ra)); - VM_NEXT(); - } - - VM_CASE(LOP_SETTABLEKS) - { - Instruction insn = *pc++; - StkId ra = VM_REG(LUAU_INSN_A(insn)); - StkId rb = VM_REG(LUAU_INSN_B(insn)); - uint32_t aux = *pc++; - TValue* kv = VM_KV(aux); - LUAU_ASSERT(ttisstring(kv)); - - // fast-path: built-in table - if (LUAU_LIKELY(ttistable(rb))) - { - Table* h = hvalue(rb); - - int slot = LUAU_INSN_C(insn) & h->nodemask8; - LuaNode* n = &h->node[slot]; - - // fast-path: value is in expected slot - if (LUAU_LIKELY(ttisstring(gkey(n)) && tsvalue(gkey(n)) == tsvalue(kv) && !ttisnil(gval(n)) && !h->readonly)) - { - setobj2t(L, gval(n), ra); - luaC_barriert(L, h, ra); - VM_NEXT(); - } - else if (fastnotm(h->metatable, TM_NEWINDEX) && !h->readonly) - { - VM_PROTECT_PC(); // set may fail - - TValue* res = luaH_setstr(L, h, tsvalue(kv)); - int cachedslot = gval2slot(h, res); - // save cachedslot to accelerate future lookups; patches currently executing instruction since pc-2 rolls back two pc++ - VM_PATCH_C(pc - 2, cachedslot); - setobj2t(L, res, ra); - luaC_barriert(L, h, ra); - VM_NEXT(); - } - else - { - // slow-path, may invoke Lua calls via __newindex metamethod - L->cachedslot = slot; - VM_PROTECT(luaV_settable(L, rb, kv, ra)); - // save cachedslot to accelerate future lookups; patches currently executing instruction since pc-2 rolls back two pc++ - VM_PATCH_C(pc - 2, L->cachedslot); - VM_NEXT(); - } - } - else - { - // fast-path: user data with C __newindex TM - const TValue* fn = 0; - if (ttisuserdata(rb) && (fn = fasttm(L, uvalue(rb)->metatable, TM_NEWINDEX)) && ttisfunction(fn) && clvalue(fn)->isC) - { - // note: it's safe to push arguments past top for complicated reasons (see top of the file) - LUAU_ASSERT(L->top + 4 < L->stack + L->stacksize); - StkId top = L->top; - setobj2s(L, top + 0, fn); - setobj2s(L, top + 1, rb); - setobj2s(L, top + 2, kv); - setobj2s(L, top + 3, ra); - L->top = top + 4; - - L->cachedslot = LUAU_INSN_C(insn); - VM_PROTECT(luaV_callTM(L, 3, -1)); - // save cachedslot to accelerate future lookups; patches currently executing instruction since pc-2 rolls back two pc++ - VM_PATCH_C(pc - 2, L->cachedslot); - VM_NEXT(); - } - else - { - // slow-path, may invoke Lua calls via __newindex metamethod - VM_PROTECT(luaV_settable(L, rb, kv, ra)); - VM_NEXT(); - } - } - } - - VM_CASE(LOP_GETTABLE) - { - Instruction insn = *pc++; - StkId ra = VM_REG(LUAU_INSN_A(insn)); - StkId rb = VM_REG(LUAU_INSN_B(insn)); - StkId rc = VM_REG(LUAU_INSN_C(insn)); - - // fast-path: array lookup - if (ttistable(rb) && ttisnumber(rc)) - { - Table* h = hvalue(rb); - - double indexd = nvalue(rc); - int index = int(indexd); - - // index has to be an exact integer and in-bounds for the array portion - if (LUAU_LIKELY(unsigned(index - 1) < unsigned(h->sizearray) && !h->metatable && double(index) == indexd)) - { - setobj2s(L, ra, &h->array[unsigned(index - 1)]); - VM_NEXT(); - } - - // fall through to slow path - } - - // slow-path: handles out of bounds array lookups, non-integer numeric keys, non-array table lookup, __index MT calls - VM_PROTECT(luaV_gettable(L, rb, rc, ra)); - VM_NEXT(); - } - - VM_CASE(LOP_SETTABLE) - { - Instruction insn = *pc++; - StkId ra = VM_REG(LUAU_INSN_A(insn)); - StkId rb = VM_REG(LUAU_INSN_B(insn)); - StkId rc = VM_REG(LUAU_INSN_C(insn)); - - // fast-path: array assign - if (ttistable(rb) && ttisnumber(rc)) - { - Table* h = hvalue(rb); - - double indexd = nvalue(rc); - int index = int(indexd); - - // index has to be an exact integer and in-bounds for the array portion - if (LUAU_LIKELY(unsigned(index - 1) < unsigned(h->sizearray) && !h->metatable && !h->readonly && double(index) == indexd)) - { - setobj2t(L, &h->array[unsigned(index - 1)], ra); - luaC_barriert(L, h, ra); - VM_NEXT(); - } - - // fall through to slow path - } - - // slow-path: handles out of bounds array assignments, non-integer numeric keys, non-array table access, __newindex MT calls - VM_PROTECT(luaV_settable(L, rb, rc, ra)); - VM_NEXT(); - } - - VM_CASE(LOP_GETTABLEN) - { - Instruction insn = *pc++; - StkId ra = VM_REG(LUAU_INSN_A(insn)); - StkId rb = VM_REG(LUAU_INSN_B(insn)); - int c = LUAU_INSN_C(insn); - - // fast-path: array lookup - if (ttistable(rb)) - { - Table* h = hvalue(rb); - - if (LUAU_LIKELY(unsigned(c) < unsigned(h->sizearray) && !h->metatable)) - { - setobj2s(L, ra, &h->array[c]); - VM_NEXT(); - } - - // fall through to slow path - } - - // slow-path: handles out of bounds array lookups - TValue n; - setnvalue(&n, c + 1); - VM_PROTECT(luaV_gettable(L, rb, &n, ra)); - VM_NEXT(); - } - - VM_CASE(LOP_SETTABLEN) - { - Instruction insn = *pc++; - StkId ra = VM_REG(LUAU_INSN_A(insn)); - StkId rb = VM_REG(LUAU_INSN_B(insn)); - int c = LUAU_INSN_C(insn); - - // fast-path: array assign - if (ttistable(rb)) - { - Table* h = hvalue(rb); - - if (LUAU_LIKELY(unsigned(c) < unsigned(h->sizearray) && !h->metatable && !h->readonly)) - { - setobj2t(L, &h->array[c], ra); - luaC_barriert(L, h, ra); - VM_NEXT(); - } - - // fall through to slow path - } - - // slow-path: handles out of bounds array lookups - TValue n; - setnvalue(&n, c + 1); - VM_PROTECT(luaV_settable(L, rb, &n, ra)); - VM_NEXT(); - } - - VM_CASE(LOP_NEWCLOSURE) - { - Instruction insn = *pc++; - StkId ra = VM_REG(LUAU_INSN_A(insn)); - - Proto* pv = cl->l.p->p[LUAU_INSN_D(insn)]; - LUAU_ASSERT(unsigned(LUAU_INSN_D(insn)) < unsigned(cl->l.p->sizep)); - - VM_PROTECT_PC(); // luaF_newLclosure may fail due to OOM - - // note: we save closure to stack early in case the code below wants to capture it by value - Closure* ncl = luaF_newLclosure(L, pv->nups, cl->env, pv); - setclvalue(L, ra, ncl); - - for (int ui = 0; ui < pv->nups; ++ui) - { - Instruction uinsn = *pc++; - LUAU_ASSERT(LUAU_INSN_OP(uinsn) == LOP_CAPTURE); - - switch (LUAU_INSN_A(uinsn)) - { - case LCT_VAL: - setobj(L, &ncl->l.uprefs[ui], VM_REG(LUAU_INSN_B(uinsn))); - break; - - case LCT_REF: - setupvalue(L, &ncl->l.uprefs[ui], luaF_findupval(L, VM_REG(LUAU_INSN_B(uinsn)))); - break; - - case LCT_UPVAL: - setobj(L, &ncl->l.uprefs[ui], VM_UV(LUAU_INSN_B(uinsn))); - break; - - default: - LUAU_ASSERT(!"Unknown upvalue capture type"); - LUAU_UNREACHABLE(); // improves switch() codegen by eliding opcode bounds checks - } - } - - VM_PROTECT(luaC_checkGC(L)); - VM_NEXT(); - } - - VM_CASE(LOP_NAMECALL) - { - Instruction insn = *pc++; - StkId ra = VM_REG(LUAU_INSN_A(insn)); - StkId rb = VM_REG(LUAU_INSN_B(insn)); - uint32_t aux = *pc++; - TValue* kv = VM_KV(aux); - LUAU_ASSERT(ttisstring(kv)); - - if (LUAU_LIKELY(ttistable(rb))) - { - Table* h = hvalue(rb); - // note: we can't use nodemask8 here because we need to query the main position of the table, and 8-bit nodemask8 only works - // for predictive lookups - LuaNode* n = &h->node[tsvalue(kv)->hash & (sizenode(h) - 1)]; - - const TValue* mt = 0; - const LuaNode* mtn = 0; - - // fast-path: key is in the table in expected slot - if (ttisstring(gkey(n)) && tsvalue(gkey(n)) == tsvalue(kv) && !ttisnil(gval(n))) - { - // note: order of copies allows rb to alias ra+1 or ra - setobj2s(L, ra + 1, rb); - setobj2s(L, ra, gval(n)); - } - // fast-path: key is absent from the base, table has an __index table, and it has the result in the expected slot - else if (gnext(n) == 0 && (mt = fasttm(L, hvalue(rb)->metatable, TM_INDEX)) && ttistable(mt) && - (mtn = &hvalue(mt)->node[LUAU_INSN_C(insn) & hvalue(mt)->nodemask8]) && ttisstring(gkey(mtn)) && - tsvalue(gkey(mtn)) == tsvalue(kv) && !ttisnil(gval(mtn))) - { - // note: order of copies allows rb to alias ra+1 or ra - setobj2s(L, ra + 1, rb); - setobj2s(L, ra, gval(mtn)); - } - else - { - // slow-path: handles full table lookup - setobj2s(L, ra + 1, rb); - L->cachedslot = LUAU_INSN_C(insn); - VM_PROTECT(luaV_gettable(L, rb, kv, ra)); - // save cachedslot to accelerate future lookups; patches currently executing instruction since pc-2 rolls back two pc++ - VM_PATCH_C(pc - 2, L->cachedslot); - // recompute ra since stack might have been reallocated - ra = VM_REG(LUAU_INSN_A(insn)); - if (ttisnil(ra)) - luaG_methoderror(L, ra + 1, tsvalue(kv)); - } - } - else - { - Table* mt = ttisuserdata(rb) ? uvalue(rb)->metatable : L->global->mt[ttype(rb)]; - const TValue* tmi = 0; - - // fast-path: metatable with __namecall - if (const TValue* fn = fasttm(L, mt, TM_NAMECALL)) - { - // note: order of copies allows rb to alias ra+1 or ra - setobj2s(L, ra + 1, rb); - setobj2s(L, ra, fn); - - L->namecall = tsvalue(kv); - } - else if ((tmi = fasttm(L, mt, TM_INDEX)) && ttistable(tmi)) - { - Table* h = hvalue(tmi); - int slot = LUAU_INSN_C(insn) & h->nodemask8; - LuaNode* n = &h->node[slot]; - - // fast-path: metatable with __index that has method in expected slot - if (LUAU_LIKELY(ttisstring(gkey(n)) && tsvalue(gkey(n)) == tsvalue(kv) && !ttisnil(gval(n)))) - { - // note: order of copies allows rb to alias ra+1 or ra - setobj2s(L, ra + 1, rb); - setobj2s(L, ra, gval(n)); - } - else - { - // slow-path: handles slot mismatch - setobj2s(L, ra + 1, rb); - L->cachedslot = slot; - VM_PROTECT(luaV_gettable(L, rb, kv, ra)); - // save cachedslot to accelerate future lookups; patches currently executing instruction since pc-2 rolls back two pc++ - VM_PATCH_C(pc - 2, L->cachedslot); - // recompute ra since stack might have been reallocated - ra = VM_REG(LUAU_INSN_A(insn)); - if (ttisnil(ra)) - luaG_methoderror(L, ra + 1, tsvalue(kv)); - } - } - else - { - // slow-path: handles non-table __index - setobj2s(L, ra + 1, rb); - VM_PROTECT(luaV_gettable(L, rb, kv, ra)); - // recompute ra since stack might have been reallocated - ra = VM_REG(LUAU_INSN_A(insn)); - if (ttisnil(ra)) - luaG_methoderror(L, ra + 1, tsvalue(kv)); - } - } - - // intentional fallthrough to CALL - LUAU_ASSERT(LUAU_INSN_OP(*pc) == LOP_CALL); - } - - VM_CASE(LOP_CALL) - { - VM_INTERRUPT(); - Instruction insn = *pc++; - StkId ra = VM_REG(LUAU_INSN_A(insn)); - - int nparams = LUAU_INSN_B(insn) - 1; - int nresults = LUAU_INSN_C(insn) - 1; - - StkId argtop = L->top; - argtop = (nparams == LUA_MULTRET) ? argtop : ra + 1 + nparams; - - // slow-path: not a function call - if (LUAU_UNLIKELY(!ttisfunction(ra))) - { - VM_PROTECT_PC(); // luaV_tryfuncTM may fail - - luaV_tryfuncTM(L, ra); - argtop++; // __call adds an extra self - } - - Closure* ccl = clvalue(ra); - L->ci->savedpc = pc; - - CallInfo* ci = incr_ci(L); - ci->func = ra; - ci->base = ra + 1; - ci->top = argtop + ccl->stacksize; // note: technically UB since we haven't reallocated the stack yet - ci->savedpc = NULL; - ci->flags = 0; - ci->nresults = nresults; - - L->base = ci->base; - L->top = argtop; - - // note: this reallocs stack, but we don't need to VM_PROTECT this - // this is because we're going to modify base/savedpc manually anyhow - // crucially, we can't use ra/argtop after this line - luaD_checkstack(L, ccl->stacksize); - - LUAU_ASSERT(ci->top <= L->stack_last); - - if (!ccl->isC) - { - Proto* p = ccl->l.p; - - // fill unused parameters with nil - StkId argi = L->top; - StkId argend = L->base + p->numparams; - while (argi < argend) - setnilvalue(argi++); // complete missing arguments - L->top = p->is_vararg ? argi : ci->top; - - // reentry - // codeentry may point to NATIVECALL instruction when proto is compiled to native code - // this will result in execution continuing in native code, and is equivalent to if (p->execdata) but has no additional overhead - // note that p->codeentry may point *outside* of p->code..p->code+p->sizecode, but that pointer never gets saved to savedpc. - pc = SingleStep ? p->code : p->codeentry; - cl = ccl; - base = L->base; - k = p->k; - VM_NEXT(); - } - else - { - lua_CFunction func = ccl->c.f; - int n = func(L); - - // yield - if (n < 0) - goto exit; - - // ci is our callinfo, cip is our parent - CallInfo* ci = L->ci; - CallInfo* cip = ci - 1; - - // copy return values into parent stack (but only up to nresults!), fill the rest with nil - // note: in MULTRET context nresults starts as -1 so i != 0 condition never activates intentionally - StkId res = ci->func; - StkId vali = L->top - n; - StkId valend = L->top; - - int i; - for (i = nresults; i != 0 && vali < valend; i--) - setobj2s(L, res++, vali++); - while (i-- > 0) - setnilvalue(res++); - - // pop the stack frame - L->ci = cip; - L->base = cip->base; - L->top = (nresults == LUA_MULTRET) ? res : cip->top; - - base = L->base; // stack may have been reallocated, so we need to refresh base ptr - VM_NEXT(); - } - } - - VM_CASE(LOP_RETURN) - { - VM_INTERRUPT(); - Instruction insn = *pc++; - StkId ra = &base[LUAU_INSN_A(insn)]; // note: this can point to L->top if b == LUA_MULTRET making VM_REG unsafe to use - int b = LUAU_INSN_B(insn) - 1; - - // ci is our callinfo, cip is our parent - CallInfo* ci = L->ci; - CallInfo* cip = ci - 1; - - StkId res = ci->func; // note: we assume CALL always puts func+args and expects results to start at func - - StkId vali = ra; - StkId valend = - (b == LUA_MULTRET) ? L->top : ra + b; // copy as much as possible for MULTRET calls, and only as much as needed otherwise - - int nresults = ci->nresults; - - // copy return values into parent stack (but only up to nresults!), fill the rest with nil - // note: in MULTRET context nresults starts as -1 so i != 0 condition never activates intentionally - int i; - for (i = nresults; i != 0 && vali < valend; i--) - setobj2s(L, res++, vali++); - while (i-- > 0) - setnilvalue(res++); - - // pop the stack frame - L->ci = cip; - L->base = cip->base; - L->top = (nresults == LUA_MULTRET) ? res : cip->top; - - // we're done! - if (LUAU_UNLIKELY(ci->flags & LUA_CALLINFO_RETURN)) - { - goto exit; - } - - LUAU_ASSERT(isLua(L->ci)); - - Closure* nextcl = clvalue(cip->func); - Proto* nextproto = nextcl->l.p; - -#if VM_HAS_NATIVE - if (LUAU_UNLIKELY((cip->flags & LUA_CALLINFO_NATIVE) && !SingleStep)) - { - if (L->global->ecb.enter(L, nextproto) == 1) - goto reentry; - else - goto exit; - } -#endif - - // reentry - pc = cip->savedpc; - cl = nextcl; - base = L->base; - k = nextproto->k; - VM_NEXT(); - } - - VM_CASE(LOP_JUMP) - { - Instruction insn = *pc++; - - pc += LUAU_INSN_D(insn); - LUAU_ASSERT(unsigned(pc - cl->l.p->code) < unsigned(cl->l.p->sizecode)); - VM_NEXT(); - } - - VM_CASE(LOP_JUMPIF) - { - Instruction insn = *pc++; - StkId ra = VM_REG(LUAU_INSN_A(insn)); - - pc += l_isfalse(ra) ? 0 : LUAU_INSN_D(insn); - LUAU_ASSERT(unsigned(pc - cl->l.p->code) < unsigned(cl->l.p->sizecode)); - VM_NEXT(); - } - - VM_CASE(LOP_JUMPIFNOT) - { - Instruction insn = *pc++; - StkId ra = VM_REG(LUAU_INSN_A(insn)); - - pc += l_isfalse(ra) ? LUAU_INSN_D(insn) : 0; - LUAU_ASSERT(unsigned(pc - cl->l.p->code) < unsigned(cl->l.p->sizecode)); - VM_NEXT(); - } - - VM_CASE(LOP_JUMPIFEQ) - { - Instruction insn = *pc++; - uint32_t aux = *pc; - StkId ra = VM_REG(LUAU_INSN_A(insn)); - StkId rb = VM_REG(aux); - - // Note that all jumps below jump by 1 in the "false" case to skip over aux - if (ttype(ra) == ttype(rb)) - { - switch (ttype(ra)) - { - case LUA_TNIL: - pc += LUAU_INSN_D(insn); - LUAU_ASSERT(unsigned(pc - cl->l.p->code) < unsigned(cl->l.p->sizecode)); - VM_NEXT(); - - case LUA_TBOOLEAN: - pc += bvalue(ra) == bvalue(rb) ? LUAU_INSN_D(insn) : 1; - LUAU_ASSERT(unsigned(pc - cl->l.p->code) < unsigned(cl->l.p->sizecode)); - VM_NEXT(); - - case LUA_TLIGHTUSERDATA: - pc += (pvalue(ra) == pvalue(rb) && (!FFlag::TaggedLuData || lightuserdatatag(ra) == lightuserdatatag(rb))) ? LUAU_INSN_D(insn) : 1; - LUAU_ASSERT(unsigned(pc - cl->l.p->code) < unsigned(cl->l.p->sizecode)); - VM_NEXT(); - - case LUA_TNUMBER: - pc += nvalue(ra) == nvalue(rb) ? LUAU_INSN_D(insn) : 1; - LUAU_ASSERT(unsigned(pc - cl->l.p->code) < unsigned(cl->l.p->sizecode)); - VM_NEXT(); - - case LUA_TVECTOR: - pc += luai_veceq(vvalue(ra), vvalue(rb)) ? LUAU_INSN_D(insn) : 1; - LUAU_ASSERT(unsigned(pc - cl->l.p->code) < unsigned(cl->l.p->sizecode)); - VM_NEXT(); - - case LUA_TSTRING: - case LUA_TFUNCTION: - case LUA_TTHREAD: - case LUA_TBUFFER: - pc += gcvalue(ra) == gcvalue(rb) ? LUAU_INSN_D(insn) : 1; - LUAU_ASSERT(unsigned(pc - cl->l.p->code) < unsigned(cl->l.p->sizecode)); - VM_NEXT(); - - case LUA_TTABLE: - // fast-path: same metatable, no EQ metamethod - if (hvalue(ra)->metatable == hvalue(rb)->metatable) - { - const TValue* fn = fasttm(L, hvalue(ra)->metatable, TM_EQ); - - if (!fn) - { - pc += hvalue(ra) == hvalue(rb) ? LUAU_INSN_D(insn) : 1; - LUAU_ASSERT(unsigned(pc - cl->l.p->code) < unsigned(cl->l.p->sizecode)); - VM_NEXT(); - } - } - // slow path after switch() - break; - - case LUA_TUSERDATA: - // fast-path: same metatable, no EQ metamethod or C metamethod - if (uvalue(ra)->metatable == uvalue(rb)->metatable) - { - const TValue* fn = fasttm(L, uvalue(ra)->metatable, TM_EQ); - - if (!fn) - { - pc += uvalue(ra) == uvalue(rb) ? LUAU_INSN_D(insn) : 1; - LUAU_ASSERT(unsigned(pc - cl->l.p->code) < unsigned(cl->l.p->sizecode)); - VM_NEXT(); - } - else if (ttisfunction(fn) && clvalue(fn)->isC) - { - // note: it's safe to push arguments past top for complicated reasons (see top of the file) - LUAU_ASSERT(L->top + 3 < L->stack + L->stacksize); - StkId top = L->top; - setobj2s(L, top + 0, fn); - setobj2s(L, top + 1, ra); - setobj2s(L, top + 2, rb); - int res = int(top - base); - L->top = top + 3; - - VM_PROTECT(luaV_callTM(L, 2, res)); - pc += !l_isfalse(&base[res]) ? LUAU_INSN_D(insn) : 1; - LUAU_ASSERT(unsigned(pc - cl->l.p->code) < unsigned(cl->l.p->sizecode)); - VM_NEXT(); - } - } - // slow path after switch() - break; - - default: - LUAU_ASSERT(!"Unknown value type"); - LUAU_UNREACHABLE(); // improves switch() codegen by eliding opcode bounds checks - } - - // slow-path: tables with metatables and userdata values - // note that we don't have a fast path for userdata values without metatables, since that's very rare - int res; - VM_PROTECT(res = luaV_equalval(L, ra, rb)); - - pc += (res == 1) ? LUAU_INSN_D(insn) : 1; - LUAU_ASSERT(unsigned(pc - cl->l.p->code) < unsigned(cl->l.p->sizecode)); - VM_NEXT(); - } - else - { - pc += 1; - LUAU_ASSERT(unsigned(pc - cl->l.p->code) < unsigned(cl->l.p->sizecode)); - VM_NEXT(); - } - } - - VM_CASE(LOP_JUMPIFNOTEQ) - { - Instruction insn = *pc++; - uint32_t aux = *pc; - StkId ra = VM_REG(LUAU_INSN_A(insn)); - StkId rb = VM_REG(aux); - - // Note that all jumps below jump by 1 in the "true" case to skip over aux - if (ttype(ra) == ttype(rb)) - { - switch (ttype(ra)) - { - case LUA_TNIL: - pc += 1; - LUAU_ASSERT(unsigned(pc - cl->l.p->code) < unsigned(cl->l.p->sizecode)); - VM_NEXT(); - - case LUA_TBOOLEAN: - pc += bvalue(ra) != bvalue(rb) ? LUAU_INSN_D(insn) : 1; - LUAU_ASSERT(unsigned(pc - cl->l.p->code) < unsigned(cl->l.p->sizecode)); - VM_NEXT(); - - case LUA_TLIGHTUSERDATA: - pc += (pvalue(ra) != pvalue(rb) || (FFlag::TaggedLuData && lightuserdatatag(ra) != lightuserdatatag(rb))) ? LUAU_INSN_D(insn) : 1; - LUAU_ASSERT(unsigned(pc - cl->l.p->code) < unsigned(cl->l.p->sizecode)); - VM_NEXT(); - - case LUA_TNUMBER: - pc += nvalue(ra) != nvalue(rb) ? LUAU_INSN_D(insn) : 1; - LUAU_ASSERT(unsigned(pc - cl->l.p->code) < unsigned(cl->l.p->sizecode)); - VM_NEXT(); - - case LUA_TVECTOR: - pc += !luai_veceq(vvalue(ra), vvalue(rb)) ? LUAU_INSN_D(insn) : 1; - LUAU_ASSERT(unsigned(pc - cl->l.p->code) < unsigned(cl->l.p->sizecode)); - VM_NEXT(); - - case LUA_TSTRING: - case LUA_TFUNCTION: - case LUA_TTHREAD: - case LUA_TBUFFER: - pc += gcvalue(ra) != gcvalue(rb) ? LUAU_INSN_D(insn) : 1; - LUAU_ASSERT(unsigned(pc - cl->l.p->code) < unsigned(cl->l.p->sizecode)); - VM_NEXT(); - - case LUA_TTABLE: - // fast-path: same metatable, no EQ metamethod - if (hvalue(ra)->metatable == hvalue(rb)->metatable) - { - const TValue* fn = fasttm(L, hvalue(ra)->metatable, TM_EQ); - - if (!fn) - { - pc += hvalue(ra) != hvalue(rb) ? LUAU_INSN_D(insn) : 1; - LUAU_ASSERT(unsigned(pc - cl->l.p->code) < unsigned(cl->l.p->sizecode)); - VM_NEXT(); - } - } - // slow path after switch() - break; - - case LUA_TUSERDATA: - // fast-path: same metatable, no EQ metamethod or C metamethod - if (uvalue(ra)->metatable == uvalue(rb)->metatable) - { - const TValue* fn = fasttm(L, uvalue(ra)->metatable, TM_EQ); - - if (!fn) - { - pc += uvalue(ra) != uvalue(rb) ? LUAU_INSN_D(insn) : 1; - LUAU_ASSERT(unsigned(pc - cl->l.p->code) < unsigned(cl->l.p->sizecode)); - VM_NEXT(); - } - else if (ttisfunction(fn) && clvalue(fn)->isC) - { - // note: it's safe to push arguments past top for complicated reasons (see top of the file) - LUAU_ASSERT(L->top + 3 < L->stack + L->stacksize); - StkId top = L->top; - setobj2s(L, top + 0, fn); - setobj2s(L, top + 1, ra); - setobj2s(L, top + 2, rb); - int res = int(top - base); - L->top = top + 3; - - VM_PROTECT(luaV_callTM(L, 2, res)); - pc += l_isfalse(&base[res]) ? LUAU_INSN_D(insn) : 1; - LUAU_ASSERT(unsigned(pc - cl->l.p->code) < unsigned(cl->l.p->sizecode)); - VM_NEXT(); - } - } - // slow path after switch() - break; - - default: - LUAU_ASSERT(!"Unknown value type"); - LUAU_UNREACHABLE(); // improves switch() codegen by eliding opcode bounds checks - } - - // slow-path: tables with metatables and userdata values - // note that we don't have a fast path for userdata values without metatables, since that's very rare - int res; - VM_PROTECT(res = luaV_equalval(L, ra, rb)); - - pc += (res == 0) ? LUAU_INSN_D(insn) : 1; - LUAU_ASSERT(unsigned(pc - cl->l.p->code) < unsigned(cl->l.p->sizecode)); - VM_NEXT(); - } - else - { - pc += LUAU_INSN_D(insn); - LUAU_ASSERT(unsigned(pc - cl->l.p->code) < unsigned(cl->l.p->sizecode)); - VM_NEXT(); - } - } - - VM_CASE(LOP_JUMPIFLE) - { - Instruction insn = *pc++; - uint32_t aux = *pc; - StkId ra = VM_REG(LUAU_INSN_A(insn)); - StkId rb = VM_REG(aux); - - // fast-path: number - // Note that all jumps below jump by 1 in the "false" case to skip over aux - if (LUAU_LIKELY(ttisnumber(ra) && ttisnumber(rb))) - { - pc += nvalue(ra) <= nvalue(rb) ? LUAU_INSN_D(insn) : 1; - LUAU_ASSERT(unsigned(pc - cl->l.p->code) < unsigned(cl->l.p->sizecode)); - VM_NEXT(); - } - // fast-path: string - else if (ttisstring(ra) && ttisstring(rb)) - { - pc += luaV_strcmp(tsvalue(ra), tsvalue(rb)) <= 0 ? LUAU_INSN_D(insn) : 1; - LUAU_ASSERT(unsigned(pc - cl->l.p->code) < unsigned(cl->l.p->sizecode)); - VM_NEXT(); - } - else - { - int res; - VM_PROTECT(res = luaV_lessequal(L, ra, rb)); - - pc += (res == 1) ? LUAU_INSN_D(insn) : 1; - LUAU_ASSERT(unsigned(pc - cl->l.p->code) < unsigned(cl->l.p->sizecode)); - VM_NEXT(); - } - } - - VM_CASE(LOP_JUMPIFNOTLE) - { - Instruction insn = *pc++; - uint32_t aux = *pc; - StkId ra = VM_REG(LUAU_INSN_A(insn)); - StkId rb = VM_REG(aux); - - // fast-path: number - // Note that all jumps below jump by 1 in the "true" case to skip over aux - if (LUAU_LIKELY(ttisnumber(ra) && ttisnumber(rb))) - { - pc += !(nvalue(ra) <= nvalue(rb)) ? LUAU_INSN_D(insn) : 1; - LUAU_ASSERT(unsigned(pc - cl->l.p->code) < unsigned(cl->l.p->sizecode)); - VM_NEXT(); - } - // fast-path: string - else if (ttisstring(ra) && ttisstring(rb)) - { - pc += !(luaV_strcmp(tsvalue(ra), tsvalue(rb)) <= 0) ? LUAU_INSN_D(insn) : 1; - LUAU_ASSERT(unsigned(pc - cl->l.p->code) < unsigned(cl->l.p->sizecode)); - VM_NEXT(); - } - else - { - int res; - VM_PROTECT(res = luaV_lessequal(L, ra, rb)); - - pc += (res == 0) ? LUAU_INSN_D(insn) : 1; - LUAU_ASSERT(unsigned(pc - cl->l.p->code) < unsigned(cl->l.p->sizecode)); - VM_NEXT(); - } - } - - VM_CASE(LOP_JUMPIFLT) - { - Instruction insn = *pc++; - uint32_t aux = *pc; - StkId ra = VM_REG(LUAU_INSN_A(insn)); - StkId rb = VM_REG(aux); - - // fast-path: number - // Note that all jumps below jump by 1 in the "false" case to skip over aux - if (LUAU_LIKELY(ttisnumber(ra) && ttisnumber(rb))) - { - pc += nvalue(ra) < nvalue(rb) ? LUAU_INSN_D(insn) : 1; - LUAU_ASSERT(unsigned(pc - cl->l.p->code) < unsigned(cl->l.p->sizecode)); - VM_NEXT(); - } - // fast-path: string - else if (ttisstring(ra) && ttisstring(rb)) - { - pc += luaV_strcmp(tsvalue(ra), tsvalue(rb)) < 0 ? LUAU_INSN_D(insn) : 1; - LUAU_ASSERT(unsigned(pc - cl->l.p->code) < unsigned(cl->l.p->sizecode)); - VM_NEXT(); - } - else - { - int res; - VM_PROTECT(res = luaV_lessthan(L, ra, rb)); - - pc += (res == 1) ? LUAU_INSN_D(insn) : 1; - LUAU_ASSERT(unsigned(pc - cl->l.p->code) < unsigned(cl->l.p->sizecode)); - VM_NEXT(); - } - } - - VM_CASE(LOP_JUMPIFNOTLT) - { - Instruction insn = *pc++; - uint32_t aux = *pc; - StkId ra = VM_REG(LUAU_INSN_A(insn)); - StkId rb = VM_REG(aux); - - // fast-path: number - // Note that all jumps below jump by 1 in the "true" case to skip over aux - if (LUAU_LIKELY(ttisnumber(ra) && ttisnumber(rb))) - { - pc += !(nvalue(ra) < nvalue(rb)) ? LUAU_INSN_D(insn) : 1; - LUAU_ASSERT(unsigned(pc - cl->l.p->code) < unsigned(cl->l.p->sizecode)); - VM_NEXT(); - } - // fast-path: string - else if (ttisstring(ra) && ttisstring(rb)) - { - pc += !(luaV_strcmp(tsvalue(ra), tsvalue(rb)) < 0) ? LUAU_INSN_D(insn) : 1; - LUAU_ASSERT(unsigned(pc - cl->l.p->code) < unsigned(cl->l.p->sizecode)); - VM_NEXT(); - } - else - { - int res; - VM_PROTECT(res = luaV_lessthan(L, ra, rb)); - - pc += (res == 0) ? LUAU_INSN_D(insn) : 1; - LUAU_ASSERT(unsigned(pc - cl->l.p->code) < unsigned(cl->l.p->sizecode)); - VM_NEXT(); - } - } - - VM_CASE(LOP_ADD) - { - Instruction insn = *pc++; - StkId ra = VM_REG(LUAU_INSN_A(insn)); - StkId rb = VM_REG(LUAU_INSN_B(insn)); - StkId rc = VM_REG(LUAU_INSN_C(insn)); - - // fast-path - if (LUAU_LIKELY(ttisnumber(rb) && ttisnumber(rc))) - { - setnvalue(ra, nvalue(rb) + nvalue(rc)); - VM_NEXT(); - } - else if (ttisvector(rb) && ttisvector(rc)) - { - const float* vb = vvalue(rb); - const float* vc = vvalue(rc); - setvvalue(ra, vb[0] + vc[0], vb[1] + vc[1], vb[2] + vc[2], vb[3] + vc[3]); - VM_NEXT(); - } - else - { - // fast-path for userdata with C functions - const TValue* fn = 0; - if (ttisuserdata(rb) && (fn = luaT_gettmbyobj(L, rb, TM_ADD)) && ttisfunction(fn) && clvalue(fn)->isC) - { - // note: it's safe to push arguments past top for complicated reasons (see top of the file) - LUAU_ASSERT(L->top + 3 < L->stack + L->stacksize); - StkId top = L->top; - setobj2s(L, top + 0, fn); - setobj2s(L, top + 1, rb); - setobj2s(L, top + 2, rc); - L->top = top + 3; - - VM_PROTECT(luaV_callTM(L, 2, LUAU_INSN_A(insn))); - VM_NEXT(); - } - else - { - // slow-path, may invoke C/Lua via metamethods - VM_PROTECT(luaV_doarith(L, ra, rb, rc, TM_ADD)); - VM_NEXT(); - } - } - } - - VM_CASE(LOP_SUB) - { - Instruction insn = *pc++; - StkId ra = VM_REG(LUAU_INSN_A(insn)); - StkId rb = VM_REG(LUAU_INSN_B(insn)); - StkId rc = VM_REG(LUAU_INSN_C(insn)); - - // fast-path - if (LUAU_LIKELY(ttisnumber(rb) && ttisnumber(rc))) - { - setnvalue(ra, nvalue(rb) - nvalue(rc)); - VM_NEXT(); - } - else if (ttisvector(rb) && ttisvector(rc)) - { - const float* vb = vvalue(rb); - const float* vc = vvalue(rc); - setvvalue(ra, vb[0] - vc[0], vb[1] - vc[1], vb[2] - vc[2], vb[3] - vc[3]); - VM_NEXT(); - } - else - { - // fast-path for userdata with C functions - const TValue* fn = 0; - if (ttisuserdata(rb) && (fn = luaT_gettmbyobj(L, rb, TM_SUB)) && ttisfunction(fn) && clvalue(fn)->isC) - { - // note: it's safe to push arguments past top for complicated reasons (see top of the file) - LUAU_ASSERT(L->top + 3 < L->stack + L->stacksize); - StkId top = L->top; - setobj2s(L, top + 0, fn); - setobj2s(L, top + 1, rb); - setobj2s(L, top + 2, rc); - L->top = top + 3; - - VM_PROTECT(luaV_callTM(L, 2, LUAU_INSN_A(insn))); - VM_NEXT(); - } - else - { - // slow-path, may invoke C/Lua via metamethods - VM_PROTECT(luaV_doarith(L, ra, rb, rc, TM_SUB)); - VM_NEXT(); - } - } - } - - VM_CASE(LOP_MUL) - { - Instruction insn = *pc++; - StkId ra = VM_REG(LUAU_INSN_A(insn)); - StkId rb = VM_REG(LUAU_INSN_B(insn)); - StkId rc = VM_REG(LUAU_INSN_C(insn)); - - // fast-path - if (LUAU_LIKELY(ttisnumber(rb) && ttisnumber(rc))) - { - setnvalue(ra, nvalue(rb) * nvalue(rc)); - VM_NEXT(); - } - else if (ttisvector(rb) && ttisnumber(rc)) - { - const float* vb = vvalue(rb); - float vc = cast_to(float, nvalue(rc)); - setvvalue(ra, vb[0] * vc, vb[1] * vc, vb[2] * vc, vb[3] * vc); - VM_NEXT(); - } - else if (ttisvector(rb) && ttisvector(rc)) - { - const float* vb = vvalue(rb); - const float* vc = vvalue(rc); - setvvalue(ra, vb[0] * vc[0], vb[1] * vc[1], vb[2] * vc[2], vb[3] * vc[3]); - VM_NEXT(); - } - else if (ttisnumber(rb) && ttisvector(rc)) - { - float vb = cast_to(float, nvalue(rb)); - const float* vc = vvalue(rc); - setvvalue(ra, vb * vc[0], vb * vc[1], vb * vc[2], vb * vc[3]); - VM_NEXT(); - } - else - { - // fast-path for userdata with C functions - StkId rbc = ttisnumber(rb) ? rc : rb; - const TValue* fn = 0; - if (ttisuserdata(rbc) && (fn = luaT_gettmbyobj(L, rbc, TM_MUL)) && ttisfunction(fn) && clvalue(fn)->isC) - { - // note: it's safe to push arguments past top for complicated reasons (see top of the file) - LUAU_ASSERT(L->top + 3 < L->stack + L->stacksize); - StkId top = L->top; - setobj2s(L, top + 0, fn); - setobj2s(L, top + 1, rb); - setobj2s(L, top + 2, rc); - L->top = top + 3; - - VM_PROTECT(luaV_callTM(L, 2, LUAU_INSN_A(insn))); - VM_NEXT(); - } - else - { - // slow-path, may invoke C/Lua via metamethods - VM_PROTECT(luaV_doarith(L, ra, rb, rc, TM_MUL)); - VM_NEXT(); - } - } - } - - VM_CASE(LOP_DIV) - { - Instruction insn = *pc++; - StkId ra = VM_REG(LUAU_INSN_A(insn)); - StkId rb = VM_REG(LUAU_INSN_B(insn)); - StkId rc = VM_REG(LUAU_INSN_C(insn)); - - // fast-path - if (LUAU_LIKELY(ttisnumber(rb) && ttisnumber(rc))) - { - setnvalue(ra, nvalue(rb) / nvalue(rc)); - VM_NEXT(); - } - else if (ttisvector(rb) && ttisnumber(rc)) - { - const float* vb = vvalue(rb); - float vc = cast_to(float, nvalue(rc)); - setvvalue(ra, vb[0] / vc, vb[1] / vc, vb[2] / vc, vb[3] / vc); - VM_NEXT(); - } - else if (ttisvector(rb) && ttisvector(rc)) - { - const float* vb = vvalue(rb); - const float* vc = vvalue(rc); - setvvalue(ra, vb[0] / vc[0], vb[1] / vc[1], vb[2] / vc[2], vb[3] / vc[3]); - VM_NEXT(); - } - else if (ttisnumber(rb) && ttisvector(rc)) - { - float vb = cast_to(float, nvalue(rb)); - const float* vc = vvalue(rc); - setvvalue(ra, vb / vc[0], vb / vc[1], vb / vc[2], vb / vc[3]); - VM_NEXT(); - } - else - { - // fast-path for userdata with C functions - StkId rbc = ttisnumber(rb) ? rc : rb; - const TValue* fn = 0; - if (ttisuserdata(rbc) && (fn = luaT_gettmbyobj(L, rbc, TM_DIV)) && ttisfunction(fn) && clvalue(fn)->isC) - { - // note: it's safe to push arguments past top for complicated reasons (see top of the file) - LUAU_ASSERT(L->top + 3 < L->stack + L->stacksize); - StkId top = L->top; - setobj2s(L, top + 0, fn); - setobj2s(L, top + 1, rb); - setobj2s(L, top + 2, rc); - L->top = top + 3; - - VM_PROTECT(luaV_callTM(L, 2, LUAU_INSN_A(insn))); - VM_NEXT(); - } - else - { - // slow-path, may invoke C/Lua via metamethods - VM_PROTECT(luaV_doarith(L, ra, rb, rc, TM_DIV)); - VM_NEXT(); - } - } - } - - VM_CASE(LOP_IDIV) - { - Instruction insn = *pc++; - StkId ra = VM_REG(LUAU_INSN_A(insn)); - StkId rb = VM_REG(LUAU_INSN_B(insn)); - StkId rc = VM_REG(LUAU_INSN_C(insn)); - - // fast-path - if (LUAU_LIKELY(ttisnumber(rb) && ttisnumber(rc))) - { - setnvalue(ra, luai_numidiv(nvalue(rb), nvalue(rc))); - VM_NEXT(); - } - else if (ttisvector(rb) && ttisnumber(rc)) - { - const float* vb = vvalue(rb); - float vc = cast_to(float, nvalue(rc)); - setvvalue(ra, float(luai_numidiv(vb[0], vc)), float(luai_numidiv(vb[1], vc)), float(luai_numidiv(vb[2], vc)), - float(luai_numidiv(vb[3], vc))); - VM_NEXT(); - } - else - { - // fast-path for userdata with C functions - StkId rbc = ttisnumber(rb) ? rc : rb; - const TValue* fn = 0; - if (ttisuserdata(rbc) && (fn = luaT_gettmbyobj(L, rbc, TM_IDIV)) && ttisfunction(fn) && clvalue(fn)->isC) - { - // note: it's safe to push arguments past top for complicated reasons (see top of the file) - LUAU_ASSERT(L->top + 3 < L->stack + L->stacksize); - StkId top = L->top; - setobj2s(L, top + 0, fn); - setobj2s(L, top + 1, rb); - setobj2s(L, top + 2, rc); - L->top = top + 3; - - VM_PROTECT(luaV_callTM(L, 2, LUAU_INSN_A(insn))); - VM_NEXT(); - } - else - { - // slow-path, may invoke C/Lua via metamethods - VM_PROTECT(luaV_doarith(L, ra, rb, rc, TM_IDIV)); - VM_NEXT(); - } - } - } - - VM_CASE(LOP_MOD) - { - Instruction insn = *pc++; - StkId ra = VM_REG(LUAU_INSN_A(insn)); - StkId rb = VM_REG(LUAU_INSN_B(insn)); - StkId rc = VM_REG(LUAU_INSN_C(insn)); - - // fast-path - if (ttisnumber(rb) && ttisnumber(rc)) - { - double nb = nvalue(rb); - double nc = nvalue(rc); - setnvalue(ra, luai_nummod(nb, nc)); - VM_NEXT(); - } - else - { - // slow-path, may invoke C/Lua via metamethods - VM_PROTECT(luaV_doarith(L, ra, rb, rc, TM_MOD)); - VM_NEXT(); - } - } - - VM_CASE(LOP_POW) - { - Instruction insn = *pc++; - StkId ra = VM_REG(LUAU_INSN_A(insn)); - StkId rb = VM_REG(LUAU_INSN_B(insn)); - StkId rc = VM_REG(LUAU_INSN_C(insn)); - - // fast-path - if (ttisnumber(rb) && ttisnumber(rc)) - { - setnvalue(ra, pow(nvalue(rb), nvalue(rc))); - VM_NEXT(); - } - else - { - // slow-path, may invoke C/Lua via metamethods - VM_PROTECT(luaV_doarith(L, ra, rb, rc, TM_POW)); - VM_NEXT(); - } - } - - VM_CASE(LOP_ADDK) - { - Instruction insn = *pc++; - StkId ra = VM_REG(LUAU_INSN_A(insn)); - StkId rb = VM_REG(LUAU_INSN_B(insn)); - TValue* kv = VM_KV(LUAU_INSN_C(insn)); - - // fast-path - if (ttisnumber(rb)) - { - setnvalue(ra, nvalue(rb) + nvalue(kv)); - VM_NEXT(); - } - else - { - // slow-path, may invoke C/Lua via metamethods - VM_PROTECT(luaV_doarith(L, ra, rb, kv, TM_ADD)); - VM_NEXT(); - } - } - - VM_CASE(LOP_SUBK) - { - Instruction insn = *pc++; - StkId ra = VM_REG(LUAU_INSN_A(insn)); - StkId rb = VM_REG(LUAU_INSN_B(insn)); - TValue* kv = VM_KV(LUAU_INSN_C(insn)); - - // fast-path - if (ttisnumber(rb)) - { - setnvalue(ra, nvalue(rb) - nvalue(kv)); - VM_NEXT(); - } - else - { - // slow-path, may invoke C/Lua via metamethods - VM_PROTECT(luaV_doarith(L, ra, rb, kv, TM_SUB)); - VM_NEXT(); - } - } - - VM_CASE(LOP_MULK) - { - Instruction insn = *pc++; - StkId ra = VM_REG(LUAU_INSN_A(insn)); - StkId rb = VM_REG(LUAU_INSN_B(insn)); - TValue* kv = VM_KV(LUAU_INSN_C(insn)); - - // fast-path - if (LUAU_LIKELY(ttisnumber(rb))) - { - setnvalue(ra, nvalue(rb) * nvalue(kv)); - VM_NEXT(); - } - else if (ttisvector(rb)) - { - const float* vb = vvalue(rb); - float vc = cast_to(float, nvalue(kv)); - setvvalue(ra, vb[0] * vc, vb[1] * vc, vb[2] * vc, vb[3] * vc); - VM_NEXT(); - } - else - { - // fast-path for userdata with C functions - const TValue* fn = 0; - if (ttisuserdata(rb) && (fn = luaT_gettmbyobj(L, rb, TM_MUL)) && ttisfunction(fn) && clvalue(fn)->isC) - { - // note: it's safe to push arguments past top for complicated reasons (see top of the file) - LUAU_ASSERT(L->top + 3 < L->stack + L->stacksize); - StkId top = L->top; - setobj2s(L, top + 0, fn); - setobj2s(L, top + 1, rb); - setobj2s(L, top + 2, kv); - L->top = top + 3; - - VM_PROTECT(luaV_callTM(L, 2, LUAU_INSN_A(insn))); - VM_NEXT(); - } - else - { - // slow-path, may invoke C/Lua via metamethods - VM_PROTECT(luaV_doarith(L, ra, rb, kv, TM_MUL)); - VM_NEXT(); - } - } - } - - VM_CASE(LOP_DIVK) - { - Instruction insn = *pc++; - StkId ra = VM_REG(LUAU_INSN_A(insn)); - StkId rb = VM_REG(LUAU_INSN_B(insn)); - TValue* kv = VM_KV(LUAU_INSN_C(insn)); - - // fast-path - if (LUAU_LIKELY(ttisnumber(rb))) - { - setnvalue(ra, nvalue(rb) / nvalue(kv)); - VM_NEXT(); - } - else if (ttisvector(rb)) - { - const float* vb = vvalue(rb); - float nc = cast_to(float, nvalue(kv)); - setvvalue(ra, vb[0] / nc, vb[1] / nc, vb[2] / nc, vb[3] / nc); - VM_NEXT(); - } - else - { - // fast-path for userdata with C functions - const TValue* fn = 0; - if (ttisuserdata(rb) && (fn = luaT_gettmbyobj(L, rb, TM_DIV)) && ttisfunction(fn) && clvalue(fn)->isC) - { - // note: it's safe to push arguments past top for complicated reasons (see top of the file) - LUAU_ASSERT(L->top + 3 < L->stack + L->stacksize); - StkId top = L->top; - setobj2s(L, top + 0, fn); - setobj2s(L, top + 1, rb); - setobj2s(L, top + 2, kv); - L->top = top + 3; - - VM_PROTECT(luaV_callTM(L, 2, LUAU_INSN_A(insn))); - VM_NEXT(); - } - else - { - // slow-path, may invoke C/Lua via metamethods - VM_PROTECT(luaV_doarith(L, ra, rb, kv, TM_DIV)); - VM_NEXT(); - } - } - } - - VM_CASE(LOP_IDIVK) - { - Instruction insn = *pc++; - StkId ra = VM_REG(LUAU_INSN_A(insn)); - StkId rb = VM_REG(LUAU_INSN_B(insn)); - TValue* kv = VM_KV(LUAU_INSN_C(insn)); - - // fast-path - if (LUAU_LIKELY(ttisnumber(rb))) - { - setnvalue(ra, luai_numidiv(nvalue(rb), nvalue(kv))); - VM_NEXT(); - } - else if (ttisvector(rb)) - { - const float* vb = vvalue(rb); - float vc = cast_to(float, nvalue(kv)); - setvvalue(ra, float(luai_numidiv(vb[0], vc)), float(luai_numidiv(vb[1], vc)), float(luai_numidiv(vb[2], vc)), - float(luai_numidiv(vb[3], vc))); - VM_NEXT(); - } - else - { - // fast-path for userdata with C functions - const TValue* fn = 0; - if (ttisuserdata(rb) && (fn = luaT_gettmbyobj(L, rb, TM_IDIV)) && ttisfunction(fn) && clvalue(fn)->isC) - { - // note: it's safe to push arguments past top for complicated reasons (see top of the file) - LUAU_ASSERT(L->top + 3 < L->stack + L->stacksize); - StkId top = L->top; - setobj2s(L, top + 0, fn); - setobj2s(L, top + 1, rb); - setobj2s(L, top + 2, kv); - L->top = top + 3; - - VM_PROTECT(luaV_callTM(L, 2, LUAU_INSN_A(insn))); - VM_NEXT(); - } - else - { - // slow-path, may invoke C/Lua via metamethods - VM_PROTECT(luaV_doarith(L, ra, rb, kv, TM_IDIV)); - VM_NEXT(); - } - } - } - - VM_CASE(LOP_MODK) - { - Instruction insn = *pc++; - StkId ra = VM_REG(LUAU_INSN_A(insn)); - StkId rb = VM_REG(LUAU_INSN_B(insn)); - TValue* kv = VM_KV(LUAU_INSN_C(insn)); - - // fast-path - if (ttisnumber(rb)) - { - double nb = nvalue(rb); - double nk = nvalue(kv); - setnvalue(ra, luai_nummod(nb, nk)); - VM_NEXT(); - } - else - { - // slow-path, may invoke C/Lua via metamethods - VM_PROTECT(luaV_doarith(L, ra, rb, kv, TM_MOD)); - VM_NEXT(); - } - } - - VM_CASE(LOP_POWK) - { - Instruction insn = *pc++; - StkId ra = VM_REG(LUAU_INSN_A(insn)); - StkId rb = VM_REG(LUAU_INSN_B(insn)); - TValue* kv = VM_KV(LUAU_INSN_C(insn)); - - // fast-path - if (ttisnumber(rb)) - { - double nb = nvalue(rb); - double nk = nvalue(kv); - - // pow is very slow so we specialize this for ^2, ^0.5 and ^3 - double r = (nk == 2.0) ? nb * nb : (nk == 0.5) ? sqrt(nb) : (nk == 3.0) ? nb * nb * nb : pow(nb, nk); - - setnvalue(ra, r); - VM_NEXT(); - } - else - { - // slow-path, may invoke C/Lua via metamethods - VM_PROTECT(luaV_doarith(L, ra, rb, kv, TM_POW)); - VM_NEXT(); - } - } - - VM_CASE(LOP_AND) - { - Instruction insn = *pc++; - StkId ra = VM_REG(LUAU_INSN_A(insn)); - StkId rb = VM_REG(LUAU_INSN_B(insn)); - StkId rc = VM_REG(LUAU_INSN_C(insn)); - - setobj2s(L, ra, l_isfalse(rb) ? rb : rc); - VM_NEXT(); - } - - VM_CASE(LOP_OR) - { - Instruction insn = *pc++; - StkId ra = VM_REG(LUAU_INSN_A(insn)); - StkId rb = VM_REG(LUAU_INSN_B(insn)); - StkId rc = VM_REG(LUAU_INSN_C(insn)); - - setobj2s(L, ra, l_isfalse(rb) ? rc : rb); - VM_NEXT(); - } - - VM_CASE(LOP_ANDK) - { - Instruction insn = *pc++; - StkId ra = VM_REG(LUAU_INSN_A(insn)); - StkId rb = VM_REG(LUAU_INSN_B(insn)); - TValue* kv = VM_KV(LUAU_INSN_C(insn)); - - setobj2s(L, ra, l_isfalse(rb) ? rb : kv); - VM_NEXT(); - } - - VM_CASE(LOP_ORK) - { - Instruction insn = *pc++; - StkId ra = VM_REG(LUAU_INSN_A(insn)); - StkId rb = VM_REG(LUAU_INSN_B(insn)); - TValue* kv = VM_KV(LUAU_INSN_C(insn)); - - setobj2s(L, ra, l_isfalse(rb) ? kv : rb); - VM_NEXT(); - } - - VM_CASE(LOP_CONCAT) - { - Instruction insn = *pc++; - int b = LUAU_INSN_B(insn); - int c = LUAU_INSN_C(insn); - - // This call may realloc the stack! So we need to query args further down - VM_PROTECT(luaV_concat(L, c - b + 1, c)); - - StkId ra = VM_REG(LUAU_INSN_A(insn)); - - setobj2s(L, ra, base + b); - VM_PROTECT(luaC_checkGC(L)); - VM_NEXT(); - } - - VM_CASE(LOP_NOT) - { - Instruction insn = *pc++; - StkId ra = VM_REG(LUAU_INSN_A(insn)); - StkId rb = VM_REG(LUAU_INSN_B(insn)); - - int res = l_isfalse(rb); - setbvalue(ra, res); - VM_NEXT(); - } - - VM_CASE(LOP_MINUS) - { - Instruction insn = *pc++; - StkId ra = VM_REG(LUAU_INSN_A(insn)); - StkId rb = VM_REG(LUAU_INSN_B(insn)); - - // fast-path - if (LUAU_LIKELY(ttisnumber(rb))) - { - setnvalue(ra, -nvalue(rb)); - VM_NEXT(); - } - else if (ttisvector(rb)) - { - const float* vb = vvalue(rb); - setvvalue(ra, -vb[0], -vb[1], -vb[2], -vb[3]); - VM_NEXT(); - } - else - { - // fast-path for userdata with C functions - const TValue* fn = 0; - if (ttisuserdata(rb) && (fn = luaT_gettmbyobj(L, rb, TM_UNM)) && ttisfunction(fn) && clvalue(fn)->isC) - { - // note: it's safe to push arguments past top for complicated reasons (see top of the file) - LUAU_ASSERT(L->top + 2 < L->stack + L->stacksize); - StkId top = L->top; - setobj2s(L, top + 0, fn); - setobj2s(L, top + 1, rb); - L->top = top + 2; - - VM_PROTECT(luaV_callTM(L, 1, LUAU_INSN_A(insn))); - VM_NEXT(); - } - else - { - // slow-path, may invoke C/Lua via metamethods - VM_PROTECT(luaV_doarith(L, ra, rb, rb, TM_UNM)); - VM_NEXT(); - } - } - } - - VM_CASE(LOP_LENGTH) - { - Instruction insn = *pc++; - StkId ra = VM_REG(LUAU_INSN_A(insn)); - StkId rb = VM_REG(LUAU_INSN_B(insn)); - - // fast-path #1: tables - if (LUAU_LIKELY(ttistable(rb))) - { - Table* h = hvalue(rb); - - if (fastnotm(h->metatable, TM_LEN)) - { - setnvalue(ra, cast_num(luaH_getn(h))); - VM_NEXT(); - } - else - { - // slow-path, may invoke C/Lua via metamethods - VM_PROTECT(luaV_dolen(L, ra, rb)); - VM_NEXT(); - } - } - // fast-path #2: strings (not very important but easy to do) - else if (ttisstring(rb)) - { - TString* ts = tsvalue(rb); - setnvalue(ra, cast_num(ts->len)); - VM_NEXT(); - } - else - { - // slow-path, may invoke C/Lua via metamethods - VM_PROTECT(luaV_dolen(L, ra, rb)); - VM_NEXT(); - } - } - - VM_CASE(LOP_NEWTABLE) - { - Instruction insn = *pc++; - StkId ra = VM_REG(LUAU_INSN_A(insn)); - int b = LUAU_INSN_B(insn); - uint32_t aux = *pc++; - - VM_PROTECT_PC(); // luaH_new may fail due to OOM - - sethvalue(L, ra, luaH_new(L, aux, b == 0 ? 0 : (1 << (b - 1)))); - VM_PROTECT(luaC_checkGC(L)); - VM_NEXT(); - } - - VM_CASE(LOP_DUPTABLE) - { - Instruction insn = *pc++; - StkId ra = VM_REG(LUAU_INSN_A(insn)); - TValue* kv = VM_KV(LUAU_INSN_D(insn)); - - VM_PROTECT_PC(); // luaH_clone may fail due to OOM - - sethvalue(L, ra, luaH_clone(L, hvalue(kv))); - VM_PROTECT(luaC_checkGC(L)); - VM_NEXT(); - } - - VM_CASE(LOP_SETLIST) - { - Instruction insn = *pc++; - StkId ra = VM_REG(LUAU_INSN_A(insn)); - StkId rb = &base[LUAU_INSN_B(insn)]; // note: this can point to L->top if c == LUA_MULTRET making VM_REG unsafe to use - int c = LUAU_INSN_C(insn) - 1; - uint32_t index = *pc++; - - if (c == LUA_MULTRET) - { - c = int(L->top - rb); - L->top = L->ci->top; - } - - Table* h = hvalue(ra); - - // TODO: we really don't need this anymore - if (!ttistable(ra)) - return; // temporary workaround to weaken a rather powerful exploitation primitive in case of a MITM attack on bytecode - - int last = index + c - 1; - if (last > h->sizearray) - { - VM_PROTECT_PC(); // luaH_resizearray may fail due to OOM - - luaH_resizearray(L, h, last); - } - - TValue* array = h->array; - - for (int i = 0; i < c; ++i) - setobj2t(L, &array[index + i - 1], rb + i); - - luaC_barrierfast(L, h); - VM_NEXT(); - } - - VM_CASE(LOP_FORNPREP) - { - Instruction insn = *pc++; - StkId ra = VM_REG(LUAU_INSN_A(insn)); - - if (!ttisnumber(ra + 0) || !ttisnumber(ra + 1) || !ttisnumber(ra + 2)) - { - // slow-path: can convert arguments to numbers and trigger Lua errors - // Note: this doesn't reallocate stack so we don't need to recompute ra/base - VM_PROTECT_PC(); - - luaV_prepareFORN(L, ra + 0, ra + 1, ra + 2); - } - - double limit = nvalue(ra + 0); - double step = nvalue(ra + 1); - double idx = nvalue(ra + 2); - - // Note: make sure the loop condition is exactly the same between this and LOP_FORNLOOP so that we handle NaN/etc. consistently - pc += (step > 0 ? idx <= limit : limit <= idx) ? 0 : LUAU_INSN_D(insn); - LUAU_ASSERT(unsigned(pc - cl->l.p->code) < unsigned(cl->l.p->sizecode)); - VM_NEXT(); - } - - VM_CASE(LOP_FORNLOOP) - { - VM_INTERRUPT(); - Instruction insn = *pc++; - StkId ra = VM_REG(LUAU_INSN_A(insn)); - LUAU_ASSERT(ttisnumber(ra + 0) && ttisnumber(ra + 1) && ttisnumber(ra + 2)); - - double limit = nvalue(ra + 0); - double step = nvalue(ra + 1); - double idx = nvalue(ra + 2) + step; - - setnvalue(ra + 2, idx); - - // Note: make sure the loop condition is exactly the same between this and LOP_FORNPREP so that we handle NaN/etc. consistently - if (step > 0 ? idx <= limit : limit <= idx) - { - pc += LUAU_INSN_D(insn); - LUAU_ASSERT(unsigned(pc - cl->l.p->code) < unsigned(cl->l.p->sizecode)); - VM_NEXT(); - } - else - { - // fallthrough to exit - VM_NEXT(); - } - } - - VM_CASE(LOP_FORGPREP) - { - Instruction insn = *pc++; - StkId ra = VM_REG(LUAU_INSN_A(insn)); - - if (ttisfunction(ra)) - { - // will be called during FORGLOOP - } - else - { - Table* mt = ttistable(ra) ? hvalue(ra)->metatable : ttisuserdata(ra) ? uvalue(ra)->metatable : cast_to(Table*, NULL); - - if (const TValue* fn = fasttm(L, mt, TM_ITER)) - { - setobj2s(L, ra + 1, ra); - setobj2s(L, ra, fn); - - L->top = ra + 2; // func + self arg - LUAU_ASSERT(L->top <= L->stack_last); - - VM_PROTECT(luaD_call(L, ra, 3)); - L->top = L->ci->top; - - // recompute ra since stack might have been reallocated - ra = VM_REG(LUAU_INSN_A(insn)); - - // protect against __iter returning nil, since nil is used as a marker for builtin iteration in FORGLOOP - if (ttisnil(ra)) - { - VM_PROTECT_PC(); // next call always errors - luaG_typeerror(L, ra, "call"); - } - } - else if (fasttm(L, mt, TM_CALL)) - { - // table or userdata with __call, will be called during FORGLOOP - // TODO: we might be able to stop supporting this depending on whether it's used in practice - } - else if (ttistable(ra)) - { - // set up registers for builtin iteration - setobj2s(L, ra + 1, ra); - setpvalue(ra + 2, reinterpret_cast(uintptr_t(0)), LU_TAG_ITERATOR); - setnilvalue(ra); - } - else - { - VM_PROTECT_PC(); // next call always errors - luaG_typeerror(L, ra, "iterate over"); - } - } - - pc += LUAU_INSN_D(insn); - LUAU_ASSERT(unsigned(pc - cl->l.p->code) < unsigned(cl->l.p->sizecode)); - VM_NEXT(); - } - - VM_CASE(LOP_FORGLOOP) - { - VM_INTERRUPT(); - Instruction insn = *pc++; - StkId ra = VM_REG(LUAU_INSN_A(insn)); - uint32_t aux = *pc; - - // fast-path: builtin table iteration - // note: ra=nil guarantees ra+1=table and ra+2=userdata because of the setup by FORGPREP* opcodes - // TODO: remove the table check per guarantee above - if (ttisnil(ra) && ttistable(ra + 1)) - { - Table* h = hvalue(ra + 1); - int index = int(reinterpret_cast(pvalue(ra + 2))); - - int sizearray = h->sizearray; - - // clear extra variables since we might have more than two - // note: while aux encodes ipairs bit, when set we always use 2 variables, so it's safe to check this via a signed comparison - if (LUAU_UNLIKELY(int(aux) > 2)) - for (int i = 2; i < int(aux); ++i) - setnilvalue(ra + 3 + i); - - // terminate ipairs-style traversal early when encountering nil - if (int(aux) < 0 && (unsigned(index) >= unsigned(sizearray) || ttisnil(&h->array[index]))) - { - pc++; - VM_NEXT(); - } - - // first we advance index through the array portion - while (unsigned(index) < unsigned(sizearray)) - { - TValue* e = &h->array[index]; - - if (!ttisnil(e)) - { - setpvalue(ra + 2, reinterpret_cast(uintptr_t(index + 1)), LU_TAG_ITERATOR); - setnvalue(ra + 3, double(index + 1)); - setobj2s(L, ra + 4, e); - - pc += LUAU_INSN_D(insn); - LUAU_ASSERT(unsigned(pc - cl->l.p->code) < unsigned(cl->l.p->sizecode)); - VM_NEXT(); - } - - index++; - } - - int sizenode = 1 << h->lsizenode; - - // then we advance index through the hash portion - while (unsigned(index - sizearray) < unsigned(sizenode)) - { - LuaNode* n = &h->node[index - sizearray]; - - if (!ttisnil(gval(n))) - { - setpvalue(ra + 2, reinterpret_cast(uintptr_t(index + 1)), LU_TAG_ITERATOR); - getnodekey(L, ra + 3, n); - setobj2s(L, ra + 4, gval(n)); - - pc += LUAU_INSN_D(insn); - LUAU_ASSERT(unsigned(pc - cl->l.p->code) < unsigned(cl->l.p->sizecode)); - VM_NEXT(); - } - - index++; - } - - // fallthrough to exit - pc++; - VM_NEXT(); - } - else - { - // note: it's safe to push arguments past top for complicated reasons (see top of the file) - setobj2s(L, ra + 3 + 2, ra + 2); - setobj2s(L, ra + 3 + 1, ra + 1); - setobj2s(L, ra + 3, ra); - - L->top = ra + 3 + 3; // func + 2 args (state and index) - LUAU_ASSERT(L->top <= L->stack_last); - - VM_PROTECT(luaD_call(L, ra + 3, uint8_t(aux))); - L->top = L->ci->top; - - // recompute ra since stack might have been reallocated - ra = VM_REG(LUAU_INSN_A(insn)); - - // copy first variable back into the iteration index - setobj2s(L, ra + 2, ra + 3); - - // note that we need to increment pc by 1 to exit the loop since we need to skip over aux - pc += ttisnil(ra + 3) ? 1 : LUAU_INSN_D(insn); - LUAU_ASSERT(unsigned(pc - cl->l.p->code) < unsigned(cl->l.p->sizecode)); - VM_NEXT(); - } - } - - VM_CASE(LOP_FORGPREP_INEXT) - { - Instruction insn = *pc++; - StkId ra = VM_REG(LUAU_INSN_A(insn)); - - // fast-path: ipairs/inext - if (cl->env->safeenv && ttistable(ra + 1) && ttisnumber(ra + 2) && nvalue(ra + 2) == 0.0) - { - setnilvalue(ra); - // ra+1 is already the table - setpvalue(ra + 2, reinterpret_cast(uintptr_t(0)), LU_TAG_ITERATOR); - } - else if (!ttisfunction(ra)) - { - VM_PROTECT_PC(); // next call always errors - luaG_typeerror(L, ra, "iterate over"); - } - - pc += LUAU_INSN_D(insn); - LUAU_ASSERT(unsigned(pc - cl->l.p->code) < unsigned(cl->l.p->sizecode)); - VM_NEXT(); - } - - VM_CASE(LOP_DEP_FORGLOOP_INEXT) - { - LUAU_ASSERT(!"Unsupported deprecated opcode"); - LUAU_UNREACHABLE(); - } - - VM_CASE(LOP_FORGPREP_NEXT) - { - Instruction insn = *pc++; - StkId ra = VM_REG(LUAU_INSN_A(insn)); - - // fast-path: pairs/next - if (cl->env->safeenv && ttistable(ra + 1) && ttisnil(ra + 2)) - { - setnilvalue(ra); - // ra+1 is already the table - setpvalue(ra + 2, reinterpret_cast(uintptr_t(0)), LU_TAG_ITERATOR); - } - else if (!ttisfunction(ra)) - { - VM_PROTECT_PC(); // next call always errors - luaG_typeerror(L, ra, "iterate over"); - } - - pc += LUAU_INSN_D(insn); - LUAU_ASSERT(unsigned(pc - cl->l.p->code) < unsigned(cl->l.p->sizecode)); - VM_NEXT(); - } - - VM_CASE(LOP_NATIVECALL) - { - Proto* p = cl->l.p; - LUAU_ASSERT(p->execdata); - - CallInfo* ci = L->ci; - ci->flags = LUA_CALLINFO_NATIVE; - ci->savedpc = p->code; - -#if VM_HAS_NATIVE - if (L->global->ecb.enter(L, p) == 1) - goto reentry; - else - goto exit; -#else - LUAU_ASSERT(!"Opcode is only valid when VM_HAS_NATIVE is defined"); - LUAU_UNREACHABLE(); -#endif - } - - VM_CASE(LOP_GETVARARGS) - { - Instruction insn = *pc++; - int b = LUAU_INSN_B(insn) - 1; - int n = cast_int(base - L->ci->func) - cl->l.p->numparams - 1; - - if (b == LUA_MULTRET) - { - VM_PROTECT(luaD_checkstack(L, n)); - StkId ra = VM_REG(LUAU_INSN_A(insn)); // previous call may change the stack - - for (int j = 0; j < n; j++) - setobj2s(L, ra + j, base - n + j); - - L->top = ra + n; - VM_NEXT(); - } - else - { - StkId ra = VM_REG(LUAU_INSN_A(insn)); - - for (int j = 0; j < b && j < n; j++) - setobj2s(L, ra + j, base - n + j); - for (int j = n; j < b; j++) - setnilvalue(ra + j); - VM_NEXT(); - } - } - - VM_CASE(LOP_DUPCLOSURE) - { - Instruction insn = *pc++; - StkId ra = VM_REG(LUAU_INSN_A(insn)); - TValue* kv = VM_KV(LUAU_INSN_D(insn)); - - Closure* kcl = clvalue(kv); - - VM_PROTECT_PC(); // luaF_newLclosure may fail due to OOM - - // clone closure if the environment is not shared - // note: we save closure to stack early in case the code below wants to capture it by value - Closure* ncl = (kcl->env == cl->env) ? kcl : luaF_newLclosure(L, kcl->nupvalues, cl->env, kcl->l.p); - setclvalue(L, ra, ncl); - - // this loop does three things: - // - if the closure was created anew, it just fills it with upvalues - // - if the closure from the constant table is used, it fills it with upvalues so that it can be shared in the future - // - if the closure is reused, it checks if the reuse is safe via rawequal, and falls back to duplicating the closure - // normally this would use two separate loops, for reuse check and upvalue setup, but MSVC codegen goes crazy if you do that - for (int ui = 0; ui < kcl->nupvalues; ++ui) - { - Instruction uinsn = pc[ui]; - LUAU_ASSERT(LUAU_INSN_OP(uinsn) == LOP_CAPTURE); - LUAU_ASSERT(LUAU_INSN_A(uinsn) == LCT_VAL || LUAU_INSN_A(uinsn) == LCT_UPVAL); - - TValue* uv = (LUAU_INSN_A(uinsn) == LCT_VAL) ? VM_REG(LUAU_INSN_B(uinsn)) : VM_UV(LUAU_INSN_B(uinsn)); - - // check if the existing closure is safe to reuse - if (ncl == kcl && luaO_rawequalObj(&ncl->l.uprefs[ui], uv)) - continue; - - // lazily clone the closure and update the upvalues - if (ncl == kcl && kcl->preload == 0) - { - ncl = luaF_newLclosure(L, kcl->nupvalues, cl->env, kcl->l.p); - setclvalue(L, ra, ncl); - - ui = -1; // restart the loop to fill all upvalues - continue; - } - - // this updates a newly created closure, or an existing closure created during preload, in which case we need a barrier - setobj(L, &ncl->l.uprefs[ui], uv); - luaC_barrier(L, ncl, uv); - } - - // this is a noop if ncl is newly created or shared successfully, but it has to run after the closure is preloaded for the first time - ncl->preload = 0; - - if (kcl != ncl) - VM_PROTECT(luaC_checkGC(L)); - - pc += kcl->nupvalues; - VM_NEXT(); - } - - VM_CASE(LOP_PREPVARARGS) - { - Instruction insn = *pc++; - int numparams = LUAU_INSN_A(insn); - - // all fixed parameters are copied after the top so we need more stack space - VM_PROTECT(luaD_checkstack(L, cl->stacksize + numparams)); - - // the caller must have filled extra fixed arguments with nil - LUAU_ASSERT(cast_int(L->top - base) >= numparams); - - // move fixed parameters to final position - StkId fixed = base; // first fixed argument - base = L->top; // final position of first argument - - for (int i = 0; i < numparams; ++i) - { - setobj2s(L, base + i, fixed + i); - setnilvalue(fixed + i); - } - - // rewire our stack frame to point to the new base - L->ci->base = base; - L->ci->top = base + cl->stacksize; - - L->base = base; - L->top = L->ci->top; - VM_NEXT(); - } - - VM_CASE(LOP_JUMPBACK) - { - VM_INTERRUPT(); - Instruction insn = *pc++; - - pc += LUAU_INSN_D(insn); - LUAU_ASSERT(unsigned(pc - cl->l.p->code) < unsigned(cl->l.p->sizecode)); - VM_NEXT(); - } - - VM_CASE(LOP_LOADKX) - { - Instruction insn = *pc++; - StkId ra = VM_REG(LUAU_INSN_A(insn)); - uint32_t aux = *pc++; - TValue* kv = VM_KV(aux); - - setobj2s(L, ra, kv); - VM_NEXT(); - } - - VM_CASE(LOP_JUMPX) - { - VM_INTERRUPT(); - Instruction insn = *pc++; - - pc += LUAU_INSN_E(insn); - LUAU_ASSERT(unsigned(pc - cl->l.p->code) < unsigned(cl->l.p->sizecode)); - VM_NEXT(); - } - - VM_CASE(LOP_FASTCALL) - { - Instruction insn = *pc++; - int bfid = LUAU_INSN_A(insn); - int skip = LUAU_INSN_C(insn); - LUAU_ASSERT(unsigned(pc - cl->l.p->code + skip) < unsigned(cl->l.p->sizecode)); - - Instruction call = pc[skip]; - LUAU_ASSERT(LUAU_INSN_OP(call) == LOP_CALL); - - StkId ra = VM_REG(LUAU_INSN_A(call)); - - int nparams = LUAU_INSN_B(call) - 1; - int nresults = LUAU_INSN_C(call) - 1; - - nparams = (nparams == LUA_MULTRET) ? int(L->top - ra - 1) : nparams; - - luau_FastFunction f = luauF_table[bfid]; - LUAU_ASSERT(f); - - if (cl->env->safeenv) - { - VM_PROTECT_PC(); // f may fail due to OOM - - int n = f(L, ra, ra + 1, nresults, ra + 2, nparams); - - if (n >= 0) - { - // when nresults != MULTRET, L->top might be pointing to the middle of stack frame if nparams is equal to MULTRET - // instead of restoring L->top to L->ci->top if nparams is MULTRET, we do it unconditionally to skip an extra check - L->top = (nresults == LUA_MULTRET) ? ra + n : L->ci->top; - - pc += skip + 1; // skip instructions that compute function as well as CALL - LUAU_ASSERT(unsigned(pc - cl->l.p->code) < unsigned(cl->l.p->sizecode)); - VM_NEXT(); - } - else - { - // continue execution through the fallback code - VM_NEXT(); - } - } - else - { - // continue execution through the fallback code - VM_NEXT(); - } - } - - VM_CASE(LOP_COVERAGE) - { - Instruction insn = *pc++; - int hits = LUAU_INSN_E(insn); - - // update hits with saturated add and patch the instruction in place - hits = (hits < (1 << 23) - 1) ? hits + 1 : hits; - VM_PATCH_E(pc - 1, hits); - - VM_NEXT(); - } - - VM_CASE(LOP_CAPTURE) - { - LUAU_ASSERT(!"CAPTURE is a pseudo-opcode and must be executed as part of NEWCLOSURE"); - LUAU_UNREACHABLE(); - } - - VM_CASE(LOP_SUBRK) - { - Instruction insn = *pc++; - StkId ra = VM_REG(LUAU_INSN_A(insn)); - TValue* kv = VM_KV(LUAU_INSN_B(insn)); - StkId rc = VM_REG(LUAU_INSN_C(insn)); - - // fast-path - if (ttisnumber(rc)) - { - setnvalue(ra, nvalue(kv) - nvalue(rc)); - VM_NEXT(); - } - else - { - // slow-path, may invoke C/Lua via metamethods - VM_PROTECT(luaV_doarith(L, ra, kv, rc, TM_SUB)); - VM_NEXT(); - } - } - - VM_CASE(LOP_DIVRK) - { - Instruction insn = *pc++; - StkId ra = VM_REG(LUAU_INSN_A(insn)); - TValue* kv = VM_KV(LUAU_INSN_B(insn)); - StkId rc = VM_REG(LUAU_INSN_C(insn)); - - // fast-path - if (LUAU_LIKELY(ttisnumber(rc))) - { - setnvalue(ra, nvalue(kv) / nvalue(rc)); - VM_NEXT(); - } - else if (ttisvector(rc)) - { - float nb = cast_to(float, nvalue(kv)); - const float* vc = vvalue(rc); - setvvalue(ra, nb / vc[0], nb / vc[1], nb / vc[2], nb / vc[3]); - VM_NEXT(); - } - else - { - // slow-path, may invoke C/Lua via metamethods - VM_PROTECT(luaV_doarith(L, ra, kv, rc, TM_DIV)); - VM_NEXT(); - } - } - - VM_CASE(LOP_FASTCALL1) - { - Instruction insn = *pc++; - int bfid = LUAU_INSN_A(insn); - TValue* arg = VM_REG(LUAU_INSN_B(insn)); - int skip = LUAU_INSN_C(insn); - - LUAU_ASSERT(unsigned(pc - cl->l.p->code + skip) < unsigned(cl->l.p->sizecode)); - - Instruction call = pc[skip]; - LUAU_ASSERT(LUAU_INSN_OP(call) == LOP_CALL); - - StkId ra = VM_REG(LUAU_INSN_A(call)); - - int nparams = 1; - int nresults = LUAU_INSN_C(call) - 1; - - luau_FastFunction f = luauF_table[bfid]; - LUAU_ASSERT(f); - - if (cl->env->safeenv) - { - VM_PROTECT_PC(); // f may fail due to OOM - - int n = f(L, ra, arg, nresults, NULL, nparams); - - if (n >= 0) - { - if (nresults == LUA_MULTRET) - L->top = ra + n; - - pc += skip + 1; // skip instructions that compute function as well as CALL - LUAU_ASSERT(unsigned(pc - cl->l.p->code) < unsigned(cl->l.p->sizecode)); - VM_NEXT(); - } - else - { - // continue execution through the fallback code - VM_NEXT(); - } - } - else - { - // continue execution through the fallback code - VM_NEXT(); - } - } - - VM_CASE(LOP_FASTCALL2) - { - Instruction insn = *pc++; - int bfid = LUAU_INSN_A(insn); - int skip = LUAU_INSN_C(insn) - 1; - uint32_t aux = *pc++; - TValue* arg1 = VM_REG(LUAU_INSN_B(insn)); - TValue* arg2 = VM_REG(aux); - - LUAU_ASSERT(unsigned(pc - cl->l.p->code + skip) < unsigned(cl->l.p->sizecode)); - - Instruction call = pc[skip]; - LUAU_ASSERT(LUAU_INSN_OP(call) == LOP_CALL); - - StkId ra = VM_REG(LUAU_INSN_A(call)); - - int nparams = 2; - int nresults = LUAU_INSN_C(call) - 1; - - luau_FastFunction f = luauF_table[bfid]; - LUAU_ASSERT(f); - - if (cl->env->safeenv) - { - VM_PROTECT_PC(); // f may fail due to OOM - - int n = f(L, ra, arg1, nresults, arg2, nparams); - - if (n >= 0) - { - if (nresults == LUA_MULTRET) - L->top = ra + n; - - pc += skip + 1; // skip instructions that compute function as well as CALL - LUAU_ASSERT(unsigned(pc - cl->l.p->code) < unsigned(cl->l.p->sizecode)); - VM_NEXT(); - } - else - { - // continue execution through the fallback code - VM_NEXT(); - } - } - else - { - // continue execution through the fallback code - VM_NEXT(); - } - } - - VM_CASE(LOP_FASTCALL2K) - { - Instruction insn = *pc++; - int bfid = LUAU_INSN_A(insn); - int skip = LUAU_INSN_C(insn) - 1; - uint32_t aux = *pc++; - TValue* arg1 = VM_REG(LUAU_INSN_B(insn)); - TValue* arg2 = VM_KV(aux); - - LUAU_ASSERT(unsigned(pc - cl->l.p->code + skip) < unsigned(cl->l.p->sizecode)); - - Instruction call = pc[skip]; - LUAU_ASSERT(LUAU_INSN_OP(call) == LOP_CALL); - - StkId ra = VM_REG(LUAU_INSN_A(call)); - - int nparams = 2; - int nresults = LUAU_INSN_C(call) - 1; - - luau_FastFunction f = luauF_table[bfid]; - LUAU_ASSERT(f); - - if (cl->env->safeenv) - { - VM_PROTECT_PC(); // f may fail due to OOM - - int n = f(L, ra, arg1, nresults, arg2, nparams); - - if (n >= 0) - { - if (nresults == LUA_MULTRET) - L->top = ra + n; - - pc += skip + 1; // skip instructions that compute function as well as CALL - LUAU_ASSERT(unsigned(pc - cl->l.p->code) < unsigned(cl->l.p->sizecode)); - VM_NEXT(); - } - else - { - // continue execution through the fallback code - VM_NEXT(); - } - } - else - { - // continue execution through the fallback code - VM_NEXT(); - } - } - - VM_CASE(LOP_BREAK) - { - LUAU_ASSERT(cl->l.p->debuginsn); - - uint8_t op = cl->l.p->debuginsn[unsigned(pc - cl->l.p->code)]; - LUAU_ASSERT(op != LOP_BREAK); - - if (L->global->cb.debugbreak) - { - VM_PROTECT(luau_callhook(L, L->global->cb.debugbreak, NULL)); - - // allow debugbreak hook to put thread into error/yield state - if (L->status != 0) - goto exit; - } - - VM_CONTINUE(op); - } - - VM_CASE(LOP_JUMPXEQKNIL) - { - Instruction insn = *pc++; - uint32_t aux = *pc; - StkId ra = VM_REG(LUAU_INSN_A(insn)); - - static_assert(LUA_TNIL == 0, "we expect type-1 to be negative iff type is nil"); - // condition is equivalent to: int(ttisnil(ra)) != (aux >> 31) - pc += int((ttype(ra) - 1) ^ aux) < 0 ? LUAU_INSN_D(insn) : 1; - LUAU_ASSERT(unsigned(pc - cl->l.p->code) < unsigned(cl->l.p->sizecode)); - VM_NEXT(); - } - - VM_CASE(LOP_JUMPXEQKB) - { - Instruction insn = *pc++; - uint32_t aux = *pc; - StkId ra = VM_REG(LUAU_INSN_A(insn)); - - pc += int(ttisboolean(ra) && bvalue(ra) == int(aux & 1)) != (aux >> 31) ? LUAU_INSN_D(insn) : 1; - LUAU_ASSERT(unsigned(pc - cl->l.p->code) < unsigned(cl->l.p->sizecode)); - VM_NEXT(); - } - - VM_CASE(LOP_JUMPXEQKN) - { - Instruction insn = *pc++; - uint32_t aux = *pc; - StkId ra = VM_REG(LUAU_INSN_A(insn)); - TValue* kv = VM_KV(aux & 0xffffff); - LUAU_ASSERT(ttisnumber(kv)); - -#if defined(__aarch64__) - // On several ARM chips (Apple M1/M2, Neoverse N1), comparing the result of a floating-point comparison is expensive, and a branch - // is much cheaper; on some 32-bit ARM chips (Cortex A53) the performance is about the same so we prefer less branchy variant there - if (aux >> 31) - pc += !(ttisnumber(ra) && nvalue(ra) == nvalue(kv)) ? LUAU_INSN_D(insn) : 1; - else - pc += (ttisnumber(ra) && nvalue(ra) == nvalue(kv)) ? LUAU_INSN_D(insn) : 1; -#else - pc += int(ttisnumber(ra) && nvalue(ra) == nvalue(kv)) != (aux >> 31) ? LUAU_INSN_D(insn) : 1; -#endif - LUAU_ASSERT(unsigned(pc - cl->l.p->code) < unsigned(cl->l.p->sizecode)); - VM_NEXT(); - } - - VM_CASE(LOP_JUMPXEQKS) - { - Instruction insn = *pc++; - uint32_t aux = *pc; - StkId ra = VM_REG(LUAU_INSN_A(insn)); - TValue* kv = VM_KV(aux & 0xffffff); - LUAU_ASSERT(ttisstring(kv)); - - pc += int(ttisstring(ra) && gcvalue(ra) == gcvalue(kv)) != (aux >> 31) ? LUAU_INSN_D(insn) : 1; - LUAU_ASSERT(unsigned(pc - cl->l.p->code) < unsigned(cl->l.p->sizecode)); - VM_NEXT(); - } - -#if !VM_USE_CGOTO - default: - LUAU_ASSERT(!"Unknown opcode"); - LUAU_UNREACHABLE(); // improves switch() codegen by eliding opcode bounds checks -#endif - } - } - -exit:; -} - -void luau_execute(lua_State* L) -{ - if (L->singlestep) - luau_execute(L); - else - luau_execute(L); -} - -int luau_precall(lua_State* L, StkId func, int nresults) -{ - if (!ttisfunction(func)) - { - luaV_tryfuncTM(L, func); - // L->top is incremented by tryfuncTM - } - - Closure* ccl = clvalue(func); - - CallInfo* ci = incr_ci(L); - ci->func = func; - ci->base = func + 1; - ci->top = L->top + ccl->stacksize; - ci->savedpc = NULL; - ci->flags = 0; - ci->nresults = nresults; - - L->base = ci->base; - // Note: L->top is assigned externally - - luaD_checkstack(L, ccl->stacksize); - LUAU_ASSERT(ci->top <= L->stack_last); - - if (!ccl->isC) - { - Proto* p = ccl->l.p; - - // fill unused parameters with nil - StkId argi = L->top; - StkId argend = L->base + p->numparams; - while (argi < argend) - setnilvalue(argi++); // complete missing arguments - L->top = p->is_vararg ? argi : ci->top; - - ci->savedpc = p->code; - -#if VM_HAS_NATIVE - if (p->execdata) - ci->flags = LUA_CALLINFO_NATIVE; -#endif - - return PCRLUA; - } - else - { - lua_CFunction func = ccl->c.f; - int n = func(L); - - // yield - if (n < 0) - return PCRYIELD; - - // ci is our callinfo, cip is our parent - CallInfo* ci = L->ci; - CallInfo* cip = ci - 1; - - // copy return values into parent stack (but only up to nresults!), fill the rest with nil - // TODO: it might be worthwhile to handle the case when nresults==b explicitly? - StkId res = ci->func; - StkId vali = L->top - n; - StkId valend = L->top; - - int i; - for (i = nresults; i != 0 && vali < valend; i--) - setobj2s(L, res++, vali++); - while (i-- > 0) - setnilvalue(res++); - - // pop the stack frame - L->ci = cip; - L->base = cip->base; - L->top = res; - - return PCRC; - } -} - -void luau_poscall(lua_State* L, StkId first) -{ - // finish interrupted execution of `OP_CALL' - // ci is our callinfo, cip is our parent - CallInfo* ci = L->ci; - CallInfo* cip = ci - 1; - - // copy return values into parent stack (but only up to nresults!), fill the rest with nil - // TODO: it might be worthwhile to handle the case when nresults==b explicitly? - StkId res = ci->func; - StkId vali = first; - StkId valend = L->top; - - int i; - for (i = ci->nresults; i != 0 && vali < valend; i--) - setobj2s(L, res++, vali++); - while (i-- > 0) - setnilvalue(res++); - - // pop the stack frame - L->ci = cip; - L->base = cip->base; - L->top = (ci->nresults == LUA_MULTRET) ? res : cip->top; -} diff --git a/lib/luau/VM/src/lvmload.cpp b/lib/luau/VM/src/lvmload.cpp deleted file mode 100644 index 5f1ff40..0000000 --- a/lib/luau/VM/src/lvmload.cpp +++ /dev/null @@ -1,424 +0,0 @@ -// This file is part of the Luau programming language and is licensed under MIT License; see LICENSE.txt for details -// This code is based on Lua 5.x implementation licensed under MIT License; see lua_LICENSE.txt for details -#include "lvm.h" - -#include "lstate.h" -#include "ltable.h" -#include "lfunc.h" -#include "lstring.h" -#include "lgc.h" -#include "lmem.h" -#include "lbytecode.h" -#include "lapi.h" - -#include - -// TODO: RAII deallocation doesn't work for longjmp builds if a memory error happens -template -struct TempBuffer -{ - lua_State* L; - T* data; - size_t count; - - TempBuffer(lua_State* L, size_t count) - : L(L) - , data(luaM_newarray(L, count, T, 0)) - , count(count) - { - } - - ~TempBuffer() - { - luaM_freearray(L, data, count, T, 0); - } - - T& operator[](size_t index) - { - LUAU_ASSERT(index < count); - return data[index]; - } -}; - -void luaV_getimport(lua_State* L, Table* env, TValue* k, StkId res, uint32_t id, bool propagatenil) -{ - int count = id >> 30; - LUAU_ASSERT(count > 0); - - int id0 = int(id >> 20) & 1023; - int id1 = int(id >> 10) & 1023; - int id2 = int(id) & 1023; - - // after the first call to luaV_gettable, res may be invalid, and env may (sometimes) be garbage collected - // we take care to not use env again and to restore res before every consecutive use - ptrdiff_t resp = savestack(L, res); - - // global lookup for id0 - TValue g; - sethvalue(L, &g, env); - luaV_gettable(L, &g, &k[id0], res); - - // table lookup for id1 - if (count < 2) - return; - - res = restorestack(L, resp); - if (!propagatenil || !ttisnil(res)) - luaV_gettable(L, res, &k[id1], res); - - // table lookup for id2 - if (count < 3) - return; - - res = restorestack(L, resp); - if (!propagatenil || !ttisnil(res)) - luaV_gettable(L, res, &k[id2], res); -} - -template -static T read(const char* data, size_t size, size_t& offset) -{ - T result; - memcpy(&result, data + offset, sizeof(T)); - offset += sizeof(T); - - return result; -} - -static unsigned int readVarInt(const char* data, size_t size, size_t& offset) -{ - unsigned int result = 0; - unsigned int shift = 0; - - uint8_t byte; - - do - { - byte = read(data, size, offset); - result |= (byte & 127) << shift; - shift += 7; - } while (byte & 128); - - return result; -} - -static TString* readString(TempBuffer& strings, const char* data, size_t size, size_t& offset) -{ - unsigned int id = readVarInt(data, size, offset); - - return id == 0 ? NULL : strings[id - 1]; -} - -static void resolveImportSafe(lua_State* L, Table* env, TValue* k, uint32_t id) -{ - struct ResolveImport - { - TValue* k; - uint32_t id; - - static void run(lua_State* L, void* ud) - { - ResolveImport* self = static_cast(ud); - - // note: we call getimport with nil propagation which means that accesses to table chains like A.B.C will resolve in nil - // this is technically not necessary but it reduces the number of exceptions when loading scripts that rely on getfenv/setfenv for global - // injection - // allocate a stack slot so that we can do table lookups - luaD_checkstack(L, 1); - setnilvalue(L->top); - L->top++; - - luaV_getimport(L, L->gt, self->k, L->top - 1, self->id, /* propagatenil= */ true); - } - }; - - ResolveImport ri = {k, id}; - if (L->gt->safeenv) - { - // luaD_pcall will make sure that if any C/Lua calls during import resolution fail, the thread state is restored back - int oldTop = lua_gettop(L); - int status = luaD_pcall(L, &ResolveImport::run, &ri, savestack(L, L->top), 0); - LUAU_ASSERT(oldTop + 1 == lua_gettop(L)); // if an error occurred, luaD_pcall saves it on stack - - if (status != 0) - { - // replace error object with nil - setnilvalue(L->top - 1); - } - } - else - { - setnilvalue(L->top); - L->top++; - } -} - -int luau_load(lua_State* L, const char* chunkname, const char* data, size_t size, int env) -{ - size_t offset = 0; - - uint8_t version = read(data, size, offset); - - - - // 0 means the rest of the bytecode is the error message - if (version == 0) - { - char chunkbuf[LUA_IDSIZE]; - const char* chunkid = luaO_chunkid(chunkbuf, sizeof(chunkbuf), chunkname, strlen(chunkname)); - lua_pushfstring(L, "%s%.*s", chunkid, int(size - offset), data + offset); - return 1; - } - - if (version < LBC_VERSION_MIN || version > LBC_VERSION_MAX) - { - char chunkbuf[LUA_IDSIZE]; - const char* chunkid = luaO_chunkid(chunkbuf, sizeof(chunkbuf), chunkname, strlen(chunkname)); - lua_pushfstring(L, "%s: bytecode version mismatch (expected [%d..%d], got %d)", chunkid, LBC_VERSION_MIN, LBC_VERSION_MAX, version); - return 1; - } - - // we will allocate a fair amount of memory so check GC before we do - luaC_checkGC(L); - - // pause GC for the duration of deserialization - some objects we're creating aren't rooted - // TODO: if an allocation error happens mid-load, we do not unpause GC! - size_t GCthreshold = L->global->GCthreshold; - L->global->GCthreshold = SIZE_MAX; - - // env is 0 for current environment and a stack index otherwise - Table* envt = (env == 0) ? L->gt : hvalue(luaA_toobject(L, env)); - - TString* source = luaS_new(L, chunkname); - - uint8_t typesversion = 0; - - if (version >= 4) - { - typesversion = read(data, size, offset); - } - - // string table - unsigned int stringCount = readVarInt(data, size, offset); - TempBuffer strings(L, stringCount); - - for (unsigned int i = 0; i < stringCount; ++i) - { - unsigned int length = readVarInt(data, size, offset); - - strings[i] = luaS_newlstr(L, data + offset, length); - offset += length; - } - - // proto table - unsigned int protoCount = readVarInt(data, size, offset); - TempBuffer protos(L, protoCount); - - for (unsigned int i = 0; i < protoCount; ++i) - { - Proto* p = luaF_newproto(L); - p->source = source; - p->bytecodeid = int(i); - - p->maxstacksize = read(data, size, offset); - p->numparams = read(data, size, offset); - p->nups = read(data, size, offset); - p->is_vararg = read(data, size, offset); - - if (version >= 4) - { - p->flags = read(data, size, offset); - - uint32_t typesize = readVarInt(data, size, offset); - - if (typesize && typesversion == LBC_TYPE_VERSION) - { - uint8_t* types = (uint8_t*)data + offset; - - LUAU_ASSERT(typesize == unsigned(2 + p->numparams)); - LUAU_ASSERT(types[0] == LBC_TYPE_FUNCTION); - LUAU_ASSERT(types[1] == p->numparams); - - p->typeinfo = luaM_newarray(L, typesize, uint8_t, p->memcat); - memcpy(p->typeinfo, types, typesize); - } - - offset += typesize; - } - - p->sizecode = readVarInt(data, size, offset); - p->code = luaM_newarray(L, p->sizecode, Instruction, p->memcat); - for (int j = 0; j < p->sizecode; ++j) - p->code[j] = read(data, size, offset); - - p->codeentry = p->code; - - p->sizek = readVarInt(data, size, offset); - p->k = luaM_newarray(L, p->sizek, TValue, p->memcat); - -#ifdef HARDMEMTESTS - // this is redundant during normal runs, but resolveImportSafe can trigger GC checks under HARDMEMTESTS - // because p->k isn't fully formed at this point, we pre-fill it with nil to make subsequent setup safe - for (int j = 0; j < p->sizek; ++j) - { - setnilvalue(&p->k[j]); - } -#endif - - for (int j = 0; j < p->sizek; ++j) - { - switch (read(data, size, offset)) - { - case LBC_CONSTANT_NIL: - setnilvalue(&p->k[j]); - break; - - case LBC_CONSTANT_BOOLEAN: - { - uint8_t v = read(data, size, offset); - setbvalue(&p->k[j], v); - break; - } - - case LBC_CONSTANT_NUMBER: - { - double v = read(data, size, offset); - setnvalue(&p->k[j], v); - break; - } - - case LBC_CONSTANT_VECTOR: - { - float x = read(data, size, offset); - float y = read(data, size, offset); - float z = read(data, size, offset); - float w = read(data, size, offset); - (void)w; - setvvalue(&p->k[j], x, y, z, w); - break; - } - - case LBC_CONSTANT_STRING: - { - TString* v = readString(strings, data, size, offset); - setsvalue(L, &p->k[j], v); - break; - } - - case LBC_CONSTANT_IMPORT: - { - uint32_t iid = read(data, size, offset); - resolveImportSafe(L, envt, p->k, iid); - setobj(L, &p->k[j], L->top - 1); - L->top--; - break; - } - - case LBC_CONSTANT_TABLE: - { - int keys = readVarInt(data, size, offset); - Table* h = luaH_new(L, 0, keys); - for (int i = 0; i < keys; ++i) - { - int key = readVarInt(data, size, offset); - TValue* val = luaH_set(L, h, &p->k[key]); - setnvalue(val, 0.0); - } - sethvalue(L, &p->k[j], h); - break; - } - - case LBC_CONSTANT_CLOSURE: - { - uint32_t fid = readVarInt(data, size, offset); - Closure* cl = luaF_newLclosure(L, protos[fid]->nups, envt, protos[fid]); - cl->preload = (cl->nupvalues > 0); - setclvalue(L, &p->k[j], cl); - break; - } - - default: - LUAU_ASSERT(!"Unexpected constant kind"); - } - } - - p->sizep = readVarInt(data, size, offset); - p->p = luaM_newarray(L, p->sizep, Proto*, p->memcat); - for (int j = 0; j < p->sizep; ++j) - { - uint32_t fid = readVarInt(data, size, offset); - p->p[j] = protos[fid]; - } - - p->linedefined = readVarInt(data, size, offset); - p->debugname = readString(strings, data, size, offset); - - uint8_t lineinfo = read(data, size, offset); - - if (lineinfo) - { - p->linegaplog2 = read(data, size, offset); - - int intervals = ((p->sizecode - 1) >> p->linegaplog2) + 1; - int absoffset = (p->sizecode + 3) & ~3; - - p->sizelineinfo = absoffset + intervals * sizeof(int); - p->lineinfo = luaM_newarray(L, p->sizelineinfo, uint8_t, p->memcat); - p->abslineinfo = (int*)(p->lineinfo + absoffset); - - uint8_t lastoffset = 0; - for (int j = 0; j < p->sizecode; ++j) - { - lastoffset += read(data, size, offset); - p->lineinfo[j] = lastoffset; - } - - int lastline = 0; - for (int j = 0; j < intervals; ++j) - { - lastline += read(data, size, offset); - p->abslineinfo[j] = lastline; - } - } - - uint8_t debuginfo = read(data, size, offset); - - if (debuginfo) - { - p->sizelocvars = readVarInt(data, size, offset); - p->locvars = luaM_newarray(L, p->sizelocvars, LocVar, p->memcat); - - for (int j = 0; j < p->sizelocvars; ++j) - { - p->locvars[j].varname = readString(strings, data, size, offset); - p->locvars[j].startpc = readVarInt(data, size, offset); - p->locvars[j].endpc = readVarInt(data, size, offset); - p->locvars[j].reg = read(data, size, offset); - } - - p->sizeupvalues = readVarInt(data, size, offset); - p->upvalues = luaM_newarray(L, p->sizeupvalues, TString*, p->memcat); - - for (int j = 0; j < p->sizeupvalues; ++j) - { - p->upvalues[j] = readString(strings, data, size, offset); - } - } - - protos[i] = p; - } - - // "main" proto is pushed to Lua stack - uint32_t mainid = readVarInt(data, size, offset); - Proto* main = protos[mainid]; - - luaC_threadbarrier(L); - - Closure* cl = luaF_newLclosure(L, 0, envt, main); - setclvalue(L, L->top, cl); - incr_top(L); - - L->global->GCthreshold = GCthreshold; - - return 0; -} diff --git a/lib/luau/VM/src/lvmutils.cpp b/lib/luau/VM/src/lvmutils.cpp deleted file mode 100644 index 851d778..0000000 --- a/lib/luau/VM/src/lvmutils.cpp +++ /dev/null @@ -1,619 +0,0 @@ -// This file is part of the Luau programming language and is licensed under MIT License; see LICENSE.txt for details -// This code is based on Lua 5.x implementation licensed under MIT License; see lua_LICENSE.txt for details -#include "lvm.h" - -#include "lstate.h" -#include "lstring.h" -#include "ltable.h" -#include "lgc.h" -#include "ldo.h" -#include "lnumutils.h" - -#include - -// limit for table tag-method chains (to avoid loops) -#define MAXTAGLOOP 100 - -const TValue* luaV_tonumber(const TValue* obj, TValue* n) -{ - double num; - if (ttisnumber(obj)) - return obj; - if (ttisstring(obj) && luaO_str2d(svalue(obj), &num)) - { - setnvalue(n, num); - return n; - } - else - return NULL; -} - -int luaV_tostring(lua_State* L, StkId obj) -{ - if (!ttisnumber(obj)) - return 0; - else - { - char s[LUAI_MAXNUM2STR]; - double n = nvalue(obj); - char* e = luai_num2str(s, n); - LUAU_ASSERT(e < s + sizeof(s)); - setsvalue(L, obj, luaS_newlstr(L, s, e - s)); - return 1; - } -} - -const float* luaV_tovector(const TValue* obj) -{ - if (ttisvector(obj)) - return vvalue(obj); - - return nullptr; -} - -static StkId callTMres(lua_State* L, StkId res, const TValue* f, const TValue* p1, const TValue* p2) -{ - ptrdiff_t result = savestack(L, res); - // using stack room beyond top is technically safe here, but for very complicated reasons: - // * The stack guarantees EXTRA_STACK room beyond stack_last (see luaD_reallocstack) will be allocated - // * we cannot move luaD_checkstack above because the arguments are *sometimes* pointers to the lua - // stack and checkstack may invalidate those pointers - // * we cannot use savestack/restorestack because the arguments are sometimes on the C++ stack - // * during stack reallocation all of the allocated stack is copied (even beyond stack_last) so these - // values will be preserved even if they go past stack_last - LUAU_ASSERT((L->top + 3) < (L->stack + L->stacksize)); - setobj2s(L, L->top, f); // push function - setobj2s(L, L->top + 1, p1); // 1st argument - setobj2s(L, L->top + 2, p2); // 2nd argument - luaD_checkstack(L, 3); - L->top += 3; - luaD_call(L, L->top - 3, 1); - res = restorestack(L, result); - L->top--; - setobj2s(L, res, L->top); - return res; -} - -static void callTM(lua_State* L, const TValue* f, const TValue* p1, const TValue* p2, const TValue* p3) -{ - // using stack room beyond top is technically safe here, but for very complicated reasons: - // * The stack guarantees EXTRA_STACK room beyond stack_last (see luaD_reallocstack) will be allocated - // * we cannot move luaD_checkstack above because the arguments are *sometimes* pointers to the lua - // stack and checkstack may invalidate those pointers - // * we cannot use savestack/restorestack because the arguments are sometimes on the C++ stack - // * during stack reallocation all of the allocated stack is copied (even beyond stack_last) so these - // values will be preserved even if they go past stack_last - LUAU_ASSERT((L->top + 4) < (L->stack + L->stacksize)); - setobj2s(L, L->top, f); // push function - setobj2s(L, L->top + 1, p1); // 1st argument - setobj2s(L, L->top + 2, p2); // 2nd argument - setobj2s(L, L->top + 3, p3); // 3th argument - luaD_checkstack(L, 4); - L->top += 4; - luaD_call(L, L->top - 4, 0); -} - -void luaV_gettable(lua_State* L, const TValue* t, TValue* key, StkId val) -{ - int loop; - for (loop = 0; loop < MAXTAGLOOP; loop++) - { - const TValue* tm; - if (ttistable(t)) - { // `t' is a table? - Table* h = hvalue(t); - - const TValue* res = luaH_get(h, key); // do a primitive get - - if (res != luaO_nilobject) - L->cachedslot = gval2slot(h, res); // remember slot to accelerate future lookups - - if (!ttisnil(res) // result is no nil? - || (tm = fasttm(L, h->metatable, TM_INDEX)) == NULL) - { // or no TM? - setobj2s(L, val, res); - return; - } - // t isn't a table, so see if it has an INDEX meta-method to look up the key with - } - else if (ttisnil(tm = luaT_gettmbyobj(L, t, TM_INDEX))) - luaG_indexerror(L, t, key); - if (ttisfunction(tm)) - { - callTMres(L, val, tm, t, key); - return; - } - t = tm; // else repeat with `tm' - } - luaG_runerror(L, "'__index' chain too long; possible loop"); -} - -void luaV_settable(lua_State* L, const TValue* t, TValue* key, StkId val) -{ - int loop; - TValue temp; - for (loop = 0; loop < MAXTAGLOOP; loop++) - { - const TValue* tm; - if (ttistable(t)) - { // `t' is a table? - Table* h = hvalue(t); - - const TValue* oldval = luaH_get(h, key); - - // should we assign the key? (if key is valid or __newindex is not set) - if (!ttisnil(oldval) || (tm = fasttm(L, h->metatable, TM_NEWINDEX)) == NULL) - { - if (h->readonly) - luaG_readonlyerror(L); - - // luaH_set would work but would repeat the lookup so we use luaH_setslot that can reuse oldval if it's safe - TValue* newval = luaH_setslot(L, h, oldval, key); - - L->cachedslot = gval2slot(h, newval); // remember slot to accelerate future lookups - - setobj2t(L, newval, val); - luaC_barriert(L, h, val); - return; - } - - // fallthrough to metamethod - } - else if (ttisnil(tm = luaT_gettmbyobj(L, t, TM_NEWINDEX))) - luaG_indexerror(L, t, key); - - if (ttisfunction(tm)) - { - callTM(L, tm, t, key, val); - return; - } - // else repeat with `tm' - setobj(L, &temp, tm); // avoid pointing inside table (may rehash) - t = &temp; - } - luaG_runerror(L, "'__newindex' chain too long; possible loop"); -} - -static int call_binTM(lua_State* L, const TValue* p1, const TValue* p2, StkId res, TMS event) -{ - const TValue* tm = luaT_gettmbyobj(L, p1, event); // try first operand - if (ttisnil(tm)) - tm = luaT_gettmbyobj(L, p2, event); // try second operand - if (ttisnil(tm)) - return 0; - callTMres(L, res, tm, p1, p2); - return 1; -} - -static const TValue* get_compTM(lua_State* L, Table* mt1, Table* mt2, TMS event) -{ - const TValue* tm1 = fasttm(L, mt1, event); - const TValue* tm2; - if (tm1 == NULL) - return NULL; // no metamethod - if (mt1 == mt2) - return tm1; // same metatables => same metamethods - tm2 = fasttm(L, mt2, event); - if (tm2 == NULL) - return NULL; // no metamethod - if (luaO_rawequalObj(tm1, tm2)) // same metamethods? - return tm1; - return NULL; -} - -static int call_orderTM(lua_State* L, const TValue* p1, const TValue* p2, TMS event, bool error = false) -{ - const TValue* tm1 = luaT_gettmbyobj(L, p1, event); - const TValue* tm2; - if (ttisnil(tm1)) - { - if (error) - luaG_ordererror(L, p1, p2, event); - return -1; // no metamethod? - } - tm2 = luaT_gettmbyobj(L, p2, event); - if (!luaO_rawequalObj(tm1, tm2)) // different metamethods? - { - if (error) - luaG_ordererror(L, p1, p2, event); - return -1; - } - callTMres(L, L->top, tm1, p1, p2); - return !l_isfalse(L->top); -} - -int luaV_strcmp(const TString* ls, const TString* rs) -{ - if (ls == rs) - return 0; - - const char* l = getstr(ls); - const char* r = getstr(rs); - - // always safe to read one character because even empty strings are nul terminated - if (*l != *r) - return uint8_t(*l) - uint8_t(*r); - - size_t ll = ls->len; - size_t lr = rs->len; - size_t lmin = ll < lr ? ll : lr; - - int res = memcmp(l, r, lmin); - if (res != 0) - return res; - - return ll == lr ? 0 : ll < lr ? -1 : 1; -} - -int luaV_lessthan(lua_State* L, const TValue* l, const TValue* r) -{ - if (LUAU_UNLIKELY(ttype(l) != ttype(r))) - luaG_ordererror(L, l, r, TM_LT); - else if (LUAU_LIKELY(ttisnumber(l))) - return luai_numlt(nvalue(l), nvalue(r)); - else if (ttisstring(l)) - return luaV_strcmp(tsvalue(l), tsvalue(r)) < 0; - else - return call_orderTM(L, l, r, TM_LT, /* error= */ true); -} - -int luaV_lessequal(lua_State* L, const TValue* l, const TValue* r) -{ - int res; - if (ttype(l) != ttype(r)) - luaG_ordererror(L, l, r, TM_LE); - else if (ttisnumber(l)) - return luai_numle(nvalue(l), nvalue(r)); - else if (ttisstring(l)) - return luaV_strcmp(tsvalue(l), tsvalue(r)) <= 0; - else if ((res = call_orderTM(L, l, r, TM_LE)) != -1) // first try `le' - return res; - else if ((res = call_orderTM(L, r, l, TM_LT)) == -1) // error if not `lt' - luaG_ordererror(L, l, r, TM_LE); - return !res; -} - -int luaV_equalval(lua_State* L, const TValue* t1, const TValue* t2) -{ - const TValue* tm; - LUAU_ASSERT(ttype(t1) == ttype(t2)); - switch (ttype(t1)) - { - case LUA_TNIL: - return 1; - case LUA_TNUMBER: - return luai_numeq(nvalue(t1), nvalue(t2)); - case LUA_TVECTOR: - return luai_veceq(vvalue(t1), vvalue(t2)); - case LUA_TBOOLEAN: - return bvalue(t1) == bvalue(t2); // true must be 1 !! - case LUA_TLIGHTUSERDATA: - return pvalue(t1) == pvalue(t2) && (!FFlag::TaggedLuData || lightuserdatatag(t1) == lightuserdatatag(t2)); - case LUA_TUSERDATA: - { - tm = get_compTM(L, uvalue(t1)->metatable, uvalue(t2)->metatable, TM_EQ); - if (!tm) - return uvalue(t1) == uvalue(t2); - break; // will try TM - } - case LUA_TTABLE: - { - tm = get_compTM(L, hvalue(t1)->metatable, hvalue(t2)->metatable, TM_EQ); - if (!tm) - return hvalue(t1) == hvalue(t2); - break; // will try TM - } - default: - return gcvalue(t1) == gcvalue(t2); - } - callTMres(L, L->top, tm, t1, t2); // call TM - return !l_isfalse(L->top); -} - -void luaV_concat(lua_State* L, int total, int last) -{ - do - { - StkId top = L->base + last + 1; - int n = 2; // number of elements handled in this pass (at least 2) - if (!(ttisstring(top - 2) || ttisnumber(top - 2)) || !tostring(L, top - 1)) - { - if (!call_binTM(L, top - 2, top - 1, top - 2, TM_CONCAT)) - luaG_concaterror(L, top - 2, top - 1); - } - else if (tsvalue(top - 1)->len == 0) // second op is empty? - (void)tostring(L, top - 2); // result is first op (as string) - else - { - // at least two string values; get as many as possible - size_t tl = tsvalue(top - 1)->len; - char* buffer; - int i; - // collect total length - for (n = 1; n < total && tostring(L, top - n - 1); n++) - { - size_t l = tsvalue(top - n - 1)->len; - if (l > MAXSSIZE - tl) - luaG_runerror(L, "string length overflow"); - tl += l; - } - - char buf[LUA_BUFFERSIZE]; - TString* ts = nullptr; - - if (tl < LUA_BUFFERSIZE) - { - buffer = buf; - } - else - { - ts = luaS_bufstart(L, tl); - buffer = ts->data; - } - - tl = 0; - for (i = n; i > 0; i--) - { // concat all strings - size_t l = tsvalue(top - i)->len; - memcpy(buffer + tl, svalue(top - i), l); - tl += l; - } - - if (tl < LUA_BUFFERSIZE) - { - setsvalue(L, top - n, luaS_newlstr(L, buffer, tl)); - } - else - { - setsvalue(L, top - n, luaS_buffinish(L, ts)); - } - } - total -= n - 1; // got `n' strings to create 1 new - last -= n - 1; - } while (total > 1); // repeat until only 1 result left -} - -void luaV_doarith(lua_State* L, StkId ra, const TValue* rb, const TValue* rc, TMS op) -{ - TValue tempb, tempc; - const TValue *b, *c; - if ((b = luaV_tonumber(rb, &tempb)) != NULL && (c = luaV_tonumber(rc, &tempc)) != NULL) - { - double nb = nvalue(b), nc = nvalue(c); - switch (op) - { - case TM_ADD: - setnvalue(ra, luai_numadd(nb, nc)); - break; - case TM_SUB: - setnvalue(ra, luai_numsub(nb, nc)); - break; - case TM_MUL: - setnvalue(ra, luai_nummul(nb, nc)); - break; - case TM_DIV: - setnvalue(ra, luai_numdiv(nb, nc)); - break; - case TM_IDIV: - setnvalue(ra, luai_numidiv(nb, nc)); - break; - case TM_MOD: - setnvalue(ra, luai_nummod(nb, nc)); - break; - case TM_POW: - setnvalue(ra, luai_numpow(nb, nc)); - break; - case TM_UNM: - setnvalue(ra, luai_numunm(nb)); - break; - default: - LUAU_ASSERT(0); - break; - } - } - else - { - // vector operations that we support: - // v+v v-v -v (add/sub/neg) - // v*v s*v v*s (mul) - // v/v s/v v/s (div) - // v//v s//v v//s (floor div) - - const float* vb = luaV_tovector(rb); - const float* vc = luaV_tovector(rc); - - if (vb && vc) - { - switch (op) - { - case TM_ADD: - setvvalue(ra, vb[0] + vc[0], vb[1] + vc[1], vb[2] + vc[2], vb[3] + vc[3]); - return; - case TM_SUB: - setvvalue(ra, vb[0] - vc[0], vb[1] - vc[1], vb[2] - vc[2], vb[3] - vc[3]); - return; - case TM_MUL: - setvvalue(ra, vb[0] * vc[0], vb[1] * vc[1], vb[2] * vc[2], vb[3] * vc[3]); - return; - case TM_DIV: - setvvalue(ra, vb[0] / vc[0], vb[1] / vc[1], vb[2] / vc[2], vb[3] / vc[3]); - return; - case TM_IDIV: - setvvalue(ra, float(luai_numidiv(vb[0], vc[0])), float(luai_numidiv(vb[1], vc[1])), float(luai_numidiv(vb[2], vc[2])), - float(luai_numidiv(vb[3], vc[3]))); - return; - case TM_UNM: - setvvalue(ra, -vb[0], -vb[1], -vb[2], -vb[3]); - return; - default: - break; - } - } - else if (vb) - { - c = luaV_tonumber(rc, &tempc); - - if (c) - { - float nc = cast_to(float, nvalue(c)); - - switch (op) - { - case TM_MUL: - setvvalue(ra, vb[0] * nc, vb[1] * nc, vb[2] * nc, vb[3] * nc); - return; - case TM_DIV: - setvvalue(ra, vb[0] / nc, vb[1] / nc, vb[2] / nc, vb[3] / nc); - return; - case TM_IDIV: - setvvalue(ra, float(luai_numidiv(vb[0], nc)), float(luai_numidiv(vb[1], nc)), float(luai_numidiv(vb[2], nc)), - float(luai_numidiv(vb[3], nc))); - return; - default: - break; - } - } - } - else if (vc) - { - b = luaV_tonumber(rb, &tempb); - - if (b) - { - float nb = cast_to(float, nvalue(b)); - - switch (op) - { - case TM_MUL: - setvvalue(ra, nb * vc[0], nb * vc[1], nb * vc[2], nb * vc[3]); - return; - case TM_DIV: - setvvalue(ra, nb / vc[0], nb / vc[1], nb / vc[2], nb / vc[3]); - return; - case TM_IDIV: - setvvalue(ra, float(luai_numidiv(nb, vc[0])), float(luai_numidiv(nb, vc[1])), float(luai_numidiv(nb, vc[2])), - float(luai_numidiv(nb, vc[3]))); - return; - default: - break; - } - } - } - - if (!call_binTM(L, rb, rc, ra, op)) - { - luaG_aritherror(L, rb, rc, op); - } - } -} - -void luaV_dolen(lua_State* L, StkId ra, const TValue* rb) -{ - const TValue* tm = NULL; - switch (ttype(rb)) - { - case LUA_TTABLE: - { - Table* h = hvalue(rb); - if ((tm = fasttm(L, h->metatable, TM_LEN)) == NULL) - { - setnvalue(ra, cast_num(luaH_getn(h))); - return; - } - break; - } - case LUA_TSTRING: - { - TString* ts = tsvalue(rb); - setnvalue(ra, cast_num(ts->len)); - return; - } - default: - tm = luaT_gettmbyobj(L, rb, TM_LEN); - } - - if (ttisnil(tm)) - luaG_typeerror(L, rb, "get length of"); - - StkId res = callTMres(L, ra, tm, rb, luaO_nilobject); - if (!ttisnumber(res)) - luaG_runerror(L, "'__len' must return a number"); // note, we can't access rb since stack may have been reallocated -} - -LUAU_NOINLINE void luaV_prepareFORN(lua_State* L, StkId plimit, StkId pstep, StkId pinit) -{ - if (!ttisnumber(pinit) && !luaV_tonumber(pinit, pinit)) - luaG_forerror(L, pinit, "initial value"); - if (!ttisnumber(plimit) && !luaV_tonumber(plimit, plimit)) - luaG_forerror(L, plimit, "limit"); - if (!ttisnumber(pstep) && !luaV_tonumber(pstep, pstep)) - luaG_forerror(L, pstep, "step"); -} - -// calls a C function f with no yielding support; optionally save one resulting value to the res register -// the function and arguments have to already be pushed to L->top -LUAU_NOINLINE void luaV_callTM(lua_State* L, int nparams, int res) -{ - ++L->nCcalls; - - if (L->nCcalls >= LUAI_MAXCCALLS) - luaD_checkCstack(L); - - luaD_checkstack(L, LUA_MINSTACK); - - StkId top = L->top; - StkId fun = top - nparams - 1; - - CallInfo* ci = incr_ci(L); - ci->func = fun; - ci->base = fun + 1; - ci->top = top + LUA_MINSTACK; - ci->savedpc = NULL; - ci->flags = 0; - ci->nresults = (res >= 0); - LUAU_ASSERT(ci->top <= L->stack_last); - - LUAU_ASSERT(ttisfunction(ci->func)); - LUAU_ASSERT(clvalue(ci->func)->isC); - - L->base = fun + 1; - LUAU_ASSERT(L->top == L->base + nparams); - - lua_CFunction func = clvalue(fun)->c.f; - int n = func(L); - LUAU_ASSERT(n >= 0); // yields should have been blocked by nCcalls - - // ci is our callinfo, cip is our parent - // note that we read L->ci again since it may have been reallocated by the call - CallInfo* cip = L->ci - 1; - - // copy return value into parent stack - if (res >= 0) - { - if (n > 0) - { - setobj2s(L, &cip->base[res], L->top - n); - } - else - { - setnilvalue(&cip->base[res]); - } - } - - L->ci = cip; - L->base = cip->base; - L->top = cip->top; - - --L->nCcalls; -} - -LUAU_NOINLINE void luaV_tryfuncTM(lua_State* L, StkId func) -{ - const TValue* tm = luaT_gettmbyobj(L, func, TM_CALL); - if (!ttisfunction(tm)) - luaG_typeerror(L, func, "call"); - for (StkId p = L->top; p > func; p--) // open space for metamethod - setobj2s(L, p, p - 1); - L->top++; // stack space pre-allocated by the caller - setobj2s(L, func, tm); // tag method is the new function to be called -} diff --git a/src/zigluau/lib.zig b/src/zigluau/lib.zig index d810b83..bf9894c 100644 --- a/src/zigluau/lib.zig +++ b/src/zigluau/lib.zig @@ -4,10 +4,9 @@ const std = @import("std"); const c = @cImport({ - @cInclude("lua/lua.h"); - @cInclude("lua/lualib.h"); - - @cInclude("lua/luacode.h"); + @cInclude("lua.h"); + @cInclude("lualib.h"); + @cInclude("luacode.h"); }); /// This function is defined in luau.cpp and must be called to define the assertion printer diff --git a/src/zigluau/tests.zig b/src/zigluau/tests.zig index 5e113f3..6d2738f 100644 --- a/src/zigluau/tests.zig +++ b/src/zigluau/tests.zig @@ -1,6 +1,6 @@ const std = @import("std"); const testing = std.testing; -const ziglua = @import("lib.zig"); +const ziglua = @import("ziglua"); const AllocFn = ziglua.AllocFn; const Buffer = ziglua.Buffer; From 41a110981cf016465f72208c3f1732fd4c92a694 Mon Sep 17 00:00:00 2001 From: Nathan Craddock Date: Tue, 9 Jan 2024 22:21:44 -0700 Subject: [PATCH 4/5] Replace Lua 5.1.5 with patched dependency --- build.zig.zon | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) diff --git a/build.zig.zon b/build.zig.zon index 431b843..5a6e7e4 100644 --- a/build.zig.zon +++ b/build.zig.zon @@ -4,9 +4,14 @@ .paths = .{""}, .dependencies = .{ + + // We do not use the lua.org version of Lua 5.1.5 because there is a known security issue + // (CVE-2014-5461) that will not be backported. This is the most resonable solution at + // the moment. Maybe there will be a way to apply a patch with the build system in the + // future. .lua51 = .{ - .url = "https://www.lua.org/ftp/lua-5.1.5.tar.gz", - .hash = "1220089572fb380fb4679b16421fc53851a8226bcebc9ce44463a0f4ada5c9bd737f", + .url = "https://github.com/natecraddock/lua/archive/refs/tags/5.1.5-1.tar.gz", + .hash = "12203fe1feebb81635f8df5a5a7242733e441fe3f3043989c8e6b4d6720e96988813", }, .lua52 = .{ From 76255246a263422f46ac37ed2d4aa0e2cabf8c97 Mon Sep 17 00:00:00 2001 From: Nathan Craddock Date: Tue, 9 Jan 2024 22:47:51 -0700 Subject: [PATCH 5/5] docs: update dependency documentation --- docs.md | 53 ----------------------------------------------------- readme.md | 44 +++++++++++++++++++++++--------------------- 2 files changed, 23 insertions(+), 74 deletions(-) diff --git a/docs.md b/docs.md index eb58a4d..a94d96a 100644 --- a/docs.md +++ b/docs.md @@ -10,59 +10,6 @@ This documentation provides Documentation on each individual function is found in the source code. -## Build Documentation - -Example `build.zig.zon` file. The hash in the url is the hash of the commit you are using. - -``` -.{ - .name = "myproject", - .version = "0.0.1", - .dependencies = .{ - .ziglua = .{ - .url = "https://github.com/natecraddock/ziglua/archive/ab111adb06d2d4dc187ee9e1e352617ca8659155.tar.gz", - .hash = "12206cf9e90462ee6e14f593ea6e0802b9fe434429ba10992a1451e32900f741005c", - }, - } -} -``` - -Example usage in `build.zig`. - -```zig -pub fn build(b: *std.Build) void { - // ... snip ... - - const ziglua = b.dependency("ziglua", .{ - .target = target, - .optimize = optimize, - }); - - // ... snip ... - - // add the ziglua module and lua artifact - exe.addModule("ziglua", ziglua.module("ziglua")); - exe.linkLibrary(ziglua.artifact("lua")); - -} -``` - -There are currently two additional options that can be passed to `b.dependency()`: - -* `.version`: Set the Lua version to build and embed. Defaults to `.lua_54`. Possible values are `.lua_51`, `.lua_52`, `.lua_53`, and `.lua_54`. -* `.shared`: Defaults to `false` for embedding in a Zig program. Set to `true` to dynamically link the Lua source code (useful for creating shared modules). - -For example, here is a `b.dependency()` call that and links against a shared Lua 5.2 library: - -```zig -const ziglua = b.dependency("ziglua", .{ - .target = target, - .optimize = optimize, - .version = .lua52, - .shared = true, -}); -``` - ## Moving from the C API to Zig While efforts have been made to keep the Ziglua API similar to the C API, many changes have been made including: diff --git a/readme.md b/readme.md index b605d06..ca1baaa 100644 --- a/readme.md +++ b/readme.md @@ -37,27 +37,12 @@ In a nutshell, Ziglua is a simple wrapper around the C API you would get by usin While there are some helper functions added to complement the C API, Ziglua aims to remain low-level. This allows full access to the Lua API through a layer of Zig's improvements over C. ## Integrating Ziglua in your project -First create a `build.zig.zon` file in your Zig project if you do not already have one. Add a ziglua dependency. -``` -.{ - .name = "myproject", - .version = "0.0.1", - .dependencies = .{ - .ziglua = .{ - // Use a tagged release of Ziglua tracking a stable Zig release - .url = "https://github.com/natecraddock/ziglua/archive/refs/tags/0.2.0.tar.gz", - - // Or a url with a hash for a specific Ziglua commit - .url = "https://github.com/natecraddock/ziglua/archive/ab111adb06d2d4dc187ee9e1e352617ca8659155.tar.gz", - }, - } -} -``` +Find the archive url of the Ziglua version you want to integrate with your project. For example, the url for the commit **41a110981cf016465f72208c3f1732fd4c92a694** is https://github.com/natecraddock/ziglua/archive/41a110981cf016465f72208c3f1732fd4c92a694.tar.gz. -When you run `zig build` it will instruct you to add a `.hash` field to this file. +Then run `zig fetch --save `. This will add the dependency to your `build.zig.zon` file. -In your `build.zig` file create and use the dependency +Then in your `build.zig` file you can use the dependency. ```zig pub fn build(b: *std.Build) void { @@ -71,13 +56,30 @@ pub fn build(b: *std.Build) void { // ... snip ... // add the ziglua module and lua artifact - exe.addModule("ziglua", ziglua.module("ziglua")); - exe.linkLibrary(ziglua.artifact("lua")); + exe.root_module.addImport("ziglua", ziglua.module("ziglua")); } ``` -This will compile the Lua C sources and link with your project. The `ziglua` module will now be available in your code. Here is a simple example that pushes and inspects an integer on the Lua stack: +This will compile the Lua C sources and link with your project. + +There are currently two additional options that can be passed to `b.dependency()`: + +* `.version`: Set the Lua version to build and embed. Defaults to `.lua54`. Possible values are `.lua51`, `.lua52`, `.lua53`, `.lua54`, and `luau`. +* `.shared`: Defaults to `false` for embedding in a Zig program. Set to `true` to dynamically link the Lua source code (useful for creating shared modules). + +For example, here is a `b.dependency()` call that and links against a shared Lua 5.2 library: + +```zig +const ziglua = b.dependency("ziglua", .{ + .target = target, + .optimize = optimize, + .version = .lua52, + .shared = true, +}); +`````` + +The `ziglua` module will now be available in your code. Here is a simple example that pushes and inspects an integer on the Lua stack: ```zig const std = @import("std");