initial revision
[ucgine.git] / lib / cmd / include / ucg_cmd_parse.h
1 /*
2  * Copyright (c) 2009-2015, Olivier MATZ <zer0@droids-corp.org>
3  *
4  * Redistribution and use in source and binary forms, with or without
5  * modification, are permitted provided that the following conditions are met:
6  *
7  *     * Redistributions of source code must retain the above copyright
8  *       notice, this list of conditions and the following disclaimer.
9  *     * Redistributions in binary form must reproduce the above copyright
10  *       notice, this list of conditions and the following disclaimer in the
11  *       documentation and/or other materials provided with the distribution.
12  *     * Neither the name of the University of California, Berkeley nor the
13  *       names of its contributors may be used to endorse or promote products
14  *       derived from this software without specific prior written permission.
15  *
16  * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND ANY
17  * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
18  * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
19  * DISCLAIMED. IN NO EVENT SHALL THE REGENTS AND CONTRIBUTORS BE LIABLE FOR ANY
20  * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
21  * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
22  * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
23  * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
24  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
25  * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
26  */
27
28 /*-
29  * Copyright (c) <2010>, Intel Corporation
30  * All rights reserved.
31  *
32  * Redistribution and use in source and binary forms, with or without
33  * modification, are permitted provided that the following conditions
34  * are met:
35  *
36  * - Redistributions of source code must retain the above copyright
37  *   notice, this list of conditions and the following disclaimer.
38  *
39  * - Redistributions in binary form must reproduce the above copyright
40  *   notice, this list of conditions and the following disclaimer in
41  *   the documentation and/or other materials provided with the
42  *   distribution.
43  *
44  * - Neither the name of Intel Corporation nor the names of its
45  *   contributors may be used to endorse or promote products derived
46  *   from this software without specific prior written permission.
47  *
48  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
49  * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
50  * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
51  * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
52  * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
53  * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
54  * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
55  * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
56  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
57  * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
58  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
59  * OF THE POSSIBILITY OF SUCH DAMAGE.
60  */
61
62 #ifndef UCG_CMD_PARSE_H_
63 #define UCG_CMD_PARSE_H_
64
65 #include <sys/types.h>
66
67 #ifndef offsetof
68 #define offsetof(type, field)  ((size_t) &( ((type *)0)->field) )
69 #endif
70
71 // XXX config
72 #define UCG_CMD_MAX_TOKEN_SIZE 32 /* including '\0' */
73 #define UCG_CMD_MAX_DSTBUF_SIZE 128
74
75 /**
76  * A token header.
77  *
78  * Stores a pointer to the ops struct, and the offset: the place to
79  * write the parsed result in the destination structure.
80  */
81 struct ucg_cmd_tk_hdr {
82         struct ucg_cmd_tk_ops *ops;
83         unsigned int offset;
84 };
85 typedef struct ucg_cmd_tk_hdr ucg_cmd_tk_hdr_t;
86
87 /**
88  * Operations on token.
89  */
90 struct ucg_cmd_tk_ops {
91         /**
92          * parse() converts a buffer containing a token into its parsed
93          * value. Ex: an integer string is converted into its integer
94          * value. The result is stored in "result" whose size is
95          * "res_size". It returns 0 on success and a negative value on
96          * error.
97          */
98         int (*parse)(ucg_cmd_tk_hdr_t *tk, const char *line,
99                 void *result, unsigned int res_size);
100
101         /**
102          * complete_start() prepares a completion operation. The
103          * "opaque" arg is an opaque pointer that will be given to
104          * complete_iterate() function. It can be used to store private
105          * data for this completion. For each complete_start() call, the
106          * user must call complete_end() at the end of iterations (if
107          * defined) in case some data have to be freed.
108          *
109          * Return a negative value if completion is not possible, or 0
110          * on success.
111          */
112         int (*complete_start)(ucg_cmd_tk_hdr_t *tk, const char *line,
113                 void **opaque);
114
115         /**
116          * complete_iterate() copy in "dst" buffer the next possible
117          * completion for this token. Return 0 on success (final
118          * completion = completion until the end of the token), 1 if
119          * it's an intermediate completion (token not fully completed),
120          * or a negative value on error (or when there is no more
121          * completion). Refer to ucg_cmd_complete_string_iterate() for
122          * an example.
123          */
124         int (*complete_iterate)(ucg_cmd_tk_hdr_t *tk, void **opaque,
125                 char *dst, unsigned int dst_size);
126
127         /**
128          * complete_end() is called when the iteration on this token is
129          * finished, this function should free all things allocated
130          * during complete_start().
131          */
132         void (*complete_end)(ucg_cmd_tk_hdr_t *tk, void **opaque);
133
134         /**
135          * help() fills the dstbuf with the help for the token. It returns
136          * -1 on error and 0 on success.
137          */
138         int (*help)(ucg_cmd_tk_hdr_t *tk, char *dst, unsigned int dst_size);
139 };
140
141 struct ucg_cmd;
142
143 /**
144  * Store a command, defined by a list of tokens and a callback function.
145  */
146 struct ucg_cmd_inst {
147         /** callback function when the commend is parsed */
148         void (*f)(void *parsed_result, struct ucg_cmd *cl, void *opaque);
149         void *data;     /**< opaque pointer given as is to the callback */
150         char *help_str; /**< help for this command */
151         ucg_cmd_tk_hdr_t *tokens[]; /**< list of tokens */
152 };
153 typedef struct ucg_cmd_inst ucg_cmd_inst_t;
154
155 /**
156  * A context is a list of commands.
157  */
158 struct ucg_cmd_ctx {
159         const char *name;                /**< The name of the context */
160         const ucg_cmd_inst_t *insts[];   /**< List of commands */
161 };
162 typedef struct ucg_cmd_ctx ucg_cmd_ctx_t;
163
164 /* return status for parsing */
165 #define UCG_CMD_PARSE_SUCCESS        0
166 #define UCG_CMD_PARSE_EMPTY         -1
167 #define UCG_CMD_PARSE_NOMATCH       -2
168 #define UCG_CMD_PARSE_AMBIGUOUS     -3
169 #define UCG_CMD_PARSE_UNTERMINATED_QUOTE -4
170
171 /**
172  * Try to parse a buffer according to the specified context. The
173  * argument linebuf must end with "\n\0".
174  *
175  * The function returns:
176  * - UCG_CMD_PARSE_SUCCESS (0) on success
177  * - UCG_CMD_PARSE_EMPTY if there is nothing to parse
178  * - UCG_CMD_PARSE_NOMATCH if line does not match any command
179  * - UCG_CMD_PARSE_AMBIGUOUS if several commands match
180  * - UCG_CMD_PARSE_UNTERMINATED_QUOTE if a quote is used incorrectly
181  */
182 int ucg_cmd_parse(struct ucg_cmd *cl, const char *linebuf, void *opaque);
183
184 /* return status for completion */
185 #define UCG_CMD_COMPLETE_APPEND    0
186 #define UCG_CMD_COMPLETE_NONE     -1
187 #define UCG_CMD_COMPLETE_MANY     -2
188
189 /**
190  * ucg_cmd_complete() tries to complete the buffer given as a parameter.
191  *
192  * It returns:
193  *   - UCG_CMD_COMPLETE_APPEND (0) on success, when a completion is
194  *     done (one possible choice). In this case, the chars are
195  *     appended in dst buffer.
196  *   - UCG_CMD_COMPLETE_NONE: error, no possible completion
197  *   - UCG_CMD_COMPLETE_MANY: error, many possble completions, need to call
198  *     ucg_cmd_help() function to see all the possibilities.
199  */
200 int ucg_cmd_complete(struct ucg_cmd *cl, const char *buf, char *dst,
201         unsigned int size);
202
203 /**
204  * Display a contextual help.
205  *
206  * @param cl
207  *   The command line pointer
208  * @param line
209  *   The current line buffer.
210  */
211 void ucg_cmd_help(struct ucg_cmd *cl, const char *line);
212
213 /**
214  * Check if the character ends a token
215  *
216  * @param c
217  *   The character.
218  * @return
219  *   True if (c == '\0' || iscomment(c) || isblank(c) ||
220  *   isendofline(c))
221  */
222 int ucg_cmd_isendoftoken(char c);
223
224 /**
225  * Quote a string and escape original quotes
226  *
227  * @param dst
228  *   The destination buffer.
229  * @param dstlen
230  *   The length of the destination buffer.
231  * @param src
232  *   The source buffer.
233  * @return
234  *   Return 0 on success, a negative value on error.
235  */
236 int ucg_cmd_quote_token(char *dst, unsigned dstlen, const char *src);
237
238 /**
239  * Get one token
240  *
241  * The function removes quotes (if any) and stop copying when the end of
242  * token is reached. The destination buffer is '\0'-terminated.
243  *
244  * @param dst
245  *   The destination buffer.
246  * @param dstlen
247  *   The length of the destination buffer.
248  * @param src
249  *   The source buffer.
250  * @return
251  *   Return the number of "consumed" bytes from the source buffer, or
252  *   a negative value on error
253  */
254 int ucg_cmd_get_token(char *dst, unsigned dstlen, const char *src);
255
256 #endif /* UCG_CMD_PARSE_H_ */