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