Home | History | Annotate | Download | only in src
      1 /*
      2 ** $Id: lua.c,v 1.206.1.1 2013/04/12 18:48:47 roberto Exp $
      3 ** Lua stand-alone interpreter
      4 ** See Copyright Notice in lua.h
      5 */
      6 
      7 
      8 #include <signal.h>
      9 #include <stdio.h>
     10 #include <stdlib.h>
     11 #include <string.h>
     12 
     13 #define lua_c
     14 
     15 #include "lua.h"
     16 
     17 #include "lauxlib.h"
     18 #include "lualib.h"
     19 
     20 
     21 #if !defined(LUA_PROMPT)
     22 #define LUA_PROMPT		"> "
     23 #define LUA_PROMPT2		">> "
     24 #endif
     25 
     26 #if !defined(LUA_PROGNAME)
     27 #define LUA_PROGNAME		"lua"
     28 #endif
     29 
     30 #if !defined(LUA_MAXINPUT)
     31 #define LUA_MAXINPUT		512
     32 #endif
     33 
     34 #if !defined(LUA_INIT)
     35 #define LUA_INIT		"LUA_INIT"
     36 #endif
     37 
     38 #define LUA_INITVERSION  \
     39 	LUA_INIT "_" LUA_VERSION_MAJOR "_" LUA_VERSION_MINOR
     40 
     41 
     42 /*
     43 ** lua_stdin_is_tty detects whether the standard input is a 'tty' (that
     44 ** is, whether we're running lua interactively).
     45 */
     46 #if defined(LUA_USE_ISATTY)
     47 #include <unistd.h>
     48 #define lua_stdin_is_tty()	isatty(0)
     49 #elif defined(LUA_WIN)
     50 #include <io.h>
     51 #include <stdio.h>
     52 #define lua_stdin_is_tty()	_isatty(_fileno(stdin))
     53 #else
     54 #define lua_stdin_is_tty()	1  /* assume stdin is a tty */
     55 #endif
     56 
     57 
     58 /*
     59 ** lua_readline defines how to show a prompt and then read a line from
     60 ** the standard input.
     61 ** lua_saveline defines how to "save" a read line in a "history".
     62 ** lua_freeline defines how to free a line read by lua_readline.
     63 */
     64 #if defined(LUA_USE_READLINE)
     65 
     66 #include <stdio.h>
     67 #include <readline/readline.h>
     68 #include <readline/history.h>
     69 #define lua_readline(L,b,p)	((void)L, ((b)=readline(p)) != NULL)
     70 #define lua_saveline(L,idx) \
     71         if (lua_rawlen(L,idx) > 0)  /* non-empty line? */ \
     72           add_history(lua_tostring(L, idx));  /* add it to history */
     73 #define lua_freeline(L,b)	((void)L, free(b))
     74 
     75 #elif !defined(lua_readline)
     76 
     77 #define lua_readline(L,b,p) \
     78         ((void)L, fputs(p, stdout), fflush(stdout),  /* show prompt */ \
     79         fgets(b, LUA_MAXINPUT, stdin) != NULL)  /* get line */
     80 #define lua_saveline(L,idx)	{ (void)L; (void)idx; }
     81 #define lua_freeline(L,b)	{ (void)L; (void)b; }
     82 
     83 #endif
     84 
     85 
     86 
     87 
     88 static lua_State *globalL = NULL;
     89 
     90 static const char *progname = LUA_PROGNAME;
     91 
     92 
     93 
     94 static void lstop (lua_State *L, lua_Debug *ar) {
     95   (void)ar;  /* unused arg. */
     96   lua_sethook(L, NULL, 0, 0);
     97   luaL_error(L, "interrupted!");
     98 }
     99 
    100 
    101 static void laction (int i) {
    102   signal(i, SIG_DFL); /* if another SIGINT happens before lstop,
    103                               terminate process (default action) */
    104   lua_sethook(globalL, lstop, LUA_MASKCALL | LUA_MASKRET | LUA_MASKCOUNT, 1);
    105 }
    106 
    107 
    108 static void print_usage (const char *badoption) {
    109   luai_writestringerror("%s: ", progname);
    110   if (badoption[1] == 'e' || badoption[1] == 'l')
    111     luai_writestringerror("'%s' needs argument\n", badoption);
    112   else
    113     luai_writestringerror("unrecognized option '%s'\n", badoption);
    114   luai_writestringerror(
    115   "usage: %s [options] [script [args]]\n"
    116   "Available options are:\n"
    117   "  -e stat  execute string " LUA_QL("stat") "\n"
    118   "  -i       enter interactive mode after executing " LUA_QL("script") "\n"
    119   "  -l name  require library " LUA_QL("name") "\n"
    120   "  -v       show version information\n"
    121   "  -E       ignore environment variables\n"
    122   "  --       stop handling options\n"
    123   "  -        stop handling options and execute stdin\n"
    124   ,
    125   progname);
    126 }
    127 
    128 
    129 static void l_message (const char *pname, const char *msg) {
    130   if (pname) luai_writestringerror("%s: ", pname);
    131   luai_writestringerror("%s\n", msg);
    132 }
    133 
    134 
    135 static int report (lua_State *L, int status) {
    136   if (status != LUA_OK && !lua_isnil(L, -1)) {
    137     const char *msg = lua_tostring(L, -1);
    138     if (msg == NULL) msg = "(error object is not a string)";
    139     l_message(progname, msg);
    140     lua_pop(L, 1);
    141     /* force a complete garbage collection in case of errors */
    142     lua_gc(L, LUA_GCCOLLECT, 0);
    143   }
    144   return status;
    145 }
    146 
    147 
    148 /* the next function is called unprotected, so it must avoid errors */
    149 static void finalreport (lua_State *L, int status) {
    150   if (status != LUA_OK) {
    151     const char *msg = (lua_type(L, -1) == LUA_TSTRING) ? lua_tostring(L, -1)
    152                                                        : NULL;
    153     if (msg == NULL) msg = "(error object is not a string)";
    154     l_message(progname, msg);
    155     lua_pop(L, 1);
    156   }
    157 }
    158 
    159 
    160 static int traceback (lua_State *L) {
    161   const char *msg = lua_tostring(L, 1);
    162   if (msg)
    163     luaL_traceback(L, L, msg, 1);
    164   else if (!lua_isnoneornil(L, 1)) {  /* is there an error object? */
    165     if (!luaL_callmeta(L, 1, "__tostring"))  /* try its 'tostring' metamethod */
    166       lua_pushliteral(L, "(no error message)");
    167   }
    168   return 1;
    169 }
    170 
    171 
    172 static int docall (lua_State *L, int narg, int nres) {
    173   int status;
    174   int base = lua_gettop(L) - narg;  /* function index */
    175   lua_pushcfunction(L, traceback);  /* push traceback function */
    176   lua_insert(L, base);  /* put it under chunk and args */
    177   globalL = L;  /* to be available to 'laction' */
    178   signal(SIGINT, laction);
    179   status = lua_pcall(L, narg, nres, base);
    180   signal(SIGINT, SIG_DFL);
    181   lua_remove(L, base);  /* remove traceback function */
    182   return status;
    183 }
    184 
    185 
    186 static void print_version (void) {
    187   luai_writestring(LUA_COPYRIGHT, strlen(LUA_COPYRIGHT));
    188   luai_writeline();
    189 }
    190 
    191 
    192 static int getargs (lua_State *L, char **argv, int n) {
    193   int narg;
    194   int i;
    195   int argc = 0;
    196   while (argv[argc]) argc++;  /* count total number of arguments */
    197   narg = argc - (n + 1);  /* number of arguments to the script */
    198   luaL_checkstack(L, narg + 3, "too many arguments to script");
    199   for (i=n+1; i < argc; i++)
    200     lua_pushstring(L, argv[i]);
    201   lua_createtable(L, narg, n + 1);
    202   for (i=0; i < argc; i++) {
    203     lua_pushstring(L, argv[i]);
    204     lua_rawseti(L, -2, i - n);
    205   }
    206   return narg;
    207 }
    208 
    209 
    210 static int dofile (lua_State *L, const char *name) {
    211   int status = luaL_loadfile(L, name);
    212   if (status == LUA_OK) status = docall(L, 0, 0);
    213   return report(L, status);
    214 }
    215 
    216 
    217 static int dostring (lua_State *L, const char *s, const char *name) {
    218   int status = luaL_loadbuffer(L, s, strlen(s), name);
    219   if (status == LUA_OK) status = docall(L, 0, 0);
    220   return report(L, status);
    221 }
    222 
    223 
    224 static int dolibrary (lua_State *L, const char *name) {
    225   int status;
    226   lua_getglobal(L, "require");
    227   lua_pushstring(L, name);
    228   status = docall(L, 1, 1);  /* call 'require(name)' */
    229   if (status == LUA_OK)
    230     lua_setglobal(L, name);  /* global[name] = require return */
    231   return report(L, status);
    232 }
    233 
    234 
    235 static const char *get_prompt (lua_State *L, int firstline) {
    236   const char *p;
    237   lua_getglobal(L, firstline ? "_PROMPT" : "_PROMPT2");
    238   p = lua_tostring(L, -1);
    239   if (p == NULL) p = (firstline ? LUA_PROMPT : LUA_PROMPT2);
    240   return p;
    241 }
    242 
    243 /* mark in error messages for incomplete statements */
    244 #define EOFMARK		"<eof>"
    245 #define marklen		(sizeof(EOFMARK)/sizeof(char) - 1)
    246 
    247 static int incomplete (lua_State *L, int status) {
    248   if (status == LUA_ERRSYNTAX) {
    249     size_t lmsg;
    250     const char *msg = lua_tolstring(L, -1, &lmsg);
    251     if (lmsg >= marklen && strcmp(msg + lmsg - marklen, EOFMARK) == 0) {
    252       lua_pop(L, 1);
    253       return 1;
    254     }
    255   }
    256   return 0;  /* else... */
    257 }
    258 
    259 
    260 static int pushline (lua_State *L, int firstline) {
    261   char buffer[LUA_MAXINPUT];
    262   char *b = buffer;
    263   size_t l;
    264   const char *prmt = get_prompt(L, firstline);
    265   int readstatus = lua_readline(L, b, prmt);
    266   lua_pop(L, 1);  /* remove result from 'get_prompt' */
    267   if (readstatus == 0)
    268     return 0;  /* no input */
    269   l = strlen(b);
    270   if (l > 0 && b[l-1] == '\n')  /* line ends with newline? */
    271     b[l-1] = '\0';  /* remove it */
    272   if (firstline && b[0] == '=')  /* first line starts with `=' ? */
    273     lua_pushfstring(L, "return %s", b+1);  /* change it to `return' */
    274   else
    275     lua_pushstring(L, b);
    276   lua_freeline(L, b);
    277   return 1;
    278 }
    279 
    280 
    281 static int loadline (lua_State *L) {
    282   int status;
    283   lua_settop(L, 0);
    284   if (!pushline(L, 1))
    285     return -1;  /* no input */
    286   for (;;) {  /* repeat until gets a complete line */
    287     size_t l;
    288     const char *line = lua_tolstring(L, 1, &l);
    289     status = luaL_loadbuffer(L, line, l, "=stdin");
    290     if (!incomplete(L, status)) break;  /* cannot try to add lines? */
    291     if (!pushline(L, 0))  /* no more input? */
    292       return -1;
    293     lua_pushliteral(L, "\n");  /* add a new line... */
    294     lua_insert(L, -2);  /* ...between the two lines */
    295     lua_concat(L, 3);  /* join them */
    296   }
    297   lua_saveline(L, 1);
    298   lua_remove(L, 1);  /* remove line */
    299   return status;
    300 }
    301 
    302 
    303 static void dotty (lua_State *L) {
    304   int status;
    305   const char *oldprogname = progname;
    306   progname = NULL;
    307   while ((status = loadline(L)) != -1) {
    308     if (status == LUA_OK) status = docall(L, 0, LUA_MULTRET);
    309     report(L, status);
    310     if (status == LUA_OK && lua_gettop(L) > 0) {  /* any result to print? */
    311       luaL_checkstack(L, LUA_MINSTACK, "too many results to print");
    312       lua_getglobal(L, "print");
    313       lua_insert(L, 1);
    314       if (lua_pcall(L, lua_gettop(L)-1, 0, 0) != LUA_OK)
    315         l_message(progname, lua_pushfstring(L,
    316                                "error calling " LUA_QL("print") " (%s)",
    317                                lua_tostring(L, -1)));
    318     }
    319   }
    320   lua_settop(L, 0);  /* clear stack */
    321   luai_writeline();
    322   progname = oldprogname;
    323 }
    324 
    325 
    326 static int handle_script (lua_State *L, char **argv, int n) {
    327   int status;
    328   const char *fname;
    329   int narg = getargs(L, argv, n);  /* collect arguments */
    330   lua_setglobal(L, "arg");
    331   fname = argv[n];
    332   if (strcmp(fname, "-") == 0 && strcmp(argv[n-1], "--") != 0)
    333     fname = NULL;  /* stdin */
    334   status = luaL_loadfile(L, fname);
    335   lua_insert(L, -(narg+1));
    336   if (status == LUA_OK)
    337     status = docall(L, narg, LUA_MULTRET);
    338   else
    339     lua_pop(L, narg);
    340   return report(L, status);
    341 }
    342 
    343 
    344 /* check that argument has no extra characters at the end */
    345 #define noextrachars(x)		{if ((x)[2] != '\0') return -1;}
    346 
    347 
    348 /* indices of various argument indicators in array args */
    349 #define has_i		0	/* -i */
    350 #define has_v		1	/* -v */
    351 #define has_e		2	/* -e */
    352 #define has_E		3	/* -E */
    353 
    354 #define num_has		4	/* number of 'has_*' */
    355 
    356 
    357 static int collectargs (char **argv, int *args) {
    358   int i;
    359   for (i = 1; argv[i] != NULL; i++) {
    360     if (argv[i][0] != '-')  /* not an option? */
    361         return i;
    362     switch (argv[i][1]) {  /* option */
    363       case '-':
    364         noextrachars(argv[i]);
    365         return (argv[i+1] != NULL ? i+1 : 0);
    366       case '\0':
    367         return i;
    368       case 'E':
    369         args[has_E] = 1;
    370         break;
    371       case 'i':
    372         noextrachars(argv[i]);
    373         args[has_i] = 1;  /* go through */
    374       case 'v':
    375         noextrachars(argv[i]);
    376         args[has_v] = 1;
    377         break;
    378       case 'e':
    379         args[has_e] = 1;  /* go through */
    380       case 'l':  /* both options need an argument */
    381         if (argv[i][2] == '\0') {  /* no concatenated argument? */
    382           i++;  /* try next 'argv' */
    383           if (argv[i] == NULL || argv[i][0] == '-')
    384             return -(i - 1);  /* no next argument or it is another option */
    385         }
    386         break;
    387       default:  /* invalid option; return its index... */
    388         return -i;  /* ...as a negative value */
    389     }
    390   }
    391   return 0;
    392 }
    393 
    394 
    395 static int runargs (lua_State *L, char **argv, int n) {
    396   int i;
    397   for (i = 1; i < n; i++) {
    398     lua_assert(argv[i][0] == '-');
    399     switch (argv[i][1]) {  /* option */
    400       case 'e': {
    401         const char *chunk = argv[i] + 2;
    402         if (*chunk == '\0') chunk = argv[++i];
    403         lua_assert(chunk != NULL);
    404         if (dostring(L, chunk, "=(command line)") != LUA_OK)
    405           return 0;
    406         break;
    407       }
    408       case 'l': {
    409         const char *filename = argv[i] + 2;
    410         if (*filename == '\0') filename = argv[++i];
    411         lua_assert(filename != NULL);
    412         if (dolibrary(L, filename) != LUA_OK)
    413           return 0;  /* stop if file fails */
    414         break;
    415       }
    416       default: break;
    417     }
    418   }
    419   return 1;
    420 }
    421 
    422 
    423 static int handle_luainit (lua_State *L) {
    424   const char *name = "=" LUA_INITVERSION;
    425   const char *init = getenv(name + 1);
    426   if (init == NULL) {
    427     name = "=" LUA_INIT;
    428     init = getenv(name + 1);  /* try alternative name */
    429   }
    430   if (init == NULL) return LUA_OK;
    431   else if (init[0] == '@')
    432     return dofile(L, init+1);
    433   else
    434     return dostring(L, init, name);
    435 }
    436 
    437 
    438 static int pmain (lua_State *L) {
    439   int argc = (int)lua_tointeger(L, 1);
    440   char **argv = (char **)lua_touserdata(L, 2);
    441   int script;
    442   int args[num_has];
    443   args[has_i] = args[has_v] = args[has_e] = args[has_E] = 0;
    444   if (argv[0] && argv[0][0]) progname = argv[0];
    445   script = collectargs(argv, args);
    446   if (script < 0) {  /* invalid arg? */
    447     print_usage(argv[-script]);
    448     return 0;
    449   }
    450   if (args[has_v]) print_version();
    451   if (args[has_E]) {  /* option '-E'? */
    452     lua_pushboolean(L, 1);  /* signal for libraries to ignore env. vars. */
    453     lua_setfield(L, LUA_REGISTRYINDEX, "LUA_NOENV");
    454   }
    455   /* open standard libraries */
    456   luaL_checkversion(L);
    457   lua_gc(L, LUA_GCSTOP, 0);  /* stop collector during initialization */
    458   luaL_openlibs(L);  /* open libraries */
    459   lua_gc(L, LUA_GCRESTART, 0);
    460   if (!args[has_E] && handle_luainit(L) != LUA_OK)
    461     return 0;  /* error running LUA_INIT */
    462   /* execute arguments -e and -l */
    463   if (!runargs(L, argv, (script > 0) ? script : argc)) return 0;
    464   /* execute main script (if there is one) */
    465   if (script && handle_script(L, argv, script) != LUA_OK) return 0;
    466   if (args[has_i])  /* -i option? */
    467     dotty(L);
    468   else if (script == 0 && !args[has_e] && !args[has_v]) {  /* no arguments? */
    469     if (lua_stdin_is_tty()) {
    470       print_version();
    471       dotty(L);
    472     }
    473     else dofile(L, NULL);  /* executes stdin as a file */
    474   }
    475   lua_pushboolean(L, 1);  /* signal no errors */
    476   return 1;
    477 }
    478 
    479 
    480 int main (int argc, char **argv) {
    481   int status, result;
    482   lua_State *L = luaL_newstate();  /* create state */
    483   if (L == NULL) {
    484     l_message(argv[0], "cannot create state: not enough memory");
    485     return EXIT_FAILURE;
    486   }
    487   /* call 'pmain' in protected mode */
    488   lua_pushcfunction(L, &pmain);
    489   lua_pushinteger(L, argc);  /* 1st argument */
    490   lua_pushlightuserdata(L, argv); /* 2nd argument */
    491   status = lua_pcall(L, 2, 1, 0);
    492   result = lua_toboolean(L, -1);  /* get result */
    493   finalreport(L, status);
    494   lua_close(L);
    495   return (result && status == LUA_OK) ? EXIT_SUCCESS : EXIT_FAILURE;
    496 }
    497 
    498