186 lines
4.6 KiB
Lua
Executable File
186 lines
4.6 KiB
Lua
Executable File
#!/usr/bin/env lua
|
|
--------------------------------------------------------------------------------
|
|
-- @script Lua Module Pre-Loader
|
|
-- @version 1.1
|
|
-- @author Renato Maia <maia@tecgraf.puc-rio.br>
|
|
--
|
|
|
|
local assert = assert
|
|
local ipairs = ipairs
|
|
local pairs = pairs
|
|
local select = select
|
|
local io = require "io"
|
|
local os = require "os"
|
|
|
|
module("preloader", require "loop.compiler.Arguments")
|
|
|
|
local FILE_SEP = "/"
|
|
local FUNC_SEP = "_"
|
|
local OPEN_PAT = "int%s+luaopen_([%w_]+)%s*%(%s*lua_State%s*%*[%w_]*%);"
|
|
|
|
help = false
|
|
names = false
|
|
include = {}
|
|
funcname = ""
|
|
output = "preload"
|
|
prefix = "LUAPRELOAD_API"
|
|
directory = ""
|
|
|
|
_optpat = "^%-(%-?%w+)(=?)(.-)$"
|
|
_alias = {
|
|
I = "include",
|
|
["-help"] = "help",
|
|
}
|
|
for name in pairs(_M) do
|
|
_alias[name:sub(1, 1)] = name
|
|
end
|
|
|
|
local start, errmsg = _M(...)
|
|
if not start or help then
|
|
if errmsg then io.stderr:write("ERROR: ", errmsg, "\n") end
|
|
io.stderr:write([[
|
|
Lua Module Pre-Loader 1.1 Copyright (C) 2006-2008 Tecgraf, PUC-Rio
|
|
Usage: ]],_NAME,[[.lua [options] [inputs]
|
|
|
|
[inputs] is a sequence of names that may be header file paths or package
|
|
names, use the options described below to indicate how they should be
|
|
interpreted. If no [inputs] is provided then such names are read from the
|
|
standard input.
|
|
|
|
Options:
|
|
|
|
-d, -directory Directory where the output files should be generated. Its
|
|
default is the current directory.
|
|
|
|
-I, -i, -include Adds a directory to the list of paths where the header files
|
|
are searched.
|
|
|
|
-f, -funcname Name of the generated function that pre-loads all library
|
|
modules. Its default is 'luapreload_' plus the name defined
|
|
by option '-output'.
|
|
|
|
-n, -names Flag that indicates provided input names are actually
|
|
package names and not header files.
|
|
|
|
-o, -output Name used to form the name of the files generated. Two files
|
|
are generated: a source code file with the sufix '.c' with
|
|
the pre-loading code and a header file with the sufix '.h'
|
|
with function signatures. Its default is ']],output,[['.
|
|
|
|
-p, -prefix Prefix added to the signature of the functions generated.
|
|
Its default is ']],prefix,[['.
|
|
|
|
]])
|
|
os.exit(1)
|
|
end
|
|
|
|
--------------------------------------------------------------------------------
|
|
|
|
local function escapepattern(pattern)
|
|
return pattern:gsub("([%^%$%(%)%%%.%[%]%*%+%-%?])", "%%%1")
|
|
end
|
|
|
|
local filesep = escapepattern(FILE_SEP)
|
|
local funcsep = escapepattern(FUNC_SEP)
|
|
|
|
local function adjustpath(path)
|
|
if path ~= "" and not path:find(filesep.."$") then
|
|
return path..FILE_SEP
|
|
end
|
|
return path
|
|
end
|
|
|
|
local filepath = adjustpath(directory)..output
|
|
|
|
if funcname == "" then funcname = "luapreload_"..output end
|
|
|
|
--------------------------------------------------------------------------------
|
|
|
|
local function openheader(name)
|
|
local file, errmsg = io.open(name)
|
|
if not file then
|
|
for _, path in ipairs(include) do
|
|
path = adjustpath(path)..name
|
|
file, errmsg = io.open(path)
|
|
if file then break end
|
|
end
|
|
end
|
|
return file, errmsg
|
|
end
|
|
|
|
--------------------------------------------------------------------------------
|
|
|
|
local outh = assert(io.open(filepath..".h", "w"))
|
|
|
|
local guard = output:upper():gsub("[^%w]", "_")
|
|
|
|
outh:write([[
|
|
#ifndef __]],guard,[[__
|
|
#define __]],guard,[[__
|
|
|
|
#ifndef ]],prefix,[[
|
|
#define ]],prefix,[[
|
|
#endif
|
|
|
|
]],prefix,[[ int ]],funcname,[[(lua_State *L);
|
|
|
|
#endif /* __]],guard,[[__ */
|
|
]])
|
|
outh:close()
|
|
|
|
--------------------------------------------------------------------------------
|
|
|
|
local inputs = { select(start, ...) }
|
|
if #inputs == 0 then
|
|
for name in io.stdin:lines() do
|
|
inputs[#inputs+1] = name
|
|
end
|
|
end
|
|
|
|
local outc = assert(io.open(filepath..".c", "w"))
|
|
outc:write([[
|
|
#include <lua.h>
|
|
#include <lauxlib.h>
|
|
|
|
]])
|
|
|
|
for i, input in ipairs(inputs) do
|
|
if names then
|
|
outc:write('int luaopen_',input:gsub("%.", FUNC_SEP),'(lua_State*);\n')
|
|
else
|
|
outc:write('#include "',input,'"\n')
|
|
end
|
|
end
|
|
|
|
outc:write([[
|
|
#include "]],output,[[.h"
|
|
|
|
]],prefix,[[ int ]],funcname,[[(lua_State *L) {
|
|
luaL_findtable(L, LUA_GLOBALSINDEX, "package.preload", ]], #inputs, [[);
|
|
|
|
]])
|
|
local code = [[
|
|
lua_pushcfunction(L, luaopen_%s);
|
|
lua_setfield(L, -2, "%s");
|
|
]]
|
|
for i, input in ipairs(inputs) do
|
|
if names then
|
|
outc:write(code:format(input:gsub("%.", FUNC_SEP), input))
|
|
else
|
|
local input = assert(openheader(input))
|
|
local header = input:read("*a")
|
|
input:close()
|
|
for func in header:gmatch(OPEN_PAT) do
|
|
outc:write(code:format(func, func:gsub(funcsep, ".")))
|
|
end
|
|
end
|
|
end
|
|
outc:write([[
|
|
|
|
lua_pop(L, 1);
|
|
return 0;
|
|
}
|
|
]])
|
|
|
|
outc:close()
|