static int num_tracecuts = -1;
+struct tuple;
+
struct tracecut {
int num_params;
int num_symbols;
const char **symbol_names;
+
+ struct tuple *tuple_list;
};
static struct tracecut *tracecut_array = NULL;
int tc_index;
struct tracecut *tracecut;
- int num_params;
struct param_val param_vals[];
};
static struct event *current_event = NULL;
+/* Each tracecut object has a list of tuples, with each tuple
+ representing one state machine that the tracecut is tracking. When
+ an event occurs, the tracecut will update the state machine for
+ every state machine whose params match the non-vacant params in the
+ event. */
+struct tuple {
+ int state;
+
+ /* For now, tuples are stored in a linked list. */
+ struct tuple *next;
+
+ struct param_val param_vals[];
+};
+
static void
fatal_tracecut_error(const char *error)
{
}
}
+void
+advance_state_machine (struct tuple *tuple, int symbol_index)
+{
+}
+
+int
+event_matches_tuple (struct event *event, struct tuple *tuple)
+{
+ int i;
+ struct tracecut *tc = event->tracecut;
+
+ for (i = 0; i < tc->num_params; i++)
+ {
+ switch (event->param_vals[i].kind)
+ {
+ case PV_VACANT:
+ continue; /* Vacant values always match. */
+ case PV_POINTER:
+ if (tuple->param_vals[i].kind != PV_POINTER
+ || event->param_vals[i].value != tuple->param_vals[i].value)
+ return 0; /* Mismatch. */
+ else
+ ; /* This param matches; keep looking. */
+ break;
+ }
+ }
+
+ /* All param matched! */
+ return 1;
+}
+
+int
+update_matching_tuples (struct event *event)
+{
+ struct tracecut *tc = event->tracecut;
+ struct tuple *tuple;
+ int tuples_updated = 0;
+
+ for (tuple = tc->tuple_list; tuple != NULL; tuple = tuple->next)
+ {
+ if (event_matches_tuple (event, tuple))
+ {
+ advance_state_machine (tuple, event->symbol_index);
+ tuples_updated++;
+ fprintf (stderr, "Advancing existing tuple.\n");
+ }
+ }
+
+ return tuples_updated;
+}
+
+struct tuple *add_tuple_for_event (struct event *event)
+{
+ struct tracecut *tc = event->tracecut;
+ struct tuple *tuple;
+ size_t tuple_size;
+
+ tuple_size = sizeof (struct tuple)
+ + tc->num_params * sizeof (struct param_val);
+ tuple = malloc (tuple_size);
+ if (tuple == NULL)
+ {
+ fatal_tracecut_error ("Out of memory");
+ return NULL;
+ }
+
+ tuple->state = 0;
+ memcpy (tuple->param_vals, event->param_vals,
+ tc->num_params * sizeof (struct param_val));
+
+ /* Insert the tuple into the tracecut's tuple list. */
+ tuple->next = tc->tuple_list;
+ tc->tuple_list = tuple;
+
+ return tuple;
+}
+
+/* An event is "complete" iff only if all its params are specified
+ (i.e., none are vacant). */
+int
+is_event_complete (struct event *event)
+{
+ int i;
+ struct tracecut *tc = event->tracecut;
+
+ for (i = 0; i < tc->num_params; i++)
+ if (event->param_vals[i].kind == PV_VACANT)
+ return 0;
+
+ return 1;
+}
+
+void
+do_transition (struct event *event)
+{
+ int tuples_updated;
+
+ tuples_updated = update_matching_tuples (event);
+
+ if (tuples_updated == 0 && is_event_complete (event))
+ {
+ struct tuple *tuple;
+
+ tuple = add_tuple_for_event (event);
+ if (tuple != NULL)
+ advance_state_machine (tuple, event->symbol_index);
+ fprintf (stderr, "Creating new tuple.\n");
+ }
+}
+
ADVICE_FUNC void
_tc_init (int _num_tracecuts)
{
memset (current_event, 0, event_size);
current_event->tc_index = tc_index;
current_event->tracecut = tc;
- current_event->num_params = tc->num_params;
}
else
{
fatal_tracecut_error ("Misplaced param value.");
return;
}
- else if (param_index < 0 || param_index >= current_event->num_params)
+ else if (param_index < 0
+ || param_index >= current_event->tracecut->num_params)
{
fatal_tracecut_error ("Out-of-bounds param value.");
}
fatal_tracecut_error ("Misplaced event transition.");
return;
}
+
+ current_event->symbol_index = symbol_index;
+ do_transition (current_event);
}