summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--lib/command.c128
1 files changed, 112 insertions, 16 deletions
diff --git a/lib/command.c b/lib/command.c
index 04f83f4bb..3b5b8feba 100644
--- a/lib/command.c
+++ b/lib/command.c
@@ -41,12 +41,19 @@ vector cmdvec = NULL;
struct cmd_token token_cr;
char *command_cr = NULL;
+/**
+ * Filter types. These tell the parser whether to allow
+ * partial matching on tokens.
+ */
enum filter_type
{
FILTER_RELAXED,
FILTER_STRICT
};
+/**
+ * Command matcher result value.
+ */
enum matcher_rv
{
MATCHER_OK,
@@ -57,6 +64,11 @@ enum matcher_rv
MATCHER_EXCEED_ARGC_MAX
};
+/**
+ * Defines which matcher_rv values constitute
+ * an error. Should be used against matcher_rv
+ * return values to do basic error checking.
+ */
#define MATCHER_ERROR(matcher_rv) \
( (matcher_rv) == MATCHER_INCOMPLETE \
|| (matcher_rv) == MATCHER_NO_MATCH \
@@ -292,24 +304,29 @@ cmd_free_strvec (vector v)
vector_free (v);
}
+/**
+ * State structure for command format parser. Tracks
+ * parse tree position and miscellaneous state variables.
+ * Used when building a command vector from format strings.
+ */
struct format_parser_state
{
- vector topvect; /* Top level vector */
- vector intvect; /* Intermediate level vector, used when there's
- * a multiple in a keyword. */
- vector curvect; /* current vector where read tokens should be
- appended. */
-
- const char *string; /* pointer to command string, not modified */
- const char *cp; /* pointer in command string, moved along while
- parsing */
- const char *dp; /* pointer in description string, moved along while
- parsing */
-
- int in_keyword; /* flag to remember if we are in a keyword group */
- int in_multiple; /* flag to remember if we are in a multiple group */
- int just_read_word; /* flag to remember if the last thing we red was a
- * real word and not some abstract token */
+ vector topvect; /* Top level vector */
+ vector intvect; /* Intermediate level vector, used when there's
+ a multiple in a keyword. */
+ vector curvect; /* current vector where read tokens should be
+ appended. */
+
+ const char *string; /* pointer to command string, not modified */
+ const char *cp; /* pointer in command string, moved along while
+ parsing */
+ const char *dp; /* pointer in description string, moved along while
+ parsing */
+
+ int in_keyword; /* flag to remember if we are in a keyword group */
+ int in_multiple; /* flag to remember if we are in a multiple group */
+ int just_read_word; /* flag to remember if the last thing we read was a
+ real word and not some abstract token */
};
static void
@@ -324,6 +341,14 @@ format_parser_error(struct format_parser_state *state, const char *message)
exit(1);
}
+/**
+ * Reads out one section of a help string from state->dp.
+ * Leading whitespace is trimmed and the string is read until
+ * a newline is reached.
+ *
+ * @param[out] state format parser state
+ * @return the help string token read
+ */
static char *
format_parser_desc_str(struct format_parser_state *state)
{
@@ -359,6 +384,21 @@ format_parser_desc_str(struct format_parser_state *state)
return token;
}
+/**
+ * Transitions format parser state into keyword parsing mode.
+ * A cmd_token struct, `token`, representing this keyword token is initialized
+ * and appended to state->curvect. token->keyword is initialized as a vector of
+ * vector, a new vector is initialized and added to token->keyword, and
+ * state->curvect is set to point at this vector. When control returns to the
+ * caller newly parsed tokens will be added to this vector.
+ *
+ * In short:
+ * state->curvect[HEAD] = new cmd_token
+ * state->curvect[HEAD]->keyword[0] = new vector
+ * state->curvect = state->curvect[HEAD]->keyword[0]
+ *
+ * @param[out] state state struct to transition
+ */
static void
format_parser_begin_keyword(struct format_parser_state *state)
{
@@ -383,6 +423,23 @@ format_parser_begin_keyword(struct format_parser_state *state)
state->curvect = keyword_vect;
}
+/**
+ * Transitions format parser state into multiple parsing mode.
+ * A cmd_token struct, `token`, representing this multiple token is initialized
+ * and appended to state->curvect. token->multiple is initialized as a vector
+ * of cmd_token and state->curvect is set to point at token->multiple. If
+ * state->curvect != state->topvect (i.e. this multiple token is nested inside
+ * another composite token) then a pointer to state->curvect is saved in
+ * state->intvect.
+ *
+ * In short:
+ * state->curvect[HEAD] = new cmd_token
+ * state->curvect[HEAD]->multiple = new vector
+ * state->intvect = state->curvect IFF nested token
+ * state->curvect = state->curvect[HEAD]->multiple
+ *
+ * @param[out] state state struct to transition
+ */
static void
format_parser_begin_multiple(struct format_parser_state *state)
{
@@ -408,6 +465,14 @@ format_parser_begin_multiple(struct format_parser_state *state)
state->curvect = token->multiple;
}
+/**
+ * Transition format parser state out of keyword parsing mode.
+ * This function is called upon encountering '}'.
+ * state->curvect is reassigned to the top level vector (as
+ * keywords cannot be nested) and state flags are set appropriately.
+ *
+ * @param[out] state state struct to transition
+ */
static void
format_parser_end_keyword(struct format_parser_state *state)
{
@@ -423,6 +488,15 @@ format_parser_end_keyword(struct format_parser_state *state)
state->curvect = state->topvect;
}
+/**
+ * Transition format parser state out of multiple parsing mode.
+ * This function is called upon encountering ')'.
+ * state->curvect is reassigned to its parent vector (state->intvect
+ * if the multiple token being exited was nested inside another token,
+ * state->topvect otherwise) and state flags are set appropriately.
+ *
+ * @param[out] state state struct to transition
+ */
static void
format_parser_end_multiple(struct format_parser_state *state)
{
@@ -457,6 +531,21 @@ format_parser_end_multiple(struct format_parser_state *state)
state->curvect = state->topvect;
}
+/**
+ * Format parser handler for pipe '|' character.
+ * This character separates subtokens in multiple and keyword type tokens.
+ * If the current token is a multiple keyword, the position pointer is
+ * simply moved past the pipe and state flags are set appropriately.
+ * If the current token is a keyword token, the position pointer is moved
+ * past the pipe. Then the cmd_token struct for the keyword is fetched and
+ * a new vector of cmd_token is appended to its vector of vector. Finally
+ * state->curvect is set to point at this new vector.
+ *
+ * In short:
+ * state->curvect = state->topvect[HEAD]->keyword[HEAD] = new vector
+ *
+ * @param[out] state state struct to transition
+ */
static void
format_parser_handle_pipe(struct format_parser_state *state)
{
@@ -485,6 +574,13 @@ format_parser_handle_pipe(struct format_parser_state *state)
}
}
+/**
+ * Format parser handler for terminal tokens.
+ * Parses the token, appends it to state->curvect, and sets
+ * state flags appropriately.
+ *
+ * @param[out] state state struct for current format parser state
+ */
static void
format_parser_read_word(struct format_parser_state *state)
{