diff --git a/configure.in b/configure.in index 5554437..abda612 100644 --- a/configure.in +++ b/configure.in @@ -1726,6 +1726,44 @@ int main () { } ], AC_DEFINE(HAVE_STRFTIME_z) AC_MSG_RESULT(yes) , AC_MSG_RESULT(no), 0) +savedLIBS=$LIBS +LIBS= +dnl Need flex if we are to get a lexer which can read from a buffer +if test $LEX = flex +then + lib_for_curses= + lib_for_readline= + + dnl first check for readline on its own then with curses + AC_CHECK_FUNC(readline,, + [ + AC_CHECK_LIB(readline, readline,, + [ + dnl AC seems to cache lib/func results + dnl so use another readline func here + AC_CHECK_LIB(readline, add_history,,,[-lcurses]) + ]) + ]) + + if test $ac_cvs_func_readline = yes + then + AC_DEFINE(HAVE_READLINE) + elif test $ac_cv_lib_readline_readline = yes + then + AC_DEFINE(HAVE_READLINE) + lib_for_readline=-lreadline + elif test $ac_cv_lib_readline_add_history = yes + then + AC_DEFINE(HAVE_READLINE) + lib_for_curses=-lcurses + lib_for_readline=-lreadline + fi + + AC_SUBST(lib_for_readline) + AC_SUBST(lib_for_curses) +fi +LIBS=$savedLIBS + dnl dnl output files dnl diff --git a/src/dbpmda/src/GNUmakefile b/src/dbpmda/src/GNUmakefile index 859177b..700b4ac 100644 --- a/src/dbpmda/src/GNUmakefile +++ b/src/dbpmda/src/GNUmakefile @@ -27,7 +27,7 @@ LFILES = lex.l YFILES = gram.y LDIRT = *.log foo.* gram.h $(YFILES:%.y=%.tab.?) $(LFILES:%.l=%.c) -LLDLIBS = -lpcp $(LIB_FOR_DLOPEN) +LLDLIBS = -lpcp $(LIB_FOR_DLOPEN) $(LIB_FOR_READLINE) $(LIB_FOR_CURSES) default: $(CMDTARGET) diff --git a/src/dbpmda/src/dbpmda.c b/src/dbpmda/src/dbpmda.c index 1f42ce2..6c6c20d 100644 --- a/src/dbpmda/src/dbpmda.c +++ b/src/dbpmda/src/dbpmda.c @@ -78,7 +78,14 @@ main(int argc, char **argv) #endif case 'e': /* echo input */ +#if HAVE_READLINE + /* + * echo is not really optional when using readline(), + * and setting eflag would only trigger a double echo + */ +#else eflag++; +#endif break; case 'i': /* be interactive */ diff --git a/src/dbpmda/src/lex.l b/src/dbpmda/src/lex.l index b3c8117..83b79f9 100644 --- a/src/dbpmda/src/lex.l +++ b/src/dbpmda/src/lex.l @@ -24,6 +24,13 @@ int lineno = 0; #include "./lex.h" +#if HAVE_READLINE +#include +#include +static char *rl_str = NULL; +static int rl_strpos = 0; +#endif + #ifdef FLEX_SCANNER #define YY_NO_UNPUT #include "./gram.tab.h" @@ -178,6 +185,46 @@ dbpmdaGetc (char * inbuf) { int inch; +#if HAVE_READLINE + char rl_prompt_storage[64]; + char *rl_prompt = rl_prompt_storage; + + if (iflag) + snprintf(rl_prompt_storage, 64, "%s> ", prompt); + else + rl_prompt = NULL; + + rl_instream = yyin; + + if (!rl_str) { + do { + /* note, echo happens here independent of eflag setting */ + rl_str = readline(rl_prompt); + if (!rl_str) { + inbuf[0] = 0; + return inbuf[0]; + } + } while (!rl_str[0]); + } + + inch = rl_str[rl_strpos++]; + if (inch == '\r') + inch = rl_str[rl_strpos++]; + + if (!inch) { + /* end of input line, fake out \n so parser notices */ + inch = '\n'; + /* and setup to call readline() next time */ + free(rl_str); + rl_str = NULL; + rl_strpos = 0; + } + + inbuf[0] = inch & 0xFFU; + + return inch; +#endif + while ((inch = fgetc (yyin)) != EOF ) { inbuf[0] = inch & 0xFFU; if (inbuf[0] == '\r') { @@ -218,10 +265,21 @@ dbpmdaFlexInput (char * inbuf, int ms) } if ( lastc == '\n' ) { +#if HAVE_READLINE + + if (line != NULL && *line != '\0' && *line != '\n') { + /* line is not empty, push it into history */ + char *newline = strchr(line, '\n'); + if (newline != NULL) *newline = '\0'; + add_history(line); + if (newline != NULL) *newline = '\n'; + } +#else if ( iflag ) { printf ("%s> ", prompt); fflush (stdout); } +#endif lineno++; linepos = 0; } @@ -246,10 +304,13 @@ dbpmdaFlexInput (char * inbuf, int ms) lineno = 1; prompt = "dbpmda"; configfile = NULL; - if ( (iflag = save_iflag) ) { - printf ("%s >", prompt); - fflush (stdout); + iflag = save_iflag; +#ifndef HAVE_READLINE + if ( iflag ) { + printf("%s> ", prompt); + fflush(stdout); } +#endif eflag = save_eflag; } else { return (0); @@ -451,6 +512,18 @@ doargs(void) } if (c == '\n' || c == '\0') { #ifdef FLEX_SCANNER +#if HAVE_READLINE + if (c == '\n') { + /* + * extra \n is faked after end of input line in + * dbpmdaGetc ... to push this back into the input + * stream requires an even bigger hack ... + */ + rl_str = strdup("\n"); + rl_strpos = 0; + } +#else +#endif ungetc (c, yyin); #else unput('\n'); diff --git a/src/include/builddefs.in b/src/include/builddefs.in index d934852..d2675e2 100644 --- a/src/include/builddefs.in +++ b/src/include/builddefs.in @@ -181,6 +181,8 @@ LIB_FOR_BASENAME = @lib_for_basename@ LIB_FOR_DLOPEN = @lib_for_dlopen@ LIB_FOR_REGEX = @lib_for_regex@ LIB_FOR_MATH = @lib_for_math@ +LIB_FOR_READLINE = @lib_for_readline@ +LIB_FOR_CURSES = @lib_for_curses@ SHELL = /bin/sh IMAGES_DIR = $(TOPDIR)/all-images diff --git a/src/include/platform_defs.h.in b/src/include/platform_defs.h.in index 88f39bd..526a993 100644 --- a/src/include/platform_defs.h.in +++ b/src/include/platform_defs.h.in @@ -137,6 +137,7 @@ extern "C" { #undef HAVE_SYS_ENDIAN_H #undef HAVE_SYS_MACHINE_H #undef HAVE_MACHINE_ENDIAN_H +#undef HAVE_READLINE #if defined(HAVE_MALLOC_H) #include