diff options
Diffstat (limited to 'src/vlib/parse.c')
-rw-r--r-- | src/vlib/parse.c | 1007 |
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: - */ |