lua.c
上传用户:yisoukefu
上传日期:2020-08-09
资源大小:39506k
文件大小:10k
源码类别:

其他游戏

开发平台:

Visual C++

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