diff options
author | Mike Pall <mike> | 2016-07-17 16:23:49 +0200 |
---|---|---|
committer | Mike Pall <mike> | 2016-07-17 16:23:49 +0200 |
commit | 92d9ff211ae864777a8580b5a7326d5f408161ce (patch) | |
tree | 894941850627260d7c54c86f406c54b1b370f415 | |
parent | 7374046299678889202459f6c26fa78b3118eae9 (diff) | |
download | luajit-92d9ff211ae864777a8580b5a7326d5f408161ce.tar.gz luajit-92d9ff211ae864777a8580b5a7326d5f408161ce.tar.bz2 luajit-92d9ff211ae864777a8580b5a7326d5f408161ce.zip |
Set arg table before evaluating LUA_INIT and -e chunks.
-rw-r--r-- | doc/extensions.html | 1 | ||||
-rw-r--r-- | src/luajit.c | 103 |
2 files changed, 60 insertions, 44 deletions
diff --git a/doc/extensions.html b/doc/extensions.html index 368b527c..9d666293 100644 --- a/doc/extensions.html +++ b/doc/extensions.html | |||
@@ -349,6 +349,7 @@ break the Lua/C API and ABI (e.g. <tt>_ENV</tt>). | |||
349 | LuaJIT supports some extensions from Lua 5.3: | 349 | LuaJIT supports some extensions from Lua 5.3: |
350 | <ul> | 350 | <ul> |
351 | <li>Unicode escape <tt>'\u{XX...}'</tt> embeds the UTF-8 encoding in string literals.</li> | 351 | <li>Unicode escape <tt>'\u{XX...}'</tt> embeds the UTF-8 encoding in string literals.</li> |
352 | <li>The argument table <tt>arg</tt> can be read (and modified) by <tt>LUA_INIT</tt> and <tt>-e</tt> chunks.</li> | ||
352 | </ul> | 353 | </ul> |
353 | 354 | ||
354 | <h2 id="exceptions">C++ Exception Interoperability</h2> | 355 | <h2 id="exceptions">C++ Exception Interoperability</h2> |
diff --git a/src/luajit.c b/src/luajit.c index 00e12bd3..4de2d43c 100644 --- a/src/luajit.c +++ b/src/luajit.c | |||
@@ -152,22 +152,15 @@ static void print_jit_status(lua_State *L) | |||
152 | putc('\n', stdout); | 152 | putc('\n', stdout); |
153 | } | 153 | } |
154 | 154 | ||
155 | static int getargs(lua_State *L, char **argv, int n) | 155 | static void createargtable(lua_State *L, char **argv, int argc, int argf) |
156 | { | 156 | { |
157 | int narg; | ||
158 | int i; | 157 | int i; |
159 | int argc = 0; | 158 | lua_createtable(L, argc - argf, argf); |
160 | while (argv[argc]) argc++; /* count total number of arguments */ | ||
161 | narg = argc - (n + 1); /* number of arguments to the script */ | ||
162 | luaL_checkstack(L, narg + 3, "too many arguments to script"); | ||
163 | for (i = n+1; i < argc; i++) | ||
164 | lua_pushstring(L, argv[i]); | ||
165 | lua_createtable(L, narg, n + 1); | ||
166 | for (i = 0; i < argc; i++) { | 159 | for (i = 0; i < argc; i++) { |
167 | lua_pushstring(L, argv[i]); | 160 | lua_pushstring(L, argv[i]); |
168 | lua_rawseti(L, -2, i - n); | 161 | lua_rawseti(L, -2, i - argf); |
169 | } | 162 | } |
170 | return narg; | 163 | lua_setglobal(L, "arg"); |
171 | } | 164 | } |
172 | 165 | ||
173 | static int dofile(lua_State *L, const char *name) | 166 | static int dofile(lua_State *L, const char *name) |
@@ -273,21 +266,30 @@ static void dotty(lua_State *L) | |||
273 | progname = oldprogname; | 266 | progname = oldprogname; |
274 | } | 267 | } |
275 | 268 | ||
276 | static int handle_script(lua_State *L, char **argv, int n) | 269 | static int handle_script(lua_State *L, char **argx) |
277 | { | 270 | { |
278 | int status; | 271 | int status; |
279 | const char *fname; | 272 | const char *fname = argx[0]; |
280 | int narg = getargs(L, argv, n); /* collect arguments */ | 273 | if (strcmp(fname, "-") == 0 && strcmp(argx[-1], "--") != 0) |
281 | lua_setglobal(L, "arg"); | ||
282 | fname = argv[n]; | ||
283 | if (strcmp(fname, "-") == 0 && strcmp(argv[n-1], "--") != 0) | ||
284 | fname = NULL; /* stdin */ | 274 | fname = NULL; /* stdin */ |
285 | status = luaL_loadfile(L, fname); | 275 | status = luaL_loadfile(L, fname); |
286 | lua_insert(L, -(narg+1)); | 276 | if (status == 0) { |
287 | if (status == 0) | 277 | /* Fetch args from arg table. LUA_INIT or -e might have changed them. */ |
278 | int narg = 0; | ||
279 | lua_getglobal(L, "arg"); | ||
280 | if (lua_istable(L, -1)) { | ||
281 | do { | ||
282 | narg++; | ||
283 | lua_rawgeti(L, -narg, narg); | ||
284 | } while (!lua_isnil(L, -1)); | ||
285 | lua_pop(L, 1); | ||
286 | lua_remove(L, -narg); | ||
287 | narg--; | ||
288 | } else { | ||
289 | lua_pop(L, 1); | ||
290 | } | ||
288 | status = docall(L, narg, 0); | 291 | status = docall(L, narg, 0); |
289 | else | 292 | } |
290 | lua_pop(L, narg); | ||
291 | return report(L, status); | 293 | return report(L, status); |
292 | } | 294 | } |
293 | 295 | ||
@@ -384,7 +386,8 @@ static int dobytecode(lua_State *L, char **argv) | |||
384 | } | 386 | } |
385 | for (argv++; *argv != NULL; narg++, argv++) | 387 | for (argv++; *argv != NULL; narg++, argv++) |
386 | lua_pushstring(L, *argv); | 388 | lua_pushstring(L, *argv); |
387 | return report(L, lua_pcall(L, narg, 0, 0)); | 389 | report(L, lua_pcall(L, narg, 0, 0)); |
390 | return 1; | ||
388 | } | 391 | } |
389 | 392 | ||
390 | /* check that argument has no extra characters at the end */ | 393 | /* check that argument has no extra characters at the end */ |
@@ -405,7 +408,7 @@ static int collectargs(char **argv, int *flags) | |||
405 | switch (argv[i][1]) { /* Check option. */ | 408 | switch (argv[i][1]) { /* Check option. */ |
406 | case '-': | 409 | case '-': |
407 | notail(argv[i]); | 410 | notail(argv[i]); |
408 | return (argv[i+1] != NULL ? i+1 : 0); | 411 | return i+1; |
409 | case '\0': | 412 | case '\0': |
410 | return i; | 413 | return i; |
411 | case 'i': | 414 | case 'i': |
@@ -430,23 +433,23 @@ static int collectargs(char **argv, int *flags) | |||
430 | case 'b': /* LuaJIT extension */ | 433 | case 'b': /* LuaJIT extension */ |
431 | if (*flags) return -1; | 434 | if (*flags) return -1; |
432 | *flags |= FLAGS_EXEC; | 435 | *flags |= FLAGS_EXEC; |
433 | return 0; | 436 | return i+1; |
434 | case 'E': | 437 | case 'E': |
435 | *flags |= FLAGS_NOENV; | 438 | *flags |= FLAGS_NOENV; |
436 | break; | 439 | break; |
437 | default: return -1; /* invalid option */ | 440 | default: return -1; /* invalid option */ |
438 | } | 441 | } |
439 | } | 442 | } |
440 | return 0; | 443 | return i; |
441 | } | 444 | } |
442 | 445 | ||
443 | static int runargs(lua_State *L, char **argv, int n) | 446 | static int runargs(lua_State *L, char **argv, int argn) |
444 | { | 447 | { |
445 | int i; | 448 | int i; |
446 | for (i = 1; i < n; i++) { | 449 | for (i = 1; i < argn; i++) { |
447 | if (argv[i] == NULL) continue; | 450 | if (argv[i] == NULL) continue; |
448 | lua_assert(argv[i][0] == '-'); | 451 | lua_assert(argv[i][0] == '-'); |
449 | switch (argv[i][1]) { /* option */ | 452 | switch (argv[i][1]) { |
450 | case 'e': { | 453 | case 'e': { |
451 | const char *chunk = argv[i] + 2; | 454 | const char *chunk = argv[i] + 2; |
452 | if (*chunk == '\0') chunk = argv[++i]; | 455 | if (*chunk == '\0') chunk = argv[++i]; |
@@ -460,10 +463,10 @@ static int runargs(lua_State *L, char **argv, int n) | |||
460 | if (*filename == '\0') filename = argv[++i]; | 463 | if (*filename == '\0') filename = argv[++i]; |
461 | lua_assert(filename != NULL); | 464 | lua_assert(filename != NULL); |
462 | if (dolibrary(L, filename)) | 465 | if (dolibrary(L, filename)) |
463 | return 1; /* stop if file fails */ | 466 | return 1; |
464 | break; | 467 | break; |
465 | } | 468 | } |
466 | case 'j': { /* LuaJIT extension */ | 469 | case 'j': { /* LuaJIT extension. */ |
467 | const char *cmd = argv[i] + 2; | 470 | const char *cmd = argv[i] + 2; |
468 | if (*cmd == '\0') cmd = argv[++i]; | 471 | if (*cmd == '\0') cmd = argv[++i]; |
469 | lua_assert(cmd != NULL); | 472 | lua_assert(cmd != NULL); |
@@ -471,11 +474,11 @@ static int runargs(lua_State *L, char **argv, int n) | |||
471 | return 1; | 474 | return 1; |
472 | break; | 475 | break; |
473 | } | 476 | } |
474 | case 'O': /* LuaJIT extension */ | 477 | case 'O': /* LuaJIT extension. */ |
475 | if (dojitopt(L, argv[i] + 2)) | 478 | if (dojitopt(L, argv[i] + 2)) |
476 | return 1; | 479 | return 1; |
477 | break; | 480 | break; |
478 | case 'b': /* LuaJIT extension */ | 481 | case 'b': /* LuaJIT extension. */ |
479 | return dobytecode(L, argv+i); | 482 | return dobytecode(L, argv+i); |
480 | default: break; | 483 | default: break; |
481 | } | 484 | } |
@@ -508,45 +511,57 @@ static int pmain(lua_State *L) | |||
508 | { | 511 | { |
509 | struct Smain *s = &smain; | 512 | struct Smain *s = &smain; |
510 | char **argv = s->argv; | 513 | char **argv = s->argv; |
511 | int script; | 514 | int argn; |
512 | int flags = 0; | 515 | int flags = 0; |
513 | globalL = L; | 516 | globalL = L; |
514 | if (argv[0] && argv[0][0]) progname = argv[0]; | 517 | if (argv[0] && argv[0][0]) progname = argv[0]; |
515 | LUAJIT_VERSION_SYM(); /* linker-enforced version check */ | 518 | |
516 | script = collectargs(argv, &flags); | 519 | LUAJIT_VERSION_SYM(); /* Linker-enforced version check. */ |
517 | if (script < 0) { /* invalid args? */ | 520 | |
521 | argn = collectargs(argv, &flags); | ||
522 | if (argn < 0) { /* Invalid args? */ | ||
518 | print_usage(); | 523 | print_usage(); |
519 | s->status = 1; | 524 | s->status = 1; |
520 | return 0; | 525 | return 0; |
521 | } | 526 | } |
527 | |||
522 | if ((flags & FLAGS_NOENV)) { | 528 | if ((flags & FLAGS_NOENV)) { |
523 | lua_pushboolean(L, 1); | 529 | lua_pushboolean(L, 1); |
524 | lua_setfield(L, LUA_REGISTRYINDEX, "LUA_NOENV"); | 530 | lua_setfield(L, LUA_REGISTRYINDEX, "LUA_NOENV"); |
525 | } | 531 | } |
526 | lua_gc(L, LUA_GCSTOP, 0); /* stop collector during initialization */ | 532 | |
527 | luaL_openlibs(L); /* open libraries */ | 533 | /* Stop collector during library initialization. */ |
534 | lua_gc(L, LUA_GCSTOP, 0); | ||
535 | luaL_openlibs(L); | ||
528 | lua_gc(L, LUA_GCRESTART, -1); | 536 | lua_gc(L, LUA_GCRESTART, -1); |
537 | |||
538 | createargtable(L, argv, s->argc, argn); | ||
539 | |||
529 | if (!(flags & FLAGS_NOENV)) { | 540 | if (!(flags & FLAGS_NOENV)) { |
530 | s->status = handle_luainit(L); | 541 | s->status = handle_luainit(L); |
531 | if (s->status != 0) return 0; | 542 | if (s->status != 0) return 0; |
532 | } | 543 | } |
544 | |||
533 | if ((flags & FLAGS_VERSION)) print_version(); | 545 | if ((flags & FLAGS_VERSION)) print_version(); |
534 | s->status = runargs(L, argv, (script > 0) ? script : s->argc); | 546 | |
547 | s->status = runargs(L, argv, argn); | ||
535 | if (s->status != 0) return 0; | 548 | if (s->status != 0) return 0; |
536 | if (script) { | 549 | |
537 | s->status = handle_script(L, argv, script); | 550 | if (s->argc > argn) { |
551 | s->status = handle_script(L, argv + argn); | ||
538 | if (s->status != 0) return 0; | 552 | if (s->status != 0) return 0; |
539 | } | 553 | } |
554 | |||
540 | if ((flags & FLAGS_INTERACTIVE)) { | 555 | if ((flags & FLAGS_INTERACTIVE)) { |
541 | print_jit_status(L); | 556 | print_jit_status(L); |
542 | dotty(L); | 557 | dotty(L); |
543 | } else if (script == 0 && !(flags & (FLAGS_EXEC|FLAGS_VERSION))) { | 558 | } else if (s->argc == argn && !(flags & (FLAGS_EXEC|FLAGS_VERSION))) { |
544 | if (lua_stdin_is_tty()) { | 559 | if (lua_stdin_is_tty()) { |
545 | print_version(); | 560 | print_version(); |
546 | print_jit_status(L); | 561 | print_jit_status(L); |
547 | dotty(L); | 562 | dotty(L); |
548 | } else { | 563 | } else { |
549 | dofile(L, NULL); /* executes stdin as a file */ | 564 | dofile(L, NULL); /* Executes stdin as a file. */ |
550 | } | 565 | } |
551 | } | 566 | } |
552 | return 0; | 567 | return 0; |
@@ -555,7 +570,7 @@ static int pmain(lua_State *L) | |||
555 | int main(int argc, char **argv) | 570 | int main(int argc, char **argv) |
556 | { | 571 | { |
557 | int status; | 572 | int status; |
558 | lua_State *L = lua_open(); /* create state */ | 573 | lua_State *L = lua_open(); |
559 | if (L == NULL) { | 574 | if (L == NULL) { |
560 | l_message(argv[0], "cannot create state: not enough memory"); | 575 | l_message(argv[0], "cannot create state: not enough memory"); |
561 | return EXIT_FAILURE; | 576 | return EXIT_FAILURE; |