Graphviz  2.41.20170921.2350
rec.c
Go to the documentation of this file.
1 /* $Id$ $Revision$ */
2 /* vim:set shiftwidth=4 ts=8: */
3 
4 /*************************************************************************
5  * Copyright (c) 2011 AT&T Intellectual Property
6  * All rights reserved. This program and the accompanying materials
7  * are made available under the terms of the Eclipse Public License v1.0
8  * which accompanies this distribution, and is available at
9  * http://www.eclipse.org/legal/epl-v10.html
10  *
11  * Contributors: See CVS logs. Details at http://www.graphviz.org/
12  *************************************************************************/
13 
14 #include <cghdr.h>
15 
16 /*
17  * run time records
18  */
19 
20 static void set_data(Agobj_t * obj, Agrec_t * data, int mtflock)
21 {
22  Agedge_t *e;
23 
24  obj->data = data;
25  obj->tag.mtflock = mtflock;
26  if ((AGTYPE(obj) == AGINEDGE) || (AGTYPE(obj) == AGOUTEDGE)) {
27  e = agopp((Agedge_t *) obj);
28  AGDATA(e) = data;
29  e->base.tag.mtflock = mtflock;
30  }
31 }
32 
33 /* find record in circular list and do optional move-to-front */
34 Agrec_t *aggetrec(void *obj, char *name, int mtf)
35 {
36  Agobj_t *hdr;
37  Agrec_t *d, *first;
38 
39  hdr = (Agobj_t *) obj;
40  first = d = hdr->data;
41  while (d) {
42  if ((d->name == name) || streq(name, d->name))
43  break;
44  d = d->next;
45  if (d == first) {
46  d = NIL(Agrec_t *);
47  break;
48  }
49  }
50  if (d) {
51  if (hdr->tag.mtflock) {
52  if (mtf && (hdr->data != d))
53  agerr(AGERR, "move to front lock inconsistency");
54  } else {
55  if ((d != first) || (mtf != hdr->tag.mtflock))
56  set_data(hdr, d, mtf); /* Always optimize */
57  }
58  }
59  return d;
60 }
61 
62 /* insert the record in data list of this object (only) */
63 static void objputrec(Agraph_t * g, Agobj_t * obj, void *arg)
64 {
65  Agrec_t *firstrec, *newrec;
66 
67  newrec = arg;
68  firstrec = obj->data;
69  if (firstrec == NIL(Agrec_t *))
70  newrec->next = newrec; /* 0 elts */
71  else {
72  if (firstrec->next == firstrec) {
73  firstrec->next = newrec; /* 1 elt */
74  newrec->next = firstrec;
75  } else {
76  newrec->next = firstrec->next;
77  firstrec->next = newrec;
78  }
79  }
80  if (NOT(obj->tag.mtflock))
81  set_data(obj, newrec, FALSE);
82 }
83 
84 /* attach a new record of the given size to the object.
85  */
86 void *agbindrec(void *arg_obj, char *recname, unsigned int recsize,
87  int mtf)
88 {
89  Agraph_t *g;
90  Agobj_t *obj;
91  Agrec_t *rec;
92 
93  obj = (Agobj_t *) arg_obj;
94  g = agraphof(obj);
95  rec = aggetrec(obj, recname, FALSE);
96  if ((rec == NIL(Agrec_t *)) && (recsize > 0)) {
97  rec = (Agrec_t *) agalloc(g, recsize);
98  rec->name = agstrdup(g, recname);
99  switch (obj->tag.objtype) {
100  case AGRAPH:
101  objputrec(g, obj, rec);
102  break;
103  case AGNODE:
104  objputrec(g, obj, rec);
105  break;
106  case AGINEDGE:
107  case AGOUTEDGE:
108  objputrec(g, obj, rec);
109  break;
110  }
111  }
112  if (mtf)
113  aggetrec(arg_obj, recname, TRUE);
114  return (void *) rec;
115 }
116 
117 
118 /* if obj points to rec, move its data pointer. break any mtf lock(?) */
119 static void objdelrec(Agraph_t * g, Agobj_t * obj, void *arg_rec)
120 {
121  Agrec_t *rec = (Agrec_t *) arg_rec, *newrec;
122  if (obj->data == rec) {
123  if (rec->next == rec)
124  newrec = NIL(Agrec_t *);
125  else
126  newrec = rec->next;
127  set_data(obj, newrec, FALSE);
128  }
129 }
130 
131 /* delete a record from a circular data list */
132 static void listdelrec(Agobj_t * obj, Agrec_t * rec)
133 {
134  Agrec_t *prev;
135 
136  prev = obj->data;
137  while (prev->next != rec) {
138  prev = prev->next;
139  assert(prev != obj->data);
140  }
141  /* following is a harmless no-op if the list is trivial */
142  prev->next = rec->next;
143 }
144 
145 int agdelrec(void *arg_obj, char *name)
146 {
147  Agobj_t *obj;
148  Agrec_t *rec;
149  Agraph_t *g;
150 
151  obj = (Agobj_t *) arg_obj;
152  g = agraphof(obj);
153  rec = aggetrec(obj, name, FALSE);
154  if (rec) {
155  listdelrec(obj, rec); /* zap it from the circular list */
156  switch (obj->tag.objtype) { /* refresh any stale pointers */
157  case AGRAPH:
158  objdelrec(g, obj, rec);
159  break;
160  case AGNODE:
161  case AGINEDGE:
162  case AGOUTEDGE:
163  agapply(agroot(g), obj, objdelrec, rec, FALSE);
164  break;
165  }
166  agstrfree(g, rec->name);
167  agfree(g, rec);
168  return SUCCESS;
169  } else
170  return FAILURE;
171 }
172 
173 static void simple_delrec(Agraph_t * g, Agobj_t * obj, void *rec_name)
174 {
175  agdelrec(obj, rec_name);
176 }
177 
178 #ifdef OLD
179 void agclean(Agraph_t * g, char *graphdata, char *nodedata, char *edgedata)
180 {
181  Agnode_t *n;
182  Agedge_t *e;
183 
184  if (nodedata || edgedata) {
185  for (n = agfstnode(g); n; n = agnxtnode(g, n)) {
186  if (edgedata)
187  for (e = agfstout(n); e; e = agnxtout(g, e)) {
188  agdelrec(e, edgedata);
189  }
190  if (nodedata)
191  agdelrec(n, nodedata);
192  }
193  }
194  agdelrec(g, graphdata);
195 }
196 #endif
197 
198 void aginit(Agraph_t * g, int kind, char *rec_name, int arg_rec_size, int mtf)
199 {
200  Agnode_t *n;
201  Agedge_t *e;
202  Agraph_t *s;
203  unsigned int rec_size;
204  int recur; /* if recursive on subgraphs */
205 
206  if (arg_rec_size < 0)
207  {
208  recur = 1;
209  }
210  else
211  {
212  recur = 0;
213  }
214  rec_size = (unsigned int) abs(arg_rec_size);
215  switch (kind) {
216  case AGRAPH:
217  agbindrec(g, rec_name, rec_size, mtf);
218  if (recur)
219  for (s = agfstsubg(g); s; s = agnxtsubg(s))
220  aginit(s,kind,rec_name,arg_rec_size,mtf);
221  break;
222  case AGNODE:
223  case AGOUTEDGE:
224  case AGINEDGE:
225  for (n = agfstnode(g); n; n = agnxtnode(g, n))
226  if (kind == AGNODE)
227  agbindrec(n, rec_name, rec_size, mtf);
228  else {
229  for (e = agfstout(g, n); e; e = agnxtout(g, e))
230  agbindrec(e, rec_name, rec_size, mtf);
231  }
232  break;
233  default:
234  break;
235  }
236 }
237 
238 void agclean(Agraph_t * g, int kind, char *rec_name)
239 {
240  Agnode_t *n;
241  Agedge_t *e;
242 
243  switch (kind) {
244  case AGRAPH:
245  agapply(g, (Agobj_t *) g, simple_delrec, rec_name, TRUE);
246  break;
247  case AGNODE:
248  case AGOUTEDGE:
249  case AGINEDGE:
250  for (n = agfstnode(g); n; n = agnxtnode(g, n))
251  if (kind == AGNODE)
252  agdelrec(n, rec_name);
253  else {
254  for (e = agfstout(g, n); e; e = agnxtout(g, e))
255  agdelrec(e, rec_name);
256  }
257  break;
258  default:
259  break;
260  }
261 }
262 
263 void agrecclose(Agobj_t * obj)
264 {
265  Agraph_t *g;
266  Agrec_t *rec, *nrec;
267 
268  g = agraphof(obj);
269  if ((rec = obj->data)) {
270  do {
271  nrec = rec->next;
272  agstrfree(g, rec->name);
273  agfree(g, rec);
274  rec = nrec;
275  } while (rec != obj->data);
276  }
277  obj->data = NIL(Agrec_t *);
278 }
CGRAPH_API Agedge_t * agopp(Agedge_t *e)
Definition: edge.c:541
CGRAPH_API void agclean(Agraph_t *g, int kind, char *rec_name)
Definition: rec.c:238
Definition: cgraph.h:388
#define SUCCESS
Definition: cghdr.h:62
void agrecclose(Agobj_t *obj)
Definition: rec.c:263
unsigned mtflock
Definition: cgraph.h:93
#define assert(x)
Definition: cghdr.h:47
Agtag_t tag
Definition: cgraph.h:108
int agerr(agerrlevel_t level, const char *fmt,...)
Definition: agerror.c:141
CGRAPH_API Agraph_t * agfstsubg(Agraph_t *g)
Definition: subg.c:72
CGRAPH_API Agraph_t * agroot(void *obj)
Definition: obj.c:169
CGRAPH_API Agedge_t * agfstout(Agraph_t *g, Agnode_t *n)
Definition: edge.c:25
#define AGOUTEDGE
Definition: cgraph.h:102
#define AGDATA(obj)
Definition: cgraph.h:117
char * name
Definition: cgraph.h:84
CGRAPH_API void agfree(Agraph_t *g, void *ptr)
Definition: mem.c:89
#define AGTYPE(obj)
Definition: cgraph.h:113
CGRAPH_API Agraph_t * agraphof(void *obj)
Definition: obj.c:185
CGRAPH_API Agraph_t * agnxtsubg(Agraph_t *subg)
Definition: subg.c:77
CGRAPH_API Agnode_t * agnxtnode(Agraph_t *g, Agnode_t *n)
Definition: node.c:45
#define NIL(t)
Definition: dthdr.h:13
int
Definition: grammar.c:1264
unsigned objtype
Definition: cgraph.h:92
#define FAILURE
Definition: cghdr.h:63
CGRAPH_API int agstrfree(Agraph_t *, char *)
Definition: refstr.c:149
CGRAPH_API char * agstrdup(Agraph_t *, char *)
Definition: refstr.c:97
CGRAPH_API Agnode_t * agfstnode(Agraph_t *g)
Definition: node.c:38
CGRAPH_API void aginit(Agraph_t *g, int kind, char *rec_name, int rec_size, int move_to_front)
Definition: rec.c:198
CGRAPH_API Agrec_t * aggetrec(void *obj, char *name, int move_to_front)
Definition: rec.c:34
Definition: grammar.c:79
Definition: cgraph.h:83
#define AGNODE
Definition: cgraph.h:101
Agobj_t base
Definition: cgraph.h:140
CGRAPH_API int agdelrec(void *obj, char *name)
Definition: rec.c:145
#define NOT(x)
Definition: cgraph.h:41
#define streq(s, t)
Definition: cghdr.h:52
CGRAPH_API void * agalloc(Agraph_t *g, size_t size)
Definition: mem.c:62
Agrec_t * data
Definition: cgraph.h:109
CGRAPH_API void * agbindrec(void *obj, char *name, unsigned int size, int move_to_front)
Definition: rec.c:86
#define AGINEDGE
Definition: cgraph.h:103
CGRAPH_API Agedge_t * agnxtout(Agraph_t *g, Agedge_t *e)
Definition: edge.c:40
int agapply(Agraph_t *g, Agobj_t *obj, agobjfn_t fn, void *arg, int preorder)
Definition: apply.c:61
#define FALSE
Definition: cgraph.h:35
Definition: legal.c:60
Agrec_t * next
Definition: cgraph.h:85
#define AGRAPH
Definition: cgraph.h:100
#define TRUE
Definition: cgraph.h:38