4 * Scanner for display filters
6 * $Id: dfilter-scanner.l,v 1.30 2000/03/23 05:43:57 gram Exp $
8 * Ethereal - Network traffic analyzer
9 * By Gerald Combs <gerald@zing.org>
10 * Copyright 1998 Gerald Combs
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.
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.
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.
33 #include <io.h> /* for isatty() on win32 */
36 #ifdef HAVE_SYS_TYPES_H
37 # include <sys/types.h>
60 #include "dfilter-int.h"
62 #include "dfilter-grammar.h"
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.
77 /* Flex has built-in support for using a string as an input source
78 * instead of using a file. Nice!
80 YY_BUFFER_STATE string_input_buffer;
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 */
88 static char *in_buffer;
90 #define getc(fp) (*in_buffer == 0 ? EOF : *in_buffer++)
105 [\t\n ]+ /* ignore whitespace */
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; }
119 \[{whitespace}*-?[0-9]+{whitespace}*:{whitespace}*[0-9]+{whitespace}*\] { /* range [ x : y ] */
121 char *byterange_string = g_strdup(yytext);
122 char *s = byterange_string + 1; /* I don't want the first '[' */
125 /* Get the offset from the string */
126 if ((p = strtok(s, ":"))) {
127 dfilter_lval.byte_range.offset = strtol(p, NULL, 10);
130 g_free(byterange_string);
134 /* Get the Length from the string */
135 if ((p = strtok(NULL, "]"))) {
136 dfilter_lval.byte_range.length = strtoul(p, NULL, 10);
139 g_free(byterange_string);
142 g_free(byterange_string);
143 return T_VAL_BYTE_RANGE;
146 \[{whitespace}*-?[0-9]+{whitespace}*\] { /* range [ x ] */
148 char *byterange_string = g_strdup(yytext);
149 char *s = byterange_string + 1; /* I don't want the first '[' */
152 /* Get the offset from the string */
153 if ((p = strtok(s, "]"))) {
154 dfilter_lval.byte_range.offset = strtol(p, NULL, 10);
157 g_free(byterange_string);
161 dfilter_lval.byte_range.length = 0;
162 g_free(byterange_string);
163 return T_VAL_BYTE_RANGE;
166 {hex}({hexsep}{hex})+ { /* byte string, any length */
167 dfilter_lval.string = g_strdup(yytext);
168 return T_VAL_BYTE_STRING;
172 0[xX][A-Fa-f0-9]+ { /* hex values */
173 dfilter_lval.string = g_strdup(yytext);
174 return T_VAL_UNQUOTED_STRING;
177 [A-Za-z0-9\:][A-Za-z0-9\.\_\-\:]+ {
178 /* looks like a protocol, field name, or hostname */
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;
188 ftype = proto_registrar_get_ftype(dfilter_lval.variable.id);
194 retval = T_FT_BOOLEAN;
200 retval = T_FT_UINT16;
203 retval = T_FT_UINT24;
206 retval = T_FT_UINT32;
221 retval = T_FT_DOUBLE;
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.",
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.",
234 retval = T_FT_STRING;
249 retval = T_FT_IPXNET;
252 printf("ftype for %s is %d\n", yytext, ftype);
253 g_assert_not_reached();
257 dfilter_lval.variable.type = retval;
261 ({plus}|{minus})?[0-9]+ { /* decimal and octal integers */
262 dfilter_lval.string = g_strdup(yytext);
263 return T_VAL_UNQUOTED_STRING;
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
270 dfilter_lval.string = g_strdup(yytext);
271 return T_VAL_UNQUOTED_STRING;
275 dfilter_lval.string = g_strdup(yytext);
276 return T_VAL_UNQUOTED_STRING;
282 /* Resets scanner and assigns the char* argument
283 * as the text to scan
286 dfilter_scanner_text(char *text)
289 string_input_buffer = yy_scan_string(text);
296 dfilter_scanner_cleanup(void)
299 yy_delete_buffer(string_input_buffer);
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.
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.
317 return 1; /* stop at EOF, instead of looking for next file */
320 /* converts a string representing a byte array
323 * Returns a non-null GByteArray pointer on success, NULL on failure.
326 byte_str_to_guint8_array(const char *s)
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);
337 /* Local copy of string, since strtok will munge it */
338 byte_str = g_strdup(s);
340 while ((p = strtok(str, "-:."))) {
341 val = (guint8) strtoul(p, NULL, 16);
342 g_byte_array_append(barray, &val, 1);
344 /* subsequent calls to strtok() require NULL as arg 1 */