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