aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorGravatar Lance Borden 2025-08-19 14:53:18 -0400
committerGravatar GitHub 2025-08-19 14:53:18 -0400
commit810c1f8f943e9683e4d2efedba98dca0010af202 (patch)
tree2507acdf5cad8bc65e32c037bdf436f1500c1b74
parentv0.3.2 (diff)
parentRevert to old hashmap: fixed gitmodule index (diff)
Merge pull request #6 from ItsMeForLua/my-feature-branch
Added Lua compat53: fixed the non-interactive mode: added .gitmodules to build.yml
-rw-r--r--.github/workflows/build.yml5
-rw-r--r--.gitignore4
-rw-r--r--.gitmodules3
-rwxr-xr-xinstall.sh3
-rw-r--r--lib/.gitkeep0
m---------lib/compat530
-rw-r--r--premake5.lua18
-rw-r--r--src/lush.c76
-rw-r--r--test/compat_test.lua60
9 files changed, 131 insertions, 38 deletions
diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml
index a05697e..36cee10 100644
--- a/.github/workflows/build.yml
+++ b/.github/workflows/build.yml
@@ -15,7 +15,10 @@ jobs:
steps:
- name: Checkout code
uses: actions/checkout@v4
-
+
+ - name: Initialize submodules
+ run: git submodule update --init --recursive
+
- name: Set up dependencies
run: |
sudo apt-get update
diff --git a/.gitignore b/.gitignore
index a861fad..f5e685f 100644
--- a/.gitignore
+++ b/.gitignore
@@ -1,5 +1,9 @@
Makefile
*.make
+*.log
bin
obj
.cache
+.vscode/
+.DS_Store
+Thumbs.dbjenkins_home/
diff --git a/.gitmodules b/.gitmodules
new file mode 100644
index 0000000..03c2dcd
--- /dev/null
+++ b/.gitmodules
@@ -0,0 +1,3 @@
+[submodule "lib/compat53"]
+ path = lib/compat53
+ url = https://github.com/lunarmodules/lua-compat-5.3.git
diff --git a/install.sh b/install.sh
index ebdbaeb..405cf6e 100755
--- a/install.sh
+++ b/install.sh
@@ -1,5 +1,8 @@
#!/bin/sh
+echo "Initializing and updating submodules..."
+git submodule update --init --recursive
+
# Function to install packages using apt (Debian/Ubuntu)
install_with_apt() {
sudo apt-get update
diff --git a/lib/.gitkeep b/lib/.gitkeep
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/lib/.gitkeep
diff --git a/lib/compat53 b/lib/compat53
new file mode 160000
+Subproject dfd83b4930c8b85fd39d208523f7293cf469b20
diff --git a/premake5.lua b/premake5.lua
index 037cfca..1043c07 100644
--- a/premake5.lua
+++ b/premake5.lua
@@ -13,12 +13,17 @@ local lua_lib_path = "/usr/lib"
if os.findlib("lua5.4") then
lua_inc_path = "/usr/include/lua5.4"
lua_lib_path = "/usr/lib/5.4"
- links({ "lua5.4" })
+-- Readline for better interactive support, dl for dynamic loading, and m for the math library dependency
+ links({ "lua5.4", "readline", "dl", "m" })
else
links({ "lua" })
end
-includedirs({ lua_inc_path, "lib/hashmap" })
+includedirs({
+ lua_inc_path,
+ "lib/hashmap",
+ "lib/compat53/c-api"
+})
libdirs({ lua_lib_path })
files({
@@ -26,8 +31,15 @@ files({
"src/**.c",
"lib/hashmap/**.h",
"lib/hashmap/**.c",
+ "lib/compat53/c-api/compat-5.3.h",
+ "lib/compat53/c-api/compat-5.3.c",
+ "lib/compat53/lbitlib.c",
+ "lib/compat53/liolib.c",
+ "lib/compat53/lstrlib.c",
+ "lib/compat53/ltablib.c",
+ "lib/compat53/lutf8lib.c"
})
-defines({ 'LUSH_VERSION="0.3.2"' })
+defines({ 'LUSH_VERSION="0.3.2"', 'COMPAT53_PREFIX=""', 'LUA_COMPAT_BITLIB' })
filter("configurations:Debug")
defines({ "DEBUG" })
diff --git a/src/lush.c b/src/lush.c
index 1c42139..b512a70 100644
--- a/src/lush.c
+++ b/src/lush.c
@@ -21,6 +21,7 @@ IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
#include "lua.h"
#include "lua_api.h"
#include "lualib.h"
+#include "compat-5.3.h"
#include <asm-generic/ioctls.h>
#include <bits/time.h>
#include <ctype.h>
@@ -42,6 +43,10 @@ IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
#include <time.h>
#include <unistd.h>
+// Forward declare the open functions for the compat C modules we need to preload
+int luaopen_bit32 (lua_State *L);
+int luaopen_utf8 (lua_State *L);
+
#define BUFFER_SIZE 1024
#define MAX_GLOB 512
@@ -1485,13 +1490,26 @@ int main(int argc, char *argv[]) {
return 0;
}
+ // init lua state
+ lua_State *L = luaL_newstate();
+ if (!L) {
+ fprintf(stderr, "Failed to create Lua state\n");
+ return -1; // or handle appropriately
+ }
+ luaL_openlibs(L);
+
+ // --- Load compat modules and make them global ---
+ luaL_requiref(L, "bit32", luaopen_bit32, 1);
+ lua_pop(L, 1); // luaL_requiref leaves the module on the stack
+
+ luaL_requiref(L, "utf8", luaopen_utf8, 1);
+ lua_pop(L, 1);
+ // --- End pre-loading ---
+ lua_register_api(L);
+ lua_run_init(L);
+
// check if being run in command string mode
if (argc > 2 && strcmp(argv[1], "-c") == 0) {
- // init Lua state
- lua_State *L = luaL_newstate();
- luaL_openlibs(L);
- lua_register_api(L);
- lua_run_init(L);
// execute the command provided
char *command = argv[2];
@@ -1521,36 +1539,26 @@ int main(int argc, char *argv[]) {
return 0;
}
- // init lua state
- lua_State *L = luaL_newstate();
- luaL_openlibs(L);
- lua_register_api(L);
- lua_run_init(L);
+ // This is the corrected logic for running a script file non-interactively.
+ if (argc > 1) {
+ char *ext = strrchr(argv[1], '.');
+ if (ext && strcmp(ext, ".lua") == 0) {
+ const char *script_name = argv[1];
+ // The arguments for the script start at argv[2].
+ // We create a pointer to that part of the array.
+ char **script_args = (argc > 2) ? &argv[2] : NULL;
- // if a lua function is passed on load run non-interactively
- if (argc > 1) {
- char *ext = strrchr(argv[1], '.');
- if (ext) {
- ext++;
- if (strcmp(ext, "lua") == 0) {
- int status = 0;
- argv++;
- char ***args = lush_split_args(argv, &status);
-
- if (status == -1) {
- fprintf(stderr, "lush: Expected end of quoted string\n");
- } else if (lush_run(L, args, status) != 0) {
- exit(1);
- }
+ // Call the script loader directly with the script and its arguments.
+ if (lua_load_script(L, script_name, script_args) != 0) {
+ exit(1); // Exit if the script had an error
+ }
- for (int i = 0; args[i]; i++) {
- free(args[i]);
- }
- free(args);
- return 0;
- }
- }
- }
+ lua_close(L); // Clean up and exit
+ return 0;
+ }
+ }
+
+ // --- Interactive Shell Mode ---
// eat ^C in main
struct sigaction sa_int;
@@ -1617,4 +1625,4 @@ int main(int argc, char *argv[]) {
if (alt_shell != NULL)
free(alt_shell);
return 0;
-}
+} \ No newline at end of file
diff --git a/test/compat_test.lua b/test/compat_test.lua
new file mode 100644
index 0000000..bd7ef90
--- /dev/null
+++ b/test/compat_test.lua
@@ -0,0 +1,60 @@
+-- test/compat_test.lua
+-- A small test suite for the lua-compat-5.3 layer.
+-- Can be run in two ways:
+-- 1. ./lush test/compat_test.lua (runs all tests)
+-- 2. ./lush test/compat_test.lua test_table_unpack (runs a single test)
+
+local tests = {}
+
+function tests.test_table_unpack()
+ print("--- Running test: table.unpack ---")
+ local my_table = { "a", "b", "c" }
+ -- The compat layer provides table.unpack for Lua 5.1.
+ local x, y, z = table.unpack(my_table)
+ assert(x == "a", "unpack failed for first element")
+ assert(y == "b", "unpack failed for second element")
+ assert(z == "c", "unpack failed for third element")
+ print("...SUCCESS!")
+end
+
+function tests.test_math_log_base()
+ print("--- Running test: math.log with base ---")
+ -- Lua 5.1's math.log only takes one argument. The compat layer adds the base.
+ local result = math.log(100, 10)
+ -- Use a small epsilon for floating point comparison
+ assert(math.abs(result - 2) < 1e-9, "math.log(100, 10) should be 2")
+ print("...SUCCESS!")
+end
+
+function tests.test_string_rep_separator()
+ print("--- Running test: string.rep with separator ---")
+ -- Lua 5.1's string.rep doesn't have the separator argument.
+ local result = string.rep("a", 3, "-")
+ assert(result == "a-a-a", "string.rep with separator failed, got: " .. tostring(result))
+ print("...SUCCESS!")
+end
+
+
+-- NOTE: The lush C host provides arguments in a global table named 'args', not 'arg'.
+local test_to_run = args and args[1]
+
+if test_to_run and tests[test_to_run] then
+ -- If a valid test name is provided, run only that test.
+ local success, err = pcall(tests[test_to_run])
+ if not success then
+ print("...FAILURE: " .. err)
+ end
+elseif test_to_run then
+ -- If an invalid name is provided, show an error.
+ print("ERROR: Test function '" .. test_to_run .. "' not found.")
+else
+ -- If no specific test is requested, run all of them.
+ print("--- Running all compatibility tests ---")
+ for name, func in pairs(tests) do
+ local success, err = pcall(func)
+ if not success then
+ print("...FAILURE on test '" .. name .. "': " .. err)
+ end
+ end
+ print("--- All tests complete ---")
+end