enum index prev; /**< Index of the last token seen. */
int next_num; /**< Number of entries in next[]. */
int args_num; /**< Number of entries in args[]. */
- uint32_t reparse:1; /**< Start over from the beginning. */
uint32_t eol:1; /**< EOL has been detected. */
uint32_t last:1; /**< No more arguments. */
uint16_t port; /**< Current port ID (for completions). */
ctx->prev = ZERO;
ctx->next_num = 0;
ctx->args_num = 0;
- ctx->reparse = 0;
ctx->eol = 0;
ctx->last = 0;
ctx->port = 0;
int i;
(void)hdr;
- /* Restart as requested. */
- if (ctx->reparse)
- cmd_flow_context_init(ctx);
token = &token_list[ctx->curr];
/* Check argument length. */
ctx->eol = 0;
int i;
(void)hdr;
- /* Tell cmd_flow_parse() that context must be reinitialized. */
- ctx->reparse = 1;
/* Count number of tokens in current list. */
if (ctx->next_num)
list = ctx->next[ctx->next_num - 1];
int i;
(void)hdr;
- /* Tell cmd_flow_parse() that context must be reinitialized. */
- ctx->reparse = 1;
/* Count number of tokens in current list. */
if (ctx->next_num)
list = ctx->next[ctx->next_num - 1];
const struct token *token = &token_list[ctx->prev];
(void)hdr;
- /* Tell cmd_flow_parse() that context must be reinitialized. */
- ctx->reparse = 1;
if (!size)
return -1;
/* Set token type and update global help with details. */
/** Populate the next dynamic token. */
static void
cmd_flow_tok(cmdline_parse_token_hdr_t **hdr,
- cmdline_parse_token_hdr_t *(*hdrs)[])
+ cmdline_parse_token_hdr_t **hdr_inst)
{
struct context *ctx = &cmd_flow_context;
/* Always reinitialize context before requesting the first token. */
- if (!(hdr - *hdrs))
+ if (!(hdr_inst - cmd_flow.tokens))
cmd_flow_context_init(ctx);
/* Return NULL when no more tokens are expected. */
if (!ctx->next_num && ctx->curr) {
/** Retrieve either static or dynamic token at a given index. */
static cmdline_parse_token_hdr_t *
-get_token(cmdline_parse_inst_t *inst,
- unsigned int index,
- cmdline_parse_token_hdr_t
- *(*dyn_tokens)[CMDLINE_PARSE_DYNAMIC_TOKENS])
+get_token(cmdline_parse_inst_t *inst, unsigned int index)
{
+ cmdline_parse_token_hdr_t *token_p;
+
/* check presence of static tokens first */
if (inst->tokens[0] || !inst->f)
return inst->tokens[index];
- /* for dynamic tokens, make sure index does not overflow */
- if (index >= CMDLINE_PARSE_DYNAMIC_TOKENS - 1)
- return NULL;
- /* in case token is already generated, return it */
- if ((*dyn_tokens)[index])
- return (*dyn_tokens)[index];
- /* generate token */
- inst->f(&(*dyn_tokens)[index], NULL, dyn_tokens);
- /* return immediately if there are no more tokens to expect */
- if (!(*dyn_tokens)[index])
- return NULL;
- /* terminate list with a NULL entry */
- (*dyn_tokens)[index + 1] = NULL;
- return (*dyn_tokens)[index];
+ /* generate dynamic token */
+ token_p = NULL;
+ inst->f(&token_p, NULL, &inst->tokens[index]);
+ return token_p;
}
/**
*/
static int
match_inst(cmdline_parse_inst_t *inst, const char *buf,
- unsigned int nb_match_token, void *resbuf, unsigned resbuf_size,
- cmdline_parse_token_hdr_t
- *(*dyn_tokens)[CMDLINE_PARSE_DYNAMIC_TOKENS])
+ unsigned int nb_match_token, void *resbuf, unsigned resbuf_size)
{
- unsigned int token_num=0;
cmdline_parse_token_hdr_t * token_p;
unsigned int i=0;
int n = 0;
struct cmdline_token_hdr token_hdr;
- token_p = get_token(inst, token_num, dyn_tokens);
- if (token_p)
+ /* check if we match all tokens of inst */
+ while (!nb_match_token || i < nb_match_token) {
+ token_p = get_token(inst, i);
+ if (!token_p)
+ break;
memcpy(&token_hdr, token_p, sizeof(token_hdr));
- /* check if we match all tokens of inst */
- while (token_p && (!nb_match_token || i<nb_match_token)) {
debug_printf("TK\n");
/* skip spaces */
while (isblank2(*buf)) {
debug_printf("TK parsed (len=%d)\n", n);
i++;
buf += n;
-
- token_num ++;
- token_p = get_token(inst, token_num, dyn_tokens);
- if (token_p)
- memcpy(&token_hdr, token_p, sizeof(token_hdr));
}
/* does not match */
char buf[CMDLINE_PARSE_RESULT_BUFSIZE];
long double align; /* strong alignment constraint for buf */
} result, tmp_result;
- cmdline_parse_token_hdr_t *dyn_tokens[CMDLINE_PARSE_DYNAMIC_TOKENS];
void (*f)(void *, struct cmdline *, void *) = NULL;
void *data = NULL;
int comment = 0;
/* parse it !! */
inst = ctx[inst_num];
- dyn_tokens[0] = NULL;
while (inst) {
debug_printf("INST %d\n", inst_num);
/* fully parsed */
tok = match_inst(inst, buf, 0, tmp_result.buf,
- sizeof(tmp_result.buf), &dyn_tokens);
+ sizeof(tmp_result.buf));
if (tok > 0) /* we matched at least one token */
err = CMDLINE_PARSE_BAD_ARGS;
inst_num ++;
inst = ctx[inst_num];
- dyn_tokens[0] = NULL;
}
/* call func */
cmdline_parse_token_hdr_t *token_p;
struct cmdline_token_hdr token_hdr;
char tmpbuf[CMDLINE_BUFFER_SIZE], comp_buf[CMDLINE_BUFFER_SIZE];
- cmdline_parse_token_hdr_t *dyn_tokens[CMDLINE_PARSE_DYNAMIC_TOKENS];
unsigned int partial_tok_len;
int comp_len = -1;
int tmp_len = -1;
nb_non_completable = 0;
inst = ctx[inst_num];
- dyn_tokens[0] = NULL;
while (inst) {
/* parse the first tokens of the inst */
if (nb_token &&
- match_inst(inst, buf, nb_token, NULL, 0,
- &dyn_tokens))
+ match_inst(inst, buf, nb_token, NULL, 0))
goto next;
debug_printf("instruction match\n");
- token_p = get_token(inst, nb_token, &dyn_tokens);
+ token_p = get_token(inst, nb_token);
if (token_p)
memcpy(&token_hdr, token_p, sizeof(token_hdr));
debug_printf("next\n");
inst_num ++;
inst = ctx[inst_num];
- dyn_tokens[0] = NULL;
}
debug_printf("total choices %d for this completion\n",
inst_num = 0;
inst = ctx[inst_num];
- dyn_tokens[0] = NULL;
while (inst) {
/* we need to redo it */
inst = ctx[inst_num];
if (nb_token &&
- match_inst(inst, buf, nb_token, NULL, 0, &dyn_tokens))
+ match_inst(inst, buf, nb_token, NULL, 0))
goto next2;
- token_p = get_token(inst, nb_token, &dyn_tokens);
+ token_p = get_token(inst, nb_token);
if (token_p)
memcpy(&token_hdr, token_p, sizeof(token_hdr));
next2:
inst_num ++;
inst = ctx[inst_num];
- dyn_tokens[0] = NULL;
}
return 0;
}
/* maximum buffer size for parsed result */
#define CMDLINE_PARSE_RESULT_BUFSIZE 8192
-/* maximum number of dynamic tokens */
-#define CMDLINE_PARSE_DYNAMIC_TOKENS 128
-
/**
* Stores a pointer to the ops struct, and the offset: the place to
* write the parsed result in the destination structure.
* When no tokens are defined (tokens[0] == NULL), they are retrieved
* dynamically by calling f() as follows:
*
- * f((struct cmdline_token_hdr **)&token_hdr,
- * NULL,
- * (struct cmdline_token_hdr *[])tokens));
+ * @code
+ *
+ * f((struct cmdline_token_hdr **)&token_p,
+ * NULL,
+ * (struct cmdline_token_hdr **)&inst->tokens[num]);
+ *
+ * @endcode
*
* The address of the resulting token is expected at the location pointed by
* the first argument. Can be set to NULL to end the list.
*
* The cmdline argument (struct cmdline *) is always NULL.
*
- * The last argument points to the NULL-terminated list of dynamic tokens
- * defined so far. Since token_hdr points to an index of that list, the
- * current index can be derived as follows:
+ * The last argument points to the inst->tokens[] entry to retrieve, which
+ * is not necessarily inside allocated memory and should neither be read nor
+ * written. Its sole purpose is to deduce the token entry index of interest
+ * as described in the example below.
+ *
+ * Note about constraints:
+ *
+ * - Only the address of these tokens is dynamic, their storage should be
+ * static like normal tokens.
+ * - Dynamic token lists that need to maintain an internal context (e.g. in
+ * order to determine the next token) must store it statically also. This
+ * context must be reinitialized when the first token is requested, that
+ * is, when &inst->tokens[0] is provided as the third argument.
+ * - Dynamic token lists must be NULL-terminated to generate usable
+ * commands.
+ *
+ * @code
+ *
+ * // Assuming first and third arguments are respectively named "token_p"
+ * // and "token":
+ *
+ * int index = token - inst->tokens;
+ *
+ * if (!index) {
+ * [...] // Clean up internal context if any.
+ * }
+ * [...] // Then set up dyn_token according to index.
+ *
+ * if (no_more_tokens)
+ * *token_p = NULL;
+ * else
+ * *token_p = &dyn_token;
*
- * int index = token_hdr - &(*tokens)[0];
+ * @endcode
*/
struct cmdline_inst {
/* f(parsed_struct, data) */