Towards new proof algorithm
[oweals/gnunet.git] / src / regex / regex.c
1 /*
2      This file is part of GNUnet
3      (C) 2012 Christian Grothoff (and other contributing authors)
4
5      GNUnet is free software; you can redistribute it and/or modify
6      it under the terms of the GNU General Public License as published
7      by the Free Software Foundation; either version 3, or (at your
8      option) any later version.
9
10      GNUnet is distributed in the hope that it will be useful, but
11      WITHOUT ANY WARRANTY; without even the implied warranty of
12      MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
13      General Public License for more details.
14
15      You should have received a copy of the GNU General Public License
16      along with GNUnet; see the file COPYING.  If not, write to the
17      Free Software Foundation, Inc., 59 Temple Place - Suite 330,
18      Boston, MA 02111-1307, USA.
19 */
20 /**
21  * @file src/regex/regex.c
22  * @brief library to create automatons from regular expressions
23  * @author Maximilian Szengel
24  */
25 #include "platform.h"
26 #include "gnunet_container_lib.h"
27 #include "gnunet_crypto_lib.h"
28 #include "gnunet_regex_lib.h"
29 #include "regex.h"
30
31 #define initial_bits 10
32
33 /**
34  * Context that contains an id counter for states and transitions as well as a
35  * DLL of automatons used as a stack for NFA construction.
36  */
37 struct GNUNET_REGEX_Context
38 {
39   /**
40    * Unique state id.
41    */
42   unsigned int state_id;
43
44   /**
45    * Unique transition id.
46    */
47   unsigned int transition_id;
48
49   /**
50    * Unique SCC (Strongly Connected Component) id.
51    */
52   unsigned int scc_id;
53
54   /**
55    * DLL of GNUNET_REGEX_Automaton's used as a stack.
56    */
57   struct GNUNET_REGEX_Automaton *stack_head;
58
59   /**
60    * DLL of GNUNET_REGEX_Automaton's used as a stack.
61    */
62   struct GNUNET_REGEX_Automaton *stack_tail;
63 };
64
65 /**
66  * Type of an automaton.
67  */
68 enum GNUNET_REGEX_automaton_type
69 {
70   NFA,
71   DFA
72 };
73
74 /**
75  * Automaton representation.
76  */
77 struct GNUNET_REGEX_Automaton
78 {
79   /**
80    * This is a linked list.
81    */
82   struct GNUNET_REGEX_Automaton *prev;
83
84   /**
85    * This is a linked list.
86    */
87   struct GNUNET_REGEX_Automaton *next;
88
89   /**
90    * First state of the automaton. This is mainly used for constructing an NFA,
91    * where each NFA itself consists of one or more NFAs linked together.
92    */
93   struct GNUNET_REGEX_State *start;
94
95   /**
96    * End state of the automaton.
97    */
98   struct GNUNET_REGEX_State *end;
99
100   /**
101    * Number of states in the automaton.
102    */
103   unsigned int state_count;
104
105   /**
106    * DLL of states.
107    */
108   struct GNUNET_REGEX_State *states_head;
109
110   /**
111    * DLL of states
112    */
113   struct GNUNET_REGEX_State *states_tail;
114
115   /**
116    * Type of the automaton.
117    */
118   enum GNUNET_REGEX_automaton_type type;
119 };
120
121 /**
122  * A state. Can be used in DFA and NFA automatons.
123  */
124 struct GNUNET_REGEX_State
125 {
126   /**
127    * This is a linked list.
128    */
129   struct GNUNET_REGEX_State *prev;
130
131   /**
132    * This is a linked list.
133    */
134   struct GNUNET_REGEX_State *next;
135
136   /**
137    * Unique state id.
138    */
139   unsigned int id;
140
141   /**
142    * If this is an accepting state or not.
143    */
144   int accepting;
145
146   /**
147    * Marking of the state. This is used for marking all visited states when
148    * traversing all states of an automaton and for cases where the state id
149    * cannot be used (dfa minimization).
150    */
151   int marked;
152
153   /**
154    * Marking the state as contained. This is used for checking, if the state is
155    * contained in a set in constant time
156    */
157   int contained;
158
159   /**
160    * Marking the state as part of an SCC (Strongly Connected Component).  All
161    * states with the same scc_id are part of the same SCC. scc_id is 0, if state
162    * is not a part of any SCC.
163    */
164   unsigned int scc_id;
165
166   /**
167    * Used for SCC detection.
168    */
169   int index;
170
171   /**
172    * Used for SCC detection.
173    */
174   int lowlink;
175
176   /**
177    * Human readable name of the automaton. Used for debugging and graph
178    * creation.
179    */
180   char *name;
181
182   /**
183    * Hash of the state.
184    */
185   GNUNET_HashCode hash;
186
187   /**
188    * Proof for this state.
189    */
190   char *proof;
191
192   /**
193    * Number of transitions from this state to other states.
194    */
195   unsigned int transition_count;
196
197   /**
198    * DLL of transitions.
199    */
200   struct Transition *transitions_head;
201
202   /**
203    * DLL of transitions.
204    */
205   struct Transition *transitions_tail;
206
207   /**
208    * Set of states on which this state is based on. Used when creating a DFA out
209    * of several NFA states.
210    */
211   struct GNUNET_REGEX_StateSet *nfa_set;
212 };
213
214 /**
215  * Transition between two states. Each state can have 0-n transitions.  If label
216  * is 0, this is considered to be an epsilon transition.
217  */
218 struct Transition
219 {
220   /**
221    * This is a linked list.
222    */
223   struct Transition *prev;
224
225   /**
226    * This is a linked list.
227    */
228   struct Transition *next;
229
230   /**
231    * Unique id of this transition.
232    */
233   unsigned int id;
234
235   /**
236    * Label for this transition. This is basically the edge label for the graph.
237    */
238   char label;
239
240   /**
241    * State to which this transition leads.
242    */
243   struct GNUNET_REGEX_State *to_state;
244
245   /**
246    * State from which this transition origins.
247    */
248   struct GNUNET_REGEX_State *from_state;
249
250   /**
251    * Mark this transition. For example when reversing the automaton.
252    */
253   int mark;
254 };
255
256 /**
257  * Set of states.
258  */
259 struct GNUNET_REGEX_StateSet
260 {
261   /**
262    * Array of states.
263    */
264   struct GNUNET_REGEX_State **states;
265
266   /**
267    * Length of the 'states' array.
268    */
269   unsigned int len;
270 };
271
272 /*
273  * Debug helper functions
274  */
275 void
276 debug_print_transitions (struct GNUNET_REGEX_State *);
277
278 void
279 debug_print_state (struct GNUNET_REGEX_State *s)
280 {
281   char *proof;
282
283   if (NULL == s->proof)
284     proof = "NULL";
285   else
286     proof = s->proof;
287
288   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
289               "State %i: %s marked: %i accepting: %i scc_id: %i transitions: %i proof: %s\n",
290               s->id, s->name, s->marked, s->accepting, s->scc_id,
291               s->transition_count, proof);
292
293   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Transitions:\n");
294   debug_print_transitions (s);
295 }
296
297 void
298 debug_print_states (struct GNUNET_REGEX_Automaton *a)
299 {
300   struct GNUNET_REGEX_State *s;
301
302   for (s = a->states_head; NULL != s; s = s->next)
303     debug_print_state (s);
304 }
305
306 void
307 debug_print_transition (struct Transition *t)
308 {
309   char *to_state;
310   char *from_state;
311   char label;
312
313   if (NULL == t)
314     return;
315
316   if (0 == t->label)
317     label = '0';
318   else
319     label = t->label;
320
321   if (NULL == t->to_state)
322     to_state = "NULL";
323   else
324     to_state = t->to_state->name;
325
326   if (NULL == t->from_state)
327     from_state = "NULL";
328   else
329     from_state = t->from_state->name;
330
331   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Transition %i: From %s on %c to %s\n",
332               t->id, from_state, label, to_state);
333 }
334
335 void
336 debug_print_transitions (struct GNUNET_REGEX_State *s)
337 {
338   struct Transition *t;
339
340   for (t = s->transitions_head; NULL != t; t = t->next)
341     debug_print_transition (t);
342 }
343
344 /**
345  * Recursive function doing DFS with 'v' as a start, detecting all SCCs inside
346  * the subgraph reachable from 'v'. Used with scc_tarjan function to detect all
347  * SCCs inside an automaton.
348  *
349  * @param ctx context
350  * @param v start vertex
351  * @param index current index
352  * @param stack stack for saving all SCCs
353  * @param stack_size current size of the stack
354  */
355 static void
356 scc_tarjan_strongconnect (struct GNUNET_REGEX_Context *ctx,
357                           struct GNUNET_REGEX_State *v, int *index,
358                           struct GNUNET_REGEX_State **stack,
359                           unsigned int *stack_size)
360 {
361   struct GNUNET_REGEX_State *w;
362   struct Transition *t;
363
364   v->index = *index;
365   v->lowlink = *index;
366   (*index)++;
367   stack[(*stack_size)++] = v;
368   v->contained = 1;
369
370   for (t = v->transitions_head; NULL != t; t = t->next)
371   {
372     w = t->to_state;
373     if (NULL != w && w->index < 0)
374     {
375       scc_tarjan_strongconnect (ctx, w, index, stack, stack_size);
376       v->lowlink = (v->lowlink > w->lowlink) ? w->lowlink : v->lowlink;
377     }
378     else if (0 != w->contained)
379       v->lowlink = (v->lowlink > w->index) ? w->index : v->lowlink;
380   }
381
382   if (v->lowlink == v->index)
383   {
384     w = stack[--(*stack_size)];
385     w->contained = 0;
386
387     if (v != w)
388     {
389       ctx->scc_id++;
390       while (v != w)
391       {
392         w->scc_id = ctx->scc_id;
393         w = stack[--(*stack_size)];
394         w->contained = 0;
395       }
396       w->scc_id = ctx->scc_id;
397     }
398   }
399 }
400
401 /**
402  * Detect all SCCs (Strongly Connected Components) inside the given automaton.
403  * SCCs will be marked using the scc_id on each state.
404  *
405  * @param ctx context
406  * @param a automaton
407  */
408 static void
409 scc_tarjan (struct GNUNET_REGEX_Context *ctx, struct GNUNET_REGEX_Automaton *a)
410 {
411   int index;
412   struct GNUNET_REGEX_State *v;
413   struct GNUNET_REGEX_State *stack[a->state_count];
414   unsigned int stack_size;
415
416   for (v = a->states_head; NULL != v; v = v->next)
417   {
418     v->contained = 0;
419     v->index = -1;
420     v->lowlink = -1;
421   }
422
423   stack_size = 0;
424   index = 0;
425
426   for (v = a->states_head; NULL != v; v = v->next)
427   {
428     if (v->index < 0)
429       scc_tarjan_strongconnect (ctx, v, &index, stack, &stack_size);
430   }
431 }
432
433 /**
434  * Adds a transition from one state to another on 'label'. Does not add
435  * duplicate states.
436  *
437  * @param ctx context
438  * @param from_state starting state for the transition
439  * @param label transition label
440  * @param to_state state to where the transition should point to
441  */
442 static void
443 state_add_transition (struct GNUNET_REGEX_Context *ctx,
444                       struct GNUNET_REGEX_State *from_state, const char label,
445                       struct GNUNET_REGEX_State *to_state)
446 {
447   int is_dup;
448   struct Transition *t;
449
450   if (NULL == from_state)
451   {
452     GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "Could not create Transition.\n");
453     return;
454   }
455
456   // Do not add duplicate state transitions
457   is_dup = GNUNET_NO;
458   for (t = from_state->transitions_head; NULL != t; t = t->next)
459   {
460     if (t->to_state == to_state && t->label == label &&
461         t->from_state == from_state)
462     {
463       is_dup = GNUNET_YES;
464       break;
465     }
466   }
467
468   if (is_dup)
469     return;
470
471   t = GNUNET_malloc (sizeof (struct Transition));
472   t->id = ctx->transition_id++;
473   t->label = label;
474   t->to_state = to_state;
475   t->from_state = from_state;
476
477   // Add outgoing transition to 'from_state'
478   from_state->transition_count++;
479   GNUNET_CONTAINER_DLL_insert (from_state->transitions_head,
480                                from_state->transitions_tail, t);
481 }
482
483 /**
484  * Compare two states. Used for sorting.
485  *
486  * @param a first state
487  * @param b second state
488  *
489  * @return an integer less than, equal to, or greater than zero
490  *         if the first argument is considered to be respectively
491  *         less than, equal to, or greater than the second.
492  */
493 static int
494 state_compare (const void *a, const void *b)
495 {
496   struct GNUNET_REGEX_State **s1;
497   struct GNUNET_REGEX_State **s2;
498
499   s1 = (struct GNUNET_REGEX_State **) a;
500   s2 = (struct GNUNET_REGEX_State **) b;
501
502   return (*s1)->id - (*s2)->id;
503 }
504
505 /**
506  * Get all edges leaving state 's'.
507  *
508  * @param s state.
509  * @param edges all edges leaving 's'.
510  *
511  * @return number of edges.
512  */
513 static unsigned int
514 state_get_edges (struct GNUNET_REGEX_State *s, struct GNUNET_REGEX_Edge *edges)
515 {
516   struct Transition *t;
517   unsigned int count;
518
519   if (NULL == s)
520     return 0;
521
522   count = 0;
523
524   for (t = s->transitions_head; NULL != t; t = t->next)
525   {
526     if (NULL != t->to_state)
527     {
528       edges[count].label = &t->label;
529       edges[count].destination = t->to_state->hash;
530       count++;
531     }
532   }
533   return count;
534 }
535
536 /**
537  * Compare to state sets by comparing the id's of the states that are contained
538  * in each set. Both sets are expected to be sorted by id!
539  *
540  * @param sset1 first state set
541  * @param sset2 second state set
542  *
543  * @return an integer less than, equal to, or greater than zero
544  *         if the first argument is considered to be respectively
545  *         less than, equal to, or greater than the second.
546  */
547 static int
548 state_set_compare (struct GNUNET_REGEX_StateSet *sset1,
549                    struct GNUNET_REGEX_StateSet *sset2)
550 {
551   int result;
552   int i;
553
554   if (NULL == sset1 || NULL == sset2)
555     return 1;
556
557   result = sset1->len - sset2->len;
558
559   for (i = 0; i < sset1->len; i++)
560   {
561     if (0 != result)
562       break;
563
564     result = state_compare (&sset1->states[i], &sset2->states[i]);
565   }
566   return result;
567 }
568
569 /**
570  * Clears the given StateSet 'set'
571  *
572  * @param set set to be cleared
573  */
574 static void
575 state_set_clear (struct GNUNET_REGEX_StateSet *set)
576 {
577   if (NULL != set)
578   {
579     GNUNET_free_non_null (set->states);
580     GNUNET_free (set);
581   }
582 }
583
584 /**
585  * Clears an automaton fragment. Does not destroy the states inside the
586  * automaton.
587  *
588  * @param a automaton to be cleared
589  */
590 static void
591 automaton_fragment_clear (struct GNUNET_REGEX_Automaton *a)
592 {
593   if (NULL == a)
594     return;
595
596   a->start = NULL;
597   a->end = NULL;
598   a->states_head = NULL;
599   a->states_tail = NULL;
600   a->state_count = 0;
601   GNUNET_free (a);
602 }
603
604 /**
605  * Frees the memory used by State 's'
606  *
607  * @param s state that should be destroyed
608  */
609 static void
610 automaton_destroy_state (struct GNUNET_REGEX_State *s)
611 {
612   struct Transition *t;
613   struct Transition *next_t;
614
615   if (NULL == s)
616     return;
617
618   GNUNET_free_non_null (s->name);
619   GNUNET_free_non_null (s->proof);
620
621   for (t = s->transitions_head; NULL != t; t = next_t)
622   {
623     next_t = t->next;
624     GNUNET_CONTAINER_DLL_remove (s->transitions_head, s->transitions_tail, t);
625     GNUNET_free (t);
626   }
627
628   state_set_clear (s->nfa_set);
629
630   GNUNET_free (s);
631 }
632
633 /**
634  * Remove a state from the given automaton 'a'. Always use this function when
635  * altering the states of an automaton. Will also remove all transitions leading
636  * to this state, before destroying it.
637  *
638  * @param a automaton
639  * @param s state to remove
640  */
641 static void
642 automaton_remove_state (struct GNUNET_REGEX_Automaton *a,
643                         struct GNUNET_REGEX_State *s)
644 {
645   struct GNUNET_REGEX_State *ss;
646   struct GNUNET_REGEX_State *s_check;
647   struct Transition *t_check;
648
649   if (NULL == a || NULL == s)
650     return;
651
652   // remove state
653   ss = s;
654   GNUNET_CONTAINER_DLL_remove (a->states_head, a->states_tail, s);
655   a->state_count--;
656
657   // remove all transitions leading to this state
658   for (s_check = a->states_head; NULL != s_check; s_check = s_check->next)
659   {
660     for (t_check = s_check->transitions_head; NULL != t_check;
661          t_check = t_check->next)
662     {
663       if (t_check->to_state == ss)
664       {
665         GNUNET_CONTAINER_DLL_remove (s_check->transitions_head,
666                                      s_check->transitions_tail, t_check);
667         s_check->transition_count--;
668       }
669     }
670   }
671
672   automaton_destroy_state (ss);
673 }
674
675 /**
676  * Merge two states into one. Will merge 's1' and 's2' into 's1' and destroy
677  * 's2'.
678  *
679  * @param ctx context
680  * @param a automaton
681  * @param s1 first state
682  * @param s2 second state, will be destroyed
683  */
684 static void
685 automaton_merge_states (struct GNUNET_REGEX_Context *ctx,
686                         struct GNUNET_REGEX_Automaton *a,
687                         struct GNUNET_REGEX_State *s1,
688                         struct GNUNET_REGEX_State *s2)
689 {
690   struct GNUNET_REGEX_State *s_check;
691   struct Transition *t_check;
692   char *new_name;
693
694   GNUNET_assert (NULL != ctx && NULL != a && NULL != s1 && NULL != s2);
695
696   if (s1 == s2)
697     return;
698
699   // 1. Make all transitions pointing to s2 point to s1
700   for (s_check = a->states_head; NULL != s_check; s_check = s_check->next)
701   {
702     for (t_check = s_check->transitions_head; NULL != t_check;
703          t_check = t_check->next)
704     {
705       if (s2 == t_check->to_state)
706         t_check->to_state = s1;
707     }
708   }
709
710   // 2. Add all transitions from s2 to sX to s1
711   for (t_check = s2->transitions_head; NULL != t_check; t_check = t_check->next)
712   {
713     if (t_check->to_state != s1)
714       state_add_transition (ctx, s1, t_check->label, t_check->to_state);
715   }
716
717   // 3. Rename s1 to {s1,s2}
718   new_name = GNUNET_strdup (s1->name);
719   GNUNET_free_non_null (s1->name);
720   GNUNET_asprintf (&s1->name, "{%s,%s}", new_name, s2->name);
721   GNUNET_free (new_name);
722
723   // remove state
724   GNUNET_CONTAINER_DLL_remove (a->states_head, a->states_tail, s2);
725   a->state_count--;
726   automaton_destroy_state (s2);
727 }
728
729 /**
730  * Add a state to the automaton 'a', always use this function to alter the
731  * states DLL of the automaton.
732  *
733  * @param a automaton to add the state to
734  * @param s state that should be added
735  */
736 static void
737 automaton_add_state (struct GNUNET_REGEX_Automaton *a,
738                      struct GNUNET_REGEX_State *s)
739 {
740   GNUNET_CONTAINER_DLL_insert (a->states_head, a->states_tail, s);
741   a->state_count++;
742 }
743
744 /**
745  * Function that is called with each state, when traversing an automaton.
746  *
747  * @param cls closure
748  * @param s state
749  */
750 typedef void (*GNUNET_REGEX_traverse_action) (void *cls,
751                                               struct GNUNET_REGEX_State * s);
752
753 /**
754  * Traverses all states that are reachable from state 's'. Expects the states to
755  * be unmarked (s->marked == GNUNET_NO). Performs 'action' on each visited
756  * state.
757  *
758  * @param cls closure.
759  * @param s start state.
760  * @param action action to be performed on each state.
761  */
762 static void
763 automaton_state_traverse (void *cls, struct GNUNET_REGEX_State *s,
764                           GNUNET_REGEX_traverse_action action)
765 {
766   struct Transition *t;
767
768   if (GNUNET_NO == s->marked)
769   {
770     s->marked = GNUNET_YES;
771
772     if (action > 0)
773       action (cls, s);
774
775     for (t = s->transitions_head; NULL != t; t = t->next)
776       automaton_state_traverse (cls, t->to_state, action);
777   }
778 }
779
780 /**
781  * Traverses the given automaton from it's start state, visiting all reachable
782  * states and calling 'action' on each one of them.
783  *
784  * @param cls closure.
785  * @param a automaton.
786  * @param action action to be performed on each state.
787  */
788 static void
789 automaton_traverse (void *cls, struct GNUNET_REGEX_Automaton *a,
790                     GNUNET_REGEX_traverse_action action)
791 {
792   struct GNUNET_REGEX_State *s;
793
794   for (s = a->states_head; NULL != s; s = s->next)
795     s->marked = GNUNET_NO;
796
797   automaton_state_traverse (cls, a->start, action);
798 }
799
800 /**
801  * Create proofs for all states in the given automaton. Implementation of the
802  * algorithms descriped in chapter 3.2.1 of "Automata Theory, Languages, and
803  * Computation 3rd Edition" by Hopcroft, Motwani and Ullman.
804  *
805  * @param a automaton.
806  */
807 static void
808 automaton_create_proofs (struct GNUNET_REGEX_Automaton *a)
809 {
810   struct GNUNET_REGEX_State *s;
811   struct Transition *t;
812   int i;
813   int j;
814   int k;
815   int n;
816   struct GNUNET_REGEX_State *states[a->state_count];
817   char *R_last[a->state_count][a->state_count];
818   char *R_cur[a->state_count][a->state_count];
819   char *temp;
820
821   k = 0;
822   n = a->state_count;
823
824   for (i = 0, s = a->states_head; NULL != s; s = s->next, i++)
825   {
826     s->marked = i;
827     states[i] = s;
828   }
829
830   // BASIS
831   for (i = 0; i < n; i++)
832   {
833     for (j = 0; j < n; j++)
834     {
835       R_cur[i][j] = NULL;
836       R_last[i][j] = NULL;
837       for (t = states[i]->transitions_head; NULL != t; t = t->next)
838       {
839         if (t->to_state == states[j])
840         {
841           if (NULL == R_last[i][j])
842             GNUNET_asprintf (&R_last[i][j], "%c", t->label);
843           else
844           {
845             temp = R_last[i][j];
846             GNUNET_asprintf (&R_last[i][j], "%s|%c", R_last[i][j], t->label);
847             GNUNET_free (temp);
848           }
849         }
850       }
851
852       if (i == j)
853       {
854         if (NULL == R_last[i][j])
855           GNUNET_asprintf (&R_last[i][j], "");
856         else if (1 < strlen (R_last[i][j]))
857         {
858           temp = R_last[i][j];
859           GNUNET_asprintf (&R_last[i][j], "(%s)", R_last[i][j]);
860           GNUNET_free (temp);
861         }
862       }
863     }
864   }
865
866   // INDUCTION
867   for (k = 0; k < n; k++)
868   {
869     for (i = 0; i < n; i++)
870     {
871       for (j = 0; j < n; j++)
872       {
873         if (NULL == R_last[i][k] || NULL == R_last[k][j])
874         {
875           if (NULL != R_last[i][j])
876             R_cur[i][j] = GNUNET_strdup (R_last[i][j]);
877         }
878         else if (NULL == R_last[i][j] ||
879                  0 == strcmp (R_last[i][j], R_last[i][k]))
880         {
881           if ((R_last[k][k][0] == '(' &&
882                R_last[k][k][strlen (R_last[k][k]) - 1] == ')') ||
883               (1 == strlen (R_last[k][k])))
884             GNUNET_asprintf (&R_cur[i][j], "(%s%s*%s)", R_last[i][k],
885                              R_last[k][k], R_last[k][j]);
886           else
887             GNUNET_asprintf (&R_cur[i][j], "(%s(%s)*%s)", R_last[i][k],
888                              R_last[k][k], R_last[k][j]);
889         }
890         else
891         {
892           if ((R_last[k][k][0] == '(' &&
893                R_last[k][k][strlen (R_last[k][k]) - 1] == ')') ||
894               (1 == strlen (R_last[k][k])))
895             GNUNET_asprintf (&R_cur[i][j], "(%s|%s%s*%s)", R_last[i][j],
896                              R_last[i][k], R_last[k][k], R_last[k][j]);
897           else
898             GNUNET_asprintf (&R_cur[i][j], "(%s|%s(%s)*%s)", R_last[i][j],
899                              R_last[i][k], R_last[k][k], R_last[k][j]);
900         }
901       }
902     }
903
904     for (i = 0; i < n; i++)
905     {
906       for (j = 0; j < n; j++)
907       {
908         GNUNET_free_non_null (R_last[i][j]);
909
910         if (NULL != R_cur[i][j])
911         {
912           R_last[i][j] = GNUNET_strdup (R_cur[i][j]);
913           GNUNET_free (R_cur[i][j]);
914           R_cur[i][j] = NULL;
915         }
916       }
917     }
918   }
919
920   for (i = 0; i < n; i++)
921   {
922     for (j = 0; j < n; j++)
923       GNUNET_free_non_null (R_last[i][j]);
924   }
925 }
926
927 /**
928  * Creates a new DFA state based on a set of NFA states. Needs to be freed using
929  * automaton_destroy_state.
930  *
931  * @param ctx context
932  * @param nfa_states set of NFA states on which the DFA should be based on
933  *
934  * @return new DFA state
935  */
936 static struct GNUNET_REGEX_State *
937 dfa_state_create (struct GNUNET_REGEX_Context *ctx,
938                   struct GNUNET_REGEX_StateSet *nfa_states)
939 {
940   struct GNUNET_REGEX_State *s;
941   char *name;
942   int len = 0;
943   struct GNUNET_REGEX_State *cstate;
944   struct Transition *ctran;
945   int insert = 1;
946   struct Transition *t;
947   int i;
948
949   s = GNUNET_malloc (sizeof (struct GNUNET_REGEX_State));
950   s->id = ctx->state_id++;
951   s->accepting = 0;
952   s->marked = 0;
953   s->name = NULL;
954   s->scc_id = 0;
955   s->index = -1;
956   s->lowlink = -1;
957   s->contained = 0;
958   s->proof = NULL;
959
960   if (NULL == nfa_states)
961   {
962     GNUNET_asprintf (&s->name, "s%i", s->id);
963     return s;
964   }
965
966   s->nfa_set = nfa_states;
967
968   if (nfa_states->len < 1)
969     return s;
970
971   // Create a name based on 'sset'
972   s->name = GNUNET_malloc (sizeof (char) * 2);
973   strcat (s->name, "{");
974   name = NULL;
975
976   for (i = 0; i < nfa_states->len; i++)
977   {
978     cstate = nfa_states->states[i];
979     GNUNET_asprintf (&name, "%i,", cstate->id);
980
981     if (NULL != name)
982     {
983       len = strlen (s->name) + strlen (name) + 1;
984       s->name = GNUNET_realloc (s->name, len);
985       strcat (s->name, name);
986       GNUNET_free (name);
987       name = NULL;
988     }
989
990     // Add a transition for each distinct label to NULL state
991     for (ctran = cstate->transitions_head; NULL != ctran; ctran = ctran->next)
992     {
993       if (0 != ctran->label)
994       {
995         insert = 1;
996
997         for (t = s->transitions_head; NULL != t; t = t->next)
998         {
999           if (t->label == ctran->label)
1000           {
1001             insert = 0;
1002             break;
1003           }
1004         }
1005
1006         if (insert)
1007           state_add_transition (ctx, s, ctran->label, NULL);
1008       }
1009     }
1010
1011     // If the nfa_states contain an accepting state, the new dfa state is also
1012     // accepting
1013     if (cstate->accepting)
1014       s->accepting = 1;
1015   }
1016
1017   s->name[strlen (s->name) - 1] = '}';
1018
1019   return s;
1020 }
1021
1022 /**
1023  * Move from the given state 's' to the next state on transition 'label'
1024  *
1025  * @param s starting state
1026  * @param label edge label to follow
1027  *
1028  * @return new state or NULL, if transition on label not possible
1029  */
1030 static struct GNUNET_REGEX_State *
1031 dfa_move (struct GNUNET_REGEX_State *s, const char label)
1032 {
1033   struct Transition *t;
1034   struct GNUNET_REGEX_State *new_s;
1035
1036   if (NULL == s)
1037     return NULL;
1038
1039   new_s = NULL;
1040
1041   for (t = s->transitions_head; NULL != t; t = t->next)
1042   {
1043     if (label == t->label)
1044     {
1045       new_s = t->to_state;
1046       break;
1047     }
1048   }
1049
1050   return new_s;
1051 }
1052
1053 /**
1054  * Remove all unreachable states from DFA 'a'. Unreachable states are those
1055  * states that are not reachable from the starting state.
1056  *
1057  * @param a DFA automaton
1058  */
1059 static void
1060 dfa_remove_unreachable_states (struct GNUNET_REGEX_Automaton *a)
1061 {
1062   struct GNUNET_REGEX_State *s;
1063   struct GNUNET_REGEX_State *s_next;
1064
1065   // 1. unmark all states
1066   for (s = a->states_head; NULL != s; s = s->next)
1067     s->marked = GNUNET_NO;
1068
1069   // 2. traverse dfa from start state and mark all visited states
1070   automaton_traverse (NULL, a, NULL);
1071
1072   // 3. delete all states that were not visited
1073   for (s = a->states_head; NULL != s; s = s_next)
1074   {
1075     s_next = s->next;
1076     if (GNUNET_NO == s->marked)
1077       automaton_remove_state (a, s);
1078   }
1079 }
1080
1081 /**
1082  * Remove all dead states from the DFA 'a'. Dead states are those states that do
1083  * not transition to any other state but themselfes.
1084  *
1085  * @param a DFA automaton
1086  */
1087 static void
1088 dfa_remove_dead_states (struct GNUNET_REGEX_Automaton *a)
1089 {
1090   struct GNUNET_REGEX_State *s;
1091   struct Transition *t;
1092   int dead;
1093
1094   GNUNET_assert (DFA == a->type);
1095
1096   for (s = a->states_head; NULL != s; s = s->next)
1097   {
1098     if (s->accepting)
1099       continue;
1100
1101     dead = 1;
1102     for (t = s->transitions_head; NULL != t; t = t->next)
1103     {
1104       if (NULL != t->to_state && t->to_state != s)
1105       {
1106         dead = 0;
1107         break;
1108       }
1109     }
1110
1111     if (0 == dead)
1112       continue;
1113
1114     // state s is dead, remove it
1115     automaton_remove_state (a, s);
1116   }
1117 }
1118
1119 /**
1120  * Merge all non distinguishable states in the DFA 'a'
1121  *
1122  * @param ctx context
1123  * @param a DFA automaton
1124  */
1125 static void
1126 dfa_merge_nondistinguishable_states (struct GNUNET_REGEX_Context *ctx,
1127                                      struct GNUNET_REGEX_Automaton *a)
1128 {
1129   int i;
1130   int table[a->state_count][a->state_count];
1131   struct GNUNET_REGEX_State *s1;
1132   struct GNUNET_REGEX_State *s2;
1133   struct Transition *t1;
1134   struct Transition *t2;
1135   struct GNUNET_REGEX_State *s1_next;
1136   struct GNUNET_REGEX_State *s2_next;
1137   int change;
1138   int num_equal_edges;
1139
1140   for (i = 0, s1 = a->states_head; i < a->state_count && NULL != s1;
1141        i++, s1 = s1->next)
1142   {
1143     s1->marked = i;
1144   }
1145
1146   // Mark all pairs of accepting/!accepting states
1147   for (s1 = a->states_head; NULL != s1; s1 = s1->next)
1148   {
1149     for (s2 = a->states_head; NULL != s2; s2 = s2->next)
1150     {
1151       table[s1->marked][s2->marked] = 0;
1152
1153       if ((s1->accepting && !s2->accepting) ||
1154           (!s1->accepting && s2->accepting))
1155       {
1156         table[s1->marked][s2->marked] = 1;
1157       }
1158     }
1159   }
1160
1161   // Find all equal states
1162   change = 1;
1163   while (0 != change)
1164   {
1165     change = 0;
1166     for (s1 = a->states_head; NULL != s1; s1 = s1->next)
1167     {
1168       for (s2 = a->states_head; NULL != s2 && s1 != s2; s2 = s2->next)
1169       {
1170         if (0 != table[s1->marked][s2->marked])
1171           continue;
1172
1173         num_equal_edges = 0;
1174         for (t1 = s1->transitions_head; NULL != t1; t1 = t1->next)
1175         {
1176           for (t2 = s2->transitions_head; NULL != t2; t2 = t2->next)
1177           {
1178             if (t1->label == t2->label)
1179             {
1180               num_equal_edges++;
1181               if (0 != table[t1->to_state->marked][t2->to_state->marked] ||
1182                   0 != table[t2->to_state->marked][t1->to_state->marked])
1183               {
1184                 table[s1->marked][s2->marked] = t1->label != 0 ? t1->label : 1;
1185                 change = 1;
1186               }
1187             }
1188           }
1189         }
1190         if (num_equal_edges != s1->transition_count ||
1191             num_equal_edges != s2->transition_count)
1192         {
1193           // Make sure ALL edges of possible equal states are the same
1194           table[s1->marked][s2->marked] = -2;
1195         }
1196       }
1197     }
1198   }
1199
1200   // Merge states that are equal
1201   for (s1 = a->states_head; NULL != s1; s1 = s1_next)
1202   {
1203     s1_next = s1->next;
1204     for (s2 = a->states_head; NULL != s2 && s1 != s2; s2 = s2_next)
1205     {
1206       s2_next = s2->next;
1207       if (table[s1->marked][s2->marked] == 0)
1208         automaton_merge_states (ctx, a, s1, s2);
1209     }
1210   }
1211 }
1212
1213 /**
1214  * Minimize the given DFA 'a' by removing all unreachable states, removing all
1215  * dead states and merging all non distinguishable states
1216  *
1217  * @param ctx context
1218  * @param a DFA automaton
1219  */
1220 static void
1221 dfa_minimize (struct GNUNET_REGEX_Context *ctx,
1222               struct GNUNET_REGEX_Automaton *a)
1223 {
1224   if (NULL == a)
1225     return;
1226
1227   GNUNET_assert (DFA == a->type);
1228
1229   // 1. remove unreachable states
1230   dfa_remove_unreachable_states (a);
1231
1232   // 2. remove dead states
1233   dfa_remove_dead_states (a);
1234
1235   // 3. Merge nondistinguishable states
1236   dfa_merge_nondistinguishable_states (ctx, a);
1237 }
1238
1239 /**
1240  * Creates a new NFA fragment. Needs to be cleared using
1241  * automaton_fragment_clear.
1242  *
1243  * @param start starting state
1244  * @param end end state
1245  *
1246  * @return new NFA fragment
1247  */
1248 static struct GNUNET_REGEX_Automaton *
1249 nfa_fragment_create (struct GNUNET_REGEX_State *start,
1250                      struct GNUNET_REGEX_State *end)
1251 {
1252   struct GNUNET_REGEX_Automaton *n;
1253
1254   n = GNUNET_malloc (sizeof (struct GNUNET_REGEX_Automaton));
1255
1256   n->type = NFA;
1257   n->start = NULL;
1258   n->end = NULL;
1259
1260   if (NULL == start && NULL == end)
1261     return n;
1262
1263   automaton_add_state (n, end);
1264   automaton_add_state (n, start);
1265
1266   n->start = start;
1267   n->end = end;
1268
1269   return n;
1270 }
1271
1272 /**
1273  * Adds a list of states to the given automaton 'n'.
1274  *
1275  * @param n automaton to which the states should be added
1276  * @param states_head head of the DLL of states
1277  * @param states_tail tail of the DLL of states
1278  */
1279 static void
1280 nfa_add_states (struct GNUNET_REGEX_Automaton *n,
1281                 struct GNUNET_REGEX_State *states_head,
1282                 struct GNUNET_REGEX_State *states_tail)
1283 {
1284   struct GNUNET_REGEX_State *s;
1285
1286   if (NULL == n || NULL == states_head)
1287   {
1288     GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "Could not add states\n");
1289     return;
1290   }
1291
1292   if (NULL == n->states_head)
1293   {
1294     n->states_head = states_head;
1295     n->states_tail = states_tail;
1296     return;
1297   }
1298
1299   if (NULL != states_head)
1300   {
1301     n->states_tail->next = states_head;
1302     n->states_tail = states_tail;
1303   }
1304
1305   for (s = states_head; NULL != s; s = s->next)
1306     n->state_count++;
1307 }
1308
1309 /**
1310  * Creates a new NFA state. Needs to be freed using automaton_destroy_state.
1311  *
1312  * @param ctx context
1313  * @param accepting is it an accepting state or not
1314  *
1315  * @return new NFA state
1316  */
1317 static struct GNUNET_REGEX_State *
1318 nfa_state_create (struct GNUNET_REGEX_Context *ctx, int accepting)
1319 {
1320   struct GNUNET_REGEX_State *s;
1321
1322   s = GNUNET_malloc (sizeof (struct GNUNET_REGEX_State));
1323   s->id = ctx->state_id++;
1324   s->accepting = accepting;
1325   s->marked = 0;
1326   s->contained = 0;
1327   s->index = -1;
1328   s->lowlink = -1;
1329   s->scc_id = 0;
1330   s->name = NULL;
1331   GNUNET_asprintf (&s->name, "s%i", s->id);
1332
1333   return s;
1334 }
1335
1336 /**
1337  * Calculates the NFA closure set for the given state.
1338  *
1339  * @param nfa the NFA containing 's'
1340  * @param s starting point state
1341  * @param label transitioning label on which to base the closure on,
1342  *                pass 0 for epsilon transition
1343  *
1344  * @return sorted nfa closure on 'label' (epsilon closure if 'label' is 0)
1345  */
1346 static struct GNUNET_REGEX_StateSet *
1347 nfa_closure_create (struct GNUNET_REGEX_Automaton *nfa,
1348                     struct GNUNET_REGEX_State *s, const char label)
1349 {
1350   struct GNUNET_REGEX_StateSet *cls;
1351   struct GNUNET_REGEX_StateSet *cls_check;
1352   struct GNUNET_REGEX_State *clsstate;
1353   struct GNUNET_REGEX_State *currentstate;
1354   struct Transition *ctran;
1355
1356   if (NULL == s)
1357     return NULL;
1358
1359   cls = GNUNET_malloc (sizeof (struct GNUNET_REGEX_StateSet));
1360   cls_check = GNUNET_malloc (sizeof (struct GNUNET_REGEX_StateSet));
1361
1362   for (clsstate = nfa->states_head; NULL != clsstate; clsstate = clsstate->next)
1363     clsstate->contained = 0;
1364
1365   // Add start state to closure only for epsilon closure
1366   if (0 == label)
1367     GNUNET_array_append (cls->states, cls->len, s);
1368
1369   GNUNET_array_append (cls_check->states, cls_check->len, s);
1370   while (cls_check->len > 0)
1371   {
1372     currentstate = cls_check->states[cls_check->len - 1];
1373     GNUNET_array_grow (cls_check->states, cls_check->len, cls_check->len - 1);
1374
1375     for (ctran = currentstate->transitions_head; NULL != ctran;
1376          ctran = ctran->next)
1377     {
1378       if (NULL != ctran->to_state && label == ctran->label)
1379       {
1380         clsstate = ctran->to_state;
1381
1382         if (NULL != clsstate && 0 == clsstate->contained)
1383         {
1384           GNUNET_array_append (cls->states, cls->len, clsstate);
1385           GNUNET_array_append (cls_check->states, cls_check->len, clsstate);
1386           clsstate->contained = 1;
1387         }
1388       }
1389     }
1390   }
1391   GNUNET_assert (0 == cls_check->len);
1392   GNUNET_free (cls_check);
1393
1394   if (cls->len > 1)
1395     qsort (cls->states, cls->len, sizeof (struct GNUNET_REGEX_State *),
1396            state_compare);
1397
1398   return cls;
1399 }
1400
1401 /**
1402  * Calculates the closure set for the given set of states.
1403  *
1404  * @param nfa the NFA containing 's'
1405  * @param states list of states on which to base the closure on
1406  * @param label transitioning label for which to base the closure on,
1407  *                pass 0 for epsilon transition
1408  *
1409  * @return sorted nfa closure on 'label' (epsilon closure if 'label' is 0)
1410  */
1411 static struct GNUNET_REGEX_StateSet *
1412 nfa_closure_set_create (struct GNUNET_REGEX_Automaton *nfa,
1413                         struct GNUNET_REGEX_StateSet *states, const char label)
1414 {
1415   struct GNUNET_REGEX_State *s;
1416   struct GNUNET_REGEX_StateSet *sset;
1417   struct GNUNET_REGEX_StateSet *cls;
1418   int i;
1419   int j;
1420   int k;
1421   int contains;
1422
1423   if (NULL == states)
1424     return NULL;
1425
1426   cls = GNUNET_malloc (sizeof (struct GNUNET_REGEX_StateSet));
1427
1428   for (i = 0; i < states->len; i++)
1429   {
1430     s = states->states[i];
1431     sset = nfa_closure_create (nfa, s, label);
1432
1433     for (j = 0; j < sset->len; j++)
1434     {
1435       contains = 0;
1436       for (k = 0; k < cls->len; k++)
1437       {
1438         if (sset->states[j]->id == cls->states[k]->id)
1439         {
1440           contains = 1;
1441           break;
1442         }
1443       }
1444       if (!contains)
1445         GNUNET_array_append (cls->states, cls->len, sset->states[j]);
1446     }
1447     state_set_clear (sset);
1448   }
1449
1450   if (cls->len > 1)
1451     qsort (cls->states, cls->len, sizeof (struct GNUNET_REGEX_State *),
1452            state_compare);
1453
1454   return cls;
1455 }
1456
1457 /**
1458  * Pops two NFA fragments (a, b) from the stack and concatenates them (ab)
1459  *
1460  * @param ctx context
1461  */
1462 static void
1463 nfa_add_concatenation (struct GNUNET_REGEX_Context *ctx)
1464 {
1465   struct GNUNET_REGEX_Automaton *a;
1466   struct GNUNET_REGEX_Automaton *b;
1467   struct GNUNET_REGEX_Automaton *new;
1468
1469   b = ctx->stack_tail;
1470   GNUNET_CONTAINER_DLL_remove (ctx->stack_head, ctx->stack_tail, b);
1471   a = ctx->stack_tail;
1472   GNUNET_CONTAINER_DLL_remove (ctx->stack_head, ctx->stack_tail, a);
1473
1474   state_add_transition (ctx, a->end, 0, b->start);
1475   a->end->accepting = 0;
1476   b->end->accepting = 1;
1477
1478   new = nfa_fragment_create (NULL, NULL);
1479   nfa_add_states (new, a->states_head, a->states_tail);
1480   nfa_add_states (new, b->states_head, b->states_tail);
1481   new->start = a->start;
1482   new->end = b->end;
1483   automaton_fragment_clear (a);
1484   automaton_fragment_clear (b);
1485
1486   GNUNET_CONTAINER_DLL_insert_tail (ctx->stack_head, ctx->stack_tail, new);
1487 }
1488
1489 /**
1490  * Pops a NFA fragment from the stack (a) and adds a new fragment (a*)
1491  *
1492  * @param ctx context
1493  */
1494 static void
1495 nfa_add_star_op (struct GNUNET_REGEX_Context *ctx)
1496 {
1497   struct GNUNET_REGEX_Automaton *a;
1498   struct GNUNET_REGEX_Automaton *new;
1499   struct GNUNET_REGEX_State *start;
1500   struct GNUNET_REGEX_State *end;
1501
1502   a = ctx->stack_tail;
1503   GNUNET_CONTAINER_DLL_remove (ctx->stack_head, ctx->stack_tail, a);
1504
1505   if (NULL == a)
1506   {
1507     GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
1508                 "nfa_add_star_op failed, because there was no element on the stack");
1509     return;
1510   }
1511
1512   start = nfa_state_create (ctx, 0);
1513   end = nfa_state_create (ctx, 1);
1514
1515   state_add_transition (ctx, start, 0, a->start);
1516   state_add_transition (ctx, start, 0, end);
1517   state_add_transition (ctx, a->end, 0, a->start);
1518   state_add_transition (ctx, a->end, 0, end);
1519
1520   a->end->accepting = 0;
1521   end->accepting = 1;
1522
1523   new = nfa_fragment_create (start, end);
1524   nfa_add_states (new, a->states_head, a->states_tail);
1525   automaton_fragment_clear (a);
1526
1527   GNUNET_CONTAINER_DLL_insert_tail (ctx->stack_head, ctx->stack_tail, new);
1528 }
1529
1530 /**
1531  * Pops an NFA fragment (a) from the stack and adds a new fragment (a+)
1532  *
1533  * @param ctx context
1534  */
1535 static void
1536 nfa_add_plus_op (struct GNUNET_REGEX_Context *ctx)
1537 {
1538   struct GNUNET_REGEX_Automaton *a;
1539
1540   a = ctx->stack_tail;
1541   GNUNET_CONTAINER_DLL_remove (ctx->stack_head, ctx->stack_tail, a);
1542
1543   state_add_transition (ctx, a->end, 0, a->start);
1544
1545   GNUNET_CONTAINER_DLL_insert_tail (ctx->stack_head, ctx->stack_tail, a);
1546 }
1547
1548 /**
1549  * Pops an NFA fragment (a) from the stack and adds a new fragment (a?)
1550  *
1551  * @param ctx context
1552  */
1553 static void
1554 nfa_add_question_op (struct GNUNET_REGEX_Context *ctx)
1555 {
1556   struct GNUNET_REGEX_Automaton *a;
1557   struct GNUNET_REGEX_Automaton *new;
1558   struct GNUNET_REGEX_State *start;
1559   struct GNUNET_REGEX_State *end;
1560
1561   a = ctx->stack_tail;
1562   GNUNET_CONTAINER_DLL_remove (ctx->stack_head, ctx->stack_tail, a);
1563
1564   if (NULL == a)
1565   {
1566     GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
1567                 "nfa_add_question_op failed, because there was no element on the stack");
1568     return;
1569   }
1570
1571   start = nfa_state_create (ctx, 0);
1572   end = nfa_state_create (ctx, 1);
1573
1574   state_add_transition (ctx, start, 0, a->start);
1575   state_add_transition (ctx, start, 0, end);
1576   state_add_transition (ctx, a->end, 0, end);
1577
1578   a->end->accepting = 0;
1579
1580   new = nfa_fragment_create (start, end);
1581   nfa_add_states (new, a->states_head, a->states_tail);
1582   automaton_fragment_clear (a);
1583
1584   GNUNET_CONTAINER_DLL_insert_tail (ctx->stack_head, ctx->stack_tail, new);
1585 }
1586
1587 /**
1588  * Pops two NFA fragments (a, b) from the stack and adds a new NFA fragment that
1589  * alternates between a and b (a|b)
1590  *
1591  * @param ctx context
1592  */
1593 static void
1594 nfa_add_alternation (struct GNUNET_REGEX_Context *ctx)
1595 {
1596   struct GNUNET_REGEX_Automaton *a;
1597   struct GNUNET_REGEX_Automaton *b;
1598   struct GNUNET_REGEX_Automaton *new;
1599   struct GNUNET_REGEX_State *start;
1600   struct GNUNET_REGEX_State *end;
1601
1602   b = ctx->stack_tail;
1603   GNUNET_CONTAINER_DLL_remove (ctx->stack_head, ctx->stack_tail, b);
1604   a = ctx->stack_tail;
1605   GNUNET_CONTAINER_DLL_remove (ctx->stack_head, ctx->stack_tail, a);
1606
1607   start = nfa_state_create (ctx, 0);
1608   end = nfa_state_create (ctx, 1);
1609   state_add_transition (ctx, start, 0, a->start);
1610   state_add_transition (ctx, start, 0, b->start);
1611
1612   state_add_transition (ctx, a->end, 0, end);
1613   state_add_transition (ctx, b->end, 0, end);
1614
1615   a->end->accepting = 0;
1616   b->end->accepting = 0;
1617   end->accepting = 1;
1618
1619   new = nfa_fragment_create (start, end);
1620   nfa_add_states (new, a->states_head, a->states_tail);
1621   nfa_add_states (new, b->states_head, b->states_tail);
1622   automaton_fragment_clear (a);
1623   automaton_fragment_clear (b);
1624
1625   GNUNET_CONTAINER_DLL_insert_tail (ctx->stack_head, ctx->stack_tail, new);
1626 }
1627
1628 /**
1629  * Adds a new nfa fragment to the stack
1630  *
1631  * @param ctx context
1632  * @param lit label for nfa transition
1633  */
1634 static void
1635 nfa_add_label (struct GNUNET_REGEX_Context *ctx, const char lit)
1636 {
1637   struct GNUNET_REGEX_Automaton *n;
1638   struct GNUNET_REGEX_State *start;
1639   struct GNUNET_REGEX_State *end;
1640
1641   GNUNET_assert (NULL != ctx);
1642
1643   start = nfa_state_create (ctx, 0);
1644   end = nfa_state_create (ctx, 1);
1645   state_add_transition (ctx, start, lit, end);
1646   n = nfa_fragment_create (start, end);
1647   GNUNET_assert (NULL != n);
1648   GNUNET_CONTAINER_DLL_insert_tail (ctx->stack_head, ctx->stack_tail, n);
1649 }
1650
1651 /**
1652  * Initialize a new context
1653  *
1654  * @param ctx context
1655  */
1656 static void
1657 GNUNET_REGEX_context_init (struct GNUNET_REGEX_Context *ctx)
1658 {
1659   if (NULL == ctx)
1660   {
1661     GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "Context was NULL!");
1662     return;
1663   }
1664   ctx->state_id = 0;
1665   ctx->transition_id = 0;
1666   ctx->scc_id = 0;
1667   ctx->stack_head = NULL;
1668   ctx->stack_tail = NULL;
1669 }
1670
1671 /**
1672  * Construct an NFA by parsing the regex string of length 'len'.
1673  *
1674  * @param regex regular expression string
1675  * @param len length of the string
1676  *
1677  * @return NFA, needs to be freed using GNUNET_REGEX_destroy_automaton
1678  */
1679 struct GNUNET_REGEX_Automaton *
1680 GNUNET_REGEX_construct_nfa (const char *regex, const size_t len)
1681 {
1682   struct GNUNET_REGEX_Context ctx;
1683   struct GNUNET_REGEX_Automaton *nfa;
1684   const char *regexp;
1685   char *error_msg;
1686   unsigned int count;
1687   unsigned int altcount;
1688   unsigned int atomcount;
1689   unsigned int pcount;
1690   struct
1691   {
1692     int altcount;
1693     int atomcount;
1694   }     *p;
1695
1696   GNUNET_REGEX_context_init (&ctx);
1697
1698   regexp = regex;
1699   p = NULL;
1700   error_msg = NULL;
1701   altcount = 0;
1702   atomcount = 0;
1703   pcount = 0;
1704
1705   for (count = 0; count < len && *regexp; count++, regexp++)
1706   {
1707     switch (*regexp)
1708     {
1709     case '(':
1710       if (atomcount > 1)
1711       {
1712         --atomcount;
1713         nfa_add_concatenation (&ctx);
1714       }
1715       GNUNET_array_grow (p, pcount, pcount + 1);
1716       p[pcount - 1].altcount = altcount;
1717       p[pcount - 1].atomcount = atomcount;
1718       altcount = 0;
1719       atomcount = 0;
1720       break;
1721     case '|':
1722       if (0 == atomcount)
1723       {
1724         error_msg = "Cannot append '|' to nothing";
1725         goto error;
1726       }
1727       while (--atomcount > 0)
1728         nfa_add_concatenation (&ctx);
1729       altcount++;
1730       break;
1731     case ')':
1732       if (0 == pcount)
1733       {
1734         error_msg = "Missing opening '('";
1735         goto error;
1736       }
1737       if (0 == atomcount)
1738       {
1739         // Ignore this: "()"
1740         pcount--;
1741         altcount = p[pcount].altcount;
1742         atomcount = p[pcount].atomcount;
1743         break;
1744       }
1745       while (--atomcount > 0)
1746         nfa_add_concatenation (&ctx);
1747       for (; altcount > 0; altcount--)
1748         nfa_add_alternation (&ctx);
1749       pcount--;
1750       altcount = p[pcount].altcount;
1751       atomcount = p[pcount].atomcount;
1752       atomcount++;
1753       break;
1754     case '*':
1755       if (atomcount == 0)
1756       {
1757         error_msg = "Cannot append '*' to nothing";
1758         goto error;
1759       }
1760       nfa_add_star_op (&ctx);
1761       break;
1762     case '+':
1763       if (atomcount == 0)
1764       {
1765         error_msg = "Cannot append '+' to nothing";
1766         goto error;
1767       }
1768       nfa_add_plus_op (&ctx);
1769       break;
1770     case '?':
1771       if (atomcount == 0)
1772       {
1773         error_msg = "Cannot append '?' to nothing";
1774         goto error;
1775       }
1776       nfa_add_question_op (&ctx);
1777       break;
1778     case 92:                   /* escape: \ */
1779       regexp++;
1780       count++;
1781     default:
1782       if (atomcount > 1)
1783       {
1784         --atomcount;
1785         nfa_add_concatenation (&ctx);
1786       }
1787       nfa_add_label (&ctx, *regexp);
1788       atomcount++;
1789       break;
1790     }
1791   }
1792   if (0 != pcount)
1793   {
1794     error_msg = "Unbalanced parenthesis";
1795     goto error;
1796   }
1797   while (--atomcount > 0)
1798     nfa_add_concatenation (&ctx);
1799   for (; altcount > 0; altcount--)
1800     nfa_add_alternation (&ctx);
1801
1802   GNUNET_free_non_null (p);
1803
1804   nfa = ctx.stack_tail;
1805   GNUNET_CONTAINER_DLL_remove (ctx.stack_head, ctx.stack_tail, nfa);
1806
1807   if (NULL != ctx.stack_head)
1808   {
1809     error_msg = "Creating the NFA failed. NFA stack was not empty!";
1810     goto error;
1811   }
1812
1813   return nfa;
1814
1815 error:
1816   GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "Could not parse regex\n");
1817   if (NULL != error_msg)
1818     GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "%s\n", error_msg);
1819
1820   GNUNET_free_non_null (p);
1821
1822   while (NULL != ctx.stack_tail)
1823   {
1824     GNUNET_REGEX_automaton_destroy (ctx.stack_tail);
1825     GNUNET_CONTAINER_DLL_remove (ctx.stack_head, ctx.stack_tail,
1826                                  ctx.stack_tail);
1827   }
1828   return NULL;
1829 }
1830
1831 /**
1832  * Create DFA states based on given 'nfa' and starting with 'dfa_state'.
1833  *
1834  * @param ctx context.
1835  * @param nfa NFA automaton.
1836  * @param dfa DFA automaton.
1837  * @param dfa_state current dfa state, pass epsilon closure of first nfa state
1838  *                  for starting.
1839  */
1840 static void
1841 construct_dfa_states (struct GNUNET_REGEX_Context *ctx,
1842                       struct GNUNET_REGEX_Automaton *nfa,
1843                       struct GNUNET_REGEX_Automaton *dfa,
1844                       struct GNUNET_REGEX_State *dfa_state)
1845 {
1846   struct Transition *ctran;
1847   struct GNUNET_REGEX_State *state_iter;
1848   struct GNUNET_REGEX_State *new_dfa_state;
1849   struct GNUNET_REGEX_State *state_contains;
1850   struct GNUNET_REGEX_StateSet *tmp;
1851   struct GNUNET_REGEX_StateSet *nfa_set;
1852
1853   for (ctran = dfa_state->transitions_head; NULL != ctran; ctran = ctran->next)
1854   {
1855     if (0 == ctran->label || NULL != ctran->to_state)
1856       continue;
1857
1858     tmp = nfa_closure_set_create (nfa, dfa_state->nfa_set, ctran->label);
1859     nfa_set = nfa_closure_set_create (nfa, tmp, 0);
1860     state_set_clear (tmp);
1861     new_dfa_state = dfa_state_create (ctx, nfa_set);
1862     state_contains = NULL;
1863     for (state_iter = dfa->states_head; NULL != state_iter;
1864          state_iter = state_iter->next)
1865     {
1866       if (0 == state_set_compare (state_iter->nfa_set, new_dfa_state->nfa_set))
1867         state_contains = state_iter;
1868     }
1869
1870     if (NULL == state_contains)
1871     {
1872       automaton_add_state (dfa, new_dfa_state);
1873       ctran->to_state = new_dfa_state;
1874       construct_dfa_states (ctx, nfa, dfa, new_dfa_state);
1875     }
1876     else
1877     {
1878       ctran->to_state = state_contains;
1879       automaton_destroy_state (new_dfa_state);
1880     }
1881   }
1882 }
1883
1884 /**
1885  * Construct DFA for the given 'regex' of length 'len'
1886  *
1887  * @param regex regular expression string
1888  * @param len length of the regular expression
1889  *
1890  * @return DFA, needs to be freed using GNUNET_REGEX_destroy_automaton
1891  */
1892 struct GNUNET_REGEX_Automaton *
1893 GNUNET_REGEX_construct_dfa (const char *regex, const size_t len)
1894 {
1895   struct GNUNET_REGEX_Context ctx;
1896   struct GNUNET_REGEX_Automaton *dfa;
1897   struct GNUNET_REGEX_Automaton *nfa;
1898   struct GNUNET_REGEX_StateSet *nfa_set;
1899
1900   GNUNET_REGEX_context_init (&ctx);
1901
1902   // Create NFA
1903   nfa = GNUNET_REGEX_construct_nfa (regex, len);
1904
1905   if (NULL == nfa)
1906   {
1907     GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
1908                 "Could not create DFA, because NFA creation failed\n");
1909     return NULL;
1910   }
1911
1912   dfa = GNUNET_malloc (sizeof (struct GNUNET_REGEX_Automaton));
1913   dfa->type = DFA;
1914
1915   // Create DFA start state from epsilon closure
1916   nfa_set = nfa_closure_create (nfa, nfa->start, 0);
1917   dfa->start = dfa_state_create (&ctx, nfa_set);
1918   automaton_add_state (dfa, dfa->start);
1919
1920   construct_dfa_states (&ctx, nfa, dfa, dfa->start);
1921
1922   GNUNET_REGEX_automaton_destroy (nfa);
1923
1924   // Minimize DFA
1925   dfa_minimize (&ctx, dfa);
1926
1927   // Calculate SCCs
1928   scc_tarjan (&ctx, dfa);
1929
1930   // Create proofs for all states
1931   automaton_create_proofs (dfa);
1932
1933   return dfa;
1934 }
1935
1936 /**
1937  * Free the memory allocated by constructing the GNUNET_REGEX_Automaton data
1938  * structure.
1939  *
1940  * @param a automaton to be destroyed
1941  */
1942 void
1943 GNUNET_REGEX_automaton_destroy (struct GNUNET_REGEX_Automaton *a)
1944 {
1945   struct GNUNET_REGEX_State *s;
1946   struct GNUNET_REGEX_State *next_state;
1947
1948   if (NULL == a)
1949     return;
1950
1951   for (s = a->states_head; NULL != s;)
1952   {
1953     next_state = s->next;
1954     automaton_destroy_state (s);
1955     s = next_state;
1956   }
1957
1958   GNUNET_free (a);
1959 }
1960
1961 /**
1962  * Save the given automaton as a GraphViz dot file
1963  *
1964  * @param a the automaton to be saved
1965  * @param filename where to save the file
1966  */
1967 void
1968 GNUNET_REGEX_automaton_save_graph (struct GNUNET_REGEX_Automaton *a,
1969                                    const char *filename)
1970 {
1971   struct GNUNET_REGEX_State *s;
1972   struct Transition *ctran;
1973   char *s_acc = NULL;
1974   char *s_tran = NULL;
1975   char *start;
1976   char *end;
1977   FILE *p;
1978
1979   if (NULL == a)
1980   {
1981     GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "Could not print NFA, was NULL!");
1982     return;
1983   }
1984
1985   if (NULL == filename || strlen (filename) < 1)
1986   {
1987     GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "No Filename given!");
1988     return;
1989   }
1990
1991   p = fopen (filename, "w");
1992
1993   if (NULL == p)
1994   {
1995     GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "Could not open file for writing: %s",
1996                 filename);
1997     return;
1998   }
1999
2000   start = "digraph G {\nrankdir=LR\n";
2001   fwrite (start, strlen (start), 1, p);
2002
2003   for (s = a->states_head; NULL != s; s = s->next)
2004   {
2005     if (s->accepting)
2006     {
2007       GNUNET_asprintf (&s_acc,
2008                        "\"%s\" [shape=doublecircle, color=\"0.%i 0.8 0.95\"];\n",
2009                        s->name, s->scc_id);
2010     }
2011     else
2012     {
2013       GNUNET_asprintf (&s_acc, "\"%s\" [color=\"0.%i 0.8 0.95\"];\n", s->name,
2014                        s->scc_id);
2015     }
2016
2017     if (NULL == s_acc)
2018     {
2019       GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "Could not print state %s\n",
2020                   s->name);
2021       return;
2022     }
2023     fwrite (s_acc, strlen (s_acc), 1, p);
2024     GNUNET_free (s_acc);
2025     s_acc = NULL;
2026
2027     for (ctran = s->transitions_head; NULL != ctran; ctran = ctran->next)
2028     {
2029       if (NULL == ctran->to_state)
2030       {
2031         GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
2032                     "Transition from State %i has has no state for transitioning\n",
2033                     s->id);
2034         continue;
2035       }
2036
2037       if (ctran->label == 0)
2038       {
2039         GNUNET_asprintf (&s_tran,
2040                          "\"%s\" -> \"%s\" [label = \"epsilon\", color=\"0.%i 0.8 0.95\"];\n",
2041                          s->name, ctran->to_state->name, s->scc_id);
2042       }
2043       else
2044       {
2045         GNUNET_asprintf (&s_tran,
2046                          "\"%s\" -> \"%s\" [label = \"%c\", color=\"0.%i 0.8 0.95\"];\n",
2047                          s->name, ctran->to_state->name, ctran->label,
2048                          s->scc_id);
2049       }
2050
2051       if (NULL == s_tran)
2052       {
2053         GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "Could not print state %s\n",
2054                     s->name);
2055         return;
2056       }
2057
2058       fwrite (s_tran, strlen (s_tran), 1, p);
2059       GNUNET_free (s_tran);
2060       s_tran = NULL;
2061     }
2062   }
2063
2064   end = "\n}\n";
2065   fwrite (end, strlen (end), 1, p);
2066   fclose (p);
2067 }
2068
2069 /**
2070  * Evaluates the given string using the given DFA automaton
2071  *
2072  * @param a automaton, type must be DFA
2073  * @param string string that should be evaluated
2074  *
2075  * @return 0 if string matches, non 0 otherwise
2076  */
2077 static int
2078 evaluate_dfa (struct GNUNET_REGEX_Automaton *a, const char *string)
2079 {
2080   const char *strp;
2081   struct GNUNET_REGEX_State *s;
2082
2083   if (DFA != a->type)
2084   {
2085     GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
2086                 "Tried to evaluate DFA, but NFA automaton given");
2087     return -1;
2088   }
2089
2090   s = a->start;
2091
2092   for (strp = string; NULL != strp && *strp; strp++)
2093   {
2094     s = dfa_move (s, *strp);
2095     if (NULL == s)
2096       break;
2097   }
2098
2099   if (NULL != s && s->accepting)
2100     return 0;
2101
2102   return 1;
2103 }
2104
2105 /**
2106  * Evaluates the given string using the given NFA automaton
2107  *
2108  * @param a automaton, type must be NFA
2109  * @param string string that should be evaluated
2110  *
2111  * @return 0 if string matches, non 0 otherwise
2112  */
2113 static int
2114 evaluate_nfa (struct GNUNET_REGEX_Automaton *a, const char *string)
2115 {
2116   const char *strp;
2117   struct GNUNET_REGEX_State *s;
2118   struct GNUNET_REGEX_StateSet *sset;
2119   struct GNUNET_REGEX_StateSet *new_sset;
2120   int i;
2121   int result;
2122
2123   if (NFA != a->type)
2124   {
2125     GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
2126                 "Tried to evaluate NFA, but DFA automaton given");
2127     return -1;
2128   }
2129
2130   result = 1;
2131   strp = string;
2132   sset = nfa_closure_create (a, a->start, 0);
2133
2134   for (strp = string; NULL != strp && *strp; strp++)
2135   {
2136     new_sset = nfa_closure_set_create (a, sset, *strp);
2137     state_set_clear (sset);
2138     sset = nfa_closure_set_create (a, new_sset, 0);
2139     state_set_clear (new_sset);
2140   }
2141
2142   for (i = 0; i < sset->len; i++)
2143   {
2144     s = sset->states[i];
2145     if (NULL != s && s->accepting)
2146     {
2147       result = 0;
2148       break;
2149     }
2150   }
2151
2152   state_set_clear (sset);
2153   return result;
2154 }
2155
2156 /**
2157  * Evaluates the given 'string' against the given compiled regex
2158  *
2159  * @param a automaton
2160  * @param string string to check
2161  *
2162  * @return 0 if string matches, non 0 otherwise
2163  */
2164 int
2165 GNUNET_REGEX_eval (struct GNUNET_REGEX_Automaton *a, const char *string)
2166 {
2167   int result;
2168
2169   switch (a->type)
2170   {
2171   case DFA:
2172     result = evaluate_dfa (a, string);
2173     break;
2174   case NFA:
2175     result = evaluate_nfa (a, string);
2176     break;
2177   default:
2178     GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
2179                 "Evaluating regex failed, automaton has no type!\n");
2180     result = GNUNET_SYSERR;
2181     break;
2182   }
2183
2184   return result;
2185 }
2186
2187 /**
2188  * Get the first key for the given 'input_string'. This hashes the first x bits
2189  * of the 'input_strings'.
2190  *
2191  * @param input_string string.
2192  * @param string_len length of the 'input_string'.
2193  * @param key pointer to where to write the hash code.
2194  *
2195  * @return number of bits of 'input_string' that have been consumed
2196  *         to construct the key
2197  */
2198 unsigned int
2199 GNUNET_REGEX_get_first_key (const char *input_string, unsigned int string_len,
2200                             GNUNET_HashCode * key)
2201 {
2202   unsigned int size;
2203
2204   size = string_len < initial_bits ? string_len : initial_bits;
2205
2206   if (NULL == input_string)
2207   {
2208     GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "Given input string was NULL!\n");
2209     return 0;
2210   }
2211
2212   GNUNET_CRYPTO_hash (input_string, size, key);
2213
2214   return size;
2215 }
2216
2217 /**
2218  * Check if the given 'proof' matches the given 'key'.
2219  *
2220  * @param proof partial regex
2221  * @param key hash
2222  *
2223  * @return GNUNET_OK if the proof is valid for the given key
2224  */
2225 int
2226 GNUNET_REGEX_check_proof (const char *proof, const GNUNET_HashCode * key)
2227 {
2228   return GNUNET_OK;
2229 }
2230
2231 /**
2232  * Iterate over all edges helper function starting from state 's', calling
2233  * iterator on for each edge.
2234  *
2235  * @param s state.
2236  * @param iterator iterator function called for each edge.
2237  * @param iterator_cls closure.
2238  */
2239 static void
2240 iterate_edge (struct GNUNET_REGEX_State *s, GNUNET_REGEX_KeyIterator iterator,
2241               void *iterator_cls)
2242 {
2243   struct Transition *t;
2244   struct GNUNET_REGEX_Edge edges[s->transition_count];
2245   unsigned int num_edges;
2246
2247   if (GNUNET_YES != s->marked)
2248   {
2249     s->marked = GNUNET_YES;
2250
2251     num_edges = state_get_edges (s, edges);
2252
2253     iterator (iterator_cls, &s->hash, s->proof, s->accepting, num_edges, edges);
2254
2255     for (t = s->transitions_head; NULL != t; t = t->next)
2256       iterate_edge (t->to_state, iterator, iterator_cls);
2257   }
2258 }
2259
2260 /**
2261  * Iterate over all edges starting from start state of automaton 'a'. Calling
2262  * iterator for each edge.
2263  *
2264  * @param a automaton.
2265  * @param iterator iterator called for each edge.
2266  * @param iterator_cls closure.
2267  */
2268 void
2269 GNUNET_REGEX_iterate_all_edges (struct GNUNET_REGEX_Automaton *a,
2270                                 GNUNET_REGEX_KeyIterator iterator,
2271                                 void *iterator_cls)
2272 {
2273   struct GNUNET_REGEX_State *s;
2274
2275   for (s = a->states_head; NULL != s; s = s->next)
2276     s->marked = GNUNET_NO;
2277
2278   iterate_edge (a->start, iterator, iterator_cls);
2279 }