From: Hugo Villeneuve Date: Sat, 8 Feb 2014 07:40:54 +0000 (-0500) Subject: Add support for GNU readline X-Git-Tag: v2.0.1~24 X-Git-Url: http://gitweb.hugovil.com/?p=emu8051.git;a=commitdiff_plain;h=f2fba46bfe9848902c71eabbf78d6092894707a6 Add support for GNU readline readline input is fed into Lex. This adds commands history. There is also a configure option to disable readline support. --- diff --git a/configure.ac b/configure.ac index 1314fca..b4e5f0d 100644 --- a/configure.ac +++ b/configure.ac @@ -17,6 +17,23 @@ dnl Testing for libtool support. AC_PROG_RANLIB AM_PROG_AR +AC_ARG_WITH([readline], + [AS_HELP_STRING([--without-readline], [disable support for readline])], + [], + [with_readline=yes]) + +LIBREADLINE= + AS_IF([test "x$with_readline" != xno], + [AC_CHECK_LIB([readline], [main], + [AC_SUBST([LIBREADLINE], ["-lreadline"]) + AC_DEFINE([HAVE_LIBREADLINE], [1], + [Define if you have libreadline]) + ], + [AC_MSG_FAILURE( + [readline test failed (--without-readline to disable)])], + [] +)]) + dnl Testing for Lex/Yacc AC_PROG_LEX AC_PROG_YACC diff --git a/src/cli/Makefile.am b/src/cli/Makefile.am index ac87424..d78b89e 100644 --- a/src/cli/Makefile.am +++ b/src/cli/Makefile.am @@ -5,10 +5,14 @@ AM_CPPFLAGS = \ -I@top_srcdir@ \ -I@top_srcdir@/src/common +# Option -d: produce header file scanner.h +AM_LFLAGS = --header-file=scanner.h + # Option -d: produce header file parser.h AM_YFLAGS = -d LDADD = \ + $(LIBREADLINE) \ $(top_builddir)/src/common/libemu8051.a bin_PROGRAMS = emu8051-cli diff --git a/src/cli/main.c b/src/cli/main.c index bf71cf9..1a3db81 100644 --- a/src/cli/main.c +++ b/src/cli/main.c @@ -19,10 +19,11 @@ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA. */ +#include "config.h" + #include #include -#include "config.h" #include "common.h" #include "cpu8051.h" #include "options.h" @@ -55,7 +56,6 @@ main(int argc, char **argv) } else { menu_display_usage(); console_show_registers(); - menu_prompt(); yyparse(); } diff --git a/src/cli/menu.c b/src/cli/menu.c index d57cbb1..f4a12d6 100644 --- a/src/cli/menu.c +++ b/src/cli/menu.c @@ -19,10 +19,16 @@ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA. */ +#include "config.h" + #include #include #include #include +#ifdef HAVE_LIBREADLINE +#include +#include +#endif /* HAVE_LIBREADLINE */ #include "common.h" #include "cpu8051.h" @@ -33,14 +39,59 @@ #include "options.h" #include "hexfile.h" #include "keyboard.h" +#include "scanner.h" #include "menu.h" extern struct options_t options; -void -menu_prompt(void) +#define YY_NULL 0 + +#define MENU_PROMPT "-> " + +int +menu_get_input(char *buf, ssize_t size) { - printf("-> "); + char *line; + int max_len; + + max_len = size - 2; + + if (feof(yyin)) + return YY_NULL; + +#ifdef HAVE_LIBREADLINE + /* Get the input line, and if non-empty, place it in the history. */ + line = readline(MENU_PROMPT); + if (!line) + return YY_NULL; + + if (line && *line) + add_history(line); + + if ((int) strlen(line) > max_len) { + printf("input line too long"); + return YY_NULL; + } + + strcpy(buf, line); + + /* Readline never gives you the last '\n', so add it back for Lex. */ + strcat(buf, "\n"); + + free(line); +#else + /* It's okay to print a prompt if we are redirecting stdout, + * as long as stdin is still a tty. Otherwise, don't print + * a prompt at all if stdin is redirected. + */ + (void) fputs(MENU_PROMPT, stdout); + (void) fflush(stdout); /* for svr4 */ + line = fgets(buf, max_len, stdin); + if (!line) + return YY_NULL; +#endif + + return strlen(buf); } void diff --git a/src/cli/menu.h b/src/cli/menu.h index 9dd2919..eba287a 100644 --- a/src/cli/menu.h +++ b/src/cli/menu.h @@ -25,8 +25,8 @@ int yyparse(void); -void -menu_prompt(void); +int +menu_get_input(char *buf, ssize_t size); void menu_display_usage(void); diff --git a/src/cli/parser.y b/src/cli/parser.y index 1cb282c..7d22681 100644 --- a/src/cli/parser.y +++ b/src/cli/parser.y @@ -45,13 +45,12 @@ int yyerror(const char *str) %% -start : start command { menu_prompt(); } +start : start command | error TOK_ENTER { /* In case of error, discard entire line */ yyerrok; - menu_prompt(); } - | start TOK_ENTER { menu_prompt(); } + | start TOK_ENTER | ; diff --git a/src/cli/scanner.l b/src/cli/scanner.l index 6abaa30..4cdf42f 100644 --- a/src/cli/scanner.l +++ b/src/cli/scanner.l @@ -2,8 +2,13 @@ %option noinput %option nounput %{ + #include "menu.h" #include "parser.h" #include "hexfile.h" + +#undef YY_INPUT +#define YY_INPUT(buf,result,max_size) result = menu_get_input(buf, max_size); + %} digit [0-9]