root/luajit.c

/* [<][>][^][v][top][bottom][index][help] */

DEFINITIONS

This source file includes following definitions.
  1. lstop
  2. laction
  3. print_usage
  4. l_message
  5. report
  6. traceback
  7. docall
  8. print_version
  9. print_jit_status
  10. getargs
  11. dofile
  12. dostring
  13. dolibrary
  14. write_prompt
  15. incomplete
  16. pushline
  17. loadline
  18. dotty
  19. handle_script
  20. loadjitmodule
  21. runcmdopt
  22. dojitcmd
  23. dojitopt
  24. dobytecode
  25. collectargs
  26. runargs
  27. handle_luainit
  28. pmain
  29. main

   1 /*
   2 ** LuaJIT frontend. Runs commands, scripts, read-eval-print (REPL) etc.
   3 ** Copyright (C) 2005-2017 Mike Pall. See Copyright Notice in luajit.h
   4 **
   5 ** Major portions taken verbatim or adapted from the Lua interpreter.
   6 ** Copyright (C) 1994-2008 Lua.org, PUC-Rio. See Copyright Notice in lua.h
   7 */
   8 
   9 #include <stdio.h>
  10 #include <stdlib.h>
  11 #include <string.h>
  12 
  13 #define luajit_c
  14 
  15 #include "lua.h"
  16 #include "lauxlib.h"
  17 #include "lualib.h"
  18 #include "luajit.h"
  19 
  20 #include "lj_arch.h"
  21 
  22 #if LJ_TARGET_POSIX
  23 #include <unistd.h>
  24 #define lua_stdin_is_tty()      isatty(0)
  25 #elif LJ_TARGET_WINDOWS
  26 #include <io.h>
  27 #ifdef __BORLANDC__
  28 #define lua_stdin_is_tty()      isatty(_fileno(stdin))
  29 #else
  30 #define lua_stdin_is_tty()      _isatty(_fileno(stdin))
  31 #endif
  32 #else
  33 #define lua_stdin_is_tty()      1
  34 #endif
  35 
  36 #if !LJ_TARGET_CONSOLE
  37 #include <signal.h>
  38 #endif
  39 
  40 static lua_State *globalL = NULL;
  41 static const char *progname = LUA_PROGNAME;
  42 
  43 #if !LJ_TARGET_CONSOLE
  44 static void lstop(lua_State *L, lua_Debug *ar)
  45 {
  46   (void)ar;  /* unused arg. */
  47   lua_sethook(L, NULL, 0, 0);
  48   /* Avoid luaL_error -- a C hook doesn't add an extra frame. */
  49   luaL_where(L, 0);
  50   lua_pushfstring(L, "%sinterrupted!", lua_tostring(L, -1));
  51   lua_error(L);
  52 }
  53 
  54 static void laction(int i)
  55 {
  56   signal(i, SIG_DFL); /* if another SIGINT happens before lstop,
  57                          terminate process (default action) */
  58   lua_sethook(globalL, lstop, LUA_MASKCALL | LUA_MASKRET | LUA_MASKCOUNT, 1);
  59 }
  60 #endif
  61 
  62 static void print_usage(void)
  63 {
  64   fprintf(stderr,
  65   "usage: %s [options]... [script [args]...].\n"
  66   "Available options are:\n"
  67   "  -e chunk  Execute string " LUA_QL("chunk") ".\n"
  68   "  -l name   Require library " LUA_QL("name") ".\n"
  69   "  -b ...    Save or list bytecode.\n"
  70   "  -j cmd    Perform LuaJIT control command.\n"
  71   "  -O[opt]   Control LuaJIT optimizations.\n"
  72   "  -i        Enter interactive mode after executing " LUA_QL("script") ".\n"
  73   "  -v        Show version information.\n"
  74   "  -E        Ignore environment variables.\n"
  75   "  --        Stop handling options.\n"
  76   "  -         Execute stdin and stop handling options.\n"
  77   ,
  78   progname);
  79   fflush(stderr);
  80 }
  81 
  82 static void l_message(const char *pname, const char *msg)
  83 {
  84   if (pname) fprintf(stderr, "%s: ", pname);
  85   fprintf(stderr, "%s\n", msg);
  86   fflush(stderr);
  87 }
  88 
  89 static int report(lua_State *L, int status)
  90 {
  91   if (status && !lua_isnil(L, -1)) {
  92     const char *msg = lua_tostring(L, -1);
  93     if (msg == NULL) msg = "(error object is not a string)";
  94     l_message(progname, msg);
  95     lua_pop(L, 1);
  96   }
  97   return status;
  98 }
  99 
 100 static int traceback(lua_State *L)
 101 {
 102   if (!lua_isstring(L, 1)) { /* Non-string error object? Try metamethod. */
 103     if (lua_isnoneornil(L, 1) ||
 104         !luaL_callmeta(L, 1, "__tostring") ||
 105         !lua_isstring(L, -1))
 106       return 1;  /* Return non-string error object. */
 107     lua_remove(L, 1);  /* Replace object by result of __tostring metamethod. */
 108   }
 109   luaL_traceback(L, L, lua_tostring(L, 1), 1);
 110   return 1;
 111 }
 112 
 113 static int docall(lua_State *L, int narg, int clear)
 114 {
 115   int status;
 116   int base = lua_gettop(L) - narg;  /* function index */
 117   lua_pushcfunction(L, traceback);  /* push traceback function */
 118   lua_insert(L, base);  /* put it under chunk and args */
 119 #if !LJ_TARGET_CONSOLE
 120   signal(SIGINT, laction);
 121 #endif
 122   status = lua_pcall(L, narg, (clear ? 0 : LUA_MULTRET), base);
 123 #if !LJ_TARGET_CONSOLE
 124   signal(SIGINT, SIG_DFL);
 125 #endif
 126   lua_remove(L, base);  /* remove traceback function */
 127   /* force a complete garbage collection in case of errors */
 128   if (status != 0) lua_gc(L, LUA_GCCOLLECT, 0);
 129   return status;
 130 }
 131 
 132 static void print_version(void)
 133 {
 134   fputs(LUAJIT_VERSION " -- " LUAJIT_COPYRIGHT ". " LUAJIT_URL "\n", stdout);
 135 }
 136 
 137 static void print_jit_status(lua_State *L)
 138 {
 139   int n;
 140   const char *s;
 141   lua_getfield(L, LUA_REGISTRYINDEX, "_LOADED");
 142   lua_getfield(L, -1, "jit");  /* Get jit.* module table. */
 143   lua_remove(L, -2);
 144   lua_getfield(L, -1, "status");
 145   lua_remove(L, -2);
 146   n = lua_gettop(L);
 147   lua_call(L, 0, LUA_MULTRET);
 148   fputs(lua_toboolean(L, n) ? "JIT: ON" : "JIT: OFF", stdout);
 149   for (n++; (s = lua_tostring(L, n)); n++) {
 150     putc(' ', stdout);
 151     fputs(s, stdout);
 152   }
 153   putc('\n', stdout);
 154 }
 155 
 156 static int getargs(lua_State *L, char **argv, int n)
 157 {
 158   int narg;
 159   int i;
 160   int argc = 0;
 161   while (argv[argc]) argc++;  /* count total number of arguments */
 162   narg = argc - (n + 1);  /* number of arguments to the script */
 163   luaL_checkstack(L, narg + 3, "too many arguments to script");
 164   for (i = n+1; i < argc; i++)
 165     lua_pushstring(L, argv[i]);
 166   lua_createtable(L, narg, n + 1);
 167   for (i = 0; i < argc; i++) {
 168     lua_pushstring(L, argv[i]);
 169     lua_rawseti(L, -2, i - n);
 170   }
 171   return narg;
 172 }
 173 
 174 static int dofile(lua_State *L, const char *name)
 175 {
 176   int status = luaL_loadfile(L, name) || docall(L, 0, 1);
 177   return report(L, status);
 178 }
 179 
 180 static int dostring(lua_State *L, const char *s, const char *name)
 181 {
 182   int status = luaL_loadbuffer(L, s, strlen(s), name) || docall(L, 0, 1);
 183   return report(L, status);
 184 }
 185 
 186 static int dolibrary(lua_State *L, const char *name)
 187 {
 188   lua_getglobal(L, "require");
 189   lua_pushstring(L, name);
 190   return report(L, docall(L, 1, 1));
 191 }
 192 
 193 static void write_prompt(lua_State *L, int firstline)
 194 {
 195   const char *p;
 196   lua_getfield(L, LUA_GLOBALSINDEX, firstline ? "_PROMPT" : "_PROMPT2");
 197   p = lua_tostring(L, -1);
 198   if (p == NULL) p = firstline ? LUA_PROMPT : LUA_PROMPT2;
 199   fputs(p, stdout);
 200   fflush(stdout);
 201   lua_pop(L, 1);  /* remove global */
 202 }
 203 
 204 static int incomplete(lua_State *L, int status)
 205 {
 206   if (status == LUA_ERRSYNTAX) {
 207     size_t lmsg;
 208     const char *msg = lua_tolstring(L, -1, &lmsg);
 209     const char *tp = msg + lmsg - (sizeof(LUA_QL("<eof>")) - 1);
 210     if (strstr(msg, LUA_QL("<eof>")) == tp) {
 211       lua_pop(L, 1);
 212       return 1;
 213     }
 214   }
 215   return 0;  /* else... */
 216 }
 217 
 218 static int pushline(lua_State *L, int firstline)
 219 {
 220   char buf[LUA_MAXINPUT];
 221   write_prompt(L, firstline);
 222   if (fgets(buf, LUA_MAXINPUT, stdin)) {
 223     size_t len = strlen(buf);
 224     if (len > 0 && buf[len-1] == '\n')
 225       buf[len-1] = '\0';
 226     if (firstline && buf[0] == '=')
 227       lua_pushfstring(L, "return %s", buf+1);
 228     else
 229       lua_pushstring(L, buf);
 230     return 1;
 231   }
 232   return 0;
 233 }
 234 
 235 static int loadline(lua_State *L)
 236 {
 237   int status;
 238   lua_settop(L, 0);
 239   if (!pushline(L, 1))
 240     return -1;  /* no input */
 241   for (;;) {  /* repeat until gets a complete line */
 242     status = luaL_loadbuffer(L, lua_tostring(L, 1), lua_strlen(L, 1), "=stdin");
 243     if (!incomplete(L, status)) break;  /* cannot try to add lines? */
 244     if (!pushline(L, 0))  /* no more input? */
 245       return -1;
 246     lua_pushliteral(L, "\n");  /* add a new line... */
 247     lua_insert(L, -2);  /* ...between the two lines */
 248     lua_concat(L, 3);  /* join them */
 249   }
 250   lua_remove(L, 1);  /* remove line */
 251   return status;
 252 }
 253 
 254 static void dotty(lua_State *L)
 255 {
 256   int status;
 257   const char *oldprogname = progname;
 258   progname = NULL;
 259   while ((status = loadline(L)) != -1) {
 260     if (status == 0) status = docall(L, 0, 0);
 261     report(L, status);
 262     if (status == 0 && lua_gettop(L) > 0) {  /* any result to print? */
 263       lua_getglobal(L, "print");
 264       lua_insert(L, 1);
 265       if (lua_pcall(L, lua_gettop(L)-1, 0, 0) != 0)
 266         l_message(progname,
 267           lua_pushfstring(L, "error calling " LUA_QL("print") " (%s)",
 268                               lua_tostring(L, -1)));
 269     }
 270   }
 271   lua_settop(L, 0);  /* clear stack */
 272   fputs("\n", stdout);
 273   fflush(stdout);
 274   progname = oldprogname;
 275 }
 276 
 277 static int handle_script(lua_State *L, char **argv, int n)
 278 {
 279   int status;
 280   const char *fname;
 281   int narg = getargs(L, argv, n);  /* collect arguments */
 282   lua_setglobal(L, "arg");
 283   fname = argv[n];
 284   if (strcmp(fname, "-") == 0 && strcmp(argv[n-1], "--") != 0)
 285     fname = NULL;  /* stdin */
 286   status = luaL_loadfile(L, fname);
 287   lua_insert(L, -(narg+1));
 288   if (status == 0)
 289     status = docall(L, narg, 0);
 290   else
 291     lua_pop(L, narg);
 292   return report(L, status);
 293 }
 294 
 295 /* Load add-on module. */
 296 static int loadjitmodule(lua_State *L)
 297 {
 298   lua_getglobal(L, "require");
 299   lua_pushliteral(L, "jit.");
 300   lua_pushvalue(L, -3);
 301   lua_concat(L, 2);
 302   if (lua_pcall(L, 1, 1, 0)) {
 303     const char *msg = lua_tostring(L, -1);
 304     if (msg && !strncmp(msg, "module ", 7))
 305       goto nomodule;
 306     return report(L, 1);
 307   }
 308   lua_getfield(L, -1, "start");
 309   if (lua_isnil(L, -1)) {
 310   nomodule:
 311     l_message(progname,
 312               "unknown luaJIT command or jit.* modules not installed");
 313     return 1;
 314   }
 315   lua_remove(L, -2);  /* Drop module table. */
 316   return 0;
 317 }
 318 
 319 /* Run command with options. */
 320 static int runcmdopt(lua_State *L, const char *opt)
 321 {
 322   int narg = 0;
 323   if (opt && *opt) {
 324     for (;;) {  /* Split arguments. */
 325       const char *p = strchr(opt, ',');
 326       narg++;
 327       if (!p) break;
 328       if (p == opt)
 329         lua_pushnil(L);
 330       else
 331         lua_pushlstring(L, opt, (size_t)(p - opt));
 332       opt = p + 1;
 333     }
 334     if (*opt)
 335       lua_pushstring(L, opt);
 336     else
 337       lua_pushnil(L);
 338   }
 339   return report(L, lua_pcall(L, narg, 0, 0));
 340 }
 341 
 342 /* JIT engine control command: try jit library first or load add-on module. */
 343 static int dojitcmd(lua_State *L, const char *cmd)
 344 {
 345   const char *opt = strchr(cmd, '=');
 346   lua_pushlstring(L, cmd, opt ? (size_t)(opt - cmd) : strlen(cmd));
 347   lua_getfield(L, LUA_REGISTRYINDEX, "_LOADED");
 348   lua_getfield(L, -1, "jit");  /* Get jit.* module table. */
 349   lua_remove(L, -2);
 350   lua_pushvalue(L, -2);
 351   lua_gettable(L, -2);  /* Lookup library function. */
 352   if (!lua_isfunction(L, -1)) {
 353     lua_pop(L, 2);  /* Drop non-function and jit.* table, keep module name. */
 354     if (loadjitmodule(L))
 355       return 1;
 356   } else {
 357     lua_remove(L, -2);  /* Drop jit.* table. */
 358   }
 359   lua_remove(L, -2);  /* Drop module name. */
 360   return runcmdopt(L, opt ? opt+1 : opt);
 361 }
 362 
 363 /* Optimization flags. */
 364 static int dojitopt(lua_State *L, const char *opt)
 365 {
 366   lua_getfield(L, LUA_REGISTRYINDEX, "_LOADED");
 367   lua_getfield(L, -1, "jit.opt");  /* Get jit.opt.* module table. */
 368   lua_remove(L, -2);
 369   lua_getfield(L, -1, "start");
 370   lua_remove(L, -2);
 371   return runcmdopt(L, opt);
 372 }
 373 
 374 /* Save or list bytecode. */
 375 static int dobytecode(lua_State *L, char **argv)
 376 {
 377   int narg = 0;
 378   lua_pushliteral(L, "bcsave");
 379   if (loadjitmodule(L))
 380     return 1;
 381   if (argv[0][2]) {
 382     narg++;
 383     argv[0][1] = '-';
 384     lua_pushstring(L, argv[0]+1);
 385   }
 386   for (argv++; *argv != NULL; narg++, argv++)
 387     lua_pushstring(L, *argv);
 388   return report(L, lua_pcall(L, narg, 0, 0));
 389 }
 390 
 391 /* check that argument has no extra characters at the end */
 392 #define notail(x)       {if ((x)[2] != '\0') return -1;}
 393 
 394 #define FLAGS_INTERACTIVE       1
 395 #define FLAGS_VERSION           2
 396 #define FLAGS_EXEC              4
 397 #define FLAGS_OPTION            8
 398 #define FLAGS_NOENV             16
 399 
 400 static int collectargs(char **argv, int *flags)
 401 {
 402   int i;
 403   for (i = 1; argv[i] != NULL; i++) {
 404     if (argv[i][0] != '-')  /* Not an option? */
 405       return i;
 406     switch (argv[i][1]) {  /* Check option. */
 407     case '-':
 408       notail(argv[i]);
 409       return (argv[i+1] != NULL ? i+1 : 0);
 410     case '\0':
 411       return i;
 412     case 'i':
 413       notail(argv[i]);
 414       *flags |= FLAGS_INTERACTIVE;
 415       /* fallthrough */
 416     case 'v':
 417       notail(argv[i]);
 418       *flags |= FLAGS_VERSION;
 419       break;
 420     case 'e':
 421       *flags |= FLAGS_EXEC;
 422     case 'j':  /* LuaJIT extension */
 423     case 'l':
 424       *flags |= FLAGS_OPTION;
 425       if (argv[i][2] == '\0') {
 426         i++;
 427         if (argv[i] == NULL) return -1;
 428       }
 429       break;
 430     case 'O': break;  /* LuaJIT extension */
 431     case 'b':  /* LuaJIT extension */
 432       if (*flags) return -1;
 433       *flags |= FLAGS_EXEC;
 434       return 0;
 435     case 'E':
 436       *flags |= FLAGS_NOENV;
 437       break;
 438     default: return -1;  /* invalid option */
 439     }
 440   }
 441   return 0;
 442 }
 443 
 444 static int runargs(lua_State *L, char **argv, int n)
 445 {
 446   int i;
 447   for (i = 1; i < n; i++) {
 448     if (argv[i] == NULL) continue;
 449     lua_assert(argv[i][0] == '-');
 450     switch (argv[i][1]) {  /* option */
 451     case 'e': {
 452       const char *chunk = argv[i] + 2;
 453       if (*chunk == '\0') chunk = argv[++i];
 454       lua_assert(chunk != NULL);
 455       if (dostring(L, chunk, "=(command line)") != 0)
 456         return 1;
 457       break;
 458       }
 459     case 'l': {
 460       const char *filename = argv[i] + 2;
 461       if (*filename == '\0') filename = argv[++i];
 462       lua_assert(filename != NULL);
 463       if (dolibrary(L, filename))
 464         return 1;  /* stop if file fails */
 465       break;
 466       }
 467     case 'j': {  /* LuaJIT extension */
 468       const char *cmd = argv[i] + 2;
 469       if (*cmd == '\0') cmd = argv[++i];
 470       lua_assert(cmd != NULL);
 471       if (dojitcmd(L, cmd))
 472         return 1;
 473       break;
 474       }
 475     case 'O':  /* LuaJIT extension */
 476       if (dojitopt(L, argv[i] + 2))
 477         return 1;
 478       break;
 479     case 'b':  /* LuaJIT extension */
 480       return dobytecode(L, argv+i);
 481     default: break;
 482     }
 483   }
 484   return 0;
 485 }
 486 
 487 static int handle_luainit(lua_State *L)
 488 {
 489 #if LJ_TARGET_CONSOLE
 490   const char *init = NULL;
 491 #else
 492   const char *init = getenv(LUA_INIT);
 493 #endif
 494   if (init == NULL)
 495     return 0;  /* status OK */
 496   else if (init[0] == '@')
 497     return dofile(L, init+1);
 498   else
 499     return dostring(L, init, "=" LUA_INIT);
 500 }
 501 
 502 static struct Smain {
 503   char **argv;
 504   int argc;
 505   int status;
 506 } smain;
 507 
 508 static int pmain(lua_State *L)
 509 {
 510   struct Smain *s = &smain;
 511   char **argv = s->argv;
 512   int script;
 513   int flags = 0;
 514   globalL = L;
 515   if (argv[0] && argv[0][0]) progname = argv[0];
 516   LUAJIT_VERSION_SYM();  /* linker-enforced version check */
 517   script = collectargs(argv, &flags);
 518   if (script < 0) {  /* invalid args? */
 519     print_usage();
 520     s->status = 1;
 521     return 0;
 522   }
 523   if ((flags & FLAGS_NOENV)) {
 524     lua_pushboolean(L, 1);
 525     lua_setfield(L, LUA_REGISTRYINDEX, "LUA_NOENV");
 526   }
 527   lua_gc(L, LUA_GCSTOP, 0);  /* stop collector during initialization */
 528   luaL_openlibs(L);  /* open libraries */
 529   lua_gc(L, LUA_GCRESTART, -1);
 530   if (!(flags & FLAGS_NOENV)) {
 531     s->status = handle_luainit(L);
 532     if (s->status != 0) return 0;
 533   }
 534   if ((flags & FLAGS_VERSION)) print_version();
 535   s->status = runargs(L, argv, (script > 0) ? script : s->argc);
 536   if (s->status != 0) return 0;
 537   if (script) {
 538     s->status = handle_script(L, argv, script);
 539     if (s->status != 0) return 0;
 540   }
 541   if ((flags & FLAGS_INTERACTIVE)) {
 542     print_jit_status(L);
 543     dotty(L);
 544   } else if (script == 0 && !(flags & (FLAGS_EXEC|FLAGS_VERSION))) {
 545     if (lua_stdin_is_tty()) {
 546       print_version();
 547       print_jit_status(L);
 548       dotty(L);
 549     } else {
 550       dofile(L, NULL);  /* executes stdin as a file */
 551     }
 552   }
 553   return 0;
 554 }
 555 
 556 int main(int argc, char **argv)
 557 {
 558   int status;
 559   lua_State *L = lua_open();  /* create state */
 560   if (L == NULL) {
 561     l_message(argv[0], "cannot create state: not enough memory");
 562     return EXIT_FAILURE;
 563   }
 564   smain.argc = argc;
 565   smain.argv = argv;
 566   status = lua_cpcall(L, pmain, NULL);
 567   report(L, status);
 568   lua_close(L);
 569   return (status || smain.status) ? EXIT_FAILURE : EXIT_SUCCESS;
 570 }
 571 

/* [<][>][^][v][top][bottom][index][help] */