LCOV - code coverage report
Current view: top level - src - lua.c Hit Total Coverage
Test: Lua 5.1.5 Lines: 142 226 62.8 %
Date: 2017-04-16 16:03:13
Legend: Lines: hit not hit

          Line data    Source code
       1             : /*
       2             : ** $Id: lua.c,v 1.160.1.2 2007/12/28 15:32:23 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             : 
      22             : static lua_State *globalL = NULL;
      23             : 
      24             : static const char *progname = LUA_PROGNAME;
      25             : 
      26             : 
      27             : 
      28           0 : static void lstop (lua_State *L, lua_Debug *ar) {
      29             :   (void)ar;  /* unused arg. */
      30           0 :   lua_sethook(L, NULL, 0, 0);
      31           0 :   luaL_error(L, "interrupted!");
      32           0 : }
      33             : 
      34             : 
      35           0 : static void laction (int i) {
      36           0 :   signal(i, SIG_DFL); /* if another SIGINT happens before lstop,
      37             :                               terminate process (default action) */
      38           0 :   lua_sethook(globalL, lstop, LUA_MASKCALL | LUA_MASKRET | LUA_MASKCOUNT, 1);
      39           0 : }
      40             : 
      41             : 
      42           1 : static void print_usage (void) {
      43           1 :   fprintf(stderr,
      44             :   "usage: %s [options] [script [args]].\n"
      45             :   "Available options are:\n"
      46             :   "  -e stat  execute string " LUA_QL("stat") "\n"
      47             :   "  -l name  require library " LUA_QL("name") "\n"
      48             :   "  -i       enter interactive mode after executing " LUA_QL("script") "\n"
      49             :   "  -v       show version information\n"
      50             :   "  --       stop handling options\n"
      51             :   "  -        execute stdin and stop handling options\n"
      52             :   ,
      53             :   progname);
      54           1 :   fflush(stderr);
      55           1 : }
      56             : 
      57             : 
      58           4 : static void l_message (const char *pname, const char *msg) {
      59           4 :   if (pname) fprintf(stderr, "%s: ", pname);
      60           4 :   fprintf(stderr, "%s\n", msg);
      61           4 :   fflush(stderr);
      62           4 : }
      63             : 
      64             : 
      65         185 : static int report (lua_State *L, int status) {
      66         185 :   if (status && !lua_isnil(L, -1)) {
      67           2 :     const char *msg = lua_tostring(L, -1);
      68           2 :     if (msg == NULL) msg = "(error object is not a string)";
      69           2 :     l_message(progname, msg);
      70           2 :     lua_pop(L, 1);
      71             :   }
      72         185 :   return status;
      73             : }
      74             : 
      75             : 
      76           1 : static int traceback (lua_State *L) {
      77           1 :   if (!lua_isstring(L, 1))  /* 'message' not a string? */
      78           0 :     return 1;  /* keep it intact */
      79           1 :   lua_getfield(L, LUA_GLOBALSINDEX, "debug");
      80           1 :   if (!lua_istable(L, -1)) {
      81           0 :     lua_pop(L, 1);
      82           0 :     return 1;
      83             :   }
      84           1 :   lua_getfield(L, -1, "traceback");
      85           1 :   if (!lua_isfunction(L, -1)) {
      86           0 :     lua_pop(L, 2);
      87           0 :     return 1;
      88             :   }
      89           1 :   lua_pushvalue(L, 1);  /* pass error message */
      90           1 :   lua_pushinteger(L, 2);  /* skip this function and traceback */
      91           1 :   lua_call(L, 2, 1);  /* call debug.traceback */
      92           1 :   return 1;
      93             : }
      94             : 
      95             : 
      96         126 : static int docall (lua_State *L, int narg, int clear) {
      97             :   int status;
      98         126 :   int base = lua_gettop(L) - narg;  /* function index */
      99         126 :   lua_pushcfunction(L, traceback);  /* push traceback function */
     100         126 :   lua_insert(L, base);  /* put it under chunk and args */
     101         126 :   signal(SIGINT, laction);
     102         126 :   status = lua_pcall(L, narg, (clear ? 0 : LUA_MULTRET), base);
     103         124 :   signal(SIGINT, SIG_DFL);
     104         124 :   lua_remove(L, base);  /* remove traceback function */
     105             :   /* force a complete garbage collection in case of errors */
     106         124 :   if (status != 0) lua_gc(L, LUA_GCCOLLECT, 0);
     107         124 :   return status;
     108             : }
     109             : 
     110             : 
     111           2 : static void print_version (void) {
     112           2 :   l_message(NULL, LUA_RELEASE "  " LUA_COPYRIGHT);
     113           2 : }
     114             : 
     115             : 
     116          43 : static int getargs (lua_State *L, char **argv, int n) {
     117             :   int narg;
     118             :   int i;
     119          43 :   int argc = 0;
     120          43 :   while (argv[argc]) argc++;  /* count total number of arguments */
     121          43 :   narg = argc - (n + 1);  /* number of arguments to the script */
     122          43 :   luaL_checkstack(L, narg + 3, "too many arguments to script");
     123          43 :   for (i=n+1; i < argc; i++)
     124           0 :     lua_pushstring(L, argv[i]);
     125          43 :   lua_createtable(L, narg, n + 1);
     126         133 :   for (i=0; i < argc; i++) {
     127          90 :     lua_pushstring(L, argv[i]);
     128          90 :     lua_rawseti(L, -2, i - n);
     129             :   }
     130          43 :   return narg;
     131             : }
     132             : 
     133             : 
     134           1 : static int dofile (lua_State *L, const char *name) {
     135           1 :   int status = luaL_loadfile(L, name) || docall(L, 0, 1);
     136           1 :   return report(L, status);
     137             : }
     138             : 
     139             : 
     140          80 : static int dostring (lua_State *L, const char *s, const char *name) {
     141          80 :   int status = luaL_loadbuffer(L, s, strlen(s), name) || docall(L, 0, 1);
     142          78 :   return report(L, status);
     143             : }
     144             : 
     145             : 
     146           3 : static int dolibrary (lua_State *L, const char *name) {
     147           3 :   lua_getglobal(L, "require");
     148           3 :   lua_pushstring(L, name);
     149           3 :   return report(L, docall(L, 1, 1));
     150             : }
     151             : 
     152             : 
     153           0 : static const char *get_prompt (lua_State *L, int firstline) {
     154             :   const char *p;
     155           0 :   lua_getfield(L, LUA_GLOBALSINDEX, firstline ? "_PROMPT" : "_PROMPT2");
     156           0 :   p = lua_tostring(L, -1);
     157           0 :   if (p == NULL) p = (firstline ? LUA_PROMPT : LUA_PROMPT2);
     158           0 :   lua_pop(L, 1);  /* remove global */
     159           0 :   return p;
     160             : }
     161             : 
     162             : 
     163           0 : static int incomplete (lua_State *L, int status) {
     164           0 :   if (status == LUA_ERRSYNTAX) {
     165             :     size_t lmsg;
     166           0 :     const char *msg = lua_tolstring(L, -1, &lmsg);
     167           0 :     const char *tp = msg + lmsg - (sizeof(LUA_QL("<eof>")) - 1);
     168           0 :     if (strstr(msg, LUA_QL("<eof>")) == tp) {
     169           0 :       lua_pop(L, 1);
     170           0 :       return 1;
     171             :     }
     172             :   }
     173           0 :   return 0;  /* else... */
     174             : }
     175             : 
     176             : 
     177           0 : static int pushline (lua_State *L, int firstline) {
     178             :   char buffer[LUA_MAXINPUT];
     179           0 :   char *b = buffer;
     180             :   size_t l;
     181           0 :   const char *prmt = get_prompt(L, firstline);
     182           0 :   if (lua_readline(L, b, prmt) == 0)
     183           0 :     return 0;  /* no input */
     184           0 :   l = strlen(b);
     185           0 :   if (l > 0 && b[l-1] == '\n')  /* line ends with newline? */
     186           0 :     b[l-1] = '\0';  /* remove it */
     187           0 :   if (firstline && b[0] == '=')  /* first line starts with `=' ? */
     188           0 :     lua_pushfstring(L, "return %s", b+1);  /* change it to `return' */
     189             :   else
     190           0 :     lua_pushstring(L, b);
     191           0 :   lua_freeline(L, b);
     192           0 :   return 1;
     193             : }
     194             : 
     195             : 
     196           0 : static int loadline (lua_State *L) {
     197             :   int status;
     198           0 :   lua_settop(L, 0);
     199           0 :   if (!pushline(L, 1))
     200           0 :     return -1;  /* no input */
     201             :   for (;;) {  /* repeat until gets a complete line */
     202           0 :     status = luaL_loadbuffer(L, lua_tostring(L, 1), lua_strlen(L, 1), "=stdin");
     203           0 :     if (!incomplete(L, status)) break;  /* cannot try to add lines? */
     204           0 :     if (!pushline(L, 0))  /* no more input? */
     205           0 :       return -1;
     206           0 :     lua_pushliteral(L, "\n");  /* add a new line... */
     207           0 :     lua_insert(L, -2);  /* ...between the two lines */
     208           0 :     lua_concat(L, 3);  /* join them */
     209             :   }
     210           0 :   lua_saveline(L, 1);
     211           0 :   lua_remove(L, 1);  /* remove line */
     212           0 :   return status;
     213             : }
     214             : 
     215             : 
     216           0 : static void dotty (lua_State *L) {
     217             :   int status;
     218           0 :   const char *oldprogname = progname;
     219           0 :   progname = NULL;
     220           0 :   while ((status = loadline(L)) != -1) {
     221           0 :     if (status == 0) status = docall(L, 0, 0);
     222           0 :     report(L, status);
     223           0 :     if (status == 0 && lua_gettop(L) > 0) {  /* any result to print? */
     224           0 :       lua_getglobal(L, "print");
     225           0 :       lua_insert(L, 1);
     226           0 :       if (lua_pcall(L, lua_gettop(L)-1, 0, 0) != 0)
     227           0 :         l_message(progname, lua_pushfstring(L,
     228             :                                "error calling " LUA_QL("print") " (%s)",
     229             :                                lua_tostring(L, -1)));
     230             :     }
     231             :   }
     232           0 :   lua_settop(L, 0);  /* clear stack */
     233           0 :   fputs("\n", stdout);
     234           0 :   fflush(stdout);
     235           0 :   progname = oldprogname;
     236           0 : }
     237             : 
     238             : 
     239          43 : static int handle_script (lua_State *L, char **argv, int n) {
     240             :   int status;
     241             :   const char *fname;
     242          43 :   int narg = getargs(L, argv, n);  /* collect arguments */
     243          43 :   lua_setglobal(L, "arg");
     244          43 :   fname = argv[n];
     245          43 :   if (strcmp(fname, "-") == 0 && strcmp(argv[n-1], "--") != 0) 
     246           0 :     fname = NULL;  /* stdin */
     247          43 :   status = luaL_loadfile(L, fname);
     248          43 :   lua_insert(L, -(narg+1));
     249          43 :   if (status == 0)
     250          43 :     status = docall(L, narg, 0);
     251             :   else
     252           0 :     lua_pop(L, narg);      
     253          43 :   return report(L, status);
     254             : }
     255             : 
     256             : 
     257             : /* check that argument has no extra characters at the end */
     258             : #define notail(x)       {if ((x)[2] != '\0') return -1;}
     259             : 
     260             : 
     261          62 : static int collectargs (char **argv, int *pi, int *pv, int *pe) {
     262             :   int i;
     263          85 :   for (i = 1; argv[i] != NULL; i++) {
     264          68 :     if (argv[i][0] != '-')  /* not an option? */
     265          44 :         return i;
     266          24 :     switch (argv[i][1]) {  /* option */
     267             :       case '-':
     268           0 :         notail(argv[i]);
     269           0 :         return (argv[i+1] != NULL ? i+1 : 0);
     270             :       case '\0':
     271           0 :         return i;
     272             :       case 'i':
     273           0 :         notail(argv[i]);
     274           0 :         *pi = 1;  /* go through */
     275             :       case 'v':
     276           2 :         notail(argv[i]);
     277           2 :         *pv = 1;
     278           2 :         break;
     279             :       case 'e':
     280          18 :         *pe = 1;  /* go through */
     281             :       case 'l':
     282          21 :         if (argv[i][2] == '\0') {
     283          18 :           i++;
     284          18 :           if (argv[i] == NULL) return -1;
     285             :         }
     286          21 :         break;
     287           1 :       default: return -1;  /* invalid option */
     288             :     }
     289             :   }
     290          17 :   return 0;
     291             : }
     292             : 
     293             : 
     294          61 : static int runargs (lua_State *L, char **argv, int n) {
     295             :   int i;
     296          80 :   for (i = 1; i < n; i++) {
     297          23 :     if (argv[i] == NULL) continue;
     298             :     lua_assert(argv[i][0] == '-');
     299          23 :     switch (argv[i][1]) {  /* option */
     300             :       case 'e': {
     301          18 :         const char *chunk = argv[i] + 2;
     302          18 :         if (*chunk == '\0') chunk = argv[++i];
     303             :         lua_assert(chunk != NULL);
     304          18 :         if (dostring(L, chunk, "=(command line)") != 0)
     305           1 :           return 1;
     306          15 :         break;
     307             :       }
     308             :       case 'l': {
     309           3 :         const char *filename = argv[i] + 2;
     310           3 :         if (*filename == '\0') filename = argv[++i];
     311             :         lua_assert(filename != NULL);
     312           3 :         if (dolibrary(L, filename))
     313           1 :           return 1;  /* stop if file fails */
     314           2 :         break;
     315             :       }
     316           2 :       default: break;
     317             :     }
     318             :   }
     319          57 :   return 0;
     320             : }
     321             : 
     322             : 
     323          62 : static int handle_luainit (lua_State *L) {
     324          62 :   const char *init = getenv(LUA_INIT);
     325          62 :   if (init == NULL) return 0;  /* status OK */
     326          62 :   else if (init[0] == '@')
     327           0 :     return dofile(L, init+1);
     328             :   else
     329          62 :     return dostring(L, init, "=" LUA_INIT);
     330             : }
     331             : 
     332             : 
     333             : struct Smain {
     334             :   int argc;
     335             :   char **argv;
     336             :   int status;
     337             : };
     338             : 
     339             : 
     340          62 : static int pmain (lua_State *L) {
     341          62 :   struct Smain *s = (struct Smain *)lua_touserdata(L, 1);
     342          62 :   char **argv = s->argv;
     343             :   int script;
     344          62 :   int has_i = 0, has_v = 0, has_e = 0;
     345          62 :   globalL = L;
     346          62 :   if (argv[0] && argv[0][0]) progname = argv[0];
     347          62 :   lua_gc(L, LUA_GCSTOP, 0);  /* stop collector during initialization */
     348          62 :   luaL_openlibs(L);  /* open libraries */
     349          62 :   lua_gc(L, LUA_GCRESTART, 0);
     350          62 :   s->status = handle_luainit(L);
     351          62 :   if (s->status != 0) return 0;
     352          62 :   script = collectargs(argv, &has_i, &has_v, &has_e);
     353          62 :   if (script < 0) {  /* invalid args? */
     354           1 :     print_usage();
     355           1 :     s->status = 1;
     356           1 :     return 0;
     357             :   }
     358          61 :   if (has_v) print_version();
     359          61 :   s->status = runargs(L, argv, (script > 0) ? script : s->argc);
     360          59 :   if (s->status != 0) return 0;
     361          57 :   if (script)
     362          43 :     s->status = handle_script(L, argv, script);
     363          57 :   if (s->status != 0) return 0;
     364          57 :   if (has_i)
     365           0 :     dotty(L);
     366          57 :   else if (script == 0 && !has_e && !has_v) {
     367           1 :     if (lua_stdin_is_tty()) {
     368           0 :       print_version();
     369           0 :       dotty(L);
     370             :     }
     371           1 :     else dofile(L, NULL);  /* executes stdin as a file */
     372             :   }
     373          57 :   return 0;
     374             : }
     375             : 
     376             : 
     377          62 : int main (int argc, char **argv) {
     378             :   int status;
     379             :   struct Smain s;
     380          62 :   lua_State *L = lua_open();  /* create state */
     381          62 :   if (L == NULL) {
     382           0 :     l_message(argv[0], "cannot create state: not enough memory");
     383           0 :     return EXIT_FAILURE;
     384             :   }
     385          62 :   s.argc = argc;
     386          62 :   s.argv = argv;
     387          62 :   status = lua_cpcall(L, &pmain, &s);
     388          60 :   report(L, status);
     389          60 :   lua_close(L);
     390          60 :   return (status || s.status) ? EXIT_FAILURE : EXIT_SUCCESS;
     391             : }
     392             : 

Generated by: LCOV version 1.13