2 * We don't use input, so don't generate code for it.
7 * We don't use unput, so don't generate code for it.
12 * We don't read from the terminal.
14 %option never-interactive
17 * Prefix scanner routines with "df_" rather than "yy", so this scanner
18 * can coexist with other scanners.
26 * Wireshark - Network traffic analyzer
27 * By Gerald Combs <gerald@wireshark.org>
28 * Copyright 2001 Gerald Combs
30 * This program is free software; you can redistribute it and/or
31 * modify it under the terms of the GNU General Public License
32 * as published by the Free Software Foundation; either version 2
33 * of the License, or (at your option) any later version.
35 * This program is distributed in the hope that it will be useful,
36 * but WITHOUT ANY WARRANTY; without even the implied warranty of
37 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
38 * GNU General Public License for more details.
40 * You should have received a copy of the GNU General Public License
41 * along with this program; if not, write to the Free Software
42 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
50 #include "dfilter-int.h"
51 #include "syntax-tree.h"
53 #include "dfunctions.h"
54 #include "scanner_lex.h"
57 /* disable Windows VC compiler warning "signed/unsigned mismatch" associated */
58 /* with YY_INPUT code generated by flex versions such as 2.5.35. */
59 #pragma warning (disable:4018)
63 #define LVAL_TYPE stnode_t*
64 #define LVAL_INIT_VAL NULL
66 #define FLEX_YY_PREFIX df_
68 #include <lemonflex-head.inc>
70 /*#undef YY_NO_UNPUT*/
72 static int set_lval(int token, gpointer data);
73 static int set_lval_int(int token, char *s);
74 static int simple(int token);
75 static gboolean str_to_gint32(char *s, gint32* pint);
76 GString* quoted_string = NULL;
77 static void mark_lval_deprecated(const char *s);
87 [[:blank:]\n]+ /* ignore whitespace */
91 "(" return simple(TOKEN_LPAREN);
92 ")" return simple(TOKEN_RPAREN);
93 "," return simple(TOKEN_COMMA);
95 "==" return simple(TOKEN_TEST_EQ);
96 "eq" return simple(TOKEN_TEST_EQ);
98 mark_lval_deprecated("!=");
99 return simple(TOKEN_TEST_NE);
102 mark_lval_deprecated("ne");
103 return simple(TOKEN_TEST_NE);
105 ">" return simple(TOKEN_TEST_GT);
106 "gt" return simple(TOKEN_TEST_GT);
107 ">=" return simple(TOKEN_TEST_GE);
108 "ge" return simple(TOKEN_TEST_GE);
109 "<" return simple(TOKEN_TEST_LT);
110 "lt" return simple(TOKEN_TEST_LT);
111 "<=" return simple(TOKEN_TEST_LE);
112 "le" return simple(TOKEN_TEST_LE);
113 "bitwise_and" return simple(TOKEN_TEST_BITWISE_AND);
114 "&" return simple(TOKEN_TEST_BITWISE_AND);
115 "contains" return simple(TOKEN_TEST_CONTAINS);
116 "~" return simple(TOKEN_TEST_MATCHES);
117 "matches" return simple(TOKEN_TEST_MATCHES);
118 "!" return simple(TOKEN_TEST_NOT);
119 "not" return simple(TOKEN_TEST_NOT);
120 "&&" return simple(TOKEN_TEST_AND);
121 "and" return simple(TOKEN_TEST_AND);
122 "||" return simple(TOKEN_TEST_OR);
123 "or" return simple(TOKEN_TEST_OR);
128 return simple(TOKEN_LBRACKET);
131 <RANGE_INT>[+-]?[[:digit:]]+ {
133 return set_lval_int(TOKEN_INTEGER, yytext);
136 <RANGE_INT>[+-]?0x[[:xdigit:]]+ {
138 return set_lval_int(TOKEN_INTEGER, yytext);
141 <RANGE_INT,RANGE_PUNCT>":" {
143 return simple(TOKEN_COLON);
148 return simple(TOKEN_HYPHEN);
151 <RANGE_INT,RANGE_PUNCT>"," {
153 return simple(TOKEN_COMMA);
156 <RANGE_INT,RANGE_PUNCT>"]" {
158 return simple(TOKEN_RBRACKET);
161 /* Error if none of the above while scanning a range (slice) */
163 <RANGE_PUNCT>[^:\-,\]]+ {
164 dfilter_fail("Invalid string \"%s\" found while scanning slice.", yytext);
168 /* XXX It would be nice to be able to match an entire non-integer string,
169 * but beware of Flex's "match the most text" rule.
173 dfilter_fail("Invalid character \"%s\" found while scanning slice; expected integer.", yytext);
179 /* The example of how to scan for strings was taken from
180 the flex 2.5.4 manual, from the section "Start Conditions".
182 http://www.gnu.org/software/flex/manual/html_node/flex_11.html */
185 /* A previous filter that failed to compile due to
186 a missing end quote will have left quoted_string set
187 to something. Clear it now that we are starting
188 a new quoted string. */
190 g_string_free(quoted_string, TRUE);
191 /* Don't set quoted_string to NULL, as we
192 do in other quoted_string-cleanup code, as we're
193 about to set it in the next line. */
195 quoted_string = g_string_new("");
199 /* unterminated string */
200 /* The example of how to handle unclosed strings was taken from
201 the flex 2.5.4 manual, from the section "End-of-file rules".
203 http://www.gnu.org/software/flex/manual/html_node/flex_13.html */
205 dfilter_fail("The final quote was missing from a quoted string.");
213 token = set_lval(TOKEN_STRING, quoted_string->str);
214 g_string_free(quoted_string, TRUE);
215 quoted_string = NULL;
219 <DQUOTE>\\[0-7]{1,3} {
221 unsigned long result;
222 result = strtoul(yytext + 1, NULL, 8);
224 g_string_free(quoted_string, TRUE);
225 quoted_string = NULL;
226 dfilter_fail("%s is larger than 255.", yytext);
229 g_string_append_c(quoted_string, (gchar) result);
232 <DQUOTE>\\x[[:xdigit:]]{1,2} {
234 unsigned long result;
235 result = strtoul(yytext + 2, NULL, 16);
236 g_string_append_c(quoted_string, (gchar) result);
241 /* escaped character */
242 g_string_append_c(quoted_string, yytext[1]);
246 /* non-escaped string */
247 g_string_append(quoted_string, yytext);
252 [-[:alnum:]_\.:]+\/[[:digit:]]+ {
254 return set_lval(TOKEN_UNPARSED, yytext);
258 /* Is it a field name? */
259 header_field_info *hfinfo;
260 df_func_def_t *df_func_def;
262 hfinfo = proto_registrar_get_byname(yytext);
264 /* Yes, it's a field name */
265 return set_lval(TOKEN_FIELD, hfinfo);
268 /* Is it a function name? */
269 df_func_def = df_func_lookup(yytext);
271 /* yes, it's a dfilter function */
272 return set_lval(TOKEN_FUNCTION, df_func_def);
275 /* No, so treat it as an unparsed string */
276 return set_lval(TOKEN_UNPARSED, yytext);
283 return set_lval(TOKEN_UNPARSED, yytext);
306 case TOKEN_TEST_BITWISE_AND:
307 case TOKEN_TEST_CONTAINS:
308 case TOKEN_TEST_MATCHES:
314 g_assert_not_reached();
320 set_lval(int token, gpointer data)
322 sttype_id_t type_id = STTYPE_UNINITIALIZED;
326 type_id = STTYPE_STRING;
329 type_id = STTYPE_FIELD;
332 type_id = STTYPE_UNPARSED;
335 type_id = STTYPE_FUNCTION;
338 g_assert_not_reached();
340 stnode_init(df_lval, type_id, data);
345 set_lval_int(int token, char *s)
347 sttype_id_t type_id = STTYPE_UNINITIALIZED;
350 if (!str_to_gint32(s, &val)) {
356 type_id = STTYPE_INTEGER;
359 g_assert_not_reached();
362 stnode_init_int(df_lval, type_id, val);
368 str_to_gint32(char *s, gint32* pint)
374 integer = strtol(s, &endptr, 0);
376 if (errno == EINVAL || endptr == s || *endptr != '\0') {
377 /* This isn't a valid number. */
378 dfilter_fail("\"%s\" is not a valid number.", s);
381 if (errno == ERANGE) {
382 if (integer == LONG_MAX) {
383 dfilter_fail("\"%s\" causes an integer overflow.", s);
385 else if (integer == LONG_MIN) {
386 dfilter_fail("\"%s\" causes an integer underflow.", s);
390 * XXX - can "strtol()" set errno to ERANGE without
391 * returning LONG_MAX or LONG_MIN?
393 dfilter_fail("\"%s\" is not an integer.", s);
397 if (integer > G_MAXINT32) {
399 * Fits in a long, but not in a gint32 (a long might be
402 dfilter_fail("\"%s\" causes an integer overflow.", s);
405 if (integer < G_MININT32) {
407 * Fits in a long, but not in a gint32 (a long might be
410 dfilter_fail("\"%s\" causes an integer underflow.", s);
414 *pint = (gint32)integer;
419 mark_lval_deprecated(const char *s)
421 df_lval->deprecated_token = s;
424 #include <lemonflex-tail.inc>