15129044dSC.J. Collier/*-
25129044dSC.J. Collier *   BSD LICENSE
35129044dSC.J. Collier *
45129044dSC.J. Collier *   Copyright(c) 2010-2014 Intel Corporation. All rights reserved.
55129044dSC.J. Collier *   All rights reserved.
65129044dSC.J. Collier *
75129044dSC.J. Collier *   Redistribution and use in source and binary forms, with or without
85129044dSC.J. Collier *   modification, are permitted provided that the following conditions
95129044dSC.J. Collier *   are met:
105129044dSC.J. Collier *
115129044dSC.J. Collier *     * Redistributions of source code must retain the above copyright
125129044dSC.J. Collier *       notice, this list of conditions and the following disclaimer.
135129044dSC.J. Collier *     * Redistributions in binary form must reproduce the above copyright
145129044dSC.J. Collier *       notice, this list of conditions and the following disclaimer in
155129044dSC.J. Collier *       the documentation and/or other materials provided with the
165129044dSC.J. Collier *       distribution.
175129044dSC.J. Collier *     * Neither the name of Intel Corporation nor the names of its
185129044dSC.J. Collier *       contributors may be used to endorse or promote products derived
195129044dSC.J. Collier *       from this software without specific prior written permission.
205129044dSC.J. Collier *
215129044dSC.J. Collier *   THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
225129044dSC.J. Collier *   "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
235129044dSC.J. Collier *   LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
245129044dSC.J. Collier *   A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
255129044dSC.J. Collier *   OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
265129044dSC.J. Collier *   SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
275129044dSC.J. Collier *   LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
285129044dSC.J. Collier *   DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
295129044dSC.J. Collier *   THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
305129044dSC.J. Collier *   (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
315129044dSC.J. Collier *   OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
325129044dSC.J. Collier */
335129044dSC.J. Collier
345129044dSC.J. Collier/*
355129044dSC.J. Collier * Copyright (c) 2009, Olivier MATZ <zer0@droids-corp.org>
365129044dSC.J. Collier * All rights reserved.
375129044dSC.J. Collier * Redistribution and use in source and binary forms, with or without
385129044dSC.J. Collier * modification, are permitted provided that the following conditions are met:
395129044dSC.J. Collier *
405129044dSC.J. Collier *     * Redistributions of source code must retain the above copyright
415129044dSC.J. Collier *       notice, this list of conditions and the following disclaimer.
425129044dSC.J. Collier *     * Redistributions in binary form must reproduce the above copyright
435129044dSC.J. Collier *       notice, this list of conditions and the following disclaimer in the
445129044dSC.J. Collier *       documentation and/or other materials provided with the distribution.
455129044dSC.J. Collier *     * Neither the name of the University of California, Berkeley nor the
465129044dSC.J. Collier *       names of its contributors may be used to endorse or promote products
475129044dSC.J. Collier *       derived from this software without specific prior written permission.
485129044dSC.J. Collier *
495129044dSC.J. Collier * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND ANY
505129044dSC.J. Collier * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
515129044dSC.J. Collier * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
525129044dSC.J. Collier * DISCLAIMED. IN NO EVENT SHALL THE REGENTS AND CONTRIBUTORS BE LIABLE FOR ANY
535129044dSC.J. Collier * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
545129044dSC.J. Collier * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
555129044dSC.J. Collier * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
565129044dSC.J. Collier * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
575129044dSC.J. Collier * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
585129044dSC.J. Collier * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
595129044dSC.J. Collier */
605129044dSC.J. Collier
615129044dSC.J. Collier#ifndef _RDLINE_H_
625129044dSC.J. Collier#define _RDLINE_H_
635129044dSC.J. Collier
645129044dSC.J. Collier/**
655129044dSC.J. Collier * This file is a small equivalent to the GNU readline library, but it
665129044dSC.J. Collier * was originally designed for small systems, like Atmel AVR
675129044dSC.J. Collier * microcontrollers (8 bits). Indeed, we don't use any malloc that is
685129044dSC.J. Collier * sometimes not implemented (or just not recommended) on such
695129044dSC.J. Collier * systems.
705129044dSC.J. Collier *
715129044dSC.J. Collier * Obviously, it does not support as many things as the GNU readline,
725129044dSC.J. Collier * but at least it supports some interesting features like a kill
735129044dSC.J. Collier * buffer and a command history.
745129044dSC.J. Collier *
755129044dSC.J. Collier * It also have a feature that does not have the GNU readline (as far
765129044dSC.J. Collier * as I know): we can have several instances of it running at the same
775129044dSC.J. Collier * time, even on a monothread program, since it works with callbacks.
785129044dSC.J. Collier *
795129044dSC.J. Collier * The lib is designed for a client-side or a server-side use:
805129044dSC.J. Collier * - server-side: the server receives all data from a socket, including
815129044dSC.J. Collier *   control chars, like arrows, tabulations, ... The client is
825129044dSC.J. Collier *   very simple, it can be a telnet or a minicom through a serial line.
835129044dSC.J. Collier * - client-side: the client receives its data through its stdin for
845129044dSC.J. Collier *   instance.
855129044dSC.J. Collier */
865129044dSC.J. Collier
875129044dSC.J. Collier#include <stdio.h>
885129044dSC.J. Collier#include <cmdline_cirbuf.h>
895129044dSC.J. Collier#include <cmdline_vt100.h>
905129044dSC.J. Collier
915129044dSC.J. Collier#ifdef __cplusplus
925129044dSC.J. Collierextern "C" {
935129044dSC.J. Collier#endif
945129044dSC.J. Collier
955129044dSC.J. Collier/* configuration */
965129044dSC.J. Collier#define RDLINE_BUF_SIZE 512
975129044dSC.J. Collier#define RDLINE_PROMPT_SIZE  32
985129044dSC.J. Collier#define RDLINE_VT100_BUF_SIZE  8
995129044dSC.J. Collier#define RDLINE_HISTORY_BUF_SIZE BUFSIZ
1005129044dSC.J. Collier#define RDLINE_HISTORY_MAX_LINE 64
1015129044dSC.J. Collier
1025129044dSC.J. Collierenum rdline_status {
1035129044dSC.J. Collier	RDLINE_INIT,
1045129044dSC.J. Collier	RDLINE_RUNNING,
1055129044dSC.J. Collier	RDLINE_EXITED
1065129044dSC.J. Collier};
1075129044dSC.J. Collier
1085129044dSC.J. Collierstruct rdline;
1095129044dSC.J. Collier
1105129044dSC.J. Colliertypedef int (rdline_write_char_t)(struct rdline *rdl, char);
1115129044dSC.J. Colliertypedef void (rdline_validate_t)(struct rdline *rdl,
1125129044dSC.J. Collier				 const char *buf, unsigned int size);
1135129044dSC.J. Colliertypedef int (rdline_complete_t)(struct rdline *rdl, const char *buf,
1145129044dSC.J. Collier				char *dstbuf, unsigned int dstsize,
1155129044dSC.J. Collier				int *state);
1165129044dSC.J. Collier
1175129044dSC.J. Collierstruct rdline {
1185129044dSC.J. Collier	enum rdline_status status;
1195129044dSC.J. Collier	/* rdline bufs */
1205129044dSC.J. Collier	struct cirbuf left;
1215129044dSC.J. Collier	struct cirbuf right;
1225129044dSC.J. Collier	char left_buf[RDLINE_BUF_SIZE+2]; /* reserve 2 chars for the \n\0 */
1235129044dSC.J. Collier	char right_buf[RDLINE_BUF_SIZE];
1245129044dSC.J. Collier
1255129044dSC.J. Collier	char prompt[RDLINE_PROMPT_SIZE];
1265129044dSC.J. Collier	unsigned int prompt_size;
1275129044dSC.J. Collier
1285129044dSC.J. Collier	char kill_buf[RDLINE_BUF_SIZE];
1295129044dSC.J. Collier	unsigned int kill_size;
1305129044dSC.J. Collier
1315129044dSC.J. Collier	/* history */
1325129044dSC.J. Collier	struct cirbuf history;
1335129044dSC.J. Collier	char history_buf[RDLINE_HISTORY_BUF_SIZE];
1345129044dSC.J. Collier	int history_cur_line;
1355129044dSC.J. Collier
1365129044dSC.J. Collier	/* callbacks and func pointers */
1375129044dSC.J. Collier	rdline_write_char_t *write_char;
1385129044dSC.J. Collier	rdline_validate_t *validate;
1395129044dSC.J. Collier	rdline_complete_t *complete;
1405129044dSC.J. Collier
1415129044dSC.J. Collier	/* vt100 parser */
1425129044dSC.J. Collier	struct cmdline_vt100 vt100;
1435129044dSC.J. Collier
1445129044dSC.J. Collier	/* opaque pointer */
1455129044dSC.J. Collier	void *opaque;
1465129044dSC.J. Collier};
1475129044dSC.J. Collier
1485129044dSC.J. Collier/**
1495129044dSC.J. Collier * Init fields for a struct rdline. Call this only once at the beginning
1505129044dSC.J. Collier * of your program.
1515129044dSC.J. Collier * \param rdl A pointer to an uninitialized struct rdline
1525129044dSC.J. Collier * \param write_char The function used by the function to write a character
1535129044dSC.J. Collier * \param validate A pointer to the function to execute when the
1545129044dSC.J. Collier *                 user validates the buffer.
1555129044dSC.J. Collier * \param complete A pointer to the function to execute when the
1565129044dSC.J. Collier *                 user completes the buffer.
1575129044dSC.J. Collier */
1585129044dSC.J. Collierint rdline_init(struct rdline *rdl,
1595129044dSC.J. Collier		 rdline_write_char_t *write_char,
1605129044dSC.J. Collier		 rdline_validate_t *validate,
1615129044dSC.J. Collier		 rdline_complete_t *complete);
1625129044dSC.J. Collier
1635129044dSC.J. Collier
1645129044dSC.J. Collier/**
1655129044dSC.J. Collier * Init the current buffer, and display a prompt.
1665129044dSC.J. Collier * \param rdl A pointer to a struct rdline
1675129044dSC.J. Collier * \param prompt A string containing the prompt
1685129044dSC.J. Collier */
1695129044dSC.J. Colliervoid rdline_newline(struct rdline *rdl, const char *prompt);
1705129044dSC.J. Collier
1715129044dSC.J. Collier/**
1725129044dSC.J. Collier * Call it and all received chars will be ignored.
1735129044dSC.J. Collier * \param rdl A pointer to a struct rdline
1745129044dSC.J. Collier */
1755129044dSC.J. Colliervoid rdline_stop(struct rdline *rdl);
1765129044dSC.J. Collier
1775129044dSC.J. Collier/**
1785129044dSC.J. Collier * Same than rdline_stop() except that next calls to rdline_char_in()
1795129044dSC.J. Collier * will return RDLINE_RES_EXITED.
1805129044dSC.J. Collier * \param rdl A pointer to a struct rdline
1815129044dSC.J. Collier */
1825129044dSC.J. Colliervoid rdline_quit(struct rdline *rdl);
1835129044dSC.J. Collier
1845129044dSC.J. Collier/**
1855129044dSC.J. Collier * Restart after a call to rdline_stop() or rdline_quit()
1865129044dSC.J. Collier * \param rdl A pointer to a struct rdline
1875129044dSC.J. Collier */
1885129044dSC.J. Colliervoid rdline_restart(struct rdline *rdl);
1895129044dSC.J. Collier
1905129044dSC.J. Collier/**
1915129044dSC.J. Collier * Redisplay the current buffer
1925129044dSC.J. Collier * \param rdl A pointer to a struct rdline
1935129044dSC.J. Collier */
1945129044dSC.J. Colliervoid rdline_redisplay(struct rdline *rdl);
1955129044dSC.J. Collier
1965129044dSC.J. Collier/**
1975129044dSC.J. Collier * Reset the current buffer and setup for a new line.
1985129044dSC.J. Collier *  \param rdl A pointer to a struct rdline
1995129044dSC.J. Collier */
2005129044dSC.J. Colliervoid rdline_reset(struct rdline *rdl);
2015129044dSC.J. Collier
2025129044dSC.J. Collier
2035129044dSC.J. Collier/* return status for rdline_char_in() */
2045129044dSC.J. Collier#define RDLINE_RES_SUCCESS       0
2055129044dSC.J. Collier#define RDLINE_RES_VALIDATED     1
2065129044dSC.J. Collier#define RDLINE_RES_COMPLETE      2
2075129044dSC.J. Collier#define RDLINE_RES_NOT_RUNNING  -1
2085129044dSC.J. Collier#define RDLINE_RES_EOF          -2
2095129044dSC.J. Collier#define RDLINE_RES_EXITED       -3
2105129044dSC.J. Collier
2115129044dSC.J. Collier/**
2125129044dSC.J. Collier * append a char to the readline buffer.
2135129044dSC.J. Collier * Return RDLINE_RES_VALIDATE when the line has been validated.
2145129044dSC.J. Collier * Return RDLINE_RES_COMPLETE when the user asked to complete the buffer.
2155129044dSC.J. Collier * Return RDLINE_RES_NOT_RUNNING if it is not running.
2165129044dSC.J. Collier * Return RDLINE_RES_EOF if EOF (ctrl-d on an empty line).
2175129044dSC.J. Collier * Else return RDLINE_RES_SUCCESS.
2185129044dSC.J. Collier * XXX error case when the buffer is full ?
2195129044dSC.J. Collier *
2205129044dSC.J. Collier * \param rdl A pointer to a struct rdline
2215129044dSC.J. Collier * \param c The character to append
2225129044dSC.J. Collier */
2235129044dSC.J. Collierint rdline_char_in(struct rdline *rdl, char c);
2245129044dSC.J. Collier
2255129044dSC.J. Collier/**
2265129044dSC.J. Collier * Return the current buffer, terminated by '\0'.
2275129044dSC.J. Collier * \param rdl A pointer to a struct rdline
2285129044dSC.J. Collier */
2295129044dSC.J. Collierconst char *rdline_get_buffer(struct rdline *rdl);
2305129044dSC.J. Collier
2315129044dSC.J. Collier
2325129044dSC.J. Collier/**
2335129044dSC.J. Collier * Add the buffer to history.
2345129044dSC.J. Collier * return < 0 on error.
2355129044dSC.J. Collier * \param rdl A pointer to a struct rdline
2365129044dSC.J. Collier * \param buf A buffer that is terminated by '\0'
2375129044dSC.J. Collier */
2385129044dSC.J. Collierint rdline_add_history(struct rdline *rdl, const char *buf);
2395129044dSC.J. Collier
2405129044dSC.J. Collier/**
2415129044dSC.J. Collier * Clear current history
2425129044dSC.J. Collier * \param rdl A pointer to a struct rdline
2435129044dSC.J. Collier */
2445129044dSC.J. Colliervoid rdline_clear_history(struct rdline *rdl);
2455129044dSC.J. Collier
2465129044dSC.J. Collier/**
2475129044dSC.J. Collier * Get the i-th history item
2485129044dSC.J. Collier */
2495129044dSC.J. Collierchar *rdline_get_history_item(struct rdline *rdl, unsigned int i);
2505129044dSC.J. Collier
2515129044dSC.J. Collier#ifdef __cplusplus
2525129044dSC.J. Collier}
2535129044dSC.J. Collier#endif
2545129044dSC.J. Collier
2555129044dSC.J. Collier#endif /* _RDLINE_H_ */
256