Give the IPX dissector dissector hash tables for the IPX type and socket
[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.30 2000/03/23 05:43:57 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 /* We don't need yyunput, so use this macro to get it out of the
83  * generated C file, avoiding a compiler warning about its lack of use */
84 #define YY_NO_UNPUT 1
85
86 #else
87
88 static char *in_buffer;
89 #undef getc
90 #define getc(fp)  (*in_buffer == 0 ? EOF : *in_buffer++)
91
92 #endif
93
94
95 %}
96
97 whitespace      [\t ]
98 hex             [A-Fa-f0-9]{1,2}
99 hexsep          [-:\.]
100 minus           [-]
101 plus            [+]
102
103 %%
104
105 [\t\n ]+        /* ignore whitespace */
106
107
108 and|\&\&        { dfilter_lval.operand = TOK_AND; return TOK_AND; }
109 or|\|\|         { dfilter_lval.operand = TOK_OR; return TOK_OR; }
110 not|\!          { dfilter_lval.operand = TOK_NOT; return TOK_NOT; }
111 xor|\^\^        { dfilter_lval.operand = TOK_XOR; return TOK_XOR; }
112 eq|\=\=         { dfilter_lval.operand = TOK_EQ; return TOK_EQ; }
113 ne|\!\=         { dfilter_lval.operand = TOK_NE; return TOK_NE; }
114 gt|\>           { dfilter_lval.operand = TOK_GT; return TOK_GT; }
115 ge|\>\=         { dfilter_lval.operand = TOK_GE; return TOK_GE; }
116 lt|\<           { dfilter_lval.operand = TOK_LT; return TOK_LT; }
117 le|\<\=         { dfilter_lval.operand = TOK_LE; return TOK_LE; }
118
119 \[{whitespace}*-?[0-9]+{whitespace}*:{whitespace}*[0-9]+{whitespace}*\] { /* range [ x : y ] */
120
121         char    *byterange_string = g_strdup(yytext);
122         char    *s = byterange_string + 1; /* I don't want the first '[' */
123         char    *p;
124
125         /* Get the offset from the string */
126         if ((p = strtok(s, ":"))) {
127                 dfilter_lval.byte_range.offset = strtol(p, NULL, 10);
128         }
129         else {
130                 g_free(byterange_string);
131                 return 0;
132         }
133
134         /* Get the Length from the string */
135         if ((p = strtok(NULL, "]"))) {
136                 dfilter_lval.byte_range.length = strtoul(p, NULL, 10);
137         }
138         else {
139                 g_free(byterange_string);
140                 return 0;
141         }
142         g_free(byterange_string);
143         return T_VAL_BYTE_RANGE;
144 }
145
146 \[{whitespace}*-?[0-9]+{whitespace}*\] { /* range [ x  ] */
147
148         char    *byterange_string = g_strdup(yytext);
149         char    *s = byterange_string + 1; /* I don't want the first '[' */
150         char    *p;
151
152         /* Get the offset from the string */
153         if ((p = strtok(s, "]"))) {
154                 dfilter_lval.byte_range.offset = strtol(p, NULL, 10);
155         }
156         else {
157                 g_free(byterange_string);
158                 return 0;
159         }
160
161         dfilter_lval.byte_range.length = 0;
162         g_free(byterange_string);
163         return T_VAL_BYTE_RANGE;
164 }
165
166 {hex}({hexsep}{hex})+ {                 /* byte string, any length */
167         dfilter_lval.string = g_strdup(yytext);
168         return T_VAL_BYTE_STRING;
169 }
170
171
172 0[xX][A-Fa-f0-9]+ {                     /* hex values */
173         dfilter_lval.string = g_strdup(yytext);
174         return T_VAL_UNQUOTED_STRING;
175 }
176
177 [A-Za-z0-9\:][A-Za-z0-9\.\_\-\:]+ {
178         /* looks like a protocol, field name, or hostname */
179
180         int retval = 0;
181         enum ftenum ftype;
182         dfilter_lval.variable.id = dfilter_lookup_token(yytext);
183         if (dfilter_lval.variable.id < 0) {
184                 dfilter_lval.string = g_strdup(yytext);
185                 return T_VAL_UNQUOTED_STRING;
186         }
187         
188         ftype = proto_registrar_get_ftype(dfilter_lval.variable.id);
189         switch (ftype) {
190                 case FT_NONE:
191                         retval = T_FT_NONE;
192                         break;
193                 case FT_BOOLEAN:
194                         retval = T_FT_BOOLEAN;
195                         break;
196                 case FT_UINT8:
197                         retval = T_FT_UINT8;
198                         break;
199                 case FT_UINT16:
200                         retval = T_FT_UINT16;
201                         break;
202                 case FT_UINT24:
203                         retval = T_FT_UINT24;
204                         break;
205                 case FT_UINT32:
206                         retval = T_FT_UINT32;
207                         break;
208                 case FT_INT8:
209                         retval = T_FT_INT8;
210                         break;
211                 case FT_INT16:
212                         retval = T_FT_INT16;
213                         break;
214                 case FT_INT24:
215                         retval = T_FT_INT24;
216                         break;
217                 case FT_INT32:
218                         retval = T_FT_INT32;
219                         break;
220                 case FT_DOUBLE:
221                         retval = T_FT_DOUBLE;
222                         break;
223                 case FT_ABSOLUTE_TIME:
224                         dfilter_fail("Sorry, you can't filter on field \"%s\", as we don't yet support filtering on time-of-day values.",
225                             yytext);
226                         retval = 0;
227                         break;
228                 case FT_RELATIVE_TIME:
229                         dfilter_fail("Sorry, you can't filter on field \"%s\", as we don't yet support filtering on time-delta values.",
230                             yytext);
231                         retval = 0;
232                         break;
233                 case FT_STRING:
234                         retval = T_FT_STRING;
235                         break;
236                 case FT_ETHER:
237                         retval = T_FT_ETHER;
238                         break;
239                 case FT_BYTES:
240                         retval = T_FT_BYTES;
241                         break;
242                 case FT_IPv4:
243                         retval = T_FT_IPv4;
244                         break;
245                 case FT_IPv6:
246                         retval = T_FT_IPv6;
247                         break;
248                 case FT_IPXNET:
249                         retval = T_FT_IPXNET;
250                         break;
251                 default:
252                         printf("ftype for %s is %d\n", yytext, ftype);
253                         g_assert_not_reached();
254                         retval = 0;
255                         break;
256         }
257         dfilter_lval.variable.type = retval;
258         return retval;
259 }
260
261 ({plus}|{minus})?[0-9]+ {                       /* decimal and octal integers */
262         dfilter_lval.string = g_strdup(yytext);
263         return T_VAL_UNQUOTED_STRING;
264 }
265
266 ({plus}|{minus})?([0-9]+|[0-9]+\.[0-9]+|\.[0-9]+)([eE]({plus}|{minus})?[0-9]+)? {
267         /* I'm trying to capture all floating points here, and
268          * am using the strtod manpage as the description of
269          * valid formats */
270         dfilter_lval.string = g_strdup(yytext);
271         return T_VAL_UNQUOTED_STRING;
272 }
273
274 [0-9\:\.]+ {
275         dfilter_lval.string = g_strdup(yytext);
276         return T_VAL_UNQUOTED_STRING;
277 }
278
279 .       return yytext[0];
280 %%
281
282 /* Resets scanner and assigns the char* argument
283  * as the text to scan
284  */
285 void
286 dfilter_scanner_text(char *text)
287 {
288 #ifdef FLEX_SCANNER
289         string_input_buffer = yy_scan_string(text);
290 #else
291         in_buffer = text;
292 #endif
293 }
294
295 void
296 dfilter_scanner_cleanup(void)
297 {
298 #ifdef FLEX_SCANNER
299         yy_delete_buffer(string_input_buffer);
300 #else
301         /* There is no standard way to reset a lex scanner.
302          * This is necessary after a failed parse on a syntactically
303          * incorrect display filter. You have to reset the scanner
304          * so that yy_lex() doesn't start scanning from the middle
305          * of the previous input string.
306          */
307 #endif
308 }
309
310 /* Flex has an option '%option noyywrap' so that I don't have to
311  * provide this yywrap function, but in order to maintain portability,
312  * I'll just use this yywrap() function.
313  */
314 int
315 yywrap()
316 {
317         return 1; /* stop at EOF, instead of looking for next file */
318 }
319
320 /* converts a string representing a byte array
321  * to a guint8 array.
322  *
323  * Returns a non-null GByteArray pointer on success, NULL on failure.
324  */
325 GByteArray*
326 byte_str_to_guint8_array(const char *s)
327 {
328         GByteArray      *barray;
329         guint8          val;
330         char            *byte_str;
331         char            *p, *str;
332
333         barray = g_byte_array_new();
334         /* XXX - don't use global_df, but pass in pointer to GSList* */
335         global_df->list_of_byte_arrays = g_slist_append(global_df->list_of_byte_arrays, barray);
336
337         /* Local copy of string, since strtok will munge it */
338         byte_str = g_strdup(s);
339         str = byte_str;
340         while ((p = strtok(str, "-:."))) {
341                 val = (guint8) strtoul(p, NULL, 16);
342                 g_byte_array_append(barray, &val, 1);
343
344                 /* subsequent calls to strtok() require NULL as arg 1 */
345                 str = NULL;
346         }
347
348         g_free(byte_str);
349         return barray;
350 }