Jspice3
graphdb.c
Go to the documentation of this file.
1 /***************************************************************************
2 JSPICE3 adaptation of Spice3e2 - Copyright (c) Stephen R. Whiteley 1992
3 Copyright 1990 Regents of the University of California. All rights reserved.
4 Authors: 1987 UCB
5  1992 Stephen R. Whiteley
6 ****************************************************************************/
7 
8 /*
9  * Manage graph data structure.
10  */
11 
12 #include "spice.h"
13 #include "ftegraph.h"
14 #include "ftedebug.h"
15 
16 #ifndef NULL
17 #define NULL ((char*)0)
18 #endif
19 
20 /* invariant: currentgraph contains the current graph */
22 
23 /* count the number of context switches */
25 
26 /*
27  * We use a linked list rather than a circular one because we
28  * expect few links per list and we don't need to add at the
29  * end of a list (we can add at the beginning).
30  */
31 
32 /* linked list of graphs */
33 typedef struct listgraph {
34  /* we use GRAPH here instead of a pointer to save a calloc */
36  struct listgraph *next;
37 } LISTGRAPH;
38 #define NEWLISTGRAPH (LISTGRAPH *) calloc(1, sizeof(LISTGRAPH))
39 
40 #define NUMGBUCKETS 16
41 
42 typedef struct gbucket {
44 } GBUCKET;
45 /* #define NEWGBUCKET (GBUCKET *) calloc(1, sizeof(GBUCKET)) */
46 
48 
49 /* note: Zero is not a valid id. This is used in plot() in graf.c. */
50 static RunningId = 1;
51 
52 /* initialize graph structure */
53 #define SETGRAPH(pgraph, id) (pgraph)->graphid = (id); \
54  (pgraph)->degree = 1; \
55  (pgraph)->linestyle = -1
56 
57 
58 GRAPH *
60 
61 /* returns NULL on error */
62 {
63 
64  GRAPH *pgraph;
65  LISTGRAPH *list;
66  int BucketId = RunningId % NUMGBUCKETS;
67 
68  if (!(list = NEWLISTGRAPH)) {
69  internalerror("can't allocate a listgraph");
70  return ((GRAPH *) NULL);
71  }
72 
73  pgraph = &list->graph;
74  SETGRAPH(pgraph, RunningId);
75 
76  if (!GBucket[BucketId].list) {
77  GBucket[BucketId].list = list;
78  }
79  else {
80  /* insert at front of current list */
81  list->next = GBucket[BucketId].list;
82  GBucket[BucketId].list = list;
83  }
84 
85  RunningId++ ;
86 
87  return (pgraph);
88 
89 }
90 
91 
92 GRAPH *
94 
95 /* Given graph id, return graph */
96 int id;
97 {
98  LISTGRAPH *list;
99 
100  for (list = GBucket[id % NUMGBUCKETS].list;
101  list && list->graph.graphid != id;
102  list = list->next)
103  ;
104 
105  if (list)
106  return (&list->graph);
107  else
108  return (NULL);
109 }
110 
111 
112 GRAPH *
114 
115 GRAPH *graph;
116 {
117  GRAPH *ret;
118  struct _keyed *k;
119 
120  ret = NewGraph();
121  bcopy(graph, ret, sizeof(struct graph));
122 
123  ret->graphid = RunningId - 1; /* restore id */
124 
125  /* copy keyed */
126  for (ret->keyed = NULL, k = graph->keyed; k; k = k->next) {
127  SaveText(ret, k->text, k->x, k->y);
128  }
129  ret->plotdata = (GRDATA)NULL;
130  if (graph->copydata)
131  ret->plotdata = (*graph->copydata)((GRDATA)graph->plotdata);
132 
133  ret->commandline = copy(graph->commandline);
134  ret->plotname = copy(graph->plotname);
135 
136  return (ret);
137 }
138 
139 
140 int
142 
143 int id;
144 {
145 
146  LISTGRAPH *list, *lastlist;
147  struct _keyed *k, *nextk;
148  extern struct dbcomm *dbiplot;
149  struct dbcomm *db;
150 
151  list = GBucket[id % NUMGBUCKETS].list;
152  lastlist = NULL;
153 
154  while (list) {
155  if (list->graph.graphid == id) { /* found it */
156 
157  /* Fix the iplot/trace dbiplot list */
158  for (db = dbiplot;
159  db && db->db_graphid != id; db = db->db_next) ;
160 
161  if (db && db->db_type == DB_IPLOT) {
162  db->db_type = DB_DEADIPLOT;
163  /* Delete this later */
164  return (0);
165  }
166 
167  /* adjust bucket pointers */
168  if (lastlist) {
169  lastlist->next = list->next;
170  }
171  else {
172  GBucket[id % NUMGBUCKETS].list = list->next;
173  }
174 
175  /* run through and de-allocate dynamically allocated keyed list */
176  k = list->graph.keyed;
177  while (k) {
178  nextk = k->next;
179  txfree(k->text);
180  txfree((char*)k);
181  k = nextk;
182  }
183 
184  if (list->graph.destroy)
185  (*list->graph.destroy)((GRDATA)list->graph.plotdata);
186  list->graph.plotdata = (GRDATA)NULL;
187 
188  tfree(list->graph.commandline);
189  tfree(list->graph.plotname);
190 
191  /* If device dependent space allocated, free it. */
192  if (list->graph.devdep)
193  txfree(list->graph.devdep);
194  txfree((char*)list);
195 
196  return (1);
197  }
198  lastlist = list;
199  list = list->next;
200  }
201 
202  internalerror("tried to destroy non-existent graph");
203  return (0);
204 }
205 
206 
207 void
209 
210 /* free up all dynamically allocated data structures */
211 {
212  GBUCKET *gbucket;
213  LISTGRAPH *list, *deadl;
214 
215  for (gbucket = GBucket; gbucket < &GBucket[NUMGBUCKETS]; gbucket++) {
216  list = gbucket->list;
217  while (list) {
218  deadl = list;
219  list = list->next;
220  txfree((char*)deadl);
221  }
222  }
223 }
224 
225 
226 void
228 
229 int graphid;
230 {
231  currentgraph = FindGraph(graphid);
232 }
233 
234 
235 typedef struct gcstack {
237  struct gcstack *next;
238 } GCSTACK;
240 #define NEWGCSTACK (GCSTACK *) calloc(1, sizeof(GCSTACK))
241 
242 
243 /* note: This Push and Pop has tricky semantics.
244  * Push(graph) will push the currentgraph onto the stack
245  * and set currentgraph to graph.
246  * Pop() simply sets currentgraph to the top of the stack and pops stack.
247  */
248 
249 void
251 
252 GRAPH *graph;
253 {
255 
256  if (!gcstacktop) {
257  gcstacktop = gcstack;
258  }
259  else {
260  gcstack->next = gcstacktop;
261  gcstacktop = gcstack;
262  }
263  gcstacktop->pgraph = currentgraph;
264  currentgraph = graph;
265  numgraphcxsw++;
266 }
267 
268 
269 void
271 
272 {
273  GCSTACK *dead;
274 
275  currentgraph = gcstacktop->pgraph;
276  dead = gcstacktop;
277  gcstacktop = gcstacktop->next;
278  txfree((char*)dead);
279  numgraphcxsw++;
280 }
struct dbcomm * dbiplot
Definition: main.c:186
GRAPH * currentgraph
Definition: graphdb.c:21
int numgraphcxsw
Definition: graphdb.c:24
GRAPH * CopyGraph(GRAPH *graph)
Definition: graphdb.c:113
static GBUCKET GBucket[NUMGBUCKETS]
Definition: graphdb.c:47
char * GRDATA
Definition: ftegraph.h:26
GRAPH graph
Definition: graphdb.c:35
int db_graphid
Definition: ftedebug.h:26
#define SETGRAPH(pgraph, id)
Definition: graphdb.c:53
void PushGraphContext(GRAPH *graph)
Definition: graphdb.c:250
internalerror(char *message)
Definition: error.c:91
#define NUMGBUCKETS
Definition: graphdb.c:40
#define NEWGCSTACK
Definition: graphdb.c:240
struct _keyed * next
Definition: ftegraph.h:129
struct listgraph * next
Definition: graphdb.c:36
char * copy()
struct gcstack * next
Definition: graphdb.c:237
void SaveText()
int DestroyGraph(int id)
Definition: graphdb.c:141
char db_type
Definition: ftedebug.h:22
#define tfree(x)
Definition: cdmacs.h:22
GCSTACK * gcstacktop
Definition: graphdb.c:239
struct gcstack GCSTACK
void FreeGraphs()
Definition: graphdb.c:208
void txfree()
int graphid
Definition: ftegraph.h:30
GRDATA plotdata
Definition: ftegraph.h:33
#define NEWLISTGRAPH
Definition: graphdb.c:38
struct dbcomm * db_next
Definition: ftedebug.h:28
Definition: ftegraph.h:29
GRAPH * FindGraph(int id)
Definition: graphdb.c:93
struct listgraph LISTGRAPH
struct graph::_keyed * keyed
char * plotname
Definition: ftegraph.h:35
void(* destroy)()
Definition: ftegraph.h:71
char * devdep
Definition: ftegraph.h:144
#define DB_DEADIPLOT
Definition: ftedebug.h:18
Definition: dir.c:53
char * commandline
Definition: ftegraph.h:133
GRAPH * pgraph
Definition: graphdb.c:236
void bcopy(char *from, char *to, int num)
Definition: string.c:339
GRAPH * NewGraph()
Definition: graphdb.c:59
#define NULL
Definition: graphdb.c:17
#define DB_IPLOT
Definition: ftedebug.h:16
LISTGRAPH * list
Definition: graphdb.c:43
static int graphid
Definition: check.c:23
struct gbucket GBUCKET
void SetGraphContext(int graphid)
Definition: graphdb.c:227
void PopGraphContext()
Definition: graphdb.c:270
static RunningId
Definition: graphdb.c:50