aboutsummaryrefslogtreecommitdiffstats
path: root/epan
diff options
context:
space:
mode:
Diffstat (limited to 'epan')
-rw-r--r--epan/dfilter/dfilter-int.h2
-rw-r--r--epan/dfilter/dfilter.c7
-rw-r--r--epan/dfilter/dfunctions.c184
-rw-r--r--epan/dfilter/dfunctions.h5
-rw-r--r--epan/dfilter/dfvm.c189
-rw-r--r--epan/dfilter/dfvm.h8
-rw-r--r--epan/dfilter/gencode.c128
-rw-r--r--epan/dfilter/grammar.lemon4
-rw-r--r--epan/dfilter/semcheck.c45
-rw-r--r--epan/dfilter/semcheck.h5
-rw-r--r--epan/dfilter/sttype-function.c37
-rw-r--r--epan/dfilter/sttype-function.h2
-rw-r--r--epan/dfilter/sttype-test.c24
-rw-r--r--epan/dfilter/syntax-tree.c30
-rw-r--r--epan/dfilter/syntax-tree.h3
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, &params_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);