If "!=" or "ne" are used in a display filter, warn the user that the results
may be unexpected. svn path=/trunk/; revision=24232
This commit is contained in:
parent
f3747bf637
commit
9703c2bb75
|
@ -39,6 +39,7 @@ struct _dfilter_t {
|
|||
gboolean *attempted_load;
|
||||
int *interesting_fields;
|
||||
int num_interesting_fields;
|
||||
GPtrArray *deprecated;
|
||||
};
|
||||
|
||||
typedef struct {
|
||||
|
|
|
@ -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");
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
||||
|
||||
|
||||
}
|
||||
|
||||
|
|
|
@ -26,17 +26,17 @@
|
|||
* Wireshark - Network traffic analyzer
|
||||
* By Gerald Combs <gerald@wireshark.org>
|
||||
* 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 <lemonflex-tail.inc>
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
|
|
@ -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)) { \
|
||||
|
|
|
@ -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");
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
|
21
gtk/main.c
21
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
|
||||
|
|
20
gtk/main.h
20
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__ */
|
||||
|
|
Loading…
Reference in New Issue