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

This commit is contained in:
pnenzi 2004-01-10 21:39:36 +00:00
parent 4fa3c84d99
commit b03a70760b
27 changed files with 682 additions and 362 deletions

View File

@ -1,9 +1,23 @@
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
distclean without barfing. (Stuart Brorson <sdb@cloud9.net>).
* configure.in
src/xspice/cmpp/Makefile src/xspice/cmpp/Makefile.in:
Make configure automatically set paths for lex yacc and

View File

@ -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 \

View File

@ -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 <veliaa@rpi.edu> */
{
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;
}

View File

@ -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();

View File

@ -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 <ftedev.h>
#include <fteinput.h>
#include <graph.h>
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

View File

@ -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);
}

View File

@ -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;
}
/*-------------------------------------------------------------------------*
* *
*-------------------------------------------------------------------------*/

View File

@ -15,12 +15,10 @@ Author: 1985 Wayne A. Christopher, U. C. Berkeley CAD Group
#include "hcomp.h"
#include "variable.h"
#ifdef HAVE_GNUREADLINE
#include <readline/readline.h>
#include <readline/history.h>
extern int gnu_history_lines;
extern char gnu_history_file[];
#endif
static void byemesg(void);
@ -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 <veliaa@rpi.edu> */
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;
}

View File

@ -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);

View File

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

View File

@ -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

View File

@ -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;
}

View File

@ -18,10 +18,15 @@ Author: 1985 Wayne A. Christopher, U. C. Berkeley CAD Group
#include <signal.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
* 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

View File

@ -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) {

View File

@ -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;

View File

@ -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

View File

@ -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);

View File

@ -5,7 +5,7 @@
Author: 1985 Wayne A. Christopher
The main routine for ngspice */
#include <ngspice.h>
#include <stdio.h>
@ -30,7 +30,7 @@
#include <misc/getopt.h>
#include <frontend/resource.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 */
#ifdef XSPICE
@ -49,7 +49,10 @@
#include <readline/readline.h>
#include <readline/history.h>
#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 <veliaa@rpi.edu> */
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 <veliaa@rpi.edu> */
void app_rl_readlines()
{
char *line, *expanded_line;
strcpy(gnu_history_file, getenv("HOME"));
strcat(gnu_history_file, "/.");
strcat(gnu_history_file, application_name);
strcat(gnu_history_file, "_history");
using_history();
read_history(gnu_history_file);
rl_readline_name = application_name;
rl_instream = cp_in;
rl_outstream = cp_out;
rl_event_hook = rl_event_func;
/* 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;
}

View File

@ -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

View File

@ -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");

View File

@ -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)

View File

@ -15,6 +15,7 @@ Modified: 2002 R. Oktas, <roktas@omu.edu.tr>
#include <pwd.h>
#endif
/* XXX To prevent a name collision with `readline's `tilde_expand',
the original name: `tilde_expand' has changed to `tildexpand'. This
situation naturally brings to mind that `tilde_expand' could be used
@ -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
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 */

View File

@ -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

151
src/misc/util.c Normal file
View File

@ -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 Normal file
View File

@ -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

View File

@ -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);
}

View File

@ -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<line-inductance> -c<line-capacitance>\n",argv[0]);
fprintf(stderr," -r<line-resistance> -g<line-conductance> \n");
fprintf(stderr," -k<inductive coeff. of coupling> \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,"See \"Efficient Transient Simulation of Lossy Interconnect\",\n");