Enable display filtering on FT_DOUBLE fields.
authorgram <gram@f5534014-38df-0310-8fa8-9805f1628bb7>
Tue, 19 Oct 1999 05:31:14 +0000 (05:31 +0000)
committergram <gram@f5534014-38df-0310-8fa8-9805f1628bb7>
Tue, 19 Oct 1999 05:31:14 +0000 (05:31 +0000)
git-svn-id: http://anonsvn.wireshark.org/wireshark/trunk@886 f5534014-38df-0310-8fa8-9805f1628bb7

dfilter-grammar.y
dfilter-int.h
dfilter-scanner.l
dfilter.c

index fc2534bc615aa0a5be87577714590ea15b0215cf..7b3c7839fafe801da0f29bf116591d12413b9c80 100644 (file)
@@ -3,7 +3,7 @@
 /* dfilter-grammar.y
  * Parser for display filters
  *
- * $Id: dfilter-grammar.y,v 1.35 1999/10/17 20:54:56 gram Exp $
+ * $Id: dfilter-grammar.y,v 1.36 1999/10/19 05:31:12 gram Exp $
  *
  * Ethereal - Network traffic analyzer
  * By Gerald Combs <gerald@zing.org>
@@ -51,6 +51,8 @@
 #endif
 
 #include <string.h>
+#include <errno.h>
+#include <math.h>
 
 #ifndef _STDLIB_H
 #include <stdlib.h>
@@ -78,6 +80,8 @@ static GNode* dfilter_mknode_join(GNode *n1, enum node_type ntype, int operand,
 static GNode* dfilter_mknode_unary(int operand, GNode *n2);
 static GNode* dfilter_mknode_numeric_variable(gint id);
 static GNode* dfilter_mknode_numeric_value(guint32 val);
+static GNode* dfilter_mknode_floating_variable(gint id);
+static GNode* dfilter_mknode_floating_value(double val);
 static GNode* dfilter_mknode_ether_value(gchar*);
 static GNode* dfilter_mknode_ether_variable(gint id);
 static GNode* dfilter_mknode_ipxnet_value(guint32);
@@ -90,7 +94,8 @@ static GNode* dfilter_mknode_existence(gint id);
 static GNode* dfilter_mknode_bytes_value(GByteArray *barray);
 static GNode* dfilter_mknode_bytes_variable(gint id, gint offset, guint length);
 
-static guint32 string_to_value(char *s);
+static guint32 string_to_guint32(char *s, gboolean *success);
+static double string_to_double(char *s, gboolean *success);
 static int ether_str_to_guint8_array(const char *s, guint8 *mac);
 static guint dfilter_get_bytes_variable_offset(GNode *gnode);
 static guint dfilter_get_bytes_value_length(GNode* gnode);
@@ -123,6 +128,7 @@ dfilter *global_df = NULL;
 
 %type <node>   statement expression relation
 %type <node>   numeric_value numeric_variable
+%type <node>   floating_value floating_variable
 %type <node>   ether_value ether_variable
 %type <node>   ipxnet_value ipxnet_variable
 %type <node>   ipv4_value ipv4_variable
@@ -150,6 +156,7 @@ dfilter *global_df = NULL;
 %token <variable>      T_FT_BOOLEAN
 %token <variable>      T_FT_STRING
 %token <variable>      T_FT_IPXNET
+%token <variable>      T_FT_DOUBLE
 
 %token <string>                T_VAL_UNQUOTED_STRING
 %token <string>                T_VAL_BYTE_STRING
@@ -191,6 +198,15 @@ relation:  numeric_variable numeric_relation numeric_value
                        $$ = dfilter_mknode_join($1, relation, $2, $3);
                }
 
+       |       floating_variable numeric_relation floating_value
+               {
+                       $$ = dfilter_mknode_join($1, relation, $2, $3);
+               }
+       |       floating_variable numeric_relation floating_variable
+               {
+                       $$ = dfilter_mknode_join($1, relation, $2, $3);
+               }
+
        |       ether_variable equality_relation ether_value
                {
                        $$ = dfilter_mknode_join($1, relation, $2, $3);
@@ -289,8 +305,12 @@ relation:  numeric_variable numeric_relation numeric_value
 
 numeric_value: T_VAL_UNQUOTED_STRING
        {
-               $$ = dfilter_mknode_numeric_value(string_to_value($1));
+               gboolean success;
+               $$ = dfilter_mknode_numeric_value(string_to_guint32($1, &success));
                g_free($1);
+               if (!success) {
+                       YYERROR;
+               }
         }
        ;
 
@@ -306,8 +326,34 @@ ether_value:       T_VAL_BYTE_STRING
 
 ipxnet_value:  T_VAL_UNQUOTED_STRING
        {
-               $$ = dfilter_mknode_ipxnet_value(string_to_value($1));
+               gboolean success;
+               $$ = dfilter_mknode_ipxnet_value(string_to_guint32($1, &success));
+               g_free($1);
+               if (!success) {
+                       YYERROR;
+               }
+       }
+       ;
+
+floating_value:        T_VAL_UNQUOTED_STRING
+       {
+               gboolean success;
+               $$ = dfilter_mknode_floating_value(string_to_double($1, &success));
+               g_free($1);
+               if (!success) {
+                       YYERROR;
+               }
+       }
+
+       |       T_VAL_BYTE_STRING
+       {
+               /* e.g., 0.0, 0.1, 0.01 ... */
+               gboolean success;
+               $$ = dfilter_mknode_floating_value(string_to_double($1, &success));
                g_free($1);
+               if (!success) {
+                       YYERROR;
+               }
        }
        ;
 
@@ -361,13 +407,20 @@ bytes_value:      T_VAL_BYTE_STRING
 
        |       T_VAL_UNQUOTED_STRING
        {
-               guint32         val32 = string_to_value($1);
+               gboolean        success;
+               guint32         val32;
                guint8          val8;
                GByteArray      *barray;
 
+               val32 = string_to_guint32($1, &success);
+               if (!success) {
+                       g_free($1);
+                       YYERROR;
+               }
                if (val32 > 0xff) {
                        dfilter_fail("The value \"%s\" cannot be stored in a single-byte byte-string. "
                                "Use the multi-byte \"xx:yy\" representation.", $1);
+                       g_free($1);
                        YYERROR;
                }
                val8 = (guint8) val32;
@@ -391,6 +444,9 @@ numeric_variable:   T_FT_UINT8      { $$ = dfilter_mknode_numeric_variable($1.id); }
 ether_variable:                T_FT_ETHER      { $$ = dfilter_mknode_ether_variable($1.id); }
        ;
 
+floating_variable:     T_FT_DOUBLE     { $$ = dfilter_mknode_floating_variable($1.id); }
+       ;
+
 ipxnet_variable:       T_FT_IPXNET     { $$ = dfilter_mknode_ipxnet_variable($1.id); }
        ;
 
@@ -423,20 +479,21 @@ bytes_variable:           any_variable_type T_VAL_BYTE_RANGE
                }
        ;
 
-any_variable_type:     T_FT_UINT8 { $$ = $1; }
-       |               T_FT_UINT16 { $$ = $1; }
-       |               T_FT_UINT32 { $$ = $1; }
-       |               T_FT_INT8 { $$ = $1; }
-       |               T_FT_INT16 { $$ = $1; }
-       |               T_FT_INT32 { $$ = $1; }
-       |               T_FT_ETHER { $$ = $1; }
-       |               T_FT_IPv4 { $$ = $1; }
-       |               T_FT_IPv6 { $$ = $1; }
-       |               T_FT_IPXNET { $$ = $1; }
-       |               T_FT_NONE { $$ = $1; }
-       |               T_FT_BYTES { $$ = $1; }
-       |               T_FT_BOOLEAN { $$ = $1; }
-       |               T_FT_STRING { $$ = $1; }
+any_variable_type:     T_FT_UINT8      { $$ = $1; }
+       |               T_FT_UINT16     { $$ = $1; }
+       |               T_FT_UINT32     { $$ = $1; }
+       |               T_FT_INT8       { $$ = $1; }
+       |               T_FT_INT16      { $$ = $1; }
+       |               T_FT_INT32      { $$ = $1; }
+       |               T_FT_DOUBLE     { $$ = $1; }
+       |               T_FT_ETHER      { $$ = $1; }
+       |               T_FT_IPv4       { $$ = $1; }
+       |               T_FT_IPv6       { $$ = $1; }
+       |               T_FT_IPXNET     { $$ = $1; }
+       |               T_FT_NONE       { $$ = $1; }
+       |               T_FT_BYTES      { $$ = $1; }
+       |               T_FT_BOOLEAN    { $$ = $1; }
+       |               T_FT_STRING     { $$ = $1; }
        ;
 
 numeric_relation:      TOK_EQ { $$ = TOK_EQ; }
@@ -541,6 +598,23 @@ dfilter_mknode_ether_variable(gint id)
        return gnode;
 }
 
+static GNode*
+dfilter_mknode_floating_variable(gint id)
+{
+       dfilter_node    *node;
+       GNode           *gnode;
+
+       node = g_mem_chunk_alloc(global_df->node_memchunk);
+       node->ntype = variable;
+       node->elem_size = sizeof(double);
+       node->fill_array_func = fill_array_floating_variable;
+       node->check_relation_func = check_relation_floating;
+       node->value.variable = id;
+       gnode = g_node_new(node);
+
+       return gnode;
+}
+
 static GNode*
 dfilter_mknode_ipxnet_variable(gint id)
 {
@@ -684,6 +758,23 @@ dfilter_mknode_numeric_value(guint32 val)
        return gnode;
 }
 
+static GNode*
+dfilter_mknode_floating_value(double val)
+{
+       dfilter_node    *node;
+       GNode           *gnode;
+
+       node = g_mem_chunk_alloc(global_df->node_memchunk);
+       node->ntype = floating;
+       node->elem_size = sizeof(double);
+       node->fill_array_func = fill_array_floating_value;
+       node->check_relation_func = check_relation_floating;
+       node->value.floating = val;
+       gnode = g_node_new(node);
+
+       return gnode;
+}
+
 /* Returns NULL on bad parse of ETHER value */
 static GNode*
 dfilter_mknode_ether_value(gchar *byte_string)
@@ -810,20 +901,59 @@ dfilter_get_bytes_value_length(GNode* gnode)
 }
 
 static guint32
-string_to_value(char *s)
+string_to_guint32(char *s, gboolean *success)
 {
        char    *endptr;
        guint32 val;
 
        val = strtoul(s, &endptr, 0);
+       *success = TRUE;
        if (endptr == s || *endptr != '\0') {
                /* This isn't a valid number. */
                dfilter_fail("\"%s\" is not a valid number.", s);
+               *success = FALSE;
+       }
+       if (errno == ERANGE) {
+               *success = FALSE;
+               if (val == ULONG_MAX) {
+                       dfilter_fail("\"%s\" causes an integer overflow.", s);
+               }
+               else {
+                       dfilter_fail("\"%s\" is not an integer.", s);
+               }
        }
-       /* I should probably check errno here */
 
        return (guint32)val;
 }
+
+static double
+string_to_double(char *s, gboolean *success)
+{
+       char    *endptr = NULL;
+       double  retval;
+
+       retval = strtod(s, &endptr);
+       *success = TRUE;
+
+       if (endptr == s) {
+               dfilter_fail("\"%s\" is not a valid floating-point number.", s);
+               *success = FALSE;
+       }
+
+       if (errno == ERANGE) {
+               *success = FALSE;
+               if (retval == 0) {
+                       dfilter_fail("\"%s\" causes a floating-point underflow.", s);
+               }
+               else if (retval == HUGE_VAL) {
+                       dfilter_fail("\"%s\" causes a floating-point overflow.", s);
+               }
+               else {
+                       dfilter_fail("\"%s\" is not a valid floating-point.", s);
+               }
+       }
+       return retval;
+}
        
 static GNode*
 dfilter_mknode_existence(gint id)
index 45a90006488e8a63469bc135ad8f18b4a226bffb..05ad062d44b06a339b8282adfad748af28524a5d 100644 (file)
@@ -2,7 +2,7 @@
  * Definitions for routines common to multiple modules in the display
  * filter code, but not used outside that code.
  *
- * $Id: dfilter-int.h,v 1.9 1999/10/11 17:04:32 deniel Exp $
+ * $Id: dfilter-int.h,v 1.10 1999/10/19 05:31:13 gram Exp $
  *
  * Ethereal - Network traffic analyzer
  * By Gerald Combs <gerald@zing.org>
@@ -53,12 +53,15 @@ void dfilter_fail(char *fmt, ...);
 
 /* functions that dfilter-grammar.y needs during parsing*/
 gboolean check_relation_numeric(gint operand, GArray *a, GArray *b);
+gboolean check_relation_floating(gint operand, GArray *a, GArray *b);
 gboolean check_relation_ether(gint operand, GArray *a, GArray *b);
 gboolean check_relation_ipv6(gint operand, GArray *a, GArray *b);
 gboolean check_relation_bytes(gint operand, GArray *a, GArray *b);
 
 gboolean fill_array_numeric_value(GNode *gnode, gpointer data);
 gboolean fill_array_numeric_variable(GNode *gnode, gpointer data);
+gboolean fill_array_floating_value(GNode *gnode, gpointer data);
+gboolean fill_array_floating_variable(GNode *gnode, gpointer data);
 gboolean fill_array_ether_value(GNode *gnode, gpointer data);
 gboolean fill_array_ether_variable(GNode *gnode, gpointer data);
 gboolean fill_array_ipv6_value(GNode *gnode, gpointer data);
@@ -78,6 +81,7 @@ enum node_type {
        alternation,    /* &, | */
        boolean,        /* true, false */
        numeric,        /* uint8, uint16, or uint32 value */
+       floating,       /* double */
        abs_time,
        string,
        ether,
@@ -108,6 +112,7 @@ typedef struct dfilter_node {
                gint            alternation; /* if type == alternation (& or |) */
 
                guint32         numeric;
+               double          floating;
                struct timeval  abs_time; /* the whole struct, not a pointer */
                gchar           *string;
                guint8          ether[6];
index cda16ed3dfd0fa0eacc956093da63ce9c3cea0c3..1f35f0f48a5ba87846afe13b8331606c42edca24 100644 (file)
@@ -3,7 +3,7 @@
 /* dfilter-scanner.l
  * Scanner for display filters
  *
- * $Id: dfilter-scanner.l,v 1.24 1999/10/17 20:54:56 gram Exp $
+ * $Id: dfilter-scanner.l,v 1.25 1999/10/19 05:31:13 gram Exp $
  *
  * Ethereal - Network traffic analyzer
  * By Gerald Combs <gerald@zing.org>
@@ -89,6 +89,7 @@ whitespace    [\t ]
 hex            [A-Fa-f0-9]{1,2}
 hexsep         [-:\.]
 minus          [-]
+plus           [+]
 
 %%
 
@@ -202,9 +203,7 @@ le|\<\=             { dfilter_lval.operand = TOK_LE; return TOK_LE; }
                        retval = T_FT_INT32;
                        break;
                case FT_DOUBLE:
-                       dfilter_fail("Sorry, you can't filter on field \"%s\", as we don't yet support filtering on floating-point values.",
-                           yytext);
-                       retval = 0;
+                       retval = T_FT_DOUBLE;
                        break;
                case FT_ABSOLUTE_TIME:
                        dfilter_fail("Sorry, you can't filter on field \"%s\", as we don't yet support filtering on time-of-day values.",
@@ -246,11 +245,18 @@ le|\<\=           { dfilter_lval.operand = TOK_LE; return TOK_LE; }
        return retval;
 }
 
-{minus}?[0-9]+ {                               /* decimal or octal values */
+({plus}|{minus})?[0-9]+ {                      /* decimal and octal integers */
        dfilter_lval.string = g_strdup(yytext);
        return T_VAL_UNQUOTED_STRING;
 }
 
+({plus}|{minus})?([0-9]+|[0-9]+\.[0-9]+|\.[0-9]+)([eE]({plus}|{minus})?[0-9]+)? {
+       /* I'm trying to capture all floating points here, and
+        * am using the strtod manpage as the description of
+        * valid formats */
+       dfilter_lval.string = g_strdup(yytext);
+       return T_VAL_UNQUOTED_STRING;
+}
 
 [0-9\:\.]+ {
        dfilter_lval.string = g_strdup(yytext);
index 444fc9f88857718b962c614545d8befb1fdfb011..ef4aa7257d1bbe38f6cc8faa77d96ac36f7c7cb8 100644 (file)
--- a/dfilter.c
+++ b/dfilter.c
@@ -1,7 +1,7 @@
 /* dfilter.c
  * Routines for display filters
  *
- * $Id: dfilter.c,v 1.30 1999/10/12 05:00:50 guy Exp $
+ * $Id: dfilter.c,v 1.31 1999/10/19 05:31:14 gram Exp $
  *
  * Ethereal - Network traffic analyzer
  * By Gerald Combs <gerald@zing.org>
@@ -347,6 +347,7 @@ dfilter_apply_node(GNode *gnode, proto_tree *ptree, const guint8* pd)
                /* not coded yet */
        
        case numeric:
+       case floating:
        case ipv4:
        case ipv6:
        case boolean:
@@ -480,7 +481,6 @@ get_values_from_dfilter(dfilter_node *dnode, GNode *gnode)
        array = g_array_new(FALSE, FALSE, dnode->elem_size);
 
        g_node_traverse(gnode, G_IN_ORDER, G_TRAVERSE_ALL, -1, dnode->fill_array_func, array);
-/*     dnode->fill_array_func(gnode, array);*/
        return array;
 }
 
@@ -496,6 +496,18 @@ gboolean fill_array_numeric_variable(GNode *gnode, gpointer data)
        return FALSE; /* FALSE = do not end traversal of GNode tree */
 }
 
+gboolean fill_array_floating_variable(GNode *gnode, gpointer data)
+{
+       proto_tree_search_info  *sinfo = (proto_tree_search_info*)data;
+       field_info              *fi = (field_info*) (gnode->data);
+
+       if (fi->hfinfo->id == sinfo->target) {
+               g_array_append_val(sinfo->result.array, fi->value.floating);
+       }
+
+       return FALSE; /* FALSE = do not end traversal of GNode tree */
+}
+
 gboolean fill_array_ether_variable(GNode *gnode, gpointer data)
 {
        proto_tree_search_info  *sinfo = (proto_tree_search_info*)data;
@@ -567,6 +579,15 @@ gboolean fill_array_numeric_value(GNode *gnode, gpointer data)
        return FALSE; /* FALSE = do not end traversal of GNode tree */
 }
 
+gboolean fill_array_floating_value(GNode *gnode, gpointer data)
+{
+       GArray          *array = (GArray*)data;
+       dfilter_node    *dnode = (dfilter_node*) (gnode->data);
+
+       g_array_append_val(array, dnode->value.floating);
+       return FALSE; /* FALSE = do not end traversal of GNode tree */
+}
+
 gboolean fill_array_ether_value(GNode *gnode, gpointer data)
 {
        GArray          *array = (GArray*)data;
@@ -676,6 +697,84 @@ gboolean check_relation_numeric(gint operand, GArray *a, GArray *b)
        return FALSE;
 }
 
+gboolean check_relation_floating(gint operand, GArray *a, GArray *b)
+{
+       int     i, j, len_a, len_b;
+       double  val_a;
+
+       len_a = a->len;
+       len_b = b->len;
+
+
+       switch(operand) {
+       case TOK_EQ:
+               for(i = 0; i < len_a; i++) {
+                       val_a = g_array_index(a, double, i);
+                       for (j = 0; j < len_b; j++) {
+                               if (val_a == g_array_index(b, double, j))
+                                       return TRUE;
+                       }
+               }
+               return FALSE;
+
+       case TOK_NE:
+               for(i = 0; i < len_a; i++) {
+                       val_a = g_array_index(a, double, i);
+                       for (j = 0; j < len_b; j++) {
+                               if (val_a != g_array_index(b, double, j))
+                                       return TRUE;
+                       }
+               }
+               return FALSE;
+
+       case TOK_GT:
+               for(i = 0; i < len_a; i++) {
+                       val_a = g_array_index(a, double, i);
+                       for (j = 0; j < len_b; j++) {
+                               if (val_a > g_array_index(b, double, j))
+                                       return TRUE;
+                       }
+               }
+               return FALSE;
+
+       case TOK_GE:
+               for(i = 0; i < len_a; i++) {
+                       val_a = g_array_index(a, double, i);
+                       for (j = 0; j < len_b; j++) {
+                               if (val_a >= g_array_index(b, double, j))
+                                       return TRUE;
+                       }
+               }
+               return FALSE;
+
+       case TOK_LT:
+               for(i = 0; i < len_a; i++) {
+                       val_a = g_array_index(a, double, i);
+                       for (j = 0; j < len_b; j++) {
+                               if (val_a < g_array_index(b, double, j))
+                                       return TRUE;
+                       }
+               }
+               return FALSE;
+
+       case TOK_LE:
+               for(i = 0; i < len_a; i++) {
+                       val_a = g_array_index(a, double, i);
+                       for (j = 0; j < len_b; j++) {
+                               if (val_a <= g_array_index(b, double, j))
+                                       return TRUE;
+                       }
+               }
+               return FALSE;
+
+       default:
+               g_assert_not_reached();
+       }
+
+       g_assert_not_reached();
+       return FALSE;
+}
+
 gboolean check_relation_ipv6(gint operand, GArray *a, GArray *b)
 {
        int     i, j, len_a, len_b;