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