diff options
-rw-r--r-- | epan/dfilter/Makefile.am | 5 | ||||
-rw-r--r-- | epan/dfilter/Makefile.nmake | 4 | ||||
-rw-r--r-- | epan/dfilter/dfvm.c | 23 | ||||
-rw-r--r-- | epan/dfilter/dfvm.h | 7 | ||||
-rw-r--r-- | epan/dfilter/drange.c | 188 | ||||
-rw-r--r-- | epan/dfilter/drange.h | 92 | ||||
-rw-r--r-- | epan/dfilter/gencode.c | 10 | ||||
-rw-r--r-- | epan/dfilter/grammar.lemon | 88 | ||||
-rw-r--r-- | epan/dfilter/scanner.l | 71 | ||||
-rw-r--r-- | epan/dfilter/semcheck.c | 306 | ||||
-rw-r--r-- | epan/dfilter/sttype-integer.c | 42 | ||||
-rw-r--r-- | epan/dfilter/sttype-range.c | 116 | ||||
-rw-r--r-- | epan/dfilter/sttype-range.h | 20 | ||||
-rw-r--r-- | epan/dfilter/syntax-tree.c | 23 | ||||
-rw-r--r-- | epan/dfilter/syntax-tree.h | 14 | ||||
-rw-r--r-- | epan/ftypes/ftypes-int.h | 4 | ||||
-rw-r--r-- | epan/ftypes/ftypes.c | 118 | ||||
-rw-r--r-- | epan/ftypes/ftypes.h | 5 |
18 files changed, 806 insertions, 330 deletions
diff --git a/epan/dfilter/Makefile.am b/epan/dfilter/Makefile.am index 2b3ad99b68..9f34939e1c 100644 --- a/epan/dfilter/Makefile.am +++ b/epan/dfilter/Makefile.am @@ -1,6 +1,6 @@ # Makefile.am # -# $Id: Makefile.am,v 1.6 2001/02/26 23:56:59 guy Exp $ +# $Id: Makefile.am,v 1.7 2001/02/27 19:23:28 gram Exp $ # # Ethereal - Network traffic analyzer # By Gerald Combs <gerald@zing.org> @@ -40,6 +40,8 @@ libdfilter_a_SOURCES = \ dfilter-int.h \ dfvm.c \ dfvm.h \ + drange.c \ + drange.h \ gencode.c \ gencode.h \ glib-util.c \ @@ -49,6 +51,7 @@ libdfilter_a_SOURCES = \ scanner.c \ semcheck.c \ semcheck.h \ + sttype-integer.c \ sttype-pointer.c \ sttype-range.c \ sttype-range.h \ diff --git a/epan/dfilter/Makefile.nmake b/epan/dfilter/Makefile.nmake index 2bc20038aa..cb4f7586b8 100644 --- a/epan/dfilter/Makefile.nmake +++ b/epan/dfilter/Makefile.nmake @@ -17,11 +17,13 @@ CFLAGS=/MT /DHAVE_CONFIG_H /I. /I.. /I..\.. /I$(LEMON) \ OBJECTS = \ dfilter.obj \ dfvm.obj \ + drange.obj \ gencode.obj \ glib-util.obj \ grammar.obj \ scanner.obj \ semcheck.obj \ + sttype-integer.obj \ sttype-pointer.obj \ sttype-range.obj \ sttype-string.obj \ @@ -36,8 +38,6 @@ dfilter.lib : $(OBJECTS) clean: rm -f $(OBJECTS) scanner.c grammar.c grammar.h grammar.out dfilter.lib - - scanner.c : scanner.l $(LEX) -Pdf_ -oscanner.c scanner.l diff --git a/epan/dfilter/dfvm.c b/epan/dfilter/dfvm.c index b5c4e40453..6f2f2b9942 100644 --- a/epan/dfilter/dfvm.c +++ b/epan/dfilter/dfvm.c @@ -1,5 +1,5 @@ /* - * $Id: dfvm.c,v 1.2 2001/02/01 20:31:18 gram Exp $ + * $Id: dfvm.c,v 1.3 2001/02/27 19:23:28 gram Exp $ * * Ethereal - Network traffic analyzer * By Gerald Combs <gerald@zing.org> @@ -37,7 +37,6 @@ dfvm_insn_new(dfvm_opcode_t op) insn->arg1 = NULL; insn->arg2 = NULL; insn->arg3 = NULL; - insn->arg4 = NULL; return insn; } @@ -53,9 +52,6 @@ dfvm_insn_free(dfvm_insn_t *insn) if (insn->arg3) { dfvm_value_free(insn->arg3); } - if (insn->arg4) { - dfvm_value_free(insn->arg4); - } g_free(insn); } @@ -78,6 +74,9 @@ dfvm_value_free(dfvm_value_t *v) case FVALUE: fvalue_free(v->value.fvalue); break; + case DRANGE: + drange_free(v->value.drange); + break; default: /* nothing */ ; @@ -125,11 +124,9 @@ dfvm_dump(FILE *f, GPtrArray *insns) break; case MK_RANGE: - fprintf(f, "%05d MK_RANGE\t\treg#%d[%d:%d] -> reg#%d\n", + fprintf(f, "%05d MK_RANGE\t\treg#%d[?] -> reg#%d\n", id, arg1->value.numeric, - arg3->value.numeric, - arg4->value.numeric, arg2->value.numeric); break; @@ -275,7 +272,7 @@ free_register_overhead(dfilter_t* df) * to make a new list of fvalue_t's (which are ranges, or byte-slices), * and puts the new list into a new register. */ static void -mk_range(dfilter_t *df, int from_reg, int to_reg, int start, int end) +mk_range(dfilter_t *df, int from_reg, int to_reg, drange *drange) { GList *from_list, *to_list; fvalue_t *old_fv, *new_fv; @@ -285,8 +282,8 @@ mk_range(dfilter_t *df, int from_reg, int to_reg, int start, int end) while (from_list) { old_fv = from_list->data; - new_fv = fvalue_slice(old_fv, start, end); - /* Assert there because semcheck.c should have + new_fv = fvalue_slice(old_fv, drange); + /* Assert here because semcheck.c should have * already caught the cases in which a slice * cannot be made. */ g_assert(new_fv); @@ -309,7 +306,6 @@ dfvm_apply(dfilter_t *df, tvbuff_t *tvb, proto_tree *tree) dfvm_value_t *arg1; dfvm_value_t *arg2; dfvm_value_t *arg3; - dfvm_value_t *arg4; g_assert(tvb); g_assert(tree); @@ -348,10 +344,9 @@ dfvm_apply(dfilter_t *df, tvbuff_t *tvb, proto_tree *tree) case MK_RANGE: arg3 = insn->arg3; - arg4 = insn->arg4; mk_range(df, arg1->value.numeric, arg2->value.numeric, - arg3->value.numeric, arg4->value.numeric); + arg3->value.drange); break; case ANY_EQ: diff --git a/epan/dfilter/dfvm.h b/epan/dfilter/dfvm.h index 7af61fe8c4..c4b00c655c 100644 --- a/epan/dfilter/dfvm.h +++ b/epan/dfilter/dfvm.h @@ -1,5 +1,5 @@ /* - * $Id: dfvm.h,v 1.2 2001/02/01 20:31:18 gram Exp $ + * $Id: dfvm.h,v 1.3 2001/02/27 19:23:28 gram Exp $ * * Ethereal - Network traffic analyzer * By Gerald Combs <gerald@zing.org> @@ -28,6 +28,7 @@ #include "proto.h" #include "dfilter-int.h" #include "syntax-tree.h" +#include "drange.h" typedef enum { EMPTY, @@ -35,7 +36,8 @@ typedef enum { FIELD_ID, INSN_NUMBER, REGISTER, - INTEGER + INTEGER, + DRANGE } dfvm_value_type_t; typedef struct { @@ -44,6 +46,7 @@ typedef struct { union { fvalue_t *fvalue; guint32 numeric; + drange *drange; } value; } dfvm_value_t; diff --git a/epan/dfilter/drange.c b/epan/dfilter/drange.c new file mode 100644 index 0000000000..f0cedfe22e --- /dev/null +++ b/epan/dfilter/drange.c @@ -0,0 +1,188 @@ +/* drange.c + * Routines for providing general range support to the dfilter library + * + * $Id: drange.c,v 1.1 2001/02/27 19:23:28 gram Exp $ + * + * Copyright (c) 2000 by Ed Warnicke <hagbard@physics.rutgers.edu> + * + * Ethereal - Network traffic analyzer + * By Gerald Combs + * Copyright 1999 Gerald Combs + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + */ + +#include "drange.h" + +/* drange_node constructor */ +drange_node* +drange_node_new(void) +{ + drange_node* new_range_node; + + new_range_node = g_malloc(sizeof(drange_node)); + new_range_node->offset = 0; + new_range_node->length = 0; + new_range_node->to_the_end = FALSE; + return new_range_node; +} + +/* drange_node destructor */ +void +drange_node_free(drange_node* drnode) +{ + g_free(drnode); +} + +/* drange_node accessors */ +gint +drange_node_get_offset(drange_node* drnode) +{ + return drnode->offset; +} + +gint +drange_node_get_length(drange_node* drnode) +{ + return drnode->length; +} + +gboolean +drange_node_get_to_the_end(drange_node* drnode) +{ + return drnode->to_the_end; +} + +/* drange_node mutators */ +void +drange_node_set_offset(drange_node* drnode, gint offset) +{ + drnode->offset = offset; +} + +void +drange_node_set_length(drange_node* drnode, gint length) +{ + drnode->length = length; + drnode->to_the_end = FALSE; +} + +void +drange_node_set_to_the_end(drange_node* drnode, gboolean to_the_end) +{ + drnode->to_the_end = to_the_end; +} + +/* drange constructor */ +drange* +drange_new(void) +{ + drange* new_drange; + new_drange = g_malloc(sizeof(drange)); + new_drange->range_list = NULL; + new_drange->has_total_length = TRUE; + new_drange->total_length = 0; + new_drange->min_offset = G_MAXINT; + new_drange->max_offset = G_MININT; + return new_drange; +} + +static void +drange_append_wrapper(gpointer data, gpointer user_data) +{ + drange_node *drnode = data; + drange *dr = user_data; + + drange_append_drange_node(dr, drnode); +} + +drange* +drange_new_from_list(GSList *list) +{ + drange *new_drange; + + new_drange = drange_new(); + g_slist_foreach(list, drange_append_wrapper, new_drange); + return new_drange; +} + + +static void +drange_node_free_wrapper(gpointer data, gpointer userdata) +{ + g_free(data); +} + +/* drange destructor */ +void +drange_free(drange* dr) +{ + drange_node_free_list(dr->range_list); + g_free(dr); +} + +/* Call drange_node destructor on all list items */ +void +drange_node_free_list(GSList* list) +{ + g_slist_foreach(list, drange_node_free_wrapper, NULL); +} + +/* drange accessors */ +gboolean drange_has_total_length(drange* dr){ return dr->has_total_length; } +gint drange_get_total_length(drange* dr) { return dr->total_length; } +gint drange_get_min_offset(drange* dr) { return dr->min_offset; } +gint drange_get_max_offset(drange* dr) { return dr->max_offset; } + +static void +update_drange_with_node(drange *dr, drange_node *drnode) +{ + if(drnode->to_the_end){ + dr->has_total_length = FALSE; + } + else if(dr->has_total_length){ + dr->total_length += drnode->length; + } + if(drnode->offset < dr->min_offset){ + dr->min_offset = drnode->offset; + } + if(drnode->offset > dr->max_offset){ + dr->max_offset = drnode->offset; + } +} + +/* drange mutators */ +void +drange_prepend_drange_node(drange* dr, drange_node* drnode) +{ + if(drnode != NULL){ + dr->range_list = g_slist_prepend(dr->range_list,drnode); + update_drange_with_node(dr, drnode); + } +} + +void +drange_append_drange_node(drange* dr, drange_node* drnode) +{ + if(drnode != NULL){ + dr->range_list = g_slist_append(dr->range_list,drnode); + update_drange_with_node(dr, drnode); + } +} + +void +drange_foreach_drange_node(drange* dr, GFunc func, gpointer funcdata) +{ + g_slist_foreach(dr->range_list,func,funcdata); +} diff --git a/epan/dfilter/drange.h b/epan/dfilter/drange.h new file mode 100644 index 0000000000..f02684c476 --- /dev/null +++ b/epan/dfilter/drange.h @@ -0,0 +1,92 @@ +/* drange.h + * Routines for providing general range support to the dfilter library + * + * $Id: drange.h,v 1.1 2001/02/27 19:23:28 gram Exp $ + * + * Copyright (c) 2000 by Ed Warnicke <hagbard@physics.rutgers.edu> + * + * Ethereal - Network traffic analyzer + * By Gerald Combs + * Copyright 1999 Gerald Combs + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + */ + +#ifndef __DRANGE_H__ +#define __DRANGE_H__ + +#include <glib.h> + +/* Please don't directly manipulate these structs. Please use + * the methods provided. If you REALLY can't do what you need to + * do with the methods provided please write new methods that do + * what you need, put them into the drange object here, and limit + * your direct manipulation of the drange and drange_node structs to + * here. + */ + +typedef struct _drange_node { + gint offset; + gint length; + gboolean to_the_end; +} drange_node; + +typedef struct _drange { + GSList* range_list; + gboolean has_total_length; + gint total_length; + gint min_offset; + gint max_offset; +} drange; + +/* drange_node constructor */ +drange_node* drange_node_new(); + +/* drange_node destructor */ +void drange_node_free(drange_node* drnode); + +/* Call drange_node destructor on all list items */ +void drange_node_free_list(GSList* list); + +/* drange_node accessors */ +gint drange_node_get_offset(drange_node* drnode); +gint drange_node_get_length(drange_node* drnode); +gboolean drange_node_get_to_the_end(drange_node* drnode); + +/* drange_node mutators */ +void drange_node_set_offset(drange_node* drnode, gint offset); +void drange_node_set_length(drange_node* drnode, gint length); +void drange_node_set_to_the_end(drange_node* drnode, gboolean to_the_end); + +/* drange constructor */ +drange* drange_new(); +drange* drange_new_from_list(GSList *list); + +/* drange destructor, only use this if you used drange_new() to creat + * the drange + */ +void drange_free(drange* dr); + +/* drange accessors */ +gboolean drange_has_total_length(drange* dr); +gint drange_get_total_length(drange* dr); +gint drange_get_min_offset(drange* dr); +gint drange_get_max_offset(drange* dr); + +/* drange mutators */ +void drange_append_drange_node(drange* dr, drange_node* drnode); +void drange_prepend_drange_node(drange* dr, drange_node* drnode); +void drange_foreach_drange_node(drange* dr, GFunc func, gpointer funcdata); + +#endif /* ! __DRANGE_H__ */ diff --git a/epan/dfilter/gencode.c b/epan/dfilter/gencode.c index 7c2ab1224d..cf3e1d5787 100644 --- a/epan/dfilter/gencode.c +++ b/epan/dfilter/gencode.c @@ -1,5 +1,5 @@ /* - * $Id: gencode.c,v 1.2 2001/02/11 03:12:46 gram Exp $ + * $Id: gencode.c,v 1.3 2001/02/27 19:23:28 gram Exp $ * * Ethereal - Network traffic analyzer * By Gerald Combs <gerald@zing.org> @@ -129,13 +129,11 @@ dfw_append_mk_range(dfwork_t *dfw, stnode_t *node) val->value.numeric = reg; insn->arg2 = val; - val = dfvm_value_new(INTEGER); - val->value.numeric = sttype_range_start(node); + val = dfvm_value_new(DRANGE); + val->value.drange = sttype_range_drange(node); insn->arg3 = val; - val = dfvm_value_new(INTEGER); - val->value.numeric = sttype_range_end(node); - insn->arg4 = val; + sttype_range_remove_drange(node); dfw_append_insn(dfw, insn); diff --git a/epan/dfilter/grammar.lemon b/epan/dfilter/grammar.lemon index 8072458ab7..b6001789cd 100644 --- a/epan/dfilter/grammar.lemon +++ b/epan/dfilter/grammar.lemon @@ -1,4 +1,4 @@ -/* $Id: grammar.lemon,v 1.1 2001/02/01 20:21:18 gram Exp $ */ +/* $Id: grammar.lemon,v 1.2 2001/02/27 19:23:28 gram Exp $ */ %include { #ifdef HAVE_CONFIG_H @@ -9,6 +9,7 @@ #include "syntax-tree.h" #include "sttype-range.h" #include "sttype-test.h" +#include "drange.h" /*extern char *df_text;*/ @@ -44,6 +45,12 @@ %type range {stnode_t*} %destructor range {stnode_free($$);} +%type drnode {drange_node*} +%destructor drnode {drange_node_free($$);} + +%type drnode_list {GSList*} +%destructor drnode_list {drange_node_free_list($$);} + /* This is called as soon as a syntax error happens. After that, any "error" symbols are shifted, if possible. */ %syntax_error { @@ -66,6 +73,10 @@ any "error" symbols are shifted, if possible. */ dfilter_fail("The string \"%s\" was unexpected in this context.", stnode_data(TOKEN)); break; + case STTYPE_INTEGER: + dfilter_fail("The integer %u was unexpected in this context.", + stnode_value(TOKEN)); + break; case STTYPE_FIELD: hfinfo = stnode_data(TOKEN); dfilter_fail("Syntax error near \"%s\".", hfinfo->abbrev); @@ -143,29 +154,82 @@ entity(E) ::= FIELD(F). { E = F; } entity(E) ::= STRING(S). { E = S; } entity(E) ::= range(R). { E = R; } -range(R) ::= FIELD(F) LBRACKET STRING(X) COLON STRING(Y) RBRACKET. + +/* Ranges */ +range(R) ::= FIELD(F) LBRACKET drnode_list(L) RBRACKET. { R = stnode_new(STTYPE_RANGE, NULL); - sttype_range_set(R, F, X, Y); + sttype_range_set(R, F, L); + + /* Delete the list, but not the drange_nodes that + * the list contains. */ + g_slist_free(L); } -range(R) ::= FIELD(F) LBRACKET STRING(X) COLON RBRACKET. +drnode_list(L) ::= drnode(D). { - R = stnode_new(STTYPE_RANGE, NULL); - sttype_range_set(R, F, X, NULL); + L = g_slist_append(NULL, D); } -range(R) ::= FIELD(F) LBRACKET COLON STRING(Y) RBRACKET. +drnode_list(L) ::= drnode_list(P) COMMA drnode(D). { - R = stnode_new(STTYPE_RANGE, NULL); - sttype_range_set(R, F, NULL, Y); + L = g_slist_append(P, D); } -range(R) ::= FIELD(F) LBRACKET STRING(Y) RBRACKET. +/* x:y is offset:length */ +drnode(D) ::= INTEGER(X) COLON INTEGER(Y). { - R = stnode_new(STTYPE_RANGE, NULL); - sttype_range_set1(R, F, Y); + D = drange_node_new(); + drange_node_set_offset(D, stnode_value(X)); + drange_node_set_length(D, stnode_value(Y)); + + stnode_free(X); + stnode_free(Y); +} + +/* x,y == offset:(offset-1) +drnode(D) ::= INTEGER(X) HYPHEN INTEGER(Y). +{ + D = drange_node_new(); + drange_node_set_offset(D, stnode_value(X)); + drange_node_set_length(D, stnode_value(Y)); + + stnode_free(X); + stnode_free(Y); } +*/ + +/* :y == from start to offset */ +drnode(D) ::= COLON INTEGER(Y). +{ + D = drange_node_new(); + drange_node_set_offset(D, 0); + drange_node_set_length(D, stnode_value(Y)); + + stnode_free(Y); +} + +/* x: from offset to end */ +drnode(D) ::= INTEGER(X) COLON. +{ + D = drange_node_new(); + drange_node_set_offset(D, stnode_value(X)); + drange_node_set_to_the_end(D, TRUE); + + stnode_free(X); +} + +/* x == x:1 */ +drnode(D) ::= INTEGER(X). +{ + D = drange_node_new(); + drange_node_set_offset(D, stnode_value(X)); + drange_node_set_length(D, 1); + + stnode_free(X); +} + + /* Relational tests */ relation_test(T) ::= entity(E) rel_op2(O) entity(F). diff --git a/epan/dfilter/scanner.l b/epan/dfilter/scanner.l index 43bcba55c7..71c5cc0a80 100644 --- a/epan/dfilter/scanner.l +++ b/epan/dfilter/scanner.l @@ -1,6 +1,6 @@ %{ /* - * $Id: scanner.l,v 1.2 2001/02/01 20:31:18 gram Exp $ + * $Id: scanner.l,v 1.3 2001/02/27 19:23:28 gram Exp $ * * Ethereal - Network traffic analyzer * By Gerald Combs <gerald@zing.org> @@ -26,6 +26,9 @@ #include "config.h" #endif +#include <stdlib.h> +#include <errno.h> + #include "glib-util.h" #include "dfilter-int.h" #include "syntax-tree.h" @@ -40,8 +43,10 @@ /*#undef YY_NO_UNPUT*/ -int set_lval(int token, gpointer data); -int simple(int token); +static int set_lval(int token, gpointer data); +static int set_lval_int(int token, char *s); +static int simple(int token); +static gboolean str_to_guint32(char *s, guint32* pint); %} @@ -88,12 +93,13 @@ VARCHARS [[:alnum:]_] } <RANGE>[+-]?[[:digit:]]+ { - return set_lval(TOKEN_STRING, g_strdup(yytext)); + return set_lval_int(TOKEN_INTEGER, yytext); } <RANGE>[+-]?0x[[:xdigit:]]+ { - return set_lval(TOKEN_STRING, g_strdup(yytext)); + return set_lval_int(TOKEN_INTEGER, yytext); } <RANGE>":" return simple(TOKEN_COLON); +<RANGE>"," return simple(TOKEN_COMMA); <RANGE>"]" { BEGIN(INITIAL); @@ -126,7 +132,7 @@ VARCHARS [[:alnum:]_] %% -int +static int simple(int token) { switch (token) { @@ -135,6 +141,7 @@ simple(int token) case TOKEN_LBRACKET: case TOKEN_RBRACKET: case TOKEN_COLON: + case TOKEN_COMMA: case TOKEN_TEST_EQ: case TOKEN_TEST_NE: case TOKEN_TEST_GT: @@ -151,7 +158,7 @@ simple(int token) return token; } -int +static int set_lval(int token, gpointer data) { sttype_id_t type_id = STTYPE_UNINITIALIZED; @@ -171,4 +178,54 @@ set_lval(int token, gpointer data) return token; } +static int +set_lval_int(int token, char *s) +{ + sttype_id_t type_id = STTYPE_UNINITIALIZED; + guint32 val; + + if (!str_to_guint32(s, &val)) { + return 0; + } + + switch (token) { + case TOKEN_INTEGER: + type_id = STTYPE_INTEGER; + break; + default: + g_assert_not_reached(); + } + + stnode_init_int(df_lval, type_id, val); + return token; +} + + +static gboolean +str_to_guint32(char *s, guint32* pint) +{ + char *endptr; + guint32 integer; + + integer = strtoul(s, &endptr, 0); + + if (endptr == s || *endptr != '\0') { + /* This isn't a valid number. */ + dfilter_fail("\"%s\" is not a valid number.", s); + return FALSE; + } + if (errno == ERANGE) { + if (integer == ULONG_MAX) { + dfilter_fail("\"%s\" causes an integer overflow.", s); + } + else { + dfilter_fail("\"%s\" is not an integer.", s); + } + return FALSE; + } + + *pint = integer; + return TRUE; +} + #include <lemonflex-tail.inc> diff --git a/epan/dfilter/semcheck.c b/epan/dfilter/semcheck.c index 24096ec694..ba272ff660 100644 --- a/epan/dfilter/semcheck.c +++ b/epan/dfilter/semcheck.c @@ -1,5 +1,5 @@ /* - * $Id: semcheck.c,v 1.2 2001/02/01 20:31:18 gram Exp $ + * $Id: semcheck.c,v 1.3 2001/02/27 19:23:28 gram Exp $ * * Ethereal - Network traffic analyzer * By Gerald Combs <gerald@zing.org> @@ -240,9 +240,8 @@ is_bytes_type(enum ftenum type) return FALSE; } -/* This could really be split up... it's too big. */ static void -check_relation(dfwork_t *dfw, FtypeCanFunc can_func, stnode_t *st_node, +check_relation_LHS_FIELD(dfwork_t *dfw, FtypeCanFunc can_func, stnode_t *st_node, stnode_t *st_arg1, stnode_t *st_arg2) { stnode_t *new_st; @@ -251,169 +250,224 @@ check_relation(dfwork_t *dfw, FtypeCanFunc can_func, stnode_t *st_node, ftenum_t ftype1, ftype2; fvalue_t *fvalue; char *s; + drange_node *rn; type1 = stnode_type_id(st_arg1); type2 = stnode_type_id(st_arg2); - if (type1 == STTYPE_FIELD) { - hfinfo1 = stnode_data(st_arg1); - ftype1 = hfinfo1->type; - if (!can_func(ftype1)) { - dfilter_fail("%s (type=%s) cannot participate in specified comparison.", - hfinfo1->abbrev, ftype_pretty_name(ftype1)); - THROW(TypeError); - } + hfinfo1 = stnode_data(st_arg1); + ftype1 = hfinfo1->type; + if (!can_func(ftype1)) { + dfilter_fail("%s (type=%s) cannot participate in specified comparison.", + hfinfo1->abbrev, ftype_pretty_name(ftype1)); + THROW(TypeError); + } - if (type2 == STTYPE_FIELD) { - hfinfo2 = stnode_data(st_arg2); - ftype2 = hfinfo2->type; - if (!compatible_ftypes(ftype1, ftype2)) { - dfilter_fail("%s and %s are not of compatible types.", - hfinfo1->abbrev, hfinfo2->abbrev); - THROW(TypeError); - } - /* Do this check even though you'd think that if - * they're compatible, then can_func() would pass. */ - if (!can_func(ftype2)) { - dfilter_fail("%s (type=%s) cannot participate in specified comparison.", - hfinfo2->abbrev, ftype_pretty_name(ftype2)); - THROW(TypeError); - } - } - else if (type2 == STTYPE_STRING) { - s = stnode_data(st_arg2); - fvalue = fvalue_from_string(ftype1, s, dfilter_fail); - if (!fvalue) { - /* check value_string */ - fvalue = mk_fvalue_from_val_string(hfinfo1, s); - if (!fvalue) { - THROW(TypeError); - } - } + if (type2 == STTYPE_FIELD) { + hfinfo2 = stnode_data(st_arg2); + ftype2 = hfinfo2->type; - new_st = stnode_new(STTYPE_FVALUE, fvalue); - sttype_test_set2_args(st_node, st_arg1, new_st); - stnode_free(st_arg2); - } - else if (type2 == STTYPE_RANGE) { - if (!is_bytes_type(ftype1)) { - if (!ftype_can_slice(ftype1)) { - dfilter_fail("\"%s\" is a %s and cannot be converted into a sequence of bytes.", - hfinfo1->abbrev, - ftype_pretty_name(ftype1)); - THROW(TypeError); - } - - /* Convert entire field to bytes */ - new_st = stnode_new(STTYPE_RANGE, NULL); - - /* st_arg1 is freed in this step */ - sttype_range_set(new_st, st_arg1, NULL, NULL); - - sttype_test_set2_args(st_node, new_st, st_arg2); - } + if (!compatible_ftypes(ftype1, ftype2)) { + dfilter_fail("%s and %s are not of compatible types.", + hfinfo1->abbrev, hfinfo2->abbrev); + THROW(TypeError); } - else { - g_assert_not_reached(); + /* Do this check even though you'd think that if + * they're compatible, then can_func() would pass. */ + if (!can_func(ftype2)) { + dfilter_fail("%s (type=%s) cannot participate in specified comparison.", + hfinfo2->abbrev, ftype_pretty_name(ftype2)); + THROW(TypeError); } } - else if (type1 == STTYPE_STRING) { - - if (type2 == STTYPE_FIELD) { - hfinfo2 = stnode_data(st_arg2); - ftype2 = hfinfo2->type; - - s = stnode_data(st_arg1); - fvalue = fvalue_from_string(ftype2, s, dfilter_fail); + else if (type2 == STTYPE_STRING) { + s = stnode_data(st_arg2); + fvalue = fvalue_from_string(ftype1, s, dfilter_fail); + if (!fvalue) { + /* check value_string */ + fvalue = mk_fvalue_from_val_string(hfinfo1, s); if (!fvalue) { - /* check value_string */ - fvalue = mk_fvalue_from_val_string(hfinfo2, s); - if (!fvalue) { - THROW(TypeError); - } + THROW(TypeError); + } + } + + new_st = stnode_new(STTYPE_FVALUE, fvalue); + sttype_test_set2_args(st_node, st_arg1, new_st); + stnode_free(st_arg2); + } + else if (type2 == STTYPE_RANGE) { + if (!is_bytes_type(ftype1)) { + if (!ftype_can_slice(ftype1)) { + dfilter_fail("\"%s\" is a %s and cannot be converted into a sequence of bytes.", + hfinfo1->abbrev, + ftype_pretty_name(ftype1)); + THROW(TypeError); } - new_st = stnode_new(STTYPE_FVALUE, fvalue); + /* Convert entire field to bytes */ + new_st = stnode_new(STTYPE_RANGE, NULL); + + rn = drange_node_new(); + drange_node_set_offset(rn, 0); + drange_node_set_to_the_end(rn, TRUE); + /* st_arg1 is freed in this step */ + sttype_range_set1(new_st, st_arg1, rn); + sttype_test_set2_args(st_node, new_st, st_arg2); - stnode_free(st_arg1); - } - else if (type2 == STTYPE_STRING) { - /* Well now that's silly... */ - dfilter_fail("Neither \"%s\" nor \"%s\" are field or protocol names.", - stnode_data(st_arg1), - stnode_data(st_arg2)); - THROW(TypeError); } - else if (type2 == STTYPE_RANGE) { - s = stnode_data(st_arg1); - fvalue = fvalue_from_string(FT_BYTES, s, dfilter_fail); + } + else { + g_assert_not_reached(); + } +} + +static void +check_relation_LHS_STRING(dfwork_t *dfw, FtypeCanFunc can_func, stnode_t *st_node, + stnode_t *st_arg1, stnode_t *st_arg2) +{ + stnode_t *new_st; + sttype_id_t type1, type2; + header_field_info *hfinfo2; + ftenum_t ftype2; + fvalue_t *fvalue; + char *s; + + type1 = stnode_type_id(st_arg1); + type2 = stnode_type_id(st_arg2); + + if (type2 == STTYPE_FIELD) { + hfinfo2 = stnode_data(st_arg2); + ftype2 = hfinfo2->type; + + s = stnode_data(st_arg1); + fvalue = fvalue_from_string(ftype2, s, dfilter_fail); + if (!fvalue) { + /* check value_string */ + fvalue = mk_fvalue_from_val_string(hfinfo2, s); if (!fvalue) { THROW(TypeError); } - new_st = stnode_new(STTYPE_FVALUE, fvalue); - sttype_test_set2_args(st_node, new_st, st_arg2); - stnode_free(st_arg1); } - else { - g_assert_not_reached(); - } - } - else if (type1 == STTYPE_RANGE) { - hfinfo1 = sttype_range_hfinfo(st_arg1); - ftype1 = hfinfo1->type; - if (!ftype_can_slice(ftype1)) { - dfilter_fail("\"%s\" is a %s and cannot be sliced into a sequence of bytes.", - hfinfo1->abbrev, ftype_pretty_name(ftype1)); + new_st = stnode_new(STTYPE_FVALUE, fvalue); + sttype_test_set2_args(st_node, new_st, st_arg2); + stnode_free(st_arg1); + } + else if (type2 == STTYPE_STRING) { + /* Well now that's silly... */ + dfilter_fail("Neither \"%s\" nor \"%s\" are field or protocol names.", + stnode_data(st_arg1), + stnode_data(st_arg2)); + THROW(TypeError); + } + else if (type2 == STTYPE_RANGE) { + s = stnode_data(st_arg1); + fvalue = fvalue_from_string(FT_BYTES, s, dfilter_fail); + if (!fvalue) { THROW(TypeError); } + new_st = stnode_new(STTYPE_FVALUE, fvalue); + sttype_test_set2_args(st_node, new_st, st_arg2); + stnode_free(st_arg1); + } + else { + g_assert_not_reached(); + } +} +static void +check_relation_LHS_RANGE(dfwork_t *dfw, FtypeCanFunc can_func, stnode_t *st_node, + stnode_t *st_arg1, stnode_t *st_arg2) +{ + stnode_t *new_st; + sttype_id_t type1, type2; + header_field_info *hfinfo1, *hfinfo2; + ftenum_t ftype1, ftype2; + fvalue_t *fvalue; + char *s; + drange_node *rn; - if (type2 == STTYPE_FIELD) { - hfinfo2 = sttype_range_hfinfo(st_arg2); - ftype2 = hfinfo2->type; + type1 = stnode_type_id(st_arg1); + type2 = stnode_type_id(st_arg2); + hfinfo1 = sttype_range_hfinfo(st_arg1); + ftype1 = hfinfo1->type; - if (!is_bytes_type(ftype2)) { - if (!ftype_can_slice(ftype2)) { - dfilter_fail("\"%s\" is a %s and cannot be converted into a sequence of bytes.", - hfinfo2->abbrev, - ftype_pretty_name(ftype2)); - THROW(TypeError); - } + if (!ftype_can_slice(ftype1)) { + dfilter_fail("\"%s\" is a %s and cannot be sliced into a sequence of bytes.", + hfinfo1->abbrev, ftype_pretty_name(ftype1)); + THROW(TypeError); + } - /* Convert entire field to bytes */ - new_st = stnode_new(STTYPE_RANGE, NULL); - /* st_arg2 is freed in this step */ - sttype_range_set(new_st, st_arg2, NULL, NULL); + if (type2 == STTYPE_FIELD) { + hfinfo2 = sttype_range_hfinfo(st_arg2); + ftype2 = hfinfo2->type; - sttype_test_set2_args(st_node, st_arg1, new_st); - } - } - else if (type2 == STTYPE_STRING) { - s = stnode_data(st_arg2); - fvalue = fvalue_from_string(FT_BYTES, s, dfilter_fail); - if (!fvalue) { + if (!is_bytes_type(ftype2)) { + if (!ftype_can_slice(ftype2)) { + dfilter_fail("\"%s\" is a %s and cannot be converted into a sequence of bytes.", + hfinfo2->abbrev, + ftype_pretty_name(ftype2)); THROW(TypeError); } - new_st = stnode_new(STTYPE_FVALUE, fvalue); + + /* Convert entire field to bytes */ + new_st = stnode_new(STTYPE_RANGE, NULL); + + rn = drange_node_new(); + drange_node_set_offset(rn, 0); + drange_node_set_to_the_end(rn, TRUE); + /* st_arg2 is freed in this step */ + sttype_range_set1(new_st, st_arg2, rn); + sttype_test_set2_args(st_node, st_arg1, new_st); - stnode_free(st_arg2); - } - else if (type2 == STTYPE_RANGE) { - /* XXX - check lengths of both ranges */ } - else { - g_assert_not_reached(); + } + else if (type2 == STTYPE_STRING) { + s = stnode_data(st_arg2); + fvalue = fvalue_from_string(FT_BYTES, s, dfilter_fail); + if (!fvalue) { + THROW(TypeError); } + new_st = stnode_new(STTYPE_FVALUE, fvalue); + sttype_test_set2_args(st_node, st_arg1, new_st); + stnode_free(st_arg2); + } + else if (type2 == STTYPE_RANGE) { + /* XXX - check lengths of both ranges */ } else { g_assert_not_reached(); } } + +static void +check_relation(dfwork_t *dfw, FtypeCanFunc can_func, stnode_t *st_node, + stnode_t *st_arg1, stnode_t *st_arg2) +{ + switch (stnode_type_id(st_arg1)) { + case STTYPE_FIELD: + check_relation_LHS_FIELD(dfw, can_func, st_node, st_arg1, st_arg2); + break; + case STTYPE_STRING: + check_relation_LHS_STRING(dfw, can_func, st_node, st_arg1, st_arg2); + break; + case STTYPE_RANGE: + check_relation_LHS_RANGE(dfw, can_func, st_node, st_arg1, st_arg2); + break; + + case STTYPE_UNINITIALIZED: + case STTYPE_TEST: + case STTYPE_INTEGER: + case STTYPE_FVALUE: + case STTYPE_NUM_TYPES: + g_assert_not_reached(); + } +} + static void check_test(dfwork_t *dfw, stnode_t *st_node) { diff --git a/epan/dfilter/sttype-integer.c b/epan/dfilter/sttype-integer.c new file mode 100644 index 0000000000..68ac0db987 --- /dev/null +++ b/epan/dfilter/sttype-integer.c @@ -0,0 +1,42 @@ +/* + * $Id: sttype-integer.c,v 1.1 2001/02/27 19:23:28 gram Exp $ + * + * Ethereal - Network traffic analyzer + * By Gerald Combs <gerald@zing.org> + * Copyright 2001 Gerald Combs + * + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + */ + +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + +#include "ftypes/ftypes.h" +#include "syntax-tree.h" + +void +sttype_register_integer(void) +{ + static sttype_t integer_type = { + STTYPE_INTEGER, + "INTEGER", + NULL, + NULL, + }; + + sttype_register(&integer_type); +} diff --git a/epan/dfilter/sttype-range.c b/epan/dfilter/sttype-range.c index e21e52a99d..1195223eb1 100644 --- a/epan/dfilter/sttype-range.c +++ b/epan/dfilter/sttype-range.c @@ -1,5 +1,5 @@ /* - * $Id: sttype-range.c,v 1.2 2001/02/01 20:31:18 gram Exp $ + * $Id: sttype-range.c,v 1.3 2001/02/27 19:23:28 gram Exp $ * * Ethereal - Network traffic analyzer * By Gerald Combs <gerald@zing.org> @@ -30,18 +30,16 @@ #include "config.h" #endif -#include <stdlib.h> -#include <errno.h> +#include <glib.h> + #include "proto.h" +#include "drange.h" #include "sttype-range.h" typedef struct { guint32 magic; header_field_info *hfinfo; - gint start; - gint end; - char *start_error; - char *end_error; + drange *drange; } range_t; #define RANGE_MAGIC 0xec0990ce @@ -57,10 +55,7 @@ range_new(gpointer junk) range->magic = RANGE_MAGIC; range->hfinfo = NULL; - range->start = 0; - range->end = -1; - range->start_error = NULL; - range->end_error = NULL; + range->drange = NULL; return (gpointer) range; } @@ -71,38 +66,29 @@ range_free(gpointer value) range_t *range = value; assert_magic(range, RANGE_MAGIC); - if (range->start_error) - g_free(range->start_error); - if (range->end_error) - g_free(range->end_error); + if (range->drange) + drange_free(range->drange); g_free(range); } -static gint -string_to_gint(char *s, gboolean *success) +void +sttype_range_remove_drange(stnode_t *node) { - char *endptr; - gint val; - - *success = TRUE; - val = strtol(s, &endptr, 0); + range_t *range; - if (endptr == s || *endptr != '\0') { - *success = FALSE; - } - else if (errno == ERANGE) { - *success = FALSE; - } + range = stnode_data(node); + assert_magic(range, RANGE_MAGIC); - return val; + range->drange = NULL; } -static void -range_set(stnode_t *node, stnode_t *field, char *start, char *end) + +/* Set a range */ +void +sttype_range_set(stnode_t *node, stnode_t *field, GSList* drange_list) { range_t *range; - gboolean success; range = stnode_data(node); assert_magic(range, RANGE_MAGIC); @@ -110,75 +96,17 @@ range_set(stnode_t *node, stnode_t *field, char *start, char *end) range->hfinfo = stnode_data(field); stnode_free(field); - if (start) { - range->start = string_to_gint(start, &success); - if (!success) { - /* Save the error-causing string for later reporting */ - range->start_error = g_strdup(start); - } - } - else { - range->start = 0; - } - - if (end) { - range->end = string_to_gint(end, &success); - - if (!success) { - /* Save the error-causing string for later reporting */ - range->end_error = g_strdup(end); - } - } - else { - range->end = G_MAXINT; - } + range->drange = drange_new_from_list(drange_list); } void -sttype_range_set(stnode_t *node, stnode_t *field, stnode_t *start, stnode_t *end) +sttype_range_set1(stnode_t *node, stnode_t *field, drange_node *rn) { - char *start_str, *end_str; - - if (start) { - start_str = stnode_data(start); - } - else { - start_str = NULL; - } - - if (end) { - end_str = stnode_data(end); - } - else { - end_str = NULL; - } - - range_set(node, field, start_str, end_str); - - if (start) - stnode_free(start); - if (end) - stnode_free(end); + sttype_range_set(node, field, g_slist_append(NULL, rn)); } -void -sttype_range_set1(stnode_t *node, stnode_t *field, stnode_t *offset) -{ - char *offset_str; - - g_assert(offset); - - offset_str = stnode_data(offset); - range_set(node, field, offset_str, "1"); - stnode_free(offset); -} - - STTYPE_ACCESSOR(header_field_info*, range, hfinfo, RANGE_MAGIC) -STTYPE_ACCESSOR(gint, range, start, RANGE_MAGIC) -STTYPE_ACCESSOR(gint, range, end, RANGE_MAGIC) -STTYPE_ACCESSOR(char*, range, start_error, RANGE_MAGIC) -STTYPE_ACCESSOR(char*, range, end_error, RANGE_MAGIC) +STTYPE_ACCESSOR(drange*, range, drange, RANGE_MAGIC) void diff --git a/epan/dfilter/sttype-range.h b/epan/dfilter/sttype-range.h index 34b654f4e9..b5d91f1cac 100644 --- a/epan/dfilter/sttype-range.h +++ b/epan/dfilter/sttype-range.h @@ -1,5 +1,5 @@ /* - * $Id: sttype-range.h,v 1.2 2001/02/01 20:31:18 gram Exp $ + * $Id: sttype-range.h,v 1.3 2001/02/27 19:23:28 gram Exp $ * * Ethereal - Network traffic analyzer * By Gerald Combs <gerald@zing.org> @@ -25,19 +25,21 @@ #define STTYPE_RANGE_H #include "syntax-tree.h" +#include "drange.h" STTYPE_ACCESSOR_PROTOTYPE(header_field_info*, range, hfinfo) -STTYPE_ACCESSOR_PROTOTYPE(gint, range, start) -STTYPE_ACCESSOR_PROTOTYPE(gint, range, end) -STTYPE_ACCESSOR_PROTOTYPE(char*, range, start_error) -STTYPE_ACCESSOR_PROTOTYPE(char*, range, end_error) +STTYPE_ACCESSOR_PROTOTYPE(drange*, range, drange) -/* Set a range, [x:y], [:y], [x:] */ +/* Set a range */ void -sttype_range_set(stnode_t *node, stnode_t *field, stnode_t *start, stnode_t *end); +sttype_range_set(stnode_t *node, stnode_t *field, GSList* drange_list); -/* Set a single-byte lookup, [x] */ void -sttype_range_set1(stnode_t *node, stnode_t *field, stnode_t *offset); +sttype_range_set1(stnode_t *node, stnode_t *field, drange_node *rn); + +/* Clear the 'drange' variable to remove responsibility for + * freeing it. */ +void +sttype_range_remove_drange(stnode_t *node); #endif diff --git a/epan/dfilter/syntax-tree.c b/epan/dfilter/syntax-tree.c index cbe85ba3fb..dafe440cc9 100644 --- a/epan/dfilter/syntax-tree.c +++ b/epan/dfilter/syntax-tree.c @@ -1,5 +1,5 @@ /* - * $Id: syntax-tree.c,v 1.2 2001/02/01 20:31:18 gram Exp $ + * $Id: syntax-tree.c,v 1.3 2001/02/27 19:23:28 gram Exp $ * * Ethereal - Network traffic analyzer * By Gerald Combs <gerald@zing.org> @@ -31,6 +31,7 @@ static sttype_t* type_list[STTYPE_NUM_TYPES]; /* These are the sttype_t registration function prototypes. */ +void sttype_register_integer(void); void sttype_register_pointer(void); void sttype_register_range(void); void sttype_register_string(void); @@ -43,6 +44,7 @@ void sttype_register_test(void); void sttype_init(void) { + sttype_register_integer(); sttype_register_pointer(); sttype_register_range(); sttype_register_string(); @@ -141,6 +143,13 @@ stnode_init(stnode_t *node, sttype_id_t type_id, gpointer data) } void +stnode_init_int(stnode_t *node, sttype_id_t type_id, guint32 value) +{ + stnode_init(node, type_id, NULL); + node->value = value; +} + +void stnode_free(stnode_t *node) { assert_magic(node, STNODE_MAGIC); @@ -179,8 +188,12 @@ gpointer stnode_data(stnode_t *node) { assert_magic(node, STNODE_MAGIC); - if (node) - return node->data; - else - return NULL; + return node->data; +} + +guint32 +stnode_value(stnode_t *node) +{ + assert_magic(node, STNODE_MAGIC); + return node->value; } diff --git a/epan/dfilter/syntax-tree.h b/epan/dfilter/syntax-tree.h index 13a77024d6..d496d25e84 100644 --- a/epan/dfilter/syntax-tree.h +++ b/epan/dfilter/syntax-tree.h @@ -1,5 +1,5 @@ /* - * $Id: syntax-tree.h,v 1.2 2001/02/01 20:31:18 gram Exp $ + * $Id: syntax-tree.h,v 1.3 2001/02/27 19:23:28 gram Exp $ * * Ethereal - Network traffic analyzer * By Gerald Combs <gerald@zing.org> @@ -33,6 +33,7 @@ typedef enum { STTYPE_STRING, STTYPE_FIELD, STTYPE_FVALUE, + STTYPE_INTEGER, STTYPE_RANGE, STTYPE_NUM_TYPES } sttype_id_t; @@ -53,8 +54,11 @@ typedef struct { typedef struct { guint32 magic; sttype_t *type; - gpointer data; + /* This could be made an enum, but I haven't + * set aside to time to do so. */ + gpointer data; + guint32 value; } stnode_t; void @@ -73,6 +77,9 @@ void stnode_init(stnode_t *node, sttype_id_t type_id, gpointer data); void +stnode_init_int(stnode_t *node, sttype_id_t type_id, guint32 value); + +void stnode_free(stnode_t *node); const char* @@ -84,6 +91,9 @@ stnode_type_id(stnode_t *node); gpointer stnode_data(stnode_t *node); +guint32 +stnode_value(stnode_t *node); + #define assert_magic(obj, mnum) \ g_assert((obj)); \ if ((obj)->magic != (mnum)) { \ diff --git a/epan/ftypes/ftypes-int.h b/epan/ftypes/ftypes-int.h index 2f9ef399c6..88dcab7d1a 100644 --- a/epan/ftypes/ftypes-int.h +++ b/epan/ftypes/ftypes-int.h @@ -1,5 +1,5 @@ /* - * $Id: ftypes-int.h,v 1.2 2001/02/01 20:31:21 gram Exp $ + * $Id: ftypes-int.h,v 1.3 2001/02/27 19:23:30 gram Exp $ * * Ethereal - Network traffic analyzer * By Gerald Combs <gerald@zing.org> @@ -44,7 +44,7 @@ typedef double (*FvalueGetFloatingFunc)(fvalue_t*); typedef gboolean (*FvalueCmp)(fvalue_t*, fvalue_t*); typedef guint (*FvalueLen)(fvalue_t*); -typedef void (*FvalueSlice)(fvalue_t*, GByteArray *, guint, guint); +typedef void (*FvalueSlice)(fvalue_t*, GByteArray *, guint offset, guint length); struct _ftype_t { const char *name; diff --git a/epan/ftypes/ftypes.c b/epan/ftypes/ftypes.c index 109104f249..3c1ea35b68 100644 --- a/epan/ftypes/ftypes.c +++ b/epan/ftypes/ftypes.c @@ -1,5 +1,5 @@ /* - * $Id: ftypes.c,v 1.2 2001/02/01 20:31:21 gram Exp $ + * $Id: ftypes.c,v 1.3 2001/02/27 19:23:30 gram Exp $ * * Ethereal - Network traffic analyzer * By Gerald Combs <gerald@zing.org> @@ -274,68 +274,94 @@ fvalue_length(fvalue_t *fv) return fv->ftype->wire_size; } -/* Returns a new FT_BYTES fvalue_t* if possible, otherwise NULL */ -fvalue_t* -fvalue_slice(fvalue_t *fv, gint start, gint end) -{ +typedef struct { + fvalue_t *fv; GByteArray *bytes; - guint data_length, abs_end; - guint offset=0, length=0; - fvalue_t *new_fv; + gboolean slice_failure; +} slice_data_t; + +static void +slice_func(gpointer data, gpointer user_data) +{ + drange_node *drnode = data; + slice_data_t *slice_data = user_data; + gint offset; + gint length; + guint field_length; + guint end_offset; + gboolean to_end; + fvalue_t *fv; - if (!fv->ftype->slice) { - return NULL; + if (slice_data->slice_failure) { + return; } - data_length = fvalue_length(fv); - bytes = g_byte_array_new(); + offset = drange_node_get_offset(drnode); + length = drange_node_get_length(drnode); + to_end = drange_node_get_to_the_end(drnode); - /* Find absolute start position (offset) */ - if (start < 0) { - start = data_length + start; - if (start < 0) { - offset = 0; - } - else { - offset = start; - } - } - else { - offset = start; - } + fv = slice_data->fv; + field_length = fvalue_length(fv); - /* Limit the offset value */ - if (offset > data_length) { - offset = data_length; +/* g_debug("field_length=%u offset=%d length=%d", + field_length, offset, length);*/ + + if (offset < 0) { + offset = field_length + offset; } - /* Find absolute end position (abs_end) */ - if (end < 0) { - end = data_length + end; - if (end < 0) { - abs_end = 0; + if (to_end) { + end_offset = field_length; + length = end_offset - offset; + } + else { + if (length < 0) { + end_offset = field_length + length; + if (end_offset >= offset) { + length = end_offset - offset; + } + else { + length = 0; + } } else { - abs_end = end; + end_offset = offset + length; } } - else { - abs_end = end; - } - /* Limit the abs_end value */ - if (abs_end > data_length) { - abs_end = data_length; - } - /* Does end position occur *after* start position? */ - if (abs_end > offset) { - length = abs_end - offset; - fv->ftype->slice(fv, bytes, offset, length); +/* g_debug("\t\t(NEW) offset=%d length=%d", + offset, length);*/ + + if (offset > field_length || end_offset > field_length) { + slice_data->slice_failure = TRUE; + return; } + fv->ftype->slice(fv, slice_data->bytes, offset, length); +} + + +/* Returns a new FT_BYTES fvalue_t* if possible, otherwise NULL */ +fvalue_t* +fvalue_slice(fvalue_t *fv, drange *drange) +{ + slice_data_t slice_data; + fvalue_t *new_fv; + + slice_data.fv = fv; + slice_data.bytes = g_byte_array_new(); + slice_data.slice_failure = FALSE; + + /* XXX - We could make some optimizations here based on + * drange_has_total_length() and + * drange_get_max_offset(). + */ + + drange_foreach_drange_node(drange, slice_func, &slice_data); + new_fv = fvalue_new(FT_BYTES); - fvalue_set(new_fv, bytes, TRUE); + fvalue_set(new_fv, slice_data.bytes, TRUE); return new_fv; } diff --git a/epan/ftypes/ftypes.h b/epan/ftypes/ftypes.h index 1431f35427..41d2c5f313 100644 --- a/epan/ftypes/ftypes.h +++ b/epan/ftypes/ftypes.h @@ -1,7 +1,7 @@ /* ftypes.h * Definitions for field types * - * $Id: ftypes.h,v 1.1 2001/02/01 20:21:19 gram Exp $ + * $Id: ftypes.h,v 1.2 2001/02/27 19:23:30 gram Exp $ * * Ethereal - Network traffic analyzer * By Gerald Combs <gerald@zing.org> @@ -121,6 +121,7 @@ ftype_can_le(enum ftenum ftype); #endif #include "tvbuff.h" +#include "dfilter/drange.h" typedef struct { ftype_t *ftype; @@ -192,6 +193,6 @@ guint fvalue_length(fvalue_t *fv); fvalue_t* -fvalue_slice(fvalue_t *fv, gint start, gint end); +fvalue_slice(fvalue_t *fv, drange *drange); #endif /* ftypes.h */ |