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