LCOV - code coverage report
Current view: directory - src - lua.c Found Hit Coverage
Test: Lua 5.1.4 Lines: 225 80 35.6 %
Date: 2009-09-13
Colors: not hit hit

       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               0 : static void print_usage (void) {
      43               0 :   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               0 :   fflush(stderr);
      55               0 : }
      56                 : 
      57                 : 
      58               0 : static void l_message (const char *pname, const char *msg) {
      59               0 :   if (pname) fprintf(stderr, "%s: ", pname);
      60               0 :   fprintf(stderr, "%s\n", msg);
      61               0 :   fflush(stderr);
      62               0 : }
      63                 : 
      64                 : 
      65             105 : static int report (lua_State *L, int status) {
      66             105 :   if (status && !lua_isnil(L, -1)) {
      67               0 :     const char *msg = lua_tostring(L, -1);
      68               0 :     if (msg == NULL) msg = "(error object is not a string)";
      69               0 :     l_message(progname, msg);
      70               0 :     lua_pop(L, 1);
      71                 :   }
      72             105 :   return status;
      73                 : }
      74                 : 
      75                 : 
      76               0 : static int traceback (lua_State *L) {
      77               0 :   if (!lua_isstring(L, 1))  /* 'message' not a string? */
      78               0 :     return 1;  /* keep it intact */
      79               0 :   lua_getfield(L, LUA_GLOBALSINDEX, "debug");
      80               0 :   if (!lua_istable(L, -1)) {
      81               0 :     lua_pop(L, 1);
      82               0 :     return 1;
      83                 :   }
      84               0 :   lua_getfield(L, -1, "traceback");
      85               0 :   if (!lua_isfunction(L, -1)) {
      86               0 :     lua_pop(L, 2);
      87               0 :     return 1;
      88                 :   }
      89               0 :   lua_pushvalue(L, 1);  /* pass error message */
      90               0 :   lua_pushinteger(L, 2);  /* skip this function and traceback */
      91               0 :   lua_call(L, 2, 1);  /* call debug.traceback */
      92               0 :   return 1;
      93                 : }
      94                 : 
      95                 : 
      96              70 : static int docall (lua_State *L, int narg, int clear) {
      97                 :   int status;
      98              70 :   int base = lua_gettop(L) - narg;  /* function index */
      99              70 :   lua_pushcfunction(L, traceback);  /* push traceback function */
     100              70 :   lua_insert(L, base);  /* put it under chunk and args */
     101              70 :   signal(SIGINT, laction);
     102              70 :   status = lua_pcall(L, narg, (clear ? 0 : LUA_MULTRET), base);
     103              70 :   signal(SIGINT, SIG_DFL);
     104              70 :   lua_remove(L, base);  /* remove traceback function */
     105                 :   /* force a complete garbage collection in case of errors */
     106              70 :   if (status != 0) lua_gc(L, LUA_GCCOLLECT, 0);
     107              70 :   return status;
     108                 : }
     109                 : 
     110                 : 
     111               0 : static void print_version (void) {
     112               0 :   l_message(NULL, LUA_RELEASE "  " LUA_COPYRIGHT);
     113               0 : }
     114                 : 
     115                 : 
     116              35 : static int getargs (lua_State *L, char **argv, int n) {
     117                 :   int narg;
     118                 :   int i;
     119              35 :   int argc = 0;
     120              35 :   while (argv[argc]) argc++;  /* count total number of arguments */
     121              35 :   narg = argc - (n + 1);  /* number of arguments to the script */
     122              35 :   luaL_checkstack(L, narg + 3, "too many arguments to script");
     123              35 :   for (i=n+1; i < argc; i++)
     124               0 :     lua_pushstring(L, argv[i]);
     125              35 :   lua_createtable(L, narg, n + 1);
     126             105 :   for (i=0; i < argc; i++) {
     127              70 :     lua_pushstring(L, argv[i]);
     128              70 :     lua_rawseti(L, -2, i - n);
     129                 :   }
     130              35 :   return narg;
     131                 : }
     132                 : 
     133                 : 
     134               0 : static int dofile (lua_State *L, const char *name) {
     135               0 :   int status = luaL_loadfile(L, name) || docall(L, 0, 1);
     136               0 :   return report(L, status);
     137                 : }
     138                 : 
     139                 : 
     140              35 : static int dostring (lua_State *L, const char *s, const char *name) {
     141              35 :   int status = luaL_loadbuffer(L, s, strlen(s), name) || docall(L, 0, 1);
     142              35 :   return report(L, status);
     143                 : }
     144                 : 
     145                 : 
     146               0 : static int dolibrary (lua_State *L, const char *name) {
     147               0 :   lua_getglobal(L, "require");
     148               0 :   lua_pushstring(L, name);
     149               0 :   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               0 :   }
     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              35 : static int handle_script (lua_State *L, char **argv, int n) {
     240                 :   int status;
     241                 :   const char *fname;
     242              35 :   int narg = getargs(L, argv, n);  /* collect arguments */
     243              35 :   lua_setglobal(L, "arg");
     244              35 :   fname = argv[n];
     245              35 :   if (strcmp(fname, "-") == 0 && strcmp(argv[n-1], "--") != 0) 
     246               0 :     fname = NULL;  /* stdin */
     247              35 :   status = luaL_loadfile(L, fname);
     248              35 :   lua_insert(L, -(narg+1));
     249              35 :   if (status == 0)
     250              35 :     status = docall(L, narg, 0);
     251                 :   else
     252               0 :     lua_pop(L, narg);      
     253              35 :   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              35 : static int collectargs (char **argv, int *pi, int *pv, int *pe) {
     262                 :   int i;
     263              35 :   for (i = 1; argv[i] != NULL; i++) {
     264              35 :     if (argv[i][0] != '-')  /* not an option? */
     265              35 :         return i;
     266               0 :     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               0 :         notail(argv[i]);
     277               0 :         *pv = 1;
     278               0 :         break;
     279                 :       case 'e':
     280               0 :         *pe = 1;  /* go through */
     281                 :       case 'l':
     282               0 :         if (argv[i][2] == '\0') {
     283               0 :           i++;
     284               0 :           if (argv[i] == NULL) return -1;
     285                 :         }
     286               0 :         break;
     287               0 :       default: return -1;  /* invalid option */
     288                 :     }
     289                 :   }
     290               0 :   return 0;
     291                 : }
     292                 : 
     293                 : 
     294              35 : static int runargs (lua_State *L, char **argv, int n) {
     295                 :   int i;
     296              35 :   for (i = 1; i < n; i++) {
     297               0 :     if (argv[i] == NULL) continue;
     298                 :     lua_assert(argv[i][0] == '-');
     299               0 :     switch (argv[i][1]) {  /* option */
     300                 :       case 'e': {
     301               0 :         const char *chunk = argv[i] + 2;
     302               0 :         if (*chunk == '\0') chunk = argv[++i];
     303                 :         lua_assert(chunk != NULL);
     304               0 :         if (dostring(L, chunk, "=(command line)") != 0)
     305               0 :           return 1;
     306               0 :         break;
     307                 :       }
     308                 :       case 'l': {
     309               0 :         const char *filename = argv[i] + 2;
     310               0 :         if (*filename == '\0') filename = argv[++i];
     311                 :         lua_assert(filename != NULL);
     312               0 :         if (dolibrary(L, filename))
     313               0 :           return 1;  /* stop if file fails */
     314                 :         break;
     315                 :       }
     316                 :       default: break;
     317                 :     }
     318                 :   }
     319              35 :   return 0;
     320                 : }
     321                 : 
     322                 : 
     323              35 : static int handle_luainit (lua_State *L) {
     324              35 :   const char *init = getenv(LUA_INIT);
     325              35 :   if (init == NULL) return 0;  /* status OK */
     326              35 :   else if (init[0] == '@')
     327               0 :     return dofile(L, init+1);
     328                 :   else
     329              35 :     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              35 : static int pmain (lua_State *L) {
     341              35 :   struct Smain *s = (struct Smain *)lua_touserdata(L, 1);
     342              35 :   char **argv = s->argv;
     343                 :   int script;
     344              35 :   int has_i = 0, has_v = 0, has_e = 0;
     345              35 :   globalL = L;
     346              35 :   if (argv[0] && argv[0][0]) progname = argv[0];
     347              35 :   lua_gc(L, LUA_GCSTOP, 0);  /* stop collector during initialization */
     348              35 :   luaL_openlibs(L);  /* open libraries */
     349              35 :   lua_gc(L, LUA_GCRESTART, 0);
     350              35 :   s->status = handle_luainit(L);
     351              35 :   if (s->status != 0) return 0;
     352              35 :   script = collectargs(argv, &has_i, &has_v, &has_e);
     353              35 :   if (script < 0) {  /* invalid args? */
     354               0 :     print_usage();
     355               0 :     s->status = 1;
     356               0 :     return 0;
     357                 :   }
     358              35 :   if (has_v) print_version();
     359              35 :   s->status = runargs(L, argv, (script > 0) ? script : s->argc);
     360              35 :   if (s->status != 0) return 0;
     361              35 :   if (script)
     362              35 :     s->status = handle_script(L, argv, script);
     363              35 :   if (s->status != 0) return 0;
     364              35 :   if (has_i)
     365               0 :     dotty(L);
     366              35 :   else if (script == 0 && !has_e && !has_v) {
     367               0 :     if (lua_stdin_is_tty()) {
     368               0 :       print_version();
     369               0 :       dotty(L);
     370                 :     }
     371               0 :     else dofile(L, NULL);  /* executes stdin as a file */
     372                 :   }
     373              35 :   return 0;
     374                 : }
     375                 : 
     376                 : 
     377              35 : int main (int argc, char **argv) {
     378                 :   int status;
     379                 :   struct Smain s;
     380              35 :   lua_State *L = lua_open();  /* create state */
     381              35 :   if (L == NULL) {
     382               0 :     l_message(argv[0], "cannot create state: not enough memory");
     383               0 :     return EXIT_FAILURE;
     384                 :   }
     385              35 :   s.argc = argc;
     386              35 :   s.argv = argv;
     387              35 :   status = lua_cpcall(L, &pmain, &s);
     388              35 :   report(L, status);
     389              35 :   lua_close(L);
     390              35 :   return (status || s.status) ? EXIT_FAILURE : EXIT_SUCCESS;
     391                 : }
     392                 : 

Generated by: LCOV version 1.7