Fixed several issues related to plotting and vector lifetimes and made ownership of vectors clearer. The issues in bugs 419, 423, 425, and 426 were related and were addressed here.

This commit is contained in:
Jim Monte 2019-12-12 19:10:29 -05:00 committed by Holger Vogt
parent 10415875f4
commit 503af6ac00
12 changed files with 710 additions and 474 deletions

View File

@ -21,10 +21,16 @@
/* hardcopy file plotargs, or 'hardcopy file' -- with no other args
* this prompts the user for a window to dump to a plot file. XXX no
* it doesn't. */
void
com_hardcopy(wordlist *wl)
void com_hardcopy(wordlist *wl)
{
/* Check if there is a graph available */
if (currentgraph == (GRAPH *) NULL) {
(void) fprintf(cp_err, "There is no graph to hardcopy.\n");
return;
}
char *fname;
size_t n_byte_fname; /* size of fname in bytes, including null */
char buf[BSIZE_SP], device[BSIZE_SP];
bool tempf = FALSE;
char *devtype;
@ -40,18 +46,22 @@ com_hardcopy(wordlist *wl)
if (wl) {
hc_button = 0;
fname = wl->wl_word;
fname = copy(wl->wl_word);
wl = wl->wl_next;
} else {
}
else {
hc_button = 1;
fname = smktemp("hc");
tempf = TRUE;
}
n_byte_fname = (strlen(fname) + 1) * sizeof *fname;
if (!cp_getvar("hcopydevtype", CP_STRING, buf, sizeof(buf)))
if (!cp_getvar("hcopydevtype", CP_STRING, buf, sizeof(buf))) {
devtype = "postscript";
else
}
else {
devtype = buf;
}
/* enable screen plot selection for these display types */
foundit = 0;
@ -63,8 +73,9 @@ com_hardcopy(wordlist *wl)
if (!wl && hc_button) {
char *psfname;
GRAPH *tempgraph;
if (DevSwitch(devtype))
if (DevSwitch(devtype)) {
return;
}
tempgraph = CopyGraph(currentgraph);
/* change .tmp to .ps */
psfname = strchr(fname, '.');
@ -72,11 +83,15 @@ com_hardcopy(wordlist *wl)
psfname[1] = 'p';
psfname[2] = 's';
psfname[3] = '\0';
} else {
fname = trealloc(fname, strlen(fname)+4);
strcat(fname, ".ps");
}
else {
fname = trealloc(fname, n_byte_fname + 3);
(void) memcpy(fname + n_byte_fname - 1, ".ps", 4);
n_byte_fname += 3;
}
tempgraph->devdep = fname;
tempgraph->n_byte_devdep = n_byte_fname;
if (NewViewport(tempgraph)) {
DevSwitch(NULL);
return;
@ -92,21 +107,23 @@ com_hardcopy(wordlist *wl)
#ifndef X_DISPLAY_MISSING
if (!wl && hc_button) {
REQUEST request;
RESPONSE response;
GRAPH *tempgraph;
request.option = click_option;
Input(&request, &response);
if (response.option == error_option)
if (response.option == error_option) {
return;
}
if (response.reply.graph) {
if (DevSwitch(devtype))
if (DevSwitch(devtype)) {
return;
}
tempgraph = CopyGraph(response.reply.graph);
tempgraph->devdep = fname;
tempgraph->n_byte_devdep = n_byte_fname;
if (NewViewport(tempgraph)) {
DevSwitch(NULL);
return;
@ -133,19 +150,20 @@ com_hardcopy(wordlist *wl)
PushGraphContext(currentgraph);
if (!foundit) {
if (!wl) {
char *buf2;
outmenuprompt("which variable ? ");
buf2 = prompt(cp_in);
if (!buf2)
if (!buf2) {
return;
}
wl = wl_cons(buf2, NULL);
wl = process(wl);
}
if (DevSwitch(devtype))
if (DevSwitch(devtype)) {
return;
}
if (!wl || !plotit(wl, fname, NULL)) {
printf("com_hardcopy: graph not defined\n");
@ -189,11 +207,13 @@ com_hardcopy(wordlist *wl)
fname);
fprintf(cp_out,
"\tor by using the '-g' flag to the Unix lpr command.\n");
} else if (!strcmp(devtype, "postscript")) {
}
else if (!strcmp(devtype, "postscript")) {
fprintf(cp_out,
"\nThe file \"%s\" may be printed on a postscript printer.\n",
fname);
} else if (!strcmp(devtype, "MFB")) {
}
else if (!strcmp(devtype, "MFB")) {
fprintf(cp_out,
"The file \"%s\" may be printed on a MFB device.\n",
fname);
@ -205,4 +225,7 @@ com_hardcopy(wordlist *wl)
/* restore previous graphics context by retrieving the previous currentgraph */
PopGraphContext();
}
} /* end of function com_hardcopy */

View File

@ -2,10 +2,10 @@
#include "ngspice/dvec.h"
struct dvec *
dvec_alloc(char *name, int type, short flags, int length, void *storage)
struct dvec *dvec_alloc(const char *name,
int type, short flags, int length, void *storage)
{
struct dvec *rv = TMALLOC(struct dvec, 1);
struct dvec * const rv = TMALLOC(struct dvec, 1);
/* If the allocation failed, return NULL as a failure flag.
* As of 2019-03, TMALLOC will not return on failure, so this check is
@ -54,60 +54,81 @@ dvec_alloc(char *name, int type, short flags, int length, void *storage)
rv->v_numdims = 0; /* Really "unknown" */
return rv;
}
} /* end of function dvec_alloc */
void
dvec_realloc(struct dvec *v, int length, void *storage)
/* Resize dvec to length if storage is NULL orr replace
* its existing allocation with storage if not
*/
void dvec_realloc(struct dvec *v, int length, void *storage)
{
if (isreal(v)) {
if (storage) {
tfree(v->v_realdata);
v->v_realdata = (double *) storage;
} else {
}
else {
v->v_realdata = TREALLOC(double, v->v_realdata, length);
}
} else {
}
else {
if (storage) {
tfree(v->v_compdata);
v->v_compdata = (ngcomplex_t *) storage;
} else {
}
else {
v->v_compdata = TREALLOC(ngcomplex_t, v->v_compdata, length);
}
}
v->v_length = length;
v->v_alloc_length = length;
}
} /* end of function dvec_realloc */
void
dvec_extend(struct dvec *v, int length)
void dvec_extend(struct dvec *v, int length)
{
if (isreal(v))
if (isreal(v)) {
v->v_realdata = TREALLOC(double, v->v_realdata, length);
else
}
else {
v->v_compdata = TREALLOC(ngcomplex_t, v->v_compdata, length);
}
v->v_alloc_length = length;
}
} /* end of function dvec_extend */
void
dvec_trunc(struct dvec *v, int length)
void dvec_trunc(struct dvec *v, int length)
{
v->v_length = length;
}
/* Ensure valid */
if (v->v_alloc_length <= length) {
v->v_length = length;
}
} /* end of function dvec_trunc */
void
dvec_free(struct dvec *v)
void dvec_free(struct dvec *v)
{
if (v->v_name)
tfree(v->v_name);
if (v->v_realdata)
tfree(v->v_realdata);
if (v->v_compdata)
tfree(v->v_compdata);
tfree(v);
}
/* Check for freed vector */
if (v == (struct dvec *) NULL) {
return;
}
/* Free the various allocations */
if (v->v_name) {
txfree(v->v_name);
}
if (v->v_realdata) {
txfree(v->v_realdata);
}
else if (v->v_compdata) { /* if data real, not complex */
txfree(v->v_compdata);
}
txfree(v);
} /* end of function dvec_free */

View File

@ -565,21 +565,22 @@ OUTpData(runDesc *plotPtr, IFvalue *refValue, IFvalue *valuePtr)
#ifdef TCL_MODULE
steps_completed = run->pointCount;
#endif
/* interpolated batch mode output to file in transient analysis */
if (interpolated && run->circuit->CKTcurJob->JOBtype == 4 && run->writeOut) {
InterpFileAdd(run, refValue, valuePtr);
return (OK);
}
/* interpolated interactive or control mode output to plot in transient analysis */
else if (interpolated && run->circuit->CKTcurJob->JOBtype == 4 && !(run->writeOut)) {
InterpPlotAdd(run, refValue, valuePtr);
return (OK);
/* interpolated batch mode output to file/plot in transient analysis */
if (interpolated && run->circuit->CKTcurJob->JOBtype == 4) {
if (run->writeOut) { /* To file */
InterpFileAdd(run, refValue, valuePtr);
}
else { /* To plot */
InterpPlotAdd(run, refValue, valuePtr);
}
return OK;
}
/* standard batch mode output to file */
else if (run->writeOut) {
if (run->pointCount == 1)
if (run->pointCount == 1) {
fileInit_pass2(run);
}
fileStartPoint(run->fp, run->binary, run->pointCount);
@ -600,10 +601,8 @@ OUTpData(runDesc *plotPtr, IFvalue *refValue, IFvalue *valuePtr)
}
}
#endif
} else {
/* And the same for a non-complex value */
}
else { /* And the same for a non-complex (real) value */
fileAddRealValue(run->fp, run->binary, refValue->rValue);
#ifndef HAS_WINGUI
if (!orflag && !ft_norefprint) {
@ -620,8 +619,9 @@ OUTpData(runDesc *plotPtr, IFvalue *refValue, IFvalue *valuePtr)
for (i = 0; i < run->numData; i++) {
/* we've already printed reference vec first */
if (run->data[i].outIndex == -1)
if (run->data[i].outIndex == -1) {
continue;
}
#ifdef TCL_MODULE
blt_add(i, refValue ? refValue->rValue : NAN);
@ -630,13 +630,14 @@ OUTpData(runDesc *plotPtr, IFvalue *refValue, IFvalue *valuePtr)
if (run->data[i].regular) {
if (run->data[i].type == IF_REAL)
fileAddRealValue(run->fp, run->binary,
valuePtr->v.vec.rVec [run->data[i].outIndex]);
valuePtr->v.vec.rVec [run->data[i].outIndex]);
else if (run->data[i].type == IF_COMPLEX)
fileAddComplexValue(run->fp, run->binary,
valuePtr->v.vec.cVec [run->data[i].outIndex]);
valuePtr->v.vec.cVec [run->data[i].outIndex]);
else
fprintf(stderr, "OUTpData: unsupported data type\n");
} else {
}
else {
IFvalue val;
/* should pre-check instance */
if (!getSpecial(&run->data[i], run, &val)) {
@ -652,7 +653,8 @@ OUTpData(runDesc *plotPtr, IFvalue *refValue, IFvalue *valuePtr)
val.cValue.real = 0;
val.cValue.imag = 0;
fileAddComplexValue(run->fp, run->binary, val.cValue);
} else {
}
else {
val.rValue = 0;
fileAddRealValue(run->fp, run->binary, val.rValue);
}
@ -683,8 +685,8 @@ OUTpData(runDesc *plotPtr, IFvalue *refValue, IFvalue *valuePtr)
shouldstop = TRUE;
}
} else {
}
else {
OUTpD_memory(run, refValue, valuePtr);
/* This is interactive mode. Update the screen with the reference
@ -718,18 +720,18 @@ OUTpData(runDesc *plotPtr, IFvalue *refValue, IFvalue *valuePtr)
sh_ExecutePerLoop();
#endif
return (OK);
}
return OK;
} /* end of function OUTpData */
int
OUTwReference(void *plotPtr, IFvalue *valuePtr, void **refPtr)
int OUTwReference(void *plotPtr, IFvalue *valuePtr, void **refPtr)
{
NG_IGNORE(refPtr);
NG_IGNORE(valuePtr);
NG_IGNORE(plotPtr);
return (OK);
return OK;
}
@ -741,7 +743,7 @@ OUTwData(runDesc *plotPtr, int dataIndex, IFvalue *valuePtr, void *refPtr)
NG_IGNORE(dataIndex);
NG_IGNORE(plotPtr);
return (OK);
return OK;
}
@ -750,7 +752,7 @@ OUTwEnd(runDesc *plotPtr)
{
NG_IGNORE(plotPtr);
return (OK);
return OK;
}

View File

@ -17,19 +17,18 @@ Author: 1988 Jeffrey M. Hsu
#include "ngspice/dvec.h" /* for struct dvec */
#include "ngspice/ftedefs.h" /* for FTEextern.h and IPOINT{MIN,MAX} */
#include "ngspice/fteinput.h"
#include "ngspice/graph.h"
#include "ngspice/ftedbgra.h"
#include "ngspice/ftedev.h"
#include "ngspice/graph.h"
#include "ngspice/grid.h"
#include "ngspice/sim.h"
#include <terminal.h>
#include "ngspice/stringskip.h"
#include "breakp2.h"
#include "display.h"
#include "graf.h"
#include "graphdb.h"
#include "ngspice/grid.h"
#include "../terminal.h"
#include "../breakp2.h"
#include "../display.h"
#include "../runcoms.h"
#include "ngspice/stringskip.h"
#include "runcoms.h"
#include "terminal.h"
static void gr_start_internal(struct dvec *dv, bool copyvec);
@ -107,8 +106,10 @@ int gr_init(double *xlims, double *ylims, /* The size of the screen. */
cur.plotno = 0;
/* note: should do only once, maybe in gr_init_once */
if (!cp_getvar("pointchars", CP_STRING, pointchars, sizeof(pointchars)))
if (!cp_getvar("pointchars", CP_STRING,
pointchars, sizeof(pointchars))) {
(void) strcpy(pointchars, DEFPOINTCHARS);
}
if (!cp_getvar("ticmarks", CP_NUM, &graph->ticmarks, 0)) {
if (cp_getvar("ticmarks", CP_BOOL, NULL, 0)) {
@ -242,8 +243,7 @@ int gr_init(double *xlims, double *ylims, /* The size of the screen. */
* We pass two points in so we can multiplex plots.
*
*/
void
gr_point(struct dvec *dv,
void gr_point(struct dvec *dv,
double newx, double newy,
double oldx, double oldy,
int np)
@ -262,11 +262,13 @@ gr_point(struct dvec *dv,
oldtox = tox; oldtoy = toy;
if (!currentgraph->grid.circular) {
if (clip_line(&fromx, &fromy, &tox, &toy,
currentgraph->viewportxoff, currentgraph->viewportyoff,
currentgraph->viewport.width + currentgraph->viewportxoff,
currentgraph->viewport.height + currentgraph->viewportyoff))
currentgraph->viewportxoff, currentgraph->viewportyoff,
currentgraph->viewport.width + currentgraph->viewportxoff,
currentgraph->viewport.height + currentgraph->viewportyoff)) {
return;
} else {
}
}
else {
if (clip_to_circle(&fromx, &fromy, &tox, &toy,
currentgraph->grid.xaxis.circular.center,
currentgraph->grid.yaxis.circular.center,
@ -276,11 +278,13 @@ gr_point(struct dvec *dv,
if (currentgraph->plottype != PLOT_POINT) {
SetLinestyle(dv->v_linestyle);
} else {
}
else {
/* if PLOT_POINT,
don't want to plot an endpoint which have been clipped */
if (tox != oldtox || toy != oldtoy)
if (tox != oldtox || toy != oldtoy) {
return;
}
}
SetColor(dv->v_color);
@ -290,8 +294,9 @@ gr_point(struct dvec *dv,
case PLOT_MONOLIN:
/* If it's a linear plot, ignore first point since we don't
want to connect with oldx and oldy. */
if (np)
if (np) {
DevDrawLine(fromx, fromy, tox, toy);
}
if ((tics = currentgraph->ticdata) != NULL) {
for (; *tics < HUGE; tics++)
if (*tics == (double) np) {
@ -304,9 +309,9 @@ gr_point(struct dvec *dv,
(int) (toy - currentgraph->fontheight / 2)); */
break;
}
} else if ((currentgraph->ticmarks >0) && (np > 0) &&
(np % currentgraph->ticmarks == 0))
{
}
else if ((currentgraph->ticmarks >0) && (np > 0) &&
(np % currentgraph->ticmarks == 0)) {
/* Draw an 'x' */
DevDrawText("x", (int) (tox - currentgraph->fontwidth / 2),
(int) (toy - currentgraph->fontheight / 2), 0);
@ -382,34 +387,45 @@ static void gr_start_internal(struct dvec *dv, bool copyvec)
link = TMALLOC(struct dveclist, 1);
link->next = currentgraph->plotdata;
/* Either reuse input vector or copy depnding on copyvec */
if (copyvec) {
link->vector = vec_copy(dv);
/* vec_copy doesn't set v_color or v_linestyle */
link->vector->v_color = dv->v_color;
link->vector->v_linestyle = dv->v_linestyle;
link->vector->v_flags |= VF_PERMANENT;
} else {
link->f_own_vector = TRUE;
}
else {
link->vector = dv;
link->f_own_vector = FALSE;
}
currentgraph->plotdata = link;
/* Add the scale vector to the list of vectors associated with the plot
* and use the copy instead of the original scale vector */
link = TMALLOC(struct dveclist, 1);
link->next = currentgraph->plotdata;
* and use the copy instead of the original scale vector if requested */
{
struct dvec * const custom_scale = dv->v_scale;
if (custom_scale != (struct dvec *) NULL) {
link = TMALLOC(struct dveclist, 1);
link->next = currentgraph->plotdata;
if (copyvec) {
link->vector = vec_copy(dv->v_scale);
link->vector->v_flags |= VF_PERMANENT;
link->next->vector->v_scale = link->vector;
}
else {
link->vector = dv->v_scale;
}
if (copyvec) {
link->vector = vec_copy(dv->v_scale);
link->vector->v_flags |= VF_PERMANENT;
link->next->vector->v_scale = link->vector;
link->f_own_vector = TRUE;
}
else {
link->vector = dv->v_scale;
link->f_own_vector = FALSE;
}
/* Make the new vector the start of the list of vectors */
currentgraph->plotdata = link;
/* Make the new vector the start of the list of vectors */
currentgraph->plotdata = link;
}
}
/* Put the legend entry on the screen. */
@ -470,8 +486,7 @@ void drawlegend(GRAPH *graph, int plotno, struct dvec *dv)
/* end one plot of a graph */
void
gr_end(struct dvec *dv)
void gr_end(struct dvec *dv)
{
NG_IGNORE(dv);
DevUpdate();
@ -480,8 +495,7 @@ gr_end(struct dvec *dv)
/* Print text in the bottom line. */
void
gr_pmsg(char *text)
void gr_pmsg(char *text)
{
char buf[BSIZE_SP];
buf[0] = '\0';
@ -503,16 +517,14 @@ gr_pmsg(char *text)
}
void
gr_clean(void)
void gr_clean(void)
{
DevUpdate();
}
/* call this routine after viewport size changes */
void
gr_resize(GRAPH *graph)
void gr_resize(GRAPH *graph)
{
double oldxratio, oldyratio;
double scalex, scaley;
@ -552,8 +564,7 @@ gr_resize(GRAPH *graph)
/* PN static */
void
gr_resize_internal(GRAPH *graph)
void gr_resize_internal(GRAPH *graph)
{
if (!graph->grid.xsized)
graph->viewport.width = (int)(graph->absolute.width -
@ -579,8 +590,7 @@ gr_resize_internal(GRAPH *graph)
/* redraw everything in struct graph */
void
gr_redraw(GRAPH *graph)
void gr_redraw(GRAPH *graph)
{
struct dveclist *link;
@ -616,8 +626,7 @@ gr_redraw(GRAPH *graph)
}
void
gr_restoretext(GRAPH *graph)
void gr_restoretext(GRAPH *graph)
{
struct _keyed *k;
@ -633,7 +642,8 @@ gr_restoretext(GRAPH *graph)
*
* First, if length < IPOINTMIN, don't do anything.
*
* Second, if length = IPOINTMIN, plot what we have so far.
* Second, if length = IPOINTMIN, plot what we have so far. This step
* is essentially the initializaiton for the graph.
*
* Third, if length > IPOINTMIN, plot the last points and resize if
* needed.
@ -643,16 +653,25 @@ gr_restoretext(GRAPH *graph)
* FIXME: there is a problem with multiple iplots that use the same
* vector, namely, that vector has the same color throughout. This is
* another reason why we need to pull color and linestyle out of dvec
* XXX Or maybe even something more drastic ?? */
static int
iplot(struct plot *pl, int id)
* XXX Or maybe even something more drastic ??
* It would be better to associate a color with an instance using a
* vector than the vector itself, for which color is something artificial. */
static int iplot(struct plot *pl, int id)
{
int len = pl->pl_scale->v_length;
if (ft_grdb) {
fprintf(cp_err, "Entering iplot, len = %d\n", len);
}
/* Do simple check for exit first */
if (len < IPOINTMIN) { /* Nothing yet */
return 0;
}
struct dvec *v, *xs = pl->pl_scale;
double *lims, dy;
double start, stop, step;
register int j;
bool changed = FALSE;
int yt;
char *yl = NULL;
@ -660,51 +679,61 @@ iplot(struct plot *pl, int id)
static REQUEST reqst = { checkup_option, NULL };
int inited = 0;
char commandline[513];
int n_vec_plot = 0;
for (j = 0, v = pl->pl_dvecs; v; v = v->v_next)
if (v->v_flags & VF_PLOT)
j++;
if (!j)
return (0);
if (ft_grdb)
fprintf(cp_err, "Entering iplot, len = %d\n", len);
/* Exit if nothing is being plotted */
for (v = pl->pl_dvecs; v; v = v->v_next) {
if (v->v_flags & VF_PLOT) {
++n_vec_plot;
}
}
if (len < IPOINTMIN) {
/* Nothing yet */
return (0);
} else if (len == IPOINTMIN || !id) {
if (n_vec_plot == 0) {
return 0;
}
if (len == IPOINTMIN || !id) { /* Do initialization */
resumption = FALSE;
/* Draw the grid for the first time, and plot everything. */
lims = ft_minmax(xs, TRUE);
xlims[0] = lims[0];
xlims[1] = lims[1];
ylims[0] = HUGE;
ylims[1] = - ylims[0];
for (v = pl->pl_dvecs; v; v = v->v_next)
ylims[1] = -ylims[0];
for (v = pl->pl_dvecs; v; v = v->v_next) {
if (v->v_flags & VF_PLOT) {
lims = ft_minmax(v, TRUE);
if (ylims[0] > lims[0])
if (ylims[0] > lims[0]) {
ylims[0] = lims[0];
if (ylims[1] < lims[1])
}
if (ylims[1] < lims[1]) {
ylims[1] = lims[1];
if (!yl)
}
if (!yl) {
yl = v->v_name;
}
}
/* generate a small difference between ymin and ymax
to catch the y=const case */
if (ylims[0] == ylims[1])
ylims[1] += 1e-9;
}
if (ft_grdb)
/* Generate a small difference between ymin and ymax
to catch the y=const case */
if (ylims[0] == ylims[1]) {
ylims[1] += 1e-9;
}
if (ft_grdb) {
fprintf(cp_err,
"iplot: after 5, xlims = %G, %G, ylims = %G, %G\n",
xlims[0], xlims[1], ylims[0], ylims[1]);
}
for (yt = pl->pl_dvecs->v_type, v = pl->pl_dvecs->v_next; v; v = v->v_next)
for (yt = pl->pl_dvecs->v_type, v = pl->pl_dvecs->v_next; v;
v = v->v_next) {
if ((v->v_flags & VF_PLOT) && (v->v_type != yt)) {
yt = SV_NOTYPE;
break;
}
}
/* note: have command options for iplot to specify xdelta,
etc. So don't need static variables hack. Assume default
@ -712,25 +741,28 @@ iplot(struct plot *pl, int id)
sprintf(commandline, "plot %s", yl);
(void) gr_init(xlims, ylims, xs->v_name,
pl->pl_title, NULL, j, 0.0, 0.0,
GRID_LIN, PLOT_LIN, xs->v_name, yl, xs->v_type, yt,
plot_cur->pl_typename, commandline);
pl->pl_title, NULL, n_vec_plot, 0.0, 0.0,
GRID_LIN, PLOT_LIN, xs->v_name, yl, xs->v_type, yt,
plot_cur->pl_typename, commandline);
for (v = pl->pl_dvecs; v; v = v->v_next)
for (v = pl->pl_dvecs; v; v = v->v_next) {
if (v->v_flags & VF_PLOT) {
gr_start_internal(v, FALSE);
ft_graf(v, xs, TRUE);
}
}
inited = 1;
} else {
}
else {
/* plot the last points and resize if needed */
Input(&reqst, NULL);
/* First see if we have to make the screen bigger */
dy = (isreal(xs) ? xs->v_realdata[len - 1] :
realpart(xs->v_compdata[len - 1]));
if (ft_grdb)
if (ft_grdb) {
fprintf(cp_err, "x = %G\n", dy);
}
if (!if_tranparams(ft_curckt, &start, &stop, &step) ||
!ciprefix("tran", pl->pl_typename)) {
stop = HUGE;
@ -739,32 +771,35 @@ iplot(struct plot *pl, int id)
/* checking for x lo */
while (dy < currentgraph->data.xmin) {
changed = TRUE;
if (ft_grdb)
if (ft_grdb) {
fprintf(cp_err, "resize: xlo %G -> %G\n",
currentgraph->data.xmin,
currentgraph->data.xmin -
(currentgraph->data.xmax - currentgraph->data.xmin)
* XFACTOR);
}
/* set the new x lo value */
currentgraph->data.xmin -=
(currentgraph->data.xmax - currentgraph->data.xmin)
* XFACTOR;
(currentgraph->data.xmax - currentgraph->data.xmin)
* XFACTOR;
if (currentgraph->data.xmin < start) {
currentgraph->data.xmin = start;
break;
}
}
if (currentgraph->data.xmax < currentgraph->data.xmin)
if (currentgraph->data.xmax < currentgraph->data.xmin) {
currentgraph->data.xmax = currentgraph->data.xmin;
}
/* checking for x hi */
while (dy > currentgraph->data.xmax) {
changed = TRUE;
if (ft_grdb)
if (ft_grdb) {
fprintf(cp_err, "resize: xhi %G -> %G\n",
currentgraph->data.xmax,
currentgraph->data.xmax +
(currentgraph->data.xmax - currentgraph->data.xmin)
* XFACTOR);
}
/* set the new x hi value */
currentgraph->data.xmax +=
(currentgraph->data.xmax - currentgraph->data.xmin) *
@ -776,21 +811,24 @@ iplot(struct plot *pl, int id)
}
/* checking for all y values */
for (v = pl->pl_dvecs; v; v = v->v_next) {
if (!(v->v_flags & VF_PLOT))
if (!(v->v_flags & VF_PLOT)) {
continue;
}
dy = (isreal(v) ? v->v_realdata[len - 1] :
realpart(v->v_compdata[len - 1]));
if (ft_grdb)
if (ft_grdb) {
fprintf(cp_err, "y = %G\n", dy);
}
/* checking for y lo */
while (dy < currentgraph->data.ymin) {
changed = TRUE;
if (ft_grdb)
if (ft_grdb) {
fprintf(cp_err, "resize: ylo %G -> %G\n",
currentgraph->data.ymin,
currentgraph->data.ymin -
(currentgraph->data.ymax - currentgraph->data.ymin)
* YFACTOR);
}
/* set the new y lo value */
currentgraph->data.ymin -=
(currentgraph->data.ymax - currentgraph->data.ymin)
@ -800,17 +838,19 @@ iplot(struct plot *pl, int id)
/* currentgraph->data.ymin = dy;
currentgraph->data.ymin *= (1 + YFACTOR); */
}
if (currentgraph->data.ymax < currentgraph->data.ymin)
if (currentgraph->data.ymax < currentgraph->data.ymin) {
currentgraph->data.ymax = currentgraph->data.ymin;
}
/* checking for y hi */
while (dy > currentgraph->data.ymax) {
changed = TRUE;
if (ft_grdb)
if (ft_grdb) {
fprintf(cp_err, "resize: yhi %G -> %G\n",
currentgraph->data.ymax,
currentgraph->data.ymax +
(currentgraph->data.ymax - currentgraph->data.ymin)
* YFACTOR);
}
/* set the new y hi value */
currentgraph->data.ymax +=
(currentgraph->data.ymax - currentgraph->data.ymin)
@ -829,10 +869,11 @@ iplot(struct plot *pl, int id)
#ifndef X_DISPLAY_MISSING
gr_redraw(currentgraph);
#endif
} else {
}
else {
/* Just connect the last two points. This won't be done
* with curve interpolation, so it might look funny. */
for (v = pl->pl_dvecs; v; v = v->v_next)
for (v = pl->pl_dvecs; v; v = v->v_next) {
if (v->v_flags & VF_PLOT) {
gr_point(v,
(isreal(xs) ? xs->v_realdata[len - 1] :
@ -845,15 +886,15 @@ iplot(struct plot *pl, int id)
realpart(v->v_compdata[len - 2])),
len - 1);
}
}
}
}
DevUpdate();
return (inited);
return inited;
}
static void
set(struct plot *plot, struct dbcomm *db, bool unset, short mode)
static void set(struct plot *plot, struct dbcomm *db, bool unset, short mode)
{
struct dvec *v;
struct dbcomm *dc;
@ -885,8 +926,7 @@ set(struct plot *plot, struct dbcomm *db, bool unset, short mode)
}
static char *
getitright(char *buf, double num)
static char *getitright(char *buf, double num)
{
char *p;
int k;
@ -909,16 +949,14 @@ getitright(char *buf, double num)
static int hit, hit2;
void
reset_trace(void)
void reset_trace(void)
{
hit = -1;
hit2 = -1;
}
void
gr_iplot(struct plot *plot)
void gr_iplot(struct plot *plot)
{
struct dbcomm *db;
int dontpop; /* So we don't pop w/o push. */
@ -959,10 +997,12 @@ gr_iplot(struct plot *plot)
if (v->v_flags & VF_PRINT) {
u = plot->pl_scale;
if (len <= 1 || hit <= 0 || hit2 < 0) {
if (len <= 1 || hit2 < 0)
if (len <= 1 || hit2 < 0) {
term_clear();
else
}
else {
term_home();
}
hit = 1;
hit2 = 1;
printf(
@ -975,7 +1015,8 @@ gr_iplot(struct plot *plot)
if (isreal(u)) {
printf("%s",
getitright(buf, u->v_realdata[len - 1]));
} else {
}
else {
/* MW. Complex data here, realdata is NULL
(why someone use realdata here again) */
printf("%s",
@ -987,12 +1028,14 @@ gr_iplot(struct plot *plot)
printf("\n");
}
}
if (v == u)
if (v == u) {
continue;
}
printf("%12s:", v->v_name);
if (isreal(v)) {
printf("%s", getitright(buf, v->v_realdata[len - 1]));
} else {
}
else {
/* MW. Complex data again */
printf("%s", getitright(buf, v->v_compdata[len - 1].cx_real));
printf(", %s", getitright(buf, v->v_compdata[len - 1].cx_imag));
@ -1014,8 +1057,7 @@ gr_iplot(struct plot *plot)
* Note: This is a clear case for separating the linestyle and color
* fields from dvec. */
void
gr_end_iplot(void)
void gr_end_iplot(void)
{
struct dbcomm *db, *prev, *next;
GRAPH *graph;
@ -1034,7 +1076,8 @@ gr_end_iplot(void)
ft_curckt->ci_dbs = dbs = next;
dbfree1(db);
}
} else if (db->db_type == DB_IPLOT || db->db_type == DB_IPLOTALL) {
}
else if (db->db_type == DB_IPLOT || db->db_type == DB_IPLOTALL) {
if (db->db_graphid) {
/* get private copy of dvecs */
@ -1063,8 +1106,7 @@ gr_end_iplot(void)
}
double *
readtics(char *string)
double *readtics(char *string)
{
int k;
char *words, *worde;

View File

@ -44,232 +44,320 @@ static GBUCKET GBucket[NUMGBUCKETS];
/* note: Zero is not a valid id. This is used in plot() in graf.c. */
static int RunningId = 1;
/* initialize graph structure */
#define SETGRAPH(pgraph, id) \
do { \
(pgraph)->graphid = (id); \
(pgraph)->degree = 1; \
(pgraph)->linestyle = -1; \
} while(0)
/* returns NULL on error */
GRAPH *
NewGraph(void)
/* Initialize graph structure */
static inline void setgraph(GRAPH *pgraph, int id)
{
pgraph->graphid = id;
pgraph->degree = 1;
pgraph->linestyle = -1;
} /* end of function setgraph */
/* Creates a new graph. Returns NULL on error */
GRAPH *NewGraph(void)
{
GRAPH *pgraph;
LISTGRAPH *list;
int BucketId = RunningId % NUMGBUCKETS;
const int BucketId = RunningId % NUMGBUCKETS;
if ((list = TMALLOC(LISTGRAPH, 1)) == NULL) {
internalerror("can't allocate a listgraph");
return (NULL);
return (GRAPH *) NULL;
}
pgraph = &list->graph;
SETGRAPH(pgraph, RunningId);
GRAPH * const pgraph = &list->graph;
setgraph(pgraph, RunningId);
GBUCKET *p_bucket = GBucket + BucketId;
if (!GBucket[BucketId].list) {
GBucket[BucketId].list = list;
} else {
/* Add to the appropriate bucket at the front of the linked list */
if (!p_bucket->list) { /* no list yet */
p_bucket->list = list;
}
else {
/* insert at front of current list */
list->next = GBucket[BucketId].list;
GBucket[BucketId].list = list;
list->next = p_bucket->list;
p_bucket->list = list;
}
RunningId++;
return (pgraph);
}
return pgraph;
} /* end of function NewGraph */
/* Given graph id, return graph */
GRAPH *
FindGraph(int id)
GRAPH *FindGraph(int id)
{
LISTGRAPH *list;
/* Step through list of graphs until found or list ends */
for (list = GBucket[id % NUMGBUCKETS].list;
list && list->graph.graphid != id;
list = list->next)
list && list->graph.graphid != id;
list = list->next) {
;
}
if (list)
return (&list->graph);
else
return (NULL);
}
if (list) { /* found */
return &list->graph;
}
else {
return (GRAPH *) NULL;
}
} /* end of function FindGraph */
GRAPH *
CopyGraph(GRAPH *graph)
GRAPH *CopyGraph(GRAPH *graph)
{
GRAPH *ret;
struct _keyed *k;
struct dveclist *link, *newlink;
if (!graph)
if (!graph) {
return NULL;
}
ret = NewGraph();
memcpy(ret, graph, sizeof(GRAPH)); /* va: compatible pointer types */
ret->graphid = RunningId - 1; /* restore id */
{
const int id = ret->graphid; /* save ID of the new graph */
memcpy(ret, graph, sizeof(GRAPH)); /* copy graph info (inc. ID) */
ret->graphid = id; /* restore ID */
}
/* copy keyed */
for (ret->keyed = NULL, k = graph->keyed; k; k = k->next)
SaveText(ret, k->text, k->x, k->y);
/* copy dvecs */
ret->plotdata = NULL;
for (link = graph->plotdata; link; link = link->next) {
newlink = TMALLOC(struct dveclist, 1);
newlink->next = ret->plotdata;
newlink->vector = vec_copy(link->vector);
/* vec_copy doesn't set v_color or v_linestyle */
newlink->vector->v_color = link->vector->v_color;
newlink->vector->v_linestyle = link->vector->v_linestyle;
newlink->vector->v_flags |= VF_PERMANENT;
ret->plotdata = newlink;
{
struct _keyed *k;
for (ret->keyed = NULL, k = graph->keyed; k; k = k->next) {
SaveText(ret, k->text, k->x, k->y);
}
}
/* copy dvecs or reuse if "borrowed" already */
{
struct dveclist *new_plotdata = (struct dveclist *) NULL;
for (link = graph->plotdata; link; link = link->next) {
if (link->f_own_vector) {
struct dvec * const old_vector = link->vector;
struct dvec * const new_vector = vec_copy(old_vector);
/* vec_copy doesn't set v_color or v_linestyle */
new_vector->v_color = old_vector->v_color;
new_vector->v_linestyle = old_vector->v_linestyle;
new_vector->v_flags |= VF_PERMANENT;
newlink = TMALLOC(struct dveclist, 1);
newlink->next = new_plotdata;
newlink->f_own_vector = TRUE;
newlink->vector = new_vector;
/* If the link owns the vector, it also owns its scale
* vector, if present */
struct dvec *old_scale = old_vector->v_scale;
if (old_scale != (struct dvec *) NULL) {
new_plotdata = newlink; /* put in front */
struct dvec * const new_scale = vec_copy(old_scale);
new_scale->v_flags |= VF_PERMANENT;
newlink = TMALLOC(struct dveclist, 1);
newlink->next = new_plotdata;
newlink->f_own_vector = TRUE;
newlink->vector = new_scale;
newlink->next = new_plotdata;
}
}
else {
newlink->vector = link->vector;
newlink->f_own_vector = FALSE;
}
new_plotdata = newlink; /* put in front */
}
ret->plotdata = new_plotdata; /* give vector list to plot */
} /* end of block copying or reusing dvecs */
ret->commandline = copy(graph->commandline);
ret->plotname = copy(graph->plotname);
return (ret);
}
{
const char * const lbl = graph->grid.xlabel;
if (lbl) {
ret->grid.xlabel = copy(lbl);
}
}
{
const char * const lbl = graph->grid.ylabel;
if (lbl) {
ret->grid.ylabel = copy(lbl);
}
}
/* Copy devdep information and size if present */
{
const void * const p = graph->devdep;
if (p != NULL) {
const size_t n = ret->n_byte_devdep = graph->n_byte_devdep;
void * const dst = ret->devdep = tmalloc(n);
(void) memcpy(dst, graph->devdep, n);
}
}
return ret;
} /* end of function CopyGraph */
int
DestroyGraph(int id)
int DestroyGraph(int id)
{
LISTGRAPH *list, *lastlist;
struct _keyed *k, *nextk;
struct dveclist *d, *nextd;
struct dbcomm *db;
/* Locate hash bucket for this graph */
const int index = id % NUMGBUCKETS;
LISTGRAPH *list = GBucket[index].list;
list = GBucket[id % NUMGBUCKETS].list;
lastlist = NULL;
/* Pointer before current one. Allows fixing list when the current
* node is deleted. Init to NULL to indicate that at head of list */
LISTGRAPH *lastlist = (LISTGRAPH *) NULL;
/* Step through graphs in the bucket until the one with id is found */
while (list) {
if (list->graph.graphid == id) { /* found it */
struct _keyed *k, *nextk;
struct dbcomm *db;
/* Fix the iplot/trace dbs list */
for (db = dbs; db && db->db_graphid != id; db = db->db_next)
for (db = dbs; db && db->db_graphid != id; db = db->db_next) {
;
if (db && (db->db_type == DB_IPLOT ||
db->db_type == DB_IPLOTALL))
{
db->db_type = DB_DEADIPLOT;
/* Delete this later */
return (0);
}
/* adjust bucket pointers */
if (lastlist)
lastlist->next = list->next;
else
GBucket[id % NUMGBUCKETS].list = list->next;
if (db && (db->db_type == DB_IPLOT ||
db->db_type == DB_IPLOTALL)) {
db->db_type = DB_DEADIPLOT;
/* Delete this later */
return 0;
}
/* run through and de-allocate dynamically allocated keyed list */
/* Adjust bucket pointers to remove the current node */
if (lastlist) { /* not at front */
lastlist->next = list->next;
}
else { /* at front */
GBucket[index].list = list->next;
}
/* Run through and de-allocate dynamically allocated keyed list */
k = list->graph.keyed;
while (k) {
nextk = k->next;
tfree(k->text);
tfree(k);
txfree(k->text);
txfree(k);
k = nextk;
}
/* de-allocate dveclist */
d = list->graph.plotdata;
while (d) {
nextd = d->next;
dvec_free(d->vector);
tfree(d);
d = nextd;
/* Free vectors owned by this graph and free the list */
{
struct dveclist *d = list->graph.plotdata;
struct dveclist *nextd;
while (d != (struct dveclist *) NULL) {
nextd = d->next;
if (d->f_own_vector) {
/* list responsible for freeing this vector */
dvec_free(d->vector);
}
txfree(d);
d = nextd;
}
}
tfree(list->graph.commandline);
tfree(list->graph.plotname);
txfree(list->graph.commandline);
txfree(list->graph.plotname);
txfree(list->graph.grid.xlabel);
txfree(list->graph.grid.ylabel);
/* If device dependent space allocated, free it. */
if (list->graph.devdep)
tfree(list->graph.devdep);
tfree(list);
/* If device-dependent space was allocated, free it. */
{
void * const p = list->graph.devdep;
if (p) {
txfree(p);
}
}
return (1);
}
lastlist = list;
list = list->next;
}
txfree(list);
return 1;
} /* end of case that graph ID was found */
lastlist = list; /* update previous node */
list = list->next; /* step to next node */
} /* end of loop over graphs in the current bucket */
/* The graph with ID id was not found */
internalerror("tried to destroy non-existent graph");
return (0);
}
return 0;
} /* end of function DestroyGraph */
/* free up all dynamically allocated data structures */
void
FreeGraphs(void)
/* Free up all dynamically allocated data structures */
void FreeGraphs(void)
{
/* Iterate over all hash buckets */
GBUCKET *gbucket;
LISTGRAPH *list, *deadl;
for (gbucket = GBucket; gbucket < &GBucket[NUMGBUCKETS]; gbucket++) {
list = gbucket->list;
while (list) {
deadl = list;
LISTGRAPH * list = gbucket->list; /* linked list of graphs here */
while (list) { /* Free each until end of list */
LISTGRAPH *deadl = list;
list = list->next;
tfree(deadl);
txfree(deadl);
}
}
}
} /* end of functdion FreeGraphs */
void
SetGraphContext(int graphid)
/* This function sets global varial currentgraph based on graphid */
void SetGraphContext(int graphid)
{
currentgraph = FindGraph(graphid);
}
} /* end of function SetGraphContext */
/* Stack of graph objects implemented as a linked list */
typedef struct gcstack {
GRAPH *pgraph;
struct gcstack *next;
} GCSTACK;
GCSTACK *gcstacktop;
static GCSTACK *gcstacktop; /* top of the stack of graphs */
/* note: This Push and Pop has tricky semantics.
Push(graph) will push the currentgraph onto the stack
and set currentgraph to graph.
Pop() simply sets currentgraph to the top of the stack and pops stack.
Pop() simply sets currentgraph to previous value at the top of the stack
and pops stack.
*/
void
PushGraphContext(GRAPH *graph)
void PushGraphContext(GRAPH *graph)
{
GCSTACK *gcstack = TMALLOC(GCSTACK, 1);
if (!gcstacktop) {
gcstacktop = gcstack;
} else {
}
else {
gcstack->next = gcstacktop;
gcstacktop = gcstack;
}
gcstacktop->pgraph = currentgraph;
currentgraph = graph;
}
} /* end of function PushGraphContext */
void
PopGraphContext(void)
void PopGraphContext(void)
{
GCSTACK *dead;
currentgraph = gcstacktop->pgraph;
dead = gcstacktop;
currentgraph = gcstacktop->pgraph; /* pop from stack, making current */
GCSTACK *dead = gcstacktop; /* remove from stack */
gcstacktop = gcstacktop->next;
tfree(dead);
}
txfree(dead); /* free allocation */
} /* end of function PopGraphContext */

View File

@ -835,90 +835,111 @@ done:
free_pnode(names);
}
void
com_destroy(wordlist *wl)
/* Free resources associated with "plot" datasets. The wordlist contains
* the names of the plots to delete or the word "all" to delete all but the
* default "const" plot, which cannot be deleted, even by name. If there are
* no names given, the current plot is deleted */
void com_destroy(wordlist *wl)
{
struct plot *pl, *npl = NULL;
/* If no name given, delete the current output data */
if (!wl) {
DelPlotWindows(plot_cur);
killplot(plot_cur);
} else if (eq(wl->wl_word, "all")) {
}
else if (eq(wl->wl_word, "all")) { /* "all" -> all plots deleted */
struct plot *pl, *npl = NULL;
for (pl = plot_list; pl; pl = npl) {
npl = pl->pl_next;
if (!eq(pl->pl_typename, "const")) {
DelPlotWindows(pl);
killplot(pl);
} else {
}
else {
plot_num = 1;
}
}
} else {
}
else { /* list of plots by name */
while (wl) {
for (pl = plot_list; pl; pl = pl->pl_next)
if (eq(pl->pl_typename, wl->wl_word))
struct plot *pl;
for (pl = plot_list; pl; pl = pl->pl_next) {
if (eq(pl->pl_typename, wl->wl_word)) {
break;
}
}
if (pl) {
DelPlotWindows(pl);
killplot(pl);
} else {
}
else {
fprintf(cp_err, "Error: no such plot %s\n", wl->wl_word);
}
wl = wl->wl_next;
}
}
}
} /* end of function com_destroy */
static void
killplot(struct plot *pl)
static void killplot(struct plot *pl)
{
struct dvec *v, *nv = NULL;
struct plot *op;
if (eq(pl->pl_typename, "const")) {
fprintf(cp_err, "Error: can't destroy the constant plot\n");
return;
}
/* pl_dvecs, pl_scale */
for (v = pl->pl_dvecs; v; v = nv) {
nv = v->v_next;
vec_free(v);
{
struct dvec *v;
struct dvec *nv;
for (v = pl->pl_dvecs; v; v = nv) {
nv = v->v_next;
vec_free(v);
}
}
/* unlink from plot_list (linked via pl_next) */
if (pl == plot_list) {
if (pl == plot_list) { /* First in list */
plot_list = pl->pl_next;
if (pl == plot_cur)
if (pl == plot_cur) {
plot_cur = plot_list;
} else {
for (op = plot_list; op; op = op->pl_next)
if (op->pl_next == pl)
}
}
else { /* inside list */
struct plot *op;
for (op = plot_list; op; op = op->pl_next) {
if (op->pl_next == pl) {
break;
if (!op)
}
}
if (!op) {
fprintf(cp_err,
"Internal Error: kill plot -- not in list\n");
return;
}
op->pl_next = pl->pl_next;
if (pl == plot_cur)
if (pl == plot_cur) {
plot_cur = op;
}
}
/* delete the hash table entry for this plot */
if (pl->pl_lookup_table)
if (pl->pl_lookup_table) {
nghash_free(pl->pl_lookup_table, NULL, NULL);
tfree(pl->pl_title);
tfree(pl->pl_name);
tfree(pl->pl_typename);
}
txfree(pl->pl_title);
txfree(pl->pl_name);
txfree(pl->pl_typename);
wl_free(pl->pl_commands);
tfree(pl->pl_date); /* va: also tfree (memory leak) */
if (pl->pl_ccom) /* va: also tfree (memory leak) */
txfree(pl->pl_date); /* va: also tfree (memory leak) */
if (pl->pl_ccom) { /* va: also tfree (memory leak) */
throwaway(pl->pl_ccom);
}
if (pl->pl_env) { /* The 'environment' for this plot. */
/* va: HOW to do? */
printf("va: killplot should tfree pl->pl_env=(%p)\n", pl->pl_env);
fflush(stdout);
}
tfree(pl); /* va: also tfree pl itself (memory leak) */
txfree(pl); /* va: also tfree pl itself (memory leak) */
}

View File

@ -369,8 +369,7 @@ dosim(
/* Usage is run [filename] */
void
com_run(wordlist *wl)
void com_run(wordlist *wl)
{
/* ft_getsaves(); */
dosim("run", wl);

View File

@ -938,8 +938,9 @@ wordlist *vareval(/* NOT const */ char *string)
break;
if (!v) {
v = cp_enqvar(string, &tbfreed);
if (tbfreed)
if (tbfreed) {
vfree = v;
}
}
wl = wl_cons(copy(v ? "1" : "0"), NULL);
free_struct_variable(vfree);
@ -948,13 +949,16 @@ wordlist *vareval(/* NOT const */ char *string)
case '#':
string++;
for (v = variables; v; v = v->va_next)
if (eq(v->va_name, string))
for (v = variables; v; v = v->va_next) {
if (eq(v->va_name, string)) {
break;
}
}
if (!v) {
v = cp_enqvar(string, &tbfreed);
if (tbfreed)
if (tbfreed) {
vfree = v;
}
}
if (!v) {
fprintf(cp_err, "Error: %s: no such variable.\n", string);
@ -989,17 +993,20 @@ wordlist *vareval(/* NOT const */ char *string)
if (eq(v->va_name, string))
break;
if (!v && isdigit_c(*string)) {
for (v = variables; v; v = v->va_next)
if (eq(v->va_name, "argv"))
for (v = variables; v; v = v->va_next) {
if (eq(v->va_name, "argv")) {
break;
}
}
range = string;
}
if (!v) {
range = NULL;
string = oldstring;
v = cp_enqvar(string, &tbfreed);
if (tbfreed)
if (tbfreed) {
vfree = v;
}
}
if (!v && (s = getenv(string)) != NULL) {
wl = wl_cons(copy(s), NULL);
@ -1020,10 +1027,12 @@ wordlist *vareval(/* NOT const */ char *string)
wordlist *r = NULL;
if (*range == '$') {
char *t = ++range;
if (*t == '&')
if (*t == '&') {
t++;
while (isalnum_c(*t))
}
while (isalnum_c(*t)) {
t++;
}
*t = '\0';
r = vareval(range);
if (!r || r->wl_next) {
@ -1034,15 +1043,20 @@ wordlist *vareval(/* NOT const */ char *string)
}
range = r->wl_word;
}
for (low = 0; isdigit_c(*range); range++)
for (low = 0; isdigit_c(*range); range++) {
low = low * 10 + *range - '0';
if ((*range == '-') && isdigit_c(range[1]))
for (up = 0, range++; isdigit_c(*range); range++)
}
if ((*range == '-') && isdigit_c(range[1])) {
for (up = 0, range++; isdigit_c(*range); range++) {
up = up * 10 + *range - '0';
else if (*range == '-')
}
}
else if (*range == '-') {
up = wl_length(wl);
else
}
else {
up = low;
}
up--, low--;
wl = wl_range(wl, low, up);
wl_free(r);
@ -1059,23 +1073,23 @@ struct xxx {
};
static int
vcmp(const void *a, const void *b)
static int vcmp(const void *a, const void *b)
{
int i;
struct xxx *v1 = (struct xxx *) a;
struct xxx *v2 = (struct xxx *) b;
if ((i = strcmp(v1->x_v->va_name, v2->x_v->va_name)) != 0)
return (i);
else
return (v1->x_char - v2->x_char);
if ((i = strcmp(v1->x_v->va_name, v2->x_v->va_name)) != 0) {
return i;
}
else {
return v1->x_char - v2->x_char;
}
}
/* Print the values of currently defined variables. */
void
cp_vprint(void)
void cp_vprint(void)
{
struct variable *v;
struct variable *uv1;
@ -1086,16 +1100,22 @@ cp_vprint(void)
uv1 = cp_usrvars();
for (v = variables, i = 0; v; v = v->va_next)
for (v = variables, i = 0; v; v = v->va_next) {
i++;
for (v = uv1; v; v = v->va_next)
}
for (v = uv1; v; v = v->va_next) {
i++;
if (plot_cur)
for (v = plot_cur->pl_env; v; v = v->va_next)
}
if (plot_cur) {
for (v = plot_cur->pl_env; v; v = v->va_next) {
i++;
if (ft_curckt)
for (v = ft_curckt->ci_vars; v; v = v->va_next)
}
}
if (ft_curckt) {
for (v = ft_curckt->ci_vars; v; v = v->va_next) {
i++;
}
}
vars = TMALLOC(struct xxx, i);
@ -1108,26 +1128,30 @@ cp_vprint(void)
vars[i].x_v = v;
vars[i].x_char = '*';
}
if (plot_cur)
if (plot_cur) {
for (v = plot_cur->pl_env; v; v = v->va_next, i++) {
vars[i].x_v = v;
vars[i].x_char = '*';
}
if (ft_curckt)
}
if (ft_curckt) {
for (v = ft_curckt->ci_vars; v; v = v->va_next, i++) {
vars[i].x_v = v;
vars[i].x_char = '+';
}
}
qsort(vars, (size_t) i, sizeof(*vars), vcmp);
for (j = 0; j < i; j++) {
if (j && eq(vars[j].x_v->va_name, vars[j-1].x_v->va_name))
if (j && eq(vars[j].x_v->va_name, vars[j-1].x_v->va_name)) {
continue;
}
v = vars[j].x_v;
if (v->va_type == CP_BOOL) {
out_printf("%c %s\n", vars[j].x_char, v->va_name);
} else {
}
else {
out_printf("%c %s\t", vars[j].x_char, v->va_name);
wl = vareval(v->va_name);
s = wl_flatten(wl);
@ -1140,88 +1164,86 @@ cp_vprint(void)
free_struct_variable(uv1);
tfree(vars);
}
} /* end of function cp_vprint */
struct variable *
var_alloc(char *name, struct variable *next)
struct variable *var_alloc(char *name, struct variable *next)
{
struct variable *v = TMALLOC(struct variable, 1);
ZERO(v, struct variable);
v -> va_name = name;
v -> va_next = next;
return v;
struct variable * const v = TMALLOC(struct variable, 1);
ZERO(v, struct variable);
v -> va_name = name;
v -> va_next = next;
return v;
}
struct variable *
var_alloc_bool(char *name, bool value, struct variable *next)
struct variable *var_alloc_bool(char *name, bool value,
struct variable *next)
{
struct variable *v = var_alloc(name, next);
var_set_bool(v, value);
return v;
}
struct variable *
var_alloc_num(char *name, int value, struct variable *next)
struct variable *var_alloc_num(char *name, int value,
struct variable *next)
{
struct variable *v = var_alloc(name, next);
var_set_num(v, value);
return v;
}
struct variable *
var_alloc_real(char *name, double value, struct variable *next)
struct variable *var_alloc_real(char *name, double value,
struct variable *next)
{
struct variable *v = var_alloc(name, next);
var_set_real(v, value);
return v;
}
struct variable *
var_alloc_string(char *name, char * value, struct variable *next)
struct variable *var_alloc_string(char *name, char * value,
struct variable *next)
{
struct variable *v = var_alloc(name, next);
var_set_string(v, value);
return v;
}
struct variable *
var_alloc_vlist(char *name, struct variable * value, struct variable *next)
struct variable * var_alloc_vlist(char *name, struct variable * value,
struct variable *next)
{
struct variable *v = var_alloc(name, next);
var_set_vlist(v, value);
return v;
}
void
var_set_bool(struct variable *v, bool value)
void var_set_bool(struct variable *v, bool value)
{
v->va_type = CP_BOOL;
v->va_bool = value;
}
void
var_set_num(struct variable *v, int value)
void var_set_num(struct variable *v, int value)
{
v->va_type = CP_NUM;
v->va_num = value;
}
void
var_set_real(struct variable *v, double value)
void var_set_real(struct variable *v, double value)
{
v->va_type = CP_REAL;
v->va_real = value;
}
void
var_set_string(struct variable *v, char *value)
void var_set_string(struct variable *v, char *value)
{
v->va_type = CP_STRING;
v->va_string = value;
}
void
var_set_vlist(struct variable *v, struct variable *value)
void var_set_vlist(struct variable *v, struct variable *value)
{
v->va_type = CP_LIST;
v->va_vlist = value;

View File

@ -1065,7 +1065,7 @@ vec_basename(struct dvec *v)
}
/* get address of plot named 'name' */
struct plot *get_plot(char* name)
struct plot *get_plot(const char *name)
{
@ -1086,9 +1086,7 @@ struct plot *get_plot(char* name)
* va: ATTENTION: has unlinked old keyword-class-tree from keywords[CT_VECTOR]
* (potentially memory leak)
*/
void
plot_setcur(char *name)
void plot_setcur(const char *name)
{
struct plot *pl;
@ -1103,28 +1101,43 @@ plot_setcur(char *name)
}
/* plots are listed in pl in reverse order */
else if (cieq(name, "previous")) {
if (plot_cur->pl_next)
if (plot_cur->pl_next) {
plot_cur = plot_cur->pl_next;
else
fprintf(cp_err, "Warning: Switching to previous plot not possible, stay with current plot (%s)\n", plot_cur->pl_typename);
return;
} else if (cieq(name, "next")) {
struct plot *prev_pl = NULL;
for (pl = plot_list; pl; pl = pl->pl_next) {
if (pl == plot_cur)
break;
prev_pl = pl;
}
if (!prev_pl) {
fprintf(cp_err, "Warning: Switching to next plot not possible, stay with current plot (%s)\n", plot_cur->pl_typename);
return;
else {
fprintf(cp_err,
"Warning: No previous plot is available. "
"Plot remains unchanged (%s).\n",
plot_cur->pl_typename);
}
plot_cur = prev_pl;
return;
}
pl = get_plot(name);
if (!pl)
else if (cieq(name, "next")) {
/* Step through the list, which has plots in reverse order */
struct plot *prev_pl = NULL;
for (pl = plot_list; pl; pl = pl->pl_next) {
if (pl == plot_cur) {
break;
}
prev_pl = pl;
}
if (prev_pl) { /* found */
plot_cur = prev_pl;
}
else { /* no next plot */
fprintf(cp_err,
"Warning: No next plot is available. "
"Plot remains unchanged (%s).\n",
plot_cur->pl_typename);
}
return;
}
pl = get_plot(name);
if (!pl) {
return;
}
/* va: we skip cp_kwswitch, because it confuses the keyword-tree management for
* repeated op-commands. When however cp_kwswitch is necessary for other
* reasons, we should hold the original keyword table pointer in an
@ -1135,15 +1148,14 @@ plot_setcur(char *name)
}
*/
plot_cur = pl;
}
} /* end of function plot_setcur */
/* Add a plot to the plot list. This is different from plot_add() in that
* all this does is update the list and the variable $plots.
*/
void
plot_new(struct plot *pl)
void plot_new(struct plot *pl)
{
pl->pl_next = plot_list;
plot_list = pl;

View File

@ -4,7 +4,7 @@
//typedef unsigned char bool;
typedef int bool;
typedef int BOOL ;
typedef int BOOL;
#define BOOLEAN int
#define TRUE 1

View File

@ -1,6 +1,7 @@
#ifndef ngspice_DVEC_H
#define ngspice_DVEC_H
#include "ngspice/bool.h"
#include "ngspice/complex.h"
#include "ngspice/grid.h"
#include "ngspice/sim.h"
@ -8,14 +9,14 @@
/* Dvec flags. */
enum dvec_flags {
VF_REAL = (1 << 0), /* The data is real. */
VF_COMPLEX = (1 << 1), /* The data is complex. */
VF_ACCUM = (1 << 2), /* writedata should save this vector. */
VF_PLOT = (1 << 3), /* writedata should incrementally plot it. */
VF_PRINT = (1 << 4), /* writedata should print this vector. */
VF_MINGIVEN = (1 << 5), /* The v_minsignal value is valid. */
VF_MAXGIVEN = (1 << 6), /* The v_maxsignal value is valid. */
VF_PERMANENT = (1 << 7) /* Don't garbage collect this vector. */
VF_REAL = (1 << 0), /* The data is real. */
VF_COMPLEX = (1 << 1), /* The data is complex. */
VF_ACCUM = (1 << 2), /* writedata should save this vector. */
VF_PLOT = (1 << 3), /* writedata should incrementally plot it. */
VF_PRINT = (1 << 4), /* writedata should print this vector. */
VF_MINGIVEN = (1 << 5), /* The v_minsignal value is valid. */
VF_MAXGIVEN = (1 << 6), /* The v_maxsignal value is valid. */
VF_PERMANENT = (1 << 7) /* Don't garbage collect this vector. */
};
@ -36,41 +37,46 @@ typedef enum {
#define MAXDIMS 8
struct dvec {
char *v_name; /* Same as so_vname. */
char *v_name; /* Same as so_vname. */
enum simulation_types v_type; /* Same as so_vtype. */
short v_flags; /* Flags (a combination of VF_*). */
double *v_realdata; /* Real data. */
ngcomplex_t *v_compdata; /* Complex data. */
double v_minsignal; /* Minimum value to plot. */
double v_maxsignal; /* Maximum value to plot. */
GRIDTYPE v_gridtype; /* One of GRID_*. */
PLOTTYPE v_plottype; /* One of PLOT_*. */
int v_length; /* Length of the vector. */
int v_alloc_length; /* How much has been actually allocated. */
int v_rlength; /* How much space we really have. Used as binary flag */
int v_outindex; /* Index if writedata is building the
vector. */
int v_linestyle; /* What line style we are using. */
int v_color; /* What color we are using. */
char *v_defcolor; /* The name of a color to use. */
int v_numdims; /* How many dims -- 0 = scalar (len = 1). */
int v_dims[MAXDIMS]; /* The actual size in each dimension. */
struct plot *v_plot; /* The plot structure (if it has one). */
struct dvec *v_next; /* Link for list of plot vectors. */
struct dvec *v_link2; /* Extra link for things like print. */
struct dvec *v_scale; /* If this has a non-standard scale... */
short v_flags; /* Flags (a combination of VF_*). */
double *v_realdata; /* Real data. */
ngcomplex_t *v_compdata; /* Complex data. */
double v_minsignal; /* Minimum value to plot. */
double v_maxsignal; /* Maximum value to plot. */
GRIDTYPE v_gridtype; /* One of GRID_*. */
PLOTTYPE v_plottype; /* One of PLOT_*. */
int v_length; /* Length of the vector. */
int v_alloc_length; /* How much has been actually allocated. */
int v_rlength; /* How much space we really have. Used as binary flag */
int v_outindex; /* Index if writedata is building the vector. */
int v_linestyle; /* What line style we are using. */
int v_color; /* What color we are using. */
char *v_defcolor; /* The name of a color to use. */
int v_numdims; /* How many dims -- 0 = scalar (len = 1). */
int v_dims[MAXDIMS]; /* The actual size in each dimension. */
struct plot *v_plot; /* The plot structure (if it has one). */
struct dvec *v_next; /* Link for list of plot vectors. */
struct dvec *v_link2; /* Extra link for things like print. */
struct dvec *v_scale; /* If this has a non-standard scale... */
} ;
#define isreal(v) ((v)->v_flags & VF_REAL)
#define isreal(v) ((v)->v_flags & VF_REAL)
#define iscomplex(v) ((v)->v_flags & VF_COMPLEX)
/* list of data vectors being displayed */
struct dveclist {
struct dvec *vector;
struct dveclist *next;
struct dvec *vector;
/* Flag that this list owns the vector in the sense that it is
* responsible for freeing it. Depending on how the entry was created,
* it either made its own copy or "borrowed" one from anothe use. */
bool f_own_vector;
};
struct dvec *dvec_alloc(char *name, int type, short flags, int length, void *storage);
struct dvec *dvec_alloc(const char *name,
int type, short flags, int length, void *storage);
void dvec_realloc(struct dvec *v, int length, void *storage);
void dvec_extend(struct dvec *v, int length);
void dvec_trunc(struct dvec *v, int length);

View File

@ -359,8 +359,8 @@ extern void ft_loadfile(char *file);
extern void vec_new(struct dvec *d);
extern void plot_docoms(wordlist *wl);
extern void vec_remove(const char *name);
extern void plot_setcur(char *name);
extern struct plot *get_plot(char* name);
extern void plot_setcur(const char *name);
extern struct plot *get_plot(const char *name);
extern void plot_new(struct plot *pl);
extern char *vec_basename(struct dvec *v);
extern void vec_transpose(struct dvec *v);