some stuff
This commit is contained in:
2
Makefile
2
Makefile
@@ -10,7 +10,7 @@ LDARGS_LUA ?= $(shell pkg-config --libs lua5.4)
|
||||
CCARGS += $(CCARGS_LUA)
|
||||
LDARGS += $(LDARGS_LUA)
|
||||
|
||||
MKLUA_FLAGS += --path "src/main/?.lua;src/main/?/init.lua;;"
|
||||
MKLUA_FLAGS += --path "src/?.lua;src/?/init.lua;;"
|
||||
MKLUA_FLAGS += --main
|
||||
|
||||
MKLUA_ENTRIES += mklua
|
||||
|
||||
189
src/mklua.lua
189
src/mklua.lua
@@ -13,7 +13,10 @@ Flags:
|
||||
--libs - outputs a list of native libraries the entries depend on
|
||||
--makefile - generates a makefile
|
||||
|
||||
--main - includes a C main function, which calls the export of the first entry
|
||||
--entry - generates a mklua_entry function, which takes an initialized lua state
|
||||
and executes the first entry
|
||||
--main - generates a main function, which creates a lua state and runs the entry
|
||||
implies `--entry`
|
||||
--output=<file> (-o <file>) - the file to write to
|
||||
--debug (-g) - emits debugging data in the lua bytecode
|
||||
|
||||
@@ -21,47 +24,57 @@ Flags:
|
||||
--cpath - specifies a c path to search
|
||||
]];
|
||||
|
||||
local main_format = [[
|
||||
#ifndef MKLUA_MAIN_NAME
|
||||
#define MKLUA_MAIN_NAME main
|
||||
local entry_format = [[
|
||||
#ifndef MKLUA_ENTRY_NAME
|
||||
#define MKLUA_ENTRY_NAME mklua_entry
|
||||
#endif
|
||||
|
||||
%s
|
||||
|
||||
int MKLUA_MAIN_NAME(int argc, const char **argv) {
|
||||
lua_State *ctx = luaL_newstate();
|
||||
luaL_openlibs(ctx);
|
||||
MKLUA_EXPORT int MKLUA_ENTRY_NAME(lua_State *ctx, int argc, const char **argv) {
|
||||
int larg, lerrcb, i, ok;
|
||||
lua_checkstack(ctx, argc + 16);
|
||||
|
||||
/* Emit other requiref-s */
|
||||
%s
|
||||
|
||||
lua_createtable(ctx, argc, 0);
|
||||
int larg = lua_gettop(ctx);
|
||||
larg = lua_gettop(ctx);
|
||||
|
||||
lua_pushvalue(ctx, larg);
|
||||
lua_setglobal(ctx, "arg");
|
||||
|
||||
luaL_requiref(ctx, "__err_handle", %s, false);
|
||||
int lerrcb = lua_gettop(ctx);
|
||||
luaL_requiref(ctx, "__err_handle", %s, 0);
|
||||
lerrcb = lua_gettop(ctx);
|
||||
|
||||
luaL_requiref(ctx, %q, %s, false);
|
||||
luaL_requiref(ctx, %q, %s, 0);
|
||||
|
||||
for (int i = 1; i < argc; i++) {
|
||||
for (i = 1; i < argc; i++) {
|
||||
lua_pushstring(ctx, argv[i]);
|
||||
lua_pushvalue(ctx, -1);
|
||||
lua_seti(ctx, larg, i);
|
||||
}
|
||||
|
||||
if (lua_pcall(ctx, argc - 1, 0, lerrcb)) {
|
||||
fprintf(stderr, "lua error: %%s\n", lua_tostring(ctx, -1));
|
||||
lua_close(ctx);
|
||||
return 1;
|
||||
}
|
||||
else {
|
||||
lua_close(ctx);
|
||||
return 0;
|
||||
}
|
||||
ok = !lua_pcall(ctx, argc - 1, 0, lerrcb);
|
||||
if (!ok) fprintf(stderr, "lua error: %%s\n", lua_tostring(ctx, -1));
|
||||
|
||||
return ok;
|
||||
}
|
||||
]];
|
||||
|
||||
local main_format = [[
|
||||
#ifndef MKLUA_MAIN_NAME
|
||||
#define MKLUA_MAIN_NAME main
|
||||
#endif
|
||||
|
||||
MKLUA_EXPORT int MKLUA_MAIN_NAME(int argc, const char **argv) {
|
||||
int ok;
|
||||
lua_State *ctx = luaL_newstate();
|
||||
luaL_openlibs(ctx);
|
||||
|
||||
ok = MKLUA_ENTRY_NAME(ctx, argc, argv);
|
||||
lua_close(ctx);
|
||||
return ok ? 0 : 1;
|
||||
}
|
||||
]];
|
||||
|
||||
@@ -164,10 +177,10 @@ local function emit_lua(name, filename, deps, func)
|
||||
local lines = {};
|
||||
local bc = string.dump(func or assert(loadfile(filename)), not debug);
|
||||
|
||||
table.insert(lines, "static int " .. funcname .. "(lua_State *ctx) {\n");
|
||||
table.insert(lines, "MKLUA_INTERNAL int " .. funcname .. "(lua_State *ctx) {\n");
|
||||
|
||||
for i = 1, #deps do
|
||||
table.insert(lines, ("\tluaL_requiref(ctx, %q, %s, false);\n"):format(deps[i][1], deps[i][2]));
|
||||
table.insert(lines, ("\tluaL_requiref(ctx, %q, %s, 0);\n"):format(deps[i][1], deps[i][2]));
|
||||
table.insert(lines, "\tlua_pop(ctx, 1);\n");
|
||||
end
|
||||
|
||||
@@ -202,7 +215,7 @@ local function emit_luaopen(f, entry, name, path, cpath, debug, passed)
|
||||
return funcname;
|
||||
elseif type == "c" then
|
||||
local funcname = "luaopen_" .. name:gsub("[.%-]", "_");
|
||||
f:write("extern int ", funcname, "(lua_State *ctx);\n");
|
||||
f:write("MKLUA_EXPORT int ", funcname, "(lua_State *ctx);\n");
|
||||
passed[name] = funcname;
|
||||
return funcname;
|
||||
elseif is_entry then
|
||||
@@ -216,21 +229,28 @@ local function emit_luaopen(f, entry, name, path, cpath, debug, passed)
|
||||
error("entry '" .. name .. "' couldn't be resolved");
|
||||
end
|
||||
|
||||
f:write("int luaopen_", name:gsub("[.%-]", "_"), "(lua_State *ctx) {\n");
|
||||
f:write("MKLUA_EXPORT int luaopen_", name:gsub("[.%-]", "_"), "(lua_State *ctx) {\n");
|
||||
f:write("\treturn ", funcname, "(ctx);\n");
|
||||
f:write("}\n\n");
|
||||
end
|
||||
|
||||
local function gen_c(f, entries, path, cpath, g, main)
|
||||
local function gen_c(f, entries, path, cpath, g, main, entry, header)
|
||||
f:write [[/* Generated by mklua */
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <stdbool.h>
|
||||
|
||||
#include <lua.h>
|
||||
#include <lualib.h>
|
||||
#include <lauxlib.h>
|
||||
|
||||
#ifndef MKLUA_INTERNAL
|
||||
#define MKLUA_INTERNAL static
|
||||
#endif
|
||||
#ifndef MKLUA_EXPORT
|
||||
#ifdef MKLUA_HEADER
|
||||
#define MKLUA_EXPORT static
|
||||
#else
|
||||
#define MKLUA_EXPORT extern
|
||||
#endif
|
||||
#endif
|
||||
|
||||
]];
|
||||
|
||||
local passed = {};
|
||||
@@ -240,24 +260,28 @@ local function gen_c(f, entries, path, cpath, g, main)
|
||||
emit_luaopen(f, in_name, out_name, path, cpath, g, passed);
|
||||
end
|
||||
|
||||
if main then
|
||||
if entry then
|
||||
local requiref_calls = {};
|
||||
|
||||
for i = 2, #entries do
|
||||
local in_name, out_name = entries[i][1], entries[i][2];
|
||||
table.insert(requiref_calls, ("luaL_requiref(ctx, %q, %s, false);"):format(out_name, passed[out_name]))
|
||||
table.insert(requiref_calls, ("luaL_requiref(ctx, %q, %s, 0);"):format(out_name, passed[out_name]))
|
||||
end
|
||||
|
||||
local func_name, func = emit_lua("__err_handle", "<internal>", {}, function ()
|
||||
return debug.traceback;
|
||||
end);
|
||||
|
||||
f:write(main_format:format(func, table.concat(requiref_calls, "\n\t\t"), func_name, entries[1][2], passed[entries[1][2]]));
|
||||
f:write(entry_format:format(func, table.concat(requiref_calls, "\n\t\t"), func_name, entries[1][2], passed[entries[1][2]]));
|
||||
|
||||
if main then
|
||||
f:write(main_format);
|
||||
end
|
||||
end
|
||||
end
|
||||
--- @param path string
|
||||
--- @param cpath string
|
||||
local function gen_makefile(f, entries, path, cpath, g, main)
|
||||
local function gen_makefile(f, entries, path, cpath, g, main, entry, header)
|
||||
local flags = {};
|
||||
local entries_opts = {};
|
||||
for i = 1, #entries do
|
||||
@@ -295,13 +319,18 @@ local function gen_makefile(f, entries, path, cpath, g, main)
|
||||
local cpath = fix_path(cpath, package.cpath);
|
||||
|
||||
if path then
|
||||
table.insert(flags, "MKLUA_FLAGS += " .. "--path \"" .. path .. "\"");
|
||||
table.insert(flags, "MKLUA_FLAGS += --path \"" .. path .. "\"");
|
||||
end
|
||||
if cpath then
|
||||
table.insert(flags, "MKLUA_FLAGS += " .. "--cpath \"" .. cpath .. "\"");
|
||||
table.insert(flags, "MKLUA_FLAGS += --cpath \"" .. cpath .. "\"");
|
||||
end
|
||||
if main then
|
||||
table.insert(flags, "MKLUA_FLAGS += " .. "--main");
|
||||
table.insert(flags, "MKLUA_FLAGS += --main");
|
||||
elseif entry then
|
||||
table.insert(flags, "MKLUA_FLAGS += --entry");
|
||||
end
|
||||
if header then
|
||||
table.insert(flags, "MKLUA_FLAGS += --header");
|
||||
end
|
||||
|
||||
f:write(make_format:format(table.concat(flags, "\n"), table.concat(entries_opts, "\n"), table.concat(entries_opts, " ")));
|
||||
@@ -323,12 +352,21 @@ local function gen_deps(f, entries, path, cpath, g, main, only_libs)
|
||||
end
|
||||
end
|
||||
|
||||
local function open_w(path)
|
||||
if path == "-" then
|
||||
return io.stdout, function () end
|
||||
else
|
||||
local f = assert(io.open(path, "w"));
|
||||
return f, f.close;
|
||||
end
|
||||
end
|
||||
|
||||
return function (...)
|
||||
local path = package.path;
|
||||
local cpath = package.cpath;
|
||||
local main;
|
||||
local out_path;
|
||||
local mode = "c";
|
||||
local main, entry;
|
||||
local c_path, makefile_path;
|
||||
local deps, libs, header;
|
||||
local g = false;
|
||||
|
||||
local entries = {};
|
||||
@@ -356,9 +394,6 @@ return function (...)
|
||||
["debug"] = function ()
|
||||
g = true;
|
||||
end,
|
||||
["main"] = function (arg)
|
||||
main = true;
|
||||
end,
|
||||
["path"] = function (arg)
|
||||
path = assert(arg())
|
||||
:gsub("^;;", path .. ";")
|
||||
@@ -372,22 +407,52 @@ return function (...)
|
||||
:gsub(";;", ";" .. cpath .. ";");
|
||||
end,
|
||||
|
||||
main = function (arg)
|
||||
entry = true;
|
||||
main = true;
|
||||
end,
|
||||
entry = function (arg)
|
||||
entry = true;
|
||||
end,
|
||||
|
||||
output = function (arg)
|
||||
if out_path then
|
||||
if c_path then
|
||||
error "--output may be specified once";
|
||||
end
|
||||
|
||||
out_path = assert(arg());
|
||||
c_path = assert(arg());
|
||||
end,
|
||||
|
||||
makefile = function (arg)
|
||||
mode = "makefile";
|
||||
if makefile_path then
|
||||
error "--makefile may be specified once";
|
||||
end
|
||||
|
||||
makefile_path = assert(arg());
|
||||
end,
|
||||
header = function (arg)
|
||||
if header then
|
||||
error "--header may be specified once";
|
||||
end
|
||||
|
||||
header = true;
|
||||
end,
|
||||
deps = function (arg)
|
||||
mode = "deps";
|
||||
if deps then
|
||||
error "--deps may be specified once";
|
||||
elseif libs then
|
||||
error "--deps and --libs are mutually-exclusive";
|
||||
end
|
||||
|
||||
deps = true;
|
||||
end,
|
||||
libs = function (arg)
|
||||
mode = "libs";
|
||||
if libs then
|
||||
error "--libs may be specified once";
|
||||
elseif deps then
|
||||
error "--deps and --libs are mutually-exclusive";
|
||||
end
|
||||
|
||||
libs = true;
|
||||
end,
|
||||
|
||||
o = "output",
|
||||
@@ -395,24 +460,22 @@ return function (...)
|
||||
h = "help",
|
||||
} (...);
|
||||
|
||||
if #entries == 0 then
|
||||
if not c_path and not makefile_path and not libs and not deps then
|
||||
print(help_msg);
|
||||
return;
|
||||
end
|
||||
|
||||
local f = io.stdout;
|
||||
|
||||
if out_path and out_path ~= "-" then
|
||||
f = assert(io.open(out_path, "w"));
|
||||
if c_path then
|
||||
local f, close = open_w(c_path);
|
||||
gen_c(f, entries, path, cpath, g, main, entry, header);
|
||||
close(f);
|
||||
end
|
||||
|
||||
if mode == "makefile" then
|
||||
return gen_makefile(f, entries, path, cpath, g, main);
|
||||
elseif mode == "deps" then
|
||||
return gen_deps(f, entries, path, cpath, g, main, false);
|
||||
elseif mode == "libs" then
|
||||
return gen_deps(f, entries, path, cpath, g, main, true);
|
||||
else
|
||||
return gen_c(f, entries, path, cpath, g, main);
|
||||
if makefile_path then
|
||||
local f, close = open_w(c_path);
|
||||
gen_makefile(f, entries, path, cpath, g, main, header);
|
||||
close(f);
|
||||
end
|
||||
if deps or libs then
|
||||
gen_deps(io.stdout, entries, path, cpath, g, main, libs);
|
||||
end
|
||||
end
|
||||
|
||||
Reference in New Issue
Block a user