From 4a8e669562fb5ba3e97617da16087641b81bdd03 Mon Sep 17 00:00:00 2001 From: Holger Vogt Date: Fri, 29 Nov 2019 23:55:13 +0100 Subject: [PATCH 1/2] enable setting a variable from an input file using the existing i/o redirection --- src/frontend/com_set.c | 61 ++++++++++++++++++++++++++++++++++++++++++ src/frontend/streams.c | 12 ++++++--- 2 files changed, 69 insertions(+), 4 deletions(-) diff --git a/src/frontend/com_set.c b/src/frontend/com_set.c index 62bfa7ca9..688c22feb 100644 --- a/src/frontend/com_set.c +++ b/src/frontend/com_set.c @@ -6,6 +6,8 @@ #include "variable.h" #include "com_set.h" +wordlist* readifile(wordlist*); + /* The set command. Syntax is set [opt ...] [opt = val ...]. Val may * be a string, an int, a float, or a list of the form (elt1 elt2 @@ -19,6 +21,12 @@ com_set(wordlist *wl) cp_vprint(); return; } + + /* special case input redirection*/ + wordlist *ww = wl->wl_next; + if (ww && eq(ww->wl_word, "<")) + wl = readifile(wl); + vars = cp_setparse(wl); /* This is sort of a hassle... */ @@ -54,3 +62,56 @@ com_set(wordlist *wl) tfree(oldvar); } } + +/* read a file from cp_in, add the tokens to a wordlist and + create an input for a string list like set ccc = ( 3 5 7 ). + Comment lines in input file (starting with '*') are ignored. */ +wordlist* +readifile(wordlist* win) +{ + /* max file size */ + char intoken[4096]; + /* save start address */ + wordlist* tw = win; + char *tmpstr; + + /* delete wordlist from '<' on */ + wl_free(win->wl_next); + wl_append_word(&win, &win, copy("=")); + wl_append_word(&win, &win, copy("(")); + /* read a line. If it starts with '*', ignore it */ + while (fgets(intoken, 4096, cp_in) != NULL) { + if (intoken[0] == '*') + continue; + char* delstr; + char* instr = delstr = copy(intoken); + /* get all tokens, ignoring '\n' + and add to string list */ + while ((tmpstr = gettok(&instr)) != NULL) { + wl_append_word(&win, &win, tmpstr); + } + tfree(delstr); + } + wl_append_word(&win, &win, copy(")")); + /* close and reset cp_in + (was opened in streams.c:84) */ + cp_ioreset(); + return tw; +#if 0 + size_t retval = fread(intoken, 1, 4096, cp_in); + intoken[retval] = '\0'; + char* delstr; + char* instr = delstr = copy(intoken); + /* get all tokens, ignoring '\n' + and add to string list */ + while ((tmpstr = gettok(&instr)) != NULL) { + wl_append_word(&win, &win, tmpstr); + } + tfree(delstr); + wl_append_word(&win, &win, copy(")")); + /* close and reset cp_in + (was opened in streams.c:84) */ + cp_ioreset(); + return tw; +#endif +} diff --git a/src/frontend/streams.c b/src/frontend/streams.c index 8906fd33c..8558220b1 100644 --- a/src/frontend/streams.c +++ b/src/frontend/streams.c @@ -82,16 +82,20 @@ cp_redirect(wordlist *wl) #endif fp = fopen(fname, "r"); - tfree(fname); - if (!fp) { perror(fname); + tfree(fname); goto error; } - + + tfree(fname); cp_in = fp; - wl_delete_slice(beg, w); + /* special case for set command: + keep i/o information (handled in com_set.c) */ + wordlist* bw = beg->wl_prev->wl_prev; + if (!(bw && cieq(bw->wl_word, "set"))) + wl_delete_slice(beg, w); } else if (*w->wl_word == cp_gt) { From dd05e246771ca3c054c58587a6a79ae932d722e9 Mon Sep 17 00:00:00 2001 From: Holger Vogt Date: Mon, 2 Dec 2019 21:33:31 +0100 Subject: [PATCH 2/2] prevent referencing a NULL pointer free the loc pointer and NULL its origin STATIC_VAR (locdata) (that translates to mif_private->inst_var[0]->element[0].pvalue) --- src/xspice/icm/table/mada/eno2.c | 3 +++ src/xspice/icm/table/mada/eno3.c | 3 +++ src/xspice/icm/table/table2D/cfunc.mod | 15 ++++++++++----- src/xspice/icm/table/table3D/cfunc.mod | 15 ++++++++++----- 4 files changed, 26 insertions(+), 10 deletions(-) diff --git a/src/xspice/icm/table/mada/eno2.c b/src/xspice/icm/table/mada/eno2.c index e36adeda0..1adb003e0 100644 --- a/src/xspice/icm/table/mada/eno2.c +++ b/src/xspice/icm/table/mada/eno2.c @@ -72,6 +72,9 @@ sf_eno2_close (sf_eno2 pnt) { int i2; + if (!pnt) + return; + sf_eno_close (pnt->jnt); for (i2 = 0; i2 < pnt->n2; i2++) sf_eno_close (pnt->ent[i2]); diff --git a/src/xspice/icm/table/mada/eno3.c b/src/xspice/icm/table/mada/eno3.c index 81b7e7e93..2942f142c 100644 --- a/src/xspice/icm/table/mada/eno3.c +++ b/src/xspice/icm/table/mada/eno3.c @@ -78,6 +78,9 @@ sf_eno3_close(sf_eno3 pnt) { int i2, i3; + if (!pnt) + return; + sf_eno2_close (pnt->jnt); for (i3 = 0; i3 < pnt->n3; i3++) { for (i2 = 0; i2 < pnt->n2; i2++) diff --git a/src/xspice/icm/table/table2D/cfunc.mod b/src/xspice/icm/table/table2D/cfunc.mod index 7a474232b..df8d363a9 100644 --- a/src/xspice/icm/table/table2D/cfunc.mod +++ b/src/xspice/icm/table/table2D/cfunc.mod @@ -298,6 +298,8 @@ cm_table2D_callback(ARGS, Mif_Callback_Reason_t reason) case MIF_CB_DESTROY: { int i; Local_Data_t *loc = STATIC_VAR (locdata); + if (!loc) + break; free(loc->state); for (i = 0; i < loc->iy; i++) free(loc->table[i]); @@ -306,6 +308,7 @@ cm_table2D_callback(ARGS, Mif_Callback_Reason_t reason) free(loc->ycol); sf_eno2_close (loc->newtable); free(loc); + STATIC_VAR (locdata) = loc = NULL; break; } } @@ -428,8 +431,9 @@ cm_table2D(ARGS) /* structure holding parms, inputs, outputs, etc. */ struct stat st; if (!loc->state->fp || fstat(fileno(loc->state->fp), &st)) { cm_message_printf("cannot open file %s", PARAM(file)); - loc->state->atend = 1; - loc->init_err = 1; + free(loc->state); + free(loc); + STATIC_VAR (locdata) = loc = NULL; return; } /* get file length */ @@ -441,8 +445,9 @@ cm_table2D(ARGS) /* structure holding parms, inputs, outputs, etc. */ cThisLine = calloc(lFileLen + 1, sizeof(char)); if (cFile == NULL || cThisLine == NULL) { cm_message_printf("Insufficient memory to read file %s", PARAM(file)); - loc->state->atend = 1; - loc->init_err = 1; + free(loc->state); + free(loc); + STATIC_VAR (locdata) = loc = NULL; if(cFile) free(cFile); if(cThisLine) free(cThisLine); return; @@ -627,7 +632,7 @@ cm_table2D(ARGS) /* structure holding parms, inputs, outputs, etc. */ loc = STATIC_VAR (locdata); /* return immediately if there was an initialization error */ - if (loc->init_err == 1) + if (!loc || loc->init_err == 1) return; /* get input x, y, diff --git a/src/xspice/icm/table/table3D/cfunc.mod b/src/xspice/icm/table/table3D/cfunc.mod index 3d12cb388..9fe1cf5b1 100644 --- a/src/xspice/icm/table/table3D/cfunc.mod +++ b/src/xspice/icm/table/table3D/cfunc.mod @@ -304,6 +304,8 @@ cm_table3D_callback(ARGS, Mif_Callback_Reason_t reason) case MIF_CB_DESTROY: { int i, j; Local_Data_t *loc = STATIC_VAR (locdata); + if (!loc) + break; free(loc->state); for (i = 0; i < loc->iz; i++) { @@ -317,6 +319,7 @@ cm_table3D_callback(ARGS, Mif_Callback_Reason_t reason) free(loc->zcol); sf_eno3_close (loc->newtable); free(loc); + STATIC_VAR (locdata) = loc = NULL; break; } } @@ -442,8 +445,9 @@ cm_table3D(ARGS) /* structure holding parms, inputs, outputs, etc. */ struct stat st; if (!loc->state->fp || fstat(fileno(loc->state->fp), &st)) { cm_message_printf("cannot open file %s", PARAM(file)); - loc->state->atend = 1; - loc->init_err = 1; + free(loc->state); + free(loc); + STATIC_VAR (locdata) = loc = NULL; return; } /* get file length */ @@ -455,8 +459,9 @@ cm_table3D(ARGS) /* structure holding parms, inputs, outputs, etc. */ cThisLine = calloc(lFileLen + 1, sizeof(char)); if (cFile == NULL || cThisLine == NULL) { cm_message_printf("Insufficient memory to read file %s", PARAM(file)); - loc->state->atend = 1; - loc->init_err = 1; + free(loc->state); + free(loc); + STATIC_VAR (locdata) = loc = NULL; if(cFile) free(cFile); if(cThisLine) free(cThisLine); return; @@ -668,7 +673,7 @@ cm_table3D(ARGS) /* structure holding parms, inputs, outputs, etc. */ loc = STATIC_VAR (locdata); /* return immediately if there was an initialization error */ - if (loc->init_err == 1) + if (!loc || loc->init_err == 1) return; /* get input x, y, z;