#!/usr/bin/env lua
----- lua 5.1 script to convert a lua file into a C file
-----
----- Usage: lua2c foo.lua > lfoo.c # compiled, so not portable
----- lua2c -s foo.lua > lfoo.c # source, and so portable
---------------- general utility functions -------------
function io.contents(filename)
local f, msg = io.open(filename, 'r')
if not f then return f, msg end
local s = assert(f:read '*a')
f:close()
return s
end
function os.capture(cmd, raw)
local f = assert(io.popen(cmd, 'r'))
local s = assert(f:read('*a'))
f:close()
if raw then return s end
s = string.gsub(s, '^%s+', '')
s = string.gsub(s, '%s+$', '')
s = string.gsub(s, '[\n\r]+', ' ')
return s
end
local quote_me = '[^%w%+%-%=%@%_%/]'
-- easier to complement what doesn't need quotes
local strfind = string.find
function os.quote(s)
if strfind(s, quote_me) or s == '' then
return "'" .. string.gsub(s, "'", [['"'"']]) .. "'"
else
return s
end
end
function os.runf(...) return os.execute(string.format(...)) end
-------------------------------------------------------
local lua -- program to be loaded (source or binary)
local libname
if arg[1]:find '^-lib' and arg[2] then
libname = arg[2]
table.remove(arg, 1)
table.remove(arg, 1)
end
if arg[1] == '-a' or arg[1] == '-s' then -- don't compile;
-- use ascii source
table.remove(arg, 1)
assert(#arg == 1)
lua = io.contents(arg[1]):gsub('^#!.-\n', '')
else
assert(#arg == 1)
local bin = os.capture 'PATH=/bin:$PATH tempfile'
assert(os.runf('luac -o %s %s', os.quote(bin), os.quote(arg[1])) == 0)
lua = io.contents(bin)
os.remove(bin)
end
libname = libname or arg[1]:gsub('.*/', ''):gsub('%.lua$', '')
outfile = io.stdout
------------------------
outfile:write [[
#include <lua.h>
#include <lauxlib.h>
static unsigned char program[] = {
]]
outfile:write ' '
local function printf(...) return outfile:write(string.format(...)) end
local last = lua:len()
for i = 1, last do
local n = string.byte(lua, i)
printf('%3d%s', n, i < last and ', ' or '')
if i % 10 == 0 then printf '\n ' end
end
printf '\n};\n\n'
outfile:write((([[
int luaload_$lib(lua_State *L) {
return luaL_loadbuffer(L, (const char*)program, sizeof(program), "@$source");
}
int luaopen_$lib(lua_State *L) {
if (luaL_loadbuffer(L, (const char*)program, sizeof(program), "@$source"))
return luaL_error(L, "Internal library '%s' failed to parse", "$lib");
if (lua_pcall(L, 0, 1, 0))
return luaL_error(L, "Internal library '%s' failed to run: %s", "$lib",
lua_tostring(L, -1));
if (lua_isnil(L, -1)) {
lua_pop(L, 1);
lua_pushboolean(L, 1);
}
lua_getglobal(L, "package"); // s: lib package
lua_getfield(L, -1, "loaded"); // s: lib package loaded
lua_remove(L, -2); // s: lib loaded
lua_pushstring(L, "$lib"); // s: lib loaded libname
lua_pushvalue(L, -3); // s: lib loaded libname lib
lua_settable(L, -3); // s: lib loaded
lua_pop(L, 1); // s: lib
return 1;
}
]]):gsub('$(%a+)', { lib = libname, source = arg[1]:gsub('.*/', '') })))