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