initial revision
[ucgine.git] / lib / cmd / include / ucg_cmd_rdline.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 CMD_RDLINE_H_
63 #define CMD_RDLINE_H_
64
65 /**
66  * This file is a small equivalent to the GNU readline library, it was
67  * originally designed for very small systems (an 8-bits Atmel AVR
68  * microcontroller), but the library can now run on many emmbedded
69  * systems with or without OS.
70  *
71  * Obviously, it does not support as many things as the GNU readline,
72  * but at least it supports some interresting features like a kill
73  * buffer and a command history.
74  *
75  * It also have a feature that does not have the GNU readline (as far
76  * as I know): it is possible to have several instances of readline
77  * running at the same time, even on a monothread program, since it
78  * works with callbacks.
79  */
80
81 #include <sys/types.h>
82 #include <stdio.h>
83
84 #include <ucg_cirbuf.h>
85 #include <ucg_cmd_vt100.h>
86
87 /* configuration */
88 #define UCG_RDLINE_BUF_SIZE 32
89 #define UCG_RDLINE_PROMPT_SIZE  16
90 #define UCG_RDLINE_VT100_BUF_SIZE  8
91 #define UCG_RDLINE_HISTORY_BUF_SIZE 64
92 #define UCG_RDLINE_MAX_LINES 23  /* pager */
93
94 enum ucg_rdline_status {
95         UCG_RDLINE_STOPPED,
96         UCG_RDLINE_RUNNING,
97         UCG_RDLINE_EXITED
98 };
99
100 struct ucg_rdline;
101
102 /**
103  * type of callback given to ucg_rdline_help() to display the content of
104  * the help. The first argument is the rdline pointer. The other args
105  * are buffer and size.
106  */
107 typedef int (ucg_rdline_printf_t)(struct ucg_rdline *rdl,
108         const char *fmt, ...);
109
110 /**
111  * type of callback invoked when a command is parsed. "rdl" is a pointer
112  * to the ucg_rdline structure, "line" is a pointer to the current line
113  * string ('\0' terminated).
114  */
115 typedef void (ucg_rdline_validate_t)(struct ucg_rdline *rdl,
116         const char *line);
117
118 /**
119  * type of callback invoked when a completion is requested. "rdl" is a
120  * pointer to the ucg_rdline structure, "line" is a pointer to the
121  * current line string ('\0' terminated). The characters to append
122  * are written to dstbuf.
123  * Return 0 on success: dstbuf contains the characters to append to
124  *   the current line ('\0' terminated)
125  * Else return a negative value if no completion is performed.
126  */
127 typedef int (ucg_rdline_complete_t)(struct ucg_rdline *rdl, const char *line,
128         char *dstbuf, unsigned int dstsize);
129
130 /**
131  * callback invoked when a the help is requested. "rdl" is a pointer to
132  * the ucg_rdline structure, "line" is a pointer to the current line string
133  * ('\0' terminated).
134  */
135 typedef void (ucg_rdline_help_t)(struct ucg_rdline *rdl, const char *line);
136
137 typedef void (ucg_rdline_pager_cb_t)(struct ucg_rdline *, void *);
138
139 struct ucg_rdline {
140         enum ucg_rdline_status status;
141         FILE *f_in;
142         FILE *f_out;
143
144         /* rdline bufs */
145         struct ucg_cirbuf left;
146         struct ucg_cirbuf right;
147         char left_buf[UCG_RDLINE_BUF_SIZE+1]; /* reserve 1 char for the \0 */
148         char right_buf[UCG_RDLINE_BUF_SIZE];
149
150         char prompt[UCG_RDLINE_PROMPT_SIZE];
151
152 #ifndef UCG_CMD_NO_RDLINE_KILL_BUF
153         char kill_buf[UCG_RDLINE_BUF_SIZE];
154         unsigned int kill_size;
155 #endif
156
157 #ifndef UCG_CMD_NO_RDLINE_HISTORY
158         /* history */
159         struct ucg_cirbuf history;
160         char history_buf[UCG_RDLINE_HISTORY_BUF_SIZE];
161         int history_cur_line;
162 #endif
163
164         /* callbacks and func pointers */
165         ucg_rdline_validate_t *validate;
166         ucg_rdline_complete_t *complete;
167         ucg_rdline_help_t *help;
168
169         /* vt100 parser */
170         struct ucg_cmd_vt100 vt100;
171
172         /* opaque pointer */
173         void *opaque;
174
175 #ifndef UCG_CMD_NO_PAGER
176         char *pager_buf; /* buffer used to store paged data */
177         int pager_len; /* total len of buffer */
178         int pager_off; /* offset of next data */
179         int pager_lines; /* number of lines displayed */
180         ucg_rdline_pager_cb_t *pager_cb; /* callback once paging is finished */
181         void *pager_arg; /* argument of callback */
182         int pager_ret; /* saved return value */
183 #endif
184 };
185
186 /**
187  * Init fields for a struct ucg_rdline.
188  *
189  * @param rdl A pointer to an uninitialized struct ucg_rdline
190  * @param fd_in
191  *   Input file descriptor
192  * @param fd_out
193  *   Output file descriptor
194  * @param validate
195  *   A pointer to the function to execute when the user validates the
196  *   buffer.
197  * @param complete
198  *   A pointer to the function to execute when the user completes the
199  *   buffer.
200  * @param help
201  *   A pointer to the function to execute when the user ask for
202  *   contextual help.
203  */
204 void ucg_rdline_init(struct ucg_rdline *rdl,
205                  FILE *f_in, FILE *f_out,
206                  ucg_rdline_validate_t *validate,
207                  ucg_rdline_complete_t *complete,
208                  ucg_rdline_help_t *help);
209
210
211 /**
212  * Init the current buffer, and display a prompt.
213  *
214  * Also set the rdline status to "running", overriding previous
215  * ucg_rdline_stop() or ucg_rdline_quit().
216  *
217  * @param rdl
218  *   A pointer to an initialized struct ucg_rdline
219  * @param prompt
220  *   A string containing the prompt, or NULL to keep existing one
221  */
222 void ucg_rdline_newline(struct ucg_rdline *rdl, const char *prompt);
223
224 /**
225  * Ignore all subsequent received chars.
226  *
227  * @param rdl
228  *   A pointer to a struct ucg_rdline
229  */
230 void ucg_rdline_stop(struct ucg_rdline *rdl);
231
232 /**
233  * Exit from running rdline loop
234  *
235  * Same than ucg_rdline_stop() except that next calls to ucg_rdline_char_in()
236  * will return UCG_RDLINE_RES_EXITED. Hence, any running rdline() function is
237  * interrupted.
238  *
239  * @param rdl
240  *   A pointer to a struct ucg_rdline
241  */
242 void ucg_rdline_quit(struct ucg_rdline *rdl);
243
244 /**
245  * Restart after a call to ucg_rdline_stop() or ucg_rdline_quit()
246  *
247  * @param rdl
248  *   A pointer to a struct ucg_rdline
249  */
250 void ucg_rdline_restart(struct ucg_rdline *rdl);
251
252 /**
253  * Redisplay the current buffer
254  *
255  * @param rdl
256  *   A pointer to a struct ucg_rdline
257  */
258 void ucg_rdline_redisplay(struct ucg_rdline *rdl);
259
260 /* return status for ucg_rdline_char_in() */
261 #define UCG_RDLINE_RES_SUCCESS          0
262 #define UCG_RDLINE_RES_VALIDATED        1
263 #define UCG_RDLINE_RES_COMPLETED        2
264 #define UCG_RDLINE_RES_NOT_RUNNING     -1
265 #define UCG_RDLINE_RES_EOF             -2
266 #define UCG_RDLINE_RES_EXITED          -3
267 #define UCG_RDLINE_RES_CANNOT_COMPLETE -3
268
269 /**
270  * Append a char to the readline buffer.
271  *
272  * @param rdl
273  *   A pointer to a struct ucg_rdline
274  * @param c
275  *   The character to append
276  * @return
277  *   - UCG_RDLINE_RES_VALIDATED when the line has been validated.
278  *   - UCG_RDLINE_RES_NOT_RUNNING if it is not running.
279  *   - UCG_RDLINE_RES_EOF if EOF (ctrl-d on an empty line).
280  *   - UCG_RDLINE_RES_EXITED if user called ucg_rdline_quit()
281  *   - Else return UCG_RDLINE_RES_SUCCESS.
282  */
283 int ucg_rdline_char_in(struct ucg_rdline *rdl, char c);
284
285 #define UCG_RDLINE_F_IGNORE_EOF 0x0001   /**< ignore eof when polling */
286
287 /**
288  * Read (and edit) a line
289  *
290  * @param rdl
291  *   A pointer to a struct ucg_rdline
292  * @param prompt
293  *   The prompt string
294  * @param flags
295  *   Any flags from UCG_RDLINE_F_*
296  *   - UCG_RDLINE_F_IGNORE_EOF: on eof, clear error and continue polling
297  * @return
298  *   - UCG_RDLINE_RES_VALIDATED when the line has been validated.
299  *   - UCG_RDLINE_RES_NOT_RUNNING if it is not running.
300  *   - UCG_RDLINE_RES_EOF if EOF (ctrl-d on an empty line).
301  *   - UCG_RDLINE_RES_EXITED if user called ucg_rdline_quit()
302  */
303 int ucg_rdline(struct ucg_rdline *rdl, const char *prompt, unsigned flags);
304
305 /**
306  * write a buffer on rdline file descriptor
307  *
308  * @param rdl
309  *   The rdline descriptor
310  * @param buf
311  *   Pointer to the buffer
312  * @param count
313  *   Number of bytes to write
314  * @return
315  *   On success, the number of bytes written is returned (zero
316  *   indicates nothing was written). On error, -1 is returned, and
317  *   errno is set appropriately
318  */
319 ssize_t ucg_rdline_write(struct ucg_rdline *rdl, void *buf, size_t count);
320
321 /**
322  * write on rdline file descriptor according to a format string
323  *
324  * @param rdl
325  *   The rdline descriptor
326  * @param fmt
327  *   The format strings
328  * @return
329  *   On success, return the number of characters printed (not including
330  *   the trailing '\0'). On error, a negative value is returned.
331  */
332 int ucg_rdline_printf(struct ucg_rdline *rdl, const char *fmt, ...);
333
334 /**
335  * write on rdline file descriptor according to a format string
336  *
337  * @param rdl
338  *   The rdline descriptor
339  * @param fmt
340  *   The format strings
341  * @param ap
342  *   Variable argument list
343  * @return
344  *   Upon successful return, these functions return the number of
345  *   characters printed (not including the trailing '\0' used to end
346  *   output to strings). On error, a negative value is returned.
347  */
348 int ucg_rdline_vprintf(struct ucg_rdline *rdl, const char *fmt, va_list ap);
349
350 /**
351  * Return the current buffer, terminated by '\0'.
352  *
353  * @param rdl
354  *   A pointer to a struct ucg_rdline
355  * @return
356  *   The rdline buffer
357  */
358 const char *ucg_rdline_get_buffer(struct ucg_rdline *rdl);
359
360 /**
361  * Add the buffer to history.
362  *
363  * @param rdl
364  *   A pointer to a struct ucg_rdline
365  * @param buf
366  *   A buffer that is terminated by '\0'
367  * @return
368  *   - 0 on success
369  *   - negative on error
370  */
371 int ucg_rdline_add_history(struct ucg_rdline *rdl, const char *buf);
372
373 /**
374  * Clear current history
375  *
376  * @param rdl
377  *   A pointer to a struct ucg_rdline
378  */
379 void ucg_rdline_clear_history(struct ucg_rdline *rdl);
380
381 /**
382  * Get the i-th history item
383  *
384  * @param rdl
385  *   A pointer to a struct ucg_rdline
386  * @param i
387  *   The index of the history item
388  * @return
389  *   The i-th string of history, or NULL on error.
390  */
391 const char *ucg_rdline_get_history_item(struct ucg_rdline *rdl, unsigned int i);
392
393 #ifndef UCG_CMD_NO_PAGER
394 /**
395  * Write data asynchronously (using pager if needed)
396  *
397  * If there is enough place to print data on the current page, it is
398  * printed synchronously. Else, a temporary buffer is allocated and
399  * the data is stored in it. When the main rdline is called again, the
400  * pager is flushed before parsing any other commands.
401  *
402  * @param rdl
403  *   The rdline descriptor
404  * @param buf
405  *   Buffer to be sent
406  * @param len
407  *   Length of buffer to be sent
408  * @return
409  *   On success, the number of bytes written is returned (zero
410  *   indicates nothing was written). On error, -1 is returned, and
411  *   errno is set appropriately
412  */
413 ssize_t ucg_rdline_pager_write(struct ucg_rdline *rdl, void *buf, size_t len);
414
415 /**
416  * Print data asynchronously (using pager if needed)
417  *
418  * If there is enough place to print data on the current page, it is
419  * printed synchronously. Else, a temporary buffer is allocated and
420  * the data is stored in it. When the main rdline is called again, the
421  * pager is flushed before parsing any other commands.
422  *
423  * @param rdl
424  *   The rdline descriptor
425  * @param fmt
426  *   The format strings
427  * @return
428  *   Upon successful return, these functions return the number of
429  *   characters printed (not including the trailing '\0' used to end
430  *   output to strings). On error, a negative value is returned.
431  */
432 int ucg_rdline_pager_printf(struct ucg_rdline *rdl, const char *fmt, ...);
433
434 /**
435  * Set the callback for the pager
436  *
437  * If there is some data in the pager to be printed, set a callback
438  * function that will be called when all the data will be printed. If
439  * the pager is empty, don't do anything and return -1.
440  * @param rdl
441  *   The rdline descriptor
442  * @return
443  *   - 0 if there is some data in the pager buffer and the callback
444  *     is loaded
445  *   - -1 if there is no data in pager buffer (in this case the callback
446  *     is not called)
447  */
448 int ucg_rdline_pager_set_cb(struct ucg_rdline *rdl,
449         ucg_rdline_pager_cb_t *cb, void *arg);
450 #endif
451
452 #endif /* UCG_CMD_RDLINE_H_ */