mirror of
https://github.com/LuaJIT/LuaJIT.git
synced 2025-02-07 15:14:08 +00:00
Add -b command line option to save/list bytecode.
This commit is contained in:
parent
4994fcc32c
commit
0eee70cd4d
2
Makefile
2
Makefile
@ -76,7 +76,7 @@ FILE_SO= libluajit.so
|
||||
FILE_MAN= luajit.1
|
||||
FILE_PC= luajit.pc
|
||||
FILES_INC= lua.h lualib.h lauxlib.h luaconf.h lua.hpp luajit.h
|
||||
FILES_JITLIB= bc.lua v.lua dump.lua dis_x86.lua dis_x64.lua vmdef.lua
|
||||
FILES_JITLIB= bc.lua v.lua dump.lua dis_x86.lua dis_x64.lua bcsave.lua vmdef.lua
|
||||
|
||||
ifeq (,$(findstring Windows,$(OS)))
|
||||
ifeq (Darwin,$(shell uname -s))
|
||||
|
@ -106,9 +106,34 @@ prints a short list of the available options. Please have a look at the
|
||||
for details.
|
||||
</p>
|
||||
<p>
|
||||
Two additional options control the behavior of LuaJIT:
|
||||
LuaJIT has some additional options:
|
||||
</p>
|
||||
|
||||
<h3 id="opt_b"><tt>-b[options] input output</tt></h3>
|
||||
<p>
|
||||
This option saves or lists bytecode. The following additional options
|
||||
are accepted:
|
||||
</p>
|
||||
<ul>
|
||||
<li><tt>-l</tt> — Only list bytecode.</li>
|
||||
<li><tt>-s</tt> — Strip debug info (this is the default).</li>
|
||||
<li><tt>-g</tt> — Keep debug info.</li>
|
||||
<li><tt>-e chunk</tt> — Use chunk string as input.</li>
|
||||
<li><tt>-</tt> (a single minus sign) — Use stdin as input and/or stdout as output.</li>
|
||||
</ul>
|
||||
<p>
|
||||
Typical usage examples:
|
||||
</p>
|
||||
<pre class="code">
|
||||
luajit -b test.lua test.out # Save to test.out
|
||||
luajit -bg test.lua test.out # Keep debug info
|
||||
luajit -be "print('hello world') end" test.out # Save cmdline script
|
||||
|
||||
luajit -bl test.lua # List to stdout
|
||||
luajit -bl test.lua test.txt # List to test.txt
|
||||
luajit -ble "print('hello world') end" # List cmdline script
|
||||
</pre>
|
||||
|
||||
<h3 id="opt_j"><tt>-j cmd[=arg[,arg...]]</tt></h3>
|
||||
<p>
|
||||
This option performs a LuaJIT control command or activates one of the
|
||||
|
125
lib/bcsave.lua
Normal file
125
lib/bcsave.lua
Normal file
@ -0,0 +1,125 @@
|
||||
----------------------------------------------------------------------------
|
||||
-- LuaJIT module to save/list bytecode.
|
||||
--
|
||||
-- Copyright (C) 2005-2011 Mike Pall. All rights reserved.
|
||||
-- Released under the MIT/X license. See Copyright Notice in luajit.h
|
||||
----------------------------------------------------------------------------
|
||||
--
|
||||
-- This module saves or lists the bytecode for an input file.
|
||||
-- It's run by the -b command line option.
|
||||
--
|
||||
------------------------------------------------------------------------------
|
||||
|
||||
-- Cache some library functions and objects.
|
||||
local jit = require("jit")
|
||||
assert(jit.version_num == 20000, "LuaJIT core/library version mismatch")
|
||||
|
||||
------------------------------------------------------------------------------
|
||||
|
||||
local function usage()
|
||||
io.stderr:write[[
|
||||
Save LuaJIT bytecode: luajit -b[options] input output
|
||||
-l Only list bytecode.
|
||||
-s Strip debug info (default).
|
||||
-g Keep debug info.
|
||||
-e chunk Use chunk string as input.
|
||||
-- Stop handling options.
|
||||
- Use stdin as input and/or stdout as output.
|
||||
]]
|
||||
os.exit(1)
|
||||
end
|
||||
|
||||
local function readfile(input)
|
||||
if type(input) == "function" then return input end
|
||||
if input == "-" then input = nil end
|
||||
local f, err = loadfile(input)
|
||||
if not f then
|
||||
io.stderr:write("luajit: ", err, "\n")
|
||||
os.exit(1)
|
||||
end
|
||||
return f
|
||||
end
|
||||
|
||||
local function readstring(input)
|
||||
local f, err = loadstring(input)
|
||||
if not f then
|
||||
io.stderr:write("luajit: ", err, "\n")
|
||||
os.exit(1)
|
||||
end
|
||||
return f
|
||||
end
|
||||
|
||||
local function savefile(name, mode)
|
||||
if name == "-" then return io.stdout end
|
||||
local fp, err = io.open(name, mode)
|
||||
if not fp then
|
||||
io.stderr:write("luajit: cannot write ", err, "\n")
|
||||
os.exit(1)
|
||||
end
|
||||
return fp
|
||||
end
|
||||
|
||||
------------------------------------------------------------------------------
|
||||
|
||||
local function bclist(input, output)
|
||||
local f = readfile(input)
|
||||
require("jit.bc").dump(f, savefile(output, "w"), true)
|
||||
end
|
||||
|
||||
local function bcsave(input, output, strip)
|
||||
local f = readfile(input)
|
||||
local s = string.dump(f, strip)
|
||||
local fp = savefile(output, "wb")
|
||||
local ok, err = fp:write(s)
|
||||
if ok and output ~= "-" then ok, err = fp:close() end
|
||||
if not ok then
|
||||
io.stderr:write("luajit: cannot write ", arg[2], ": ", err, "\n")
|
||||
os.exit(1)
|
||||
end
|
||||
end
|
||||
|
||||
local function docmd(...)
|
||||
local arg = {...}
|
||||
local n = 1
|
||||
local list = false
|
||||
local strip = true
|
||||
while n <= #arg do
|
||||
local a = arg[n]
|
||||
if type(a) == "string" and string.sub(a, 1, 1) == "-" and a ~= "-" then
|
||||
if a == "--" then table.remove(arg, n); break end
|
||||
for m=2,#a do
|
||||
local opt = string.sub(a, m, m)
|
||||
if opt == "l" then
|
||||
list = true
|
||||
elseif opt == "s" then
|
||||
strip = true
|
||||
elseif opt == "g" then
|
||||
strip = false
|
||||
elseif opt == "e" then
|
||||
if n ~= 1 or #arg < 2 or m ~= #a then usage() end
|
||||
arg[2] = readstring(arg[2])
|
||||
else
|
||||
usage()
|
||||
end
|
||||
end
|
||||
table.remove(arg, n)
|
||||
else
|
||||
n = n + 1
|
||||
end
|
||||
end
|
||||
if list then
|
||||
if #arg == 0 or #arg > 2 then usage() end
|
||||
bclist(arg[1], arg[2] or "-")
|
||||
else
|
||||
if #arg ~= 2 then usage() end
|
||||
bcsave(arg[1], arg[2], strip)
|
||||
end
|
||||
end
|
||||
|
||||
------------------------------------------------------------------------------
|
||||
|
||||
-- Public module functions.
|
||||
module(...)
|
||||
|
||||
start = docmd -- Process -b command line option.
|
||||
|
60
src/luajit.c
60
src/luajit.c
@ -61,6 +61,7 @@ static void print_usage(void)
|
||||
"Available options are:\n"
|
||||
" -e chunk Execute string " LUA_QL("chunk") ".\n"
|
||||
" -l name Require library " LUA_QL("name") ".\n"
|
||||
" -b ... Save or list bytecode.\n"
|
||||
" -j cmd Perform LuaJIT control command.\n"
|
||||
" -O[opt] Control LuaJIT optimizations.\n"
|
||||
" -i Enter interactive mode after executing " LUA_QL("script") ".\n"
|
||||
@ -288,7 +289,7 @@ static int handle_script(lua_State *L, char **argv, int n)
|
||||
}
|
||||
|
||||
/* Load add-on module. */
|
||||
static int loadjitmodule(lua_State *L, const char *notfound)
|
||||
static int loadjitmodule(lua_State *L)
|
||||
{
|
||||
lua_getglobal(L, "require");
|
||||
lua_pushliteral(L, "jit.");
|
||||
@ -298,7 +299,8 @@ static int loadjitmodule(lua_State *L, const char *notfound)
|
||||
const char *msg = lua_tostring(L, -1);
|
||||
if (msg && !strncmp(msg, "module ", 7)) {
|
||||
err:
|
||||
l_message(progname, notfound);
|
||||
l_message(progname,
|
||||
"unknown luaJIT command or jit.* modules not installed");
|
||||
return 1;
|
||||
} else {
|
||||
return report(L, 1);
|
||||
@ -345,7 +347,7 @@ static int dojitcmd(lua_State *L, const char *cmd)
|
||||
lua_gettable(L, -2); /* Lookup library function. */
|
||||
if (!lua_isfunction(L, -1)) {
|
||||
lua_pop(L, 2); /* Drop non-function and jit.* table, keep module name. */
|
||||
if (loadjitmodule(L, "unknown luaJIT command"))
|
||||
if (loadjitmodule(L))
|
||||
return 1;
|
||||
} else {
|
||||
lua_remove(L, -2); /* Drop jit.* table. */
|
||||
@ -365,16 +367,38 @@ static int dojitopt(lua_State *L, const char *opt)
|
||||
return runcmdopt(L, opt);
|
||||
}
|
||||
|
||||
/* Save or list bytecode. */
|
||||
static int dobytecode(lua_State *L, char **argv)
|
||||
{
|
||||
int narg = 0;
|
||||
lua_pushliteral(L, "bcsave");
|
||||
if (loadjitmodule(L))
|
||||
return 1;
|
||||
if (argv[0][2]) {
|
||||
narg++;
|
||||
argv[0][1] = '-';
|
||||
lua_pushstring(L, argv[0]+1);
|
||||
}
|
||||
for (argv++; *argv != NULL; narg++, argv++)
|
||||
lua_pushstring(L, *argv);
|
||||
return report(L, lua_pcall(L, narg, 0, 0));
|
||||
}
|
||||
|
||||
/* check that argument has no extra characters at the end */
|
||||
#define notail(x) {if ((x)[2] != '\0') return -1;}
|
||||
|
||||
static int collectargs(char **argv, int *pi, int *pv, int *pe)
|
||||
#define FLAGS_INTERACTIVE 1
|
||||
#define FLAGS_VERSION 2
|
||||
#define FLAGS_EXEC 4
|
||||
#define FLAGS_OPTION 8
|
||||
|
||||
static int collectargs(char **argv, int *flags)
|
||||
{
|
||||
int i;
|
||||
for (i = 1; argv[i] != NULL; i++) {
|
||||
if (argv[i][0] != '-') /* not an option? */
|
||||
if (argv[i][0] != '-') /* Not an option? */
|
||||
return i;
|
||||
switch (argv[i][1]) { /* option */
|
||||
switch (argv[i][1]) { /* Check option. */
|
||||
case '-':
|
||||
notail(argv[i]);
|
||||
return (argv[i+1] != NULL ? i+1 : 0);
|
||||
@ -382,21 +406,27 @@ static int collectargs(char **argv, int *pi, int *pv, int *pe)
|
||||
return i;
|
||||
case 'i':
|
||||
notail(argv[i]);
|
||||
*pi = 1; /* go through */
|
||||
*flags |= FLAGS_INTERACTIVE;
|
||||
/* fallthrough */
|
||||
case 'v':
|
||||
notail(argv[i]);
|
||||
*pv = 1;
|
||||
*flags |= FLAGS_VERSION;
|
||||
break;
|
||||
case 'e':
|
||||
*pe = 1; /* go through */
|
||||
*flags |= FLAGS_EXEC;
|
||||
case 'j': /* LuaJIT extension */
|
||||
case 'l':
|
||||
*flags |= FLAGS_OPTION;
|
||||
if (argv[i][2] == '\0') {
|
||||
i++;
|
||||
if (argv[i] == NULL) return -1;
|
||||
}
|
||||
break;
|
||||
case 'O': break; /* LuaJIT extension */
|
||||
case 'b': /* LuaJIT extension */
|
||||
if (*flags) return -1;
|
||||
*flags |= FLAGS_EXEC;
|
||||
return 0;
|
||||
default: return -1; /* invalid option */
|
||||
}
|
||||
}
|
||||
@ -438,6 +468,8 @@ static int runargs(lua_State *L, char **argv, int n)
|
||||
if (dojitopt(L, argv[i] + 2))
|
||||
return 1;
|
||||
break;
|
||||
case 'b': /* LuaJIT extension */
|
||||
return dobytecode(L, argv+i);
|
||||
default: break;
|
||||
}
|
||||
}
|
||||
@ -466,7 +498,7 @@ static int pmain(lua_State *L)
|
||||
struct Smain *s = (struct Smain *)lua_touserdata(L, 1);
|
||||
char **argv = s->argv;
|
||||
int script;
|
||||
int has_i = 0, has_v = 0, has_e = 0;
|
||||
int flags = 0;
|
||||
globalL = L;
|
||||
if (argv[0] && argv[0][0]) progname = argv[0];
|
||||
LUAJIT_VERSION_SYM(); /* linker-enforced version check */
|
||||
@ -475,22 +507,22 @@ static int pmain(lua_State *L)
|
||||
lua_gc(L, LUA_GCRESTART, -1);
|
||||
s->status = handle_luainit(L);
|
||||
if (s->status != 0) return 0;
|
||||
script = collectargs(argv, &has_i, &has_v, &has_e);
|
||||
script = collectargs(argv, &flags);
|
||||
if (script < 0) { /* invalid args? */
|
||||
print_usage();
|
||||
s->status = 1;
|
||||
return 0;
|
||||
}
|
||||
if (has_v) print_version();
|
||||
if ((flags & FLAGS_VERSION)) print_version();
|
||||
s->status = runargs(L, argv, (script > 0) ? script : s->argc);
|
||||
if (s->status != 0) return 0;
|
||||
if (script)
|
||||
s->status = handle_script(L, argv, script);
|
||||
if (s->status != 0) return 0;
|
||||
if (has_i) {
|
||||
if ((flags & FLAGS_INTERACTIVE)) {
|
||||
print_jit_status(L);
|
||||
dotty(L);
|
||||
} else if (script == 0 && !has_e && !has_v) {
|
||||
} else if (script == 0 && !(flags & (FLAGS_EXEC|FLAGS_VERSION))) {
|
||||
if (lua_stdin_is_tty()) {
|
||||
print_version();
|
||||
print_jit_status(L);
|
||||
|
Loading…
Reference in New Issue
Block a user