2000-04-27 22:03:57 +02:00
|
|
|
/**********
|
|
|
|
|
Copyright 1990 Regents of the University of California. All rights reserved.
|
2005-05-29 03:05:33 +02:00
|
|
|
$Id$
|
2000-04-27 22:03:57 +02:00
|
|
|
**********/
|
|
|
|
|
|
|
|
|
|
/*
|
|
|
|
|
Manage graph data structure.
|
|
|
|
|
*/
|
|
|
|
|
|
2000-05-13 19:28:16 +02:00
|
|
|
#include <ngspice.h>
|
|
|
|
|
#include <graph.h>
|
|
|
|
|
#include <ftedebug.h>
|
|
|
|
|
#include <fteext.h>
|
|
|
|
|
|
2010-10-15 20:20:56 +02:00
|
|
|
#include "ftedbgra.h"
|
2000-04-27 22:03:57 +02:00
|
|
|
#include "graphdb.h"
|
2005-05-29 03:05:33 +02:00
|
|
|
#include "../breakp2.h"
|
2005-05-30 22:28:29 +02:00
|
|
|
#include "../error.h"
|
|
|
|
|
#include "../display.h"
|
2000-04-27 22:03:57 +02:00
|
|
|
|
|
|
|
|
|
|
|
|
|
/* invariant: currentgraph contains the current graph */
|
|
|
|
|
GRAPH *currentgraph;
|
|
|
|
|
|
|
|
|
|
/*
|
|
|
|
|
* We use a linked list rather than a circular one because we
|
|
|
|
|
* expect few links per list and we don't need to add at the
|
|
|
|
|
* end of a list (we can add at the beginning).
|
|
|
|
|
*/
|
|
|
|
|
|
|
|
|
|
/* linked list of graphs */
|
|
|
|
|
typedef struct listgraph {
|
* src/main.c, src/multidec.c, src/proc2mod.c,
src/frontend/display.c, src/frontend/outitf.c,
src/frontend/help/readhelp.c, src/frontend/help/x11disp.c,
src/frontend/parser/complete.c, src/frontend/parser/glob.c,
src/frontend/plotting/graf.c,
src/frontend/plotting/graphdb.c,
src/frontend/plotting/x11.c, src/include/graph.h,
src/include/iferrmsg.h, src/include/ifsim.h,
src/include/macros.h, src/maths/poly/polyfit.c,
src/maths/sparse/spalloc.c, src/maths/sparse/spconfig.h,
src/misc/alloc.c, src/misc/mktemp.c,
src/spicelib/analysis/cktpzstr.c,
src/spicelib/devices/bsim2/b2temp.c,
src/spicelib/devices/bsim3/b3temp.c,
src/spicelib/devices/bsim3v1/b3v1temp.c,
src/spicelib/devices/bsim3v2/b3v2temp.c,
src/spicelib/devices/bsim4/b4temp.c: replaced malloc
realloc and free calls to use tmalloc trealloc and txfree.
* tests/diffpair.out, tests/fourbitadder.out,
tests/resistance/res_partition.out: Updated.
2000-10-14 15:16:53 +02:00
|
|
|
/* we use GRAPH here instead of a pointer to save a tmalloc */
|
2000-04-27 22:03:57 +02:00
|
|
|
GRAPH graph;
|
|
|
|
|
struct listgraph *next;
|
|
|
|
|
} LISTGRAPH;
|
2010-10-28 21:32:34 +02:00
|
|
|
#define NEWLISTGRAPH TMALLOC(LISTGRAPH, 1)
|
2000-04-27 22:03:57 +02:00
|
|
|
|
|
|
|
|
#define NUMGBUCKETS 16
|
|
|
|
|
|
|
|
|
|
typedef struct gbucket {
|
|
|
|
|
LISTGRAPH *list;
|
|
|
|
|
} GBUCKET;
|
|
|
|
|
|
|
|
|
|
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) (pgraph)->graphid = (id); \
|
|
|
|
|
(pgraph)->degree = 1; \
|
|
|
|
|
(pgraph)->linestyle = -1
|
|
|
|
|
|
|
|
|
|
/* returns NULL on error */
|
|
|
|
|
|
|
|
|
|
GRAPH *NewGraph(void)
|
|
|
|
|
{
|
|
|
|
|
|
|
|
|
|
GRAPH *pgraph;
|
|
|
|
|
LISTGRAPH *list;
|
|
|
|
|
int BucketId = RunningId % NUMGBUCKETS;
|
|
|
|
|
|
2010-11-19 19:54:40 +01:00
|
|
|
if ((list = NEWLISTGRAPH) == NULL) {
|
2000-04-27 22:03:57 +02:00
|
|
|
internalerror("can't allocate a listgraph");
|
2011-04-28 17:59:36 +02:00
|
|
|
return(NULL);
|
2000-04-27 22:03:57 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
pgraph = &list->graph;
|
|
|
|
|
SETGRAPH(pgraph, RunningId);
|
|
|
|
|
|
|
|
|
|
if (!GBucket[BucketId].list) {
|
|
|
|
|
GBucket[BucketId].list = list;
|
|
|
|
|
} else {
|
|
|
|
|
/* insert at front of current list */
|
|
|
|
|
list->next = GBucket[BucketId].list;
|
|
|
|
|
GBucket[BucketId].list = list;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
RunningId++ ;
|
|
|
|
|
|
|
|
|
|
return(pgraph);
|
|
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/* Given graph id, return graph */
|
|
|
|
|
GRAPH *FindGraph(int id)
|
|
|
|
|
{
|
|
|
|
|
|
|
|
|
|
LISTGRAPH *list;
|
|
|
|
|
|
|
|
|
|
for (list = GBucket[id % NUMGBUCKETS].list;
|
|
|
|
|
list && list->graph.graphid != id;
|
|
|
|
|
list = list->next)
|
|
|
|
|
|
|
|
|
|
;
|
|
|
|
|
|
|
|
|
|
if (list)
|
|
|
|
|
return(&list->graph);
|
|
|
|
|
else
|
|
|
|
|
return(NULL);
|
|
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
GRAPH *CopyGraph(GRAPH *graph)
|
|
|
|
|
{
|
|
|
|
|
|
|
|
|
|
GRAPH *ret;
|
|
|
|
|
struct _keyed *k;
|
|
|
|
|
struct dveclist *link, *newlink;
|
|
|
|
|
|
|
|
|
|
ret = NewGraph();
|
2010-06-27 19:22:11 +02:00
|
|
|
bcopy(graph, ret, sizeof(GRAPH)); /* va: compatible pointer types */
|
2000-04-27 22:03:57 +02:00
|
|
|
|
|
|
|
|
ret->graphid = RunningId - 1; /* 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) {
|
2010-10-28 21:32:34 +02:00
|
|
|
newlink = TMALLOC(struct dveclist, 1);
|
2000-04-27 22:03:57 +02:00
|
|
|
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;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
ret->commandline = copy(graph->commandline);
|
|
|
|
|
ret->plotname = copy(graph->plotname);
|
|
|
|
|
|
|
|
|
|
return(ret);
|
|
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
int
|
|
|
|
|
DestroyGraph(int id)
|
|
|
|
|
{
|
|
|
|
|
|
|
|
|
|
LISTGRAPH *list, *lastlist;
|
|
|
|
|
struct _keyed *k, *nextk;
|
|
|
|
|
struct dveclist *d, *nextd;
|
|
|
|
|
struct dbcomm *db;
|
|
|
|
|
|
|
|
|
|
list = GBucket[id % NUMGBUCKETS].list;
|
|
|
|
|
lastlist = NULL;
|
|
|
|
|
while (list) {
|
|
|
|
|
if (list->graph.graphid == id) { /* found it */
|
|
|
|
|
|
|
|
|
|
/* Fix the iplot/trace dbs list */
|
|
|
|
|
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;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/* run through and de-allocate dynamically allocated keyed list */
|
|
|
|
|
k=list->graph.keyed;
|
|
|
|
|
while (k) {
|
|
|
|
|
nextk = k->next;
|
* src/main.c, src/multidec.c, src/proc2mod.c,
src/frontend/display.c, src/frontend/outitf.c,
src/frontend/help/readhelp.c, src/frontend/help/x11disp.c,
src/frontend/parser/complete.c, src/frontend/parser/glob.c,
src/frontend/plotting/graf.c,
src/frontend/plotting/graphdb.c,
src/frontend/plotting/x11.c, src/include/graph.h,
src/include/iferrmsg.h, src/include/ifsim.h,
src/include/macros.h, src/maths/poly/polyfit.c,
src/maths/sparse/spalloc.c, src/maths/sparse/spconfig.h,
src/misc/alloc.c, src/misc/mktemp.c,
src/spicelib/analysis/cktpzstr.c,
src/spicelib/devices/bsim2/b2temp.c,
src/spicelib/devices/bsim3/b3temp.c,
src/spicelib/devices/bsim3v1/b3v1temp.c,
src/spicelib/devices/bsim3v2/b3v2temp.c,
src/spicelib/devices/bsim4/b4temp.c: replaced malloc
realloc and free calls to use tmalloc trealloc and txfree.
* tests/diffpair.out, tests/fourbitadder.out,
tests/resistance/res_partition.out: Updated.
2000-10-14 15:16:53 +02:00
|
|
|
tfree(k->text);
|
|
|
|
|
tfree(k);
|
2000-04-27 22:03:57 +02:00
|
|
|
k = nextk;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/* de-allocate dveclist */
|
|
|
|
|
d = list->graph.plotdata;
|
|
|
|
|
while (d) {
|
|
|
|
|
nextd = d->next;
|
|
|
|
|
tfree(d->vector->v_name);
|
|
|
|
|
if (isreal(d->vector)) {
|
|
|
|
|
tfree(d->vector->v_realdata);
|
|
|
|
|
} else {
|
|
|
|
|
tfree(d->vector->v_compdata);
|
|
|
|
|
}
|
* src/main.c, src/multidec.c, src/proc2mod.c,
src/frontend/display.c, src/frontend/outitf.c,
src/frontend/help/readhelp.c, src/frontend/help/x11disp.c,
src/frontend/parser/complete.c, src/frontend/parser/glob.c,
src/frontend/plotting/graf.c,
src/frontend/plotting/graphdb.c,
src/frontend/plotting/x11.c, src/include/graph.h,
src/include/iferrmsg.h, src/include/ifsim.h,
src/include/macros.h, src/maths/poly/polyfit.c,
src/maths/sparse/spalloc.c, src/maths/sparse/spconfig.h,
src/misc/alloc.c, src/misc/mktemp.c,
src/spicelib/analysis/cktpzstr.c,
src/spicelib/devices/bsim2/b2temp.c,
src/spicelib/devices/bsim3/b3temp.c,
src/spicelib/devices/bsim3v1/b3v1temp.c,
src/spicelib/devices/bsim3v2/b3v2temp.c,
src/spicelib/devices/bsim4/b4temp.c: replaced malloc
realloc and free calls to use tmalloc trealloc and txfree.
* tests/diffpair.out, tests/fourbitadder.out,
tests/resistance/res_partition.out: Updated.
2000-10-14 15:16:53 +02:00
|
|
|
tfree(d->vector);
|
|
|
|
|
tfree(d);
|
2000-04-27 22:03:57 +02:00
|
|
|
d = nextd;
|
|
|
|
|
}
|
|
|
|
|
|
* src/main.c, src/multidec.c, src/proc2mod.c,
src/frontend/display.c, src/frontend/outitf.c,
src/frontend/help/readhelp.c, src/frontend/help/x11disp.c,
src/frontend/parser/complete.c, src/frontend/parser/glob.c,
src/frontend/plotting/graf.c,
src/frontend/plotting/graphdb.c,
src/frontend/plotting/x11.c, src/include/graph.h,
src/include/iferrmsg.h, src/include/ifsim.h,
src/include/macros.h, src/maths/poly/polyfit.c,
src/maths/sparse/spalloc.c, src/maths/sparse/spconfig.h,
src/misc/alloc.c, src/misc/mktemp.c,
src/spicelib/analysis/cktpzstr.c,
src/spicelib/devices/bsim2/b2temp.c,
src/spicelib/devices/bsim3/b3temp.c,
src/spicelib/devices/bsim3v1/b3v1temp.c,
src/spicelib/devices/bsim3v2/b3v2temp.c,
src/spicelib/devices/bsim4/b4temp.c: replaced malloc
realloc and free calls to use tmalloc trealloc and txfree.
* tests/diffpair.out, tests/fourbitadder.out,
tests/resistance/res_partition.out: Updated.
2000-10-14 15:16:53 +02:00
|
|
|
tfree(list->graph.commandline);
|
|
|
|
|
tfree(list->graph.plotname);
|
2000-04-27 22:03:57 +02:00
|
|
|
|
|
|
|
|
/* If device dependent space allocated, free it. */
|
|
|
|
|
if (list->graph.devdep)
|
* src/main.c, src/multidec.c, src/proc2mod.c,
src/frontend/display.c, src/frontend/outitf.c,
src/frontend/help/readhelp.c, src/frontend/help/x11disp.c,
src/frontend/parser/complete.c, src/frontend/parser/glob.c,
src/frontend/plotting/graf.c,
src/frontend/plotting/graphdb.c,
src/frontend/plotting/x11.c, src/include/graph.h,
src/include/iferrmsg.h, src/include/ifsim.h,
src/include/macros.h, src/maths/poly/polyfit.c,
src/maths/sparse/spalloc.c, src/maths/sparse/spconfig.h,
src/misc/alloc.c, src/misc/mktemp.c,
src/spicelib/analysis/cktpzstr.c,
src/spicelib/devices/bsim2/b2temp.c,
src/spicelib/devices/bsim3/b3temp.c,
src/spicelib/devices/bsim3v1/b3v1temp.c,
src/spicelib/devices/bsim3v2/b3v2temp.c,
src/spicelib/devices/bsim4/b4temp.c: replaced malloc
realloc and free calls to use tmalloc trealloc and txfree.
* tests/diffpair.out, tests/fourbitadder.out,
tests/resistance/res_partition.out: Updated.
2000-10-14 15:16:53 +02:00
|
|
|
tfree(list->graph.devdep);
|
|
|
|
|
tfree(list);
|
2000-04-27 22:03:57 +02:00
|
|
|
|
|
|
|
|
return(1);
|
|
|
|
|
}
|
|
|
|
|
lastlist = list;
|
|
|
|
|
list = list->next;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
internalerror("tried to destroy non-existent graph");
|
|
|
|
|
return (0);
|
|
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/* free up all dynamically allocated data structures */
|
|
|
|
|
void
|
|
|
|
|
FreeGraphs(void)
|
|
|
|
|
{
|
|
|
|
|
|
|
|
|
|
GBUCKET *gbucket;
|
|
|
|
|
LISTGRAPH *list, *deadl;
|
|
|
|
|
|
|
|
|
|
for (gbucket = GBucket; gbucket < &GBucket[NUMGBUCKETS]; gbucket++) {
|
|
|
|
|
list = gbucket->list;
|
|
|
|
|
while (list) {
|
|
|
|
|
deadl = list;
|
|
|
|
|
list = list->next;
|
* src/main.c, src/multidec.c, src/proc2mod.c,
src/frontend/display.c, src/frontend/outitf.c,
src/frontend/help/readhelp.c, src/frontend/help/x11disp.c,
src/frontend/parser/complete.c, src/frontend/parser/glob.c,
src/frontend/plotting/graf.c,
src/frontend/plotting/graphdb.c,
src/frontend/plotting/x11.c, src/include/graph.h,
src/include/iferrmsg.h, src/include/ifsim.h,
src/include/macros.h, src/maths/poly/polyfit.c,
src/maths/sparse/spalloc.c, src/maths/sparse/spconfig.h,
src/misc/alloc.c, src/misc/mktemp.c,
src/spicelib/analysis/cktpzstr.c,
src/spicelib/devices/bsim2/b2temp.c,
src/spicelib/devices/bsim3/b3temp.c,
src/spicelib/devices/bsim3v1/b3v1temp.c,
src/spicelib/devices/bsim3v2/b3v2temp.c,
src/spicelib/devices/bsim4/b4temp.c: replaced malloc
realloc and free calls to use tmalloc trealloc and txfree.
* tests/diffpair.out, tests/fourbitadder.out,
tests/resistance/res_partition.out: Updated.
2000-10-14 15:16:53 +02:00
|
|
|
tfree(deadl);
|
2000-04-27 22:03:57 +02:00
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void
|
|
|
|
|
SetGraphContext(int graphid)
|
|
|
|
|
{
|
|
|
|
|
|
|
|
|
|
currentgraph = FindGraph(graphid);
|
|
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
typedef struct gcstack {
|
|
|
|
|
GRAPH *pgraph;
|
|
|
|
|
struct gcstack *next;
|
|
|
|
|
} GCSTACK;
|
|
|
|
|
GCSTACK *gcstacktop;
|
2010-10-28 21:32:34 +02:00
|
|
|
#define NEWGCSTACK TMALLOC(GCSTACK, 1)
|
2000-04-27 22:03:57 +02:00
|
|
|
|
|
|
|
|
/* 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.
|
|
|
|
|
*/
|
|
|
|
|
void
|
|
|
|
|
PushGraphContext(GRAPH *graph)
|
|
|
|
|
{
|
|
|
|
|
|
|
|
|
|
GCSTACK *gcstack = NEWGCSTACK;
|
|
|
|
|
|
|
|
|
|
if (!gcstacktop) {
|
|
|
|
|
gcstacktop = gcstack;
|
|
|
|
|
} else {
|
|
|
|
|
gcstack->next = gcstacktop;
|
|
|
|
|
gcstacktop = gcstack;
|
|
|
|
|
}
|
|
|
|
|
gcstacktop->pgraph = currentgraph;
|
|
|
|
|
currentgraph = graph;
|
|
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void
|
|
|
|
|
PopGraphContext(void)
|
|
|
|
|
{
|
|
|
|
|
|
|
|
|
|
GCSTACK *dead;
|
|
|
|
|
|
|
|
|
|
currentgraph = gcstacktop->pgraph;
|
|
|
|
|
dead = gcstacktop;
|
|
|
|
|
gcstacktop = gcstacktop->next;
|
* src/main.c, src/multidec.c, src/proc2mod.c,
src/frontend/display.c, src/frontend/outitf.c,
src/frontend/help/readhelp.c, src/frontend/help/x11disp.c,
src/frontend/parser/complete.c, src/frontend/parser/glob.c,
src/frontend/plotting/graf.c,
src/frontend/plotting/graphdb.c,
src/frontend/plotting/x11.c, src/include/graph.h,
src/include/iferrmsg.h, src/include/ifsim.h,
src/include/macros.h, src/maths/poly/polyfit.c,
src/maths/sparse/spalloc.c, src/maths/sparse/spconfig.h,
src/misc/alloc.c, src/misc/mktemp.c,
src/spicelib/analysis/cktpzstr.c,
src/spicelib/devices/bsim2/b2temp.c,
src/spicelib/devices/bsim3/b3temp.c,
src/spicelib/devices/bsim3v1/b3v1temp.c,
src/spicelib/devices/bsim3v2/b3v2temp.c,
src/spicelib/devices/bsim4/b4temp.c: replaced malloc
realloc and free calls to use tmalloc trealloc and txfree.
* tests/diffpair.out, tests/fourbitadder.out,
tests/resistance/res_partition.out: Updated.
2000-10-14 15:16:53 +02:00
|
|
|
tfree(dead);
|
2000-04-27 22:03:57 +02:00
|
|
|
}
|