Browse Source

Applied Stuart's 12-03-2003 patch. Support for readline (disabled) and for node names in the form (x,y).

pre-master-46
pnenzi 23 years ago
parent
commit
b03a70760b
  1. 16
      ChangeLog
  2. 28
      configure.in
  3. 50
      src/frontend/com_history.c
  4. 3
      src/frontend/cpitf.c
  5. 9
      src/frontend/display.h
  6. 10
      src/frontend/evaluate.c
  7. 99
      src/frontend/inpcom.c
  8. 28
      src/frontend/misccoms.c
  9. 5
      src/frontend/parser/glob.c
  10. 1
      src/frontend/plotting/x11.c
  11. 8
      src/frontend/resource.c
  12. 22
      src/frontend/runcoms.c
  13. 56
      src/frontend/signal_handler.c
  14. 112
      src/frontend/subckt.c
  15. 19
      src/frontend/variable.c
  16. 7
      src/include/ftedev.h
  17. 9
      src/include/ngspice.h
  18. 190
      src/main.c
  19. 4
      src/misc/Makefile.am
  20. 5
      src/misc/ivars.c
  21. 89
      src/misc/string.c
  22. 106
      src/misc/tilde.c
  23. 5
      src/misc/tilde.h
  24. 151
      src/misc/util.c
  25. 12
      src/misc/util.h
  26. 3
      src/nghelp.c
  27. 5
      src/ngmultidec.c

16
ChangeLog

@ -1,9 +1,23 @@
2004-01-10 Paolo Nenzi <p.nenzi@ieee.org> 2004-01-10 Paolo Nenzi <p.nenzi@ieee.org>
* 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
<sdb@cloud9.net>).
* Fixed makefiles in src/xspice/icm and src/xspice/cmpp to make * Fixed makefiles in src/xspice/icm and src/xspice/cmpp to make
distclean without barfing. (Stuart Brorson <sdb@cloud9.net>). distclean without barfing. (Stuart Brorson <sdb@cloud9.net>).
* configure.in * configure.in
src/xspice/cmpp/Makefile src/xspice/cmpp/Makefile.in: src/xspice/cmpp/Makefile src/xspice/cmpp/Makefile.in:
Make configure automatically set paths for lex yacc and Make configure automatically set paths for lex yacc and

28
configure.in

@ -9,7 +9,7 @@ dnl Create a configuration header
AM_CONFIG_HEADER(config.h) AM_CONFIG_HEADER(config.h)
dnl Initialize automake stuff 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 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, AC_ARG_ENABLE(numparam,
[ --enable-numparam Enable numparams library support, experimental *not in standard distribution*]) [ --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 dnl Enable maintainer commands only if requested
AM_MAINTAINER_MODE AM_MAINTAINER_MODE
@ -495,13 +501,19 @@ fi
AC_SUBST(NUMPARAMDIR) AC_SUBST(NUMPARAMDIR)
AC_SUBST(NUMPARAMLIB) 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( \ AC_OUTPUT( \
Makefile \ Makefile \

50
src/frontend/com_history.c

@ -353,10 +353,10 @@ cp_addhistent(int event, wordlist *wlist)
cp_lastone->hi_next = NULL; cp_lastone->hi_next = NULL;
cp_lastone->hi_event = event; cp_lastone->hi_event = event;
cp_lastone->hi_wlist = wl_copy(wlist); cp_lastone->hi_wlist = wl_copy(wlist);
#ifndef HAVE_GNUREADLINE
#ifndef HAVE_GNUREADLINE
freehist(histlength - cp_maxhistlength); freehist(histlength - cp_maxhistlength);
histlength++; histlength++;
#endif
#endif
return; return;
} }
@ -493,36 +493,38 @@ com_history(wordlist *wl)
wl = wl->wl_next; wl = wl->wl_next;
rev = TRUE; rev = TRUE;
} }
#ifdef HAVE_GNUREADLINE #ifdef HAVE_GNUREADLINE
/* Added GNU Readline Support -- Andrew Veliath <veliaa@rpi.edu> */ /* 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);
}
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
#else
if (wl == NULL) if (wl == NULL)
cp_hprint(cp_event - 1, cp_event - histlength, rev); cp_hprint(cp_event - 1, cp_event - histlength, rev);
else else
cp_hprint(cp_event - 1, cp_event - 1 - atoi(wl->wl_word), rev); cp_hprint(cp_event - 1, cp_event - 1 - atoi(wl->wl_word), rev);
#endif /* ifelse HAVE_GNUREADLINE */
#endif /* ifelse HAVE_GNUREADLINE */
return; return;
} }

3
src/frontend/cpitf.c

@ -293,7 +293,8 @@ cp_istrue(wordlist *wl)
void void
cp_periodic(void) cp_periodic(void)
{ {
ft_setflag = ft_intrpt = FALSE;
ft_setflag = FALSE;
ft_intrpt = FALSE;
ft_ckspace(); ft_ckspace();
ft_checkkids(); ft_checkkids();
vec_gc(); vec_gc();

9
src/frontend/display.h

@ -3,9 +3,15 @@
* 1999 E. Rouat * 1999 E. Rouat
************/ ************/
/* See if we have been already included */
#ifndef DISPLAY_H_INCLUDED #ifndef DISPLAY_H_INCLUDED
#define DISPLAY_H_INCLUDED #define DISPLAY_H_INCLUDED
/* Include a bunch of other stuff to make display.h work */
#include <ftedev.h>
#include <fteinput.h>
#include <graph.h>
DISPDEVICE *FindDev(char *name); DISPDEVICE *FindDev(char *name);
void DevInit(void); void DevInit(void);
int NewViewport(GRAPH *pgraph); int NewViewport(GRAPH *pgraph);
@ -25,6 +31,5 @@ void SaveText(GRAPH *graph, char *text, int x, int y);
int DevSwitch(char *devname); int DevSwitch(char *devname);
#endif /* DISPLAY_H_INCLUDED */
#endif

10
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. * be lost, but that's no great loss.
*/ */
static jmp_buf matherrbuf;
static sigjmp_buf matherrbuf;
static RETSIGTYPE static RETSIGTYPE
sig_matherr(void) sig_matherr(void)
{ {
fprintf(cp_err, "Error: argument out of range for math function\n"); 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 /* Some of the math routines generate SIGILL if the argument is
* out of range. Catch this here. * out of range. Catch this here.
*/ */
if (setjmp(matherrbuf)) {
if (sigsetjmp(matherrbuf, 1)) {
return (NULL); return (NULL);
} }
(void) signal(SIGILL, (SIGNAL_FUNCTION) sig_matherr); (void) signal(SIGILL, (SIGNAL_FUNCTION) sig_matherr);
@ -296,7 +296,7 @@ doop(char what,
tfree(c2); tfree(c2);
} }
} }
/* va: garbage collection */ /* va: garbage collection */
if (arg1->pn_value==NULL && v1!=NULL) vec_free(v1); if (arg1->pn_value==NULL && v1!=NULL) vec_free(v1);
if (arg2->pn_value==NULL && v2!=NULL) vec_free(v2); 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 /* Some of the math routines generate SIGILL if the argument is
* out of range. Catch this here. * out of range. Catch this here.
*/ */
if (setjmp(matherrbuf)) {
if (sigsetjmp(matherrbuf, 1)) {
(void) signal(SIGILL, SIG_DFL); (void) signal(SIGILL, SIG_DFL);
return (NULL); return (NULL);
} }

99
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; struct line *end = NULL, *cc = NULL, *prev = NULL, *working, *newcard;
char *buffer, *s, *t, c; char *buffer, *s, *t, c;
/* segfault fix */ /* segfault fix */
char *copys = NULL;
char *copys=NULL;
int line = 1; int line = 1;
FILE *newfp; 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 #ifdef XSPICE
Ipc_Status_t ipc_status; Ipc_Status_t ipc_status;
char ipc_buffer[1025]; /* Had better be big enough */ 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 */ /* gtri - end - 12/12/90 */
#else #else
while ((buffer = readline(fp))) { while ((buffer = readline(fp))) {
#endif
#endif
#ifdef TRACE #ifdef TRACE
/* SDB debug statement */ /* SDB debug statement */
@ -185,12 +188,15 @@ inp_readall(FILE *fp, struct line **data)
|| (strcmp(buffer,"\r\n") == 0) ) { || (strcmp(buffer,"\r\n") == 0) ) {
continue; continue;
} }
if (*buffer == '@') { if (*buffer == '@') {
tfree(buffer); /* was allocated by readline() */ tfree(buffer); /* was allocated by readline() */
break; 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 premature end. If premature end is reached, spew
error and zap the line. */ error and zap the line. */
for (s = buffer; *s && (*s != '\n'); s++); 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 */ if(*(s-1) == '\r') /* Zop the carriage return under windows */
*(s-1) = '\0'; *(s-1) = '\0';
/* now handle .include statements */ /* now handle .include statements */
if (ciprefix(".include", buffer)) { 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++; 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"); fprintf(cp_err, "Error: .include filename missing\n");
tfree(buffer); /* was allocated by readline() */ tfree(buffer); /* was allocated by readline() */
continue; continue;
} /* Now s points to first char after .include */ } /* 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 == '~') { if (*s == '~') {
copys = cp_tildexpand(s); /* allocates memory, but can also return NULL */ 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); perror(s);
if(copys) { if(copys) {
tfree(copys); /* allocated by the cp_tildexpand() above */ tfree(copys); /* allocated by the cp_tildexpand() above */
@ -243,16 +249,17 @@ inp_readall(FILE *fp, struct line **data)
/* Make the .include a comment */ /* Make the .include a comment */
*buffer = '*'; *buffer = '*';
/* now check if this is the first pass (i.e. end points to null) */ /* 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 { } 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. */ /* now fill out rest of struct end. */
end->li_next = NULL; end->li_next = NULL;
end->li_error = NULL; end->li_error = NULL;
@ -267,28 +274,29 @@ inp_readall(FILE *fp, struct line **data)
/* Fix the buffer up a bit. */ /* Fix the buffer up a bit. */
(void) strncpy(buffer + 1, "end of:", 7); (void) strncpy(buffer + 1, "end of:", 7);
} /* 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 */
} /* 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 put buffer into li */
/* now put buffer into li */
end->li_next = NULL; end->li_next = NULL;
end->li_error = NULL; end->li_error = NULL;
end->li_actual = NULL; end->li_actual = NULL;
end->li_line = buffer; end->li_line = buffer;
end->li_linenum = line++; end->li_linenum = line++;
} }
if (!end) { /* No stuff here */ if (!end) { /* No stuff here */
*data = NULL; *data = NULL;
return; return;
} /* end while ((buffer = readline(fp))) */
} /* end while ((buffer = readline(fp))) */
/* This should be freed because we are done with it. */ /* This should be freed because we are done with it. */
/* tfree(buffer); */ /* tfree(buffer); */
@ -296,8 +304,7 @@ inp_readall(FILE *fp, struct line **data)
/* Now clean up li: remove comments & stitch together continuation lines. */ /* Now clean up li: remove comments & stitch together continuation lines. */
working = cc->li_next; /* cc points to head of deck. Start with the working = cc->li_next; /* cc points to head of deck. Start with the
next card (skip title). */
next card. */
while (working) { while (working) {
for (s = working->li_line; (c = *s) && c <= ' '; s++) for (s = working->li_line; (c = *s) && c <= ' '; s++)
@ -306,28 +313,30 @@ inp_readall(FILE *fp, struct line **data)
#ifdef TRACE #ifdef TRACE
/* SDB debug statement */ /* SDB debug statement */
printf("In inp_readall, processing linked list element s = %s . . . \n", s); printf("In inp_readall, processing linked list element s = %s . . . \n", s);
#endif
#endif
switch (c) { switch (c) {
case '#':
case '#':
case '$': case '$':
case '*': case '*':
case '\0': 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; break;
case '+': /* handle continuation */
case '+': /* handle continuation */
if (!prev) { if (!prev) {
working->li_error = copy( working->li_error = copy(
"Illegal continuation line: ignored."); "Illegal continuation line: ignored.");
working = working->li_next; working = working->li_next;
break; break;
} }
/* create buffer and write last and current line into it. */ /* create buffer and write last and current line into it. */
buffer = tmalloc(strlen(prev->li_line) + strlen(s) + 2); 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; s = prev->li_line;
prev->li_line = buffer; prev->li_line = buffer;
prev->li_next = working->li_next; prev->li_next = working->li_next;
@ -349,7 +358,8 @@ inp_readall(FILE *fp, struct line **data)
} }
working = prev->li_next; working = prev->li_next;
break; break;
default: /* regular one-line card */
default: /* regular one-line card */
prev = working; prev = working;
working = working->li_next; working = working->li_next;
break; break;
@ -360,7 +370,6 @@ inp_readall(FILE *fp, struct line **data)
return; return;
} }
/*-------------------------------------------------------------------------* /*-------------------------------------------------------------------------*
* * * *
*-------------------------------------------------------------------------*/ *-------------------------------------------------------------------------*/

28
src/frontend/misccoms.c

@ -15,12 +15,10 @@ Author: 1985 Wayne A. Christopher, U. C. Berkeley CAD Group
#include "hcomp.h" #include "hcomp.h"
#include "variable.h" #include "variable.h"
#ifdef HAVE_GNUREADLINE #ifdef HAVE_GNUREADLINE
#include <readline/readline.h> #include <readline/readline.h>
#include <readline/history.h> #include <readline/history.h>
extern int gnu_history_lines;
extern char gnu_history_file[];
#endif #endif
static void byemesg(void); static void byemesg(void);
@ -77,8 +75,9 @@ com_quit(wordlist *wl)
clearerr(stdin); clearerr(stdin);
*buf = 'y'; *buf = 'y';
} }
if ((*buf == 'y') || (*buf == 'Y') || (*buf == '\n'))
if ((*buf == 'y') || (*buf == 'Y') || (*buf == '\n')) {
byemesg(); byemesg();
}
else { else {
return; return;
} }
@ -86,14 +85,9 @@ com_quit(wordlist *wl)
byemesg(); byemesg();
} else } else
byemesg(); 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); exit(EXIT_NORMAL);
} }
@ -235,6 +229,18 @@ com_version(wordlist *wl)
static void static void
byemesg(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); printf("%s-%s done\n", ft_sim->simulator, ft_sim->version);
return; return;
} }

5
src/frontend/parser/glob.c

@ -72,11 +72,8 @@ cp_tildexpand(char *string)
{ {
char *result; char *result;
#ifdef HAVE_READLINE
result = tildexpand(string); result = tildexpand(string);
#else
result = tilde_expand(string);
#endif
if (!result) { if (!result) {
if (cp_nonomatch) { if (cp_nonomatch) {
return copy(string); return copy(string);

1
src/frontend/plotting/x11.c

@ -796,6 +796,7 @@ zoomin(GRAPH *graph)
wl = cp_parse(buf); wl = cp_parse(buf);
(void) cp_addhistent(cp_event++, wl); (void) cp_addhistent(cp_event++, wl);
} }
#endif /* HAVE_GNUREADLINE */ #endif /* HAVE_GNUREADLINE */
(void) cp_evloop(buf); (void) cp_evloop(buf);

8
src/frontend/resource.c

@ -386,13 +386,13 @@ printres(char *name)
#define LOG2_PAGESIZE 8 #define LOG2_PAGESIZE 8
static jmp_buf env;
static sigjmp_buf env;
static RETSIGTYPE static RETSIGTYPE
fault(void) fault(void)
{ {
signal(SIGSEGV, (SIGNAL_FUNCTION) fault); /* SysV style */ signal(SIGSEGV, (SIGNAL_FUNCTION) fault); /* SysV style */
longjmp(env, 1);
siglongjmp(env, 1);
} }
static void * static void *
@ -425,13 +425,13 @@ baseaddr(void)
break; break;
} }
if (setjmp(env)) {
if (sigsetjmp(env, 1)) {
low = at; low = at;
continue; continue;
} else } else
x = *at; x = *at;
if (setjmp(env)) {
if (sigsetjmp(env, 1)) {
low = at; low = at;
continue; continue;
} else } else

22
src/frontend/runcoms.c

@ -203,11 +203,11 @@ dosim(char *what, wordlist *wl)
ct->ci_inprogress = FALSE; ct->ci_inprogress = FALSE;
} }
if (ft_curckt->ci_inprogress && eq(what, "resume")) { 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; ft_intrpt = FALSE;
fprintf(cp_err, "Warning: resuming run in progress.\n"); fprintf(cp_err, "Warning: resuming run in progress.\n");
com_resume((wordlist *) NULL); com_resume((wordlist *) NULL);
ft_setflag = FALSE;
ft_setflag = FALSE; /* Now allow aborts again */
return 0; return 0;
} }
@ -215,7 +215,7 @@ dosim(char *what, wordlist *wl)
* set a flag and let spice finish up, then control will be * set a flag and let spice finish up, then control will be
* passed back to the user. * passed back to the user.
*/ */
ft_setflag = TRUE;
ft_setflag = TRUE; /* Don't allow abort upon interrupt during run. */
ft_intrpt = FALSE; ft_intrpt = FALSE;
if (dofile) { if (dofile) {
#ifdef PARALLEL_ARCH #ifdef PARALLEL_ARCH
@ -245,9 +245,9 @@ dosim(char *what, wordlist *wl)
#else #else
else if (!(rawfileFp = fopen(wl->wl_word, "w"))) { else if (!(rawfileFp = fopen(wl->wl_word, "w"))) {
setvbuf(rawfileFp, rawfileBuf, _IOFBF, RAWBUF_SIZE); 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__ */ #endif /* __MINGW32__ */
rawfileBinary = !ascii; rawfileBinary = !ascii;
@ -261,14 +261,14 @@ dosim(char *what, wordlist *wl)
} }
/*save rawfile name saj*/ /*save rawfile name saj*/
if(last_used_rawfile) if(last_used_rawfile)
tfree(last_used_rawfile); /* va: we should allways use tfree */
tfree(last_used_rawfile);
if(rawfileFp){ if(rawfileFp){
last_used_rawfile = copy(wl->wl_word); last_used_rawfile = copy(wl->wl_word);
}else { }else {
last_used_rawfile = NULL; last_used_rawfile = NULL;
} }
/*end saj*/ /*end saj*/
/* Spice calls wrd_init and wrd_end itself */ /* Spice calls wrd_init and wrd_end itself */
ft_curckt->ci_inprogress = TRUE; ft_curckt->ci_inprogress = TRUE;
if (eq(what,"sens2")) { if (eq(what,"sens2")) {
@ -282,7 +282,7 @@ dosim(char *what, wordlist *wl)
if(g_ipc.enabled) if(g_ipc.enabled)
ipc_send_errchk(); ipc_send_errchk();
/* gtri - end - 12/12/90 */ /* gtri - end - 12/12/90 */
#endif
#endif
} else } else
ft_curckt->ci_inprogress = FALSE; ft_curckt->ci_inprogress = FALSE;
} else { } else {
@ -296,7 +296,7 @@ dosim(char *what, wordlist *wl)
if(g_ipc.enabled) if(g_ipc.enabled)
ipc_send_errchk(); ipc_send_errchk();
/* gtri - end - 12/12/90 */ /* gtri - end - 12/12/90 */
#endif
#endif
err = 0; err = 0;
} else if (err == 2) { } else if (err == 2) {
fprintf(cp_err, "%s simulation(s) aborted\n", what); fprintf(cp_err, "%s simulation(s) aborted\n", what);
@ -322,7 +322,7 @@ dosim(char *what, wordlist *wl)
if (wl) if (wl)
wl->wl_prev = NULL; wl->wl_prev = NULL;
tfree(ww); tfree(ww);
}
}
return err; return err;
} }

56
src/frontend/signal_handler.c

@ -18,10 +18,15 @@ Author: 1985 Wayne A. Christopher, U. C. Berkeley CAD Group
#include <signal.h> #include <signal.h>
#include "signal_handler.h" #include "signal_handler.h"
#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
extern jmp_buf jbuf;
extern sigjmp_buf jbuf;
/* The (void) signal handlers... SIGINT is the only one that gets reset (by /* 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 * 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); extern pid_t getpid (void);
/* not using SIGINT with GNU Readline - AV */
#ifndef HAVE_GNUREADLINE
/* invoke this function upon keyboard interrupt */
RETSIGTYPE RETSIGTYPE
ft_sigintr(void) 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 { else {
fprintf(cp_err, "Interrupt\n");
fprintf(cp_err, "Interrupted once . . .\n");
ft_intrpt = TRUE; 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_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 RETSIGTYPE
sigfloat(int sig, int code) sigfloat(int sig, int code)
@ -66,7 +84,7 @@ sigfloat(int sig, int code)
fperror("Error", code); fperror("Error", code);
rewind(cp_out); rewind(cp_out);
(void) signal( SIGFPE, (SIGNAL_FUNCTION) sigfloat ); (void) signal( SIGFPE, (SIGNAL_FUNCTION) sigfloat );
longjmp(jbuf, 1);
siglongjmp(jbuf, 1);
} }
/* This should give a new prompt if cshpar is waiting for input. */ /* This should give a new prompt if cshpar is waiting for input. */
@ -88,7 +106,7 @@ sigcont(void)
{ {
(void) signal(SIGTSTP, (SIGNAL_FUNCTION) sigstop); (void) signal(SIGTSTP, (SIGNAL_FUNCTION) sigstop);
if (cp_cwait) if (cp_cwait)
longjmp(jbuf, 1);
siglongjmp(jbuf, 1);
} }
# endif # endif

112
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 */ for (c = deck; c; c = c->li_next) { /* iterate on lines in deck */
if (prefix(start, c->li_line)) { /* if we find .subckt . . . */ 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 */ for (s = c->li_line; *s && (*s != '('); s++) /* Iterate charwise along line until ( is found */
; ;
if (*s) { if (*s) {
@ -200,6 +204,10 @@ inp_subcktexpand(struct line *deck)
/* doit does the actual splicing in of the .subckt . . . */ /* 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); ll = doit(deck);
/* Now check to see if there are still subckt instances undefined... */ /* Now check to see if there are still subckt instances undefined... */
@ -259,6 +267,11 @@ doit(struct line *deck)
subs = NULL; subs = NULL;
submod = 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. */ /* First pass: xtract all the .subckts and stick pointers to them into sss. */
for (last = deck, lc = NULL; last; ) { for (last = deck, lc = NULL; last; ) {
if (prefix(sbend, last->li_line)) { /* if line == .ends */ 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 */ 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; error = 0;
/* Second pass: do the replacements. */ /* Second pass: do the replacements. */
do { /* while (!error && numpasses-- && gotone) */ do { /* while (!error && numpasses-- && gotone) */
@ -444,8 +462,8 @@ doit(struct line *deck)
lcc = inp_deckcopy(sss->su_def); lcc = inp_deckcopy(sss->su_def);
/* Change the names of .models found in .subckts . . . */ /* 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; s = sss->su_args;
txfree(gettok(&t)); /* Throw out the subcircuit refdes */ 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); nnodes = numnodes(c->li_line);
while (nnodes-- > 0) { while (nnodes-- > 0) {
name = gettok(&s);
name = gettok_node(&s);
if (name == NULL) { if (name == NULL) {
fprintf(cp_err, "Error: too few nodes: %s\n", fprintf(cp_err, "Error: too few nodes: %s\n",
c->li_line); 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"); printf("In translate, looking at e, f, g, h found poly\n");
#endif #endif
/* move pointer ahead of paren */
/* move pointer ahead of ( */
if( get_l_paren(&s) == 1 ) { 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); nametofree = gettok_noparens(&s);
@ -784,10 +802,10 @@ translate(struct line *deck, char *formal, char *actual, char *scname, char *sub
/* move pointer ahead of ) */ /* move pointer ahead of ) */
if( get_r_paren(&s) == 1 ) { 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 */ /* 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 */ /* Now translate the controlling source/nodes */
nnodes = dim * numdevs(c->li_line); nnodes = dim * numdevs(c->li_line);
while (nnodes-- > 0) { 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) { if (name == NULL) {
fprintf(cp_err, "Error: too few devs: %s\n", fprintf(cp_err, "Error: too few devs: %s\n",
c->li_line); c->li_line);
@ -863,7 +881,7 @@ translate(struct line *deck, char *formal, char *actual, char *scname, char *sub
/*================= Default case ===================*/ /*================= Default case ===================*/
default: /* this section handles ordinary components */ default: /* this section handles ordinary components */
s = c->li_line; s = c->li_line;
nametofree = name = gettok(&s);
nametofree = name = gettok_node(&s); /* changed to gettok_node to handle netlists with ( , ) */
if (!name) if (!name)
continue; continue;
if (!*name) { if (!*name) {
@ -892,7 +910,7 @@ translate(struct line *deck, char *formal, char *actual, char *scname, char *sub
nnodes = numnodes(c->li_line); nnodes = numnodes(c->li_line);
while (nnodes-- > 0) { while (nnodes-- > 0) {
name = gettok(&s);
name = gettok_node(&s);
if (name == NULL) { if (name == NULL) {
fprintf(cp_err, "Error: too few nodes: %s\n", fprintf(cp_err, "Error: too few nodes: %s\n",
c->li_line); c->li_line);
@ -920,7 +938,7 @@ translate(struct line *deck, char *formal, char *actual, char *scname, char *sub
*/ */
nnodes = numdevs(c->li_line); nnodes = numdevs(c->li_line);
while (nnodes-- > 0) { while (nnodes-- > 0) {
t = name = gettok(&s);
t = name = gettok_node(&s);
if (name == NULL) { if (name == NULL) {
fprintf(cp_err, "Error: too few devs: %s\n", fprintf(cp_err, "Error: too few devs: %s\n",
c->li_line); c->li_line);
@ -1192,9 +1210,9 @@ numnodes(char *name)
i = 0; i = 0;
s = buf; s = buf;
gotit = 0; gotit = 0;
txfree(gettok(&s)); /* Skip component name */
txfree(gettok(&s)); /* Skip component name */
while ((i < n) && (*s) && !gotit) { while ((i < n) && (*s) && !gotit) {
t = gettok(&s);
t = gettok_node(&s); /* get nodenames . . . */
for (wl = modnames; wl; wl = wl->wl_next) for (wl = modnames; wl; wl = wl->wl_next)
if (eq(t, wl->wl_word)) if (eq(t, wl->wl_word))
gotit = 1; 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 static void
devmodtranslate(struct line *deck, char *subname) devmodtranslate(struct line *deck, char *subname)
@ -1345,9 +1366,14 @@ devmodtranslate(struct line *deck, char *subname)
for (s = deck; s; s = s->li_next) { for (s = deck; s; s = s->li_next) {
t = s->li_line; t = s->li_line;
#ifdef TRACE
/* SDB debug stuff */
printf("In devmodtranslate, examining line %s.\n", t);
#endif
while (*t && isspace(*t)) while (*t && isspace(*t))
t++; t++;
c = isupper(*t) ? tolower(*t) : *t;
c = isupper(*t) ? tolower(*t) : *t; /* set c to first char in line. . . . */
found = FALSE; found = FALSE;
buffer = tmalloc(strlen(t) + strlen(subname) + 4); buffer = tmalloc(strlen(t) + strlen(subname) + 4);
@ -1355,17 +1381,17 @@ devmodtranslate(struct line *deck, char *subname)
case 'r': case 'r':
case 'c': case 'c':
name = gettok(&t);
name = gettok(&t); /* get refdes */
(void) sprintf(buffer,"%s ",name); (void) sprintf(buffer,"%s ",name);
tfree(name); tfree(name);
name = gettok(&t);
name = gettok_node(&t); /* get first netname */
(void) sprintf(buffer + strlen(buffer), "%s ", name); (void) sprintf(buffer + strlen(buffer), "%s ", name);
tfree(name); tfree(name);
name = gettok(&t);
name = gettok_node(&t); /* get second netname */
(void) sprintf(buffer + strlen(buffer), "%s ", name); (void) sprintf(buffer + strlen(buffer), "%s ", name);
tfree(name); tfree(name);
if (*t) {
if (*t) { /* if there is a model, process it. . . . */
name = gettok(&t); name = gettok(&t);
/* Now, is this a subcircuit model? */ /* Now, is this a subcircuit model? */
for (wlsub = submod; wlsub; wlsub = wlsub->wl_next) { for (wlsub = submod; wlsub; wlsub = wlsub->wl_next) {
@ -1404,13 +1430,13 @@ devmodtranslate(struct line *deck, char *subname)
break; break;
case 'd': case 'd':
name = gettok(&t);
name = gettok(&t); /* get refdes */
(void) sprintf(buffer,"%s ",name); (void) sprintf(buffer,"%s ",name);
tfree(name); tfree(name);
name = gettok(&t);
name = gettok_node(&t); /* get first attached netname */
(void) sprintf(buffer + strlen(buffer), "%s ", name); (void) sprintf(buffer + strlen(buffer), "%s ", name);
tfree(name); tfree(name);
name = gettok(&t);
name = gettok_node(&t); /* get second attached netname */
(void) sprintf(buffer + strlen(buffer), "%s ", name); (void) sprintf(buffer + strlen(buffer), "%s ", name);
tfree(name); tfree(name);
name = gettok(&t); name = gettok(&t);
@ -1437,6 +1463,10 @@ devmodtranslate(struct line *deck, char *subname)
case 'u': case 'u':
case 'j': case 'j':
case 'z': 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); name = gettok(&t);
(void) sprintf(buffer,"%s ",name); (void) sprintf(buffer,"%s ",name);
name = gettok(&t); name = gettok(&t);
@ -1464,22 +1494,26 @@ devmodtranslate(struct line *deck, char *subname)
s->li_line = buffer; s->li_line = buffer;
break; 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 's':
case 'm': case 'm':
name = gettok(&t);
name = gettok(&t); /* get refdes */
(void) sprintf(buffer,"%s ",name); (void) sprintf(buffer,"%s ",name);
tfree(name); tfree(name);
name = gettok(&t);
name = gettok_node(&t); /* get first attached netname */
(void) sprintf(buffer + strlen(buffer), "%s ", name); (void) sprintf(buffer + strlen(buffer), "%s ", name);
tfree(name); tfree(name);
name = gettok(&t);
name = gettok_node(&t); /* get second attached netname */
(void) sprintf(buffer + strlen(buffer), "%s ", name); (void) sprintf(buffer + strlen(buffer), "%s ", name);
tfree(name); tfree(name);
name = gettok(&t);
name = gettok_node(&t); /* get third attached netname */
(void) sprintf(buffer + strlen(buffer), "%s ", name); (void) sprintf(buffer + strlen(buffer), "%s ", name);
tfree(name); tfree(name);
name = gettok(&t);
name = gettok_node(&t); /* get fourth attached netname */
(void) sprintf(buffer + strlen(buffer), "%s ", name); (void) sprintf(buffer + strlen(buffer), "%s ", name);
tfree(name); tfree(name);
name = gettok(&t); name = gettok(&t);
@ -1503,19 +1537,19 @@ devmodtranslate(struct line *deck, char *subname)
break; break;
case 'q': case 'q':
name = gettok(&t);
name = gettok(&t); /* get refdes */
(void) sprintf(buffer,"%s ",name); (void) sprintf(buffer,"%s ",name);
tfree(name); tfree(name);
name = gettok(&t);
name = gettok_node(&t); /* get first attached netname */
(void) sprintf(buffer + strlen(buffer), "%s ", name); (void) sprintf(buffer + strlen(buffer), "%s ", name);
tfree(name); tfree(name);
name = gettok(&t);
name = gettok_node(&t); /* get second attached netname */
(void) sprintf(buffer + strlen(buffer), "%s ", name); (void) sprintf(buffer + strlen(buffer), "%s ", name);
tfree(name); tfree(name);
name = gettok(&t);
name = gettok_node(&t); /* get third attached netname */
(void) sprintf(buffer + strlen(buffer), "%s ", name); (void) sprintf(buffer + strlen(buffer), "%s ", name);
tfree(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? */ /* Now, is this a subcircuit model? */
for (wlsub = submod; wlsub; wlsub = wlsub->wl_next) { for (wlsub = submod; wlsub; wlsub = wlsub->wl_next) {

19
src/frontend/variable.c

@ -157,7 +157,7 @@ cp_vset(char *varname, char type, char *value)
cp_maxhistlength = v->va_real; cp_maxhistlength = v->va_real;
else if (eq(copyvarname, "noclobber")) else if (eq(copyvarname, "noclobber"))
cp_noclobber = TRUE; cp_noclobber = TRUE;
else if (eq(varname, "echo")) /*CDHW*/
else if (eq(varname, "echo")) /*CDHW*/
cp_echo = TRUE; /*CDHW*/ cp_echo = TRUE; /*CDHW*/
else if (eq(copyvarname, "prompt") && (type == VT_STRING)) else if (eq(copyvarname, "prompt") && (type == VT_STRING))
cp_promptstring = copy(v->va_string); cp_promptstring = copy(v->va_string);
@ -208,10 +208,12 @@ cp_vset(char *varname, char type, char *value)
alreadythere = FALSE; alreadythere = FALSE;
if (ft_curckt) { if (ft_curckt) {
for (u = ft_curckt->ci_vars; u; u = u->va_next) for (u = ft_curckt->ci_vars; u; u = u->va_next)
{
if (eq(copyvarname, u->va_name)) { if (eq(copyvarname, u->va_name)) {
alreadythere = TRUE; alreadythere = TRUE;
break; break;
} }
}
if (!alreadythere) { if (!alreadythere) {
v->va_next = ft_curckt->ci_vars; v->va_next = ft_curckt->ci_vars;
ft_curckt->ci_vars = v; ft_curckt->ci_vars = v;
@ -225,7 +227,7 @@ cp_vset(char *varname, char type, char *value)
/* va_next left unchanged */ /* va_next left unchanged */
tfree(v->va_name); tfree(v->va_name);
tfree(v); tfree(v);
/* va: old version with memory leaks
/* va: old version with memory leaks
w = u->va_next; w = u->va_next;
bcopy(v, u, sizeof(*u)); bcopy(v, u, sizeof(*u));
u->va_next = w; u->va_next = w;
@ -291,9 +293,7 @@ cp_setparse(wordlist *wl)
*s = '\0'; *s = '\0';
if (*val == '\0') { if (*val == '\0') {
if (!wl) { 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*/ tfree(name);/*DG: cp_unquote Memory leak: free name before exiting*/
return (NULL); return (NULL);
} else { } else {
@ -343,7 +343,7 @@ cp_setparse(wordlist *wl)
} }
if (balance && !wl) { if (balance && !wl) {
fprintf(cp_err, "Error: bad set form.\n"); 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); return (NULL);
} }
@ -373,7 +373,7 @@ cp_setparse(wordlist *wl)
vv->va_string = copy(val); vv->va_string = copy(val);
} }
tfree(copyval);/*DG: must free ss any way to avoid cp_unquote memory leak */ 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) if(name)
tfree(name); tfree(name);
@ -485,6 +485,11 @@ cp_getvar(char *name, int type, void *retval)
{ {
struct variable *v; 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) for (v = variables; v; v = v->va_next)
if (eq(name, v->va_name)) if (eq(name, v->va_name))
break; break;

7
src/include/ftedev.h

@ -9,6 +9,10 @@ Author: 1987 Jeffrey M. Hsu
The display device structure. The display device structure.
*/ */
#ifndef FTEDEV_H_INCLUDED
#define FTEDEV_H_INCLUDED
typedef struct { typedef struct {
char *name; char *name;
int minx, miny; int minx, miny;
@ -35,3 +39,6 @@ typedef struct {
} DISPDEVICE; } DISPDEVICE;
extern DISPDEVICE *dispdev; extern DISPDEVICE *dispdev;
#endif

9
src/include/ngspice.h

@ -127,6 +127,7 @@ struct timeb timebegin;
extern char *gettok(char **s); extern char *gettok(char **s);
extern char *gettok_noparens(char **s); extern char *gettok_noparens(char **s);
extern char *gettok_node(char **s);
extern int get_l_paren(char **s); extern int get_l_paren(char **s);
extern int get_r_paren(char **s); extern int get_r_paren(char **s);
extern void appendc(char *s, char c); 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 ciprefix(register char *p, register char *s);
extern int cieq(register char *p, register char *s); extern int cieq(register char *p, register char *s);
extern void strtolower(char *str); extern void strtolower(char *str);
#ifdef HAVE_GNUREADLINE
extern char *tildexpand(char *string); 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 *smktemp(char *id);
extern char *copy(char *str); extern char *copy(char *str);

190
src/main.c

@ -5,7 +5,7 @@
Author: 1985 Wayne A. Christopher Author: 1985 Wayne A. Christopher
The main routine for ngspice */ The main routine for ngspice */
#include <ngspice.h> #include <ngspice.h>
#include <stdio.h> #include <stdio.h>
@ -30,7 +30,7 @@
#include <misc/getopt.h> #include <misc/getopt.h>
#include <frontend/resource.h> #include <frontend/resource.h>
#include <frontend/variable.h> #include <frontend/variable.h>
//#include "frontend/display.h" /* va */
#include <frontend/display.h> /* added by SDB to pick up Input() fcn */
/* saj xspice headers */ /* saj xspice headers */
#ifdef XSPICE #ifdef XSPICE
@ -49,7 +49,10 @@
#include <readline/readline.h> #include <readline/readline.h>
#include <readline/history.h> #include <readline/history.h>
#include "fteinput.h" #include "fteinput.h"
#endif
char gnu_history_file[512];
static char *application_name;
#endif /* HAVE_GNUREADLINE */
#ifndef HAVE_GETRUSAGE #ifndef HAVE_GETRUSAGE
#ifdef HAVE_FTIME #ifdef HAVE_FTIME
@ -68,8 +71,8 @@ static bool ft_servermode = FALSE;
static bool ft_batchmode = FALSE; static bool ft_batchmode = FALSE;
/* Frontend options */ /* 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"; char *ft_rawfile = "rawspice.raw";
#ifdef HAVE_GNUREADLINE #ifdef HAVE_GNUREADLINE
@ -144,7 +147,7 @@ struct variable *(*if_getparam)( );
jmp_buf jbuf;
sigjmp_buf jbuf;
static int started = FALSE; static int started = FALSE;
@ -171,56 +174,67 @@ extern struct comm nutcp_coms[ ];
struct comm *cp_coms = nutcp_coms; struct comm *cp_coms = nutcp_coms;
static IFfrontEnd nutmeginfo; static IFfrontEnd nutmeginfo;
/* -------------------------------------------------------------------------- */
int int
if_run(char *t, char *w, wordlist *s, char *b) if_run(char *t, char *w, wordlist *s, char *b)
{ {
return (0); return (0);
} }
/* -------------------------------------------------------------------------- */
int int
if_sens_run(char *t, char *w, wordlist *s, char *b) if_sens_run(char *t, char *w, wordlist *s, char *b)
{ {
return (0); return (0);
} }
/* -------------------------------------------------------------------------- */
void void
if_dump(char *ckt, FILE *fp) if_dump(char *ckt, FILE *fp)
{} {}
/* -------------------------------------------------------------------------- */
char * char *
if_inpdeck(struct line *deck, char **tab) if_inpdeck(struct line *deck, char **tab)
{ {
return ((char *) 0); return ((char *) 0);
} }
/* -------------------------------------------------------------------------- */
int int
if_option(char *ckt, char *name, int type, char *value) if_option(char *ckt, char *name, int type, char *value)
{ {
return 0; return 0;
} }
/* -------------------------------------------------------------------------- */
void if_cktfree(char *ckt, char *tab) void if_cktfree(char *ckt, char *tab)
{} {}
/* -------------------------------------------------------------------------- */
void if_setndnames(char *line) void if_setndnames(char *line)
{} {}
/* -------------------------------------------------------------------------- */
char * char *
if_errstring(int code) if_errstring(int code)
{ {
return ("spice error"); return ("spice error");
} }
/* -------------------------------------------------------------------------- */
void void
if_setparam(char *ckt, char *name, char *param, struct variable *val) if_setparam(char *ckt, char *name, char *param, struct variable *val)
{} {}
/* -------------------------------------------------------------------------- */
bool bool
if_tranparams(struct circ *ckt, double *start, double *stop, double *step) if_tranparams(struct circ *ckt, double *start, double *stop, double *step)
{ {
return (FALSE); return (FALSE);
} }
/* -------------------------------------------------------------------------- */
struct variable * struct variable *
if_getstat(char *n, char *c) if_getstat(char *n, char *c)
{ {
@ -237,7 +251,7 @@ void com_savesnap(wordlist *wl) { return; }
#ifndef SIMULATOR #ifndef SIMULATOR
#ifdef XSPICE #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_Tiein_t g_ipc;
Ipc_Status_t ipc_send_errchk(void ) { Ipc_Status_t ipc_send_errchk(void ) {
Ipc_Status_t x=0; Ipc_Status_t x=0;
@ -278,7 +292,7 @@ double CONSTe;
IFfrontEnd *SPfrontEnd = NULL; IFfrontEnd *SPfrontEnd = NULL;
int DEVmaxnum = 0; int DEVmaxnum = 0;
/* -------------------------------------------------------------------------- */
int SIMinit(IFfrontEnd *frontEnd, IFsimulator **simulator) int SIMinit(IFfrontEnd *frontEnd, IFsimulator **simulator)
{ {
#ifdef SIMULATOR #ifdef SIMULATOR
@ -307,6 +321,7 @@ int SIMinit(IFfrontEnd *frontEnd, IFsimulator **simulator)
} }
/* -------------------------------------------------------------------------- */
/* Shutdown gracefully. */ /* Shutdown gracefully. */
int int
shutdown(int exitval) shutdown(int exitval)
@ -322,6 +337,8 @@ shutdown(int exitval)
exit (exitval); exit (exitval);
} }
/* -------------------------------------------------------------------------- */
#ifdef HAVE_GNUREADLINE #ifdef HAVE_GNUREADLINE
/* Adapted ../lib/cp/lexical.c:prompt() for GNU Readline -- Andrew Veliath <veliaa@rpi.edu> */ /* Adapted ../lib/cp/lexical.c:prompt() for GNU Readline -- Andrew Veliath <veliaa@rpi.edu> */
static char * static char *
@ -340,15 +357,15 @@ prompt()
s = cp_altprompt; s = cp_altprompt;
while (*s) { while (*s) {
switch (strip(*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++; s++;
} }
@ -356,55 +373,51 @@ prompt()
return pbuf; return pbuf;
} }
/* -------------------------------------------------------------------------- */
/* Process device events in Readline's hook since there is no where /* Process device events in Readline's hook since there is no where
else to do it now - AV */ 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 }; static REQUEST reqst = { checkup_option, 0 };
Input(&reqst, NULL); Input(&reqst, NULL);
return 0; return 0;
} }
/* -------------------------------------------------------------------------- */
/* Added GNU Readline Support -- Andrew Veliath <veliaa@rpi.edu> */ /* Added GNU Readline Support -- Andrew Veliath <veliaa@rpi.edu> */
void app_rl_readlines() void app_rl_readlines()
{ {
char *line, *expanded_line; 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) { 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 */ /* History gets written in ../fte/misccoms.c com_quit */
} }
#endif /* HAVE_GNUREADLINE */ #endif /* HAVE_GNUREADLINE */
/* -------------------------------------------------------------------------- */
void void
show_help(void) show_help(void)
{ {
@ -426,6 +439,7 @@ show_help(void)
"Report bugs to %s.\n", cp_program, Bug_Addr); "Report bugs to %s.\n", cp_program, Bug_Addr);
} }
/* -------------------------------------------------------------------------- */
void void
show_version(void) show_version(void)
{ {
@ -438,6 +452,7 @@ show_version(void)
" The NGSpice Project\n", cp_program, PACKAGE, VERSION); " The NGSpice Project\n", cp_program, PACKAGE, VERSION);
} }
/* -------------------------------------------------------------------------- */
void void
append_to_stream(FILE *dest, FILE *source) append_to_stream(FILE *dest, FILE *source)
{ {
@ -500,6 +515,8 @@ main(int argc, char **argv)
FILE *fp; FILE *fp;
FILE *circuit_file; FILE *circuit_file;
#ifdef TRACE #ifdef TRACE
/* this is used to detect memory leaks during debugging */ /* this is used to detect memory leaks during debugging */
/* added by SDB during debug . . . . */ /* added by SDB during debug . . . . */
@ -524,8 +541,8 @@ main(int argc, char **argv)
application_name = argv[0]; application_name = argv[0];
else else
++application_name; ++application_name;
#endif
#endif /* HAVE_GNUREADLINE */
#ifdef PARALLEL_ARCH #ifdef PARALLEL_ARCH
PBEGIN_(argc, argv); PBEGIN_(argc, argv);
ARCHme = NODEID_(); ARCHme = NODEID_();
@ -553,8 +570,7 @@ main(int argc, char **argv)
#ifdef MALLOCTRACE #ifdef MALLOCTRACE
mallocTraceInit("malloc.out"); mallocTraceInit("malloc.out");
#endif #endif
#if defined (HAVE_ISATTY) && !defined(HAS_WINDOWS)
#if defined(HAVE_ISATTY) && !defined(HAS_WINDOWS)
istty = (bool) isatty(fileno(stdin)); istty = (bool) isatty(fileno(stdin));
#endif #endif
@ -571,7 +587,7 @@ main(int argc, char **argv)
srandom(getpid()); srandom(getpid());
/* --- Process command line options --- */
while (1) { while (1) {
int option_index = 0; int option_index = 0;
static struct option long_options[] = { static struct option long_options[] = {
@ -681,7 +697,7 @@ main(int argc, char **argv)
default: default:
printf ("?? getopt returned character code 0%o ??\n", c); printf ("?? getopt returned character code 0%o ??\n", c);
} }
}
} /* --- End of command line option processing --- */
#ifdef SIMULATOR #ifdef SIMULATOR
@ -712,7 +728,7 @@ main(int argc, char **argv)
ft_cpinit(); ft_cpinit();
/* To catch interrupts during .spiceinit... */ /* To catch interrupts during .spiceinit... */
if (setjmp(jbuf) == 1) {
if (sigsetjmp(jbuf, 1) == 1) {
fprintf(cp_err, "Warning: error executing .spiceinit.\n"); fprintf(cp_err, "Warning: error executing .spiceinit.\n");
if (!ft_batchmode) if (!ft_batchmode)
goto bot; goto bot;
@ -720,13 +736,13 @@ main(int argc, char **argv)
/* Set up signal handling */ /* Set up signal handling */
if (!ft_batchmode) { 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); signal(SIGTSTP, sigstop);
#endif #endif
} }
@ -761,9 +777,9 @@ main(int argc, char **argv)
#define INITSTR "/.spiceinit" #define INITSTR "/.spiceinit"
#ifdef HAVE_ASPRINTF #ifdef HAVE_ASPRINTF
asprintf(&s, "%s%s", pw->pw_dir,INITSTR); 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 */ #endif /* HAVE_ASPRINTF */
if (access(s, 0) == 0) if (access(s, 0) == 0)
@ -800,7 +816,7 @@ bot:
* build a circuit for this file. If this is in server mode, don't * build a circuit for this file. If this is in server mode, don't
* process any of these args. */ * process any of these args. */
if (setjmp(jbuf) == 1)
if (sigsetjmp(jbuf, 1) == 1)
goto evl; goto evl;
@ -846,7 +862,7 @@ bot:
} }
if (ft_batchmode && err) if (ft_batchmode && err)
shutdown(EXIT_BAD); shutdown(EXIT_BAD);
}
} /* --- if (!ft_servermode && !ft_nutmeg) --- */
if (!gotone && ft_batchmode && !ft_nutmeg) if (!gotone && ft_batchmode && !ft_nutmeg)
inp_spsource(circuit_file, FALSE, (char *) NULL); inp_spsource(circuit_file, FALSE, (char *) NULL);
@ -857,7 +873,8 @@ evl:
* so exit. */ * so exit. */
bool st = FALSE; bool st = FALSE;
(void) setjmp(jbuf);
(void) sigsetjmp(jbuf, 1);
if (st == TRUE) { if (st == TRUE) {
shutdown(EXIT_BAD); shutdown(EXIT_BAD);
@ -878,7 +895,7 @@ evl:
* save too much. */ * save too much. */
cp_interactive = FALSE; cp_interactive = FALSE;
if (rflag) { if (rflag) {
/* saj done already in inp_spsource ft_dotsaves();*/
/* saj done already in inp_spsource ft_dotsaves();*/
error2 = ft_dorun(ft_rawfile); error2 = ft_dorun(ft_rawfile);
if (ft_cktcoms(TRUE) || error2) if (ft_cktcoms(TRUE) || error2)
shutdown(EXIT_BAD); shutdown(EXIT_BAD);
@ -892,15 +909,34 @@ evl:
"no simulations run\n"); "no simulations run\n");
shutdown(EXIT_BAD); shutdown(EXIT_BAD);
} }
} else {
(void) setjmp(jbuf);
} /* --- if (ft_batchmode) --- */
else {
cp_interactive = TRUE; cp_interactive = TRUE;
#ifdef HAVE_GNUREADLINE #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) ; while (cp_evloop((char *) NULL) == 1) ;
#endif /* ifelse HAVE_GNUREADLINE */
}
#endif /* ifelse HAVE_GNUREADLINE */
} /* --- else (if (ft_batchmode)) --- */
#else /* ~ SIMULATOR */ #else /* ~ SIMULATOR */
@ -915,16 +951,16 @@ evl:
evl: evl:
/* Nutmeg "main" */ /* Nutmeg "main" */
(void) setjmp(jbuf);
(void) sigsetjmp(jbuf, 1);
cp_interactive = TRUE; cp_interactive = TRUE;
#ifdef HAVE_GNUREADLINE
app_rl_readlines();
#else
while (cp_evloop((char *) NULL) == 1) ; while (cp_evloop((char *) NULL) == 1) ;
#endif /* ifelse HAVE_GNUREADLINE */
#endif /* ~ SIMULATOR */ #endif /* ~ SIMULATOR */
shutdown(EXIT_NORMAL); shutdown(EXIT_NORMAL);
return EXIT_NORMAL; return EXIT_NORMAL;
} }

4
src/misc/Makefile.am

@ -27,7 +27,9 @@ libmisc_a_SOURCES = \
tilde.h \ tilde.h \
misc_time.c \ misc_time.c \
misc_time.h \ misc_time.h \
wlist.c
wlist.c \
util.c \
util.h
## Note that the getopt files get compiled unconditionnaly but some ## Note that the getopt files get compiled unconditionnaly but some
## magic #define away the body of their own code if the compilation environment ## magic #define away the body of their own code if the compilation environment

5
src/misc/ivars.c

@ -40,7 +40,7 @@ mkvar(char **p, char *path_prefix, char *var_dir, char *env_var)
asprintf(p, "%s", buffer); asprintf(p, "%s", buffer);
else else
asprintf(p, "%s%s%s", path_prefix, DIR_PATHSEP, var_dir); asprintf(p, "%s%s%s", path_prefix, DIR_PATHSEP, var_dir);
#else /* ~ HAVE_ASPRINTF */ /* va: we use tmalloc */
#else /* ~ HAVE_ASPRINTF */
if (buffer){ if (buffer){
*p = (char *) tmalloc(strlen(buffer)+1); *p = (char *) tmalloc(strlen(buffer)+1);
sprintf(*p,"%s",buffer); sprintf(*p,"%s",buffer);
@ -48,7 +48,7 @@ mkvar(char **p, char *path_prefix, char *var_dir, char *env_var)
} }
else{ else{
*p = (char *) tmalloc(strlen(path_prefix) + *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); sprintf(*p, "%s%s%s", path_prefix, DIR_PATHSEP, var_dir);
/* asprintf(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_Exec_Dir, "SPICE_EXEC_DIR");
env_overr(&Spice_Lib_Dir, "SPICE_LIB_DIR"); env_overr(&Spice_Lib_Dir, "SPICE_LIB_DIR");
mkvar(&News_File, Spice_Lib_Dir, "news", "SPICE_NEWS"); mkvar(&News_File, Spice_Lib_Dir, "news", "SPICE_NEWS");
mkvar(&Default_MFB_Cap, Spice_Lib_Dir, "mfbcap", "SPICE_MFBCAP"); mkvar(&Default_MFB_Cap, Spice_Lib_Dir, "mfbcap", "SPICE_MFBCAP");
mkvar(&Help_Path, Spice_Lib_Dir, "helpdir", "SPICE_HELP_DIR"); mkvar(&Help_Path, Spice_Lib_Dir, "helpdir", "SPICE_HELP_DIR");

89
src/misc/string.c

@ -192,8 +192,13 @@ register char *p, *s;
#endif /* CIDER */ #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 * char *
gettok(char **s) gettok(char **s)
{ {
@ -224,9 +229,10 @@ gettok(char **s)
/*-------------------------------------------------------------------------* /*-------------------------------------------------------------------------*
* gettok_noparens was added by SDB on 4.21.2003. * 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 * char *
gettok_noparens(char **s) gettok_noparens(char **s)
@ -235,24 +241,78 @@ gettok_noparens(char **s)
int i = 0; int i = 0;
char c; char c;
while (isspace(**s))
(*s)++;
while ( isspace(**s) )
(*s)++; /* iterate over whitespace */
if (!**s) 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++] = *(*s)++;
} }
buf[i] = '\0'; 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)); return (copy(buf));
} }
/*-------------------------------------------------------------------------* /*-------------------------------------------------------------------------*
* get_l_paren iterates the pointer forward in a string until it hits * 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 * 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 int
get_l_paren(char **s) 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 * 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 * 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 int
get_r_paren(char **s) get_r_paren(char **s)

106
src/misc/tilde.c

@ -15,6 +15,7 @@ Modified: 2002 R. Oktas, <roktas@omu.edu.tr>
#include <pwd.h> #include <pwd.h>
#endif #endif
/* XXX To prevent a name collision with `readline's `tilde_expand', /* XXX To prevent a name collision with `readline's `tilde_expand',
the original name: `tilde_expand' has changed to `tildexpand'. This the original name: `tilde_expand' has changed to `tildexpand'. This
situation naturally brings to mind that `tilde_expand' could be used situation naturally brings to mind that `tilde_expand' could be used
@ -25,70 +26,13 @@ Modified: 2002 R. Oktas, <roktas@omu.edu.tr>
not behave this way, IMHO. Anyway... Don't care for the moment, may not behave this way, IMHO. Anyway... Don't care for the moment, may
be in the future. -- ro */ 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 * char *
tildexpand(char *string) tildexpand(char *string)
{ {
char buf[BSIZE_SP]; char buf[BSIZE_SP];
char *result, *k, c; char *result, *k, c;
if (!string) if (!string)
return NULL; return NULL;
@ -101,42 +45,44 @@ tildexpand(char *string)
string += 1; string += 1;
if (!*string || *string == '/') { 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 #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 { } else {
struct passwd *pw;
struct passwd *pw;
k = buf; k = buf;
while ((c = *string) && c != '/') while ((c = *string) && c != '/')
*k++ = c, string++; *k++ = c, string++;
*k = 0; *k = 0;
pw = getpwnam(buf); pw = getpwnam(buf);
if (pw)
result = pw->pw_dir;
#endif
if (pw)
result = pw->pw_dir;
#endif
} }
if (result) { if (result) {
#ifdef HAVE_PWD_H #ifdef HAVE_PWD_H
strcpy(buf, result);
strcpy(buf, result);
if (*string) if (*string)
strcat(buf, string); strcat(buf, string);
return copy(buf);
return copy(buf);
} else } else
return NULL; 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
} }
#endif /* HAVE_GNUREADLINE */

5
src/misc/tilde.h

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

151
src/misc/util.c

@ -0,0 +1,151 @@
/*************
* Various utility functions.
* 2002 R. Oktas, <roktas@omu.edu.tr>
************/
#ifdef HAVE_STRING_H
#include <string.h>
#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);
}

12
src/misc/util.h

@ -0,0 +1,12 @@
/*************
* Header file for util.c
* 2002 R. Oktas, <roktas@omu.edu.tr>
************/
#ifndef UTIL_H_INCLUDED
#define UTIL_H_INCLUDED
char *canonicalize_pathname(char *path);
char *absolute_pathname(char *string, char *dot_path);
#endif

3
src/nghelp.c

@ -28,6 +28,7 @@ char *Bug_Addr = "";
char *Spice_Host = ""; char *Spice_Host = "";
char *Spiced_Log = ""; char *Spiced_Log = "";
/* dummy declaration so CP.a doesn't pull in lexical.o and other objects */ /* dummy declaration so CP.a doesn't pull in lexical.o and other objects */
bool cp_interactive = FALSE; bool cp_interactive = FALSE;
@ -110,5 +111,5 @@ cp_getvar(char *n, int t, void *r)
char * char *
cp_tildexpand(char *s) cp_tildexpand(char *s)
{ {
return tilde_expand(s);
return tildexpand(s);
} }

5
src/ngmultidec.c

@ -14,6 +14,7 @@ Author: 1990 Jaijeet Roychowdury
#undef DEBUG_LEVEL1 #undef DEBUG_LEVEL1
/* `-u' option showing the usage help is changed to `-h'. -- ro */
extern void usage(); extern void usage();
extern void comments(); extern void comments();
@ -102,7 +103,7 @@ int
use_opt = 1; use_opt = 1;
gotnum=1; gotnum=1;
break; break;
case 'u':
case 'h':
usage(pname); usage(pname);
exit(1); exit(1);
break; break;
@ -350,7 +351,7 @@ fprintf(stderr,"Usage: %s -l<line-inductance> -c<line-capacitance>\n",argv[0]);
fprintf(stderr," -r<line-resistance> -g<line-conductance> \n"); fprintf(stderr," -r<line-resistance> -g<line-conductance> \n");
fprintf(stderr," -k<inductive coeff. of coupling> \n"); fprintf(stderr," -k<inductive coeff. of coupling> \n");
fprintf(stderr," -x<line-to-line capacitance> -o<subckt-name> \n"); fprintf(stderr," -x<line-to-line capacitance> -o<subckt-name> \n");
fprintf(stderr," -n<number of conductors> -L<length> -u\n");
fprintf(stderr," -n<number of conductors> -L<length> -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,"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"); fprintf(stderr,"See \"Efficient Transient Simulation of Lossy Interconnect\",\n");

Loading…
Cancel
Save