every state machine whose params match the non-vacant params in the
event. */
struct tuple {
- /* For now, tuples are stored in a linked list. */
+ /* For now, tuples are stored in a doubly-linked list. */
struct tuple *next;
+ struct tuple *prev;
struct param_val *param_vals;
}
}
+static void
+insert_tuple (struct tracecut *tc, struct tuple *tuple)
+{
+ tuple->prev = NULL;
+ tuple->next = tc->tuple_list;
+
+ if (tc->tuple_list != NULL)
+ tc->tuple_list->prev = tuple;
+
+ tc->tuple_list = tuple;
+}
+
+
+static void
+remove_tuple (struct tracecut *tc, struct tuple *tuple)
+{
+ if (tc->tuple_list == tuple)
+ tc->tuple_list = tuple->next;
+
+ if (tuple->next != NULL)
+ tuple->next->prev = tuple->prev;
+
+ if (tuple->prev != NULL)
+ tuple->prev->next = tuple->next;
+
+ tuple->next = tuple->prev = NULL;
+}
+
+static void
+destroy_tuple (struct tuple *tuple, int num_rules)
+{
+ if (tuple != NULL)
+ {
+ int i;
+ for (i = 0; i < num_rules; i++)
+ freenstate (tuple->states[i]);
+
+ free (tuple->states);
+ free (tuple->param_vals);
+ free (tuple);
+ }
+}
+
static void
advance_state_machine (struct tracecut *tc, struct tuple *tuple, int symbol_index)
{
int i;
+ int num_trivial = 0;
for (i = 0; i < tc->num_rules; i++)
{
step (tuple->states[i], symbol_index);
if (ismatch (tuple->states[i]))
tc_report_match (tc, tuple, symbol_index);
+
+ if (isatstart (tuple->states[i]))
+ num_trivial++;
+ }
+
+ /* If every state machine is in a "trivial" state, then we don't
+ need to keep this tuple around any more. We say a state is
+ trivial when it looks exactly as it did when it was
+ initialized. */
+ if (num_trivial == tc->num_rules)
+ {
+ remove_tuple (tc, tuple);
+ destroy_tuple (tuple, tc->num_rules);
}
}
struct tuple *tuple;
int tuples_updated = 0;
- for (tuple = tc->tuple_list; tuple != NULL; tuple = tuple->next)
+ tuple = tc->tuple_list;
+ while (tuple != NULL)
{
+ /* This tuple might get destroyed by advance_state_machine, so
+ save it's next value now. */
+ struct tuple *next = tuple->next;
+
if (event_matches_tuple (event, tuple))
{
advance_state_machine (event->tracecut, tuple, event->symbol_index);
tuples_updated++;
fprintf (stderr, "Advancing existing tuple.\n");
}
+
+ tuple = next;
}
return tuples_updated;
return NULL;
}
+ tuple->next = tuple->prev = NULL;
tuple->param_vals = calloc (tc->num_params, sizeof (struct param_val));
tuple->states = calloc (tc->num_rules, sizeof (struct DState *));
if (tuple->param_vals == NULL || tuple->states == NULL)
goto nomem;
}
- /* Insert the tuple into the tracecut's tuple list. */
- tuple->next = tc->tuple_list;
- tc->tuple_list = tuple;
+ insert_tuple (tc, tuple);
return tuple;
return;
}
+ fprintf (stderr, "Event: %s\n", current_event->tracecut->symbol_names[symbol_index]);
+
current_event->symbol_index = symbol_index;
do_transition (current_event);
}