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