···2929#include <lua.hpp>
3030#include <unistd.h>
3131#include "soc_desc.hpp"
3232+extern "C" {
3333+#include "prompt.h"
3434+}
32353336#if LUA_VERSION_NUM < 502
3437#warning You need at least lua 5.2
···941944 printf("error: %s\n", lua_tostring(g_lua, -1));
942945 }
943946944944- // use readline to provide some history and completion
945945- rl_bind_key('\t', rl_complete);
946946- while(!g_exit)
947947- {
948948- char *input = readline("> ");
949949- if(!input)
950950- break;
951951- add_history(input);
952952- // evaluate string
953953- if(luaL_dostring(g_lua, input))
954954- printf("error: %s\n", lua_tostring(g_lua, -1));
955955- // pop everything to start from a clean stack
956956- lua_pop(g_lua, lua_gettop(g_lua));
957957- free(input);
958958- }
947947+ // start interactive shell
948948+ luap_enter(g_lua, &g_exit);
959949960950 Lerr:
961951 // display log if handled
+4-2
utils/hwstub/tools/lua/hwlib.lua
···2222 io.close(f)
2323end
24242525-function HWLIB.printf(s,...)
2626- return io.write(s:format(...))
2525+function HWLIB.printf(...)
2626+ local function wrapper(...) io.write(string.format(...)) end
2727+ local status, result = pcall(wrapper, ...)
2828+ if not status then error(result, 2) end
2729end
+1659
utils/hwstub/tools/prompt.c
···11+/* Copyright (C) 2012-2015 Papavasileiou Dimitris
22+ *
33+ * Permission is hereby granted, free of charge, to any person
44+ * obtaining a copy of this software and associated documentation
55+ * files (the "Software"), to deal in the Software without
66+ * restriction, including without limitation the rights to use, copy,
77+ * modify, merge, publish, distribute, sublicense, and/or sell copies
88+ * of the Software, and to permit persons to whom the Software is
99+ * furnished to do so, subject to the following conditions:
1010+ *
1111+ * The above copyright notice and this permission notice shall be
1212+ * included in all copies or substantial portions of the Software.
1313+ *
1414+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
1515+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
1616+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
1717+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
1818+ * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
1919+ * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
2020+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
2121+ * SOFTWARE.
2222+ */
2323+2424+#ifdef HAVE_CONFIG_H
2525+#include <config.h>
2626+#endif
2727+2828+#define _GNU_SOURCE
2929+#include <stdio.h>
3030+#include <stdlib.h>
3131+#include <string.h>
3232+#include <ctype.h>
3333+#include <stdbool.h>
3434+#include <sys/stat.h>
3535+#include <unistd.h>
3636+#include "prompt.h"
3737+3838+#ifdef HAVE_IOCTL
3939+#include <sys/ioctl.h>
4040+#endif
4141+4242+#include <glob.h>
4343+4444+#include <lualib.h>
4545+#include <lauxlib.h>
4646+4747+4848+#if LUA_VERSION_NUM == 501
4949+#define lua_pushglobaltable(L) lua_pushvalue (L, LUA_GLOBALSINDEX)
5050+#define LUA_OK 0
5151+#define lua_rawlen lua_objlen
5252+#endif
5353+5454+#ifdef HAVE_LIBREADLINE
5555+#include <readline/readline.h>
5656+#else
5757+5858+/* This is a simple readline-like function in case readline is not
5959+ * available. */
6060+6161+#define MAXINPUT 1024
6262+6363+static char *readline(char *prompt)
6464+{
6565+ char *line = NULL;
6666+ int k;
6767+6868+ line = malloc (MAXINPUT);
6969+7070+ fputs(prompt, stdout);
7171+ fflush(stdout);
7272+7373+ if (!fgets(line, MAXINPUT, stdin)) {
7474+ return NULL;
7575+ }
7676+7777+ k = strlen (line);
7878+7979+ if (line[k - 1] == '\n') {
8080+ line[k - 1] = '\0';
8181+ }
8282+8383+ return line;
8484+}
8585+8686+#endif /* HAVE_LIBREADLINE */
8787+8888+#ifdef HAVE_READLINE_HISTORY
8989+#include <readline/history.h>
9090+#endif /* HAVE_READLINE_HISTORY */
9191+9292+#if LUA_VERSION_NUM == 501
9393+#define EOF_MARKER "'<eof>'"
9494+#else
9595+#define EOF_MARKER "<eof>"
9696+#endif
9797+9898+#define print_output(...) fprintf (stdout, __VA_ARGS__), fflush(stdout)
9999+#define print_error(...) fprintf (stderr, __VA_ARGS__), fflush(stderr)
100100+#define absolute(L, i) (i < 0 ? lua_gettop (L) + i + 1 : i)
101101+102102+#define COLOR(i) (colorize ? colors[i] : "")
103103+104104+static lua_State *M;
105105+static int initialized = 0;
106106+static char *logfile, *chunkname, *prompts[2][2], *buffer = NULL;
107107+108108+#ifdef SAVE_RESULTS
109109+static int results = LUA_REFNIL, results_n = 0;
110110+#endif
111111+112112+static int colorize = 1;
113113+static const char *colors[] = {"\033[0m",
114114+ "\033[0;31m",
115115+ "\033[1;31m",
116116+ "\033[0;32m",
117117+ "\033[1;32m",
118118+ "\033[0;33m",
119119+ "\033[1;33m",
120120+ "\033[1m",
121121+ "\033[22m"};
122122+123123+#ifdef HAVE_LIBREADLINE
124124+125125+static void display_matches (char **matches, int num_matches, int max_length)
126126+{
127127+ print_output ("%s", COLOR(7));
128128+ rl_display_match_list (matches, num_matches, max_length);
129129+ print_output ("%s", COLOR(0));
130130+ rl_on_new_line ();
131131+}
132132+133133+#ifdef COMPLETE_KEYWORDS
134134+static char *keyword_completions (const char *text, int state)
135135+{
136136+ static const char **c, *keywords[] = {
137137+#if LUA_VERSION_NUM == 502
138138+ "goto",
139139+#endif
140140+ "and", "break", "do", "else", "elseif", "end", "false", "for",
141141+ "function", "if", "in", "local", "nil", "not", "or",
142142+ "repeat", "return", "then", "true", "until", "while", NULL
143143+ };
144144+145145+ int s, t;
146146+147147+ if (state == 0) {
148148+ c = keywords - 1;
149149+ }
150150+151151+ /* Loop through the list of keywords and return the ones that
152152+ * match. */
153153+154154+ for (c += 1 ; *c ; c += 1) {
155155+ s = strlen (*c);
156156+ t = strlen(text);
157157+158158+ if (s >= t && !strncmp (*c, text, t)) {
159159+ return strdup (*c);
160160+ }
161161+ }
162162+163163+ return NULL;
164164+}
165165+#endif
166166+167167+#ifdef COMPLETE_TABLE_KEYS
168168+169169+static int look_up_metatable;
170170+171171+static char *table_key_completions (const char *text, int state)
172172+{
173173+ static const char *c, *token;
174174+ static char oper;
175175+ static int h;
176176+177177+ if (state == 0) {
178178+ h = lua_gettop(M);
179179+180180+ /* Scan to the beginning of the to-be-completed token. */
181181+182182+ for (c = text + strlen (text) - 1;
183183+ c >= text && *c != '.' && *c != ':' && *c != '[';
184184+ c -= 1);
185185+186186+ if (c > text) {
187187+ oper = *c;
188188+ token = c + 1;
189189+190190+ /* Get the iterable value, the keys of which we wish to
191191+ * complete. */
192192+193193+ lua_pushliteral (M, "return ");
194194+ lua_pushlstring (M, text, token - text - 1);
195195+ lua_concat (M, 2);
196196+197197+ if (luaL_loadstring (M, lua_tostring (M, -1)) ||
198198+ lua_pcall (M, 0, 1, 0) ||
199199+ (lua_type (M, -1) != LUA_TUSERDATA &&
200200+ lua_type (M, -1) != LUA_TTABLE)) {
201201+202202+ lua_settop(M, h);
203203+ return NULL;
204204+ }
205205+ } else {
206206+ oper = 0;
207207+ token = text;
208208+209209+ lua_pushglobaltable(M);
210210+ }
211211+212212+ if (look_up_metatable) {
213213+ /* Replace the to-be-iterated value with it's metatable
214214+ * and set up a call to next. */
215215+216216+ if (!luaL_getmetafield(M, -1, "__index") ||
217217+ (lua_type (M, -1) != LUA_TUSERDATA &&
218218+ lua_type (M, -1) != LUA_TTABLE)) {
219219+ lua_settop(M, h);
220220+ return NULL;
221221+ }
222222+223223+ lua_getglobal(M, "next");
224224+ lua_replace(M, -3);
225225+ lua_pushnil(M);
226226+ } else {
227227+ /* Call the standard pairs function. */
228228+229229+ lua_getglobal (M, "pairs");
230230+ lua_insert (M, -2);
231231+232232+ if(lua_type (M, -2) != LUA_TFUNCTION ||
233233+ lua_pcall (M, 1, 3, 0)) {
234234+235235+ lua_settop(M, h);
236236+ return NULL;
237237+ }
238238+ }
239239+ }
240240+241241+ /* Iterate the table/userdata and generate matches. */
242242+243243+ while (lua_pushvalue(M, -3), lua_insert (M, -3),
244244+ lua_pushvalue(M, -2), lua_insert (M, -4),
245245+ lua_pcall (M, 2, 2, 0) == 0) {
246246+ char *candidate;
247247+ size_t l, m;
248248+ int suppress, type, keytype;
249249+250250+ if (lua_isnil(M, -2)) {
251251+ lua_settop(M, h);
252252+ return NULL;
253253+ }
254254+255255+ /* Make some notes about the value we're completing. We'll
256256+ * make use of them later on. */
257257+258258+ type = lua_type (M, -1);
259259+ suppress = (type == LUA_TTABLE || type == LUA_TUSERDATA ||
260260+ type == LUA_TFUNCTION);
261261+262262+ keytype = LUA_TNIL;
263263+ if (type == LUA_TTABLE) {
264264+ lua_pushnil(M);
265265+ if (lua_next(M, -2)) {
266266+ keytype = lua_type (M, -2);
267267+ lua_pop (M, 2);
268268+ } else {
269269+ /* There are no keys in the table so we won't want to
270270+ * index it. Add a space. */
271271+272272+ suppress = 0;
273273+ }
274274+ }
275275+276276+ /* Pop the value, keep the key. */
277277+278278+ lua_pop (M, 1);
279279+280280+ /* We're mainly interested in strings at this point but if
281281+ * we're completing for the table[key] syntax we consider
282282+ * numeric keys too. */
283283+284284+ if (lua_type (M, -1) == LUA_TSTRING ||
285285+ (oper == '[' && lua_type (M, -1) == LUA_TNUMBER)) {
286286+ if (oper == '[') {
287287+ if (lua_type (M, -1) == LUA_TNUMBER) {
288288+ lua_Number n;
289289+ int i;
290290+291291+ n = lua_tonumber (M, -1);
292292+ i = lua_tointeger (M, -1);
293293+294294+ /* If this isn't an integer key, we may as well
295295+ * forget about it. */
296296+297297+ if ((lua_Number)i == n) {
298298+ l = asprintf (&candidate, "%d]", i);
299299+ } else {
300300+ continue;
301301+ }
302302+ } else {
303303+ char q;
304304+305305+ q = token[0];
306306+ if (q != '"' && q != '\'') {
307307+ q = '"';
308308+ }
309309+310310+ l = asprintf (&candidate, "%c%s%c]",
311311+ q, lua_tostring (M, -1), q);
312312+ }
313313+ } else {
314314+ candidate = strdup((char *)lua_tolstring (M, -1, &l));
315315+ }
316316+317317+ m = strlen(token);
318318+319319+ if (l >= m && !strncmp (token, candidate, m) &&
320320+ (oper != ':' || type == LUA_TFUNCTION)
321321+#ifdef HIDDEN_KEY_PREFIX
322322+ && strncmp(candidate, HIDDEN_KEY_PREFIX,
323323+ sizeof(HIDDEN_KEY_PREFIX) - 1)
324324+#endif
325325+ ) {
326326+ char *match;
327327+328328+ /* If the candidate has been fully typed (or
329329+ * previously completed) consider adding certain
330330+ * helpful suffixes. */
331331+#ifndef ALWAYS_APPEND_SUFFIXES
332332+ if (l == m) {
333333+#endif
334334+ if (type == LUA_TFUNCTION) {
335335+ rl_completion_append_character = '('; suppress = 0;
336336+ } else if (type == LUA_TTABLE) {
337337+ if (keytype == LUA_TSTRING) {
338338+ rl_completion_append_character = '.'; suppress = 0;
339339+ } else if (keytype != LUA_TNIL) {
340340+ rl_completion_append_character = '['; suppress = 0;
341341+ }
342342+ }
343343+#ifndef ALWAYS_APPEND_SUFFIXES
344344+ };
345345+#endif
346346+347347+ if (token > text) {
348348+ /* Were not completing a global variable. Put the
349349+ * completed string together out of the table and
350350+ * the key. */
351351+352352+ match = (char *)malloc ((token - text) + l + 1);
353353+ strncpy (match, text, token - text);
354354+ strcpy (match + (token - text), candidate);
355355+356356+ free(candidate);
357357+ } else {
358358+ /* Return the whole candidate as is, to be freed
359359+ * by Readline. */
360360+361361+ match = candidate;
362362+ }
363363+364364+ /* Suppress the newline when completing a table
365365+ * or other potentially complex value. */
366366+367367+ if (suppress) {
368368+ rl_completion_suppress_append = 1;
369369+ }
370370+371371+ return match;
372372+ } else {
373373+ free(candidate);
374374+ }
375375+ }
376376+ }
377377+378378+ lua_settop(M, h);
379379+ return NULL;
380380+}
381381+#endif
382382+383383+#ifdef COMPLETE_MODULES
384384+static char *module_completions (const char *text, int state)
385385+{
386386+ char *match = NULL;
387387+ static int h;
388388+389389+ if (state == 0) {
390390+ glob_t vector;
391391+ const char *b, *d, *q, *s, *t, *strings[3];
392392+ int i, n = 0, ondot, hasdot, quoted;
393393+394394+ hasdot = strchr(text, '.') != NULL;
395395+ ondot = text[0] != '\0' && text[strlen(text) - 1] == '.';
396396+ quoted = text[0] == '\'' || text[0] == '"';
397397+398398+#ifdef NO_MODULE_LOAD
399399+ if(!quoted) {
400400+ return NULL;
401401+ }
402402+#endif
403403+404404+ lua_newtable(M);
405405+ h = lua_gettop(M);
406406+407407+ /* Try to load the input as a module. */
408408+409409+ lua_getglobal(M, "require");
410410+411411+ if (!lua_isfunction (M, -1)) {
412412+ lua_settop(M, h - 1);
413413+ return NULL;
414414+ }
415415+416416+ lua_pushliteral(M, "package");
417417+418418+ if(lua_pcall(M, 1, 1, 0) != LUA_OK) {
419419+ lua_settop(M, h - 1);
420420+ return NULL;
421421+ }
422422+423423+ if (!ondot && !quoted && text[0] != '\0') {
424424+ lua_getfield(M, -1, "loaded");
425425+ lua_pushstring(M, text);
426426+ lua_gettable(M, -2);
427427+428428+ /* If it's not an already loaded module, check whether the
429429+ * input is an available module by searching for it and/or
430430+ * trying to load it. */
431431+432432+ if (!lua_toboolean(M, -1)) {
433433+ int load = 1;
434434+435435+ lua_pop(M, 2);
436436+437437+#ifdef CONFIRM_MODULE_LOAD
438438+ /* Look for the module as require would and ask the
439439+ * user whether it should be loaded or not. */
440440+441441+#if LUA_VERSION_NUM == 501
442442+ lua_getfield(M, -1, "loaders");
443443+#else
444444+ lua_getfield(M, -1, "searchers");
445445+#endif
446446+ lua_pushnil(M);
447447+448448+ while((load = lua_next(M, -2))) {
449449+ lua_pushstring(M, text);
450450+ lua_call(M, 1, 1);
451451+452452+ if (lua_isfunction(M, -1)) {
453453+ char c;
454454+455455+ print_output ("\nLoad module '%s' (y or n)", text);
456456+457457+ while ((c = tolower(rl_read_key())) != 'y' && c != 'n');
458458+459459+ if (c == 'y') {
460460+ lua_pop(M, 3);
461461+ break;
462462+ } else {
463463+ print_output ("\n");
464464+ rl_on_new_line ();
465465+466466+ /* If it was found but not loaded, return
467467+ * the module name as a match to avoid
468468+ * asking the user againg if the tab key
469469+ * is pressed repeatedly. */
470470+471471+ lua_settop(M, h);
472472+ return strdup(text);
473473+ }
474474+ }
475475+476476+ lua_pop(M, 1);
477477+ }
478478+#endif
479479+480480+ /* Load the model if needed. */
481481+482482+ if (load) {
483483+ lua_pushfstring (M, "%s=require(\"%s\")", text, text);
484484+485485+ if (luaL_loadstring (M, lua_tostring (M, -1)) == LUA_OK &&
486486+ lua_pcall (M, 0, 0, 0) == LUA_OK) {
487487+#ifdef CONFIRM_MODULE_LOAD
488488+ print_output (" ...loaded\n");
489489+#else
490490+ print_output ("\nLoaded module '%s'.\n", text);
491491+#endif
492492+493493+ rl_on_new_line ();
494494+495495+ lua_settop(M, h - 1);
496496+ return NULL;
497497+ }
498498+ }
499499+ } else {
500500+ lua_settop(M, h - 1);
501501+ return NULL;
502502+ }
503503+504504+ /* Clean up but leave the package.table on the stack. */
505505+506506+ lua_settop(M, h + 1);
507507+ }
508508+509509+ /* Look for matches in package.preload. */
510510+511511+ lua_getfield(M, -1, "preload");
512512+513513+ lua_pushnil(M);
514514+ while(lua_next(M, -2)) {
515515+ lua_pop(M, 1);
516516+517517+ if (lua_type(M, -1) == LUA_TSTRING &&
518518+ !strncmp(text + quoted, lua_tostring(M, -1),
519519+ strlen(text + quoted))) {
520520+521521+ lua_pushstring(M, text);
522522+ lua_rawseti (M, h, (n += 1));
523523+ }
524524+ }
525525+526526+ lua_pop(M, 1);
527527+528528+ /* Get the configuration (directory, path separators, module
529529+ * name wildcard). */
530530+531531+ lua_getfield(M, -1, "config");
532532+ for (s = (char *)lua_tostring(M, -1), i = 0;
533533+ i < 3;
534534+ s = t + 1, i += 1) {
535535+536536+ t = strchr(s, '\n');
537537+ lua_pushlstring(M, s, t - s);
538538+ strings[i] = lua_tostring(M, -1);
539539+ }
540540+541541+ lua_remove(M, -4);
542542+543543+ /* Get the path and cpath */
544544+545545+ lua_getfield(M, -4, "path");
546546+ lua_pushstring(M, strings[1]);
547547+ lua_getfield(M, -6, "cpath");
548548+ lua_pushstring(M, strings[1]);
549549+ lua_concat(M, 4);
550550+551551+ /* Synthesize the pattern. */
552552+553553+ if (hasdot) {
554554+ luaL_gsub(M, text + quoted, ".", strings[0]);
555555+ } else {
556556+ lua_pushstring(M, text + quoted);
557557+ }
558558+559559+ lua_pushliteral(M, "*");
560560+ lua_concat(M, 2);
561561+562562+ for (b = d = lua_tostring(M, -2) ; d ; b = d + 1) {
563563+ size_t i;
564564+565565+ d = strstr(b, strings[1]);
566566+ q = strstr(b, strings[2]);
567567+568568+ if (!q || q > d) {
569569+ continue;
570570+ }
571571+572572+ lua_pushlstring(M, b, d - b);
573573+ luaL_gsub(M, lua_tostring(M, -1), strings[2],
574574+ lua_tostring(M, -2));
575575+576576+ glob(lua_tostring(M, -1), 0, NULL, &vector);
577577+578578+ lua_pop(M, 2);
579579+580580+ for (i = 0 ; i < vector.gl_pathc ; i += 1) {
581581+ char *p = vector.gl_pathv[i];
582582+583583+ if (quoted) {
584584+ lua_pushlstring(M, text, 1);
585585+ }
586586+587587+ lua_pushlstring(M, p + (q - b), strlen(p) - (d - b) + 1);
588588+589589+ if (hasdot) {
590590+ luaL_gsub(M, lua_tostring(M, -1), strings[0], ".");
591591+ lua_replace(M, -2);
592592+ }
593593+594594+ {
595595+ const char *s;
596596+ size_t l;
597597+598598+ s = lua_tolstring(M, -1, &l);
599599+600600+ /* Suppress submodules named init. */
601601+602602+ if (l < sizeof("init") - 1 ||
603603+ strcmp(s + l - sizeof("init") + 1, "init")) {
604604+605605+ if (quoted) {
606606+ lua_pushlstring(M, text, 1);
607607+608608+ lua_concat(M, 3);
609609+ }
610610+611611+ lua_rawseti(M, h, (n += 1));
612612+ } else {
613613+ lua_pop(M, 1 + quoted);
614614+ }
615615+ }
616616+ }
617617+618618+ globfree(&vector);
619619+ }
620620+621621+ lua_pop(M, 6);
622622+ }
623623+624624+ /* Return the next match from the table of matches. */
625625+626626+ lua_pushnil(M);
627627+ if (lua_next(M, -2)) {
628628+ match = strdup(lua_tostring(M, -1));
629629+630630+ rl_completion_suppress_append = !(match[0] == '"' || match[0] == '\'');
631631+632632+ /* Pop the match. */
633633+634634+ lua_pushnil(M);
635635+ lua_rawseti(M, -4, lua_tointeger(M, -3));
636636+637637+ /* Pop key/value. */
638638+639639+ lua_pop(M, 2);
640640+ } else {
641641+ /* Pop the empty table. */
642642+643643+ lua_pop(M, 1);
644644+ }
645645+646646+ return match;
647647+}
648648+#endif
649649+650650+static char *generator (const char *text, int state)
651651+{
652652+ static int which;
653653+ char *match = NULL;
654654+655655+ if (state == 0) {
656656+ which = 0;
657657+ }
658658+659659+ /* Try to complete a keyword. */
660660+661661+ if (which == 0) {
662662+#ifdef COMPLETE_KEYWORDS
663663+ if ((match = keyword_completions (text, state))) {
664664+ return match;
665665+ }
666666+#endif
667667+ which += 1;
668668+ state = 0;
669669+ }
670670+671671+ /* Try to complete a module name. */
672672+673673+ if (which == 1) {
674674+#ifdef COMPLETE_MODULES
675675+ if ((match = module_completions (text, state))) {
676676+ return match;
677677+ }
678678+#endif
679679+ which += 1;
680680+ state = 0;
681681+ }
682682+683683+ /* Try to complete a table access. */
684684+685685+ if (which == 2) {
686686+#ifdef COMPLETE_TABLE_KEYS
687687+ look_up_metatable = 0;
688688+ if ((match = table_key_completions (text, state))) {
689689+ return match;
690690+ }
691691+#endif
692692+ which += 1;
693693+ state = 0;
694694+ }
695695+696696+ /* Try to complete a metatable access. */
697697+698698+ if (which == 3) {
699699+#ifdef COMPLETE_METATABLE_KEYS
700700+ look_up_metatable = 1;
701701+ if ((match = table_key_completions (text, state))) {
702702+ return match;
703703+ }
704704+#endif
705705+ which += 1;
706706+ state = 0;
707707+ }
708708+709709+#ifdef COMPLETE_FILE_NAMES
710710+ /* Try to complete a file name. */
711711+712712+ if (which == 4) {
713713+ if (text[0] == '\'' || text[0] == '"') {
714714+ match = rl_filename_completion_function (text + 1, state);
715715+716716+ if (match) {
717717+ struct stat s;
718718+ int n;
719719+720720+ n = strlen (match);
721721+ stat(match, &s);
722722+723723+ /* If a match was produced, add the quote
724724+ * characters. */
725725+726726+ match = (char *)realloc (match, n + 3);
727727+ memmove (match + 1, match, n);
728728+ match[0] = text[0];
729729+730730+ /* If the file's a directory, add a trailing backslash
731731+ * and suppress the space, otherwise add the closing
732732+ * quote. */
733733+734734+ if (S_ISDIR(s.st_mode)) {
735735+ match[n + 1] = '/';
736736+737737+ rl_completion_suppress_append = 1;
738738+ } else {
739739+ match[n + 1] = text[0];
740740+ }
741741+742742+ match[n + 2] = '\0';
743743+ }
744744+ }
745745+ }
746746+#endif
747747+748748+ return match;
749749+}
750750+#endif
751751+752752+static void finish ()
753753+{
754754+#ifdef HAVE_READLINE_HISTORY
755755+ /* Save the command history on exit. */
756756+757757+ if (logfile) {
758758+ write_history (logfile);
759759+ }
760760+#endif
761761+}
762762+763763+static int traceback(lua_State *L)
764764+{
765765+ lua_Debug ar;
766766+ int i;
767767+768768+ if (lua_isnoneornil (L, 1) ||
769769+ (!lua_isstring (L, 1) &&
770770+ !luaL_callmeta(L, 1, "__tostring"))) {
771771+ lua_pushliteral(L, "(no error message)");
772772+ }
773773+774774+ if (lua_gettop (L) > 1) {
775775+ lua_replace (L, 1);
776776+ lua_settop (L, 1);
777777+ }
778778+779779+ /* Print the Lua stack. */
780780+781781+ lua_pushstring(L, "\n\nStack trace:\n");
782782+783783+ for (i = 0 ; lua_getstack (L, i, &ar) ; i += 1) {
784784+#if LUA_VERSION_NUM == 501
785785+ lua_getinfo(M, "Snl", &ar);
786786+#else
787787+ lua_getinfo(M, "Snlt", &ar);
788788+789789+ if (ar.istailcall) {
790790+ lua_pushfstring(L, "\t... tail calls\n");
791791+ }
792792+#endif
793793+794794+ if (!strcmp (ar.what, "C")) {
795795+ lua_pushfstring(L, "\t#%d %s[C]:%s in function ",
796796+ i, COLOR(7), COLOR(8));
797797+798798+ if (ar.name) {
799799+ lua_pushfstring(L, "'%s%s%s'\n",
800800+ COLOR(7), ar.name, COLOR(8));
801801+ } else {
802802+ lua_pushfstring(L, "%s?%s\n", COLOR(7), COLOR(8));
803803+ }
804804+ } else if (!strcmp (ar.what, "main")) {
805805+ lua_pushfstring(L, "\t#%d %s%s:%d:%s in the main chunk\n",
806806+ i, COLOR(7), ar.short_src, ar.currentline,
807807+ COLOR(8));
808808+ } else if (!strcmp (ar.what, "Lua")) {
809809+ lua_pushfstring(L, "\t#%d %s%s:%d:%s in function ",
810810+ i, COLOR(7), ar.short_src, ar.currentline,
811811+ COLOR(8));
812812+813813+ if (ar.name) {
814814+ lua_pushfstring(L, "'%s%s%s'\n",
815815+ COLOR(7), ar.name, COLOR(8));
816816+ } else {
817817+ lua_pushfstring(L, "%s?%s\n", COLOR(7), COLOR(8));
818818+ }
819819+ }
820820+ }
821821+822822+ if (i == 0) {
823823+ lua_pushstring (L, "No activation records.\n");
824824+ }
825825+826826+ lua_concat (L, lua_gettop(L));
827827+828828+ return 1;
829829+}
830830+831831+static int execute ()
832832+{
833833+ int i, h_0, h, status;
834834+835835+#ifdef SAVE_RESULTS
836836+ /* Get the results table, and stash it behind the to-be-executed
837837+ * chunk. */
838838+839839+ lua_rawgeti(M, LUA_REGISTRYINDEX, results);
840840+ lua_insert(M, -2);
841841+#endif
842842+843843+ h_0 = lua_gettop(M);
844844+ status = luap_call (M, 0);
845845+ h = lua_gettop (M) - h_0 + 1;
846846+847847+ for (i = h ; i > 0 ; i -= 1) {
848848+ const char *result;
849849+850850+ result = luap_describe (M, -i);
851851+852852+#ifdef SAVE_RESULTS
853853+ lua_pushvalue (M, -i);
854854+ lua_rawseti(M, h_0 - 1, (results_n += 1));
855855+856856+ print_output ("%s%s[%d]%s = %s%s\n",
857857+ COLOR(4), RESULTS_TABLE_NAME, results_n,
858858+ COLOR(3), result, COLOR(0));
859859+#else
860860+ if (h == 1) {
861861+ print_output ("%s%s%s\n", COLOR(3), result, COLOR(0));
862862+ } else {
863863+ print_output ("%s%d%s: %s%s\n", COLOR(4), h - i + 1,
864864+ COLOR(3), result, COLOR(0));
865865+ }
866866+#endif
867867+ }
868868+869869+ /* Clean up. We need to remove the results table as well if we
870870+ * track results. */
871871+872872+#ifdef SAVE_RESULTS
873873+ lua_settop (M, h_0 - 2);
874874+#else
875875+ lua_settop (M, h_0 - 1);
876876+#endif
877877+878878+ return status;
879879+}
880880+881881+/* This is the pretty-printing related stuff. */
882882+883883+static char *dump;
884884+static int length, offset, indent, column, linewidth, ancestors;
885885+886886+#define dump_literal(s) (check_fit(sizeof(s) - 1), \
887887+ strcpy (dump + offset, s), \
888888+ offset += sizeof(s) - 1, \
889889+ column += width(s))
890890+891891+#define dump_character(c) (check_fit(1), \
892892+ dump[offset] = c, \
893893+ offset += 1, \
894894+ column += 1)
895895+896896+static int width (const char *s)
897897+{
898898+ const char *c;
899899+ int n, discard = 0;
900900+901901+ /* Calculate the printed width of the chunk s ignoring escape
902902+ * sequences. */
903903+904904+ for (c = s, n = 0 ; *c ; c += 1) {
905905+ if (!discard && *c == '\033') {
906906+ discard = 1;
907907+ }
908908+909909+ if (!discard) {
910910+ n+= 1;
911911+ }
912912+913913+ if (discard && *c == 'm') {
914914+ discard = 0;
915915+ }
916916+ }
917917+918918+ return n;
919919+}
920920+921921+static void check_fit (int size)
922922+{
923923+ /* Check if a chunk fits in the buffer and expand as necessary. */
924924+925925+ if (offset + size + 1 > length) {
926926+ length = offset + size + 1;
927927+ dump = (char *)realloc (dump, length * sizeof (char));
928928+ }
929929+}
930930+931931+static int is_identifier (const char *s, int n)
932932+{
933933+ int i;
934934+935935+ /* Check whether a string can be used as a key without quotes and
936936+ * braces. */
937937+938938+ for (i = 0 ; i < n ; i += 1) {
939939+ if (!isalpha(s[i]) &&
940940+ (i == 0 || !isalnum(s[i])) &&
941941+ s[i] != '_') {
942942+ return 0;
943943+ }
944944+ }
945945+946946+ return 1;
947947+}
948948+949949+static void break_line ()
950950+{
951951+ int i;
952952+953953+ check_fit (indent + 1);
954954+955955+ /* Add a line break. */
956956+957957+ dump[offset] = '\n';
958958+959959+ /* And indent to the current level. */
960960+961961+ for (i = 1 ; i <= indent ; i += 1) {
962962+ dump[offset + i] = ' ';
963963+ }
964964+965965+ offset += indent + 1;
966966+ column = indent;
967967+}
968968+969969+static void dump_string (const char *s, int n)
970970+{
971971+ int l;
972972+973973+ /* Break the line if the current chunk doesn't fit but it would
974974+ * fit if we started on a fresh line at the current indent. */
975975+976976+ l = width(s);
977977+978978+ if (column + l > linewidth && indent + l <= linewidth) {
979979+ break_line();
980980+ }
981981+982982+ check_fit (n);
983983+984984+ /* Copy the string to the buffer. */
985985+986986+ memcpy (dump + offset, s, n);
987987+ dump[offset + n] = '\0';
988988+989989+ offset += n;
990990+ column += l;
991991+}
992992+993993+static void describe (lua_State *L, int index)
994994+{
995995+ char *s;
996996+ size_t n;
997997+ int type;
998998+999999+ index = absolute (L, index);
10001000+ type = lua_type (L, index);
10011001+10021002+ if (luaL_getmetafield (L, index, "__tostring")) {
10031003+ lua_pushvalue (L, index);
10041004+ lua_pcall (L, 1, 1, 0);
10051005+ s = (char *)lua_tolstring (L, -1, &n);
10061006+ lua_pop (L, 1);
10071007+10081008+ dump_string (s, n);
10091009+ } else if (type == LUA_TNUMBER) {
10101010+ /* Copy the value to avoid mutating it. */
10111011+10121012+ lua_pushvalue (L, index);
10131013+ s = (char *)lua_tolstring (L, -1, &n);
10141014+ lua_pop (L, 1);
10151015+10161016+ dump_string (s, n);
10171017+ } else if (type == LUA_TSTRING) {
10181018+ int i, started, score, level, uselevel = 0;
10191019+10201020+ s = (char *)lua_tolstring (L, index, &n);
10211021+10221022+ /* Scan the string to decide how to print it. */
10231023+10241024+ for (i = 0, score = n, started = 0 ; i < (int)n ; i += 1) {
10251025+ if (s[i] == '\n' || s[i] == '\t' ||
10261026+ s[i] == '\v' || s[i] == '\r') {
10271027+ /* These characters show up better in a long sting so
10281028+ * bias towards that. */
10291029+10301030+ score += linewidth / 2;
10311031+ } else if (s[i] == '\a' || s[i] == '\b' ||
10321032+ s[i] == '\f' || !isprint(s[i])) {
10331033+ /* These however go better with an escaped short
10341034+ * string (unless you like the bell or weird
10351035+ * characters). */
10361036+10371037+ score -= linewidth / 4;
10381038+ }
10391039+10401040+ /* Check what long string delimeter level to use so that
10411041+ * the string won't be closed prematurely. */
10421042+10431043+ if (!started) {
10441044+ if (s[i] == ']') {
10451045+ started = 1;
10461046+ level = 0;
10471047+ }
10481048+ } else {
10491049+ if (s[i] == '=') {
10501050+ level += 1;
10511051+ } else if (s[i] == ']') {
10521052+ if (level >= uselevel) {
10531053+ uselevel = level + 1;
10541054+ }
10551055+ } else {
10561056+ started = 0;
10571057+ }
10581058+ }
10591059+ }
10601060+10611061+ if (score > linewidth) {
10621062+ /* Dump the string as a long string. */
10631063+10641064+ dump_character ('[');
10651065+ for (i = 0 ; i < uselevel ; i += 1) {
10661066+ dump_character ('=');
10671067+ }
10681068+ dump_literal ("[\n");
10691069+10701070+ dump_string (s, n);
10711071+10721072+ dump_character (']');
10731073+ for (i = 0 ; i < uselevel ; i += 1) {
10741074+ dump_character ('=');
10751075+ }
10761076+ dump_literal ("]");
10771077+ } else {
10781078+ /* Escape the string as needed and print it as a normal
10791079+ * string. */
10801080+10811081+ dump_literal ("\"");
10821082+10831083+ for (i = 0 ; i < (int)n ; i += 1) {
10841084+ if (s[i] == '"' || s[i] == '\\') {
10851085+ dump_literal ("\\");
10861086+ dump_character (s[i]);
10871087+ } else if (s[i] == '\a') {
10881088+ dump_literal ("\\a");
10891089+ } else if (s[i] == '\b') {
10901090+ dump_literal ("\\b");
10911091+ } else if (s[i] == '\f') {
10921092+ dump_literal ("\\f");
10931093+ } else if (s[i] == '\n') {
10941094+ dump_literal ("\\n");
10951095+ } else if (s[i] == '\r') {
10961096+ dump_literal ("\\r");
10971097+ } else if (s[i] == '\t') {
10981098+ dump_literal ("\\t");
10991099+ } else if (s[i] == '\v') {
11001100+ dump_literal ("\\v");
11011101+ } else if (isprint(s[i])) {
11021102+ dump_character (s[i]);
11031103+ } else {
11041104+ char t[5];
11051105+ size_t n;
11061106+11071107+ n = sprintf (t, "\\%03u", ((unsigned char *)s)[i]);
11081108+ dump_string (t, n);
11091109+ }
11101110+ }
11111111+11121112+ dump_literal ("\"");
11131113+ }
11141114+ } else if (type == LUA_TNIL) {
11151115+ n = asprintf (&s, "%snil%s", COLOR(7), COLOR(8));
11161116+ dump_string (s, n);
11171117+ free(s);
11181118+ } else if (type == LUA_TBOOLEAN) {
11191119+ n = asprintf (&s, "%s%s%s",
11201120+ COLOR(7),
11211121+ lua_toboolean (L, index) ? "true" : "false",
11221122+ COLOR(8));
11231123+ dump_string (s, n);
11241124+ free(s);
11251125+ } else if (type == LUA_TFUNCTION) {
11261126+ n = asprintf (&s, "<%sfunction:%s %p>",
11271127+ COLOR(7), COLOR(8), lua_topointer (L, index));
11281128+ dump_string (s, n);
11291129+ free(s);
11301130+ } else if (type == LUA_TUSERDATA) {
11311131+ n = asprintf (&s, "<%suserdata:%s %p>",
11321132+ COLOR(7), COLOR(8), lua_topointer (L, index));
11331133+11341134+ dump_string (s, n);
11351135+ free(s);
11361136+ } else if (type == LUA_TTHREAD) {
11371137+ n = asprintf (&s, "<%sthread:%s %p>",
11381138+ COLOR(7), COLOR(8), lua_topointer (L, index));
11391139+ dump_string (s, n);
11401140+ free(s);
11411141+ } else if (type == LUA_TTABLE) {
11421142+ int i, l, n, oldindent, multiline, nobreak;
11431143+11441144+ /* Check if table is too deeply nested. */
11451145+11461146+ if (indent > 8 * linewidth / 10) {
11471147+ char *s;
11481148+ size_t n;
11491149+11501150+ n = asprintf (&s, "{ %s...%s }", COLOR(7), COLOR(8));
11511151+ dump_string (s, n);
11521152+ free(s);
11531153+11541154+ return;
11551155+ }
11561156+11571157+ /* Check if the table introduces a cycle by checking whether
11581158+ * it is a back-edge (that is equal to an ancestor table. */
11591159+11601160+ lua_rawgeti (L, LUA_REGISTRYINDEX, ancestors);
11611161+ n = lua_rawlen(L, -1);
11621162+11631163+ for (i = 0 ; i < n ; i += 1) {
11641164+ lua_rawgeti (L, -1, n - i);
11651165+#if LUA_VERSION_NUM == 501
11661166+ if(lua_equal (L, -1, -3)) {
11671167+#else
11681168+ if(lua_compare (L, -1, -3, LUA_OPEQ)) {
11691169+#endif
11701170+ char *s;
11711171+ size_t n;
11721172+11731173+ n = asprintf (&s, "{ %s[%d]...%s }",
11741174+ COLOR(7), -(i + 1), COLOR(8));
11751175+ dump_string (s, n);
11761176+ free(s);
11771177+ lua_pop (L, 2);
11781178+11791179+ return;
11801180+ }
11811181+11821182+ lua_pop (L, 1);
11831183+ }
11841184+11851185+ /* Add the table to the ancestor list and pop the ancestor
11861186+ * list table. */
11871187+11881188+ lua_pushvalue (L, index);
11891189+ lua_rawseti (L, -2, n + 1);
11901190+ lua_pop (L, 1);
11911191+11921192+ /* Open the table and update the indentation level to the
11931193+ * current column. */
11941194+11951195+ dump_literal ("{ ");
11961196+ oldindent = indent;
11971197+ indent = column;
11981198+ multiline = 0;
11991199+ nobreak = 0;
12001200+12011201+ l = lua_rawlen (L, index);
12021202+12031203+ /* Traverse the array part first. */
12041204+12051205+ for (i = 0 ; i < l ; i += 1) {
12061206+ lua_pushinteger (L, i + 1);
12071207+ lua_gettable (L, index);
12081208+12091209+ /* Start a fresh line when dumping tables to make sure
12101210+ * there's plenty of room. */
12111211+12121212+ if (lua_istable (L, -1)) {
12131213+ if (!nobreak) {
12141214+ break_line();
12151215+ }
12161216+12171217+ multiline = 1;
12181218+ }
12191219+12201220+ nobreak = 0;
12211221+12221222+ /* Dump the value and separating comma. */
12231223+12241224+ describe (L, -1);
12251225+ dump_literal (", ");
12261226+12271227+ if (lua_istable (L, -1) && i != l - 1) {
12281228+ break_line();
12291229+ nobreak = 1;
12301230+ }
12311231+12321232+ lua_pop (L, 1);
12331233+ }
12341234+12351235+ /* Now for the hash part. */
12361236+12371237+ lua_pushnil (L);
12381238+ while (lua_next (L, index) != 0) {
12391239+ if (lua_type (L, -2) != LUA_TNUMBER ||
12401240+ lua_tonumber (L, -2) != lua_tointeger (L, -2) ||
12411241+ lua_tointeger (L, -2) < 1 ||
12421242+ lua_tointeger (L, -2) > l) {
12431243+12441244+ /* Keep each key-value pair on a separate line. */
12451245+12461246+ break_line ();
12471247+ multiline = 1;
12481248+12491249+ /* Dump the key and value. */
12501250+12511251+ if (lua_type (L, -2) == LUA_TSTRING) {
12521252+ char *s;
12531253+ size_t n;
12541254+12551255+ s = (char *)lua_tolstring (L, -2, &n);
12561256+12571257+ if(is_identifier (s, n)) {
12581258+ dump_string (COLOR(7), strlen(COLOR(7)));
12591259+ dump_string (s, n);
12601260+ dump_string (COLOR(8), strlen(COLOR(8)));
12611261+ } else {
12621262+ dump_literal ("[");
12631263+ describe (L, -2);
12641264+ dump_literal ("]");
12651265+ }
12661266+ } else {
12671267+ dump_literal ("[");
12681268+ describe (L, -2);
12691269+ dump_literal ("]");
12701270+ }
12711271+12721272+ dump_literal (" = ");
12731273+ describe (L, -1);
12741274+ dump_literal (",");
12751275+ }
12761276+12771277+ lua_pop (L, 1);
12781278+ }
12791279+12801280+ /* Remove the table from the ancestor list. */
12811281+12821282+ lua_rawgeti (L, LUA_REGISTRYINDEX, ancestors);
12831283+ lua_pushnil (L);
12841284+ lua_rawseti (L, -2, n + 1);
12851285+ lua_pop (L, 1);
12861286+12871287+ /* Pop the indentation level. */
12881288+12891289+ indent = oldindent;
12901290+12911291+ if (multiline) {
12921292+ break_line();
12931293+ dump_literal ("}");
12941294+ } else {
12951295+ dump_literal (" }");
12961296+ }
12971297+ }
12981298+}
12991299+13001300+char *luap_describe (lua_State *L, int index)
13011301+{
13021302+ int oldcolorize;
13031303+13041304+#ifdef HAVE_IOCTL
13051305+ struct winsize w;
13061306+13071307+ /* Initialize the state. */
13081308+13091309+ if (ioctl(STDOUT_FILENO, TIOCGWINSZ, &w) < 0) {
13101310+ linewidth = 80;
13111311+ } else {
13121312+ linewidth = w.ws_col;
13131313+ }
13141314+#else
13151315+ linewidth = 80;
13161316+#endif
13171317+13181318+ index = absolute (L, index);
13191319+ offset = 0;
13201320+ indent = 0;
13211321+ column = 0;
13221322+13231323+ /* Suppress colorization, to avoid escape sequences in the
13241324+ * returned strings. */
13251325+13261326+ oldcolorize = colorize;
13271327+ colorize = 0;
13281328+13291329+ /* Create a table to hold the ancestors for checking for cycles
13301330+ * when printing table hierarchies. */
13311331+13321332+ lua_newtable (L);
13331333+ ancestors = luaL_ref (L, LUA_REGISTRYINDEX);
13341334+13351335+ describe (L, index);
13361336+13371337+ luaL_unref (L, LUA_REGISTRYINDEX, ancestors);
13381338+ colorize = oldcolorize;
13391339+13401340+ return dump;
13411341+}
13421342+13431343+/* These are custom commands. */
13441344+13451345+#ifdef HAVE_LIBREADLINE
13461346+static int describe_stack (int count, int key)
13471347+{
13481348+ int i, h;
13491349+13501350+ print_output ("%s", COLOR(7));
13511351+13521352+ h = lua_gettop (M);
13531353+13541354+ if (count < 0) {
13551355+ i = h + count + 1;
13561356+13571357+ if (i > 0 && i <= h) {
13581358+ print_output ("\nValue at stack index %d(%d):\n%s%s",
13591359+ i, -h + i - 1, COLOR(3), luap_describe (M, i));
13601360+ } else {
13611361+ print_error ("Invalid stack index.\n");
13621362+ }
13631363+ } else {
13641364+ if (h > 0) {
13651365+ print_output ("\nThe stack contains %d values.\n", h);
13661366+ for (i = 1 ; i <= h ; i += 1) {
13671367+ print_output ("\n%d(%d):\t%s", i, -h + i - 1, lua_typename(M, lua_type(M, i)));
13681368+ }
13691369+ } else {
13701370+ print_output ("\nThe stack is empty.");
13711371+ }
13721372+ }
13731373+13741374+ print_output ("%s\n", COLOR(0));
13751375+13761376+ rl_on_new_line ();
13771377+13781378+ return 0;
13791379+}
13801380+#endif
13811381+13821382+int luap_call (lua_State *L, int n) {
13831383+ int h, status;
13841384+13851385+ /* We can wind up here before reaching luap_enter, so this is
13861386+ * needed. */
13871387+13881388+ M = L;
13891389+13901390+ /* Push the error handler onto the stack. */
13911391+13921392+ h = lua_gettop(L) - n;
13931393+ lua_pushcfunction (L, traceback);
13941394+ lua_insert (L, h);
13951395+13961396+ /* Try to execute the supplied chunk and keep note of any return
13971397+ * values. */
13981398+13991399+ status = lua_pcall(L, n, LUA_MULTRET, h);
14001400+14011401+ /* Print any errors. */
14021402+14031403+ if (status != LUA_OK) {
14041404+ print_error ("%s%s%s\n", COLOR(1), lua_tostring (L, -1), COLOR(0));
14051405+ lua_pop (L, 1);
14061406+ }
14071407+14081408+ /* Remove the error handler. */
14091409+14101410+ lua_remove (L, h);
14111411+14121412+ return status;
14131413+}
14141414+14151415+void luap_setprompts(lua_State *L, const char *single, const char *multi)
14161416+{
14171417+ /* Plain, uncolored prompts. */
14181418+14191419+ prompts[0][0] = (char *)realloc (prompts[0][0], strlen (single) + 1);
14201420+ prompts[0][1] = (char *)realloc (prompts[0][1], strlen (multi) + 1);
14211421+ strcpy(prompts[0][0], single);
14221422+ strcpy(prompts[0][1], multi);
14231423+14241424+ /* Colored prompts. */
14251425+14261426+ prompts[1][0] = (char *)realloc (prompts[1][0], strlen (single) + 16);
14271427+ prompts[1][1] = (char *)realloc (prompts[1][1], strlen (multi) + 16);
14281428+#ifdef HAVE_LIBREADLINE
14291429+ sprintf (prompts[1][0], "\001%s\002%s\001%s\002",
14301430+ COLOR(6), single, COLOR(0));
14311431+ sprintf (prompts[1][1], "\001%s\002%s\001%s\002",
14321432+ COLOR(6), multi, COLOR(0));
14331433+#else
14341434+ sprintf (prompts[1][0], "%s%s%s", COLOR(6), single, COLOR(0));
14351435+ sprintf (prompts[1][1], "%s%s%s", COLOR(6), multi, COLOR(0));
14361436+#endif
14371437+}
14381438+14391439+void luap_sethistory(lua_State *L, const char *file)
14401440+{
14411441+ if (file) {
14421442+ logfile = realloc (logfile, strlen(file) + 1);
14431443+ strcpy (logfile, file);
14441444+ } else if (logfile) {
14451445+ free(logfile);
14461446+ logfile = NULL;
14471447+ }
14481448+}
14491449+14501450+void luap_setcolor(lua_State *L, int enable)
14511451+{
14521452+ /* Don't allow color if we're not writing to a terminal. */
14531453+14541454+ if (!isatty (STDOUT_FILENO) || !isatty (STDERR_FILENO)) {
14551455+ colorize = 0;
14561456+ } else {
14571457+ colorize = enable;
14581458+ }
14591459+}
14601460+14611461+void luap_setname(lua_State *L, const char *name)
14621462+{
14631463+ chunkname = (char *)realloc (chunkname, strlen(name) + 2);
14641464+ chunkname[0] = '=';
14651465+ strcpy (chunkname + 1, name);
14661466+}
14671467+14681468+void luap_getprompts(lua_State *L, const char **single, const char **multi)
14691469+{
14701470+ *single = prompts[0][0];
14711471+ *multi = prompts[0][1];
14721472+}
14731473+14741474+void luap_gethistory(lua_State *L, const char **file)
14751475+{
14761476+ *file = logfile;
14771477+}
14781478+14791479+void luap_getcolor(lua_State *L, int *enabled)
14801480+{
14811481+ *enabled = colorize;
14821482+}
14831483+14841484+void luap_getname(lua_State *L, const char **name)
14851485+{
14861486+ *name = chunkname + 1;
14871487+}
14881488+14891489+void luap_enter(lua_State *L, bool *terminate)
14901490+{
14911491+ int incomplete = 0, s = 0, t = 0, l;
14921492+ char *line, *prepended;
14931493+#ifdef SAVE_RESULTS
14941494+ int cleanup = 0;
14951495+#endif
14961496+14971497+ /* Save the state since it needs to be passed to some readline
14981498+ * callbacks. */
14991499+15001500+ M = L;
15011501+15021502+ if (!initialized) {
15031503+#ifdef HAVE_LIBREADLINE
15041504+ rl_basic_word_break_characters = " \t\n`@$><=;|&{(";
15051505+ rl_completion_entry_function = generator;
15061506+ rl_completion_display_matches_hook = display_matches;
15071507+15081508+ rl_add_defun ("lua-describe-stack", describe_stack, META('s'));
15091509+#endif
15101510+15111511+#ifdef HAVE_READLINE_HISTORY
15121512+ /* Load the command history if there is one. */
15131513+15141514+ if (logfile) {
15151515+ read_history (logfile);
15161516+ }
15171517+#endif
15181518+ if (!chunkname) {
15191519+ luap_setname (L, "lua");
15201520+ }
15211521+15221522+ if (!prompts[0][0]) {
15231523+ luap_setprompts (L, "> ", ">> ");
15241524+ }
15251525+15261526+ atexit (finish);
15271527+15281528+ initialized = 1;
15291529+ }
15301530+15311531+#ifdef SAVE_RESULTS
15321532+ if (results == LUA_REFNIL) {
15331533+ lua_newtable(L);
15341534+15351535+#ifdef WEAK_RESULTS
15361536+ lua_newtable(L);
15371537+ lua_pushliteral(L, "v");
15381538+ lua_setfield(L, -2, "__mode");
15391539+ lua_setmetatable(L, -2);
15401540+#endif
15411541+15421542+ results = luaL_ref(L, LUA_REGISTRYINDEX);
15431543+ }
15441544+15451545+ lua_getglobal(L, RESULTS_TABLE_NAME);
15461546+ if (lua_isnil(L, -1)) {
15471547+ lua_rawgeti(L, LUA_REGISTRYINDEX, results);
15481548+ lua_setglobal(L, RESULTS_TABLE_NAME);
15491549+15501550+ cleanup = 1;
15511551+ }
15521552+ lua_pop(L, 1);
15531553+#endif
15541554+15551555+ while (!(*terminate) &&
15561556+ (line = readline (incomplete ?
15571557+ prompts[colorize][1] : prompts[colorize][0]))) {
15581558+ int status;
15591559+15601560+ if (*line == '\0') {
15611561+ free(line);
15621562+ continue;
15631563+ }
15641564+15651565+ /* Add/copy the line to the buffer. */
15661566+15671567+ if (incomplete) {
15681568+ s += strlen (line) + 1;
15691569+15701570+ if (s > t) {
15711571+ buffer = (char *)realloc (buffer, s + 1);
15721572+ t = s;
15731573+ }
15741574+15751575+ strcat (buffer, "\n");
15761576+ strcat (buffer, line);
15771577+ } else {
15781578+ s = strlen (line);
15791579+15801580+ if (s > t) {
15811581+ buffer = (char *)realloc (buffer, s + 1);
15821582+ t = s;
15831583+ }
15841584+15851585+ strcpy (buffer, line);
15861586+ }
15871587+15881588+ /* Try to execute the line with a return prepended first. If
15891589+ * this works we can show returned values. */
15901590+15911591+ l = asprintf (&prepended, "return %s", buffer);
15921592+15931593+ if (luaL_loadbuffer(L, prepended, l, chunkname) == LUA_OK) {
15941594+ execute();
15951595+15961596+ incomplete = 0;
15971597+ } else {
15981598+ lua_pop (L, 1);
15991599+16001600+ /* Try to execute the line as-is. */
16011601+16021602+ status = luaL_loadbuffer(L, buffer, s, chunkname);
16031603+16041604+ incomplete = 0;
16051605+16061606+ if (status == LUA_ERRSYNTAX) {
16071607+ const char *message;
16081608+ const int k = sizeof(EOF_MARKER) / sizeof(char) - 1;
16091609+ size_t n;
16101610+16111611+ message = lua_tolstring (L, -1, &n);
16121612+16131613+ /* If the error message mentions an unexpected eof
16141614+ * then consider this a multi-line statement and wait
16151615+ * for more input. If not then just print the error
16161616+ * message.*/
16171617+16181618+ if ((int)n > k &&
16191619+ !strncmp (message + n - k, EOF_MARKER, k)) {
16201620+ incomplete = 1;
16211621+ } else {
16221622+ print_error ("%s%s%s\n", COLOR(1), lua_tostring (L, -1),
16231623+ COLOR(0));
16241624+ }
16251625+16261626+ lua_pop (L, 1);
16271627+ } else if (status == LUA_ERRMEM) {
16281628+ print_error ("%s%s%s\n", COLOR(1), lua_tostring (L, -1),
16291629+ COLOR(0));
16301630+ lua_pop (L, 1);
16311631+ } else {
16321632+ /* Try to execute the loaded chunk. */
16331633+16341634+ execute ();
16351635+ incomplete = 0;
16361636+ }
16371637+ }
16381638+16391639+#ifdef HAVE_READLINE_HISTORY
16401640+ /* Add the line to the history if non-empty. */
16411641+16421642+ if (!incomplete) {
16431643+ add_history (buffer);
16441644+ }
16451645+#endif
16461646+16471647+ free (prepended);
16481648+ free (line);
16491649+ }
16501650+16511651+#ifdef SAVE_RESULTS
16521652+ if (cleanup) {
16531653+ lua_pushnil(L);
16541654+ lua_setglobal(L, RESULTS_TABLE_NAME);
16551655+ }
16561656+#endif
16571657+16581658+ print_output ("\n");
16591659+}
+55
utils/hwstub/tools/prompt.h
···11+/* Copyright (C) 2012-2015 Papavasileiou Dimitris
22+ *
33+ * Permission is hereby granted, free of charge, to any person
44+ * obtaining a copy of this software and associated documentation
55+ * files (the "Software"), to deal in the Software without
66+ * restriction, including without limitation the rights to use, copy,
77+ * modify, merge, publish, distribute, sublicense, and/or sell copies
88+ * of the Software, and to permit persons to whom the Software is
99+ * furnished to do so, subject to the following conditions:
1010+ *
1111+ * The above copyright notice and this permission notice shall be
1212+ * included in all copies or substantial portions of the Software.
1313+ *
1414+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
1515+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
1616+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
1717+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
1818+ * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
1919+ * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
2020+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
2121+ * SOFTWARE.
2222+ */
2323+2424+#ifndef _PROMPT_H_
2525+#define _PROMPT_H_
2626+2727+#include <lualib.h>
2828+#include <lauxlib.h>
2929+3030+#define HAVE_LIBREADLINE
3131+#define HAVE_READLINE_HISTORY
3232+#define HAVE_IOCTL
3333+#define COMPLETE_KEYWORDS
3434+#define COMPLETE_MODULES
3535+#define COMPLETE_TABLE_KEYS
3636+#define COMPLETE_METATABLE_KEYS
3737+#define COMPLETE_FILE_NAMES
3838+3939+#define LUAP_VERSION "0.6"
4040+4141+void luap_setprompts(lua_State *L, const char *single, const char *multi);
4242+void luap_sethistory(lua_State *L, const char *file);
4343+void luap_setname(lua_State *L, const char *name);
4444+void luap_setcolor(lua_State *L, int enable);
4545+4646+void luap_getprompts(lua_State *L, const char **single, const char **multi);
4747+void luap_gethistory(lua_State *L, const char **file);
4848+void luap_getcolor(lua_State *L, int *enabled);
4949+void luap_getname(lua_State *L, const char **name);
5050+5151+void luap_enter(lua_State *L, bool *terminate);
5252+char *luap_describe (lua_State *L, int index);
5353+int luap_call (lua_State *L, int n);
5454+5555+#endif