diff options
Diffstat (limited to 'src/regex/regex_test_graph.c')
-rw-r--r-- | src/regex/regex_test_graph.c | 281 |
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 | */ |
34 | struct REGEX_TEST_Graph_Context { | 34 | struct 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 | */ |
64 | static void | 65 | static void |
65 | scc_tarjan_strongconnect(unsigned int *scc_counter, | 66 | scc_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 | */ |
115 | static void | 116 | static void |
116 | scc_tarjan(struct REGEX_INTERNAL_Automaton *a) | 117 | scc_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 | */ |
152 | void | 153 | void |
153 | REGEX_TEST_automaton_save_graph_step(void *cls, unsigned int count, | 154 | REGEX_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 | */ |
269 | void | 270 | void |
270 | REGEX_TEST_automaton_save_graph(struct REGEX_INTERNAL_Automaton *a, | 271 | REGEX_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 | ®EX_TEST_automaton_save_graph_step, | 312 | ®EX_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 | } |