use proto_tree_add_item() for IPv6 header, to allow filtering like below
[obnox/wireshark/wip.git] / dfilter-scanner.l
1 %{
2
3 /* dfilter-scanner.l
4  * Scanner for display filters
5  *
6  * $Id: dfilter-scanner.l,v 1.21 1999/10/15 04:22:47 itojun Exp $
7  *
8  * Ethereal - Network traffic analyzer
9  * By Gerald Combs <gerald@zing.org>
10  * Copyright 1998 Gerald Combs
11  *
12  * 
13  * This program is free software; you can redistribute it and/or
14  * modify it under the terms of the GNU General Public License
15  * as published by the Free Software Foundation; either version 2
16  * of the License, or (at your option) any later version.
17  * 
18  * This program is distributed in the hope that it will be useful,
19  * but WITHOUT ANY WARRANTY; without even the implied warranty of
20  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
21  * GNU General Public License for more details.
22  * 
23  * You should have received a copy of the GNU General Public License
24  * along with this program; if not, write to the Free Software
25  * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
26  */
27
28 #ifdef HAVE_CONFIG_H
29 # include "config.h"
30 #endif
31
32 #ifdef HAVE_SYS_TYPES_H
33 # include <sys/types.h>
34 #endif
35
36 #ifndef _STDIO_H
37 #include <stdio.h>
38 #endif
39
40 #ifndef _STRING_H
41 #include <string.h>
42 #endif
43
44 #ifndef __G_LIB_H__
45 #include <glib.h>
46 #endif
47
48 #ifndef __PROTO_H__
49 #include "proto.h"
50 #endif
51
52 #ifndef __DFILTER_H__
53 #include "dfilter.h"
54 #endif
55
56 #include "dfilter-int.h"
57
58 #include "dfilter-grammar.h"
59
60 /* Flex has a few routines which help us get the scanner to read
61  * from a string rather than from a file. POSIX lex only provides
62  * for reading from a file; any method of reading from a string
63  * is inherently non-portable.  Besides reading from a string,
64  * we have to worry about resetting the scanner after a bad
65  * parse; this too is non-portable. Combine the reset with
66  * a string input, and you have major non-portability. I'll provide
67  * the routines for flex here. If you really want to modify the
68  * scanner and use a non-flex lex implementation, you may
69  * add more ifdef's below.
70  */
71 #ifdef FLEX_SCANNER
72
73 /* Flex has built-in support for using a string as an input source
74  * instead of using a file. Nice!
75  */
76 YY_BUFFER_STATE string_input_buffer;
77
78 #else
79
80 static char *in_buffer;
81 #undef getc
82 #define getc(fp)  (*in_buffer == 0 ? EOF : *in_buffer++)
83
84 #endif
85
86 %}
87
88 whitespace      [\t ]
89 hex             [A-Fa-f0-9]{1,2}
90 hexsep          [-:\.]
91 minus           [-]
92
93 %%
94
95 [\t\n ]+        /* ignore whitespace */
96
97
98 and|\&\&        { dfilter_lval.operand = TOK_AND; return TOK_AND; }
99 or|\|\|         { dfilter_lval.operand = TOK_OR; return TOK_OR; }
100 not|\!          { dfilter_lval.operand = TOK_NOT; return TOK_NOT; }
101 xor|\^\^        { dfilter_lval.operand = TOK_XOR; return TOK_XOR; }
102 eq|\=\=         { dfilter_lval.operand = TOK_EQ; return TOK_EQ; }
103 ne|\!\=         { dfilter_lval.operand = TOK_NE; return TOK_NE; }
104 gt|\>           { dfilter_lval.operand = TOK_GT; return TOK_GT; }
105 ge|\>\=         { dfilter_lval.operand = TOK_GE; return TOK_GE; }
106 lt|\<           { dfilter_lval.operand = TOK_LT; return TOK_LT; }
107 le|\<\=         { dfilter_lval.operand = TOK_LE; return TOK_LE; }
108
109 \[{whitespace}*-?[0-9]+{whitespace}*:{whitespace}*[0-9]+{whitespace}*\] { /* range [ x : y ] */
110
111         char    *byterange_string = g_strdup(yytext);
112         char    *s = byterange_string + 1; /* I don't want the first '[' */
113         char    *p;
114
115         /* Get the offset from the string */
116         if ((p = strtok(s, ":"))) {
117                 dfilter_lval.byte_range.offset = strtol(p, NULL, 10);
118         }
119         else {
120                 g_free(byterange_string);
121                 return 0;
122         }
123
124         /* Get the Length from the string */
125         if ((p = strtok(NULL, "]"))) {
126                 dfilter_lval.byte_range.length = strtoul(p, NULL, 10);
127         }
128         else {
129                 g_free(byterange_string);
130                 return 0;
131         }
132         g_free(byterange_string);
133         return T_VAL_BYTE_RANGE;
134 }
135
136 \[{whitespace}*-?[0-9]+{whitespace}*\] { /* range [ x  ] */
137
138         char    *byterange_string = g_strdup(yytext);
139         char    *s = byterange_string + 1; /* I don't want the first '[' */
140         char    *p;
141
142         /* Get the offset from the string */
143         if ((p = strtok(s, "]"))) {
144                 dfilter_lval.byte_range.offset = strtol(p, NULL, 10);
145         }
146         else {
147                 g_free(byterange_string);
148                 return 0;
149         }
150
151         dfilter_lval.byte_range.length = 0;
152         g_free(byterange_string);
153         return T_VAL_BYTE_RANGE;
154 }
155
156 {hex}({hexsep}{hex})+ {                 /* byte string, any length */
157         dfilter_lval.string = g_strdup(yytext);
158         return T_VAL_BYTE_STRING;
159 }
160
161
162 [A-Za-z0-9\:][A-Za-z0-9\.\_\-\:]+ {
163         /* looks like a protocol, field name, or hostname */
164
165         int retval = 0;
166         enum ftenum ftype;
167         dfilter_lval.variable.id = dfilter_lookup_token(yytext);
168         if (dfilter_lval.variable.id < 0) {
169                 dfilter_lval.string = g_strdup(yytext);
170                 return T_VAL_UNQUOTED_STRING;
171         }
172         
173         ftype = proto_registrar_get_ftype(dfilter_lval.variable.id);
174         switch (ftype) {
175                 case FT_NONE:
176                         retval = T_FT_NONE;
177                         break;
178                 case FT_BOOLEAN:
179                         retval = T_FT_BOOLEAN;
180                         break;
181                 case FT_UINT8:
182                         retval = T_FT_UINT8;
183                         break;
184                 case FT_UINT16:
185                         retval = T_FT_UINT16;
186                         break;
187                 case FT_UINT32:
188                         retval = T_FT_UINT32;
189                         break;
190                 case FT_INT8:
191                         retval = T_FT_INT8;
192                         break;
193                 case FT_INT16:
194                         retval = T_FT_INT16;
195                         break;
196                 case FT_INT32:
197                         retval = T_FT_INT32;
198                         break;
199                 case FT_DOUBLE:
200                         dfilter_fail("Sorry, you can't filter on field \"%s\", as we don't yet support filtering on floating-point values.",
201                             yytext);
202                         retval = 0;
203                         break;
204                 case FT_ABSOLUTE_TIME:
205                         dfilter_fail("Sorry, you can't filter on field \"%s\", as we don't yet support filtering on time-of-day values.",
206                             yytext);
207                         retval = 0;
208                         break;
209                 case FT_RELATIVE_TIME:
210                         dfilter_fail("Sorry, you can't filter on field \"%s\", as we don't yet support filtering on time-delta values.",
211                             yytext);
212                         retval = 0;
213                         break;
214                 case FT_STRING:
215                         dfilter_fail("Sorry, you can't filter on field \"%s\", as we don't yet support filtering on string values.",
216                             yytext);
217                         retval = 0;
218                         break;
219                 case FT_ETHER:
220                         retval = T_FT_ETHER;
221                         break;
222                 case FT_BYTES:
223                         retval = T_FT_BYTES;
224                         break;
225                 case FT_IPv4:
226                         retval = T_FT_IPv4;
227                         break;
228                 case FT_IPv6:
229                         retval = T_FT_IPv6;
230                         break;
231                 case FT_IPXNET:
232                         retval = T_FT_IPXNET;
233                         break;
234                 default:
235                         printf("ftype for %s is %d\n", yytext, ftype);
236                         g_assert_not_reached();
237                         retval = 0;
238                         break;
239         }
240         dfilter_lval.variable.type = retval;
241         return retval;
242 }
243
244 {minus}?[0-9]+ {                                /* decimal or octal values */
245         dfilter_lval.string = g_strdup(yytext);
246         return T_VAL_NUMBER_STRING;
247 }
248
249
250 0[xX][A-Fa-f0-9]+ {                     /* hex values */
251         dfilter_lval.string = g_strdup(yytext);
252         return T_VAL_NUMBER_STRING;
253 }
254
255 [0-9\:\.]+ {
256         dfilter_lval.string = g_strdup(yytext);
257         return T_VAL_UNQUOTED_STRING;
258 }
259
260 .       return yytext[0];
261 %%
262
263 /* Resets scanner and assigns the char* argument
264  * as the text to scan
265  */
266 void
267 dfilter_scanner_text(char *text)
268 {
269 #ifdef FLEX_SCANNER
270         string_input_buffer = yy_scan_string(text);
271 #else
272         in_buffer = text;
273 #endif
274 }
275
276 void
277 dfilter_scanner_cleanup(void)
278 {
279 #ifdef FLEX_SCANNER
280         yy_delete_buffer(string_input_buffer);
281 #else
282         /* There is no standard way to reset a lex scanner.
283          * This is necessary after a failed parse on a syntactically
284          * incorrect display filter. You have to reset the scanner
285          * so that yy_lex() doesn't start scanning from the middle
286          * of the previous input string.
287          */
288 #endif
289 }
290
291 /* Flex has an option '%option noyywrap' so that I don't have to
292  * provide this yywrap function, but in order to maintain portability,
293  * I'll just use this yywrap() function.
294  */
295 int
296 yywrap()
297 {
298         return 1; /* stop at EOF, instead of looking for next file */
299 }
300
301 /* converts a string representing a byte array
302  * to a guint8 array.
303  *
304  * Returns a non-null GByteArray pointer on success, NULL on failure.
305  */
306 GByteArray*
307 byte_str_to_guint8_array(const char *s)
308 {
309         GByteArray      *barray;
310         guint8          val;
311         char            *byte_str = g_strdup(s); /* local copy of string */
312         char            *p, *str;
313
314         barray = g_byte_array_new();
315         /* XXX - don't use global_df, but pass in pointer to GSList* */
316         global_df->list_of_byte_arrays = g_slist_append(global_df->list_of_byte_arrays, barray);
317
318         byte_str = g_strdup(s);
319         str = byte_str;
320         while ((p = strtok(str, "-:."))) {
321                 val = (guint8) strtoul(p, NULL, 16);
322                 g_byte_array_append(barray, &val, 1);
323
324                 /* subsequent calls to strtok() require NULL as arg 1 */
325                 str = NULL;
326         }
327
328         g_free(byte_str);
329         return barray;
330 }