From 508fee7d4bb1cc1e1a54f5931531f756b58f8134 Mon Sep 17 00:00:00 2001 From: arno Date: Sat, 9 Sep 2000 13:24:30 +0000 Subject: [PATCH] * commands.c: Use fourier.h. * dotcards.c: Update to prevent segfault. * fourier.c, fourier.h: com_fourier is now calling fourier(), a function with more parameters. * dotcards.c: Added assertions to guard a double indirection, now ngspice will bomb out on an assertion instead of a segfault. --- src/frontend/ChangeLog | 7 +++ src/frontend/commands.c | 2 +- src/frontend/dotcards.c | 129 +++++++++++++++++++++------------------- src/frontend/fourier.c | 109 +++++++++++++++++++-------------- src/frontend/fourier.h | 3 +- 5 files changed, 142 insertions(+), 108 deletions(-) diff --git a/src/frontend/ChangeLog b/src/frontend/ChangeLog index e78feeb45..04c841c78 100644 --- a/src/frontend/ChangeLog +++ b/src/frontend/ChangeLog @@ -1,5 +1,12 @@ 2000-09-09 Arno W. Peters + * commands.c: Use fourier.h. + + * dotcards.c: Update to prevent segfault. + + * fourier.c, fourier.h: com_fourier is now calling fourier(), a + function with more parameters. + * dotcards.c: Added assertions to guard a double indirection, now ngspice will bomb out on an assertion instead of a segfault. diff --git a/src/frontend/commands.c b/src/frontend/commands.c index 1f8647509..7d325cb31 100644 --- a/src/frontend/commands.c +++ b/src/frontend/commands.c @@ -47,7 +47,7 @@ #include "com_plot.h" #include "com_setscale.h" #include "com_xgraph.h" - +#include "fourier.h" /* FIXME: Integrate spcp_coms and nutcp_coms into one variable. */ diff --git a/src/frontend/dotcards.c b/src/frontend/dotcards.c index e702f5bc2..7ad0d4323 100644 --- a/src/frontend/dotcards.c +++ b/src/frontend/dotcards.c @@ -20,19 +20,35 @@ Modified: 2000 AlansFixes #include "circuits.h" #include "dotcards.h" #include "variable.h" - +#include "fourier.h" /* Extract all the .save lines */ static void fixdotplot(wordlist *wl); static void fixdotprint(wordlist *wl); static char * fixem(char *string); -static bool setcplot(char *name); static wordlist * gettoks(char *s); extern void com_save2 (wordlist *wl, char *name); + + +static struct plot * +setcplot(char *name) +{ + struct plot *pl; + + for (pl = plot_list; pl; pl = pl->pl_next) { + if (ciprefix(name, pl->pl_typename)) { + return pl; + } + } + return NULL; +} + + + void ft_dotsaves(void) { @@ -157,7 +173,9 @@ ft_cktcoms(bool terse) if (!ft_curckt) return 1; - if (!ft_curckt->ci_commands && !setcplot("op")) + + plot_cur = setcplot("op"); + if (!ft_curckt->ci_commands && !plot_cur) goto nocmds; coms = ft_curckt->ci_commands; cp_interactive = FALSE; @@ -168,41 +186,43 @@ ft_cktcoms(bool terse) fprintf(cp_err, ".options: no listing, rawfile was generated.\n"); else inp_list(cp_out, ft_curckt->ci_deck, ft_curckt->ci_options, - LS_DECK); + LS_DECK); } /* If there was a .op line, then we have to do the .op output. */ - assert(plot_cur != NULL); - assert(plot_cur->pl_dvecs != NULL); - if (setcplot("op") && (plot_cur->pl_dvecs->v_realdata!=NULL)) { - if (terse) { - fprintf(cp_out, "OP information in rawfile.\n"); - } else { - fprintf(cp_out, "\t%-30s%15s\n", "Node", "Voltage"); - fprintf(cp_out, "\t%-30s%15s\n", "----", "-------"); - fprintf(cp_out, "\t----\t-------\n"); - for (v = plot_cur->pl_dvecs; v; v = v->v_next) { - if (!isreal(v)) { - fprintf(cp_err, - "Internal error: op vector %s not real\n", - v->v_name); - continue; + plot_cur = setcplot("op"); + if (plot_cur != NULL) { + assert(plot_cur->pl_dvecs != NULL); + if (plot_cur->pl_dvecs->v_realdata!=NULL) { + if (terse) { + fprintf(cp_out, "OP information in rawfile.\n"); + } else { + fprintf(cp_out, "\t%-30s%15s\n", "Node", "Voltage"); + fprintf(cp_out, "\t%-30s%15s\n", "----", "-------"); + fprintf(cp_out, "\t----\t-------\n"); + for (v = plot_cur->pl_dvecs; v; v = v->v_next) { + if (!isreal(v)) { + fprintf(cp_err, + "Internal error: op vector %s not real\n", + v->v_name); + continue; + } + if ((v->v_type == SV_VOLTAGE) && (*(v->v_name)!='@')) + fprintf(cp_out, "\t%-30s%15s\n", v->v_name, + printnum(v->v_realdata[0])); } - if ((v->v_type == SV_VOLTAGE) && (*(v->v_name)!='@')) - fprintf(cp_out, "\t%-30s%15s\n", v->v_name, - printnum(v->v_realdata[0])); + fprintf(cp_out, "\n\tSource\tCurrent\n"); + fprintf(cp_out, "\t------\t-------\n\n"); + for (v = plot_cur->pl_dvecs; v; v = v->v_next) + if (v->v_type == SV_CURRENT) + fprintf(cp_out, "\t%-30s%15s\n", v->v_name, + printnum(v->v_realdata[0])); + fprintf(cp_out, "\n"); + + if (!ft_nomod) + com_showmod(&all); + com_show(&all); } - fprintf(cp_out, "\n\tSource\tCurrent\n"); - fprintf(cp_out, "\t------\t-------\n\n"); - for (v = plot_cur->pl_dvecs; v; v = v->v_next) - if (v->v_type == SV_CURRENT) - fprintf(cp_out, "\t%-30s%15s\n", v->v_name, - printnum(v->v_realdata[0])); - fprintf(cp_out, "\n"); - - if (!ft_nomod) - com_showmod(&all); - com_show(&all); } } @@ -264,7 +284,7 @@ ft_cktcoms(bool terse) } if (!found) fprintf(cp_err, "Error: .print: no %s analysis found.\n", - plottype); + plottype); } } else if (eq(command->wl_word, ".plot")) { if (terse) { @@ -298,22 +318,27 @@ ft_cktcoms(bool terse) if (terse) { fprintf(cp_out, ".fourier line ignored since rawfile was produced.\n"); - } else if (setcplot("tran")) { - com_fourier(command->wl_next); - fprintf(cp_out, "\n\n"); - } else - fprintf(cp_err, - "No transient data available for fourier analysis"); + } else { + int err; + + plot_cur = setcplot("tran"); + err = fourier(command->wl_next, plot_cur); + if (!err) + fprintf(cp_out, "\n\n"); + else + fprintf(cp_err, "No transient data available for " + "fourier analysis"); + } } else if (!eq(command->wl_word, ".save") - && !eq(command->wl_word, ".op") - && !eq(command->wl_word, ".tf")) + && !eq(command->wl_word, ".op") + && !eq(command->wl_word, ".tf")) { goto bad; } coms = coms->wl_next; } -nocmds: + nocmds: /* Now the node table */ if (ft_nodesprint) ; @@ -335,7 +360,7 @@ nocmds: putc('\n', cp_out); return 0; -bad: + bad: fprintf(cp_err, "Internal Error: ft_cktcoms: bad commands\n"); return 1; } @@ -473,22 +498,6 @@ fixem(char *string) return (string); } -/* Don't bother with ccom strangeness here. */ - -static bool -setcplot(char *name) -{ - struct plot *pl; - - for (pl = plot_list; pl; pl = pl->pl_next) { - if (ciprefix(name, pl->pl_typename)) { - plot_cur = pl; - return (TRUE); - } - } - return (FALSE); -} - static wordlist * gettoks(char *s) { diff --git a/src/frontend/fourier.c b/src/frontend/fourier.c index 8148ef3f9..737323b11 100644 --- a/src/frontend/fourier.c +++ b/src/frontend/fourier.c @@ -31,12 +31,15 @@ static int CKTfour(int ndata, int numFreq, double *thd, double *Time, double *Va #define DEF_FOURGRIDSIZE 200 + /* CKTfour(ndata,numFreq,thd,Time,Value,FundFreq,Freq,Mag,Phase,nMag,nPhase) * len 10 ? inp inp inp out out out out out */ -void -com_fourier(wordlist *wl) +/* FIXME: This function leaks memory due to non local exit bypassing + freeing of memory at the end of the function. */ +int +fourier(wordlist *wl, struct plot *current_plot) { struct dvec *time, *vec; struct pnode *names, *first_name; @@ -49,11 +52,14 @@ com_fourier(wordlist *wl) char xbuf[20]; int shift; + if (!current_plot) + return 1; + sprintf(xbuf, "%1.1e", 0.0); shift = strlen(xbuf) - 7; - if (!plot_cur || !plot_cur->pl_scale) { + if (!current_plot || !current_plot->pl_scale) { fprintf(cp_err, "Error: no vectors loaded.\n"); - return; + return 1; } if ((!cp_getvar("nfreqs", VT_NUM, (char *) &nfreqs)) || (nfreqs < 1)) @@ -65,15 +71,15 @@ com_fourier(wordlist *wl) (fourgridsize < 1)) fourgridsize = DEF_FOURGRIDSIZE; - time = plot_cur->pl_scale; + time = current_plot->pl_scale; if (!isreal(time)) { fprintf(cp_err, "Error: fourier needs real time scale\n"); - return; + return 1; } s = wl->wl_word; if (!(ff = ft_numparse(&s, FALSE)) || (*ff <= 0.0)) { fprintf(cp_err, "Error: bad fund freq %s\n", wl->wl_word); - return; + return 1; } fundfreq = *ff; @@ -114,8 +120,8 @@ com_fourier(wordlist *wl) d = 1 / fundfreq; /* The wavelength... */ if (dp[1] - dp[0] < d) { fprintf(cp_err, - "Error: wavelength longer than time span\n"); - return; + "Error: wavelength longer than time span\n"); + return 1; } else if (dp[1] - dp[0] > d) { dp[0] = dp[1] - d; } @@ -131,7 +137,7 @@ com_fourier(wordlist *wl) polydegree)) { fprintf(cp_err, "Error: can't interpolate\n"); - return; + return 1; } timescale = grid; } else { @@ -145,7 +151,7 @@ com_fourier(wordlist *wl) nphase); if (err != OK) { ft_sperror(err, "fourier"); - return; + return 1; } fprintf(cp_out, "Fourier analysis for %s:\n", @@ -185,9 +191,18 @@ com_fourier(wordlist *wl) tfree(phase); tfree(nmag); tfree(nphase); - return; + return 0; } + +void +com_fourier(wordlist *wl) +{ + fourier(wl, plot_cur); +} + + + static char * pn(double num) { @@ -198,50 +213,54 @@ pn(double num) i = 6; if (num < 0.0) - (void) sprintf(buf, "%.*g", i - 1, num); + sprintf(buf, "%.*g", i - 1, num); else - (void) sprintf(buf, "%.*g", i, num); + sprintf(buf, "%.*g", i, num); return (copy(buf)); } -/* - * CKTfour() - perform fourier analysis of an output vector. - * Due to the construction of the program which places all the - * output data in the post-processor, the fourier analysis can not - * be done directly. This function allows the post processor to - * hand back vectors of time and data values to have the fourier analysis - * performed on them. - * - */ - +/* CKTfour() - perform fourier analysis of an output vector. + * + * Due to the construction of the program which places all the output + * data in the post-processor, the fourier analysis can not be done + * directly. This function allows the post processor to hand back + * vectors of time and data values to have the fourier analysis + * performed on them. */ static int -CKTfour(int ndata, int numFreq, double *thd, double *Time, double *Value, double FundFreq, double *Freq, double *Mag, double *Phase, double *nMag, double *nPhase) - /* number of entries in the Time and Value arrays */ - /* number of harmonics to calculate */ - /* total harmonic distortion (percent) to be returned */ - /* times at which the voltage/current values were measured*/ - /* voltage or current vector whose transform is desired */ - /* the fundamental frequency of the analysis */ - /* the frequency value of the various harmonics */ - /* the Magnitude of the fourier transform */ - /* the Phase of the fourier transform */ - /* the normalized magnitude of the transform: nMag(fund)=1*/ - /* the normalized phase of the transform: Nphase(fund)=0 */ - /* note we can consider these as a set of arrays: The sizes are: - * Time[ndata], Value[ndata] - * Freq[numFreq],Mag[numfreq],Phase[numfreq],nMag[numfreq],nPhase[numfreq] +CKTfour(int ndata, /* number of entries in the Time and + Value arrays */ + int numFreq, /* number of harmonics to calculate */ + double *thd, /* total harmonic distortion (percent) + to be returned */ + double *Time, /* times at which the voltage/current + values were measured*/ + double *Value, /* voltage or current vector whose + transform is desired */ + double FundFreq, /* the fundamental frequency of the + analysis */ + double *Freq, /* the frequency value of the various + harmonics */ + double *Mag, /* the Magnitude of the fourier + transform */ + double *Phase, /* the Phase of the fourier transform */ + double *nMag, /* the normalized magnitude of the + transform: nMag(fund)=1*/ + double *nPhase) /* the normalized phase of the + transform: Nphase(fund)=0 */ +{ + /* Note: we can consider these as a set of arrays. The sizes are: + * Time[ndata], Value[ndata], Freq[numFreq], Mag[numfreq], + * Phase[numfreq], nMag[numfreq], nPhase[numfreq] + * * The arrays must all be allocated by the caller. * The Time and Value array must be reasonably distributed over at * least one full period of the fundamental Frequency for the * fourier transform to be useful. The function will take the * last period of the frequency as data for the transform. - */ - -{ -/* we are assuming that the caller has provided exactly one period - * of the fundamental frequency. - */ + * + * We are assuming that the caller has provided exactly one period + * of the fundamental frequency. */ int i; int j; double tmp; diff --git a/src/frontend/fourier.h b/src/frontend/fourier.h index 597f7cf2f..e30e237b8 100644 --- a/src/frontend/fourier.h +++ b/src/frontend/fourier.h @@ -7,7 +7,6 @@ #define FOURIER_H_INCLUDED void com_fourier(wordlist *wl); - - +int fourier(wordlist *wl, struct plot *current); #endif