ea5bca9a9c0222c0b4d1322d1eb0a40ac8c26343
[oweals/gnunet.git] / src / regex / regex_internal.c
1 /*
2      This file is part of GNUnet
3      Copyright (C) 2012 GNUnet e.V.
4
5      GNUnet is free software: you can redistribute it and/or modify it
6      under the terms of the GNU Affero General Public License as published
7      by the Free Software Foundation, either version 3 of the License,
8      or (at your 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      Affero General Public License for more details.
14 */
15 /**
16  * @file src/regex/regex_internal.c
17  * @brief library to create Deterministic Finite Automatons (DFAs) from regular
18  * expressions (regexes).
19  * @author Maximilian Szengel
20  */
21 #include "platform.h"
22 #include "gnunet_util_lib.h"
23 #include "gnunet_regex_service.h"
24 #include "regex_internal_lib.h"
25 #include "regex_internal.h"
26
27
28 /**
29  * Set this to #GNUNET_YES to enable state naming. Used to debug NFA->DFA
30  * creation. Disabled by default for better performance.
31  */
32 #define REGEX_DEBUG_DFA GNUNET_NO
33
34 /**
35  * Set of states using MDLL API.
36  */
37 struct REGEX_INTERNAL_StateSet_MDLL
38 {
39   /**
40    * MDLL of states.
41    */
42   struct REGEX_INTERNAL_State *head;
43
44   /**
45    * MDLL of states.
46    */
47   struct REGEX_INTERNAL_State *tail;
48
49   /**
50    * Length of the MDLL.
51    */
52   unsigned int len;
53 };
54
55
56 /**
57  * Append state to the given StateSet.
58  *
59  * @param set set to be modified
60  * @param state state to be appended
61  */
62 static void
63 state_set_append (struct REGEX_INTERNAL_StateSet *set,
64                   struct REGEX_INTERNAL_State *state)
65 {
66   if (set->off == set->size)
67     GNUNET_array_grow (set->states, set->size, set->size * 2 + 4);
68   set->states[set->off++] = state;
69 }
70
71
72 /**
73  * Compare two strings for equality. If either is NULL they are not equal.
74  *
75  * @param str1 first string for comparison.
76  * @param str2 second string for comparison.
77  *
78  * @return 0 if the strings are the same or both NULL, 1 or -1 if not.
79  */
80 static int
81 nullstrcmp (const char *str1, const char *str2)
82 {
83   if ((NULL == str1) != (NULL == str2))
84     return -1;
85   if ((NULL == str1) && (NULL == str2))
86     return 0;
87
88   return strcmp (str1, str2);
89 }
90
91
92 /**
93  * Adds a transition from one state to another on @a label. Does not add
94  * duplicate states.
95  *
96  * @param ctx context
97  * @param from_state starting state for the transition
98  * @param label transition label
99  * @param to_state state to where the transition should point to
100  */
101 static void
102 state_add_transition (struct REGEX_INTERNAL_Context *ctx,
103                       struct REGEX_INTERNAL_State *from_state,
104                       const char *label,
105                       struct REGEX_INTERNAL_State *to_state)
106 {
107   struct REGEX_INTERNAL_Transition *t;
108   struct REGEX_INTERNAL_Transition *oth;
109
110   if (NULL == from_state)
111   {
112     GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
113                 "Could not create Transition.\n");
114     return;
115   }
116
117   /* Do not add duplicate state transitions */
118   for (t = from_state->transitions_head; NULL != t; t = t->next)
119   {
120     if (t->to_state == to_state && 0 == nullstrcmp (t->label, label) &&
121         t->from_state == from_state)
122       return;
123   }
124
125   /* sort transitions by label */
126   for (oth = from_state->transitions_head; NULL != oth; oth = oth->next)
127   {
128     if (0 < nullstrcmp (oth->label, label))
129       break;
130   }
131
132   t = GNUNET_new (struct REGEX_INTERNAL_Transition);
133   if (NULL != ctx)
134     t->id = ctx->transition_id++;
135   if (NULL != label)
136     t->label = GNUNET_strdup (label);
137   else
138     t->label = NULL;
139   t->to_state = to_state;
140   t->from_state = from_state;
141
142   /* Add outgoing transition to 'from_state' */
143   from_state->transition_count++;
144   GNUNET_CONTAINER_DLL_insert_before (from_state->transitions_head,
145                                       from_state->transitions_tail, oth, t);
146 }
147
148
149 /**
150  * Remove a 'transition' from 'state'.
151  *
152  * @param state state from which the to-be-removed transition originates.
153  * @param transition transition that should be removed from state 'state'.
154  */
155 static void
156 state_remove_transition (struct REGEX_INTERNAL_State *state,
157                          struct REGEX_INTERNAL_Transition *transition)
158 {
159   if (NULL == state || NULL == transition)
160     return;
161
162   if (transition->from_state != state)
163     return;
164
165   GNUNET_free_non_null (transition->label);
166
167   state->transition_count--;
168   GNUNET_CONTAINER_DLL_remove (state->transitions_head, state->transitions_tail,
169                                transition);
170
171   GNUNET_free (transition);
172 }
173
174
175 /**
176  * Compare two states. Used for sorting.
177  *
178  * @param a first state
179  * @param b second state
180  *
181  * @return an integer less than, equal to, or greater than zero
182  *         if the first argument is considered to be respectively
183  *         less than, equal to, or greater than the second.
184  */
185 static int
186 state_compare (const void *a, const void *b)
187 {
188   struct REGEX_INTERNAL_State **s1 = (struct REGEX_INTERNAL_State **) a;
189   struct REGEX_INTERNAL_State **s2 = (struct REGEX_INTERNAL_State **) b;
190
191   return (*s1)->id - (*s2)->id;
192 }
193
194
195 /**
196  * Get all edges leaving state @a s.
197  *
198  * @param s state.
199  * @param edges all edges leaving @a s, expected to be allocated and have enough
200  *        space for `s->transitions_count` elements.
201  *
202  * @return number of edges.
203  */
204 static unsigned int
205 state_get_edges (struct REGEX_INTERNAL_State *s,
206                  struct REGEX_BLOCK_Edge *edges)
207 {
208   struct REGEX_INTERNAL_Transition *t;
209   unsigned int count;
210
211   if (NULL == s)
212     return 0;
213
214   count = 0;
215
216   for (t = s->transitions_head; NULL != t; t = t->next)
217   {
218     if (NULL != t->to_state)
219     {
220       edges[count].label = t->label;
221       edges[count].destination = t->to_state->hash;
222       count++;
223     }
224   }
225   return count;
226 }
227
228
229 /**
230  * Compare to state sets by comparing the id's of the states that are contained
231  * in each set. Both sets are expected to be sorted by id!
232  *
233  * @param sset1 first state set
234  * @param sset2 second state set
235  * @return 0 if the sets are equal, otherwise non-zero
236  */
237 static int
238 state_set_compare (struct REGEX_INTERNAL_StateSet *sset1,
239                    struct REGEX_INTERNAL_StateSet *sset2)
240 {
241   int result;
242   unsigned int i;
243
244   if (NULL == sset1 || NULL == sset2)
245     return 1;
246
247   result = sset1->off - sset2->off;
248   if (result < 0)
249     return -1;
250   if (result > 0)
251     return 1;
252   for (i = 0; i < sset1->off; i++)
253     if (0 != (result = state_compare (&sset1->states[i], &sset2->states[i])))
254       break;
255   return result;
256 }
257
258
259 /**
260  * Clears the given StateSet 'set'
261  *
262  * @param set set to be cleared
263  */
264 static void
265 state_set_clear (struct REGEX_INTERNAL_StateSet *set)
266 {
267   GNUNET_array_grow (set->states, set->size, 0);
268   set->off = 0;
269 }
270
271
272 /**
273  * Clears an automaton fragment. Does not destroy the states inside the
274  * automaton.
275  *
276  * @param a automaton to be cleared
277  */
278 static void
279 automaton_fragment_clear (struct REGEX_INTERNAL_Automaton *a)
280 {
281   if (NULL == a)
282     return;
283
284   a->start = NULL;
285   a->end = NULL;
286   a->states_head = NULL;
287   a->states_tail = NULL;
288   a->state_count = 0;
289   GNUNET_free (a);
290 }
291
292
293 /**
294  * Frees the memory used by State @a s
295  *
296  * @param s state that should be destroyed
297  */
298 static void
299 automaton_destroy_state (struct REGEX_INTERNAL_State *s)
300 {
301   struct REGEX_INTERNAL_Transition *t;
302   struct REGEX_INTERNAL_Transition *next_t;
303
304   if (NULL == s)
305     return;
306
307   GNUNET_free_non_null (s->name);
308   GNUNET_free_non_null (s->proof);
309   state_set_clear (&s->nfa_set);
310   for (t = s->transitions_head; NULL != t; t = next_t)
311   {
312     next_t = t->next;
313     state_remove_transition (s, t);
314   }
315
316   GNUNET_free (s);
317 }
318
319
320 /**
321  * Remove a state from the given automaton 'a'. Always use this function when
322  * altering the states of an automaton. Will also remove all transitions leading
323  * to this state, before destroying it.
324  *
325  * @param a automaton
326  * @param s state to remove
327  */
328 static void
329 automaton_remove_state (struct REGEX_INTERNAL_Automaton *a,
330                         struct REGEX_INTERNAL_State *s)
331 {
332   struct REGEX_INTERNAL_State *s_check;
333   struct REGEX_INTERNAL_Transition *t_check;
334   struct REGEX_INTERNAL_Transition *t_check_next;
335
336   if (NULL == a || NULL == s)
337     return;
338
339   /* remove all transitions leading to this state */
340   for (s_check = a->states_head; NULL != s_check; s_check = s_check->next)
341   {
342     for (t_check = s_check->transitions_head; NULL != t_check;
343          t_check = t_check_next)
344     {
345       t_check_next = t_check->next;
346       if (t_check->to_state == s)
347         state_remove_transition (s_check, t_check);
348     }
349   }
350
351   /* remove state */
352   GNUNET_CONTAINER_DLL_remove (a->states_head, a->states_tail, s);
353   a->state_count--;
354
355   automaton_destroy_state (s);
356 }
357
358
359 /**
360  * Merge two states into one. Will merge 's1' and 's2' into 's1' and destroy
361  * 's2'. 's1' will contain all (non-duplicate) outgoing transitions of 's2'.
362  *
363  * @param ctx context
364  * @param a automaton
365  * @param s1 first state
366  * @param s2 second state, will be destroyed
367  */
368 static void
369 automaton_merge_states (struct REGEX_INTERNAL_Context *ctx,
370                         struct REGEX_INTERNAL_Automaton *a,
371                         struct REGEX_INTERNAL_State *s1,
372                         struct REGEX_INTERNAL_State *s2)
373 {
374   struct REGEX_INTERNAL_State *s_check;
375   struct REGEX_INTERNAL_Transition *t_check;
376   struct REGEX_INTERNAL_Transition *t;
377   struct REGEX_INTERNAL_Transition *t_next;
378   int is_dup;
379
380   if (s1 == s2)
381     return;
382
383   /* 1. Make all transitions pointing to s2 point to s1, unless this transition
384    * does not already exists, if it already exists remove transition. */
385   for (s_check = a->states_head; NULL != s_check; s_check = s_check->next)
386   {
387     for (t_check = s_check->transitions_head; NULL != t_check; t_check = t_next)
388     {
389       t_next = t_check->next;
390
391       if (s2 == t_check->to_state)
392       {
393         is_dup = GNUNET_NO;
394         for (t = t_check->from_state->transitions_head; NULL != t; t = t->next)
395         {
396           if (t->to_state == s1 && 0 == strcmp (t_check->label, t->label))
397             is_dup = GNUNET_YES;
398         }
399         if (GNUNET_NO == is_dup)
400           t_check->to_state = s1;
401         else
402           state_remove_transition (t_check->from_state, t_check);
403       }
404     }
405   }
406
407   /* 2. Add all transitions from s2 to sX to s1 */
408   for (t_check = s2->transitions_head; NULL != t_check; t_check = t_check->next)
409   {
410     if (t_check->to_state != s1)
411       state_add_transition (ctx, s1, t_check->label, t_check->to_state);
412   }
413
414   /* 3. Rename s1 to {s1,s2} */
415 #if REGEX_DEBUG_DFA
416   char *new_name;
417
418   new_name = s1->name;
419   GNUNET_asprintf (&s1->name, "{%s,%s}", new_name, s2->name);
420   GNUNET_free (new_name);
421 #endif
422
423   /* remove state */
424   GNUNET_CONTAINER_DLL_remove (a->states_head, a->states_tail, s2);
425   a->state_count--;
426   automaton_destroy_state (s2);
427 }
428
429
430 /**
431  * Add a state to the automaton 'a', always use this function to alter the
432  * states DLL of the automaton.
433  *
434  * @param a automaton to add the state to
435  * @param s state that should be added
436  */
437 static void
438 automaton_add_state (struct REGEX_INTERNAL_Automaton *a,
439                      struct REGEX_INTERNAL_State *s)
440 {
441   GNUNET_CONTAINER_DLL_insert (a->states_head, a->states_tail, s);
442   a->state_count++;
443 }
444
445
446 /**
447  * Depth-first traversal (DFS) of all states that are reachable from state
448  * 's'. Performs 'action' on each visited state.
449  *
450  * @param s start state.
451  * @param marks an array of size a->state_count to remember which state was
452  *        already visited.
453  * @param count current count of the state.
454  * @param check function that is checked before advancing on each transition
455  *              in the DFS.
456  * @param check_cls closure for check.
457  * @param action action to be performed on each state.
458  * @param action_cls closure for action.
459  */
460 static void
461 automaton_state_traverse (struct REGEX_INTERNAL_State *s, int *marks,
462                           unsigned int *count,
463                           REGEX_INTERNAL_traverse_check check, void *check_cls,
464                           REGEX_INTERNAL_traverse_action action, void *action_cls)
465 {
466   struct REGEX_INTERNAL_Transition *t;
467
468   if (GNUNET_YES == marks[s->traversal_id])
469     return;
470
471   marks[s->traversal_id] = GNUNET_YES;
472
473   if (NULL != action)
474     action (action_cls, *count, s);
475
476   (*count)++;
477
478   for (t = s->transitions_head; NULL != t; t = t->next)
479   {
480     if (NULL == check ||
481         (NULL != check && GNUNET_YES == check (check_cls, s, t)))
482     {
483       automaton_state_traverse (t->to_state, marks, count, check, check_cls,
484                                 action, action_cls);
485     }
486   }
487 }
488
489
490 /**
491  * Traverses the given automaton using depth-first-search (DFS) from it's start
492  * state, visiting all reachable states and calling 'action' on each one of
493  * them.
494  *
495  * @param a automaton to be traversed.
496  * @param start start state, pass a->start or NULL to traverse the whole automaton.
497  * @param check function that is checked before advancing on each transition
498  *              in the DFS.
499  * @param check_cls closure for @a check.
500  * @param action action to be performed on each state.
501  * @param action_cls closure for @a action
502  */
503 void
504 REGEX_INTERNAL_automaton_traverse (const struct REGEX_INTERNAL_Automaton *a,
505                                    struct REGEX_INTERNAL_State *start,
506                                    REGEX_INTERNAL_traverse_check check,
507                                    void *check_cls,
508                                    REGEX_INTERNAL_traverse_action action,
509                                    void *action_cls)
510 {
511   unsigned int count;
512   struct REGEX_INTERNAL_State *s;
513
514   if (NULL == a || 0 == a->state_count)
515     return;
516
517   int marks[a->state_count];
518
519   for (count = 0, s = a->states_head; NULL != s && count < a->state_count;
520        s = s->next, count++)
521   {
522     s->traversal_id = count;
523     marks[s->traversal_id] = GNUNET_NO;
524   }
525
526   count = 0;
527
528   if (NULL == start)
529     s = a->start;
530   else
531     s = start;
532
533   automaton_state_traverse (s, marks, &count,
534                             check, check_cls,
535                             action, action_cls);
536 }
537
538
539 /**
540  * String container for faster string operations.
541  */
542 struct StringBuffer
543 {
544   /**
545    * Buffer holding the string (may start in the middle!);
546    * NOT 0-terminated!
547    */
548   char *sbuf;
549
550   /**
551    * Allocated buffer.
552    */
553   char *abuf;
554
555   /**
556    * Length of the string in the buffer.
557    */
558   size_t slen;
559
560   /**
561    * Number of bytes allocated for @e sbuf
562    */
563   unsigned int blen;
564
565   /**
566    * Buffer currently represents "NULL" (not the empty string!)
567    */
568   int16_t null_flag;
569
570   /**
571    * If this entry is part of the last/current generation array,
572    * this flag is #GNUNET_YES if the last and current generation are
573    * identical (and thus copying is unnecessary if the value didn't
574    * change).  This is used in an optimization that improves
575    * performance by about 1% --- if we use int16_t here.  With just
576    * "int" for both flags, performance drops (on my system) significantly,
577    * most likely due to increased cache misses.
578    */
579   int16_t synced;
580
581 };
582
583
584 /**
585  * Compare two strings for equality. If either is NULL they are not equal.
586  *
587  * @param s1 first string for comparison.
588  * @param s2 second string for comparison.
589  *
590  * @return 0 if the strings are the same or both NULL, 1 or -1 if not.
591  */
592 static int
593 sb_nullstrcmp (const struct StringBuffer *s1,
594                const struct StringBuffer *s2)
595 {
596   if ( (GNUNET_YES == s1->null_flag) &&
597        (GNUNET_YES == s2->null_flag) )
598     return 0;
599   if ( (GNUNET_YES == s1->null_flag) ||
600        (GNUNET_YES == s2->null_flag) )
601     return -1;
602   if (s1->slen != s2->slen)
603     return -1;
604   if (0 == s1->slen)
605     return 0;
606   return memcmp (s1->sbuf, s2->sbuf, s1->slen);
607 }
608
609
610 /**
611  * Compare two strings for equality.
612  *
613  * @param s1 first string for comparison.
614  * @param s2 second string for comparison.
615  *
616  * @return 0 if the strings are the same, 1 or -1 if not.
617  */
618 static int
619 sb_strcmp (const struct StringBuffer *s1,
620            const struct StringBuffer *s2)
621 {
622   if (s1->slen != s2->slen)
623     return -1;
624   if (0 == s1->slen)
625     return 0;
626   return memcmp (s1->sbuf, s2->sbuf, s1->slen);
627 }
628
629
630 /**
631  * Reallocate the buffer of 'ret' to fit 'nlen' characters;
632  * move the existing string to the beginning of the new buffer.
633  *
634  * @param ret current buffer, to be updated
635  * @param nlen target length for the buffer, must be at least ret->slen
636  */
637 static void
638 sb_realloc (struct StringBuffer *ret,
639             size_t nlen)
640 {
641   char *old;
642
643   GNUNET_assert (nlen >= ret->slen);
644   old = ret->abuf;
645   ret->abuf = GNUNET_malloc (nlen);
646   ret->blen = nlen;
647   GNUNET_memcpy (ret->abuf,
648           ret->sbuf,
649           ret->slen);
650   ret->sbuf = ret->abuf;
651   GNUNET_free_non_null (old);
652 }
653
654
655 /**
656  * Append a string.
657  *
658  * @param ret where to write the result
659  * @param sarg string to append
660  */
661 static void
662 sb_append (struct StringBuffer *ret,
663            const struct StringBuffer *sarg)
664 {
665   if (GNUNET_YES == ret->null_flag)
666     ret->slen = 0;
667   ret->null_flag = GNUNET_NO;
668   if (ret->blen < sarg->slen + ret->slen)
669     sb_realloc (ret, ret->blen + sarg->slen + 128);
670   GNUNET_memcpy (&ret->sbuf[ret->slen],
671           sarg->sbuf,
672           sarg->slen);
673   ret->slen += sarg->slen;
674 }
675
676
677 /**
678  * Append a C string.
679  *
680  * @param ret where to write the result
681  * @param cstr string to append
682  */
683 static void
684 sb_append_cstr (struct StringBuffer *ret,
685                 const char *cstr)
686 {
687   size_t cstr_len = strlen (cstr);
688
689   if (GNUNET_YES == ret->null_flag)
690     ret->slen = 0;
691   ret->null_flag = GNUNET_NO;
692   if (ret->blen < cstr_len + ret->slen)
693     sb_realloc (ret, ret->blen + cstr_len + 128);
694   GNUNET_memcpy (&ret->sbuf[ret->slen],
695           cstr,
696           cstr_len);
697   ret->slen += cstr_len;
698 }
699
700
701 /**
702  * Wrap a string buffer, that is, set ret to the format string
703  * which contains an "%s" which is to be replaced with the original
704  * content of 'ret'.  Note that optimizing this function is not
705  * really worth it, it is rarely called.
706  *
707  * @param ret where to write the result and take the input for %.*s from
708  * @param format format string, fprintf-style, with exactly one "%.*s"
709  * @param extra_chars how long will the result be, in addition to 'sarg' length
710  */
711 static void
712 sb_wrap (struct StringBuffer *ret,
713          const char *format,
714          size_t extra_chars)
715 {
716   char *temp;
717
718   if (GNUNET_YES == ret->null_flag)
719     ret->slen = 0;
720   ret->null_flag = GNUNET_NO;
721   temp = GNUNET_malloc (ret->slen + extra_chars + 1);
722   GNUNET_snprintf (temp,
723                    ret->slen + extra_chars + 1,
724                    format,
725                    (int) ret->slen,
726                    ret->sbuf);
727   GNUNET_free_non_null (ret->abuf);
728   ret->abuf = temp;
729   ret->sbuf = temp;
730   ret->blen = ret->slen + extra_chars + 1;
731   ret->slen = ret->slen + extra_chars;
732 }
733
734
735 /**
736  * Format a string buffer.    Note that optimizing this function is not
737  * really worth it, it is rarely called.
738  *
739  * @param ret where to write the result
740  * @param format format string, fprintf-style, with exactly one "%.*s"
741  * @param extra_chars how long will the result be, in addition to 'sarg' length
742  * @param sarg string to print into the format
743  */
744 static void
745 sb_printf1 (struct StringBuffer *ret,
746             const char *format,
747             size_t extra_chars,
748             const struct StringBuffer *sarg)
749 {
750   if (ret->blen < sarg->slen + extra_chars + 1)
751     sb_realloc (ret,
752                 sarg->slen + extra_chars + 1);
753   ret->null_flag = GNUNET_NO;
754   ret->sbuf = ret->abuf;
755   ret->slen = sarg->slen + extra_chars;
756   GNUNET_snprintf (ret->sbuf,
757                    ret->blen,
758                    format,
759                    (int) sarg->slen,
760                    sarg->sbuf);
761 }
762
763
764 /**
765  * Format a string buffer.
766  *
767  * @param ret where to write the result
768  * @param format format string, fprintf-style, with exactly two "%.*s"
769  * @param extra_chars how long will the result be, in addition to 'sarg1/2' length
770  * @param sarg1 first string to print into the format
771  * @param sarg2 second string to print into the format
772  */
773 static void
774 sb_printf2 (struct StringBuffer *ret,
775             const char *format,
776             size_t extra_chars,
777             const struct StringBuffer *sarg1,
778             const struct StringBuffer *sarg2)
779 {
780   if (ret->blen < sarg1->slen + sarg2->slen + extra_chars + 1)
781     sb_realloc (ret,
782                 sarg1->slen + sarg2->slen + extra_chars + 1);
783   ret->null_flag = GNUNET_NO;
784   ret->slen = sarg1->slen + sarg2->slen + extra_chars;
785   ret->sbuf = ret->abuf;
786   GNUNET_snprintf (ret->sbuf,
787                    ret->blen,
788                    format,
789                    (int) sarg1->slen,
790                    sarg1->sbuf,
791                    (int) sarg2->slen,
792                    sarg2->sbuf);
793 }
794
795
796 /**
797  * Format a string buffer.     Note that optimizing this function is not
798  * really worth it, it is rarely called.
799  *
800  * @param ret where to write the result
801  * @param format format string, fprintf-style, with exactly three "%.*s"
802  * @param extra_chars how long will the result be, in addition to 'sarg1/2/3' length
803  * @param sarg1 first string to print into the format
804  * @param sarg2 second string to print into the format
805  * @param sarg3 third string to print into the format
806  */
807 static void
808 sb_printf3 (struct StringBuffer *ret,
809             const char *format,
810             size_t extra_chars,
811             const struct StringBuffer *sarg1,
812             const struct StringBuffer *sarg2,
813             const struct StringBuffer *sarg3)
814 {
815   if (ret->blen < sarg1->slen + sarg2->slen + sarg3->slen + extra_chars + 1)
816     sb_realloc (ret,
817                 sarg1->slen + sarg2->slen + sarg3->slen + extra_chars + 1);
818   ret->null_flag = GNUNET_NO;
819   ret->slen = sarg1->slen + sarg2->slen + sarg3->slen + extra_chars;
820   ret->sbuf = ret->abuf;
821   GNUNET_snprintf (ret->sbuf,
822                    ret->blen,
823                    format,
824                    (int) sarg1->slen,
825                    sarg1->sbuf,
826                    (int) sarg2->slen,
827                    sarg2->sbuf,
828                    (int) sarg3->slen,
829                    sarg3->sbuf);
830 }
831
832
833 /**
834  * Free resources of the given string buffer.
835  *
836  * @param sb buffer to free (actual pointer is not freed, as they
837  *        should not be individually allocated)
838  */
839 static void
840 sb_free (struct StringBuffer *sb)
841 {
842   GNUNET_array_grow (sb->abuf,
843                      sb->blen,
844                      0);
845   sb->slen = 0;
846   sb->sbuf = NULL;
847   sb->null_flag= GNUNET_YES;
848 }
849
850
851 /**
852  * Copy the given string buffer from 'in' to 'out'.
853  *
854  * @param in input string
855  * @param out output string
856  */
857 static void
858 sb_strdup (struct StringBuffer *out,
859            const struct StringBuffer *in)
860
861 {
862   out->null_flag = in->null_flag;
863   if (GNUNET_YES == out->null_flag)
864     return;
865   if (out->blen < in->slen)
866   {
867     GNUNET_array_grow (out->abuf,
868                        out->blen,
869                        in->slen);
870   }
871   out->sbuf = out->abuf;
872   out->slen = in->slen;
873   GNUNET_memcpy (out->sbuf, in->sbuf, out->slen);
874 }
875
876
877 /**
878  * Copy the given string buffer from 'in' to 'out'.
879  *
880  * @param cstr input string
881  * @param out output string
882  */
883 static void
884 sb_strdup_cstr (struct StringBuffer *out,
885                 const char *cstr)
886 {
887   if (NULL == cstr)
888   {
889     out->null_flag = GNUNET_YES;
890     return;
891   }
892   out->null_flag = GNUNET_NO;
893   out->slen = strlen (cstr);
894   if (out->blen < out->slen)
895   {
896     GNUNET_array_grow (out->abuf,
897                        out->blen,
898                        out->slen);
899   }
900   out->sbuf = out->abuf;
901   GNUNET_memcpy (out->sbuf, cstr, out->slen);
902 }
903
904
905 /**
906  * Check if the given string @a str needs parentheses around it when
907  * using it to generate a regex.
908  *
909  * @param str string
910  *
911  * @return #GNUNET_YES if parentheses are needed, #GNUNET_NO otherwise
912  */
913 static int
914 needs_parentheses (const struct StringBuffer *str)
915 {
916   size_t slen;
917   const char *op;
918   const char *cl;
919   const char *pos;
920   const char *end;
921   unsigned int cnt;
922
923   if ((GNUNET_YES == str->null_flag) || ((slen = str->slen) < 2))
924     return GNUNET_NO;
925   pos = str->sbuf;
926   if ('(' != pos[0])
927     return GNUNET_YES;
928   end = str->sbuf + slen;
929   cnt = 1;
930   pos++;
931   while (cnt > 0)
932   {
933     cl = memchr (pos, ')', end - pos);
934     if (NULL == cl)
935     {
936       GNUNET_break (0);
937       return GNUNET_YES;
938     }
939     /* while '(' before ')', count opening parens */
940     while ( (NULL != (op = memchr (pos, '(', end - pos)))  &&
941             (op < cl) )
942     {
943       cnt++;
944       pos = op + 1;
945     }
946     /* got ')' first */
947     cnt--;
948     pos = cl + 1;
949   }
950   return (*pos == '\0') ? GNUNET_NO : GNUNET_YES;
951 }
952
953
954 /**
955  * Remove parentheses surrounding string @a str.
956  * Example: "(a)" becomes "a", "(a|b)|(a|c)" stays the same.
957  * You need to #GNUNET_free() the returned string.
958  *
959  * @param str string, modified to contain a
960  * @return string without surrounding parentheses, string 'str' if no preceding
961  *         epsilon could be found, NULL if 'str' was NULL
962  */
963 static void
964 remove_parentheses (struct StringBuffer *str)
965 {
966   size_t slen;
967   const char *pos;
968   const char *end;
969   const char *sbuf;
970   const char *op;
971   const char *cp;
972   unsigned int cnt;
973
974   if (0)
975     return;
976   sbuf = str->sbuf;
977   if ( (GNUNET_YES == str->null_flag) ||
978        (1 >=  (slen = str->slen)) ||
979        ('(' != str->sbuf[0]) ||
980        (')' != str->sbuf[slen - 1]) )
981     return;
982   cnt = 0;
983   pos = &sbuf[1];
984   end = &sbuf[slen - 1];
985   op = memchr (pos, '(', end - pos);
986   cp = memchr (pos, ')', end - pos);
987   while (NULL != cp)
988   {
989     while ( (NULL != op) &&
990             (op < cp) )
991     {
992       cnt++;
993       pos = op + 1;
994       op = memchr (pos, '(', end - pos);
995     }
996     while ( (NULL != cp) &&
997             ( (NULL == op) ||
998               (cp < op) ) )
999     {
1000       if (0 == cnt)
1001         return; /* can't strip parens */
1002       cnt--;
1003       pos = cp + 1;
1004       cp = memchr (pos, ')', end - pos);
1005     }
1006   }
1007   if (0 != cnt)
1008   {
1009     GNUNET_break (0);
1010     return;
1011   }
1012   str->sbuf++;
1013   str->slen -= 2;
1014 }
1015
1016
1017 /**
1018  * Check if the string 'str' starts with an epsilon (empty string).
1019  * Example: "(|a)" is starting with an epsilon.
1020  *
1021  * @param str string to test
1022  *
1023  * @return 0 if str has no epsilon, 1 if str starts with '(|' and ends with ')'
1024  */
1025 static int
1026 has_epsilon (const struct StringBuffer *str)
1027 {
1028   return
1029     (GNUNET_YES != str->null_flag) &&
1030     (0 < str->slen) &&
1031     ('(' == str->sbuf[0]) &&
1032     ('|' == str->sbuf[1]) &&
1033     (')' == str->sbuf[str->slen - 1]);
1034 }
1035
1036
1037 /**
1038  * Remove an epsilon from the string str. Where epsilon is an empty string
1039  * Example: str = "(|a|b|c)", result: "a|b|c"
1040  * The returned string needs to be freed.
1041  *
1042  * @param str original string
1043  * @param ret where to return string without preceding epsilon, string 'str' if no preceding
1044  *         epsilon could be found, NULL if 'str' was NULL
1045  */
1046 static void
1047 remove_epsilon (const struct StringBuffer *str,
1048                 struct StringBuffer *ret)
1049 {
1050   if (GNUNET_YES == str->null_flag)
1051   {
1052     ret->null_flag = GNUNET_YES;
1053     return;
1054   }
1055   if ( (str->slen > 1) &&
1056        ('(' == str->sbuf[0]) &&
1057        ('|' == str->sbuf[1]) &&
1058        (')' == str->sbuf[str->slen - 1]) )
1059   {
1060     /* remove epsilon */
1061     if (ret->blen < str->slen - 3)
1062     {
1063       GNUNET_array_grow (ret->abuf,
1064                          ret->blen,
1065                          str->slen - 3);
1066     }
1067     ret->sbuf = ret->abuf;
1068     ret->slen = str->slen - 3;
1069     GNUNET_memcpy (ret->sbuf, &str->sbuf[2], ret->slen);
1070     return;
1071   }
1072   sb_strdup (ret, str);
1073 }
1074
1075
1076 /**
1077  * Compare n bytes of 'str1' and 'str2'
1078  *
1079  * @param str1 first string to compare
1080  * @param str2 second string for comparison
1081  * @param n number of bytes to compare
1082  *
1083  * @return -1 if any of the strings is NULL, 0 if equal, non 0 otherwise
1084  */
1085 static int
1086 sb_strncmp (const struct StringBuffer *str1,
1087             const struct StringBuffer *str2, size_t n)
1088 {
1089   size_t max;
1090
1091   if ( (str1->slen != str2->slen) &&
1092        ( (str1->slen < n) ||
1093          (str2->slen < n) ) )
1094     return -1;
1095   max = GNUNET_MAX (str1->slen, str2->slen);
1096   if (max > n)
1097     max = n;
1098   return memcmp (str1->sbuf, str2->sbuf, max);
1099 }
1100
1101
1102 /**
1103  * Compare n bytes of 'str1' and 'str2'
1104  *
1105  * @param str1 first string to compare
1106  * @param str2 second C string for comparison
1107  * @param n number of bytes to compare (and length of str2)
1108  *
1109  * @return -1 if any of the strings is NULL, 0 if equal, non 0 otherwise
1110  */
1111 static int
1112 sb_strncmp_cstr (const struct StringBuffer *str1,
1113                  const char *str2, size_t n)
1114 {
1115   if (str1->slen < n)
1116     return -1;
1117   return memcmp (str1->sbuf, str2, n);
1118 }
1119
1120
1121 /**
1122  * Initialize string buffer for storing strings of up to n
1123  * characters.
1124  *
1125  * @param sb buffer to initialize
1126  * @param n desired target length
1127  */
1128 static void
1129 sb_init (struct StringBuffer *sb,
1130          size_t n)
1131 {
1132   sb->null_flag = GNUNET_NO;
1133   sb->abuf = sb->sbuf = (0 == n) ? NULL : GNUNET_malloc (n);
1134   sb->blen = n;
1135   sb->slen = 0;
1136 }
1137
1138
1139 /**
1140  * Compare 'str1', starting from position 'k',  with whole 'str2'
1141  *
1142  * @param str1 first string to compare, starting from position 'k'
1143  * @param str2 second string for comparison
1144  * @param k starting position in 'str1'
1145  *
1146  * @return -1 if any of the strings is NULL, 0 if equal, non 0 otherwise
1147  */
1148 static int
1149 sb_strkcmp (const struct StringBuffer *str1,
1150             const struct StringBuffer *str2, size_t k)
1151 {
1152   if ( (GNUNET_YES == str1->null_flag) ||
1153        (GNUNET_YES == str2->null_flag) ||
1154        (k > str1->slen) ||
1155        (str1->slen - k != str2->slen) )
1156     return -1;
1157   return memcmp (&str1->sbuf[k], str2->sbuf, str2->slen);
1158 }
1159
1160
1161 /**
1162  * Helper function used as 'action' in 'REGEX_INTERNAL_automaton_traverse'
1163  * function to create the depth-first numbering of the states.
1164  *
1165  * @param cls states array.
1166  * @param count current state counter.
1167  * @param s current state.
1168  */
1169 static void
1170 number_states (void *cls, const unsigned int count,
1171                struct REGEX_INTERNAL_State *s)
1172 {
1173   struct REGEX_INTERNAL_State **states = cls;
1174
1175   s->dfs_id = count;
1176   if (NULL != states)
1177     states[count] = s;
1178 }
1179
1180
1181
1182 #define PRIS(a) \
1183   ((GNUNET_YES == a.null_flag) ? 6 : (int) a.slen), \
1184   ((GNUNET_YES == a.null_flag) ? "(null)" : a.sbuf)
1185
1186
1187 /**
1188  * Construct the regular expression given the inductive step,
1189  * $R^{(k)}_{ij} = R^{(k-1)}_{ij} | R^{(k-1)}_{ik} ( R^{(k-1)}_{kk} )^*
1190  * R^{(k-1)}_{kj}, and simplify the resulting expression saved in R_cur_ij.
1191  *
1192  * @param R_last_ij value of  $R^{(k-1)_{ij}.
1193  * @param R_last_ik value of  $R^{(k-1)_{ik}.
1194  * @param R_last_kk value of  $R^{(k-1)_{kk}.
1195  * @param R_last_kj value of  $R^{(k-1)_{kj}.
1196  * @param R_cur_ij result for this inductive step is saved in R_cur_ij, R_cur_ij
1197  *                 is expected to be NULL when called!
1198  * @param R_cur_l optimization -- kept between iterations to avoid realloc
1199  * @param R_cur_r optimization -- kept between iterations to avoid realloc
1200  */
1201 static void
1202 automaton_create_proofs_simplify (const struct StringBuffer *R_last_ij,
1203                                   const struct StringBuffer *R_last_ik,
1204                                   const struct StringBuffer *R_last_kk,
1205                                   const struct StringBuffer *R_last_kj,
1206                                   struct StringBuffer *R_cur_ij,
1207                                   struct StringBuffer *R_cur_l,
1208                                   struct StringBuffer *R_cur_r)
1209 {
1210   struct StringBuffer R_temp_ij;
1211   struct StringBuffer R_temp_ik;
1212   struct StringBuffer R_temp_kj;
1213   struct StringBuffer R_temp_kk;
1214   int eps_check;
1215   int ij_ik_cmp;
1216   int ij_kj_cmp;
1217   int ik_kk_cmp;
1218   int kk_kj_cmp;
1219   int clean_ik_kk_cmp;
1220   int clean_kk_kj_cmp;
1221   size_t length;
1222   size_t length_l;
1223   size_t length_r;
1224
1225   /*
1226    * $R^{(k)}_{ij} = R^{(k-1)}_{ij} | R^{(k-1)}_{ik} ( R^{(k-1)}_{kk} )^* R^{(k-1)}_{kj}
1227    * R_last == R^{(k-1)}, R_cur == R^{(k)}
1228    * R_cur_ij = R_cur_l | R_cur_r
1229    * R_cur_l == R^{(k-1)}_{ij}
1230    * R_cur_r == R^{(k-1)}_{ik} ( R^{(k-1)}_{kk} )^* R^{(k-1)}_{kj}
1231    */
1232
1233   if ( (GNUNET_YES == R_last_ij->null_flag) &&
1234        ( (GNUNET_YES == R_last_ik->null_flag) ||
1235          (GNUNET_YES == R_last_kj->null_flag)))
1236   {
1237     /* R^{(k)}_{ij} = N | N */
1238     R_cur_ij->null_flag = GNUNET_YES;
1239     R_cur_ij->synced = GNUNET_NO;
1240     return;
1241   }
1242
1243   if ( (GNUNET_YES == R_last_ik->null_flag) ||
1244        (GNUNET_YES == R_last_kj->null_flag) )
1245   {
1246     /*  R^{(k)}_{ij} = R^{(k-1)}_{ij} | N */
1247     if (GNUNET_YES == R_last_ij->synced)
1248     {
1249       R_cur_ij->synced = GNUNET_YES;
1250       R_cur_ij->null_flag = GNUNET_NO;
1251       return;
1252     }
1253     R_cur_ij->synced = GNUNET_YES;
1254     sb_strdup (R_cur_ij, R_last_ij);
1255     return;
1256   }
1257   R_cur_ij->synced = GNUNET_NO;
1258
1259   /* $R^{(k)}_{ij} = N | R^{(k-1)}_{ik} ( R^{(k-1)}_{kk} )^* R^{(k-1)}_{kj} OR
1260    * $R^{(k)}_{ij} = R^{(k-1)}_{ij} | R^{(k-1)}_{ik} ( R^{(k-1)}_{kk} )^* R^{(k-1)}_{kj} */
1261
1262   R_cur_r->null_flag = GNUNET_YES;
1263   R_cur_r->slen = 0;
1264   R_cur_l->null_flag = GNUNET_YES;
1265   R_cur_l->slen = 0;
1266
1267   /* cache results from strcmp, we might need these many times */
1268   ij_kj_cmp = sb_nullstrcmp (R_last_ij, R_last_kj);
1269   ij_ik_cmp = sb_nullstrcmp (R_last_ij, R_last_ik);
1270   ik_kk_cmp = sb_nullstrcmp (R_last_ik, R_last_kk);
1271   kk_kj_cmp = sb_nullstrcmp (R_last_kk, R_last_kj);
1272
1273   /* Assign R_temp_(ik|kk|kj) to R_last[][] and remove epsilon as well
1274    * as parentheses, so we can better compare the contents */
1275
1276   memset (&R_temp_ij, 0, sizeof (struct StringBuffer));
1277   memset (&R_temp_ik, 0, sizeof (struct StringBuffer));
1278   memset (&R_temp_kk, 0, sizeof (struct StringBuffer));
1279   memset (&R_temp_kj, 0, sizeof (struct StringBuffer));
1280   remove_epsilon (R_last_ik, &R_temp_ik);
1281   remove_epsilon (R_last_kk, &R_temp_kk);
1282   remove_epsilon (R_last_kj, &R_temp_kj);
1283   remove_parentheses (&R_temp_ik);
1284   remove_parentheses (&R_temp_kk);
1285   remove_parentheses (&R_temp_kj);
1286   clean_ik_kk_cmp = sb_nullstrcmp (R_last_ik, &R_temp_kk);
1287   clean_kk_kj_cmp = sb_nullstrcmp (&R_temp_kk, R_last_kj);
1288
1289   /* construct R_cur_l (and, if necessary R_cur_r) */
1290   if (GNUNET_YES != R_last_ij->null_flag)
1291   {
1292     /* Assign R_temp_ij to R_last_ij and remove epsilon as well
1293      * as parentheses, so we can better compare the contents */
1294     remove_epsilon (R_last_ij, &R_temp_ij);
1295     remove_parentheses (&R_temp_ij);
1296
1297     if ( (0 == sb_strcmp (&R_temp_ij, &R_temp_ik)) &&
1298          (0 == sb_strcmp (&R_temp_ik, &R_temp_kk)) &&
1299          (0 == sb_strcmp (&R_temp_kk, &R_temp_kj)) )
1300     {
1301       if (0 == R_temp_ij.slen)
1302       {
1303         R_cur_r->null_flag = GNUNET_NO;
1304       }
1305       else if ((0 == sb_strncmp_cstr (R_last_ij, "(|", 2)) ||
1306                (0 == sb_strncmp_cstr (R_last_ik, "(|", 2) &&
1307                 0 == sb_strncmp_cstr (R_last_kj, "(|", 2)))
1308       {
1309         /*
1310          * a|(e|a)a*(e|a) = a*
1311          * a|(e|a)(e|a)*(e|a) = a*
1312          * (e|a)|aa*a = a*
1313          * (e|a)|aa*(e|a) = a*
1314          * (e|a)|(e|a)a*a = a*
1315          * (e|a)|(e|a)a*(e|a) = a*
1316          * (e|a)|(e|a)(e|a)*(e|a) = a*
1317          */
1318         if (GNUNET_YES == needs_parentheses (&R_temp_ij))
1319           sb_printf1 (R_cur_r, "(%.*s)*", 3, &R_temp_ij);
1320         else
1321           sb_printf1 (R_cur_r, "%.*s*", 1, &R_temp_ij);
1322       }
1323       else
1324       {
1325         /*
1326          * a|aa*a = a+
1327          * a|(e|a)a*a = a+
1328          * a|aa*(e|a) = a+
1329          * a|(e|a)(e|a)*a = a+
1330          * a|a(e|a)*(e|a) = a+
1331          */
1332         if (GNUNET_YES == needs_parentheses (&R_temp_ij))
1333           sb_printf1 (R_cur_r, "(%.*s)+", 3, &R_temp_ij);
1334         else
1335           sb_printf1 (R_cur_r, "%.*s+", 1, &R_temp_ij);
1336       }
1337     }
1338     else if ( (0 == ij_ik_cmp) && (0 == clean_kk_kj_cmp) && (0 != clean_ik_kk_cmp) )
1339     {
1340       /* a|ab*b = ab* */
1341       if (0 == R_last_kk->slen)
1342         sb_strdup (R_cur_r, R_last_ij);
1343       else if (GNUNET_YES == needs_parentheses (&R_temp_kk))
1344         sb_printf2 (R_cur_r, "%.*s(%.*s)*", 3, R_last_ij, &R_temp_kk);
1345       else
1346         sb_printf2 (R_cur_r, "%.*s%.*s*", 1, R_last_ij, R_last_kk);
1347       R_cur_l->null_flag = GNUNET_YES;
1348     }
1349     else if ( (0 == ij_kj_cmp) && (0 == clean_ik_kk_cmp) && (0 != clean_kk_kj_cmp))
1350     {
1351       /* a|bb*a = b*a */
1352       if (R_last_kk->slen < 1)
1353       {
1354         sb_strdup (R_cur_r, R_last_kj);
1355       }
1356       else if (GNUNET_YES == needs_parentheses (&R_temp_kk))
1357         sb_printf2 (R_cur_r, "(%.*s)*%.*s", 3, &R_temp_kk, R_last_kj);
1358       else
1359         sb_printf2 (R_cur_r, "%.*s*%.*s", 1, &R_temp_kk, R_last_kj);
1360
1361       R_cur_l->null_flag = GNUNET_YES;
1362     }
1363     else if ( (0 == ij_ik_cmp) && (0 == kk_kj_cmp) && (! has_epsilon (R_last_ij)) &&
1364               has_epsilon (R_last_kk))
1365     {
1366       /* a|a(e|b)*(e|b) = a|ab* = a|a|ab|abb|abbb|... = ab* */
1367       if (needs_parentheses (&R_temp_kk))
1368         sb_printf2 (R_cur_r, "%.*s(%.*s)*", 3, R_last_ij, &R_temp_kk);
1369       else
1370         sb_printf2 (R_cur_r, "%.*s%.*s*", 1, R_last_ij, &R_temp_kk);
1371       R_cur_l->null_flag = GNUNET_YES;
1372     }
1373     else if ( (0 == ij_kj_cmp) && (0 == ik_kk_cmp) && (! has_epsilon (R_last_ij)) &&
1374              has_epsilon (R_last_kk))
1375     {
1376       /* a|(e|b)(e|b)*a = a|b*a = a|a|ba|bba|bbba|...  = b*a */
1377       if (needs_parentheses (&R_temp_kk))
1378         sb_printf2 (R_cur_r, "(%.*s)*%.*s", 3, &R_temp_kk, R_last_ij);
1379       else
1380         sb_printf2 (R_cur_r, "%.*s*%.*s", 1, &R_temp_kk, R_last_ij);
1381       R_cur_l->null_flag = GNUNET_YES;
1382     }
1383     else
1384     {
1385       sb_strdup (R_cur_l, R_last_ij);
1386       remove_parentheses (R_cur_l);
1387     }
1388   }
1389   else
1390   {
1391     /* we have no left side */
1392     R_cur_l->null_flag = GNUNET_YES;
1393   }
1394
1395   /* construct R_cur_r, if not already constructed */
1396   if (GNUNET_YES == R_cur_r->null_flag)
1397   {
1398     length = R_temp_kk.slen - R_last_ik->slen;
1399
1400     /* a(ba)*bx = (ab)+x */
1401     if ( (length > 0) &&
1402          (GNUNET_YES != R_last_kk->null_flag) &&
1403          (0 < R_last_kk->slen) &&
1404          (GNUNET_YES != R_last_kj->null_flag) &&
1405          (0 < R_last_kj->slen) &&
1406          (GNUNET_YES != R_last_ik->null_flag) &&
1407          (0 < R_last_ik->slen) &&
1408          (0 == sb_strkcmp (&R_temp_kk, R_last_ik, length)) &&
1409          (0 == sb_strncmp (&R_temp_kk, R_last_kj, length)) )
1410     {
1411       struct StringBuffer temp_a;
1412       struct StringBuffer temp_b;
1413
1414       sb_init (&temp_a, length);
1415       sb_init (&temp_b, R_last_kj->slen - length);
1416
1417       length_l = length;
1418       temp_a.sbuf = temp_a.abuf;
1419       GNUNET_memcpy (temp_a.sbuf, R_last_kj->sbuf, length_l);
1420       temp_a.slen = length_l;
1421
1422       length_r = R_last_kj->slen - length;
1423       temp_b.sbuf = temp_b.abuf;
1424       GNUNET_memcpy (temp_b.sbuf, &R_last_kj->sbuf[length], length_r);
1425       temp_b.slen = length_r;
1426
1427       /* e|(ab)+ = (ab)* */
1428       if ( (GNUNET_YES != R_cur_l->null_flag) &&
1429            (0 == R_cur_l->slen) &&
1430            (0 == temp_b.slen) )
1431       {
1432         sb_printf2 (R_cur_r, "(%.*s%.*s)*", 3, R_last_ik, &temp_a);
1433         sb_free (R_cur_l);
1434         R_cur_l->null_flag = GNUNET_YES;
1435       }
1436       else
1437       {
1438         sb_printf3 (R_cur_r, "(%.*s%.*s)+%.*s", 3, R_last_ik, &temp_a, &temp_b);
1439       }
1440       sb_free (&temp_a);
1441       sb_free (&temp_b);
1442     }
1443     else if (0 == sb_strcmp (&R_temp_ik, &R_temp_kk) &&
1444              0 == sb_strcmp (&R_temp_kk, &R_temp_kj))
1445     {
1446       /*
1447        * (e|a)a*(e|a) = a*
1448        * (e|a)(e|a)*(e|a) = a*
1449        */
1450       if (has_epsilon (R_last_ik) && has_epsilon (R_last_kj))
1451       {
1452         if (needs_parentheses (&R_temp_kk))
1453           sb_printf1 (R_cur_r, "(%.*s)*", 3, &R_temp_kk);
1454         else
1455           sb_printf1 (R_cur_r, "%.*s*", 1, &R_temp_kk);
1456       }
1457       /* aa*a = a+a */
1458       else if ( (0 == clean_ik_kk_cmp) &&
1459                 (0 == clean_kk_kj_cmp) &&
1460                 (! has_epsilon (R_last_ik)) )
1461       {
1462         if (needs_parentheses (&R_temp_kk))
1463           sb_printf2 (R_cur_r, "(%.*s)+%.*s", 3, &R_temp_kk, &R_temp_kk);
1464         else
1465           sb_printf2 (R_cur_r, "%.*s+%.*s", 1, &R_temp_kk, &R_temp_kk);
1466       }
1467       /*
1468        * (e|a)a*a = a+
1469        * aa*(e|a) = a+
1470        * a(e|a)*(e|a) = a+
1471        * (e|a)a*a = a+
1472        */
1473       else
1474       {
1475         eps_check =
1476           (has_epsilon (R_last_ik) + has_epsilon (R_last_kk) +
1477            has_epsilon (R_last_kj));
1478
1479         if (1 == eps_check)
1480         {
1481           if (needs_parentheses (&R_temp_kk))
1482             sb_printf1 (R_cur_r, "(%.*s)+", 3, &R_temp_kk);
1483           else
1484             sb_printf1 (R_cur_r, "%.*s+", 1, &R_temp_kk);
1485         }
1486       }
1487     }
1488     /*
1489      * aa*b = a+b
1490      * (e|a)(e|a)*b = a*b
1491      */
1492     else if (0 == sb_strcmp (&R_temp_ik, &R_temp_kk))
1493     {
1494       if (has_epsilon (R_last_ik))
1495       {
1496         if (needs_parentheses (&R_temp_kk))
1497           sb_printf2 (R_cur_r, "(%.*s)*%.*s", 3, &R_temp_kk, R_last_kj);
1498         else
1499           sb_printf2 (R_cur_r, "%.*s*%.*s", 1, &R_temp_kk, R_last_kj);
1500       }
1501       else
1502       {
1503         if (needs_parentheses (&R_temp_kk))
1504           sb_printf2 (R_cur_r, "(%.*s)+%.*s", 3, &R_temp_kk, R_last_kj);
1505         else
1506           sb_printf2 (R_cur_r, "%.*s+%.*s", 1, &R_temp_kk, R_last_kj);
1507       }
1508     }
1509     /*
1510      * ba*a = ba+
1511      * b(e|a)*(e|a) = ba*
1512      */
1513     else if (0 == sb_strcmp (&R_temp_kk, &R_temp_kj))
1514     {
1515       if (has_epsilon (R_last_kj))
1516       {
1517         if (needs_parentheses (&R_temp_kk))
1518           sb_printf2 (R_cur_r, "%.*s(%.*s)*", 3, R_last_ik, &R_temp_kk);
1519         else
1520           sb_printf2 (R_cur_r, "%.*s%.*s*", 1, R_last_ik, &R_temp_kk);
1521       }
1522       else
1523       {
1524         if (needs_parentheses (&R_temp_kk))
1525           sb_printf2 (R_cur_r, "(%.*s)+%.*s", 3, R_last_ik, &R_temp_kk);
1526         else
1527           sb_printf2 (R_cur_r, "%.*s+%.*s", 1, R_last_ik, &R_temp_kk);
1528       }
1529     }
1530     else
1531     {
1532       if (0 < R_temp_kk.slen)
1533       {
1534         if (needs_parentheses (&R_temp_kk))
1535         {
1536           sb_printf3 (R_cur_r, "%.*s(%.*s)*%.*s", 3, R_last_ik, &R_temp_kk,
1537                       R_last_kj);
1538         }
1539         else
1540         {
1541           sb_printf3 (R_cur_r, "%.*s%.*s*%.*s", 1, R_last_ik, &R_temp_kk,
1542                       R_last_kj);
1543         }
1544       }
1545       else
1546       {
1547         sb_printf2 (R_cur_r, "%.*s%.*s", 0, R_last_ik, R_last_kj);
1548       }
1549     }
1550   }
1551   sb_free (&R_temp_ij);
1552   sb_free (&R_temp_ik);
1553   sb_free (&R_temp_kk);
1554   sb_free (&R_temp_kj);
1555
1556   if ( (GNUNET_YES == R_cur_l->null_flag) &&
1557        (GNUNET_YES == R_cur_r->null_flag) )
1558   {
1559     R_cur_ij->null_flag = GNUNET_YES;
1560     return;
1561   }
1562
1563   if ( (GNUNET_YES != R_cur_l->null_flag) &&
1564        (GNUNET_YES == R_cur_r->null_flag) )
1565   {
1566     struct StringBuffer tmp;
1567
1568     tmp = *R_cur_ij;
1569     *R_cur_ij = *R_cur_l;
1570     *R_cur_l = tmp;
1571     return;
1572   }
1573
1574   if ( (GNUNET_YES == R_cur_l->null_flag) &&
1575        (GNUNET_YES != R_cur_r->null_flag) )
1576   {
1577     struct StringBuffer tmp;
1578
1579     tmp = *R_cur_ij;
1580     *R_cur_ij = *R_cur_r;
1581     *R_cur_r = tmp;
1582     return;
1583   }
1584
1585   if (0 == sb_nullstrcmp (R_cur_l, R_cur_r))
1586   {
1587     struct StringBuffer tmp;
1588
1589     tmp = *R_cur_ij;
1590     *R_cur_ij = *R_cur_l;
1591     *R_cur_l = tmp;
1592     return;
1593   }
1594   sb_printf2 (R_cur_ij, "(%.*s|%.*s)", 3, R_cur_l, R_cur_r);
1595 }
1596
1597
1598 /**
1599  * Create proofs for all states in the given automaton. Implementation of the
1600  * algorithm descriped in chapter 3.2.1 of "Automata Theory, Languages, and
1601  * Computation 3rd Edition" by Hopcroft, Motwani and Ullman.
1602  *
1603  * Each state in the automaton gets assigned 'proof' and 'hash' (hash of the
1604  * proof) fields. The starting state will only have a valid proof/hash if it has
1605  * any incoming transitions.
1606  *
1607  * @param a automaton for which to assign proofs and hashes, must not be NULL
1608  */
1609 static int
1610 automaton_create_proofs (struct REGEX_INTERNAL_Automaton *a)
1611 {
1612   unsigned int n = a->state_count;
1613   struct REGEX_INTERNAL_State *states[n];
1614   struct StringBuffer *R_last;
1615   struct StringBuffer *R_cur;
1616   struct StringBuffer R_cur_r;
1617   struct StringBuffer R_cur_l;
1618   struct StringBuffer *R_swap;
1619   struct REGEX_INTERNAL_Transition *t;
1620   struct StringBuffer complete_regex;
1621   unsigned int i;
1622   unsigned int j;
1623   unsigned int k;
1624
1625   R_last = GNUNET_malloc_large (sizeof (struct StringBuffer) * n * n);
1626   R_cur = GNUNET_malloc_large (sizeof (struct StringBuffer) * n * n);
1627   if ( (NULL == R_last) ||
1628        (NULL == R_cur) )
1629   {
1630     GNUNET_log_strerror (GNUNET_ERROR_TYPE_ERROR, "malloc");
1631     GNUNET_free_non_null (R_cur);
1632     GNUNET_free_non_null (R_last);
1633     return GNUNET_SYSERR;
1634   }
1635
1636   /* create depth-first numbering of the states, initializes 'state' */
1637   REGEX_INTERNAL_automaton_traverse (a, a->start, NULL, NULL, &number_states,
1638                                    states);
1639
1640   for (i = 0; i < n; i++)
1641     GNUNET_assert (NULL != states[i]);
1642   for (i = 0; i < n; i++)
1643     for (j = 0; j < n; j++)
1644       R_last[i *n + j].null_flag = GNUNET_YES;
1645
1646   /* Compute regular expressions of length "1" between each pair of states */
1647   for (i = 0; i < n; i++)
1648   {
1649     for (t = states[i]->transitions_head; NULL != t; t = t->next)
1650     {
1651       j = t->to_state->dfs_id;
1652       if (GNUNET_YES == R_last[i * n + j].null_flag)
1653       {
1654         sb_strdup_cstr (&R_last[i * n + j], t->label);
1655       }
1656       else
1657       {
1658         sb_append_cstr (&R_last[i * n + j], "|");
1659         sb_append_cstr (&R_last[i * n + j], t->label);
1660       }
1661     }
1662     /* add self-loop: i is reachable from i via epsilon-transition */
1663     if (GNUNET_YES == R_last[i * n + i].null_flag)
1664     {
1665       R_last[i * n + i].slen = 0;
1666       R_last[i * n + i].null_flag = GNUNET_NO;
1667     }
1668     else
1669     {
1670       sb_wrap (&R_last[i * n + i], "(|%.*s)", 3);
1671     }
1672   }
1673   for (i = 0; i < n; i++)
1674     for (j = 0; j < n; j++)
1675       if (needs_parentheses (&R_last[i * n + j]))
1676         sb_wrap (&R_last[i * n + j], "(%.*s)", 2);
1677   /* Compute regular expressions of length "k" between each pair of states per
1678    * induction */
1679   memset (&R_cur_l, 0, sizeof (struct StringBuffer));
1680   memset (&R_cur_r, 0, sizeof (struct StringBuffer));
1681   for (k = 0; k < n; k++)
1682   {
1683     for (i = 0; i < n; i++)
1684     {
1685       for (j = 0; j < n; j++)
1686       {
1687         /* Basis for the recursion:
1688          * $R^{(k)}_{ij} = R^{(k-1)}_{ij} | R^{(k-1)}_{ik} ( R^{(k-1)}_{kk} )^* R^{(k-1)}_{kj}
1689          * R_last == R^{(k-1)}, R_cur == R^{(k)}
1690          */
1691
1692         /* Create R_cur[i][j] and simplify the expression */
1693         automaton_create_proofs_simplify (&R_last[i * n + j], &R_last[i * n + k],
1694                                           &R_last[k * n + k], &R_last[k * n + j],
1695                                           &R_cur[i * n + j],
1696                                           &R_cur_l, &R_cur_r);
1697       }
1698     }
1699     /* set R_last = R_cur */
1700     R_swap = R_last;
1701     R_last = R_cur;
1702     R_cur = R_swap;
1703     /* clear 'R_cur' for next iteration */
1704     for (i = 0; i < n; i++)
1705       for (j = 0; j < n; j++)
1706         R_cur[i * n + j].null_flag = GNUNET_YES;
1707   }
1708   sb_free (&R_cur_l);
1709   sb_free (&R_cur_r);
1710   /* assign proofs and hashes */
1711   for (i = 0; i < n; i++)
1712   {
1713     if (GNUNET_YES != R_last[a->start->dfs_id * n + i].null_flag)
1714     {
1715       states[i]->proof = GNUNET_strndup (R_last[a->start->dfs_id * n + i].sbuf,
1716                                          R_last[a->start->dfs_id * n + i].slen);
1717       GNUNET_CRYPTO_hash (states[i]->proof, strlen (states[i]->proof),
1718                           &states[i]->hash);
1719     }
1720   }
1721
1722   /* complete regex for whole DFA: union of all pairs (start state/accepting
1723    * state(s)). */
1724   sb_init (&complete_regex, 16 * n);
1725   for (i = 0; i < n; i++)
1726   {
1727     if (states[i]->accepting)
1728     {
1729       if ( (0 == complete_regex.slen) &&
1730            (0 < R_last[a->start->dfs_id * n + i].slen) )
1731       {
1732         sb_append (&complete_regex,
1733                    &R_last[a->start->dfs_id * n + i]);
1734       }
1735       else if ( (GNUNET_YES != R_last[a->start->dfs_id * n + i].null_flag) &&
1736                 (0 < R_last[a->start->dfs_id * n + i].slen) )
1737       {
1738         sb_append_cstr (&complete_regex, "|");
1739         sb_append (&complete_regex,
1740                    &R_last[a->start->dfs_id * n + i]);
1741       }
1742     }
1743   }
1744   a->canonical_regex = GNUNET_strndup (complete_regex.sbuf, complete_regex.slen);
1745
1746   /* cleanup */
1747   sb_free (&complete_regex);
1748   for (i = 0; i < n; i++)
1749     for (j = 0; j < n; j++)
1750     {
1751       sb_free (&R_cur[i * n + j]);
1752       sb_free (&R_last[i * n + j]);
1753     }
1754   GNUNET_free (R_cur);
1755   GNUNET_free (R_last);
1756   return GNUNET_OK;
1757 }
1758
1759
1760 /**
1761  * Creates a new DFA state based on a set of NFA states. Needs to be freed using
1762  * automaton_destroy_state.
1763  *
1764  * @param ctx context
1765  * @param nfa_states set of NFA states on which the DFA should be based on
1766  *
1767  * @return new DFA state
1768  */
1769 static struct REGEX_INTERNAL_State *
1770 dfa_state_create (struct REGEX_INTERNAL_Context *ctx,
1771                   struct REGEX_INTERNAL_StateSet *nfa_states)
1772 {
1773   struct REGEX_INTERNAL_State *s;
1774   char *pos;
1775   size_t len;
1776   struct REGEX_INTERNAL_State *cstate;
1777   struct REGEX_INTERNAL_Transition *ctran;
1778   unsigned int i;
1779
1780   s = GNUNET_new (struct REGEX_INTERNAL_State);
1781   s->id = ctx->state_id++;
1782   s->index = -1;
1783   s->lowlink = -1;
1784
1785   if (NULL == nfa_states)
1786   {
1787     GNUNET_asprintf (&s->name, "s%i", s->id);
1788     return s;
1789   }
1790
1791   s->nfa_set = *nfa_states;
1792
1793   if (nfa_states->off < 1)
1794     return s;
1795
1796   /* Create a name based on 'nfa_states' */
1797   len = nfa_states->off * 14 + 4;
1798   s->name = GNUNET_malloc (len);
1799   strcat (s->name, "{");
1800   pos = s->name + 1;
1801
1802   for (i = 0; i < nfa_states->off; i++)
1803   {
1804     cstate = nfa_states->states[i];
1805     GNUNET_snprintf (pos,
1806                      pos - s->name + len,
1807                      "%i,",
1808                      cstate->id);
1809     pos += strlen (pos);
1810
1811     /* Add a transition for each distinct label to NULL state */
1812     for (ctran = cstate->transitions_head; NULL != ctran; ctran = ctran->next)
1813       if (NULL != ctran->label)
1814         state_add_transition (ctx, s, ctran->label, NULL);
1815
1816     /* If the nfa_states contain an accepting state, the new dfa state is also
1817      * accepting. */
1818     if (cstate->accepting)
1819       s->accepting = 1;
1820   }
1821   pos[-1] = '}';
1822   s->name = GNUNET_realloc (s->name, strlen (s->name) + 1);
1823
1824   memset (nfa_states, 0, sizeof (struct REGEX_INTERNAL_StateSet));
1825   return s;
1826 }
1827
1828
1829 /**
1830  * Move from the given state 's' to the next state on transition 'str'. Consumes
1831  * as much of the given 'str' as possible (usefull for strided DFAs). On return
1832  * 's' will point to the next state, and the length of the substring used for
1833  * this transition will be returned. If no transition possible 0 is returned and
1834  * 's' points to NULL.
1835  *
1836  * @param s starting state, will point to the next state or NULL (if no
1837  * transition possible)
1838  * @param str edge label to follow (will match longest common prefix)
1839  *
1840  * @return length of the substring comsumed from 'str'
1841  */
1842 static unsigned int
1843 dfa_move (struct REGEX_INTERNAL_State **s, const char *str)
1844 {
1845   struct REGEX_INTERNAL_Transition *t;
1846   struct REGEX_INTERNAL_State *new_s;
1847   unsigned int len;
1848   unsigned int max_len;
1849
1850   if (NULL == s)
1851     return 0;
1852
1853   new_s = NULL;
1854   max_len = 0;
1855   for (t = (*s)->transitions_head; NULL != t; t = t->next)
1856   {
1857     len = strlen (t->label);
1858
1859     if (0 == strncmp (t->label, str, len))
1860     {
1861       if (len >= max_len)
1862       {
1863         max_len = len;
1864         new_s = t->to_state;
1865       }
1866     }
1867   }
1868
1869   *s = new_s;
1870   return max_len;
1871 }
1872
1873
1874 /**
1875  * Set the given state 'marked' to #GNUNET_YES. Used by the
1876  * #dfa_remove_unreachable_states() function to detect unreachable states in the
1877  * automaton.
1878  *
1879  * @param cls closure, not used.
1880  * @param count count, not used.
1881  * @param s state where the marked attribute will be set to #GNUNET_YES.
1882  */
1883 static void
1884 mark_states (void *cls,
1885              const unsigned int count,
1886              struct REGEX_INTERNAL_State *s)
1887 {
1888   s->marked = GNUNET_YES;
1889 }
1890
1891
1892 /**
1893  * Remove all unreachable states from DFA 'a'. Unreachable states are those
1894  * states that are not reachable from the starting state.
1895  *
1896  * @param a DFA automaton
1897  */
1898 static void
1899 dfa_remove_unreachable_states (struct REGEX_INTERNAL_Automaton *a)
1900 {
1901   struct REGEX_INTERNAL_State *s;
1902   struct REGEX_INTERNAL_State *s_next;
1903
1904   /* 1. unmark all states */
1905   for (s = a->states_head; NULL != s; s = s->next)
1906     s->marked = GNUNET_NO;
1907
1908   /* 2. traverse dfa from start state and mark all visited states */
1909   REGEX_INTERNAL_automaton_traverse (a, a->start, NULL, NULL, &mark_states, NULL);
1910
1911   /* 3. delete all states that were not visited */
1912   for (s = a->states_head; NULL != s; s = s_next)
1913   {
1914     s_next = s->next;
1915     if (GNUNET_NO == s->marked)
1916       automaton_remove_state (a, s);
1917   }
1918 }
1919
1920
1921 /**
1922  * Remove all dead states from the DFA 'a'. Dead states are those states that do
1923  * not transition to any other state but themselves.
1924  *
1925  * @param a DFA automaton
1926  */
1927 static void
1928 dfa_remove_dead_states (struct REGEX_INTERNAL_Automaton *a)
1929 {
1930   struct REGEX_INTERNAL_State *s;
1931   struct REGEX_INTERNAL_State *s_next;
1932   struct REGEX_INTERNAL_Transition *t;
1933   int dead;
1934
1935   GNUNET_assert (DFA == a->type);
1936
1937   for (s = a->states_head; NULL != s; s = s_next)
1938   {
1939     s_next = s->next;
1940
1941     if (s->accepting)
1942       continue;
1943
1944     dead = 1;
1945     for (t = s->transitions_head; NULL != t; t = t->next)
1946     {
1947       if (NULL != t->to_state && t->to_state != s)
1948       {
1949         dead = 0;
1950         break;
1951       }
1952     }
1953
1954     if (0 == dead)
1955       continue;
1956
1957     /* state s is dead, remove it */
1958     automaton_remove_state (a, s);
1959   }
1960 }
1961
1962
1963 /**
1964  * Merge all non distinguishable states in the DFA 'a'
1965  *
1966  * @param ctx context
1967  * @param a DFA automaton
1968  * @return #GNUNET_OK on success
1969  */
1970 static int
1971 dfa_merge_nondistinguishable_states (struct REGEX_INTERNAL_Context *ctx,
1972                                      struct REGEX_INTERNAL_Automaton *a)
1973 {
1974   uint32_t *table;
1975   struct REGEX_INTERNAL_State *s1;
1976   struct REGEX_INTERNAL_State *s2;
1977   struct REGEX_INTERNAL_Transition *t1;
1978   struct REGEX_INTERNAL_Transition *t2;
1979   struct REGEX_INTERNAL_State *s1_next;
1980   struct REGEX_INTERNAL_State *s2_next;
1981   int change;
1982   unsigned int num_equal_edges;
1983   unsigned int i;
1984   unsigned int state_cnt;
1985   unsigned long long idx;
1986   unsigned long long idx1;
1987
1988   if ( (NULL == a) || (0 == a->state_count) )
1989   {
1990     GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
1991                 "Could not merge nondistinguishable states, automaton was NULL.\n");
1992     return GNUNET_SYSERR;
1993   }
1994
1995   state_cnt = a->state_count;
1996   table = GNUNET_malloc_large ((sizeof (uint32_t) * state_cnt * state_cnt / 32)  + sizeof (uint32_t));
1997   if (NULL == table)
1998   {
1999     GNUNET_log_strerror (GNUNET_ERROR_TYPE_ERROR, "malloc");
2000     return GNUNET_SYSERR;
2001   }
2002
2003   for (i = 0, s1 = a->states_head; NULL != s1; s1 = s1->next)
2004     s1->marked = i++;
2005
2006   /* Mark all pairs of accepting/!accepting states */
2007   for (s1 = a->states_head; NULL != s1; s1 = s1->next)
2008     for (s2 = a->states_head; NULL != s2; s2 = s2->next)
2009       if ( (s1->accepting && !s2->accepting) ||
2010            (!s1->accepting && s2->accepting) )
2011       {
2012         idx = (unsigned long long) s1->marked * state_cnt + s2->marked;
2013         table[idx / 32] |= (1U << (idx % 32));
2014       }
2015
2016   /* Find all equal states */
2017   change = 1;
2018   while (0 != change)
2019   {
2020     change = 0;
2021     for (s1 = a->states_head; NULL != s1; s1 = s1->next)
2022     {
2023       for (s2 = a->states_head; NULL != s2 && s1 != s2; s2 = s2->next)
2024       {
2025         idx = (unsigned long long) s1->marked * state_cnt + s2->marked;
2026         if (0 != (table[idx / 32] & (1U << (idx % 32))))
2027           continue;
2028         num_equal_edges = 0;
2029         for (t1 = s1->transitions_head; NULL != t1; t1 = t1->next)
2030         {
2031           for (t2 = s2->transitions_head; NULL != t2; t2 = t2->next)
2032           {
2033             if (0 == strcmp (t1->label, t2->label))
2034             {
2035               num_equal_edges++;
2036               /* same edge, but targets definitively different, so we're different
2037                  as well */
2038               if (t1->to_state->marked > t2->to_state->marked)
2039                 idx1 = (unsigned long long) t1->to_state->marked * state_cnt + t2->to_state->marked;
2040               else
2041                 idx1 = (unsigned long long) t2->to_state->marked * state_cnt + t1->to_state->marked;
2042               if (0 != (table[idx1 / 32] & (1U << (idx1 % 32))))
2043               {
2044                 table[idx / 32] |= (1U << (idx % 32));
2045                 change = 1; /* changed a marker, need to run again */
2046               }
2047             }
2048           }
2049         }
2050         if ( (num_equal_edges != s1->transition_count) ||
2051              (num_equal_edges != s2->transition_count) )
2052         {
2053           /* Make sure ALL edges of possible equal states are the same */
2054           table[idx / 32] |= (1U << (idx % 32));
2055           change = 1;  /* changed a marker, need to run again */
2056         }
2057       }
2058     }
2059   }
2060
2061   /* Merge states that are equal */
2062   for (s1 = a->states_head; NULL != s1; s1 = s1_next)
2063   {
2064     s1_next = s1->next;
2065     for (s2 = a->states_head; NULL != s2 && s1 != s2; s2 = s2_next)
2066     {
2067       s2_next = s2->next;
2068       idx = (unsigned long long) s1->marked * state_cnt + s2->marked;
2069       if (0 == (table[idx / 32] & (1U << (idx % 32))))
2070         automaton_merge_states (ctx, a, s1, s2);
2071     }
2072   }
2073
2074   GNUNET_free (table);
2075   return GNUNET_OK;
2076 }
2077
2078
2079 /**
2080  * Minimize the given DFA 'a' by removing all unreachable states, removing all
2081  * dead states and merging all non distinguishable states
2082  *
2083  * @param ctx context
2084  * @param a DFA automaton
2085  * @return GNUNET_OK on success
2086  */
2087 static int
2088 dfa_minimize (struct REGEX_INTERNAL_Context *ctx,
2089               struct REGEX_INTERNAL_Automaton *a)
2090 {
2091   if (NULL == a)
2092     return GNUNET_SYSERR;
2093
2094   GNUNET_assert (DFA == a->type);
2095
2096   /* 1. remove unreachable states */
2097   dfa_remove_unreachable_states (a);
2098
2099   /* 2. remove dead states */
2100   dfa_remove_dead_states (a);
2101
2102   /* 3. Merge nondistinguishable states */
2103   if (GNUNET_OK != dfa_merge_nondistinguishable_states (ctx, a))
2104     return GNUNET_SYSERR;
2105   return GNUNET_OK;
2106 }
2107
2108
2109 /**
2110  * Context for adding strided transitions to a DFA.
2111  */
2112 struct REGEX_INTERNAL_Strided_Context
2113 {
2114   /**
2115    * Length of the strides.
2116    */
2117   const unsigned int stride;
2118
2119   /**
2120    * Strided transitions DLL. New strided transitions will be stored in this DLL
2121    * and afterwards added to the DFA.
2122    */
2123   struct REGEX_INTERNAL_Transition *transitions_head;
2124
2125   /**
2126    * Strided transitions DLL.
2127    */
2128   struct REGEX_INTERNAL_Transition *transitions_tail;
2129 };
2130
2131
2132 /**
2133  * Recursive helper function to add strides to a DFA.
2134  *
2135  * @param cls context, contains stride length and strided transitions DLL.
2136  * @param depth current depth of the depth-first traversal of the graph.
2137  * @param label current label, string that contains all labels on the path from
2138  *        'start' to 's'.
2139  * @param start start state for the depth-first traversal of the graph.
2140  * @param s current state in the depth-first traversal
2141  */
2142 static void
2143 dfa_add_multi_strides_helper (void *cls, const unsigned int depth, char *label,
2144                               struct REGEX_INTERNAL_State *start,
2145                               struct REGEX_INTERNAL_State *s)
2146 {
2147   struct REGEX_INTERNAL_Strided_Context *ctx = cls;
2148   struct REGEX_INTERNAL_Transition *t;
2149   char *new_label;
2150
2151   if (depth == ctx->stride)
2152   {
2153     t = GNUNET_new (struct REGEX_INTERNAL_Transition);
2154     t->label = GNUNET_strdup (label);
2155     t->to_state = s;
2156     t->from_state = start;
2157     GNUNET_CONTAINER_DLL_insert (ctx->transitions_head, ctx->transitions_tail,
2158                                  t);
2159   }
2160   else
2161   {
2162     for (t = s->transitions_head; NULL != t; t = t->next)
2163     {
2164       /* Do not consider self-loops, because it end's up in too many
2165        * transitions */
2166       if (t->to_state == t->from_state)
2167         continue;
2168
2169       if (NULL != label)
2170       {
2171         GNUNET_asprintf (&new_label, "%s%s", label, t->label);
2172       }
2173       else
2174         new_label = GNUNET_strdup (t->label);
2175
2176       dfa_add_multi_strides_helper (cls, (depth + 1), new_label, start,
2177                                     t->to_state);
2178     }
2179   }
2180   GNUNET_free_non_null (label);
2181 }
2182
2183
2184 /**
2185  * Function called for each state in the DFA. Starts a traversal of depth set in
2186  * context starting from state 's'.
2187  *
2188  * @param cls context.
2189  * @param count not used.
2190  * @param s current state.
2191  */
2192 static void
2193 dfa_add_multi_strides (void *cls, const unsigned int count,
2194                        struct REGEX_INTERNAL_State *s)
2195 {
2196   dfa_add_multi_strides_helper (cls, 0, NULL, s, s);
2197 }
2198
2199
2200 /**
2201  * Adds multi-strided transitions to the given 'dfa'.
2202  *
2203  * @param regex_ctx regex context needed to add transitions to the automaton.
2204  * @param dfa DFA to which the multi strided transitions should be added.
2205  * @param stride_len length of the strides.
2206  */
2207 void
2208 REGEX_INTERNAL_dfa_add_multi_strides (struct REGEX_INTERNAL_Context *regex_ctx,
2209                                     struct REGEX_INTERNAL_Automaton *dfa,
2210                                     const unsigned int stride_len)
2211 {
2212   struct REGEX_INTERNAL_Strided_Context ctx = { stride_len, NULL, NULL };
2213   struct REGEX_INTERNAL_Transition *t;
2214   struct REGEX_INTERNAL_Transition *t_next;
2215
2216   if (1 > stride_len || GNUNET_YES == dfa->is_multistrided)
2217     return;
2218
2219   /* Compute the new transitions of given stride_len */
2220   REGEX_INTERNAL_automaton_traverse (dfa, dfa->start, NULL, NULL,
2221                                    &dfa_add_multi_strides, &ctx);
2222
2223   /* Add all the new transitions to the automaton. */
2224   for (t = ctx.transitions_head; NULL != t; t = t_next)
2225   {
2226     t_next = t->next;
2227     state_add_transition (regex_ctx, t->from_state, t->label, t->to_state);
2228     GNUNET_CONTAINER_DLL_remove (ctx.transitions_head, ctx.transitions_tail, t);
2229     GNUNET_free_non_null (t->label);
2230     GNUNET_free (t);
2231   }
2232
2233   /* Mark this automaton as multistrided */
2234   dfa->is_multistrided = GNUNET_YES;
2235 }
2236
2237 /**
2238  * Recursive Helper function for DFA path compression. Does DFS on the DFA graph
2239  * and adds new transitions to the given transitions DLL and marks states that
2240  * should be removed by setting state->contained to GNUNET_YES.
2241  *
2242  * @param dfa DFA for which the paths should be compressed.
2243  * @param start starting state for linear path search.
2244  * @param cur current state in the recursive DFS.
2245  * @param label current label (string of traversed labels).
2246  * @param max_len maximal path compression length.
2247  * @param transitions_head transitions DLL.
2248  * @param transitions_tail transitions DLL.
2249  */
2250 void
2251 dfa_compress_paths_helper (struct REGEX_INTERNAL_Automaton *dfa,
2252                            struct REGEX_INTERNAL_State *start,
2253                            struct REGEX_INTERNAL_State *cur, char *label,
2254                            unsigned int max_len,
2255                            struct REGEX_INTERNAL_Transition **transitions_head,
2256                            struct REGEX_INTERNAL_Transition **transitions_tail)
2257 {
2258   struct REGEX_INTERNAL_Transition *t;
2259   char *new_label;
2260
2261
2262   if (NULL != label &&
2263       ((cur->incoming_transition_count > 1 || GNUNET_YES == cur->accepting ||
2264         GNUNET_YES == cur->marked) || (start != dfa->start && max_len > 0 &&
2265                                        max_len == strlen (label)) ||
2266        (start == dfa->start && GNUNET_REGEX_INITIAL_BYTES == strlen (label))))
2267   {
2268     t = GNUNET_new (struct REGEX_INTERNAL_Transition);
2269     t->label = GNUNET_strdup (label);
2270     t->to_state = cur;
2271     t->from_state = start;
2272     GNUNET_CONTAINER_DLL_insert (*transitions_head, *transitions_tail, t);
2273
2274     if (GNUNET_NO == cur->marked)
2275     {
2276       dfa_compress_paths_helper (dfa, cur, cur, NULL, max_len, transitions_head,
2277                                  transitions_tail);
2278     }
2279     return;
2280   }
2281   else if (cur != start)
2282     cur->contained = GNUNET_YES;
2283
2284   if (GNUNET_YES == cur->marked && cur != start)
2285     return;
2286
2287   cur->marked = GNUNET_YES;
2288
2289
2290   for (t = cur->transitions_head; NULL != t; t = t->next)
2291   {
2292     if (NULL != label)
2293       GNUNET_asprintf (&new_label, "%s%s", label, t->label);
2294     else
2295       new_label = GNUNET_strdup (t->label);
2296
2297     if (t->to_state != cur)
2298     {
2299       dfa_compress_paths_helper (dfa, start, t->to_state, new_label, max_len,
2300                                  transitions_head, transitions_tail);
2301     }
2302     GNUNET_free (new_label);
2303   }
2304 }
2305
2306
2307 /**
2308  * Compress paths in the given 'dfa'. Linear paths like 0->1->2->3 will be
2309  * compressed to 0->3 by combining transitions.
2310  *
2311  * @param regex_ctx context for adding new transitions.
2312  * @param dfa DFA representation, will directly modify the given DFA.
2313  * @param max_len maximal length of the compressed paths.
2314  */
2315 static void
2316 dfa_compress_paths (struct REGEX_INTERNAL_Context *regex_ctx,
2317                     struct REGEX_INTERNAL_Automaton *dfa, unsigned int max_len)
2318 {
2319   struct REGEX_INTERNAL_State *s;
2320   struct REGEX_INTERNAL_State *s_next;
2321   struct REGEX_INTERNAL_Transition *t;
2322   struct REGEX_INTERNAL_Transition *t_next;
2323   struct REGEX_INTERNAL_Transition *transitions_head = NULL;
2324   struct REGEX_INTERNAL_Transition *transitions_tail = NULL;
2325
2326   if (NULL == dfa)
2327     return;
2328
2329   /* Count the incoming transitions on each state. */
2330   for (s = dfa->states_head; NULL != s; s = s->next)
2331   {
2332     for (t = s->transitions_head; NULL != t; t = t->next)
2333     {
2334       if (NULL != t->to_state)
2335         t->to_state->incoming_transition_count++;
2336     }
2337   }
2338
2339   /* Unmark all states. */
2340   for (s = dfa->states_head; NULL != s; s = s->next)
2341   {
2342     s->marked = GNUNET_NO;
2343     s->contained = GNUNET_NO;
2344   }
2345
2346   /* Add strides and mark states that can be deleted. */
2347   dfa_compress_paths_helper (dfa, dfa->start, dfa->start, NULL, max_len,
2348                              &transitions_head, &transitions_tail);
2349
2350   /* Add all the new transitions to the automaton. */
2351   for (t = transitions_head; NULL != t; t = t_next)
2352   {
2353     t_next = t->next;
2354     state_add_transition (regex_ctx, t->from_state, t->label, t->to_state);
2355     GNUNET_CONTAINER_DLL_remove (transitions_head, transitions_tail, t);
2356     GNUNET_free_non_null (t->label);
2357     GNUNET_free (t);
2358   }
2359
2360   /* Remove marked states (including their incoming and outgoing transitions). */
2361   for (s = dfa->states_head; NULL != s; s = s_next)
2362   {
2363     s_next = s->next;
2364     if (GNUNET_YES == s->contained)
2365       automaton_remove_state (dfa, s);
2366   }
2367 }
2368
2369
2370 /**
2371  * Creates a new NFA fragment. Needs to be cleared using
2372  * automaton_fragment_clear.
2373  *
2374  * @param start starting state
2375  * @param end end state
2376  *
2377  * @return new NFA fragment
2378  */
2379 static struct REGEX_INTERNAL_Automaton *
2380 nfa_fragment_create (struct REGEX_INTERNAL_State *start,
2381                      struct REGEX_INTERNAL_State *end)
2382 {
2383   struct REGEX_INTERNAL_Automaton *n;
2384
2385   n = GNUNET_new (struct REGEX_INTERNAL_Automaton);
2386
2387   n->type = NFA;
2388   n->start = NULL;
2389   n->end = NULL;
2390   n->state_count = 0;
2391
2392   if (NULL == start || NULL == end)
2393     return n;
2394
2395   automaton_add_state (n, end);
2396   automaton_add_state (n, start);
2397
2398   n->state_count = 2;
2399
2400   n->start = start;
2401   n->end = end;
2402
2403   return n;
2404 }
2405
2406
2407 /**
2408  * Adds a list of states to the given automaton 'n'.
2409  *
2410  * @param n automaton to which the states should be added
2411  * @param states_head head of the DLL of states
2412  * @param states_tail tail of the DLL of states
2413  */
2414 static void
2415 nfa_add_states (struct REGEX_INTERNAL_Automaton *n,
2416                 struct REGEX_INTERNAL_State *states_head,
2417                 struct REGEX_INTERNAL_State *states_tail)
2418 {
2419   struct REGEX_INTERNAL_State *s;
2420
2421   if (NULL == n || NULL == states_head)
2422   {
2423     GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "Could not add states\n");
2424     return;
2425   }
2426
2427   if (NULL == n->states_head)
2428   {
2429     n->states_head = states_head;
2430     n->states_tail = states_tail;
2431     return;
2432   }
2433
2434   if (NULL != states_head)
2435   {
2436     n->states_tail->next = states_head;
2437     n->states_tail = states_tail;
2438   }
2439
2440   for (s = states_head; NULL != s; s = s->next)
2441     n->state_count++;
2442 }
2443
2444
2445 /**
2446  * Creates a new NFA state. Needs to be freed using automaton_destroy_state.
2447  *
2448  * @param ctx context
2449  * @param accepting is it an accepting state or not
2450  *
2451  * @return new NFA state
2452  */
2453 static struct REGEX_INTERNAL_State *
2454 nfa_state_create (struct REGEX_INTERNAL_Context *ctx, int accepting)
2455 {
2456   struct REGEX_INTERNAL_State *s;
2457
2458   s = GNUNET_new (struct REGEX_INTERNAL_State);
2459   s->id = ctx->state_id++;
2460   s->accepting = accepting;
2461   s->marked = GNUNET_NO;
2462   s->contained = 0;
2463   s->index = -1;
2464   s->lowlink = -1;
2465   s->scc_id = 0;
2466   s->name = NULL;
2467   GNUNET_asprintf (&s->name, "s%i", s->id);
2468
2469   return s;
2470 }
2471
2472
2473 /**
2474  * Calculates the closure set for the given set of states.
2475  *
2476  * @param ret set to sorted nfa closure on 'label' (epsilon closure if 'label' is NULL)
2477  * @param nfa the NFA containing 's'
2478  * @param states list of states on which to base the closure on
2479  * @param label transitioning label for which to base the closure on,
2480  *                pass NULL for epsilon transition
2481  */
2482 static void
2483 nfa_closure_set_create (struct REGEX_INTERNAL_StateSet *ret,
2484                         struct REGEX_INTERNAL_Automaton *nfa,
2485                         struct REGEX_INTERNAL_StateSet *states, const char *label)
2486 {
2487   struct REGEX_INTERNAL_State *s;
2488   unsigned int i;
2489   struct REGEX_INTERNAL_StateSet_MDLL cls_stack;
2490   struct REGEX_INTERNAL_State *clsstate;
2491   struct REGEX_INTERNAL_State *currentstate;
2492   struct REGEX_INTERNAL_Transition *ctran;
2493
2494   memset (ret, 0, sizeof (struct REGEX_INTERNAL_StateSet));
2495   if (NULL == states)
2496     return;
2497
2498   for (i = 0; i < states->off; i++)
2499   {
2500     s = states->states[i];
2501
2502     /* Add start state to closure only for epsilon closure */
2503     if (NULL == label)
2504       state_set_append (ret, s);
2505
2506     /* initialize work stack */
2507     cls_stack.head = NULL;
2508     cls_stack.tail = NULL;
2509     GNUNET_CONTAINER_MDLL_insert (ST, cls_stack.head, cls_stack.tail, s);
2510     cls_stack.len = 1;
2511
2512     while (NULL != (currentstate = cls_stack.tail))
2513     {
2514       GNUNET_CONTAINER_MDLL_remove (ST, cls_stack.head, cls_stack.tail,
2515                                     currentstate);
2516       cls_stack.len--;
2517       for (ctran = currentstate->transitions_head; NULL != ctran;
2518            ctran = ctran->next)
2519       {
2520         if (NULL == (clsstate = ctran->to_state))
2521           continue;
2522         if (0 != clsstate->contained)
2523           continue;
2524         if (0 != nullstrcmp (label, ctran->label))
2525           continue;
2526         state_set_append (ret, clsstate);
2527         GNUNET_CONTAINER_MDLL_insert_tail (ST, cls_stack.head, cls_stack.tail,
2528                                            clsstate);
2529         cls_stack.len++;
2530         clsstate->contained = 1;
2531       }
2532     }
2533   }
2534   for (i = 0; i < ret->off; i++)
2535     ret->states[i]->contained = 0;
2536
2537   if (ret->off > 1)
2538     qsort (ret->states, ret->off, sizeof (struct REGEX_INTERNAL_State *),
2539            &state_compare);
2540 }
2541
2542
2543 /**
2544  * Pops two NFA fragments (a, b) from the stack and concatenates them (ab)
2545  *
2546  * @param ctx context
2547  */
2548 static void
2549 nfa_add_concatenation (struct REGEX_INTERNAL_Context *ctx)
2550 {
2551   struct REGEX_INTERNAL_Automaton *a;
2552   struct REGEX_INTERNAL_Automaton *b;
2553   struct REGEX_INTERNAL_Automaton *new_nfa;
2554
2555   b = ctx->stack_tail;
2556   GNUNET_assert (NULL != b);
2557   GNUNET_CONTAINER_DLL_remove (ctx->stack_head, ctx->stack_tail, b);
2558   a = ctx->stack_tail;
2559   GNUNET_assert (NULL != a);
2560   GNUNET_CONTAINER_DLL_remove (ctx->stack_head, ctx->stack_tail, a);
2561
2562   state_add_transition (ctx, a->end, NULL, b->start);
2563   a->end->accepting = 0;
2564   b->end->accepting = 1;
2565
2566   new_nfa = nfa_fragment_create (NULL, NULL);
2567   nfa_add_states (new_nfa, a->states_head, a->states_tail);
2568   nfa_add_states (new_nfa, b->states_head, b->states_tail);
2569   new_nfa->start = a->start;
2570   new_nfa->end = b->end;
2571   new_nfa->state_count += a->state_count + b->state_count;
2572   automaton_fragment_clear (a);
2573   automaton_fragment_clear (b);
2574
2575   GNUNET_CONTAINER_DLL_insert_tail (ctx->stack_head, ctx->stack_tail, new_nfa);
2576 }
2577
2578
2579 /**
2580  * Pops a NFA fragment from the stack (a) and adds a new fragment (a*)
2581  *
2582  * @param ctx context
2583  */
2584 static void
2585 nfa_add_star_op (struct REGEX_INTERNAL_Context *ctx)
2586 {
2587   struct REGEX_INTERNAL_Automaton *a;
2588   struct REGEX_INTERNAL_Automaton *new_nfa;
2589   struct REGEX_INTERNAL_State *start;
2590   struct REGEX_INTERNAL_State *end;
2591
2592   a = ctx->stack_tail;
2593
2594   if (NULL == a)
2595   {
2596     GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
2597                 "nfa_add_star_op failed, because there was no element on the stack");
2598     return;
2599   }
2600
2601   GNUNET_CONTAINER_DLL_remove (ctx->stack_head, ctx->stack_tail, a);
2602
2603   start = nfa_state_create (ctx, 0);
2604   end = nfa_state_create (ctx, 1);
2605
2606   state_add_transition (ctx, start, NULL, a->start);
2607   state_add_transition (ctx, start, NULL, end);
2608   state_add_transition (ctx, a->end, NULL, a->start);
2609   state_add_transition (ctx, a->end, NULL, end);
2610
2611   a->end->accepting = 0;
2612   end->accepting = 1;
2613
2614   new_nfa = nfa_fragment_create (start, end);
2615   nfa_add_states (new_nfa, a->states_head, a->states_tail);
2616   automaton_fragment_clear (a);
2617
2618   GNUNET_CONTAINER_DLL_insert_tail (ctx->stack_head, ctx->stack_tail, new_nfa);
2619 }
2620
2621
2622 /**
2623  * Pops an NFA fragment (a) from the stack and adds a new fragment (a+)
2624  *
2625  * @param ctx context
2626  */
2627 static void
2628 nfa_add_plus_op (struct REGEX_INTERNAL_Context *ctx)
2629 {
2630   struct REGEX_INTERNAL_Automaton *a;
2631
2632   a = ctx->stack_tail;
2633
2634   if (NULL == a)
2635   {
2636     GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
2637                 "nfa_add_plus_op failed, because there was no element on the stack");
2638     return;
2639   }
2640
2641   GNUNET_CONTAINER_DLL_remove (ctx->stack_head, ctx->stack_tail, a);
2642
2643   state_add_transition (ctx, a->end, NULL, a->start);
2644
2645   GNUNET_CONTAINER_DLL_insert_tail (ctx->stack_head, ctx->stack_tail, a);
2646 }
2647
2648
2649 /**
2650  * Pops an NFA fragment (a) from the stack and adds a new fragment (a?)
2651  *
2652  * @param ctx context
2653  */
2654 static void
2655 nfa_add_question_op (struct REGEX_INTERNAL_Context *ctx)
2656 {
2657   struct REGEX_INTERNAL_Automaton *a;
2658   struct REGEX_INTERNAL_Automaton *new_nfa;
2659   struct REGEX_INTERNAL_State *start;
2660   struct REGEX_INTERNAL_State *end;
2661
2662   a = ctx->stack_tail;
2663   if (NULL == a)
2664   {
2665     GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
2666                 "nfa_add_question_op failed, because there was no element on the stack");
2667     return;
2668   }
2669
2670   GNUNET_CONTAINER_DLL_remove (ctx->stack_head, ctx->stack_tail, a);
2671
2672   start = nfa_state_create (ctx, 0);
2673   end = nfa_state_create (ctx, 1);
2674
2675   state_add_transition (ctx, start, NULL, a->start);
2676   state_add_transition (ctx, start, NULL, end);
2677   state_add_transition (ctx, a->end, NULL, end);
2678
2679   a->end->accepting = 0;
2680
2681   new_nfa = nfa_fragment_create (start, end);
2682   nfa_add_states (new_nfa, a->states_head, a->states_tail);
2683   GNUNET_CONTAINER_DLL_insert_tail (ctx->stack_head, ctx->stack_tail, new_nfa);
2684   automaton_fragment_clear (a);
2685 }
2686
2687
2688 /**
2689  * Pops two NFA fragments (a, b) from the stack and adds a new NFA fragment that
2690  * alternates between a and b (a|b)
2691  *
2692  * @param ctx context
2693  */
2694 static void
2695 nfa_add_alternation (struct REGEX_INTERNAL_Context *ctx)
2696 {
2697   struct REGEX_INTERNAL_Automaton *a;
2698   struct REGEX_INTERNAL_Automaton *b;
2699   struct REGEX_INTERNAL_Automaton *new_nfa;
2700   struct REGEX_INTERNAL_State *start;
2701   struct REGEX_INTERNAL_State *end;
2702
2703   b = ctx->stack_tail;
2704   GNUNET_assert (NULL != b);
2705   GNUNET_CONTAINER_DLL_remove (ctx->stack_head, ctx->stack_tail, b);
2706   a = ctx->stack_tail;
2707   GNUNET_assert (NULL != a);
2708   GNUNET_CONTAINER_DLL_remove (ctx->stack_head, ctx->stack_tail, a);
2709
2710   start = nfa_state_create (ctx, 0);
2711   end = nfa_state_create (ctx, 1);
2712   state_add_transition (ctx, start, NULL, a->start);
2713   state_add_transition (ctx, start, NULL, b->start);
2714
2715   state_add_transition (ctx, a->end, NULL, end);
2716   state_add_transition (ctx, b->end, NULL, end);
2717
2718   a->end->accepting = 0;
2719   b->end->accepting = 0;
2720   end->accepting = 1;
2721
2722   new_nfa = nfa_fragment_create (start, end);
2723   nfa_add_states (new_nfa, a->states_head, a->states_tail);
2724   nfa_add_states (new_nfa, b->states_head, b->states_tail);
2725   automaton_fragment_clear (a);
2726   automaton_fragment_clear (b);
2727
2728   GNUNET_CONTAINER_DLL_insert_tail (ctx->stack_head, ctx->stack_tail, new_nfa);
2729 }
2730
2731
2732 /**
2733  * Adds a new nfa fragment to the stack
2734  *
2735  * @param ctx context
2736  * @param label label for nfa transition
2737  */
2738 static void
2739 nfa_add_label (struct REGEX_INTERNAL_Context *ctx, const char *label)
2740 {
2741   struct REGEX_INTERNAL_Automaton *n;
2742   struct REGEX_INTERNAL_State *start;
2743   struct REGEX_INTERNAL_State *end;
2744
2745   GNUNET_assert (NULL != ctx);
2746
2747   start = nfa_state_create (ctx, 0);
2748   end = nfa_state_create (ctx, 1);
2749   state_add_transition (ctx, start, label, end);
2750   n = nfa_fragment_create (start, end);
2751   GNUNET_assert (NULL != n);
2752   GNUNET_CONTAINER_DLL_insert_tail (ctx->stack_head, ctx->stack_tail, n);
2753 }
2754
2755
2756 /**
2757  * Initialize a new context
2758  *
2759  * @param ctx context
2760  */
2761 static void
2762 REGEX_INTERNAL_context_init (struct REGEX_INTERNAL_Context *ctx)
2763 {
2764   if (NULL == ctx)
2765   {
2766     GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "Context was NULL!");
2767     return;
2768   }
2769   ctx->state_id = 0;
2770   ctx->transition_id = 0;
2771   ctx->stack_head = NULL;
2772   ctx->stack_tail = NULL;
2773 }
2774
2775
2776 /**
2777  * Construct an NFA by parsing the regex string of length 'len'.
2778  *
2779  * @param regex regular expression string
2780  * @param len length of the string
2781  *
2782  * @return NFA, needs to be freed using REGEX_INTERNAL_destroy_automaton
2783  */
2784 struct REGEX_INTERNAL_Automaton *
2785 REGEX_INTERNAL_construct_nfa (const char *regex, const size_t len)
2786 {
2787   struct REGEX_INTERNAL_Context ctx;
2788   struct REGEX_INTERNAL_Automaton *nfa;
2789   const char *regexp;
2790   char curlabel[2];
2791   char *error_msg;
2792   unsigned int count;
2793   unsigned int altcount;
2794   unsigned int atomcount;
2795   unsigned int poff;
2796   unsigned int psize;
2797   struct
2798   {
2799     int altcount;
2800     int atomcount;
2801   }     *p;
2802
2803   if (NULL == regex || 0 == strlen (regex) || 0 == len)
2804   {
2805     GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
2806                 "Could not parse regex. Empty regex string provided.\n");
2807
2808     return NULL;
2809   }
2810   REGEX_INTERNAL_context_init (&ctx);
2811
2812   regexp = regex;
2813   curlabel[1] = '\0';
2814   p = NULL;
2815   error_msg = NULL;
2816   altcount = 0;
2817   atomcount = 0;
2818   poff = 0;
2819   psize = 0;
2820
2821   for (count = 0; count < len && *regexp; count++, regexp++)
2822   {
2823     switch (*regexp)
2824     {
2825     case '(':
2826       if (atomcount > 1)
2827       {
2828         --atomcount;
2829         nfa_add_concatenation (&ctx);
2830       }
2831       if (poff == psize)
2832         GNUNET_array_grow (p, psize, psize * 2 + 4); /* FIXME why *2 +4? */
2833       p[poff].altcount = altcount;
2834       p[poff].atomcount = atomcount;
2835       poff++;
2836       altcount = 0;
2837       atomcount = 0;
2838       break;
2839     case '|':
2840       if (0 == atomcount)
2841       {
2842         error_msg = "Cannot append '|' to nothing";
2843         goto error;
2844       }
2845       while (--atomcount > 0)
2846         nfa_add_concatenation (&ctx);
2847       altcount++;
2848       break;
2849     case ')':
2850       if (0 == poff)
2851       {
2852         error_msg = "Missing opening '('";
2853         goto error;
2854       }
2855       if (0 == atomcount)
2856       {
2857         /* Ignore this: "()" */
2858         poff--;
2859         altcount = p[poff].altcount;
2860         atomcount = p[poff].atomcount;
2861         break;
2862       }
2863       while (--atomcount > 0)
2864         nfa_add_concatenation (&ctx);
2865       for (; altcount > 0; altcount--)
2866         nfa_add_alternation (&ctx);
2867       poff--;
2868       altcount = p[poff].altcount;
2869       atomcount = p[poff].atomcount;
2870       atomcount++;
2871       break;
2872     case '*':
2873       if (atomcount == 0)
2874       {
2875         error_msg = "Cannot append '*' to nothing";
2876         goto error;
2877       }
2878       nfa_add_star_op (&ctx);
2879       break;
2880     case '+':
2881       if (atomcount == 0)
2882       {
2883         error_msg = "Cannot append '+' to nothing";
2884         goto error;
2885       }
2886       nfa_add_plus_op (&ctx);
2887       break;
2888     case '?':
2889       if (atomcount == 0)
2890       {
2891         error_msg = "Cannot append '?' to nothing";
2892         goto error;
2893       }
2894       nfa_add_question_op (&ctx);
2895       break;
2896     default:
2897       if (atomcount > 1)
2898       {
2899         --atomcount;
2900         nfa_add_concatenation (&ctx);
2901       }
2902       curlabel[0] = *regexp;
2903       nfa_add_label (&ctx, curlabel);
2904       atomcount++;
2905       break;
2906     }
2907   }
2908   if (0 != poff)
2909   {
2910     error_msg = "Unbalanced parenthesis";
2911     goto error;
2912   }
2913   while (--atomcount > 0)
2914     nfa_add_concatenation (&ctx);
2915   for (; altcount > 0; altcount--)
2916     nfa_add_alternation (&ctx);
2917
2918   GNUNET_array_grow (p, psize, 0);
2919
2920   nfa = ctx.stack_tail;
2921   GNUNET_CONTAINER_DLL_remove (ctx.stack_head, ctx.stack_tail, nfa);
2922
2923   if (NULL != ctx.stack_head)
2924   {
2925     error_msg = "Creating the NFA failed. NFA stack was not empty!";
2926     goto error;
2927   }
2928
2929   /* Remember the regex that was used to generate this NFA */
2930   nfa->regex = GNUNET_strdup (regex);
2931
2932   /* create depth-first numbering of the states for pretty printing */
2933   REGEX_INTERNAL_automaton_traverse (nfa, NULL, NULL, NULL, &number_states, NULL);
2934
2935   /* No multistriding added so far */
2936   nfa->is_multistrided = GNUNET_NO;
2937
2938   return nfa;
2939
2940 error:
2941   GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "Could not parse regex: `%s'\n", regex);
2942   if (NULL != error_msg)
2943     GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "%s\n", error_msg);
2944
2945   GNUNET_free_non_null (p);
2946
2947   while (NULL != (nfa = ctx.stack_head))
2948   {
2949     GNUNET_CONTAINER_DLL_remove (ctx.stack_head, ctx.stack_tail, nfa);
2950     REGEX_INTERNAL_automaton_destroy (nfa);
2951   }
2952
2953   return NULL;
2954 }
2955
2956
2957 /**
2958  * Create DFA states based on given 'nfa' and starting with 'dfa_state'.
2959  *
2960  * @param ctx context.
2961  * @param nfa NFA automaton.
2962  * @param dfa DFA automaton.
2963  * @param dfa_state current dfa state, pass epsilon closure of first nfa state
2964  *                  for starting.
2965  */
2966 static void
2967 construct_dfa_states (struct REGEX_INTERNAL_Context *ctx,
2968                       struct REGEX_INTERNAL_Automaton *nfa,
2969                       struct REGEX_INTERNAL_Automaton *dfa,
2970                       struct REGEX_INTERNAL_State *dfa_state)
2971 {
2972   struct REGEX_INTERNAL_Transition *ctran;
2973   struct REGEX_INTERNAL_State *new_dfa_state;
2974   struct REGEX_INTERNAL_State *state_contains;
2975   struct REGEX_INTERNAL_State *state_iter;
2976   struct REGEX_INTERNAL_StateSet tmp;
2977   struct REGEX_INTERNAL_StateSet nfa_set;
2978
2979   for (ctran = dfa_state->transitions_head; NULL != ctran; ctran = ctran->next)
2980   {
2981     if (NULL == ctran->label || NULL != ctran->to_state)
2982       continue;
2983
2984     nfa_closure_set_create (&tmp, nfa, &dfa_state->nfa_set, ctran->label);
2985     nfa_closure_set_create (&nfa_set, nfa, &tmp, NULL);
2986     state_set_clear (&tmp);
2987
2988     state_contains = NULL;
2989     for (state_iter = dfa->states_head; NULL != state_iter;
2990          state_iter = state_iter->next)
2991     {
2992       if (0 == state_set_compare (&state_iter->nfa_set, &nfa_set))
2993       {
2994         state_contains = state_iter;
2995         break;
2996       }
2997     }
2998     if (NULL == state_contains)
2999     {
3000       new_dfa_state = dfa_state_create (ctx, &nfa_set);
3001       automaton_add_state (dfa, new_dfa_state);
3002       ctran->to_state = new_dfa_state;
3003       construct_dfa_states (ctx, nfa, dfa, new_dfa_state);
3004     }
3005     else
3006     {
3007       ctran->to_state = state_contains;
3008       state_set_clear (&nfa_set);
3009     }
3010   }
3011 }
3012
3013
3014 /**
3015  * Construct DFA for the given 'regex' of length 'len'.
3016  *
3017  * Path compression means, that for example a DFA o -> a -> b -> c -> o will be
3018  * compressed to o -> abc -> o. Note that this parameter influences the
3019  * non-determinism of states of the resulting NFA in the DHT (number of outgoing
3020  * edges with the same label). For example for an application that stores IPv4
3021  * addresses as bitstrings it could make sense to limit the path compression to
3022  * 4 or 8.
3023  *
3024  * @param regex regular expression string.
3025  * @param len length of the regular expression.
3026  * @param max_path_len limit the path compression length to the
3027  *        given value. If set to 1, no path compression is applied. Set to 0 for
3028  *        maximal possible path compression (generally not desireable).
3029  * @return DFA, needs to be freed using REGEX_INTERNAL_automaton_destroy.
3030  */
3031 struct REGEX_INTERNAL_Automaton *
3032 REGEX_INTERNAL_construct_dfa (const char *regex, const size_t len,
3033                               unsigned int max_path_len)
3034 {
3035   struct REGEX_INTERNAL_Context ctx;
3036   struct REGEX_INTERNAL_Automaton *dfa;
3037   struct REGEX_INTERNAL_Automaton *nfa;
3038   struct REGEX_INTERNAL_StateSet nfa_start_eps_cls;
3039   struct REGEX_INTERNAL_StateSet singleton_set;
3040
3041   REGEX_INTERNAL_context_init (&ctx);
3042
3043   /* Create NFA */
3044   nfa = REGEX_INTERNAL_construct_nfa (regex, len);
3045
3046   if (NULL == nfa)
3047   {
3048     GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
3049                 "Could not create DFA, because NFA creation failed\n");
3050     return NULL;
3051   }
3052
3053   dfa = GNUNET_new (struct REGEX_INTERNAL_Automaton);
3054   dfa->type = DFA;
3055   dfa->regex = GNUNET_strdup (regex);
3056
3057   /* Create DFA start state from epsilon closure */
3058   memset (&singleton_set, 0, sizeof (struct REGEX_INTERNAL_StateSet));
3059   state_set_append (&singleton_set, nfa->start);
3060   nfa_closure_set_create (&nfa_start_eps_cls, nfa, &singleton_set, NULL);
3061   state_set_clear (&singleton_set);
3062   dfa->start = dfa_state_create (&ctx, &nfa_start_eps_cls);
3063   automaton_add_state (dfa, dfa->start);
3064
3065   construct_dfa_states (&ctx, nfa, dfa, dfa->start);
3066   REGEX_INTERNAL_automaton_destroy (nfa);
3067
3068   /* Minimize DFA */
3069   if (GNUNET_OK != dfa_minimize (&ctx, dfa))
3070   {
3071     REGEX_INTERNAL_automaton_destroy (dfa);
3072     return NULL;
3073   }
3074
3075   /* Create proofs and hashes for all states */
3076   if (GNUNET_OK != automaton_create_proofs (dfa))
3077   {
3078     REGEX_INTERNAL_automaton_destroy (dfa);
3079     return NULL;
3080   }
3081
3082   /* Compress linear DFA paths */
3083   if (1 != max_path_len)
3084     dfa_compress_paths (&ctx, dfa, max_path_len);
3085
3086   return dfa;
3087 }
3088
3089
3090 /**
3091  * Free the memory allocated by constructing the REGEX_INTERNAL_Automaton data
3092  * structure.
3093  *
3094  * @param a automaton to be destroyed
3095  */
3096 void
3097 REGEX_INTERNAL_automaton_destroy (struct REGEX_INTERNAL_Automaton *a)
3098 {
3099   struct REGEX_INTERNAL_State *s;
3100   struct REGEX_INTERNAL_State *next_state;
3101
3102   if (NULL == a)
3103     return;
3104
3105   GNUNET_free_non_null (a->regex);
3106   GNUNET_free_non_null (a->canonical_regex);
3107
3108   for (s = a->states_head; NULL != s; s = next_state)
3109   {
3110     next_state = s->next;
3111     GNUNET_CONTAINER_DLL_remove (a->states_head, a->states_tail, s);
3112     automaton_destroy_state (s);
3113   }
3114
3115   GNUNET_free (a);
3116 }
3117
3118
3119 /**
3120  * Evaluates the given string using the given DFA automaton
3121  *
3122  * @param a automaton, type must be DFA
3123  * @param string string that should be evaluated
3124  *
3125  * @return 0 if string matches, non-0 otherwise
3126  */
3127 static int
3128 evaluate_dfa (struct REGEX_INTERNAL_Automaton *a,
3129               const char *string)
3130 {
3131   const char *strp;
3132   struct REGEX_INTERNAL_State *s;
3133   unsigned int step_len;
3134
3135   if (DFA != a->type)
3136   {
3137     GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
3138                 "Tried to evaluate DFA, but NFA automaton given");
3139     return -1;
3140   }
3141
3142   s = a->start;
3143
3144   /* If the string is empty but the starting state is accepting, we accept. */
3145   if ((NULL == string || 0 == strlen (string)) && s->accepting)
3146     return 0;
3147
3148   for (strp = string; NULL != strp && *strp; strp += step_len)
3149   {
3150     step_len = dfa_move (&s, strp);
3151
3152     if (NULL == s)
3153       break;
3154   }
3155
3156   if (NULL != s && s->accepting)
3157     return 0;
3158
3159   return 1;
3160 }
3161
3162
3163 /**
3164  * Evaluates the given string using the given NFA automaton
3165  *
3166  * @param a automaton, type must be NFA
3167  * @param string string that should be evaluated
3168  * @return 0 if string matches, non-0 otherwise
3169  */
3170 static int
3171 evaluate_nfa (struct REGEX_INTERNAL_Automaton *a,
3172               const char *string)
3173 {
3174   const char *strp;
3175   char str[2];
3176   struct REGEX_INTERNAL_State *s;
3177   struct REGEX_INTERNAL_StateSet sset;
3178   struct REGEX_INTERNAL_StateSet new_sset;
3179   struct REGEX_INTERNAL_StateSet singleton_set;
3180   unsigned int i;
3181   int result;
3182
3183   if (NFA != a->type)
3184   {
3185     GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
3186                 "Tried to evaluate NFA, but DFA automaton given");
3187     return -1;
3188   }
3189
3190   /* If the string is empty but the starting state is accepting, we accept. */
3191   if ((NULL == string || 0 == strlen (string)) && a->start->accepting)
3192     return 0;
3193
3194   result = 1;
3195   memset (&singleton_set, 0, sizeof (struct REGEX_INTERNAL_StateSet));
3196   state_set_append (&singleton_set, a->start);
3197   nfa_closure_set_create (&sset, a, &singleton_set, NULL);
3198   state_set_clear (&singleton_set);
3199
3200   str[1] = '\0';
3201   for (strp = string; NULL != strp && *strp; strp++)
3202   {
3203     str[0] = *strp;
3204     nfa_closure_set_create (&new_sset, a, &sset, str);
3205     state_set_clear (&sset);
3206     nfa_closure_set_create (&sset, a, &new_sset, 0);
3207     state_set_clear (&new_sset);
3208   }
3209
3210   for (i = 0; i < sset.off; i++)
3211   {
3212     s = sset.states[i];
3213     if ( (NULL != s) && (s->accepting) )
3214     {
3215       result = 0;
3216       break;
3217     }
3218   }
3219
3220   state_set_clear (&sset);
3221   return result;
3222 }
3223
3224
3225 /**
3226  * Evaluates the given @a string against the given compiled regex @a a
3227  *
3228  * @param a automaton
3229  * @param string string to check
3230  * @return 0 if string matches, non-0 otherwise
3231  */
3232 int
3233 REGEX_INTERNAL_eval (struct REGEX_INTERNAL_Automaton *a,
3234                      const char *string)
3235 {
3236   int result;
3237
3238   switch (a->type)
3239   {
3240   case DFA:
3241     result = evaluate_dfa (a, string);
3242     break;
3243   case NFA:
3244     result = evaluate_nfa (a, string);
3245     break;
3246   default:
3247     GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
3248                 "Evaluating regex failed, automaton has no type!\n");
3249     result = GNUNET_SYSERR;
3250     break;
3251   }
3252
3253   return result;
3254 }
3255
3256
3257 /**
3258  * Get the canonical regex of the given automaton.
3259  * When constructing the automaton a proof is computed for each state,
3260  * consisting of the regular expression leading to this state. A complete
3261  * regex for the automaton can be computed by combining these proofs.
3262  * As of now this function is only useful for testing.
3263  *
3264  * @param a automaton for which the canonical regex should be returned.
3265  *
3266  * @return
3267  */
3268 const char *
3269 REGEX_INTERNAL_get_canonical_regex (struct REGEX_INTERNAL_Automaton *a)
3270 {
3271   if (NULL == a)
3272     return NULL;
3273
3274   return a->canonical_regex;
3275 }
3276
3277
3278 /**
3279  * Get the number of transitions that are contained in the given automaton.
3280  *
3281  * @param a automaton for which the number of transitions should be returned.
3282  *
3283  * @return number of transitions in the given automaton.
3284  */
3285 unsigned int
3286 REGEX_INTERNAL_get_transition_count (struct REGEX_INTERNAL_Automaton *a)
3287 {
3288   unsigned int t_count;
3289   struct REGEX_INTERNAL_State *s;
3290
3291   if (NULL == a)
3292     return 0;
3293
3294   t_count = 0;
3295   for (s = a->states_head; NULL != s; s = s->next)
3296     t_count += s->transition_count;
3297
3298   return t_count;
3299 }
3300
3301
3302 /**
3303  * Get the first key for the given @a input_string. This hashes the first x bits
3304  * of the @a input_string.
3305  *
3306  * @param input_string string.
3307  * @param string_len length of the @a input_string.
3308  * @param key pointer to where to write the hash code.
3309  * @return number of bits of @a input_string that have been consumed
3310  *         to construct the key
3311  */
3312 size_t
3313 REGEX_INTERNAL_get_first_key (const char *input_string,
3314                               size_t string_len,
3315                               struct GNUNET_HashCode *key)
3316 {
3317   size_t size;
3318
3319   size = string_len < GNUNET_REGEX_INITIAL_BYTES ? string_len :
3320                                                    GNUNET_REGEX_INITIAL_BYTES;
3321   if (NULL == input_string)
3322   {
3323     GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
3324                 "Given input string was NULL!\n");
3325     return 0;
3326   }
3327   GNUNET_CRYPTO_hash (input_string, size, key);
3328
3329   return size;
3330 }
3331
3332
3333 /**
3334  * Recursive function that calls the iterator for each synthetic start state.
3335  *
3336  * @param min_len minimum length of the path in the graph.
3337  * @param max_len maximum length of the path in the graph.
3338  * @param consumed_string string consumed by traversing the graph till this state.
3339  * @param state current state of the automaton.
3340  * @param iterator iterator function called for each edge.
3341  * @param iterator_cls closure for the @a iterator function.
3342  */
3343 static void
3344 iterate_initial_edge (unsigned int min_len,
3345                       unsigned int max_len,
3346                       char *consumed_string,
3347                       struct REGEX_INTERNAL_State *state,
3348                       REGEX_INTERNAL_KeyIterator iterator,
3349                       void *iterator_cls)
3350 {
3351   char *temp;
3352   struct REGEX_INTERNAL_Transition *t;
3353   unsigned int num_edges = state->transition_count;
3354   struct REGEX_BLOCK_Edge edges[num_edges];
3355   struct REGEX_BLOCK_Edge edge[1];
3356   struct GNUNET_HashCode hash;
3357   struct GNUNET_HashCode hash_new;
3358   unsigned int cur_len;
3359
3360   if (NULL != consumed_string)
3361     cur_len = strlen (consumed_string);
3362   else
3363     cur_len = 0;
3364
3365   if ( ( (cur_len >= min_len) ||
3366          (GNUNET_YES == state->accepting) ) &&
3367        (cur_len > 0) &&
3368        (NULL != consumed_string) )
3369   {
3370     if (cur_len <= max_len)
3371     {
3372       if ( (NULL != state->proof) &&
3373            (0 != strcmp (consumed_string,
3374                          state->proof)) )
3375       {
3376         (void) state_get_edges (state, edges);
3377         GNUNET_CRYPTO_hash (consumed_string,
3378                             strlen (consumed_string),
3379                             &hash);
3380         GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
3381                     "Start state for string `%s' is %s\n",
3382                     consumed_string,
3383                     GNUNET_h2s (&hash));
3384         iterator (iterator_cls,
3385                   &hash,
3386                   consumed_string,
3387                   state->accepting,
3388                   num_edges, edges);
3389       }
3390
3391       if ( (GNUNET_YES == state->accepting) &&
3392            (cur_len > 1) &&
3393            (state->transition_count < 1) &&
3394            (cur_len < max_len) )
3395       {
3396         /* Special case for regex consisting of just a string that is shorter than
3397          * max_len */
3398         edge[0].label = &consumed_string[cur_len - 1];
3399         edge[0].destination = state->hash;
3400         temp = GNUNET_strdup (consumed_string);
3401         temp[cur_len - 1] = '\0';
3402         GNUNET_CRYPTO_hash (temp,
3403                             cur_len - 1,
3404                             &hash_new);
3405         GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
3406                     "Start state for short string `%s' is %s\n",
3407                     temp,
3408                     GNUNET_h2s (&hash_new));
3409         iterator (iterator_cls,
3410                   &hash_new,
3411                   temp,
3412                   GNUNET_NO, 1,
3413                   edge);
3414         GNUNET_free (temp);
3415       }
3416     }
3417     else /* cur_len > max_len */
3418     {
3419       /* Case where the concatenated labels are longer than max_len, then split. */
3420       edge[0].label = &consumed_string[max_len];
3421       edge[0].destination = state->hash;
3422       temp = GNUNET_strdup (consumed_string);
3423       temp[max_len] = '\0';
3424       GNUNET_CRYPTO_hash (temp, max_len, &hash);
3425       GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
3426                   "Start state at split edge `%s'-`%s` is %s\n",
3427                   temp,
3428                   edge[0].label,
3429                   GNUNET_h2s (&hash_new));
3430       iterator (iterator_cls,
3431                 &hash,
3432                 temp,
3433                 GNUNET_NO,
3434                 1,
3435                 edge);
3436       GNUNET_free (temp);
3437     }
3438   }
3439
3440   if (cur_len < max_len)
3441   {
3442     for (t = state->transitions_head; NULL != t; t = t->next)
3443     {
3444       if (NULL != strchr (t->label,
3445                           (int) '.'))
3446       {
3447         /* Wildcards not allowed during starting states */
3448         GNUNET_break (0);
3449         continue;
3450       }
3451       if (NULL != consumed_string)
3452         GNUNET_asprintf (&temp,
3453                          "%s%s",
3454                          consumed_string,
3455                          t->label);
3456       else
3457         GNUNET_asprintf (&temp,
3458                          "%s",
3459                          t->label);
3460       iterate_initial_edge (min_len,
3461                             max_len,
3462                             temp,
3463                             t->to_state,
3464                             iterator,
3465                             iterator_cls);
3466       GNUNET_free (temp);
3467     }
3468   }
3469 }
3470
3471
3472 /**
3473  * Iterate over all edges starting from start state of automaton 'a'. Calling
3474  * iterator for each edge.
3475  *
3476  * @param a automaton.
3477  * @param iterator iterator called for each edge.
3478  * @param iterator_cls closure.
3479  */
3480 void
3481 REGEX_INTERNAL_iterate_all_edges (struct REGEX_INTERNAL_Automaton *a,
3482                                   REGEX_INTERNAL_KeyIterator iterator,
3483                                   void *iterator_cls)
3484 {
3485   struct REGEX_INTERNAL_State *s;
3486
3487   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
3488               "Iterating over starting edges\n");
3489   iterate_initial_edge (GNUNET_REGEX_INITIAL_BYTES,
3490                         GNUNET_REGEX_INITIAL_BYTES,
3491                         NULL, a->start,
3492                         iterator, iterator_cls);
3493   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
3494               "Iterating over DFA edges\n");
3495   for (s = a->states_head; NULL != s; s = s->next)
3496   {
3497     struct REGEX_BLOCK_Edge edges[s->transition_count];
3498     unsigned int num_edges;
3499
3500     num_edges = state_get_edges (s, edges);
3501     if ( ( (NULL != s->proof) &&
3502            (0 < strlen (s->proof)) ) || s->accepting)
3503     {
3504       GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
3505                   "Creating DFA edges at `%s' under key %s\n",
3506                   s->proof,
3507                   GNUNET_h2s (&s->hash));
3508       iterator (iterator_cls, &s->hash, s->proof,
3509                 s->accepting,
3510                 num_edges, edges);
3511     }
3512     s->marked = GNUNET_NO;
3513   }
3514 }
3515
3516
3517 /**
3518  * Struct to hold all the relevant state information in the HashMap.
3519  *
3520  * Contains the same info as the Regex Iterator parametes except the key,
3521  * which comes directly from the HashMap iterator.
3522  */
3523 struct temporal_state_store {
3524   int reachable;
3525   char *proof;
3526   int accepting;
3527   int num_edges;
3528   struct REGEX_BLOCK_Edge *edges;
3529 };
3530
3531
3532 /**
3533  * Store regex iterator and cls in one place to pass to the hashmap iterator.
3534  */
3535 struct client_iterator {
3536   REGEX_INTERNAL_KeyIterator iterator;
3537   void *iterator_cls;
3538 };
3539
3540
3541 /**
3542  * Iterator over all edges of a dfa. Stores all of them in a HashMap
3543  * for later reachability marking.
3544  *
3545  * @param cls Closure (HashMap)
3546  * @param key hash for current state.
3547  * @param proof proof for current state
3548  * @param accepting GNUNET_YES if this is an accepting state, GNUNET_NO if not.
3549  * @param num_edges number of edges leaving current state.
3550  * @param edges edges leaving current state.
3551  */
3552 static void
3553 store_all_states (void *cls,
3554                   const struct GNUNET_HashCode *key,
3555                   const char *proof,
3556                   int accepting,
3557                   unsigned int num_edges,
3558                   const struct REGEX_BLOCK_Edge *edges)
3559 {
3560   struct GNUNET_CONTAINER_MultiHashMap *hm = cls;
3561   struct temporal_state_store *tmp;
3562   size_t edges_size;
3563
3564   tmp = GNUNET_new (struct temporal_state_store);
3565   tmp->reachable = GNUNET_NO;
3566   tmp->proof = GNUNET_strdup (proof);
3567   tmp->accepting = accepting;
3568   tmp->num_edges = num_edges;
3569   edges_size = sizeof (struct REGEX_BLOCK_Edge) * num_edges;
3570   tmp->edges = GNUNET_malloc (edges_size);
3571   GNUNET_memcpy(tmp->edges, edges, edges_size);
3572   GNUNET_CONTAINER_multihashmap_put (hm, key, tmp,
3573                                      GNUNET_CONTAINER_MULTIHASHMAPOPTION_UNIQUE_FAST);
3574 }
3575
3576
3577 /**
3578  * Mark state as reachable and call recursively on all its edges.
3579  *
3580  * If already marked as reachable, do nothing.
3581  *
3582  * @param state State to mark as reachable.
3583  * @param hm HashMap which stores all the states indexed by key.
3584  */
3585 static void
3586 mark_as_reachable (struct temporal_state_store *state,
3587                    struct GNUNET_CONTAINER_MultiHashMap *hm)
3588 {
3589   struct temporal_state_store *child;
3590   unsigned int i;
3591
3592   if (GNUNET_YES == state->reachable)
3593     /* visited */
3594     return;
3595
3596   state->reachable = GNUNET_YES;
3597   for (i = 0; i < state->num_edges; i++)
3598   {
3599     child = GNUNET_CONTAINER_multihashmap_get (hm,
3600                                                &state->edges[i].destination);
3601     if (NULL == child)
3602     {
3603       GNUNET_break (0);
3604       continue;
3605     }
3606     mark_as_reachable (child, hm);
3607   }
3608 }
3609
3610
3611 /**
3612  * Iterator over hash map entries to mark the ones that are reachable.
3613  *
3614  * @param cls closure
3615  * @param key current key code
3616  * @param value value in the hash map
3617  * @return #GNUNET_YES if we should continue to iterate,
3618  *         #GNUNET_NO if not.
3619  */
3620 static int
3621 reachability_iterator (void *cls,
3622                        const struct GNUNET_HashCode *key,
3623                        void *value)
3624 {
3625   struct GNUNET_CONTAINER_MultiHashMap *hm = cls;
3626   struct temporal_state_store *state = value;
3627
3628   if (GNUNET_YES == state->reachable)
3629     /* already visited and marked */
3630     return GNUNET_YES;
3631
3632   if (GNUNET_REGEX_INITIAL_BYTES > strlen (state->proof) &&
3633       GNUNET_NO == state->accepting)
3634     /* not directly reachable */
3635     return GNUNET_YES;
3636
3637   mark_as_reachable (state, hm);
3638   return GNUNET_YES;
3639 }
3640
3641
3642 /**
3643  * Iterator over hash map entries.
3644  * Calling the callback on the ones marked as reachables.
3645  *
3646  * @param cls closure
3647  * @param key current key code
3648  * @param value value in the hash map
3649  * @return #GNUNET_YES if we should continue to iterate,
3650  *         #GNUNET_NO if not.
3651  */
3652 static int
3653 iterate_reachables (void *cls,
3654                     const struct GNUNET_HashCode *key,
3655                     void *value)
3656 {
3657   struct client_iterator *ci = cls;
3658   struct temporal_state_store *state = value;
3659
3660   if (GNUNET_YES == state->reachable)
3661   {
3662     ci->iterator (ci->iterator_cls, key,
3663                   state->proof, state->accepting,
3664                   state->num_edges, state->edges);
3665   }
3666   GNUNET_free (state->edges);
3667   GNUNET_free (state->proof);
3668   GNUNET_free (state);
3669   return GNUNET_YES;
3670
3671 }
3672
3673 /**
3674  * Iterate over all edges of automaton 'a' that are reachable from a state with
3675  * a proof of at least GNUNET_REGEX_INITIAL_BYTES characters.
3676  *
3677  * Call the iterator for each such edge.
3678  *
3679  * @param a automaton.
3680  * @param iterator iterator called for each reachable edge.
3681  * @param iterator_cls closure.
3682  */
3683 void
3684 REGEX_INTERNAL_iterate_reachable_edges (struct REGEX_INTERNAL_Automaton *a,
3685                                         REGEX_INTERNAL_KeyIterator iterator,
3686                                         void *iterator_cls)
3687 {
3688   struct GNUNET_CONTAINER_MultiHashMap *hm;
3689   struct client_iterator ci;
3690
3691   hm = GNUNET_CONTAINER_multihashmap_create (a->state_count * 2, GNUNET_NO);
3692   ci.iterator = iterator;
3693   ci.iterator_cls = iterator_cls;
3694
3695   REGEX_INTERNAL_iterate_all_edges (a, &store_all_states, hm);
3696   GNUNET_CONTAINER_multihashmap_iterate (hm, &reachability_iterator, hm);
3697   GNUNET_CONTAINER_multihashmap_iterate (hm, &iterate_reachables, &ci);
3698
3699   GNUNET_CONTAINER_multihashmap_destroy (hm);
3700 }
3701
3702
3703 /* end of regex_internal.c */