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))
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
--- /dev/null
+----------------------------------------------------------------------------
+-- 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.
+
"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"
}
/* 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.");
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);
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. */
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);
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 */
}
}
if (dojitopt(L, argv[i] + 2))
return 1;
break;
+ case 'b': /* LuaJIT extension */
+ return dobytecode(L, argv+i);
default: break;
}
}
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 */
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);