#
# Patch managed by http://www.holgerschurig.de/patcher.html
#

--- lua-5.0.2/etc/saconfig.c~advanced-readline
+++ lua-5.0.2/etc/saconfig.c
@@ -1,14 +1,14 @@
-/* sa-config.c -- configuration for stand-alone Lua interpreter
+/* saconfig.c -- configuration for stand-alone Lua interpreter
 *
 * #define LUA_USERCONFIG to this file
 *
 * Here are the features that can be customized using #define:
 *
-*** Line edit and history:
+*** Line editing and history:
 *   #define USE_READLINE to use the GNU readline library.
 *
 *   To use another library for this, use the code below as a start.
-*   Make sure you #define lua_readline and lua_saveline accordingly.
+*   Make sure you #define lua_{read,save,init,exit}line accordingly.
 *   If you do not #define lua_readline, you'll get a version based on fgets
 *   that uses a static buffer of size MAXINPUT.
 *
@@ -41,13 +41,20 @@
 
 #ifdef USE_READLINE
 /*
-* This section implements of lua_readline and lua_saveline  for lua.c using
-* the GNU readline and history libraries.  It should also work with drop-in
-* replacements  such as  editline  and  libedit (you  may  have to  include
-* different headers, though).
+* This section implements lua_xxxxline for lua.c using the GNU readline
+* and history libraries or compatible replacements.
 *
+* It 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)
+* NETBSD libedit  2.6.5  (2002-03-25)
+* NETBSD libedit  2.6.9  (2004-05-01)
 */
 
+#define lua_initline	myinitline
+#define lua_exitline	myexitline
 #define lua_readline	myreadline
 #define lua_saveline	mysaveline
 
@@ -55,33 +62,226 @@
 #include <readline/readline.h>
 #include <readline/history.h>
 
-static int myreadline (lua_State *L, const char *prompt) {
-  char *s=readline(prompt);
-  if (s==NULL)
-    return 0;
-  else {
-    lua_pushstring(L,s);
-    lua_pushliteral(L,"\n");
-    lua_concat(L,2);
-    free(s);
-    return 1;
-  }
+/* Environment variable names for the history file and the history size */
+#ifndef LUA_HISTORY_ENV
+#define LUA_HISTORY_ENV		"LUA_HISTORY"
+#endif
+
+#ifndef LUA_HISTSIZE_ENV
+#define LUA_HISTSIZE_ENV	"LUA_HISTSIZE"
+#endif
+
+static char *myhist;
+static int myhistsize;
+
+static lua_State *myL;	/* readline does not pass user data to callbacks */
+
+/* Read a line from the terminal with line editing */
+static int myreadline(lua_State *L, const char *prompt)
+{
+  char *s;
+  if (!(s = readline(prompt))) return 0;
+  lua_pushstring(L, s);
+  lua_pushliteral(L, "\n");
+  lua_concat(L, 2);
+  free(s);
+  return 1;
 }
 
-static void mysaveline (lua_State *L, const char *s) {
+/* Add a line to the history */
+static void mysaveline(lua_State *L, const char *s)
+{
   const char *p;
-  for (p=s; isspace(*p); p++)
-    ;
-  if (*p!=0) {
-    size_t n=strlen(s)-1;
-    if (s[n]!='\n')
+  for (p = s; isspace(*p); p++) ;
+  if (*p) {
+    size_t n = strlen(s)-1;
+    if (s[n] != '\n') {
       add_history(s);
-    else {
-      lua_pushlstring(L,s,n);
-      s=lua_tostring(L,-1);
+    } else {
+      lua_pushlstring(L, s, n);
+      s = lua_tostring(L, -1);
       add_history(s);
-      lua_remove(L,-1);
+      lua_pop(L, 1);
+    }
+  }
+}
+
+/* Reserved lua keywords */
+static const char * const reskeywords[] = {
+  "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 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 getmetaindex(lua_State *L)
+{
+  if (!lua_getmetatable(L, -1)) { lua_pop(L, 1); return 0; }
+  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 safegetfield(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 && getmetaindex(L));
+  lua_pop(L, 1);
+  return 0;
+} /* 1: obj -- val, 0: obj -- */
+
+/* Completion function */
+static char **mycomplete(const char *text, int start, int end)
+{
+  dmlist ml;
+  const char *s;
+  size_t i, n, dot;
+  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(myL);
+  lua_pushvalue(myL, LUA_GLOBALSINDEX);
+  for (n = (size_t)(end-start), i = dot = 0; i < n; i++)
+    if (text[i] == '.' || text[i] == ':') {
+      if (!safegetfield(myL, 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 = reskeywords[i]) != NULL; i++)
+      if (!strncmp(s, text, n) && dmadd(&ml, NULL, 0, s, ' ')) goto error;
+
+  /* Add all valid matches from all tables/metatables */
+  i = 20; /* Avoid infinite metatable loops */
+  do {
+    if (lua_istable(myL, -1))
+      for (lua_pushnil(myL); lua_next(myL, -2); lua_pop(myL, 1))
+	if (lua_type(myL, -2) == LUA_TSTRING) {
+	  s = lua_tostring(myL, -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(myL, -1)) {
+	    case LUA_TTABLE:	suf = '.'; break; /* No way to guess ':' */
+	    case LUA_TFUNCTION:	suf = '('; break;
+	    case LUA_TUSERDATA:
+	      if (lua_getmetatable(myL, -1)) { lua_pop(myL, 1); suf = ':'; }
+	      break;
+	    }
+	    if (dmadd(&ml, text, dot, s, suf)) goto error;
+	  }
+	}
+  } while (--i > 0 && getmetaindex(myL));
+
+  if (ml.idx > 1) {
+    /* list[0] holds the common prefix of all matches (may be "") */
+    if (!(ml.list[0] = (char *)malloc(sizeof(char)*(ml.matchlen+1)))) {
+error:
+      lua_settop(myL, savetop);
+      return NULL;
     }
+    memcpy(ml.list[0], ml.list[1], ml.matchlen);
+    ml.list[0][ml.matchlen] = '\0';
+    /* Add the NULL list terminator */
+    if (dmadd(&ml, NULL, 0, NULL, 0)) goto error;
+  } else if (ml.idx == 1) {
+    ml.list[0] = ml.list[1];		/* Only return common prefix */
+    ml.list[1] = NULL;
   }
+
+  lua_settop(myL, savetop);
+  return ml.list;
+}
+
+/* Initialize library */
+static void myinitline(lua_State *L, char *pname)
+{
+  char *s;
+
+  myL = L;
+
+  /* This allows for $if lua ... $endif in ~/.inputrc */
+  rl_readline_name = pname;
+  /* Break words at every non-identifier character except '.' and ':' */
+  rl_completer_word_break_characters = 
+    "\t\r\n !\"#$%&'()*+,-/;<=>?@[\\]^`{|}~";
+  rl_completer_quote_characters = "\"'";
+  rl_completion_append_character = '\0';
+  rl_attempted_completion_function = mycomplete;
+  rl_initialize();
+
+  /* Start using history, optionally set history size and load history file */
+  using_history();
+  if ((s = getenv(LUA_HISTSIZE_ENV)) &&
+      (myhistsize = atoi(s))) stifle_history(myhistsize);
+  if ((myhist = getenv(LUA_HISTORY_ENV))) read_history(myhist);
+}
+
+/* Finalize library */
+static void myexitline(lua_State *L)
+{
+  /* Optionally save history file */
+  if (myhist) write_history(myhist);
 }
 #endif
--- lua-5.0.2/src/lua/lua.c~advanced-readline
+++ lua-5.0.2/src/lua/lua.c
@@ -265,6 +265,19 @@
 
 
 /*
+** these macros can be used to perform initialization and finalization
+** for lua_saveline and lua_readline
+*/
+#ifndef lua_initline
+#define lua_initline(L,pname)	/* empty */
+#endif
+
+#ifndef lua_exitline
+#define lua_exitline(L)		/* empty */
+#endif
+
+
+/*
 ** this macro can be used by some `history' system to save lines
 ** read in manual input
 */
@@ -352,6 +365,7 @@
   const char *oldprogname = progname;
   progname = NULL;
   do_path();
+  lua_initline(L, PROGNAME); /* progname may contain a path, so use PROGNAME */
   while ((status = load_string()) != -1) {
     if (status == 0) status = lcall(0, 0);
     report(status);
@@ -365,6 +379,7 @@
   }
   lua_settop(L, 0);  /* clear stack */
   fputs("\n", stdout);
+  lua_exitline(L);
   progname = oldprogname;
 }