diff --git a/dftest.c b/dftest.c index a40f25f9b6..32f0cad244 100644 --- a/dftest.c +++ b/dftest.c @@ -49,6 +49,7 @@ static int opt_debug_level = 0; /* currently up to 2 */ static int opt_flex = 0; static int opt_lemon = 0; static int opt_syntax_tree = 0; +static int opt_return_vals = 0; static int opt_timer = 0; static long opt_optimize = 1; static int opt_show_types = 0; @@ -108,6 +109,7 @@ print_usage(int status) fprintf(fp, " -s, --syntax print syntax tree\n"); fprintf(fp, " -m --macros print saved macros\n"); fprintf(fp, " -t, --timer print elapsed compilation time\n"); + fprintf(fp, " -r --return-vals return field values for the tree root\n"); fprintf(fp, " -0, --optimize=0 do not optimize (check syntax)\n"); fprintf(fp, " --types show field value types\n"); /* NOTE: References are loaded during runtime and dftest only does compilation. @@ -216,6 +218,8 @@ compile_filter(const char *text, dfilter_t **dfp) df_flags |= DF_DEBUG_FLEX; if (opt_lemon) df_flags |= DF_DEBUG_LEMON; + if (opt_return_vals) + df_flags |= DF_RETURN_VALUES; start = g_get_monotonic_time(); ok = dfilter_compile_full(text, dfp, &df_err, df_flags, "dftest"); @@ -278,7 +282,7 @@ main(int argc, char **argv) ws_init_version_info("DFTest", NULL, NULL); - const char *optstring = "hvdDflsmtV0"; + const char *optstring = "hvdDflsmrtV0"; static struct ws_option long_options[] = { { "help", ws_no_argument, 0, 'h' }, { "version", ws_no_argument, 0, 'v' }, @@ -289,6 +293,7 @@ main(int argc, char **argv) { "macros", ws_no_argument, 0, 'm' }, { "timer", ws_no_argument, 0, 't' }, { "verbose", ws_no_argument, 0, 'V' }, + { "return-vals", ws_no_argument, 0, 'r' }, { "optimize", ws_required_argument, 0, 1000 }, { "types", ws_no_argument, 0, 2000 }, { "refs", ws_no_argument, 0, 3000 }, @@ -335,6 +340,9 @@ main(int argc, char **argv) case 't': opt_timer = 1; break; + case 'r': + opt_return_vals = 1; + break; case '0': opt_optimize = 0; break; diff --git a/epan/dfilter/dfilter.h b/epan/dfilter/dfilter.h index 3f606091e0..50ac0076b8 100644 --- a/epan/dfilter/dfilter.h +++ b/epan/dfilter/dfilter.h @@ -73,6 +73,9 @@ dfilter_expand(const char *expr, df_error_t **err_ret); #define DF_DEBUG_FLEX (1U << 3) /* Enable debug trace for lemon. */ #define DF_DEBUG_LEMON (1U << 4) +/* If the root of the syntax tree is a field, load and return the field values. + * By default the field is only checked for existence. */ +#define DF_RETURN_VALUES (1U << 5) /* Compiles a string to a dfilter_t. * On success, sets the dfilter* pointed to by dfp diff --git a/epan/dfilter/gencode.c b/epan/dfilter/gencode.c index 8d2248d55a..d9cb43f9ff 100644 --- a/epan/dfilter/gencode.c +++ b/epan/dfilter/gencode.c @@ -657,6 +657,18 @@ gen_exists(dfwork_t *dfw, stnode_t *st_node) } } +static dfvm_value_t* +gen_field(dfwork_t *dfw, stnode_t *st_node) +{ + dfvm_value_t *val1; + GSList *jumps = NULL; + + val1 = gen_entity(dfw, st_node, &jumps); + g_slist_foreach(jumps, fixup_jumps, dfw); + g_slist_free(jumps); + return val1; +} + static dfvm_value_t* gen_notzero(dfwork_t *dfw, stnode_t *st_node) { @@ -805,12 +817,22 @@ static dfvm_value_t* gencode(dfwork_t *dfw, stnode_t *st_node) { dfvm_value_t* val = NULL; + /* If the root of the tree is a field, load and return the + * values if we were asked to do so. If not, or anywhere + * other than the root, just test for existence. + */ + bool return_val = dfw->flags & DF_RETURN_VALUES; + dfw->flags &= ~DF_RETURN_VALUES; switch (stnode_type_id(st_node)) { case STTYPE_TEST: gen_test(dfw, st_node); break; case STTYPE_FIELD: - gen_exists(dfw, st_node); + if (return_val) { + val = gen_field(dfw, st_node); + } else { + gen_exists(dfw, st_node); + } break; case STTYPE_ARITHMETIC: case STTYPE_FUNCTION: