blob: 947f25bc50bbd5a1ee9a164dcc114bb5eb6a39dd [file] [log] [blame]
Ed Warnickecb9cada2015-12-08 15:45:58 -07001/*
2 * Copyright (c) 2015 Cisco and/or its affiliates.
3 * Licensed under the Apache License, Version 2.0 (the "License");
4 * you may not use this file except in compliance with the License.
5 * You may obtain a copy of the License at:
6 *
7 * http://www.apache.org/licenses/LICENSE-2.0
8 *
9 * Unless required by applicable law or agreed to in writing, software
10 * distributed under the License is distributed on an "AS IS" BASIS,
11 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 * See the License for the specific language governing permissions and
13 * limitations under the License.
14 */
15#include <vlib/parse.h>
16#include <vlib/unix/unix.h>
17
18static u8 * format_value_v4_address (u8 * s, va_list * args)
19{
20 vlib_parse_value_t *v = va_arg (*args, vlib_parse_value_t *);
21 u32 a = v->value.as_uword;
22
23 s = format (s, "%d.%d.%d.%d",
24 (a>>24) & 0xFF,
25 (a>>16) & 0xFF,
26 (a>>8) & 0xFF,
27 (a>>0) & 0xFF);
28
29 return s;
30}
31
32static vlib_parse_match_t
33v4_address_match (vlib_parse_main_t *pm, vlib_parse_type_t *type,
34 vlib_lex_token_t *t, vlib_parse_value_t *valuep)
35{
36 u32 digit;
37 u32 value = 0;
38 int i;
39
40 if (vec_len (pm->tokens) - (t - pm->tokens) < 7)
41 return VLIB_PARSE_MATCH_FAIL;
42
43 /* NUMBER DOT NUMBER DOT NUMBER DOT NUMBER */
44
45 for (i = 0; i < 7; i++) {
46 if ((i & 1) == 0) {
47 if (t[i].token != VLIB_LEX_number)
48 return VLIB_PARSE_MATCH_FAIL;
49 if (t[i].value.as_uword > 0xff)
50 return VLIB_PARSE_MATCH_FAIL;
51 digit = t[i].value.as_uword;
52 value = (value << 8) | digit;
53 } else {
54 if (t[i].token != VLIB_LEX_dot)
55 return VLIB_PARSE_MATCH_FAIL;
56 }
57 }
58 /* note: caller advances by 1 */
59 pm->current_token_index += 6;
60 valuep->value.as_uword = value;
61 return VLIB_PARSE_MATCH_VALUE;
62}
63
64PARSE_TYPE_INIT (v4_address, v4_address_match, 0, format_value_v4_address)
65
66static u8 * format_value_v4_address_and_mask (u8 * s, va_list * args)
67{
68 vlib_parse_value_t *v = va_arg (*args, vlib_parse_value_t *);
69 u32 * a = v->value.as_pointer;
70
71 s = format (s, "%d.%d.%d.%d",
72 (a[0]>>24) & 0xFF,
73 (a[0]>>16) & 0xFF,
74 (a[0]>>8) & 0xFF,
75 (a[0]>>0) & 0xFF);
76 s = format (s, "/%d", a[1]);
77
78 return s;
79}
80
81static vlib_parse_match_t
82v4_address_and_mask_match (vlib_parse_main_t *pm, vlib_parse_type_t *type,
83 vlib_lex_token_t *t, vlib_parse_value_t *valuep)
84{
85 u32 digit;
86 u32 address = 0;
87 u32 *rv = 0;
88 int i;
89
90 if (vec_len (pm->tokens) - (t - pm->tokens) < 9)
91 return VLIB_PARSE_MATCH_FAIL;
92
93 /* NUMBER DOT NUMBER DOT NUMBER DOT NUMBER */
94
95 for (i = 0; i < 7; i++) {
96 if ((i & 1) == 0) {
97 if (t[i].token != VLIB_LEX_number)
98 return VLIB_PARSE_MATCH_FAIL;
99 if (t[i].value.as_uword > 0xff)
100 return VLIB_PARSE_MATCH_FAIL;
101 digit = t[i].value.as_uword;
102 address = (address << 8) | digit;
103 } else {
104 if (t[i].token != VLIB_LEX_dot)
105 return VLIB_PARSE_MATCH_FAIL;
106 }
107 }
108
109 if (t[7].token != VLIB_LEX_slash || t[8].token != VLIB_LEX_number)
110 return VLIB_PARSE_MATCH_FAIL;
111
112 vec_add1 (rv, address);
113 vec_add1 (rv, t[8].value.as_uword);
114
115 /* note: caller advances by 1 */
116 pm->current_token_index += 8;
117 valuep->value.as_pointer = rv;
118 return VLIB_PARSE_MATCH_VALUE;
119}
120
121void v4_address_and_mask_cleanup (vlib_parse_value_t *valuep)
122{
123 u32 * trash = valuep->value.as_pointer;
124 vec_free (trash);
125}
126
127PARSE_TYPE_INIT (v4_address_and_mask, v4_address_and_mask_match,
128 v4_address_and_mask_cleanup,
129 format_value_v4_address_and_mask)
130
131vlib_lex_main_t vlib_lex_main;
132
133
134
135vlib_parse_match_t eval_factor0 (vlib_parse_main_t *pm,
136 vlib_parse_item_t *item,
137 vlib_parse_value_t *value)
138{
139 clib_warning ("%U", format_vlib_parse_value, pm);
140 return VLIB_PARSE_MATCH_RULE;
141}
142vlib_parse_match_t eval_factor1 (vlib_parse_main_t *pm,
143 vlib_parse_item_t *item,
144 vlib_parse_value_t *value)
145{
146 clib_warning ("%U", format_vlib_parse_value, pm);
147 return VLIB_PARSE_MATCH_RULE;
148}
149vlib_parse_match_t eval_factor2 (vlib_parse_main_t *pm,
150 vlib_parse_item_t *item,
151 vlib_parse_value_t *value)
152{
153 word a;
154 int index = vec_len (pm->parse_value)-1;
155
156 a = pm->parse_value [index].value.as_word;
157
158 pm->parse_value[index].value.as_word = -a;
159 return VLIB_PARSE_MATCH_RULE;
160}
161vlib_parse_match_t eval_term0 (vlib_parse_main_t *pm,
162 vlib_parse_item_t *item,
163 vlib_parse_value_t *value)
164{
165 clib_warning ("%U", format_vlib_parse_value, pm);
166 return VLIB_PARSE_MATCH_RULE;
167}
168vlib_parse_match_t eval_term1 (vlib_parse_main_t *pm,
169 vlib_parse_item_t *item,
170 vlib_parse_value_t *value)
171{
172 uword a, b;
173 int index = vec_len (pm->parse_value)-2;
174
175 a = pm->parse_value [index].value.as_uword;
176 b = pm->parse_value [index+1].value.as_uword;
177
178 pm->parse_value[index].value.as_uword = a * b;
179 _vec_len (pm->parse_value) -= 1;
180 clib_warning ("%U", format_vlib_parse_value, pm);
181
182 return VLIB_PARSE_MATCH_RULE;
183}
184vlib_parse_match_t eval_term2 (vlib_parse_main_t *pm,
185 vlib_parse_item_t *item,
186 vlib_parse_value_t *value)
187{
188 uword a, b;
189 int index = vec_len (pm->parse_value)-2;
190
191 a = pm->parse_value [index].value.as_uword;
192 b = pm->parse_value [index+1].value.as_uword;
193
194 pm->parse_value[index].value.as_uword = a / b;
195 _vec_len (pm->parse_value) -= 1;
196 clib_warning ("%U", format_vlib_parse_value, pm);
197
198 return VLIB_PARSE_MATCH_RULE;
199}
200vlib_parse_match_t eval_exp0 (vlib_parse_main_t *pm,
201 vlib_parse_item_t *item,
202 vlib_parse_value_t *value)
203{
204 return VLIB_PARSE_MATCH_RULE;
205}
206vlib_parse_match_t eval_exp1 (vlib_parse_main_t *pm,
207 vlib_parse_item_t *item,
208 vlib_parse_value_t *value)
209{
210 uword a, b;
211 int index = vec_len (pm->parse_value)-2;
212
213 a = pm->parse_value [index].value.as_uword;
214 b = pm->parse_value [index+1].value.as_uword;
215
216 pm->parse_value[index].value.as_uword = a + b;
217 _vec_len (pm->parse_value) -= 1;
218 clib_warning ("%U", format_vlib_parse_value, pm);
219
220 return VLIB_PARSE_MATCH_RULE;
221}
222vlib_parse_match_t eval_exp2 (vlib_parse_main_t *pm,
223 vlib_parse_item_t *item,
224 vlib_parse_value_t *value)
225{
226 uword a, b;
227 int index = vec_len (pm->parse_value)-2;
228
229 a = pm->parse_value [index].value.as_uword;
230 b = pm->parse_value [index+1].value.as_uword;
231
232 pm->parse_value[index].value.as_uword = a - b;
233 _vec_len (pm->parse_value) -= 1;
234 clib_warning ("%U", format_vlib_parse_value, pm);
235
236 return VLIB_PARSE_MATCH_RULE;
237}
238
239vlib_parse_match_t eval_result (vlib_parse_main_t *pm,
240 vlib_parse_item_t *item,
241 vlib_parse_value_t *value)
242{
243 clib_warning ("%U", format_vlib_parse_value, pm);
244 return VLIB_PARSE_MATCH_DONE;
245}
246
247vlib_parse_match_t noop_match_rule (vlib_parse_main_t *pm,
248 vlib_parse_item_t *item,
249 vlib_parse_value_t *value)
250{
251 clib_warning ("%U", format_vlib_parse_value, pm);
252 return VLIB_PARSE_MATCH_RULE;
253}
254
255#if 0
256PARSE_INIT (t1, "moo", eval0);
257PARSE_INIT (t2, "moo cow mumble", eval1);
258PARSE_INIT (t3, "moo cow", eval2);
259PARSE_INIT (t4, "moo cow mumble grunch", eval3);
260#endif
261
262#if 0
263PARSE_INIT (r1, "eval <exp>", eval_result);
264
265PARSE_INIT (r2, "<exp> = <term><exp2>", eval_exp0);
266PARSE_INIT (r3, "<exp2> = <plus> <exp>", eval_exp1);
267PARSE_INIT (r4, "<exp2> = <minus> <exp>", eval_exp2);
268PARSE_INIT (r5, "<exp2> = ", noop_match_rule);
269PARSE_TYPE_INIT (exp, rule_match, 0, 0);
270PARSE_TYPE_INIT (exp2, rule_match, 0, 0);
271
272PARSE_INIT (r6, "<term> = <factor><term2>", eval_term0);
273PARSE_INIT (r7, "<term2> = <star> <term>", eval_term1);
274PARSE_INIT (r8, "<term2> = <slash> <term>", eval_term2);
275PARSE_INIT (r9, "<term2> = ", noop_match_rule);
276PARSE_TYPE_INIT (term, rule_match, 0, 0);
277PARSE_TYPE_INIT (term2, rule_match, 0, 0);
278
279PARSE_INIT (r11, "<factor> = <lpar> <exp> <rpar>", eval_factor1);
280PARSE_INIT (r10, "<factor> = <number>", eval_factor0);
281PARSE_INIT (r12, "<factor> = <minus> <factor>", eval_factor2);
282
283PARSE_TYPE_INIT (factor, rule_match, 0, 0);
284#endif
285
286PARSE_INIT (r1, "eval <exp>", eval_result);
287
288#if 1
289PARSE_INIT (r2, "<exp> = <term><exp2>", eval_exp0);
290PARSE_INIT (r3, "<exp2> = <plus> <exp>", eval_exp1);
291PARSE_INIT (r4, "<exp2> = <minus> <exp>", eval_exp2);
292PARSE_INIT (r5, "<exp2> = ", noop_match_rule);
293PARSE_TYPE_INIT (exp, rule_match, 0, 0);
294PARSE_TYPE_INIT (exp2, rule_match, 0, 0);
295
296PARSE_INIT (r6, "<term> = <factor><term2>", eval_term0);
297PARSE_INIT (r7, "<term2> = <star> <term>", eval_term1);
298PARSE_INIT (r8, "<term2> = <slash> <term>", eval_term2);
299PARSE_INIT (r9, "<term2> = ", noop_match_rule);
300PARSE_TYPE_INIT (term, rule_match, 0, 0);
301PARSE_TYPE_INIT (term2, rule_match, 0, 0);
302
303PARSE_INIT (r11, "<factor> = <lpar> <exp> <rpar>", eval_factor1);
304PARSE_INIT (r10, "<factor> = <number>", eval_factor0);
305PARSE_INIT (r12, "<factor> = <minus> <factor>", eval_factor2);
306
307PARSE_TYPE_INIT (factor, rule_match, 0, 0);
308#endif
309
310#if 0
311PARSE_TYPE_INIT (exp, rule_match, 0, 0);
312PARSE_INIT (r6, "<exp> = a b", eval_term0);
313PARSE_INIT (r7, "<exp> = c d", eval_term1);
314PARSE_INIT (r9, "<exp> = ", noop_match_rule);
315#endif
316
317#if 0
318#define foreach_rule_evaluator \
319_(0) \
320_(1) \
321_(2) \
322_(3)
323
324#define _(n) \
325vlib_parse_match_t eval##n (vlib_parse_main_t *pm, \
326 vlib_parse_item_t *item, \
327 vlib_parse_value_t *value) \
328{ \
329 clib_warning ("%U", format_vlib_parse_value, pm); \
330 return VLIB_PARSE_MATCH_DONE; \
331}
332foreach_rule_evaluator
333
334#undef _
335
336PARSE_INIT (r1, "eval <moo>", eval_result);
337
338PARSE_INIT (r2, "<moo> = cow", eval0);
339PARSE_INIT (r4, "<moo> = ", eval1);
340PARSE_TYPE_INIT (moo, rule_match, 0, 0);
341#endif
342
343
344clib_error_t *test_init (vlib_main_t *vm)
345{
346 clib_error_t *error;
347
348 if ((error = vlib_call_init_function (vm, parse_init)))
349 return error;
350
351 return 0;
352}
353
354VLIB_INIT_FUNCTION (test_init);
355
356clib_error_t *
357vlib_stdlex_init (vlib_main_t * vm)
358{
359 vlib_lex_main_t * lm = &vlib_lex_main;
360 u16 top_index;
361 u16 slash_index, slash_star_index, slash_slash_index, slash_star_star_index;
362 u16 slash_token;
363 u16 word_index;
364 u16 zero_index, octal_index, decimal_index, hex_index, binary_index;
365
366 top_index = vlib_lex_add_table ("top");
367
368#define foreach_top_level_single_character_token \
369 _('(', lpar) \
370 _(')', rpar) \
371 _(';', semi) \
372 _('[', lbrack) \
373 _(']', rbrack) \
374 _('{', lcurly) \
375 _('}', rcurly) \
376 _('+', plus) \
377 _('-', minus) \
378 _('*', star) \
379 _('%', percent) \
380 _('@', atsign) \
381 _(',', comma) \
382 _('.', dot) \
383 _('?', qmark)
384
385#define _(c,t) \
386 vlib_lex_set_action_range(top_index,c,c,VLIB_LEX_RETURN,vlib_lex_add_token(lm, #t), top_index);
387 foreach_top_level_single_character_token;
388#undef _
389
390 /* Numbers */
391 zero_index = vlib_lex_add_table ("zero");
392 octal_index = vlib_lex_add_table ("octal");
393 decimal_index = vlib_lex_add_table ("decimal");
394 hex_index = vlib_lex_add_table ("hex");
395 binary_index = vlib_lex_add_table ("binary");
396
397 /* Support 0x 0b 0t and 0123 [octal] */
398 vlib_lex_set_action_range (top_index, '0', '0', VLIB_LEX_START_NUMBER, 10, zero_index);
399 vlib_lex_set_action_range (top_index, '1', '9', VLIB_LEX_START_NUMBER, 10, decimal_index);
400
401 vlib_lex_set_action_range (zero_index, 0, 0x7F, VLIB_LEX_RETURN_AND_RESCAN, VLIB_LEX_number, top_index);
402
403 vlib_lex_set_action_range (zero_index, 'x', 'x', VLIB_LEX_IGNORE, ~0, hex_index);
404 vlib_lex_set_action_range (zero_index, 'b', 'b', VLIB_LEX_IGNORE, ~0, binary_index);
405 vlib_lex_set_action_range (zero_index, 't', 't', VLIB_LEX_IGNORE, ~0, decimal_index);
406 vlib_lex_set_action_range (zero_index, '0', '7', VLIB_LEX_START_NUMBER, 8, octal_index);
407
408 /* Octal */
409 vlib_lex_set_action_range (octal_index, 0, 0x7f, VLIB_LEX_RETURN_AND_RESCAN,
410 VLIB_LEX_number, top_index);
411 vlib_lex_set_action_range (octal_index, '0', '7', VLIB_LEX_ADD_TO_NUMBER, 8,
412 octal_index);
413
414 /* Decimal */
415 vlib_lex_set_action_range (decimal_index, 0, 0x7f, VLIB_LEX_RETURN_AND_RESCAN,
416 VLIB_LEX_number, top_index);
417 vlib_lex_set_action_range (decimal_index, '0', '9', VLIB_LEX_ADD_TO_NUMBER, 10,
418 decimal_index);
419
420 /* Hex */
421 vlib_lex_set_action_range (hex_index, 0, 0x7f, VLIB_LEX_RETURN_AND_RESCAN,
422 VLIB_LEX_number, top_index);
423 vlib_lex_set_action_range (hex_index, '0', '9', VLIB_LEX_ADD_TO_NUMBER, 16,
424 hex_index);
425 vlib_lex_set_action_range (hex_index, 'a', 'f', VLIB_LEX_ADD_TO_NUMBER, 16,
426 hex_index);
427 vlib_lex_set_action_range (hex_index, 'A', 'F', VLIB_LEX_ADD_TO_NUMBER, 16,
428 hex_index);
429
430 /* Binary */
431 vlib_lex_set_action_range (binary_index, 0, 0x7f, VLIB_LEX_RETURN_AND_RESCAN,
432 VLIB_LEX_number, top_index);
433 vlib_lex_set_action_range (binary_index, '0', '1', VLIB_LEX_ADD_TO_NUMBER, 2,
434 binary_index);
435
436 /* c/c++ comment syntax is the worst... */
437
438 slash_index = vlib_lex_add_table ("slash");
439 slash_star_index = vlib_lex_add_table ("slash_star");
440 slash_star_star_index = vlib_lex_add_table ("slash_star_star");
441 slash_slash_index = vlib_lex_add_table ("slash_slash");
442 slash_token = vlib_lex_add_token (lm, "slash");
443
444 /* Top level: see a slash, ignore, go to slash table */
445 vlib_lex_set_action_range (top_index, '/', '/', VLIB_LEX_IGNORE, ~0, slash_index);
446
447 /* default for slash table: return SLASH, go to top table */
448 vlib_lex_set_action_range (slash_index, 1, 0x7F, VLIB_LEX_RETURN_AND_RESCAN, slash_token,
449 top_index);
450 /* see slash-slash, go to s-s table */
451 vlib_lex_set_action_range (slash_index, '/', '/', VLIB_LEX_IGNORE, ~0,
452 slash_slash_index);
453 /* see slash-star, go to s-* table */
454 vlib_lex_set_action_range (slash_index, '*', '*', VLIB_LEX_IGNORE, ~0,
455 slash_star_index);
456
457 /* EOL in s-s table, ignore, go to top table */
458 vlib_lex_set_action_range (slash_slash_index, '\n', '\n', VLIB_LEX_IGNORE, ~0,
459 top_index);
460
461 /* slash-star blah blah star */
462 vlib_lex_set_action_range (slash_star_index, '*', '*', VLIB_LEX_IGNORE, ~0,
463 slash_star_star_index);
464
465 /* slash star blah blah star slash */
466 vlib_lex_set_action_range (slash_star_star_index, '/', '/', VLIB_LEX_IGNORE, ~0,
467 top_index);
468
469 /* LT, =, GT */
470 vlib_lex_set_action_range (top_index, '<', '<', VLIB_LEX_RETURN, VLIB_LEX_lt, top_index);
471 vlib_lex_set_action_range (top_index, '=', '=', VLIB_LEX_RETURN, VLIB_LEX_equals,
472 top_index);
473 vlib_lex_set_action_range (top_index, '>', '>', VLIB_LEX_RETURN, VLIB_LEX_gt, top_index);
474
475 /* words, key and otherwise */
476 word_index = vlib_lex_add_table ("word");
477
478 vlib_lex_set_action_range (top_index, 'a', 'z', VLIB_LEX_ADD_TO_TOKEN, ~0, word_index);
479 vlib_lex_set_action_range (top_index, 'A', 'Z', VLIB_LEX_ADD_TO_TOKEN, ~0, word_index);
480
481 vlib_lex_set_action_range (word_index, 0, 0x7f, VLIB_LEX_KEYWORD_CHECK, ~0, top_index);
482
483 vlib_lex_set_action_range (word_index, 'a', 'z', VLIB_LEX_ADD_TO_TOKEN, ~0, word_index);
484 vlib_lex_set_action_range (word_index, 'A', 'Z', VLIB_LEX_ADD_TO_TOKEN, ~0, word_index);
485 vlib_lex_set_action_range (word_index, '_', '_', VLIB_LEX_ADD_TO_TOKEN, ~0, word_index);
486 vlib_lex_set_action_range (word_index, '0', '9', VLIB_LEX_ADD_TO_TOKEN, ~0, word_index);
487
488 return 0;
489}
490