blob: 1c4500ce85a857cdfe99a9bdf5d9001f664aab76 [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
17#define PARSE_DEBUG 0
18
19u16 word_type_index, number_type_index, eof_type_index, rule_eof_type_index,
Dave Barach9b8ffd92016-07-08 08:13:45 -040020 plus_type_index, minus_type_index, star_type_index, slash_type_index,
21 lpar_type_index, rpar_type_index;
Ed Warnickecb9cada2015-12-08 15:45:58 -070022
Dave Barach9b8ffd92016-07-08 08:13:45 -040023u8 *
24format_vlib_parse_value (u8 * s, va_list * args)
Ed Warnickecb9cada2015-12-08 15:45:58 -070025{
26 vlib_parse_main_t *pm = va_arg (*args, vlib_parse_main_t *);
27 vlib_parse_type_t *type;
28 vlib_parse_value_t *v;
29 u16 type_index;
30
31 s = format (s, "%d items:\n", vec_len (pm->parse_value));
32 vec_foreach (v, pm->parse_value)
Dave Barach9b8ffd92016-07-08 08:13:45 -040033 {
34 type_index = v->type;
35 type = pool_elt_at_index (pm->parse_types, type_index);
36 if (type->format_value)
37 s = format (s, "[%d]: %U\n", v - pm->parse_value,
38 type->format_value, v);
39 else
40 s = format (s, "[%d]: (nofun)\n", v - pm->parse_value);
41 }
Ed Warnickecb9cada2015-12-08 15:45:58 -070042 return s;
43}
44
Dave Barach9b8ffd92016-07-08 08:13:45 -040045static u8 *
46format_vlib_parse_match (u8 * s, va_list * args)
Ed Warnickecb9cada2015-12-08 15:45:58 -070047{
48 vlib_parse_match_t m = va_arg (*args, vlib_parse_match_t);
Dave Barach9b8ffd92016-07-08 08:13:45 -040049 char *t = 0;
Ed Warnickecb9cada2015-12-08 15:45:58 -070050 switch (m)
51 {
52#define _(a) case VLIB_PARSE_##a: t = #a; break;
53 foreach_parse_match_type
54#undef _
Dave Barach9b8ffd92016-07-08 08:13:45 -040055 default:
56 t = 0;
57 break;
Ed Warnickecb9cada2015-12-08 15:45:58 -070058 }
Dave Barach9b8ffd92016-07-08 08:13:45 -040059
Ed Warnickecb9cada2015-12-08 15:45:58 -070060 if (t)
61 return format (s, "%s", t);
62 else
63 return format (s, "unknown 0x%x", m);
64}
65
Dave Barach9b8ffd92016-07-08 08:13:45 -040066static u8 *
67format_vlib_parse_item (u8 * s, va_list * args)
Ed Warnickecb9cada2015-12-08 15:45:58 -070068{
69 vlib_parse_main_t *pm = va_arg (*args, vlib_parse_main_t *);
70 vlib_parse_item_t *item = va_arg (*args, vlib_parse_item_t *);
71 vlib_parse_type_t *type = pool_elt_at_index (pm->parse_types, item->type);
72
73 if (item->type == word_type_index)
74 s = format (s, "%s", item->value.as_pointer);
75 else
76 s = format (s, "<%s>", type->name);
77 return s;
78}
79
Dave Barach9b8ffd92016-07-08 08:13:45 -040080static u8 *
81format_vlib_parse_graph (u8 * s, va_list * args)
Ed Warnickecb9cada2015-12-08 15:45:58 -070082{
83 vlib_parse_main_t *pm = va_arg (*args, vlib_parse_main_t *);
84 vlib_parse_graph_t *node = va_arg (*args, vlib_parse_graph_t *);
85 vlib_parse_item_t *item;
86 vlib_parse_type_t *type;
87
88 /* $$$ hash table */
Dave Barach9b8ffd92016-07-08 08:13:45 -040089 /* *INDENT-OFF* */
90 pool_foreach (type, pm->parse_types,
Ed Warnickecb9cada2015-12-08 15:45:58 -070091 ({
92 if (type->rule_index == node - pm->parse_graph)
93 s = format (s, "\n<%s>\n", type->name);
94 }));
Dave Barach9b8ffd92016-07-08 08:13:45 -040095/* *INDENT-ON* */
Ed Warnickecb9cada2015-12-08 15:45:58 -070096
97 if (pm->root_index == (node - pm->parse_graph))
98 s = format (s, "\n<root>\n");
99
100 item = pool_elt_at_index (pm->parse_items, node->item);
101
102 s = format (s, "[%d] %U ", node - pm->parse_graph,
103 format_vlib_parse_item, pm, item);
104
Dave Barach9b8ffd92016-07-08 08:13:45 -0400105 if (node->peer == (u32) ~ 0)
Ed Warnickecb9cada2015-12-08 15:45:58 -0700106 s = format (s, "peer nil ");
107 else
108 s = format (s, "peer %4u ", node->peer);
109
Dave Barach9b8ffd92016-07-08 08:13:45 -0400110 if (node->deeper == (u32) ~ 0)
Ed Warnickecb9cada2015-12-08 15:45:58 -0700111 s = format (s, "deeper nil ");
112 else
113 s = format (s, "deeper %4u ", node->deeper);
114
115 return s;
116}
117
Dave Barach9b8ffd92016-07-08 08:13:45 -0400118void
119dump_parse_graph (void)
Ed Warnickecb9cada2015-12-08 15:45:58 -0700120{
121 vlib_parse_main_t *pm = &vlib_parse_main;
122 vlib_parse_graph_t *node;
123
Dave Barach9b8ffd92016-07-08 08:13:45 -0400124 /* *INDENT-OFF* */
Ed Warnickecb9cada2015-12-08 15:45:58 -0700125 pool_foreach (node, pm->parse_graph, ({
126 fformat(stdout, "%U\n", format_vlib_parse_graph, pm, node);
127 }));
Dave Barach9b8ffd92016-07-08 08:13:45 -0400128/* *INDENT-ON* */
Ed Warnickecb9cada2015-12-08 15:45:58 -0700129}
130
131always_inline void
Dave Barach9b8ffd92016-07-08 08:13:45 -0400132parse_cleanup_value (vlib_parse_main_t * pm, vlib_parse_value_t * pv)
Ed Warnickecb9cada2015-12-08 15:45:58 -0700133{
134 vlib_parse_type_t *type = pool_elt_at_index (pm->parse_types, pv->type);
135 if (type->value_cleanup_function)
136 type->value_cleanup_function (pv);
137}
138
Dave Barach9b8ffd92016-07-08 08:13:45 -0400139static void
140parse_reset (vlib_parse_main_t * pm, u8 * input)
Ed Warnickecb9cada2015-12-08 15:45:58 -0700141{
142 vlib_lex_token_t *t;
143 vlib_parse_value_t *pv;
144
145 vlib_lex_reset (pm->lex_main, input);
146
Dave Barach9b8ffd92016-07-08 08:13:45 -0400147 vec_foreach (t, pm->tokens) vlib_lex_cleanup_token (t);
Ed Warnickecb9cada2015-12-08 15:45:58 -0700148
Dave Barach9b8ffd92016-07-08 08:13:45 -0400149 vec_foreach (pv, pm->parse_value) parse_cleanup_value (pm, pv);
Ed Warnickecb9cada2015-12-08 15:45:58 -0700150
151 _vec_len (pm->parse_value) = 0;
152 _vec_len (pm->tokens) = 0;
153 pm->current_token_index = 0;
154}
155
Dave Barach9b8ffd92016-07-08 08:13:45 -0400156static void
157parse_help (vlib_parse_main_t * pm, u32 index)
Ed Warnickecb9cada2015-12-08 15:45:58 -0700158{
159 vlib_parse_graph_t *node;
Dave Barach9b8ffd92016-07-08 08:13:45 -0400160 vlib_parse_item_t *item;
161 vlib_parse_type_t *type;
Ed Warnickecb9cada2015-12-08 15:45:58 -0700162 vlib_main_t *vm = pm->vlib_main;
163 u8 *help_input;
164 int i;
Dave Barach9b8ffd92016-07-08 08:13:45 -0400165
Ed Warnickecb9cada2015-12-08 15:45:58 -0700166 help_input = vec_dup (pm->lex_main->input_vector);
167
Dave Barach9b8ffd92016-07-08 08:13:45 -0400168 for (i = vec_len (help_input) - 1; i >= 0; i--)
Ed Warnickecb9cada2015-12-08 15:45:58 -0700169 if (help_input[i] == '?')
170 {
171 help_input[i] = 0;
Dave Barach9b8ffd92016-07-08 08:13:45 -0400172 _vec_len (help_input) = i;
Ed Warnickecb9cada2015-12-08 15:45:58 -0700173 break;
174 }
175
Dave Barach9b8ffd92016-07-08 08:13:45 -0400176 for (i = vec_len (help_input) - 1; i >= 0; i--)
Ed Warnickecb9cada2015-12-08 15:45:58 -0700177 {
178 if (help_input[i] != ' ' && help_input[i] != '\t')
179 break;
180 help_input[i] = 0;
181 break;
182 }
Dave Barach9b8ffd92016-07-08 08:13:45 -0400183 _vec_len (help_input) = i + 1;
Ed Warnickecb9cada2015-12-08 15:45:58 -0700184
Dave Barach9b8ffd92016-07-08 08:13:45 -0400185 while (index != (u32) ~ 0)
Ed Warnickecb9cada2015-12-08 15:45:58 -0700186 {
187 node = pool_elt_at_index (pm->parse_graph, index);
188 item = pool_elt_at_index (pm->parse_items, node->item);
189 type = pool_elt_at_index (pm->parse_types, item->type);
Dave Barach9b8ffd92016-07-08 08:13:45 -0400190
Ed Warnickecb9cada2015-12-08 15:45:58 -0700191 if (item->type == eof_type_index && vec_len (pm->match_items) == 0)
Dave Barach9b8ffd92016-07-08 08:13:45 -0400192 /* do nothing */ ;
Ed Warnickecb9cada2015-12-08 15:45:58 -0700193 else if (item->type == word_type_index)
194 vlib_cli_output (vm, "%s %s\n", help_input, item->value.as_pointer);
195 else
196 vlib_cli_output (vm, "%s <%s>\n", help_input, type->name);
197 index = node->peer;
198 }
199 vec_free (help_input);
200}
201
202static vlib_parse_match_t
Dave Barach9b8ffd92016-07-08 08:13:45 -0400203parse_eval_internal (vlib_parse_main_t * pm, u32 index)
Ed Warnickecb9cada2015-12-08 15:45:58 -0700204{
205 vlib_parse_graph_t *node;
Dave Barach9b8ffd92016-07-08 08:13:45 -0400206 vlib_parse_item_t *item;
207 vlib_parse_type_t *type;
Ed Warnickecb9cada2015-12-08 15:45:58 -0700208 vlib_parse_value_t value, *pv;
209 vlib_parse_match_t rv;
210 u32 *partial_matches = 0;
211 vlib_lex_token_t *t;
Dave Barach9b8ffd92016-07-08 08:13:45 -0400212 u32 save_token_index = (u32) ~ 0, save_match_items = 0;
Ed Warnickecb9cada2015-12-08 15:45:58 -0700213 int had_value = 0;
214
Dave Barach9b8ffd92016-07-08 08:13:45 -0400215 if (pm->current_token_index >= vec_len (pm->tokens))
Ed Warnickecb9cada2015-12-08 15:45:58 -0700216 return VLIB_PARSE_MATCH_FAIL;
217
218 /* current token */
219 t = vec_elt_at_index (pm->tokens, pm->current_token_index);
220
221 /* Help ? */
Dave Barach9b8ffd92016-07-08 08:13:45 -0400222 if (PREDICT_FALSE (t->token == VLIB_LEX_qmark))
Ed Warnickecb9cada2015-12-08 15:45:58 -0700223 {
224 parse_help (pm, index);
225 _vec_len (pm->match_items) = 0;
226 return VLIB_PARSE_MATCH_DONE;
227 }
228
229 /* Across all peers at this level of the parse graph */
Dave Barach9b8ffd92016-07-08 08:13:45 -0400230 while (index != (u32) ~ 0)
Ed Warnickecb9cada2015-12-08 15:45:58 -0700231 {
232 node = pool_elt_at_index (pm->parse_graph, index);
233 item = pool_elt_at_index (pm->parse_items, node->item);
234 type = pool_elt_at_index (pm->parse_types, item->type);
Dave Barach9b8ffd92016-07-08 08:13:45 -0400235
236 /*
Ed Warnickecb9cada2015-12-08 15:45:58 -0700237 * Save the token index. We may have to back up several
Dave Barach9b8ffd92016-07-08 08:13:45 -0400238 * trie plies. Type-specific match functions can consume
Ed Warnickecb9cada2015-12-08 15:45:58 -0700239 * multiple tokens, and they may not be optimally careful
240 */
241 save_token_index = pm->current_token_index;
242 save_match_items = vec_len (pm->match_items);
243 vec_add1 (pm->match_items, node->item);
Dave Barach9b8ffd92016-07-08 08:13:45 -0400244
Ed Warnickecb9cada2015-12-08 15:45:58 -0700245 if (PARSE_DEBUG > 1)
Dave Barach9b8ffd92016-07-08 08:13:45 -0400246 clib_warning ("Try to match token %U against node %d",
247 format_vlib_lex_token, pm->lex_main, t, index);
248
Ed Warnickecb9cada2015-12-08 15:45:58 -0700249 /* Call the type-specific match function */
250 rv = type->match_function (pm, type, t, &value);
Dave Barach9b8ffd92016-07-08 08:13:45 -0400251
Ed Warnickecb9cada2015-12-08 15:45:58 -0700252 if (PARSE_DEBUG > 1)
Dave Barach9b8ffd92016-07-08 08:13:45 -0400253 clib_warning ("returned %U", format_vlib_parse_match, rv);
254
Ed Warnickecb9cada2015-12-08 15:45:58 -0700255 switch (rv)
Dave Barach9b8ffd92016-07-08 08:13:45 -0400256 {
257 case VLIB_PARSE_MATCH_VALUE:
258 /*
259 * Matched, and returned a value to append to the
260 * set of args passed to the action function
261 */
262 value.type = item->type;
263 vec_add1 (pm->parse_value, value);
264 had_value = 1;
265 /* fallthrough */
Ed Warnickecb9cada2015-12-08 15:45:58 -0700266
Dave Barach9b8ffd92016-07-08 08:13:45 -0400267 case VLIB_PARSE_MATCH_FULL:
268 unambiguous_partial_match:
269 /* Consume the matched token */
270 pm->current_token_index++;
Ed Warnickecb9cada2015-12-08 15:45:58 -0700271
Dave Barach9b8ffd92016-07-08 08:13:45 -0400272 /* continue matching along this path */
273 rv = parse_eval_internal (pm, node->deeper);
Ed Warnickecb9cada2015-12-08 15:45:58 -0700274
Dave Barach9b8ffd92016-07-08 08:13:45 -0400275 /* this is not the right path */
276 if (rv == VLIB_PARSE_MATCH_FAIL)
277 {
278 if (had_value)
279 {
280 /* Delete the value */
281 value = pm->parse_value[vec_len (pm->parse_value) - 1];
282 parse_cleanup_value (pm, &value);
283 _vec_len (pm->parse_value) -= 1;
284 }
285 /* Continue with the next sibling */
286 pm->current_token_index = save_token_index;
287 _vec_len (pm->match_items) = save_match_items;
288 index = node->peer;
289 break;
290 }
291 return rv;
Ed Warnickecb9cada2015-12-08 15:45:58 -0700292
Dave Barach9b8ffd92016-07-08 08:13:45 -0400293 case VLIB_PARSE_MATCH_PARTIAL:
294 /* Partial (substring) match, remember it but keep going */
295 vec_add1 (partial_matches, node - pm->parse_graph);
296 index = node->peer;
297 break;
Ed Warnickecb9cada2015-12-08 15:45:58 -0700298
Dave Barach9b8ffd92016-07-08 08:13:45 -0400299 case VLIB_PARSE_MATCH_FAIL:
300 /* Continue with the next sibling */
301 index = node->peer;
302 _vec_len (pm->match_items) = save_match_items;
303 break;
Ed Warnickecb9cada2015-12-08 15:45:58 -0700304
Dave Barach9b8ffd92016-07-08 08:13:45 -0400305 case VLIB_PARSE_MATCH_DONE:
306 /* Parse complete, invoke the action function */
307 if (PARSE_DEBUG > 0)
308 clib_warning ("parse_value: %U", format_vlib_parse_value, pm);
Ed Warnickecb9cada2015-12-08 15:45:58 -0700309
Dave Barach9b8ffd92016-07-08 08:13:45 -0400310 {
311 vlib_parse_eval_function_t *f = item->value.as_pointer;
312 if (f)
Ed Warnickecb9cada2015-12-08 15:45:58 -0700313 rv = f (pm, item, pm->parse_value);
Dave Barach9b8ffd92016-07-08 08:13:45 -0400314 }
Ed Warnickecb9cada2015-12-08 15:45:58 -0700315
Dave Barach9b8ffd92016-07-08 08:13:45 -0400316 vec_foreach (pv, pm->parse_value) parse_cleanup_value (pm, pv);
317 _vec_len (pm->parse_value) = 0;
318 _vec_len (pm->match_items) = 0;
319 return rv;
320
321 case VLIB_PARSE_MATCH_AMBIGUOUS:
322 case VLIB_PARSE_MATCH_EVAL_FAIL:
323 case VLIB_PARSE_MATCH_RULE:
324 _vec_len (pm->match_items) = save_match_items;
325 return rv;
326 }
Ed Warnickecb9cada2015-12-08 15:45:58 -0700327 }
328
Dave Barach9b8ffd92016-07-08 08:13:45 -0400329 /*
Ed Warnickecb9cada2015-12-08 15:45:58 -0700330 * Out of siblings. If we have exactly one partial match
331 * we win
332 */
333 if (vec_len (partial_matches) == 1)
334 {
335 index = partial_matches[0];
336 node = pool_elt_at_index (pm->parse_graph, index);
337 vec_free (partial_matches);
338 goto unambiguous_partial_match;
339 }
340
341 /* Ordinary loser */
342 rv = VLIB_PARSE_MATCH_FAIL;
343
344 /* Ambiguous loser */
345 if (vec_len (partial_matches) > 1)
346 {
347 vec_free (partial_matches);
348 rv = VLIB_PARSE_MATCH_AMBIGUOUS;
349 }
350
351 _vec_len (pm->match_items) = save_match_items;
352 return rv;
353}
354
Dave Barach9b8ffd92016-07-08 08:13:45 -0400355vlib_parse_match_t
356rule_match (vlib_parse_main_t * pm, vlib_parse_type_t * type,
357 vlib_lex_token_t * t, vlib_parse_value_t * valuep)
Ed Warnickecb9cada2015-12-08 15:45:58 -0700358{
359 vlib_parse_match_t rv;
360 static int recursion_level;
361
362 if (PARSE_DEBUG > 1)
Dave Barach9b8ffd92016-07-08 08:13:45 -0400363 clib_warning ("[%d]: try to match type %s graph index %d",
364 recursion_level, type->name, type->rule_index);
Ed Warnickecb9cada2015-12-08 15:45:58 -0700365 recursion_level++;
366 rv = parse_eval_internal (pm, type->rule_index);
367 recursion_level--;
368
369 /* Break the recusive unwind here... */
370 if (rv == VLIB_PARSE_MATCH_RULE)
371 {
372 if (PARSE_DEBUG > 1)
Dave Barach9b8ffd92016-07-08 08:13:45 -0400373 clib_warning ("[%d]: type %s matched", recursion_level, type->name);
Ed Warnickecb9cada2015-12-08 15:45:58 -0700374
375 return VLIB_PARSE_MATCH_FULL;
Dave Barach9b8ffd92016-07-08 08:13:45 -0400376 }
377 else
Ed Warnickecb9cada2015-12-08 15:45:58 -0700378 {
379 if (PARSE_DEBUG > 1)
Dave Barach9b8ffd92016-07-08 08:13:45 -0400380 clib_warning ("[%d]: type %s returns %U", recursion_level, type->name,
381 format_vlib_parse_match, rv);
Ed Warnickecb9cada2015-12-08 15:45:58 -0700382 }
383 return rv;
384}
385
Dave Barach9b8ffd92016-07-08 08:13:45 -0400386static int
387parse_eval (vlib_parse_main_t * pm, u8 * input)
Ed Warnickecb9cada2015-12-08 15:45:58 -0700388{
Dave Barach9b8ffd92016-07-08 08:13:45 -0400389 vlib_lex_token_t *t;
Ed Warnickecb9cada2015-12-08 15:45:58 -0700390
391 parse_reset (pm, input);
Dave Barach9b8ffd92016-07-08 08:13:45 -0400392
Ed Warnickecb9cada2015-12-08 15:45:58 -0700393 /* Tokenize the entire input vector */
Dave Barach9b8ffd92016-07-08 08:13:45 -0400394 do
395 {
396 vec_add2 (pm->tokens, t, 1);
397 vlib_lex_get_token (pm->lex_main, t);
398 }
399 while (t->token != VLIB_LEX_eof);
Ed Warnickecb9cada2015-12-08 15:45:58 -0700400
401 /* Feed it to the parser */
402 return parse_eval_internal (pm, pm->root_index);
403}
404
405/* Temporary vlib stub */
Dave Barach9b8ffd92016-07-08 08:13:45 -0400406vlib_parse_match_t
407vlib_parse_eval (u8 * input)
Ed Warnickecb9cada2015-12-08 15:45:58 -0700408{
409 return parse_eval (&vlib_parse_main, input);
410}
411
Dave Barach9b8ffd92016-07-08 08:13:45 -0400412u16
413parse_type_find_or_create (vlib_parse_main_t * pm, vlib_parse_type_t * t)
Ed Warnickecb9cada2015-12-08 15:45:58 -0700414{
415 uword *p;
416 vlib_parse_type_t *n;
417 u8 *name_copy;
418
419 p = hash_get_mem (pm->parse_type_by_name_hash, t->name);
420 if (p)
421 return p[0];
422
423 pool_get (pm->parse_types, n);
424 *n = *t;
Dave Barach9b8ffd92016-07-08 08:13:45 -0400425 n->rule_index = (u32) ~ 0;
Ed Warnickecb9cada2015-12-08 15:45:58 -0700426
427 name_copy = format (0, "%s%c", n->name, 0);
428
429 hash_set_mem (pm->parse_type_by_name_hash, name_copy, n - pm->parse_types);
430 return n - pm->parse_types;
431}
432
Dave Barach9b8ffd92016-07-08 08:13:45 -0400433u16
434parse_type_find_by_name (vlib_parse_main_t * pm, char *name)
Ed Warnickecb9cada2015-12-08 15:45:58 -0700435{
436 uword *p;
437
438 p = hash_get_mem (pm->parse_type_by_name_hash, name);
439 if (p)
440 return p[0];
441
Dave Barach9b8ffd92016-07-08 08:13:45 -0400442 return (u16) ~ 0;
Ed Warnickecb9cada2015-12-08 15:45:58 -0700443}
444
Dave Barach9b8ffd92016-07-08 08:13:45 -0400445u32
446parse_item_find_or_create (vlib_parse_main_t * pm, vlib_parse_item_t * item)
Ed Warnickecb9cada2015-12-08 15:45:58 -0700447{
448 uword *p;
449 vlib_parse_item_t *i;
450
451 /* Exact match the entire item */
452 p = mhash_get (&pm->parse_item_hash, item);
453 if (p)
454 return p[0];
455
456 pool_get (pm->parse_items, i);
457 *i = *item;
458
459 mhash_set (&pm->parse_item_hash, i, i - pm->parse_items, 0);
460 return i - pm->parse_items;
461}
462
Dave Barach9b8ffd92016-07-08 08:13:45 -0400463static void
464parse_type_and_graph_init (vlib_parse_main_t * pm)
Ed Warnickecb9cada2015-12-08 15:45:58 -0700465{
466 u32 eof_index;
467 vlib_parse_type_t type;
468 vlib_parse_item_t item;
469
470 memset (&type, 0, sizeof (type));
471
472#define foreach_token_type \
473 _ (eof) \
474 _ (rule_eof) \
475 _ (word) \
476 _ (number) \
477 _ (plus) \
478 _ (minus) \
479 _ (star) \
480 _ (slash) \
481 _ (lpar) \
482 _ (rpar)
483
484#define _(a) a##_type_index = parse_type_find_by_name (pm, #a);
Dave Barach9b8ffd92016-07-08 08:13:45 -0400485 foreach_token_type
Ed Warnickecb9cada2015-12-08 15:45:58 -0700486#undef _
Dave Barach9b8ffd92016-07-08 08:13:45 -0400487 memset (&item, 0, sizeof (item));
Ed Warnickecb9cada2015-12-08 15:45:58 -0700488 item.type = eof_type_index;
Dave Barach9b8ffd92016-07-08 08:13:45 -0400489
Ed Warnickecb9cada2015-12-08 15:45:58 -0700490 eof_index = parse_item_find_or_create (pm, &item);
Dave Barach9b8ffd92016-07-08 08:13:45 -0400491 pm->root_index = (u32) ~ 0;
Ed Warnickecb9cada2015-12-08 15:45:58 -0700492
493#if 0
494 pool_get (pm->parse_graph, g);
495 memset (g, 0xff, sizeof (*g));
496 g->item = eof_index;
497 pm->root_index = 0;
498#endif
499}
500
501
502
Dave Barach9b8ffd92016-07-08 08:13:45 -0400503static void
504tokenize (vlib_parse_main_t * pm, parse_registration_t * pr)
Ed Warnickecb9cada2015-12-08 15:45:58 -0700505{
506 vlib_lex_token_t *t;
Dave Barach9b8ffd92016-07-08 08:13:45 -0400507 pm->register_input = format (pm->register_input,
508 "%s%c", pr->initializer, 0);
509
Ed Warnickecb9cada2015-12-08 15:45:58 -0700510 parse_reset (pm, pm->register_input);
Dave Barach9b8ffd92016-07-08 08:13:45 -0400511
512 do
513 {
514 vec_add2 (pm->tokens, t, 1);
515 vlib_lex_get_token (pm->lex_main, t);
516 }
517 while (t->token != VLIB_LEX_eof);
Ed Warnickecb9cada2015-12-08 15:45:58 -0700518 _vec_len (pm->register_input) = 0;
519}
520
Dave Barach9b8ffd92016-07-08 08:13:45 -0400521static int
522is_typed_rule (vlib_parse_main_t * pm)
Ed Warnickecb9cada2015-12-08 15:45:58 -0700523{
524 vlib_lex_token_t *t = vec_elt_at_index (pm->tokens, 0);
Dave Barach9b8ffd92016-07-08 08:13:45 -0400525
Ed Warnickecb9cada2015-12-08 15:45:58 -0700526 /* <mytype> = blah blah blah */
Dave Barach9b8ffd92016-07-08 08:13:45 -0400527 if (vec_len (pm->tokens) >= 4
Ed Warnickecb9cada2015-12-08 15:45:58 -0700528 && t[0].token == VLIB_LEX_lt
529 && t[1].token == VLIB_LEX_word
Dave Barach9b8ffd92016-07-08 08:13:45 -0400530 && t[2].token == VLIB_LEX_gt && t[3].token == VLIB_LEX_equals)
Ed Warnickecb9cada2015-12-08 15:45:58 -0700531 return 1;
532 return 0;
533}
534
Dave Barach9b8ffd92016-07-08 08:13:45 -0400535static int
536token_matches_graph_node (vlib_parse_main_t * pm,
537 vlib_lex_token_t * t,
538 vlib_parse_graph_t * node,
539 vlib_parse_item_t * item,
540 vlib_parse_type_t * type, u32 * token_increment)
Ed Warnickecb9cada2015-12-08 15:45:58 -0700541{
542 /* EOFs don't match */
543 if (t->token == VLIB_LEX_eof)
544 return 0;
545
546 /* New chain element is a word */
547 if (t->token == VLIB_LEX_word)
548 {
549 /* but the item in hand is not a word */
550 if (item->type != word_type_index)
Dave Barach9b8ffd92016-07-08 08:13:45 -0400551 return 0;
552
Ed Warnickecb9cada2015-12-08 15:45:58 -0700553 /* Or it's not this particular word */
554 if (strcmp (t->value.as_pointer, item->value.as_pointer))
Dave Barach9b8ffd92016-07-08 08:13:45 -0400555 return 0;
Ed Warnickecb9cada2015-12-08 15:45:58 -0700556 *token_increment = 1;
557 return 1;
558 }
559 /* New chain element is a type-name: < TYPE-NAME > */
560 if (t->token == VLIB_LEX_lt)
561 {
562 u16 token_type_index;
Dave Barach9b8ffd92016-07-08 08:13:45 -0400563
Ed Warnickecb9cada2015-12-08 15:45:58 -0700564 /* < TYPE > */
Dave Barach9b8ffd92016-07-08 08:13:45 -0400565 if (t[1].token != VLIB_LEX_word || t[2].token != VLIB_LEX_gt)
566 {
567 clib_warning (0, "broken type name in '%s'", pm->register_input);
568 return 0;
569 }
570
Ed Warnickecb9cada2015-12-08 15:45:58 -0700571 token_type_index = parse_type_find_by_name (pm, t[1].value.as_pointer);
Dave Barach9b8ffd92016-07-08 08:13:45 -0400572 if (token_type_index == (u16) ~ 0)
573 {
574 clib_warning (0, "unknown type '%s'", t[1].value.as_pointer);
575 return 0;
576 }
577
Ed Warnickecb9cada2015-12-08 15:45:58 -0700578 /* Its a known type but does not match. */
579 if (item->type != token_type_index)
Dave Barach9b8ffd92016-07-08 08:13:45 -0400580 return 0;
581
Ed Warnickecb9cada2015-12-08 15:45:58 -0700582 *token_increment = 3;
583 return 1;
584 }
585 clib_warning ("BUG: t->token = %d", t->token);
586 return 0;
587}
588
Dave Barach9b8ffd92016-07-08 08:13:45 -0400589u32
590generate_subgraph_from_tokens (vlib_parse_main_t * pm,
591 vlib_lex_token_t * t,
592 u32 * new_subgraph_depth,
593 parse_registration_t * pr, int not_a_rule)
Ed Warnickecb9cada2015-12-08 15:45:58 -0700594{
595 vlib_parse_graph_t *g, *last_g;
596 vlib_parse_item_t new_item;
Dave Barach9b8ffd92016-07-08 08:13:45 -0400597 u32 rv = (u32) ~ 0, new_item_index, last_index = (u32) ~ 0;
Ed Warnickecb9cada2015-12-08 15:45:58 -0700598 u16 token_type_index;
599 u32 depth = 0;
600
601 while (t < pm->tokens + vec_len (pm->tokens))
602 {
603 memset (&new_item, 0, sizeof (new_item));
604
605 if (t->token == VLIB_LEX_word)
606 {
607 new_item.type = word_type_index;
608 new_item.value.as_pointer = vec_dup ((u8 *) t->value.as_pointer);
609 new_item_index = parse_item_find_or_create (pm, &new_item);
Dave Barach9b8ffd92016-07-08 08:13:45 -0400610 t++;
Ed Warnickecb9cada2015-12-08 15:45:58 -0700611 }
612 else if (t->token == VLIB_LEX_lt)
613 {
Dave Barach9b8ffd92016-07-08 08:13:45 -0400614 if (t[1].token != VLIB_LEX_word || t[2].token != VLIB_LEX_gt)
Ed Warnickecb9cada2015-12-08 15:45:58 -0700615 {
616 clib_warning ("broken type name in '%s'", pm->register_input);
Dave Barach9b8ffd92016-07-08 08:13:45 -0400617 goto screwed;
Ed Warnickecb9cada2015-12-08 15:45:58 -0700618 }
Dave Barach9b8ffd92016-07-08 08:13:45 -0400619 token_type_index = parse_type_find_by_name (pm,
620 t[1].value.as_pointer);
621 if (token_type_index == (u16) ~ 0)
Ed Warnickecb9cada2015-12-08 15:45:58 -0700622 {
Dave Barach9b8ffd92016-07-08 08:13:45 -0400623 clib_warning ("unknown type 2 '%s'", t[1].value.as_pointer);
624 goto screwed;
Ed Warnickecb9cada2015-12-08 15:45:58 -0700625 }
626
627 new_item.type = token_type_index;
628 new_item.value.as_pointer = 0;
629 new_item_index = parse_item_find_or_create (pm, &new_item);
Dave Barach9b8ffd92016-07-08 08:13:45 -0400630 t += 3; /* skip < <type-name> and > */
Ed Warnickecb9cada2015-12-08 15:45:58 -0700631 }
632 else if (t->token == VLIB_LEX_eof)
633 {
Dave Barach9b8ffd92016-07-08 08:13:45 -0400634 screwed:
Ed Warnickecb9cada2015-12-08 15:45:58 -0700635 new_item.type = not_a_rule ? eof_type_index : rule_eof_type_index;
636 new_item.value.as_pointer = pr->eof_match;
637 new_item_index = parse_item_find_or_create (pm, &new_item);
Dave Barach9b8ffd92016-07-08 08:13:45 -0400638 t++;
Ed Warnickecb9cada2015-12-08 15:45:58 -0700639 }
640 else
641 {
Dave Barach9b8ffd92016-07-08 08:13:45 -0400642 clib_warning ("unexpected token %U index %d in '%s'",
643 format_vlib_lex_token, pm->lex_main, t,
644 t - pm->tokens, pm->register_input);
645 goto screwed;
Ed Warnickecb9cada2015-12-08 15:45:58 -0700646 }
647
648 pool_get (pm->parse_graph, g);
649 memset (g, 0xff, sizeof (*g));
650 g->item = new_item_index;
651 depth++;
Dave Barach9b8ffd92016-07-08 08:13:45 -0400652
653 if (rv == (u32) ~ 0)
654 {
655 rv = g - pm->parse_graph;
656 last_index = rv;
657 }
Ed Warnickecb9cada2015-12-08 15:45:58 -0700658 else
Dave Barach9b8ffd92016-07-08 08:13:45 -0400659 {
660 last_g = pool_elt_at_index (pm->parse_graph, last_index);
661 last_index = last_g->deeper = g - pm->parse_graph;
662 }
Ed Warnickecb9cada2015-12-08 15:45:58 -0700663 }
664 *new_subgraph_depth = depth;
665 return rv;
666}
667
Dave Barach9b8ffd92016-07-08 08:13:45 -0400668static u32
669measure_depth (vlib_parse_main_t * pm, u32 index)
Ed Warnickecb9cada2015-12-08 15:45:58 -0700670{
671 vlib_parse_graph_t *node;
672 vlib_parse_item_t *item;
Dave Barach9b8ffd92016-07-08 08:13:45 -0400673 u32 max = 0;
Ed Warnickecb9cada2015-12-08 15:45:58 -0700674 u32 depth;
675
Dave Barach9b8ffd92016-07-08 08:13:45 -0400676 if (index == (u32) ~ 0)
Ed Warnickecb9cada2015-12-08 15:45:58 -0700677 return 0;
678
679 node = pool_elt_at_index (pm->parse_graph, index);
680 item = pool_elt_at_index (pm->parse_items, node->item);
681
682 if (item->type == eof_type_index)
683 return 1;
684
Dave Barach9b8ffd92016-07-08 08:13:45 -0400685 while (index != (u32) ~ 0)
Ed Warnickecb9cada2015-12-08 15:45:58 -0700686 {
687 node = pool_elt_at_index (pm->parse_graph, index);
688 depth = measure_depth (pm, node->deeper);
689 if (max < depth)
Dave Barach9b8ffd92016-07-08 08:13:45 -0400690 max = depth;
Ed Warnickecb9cada2015-12-08 15:45:58 -0700691 index = node->peer;
692 }
693
694 return max + 1;
695}
696
Dave Barach9b8ffd92016-07-08 08:13:45 -0400697static void
698add_subgraph_to_graph (vlib_parse_main_t * pm,
699 u32 last_matching_index,
700 u32 graph_root_index,
701 u32 new_subgraph_index, u32 new_subgraph_depth)
Ed Warnickecb9cada2015-12-08 15:45:58 -0700702{
703 vlib_parse_graph_t *parent_node;
704 int new_subgraph_longest = 1;
705 u32 current_peer_index;
706 u32 current_depth;
707 vlib_parse_graph_t *current_peer = 0;
Dave Barach9b8ffd92016-07-08 08:13:45 -0400708 vlib_parse_graph_t *new_subgraph_node =
Ed Warnickecb9cada2015-12-08 15:45:58 -0700709 pool_elt_at_index (pm->parse_graph, new_subgraph_index);
710
Dave Barach9b8ffd92016-07-08 08:13:45 -0400711 /*
Ed Warnickecb9cada2015-12-08 15:45:58 -0700712 * Case 1: top-level peer. Splice into the top-level
Dave Barach9b8ffd92016-07-08 08:13:45 -0400713 * peer chain according to rule depth
Ed Warnickecb9cada2015-12-08 15:45:58 -0700714 */
Dave Barach9b8ffd92016-07-08 08:13:45 -0400715 if (last_matching_index == (u32) ~ 0)
Ed Warnickecb9cada2015-12-08 15:45:58 -0700716 {
717 u32 index = graph_root_index;
Dave Barach9b8ffd92016-07-08 08:13:45 -0400718 while (1)
719 {
720 current_peer = pool_elt_at_index (pm->parse_graph, index);
721 current_depth = measure_depth (pm, index);
722 if (current_depth < new_subgraph_depth
723 || current_peer->peer == (u32) ~ 0)
724 break;
725 index = current_peer->peer;
726 }
Ed Warnickecb9cada2015-12-08 15:45:58 -0700727 new_subgraph_node->peer = current_peer->peer;
728 current_peer->peer = new_subgraph_index;
729 return;
730 }
731
732 parent_node = pool_elt_at_index (pm->parse_graph, last_matching_index);
733 current_peer_index = parent_node->deeper;
734
Dave Barach9b8ffd92016-07-08 08:13:45 -0400735 while (current_peer_index != (u32) ~ 0)
Ed Warnickecb9cada2015-12-08 15:45:58 -0700736 {
737 current_peer = pool_elt_at_index (pm->parse_graph, current_peer_index);
738 current_depth = measure_depth (pm, current_peer_index);
739 if (current_depth < new_subgraph_depth)
Dave Barach9b8ffd92016-07-08 08:13:45 -0400740 break;
Ed Warnickecb9cada2015-12-08 15:45:58 -0700741 new_subgraph_longest = 0;
742 current_peer_index = current_peer->peer;
743 }
744
745 ASSERT (current_peer);
746
747 if (new_subgraph_longest)
748 {
749 new_subgraph_node->peer = parent_node->deeper;
750 parent_node->deeper = new_subgraph_index;
751 }
752 else
753 {
754 new_subgraph_node->peer = current_peer->peer;
755 current_peer->peer = new_subgraph_index;
756 }
757}
758
759static clib_error_t *
Dave Barach9b8ffd92016-07-08 08:13:45 -0400760parse_register_one (vlib_parse_main_t * pm, parse_registration_t * pr)
Ed Warnickecb9cada2015-12-08 15:45:58 -0700761{
762 u32 graph_root_index;
Dave Barach9b8ffd92016-07-08 08:13:45 -0400763 u16 subgraph_type_index = (u16) ~ 0;
Ed Warnickecb9cada2015-12-08 15:45:58 -0700764 vlib_parse_type_t *subgraph_type = 0;
765 vlib_lex_token_t *t;
766 vlib_parse_graph_t *node;
767 u32 node_index, last_index, token_increment, new_subgraph_index;
768 u32 new_subgraph_depth, last_matching_index;
769 vlib_parse_item_t *item;
770 vlib_parse_type_t *type;
771
772 int use_main_graph = 1;
773
774 tokenize (pm, pr);
Dave Barach9b8ffd92016-07-08 08:13:45 -0400775
Ed Warnickecb9cada2015-12-08 15:45:58 -0700776 /* A typed rule? */
777 if (is_typed_rule (pm))
778 {
779 /* Get the type and its current subgraph root, if any */
780 t = vec_elt_at_index (pm->tokens, 1);
781 subgraph_type_index = parse_type_find_by_name (pm, t->value.as_pointer);
Dave Barach9b8ffd92016-07-08 08:13:45 -0400782 if (subgraph_type_index == (u16) ~ 0)
783 return clib_error_return (0, "undeclared type '%s'",
784 t->value.as_pointer);
785 subgraph_type =
786 pool_elt_at_index (pm->parse_types, subgraph_type_index);
Ed Warnickecb9cada2015-12-08 15:45:58 -0700787 graph_root_index = subgraph_type->rule_index;
788 /* Skip "mytype> = */
789 t += 3;
790 use_main_graph = 0;
Dave Barach9b8ffd92016-07-08 08:13:45 -0400791 }
Ed Warnickecb9cada2015-12-08 15:45:58 -0700792 else
793 {
794 /* top-level graph */
795 graph_root_index = pm->root_index;
796 t = vec_elt_at_index (pm->tokens, 0);
797 }
798
Dave Barach9b8ffd92016-07-08 08:13:45 -0400799 last_matching_index = (u32) ~ 0;
Ed Warnickecb9cada2015-12-08 15:45:58 -0700800 last_index = node_index = graph_root_index;
801
802 /* Find the first token which isn't already being parsed */
Dave Barach9b8ffd92016-07-08 08:13:45 -0400803 while (t < pm->tokens + vec_len (pm->tokens) && node_index != (u32) ~ 0)
Ed Warnickecb9cada2015-12-08 15:45:58 -0700804 {
805 node = pool_elt_at_index (pm->parse_graph, node_index);
806 item = pool_elt_at_index (pm->parse_items, node->item);
807 type = pool_elt_at_index (pm->parse_types, item->type);
808 last_index = node_index;
Dave Barach9b8ffd92016-07-08 08:13:45 -0400809
810 if (token_matches_graph_node
811 (pm, t, node, item, type, &token_increment))
812 {
813 t += token_increment;
814 last_matching_index = node_index;
815 node_index = node->deeper;
816 }
Ed Warnickecb9cada2015-12-08 15:45:58 -0700817 else
Dave Barach9b8ffd92016-07-08 08:13:45 -0400818 node_index = node->peer;
Ed Warnickecb9cada2015-12-08 15:45:58 -0700819 }
Dave Barach9b8ffd92016-07-08 08:13:45 -0400820
821 new_subgraph_index =
822 generate_subgraph_from_tokens (pm, t, &new_subgraph_depth, pr,
823 use_main_graph);
824
Ed Warnickecb9cada2015-12-08 15:45:58 -0700825 /* trivial cases: first graph node or first type rule */
Dave Barach9b8ffd92016-07-08 08:13:45 -0400826 if (graph_root_index == (u32) ~ 0)
Ed Warnickecb9cada2015-12-08 15:45:58 -0700827 {
828 if (use_main_graph)
Dave Barach9b8ffd92016-07-08 08:13:45 -0400829 pm->root_index = new_subgraph_index;
Ed Warnickecb9cada2015-12-08 15:45:58 -0700830 else
Dave Barach9b8ffd92016-07-08 08:13:45 -0400831 subgraph_type->rule_index = new_subgraph_index;
Ed Warnickecb9cada2015-12-08 15:45:58 -0700832 return 0;
833 }
Dave Barach9b8ffd92016-07-08 08:13:45 -0400834
Ed Warnickecb9cada2015-12-08 15:45:58 -0700835 add_subgraph_to_graph (pm, last_matching_index, graph_root_index,
Dave Barach9b8ffd92016-07-08 08:13:45 -0400836 new_subgraph_index, new_subgraph_depth);
Ed Warnickecb9cada2015-12-08 15:45:58 -0700837 return 0;
838}
839
840static clib_error_t *
841parse_register (vlib_main_t * vm,
Dave Barach9b8ffd92016-07-08 08:13:45 -0400842 parse_registration_t * lo,
843 parse_registration_t * hi, vlib_parse_main_t * pm)
Ed Warnickecb9cada2015-12-08 15:45:58 -0700844{
Dave Barach9b8ffd92016-07-08 08:13:45 -0400845 parse_registration_t *pr;
846
Ed Warnickecb9cada2015-12-08 15:45:58 -0700847 for (pr = lo; pr < hi; pr = vlib_elf_section_data_next (pr, 0))
848 vec_add1 (pm->parse_registrations, pr);
849
850 return 0;
851}
852
853static clib_error_t *
Dave Barach9b8ffd92016-07-08 08:13:45 -0400854parse_register_one_type (vlib_parse_main_t * pm, vlib_parse_type_t * rp)
Ed Warnickecb9cada2015-12-08 15:45:58 -0700855{
Dave Barach9b8ffd92016-07-08 08:13:45 -0400856 (void) parse_type_find_or_create (pm, (vlib_parse_type_t *) rp);
Ed Warnickecb9cada2015-12-08 15:45:58 -0700857 return 0;
858}
859
860static clib_error_t *
861parse_type_register (vlib_main_t * vm,
Dave Barach9b8ffd92016-07-08 08:13:45 -0400862 vlib_parse_type_t * lo,
863 vlib_parse_type_t * hi, vlib_parse_main_t * pm)
Ed Warnickecb9cada2015-12-08 15:45:58 -0700864{
Dave Barach9b8ffd92016-07-08 08:13:45 -0400865 clib_error_t *error = 0;
866 vlib_parse_type_t *ptr;
867
868 for (ptr = lo; ptr < hi; ptr = vlib_elf_section_data_next (ptr, 0))
869 {
870 error = parse_register_one_type (pm, ptr);
871 if (error)
872 goto done;
873 }
874
875done:
Ed Warnickecb9cada2015-12-08 15:45:58 -0700876 return error;
877}
878
Dave Barach9b8ffd92016-07-08 08:13:45 -0400879clib_error_t *vlib_stdlex_init (vlib_main_t * vm) __attribute__ ((weak));
880clib_error_t *
881vlib_stdlex_init (vlib_main_t * vm)
882{
Ed Warnickecb9cada2015-12-08 15:45:58 -0700883 (void) vlib_lex_add_table ("ignore_everything");
Dave Barach9b8ffd92016-07-08 08:13:45 -0400884 return 0;
Ed Warnickecb9cada2015-12-08 15:45:58 -0700885}
886
Dave Barach9b8ffd92016-07-08 08:13:45 -0400887static int
888compute_rule_length (parse_registration_t * r)
Ed Warnickecb9cada2015-12-08 15:45:58 -0700889{
890 int length, i;
891 vlib_parse_main_t *pm = &vlib_parse_main;
892
893 if (r->rule_length)
894 return r->rule_length;
895
896 length = 0;
897
898 tokenize (pm, r);
899 length = vec_len (pm->tokens);
900
901 /* Account for "<foo> = " in "<foo> = bar" etc. */
902 if (is_typed_rule (pm))
903 length -= 2;
904
905 for (i = 0; i < vec_len (pm->tokens); i++)
906 {
907 switch (pm->tokens[i].token)
Dave Barach9b8ffd92016-07-08 08:13:45 -0400908 {
909 case VLIB_LEX_lt:
910 case VLIB_LEX_gt:
911 length -= 1;
Ed Warnickecb9cada2015-12-08 15:45:58 -0700912
Dave Barach9b8ffd92016-07-08 08:13:45 -0400913 default:
914 break;
915 }
Ed Warnickecb9cada2015-12-08 15:45:58 -0700916 }
917
918 ASSERT (length > 0);
919 r->rule_length = length;
920 return length;
921}
922
Dave Barach9b8ffd92016-07-08 08:13:45 -0400923static int
924rule_length_compare (parse_registration_t * r1, parse_registration_t * r2)
Ed Warnickecb9cada2015-12-08 15:45:58 -0700925{
926 compute_rule_length (r1);
927 compute_rule_length (r2);
928 /* Descending sort */
929 return r2->rule_length - r1->rule_length;
930}
931
932
Dave Barach9b8ffd92016-07-08 08:13:45 -0400933static clib_error_t *
934parse_init (vlib_main_t * vm)
Ed Warnickecb9cada2015-12-08 15:45:58 -0700935{
936 vlib_parse_main_t *pm = &vlib_parse_main;
937 vlib_lex_main_t *lm = &vlib_lex_main;
Dave Barach9b8ffd92016-07-08 08:13:45 -0400938 vlib_elf_section_bounds_t *b, *bounds;
939 clib_error_t *error = 0;
Ed Warnickecb9cada2015-12-08 15:45:58 -0700940 parse_registration_t *rule;
941 int i;
942
943 if ((error = vlib_call_init_function (vm, lex_onetime_init)))
944 return error;
945
Dave Barach9b8ffd92016-07-08 08:13:45 -0400946 if ((error = vlib_stdlex_init (vm)))
Ed Warnickecb9cada2015-12-08 15:45:58 -0700947 return error;
948
949 if ((error = vlib_call_init_function (vm, parse_builtin_init)))
950 return error;
951
952 pm->vlib_main = vm;
953 pm->lex_main = lm;
954
955 mhash_init (&pm->parse_item_hash, sizeof (u32), sizeof (vlib_parse_item_t));
956 pm->parse_type_by_name_hash = hash_create_string (0, sizeof (u32));
957
958 vec_validate (pm->parse_value, 16);
959 vec_validate (pm->tokens, 16);
960 vec_validate (pm->register_input, 32);
961 vec_validate (pm->match_items, 16);
962
963 _vec_len (pm->parse_value) = 0;
964 _vec_len (pm->tokens) = 0;
965 _vec_len (pm->register_input) = 0;
966 _vec_len (pm->match_items) = 0;
967
968 bounds = vlib_get_elf_section_bounds (vm, "parse_type_registrations");
969 vec_foreach (b, bounds)
Dave Barach9b8ffd92016-07-08 08:13:45 -0400970 {
971 error = parse_type_register (vm, b->lo, b->hi, pm);
972 if (error)
973 break;
974 }
Ed Warnickecb9cada2015-12-08 15:45:58 -0700975 vec_free (bounds);
976
977 parse_type_and_graph_init (pm);
978
979 bounds = vlib_get_elf_section_bounds (vm, "parse_registrations");
980 vec_foreach (b, bounds)
Dave Barach9b8ffd92016-07-08 08:13:45 -0400981 {
982 error = parse_register (vm, b->lo, b->hi, pm);
983 if (error)
984 break;
985 }
Ed Warnickecb9cada2015-12-08 15:45:58 -0700986 vec_free (bounds);
987
Matus Fabiand2dc3df2015-12-14 10:31:33 -0500988 vec_sort_with_function (pm->parse_registrations, rule_length_compare);
Ed Warnickecb9cada2015-12-08 15:45:58 -0700989
990 for (i = 0; i < vec_len (pm->parse_registrations); i++)
991 {
992 rule = pm->parse_registrations[i];
993 parse_register_one (pm, rule);
994 }
995
996 return error;
997}
998
999VLIB_INIT_FUNCTION (parse_init);
Dave Barach9b8ffd92016-07-08 08:13:45 -04001000
1001/*
1002 * fd.io coding-style-patch-verification: ON
1003 *
1004 * Local Variables:
1005 * eval: (c-set-style "gnu")
1006 * End:
1007 */