1db3ae63b181f83f39b517994038040bc6d535b1
[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.16 1999/10/09 14:14:53 deniel 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
92 %%
93
94 [\t\n ]+        /* ignore whitespace */
95
96
97 and|\&\&        { dfilter_lval.operand = TOK_AND; return TOK_AND; }
98 or|\|\|         { dfilter_lval.operand = TOK_OR; return TOK_OR; }
99 not|\!          { dfilter_lval.operand = TOK_NOT; return TOK_NOT; }
100 xor|\^\^        { dfilter_lval.operand = TOK_XOR; return TOK_XOR; }
101 eq|\=\=         { dfilter_lval.operand = TOK_EQ; return TOK_EQ; }
102 ne|\!\=         { dfilter_lval.operand = TOK_NE; return TOK_NE; }
103 gt|\>           { dfilter_lval.operand = TOK_GT; return TOK_GT; }
104 ge|\>\=         { dfilter_lval.operand = TOK_GE; return TOK_GE; }
105 lt|\<           { dfilter_lval.operand = TOK_LT; return TOK_LT; }
106 le|\<\=         { dfilter_lval.operand = TOK_LE; return TOK_LE; }
107
108 \[{whitespace}*-?[0-9]+{whitespace}*:{whitespace}*[0-9]+{whitespace}*\] { /* range [ x : y ] */
109
110         char    *byterange_string = g_strdup(yytext);
111         char    *s = byterange_string + 1; /* I don't want the first '[' */
112         char    *p;
113
114         /* Get the offset from the string */
115         if ((p = strtok(s, ":"))) {
116                 dfilter_lval.byte_range.offset = strtol(p, NULL, 10);
117         }
118         else {
119                 g_free(byterange_string);
120                 return 0;
121         }
122
123         /* Get the Length from the string */
124         if ((p = strtok(NULL, "]"))) {
125                 dfilter_lval.byte_range.length = strtoul(p, NULL, 10);
126         }
127         else {
128                 g_free(byterange_string);
129                 return 0;
130         }
131         g_free(byterange_string);
132         return T_VAL_BYTE_RANGE;
133 }
134
135
136 {hex}({hexsep}{hex})+ {                 /* byte string, any length */
137         dfilter_lval.string = g_strdup(yytext);
138         return T_VAL_BYTE_STRING;
139 }
140
141
142 [A-Za-z][A-Za-z0-9\.\_\-]+      { /* looks like a protocol, field name, or hostname */
143
144         int retval = 0;
145         enum ftenum ftype;
146         dfilter_lval.variable.id = dfilter_lookup_token(yytext);
147         if (dfilter_lval.variable.id < 0) {
148                 dfilter_lval.string = g_strdup(yytext);
149                 return T_VAL_UNQUOTED_STRING;
150         }
151         
152         ftype = proto_registrar_get_ftype(dfilter_lval.variable.id);
153         switch (ftype) {
154                 case FT_NONE:
155                         retval = T_FT_NONE;
156                         break;
157                 case FT_BOOLEAN:
158                         retval = T_FT_BOOLEAN;
159                         break;
160                 case FT_UINT8:
161                 case FT_VALS_UINT8:
162                         retval = T_FT_UINT8;
163                         break;
164                 case FT_UINT16:
165                 case FT_VALS_UINT16:
166                         retval = T_FT_UINT16;
167                         break;
168                 case FT_UINT32:
169                 case FT_VALS_UINT32:
170                 case FT_VALS_UINT24:
171                         retval = T_FT_UINT32;
172                         break;
173                 case FT_DOUBLE:
174                         dfilter_error("sorry, we don't yet support filtering on floating-point values");
175                         retval = 0;
176                         break;
177                 case FT_ABSOLUTE_TIME:
178                         dfilter_error("sorry, we don't yet support filtering on time-of-day values");
179                         retval = 0;
180                         break;
181                 case FT_RELATIVE_TIME:
182                         dfilter_error("sorry, we don't yet support filtering on time-delta values");
183                         retval = 0;
184                         break;
185                 case FT_STRING:
186                         dfilter_error("sorry, we don't yet support filtering on string values");
187                         retval = 0;
188                         break;
189                 case FT_ETHER:
190                         retval = T_FT_ETHER;
191                         break;
192                 case FT_BYTES:
193                         retval = T_FT_BYTES;
194                         break;
195                 case FT_IPv4:
196                         retval = T_FT_IPv4;
197                         break;
198                 case FT_IPv6:
199                         dfilter_error("sorry, we don't yet support filtering on IPv6 addresses");
200                         retval = 0;
201                         break;
202                 case FT_IPXNET:
203                         retval = T_FT_IPXNET;
204                         break;
205                 default:
206                         g_assert_not_reached();
207                         retval = 0;
208                         break;
209         }
210         dfilter_lval.variable.type = retval;
211         return retval;
212 }
213
214 [0-9]+ {                                /* decimal or octal values */
215         dfilter_lval.string = g_strdup(yytext);
216         return T_VAL_NUMBER_STRING;
217 }
218
219
220 0[xX][A-Fa-f0-9]+ {                     /* hex values */
221         dfilter_lval.string = g_strdup(yytext);
222         return T_VAL_NUMBER_STRING;
223 }
224
225 [0-9\:\.]+ {
226         dfilter_lval.string = g_strdup(yytext);
227         return T_VAL_UNQUOTED_STRING;
228 }
229
230 .       return yytext[0];
231 %%
232
233 /* Resets scanner and assigns the char* argument
234  * as the text to scan
235  */
236 void
237 dfilter_scanner_text(char *text)
238 {
239 #ifdef FLEX_SCANNER
240         string_input_buffer = yy_scan_string(text);
241 #else
242         in_buffer = text;
243 #endif
244 }
245
246 void
247 dfilter_scanner_cleanup(void)
248 {
249 #ifdef FLEX_SCANNER
250         yy_delete_buffer(string_input_buffer);
251 #else
252         /* There is no standard way to reset a lex scanner.
253          * This is necessary after a failed parse on a syntactically
254          * incorrect display filter. You have to reset the scanner
255          * so that yy_lex() doesn't start scanning from the middle
256          * of the previous input string.
257          */
258 #endif
259 }
260
261 /* Flex has an option '%option noyywrap' so that I don't have to
262  * provide this yywrap function, but in order to maintain portability,
263  * I'll just use this yywrap() function.
264  */
265 int
266 yywrap()
267 {
268         return 1; /* stop at EOF, instead of looking for next file */
269 }
270
271 /* converts a string representing a byte array
272  * to a guint8 array.
273  *
274  * Returns a non-null GByteArray pointer on success, NULL on failure.
275  */
276 GByteArray*
277 byte_str_to_guint8_array(const char *s)
278 {
279         GByteArray      *barray;
280         guint8          val;
281         char            *byte_str = g_strdup(s); /* local copy of string */
282         char            *p, *str;
283
284         barray = g_byte_array_new();
285         /* XXX - don't use global_df, but pass in pointer to GSList* */
286         global_df->list_of_byte_arrays = g_slist_append(global_df->list_of_byte_arrays, barray);
287
288         byte_str = g_strdup(s);
289         str = byte_str;
290         while ((p = strtok(str, "-:."))) {
291                 val = (guint8) strtoul(p, NULL, 16);
292                 g_byte_array_append(barray, &val, 1);
293
294                 /* subsequent calls to strtok() require NULL as arg 1 */
295                 str = NULL;
296         }
297
298         g_free(byte_str);
299         return barray;
300 }