1*d30ea906Sjfb8856606 /* SPDX-License-Identifier: BSD-3-Clause
2*d30ea906Sjfb8856606  * Copyright(c) 2010-2014 Intel Corporation.
3a9643ea8Slogwang  * Copyright (c) 2009, Olivier MATZ <[email protected]>
4a9643ea8Slogwang  * All rights reserved.
5a9643ea8Slogwang  */
6a9643ea8Slogwang 
7a9643ea8Slogwang #ifndef _CMDLINE_PARSE_H_
8a9643ea8Slogwang #define _CMDLINE_PARSE_H_
9a9643ea8Slogwang 
10a9643ea8Slogwang #ifdef __cplusplus
11a9643ea8Slogwang extern "C" {
12a9643ea8Slogwang #endif
13a9643ea8Slogwang 
14a9643ea8Slogwang #ifndef offsetof
15a9643ea8Slogwang #define offsetof(type, field)  ((size_t) &( ((type *)0)->field) )
16a9643ea8Slogwang #endif
17a9643ea8Slogwang 
18a9643ea8Slogwang /* return status for parsing */
19a9643ea8Slogwang #define CMDLINE_PARSE_SUCCESS        0
20a9643ea8Slogwang #define CMDLINE_PARSE_AMBIGUOUS     -1
21a9643ea8Slogwang #define CMDLINE_PARSE_NOMATCH       -2
22a9643ea8Slogwang #define CMDLINE_PARSE_BAD_ARGS      -3
23a9643ea8Slogwang 
24a9643ea8Slogwang /* return status for completion */
25a9643ea8Slogwang #define CMDLINE_PARSE_COMPLETE_FINISHED 0
26a9643ea8Slogwang #define CMDLINE_PARSE_COMPLETE_AGAIN    1
27a9643ea8Slogwang #define CMDLINE_PARSE_COMPLETED_BUFFER  2
28a9643ea8Slogwang 
29a9643ea8Slogwang /* maximum buffer size for parsed result */
30a9643ea8Slogwang #define CMDLINE_PARSE_RESULT_BUFSIZE 8192
31a9643ea8Slogwang 
32a9643ea8Slogwang /**
33a9643ea8Slogwang  * Stores a pointer to the ops struct, and the offset: the place to
34a9643ea8Slogwang  * write the parsed result in the destination structure.
35a9643ea8Slogwang  */
36a9643ea8Slogwang struct cmdline_token_hdr {
37a9643ea8Slogwang 	struct cmdline_token_ops *ops;
38a9643ea8Slogwang 	unsigned int offset;
39a9643ea8Slogwang };
40a9643ea8Slogwang typedef struct cmdline_token_hdr cmdline_parse_token_hdr_t;
41a9643ea8Slogwang 
42a9643ea8Slogwang /**
43a9643ea8Slogwang  * A token is defined by this structure.
44a9643ea8Slogwang  *
45a9643ea8Slogwang  * parse() takes the token as first argument, then the source buffer
46a9643ea8Slogwang  * starting at the token we want to parse. The 3rd arg is a pointer
47a9643ea8Slogwang  * where we store the parsed data (as binary). It returns the number of
48a9643ea8Slogwang  * parsed chars on success and a negative value on error.
49a9643ea8Slogwang  *
50a9643ea8Slogwang  * complete_get_nb() returns the number of possible values for this
51a9643ea8Slogwang  * token if completion is possible. If it is NULL or if it returns 0,
52a9643ea8Slogwang  * no completion is possible.
53a9643ea8Slogwang  *
54a9643ea8Slogwang  * complete_get_elt() copy in dstbuf (the size is specified in the
55a9643ea8Slogwang  * parameter) the i-th possible completion for this token.  returns 0
56a9643ea8Slogwang  * on success or and a negative value on error.
57a9643ea8Slogwang  *
58a9643ea8Slogwang  * get_help() fills the dstbuf with the help for the token. It returns
59a9643ea8Slogwang  * -1 on error and 0 on success.
60a9643ea8Slogwang  */
61a9643ea8Slogwang struct cmdline_token_ops {
62a9643ea8Slogwang 	/** parse(token ptr, buf, res pts, buf len) */
63a9643ea8Slogwang 	int (*parse)(cmdline_parse_token_hdr_t *, const char *, void *,
64a9643ea8Slogwang 		unsigned int);
65a9643ea8Slogwang 	/** return the num of possible choices for this token */
66a9643ea8Slogwang 	int (*complete_get_nb)(cmdline_parse_token_hdr_t *);
67a9643ea8Slogwang 	/** return the elt x for this token (token, idx, dstbuf, size) */
68a9643ea8Slogwang 	int (*complete_get_elt)(cmdline_parse_token_hdr_t *, int, char *,
69a9643ea8Slogwang 		unsigned int);
70a9643ea8Slogwang 	/** get help for this token (token, dstbuf, size) */
71a9643ea8Slogwang 	int (*get_help)(cmdline_parse_token_hdr_t *, char *, unsigned int);
72a9643ea8Slogwang };
73a9643ea8Slogwang 
74a9643ea8Slogwang struct cmdline;
75a9643ea8Slogwang /**
76a9643ea8Slogwang  * Store a instruction, which is a pointer to a callback function and
77a9643ea8Slogwang  * its parameter that is called when the instruction is parsed, a help
78a9643ea8Slogwang  * string, and a list of token composing this instruction.
792bfe3f2eSlogwang  *
802bfe3f2eSlogwang  * When no tokens are defined (tokens[0] == NULL), they are retrieved
812bfe3f2eSlogwang  * dynamically by calling f() as follows:
822bfe3f2eSlogwang  *
832bfe3f2eSlogwang  * @code
842bfe3f2eSlogwang  *
852bfe3f2eSlogwang  * f((struct cmdline_token_hdr **)&token_p,
862bfe3f2eSlogwang  *   NULL,
872bfe3f2eSlogwang  *   (struct cmdline_token_hdr **)&inst->tokens[num]);
882bfe3f2eSlogwang  *
892bfe3f2eSlogwang  * @endcode
902bfe3f2eSlogwang  *
912bfe3f2eSlogwang  * The address of the resulting token is expected at the location pointed by
922bfe3f2eSlogwang  * the first argument. Can be set to NULL to end the list.
932bfe3f2eSlogwang  *
942bfe3f2eSlogwang  * The cmdline argument (struct cmdline *) is always NULL.
952bfe3f2eSlogwang  *
962bfe3f2eSlogwang  * The last argument points to the inst->tokens[] entry to retrieve, which
972bfe3f2eSlogwang  * is not necessarily inside allocated memory and should neither be read nor
982bfe3f2eSlogwang  * written. Its sole purpose is to deduce the token entry index of interest
992bfe3f2eSlogwang  * as described in the example below.
1002bfe3f2eSlogwang  *
1012bfe3f2eSlogwang  * Note about constraints:
1022bfe3f2eSlogwang  *
1032bfe3f2eSlogwang  * - Only the address of these tokens is dynamic, their storage should be
1042bfe3f2eSlogwang  *   static like normal tokens.
1052bfe3f2eSlogwang  * - Dynamic token lists that need to maintain an internal context (e.g. in
1062bfe3f2eSlogwang  *   order to determine the next token) must store it statically also. This
1072bfe3f2eSlogwang  *   context must be reinitialized when the first token is requested, that
1082bfe3f2eSlogwang  *   is, when &inst->tokens[0] is provided as the third argument.
1092bfe3f2eSlogwang  * - Dynamic token lists must be NULL-terminated to generate usable
1102bfe3f2eSlogwang  *   commands.
1112bfe3f2eSlogwang  *
1122bfe3f2eSlogwang  * @code
1132bfe3f2eSlogwang  *
1142bfe3f2eSlogwang  * // Assuming first and third arguments are respectively named "token_p"
1152bfe3f2eSlogwang  * // and "token":
1162bfe3f2eSlogwang  *
1172bfe3f2eSlogwang  * int index = token - inst->tokens;
1182bfe3f2eSlogwang  *
1192bfe3f2eSlogwang  * if (!index) {
1202bfe3f2eSlogwang  *     [...] // Clean up internal context if any.
1212bfe3f2eSlogwang  * }
1222bfe3f2eSlogwang  * [...] // Then set up dyn_token according to index.
1232bfe3f2eSlogwang  *
1242bfe3f2eSlogwang  * if (no_more_tokens)
1252bfe3f2eSlogwang  *     *token_p = NULL;
1262bfe3f2eSlogwang  * else
1272bfe3f2eSlogwang  *     *token_p = &dyn_token;
1282bfe3f2eSlogwang  *
1292bfe3f2eSlogwang  * @endcode
130a9643ea8Slogwang  */
131a9643ea8Slogwang struct cmdline_inst {
132a9643ea8Slogwang 	/* f(parsed_struct, data) */
133a9643ea8Slogwang 	void (*f)(void *, struct cmdline *, void *);
134a9643ea8Slogwang 	void *data;
135a9643ea8Slogwang 	const char *help_str;
136a9643ea8Slogwang 	cmdline_parse_token_hdr_t *tokens[];
137a9643ea8Slogwang };
138a9643ea8Slogwang typedef struct cmdline_inst cmdline_parse_inst_t;
139a9643ea8Slogwang 
140a9643ea8Slogwang /**
141a9643ea8Slogwang  * A context is identified by its name, and contains a list of
142a9643ea8Slogwang  * instruction
143a9643ea8Slogwang  *
144a9643ea8Slogwang  */
145a9643ea8Slogwang typedef cmdline_parse_inst_t *cmdline_parse_ctx_t;
146a9643ea8Slogwang 
147a9643ea8Slogwang /**
148a9643ea8Slogwang  * Try to parse a buffer according to the specified context. The
149a9643ea8Slogwang  * argument buf must ends with "\n\0". The function returns
150a9643ea8Slogwang  * CMDLINE_PARSE_AMBIGUOUS, CMDLINE_PARSE_NOMATCH or
151a9643ea8Slogwang  * CMDLINE_PARSE_BAD_ARGS on error. Else it calls the associated
152a9643ea8Slogwang  * function (defined in the context) and returns 0
153a9643ea8Slogwang  * (CMDLINE_PARSE_SUCCESS).
154a9643ea8Slogwang  */
155a9643ea8Slogwang int cmdline_parse(struct cmdline *cl, const char *buf);
156a9643ea8Slogwang 
157a9643ea8Slogwang /**
158a9643ea8Slogwang  * complete() must be called with *state==0 (try to complete) or
159a9643ea8Slogwang  * with *state==-1 (just display choices), then called without
160a9643ea8Slogwang  * modifying *state until it returns CMDLINE_PARSE_COMPLETED_BUFFER or
161a9643ea8Slogwang  * CMDLINE_PARSE_COMPLETED_BUFFER.
162a9643ea8Slogwang  *
163a9643ea8Slogwang  * It returns < 0 on error.
164a9643ea8Slogwang  *
165a9643ea8Slogwang  * Else it returns:
166a9643ea8Slogwang  *   - CMDLINE_PARSE_COMPLETED_BUFFER on completion (one possible
167a9643ea8Slogwang  *     choice). In this case, the chars are appended in dst buffer.
168a9643ea8Slogwang  *   - CMDLINE_PARSE_COMPLETE_AGAIN if there is several possible
169a9643ea8Slogwang  *     choices. In this case, you must call the function again,
170a9643ea8Slogwang  *     keeping the value of state intact.
171a9643ea8Slogwang  *   - CMDLINE_PARSE_COMPLETED_BUFFER when the iteration is
172a9643ea8Slogwang  *     finished. The dst is not valid for this last call.
173a9643ea8Slogwang  *
174a9643ea8Slogwang  * The returned dst buf ends with \0.
175a9643ea8Slogwang  */
176a9643ea8Slogwang int cmdline_complete(struct cmdline *cl, const char *buf, int *state,
177a9643ea8Slogwang 		     char *dst, unsigned int size);
178a9643ea8Slogwang 
179a9643ea8Slogwang 
180a9643ea8Slogwang /* return true if(!c || iscomment(c) || isblank(c) ||
181a9643ea8Slogwang  * isendofline(c)) */
182a9643ea8Slogwang int cmdline_isendoftoken(char c);
183a9643ea8Slogwang 
184a9643ea8Slogwang /* return true if(!c || iscomment(c) || isendofline(c)) */
185a9643ea8Slogwang int cmdline_isendofcommand(char c);
186a9643ea8Slogwang 
187a9643ea8Slogwang #ifdef __cplusplus
188a9643ea8Slogwang }
189a9643ea8Slogwang #endif
190a9643ea8Slogwang 
191a9643ea8Slogwang #endif /* _CMDLINE_PARSE_H_ */
192