author | Francesco Abbate <francesco.abbate@gmail.com> | 2013年10月13日 22:04:42 +0200 |
---|---|---|
committer | Francesco Abbate <francesco.abbate@gmail.com> | 2013年10月13日 22:04:42 +0200 |
commit | cf678f7beefec742b3720ce9b911ab75eede829b (patch) | |
tree | 5047f3119ff215e1bfe1edb2b5137a40ca5974e9 | |
parent | ee91e5ca1ab08642208072a3fc6274f816564ba2 (diff) | |
download | gsl-shell-cf678f7beefec742b3720ce9b911ab75eede829b.tar.gz |
-rw-r--r-- | gsl-shell-jit.c | 127 |
diff --git a/gsl-shell-jit.c b/gsl-shell-jit.c index c4414d07..d618fdad 100644 --- a/gsl-shell-jit.c +++ b/gsl-shell-jit.c @@ -142,10 +142,12 @@ 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" " -v Show version information.\n" + " -E Ignore environment variables.\n" " -- Stop handling options.\n" " - Execute stdin and stop handling options.\n" , @@ -173,21 +175,14 @@ static int report(lua_State *L, int status) static int traceback(lua_State *L) { - if (!lua_isstring(L, 1)) /* 'message' not a string? */ - return 1; /* keep it intact */ - lua_getfield(L, LUA_GLOBALSINDEX, "debug"); - if (!lua_istable(L, -1)) { - lua_pop(L, 1); - return 1; - } - lua_getfield(L, -1, "traceback"); - if (!lua_isfunction(L, -1)) { - lua_pop(L, 2); - return 1; + if (!lua_isstring(L, 1)) { /* Non-string error object? Try metamethod. */ + if (lua_isnoneornil(L, 1) || + !luaL_callmeta(L, 1, "__tostring") || + !lua_isstring(L, -1)) + return 1; /* Return non-string error object. */ + lua_remove(L, 1); /* Replace object by result of __tostring metamethod. */ } - lua_pushvalue(L, 1); /* pass error message */ - lua_pushinteger(L, 2); /* skip this function and traceback */ - lua_call(L, 2, 1); /* call debug.traceback */ + luaL_traceback(L, L, lua_tostring(L, 1), 1); return 1; } @@ -449,7 +444,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."); @@ -459,7 +454,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); @@ -506,7 +502,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. */ @@ -526,16 +522,39 @@ 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 +#define FLAGS_NOENV 16 + +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); @@ -543,15 +562,17 @@ 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; @@ -559,6 +580,13 @@ static int collectargs(char **argv, int *pi, int *pv, int *pe) break; case 'O': break; /* LuaJIT extension */ + case 'b': /* LuaJIT extension */ + if (*flags) return -1; + *flags |= FLAGS_EXEC; + return 0; + case 'E': + *flags |= FLAGS_NOENV; + break; default: return -1; /* invalid option */ } @@ -601,6 +629,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; } @@ -619,47 +649,55 @@ static int handle_luainit(lua_State *L) return dostring(L, init, "=" LUA_INIT); } -struct Smain { +static struct Smain { char **argv; int argc; int status; int keep_windows; -}; +} smain; static int pmain(lua_State *L) { - struct Smain *s = (struct Smain *)lua_touserdata(L, 1); + struct Smain *s = &smain; 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 */ + script = collectargs(argv, &flags); + if (script < 0) { /* invalid args? */ + print_usage(); + s->status = 1; + return 0; + } + if ((flags & FLAGS_NOENV)) { + lua_pushboolean(L, 1); + lua_setfield(L, LUA_REGISTRYINDEX, "LUA_NOENV"); + } lua_gc(L, LUA_GCSTOP, 0); /* stop collector during initialization */ luaL_openlibs(L); /* open libraries */ gsl_shell_openlibs(L); lua_gc(L, LUA_GCRESTART, -1); dolibrary (L, "gslext"); s->keep_windows = 1; - s->status = handle_luainit(L); - if (s->status != 0) return 0; - script = collectargs(argv, &has_i, &has_v, &has_e); - if (script < 0) { /* invalid args? */ - print_usage(); - s->status = 1; - return 0; + if (!(flags & FLAGS_NOENV)) { + s->status = handle_luainit(L); + if (s->status != 0) return 0; } - if (has_v) print_version(); + if (s->status != 0) return 0; + if ((flags & FLAGS_VERSION)) print_version(); s->status = runargs(L, argv, (script > 0) ? script : s->argc); if (s->status != 0) return 0; - if (script) + if (script) { s->status = handle_script(L, argv, script); - if (s->status != 0) return 0; - if (has_i) { + if (s->status != 0) return 0; + } + if ((flags & FLAGS_INTERACTIVE)) { print_jit_status(L); dotty(L); s->keep_windows = 0; - } 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); @@ -676,7 +714,6 @@ static int pmain(lua_State *L) int main(int argc, char **argv) { int status; - struct Smain s; #ifdef USE_READLINE initialize_readline(); #endif @@ -685,15 +722,15 @@ int main(int argc, char **argv) pthread_mutex_lock(&gsl_shell->exec_mutex); - s.argc = argc; - s.argv = argv; - status = lua_cpcall(gsl_shell->L, pmain, &s); + smain.argc = argc; + smain.argv = argv; + status = lua_cpcall(gsl_shell->L, pmain, NULL); report(gsl_shell->L, status); pthread_mutex_unlock(&gsl_shell->exec_mutex); - gsl_shell_close_with_graph(gsl_shell, !s.keep_windows); + gsl_shell_close_with_graph(gsl_shell, !smain.keep_windows); gsl_shell_free(gsl_shell); - return (status || s.status) ? EXIT_FAILURE : EXIT_SUCCESS; + return (status || smain.status) ? EXIT_FAILURE : EXIT_SUCCESS; } |