aboutsummaryrefslogtreecommitdiffstats
path: root/epan/dfilter
diff options
context:
space:
mode:
authorJoão Valverde <j@v6e.pt>2021-11-28 01:10:11 +0000
committerJoão Valverde <j@v6e.pt>2021-12-01 13:34:01 +0000
commit557cee31fc1306ce310ebe8796f836fcee1e1a61 (patch)
tree8a8798b18579d7c2c66ce6e7ad4efd8f6b32d8f4 /epan/dfilter
parentae14cedd4498b85c76818afef66e7277c02bb008 (diff)
dfilter: Save lexical token value to syntax tree
Use that for error messages, including any using test operators. This allows to always use the same name as the user. It avoids cases where the user write "a && b" and the message is "a and b" is syntactically invalid. It should also allow us to be more consistent with the use of double quotes.
Diffstat (limited to 'epan/dfilter')
-rw-r--r--epan/dfilter/grammar.lemon98
-rw-r--r--epan/dfilter/semcheck.c81
-rw-r--r--epan/dfilter/sttype-test.c172
-rw-r--r--epan/dfilter/sttype-test.h9
-rw-r--r--epan/dfilter/syntax-tree.c44
-rw-r--r--epan/dfilter/syntax-tree.h13
6 files changed, 243 insertions, 174 deletions
diff --git a/epan/dfilter/grammar.lemon b/epan/dfilter/grammar.lemon
index 752b21e7c1..cb46bc2fdf 100644
--- a/epan/dfilter/grammar.lemon
+++ b/epan/dfilter/grammar.lemon
@@ -21,6 +21,9 @@
static stnode_t *
new_function(dfwork_t *dfw, df_lval_t *lval);
+static stnode_t *
+new_test(dfwork_t *dfw, test_op_t op, df_lval_t *lval);
+
/* End of C code */
}
@@ -57,9 +60,11 @@ new_function(dfwork_t *dfw, df_lval_t *lval);
%type logical_test {stnode_t*}
%destructor logical_test {stnode_free($$);}
-%type rel_binop {test_op_t}
+%type rel_binop {stnode_t*}
+%destructor rel_binop {stnode_free($$);}
-%type cmp_op {test_op_t}
+%type cmp_op {stnode_t*}
+%destructor cmp_op {stnode_free($$);}
%type range {stnode_t*}
%destructor range {stnode_free($$);}
@@ -116,26 +121,39 @@ sentence ::= . { dfw->st_root = NULL; }
expr(X) ::= relation_test(R). { X = R; }
expr(X) ::= logical_test(L). { X = L; }
+%code {
+ static stnode_t *
+ new_test(dfwork_t *dfw _U_, test_op_t op, df_lval_t *lval)
+ {
+ stnode_t *node = stnode_new_test(op, df_lval_value(lval));
+ df_lval_free(lval);
+ return node;
+ }
+}
/* Logical tests */
-logical_test(T) ::= expr(E) TEST_AND expr(F).
+logical_test(T) ::= expr(E) TEST_AND(L) expr(F).
{
- T = stnode_new_test(TEST_OP_AND, E, F);
+ T = new_test(dfw, TEST_OP_AND, L);
+ sttype_test_set2_args(T, E, F);
}
-logical_test(T) ::= expr(E) TEST_OR expr(F).
+logical_test(T) ::= expr(E) TEST_OR(L) expr(F).
{
- T = stnode_new_test(TEST_OP_OR, E, F);
+ T = new_test(dfw, TEST_OP_OR, L);
+ sttype_test_set2_args(T, E, F);
}
-logical_test(T) ::= TEST_NOT expr(E).
+logical_test(T) ::= TEST_NOT(L) expr(E).
{
- T = stnode_new_test(TEST_OP_NOT, E, NULL);
+ T = new_test(dfw, TEST_OP_NOT, L);
+ sttype_test_set1_args(T, E);
}
logical_test(T) ::= entity(E).
{
- T = stnode_new_test(TEST_OP_EXISTS, E, NULL);
+ T = new_test(dfw, TEST_OP_EXISTS, NULL);
+ sttype_test_set1_args(T, E);
}
@@ -143,17 +161,17 @@ logical_test(T) ::= entity(E).
/* Entities, or things that can be compared/tested/checked */
entity(E) ::= STRING(S).
{
- E = stnode_new_string(df_lval_value(S));
+ E = stnode_new_string(df_lval_value(S), df_lval_value(S));
df_lval_free(S);
}
entity(E) ::= CHARCONST(C).
{
- E = stnode_new_charconst(df_lval_number(C));
+ E = stnode_new_charconst(df_lval_number(C), df_lval_value(C));
df_lval_free(C);
}
entity(E) ::= UNPARSED(U).
{
- E = stnode_new_unparsed(df_lval_value(U));
+ E = stnode_new_unparsed(df_lval_value(U), df_lval_value(U));
dfilter_resolve_unparsed(dfw, E);
df_lval_free(U);
}
@@ -164,7 +182,7 @@ entity(E) ::= function(F). { E = F; }
/* Ranges */
range(R) ::= entity(E) LBRACKET range_node_list(L) RBRACKET.
{
- R = stnode_new(STTYPE_RANGE, NULL);
+ R = stnode_new(STTYPE_RANGE, NULL, NULL);
sttype_range_set(R, E, L);
/* Delete the list, but not the drange_nodes that
@@ -195,20 +213,20 @@ range_node(D) ::= RANGE(R).
df_lval_free(R);
}
-
/* Relational tests */
-cmp_op(O) ::= TEST_ANY_EQ. { O = TEST_OP_ANY_EQ; }
-cmp_op(O) ::= TEST_ALL_NE. { O = TEST_OP_ALL_NE; }
-cmp_op(O) ::= TEST_ANY_NE. { O = TEST_OP_ANY_NE; }
-cmp_op(O) ::= TEST_GT. { O = TEST_OP_GT; }
-cmp_op(O) ::= TEST_GE. { O = TEST_OP_GE; }
-cmp_op(O) ::= TEST_LT. { O = TEST_OP_LT; }
-cmp_op(O) ::= TEST_LE. { O = TEST_OP_LE; }
-cmp_op(O) ::= TEST_BITWISE_AND. { O = TEST_OP_BITWISE_AND; }
+cmp_op(O) ::= TEST_ANY_EQ(L). { O = new_test(dfw, TEST_OP_ANY_EQ, L); }
+cmp_op(O) ::= TEST_ALL_NE(L). { O = new_test(dfw, TEST_OP_ALL_NE, L); }
+cmp_op(O) ::= TEST_ANY_NE(L). { O = new_test(dfw, TEST_OP_ANY_NE, L); }
+cmp_op(O) ::= TEST_GT(L). { O = new_test(dfw, TEST_OP_GT, L); }
+cmp_op(O) ::= TEST_GE(L). { O = new_test(dfw, TEST_OP_GE, L); }
+cmp_op(O) ::= TEST_LT(L). { O = new_test(dfw, TEST_OP_LT, L); }
+cmp_op(O) ::= TEST_LE(L). { O = new_test(dfw, TEST_OP_LE, L); }
+cmp_op(O) ::= TEST_BITWISE_AND(L). { O = new_test(dfw, TEST_OP_BITWISE_AND, L); }
comparison_test(T) ::= entity(E) cmp_op(O) entity(F).
{
- T = stnode_new_test(O, E, F);
+ T = O;
+ sttype_test_set2_args(O, E, F);
}
/* 'a == b == c' or 'a < b <= c <= d < e' */
@@ -225,37 +243,43 @@ comparison_test(T) ::= entity(E) cmp_op(O) comparison_test(R).
sttype_test_get(F, NULL, &F, NULL);
} while (stnode_type_id(F) == STTYPE_TEST);
- L = stnode_new_test(O, E, stnode_dup(F));
+ L = O;
+ sttype_test_set2_args(L, E, stnode_dup(F));
- T = stnode_new_test(TEST_OP_AND, L, R);
+ T = stnode_new_test(TEST_OP_AND, NULL);
+ sttype_test_set2_args(T, L, R);
}
relation_test(T) ::= comparison_test(C). { T = C; }
/* Does not chain like math comparisons. */
-rel_binop(O) ::= TEST_CONTAINS. { O = TEST_OP_CONTAINS; }
-rel_binop(O) ::= TEST_MATCHES. { O = TEST_OP_MATCHES; }
+rel_binop(O) ::= TEST_CONTAINS(L). { O = new_test(dfw, TEST_OP_CONTAINS, L); }
+rel_binop(O) ::= TEST_MATCHES(L). { O = new_test(dfw, TEST_OP_MATCHES, L); }
relation_test(T) ::= entity(E) rel_binop(O) entity(F).
{
- T = stnode_new_test(O, E, F);
+ T = O;
+ sttype_test_set2_args(O, E, F);
}
-relation_test(T) ::= entity(E) TEST_IN set(S).
+relation_test(T) ::= entity(E) TEST_IN(O) set(S).
{
- T = stnode_new_test(TEST_OP_IN, E, S);
+ T = new_test(dfw, TEST_OP_IN, O);
+ sttype_test_set2_args(T, E, S);
}
-relation_test(T) ::= entity(E) TEST_NOT TEST_IN set(S).
+relation_test(T) ::= entity(E) TEST_NOT(P) TEST_IN(O) set(S).
{
- stnode_t *R = stnode_new_test(TEST_OP_IN, E, S);
+ stnode_t *R = new_test(dfw, TEST_OP_IN, O);
+ sttype_test_set2_args(R, E, S);
- T = stnode_new_test(TEST_OP_NOT, R, NULL);
+ T = new_test(dfw, TEST_OP_NOT, P);
+ sttype_test_set1_args(T, R);
}
set(S) ::= LBRACE set_list(L) RBRACE.
{
- S = stnode_new(STTYPE_SET, L);
+ S = stnode_new(STTYPE_SET, L, NULL);
}
set_list(L) ::= set_element(N).
@@ -291,7 +315,9 @@ set_element(N) ::= entity(X) DOTDOT entity(Y).
if (!def) {
dfilter_fail(dfw, "Function '%s' does not exist", name);
}
- return stnode_new(STTYPE_FUNCTION, def);
+ stnode_t *node = stnode_new(STTYPE_FUNCTION, def, df_lval_value(lval));
+ df_lval_free(lval);
+ return node;
}
}
@@ -300,14 +326,12 @@ function(F) ::= UNPARSED(U) LPAREN function_params(P) RPAREN.
{
F = new_function(dfw, U);
sttype_function_set_params(F, P);
- df_lval_free(U);
}
/* A function can have zero parameters. */
function(F) ::= UNPARSED(U) LPAREN RPAREN.
{
F = new_function(dfw, U);
- df_lval_free(U);
}
function_params(P) ::= entity(E).
diff --git a/epan/dfilter/semcheck.c b/epan/dfilter/semcheck.c
index 12199be847..9e9f68907b 100644
--- a/epan/dfilter/semcheck.c
+++ b/epan/dfilter/semcheck.c
@@ -435,7 +435,7 @@ check_exists(dfwork_t *dfw, stnode_t *st_arg1)
case STTYPE_STRING:
case STTYPE_UNPARSED:
case STTYPE_CHARCONST:
- FAIL(dfw, "\"%s\" is neither a field nor a protocol name.",
+ FAIL(dfw, "%s is neither a field nor a protocol name.",
stnode_todisplay(st_arg1));
break;
@@ -492,7 +492,7 @@ check_drange_sanity(dfwork_t *dfw, stnode_t *st)
/* Should this be rejected instead? */
check_drange_sanity(dfw, entity1);
} else {
- FAIL(dfw, "Range is not supported for entity \"%s\" of type %s",
+ FAIL(dfw, "Range is not supported for entity %s of type %s",
stnode_todisplay(entity1), stnode_type_name(entity1));
}
}
@@ -560,7 +560,8 @@ dfilter_fvalue_from_charconst(dfwork_t *dfw, ftenum_t ftype, stnode_t *st)
static void
check_relation_LHS_FIELD(dfwork_t *dfw, test_op_t st_op,
FtypeCanFunc can_func, gboolean allow_partial_value,
- stnode_t *st_node _U_, stnode_t *st_arg1, stnode_t *st_arg2)
+ stnode_t *st_node,
+ stnode_t *st_arg1, stnode_t *st_arg2)
{
sttype_id_t type2;
header_field_info *hfinfo1, *hfinfo2;
@@ -574,9 +575,9 @@ check_relation_LHS_FIELD(dfwork_t *dfw, test_op_t st_op,
ftype1 = hfinfo1->type;
if (!can_func(ftype1)) {
- FAIL(dfw, "%s (type=%s) cannot participate in '%s' comparison.",
+ FAIL(dfw, "%s (type=%s) cannot participate in %s comparison.",
hfinfo1->abbrev, ftype_pretty_name(ftype1),
- sttype_test_todisplay(st_op));
+ stnode_todisplay(st_node));
}
if (type2 == STTYPE_FIELD) {
@@ -654,9 +655,9 @@ check_relation_LHS_FIELD(dfwork_t *dfw, test_op_t st_op,
}
static void
-check_relation_LHS_STRING(dfwork_t *dfw, test_op_t st_op,
+check_relation_LHS_STRING(dfwork_t *dfw, test_op_t st_op _U_,
FtypeCanFunc can_func, gboolean allow_partial_value _U_,
- stnode_t *st_node _U_,
+ stnode_t *st_node,
stnode_t *st_arg1, stnode_t *st_arg2)
{
sttype_id_t type2;
@@ -672,9 +673,9 @@ check_relation_LHS_STRING(dfwork_t *dfw, test_op_t st_op,
ftype2 = hfinfo2->type;
if (!can_func(ftype2)) {
- FAIL(dfw, "%s (type=%s) cannot participate in '%s' comparison.",
+ FAIL(dfw, "%s (type=%s) cannot participate in %s comparison.",
hfinfo2->abbrev, ftype_pretty_name(ftype2),
- sttype_test_todisplay(st_op));
+ stnode_todisplay(st_node));
}
fvalue = dfilter_fvalue_from_string(dfw, ftype2, st_arg1, hfinfo2);
@@ -683,7 +684,7 @@ check_relation_LHS_STRING(dfwork_t *dfw, test_op_t st_op,
else if (type2 == STTYPE_STRING || type2 == STTYPE_UNPARSED ||
type2 == STTYPE_CHARCONST) {
/* Well now that's silly... */
- FAIL(dfw, "Neither \"%s\" nor \"%s\" are field or protocol names.",
+ FAIL(dfw, "Neither %s nor %s are field or protocol names.",
stnode_todisplay(st_arg1),
stnode_todisplay(st_arg2));
}
@@ -699,9 +700,9 @@ check_relation_LHS_STRING(dfwork_t *dfw, test_op_t st_op,
ftype2 = funcdef->retval_ftype;
if (!can_func(ftype2)) {
- FAIL(dfw, "Return value of function %s (type=%s) cannot participate in '%s' comparison.",
+ FAIL(dfw, "Return value of function %s (type=%s) cannot participate in %s comparison.",
funcdef->name, ftype_pretty_name(ftype2),
- sttype_test_todisplay(st_op));
+ stnode_todisplay(st_node));
}
fvalue = dfilter_fvalue_from_string(dfw, ftype2, st_arg1, NULL);
@@ -713,9 +714,9 @@ check_relation_LHS_STRING(dfwork_t *dfw, test_op_t st_op,
}
static void
-check_relation_LHS_UNPARSED(dfwork_t *dfw, test_op_t st_op,
+check_relation_LHS_UNPARSED(dfwork_t *dfw, test_op_t st_op _U_,
FtypeCanFunc can_func, gboolean allow_partial_value,
- stnode_t *st_node _U_,
+ stnode_t *st_node,
stnode_t *st_arg1, stnode_t *st_arg2)
{
sttype_id_t type2;
@@ -731,9 +732,9 @@ check_relation_LHS_UNPARSED(dfwork_t *dfw, test_op_t st_op,
ftype2 = hfinfo2->type;
if (!can_func(ftype2)) {
- FAIL(dfw, "%s (type=%s) cannot participate in '%s' comparison.",
+ FAIL(dfw, "%s (type=%s) cannot participate in %s comparison.",
hfinfo2->abbrev, ftype_pretty_name(ftype2),
- sttype_test_todisplay(st_op));
+ stnode_todisplay(st_node));
}
fvalue = dfilter_fvalue_from_unparsed(dfw, ftype2, st_arg1, allow_partial_value, hfinfo2);
@@ -742,7 +743,7 @@ check_relation_LHS_UNPARSED(dfwork_t *dfw, test_op_t st_op,
else if (type2 == STTYPE_STRING || type2 == STTYPE_UNPARSED ||
type2 == STTYPE_CHARCONST) {
/* Well now that's silly... */
- FAIL(dfw, "Neither \"%s\" nor \"%s\" are field or protocol names.",
+ FAIL(dfw, "Neither %s nor %s are field or protocol names.",
stnode_todisplay(st_arg1),
stnode_todisplay(st_arg2));
}
@@ -758,8 +759,8 @@ check_relation_LHS_UNPARSED(dfwork_t *dfw, test_op_t st_op,
ftype2 = funcdef->retval_ftype;
if (!can_func(ftype2)) {
- FAIL(dfw, "return value of function %s() (type=%s) cannot participate in '%s' comparison.",
- funcdef->name, ftype_pretty_name(ftype2), sttype_test_todisplay(st_op));
+ FAIL(dfw, "return value of function %s() (type=%s) cannot participate in %s comparison.",
+ funcdef->name, ftype_pretty_name(ftype2), stnode_todisplay(st_node));
}
fvalue = dfilter_fvalue_from_unparsed(dfw, ftype2, st_arg1, allow_partial_value, NULL);
@@ -771,9 +772,9 @@ check_relation_LHS_UNPARSED(dfwork_t *dfw, test_op_t st_op,
}
static void
-check_relation_LHS_CHARCONST(dfwork_t *dfw, test_op_t st_op,
+check_relation_LHS_CHARCONST(dfwork_t *dfw, test_op_t st_op _U_,
FtypeCanFunc can_func, gboolean allow_partial_value _U_,
- stnode_t *st_node _U_,
+ stnode_t *st_node,
stnode_t *st_arg1, stnode_t *st_arg2)
{
sttype_id_t type2;
@@ -789,9 +790,9 @@ check_relation_LHS_CHARCONST(dfwork_t *dfw, test_op_t st_op,
ftype2 = hfinfo2->type;
if (!can_func(ftype2)) {
- FAIL(dfw, "%s (type=%s) cannot participate in '%s' comparison.",
+ FAIL(dfw, "%s (type=%s) cannot participate in %s comparison.",
hfinfo2->abbrev, ftype_pretty_name(ftype2),
- sttype_test_todisplay(st_op));
+ stnode_todisplay(st_node));
}
fvalue = dfilter_fvalue_from_charconst(dfw, ftype2, st_arg1);
@@ -800,7 +801,7 @@ check_relation_LHS_CHARCONST(dfwork_t *dfw, test_op_t st_op,
else if (type2 == STTYPE_STRING || type2 == STTYPE_UNPARSED ||
type2 == STTYPE_CHARCONST) {
/* Well now that's silly... */
- FAIL(dfw, "Neither \"%s\" nor \"%s\" are field or protocol names.",
+ FAIL(dfw, "Neither %s nor %s are field or protocol names.",
stnode_todisplay(st_arg1),
stnode_todisplay(st_arg2));
}
@@ -816,8 +817,8 @@ check_relation_LHS_CHARCONST(dfwork_t *dfw, test_op_t st_op,
ftype2 = funcdef->retval_ftype;
if (!can_func(ftype2)) {
- FAIL(dfw, "return value of function %s() (type=%s) cannot participate in '%s' comparison.",
- funcdef->name, ftype_pretty_name(ftype2), sttype_test_todisplay(st_op));
+ FAIL(dfw, "return value of function %s() (type=%s) cannot participate in %s comparison.",
+ funcdef->name, ftype_pretty_name(ftype2), stnode_todisplay(st_node));
}
fvalue = dfilter_fvalue_from_charconst(dfw, ftype2, st_arg1);
@@ -903,9 +904,9 @@ check_relation_LHS_RANGE(dfwork_t *dfw, test_op_t st_op,
* and possibly some modifications of syntax tree nodes. */
static void
check_relation_LHS_FUNCTION(dfwork_t *dfw, test_op_t st_op,
- FtypeCanFunc can_func,
- gboolean allow_partial_value,
- stnode_t *st_node _U_, stnode_t *st_arg1, stnode_t *st_arg2)
+ FtypeCanFunc can_func, gboolean allow_partial_value,
+ stnode_t *st_node,
+ stnode_t *st_arg1, stnode_t *st_arg2)
{
sttype_id_t type2;
header_field_info *hfinfo2;
@@ -922,9 +923,9 @@ check_relation_LHS_FUNCTION(dfwork_t *dfw, test_op_t st_op,
ftype1 = funcdef->retval_ftype;
if (!can_func(ftype1)) {
- FAIL(dfw, "Function %s (type=%s) cannot participate in '%s' comparison.",
+ FAIL(dfw, "Function %s (type=%s) cannot participate in %s comparison.",
funcdef->name, ftype_pretty_name(ftype1),
- sttype_test_todisplay(st_op));
+ stnode_todisplay(st_node));
}
if (type2 == STTYPE_FIELD) {
@@ -1080,7 +1081,7 @@ check_relation_contains(dfwork_t *dfw, stnode_t *st_node,
case STTYPE_STRING:
case STTYPE_UNPARSED:
case STTYPE_CHARCONST:
- FAIL(dfw, "\"%s\" is not a valid operand for contains.", stnode_todisplay(st_arg1));
+ FAIL(dfw, "%s is not a valid operand for contains.", stnode_todisplay(st_arg1));
break;
default:
ws_assert_not_reached();
@@ -1096,7 +1097,7 @@ check_relation_matches(dfwork_t *dfw, stnode_t *st_node,
const char *patt;
if (stnode_type_id(st_arg2) != STTYPE_STRING) {
- FAIL(dfw, "Expected a double quoted string not '%s'", stnode_todisplay(st_arg2));
+ FAIL(dfw, "Matches requires a double quoted string on the right side.");
}
patt = stnode_data(st_arg2);
@@ -1127,7 +1128,7 @@ check_relation_matches(dfwork_t *dfw, stnode_t *st_node,
case STTYPE_STRING:
case STTYPE_UNPARSED:
case STTYPE_CHARCONST:
- FAIL(dfw, "\"%s\" is not a valid operand for matches.", stnode_todisplay(st_arg1));
+ FAIL(dfw, "Matches requires a field-like value on the left side.");
break;
default:
ws_assert_not_reached();
@@ -1139,7 +1140,7 @@ check_relation_in(dfwork_t *dfw, stnode_t *st_node _U_,
stnode_t *st_arg1, stnode_t *st_arg2)
{
GSList *nodelist;
- stnode_t *node, *node_right;
+ stnode_t *node_left, *node_right;
if (stnode_type_id(st_arg1) != STTYPE_FIELD) {
FAIL(dfw, "Only a field may be tested for membership in a set.");
@@ -1153,10 +1154,10 @@ check_relation_in(dfwork_t *dfw, stnode_t *st_node _U_,
* value if the element is a range. */
nodelist = stnode_data(st_arg2);
while (nodelist) {
- node = nodelist->data;
+ node_left = nodelist->data;
/* Don't let a range on the RHS affect the LHS field. */
- if (stnode_type_id(node) == STTYPE_RANGE) {
+ if (stnode_type_id(node_left) == STTYPE_RANGE) {
FAIL(dfw, "A range may not appear inside a set.");
break;
}
@@ -1166,12 +1167,12 @@ check_relation_in(dfwork_t *dfw, stnode_t *st_node _U_,
node_right = nodelist->data;
if (node_right) {
check_relation_LHS_FIELD(dfw, TEST_OP_GE, ftype_can_cmp,
- FALSE, st_arg2, st_arg1, node);
+ FALSE, st_node, st_arg1, node_left);
check_relation_LHS_FIELD(dfw, TEST_OP_LE, ftype_can_cmp,
- FALSE, st_arg2, st_arg1, node_right);
+ FALSE, st_node, st_arg1, node_right);
} else {
check_relation_LHS_FIELD(dfw, TEST_OP_ANY_EQ, ftype_can_eq,
- FALSE, st_arg2, st_arg1, node);
+ FALSE, st_node, st_arg1, node_left);
}
nodelist = g_slist_next(nodelist);
}
diff --git a/epan/dfilter/sttype-test.c b/epan/dfilter/sttype-test.c
index f5b1f4fb7a..4fb359154e 100644
--- a/epan/dfilter/sttype-test.c
+++ b/epan/dfilter/sttype-test.c
@@ -64,18 +64,73 @@ test_free(gpointer value)
g_free(test);
}
-static char *
-test_tostr(const void *value, gboolean pretty)
+static const char *
+test_todisplay(test_op_t op)
{
- const test_t *test = value;
- ws_assert_magic(test, TEST_MAGIC);
+ const char *s;
- if (pretty)
- return g_strdup(sttype_test_todisplay(test->op));
+ switch(op) {
+ case TEST_OP_EXISTS:
+ s = "exists";
+ break;
+ case TEST_OP_NOT:
+ s = "!";
+ break;
+ case TEST_OP_AND:
+ s = "&&";
+ break;
+ case TEST_OP_OR:
+ s = "||";
+ break;
+ case TEST_OP_ANY_EQ:
+ s = "==";
+ break;
+ case TEST_OP_ALL_NE:
+ s = "!=";
+ break;
+ case TEST_OP_ANY_NE:
+ s = "~=";
+ break;
+ case TEST_OP_GT:
+ s = ">";
+ break;
+ case TEST_OP_GE:
+ s = ">=";
+ break;
+ case TEST_OP_LT:
+ s = "<";
+ break;
+ case TEST_OP_LE:
+ s = "<=";
+ break;
+ case TEST_OP_BITWISE_AND:
+ s = "&";
+ break;
+ case TEST_OP_CONTAINS:
+ s = "contains";
+ break;
+ case TEST_OP_MATCHES:
+ s = "matches";
+ break;
+ case TEST_OP_IN:
+ s = "in";
+ break;
+ case TEST_OP_UNINITIALIZED:
+ s = "<uninitialized>";
+ break;
+ default:
+ s = "<null>";
+ break;
+ }
+ return s;
+}
- const char *s = "<null>";
+static const char *
+test_todebug(test_op_t op)
+{
+ const char *s;
- switch(test->op) {
+ switch(op) {
case TEST_OP_EXISTS:
s = "TEST_EXISTS";
break;
@@ -125,8 +180,23 @@ test_tostr(const void *value, gboolean pretty)
s = "<uninitialized>";
break;
default:
+ s = "<null>";
break;
}
+ return s;
+}
+
+static char *
+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);
}
@@ -183,6 +253,18 @@ sttype_test_set2(stnode_t *node, test_op_t op, stnode_t *val1, stnode_t *val2)
}
void
+sttype_test_set1_args(stnode_t *node, stnode_t *val1)
+{
+ test_t *test;
+
+ test = (test_t*)stnode_data(node);
+ ws_assert_magic(test, TEST_MAGIC);
+
+ g_assert_true(num_operands(test->op) == 1);
+ test->val1 = val1;
+}
+
+void
sttype_test_set2_args(stnode_t *node, stnode_t *val1, stnode_t *val2)
{
test_t *test;
@@ -190,13 +272,20 @@ sttype_test_set2_args(stnode_t *node, stnode_t *val1, stnode_t *val2)
test = (test_t*)stnode_data(node);
ws_assert_magic(test, TEST_MAGIC);
- if (num_operands(test->op) == 1) {
- g_assert_true(val2 == NULL);
- }
+ g_assert_true(num_operands(test->op) == 2);
test->val1 = val1;
test->val2 = val2;
}
+void
+sttype_test_set_op(stnode_t *node, test_op_t op)
+{
+ test_t *test = stnode_data(node);
+ ws_assert_magic(test, TEST_MAGIC);
+ ws_assert(test->op == TEST_OP_UNINITIALIZED);
+ test->op = op;
+}
+
test_op_t
sttype_test_get_op(stnode_t *node)
{
@@ -204,67 +293,6 @@ sttype_test_get_op(stnode_t *node)
return ((test_t *)node)->op;
}
-const char *
-sttype_test_todisplay(test_op_t op)
-{
- const char *s;
-
- switch(op) {
- case TEST_OP_EXISTS:
- s = "exists";
- break;
- case TEST_OP_NOT:
- s = "!";
- break;
- case TEST_OP_AND:
- s = "&&";
- break;
- case TEST_OP_OR:
- s = "||";
- break;
- case TEST_OP_ANY_EQ:
- s = "==";
- break;
- case TEST_OP_ALL_NE:
- s = "!=";
- break;
- case TEST_OP_ANY_NE:
- s = "~=";
- break;
- case TEST_OP_GT:
- s = ">";
- break;
- case TEST_OP_GE:
- s = ">=";
- break;
- case TEST_OP_LT:
- s = "<";
- break;
- case TEST_OP_LE:
- s = "<=";
- break;
- case TEST_OP_BITWISE_AND:
- s = "&";
- break;
- case TEST_OP_CONTAINS:
- s = "contains";
- break;
- case TEST_OP_MATCHES:
- s = "matches";
- break;
- case TEST_OP_IN:
- s = "in";
- break;
- case TEST_OP_UNINITIALIZED:
- s = "<uninitialized>";
- break;
- default:
- s = "<null>";
- break;
- }
- return s;
-}
-
void
sttype_test_get(stnode_t *node, test_op_t *p_op, stnode_t **p_val1, stnode_t **p_val2)
{
diff --git a/epan/dfilter/sttype-test.h b/epan/dfilter/sttype-test.h
index 0749f7eb0b..384e9965bc 100644
--- a/epan/dfilter/sttype-test.h
+++ b/epan/dfilter/sttype-test.h
@@ -18,14 +18,17 @@ void
sttype_test_set2(stnode_t *node, test_op_t op, stnode_t *val1, stnode_t *val2);
void
+sttype_test_set1_args(stnode_t *node, stnode_t *val1);
+
+void
sttype_test_set2_args(stnode_t *node, stnode_t *val1, stnode_t *val2);
+void
+sttype_test_set_op(stnode_t *node, test_op_t op);
+
test_op_t
sttype_test_get_op(stnode_t *node);
-const char *
-sttype_test_todisplay(test_op_t op);
-
void
sttype_test_get(stnode_t *node, test_op_t *p_op, stnode_t **p_val1, stnode_t **p_val2);
diff --git a/epan/dfilter/syntax-tree.c b/epan/dfilter/syntax-tree.c
index cb55ac920a..2072688165 100644
--- a/epan/dfilter/syntax-tree.c
+++ b/epan/dfilter/syntax-tree.c
@@ -93,10 +93,12 @@ stnode_clear(stnode_t *node)
node->repr_display = NULL;
g_free(node->repr_debug);
node->repr_debug = NULL;
+ g_free(node->repr_token);
+ node->repr_token = NULL;
}
void
-stnode_init(stnode_t *node, sttype_id_t type_id, gpointer data)
+stnode_init(stnode_t *node, sttype_id_t type_id, gpointer data, const char *token)
{
sttype_t *type;
@@ -106,6 +108,7 @@ stnode_init(stnode_t *node, sttype_id_t type_id, gpointer data)
node->flags = 0;
node->repr_display = NULL;
node->repr_debug = NULL;
+ node->repr_token = g_strdup(token);
if (type_id == STTYPE_UNINITIALIZED) {
node->type = NULL;
@@ -130,53 +133,52 @@ void
stnode_replace(stnode_t *node, sttype_id_t type_id, gpointer data)
{
uint16_t flags = node->flags; /* Save flags. */
+ char *repr_token = g_strdup(node->repr_token);
stnode_clear(node);
- stnode_init(node, type_id, data);
+ stnode_init(node, type_id, data, NULL);
node->flags = flags;
+ node->repr_token = repr_token;
}
stnode_t*
-stnode_new(sttype_id_t type_id, gpointer data)
+stnode_new(sttype_id_t type_id, gpointer data, const char *token)
{
stnode_t *node;
node = g_new0(stnode_t, 1);
node->magic = STNODE_MAGIC;
- stnode_init(node, type_id, data);
+ stnode_init(node, type_id, data, token);
return node;
}
stnode_t *
-stnode_new_test(test_op_t op, stnode_t *val1, stnode_t *val2)
+stnode_new_test(test_op_t op, const char *token)
{
stnode_t *node;
- node = stnode_new(STTYPE_TEST, NULL);
- if (val2 != NULL)
- sttype_test_set2(node, op, val1, val2);
- else
- sttype_test_set1(node, op, val1);
+ node = stnode_new(STTYPE_TEST, NULL, token);
+ sttype_test_set_op(node, op);
return node;
}
stnode_t *
-stnode_new_string(const char *str)
+stnode_new_string(const char *str, const char *token)
{
- return stnode_new(STTYPE_STRING, g_strdup(str));
+ return stnode_new(STTYPE_STRING, g_strdup(str), token);
}
stnode_t *
-stnode_new_unparsed(const char *str)
+stnode_new_unparsed(const char *str, const char *token)
{
- return stnode_new(STTYPE_UNPARSED, g_strdup(str));
+ return stnode_new(STTYPE_UNPARSED, g_strdup(str), token);
}
stnode_t *
-stnode_new_charconst(unsigned long number)
+stnode_new_charconst(unsigned long number, const char *token)
{
- return stnode_new(STTYPE_CHARCONST, g_memdup2(&number, sizeof(number)));
+ return stnode_new(STTYPE_CHARCONST, g_memdup2(&number, sizeof(number)), token);
}
stnode_t*
@@ -190,6 +192,7 @@ stnode_dup(const stnode_t *node)
new->flags = node->flags;
new->repr_display = NULL;
new->repr_debug = NULL;
+ new->repr_token = g_strdup(node->repr_token);
new->type = node->type;
if (node->type == NULL)
@@ -296,6 +299,15 @@ stnode_tostr(stnode_t *node, gboolean pretty)
if (pretty && node->repr_display != NULL)
return node->repr_display;
+ if (pretty && node->repr_token != NULL) {
+ if (stnode_type_id(node) == STTYPE_CHARCONST) {
+ return node->repr_token;
+ }
+
+ node->repr_display = g_strdup_printf("\"%s\"", node->repr_token);
+ return node->repr_display;
+ }
+
if (!pretty && node->repr_debug != NULL)
return node->repr_debug;
diff --git a/epan/dfilter/syntax-tree.h b/epan/dfilter/syntax-tree.h
index ef02c1ef72..d94440040d 100644
--- a/epan/dfilter/syntax-tree.h
+++ b/epan/dfilter/syntax-tree.h
@@ -77,6 +77,7 @@ typedef struct {
sttype_t *type;
uint16_t flags;
gpointer data;
+ char *repr_token;
char *repr_display;
char *repr_debug;
} stnode_t;
@@ -100,19 +101,19 @@ void
sttype_register(sttype_t *type);
stnode_t*
-stnode_new(sttype_id_t type_id, gpointer data);
+stnode_new(sttype_id_t type_id, gpointer data, const char *token);
stnode_t *
-stnode_new_test(test_op_t op, stnode_t *val1, stnode_t *val2);
+stnode_new_test(test_op_t op, const char *token);
stnode_t *
-stnode_new_string(const char *str);
+stnode_new_string(const char *str, const char *token);
stnode_t *
-stnode_new_unparsed(const char *str);
+stnode_new_unparsed(const char *str, const char *token);
stnode_t *
-stnode_new_charconst(unsigned long number);
+stnode_new_charconst(unsigned long number, const char *token);
stnode_t*
stnode_dup(const stnode_t *org);
@@ -121,7 +122,7 @@ void
stnode_clear(stnode_t *node);
void
-stnode_init(stnode_t *node, sttype_id_t type_id, gpointer data);
+stnode_init(stnode_t *node, sttype_id_t type_id, gpointer data, const char *token);
void
stnode_replace(stnode_t *node, sttype_id_t type_id, gpointer data);