diff --git a/src/frontend/com_help.c b/src/frontend/com_help.c
index 1039ec386..d8ffebe6a 100644
--- a/src/frontend/com_help.c
+++ b/src/frontend/com_help.c
@@ -81,7 +81,7 @@ void com_help(wordlist *wl)
else {
while (wl != NULL) {
struct comm *c;
- for (c = &cp_coms[0]; c->co_func != NULL; c++)
+ for (c = &cp_coms[0]; c->co_comname != NULL; c++) {
if (eq(wl->wl_word, c->co_comname)) {
out_printf("%s ", c->co_comname);
out_printf(c->co_help, cp_program);
@@ -90,7 +90,8 @@ void com_help(wordlist *wl)
out_send("\n");
break;
}
- if (c->co_func == NULL) {
+ }
+ if (c->co_comname == NULL) {
/* See if this is aliased. */
struct alias *al;
diff --git a/src/frontend/com_wr_ic.c b/src/frontend/com_wr_ic.c
index cad8454fa..db9ebf1b5 100644
--- a/src/frontend/com_wr_ic.c
+++ b/src/frontend/com_wr_ic.c
@@ -18,6 +18,8 @@ void com_wric(wordlist* wl);
/* Print the current node status to a file with format
.ic V(node) = value
+ during a transient simulation which has been stopped,
+ by command 'stop' and which may continue by 'resume'.
*/
void
com_wric(wordlist* wl) {
@@ -32,11 +34,6 @@ com_wric(wordlist* wl) {
else
file = "dot_ic_out.txt";
- if ((fp = fopen(file, "w")) == NULL) {
- perror(file);
- return;
- }
-
if (!ft_curckt) {
fprintf(cp_err, "Error: there aren't any circuits loaded.\n");
return;
@@ -48,6 +45,17 @@ com_wric(wordlist* wl) {
ckt = ft_curckt->ci_ckt;
+ if (!ckt->CKTrhsOld) {
+ fprintf(stderr, "\nWarning: Command wrnodev is ignored!\n");
+ fprintf(stderr, " You need to execute stop ... tran ... resume\n\n");
+ return;
+ }
+
+ if ((fp = fopen(file, "w")) == NULL) {
+ perror(file);
+ return;
+ }
+
fprintf(fp, "* Intermediate Transient Solution\n");
fprintf(fp, "* Circuit: %s\n", ft_curckt->ci_name);
fprintf(fp, "* Recorded at simulation time: %g\n", ckt->CKTtime);
diff --git a/src/frontend/control.c b/src/frontend/control.c
index fb697f8e0..5c724ec12 100644
--- a/src/frontend/control.c
+++ b/src/frontend/control.c
@@ -615,9 +615,10 @@ getcommand(char *string)
#if !defined(HAVE_GNUREADLINE) && !defined(HAVE_BSDEDITLINE)
/* set cp_altprompt for use by the lexer - see parser/lexical.c */
cp_altprompt = get_alt_prompt();
+#else
+ cp_cwait = TRUE;
#endif /* !defined(HAVE_GNUREADLINE) && !defined(HAVE_BSDEDITLINE) */
- cp_cwait = TRUE;
wlist = cp_parse(string);
cp_cwait = FALSE;
if (cp_debug) {
diff --git a/src/frontend/cpitf.c b/src/frontend/cpitf.c
index 484b2ff49..ec92c981c 100644
--- a/src/frontend/cpitf.c
+++ b/src/frontend/cpitf.c
@@ -180,7 +180,6 @@ ft_cpinit(void)
}
cp_vset("prompt", CP_STRING, buf);
- cp_vset("noglob", CP_BOOL, &t);
cp_vset("brief", CP_BOOL, &t);
/* Make vectors from values in predefs[] for the current plot.
diff --git a/src/frontend/inp.c b/src/frontend/inp.c
index 9c5f0f405..a48e89724 100644
--- a/src/frontend/inp.c
+++ b/src/frontend/inp.c
@@ -179,8 +179,11 @@ com_listing(wordlist *wl)
} else {
if (type != LS_DECK && type != LS_RUNNABLE)
fprintf(cp_out, "\t%s\n\n", ft_curckt->ci_name);
- else if (type == LS_RUNNABLE)
+ else if (type == LS_RUNNABLE) {
fprintf(cp_out, "* expanded deck of %s\n", ft_curckt->ci_name);
+ fprintf(cp_out, "* %s\n", ft_curckt->ci_deck->line); /* title line with extra '*' */
+ ft_curckt->ci_deck = ft_curckt->ci_deck->nextcard; /* skip title */
+ }
inp_list(cp_out,
expand ? ft_curckt->ci_deck : ft_curckt->ci_origdeck,
ft_curckt->ci_options, type);
diff --git a/src/frontend/inpc_probe.c b/src/frontend/inpc_probe.c
index 825eef914..730ce30f0 100644
--- a/src/frontend/inpc_probe.c
+++ b/src/frontend/inpc_probe.c
@@ -1052,8 +1052,8 @@ static char *get_terminal_name(char* element, char *numberstr, NGHASHPTR instanc
if (!allsubs) {
char* instline = xcard->line;
char* inst = gettok(&instline);
- fprintf(stderr, "Warning: No .subckt line found during evaluating command .probe (...)!\n");
- fprintf(stderr, " failing instance: %s\n", inst);
+ fprintf(stderr, "Instance '%s' does not have an corresponding subcircuit '%s'!\n", inst, subcktname);
+ fprintf(stderr, " Is the model missing? .probe cannot determine subcircuit pin names.\n");
tfree(subcktname);
tfree(inst);
return tprintf("n%s", numberstr);
diff --git a/src/frontend/inpcom.c b/src/frontend/inpcom.c
index f5f1c1e73..97c822937 100644
--- a/src/frontend/inpcom.c
+++ b/src/frontend/inpcom.c
@@ -1009,6 +1009,10 @@ struct card *inp_readall(FILE *fp, const char *dir_name,
rv = inp_read(fp, 0, dir_name, comfile, intfile);
cc = rv.cc;
+ /* skip all pre-processing for expanded input files created by 'listing r' */
+ if (ciprefix("* expanded deck of", cc->line))
+ return cc;
+
/* files starting with *ng_script are user supplied command files */
if (cc && ciprefix("*ng_script", cc->line))
comfile = TRUE;
diff --git a/src/frontend/parser/glob.c b/src/frontend/parser/glob.c
index 9353a7235..2a1566cc3 100644
--- a/src/frontend/parser/glob.c
+++ b/src/frontend/parser/glob.c
@@ -79,13 +79,16 @@ static inline void strip_1st_char(wordlist *wl_node);
static void tilde_expand_word(wordlist *wl_node);
-/* For each word, go through two steps: expand the {}'s, and then do ?*[]
- * globbing in them. Sort after the second phase but not the first...
+/* For each word, go through two steps: expand the {}'s, and then do
+ * tilde-expansion in them (not available of Windows).
*
* Globbing of arbitrary levels of brace nesting and tilde expansion to the
- * name of a "HOME" directory are supported. ?*[] are not */
+ * name of a "HOME" directory are supported. File globbing (?*[]) is not */
wordlist *cp_doglob(wordlist *wlist)
{
+ if (cp_noglob)
+ return wlist;
+
/* Expand {a,b,c} */
{
wordlist *wl = wlist;
diff --git a/src/frontend/plotting/gnuplot.c b/src/frontend/plotting/gnuplot.c
index 00f94a220..27f727947 100644
--- a/src/frontend/plotting/gnuplot.c
+++ b/src/frontend/plotting/gnuplot.c
@@ -751,12 +751,12 @@ void ft_writesimple(double *xlims, double *ylims,
struct dvec* scale = v->v_scale;
/* If wr_singlescale is set, print scale name only in first column */
if (prscale)
- fprintf(file_data, " %s", scale->v_name);
+ fprintf(file_data, "%s ", scale->v_name);
if (isreal(v))
- fprintf(file_data, " %s", v->v_name);
+ fprintf(file_data, "%s ", v->v_name);
else
- fprintf(file_data, " %s %s", v->v_name, v->v_name);
+ fprintf(file_data, "%s %s ", v->v_name, v->v_name);
if (singlescale)
/* the following names are printed without scale vector names */
prscale = FALSE;
diff --git a/src/frontend/signal_handler.c b/src/frontend/signal_handler.c
index 058c3c352..4e72bfcf7 100644
--- a/src/frontend/signal_handler.c
+++ b/src/frontend/signal_handler.c
@@ -91,6 +91,7 @@ ft_sigintr(void)
if (interrupt_counter >= 3) {
fprintf(cp_err, "\nKilling, since %d interrupts have been requested\n\n", interrupt_counter);
+ cp_ccon(FALSE);
controlled_exit(1);
}
@@ -99,6 +100,7 @@ ft_sigintr(void)
}
/* here we jump to the start of command processing in main() after resetting everything. */
+ cp_background = FALSE;
LONGJMP(jbuf, 1);
}
@@ -112,6 +114,32 @@ sigfloat(int code)
LONGJMP(jbuf, 1);
}
+/* Shared handler for SIGTTIN and SIGTTOU. Restart event handling if caught
+ * attempting terminal IO as a background process.
+ */
+
+bool cp_background = FALSE;
+
+#ifdef SIGTTIN
+void
+sigttio(void)
+{
+ if (cp_cwait) {
+ /* Attempted command input/output on the terminal while in background.
+ * Set background flag and restart event loop.
+ */
+ cp_background = TRUE;
+ LONGJMP(jbuf, 1);
+ } else {
+ /* Non-command terminal IO in background. That should never happen.
+ * Stop.
+ */
+
+ (void) signal(SIGTSTP, SIG_DFL);
+ (void) kill(getpid(), SIGTSTP); /* This should stop us */
+ }
+}
+#endif
/* This should give a new prompt if cshpar is waiting for input. */
@@ -122,8 +150,10 @@ sigstop(void)
{
gr_clean();
cp_ccon(FALSE);
- (void) signal(SIGTSTP, SIG_DFL);
- (void) kill(getpid(), SIGTSTP); /* This should stop us */
+ if (!cp_background) {
+ (void) signal(SIGTSTP, SIG_DFL);
+ (void) kill(getpid(), SIGTSTP); /* This should stop us */
+ }
}
diff --git a/src/frontend/signal_handler.h b/src/frontend/signal_handler.h
index 7ef02c6da..66168d818 100644
--- a/src/frontend/signal_handler.h
+++ b/src/frontend/signal_handler.h
@@ -8,6 +8,7 @@
void ft_sigintr(void);
void sigfloat(int code);
+void sigttio(void);
void sigstop(void);
void sigcont(void);
void sigill(void);
diff --git a/src/frontend/variable.c b/src/frontend/variable.c
index ef28cffed..f4302e52c 100644
--- a/src/frontend/variable.c
+++ b/src/frontend/variable.c
@@ -19,7 +19,7 @@ Author: 1985 Wayne A. Christopher, U. C. Berkeley CAD Group
#include "variable.h"
-bool cp_noglob = TRUE;
+bool cp_noglob = FALSE;
bool cp_nonomatch = FALSE;
bool cp_noclobber = FALSE;
bool cp_ignoreeof = FALSE;
diff --git a/src/include/ngspice/cpextern.h b/src/include/ngspice/cpextern.h
index fedf26307..b051e0bcd 100644
--- a/src/include/ngspice/cpextern.h
+++ b/src/include/ngspice/cpextern.h
@@ -67,7 +67,8 @@ extern wordlist *cp_parse(char *string);
/* control.c */
-extern bool cp_cwait;
+extern bool cp_cwait; // Interactive and awaiting command input.
+extern bool cp_background; // Running in background.
extern bool cp_dounixcom;
extern char *cp_csep;
extern char * get_alt_prompt(void);
diff --git a/src/main.c b/src/main.c
index 653d3ddcb..e3999a865 100644
--- a/src/main.c
+++ b/src/main.c
@@ -681,10 +681,32 @@ app_rl_readlines(void)
history_set_pos(history_length);
if (SETJMP(jbuf, 1)) { /* Set location to jump to after handling SIGINT (ctrl-C) */
- ft_sigintr_cleanup();
+ if (!cp_background)
+ ft_sigintr_cleanup();
}
- line = readline(prompt());
+#if defined(SIGTTIN) && !defined(X_DISPLAY_MISSING)
+ if (cp_background) {
+ /* This process is running in the background, so reading from
+ * the terminal will fail. Instead, call the X11 input loop
+ * directly. It will process X11 events until terminal input
+ * is available, then return. If the process is still in background
+ * readline() will then cause another SIGTTIN and this loop
+ * will restart at SETJMP(). Such polling sees to be the only way
+ * to detect a return to the foreground.
+ *
+ * Global cp_cwait is set early so that SIGTTOU from output
+ * caused by clicking in a plot window will not stop the program.
+ */
+
+ cp_cwait = TRUE;
+ app_event_func(); // Direct call to process X11 input.
+ }
+#endif
+ cp_cwait = TRUE;
+ line = readline(cp_background ? NULL : prompt());
+ cp_cwait = FALSE;
+ cp_background = FALSE;
if (!line) {
cp_evloop("quit");
@@ -706,7 +728,6 @@ app_rl_readlines(void)
}
tfree(expanded_line);
}
-
tfree(line);
}
/* History gets written in ../fte/misccoms.c com_quit */
@@ -1189,6 +1210,10 @@ int main(int argc, char **argv)
#ifdef SIGTSTP
signal(SIGTSTP, (SIGNAL_FUNCTION) sigstop);
+#endif
+#ifdef SIGTTIN
+ signal(SIGTTIN, (SIGNAL_FUNCTION) sigttio);
+ signal(SIGTTOU, (SIGNAL_FUNCTION) sigttio);
#endif
}
diff --git a/src/xspice/cmpp/mod_lex.l b/src/xspice/cmpp/mod_lex.l
index 444a7d2ba..fbb86eb5b 100644
--- a/src/xspice/cmpp/mod_lex.l
+++ b/src/xspice/cmpp/mod_lex.l
@@ -89,6 +89,8 @@ Z [0-9A-Za-z_]
} while (ch != '\n');
}
+\"(\\.|[^"\\])*\" {return TOK_IDENTIFIER;} /* Literal string. */
+
ARGS {return TOK_ARGS;}
INIT {return TOK_INIT;}
CALLBACK {return TOK_CALLBACK;}
diff --git a/src/xspice/cmpp/mod_yacc.y b/src/xspice/cmpp/mod_yacc.y
index 4d3e00aa3..92433aca4 100644
--- a/src/xspice/cmpp/mod_yacc.y
+++ b/src/xspice/cmpp/mod_yacc.y
@@ -31,20 +31,13 @@ SUMMARY
INTERFACES
mod_yyparse() - Function 'yyparse()' is generated automatically
- by UNIX 'yacc' utility and then converted to
- 'mod_yyparse()' by UNIX 'sed' utility under
- direction of Makefile.
+ by UNIX 'yacc' utility. All yy* global names
+ are converted to mod_yy* by #define.
REFERENCED FILES
mod_lex.l
-NON-STANDARD FEATURES
-
- Names of functions generated by 'yacc' are translated by 'sed'
- under direction of the Makefile to prevent collisions with
- functions generated from ifs_yacc.y.
-
============================================================================*/
@@ -388,8 +381,8 @@ mod_file : /* empty */
c_code : /* empty */
| c_code c_char
| c_code macro
- /*| TOK_RPAREN {yyerror ("Unmatched )"); YYERROR;}
- | TOK_RBRACKET {yyerror ("Unmatched ]"); YYERROR;}*/
+ | TOK_RPAREN {yyerror ("Unmatched )"); YYERROR;}
+ | TOK_RBRACKET {yyerror ("Unmatched ]"); YYERROR;}
;
buffered_c_code : {init_buffer();} buffered_c_code2
@@ -416,10 +409,12 @@ buffered_c_char : TOK_IDENTIFIER {append (mod_yytext);}
c_char : TOK_IDENTIFIER {fputs (mod_yytext, mod_yyout);}
| TOK_MISC_C {fputs (mod_yytext, mod_yyout);}
| TOK_COMMA {fputs (mod_yytext, mod_yyout);}
+ | TOK_LBRACKET TOK_RBRACKET {fputs ("[]", mod_yyout);}
| TOK_LBRACKET
{putc ('[', mod_yyout);}
c_code TOK_RBRACKET
{putc (']', mod_yyout);}
+ | TOK_LPAREN TOK_RPAREN {fputs ("()", mod_yyout);}
| TOK_LPAREN
{putc ('(', mod_yyout);}
c_code TOK_RPAREN
diff --git a/src/xspice/icm/GNUmakefile.in b/src/xspice/icm/GNUmakefile.in
index 662c4103f..78e578e99 100644
--- a/src/xspice/icm/GNUmakefile.in
+++ b/src/xspice/icm/GNUmakefile.in
@@ -95,10 +95,14 @@ cm-descr := \
.SECONDARY : $(cm-gens)
+# When recursively making clean, cm-objs and cm-gens do not contain
+# the files generated for individual code models, as cmpp has already gone
+# and modlist and udnlist are empty. Those files are explicitly removed.
cm-clean :
-rm -f $(cm)/$(cm).cm
-rm -f $(cm-descr) $(cm-objs) $(cm-gens)
+ -rm -f $(cm)/*/*.o $(cm)/*/*.c $(cm)/*/.deps/*
-rm -f $(cm-deps)
cm-distclean :
diff --git a/src/xspice/icm/analog/delay/cfunc.mod b/src/xspice/icm/analog/delay/cfunc.mod
index a1bd95d83..0830bcc12 100644
--- a/src/xspice/icm/analog/delay/cfunc.mod
+++ b/src/xspice/icm/analog/delay/cfunc.mod
@@ -298,13 +298,17 @@ void cm_delay(ARGS)
delmin = loc->tdelmin;
delmax = loc->tdelmax;
- lcntrl = INPUT(cntrl);
- if (lcntrl < 0)
- lcntrl = 0.;
- else if (lcntrl > 1.)
- lcntrl = 1.;
-
if (PARAM(has_delay_cnt) == MIF_TRUE) {
+ if (!PORT_NULL(cntrl)) {
+ lcntrl = INPUT(cntrl);
+ if (lcntrl < 0)
+ lcntrl = 0.;
+ else if (lcntrl > 1.)
+ lcntrl = 1.;
+ }
+ else {
+ lcntrl = 0;
+ }
delay = (delmax - delmin) * lcntrl + delmin;
}
diff --git a/visualc/sharedspice.vcxproj b/visualc/sharedspice.vcxproj
index a1ccfb3ad..bdc35148e 100644
--- a/visualc/sharedspice.vcxproj
+++ b/visualc/sharedspice.vcxproj
@@ -227,6 +227,7 @@
false
+ KLU\x64\Debug;%(AdditionalLibraryDirectories)