aboutsummaryrefslogtreecommitdiffstats
path: root/epan/dfilter/dfilter.c
diff options
context:
space:
mode:
Diffstat (limited to 'epan/dfilter/dfilter.c')
-rw-r--r--epan/dfilter/dfilter.c352
1 files changed, 352 insertions, 0 deletions
diff --git a/epan/dfilter/dfilter.c b/epan/dfilter/dfilter.c
new file mode 100644
index 0000000000..a8d249cbf4
--- /dev/null
+++ b/epan/dfilter/dfilter.c
@@ -0,0 +1,352 @@
+/* dfilter.c
+ * Main entry point for dfilter routines
+ *
+ * $Id: dfilter.c,v 1.1 2001/02/01 20:21:18 gram Exp $
+ *
+ */
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include <stdio.h>
+
+#ifdef NEED_SNPRINTF_H
+#include "snprintf.h"
+#endif
+
+#include "dfilter-int.h"
+#include "syntax-tree.h"
+#include "gencode.h"
+#include "semcheck.h"
+#include "dfvm.h"
+
+
+/* Balanced tree of abbreviations and IDs */
+GTree *dfilter_tokens = NULL;
+
+#define DFILTER_TOKEN_ID_OFFSET 1
+
+/* Comparision function for tree insertion. A wrapper around strcmp() */
+static int g_strcmp(gconstpointer a, gconstpointer b);
+
+/* Global error message space for dfilter_compile errors */
+gchar dfilter_error_msg_buf[1024];
+gchar *dfilter_error_msg; /* NULL when no error resulted */
+
+/* In proto.c */
+extern int hf_text_only;
+
+/* From scanner.c */
+void df_scanner_text(const char *text);
+void df_scanner_file(FILE *fh);
+void df_scanner_cleanup(void);
+int df_lex(void);
+
+/* Holds the singular instance of our Lemon parser object */
+void* ParserObj = NULL;
+
+void
+dfilter_fail(char *format, ...)
+{
+ va_list args;
+
+ /* If we've already reported one error, don't overwite it */
+ if (dfilter_error_msg != NULL)
+ return;
+
+ va_start(args, format);
+
+ vsnprintf(dfilter_error_msg_buf, sizeof(dfilter_error_msg_buf),
+ format, args);
+ dfilter_error_msg = dfilter_error_msg_buf;
+ va_end(args);
+}
+
+
+/* Initialize the dfilter module */
+void
+dfilter_init(void)
+{
+ int id, num_symbols;
+ char *abbrev;
+ header_field_info *hfinfo, *same_name_hfinfo;
+
+ num_symbols = proto_registrar_n();
+
+ if (dfilter_tokens) {
+ /* XXX - needed? */
+ g_message("I expected hf_ids to be NULL\n");
+ g_tree_destroy(dfilter_tokens);
+
+ /* Make sure the hfinfo->same_name links are broken */
+ for (id = 0; id < num_symbols; id++) {
+ hfinfo = proto_registrar_get_nth(id);
+ hfinfo->same_name = NULL;
+ }
+ }
+ dfilter_tokens = g_tree_new(g_strcmp);
+
+ /* Populate the abbrev/ID GTree (header-field symbol table) */
+
+
+ for (id = 0; id < num_symbols; id++) {
+ if (id == hf_text_only) {
+ continue;
+ }
+ abbrev = proto_registrar_get_abbrev(id);
+ hfinfo = proto_registrar_get_nth(id);
+
+ g_assert(abbrev); /* Not Null */
+ g_assert(abbrev[0] != 0); /* Not empty string */
+
+ /* We allow multiple hfinfo's to be registered under the same
+ * abbreviation. This was done for X.25 */
+ same_name_hfinfo = g_tree_lookup(dfilter_tokens, abbrev);
+ if (same_name_hfinfo) {
+ /* Set the "same_name" pointer in the hfinfo, then
+ * allow the code after this if{} block to replace the
+ * old hfinfo with the new hfinfo in the GTree. Thus,
+ * we end up with a linked-list of same-named hfinfo's,
+ * with the root of the list being the hfinfo in the GTree */
+ hfinfo->same_name = same_name_hfinfo;
+
+ }
+ g_tree_insert(dfilter_tokens, abbrev, hfinfo);
+ }
+
+ if (ParserObj) {
+ g_message("I expected ParserObj to be NULL\n");
+ /* Free the Lemon Parser object */
+ DfilterFree(ParserObj, g_free);
+ }
+ /* Allocate an instance of our Lemon-based parser */
+ ParserObj = DfilterAlloc(g_malloc);
+
+ /* Initialize the syntax-tree sub-sub-system */
+ sttype_init();
+}
+
+/* Clean-up the dfilter module */
+void
+dfilter_cleanup(void)
+{
+ /* Free the abbrev/ID GTree */
+ if (dfilter_tokens) {
+ g_tree_destroy(dfilter_tokens);
+ dfilter_tokens = NULL;
+ }
+
+ /* Free the Lemon Parser object */
+ if (ParserObj) {
+ DfilterFree(ParserObj, g_free);
+ }
+
+ /* Clean up the syntax-tree sub-sub-system */
+ sttype_cleanup();
+}
+
+
+
+/* Lookup an abbreviation in our token tree, returing the ID #
+ * If the abbreviation doesn't exit, returns -1 */
+header_field_info*
+dfilter_lookup_token(char *abbrev)
+{
+ g_assert(abbrev != NULL);
+ return g_tree_lookup(dfilter_tokens, abbrev);
+}
+
+/* String comparison func for dfilter_token GTree */
+static int
+g_strcmp(gconstpointer a, gconstpointer b)
+{
+ return strcmp((const char*)a, (const char*)b);
+}
+
+static dfilter_t*
+dfilter_new(void)
+{
+ dfilter_t *df;
+
+ df = g_new(dfilter_t, 1);
+ df->insns = NULL;
+
+ return df;
+}
+
+/* Given a GPtrArray of instructions (dfvm_insn_t),
+ * free them. */
+static void
+free_insns(GPtrArray *insns)
+{
+ int i;
+ dfvm_insn_t *insn;
+
+ for (i = 0; i < insns->len; i++) {
+ insn = g_ptr_array_index(insns, i);
+ dfvm_insn_free(insn);
+ }
+}
+
+void
+dfilter_free(dfilter_t *df)
+{
+ if (df->insns) {
+ free_insns(df->insns);
+ }
+
+ g_free(df->registers);
+ g_free(df->attempted_load);
+ g_free(df);
+}
+
+
+static dfwork_t*
+dfwork_new(void)
+{
+ dfwork_t *dfw;
+
+ dfw = g_new(dfwork_t, 1);
+
+ dfw->st_root = NULL;
+ dfw->syntax_error = FALSE;
+ dfw->insns = NULL;
+ dfw->loaded_fields = NULL;
+ dfw->next_insn_id = 0;
+ dfw->next_register = 0;
+
+ return dfw;
+}
+
+static void
+dfwork_free(dfwork_t *dfw)
+{
+ if (dfw->st_root) {
+ stnode_free(dfw->st_root);
+ }
+
+ if (dfw->loaded_fields) {
+ g_hash_table_destroy(dfw->loaded_fields);
+ }
+
+ if (dfw->insns) {
+ free_insns(dfw->insns);
+ }
+
+ g_free(dfw);
+}
+
+
+gboolean
+dfilter_compile(gchar *text, dfilter_t **dfp)
+{
+ int token;
+ dfilter_t *dfilter;
+ dfwork_t *dfw;
+
+ dfilter_error_msg = NULL;
+
+ dfw = dfwork_new();
+
+ df_scanner_text(text);
+
+ while (1) {
+ df_lval = stnode_new(STTYPE_UNINITIALIZED, NULL);
+ token = df_lex();
+
+ /* Check for end-of-input */
+ if (token == 0) {
+ /* Tell the parser that we have reached the end of input */
+ Dfilter(ParserObj, 0, NULL, dfw);
+
+ /* Free the stnode_t that we just generated, since
+ * the parser doesn't know about it and won't free it
+ * for us. */
+ stnode_free(df_lval);
+ df_lval = NULL;
+ break;
+ }
+
+ /* Give the token to the parser */
+ Dfilter(ParserObj, token, df_lval, dfw);
+
+ if (dfw->syntax_error) {
+ break;
+ }
+ }
+
+ /* One last check for syntax error (after EOF) */
+ if (dfw->syntax_error) {
+ goto FAILURE;
+ }
+
+
+ /* Success, but was it an empty filter? If so, discard
+ * it and set *dfp to NULL */
+ if (dfw->st_root == NULL) {
+ *dfp = NULL;
+ }
+ else {
+
+ /* Check semantics and do necessary type conversion*/
+ if (!dfw_semcheck(dfw)) {
+ goto FAILURE;
+ }
+
+ /* Create bytecode */
+ dfw_gencode(dfw);
+
+ /* Tuck away the bytecode in the dfilter_t */
+ dfilter = dfilter_new();
+ dfilter->insns = dfw->insns;
+ dfw->insns = NULL;
+
+ /* Initialize run-time space */
+ dfilter->num_registers = dfw->next_register;
+ dfilter->registers = g_new0(GList*, dfilter->num_registers);
+ dfilter->attempted_load = g_new0(gboolean, dfilter->num_registers);
+
+ /* And give it to the user. */
+ *dfp = dfilter;
+ }
+ /* SUCCESS */
+ dfwork_free(dfw);
+
+ /* Reset flex */
+ df_scanner_cleanup();
+
+ return TRUE;
+
+FAILURE:
+ if (dfw) {
+ dfwork_free(dfw);
+ }
+ dfilter_fail("Unable to parse filter string \"%s\".", text);
+ *dfp = NULL;
+
+ /* Reset flex */
+ df_scanner_cleanup();
+ return FALSE;
+
+}
+
+
+gboolean
+dfilter_apply(dfilter_t *df, tvbuff_t *tvb, proto_tree *tree)
+{
+ return dfvm_apply(df, tvb, tree);
+}
+
+gboolean
+dfilter_apply_edt(dfilter_t *df, epan_dissect_t* edt)
+{
+ return dfvm_apply(df, edt->tvb, edt->tree);
+}
+
+
+void
+dfilter_dump(dfilter_t *df)
+{
+ dfvm_dump(stdout, df->insns);
+}