00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017 #include <limits.h>
00018
00019 #include "libgraph.h"
00020
00021 #ifdef DMALLOC
00022 #include "dmalloc.h"
00023 #endif
00024
00025 static void graphs_of_e(Agedge_t * e, Dict_t * g_e, Agraph_t * g)
00026 {
00027 Agedge_t *sub;
00028
00029 if (dtsearch(g->inedges, e) == NULL)
00030 return;
00031 if (dtsearch(g_e, g->meta_node))
00032 return;
00033 dtinsert(g_e, g->meta_node);
00034 for (sub = agfstin(g->meta_node->graph, g->meta_node); sub;
00035 sub = agnxtin(g->meta_node->graph, sub))
00036 graphs_of_e(e, g_e, agusergraph(sub->head));
00037 }
00038
00039 static Agedge_t *esearch(Agraph_t * g, Agnode_t * tail, Agnode_t * head,
00040 char *usrkey)
00041 {
00042 Agedge_t key, *e;
00043 char *attr[KEYX + 1];
00044
00045 attr[KEYX] = usrkey;
00046 key.tail = tail;
00047 key.head = head;
00048 key.attr = (usrkey ? attr : 0);
00049 if (usrkey)
00050 e = (Agedge_t *) dtsearch(g->inedges, &key);
00051 else {
00052 e = (Agedge_t *) dtnext(g->inedges, &key);
00053 if (e && ((e->tail != tail) || (e->head != head)))
00054 e = NULL;
00055 }
00056 return e;
00057 }
00058
00059 Agedge_t *agfindedge(Agraph_t * g, Agnode_t * tail, Agnode_t * head)
00060 {
00061 Agedge_t *e;
00062
00063 e = esearch(g, tail, head, NULL);
00064 if ((e == NULL) && !(AG_IS_DIRECTED(g)))
00065 e = esearch(g, head, tail, NULL);
00066 return e;
00067 }
00068
00069 static void install_edge(Agraph_t * g, Agedge_t * e)
00070 {
00071 Agraph_t *meta;
00072 Agedge_t *f;
00073
00074 if (dtsearch(g->inedges, e))
00075 return;
00076 agINSnode(g, e->tail);
00077 agINSnode(g, e->head);
00078 dtinsert(g->outedges, e);
00079 dtinsert(g->inedges, e);
00080 f = (Agedge_t *) dtprev(g->outedges, e);
00081 if (f && (f->tail == e->tail) && (f->head == e->head)
00082 && (e->printkey == NOPRINT))
00083 e->printkey = MULTIPLE;
00084 if (AG_IS_METAGRAPH(g) == FALSE) {
00085 meta = g->meta_node->graph;
00086 for (f = agfstin(meta, g->meta_node); f; f = agnxtin(meta, f)) {
00087 install_edge(agusergraph(f->tail), e);
00088 }
00089 }
00090 }
00091
00092 void agINSedge(Agraph_t * g, Agedge_t * e)
00093 {
00094 if (e->printkey == MULTIPLE)
00095 e->printkey = MUSTPRINT;
00096 install_edge(g, e);
00097 }
00098
00099
00100 static int printedge(Dict_t * d, void *p, void *ignored)
00101 {
00102 Agedge_t *e = (Agedge_t *) p;
00103 agerr(AGPREV, "\t%p %s,%s\n", e, e->tail->name, e->head->name);
00104 return 0;
00105 }
00106
00107 Agedge_t *agfstedge(Agraph_t * g, Agnode_t * n)
00108 {
00109 Agedge_t *e;
00110
00111 e = NULL;
00112 if ((g != NULL) && (n != NULL)) {
00113 e = agfstout(g, n);
00114 if (e == NULL)
00115 e = agfstin(g, n);
00116 }
00117 return e;
00118 }
00119
00120 Agedge_t *agnxtedge(Agraph_t * g, Agedge_t * e, Agnode_t * n)
00121 {
00122 Agedge_t *f;
00123
00124 f = NULL;
00125 if ((g != NULL) && (e != NULL) && (n != NULL)) {
00126 if (e->tail == n) {
00127 f = (Agedge_t *) dtnext(g->outedges, e);
00128 if ((f != NULL) && (f->tail == n))
00129 return f;
00130 f = agfstin(g, n);
00131 while (f && (f->head == f->tail) && (f->head == n))
00132 f = (Agedge_t *) dtnext(g->inedges, f);
00133 } else {
00134 if (e->head != n)
00135 return NULL;
00136 else
00137 f = (Agedge_t *) dtnext(g->inedges, e);
00138 }
00139 while (f && (f->head == f->tail) && (f->head == n))
00140 f = (Agedge_t *) dtnext(g->inedges, f);
00141 if (f && (f->head != n))
00142 f = NULL;
00143 }
00144 return f;
00145 }
00146
00147 Agedge_t *agfstout(Agraph_t * g, Agnode_t * n)
00148 {
00149 Agedge_t *f, key;
00150
00151 f = NULL;
00152 if ((g != NULL) && (n != NULL)) {
00153 key.tail = n;
00154 key.head = NULL;
00155 key.attr = NULL;
00156 f = (Agedge_t *) dtnext(g->outedges, &key);
00157 if (f && (f->tail != n))
00158 f = NULL;
00159 }
00160 return f;
00161 }
00162
00163 Agedge_t *agnxtout(Agraph_t * g, Agedge_t * e)
00164 {
00165 Agedge_t *f;
00166 f = (Agedge_t *) dtnext(g->outedges, e);
00167 if (f && (f->tail != e->tail))
00168 f = NULL;
00169 return f;
00170 }
00171
00172 Agedge_t *agfstin(Agraph_t * g, Agnode_t * n)
00173 {
00174 Agedge_t *f, key;
00175
00176 f = NULL;
00177 if ((g != NULL) && (n != NULL)) {
00178 key.head = n;
00179 key.tail = NULL;
00180 key.attr = NULL;
00181 f = (Agedge_t *) dtnext(g->inedges, &key);
00182 if (f && (f->head != n))
00183 f = NULL;
00184 }
00185 return f;
00186 }
00187
00188 Agedge_t *agnxtin(Agraph_t * g, Agedge_t * e)
00189 {
00190 Agedge_t *f;
00191
00192 f = (Agedge_t *) dtnext(g->inedges, e);
00193 if (f && (f->head != e->head))
00194 f = NULL;
00195 return f;
00196 }
00197
00198 Agedge_t *agNEWedge(Agraph_t * subg, Agnode_t * tail, Agnode_t * head,
00199 Agedge_t * proto)
00200 {
00201 int i, nobj;
00202 Agedge_t *e;
00203
00204 e = (Agedge_t *) calloc(1, AG.edge_nbytes);
00205 e->tag = TAG_EDGE;
00206 e->tail = tail;
00207 e->head = head;
00208 e->id = subg->univ->max_edge_id++;
00209
00210 nobj = dtsize(subg->univ->edgeattr->dict);
00211 if (nobj) {
00212 e->attr = N_NEW(nobj, char *);
00213 e->didset = N_NEW((nobj + CHAR_BIT - 1) / CHAR_BIT, char);
00214 }
00215 else {
00216 e->attr = NULL;
00217 e->didset = NULL;
00218 }
00219 for (i = 0; i < nobj; i++)
00220 e->attr[i] =
00221 agstrdup(proto ? proto->attr[i] : subg->univ->edgeattr->
00222 list[i]->value);
00223 return e;
00224 }
00225
00226 Agedge_t *agedge(Agraph_t * g, Agnode_t * tail, Agnode_t * head)
00227 {
00228 Agedge_t *e;
00229 char *keystr, key[SMALLBUF], printkey = NOPRINT;
00230 static int ctr;
00231
00232 keystr = g->proto->e->attr[KEYX];
00233 e = NULL;
00234 g->proto->e->head = head;
00235 g->proto->e->tail = tail;
00236 if (AG_IS_STRICT(g)) {
00237 e = esearch(g, tail, head, NULL);
00238 if (!e && !AG_IS_DIRECTED(g))
00239 e = esearch(g, head, tail, NULL);
00240 if (e)
00241 install_edge(g, e);
00242 } else {
00243 if (keystr[0]) {
00244 e = esearch(g, tail, head, keystr);
00245 if (!e && !AG_IS_DIRECTED(g))
00246 e = esearch(g, head, tail, keystr);
00247 if (e)
00248 agINSedge(g, e);
00249 else
00250 printkey = MUSTPRINT;
00251 } else {
00252 sprintf(key, "%d", ctr++);
00253 g->proto->e->attr[KEYX] = key;
00254 }
00255 }
00256 if (e == NULL) {
00257 e = agNEWedge(g, tail, head, g->proto->e);
00258 install_edge(g, e);
00259 g->proto->e->head = g->proto->e->tail = g->proto->n;
00260 e->printkey = printkey;
00261 }
00262 g->proto->e->attr[KEYX] = keystr;
00263 return e;
00264 }
00265
00266 void agFREEedge(Agedge_t * e)
00267 {
00268 int i, nobj;
00269 Agdict_t *dict = agdictof(e);
00270
00271 dict = dict;
00272 TAG_OF(e) = -1;
00273 nobj = dtsize(e->tail->graph->univ->edgeattr->dict);
00274 for (i = 0; i < nobj; i++)
00275 agstrfree(e->attr[i]);
00276 free(e->attr);
00277 free(e->didset);
00278 free(e);
00279 }
00280
00281 void agDELedge(Agraph_t * g, Agedge_t * e)
00282 {
00283 Agraph_t *meta;
00284 Agraph_t *g0;
00285 Agedge_t *f;
00286
00287 if (dtsearch(g->inedges, e) == NULL) {
00288 agerr(AGERR, "Edge %p was not found\n", e);
00289 dtwalk(g->inedges, printedge, NIL(void *));
00290 return;
00291 }
00292 if (AG_IS_METAGRAPH(g) == FALSE) {
00293 meta = g->meta_node->graph;
00294 for (f = agfstout(meta, g->meta_node); f; f = agnxtout(meta, f)) {
00295 g0 = agusergraph(f->head);
00296 if (dtsearch(g0->inedges, e))
00297 agDELedge(g0, e);
00298 }
00299 }
00300 dtdelete(g->inedges, e);
00301 dtdelete(g->outedges, e);
00302 if (g == g->root)
00303 agFREEedge(e);
00304 }