diff options
Diffstat (limited to 'src/luajit.c')
| -rw-r--r-- | src/luajit.c | 156 |
1 files changed, 92 insertions, 64 deletions
diff --git a/src/luajit.c b/src/luajit.c index 78a0d350..65d55c3c 100644 --- a/src/luajit.c +++ b/src/luajit.c | |||
| @@ -35,6 +35,21 @@ | |||
| 35 | 35 | ||
| 36 | #if !LJ_TARGET_CONSOLE | 36 | #if !LJ_TARGET_CONSOLE |
| 37 | #include <signal.h> | 37 | #include <signal.h> |
| 38 | |||
| 39 | #if LJ_TARGET_POSIX | ||
| 40 | /* Improve signal handling on POSIX. Try CTRL-C on: luajit -e 'io.read()' */ | ||
| 41 | static void signal_set(int sig, void (*h)(int)) | ||
| 42 | { | ||
| 43 | struct sigaction sa; | ||
| 44 | memset(&sa, 0, sizeof(sa)); | ||
| 45 | sa.sa_handler = h; | ||
| 46 | sigemptyset(&sa.sa_mask); | ||
| 47 | sigaction(sig, &sa, NULL); | ||
| 48 | } | ||
| 49 | #else | ||
| 50 | #define signal_set signal | ||
| 51 | #endif | ||
| 52 | |||
| 38 | #endif | 53 | #endif |
| 39 | 54 | ||
| 40 | static lua_State *globalL = NULL; | 55 | static lua_State *globalL = NULL; |
| @@ -54,16 +69,17 @@ static void lstop(lua_State *L, lua_Debug *ar) | |||
| 54 | 69 | ||
| 55 | static void laction(int i) | 70 | static void laction(int i) |
| 56 | { | 71 | { |
| 57 | signal(i, SIG_DFL); /* if another SIGINT happens before lstop, | 72 | /* Terminate process if another SIGINT happens (double CTRL-C). */ |
| 58 | terminate process (default action) */ | 73 | signal_set(i, SIG_DFL); |
| 59 | lua_sethook(globalL, lstop, LUA_MASKCALL | LUA_MASKRET | LUA_MASKCOUNT, 1); | 74 | lua_sethook(globalL, lstop, LUA_MASKCALL | LUA_MASKRET | LUA_MASKCOUNT, 1); |
| 60 | } | 75 | } |
| 61 | #endif | 76 | #endif |
| 62 | 77 | ||
| 63 | static void print_usage(void) | 78 | static void print_usage(void) |
| 64 | { | 79 | { |
| 65 | fprintf(stderr, | 80 | fputs("usage: ", stderr); |
| 66 | "usage: %s [options]... [script [args]...].\n" | 81 | fputs(progname, stderr); |
| 82 | fputs(" [options]... [script [args]...].\n" | ||
| 67 | "Available options are:\n" | 83 | "Available options are:\n" |
| 68 | " -e chunk Execute string " LUA_QL("chunk") ".\n" | 84 | " -e chunk Execute string " LUA_QL("chunk") ".\n" |
| 69 | " -l name Require library " LUA_QL("name") ".\n" | 85 | " -l name Require library " LUA_QL("name") ".\n" |
| @@ -74,16 +90,14 @@ static void print_usage(void) | |||
| 74 | " -v Show version information.\n" | 90 | " -v Show version information.\n" |
| 75 | " -E Ignore environment variables.\n" | 91 | " -E Ignore environment variables.\n" |
| 76 | " -- Stop handling options.\n" | 92 | " -- Stop handling options.\n" |
| 77 | " - Execute stdin and stop handling options.\n" | 93 | " - Execute stdin and stop handling options.\n", stderr); |
| 78 | , | ||
| 79 | progname); | ||
| 80 | fflush(stderr); | 94 | fflush(stderr); |
| 81 | } | 95 | } |
| 82 | 96 | ||
| 83 | static void l_message(const char *msg) | 97 | static void l_message(const char *msg) |
| 84 | { | 98 | { |
| 85 | if (progname) fprintf(stderr, "%s: ", progname); | 99 | if (progname) { fputs(progname, stderr); fputc(':', stderr); fputc(' ', stderr); } |
| 86 | fprintf(stderr, "%s\n", msg); | 100 | fputs(msg, stderr); fputc('\n', stderr); |
| 87 | fflush(stderr); | 101 | fflush(stderr); |
| 88 | } | 102 | } |
| 89 | 103 | ||
| @@ -118,15 +132,15 @@ static int docall(lua_State *L, int narg, int clear) | |||
| 118 | lua_pushcfunction(L, traceback); /* push traceback function */ | 132 | lua_pushcfunction(L, traceback); /* push traceback function */ |
| 119 | lua_insert(L, base); /* put it under chunk and args */ | 133 | lua_insert(L, base); /* put it under chunk and args */ |
| 120 | #if !LJ_TARGET_CONSOLE | 134 | #if !LJ_TARGET_CONSOLE |
| 121 | signal(SIGINT, laction); | 135 | signal_set(SIGINT, laction); |
| 122 | #endif | 136 | #endif |
| 123 | status = lua_pcall(L, narg, (clear ? 0 : LUA_MULTRET), base); | 137 | status = lua_pcall(L, narg, (clear ? 0 : LUA_MULTRET), base); |
| 124 | #if !LJ_TARGET_CONSOLE | 138 | #if !LJ_TARGET_CONSOLE |
| 125 | signal(SIGINT, SIG_DFL); | 139 | signal_set(SIGINT, SIG_DFL); |
| 126 | #endif | 140 | #endif |
| 127 | lua_remove(L, base); /* remove traceback function */ | 141 | lua_remove(L, base); /* remove traceback function */ |
| 128 | /* force a complete garbage collection in case of errors */ | 142 | /* force a complete garbage collection in case of errors */ |
| 129 | if (status != 0) lua_gc(L, LUA_GCCOLLECT, 0); | 143 | if (status != LUA_OK) lua_gc(L, LUA_GCCOLLECT, 0); |
| 130 | return status; | 144 | return status; |
| 131 | } | 145 | } |
| 132 | 146 | ||
| @@ -155,22 +169,15 @@ static void print_jit_status(lua_State *L) | |||
| 155 | lua_settop(L, 0); /* clear stack */ | 169 | lua_settop(L, 0); /* clear stack */ |
| 156 | } | 170 | } |
| 157 | 171 | ||
| 158 | static int getargs(lua_State *L, char **argv, int n) | 172 | static void createargtable(lua_State *L, char **argv, int argc, int argf) |
| 159 | { | 173 | { |
| 160 | int narg; | ||
| 161 | int i; | 174 | int i; |
| 162 | int argc = 0; | 175 | lua_createtable(L, argc - argf, argf); |
| 163 | while (argv[argc]) argc++; /* count total number of arguments */ | ||
| 164 | narg = argc - (n + 1); /* number of arguments to the script */ | ||
| 165 | luaL_checkstack(L, narg + 3, "too many arguments to script"); | ||
| 166 | for (i = n+1; i < argc; i++) | ||
| 167 | lua_pushstring(L, argv[i]); | ||
| 168 | lua_createtable(L, narg, n + 1); | ||
| 169 | for (i = 0; i < argc; i++) { | 176 | for (i = 0; i < argc; i++) { |
| 170 | lua_pushstring(L, argv[i]); | 177 | lua_pushstring(L, argv[i]); |
| 171 | lua_rawseti(L, -2, i - n); | 178 | lua_rawseti(L, -2, i - argf); |
| 172 | } | 179 | } |
| 173 | return narg; | 180 | lua_setglobal(L, "arg"); |
| 174 | } | 181 | } |
| 175 | 182 | ||
| 176 | static int dofile(lua_State *L, const char *name) | 183 | static int dofile(lua_State *L, const char *name) |
| @@ -259,9 +266,9 @@ static void dotty(lua_State *L) | |||
| 259 | const char *oldprogname = progname; | 266 | const char *oldprogname = progname; |
| 260 | progname = NULL; | 267 | progname = NULL; |
| 261 | while ((status = loadline(L)) != -1) { | 268 | while ((status = loadline(L)) != -1) { |
| 262 | if (status == 0) status = docall(L, 0, 0); | 269 | if (status == LUA_OK) status = docall(L, 0, 0); |
| 263 | report(L, status); | 270 | report(L, status); |
| 264 | if (status == 0 && lua_gettop(L) > 0) { /* any result to print? */ | 271 | if (status == LUA_OK && lua_gettop(L) > 0) { /* any result to print? */ |
| 265 | lua_getglobal(L, "print"); | 272 | lua_getglobal(L, "print"); |
| 266 | lua_insert(L, 1); | 273 | lua_insert(L, 1); |
| 267 | if (lua_pcall(L, lua_gettop(L)-1, 0, 0) != 0) | 274 | if (lua_pcall(L, lua_gettop(L)-1, 0, 0) != 0) |
| @@ -275,21 +282,30 @@ static void dotty(lua_State *L) | |||
| 275 | progname = oldprogname; | 282 | progname = oldprogname; |
| 276 | } | 283 | } |
| 277 | 284 | ||
| 278 | static int handle_script(lua_State *L, char **argv, int n) | 285 | static int handle_script(lua_State *L, char **argx) |
| 279 | { | 286 | { |
| 280 | int status; | 287 | int status; |
| 281 | const char *fname; | 288 | const char *fname = argx[0]; |
| 282 | int narg = getargs(L, argv, n); /* collect arguments */ | 289 | if (strcmp(fname, "-") == 0 && strcmp(argx[-1], "--") != 0) |
| 283 | lua_setglobal(L, "arg"); | ||
| 284 | fname = argv[n]; | ||
| 285 | if (strcmp(fname, "-") == 0 && strcmp(argv[n-1], "--") != 0) | ||
| 286 | fname = NULL; /* stdin */ | 290 | fname = NULL; /* stdin */ |
| 287 | status = luaL_loadfile(L, fname); | 291 | status = luaL_loadfile(L, fname); |
| 288 | lua_insert(L, -(narg+1)); | 292 | if (status == LUA_OK) { |
| 289 | if (status == 0) | 293 | /* Fetch args from arg table. LUA_INIT or -e might have changed them. */ |
| 294 | int narg = 0; | ||
| 295 | lua_getglobal(L, "arg"); | ||
| 296 | if (lua_istable(L, -1)) { | ||
| 297 | do { | ||
| 298 | narg++; | ||
| 299 | lua_rawgeti(L, -narg, narg); | ||
| 300 | } while (!lua_isnil(L, -1)); | ||
| 301 | lua_pop(L, 1); | ||
| 302 | lua_remove(L, -narg); | ||
| 303 | narg--; | ||
| 304 | } else { | ||
| 305 | lua_pop(L, 1); | ||
| 306 | } | ||
| 290 | status = docall(L, narg, 0); | 307 | status = docall(L, narg, 0); |
| 291 | else | 308 | } |
| 292 | lua_pop(L, narg); | ||
| 293 | return report(L, status); | 309 | return report(L, status); |
| 294 | } | 310 | } |
| 295 | 311 | ||
| @@ -385,7 +401,8 @@ static int dobytecode(lua_State *L, char **argv) | |||
| 385 | } | 401 | } |
| 386 | for (argv++; *argv != NULL; narg++, argv++) | 402 | for (argv++; *argv != NULL; narg++, argv++) |
| 387 | lua_pushstring(L, *argv); | 403 | lua_pushstring(L, *argv); |
| 388 | return report(L, lua_pcall(L, narg, 0, 0)); | 404 | report(L, lua_pcall(L, narg, 0, 0)); |
| 405 | return -1; | ||
| 389 | } | 406 | } |
| 390 | 407 | ||
| 391 | /* check that argument has no extra characters at the end */ | 408 | /* check that argument has no extra characters at the end */ |
| @@ -406,7 +423,7 @@ static int collectargs(char **argv, int *flags) | |||
| 406 | switch (argv[i][1]) { /* Check option. */ | 423 | switch (argv[i][1]) { /* Check option. */ |
| 407 | case '-': | 424 | case '-': |
| 408 | notail(argv[i]); | 425 | notail(argv[i]); |
| 409 | return (argv[i+1] != NULL ? i+1 : 0); | 426 | return i+1; |
| 410 | case '\0': | 427 | case '\0': |
| 411 | return i; | 428 | return i; |
| 412 | case 'i': | 429 | case 'i': |
| @@ -432,23 +449,23 @@ static int collectargs(char **argv, int *flags) | |||
| 432 | case 'b': /* LuaJIT extension */ | 449 | case 'b': /* LuaJIT extension */ |
| 433 | if (*flags) return -1; | 450 | if (*flags) return -1; |
| 434 | *flags |= FLAGS_EXEC; | 451 | *flags |= FLAGS_EXEC; |
| 435 | return 0; | 452 | return i+1; |
| 436 | case 'E': | 453 | case 'E': |
| 437 | *flags |= FLAGS_NOENV; | 454 | *flags |= FLAGS_NOENV; |
| 438 | break; | 455 | break; |
| 439 | default: return -1; /* invalid option */ | 456 | default: return -1; /* invalid option */ |
| 440 | } | 457 | } |
| 441 | } | 458 | } |
| 442 | return 0; | 459 | return i; |
| 443 | } | 460 | } |
| 444 | 461 | ||
| 445 | static int runargs(lua_State *L, char **argv, int n) | 462 | static int runargs(lua_State *L, char **argv, int argn) |
| 446 | { | 463 | { |
| 447 | int i; | 464 | int i; |
| 448 | for (i = 1; i < n; i++) { | 465 | for (i = 1; i < argn; i++) { |
| 449 | if (argv[i] == NULL) continue; | 466 | if (argv[i] == NULL) continue; |
| 450 | lua_assert(argv[i][0] == '-'); | 467 | lua_assert(argv[i][0] == '-'); |
| 451 | switch (argv[i][1]) { /* option */ | 468 | switch (argv[i][1]) { |
| 452 | case 'e': { | 469 | case 'e': { |
| 453 | const char *chunk = argv[i] + 2; | 470 | const char *chunk = argv[i] + 2; |
| 454 | if (*chunk == '\0') chunk = argv[++i]; | 471 | if (*chunk == '\0') chunk = argv[++i]; |
| @@ -462,10 +479,10 @@ static int runargs(lua_State *L, char **argv, int n) | |||
| 462 | if (*filename == '\0') filename = argv[++i]; | 479 | if (*filename == '\0') filename = argv[++i]; |
| 463 | lua_assert(filename != NULL); | 480 | lua_assert(filename != NULL); |
| 464 | if (dolibrary(L, filename)) | 481 | if (dolibrary(L, filename)) |
| 465 | return 1; /* stop if file fails */ | 482 | return 1; |
| 466 | break; | 483 | break; |
| 467 | } | 484 | } |
| 468 | case 'j': { /* LuaJIT extension */ | 485 | case 'j': { /* LuaJIT extension. */ |
| 469 | const char *cmd = argv[i] + 2; | 486 | const char *cmd = argv[i] + 2; |
| 470 | if (*cmd == '\0') cmd = argv[++i]; | 487 | if (*cmd == '\0') cmd = argv[++i]; |
| 471 | lua_assert(cmd != NULL); | 488 | lua_assert(cmd != NULL); |
| @@ -473,16 +490,16 @@ static int runargs(lua_State *L, char **argv, int n) | |||
| 473 | return 1; | 490 | return 1; |
| 474 | break; | 491 | break; |
| 475 | } | 492 | } |
| 476 | case 'O': /* LuaJIT extension */ | 493 | case 'O': /* LuaJIT extension. */ |
| 477 | if (dojitopt(L, argv[i] + 2)) | 494 | if (dojitopt(L, argv[i] + 2)) |
| 478 | return 1; | 495 | return 1; |
| 479 | break; | 496 | break; |
| 480 | case 'b': /* LuaJIT extension */ | 497 | case 'b': /* LuaJIT extension. */ |
| 481 | return dobytecode(L, argv+i); | 498 | return dobytecode(L, argv+i); |
| 482 | default: break; | 499 | default: break; |
| 483 | } | 500 | } |
| 484 | } | 501 | } |
| 485 | return 0; | 502 | return LUA_OK; |
| 486 | } | 503 | } |
| 487 | 504 | ||
| 488 | static int handle_luainit(lua_State *L) | 505 | static int handle_luainit(lua_State *L) |
| @@ -493,7 +510,7 @@ static int handle_luainit(lua_State *L) | |||
| 493 | const char *init = getenv(LUA_INIT); | 510 | const char *init = getenv(LUA_INIT); |
| 494 | #endif | 511 | #endif |
| 495 | if (init == NULL) | 512 | if (init == NULL) |
| 496 | return 0; /* status OK */ | 513 | return LUA_OK; |
| 497 | else if (init[0] == '@') | 514 | else if (init[0] == '@') |
| 498 | return dofile(L, init+1); | 515 | return dofile(L, init+1); |
| 499 | else | 516 | else |
| @@ -510,44 +527,55 @@ static int pmain(lua_State *L) | |||
| 510 | { | 527 | { |
| 511 | struct Smain *s = &smain; | 528 | struct Smain *s = &smain; |
| 512 | char **argv = s->argv; | 529 | char **argv = s->argv; |
| 513 | int script; | 530 | int argn; |
| 514 | int flags = 0; | 531 | int flags = 0; |
| 515 | globalL = L; | 532 | globalL = L; |
| 516 | LUAJIT_VERSION_SYM(); /* linker-enforced version check */ | 533 | LUAJIT_VERSION_SYM(); /* Linker-enforced version check. */ |
| 517 | script = collectargs(argv, &flags); | 534 | |
| 518 | if (script < 0) { /* invalid args? */ | 535 | argn = collectargs(argv, &flags); |
| 536 | if (argn < 0) { /* Invalid args? */ | ||
| 519 | print_usage(); | 537 | print_usage(); |
| 520 | s->status = 1; | 538 | s->status = 1; |
| 521 | return 0; | 539 | return 0; |
| 522 | } | 540 | } |
| 541 | |||
| 523 | if ((flags & FLAGS_NOENV)) { | 542 | if ((flags & FLAGS_NOENV)) { |
| 524 | lua_pushboolean(L, 1); | 543 | lua_pushboolean(L, 1); |
| 525 | lua_setfield(L, LUA_REGISTRYINDEX, "LUA_NOENV"); | 544 | lua_setfield(L, LUA_REGISTRYINDEX, "LUA_NOENV"); |
| 526 | } | 545 | } |
| 527 | lua_gc(L, LUA_GCSTOP, 0); /* stop collector during initialization */ | 546 | |
| 528 | luaL_openlibs(L); /* open libraries */ | 547 | /* Stop collector during library initialization. */ |
| 548 | lua_gc(L, LUA_GCSTOP, 0); | ||
| 549 | luaL_openlibs(L); | ||
| 529 | lua_gc(L, LUA_GCRESTART, -1); | 550 | lua_gc(L, LUA_GCRESTART, -1); |
| 551 | |||
| 552 | createargtable(L, argv, s->argc, argn); | ||
| 553 | |||
| 530 | if (!(flags & FLAGS_NOENV)) { | 554 | if (!(flags & FLAGS_NOENV)) { |
| 531 | s->status = handle_luainit(L); | 555 | s->status = handle_luainit(L); |
| 532 | if (s->status != 0) return 0; | 556 | if (s->status != LUA_OK) return 0; |
| 533 | } | 557 | } |
| 558 | |||
| 534 | if ((flags & FLAGS_VERSION)) print_version(); | 559 | if ((flags & FLAGS_VERSION)) print_version(); |
| 535 | s->status = runargs(L, argv, (script > 0) ? script : s->argc); | 560 | |
| 536 | if (s->status != 0) return 0; | 561 | s->status = runargs(L, argv, argn); |
| 537 | if (script) { | 562 | if (s->status != LUA_OK) return 0; |
| 538 | s->status = handle_script(L, argv, script); | 563 | |
| 539 | if (s->status != 0) return 0; | 564 | if (s->argc > argn) { |
| 565 | s->status = handle_script(L, argv + argn); | ||
| 566 | if (s->status != LUA_OK) return 0; | ||
| 540 | } | 567 | } |
| 568 | |||
| 541 | if ((flags & FLAGS_INTERACTIVE)) { | 569 | if ((flags & FLAGS_INTERACTIVE)) { |
| 542 | print_jit_status(L); | 570 | print_jit_status(L); |
| 543 | dotty(L); | 571 | dotty(L); |
| 544 | } else if (script == 0 && !(flags & (FLAGS_EXEC|FLAGS_VERSION))) { | 572 | } else if (s->argc == argn && !(flags & (FLAGS_EXEC|FLAGS_VERSION))) { |
| 545 | if (lua_stdin_is_tty()) { | 573 | if (lua_stdin_is_tty()) { |
| 546 | print_version(); | 574 | print_version(); |
| 547 | print_jit_status(L); | 575 | print_jit_status(L); |
| 548 | dotty(L); | 576 | dotty(L); |
| 549 | } else { | 577 | } else { |
| 550 | dofile(L, NULL); /* executes stdin as a file */ | 578 | dofile(L, NULL); /* Executes stdin as a file. */ |
| 551 | } | 579 | } |
| 552 | } | 580 | } |
| 553 | return 0; | 581 | return 0; |
| @@ -558,7 +586,7 @@ int main(int argc, char **argv) | |||
| 558 | int status; | 586 | int status; |
| 559 | lua_State *L; | 587 | lua_State *L; |
| 560 | if (!argv[0]) argv = empty_argv; else if (argv[0][0]) progname = argv[0]; | 588 | if (!argv[0]) argv = empty_argv; else if (argv[0][0]) progname = argv[0]; |
| 561 | L = lua_open(); /* create state */ | 589 | L = lua_open(); |
| 562 | if (L == NULL) { | 590 | if (L == NULL) { |
| 563 | l_message("cannot create state: not enough memory"); | 591 | l_message("cannot create state: not enough memory"); |
| 564 | return EXIT_FAILURE; | 592 | return EXIT_FAILURE; |
| @@ -568,6 +596,6 @@ int main(int argc, char **argv) | |||
| 568 | status = lua_cpcall(L, pmain, NULL); | 596 | status = lua_cpcall(L, pmain, NULL); |
| 569 | report(L, status); | 597 | report(L, status); |
| 570 | lua_close(L); | 598 | lua_close(L); |
| 571 | return (status || smain.status) ? EXIT_FAILURE : EXIT_SUCCESS; | 599 | return (status || smain.status > 0) ? EXIT_FAILURE : EXIT_SUCCESS; |
| 572 | } | 600 | } |
| 573 | 601 | ||
