00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018 #include <render.h>
00019 #include <pack.h>
00020 #include <ctype.h>
00021
00022 #define MARKED(n) ((n)->u.mark)
00023 #define MARK(n) ((n)->u.mark = 1)
00024 #define UNMARK(n) ((n)->u.mark = 0)
00025
00026 typedef void (*dfsfn) (Agnode_t *, void *);
00027
00028 static void dfs(Agraph_t * g, Agnode_t * n, dfsfn action, void *state)
00029 {
00030 Agedge_t *e;
00031 Agnode_t *other;
00032
00033 MARK(n);
00034 action(n, state);
00035 for (e = agfstedge(g, n); e; e = agnxtedge(g, e, n)) {
00036 if ((other = e->tail) == n)
00037 other = e->head;
00038 if (!MARKED(other))
00039 dfs(g, other, action, state);
00040 }
00041 }
00042
00043 static int isLegal(char *p)
00044 {
00045 unsigned char c;
00046
00047 while ((c = *(unsigned char *) p++)) {
00048 if ((c != '_') && !isalnum(c))
00049 return 0;
00050 }
00051
00052 return 1;
00053 }
00054
00055
00056
00057 static void insertFn(Agnode_t * n, void *state)
00058 {
00059 aginsert((Agraph_t *) state, n);
00060 }
00061
00062
00063
00064
00065
00066
00067
00068
00069
00070
00071
00072
00073 Agraph_t **pccomps(Agraph_t * g, int *ncc, char *pfx, boolean * pinned)
00074 {
00075 int c_cnt = 0;
00076 char buffer[SMALLBUF];
00077 char *name;
00078 Agraph_t *out = 0;
00079 Agnode_t *n;
00080 Agraph_t **ccs;
00081 int len;
00082 int bnd = 10;
00083 boolean pin = FALSE;
00084
00085 if (agnnodes(g) == 0) {
00086 *ncc = 0;
00087 return 0;
00088 }
00089 if (!pfx || !isLegal(pfx)) {
00090 pfx = "_cc_";
00091 }
00092 len = strlen(pfx);
00093 if (len + 25 <= SMALLBUF)
00094 name = buffer;
00095 else
00096 name = (char *) gmalloc(len + 25);
00097 strcpy(name, pfx);
00098
00099 for (n = agfstnode(g); n; n = agnxtnode(g, n))
00100 UNMARK(n);
00101
00102 ccs = N_GNEW(bnd, Agraph_t *);
00103
00104
00105 for (n = agfstnode(g); n; n = agnxtnode(g, n)) {
00106 if (MARKED(n) || !isPinned(n))
00107 continue;
00108 if (!out) {
00109 sprintf(name + len, "%d", c_cnt);
00110 out = agsubg(g, name);
00111 ccs[c_cnt] = out;
00112 c_cnt++;
00113 pin = TRUE;
00114 }
00115 dfs(g, n, insertFn, out);
00116 }
00117
00118
00119 for (n = agfstnode(g); n; n = agnxtnode(g, n)) {
00120 if (MARKED(n))
00121 continue;
00122 sprintf(name + len, "%d", c_cnt);
00123 out = agsubg(g, name);
00124 dfs(g, n, insertFn, out);
00125 if (c_cnt == bnd) {
00126 bnd *= 2;
00127 ccs = RALLOC(bnd, ccs, Agraph_t *);
00128 }
00129 ccs[c_cnt] = out;
00130 c_cnt++;
00131 }
00132
00133 ccs = RALLOC(c_cnt, ccs, Agraph_t *);
00134 if (name != buffer)
00135 free(name);
00136 *ncc = c_cnt;
00137 *pinned = pin;
00138 return ccs;
00139 }
00140
00141
00142
00143
00144
00145
00146
00147
00148
00149 Agraph_t **ccomps(Agraph_t * g, int *ncc, char *pfx)
00150 {
00151 int c_cnt = 0;
00152 char buffer[SMALLBUF];
00153 char *name;
00154 Agraph_t *out;
00155 Agnode_t *n;
00156 Agraph_t **ccs;
00157 int len;
00158 int bnd = 10;
00159
00160 if (agnnodes(g) == 0) {
00161 *ncc = 0;
00162 return 0;
00163 }
00164 if (!pfx || !isLegal(pfx)) {
00165 pfx = "_cc_";
00166 }
00167 len = strlen(pfx);
00168 if (len + 25 <= SMALLBUF)
00169 name = buffer;
00170 else
00171 name = (char *) gmalloc(len + 25);
00172 strcpy(name, pfx);
00173
00174 for (n = agfstnode(g); n; n = agnxtnode(g, n))
00175 UNMARK(n);
00176
00177 ccs = N_GNEW(bnd, Agraph_t *);
00178 for (n = agfstnode(g); n; n = agnxtnode(g, n)) {
00179 if (MARKED(n))
00180 continue;
00181 sprintf(name + len, "%d", c_cnt);
00182 out = agsubg(g, name);
00183 dfs(g, n, insertFn, out);
00184 if (c_cnt == bnd) {
00185 bnd *= 2;
00186 ccs = RALLOC(bnd, ccs, Agraph_t *);
00187 }
00188 ccs[c_cnt] = out;
00189 c_cnt++;
00190 }
00191 ccs = RALLOC(c_cnt, ccs, Agraph_t *);
00192 if (name != buffer)
00193 free(name);
00194 *ncc = c_cnt;
00195 return ccs;
00196 }
00197
00198
00199
00200 static void cntFn(Agnode_t * n, void *s)
00201 {
00202 *(int *) s += 1;
00203 }
00204
00205
00206
00207
00208 int isConnected(Agraph_t * g)
00209 {
00210 Agnode_t *n;
00211 int ret = 1;
00212 int cnt = 0;
00213
00214 for (n = agfstnode(g); n; n = agnxtnode(g, n))
00215 UNMARK(n);
00216
00217 n = agfstnode(g);
00218 if (n) {
00219 dfs(g, n, cntFn, &cnt);
00220 if (cnt != agnnodes(g))
00221 ret = 0;
00222 }
00223 return ret;
00224 }
00225
00226
00227
00228
00229
00230
00231
00232
00233 int nodeInduce(Agraph_t * g)
00234 {
00235 Agnode_t *n;
00236 Agraph_t *root = g->root;
00237 Agedge_t *e;
00238 int e_cnt = 0;
00239
00240 for (n = agfstnode(g); n; n = agnxtnode(g, n)) {
00241 for (e = agfstout(root, n); e; e = agnxtout(root, e)) {
00242 if (agcontains(g, e->head)) {
00243 aginsert(g, e);
00244 e_cnt++;
00245 }
00246 }
00247 }
00248 return e_cnt;
00249 }