test
[oweals/gnunet.git] / src / regex / regex.c
1 /*
2      This file is part of GNUnet
3      (C) 2012 Christian Grothoff (and other contributing authors)
4
5      GNUnet is free software; you can redistribute it and/or modify
6      it under the terms of the GNU General Public License as published
7      by the Free Software Foundation; either version 3, or (at your
8      option) any later version.
9
10      GNUnet is distributed in the hope that it will be useful, but
11      WITHOUT ANY WARRANTY; without even the implied warranty of
12      MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
13      General Public License for more details.
14
15      You should have received a copy of the GNU General Public License
16      along with GNUnet; see the file COPYING.  If not, write to the
17      Free Software Foundation, Inc., 59 Temple Place - Suite 330,
18      Boston, MA 02111-1307, USA.
19 */
20 /**
21  * @file src/regex/regex.c
22  * @brief library to create automatons from regular expressions
23  * @author Maximilian Szengel
24  */
25 #include "platform.h"
26 #include "gnunet_container_lib.h"
27 #include "gnunet_crypto_lib.h"
28 #include "gnunet_regex_lib.h"
29 #include "regex_internal.h"
30
31
32 /**
33  * Constant for how many bits the initial string regex should have.
34  */
35 #define INITIAL_BITS 8
36
37
38 /**
39  * Set of states.
40  */
41 struct GNUNET_REGEX_StateSet
42 {
43   /**
44    * Array of states.
45    */
46   struct GNUNET_REGEX_State **states;
47
48   /**
49    * Length of the 'states' array.
50    */
51   unsigned int len;
52 };
53
54
55 /*
56  * Debug helper functions
57  */
58
59 /**
60  * Print all the transitions of state 's'.
61  *
62  * @param s state for which to print it's transitions.
63  */
64 void
65 debug_print_transitions (struct GNUNET_REGEX_State *s);
66
67
68 /**
69  * Print information of the given state 's'.
70  *
71  * @param s state for which debug information should be printed.
72  */
73 void
74 debug_print_state (struct GNUNET_REGEX_State *s)
75 {
76   char *proof;
77
78   if (NULL == s->proof)
79     proof = "NULL";
80   else
81     proof = s->proof;
82
83   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
84               "State %i: %s marked: %i accepting: %i scc_id: %i transitions: %i proof: %s\n",
85               s->id, s->name, s->marked, s->accepting, s->scc_id,
86               s->transition_count, proof);
87
88   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Transitions:\n");
89   debug_print_transitions (s);
90 }
91
92
93 /**
94  * Print debug information for all states contained in the automaton 'a'.
95  *
96  * @param a automaton for which debug information of it's states should be printed.
97  */
98 void
99 debug_print_states (struct GNUNET_REGEX_Automaton *a)
100 {
101   struct GNUNET_REGEX_State *s;
102
103   for (s = a->states_head; NULL != s; s = s->next)
104     debug_print_state (s);
105 }
106
107
108 /**
109  * Print debug information for given transition 't'.
110  *
111  * @param t transition for which to print debug info.
112  */
113 void
114 debug_print_transition (struct GNUNET_REGEX_Transition *t)
115 {
116   char *to_state;
117   char *from_state;
118   char *label;
119
120   if (NULL == t)
121     return;
122
123   if (0 == t->label)
124     label = "0";
125   else
126     label = t->label;
127
128   if (NULL == t->to_state)
129     to_state = "NULL";
130   else
131     to_state = t->to_state->name;
132
133   if (NULL == t->from_state)
134     from_state = "NULL";
135   else
136     from_state = t->from_state->name;
137
138   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Transition %i: From %s on %s to %s\n",
139               t->id, from_state, label, to_state);
140 }
141
142
143 void
144 debug_print_transitions (struct GNUNET_REGEX_State *s)
145 {
146   struct GNUNET_REGEX_Transition *t;
147
148   for (t = s->transitions_head; NULL != t; t = t->next)
149     debug_print_transition (t);
150 }
151
152
153 /**
154  * Compare two strings for equality. If either is NULL they are not equal.
155  *
156  * @param str1 first string for comparison.
157  * @param str2 second string for comparison.
158  *
159  * @return 0 if the strings are the same or both NULL, 1 or -1 if not.
160  */
161 static int
162 nullstrcmp (const char *str1, const char *str2)
163 {
164   if ((NULL == str1) != (NULL == str2))
165     return -1;
166   if ((NULL == str1) && (NULL == str2))
167     return 0;
168
169   return strcmp (str1, str2);
170 }
171
172
173 /**
174  * Adds a transition from one state to another on 'label'. Does not add
175  * duplicate states.
176  *
177  * @param ctx context
178  * @param from_state starting state for the transition
179  * @param label transition label
180  * @param to_state state to where the transition should point to
181  */
182 static void
183 state_add_transition (struct GNUNET_REGEX_Context *ctx,
184                       struct GNUNET_REGEX_State *from_state, const char *label,
185                       struct GNUNET_REGEX_State *to_state)
186 {
187   int is_dup;
188   struct GNUNET_REGEX_Transition *t;
189   struct GNUNET_REGEX_Transition *oth;
190
191   if (NULL == from_state)
192   {
193     GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "Could not create Transition.\n");
194     return;
195   }
196
197   // Do not add duplicate state transitions
198   is_dup = GNUNET_NO;
199   for (t = from_state->transitions_head; NULL != t; t = t->next)
200   {
201     if (t->to_state == to_state && 0 == nullstrcmp (t->label, label) &&
202         t->from_state == from_state)
203     {
204       is_dup = GNUNET_YES;
205       break;
206     }
207   }
208
209   if (GNUNET_YES == is_dup)
210     return;
211
212   // sort transitions by label
213   for (oth = from_state->transitions_head; NULL != oth; oth = oth->next)
214   {
215     if (0 < nullstrcmp (oth->label, label))
216       break;
217   }
218
219   t = GNUNET_malloc (sizeof (struct GNUNET_REGEX_Transition));
220   if (NULL != ctx)
221     t->id = ctx->transition_id++;
222   if (NULL != label)
223     t->label = GNUNET_strdup (label);
224   else
225     t->label = NULL;
226   t->to_state = to_state;
227   t->from_state = from_state;
228
229   // Add outgoing transition to 'from_state'
230   from_state->transition_count++;
231   GNUNET_CONTAINER_DLL_insert_before (from_state->transitions_head,
232                                       from_state->transitions_tail, oth, t);
233 }
234
235
236 /**
237  * Remove a 'transition' from 'state'.
238  *
239  * @param state state from which the to-be-removed transition originates.
240  * @param transition transition that should be removed from state 'state'.
241  */
242 static void
243 state_remove_transition (struct GNUNET_REGEX_State *state,
244                          struct GNUNET_REGEX_Transition *transition)
245 {
246   if (NULL == state || NULL == transition)
247     return;
248
249   if (transition->from_state != state)
250     return;
251
252   state->transition_count--;
253   GNUNET_CONTAINER_DLL_remove (state->transitions_head, state->transitions_tail,
254                                transition);
255   GNUNET_free_non_null (transition->label);
256   GNUNET_free (transition);
257 }
258
259
260 /**
261  * Compare two states. Used for sorting.
262  *
263  * @param a first state
264  * @param b second state
265  *
266  * @return an integer less than, equal to, or greater than zero
267  *         if the first argument is considered to be respectively
268  *         less than, equal to, or greater than the second.
269  */
270 static int
271 state_compare (const void *a, const void *b)
272 {
273   struct GNUNET_REGEX_State **s1;
274   struct GNUNET_REGEX_State **s2;
275
276   s1 = (struct GNUNET_REGEX_State **) a;
277   s2 = (struct GNUNET_REGEX_State **) b;
278
279   return (*s1)->id - (*s2)->id;
280 }
281
282
283 /**
284  * Get all edges leaving state 's'.
285  *
286  * @param s state.
287  * @param edges all edges leaving 's', expected to be allocated and have enough
288  *        space for s->transitions_count elements.
289  *
290  * @return number of edges.
291  */
292 static unsigned int
293 state_get_edges (struct GNUNET_REGEX_State *s, struct GNUNET_REGEX_Edge *edges)
294 {
295   struct GNUNET_REGEX_Transition *t;
296   unsigned int count;
297
298   if (NULL == s)
299     return 0;
300
301   count = 0;
302
303   for (t = s->transitions_head; NULL != t; t = t->next)
304   {
305     if (NULL != t->to_state)
306     {
307       edges[count].label = t->label;
308       edges[count].destination = t->to_state->hash;
309       count++;
310     }
311   }
312   return count;
313 }
314
315
316 /**
317  * Compare to state sets by comparing the id's of the states that are contained
318  * in each set. Both sets are expected to be sorted by id!
319  *
320  * @param sset1 first state set
321  * @param sset2 second state set
322  *
323  * @return an integer less than, equal to, or greater than zero
324  *         if the first argument is considered to be respectively
325  *         less than, equal to, or greater than the second.
326  */
327 static int
328 state_set_compare (struct GNUNET_REGEX_StateSet *sset1,
329                    struct GNUNET_REGEX_StateSet *sset2)
330 {
331   int result;
332   unsigned int i;
333
334   if (NULL == sset1 || NULL == sset2)
335     return 1;
336
337   result = sset1->len - sset2->len;
338
339   for (i = 0; i < sset1->len; i++)
340   {
341     if (0 != result)
342       break;
343
344     result = state_compare (&sset1->states[i], &sset2->states[i]);
345   }
346   return result;
347 }
348
349
350 /**
351  * Clears the given StateSet 'set'
352  *
353  * @param set set to be cleared
354  */
355 static void
356 state_set_clear (struct GNUNET_REGEX_StateSet *set)
357 {
358   if (NULL != set)
359   {
360     GNUNET_free_non_null (set->states);
361     GNUNET_free (set);
362   }
363 }
364
365
366 /**
367  * Clears an automaton fragment. Does not destroy the states inside the
368  * automaton.
369  *
370  * @param a automaton to be cleared
371  */
372 static void
373 automaton_fragment_clear (struct GNUNET_REGEX_Automaton *a)
374 {
375   if (NULL == a)
376     return;
377
378   a->start = NULL;
379   a->end = NULL;
380   a->states_head = NULL;
381   a->states_tail = NULL;
382   a->state_count = 0;
383   GNUNET_free (a);
384 }
385
386
387 /**
388  * Frees the memory used by State 's'
389  *
390  * @param s state that should be destroyed
391  */
392 static void
393 automaton_destroy_state (struct GNUNET_REGEX_State *s)
394 {
395   struct GNUNET_REGEX_Transition *t;
396   struct GNUNET_REGEX_Transition *next_t;
397
398   if (NULL == s)
399     return;
400
401   GNUNET_free_non_null (s->name);
402   GNUNET_free_non_null (s->proof);
403
404   for (t = s->transitions_head; NULL != t; t = next_t)
405   {
406     next_t = t->next;
407     GNUNET_CONTAINER_DLL_remove (s->transitions_head, s->transitions_tail, t);
408     GNUNET_free_non_null (t->label);
409     GNUNET_free (t);
410   }
411
412   state_set_clear (s->nfa_set);
413
414   GNUNET_free (s);
415 }
416
417
418 /**
419  * Remove a state from the given automaton 'a'. Always use this function when
420  * altering the states of an automaton. Will also remove all transitions leading
421  * to this state, before destroying it.
422  *
423  * @param a automaton
424  * @param s state to remove
425  */
426 static void
427 automaton_remove_state (struct GNUNET_REGEX_Automaton *a,
428                         struct GNUNET_REGEX_State *s)
429 {
430   struct GNUNET_REGEX_State *ss;
431   struct GNUNET_REGEX_State *s_check;
432   struct GNUNET_REGEX_Transition *t_check;
433
434   if (NULL == a || NULL == s)
435     return;
436
437   // remove state
438   ss = s;
439   GNUNET_CONTAINER_DLL_remove (a->states_head, a->states_tail, s);
440   a->state_count--;
441
442   // remove all transitions leading to this state
443   for (s_check = a->states_head; NULL != s_check; s_check = s_check->next)
444   {
445     for (t_check = s_check->transitions_head; NULL != t_check;
446          t_check = t_check->next)
447     {
448       if (t_check->to_state == ss)
449       {
450         GNUNET_CONTAINER_DLL_remove (s_check->transitions_head,
451                                      s_check->transitions_tail, t_check);
452         s_check->transition_count--;
453       }
454     }
455   }
456
457   automaton_destroy_state (ss);
458 }
459
460
461 /**
462  * Merge two states into one. Will merge 's1' and 's2' into 's1' and destroy
463  * 's2'.
464  *
465  * @param ctx context
466  * @param a automaton
467  * @param s1 first state
468  * @param s2 second state, will be destroyed
469  */
470 static void
471 automaton_merge_states (struct GNUNET_REGEX_Context *ctx,
472                         struct GNUNET_REGEX_Automaton *a,
473                         struct GNUNET_REGEX_State *s1,
474                         struct GNUNET_REGEX_State *s2)
475 {
476   struct GNUNET_REGEX_State *s_check;
477   struct GNUNET_REGEX_Transition *t_check;
478   struct GNUNET_REGEX_Transition *t;
479   struct GNUNET_REGEX_Transition *t_next;
480   char *new_name;
481   int is_dup;
482
483   GNUNET_assert (NULL != ctx && NULL != a && NULL != s1 && NULL != s2);
484
485   if (s1 == s2)
486     return;
487
488   // 1. Make all transitions pointing to s2 point to s1, unless this transition
489   // does not already exists, if it already exists remove transition.
490   for (s_check = a->states_head; NULL != s_check; s_check = s_check->next)
491   {
492     for (t_check = s_check->transitions_head; NULL != t_check; t_check = t_next)
493     {
494       t_next = t_check->next;
495
496       if (s2 == t_check->to_state)
497       {
498         is_dup = GNUNET_NO;
499         for (t = t_check->from_state->transitions_head; NULL != t; t = t->next)
500         {
501           if (t->to_state == s1 && 0 == strcmp (t_check->label, t->label))
502             is_dup = GNUNET_YES;
503         }
504         if (GNUNET_NO == is_dup)
505           t_check->to_state = s1;
506         else
507           state_remove_transition (t_check->from_state, t_check);
508       }
509     }
510   }
511
512   // 2. Add all transitions from s2 to sX to s1
513   for (t_check = s2->transitions_head; NULL != t_check; t_check = t_check->next)
514   {
515     if (t_check->to_state != s1)
516       state_add_transition (ctx, s1, t_check->label, t_check->to_state);
517   }
518
519   // 3. Rename s1 to {s1,s2}
520   new_name = s1->name;
521   GNUNET_asprintf (&s1->name, "{%s,%s}", new_name, s2->name);
522   GNUNET_free (new_name);
523
524   // remove state
525   GNUNET_CONTAINER_DLL_remove (a->states_head, a->states_tail, s2);
526   a->state_count--;
527   automaton_destroy_state (s2);
528 }
529
530
531 /**
532  * Add a state to the automaton 'a', always use this function to alter the
533  * states DLL of the automaton.
534  *
535  * @param a automaton to add the state to
536  * @param s state that should be added
537  */
538 static void
539 automaton_add_state (struct GNUNET_REGEX_Automaton *a,
540                      struct GNUNET_REGEX_State *s)
541 {
542   GNUNET_CONTAINER_DLL_insert (a->states_head, a->states_tail, s);
543   a->state_count++;
544 }
545
546
547 /**
548  * Depth-first traversal (DFS) of all states that are reachable from state
549  * 's'. Performs 'action' on each visited state.
550  *
551  * @param s start state.
552  * @param marks an array of size a->state_count to remember which state was
553  *        already visited.
554  * @param count current count of the state.
555  * @param check function that is checked before advancing on each transition
556  *              in the DFS.
557  * @param check_cls closure for check.
558  * @param action action to be performed on each state.
559  * @param action_cls closure for action.
560  */
561 static void
562 automaton_state_traverse (struct GNUNET_REGEX_State *s, int *marks,
563                           unsigned int *count,
564                           GNUNET_REGEX_traverse_check check, void *check_cls,
565                           GNUNET_REGEX_traverse_action action, void *action_cls)
566 {
567   struct GNUNET_REGEX_Transition *t;
568
569   if (GNUNET_YES == marks[s->traversal_id])
570     return;
571
572   marks[s->traversal_id] = GNUNET_YES;
573
574   if (NULL != action)
575     action (action_cls, *count, s);
576
577   (*count)++;
578
579   for (t = s->transitions_head; NULL != t; t = t->next)
580   {
581     if (NULL == check ||
582         (NULL != check && GNUNET_YES == check (check_cls, s, t)))
583     {
584       automaton_state_traverse (t->to_state, marks, count, check, check_cls,
585                                 action, action_cls);
586     }
587   }
588 }
589
590
591 /**
592  * Traverses the given automaton using depth-first-search (DFS) from it's start
593  * state, visiting all reachable states and calling 'action' on each one of
594  * them.
595  *
596  * @param a automaton to be traversed.
597  * @param start start state, pass a->start or NULL to traverse the whole automaton.
598  * @param check function that is checked before advancing on each transition
599  *              in the DFS.
600  * @param check_cls closure for check.
601  * @param action action to be performed on each state.
602  * @param action_cls closure for action
603  */
604 void
605 GNUNET_REGEX_automaton_traverse (const struct GNUNET_REGEX_Automaton *a,
606                                  struct GNUNET_REGEX_State *start,
607                                  GNUNET_REGEX_traverse_check check,
608                                  void *check_cls,
609                                  GNUNET_REGEX_traverse_action action,
610                                  void *action_cls)
611 {
612   unsigned int count;
613   struct GNUNET_REGEX_State *s;
614   int marks[a->state_count];
615
616   if (NULL == a || 0 == a->state_count)
617     return;
618
619   for (count = 0, s = a->states_head; NULL != s && count < a->state_count;
620        s = s->next, count++)
621   {
622     s->traversal_id = count;
623     marks[s->traversal_id] = GNUNET_NO;
624   }
625
626   count = 0;
627
628   if (NULL == start)
629     s = a->start;
630   else
631     s = start;
632
633   automaton_state_traverse (s, marks, &count, check, check_cls, action,
634                             action_cls);
635 }
636
637
638 /**
639  * Context for adding strided transitions to a DFA.
640  */
641 struct GNUNET_REGEX_Strided_Context
642 {
643   /**
644    * Length of the strides.
645    */
646   const unsigned int stride;
647
648   /**
649    * Strided transitions DLL. New strided transitions will be stored in this DLL
650    * and afterwards added to the DFA.
651    */
652   struct GNUNET_REGEX_Transition *transitions_head;
653
654   /**
655    * Strided transitions DLL.
656    */
657   struct GNUNET_REGEX_Transition *transitions_tail;
658 };
659
660
661 /**
662  * Recursive helper function to add strides to a DFA.
663  *
664  * @param cls context, contains stride length and strided transitions DLL.
665  * @param depth current depth of the depth-first traversal of the graph.
666  * @param label current label, string that contains all labels on the path from
667  *        'start' to 's'.
668  * @param start start state for the depth-first traversal of the graph.
669  * @param s current state in the depth-first traversal
670  */
671 void
672 add_multi_strides_to_dfa_helper (void *cls, const unsigned int depth,
673                                  char *label, struct GNUNET_REGEX_State *start,
674                                  struct GNUNET_REGEX_State *s)
675 {
676   struct GNUNET_REGEX_Strided_Context *ctx = cls;
677   struct GNUNET_REGEX_Transition *t;
678   char *new_label;
679
680   if (depth == ctx->stride)
681   {
682     t = GNUNET_malloc (sizeof (struct GNUNET_REGEX_Transition));
683     t->label = GNUNET_strdup (label);
684     t->to_state = s;
685     t->from_state = start;
686     GNUNET_CONTAINER_DLL_insert (ctx->transitions_head, ctx->transitions_tail,
687                                  t);
688   }
689   else
690   {
691     for (t = s->transitions_head; NULL != t; t = t->next)
692     {
693       /* Do not consider self-loops, because it end's up in too many
694        * transitions */
695       if (t->to_state == t->from_state)
696         continue;
697
698       if (NULL != label)
699       {
700         GNUNET_asprintf (&new_label, "%s%s", label, t->label);
701       }
702       else
703         new_label = GNUNET_strdup (t->label);
704
705       add_multi_strides_to_dfa_helper (cls, (depth + 1), new_label, start,
706                                        t->to_state);
707     }
708   }
709   GNUNET_free_non_null (label);
710 }
711
712
713 /**
714  * Function called for each state in the DFA. Starts a traversal of depth set in
715  * context starting from state 's'.
716  *
717  * @param cls context.
718  * @param count not used.
719  * @param s current state.
720  */
721 void
722 add_multi_strides_to_dfa (void *cls, const unsigned int count,
723                           struct GNUNET_REGEX_State *s)
724 {
725   add_multi_strides_to_dfa_helper (cls, 0, NULL, s, s);
726 }
727
728
729 /**
730  * Adds multi-strided transitions to the given 'dfa'.
731  *
732  * @param regex_ctx regex context needed to add transitions to the automaton.
733  * @param dfa DFA to which the multi strided transitions should be added.
734  * @param stride_len length of the strides.
735  */
736 void
737 GNUNET_REGEX_add_multi_strides_to_dfa (struct GNUNET_REGEX_Context *regex_ctx,
738                                        struct GNUNET_REGEX_Automaton *dfa,
739                                        const unsigned int stride_len)
740 {
741   struct GNUNET_REGEX_Strided_Context ctx = { stride_len, NULL, NULL };
742   struct GNUNET_REGEX_Transition *t;
743   struct GNUNET_REGEX_Transition *t_next;
744
745   if (1 > stride_len)
746     return;
747
748   // Compute the new transitions.
749   GNUNET_REGEX_automaton_traverse (dfa, dfa->start, NULL, NULL,
750                                    &add_multi_strides_to_dfa, &ctx);
751
752   // Add all the new transitions to the automaton.
753   for (t = ctx.transitions_head; NULL != t; t = t_next)
754   {
755     t_next = t->next;
756     state_add_transition (regex_ctx, t->from_state, t->label, t->to_state);
757     GNUNET_CONTAINER_DLL_remove (ctx.transitions_head, ctx.transitions_tail, t);
758     GNUNET_free_non_null (t->label);
759     GNUNET_free (t);
760   }
761 }
762
763
764
765 /**
766  * Check if the given string 'str' needs parentheses around it when
767  * using it to generate a regex.
768  *
769  * @param str string
770  *
771  * @return GNUNET_YES if parentheses are needed, GNUNET_NO otherwise
772  */
773 static int
774 needs_parentheses (const char *str)
775 {
776   size_t slen;
777   const char *op;
778   const char *cl;
779   const char *pos;
780   unsigned int cnt;
781
782   if ((NULL == str) || ((slen = strlen (str)) < 2))
783     return GNUNET_NO;
784
785   if ('(' != str[0])
786     return GNUNET_YES;
787   cnt = 1;
788   pos = &str[1];
789   while (cnt > 0)
790   {
791     cl = strchr (pos, ')');
792     if (NULL == cl)
793     {
794       GNUNET_break (0);
795       return GNUNET_YES;
796     }
797     op = strchr (pos, '(');
798     if ((NULL != op) && (op < cl))
799     {
800       cnt++;
801       pos = op + 1;
802       continue;
803     }
804     /* got ')' first */
805     cnt--;
806     pos = cl + 1;
807   }
808   return (*pos == '\0') ? GNUNET_NO : GNUNET_YES;
809 }
810
811
812 /**
813  * Remove parentheses surrounding string 'str'.
814  * Example: "(a)" becomes "a", "(a|b)|(a|c)" stays the same.
815  * You need to GNUNET_free the returned string.
816  *
817  * @param str string, free'd or re-used by this function, can be NULL
818  *
819  * @return string without surrounding parentheses, string 'str' if no preceding
820  *         epsilon could be found, NULL if 'str' was NULL
821  */
822 static char *
823 remove_parentheses (char *str)
824 {
825   size_t slen;
826   const char *pos;
827
828   if ((NULL == str) || ('(' != str[0]) ||
829       (str[(slen = strlen (str)) - 1] != ')'))
830     return str;
831
832   pos = strchr (&str[1], ')');
833   if (pos == &str[slen - 1])
834   {
835     memmove (str, &str[1], slen - 2);
836     str[slen - 2] = '\0';
837   }
838   return str;
839 }
840
841
842 /**
843  * Check if the string 'str' starts with an epsilon (empty string).
844  * Example: "(|a)" is starting with an epsilon.
845  *
846  * @param str string to test
847  *
848  * @return 0 if str has no epsilon, 1 if str starts with '(|' and ends with ')'
849  */
850 static int
851 has_epsilon (const char *str)
852 {
853   return (NULL != str) && ('(' == str[0]) && ('|' == str[1]) &&
854       (')' == str[strlen (str) - 1]);
855 }
856
857
858 /**
859  * Remove an epsilon from the string str. Where epsilon is an empty string
860  * Example: str = "(|a|b|c)", result: "a|b|c"
861  * The returned string needs to be freed.
862  *
863  * @param str string
864  *
865  * @return string without preceding epsilon, string 'str' if no preceding
866  *         epsilon could be found, NULL if 'str' was NULL
867  */
868 static char *
869 remove_epsilon (const char *str)
870 {
871   size_t len;
872
873   if (NULL == str)
874     return NULL;
875   if (('(' == str[0]) && ('|' == str[1]))
876   {
877     len = strlen (str);
878     if (')' == str[len - 1])
879       return GNUNET_strndup (&str[2], len - 3);
880   }
881   return GNUNET_strdup (str);
882 }
883
884
885 /**
886  * Compare 'str1', starting from position 'k',  with whole 'str2'
887  *
888  * @param str1 first string to compare, starting from position 'k'
889  * @param str2 second string for comparison
890  * @param k starting position in 'str1'
891  *
892  * @return -1 if any of the strings is NULL, 0 if equal, non 0 otherwise
893  */
894 static int
895 strkcmp (const char *str1, const char *str2, size_t k)
896 {
897   if ((NULL == str1) || (NULL == str2) || (strlen (str1) < k))
898     return -1;
899   return strcmp (&str1[k], str2);
900 }
901
902
903 /**
904  * Helper function used as 'action' in 'GNUNET_REGEX_automaton_traverse'
905  * function to create the depth-first numbering of the states.
906  *
907  * @param cls states array.
908  * @param count current state counter.
909  * @param s current state.
910  */
911 void
912 number_states (void *cls, const unsigned int count,
913                struct GNUNET_REGEX_State *s)
914 {
915   struct GNUNET_REGEX_State **states = cls;
916
917   s->dfs_id = count;
918   if (NULL != states)
919     states[count] = s;
920 }
921
922
923 /**
924  * Construct the regular expression given the inductive step,
925  * $R^{(k)}_{ij} = R^{(k-1)}_{ij} | R^{(k-1)}_{ik} ( R^{(k-1)}_{kk} )^*
926  * R^{(k-1)}_{kj}, and simplify the resulting expression saved in R_cur_ij.
927  *
928  * @param R_last_ij value of  $R^{(k-1)_{ij}.
929  * @param R_last_ik value of  $R^{(k-1)_{ik}.
930  * @param R_last_kk value of  $R^{(k-1)_{kk}.
931  * @param R_last_kj value of  $R^{(k-1)_{kj}.
932  * @param R_cur_ij result for this inductive step is saved in R_cur_ij, R_cur_ij
933  *                 is expected to be NULL when called!
934  */
935 static void
936 automaton_create_proofs_simplify (char *R_last_ij, char *R_last_ik,
937                                   char *R_last_kk, char *R_last_kj,
938                                   char **R_cur_ij)
939 {
940   char *R_cur_l;
941   char *R_cur_r;
942   char *temp_a;
943   char *temp_b;
944   char *R_temp_ij;
945   char *R_temp_ik;
946   char *R_temp_kj;
947   char *R_temp_kk;
948
949   int eps_check;
950   int ij_ik_cmp;
951   int ij_kj_cmp;
952
953   int ik_kk_cmp;
954   int kk_kj_cmp;
955   int clean_ik_kk_cmp;
956   int clean_kk_kj_cmp;
957   unsigned int cnt;
958
959   size_t length;
960   size_t length_l;
961   size_t length_r;
962
963   GNUNET_assert (NULL == *R_cur_ij && NULL != R_cur_ij);
964
965   // $R^{(k)}_{ij} = R^{(k-1)}_{ij} | R^{(k-1)}_{ik} ( R^{(k-1)}_{kk} )^* R^{(k-1)}_{kj}
966   // R_last == R^{(k-1)}, R_cur == R^{(k)}
967   // R_cur_ij = R_cur_l | R_cur_r
968   // R_cur_l == R^{(k-1)}_{ij}
969   // R_cur_r == R^{(k-1)}_{ik} ( R^{(k-1)}_{kk} )^* R^{(k-1)}_{kj}
970
971   if ((NULL == R_last_ij) && ((NULL == R_last_ik) || (NULL == R_last_kk) ||     /* technically cannot happen, but looks saner */
972                               (NULL == R_last_kj)))
973   {
974     /* R^{(k)}_{ij} = N | N */
975     *R_cur_ij = NULL;
976     return;
977   }
978
979   if ((NULL == R_last_ik) || (NULL == R_last_kk) ||     /* technically cannot happen, but looks saner */
980       (NULL == R_last_kj))
981   {
982     /*  R^{(k)}_{ij} = R^{(k-1)}_{ij} | N */
983     *R_cur_ij = GNUNET_strdup (R_last_ij);
984     return;
985   }
986
987   // $R^{(k)}_{ij} = N | R^{(k-1)}_{ik} ( R^{(k-1)}_{kk} )^* R^{(k-1)}_{kj} OR
988   // $R^{(k)}_{ij} = R^{(k-1)}_{ij} | R^{(k-1)}_{ik} ( R^{(k-1)}_{kk} )^* R^{(k-1)}_{kj}
989
990   R_cur_r = NULL;
991   R_cur_l = NULL;
992
993   // cache results from strcmp, we might need these many times
994   ij_kj_cmp = nullstrcmp (R_last_ij, R_last_kj);
995   ij_ik_cmp = nullstrcmp (R_last_ij, R_last_ik);
996   ik_kk_cmp = nullstrcmp (R_last_ik, R_last_kk);
997   kk_kj_cmp = nullstrcmp (R_last_kk, R_last_kj);
998
999   // Assign R_temp_(ik|kk|kj) to R_last[][] and remove epsilon as well
1000   // as parentheses, so we can better compare the contents
1001   R_temp_ik = remove_parentheses (remove_epsilon (R_last_ik));
1002   R_temp_kk = remove_parentheses (remove_epsilon (R_last_kk));
1003   R_temp_kj = remove_parentheses (remove_epsilon (R_last_kj));
1004
1005   clean_ik_kk_cmp = nullstrcmp (R_last_ik, R_temp_kk);
1006   clean_kk_kj_cmp = nullstrcmp (R_temp_kk, R_last_kj);
1007
1008   // construct R_cur_l (and, if necessary R_cur_r)
1009   if (NULL != R_last_ij)
1010   {
1011     // Assign R_temp_ij to R_last_ij and remove epsilon as well
1012     // as parentheses, so we can better compare the contents
1013     R_temp_ij = remove_parentheses (remove_epsilon (R_last_ij));
1014
1015     if (0 == strcmp (R_temp_ij, R_temp_ik) && 0 == strcmp (R_temp_ik, R_temp_kk)
1016         && 0 == strcmp (R_temp_kk, R_temp_kj))
1017     {
1018       if (0 == strlen (R_temp_ij))
1019       {
1020         R_cur_r = GNUNET_strdup ("");
1021       }
1022       else if ((0 == strncmp (R_last_ij, "(|", 2)) ||
1023                (0 == strncmp (R_last_ik, "(|", 2) &&
1024                 0 == strncmp (R_last_kj, "(|", 2)))
1025       {
1026         // a|(e|a)a*(e|a) = a*
1027         // a|(e|a)(e|a)*(e|a) = a*
1028         // (e|a)|aa*a = a*
1029         // (e|a)|aa*(e|a) = a*
1030         // (e|a)|(e|a)a*a = a*
1031         // (e|a)|(e|a)a*(e|a) = a*
1032         // (e|a)|(e|a)(e|a)*(e|a) = a*
1033         if (GNUNET_YES == needs_parentheses (R_temp_ij))
1034           GNUNET_asprintf (&R_cur_r, "(%s)*", R_temp_ij);
1035         else
1036           GNUNET_asprintf (&R_cur_r, "%s*", R_temp_ij);
1037       }
1038       else
1039       {
1040         // a|aa*a = a+
1041         // a|(e|a)a*a = a+
1042         // a|aa*(e|a) = a+
1043         // a|(e|a)(e|a)*a = a+
1044         // a|a(e|a)*(e|a) = a+
1045         if (GNUNET_YES == needs_parentheses (R_temp_ij))
1046           GNUNET_asprintf (&R_cur_r, "(%s)+", R_temp_ij);
1047         else
1048           GNUNET_asprintf (&R_cur_r, "%s+", R_temp_ij);
1049       }
1050     }
1051     else if (0 == ij_ik_cmp && 0 == clean_kk_kj_cmp && 0 != clean_ik_kk_cmp)
1052     {
1053       // a|ab*b = ab*
1054       if (strlen (R_last_kk) < 1)
1055         R_cur_r = GNUNET_strdup (R_last_ij);
1056       else if (GNUNET_YES == needs_parentheses (R_temp_kk))
1057         GNUNET_asprintf (&R_cur_r, "%s(%s)*", R_last_ij, R_temp_kk);
1058       else
1059         GNUNET_asprintf (&R_cur_r, "%s%s*", R_last_ij, R_last_kk);
1060
1061       R_cur_l = NULL;
1062     }
1063     else if (0 == ij_kj_cmp && 0 == clean_ik_kk_cmp && 0 != clean_kk_kj_cmp)
1064     {
1065       // a|bb*a = b*a
1066       if (strlen (R_last_kk) < 1)
1067         R_cur_r = GNUNET_strdup (R_last_kj);
1068       else if (GNUNET_YES == needs_parentheses (R_temp_kk))
1069         GNUNET_asprintf (&R_cur_r, "(%s)*%s", R_temp_kk, R_last_kj);
1070       else
1071         GNUNET_asprintf (&R_cur_r, "%s*%s", R_temp_kk, R_last_kj);
1072
1073       R_cur_l = NULL;
1074     }
1075     else if (0 == ij_ik_cmp && 0 == kk_kj_cmp && !has_epsilon (R_last_ij) &&
1076              has_epsilon (R_last_kk))
1077     {
1078       // a|a(e|b)*(e|b) = a|ab* = a|a|ab|abb|abbb|... = ab*
1079       if (needs_parentheses (R_temp_kk))
1080         GNUNET_asprintf (&R_cur_r, "%s(%s)*", R_last_ij, R_temp_kk);
1081       else
1082         GNUNET_asprintf (&R_cur_r, "%s%s*", R_last_ij, R_temp_kk);
1083
1084       R_cur_l = NULL;
1085     }
1086     else if (0 == ij_kj_cmp && 0 == ik_kk_cmp && !has_epsilon (R_last_ij) &&
1087              has_epsilon (R_last_kk))
1088     {
1089       // a|(e|b)(e|b)*a = a|b*a = a|a|ba|bba|bbba|...  = b*a
1090       if (needs_parentheses (R_temp_kk))
1091         GNUNET_asprintf (&R_cur_r, "(%s)*%s", R_temp_kk, R_last_ij);
1092       else
1093         GNUNET_asprintf (&R_cur_r, "%s*%s", R_temp_kk, R_last_ij);
1094
1095       R_cur_l = NULL;
1096     }
1097     else
1098     {
1099       temp_a = (NULL == R_last_ij) ? NULL : GNUNET_strdup (R_last_ij);
1100       temp_a = remove_parentheses (temp_a);
1101       R_cur_l = temp_a;
1102     }
1103
1104     GNUNET_free_non_null (R_temp_ij);
1105   }
1106   else
1107   {
1108     // we have no left side
1109     R_cur_l = NULL;
1110   }
1111
1112   // construct R_cur_r, if not already constructed
1113   if (NULL == R_cur_r)
1114   {
1115     length = strlen (R_temp_kk) - strlen (R_last_ik);
1116
1117     // a(ba)*bx = (ab)+x
1118     if (length > 0 && NULL != R_last_kk && 0 < strlen (R_last_kk) &&
1119         NULL != R_last_kj && 0 < strlen (R_last_kj) && NULL != R_last_ik &&
1120         0 < strlen (R_last_ik) && 0 == strkcmp (R_temp_kk, R_last_ik, length) &&
1121         0 == strncmp (R_temp_kk, R_last_kj, length))
1122     {
1123       temp_a = GNUNET_malloc (length + 1);
1124       temp_b = GNUNET_malloc ((strlen (R_last_kj) - length) + 1);
1125
1126       length_l = 0;
1127       length_r = 0;
1128
1129       for (cnt = 0; cnt < strlen (R_last_kj); cnt++)
1130       {
1131         if (cnt < length)
1132         {
1133           temp_a[length_l] = R_last_kj[cnt];
1134           length_l++;
1135         }
1136         else
1137         {
1138           temp_b[length_r] = R_last_kj[cnt];
1139           length_r++;
1140         }
1141       }
1142       temp_a[length_l] = '\0';
1143       temp_b[length_r] = '\0';
1144
1145       // e|(ab)+ = (ab)*
1146       if (NULL != R_cur_l && 0 == strlen (R_cur_l) && 0 == strlen (temp_b))
1147       {
1148         GNUNET_asprintf (&R_cur_r, "(%s%s)*", R_last_ik, temp_a);
1149         GNUNET_free (R_cur_l);
1150         R_cur_l = NULL;
1151       }
1152       else
1153       {
1154         GNUNET_asprintf (&R_cur_r, "(%s%s)+%s", R_last_ik, temp_a, temp_b);
1155       }
1156       GNUNET_free (temp_a);
1157       GNUNET_free (temp_b);
1158     }
1159     else if (0 == strcmp (R_temp_ik, R_temp_kk) &&
1160              0 == strcmp (R_temp_kk, R_temp_kj))
1161     {
1162       // (e|a)a*(e|a) = a*
1163       // (e|a)(e|a)*(e|a) = a*
1164       if (has_epsilon (R_last_ik) && has_epsilon (R_last_kj))
1165       {
1166         if (needs_parentheses (R_temp_kk))
1167           GNUNET_asprintf (&R_cur_r, "(%s)*", R_temp_kk);
1168         else
1169           GNUNET_asprintf (&R_cur_r, "%s*", R_temp_kk);
1170       }
1171       // aa*a = a+a
1172       else if (0 == clean_ik_kk_cmp && 0 == clean_kk_kj_cmp &&
1173                !has_epsilon (R_last_ik))
1174       {
1175         if (needs_parentheses (R_temp_kk))
1176           GNUNET_asprintf (&R_cur_r, "(%s)+%s", R_temp_kk, R_temp_kk);
1177         else
1178           GNUNET_asprintf (&R_cur_r, "(%s)+%s", R_temp_kk, R_temp_kk);
1179       }
1180       // (e|a)a*a = a+
1181       // aa*(e|a) = a+
1182       // a(e|a)*(e|a) = a+
1183       // (e|a)a*a = a+
1184       else
1185       {
1186         eps_check =
1187             (has_epsilon (R_last_ik) + has_epsilon (R_last_kk) +
1188              has_epsilon (R_last_kj));
1189
1190         if (eps_check == 1)
1191         {
1192           if (needs_parentheses (R_temp_kk))
1193             GNUNET_asprintf (&R_cur_r, "(%s)+", R_temp_kk);
1194           else
1195             GNUNET_asprintf (&R_cur_r, "%s+", R_temp_kk);
1196         }
1197       }
1198     }
1199     // aa*b = a+b
1200     // (e|a)(e|a)*b = a*b
1201     else if (0 == strcmp (R_temp_ik, R_temp_kk))
1202     {
1203       if (has_epsilon (R_last_ik))
1204       {
1205         if (needs_parentheses (R_temp_kk))
1206           GNUNET_asprintf (&R_cur_r, "(%s)*%s", R_temp_kk, R_last_kj);
1207         else
1208           GNUNET_asprintf (&R_cur_r, "%s*%s", R_temp_kk, R_last_kj);
1209       }
1210       else
1211       {
1212         if (needs_parentheses (R_temp_kk))
1213           GNUNET_asprintf (&R_cur_r, "(%s)+%s", R_temp_kk, R_last_kj);
1214         else
1215           GNUNET_asprintf (&R_cur_r, "%s+%s", R_temp_kk, R_last_kj);
1216       }
1217     }
1218     // ba*a = ba+
1219     // b(e|a)*(e|a) = ba*
1220     else if (0 == strcmp (R_temp_kk, R_temp_kj))
1221     {
1222       if (has_epsilon (R_last_kj))
1223       {
1224         if (needs_parentheses (R_temp_kk))
1225           GNUNET_asprintf (&R_cur_r, "%s(%s)*", R_last_ik, R_temp_kk);
1226         else
1227           GNUNET_asprintf (&R_cur_r, "%s%s*", R_last_ik, R_temp_kk);
1228       }
1229       else
1230       {
1231         if (needs_parentheses (R_temp_kk))
1232           GNUNET_asprintf (&R_cur_r, "(%s)+%s", R_last_ik, R_temp_kk);
1233         else
1234           GNUNET_asprintf (&R_cur_r, "%s+%s", R_last_ik, R_temp_kk);
1235       }
1236     }
1237     else
1238     {
1239       if (strlen (R_temp_kk) > 0)
1240       {
1241         if (needs_parentheses (R_temp_kk))
1242         {
1243           GNUNET_asprintf (&R_cur_r, "%s(%s)*%s", R_last_ik, R_temp_kk,
1244                            R_last_kj);
1245         }
1246         else
1247         {
1248           GNUNET_asprintf (&R_cur_r, "%s%s*%s", R_last_ik, R_temp_kk,
1249                            R_last_kj);
1250         }
1251       }
1252       else
1253       {
1254         GNUNET_asprintf (&R_cur_r, "%s%s", R_last_ik, R_last_kj);
1255       }
1256     }
1257   }
1258
1259   GNUNET_free_non_null (R_temp_ik);
1260   GNUNET_free_non_null (R_temp_kk);
1261   GNUNET_free_non_null (R_temp_kj);
1262
1263   if (NULL == R_cur_l && NULL == R_cur_r)
1264   {
1265     *R_cur_ij = NULL;
1266     return;
1267   }
1268
1269   if (NULL != R_cur_l && NULL == R_cur_r)
1270   {
1271     *R_cur_ij = R_cur_l;
1272     return;
1273   }
1274
1275   if (NULL == R_cur_l && NULL != R_cur_r)
1276   {
1277     *R_cur_ij = R_cur_r;
1278     return;
1279   }
1280
1281   if (0 == nullstrcmp (R_cur_l, R_cur_r))
1282   {
1283     *R_cur_ij = R_cur_l;
1284     GNUNET_free (R_cur_r);
1285     return;
1286   }
1287
1288   GNUNET_asprintf (R_cur_ij, "(%s|%s)", R_cur_l, R_cur_r);
1289
1290   GNUNET_free (R_cur_l);
1291   GNUNET_free (R_cur_r);
1292 }
1293
1294
1295 /**
1296  * create proofs for all states in the given automaton. Implementation of the
1297  * algorithm descriped in chapter 3.2.1 of "Automata Theory, Languages, and
1298  * Computation 3rd Edition" by Hopcroft, Motwani and Ullman.
1299  *
1300  * @param a automaton.
1301  */
1302 static void
1303 automaton_create_proofs (struct GNUNET_REGEX_Automaton *a)
1304 {
1305   unsigned int n = a->state_count;
1306   struct GNUNET_REGEX_State *states[n];
1307   char *R_last[n][n];
1308   char *R_cur[n][n];
1309   char *temp;
1310   struct GNUNET_REGEX_Transition *t;
1311   char *complete_regex;
1312   unsigned int i;
1313   unsigned int j;
1314   unsigned int k;
1315
1316   if (NULL == a)
1317   {
1318     GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
1319                 "Could not create proofs, automaton was NULL\n");
1320     return;
1321   }
1322
1323   /* create depth-first numbering of the states, initializes 'state' */
1324   GNUNET_REGEX_automaton_traverse (a, a->start, NULL, NULL, &number_states,
1325                                    states);
1326
1327   for (i = 0; i < n; i++)
1328     GNUNET_assert (NULL != states[i]);
1329
1330   /* Compute regular expressions of length "1" between each pair of states */
1331   for (i = 0; i < n; i++)
1332   {
1333     for (j = 0; j < n; j++)
1334     {
1335       R_cur[i][j] = NULL;
1336       R_last[i][j] = NULL;
1337     }
1338     for (t = states[i]->transitions_head; NULL != t; t = t->next)
1339     {
1340       j = t->to_state->dfs_id;
1341       if (NULL == R_last[i][j])
1342         GNUNET_asprintf (&R_last[i][j], "%s", t->label);
1343       else
1344       {
1345         temp = R_last[i][j];
1346         GNUNET_asprintf (&R_last[i][j], "%s|%s", R_last[i][j], t->label);
1347         GNUNET_free (temp);
1348       }
1349     }
1350     if (NULL == R_last[i][i])
1351       GNUNET_asprintf (&R_last[i][i], "");
1352     else
1353     {
1354       temp = R_last[i][i];
1355       GNUNET_asprintf (&R_last[i][i], "(|%s)", R_last[i][i]);
1356       GNUNET_free (temp);
1357     }
1358   }
1359   for (i = 0; i < n; i++)
1360     for (j = 0; j < n; j++)
1361       if (needs_parentheses (R_last[i][j]))
1362       {
1363         temp = R_last[i][j];
1364         GNUNET_asprintf (&R_last[i][j], "(%s)", R_last[i][j]);
1365         GNUNET_free (temp);
1366       }
1367
1368   /* Compute regular expressions of length "k" between each pair of states per
1369    * induction */
1370   for (k = 0; k < n; k++)
1371   {
1372     for (i = 0; i < n; i++)
1373     {
1374       for (j = 0; j < n; j++)
1375       {
1376         // Basis for the recursion:
1377         // $R^{(k)}_{ij} = R^{(k-1)}_{ij} | R^{(k-1)}_{ik} ( R^{(k-1)}_{kk} )^* R^{(k-1)}_{kj}
1378         // R_last == R^{(k-1)}, R_cur == R^{(k)}
1379
1380         // Create R_cur[i][j] and simplify the expression
1381         automaton_create_proofs_simplify (R_last[i][j], R_last[i][k],
1382                                           R_last[k][k], R_last[k][j],
1383                                           &R_cur[i][j]);
1384       }
1385     }
1386
1387     // set R_last = R_cur
1388     for (i = 0; i < n; i++)
1389     {
1390       for (j = 0; j < n; j++)
1391       {
1392         GNUNET_free_non_null (R_last[i][j]);
1393         R_last[i][j] = R_cur[i][j];
1394         R_cur[i][j] = NULL;
1395       }
1396     }
1397   }
1398
1399   // assign proofs and hashes
1400   for (i = 0; i < n; i++)
1401   {
1402     if (NULL != R_last[a->start->dfs_id][i])
1403     {
1404       states[i]->proof = GNUNET_strdup (R_last[a->start->dfs_id][i]);
1405       GNUNET_CRYPTO_hash (states[i]->proof, strlen (states[i]->proof),
1406                           &states[i]->hash);
1407     }
1408   }
1409
1410   // complete regex for whole DFA: union of all pairs (start state/accepting
1411   // state(s)).
1412   complete_regex = NULL;
1413   for (i = 0; i < n; i++)
1414   {
1415     if (states[i]->accepting)
1416     {
1417       if (NULL == complete_regex && 0 < strlen (R_last[a->start->dfs_id][i]))
1418       {
1419         GNUNET_asprintf (&complete_regex, "%s", R_last[a->start->dfs_id][i]);
1420       }
1421       else if (NULL != R_last[a->start->dfs_id][i] &&
1422                0 < strlen (R_last[a->start->dfs_id][i]))
1423       {
1424         temp = complete_regex;
1425         GNUNET_asprintf (&complete_regex, "%s|%s", complete_regex,
1426                          R_last[a->start->dfs_id][i]);
1427         GNUNET_free (temp);
1428       }
1429     }
1430   }
1431   a->canonical_regex = complete_regex;
1432
1433   // cleanup
1434   for (i = 0; i < n; i++)
1435   {
1436     for (j = 0; j < n; j++)
1437       GNUNET_free_non_null (R_last[i][j]);
1438   }
1439 }
1440
1441
1442 /**
1443  * Creates a new DFA state based on a set of NFA states. Needs to be freed using
1444  * automaton_destroy_state.
1445  *
1446  * @param ctx context
1447  * @param nfa_states set of NFA states on which the DFA should be based on
1448  *
1449  * @return new DFA state
1450  */
1451 static struct GNUNET_REGEX_State *
1452 dfa_state_create (struct GNUNET_REGEX_Context *ctx,
1453                   struct GNUNET_REGEX_StateSet *nfa_states)
1454 {
1455   struct GNUNET_REGEX_State *s;
1456   char *name;
1457   int len = 0;
1458   struct GNUNET_REGEX_State *cstate;
1459   struct GNUNET_REGEX_Transition *ctran;
1460   unsigned int i;
1461
1462   s = GNUNET_malloc (sizeof (struct GNUNET_REGEX_State));
1463   s->id = ctx->state_id++;
1464   s->accepting = 0;
1465   s->marked = GNUNET_NO;
1466   s->name = NULL;
1467   s->scc_id = 0;
1468   s->index = -1;
1469   s->lowlink = -1;
1470   s->contained = 0;
1471   s->proof = NULL;
1472
1473   if (NULL == nfa_states)
1474   {
1475     GNUNET_asprintf (&s->name, "s%i", s->id);
1476     return s;
1477   }
1478
1479   s->nfa_set = nfa_states;
1480
1481   if (nfa_states->len < 1)
1482     return s;
1483
1484   // Create a name based on 'sset'
1485   s->name = GNUNET_malloc (sizeof (char) * 2);
1486   strcat (s->name, "{");
1487   name = NULL;
1488
1489   for (i = 0; i < nfa_states->len; i++)
1490   {
1491     cstate = nfa_states->states[i];
1492     GNUNET_asprintf (&name, "%i,", cstate->id);
1493
1494     if (NULL != name)
1495     {
1496       len = strlen (s->name) + strlen (name) + 1;
1497       s->name = GNUNET_realloc (s->name, len);
1498       strcat (s->name, name);
1499       GNUNET_free (name);
1500       name = NULL;
1501     }
1502
1503     // Add a transition for each distinct label to NULL state
1504     for (ctran = cstate->transitions_head; NULL != ctran; ctran = ctran->next)
1505     {
1506       if (NULL != ctran->label)
1507         state_add_transition (ctx, s, ctran->label, NULL);
1508     }
1509
1510     // If the nfa_states contain an accepting state, the new dfa state is also
1511     // accepting
1512     if (cstate->accepting)
1513       s->accepting = 1;
1514   }
1515
1516   s->name[strlen (s->name) - 1] = '}';
1517
1518   return s;
1519 }
1520
1521
1522 /**
1523  * Move from the given state 's' to the next state on transition 'label'
1524  *
1525  * @param s starting state
1526  * @param label edge label to follow
1527  *
1528  * @return new state or NULL, if transition on label not possible
1529  */
1530 static struct GNUNET_REGEX_State *
1531 dfa_move (struct GNUNET_REGEX_State *s, const char *label)
1532 {
1533   struct GNUNET_REGEX_Transition *t;
1534   struct GNUNET_REGEX_State *new_s;
1535
1536   if (NULL == s)
1537     return NULL;
1538
1539   new_s = NULL;
1540
1541   for (t = s->transitions_head; NULL != t; t = t->next)
1542   {
1543     // TODO: Use strstr to match substring and return number of char's that have
1544     // been consumed'
1545     if (0 == strcmp (label, t->label))
1546     {
1547       new_s = t->to_state;
1548       break;
1549     }
1550   }
1551
1552   return new_s;
1553 }
1554
1555 /**
1556  * Set the given state 'marked' to GNUNET_YES. Used by the
1557  * 'dfa_remove_unreachable_states' function to detect unreachable states in the
1558  * automaton.
1559  *
1560  * @param cls closure, not used.
1561  * @param count count, not used.
1562  * @param s state where the marked attribute will be set to GNUNET_YES.
1563  */
1564 void
1565 mark_states (void *cls, const unsigned int count, struct GNUNET_REGEX_State *s)
1566 {
1567   s->marked = GNUNET_YES;
1568 }
1569
1570 /**
1571  * Remove all unreachable states from DFA 'a'. Unreachable states are those
1572  * states that are not reachable from the starting state.
1573  *
1574  * @param a DFA automaton
1575  */
1576 static void
1577 dfa_remove_unreachable_states (struct GNUNET_REGEX_Automaton *a)
1578 {
1579   struct GNUNET_REGEX_State *s;
1580   struct GNUNET_REGEX_State *s_next;
1581
1582   // 1. unmark all states
1583   for (s = a->states_head; NULL != s; s = s->next)
1584     s->marked = GNUNET_NO;
1585
1586   // 2. traverse dfa from start state and mark all visited states
1587   GNUNET_REGEX_automaton_traverse (a, a->start, NULL, NULL, &mark_states, NULL);
1588
1589   // 3. delete all states that were not visited
1590   for (s = a->states_head; NULL != s; s = s_next)
1591   {
1592     s_next = s->next;
1593     if (GNUNET_NO == s->marked)
1594       automaton_remove_state (a, s);
1595   }
1596 }
1597
1598
1599 /**
1600  * Remove all dead states from the DFA 'a'. Dead states are those states that do
1601  * not transition to any other state but themselves.
1602  *
1603  * @param a DFA automaton
1604  */
1605 static void
1606 dfa_remove_dead_states (struct GNUNET_REGEX_Automaton *a)
1607 {
1608   struct GNUNET_REGEX_State *s;
1609   struct GNUNET_REGEX_Transition *t;
1610   int dead;
1611
1612   GNUNET_assert (DFA == a->type);
1613
1614   for (s = a->states_head; NULL != s; s = s->next)
1615   {
1616     if (s->accepting)
1617       continue;
1618
1619     dead = 1;
1620     for (t = s->transitions_head; NULL != t; t = t->next)
1621     {
1622       if (NULL != t->to_state && t->to_state != s)
1623       {
1624         dead = 0;
1625         break;
1626       }
1627     }
1628
1629     if (0 == dead)
1630       continue;
1631
1632     // state s is dead, remove it
1633     automaton_remove_state (a, s);
1634   }
1635 }
1636
1637
1638 /**
1639  * Merge all non distinguishable states in the DFA 'a'
1640  *
1641  * @param ctx context
1642  * @param a DFA automaton
1643  */
1644 static void
1645 dfa_merge_nondistinguishable_states (struct GNUNET_REGEX_Context *ctx,
1646                                      struct GNUNET_REGEX_Automaton *a)
1647 {
1648   int table[a->state_count][a->state_count];
1649   struct GNUNET_REGEX_State *s1;
1650   struct GNUNET_REGEX_State *s2;
1651   struct GNUNET_REGEX_Transition *t1;
1652   struct GNUNET_REGEX_Transition *t2;
1653   struct GNUNET_REGEX_State *s1_next;
1654   struct GNUNET_REGEX_State *s2_next;
1655   int change;
1656   unsigned int num_equal_edges;
1657   unsigned int i;
1658
1659   for (i = 0, s1 = a->states_head; i < a->state_count && NULL != s1;
1660        i++, s1 = s1->next)
1661   {
1662     s1->marked = i;
1663   }
1664
1665   // Mark all pairs of accepting/!accepting states
1666   for (s1 = a->states_head; NULL != s1; s1 = s1->next)
1667   {
1668     for (s2 = a->states_head; NULL != s2; s2 = s2->next)
1669     {
1670       table[s1->marked][s2->marked] = 0;
1671
1672       if ((s1->accepting && !s2->accepting) ||
1673           (!s1->accepting && s2->accepting))
1674       {
1675         table[s1->marked][s2->marked] = 1;
1676       }
1677     }
1678   }
1679
1680   // Find all equal states
1681   change = 1;
1682   while (0 != change)
1683   {
1684     change = 0;
1685     for (s1 = a->states_head; NULL != s1; s1 = s1->next)
1686     {
1687       for (s2 = a->states_head; NULL != s2 && s1 != s2; s2 = s2->next)
1688       {
1689         if (0 != table[s1->marked][s2->marked])
1690           continue;
1691
1692         num_equal_edges = 0;
1693         for (t1 = s1->transitions_head; NULL != t1; t1 = t1->next)
1694         {
1695           for (t2 = s2->transitions_head; NULL != t2; t2 = t2->next)
1696           {
1697             if (0 == strcmp (t1->label, t2->label))
1698             {
1699               num_equal_edges++;
1700               if (0 != table[t1->to_state->marked][t2->to_state->marked] ||
1701                   0 != table[t2->to_state->marked][t1->to_state->marked])
1702               {
1703                 table[s1->marked][s2->marked] = 1;
1704                 change = 1;
1705               }
1706             }
1707           }
1708         }
1709         if (num_equal_edges != s1->transition_count ||
1710             num_equal_edges != s2->transition_count)
1711         {
1712           // Make sure ALL edges of possible equal states are the same
1713           table[s1->marked][s2->marked] = -2;
1714         }
1715       }
1716     }
1717   }
1718
1719   // Merge states that are equal
1720   for (s1 = a->states_head; NULL != s1; s1 = s1_next)
1721   {
1722     s1_next = s1->next;
1723     for (s2 = a->states_head; NULL != s2 && s1 != s2; s2 = s2_next)
1724     {
1725       s2_next = s2->next;
1726       if (table[s1->marked][s2->marked] == 0)
1727         automaton_merge_states (ctx, a, s1, s2);
1728     }
1729   }
1730 }
1731
1732
1733 /**
1734  * Minimize the given DFA 'a' by removing all unreachable states, removing all
1735  * dead states and merging all non distinguishable states
1736  *
1737  * @param ctx context
1738  * @param a DFA automaton
1739  */
1740 static void
1741 dfa_minimize (struct GNUNET_REGEX_Context *ctx,
1742               struct GNUNET_REGEX_Automaton *a)
1743 {
1744   if (NULL == a)
1745     return;
1746
1747   GNUNET_assert (DFA == a->type);
1748
1749   // 1. remove unreachable states
1750   dfa_remove_unreachable_states (a);
1751
1752   // 2. remove dead states
1753   dfa_remove_dead_states (a);
1754
1755   // 3. Merge nondistinguishable states
1756   dfa_merge_nondistinguishable_states (ctx, a);
1757 }
1758
1759
1760 /**
1761  * Creates a new NFA fragment. Needs to be cleared using
1762  * automaton_fragment_clear.
1763  *
1764  * @param start starting state
1765  * @param end end state
1766  *
1767  * @return new NFA fragment
1768  */
1769 static struct GNUNET_REGEX_Automaton *
1770 nfa_fragment_create (struct GNUNET_REGEX_State *start,
1771                      struct GNUNET_REGEX_State *end)
1772 {
1773   struct GNUNET_REGEX_Automaton *n;
1774
1775   n = GNUNET_malloc (sizeof (struct GNUNET_REGEX_Automaton));
1776
1777   n->type = NFA;
1778   n->start = NULL;
1779   n->end = NULL;
1780   n->state_count = 0;
1781
1782   if (NULL == start || NULL == end)
1783     return n;
1784
1785   automaton_add_state (n, end);
1786   automaton_add_state (n, start);
1787
1788   n->state_count = 2;
1789
1790   n->start = start;
1791   n->end = end;
1792
1793   return n;
1794 }
1795
1796
1797 /**
1798  * Adds a list of states to the given automaton 'n'.
1799  *
1800  * @param n automaton to which the states should be added
1801  * @param states_head head of the DLL of states
1802  * @param states_tail tail of the DLL of states
1803  */
1804 static void
1805 nfa_add_states (struct GNUNET_REGEX_Automaton *n,
1806                 struct GNUNET_REGEX_State *states_head,
1807                 struct GNUNET_REGEX_State *states_tail)
1808 {
1809   struct GNUNET_REGEX_State *s;
1810
1811   if (NULL == n || NULL == states_head)
1812   {
1813     GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "Could not add states\n");
1814     return;
1815   }
1816
1817   if (NULL == n->states_head)
1818   {
1819     n->states_head = states_head;
1820     n->states_tail = states_tail;
1821     return;
1822   }
1823
1824   if (NULL != states_head)
1825   {
1826     n->states_tail->next = states_head;
1827     n->states_tail = states_tail;
1828   }
1829
1830   for (s = states_head; NULL != s; s = s->next)
1831     n->state_count++;
1832 }
1833
1834
1835 /**
1836  * Creates a new NFA state. Needs to be freed using automaton_destroy_state.
1837  *
1838  * @param ctx context
1839  * @param accepting is it an accepting state or not
1840  *
1841  * @return new NFA state
1842  */
1843 static struct GNUNET_REGEX_State *
1844 nfa_state_create (struct GNUNET_REGEX_Context *ctx, int accepting)
1845 {
1846   struct GNUNET_REGEX_State *s;
1847
1848   s = GNUNET_malloc (sizeof (struct GNUNET_REGEX_State));
1849   s->id = ctx->state_id++;
1850   s->accepting = accepting;
1851   s->marked = GNUNET_NO;
1852   s->contained = 0;
1853   s->index = -1;
1854   s->lowlink = -1;
1855   s->scc_id = 0;
1856   s->name = NULL;
1857   GNUNET_asprintf (&s->name, "s%i", s->id);
1858
1859   return s;
1860 }
1861
1862
1863 /**
1864  * Calculates the NFA closure set for the given state.
1865  *
1866  * @param nfa the NFA containing 's'
1867  * @param s starting point state
1868  * @param label transitioning label on which to base the closure on,
1869  *                pass NULL for epsilon transition
1870  *
1871  * @return sorted nfa closure on 'label' (epsilon closure if 'label' is NULL)
1872  */
1873 static struct GNUNET_REGEX_StateSet *
1874 nfa_closure_create (struct GNUNET_REGEX_Automaton *nfa,
1875                     struct GNUNET_REGEX_State *s, const char *label)
1876 {
1877   struct GNUNET_REGEX_StateSet *cls;
1878   struct GNUNET_REGEX_StateSet *cls_check;
1879   struct GNUNET_REGEX_State *clsstate;
1880   struct GNUNET_REGEX_State *currentstate;
1881   struct GNUNET_REGEX_Transition *ctran;
1882
1883   if (NULL == s)
1884     return NULL;
1885
1886   cls = GNUNET_malloc (sizeof (struct GNUNET_REGEX_StateSet));
1887   cls_check = GNUNET_malloc (sizeof (struct GNUNET_REGEX_StateSet));
1888
1889   for (clsstate = nfa->states_head; NULL != clsstate; clsstate = clsstate->next)
1890     clsstate->contained = 0;
1891
1892   // Add start state to closure only for epsilon closure
1893   if (NULL == label)
1894     GNUNET_array_append (cls->states, cls->len, s);
1895
1896   GNUNET_array_append (cls_check->states, cls_check->len, s);
1897   while (cls_check->len > 0)
1898   {
1899     currentstate = cls_check->states[cls_check->len - 1];
1900     GNUNET_array_grow (cls_check->states, cls_check->len, cls_check->len - 1);
1901
1902     for (ctran = currentstate->transitions_head; NULL != ctran;
1903          ctran = ctran->next)
1904     {
1905       if (NULL != ctran->to_state && 0 == nullstrcmp (label, ctran->label))
1906       {
1907         clsstate = ctran->to_state;
1908
1909         if (NULL != clsstate && 0 == clsstate->contained)
1910         {
1911           GNUNET_array_append (cls->states, cls->len, clsstate);
1912           GNUNET_array_append (cls_check->states, cls_check->len, clsstate);
1913           clsstate->contained = 1;
1914         }
1915       }
1916     }
1917   }
1918   GNUNET_assert (0 == cls_check->len);
1919   GNUNET_free (cls_check);
1920
1921   // sort the states
1922   if (cls->len > 1)
1923     qsort (cls->states, cls->len, sizeof (struct GNUNET_REGEX_State *),
1924            state_compare);
1925
1926   return cls;
1927 }
1928
1929
1930 /**
1931  * Calculates the closure set for the given set of states.
1932  *
1933  * @param nfa the NFA containing 's'
1934  * @param states list of states on which to base the closure on
1935  * @param label transitioning label for which to base the closure on,
1936  *                pass NULL for epsilon transition
1937  *
1938  * @return sorted nfa closure on 'label' (epsilon closure if 'label' is NULL)
1939  */
1940 static struct GNUNET_REGEX_StateSet *
1941 nfa_closure_set_create (struct GNUNET_REGEX_Automaton *nfa,
1942                         struct GNUNET_REGEX_StateSet *states, const char *label)
1943 {
1944   struct GNUNET_REGEX_State *s;
1945   struct GNUNET_REGEX_StateSet *sset;
1946   struct GNUNET_REGEX_StateSet *cls;
1947   unsigned int i;
1948   unsigned int j;
1949   unsigned int k;
1950   unsigned int contains;
1951
1952   if (NULL == states)
1953     return NULL;
1954
1955   cls = GNUNET_malloc (sizeof (struct GNUNET_REGEX_StateSet));
1956
1957   for (i = 0; i < states->len; i++)
1958   {
1959     s = states->states[i];
1960     sset = nfa_closure_create (nfa, s, label);
1961
1962     for (j = 0; j < sset->len; j++)
1963     {
1964       contains = 0;
1965       for (k = 0; k < cls->len; k++)
1966       {
1967         if (sset->states[j]->id == cls->states[k]->id)
1968         {
1969           contains = 1;
1970           break;
1971         }
1972       }
1973       if (!contains)
1974         GNUNET_array_append (cls->states, cls->len, sset->states[j]);
1975     }
1976     state_set_clear (sset);
1977   }
1978
1979   if (cls->len > 1)
1980     qsort (cls->states, cls->len, sizeof (struct GNUNET_REGEX_State *),
1981            state_compare);
1982
1983   return cls;
1984 }
1985
1986
1987 /**
1988  * Pops two NFA fragments (a, b) from the stack and concatenates them (ab)
1989  *
1990  * @param ctx context
1991  */
1992 static void
1993 nfa_add_concatenation (struct GNUNET_REGEX_Context *ctx)
1994 {
1995   struct GNUNET_REGEX_Automaton *a;
1996   struct GNUNET_REGEX_Automaton *b;
1997   struct GNUNET_REGEX_Automaton *new_nfa;
1998
1999   b = ctx->stack_tail;
2000   GNUNET_assert (NULL != b);
2001   GNUNET_CONTAINER_DLL_remove (ctx->stack_head, ctx->stack_tail, b);
2002   a = ctx->stack_tail;
2003   GNUNET_assert (NULL != a);
2004   GNUNET_CONTAINER_DLL_remove (ctx->stack_head, ctx->stack_tail, a);
2005
2006   state_add_transition (ctx, a->end, NULL, b->start);
2007   a->end->accepting = 0;
2008   b->end->accepting = 1;
2009
2010   new_nfa = nfa_fragment_create (NULL, NULL);
2011   nfa_add_states (new_nfa, a->states_head, a->states_tail);
2012   nfa_add_states (new_nfa, b->states_head, b->states_tail);
2013   new_nfa->start = a->start;
2014   new_nfa->end = b->end;
2015   new_nfa->state_count += a->state_count + b->state_count;
2016   automaton_fragment_clear (a);
2017   automaton_fragment_clear (b);
2018
2019   GNUNET_CONTAINER_DLL_insert_tail (ctx->stack_head, ctx->stack_tail, new_nfa);
2020 }
2021
2022
2023 /**
2024  * Pops a NFA fragment from the stack (a) and adds a new fragment (a*)
2025  *
2026  * @param ctx context
2027  */
2028 static void
2029 nfa_add_star_op (struct GNUNET_REGEX_Context *ctx)
2030 {
2031   struct GNUNET_REGEX_Automaton *a;
2032   struct GNUNET_REGEX_Automaton *new_nfa;
2033   struct GNUNET_REGEX_State *start;
2034   struct GNUNET_REGEX_State *end;
2035
2036   a = ctx->stack_tail;
2037
2038   if (NULL == a)
2039   {
2040     GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
2041                 "nfa_add_star_op failed, because there was no element on the stack");
2042     return;
2043   }
2044
2045   GNUNET_CONTAINER_DLL_remove (ctx->stack_head, ctx->stack_tail, a);
2046
2047   start = nfa_state_create (ctx, 0);
2048   end = nfa_state_create (ctx, 1);
2049
2050   state_add_transition (ctx, start, NULL, a->start);
2051   state_add_transition (ctx, start, NULL, end);
2052   state_add_transition (ctx, a->end, NULL, a->start);
2053   state_add_transition (ctx, a->end, NULL, end);
2054
2055   a->end->accepting = 0;
2056   end->accepting = 1;
2057
2058   new_nfa = nfa_fragment_create (start, end);
2059   nfa_add_states (new_nfa, a->states_head, a->states_tail);
2060   automaton_fragment_clear (a);
2061
2062   GNUNET_CONTAINER_DLL_insert_tail (ctx->stack_head, ctx->stack_tail, new_nfa);
2063 }
2064
2065
2066 /**
2067  * Pops an NFA fragment (a) from the stack and adds a new fragment (a+)
2068  *
2069  * @param ctx context
2070  */
2071 static void
2072 nfa_add_plus_op (struct GNUNET_REGEX_Context *ctx)
2073 {
2074   struct GNUNET_REGEX_Automaton *a;
2075
2076   a = ctx->stack_tail;
2077   GNUNET_CONTAINER_DLL_remove (ctx->stack_head, ctx->stack_tail, a);
2078
2079   state_add_transition (ctx, a->end, NULL, a->start);
2080
2081   GNUNET_CONTAINER_DLL_insert_tail (ctx->stack_head, ctx->stack_tail, a);
2082 }
2083
2084
2085 /**
2086  * Pops an NFA fragment (a) from the stack and adds a new fragment (a?)
2087  *
2088  * @param ctx context
2089  */
2090 static void
2091 nfa_add_question_op (struct GNUNET_REGEX_Context *ctx)
2092 {
2093   struct GNUNET_REGEX_Automaton *a;
2094   struct GNUNET_REGEX_Automaton *new_nfa;
2095   struct GNUNET_REGEX_State *start;
2096   struct GNUNET_REGEX_State *end;
2097
2098   a = ctx->stack_tail;
2099
2100   if (NULL == a)
2101   {
2102     GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
2103                 "nfa_add_question_op failed, because there was no element on the stack");
2104     return;
2105   }
2106
2107   GNUNET_CONTAINER_DLL_remove (ctx->stack_head, ctx->stack_tail, a);
2108
2109   start = nfa_state_create (ctx, 0);
2110   end = nfa_state_create (ctx, 1);
2111
2112   state_add_transition (ctx, start, NULL, a->start);
2113   state_add_transition (ctx, start, NULL, end);
2114   state_add_transition (ctx, a->end, NULL, end);
2115
2116   a->end->accepting = 0;
2117
2118   new_nfa = nfa_fragment_create (start, end);
2119   nfa_add_states (new_nfa, a->states_head, a->states_tail);
2120   automaton_fragment_clear (a);
2121
2122   GNUNET_CONTAINER_DLL_insert_tail (ctx->stack_head, ctx->stack_tail, new_nfa);
2123 }
2124
2125
2126 /**
2127  * Pops two NFA fragments (a, b) from the stack and adds a new NFA fragment that
2128  * alternates between a and b (a|b)
2129  *
2130  * @param ctx context
2131  */
2132 static void
2133 nfa_add_alternation (struct GNUNET_REGEX_Context *ctx)
2134 {
2135   struct GNUNET_REGEX_Automaton *a;
2136   struct GNUNET_REGEX_Automaton *b;
2137   struct GNUNET_REGEX_Automaton *new_nfa;
2138   struct GNUNET_REGEX_State *start;
2139   struct GNUNET_REGEX_State *end;
2140
2141   b = ctx->stack_tail;
2142   GNUNET_assert (NULL != b);
2143   GNUNET_CONTAINER_DLL_remove (ctx->stack_head, ctx->stack_tail, b);
2144   a = ctx->stack_tail;
2145   GNUNET_assert (NULL != a);
2146   GNUNET_CONTAINER_DLL_remove (ctx->stack_head, ctx->stack_tail, a);
2147
2148   start = nfa_state_create (ctx, 0);
2149   end = nfa_state_create (ctx, 1);
2150   state_add_transition (ctx, start, NULL, a->start);
2151   state_add_transition (ctx, start, NULL, b->start);
2152
2153   state_add_transition (ctx, a->end, NULL, end);
2154   state_add_transition (ctx, b->end, NULL, end);
2155
2156   a->end->accepting = 0;
2157   b->end->accepting = 0;
2158   end->accepting = 1;
2159
2160   new_nfa = nfa_fragment_create (start, end);
2161   nfa_add_states (new_nfa, a->states_head, a->states_tail);
2162   nfa_add_states (new_nfa, b->states_head, b->states_tail);
2163   automaton_fragment_clear (a);
2164   automaton_fragment_clear (b);
2165
2166   GNUNET_CONTAINER_DLL_insert_tail (ctx->stack_head, ctx->stack_tail, new_nfa);
2167 }
2168
2169
2170 /**
2171  * Adds a new nfa fragment to the stack
2172  *
2173  * @param ctx context
2174  * @param label label for nfa transition
2175  */
2176 static void
2177 nfa_add_label (struct GNUNET_REGEX_Context *ctx, const char *label)
2178 {
2179   struct GNUNET_REGEX_Automaton *n;
2180   struct GNUNET_REGEX_State *start;
2181   struct GNUNET_REGEX_State *end;
2182
2183   GNUNET_assert (NULL != ctx);
2184
2185   start = nfa_state_create (ctx, 0);
2186   end = nfa_state_create (ctx, 1);
2187   state_add_transition (ctx, start, label, end);
2188   n = nfa_fragment_create (start, end);
2189   GNUNET_assert (NULL != n);
2190   GNUNET_CONTAINER_DLL_insert_tail (ctx->stack_head, ctx->stack_tail, n);
2191 }
2192
2193
2194 /**
2195  * Initialize a new context
2196  *
2197  * @param ctx context
2198  */
2199 static void
2200 GNUNET_REGEX_context_init (struct GNUNET_REGEX_Context *ctx)
2201 {
2202   if (NULL == ctx)
2203   {
2204     GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "Context was NULL!");
2205     return;
2206   }
2207   ctx->state_id = 0;
2208   ctx->transition_id = 0;
2209   ctx->stack_head = NULL;
2210   ctx->stack_tail = NULL;
2211 }
2212
2213
2214 /**
2215  * Construct an NFA by parsing the regex string of length 'len'.
2216  *
2217  * @param regex regular expression string
2218  * @param len length of the string
2219  *
2220  * @return NFA, needs to be freed using GNUNET_REGEX_destroy_automaton
2221  */
2222 struct GNUNET_REGEX_Automaton *
2223 GNUNET_REGEX_construct_nfa (const char *regex, const size_t len)
2224 {
2225   struct GNUNET_REGEX_Context ctx;
2226   struct GNUNET_REGEX_Automaton *nfa;
2227   const char *regexp;
2228   char curlabel[2];
2229   char *error_msg;
2230   unsigned int count;
2231   unsigned int altcount;
2232   unsigned int atomcount;
2233   unsigned int pcount;
2234   struct
2235   {
2236     int altcount;
2237     int atomcount;
2238   }     *p;
2239
2240   GNUNET_REGEX_context_init (&ctx);
2241
2242   regexp = regex;
2243   curlabel[1] = '\0';
2244   p = NULL;
2245   error_msg = NULL;
2246   altcount = 0;
2247   atomcount = 0;
2248   pcount = 0;
2249
2250   for (count = 0; count < len && *regexp; count++, regexp++)
2251   {
2252     switch (*regexp)
2253     {
2254     case '(':
2255       if (atomcount > 1)
2256       {
2257         --atomcount;
2258         nfa_add_concatenation (&ctx);
2259       }
2260       GNUNET_array_grow (p, pcount, pcount + 1);
2261       p[pcount - 1].altcount = altcount;
2262       p[pcount - 1].atomcount = atomcount;
2263       altcount = 0;
2264       atomcount = 0;
2265       break;
2266     case '|':
2267       if (0 == atomcount)
2268       {
2269         error_msg = "Cannot append '|' to nothing";
2270         goto error;
2271       }
2272       while (--atomcount > 0)
2273         nfa_add_concatenation (&ctx);
2274       altcount++;
2275       break;
2276     case ')':
2277       if (0 == pcount)
2278       {
2279         error_msg = "Missing opening '('";
2280         goto error;
2281       }
2282       if (0 == atomcount)
2283       {
2284         // Ignore this: "()"
2285         pcount--;
2286         altcount = p[pcount].altcount;
2287         atomcount = p[pcount].atomcount;
2288         break;
2289       }
2290       while (--atomcount > 0)
2291         nfa_add_concatenation (&ctx);
2292       for (; altcount > 0; altcount--)
2293         nfa_add_alternation (&ctx);
2294       pcount--;
2295       altcount = p[pcount].altcount;
2296       atomcount = p[pcount].atomcount;
2297       atomcount++;
2298       break;
2299     case '*':
2300       if (atomcount == 0)
2301       {
2302         error_msg = "Cannot append '*' to nothing";
2303         goto error;
2304       }
2305       nfa_add_star_op (&ctx);
2306       break;
2307     case '+':
2308       if (atomcount == 0)
2309       {
2310         error_msg = "Cannot append '+' to nothing";
2311         goto error;
2312       }
2313       nfa_add_plus_op (&ctx);
2314       break;
2315     case '?':
2316       if (atomcount == 0)
2317       {
2318         error_msg = "Cannot append '?' to nothing";
2319         goto error;
2320       }
2321       nfa_add_question_op (&ctx);
2322       break;
2323     case 92:                   /* escape: \ */
2324       regexp++;
2325       count++;
2326       /* fall through! */
2327     default:
2328       if (atomcount > 1)
2329       {
2330         --atomcount;
2331         nfa_add_concatenation (&ctx);
2332       }
2333       curlabel[0] = *regexp;
2334       nfa_add_label (&ctx, curlabel);
2335       atomcount++;
2336       break;
2337     }
2338   }
2339   if (0 != pcount)
2340   {
2341     error_msg = "Unbalanced parenthesis";
2342     goto error;
2343   }
2344   while (--atomcount > 0)
2345     nfa_add_concatenation (&ctx);
2346   for (; altcount > 0; altcount--)
2347     nfa_add_alternation (&ctx);
2348
2349   GNUNET_free_non_null (p);
2350
2351   nfa = ctx.stack_tail;
2352   GNUNET_CONTAINER_DLL_remove (ctx.stack_head, ctx.stack_tail, nfa);
2353
2354   if (NULL != ctx.stack_head)
2355   {
2356     error_msg = "Creating the NFA failed. NFA stack was not empty!";
2357     goto error;
2358   }
2359
2360   nfa->regex = GNUNET_strdup (regex);
2361
2362   /* create depth-first numbering of the states for pretty printing */
2363   GNUNET_REGEX_automaton_traverse (nfa, NULL, NULL, NULL, &number_states, NULL);
2364
2365   return nfa;
2366
2367 error:
2368   GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "Could not parse regex: %s\n", regex);
2369   if (NULL != error_msg)
2370     GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "%s\n", error_msg);
2371
2372   GNUNET_free_non_null (p);
2373
2374   while (NULL != (nfa = ctx.stack_head))
2375   {
2376     GNUNET_CONTAINER_DLL_remove (ctx.stack_head, ctx.stack_tail, nfa);
2377     GNUNET_REGEX_automaton_destroy (nfa);
2378   }
2379
2380   return NULL;
2381 }
2382
2383
2384 /**
2385  * Create DFA states based on given 'nfa' and starting with 'dfa_state'.
2386  *
2387  * @param ctx context.
2388  * @param nfa NFA automaton.
2389  * @param dfa DFA automaton.
2390  * @param dfa_state current dfa state, pass epsilon closure of first nfa state
2391  *                  for starting.
2392  */
2393 static void
2394 construct_dfa_states (struct GNUNET_REGEX_Context *ctx,
2395                       struct GNUNET_REGEX_Automaton *nfa,
2396                       struct GNUNET_REGEX_Automaton *dfa,
2397                       struct GNUNET_REGEX_State *dfa_state)
2398 {
2399   struct GNUNET_REGEX_Transition *ctran;
2400   struct GNUNET_REGEX_State *state_iter;
2401   struct GNUNET_REGEX_State *new_dfa_state;
2402   struct GNUNET_REGEX_State *state_contains;
2403   struct GNUNET_REGEX_StateSet *tmp;
2404   struct GNUNET_REGEX_StateSet *nfa_set;
2405
2406   for (ctran = dfa_state->transitions_head; NULL != ctran; ctran = ctran->next)
2407   {
2408     if (NULL == ctran->label || NULL != ctran->to_state)
2409       continue;
2410
2411     tmp = nfa_closure_set_create (nfa, dfa_state->nfa_set, ctran->label);
2412     nfa_set = nfa_closure_set_create (nfa, tmp, 0);
2413     state_set_clear (tmp);
2414     new_dfa_state = dfa_state_create (ctx, nfa_set);
2415     state_contains = NULL;
2416     for (state_iter = dfa->states_head; NULL != state_iter;
2417          state_iter = state_iter->next)
2418     {
2419       if (0 == state_set_compare (state_iter->nfa_set, new_dfa_state->nfa_set))
2420         state_contains = state_iter;
2421     }
2422
2423     if (NULL == state_contains)
2424     {
2425       automaton_add_state (dfa, new_dfa_state);
2426       ctran->to_state = new_dfa_state;
2427       construct_dfa_states (ctx, nfa, dfa, new_dfa_state);
2428     }
2429     else
2430     {
2431       ctran->to_state = state_contains;
2432       automaton_destroy_state (new_dfa_state);
2433     }
2434   }
2435 }
2436
2437
2438 /**
2439  * Construct DFA for the given 'regex' of length 'len'
2440  *
2441  * @param regex regular expression string
2442  * @param len length of the regular expression
2443  *
2444  * @return DFA, needs to be freed using GNUNET_REGEX_destroy_automaton
2445  */
2446 struct GNUNET_REGEX_Automaton *
2447 GNUNET_REGEX_construct_dfa (const char *regex, const size_t len)
2448 {
2449   struct GNUNET_REGEX_Context ctx;
2450   struct GNUNET_REGEX_Automaton *dfa;
2451   struct GNUNET_REGEX_Automaton *nfa;
2452   struct GNUNET_REGEX_StateSet *nfa_set;
2453
2454   GNUNET_REGEX_context_init (&ctx);
2455
2456   // Create NFA
2457   nfa = GNUNET_REGEX_construct_nfa (regex, len);
2458
2459   if (NULL == nfa)
2460   {
2461     GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
2462                 "Could not create DFA, because NFA creation failed\n");
2463     return NULL;
2464   }
2465
2466   dfa = GNUNET_malloc (sizeof (struct GNUNET_REGEX_Automaton));
2467   dfa->type = DFA;
2468   dfa->state_count = 0;
2469   dfa->states_head = NULL;
2470   dfa->states_tail = NULL;
2471   dfa->regex = GNUNET_strdup (regex);
2472
2473   // Create DFA start state from epsilon closure
2474   nfa_set = nfa_closure_create (nfa, nfa->start, 0);
2475   dfa->start = dfa_state_create (&ctx, nfa_set);
2476   automaton_add_state (dfa, dfa->start);
2477
2478   construct_dfa_states (&ctx, nfa, dfa, dfa->start);
2479
2480   GNUNET_REGEX_automaton_destroy (nfa);
2481
2482   // Minimize DFA
2483   dfa_minimize (&ctx, dfa);
2484
2485   // Create proofs for all states
2486   automaton_create_proofs (dfa);
2487
2488   // Add strides to DFA
2489   // GNUNET_REGEX_add_multi_strides_to_dfa (&ctx, dfa, 2);
2490
2491   return dfa;
2492 }
2493
2494
2495 /**
2496  * Free the memory allocated by constructing the GNUNET_REGEX_Automaton data
2497  * structure.
2498  *
2499  * @param a automaton to be destroyed
2500  */
2501 void
2502 GNUNET_REGEX_automaton_destroy (struct GNUNET_REGEX_Automaton *a)
2503 {
2504   struct GNUNET_REGEX_State *s;
2505   struct GNUNET_REGEX_State *next_state;
2506
2507   if (NULL == a)
2508     return;
2509
2510   GNUNET_free_non_null (a->regex);
2511   GNUNET_free_non_null (a->canonical_regex);
2512
2513   for (s = a->states_head; NULL != s;)
2514   {
2515     next_state = s->next;
2516     automaton_destroy_state (s);
2517     s = next_state;
2518   }
2519
2520   GNUNET_free (a);
2521 }
2522
2523
2524 /**
2525  * Evaluates the given string using the given DFA automaton
2526  *
2527  * @param a automaton, type must be DFA
2528  * @param string string that should be evaluated
2529  *
2530  * @return 0 if string matches, non 0 otherwise
2531  */
2532 static int
2533 evaluate_dfa (struct GNUNET_REGEX_Automaton *a, const char *string)
2534 {
2535   const char *strp;
2536   char str[2];
2537   struct GNUNET_REGEX_State *s;
2538
2539   if (DFA != a->type)
2540   {
2541     GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
2542                 "Tried to evaluate DFA, but NFA automaton given");
2543     return -1;
2544   }
2545
2546   s = a->start;
2547
2548   // If the string is empty but the starting state is accepting, we accept.
2549   if ((NULL == string || 0 == strlen (string)) && s->accepting)
2550     return 0;
2551
2552   str[1] = '\0';
2553   for (strp = string; NULL != strp && *strp; strp++)
2554   {
2555     str[0] = *strp;
2556     s = dfa_move (s, str);
2557     if (NULL == s)
2558       break;
2559   }
2560
2561   if (NULL != s && s->accepting)
2562     return 0;
2563
2564   return 1;
2565 }
2566
2567
2568 /**
2569  * Evaluates the given string using the given NFA automaton
2570  *
2571  * @param a automaton, type must be NFA
2572  * @param string string that should be evaluated
2573  *
2574  * @return 0 if string matches, non 0 otherwise
2575  */
2576 static int
2577 evaluate_nfa (struct GNUNET_REGEX_Automaton *a, const char *string)
2578 {
2579   const char *strp;
2580   char str[2];
2581   struct GNUNET_REGEX_State *s;
2582   struct GNUNET_REGEX_StateSet *sset;
2583   struct GNUNET_REGEX_StateSet *new_sset;
2584   unsigned int i;
2585   int result;
2586
2587   if (NFA != a->type)
2588   {
2589     GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
2590                 "Tried to evaluate NFA, but DFA automaton given");
2591     return -1;
2592   }
2593
2594   // If the string is empty but the starting state is accepting, we accept.
2595   if ((NULL == string || 0 == strlen (string)) && a->start->accepting)
2596     return 0;
2597
2598   result = 1;
2599   sset = nfa_closure_create (a, a->start, 0);
2600
2601   str[1] = '\0';
2602   for (strp = string; NULL != strp && *strp; strp++)
2603   {
2604     str[0] = *strp;
2605     new_sset = nfa_closure_set_create (a, sset, str);
2606     state_set_clear (sset);
2607     sset = nfa_closure_set_create (a, new_sset, 0);
2608     state_set_clear (new_sset);
2609   }
2610
2611   for (i = 0; i < sset->len; i++)
2612   {
2613     s = sset->states[i];
2614     if (NULL != s && s->accepting)
2615     {
2616       result = 0;
2617       break;
2618     }
2619   }
2620
2621   state_set_clear (sset);
2622   return result;
2623 }
2624
2625
2626 /**
2627  * Evaluates the given 'string' against the given compiled regex
2628  *
2629  * @param a automaton
2630  * @param string string to check
2631  *
2632  * @return 0 if string matches, non 0 otherwise
2633  */
2634 int
2635 GNUNET_REGEX_eval (struct GNUNET_REGEX_Automaton *a, const char *string)
2636 {
2637   int result;
2638
2639   switch (a->type)
2640   {
2641   case DFA:
2642     result = evaluate_dfa (a, string);
2643     break;
2644   case NFA:
2645     result = evaluate_nfa (a, string);
2646     break;
2647   default:
2648     GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
2649                 "Evaluating regex failed, automaton has no type!\n");
2650     result = GNUNET_SYSERR;
2651     break;
2652   }
2653
2654   return result;
2655 }
2656
2657
2658 /**
2659  * Get the canonical regex of the given automaton.
2660  * When constructing the automaton a proof is computed for each state,
2661  * consisting of the regular expression leading to this state. A complete
2662  * regex for the automaton can be computed by combining these proofs.
2663  * As of now this function is only useful for testing.
2664  *
2665  * @param a automaton for which the canonical regex should be returned.
2666  *
2667  * @return
2668  */
2669 const char *
2670 GNUNET_REGEX_get_canonical_regex (struct GNUNET_REGEX_Automaton *a)
2671 {
2672   if (NULL == a)
2673     return NULL;
2674
2675   return a->canonical_regex;
2676 }
2677
2678
2679 /**
2680  * Get the number of transitions that are contained in the given automaton.
2681  *
2682  * @param a automaton for which the number of transitions should be returned.
2683  *
2684  * @return number of transitions in the given automaton.
2685  */
2686 unsigned int
2687 GNUNET_REGEX_get_transition_count (struct GNUNET_REGEX_Automaton *a)
2688 {
2689   unsigned int t_count;
2690   struct GNUNET_REGEX_State *s;
2691
2692   if (NULL == a)
2693     return 0;
2694
2695   for (t_count = 0, s = a->states_head; NULL != s; s = s->next)
2696   {
2697     t_count += s->transition_count;
2698   }
2699
2700   return t_count;
2701 }
2702
2703
2704 /**
2705  * Get the first key for the given 'input_string'. This hashes the first x bits
2706  * of the 'input_string'.
2707  *
2708  * @param input_string string.
2709  * @param string_len length of the 'input_string'.
2710  * @param key pointer to where to write the hash code.
2711  *
2712  * @return number of bits of 'input_string' that have been consumed
2713  *         to construct the key
2714  */
2715 size_t
2716 GNUNET_REGEX_get_first_key (const char *input_string, size_t string_len,
2717                             struct GNUNET_HashCode * key)
2718 {
2719   unsigned int size;
2720
2721   size = string_len < INITIAL_BITS ? string_len : INITIAL_BITS;
2722
2723   if (NULL == input_string)
2724   {
2725     GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "Given input string was NULL!\n");
2726     return 0;
2727   }
2728
2729   GNUNET_CRYPTO_hash (input_string, size, key);
2730
2731   return size;
2732 }
2733
2734
2735 /**
2736  * Check if the given 'proof' matches the given 'key'.
2737  *
2738  * @param proof partial regex of a state.
2739  * @param key hash of a state.
2740  *
2741  * @return GNUNET_OK if the proof is valid for the given key.
2742  */
2743 int
2744 GNUNET_REGEX_check_proof (const char *proof, const struct GNUNET_HashCode *key)
2745 {
2746   struct GNUNET_HashCode key_check;
2747
2748   if (NULL == proof || NULL == key)
2749   {
2750     GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "Proof check failed, was NULL.\n");
2751     return GNUNET_NO;
2752   }
2753
2754   GNUNET_CRYPTO_hash (proof, strlen (proof), &key_check);
2755   return (0 ==
2756           GNUNET_CRYPTO_hash_cmp (key, &key_check)) ? GNUNET_OK : GNUNET_NO;
2757 }
2758
2759
2760 /**
2761  * Recursive helper function for iterate_initial_edges. Will call iterator
2762  * function for each initial state.
2763  *
2764  * @param min_len minimum length of the path in the graph.
2765  * @param max_len maximum length of the path in the graph.
2766  * @param cur_len current length of the path already traversed.
2767  * @param consumed_string string consumed by traversing the graph till this state.
2768  * @param state current state of the automaton.
2769  * @param iterator iterator function called for each edge.
2770  * @param iterator_cls closure for the iterator function.
2771  */
2772 static void
2773 iterate_initial_edge (const unsigned int min_len, const unsigned int max_len,
2774                       unsigned int cur_len, char *consumed_string,
2775                       struct GNUNET_REGEX_State *state,
2776                       GNUNET_REGEX_KeyIterator iterator, void *iterator_cls)
2777 {
2778   unsigned int i;
2779   char *temp;
2780   struct GNUNET_REGEX_Transition *t;
2781   unsigned int num_edges = state->transition_count;
2782   struct GNUNET_REGEX_Edge edges[num_edges];
2783   struct GNUNET_HashCode hash;
2784
2785   if (cur_len > min_len && NULL != consumed_string && cur_len <= max_len)
2786   {
2787     for (i = 0, t = state->transitions_head; NULL != t; t = t->next, i++)
2788     {
2789       edges[i].label = t->label;
2790       edges[i].destination = t->to_state->hash;
2791     }
2792
2793     GNUNET_CRYPTO_hash (consumed_string, strlen (consumed_string), &hash);
2794     iterator (iterator_cls, &hash, consumed_string, state->accepting, num_edges,
2795               edges);
2796   }
2797
2798   if (cur_len < max_len)
2799   {
2800     cur_len++;
2801     for (t = state->transitions_head; NULL != t; t = t->next)
2802     {
2803       if (NULL != consumed_string)
2804         GNUNET_asprintf (&temp, "%s%s", consumed_string, t->label);
2805       else
2806         GNUNET_asprintf (&temp, "%s", t->label);
2807
2808       iterate_initial_edge (min_len, max_len, cur_len, temp, t->to_state,
2809                             iterator, iterator_cls);
2810       GNUNET_free (temp);
2811     }
2812   }
2813 }
2814
2815
2816 /**
2817  * Iterate over all initial edges that aren't actually part of the automaton.
2818  * This is needed to find the initial states returned by
2819  * GNUNET_REGEX_get_first_key. Iteration will start at the first state that has
2820  * more than one outgoing edge, i.e. the state that branches the graph.
2821  * For example consider the following graph:
2822  * a -> b -> c -> d -> ...
2823  *            \-> e -> ...
2824  *
2825  * This function will not iterate over the edges leading to "c", because these
2826  * will be covered by the iterate_edges function.
2827  *
2828  * @param a the automaton for which the initial states should be computed.
2829  * @param initial_len length of the initial state string.
2830  * @param iterator iterator function called for each edge.
2831  * @param iterator_cls closure for the iterator function.
2832  */
2833 void
2834 iterate_initial_edges (struct GNUNET_REGEX_Automaton *a,
2835                        const unsigned int initial_len,
2836                        GNUNET_REGEX_KeyIterator iterator, void *iterator_cls)
2837 {
2838   char *consumed_string;
2839   char *temp;
2840   struct GNUNET_REGEX_State *s;
2841   unsigned int cur_len;
2842
2843   if (1 > initial_len)
2844     return;
2845
2846   consumed_string = NULL;
2847   s = a->start;
2848   cur_len = 0;
2849
2850   if (1 == s->transition_count)
2851   {
2852     do
2853     {
2854       if (NULL != consumed_string)
2855       {
2856         temp = consumed_string;
2857         GNUNET_asprintf (&consumed_string, "%s%s", consumed_string,
2858                          s->transitions_head->label);
2859         GNUNET_free (temp);
2860       }
2861       else
2862         GNUNET_asprintf (&consumed_string, "%s", s->transitions_head->label);
2863
2864       s = s->transitions_head->to_state;
2865       cur_len += strlen (s->transitions_head->label);
2866     }
2867     while (cur_len < initial_len && 1 == s->transition_count);
2868   }
2869
2870   iterate_initial_edge (cur_len, initial_len, cur_len, consumed_string, s,
2871                         iterator, iterator_cls);
2872
2873   GNUNET_free_non_null (consumed_string);
2874 }
2875
2876
2877 /**
2878  * Iterate over all edges helper function starting from state 's', calling
2879  * iterator function for each edge.
2880  *
2881  * @param s state.
2882  * @param iterator iterator function called for each edge.
2883  * @param iterator_cls closure.
2884  */
2885 static void
2886 iterate_edge (struct GNUNET_REGEX_State *s, GNUNET_REGEX_KeyIterator iterator,
2887               void *iterator_cls)
2888 {
2889   struct GNUNET_REGEX_Transition *t;
2890   struct GNUNET_REGEX_Edge edges[s->transition_count];
2891   unsigned int num_edges;
2892
2893   if (GNUNET_YES != s->marked)
2894   {
2895     s->marked = GNUNET_YES;
2896
2897     num_edges = state_get_edges (s, edges);
2898
2899     if ((NULL != s->proof && 0 < strlen (s->proof)) || s->accepting)
2900       iterator (iterator_cls, &s->hash, s->proof, s->accepting, num_edges,
2901                 edges);
2902
2903     for (t = s->transitions_head; NULL != t; t = t->next)
2904       iterate_edge (t->to_state, iterator, iterator_cls);
2905   }
2906 }
2907
2908
2909 /**
2910  * Iterate over all edges starting from start state of automaton 'a'. Calling
2911  * iterator for each edge.
2912  *
2913  * @param a automaton.
2914  * @param iterator iterator called for each edge.
2915  * @param iterator_cls closure.
2916  */
2917 void
2918 GNUNET_REGEX_iterate_all_edges (struct GNUNET_REGEX_Automaton *a,
2919                                 GNUNET_REGEX_KeyIterator iterator,
2920                                 void *iterator_cls)
2921 {
2922   struct GNUNET_REGEX_State *s;
2923
2924   for (s = a->states_head; NULL != s; s = s->next)
2925     s->marked = GNUNET_NO;
2926
2927   iterate_initial_edges (a, INITIAL_BITS, iterator, iterator_cls);
2928   iterate_edge (a->start, iterator, iterator_cls);
2929 }