even better proofs
[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   char *R_cur_l;
821   char *R_cur_r;
822   int length_l;
823   int length_r;
824
825   k = 0;
826   n = a->state_count;
827
828   for (i = 0, s = a->states_head; NULL != s; s = s->next, i++)
829   {
830     s->marked = i;
831     states[i] = s;
832   }
833
834   // BASIS
835   for (i = 0; i < n; i++)
836   {
837     for (j = 0; j < n; j++)
838     {
839       R_cur[i][j] = NULL;
840       R_last[i][j] = NULL;
841       for (t = states[i]->transitions_head; NULL != t; t = t->next)
842       {
843         if (t->to_state == states[j])
844         {
845           if (NULL == R_last[i][j])
846             GNUNET_asprintf (&R_last[i][j], "%c", t->label);
847           else
848           {
849             temp = R_last[i][j];
850             GNUNET_asprintf (&R_last[i][j], "%s|%c", R_last[i][j], t->label);
851             GNUNET_free (temp);
852           }
853         }
854       }
855
856
857       if (i == j)
858       {
859         if (NULL == R_last[i][j])
860           GNUNET_asprintf (&R_last[i][j], "");
861         else if (NULL != R_last[i][j] && 1 < strlen (R_last[i][j]))
862         {
863           temp = R_last[i][j];
864           GNUNET_asprintf (&R_last[i][j], "(%s)", R_last[i][j]);
865           GNUNET_free (temp);
866         }
867       }
868       else if (NULL != R_last[i][j] && 1 < strlen (R_last[i][j]))
869       {
870         temp = R_last[i][j];
871         GNUNET_asprintf (&R_last[i][j], "(%s)", R_last[i][j]);
872         GNUNET_free (temp);
873       }
874     }
875   }
876
877   // INDUCTION
878   for (k = 0; k < n; k++)
879   {
880     for (i = 0; i < n; i++)
881     {
882       for (j = 0; j < n; j++)
883       {
884         // 0*R = R*0 = 0
885         // 0+R = R+0 = R
886         if (NULL == R_last[i][k] || NULL == R_last[k][j])
887         {
888           if (NULL != R_last[i][j])
889             R_cur[i][j] = GNUNET_strdup (R_last[i][j]);
890         }
891         else
892         {
893           // R(k)ij = R(k-1)ij + R(k-1)ik (R(k-1)kk)* R(k-1)kj
894           length_l = (NULL == R_last[i][j]) ? 1 : strlen (R_last[i][j]) + 1;
895           length_r =
896               snprintf (NULL, 0, "%s(%s)*%s", R_last[i][k], R_last[k][k],
897                         R_last[k][j]) + 1;
898           R_cur_l = GNUNET_malloc (length_l);
899           R_cur_r = GNUNET_malloc (length_r);
900
901           if (NULL != R_last[i][j])
902             strcat (R_cur_l, R_last[i][j]);
903
904           if (NULL != R_last[i][k])
905             strcat (R_cur_r, R_last[i][k]);
906
907           if (NULL != R_last[k][k] && 0 != strcmp (R_last[k][k], ""))
908           {
909             strcat (R_cur_r, "(");
910             strcat (R_cur_r, R_last[k][k]);
911             strcat (R_cur_r, ")*");
912           }
913
914           if (NULL != R_last[k][j])
915             strcat (R_cur_r, R_last[k][j]);
916
917           // | is idempotent: a | a = a for all a in A
918           if (0 == strcmp (R_cur_l, R_cur_r) || 0 == strcmp (R_cur_l, "") ||
919               0 == strcmp (R_cur_r, ""))
920           {
921             if (0 == strcmp (R_cur_l, ""))
922               GNUNET_asprintf (&R_cur[i][j], "%s", R_cur_r);
923             else
924               GNUNET_asprintf (&R_cur[i][j], "%s", R_cur_l);
925           }
926           // a | a a* a = a+
927           else if (R_last[i][j] == R_last[i][k] && R_last[i][k] == R_last[k][k]
928                    && R_last[k][k] == R_last[k][j])
929           {
930             GNUNET_asprintf (&R_cur[i][j], "%s+", R_last[i][j]);
931           }
932           // a | a b* b => a | a b | a b b | ... => a b*
933           else if (R_last[i][j] == R_last[i][k] && R_last[k][k] == R_last[k][j])
934           {
935             GNUNET_asprintf (&R_cur[i][j], "%s%s*", R_last[i][k], R_last[k][k]);
936           }
937           // a | b b* a => a | b a | b b a | ... => b* a
938           else if (R_last[i][j] == R_last[k][j] && R_last[i][k] == R_last[k][k])
939           {
940             GNUNET_asprintf (&R_cur[i][j], "%s*%s", R_last[k][k], R_last[k][j]);
941           }
942           else
943             GNUNET_asprintf (&R_cur[i][j], "(%s|%s)", R_cur_l, R_cur_r);
944
945           GNUNET_free_non_null (R_cur_l);
946           GNUNET_free_non_null (R_cur_r);
947
948         }
949       }
950     }
951
952     for (i = 0; i < n; i++)
953     {
954       for (j = 0; j < n; j++)
955       {
956         GNUNET_free_non_null (R_last[i][j]);
957
958         if (NULL != R_cur[i][j])
959         {
960           R_last[i][j] = GNUNET_strdup (R_cur[i][j]);
961           GNUNET_free (R_cur[i][j]);
962           R_cur[i][j] = NULL;
963         }
964       }
965     }
966   }
967
968   // assign proofs and hashes
969   for (i = 0; i < n; i++)
970   {
971     states[i]->proof = GNUNET_strdup (R_last[a->start->marked][i]);
972     GNUNET_CRYPTO_hash (states[i]->proof, strlen (states[i]->proof),
973                         &states[i]->hash);
974   }
975
976   // cleanup
977   for (i = 0; i < n; i++)
978   {
979     for (j = 0; j < n; j++)
980       GNUNET_free_non_null (R_last[i][j]);
981   }
982 }
983
984 /**
985  * Creates a new DFA state based on a set of NFA states. Needs to be freed using
986  * automaton_destroy_state.
987  *
988  * @param ctx context
989  * @param nfa_states set of NFA states on which the DFA should be based on
990  *
991  * @return new DFA state
992  */
993 static struct GNUNET_REGEX_State *
994 dfa_state_create (struct GNUNET_REGEX_Context *ctx,
995                   struct GNUNET_REGEX_StateSet *nfa_states)
996 {
997   struct GNUNET_REGEX_State *s;
998   char *name;
999   int len = 0;
1000   struct GNUNET_REGEX_State *cstate;
1001   struct Transition *ctran;
1002   int insert = 1;
1003   struct Transition *t;
1004   int i;
1005
1006   s = GNUNET_malloc (sizeof (struct GNUNET_REGEX_State));
1007   s->id = ctx->state_id++;
1008   s->accepting = 0;
1009   s->marked = 0;
1010   s->name = NULL;
1011   s->scc_id = 0;
1012   s->index = -1;
1013   s->lowlink = -1;
1014   s->contained = 0;
1015   s->proof = NULL;
1016
1017   if (NULL == nfa_states)
1018   {
1019     GNUNET_asprintf (&s->name, "s%i", s->id);
1020     return s;
1021   }
1022
1023   s->nfa_set = nfa_states;
1024
1025   if (nfa_states->len < 1)
1026     return s;
1027
1028   // Create a name based on 'sset'
1029   s->name = GNUNET_malloc (sizeof (char) * 2);
1030   strcat (s->name, "{");
1031   name = NULL;
1032
1033   for (i = 0; i < nfa_states->len; i++)
1034   {
1035     cstate = nfa_states->states[i];
1036     GNUNET_asprintf (&name, "%i,", cstate->id);
1037
1038     if (NULL != name)
1039     {
1040       len = strlen (s->name) + strlen (name) + 1;
1041       s->name = GNUNET_realloc (s->name, len);
1042       strcat (s->name, name);
1043       GNUNET_free (name);
1044       name = NULL;
1045     }
1046
1047     // Add a transition for each distinct label to NULL state
1048     for (ctran = cstate->transitions_head; NULL != ctran; ctran = ctran->next)
1049     {
1050       if (0 != ctran->label)
1051       {
1052         insert = 1;
1053
1054         for (t = s->transitions_head; NULL != t; t = t->next)
1055         {
1056           if (t->label == ctran->label)
1057           {
1058             insert = 0;
1059             break;
1060           }
1061         }
1062
1063         if (insert)
1064           state_add_transition (ctx, s, ctran->label, NULL);
1065       }
1066     }
1067
1068     // If the nfa_states contain an accepting state, the new dfa state is also
1069     // accepting
1070     if (cstate->accepting)
1071       s->accepting = 1;
1072   }
1073
1074   s->name[strlen (s->name) - 1] = '}';
1075
1076   return s;
1077 }
1078
1079 /**
1080  * Move from the given state 's' to the next state on transition 'label'
1081  *
1082  * @param s starting state
1083  * @param label edge label to follow
1084  *
1085  * @return new state or NULL, if transition on label not possible
1086  */
1087 static struct GNUNET_REGEX_State *
1088 dfa_move (struct GNUNET_REGEX_State *s, const char label)
1089 {
1090   struct Transition *t;
1091   struct GNUNET_REGEX_State *new_s;
1092
1093   if (NULL == s)
1094     return NULL;
1095
1096   new_s = NULL;
1097
1098   for (t = s->transitions_head; NULL != t; t = t->next)
1099   {
1100     if (label == t->label)
1101     {
1102       new_s = t->to_state;
1103       break;
1104     }
1105   }
1106
1107   return new_s;
1108 }
1109
1110 /**
1111  * Remove all unreachable states from DFA 'a'. Unreachable states are those
1112  * states that are not reachable from the starting state.
1113  *
1114  * @param a DFA automaton
1115  */
1116 static void
1117 dfa_remove_unreachable_states (struct GNUNET_REGEX_Automaton *a)
1118 {
1119   struct GNUNET_REGEX_State *s;
1120   struct GNUNET_REGEX_State *s_next;
1121
1122   // 1. unmark all states
1123   for (s = a->states_head; NULL != s; s = s->next)
1124     s->marked = GNUNET_NO;
1125
1126   // 2. traverse dfa from start state and mark all visited states
1127   automaton_traverse (NULL, a, NULL);
1128
1129   // 3. delete all states that were not visited
1130   for (s = a->states_head; NULL != s; s = s_next)
1131   {
1132     s_next = s->next;
1133     if (GNUNET_NO == s->marked)
1134       automaton_remove_state (a, s);
1135   }
1136 }
1137
1138 /**
1139  * Remove all dead states from the DFA 'a'. Dead states are those states that do
1140  * not transition to any other state but themselfes.
1141  *
1142  * @param a DFA automaton
1143  */
1144 static void
1145 dfa_remove_dead_states (struct GNUNET_REGEX_Automaton *a)
1146 {
1147   struct GNUNET_REGEX_State *s;
1148   struct Transition *t;
1149   int dead;
1150
1151   GNUNET_assert (DFA == a->type);
1152
1153   for (s = a->states_head; NULL != s; s = s->next)
1154   {
1155     if (s->accepting)
1156       continue;
1157
1158     dead = 1;
1159     for (t = s->transitions_head; NULL != t; t = t->next)
1160     {
1161       if (NULL != t->to_state && t->to_state != s)
1162       {
1163         dead = 0;
1164         break;
1165       }
1166     }
1167
1168     if (0 == dead)
1169       continue;
1170
1171     // state s is dead, remove it
1172     automaton_remove_state (a, s);
1173   }
1174 }
1175
1176 /**
1177  * Merge all non distinguishable states in the DFA 'a'
1178  *
1179  * @param ctx context
1180  * @param a DFA automaton
1181  */
1182 static void
1183 dfa_merge_nondistinguishable_states (struct GNUNET_REGEX_Context *ctx,
1184                                      struct GNUNET_REGEX_Automaton *a)
1185 {
1186   int i;
1187   int table[a->state_count][a->state_count];
1188   struct GNUNET_REGEX_State *s1;
1189   struct GNUNET_REGEX_State *s2;
1190   struct Transition *t1;
1191   struct Transition *t2;
1192   struct GNUNET_REGEX_State *s1_next;
1193   struct GNUNET_REGEX_State *s2_next;
1194   int change;
1195   int num_equal_edges;
1196
1197   for (i = 0, s1 = a->states_head; i < a->state_count && NULL != s1;
1198        i++, s1 = s1->next)
1199   {
1200     s1->marked = i;
1201   }
1202
1203   // Mark all pairs of accepting/!accepting states
1204   for (s1 = a->states_head; NULL != s1; s1 = s1->next)
1205   {
1206     for (s2 = a->states_head; NULL != s2; s2 = s2->next)
1207     {
1208       table[s1->marked][s2->marked] = 0;
1209
1210       if ((s1->accepting && !s2->accepting) ||
1211           (!s1->accepting && s2->accepting))
1212       {
1213         table[s1->marked][s2->marked] = 1;
1214       }
1215     }
1216   }
1217
1218   // Find all equal states
1219   change = 1;
1220   while (0 != change)
1221   {
1222     change = 0;
1223     for (s1 = a->states_head; NULL != s1; s1 = s1->next)
1224     {
1225       for (s2 = a->states_head; NULL != s2 && s1 != s2; s2 = s2->next)
1226       {
1227         if (0 != table[s1->marked][s2->marked])
1228           continue;
1229
1230         num_equal_edges = 0;
1231         for (t1 = s1->transitions_head; NULL != t1; t1 = t1->next)
1232         {
1233           for (t2 = s2->transitions_head; NULL != t2; t2 = t2->next)
1234           {
1235             if (t1->label == t2->label)
1236             {
1237               num_equal_edges++;
1238               if (0 != table[t1->to_state->marked][t2->to_state->marked] ||
1239                   0 != table[t2->to_state->marked][t1->to_state->marked])
1240               {
1241                 table[s1->marked][s2->marked] = t1->label != 0 ? t1->label : 1;
1242                 change = 1;
1243               }
1244             }
1245           }
1246         }
1247         if (num_equal_edges != s1->transition_count ||
1248             num_equal_edges != s2->transition_count)
1249         {
1250           // Make sure ALL edges of possible equal states are the same
1251           table[s1->marked][s2->marked] = -2;
1252         }
1253       }
1254     }
1255   }
1256
1257   // Merge states that are equal
1258   for (s1 = a->states_head; NULL != s1; s1 = s1_next)
1259   {
1260     s1_next = s1->next;
1261     for (s2 = a->states_head; NULL != s2 && s1 != s2; s2 = s2_next)
1262     {
1263       s2_next = s2->next;
1264       if (table[s1->marked][s2->marked] == 0)
1265         automaton_merge_states (ctx, a, s1, s2);
1266     }
1267   }
1268 }
1269
1270 /**
1271  * Minimize the given DFA 'a' by removing all unreachable states, removing all
1272  * dead states and merging all non distinguishable states
1273  *
1274  * @param ctx context
1275  * @param a DFA automaton
1276  */
1277 static void
1278 dfa_minimize (struct GNUNET_REGEX_Context *ctx,
1279               struct GNUNET_REGEX_Automaton *a)
1280 {
1281   if (NULL == a)
1282     return;
1283
1284   GNUNET_assert (DFA == a->type);
1285
1286   // 1. remove unreachable states
1287   dfa_remove_unreachable_states (a);
1288
1289   // 2. remove dead states
1290   dfa_remove_dead_states (a);
1291
1292   // 3. Merge nondistinguishable states
1293   dfa_merge_nondistinguishable_states (ctx, a);
1294 }
1295
1296 /**
1297  * Creates a new NFA fragment. Needs to be cleared using
1298  * automaton_fragment_clear.
1299  *
1300  * @param start starting state
1301  * @param end end state
1302  *
1303  * @return new NFA fragment
1304  */
1305 static struct GNUNET_REGEX_Automaton *
1306 nfa_fragment_create (struct GNUNET_REGEX_State *start,
1307                      struct GNUNET_REGEX_State *end)
1308 {
1309   struct GNUNET_REGEX_Automaton *n;
1310
1311   n = GNUNET_malloc (sizeof (struct GNUNET_REGEX_Automaton));
1312
1313   n->type = NFA;
1314   n->start = NULL;
1315   n->end = NULL;
1316
1317   if (NULL == start && NULL == end)
1318     return n;
1319
1320   automaton_add_state (n, end);
1321   automaton_add_state (n, start);
1322
1323   n->start = start;
1324   n->end = end;
1325
1326   return n;
1327 }
1328
1329 /**
1330  * Adds a list of states to the given automaton 'n'.
1331  *
1332  * @param n automaton to which the states should be added
1333  * @param states_head head of the DLL of states
1334  * @param states_tail tail of the DLL of states
1335  */
1336 static void
1337 nfa_add_states (struct GNUNET_REGEX_Automaton *n,
1338                 struct GNUNET_REGEX_State *states_head,
1339                 struct GNUNET_REGEX_State *states_tail)
1340 {
1341   struct GNUNET_REGEX_State *s;
1342
1343   if (NULL == n || NULL == states_head)
1344   {
1345     GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "Could not add states\n");
1346     return;
1347   }
1348
1349   if (NULL == n->states_head)
1350   {
1351     n->states_head = states_head;
1352     n->states_tail = states_tail;
1353     return;
1354   }
1355
1356   if (NULL != states_head)
1357   {
1358     n->states_tail->next = states_head;
1359     n->states_tail = states_tail;
1360   }
1361
1362   for (s = states_head; NULL != s; s = s->next)
1363     n->state_count++;
1364 }
1365
1366 /**
1367  * Creates a new NFA state. Needs to be freed using automaton_destroy_state.
1368  *
1369  * @param ctx context
1370  * @param accepting is it an accepting state or not
1371  *
1372  * @return new NFA state
1373  */
1374 static struct GNUNET_REGEX_State *
1375 nfa_state_create (struct GNUNET_REGEX_Context *ctx, int accepting)
1376 {
1377   struct GNUNET_REGEX_State *s;
1378
1379   s = GNUNET_malloc (sizeof (struct GNUNET_REGEX_State));
1380   s->id = ctx->state_id++;
1381   s->accepting = accepting;
1382   s->marked = 0;
1383   s->contained = 0;
1384   s->index = -1;
1385   s->lowlink = -1;
1386   s->scc_id = 0;
1387   s->name = NULL;
1388   GNUNET_asprintf (&s->name, "s%i", s->id);
1389
1390   return s;
1391 }
1392
1393 /**
1394  * Calculates the NFA closure set for the given state.
1395  *
1396  * @param nfa the NFA containing 's'
1397  * @param s starting point state
1398  * @param label transitioning label on which to base the closure on,
1399  *                pass 0 for epsilon transition
1400  *
1401  * @return sorted nfa closure on 'label' (epsilon closure if 'label' is 0)
1402  */
1403 static struct GNUNET_REGEX_StateSet *
1404 nfa_closure_create (struct GNUNET_REGEX_Automaton *nfa,
1405                     struct GNUNET_REGEX_State *s, const char label)
1406 {
1407   struct GNUNET_REGEX_StateSet *cls;
1408   struct GNUNET_REGEX_StateSet *cls_check;
1409   struct GNUNET_REGEX_State *clsstate;
1410   struct GNUNET_REGEX_State *currentstate;
1411   struct Transition *ctran;
1412
1413   if (NULL == s)
1414     return NULL;
1415
1416   cls = GNUNET_malloc (sizeof (struct GNUNET_REGEX_StateSet));
1417   cls_check = GNUNET_malloc (sizeof (struct GNUNET_REGEX_StateSet));
1418
1419   for (clsstate = nfa->states_head; NULL != clsstate; clsstate = clsstate->next)
1420     clsstate->contained = 0;
1421
1422   // Add start state to closure only for epsilon closure
1423   if (0 == label)
1424     GNUNET_array_append (cls->states, cls->len, s);
1425
1426   GNUNET_array_append (cls_check->states, cls_check->len, s);
1427   while (cls_check->len > 0)
1428   {
1429     currentstate = cls_check->states[cls_check->len - 1];
1430     GNUNET_array_grow (cls_check->states, cls_check->len, cls_check->len - 1);
1431
1432     for (ctran = currentstate->transitions_head; NULL != ctran;
1433          ctran = ctran->next)
1434     {
1435       if (NULL != ctran->to_state && label == ctran->label)
1436       {
1437         clsstate = ctran->to_state;
1438
1439         if (NULL != clsstate && 0 == clsstate->contained)
1440         {
1441           GNUNET_array_append (cls->states, cls->len, clsstate);
1442           GNUNET_array_append (cls_check->states, cls_check->len, clsstate);
1443           clsstate->contained = 1;
1444         }
1445       }
1446     }
1447   }
1448   GNUNET_assert (0 == cls_check->len);
1449   GNUNET_free (cls_check);
1450
1451   if (cls->len > 1)
1452     qsort (cls->states, cls->len, sizeof (struct GNUNET_REGEX_State *),
1453            state_compare);
1454
1455   return cls;
1456 }
1457
1458 /**
1459  * Calculates the closure set for the given set of states.
1460  *
1461  * @param nfa the NFA containing 's'
1462  * @param states list of states on which to base the closure on
1463  * @param label transitioning label for which to base the closure on,
1464  *                pass 0 for epsilon transition
1465  *
1466  * @return sorted nfa closure on 'label' (epsilon closure if 'label' is 0)
1467  */
1468 static struct GNUNET_REGEX_StateSet *
1469 nfa_closure_set_create (struct GNUNET_REGEX_Automaton *nfa,
1470                         struct GNUNET_REGEX_StateSet *states, const char label)
1471 {
1472   struct GNUNET_REGEX_State *s;
1473   struct GNUNET_REGEX_StateSet *sset;
1474   struct GNUNET_REGEX_StateSet *cls;
1475   int i;
1476   int j;
1477   int k;
1478   int contains;
1479
1480   if (NULL == states)
1481     return NULL;
1482
1483   cls = GNUNET_malloc (sizeof (struct GNUNET_REGEX_StateSet));
1484
1485   for (i = 0; i < states->len; i++)
1486   {
1487     s = states->states[i];
1488     sset = nfa_closure_create (nfa, s, label);
1489
1490     for (j = 0; j < sset->len; j++)
1491     {
1492       contains = 0;
1493       for (k = 0; k < cls->len; k++)
1494       {
1495         if (sset->states[j]->id == cls->states[k]->id)
1496         {
1497           contains = 1;
1498           break;
1499         }
1500       }
1501       if (!contains)
1502         GNUNET_array_append (cls->states, cls->len, sset->states[j]);
1503     }
1504     state_set_clear (sset);
1505   }
1506
1507   if (cls->len > 1)
1508     qsort (cls->states, cls->len, sizeof (struct GNUNET_REGEX_State *),
1509            state_compare);
1510
1511   return cls;
1512 }
1513
1514 /**
1515  * Pops two NFA fragments (a, b) from the stack and concatenates them (ab)
1516  *
1517  * @param ctx context
1518  */
1519 static void
1520 nfa_add_concatenation (struct GNUNET_REGEX_Context *ctx)
1521 {
1522   struct GNUNET_REGEX_Automaton *a;
1523   struct GNUNET_REGEX_Automaton *b;
1524   struct GNUNET_REGEX_Automaton *new;
1525
1526   b = ctx->stack_tail;
1527   GNUNET_CONTAINER_DLL_remove (ctx->stack_head, ctx->stack_tail, b);
1528   a = ctx->stack_tail;
1529   GNUNET_CONTAINER_DLL_remove (ctx->stack_head, ctx->stack_tail, a);
1530
1531   state_add_transition (ctx, a->end, 0, b->start);
1532   a->end->accepting = 0;
1533   b->end->accepting = 1;
1534
1535   new = nfa_fragment_create (NULL, NULL);
1536   nfa_add_states (new, a->states_head, a->states_tail);
1537   nfa_add_states (new, b->states_head, b->states_tail);
1538   new->start = a->start;
1539   new->end = b->end;
1540   automaton_fragment_clear (a);
1541   automaton_fragment_clear (b);
1542
1543   GNUNET_CONTAINER_DLL_insert_tail (ctx->stack_head, ctx->stack_tail, new);
1544 }
1545
1546 /**
1547  * Pops a NFA fragment from the stack (a) and adds a new fragment (a*)
1548  *
1549  * @param ctx context
1550  */
1551 static void
1552 nfa_add_star_op (struct GNUNET_REGEX_Context *ctx)
1553 {
1554   struct GNUNET_REGEX_Automaton *a;
1555   struct GNUNET_REGEX_Automaton *new;
1556   struct GNUNET_REGEX_State *start;
1557   struct GNUNET_REGEX_State *end;
1558
1559   a = ctx->stack_tail;
1560   GNUNET_CONTAINER_DLL_remove (ctx->stack_head, ctx->stack_tail, a);
1561
1562   if (NULL == a)
1563   {
1564     GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
1565                 "nfa_add_star_op failed, because there was no element on the stack");
1566     return;
1567   }
1568
1569   start = nfa_state_create (ctx, 0);
1570   end = nfa_state_create (ctx, 1);
1571
1572   state_add_transition (ctx, start, 0, a->start);
1573   state_add_transition (ctx, start, 0, end);
1574   state_add_transition (ctx, a->end, 0, a->start);
1575   state_add_transition (ctx, a->end, 0, end);
1576
1577   a->end->accepting = 0;
1578   end->accepting = 1;
1579
1580   new = nfa_fragment_create (start, end);
1581   nfa_add_states (new, a->states_head, a->states_tail);
1582   automaton_fragment_clear (a);
1583
1584   GNUNET_CONTAINER_DLL_insert_tail (ctx->stack_head, ctx->stack_tail, new);
1585 }
1586
1587 /**
1588  * Pops an NFA fragment (a) from the stack and adds a new fragment (a+)
1589  *
1590  * @param ctx context
1591  */
1592 static void
1593 nfa_add_plus_op (struct GNUNET_REGEX_Context *ctx)
1594 {
1595   struct GNUNET_REGEX_Automaton *a;
1596
1597   a = ctx->stack_tail;
1598   GNUNET_CONTAINER_DLL_remove (ctx->stack_head, ctx->stack_tail, a);
1599
1600   state_add_transition (ctx, a->end, 0, a->start);
1601
1602   GNUNET_CONTAINER_DLL_insert_tail (ctx->stack_head, ctx->stack_tail, a);
1603 }
1604
1605 /**
1606  * Pops an NFA fragment (a) from the stack and adds a new fragment (a?)
1607  *
1608  * @param ctx context
1609  */
1610 static void
1611 nfa_add_question_op (struct GNUNET_REGEX_Context *ctx)
1612 {
1613   struct GNUNET_REGEX_Automaton *a;
1614   struct GNUNET_REGEX_Automaton *new;
1615   struct GNUNET_REGEX_State *start;
1616   struct GNUNET_REGEX_State *end;
1617
1618   a = ctx->stack_tail;
1619   GNUNET_CONTAINER_DLL_remove (ctx->stack_head, ctx->stack_tail, a);
1620
1621   if (NULL == a)
1622   {
1623     GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
1624                 "nfa_add_question_op failed, because there was no element on the stack");
1625     return;
1626   }
1627
1628   start = nfa_state_create (ctx, 0);
1629   end = nfa_state_create (ctx, 1);
1630
1631   state_add_transition (ctx, start, 0, a->start);
1632   state_add_transition (ctx, start, 0, end);
1633   state_add_transition (ctx, a->end, 0, end);
1634
1635   a->end->accepting = 0;
1636
1637   new = nfa_fragment_create (start, end);
1638   nfa_add_states (new, a->states_head, a->states_tail);
1639   automaton_fragment_clear (a);
1640
1641   GNUNET_CONTAINER_DLL_insert_tail (ctx->stack_head, ctx->stack_tail, new);
1642 }
1643
1644 /**
1645  * Pops two NFA fragments (a, b) from the stack and adds a new NFA fragment that
1646  * alternates between a and b (a|b)
1647  *
1648  * @param ctx context
1649  */
1650 static void
1651 nfa_add_alternation (struct GNUNET_REGEX_Context *ctx)
1652 {
1653   struct GNUNET_REGEX_Automaton *a;
1654   struct GNUNET_REGEX_Automaton *b;
1655   struct GNUNET_REGEX_Automaton *new;
1656   struct GNUNET_REGEX_State *start;
1657   struct GNUNET_REGEX_State *end;
1658
1659   b = ctx->stack_tail;
1660   GNUNET_CONTAINER_DLL_remove (ctx->stack_head, ctx->stack_tail, b);
1661   a = ctx->stack_tail;
1662   GNUNET_CONTAINER_DLL_remove (ctx->stack_head, ctx->stack_tail, a);
1663
1664   start = nfa_state_create (ctx, 0);
1665   end = nfa_state_create (ctx, 1);
1666   state_add_transition (ctx, start, 0, a->start);
1667   state_add_transition (ctx, start, 0, b->start);
1668
1669   state_add_transition (ctx, a->end, 0, end);
1670   state_add_transition (ctx, b->end, 0, end);
1671
1672   a->end->accepting = 0;
1673   b->end->accepting = 0;
1674   end->accepting = 1;
1675
1676   new = nfa_fragment_create (start, end);
1677   nfa_add_states (new, a->states_head, a->states_tail);
1678   nfa_add_states (new, b->states_head, b->states_tail);
1679   automaton_fragment_clear (a);
1680   automaton_fragment_clear (b);
1681
1682   GNUNET_CONTAINER_DLL_insert_tail (ctx->stack_head, ctx->stack_tail, new);
1683 }
1684
1685 /**
1686  * Adds a new nfa fragment to the stack
1687  *
1688  * @param ctx context
1689  * @param lit label for nfa transition
1690  */
1691 static void
1692 nfa_add_label (struct GNUNET_REGEX_Context *ctx, const char lit)
1693 {
1694   struct GNUNET_REGEX_Automaton *n;
1695   struct GNUNET_REGEX_State *start;
1696   struct GNUNET_REGEX_State *end;
1697
1698   GNUNET_assert (NULL != ctx);
1699
1700   start = nfa_state_create (ctx, 0);
1701   end = nfa_state_create (ctx, 1);
1702   state_add_transition (ctx, start, lit, end);
1703   n = nfa_fragment_create (start, end);
1704   GNUNET_assert (NULL != n);
1705   GNUNET_CONTAINER_DLL_insert_tail (ctx->stack_head, ctx->stack_tail, n);
1706 }
1707
1708 /**
1709  * Initialize a new context
1710  *
1711  * @param ctx context
1712  */
1713 static void
1714 GNUNET_REGEX_context_init (struct GNUNET_REGEX_Context *ctx)
1715 {
1716   if (NULL == ctx)
1717   {
1718     GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "Context was NULL!");
1719     return;
1720   }
1721   ctx->state_id = 0;
1722   ctx->transition_id = 0;
1723   ctx->scc_id = 0;
1724   ctx->stack_head = NULL;
1725   ctx->stack_tail = NULL;
1726 }
1727
1728 /**
1729  * Construct an NFA by parsing the regex string of length 'len'.
1730  *
1731  * @param regex regular expression string
1732  * @param len length of the string
1733  *
1734  * @return NFA, needs to be freed using GNUNET_REGEX_destroy_automaton
1735  */
1736 struct GNUNET_REGEX_Automaton *
1737 GNUNET_REGEX_construct_nfa (const char *regex, const size_t len)
1738 {
1739   struct GNUNET_REGEX_Context ctx;
1740   struct GNUNET_REGEX_Automaton *nfa;
1741   const char *regexp;
1742   char *error_msg;
1743   unsigned int count;
1744   unsigned int altcount;
1745   unsigned int atomcount;
1746   unsigned int pcount;
1747   struct
1748   {
1749     int altcount;
1750     int atomcount;
1751   }     *p;
1752
1753   GNUNET_REGEX_context_init (&ctx);
1754
1755   regexp = regex;
1756   p = NULL;
1757   error_msg = NULL;
1758   altcount = 0;
1759   atomcount = 0;
1760   pcount = 0;
1761
1762   for (count = 0; count < len && *regexp; count++, regexp++)
1763   {
1764     switch (*regexp)
1765     {
1766     case '(':
1767       if (atomcount > 1)
1768       {
1769         --atomcount;
1770         nfa_add_concatenation (&ctx);
1771       }
1772       GNUNET_array_grow (p, pcount, pcount + 1);
1773       p[pcount - 1].altcount = altcount;
1774       p[pcount - 1].atomcount = atomcount;
1775       altcount = 0;
1776       atomcount = 0;
1777       break;
1778     case '|':
1779       if (0 == atomcount)
1780       {
1781         error_msg = "Cannot append '|' to nothing";
1782         goto error;
1783       }
1784       while (--atomcount > 0)
1785         nfa_add_concatenation (&ctx);
1786       altcount++;
1787       break;
1788     case ')':
1789       if (0 == pcount)
1790       {
1791         error_msg = "Missing opening '('";
1792         goto error;
1793       }
1794       if (0 == atomcount)
1795       {
1796         // Ignore this: "()"
1797         pcount--;
1798         altcount = p[pcount].altcount;
1799         atomcount = p[pcount].atomcount;
1800         break;
1801       }
1802       while (--atomcount > 0)
1803         nfa_add_concatenation (&ctx);
1804       for (; altcount > 0; altcount--)
1805         nfa_add_alternation (&ctx);
1806       pcount--;
1807       altcount = p[pcount].altcount;
1808       atomcount = p[pcount].atomcount;
1809       atomcount++;
1810       break;
1811     case '*':
1812       if (atomcount == 0)
1813       {
1814         error_msg = "Cannot append '*' to nothing";
1815         goto error;
1816       }
1817       nfa_add_star_op (&ctx);
1818       break;
1819     case '+':
1820       if (atomcount == 0)
1821       {
1822         error_msg = "Cannot append '+' to nothing";
1823         goto error;
1824       }
1825       nfa_add_plus_op (&ctx);
1826       break;
1827     case '?':
1828       if (atomcount == 0)
1829       {
1830         error_msg = "Cannot append '?' to nothing";
1831         goto error;
1832       }
1833       nfa_add_question_op (&ctx);
1834       break;
1835     case 92:                   /* escape: \ */
1836       regexp++;
1837       count++;
1838     default:
1839       if (atomcount > 1)
1840       {
1841         --atomcount;
1842         nfa_add_concatenation (&ctx);
1843       }
1844       nfa_add_label (&ctx, *regexp);
1845       atomcount++;
1846       break;
1847     }
1848   }
1849   if (0 != pcount)
1850   {
1851     error_msg = "Unbalanced parenthesis";
1852     goto error;
1853   }
1854   while (--atomcount > 0)
1855     nfa_add_concatenation (&ctx);
1856   for (; altcount > 0; altcount--)
1857     nfa_add_alternation (&ctx);
1858
1859   GNUNET_free_non_null (p);
1860
1861   nfa = ctx.stack_tail;
1862   GNUNET_CONTAINER_DLL_remove (ctx.stack_head, ctx.stack_tail, nfa);
1863
1864   if (NULL != ctx.stack_head)
1865   {
1866     error_msg = "Creating the NFA failed. NFA stack was not empty!";
1867     goto error;
1868   }
1869
1870   return nfa;
1871
1872 error:
1873   GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "Could not parse regex\n");
1874   if (NULL != error_msg)
1875     GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "%s\n", error_msg);
1876
1877   GNUNET_free_non_null (p);
1878
1879   while (NULL != ctx.stack_tail)
1880   {
1881     GNUNET_REGEX_automaton_destroy (ctx.stack_tail);
1882     GNUNET_CONTAINER_DLL_remove (ctx.stack_head, ctx.stack_tail,
1883                                  ctx.stack_tail);
1884   }
1885   return NULL;
1886 }
1887
1888 /**
1889  * Create DFA states based on given 'nfa' and starting with 'dfa_state'.
1890  *
1891  * @param ctx context.
1892  * @param nfa NFA automaton.
1893  * @param dfa DFA automaton.
1894  * @param dfa_state current dfa state, pass epsilon closure of first nfa state
1895  *                  for starting.
1896  */
1897 static void
1898 construct_dfa_states (struct GNUNET_REGEX_Context *ctx,
1899                       struct GNUNET_REGEX_Automaton *nfa,
1900                       struct GNUNET_REGEX_Automaton *dfa,
1901                       struct GNUNET_REGEX_State *dfa_state)
1902 {
1903   struct Transition *ctran;
1904   struct GNUNET_REGEX_State *state_iter;
1905   struct GNUNET_REGEX_State *new_dfa_state;
1906   struct GNUNET_REGEX_State *state_contains;
1907   struct GNUNET_REGEX_StateSet *tmp;
1908   struct GNUNET_REGEX_StateSet *nfa_set;
1909
1910   for (ctran = dfa_state->transitions_head; NULL != ctran; ctran = ctran->next)
1911   {
1912     if (0 == ctran->label || NULL != ctran->to_state)
1913       continue;
1914
1915     tmp = nfa_closure_set_create (nfa, dfa_state->nfa_set, ctran->label);
1916     nfa_set = nfa_closure_set_create (nfa, tmp, 0);
1917     state_set_clear (tmp);
1918     new_dfa_state = dfa_state_create (ctx, nfa_set);
1919     state_contains = NULL;
1920     for (state_iter = dfa->states_head; NULL != state_iter;
1921          state_iter = state_iter->next)
1922     {
1923       if (0 == state_set_compare (state_iter->nfa_set, new_dfa_state->nfa_set))
1924         state_contains = state_iter;
1925     }
1926
1927     if (NULL == state_contains)
1928     {
1929       automaton_add_state (dfa, new_dfa_state);
1930       ctran->to_state = new_dfa_state;
1931       construct_dfa_states (ctx, nfa, dfa, new_dfa_state);
1932     }
1933     else
1934     {
1935       ctran->to_state = state_contains;
1936       automaton_destroy_state (new_dfa_state);
1937     }
1938   }
1939 }
1940
1941 /**
1942  * Construct DFA for the given 'regex' of length 'len'
1943  *
1944  * @param regex regular expression string
1945  * @param len length of the regular expression
1946  *
1947  * @return DFA, needs to be freed using GNUNET_REGEX_destroy_automaton
1948  */
1949 struct GNUNET_REGEX_Automaton *
1950 GNUNET_REGEX_construct_dfa (const char *regex, const size_t len)
1951 {
1952   struct GNUNET_REGEX_Context ctx;
1953   struct GNUNET_REGEX_Automaton *dfa;
1954   struct GNUNET_REGEX_Automaton *nfa;
1955   struct GNUNET_REGEX_StateSet *nfa_set;
1956
1957   GNUNET_REGEX_context_init (&ctx);
1958
1959   // Create NFA
1960   nfa = GNUNET_REGEX_construct_nfa (regex, len);
1961
1962   if (NULL == nfa)
1963   {
1964     GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
1965                 "Could not create DFA, because NFA creation failed\n");
1966     return NULL;
1967   }
1968
1969   dfa = GNUNET_malloc (sizeof (struct GNUNET_REGEX_Automaton));
1970   dfa->type = DFA;
1971
1972   // Create DFA start state from epsilon closure
1973   nfa_set = nfa_closure_create (nfa, nfa->start, 0);
1974   dfa->start = dfa_state_create (&ctx, nfa_set);
1975   automaton_add_state (dfa, dfa->start);
1976
1977   construct_dfa_states (&ctx, nfa, dfa, dfa->start);
1978
1979   GNUNET_REGEX_automaton_destroy (nfa);
1980
1981   // Minimize DFA
1982   dfa_minimize (&ctx, dfa);
1983
1984   // Calculate SCCs
1985   scc_tarjan (&ctx, dfa);
1986
1987   // Create proofs for all states
1988   automaton_create_proofs (dfa);
1989
1990   return dfa;
1991 }
1992
1993 /**
1994  * Free the memory allocated by constructing the GNUNET_REGEX_Automaton data
1995  * structure.
1996  *
1997  * @param a automaton to be destroyed
1998  */
1999 void
2000 GNUNET_REGEX_automaton_destroy (struct GNUNET_REGEX_Automaton *a)
2001 {
2002   struct GNUNET_REGEX_State *s;
2003   struct GNUNET_REGEX_State *next_state;
2004
2005   if (NULL == a)
2006     return;
2007
2008   for (s = a->states_head; NULL != s;)
2009   {
2010     next_state = s->next;
2011     automaton_destroy_state (s);
2012     s = next_state;
2013   }
2014
2015   GNUNET_free (a);
2016 }
2017
2018 /**
2019  * Save the given automaton as a GraphViz dot file
2020  *
2021  * @param a the automaton to be saved
2022  * @param filename where to save the file
2023  */
2024 void
2025 GNUNET_REGEX_automaton_save_graph (struct GNUNET_REGEX_Automaton *a,
2026                                    const char *filename)
2027 {
2028   struct GNUNET_REGEX_State *s;
2029   struct Transition *ctran;
2030   char *s_acc = NULL;
2031   char *s_tran = NULL;
2032   char *start;
2033   char *end;
2034   FILE *p;
2035
2036   if (NULL == a)
2037   {
2038     GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "Could not print NFA, was NULL!");
2039     return;
2040   }
2041
2042   if (NULL == filename || strlen (filename) < 1)
2043   {
2044     GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "No Filename given!");
2045     return;
2046   }
2047
2048   p = fopen (filename, "w");
2049
2050   if (NULL == p)
2051   {
2052     GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "Could not open file for writing: %s",
2053                 filename);
2054     return;
2055   }
2056
2057   start = "digraph G {\nrankdir=LR\n";
2058   fwrite (start, strlen (start), 1, p);
2059
2060   for (s = a->states_head; NULL != s; s = s->next)
2061   {
2062     if (s->accepting)
2063     {
2064       GNUNET_asprintf (&s_acc,
2065                        "\"%s\" [shape=doublecircle, color=\"0.%i 0.8 0.95\"];\n",
2066                        s->name, s->scc_id);
2067     }
2068     else
2069     {
2070       GNUNET_asprintf (&s_acc, "\"%s\" [color=\"0.%i 0.8 0.95\"];\n", s->name,
2071                        s->scc_id);
2072     }
2073
2074     if (NULL == s_acc)
2075     {
2076       GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "Could not print state %s\n",
2077                   s->name);
2078       return;
2079     }
2080     fwrite (s_acc, strlen (s_acc), 1, p);
2081     GNUNET_free (s_acc);
2082     s_acc = NULL;
2083
2084     for (ctran = s->transitions_head; NULL != ctran; ctran = ctran->next)
2085     {
2086       if (NULL == ctran->to_state)
2087       {
2088         GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
2089                     "Transition from State %i has has no state for transitioning\n",
2090                     s->id);
2091         continue;
2092       }
2093
2094       if (ctran->label == 0)
2095       {
2096         GNUNET_asprintf (&s_tran,
2097                          "\"%s\" -> \"%s\" [label = \"epsilon\", color=\"0.%i 0.8 0.95\"];\n",
2098                          s->name, ctran->to_state->name, s->scc_id);
2099       }
2100       else
2101       {
2102         GNUNET_asprintf (&s_tran,
2103                          "\"%s\" -> \"%s\" [label = \"%c\", color=\"0.%i 0.8 0.95\"];\n",
2104                          s->name, ctran->to_state->name, ctran->label,
2105                          s->scc_id);
2106       }
2107
2108       if (NULL == s_tran)
2109       {
2110         GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "Could not print state %s\n",
2111                     s->name);
2112         return;
2113       }
2114
2115       fwrite (s_tran, strlen (s_tran), 1, p);
2116       GNUNET_free (s_tran);
2117       s_tran = NULL;
2118     }
2119   }
2120
2121   end = "\n}\n";
2122   fwrite (end, strlen (end), 1, p);
2123   fclose (p);
2124 }
2125
2126 /**
2127  * Evaluates the given string using the given DFA automaton
2128  *
2129  * @param a automaton, type must be DFA
2130  * @param string string that should be evaluated
2131  *
2132  * @return 0 if string matches, non 0 otherwise
2133  */
2134 static int
2135 evaluate_dfa (struct GNUNET_REGEX_Automaton *a, const char *string)
2136 {
2137   const char *strp;
2138   struct GNUNET_REGEX_State *s;
2139
2140   if (DFA != a->type)
2141   {
2142     GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
2143                 "Tried to evaluate DFA, but NFA automaton given");
2144     return -1;
2145   }
2146
2147   s = a->start;
2148
2149   for (strp = string; NULL != strp && *strp; strp++)
2150   {
2151     s = dfa_move (s, *strp);
2152     if (NULL == s)
2153       break;
2154   }
2155
2156   if (NULL != s && s->accepting)
2157     return 0;
2158
2159   return 1;
2160 }
2161
2162 /**
2163  * Evaluates the given string using the given NFA automaton
2164  *
2165  * @param a automaton, type must be NFA
2166  * @param string string that should be evaluated
2167  *
2168  * @return 0 if string matches, non 0 otherwise
2169  */
2170 static int
2171 evaluate_nfa (struct GNUNET_REGEX_Automaton *a, const char *string)
2172 {
2173   const char *strp;
2174   struct GNUNET_REGEX_State *s;
2175   struct GNUNET_REGEX_StateSet *sset;
2176   struct GNUNET_REGEX_StateSet *new_sset;
2177   int i;
2178   int result;
2179
2180   if (NFA != a->type)
2181   {
2182     GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
2183                 "Tried to evaluate NFA, but DFA automaton given");
2184     return -1;
2185   }
2186
2187   result = 1;
2188   strp = string;
2189   sset = nfa_closure_create (a, a->start, 0);
2190
2191   for (strp = string; NULL != strp && *strp; strp++)
2192   {
2193     new_sset = nfa_closure_set_create (a, sset, *strp);
2194     state_set_clear (sset);
2195     sset = nfa_closure_set_create (a, new_sset, 0);
2196     state_set_clear (new_sset);
2197   }
2198
2199   for (i = 0; i < sset->len; i++)
2200   {
2201     s = sset->states[i];
2202     if (NULL != s && s->accepting)
2203     {
2204       result = 0;
2205       break;
2206     }
2207   }
2208
2209   state_set_clear (sset);
2210   return result;
2211 }
2212
2213 /**
2214  * Evaluates the given 'string' against the given compiled regex
2215  *
2216  * @param a automaton
2217  * @param string string to check
2218  *
2219  * @return 0 if string matches, non 0 otherwise
2220  */
2221 int
2222 GNUNET_REGEX_eval (struct GNUNET_REGEX_Automaton *a, const char *string)
2223 {
2224   int result;
2225
2226   switch (a->type)
2227   {
2228   case DFA:
2229     result = evaluate_dfa (a, string);
2230     break;
2231   case NFA:
2232     result = evaluate_nfa (a, string);
2233     break;
2234   default:
2235     GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
2236                 "Evaluating regex failed, automaton has no type!\n");
2237     result = GNUNET_SYSERR;
2238     break;
2239   }
2240
2241   return result;
2242 }
2243
2244 /**
2245  * Get the first key for the given 'input_string'. This hashes the first x bits
2246  * of the 'input_strings'.
2247  *
2248  * @param input_string string.
2249  * @param string_len length of the 'input_string'.
2250  * @param key pointer to where to write the hash code.
2251  *
2252  * @return number of bits of 'input_string' that have been consumed
2253  *         to construct the key
2254  */
2255 unsigned int
2256 GNUNET_REGEX_get_first_key (const char *input_string, unsigned int string_len,
2257                             GNUNET_HashCode * key)
2258 {
2259   unsigned int size;
2260
2261   size = string_len < initial_bits ? string_len : initial_bits;
2262
2263   if (NULL == input_string)
2264   {
2265     GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "Given input string was NULL!\n");
2266     return 0;
2267   }
2268
2269   GNUNET_CRYPTO_hash (input_string, size, key);
2270
2271   return size;
2272 }
2273
2274 /**
2275  * Check if the given 'proof' matches the given 'key'.
2276  *
2277  * @param proof partial regex
2278  * @param key hash
2279  *
2280  * @return GNUNET_OK if the proof is valid for the given key
2281  */
2282 int
2283 GNUNET_REGEX_check_proof (const char *proof, const GNUNET_HashCode * key)
2284 {
2285   return GNUNET_OK;
2286 }
2287
2288 /**
2289  * Iterate over all edges helper function starting from state 's', calling
2290  * iterator on for each edge.
2291  *
2292  * @param s state.
2293  * @param iterator iterator function called for each edge.
2294  * @param iterator_cls closure.
2295  */
2296 static void
2297 iterate_edge (struct GNUNET_REGEX_State *s, GNUNET_REGEX_KeyIterator iterator,
2298               void *iterator_cls)
2299 {
2300   struct Transition *t;
2301   struct GNUNET_REGEX_Edge edges[s->transition_count];
2302   unsigned int num_edges;
2303
2304   if (GNUNET_YES != s->marked)
2305   {
2306     s->marked = GNUNET_YES;
2307
2308     num_edges = state_get_edges (s, edges);
2309
2310     iterator (iterator_cls, &s->hash, s->proof, s->accepting, num_edges, edges);
2311
2312     for (t = s->transitions_head; NULL != t; t = t->next)
2313       iterate_edge (t->to_state, iterator, iterator_cls);
2314   }
2315 }
2316
2317 /**
2318  * Iterate over all edges starting from start state of automaton 'a'. Calling
2319  * iterator for each edge.
2320  *
2321  * @param a automaton.
2322  * @param iterator iterator called for each edge.
2323  * @param iterator_cls closure.
2324  */
2325 void
2326 GNUNET_REGEX_iterate_all_edges (struct GNUNET_REGEX_Automaton *a,
2327                                 GNUNET_REGEX_KeyIterator iterator,
2328                                 void *iterator_cls)
2329 {
2330   struct GNUNET_REGEX_State *s;
2331
2332   for (s = a->states_head; NULL != s; s = s->next)
2333     s->marked = GNUNET_NO;
2334
2335   iterate_edge (a->start, iterator, iterator_cls);
2336 }