luajit.c (23190B)
1 /* 2 ** LuaJIT frontend. Runs commands, scripts, read-eval-print (REPL) etc. 3 ** Copyright (C) 2005-2016 Mike Pall. See Copyright Notice in luajit.h 4 ** 5 ** Advanced readline support for the GNU readline and history 6 ** libraries or compatible replacements taken from Mike's Lua patch. 7 ** 8 ** Major portions taken verbatim or adapted from the Lua interpreter. 9 ** Copyright (C) 1994-2008 Lua.org, PUC-Rio. See Copyright Notice in lua.h 10 */ 11 12 13 #include <stdio.h> 14 #include <stdlib.h> 15 #include <string.h> 16 17 #define luajit_c 18 19 #include "lua.h" 20 #include "lauxlib.h" 21 #include "lualib.h" 22 #include "luajit.h" 23 24 #include "lj_arch.h" 25 #include "lj_char.h" 26 27 #include <unistd.h> 28 29 #if !defined(lua_readline) 30 #if defined(LUA_USE_READLINE) 31 #include <readline/readline.h> 32 #include <readline/history.h> 33 #include <ctype.h> 34 #define lua_readline(L,b,p) ((void)L, ((b)=readline(p)) != NULL) 35 #define lua_saveline(L,idx) \ 36 if (lua_rawlen(L,idx) > 0) /* non-empty line? */ \ 37 add_history(lua_tostring(L, idx)); /* add it to history */ 38 #define lua_freeline(L,b) ((void)L, free(b)) 39 40 static char *lua_rl_hist; 41 static int lua_rl_histsize; 42 static lua_State *lua_rl_L; /* User data is not passed to rl callbacks. */ 43 44 /* Reserved keywords. */ 45 static const char *const lua_rl_keywords[] = { 46 "and", "break", "do", "else", "elseif", "end", "false", 47 "for", "function", "goto", "if", "in", "local", "nil", "not", "or", 48 "repeat", "return", "then", "true", "until", "while", NULL 49 }; 50 51 static int valididentifier(const char *s) 52 { 53 if (!(isalpha((int)*s) || *s == '_')) return 0; 54 for (s++; *s; s++) if (!(isalpha((int)*s) || isdigit((int)*s) || *s == '_')) return 0; 55 return 1; 56 } 57 58 /* Dynamically resizable match list. */ 59 typedef struct { 60 char **list; 61 size_t idx, allocated, matchlen; 62 } dmlist; 63 64 /* Add prefix + string + suffix to list and compute common prefix. */ 65 static int lua_rl_dmadd(dmlist *ml, const char *p, size_t pn, const char *s, 66 int suf) 67 { 68 char *t = NULL; 69 70 if (ml->idx+1 >= ml->allocated && 71 !(ml->list = realloc(ml->list, sizeof(char *)*(ml->allocated += 32)))) 72 return -1; 73 74 if (s) { 75 size_t n = strlen(s); 76 if (!(t = (char *)malloc(sizeof(char)*(pn+n+(suf?2:1))))) return 1; 77 memcpy(t, p, pn); 78 memcpy(t+pn, s, n); 79 n += pn; 80 t[n] = suf; 81 if (suf) t[++n] = '\0'; 82 83 if (ml->idx == 0) { 84 ml->matchlen = n; 85 } else { 86 size_t i; 87 for (i = 0; i < ml->matchlen && i < n && ml->list[1][i] == t[i]; i++) ; 88 ml->matchlen = i; /* Set matchlen to common prefix. */ 89 } 90 } 91 92 ml->list[++ml->idx] = t; 93 return 0; 94 } 95 96 /* Get __index field of metatable of object on top of stack. */ 97 static int lua_rl_getmetaindex(lua_State *L) 98 { 99 if (!lua_getmetatable(L, -1)) { lua_pop(L, 1); return 0; } 100 lua_pushstring(L, "__index"); 101 lua_rawget(L, -2); 102 lua_replace(L, -2); 103 if (lua_isnil(L, -1) || lua_rawequal(L, -1, -2)) { lua_pop(L, 2); return 0; } 104 lua_replace(L, -2); 105 return 1; 106 } /* 1: obj -- val, 0: obj -- */ 107 108 /* Get field from object on top of stack. Avoid calling metamethods. */ 109 static int lua_rl_getfield(lua_State *L, const char *s, size_t n) 110 { 111 int i = 20; /* Avoid infinite metatable loops. */ 112 do { 113 if (lua_istable(L, -1)) { 114 lua_pushlstring(L, s, n); 115 lua_rawget(L, -2); 116 if (!lua_isnil(L, -1)) { lua_replace(L, -2); return 1; } 117 lua_pop(L, 1); 118 } 119 } while (--i > 0 && lua_rl_getmetaindex(L)); 120 lua_pop(L, 1); 121 return 0; 122 } /* 1: obj -- val, 0: obj -- */ 123 124 /* Completion callback. */ 125 static char **lua_rl_complete(const char *text, int start, int end) 126 { 127 lua_State *L = lua_rl_L; 128 dmlist ml; 129 const char *s; 130 size_t i, n, dot, loop; 131 int savetop; 132 133 if (!(text[0] == '\0' || isalpha((int)text[0]) || text[0] == '_')) return NULL; 134 135 ml.list = NULL; 136 ml.idx = ml.allocated = ml.matchlen = 0; 137 138 savetop = lua_gettop(L); 139 lua_pushglobaltable(L); 140 for (n = (size_t)(end-start), i = dot = 0; i < n; i++) 141 if (text[i] == '.' || text[i] == ':') { 142 if (!lua_rl_getfield(L, text+dot, i-dot)) 143 goto error; /* Invalid prefix. */ 144 dot = i+1; /* Points to first char after dot/colon. */ 145 } 146 147 /* Add all matches against keywords if there is no dot/colon. */ 148 if (dot == 0) 149 for (i = 0; (s = lua_rl_keywords[i]) != NULL; i++) 150 if (!strncmp(s, text, n) && lua_rl_dmadd(&ml, NULL, 0, s, ' ')) 151 goto error; 152 153 /* Add all valid matches from all tables/metatables. */ 154 loop = 0; /* Avoid infinite metatable loops. */ 155 lua_pushglobaltable(L); 156 lua_insert(L, -2); 157 do { 158 if (lua_istable(L, -1) && 159 (loop == 0 || !lua_rawequal(L, -1, -2))) 160 for (lua_pushnil(L); lua_next(L, -2); lua_pop(L, 1)) 161 if (lua_type(L, -2) == LUA_TSTRING) { 162 s = lua_tostring(L, -2); 163 /* Only match names starting with '_' if explicitly requested. */ 164 if (!strncmp(s, text+dot, n-dot) && valididentifier(s) && 165 (*s != '_' || text[dot] == '_')) { 166 int suf = ' '; /* Default suffix is a space. */ 167 switch (lua_type(L, -1)) { 168 case LUA_TTABLE: suf = '.'; break; /* No way to guess ':'. */ 169 case LUA_TFUNCTION: suf = '('; break; 170 case LUA_TUSERDATA: 171 if (lua_getmetatable(L, -1)) { lua_pop(L, 1); suf = ':'; } 172 break; 173 } 174 if (lua_rl_dmadd(&ml, text, dot, s, suf)) goto error; 175 } 176 } 177 } while (++loop < 20 && lua_rl_getmetaindex(L)); 178 lua_pop(L, 1); 179 180 if (ml.idx == 0) { 181 error: 182 lua_settop(L, savetop); 183 return NULL; 184 } else { 185 /* list[0] holds the common prefix of all matches (may be ""). */ 186 /* If there is only one match, list[0] and list[1] will be the same. */ 187 if (!(ml.list[0] = (char *)malloc(sizeof(char)*(ml.matchlen+1)))) 188 goto error; 189 memcpy(ml.list[0], ml.list[1], ml.matchlen); 190 ml.list[0][ml.matchlen] = '\0'; 191 /* Add the NULL list terminator. */ 192 if (lua_rl_dmadd(&ml, NULL, 0, NULL, 0)) goto error; 193 } 194 195 lua_settop(L, savetop); 196 #if RL_READLINE_VERSION >= 0x0600 197 rl_completion_suppress_append = 1; 198 #endif 199 return ml.list; 200 } 201 202 /* Initialize readline library. */ 203 static void lua_rl_init(lua_State *L) 204 { 205 char *s; 206 207 lua_rl_L = L; 208 209 /* This allows for $if lua ... $endif in ~/.inputrc. */ 210 rl_readline_name = "lua"; 211 /* Break words at every non-identifier character except '.' and ':'. */ 212 rl_completer_word_break_characters = 213 "\t\r\n !\"#$%&'()*+,-/;<=>?@[\\]^`{|}~"; 214 rl_completer_quote_characters = "\"'"; 215 #if RL_READLINE_VERSION < 0x0600 216 rl_completion_append_character = '\0'; 217 #endif 218 rl_attempted_completion_function = lua_rl_complete; 219 rl_initialize(); 220 221 /* Start using history, optionally set history size and load history file. */ 222 using_history(); 223 if ((s = getenv("LUA_HISTSIZE")) && 224 (lua_rl_histsize = atoi(s))) stifle_history(lua_rl_histsize); 225 if ((lua_rl_hist = getenv("LUA_HISTORY"))) read_history(lua_rl_hist); 226 } 227 228 /* Finalize readline library. */ 229 static void lua_rl_exit(lua_State *L) 230 { 231 (void)L; /* Avoid 'unused parameter' warning. */ 232 /* Optionally save history file. */ 233 if (lua_rl_hist) write_history(lua_rl_hist); 234 } 235 #else 236 /* ------------------------------------------------------------------------ */ 237 #define lua_rl_init(L) ((void)L) 238 #define lua_rl_exit(L) ((void)L) 239 240 #define lua_readline(L,b,p) \ 241 ((void)L, fputs(p, stdout), fflush(stdout), /* show prompt */ \ 242 fgets(b, LUA_MAXINPUT, stdin) != NULL) /* get line */ 243 #define lua_saveline(L,idx) { (void)L; (void)idx; } 244 #define lua_freeline(L,b) { (void)L; (void)b; } 245 #endif 246 #endif 247 248 #if LJ_TARGET_POSIX 249 #define lua_stdin_is_tty() isatty(0) 250 #elif LJ_TARGET_WINDOWS 251 #include <io.h> 252 #ifdef __BORLANDC__ 253 #define lua_stdin_is_tty() isatty(_fileno(stdin)) 254 #else 255 #define lua_stdin_is_tty() _isatty(_fileno(stdin)) 256 #endif 257 #else 258 #define lua_stdin_is_tty() 1 259 #endif 260 261 #if !LJ_TARGET_CONSOLE 262 #include <signal.h> 263 #endif 264 265 static lua_State *globalL = NULL; 266 static const char *progname = LUA_PROGNAME; 267 268 #if !LJ_TARGET_CONSOLE 269 static void lstop(lua_State *L, lua_Debug *ar) 270 { 271 (void)ar; /* unused arg. */ 272 lua_sethook(L, NULL, 0, 0); 273 /* Avoid luaL_error -- a C hook doesn't add an extra frame. */ 274 luaL_where(L, 0); 275 lua_pushfstring(L, "%sinterrupted!", lua_tostring(L, -1)); 276 lua_error(L); 277 } 278 279 static void laction(int i) 280 { 281 signal(i, SIG_DFL); /* if another SIGINT happens before lstop, 282 terminate process (default action) */ 283 lua_sethook(globalL, lstop, LUA_MASKCALL | LUA_MASKRET | LUA_MASKCOUNT, 1); 284 } 285 #endif 286 287 static void print_usage(void) 288 { 289 fputs("usage: ", stderr); 290 fputs(progname, stderr); 291 fputs(" [options]... [script [args]...].\n" 292 "Available options are:\n" 293 " -e chunk Execute string " LUA_QL("chunk") ".\n" 294 " -l name Require library " LUA_QL("name") ".\n" 295 " -b ... Save or list bytecode.\n" 296 " -j cmd Perform LuaJIT control command.\n" 297 " -O[opt] Control LuaJIT optimizations.\n" 298 " -i Enter interactive mode after executing " LUA_QL("script") ".\n" 299 " -v Show version information.\n" 300 " -E Ignore environment variables.\n" 301 " -- Stop handling options.\n" 302 " - Execute stdin and stop handling options.\n", stderr); 303 fflush(stderr); 304 } 305 306 static void l_message(const char *pname, const char *msg) 307 { 308 if (pname) { fputs(pname, stderr); fputc(':', stderr); fputc(' ', stderr); } 309 fputs(msg, stderr); fputc('\n', stderr); 310 fflush(stderr); 311 } 312 313 static int report(lua_State *L, int status) 314 { 315 if (status && !lua_isnil(L, -1)) { 316 const char *msg = lua_tostring(L, -1); 317 if (msg == NULL) msg = "(error object is not a string)"; 318 l_message(progname, msg); 319 lua_pop(L, 1); 320 } 321 return status; 322 } 323 324 static int traceback (lua_State *L) { 325 const char *msg = lua_tostring(L, 1); 326 if (msg) 327 luaL_traceback(L, L, msg, 1); 328 else if (!lua_isnoneornil(L, 1)) { /* is there an error object? */ 329 if (!luaL_callmeta(L, 1, "__tostring")) /* try its 'tostring' metamethod */ 330 lua_pushliteral(L, "(no error message)"); 331 } 332 return 1; 333 } 334 335 static int docall(lua_State *L, int narg, int nres) 336 { 337 int status; 338 int base = lua_gettop(L) - narg; /* function index */ 339 lua_pushcfunction(L, traceback); /* push traceback function */ 340 lua_insert(L, base); /* put it under chunk and args */ 341 #if !LJ_TARGET_CONSOLE 342 signal(SIGINT, laction); 343 #endif 344 status = lua_pcall(L, narg, nres, base); 345 #if !LJ_TARGET_CONSOLE 346 signal(SIGINT, SIG_DFL); 347 #endif 348 lua_remove(L, base); /* remove traceback function */ 349 /* force a complete garbage collection in case of errors */ 350 if (status != 0) lua_gc(L, LUA_GCCOLLECT, 0); 351 return status; 352 } 353 354 static void print_jit_status(lua_State *L) 355 { 356 int n; 357 const char *s; 358 lua_getfield(L, LUA_REGISTRYINDEX, "_LOADED"); 359 lua_getfield(L, -1, "jit"); /* Get jit.* module table. */ 360 lua_remove(L, -2); 361 lua_getfield(L, -1, "status"); 362 lua_remove(L, -2); 363 n = lua_gettop(L); 364 lua_call(L, 0, LUA_MULTRET); 365 fputs(lua_toboolean(L, n) ? "JIT: ON" : "JIT: OFF", stdout); 366 for (n++; (s = lua_tostring(L, n)); n++) { 367 putc(' ', stdout); 368 fputs(s, stdout); 369 } 370 putc('\n', stdout); 371 } 372 373 static void print_version(lua_State *L, int jit) 374 { 375 #ifndef LUAJIT_PRETEND_RIO 376 fputs(LJX_VERSION 377 ", type _COPYRIGHTS, _CREDITS, _VERSION for more info.\n", stdout); 378 fputs(LUA_VERSION ", ABI: " LUA_ABIVER_STRING 379 " on " LJ_OS_NAME "/" LJ_ARCH_NAME 380 #if LJ_4GB 381 "/4GB heap" 382 #elif LJ_GC64 383 "/GC64" 384 #endif 385 , stdout); 386 #ifdef __DATE__ 387 fputs(", built " __DATE__, stdout); 388 #endif 389 #ifdef __VERSION__ 390 fputs(" using GCC " __VERSION__ "\n", stdout); 391 #else 392 fputs("\n", stdout); 393 #endif 394 if (jit) print_jit_status(L); 395 #else 396 fputs(LUA_RELEASE " " LUA_COPYRIGHT"\n", stdout); 397 #endif 398 /* These are defined only in interactive session. */ 399 lua_pushliteral(L, LUA_COPYRIGHTS); 400 lua_setglobal(L, "_COPYRIGHTS"); 401 lua_pushliteral(L, LUA_CREDITS); 402 lua_setglobal(L, "_CREDITS"); 403 } 404 405 static int getargs(lua_State *L, char **argv, int n) 406 { 407 int narg; 408 int i; 409 int argc = 0; 410 while (argv[argc]) argc++; /* count total number of arguments */ 411 narg = argc - (n + 1); /* number of arguments to the script */ 412 luaL_checkstack(L, narg + 3, "too many arguments to script"); 413 for (i = n+1; i < argc; i++) 414 lua_pushstring(L, argv[i]); 415 lua_createtable(L, narg, n + 1); 416 for (i = 0; i < argc; i++) { 417 lua_pushstring(L, argv[i]); 418 lua_rawseti(L, -2, i - n); 419 } 420 return narg; 421 } 422 423 static int dofile(lua_State *L, const char *name) 424 { 425 int status = luaL_loadfile(L, name) || docall(L, 0, 0); 426 return report(L, status); 427 } 428 429 static int dostring(lua_State *L, const char *s, const char *name) 430 { 431 int status = luaL_loadbuffer(L, s, strlen(s), name) || docall(L, 0, 0); 432 return report(L, status); 433 } 434 435 static int dolibrary(lua_State *L, const char *name) 436 { 437 int status; 438 lua_getglobal(L, "require"); 439 lua_pushstring(L, name); 440 status = docall(L, 1, 1); /* call 'require(name)' */ 441 if (status == LUA_OK) 442 lua_setglobal(L, name); /* global[name] = require return */ 443 return report(L, status); 444 } 445 446 static const char *get_prompt(lua_State *L, int firstline) 447 { 448 const char *p; 449 lua_getfield(L, LUA_GLOBALSINDEX, firstline ? "_PROMPT" : "_PROMPT2"); 450 p = lua_tostring(L, -1); 451 if (p == NULL) p = firstline ? LUA_PROMPT : LUA_PROMPT2; 452 return p; 453 } 454 455 static int incomplete(lua_State *L, int status) 456 { 457 if (status == LUA_ERRSYNTAX) { 458 size_t lmsg; 459 const char *msg = lua_tolstring(L, -1, &lmsg); 460 const char *tp = msg + lmsg - (sizeof(LUA_QL("<eof>")) - 1); 461 if (strstr(msg, LUA_QL("<eof>")) == tp) { 462 lua_pop(L, 1); 463 return 1; 464 } 465 } 466 return 0; /* else... */ 467 } 468 469 static int pushline(lua_State *L, int firstline) 470 { 471 char buffer[LUA_MAXINPUT]; 472 char *buf = buffer; 473 size_t len; 474 const char *prmt = get_prompt(L, firstline); 475 if (lua_readline(L, buf, prmt)) { 476 lua_pop(L, 1); /* prompt */ 477 len = strlen(buf); 478 if (len > 0 && buf[len-1] == '\n') 479 buf[len-1] = '\0'; 480 if (firstline && buf[0] == '=') 481 lua_pushfstring(L, "return %s", buf+1); 482 else 483 lua_pushstring(L, buf); 484 return 1; 485 } 486 return 0; 487 } 488 489 static int addreturn (lua_State *L) { 490 int status; 491 size_t len; const char *line; 492 lua_pushliteral(L, "return "); 493 lua_pushvalue(L, -2); /* duplicate line */ 494 lua_concat(L, 2); /* new line is "return ..." */ 495 line = lua_tolstring(L, -1, &len); 496 if ((status = luaL_loadbuffer(L, line, len, "=stdin")) == LUA_OK) 497 lua_remove(L, -3); /* remove original line */ 498 else 499 lua_pop(L, 2); /* remove result from 'luaL_loadbuffer' and new line */ 500 return status; 501 } 502 503 static int loadline(lua_State *L) 504 { 505 int status; 506 lua_settop(L, 0); 507 if (!pushline(L, 1)) 508 return -1; /* no input */ 509 if ((status = addreturn(L)) != LUA_OK) for (;;) { /* repeat until gets a complete line */ 510 status = luaL_loadbuffer(L, lua_tostring(L, 1), lua_strlen(L, 1), "=stdin"); 511 if (!incomplete(L, status)) break; /* cannot try to add lines? */ 512 if (!pushline(L, 0)) /* no more input? */ 513 return -1; 514 lua_pushliteral(L, "\n"); /* add a new line... */ 515 lua_insert(L, -2); /* ...between the two lines */ 516 lua_concat(L, 3); /* join them */ 517 } 518 lua_saveline(L, 1); 519 lua_remove(L, 1); /* remove line */ 520 return status; 521 } 522 523 static void dotty(lua_State *L) 524 { 525 int status; 526 const char *oldprogname = progname; 527 progname = NULL; 528 lua_rl_init(L); 529 while ((status = loadline(L)) != -1) { 530 if (status == 0) status = docall(L, 0, LUA_MULTRET); 531 report(L, status); 532 if (status == 0 && lua_gettop(L) > 0) { /* any result to print? */ 533 lua_getglobal(L, "print"); 534 lua_insert(L, 1); 535 if (lua_pcall(L, lua_gettop(L)-1, 0, 0) != 0) 536 l_message(progname, 537 lua_pushfstring(L, "error calling " LUA_QL("print") " (%s)", 538 lua_tostring(L, -1))); 539 } 540 } 541 lua_settop(L, 0); /* clear stack */ 542 fputs("\n", stdout); 543 fflush(stdout); 544 lua_rl_exit(L); 545 progname = oldprogname; 546 } 547 548 static int handle_script(lua_State *L, char **argv, int n) 549 { 550 int status; 551 const char *fname; 552 int narg = getargs(L, argv, n); /* collect arguments */ 553 lua_setglobal(L, "arg"); 554 fname = argv[n]; 555 if (strcmp(fname, "-") == 0 && strcmp(argv[n-1], "--") != 0) 556 fname = NULL; /* stdin */ 557 status = luaL_loadfile(L, fname); 558 lua_insert(L, -(narg+1)); 559 if (status == 0) 560 status = docall(L, narg, LUA_MULTRET); 561 else 562 lua_pop(L, narg); 563 return report(L, status); 564 } 565 566 /* Load add-on module. */ 567 static int loadjitmodule(lua_State *L) 568 { 569 lua_getglobal(L, "require"); 570 lua_pushliteral(L, "jit."); 571 lua_pushvalue(L, -3); 572 lua_concat(L, 2); 573 if (lua_pcall(L, 1, 1, 0)) { 574 const char *msg = lua_tostring(L, -1); 575 if (msg && !strncmp(msg, "module ", 7)) 576 goto nomodule; 577 return report(L, 1); 578 } 579 lua_getfield(L, -1, "start"); 580 if (lua_isnil(L, -1)) { 581 nomodule: 582 l_message(progname, 583 "unknown luaJIT command or jit.* modules not installed"); 584 return 1; 585 } 586 lua_remove(L, -2); /* Drop module table. */ 587 return 0; 588 } 589 590 /* Run command with options. */ 591 static int runcmdopt(lua_State *L, const char *opt) 592 { 593 int narg = 0; 594 if (opt && *opt) { 595 for (;;) { /* Split arguments. */ 596 const char *p = strchr(opt, ','); 597 narg++; 598 if (!p) break; 599 if (p == opt) 600 lua_pushnil(L); 601 else 602 lua_pushlstring(L, opt, (size_t)(p - opt)); 603 opt = p + 1; 604 } 605 if (*opt) 606 lua_pushstring(L, opt); 607 else 608 lua_pushnil(L); 609 } 610 return report(L, lua_pcall(L, narg, 0, 0)); 611 } 612 613 /* JIT engine control command: try jit library first or load add-on module. */ 614 static int dojitcmd(lua_State *L, const char *cmd) 615 { 616 const char *opt = strchr(cmd, '='); 617 lua_pushlstring(L, cmd, opt ? (size_t)(opt - cmd) : strlen(cmd)); 618 lua_getfield(L, LUA_REGISTRYINDEX, "_LOADED"); 619 lua_getfield(L, -1, "jit"); /* Get jit.* module table. */ 620 lua_remove(L, -2); 621 lua_pushvalue(L, -2); 622 lua_gettable(L, -2); /* Lookup library function. */ 623 if (!lua_isfunction(L, -1)) { 624 lua_pop(L, 2); /* Drop non-function and jit.* table, keep module name. */ 625 if (loadjitmodule(L)) 626 return 1; 627 } else { 628 lua_remove(L, -2); /* Drop jit.* table. */ 629 } 630 lua_remove(L, -2); /* Drop module name. */ 631 return runcmdopt(L, opt ? opt+1 : opt); 632 } 633 634 /* Optimization flags. */ 635 static int dojitopt(lua_State *L, const char *opt) 636 { 637 lua_getfield(L, LUA_REGISTRYINDEX, "_LOADED"); 638 lua_getfield(L, -1, "jit.opt"); /* Get jit.opt.* module table. */ 639 lua_remove(L, -2); 640 lua_getfield(L, -1, "start"); 641 lua_remove(L, -2); 642 return runcmdopt(L, opt); 643 } 644 645 /* Save or list bytecode. */ 646 static int dobytecode(lua_State *L, char **argv) 647 { 648 int narg = 0; 649 lua_pushliteral(L, "bcsave"); 650 if (loadjitmodule(L)) 651 return 1; 652 if (argv[0][2]) { 653 narg++; 654 argv[0][1] = '-'; 655 lua_pushstring(L, argv[0]+1); 656 } 657 for (argv++; *argv != NULL; narg++, argv++) 658 lua_pushstring(L, *argv); 659 return report(L, lua_pcall(L, narg, 0, 0)); 660 } 661 662 /* check that argument has no extra characters at the end */ 663 #define notail(x) {if ((x)[2] != '\0') return -1;} 664 665 #define FLAGS_INTERACTIVE 1 666 #define FLAGS_VERSION 2 667 #define FLAGS_EXEC 4 668 #define FLAGS_OPTION 8 669 #define FLAGS_NOENV 16 670 671 static int collectargs(char **argv, int *flags) 672 { 673 int i; 674 for (i = 1; argv[i] != NULL; i++) { 675 if (argv[i][0] != '-') /* Not an option? */ 676 return i; 677 switch (argv[i][1]) { /* Check option. */ 678 case '-': 679 notail(argv[i]); 680 return (argv[i+1] != NULL ? i+1 : 0); 681 case '\0': 682 return i; 683 case 'i': 684 notail(argv[i]); 685 *flags |= FLAGS_INTERACTIVE; 686 /* fallthrough */ 687 case 'v': 688 notail(argv[i]); 689 *flags |= FLAGS_VERSION; 690 break; 691 case 'e': 692 *flags |= FLAGS_EXEC; 693 case 'j': /* LuaJIT extension */ 694 case 'l': 695 *flags |= FLAGS_OPTION; 696 if (argv[i][2] == '\0') { 697 i++; 698 if (argv[i] == NULL) return -1; 699 } 700 break; 701 case 'O': break; /* LuaJIT extension */ 702 case 'b': /* LuaJIT extension */ 703 if (*flags) return -1; 704 *flags |= FLAGS_EXEC; 705 return 0; 706 case 'E': 707 *flags |= FLAGS_NOENV; 708 break; 709 default: return -1; /* invalid option */ 710 } 711 } 712 return 0; 713 } 714 715 static int runargs(lua_State *L, char **argv, int n) 716 { 717 int i; 718 for (i = 1; i < n; i++) { 719 if (argv[i] == NULL) continue; 720 lua_assert(argv[i][0] == '-'); 721 switch (argv[i][1]) { /* option */ 722 case 'e': { 723 const char *chunk = argv[i] + 2; 724 if (*chunk == '\0') chunk = argv[++i]; 725 lua_assert(chunk != NULL); 726 if (dostring(L, chunk, "=(command line)") != 0) 727 return 1; 728 break; 729 } 730 case 'l': { 731 const char *filename = argv[i] + 2; 732 if (*filename == '\0') filename = argv[++i]; 733 lua_assert(filename != NULL); 734 if (dolibrary(L, filename)) 735 return 1; /* stop if file fails */ 736 break; 737 } 738 case 'j': { /* LuaJIT extension */ 739 const char *cmd = argv[i] + 2; 740 if (*cmd == '\0') cmd = argv[++i]; 741 lua_assert(cmd != NULL); 742 if (dojitcmd(L, cmd)) 743 return 1; 744 break; 745 } 746 case 'O': /* LuaJIT extension */ 747 if (dojitopt(L, argv[i] + 2)) 748 return 1; 749 break; 750 case 'b': /* LuaJIT extension */ 751 return dobytecode(L, argv+i); 752 default: break; 753 } 754 } 755 return 0; 756 } 757 758 static int handle_luainit(lua_State *L) 759 { 760 #if LJ_TARGET_CONSOLE 761 const char *init = NULL; 762 #else 763 const char *init = getenv(LUA_INIT_5_2); 764 if (!init) 765 init = getenv(LUA_INIT); 766 #endif 767 if (init == NULL) 768 return 0; /* status OK */ 769 else if (init[0] == '@') 770 return dofile(L, init+1); 771 else 772 return dostring(L, init, "=" LUA_INIT); 773 } 774 775 static struct Smain { 776 char **argv; 777 int argc; 778 int status; 779 } smain; 780 781 static int pmain(lua_State *L) 782 { 783 struct Smain *s = &smain; 784 char **argv = s->argv; 785 int script; 786 int flags = 0; 787 globalL = L; 788 if (argv[0] && argv[0][0]) progname = argv[0]; 789 LUAJIT_VERSION_SYM(); /* linker-enforced version check */ 790 script = collectargs(argv, &flags); 791 if (script < 0) { /* invalid args? */ 792 print_usage(); 793 s->status = 1; 794 return 0; 795 } 796 if ((flags & FLAGS_NOENV)) { 797 lua_pushboolean(L, 1); 798 lua_setfield(L, LUA_REGISTRYINDEX, "LUA_NOENV"); 799 } 800 lua_gc(L, LUA_GCSTOP, 0); /* stop collector during initialization */ 801 luaL_openlibs(L); /* open libraries */ 802 lua_gc(L, LUA_GCRESTART, -1); 803 if (!(flags & FLAGS_NOENV)) { 804 s->status = handle_luainit(L); 805 if (s->status != 0) return 0; 806 } 807 if ((flags & FLAGS_VERSION)) fputs(LUA_COPYRIGHTS, stdout); 808 s->status = runargs(L, argv, (script > 0) ? script : s->argc); 809 if (s->status != 0) return 0; 810 if (script) { 811 s->status = handle_script(L, argv, script); 812 if (s->status != 0) return 0; 813 } 814 if ((flags & FLAGS_INTERACTIVE)) { 815 print_jit_status(L); 816 dotty(L); 817 } else if (script == 0 && !(flags & (FLAGS_EXEC|FLAGS_VERSION))) { 818 if (lua_stdin_is_tty()) { 819 print_version(L, 1); 820 dotty(L); 821 } else { 822 dofile(L, NULL); /* executes stdin as a file */ 823 } 824 } 825 return 0; 826 } 827 828 int main(int argc, char **argv) 829 { 830 int status; 831 lua_State *L = lua_open(); /* create state */ 832 if (L == NULL) { 833 l_message(argv[0], "cannot create state: not enough memory"); 834 return EXIT_FAILURE; 835 } 836 smain.argc = argc; 837 smain.argv = argv; 838 status = lua_cpcall(L, pmain, NULL); 839 report(L, status); 840 lua_close(L); 841 return (status || smain.status) ? EXIT_FAILURE : EXIT_SUCCESS; 842 } 843