diff --git a/epan/dfilter/dfilter-int.h b/epan/dfilter/dfilter-int.h index f66e7c8a4c..aa3f4831c4 100644 --- a/epan/dfilter/dfilter-int.h +++ b/epan/dfilter/dfilter-int.h @@ -39,6 +39,7 @@ struct _dfilter_t { gboolean *attempted_load; int *interesting_fields; int num_interesting_fields; + GPtrArray *deprecated; }; typedef struct { diff --git a/epan/dfilter/dfilter.c b/epan/dfilter/dfilter.c index c6d0a2b3d7..23d136cf6f 100644 --- a/epan/dfilter/dfilter.c +++ b/epan/dfilter/dfilter.c @@ -88,10 +88,10 @@ dfilter_init(void) /* Trace parser */ DfilterTrace(stdout, "lemon> "); #endif - + /* Initialize the syntax-tree sub-sub-system */ sttype_init(); - + dfilter_macro_init(); } @@ -115,6 +115,7 @@ dfilter_new(void) df = g_new(dfilter_t, 1); df->insns = NULL; + df->deprecated = NULL; return df; } @@ -141,7 +142,7 @@ dfilter_free(dfilter_t *df) if (!df) return; - + if (df->insns) { free_insns(df->insns); } @@ -152,7 +153,7 @@ dfilter_free(dfilter_t *df) if (df->interesting_fields) { g_free(df->interesting_fields); } - + /* clear registers */ for (i = 0; i < df->max_registers; i++) { if (df->registers[i]) { @@ -208,7 +209,7 @@ dfwork_free(dfwork_t *dfw) if (dfw->consts) { free_insns(dfw->consts); } - + g_free(dfw); } @@ -219,13 +220,16 @@ dfilter_compile(const gchar *text, dfilter_t **dfp) dfilter_t *dfilter; dfwork_t *dfw; gboolean failure = FALSE; - + char *depr_test; + guint i; + GPtrArray *deprecated = g_ptr_array_new(); + dfilter_error_msg = NULL; if ( !( text = dfilter_macro_apply(text, 0, &dfilter_error_msg) ) ) { return FALSE; } - + dfw = dfwork_new(); df_scanner_text(text); @@ -245,6 +249,22 @@ dfilter_compile(const gchar *text, dfilter_t **dfp) break; } + /* See if the node is deprecated */ + depr_test = stnode_deprecated(df_lval); + + if (depr_test) { + for (i = 0; i < deprecated->len; i++) { + if (strcasecmp(depr_test, g_ptr_array_index(deprecated, i)) == 0) { + /* It's already in our list */ + depr_test = NULL; + } + } + } + + if (depr_test) { + g_ptr_array_add(deprecated, depr_test); + } + /* Give the token to the parser */ Dfilter(ParserObj, token, df_lval, dfw); /* We've used the stnode_t, so we don't want to free it */ @@ -254,6 +274,7 @@ dfilter_compile(const gchar *text, dfilter_t **dfp) failure = TRUE; break; } + } /* while (1) */ /* If we created an stnode_t but didn't use it, free it; the @@ -285,6 +306,7 @@ dfilter_compile(const gchar *text, dfilter_t **dfp) * it and set *dfp to NULL */ if (dfw->st_root == NULL) { *dfp = NULL; + g_ptr_array_free(deprecated, TRUE); } else { @@ -314,6 +336,9 @@ dfilter_compile(const gchar *text, dfilter_t **dfp) /* Initialize constants */ dfvm_init_const(dfilter); + /* Add any deprecated items */ + dfilter->deprecated = deprecated; + /* And give it to the user. */ *dfp = dfilter; } @@ -325,6 +350,7 @@ FAILURE: if (dfw) { dfwork_free(dfw); } + g_ptr_array_free(deprecated, TRUE); dfilter_fail("Unable to parse filter string \"%s\".", text); *dfp = NULL; return FALSE; @@ -355,9 +381,28 @@ dfilter_prime_proto_tree(const dfilter_t *df, proto_tree *tree) } } +GPtrArray * +dfilter_deprecated_tokens(dfilter_t *df) { + if (df->deprecated && df->deprecated->len > 0) { + return df->deprecated; + } + return NULL; +} void dfilter_dump(dfilter_t *df) { + guint i; + gchar *sep = ""; + dfvm_dump(stdout, df->insns); + + if (df->deprecated && df->deprecated->len) { + printf("\nDeprecated tokens: "); + for (i = 0; i < df->deprecated->len; i++) { + printf("%s\"%s\"", sep, (char *) g_ptr_array_index(df->deprecated, i)); + sep = ", "; + } + printf("\n"); + } } diff --git a/epan/dfilter/dfilter.h b/epan/dfilter/dfilter.h index 7be98cae20..7951569f23 100644 --- a/epan/dfilter/dfilter.h +++ b/epan/dfilter/dfilter.h @@ -65,7 +65,7 @@ dfilter_free(dfilter_t *df); /* dfilter_error_msg is NULL if there was no error during dfilter_compile, - * otherwise it points to a displayable error message. With MSVC and a + * otherwise it points to a displayable error message. With MSVC and a * libwireshark.dll, we need a special declaration. */ @@ -84,6 +84,9 @@ dfilter_apply(dfilter_t *df, proto_tree *tree); void dfilter_prime_proto_tree(const dfilter_t *df, proto_tree *tree); +GPtrArray * +dfilter_deprecated_tokens(dfilter_t *df); + /* Print bytecode of dfilter to stdout */ void dfilter_dump(dfilter_t *df); diff --git a/epan/dfilter/gencode.c b/epan/dfilter/gencode.c index e6ff76ac70..7f140cbc49 100644 --- a/epan/dfilter/gencode.c +++ b/epan/dfilter/gencode.c @@ -98,7 +98,7 @@ dfw_append_read_tree(dfwork_t *dfw, header_field_info *hfinfo) insn->arg1 = val1; insn->arg2 = val2; dfw_append_insn(dfw, insn); - + if (added_new_hfinfo) { while (hfinfo) { /* Record the FIELD_ID in hash of interesting fields. */ @@ -186,7 +186,7 @@ dfw_append_function(dfwork_t *dfw, stnode_t *node, dfvm_value_t **p_jmp) /* Create the new DFVM instruction */ insn = dfvm_insn_new(CALL_FUNCTION); - + val1 = dfvm_value_new(FUNCTION_DEF); val1->value.funcdef = sttype_function_funcdef(node); insn->arg1 = val1; @@ -241,7 +241,7 @@ dfw_append_function(dfwork_t *dfw, stnode_t *node, dfvm_value_t **p_jmp) dfw_append_insn(dfw, insn); g_free(jmps); - + return val2->value.numeric; } @@ -450,7 +450,7 @@ dfw_gencode(dfwork_t *dfw) int id, id1, length; dfvm_insn_t *insn, *insn1, *prev; dfvm_value_t *arg1; - + dfw->insns = g_ptr_array_new(); dfw->consts = g_ptr_array_new(); dfw->loaded_fields = g_hash_table_new(g_direct_hash, g_direct_equal); @@ -467,17 +467,17 @@ dfw_gencode(dfwork_t *dfw) if (insn->op == IF_TRUE_GOTO || insn->op == IF_FALSE_GOTO) { dfvm_opcode_t revert = (insn->op == IF_FALSE_GOTO)?IF_TRUE_GOTO:IF_FALSE_GOTO; id1 = arg1->value.numeric; - do { + do { insn1 = g_ptr_array_index(dfw->insns, id1); if (insn1->op == revert) { /* this one is always false and the branch is not taken*/ id1 = id1 +1; continue; } - else if (insn1->op == READ_TREE && prev && prev->op == READ_TREE && + else if (insn1->op == READ_TREE && prev && prev->op == READ_TREE && prev->arg2->value.numeric == insn1->arg2->value.numeric) { - /* hack if it's the same register it's the same field - * and it returns the same value + /* hack if it's the same register it's the same field + * and it returns the same value */ id1 = id1 +1; continue; @@ -508,26 +508,26 @@ dfw_gencode(dfwork_t *dfw) length = dfw->consts->len; for (id = 0; id < length; id++) { insn = g_ptr_array_index(dfw->consts, id); - if (insn->arg2 && insn->arg2->type == REGISTER && (int)insn->arg2->value.numeric < 0 ) + if (insn->arg2 && insn->arg2->type == REGISTER && (int)insn->arg2->value.numeric < 0 ) insn->arg2->value.numeric = dfw->first_constant - insn->arg2->value.numeric -1; } length = dfw->insns->len; for (id = 0; id < length; id++) { insn = g_ptr_array_index(dfw->insns, id); - if (insn->arg1 && insn->arg1->type == REGISTER && (int)insn->arg1->value.numeric < 0 ) + if (insn->arg1 && insn->arg1->type == REGISTER && (int)insn->arg1->value.numeric < 0 ) insn->arg1->value.numeric = dfw->first_constant - insn->arg1->value.numeric -1; - if (insn->arg2 && insn->arg2->type == REGISTER && (int)insn->arg2->value.numeric < 0 ) + if (insn->arg2 && insn->arg2->type == REGISTER && (int)insn->arg2->value.numeric < 0 ) insn->arg2->value.numeric = dfw->first_constant - insn->arg2->value.numeric -1; - if (insn->arg3 && insn->arg3->type == REGISTER && (int)insn->arg3->value.numeric < 0 ) + if (insn->arg3 && insn->arg3->type == REGISTER && (int)insn->arg3->value.numeric < 0 ) insn->arg3->value.numeric = dfw->first_constant - insn->arg3->value.numeric -1; - if (insn->arg4 && insn->arg4->type == REGISTER && (int)insn->arg4->value.numeric < 0 ) + if (insn->arg4 && insn->arg4->type == REGISTER && (int)insn->arg4->value.numeric < 0 ) insn->arg4->value.numeric = dfw->first_constant - insn->arg4->value.numeric -1; } - + } diff --git a/epan/dfilter/scanner.l b/epan/dfilter/scanner.l index 6af7921798..8ce6d91d60 100644 --- a/epan/dfilter/scanner.l +++ b/epan/dfilter/scanner.l @@ -26,17 +26,17 @@ * Wireshark - Network traffic analyzer * By Gerald Combs * Copyright 2001 Gerald Combs - * + * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. - * + * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. - * + * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. @@ -83,6 +83,7 @@ static int set_lval_int(int token, char *s); static int simple(int token); static gboolean str_to_gint32(char *s, gint32* pint); GString* quoted_string = NULL; +static void mark_lval_deprecated(const char *s); %} @@ -102,8 +103,14 @@ GString* quoted_string = NULL; "==" return simple(TOKEN_TEST_EQ); "eq" return simple(TOKEN_TEST_EQ); -"!=" return simple(TOKEN_TEST_NE); -"ne" return simple(TOKEN_TEST_NE); +"!=" { + mark_lval_deprecated("!="); + return simple(TOKEN_TEST_NE); +} +"ne" { + mark_lval_deprecated("ne"); + return simple(TOKEN_TEST_NE); +} ">" return simple(TOKEN_TEST_GT); "gt" return simple(TOKEN_TEST_GT); ">=" return simple(TOKEN_TEST_GE); @@ -351,7 +358,7 @@ set_lval_int(int token, char *s) if (!str_to_gint32(s, &val)) { return SCAN_FAILED; - } + } switch (token) { case TOKEN_INTEGER: @@ -417,4 +424,10 @@ str_to_gint32(char *s, gint32* pint) return TRUE; } +static void +mark_lval_deprecated(const char *s) +{ + df_lval->deprecated_token = s; +} + #include diff --git a/epan/dfilter/syntax-tree.c b/epan/dfilter/syntax-tree.c index 51bb0879f3..5a2cd920a2 100644 --- a/epan/dfilter/syntax-tree.c +++ b/epan/dfilter/syntax-tree.c @@ -92,6 +92,7 @@ stnode_new(sttype_id_t type_id, gpointer data) node = g_new(stnode_t, 1); node->magic = STNODE_MAGIC; + node->deprecated_token = NULL; if (type_id == STTYPE_UNINITIALIZED) { node->type = NULL; @@ -188,3 +189,12 @@ stnode_value(stnode_t *node) assert_magic(node, STNODE_MAGIC); return node->value; } + +char * +stnode_deprecated(stnode_t *node) +{ + if (!node) { + return NULL; + } + return node->deprecated_token; +} diff --git a/epan/dfilter/syntax-tree.h b/epan/dfilter/syntax-tree.h index 635feeda32..aa75860688 100644 --- a/epan/dfilter/syntax-tree.h +++ b/epan/dfilter/syntax-tree.h @@ -60,6 +60,7 @@ typedef struct { * set aside to time to do so. */ gpointer data; gint32 value; + char *deprecated_token; } stnode_t; /* These are the sttype_t registration function prototypes. */ @@ -103,6 +104,9 @@ stnode_data(stnode_t *node); gint32 stnode_value(stnode_t *node); +char * +stnode_deprecated(stnode_t *node); + #define assert_magic(obj, mnum) \ g_assert((obj)); \ if ((obj)->magic != (mnum)) { \ diff --git a/gtk/filter_dlg.c b/gtk/filter_dlg.c index 571c01bce3..7bc497c170 100644 --- a/gtk/filter_dlg.c +++ b/gtk/filter_dlg.c @@ -1440,7 +1440,7 @@ filter_add_expr_bt_cb(GtkWidget *w _U_, gpointer main_w_arg) * through file->open, make the latest dialog modal also so that it * takes over "control" from the other modal dialogs. Also set * the transient property of the new dialog so the user doesn't try - * to interact with the previous window when they can't. + * to interact with the previous window when they can't. * XXX: containing widget might be the Filter Toolbar */ if ( GTK_IS_WINDOW(main_w) && gtk_window_get_modal(GTK_WINDOW(main_w))) { @@ -1482,6 +1482,13 @@ colorize_filter_te_as_invalid(GtkWidget *w) color_filter_te(w, 0xFFFF, 0xAFFF, 0xAFFF); } +void +colorize_filter_te_as_deprecated(GtkWidget *w) +{ + /* light yellow */ + color_filter_te(w, 0xFFFF, 0xFFFF, 0xAFFF); +} + void colorize_filter_te_as_valid(GtkWidget *w) { @@ -1494,19 +1501,39 @@ filter_te_syntax_check_cb(GtkWidget *w) { const gchar *strval; dfilter_t *dfp; + GPtrArray *depr = NULL; + gchar *msg; + + statusbar_pop_filter_msg(); strval = gtk_entry_get_text(GTK_ENTRY(w)); /* colorize filter string entry */ if (strval && dfilter_compile(strval, &dfp)) { - if (dfp != NULL) - dfilter_free(dfp); - if (strlen(strval) == 0) + if (dfp != NULL) { + depr = dfilter_deprecated_tokens(dfp); + dfilter_free(dfp); + } + if (strlen(strval) == 0) { colorize_filter_te_as_empty(w); - else + } else if (depr) { + /* You keep using that word. I do not think it means what you think it means. */ + colorize_filter_te_as_deprecated(w); + /* + * We're being lazy and only printing the first "problem" token. + * Would it be better to print all of them? + */ + msg = g_strdup_printf("\"%s\" may have unexpected results.", + (char *) g_ptr_array_index(depr, 0)); + statusbar_push_filter_msg(msg); + g_free(msg); + } else { colorize_filter_te_as_valid(w); - } else + } + } else { colorize_filter_te_as_invalid(w); + statusbar_push_filter_msg("Invalid filter"); + } } diff --git a/gtk/main.c b/gtk/main.c index 4d7237d4d3..68ff4a8eaa 100644 --- a/gtk/main.c +++ b/gtk/main.c @@ -225,7 +225,7 @@ static GtkWidget *info_bar; static GtkWidget *packets_bar = NULL; static GtkWidget *profile_bar = NULL; static GtkWidget *welcome_pane; -static guint main_ctx, file_ctx, help_ctx; +static guint main_ctx, file_ctx, help_ctx, filter_ctx; static guint packets_ctx; static guint profile_ctx; static gchar *packets_str = NULL; @@ -1008,6 +1008,24 @@ statusbar_pop_field_msg(void) gtk_statusbar_pop(GTK_STATUSBAR(info_bar), help_ctx); } +/* + * Push a message referring to the current filter onto the statusbar. + */ +void +statusbar_push_filter_msg(const gchar *msg) +{ + gtk_statusbar_push(GTK_STATUSBAR(info_bar), filter_ctx, msg); +} + +/* + * Pop a message referring to the current filter off the statusbar. + */ +void +statusbar_pop_filter_msg(void) +{ + gtk_statusbar_pop(GTK_STATUSBAR(info_bar), filter_ctx); +} + /* * update the packets statusbar to the current values */ @@ -3358,6 +3376,7 @@ static GtkWidget *info_bar_new(void) main_ctx = gtk_statusbar_get_context_id(GTK_STATUSBAR(info_bar), "main"); file_ctx = gtk_statusbar_get_context_id(GTK_STATUSBAR(info_bar), "file"); help_ctx = gtk_statusbar_get_context_id(GTK_STATUSBAR(info_bar), "help"); + filter_ctx = gtk_statusbar_get_context_id(GTK_STATUSBAR(info_bar), "filter"); #if GTK_MAJOR_VERSION >= 2 gtk_statusbar_set_has_resize_grip(GTK_STATUSBAR(info_bar), FALSE); #endif diff --git a/gtk/main.h b/gtk/main.h index 180b4e8c18..dfb8b4568c 100644 --- a/gtk/main.h +++ b/gtk/main.h @@ -129,14 +129,14 @@ typedef enum { /** "bitwise or" this with MATCH_SELECTED_E value for copy to clipboard instead of prepare only */ #define MATCH_SELECTED_COPY_ONLY 0x200 -/** User highlited item in details window and then right clicked and selected the copy option +/** User highlited item in details window and then right clicked and selected the copy option * * @param widget parent widget * @param data parent widget */ extern void copy_selected_plist_cb(GtkWidget *w _U_, gpointer data); -/** User requested one of "Apply as Filter" or "Prepare a Filter" functions +/** User requested one of "Apply as Filter" or "Prepare a Filter" functions * by menu or context menu of protocol tree. * * @param widget parent widget @@ -289,7 +289,7 @@ extern gboolean dfilter_combo_add_recent(gchar *dftext); /** Empty out the combobox entry field */ extern void dfilter_combo_add_empty(void); -/** Write all non empty display filters (until maximum count) +/** Write all non empty display filters (until maximum count) * of the combo box GList to the user's recent file. * * @param rf the recent file @@ -308,7 +308,7 @@ extern void main_widgets_rearrange(void); /** Show or hide the main window widgets, user changed it's preferences. */ extern void main_widgets_show_or_hide(void); -/** Apply a new filter string. +/** Apply a new filter string. * Call cf_filter_packets() and add this filter string to the recent filter list. * * @param cf the capture file @@ -349,4 +349,16 @@ extern void change_configuration_profile(const gchar *profile_name); extern GtkWidget *pkt_scrollw; +/** Push a message referring to the current filter onto the statusbar. + * + * @param msg The message + */ +void +statusbar_push_filter_msg(const gchar *msg); + +/** Pop a message referring to the current filter off the statusbar. + */ +void +statusbar_pop_filter_msg(void); + #endif /* __MAIN_H__ */