summaryrefslogtreecommitdiffstats
path: root/lib/command_parse.h
diff options
context:
space:
mode:
Diffstat (limited to 'lib/command_parse.h')
-rw-r--r--lib/command_parse.h814
1 files changed, 814 insertions, 0 deletions
diff --git a/lib/command_parse.h b/lib/command_parse.h
new file mode 100644
index 00000000..ee219f84
--- /dev/null
+++ b/lib/command_parse.h
@@ -0,0 +1,814 @@
+/* Quagga command line parsing -- header
+ * Copyright (C) 1997, 98 Kunihiro Ishiguro
+ *
+ * Recast and extended: Copyright (C) 2010 Chris Hall (GMCH), Highwayman
+ *
+ * This file is part of GNU Zebra.
+ *
+ * GNU Zebra is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published
+ * by the Free Software Foundation; either version 2, or (at your
+ * option) any later version.
+ *
+ * GNU Zebra is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with GNU Zebra; see the file COPYING. If not, write to the
+ * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ * Boston, MA 02111-1307, USA.
+ */
+
+#ifndef _ZEBRA_COMMAND_PARSE_H
+#define _ZEBRA_COMMAND_PARSE_H
+
+#include "misc.h"
+
+#include "command_common.h"
+#include "vector.h"
+#include "vio_fifo.h"
+#include "qstring.h"
+#include "elstring.h"
+#include "qpath.h"
+#include "elstring.h"
+#include "memory.h"
+
+#if 0
+/*==============================================================================
+ * Parsing of tokens
+ */
+
+enum cmd_token_spec
+{
+ cmd_ts_simple = 0,
+
+ cmd_ts_keyword,
+ cmd_ts_number,
+ cmd_ts_word,
+ cmd_ts_option,
+
+ cmd_ts_ipv4_addr,
+ cmd_ts_ipv4_prefix,
+
+ cmd_ts_ipv6_addr,
+ cmd_ts_ipv6_prefix,
+
+ cmd_ts_vararg,
+} ;
+typedef enum cmd_token_spec cmd_token_spec_t ;
+#endif
+
+/*==============================================================================
+ * Sexing of token types in command descriptions
+ */
+#define CMD_OPTION(S) ((S[0]) == '[')
+#define CMD_VARIABLE(S) (((S[0]) >= 'A' && (S[0]) <= 'Z') || ((S[0]) == '<'))
+#define CMD_VARARG(S) ((S[0]) == '.')
+#define CMD_RANGE(S) ((S[0] == '<'))
+
+#define CMD_IPV4(S) ((strcmp ((S), "A.B.C.D") == 0))
+#define CMD_IPV4_PREFIX(S) ((strcmp ((S), "A.B.C.D/M") == 0))
+#define CMD_IPV6(S) ((strcmp ((S), "X:X::X:X") == 0))
+#define CMD_IPV6_PREFIX(S) ((strcmp ((S), "X:X::X:X/M") == 0))
+
+/*==============================================================================
+ * Command Items.
+ *
+ * A command is compiled into a vector of lists of command items -- the
+ * cmd_command->items (so called).
+ *
+ */
+
+/* Command item types
+ *
+ * NB: the command items sort according to this -- highest first.
+ *
+ * NB: this is in the same order as the match_type -- and should remain so.
+ * See match_type below for further discussion of the hierarchy.
+ */
+enum cmd_item_type
+{
+ item_null,
+
+ item_eol,
+
+ item_option_word,
+
+ item_vararg, /* rest of the line */
+ item_word,
+
+ item_ipv6_prefix,
+ item_ipv6_address,
+ item_ipv4_prefix,
+ item_ipv4_address,
+
+ item_range,
+
+ item_keyword,
+
+ item_type_count, /* number of types */
+} ;
+typedef enum cmd_item_type cmd_item_type_t ;
+
+enum {
+ item_max_number = 0xFFFFFFFF /* can be +/- this */
+} ;
+
+CONFIRM(LONG_MAX >= item_max_number) ;
+
+enum cmd_item_type_bit
+{
+ item_null_bit = BIT(item_null),
+ item_eol_bit = BIT(item_eol),
+ item_option_word_bit = BIT(item_option_word),
+ item_vararg_bit = BIT(item_vararg),
+ item_word_bit = BIT(item_word),
+ item_ipv6_prefix_bit = BIT(item_ipv6_prefix),
+ item_ipv6_address_bit = BIT(item_ipv6_address),
+ item_ipv4_prefix_bit = BIT(item_ipv4_prefix),
+ item_ipv4_address_bit = BIT(item_ipv4_address),
+ item_range_bit = BIT(item_range),
+ item_keyword_bit = BIT(item_keyword),
+} ;
+typedef enum cmd_item_type_bit cmd_item_type_bit_t ;
+
+/*------------------------------------------------------------------------------
+ * Sex cmd_item_type and return whether it is an "option" type, or not.
+ *
+ * NB: tolerates item_null -- others may well not.
+ */
+Inline bool
+cmd_item_is_option(cmd_item_type_t itt)
+{
+ const static bool is_option[item_type_count] =
+ {
+ [item_null] = false,
+
+ [item_eol] = false,
+
+ [item_option_word] = true,
+
+ [item_vararg] = false,
+ [item_word] = false,
+
+ [item_ipv6_prefix] = false,
+ [item_ipv6_address] = false,
+ [item_ipv4_prefix] = false,
+ [item_ipv4_address] = false,
+
+ [item_range] = false,
+
+ [item_keyword] = false,
+ } ;
+
+ assert((itt >= 0) && (itt < item_type_count)) ;
+
+ return is_option[itt] ;
+} ;
+
+/*------------------------------------------------------------------------------
+ * Sex cmd_item_type and return whether it is an "vararg" type, or not.
+ *
+ * NB: tolerates item_null -- others may well not.
+ */
+Inline bool
+cmd_item_is_vararg(cmd_item_type_t itt)
+{
+ const static bool is_vararg[item_type_count] =
+ {
+ [item_null] = false,
+
+ [item_eol] = false,
+
+ [item_option_word] = false,
+
+ [item_vararg] = true,
+ [item_word] = false,
+
+ [item_ipv6_prefix] = false,
+ [item_ipv6_address] = false,
+ [item_ipv4_prefix] = false,
+ [item_ipv4_address] = false,
+
+ [item_range] = false,
+
+ [item_keyword] = false,
+ } ;
+
+ assert((itt >= 0) && (itt < item_type_count)) ;
+
+ return is_vararg[itt] ;
+} ;
+
+/*------------------------------------------------------------------------------
+ * The command item structure.
+ */
+typedef struct cmd_item* cmd_item ;
+struct cmd_item
+{
+ elstring_t str ; /* in some word_lump */
+
+ const char* doc ; /* in r_doc -- description text */
+
+ cmd_item next ; /* Next possibility (if any) */
+
+ cmd_item_type_t type ;
+ bool arg ; /* include in argv */
+
+ /* For item_range values */
+ bool range_sign_allowed ;
+ bool range_sign_required ;
+ long range_min ;
+ long range_max ;
+} ;
+
+/*==============================================================================
+ * Match strengths types and filter settings.
+ *
+ * When matching a token, may have a number of competing items, possibly of
+ * different types.
+ *
+ * For execution a token must match completely -- or, for keyword items,
+ * match partially at most one possible keyword.
+ */
+
+/* Match strength
+ *
+ * When matching a token against an item, the following are the possible
+ * results.
+ */
+enum match_strength
+{
+ ms_no_match = 0, /* match failed: token is definitely NOT
+ * the item in question.
+ */
+
+ ms_min_parse = ms_no_match + 1,
+ /* for parsing must match somehow ! */
+
+ ms_partial, /* match OK up to the end of the token, but
+ * more is required to complete it.
+ * This is used by the variable matches.
+ */
+
+ ms_min_execute = ms_partial + 1,
+ /* for execution must be at least this */
+
+ ms_anything, /* matches because will match anything.
+ * This is used for WORD and such like items.
+ */
+
+ ms_kwd_incomplete, /* keyword match OK, but not complete.
+ */
+
+ ms_var_complete, /* match succeeded: token is a complete and
+ * valid instance of the item in question
+ */
+
+ ms_kwd_complete /* match succeeded: token is a complete and
+ * valid instance of the item in question
+ */
+} ;
+typedef enum match_strength match_strength_t ;
+
+
+/* The match type indicates what has been matched and the strength of the
+ * match.
+ *
+ * NB: the order of these is significant, higher numbered match types are
+ * preferred over lower numbered ones.
+ *
+ * NB: this is in the same order as the cmd_item_type -- and should remain so.
+ *
+ * During the command filtering, when a token and an item match, and the
+ * match type is better than the match type to date, then all previous matches
+ * are discarded.
+ *
+ * The hierarchy means that, for example, '22' will match an IPv4 prefix
+ * partially, but that will be forgotten if it later matches a WORD, and that
+ * will be forgotten if it later matches a number range.
+ *
+ * The IPv6 items have a lower priority so that a simple decimal will prefer
+ * the simpler IPv4 address form. As soon as there is an 'a'..'f' or a ':',
+ * the IPv4 will no longer match.
+ *
+ * The partial keyword match is preferred over a partial anything else, but
+ * cannot mask a complete value !
+ *
+ * The relative ranking of: mt_option_word_match, mt_vararg_match, and
+ * mt_word_match, is more or less arbitrary -- if these are ever candidates
+ * at the same time, the commands are ambiguous.
+ *
+ */
+enum match_type
+{
+ mt_no_match,
+
+ mt_eol_partial, /* a partial match ! */
+
+ mt_ipv6_address_partial,
+ mt_ipv6_prefix_partial,
+ mt_ipv4_address_partial,
+ mt_ipv4_prefix_partial,
+
+ mt_range_partial,
+
+ mt_eol, /* an ms_anything match */
+
+ mt_option_word_match, /* anything can match a [WORD] */
+
+ mt_vararg_match, /* anything can match a .vararg */
+ mt_word_match, /* anything can match a WORD */
+
+ mt_keyword_incomplete,
+
+ mt_ipv6_prefix_complete,
+ mt_ipv6_address_complete,
+ mt_ipv4_prefix_complete,
+ mt_ipv4_address_complete,
+
+ mt_range_complete,
+
+ mt_keyword_complete,
+
+ match_type_count /* Number of match types */
+} ;
+typedef enum match_type match_type_t ;
+
+/*------------------------------------------------------------------------------
+ * Map match_type -> cmd_item_type
+ *
+ * From a match type extract the type of item which has been match, partially
+ * or completely.
+ */
+Inline cmd_item_type_t
+match_item_type(match_type_t mt)
+{
+ static cmd_item_type_t match_item_type[match_type_count] =
+ {
+ [mt_no_match] = item_null,
+
+ [mt_eol_partial] = item_eol,
+
+ [mt_ipv4_prefix_partial] = item_ipv4_prefix,
+ [mt_ipv4_address_partial] = item_ipv4_address,
+ [mt_ipv6_prefix_partial] = item_ipv6_prefix,
+ [mt_ipv6_address_partial] = item_ipv6_address,
+
+ [mt_range_partial] = item_range,
+
+ [mt_eol] = item_eol,
+
+ [mt_option_word_match] = item_option_word,
+
+ [mt_vararg_match] = item_vararg,
+ [mt_word_match] = item_word,
+
+ [mt_keyword_incomplete] = item_keyword,
+
+ [mt_ipv6_prefix_complete] = item_ipv6_prefix,
+ [mt_ipv6_address_complete] = item_ipv6_address,
+ [mt_ipv4_prefix_complete] = item_ipv4_prefix,
+ [mt_ipv4_address_complete] = item_ipv4_address,
+
+ [mt_range_complete] = item_range,
+
+ [mt_keyword_complete] = item_keyword,
+ } ;
+
+ assert((mt >= 0) && (mt < match_type_count)) ;
+
+ return match_item_type[mt] ;
+} ;
+
+/*------------------------------------------------------------------------------
+ * Map match_type -> match_strength.
+ *
+ * From a match type extract the strength of the match.
+ */
+Inline match_strength_t
+match_match_strength(match_type_t mt)
+{
+ const static match_strength_t match_match_strength[match_type_count] =
+ {
+ [mt_no_match] = ms_no_match,
+
+ [mt_eol_partial] = ms_partial,
+
+ [mt_ipv6_prefix_partial] = ms_partial,
+ [mt_ipv6_address_partial] = ms_partial,
+ [mt_ipv4_prefix_partial] = ms_partial,
+ [mt_ipv4_address_partial] = ms_partial,
+
+ [mt_range_partial] = ms_partial,
+
+ [mt_eol] = ms_anything,
+
+ [mt_option_word_match] = ms_anything,
+
+ [mt_vararg_match] = ms_anything,
+ [mt_word_match] = ms_anything,
+
+ [mt_keyword_incomplete] = ms_kwd_incomplete,
+
+ [mt_ipv6_prefix_complete] = ms_var_complete,
+ [mt_ipv6_address_complete] = ms_var_complete,
+ [mt_ipv4_prefix_complete] = ms_var_complete,
+ [mt_ipv4_address_complete] = ms_var_complete,
+
+ [mt_range_complete] = ms_var_complete,
+
+ [mt_keyword_complete] = ms_kwd_complete,
+ } ;
+
+ assert((mt >= 0) && (mt < match_type_count)) ;
+
+ return match_match_strength[mt] ;
+} ;
+
+/*------------------------------------------------------------------------------
+ * Map cmd_item_type -> best possible match type.
+ *
+ * This gives the most optimistic outcome of an attempt to match to the given
+ * type of item.
+ *
+ * NB: tolerates item_null -- others may not
+ */
+Inline match_type_t
+item_best_match(cmd_item_type_t it)
+{
+ const static match_type_t item_best_match[item_type_count] =
+ {
+ [item_null] = mt_no_match,
+
+ [item_eol] = mt_eol,
+
+ [item_option_word] = mt_option_word_match,
+
+ [item_vararg] = mt_vararg_match,
+ [item_word] = mt_word_match,
+
+ [item_ipv6_prefix] = mt_ipv6_prefix_complete,
+ [item_ipv6_address] = mt_ipv6_address_complete,
+ [item_ipv4_prefix] = mt_ipv4_prefix_complete,
+ [item_ipv4_address] = mt_ipv4_address_complete,
+
+ [item_range] = mt_range_complete,
+
+ [item_keyword] = mt_keyword_complete,
+ } ;
+
+ assert((it >= 0) && (it < item_type_count)) ;
+
+ return item_best_match[it] ;
+} ;
+
+/*==============================================================================
+ *
+ */
+
+/* Pipe types */
+enum cmd_pipe_type /* bit significant */
+{
+ cmd_pipe_none = 0,
+
+ cmd_pipe_file = BIT(0),
+ cmd_pipe_shell = BIT(1),
+ cmd_pipe_dev_null = BIT(2), /* out pipe only -- black hole */
+
+ /* For in pipes */
+ cmd_pipe_reflect = BIT(4), /* + option */
+
+ /* For out file pipes */
+ cmd_pipe_append = BIT(4), /* >> */
+
+ /* For out shell pipes */
+ cmd_pipe_shell_cmd = BIT(4), /* | at start of line */
+} ;
+typedef enum cmd_pipe_type cmd_pipe_type_t ;
+
+/* Parsed parts */
+enum cmd_parts /* bit significant */
+{
+ cmd_parts_none = 0,
+
+ cmd_part_do = BIT(0),
+ cmd_part_command = BIT(1),
+
+ cmd_part_in_pipe = BIT(2),
+ cmd_part_out_pipe = BIT(3),
+
+ cmd_parts_pipe = (cmd_part_in_pipe | cmd_part_out_pipe),
+
+ cmd_part_comment = BIT(4),
+} ;
+typedef enum cmd_parts cmd_parts_t ;
+
+
+/*------------------------------------------------------------------------------
+ * Token object -- a qstring and some other properties.
+ */
+enum cmd_token_type /* *bit* significant */
+{
+ cmd_tok_eol = 0, /* all lines have one */
+
+ cmd_tok_simple = BIT( 0),
+
+ cmd_tok_sq = BIT( 4),
+ cmd_tok_dq = BIT( 5), /* '\\' within "..." are not
+ registered separately. */
+ cmd_tok_esc = BIT( 6),
+
+ cmd_tok_incomplete = (cmd_tok_sq | cmd_tok_dq | cmd_tok_esc),
+
+ cmd_tok_in_pipe = BIT( 8), /* token starting '<' */
+ cmd_tok_out_pipe = BIT( 9), /* token starting '>' */
+ cmd_tok_out_shell = BIT(10), /* token starting '|' */
+
+ cmd_tok_comment = BIT(14), /* token starting '!' or '#" */
+} ;
+typedef enum cmd_token_type cmd_token_type_t ;
+
+struct cmd_token
+{
+ cmd_token_type_t type ;
+ usize tp ; /* location of token in the line */
+
+ bool term ; /* token has been '\0' terminated */
+
+ qstring_t qs ; /* token string */
+ elstring_t ot ; /* original token in the line */
+
+ const void* word ; /* set when a word match is done */
+ ulen w_len ; /* length of word match */
+ int cw ; /* result of the word match */
+
+ cmd_item_type_bit_t seen ; /* bit set when match done */
+ match_type_t match[item_type_count] ;
+ /* result of match seen */
+} ;
+
+typedef struct cmd_token* cmd_token ;
+
+/*------------------------------------------------------------------------------
+ * Token vector -- a vector of token objects
+ */
+struct token_vector
+{
+ vector_t body ;
+} ;
+
+typedef struct token_vector token_vector_t[1] ;
+typedef struct token_vector* token_vector ;
+
+enum {
+ TOKEN_VECTOR_INIT_ALL_ZEROS = VECTOR_INIT_ALL_ZEROS
+} ;
+
+/*------------------------------------------------------------------------------
+ * Argument vector -- a vector of const char*
+ */
+struct arg_vector
+{
+ vector_t body ;
+} ;
+typedef struct arg_vector arg_vector_t[1] ;
+typedef struct arg_vector* arg_vector ;
+
+enum {
+ ARG_VECTOR_INIT_ALL_ZEROS = VECTOR_INIT_ALL_ZEROS
+} ;
+
+/*------------------------------------------------------------------------------
+ * Parsed command line
+ *
+ * The current command line is only valid while command is being parsed and
+ * executed -- in between it is nonsense. The pointer can be overwritten at
+ * any time -- responsibility for the memory lies elsewhere.
+ *
+ * The args vector is a set of pointers to the strings in the relevant tokens.
+ * This vector is only valid while command is being parsed and executed -- in
+ * between it too is nonsense. The pointers can be overwritten or discarded at
+ * any time -- responsibility for the memory lies elsewhere.
+ *
+ * The token vectors contain the tokens for the current command being parsed
+ * and executed. After the command has completed these vectors can be
+ * emptied -- see cmd_empty_parsed_tokens() -- but the next command to be
+ * parsed will tidy up before proceeding.
+ */
+struct cmd_parsed
+{
+ cmd_parts_t parts ; /* What parts are present */
+
+ cmd_token_type_t tok_total ; /* What token types are present */
+
+ usize elen ; /* effective length (less trailing spaces) */
+ usize tsp ; /* number of trailing spaces */
+
+ uint num_tokens ; /* number of tokens parsed */
+
+ token_vector tokens ; /* vector of token objects */
+
+ /* NB: the following are significant only if there is a command part
+ * or a do part
+ */
+ struct cmd_command *cmd ; /* NULL if empty command
+ or fails to parse */
+ node_type_t cnode ; /* node command is in */
+ node_type_t nnode ; /* node to set if command succeeds */
+
+ arg_vector args ; /* vector of arguments */
+
+ /* NB: the following are significant only if an error is returned */
+
+ qstring emess ; /* parse error */
+ ssize eloc ; /* error location */
+
+ /* NB: the following are significant only if respective part is
+ * present.
+ */
+ cmd_pipe_type_t in_pipe ; /* if any */
+ cmd_pipe_type_t out_pipe ; /* if any */
+
+ uint first_in_pipe ;
+ uint num_in_pipe ;
+
+ uint first_do ;
+ uint num_do ;
+
+ uint first_command ;
+ uint num_command ;
+
+ uint first_out_pipe ;
+ uint num_out_pipe ;
+
+ uint first_comment ;
+ uint num_comment ;
+
+ /* The following are significant after cmd_token_position() */
+
+ uint cti ; /* cursor token index -- may be eol token */
+ uint ctl ; /* cursor token length -- 0 <=> eol token */
+ int rp ; /* cursor relative to start of cursor token */
+
+ /* The following are used while filtering commands */
+
+ vector cmd_v ; /* working vector */
+ vector item_v ; /* working vector */
+
+ match_strength_t strongest ;
+ match_type_t best_complete ;
+
+ match_strength_t min_strength ; /* for execution */
+ bool strict ; /* for strict keyword match */
+} ;
+
+enum
+{
+ CMD_PARSED_INIT_ALL_ZEROS = (cmd_pipe_none == 0)
+} ;
+
+typedef struct cmd_parsed cmd_parsed_t[1] ;
+typedef struct cmd_parsed* cmd_parsed ;
+
+/*==============================================================================
+ * This is the stuff that defines the context in which commands are parsed,
+ * and then executed.
+ *
+ * The context lives in the cmd_exec. The CLI has a copy of the context,
+ * which it uses for the prompt and for command line help handling.
+ *
+ * Each time a new vin is pushed, the current context is copied to the current
+ * TOS (before the push).
+ *
+ * Easch time a vin is popped, the context is restored.
+ *
+ * Each time a vin or vout is pushed or popped the context the cmd_exec
+ * out_suppress and reflect flags must be updated.
+ */
+struct cmd_context
+{
+ /* The node between commands. */
+
+ node_type_t node ; /* updated on CMD_SUCCESS */
+
+ /* These properties affect the parsing of command lines. */
+
+ bool full_lex ; /* as required */
+
+ bool parse_execution ; /* parsing to execute */
+
+ bool parse_only ; /* do not execute */
+
+ bool parse_strict ; /* no incomplete keywords */
+ bool parse_no_do ; /* no 'do' commands */
+ bool parse_no_tree ; /* no tree walking */
+
+ bool can_auth_enable ; /* if required */
+ bool can_enable ; /* no (further) password needed */
+
+ /* These properties affect the execution of parsed commands. */
+
+ bool reflect_enabled ; /* per the pipe */
+
+ /* Special for AUTH_ENABLE_NODE -- going from/to */
+
+ node_type_t onode ; /* VIEW_NODE or RESTRICTED_NODE */
+ node_type_t tnode ; /* ENABLE_NODE or CONFIG_NODE */
+
+ /* The current directories. */
+
+ qpath dir_cd ; /* chdir directory */
+ qpath dir_home ; /* "~/" directory */
+ qpath dir_here ; /* "~./" directory */
+} ;
+
+typedef struct cmd_context cmd_context_t[1] ;
+typedef struct cmd_context* cmd_context ;
+
+/*==============================================================================
+ * Prototypes
+ */
+extern void cmd_compile(cmd_command cmd) ;
+extern void cmd_compile_check(cmd_command cmd) ;
+
+extern cmd_parsed cmd_parsed_new(void) ;
+extern cmd_parsed cmd_parsed_free(cmd_parsed parsed) ;
+
+extern bool cmd_is_empty(qstring line) ;
+extern void cmd_tokenize(cmd_parsed parsed, qstring line, bool full_lex) ;
+extern qstring cmd_tokens_concat(cmd_parsed parsed, uint ti, uint nt) ;
+
+extern cmd_return_code_t cmd_parse_command(cmd_parsed parsed,
+ cmd_context context) ;
+
+extern bool cmd_token_position(cmd_parsed parsed, qstring line) ;
+extern const char* cmd_help_preflight(cmd_parsed parsed) ;
+extern cmd_return_code_t cmd_completion(cmd_parsed parsed, cmd_context context);
+
+extern void cmd_complete_keyword(cmd_parsed parsed,
+ int* pre, int* rep, int* ins, int* mov) ;
+
+extern void cmd_get_parse_error(vio_fifo ebuf, cmd_parsed parsed, uint indent) ;
+
+extern void cmd_parser_init(void) ;
+
+
+
+//extern vector cmd_make_strvec (const char *);
+//extern vector cmd_add_to_strvec (vector v, const char* str) ;
+//extern void cmd_free_strvec (vector);
+extern vector cmd_describe_command (const char* line, node_type_t node,
+ cmd_return_code_t* status) ;
+extern vector cmd_complete_command (vector, int, int *status);
+
+
+
+//extern cmd_return_code_t cmd_parse_error(cmd_parsed parsed, cmd_token t,
+// usize off, const char* mess) ;
+
+//Inline const char* cmd_token_string(cmd_token t) ;
+//Inline char* cmd_token_make_string(cmd_token t) ;
+//Inline int cmd_token_count(token_vector tv) ;
+//Inline cmd_token cmd_token_get(token_vector tv, vector_index_t i) ;
+//Inline void cmd_token_set(token_vector tv, vector_index_t i,
+// cmd_token_type_t type, const char* p, usize len, usize tp) ;
+
+//extern cmd_return_code_t cmd_token_complete(cmd_parsed parsed, cmd_token t) ;
+//Inline const char* cmd_token_string(cmd_token t) ;
+//extern cmd_return_code_t cmd_parse_in_pipe(cmd_parsed parsed, cmd_token t) ;
+//extern cmd_return_code_t cmd_parse_out_pipe(cmd_parsed parsed, cmd_token t) ;
+
+//extern match_type_t cmd_ipv4_match (const char *str) ;
+//extern match_type_t cmd_ipv4_prefix_match (const char *str) ;
+#if HAVE_IPV6
+//extern match_type_t cmd_ipv6_match (const char *str) ;
+//extern match_type_t cmd_ipv6_prefix_match (const char *str) ;
+#endif
+//extern bool cmd_range_match (const char *range, const char *str) ;
+
+/*==============================================================================
+ * Inlines
+ */
+
+/*------------------------------------------------------------------------------
+ * Get the body of the argument vector.
+ */
+Inline const char * const*
+cmd_arg_vector_argv(cmd_parsed parsed)
+{
+ return (const char* const*)vector_body(parsed->args->body) ;
+} ;
+
+/*------------------------------------------------------------------------------
+ * Get length of the body of the argument vector.
+ */
+Inline unsigned
+cmd_arg_vector_argc(cmd_parsed parsed)
+{
+ return vector_length(parsed->args->body) ;
+} ;
+
+#endif /* _ZEBRA_COMMAND_PARSE_H */