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