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