diff options
Diffstat (limited to 'epan')
-rw-r--r-- | epan/dfilter/dfilter-int.h | 2 | ||||
-rw-r--r-- | epan/dfilter/dfilter.c | 7 | ||||
-rw-r--r-- | epan/dfilter/dfunctions.c | 184 | ||||
-rw-r--r-- | epan/dfilter/dfunctions.h | 5 | ||||
-rw-r--r-- | epan/dfilter/dfvm.c | 189 | ||||
-rw-r--r-- | epan/dfilter/dfvm.h | 8 | ||||
-rw-r--r-- | epan/dfilter/gencode.c | 128 | ||||
-rw-r--r-- | epan/dfilter/grammar.lemon | 4 | ||||
-rw-r--r-- | epan/dfilter/semcheck.c | 45 | ||||
-rw-r--r-- | epan/dfilter/semcheck.h | 5 | ||||
-rw-r--r-- | epan/dfilter/sttype-function.c | 37 | ||||
-rw-r--r-- | epan/dfilter/sttype-function.h | 2 | ||||
-rw-r--r-- | epan/dfilter/sttype-test.c | 24 | ||||
-rw-r--r-- | epan/dfilter/syntax-tree.c | 30 | ||||
-rw-r--r-- | epan/dfilter/syntax-tree.h | 3 |
15 files changed, 413 insertions, 260 deletions
diff --git a/epan/dfilter/dfilter-int.h b/epan/dfilter/dfilter-int.h index 4d89277d8c..5bdd6056fc 100644 --- a/epan/dfilter/dfilter-int.h +++ b/epan/dfilter/dfilter-int.h @@ -29,6 +29,8 @@ struct epan_dfilter { char *expanded_text; GHashTable *references; char *syntax_tree_str; + /* Used to pass arguments to functions. List of Lists (list of registers). */ + GSList *function_stack; }; typedef struct { diff --git a/epan/dfilter/dfilter.c b/epan/dfilter/dfilter.c index 39adb1cedd..ba0b36a2d1 100644 --- a/epan/dfilter/dfilter.c +++ b/epan/dfilter/dfilter.c @@ -188,6 +188,8 @@ dfilter_new(GPtrArray *deprecated) if (deprecated) df->deprecated = g_ptr_array_ref(deprecated); + df->function_stack = NULL; + return df; } @@ -223,6 +225,11 @@ dfilter_free(dfilter_t *df) if (df->deprecated) g_ptr_array_unref(df->deprecated); + if (df->function_stack != NULL) { + ws_critical("Function stack list should be NULL"); + g_slist_free(df->function_stack); + } + g_free(df->registers); g_free(df->attempted_load); g_free(df->free_registers); diff --git a/epan/dfilter/dfunctions.c b/epan/dfilter/dfunctions.c index 6c05f92162..0c5234a201 100644 --- a/epan/dfilter/dfunctions.c +++ b/epan/dfilter/dfunctions.c @@ -13,6 +13,7 @@ #include "dfilter-int.h" #include "dfunctions.h" #include "sttype-pointer.h" +#include "semcheck.h" #include <string.h> @@ -25,7 +26,7 @@ /* Convert an FT_STRING using a callback function */ static gboolean -string_walk(GSList **args, guint32 arg_count, GSList **retval, gchar(*conv_func)(gchar)) +string_walk(GSList *args, guint32 arg_count, GSList **retval, gchar(*conv_func)(gchar)) { GSList *arg1; fvalue_t *arg_fvalue; @@ -33,7 +34,7 @@ string_walk(GSList **args, guint32 arg_count, GSList **retval, gchar(*conv_func) char *s, *c; ws_assert(arg_count == 1); - arg1 = args[0]; + arg1 = args->data; if (arg1 == NULL) return FALSE; @@ -59,28 +60,28 @@ string_walk(GSList **args, guint32 arg_count, GSList **retval, gchar(*conv_func) /* dfilter function: lower() */ static gboolean -df_func_lower(GSList **args, guint32 arg_count, GSList **retval) +df_func_lower(GSList *args, guint32 arg_count, GSList **retval) { return string_walk(args, arg_count, retval, g_ascii_tolower); } /* dfilter function: upper() */ static gboolean -df_func_upper(GSList **args, guint32 arg_count, GSList **retval) +df_func_upper(GSList *args, guint32 arg_count, GSList **retval) { return string_walk(args, arg_count, retval, g_ascii_toupper); } /* dfilter function: len() */ static gboolean -df_func_len(GSList **args, guint32 arg_count, GSList **retval) +df_func_len(GSList *args, guint32 arg_count, GSList **retval) { GSList *arg1; fvalue_t *arg_fvalue; fvalue_t *ft_len; ws_assert(arg_count == 1); - arg1 = args[0]; + arg1 = args->data; if (arg1 == NULL) return FALSE; @@ -97,14 +98,14 @@ df_func_len(GSList **args, guint32 arg_count, GSList **retval) /* dfilter function: count() */ static gboolean -df_func_count(GSList **args, guint32 arg_count, GSList **retval) +df_func_count(GSList *args, guint32 arg_count, GSList **retval) { GSList *arg1; fvalue_t *ft_ret; guint32 num_items; ws_assert(arg_count == 1); - arg1 = args[0]; + arg1 = args->data; if (arg1 == NULL) return FALSE; @@ -118,7 +119,7 @@ df_func_count(GSList **args, guint32 arg_count, GSList **retval) /* dfilter function: string() */ static gboolean -df_func_string(GSList **args, guint32 arg_count, GSList **retval) +df_func_string(GSList *args, guint32 arg_count, GSList **retval) { GSList *arg1; fvalue_t *arg_fvalue; @@ -126,7 +127,7 @@ df_func_string(GSList **args, guint32 arg_count, GSList **retval) char *s; ws_assert(arg_count == 1); - arg1 = args[0]; + arg1 = args->data; if (arg1 == NULL) return FALSE; @@ -187,17 +188,17 @@ df_func_string(GSList **args, guint32 arg_count, GSList **retval) } static gboolean -df_func_compare(GSList **args, guint32 arg_count, GSList **retval, +df_func_compare(GSList *args, guint32 arg_count, GSList **retval, gboolean (*fv_cmp)(const fvalue_t *a, const fvalue_t *b)) { fvalue_t *fv_ret = NULL; - GSList *l; + GSList *l1, *l2; guint32 i; - for (i = 0; i < arg_count; i++) { - for (l = args[i]; l != NULL; l = l->next) { - if (fv_ret == NULL || fv_cmp(l->data, fv_ret)) { - fv_ret = l->data; + for (l1 = args, i = 0; i < arg_count; l1 = l1->next, i++) { + for (l2 = l1->data; l2 != NULL; l2 = l2->next) { + if (fv_ret == NULL || fv_cmp(l2->data, fv_ret)) { + fv_ret = l2->data; } } } @@ -212,20 +213,20 @@ df_func_compare(GSList **args, guint32 arg_count, GSList **retval, /* Find maximum value. */ static gboolean -df_func_max(GSList **args, guint32 arg_count, GSList **retval) +df_func_max(GSList *args, guint32 arg_count, GSList **retval) { return df_func_compare(args, arg_count, retval, fvalue_gt); } /* Find minimum value. */ static gboolean -df_func_min(GSList **args, guint32 arg_count, GSList **retval) +df_func_min(GSList *args, guint32 arg_count, GSList **retval) { return df_func_compare(args, arg_count, retval, fvalue_lt); } static gboolean -df_func_abs(GSList **args, guint32 arg_count, GSList **retval) +df_func_abs(GSList *args, guint32 arg_count, GSList **retval) { GSList *arg1; fvalue_t *fv_arg, *new_fv; @@ -233,7 +234,7 @@ df_func_abs(GSList **args, guint32 arg_count, GSList **retval) GSList *result = NULL; ws_assert(arg_count == 1); - arg1 = args[0]; + arg1 = args->data; if (arg1 == NULL) return FALSE; @@ -263,8 +264,8 @@ df_func_abs(GSList **args, guint32 arg_count, GSList **retval) /* For upper() and lower() checks that the parameter passed to * it is an FT_STRING */ -static void -ul_semcheck_is_field_string(dfwork_t *dfw, const char *func_name, +static ftenum_t +ul_semcheck_is_field_string(dfwork_t *dfw, const char *func_name, ftenum_t lhs_ftype _U_, GSList *param_list, stloc_t *func_loc _U_) { header_field_info *hfinfo; @@ -277,14 +278,14 @@ ul_semcheck_is_field_string(dfwork_t *dfw, const char *func_name, if (stnode_type_id(st_node) == STTYPE_FIELD) { hfinfo = stnode_data(st_node); if (IS_FT_STRING(hfinfo->type)) { - return; + return FT_STRING; } } FAIL(dfw, st_node, "Only string type fields can be used as parameter for %s()", func_name); } -static void -ul_semcheck_is_field(dfwork_t *dfw, const char *func_name, +static ftenum_t +ul_semcheck_is_field(dfwork_t *dfw, const char *func_name, ftenum_t lhs_ftype _U_, GSList *param_list, stloc_t *func_loc _U_) { ws_assert(g_slist_length(param_list) == 1); @@ -293,13 +294,13 @@ ul_semcheck_is_field(dfwork_t *dfw, const char *func_name, dfw_resolve_unparsed(dfw, st_node); if (stnode_type_id(st_node) == STTYPE_FIELD) - return; + return FT_UINT32; FAIL(dfw, st_node, "Only fields can be used as parameter for %s()", func_name); } -static void -ul_semcheck_string_param(dfwork_t *dfw, const char *func_name, +static ftenum_t +ul_semcheck_string_param(dfwork_t *dfw, const char *func_name, ftenum_t lhs_ftype _U_, GSList *param_list, stloc_t *func_loc _U_) { header_field_info *hfinfo; @@ -344,7 +345,7 @@ ul_semcheck_string_param(dfwork_t *dfw, const char *func_name, case FT_FCWWN: case FT_IEEE_11073_SFLOAT: case FT_IEEE_11073_FLOAT: - return; + return FT_STRING; default: break; } @@ -354,109 +355,126 @@ ul_semcheck_string_param(dfwork_t *dfw, const char *func_name, } /* Check arguments are all the same type and they can be compared. */ -static void -ul_semcheck_compare(dfwork_t *dfw, const char *func_name, - GSList *param_list, stloc_t *func_loc) +static ftenum_t +ul_semcheck_compare(dfwork_t *dfw, const char *func_name, ftenum_t lhs_ftype, + GSList *param_list, stloc_t *func_loc _U_) { stnode_t *arg; ftenum_t ftype, ft_arg; GSList *l; - const header_field_info *hfinfo; fvalue_t *fv; - /* First argument must be a field not FT_NONE. */ arg = param_list->data; dfw_resolve_unparsed(dfw, arg); - ftype = sttype_pointer_ftenum(arg); + + if (stnode_type_id(arg) == STTYPE_ARITHMETIC) { + ftype = check_arithmetic_expr(dfw, arg, lhs_ftype); + } + else if (stnode_type_id(arg) == STTYPE_LITERAL && lhs_ftype != FT_NONE) { + fv = dfilter_fvalue_from_literal(dfw, lhs_ftype, arg, FALSE, NULL); + stnode_replace(arg, STTYPE_FVALUE, fv); + ftype = fvalue_type_ftenum(fv); + } + else if (stnode_type_id(arg) == STTYPE_FUNCTION) { + ftype = check_function(dfw, arg, lhs_ftype); + } + else { + ftype = sttype_pointer_ftenum(arg); + } + if (ftype == FT_NONE) { - FAIL(dfw, arg, "First argument to %s() must be a field, not %s", - func_name, stnode_type_name(arg)); + FAIL(dfw, arg, "Argument '%s' (FT_NONE) is not valid for %s()", + stnode_todisplay(arg), func_name); } - for (l = param_list; l != NULL; l = l->next) { + for (l = param_list->next; l != NULL; l = l->next) { arg = l->data; dfw_resolve_unparsed(dfw, arg); - switch (stnode_type_id(arg)) { - case STTYPE_FIELD: - case STTYPE_REFERENCE: - hfinfo = stnode_data(arg); - ft_arg = hfinfo->type; - break; - case STTYPE_LITERAL: - fv = dfilter_fvalue_from_literal(dfw, ftype, arg, FALSE, NULL); - stnode_replace(arg, STTYPE_FVALUE, fv); - ft_arg = fvalue_type_ftenum(stnode_data(arg)); - break; - case STTYPE_FVALUE: - ft_arg = fvalue_type_ftenum(stnode_data(arg)); - break; - default: - FAIL(dfw, arg, "Type %s is not valid for %s", - stnode_type_name(arg), func_name); + if (stnode_type_id(arg) == STTYPE_ARITHMETIC) { + ft_arg = check_arithmetic_expr(dfw, arg, ftype); + } + else if (stnode_type_id(arg) == STTYPE_LITERAL && ftype != FT_NONE) { + fv = dfilter_fvalue_from_literal(dfw, ftype, arg, FALSE, NULL); + stnode_replace(arg, STTYPE_FVALUE, fv); + ft_arg = fvalue_type_ftenum(fv); } + else if (stnode_type_id(arg) == STTYPE_FUNCTION) { + ft_arg = check_function(dfw, arg, ftype); + } + else { + ft_arg = sttype_pointer_ftenum(arg); + } + if (ft_arg == FT_NONE) { - dfilter_fail_throw(dfw, func_loc, - "Argument '%s' (FT_NONE) is not valid for %s()", + FAIL(dfw, arg, "Argument '%s' (FT_NONE) is not valid for %s()", stnode_todisplay(arg), func_name); } if (ftype == FT_NONE) { ftype = ft_arg; } if (ft_arg != ftype) { - dfilter_fail_throw(dfw, func_loc, - "Arguments to '%s' must have the same type", - func_name); + FAIL(dfw, arg, "Arguments to '%s' must have the same type (expected %s, got %s)", + func_name, ftype_name(ftype), ftype_name(ft_arg)); } if (!ftype_can_cmp(ft_arg)) { - dfilter_fail_throw(dfw, func_loc, - "Argument '%s' to '%s' cannot be ordered", + FAIL(dfw, arg, "Argument '%s' to '%s' cannot be ordered", stnode_todisplay(arg), func_name); } } + return ftype; } -static void -ul_semcheck_absolute_value(dfwork_t *dfw, const char *func_name, +static ftenum_t +ul_semcheck_absolute_value(dfwork_t *dfw, const char *func_name, ftenum_t lhs_ftype, GSList *param_list, stloc_t *func_loc _U_) { ws_assert(g_slist_length(param_list) == 1); stnode_t *st_node; ftenum_t ftype; - const header_field_info *hfinfo; + fvalue_t *fv; st_node = param_list->data; dfw_resolve_unparsed(dfw, st_node); - switch (stnode_type_id(st_node)) { - case STTYPE_FIELD: - case STTYPE_REFERENCE: - hfinfo = stnode_data(st_node); - ftype = hfinfo->type; - break; - default: - FAIL(dfw, st_node, "Type %s is not valid for %s", - stnode_type_name(st_node), func_name); + if (stnode_type_id(st_node) == STTYPE_ARITHMETIC) { + ftype = check_arithmetic_expr(dfw, st_node, lhs_ftype); + } + else if (stnode_type_id(st_node) == STTYPE_LITERAL && lhs_ftype != FT_NONE) { + fv = dfilter_fvalue_from_literal(dfw, lhs_ftype, st_node, FALSE, NULL); + stnode_replace(st_node, STTYPE_FVALUE, fv); + ftype = fvalue_type_ftenum(fv); + } + else if (stnode_type_id(st_node) == STTYPE_FUNCTION) { + ftype = check_function(dfw, st_node, lhs_ftype); + } + else { + ftype = sttype_pointer_ftenum(st_node); } + if (ftype == FT_NONE) { + FAIL(dfw, st_node, "Type %s is not valid for %s", + stnode_type_name(st_node), func_name); + } if (!ftype_can_is_negative(ftype)) { FAIL(dfw, st_node, "'%s' is not a valid argument to '%s'()", stnode_todisplay(st_node), func_name); } + return ftype; } /* The table of all display-filter functions */ static df_func_def_t df_functions[] = { - { "lower", df_func_lower, FT_STRING, 1, 1, ul_semcheck_is_field_string }, - { "upper", df_func_upper, FT_STRING, 1, 1, ul_semcheck_is_field_string }, - { "len", df_func_len, FT_UINT32, 1, 1, ul_semcheck_is_field }, - { "count", df_func_count, FT_UINT32, 1, 1, ul_semcheck_is_field }, - { "string", df_func_string, FT_STRING, 1, 1, ul_semcheck_string_param }, - { "max", df_func_max, 0, 1, 0, ul_semcheck_compare }, - { "min", df_func_min, 0, 1, 0, ul_semcheck_compare }, - { "abs", df_func_abs, 0, 1, 1, ul_semcheck_absolute_value }, - { NULL, NULL, FT_NONE, 0, 0, NULL } + { "lower", df_func_lower, 1, 1, ul_semcheck_is_field_string }, + { "upper", df_func_upper, 1, 1, ul_semcheck_is_field_string }, + { "len", df_func_len, 1, 1, ul_semcheck_is_field }, + { "count", df_func_count, 1, 1, ul_semcheck_is_field }, + { "string", df_func_string, 1, 1, ul_semcheck_string_param }, + { "max", df_func_max, 1, 0, ul_semcheck_compare }, + { "min", df_func_min, 1, 0, ul_semcheck_compare }, + { "abs", df_func_abs, 1, 1, ul_semcheck_absolute_value }, + { NULL, NULL, 0, 0, NULL } }; /* Lookup a display filter function record by name */ diff --git a/epan/dfilter/dfunctions.h b/epan/dfilter/dfunctions.h index 60cae3a33e..71157ea00e 100644 --- a/epan/dfilter/dfunctions.h +++ b/epan/dfilter/dfunctions.h @@ -17,10 +17,10 @@ /* Functions take any number of arguments and return 1. */ /* The run-time logic of the dfilter function */ -typedef gboolean (*DFFuncType)(GSList **arg_list, guint32 arg_count, GSList **retval); +typedef gboolean (*DFFuncType)(GSList *arg_list, guint32 arg_count, GSList **retval); /* The semantic check for the dfilter function */ -typedef void (*DFSemCheckType)(dfwork_t *dfw, const char *func_name, +typedef ftenum_t (*DFSemCheckType)(dfwork_t *dfw, const char *func_name, ftenum_t lhs_ftype, GSList *param_list, stloc_t *func_loc); /* This is a "function definition" record, holding everything @@ -28,7 +28,6 @@ typedef void (*DFSemCheckType)(dfwork_t *dfw, const char *func_name, typedef struct { const char *name; DFFuncType function; - ftenum_t retval_ftype; /* 0 means return value is the same as input argument(s) */ guint min_nargs; guint max_nargs; /* 0 for no limit */ DFSemCheckType semcheck_param_function; diff --git a/epan/dfilter/dfvm.c b/epan/dfilter/dfvm.c index 5e0ef1521c..17c611711e 100644 --- a/epan/dfilter/dfvm.c +++ b/epan/dfilter/dfvm.c @@ -17,6 +17,46 @@ static void debug_register(GSList *reg, guint32 num); +const char * +dfvm_opcode_tostr(dfvm_opcode_t code) +{ + switch (code) { + case IF_TRUE_GOTO: return "IF_TRUE_GOTO"; + case IF_FALSE_GOTO: return "IF_FALSE_GOTO"; + case CHECK_EXISTS: return "CHECK_EXISTS"; + case NOT: return "NOT"; + case RETURN: return "RETURN"; + case READ_TREE: return "READ_TREE"; + case READ_REFERENCE: return "READ_REFERENCE"; + case PUT_FVALUE: return "PUT_FVALUE"; + case ALL_EQ: return "ALL_EQ"; + case ANY_EQ: return "ANY_EQ"; + case ALL_NE: return "ALL_NE"; + case ANY_NE: return "ANY_NE"; + case ANY_GT: return "ANY_GT"; + case ANY_GE: return "ANY_GE"; + case ANY_LT: return "ANY_LT"; + case ANY_LE: return "ANY_LE"; + case ANY_ZERO: return "ANY_ZERO"; + case ALL_ZERO: return "ALL_ZERO"; + case ANY_CONTAINS: return "ANY_CONTAINS"; + case ANY_MATCHES: return "ANY_MATCHES"; + case MK_RANGE: return "MK_RANGE"; + case MK_BITWISE_AND: return "MK_BITWISE_AND"; + case MK_MINUS: return "MK_MINUS"; + case DFVM_ADD: return "DFVM_ADD"; + case DFVM_SUBTRACT: return "DFVM_SUBTRACT"; + case DFVM_MULTIPLY: return "DFVM_MULTIPLY"; + case DFVM_DIVIDE: return "DFVM_DIVIDE"; + case DFVM_MODULO: return "DFMV_MODULO"; + case CALL_FUNCTION: return "CALL_FUNCTION"; + case STACK_PUSH: return "STACK_PUSH"; + case STACK_POP: return "STACK_POP"; + case ANY_IN_RANGE: return "ANY_IN_RANGE"; + } + return "(fix-opcode-string)"; +} + dfvm_insn_t* dfvm_insn_new(dfvm_opcode_t op) { @@ -148,6 +188,14 @@ dfvm_value_new_pcre(ws_regex_t *re) return v; } +dfvm_value_t* +dfvm_value_new_guint(guint num) +{ + dfvm_value_t *v = dfvm_value_new(INTEGER); + v->value.numeric = num; + return v; +} + char * dfvm_value_tostr(dfvm_value_t *v) { @@ -187,6 +235,23 @@ dfvm_value_tostr(dfvm_value_t *v) return s; } +static GSList * +dump_str_stack_push(GSList *stack, const char *str) +{ + return g_slist_prepend(stack, g_strdup(str)); +} + +static GSList * +dump_str_stack_pop(GSList *stack) +{ + char *str; + + str = stack->data; + stack = g_slist_delete_link(stack, stack); + g_free(str); + return stack; +} + char * dfvm_dump_str(wmem_allocator_t *alloc, dfilter_t *df, gboolean print_references) { @@ -198,6 +263,8 @@ dfvm_dump_str(wmem_allocator_t *alloc, dfilter_t *df, gboolean print_references) GHashTableIter ref_iter; gpointer key, value; char *str; + GSList *stack_print = NULL, *l; + guint i; buf = wmem_strbuf_new(alloc, NULL); @@ -240,16 +307,27 @@ dfvm_dump_str(wmem_allocator_t *alloc, dfilter_t *df, gboolean print_references) case CALL_FUNCTION: wmem_strbuf_append_printf(buf, "%05d CALL_FUNCTION\t%s(", id, arg1_str); - if (arg3_str) { - wmem_strbuf_append_printf(buf, "%s", arg3_str); - } - for (guint32 i = 1; i <= arg4->value.numeric; i++) { - wmem_strbuf_append_printf(buf, ", reg#%"G_GUINT32_FORMAT, - arg3->value.numeric + i); + for (l = stack_print, i = 0; i < arg3->value.numeric; i++, l = l->next) { + if (l != stack_print) { + wmem_strbuf_append(buf, ", "); + } + wmem_strbuf_append(buf, l->data); } wmem_strbuf_append_printf(buf, ") -> %s\n", arg2_str); break; + case STACK_PUSH: + wmem_strbuf_append_printf(buf, "%05d STACK_PUSH\t%s\n", id, arg1_str); + stack_print = dump_str_stack_push(stack_print, arg1_str); + break; + + case STACK_POP: + wmem_strbuf_append_printf(buf, "%05d STACK_POP\t%s\n", id, arg1_str); + for (i = 0; i < arg1->value.numeric; i ++) { + stack_print = dump_str_stack_pop(stack_print); + } + break; + case MK_RANGE: wmem_strbuf_append_printf(buf, "%05d MK_RANGE\t\t%s[%s] -> %s\n", id, arg1_str, arg3_str, arg2_str); @@ -639,13 +717,8 @@ any_matches(dfilter_t *df, dfvm_value_t *arg1, dfvm_value_t *arg2) } static gboolean -any_in_range(dfilter_t *df, dfvm_value_t *arg1, - dfvm_value_t *arg_low, dfvm_value_t *arg_high) +any_in_range_internal(GSList *list1, fvalue_t *low, fvalue_t *high) { - GSList *list1 = df->registers[arg1->value.numeric]; - fvalue_t *low = arg_low->value.fvalue; - fvalue_t *high = arg_high->value.fvalue; - while (list1) { if (fvalue_ge(list1->data, low) && fvalue_le(list1->data, high)) { @@ -656,6 +729,39 @@ any_in_range(dfilter_t *df, dfvm_value_t *arg1, return FALSE; } +static gboolean +any_in_range(dfilter_t *df, dfvm_value_t *arg1, + dfvm_value_t *arg_low, dfvm_value_t *arg_high) +{ + GSList *list1 = df->registers[arg1->value.numeric]; + GSList *_low, *_high; + fvalue_t *low, *high; + + if (arg_low->type == REGISTER) { + _low = df->registers[arg_low->value.numeric]; + ws_assert(g_slist_length(_low) == 1); + low = _low->data; + } + else if (arg_low->type == FVALUE) { + low = arg_low->value.fvalue; + } + else { + ws_assert_not_reached(); + } + if (arg_high->type == REGISTER) { + _high = df->registers[arg_high->value.numeric]; + ws_assert(g_slist_length(_high) == 1); + high = _high->data; + } + else if (arg_high->type == FVALUE) { + high = arg_high->value.fvalue; + } + else { + ws_assert_not_reached(); + } + return any_in_range_internal(list1, low, high); +} + /* Clear registers that were populated during evaluation. * If we created the values, then these will be freed as well. */ static void @@ -716,19 +822,18 @@ mk_range(dfilter_t *df, dfvm_value_t *from_arg, dfvm_value_t *to_arg, */ static gboolean call_function(dfilter_t *df, dfvm_value_t *arg1, dfvm_value_t *arg2, - dfvm_value_t *arg3, dfvm_value_t *arg4) + dfvm_value_t *arg3) { df_func_def_t *funcdef; GSList *retval = NULL; gboolean accum; - guint32 reg_return, reg_first_arg, more_args_count; + guint32 reg_return, arg_count; funcdef = arg1->value.funcdef; reg_return = arg2->value.numeric; - reg_first_arg = arg3->value.numeric; - more_args_count = arg4->value.numeric; + arg_count = arg3->value.numeric; - accum = funcdef->function(&df->registers[reg_first_arg], 1 + more_args_count, &retval); + accum = funcdef->function(df->function_stack, arg_count, &retval); /* Write return registers. */ df->registers[reg_return] = retval; @@ -892,6 +997,42 @@ put_fvalue(dfilter_t *df, dfvm_value_t *arg1, dfvm_value_t *to_arg) df->free_registers[to_arg->value.numeric] = NULL; } +static void +stack_push(dfilter_t *df, dfvm_value_t *arg1) +{ + GSList *arg; + + if (arg1->type == FVALUE) { + arg = g_slist_prepend(NULL, arg1->value.fvalue); + } + else if (arg1->type == REGISTER) { + arg = g_slist_copy(df->registers[arg1->value.numeric]); + } + else { + ws_assert_not_reached(); + } + df->function_stack = g_slist_prepend(df->function_stack, arg); +} + +static void +stack_pop(dfilter_t *df, dfvm_value_t *arg1) +{ + guint count; + GSList *reg; + + count = arg1->value.numeric; + + for (guint i = 0; i < count; i++) { + /* Free top of stack and register contained there. The register + * contentes are not owned by us. */ + reg = df->function_stack->data; + /* Free the list but not the data it contains. */ + g_slist_free(reg); + /* remove top of stack */ + df->function_stack = g_slist_delete_link(df->function_stack, df->function_stack); + } +} + gboolean dfvm_apply(dfilter_t *df, proto_tree *tree) { @@ -901,7 +1042,6 @@ dfvm_apply(dfilter_t *df, proto_tree *tree) dfvm_value_t *arg1; dfvm_value_t *arg2; dfvm_value_t *arg3 = NULL; - dfvm_value_t *arg4 = NULL; header_field_info *hfinfo; ws_assert(tree); @@ -915,7 +1055,8 @@ dfvm_apply(dfilter_t *df, proto_tree *tree) arg1 = insn->arg1; arg2 = insn->arg2; arg3 = insn->arg3; - arg4 = insn->arg4; + + ws_noisy("ID: %d; OP: %s", id, dfvm_opcode_tostr(insn->op)); switch (insn->op) { case CHECK_EXISTS: @@ -945,7 +1086,15 @@ dfvm_apply(dfilter_t *df, proto_tree *tree) break; case CALL_FUNCTION: - accum = call_function(df, arg1, arg2, arg3, arg4); + accum = call_function(df, arg1, arg2, arg3); + break; + + case STACK_PUSH: + stack_push(df, arg1); + break; + + case STACK_POP: + stack_pop(df, arg1); break; case MK_RANGE: diff --git a/epan/dfilter/dfvm.h b/epan/dfilter/dfvm.h index 565e5568fd..c29608ed50 100644 --- a/epan/dfilter/dfvm.h +++ b/epan/dfilter/dfvm.h @@ -76,10 +76,15 @@ typedef enum { DFVM_DIVIDE, DFVM_MODULO, CALL_FUNCTION, + STACK_PUSH, + STACK_POP, ANY_IN_RANGE } dfvm_opcode_t; +const char * +dfvm_opcode_tostr(dfvm_opcode_t code); + typedef struct { int id; dfvm_opcode_t op; @@ -122,6 +127,9 @@ dfvm_value_new_funcdef(df_func_def_t *funcdef); dfvm_value_t* dfvm_value_new_pcre(ws_regex_t *re); +dfvm_value_t* +dfvm_value_new_guint(guint num); + void dfvm_dump(FILE *f, dfilter_t *df); diff --git a/epan/dfilter/gencode.c b/epan/dfilter/gencode.c index 7a4470e750..6b6c7a6821 100644 --- a/epan/dfilter/gencode.c +++ b/epan/dfilter/gencode.c @@ -36,9 +36,44 @@ dfw_append_insn(dfwork_t *dfw, dfvm_insn_t *insn) g_ptr_array_add(dfw->insns, insn); } +static void +dfw_append_stack_push(dfwork_t *dfw, dfvm_value_t *arg1) +{ + dfvm_insn_t *insn; + + insn = dfvm_insn_new(STACK_PUSH); + insn->arg1 = dfvm_value_ref(arg1); + dfw_append_insn(dfw, insn); +} + +static void +dfw_append_stack_pop(dfwork_t *dfw, guint count) +{ + dfvm_insn_t *insn; + dfvm_value_t *val; + + insn = dfvm_insn_new(STACK_POP); + val = dfvm_value_new_guint(count); + insn->arg1 = dfvm_value_ref(val); + dfw_append_insn(dfw, insn); +} + +static dfvm_value_t * +dfw_append_jump(dfwork_t *dfw) +{ + dfvm_insn_t *insn; + dfvm_value_t *jmp; + + insn = dfvm_insn_new(IF_FALSE_GOTO); + jmp = dfvm_value_new(INSN_NUMBER); + insn->arg1 = dfvm_value_ref(jmp); + dfw_append_insn(dfw, insn); + return jmp; +} + /* returns register number */ static dfvm_value_t * -dfw_append_read_tree(dfwork_t *dfw, header_field_info *hfinfo, gboolean reuse_register) +dfw_append_read_tree(dfwork_t *dfw, header_field_info *hfinfo) { dfvm_insn_t *insn; int reg = -1; @@ -56,19 +91,13 @@ dfw_append_read_tree(dfwork_t *dfw, header_field_info *hfinfo, gboolean reuse_re * can re-use registers. */ loaded_key = g_hash_table_lookup(dfw->loaded_fields, hfinfo); if (loaded_key != NULL) { - /* Already loaded at least once. */ - if (reuse_register) { - /* - * Reg's are stored in has as reg+1, so - * that the non-existence of a hfinfo in - * the hash, or 0, can be differentiated from - * a hfinfo being loaded into register #0. - */ - reg = GPOINTER_TO_INT(loaded_key) - 1; - } - else { - reg = dfw->next_register++; - } + /* + * Reg's are stored in has as reg+1, so + * that the non-existence of a hfinfo in + * the hash, or 0, can be differentiated from + * a hfinfo being loaded into register #0. + */ + reg = GPOINTER_TO_INT(loaded_key) - 1; } else { reg = dfw->next_register++; @@ -169,7 +198,7 @@ dfw_append_mk_range(dfwork_t *dfw, stnode_t *node, GSList **jumps_ptr) } /* returns register number */ -static dfvm_value_t * +_U_ static dfvm_value_t * dfw_append_put_fvalue(dfwork_t *dfw, fvalue_t *fv) { dfvm_insn_t *insn; @@ -190,11 +219,11 @@ static dfvm_value_t * dfw_append_function(dfwork_t *dfw, stnode_t *node, GSList **jumps_ptr) { GSList *params; + GSList *params_jumps = NULL; dfvm_value_t *jmp; dfvm_insn_t *insn; - dfvm_value_t *reg_val, *val1, *val3, *val4, *val_arg; - guint32 reg_first, more_args_count; - stnode_t *arg; + dfvm_value_t *reg_val, *val1, *val3, *val_arg; + guint count; /* Create the new DFVM instruction */ insn = dfvm_insn_new(CALL_FUNCTION); @@ -206,40 +235,22 @@ dfw_append_function(dfwork_t *dfw, stnode_t *node, GSList **jumps_ptr) /* Create input arguments */ params = sttype_function_params(node); ws_assert(params); - val3 = dfw_append_read_tree(dfw, stnode_steal_data(params->data), FALSE); - insn->arg3 = dfvm_value_ref(val3); - - params = params->next; - reg_first = val3->value.numeric; - more_args_count = 0; + count = 0; while (params) { - arg = params->data; - switch (stnode_type_id(arg)) { - case STTYPE_FVALUE: - dfw_append_put_fvalue(dfw, stnode_steal_data(arg)); - break; - case STTYPE_FIELD: - /* We cannot reuse registers here because the function calling - * convention is to pass input arguments sequentially. */ - val_arg = dfw_append_read_tree(dfw, stnode_data(arg), FALSE); - /* Assert the registers are numbered sequentially. */ - ws_assert(val_arg->value.numeric == reg_first + more_args_count + 1); - break; - default: - ws_assert_not_reached(); - } - more_args_count++; + val_arg = gen_entity(dfw, params->data, ¶ms_jumps); + /* If a parameter fails to generate jump here. + * Note: stack_push NULL register is valid. */ + g_slist_foreach(params_jumps, fixup_jumps, dfw); + g_slist_free(params_jumps); + params_jumps = NULL; + dfw_append_stack_push(dfw, val_arg); + count++; params = params->next; } - val4 = dfvm_value_new(INTEGER); - val4->value.numeric = more_args_count; - insn->arg4 = dfvm_value_ref(val4); - + val3 = dfvm_value_new_guint(count); + insn->arg3 = dfvm_value_ref(val3); dfw_append_insn(dfw, insn); - - /* There is no jump if READ_TREE fails for a function parameter. It - * is up to the function to return TRUE/FALSE for any combination - * of (missing or not) arguments. */ + dfw_append_stack_pop(dfw, count); /* We need another instruction to jump to another exit * place, if the call() of our function failed for some reaosn */ @@ -422,30 +433,19 @@ static dfvm_value_t * gen_entity(dfwork_t *dfw, stnode_t *st_arg, GSList **jumps_ptr) { sttype_id_t e_type; - dfvm_insn_t *insn; - dfvm_value_t *val, *jmp; + dfvm_value_t *val; header_field_info *hfinfo; e_type = stnode_type_id(st_arg); if (e_type == STTYPE_FIELD) { hfinfo = stnode_data(st_arg); - val = dfw_append_read_tree(dfw, hfinfo, TRUE); - - insn = dfvm_insn_new(IF_FALSE_GOTO); - jmp = dfvm_value_new(INSN_NUMBER); - insn->arg1 = dfvm_value_ref(jmp); - dfw_append_insn(dfw, insn); - *jumps_ptr = g_slist_prepend(*jumps_ptr, jmp); + val = dfw_append_read_tree(dfw, hfinfo); + *jumps_ptr = g_slist_prepend(*jumps_ptr, dfw_append_jump(dfw)); } else if (e_type == STTYPE_REFERENCE) { hfinfo = stnode_data(st_arg); val = dfw_append_read_reference(dfw, hfinfo); - - insn = dfvm_insn_new(IF_FALSE_GOTO); - jmp = dfvm_value_new(INSN_NUMBER); - insn->arg1 = dfvm_value_ref(jmp); - dfw_append_insn(dfw, insn); - *jumps_ptr = g_slist_prepend(*jumps_ptr, jmp); + *jumps_ptr = g_slist_prepend(*jumps_ptr, dfw_append_jump(dfw)); } else if (e_type == STTYPE_FVALUE) { val = dfvm_value_new_fvalue(stnode_steal_data(st_arg)); @@ -463,7 +463,7 @@ gen_entity(dfwork_t *dfw, stnode_t *st_arg, GSList **jumps_ptr) val = gen_arithmetic(dfw, st_arg, jumps_ptr); } else { - /* printf("sttype_id is %u\n", (unsigned)e_type); */ + WS_DEBUG_HERE("sttype is %s", stnode_type_name(st_arg)); ws_assert_not_reached(); } return val; diff --git a/epan/dfilter/grammar.lemon b/epan/dfilter/grammar.lemon index c13b640c55..2cd63af9f5 100644 --- a/epan/dfilter/grammar.lemon +++ b/epan/dfilter/grammar.lemon @@ -343,12 +343,12 @@ function(F) ::= UNPARSED(U) LPAREN RPAREN. F = new_function(dfw, U); } -function_params(P) ::= entity(E). +function_params(P) ::= arithmetic_expr(E). { P = g_slist_append(NULL, E); } -function_params(P) ::= function_params(L) COMMA entity(E). +function_params(P) ::= function_params(L) COMMA arithmetic_expr(E). { P = g_slist_append(L, E); } diff --git a/epan/dfilter/semcheck.c b/epan/dfilter/semcheck.c index 838d2d847c..df984fcdeb 100644 --- a/epan/dfilter/semcheck.c +++ b/epan/dfilter/semcheck.c @@ -38,13 +38,6 @@ static void semcheck(dfwork_t *dfw, stnode_t *st_node); -static void -check_function(dfwork_t *dfw, stnode_t *st_node); - -static -ftenum_t -check_arithmetic_expr(dfwork_t *dfw, stnode_t *st_node, ftenum_t lhs_ftype); - static fvalue_t * mk_fvalue_from_val_string(dfwork_t *dfw, header_field_info *hfinfo, const char *s); @@ -552,7 +545,7 @@ check_exists(dfwork_t *dfw, stnode_t *st_arg1) } static void -check_drange_sanity(dfwork_t *dfw, stnode_t *st) +check_drange_sanity(dfwork_t *dfw, stnode_t *st, ftenum_t lhs_ftype) { stnode_t *entity1; header_field_info *hfinfo1; @@ -573,8 +566,7 @@ check_drange_sanity(dfwork_t *dfw, stnode_t *st) hfinfo1->abbrev, ftype_pretty_name(ftype1)); } } else if (stnode_type_id(entity1) == STTYPE_FUNCTION) { - check_function(dfw, entity1); - ftype1 = sttype_function_retval_ftype(entity1); + ftype1 = check_function(dfw, entity1, lhs_ftype); if (!ftype_can_slice(ftype1)) { FAIL(dfw, entity1, "Return value of function \"%s\" is a %s and cannot be converted into a sequence of bytes.", @@ -582,7 +574,7 @@ check_drange_sanity(dfwork_t *dfw, stnode_t *st) } } else if (stnode_type_id(entity1) == STTYPE_RANGE) { /* Should this be rejected instead? */ - check_drange_sanity(dfw, entity1); + check_drange_sanity(dfw, entity1, lhs_ftype); } else { FAIL(dfw, entity1, "Range is not supported for entity %s", stnode_todisplay(entity1)); @@ -604,8 +596,8 @@ convert_to_bytes(stnode_t *arg) sttype_range_set1(arg, entity1, rn); } -static void -check_function(dfwork_t *dfw, stnode_t *st_node) +ftenum_t +check_function(dfwork_t *dfw, stnode_t *st_node, ftenum_t lhs_ftype) { df_func_def_t *funcdef; GSList *params; @@ -625,7 +617,7 @@ check_function(dfwork_t *dfw, stnode_t *st_node) funcdef->name, funcdef->max_nargs); } - funcdef->semcheck_param_function(dfw, funcdef->name, params, + return funcdef->semcheck_param_function(dfw, funcdef->name, lhs_ftype, params, stnode_location(st_node)); } @@ -718,7 +710,7 @@ again: stnode_replace(st_arg2, STTYPE_FVALUE, fvalue); } else if (type2 == STTYPE_RANGE) { - check_drange_sanity(dfw, st_arg2); + check_drange_sanity(dfw, st_arg2, ftype1); if (!is_bytes_type(ftype1)) { if (!ftype_can_slice(ftype1)) { FAIL(dfw, st_arg1, "\"%s\" is a %s and cannot be converted into a sequence of bytes.", @@ -731,8 +723,7 @@ again: } } else if (type2 == STTYPE_FUNCTION) { - check_function(dfw, st_arg2); - ftype2 = sttype_function_retval_ftype(st_arg2); + ftype2 = check_function(dfw, st_arg2, ftype1); if (!compatible_ftypes(ftype1, ftype2)) { FAIL(dfw, st_arg2, "%s (type=%s) and return value of %s() (type=%s) are not of compatible types.", @@ -780,7 +771,7 @@ check_relation_LHS_RANGE(dfwork_t *dfw, test_op_t st_op, LOG_NODE(st_node); - check_drange_sanity(dfw, st_arg1); + check_drange_sanity(dfw, st_arg1, FT_NONE); again: type2 = stnode_type_id(st_arg2); @@ -821,11 +812,10 @@ again: stnode_replace(st_arg2, STTYPE_FVALUE, fvalue); } else if (type2 == STTYPE_RANGE) { - check_drange_sanity(dfw, st_arg2); + check_drange_sanity(dfw, st_arg2, FT_BYTES); } else if (type2 == STTYPE_FUNCTION) { - check_function(dfw, st_arg2); - ftype2 = sttype_function_retval_ftype(st_arg2); + ftype2 = check_function(dfw, st_arg2, FT_BYTES); if (!is_bytes_type(ftype2)) { if (!ftype_can_slice(ftype2)) { @@ -874,8 +864,7 @@ check_relation_LHS_FUNCTION(dfwork_t *dfw, test_op_t st_op, LOG_NODE(st_node); - check_function(dfw, st_arg1); - ftype1 = sttype_function_retval_ftype(st_arg1); + ftype1 = check_function(dfw, st_arg1, FT_NONE); if (!can_func(ftype1)) { FAIL(dfw, st_arg1, "Function %s (type=%s) cannot participate in %s comparison.", @@ -922,7 +911,7 @@ again: stnode_replace(st_arg2, STTYPE_FVALUE, fvalue); } else if (type2 == STTYPE_RANGE) { - check_drange_sanity(dfw, st_arg2); + check_drange_sanity(dfw, st_arg2, ftype1); if (!is_bytes_type(ftype1)) { if (!ftype_can_slice(ftype1)) { FAIL(dfw, st_arg1, "Function \"%s\" is a %s and cannot be converted into a sequence of bytes.", @@ -935,8 +924,7 @@ again: } } else if (type2 == STTYPE_FUNCTION) { - check_function(dfw, st_arg2); - ftype2 = sttype_function_retval_ftype(st_arg2); + ftype2 = check_function(dfw, st_arg2, ftype1); if (!compatible_ftypes(ftype1, ftype2)) { FAIL(dfw, st_arg2, "Return values of function %s (type=%s) and function %s (type=%s) are not of compatible types.", @@ -1241,11 +1229,10 @@ check_arithmetic_entity(dfwork_t *dfw, stnode_t *st_arg, ftenum_t lhs_ftype) ftype = hfinfo->type; } else if (type == STTYPE_FUNCTION) { - check_function(dfw, st_arg); - ftype = sttype_function_retval_ftype(st_arg); + ftype = check_function(dfw, st_arg, lhs_ftype); } else if (type == STTYPE_RANGE) { - check_drange_sanity(dfw, st_arg); + check_drange_sanity(dfw, st_arg, lhs_ftype); ftype = FT_BYTES; } diff --git a/epan/dfilter/semcheck.h b/epan/dfilter/semcheck.h index 8c29281982..733bd2ed0d 100644 --- a/epan/dfilter/semcheck.h +++ b/epan/dfilter/semcheck.h @@ -14,5 +14,10 @@ gboolean dfw_semcheck(dfwork_t *dfw); +ftenum_t +check_arithmetic_expr(dfwork_t *dfw, stnode_t *st_node, ftenum_t lhs_ftype); + +ftenum_t +check_function(dfwork_t *dfw, stnode_t *st_node, ftenum_t lhs_ftype); #endif diff --git a/epan/dfilter/sttype-function.c b/epan/dfilter/sttype-function.c index bc1c6021f2..fd0ed657b0 100644 --- a/epan/dfilter/sttype-function.c +++ b/epan/dfilter/sttype-function.c @@ -60,14 +60,20 @@ function_tostr(const void *data, gboolean pretty) ws_assert(def); - g_string_printf(repr, "%s: ", def->name); - while (params != NULL) { - ws_assert(params->data); - g_string_append(repr, stnode_tostr(params->data, pretty)); - params = params->next; - if (params != NULL) { - g_string_append(repr, ", "); + if (pretty) { + g_string_printf(repr, "%s(", def->name); + while (params != NULL) { + ws_assert(params->data); + g_string_append(repr, stnode_tostr(params->data, pretty)); + params = params->next; + if (params != NULL) { + g_string_append(repr, ", "); + } } + g_string_append_c(repr, ')'); + } + else { + g_string_printf(repr, "%s#%u", def->name, g_slist_length(params)); } return g_string_free(repr, FALSE); @@ -119,23 +125,6 @@ sttype_function_funcdef(stnode_t *node) return stfuncrec->funcdef; } -ftenum_t -sttype_function_retval_ftype(stnode_t *node) -{ - function_t *stfuncrec; - - stfuncrec = stnode_data(node); - ws_assert_magic(stfuncrec, FUNCTION_MAGIC); - if (stfuncrec->funcdef->retval_ftype != 0) - return stfuncrec->funcdef->retval_ftype; - - if (stfuncrec->params) { - stnode_t *first_arg = stfuncrec->params->data; - return stnode_ftenum(first_arg); - } - return FT_NONE; -} - const char * sttype_function_name(stnode_t *node) { diff --git a/epan/dfilter/sttype-function.h b/epan/dfilter/sttype-function.h index 48294ce2d7..6f1cb3e8ce 100644 --- a/epan/dfilter/sttype-function.h +++ b/epan/dfilter/sttype-function.h @@ -21,8 +21,6 @@ sttype_function_set_params(stnode_t *node, GSList *params); /* Get the function-definition record for a function stnode_t. */ df_func_def_t* sttype_function_funcdef(stnode_t *node); -ftenum_t sttype_function_retval_ftype(stnode_t *node); - const char *sttype_function_name(stnode_t *node); /* Get the parameters for a function stnode_t. */ diff --git a/epan/dfilter/sttype-test.c b/epan/dfilter/sttype-test.c index 13c0040ee3..faef9f9a43 100644 --- a/epan/dfilter/sttype-test.c +++ b/epan/dfilter/sttype-test.c @@ -64,12 +64,12 @@ test_free(gpointer value) g_free(test); } -static const char * -test_todisplay(test_op_t op) +static char * +test_todisplay(const test_t *test) { const char *s = "<notset>"; - switch(op) { + switch(test->op) { case TEST_OP_NOT: s = "!"; break; @@ -135,15 +135,15 @@ test_todisplay(test_op_t op) s = "<uninitialized>"; break; } - return s; + return g_strdup(s); } -static const char * -test_todebug(test_op_t op) +static char * +test_todebug(const test_t *test) { const char *s = "<notset>"; - switch(op) { + switch(test->op) { case TEST_OP_NOT: s = "TEST_NOT"; break; @@ -211,7 +211,8 @@ test_todebug(test_op_t op) s = "<uninitialized>"; break; } - return s; + + return g_strdup(s); } static char * @@ -219,13 +220,10 @@ test_tostr(const void *value, gboolean pretty) { const test_t *test = value; ws_assert_magic(test, TEST_MAGIC); - const char *s; if (pretty) - s = test_todisplay(test->op); - else - s = test_todebug(test->op); - return g_strdup(s); + return test_todisplay(test); + return test_todebug(test); } static int diff --git a/epan/dfilter/syntax-tree.c b/epan/dfilter/syntax-tree.c index bd72a74222..36c73cc1b4 100644 --- a/epan/dfilter/syntax-tree.c +++ b/epan/dfilter/syntax-tree.c @@ -15,7 +15,6 @@ #include <wsutil/str_util.h> #include <wsutil/glib-compat.h> #include "sttype-test.h" -#include "sttype-pointer.h" #include "sttype-function.h" #include "dfilter-int.h" @@ -213,22 +212,6 @@ stnode_type_id(stnode_t *node) return STTYPE_UNINITIALIZED; } -ftenum_t -stnode_ftenum(stnode_t *node) -{ - ws_assert_magic(node, STNODE_MAGIC); - switch (node->type->id) { - case STTYPE_FVALUE: - case STTYPE_FIELD: - return sttype_pointer_ftenum(node); - case STTYPE_FUNCTION: - return sttype_function_retval_ftype(node); - default: - break; - } - return FT_NONE; -} - gpointer stnode_data(stnode_t *node) { @@ -397,6 +380,7 @@ static void visit_tree(wmem_strbuf_t *buf, stnode_t *node, int level) { stnode_t *left, *right; + GSList *params; if (stnode_type_id(node) == STTYPE_TEST || stnode_type_id(node) == STTYPE_ARITHMETIC) { @@ -417,6 +401,18 @@ visit_tree(wmem_strbuf_t *buf, stnode_t *node, int level) ws_assert_not_reached(); } } + else if (stnode_type_id(node) == STTYPE_FUNCTION) { + wmem_strbuf_append_printf(buf, "%s:\n", stnode_todebug(node)); + params = sttype_function_params(node); + while (params) { + indent(buf, level + 1); + visit_tree(buf, params->data, level + 1); + if (params->next != NULL) { + wmem_strbuf_append_c(buf, '\n'); + } + params = params->next; + } + } else { wmem_strbuf_append(buf, stnode_todebug(node)); } diff --git a/epan/dfilter/syntax-tree.h b/epan/dfilter/syntax-tree.h index 796c70d349..9e4912e00f 100644 --- a/epan/dfilter/syntax-tree.h +++ b/epan/dfilter/syntax-tree.h @@ -138,9 +138,6 @@ stnode_type_name(stnode_t *node); sttype_id_t stnode_type_id(stnode_t *node); -ftenum_t -stnode_ftenum(stnode_t *node); - gpointer stnode_data(stnode_t *node); |