better modularization of the code for the REPL
This commit is contained in:
401
lua.c
401
lua.c
@@ -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
|
** Lua stand-alone interpreter
|
||||||
** See Copyright Notice in lua.h
|
** See Copyright Notice in lua.h
|
||||||
*/
|
*/
|
||||||
@@ -21,20 +21,10 @@
|
|||||||
#include "lualib.h"
|
#include "lualib.h"
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
#if !defined(LUA_PROMPT)
|
|
||||||
#define LUA_PROMPT "> "
|
|
||||||
#define LUA_PROMPT2 ">> "
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#if !defined(LUA_PROGNAME)
|
#if !defined(LUA_PROGNAME)
|
||||||
#define LUA_PROGNAME "lua"
|
#define LUA_PROGNAME "lua"
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#if !defined(LUA_MAXINPUT)
|
|
||||||
#define LUA_MAXINPUT 512
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#if !defined(LUA_INIT_VAR)
|
#if !defined(LUA_INIT_VAR)
|
||||||
#define LUA_INIT_VAR "LUA_INIT"
|
#define LUA_INIT_VAR "LUA_INIT"
|
||||||
#endif
|
#endif
|
||||||
@@ -42,65 +32,6 @@
|
|||||||
#define LUA_INITVARVERSION LUA_INIT_VAR LUA_VERSUFFIX
|
#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 lua_State *globalL = NULL;
|
||||||
|
|
||||||
static const char *progname = LUA_PROGNAME;
|
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.
|
** Returns the string to be used as a prompt by the interpreter.
|
||||||
*/
|
*/
|
||||||
@@ -418,134 +550,7 @@ static void doREPL (lua_State *L) {
|
|||||||
progname = oldprogname;
|
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);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
|||||||
Reference in New Issue
Block a user