#undef PACKAGE_VERSION
#include <locale.h>
+#include <stdio.h>
#include <stdlib.h>
+#include <string.h>
#include "aop.h"
#include "tracecut.h"
};
struct tc_tracecut {
- struct tracecut_symbol *tc_symbol_list;
+ struct tc_call_symbol *symbol_list;
+
+ struct tc_tracecut *next;
};
/**
* \endcond
* \{
*/
+/* It is necessary to keep a master list of all tracecuts so that the
+ main tracecut pass has access to them. */
+static struct tc_tracecut *tracecut_list = NULL;
+
+static int
+symbol_exists (struct tc_tracecut *tc, const char *name)
+{
+ struct tc_call_symbol *symbol;
+
+ for (symbol = tc->symbol_list; symbol != NULL; symbol = symbol->next)
+ {
+ if (strcmp (name, symbol->name) == 0)
+ return 1; /* Found it. */
+ }
+
+ /* We did not find a symbol with the given name. */
+ return 0;
+}
+
+/**
+ * Add a new tracecut symbol representing a function call event. The
+ * event bound to this new symbol is triggered whenever the specified
+ * function is called.
+ *
+ * All symbols must have unique name: attempting to create a duplicate
+ * symbol will fail. It is possible to create multiple symbols for
+ * the same function.
+ *
+ * \param tc The tracecut to add a symbol to.
+ * \param name The name used to reference this symbol.
+ * \param func_name The name of the function that should trigger the
+ * new symbol's event.
+ * \param location Specifies whether the the symbol event should
+ * trigger before or after the specified function is called.
+ */
+void
+tc_add_call_symbol (struct tc_tracecut *tc, const char *name,
+ const char *func_name, enum aop_insert_location location)
+{
+ struct tc_call_symbol *symbol;
+
+ if (symbol_exists (tc, name))
+ {
+ fprintf (stderr, "(Tracecut) Ignoring duplicate symbol: %s\n", name);
+ return;
+ }
+
+ symbol = (struct tc_call_symbol *)malloc (sizeof (struct tc_call_symbol));
+ aop_assert (symbol != NULL);
+
+ symbol->name = strdup (name);
+ symbol->func_name = strdup (func_name);
+ aop_assert (symbol->name != NULL && symbol->func_name != NULL);
+
+ /* Insert this new symbol into the list of call symbols. */
+ symbol->next = tc->symbol_list;
+ tc->symbol_list = symbol;
+}
+
/**
* Create an empty tc_tracecut object. The caller is responsible for
* freeing the object using tc_free_tracecut().
tc = (struct tc_tracecut *)malloc (sizeof (struct tc_tracecut));
aop_assert (tc != NULL);
- tc->tc_symbol_list = NULL;
+ tc->symbol_list = NULL;
return tc;
}
+/* Find a tracecut object in the master list and remove it (if
+ found). */
+static void
+remove_tracecut_from_list (struct tc_tracecut *tc)
+{
+ struct tc_tracecut **iterator;
+
+ for (iterator = &tracecut_list; *iterator != NULL;
+ iterator = &((*iterator)->next))
+ {
+ if (*iterator == tc)
+ {
+ *iterator = (*iterator)->next;
+ return; /* Done. */
+ }
+ }
+}
+
/**
* Free all the memory used by a tc_object. Every call to
* tc_create_tracecut() should have a matching call to
void
tc_free_tracecut (struct tc_tracecut *tc)
{
+ remove_tracecut_from_list (tc);
+
free(tc);
}