Have "get_host_ipaddr()" return a Boolean indicating whether it
[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.17 1999/10/11 03:03:10 guy 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_fail("Sorry, you can't filter on field \"%s\", as we don't yet support filtering on floating-point values.",
175                             yytext);
176                         retval = 0;
177                         break;
178                 case FT_ABSOLUTE_TIME:
179                         dfilter_fail("Sorry, you can't filter on field \"%s\", as we don't yet support filtering on time-of-day values.",
180                             yytext);
181                         retval = 0;
182                         break;
183                 case FT_RELATIVE_TIME:
184                         dfilter_fail("Sorry, you can't filter on field \"%s\", as we don't yet support filtering on time-delta values.",
185                             yytext);
186                         retval = 0;
187                         break;
188                 case FT_STRING:
189                         dfilter_fail("Sorry, you can't filter on field \"%s\", as we don't yet support filtering on string values.",
190                             yytext);
191                         retval = 0;
192                         break;
193                 case FT_ETHER:
194                         retval = T_FT_ETHER;
195                         break;
196                 case FT_BYTES:
197                         retval = T_FT_BYTES;
198                         break;
199                 case FT_IPv4:
200                         retval = T_FT_IPv4;
201                         break;
202                 case FT_IPv6:
203                         dfilter_fail("Sorry, you can't filter on field \"%s\", as we don't yet support filtering on IPv6 addresses.",
204                             yytext);
205                         retval = 0;
206                         break;
207                 case FT_IPXNET:
208                         retval = T_FT_IPXNET;
209                         break;
210                 default:
211                         g_assert_not_reached();
212                         retval = 0;
213                         break;
214         }
215         dfilter_lval.variable.type = retval;
216         return retval;
217 }
218
219 [0-9]+ {                                /* decimal or octal values */
220         dfilter_lval.string = g_strdup(yytext);
221         return T_VAL_NUMBER_STRING;
222 }
223
224
225 0[xX][A-Fa-f0-9]+ {                     /* hex values */
226         dfilter_lval.string = g_strdup(yytext);
227         return T_VAL_NUMBER_STRING;
228 }
229
230 [0-9\:\.]+ {
231         dfilter_lval.string = g_strdup(yytext);
232         return T_VAL_UNQUOTED_STRING;
233 }
234
235 .       return yytext[0];
236 %%
237
238 /* Resets scanner and assigns the char* argument
239  * as the text to scan
240  */
241 void
242 dfilter_scanner_text(char *text)
243 {
244 #ifdef FLEX_SCANNER
245         string_input_buffer = yy_scan_string(text);
246 #else
247         in_buffer = text;
248 #endif
249 }
250
251 void
252 dfilter_scanner_cleanup(void)
253 {
254 #ifdef FLEX_SCANNER
255         yy_delete_buffer(string_input_buffer);
256 #else
257         /* There is no standard way to reset a lex scanner.
258          * This is necessary after a failed parse on a syntactically
259          * incorrect display filter. You have to reset the scanner
260          * so that yy_lex() doesn't start scanning from the middle
261          * of the previous input string.
262          */
263 #endif
264 }
265
266 /* Flex has an option '%option noyywrap' so that I don't have to
267  * provide this yywrap function, but in order to maintain portability,
268  * I'll just use this yywrap() function.
269  */
270 int
271 yywrap()
272 {
273         return 1; /* stop at EOF, instead of looking for next file */
274 }
275
276 /* converts a string representing a byte array
277  * to a guint8 array.
278  *
279  * Returns a non-null GByteArray pointer on success, NULL on failure.
280  */
281 GByteArray*
282 byte_str_to_guint8_array(const char *s)
283 {
284         GByteArray      *barray;
285         guint8          val;
286         char            *byte_str = g_strdup(s); /* local copy of string */
287         char            *p, *str;
288
289         barray = g_byte_array_new();
290         /* XXX - don't use global_df, but pass in pointer to GSList* */
291         global_df->list_of_byte_arrays = g_slist_append(global_df->list_of_byte_arrays, barray);
292
293         byte_str = g_strdup(s);
294         str = byte_str;
295         while ((p = strtok(str, "-:."))) {
296                 val = (guint8) strtoul(p, NULL, 16);
297                 g_byte_array_append(barray, &val, 1);
298
299                 /* subsequent calls to strtok() require NULL as arg 1 */
300                 str = NULL;
301         }
302
303         g_free(byte_str);
304         return barray;
305 }