diff options
Diffstat (limited to 'epan/dfilter/dfilter.c')
-rw-r--r-- | epan/dfilter/dfilter.c | 77 |
1 files changed, 75 insertions, 2 deletions
diff --git a/epan/dfilter/dfilter.c b/epan/dfilter/dfilter.c index a185956b12..987653cfdc 100644 --- a/epan/dfilter/dfilter.c +++ b/epan/dfilter/dfilter.c @@ -199,6 +199,8 @@ dfilter_free(dfilter_t *df) g_free(df->interesting_fields); + g_hash_table_destroy(df->references); + if (df->deprecated) g_ptr_array_unref(df->deprecated); @@ -209,11 +211,30 @@ dfilter_free(dfilter_t *df) g_free(df); } +static void free_reference(gpointer data) +{ + /* List data is not owned by us. */ + GSList **fvalues_ptr = data; + if (*fvalues_ptr) + g_slist_free(*fvalues_ptr); + g_free(fvalues_ptr); +} + static dfwork_t* dfwork_new(void) { - return g_new0(dfwork_t, 1); + dfwork_t *dfw = g_new0(dfwork_t, 1); + + dfw->references = + g_hash_table_new_full(g_direct_hash, g_direct_equal, + NULL, free_reference); + + dfw->loaded_references = + g_hash_table_new_full(g_direct_hash, g_direct_equal, + NULL, (GDestroyNotify)dfvm_value_unref); + + return dfw; } static void @@ -231,6 +252,14 @@ dfwork_free(dfwork_t *dfw) g_hash_table_destroy(dfw->interesting_fields); } + if (dfw->references) { + g_hash_table_destroy(dfw->references); + } + + if (dfw->loaded_references) { + g_hash_table_destroy(dfw->loaded_references); + } + if (dfw->insns) { free_insns(dfw->insns); } @@ -279,6 +308,9 @@ const char *tokenstr(int token) case TOKEN_DOTDOT: return "DOTDOT"; case TOKEN_LPAREN: return "LPAREN"; case TOKEN_RPAREN: return "RPAREN"; + case TOKEN_REFERENCE: return "REFERENCE"; + case TOKEN_REF_OPEN: return "REF_OPEN"; + case TOKEN_REF_CLOSE: return "REF_CLOSE"; } return "<unknown>"; } @@ -446,6 +478,8 @@ dfilter_compile_real(const gchar *text, dfilter_t **dfp, dfilter->interesting_fields = dfw_interesting_fields(dfw, &dfilter->num_interesting_fields); dfilter->expanded_text = ws_strdup(expanded_text); + dfilter->references = dfw->references; + dfw->references = NULL; /* Initialize run-time space */ dfilter->num_registers = dfw->next_register; @@ -559,7 +593,7 @@ dfilter_log_full(const char *domain, enum ws_log_level level, return; } - char *str = dfvm_dump_str(NULL, df); + char *str = dfvm_dump_str(NULL, df, TRUE); if (G_UNLIKELY(msg == NULL)) ws_log_write_always_full(domain, level, file, line, func, "\n%s", str); else @@ -567,6 +601,45 @@ dfilter_log_full(const char *domain, enum ws_log_level level, g_free(str); } +void +dfilter_load_field_references(const dfilter_t *df, proto_tree *tree) +{ + GHashTableIter iter; + GPtrArray *finfos; + field_info *finfo; + header_field_info *hfinfo; + GSList **fvalues_ptr; + int i, len; + + if (g_hash_table_size(df->references) == 0) { + /* Nothing to do. */ + return; + } + + g_hash_table_iter_init( &iter, df->references); + while (g_hash_table_iter_next (&iter, (void **)&hfinfo, (void **)&fvalues_ptr)) { + /* If we have a previous list free it leaving the data alone */ + g_slist_free(*fvalues_ptr); + *fvalues_ptr = NULL; + + while (hfinfo) { + finfos = proto_find_finfo(tree, hfinfo->id); + if ((finfos == NULL) || (g_ptr_array_len(finfos) == 0)) { + hfinfo = hfinfo->same_name_next; + continue; + } + + len = finfos->len; + for (i = 0; i < len; i++) { + finfo = g_ptr_array_index(finfos, i); + *fvalues_ptr = g_slist_prepend(*fvalues_ptr, &finfo->value); + } + + hfinfo = hfinfo->same_name_next; + } + } +} + /* * Editor modelines - https://www.wireshark.org/tools/modelines.html * |