/* 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>
#endif
#include <string.h>
+#include <errno.h>
+#include <math.h>
#ifndef _STDLIB_H
#include <stdlib.h>
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);
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);
%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
%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
$$ = 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);
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;
+ }
}
;
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;
+ }
}
;
| 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;
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); }
;
}
;
-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; }
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)
{
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)
}
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)
* 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>
/* 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);
alternation, /* &, | */
boolean, /* true, false */
numeric, /* uint8, uint16, or uint32 value */
+ floating, /* double */
abs_time,
string,
ether,
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];
/* 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>
/* not coded yet */
case numeric:
+ case floating:
case ipv4:
case ipv6:
case boolean:
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;
}
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;
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;
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;