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_MAN= luajit.1
|
||||||
FILE_PC= luajit.pc
|
FILE_PC= luajit.pc
|
||||||
FILES_INC= lua.h lualib.h lauxlib.h luaconf.h lua.hpp luajit.h
|
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 (,$(findstring Windows,$(OS)))
|
||||||
ifeq (Darwin,$(shell uname -s))
|
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.
|
for details.
|
||||||
</p>
|
</p>
|
||||||
<p>
|
<p>
|
||||||
Two additional options control the behavior of LuaJIT:
|
LuaJIT has some additional options:
|
||||||
</p>
|
</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>
|
<h3 id="opt_j"><tt>-j cmd[=arg[,arg...]]</tt></h3>
|
||||||
<p>
|
<p>
|
||||||
This option performs a LuaJIT control command or activates one of the
|
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"
|
"Available options are:\n"
|
||||||
" -e chunk Execute string " LUA_QL("chunk") ".\n"
|
" -e chunk Execute string " LUA_QL("chunk") ".\n"
|
||||||
" -l name Require library " LUA_QL("name") ".\n"
|
" -l name Require library " LUA_QL("name") ".\n"
|
||||||
|
" -b ... Save or list bytecode.\n"
|
||||||
" -j cmd Perform LuaJIT control command.\n"
|
" -j cmd Perform LuaJIT control command.\n"
|
||||||
" -O[opt] Control LuaJIT optimizations.\n"
|
" -O[opt] Control LuaJIT optimizations.\n"
|
||||||
" -i Enter interactive mode after executing " LUA_QL("script") ".\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. */
|
/* Load add-on module. */
|
||||||
static int loadjitmodule(lua_State *L, const char *notfound)
|
static int loadjitmodule(lua_State *L)
|
||||||
{
|
{
|
||||||
lua_getglobal(L, "require");
|
lua_getglobal(L, "require");
|
||||||
lua_pushliteral(L, "jit.");
|
lua_pushliteral(L, "jit.");
|
||||||
@ -298,7 +299,8 @@ static int loadjitmodule(lua_State *L, const char *notfound)
|
|||||||
const char *msg = lua_tostring(L, -1);
|
const char *msg = lua_tostring(L, -1);
|
||||||
if (msg && !strncmp(msg, "module ", 7)) {
|
if (msg && !strncmp(msg, "module ", 7)) {
|
||||||
err:
|
err:
|
||||||
l_message(progname, notfound);
|
l_message(progname,
|
||||||
|
"unknown luaJIT command or jit.* modules not installed");
|
||||||
return 1;
|
return 1;
|
||||||
} else {
|
} else {
|
||||||
return report(L, 1);
|
return report(L, 1);
|
||||||
@ -345,7 +347,7 @@ static int dojitcmd(lua_State *L, const char *cmd)
|
|||||||
lua_gettable(L, -2); /* Lookup library function. */
|
lua_gettable(L, -2); /* Lookup library function. */
|
||||||
if (!lua_isfunction(L, -1)) {
|
if (!lua_isfunction(L, -1)) {
|
||||||
lua_pop(L, 2); /* Drop non-function and jit.* table, keep module name. */
|
lua_pop(L, 2); /* Drop non-function and jit.* table, keep module name. */
|
||||||
if (loadjitmodule(L, "unknown luaJIT command"))
|
if (loadjitmodule(L))
|
||||||
return 1;
|
return 1;
|
||||||
} else {
|
} else {
|
||||||
lua_remove(L, -2); /* Drop jit.* table. */
|
lua_remove(L, -2); /* Drop jit.* table. */
|
||||||
@ -365,16 +367,38 @@ static int dojitopt(lua_State *L, const char *opt)
|
|||||||
return runcmdopt(L, 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 */
|
/* check that argument has no extra characters at the end */
|
||||||
#define notail(x) {if ((x)[2] != '\0') return -1;}
|
#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;
|
int i;
|
||||||
for (i = 1; argv[i] != NULL; i++) {
|
for (i = 1; argv[i] != NULL; i++) {
|
||||||
if (argv[i][0] != '-') /* not an option? */
|
if (argv[i][0] != '-') /* Not an option? */
|
||||||
return i;
|
return i;
|
||||||
switch (argv[i][1]) { /* option */
|
switch (argv[i][1]) { /* Check option. */
|
||||||
case '-':
|
case '-':
|
||||||
notail(argv[i]);
|
notail(argv[i]);
|
||||||
return (argv[i+1] != NULL ? i+1 : 0);
|
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;
|
return i;
|
||||||
case 'i':
|
case 'i':
|
||||||
notail(argv[i]);
|
notail(argv[i]);
|
||||||
*pi = 1; /* go through */
|
*flags |= FLAGS_INTERACTIVE;
|
||||||
|
/* fallthrough */
|
||||||
case 'v':
|
case 'v':
|
||||||
notail(argv[i]);
|
notail(argv[i]);
|
||||||
*pv = 1;
|
*flags |= FLAGS_VERSION;
|
||||||
break;
|
break;
|
||||||
case 'e':
|
case 'e':
|
||||||
*pe = 1; /* go through */
|
*flags |= FLAGS_EXEC;
|
||||||
case 'j': /* LuaJIT extension */
|
case 'j': /* LuaJIT extension */
|
||||||
case 'l':
|
case 'l':
|
||||||
|
*flags |= FLAGS_OPTION;
|
||||||
if (argv[i][2] == '\0') {
|
if (argv[i][2] == '\0') {
|
||||||
i++;
|
i++;
|
||||||
if (argv[i] == NULL) return -1;
|
if (argv[i] == NULL) return -1;
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case 'O': break; /* LuaJIT extension */
|
case 'O': break; /* LuaJIT extension */
|
||||||
|
case 'b': /* LuaJIT extension */
|
||||||
|
if (*flags) return -1;
|
||||||
|
*flags |= FLAGS_EXEC;
|
||||||
|
return 0;
|
||||||
default: return -1; /* invalid option */
|
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))
|
if (dojitopt(L, argv[i] + 2))
|
||||||
return 1;
|
return 1;
|
||||||
break;
|
break;
|
||||||
|
case 'b': /* LuaJIT extension */
|
||||||
|
return dobytecode(L, argv+i);
|
||||||
default: break;
|
default: break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -466,7 +498,7 @@ static int pmain(lua_State *L)
|
|||||||
struct Smain *s = (struct Smain *)lua_touserdata(L, 1);
|
struct Smain *s = (struct Smain *)lua_touserdata(L, 1);
|
||||||
char **argv = s->argv;
|
char **argv = s->argv;
|
||||||
int script;
|
int script;
|
||||||
int has_i = 0, has_v = 0, has_e = 0;
|
int flags = 0;
|
||||||
globalL = L;
|
globalL = L;
|
||||||
if (argv[0] && argv[0][0]) progname = argv[0];
|
if (argv[0] && argv[0][0]) progname = argv[0];
|
||||||
LUAJIT_VERSION_SYM(); /* linker-enforced version check */
|
LUAJIT_VERSION_SYM(); /* linker-enforced version check */
|
||||||
@ -475,22 +507,22 @@ static int pmain(lua_State *L)
|
|||||||
lua_gc(L, LUA_GCRESTART, -1);
|
lua_gc(L, LUA_GCRESTART, -1);
|
||||||
s->status = handle_luainit(L);
|
s->status = handle_luainit(L);
|
||||||
if (s->status != 0) return 0;
|
if (s->status != 0) return 0;
|
||||||
script = collectargs(argv, &has_i, &has_v, &has_e);
|
script = collectargs(argv, &flags);
|
||||||
if (script < 0) { /* invalid args? */
|
if (script < 0) { /* invalid args? */
|
||||||
print_usage();
|
print_usage();
|
||||||
s->status = 1;
|
s->status = 1;
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
if (has_v) print_version();
|
if ((flags & FLAGS_VERSION)) print_version();
|
||||||
s->status = runargs(L, argv, (script > 0) ? script : s->argc);
|
s->status = runargs(L, argv, (script > 0) ? script : s->argc);
|
||||||
if (s->status != 0) return 0;
|
if (s->status != 0) return 0;
|
||||||
if (script)
|
if (script)
|
||||||
s->status = handle_script(L, argv, script);
|
s->status = handle_script(L, argv, script);
|
||||||
if (s->status != 0) return 0;
|
if (s->status != 0) return 0;
|
||||||
if (has_i) {
|
if ((flags & FLAGS_INTERACTIVE)) {
|
||||||
print_jit_status(L);
|
print_jit_status(L);
|
||||||
dotty(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()) {
|
if (lua_stdin_is_tty()) {
|
||||||
print_version();
|
print_version();
|
||||||
print_jit_status(L);
|
print_jit_status(L);
|
||||||
|
Loading…
Reference in New Issue
Block a user