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