X-Git-Url: http://git.droids-corp.org/?a=blobdiff_plain;f=src%2Flib%2Fcmdline_rdline.h;h=47ab6c99b90803a947c330221207e30e1614550b;hb=568d6d51fc9e6e2d8842fc1abe63c23de503f8bc;hp=20f7652e1575bc6946463866007a3e8d53a91761;hpb=c60ed50ac1449a2b2bccc33598d1f68458a36fb1;p=libcmdline.git diff --git a/src/lib/cmdline_rdline.h b/src/lib/cmdline_rdline.h index 20f7652..47ab6c9 100644 --- a/src/lib/cmdline_rdline.h +++ b/src/lib/cmdline_rdline.h @@ -1,3 +1,37 @@ +/*- + * Copyright (c) <2010>, Intel Corporation + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * - Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * - Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * + * - Neither the name of Intel Corporation nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, + * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED + * OF THE POSSIBILITY OF SUCH DAMAGE. + */ + /* * Copyright (c) 2009, Olivier MATZ * All rights reserved. @@ -29,76 +63,62 @@ #define _RDLINE_H_ /** - * This file is a small equivalent to the GNU readline library, but it - * was originally designed for small systems, like Atmel AVR - * microcontrollers (8 bits). Indeed, we don't use any malloc that is - * sometimes not implemented (or just not recommended) on such - * systems. + * This file is a small equivalent to the GNU readline library, it was + * originally designed for very small systems (an 8-bits Atmel AVR + * microcontroller), but the library can now run on many emmbedded + * systems with or without OS. * * Obviously, it does not support as many things as the GNU readline, * but at least it supports some interresting features like a kill * buffer and a command history. * * It also have a feature that does not have the GNU readline (as far - * as I know): we can have several instances of it running at the same - * time, even on a monothread program, since it works with callbacks. - * - * The lib is designed for a client-side or a server-side use: - * - server-side: the server receives all data from a socket, including - * control chars, like arrows, tabulations, ... The client is - * very simple, it can be a telnet or a minicom through a serial line. - * - client-side: the client receives its data through its stdin for - * instance. + * as I know): it is possible to have several instances of readline + * running at the same time, even on a monothread program, since it + * works with callbacks. */ #include #include -#define vt100_bell "\007" -#define vt100_bs "\010" -#define vt100_bs_clear "\010 \010" -#define vt100_tab "\011" -#define vt100_crnl "\012\015" -#define vt100_clear_right "\033[0K" -#define vt100_clear_left "\033[1K" -#define vt100_clear_down "\033[0J" -#define vt100_clear_up "\033[1J" -#define vt100_clear_line "\033[2K" -#define vt100_clear_screen "\033[2J" -#define vt100_up_arr "\033\133\101" -#define vt100_down_arr "\033\133\102" -#define vt100_right_arr "\033\133\103" -#define vt100_left_arr "\033\133\104" -#define vt100_multi_right "\033\133%uC" -#define vt100_multi_left "\033\133%uD" -#define vt100_suppr "\033\133\063\176" -#define vt100_home "\033M\033E" -#define vt100_word_left "\033\142" -#define vt100_word_right "\033\146" - /* configuration */ #define RDLINE_BUF_SIZE 256 #define RDLINE_PROMPT_SIZE 32 #define RDLINE_VT100_BUF_SIZE 8 #define RDLINE_HISTORY_BUF_SIZE BUFSIZ #define RDLINE_HISTORY_MAX_LINE 64 +#define RDLINE_MAX_LINES 23 enum rdline_status { - RDLINE_INIT, + RDLINE_STOPPED, RDLINE_RUNNING, + RDLINE_EXITED }; struct rdline; -typedef void (rdline_write_char_t)(struct rdline *rdl, char); +/** + * callback given to rdline_help() to display the content of the + * help. The first argument is an opaque pointer. The other args + * are buffer and size. + */ +typedef ssize_t (rdline_write_t)(struct rdline *, void *, size_t); + + typedef void (rdline_validate_t)(struct rdline *rdl, const char *buf, unsigned int size); typedef int (rdline_complete_t)(struct rdline *rdl, const char *buf, - char *dstbuf, unsigned int dstsize, - int *state); + char *dstbuf, unsigned int dstsize); +typedef int (rdline_help_t)(struct rdline *rdl, const char *buf, + rdline_write_t *write, void *opaque); + +typedef void (rdline_asyncpager_cb_t)(struct rdline *, void *); struct rdline { enum rdline_status status; + int fd_in; + int fd_out; + /* rdline bufs */ struct cirbuf left; struct cirbuf right; @@ -106,7 +126,6 @@ struct rdline { char right_buf[RDLINE_BUF_SIZE]; char prompt[RDLINE_PROMPT_SIZE]; - unsigned int prompt_size; #ifndef NO_RDLINE_KILL_BUF char kill_buf[RDLINE_BUF_SIZE]; @@ -121,97 +140,287 @@ struct rdline { #endif /* callbacks and func pointers */ - rdline_write_char_t *write_char; rdline_validate_t *validate; rdline_complete_t *complete; + rdline_help_t *help; /* vt100 parser */ struct cmdline_vt100 vt100; /* opaque pointer */ void *opaque; + +#ifndef NO_PAGER + char *pager_buf; /* buffer used to store paged data */ + int pager_len; /* total len of buffer */ + int pager_off; /* offset of next data */ + int pager_lines; /* number of lines displayed */ + rdline_asyncpager_cb_t *pager_cb; /* callback once paging is finished */ + void *pager_arg; /* argument of callback */ + int pager_ret; /* saved return value */ +#endif }; /** - * Init fields for a struct rdline. Call this only once at the beginning - * of your program. - * \param rdl A pointer to an uninitialized struct rdline - * \param write_char The function used by the function to write a character - * \param validate A pointer to the function to execute when the - * user validates the buffer. - * \param complete A pointer to the function to execute when the - * user completes the buffer. + * Init fields for a struct rdline. + * + * @param rdl A pointer to an uninitialized struct rdline + * @param fd_in + * Input file descriptor + * @param fd_out + * Output file descriptor + * @param validate + * A pointer to the function to execute when the user validates the + * buffer. + * @param complete + * A pointer to the function to execute when the user completes the + * buffer. + * @param help + * A pointer to the function to execute when the user ask for + * contextual help. */ void rdline_init(struct rdline *rdl, - rdline_write_char_t *write_char, + int fd_in, int fd_out, rdline_validate_t *validate, - rdline_complete_t *complete); + rdline_complete_t *complete, + rdline_help_t *help); /** * Init the current buffer, and display a prompt. - * \param rdl A pointer to a struct rdline - * \param prompt A string containing the prompt + * + * Also set the rdline status to "running", overriding previous + * rdline_stop() or rdline_quit(). + * + * @param rdl + * A pointer to an initialized struct rdline + * @param prompt + * A string containing the prompt */ void rdline_newline(struct rdline *rdl, const char *prompt); /** - * Call it and all received chars will be ignored. - * \param rdl A pointer to a struct rdline + * Ignore all subsequent received chars. + * + * @param rdl + * A pointer to a struct rdline */ void rdline_stop(struct rdline *rdl); /** - * Restart after a call to rdline_stop() - * \param rdl A pointer to a struct rdline + * Exit from running rdline loop + * + * Same than rdline_stop() except that next calls to rdline_char_in() + * will return RDLINE_RES_EXITED. Hence, any running rdline() function is + * interrupted. + * + * @param rdl + * A pointer to a struct rdline + */ +void rdline_quit(struct rdline *rdl); + +/** + * Restart after a call to rdline_stop() or rdline_quit() + * + * @param rdl + * A pointer to a struct rdline */ void rdline_restart(struct rdline *rdl); /** * Redisplay the current buffer - * \param rdl A pointer to a struct rdline + * + * @param rdl + * A pointer to a struct rdline */ void rdline_redisplay(struct rdline *rdl); +/* return status for rdline_char_in() */ +#define RDLINE_RES_SUCCESS 0 +#define RDLINE_RES_VALIDATED 1 +#define RDLINE_RES_NOT_RUNNING -1 +#define RDLINE_RES_EOF -2 +#define RDLINE_RES_EXITED -3 + /** - * append a char to the readline buffer. - * Return 1 when the line has been validated. - * Return 2 when the user asked to complete the buffer. - * Return -1 if it is not running. - * Return -2 if EOF (ctrl-d on an empty line). - * Else return 0. - * XXX error case when the buffer is full ? + * Append a char to the readline buffer. * - * \param rdl A pointer to a struct rdline - * \param c The character to append + * @param rdl + * A pointer to a struct rdline + * @param c + * The character to append + * @return + * - RDLINE_RES_VALIDATED when the line has been validated. + * - RDLINE_RES_NOT_RUNNING if it is not running. + * - RDLINE_RES_EOF if EOF (ctrl-d on an empty line). + * - RDLINE_RES_EXITED if user called rdline_quit() + * - Else return RDLINE_RES_SUCCESS. */ int rdline_char_in(struct rdline *rdl, char c); +/** + * Read (and edit) a line + * + * @param rdl + * A pointer to a struct rdline + * @param prompt + * The prompt string + * @return + * - RDLINE_RES_VALIDATED when the line has been validated. + * - RDLINE_RES_NOT_RUNNING if it is not running. + * - RDLINE_RES_EOF if EOF (ctrl-d on an empty line). + * - RDLINE_RES_EXITED if user called rdline_quit() + */ +int rdline(struct rdline *rdl, const char *prompt); + +/** + * write a buffer on rdline file descriptor + * + * @param rdl + * The rdline descriptor + * @param buf + * Pointer to the buffer + * @param count + * Number of bytes to write + * @return + * On success, the number of bytes written is returned (zero + * indicates nothing was written). On error, -1 is returned, and + * errno is set appropriately + */ +ssize_t rdline_write(const struct rdline *rdl, void *buf, size_t count); + +/** + * write on rdline file descriptor according to a format string + * + * @param rdl + * The rdline descriptor + * @param fmt + * The format strings + * @return + * Upon successful return, these functions return the number of + * characters printed (not including the trailing '\0' used to end + * output to strings). On error, a negative value is returned. + */ +int rdline_printf(const struct rdline *rdl, const char *fmt, ...); + +/** + * write on rdline file descriptor according to a format string + * + * @param rdl + * The rdline descriptor + * @param fmt + * The format strings + * @param ap + * Variable argument list + * @return + * Upon successful return, these functions return the number of + * characters printed (not including the trailing '\0' used to end + * output to strings). On error, a negative value is returned. + */ +int rdline_vprintf(const struct rdline *rdl, const char *fmt, va_list ap); + /** * Return the current buffer, terminated by '\0'. - * \param rdl A pointer to a struct rdline + * + * @param rdl + * A pointer to a struct rdline + * @return + * The rdline buffer */ const char *rdline_get_buffer(struct rdline *rdl); - /** * Add the buffer to history. - * return < 0 on error. - * \param rdl A pointer to a struct rdline - * \param buf A buffer that is terminated by '\0' + * + * @param rdl + * A pointer to a struct rdline + * @param buf + * A buffer that is terminated by '\0' + * @return + * - 0 on success + * - negative on error */ int rdline_add_history(struct rdline *rdl, const char *buf); /** * Clear current history - * \param rdl A pointer to a struct rdline + * + * @param rdl + * A pointer to a struct rdline */ void rdline_clear_history(struct rdline *rdl); /** * Get the i-th history item + * + * @param rdl + * A pointer to a struct rdline + * @param i + * The index of the history item + * @return + * The i-th string of history, or NULL on error. */ char *rdline_get_history_item(struct rdline *rdl, unsigned int i); +#ifndef NO_PAGER +/** + * Write data asynchronously (using pager if needed) + * + * If there is enough place to print data on the current page, it is + * printed synchronously. Else, a temporary buffer is allocated and + * the data is stored in it. When the main rdline is called again, the + * pager is flushed before parsing any other commands. + * + * @param rdl + * The rdline descriptor + * @param buf + * Buffer to be sent + * @param len + * Length of buffer to be sent + * @return + * On success, the number of bytes written is returned (zero + * indicates nothing was written). On error, -1 is returned, and + * errno is set appropriately + */ +ssize_t rdline_asyncpager_write(struct rdline *rdl, void *buf, size_t len); + +/** + * Print data asynchronously (using pager if needed) + * + * If there is enough place to print data on the current page, it is + * printed synchronously. Else, a temporary buffer is allocated and + * the data is stored in it. When the main rdline is called again, the + * pager is flushed before parsing any other commands. + * + * @param rdl + * The rdline descriptor + * @param fmt + * The format strings + * @return + * Upon successful return, these functions return the number of + * characters printed (not including the trailing '\0' used to end + * output to strings). On error, a negative value is returned. + */ +int rdline_asyncpager_printf(struct rdline *rdl, const char *fmt, ...); + +/** + * Set the callback for the pager + * + * If there is some data in the pager to be printed, set a callback + * function that will be called when all the data will be printed. If + * the pager is empty, don't do anything and return -1. + * @param rdl + * The rdline descriptor + * @return + * - 0 if there is some data in the pager buffer and the callback + * is loaded + * - -1 if there is no data in pager buffer (in this case the callback + * is not called) + */ +int rdline_asyncpager_set_cb(struct rdline *rdl, rdline_asyncpager_cb_t *cb, + void *arg); +#endif + + #endif /* _RDLINE_H_ */