diff --git a/ChangeLog b/ChangeLog
index 0a68042f7..b45bda33b 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,21 @@
+2003-08-14 Paolo Nenzi
+
+ * 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
* doc/ngspice.texi: updated documentation. Still incomplete
diff --git a/configure.in b/configure.in
index abb105f91..f42e8e4cd 100644
--- a/configure.in
+++ b/configure.in
@@ -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")
)
diff --git a/src/frontend/com_history.c b/src/frontend/com_history.c
index f6b03a77b..0fa5cb2ed 100644
--- a/src/frontend/com_history.c
+++ b/src/frontend/com_history.c
@@ -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 */
+#include
+#include
+
+#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 */
+ {
+ 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;
}
diff --git a/src/frontend/misccoms.c b/src/frontend/misccoms.c
index bec8db9b9..09fc0e7ed 100644
--- a/src/frontend/misccoms.c
+++ b/src/frontend/misccoms.c
@@ -15,6 +15,13 @@ Author: 1985 Wayne A. Christopher, U. C. Berkeley CAD Group
#include "hcomp.h"
#include "variable.h"
+#ifdef HAVE_GNUREADLINE
+#include
+#include
+
+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 */
+ if (cp_interactive && (cp_maxhistlength > 0)) {
+ stifle_history(cp_maxhistlength);
+ write_history(gnu_history_file);
+ }
+#endif /* HAVE_GNUREADLINE */
exit(EXIT_NORMAL);
-
}
diff --git a/src/frontend/parser/glob.c b/src/frontend/parser/glob.c
index 4135e6eaa..7a46c3bda 100644
--- a/src/frontend/parser/glob.c
+++ b/src/frontend/parser/glob.c
@@ -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);
diff --git a/src/frontend/plotting/x11.c b/src/frontend/plotting/x11.c
index 9fce9606b..8f337fcad 100644
--- a/src/frontend/plotting/x11.c
+++ b/src/frontend/plotting/x11.c
@@ -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);
diff --git a/src/frontend/signal_handler.c b/src/frontend/signal_handler.c
index 4f51bab0d..37a2a7a56 100644
--- a/src/frontend/signal_handler.c
+++ b/src/frontend/signal_handler.c
@@ -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)
diff --git a/src/include/ngspice.h b/src/include/ngspice.h
index e3149d8a7..e5f1aa11c 100644
--- a/src/include/ngspice.h
+++ b/src/include/ngspice.h
@@ -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);
diff --git a/src/main.c b/src/main.c
index 62d1807cd..5a640034d 100644
--- a/src/main.c
+++ b/src/main.c
@@ -43,6 +43,14 @@
#include
#endif
+#ifdef HAVE_GNUREADLINE
+/* Added GNU Readline Support 11/3/97 -- Andrew Veliath */
+/* from spice3f4 patch to ng-spice. jmr */
+#include
+#include
+#include "fteinput.h"
+#endif
+
#ifndef HAVE_GETRUSAGE
#ifdef HAVE_FTIME
#include
@@ -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 */
+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 */
+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 */
diff --git a/src/misc/tilde.c b/src/misc/tilde.c
index ece5fde70..1e72b4e27 100644
--- a/src/misc/tilde.c
+++ b/src/misc/tilde.c
@@ -1,5 +1,6 @@
/**********
Copyright 1991 Regents of the University of California. All rights reserved.
+Modified: 2002 R. Oktas,
**********/
#include
@@ -14,11 +15,30 @@ Copyright 1991 Regents of the University of California. All rights reserved.
#include
#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 */
diff --git a/src/misc/tilde.h b/src/misc/tilde.h
index 9f98faa16..54b605aee 100644
--- a/src/misc/tilde.h
+++ b/src/misc/tilde.h
@@ -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