lua.c

Go to the documentation of this file.
00001 /*
00002 ** $Id: lua.c,v 1.160.1.2 2007/12/28 15:32:23 roberto Exp $
00003 ** Lua stand-alone interpreter
00004 ** See Copyright Notice in lua.h
00005 */
00006 
00007 
00008 #include <signal.h>
00009 #include <stdio.h>
00010 #include <stdlib.h>
00011 #include <string.h>
00012 
00013 #define lua_c
00014 
00015 #include "lua.h"
00016 
00017 #include "lauxlib.h"
00018 #include "lualib.h"
00019 
00020 
00021 
00022 static lua_State *globalL = NULL;
00023 
00024 static const char *progname = LUA_PROGNAME;
00025 
00026 
00027 
00028 static void lstop (lua_State *L, lua_Debug *ar) {
00029   (void)ar;  /* unused arg. */
00030   lua_sethook(L, NULL, 0, 0);
00031   luaL_error(L, "interrupted!");
00032 }
00033 
00034 
00035 #if !defined(LUA_SYMBIAN)
00036 static void laction (int i) {
00037   signal(i, SIG_DFL); /* if another SIGINT happens before lstop,
00038                               terminate process (default action) */
00039   lua_sethook(globalL, lstop, LUA_MASKCALL | LUA_MASKRET | LUA_MASKCOUNT, 1);
00040 }
00041 #endif
00042 
00043 
00044 static void print_usage (void) {
00045   fprintf(stderr,
00046   "usage: %s [options] [script [args]].\n"
00047   "Available options are:\n"
00048   "  -e stat  execute string " LUA_QL("stat") "\n"
00049   "  -l name  require library " LUA_QL("name") "\n"
00050   "  -i       enter interactive mode after executing " LUA_QL("script") "\n"
00051   "  -v       show version information\n"
00052   "  --       stop handling options\n"
00053   "  -        execute stdin and stop handling options\n"
00054   ,
00055   progname);
00056   fflush(stderr);
00057 }
00058 
00059 
00060 static void l_message (const char *pname, const char *msg) {
00061   if (pname) fprintf(stderr, "%s: ", pname);
00062   fprintf(stderr, "%s\n", msg);
00063   fflush(stderr);
00064 }
00065 
00066 
00067 static int report (lua_State *L, int status) {
00068   if (status && !lua_isnil(L, -1)) {
00069     const char *msg = lua_tostring(L, -1);
00070     if (msg == NULL) msg = "(error object is not a string)";
00071     l_message(progname, msg);
00072     lua_pop(L, 1);
00073   }
00074   return status;
00075 }
00076 
00077 
00078 static int traceback (lua_State *L) {
00079   if (!lua_isstring(L, 1))  /* 'message' not a string? */
00080     return 1;  /* keep it intact */
00081   lua_getfield(L, LUA_GLOBALSINDEX, "debug");
00082   if (!lua_istable(L, -1)) {
00083     lua_pop(L, 1);
00084     return 1;
00085   }
00086   lua_getfield(L, -1, "traceback");
00087   if (!lua_isfunction(L, -1)) {
00088     lua_pop(L, 2);
00089     return 1;
00090   }
00091   lua_pushvalue(L, 1);  /* pass error message */
00092   lua_pushinteger(L, 2);  /* skip this function and traceback */
00093   lua_call(L, 2, 1);  /* call debug.traceback */
00094   return 1;
00095 }
00096 
00097 
00098 static int docall (lua_State *L, int narg, int clear) {
00099   int status;
00100   int base = lua_gettop(L) - narg;  /* function index */
00101   lua_pushcfunction(L, traceback);  /* push traceback function */
00102   lua_insert(L, base);  /* put it under chunk and args */
00103 #if !defined(LUA_SYMBIAN)
00104   signal(SIGINT, laction);
00105 #endif
00106   status = lua_pcall(L, narg, (clear ? 0 : LUA_MULTRET), base);
00107 #if !defined(LUA_SYMBIAN)
00108   signal(SIGINT, SIG_DFL);
00109 #endif
00110   lua_remove(L, base);  /* remove traceback function */
00111   /* force a complete garbage collection in case of errors */
00112   if (status != 0) lua_gc(L, LUA_GCCOLLECT, 0);
00113   return status;
00114 }
00115 
00116 
00117 static void print_version (void) {
00118   l_message(NULL, LUA_RELEASE "  " LUA_COPYRIGHT);
00119 }
00120 
00121 
00122 static int getargs (lua_State *L, char **argv, int n) {
00123   int narg;
00124   int i;
00125   int argc = 0;
00126   while (argv[argc]) argc++;  /* count total number of arguments */
00127   narg = argc - (n + 1);  /* number of arguments to the script */
00128   luaL_checkstack(L, narg + 3, "too many arguments to script");
00129   for (i=n+1; i < argc; i++)
00130     lua_pushstring(L, argv[i]);
00131   lua_createtable(L, narg, n + 1);
00132   for (i=0; i < argc; i++) {
00133     lua_pushstring(L, argv[i]);
00134     lua_rawseti(L, -2, i - n);
00135   }
00136   return narg;
00137 }
00138 
00139 
00140 static int dofile (lua_State *L, const char *name) {
00141   int status = luaL_loadfile(L, name) || docall(L, 0, 1);
00142   return report(L, status);
00143 }
00144 
00145 
00146 static int dostring (lua_State *L, const char *s, const char *name) {
00147   int status = luaL_loadbuffer(L, s, strlen(s), name) || docall(L, 0, 1);
00148   return report(L, status);
00149 }
00150 
00151 
00152 static int dolibrary (lua_State *L, const char *name) {
00153   lua_getglobal(L, "require");
00154   lua_pushstring(L, name);
00155   return report(L, docall(L, 1, 1));
00156 }
00157 
00158 
00159 static const char *get_prompt (lua_State *L, int firstline) {
00160   const char *p;
00161   lua_getfield(L, LUA_GLOBALSINDEX, firstline ? "_PROMPT" : "_PROMPT2");
00162   p = lua_tostring(L, -1);
00163   if (p == NULL) p = (firstline ? LUA_PROMPT : LUA_PROMPT2);
00164   lua_pop(L, 1);  /* remove global */
00165   return p;
00166 }
00167 
00168 
00169 static int incomplete (lua_State *L, int status) {
00170   if (status == LUA_ERRSYNTAX) {
00171     size_t lmsg;
00172     const char *msg = lua_tolstring(L, -1, &lmsg);
00173     const char *tp = msg + lmsg - (sizeof(LUA_QL("<eof>")) - 1);
00174     if (strstr(msg, LUA_QL("<eof>")) == tp) {
00175       lua_pop(L, 1);
00176       return 1;
00177     }
00178   }
00179   return 0;  /* else... */
00180 }
00181 
00182 
00183 static int pushline (lua_State *L, int firstline) {
00184   char buffer[LUA_MAXINPUT];
00185   char *b = buffer;
00186   size_t l;
00187   const char *prmt = get_prompt(L, firstline);
00188   if (lua_readline(L, b, prmt) == 0)
00189     return 0;  /* no input */
00190   l = strlen(b);
00191   if (l > 0 && b[l-1] == '\n')  /* line ends with newline? */
00192     b[l-1] = '\0';  /* remove it */
00193   if (firstline && b[0] == '=')  /* first line starts with `=' ? */
00194     lua_pushfstring(L, "return %s", b+1);  /* change it to `return' */
00195   else
00196     lua_pushstring(L, b);
00197   lua_freeline(L, b);
00198   return 1;
00199 }
00200 
00201 
00202 static int loadline (lua_State *L) {
00203   int status;
00204   lua_settop(L, 0);
00205   if (!pushline(L, 1))
00206     return -1;  /* no input */
00207   for (;;) {  /* repeat until gets a complete line */
00208     status = luaL_loadbuffer(L, lua_tostring(L, 1), lua_strlen(L, 1), "=stdin");
00209     if (!incomplete(L, status)) break;  /* cannot try to add lines? */
00210     if (!pushline(L, 0))  /* no more input? */
00211       return -1;
00212     lua_pushliteral(L, "\n");  /* add a new line... */
00213     lua_insert(L, -2);  /* ...between the two lines */
00214     lua_concat(L, 3);  /* join them */
00215   }
00216   lua_saveline(L, 1);
00217   lua_remove(L, 1);  /* remove line */
00218   return status;
00219 }
00220 
00221 
00222 static void dotty (lua_State *L) {
00223   int status;
00224   const char *oldprogname = progname;
00225   progname = NULL;
00226   while ((status = loadline(L)) != -1) {
00227     if (status == 0) status = docall(L, 0, 0);
00228     report(L, status);
00229     if (status == 0 && lua_gettop(L) > 0) {  /* any result to print? */
00230       lua_getglobal(L, "print");
00231       lua_insert(L, 1);
00232       if (lua_pcall(L, lua_gettop(L)-1, 0, 0) != 0)
00233         l_message(progname, lua_pushfstring(L,
00234                                "error calling " LUA_QL("print") " (%s)",
00235                                lua_tostring(L, -1)));
00236     }
00237   }
00238   lua_settop(L, 0);  /* clear stack */
00239   fputs("\n", stdout);
00240   fflush(stdout);
00241   progname = oldprogname;
00242 }
00243 
00244 
00245 static int handle_script (lua_State *L, char **argv, int n) {
00246   int status;
00247   const char *fname;
00248   int narg = getargs(L, argv, n);  /* collect arguments */
00249   lua_setglobal(L, "arg");
00250   fname = argv[n];
00251   if (strcmp(fname, "-") == 0 && strcmp(argv[n-1], "--") != 0) 
00252     fname = NULL;  /* stdin */
00253   status = luaL_loadfile(L, fname);
00254   lua_insert(L, -(narg+1));
00255   if (status == 0)
00256     status = docall(L, narg, 0);
00257   else
00258     lua_pop(L, narg);      
00259   return report(L, status);
00260 }
00261 
00262 
00263 /* check that argument has no extra characters at the end */
00264 #define notail(x) {if ((x)[2] != '\0') return -1;}
00265 
00266 
00267 static int collectargs (char **argv, int *pi, int *pv, int *pe) {
00268   int i;
00269   for (i = 1; argv[i] != NULL; i++) {
00270     if (argv[i][0] != '-')  /* not an option? */
00271         return i;
00272     switch (argv[i][1]) {  /* option */
00273       case '-':
00274         notail(argv[i]);
00275         return (argv[i+1] != NULL ? i+1 : 0);
00276       case '\0':
00277         return i;
00278       case 'i':
00279         notail(argv[i]);
00280         *pi = 1;  /* go through */
00281       case 'v':
00282         notail(argv[i]);
00283         *pv = 1;
00284         break;
00285       case 'e':
00286         *pe = 1;  /* go through */
00287       case 'l':
00288         if (argv[i][2] == '\0') {
00289           i++;
00290           if (argv[i] == NULL) return -1;
00291         }
00292         break;
00293       default: return -1;  /* invalid option */
00294     }
00295   }
00296   return 0;
00297 }
00298 
00299 
00300 static int runargs (lua_State *L, char **argv, int n) {
00301   int i;
00302   for (i = 1; i < n; i++) {
00303     if (argv[i] == NULL) continue;
00304     lua_assert(argv[i][0] == '-');
00305     switch (argv[i][1]) {  /* option */
00306       case 'e': {
00307         const char *chunk = argv[i] + 2;
00308         if (*chunk == '\0') chunk = argv[++i];
00309         lua_assert(chunk != NULL);
00310         if (dostring(L, chunk, "=(command line)") != 0)
00311           return 1;
00312         break;
00313       }
00314       case 'l': {
00315         const char *filename = argv[i] + 2;
00316         if (*filename == '\0') filename = argv[++i];
00317         lua_assert(filename != NULL);
00318         if (dolibrary(L, filename))
00319           return 1;  /* stop if file fails */
00320         break;
00321       }
00322       default: break;
00323     }
00324   }
00325   return 0;
00326 }
00327 
00328 
00329 static int handle_luainit (lua_State *L) {
00330   const char *init = getenv(LUA_INIT);
00331   if (init == NULL) return 0;  /* status OK */
00332   else if (init[0] == '@')
00333     return dofile(L, init+1);
00334   else
00335     return dostring(L, init, "=" LUA_INIT);
00336 }
00337 
00338 
00339 struct Smain {
00340   int argc;
00341   char **argv;
00342   int status;
00343 };
00344 
00345 
00346 static int pmain (lua_State *L) {
00347   struct Smain *s = (struct Smain *)lua_touserdata(L, 1);
00348   char **argv = s->argv;
00349   int script;
00350   int has_i = 0, has_v = 0, has_e = 0;
00351   globalL = L;
00352   if (argv[0] && argv[0][0]) progname = argv[0];
00353   lua_gc(L, LUA_GCSTOP, 0);  /* stop collector during initialization */
00354   luaL_openlibs(L);  /* open libraries */
00355   lua_gc(L, LUA_GCRESTART, 0);
00356   s->status = handle_luainit(L);
00357   if (s->status != 0) return 0;
00358   script = collectargs(argv, &has_i, &has_v, &has_e);
00359   if (script < 0) {  /* invalid args? */
00360     print_usage();
00361     s->status = 1;
00362     return 0;
00363   }
00364   if (has_v) print_version();
00365   s->status = runargs(L, argv, (script > 0) ? script : s->argc);
00366   if (s->status != 0) return 0;
00367   if (script)
00368     s->status = handle_script(L, argv, script);
00369   if (s->status != 0) return 0;
00370   if (has_i)
00371     dotty(L);
00372   else if (script == 0 && !has_e && !has_v) {
00373     if (lua_stdin_is_tty()) {
00374       print_version();
00375       dotty(L);
00376     }
00377     else dofile(L, NULL);  /* executes stdin as a file */
00378   }
00379   return 0;
00380 }
00381 
00382 
00383 int main (int argc, char **argv) {
00384   int status;
00385   struct Smain s;
00386   lua_State *L = lua_open();  /* create state */
00387   if (L == NULL) {
00388     l_message(argv[0], "cannot create state: not enough memory");
00389     return EXIT_FAILURE;
00390   }
00391   s.argc = argc;
00392   s.argv = argv;
00393   status = lua_cpcall(L, &pmain, &s);
00394   report(L, status);
00395   lua_close(L);
00396   return (status || s.status) ? EXIT_FAILURE : EXIT_SUCCESS;
00397 }
00398 

ContextLogger2—ContextLogger2 Logger Daemon Internals—Generated on Mon May 2 13:49:54 2011 by Doxygen 1.6.1