From 87751ad0733ae0b49f153a4b025f5ce704568907 Mon Sep 17 00:00:00 2001 From: Holger Vogt Date: Sat, 21 Nov 2020 13:58:57 +0100 Subject: [PATCH] Make the ngSpice_Circ(char** circa) more robust: Error message when .end card is missing Reset if .end card is missing, to allow loading a netlist again. NULL as last element is no longer required, but .end card (this has been implicitedly assumed). Remove a bug that skippoed the last line (the .end card). --- src/frontend/inp.c | 16 +++++++++++++--- src/include/ngspice/sharedspice.h | 2 +- src/sharedspice.c | 16 +++++++++++++--- 3 files changed, 27 insertions(+), 7 deletions(-) diff --git a/src/frontend/inp.c b/src/frontend/inp.c index a4c2c3c11..139f6237b 100644 --- a/src/frontend/inp.c +++ b/src/frontend/inp.c @@ -55,7 +55,7 @@ static struct card *mc_deck = NULL; static struct card *recent_deck = NULL; static void cktislinear(CKTcircuit *ckt, struct card *deck); -void create_circbyline(char *line); +void create_circbyline(char *line, bool reset, bool lastline); static bool doedit(char *filename); static void dotifeval(struct card *deck); static void eval_agauss(struct card *deck, char *fcn); @@ -1716,11 +1716,17 @@ static void cktislinear(CKTcircuit *ckt, struct card *deck) char **circarray; -void create_circbyline(char *line) +void create_circbyline(char *line, bool reset, bool lastline) { static unsigned int linec = 0; static unsigned int n_elem_alloc = 0; + if (reset) { + linec = 0; + n_elem_alloc = 0; + tfree(circarray); + } + /* Ensure up to 2 cards can be added */ if (n_elem_alloc < linec + 2) { n_elem_alloc = n_elem_alloc == 0 ? 256 : 2 * n_elem_alloc; @@ -1754,6 +1760,10 @@ void create_circbyline(char *line) linec = 0; n_elem_alloc = 0; } + /* If the .end statement is missing */ + else if (lastline) { + fprintf(stderr, "Error: .end statement is missing in netlist!\n"); + } } /* end of function create_circbyline */ @@ -1766,7 +1776,7 @@ void com_circbyline(wordlist *wl) This memory will be released line by line in inp_source(). */ char *newline = wl_flatten(wl); - create_circbyline(newline); + create_circbyline(newline, FALSE, FALSE); } /* handle .if('expr') ... .elseif('expr') ... .else ... .endif statements. diff --git a/src/include/ngspice/sharedspice.h b/src/include/ngspice/sharedspice.h index ae91b300e..a0125167e 100644 --- a/src/include/ngspice/sharedspice.h +++ b/src/include/ngspice/sharedspice.h @@ -371,7 +371,7 @@ int ngSpice_Init_Evt(SendEvtData* sevtdata, SendInitEvtData* sinitevtdata, void /* send a circuit to ngspice.dll The circuit description is a dynamic array of char*. Each char* corresponds to a single circuit - line. The last entry of the array has to be a NULL */ + line. The last entry of the array has to be a .end card. */ IMPEXP int ngSpice_Circ(char** circarray); diff --git a/src/sharedspice.c b/src/sharedspice.c index 3a8ba6d80..c116dc278 100644 --- a/src/sharedspice.c +++ b/src/sharedspice.c @@ -194,7 +194,7 @@ extern struct comm spcp_coms[ ]; extern void DevInit(void); extern int SIMinit(IFfrontEnd *frontEnd, IFsimulator **simulator); extern wordlist *cp_varwl(struct variable *var); -extern void create_circbyline(char *line); +extern void create_circbyline(char *line, bool reset, bool lastline); void exec_controls(wordlist *shcontrols); void rem_controls(void); @@ -971,6 +971,7 @@ IMPEXP int ngSpice_Circ(char** circa){ int entries = 0, i; char* newline; + bool reset = FALSE, lastline = FALSE; if ( ! setjmp(errbufm) ) { intermj = 0; @@ -978,14 +979,23 @@ int ngSpice_Circ(char** circa){ /* count the entries */ while (circa[entries]) { entries++; + char* line = circa[entries - 1]; + if (ciprefix(".end", line) && (line[4] == '\0' || isspace_c(line[4]))) + break; } - entries--; /* don't send the empty line */ + if (ft_ngdebug) fprintf(stdout, "\nngspiceCirc: received netlist array with %d entries\n", entries); /* create a local copy (to be freed in inpcom.c) */ for (i = 0; i < entries; i++) { newline = copy(circa[i]); - create_circbyline(newline); + if (i == 0) + reset = TRUE; + else + reset = FALSE; + if (i == entries - 1) + lastline = TRUE; + create_circbyline(newline, reset, lastline); } return 0; }