diff --git a/ChangeLog b/ChangeLog
index 66872e1e3..003d78f53 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,9 +1,23 @@
2004-01-10 Paolo Nenzi
+ * configure.in: changed version to rework-15pre2.
+
+ * src/frontend/{com_history.c, cpitf.c, display.h, evaluate.c,
+ inpcom.c, misccoms.c, parser/glob.c, plotting/x11.c, resource.c,
+ runcoms.c, signal_handler.c, subckt.c, variable.c}
+ src/include/{ftedev.h, ngspice.h}
+ src/misc{ivars.c, Makefile.am, string.c, tilde.c, tilde.h, util.c,
+ util.h}
+ src/{main.c, nghelp.c, ngmultidec.c}
+ configure.in:
+
+ Applied Stuart's patch tclspice-0.2.14_12-03-2003.diff.gz but
+ with libreadline disabled by default. (Stuart Brorson
+ ).
+
* Fixed makefiles in src/xspice/icm and src/xspice/cmpp to make
distclean without barfing. (Stuart Brorson ).
-
* configure.in
src/xspice/cmpp/Makefile src/xspice/cmpp/Makefile.in:
Make configure automatically set paths for lex yacc and
diff --git a/configure.in b/configure.in
index 05be16cc0..3507f6f7b 100644
--- a/configure.in
+++ b/configure.in
@@ -9,7 +9,7 @@ dnl Create a configuration header
AM_CONFIG_HEADER(config.h)
dnl Initialize automake stuff
-AM_INIT_AUTOMAKE(ng-spice-rework,15pre1)
+AM_INIT_AUTOMAKE(ng-spice-rework,15pre2)
dnl --enable-ansi : try to force --ansi option to the compiler
@@ -116,6 +116,12 @@ dnl --enable-numparams: define NUMPARAMS in the code. This is for .param support
AC_ARG_ENABLE(numparam,
[ --enable-numparam Enable numparams library support, experimental *not in standard distribution*])
+dnl --with-readline: Includes GNU readline support into CLI. Default is "no".
+dnl Including readline into ngspice is a violation of GPL license. It's use
+dnl is discouraged.
+AC_ARG_WITH(readline,
+ [ --with-readline[=yes/no] Enable GNU readline support for CLI. Default=no.])
+
dnl Enable maintainer commands only if requested
AM_MAINTAINER_MODE
@@ -495,13 +501,19 @@ fi
AC_SUBST(NUMPARAMDIR)
AC_SUBST(NUMPARAMLIB)
-dnl --with-readline : the user wants to use readline library
-AC_ARG_WITH(readline,
- [ --with-readline Use the readline library. WARNING: breaks GPL license],
- AC_MSG_RESULT(Checking for readline library:)
- AC_CHECK_LIB(readline, readline, AC_DEFINE(HAVE_GNUREADLINE) LIBS="$LIBS -lreadline")
-)
-
+dnl ---- Option to include GNU readline support in ngspice CLI ----
+if test "$with_readline" != "yes"; then
+ AC_MSG_RESULT(GNU readline disabled.)
+
+else
+ AC_MSG_RESULT(Checking for readline:)
+ AC_CHECK_HEADERS([readline/readline.h readline/history.h],
+ [AC_DEFINE(HAVE_GNUREADLINE)],
+ [AC_MSG_ERROR(Couldn't find GNU readline headers.)])
+ AC_CHECK_LIB(readline, readline,
+ [LIBS="$LIBS -lreadline"],
+ [AC_MSG_ERROR(Couldn't find readline libraries.)])
+fi
AC_OUTPUT( \
Makefile \
diff --git a/src/frontend/com_history.c b/src/frontend/com_history.c
index 0fa5cb2ed..35d94ab24 100644
--- a/src/frontend/com_history.c
+++ b/src/frontend/com_history.c
@@ -353,10 +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
+#ifndef HAVE_GNUREADLINE
freehist(histlength - cp_maxhistlength);
histlength++;
-#endif
+#endif
return;
}
@@ -493,36 +493,38 @@ 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;
+ HIST_ENTRY *he;
+ int i, N;
- N = (wl == NULL) ? history_length : atoi(wl->wl_word);
+ N = (wl == NULL) ? history_length : atoi(wl->wl_word);
- if (N < 0) N = 0;
- if (N > history_length) N = history_length;
+ 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);
- }
+ 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
+#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 */
+#endif /* ifelse HAVE_GNUREADLINE */
+
return;
}
diff --git a/src/frontend/cpitf.c b/src/frontend/cpitf.c
index 50b880220..018c95cc0 100644
--- a/src/frontend/cpitf.c
+++ b/src/frontend/cpitf.c
@@ -293,7 +293,8 @@ cp_istrue(wordlist *wl)
void
cp_periodic(void)
{
- ft_setflag = ft_intrpt = FALSE;
+ ft_setflag = FALSE;
+ ft_intrpt = FALSE;
ft_ckspace();
ft_checkkids();
vec_gc();
diff --git a/src/frontend/display.h b/src/frontend/display.h
index a0a9e2d3d..a1ab5e5a1 100644
--- a/src/frontend/display.h
+++ b/src/frontend/display.h
@@ -3,9 +3,15 @@
* 1999 E. Rouat
************/
+/* See if we have been already included */
#ifndef DISPLAY_H_INCLUDED
#define DISPLAY_H_INCLUDED
+/* Include a bunch of other stuff to make display.h work */
+#include
+#include
+#include
+
DISPDEVICE *FindDev(char *name);
void DevInit(void);
int NewViewport(GRAPH *pgraph);
@@ -25,6 +31,5 @@ void SaveText(GRAPH *graph, char *text, int x, int y);
int DevSwitch(char *devname);
+#endif /* DISPLAY_H_INCLUDED */
-
-#endif
diff --git a/src/frontend/evaluate.c b/src/frontend/evaluate.c
index cf9cf0d10..5c05c3177 100644
--- a/src/frontend/evaluate.c
+++ b/src/frontend/evaluate.c
@@ -28,13 +28,13 @@ static char * mkcname(char what, char *v1, char *v2);
* be lost, but that's no great loss.
*/
-static jmp_buf matherrbuf;
+static sigjmp_buf matherrbuf;
static RETSIGTYPE
sig_matherr(void)
{
fprintf(cp_err, "Error: argument out of range for math function\n");
- longjmp(matherrbuf, 1);
+ siglongjmp(matherrbuf, 1);
}
@@ -221,7 +221,7 @@ doop(char what,
/* Some of the math routines generate SIGILL if the argument is
* out of range. Catch this here.
*/
- if (setjmp(matherrbuf)) {
+ if (sigsetjmp(matherrbuf, 1)) {
return (NULL);
}
(void) signal(SIGILL, (SIGNAL_FUNCTION) sig_matherr);
@@ -296,7 +296,7 @@ doop(char what,
tfree(c2);
}
}
-
+
/* va: garbage collection */
if (arg1->pn_value==NULL && v1!=NULL) vec_free(v1);
if (arg2->pn_value==NULL && v2!=NULL) vec_free(v2);
@@ -701,7 +701,7 @@ apply_func(struct func *func, struct pnode *arg)
/* Some of the math routines generate SIGILL if the argument is
* out of range. Catch this here.
*/
- if (setjmp(matherrbuf)) {
+ if (sigsetjmp(matherrbuf, 1)) {
(void) signal(SIGILL, SIG_DFL);
return (NULL);
}
diff --git a/src/frontend/inpcom.c b/src/frontend/inpcom.c
index 93736ebd2..aa1159bfa 100644
--- a/src/frontend/inpcom.c
+++ b/src/frontend/inpcom.c
@@ -131,11 +131,14 @@ inp_readall(FILE *fp, struct line **data)
struct line *end = NULL, *cc = NULL, *prev = NULL, *working, *newcard;
char *buffer, *s, *t, c;
/* segfault fix */
- char *copys = NULL;
+ char *copys=NULL;
int line = 1;
FILE *newfp;
-/* gtri - modify - 12/12/90 - wbk - read from mailbox if ipc enabled */
+ /* Must set this to NULL or non-tilde includes segfault. -- Tim Molteno */
+ /* copys = NULL; */ /* This caused a parse error with gcc 2.96. Why??? */
+
+/* gtri - modify - 12/12/90 - wbk - read from mailbox if ipc enabled */
#ifdef XSPICE
Ipc_Status_t ipc_status;
char ipc_buffer[1025]; /* Had better be big enough */
@@ -172,7 +175,7 @@ inp_readall(FILE *fp, struct line **data)
/* gtri - end - 12/12/90 */
#else
while ((buffer = readline(fp))) {
- #endif
+#endif
#ifdef TRACE
/* SDB debug statement */
@@ -185,12 +188,15 @@ inp_readall(FILE *fp, struct line **data)
|| (strcmp(buffer,"\r\n") == 0) ) {
continue;
}
-
+
+
if (*buffer == '@') {
tfree(buffer); /* was allocated by readline() */
break;
}
- /* loop through 'buffer' until end is reached. Then test for
+
+
+ /* loop through 'buffer' until end is reached. Then test for
premature end. If premature end is reached, spew
error and zap the line. */
for (s = buffer; *s && (*s != '\n'); s++);
@@ -201,21 +207,21 @@ inp_readall(FILE *fp, struct line **data)
if(*(s-1) == '\r') /* Zop the carriage return under windows */
*(s-1) = '\0';
-
+
/* now handle .include statements */
if (ciprefix(".include", buffer)) {
- for (s = buffer; *s && !isspace(*s); s++)/* advance past non-space chars */
+ for (s = buffer; *s && !isspace(*s); s++) /* advance past non-space chars */
;
- while (isspace(*s)) /* now advance past space chars */
+ while (isspace(*s)) /* now advance past space chars */
s++;
- if (!*s) { /* if at end of line, error */
+ if (!*s) { /* if at end of line, error */
fprintf(cp_err, "Error: .include filename missing\n");
tfree(buffer); /* was allocated by readline() */
continue;
} /* Now s points to first char after .include */
- for (t = s; *t && !isspace(*t); t++) /* now advance past non-space chars */
+ for (t = s; *t && !isspace(*t); t++) /* now advance past non-space chars */
;
- *t = '\0'; /* place \0 and end of file name in buffer */
+ *t = '\0'; /* place \0 and end of file name in buffer */
if (*s == '~') {
copys = cp_tildexpand(s); /* allocates memory, but can also return NULL */
@@ -224,8 +230,8 @@ inp_readall(FILE *fp, struct line **data)
}
}
- /* open file specified by .include statement */
- if (!(newfp = inp_pathopen(s, "r"))) {
+ /* open file specified by .include statement */
+ if (!(newfp = inp_pathopen(s, "r"))) {
perror(s);
if(copys) {
tfree(copys); /* allocated by the cp_tildexpand() above */
@@ -243,16 +249,17 @@ inp_readall(FILE *fp, struct line **data)
/* Make the .include a comment */
*buffer = '*';
+
/* now check if this is the first pass (i.e. end points to null) */
- if (end) { /* end already exists */
- end->li_next = alloc(struct line); /* create next card */
- end = end->li_next; /* make end point to next card */
+ if (end) { /* end already exists */
+ end->li_next = alloc(struct line); /* create next card */
+ end = end->li_next; /* make end point to next card */
} else {
- end = cc = alloc(struct line); /* create the deck & end. cc will
- point to beginning of deck, end to
- the end */
+ end = cc = alloc(struct line); /* create the deck & end. cc will
+ point to beginning of deck, end to
+ the end */
}
-
+
/* now fill out rest of struct end. */
end->li_next = NULL;
end->li_error = NULL;
@@ -267,28 +274,29 @@ inp_readall(FILE *fp, struct line **data)
/* Fix the buffer up a bit. */
(void) strncpy(buffer + 1, "end of:", 7);
- } /* end of .include handling */
+ } /* end of .include handling */
- /* now check if this is the first pass (i.e. end points to null) */
- if (end) { /* end already exists */
- end->li_next = alloc(struct line); /* create next card */
- end = end->li_next; /* point to next card */
- } else { /* End doesn't exist. Create it. */
- end = cc = alloc(struct line); /* note that cc points to beginning
- of deck, end to the end */
+ /* now check if this is the first pass (i.e. end points to null) */
+ if (end) { /* end already exists */
+ end->li_next = alloc(struct line); /* create next card */
+ end = end->li_next; /* point to next card */
+ } else { /* End doesn't exist. Create it. */
+ end = cc = alloc(struct line); /* note that cc points to beginning
+ of deck, end to the end */
}
-
- /* now put buffer into li */
+
+ /* now put buffer into li */
end->li_next = NULL;
end->li_error = NULL;
end->li_actual = NULL;
end->li_line = buffer;
end->li_linenum = line++;
}
+
if (!end) { /* No stuff here */
*data = NULL;
return;
- } /* end while ((buffer = readline(fp))) */
+ } /* end while ((buffer = readline(fp))) */
/* This should be freed because we are done with it. */
/* tfree(buffer); */
@@ -296,8 +304,7 @@ inp_readall(FILE *fp, struct line **data)
/* Now clean up li: remove comments & stitch together continuation lines. */
working = cc->li_next; /* cc points to head of deck. Start with the
- next card (skip title). */
-
+ next card. */
while (working) {
for (s = working->li_line; (c = *s) && c <= ' '; s++)
@@ -306,28 +313,30 @@ inp_readall(FILE *fp, struct line **data)
#ifdef TRACE
/* SDB debug statement */
printf("In inp_readall, processing linked list element s = %s . . . \n", s);
-#endif
-
+#endif
+
switch (c) {
- case '#':
+ case '#':
case '$':
case '*':
case '\0':
- /* this used to be commented out. Why? */
- /* prev = NULL; */
- working = working->li_next; /* for these chars, go to next card */
+ /* this used to be commented out. Why? */
+ /* prev = NULL; */
+ working = working->li_next; /* for these chars, go to next card */
break;
- case '+': /* handle continuation */
+
+ case '+': /* handle continuation */
if (!prev) {
working->li_error = copy(
"Illegal continuation line: ignored.");
working = working->li_next;
break;
}
-
+
/* create buffer and write last and current line into it. */
buffer = tmalloc(strlen(prev->li_line) + strlen(s) + 2);
- (void) sprintf(buffer, "%s %s", prev->li_line, s + 1);
+ (void) sprintf(buffer, "%s %s", prev->li_line, s + 1);
+
s = prev->li_line;
prev->li_line = buffer;
prev->li_next = working->li_next;
@@ -349,7 +358,8 @@ inp_readall(FILE *fp, struct line **data)
}
working = prev->li_next;
break;
- default: /* regular one-line card */
+
+ default: /* regular one-line card */
prev = working;
working = working->li_next;
break;
@@ -360,7 +370,6 @@ inp_readall(FILE *fp, struct line **data)
return;
}
-
/*-------------------------------------------------------------------------*
* *
*-------------------------------------------------------------------------*/
diff --git a/src/frontend/misccoms.c b/src/frontend/misccoms.c
index de3e16d9c..039e737e5 100644
--- a/src/frontend/misccoms.c
+++ b/src/frontend/misccoms.c
@@ -15,12 +15,10 @@ 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);
@@ -77,8 +75,9 @@ com_quit(wordlist *wl)
clearerr(stdin);
*buf = 'y';
}
- if ((*buf == 'y') || (*buf == 'Y') || (*buf == '\n'))
+ if ((*buf == 'y') || (*buf == 'Y') || (*buf == '\n')) {
byemesg();
+ }
else {
return;
}
@@ -86,14 +85,9 @@ 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);
+
}
@@ -235,6 +229,18 @@ com_version(wordlist *wl)
static void
byemesg(void)
{
+
+#ifdef HAVE_GNUREADLINE
+ extern char gnu_history_file[];
+
+ /* write out command history only when saying goodbye. */
+ if (cp_interactive && (cp_maxhistlength > 0)) {
+ stifle_history(cp_maxhistlength);
+ write_history(gnu_history_file);
+ }
+#endif /* HAVE_GNUREADLINE */
+
printf("%s-%s done\n", ft_sim->simulator, ft_sim->version);
return;
}
+
diff --git a/src/frontend/parser/glob.c b/src/frontend/parser/glob.c
index 7a46c3bda..9c366bf47 100644
--- a/src/frontend/parser/glob.c
+++ b/src/frontend/parser/glob.c
@@ -72,11 +72,8 @@ 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 8f337fcad..af277922e 100644
--- a/src/frontend/plotting/x11.c
+++ b/src/frontend/plotting/x11.c
@@ -796,6 +796,7 @@ zoomin(GRAPH *graph)
wl = cp_parse(buf);
(void) cp_addhistent(cp_event++, wl);
}
+
#endif /* HAVE_GNUREADLINE */
(void) cp_evloop(buf);
diff --git a/src/frontend/resource.c b/src/frontend/resource.c
index a18e75fe1..3a2a949a6 100644
--- a/src/frontend/resource.c
+++ b/src/frontend/resource.c
@@ -386,13 +386,13 @@ printres(char *name)
#define LOG2_PAGESIZE 8
-static jmp_buf env;
+static sigjmp_buf env;
static RETSIGTYPE
fault(void)
{
signal(SIGSEGV, (SIGNAL_FUNCTION) fault); /* SysV style */
- longjmp(env, 1);
+ siglongjmp(env, 1);
}
static void *
@@ -425,13 +425,13 @@ baseaddr(void)
break;
}
- if (setjmp(env)) {
+ if (sigsetjmp(env, 1)) {
low = at;
continue;
} else
x = *at;
- if (setjmp(env)) {
+ if (sigsetjmp(env, 1)) {
low = at;
continue;
} else
diff --git a/src/frontend/runcoms.c b/src/frontend/runcoms.c
index 97f801949..7b9d4dfcf 100644
--- a/src/frontend/runcoms.c
+++ b/src/frontend/runcoms.c
@@ -203,11 +203,11 @@ dosim(char *what, wordlist *wl)
ct->ci_inprogress = FALSE;
}
if (ft_curckt->ci_inprogress && eq(what, "resume")) {
- ft_setflag = TRUE;
+ ft_setflag = TRUE; /* don't allow abort upon interrupt during run */
ft_intrpt = FALSE;
fprintf(cp_err, "Warning: resuming run in progress.\n");
com_resume((wordlist *) NULL);
- ft_setflag = FALSE;
+ ft_setflag = FALSE; /* Now allow aborts again */
return 0;
}
@@ -215,7 +215,7 @@ dosim(char *what, wordlist *wl)
* set a flag and let spice finish up, then control will be
* passed back to the user.
*/
- ft_setflag = TRUE;
+ ft_setflag = TRUE; /* Don't allow abort upon interrupt during run. */
ft_intrpt = FALSE;
if (dofile) {
#ifdef PARALLEL_ARCH
@@ -245,9 +245,9 @@ dosim(char *what, wordlist *wl)
#else
else if (!(rawfileFp = fopen(wl->wl_word, "w"))) {
setvbuf(rawfileFp, rawfileBuf, _IOFBF, RAWBUF_SIZE);
- perror(wl->wl_word);
- ft_setflag = FALSE;
- return 1;
+ perror(wl->wl_word);
+ ft_setflag = FALSE;
+ return 1;
}
#endif /* __MINGW32__ */
rawfileBinary = !ascii;
@@ -261,14 +261,14 @@ dosim(char *what, wordlist *wl)
}
/*save rawfile name saj*/
if(last_used_rawfile)
- tfree(last_used_rawfile); /* va: we should allways use tfree */
+ tfree(last_used_rawfile);
if(rawfileFp){
last_used_rawfile = copy(wl->wl_word);
}else {
last_used_rawfile = NULL;
}
/*end saj*/
-
+
/* Spice calls wrd_init and wrd_end itself */
ft_curckt->ci_inprogress = TRUE;
if (eq(what,"sens2")) {
@@ -282,7 +282,7 @@ dosim(char *what, wordlist *wl)
if(g_ipc.enabled)
ipc_send_errchk();
/* gtri - end - 12/12/90 */
-#endif
+#endif
} else
ft_curckt->ci_inprogress = FALSE;
} else {
@@ -296,7 +296,7 @@ dosim(char *what, wordlist *wl)
if(g_ipc.enabled)
ipc_send_errchk();
/* gtri - end - 12/12/90 */
-#endif
+#endif
err = 0;
} else if (err == 2) {
fprintf(cp_err, "%s simulation(s) aborted\n", what);
@@ -322,7 +322,7 @@ dosim(char *what, wordlist *wl)
if (wl)
wl->wl_prev = NULL;
tfree(ww);
- }
+ }
return err;
}
diff --git a/src/frontend/signal_handler.c b/src/frontend/signal_handler.c
index 37a2a7a56..adaac68ce 100644
--- a/src/frontend/signal_handler.c
+++ b/src/frontend/signal_handler.c
@@ -18,10 +18,15 @@ Author: 1985 Wayne A. Christopher, U. C. Berkeley CAD Group
#include
#include "signal_handler.h"
+#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
-
-
-extern jmp_buf jbuf;
+extern sigjmp_buf jbuf;
/* The (void) signal handlers... SIGINT is the only one that gets reset (by
* cshpar) so it is global. They are ifdef BSD because of the sigmask
@@ -32,32 +37,45 @@ extern jmp_buf jbuf;
extern pid_t getpid (void);
-/* not using SIGINT with GNU Readline - AV */
-#ifndef HAVE_GNUREADLINE
+/* invoke this function upon keyboard interrupt */
RETSIGTYPE
ft_sigintr(void)
{
+ /* fprintf (cp_err, "Received interrupt. Handling it . . . . .\n"); */
- gr_clean();
+ /* Reinstall ft_signintr as the signal handler. */
+ (void) signal( SIGINT, (SIGNAL_FUNCTION) ft_sigintr );
- (void) signal( SIGINT, (SIGNAL_FUNCTION) ft_sigintr );
+ gr_clean(); /* Clean up plot window */
- if (ft_intrpt)
- fprintf(cp_err, "Interrupt (ouch)\n");
+ if (ft_intrpt) /* check to see if we're being interrupted repeatedly */
+ fprintf(cp_err, "Interrupted again (ouch)\n");
else {
- fprintf(cp_err, "Interrupt\n");
+ fprintf(cp_err, "Interrupted once . . .\n");
ft_intrpt = TRUE;
}
- if (ft_setflag)
- return;
-/* To restore screen after an interrupt to a plot for instance
- */
+ if (ft_setflag) {
+ return; /* just return without aborting simulation if ft_setflag = TRUE */
+ }
+
+#ifdef HAVE_GNUREADLINE
+ /* Clean up readline after catching signals */
+ /* One or all of these might be supurfluous */
+ (void) rl_free_line_state();
+ (void) rl_cleanup_after_signal();
+ (void) rl_reset_after_signal();
+#endif
+
+ /* To restore screen after an interrupt to a plot for instance */
cp_interactive = TRUE;
- cp_resetcontrol();
- longjmp(jbuf, 1);
+ cp_resetcontrol();
+
+ /* here we jump to the start of command processing in main() after resetting everything. */
+ siglongjmp(jbuf, 1);
+
}
-#endif /* !HAVE_GNUREADLINE */
+
RETSIGTYPE
sigfloat(int sig, int code)
@@ -66,7 +84,7 @@ sigfloat(int sig, int code)
fperror("Error", code);
rewind(cp_out);
(void) signal( SIGFPE, (SIGNAL_FUNCTION) sigfloat );
- longjmp(jbuf, 1);
+ siglongjmp(jbuf, 1);
}
/* This should give a new prompt if cshpar is waiting for input. */
@@ -88,7 +106,7 @@ sigcont(void)
{
(void) signal(SIGTSTP, (SIGNAL_FUNCTION) sigstop);
if (cp_cwait)
- longjmp(jbuf, 1);
+ siglongjmp(jbuf, 1);
}
# endif
diff --git a/src/frontend/subckt.c b/src/frontend/subckt.c
index 69ed615a5..04c74cc66 100644
--- a/src/frontend/subckt.c
+++ b/src/frontend/subckt.c
@@ -168,6 +168,10 @@ inp_subcktexpand(struct line *deck)
*/
for (c = deck; c; c = c->li_next) { /* iterate on lines in deck */
if (prefix(start, c->li_line)) { /* if we find .subckt . . . */
+#ifdef TRACE
+ /* SDB debug statement */
+ printf("In inp_subcktexpand, found a .subckt: %s\n", c->li_line);
+#endif
for (s = c->li_line; *s && (*s != '('); s++) /* Iterate charwise along line until ( is found */
;
if (*s) {
@@ -200,6 +204,10 @@ inp_subcktexpand(struct line *deck)
/* doit does the actual splicing in of the .subckt . . . */
+#ifdef TRACE
+ /* SDB debug statement */
+ printf("In inp_subcktexpand, about to call doit.\n");
+#endif
ll = doit(deck);
/* Now check to see if there are still subckt instances undefined... */
@@ -259,6 +267,11 @@ doit(struct line *deck)
subs = NULL;
submod = NULL;
+#ifdef TRACE
+ /* SDB debug statement */
+ printf("In doit, about to start first pass through deck.\n");
+#endif
+
/* First pass: xtract all the .subckts and stick pointers to them into sss. */
for (last = deck, lc = NULL; last; ) {
if (prefix(sbend, last->li_line)) { /* if line == .ends */
@@ -383,6 +396,11 @@ doit(struct line *deck)
wl->wl_word = gettok(&s); /* wl->wl_word now holds name of model */
}
+#ifdef TRACE
+ /* SDB debug statement */
+ printf("In doit, about to start second pass through deck.\n");
+#endif
+
error = 0;
/* Second pass: do the replacements. */
do { /* while (!error && numpasses-- && gotone) */
@@ -444,8 +462,8 @@ doit(struct line *deck)
lcc = inp_deckcopy(sss->su_def);
/* Change the names of .models found in .subckts . . . */
- if (modtranslate(lcc, scname))
- devmodtranslate(lcc, scname);
+ if (modtranslate(lcc, scname)) /* this translates the model name in the .model line */
+ devmodtranslate(lcc, scname); /* This translates the model name on all components in the deck */
s = sss->su_args;
txfree(gettok(&t)); /* Throw out the subcircuit refdes */
@@ -735,7 +753,7 @@ translate(struct line *deck, char *formal, char *actual, char *scname, char *sub
nnodes = numnodes(c->li_line);
while (nnodes-- > 0) {
- name = gettok(&s);
+ name = gettok_node(&s);
if (name == NULL) {
fprintf(cp_err, "Error: too few nodes: %s\n",
c->li_line);
@@ -770,12 +788,12 @@ translate(struct line *deck, char *formal, char *actual, char *scname, char *sub
printf("In translate, looking at e, f, g, h found poly\n");
#endif
- /* move pointer ahead of paren */
+ /* move pointer ahead of ( */
if( get_l_paren(&s) == 1 ) {
- fprintf(cp_err, "Error: no left paren after POLY %s\n",
- c->li_line);
- tfree(next_name);
- goto quit;
+ fprintf(cp_err, "Error: no left paren after POLY %s\n",
+ c->li_line);
+ tfree(next_name);
+ goto quit;
}
nametofree = gettok_noparens(&s);
@@ -784,10 +802,10 @@ translate(struct line *deck, char *formal, char *actual, char *scname, char *sub
/* move pointer ahead of ) */
if( get_r_paren(&s) == 1 ) {
- fprintf(cp_err, "Error: no right paren after POLY %s\n",
- c->li_line);
- tfree(next_name);
- goto quit;
+ fprintf(cp_err, "Error: no right paren after POLY %s\n",
+ c->li_line);
+ tfree(next_name);
+ goto quit;
}
/* Write POLY(dim) into buffer */
@@ -803,7 +821,7 @@ translate(struct line *deck, char *formal, char *actual, char *scname, char *sub
/* Now translate the controlling source/nodes */
nnodes = dim * numdevs(c->li_line);
while (nnodes-- > 0) {
- nametofree = name = gettok(&s); /* name points to the returned token */
+ nametofree = name = gettok_node(&s); /* name points to the returned token */
if (name == NULL) {
fprintf(cp_err, "Error: too few devs: %s\n",
c->li_line);
@@ -863,7 +881,7 @@ translate(struct line *deck, char *formal, char *actual, char *scname, char *sub
/*================= Default case ===================*/
default: /* this section handles ordinary components */
s = c->li_line;
- nametofree = name = gettok(&s);
+ nametofree = name = gettok_node(&s); /* changed to gettok_node to handle netlists with ( , ) */
if (!name)
continue;
if (!*name) {
@@ -892,7 +910,7 @@ translate(struct line *deck, char *formal, char *actual, char *scname, char *sub
nnodes = numnodes(c->li_line);
while (nnodes-- > 0) {
- name = gettok(&s);
+ name = gettok_node(&s);
if (name == NULL) {
fprintf(cp_err, "Error: too few nodes: %s\n",
c->li_line);
@@ -920,7 +938,7 @@ translate(struct line *deck, char *formal, char *actual, char *scname, char *sub
*/
nnodes = numdevs(c->li_line);
while (nnodes-- > 0) {
- t = name = gettok(&s);
+ t = name = gettok_node(&s);
if (name == NULL) {
fprintf(cp_err, "Error: too few devs: %s\n",
c->li_line);
@@ -1192,9 +1210,9 @@ numnodes(char *name)
i = 0;
s = buf;
gotit = 0;
- txfree(gettok(&s)); /* Skip component name */
+ txfree(gettok(&s)); /* Skip component name */
while ((i < n) && (*s) && !gotit) {
- t = gettok(&s);
+ t = gettok_node(&s); /* get nodenames . . . */
for (wl = modnames; wl; wl = wl->wl_next)
if (eq(t, wl->wl_word))
gotit = 1;
@@ -1332,8 +1350,11 @@ modtranslate(struct line *deck, char *subname)
/*-------------------------------------------------------------------*
- * Devmodtranslate translates ??????
- *
+ * Devmodtranslate scans through the deck, and translates the
+ * name of the model in a line held in a .subckt. For example:
+ * before: .subckt U1 . . . .
+ * Q1 c b e 2N3904
+ * after: Q1 c b e U1:2N3904
*-------------------------------------------------------------------*/
static void
devmodtranslate(struct line *deck, char *subname)
@@ -1345,9 +1366,14 @@ devmodtranslate(struct line *deck, char *subname)
for (s = deck; s; s = s->li_next) {
t = s->li_line;
+#ifdef TRACE
+ /* SDB debug stuff */
+ printf("In devmodtranslate, examining line %s.\n", t);
+#endif
+
while (*t && isspace(*t))
t++;
- c = isupper(*t) ? tolower(*t) : *t;
+ c = isupper(*t) ? tolower(*t) : *t; /* set c to first char in line. . . . */
found = FALSE;
buffer = tmalloc(strlen(t) + strlen(subname) + 4);
@@ -1355,17 +1381,17 @@ devmodtranslate(struct line *deck, char *subname)
case 'r':
case 'c':
- name = gettok(&t);
+ name = gettok(&t); /* get refdes */
(void) sprintf(buffer,"%s ",name);
tfree(name);
- name = gettok(&t);
+ name = gettok_node(&t); /* get first netname */
(void) sprintf(buffer + strlen(buffer), "%s ", name);
tfree(name);
- name = gettok(&t);
+ name = gettok_node(&t); /* get second netname */
(void) sprintf(buffer + strlen(buffer), "%s ", name);
tfree(name);
- if (*t) {
+ if (*t) { /* if there is a model, process it. . . . */
name = gettok(&t);
/* Now, is this a subcircuit model? */
for (wlsub = submod; wlsub; wlsub = wlsub->wl_next) {
@@ -1404,13 +1430,13 @@ devmodtranslate(struct line *deck, char *subname)
break;
case 'd':
- name = gettok(&t);
+ name = gettok(&t); /* get refdes */
(void) sprintf(buffer,"%s ",name);
tfree(name);
- name = gettok(&t);
+ name = gettok_node(&t); /* get first attached netname */
(void) sprintf(buffer + strlen(buffer), "%s ", name);
tfree(name);
- name = gettok(&t);
+ name = gettok_node(&t); /* get second attached netname */
(void) sprintf(buffer + strlen(buffer), "%s ", name);
tfree(name);
name = gettok(&t);
@@ -1437,6 +1463,10 @@ devmodtranslate(struct line *deck, char *subname)
case 'u':
case 'j':
case 'z':
+ /* What are these devices anyway? J = JFET, W = trans line (?),
+ and u = IC, but what is Z?.
+ Also, why is 'U' here? A 'U' element can have an arbitrary
+ number of nodes attached. . . . -- SDB. */
name = gettok(&t);
(void) sprintf(buffer,"%s ",name);
name = gettok(&t);
@@ -1464,22 +1494,26 @@ devmodtranslate(struct line *deck, char *subname)
s->li_line = buffer;
break;
- case 'o':
+ /* Changed gettok() to gettok_node() on 12.2.2003 by SDB
+ to enable parsing lines like "S1 10 11 (80,51) SLATCH1"
+ which occurr in real Analog Devices SPICE models.
+ */
+ case 'o': /* what is this element? -- SDB */
case 's':
case 'm':
- name = gettok(&t);
+ name = gettok(&t); /* get refdes */
(void) sprintf(buffer,"%s ",name);
tfree(name);
- name = gettok(&t);
+ name = gettok_node(&t); /* get first attached netname */
(void) sprintf(buffer + strlen(buffer), "%s ", name);
tfree(name);
- name = gettok(&t);
+ name = gettok_node(&t); /* get second attached netname */
(void) sprintf(buffer + strlen(buffer), "%s ", name);
tfree(name);
- name = gettok(&t);
+ name = gettok_node(&t); /* get third attached netname */
(void) sprintf(buffer + strlen(buffer), "%s ", name);
tfree(name);
- name = gettok(&t);
+ name = gettok_node(&t); /* get fourth attached netname */
(void) sprintf(buffer + strlen(buffer), "%s ", name);
tfree(name);
name = gettok(&t);
@@ -1503,19 +1537,19 @@ devmodtranslate(struct line *deck, char *subname)
break;
case 'q':
- name = gettok(&t);
+ name = gettok(&t); /* get refdes */
(void) sprintf(buffer,"%s ",name);
tfree(name);
- name = gettok(&t);
+ name = gettok_node(&t); /* get first attached netname */
(void) sprintf(buffer + strlen(buffer), "%s ", name);
tfree(name);
- name = gettok(&t);
+ name = gettok_node(&t); /* get second attached netname */
(void) sprintf(buffer + strlen(buffer), "%s ", name);
tfree(name);
- name = gettok(&t);
+ name = gettok_node(&t); /* get third attached netname */
(void) sprintf(buffer + strlen(buffer), "%s ", name);
tfree(name);
- name = gettok(&t);
+ name = gettok_node(&t); /* this can be either a model name or a node name. */
/* Now, is this a subcircuit model? */
for (wlsub = submod; wlsub; wlsub = wlsub->wl_next) {
diff --git a/src/frontend/variable.c b/src/frontend/variable.c
index 706bd504a..ea7a813e8 100644
--- a/src/frontend/variable.c
+++ b/src/frontend/variable.c
@@ -157,7 +157,7 @@ cp_vset(char *varname, char type, char *value)
cp_maxhistlength = v->va_real;
else if (eq(copyvarname, "noclobber"))
cp_noclobber = TRUE;
- else if (eq(varname, "echo")) /*CDHW*/
+ else if (eq(varname, "echo")) /*CDHW*/
cp_echo = TRUE; /*CDHW*/
else if (eq(copyvarname, "prompt") && (type == VT_STRING))
cp_promptstring = copy(v->va_string);
@@ -208,10 +208,12 @@ cp_vset(char *varname, char type, char *value)
alreadythere = FALSE;
if (ft_curckt) {
for (u = ft_curckt->ci_vars; u; u = u->va_next)
+ {
if (eq(copyvarname, u->va_name)) {
alreadythere = TRUE;
break;
}
+ }
if (!alreadythere) {
v->va_next = ft_curckt->ci_vars;
ft_curckt->ci_vars = v;
@@ -225,7 +227,7 @@ cp_vset(char *varname, char type, char *value)
/* va_next left unchanged */
tfree(v->va_name);
tfree(v);
-/* va: old version with memory leaks
+/* va: old version with memory leaks
w = u->va_next;
bcopy(v, u, sizeof(*u));
u->va_next = w;
@@ -291,9 +293,7 @@ cp_setparse(wordlist *wl)
*s = '\0';
if (*val == '\0') {
if (!wl) {
- fprintf(cp_err,
- "Error: %s equals what?.\n",
- name);
+ fprintf(cp_err, "Error: %s equals what?.\n", name);
tfree(name);/*DG: cp_unquote Memory leak: free name before exiting*/
return (NULL);
} else {
@@ -343,7 +343,7 @@ cp_setparse(wordlist *wl)
}
if (balance && !wl) {
fprintf(cp_err, "Error: bad set form.\n");
- tfree(name); /* va: cp_unquote memory leak: free name before exiting */
+ tfree(name); /* va: cp_unquote memory leak: free name before exiting */
return (NULL);
}
@@ -373,7 +373,7 @@ cp_setparse(wordlist *wl)
vv->va_string = copy(val);
}
tfree(copyval);/*DG: must free ss any way to avoid cp_unquote memory leak */
- tfree(name); /* va: cp_unquote memory leak: free name for every loop */
+ tfree(name); /* va: cp_unquote memory leak: free name for every loop */
}
if(name)
tfree(name);
@@ -485,6 +485,11 @@ cp_getvar(char *name, int type, void *retval)
{
struct variable *v;
+#ifdef TRACE
+ /* SDB debug statement */
+ printf("in cp_getvar, trying to get value of variable %s.\n", name);
+#endif
+
for (v = variables; v; v = v->va_next)
if (eq(name, v->va_name))
break;
diff --git a/src/include/ftedev.h b/src/include/ftedev.h
index 1d4d9bd00..12385b225 100644
--- a/src/include/ftedev.h
+++ b/src/include/ftedev.h
@@ -9,6 +9,10 @@ Author: 1987 Jeffrey M. Hsu
The display device structure.
*/
+#ifndef FTEDEV_H_INCLUDED
+#define FTEDEV_H_INCLUDED
+
+
typedef struct {
char *name;
int minx, miny;
@@ -35,3 +39,6 @@ typedef struct {
} DISPDEVICE;
extern DISPDEVICE *dispdev;
+
+
+#endif
diff --git a/src/include/ngspice.h b/src/include/ngspice.h
index e5f1aa11c..b83e5894a 100644
--- a/src/include/ngspice.h
+++ b/src/include/ngspice.h
@@ -127,6 +127,7 @@ struct timeb timebegin;
extern char *gettok(char **s);
extern char *gettok_noparens(char **s);
+extern char *gettok_node(char **s);
extern int get_l_paren(char **s);
extern int get_r_paren(char **s);
extern void appendc(char *s, char c);
@@ -134,11 +135,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 *canonicalize_pathname(char *path);
+extern char *absolute_pathname(char *string, char *dot_path);
+
extern char *smktemp(char *id);
extern char *copy(char *str);
diff --git a/src/main.c b/src/main.c
index 5a640034d..5c7190fec 100644
--- a/src/main.c
+++ b/src/main.c
@@ -5,7 +5,7 @@
Author: 1985 Wayne A. Christopher
The main routine for ngspice */
-
+
#include
#include
@@ -30,7 +30,7 @@
#include
#include
#include
-//#include "frontend/display.h" /* va */
+#include /* added by SDB to pick up Input() fcn */
/* saj xspice headers */
#ifdef XSPICE
@@ -49,7 +49,10 @@
#include
#include
#include "fteinput.h"
-#endif
+
+char gnu_history_file[512];
+static char *application_name;
+#endif /* HAVE_GNUREADLINE */
#ifndef HAVE_GETRUSAGE
#ifdef HAVE_FTIME
@@ -68,8 +71,8 @@ static bool ft_servermode = FALSE;
static bool ft_batchmode = FALSE;
/* Frontend options */
-bool ft_intrpt = FALSE; /* Set by the (void) signal handlers. */
-bool ft_setflag = FALSE; /* Don't abort after an interrupt. */
+bool ft_intrpt = FALSE; /* Set by the (void) signal handlers. TRUE = we've been interrupted. */
+bool ft_setflag = FALSE; /* TRUE = Don't abort simulation after an interrupt. */
char *ft_rawfile = "rawspice.raw";
#ifdef HAVE_GNUREADLINE
@@ -144,7 +147,7 @@ struct variable *(*if_getparam)( );
-jmp_buf jbuf;
+sigjmp_buf jbuf;
static int started = FALSE;
@@ -171,56 +174,67 @@ extern struct comm nutcp_coms[ ];
struct comm *cp_coms = nutcp_coms;
static IFfrontEnd nutmeginfo;
+/* -------------------------------------------------------------------------- */
int
if_run(char *t, char *w, wordlist *s, char *b)
{
return (0);
}
+/* -------------------------------------------------------------------------- */
int
if_sens_run(char *t, char *w, wordlist *s, char *b)
{
return (0);
}
+/* -------------------------------------------------------------------------- */
void
if_dump(char *ckt, FILE *fp)
{}
+/* -------------------------------------------------------------------------- */
char *
if_inpdeck(struct line *deck, char **tab)
{
return ((char *) 0);
}
+/* -------------------------------------------------------------------------- */
int
if_option(char *ckt, char *name, int type, char *value)
{
return 0;
}
+/* -------------------------------------------------------------------------- */
void if_cktfree(char *ckt, char *tab)
{}
+/* -------------------------------------------------------------------------- */
void if_setndnames(char *line)
{}
+/* -------------------------------------------------------------------------- */
char *
if_errstring(int code)
{
return ("spice error");
}
+/* -------------------------------------------------------------------------- */
void
if_setparam(char *ckt, char *name, char *param, struct variable *val)
{}
+/* -------------------------------------------------------------------------- */
bool
if_tranparams(struct circ *ckt, double *start, double *stop, double *step)
{
return (FALSE);
}
+/* -------------------------------------------------------------------------- */
struct variable *
if_getstat(char *n, char *c)
{
@@ -237,7 +251,7 @@ void com_savesnap(wordlist *wl) { return; }
#ifndef SIMULATOR
#ifdef XSPICE
-/* saj,dw to get nutmeg to compile, not nice but necessary */
+/* saj to get nutmeg to compile, not nice but necessary */
Ipc_Tiein_t g_ipc;
Ipc_Status_t ipc_send_errchk(void ) {
Ipc_Status_t x=0;
@@ -278,7 +292,7 @@ double CONSTe;
IFfrontEnd *SPfrontEnd = NULL;
int DEVmaxnum = 0;
-
+/* -------------------------------------------------------------------------- */
int SIMinit(IFfrontEnd *frontEnd, IFsimulator **simulator)
{
#ifdef SIMULATOR
@@ -307,6 +321,7 @@ int SIMinit(IFfrontEnd *frontEnd, IFsimulator **simulator)
}
+/* -------------------------------------------------------------------------- */
/* Shutdown gracefully. */
int
shutdown(int exitval)
@@ -322,6 +337,8 @@ shutdown(int exitval)
exit (exitval);
}
+/* -------------------------------------------------------------------------- */
+
#ifdef HAVE_GNUREADLINE
/* Adapted ../lib/cp/lexical.c:prompt() for GNU Readline -- Andrew Veliath */
static char *
@@ -340,15 +357,15 @@ prompt()
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;
+ 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++;
}
@@ -356,55 +373,51 @@ prompt()
return pbuf;
}
+/* -------------------------------------------------------------------------- */
/* Process device events in Readline's hook since there is no where
else to do it now - AV */
-int rl_event_func()
+int rl_event_func()
+/* called by GNU readline periodically to know what to do about keypresses */
{
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;
-
+ /* note that we want some mechanism to detect ctrl-D and expand it to exit */
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_set_pos(history_length);
+
+ sigsetjmp(jbuf, 1); /* Set location to jump to after handling SIGINT (ctrl-C) */
+
+ 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)
{
@@ -426,6 +439,7 @@ show_help(void)
"Report bugs to %s.\n", cp_program, Bug_Addr);
}
+/* -------------------------------------------------------------------------- */
void
show_version(void)
{
@@ -438,6 +452,7 @@ show_version(void)
" The NGSpice Project\n", cp_program, PACKAGE, VERSION);
}
+/* -------------------------------------------------------------------------- */
void
append_to_stream(FILE *dest, FILE *source)
{
@@ -500,6 +515,8 @@ main(int argc, char **argv)
FILE *fp;
FILE *circuit_file;
+
+
#ifdef TRACE
/* this is used to detect memory leaks during debugging */
/* added by SDB during debug . . . . */
@@ -524,8 +541,8 @@ main(int argc, char **argv)
application_name = argv[0];
else
++application_name;
-#endif
-
+#endif /* HAVE_GNUREADLINE */
+
#ifdef PARALLEL_ARCH
PBEGIN_(argc, argv);
ARCHme = NODEID_();
@@ -553,8 +570,7 @@ main(int argc, char **argv)
#ifdef MALLOCTRACE
mallocTraceInit("malloc.out");
#endif
-
-#if defined (HAVE_ISATTY) && !defined(HAS_WINDOWS)
+#if defined(HAVE_ISATTY) && !defined(HAS_WINDOWS)
istty = (bool) isatty(fileno(stdin));
#endif
@@ -571,7 +587,7 @@ main(int argc, char **argv)
srandom(getpid());
-
+ /* --- Process command line options --- */
while (1) {
int option_index = 0;
static struct option long_options[] = {
@@ -681,7 +697,7 @@ main(int argc, char **argv)
default:
printf ("?? getopt returned character code 0%o ??\n", c);
}
- }
+ } /* --- End of command line option processing --- */
#ifdef SIMULATOR
@@ -712,7 +728,7 @@ main(int argc, char **argv)
ft_cpinit();
/* To catch interrupts during .spiceinit... */
- if (setjmp(jbuf) == 1) {
+ if (sigsetjmp(jbuf, 1) == 1) {
fprintf(cp_err, "Warning: error executing .spiceinit.\n");
if (!ft_batchmode)
goto bot;
@@ -720,13 +736,13 @@ main(int argc, char **argv)
/* Set up signal handling */
if (!ft_batchmode) {
+ /* Set up interrupt handler */
+ (void) signal(SIGINT, ft_sigintr);
-#ifndef HAVE_GNUREADLINE
- signal(SIGINT, ft_sigintr);
-#endif
+ /* floating point exception */
+ (void) signal(SIGFPE, sigfloat);
- signal(SIGFPE, sigfloat);
-#if defined(SIGTSTP) // && !defined(__MINGW32__)
+#ifdef SIGTSTP
signal(SIGTSTP, sigstop);
#endif
}
@@ -761,9 +777,9 @@ main(int argc, char **argv)
#define INITSTR "/.spiceinit"
#ifdef HAVE_ASPRINTF
asprintf(&s, "%s%s", pw->pw_dir,INITSTR);
-#else /* ~ HAVE_ASPRINTF */ /* va: we use tmalloc */
- s=(char *) tmalloc(1 + strlen(pw->pw_dir)+strlen(INITSTR));
- sprintf(s,"%s%s",pw->pw_dir,INITSTR);
+#else /* ~ HAVE_ASPRINTF */
+ s=(char *) tmalloc(1 + strlen(pw->pw_dir)+strlen(INITSTR));
+ sprintf(s,"%s%s",pw->pw_dir,INITSTR);
#endif /* HAVE_ASPRINTF */
if (access(s, 0) == 0)
@@ -800,7 +816,7 @@ bot:
* build a circuit for this file. If this is in server mode, don't
* process any of these args. */
- if (setjmp(jbuf) == 1)
+ if (sigsetjmp(jbuf, 1) == 1)
goto evl;
@@ -846,7 +862,7 @@ bot:
}
if (ft_batchmode && err)
shutdown(EXIT_BAD);
- }
+ } /* --- if (!ft_servermode && !ft_nutmeg) --- */
if (!gotone && ft_batchmode && !ft_nutmeg)
inp_spsource(circuit_file, FALSE, (char *) NULL);
@@ -857,7 +873,8 @@ evl:
* so exit. */
bool st = FALSE;
- (void) setjmp(jbuf);
+ (void) sigsetjmp(jbuf, 1);
+
if (st == TRUE) {
shutdown(EXIT_BAD);
@@ -878,7 +895,7 @@ evl:
* save too much. */
cp_interactive = FALSE;
if (rflag) {
- /* saj done already in inp_spsource ft_dotsaves();*/
+ /* saj done already in inp_spsource ft_dotsaves();*/
error2 = ft_dorun(ft_rawfile);
if (ft_cktcoms(TRUE) || error2)
shutdown(EXIT_BAD);
@@ -892,15 +909,34 @@ evl:
"no simulations run\n");
shutdown(EXIT_BAD);
}
- } else {
- (void) setjmp(jbuf);
+ } /* --- if (ft_batchmode) --- */
+ else {
cp_interactive = TRUE;
+
#ifdef HAVE_GNUREADLINE
- app_rl_readlines();
-#else
+ /* --- set up readline params --- */
+ 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;
+ rl_catch_signals = 0; /* disable readline signal handling */
+ rl_catch_sigwinch = 1; /* allow readline to respond to resized windows */
+
+ /* Here's where we enter the command processing loop */
+ app_rl_readlines();
+#else
while (cp_evloop((char *) NULL) == 1) ;
-#endif /* ifelse HAVE_GNUREADLINE */
- }
+#endif /* ifelse HAVE_GNUREADLINE */
+
+ } /* --- else (if (ft_batchmode)) --- */
#else /* ~ SIMULATOR */
@@ -915,16 +951,16 @@ evl:
evl:
/* Nutmeg "main" */
- (void) setjmp(jbuf);
+ (void) sigsetjmp(jbuf, 1);
cp_interactive = TRUE;
-#ifdef HAVE_GNUREADLINE
- app_rl_readlines();
-#else
while (cp_evloop((char *) NULL) == 1) ;
-#endif /* ifelse HAVE_GNUREADLINE */
#endif /* ~ SIMULATOR */
shutdown(EXIT_NORMAL);
return EXIT_NORMAL;
}
+
+
+
+
diff --git a/src/misc/Makefile.am b/src/misc/Makefile.am
index 2477d316d..6d355cd45 100644
--- a/src/misc/Makefile.am
+++ b/src/misc/Makefile.am
@@ -27,7 +27,9 @@ libmisc_a_SOURCES = \
tilde.h \
misc_time.c \
misc_time.h \
- wlist.c
+ wlist.c \
+ util.c \
+ util.h
## Note that the getopt files get compiled unconditionnaly but some
## magic #define away the body of their own code if the compilation environment
diff --git a/src/misc/ivars.c b/src/misc/ivars.c
index e6fc50d6a..caa20de82 100644
--- a/src/misc/ivars.c
+++ b/src/misc/ivars.c
@@ -40,7 +40,7 @@ mkvar(char **p, char *path_prefix, char *var_dir, char *env_var)
asprintf(p, "%s", buffer);
else
asprintf(p, "%s%s%s", path_prefix, DIR_PATHSEP, var_dir);
-#else /* ~ HAVE_ASPRINTF */ /* va: we use tmalloc */
+#else /* ~ HAVE_ASPRINTF */
if (buffer){
*p = (char *) tmalloc(strlen(buffer)+1);
sprintf(*p,"%s",buffer);
@@ -48,7 +48,7 @@ mkvar(char **p, char *path_prefix, char *var_dir, char *env_var)
}
else{
*p = (char *) tmalloc(strlen(path_prefix) +
- strlen(DIR_PATHSEP) + strlen(var_dir) + 1);
+ strlen(DIR_PATHSEP) + strlen(var_dir) + 1);
sprintf(*p, "%s%s%s", path_prefix, DIR_PATHSEP, var_dir);
/* asprintf(p, "%s%s%s", path_prefix, DIR_PATHSEP, var_dir); */
}
@@ -64,6 +64,7 @@ ivars(void)
env_overr(&Spice_Exec_Dir, "SPICE_EXEC_DIR");
env_overr(&Spice_Lib_Dir, "SPICE_LIB_DIR");
+
mkvar(&News_File, Spice_Lib_Dir, "news", "SPICE_NEWS");
mkvar(&Default_MFB_Cap, Spice_Lib_Dir, "mfbcap", "SPICE_MFBCAP");
mkvar(&Help_Path, Spice_Lib_Dir, "helpdir", "SPICE_HELP_DIR");
diff --git a/src/misc/string.c b/src/misc/string.c
index ebbbabd3e..53aff57f1 100644
--- a/src/misc/string.c
+++ b/src/misc/string.c
@@ -192,8 +192,13 @@ register char *p, *s;
#endif /* CIDER */
-
-
+/*-------------------------------------------------------------------------*
+ * gettok skips over whitespace and returns the next token found. This is
+ * the original version. It does not "do the right thing" when you have
+ * parens or commas anywhere in the nodelist. Note that I left this unmodified
+ * since I didn't want to break any fcns which called it from elsewhere than
+ * subckt.c. -- SDB 12.3.2003.
+ *-------------------------------------------------------------------------*/
char *
gettok(char **s)
{
@@ -224,9 +229,10 @@ gettok(char **s)
/*-------------------------------------------------------------------------*
* gettok_noparens was added by SDB on 4.21.2003.
- * It acts like gettok, except that it stops parsing when it hits a paren
- * (i.e. it treats parens like whitespace). It is used in translate (subckt.c)
- * while looking for the POLY token.
+ * It acts like gettok, except that it treats parens and commas like
+ * whitespace while looking for the POLY token. That is, it stops
+ * parsing and returns when it finds one of those chars. It is called from
+ * 'translate' (subckt.c).
*-------------------------------------------------------------------------*/
char *
gettok_noparens(char **s)
@@ -235,24 +241,78 @@ gettok_noparens(char **s)
int i = 0;
char c;
- while (isspace(**s))
- (*s)++;
+ while ( isspace(**s) )
+ (*s)++; /* iterate over whitespace */
+
if (!**s)
- return (NULL);
- while ((c = **s) && !isspace(c) &&
- ( **s != '(' ) && ( **s != ')' ) ) {
+ return (NULL); /* return NULL if we come to end of line */
+
+ while ((c = **s) &&
+ !isspace(c) &&
+ ( **s != '(' ) &&
+ ( **s != ')' ) &&
+ ( **s != ',')
+ ) {
buf[i++] = *(*s)++;
}
buf[i] = '\0';
- while (isspace(**s))
- (*s)++;
+
+ /* Now iterate up to next non-whitespace char */
+ while ( isspace(**s) )
+ (*s)++;
+
+ return (copy(buf));
+}
+
+/*-------------------------------------------------------------------------*
+ * gettok_node was added by SDB on 12.3.2003
+ * It acts like gettok, except that it treats parens and commas like
+ * whitespace (i.e. it ignores them). Use it when parsing through netnames
+ * (node names) since they may be grouped using ( , ).
+ *-------------------------------------------------------------------------*/
+char *
+gettok_node(char **s)
+{
+ char buf[BSIZE_SP];
+ int i = 0;
+ char c;
+
+ while (isspace(**s) ||
+ ( **s == '(' ) ||
+ ( **s == ')' ) ||
+ ( **s == ',')
+ )
+ (*s)++; /* iterate over whitespace and ( , ) */
+
+ if (!**s)
+ return (NULL); /* return NULL if we come to end of line */
+
+ while ((c = **s) &&
+ !isspace(c) &&
+ ( **s != '(' ) &&
+ ( **s != ')' ) &&
+ ( **s != ',')
+ ) { /* collect chars until whitespace or ( , ) */
+ buf[i++] = *(*s)++;
+ }
+ buf[i] = '\0';
+
+ /* Now iterate up to next non-whitespace char */
+ while (isspace(**s) ||
+ ( **s == '(' ) ||
+ ( **s == ')' ) ||
+ ( **s == ',')
+ )
+ (*s)++; /* iterate over whitespace and ( , ) */
+
return (copy(buf));
}
/*-------------------------------------------------------------------------*
* get_l_paren iterates the pointer forward in a string until it hits
* the position after the next left paren "(". It returns 0 if it found a left
- * paren, and 1 if no left paren is found.
+ * paren, and 1 if no left paren is found. It is called from 'translate'
+ * (subckt.c).
*-------------------------------------------------------------------------*/
int
get_l_paren(char **s)
@@ -274,7 +334,8 @@ get_l_paren(char **s)
/*-------------------------------------------------------------------------*
* get_r_paren iterates the pointer forward in a string until it hits
* the position after the next right paren ")". It returns 0 if it found a right
- * paren, and 1 if no right paren is found.
+ * paren, and 1 if no right paren is found. It is called from 'translate'
+ * (subckt.c).
*-------------------------------------------------------------------------*/
int
get_r_paren(char **s)
diff --git a/src/misc/tilde.c b/src/misc/tilde.c
index 1e72b4e27..d657b41e8 100644
--- a/src/misc/tilde.c
+++ b/src/misc/tilde.c
@@ -15,6 +15,7 @@ Modified: 2002 R. Oktas,
#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
@@ -25,70 +26,13 @@ Modified: 2002 R. Oktas,
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( );*/
- char buf[BSIZE_SP];
- char *k, c;
-
- if (!string)
- return NULL;
-
- while (*string && isspace(*string))
- string++;
-
- if (*string != '~')
- return copy(string);
-
- string += 1;
-
- if (!*string || *string == '/') {
- pw = getpwuid(getuid());
- *buf = 0;
- } else {
- k = buf;
- while ((c = *string) && c != '/')
- *k++ = c, string++;
- *k = 0;
- pw = getpwnam(buf);
- }
-
- if (pw) {
- strcpy(buf, pw->pw_dir);
- if (*string)
- strcat(buf, string);
- } else
- return NULL;
-
- return copy(buf);
-
-#else
- return copy(string);
-#endif
-}
-
-#else /* HAVE_GNUREADLINE */
char *
tildexpand(char *string)
{
-
char buf[BSIZE_SP];
char *result, *k, c;
+
if (!string)
return NULL;
@@ -101,42 +45,44 @@ tildexpand(char *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");
+ /* 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;
- }
+ /* 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;
+ 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 (pw)
+ result = pw->pw_dir;
+#endif
}
if (result) {
#ifdef HAVE_PWD_H
- strcpy(buf, result);
+ strcpy(buf, result);
if (*string)
strcat(buf, string);
- return copy(buf);
+ return copy(buf);
+
} else
return NULL;
-#else
- /* Emulate the old behavior to prevent side effects. -- ro */
- return copy(string);
+#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 54b605aee..83cd8f72c 100644
--- a/src/misc/tilde.h
+++ b/src/misc/tilde.h
@@ -6,10 +6,7 @@
#ifndef TILDE_H_INCLUDED
#define TILDE_H_INCLUDED
-#ifdef HAVE_GNUREADLINE
char * tildexpand(char *string);
-#else
-char * tilde_expand(char *string);
-#endif
+
#endif
diff --git a/src/misc/util.c b/src/misc/util.c
new file mode 100644
index 000000000..369641dec
--- /dev/null
+++ b/src/misc/util.c
@@ -0,0 +1,151 @@
+/*************
+ * Various utility functions.
+ * 2002 R. Oktas,
+ ************/
+
+#ifdef HAVE_STRING_H
+#include
+#endif
+
+#include "ngspice.h"
+#include "util.h"
+
+
+/* **************************************************************** */
+/* */
+/* Stuff for Filename Handling */
+/* */
+/* **************************************************************** */
+
+/* Canonicalize PATH, and return a new path. The new path differs from PATH
+ in that:
+ Multple `/'s are collapsed to a single `/'.
+ Leading `./'s and trailing `/.'s are removed.
+ Trailing `/'s are removed.
+ Non-leading `../'s and trailing `..'s are handled by removing
+ portions of the path.
+
+ Stolen from Bash source (slightly modified).
+ Credit goes to Chet Ramey, et al. -- ro */
+
+char *
+canonicalize_pathname(char *path)
+{
+ int i, start;
+ char stub_char;
+ char *result;
+
+ /* The result cannot be larger than the input PATH. */
+ result = copy(path);
+
+ stub_char = (*path == '/') ? '/' : '.';
+
+ /* Walk along RESULT looking for things to compact. */
+ i = 0;
+ while (1) {
+ if (!result[i])
+ break;
+
+ while (result[i] && result[i] != '/')
+ i++;
+
+ start = i++;
+
+ /* If we didn't find any slashes, then there is nothing left to do. */
+ if (!result[start])
+ break;
+
+ /* Handle multiple `/'s in a row. */
+ while (result[i] == '/')
+ i++;
+
+#if !defined (apollo)
+ if ((start + 1) != i)
+#else
+ if ((start + 1) != i && (start != 0 || i != 2))
+#endif /* apollo */
+ {
+ strcpy (result + start + 1, result + i);
+ i = start + 1;
+ }
+
+#if 0
+ /* Handle backslash-quoted `/'. */
+ if (start > 0 && result[start - 1] == '\\')
+ continue;
+#endif
+
+ /* Check for trailing `/'. */
+ if (start && !result[i]) {
+ zero_last:
+ result[--i] = '\0';
+ break;
+ }
+
+ /* Check for `../', `./' or trailing `.' by itself. */
+ if (result[i] == '.') {
+ /* Handle trailing `.' by itself. */
+ if (!result[i + 1])
+ goto zero_last;
+
+ /* Handle `./'. */
+ if (result[i + 1] == '/') {
+ strcpy(result + i, result + i + 1);
+ i = (start < 0) ? 0 : start;
+ continue;
+ }
+
+ /* Handle `../' or trailing `..' by itself. */
+ if (result[i + 1] == '.' &&
+ (result[i + 2] == '/' || !result[i + 2])) {
+ while (--start > -1 && result[start] != '/');
+ strcpy(result + start + 1, result + i + 2);
+ i = (start < 0) ? 0 : start;
+ continue;
+ }
+ }
+ }
+
+ if (!*result) {
+ *result = stub_char;
+ result[1] = '\0';
+ }
+ return (result);
+}
+
+
+/* Turn STRING (a pathname) into an absolute pathname, assuming that
+ DOT_PATH contains the symbolic location of `.'. This always
+ returns a new string, even if STRING was an absolute pathname to
+ begin with.
+
+ Stolen from Bash source (slightly modified).
+ Credit goes to Chet Ramey, et al. -- ro */
+
+char * absolute_pathname(char *string, char *dot_path)
+{
+ char *result;
+ int result_len;
+
+ if (!dot_path || *string == '/')
+ result = copy(string);
+ else {
+ if (dot_path && dot_path[0]) {
+ result = tmalloc(2 + strlen(dot_path) + strlen(string));
+ strcpy(result, dot_path);
+ result_len = strlen(result);
+ if (result[result_len - 1] != '/') {
+ result[result_len++] = '/';
+ result[result_len] = '\0';
+ }
+ } else {
+ result = tmalloc(3 + strlen (string));
+ result[0] = '.'; result[1] = '/'; result[2] = '\0';
+ result_len = 2;
+ }
+
+ strcpy(result + result_len, string);
+ }
+
+ return (result);
+}
diff --git a/src/misc/util.h b/src/misc/util.h
new file mode 100644
index 000000000..af071e72f
--- /dev/null
+++ b/src/misc/util.h
@@ -0,0 +1,12 @@
+/*************
+ * Header file for util.c
+ * 2002 R. Oktas,
+ ************/
+
+#ifndef UTIL_H_INCLUDED
+#define UTIL_H_INCLUDED
+
+char *canonicalize_pathname(char *path);
+char *absolute_pathname(char *string, char *dot_path);
+
+#endif
diff --git a/src/nghelp.c b/src/nghelp.c
index 1fdc3b195..9bac2307d 100644
--- a/src/nghelp.c
+++ b/src/nghelp.c
@@ -28,6 +28,7 @@ char *Bug_Addr = "";
char *Spice_Host = "";
char *Spiced_Log = "";
+
/* dummy declaration so CP.a doesn't pull in lexical.o and other objects */
bool cp_interactive = FALSE;
@@ -110,5 +111,5 @@ cp_getvar(char *n, int t, void *r)
char *
cp_tildexpand(char *s)
{
- return tilde_expand(s);
+ return tildexpand(s);
}
diff --git a/src/ngmultidec.c b/src/ngmultidec.c
index b8e8e0744..8ab3aa62e 100644
--- a/src/ngmultidec.c
+++ b/src/ngmultidec.c
@@ -14,6 +14,7 @@ Author: 1990 Jaijeet Roychowdury
#undef DEBUG_LEVEL1
+/* `-u' option showing the usage help is changed to `-h'. -- ro */
extern void usage();
extern void comments();
@@ -102,7 +103,7 @@ int
use_opt = 1;
gotnum=1;
break;
- case 'u':
+ case 'h':
usage(pname);
exit(1);
break;
@@ -350,7 +351,7 @@ fprintf(stderr,"Usage: %s -l -c\n",argv[0]);
fprintf(stderr," -r -g \n");
fprintf(stderr," -k \n");
fprintf(stderr," -x -o \n");
-fprintf(stderr," -n -L -u\n");
+fprintf(stderr," -n -L -h\n");
fprintf(stderr,"Example: %s -n4 -l9e-9 -c20e-12 -r5.3 -x5e-12 -k0.7 -otest -L5.4\n\n",argv[0]);
fprintf(stderr,"See \"Efficient Transient Simulation of Lossy Interconnect\",\n");