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