Added readline patch (support for command history).

This commit is contained in:
pnenzi 2003-08-14 19:21:10 +00:00
parent 8d05f51d74
commit 8686a73047
11 changed files with 283 additions and 10 deletions

View File

@ -1,3 +1,21 @@
2003-08-14 Paolo Nenzi <p.nenzi@ieee.org>
* configure.in, src/main.c, src/misc/tilde.c, src/misc/tilde.h,
src/frontend/com_history.c, src/frontend/misccoms.h,
src/frontend/signal_handler.c, src/frontend/plotting/x11.c,
src/frontend/parser/glob.c, src/include/ngspice.h:
Added Andrew Veliath patch fo readline support. Using
readline with ngspice IS A VIOLATION OF GPL LICENSE, you
have been warned. The final decision is up to you. The
patch has been applied in the perspective of changing
readline library with libedit. Libedit aims to be a
replacement of readline and is covered by BSD license.
Libedit is available at the URL: libedit.sourceforge.net.
Readline code has been extrapolated from a patch available
on http://www.btae.mam.gov.tr/~genc/ngspice/.
2003-08-11 Paolo Nenzi <p.nenzi@ieee.org>
* doc/ngspice.texi: updated documentation. Still incomplete

View File

@ -463,9 +463,8 @@ fi
dnl --with-readline : the user wants to use readline library
AC_ARG_WITH(readline,
[ --with-readline Use the readline package: SEE README],
[ --with-readline Use the readline library. WARNING: breaks GPL license],
AC_MSG_RESULT(Checking for readline library:)
Check for the readline library:
AC_CHECK_LIB(readline, readline, AC_DEFINE(HAVE_GNUREADLINE) LIBS="$LIBS -lreadline")
)

View File

@ -10,6 +10,13 @@ Author: 1985 Wayne A. Christopher, U. C. Berkeley CAD Group
#include "com_history.h"
#ifdef HAVE_GNUREADLINE
/* Added GNU Readline Support -- Andrew Veliath <veliaa@rpi.edu> */
#include <readline/readline.h>
#include <readline/history.h>
#endif /* HAVE_GNUREADLINE */
/* static declarations */
static wordlist * dohsubst(char *string);
@ -346,8 +353,10 @@ cp_addhistent(int event, wordlist *wlist)
cp_lastone->hi_next = NULL;
cp_lastone->hi_event = event;
cp_lastone->hi_wlist = wl_copy(wlist);
#ifndef HAVE_GNUREADLINE
freehist(histlength - cp_maxhistlength);
histlength++;
#endif
return;
}
@ -484,10 +493,36 @@ com_history(wordlist *wl)
wl = wl->wl_next;
rev = TRUE;
}
#ifdef HAVE_GNUREADLINE
/* Added GNU Readline Support -- Andrew Veliath <veliaa@rpi.edu> */
{
HIST_ENTRY *he;
int i, N;
N = (wl == NULL) ? history_length : atoi(wl->wl_word);
if (N < 0) N = 0;
if (N > history_length) N = history_length;
if (rev)
for (i = history_length; i > 0 && N; --i, --N) {
he = history_get(i);
if (!he) return;
fprintf(cp_out, "%d\t%s\n", i, he->line);
}
else
for (i = history_length - N + 1; i <= history_length; ++i) {
he = history_get(i);
if (!he) return;
fprintf(cp_out, "%d\t%s\n", i, he->line);
}
}
#else
if (wl == NULL)
cp_hprint(cp_event - 1, cp_event - histlength, rev);
else
cp_hprint(cp_event - 1, cp_event - 1 - atoi(wl->wl_word), rev);
#endif /* ifelse HAVE_GNUREADLINE */
return;
}

View File

@ -15,6 +15,13 @@ Author: 1985 Wayne A. Christopher, U. C. Berkeley CAD Group
#include "hcomp.h"
#include "variable.h"
#ifdef HAVE_GNUREADLINE
#include <readline/readline.h>
#include <readline/history.h>
extern int gnu_history_lines;
extern char gnu_history_file[];
#endif
static void byemesg(void);
@ -79,9 +86,14 @@ com_quit(wordlist *wl)
byemesg();
} else
byemesg();
#ifdef HAVE_GNUREADLINE
/* Added GNU Readline Support -- Andrew Veliath <veliaa@rpi.edu> */
if (cp_interactive && (cp_maxhistlength > 0)) {
stifle_history(cp_maxhistlength);
write_history(gnu_history_file);
}
#endif /* HAVE_GNUREADLINE */
exit(EXIT_NORMAL);
}

View File

@ -42,7 +42,7 @@ char cp_til = '~';
* globbing in them. Sort after the second phase but not the first...
*/
/* MW. Now only tilde is supportef, {}*? don't work */
/* MW. Now only tilde is supported, {}*? don't work */
wordlist *
cp_doglob(wordlist *wlist)
@ -72,8 +72,11 @@ cp_tildexpand(char *string)
{
char *result;
#ifdef HAVE_READLINE
result = tildexpand(string);
#else
result = tilde_expand(string);
#endif
if (!result) {
if (cp_nonomatch) {
return copy(string);

View File

@ -788,12 +788,15 @@ zoomin(GRAPH *graph)
graph->commandline, fx0, fx1, fy0, fy1);
}
/* don't use the following if using GNU Readline - AV */
#ifndef HAVE_GNUREADLINE
/* hack for Gordon Jacobs */
/* add to history list if plothistory is set */
if (cp_getvar("plothistory", VT_BOOL, (char *) &dummy)) {
wl = cp_parse(buf);
(void) cp_addhistent(cp_event++, wl);
}
#endif /* HAVE_GNUREADLINE */
(void) cp_evloop(buf);

View File

@ -32,6 +32,8 @@ extern jmp_buf jbuf;
extern pid_t getpid (void);
/* not using SIGINT with GNU Readline - AV */
#ifndef HAVE_GNUREADLINE
RETSIGTYPE
ft_sigintr(void)
{
@ -55,7 +57,7 @@ ft_sigintr(void)
cp_resetcontrol();
longjmp(jbuf, 1);
}
#endif /* !HAVE_GNUREADLINE */
RETSIGTYPE
sigfloat(int sig, int code)

View File

@ -134,8 +134,11 @@ extern int scannum(char *str);
extern int ciprefix(register char *p, register char *s);
extern int cieq(register char *p, register char *s);
extern void strtolower(char *str);
#ifdef HAVE_GNUREADLINE
extern char *tildexpand(char *string);
#else
extern char *tilde_expand(char *string);
#endif
extern char *smktemp(char *id);
extern char *copy(char *str);

View File

@ -43,6 +43,14 @@
#include <pwd.h>
#endif
#ifdef HAVE_GNUREADLINE
/* Added GNU Readline Support 11/3/97 -- Andrew Veliath <veliaa@rpi.edu> */
/* from spice3f4 patch to ng-spice. jmr */
#include <readline/readline.h>
#include <readline/history.h>
#include "fteinput.h"
#endif
#ifndef HAVE_GETRUSAGE
#ifdef HAVE_FTIME
#include <sys/timeb.h>
@ -64,6 +72,11 @@ bool ft_intrpt = FALSE; /* Set by the (void) signal handlers. */
bool ft_setflag = FALSE; /* Don't abort after an interrupt. */
char *ft_rawfile = "rawspice.raw";
#ifdef HAVE_GNUREADLINE
char gnu_history_file[512];
static char *application_name;
#endif
bool oflag = FALSE; /* Output über redefinierte Funktionen */
FILE *flogp; // hvogt 15.12.2001
@ -309,6 +322,89 @@ shutdown(int exitval)
exit (exitval);
}
#ifdef HAVE_GNUREADLINE
/* Adapted ../lib/cp/lexical.c:prompt() for GNU Readline -- Andrew Veliath <veliaa@rpi.edu> */
static char *
prompt()
{
static char pbuf[128];
char *p = pbuf, *s;
if (cp_interactive == FALSE)
return;
if (cp_promptstring == NULL)
s = "-> ";
else
s = cp_promptstring;
if (cp_altprompt)
s = cp_altprompt;
while (*s) {
switch (strip(*s)) {
case '!':
p += sprintf(p, "%d", where_history() + 1);
break;
case '\\':
if (*(s + 1))
p += sprintf(p, "%c", strip(*++s));
default:
*p = strip(*s); ++p;
break;
}
s++;
}
*p = 0;
return pbuf;
}
/* Process device events in Readline's hook since there is no where
else to do it now - AV */
int rl_event_func()
{
static REQUEST reqst = { checkup_option, 0 };
Input(&reqst, NULL);
return 0;
}
/* Added GNU Readline Support -- Andrew Veliath <veliaa@rpi.edu> */
void app_rl_readlines()
{
char *line, *expanded_line;
strcpy(gnu_history_file, getenv("HOME"));
strcat(gnu_history_file, "/.");
strcat(gnu_history_file, application_name);
strcat(gnu_history_file, "_history");
using_history();
read_history(gnu_history_file);
rl_readline_name = application_name;
rl_instream = cp_in;
rl_outstream = cp_out;
rl_event_hook = rl_event_func;
while (1) {
history_set_pos(history_length);
line = readline(prompt());
if (line && *line) {
int s = history_expand(line, &expanded_line);
if (s == 2) {
fprintf(stderr, "-> %s\n", expanded_line);
} else if (s == -1) {
fprintf(stderr, "readline: %s\n", expanded_line);
} else {
cp_evloop(expanded_line);
add_history(expanded_line);
}
free(expanded_line);
}
if (line) free(line);
}
/* History gets written in ../fte/misccoms.c com_quit */
}
#endif /* HAVE_GNUREADLINE */
void
show_help(void)
{
@ -423,6 +519,13 @@ main(int argc, char **argv)
}
started = TRUE;
#ifdef HAVE_GNUREADLINE
if (!(application_name = strrchr(argv[0],'/')))
application_name = argv[0];
else
++application_name;
#endif
#ifdef PARALLEL_ARCH
PBEGIN_(argc, argv);
ARCHme = NODEID_();
@ -617,7 +720,11 @@ main(int argc, char **argv)
/* Set up signal handling */
if (!ft_batchmode) {
#ifndef HAVE_GNUREADLINE
signal(SIGINT, ft_sigintr);
#endif
signal(SIGFPE, sigfloat);
#if defined(SIGTSTP) // && !defined(__MINGW32__)
signal(SIGTSTP, sigstop);
@ -788,7 +895,11 @@ evl:
} else {
(void) setjmp(jbuf);
cp_interactive = TRUE;
#ifdef HAVE_GNUREADLINE
app_rl_readlines();
#else
while (cp_evloop((char *) NULL) == 1) ;
#endif /* ifelse HAVE_GNUREADLINE */
}
#else /* ~ SIMULATOR */
@ -806,7 +917,11 @@ evl:
/* Nutmeg "main" */
(void) setjmp(jbuf);
cp_interactive = TRUE;
#ifdef HAVE_GNUREADLINE
app_rl_readlines();
#else
while (cp_evloop((char *) NULL) == 1) ;
#endif /* ifelse HAVE_GNUREADLINE */
#endif /* ~ SIMULATOR */

View File

@ -1,5 +1,6 @@
/**********
Copyright 1991 Regents of the University of California. All rights reserved.
Modified: 2002 R. Oktas, <roktas@omu.edu.tr>
**********/
#include <config.h>
@ -14,11 +15,30 @@ Copyright 1991 Regents of the University of California. All rights reserved.
#include <pwd.h>
#endif
/* XXX To prevent a name collision with `readline's `tilde_expand',
the original name: `tilde_expand' has changed to `tildexpand'. This
situation naturally brings to mind that `tilde_expand' could be used
directly from `readline' (since it will already be included if we
wish to activate the `readline' support). Following implementation of
'tilde expanding' has some problems which constitutes another good
reason why it should be replaced: eg. it returns NULL which should
not behave this way, IMHO. Anyway... Don't care for the moment, may
be in the future. -- ro */
/* PN: Since readline patch is not compiled in by default the behaviour
described above is not acceptable. I will make two different version
of tilde expansion routine, the one choosen depends on HAVE_GNUREADLINE
Note: since a readline replacement called libedit is under
development at libedit.sourceforge.net, I will switch to it
ASAP, since libedit is covered by BSD licnse.
*/
#ifndef HAVE_GNUREADLINE
char *
tilde_expand(char *string)
{
#ifdef HAVE_PWD_H
struct passwd *pw;
/*extern struct passwd *getpwuid( );*/
@ -60,3 +80,63 @@ tilde_expand(char *string)
return copy(string);
#endif
}
#else /* HAVE_GNUREADLINE */
char *
tildexpand(char *string)
{
char buf[BSIZE_SP];
char *result, *k, c;
if (!string)
return NULL;
while (*string && isspace(*string))
string++;
if (*string != '~')
return copy(string);
string += 1;
if (!*string || *string == '/') {
/* First try the environment setting. May also make life easier
for non-unix platforms, eg. MS-DOS. -- ro */
result = getenv("HOME");
#ifdef HAVE_PWD_H
/* Can't find a result from the environment, let's try
the other stuff. -- ro */
if (!result) {
struct passwd *pw;
pw = getpwuid(getuid());
if (pw)
result = pw->pw_dir;
*buf = 0;
}
} else {
struct passwd *pw;
k = buf;
while ((c = *string) && c != '/')
*k++ = c, string++;
*k = 0;
pw = getpwnam(buf);
if (pw)
result = pw->pw_dir;
#endif
}
if (result) {
#ifdef HAVE_PWD_H
strcpy(buf, result);
if (*string)
strcat(buf, string);
return copy(buf);
} else
return NULL;
#else
/* Emulate the old behavior to prevent side effects. -- ro */
return copy(string);
#endif
}
#endif /* HAVE_GNUREADLINE */

View File

@ -6,7 +6,10 @@
#ifndef TILDE_H_INCLUDED
#define TILDE_H_INCLUDED
#ifdef HAVE_GNUREADLINE
char * tildexpand(char *string);
#else
char * tilde_expand(char *string);
#endif
#endif