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