]> pilppa.org Git - familiar-h63xx-build.git/blob - org.handhelds.familiar/packages/lua/files/advanced-readline.patch
OE tree imported from monotone branch org.openembedded.oz354fam083 at revision 8b12e3...
[familiar-h63xx-build.git] / org.handhelds.familiar / packages / lua / files / advanced-readline.patch
1
2 #
3 # Patch managed by http://www.holgerschurig.de/patcher.html
4 #
5
6 --- lua-5.0.2/etc/saconfig.c~advanced-readline
7 +++ lua-5.0.2/etc/saconfig.c
8 @@ -1,14 +1,14 @@
9 -/* sa-config.c -- configuration for stand-alone Lua interpreter
10 +/* saconfig.c -- configuration for stand-alone Lua interpreter
11  *
12  * #define LUA_USERCONFIG to this file
13  *
14  * Here are the features that can be customized using #define:
15  *
16 -*** Line edit and history:
17 +*** Line editing and history:
18  *   #define USE_READLINE to use the GNU readline library.
19  *
20  *   To use another library for this, use the code below as a start.
21 -*   Make sure you #define lua_readline and lua_saveline accordingly.
22 +*   Make sure you #define lua_{read,save,init,exit}line accordingly.
23  *   If you do not #define lua_readline, you'll get a version based on fgets
24  *   that uses a static buffer of size MAXINPUT.
25  *
26 @@ -41,13 +41,20 @@
27  
28  #ifdef USE_READLINE
29  /*
30 -* This section implements of lua_readline and lua_saveline  for lua.c using
31 -* the GNU readline and history libraries.  It should also work with drop-in
32 -* replacements  such as  editline  and  libedit (you  may  have to  include
33 -* different headers, though).
34 +* This section implements lua_xxxxline for lua.c using the GNU readline
35 +* and history libraries or compatible replacements.
36  *
37 +* It has been successfully tested with:
38 +*
39 +* GNU    readline 2.2.1  (1998-07-17)
40 +* GNU    readline 4.0    (1999-02-18) [harmless compiler warning]
41 +* GNU    readline 4.3    (2002-07-16)
42 +* NETBSD libedit  2.6.5  (2002-03-25)
43 +* NETBSD libedit  2.6.9  (2004-05-01)
44  */
45  
46 +#define lua_initline   myinitline
47 +#define lua_exitline   myexitline
48  #define lua_readline   myreadline
49  #define lua_saveline   mysaveline
50  
51 @@ -55,33 +62,226 @@
52  #include <readline/readline.h>
53  #include <readline/history.h>
54  
55 -static int myreadline (lua_State *L, const char *prompt) {
56 -  char *s=readline(prompt);
57 -  if (s==NULL)
58 -    return 0;
59 -  else {
60 -    lua_pushstring(L,s);
61 -    lua_pushliteral(L,"\n");
62 -    lua_concat(L,2);
63 -    free(s);
64 -    return 1;
65 -  }
66 +/* Environment variable names for the history file and the history size */
67 +#ifndef LUA_HISTORY_ENV
68 +#define LUA_HISTORY_ENV                "LUA_HISTORY"
69 +#endif
70 +
71 +#ifndef LUA_HISTSIZE_ENV
72 +#define LUA_HISTSIZE_ENV       "LUA_HISTSIZE"
73 +#endif
74 +
75 +static char *myhist;
76 +static int myhistsize;
77 +
78 +static lua_State *myL; /* readline does not pass user data to callbacks */
79 +
80 +/* Read a line from the terminal with line editing */
81 +static int myreadline(lua_State *L, const char *prompt)
82 +{
83 +  char *s;
84 +  if (!(s = readline(prompt))) return 0;
85 +  lua_pushstring(L, s);
86 +  lua_pushliteral(L, "\n");
87 +  lua_concat(L, 2);
88 +  free(s);
89 +  return 1;
90  }
91  
92 -static void mysaveline (lua_State *L, const char *s) {
93 +/* Add a line to the history */
94 +static void mysaveline(lua_State *L, const char *s)
95 +{
96    const char *p;
97 -  for (p=s; isspace(*p); p++)
98 -    ;
99 -  if (*p!=0) {
100 -    size_t n=strlen(s)-1;
101 -    if (s[n]!='\n')
102 +  for (p = s; isspace(*p); p++) ;
103 +  if (*p) {
104 +    size_t n = strlen(s)-1;
105 +    if (s[n] != '\n') {
106        add_history(s);
107 -    else {
108 -      lua_pushlstring(L,s,n);
109 -      s=lua_tostring(L,-1);
110 +    } else {
111 +      lua_pushlstring(L, s, n);
112 +      s = lua_tostring(L, -1);
113        add_history(s);
114 -      lua_remove(L,-1);
115 +      lua_pop(L, 1);
116 +    }
117 +  }
118 +}
119 +
120 +/* Reserved lua keywords */
121 +static const char * const reskeywords[] = {
122 +  "and", "break", "do", "else", "elseif", "end", "false",
123 +  "for", "function", "if", "in", "local", "nil", "not", "or",
124 +  "repeat", "return", "then", "true", "until", "while", NULL
125 +};
126 +
127 +static int valididentifier(const char *s)
128 +{
129 +  if (!(isalpha(*s) || *s == '_')) return 0;
130 +  for (s++; *s; s++) if (!(isalpha(*s) || isdigit(*s) || *s == '_')) return 0;
131 +  return 1;
132 +}
133 +
134 +/* Dynamically resizable match list */
135 +typedef struct {
136 +  char **list;
137 +  size_t idx, allocated, matchlen;
138 +} dmlist;
139 +
140 +/* Add prefix + string + suffix to list and compute common prefix */
141 +static int dmadd(dmlist *ml, const char *p, size_t pn, const char *s, int suf)
142 +{
143 +  char *t = NULL;
144 +
145 +  if (ml->idx+1 >= ml->allocated &&
146 +      !(ml->list = realloc(ml->list, sizeof(char *)*(ml->allocated += 32))))
147 +    return -1;
148 +
149 +  if (s) {
150 +    size_t n = strlen(s);
151 +    if (!(t = (char *)malloc(sizeof(char)*(pn+n+(suf?2:1))))) return 1;
152 +    memcpy(t, p, pn);
153 +    memcpy(t+pn, s, n);
154 +    n += pn;
155 +    t[n] = suf;
156 +    if (suf) t[++n] = '\0';
157 +
158 +    if (ml->idx == 0) {
159 +      ml->matchlen = n;
160 +    } else {
161 +      size_t i;
162 +      for (i = 0; i < ml->matchlen && i < n && ml->list[1][i] == t[i]; i++) ;
163 +      ml->matchlen = i;        /* Set matchlen to common prefix */
164 +    }
165 +  }
166 +
167 +  ml->list[++ml->idx] = t;
168 +  return 0;
169 +}
170 +
171 +/* Get __index field of metatable of object on top of stack */
172 +static int getmetaindex(lua_State *L)
173 +{
174 +  if (!lua_getmetatable(L, -1)) { lua_pop(L, 1); return 0; }
175 +  lua_pushstring(L, "__index");
176 +  lua_rawget(L, -2);
177 +  lua_replace(L, -2);
178 +  if (lua_isnil(L, -1) || lua_rawequal(L, -1, -2)) { lua_pop(L, 2); return 0; }
179 +  lua_replace(L, -2);
180 +  return 1;
181 +} /* 1: obj -- val, 0: obj -- */
182 +
183 +/* Get field from object on top of stack. Avoid calling metamethods */
184 +static int safegetfield(lua_State *L, const char *s, size_t n)
185 +{
186 +  int i = 20; /* Avoid infinite metatable loops */
187 +  do {
188 +    if (lua_istable(L, -1)) {
189 +      lua_pushlstring(L, s, n);
190 +      lua_rawget(L, -2);
191 +      if (!lua_isnil(L, -1)) { lua_replace(L, -2); return 1; }
192 +      lua_pop(L, 1);
193 +    }
194 +  } while (--i > 0 && getmetaindex(L));
195 +  lua_pop(L, 1);
196 +  return 0;
197 +} /* 1: obj -- val, 0: obj -- */
198 +
199 +/* Completion function */
200 +static char **mycomplete(const char *text, int start, int end)
201 +{
202 +  dmlist ml;
203 +  const char *s;
204 +  size_t i, n, dot;
205 +  int savetop;
206 +
207 +  if (!(text[0] == '\0' || isalpha(text[0]) || text[0] == '_')) return NULL;
208 +
209 +  ml.list = NULL;
210 +  ml.idx = ml.allocated = ml.matchlen = 0;
211 +
212 +  savetop = lua_gettop(myL);
213 +  lua_pushvalue(myL, LUA_GLOBALSINDEX);
214 +  for (n = (size_t)(end-start), i = dot = 0; i < n; i++)
215 +    if (text[i] == '.' || text[i] == ':') {
216 +      if (!safegetfield(myL, text+dot, i-dot)) goto error; /* invalid prefix */
217 +      dot = i+1; /* points to first char after dot/colon */
218 +    }
219 +
220 +  /* Add all matches against keywords if there is no dot/colon */
221 +  if (dot == 0)
222 +    for (i = 0; (s = reskeywords[i]) != NULL; i++)
223 +      if (!strncmp(s, text, n) && dmadd(&ml, NULL, 0, s, ' ')) goto error;
224 +
225 +  /* Add all valid matches from all tables/metatables */
226 +  i = 20; /* Avoid infinite metatable loops */
227 +  do {
228 +    if (lua_istable(myL, -1))
229 +      for (lua_pushnil(myL); lua_next(myL, -2); lua_pop(myL, 1))
230 +       if (lua_type(myL, -2) == LUA_TSTRING) {
231 +         s = lua_tostring(myL, -2);
232 +         /* Only match names starting with '_' if explicitly requested */
233 +         if (!strncmp(s, text+dot, n-dot) && valididentifier(s) &&
234 +             (*s != '_' || text[dot] == '_')) {
235 +           int suf = ' '; /* default suffix is a space */
236 +           switch (lua_type(myL, -1)) {
237 +           case LUA_TTABLE:    suf = '.'; break; /* No way to guess ':' */
238 +           case LUA_TFUNCTION: suf = '('; break;
239 +           case LUA_TUSERDATA:
240 +             if (lua_getmetatable(myL, -1)) { lua_pop(myL, 1); suf = ':'; }
241 +             break;
242 +           }
243 +           if (dmadd(&ml, text, dot, s, suf)) goto error;
244 +         }
245 +       }
246 +  } while (--i > 0 && getmetaindex(myL));
247 +
248 +  if (ml.idx > 1) {
249 +    /* list[0] holds the common prefix of all matches (may be "") */
250 +    if (!(ml.list[0] = (char *)malloc(sizeof(char)*(ml.matchlen+1)))) {
251 +error:
252 +      lua_settop(myL, savetop);
253 +      return NULL;
254      }
255 +    memcpy(ml.list[0], ml.list[1], ml.matchlen);
256 +    ml.list[0][ml.matchlen] = '\0';
257 +    /* Add the NULL list terminator */
258 +    if (dmadd(&ml, NULL, 0, NULL, 0)) goto error;
259 +  } else if (ml.idx == 1) {
260 +    ml.list[0] = ml.list[1];           /* Only return common prefix */
261 +    ml.list[1] = NULL;
262    }
263 +
264 +  lua_settop(myL, savetop);
265 +  return ml.list;
266 +}
267 +
268 +/* Initialize library */
269 +static void myinitline(lua_State *L, char *pname)
270 +{
271 +  char *s;
272 +
273 +  myL = L;
274 +
275 +  /* This allows for $if lua ... $endif in ~/.inputrc */
276 +  rl_readline_name = pname;
277 +  /* Break words at every non-identifier character except '.' and ':' */
278 +  rl_completer_word_break_characters = 
279 +    "\t\r\n !\"#$%&'()*+,-/;<=>?@[\\]^`{|}~";
280 +  rl_completer_quote_characters = "\"'";
281 +  rl_completion_append_character = '\0';
282 +  rl_attempted_completion_function = mycomplete;
283 +  rl_initialize();
284 +
285 +  /* Start using history, optionally set history size and load history file */
286 +  using_history();
287 +  if ((s = getenv(LUA_HISTSIZE_ENV)) &&
288 +      (myhistsize = atoi(s))) stifle_history(myhistsize);
289 +  if ((myhist = getenv(LUA_HISTORY_ENV))) read_history(myhist);
290 +}
291 +
292 +/* Finalize library */
293 +static void myexitline(lua_State *L)
294 +{
295 +  /* Optionally save history file */
296 +  if (myhist) write_history(myhist);
297  }
298  #endif
299 --- lua-5.0.2/src/lua/lua.c~advanced-readline
300 +++ lua-5.0.2/src/lua/lua.c
301 @@ -265,6 +265,19 @@
302  
303  
304  /*
305 +** these macros can be used to perform initialization and finalization
306 +** for lua_saveline and lua_readline
307 +*/
308 +#ifndef lua_initline
309 +#define lua_initline(L,pname)  /* empty */
310 +#endif
311 +
312 +#ifndef lua_exitline
313 +#define lua_exitline(L)                /* empty */
314 +#endif
315 +
316 +
317 +/*
318  ** this macro can be used by some `history' system to save lines
319  ** read in manual input
320  */
321 @@ -352,6 +365,7 @@
322    const char *oldprogname = progname;
323    progname = NULL;
324    do_path();
325 +  lua_initline(L, PROGNAME); /* progname may contain a path, so use PROGNAME */
326    while ((status = load_string()) != -1) {
327      if (status == 0) status = lcall(0, 0);
328      report(status);
329 @@ -365,6 +379,7 @@
330    }
331    lua_settop(L, 0);  /* clear stack */
332    fputs("\n", stdout);
333 +  lua_exitline(L);
334    progname = oldprogname;
335  }
336