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