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