summaryrefslogtreecommitdiff
path: root/src/regex/regex_test_graph.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/regex/regex_test_graph.c')
-rw-r--r--src/regex/regex_test_graph.c281
1 files changed, 141 insertions, 140 deletions
diff --git a/src/regex/regex_test_graph.c b/src/regex/regex_test_graph.c
index e809d578d..c988b5aae 100644
--- a/src/regex/regex_test_graph.c
+++ b/src/regex/regex_test_graph.c
@@ -31,7 +31,8 @@
31 * Context for graph creation. Passed as the cls to 31 * Context for graph creation. Passed as the cls to
32 * REGEX_TEST_automaton_save_graph_step. 32 * REGEX_TEST_automaton_save_graph_step.
33 */ 33 */
34struct REGEX_TEST_Graph_Context { 34struct REGEX_TEST_Graph_Context
35{
35 /** 36 /**
36 * File pointer to the dot file used for output. 37 * File pointer to the dot file used for output.
37 */ 38 */
@@ -62,10 +63,10 @@ struct REGEX_TEST_Graph_Context {
62 * @param stack_size current size of the stack 63 * @param stack_size current size of the stack
63 */ 64 */
64static void 65static void
65scc_tarjan_strongconnect(unsigned int *scc_counter, 66scc_tarjan_strongconnect (unsigned int *scc_counter,
66 struct REGEX_INTERNAL_State *v, unsigned int *index, 67 struct REGEX_INTERNAL_State *v, unsigned int *index,
67 struct REGEX_INTERNAL_State **stack, 68 struct REGEX_INTERNAL_State **stack,
68 unsigned int *stack_size) 69 unsigned int *stack_size)
69{ 70{
70 struct REGEX_INTERNAL_State *w; 71 struct REGEX_INTERNAL_State *w;
71 struct REGEX_INTERNAL_Transition *t; 72 struct REGEX_INTERNAL_Transition *t;
@@ -77,32 +78,32 @@ scc_tarjan_strongconnect(unsigned int *scc_counter,
77 v->contained = 1; 78 v->contained = 1;
78 79
79 for (t = v->transitions_head; NULL != t; t = t->next) 80 for (t = v->transitions_head; NULL != t; t = t->next)
81 {
82 w = t->to_state;
83
84 if (NULL == w)
85 continue;
86
87 if (w->index < 0)
80 { 88 {
81 w = t->to_state; 89 scc_tarjan_strongconnect (scc_counter, w, index, stack, stack_size);
82 90 v->lowlink = (v->lowlink > w->lowlink) ? w->lowlink : v->lowlink;
83 if (NULL == w)
84 continue;
85
86 if (w->index < 0)
87 {
88 scc_tarjan_strongconnect(scc_counter, w, index, stack, stack_size);
89 v->lowlink = (v->lowlink > w->lowlink) ? w->lowlink : v->lowlink;
90 }
91 else if (1 == w->contained)
92 v->lowlink = (v->lowlink > w->index) ? w->index : v->lowlink;
93 } 91 }
92 else if (1 == w->contained)
93 v->lowlink = (v->lowlink > w->index) ? w->index : v->lowlink;
94 }
94 95
95 if (v->lowlink == v->index) 96 if (v->lowlink == v->index)
97 {
98 (*scc_counter)++;
99 do
96 { 100 {
97 (*scc_counter)++; 101 w = stack[--(*stack_size)];
98 do 102 w->contained = 0;
99 { 103 w->scc_id = *scc_counter;
100 w = stack[--(*stack_size)];
101 w->contained = 0;
102 w->scc_id = *scc_counter;
103 }
104 while (w != v);
105 } 104 }
105 while (w != v);
106 }
106} 107}
107 108
108 109
@@ -113,7 +114,7 @@ scc_tarjan_strongconnect(unsigned int *scc_counter,
113 * @param a the automaton for which SCCs should be computed and assigned. 114 * @param a the automaton for which SCCs should be computed and assigned.
114 */ 115 */
115static void 116static void
116scc_tarjan(struct REGEX_INTERNAL_Automaton *a) 117scc_tarjan (struct REGEX_INTERNAL_Automaton *a)
117{ 118{
118 unsigned int index; 119 unsigned int index;
119 unsigned int scc_counter; 120 unsigned int scc_counter;
@@ -122,21 +123,21 @@ scc_tarjan(struct REGEX_INTERNAL_Automaton *a)
122 unsigned int stack_size; 123 unsigned int stack_size;
123 124
124 for (v = a->states_head; NULL != v; v = v->next) 125 for (v = a->states_head; NULL != v; v = v->next)
125 { 126 {
126 v->contained = 0; 127 v->contained = 0;
127 v->index = -1; 128 v->index = -1;
128 v->lowlink = -1; 129 v->lowlink = -1;
129 } 130 }
130 131
131 stack_size = 0; 132 stack_size = 0;
132 index = 0; 133 index = 0;
133 scc_counter = 0; 134 scc_counter = 0;
134 135
135 for (v = a->states_head; NULL != v; v = v->next) 136 for (v = a->states_head; NULL != v; v = v->next)
136 { 137 {
137 if (v->index < 0) 138 if (v->index < 0)
138 scc_tarjan_strongconnect(&scc_counter, v, &index, stack, &stack_size); 139 scc_tarjan_strongconnect (&scc_counter, v, &index, stack, &stack_size);
139 } 140 }
140} 141}
141 142
142 143
@@ -150,8 +151,8 @@ scc_tarjan(struct REGEX_INTERNAL_Automaton *a)
150 * @param s state. 151 * @param s state.
151 */ 152 */
152void 153void
153REGEX_TEST_automaton_save_graph_step(void *cls, unsigned int count, 154REGEX_TEST_automaton_save_graph_step (void *cls, unsigned int count,
154 struct REGEX_INTERNAL_State *s) 155 struct REGEX_INTERNAL_State *s)
155{ 156{
156 struct REGEX_TEST_Graph_Context *ctx = cls; 157 struct REGEX_TEST_Graph_Context *ctx = cls;
157 struct REGEX_INTERNAL_Transition *ctran; 158 struct REGEX_INTERNAL_Transition *ctran;
@@ -161,100 +162,100 @@ REGEX_TEST_automaton_save_graph_step(void *cls, unsigned int count,
161 char *to_name; 162 char *to_name;
162 163
163 if (GNUNET_YES == ctx->verbose) 164 if (GNUNET_YES == ctx->verbose)
164 GNUNET_asprintf(&name, "%i (%s) (%s) (%s)", s->dfs_id, s->name, s->proof, 165 GNUNET_asprintf (&name, "%i (%s) (%s) (%s)", s->dfs_id, s->name, s->proof,
165 GNUNET_h2s(&s->hash)); 166 GNUNET_h2s (&s->hash));
166 else 167 else
167 GNUNET_asprintf(&name, "%i", s->dfs_id); 168 GNUNET_asprintf (&name, "%i", s->dfs_id);
168 169
169 if (s->accepting) 170 if (s->accepting)
171 {
172 if (GNUNET_YES == ctx->coloring)
170 { 173 {
171 if (GNUNET_YES == ctx->coloring) 174 GNUNET_asprintf (&s_acc,
172 { 175 "\"%s\" [shape=doublecircle, color=\"0.%i 0.8 0.95\"];\n",
173 GNUNET_asprintf(&s_acc, 176 name, s->scc_id * s->scc_id);
174 "\"%s\" [shape=doublecircle, color=\"0.%i 0.8 0.95\"];\n",
175 name, s->scc_id * s->scc_id);
176 }
177 else
178 {
179 GNUNET_asprintf(&s_acc, "\"%s\" [shape=doublecircle];\n", name,
180 s->scc_id);
181 }
182 } 177 }
183 else if (GNUNET_YES == ctx->coloring) 178 else
184 { 179 {
185 GNUNET_asprintf(&s_acc, 180 GNUNET_asprintf (&s_acc, "\"%s\" [shape=doublecircle];\n", name,
186 "\"%s\" [shape=circle, color=\"0.%i 0.8 0.95\"];\n", name, 181 s->scc_id);
187 s->scc_id * s->scc_id);
188 } 182 }
183 }
184 else if (GNUNET_YES == ctx->coloring)
185 {
186 GNUNET_asprintf (&s_acc,
187 "\"%s\" [shape=circle, color=\"0.%i 0.8 0.95\"];\n", name,
188 s->scc_id * s->scc_id);
189 }
189 else 190 else
190 { 191 {
191 GNUNET_asprintf(&s_acc, "\"%s\" [shape=circle];\n", name, s->scc_id); 192 GNUNET_asprintf (&s_acc, "\"%s\" [shape=circle];\n", name, s->scc_id);
192 } 193 }
193 194
194 GNUNET_assert(NULL != s_acc); 195 GNUNET_assert (NULL != s_acc);
195 196
196 fwrite(s_acc, strlen(s_acc), 1, ctx->filep); 197 fwrite (s_acc, strlen (s_acc), 1, ctx->filep);
197 GNUNET_free(s_acc); 198 GNUNET_free (s_acc);
198 s_acc = NULL; 199 s_acc = NULL;
199 200
200 for (ctran = s->transitions_head; NULL != ctran; ctran = ctran->next) 201 for (ctran = s->transitions_head; NULL != ctran; ctran = ctran->next)
202 {
203 if (NULL == ctran->to_state)
204 {
205 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
206 "Transition from State %i has no state for transitioning\n",
207 s->id);
208 continue;
209 }
210
211 if (GNUNET_YES == ctx->verbose)
212 {
213 GNUNET_asprintf (&to_name, "%i (%s) (%s) (%s)", ctran->to_state->dfs_id,
214 ctran->to_state->name, ctran->to_state->proof,
215 GNUNET_h2s (&ctran->to_state->hash));
216 }
217 else
218 GNUNET_asprintf (&to_name, "%i", ctran->to_state->dfs_id);
219
220 if (NULL == ctran->label)
201 { 221 {
202 if (NULL == ctran->to_state) 222 if (GNUNET_YES == ctx->coloring)
203 { 223 {
204 GNUNET_log(GNUNET_ERROR_TYPE_ERROR, 224 GNUNET_asprintf (&s_tran,
205 "Transition from State %i has no state for transitioning\n", 225 "\"%s\" -> \"%s\" [label = \"ε\", color=\"0.%i 0.8 0.95\"];\n",
206 s->id); 226 name, to_name, s->scc_id * s->scc_id);
207 continue; 227 }
208 }
209
210 if (GNUNET_YES == ctx->verbose)
211 {
212 GNUNET_asprintf(&to_name, "%i (%s) (%s) (%s)", ctran->to_state->dfs_id,
213 ctran->to_state->name, ctran->to_state->proof,
214 GNUNET_h2s(&ctran->to_state->hash));
215 }
216 else 228 else
217 GNUNET_asprintf(&to_name, "%i", ctran->to_state->dfs_id); 229 {
218 230 GNUNET_asprintf (&s_tran, "\"%s\" -> \"%s\" [label = \"ε\"];\n", name,
219 if (NULL == ctran->label) 231 to_name, s->scc_id);
220 { 232 }
221 if (GNUNET_YES == ctx->coloring) 233 }
222 { 234 else
223 GNUNET_asprintf(&s_tran, 235 {
224 "\"%s\" -> \"%s\" [label = \"ε\", color=\"0.%i 0.8 0.95\"];\n", 236 if (GNUNET_YES == ctx->coloring)
225 name, to_name, s->scc_id * s->scc_id); 237 {
226 } 238 GNUNET_asprintf (&s_tran,
227 else 239 "\"%s\" -> \"%s\" [label = \"%s\", color=\"0.%i 0.8 0.95\"];\n",
228 { 240 name, to_name, ctran->label, s->scc_id * s->scc_id);
229 GNUNET_asprintf(&s_tran, "\"%s\" -> \"%s\" [label = \"ε\"];\n", name, 241 }
230 to_name, s->scc_id);
231 }
232 }
233 else 242 else
234 { 243 {
235 if (GNUNET_YES == ctx->coloring) 244 GNUNET_asprintf (&s_tran, "\"%s\" -> \"%s\" [label = \"%s\"];\n", name,
236 { 245 to_name, ctran->label, s->scc_id);
237 GNUNET_asprintf(&s_tran, 246 }
238 "\"%s\" -> \"%s\" [label = \"%s\", color=\"0.%i 0.8 0.95\"];\n",
239 name, to_name, ctran->label, s->scc_id * s->scc_id);
240 }
241 else
242 {
243 GNUNET_asprintf(&s_tran, "\"%s\" -> \"%s\" [label = \"%s\"];\n", name,
244 to_name, ctran->label, s->scc_id);
245 }
246 }
247
248 GNUNET_free(to_name);
249
250 GNUNET_assert(NULL != s_tran);
251
252 fwrite(s_tran, strlen(s_tran), 1, ctx->filep);
253 GNUNET_free(s_tran);
254 s_tran = NULL;
255 } 247 }
256 248
257 GNUNET_free(name); 249 GNUNET_free (to_name);
250
251 GNUNET_assert (NULL != s_tran);
252
253 fwrite (s_tran, strlen (s_tran), 1, ctx->filep);
254 GNUNET_free (s_tran);
255 s_tran = NULL;
256 }
257
258 GNUNET_free (name);
258} 259}
259 260
260 261
@@ -267,51 +268,51 @@ REGEX_TEST_automaton_save_graph_step(void *cls, unsigned int count,
267 * mode 268 * mode
268 */ 269 */
269void 270void
270REGEX_TEST_automaton_save_graph(struct REGEX_INTERNAL_Automaton *a, 271REGEX_TEST_automaton_save_graph (struct REGEX_INTERNAL_Automaton *a,
271 const char *filename, 272 const char *filename,
272 enum REGEX_TEST_GraphSavingOptions options) 273 enum REGEX_TEST_GraphSavingOptions options)
273{ 274{
274 char *start; 275 char *start;
275 char *end; 276 char *end;
276 struct REGEX_TEST_Graph_Context ctx; 277 struct REGEX_TEST_Graph_Context ctx;
277 278
278 if (NULL == a) 279 if (NULL == a)
279 { 280 {
280 GNUNET_log(GNUNET_ERROR_TYPE_ERROR, "Could not print NFA, was NULL!"); 281 GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "Could not print NFA, was NULL!");
281 return; 282 return;
282 } 283 }
283 284
284 if (NULL == filename || strlen(filename) < 1) 285 if ((NULL == filename)||(strlen (filename) < 1))
285 { 286 {
286 GNUNET_log(GNUNET_ERROR_TYPE_ERROR, "No Filename given!"); 287 GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "No Filename given!");
287 return; 288 return;
288 } 289 }
289 290
290 ctx.filep = fopen(filename, "w"); 291 ctx.filep = fopen (filename, "w");
291 ctx.verbose = 292 ctx.verbose =
292 (0 == (options & REGEX_TEST_GRAPH_VERBOSE)) ? GNUNET_NO : GNUNET_YES; 293 (0 == (options & REGEX_TEST_GRAPH_VERBOSE)) ? GNUNET_NO : GNUNET_YES;
293 ctx.coloring = 294 ctx.coloring =
294 (0 == (options & REGEX_TEST_GRAPH_COLORING)) ? GNUNET_NO : GNUNET_YES; 295 (0 == (options & REGEX_TEST_GRAPH_COLORING)) ? GNUNET_NO : GNUNET_YES;
295 296
296 if (NULL == ctx.filep) 297 if (NULL == ctx.filep)
297 { 298 {
298 GNUNET_log(GNUNET_ERROR_TYPE_ERROR, "Could not open file for writing: %s", 299 GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "Could not open file for writing: %s",
299 filename); 300 filename);
300 return; 301 return;
301 } 302 }
302 303
303 /* First add the SCCs to the automaton, so we can color them nicely */ 304 /* First add the SCCs to the automaton, so we can color them nicely */
304 if (GNUNET_YES == ctx.coloring) 305 if (GNUNET_YES == ctx.coloring)
305 scc_tarjan(a); 306 scc_tarjan (a);
306 307
307 start = "digraph G {\nrankdir=LR\n"; 308 start = "digraph G {\nrankdir=LR\n";
308 fwrite(start, strlen(start), 1, ctx.filep); 309 fwrite (start, strlen (start), 1, ctx.filep);
309 310
310 REGEX_INTERNAL_automaton_traverse(a, a->start, NULL, NULL, 311 REGEX_INTERNAL_automaton_traverse (a, a->start, NULL, NULL,
311 &REGEX_TEST_automaton_save_graph_step, 312 &REGEX_TEST_automaton_save_graph_step,
312 &ctx); 313 &ctx);
313 314
314 end = "\n}\n"; 315 end = "\n}\n";
315 fwrite(end, strlen(end), 1, ctx.filep); 316 fwrite (end, strlen (end), 1, ctx.filep);
316 fclose(ctx.filep); 317 fclose (ctx.filep);
317} 318}