summaryrefslogtreecommitdiffstats
path: root/src/vlib/parse.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/vlib/parse.c')
-rw-r--r--src/vlib/parse.c1007
1 files changed, 0 insertions, 1007 deletions
diff --git a/src/vlib/parse.c b/src/vlib/parse.c
deleted file mode 100644
index 1c4500ce85a..00000000000
--- a/src/vlib/parse.c
+++ /dev/null
@@ -1,1007 +0,0 @@
-/*
- * Copyright (c) 2015 Cisco and/or its affiliates.
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at:
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-#include <vlib/parse.h>
-
-#define PARSE_DEBUG 0
-
-u16 word_type_index, number_type_index, eof_type_index, rule_eof_type_index,
- plus_type_index, minus_type_index, star_type_index, slash_type_index,
- lpar_type_index, rpar_type_index;
-
-u8 *
-format_vlib_parse_value (u8 * s, va_list * args)
-{
- vlib_parse_main_t *pm = va_arg (*args, vlib_parse_main_t *);
- vlib_parse_type_t *type;
- vlib_parse_value_t *v;
- u16 type_index;
-
- s = format (s, "%d items:\n", vec_len (pm->parse_value));
- vec_foreach (v, pm->parse_value)
- {
- type_index = v->type;
- type = pool_elt_at_index (pm->parse_types, type_index);
- if (type->format_value)
- s = format (s, "[%d]: %U\n", v - pm->parse_value,
- type->format_value, v);
- else
- s = format (s, "[%d]: (nofun)\n", v - pm->parse_value);
- }
- return s;
-}
-
-static u8 *
-format_vlib_parse_match (u8 * s, va_list * args)
-{
- vlib_parse_match_t m = va_arg (*args, vlib_parse_match_t);
- char *t = 0;
- switch (m)
- {
-#define _(a) case VLIB_PARSE_##a: t = #a; break;
- foreach_parse_match_type
-#undef _
- default:
- t = 0;
- break;
- }
-
- if (t)
- return format (s, "%s", t);
- else
- return format (s, "unknown 0x%x", m);
-}
-
-static u8 *
-format_vlib_parse_item (u8 * s, va_list * args)
-{
- vlib_parse_main_t *pm = va_arg (*args, vlib_parse_main_t *);
- vlib_parse_item_t *item = va_arg (*args, vlib_parse_item_t *);
- vlib_parse_type_t *type = pool_elt_at_index (pm->parse_types, item->type);
-
- if (item->type == word_type_index)
- s = format (s, "%s", item->value.as_pointer);
- else
- s = format (s, "<%s>", type->name);
- return s;
-}
-
-static u8 *
-format_vlib_parse_graph (u8 * s, va_list * args)
-{
- vlib_parse_main_t *pm = va_arg (*args, vlib_parse_main_t *);
- vlib_parse_graph_t *node = va_arg (*args, vlib_parse_graph_t *);
- vlib_parse_item_t *item;
- vlib_parse_type_t *type;
-
- /* $$$ hash table */
- /* *INDENT-OFF* */
- pool_foreach (type, pm->parse_types,
- ({
- if (type->rule_index == node - pm->parse_graph)
- s = format (s, "\n<%s>\n", type->name);
- }));
-/* *INDENT-ON* */
-
- if (pm->root_index == (node - pm->parse_graph))
- s = format (s, "\n<root>\n");
-
- item = pool_elt_at_index (pm->parse_items, node->item);
-
- s = format (s, "[%d] %U ", node - pm->parse_graph,
- format_vlib_parse_item, pm, item);
-
- if (node->peer == (u32) ~ 0)
- s = format (s, "peer nil ");
- else
- s = format (s, "peer %4u ", node->peer);
-
- if (node->deeper == (u32) ~ 0)
- s = format (s, "deeper nil ");
- else
- s = format (s, "deeper %4u ", node->deeper);
-
- return s;
-}
-
-void
-dump_parse_graph (void)
-{
- vlib_parse_main_t *pm = &vlib_parse_main;
- vlib_parse_graph_t *node;
-
- /* *INDENT-OFF* */
- pool_foreach (node, pm->parse_graph, ({
- fformat(stdout, "%U\n", format_vlib_parse_graph, pm, node);
- }));
-/* *INDENT-ON* */
-}
-
-always_inline void
-parse_cleanup_value (vlib_parse_main_t * pm, vlib_parse_value_t * pv)
-{
- vlib_parse_type_t *type = pool_elt_at_index (pm->parse_types, pv->type);
- if (type->value_cleanup_function)
- type->value_cleanup_function (pv);
-}
-
-static void
-parse_reset (vlib_parse_main_t * pm, u8 * input)
-{
- vlib_lex_token_t *t;
- vlib_parse_value_t *pv;
-
- vlib_lex_reset (pm->lex_main, input);
-
- vec_foreach (t, pm->tokens) vlib_lex_cleanup_token (t);
-
- vec_foreach (pv, pm->parse_value) parse_cleanup_value (pm, pv);
-
- _vec_len (pm->parse_value) = 0;
- _vec_len (pm->tokens) = 0;
- pm->current_token_index = 0;
-}
-
-static void
-parse_help (vlib_parse_main_t * pm, u32 index)
-{
- vlib_parse_graph_t *node;
- vlib_parse_item_t *item;
- vlib_parse_type_t *type;
- vlib_main_t *vm = pm->vlib_main;
- u8 *help_input;
- int i;
-
- help_input = vec_dup (pm->lex_main->input_vector);
-
- for (i = vec_len (help_input) - 1; i >= 0; i--)
- if (help_input[i] == '?')
- {
- help_input[i] = 0;
- _vec_len (help_input) = i;
- break;
- }
-
- for (i = vec_len (help_input) - 1; i >= 0; i--)
- {
- if (help_input[i] != ' ' && help_input[i] != '\t')
- break;
- help_input[i] = 0;
- break;
- }
- _vec_len (help_input) = i + 1;
-
- while (index != (u32) ~ 0)
- {
- node = pool_elt_at_index (pm->parse_graph, index);
- item = pool_elt_at_index (pm->parse_items, node->item);
- type = pool_elt_at_index (pm->parse_types, item->type);
-
- if (item->type == eof_type_index && vec_len (pm->match_items) == 0)
- /* do nothing */ ;
- else if (item->type == word_type_index)
- vlib_cli_output (vm, "%s %s\n", help_input, item->value.as_pointer);
- else
- vlib_cli_output (vm, "%s <%s>\n", help_input, type->name);
- index = node->peer;
- }
- vec_free (help_input);
-}
-
-static vlib_parse_match_t
-parse_eval_internal (vlib_parse_main_t * pm, u32 index)
-{
- vlib_parse_graph_t *node;
- vlib_parse_item_t *item;
- vlib_parse_type_t *type;
- vlib_parse_value_t value, *pv;
- vlib_parse_match_t rv;
- u32 *partial_matches = 0;
- vlib_lex_token_t *t;
- u32 save_token_index = (u32) ~ 0, save_match_items = 0;
- int had_value = 0;
-
- if (pm->current_token_index >= vec_len (pm->tokens))
- return VLIB_PARSE_MATCH_FAIL;
-
- /* current token */
- t = vec_elt_at_index (pm->tokens, pm->current_token_index);
-
- /* Help ? */
- if (PREDICT_FALSE (t->token == VLIB_LEX_qmark))
- {
- parse_help (pm, index);
- _vec_len (pm->match_items) = 0;
- return VLIB_PARSE_MATCH_DONE;
- }
-
- /* Across all peers at this level of the parse graph */
- while (index != (u32) ~ 0)
- {
- node = pool_elt_at_index (pm->parse_graph, index);
- item = pool_elt_at_index (pm->parse_items, node->item);
- type = pool_elt_at_index (pm->parse_types, item->type);
-
- /*
- * Save the token index. We may have to back up several
- * trie plies. Type-specific match functions can consume
- * multiple tokens, and they may not be optimally careful
- */
- save_token_index = pm->current_token_index;
- save_match_items = vec_len (pm->match_items);
- vec_add1 (pm->match_items, node->item);
-
- if (PARSE_DEBUG > 1)
- clib_warning ("Try to match token %U against node %d",
- format_vlib_lex_token, pm->lex_main, t, index);
-
- /* Call the type-specific match function */
- rv = type->match_function (pm, type, t, &value);
-
- if (PARSE_DEBUG > 1)
- clib_warning ("returned %U", format_vlib_parse_match, rv);
-
- switch (rv)
- {
- case VLIB_PARSE_MATCH_VALUE:
- /*
- * Matched, and returned a value to append to the
- * set of args passed to the action function
- */
- value.type = item->type;
- vec_add1 (pm->parse_value, value);
- had_value = 1;
- /* fallthrough */
-
- case VLIB_PARSE_MATCH_FULL:
- unambiguous_partial_match:
- /* Consume the matched token */
- pm->current_token_index++;
-
- /* continue matching along this path */
- rv = parse_eval_internal (pm, node->deeper);
-
- /* this is not the right path */
- if (rv == VLIB_PARSE_MATCH_FAIL)
- {
- if (had_value)
- {
- /* Delete the value */
- value = pm->parse_value[vec_len (pm->parse_value) - 1];
- parse_cleanup_value (pm, &value);
- _vec_len (pm->parse_value) -= 1;
- }
- /* Continue with the next sibling */
- pm->current_token_index = save_token_index;
- _vec_len (pm->match_items) = save_match_items;
- index = node->peer;
- break;
- }
- return rv;
-
- case VLIB_PARSE_MATCH_PARTIAL:
- /* Partial (substring) match, remember it but keep going */
- vec_add1 (partial_matches, node - pm->parse_graph);
- index = node->peer;
- break;
-
- case VLIB_PARSE_MATCH_FAIL:
- /* Continue with the next sibling */
- index = node->peer;
- _vec_len (pm->match_items) = save_match_items;
- break;
-
- case VLIB_PARSE_MATCH_DONE:
- /* Parse complete, invoke the action function */
- if (PARSE_DEBUG > 0)
- clib_warning ("parse_value: %U", format_vlib_parse_value, pm);
-
- {
- vlib_parse_eval_function_t *f = item->value.as_pointer;
- if (f)
- rv = f (pm, item, pm->parse_value);
- }
-
- vec_foreach (pv, pm->parse_value) parse_cleanup_value (pm, pv);
- _vec_len (pm->parse_value) = 0;
- _vec_len (pm->match_items) = 0;
- return rv;
-
- case VLIB_PARSE_MATCH_AMBIGUOUS:
- case VLIB_PARSE_MATCH_EVAL_FAIL:
- case VLIB_PARSE_MATCH_RULE:
- _vec_len (pm->match_items) = save_match_items;
- return rv;
- }
- }
-
- /*
- * Out of siblings. If we have exactly one partial match
- * we win
- */
- if (vec_len (partial_matches) == 1)
- {
- index = partial_matches[0];
- node = pool_elt_at_index (pm->parse_graph, index);
- vec_free (partial_matches);
- goto unambiguous_partial_match;
- }
-
- /* Ordinary loser */
- rv = VLIB_PARSE_MATCH_FAIL;
-
- /* Ambiguous loser */
- if (vec_len (partial_matches) > 1)
- {
- vec_free (partial_matches);
- rv = VLIB_PARSE_MATCH_AMBIGUOUS;
- }
-
- _vec_len (pm->match_items) = save_match_items;
- return rv;
-}
-
-vlib_parse_match_t
-rule_match (vlib_parse_main_t * pm, vlib_parse_type_t * type,
- vlib_lex_token_t * t, vlib_parse_value_t * valuep)
-{
- vlib_parse_match_t rv;
- static int recursion_level;
-
- if (PARSE_DEBUG > 1)
- clib_warning ("[%d]: try to match type %s graph index %d",
- recursion_level, type->name, type->rule_index);
- recursion_level++;
- rv = parse_eval_internal (pm, type->rule_index);
- recursion_level--;
-
- /* Break the recusive unwind here... */
- if (rv == VLIB_PARSE_MATCH_RULE)
- {
- if (PARSE_DEBUG > 1)
- clib_warning ("[%d]: type %s matched", recursion_level, type->name);
-
- return VLIB_PARSE_MATCH_FULL;
- }
- else
- {
- if (PARSE_DEBUG > 1)
- clib_warning ("[%d]: type %s returns %U", recursion_level, type->name,
- format_vlib_parse_match, rv);
- }
- return rv;
-}
-
-static int
-parse_eval (vlib_parse_main_t * pm, u8 * input)
-{
- vlib_lex_token_t *t;
-
- parse_reset (pm, input);
-
- /* Tokenize the entire input vector */
- do
- {
- vec_add2 (pm->tokens, t, 1);
- vlib_lex_get_token (pm->lex_main, t);
- }
- while (t->token != VLIB_LEX_eof);
-
- /* Feed it to the parser */
- return parse_eval_internal (pm, pm->root_index);
-}
-
-/* Temporary vlib stub */
-vlib_parse_match_t
-vlib_parse_eval (u8 * input)
-{
- return parse_eval (&vlib_parse_main, input);
-}
-
-u16
-parse_type_find_or_create (vlib_parse_main_t * pm, vlib_parse_type_t * t)
-{
- uword *p;
- vlib_parse_type_t *n;
- u8 *name_copy;
-
- p = hash_get_mem (pm->parse_type_by_name_hash, t->name);
- if (p)
- return p[0];
-
- pool_get (pm->parse_types, n);
- *n = *t;
- n->rule_index = (u32) ~ 0;
-
- name_copy = format (0, "%s%c", n->name, 0);
-
- hash_set_mem (pm->parse_type_by_name_hash, name_copy, n - pm->parse_types);
- return n - pm->parse_types;
-}
-
-u16
-parse_type_find_by_name (vlib_parse_main_t * pm, char *name)
-{
- uword *p;
-
- p = hash_get_mem (pm->parse_type_by_name_hash, name);
- if (p)
- return p[0];
-
- return (u16) ~ 0;
-}
-
-u32
-parse_item_find_or_create (vlib_parse_main_t * pm, vlib_parse_item_t * item)
-{
- uword *p;
- vlib_parse_item_t *i;
-
- /* Exact match the entire item */
- p = mhash_get (&pm->parse_item_hash, item);
- if (p)
- return p[0];
-
- pool_get (pm->parse_items, i);
- *i = *item;
-
- mhash_set (&pm->parse_item_hash, i, i - pm->parse_items, 0);
- return i - pm->parse_items;
-}
-
-static void
-parse_type_and_graph_init (vlib_parse_main_t * pm)
-{
- u32 eof_index;
- vlib_parse_type_t type;
- vlib_parse_item_t item;
-
- memset (&type, 0, sizeof (type));
-
-#define foreach_token_type \
- _ (eof) \
- _ (rule_eof) \
- _ (word) \
- _ (number) \
- _ (plus) \
- _ (minus) \
- _ (star) \
- _ (slash) \
- _ (lpar) \
- _ (rpar)
-
-#define _(a) a##_type_index = parse_type_find_by_name (pm, #a);
- foreach_token_type
-#undef _
- memset (&item, 0, sizeof (item));
- item.type = eof_type_index;
-
- eof_index = parse_item_find_or_create (pm, &item);
- pm->root_index = (u32) ~ 0;
-
-#if 0
- pool_get (pm->parse_graph, g);
- memset (g, 0xff, sizeof (*g));
- g->item = eof_index;
- pm->root_index = 0;
-#endif
-}
-
-
-
-static void
-tokenize (vlib_parse_main_t * pm, parse_registration_t * pr)
-{
- vlib_lex_token_t *t;
- pm->register_input = format (pm->register_input,
- "%s%c", pr->initializer, 0);
-
- parse_reset (pm, pm->register_input);
-
- do
- {
- vec_add2 (pm->tokens, t, 1);
- vlib_lex_get_token (pm->lex_main, t);
- }
- while (t->token != VLIB_LEX_eof);
- _vec_len (pm->register_input) = 0;
-}
-
-static int
-is_typed_rule (vlib_parse_main_t * pm)
-{
- vlib_lex_token_t *t = vec_elt_at_index (pm->tokens, 0);
-
- /* <mytype> = blah blah blah */
- if (vec_len (pm->tokens) >= 4
- && t[0].token == VLIB_LEX_lt
- && t[1].token == VLIB_LEX_word
- && t[2].token == VLIB_LEX_gt && t[3].token == VLIB_LEX_equals)
- return 1;
- return 0;
-}
-
-static int
-token_matches_graph_node (vlib_parse_main_t * pm,
- vlib_lex_token_t * t,
- vlib_parse_graph_t * node,
- vlib_parse_item_t * item,
- vlib_parse_type_t * type, u32 * token_increment)
-{
- /* EOFs don't match */
- if (t->token == VLIB_LEX_eof)
- return 0;
-
- /* New chain element is a word */
- if (t->token == VLIB_LEX_word)
- {
- /* but the item in hand is not a word */
- if (item->type != word_type_index)
- return 0;
-
- /* Or it's not this particular word */
- if (strcmp (t->value.as_pointer, item->value.as_pointer))
- return 0;
- *token_increment = 1;
- return 1;
- }
- /* New chain element is a type-name: < TYPE-NAME > */
- if (t->token == VLIB_LEX_lt)
- {
- u16 token_type_index;
-
- /* < TYPE > */
- if (t[1].token != VLIB_LEX_word || t[2].token != VLIB_LEX_gt)
- {
- clib_warning (0, "broken type name in '%s'", pm->register_input);
- return 0;
- }
-
- token_type_index = parse_type_find_by_name (pm, t[1].value.as_pointer);
- if (token_type_index == (u16) ~ 0)
- {
- clib_warning (0, "unknown type '%s'", t[1].value.as_pointer);
- return 0;
- }
-
- /* Its a known type but does not match. */
- if (item->type != token_type_index)
- return 0;
-
- *token_increment = 3;
- return 1;
- }
- clib_warning ("BUG: t->token = %d", t->token);
- return 0;
-}
-
-u32
-generate_subgraph_from_tokens (vlib_parse_main_t * pm,
- vlib_lex_token_t * t,
- u32 * new_subgraph_depth,
- parse_registration_t * pr, int not_a_rule)
-{
- vlib_parse_graph_t *g, *last_g;
- vlib_parse_item_t new_item;
- u32 rv = (u32) ~ 0, new_item_index, last_index = (u32) ~ 0;
- u16 token_type_index;
- u32 depth = 0;
-
- while (t < pm->tokens + vec_len (pm->tokens))
- {
- memset (&new_item, 0, sizeof (new_item));
-
- if (t->token == VLIB_LEX_word)
- {
- new_item.type = word_type_index;
- new_item.value.as_pointer = vec_dup ((u8 *) t->value.as_pointer);
- new_item_index = parse_item_find_or_create (pm, &new_item);
- t++;
- }
- else if (t->token == VLIB_LEX_lt)
- {
- if (t[1].token != VLIB_LEX_word || t[2].token != VLIB_LEX_gt)
- {
- clib_warning ("broken type name in '%s'", pm->register_input);
- goto screwed;
- }
- token_type_index = parse_type_find_by_name (pm,
- t[1].value.as_pointer);
- if (token_type_index == (u16) ~ 0)
- {
- clib_warning ("unknown type 2 '%s'", t[1].value.as_pointer);
- goto screwed;
- }
-
- new_item.type = token_type_index;
- new_item.value.as_pointer = 0;
- new_item_index = parse_item_find_or_create (pm, &new_item);
- t += 3; /* skip < <type-name> and > */
- }
- else if (t->token == VLIB_LEX_eof)
- {
- screwed:
- new_item.type = not_a_rule ? eof_type_index : rule_eof_type_index;
- new_item.value.as_pointer = pr->eof_match;
- new_item_index = parse_item_find_or_create (pm, &new_item);
- t++;
- }
- else
- {
- clib_warning ("unexpected token %U index %d in '%s'",
- format_vlib_lex_token, pm->lex_main, t,
- t - pm->tokens, pm->register_input);
- goto screwed;
- }
-
- pool_get (pm->parse_graph, g);
- memset (g, 0xff, sizeof (*g));
- g->item = new_item_index;
- depth++;
-
- if (rv == (u32) ~ 0)
- {
- rv = g - pm->parse_graph;
- last_index = rv;
- }
- else
- {
- last_g = pool_elt_at_index (pm->parse_graph, last_index);
- last_index = last_g->deeper = g - pm->parse_graph;
- }
- }
- *new_subgraph_depth = depth;
- return rv;
-}
-
-static u32
-measure_depth (vlib_parse_main_t * pm, u32 index)
-{
- vlib_parse_graph_t *node;
- vlib_parse_item_t *item;
- u32 max = 0;
- u32 depth;
-
- if (index == (u32) ~ 0)
- return 0;
-
- node = pool_elt_at_index (pm->parse_graph, index);
- item = pool_elt_at_index (pm->parse_items, node->item);
-
- if (item->type == eof_type_index)
- return 1;
-
- while (index != (u32) ~ 0)
- {
- node = pool_elt_at_index (pm->parse_graph, index);
- depth = measure_depth (pm, node->deeper);
- if (max < depth)
- max = depth;
- index = node->peer;
- }
-
- return max + 1;
-}
-
-static void
-add_subgraph_to_graph (vlib_parse_main_t * pm,
- u32 last_matching_index,
- u32 graph_root_index,
- u32 new_subgraph_index, u32 new_subgraph_depth)
-{
- vlib_parse_graph_t *parent_node;
- int new_subgraph_longest = 1;
- u32 current_peer_index;
- u32 current_depth;
- vlib_parse_graph_t *current_peer = 0;
- vlib_parse_graph_t *new_subgraph_node =
- pool_elt_at_index (pm->parse_graph, new_subgraph_index);
-
- /*
- * Case 1: top-level peer. Splice into the top-level
- * peer chain according to rule depth
- */
- if (last_matching_index == (u32) ~ 0)
- {
- u32 index = graph_root_index;
- while (1)
- {
- current_peer = pool_elt_at_index (pm->parse_graph, index);
- current_depth = measure_depth (pm, index);
- if (current_depth < new_subgraph_depth
- || current_peer->peer == (u32) ~ 0)
- break;
- index = current_peer->peer;
- }
- new_subgraph_node->peer = current_peer->peer;
- current_peer->peer = new_subgraph_index;
- return;
- }
-
- parent_node = pool_elt_at_index (pm->parse_graph, last_matching_index);
- current_peer_index = parent_node->deeper;
-
- while (current_peer_index != (u32) ~ 0)
- {
- current_peer = pool_elt_at_index (pm->parse_graph, current_peer_index);
- current_depth = measure_depth (pm, current_peer_index);
- if (current_depth < new_subgraph_depth)
- break;
- new_subgraph_longest = 0;
- current_peer_index = current_peer->peer;
- }
-
- ASSERT (current_peer);
-
- if (new_subgraph_longest)
- {
- new_subgraph_node->peer = parent_node->deeper;
- parent_node->deeper = new_subgraph_index;
- }
- else
- {
- new_subgraph_node->peer = current_peer->peer;
- current_peer->peer = new_subgraph_index;
- }
-}
-
-static clib_error_t *
-parse_register_one (vlib_parse_main_t * pm, parse_registration_t * pr)
-{
- u32 graph_root_index;
- u16 subgraph_type_index = (u16) ~ 0;
- vlib_parse_type_t *subgraph_type = 0;
- vlib_lex_token_t *t;
- vlib_parse_graph_t *node;
- u32 node_index, last_index, token_increment, new_subgraph_index;
- u32 new_subgraph_depth, last_matching_index;
- vlib_parse_item_t *item;
- vlib_parse_type_t *type;
-
- int use_main_graph = 1;
-
- tokenize (pm, pr);
-
- /* A typed rule? */
- if (is_typed_rule (pm))
- {
- /* Get the type and its current subgraph root, if any */
- t = vec_elt_at_index (pm->tokens, 1);
- subgraph_type_index = parse_type_find_by_name (pm, t->value.as_pointer);
- if (subgraph_type_index == (u16) ~ 0)
- return clib_error_return (0, "undeclared type '%s'",
- t->value.as_pointer);
- subgraph_type =
- pool_elt_at_index (pm->parse_types, subgraph_type_index);
- graph_root_index = subgraph_type->rule_index;
- /* Skip "mytype> = */
- t += 3;
- use_main_graph = 0;
- }
- else
- {
- /* top-level graph */
- graph_root_index = pm->root_index;
- t = vec_elt_at_index (pm->tokens, 0);
- }
-
- last_matching_index = (u32) ~ 0;
- last_index = node_index = graph_root_index;
-
- /* Find the first token which isn't already being parsed */
- while (t < pm->tokens + vec_len (pm->tokens) && node_index != (u32) ~ 0)
- {
- node = pool_elt_at_index (pm->parse_graph, node_index);
- item = pool_elt_at_index (pm->parse_items, node->item);
- type = pool_elt_at_index (pm->parse_types, item->type);
- last_index = node_index;
-
- if (token_matches_graph_node
- (pm, t, node, item, type, &token_increment))
- {
- t += token_increment;
- last_matching_index = node_index;
- node_index = node->deeper;
- }
- else
- node_index = node->peer;
- }
-
- new_subgraph_index =
- generate_subgraph_from_tokens (pm, t, &new_subgraph_depth, pr,
- use_main_graph);
-
- /* trivial cases: first graph node or first type rule */
- if (graph_root_index == (u32) ~ 0)
- {
- if (use_main_graph)
- pm->root_index = new_subgraph_index;
- else
- subgraph_type->rule_index = new_subgraph_index;
- return 0;
- }
-
- add_subgraph_to_graph (pm, last_matching_index, graph_root_index,
- new_subgraph_index, new_subgraph_depth);
- return 0;
-}
-
-static clib_error_t *
-parse_register (vlib_main_t * vm,
- parse_registration_t * lo,
- parse_registration_t * hi, vlib_parse_main_t * pm)
-{
- parse_registration_t *pr;
-
- for (pr = lo; pr < hi; pr = vlib_elf_section_data_next (pr, 0))
- vec_add1 (pm->parse_registrations, pr);
-
- return 0;
-}
-
-static clib_error_t *
-parse_register_one_type (vlib_parse_main_t * pm, vlib_parse_type_t * rp)
-{
- (void) parse_type_find_or_create (pm, (vlib_parse_type_t *) rp);
- return 0;
-}
-
-static clib_error_t *
-parse_type_register (vlib_main_t * vm,
- vlib_parse_type_t * lo,
- vlib_parse_type_t * hi, vlib_parse_main_t * pm)
-{
- clib_error_t *error = 0;
- vlib_parse_type_t *ptr;
-
- for (ptr = lo; ptr < hi; ptr = vlib_elf_section_data_next (ptr, 0))
- {
- error = parse_register_one_type (pm, ptr);
- if (error)
- goto done;
- }
-
-done:
- return error;
-}
-
-clib_error_t *vlib_stdlex_init (vlib_main_t * vm) __attribute__ ((weak));
-clib_error_t *
-vlib_stdlex_init (vlib_main_t * vm)
-{
- (void) vlib_lex_add_table ("ignore_everything");
- return 0;
-}
-
-static int
-compute_rule_length (parse_registration_t * r)
-{
- int length, i;
- vlib_parse_main_t *pm = &vlib_parse_main;
-
- if (r->rule_length)
- return r->rule_length;
-
- length = 0;
-
- tokenize (pm, r);
- length = vec_len (pm->tokens);
-
- /* Account for "<foo> = " in "<foo> = bar" etc. */
- if (is_typed_rule (pm))
- length -= 2;
-
- for (i = 0; i < vec_len (pm->tokens); i++)
- {
- switch (pm->tokens[i].token)
- {
- case VLIB_LEX_lt:
- case VLIB_LEX_gt:
- length -= 1;
-
- default:
- break;
- }
- }
-
- ASSERT (length > 0);
- r->rule_length = length;
- return length;
-}
-
-static int
-rule_length_compare (parse_registration_t * r1, parse_registration_t * r2)
-{
- compute_rule_length (r1);
- compute_rule_length (r2);
- /* Descending sort */
- return r2->rule_length - r1->rule_length;
-}
-
-
-static clib_error_t *
-parse_init (vlib_main_t * vm)
-{
- vlib_parse_main_t *pm = &vlib_parse_main;
- vlib_lex_main_t *lm = &vlib_lex_main;
- vlib_elf_section_bounds_t *b, *bounds;
- clib_error_t *error = 0;
- parse_registration_t *rule;
- int i;
-
- if ((error = vlib_call_init_function (vm, lex_onetime_init)))
- return error;
-
- if ((error = vlib_stdlex_init (vm)))
- return error;
-
- if ((error = vlib_call_init_function (vm, parse_builtin_init)))
- return error;
-
- pm->vlib_main = vm;
- pm->lex_main = lm;
-
- mhash_init (&pm->parse_item_hash, sizeof (u32), sizeof (vlib_parse_item_t));
- pm->parse_type_by_name_hash = hash_create_string (0, sizeof (u32));
-
- vec_validate (pm->parse_value, 16);
- vec_validate (pm->tokens, 16);
- vec_validate (pm->register_input, 32);
- vec_validate (pm->match_items, 16);
-
- _vec_len (pm->parse_value) = 0;
- _vec_len (pm->tokens) = 0;
- _vec_len (pm->register_input) = 0;
- _vec_len (pm->match_items) = 0;
-
- bounds = vlib_get_elf_section_bounds (vm, "parse_type_registrations");
- vec_foreach (b, bounds)
- {
- error = parse_type_register (vm, b->lo, b->hi, pm);
- if (error)
- break;
- }
- vec_free (bounds);
-
- parse_type_and_graph_init (pm);
-
- bounds = vlib_get_elf_section_bounds (vm, "parse_registrations");
- vec_foreach (b, bounds)
- {
- error = parse_register (vm, b->lo, b->hi, pm);
- if (error)
- break;
- }
- vec_free (bounds);
-
- vec_sort_with_function (pm->parse_registrations, rule_length_compare);
-
- for (i = 0; i < vec_len (pm->parse_registrations); i++)
- {
- rule = pm->parse_registrations[i];
- parse_register_one (pm, rule);
- }
-
- return error;
-}
-
-VLIB_INIT_FUNCTION (parse_init);
-
-/*
- * fd.io coding-style-patch-verification: ON
- *
- * Local Variables:
- * eval: (c-set-style "gnu")
- * End:
- */