-- [ʞ] tools/makeshim.lua
--  ~ lexi hale <lexi@hale.su>
--  🄯 AGPLv3
--  ? this program creates a C source file embedding
--    cortav, for the purposes of standalone deployment
--    without a lua interpreter, or for the purposes of
--    giving cortav extra privileges

local includes = [[
#include <lua.h>
#include <lauxlib.h>
#include <stdio.h>
#include <stddef.h>
extern int luaL_openlibs(lua_State* l);
]]


local main = [[
int main(int argc, char** argv) {
	lua_State* l = luaL_newstate();
	luaL_openlibs(l);

	// pass arguments thru to lua
	lua_newtable(l);
	for(size_t i = 0; i < argc; ++i) {
		lua_pushstring(l,argv[i]);
		lua_rawseti(l, -2, i);
	}
	lua_setglobal(l, "arg");

	// load and run our payload
	int e = luaL_loadbufferx(l, ct_bytecode, sizeof(ct_bytecode), "cortav", "b");
	if (e != LUA_OK) {
		printf("some kind of error idk fam\n");
		return -1;
	}

	lua_call(l, 0, 0);

	// normal termination is by the os.exit() call
	return -1;
}
]]

local function setfile(i, dflt, mode)
	if arg[i] and arg[i] ~= '' then
		local fn = io.open(arg[i], mode)
		if fn then
			return fn
		end
		io.stderr:write('(' .. arg[0]..' fatal) cannot open file '..arg[i])
	end
	return dflt
end

local src = setfile(1, io.stdin, "rb")
local dest = setfile(2, io.stdout, "w")

local cstr = {}
local strtpl = 'static char ct_bytecode [%u] = {%s};'
local lines = {includes}

local bytes = {}

local bn = 1
local len = 0
while true do
	local byte = src:read(1)
	if not byte then break end
	local str = tostring(byte:byte(1))..','
	-- make sure our source file is parseable by
	-- a compliant C compiler
	len = len + string.len(str)
	if len >= 4096 then
		len = 0
		bytes[bn]='\n'
		bn = bn + 1
	end
	bytes[bn] = str
	bn = bn + 1
end

table.insert(lines, strtpl:format(#bytes, table.concat(bytes)))
table.insert(lines, main)

dest:write(table.concat(lines, '\n'))