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