From 01bdd44ef985b28f2c53e96cbc4393b7be0ee3b2 Mon Sep 17 00:00:00 2001 From: Holger Vogt Date: Fri, 15 Sep 2023 23:41:12 +0200 Subject: [PATCH 01/15] Modify the previous commit a616a0abe: no spaces in the first column --- src/frontend/plotting/gnuplot.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) 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; From dbc5042263d1c35e8ab1624e36882b53f3f83170 Mon Sep 17 00:00:00 2001 From: Holger Vogt Date: Fri, 15 Sep 2023 23:42:08 +0200 Subject: [PATCH 02/15] Prevent a crash if port cntrl is set to NULL --- src/xspice/icm/analog/delay/cfunc.mod | 16 ++++++++++------ 1 file changed, 10 insertions(+), 6 deletions(-) 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; } From 62471ecede31b358afaa5dd1bcec70b97330dd1c Mon Sep 17 00:00:00 2001 From: Giles Atkinson <“gatk555@gmail.com”> Date: Tue, 12 Sep 2023 08:18:19 +0100 Subject: [PATCH 03/15] Fix two bugs in cmpp: an unmatched right bracket in cfunc.mod causes an infinite parsing loop (mod_yacc.y) and XSPICE macros are replaced in string literals (mod_lex.l). --- src/xspice/cmpp/mod_lex.l | 2 ++ src/xspice/cmpp/mod_yacc.y | 17 ++++++----------- 2 files changed, 8 insertions(+), 11 deletions(-) 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 From b034332e84d66fe0dd29fe60db45d9d9dc2087a1 Mon Sep 17 00:00:00 2001 From: Holger Vogt Date: Tue, 19 Sep 2023 14:57:22 +0200 Subject: [PATCH 04/15] Improve warning message during evaluating .probe --- src/frontend/inpc_probe.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/frontend/inpc_probe.c b/src/frontend/inpc_probe.c index 825eef914..fcced38da 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", inst); tfree(subcktname); tfree(inst); return tprintf("n%s", numberstr); From f3eb46e76da2076f3e6614bf6e74c7cb5818fddb Mon Sep 17 00:00:00 2001 From: Holger Vogt Date: Sat, 23 Sep 2023 16:45:35 +0200 Subject: [PATCH 05/15] Fix bug in fprintf --- src/frontend/inpc_probe.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/frontend/inpc_probe.c b/src/frontend/inpc_probe.c index fcced38da..730ce30f0 100644 --- a/src/frontend/inpc_probe.c +++ b/src/frontend/inpc_probe.c @@ -1053,7 +1053,7 @@ static char *get_terminal_name(char* element, char *numberstr, NGHASHPTR instanc char* instline = xcard->line; char* inst = gettok(&instline); 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", inst); + fprintf(stderr, " Is the model missing? .probe cannot determine subcircuit pin names.\n"); tfree(subcktname); tfree(inst); return tprintf("n%s", numberstr); From 930bd12dc2de77fa91ec616ac665a4cdbf4821ab Mon Sep 17 00:00:00 2001 From: Holger Vogt Date: Sat, 23 Sep 2023 16:51:28 +0200 Subject: [PATCH 06/15] Enable degug mode in shared ngspice with KLU --- visualc/sharedspice.vcxproj | 1 + 1 file changed, 1 insertion(+) 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) From 423f9a9db26ea8ee76ed57965d80b7e39f31e3a0 Mon Sep 17 00:00:00 2001 From: Giles Atkinson <“gatk555@gmail.com”> Date: Tue, 12 Sep 2023 16:17:13 +0100 Subject: [PATCH 07/15] Fix a build bug for XSPICE: files generated for code models are not removed when doing 'make clean' from release/src/xspice or above. --- src/xspice/icm/GNUmakefile.in | 4 ++++ 1 file changed, 4 insertions(+) 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 : From 588116af483416a1cd99526627760a44473e5d0c Mon Sep 17 00:00:00 2001 From: Giles Atkinson <“gatk555@gmail.com”> Date: Tue, 19 Sep 2023 18:29:10 +0100 Subject: [PATCH 08/15] Fix a bug in the "help" command. Some commands have no action function, so the function pointer should not be used to detect the end of the table. Use the command name instead. --- src/frontend/com_help.c | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) 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; From 41c61604c5ca3559e76bedfec6ede996effe29c9 Mon Sep 17 00:00:00 2001 From: Giles Atkinson <“gatk555@gmail.com”> Date: Fri, 22 Sep 2023 21:41:04 +0100 Subject: [PATCH 09/15] Handle SIGTTIN and SIGTTOU on Unix-like OSs with X11 graphics. That makes it possible to push ngspice into the background while plot windows are open: the windows remain responsive. Discussion on ngspice-users, starting 2023-09-01, title: "`quit` in Interactive Mode." Also restore terminal state when forcing exit with SIGINT (control-C). --- src/frontend/control.c | 3 ++- src/frontend/signal_handler.c | 34 ++++++++++++++++++++++++++++++++-- src/frontend/signal_handler.h | 1 + src/include/ngspice/cpextern.h | 3 ++- src/main.c | 31 ++++++++++++++++++++++++++++--- 5 files changed, 65 insertions(+), 7 deletions(-) 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/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/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 } From a70e708114df805b01fa5b4b472a10827c5d7d33 Mon Sep 17 00:00:00 2001 From: Giles Atkinson <“gatk555@gmail.com”> Date: Sat, 23 Sep 2023 08:50:47 +0100 Subject: [PATCH 10/15] Make special interpreter variable "noglob" behave as documented: globbing is off by default. An incompatible change, but previous behaviour can be restored by "unset noglob" in .spiceinit. --- src/frontend/parser/glob.c | 3 +++ tests/regression/misc/dollar-1.cir | 2 +- tests/regression/misc/dollar-1.out | 2 +- 3 files changed, 5 insertions(+), 2 deletions(-) diff --git a/src/frontend/parser/glob.c b/src/frontend/parser/glob.c index 9353a7235..caefafe48 100644 --- a/src/frontend/parser/glob.c +++ b/src/frontend/parser/glob.c @@ -86,6 +86,9 @@ static void tilde_expand_word(wordlist *wl_node); * name of a "HOME" directory are supported. ?*[] are not */ wordlist *cp_doglob(wordlist *wlist) { + if (cp_noglob) + return wlist; + /* Expand {a,b,c} */ { wordlist *wl = wlist; diff --git a/tests/regression/misc/dollar-1.cir b/tests/regression/misc/dollar-1.cir index 8fe009293..31d518c96 100644 --- a/tests/regression/misc/dollar-1.cir +++ b/tests/regression/misc/dollar-1.cir @@ -5,7 +5,7 @@ v1 1 0 dc = 0 .control set foo = "" -echo "TEST:" ">{$foo}< should be ><" +echo "TEST:" ">{$foo}< should be >{}<" set foo = ( 1 2 3 ) set bar = 2 diff --git a/tests/regression/misc/dollar-1.out b/tests/regression/misc/dollar-1.out index 278b1394e..be06413ae 100644 --- a/tests/regression/misc/dollar-1.out +++ b/tests/regression/misc/dollar-1.out @@ -1,7 +1,7 @@ Circuit: test for regression of already fixed bugs -TEST: >< should be >< +TEST: >{}< should be >{}< TEST: >1< should be >1< TEST: >2< should be >2< TEST: 1 2 3 baz bar From 2790fd68bb4783b194a6bfdf3a83b70bff3261b5 Mon Sep 17 00:00:00 2001 From: Giles Atkinson <“gatk555@gmail.com”> Date: Mon, 25 Sep 2023 08:08:30 +0100 Subject: [PATCH 11/15] Make the special "noglob" variable work. To preserve previous behaviour change the default value from true to undefined (meaning false). Also fix a misleading comment in glob.c. --- src/frontend/cpitf.c | 1 - src/frontend/parser/glob.c | 6 +++--- src/frontend/variable.c | 2 +- 3 files changed, 4 insertions(+), 5 deletions(-) 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/parser/glob.c b/src/frontend/parser/glob.c index caefafe48..2a1566cc3 100644 --- a/src/frontend/parser/glob.c +++ b/src/frontend/parser/glob.c @@ -79,11 +79,11 @@ 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) 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; From a5704c8453426f65cccbb3247ba0645f06d26b44 Mon Sep 17 00:00:00 2001 From: Giles Atkinson <“gatk555@gmail.com”> Date: Mon, 25 Sep 2023 18:00:50 +0100 Subject: [PATCH 12/15] Fix a "make check" failure, by restoring the dollar-1 test to its state before a70e708 as that change is no longer needed after 2790fd6. --- tests/regression/misc/dollar-1.cir | 2 +- tests/regression/misc/dollar-1.out | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/tests/regression/misc/dollar-1.cir b/tests/regression/misc/dollar-1.cir index 31d518c96..8fe009293 100644 --- a/tests/regression/misc/dollar-1.cir +++ b/tests/regression/misc/dollar-1.cir @@ -5,7 +5,7 @@ v1 1 0 dc = 0 .control set foo = "" -echo "TEST:" ">{$foo}< should be >{}<" +echo "TEST:" ">{$foo}< should be ><" set foo = ( 1 2 3 ) set bar = 2 diff --git a/tests/regression/misc/dollar-1.out b/tests/regression/misc/dollar-1.out index be06413ae..278b1394e 100644 --- a/tests/regression/misc/dollar-1.out +++ b/tests/regression/misc/dollar-1.out @@ -1,7 +1,7 @@ Circuit: test for regression of already fixed bugs -TEST: >{}< should be >{}< +TEST: >< should be >< TEST: >1< should be >1< TEST: >2< should be >2< TEST: 1 2 3 baz bar From 76f837b0b70b0d359a8cd9559b6d2ac05b552a1a Mon Sep 17 00:00:00 2001 From: Holger Vogt Date: Wed, 27 Sep 2023 15:49:37 +0200 Subject: [PATCH 13/15] skip all pre-processing for expanded input files created by 'listing r' --- src/frontend/inpcom.c | 4 ++++ 1 file changed, 4 insertions(+) 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; From e449c894ce9847d6ffc6594c24e386c2daf0026c Mon Sep 17 00:00:00 2001 From: Holger Vogt Date: Wed, 27 Sep 2023 15:51:16 +0200 Subject: [PATCH 14/15] Prepend title line by '*' if printed by 'listing r'. This allows skipping all pre-processing. --- src/frontend/inp.c | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) 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); From 28b495318dc73ef1f6a7059e48cfa194e86a8b8a Mon Sep 17 00:00:00 2001 From: Holger Vogt Date: Thu, 28 Sep 2023 10:05:31 +0200 Subject: [PATCH 15/15] Update to command 'wrnodev': Prevent crash if tran is not (yet) run. Open output file only when data are available. Enhanced comment and warning message. --- src/frontend/com_wr_ic.c | 18 +++++++++++++----- 1 file changed, 13 insertions(+), 5 deletions(-) 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);