aboutsummaryrefslogtreecommitdiff
path: root/src/luajit.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/luajit.c')
-rw-r--r--src/luajit.c156
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()' */
41static 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
40static lua_State *globalL = NULL; 55static lua_State *globalL = NULL;
@@ -54,16 +69,17 @@ static void lstop(lua_State *L, lua_Debug *ar)
54 69
55static void laction(int i) 70static 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
63static void print_usage(void) 78static 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
83static void l_message(const char *msg) 97static 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
158static int getargs(lua_State *L, char **argv, int n) 172static 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
176static int dofile(lua_State *L, const char *name) 183static 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
278static int handle_script(lua_State *L, char **argv, int n) 285static 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
445static int runargs(lua_State *L, char **argv, int n) 462static 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
488static int handle_luainit(lua_State *L) 505static 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