|
@@ -1,5 +1,5 @@
|
|
|
/*
|
|
|
-** $Id: lua.c,v 1.232 2017/05/24 21:11:19 roberto Exp roberto $
|
|
|
+** $Id: lua.c,v 1.233 2018/02/06 15:32:36 roberto Exp roberto $
|
|
|
** Lua stand-alone interpreter
|
|
|
** See Copyright Notice in lua.h
|
|
|
*/
|
|
@@ -21,20 +21,10 @@
|
|
|
#include "lualib.h"
|
|
|
|
|
|
|
|
|
-
|
|
|
-#if !defined(LUA_PROMPT)
|
|
|
-#define LUA_PROMPT "> "
|
|
|
-#define LUA_PROMPT2 ">> "
|
|
|
-#endif
|
|
|
-
|
|
|
#if !defined(LUA_PROGNAME)
|
|
|
#define LUA_PROGNAME "lua"
|
|
|
#endif
|
|
|
|
|
|
-#if !defined(LUA_MAXINPUT)
|
|
|
-#define LUA_MAXINPUT 512
|
|
|
-#endif
|
|
|
-
|
|
|
#if !defined(LUA_INIT_VAR)
|
|
|
#define LUA_INIT_VAR "LUA_INIT"
|
|
|
#endif
|
|
@@ -42,65 +32,6 @@
|
|
|
#define LUA_INITVARVERSION LUA_INIT_VAR LUA_VERSUFFIX
|
|
|
|
|
|
|
|
|
-/*
|
|
|
-** lua_stdin_is_tty detects whether the standard input is a 'tty' (that
|
|
|
-** is, whether we're running lua interactively).
|
|
|
-*/
|
|
|
-#if !defined(lua_stdin_is_tty) /* { */
|
|
|
-
|
|
|
-#if defined(LUA_USE_POSIX) /* { */
|
|
|
-
|
|
|
-#include <unistd.h>
|
|
|
-#define lua_stdin_is_tty() isatty(0)
|
|
|
-
|
|
|
-#elif defined(LUA_USE_WINDOWS) /* }{ */
|
|
|
-
|
|
|
-#include <io.h>
|
|
|
-#include <windows.h>
|
|
|
-
|
|
|
-#define lua_stdin_is_tty() _isatty(_fileno(stdin))
|
|
|
-
|
|
|
-#else /* }{ */
|
|
|
-
|
|
|
-/* ISO C definition */
|
|
|
-#define lua_stdin_is_tty() 1 /* assume stdin is a tty */
|
|
|
-
|
|
|
-#endif /* } */
|
|
|
-
|
|
|
-#endif /* } */
|
|
|
-
|
|
|
-
|
|
|
-/*
|
|
|
-** lua_readline defines how to show a prompt and then read a line from
|
|
|
-** the standard input.
|
|
|
-** lua_saveline defines how to "save" a read line in a "history".
|
|
|
-** lua_freeline defines how to free a line read by lua_readline.
|
|
|
-*/
|
|
|
-#if !defined(lua_readline) /* { */
|
|
|
-
|
|
|
-#if defined(LUA_USE_READLINE) /* { */
|
|
|
-
|
|
|
-#include <readline/readline.h>
|
|
|
-#include <readline/history.h>
|
|
|
-#define lua_readline(L,b,p) ((void)L, ((b)=readline(p)) != NULL)
|
|
|
-#define lua_saveline(L,line) ((void)L, add_history(line))
|
|
|
-#define lua_freeline(L,b) ((void)L, free(b))
|
|
|
-
|
|
|
-#else /* }{ */
|
|
|
-
|
|
|
-#define lua_readline(L,b,p) \
|
|
|
- ((void)L, fputs(p, stdout), fflush(stdout), /* show prompt */ \
|
|
|
- fgets(b, LUA_MAXINPUT, stdin) != NULL) /* get line */
|
|
|
-#define lua_saveline(L,line) { (void)L; (void)line; }
|
|
|
-#define lua_freeline(L,b) { (void)L; (void)b; }
|
|
|
-
|
|
|
-#endif /* } */
|
|
|
-
|
|
|
-#endif /* } */
|
|
|
-
|
|
|
-
|
|
|
-
|
|
|
-
|
|
|
static lua_State *globalL = NULL;
|
|
|
|
|
|
static const char *progname = LUA_PROGNAME;
|
|
@@ -268,6 +199,207 @@ static int dolibrary (lua_State *L, const char *name) {
|
|
|
}
|
|
|
|
|
|
|
|
|
+/*
|
|
|
+** Push on the stack the contents of table 'arg' from 1 to #arg
|
|
|
+*/
|
|
|
+static int pushargs (lua_State *L) {
|
|
|
+ int i, n;
|
|
|
+ if (lua_getglobal(L, "arg") != LUA_TTABLE)
|
|
|
+ luaL_error(L, "'arg' is not a table");
|
|
|
+ n = (int)luaL_len(L, -1);
|
|
|
+ luaL_checkstack(L, n + 3, "too many arguments to script");
|
|
|
+ for (i = 1; i <= n; i++)
|
|
|
+ lua_rawgeti(L, -i, i);
|
|
|
+ lua_remove(L, -i); /* remove table from the stack */
|
|
|
+ return n;
|
|
|
+}
|
|
|
+
|
|
|
+
|
|
|
+static int handle_script (lua_State *L, char **argv) {
|
|
|
+ int status;
|
|
|
+ const char *fname = argv[0];
|
|
|
+ if (strcmp(fname, "-") == 0 && strcmp(argv[-1], "--") != 0)
|
|
|
+ fname = NULL; /* stdin */
|
|
|
+ status = luaL_loadfile(L, fname);
|
|
|
+ if (status == LUA_OK) {
|
|
|
+ int n = pushargs(L); /* push arguments to script */
|
|
|
+ status = docall(L, n, LUA_MULTRET);
|
|
|
+ }
|
|
|
+ return report(L, status);
|
|
|
+}
|
|
|
+
|
|
|
+
|
|
|
+/* bits of various argument indicators in 'args' */
|
|
|
+#define has_error 1 /* bad option */
|
|
|
+#define has_i 2 /* -i */
|
|
|
+#define has_v 4 /* -v */
|
|
|
+#define has_e 8 /* -e */
|
|
|
+#define has_E 16 /* -E */
|
|
|
+
|
|
|
+
|
|
|
+/*
|
|
|
+** Traverses all arguments from 'argv', returning a mask with those
|
|
|
+** needed before running any Lua code (or an error code if it finds
|
|
|
+** any invalid argument). 'first' returns the first not-handled argument
|
|
|
+** (either the script name or a bad argument in case of error).
|
|
|
+*/
|
|
|
+static int collectargs (char **argv, int *first) {
|
|
|
+ int args = 0;
|
|
|
+ int i;
|
|
|
+ for (i = 1; argv[i] != NULL; i++) {
|
|
|
+ *first = i;
|
|
|
+ if (argv[i][0] != '-') /* not an option? */
|
|
|
+ return args; /* stop handling options */
|
|
|
+ switch (argv[i][1]) { /* else check option */
|
|
|
+ case '-': /* '--' */
|
|
|
+ if (argv[i][2] != '\0') /* extra characters after '--'? */
|
|
|
+ return has_error; /* invalid option */
|
|
|
+ *first = i + 1;
|
|
|
+ return args;
|
|
|
+ case '\0': /* '-' */
|
|
|
+ return args; /* script "name" is '-' */
|
|
|
+ case 'E':
|
|
|
+ if (argv[i][2] != '\0') /* extra characters after 1st? */
|
|
|
+ return has_error; /* invalid option */
|
|
|
+ args |= has_E;
|
|
|
+ break;
|
|
|
+ case 'i':
|
|
|
+ args |= has_i; /* (-i implies -v) *//* FALLTHROUGH */
|
|
|
+ case 'v':
|
|
|
+ if (argv[i][2] != '\0') /* extra characters after 1st? */
|
|
|
+ return has_error; /* invalid option */
|
|
|
+ args |= has_v;
|
|
|
+ break;
|
|
|
+ case 'e':
|
|
|
+ args |= has_e; /* FALLTHROUGH */
|
|
|
+ case 'l': /* both options need an argument */
|
|
|
+ if (argv[i][2] == '\0') { /* no concatenated argument? */
|
|
|
+ i++; /* try next 'argv' */
|
|
|
+ if (argv[i] == NULL || argv[i][0] == '-')
|
|
|
+ return has_error; /* no next argument or it is another option */
|
|
|
+ }
|
|
|
+ break;
|
|
|
+ default: /* invalid option */
|
|
|
+ return has_error;
|
|
|
+ }
|
|
|
+ }
|
|
|
+ *first = i; /* no script name */
|
|
|
+ return args;
|
|
|
+}
|
|
|
+
|
|
|
+
|
|
|
+/*
|
|
|
+** Processes options 'e' and 'l', which involve running Lua code.
|
|
|
+** Returns 0 if some code raises an error.
|
|
|
+*/
|
|
|
+static int runargs (lua_State *L, char **argv, int n) {
|
|
|
+ int i;
|
|
|
+ for (i = 1; i < n; i++) {
|
|
|
+ int option = argv[i][1];
|
|
|
+ lua_assert(argv[i][0] == '-'); /* already checked */
|
|
|
+ if (option == 'e' || option == 'l') {
|
|
|
+ int status;
|
|
|
+ const char *extra = argv[i] + 2; /* both options need an argument */
|
|
|
+ if (*extra == '\0') extra = argv[++i];
|
|
|
+ lua_assert(extra != NULL);
|
|
|
+ status = (option == 'e')
|
|
|
+ ? dostring(L, extra, "=(command line)")
|
|
|
+ : dolibrary(L, extra);
|
|
|
+ if (status != LUA_OK) return 0;
|
|
|
+ }
|
|
|
+ }
|
|
|
+ return 1;
|
|
|
+}
|
|
|
+
|
|
|
+
|
|
|
+static int handle_luainit (lua_State *L) {
|
|
|
+ const char *name = "=" LUA_INITVARVERSION;
|
|
|
+ const char *init = getenv(name + 1);
|
|
|
+ if (init == NULL) {
|
|
|
+ name = "=" LUA_INIT_VAR;
|
|
|
+ init = getenv(name + 1); /* try alternative name */
|
|
|
+ }
|
|
|
+ if (init == NULL) return LUA_OK;
|
|
|
+ else if (init[0] == '@')
|
|
|
+ return dofile(L, init+1);
|
|
|
+ else
|
|
|
+ return dostring(L, init, name);
|
|
|
+}
|
|
|
+
|
|
|
+
|
|
|
+/*
|
|
|
+** {==================================================================
|
|
|
+** Read-Eval-Print Loop (REPL)
|
|
|
+** ===================================================================
|
|
|
+*/
|
|
|
+
|
|
|
+#if !defined(LUA_PROMPT)
|
|
|
+#define LUA_PROMPT "> "
|
|
|
+#define LUA_PROMPT2 ">> "
|
|
|
+#endif
|
|
|
+
|
|
|
+#if !defined(LUA_MAXINPUT)
|
|
|
+#define LUA_MAXINPUT 512
|
|
|
+#endif
|
|
|
+
|
|
|
+
|
|
|
+/*
|
|
|
+** lua_stdin_is_tty detects whether the standard input is a 'tty' (that
|
|
|
+** is, whether we're running lua interactively).
|
|
|
+*/
|
|
|
+#if !defined(lua_stdin_is_tty) /* { */
|
|
|
+
|
|
|
+#if defined(LUA_USE_POSIX) /* { */
|
|
|
+
|
|
|
+#include <unistd.h>
|
|
|
+#define lua_stdin_is_tty() isatty(0)
|
|
|
+
|
|
|
+#elif defined(LUA_USE_WINDOWS) /* }{ */
|
|
|
+
|
|
|
+#include <io.h>
|
|
|
+#include <windows.h>
|
|
|
+
|
|
|
+#define lua_stdin_is_tty() _isatty(_fileno(stdin))
|
|
|
+
|
|
|
+#else /* }{ */
|
|
|
+
|
|
|
+/* ISO C definition */
|
|
|
+#define lua_stdin_is_tty() 1 /* assume stdin is a tty */
|
|
|
+
|
|
|
+#endif /* } */
|
|
|
+
|
|
|
+#endif /* } */
|
|
|
+
|
|
|
+
|
|
|
+/*
|
|
|
+** lua_readline defines how to show a prompt and then read a line from
|
|
|
+** the standard input.
|
|
|
+** lua_saveline defines how to "save" a read line in a "history".
|
|
|
+** lua_freeline defines how to free a line read by lua_readline.
|
|
|
+*/
|
|
|
+#if !defined(lua_readline) /* { */
|
|
|
+
|
|
|
+#if defined(LUA_USE_READLINE) /* { */
|
|
|
+
|
|
|
+#include <readline/readline.h>
|
|
|
+#include <readline/history.h>
|
|
|
+#define lua_readline(L,b,p) ((void)L, ((b)=readline(p)) != NULL)
|
|
|
+#define lua_saveline(L,line) ((void)L, add_history(line))
|
|
|
+#define lua_freeline(L,b) ((void)L, free(b))
|
|
|
+
|
|
|
+#else /* }{ */
|
|
|
+
|
|
|
+#define lua_readline(L,b,p) \
|
|
|
+ ((void)L, fputs(p, stdout), fflush(stdout), /* show prompt */ \
|
|
|
+ fgets(b, LUA_MAXINPUT, stdin) != NULL) /* get line */
|
|
|
+#define lua_saveline(L,line) { (void)L; (void)line; }
|
|
|
+#define lua_freeline(L,b) { (void)L; (void)b; }
|
|
|
+
|
|
|
+#endif /* } */
|
|
|
+
|
|
|
+#endif /* } */
|
|
|
+
|
|
|
+
|
|
|
/*
|
|
|
** Returns the string to be used as a prompt by the interpreter.
|
|
|
*/
|
|
@@ -418,134 +550,7 @@ static void doREPL (lua_State *L) {
|
|
|
progname = oldprogname;
|
|
|
}
|
|
|
|
|
|
-
|
|
|
-/*
|
|
|
-** Push on the stack the contents of table 'arg' from 1 to #arg
|
|
|
-*/
|
|
|
-static int pushargs (lua_State *L) {
|
|
|
- int i, n;
|
|
|
- if (lua_getglobal(L, "arg") != LUA_TTABLE)
|
|
|
- luaL_error(L, "'arg' is not a table");
|
|
|
- n = (int)luaL_len(L, -1);
|
|
|
- luaL_checkstack(L, n + 3, "too many arguments to script");
|
|
|
- for (i = 1; i <= n; i++)
|
|
|
- lua_rawgeti(L, -i, i);
|
|
|
- lua_remove(L, -i); /* remove table from the stack */
|
|
|
- return n;
|
|
|
-}
|
|
|
-
|
|
|
-
|
|
|
-static int handle_script (lua_State *L, char **argv) {
|
|
|
- int status;
|
|
|
- const char *fname = argv[0];
|
|
|
- if (strcmp(fname, "-") == 0 && strcmp(argv[-1], "--") != 0)
|
|
|
- fname = NULL; /* stdin */
|
|
|
- status = luaL_loadfile(L, fname);
|
|
|
- if (status == LUA_OK) {
|
|
|
- int n = pushargs(L); /* push arguments to script */
|
|
|
- status = docall(L, n, LUA_MULTRET);
|
|
|
- }
|
|
|
- return report(L, status);
|
|
|
-}
|
|
|
-
|
|
|
-
|
|
|
-
|
|
|
-/* bits of various argument indicators in 'args' */
|
|
|
-#define has_error 1 /* bad option */
|
|
|
-#define has_i 2 /* -i */
|
|
|
-#define has_v 4 /* -v */
|
|
|
-#define has_e 8 /* -e */
|
|
|
-#define has_E 16 /* -E */
|
|
|
-
|
|
|
-/*
|
|
|
-** Traverses all arguments from 'argv', returning a mask with those
|
|
|
-** needed before running any Lua code (or an error code if it finds
|
|
|
-** any invalid argument). 'first' returns the first not-handled argument
|
|
|
-** (either the script name or a bad argument in case of error).
|
|
|
-*/
|
|
|
-static int collectargs (char **argv, int *first) {
|
|
|
- int args = 0;
|
|
|
- int i;
|
|
|
- for (i = 1; argv[i] != NULL; i++) {
|
|
|
- *first = i;
|
|
|
- if (argv[i][0] != '-') /* not an option? */
|
|
|
- return args; /* stop handling options */
|
|
|
- switch (argv[i][1]) { /* else check option */
|
|
|
- case '-': /* '--' */
|
|
|
- if (argv[i][2] != '\0') /* extra characters after '--'? */
|
|
|
- return has_error; /* invalid option */
|
|
|
- *first = i + 1;
|
|
|
- return args;
|
|
|
- case '\0': /* '-' */
|
|
|
- return args; /* script "name" is '-' */
|
|
|
- case 'E':
|
|
|
- if (argv[i][2] != '\0') /* extra characters after 1st? */
|
|
|
- return has_error; /* invalid option */
|
|
|
- args |= has_E;
|
|
|
- break;
|
|
|
- case 'i':
|
|
|
- args |= has_i; /* (-i implies -v) *//* FALLTHROUGH */
|
|
|
- case 'v':
|
|
|
- if (argv[i][2] != '\0') /* extra characters after 1st? */
|
|
|
- return has_error; /* invalid option */
|
|
|
- args |= has_v;
|
|
|
- break;
|
|
|
- case 'e':
|
|
|
- args |= has_e; /* FALLTHROUGH */
|
|
|
- case 'l': /* both options need an argument */
|
|
|
- if (argv[i][2] == '\0') { /* no concatenated argument? */
|
|
|
- i++; /* try next 'argv' */
|
|
|
- if (argv[i] == NULL || argv[i][0] == '-')
|
|
|
- return has_error; /* no next argument or it is another option */
|
|
|
- }
|
|
|
- break;
|
|
|
- default: /* invalid option */
|
|
|
- return has_error;
|
|
|
- }
|
|
|
- }
|
|
|
- *first = i; /* no script name */
|
|
|
- return args;
|
|
|
-}
|
|
|
-
|
|
|
-
|
|
|
-/*
|
|
|
-** Processes options 'e' and 'l', which involve running Lua code.
|
|
|
-** Returns 0 if some code raises an error.
|
|
|
-*/
|
|
|
-static int runargs (lua_State *L, char **argv, int n) {
|
|
|
- int i;
|
|
|
- for (i = 1; i < n; i++) {
|
|
|
- int option = argv[i][1];
|
|
|
- lua_assert(argv[i][0] == '-'); /* already checked */
|
|
|
- if (option == 'e' || option == 'l') {
|
|
|
- int status;
|
|
|
- const char *extra = argv[i] + 2; /* both options need an argument */
|
|
|
- if (*extra == '\0') extra = argv[++i];
|
|
|
- lua_assert(extra != NULL);
|
|
|
- status = (option == 'e')
|
|
|
- ? dostring(L, extra, "=(command line)")
|
|
|
- : dolibrary(L, extra);
|
|
|
- if (status != LUA_OK) return 0;
|
|
|
- }
|
|
|
- }
|
|
|
- return 1;
|
|
|
-}
|
|
|
-
|
|
|
-
|
|
|
-
|
|
|
-static int handle_luainit (lua_State *L) {
|
|
|
- const char *name = "=" LUA_INITVARVERSION;
|
|
|
- const char *init = getenv(name + 1);
|
|
|
- if (init == NULL) {
|
|
|
- name = "=" LUA_INIT_VAR;
|
|
|
- init = getenv(name + 1); /* try alternative name */
|
|
|
- }
|
|
|
- if (init == NULL) return LUA_OK;
|
|
|
- else if (init[0] == '@')
|
|
|
- return dofile(L, init+1);
|
|
|
- else
|
|
|
- return dostring(L, init, name);
|
|
|
-}
|
|
|
+/* }================================================================== */
|
|
|
|
|
|
|
|
|
/*
|