4d5669ac05ff41634ba45cedcb41d4e43e1fa521
[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_regex_lib.h"
28 #include "regex.h"
29
30 /**
31  * Context that contains an id counter for states and transitions
32  * as well as a DLL of automatons used as a stack for NFA construction.
33  */
34 struct GNUNET_REGEX_Context
35 {
36   /**
37    * Unique state id.
38    */
39   unsigned int state_id;
40
41   /**
42    * Unique transition id.
43    */
44   unsigned int transition_id;
45
46   /**
47    * DLL of GNUNET_REGEX_Automaton's used as a stack.
48    */
49   struct GNUNET_REGEX_Automaton *stack_head;
50
51   /**
52    * DLL of GNUNET_REGEX_Automaton's used as a stack.
53    */
54   struct GNUNET_REGEX_Automaton *stack_tail;
55 };
56
57 /**
58  * Type of an automaton.
59  */
60 enum GNUNET_REGEX_automaton_type
61 {
62   NFA,
63   DFA
64 };
65
66 /**
67  * Automaton representation.
68  */
69 struct GNUNET_REGEX_Automaton
70 {
71   /**
72    * This is a linked list.
73    */
74   struct GNUNET_REGEX_Automaton *prev;
75
76   /**
77    * This is a linked list.
78    */
79   struct GNUNET_REGEX_Automaton *next;
80
81   /**
82    * First state of the automaton. This is mainly
83    * used for constructing an NFA, where each NFA
84    * itself consists of one or more NFAs linked
85    * together.
86    */
87   struct State *start;
88
89   /**
90    * End state of the automaton.
91    */
92   struct State *end;
93
94   /**
95    * Number of states in the automaton.
96    */
97   unsigned int state_count;
98
99   /**
100    * DLL of states.
101    */
102   struct State *states_head;
103
104   /**
105    * DLL of states
106    */
107   struct State *states_tail;
108
109   /**
110    * Type of the automaton.
111    */
112   enum GNUNET_REGEX_automaton_type type;
113 };
114
115 /**
116  * A state. Can be used in DFA and NFA automatons.
117  */
118 struct State
119 {
120   /**
121    * This is a linked list.
122    */
123   struct State *prev;
124
125   /**
126    * This is a linked list.
127    */
128   struct State *next;
129
130   /**
131    * Unique state id.
132    */
133   unsigned int id;
134
135   /**
136    * If this is an accepting state or not.
137    */
138   int accepting;
139
140   /**
141    * Marking of the state. This is used for marking all visited
142    * states when traversing all states of an automaton and for
143    * cases where the state id cannot be used (dfa minimization).
144    */
145   int marked;
146
147   /**
148    * Human readable name of the automaton. Used for debugging
149    * and graph creation.
150    */
151   char *name;
152
153   /**
154    * Number of transitions from this state to other states.
155    */
156   unsigned int transition_count;
157
158   /**
159    * DLL of transitions.
160    */
161   struct Transition *transitions_head;
162
163   /**
164    * DLL of transitions.
165    */
166   struct Transition *transitions_tail;
167
168   /**
169    * Set of states on which this state is based on. Used when
170    * creating a DFA out of several NFA states.
171    */
172   struct StateSet *nfa_set;
173 };
174
175 /**
176  * Transition between two states. Each state can have 0-n transitions.
177  * If literal is 0, this is considered to be an epsilon transition.
178  */
179 struct Transition
180 {
181   /**
182    * This is a linked list.
183    */
184   struct Transition *prev;
185
186   /**
187    * This is a linked list.
188    */
189   struct Transition *next;
190
191   /**
192    * Unique id of this transition.
193    */
194   unsigned int id;
195
196   /**
197    * Literal for this transition. This is basically the edge label for
198    * the graph.
199    */
200   char literal;
201
202   /**
203    * State to which this transition leads.
204    */
205   struct State *to_state;
206
207   /**
208    * State from which this transition origins.
209    */
210   struct State *from_state;
211 };
212
213 /**
214  * Set of states.
215  */
216 struct StateSet
217 {
218   /**
219    * Array of states.
220    */
221   struct State **states;
222
223   /**
224    * Length of the 'states' array.
225    */
226   unsigned int len;
227 };
228
229 /**
230  * Initialize a new context
231  *
232  * @param ctx context
233  */
234 static void
235 GNUNET_REGEX_context_init (struct GNUNET_REGEX_Context *ctx)
236 {
237   if (NULL == ctx)
238   {
239     GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "Context was NULL!");
240     return;
241   }
242   ctx->state_id = 0;
243   ctx->transition_id = 0;
244   ctx->stack_head = NULL;
245   ctx->stack_tail = NULL;
246 }
247
248 static void
249 debug_print_state (struct State *s)
250 {
251   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
252               "State %i: %s marked: %i accepting: %i\n", s->id, s->name,
253               s->marked, s->accepting);
254 }
255
256 static void
257 debug_print_states (struct StateSet *sset)
258 {
259   struct State *s;
260   int i;
261
262   for (i = 0; i < sset->len; i++)
263   {
264     s = sset->states[i];
265     debug_print_state (s);
266   }
267 }
268
269 static void
270 debug_print_transitions (struct State *s)
271 {
272   struct Transition *t;
273   char *state;
274   char literal;
275
276   for (t = s->transitions_head; NULL != t; t = t->next)
277   {
278     if (0 == t->literal)
279       literal = '0';
280     else
281       literal = t->literal;
282
283     if (NULL == t->to_state)
284       state = "NULL";
285     else
286       state = t->to_state->name;
287
288     GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Transition %i: On %c to %s\n", t->id,
289                 literal, state);
290   }
291 }
292
293 /**
294  * Compare two states. Used for sorting.
295  *
296  * @param a first state
297  * @param b second state
298  *
299  * @return an integer less than, equal to, or greater than zero
300  *         if the first argument is considered to be respectively
301  *         less than, equal to, or greater than the second.
302  */
303 static int
304 state_compare (const void *a, const void *b)
305 {
306   struct State **s1;
307   struct State **s2;
308
309   s1 = (struct State **) a;
310   s2 = (struct State **) b;
311
312   return (*s1)->id - (*s2)->id;
313 }
314
315 /**
316  * Compare to state sets by comparing the id's of the states that are
317  * contained in each set. Both sets are expected to be sorted by id!
318  *
319  * @param sset1 first state set
320  * @param sset2 second state set
321  *
322  * @return an integer less than, equal to, or greater than zero
323  *         if the first argument is considered to be respectively
324  *         less than, equal to, or greater than the second.
325  */
326 static int
327 state_set_compare (struct StateSet *sset1, struct StateSet *sset2)
328 {
329   int result;
330   int i;
331
332   if (NULL == sset1 || NULL == sset2)
333     return 1;
334
335   result = sset1->len - sset2->len;
336
337   for (i = 0; i < sset1->len; i++)
338   {
339     if (0 != result)
340       break;
341
342     result = state_compare (&sset1->states[i], &sset2->states[i]);
343   }
344   return result;
345 }
346
347 /**
348  * Checks if 'elem' is contained in 'set'
349  *
350  * @param set set of states
351  * @param elem state
352  *
353  * @return GNUNET_YES if 'set' contains 'elem, GNUNET_NO otherwise
354  */
355 static int
356 state_set_contains (struct StateSet *set, struct State *elem)
357 {
358   struct State *s;
359   int i;
360
361   for (i = 0; i < set->len; i++)
362   {
363     s = set->states[i];
364     if (0 == memcmp (s, elem, sizeof (struct State)))
365       return GNUNET_YES;
366   }
367   return GNUNET_NO;
368 }
369
370 /**
371  * Clears the given StateSet 'set'
372  *
373  * @param set set to be cleared
374  */
375 static void
376 state_set_clear (struct StateSet *set)
377 {
378   if (NULL != set)
379   {
380     if (NULL != set->states)
381       GNUNET_free (set->states);
382     GNUNET_free (set);
383   }
384 }
385
386 /**
387  * Adds a transition from one state to another on 'literal'
388  *
389  * @param ctx context
390  * @param from_state starting state for the transition
391  * @param literal transition label
392  * @param to_state state to where the transition should point to
393  */
394 static void
395 state_add_transition (struct GNUNET_REGEX_Context *ctx,
396                       struct State *from_state, const char literal,
397                       struct State *to_state)
398 {
399   struct Transition *t;
400
401   if (NULL == from_state)
402   {
403     GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "Could not create Transition.\n");
404     return;
405   }
406
407   t = GNUNET_malloc (sizeof (struct Transition));
408
409   t->id = ctx->transition_id++;
410   t->literal = literal;
411   t->to_state = to_state;
412   t->from_state = from_state;
413
414   GNUNET_CONTAINER_DLL_insert (from_state->transitions_head,
415                                from_state->transitions_tail, t);
416 }
417
418 /**
419  * Clears an automaton fragment. Does not destroy the states inside
420  * the automaton.
421  *
422  * @param a automaton to be cleared
423  */
424 static void
425 automaton_fragment_clear (struct GNUNET_REGEX_Automaton *a)
426 {
427   if (NULL == a)
428     return;
429
430   a->start = NULL;
431   a->end = NULL;
432   a->states_head = NULL;
433   a->states_tail = NULL;
434   a->state_count = 0;
435   GNUNET_free (a);
436 }
437
438 /**
439  * Frees the memory used by State 's'
440  *
441  * @param s state that should be destroyed
442  */
443 static void
444 automaton_destroy_state (struct State *s)
445 {
446   struct Transition *t;
447   struct Transition *next_t;
448
449   if (NULL == s)
450     return;
451
452   if (NULL != s->name)
453     GNUNET_free (s->name);
454
455   for (t = s->transitions_head; NULL != t;)
456   {
457     next_t = t->next;
458     GNUNET_CONTAINER_DLL_remove (s->transitions_head, s->transitions_tail, t);
459     GNUNET_free (t);
460     t = next_t;
461   }
462
463   state_set_clear (s->nfa_set);
464
465   GNUNET_free (s);
466 }
467
468 /**
469  * Remove a state from the given automaton 'a'. Always use this function
470  * when altering the states of an automaton. Will also remove all transitions
471  * leading to this state, before destroying it.
472  *
473  * @param a automaton
474  * @param s state to remove
475  */
476 static void
477 automaton_remove_state (struct GNUNET_REGEX_Automaton *a, struct State *s)
478 {
479   struct State *ss;
480   struct State *s_check;
481   struct Transition *t_check;
482
483   if (NULL == a || NULL == s)
484     return;
485
486   // remove state
487   ss = s;
488   GNUNET_CONTAINER_DLL_remove (a->states_head, a->states_tail, s);
489   a->state_count--;
490
491   // remove all transitions leading to this state
492   for (s_check = a->states_head; NULL != s_check; s_check = s_check->next)
493   {
494     for (t_check = s_check->transitions_head; NULL != t_check;
495          t_check = t_check->next)
496     {
497       if (t_check->to_state == ss)
498       {
499         GNUNET_CONTAINER_DLL_remove (s_check->transitions_head,
500                                      s_check->transitions_tail, t_check);
501         s_check->transition_count--;
502       }
503     }
504   }
505
506   automaton_destroy_state (ss);
507 }
508
509 /**
510  * Merge two states into one. Will merge 's1' and 's2' into 's1' and destroy 's2'.
511  *
512  * @param ctx context
513  * @param a automaton
514  * @param s1 first state
515  * @param s2 second state, will be destroyed
516  */
517 static void
518 automaton_merge_states (struct GNUNET_REGEX_Context *ctx,
519                         struct GNUNET_REGEX_Automaton *a, struct State *s1,
520                         struct State *s2)
521 {
522   struct State *s_check;
523   struct Transition *t_check;
524   struct Transition *t;
525   char *new_name;
526
527   GNUNET_assert (NULL != ctx && NULL != a && NULL != s1 && NULL != s2);
528
529   // 1. Make all transitions pointing to s2 point to s1
530   for (s_check = a->states_head; NULL != s_check; s_check = s_check->next)
531   {
532     for (t_check = s_check->transitions_head; NULL != t_check;
533          t_check = t_check->next)
534     {
535       if (s_check != s1 && s2 == t_check->to_state)
536         t_check->to_state = s1;
537     }
538   }
539
540   // 2. Add all transitions from s2 to sX to s1
541   for (t_check = s2->transitions_head; NULL != t_check; t_check = t_check->next)
542   {
543     for (t = s1->transitions_head; NULL != t; t = t->next)
544     {
545       if (t_check->literal != t->literal && NULL != t_check->to_state &&
546           t_check->to_state != t->to_state && t_check->to_state != s2)
547       {
548         state_add_transition (ctx, s1, t_check->literal, t_check->to_state);
549       }
550     }
551   }
552
553   // 3. Rename s1 to {s1,s2}
554   new_name = GNUNET_malloc (strlen (s1->name) + strlen (s2->name) + 1);
555   strncat (new_name, s1->name, strlen (s1->name));
556   strncat (new_name, s2->name, strlen (s2->name));
557   if (NULL != s1->name)
558     GNUNET_free (s1->name);
559   s1->name = new_name;
560
561   // remove state
562   s_check = s2;
563   GNUNET_CONTAINER_DLL_remove (a->states_head, a->states_tail, s_check);
564   a->state_count--;
565   automaton_destroy_state (s_check);
566 }
567
568 /**
569  * Add a state to the automaton 'a', always use this function to
570  * alter the states DLL of the automaton.
571  *
572  * @param a automaton to add the state to
573  * @param s state that should be added
574  */
575 static void
576 automaton_add_state (struct GNUNET_REGEX_Automaton *a, struct State *s)
577 {
578   GNUNET_CONTAINER_DLL_insert (a->states_head, a->states_tail, s);
579   a->state_count++;
580 }
581
582 /**
583  * Creates a new DFA state based on a set of NFA states. Needs to be freed
584  * using automaton_destroy_state.
585  *
586  * @param ctx context
587  * @param nfa_states set of NFA states on which the DFA should be based on
588  *
589  * @return new DFA state
590  */
591 static struct State *
592 dfa_state_create (struct GNUNET_REGEX_Context *ctx, struct StateSet *nfa_states)
593 {
594   struct State *s;
595   char *name;
596   int len = 0;
597   struct State *cstate;
598   struct Transition *ctran;
599   int insert = 1;
600   struct Transition *t;
601   int i;
602
603   s = GNUNET_malloc (sizeof (struct State));
604   s->id = ctx->state_id++;
605   s->accepting = 0;
606   s->marked = 0;
607   s->name = NULL;
608
609   if (NULL == nfa_states)
610   {
611     GNUNET_asprintf (&s->name, "s%i", s->id);
612     return s;
613   }
614
615   s->nfa_set = nfa_states;
616
617   if (nfa_states->len < 1)
618     return s;
619
620   // Create a name based on 'sset'
621   s->name = GNUNET_malloc (sizeof (char) * 2);
622   strcat (s->name, "{");
623   name = NULL;
624
625   for (i = 0; i < nfa_states->len; i++)
626   {
627     cstate = nfa_states->states[i];
628     GNUNET_asprintf (&name, "%i,", cstate->id);
629
630     if (NULL != name)
631     {
632       len = strlen (s->name) + strlen (name) + 1;
633       s->name = GNUNET_realloc (s->name, len);
634       strcat (s->name, name);
635       GNUNET_free (name);
636       name = NULL;
637     }
638
639     // Add a transition for each distinct literal to NULL state
640     for (ctran = cstate->transitions_head; NULL != ctran; ctran = ctran->next)
641     {
642       if (0 != ctran->literal)
643       {
644         insert = 1;
645
646         for (t = s->transitions_head; NULL != t; t = t->next)
647         {
648           if (t->literal == ctran->literal)
649           {
650             insert = 0;
651             break;
652           }
653         }
654
655         if (insert)
656           state_add_transition (ctx, s, ctran->literal, NULL);
657       }
658     }
659
660     // If the nfa_states contain an accepting state, the new dfa state is also accepting
661     if (cstate->accepting)
662       s->accepting = 1;
663   }
664
665   s->name[strlen (s->name) - 1] = '}';
666
667   return s;
668 }
669
670 /**
671  * Move from the given state 's' to the next state on
672  * transition 'literal'
673  *
674  * @param s starting state
675  * @param literal edge label to follow
676  *
677  * @return new state or NULL, if transition on literal not possible
678  */
679 static struct State *
680 dfa_move (struct State *s, const char literal)
681 {
682   struct Transition *t;
683   struct State *new_s;
684
685   if (NULL == s)
686     return NULL;
687
688   new_s = NULL;
689
690   for (t = s->transitions_head; NULL != t; t = t->next)
691   {
692     if (literal == t->literal)
693     {
694       new_s = t->to_state;
695       break;
696     }
697   }
698
699   return new_s;
700 }
701
702 /**
703  * Remove all unreachable states from DFA 'a'. Unreachable states
704  * are those states that are not reachable from the starting state.
705  *
706  * @param a DFA automaton
707  */
708 static void
709 dfa_remove_unreachable_states (struct GNUNET_REGEX_Automaton *a)
710 {
711   struct State *stack[a->state_count * a->state_count];
712   int stack_len;
713   struct State *s;
714   struct State *s_next;
715   struct Transition *t;
716
717   stack_len = 0;
718
719   // 1. unmark all states
720   for (s = a->states_head; NULL != s; s = s->next)
721     s->marked = 0;
722
723   // 2. traverse dfa from start state and mark all visited states
724   stack[stack_len++] = a->start;
725   while (stack_len > 0)
726   {
727     s = stack[--stack_len];
728     s->marked = 1;              // mark s as visited
729     for (t = s->transitions_head; NULL != t; t = t->next)
730     {
731       // add next states to stack
732       if (NULL != t->to_state && 0 == t->to_state->marked)
733         stack[stack_len++] = t->to_state;
734     }
735   }
736
737   // 3. delete all states that were not visited
738   for (s = a->states_head; NULL != s; s = s_next)
739   {
740     s_next = s->next;
741     if (0 == s->marked)
742     {
743       GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Removed state %s\n", s->name);
744       automaton_remove_state (a, s);
745     }
746   }
747 }
748
749 /**
750  * Remove all dead states from the DFA 'a'. Dead states are those
751  * states that do not transition to any other state but themselfes.
752  *
753  * @param a DFA automaton
754  */
755 static void
756 dfa_remove_dead_states (struct GNUNET_REGEX_Automaton *a)
757 {
758   struct State *s;
759   struct Transition *t;
760   int dead;
761
762   GNUNET_assert (DFA == a->type);
763
764   for (s = a->states_head; NULL != s; s = s->next)
765   {
766     if (s->accepting)
767       continue;
768
769     dead = 1;
770     for (t = s->transitions_head; NULL != t; t = t->next)
771     {
772       if (NULL != t->to_state && t->to_state != s)
773       {
774         dead = 0;
775         break;
776       }
777     }
778
779     if (0 == dead)
780       continue;
781
782     // state s is dead, remove it
783     automaton_remove_state (a, s);
784   }
785 }
786
787 /**
788  * Merge all non distinguishable states in the DFA 'a'
789  *
790  * @param ctx context
791  * @param a DFA automaton
792  */
793 static void
794 dfa_merge_nondistinguishable_states (struct GNUNET_REGEX_Context *ctx,
795                                      struct GNUNET_REGEX_Automaton *a)
796 {
797   int i;
798   int table[a->state_count][a->state_count];
799   struct State *s1;
800   struct State *s2;
801   struct Transition *t1;
802   struct Transition *t2;
803   int change;
804
805   change = 1;
806   for (i = 0, s1 = a->states_head; i < a->state_count && NULL != s1;
807        i++, s1 = s1->next)
808     s1->marked = i;
809
810   // Mark all pairs of accepting/!accepting states
811   for (s1 = a->states_head; NULL != s1; s1 = s1->next)
812   {
813     for (s2 = a->states_head; NULL != s2 && s1 != s2; s2 = s2->next)
814     {
815       if ((s1->accepting && !s2->accepting) ||
816           (!s1->accepting && s2->accepting))
817       {
818         table[s1->marked][s2->marked] = 1;
819       }
820       else
821         table[s1->marked][s2->marked] = 0;
822     }
823   }
824
825   while (0 != change)
826   {
827     change = 0;
828     for (s1 = a->states_head; NULL != s1; s1 = s1->next)
829     {
830       for (s2 = a->states_head; NULL != s2 && s1 != s2; s2 = s2->next)
831       {
832         if (0 != table[s1->marked][s2->marked])
833           continue;
834
835         for (t1 = s1->transitions_head; NULL != t1; t1 = t1->next)
836         {
837           for (t2 = s2->transitions_head; NULL != t2; t2 = t2->next)
838           {
839             if (t1->literal == t2->literal && t1->to_state == t2->to_state &&
840                 (0 != table[t1->to_state->marked][t2->to_state->marked] ||
841                  0 != table[t2->to_state->marked][t1->to_state->marked]))
842             {
843               table[s1->marked][s2->marked] = t1->literal;
844               change = 1;
845             }
846             else if (t1->literal != t2->literal && t1->to_state != t2->to_state)
847             {
848               table[s1->marked][s2->marked] = -1;
849               change = 1;
850             }
851           }
852         }
853       }
854     }
855   }
856
857   struct State *s2_next;
858
859   for (i = 0, s1 = a->states_head; NULL != s1; s1 = s1->next)
860   {
861     for (s2 = a->states_head; NULL != s2 && s1 != s2; s2 = s2_next)
862     {
863       s2_next = s2->next;
864       if (s1 != s2 && table[s1->marked][s2->marked] == 0)
865         automaton_merge_states (ctx, a, s1, s2);
866     }
867   }
868 }
869
870 /**
871  * Minimize the given DFA 'a' by removing all unreachable states,
872  * removing all dead states and merging all non distinguishable states
873  *
874  * @param ctx context
875  * @param a DFA automaton
876  */
877 static void
878 dfa_minimize (struct GNUNET_REGEX_Context *ctx,
879               struct GNUNET_REGEX_Automaton *a)
880 {
881   if (NULL == a)
882     return;
883
884   GNUNET_assert (DFA == a->type);
885
886   // 1. remove unreachable states
887   dfa_remove_unreachable_states (a);
888
889   // 2. remove dead states
890   dfa_remove_dead_states (a);
891
892   // 3. Merge nondistinguishable states
893   dfa_merge_nondistinguishable_states (ctx, a);
894 }
895
896 /**
897  * Creates a new NFA fragment. Needs to be cleared using automaton_fragment_clear.
898  *
899  * @param start starting state
900  * @param end end state
901  *
902  * @return new NFA fragment
903  */
904 static struct GNUNET_REGEX_Automaton *
905 nfa_fragment_create (struct State *start, struct State *end)
906 {
907   struct GNUNET_REGEX_Automaton *n;
908
909   n = GNUNET_malloc (sizeof (struct GNUNET_REGEX_Automaton));
910
911   n->type = NFA;
912   n->start = NULL;
913   n->end = NULL;
914
915   if (NULL == start && NULL == end)
916     return n;
917
918   automaton_add_state (n, end);
919   automaton_add_state (n, start);
920
921   n->start = start;
922   n->end = end;
923
924   return n;
925 }
926
927 /**
928  * Adds a list of states to the given automaton 'n'.
929  *
930  * @param n automaton to which the states should be added
931  * @param states_head head of the DLL of states
932  * @param states_tail tail of the DLL of states
933  */
934 static void
935 nfa_add_states (struct GNUNET_REGEX_Automaton *n, struct State *states_head,
936                 struct State *states_tail)
937 {
938   struct State *s;
939
940   if (NULL == n || NULL == states_head)
941   {
942     GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "Could not add states\n");
943     return;
944   }
945
946   if (NULL == n->states_head)
947   {
948     n->states_head = states_head;
949     n->states_tail = states_tail;
950     return;
951   }
952
953   if (NULL != states_head)
954   {
955     n->states_tail->next = states_head;
956     n->states_tail = states_tail;
957   }
958
959   for (s = states_head; NULL != s; s = s->next)
960     n->state_count++;
961 }
962
963 /**
964  * Creates a new NFA state. Needs to be freed using automaton_destroy_state.
965  *
966  * @param ctx context
967  * @param accepting is it an accepting state or not
968  *
969  * @return new NFA state
970  */
971 static struct State *
972 nfa_state_create (struct GNUNET_REGEX_Context *ctx, int accepting)
973 {
974   struct State *s;
975
976   s = GNUNET_malloc (sizeof (struct State));
977   s->id = ctx->state_id++;
978   s->accepting = accepting;
979   s->marked = 0;
980   s->name = NULL;
981   GNUNET_asprintf (&s->name, "s%i", s->id);
982
983   return s;
984 }
985
986 /**
987  * Calculates the NFA closure set for the given state.
988  *
989  * @param s starting point state
990  * @param literal transitioning literal on which to base the closure on,
991  *                pass 0 for epsilon transition
992  *
993  * @return sorted nfa closure on 'literal' (epsilon closure if 'literal' is 0)
994  */
995 static struct StateSet *
996 nfa_closure_create (struct State *s, const char literal)
997 {
998   struct StateSet *cls;
999   struct StateSet *cls_check;
1000   struct State *clsstate;
1001   struct State *currentstate;
1002   struct Transition *ctran;
1003
1004   if (NULL == s)
1005     return NULL;
1006
1007   cls = GNUNET_malloc (sizeof (struct StateSet));
1008   cls_check = GNUNET_malloc (sizeof (struct StateSet));
1009
1010   // Add start state to closure only for epsilon closure
1011   if (0 == literal)
1012     GNUNET_array_append (cls->states, cls->len, s);
1013
1014   GNUNET_array_append (cls_check->states, cls_check->len, s);
1015   while (cls_check->len > 0)
1016   {
1017     currentstate = cls_check->states[cls_check->len - 1];
1018     GNUNET_array_grow (cls_check->states, cls_check->len, cls_check->len - 1);
1019
1020     for (ctran = currentstate->transitions_head; NULL != ctran;
1021          ctran = ctran->next)
1022     {
1023       if (NULL != ctran->to_state && literal == ctran->literal)
1024       {
1025         clsstate = ctran->to_state;
1026
1027         if (NULL != clsstate &&
1028             GNUNET_YES != state_set_contains (cls, clsstate))
1029         {
1030           GNUNET_array_append (cls->states, cls->len, clsstate);
1031           GNUNET_array_append (cls_check->states, cls_check->len, clsstate);
1032         }
1033       }
1034     }
1035   }
1036   GNUNET_assert (0 == cls_check->len);
1037   GNUNET_free (cls_check);
1038
1039   if (cls->len > 1)
1040     qsort (cls->states, cls->len, sizeof (struct State *), state_compare);
1041
1042   return cls;
1043 }
1044
1045 /**
1046  * Calculates the closure set for the given set of states.
1047  *
1048  * @param states list of states on which to base the closure on
1049  * @param literal transitioning literal for which to base the closure on,
1050  *                pass 0 for epsilon transition
1051  *
1052  * @return sorted nfa closure on 'literal' (epsilon closure if 'literal' is 0)
1053  */
1054 static struct StateSet *
1055 nfa_closure_set_create (struct StateSet *states, const char literal)
1056 {
1057   struct State *s;
1058   struct StateSet *sset;
1059   struct StateSet *cls;
1060   int i;
1061   int j;
1062   int k;
1063   int contains;
1064
1065   if (NULL == states)
1066     return NULL;
1067
1068   cls = GNUNET_malloc (sizeof (struct StateSet));
1069
1070   for (i = 0; i < states->len; i++)
1071   {
1072     s = states->states[i];
1073     sset = nfa_closure_create (s, literal);
1074
1075     for (j = 0; j < sset->len; j++)
1076     {
1077       contains = 0;
1078       for (k = 0; k < cls->len; k++)
1079       {
1080         if (sset->states[j]->id == cls->states[k]->id)
1081         {
1082           contains = 1;
1083           break;
1084         }
1085       }
1086       if (!contains)
1087         GNUNET_array_append (cls->states, cls->len, sset->states[j]);
1088     }
1089     state_set_clear (sset);
1090   }
1091
1092   if (cls->len > 1)
1093     qsort (cls->states, cls->len, sizeof (struct State *), state_compare);
1094
1095   return cls;
1096 }
1097
1098 /**
1099  * Pops two NFA fragments (a, b) from the stack and concatenates them (ab)
1100  *
1101  * @param ctx context
1102  */
1103 static void
1104 nfa_add_concatenation (struct GNUNET_REGEX_Context *ctx)
1105 {
1106   struct GNUNET_REGEX_Automaton *a;
1107   struct GNUNET_REGEX_Automaton *b;
1108   struct GNUNET_REGEX_Automaton *new;
1109
1110   b = ctx->stack_tail;
1111   GNUNET_CONTAINER_DLL_remove (ctx->stack_head, ctx->stack_tail, b);
1112   a = ctx->stack_tail;
1113   GNUNET_CONTAINER_DLL_remove (ctx->stack_head, ctx->stack_tail, a);
1114
1115   state_add_transition (ctx, a->end, 0, b->start);
1116   a->end->accepting = 0;
1117   b->end->accepting = 1;
1118
1119   new = nfa_fragment_create (NULL, NULL);
1120   nfa_add_states (new, a->states_head, a->states_tail);
1121   nfa_add_states (new, b->states_head, b->states_tail);
1122   new->start = a->start;
1123   new->end = b->end;
1124   automaton_fragment_clear (a);
1125   automaton_fragment_clear (b);
1126
1127   GNUNET_CONTAINER_DLL_insert_tail (ctx->stack_head, ctx->stack_tail, new);
1128 }
1129
1130 /**
1131  * Pops a NFA fragment from the stack (a) and adds a new fragment (a*)
1132  *
1133  * @param ctx context
1134  */
1135 static void
1136 nfa_add_star_op (struct GNUNET_REGEX_Context *ctx)
1137 {
1138   struct GNUNET_REGEX_Automaton *a;
1139   struct GNUNET_REGEX_Automaton *new;
1140   struct State *start;
1141   struct State *end;
1142
1143   a = ctx->stack_tail;
1144   GNUNET_CONTAINER_DLL_remove (ctx->stack_head, ctx->stack_tail, a);
1145
1146   if (NULL == a)
1147   {
1148     GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
1149                 "nfa_add_star_op failed, because there was no element on the stack");
1150     return;
1151   }
1152
1153   start = nfa_state_create (ctx, 0);
1154   end = nfa_state_create (ctx, 1);
1155
1156   state_add_transition (ctx, start, 0, a->start);
1157   state_add_transition (ctx, start, 0, end);
1158   state_add_transition (ctx, a->end, 0, a->start);
1159   state_add_transition (ctx, a->end, 0, end);
1160
1161   a->end->accepting = 0;
1162   end->accepting = 1;
1163
1164   new = nfa_fragment_create (start, end);
1165   nfa_add_states (new, a->states_head, a->states_tail);
1166   automaton_fragment_clear (a);
1167
1168   GNUNET_CONTAINER_DLL_insert_tail (ctx->stack_head, ctx->stack_tail, new);
1169 }
1170
1171 /**
1172  * Pops an NFA fragment (a) from the stack and adds a new fragment (a+)
1173  *
1174  * @param ctx context
1175  */
1176 static void
1177 nfa_add_plus_op (struct GNUNET_REGEX_Context *ctx)
1178 {
1179   struct GNUNET_REGEX_Automaton *a;
1180
1181   a = ctx->stack_tail;
1182   GNUNET_CONTAINER_DLL_remove (ctx->stack_head, ctx->stack_tail, a);
1183
1184   state_add_transition (ctx, a->end, 0, a->start);
1185
1186   GNUNET_CONTAINER_DLL_insert_tail (ctx->stack_head, ctx->stack_tail, a);
1187 }
1188
1189 /**
1190  * Pops an NFA fragment (a) from the stack and adds a new fragment (a?)
1191  *
1192  * @param ctx context
1193  */
1194 static void
1195 nfa_add_question_op (struct GNUNET_REGEX_Context *ctx)
1196 {
1197   struct GNUNET_REGEX_Automaton *a;
1198   struct GNUNET_REGEX_Automaton *new;
1199   struct State *start;
1200   struct State *end;
1201
1202   a = ctx->stack_tail;
1203   GNUNET_CONTAINER_DLL_remove (ctx->stack_head, ctx->stack_tail, a);
1204
1205   if (NULL == a)
1206   {
1207     GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
1208                 "nfa_add_question_op failed, because there was no element on the stack");
1209     return;
1210   }
1211
1212   start = nfa_state_create (ctx, 0);
1213   end = nfa_state_create (ctx, 1);
1214
1215   state_add_transition (ctx, start, 0, a->start);
1216   state_add_transition (ctx, start, 0, end);
1217   state_add_transition (ctx, a->end, 0, end);
1218
1219   a->end->accepting = 0;
1220
1221   new = nfa_fragment_create (start, end);
1222   nfa_add_states (new, a->states_head, a->states_tail);
1223   automaton_fragment_clear (a);
1224
1225   GNUNET_CONTAINER_DLL_insert_tail (ctx->stack_head, ctx->stack_tail, new);
1226 }
1227
1228 /**
1229  * Pops two NFA fragments (a, b) from the stack and adds a new NFA fragment
1230  * that alternates between a and b (a|b)
1231  *
1232  * @param ctx context
1233  */
1234 static void
1235 nfa_add_alternation (struct GNUNET_REGEX_Context *ctx)
1236 {
1237   struct GNUNET_REGEX_Automaton *a;
1238   struct GNUNET_REGEX_Automaton *b;
1239   struct GNUNET_REGEX_Automaton *new;
1240   struct State *start;
1241   struct State *end;
1242
1243   b = ctx->stack_tail;
1244   GNUNET_CONTAINER_DLL_remove (ctx->stack_head, ctx->stack_tail, b);
1245   a = ctx->stack_tail;
1246   GNUNET_CONTAINER_DLL_remove (ctx->stack_head, ctx->stack_tail, a);
1247
1248   start = nfa_state_create (ctx, 0);
1249   end = nfa_state_create (ctx, 1);
1250   state_add_transition (ctx, start, 0, a->start);
1251   state_add_transition (ctx, start, 0, b->start);
1252
1253   state_add_transition (ctx, a->end, 0, end);
1254   state_add_transition (ctx, b->end, 0, end);
1255
1256   a->end->accepting = 0;
1257   b->end->accepting = 0;
1258   end->accepting = 1;
1259
1260   new = nfa_fragment_create (start, end);
1261   nfa_add_states (new, a->states_head, a->states_tail);
1262   nfa_add_states (new, b->states_head, b->states_tail);
1263   automaton_fragment_clear (a);
1264   automaton_fragment_clear (b);
1265
1266   GNUNET_CONTAINER_DLL_insert_tail (ctx->stack_head, ctx->stack_tail, new);
1267 }
1268
1269 /**
1270  * Adds a new nfa fragment to the stack
1271  *
1272  * @param ctx context
1273  * @param lit literal for nfa transition
1274  */
1275 static void
1276 nfa_add_literal (struct GNUNET_REGEX_Context *ctx, const char lit)
1277 {
1278   struct GNUNET_REGEX_Automaton *n;
1279   struct State *start;
1280   struct State *end;
1281
1282   GNUNET_assert (NULL != ctx);
1283
1284   start = nfa_state_create (ctx, 0);
1285   end = nfa_state_create (ctx, 1);
1286   state_add_transition (ctx, start, lit, end);
1287   n = nfa_fragment_create (start, end);
1288   GNUNET_assert (NULL != n);
1289   GNUNET_CONTAINER_DLL_insert_tail (ctx->stack_head, ctx->stack_tail, n);
1290 }
1291
1292 /**
1293  * Construct an NFA by parsing the regex string of length 'len'.
1294  *
1295  * @param regex regular expression string
1296  * @param len length of the string
1297  *
1298  * @return NFA, needs to be freed using GNUNET_REGEX_destroy_automaton
1299  */
1300 struct GNUNET_REGEX_Automaton *
1301 GNUNET_REGEX_construct_nfa (const char *regex, const size_t len)
1302 {
1303   struct GNUNET_REGEX_Context ctx;
1304   struct GNUNET_REGEX_Automaton *nfa;
1305   const char *regexp;
1306   char *error_msg;
1307   unsigned int count;
1308   unsigned int altcount;
1309   unsigned int atomcount;
1310   unsigned int pcount;
1311   struct
1312   {
1313     int altcount;
1314     int atomcount;
1315   }     *p;
1316
1317   GNUNET_REGEX_context_init (&ctx);
1318
1319   regexp = regex;
1320   p = NULL;
1321   error_msg = NULL;
1322   altcount = 0;
1323   atomcount = 0;
1324   pcount = 0;
1325
1326   for (count = 0; count < len && *regexp; count++, regexp++)
1327   {
1328     switch (*regexp)
1329     {
1330     case '(':
1331       if (atomcount > 1)
1332       {
1333         --atomcount;
1334         nfa_add_concatenation (&ctx);
1335       }
1336       GNUNET_array_grow (p, pcount, pcount + 1);
1337       p[pcount - 1].altcount = altcount;
1338       p[pcount - 1].atomcount = atomcount;
1339       altcount = 0;
1340       atomcount = 0;
1341       break;
1342     case '|':
1343       if (0 == atomcount)
1344       {
1345         error_msg = "Cannot append '|' to nothing";
1346         goto error;
1347       }
1348       while (--atomcount > 0)
1349         nfa_add_concatenation (&ctx);
1350       altcount++;
1351       break;
1352     case ')':
1353       if (0 == pcount)
1354       {
1355         error_msg = "Missing opening '('";
1356         goto error;
1357       }
1358       if (0 == atomcount)
1359       {
1360         // Ignore this: "()"
1361         pcount--;
1362         altcount = p[pcount].altcount;
1363         atomcount = p[pcount].atomcount;
1364         break;
1365       }
1366       while (--atomcount > 0)
1367         nfa_add_concatenation (&ctx);
1368       for (; altcount > 0; altcount--)
1369         nfa_add_alternation (&ctx);
1370       pcount--;
1371       altcount = p[pcount].altcount;
1372       atomcount = p[pcount].atomcount;
1373       atomcount++;
1374       break;
1375     case '*':
1376       if (atomcount == 0)
1377       {
1378         error_msg = "Cannot append '+' to nothing";
1379         goto error;
1380       }
1381       nfa_add_star_op (&ctx);
1382       break;
1383     case '+':
1384       if (atomcount == 0)
1385       {
1386         error_msg = "Cannot append '+' to nothing";
1387         goto error;
1388       }
1389       nfa_add_plus_op (&ctx);
1390       break;
1391     case '?':
1392       if (atomcount == 0)
1393       {
1394         error_msg = "Cannot append '?' to nothing";
1395         goto error;
1396       }
1397       nfa_add_question_op (&ctx);
1398       break;
1399     case 92:                   /* escape: \ */
1400       regexp++;
1401       count++;
1402     default:
1403       if (atomcount > 1)
1404       {
1405         --atomcount;
1406         nfa_add_concatenation (&ctx);
1407       }
1408       nfa_add_literal (&ctx, *regexp);
1409       atomcount++;
1410       break;
1411     }
1412   }
1413   if (0 != pcount)
1414   {
1415     error_msg = "Unbalanced parenthesis";
1416     goto error;
1417   }
1418   while (--atomcount > 0)
1419     nfa_add_concatenation (&ctx);
1420   for (; altcount > 0; altcount--)
1421     nfa_add_alternation (&ctx);
1422
1423   if (NULL != p)
1424     GNUNET_free (p);
1425
1426   nfa = ctx.stack_tail;
1427   GNUNET_CONTAINER_DLL_remove (ctx.stack_head, ctx.stack_tail, nfa);
1428
1429
1430   if (NULL != ctx.stack_head)
1431   {
1432     error_msg = "Creating the NFA failed. NFA stack was not empty!";
1433     goto error;
1434   }
1435
1436   return nfa;
1437
1438 error:
1439   GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "Could not parse regex\n");
1440   if (NULL != error_msg)
1441     GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "%s\n", error_msg);
1442   if (NULL != p)
1443     GNUNET_free (p);
1444   while (NULL != ctx.stack_tail)
1445   {
1446     GNUNET_REGEX_automaton_destroy (ctx.stack_tail);
1447     GNUNET_CONTAINER_DLL_remove (ctx.stack_head, ctx.stack_tail,
1448                                  ctx.stack_tail);
1449   }
1450   return NULL;
1451 }
1452
1453 /**
1454  * Free the memory allocated by constructing the GNUNET_REGEX_Automaton
1455  * data structure.
1456  *
1457  * @param a automaton to be destroyed
1458  */
1459 void
1460 GNUNET_REGEX_automaton_destroy (struct GNUNET_REGEX_Automaton *a)
1461 {
1462   struct State *s;
1463   struct State *next_state;
1464
1465   if (NULL == a)
1466     return;
1467
1468   for (s = a->states_head; NULL != s;)
1469   {
1470     next_state = s->next;
1471     automaton_destroy_state (s);
1472     s = next_state;
1473   }
1474
1475   GNUNET_free (a);
1476 }
1477
1478 /**
1479  * Construct DFA for the given 'regex' of length 'len'
1480  *
1481  * @param regex regular expression string
1482  * @param len length of the regular expression
1483  *
1484  * @return DFA, needs to be freed using GNUNET_REGEX_destroy_automaton
1485  */
1486 struct GNUNET_REGEX_Automaton *
1487 GNUNET_REGEX_construct_dfa (const char *regex, const size_t len)
1488 {
1489   struct GNUNET_REGEX_Context ctx;
1490   struct GNUNET_REGEX_Automaton *dfa;
1491   struct GNUNET_REGEX_Automaton *nfa;
1492   struct StateSet *tmp;
1493   struct StateSet *nfa_set;
1494   struct StateSet *dfa_stack;
1495   struct Transition *ctran;
1496   struct State *dfa_state;
1497   struct State *new_dfa_state;
1498   struct State *state_contains;
1499   struct State *state_iter;
1500
1501   GNUNET_REGEX_context_init (&ctx);
1502
1503   // Create NFA
1504   nfa = GNUNET_REGEX_construct_nfa (regex, len);
1505
1506   if (NULL == nfa)
1507   {
1508     GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
1509                 "Could not create DFA, because NFA creation failed\n");
1510     return NULL;
1511   }
1512
1513   dfa = GNUNET_malloc (sizeof (struct GNUNET_REGEX_Automaton));
1514   dfa->type = DFA;
1515
1516   // Create DFA start state from epsilon closure
1517   dfa_stack = GNUNET_malloc (sizeof (struct StateSet));
1518   nfa_set = nfa_closure_create (nfa->start, 0);
1519   dfa->start = dfa_state_create (&ctx, nfa_set);
1520   automaton_add_state (dfa, dfa->start);
1521   GNUNET_array_append (dfa_stack->states, dfa_stack->len, dfa->start);
1522
1523   // Create dfa states by combining nfa states
1524   while (dfa_stack->len > 0)
1525   {
1526     dfa_state = dfa_stack->states[dfa_stack->len - 1];
1527     GNUNET_array_grow (dfa_stack->states, dfa_stack->len, dfa_stack->len - 1);
1528
1529     for (ctran = dfa_state->transitions_head; NULL != ctran;
1530          ctran = ctran->next)
1531     {
1532       if (0 != ctran->literal && NULL == ctran->to_state)
1533       {
1534         tmp = nfa_closure_set_create (dfa_state->nfa_set, ctran->literal);
1535         nfa_set = nfa_closure_set_create (tmp, 0);
1536         state_set_clear (tmp);
1537         new_dfa_state = dfa_state_create (&ctx, nfa_set);
1538         state_contains = NULL;
1539         for (state_iter = dfa->states_head; NULL != state_iter;
1540              state_iter = state_iter->next)
1541         {
1542           if (0 ==
1543               state_set_compare (state_iter->nfa_set, new_dfa_state->nfa_set))
1544             state_contains = state_iter;
1545         }
1546
1547         if (NULL == state_contains)
1548         {
1549           automaton_add_state (dfa, new_dfa_state);
1550           GNUNET_array_append (dfa_stack->states, dfa_stack->len,
1551                                new_dfa_state);
1552           ctran->to_state = new_dfa_state;
1553         }
1554         else
1555         {
1556           ctran->to_state = state_contains;
1557           automaton_destroy_state (new_dfa_state);
1558         }
1559       }
1560     }
1561   }
1562
1563   GNUNET_free (dfa_stack);
1564   GNUNET_REGEX_automaton_destroy (nfa);
1565
1566   dfa_minimize (&ctx, dfa);
1567
1568   return dfa;
1569 }
1570
1571 /**
1572  * Save the given automaton as a GraphViz dot file
1573  *
1574  * @param a the automaton to be saved
1575  * @param filename where to save the file
1576  */
1577 void
1578 GNUNET_REGEX_automaton_save_graph (struct GNUNET_REGEX_Automaton *a,
1579                                    const char *filename)
1580 {
1581   struct State *s;
1582   struct Transition *ctran;
1583   char *s_acc = NULL;
1584   char *s_tran = NULL;
1585   char *start;
1586   char *end;
1587   FILE *p;
1588
1589   if (NULL == a)
1590   {
1591     GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "Could not print NFA, was NULL!");
1592     return;
1593   }
1594
1595   if (NULL == filename || strlen (filename) < 1)
1596   {
1597     GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "No Filename given!");
1598     return;
1599   }
1600
1601   p = fopen (filename, "w");
1602
1603   if (p == NULL)
1604   {
1605     GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "Could not open file for writing: %s",
1606                 filename);
1607     return;
1608   }
1609
1610   start = "digraph G {\nrankdir=LR\n";
1611   fwrite (start, strlen (start), 1, p);
1612
1613   for (s = a->states_head; NULL != s; s = s->next)
1614   {
1615     if (s->accepting)
1616     {
1617       GNUNET_asprintf (&s_acc, "\"%s\" [shape=doublecircle];\n", s->name);
1618       fwrite (s_acc, strlen (s_acc), 1, p);
1619       GNUNET_free (s_acc);
1620     }
1621
1622     s->marked = 1;
1623
1624     for (ctran = s->transitions_head; NULL != ctran; ctran = ctran->next)
1625     {
1626       if (NULL == ctran->to_state)
1627       {
1628         GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
1629                     "Transition from State %i has has no state for transitioning\n",
1630                     s->id);
1631         continue;
1632       }
1633
1634       if (ctran->literal == 0)
1635       {
1636         GNUNET_asprintf (&s_tran, "\"%s\" -> \"%s\" [label = \"epsilon\"];\n",
1637                          s->name, ctran->to_state->name);
1638       }
1639       else
1640       {
1641         GNUNET_asprintf (&s_tran, "\"%s\" -> \"%s\" [label = \"%c\"];\n",
1642                          s->name, ctran->to_state->name, ctran->literal);
1643       }
1644
1645       fwrite (s_tran, strlen (s_tran), 1, p);
1646       GNUNET_free (s_tran);
1647     }
1648   }
1649
1650   end = "\n}\n";
1651   fwrite (end, strlen (end), 1, p);
1652   fclose (p);
1653 }
1654
1655 /**
1656  * Evaluates the given string using the given DFA automaton
1657  *
1658  * @param a automaton, type must be DFA
1659  * @param string string that should be evaluated
1660  *
1661  * @return 0 if string matches, non 0 otherwise
1662  */
1663 static int
1664 evaluate_dfa (struct GNUNET_REGEX_Automaton *a, const char *string)
1665 {
1666   const char *strp;
1667   struct State *s;
1668
1669   if (DFA != a->type)
1670   {
1671     GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
1672                 "Tried to evaluate DFA, but NFA automaton given");
1673     return -1;
1674   }
1675
1676   s = a->start;
1677
1678   for (strp = string; NULL != strp && *strp; strp++)
1679   {
1680     s = dfa_move (s, *strp);
1681     if (NULL == s)
1682       break;
1683   }
1684
1685   if (NULL != s && s->accepting)
1686     return 0;
1687
1688   return 1;
1689 }
1690
1691 /**
1692  * Evaluates the given string using the given NFA automaton
1693  *
1694  * @param a automaton, type must be NFA
1695  * @param string string that should be evaluated
1696  *
1697  * @return 0 if string matches, non 0 otherwise
1698  */
1699 static int
1700 evaluate_nfa (struct GNUNET_REGEX_Automaton *a, const char *string)
1701 {
1702   const char *strp;
1703   struct State *s;
1704   struct StateSet *sset;
1705   struct StateSet *new_sset;
1706   int i;
1707   int result;
1708
1709   if (NFA != a->type)
1710   {
1711     GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
1712                 "Tried to evaluate NFA, but DFA automaton given");
1713     return -1;
1714   }
1715
1716   result = 1;
1717   strp = string;
1718   sset = nfa_closure_create (a->start, 0);
1719
1720   for (strp = string; NULL != strp && *strp; strp++)
1721   {
1722     new_sset = nfa_closure_set_create (sset, *strp);
1723     state_set_clear (sset);
1724     sset = nfa_closure_set_create (new_sset, 0);
1725     state_set_clear (new_sset);
1726   }
1727
1728   for (i = 0; i < sset->len; i++)
1729   {
1730     s = sset->states[i];
1731     if (NULL != s && s->accepting)
1732     {
1733       result = 0;
1734       break;
1735     }
1736   }
1737
1738   state_set_clear (sset);
1739   return result;
1740 }
1741
1742 /**
1743  * Evaluates the given 'string' against the given compiled regex
1744  *
1745  * @param a automaton
1746  * @param string string to check
1747  *
1748  * @return 0 if string matches, non 0 otherwise
1749  */
1750 int
1751 GNUNET_REGEX_eval (struct GNUNET_REGEX_Automaton *a, const char *string)
1752 {
1753   int result;
1754
1755   switch (a->type)
1756   {
1757   case DFA:
1758     result = evaluate_dfa (a, string);
1759     break;
1760   case NFA:
1761     result = evaluate_nfa (a, string);
1762     break;
1763   default:
1764     GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
1765                 "Evaluating regex failed, automaton has no type!\n");
1766     result = GNUNET_SYSERR;
1767     break;
1768   }
1769
1770   return result;
1771 }