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