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