Welcome to mirror list, hosted at ThFree Co, Russian Federation.

github.com/torch/luajit-rocks.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorRonan Collobert <ronan@collobert.com>2014-11-04 04:09:28 +0300
committerRonan Collobert <ronan@collobert.com>2014-11-04 04:09:28 +0300
commit98b159ad2709c81cd539b0e93bcfb5af38308a38 (patch)
tree8e506ca3933c52b24c45a748c05ca4aaaddfff88
parent7f0ec4e6fb781dc0b02365d4b512665cfa609a19 (diff)
added readline support for luajit 2.0
-rw-r--r--luajit-2.0/src/luajit.c313
1 files changed, 302 insertions, 11 deletions
diff --git a/luajit-2.0/src/luajit.c b/luajit-2.0/src/luajit.c
index e034343..4e85908 100644
--- a/luajit-2.0/src/luajit.c
+++ b/luajit-2.0/src/luajit.c
@@ -40,6 +40,285 @@
static lua_State *globalL = NULL;
static const char *progname = LUA_PROGNAME;
+/* ------------------------------------------------------------------------ */
+
+#ifdef 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,idx) \
+ if (lua_strlen(L,idx) > 0) /* non-empty line? */ \
+ add_history(lua_tostring(L, idx)); /* add it to history */
+#define lua_freeline(L,b) ((void)L, free(b))
+
+/*
+** Lua 5.1.4 advanced readline support for the GNU readline and history
+** libraries or compatible replacements.
+**
+** Author: Mike Pall.
+** Maintainer: Sean Bolton (sean at smbolton dot com).
+**
+** Copyright (C) 2004-2006, 2011 Mike Pall. Same license as Lua. See lua.h.
+**
+** Advanced features:
+** - Completion of keywords and global variable names.
+** - Recursive and metatable-aware completion of variable names.
+** - Context sensitive delimiter completion.
+** - Save/restore of the history to/from a file (LUA_HISTORY env variable).
+** - Setting a limit for the size of the history (LUA_HISTSIZE env variable).
+** - Setting the app name to allow for $if lua ... $endif in ~/.inputrc.
+**
+** Start lua and try these (replace ~ with the TAB key):
+**
+** ~~
+** fu~foo() ret~fa~end<CR>
+** io~~~s~~~o~~~w~"foo\n")<CR>
+**
+** The ~~ are just for demonstration purposes (io~s~o~w~ suffices, of course).
+**
+** If you are used to zsh/tcsh-style completion support, try adding
+** 'TAB: menu-complete' and 'C-d: possible-completions' to your ~/.inputrc.
+**
+** The patch has been successfully tested with:
+**
+** GNU readline 2.2.1 (1998-07-17)
+** GNU readline 4.0 (1999-02-18) [harmless compiler warning]
+** GNU readline 4.3 (2002-07-16)
+** GNU readline 5.0 (2004-07-27)
+** GNU readline 5.1 (2005-12-07)
+** GNU readline 5.2 (2006-10-11)
+** GNU readline 6.0 (2009-02-20)
+** GNU readline 6.2 (2011-02-13)
+** MacOSX libedit 2.11 (2008-07-12)
+** NETBSD libedit 2.6.5 (2002-03-25)
+** NETBSD libedit 2.6.9 (2004-05-01)
+**
+** Change Log:
+** 2004-2006 Mike Pall - original patch
+** 2009/08/24 Sean Bolton - updated for GNU readline version 6
+** 2011/12/14 Sean Bolton - fixed segfault when using Mac OS X libedit 2.11
+*/
+
+#include <ctype.h>
+
+static char *lua_rl_hist;
+static int lua_rl_histsize;
+
+static lua_State *lua_rl_L; /* User data is not passed to rl callbacks. */
+
+/* Reserved keywords. */
+static const char *const lua_rl_keywords[] = {
+ "and", "break", "do", "else", "elseif", "end", "false",
+ "for", "function", "if", "in", "local", "nil", "not", "or",
+ "repeat", "return", "then", "true", "until", "while", NULL
+};
+
+static int valididentifier(const char *s)
+{
+ if (!(isalpha(*s) || *s == '_')) return 0;
+ for (s++; *s; s++) if (!(isalpha(*s) || isdigit(*s) || *s == '_')) return 0;
+ return 1;
+}
+
+/* Dynamically resizable match list. */
+typedef struct {
+ char **list;
+ size_t idx, allocated, matchlen;
+} dmlist;
+
+/* Add prefix + string + suffix to list and compute common prefix. */
+static int lua_rl_dmadd(dmlist *ml, const char *p, size_t pn, const char *s,
+ int suf)
+{
+ char *t = NULL;
+
+ if (ml->idx+1 >= ml->allocated &&
+ !(ml->list = realloc(ml->list, sizeof(char *)*(ml->allocated += 32))))
+ return -1;
+
+ if (s) {
+ size_t n = strlen(s);
+ if (!(t = (char *)malloc(sizeof(char)*(pn+n+(suf?2:1))))) return 1;
+ memcpy(t, p, pn);
+ memcpy(t+pn, s, n);
+ n += pn;
+ t[n] = suf;
+ if (suf) t[++n] = '\0';
+
+ if (ml->idx == 0) {
+ ml->matchlen = n;
+ } else {
+ size_t i;
+ for (i = 0; i < ml->matchlen && i < n && ml->list[1][i] == t[i]; i++) ;
+ ml->matchlen = i; /* Set matchlen to common prefix. */
+ }
+ }
+
+ ml->list[++ml->idx] = t;
+ return 0;
+}
+
+/* Get __index field of metatable of object on top of stack. */
+static int lua_rl_getmetaindex(lua_State *L)
+{
+ if (!lua_getmetatable(L, -1)) { lua_pop(L, 1); return 0; }
+
+ /* prefer __metatable if it exists */
+ lua_pushstring(L, "__metatable");
+ lua_rawget(L, -2);
+ if(lua_istable(L, -1))
+ {
+ lua_remove(L, -2);
+ return 1;
+ }
+ else
+ lua_pop(L, 1);
+
+ lua_pushstring(L, "__index");
+ lua_rawget(L, -2);
+ lua_replace(L, -2);
+ if (lua_isnil(L, -1) || lua_rawequal(L, -1, -2)) { lua_pop(L, 2); return 0; }
+ lua_replace(L, -2);
+ return 1;
+} /* 1: obj -- val, 0: obj -- */
+
+/* Get field from object on top of stack. Avoid calling metamethods. */
+static int lua_rl_getfield(lua_State *L, const char *s, size_t n)
+{
+ int i = 20; /* Avoid infinite metatable loops. */
+ do {
+ if (lua_istable(L, -1)) {
+ lua_pushlstring(L, s, n);
+ lua_rawget(L, -2);
+ if (!lua_isnil(L, -1)) { lua_replace(L, -2); return 1; }
+ lua_pop(L, 1);
+ }
+ } while (--i > 0 && lua_rl_getmetaindex(L));
+ lua_pop(L, 1);
+ return 0;
+} /* 1: obj -- val, 0: obj -- */
+
+/* Completion callback. */
+static char **lua_rl_complete(const char *text, int start, int end)
+{
+ lua_State *L = lua_rl_L;
+ dmlist ml;
+ const char *s;
+ size_t i, n, dot, loop;
+ int savetop;
+
+ if (!(text[0] == '\0' || isalpha(text[0]) || text[0] == '_')) return NULL;
+
+ ml.list = NULL;
+ ml.idx = ml.allocated = ml.matchlen = 0;
+
+ savetop = lua_gettop(L);
+ lua_pushvalue(L, LUA_GLOBALSINDEX);
+ for (n = (size_t)(end-start), i = dot = 0; i < n; i++)
+ if (text[i] == '.' || text[i] == ':') {
+ if (!lua_rl_getfield(L, text+dot, i-dot))
+ goto error; /* Invalid prefix. */
+ dot = i+1; /* Points to first char after dot/colon. */
+ }
+
+ /* Add all matches against keywords if there is no dot/colon. */
+ if (dot == 0)
+ for (i = 0; (s = lua_rl_keywords[i]) != NULL; i++)
+ if (!strncmp(s, text, n) && lua_rl_dmadd(&ml, NULL, 0, s, ' '))
+ goto error;
+
+ /* Add all valid matches from all tables/metatables. */
+ loop = 0; /* Avoid infinite metatable loops. */
+ do {
+ if (lua_istable(L, -1) &&
+ (loop == 0 || !lua_rawequal(L, -1, LUA_GLOBALSINDEX)))
+ for (lua_pushnil(L); lua_next(L, -2); lua_pop(L, 1))
+ if (lua_type(L, -2) == LUA_TSTRING) {
+ s = lua_tostring(L, -2);
+ /* Only match names starting with '_' if explicitly requested. */
+ if (!strncmp(s, text+dot, n-dot) && valididentifier(s) &&
+ (*s != '_' || text[dot] == '_')) {
+ int suf = ' '; /* Default suffix is a space. */
+ switch (lua_type(L, -1)) {
+ case LUA_TTABLE: suf = '.'; break; /* No way to guess ':'. */
+ case LUA_TFUNCTION: suf = '('; break;
+ case LUA_TUSERDATA:
+ if (lua_getmetatable(L, -1)) { lua_pop(L, 1); suf = ':'; }
+ break;
+ }
+ if (lua_rl_dmadd(&ml, text, dot, s, suf)) goto error;
+ }
+ }
+ } while (++loop < 20 && lua_rl_getmetaindex(L));
+
+ if (ml.idx == 0) {
+error:
+ lua_settop(L, savetop);
+ return NULL;
+ } else {
+ /* list[0] holds the common prefix of all matches (may be ""). */
+ /* If there is only one match, list[0] and list[1] will be the same. */
+ if (!(ml.list[0] = (char *)malloc(sizeof(char)*(ml.matchlen+1))))
+ goto error;
+ memcpy(ml.list[0], ml.list[1], ml.matchlen);
+ ml.list[0][ml.matchlen] = '\0';
+ /* Add the NULL list terminator. */
+ if (lua_rl_dmadd(&ml, NULL, 0, NULL, 0)) goto error;
+ }
+
+ lua_settop(L, savetop);
+#if RL_READLINE_VERSION >= 0x0600
+ rl_completion_suppress_append = 1;
+#endif
+ return ml.list;
+}
+
+/* Initialize readline library. */
+static void lua_rl_init(lua_State *L)
+{
+ char *s;
+
+ lua_rl_L = L;
+
+ /* This allows for $if lua ... $endif in ~/.inputrc. */
+ rl_readline_name = "lua";
+ /* Break words at every non-identifier character except '.' and ':'. */
+ rl_completer_word_break_characters =
+ "\t\r\n !\"#$%&'()*+,-/;<=>?@[\\]^`{|}~";
+ rl_completer_quote_characters = "\"'";
+#if RL_READLINE_VERSION < 0x0600
+ rl_completion_append_character = '\0';
+#endif
+ rl_attempted_completion_function = lua_rl_complete;
+ rl_initialize();
+
+ /* Start using history, optionally set history size and load history file. */
+ using_history();
+ if ((s = getenv("LUA_HISTSIZE")) &&
+ (lua_rl_histsize = atoi(s))) stifle_history(lua_rl_histsize);
+ if ((lua_rl_hist = getenv("LUA_HISTORY"))) read_history(lua_rl_hist);
+}
+
+/* Finalize readline library. */
+static void lua_rl_exit(lua_State *L)
+{
+ /* Optionally save history file. */
+ if (lua_rl_hist) write_history(lua_rl_hist);
+}
+#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,idx) { (void)L; (void)idx; }
+#define lua_freeline(L,b) { (void)L; (void)b; }
+#define lua_rl_init(L) ((void)L)
+#define lua_rl_exit(L) ((void)L)
+#endif
+
+/* ------------------------------------------------------------------------ */
+
#if !LJ_TARGET_CONSOLE
static void lstop(lua_State *L, lua_Debug *ar)
{
@@ -132,6 +411,14 @@ static int docall(lua_State *L, int narg, int clear)
static void print_version(void)
{
fputs(LUAJIT_VERSION " -- " LUAJIT_COPYRIGHT ". " LUAJIT_URL "\n", stdout);
+ fputs("\n", stdout);
+ fputs(" _____ _ \n", stdout);
+ fputs("|_ _| | | \n", stdout);
+ fputs(" | | ___ _ __ ___| |__ \n", stdout);
+ fputs(" | |/ _ \\| '__/ __| '_ \\ \n", stdout);
+ fputs(" | | (_) | | | (__| | | |\n", stdout);
+ fputs(" \\_/\\___/|_| \\___|_| |_|\n", stdout);
+ fputs("\n", stdout);
}
static void print_jit_status(lua_State *L)
@@ -190,15 +477,14 @@ static int dolibrary(lua_State *L, const char *name)
return report(L, docall(L, 1, 1));
}
-static void write_prompt(lua_State *L, int firstline)
+static const char* get_prompt(lua_State *L, int firstline)
{
const char *p;
lua_getfield(L, LUA_GLOBALSINDEX, firstline ? "_PROMPT" : "_PROMPT2");
p = lua_tostring(L, -1);
if (p == NULL) p = firstline ? LUA_PROMPT : LUA_PROMPT2;
- fputs(p, stdout);
- fflush(stdout);
lua_pop(L, 1); /* remove global */
+ return p;
}
static int incomplete(lua_State *L, int status)
@@ -218,15 +504,17 @@ static int incomplete(lua_State *L, int status)
static int pushline(lua_State *L, int firstline)
{
char buf[LUA_MAXINPUT];
- write_prompt(L, firstline);
- if (fgets(buf, LUA_MAXINPUT, stdin)) {
- size_t len = strlen(buf);
- if (len > 0 && buf[len-1] == '\n')
- buf[len-1] = '\0';
- if (firstline && buf[0] == '=')
- lua_pushfstring(L, "return %s", buf+1);
+ char *b = buf;
+ const char *prmt = get_prompt(L, firstline);
+ if (lua_readline(L, b, prmt)) {
+ size_t len = strlen(b);
+ if (len > 0 && b[len-1] == '\n')
+ b[len-1] = '\0';
+ if (firstline && b[0] == '=')
+ lua_pushfstring(L, "return %s", b+1);
else
- lua_pushstring(L, buf);
+ lua_pushstring(L, b);
+ lua_freeline(L, b);
return 1;
}
return 0;
@@ -247,6 +535,7 @@ static int loadline(lua_State *L)
lua_insert(L, -2); /* ...between the two lines */
lua_concat(L, 3); /* join them */
}
+ lua_saveline(L, 1);
lua_remove(L, 1); /* remove line */
return status;
}
@@ -256,6 +545,7 @@ static void dotty(lua_State *L)
int status;
const char *oldprogname = progname;
progname = NULL;
+ lua_rl_init(L);
while ((status = loadline(L)) != -1) {
if (status == 0) status = docall(L, 0, 0);
report(L, status);
@@ -271,6 +561,7 @@ static void dotty(lua_State *L)
lua_settop(L, 0); /* clear stack */
fputs("\n", stdout);
fflush(stdout);
+ lua_rl_exit(L);
progname = oldprogname;
}