* [dpdk-dev] [RFC] cmdline: rework as a wrapper to libedit @ 2017-11-09 13:43 Adrien Mazarguil 2017-11-15 4:12 ` Wiles, Keith ` (2 more replies) 0 siblings, 3 replies; 18+ messages in thread From: Adrien Mazarguil @ 2017-11-09 13:43 UTC (permalink / raw) To: Olivier Matz, Jingjing Wu; +Cc: dev, Thomas Monjalon, Ferruh Yigit This patch removes all code associated with symbols not internally relied on by other DPDK components, makes struct cmdline opaque and then proceeds to re-implement the remaining functionality as a wrapper to the editline library (also known as libedit) [1]. Besides adding a new external dependency to its users, its large impact on librte_cmdline's API/ABI also warrants a major version number bump. While librte_cmdline served DPDK well all these years as a small, easy to use and self-sufficient interactive command-line handler, it started to show its limits with testpmd's flow (rte_flow) command, which required support for dynamic tokens and very long commands. This is the main motivation behind this rework. Long commands often need to be displayed on multiple lines, which are not properly supported by librte_cmdline's limited terminal handling capabilities, resulting in a rather frustrating user experience. Testpmd being one of the main tools used by PMD developers and given flow command lines won't get any shorter, this issue had to be addressed. Three options were considered: - Fixing and enhancing librte_cmdline. The amount of work necessary to add support for edition on multiple lines was deemed significant and the result would still have lacked in some areas, such as working backspace/delete keys in all terminals (i.e. full termcap support). - Making testpmd directly rely on a more capable library. All testpmd commands rely on the cmdline_parse interface provided by librte_cmdline. This approach would have required either a complete rewrite or importing the missing bits from librte_cmdline to wrap them around the new library, which naturally led to... - Converting librte_cmdline as a wrapper to a more capable library. Let's be honest, interactive command line handling isn't what makes DPDK shine. It's also far removed from its core functionality, but is still necessary in order to easily implement test and example programs; the cmdline_parse interface is particularly good at this. DPDK actually only relies on cmdline_parse. By removing all the other unused interfaces, implementing what remains on top of a different terminal-handling library would be quick and easy. This last approach was chosen for the stated reasons. Libedit is well-known, BSD-licensed, widely available [2], used by many projects, does everything needed and more [3]. This rework results in the following changes: - Removed circular buffer management interface for command history (cmdline_cirbuf.c), command history being handled by libedit. - Removed raw command-line interpreter (cmdline_rdline.c). - Removed raw terminal handler (cmdline_vt100.c). - Removed all test/example code for the above. - Re-implemented high level interactive and non-interactive command-line handlers (cmdline.c and cmdline_socket.c) on top of libedit using its native interface, not its readline compatibility layer. - Made struct cmdline opaque so that applications relying on librte_cmdline do not need to include any libedit headers. - The only visible change for most applications besides being linked to libedit is they do not have to include cmdline_rdline.h anymore. As an added bonus, terminal resizing is now automatically handled. In the future, cmdline_parse could use libedit's advanced tokenizer as well to interpret quoted strings and escape sequences. [1] http://thrysoee.dk/editline/ [2] It usually goes by the name "libedit" in Linux distributions. [3] http://netbsd.gw.com/cgi-bin/man-cgi?editline++NetBSD-current Signed-off-by: Adrien Mazarguil <adrien.mazarguil@6wind.com> --- app/test-pmd/cmdline.c | 1 - examples/bond/main.c | 1 - examples/cmdline/commands.c | 1 - examples/cmdline/main.c | 1 - .../ip_pipeline/pipeline/pipeline_common_fe.c | 1 - .../ip_pipeline/pipeline/pipeline_firewall.c | 1 - .../pipeline/pipeline_flow_actions.c | 1 - .../pipeline/pipeline_flow_classification.c | 1 - examples/ip_pipeline/thread_fe.c | 1 - examples/multi_process/simple_mp/main.c | 1 - examples/multi_process/simple_mp/mp_commands.c | 1 - examples/qos_sched/cmdline.c | 1 - examples/quota_watermark/qwctl/commands.c | 1 - examples/quota_watermark/qwctl/qwctl.c | 1 - .../guest_cli/vm_power_cli_guest.c | 1 - examples/vm_power_manager/vm_power_cli.c | 1 - lib/librte_cmdline/Makefile | 10 +- lib/librte_cmdline/cmdline.c | 385 +++-- lib/librte_cmdline/cmdline.h | 22 +- lib/librte_cmdline/cmdline_cirbuf.c | 466 ------ lib/librte_cmdline/cmdline_cirbuf.h | 245 ---- lib/librte_cmdline/cmdline_parse.c | 7 +- lib/librte_cmdline/cmdline_rdline.c | 697 --------- lib/librte_cmdline/cmdline_rdline.h | 255 ---- lib/librte_cmdline/cmdline_socket.c | 36 +- lib/librte_cmdline/cmdline_vt100.c | 185 --- lib/librte_cmdline/cmdline_vt100.h | 153 -- lib/librte_cmdline/rte_cmdline_version.map | 41 +- mk/rte.app.mk | 2 + test/cmdline_test/cmdline_test.c | 1 - test/cmdline_test/commands.c | 69 - test/test/Makefile | 1 - test/test/commands.c | 1 - test/test/test.c | 1 - test/test/test_cmdline.c | 9 - test/test/test_cmdline.h | 6 - test/test/test_cmdline_cirbuf.c | 1330 ------------------ test/test/test_cmdline_lib.c | 117 +- 38 files changed, 293 insertions(+), 3762 deletions(-) diff --git a/app/test-pmd/cmdline.c b/app/test-pmd/cmdline.c index f71d963..9fe625c 100644 --- a/app/test-pmd/cmdline.c +++ b/app/test-pmd/cmdline.c @@ -77,7 +77,6 @@ #include <rte_flow.h> #include <rte_gro.h> -#include <cmdline_rdline.h> #include <cmdline_parse.h> #include <cmdline_parse_num.h> #include <cmdline_parse_string.h> diff --git a/examples/bond/main.c b/examples/bond/main.c index 8e3b1f3..d903314 100644 --- a/examples/bond/main.c +++ b/examples/bond/main.c @@ -71,7 +71,6 @@ #include <rte_arp.h> #include <rte_spinlock.h> -#include <cmdline_rdline.h> #include <cmdline_parse.h> #include <cmdline_parse_num.h> #include <cmdline_parse_string.h> diff --git a/examples/cmdline/commands.c b/examples/cmdline/commands.c index f3ba247..e8fa7f0 100644 --- a/examples/cmdline/commands.c +++ b/examples/cmdline/commands.c @@ -74,7 +74,6 @@ #endif #endif -#include <cmdline_rdline.h> #include <cmdline_parse.h> #include <cmdline_parse_ipaddr.h> #include <cmdline_parse_num.h> diff --git a/examples/cmdline/main.c b/examples/cmdline/main.c index c6de944..c229f50 100644 --- a/examples/cmdline/main.c +++ b/examples/cmdline/main.c @@ -65,7 +65,6 @@ #include <termios.h> #include <sys/queue.h> -#include <cmdline_rdline.h> #include <cmdline_parse.h> #include <cmdline_socket.h> #include <cmdline.h> diff --git a/examples/ip_pipeline/pipeline/pipeline_common_fe.c b/examples/ip_pipeline/pipeline/pipeline_common_fe.c index 7521187..f1df197 100644 --- a/examples/ip_pipeline/pipeline/pipeline_common_fe.c +++ b/examples/ip_pipeline/pipeline/pipeline_common_fe.c @@ -37,7 +37,6 @@ #include <rte_common.h> #include <rte_malloc.h> -#include <cmdline_rdline.h> #include <cmdline_parse.h> #include <cmdline_parse_num.h> #include <cmdline_parse_string.h> diff --git a/examples/ip_pipeline/pipeline/pipeline_firewall.c b/examples/ip_pipeline/pipeline/pipeline_firewall.c index a82e552..e49d9ca 100644 --- a/examples/ip_pipeline/pipeline/pipeline_firewall.c +++ b/examples/ip_pipeline/pipeline/pipeline_firewall.c @@ -41,7 +41,6 @@ #include <rte_common.h> #include <rte_hexdump.h> #include <rte_malloc.h> -#include <cmdline_rdline.h> #include <cmdline_parse.h> #include <cmdline_parse_num.h> #include <cmdline_parse_string.h> diff --git a/examples/ip_pipeline/pipeline/pipeline_flow_actions.c b/examples/ip_pipeline/pipeline/pipeline_flow_actions.c index 349db6b..0f680db 100644 --- a/examples/ip_pipeline/pipeline/pipeline_flow_actions.c +++ b/examples/ip_pipeline/pipeline/pipeline_flow_actions.c @@ -40,7 +40,6 @@ #include <rte_common.h> #include <rte_hexdump.h> #include <rte_malloc.h> -#include <cmdline_rdline.h> #include <cmdline_parse.h> #include <cmdline_parse_num.h> #include <cmdline_parse_string.h> diff --git a/examples/ip_pipeline/pipeline/pipeline_flow_classification.c b/examples/ip_pipeline/pipeline/pipeline_flow_classification.c index 70b1938..b9e4ed5 100644 --- a/examples/ip_pipeline/pipeline/pipeline_flow_classification.c +++ b/examples/ip_pipeline/pipeline/pipeline_flow_classification.c @@ -40,7 +40,6 @@ #include <rte_common.h> #include <rte_hexdump.h> #include <rte_malloc.h> -#include <cmdline_rdline.h> #include <cmdline_parse.h> #include <cmdline_parse_num.h> #include <cmdline_parse_string.h> diff --git a/examples/ip_pipeline/thread_fe.c b/examples/ip_pipeline/thread_fe.c index 4590c2b..4f54094 100644 --- a/examples/ip_pipeline/thread_fe.c +++ b/examples/ip_pipeline/thread_fe.c @@ -1,7 +1,6 @@ #include <rte_common.h> #include <rte_ring.h> #include <rte_malloc.h> -#include <cmdline_rdline.h> #include <cmdline_parse.h> #include <cmdline_parse_num.h> #include <cmdline_parse_string.h> diff --git a/examples/multi_process/simple_mp/main.c b/examples/multi_process/simple_mp/main.c index 62537b0..c0fc6ea 100644 --- a/examples/multi_process/simple_mp/main.c +++ b/examples/multi_process/simple_mp/main.c @@ -64,7 +64,6 @@ #include <rte_ring.h> #include <rte_log.h> #include <rte_mempool.h> -#include <cmdline_rdline.h> #include <cmdline_parse.h> #include <cmdline_parse_string.h> #include <cmdline_socket.h> diff --git a/examples/multi_process/simple_mp/mp_commands.c b/examples/multi_process/simple_mp/mp_commands.c index ef6dc58..264dea2 100644 --- a/examples/multi_process/simple_mp/mp_commands.c +++ b/examples/multi_process/simple_mp/mp_commands.c @@ -54,7 +54,6 @@ #include <rte_mempool.h> #include <rte_string_fns.h> -#include <cmdline_rdline.h> #include <cmdline_parse.h> #include <cmdline_parse_string.h> #include <cmdline_socket.h> diff --git a/examples/qos_sched/cmdline.c b/examples/qos_sched/cmdline.c index b62d165..c2a4f6b 100644 --- a/examples/qos_sched/cmdline.c +++ b/examples/qos_sched/cmdline.c @@ -36,7 +36,6 @@ #include <inttypes.h> #include <string.h> -#include <cmdline_rdline.h> #include <cmdline_parse.h> #include <cmdline_parse_num.h> #include <cmdline_parse_string.h> diff --git a/examples/quota_watermark/qwctl/commands.c b/examples/quota_watermark/qwctl/commands.c index 5cac0e1..a30a35c 100644 --- a/examples/quota_watermark/qwctl/commands.c +++ b/examples/quota_watermark/qwctl/commands.c @@ -36,7 +36,6 @@ #include <string.h> #include <termios.h> -#include <cmdline_rdline.h> #include <cmdline_parse.h> #include <cmdline_parse_num.h> #include <cmdline_parse_string.h> diff --git a/examples/quota_watermark/qwctl/qwctl.c b/examples/quota_watermark/qwctl/qwctl.c index 18ec17a..2831667 100644 --- a/examples/quota_watermark/qwctl/qwctl.c +++ b/examples/quota_watermark/qwctl/qwctl.c @@ -42,7 +42,6 @@ #include <rte_log.h> #include <rte_memzone.h> -#include <cmdline_rdline.h> #include <cmdline_parse.h> #include <cmdline_socket.h> #include <cmdline.h> diff --git a/examples/vm_power_manager/guest_cli/vm_power_cli_guest.c b/examples/vm_power_manager/guest_cli/vm_power_cli_guest.c index 63f711e..83cd215 100644 --- a/examples/vm_power_manager/guest_cli/vm_power_cli_guest.c +++ b/examples/vm_power_manager/guest_cli/vm_power_cli_guest.c @@ -37,7 +37,6 @@ #include <stdio.h> #include <termios.h> -#include <cmdline_rdline.h> #include <cmdline_parse.h> #include <cmdline_parse_string.h> #include <cmdline_parse_num.h> diff --git a/examples/vm_power_manager/vm_power_cli.c b/examples/vm_power_manager/vm_power_cli.c index 6f234fb..d013715 100644 --- a/examples/vm_power_manager/vm_power_cli.c +++ b/examples/vm_power_manager/vm_power_cli.c @@ -39,7 +39,6 @@ #include <termios.h> #include <errno.h> -#include <cmdline_rdline.h> #include <cmdline_parse.h> #include <cmdline_parse_string.h> #include <cmdline_parse_num.h> diff --git a/lib/librte_cmdline/Makefile b/lib/librte_cmdline/Makefile index 2c48e62..35c8972 100644 --- a/lib/librte_cmdline/Makefile +++ b/lib/librte_cmdline/Makefile @@ -38,28 +38,24 @@ CFLAGS += $(WERROR_FLAGS) -I$(SRCDIR) -O3 EXPORT_MAP := rte_cmdline_version.map -LIBABIVER := 2 +LIBABIVER := 3 # all source are stored in SRCS-y SRCS-$(CONFIG_RTE_LIBRTE_CMDLINE) := cmdline.c -SRCS-$(CONFIG_RTE_LIBRTE_CMDLINE) += cmdline_cirbuf.c SRCS-$(CONFIG_RTE_LIBRTE_CMDLINE) += cmdline_parse.c SRCS-$(CONFIG_RTE_LIBRTE_CMDLINE) += cmdline_parse_etheraddr.c SRCS-$(CONFIG_RTE_LIBRTE_CMDLINE) += cmdline_parse_ipaddr.c SRCS-$(CONFIG_RTE_LIBRTE_CMDLINE) += cmdline_parse_num.c SRCS-$(CONFIG_RTE_LIBRTE_CMDLINE) += cmdline_parse_string.c -SRCS-$(CONFIG_RTE_LIBRTE_CMDLINE) += cmdline_rdline.c -SRCS-$(CONFIG_RTE_LIBRTE_CMDLINE) += cmdline_vt100.c SRCS-$(CONFIG_RTE_LIBRTE_CMDLINE) += cmdline_socket.c SRCS-$(CONFIG_RTE_LIBRTE_CMDLINE) += cmdline_parse_portlist.c -CFLAGS += -D_GNU_SOURCE LDLIBS += -lrte_eal # install includes INCS := cmdline.h cmdline_parse.h cmdline_parse_num.h cmdline_parse_ipaddr.h -INCS += cmdline_parse_etheraddr.h cmdline_parse_string.h cmdline_rdline.h -INCS += cmdline_vt100.h cmdline_socket.h cmdline_cirbuf.h cmdline_parse_portlist.h +INCS += cmdline_parse_etheraddr.h cmdline_parse_string.h +INCS += cmdline_socket.h cmdline_parse_portlist.h SYMLINK-$(CONFIG_RTE_LIBRTE_CMDLINE)-include := $(INCS) include $(RTE_SDK)/mk/rte.lib.mk diff --git a/lib/librte_cmdline/cmdline.c b/lib/librte_cmdline/cmdline.c index d749165..1c19546 100644 --- a/lib/librte_cmdline/cmdline.c +++ b/lib/librte_cmdline/cmdline.c @@ -58,79 +58,181 @@ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ +#include <ctype.h> +#include <histedit.h> +#include <stdint.h> #include <stdio.h> #include <string.h> #include <unistd.h> #include <stdlib.h> #include <stdarg.h> -#include <inttypes.h> #include <fcntl.h> #include <poll.h> #include <errno.h> -#include <termios.h> -#include <netinet/in.h> - -#include <rte_string_fns.h> #include "cmdline_parse.h" -#include "cmdline_rdline.h" #include "cmdline.h" -static void -cmdline_valid_buffer(struct rdline *rdl, const char *buf, - __attribute__((unused)) unsigned int size) +struct cmdline { + char *line; + FILE *f_in; + FILE *f_out; + cmdline_parse_ctx_t *ctx; + EditLine *el; + History *hist; + HistEvent histev; + uint32_t eof:1; + uint32_t error:1; + char prompt[RDLINE_PROMPT_SIZE]; +}; + +void +cmdline_set_prompt(struct cmdline *cl, const char *prompt) { - struct cmdline *cl = rdl->opaque; - int ret; - ret = cmdline_parse(cl, buf); - if (ret == CMDLINE_PARSE_AMBIGUOUS) - cmdline_printf(cl, "Ambiguous command\n"); - else if (ret == CMDLINE_PARSE_NOMATCH) - cmdline_printf(cl, "Command not found\n"); - else if (ret == CMDLINE_PARSE_BAD_ARGS) - cmdline_printf(cl, "Bad arguments\n"); + if (!cl || !prompt) + return; + snprintf(cl->prompt, sizeof(cl->prompt), "%s", prompt); } -static int -cmdline_complete_buffer(struct rdline *rdl, const char *buf, - char *dstbuf, unsigned int dstsize, - int *state) +void * +cmdline_ctx_get(struct cmdline *cl) { - struct cmdline *cl = rdl->opaque; - return cmdline_complete(cl, buf, state, dstbuf, dstsize); + if (!cl) + return NULL; + return cl->ctx; } -int -cmdline_write_char(struct rdline *rdl, char c) +static char * +cmdline_el_prompt(EditLine *el) { - int ret = -1; struct cmdline *cl; - if (!rdl) - return -1; - - cl = rdl->opaque; + if (el_get(el, EL_CLIENTDATA, &cl)) + return NULL; + return cl->prompt; +} - if (cl->s_out >= 0) - ret = write(cl->s_out, &c, 1); +static unsigned char +cmdline_el_execute(EditLine *el, int c) +{ + const LineInfo *li = el_line(el); + size_t len = li->lastchar - li->buffer; + char *line; + struct cmdline *cl; + int ret; - return ret; + (void)c; + if (el_get(el, EL_CLIENTDATA, &cl)) + return CC_FATAL; + line = realloc(cl->line, len + 2); + if (!line) { + cl->error = 1; + return CC_FATAL; + } + cl->line = line; + memcpy(line, li->buffer, len); + line[len] = '\n'; + line[len + 1] = '\0'; + fputs("\r\n", cl->f_out); + ret = cmdline_parse(cl, line); + if (ret == CMDLINE_PARSE_AMBIGUOUS) + fprintf(cl->f_out, "Ambiguous command\r\n"); + else if (ret == CMDLINE_PARSE_NOMATCH) + fprintf(cl->f_out, "Command not found\r\n"); + else if (ret == CMDLINE_PARSE_BAD_ARGS) + fprintf(cl->f_out, "Bad arguments\r\n"); + if (cl->error) + return CC_FATAL; + if (cl->eof) + return CC_EOF; + if (len) { + line[len] = '\0'; + history(cl->hist, &cl->histev, H_ENTER, line); + } + return CC_NEWLINE; } +static unsigned char +cmdline_el_complete(EditLine *el, int c) +{ + const LineInfo *li = el_line(el); + size_t pos = li->cursor - li->buffer; + char *line; + struct cmdline *cl; + char complete_buf[RDLINE_COMPLETE_SIZE]; + int complete_state; + int ret; -void -cmdline_set_prompt(struct cmdline *cl, const char *prompt) + if (el_get(el, EL_CLIENTDATA, &cl)) + return CC_FATAL; + line = realloc(cl->line, pos + 1); + if (!line) { + cl->error = 1; + return CC_FATAL; + } + cl->line = line; + memcpy(line, li->buffer, pos); + line[pos] = '\0'; + if (c == '\t') + complete_state = 0; + else + complete_state = -1; + /* see in parse.h for help on complete() */ + ret = cmdline_complete(cl, line, &complete_state, + complete_buf, sizeof(complete_buf)); + /* no completion or error */ + if (ret <= 0) + return CC_ARGHACK; + /* string must be NUL-terminated */ + if (strnlen(complete_buf, sizeof(complete_buf)) == sizeof(complete_buf)) + return CC_ERROR; + /* add chars */ + if (ret == CMDLINE_PARSE_COMPLETED_BUFFER) { + /* if in the middle of a token, remove its suffix first */ + for (pos = 0; li->cursor + pos != li->lastchar; pos++) + if (isblank(li->cursor[pos])) + break; + el_cursor(el, pos); + el_deletestr(el, pos); + if (el_insertstr(el, complete_buf)) + return CC_ERROR; + return CC_REFRESH; + } + /* choice */ + fputs("\r\n", cl->f_out); + while (ret) { + fputc(' ', cl->f_out); + fputs(complete_buf, cl->f_out); + fputs("\r\n", cl->f_out); + ret = cmdline_complete(cl, line, &complete_state, + complete_buf, sizeof(complete_buf)); + } + el_set(el, EL_REFRESH); + return CC_REDISPLAY; +} + +static unsigned char +cmdline_el_delete_next_char_or_eof(EditLine *el, int c) { - if (!cl || !prompt) - return; - snprintf(cl->prompt, sizeof(cl->prompt), "%s", prompt); + const LineInfo *li = el_line(el); + struct cmdline *cl; + + (void)c; + if (el_get(el, EL_CLIENTDATA, &cl)) + return CC_FATAL; + if (li->buffer == li->lastchar) { + cl->eof = 1; + return CC_EOF; + } + el_cursor(el, 1); + el_deletestr(el, 1); + return CC_REFRESH; } struct cmdline * cmdline_new(cmdline_parse_ctx_t *ctx, const char *prompt, int s_in, int s_out) { struct cmdline *cl; - int ret; if (!ctx || !prompt) return NULL; @@ -139,36 +241,89 @@ cmdline_new(cmdline_parse_ctx_t *ctx, const char *prompt, int s_in, int s_out) if (cl == NULL) return NULL; memset(cl, 0, sizeof(struct cmdline)); - cl->s_in = s_in; - cl->s_out = s_out; + cl->line = NULL; + s_in = dup(s_in); + s_out = s_out != -1 ? dup(s_out) : open("/dev/null", O_WRONLY); + if (s_in == -1 || s_out == -1) + goto error; + cl->f_in = fdopen(s_in, "rb"); + cl->f_out = fdopen(s_out, "wb"); + if (!cl->f_in || !cl->f_out) + goto error; cl->ctx = ctx; - - ret = rdline_init(&cl->rdl, cmdline_write_char, cmdline_valid_buffer, - cmdline_complete_buffer); - if (ret != 0) { - free(cl); - return NULL; - } - - cl->rdl.opaque = cl; + cl->el = el_init("dpdk", cl->f_in, cl->f_out, stderr); + if (!cl->el) + goto error; + if (el_set(cl->el, EL_CLIENTDATA, cl)) + goto error; cmdline_set_prompt(cl, prompt); - rdline_newline(&cl->rdl, cl->prompt); - + if (el_set(cl->el, EL_PROMPT, cmdline_el_prompt)) + goto error; + if (el_set(cl->el, EL_EDITOR, "emacs")) + goto error; + if (el_set(cl->el, EL_SIGNAL, 1)) + goto error; + cl->hist = history_init(); + if (!cl->hist) + goto error; + if (history(cl->hist, &cl->histev, H_SETSIZE, + RDLINE_HISTORY_MAX_LINE) < 0) + goto error; + if (history(cl->hist, &cl->histev, H_SETUNIQUE, 1)) + goto error; + if (el_set(cl->el, EL_HIST, history, cl->hist)) + goto error; + if (el_set(cl->el, EL_ADDFN, "ed-execute", "Execute command", + cmdline_el_execute)) + goto error; + if (el_set(cl->el, EL_BIND, "^J", "ed-execute", NULL)) + goto error; + if (el_set(cl->el, EL_BIND, "^M", "ed-execute", NULL)) + goto error; + if (el_set(cl->el, EL_ADDFN, "ed-complete", "Complete argument", + cmdline_el_complete)) + goto error; + if (el_set(cl->el, EL_BIND, "^I", "ed-complete", NULL)) + goto error; + if (el_set(cl->el, EL_BIND, "?", "ed-complete", NULL)) + goto error; + if (el_set(cl->el, EL_ADDFN, "ed-delete-next-char-or-eof", + "Delete next character or assume EOF", + cmdline_el_delete_next_char_or_eof)) + goto error; + if (el_set(cl->el, EL_BIND, "^D", + "ed-delete-next-char-or-eof", NULL)) + goto error; + if (el_set(cl->el, EL_BIND, "^W", "ed-delete-prev-word", NULL)) + goto error; return cl; +error: + if (cl->hist) + history_end(cl->hist); + if (cl->el) + el_end(cl->el); + if (cl->f_out) + fclose(cl->f_out); + else if (s_out != -1) + close(s_out); + if (cl->f_in) + fclose(cl->f_in); + else if (s_in != -1) + close(s_in); + free(cl); + return NULL; } void cmdline_free(struct cmdline *cl) { - dprintf("called\n"); - if (!cl) return; - - if (cl->s_in > 2) - close(cl->s_in); - if (cl->s_out != cl->s_in && cl->s_out > 2) - close(cl->s_out); + history_end(cl->hist); + el_end(cl->el); + fclose(cl->f_out); + fclose(cl->f_in); + free(cl->line); free(cl); } @@ -180,70 +335,23 @@ cmdline_printf(const struct cmdline *cl, const char *fmt, ...) if (!cl || !fmt) return; -#ifdef _GNU_SOURCE - if (cl->s_out < 0) - return; - va_start(ap, fmt); - vdprintf(cl->s_out, fmt, ap); - va_end(ap); -#else - int ret; - char *buf; - - if (cl->s_out < 0) - return; - - buf = malloc(BUFSIZ); - if (buf == NULL) - return; va_start(ap, fmt); - ret = vsnprintf(buf, BUFSIZ, fmt, ap); + vfprintf(cl->f_out, fmt, ap); va_end(ap); - if (ret < 0) { - free(buf); - return; - } - if (ret >= BUFSIZ) - ret = BUFSIZ - 1; - ret = write(cl->s_out, buf, ret); - (void)ret; - free(buf); -#endif } int cmdline_in(struct cmdline *cl, const char *buf, int size) { - const char *history, *buffer; - size_t histlen, buflen; - int ret = 0; - int i, same; + int i; if (!cl || !buf) return -1; for (i=0; i<size; i++) { - ret = rdline_char_in(&cl->rdl, buf[i]); - - if (ret == RDLINE_RES_VALIDATED) { - buffer = rdline_get_buffer(&cl->rdl); - history = rdline_get_history_item(&cl->rdl, 0); - if (history) { - histlen = strnlen(history, RDLINE_BUF_SIZE); - same = !memcmp(buffer, history, histlen) && - buffer[histlen] == '\n'; - } - else - same = 0; - buflen = strnlen(buffer, RDLINE_BUF_SIZE); - if (buflen > 1 && !same) - rdline_add_history(&cl->rdl, buffer); - rdline_newline(&cl->rdl, cl->prompt); - } - else if (ret == RDLINE_RES_EOF) - return -1; - else if (ret == RDLINE_RES_EXITED) - return -1; + char tmp[2] = { buf[i], '\0' }; + + el_push(cl->el, tmp); } return i; } @@ -253,7 +361,7 @@ cmdline_quit(struct cmdline *cl) { if (!cl) return; - rdline_quit(&cl->rdl); + cl->eof = 1; } int @@ -261,48 +369,49 @@ cmdline_poll(struct cmdline *cl) { struct pollfd pfd; int status; - ssize_t read_status; - char c; + int read_status; + int flags; if (!cl) return -EINVAL; - else if (cl->rdl.status == RDLINE_EXITED) + else if (cl->error) + return RDLINE_ERROR; + else if (cl->eof) return RDLINE_EXITED; - pfd.fd = cl->s_in; + pfd.fd = fileno(cl->f_in); pfd.events = POLLIN; pfd.revents = 0; status = poll(&pfd, 1, 0); if (status < 0) - return status; - else if (status > 0) { - c = -1; - read_status = read(cl->s_in, &c, 1); - if (read_status < 0) - return read_status; - - status = cmdline_in(cl, &c, 1); - if (status < 0 && cl->rdl.status != RDLINE_EXITED) - return status; - } - - return cl->rdl.status; + return RDLINE_ERROR; + if (!status) + return RDLINE_RUNNING; + flags = fcntl(pfd.fd, F_GETFL); + if (!(flags & O_NONBLOCK)) + fcntl(pfd.fd, F_SETFL, flags | O_NONBLOCK); + if (!el_gets(cl->el, &read_status) && read_status == -1) + cl->error = 1; + if (!(flags & O_NONBLOCK)) + fcntl(pfd.fd, F_SETFL, flags); + return cl->error ? RDLINE_ERROR : + cl->eof ? RDLINE_EXITED : + RDLINE_RUNNING; } void cmdline_interact(struct cmdline *cl) { - char c; - if (!cl) return; - c = -1; - while (1) { - if (read(cl->s_in, &c, 1) <= 0) - break; - if (cmdline_in(cl, &c, 1) < 0) - break; + while (!cl->error && !cl->eof) { + int read_status; + + if (el_gets(cl->el, &read_status)) + continue; + if (read_status == -1) + cl->error = 1; } } diff --git a/lib/librte_cmdline/cmdline.h b/lib/librte_cmdline/cmdline.h index 65d73b0..4507268 100644 --- a/lib/librte_cmdline/cmdline.h +++ b/lib/librte_cmdline/cmdline.h @@ -61,8 +61,6 @@ #ifndef _CMDLINE_H_ #define _CMDLINE_H_ -#include <termios.h> -#include <cmdline_rdline.h> #include <cmdline_parse.h> /** @@ -75,22 +73,26 @@ extern "C" { #endif -struct cmdline { - int s_in; - int s_out; - cmdline_parse_ctx_t *ctx; - struct rdline rdl; - char prompt[RDLINE_PROMPT_SIZE]; - struct termios oldterm; +#define RDLINE_PROMPT_SIZE 32 +#define RDLINE_HISTORY_MAX_LINE 64 +#define RDLINE_COMPLETE_SIZE 128 + +enum rdline_status { + RDLINE_ERROR = -1, + RDLINE_INIT, + RDLINE_RUNNING, + RDLINE_EXITED, }; +struct cmdline; + +void *cmdline_ctx_get(struct cmdline *cl); struct cmdline *cmdline_new(cmdline_parse_ctx_t *ctx, const char *prompt, int s_in, int s_out); void cmdline_set_prompt(struct cmdline *cl, const char *prompt); void cmdline_free(struct cmdline *cl); void cmdline_printf(const struct cmdline *cl, const char *fmt, ...) __attribute__((format(printf,2,3))); int cmdline_in(struct cmdline *cl, const char *buf, int size); -int cmdline_write_char(struct rdline *rdl, char c); /** * This function is nonblocking equivalent of ``cmdline_interact()``. It polls diff --git a/lib/librte_cmdline/cmdline_cirbuf.c b/lib/librte_cmdline/cmdline_cirbuf.c deleted file mode 100644 index f506f88..0000000 --- a/lib/librte_cmdline/cmdline_cirbuf.c +++ /dev/null @@ -1,466 +0,0 @@ -/*- - * BSD LICENSE - * - * Copyright(c) 2010-2014 Intel Corporation. All rights reserved. - * 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 <zer0@droids-corp.org> - * 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 the University of California, Berkeley 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 REGENTS 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 REGENTS AND 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. - */ - -#include <string.h> -#include <errno.h> -#include <stdio.h> - -#include "cmdline_cirbuf.h" - - -int -cirbuf_init(struct cirbuf *cbuf, char *buf, unsigned int start, unsigned int maxlen) -{ - if (!cbuf || !buf) - return -EINVAL; - cbuf->maxlen = maxlen; - cbuf->len = 0; - cbuf->start = start; - cbuf->end = start; - cbuf->buf = buf; - return 0; -} - -/* multiple add */ - -int -cirbuf_add_buf_head(struct cirbuf *cbuf, const char *c, unsigned int n) -{ - unsigned int e; - - if (!cbuf || !c || !n || n > CIRBUF_GET_FREELEN(cbuf)) - return -EINVAL; - - e = CIRBUF_IS_EMPTY(cbuf) ? 1 : 0; - - if (n < cbuf->start + e) { - dprintf("s[%d] -> d[%d] (%d)\n", 0, cbuf->start - n + e, n); - memcpy(cbuf->buf + cbuf->start - n + e, c, n); - } - else { - dprintf("s[%d] -> d[%d] (%d)\n", + n - (cbuf->start + e), 0, - cbuf->start + e); - dprintf("s[%d] -> d[%d] (%d)\n", cbuf->maxlen - n + - (cbuf->start + e), 0, n - (cbuf->start + e)); - memcpy(cbuf->buf, c + n - (cbuf->start + e) , cbuf->start + e); - memcpy(cbuf->buf + cbuf->maxlen - n + (cbuf->start + e), c, - n - (cbuf->start + e)); - } - cbuf->len += n; - cbuf->start += (cbuf->maxlen - n + e); - cbuf->start %= cbuf->maxlen; - return n; -} - -/* multiple add */ - -int -cirbuf_add_buf_tail(struct cirbuf *cbuf, const char *c, unsigned int n) -{ - unsigned int e; - - if (!cbuf || !c || !n || n > CIRBUF_GET_FREELEN(cbuf)) - return -EINVAL; - - e = CIRBUF_IS_EMPTY(cbuf) ? 1 : 0; - - if (n < cbuf->maxlen - cbuf->end - 1 + e) { - dprintf("s[%d] -> d[%d] (%d)\n", 0, cbuf->end + !e, n); - memcpy(cbuf->buf + cbuf->end + !e, c, n); - } - else { - dprintf("s[%d] -> d[%d] (%d)\n", cbuf->end + !e, 0, - cbuf->maxlen - cbuf->end - 1 + e); - dprintf("s[%d] -> d[%d] (%d)\n", cbuf->maxlen - cbuf->end - 1 + - e, 0, n - cbuf->maxlen + cbuf->end + 1 - e); - memcpy(cbuf->buf + cbuf->end + !e, c, cbuf->maxlen - - cbuf->end - 1 + e); - memcpy(cbuf->buf, c + cbuf->maxlen - cbuf->end - 1 + e, - n - cbuf->maxlen + cbuf->end + 1 - e); - } - cbuf->len += n; - cbuf->end += n - e; - cbuf->end %= cbuf->maxlen; - return n; -} - -/* add at head */ - -static inline void -__cirbuf_add_head(struct cirbuf * cbuf, char c) -{ - if (!CIRBUF_IS_EMPTY(cbuf)) { - cbuf->start += (cbuf->maxlen - 1); - cbuf->start %= cbuf->maxlen; - } - cbuf->buf[cbuf->start] = c; - cbuf->len ++; -} - -int -cirbuf_add_head_safe(struct cirbuf * cbuf, char c) -{ - if (cbuf && !CIRBUF_IS_FULL(cbuf)) { - __cirbuf_add_head(cbuf, c); - return 0; - } - return -EINVAL; -} - -void -cirbuf_add_head(struct cirbuf * cbuf, char c) -{ - __cirbuf_add_head(cbuf, c); -} - -/* add at tail */ - -static inline void -__cirbuf_add_tail(struct cirbuf * cbuf, char c) -{ - if (!CIRBUF_IS_EMPTY(cbuf)) { - cbuf->end ++; - cbuf->end %= cbuf->maxlen; - } - cbuf->buf[cbuf->end] = c; - cbuf->len ++; -} - -int -cirbuf_add_tail_safe(struct cirbuf * cbuf, char c) -{ - if (cbuf && !CIRBUF_IS_FULL(cbuf)) { - __cirbuf_add_tail(cbuf, c); - return 0; - } - return -EINVAL; -} - -void -cirbuf_add_tail(struct cirbuf * cbuf, char c) -{ - __cirbuf_add_tail(cbuf, c); -} - - -static inline void -__cirbuf_shift_left(struct cirbuf *cbuf) -{ - unsigned int i; - char tmp = cbuf->buf[cbuf->start]; - - for (i=0 ; i<cbuf->len ; i++) { - cbuf->buf[(cbuf->start+i)%cbuf->maxlen] = - cbuf->buf[(cbuf->start+i+1)%cbuf->maxlen]; - } - cbuf->buf[(cbuf->start-1+cbuf->maxlen)%cbuf->maxlen] = tmp; - cbuf->start += (cbuf->maxlen - 1); - cbuf->start %= cbuf->maxlen; - cbuf->end += (cbuf->maxlen - 1); - cbuf->end %= cbuf->maxlen; -} - -static inline void -__cirbuf_shift_right(struct cirbuf *cbuf) -{ - unsigned int i; - char tmp = cbuf->buf[cbuf->end]; - - for (i=0 ; i<cbuf->len ; i++) { - cbuf->buf[(cbuf->end+cbuf->maxlen-i)%cbuf->maxlen] = - cbuf->buf[(cbuf->end+cbuf->maxlen-i-1)%cbuf->maxlen]; - } - cbuf->buf[(cbuf->end+1)%cbuf->maxlen] = tmp; - cbuf->start += 1; - cbuf->start %= cbuf->maxlen; - cbuf->end += 1; - cbuf->end %= cbuf->maxlen; -} - -/* XXX we could do a better algorithm here... */ -int -cirbuf_align_left(struct cirbuf * cbuf) -{ - if (!cbuf) - return -EINVAL; - - if (cbuf->start < cbuf->maxlen/2) { - while (cbuf->start != 0) { - __cirbuf_shift_left(cbuf); - } - } - else { - while (cbuf->start != 0) { - __cirbuf_shift_right(cbuf); - } - } - - return 0; -} - -/* XXX we could do a better algorithm here... */ -int -cirbuf_align_right(struct cirbuf * cbuf) -{ - if (!cbuf) - return -EINVAL; - - if (cbuf->start >= cbuf->maxlen/2) { - while (cbuf->end != cbuf->maxlen-1) { - __cirbuf_shift_left(cbuf); - } - } - else { - while (cbuf->start != cbuf->maxlen-1) { - __cirbuf_shift_right(cbuf); - } - } - - return 0; -} - -/* buffer del */ - -int -cirbuf_del_buf_head(struct cirbuf *cbuf, unsigned int size) -{ - if (!cbuf || !size || size > CIRBUF_GET_LEN(cbuf)) - return -EINVAL; - - cbuf->len -= size; - if (CIRBUF_IS_EMPTY(cbuf)) { - cbuf->start += size - 1; - cbuf->start %= cbuf->maxlen; - } - else { - cbuf->start += size; - cbuf->start %= cbuf->maxlen; - } - return 0; -} - -/* buffer del */ - -int -cirbuf_del_buf_tail(struct cirbuf *cbuf, unsigned int size) -{ - if (!cbuf || !size || size > CIRBUF_GET_LEN(cbuf)) - return -EINVAL; - - cbuf->len -= size; - if (CIRBUF_IS_EMPTY(cbuf)) { - cbuf->end += (cbuf->maxlen - size + 1); - cbuf->end %= cbuf->maxlen; - } - else { - cbuf->end += (cbuf->maxlen - size); - cbuf->end %= cbuf->maxlen; - } - return 0; -} - -/* del at head */ - -static inline void -__cirbuf_del_head(struct cirbuf * cbuf) -{ - cbuf->len --; - if (!CIRBUF_IS_EMPTY(cbuf)) { - cbuf->start ++; - cbuf->start %= cbuf->maxlen; - } -} - -int -cirbuf_del_head_safe(struct cirbuf * cbuf) -{ - if (cbuf && !CIRBUF_IS_EMPTY(cbuf)) { - __cirbuf_del_head(cbuf); - return 0; - } - return -EINVAL; -} - -void -cirbuf_del_head(struct cirbuf * cbuf) -{ - __cirbuf_del_head(cbuf); -} - -/* del at tail */ - -static inline void -__cirbuf_del_tail(struct cirbuf * cbuf) -{ - cbuf->len --; - if (!CIRBUF_IS_EMPTY(cbuf)) { - cbuf->end += (cbuf->maxlen - 1); - cbuf->end %= cbuf->maxlen; - } -} - -int -cirbuf_del_tail_safe(struct cirbuf * cbuf) -{ - if (cbuf && !CIRBUF_IS_EMPTY(cbuf)) { - __cirbuf_del_tail(cbuf); - return 0; - } - return -EINVAL; -} - -void -cirbuf_del_tail(struct cirbuf * cbuf) -{ - __cirbuf_del_tail(cbuf); -} - -/* convert to buffer */ - -int -cirbuf_get_buf_head(struct cirbuf *cbuf, char *c, unsigned int size) -{ - unsigned int n; - - if (!cbuf || !c) - return -EINVAL; - - n = (size < CIRBUF_GET_LEN(cbuf)) ? size : CIRBUF_GET_LEN(cbuf); - - if (!n) - return 0; - - if (cbuf->start <= cbuf->end) { - dprintf("s[%d] -> d[%d] (%d)\n", cbuf->start, 0, n); - memcpy(c, cbuf->buf + cbuf->start , n); - } - else { - /* check if we need to go from end to the beginning */ - if (n <= cbuf->maxlen - cbuf->start) { - dprintf("s[%d] -> d[%d] (%d)\n", 0, cbuf->start, n); - memcpy(c, cbuf->buf + cbuf->start , n); - } - else { - dprintf("s[%d] -> d[%d] (%d)\n", cbuf->start, 0, - cbuf->maxlen - cbuf->start); - dprintf("s[%d] -> d[%d] (%d)\n", 0, cbuf->maxlen - cbuf->start, - n - cbuf->maxlen + cbuf->start); - memcpy(c, cbuf->buf + cbuf->start , cbuf->maxlen - cbuf->start); - memcpy(c + cbuf->maxlen - cbuf->start, cbuf->buf, - n - cbuf->maxlen + cbuf->start); - } - } - return n; -} - -/* convert to buffer */ - -int -cirbuf_get_buf_tail(struct cirbuf *cbuf, char *c, unsigned int size) -{ - unsigned int n; - - if (!cbuf || !c) - return -EINVAL; - - n = (size < CIRBUF_GET_LEN(cbuf)) ? size : CIRBUF_GET_LEN(cbuf); - - if (!n) - return 0; - - if (cbuf->start <= cbuf->end) { - dprintf("s[%d] -> d[%d] (%d)\n", cbuf->end - n + 1, 0, n); - memcpy(c, cbuf->buf + cbuf->end - n + 1, n); - } - else { - /* check if we need to go from end to the beginning */ - if (n <= cbuf->end + 1) { - dprintf("s[%d] -> d[%d] (%d)\n", 0, cbuf->end - n + 1, n); - memcpy(c, cbuf->buf + cbuf->end - n + 1, n); - } - else { - dprintf("s[%d] -> d[%d] (%d)\n", 0, - cbuf->maxlen - cbuf->start, cbuf->end + 1); - dprintf("s[%d] -> d[%d] (%d)\n", - cbuf->maxlen - n + cbuf->end + 1, 0, n - cbuf->end - 1); - memcpy(c + cbuf->maxlen - cbuf->start, - cbuf->buf, cbuf->end + 1); - memcpy(c, cbuf->buf + cbuf->maxlen - n + cbuf->end +1, - n - cbuf->end - 1); - } - } - return n; -} - -/* get head or get tail */ - -char -cirbuf_get_head(struct cirbuf * cbuf) -{ - return cbuf->buf[cbuf->start]; -} - -/* get head or get tail */ - -char -cirbuf_get_tail(struct cirbuf * cbuf) -{ - return cbuf->buf[cbuf->end]; -} diff --git a/lib/librte_cmdline/cmdline_cirbuf.h b/lib/librte_cmdline/cmdline_cirbuf.h deleted file mode 100644 index 6321dec..0000000 --- a/lib/librte_cmdline/cmdline_cirbuf.h +++ /dev/null @@ -1,245 +0,0 @@ -/*- - * BSD LICENSE - * - * Copyright(c) 2010-2014 Intel Corporation. All rights reserved. - * 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 <zer0@droids-corp.org> - * 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 the University of California, Berkeley 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 REGENTS 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 REGENTS AND 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. - */ - -#ifndef _CIRBUF_H_ -#define _CIRBUF_H_ - -#ifdef __cplusplus -extern "C" { -#endif - -/** - * This structure is the header of a cirbuf type. - */ -struct cirbuf { - unsigned int maxlen; /**< total len of the fifo (number of elements) */ - unsigned int start; /**< indice of the first elt */ - unsigned int end; /**< indice of the last elt */ - unsigned int len; /**< current len of fifo */ - char *buf; -}; - -#ifdef RTE_LIBRTE_CMDLINE_DEBUG -#define dprintf_(fmt, ...) printf("line %3.3d - " fmt "%.0s", __LINE__, __VA_ARGS__) -#define dprintf(...) dprintf_(__VA_ARGS__, "dummy") -#else -#define dprintf(...) (void)0 -#endif - - -/** - * Init the circular buffer - */ -int cirbuf_init(struct cirbuf *cbuf, char *buf, unsigned int start, unsigned int maxlen); - - -/** - * Return 1 if the circular buffer is full - */ -#define CIRBUF_IS_FULL(cirbuf) ((cirbuf)->maxlen == (cirbuf)->len) - -/** - * Return 1 if the circular buffer is empty - */ -#define CIRBUF_IS_EMPTY(cirbuf) ((cirbuf)->len == 0) - -/** - * return current size of the circular buffer (number of used elements) - */ -#define CIRBUF_GET_LEN(cirbuf) ((cirbuf)->len) - -/** - * return size of the circular buffer (used + free elements) - */ -#define CIRBUF_GET_MAXLEN(cirbuf) ((cirbuf)->maxlen) - -/** - * return the number of free elts - */ -#define CIRBUF_GET_FREELEN(cirbuf) ((cirbuf)->maxlen - (cirbuf)->len) - -/** - * Iterator for a circular buffer - * c: struct cirbuf pointer - * i: an integer type internally used in the macro - * e: char that takes the value for each iteration - */ -#define CIRBUF_FOREACH(c, i, e) \ - for ( i=0, e=(c)->buf[(c)->start] ; \ - i<((c)->len) ; \ - i ++, e=(c)->buf[((c)->start+i)%((c)->maxlen)]) - - -/** - * Add a character at head of the circular buffer. Return 0 on success, or - * a negative value on error. - */ -int cirbuf_add_head_safe(struct cirbuf *cbuf, char c); - -/** - * Add a character at head of the circular buffer. You _must_ check that you - * have enough free space in the buffer before calling this func. - */ -void cirbuf_add_head(struct cirbuf *cbuf, char c); - -/** - * Add a character at tail of the circular buffer. Return 0 on success, or - * a negative value on error. - */ -int cirbuf_add_tail_safe(struct cirbuf *cbuf, char c); - -/** - * Add a character at tail of the circular buffer. You _must_ check that you - * have enough free space in the buffer before calling this func. - */ -void cirbuf_add_tail(struct cirbuf *cbuf, char c); - -/** - * Remove a char at the head of the circular buffer. Return 0 on - * success, or a negative value on error. - */ -int cirbuf_del_head_safe(struct cirbuf *cbuf); - -/** - * Remove a char at the head of the circular buffer. You _must_ check - * that buffer is not empty before calling the function. - */ -void cirbuf_del_head(struct cirbuf *cbuf); - -/** - * Remove a char at the tail of the circular buffer. Return 0 on - * success, or a negative value on error. - */ -int cirbuf_del_tail_safe(struct cirbuf *cbuf); - -/** - * Remove a char at the tail of the circular buffer. You _must_ check - * that buffer is not empty before calling the function. - */ -void cirbuf_del_tail(struct cirbuf *cbuf); - -/** - * Return the head of the circular buffer. You _must_ check that - * buffer is not empty before calling the function. - */ -char cirbuf_get_head(struct cirbuf *cbuf); - -/** - * Return the tail of the circular buffer. You _must_ check that - * buffer is not empty before calling the function. - */ -char cirbuf_get_tail(struct cirbuf *cbuf); - -/** - * Add a buffer at head of the circular buffer. 'c' is a pointer to a - * buffer, and n is the number of char to add. Return the number of - * copied bytes on success, or a negative value on error. - */ -int cirbuf_add_buf_head(struct cirbuf *cbuf, const char *c, unsigned int n); - -/** - * Add a buffer at tail of the circular buffer. 'c' is a pointer to a - * buffer, and n is the number of char to add. Return the number of - * copied bytes on success, or a negative value on error. - */ -int cirbuf_add_buf_tail(struct cirbuf *cbuf, const char *c, unsigned int n); - -/** - * Remove chars at the head of the circular buffer. Return 0 on - * success, or a negative value on error. - */ -int cirbuf_del_buf_head(struct cirbuf *cbuf, unsigned int size); - -/** - * Remove chars at the tail of the circular buffer. Return 0 on - * success, or a negative value on error. - */ -int cirbuf_del_buf_tail(struct cirbuf *cbuf, unsigned int size); - -/** - * Copy a maximum of 'size' characters from the head of the circular - * buffer to a flat one pointed by 'c'. Return the number of copied - * chars. - */ -int cirbuf_get_buf_head(struct cirbuf *cbuf, char *c, unsigned int size); - -/** - * Copy a maximum of 'size' characters from the tail of the circular - * buffer to a flat one pointed by 'c'. Return the number of copied - * chars. - */ -int cirbuf_get_buf_tail(struct cirbuf *cbuf, char *c, unsigned int size); - - -/** - * Set the start of the data to the index 0 of the internal buffer. - */ -int cirbuf_align_left(struct cirbuf *cbuf); - -/** - * Set the end of the data to the last index of the internal buffer. - */ -int cirbuf_align_right(struct cirbuf *cbuf); - -#ifdef __cplusplus -} -#endif - -#endif /* _CIRBUF_H_ */ diff --git a/lib/librte_cmdline/cmdline_parse.c b/lib/librte_cmdline/cmdline_parse.c index 3e12ee5..0cc0b57 100644 --- a/lib/librte_cmdline/cmdline_parse.c +++ b/lib/librte_cmdline/cmdline_parse.c @@ -70,7 +70,6 @@ #include <rte_string_fns.h> -#include "cmdline_rdline.h" #include "cmdline_parse.h" #include "cmdline.h" @@ -267,7 +266,7 @@ cmdline_parse(struct cmdline *cl, const char * buf) if (!cl || !buf) return CMDLINE_PARSE_BAD_ARGS; - ctx = cl->ctx; + ctx = cmdline_ctx_get(cl); /* * - look if the buffer contains at least one line @@ -386,7 +385,7 @@ cmdline_complete(struct cmdline *cl, const char *buf, int *state, if (!cl || !buf || !state || !dst) return -1; - ctx = cl->ctx; + ctx = cmdline_ctx_get(cl); debug_printf("%s called\n", __func__); memset(&token_hdr, 0, sizeof(token_hdr)); @@ -398,7 +397,7 @@ cmdline_complete(struct cmdline *cl, const char *buf, int *state, if (isblank2(buf[i]) && !isblank2(buf[i+1])) partial_tok = buf+i+1; } - partial_tok_len = strnlen(partial_tok, RDLINE_BUF_SIZE); + partial_tok_len = strlen(partial_tok); /* first call -> do a first pass */ if (*state <= 0) { diff --git a/lib/librte_cmdline/cmdline_rdline.c b/lib/librte_cmdline/cmdline_rdline.c deleted file mode 100644 index 1ef2258..0000000 --- a/lib/librte_cmdline/cmdline_rdline.c +++ /dev/null @@ -1,697 +0,0 @@ -/*- - * BSD LICENSE - * - * Copyright(c) 2010-2014 Intel Corporation. All rights reserved. - * 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 <zer0@droids-corp.org> - * 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 the University of California, Berkeley 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 REGENTS 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 REGENTS AND 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. - */ - -#include <stdlib.h> -#include <stdio.h> -#include <stdint.h> -#include <string.h> -#include <stdarg.h> -#include <errno.h> -#include <ctype.h> - -#include "cmdline_cirbuf.h" -#include "cmdline_rdline.h" - -static void rdline_puts(struct rdline *rdl, const char *buf); -static void rdline_miniprintf(struct rdline *rdl, - const char *buf, unsigned int val); - -static void rdline_remove_old_history_item(struct rdline *rdl); -static void rdline_remove_first_history_item(struct rdline *rdl); -static unsigned int rdline_get_history_size(struct rdline *rdl); - - -/* isblank() needs _XOPEN_SOURCE >= 600 || _ISOC99_SOURCE, so use our - * own. */ -static int -isblank2(char c) -{ - if (c == ' ' || - c == '\t' ) - return 1; - return 0; -} - -int -rdline_init(struct rdline *rdl, - rdline_write_char_t *write_char, - rdline_validate_t *validate, - rdline_complete_t *complete) -{ - if (!rdl || !write_char || !validate || !complete) - return -EINVAL; - memset(rdl, 0, sizeof(*rdl)); - rdl->validate = validate; - rdl->complete = complete; - rdl->write_char = write_char; - rdl->status = RDLINE_INIT; - return cirbuf_init(&rdl->history, rdl->history_buf, 0, RDLINE_HISTORY_BUF_SIZE); -} - -void -rdline_newline(struct rdline *rdl, const char *prompt) -{ - unsigned int i; - - if (!rdl || !prompt) - return; - - vt100_init(&rdl->vt100); - cirbuf_init(&rdl->left, rdl->left_buf, 0, RDLINE_BUF_SIZE); - cirbuf_init(&rdl->right, rdl->right_buf, 0, RDLINE_BUF_SIZE); - - rdl->prompt_size = strnlen(prompt, RDLINE_PROMPT_SIZE-1); - if (prompt != rdl->prompt) - memcpy(rdl->prompt, prompt, rdl->prompt_size); - rdl->prompt[RDLINE_PROMPT_SIZE-1] = '\0'; - - for (i=0 ; i<rdl->prompt_size ; i++) - rdl->write_char(rdl, rdl->prompt[i]); - rdl->status = RDLINE_RUNNING; - - rdl->history_cur_line = -1; -} - -void -rdline_stop(struct rdline *rdl) -{ - if (!rdl) - return; - rdl->status = RDLINE_INIT; -} - -void -rdline_quit(struct rdline *rdl) -{ - if (!rdl) - return; - rdl->status = RDLINE_EXITED; -} - -void -rdline_restart(struct rdline *rdl) -{ - if (!rdl) - return; - rdl->status = RDLINE_RUNNING; -} - -void -rdline_reset(struct rdline *rdl) -{ - if (!rdl) - return; - vt100_init(&rdl->vt100); - cirbuf_init(&rdl->left, rdl->left_buf, 0, RDLINE_BUF_SIZE); - cirbuf_init(&rdl->right, rdl->right_buf, 0, RDLINE_BUF_SIZE); - - rdl->status = RDLINE_RUNNING; - - rdl->history_cur_line = -1; -} - -const char * -rdline_get_buffer(struct rdline *rdl) -{ - if (!rdl) - return NULL; - unsigned int len_l, len_r; - cirbuf_align_left(&rdl->left); - cirbuf_align_left(&rdl->right); - - len_l = CIRBUF_GET_LEN(&rdl->left); - len_r = CIRBUF_GET_LEN(&rdl->right); - memcpy(rdl->left_buf+len_l, rdl->right_buf, len_r); - - rdl->left_buf[len_l + len_r] = '\n'; - rdl->left_buf[len_l + len_r + 1] = '\0'; - return rdl->left_buf; -} - -static void -display_right_buffer(struct rdline *rdl, int force) -{ - unsigned int i; - char tmp; - - if (!force && CIRBUF_IS_EMPTY(&rdl->right)) - return; - - rdline_puts(rdl, vt100_clear_right); - CIRBUF_FOREACH(&rdl->right, i, tmp) { - rdl->write_char(rdl, tmp); - } - if (!CIRBUF_IS_EMPTY(&rdl->right)) - rdline_miniprintf(rdl, vt100_multi_left, - CIRBUF_GET_LEN(&rdl->right)); -} - -void -rdline_redisplay(struct rdline *rdl) -{ - unsigned int i; - char tmp; - - if (!rdl) - return; - - rdline_puts(rdl, vt100_home); - for (i=0 ; i<rdl->prompt_size ; i++) - rdl->write_char(rdl, rdl->prompt[i]); - CIRBUF_FOREACH(&rdl->left, i, tmp) { - rdl->write_char(rdl, tmp); - } - display_right_buffer(rdl, 1); -} - -int -rdline_char_in(struct rdline *rdl, char c) -{ - unsigned int i; - int cmd; - char tmp; - char *buf; - - if (!rdl) - return -EINVAL; - - if (rdl->status == RDLINE_EXITED) - return RDLINE_RES_EXITED; - if (rdl->status != RDLINE_RUNNING) - return RDLINE_RES_NOT_RUNNING; - - cmd = vt100_parser(&rdl->vt100, c); - if (cmd == -2) - return RDLINE_RES_SUCCESS; - - if (cmd >= 0) { - switch (cmd) { - /* move caret 1 char to the left */ - case CMDLINE_KEY_CTRL_B: - case CMDLINE_KEY_LEFT_ARR: - if (CIRBUF_IS_EMPTY(&rdl->left)) - break; - tmp = cirbuf_get_tail(&rdl->left); - cirbuf_del_tail(&rdl->left); - cirbuf_add_head(&rdl->right, tmp); - rdline_puts(rdl, vt100_left_arr); - break; - - /* move caret 1 char to the right */ - case CMDLINE_KEY_CTRL_F: - case CMDLINE_KEY_RIGHT_ARR: - if (CIRBUF_IS_EMPTY(&rdl->right)) - break; - tmp = cirbuf_get_head(&rdl->right); - cirbuf_del_head(&rdl->right); - cirbuf_add_tail(&rdl->left, tmp); - rdline_puts(rdl, vt100_right_arr); - break; - - /* move caret 1 word to the left */ - /* keyboard equivalent: Alt+B */ - case CMDLINE_KEY_WLEFT: - while (! CIRBUF_IS_EMPTY(&rdl->left) && - (tmp = cirbuf_get_tail(&rdl->left)) && - isblank2(tmp)) { - rdline_puts(rdl, vt100_left_arr); - cirbuf_del_tail(&rdl->left); - cirbuf_add_head(&rdl->right, tmp); - } - while (! CIRBUF_IS_EMPTY(&rdl->left) && - (tmp = cirbuf_get_tail(&rdl->left)) && - !isblank2(tmp)) { - rdline_puts(rdl, vt100_left_arr); - cirbuf_del_tail(&rdl->left); - cirbuf_add_head(&rdl->right, tmp); - } - break; - - /* move caret 1 word to the right */ - /* keyboard equivalent: Alt+F */ - case CMDLINE_KEY_WRIGHT: - while (! CIRBUF_IS_EMPTY(&rdl->right) && - (tmp = cirbuf_get_head(&rdl->right)) && - isblank2(tmp)) { - rdline_puts(rdl, vt100_right_arr); - cirbuf_del_head(&rdl->right); - cirbuf_add_tail(&rdl->left, tmp); - } - while (! CIRBUF_IS_EMPTY(&rdl->right) && - (tmp = cirbuf_get_head(&rdl->right)) && - !isblank2(tmp)) { - rdline_puts(rdl, vt100_right_arr); - cirbuf_del_head(&rdl->right); - cirbuf_add_tail(&rdl->left, tmp); - } - break; - - /* move caret to the left */ - case CMDLINE_KEY_CTRL_A: - if (CIRBUF_IS_EMPTY(&rdl->left)) - break; - rdline_miniprintf(rdl, vt100_multi_left, - CIRBUF_GET_LEN(&rdl->left)); - while (! CIRBUF_IS_EMPTY(&rdl->left)) { - tmp = cirbuf_get_tail(&rdl->left); - cirbuf_del_tail(&rdl->left); - cirbuf_add_head(&rdl->right, tmp); - } - break; - - /* move caret to the right */ - case CMDLINE_KEY_CTRL_E: - if (CIRBUF_IS_EMPTY(&rdl->right)) - break; - rdline_miniprintf(rdl, vt100_multi_right, - CIRBUF_GET_LEN(&rdl->right)); - while (! CIRBUF_IS_EMPTY(&rdl->right)) { - tmp = cirbuf_get_head(&rdl->right); - cirbuf_del_head(&rdl->right); - cirbuf_add_tail(&rdl->left, tmp); - } - break; - - /* delete 1 char from the left */ - case CMDLINE_KEY_BKSPACE: - if(!cirbuf_del_tail_safe(&rdl->left)) { - rdline_puts(rdl, vt100_bs); - display_right_buffer(rdl, 1); - } - break; - - /* delete 1 char from the right */ - case CMDLINE_KEY_SUPPR: - case CMDLINE_KEY_CTRL_D: - if (cmd == CMDLINE_KEY_CTRL_D && - CIRBUF_IS_EMPTY(&rdl->left) && - CIRBUF_IS_EMPTY(&rdl->right)) { - return RDLINE_RES_EOF; - } - if (!cirbuf_del_head_safe(&rdl->right)) { - display_right_buffer(rdl, 1); - } - break; - - /* delete 1 word from the left */ - case CMDLINE_KEY_META_BKSPACE: - case CMDLINE_KEY_CTRL_W: - while (! CIRBUF_IS_EMPTY(&rdl->left) && isblank2(cirbuf_get_tail(&rdl->left))) { - rdline_puts(rdl, vt100_bs); - cirbuf_del_tail(&rdl->left); - } - while (! CIRBUF_IS_EMPTY(&rdl->left) && !isblank2(cirbuf_get_tail(&rdl->left))) { - rdline_puts(rdl, vt100_bs); - cirbuf_del_tail(&rdl->left); - } - display_right_buffer(rdl, 1); - break; - - /* delete 1 word from the right */ - case CMDLINE_KEY_META_D: - while (! CIRBUF_IS_EMPTY(&rdl->right) && isblank2(cirbuf_get_head(&rdl->right))) - cirbuf_del_head(&rdl->right); - while (! CIRBUF_IS_EMPTY(&rdl->right) && !isblank2(cirbuf_get_head(&rdl->right))) - cirbuf_del_head(&rdl->right); - display_right_buffer(rdl, 1); - break; - - /* set kill buffer to contents on the right side of caret */ - case CMDLINE_KEY_CTRL_K: - cirbuf_get_buf_head(&rdl->right, rdl->kill_buf, RDLINE_BUF_SIZE); - rdl->kill_size = CIRBUF_GET_LEN(&rdl->right); - cirbuf_del_buf_head(&rdl->right, rdl->kill_size); - rdline_puts(rdl, vt100_clear_right); - break; - - /* paste contents of kill buffer to the left side of caret */ - case CMDLINE_KEY_CTRL_Y: - i=0; - while(CIRBUF_GET_LEN(&rdl->right) + CIRBUF_GET_LEN(&rdl->left) < - RDLINE_BUF_SIZE && - i < rdl->kill_size) { - cirbuf_add_tail(&rdl->left, rdl->kill_buf[i]); - rdl->write_char(rdl, rdl->kill_buf[i]); - i++; - } - display_right_buffer(rdl, 0); - break; - - /* clear and newline */ - case CMDLINE_KEY_CTRL_C: - rdline_puts(rdl, "\r\n"); - rdline_newline(rdl, rdl->prompt); - break; - - /* redisplay (helps when prompt is lost in other output) */ - case CMDLINE_KEY_CTRL_L: - rdline_redisplay(rdl); - break; - - /* autocomplete */ - case CMDLINE_KEY_TAB: - case CMDLINE_KEY_HELP: - cirbuf_align_left(&rdl->left); - rdl->left_buf[CIRBUF_GET_LEN(&rdl->left)] = '\0'; - if (rdl->complete) { - char tmp_buf[BUFSIZ]; - int complete_state; - int ret; - unsigned int tmp_size; - - if (cmd == CMDLINE_KEY_TAB) - complete_state = 0; - else - complete_state = -1; - - /* see in parse.h for help on complete() */ - ret = rdl->complete(rdl, rdl->left_buf, - tmp_buf, sizeof(tmp_buf), - &complete_state); - /* no completion or error */ - if (ret <= 0) { - return RDLINE_RES_COMPLETE; - } - - tmp_size = strnlen(tmp_buf, sizeof(tmp_buf)); - /* add chars */ - if (ret == RDLINE_RES_COMPLETE) { - i=0; - while(CIRBUF_GET_LEN(&rdl->right) + CIRBUF_GET_LEN(&rdl->left) < - RDLINE_BUF_SIZE && - i < tmp_size) { - cirbuf_add_tail(&rdl->left, tmp_buf[i]); - rdl->write_char(rdl, tmp_buf[i]); - i++; - } - display_right_buffer(rdl, 1); - return RDLINE_RES_COMPLETE; /* ?? */ - } - - /* choice */ - rdline_puts(rdl, "\r\n"); - while (ret) { - rdl->write_char(rdl, ' '); - for (i=0 ; tmp_buf[i] ; i++) - rdl->write_char(rdl, tmp_buf[i]); - rdline_puts(rdl, "\r\n"); - ret = rdl->complete(rdl, rdl->left_buf, - tmp_buf, sizeof(tmp_buf), - &complete_state); - } - - rdline_redisplay(rdl); - } - return RDLINE_RES_COMPLETE; - - /* complete buffer */ - case CMDLINE_KEY_RETURN: - case CMDLINE_KEY_RETURN2: - rdline_get_buffer(rdl); - rdl->status = RDLINE_INIT; - rdline_puts(rdl, "\r\n"); - if (rdl->history_cur_line != -1) - rdline_remove_first_history_item(rdl); - - if (rdl->validate) - rdl->validate(rdl, rdl->left_buf, CIRBUF_GET_LEN(&rdl->left)+2); - /* user may have stopped rdline */ - if (rdl->status == RDLINE_EXITED) - return RDLINE_RES_EXITED; - return RDLINE_RES_VALIDATED; - - /* previous element in history */ - case CMDLINE_KEY_UP_ARR: - case CMDLINE_KEY_CTRL_P: - if (rdl->history_cur_line == 0) { - rdline_remove_first_history_item(rdl); - } - if (rdl->history_cur_line <= 0) { - rdline_add_history(rdl, rdline_get_buffer(rdl)); - rdl->history_cur_line = 0; - } - - buf = rdline_get_history_item(rdl, rdl->history_cur_line + 1); - if (!buf) - break; - - rdl->history_cur_line ++; - vt100_init(&rdl->vt100); - cirbuf_init(&rdl->left, rdl->left_buf, 0, RDLINE_BUF_SIZE); - cirbuf_init(&rdl->right, rdl->right_buf, 0, RDLINE_BUF_SIZE); - cirbuf_add_buf_tail(&rdl->left, buf, strnlen(buf, RDLINE_BUF_SIZE)); - rdline_redisplay(rdl); - break; - - /* next element in history */ - case CMDLINE_KEY_DOWN_ARR: - case CMDLINE_KEY_CTRL_N: - if (rdl->history_cur_line - 1 < 0) - break; - - rdl->history_cur_line --; - buf = rdline_get_history_item(rdl, rdl->history_cur_line); - if (!buf) - break; - vt100_init(&rdl->vt100); - cirbuf_init(&rdl->left, rdl->left_buf, 0, RDLINE_BUF_SIZE); - cirbuf_init(&rdl->right, rdl->right_buf, 0, RDLINE_BUF_SIZE); - cirbuf_add_buf_tail(&rdl->left, buf, strnlen(buf, RDLINE_BUF_SIZE)); - rdline_redisplay(rdl); - - break; - - - default: - break; - } - - return RDLINE_RES_SUCCESS; - } - - if (!isprint((int)c)) - return RDLINE_RES_SUCCESS; - - /* standard chars */ - if (CIRBUF_GET_LEN(&rdl->left) + CIRBUF_GET_LEN(&rdl->right) >= RDLINE_BUF_SIZE) - return RDLINE_RES_SUCCESS; - - if (cirbuf_add_tail_safe(&rdl->left, c)) - return RDLINE_RES_SUCCESS; - - rdl->write_char(rdl, c); - display_right_buffer(rdl, 0); - - return RDLINE_RES_SUCCESS; -} - - -/* HISTORY */ - -static void -rdline_remove_old_history_item(struct rdline * rdl) -{ - char tmp; - - while (! CIRBUF_IS_EMPTY(&rdl->history) ) { - tmp = cirbuf_get_head(&rdl->history); - cirbuf_del_head(&rdl->history); - if (!tmp) - break; - } -} - -static void -rdline_remove_first_history_item(struct rdline * rdl) -{ - char tmp; - - if ( CIRBUF_IS_EMPTY(&rdl->history) ) { - return; - } - else { - cirbuf_del_tail(&rdl->history); - } - - while (! CIRBUF_IS_EMPTY(&rdl->history) ) { - tmp = cirbuf_get_tail(&rdl->history); - if (!tmp) - break; - cirbuf_del_tail(&rdl->history); - } -} - -static unsigned int -rdline_get_history_size(struct rdline * rdl) -{ - unsigned int i, tmp, ret=0; - - CIRBUF_FOREACH(&rdl->history, i, tmp) { - if (tmp == 0) - ret ++; - } - - return ret; -} - -char * -rdline_get_history_item(struct rdline * rdl, unsigned int idx) -{ - unsigned int len, i, tmp; - - if (!rdl) - return NULL; - - len = rdline_get_history_size(rdl); - if ( idx >= len ) { - return NULL; - } - - cirbuf_align_left(&rdl->history); - - CIRBUF_FOREACH(&rdl->history, i, tmp) { - if ( idx == len - 1) { - return rdl->history_buf + i; - } - if (tmp == 0) - len --; - } - - return NULL; -} - -int -rdline_add_history(struct rdline * rdl, const char * buf) -{ - unsigned int len, i; - - if (!rdl || !buf) - return -EINVAL; - - len = strnlen(buf, RDLINE_BUF_SIZE); - for (i=0; i<len ; i++) { - if (buf[i] == '\n') { - len = i; - break; - } - } - - if ( len >= RDLINE_HISTORY_BUF_SIZE ) - return -1; - - while ( len >= CIRBUF_GET_FREELEN(&rdl->history) ) { - rdline_remove_old_history_item(rdl); - } - - cirbuf_add_buf_tail(&rdl->history, buf, len); - cirbuf_add_tail(&rdl->history, 0); - - return 0; -} - -void -rdline_clear_history(struct rdline * rdl) -{ - if (!rdl) - return; - cirbuf_init(&rdl->history, rdl->history_buf, 0, RDLINE_HISTORY_BUF_SIZE); -} - - -/* STATIC USEFUL FUNCS */ - -static void -rdline_puts(struct rdline * rdl, const char * buf) -{ - char c; - while ( (c = *(buf++)) != '\0' ) { - rdl->write_char(rdl, c); - } -} - -/* a very very basic printf with one arg and one format 'u' */ -static void -rdline_miniprintf(struct rdline *rdl, const char * buf, unsigned int val) -{ - char c, started=0, div=100; - - while ( (c=*(buf++)) ) { - if (c != '%') { - rdl->write_char(rdl, c); - continue; - } - c = *(buf++); - if (c != 'u') { - rdl->write_char(rdl, '%'); - rdl->write_char(rdl, c); - continue; - } - /* val is never more than 255 */ - while (div) { - c = (char)(val / div); - if (c || started) { - rdl->write_char(rdl, (char)(c+'0')); - started = 1; - } - val %= div; - div /= 10; - } - } -} diff --git a/lib/librte_cmdline/cmdline_rdline.h b/lib/librte_cmdline/cmdline_rdline.h deleted file mode 100644 index 72e2dad..0000000 --- a/lib/librte_cmdline/cmdline_rdline.h +++ /dev/null @@ -1,255 +0,0 @@ -/*- - * BSD LICENSE - * - * Copyright(c) 2010-2014 Intel Corporation. All rights reserved. - * 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 <zer0@droids-corp.org> - * 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 the University of California, Berkeley 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 REGENTS 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 REGENTS AND 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. - */ - -#ifndef _RDLINE_H_ -#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. - * - * Obviously, it does not support as many things as the GNU readline, - * but at least it supports some interesting 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. - */ - -#include <stdio.h> -#include <cmdline_cirbuf.h> -#include <cmdline_vt100.h> - -#ifdef __cplusplus -extern "C" { -#endif - -/* configuration */ -#define RDLINE_BUF_SIZE 512 -#define RDLINE_PROMPT_SIZE 32 -#define RDLINE_VT100_BUF_SIZE 8 -#define RDLINE_HISTORY_BUF_SIZE BUFSIZ -#define RDLINE_HISTORY_MAX_LINE 64 - -enum rdline_status { - RDLINE_INIT, - RDLINE_RUNNING, - RDLINE_EXITED -}; - -struct rdline; - -typedef int (rdline_write_char_t)(struct rdline *rdl, char); -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); - -struct rdline { - enum rdline_status status; - /* rdline bufs */ - struct cirbuf left; - struct cirbuf right; - char left_buf[RDLINE_BUF_SIZE+2]; /* reserve 2 chars for the \n\0 */ - char right_buf[RDLINE_BUF_SIZE]; - - char prompt[RDLINE_PROMPT_SIZE]; - unsigned int prompt_size; - - char kill_buf[RDLINE_BUF_SIZE]; - unsigned int kill_size; - - /* history */ - struct cirbuf history; - char history_buf[RDLINE_HISTORY_BUF_SIZE]; - int history_cur_line; - - /* callbacks and func pointers */ - rdline_write_char_t *write_char; - rdline_validate_t *validate; - rdline_complete_t *complete; - - /* vt100 parser */ - struct cmdline_vt100 vt100; - - /* opaque pointer */ - void *opaque; -}; - -/** - * 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. - */ -int rdline_init(struct rdline *rdl, - rdline_write_char_t *write_char, - rdline_validate_t *validate, - rdline_complete_t *complete); - - -/** - * Init the current buffer, and display a prompt. - * \param rdl A pointer to a 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 - */ -void rdline_stop(struct rdline *rdl); - -/** - * Same than rdline_stop() except that next calls to rdline_char_in() - * will return RDLINE_RES_EXITED. - * \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 - */ -void rdline_redisplay(struct rdline *rdl); - -/** - * Reset the current buffer and setup for a new line. - * \param rdl A pointer to a struct rdline - */ -void rdline_reset(struct rdline *rdl); - - -/* return status for rdline_char_in() */ -#define RDLINE_RES_SUCCESS 0 -#define RDLINE_RES_VALIDATED 1 -#define RDLINE_RES_COMPLETE 2 -#define RDLINE_RES_NOT_RUNNING -1 -#define RDLINE_RES_EOF -2 -#define RDLINE_RES_EXITED -3 - -/** - * append a char to the readline buffer. - * Return RDLINE_RES_VALIDATE when the line has been validated. - * Return RDLINE_RES_COMPLETE when the user asked to complete the buffer. - * Return RDLINE_RES_NOT_RUNNING if it is not running. - * Return RDLINE_RES_EOF if EOF (ctrl-d on an empty line). - * Else return RDLINE_RES_SUCCESS. - * XXX error case when the buffer is full ? - * - * \param rdl A pointer to a struct rdline - * \param c The character to append - */ -int rdline_char_in(struct rdline *rdl, char c); - -/** - * Return the current buffer, terminated by '\0'. - * \param rdl A pointer to a struct rdline - */ -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' - */ -int rdline_add_history(struct rdline *rdl, const char *buf); - -/** - * Clear current history - * \param rdl A pointer to a struct rdline - */ -void rdline_clear_history(struct rdline *rdl); - -/** - * Get the i-th history item - */ -char *rdline_get_history_item(struct rdline *rdl, unsigned int i); - -#ifdef __cplusplus -} -#endif - -#endif /* _RDLINE_H_ */ diff --git a/lib/librte_cmdline/cmdline_socket.c b/lib/librte_cmdline/cmdline_socket.c index 3fc243b..11524b5 100644 --- a/lib/librte_cmdline/cmdline_socket.c +++ b/lib/librte_cmdline/cmdline_socket.c @@ -58,23 +58,18 @@ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ -#include <stdio.h> -#include <string.h> +#include <stddef.h> #include <unistd.h> -#include <stdlib.h> -#include <stdarg.h> -#include <inttypes.h> #include <fcntl.h> -#include <termios.h> #include "cmdline_parse.h" -#include "cmdline_rdline.h" #include "cmdline_socket.h" #include "cmdline.h" struct cmdline * cmdline_file_new(cmdline_parse_ctx_t *ctx, const char *prompt, const char *path) { + struct cmdline *cl; int fd; /* everything else is checked in cmdline_new() */ @@ -83,37 +78,22 @@ cmdline_file_new(cmdline_parse_ctx_t *ctx, const char *prompt, const char *path) fd = open(path, O_RDONLY, 0); if (fd < 0) { - dprintf("open() failed\n"); return NULL; } - return cmdline_new(ctx, prompt, fd, -1); + cl = cmdline_new(ctx, prompt, fd, -1); + /* cmdline_new() duplicates fd */ + close(fd); + return cl; } struct cmdline * cmdline_stdin_new(cmdline_parse_ctx_t *ctx, const char *prompt) { - struct cmdline *cl; - struct termios oldterm, term; - - tcgetattr(0, &oldterm); - memcpy(&term, &oldterm, sizeof(term)); - term.c_lflag &= ~(ICANON | ECHO | ISIG); - tcsetattr(0, TCSANOW, &term); - setbuf(stdin, NULL); - - cl = cmdline_new(ctx, prompt, 0, 1); - - if (cl) - memcpy(&cl->oldterm, &oldterm, sizeof(term)); - - return cl; + return cmdline_new(ctx, prompt, 0, 1); } void cmdline_stdin_exit(struct cmdline *cl) { - if (!cl) - return; - - tcsetattr(fileno(stdin), TCSANOW, &cl->oldterm); + cmdline_free(cl); } diff --git a/lib/librte_cmdline/cmdline_vt100.c b/lib/librte_cmdline/cmdline_vt100.c deleted file mode 100644 index a253e8b..0000000 --- a/lib/librte_cmdline/cmdline_vt100.c +++ /dev/null @@ -1,185 +0,0 @@ -/*- - * BSD LICENSE - * - * Copyright(c) 2010-2014 Intel Corporation. All rights reserved. - * 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 <zer0@droids-corp.org> - * 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 the University of California, Berkeley 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 REGENTS 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 REGENTS AND 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. - */ - -#include <stdlib.h> -#include <stdint.h> -#include <stdio.h> -#include <string.h> -#include <stdarg.h> -#include <ctype.h> -#include <termios.h> - -#include "cmdline_vt100.h" - -const char *cmdline_vt100_commands[] = { - vt100_up_arr, - vt100_down_arr, - vt100_right_arr, - vt100_left_arr, - "\177", - "\n", - "\001", - "\005", - "\013", - "\031", - "\003", - "\006", - "\002", - vt100_suppr, - vt100_tab, - "\004", - "\014", - "\r", - "\033\177", - vt100_word_left, - vt100_word_right, - "?", - "\027", - "\020", - "\016", - "\033\144", -}; - -void -vt100_init(struct cmdline_vt100 *vt) -{ - if (!vt) - return; - vt->state = CMDLINE_VT100_INIT; -} - - -static int -match_command(char *buf, unsigned int size) -{ - const char *cmd; - size_t cmdlen; - unsigned int i = 0; - - for (i=0 ; i<sizeof(cmdline_vt100_commands)/sizeof(const char *) ; i++) { - cmd = *(cmdline_vt100_commands + i); - - cmdlen = strnlen(cmd, CMDLINE_VT100_BUF_SIZE); - if (size == cmdlen && - !strncmp(buf, cmd, cmdlen)) { - return i; - } - } - - return -1; -} - -int -vt100_parser(struct cmdline_vt100 *vt, char ch) -{ - unsigned int size; - uint8_t c = (uint8_t) ch; - - if (!vt) - return -1; - - if (vt->bufpos >= CMDLINE_VT100_BUF_SIZE) { - vt->state = CMDLINE_VT100_INIT; - vt->bufpos = 0; - } - - vt->buf[vt->bufpos++] = c; - size = vt->bufpos; - - switch (vt->state) { - case CMDLINE_VT100_INIT: - if (c == 033) { - vt->state = CMDLINE_VT100_ESCAPE; - } - else { - vt->bufpos = 0; - goto match_command; - } - break; - - case CMDLINE_VT100_ESCAPE: - if (c == 0133) { - vt->state = CMDLINE_VT100_ESCAPE_CSI; - } - else if (c >= 060 && c <= 0177) { /* XXX 0177 ? */ - vt->bufpos = 0; - vt->state = CMDLINE_VT100_INIT; - goto match_command; - } - break; - - case CMDLINE_VT100_ESCAPE_CSI: - if (c >= 0100 && c <= 0176) { - vt->bufpos = 0; - vt->state = CMDLINE_VT100_INIT; - goto match_command; - } - break; - - default: - vt->bufpos = 0; - break; - } - - return -2; - - match_command: - return match_command(vt->buf, size); -} diff --git a/lib/librte_cmdline/cmdline_vt100.h b/lib/librte_cmdline/cmdline_vt100.h deleted file mode 100644 index 963add8..0000000 --- a/lib/librte_cmdline/cmdline_vt100.h +++ /dev/null @@ -1,153 +0,0 @@ -/*- - * BSD LICENSE - * - * Copyright(c) 2010-2014 Intel Corporation. All rights reserved. - * 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 <zer0@droids-corp.org> - * 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 the University of California, Berkeley 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 REGENTS 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 REGENTS AND 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. - */ - -#ifndef _CMDLINE_VT100_H_ -#define _CMDLINE_VT100_H_ - -#include <stdint.h> - -#ifdef __cplusplus -extern "C" { -#endif - -#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" - -/* Result of parsing : it must be synchronized with - * cmdline_vt100_commands[] in vt100.c */ -#define CMDLINE_KEY_UP_ARR 0 -#define CMDLINE_KEY_DOWN_ARR 1 -#define CMDLINE_KEY_RIGHT_ARR 2 -#define CMDLINE_KEY_LEFT_ARR 3 -#define CMDLINE_KEY_BKSPACE 4 -#define CMDLINE_KEY_RETURN 5 -#define CMDLINE_KEY_CTRL_A 6 -#define CMDLINE_KEY_CTRL_E 7 -#define CMDLINE_KEY_CTRL_K 8 -#define CMDLINE_KEY_CTRL_Y 9 -#define CMDLINE_KEY_CTRL_C 10 -#define CMDLINE_KEY_CTRL_F 11 -#define CMDLINE_KEY_CTRL_B 12 -#define CMDLINE_KEY_SUPPR 13 -#define CMDLINE_KEY_TAB 14 -#define CMDLINE_KEY_CTRL_D 15 -#define CMDLINE_KEY_CTRL_L 16 -#define CMDLINE_KEY_RETURN2 17 -#define CMDLINE_KEY_META_BKSPACE 18 -#define CMDLINE_KEY_WLEFT 19 -#define CMDLINE_KEY_WRIGHT 20 -#define CMDLINE_KEY_HELP 21 -#define CMDLINE_KEY_CTRL_W 22 -#define CMDLINE_KEY_CTRL_P 23 -#define CMDLINE_KEY_CTRL_N 24 -#define CMDLINE_KEY_META_D 25 - -extern const char *cmdline_vt100_commands[]; - -enum cmdline_vt100_parser_state { - CMDLINE_VT100_INIT, - CMDLINE_VT100_ESCAPE, - CMDLINE_VT100_ESCAPE_CSI -}; - -#define CMDLINE_VT100_BUF_SIZE 8 -struct cmdline_vt100 { - uint8_t bufpos; - char buf[CMDLINE_VT100_BUF_SIZE]; - enum cmdline_vt100_parser_state state; -}; - -/** - * Init - */ -void vt100_init(struct cmdline_vt100 *vt); - -/** - * Input a new character. - * Return -1 if the character is not part of a control sequence - * Return -2 if c is not the last char of a control sequence - * Else return the index in vt100_commands[] - */ -int vt100_parser(struct cmdline_vt100 *vt, char c); - -#ifdef __cplusplus -} -#endif - -#endif diff --git a/lib/librte_cmdline/rte_cmdline_version.map b/lib/librte_cmdline/rte_cmdline_version.map index 04bcb38..3133199 100644 --- a/lib/librte_cmdline/rte_cmdline_version.map +++ b/lib/librte_cmdline/rte_cmdline_version.map @@ -1,25 +1,6 @@ DPDK_2.0 { global: - cirbuf_add_buf_head; - cirbuf_add_buf_tail; - cirbuf_add_head; - cirbuf_add_head_safe; - cirbuf_add_tail; - cirbuf_add_tail_safe; - cirbuf_align_left; - cirbuf_align_right; - cirbuf_del_buf_head; - cirbuf_del_buf_tail; - cirbuf_del_head; - cirbuf_del_head_safe; - cirbuf_del_tail; - cirbuf_del_tail_safe; - cirbuf_get_buf_head; - cirbuf_get_buf_tail; - cirbuf_get_head; - cirbuf_get_tail; - cirbuf_init; cmdline_complete; cmdline_complete_get_elt_string; cmdline_complete_get_nb_string; @@ -50,21 +31,6 @@ DPDK_2.0 { cmdline_token_num_ops; cmdline_token_portlist_ops; cmdline_token_string_ops; - cmdline_write_char; - rdline_add_history; - rdline_char_in; - rdline_clear_history; - rdline_get_buffer; - rdline_get_history_item; - rdline_init; - rdline_newline; - rdline_quit; - rdline_redisplay; - rdline_reset; - rdline_restart; - rdline_stop; - vt100_init; - vt100_parser; local: *; }; @@ -75,3 +41,10 @@ DPDK_2.1 { cmdline_poll; } DPDK_2.0; + +DPDK_18.02 { + global: + + cmdline_ctx_get; + +} DPDK_2.1; diff --git a/mk/rte.app.mk b/mk/rte.app.mk index 6a6a745..504bb4e 100644 --- a/mk/rte.app.mk +++ b/mk/rte.app.mk @@ -102,6 +102,8 @@ _LDLIBS-$(CONFIG_RTE_LIBRTE_RING) += -lrte_ring _LDLIBS-$(CONFIG_RTE_LIBRTE_PCI) += -lrte_pci _LDLIBS-$(CONFIG_RTE_LIBRTE_EAL) += -lrte_eal _LDLIBS-$(CONFIG_RTE_LIBRTE_CMDLINE) += -lrte_cmdline + +_LDLIBS-$(CONFIG_RTE_LIBRTE_CMDLINE) += $(shell pkg-config --libs libedit) _LDLIBS-$(CONFIG_RTE_LIBRTE_REORDER) += -lrte_reorder _LDLIBS-$(CONFIG_RTE_LIBRTE_SCHED) += -lrte_sched diff --git a/test/cmdline_test/cmdline_test.c b/test/cmdline_test/cmdline_test.c index 716b5f1..595efa5 100644 --- a/test/cmdline_test/cmdline_test.c +++ b/test/cmdline_test/cmdline_test.c @@ -41,7 +41,6 @@ #include <ctype.h> #include <sys/queue.h> -#include <cmdline_rdline.h> #include <cmdline_parse.h> #include <cmdline_socket.h> #include <cmdline.h> diff --git a/test/cmdline_test/commands.c b/test/cmdline_test/commands.c index 404f51a..8481af9 100644 --- a/test/cmdline_test/commands.c +++ b/test/cmdline_test/commands.c @@ -36,7 +36,6 @@ #include <termios.h> #include <inttypes.h> -#include <cmdline_rdline.h> #include <cmdline_parse.h> #include <cmdline_parse_string.h> #include <cmdline_parse_num.h> @@ -306,72 +305,6 @@ cmdline_parse_inst_t cmd_ambig_2 = { -/*** get_history_bufsize ***/ -/* command that displays total space in history buffer - * this will be useful for testing history (to fill it up just enough to - * remove the last entry, we need to know how big it is). - */ - -struct cmd_get_history_bufsize_result { - cmdline_fixed_string_t str; -}; - -static void -cmd_get_history_bufsize_parsed(__attribute__((unused)) void *parsed_result, - struct cmdline *cl, - __attribute__((unused)) void *data) -{ - cmdline_printf(cl, "History buffer size: %zu\n", - sizeof(cl->rdl.history_buf)); -} - -cmdline_parse_token_string_t cmd_get_history_bufsize_tok = - TOKEN_STRING_INITIALIZER(struct cmd_get_history_bufsize_result, str, - "get_history_bufsize"); - -cmdline_parse_inst_t cmd_get_history_bufsize = { - .f = cmd_get_history_bufsize_parsed, /* function to call */ - .data = NULL, /* 2nd arg of func */ - .help_str = "command that displays total space in history buffer", - .tokens = { /* token list, NULL terminated */ - (void *)&cmd_get_history_bufsize_tok, - NULL, - }, -}; - - - -/*** clear_history ***/ -/* clears history buffer */ - -struct cmd_clear_history_result { - cmdline_fixed_string_t str; -}; - -static void -cmd_clear_history_parsed(__attribute__((unused)) void *parsed_result, - struct cmdline *cl, - __attribute__((unused)) void *data) -{ - rdline_clear_history(&cl->rdl); -} - -cmdline_parse_token_string_t cmd_clear_history_tok = - TOKEN_STRING_INITIALIZER(struct cmd_clear_history_result, str, - "clear_history"); - -cmdline_parse_inst_t cmd_clear_history = { - .f = cmd_clear_history_parsed, /* function to call */ - .data = NULL, /* 2nd arg of func */ - .help_str = "clear command history", - .tokens = { /* token list, NULL terminated */ - (void *)&cmd_clear_history_tok, - NULL, - }, -}; - - - /****************/ cmdline_parse_ctx_t main_ctx[] = { @@ -381,8 +314,6 @@ cmdline_parse_ctx_t main_ctx[] = { (cmdline_parse_inst_t *)&cmd_single, (cmdline_parse_inst_t *)&cmd_single_long, (cmdline_parse_inst_t *)&cmd_num, - (cmdline_parse_inst_t *)&cmd_get_history_bufsize, - (cmdline_parse_inst_t *)&cmd_clear_history, (cmdline_parse_inst_t *)&cmd_autocomplete_1, (cmdline_parse_inst_t *)&cmd_autocomplete_2, NULL, diff --git a/test/test/Makefile b/test/test/Makefile index bb54c98..49e907c 100644 --- a/test/test/Makefile +++ b/test/test/Makefile @@ -164,7 +164,6 @@ SRCS-$(CONFIG_RTE_LIBRTE_CMDLINE) += test_cmdline_num.c SRCS-$(CONFIG_RTE_LIBRTE_CMDLINE) += test_cmdline_etheraddr.c SRCS-$(CONFIG_RTE_LIBRTE_CMDLINE) += test_cmdline_portlist.c SRCS-$(CONFIG_RTE_LIBRTE_CMDLINE) += test_cmdline_ipaddr.c -SRCS-$(CONFIG_RTE_LIBRTE_CMDLINE) += test_cmdline_cirbuf.c SRCS-$(CONFIG_RTE_LIBRTE_CMDLINE) += test_cmdline_string.c SRCS-$(CONFIG_RTE_LIBRTE_CMDLINE) += test_cmdline_lib.c diff --git a/test/test/commands.c b/test/test/commands.c index 4097a33..21a4a06 100644 --- a/test/test/commands.c +++ b/test/test/commands.c @@ -66,7 +66,6 @@ #include <rte_mbuf.h> #include <rte_devargs.h> -#include <cmdline_rdline.h> #include <cmdline_parse.h> #include <cmdline_parse_ipaddr.h> #include <cmdline_parse_num.h> diff --git a/test/test/test.c b/test/test/test.c index 0e6ff7c..6f48892 100644 --- a/test/test/test.c +++ b/test/test/test.c @@ -42,7 +42,6 @@ #include <sys/queue.h> #ifdef RTE_LIBRTE_CMDLINE -#include <cmdline_rdline.h> #include <cmdline_parse.h> #include <cmdline_socket.h> #include <cmdline.h> diff --git a/test/test/test_cmdline.c b/test/test/test_cmdline.c index 38c7256..056b569 100644 --- a/test/test/test_cmdline.c +++ b/test/test/test_cmdline.c @@ -74,15 +74,6 @@ test_cmdline(void) return -1; if (test_parse_string_invalid_param() < 0) return -1; - printf("Testing circular buffer...\n"); - if (test_cirbuf_char() < 0) - return -1; - if (test_cirbuf_string() < 0) - return -1; - if (test_cirbuf_align() < 0) - return -1; - if (test_cirbuf_invalid_param() < 0) - return -1; printf("Testing library functions...\n"); if (test_cmdline_lib() < 0) return -1; diff --git a/test/test/test_cmdline.h b/test/test/test_cmdline.h index 0ee91c1..b55caa9 100644 --- a/test/test/test_cmdline.h +++ b/test/test/test_cmdline.h @@ -61,12 +61,6 @@ int test_parse_string_valid(void); int test_parse_string_invalid_data(void); int test_parse_string_invalid_param(void); -/* cmdline_cirbuf tests */ -int test_cirbuf_invalid_param(void); -int test_cirbuf_char(void); -int test_cirbuf_string(void); -int test_cirbuf_align(void); - /* test the rest of the library */ int test_cmdline_lib(void); diff --git a/test/test/test_cmdline_cirbuf.c b/test/test/test_cmdline_cirbuf.c deleted file mode 100644 index 2c32145..0000000 --- a/test/test/test_cmdline_cirbuf.c +++ /dev/null @@ -1,1330 +0,0 @@ -/*- - * BSD LICENSE - * - * Copyright(c) 2010-2014 Intel Corporation. All rights reserved. - * 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. - */ - -#include <stdio.h> -#include <stdlib.h> -#include <string.h> - -#include <rte_string_fns.h> - -#include <cmdline_cirbuf.h> - -#include "test_cmdline.h" - -/* different length strings */ -#define CIRBUF_STR_HEAD " HEAD" -#define CIRBUF_STR_TAIL "TAIL" - -/* miscellaneous tests - they make bullseye happy */ -static int -test_cirbuf_string_misc(void) -{ - struct cirbuf cb; - char buf[CMDLINE_TEST_BUFSIZE]; - char tmp[CMDLINE_TEST_BUFSIZE]; - - /* initialize buffers */ - memset(buf, 0, sizeof(buf)); - memset(tmp, 0, sizeof(tmp)); - - /* - * initialize circular buffer - */ - if (cirbuf_init(&cb, buf, 0, sizeof(buf)) < 0) { - printf("Error: failed to initialize circular buffer!\n"); - return -1; - } - - /* - * add strings to head and tail, but read only tail - * this results in read operation that does not transcend - * from buffer end to buffer beginning (in other words, - * strlen <= cb->maxlen - cb->end) - */ - - /* add string to head */ - if (cirbuf_add_buf_head(&cb, CIRBUF_STR_HEAD, sizeof(CIRBUF_STR_HEAD)) - != (sizeof(CIRBUF_STR_HEAD))) { - printf("Error: failed to add string to head!\n"); - return -1; - } - /* add string to tail */ - if (cirbuf_add_buf_tail(&cb, CIRBUF_STR_TAIL, sizeof(CIRBUF_STR_TAIL)) - != (sizeof(CIRBUF_STR_TAIL))) { - printf("Error: failed to add string to head!\n"); - return -1; - } - /* read string from tail */ - if (cirbuf_get_buf_tail(&cb, tmp, sizeof(CIRBUF_STR_TAIL)) - != (sizeof(CIRBUF_STR_TAIL))) { - printf("Error: failed to get string from tail!\n"); - return -1; - } - /* verify string */ - if (strncmp(tmp, CIRBUF_STR_TAIL, sizeof(CIRBUF_STR_TAIL)) != 0) { - printf("Error: tail strings do not match!\n"); - return -1; - } - /* clear buffers */ - memset(tmp, 0, sizeof(tmp)); - memset(buf, 0, sizeof(buf)); - - - - /* - * add a string to buffer when start/end is at end of buffer - */ - - /* - * reinitialize circular buffer with start at the end of cirbuf - */ - if (cirbuf_init(&cb, buf, CMDLINE_TEST_BUFSIZE - 2, sizeof(buf)) < 0) { - printf("Error: failed to reinitialize circular buffer!\n"); - return -1; - } - - - /* add string to tail */ - if (cirbuf_add_buf_tail(&cb, CIRBUF_STR_TAIL, sizeof(CIRBUF_STR_TAIL)) - != (sizeof(CIRBUF_STR_TAIL))) { - printf("Error: failed to add string to tail!\n"); - return -1; - } - /* read string from tail */ - if (cirbuf_get_buf_tail(&cb, tmp, sizeof(CIRBUF_STR_TAIL)) - != (sizeof(CIRBUF_STR_TAIL))) { - printf("Error: failed to get string from tail!\n"); - return -1; - } - /* verify string */ - if (strncmp(tmp, CIRBUF_STR_TAIL, sizeof(CIRBUF_STR_TAIL)) != 0) { - printf("Error: tail strings do not match!\n"); - return -1; - } - /* clear tmp buffer */ - memset(tmp, 0, sizeof(tmp)); - - - /* add string to head */ - if (cirbuf_add_buf_head(&cb, CIRBUF_STR_HEAD, sizeof(CIRBUF_STR_HEAD)) - != (sizeof(CIRBUF_STR_HEAD))) { - printf("Error: failed to add string to head!\n"); - return -1; - } - /* read string from tail */ - if (cirbuf_get_buf_head(&cb, tmp, sizeof(CIRBUF_STR_HEAD)) - != (sizeof(CIRBUF_STR_HEAD))) { - printf("Error: failed to get string from head!\n"); - return -1; - } - /* verify string */ - if (strncmp(tmp, CIRBUF_STR_HEAD, sizeof(CIRBUF_STR_HEAD)) != 0) { - printf("Error: headstrings do not match!\n"); - return -1; - } - - return 0; -} - -/* test adding and deleting strings */ -static int -test_cirbuf_string_add_del(void) -{ - struct cirbuf cb; - char buf[CMDLINE_TEST_BUFSIZE]; - char tmp[CMDLINE_TEST_BUFSIZE]; - - /* initialize buffers */ - memset(buf, 0, sizeof(buf)); - memset(tmp, 0, sizeof(tmp)); - - /* - * initialize circular buffer - */ - if (cirbuf_init(&cb, buf, 0, sizeof(buf)) < 0) { - printf("Error: failed to initialize circular buffer!\n"); - return -1; - } - - /* add string to head */ - if (cirbuf_add_buf_head(&cb, CIRBUF_STR_HEAD, sizeof(CIRBUF_STR_HEAD)) - != (sizeof(CIRBUF_STR_HEAD))) { - printf("Error: failed to add string to head!\n"); - return -1; - } - /* read string from head */ - if (cirbuf_get_buf_head(&cb, tmp, sizeof(CIRBUF_STR_HEAD)) - != (sizeof(CIRBUF_STR_HEAD))) { - printf("Error: failed to get string from head!\n"); - return -1; - } - /* verify string */ - if (strncmp(tmp, CIRBUF_STR_HEAD, sizeof(CIRBUF_STR_HEAD)) != 0) { - printf("Error: head strings do not match!\n"); - return -1; - } - /* clear tmp buffer */ - memset(tmp, 0, sizeof(tmp)); - /* read string from tail */ - if (cirbuf_get_buf_tail(&cb, tmp, sizeof(CIRBUF_STR_HEAD)) - != (sizeof(CIRBUF_STR_HEAD))) { - printf("Error: failed to get string from head!\n"); - return -1; - } - /* verify string */ - if (strncmp(tmp, CIRBUF_STR_HEAD, sizeof(CIRBUF_STR_HEAD)) != 0) { - printf("Error: head strings do not match!\n"); - return -1; - } - /* delete string from head*/ - if (cirbuf_del_buf_head(&cb, sizeof(CIRBUF_STR_HEAD)) < 0) { - printf("Error: failed to delete string from head!\n"); - return -1; - } - /* verify string was deleted */ - if (cirbuf_del_head_safe(&cb) == 0) { - printf("Error: buffer should have been empty!\n"); - return -1; - } - /* clear tmp buffer */ - memset(tmp, 0, sizeof(tmp)); - - - - /* - * reinitialize circular buffer - */ - memset(buf, 0, sizeof(buf)); - if (cirbuf_init(&cb, buf, 0, sizeof(buf)) < 0) { - printf("Error: failed to reinitialize circular buffer!\n"); - return -1; - } - - /* add string to tail */ - if (cirbuf_add_buf_tail(&cb, CIRBUF_STR_TAIL, sizeof(CIRBUF_STR_TAIL)) - != (sizeof(CIRBUF_STR_TAIL))) { - printf("Error: failed to add string to tail!\n"); - return -1; - } - /* get string from tail */ - if (cirbuf_get_buf_tail(&cb, tmp, sizeof(CIRBUF_STR_TAIL)) - != (sizeof(CIRBUF_STR_TAIL))) { - printf("Error: failed to get string from tail!\n"); - return -1; - } - /* verify string */ - if (strncmp(tmp, CIRBUF_STR_TAIL, sizeof(CIRBUF_STR_TAIL)) != 0) { - printf("Error: tail strings do not match!\n"); - return -1; - } - /* clear tmp buffer */ - memset(tmp, 0, sizeof(tmp)); - /* get string from head */ - if (cirbuf_get_buf_head(&cb, tmp, sizeof(CIRBUF_STR_TAIL)) - != (sizeof(CIRBUF_STR_TAIL))) { - printf("Error: failed to get string from tail!\n"); - return -1; - } - /* verify string */ - if (strncmp(tmp, CIRBUF_STR_TAIL, sizeof(CIRBUF_STR_TAIL)) != 0) { - printf("Error: tail strings do not match!\n"); - return -1; - } - /* delete string from tail */ - if (cirbuf_del_buf_tail(&cb, sizeof(CIRBUF_STR_TAIL)) < 0) { - printf("Error: failed to delete string from tail!\n"); - return -1; - } - /* verify string was deleted */ - if (cirbuf_del_tail_safe(&cb) == 0) { - printf("Error: buffer should have been empty!\n"); - return -1; - } - - return 0; -} - -/* test adding from head and deleting from tail, and vice versa */ -static int -test_cirbuf_string_add_del_reverse(void) -{ - struct cirbuf cb; - char buf[CMDLINE_TEST_BUFSIZE]; - char tmp[CMDLINE_TEST_BUFSIZE]; - - /* initialize buffers */ - memset(buf, 0, sizeof(buf)); - memset(tmp, 0, sizeof(tmp)); - - /* - * initialize circular buffer - */ - if (cirbuf_init(&cb, buf, 0, sizeof(buf)) < 0) { - printf("Error: failed to initialize circular buffer!\n"); - return -1; - } - - /* add string to head */ - if (cirbuf_add_buf_head(&cb, CIRBUF_STR_HEAD, sizeof(CIRBUF_STR_HEAD)) - != (sizeof(CIRBUF_STR_HEAD))) { - printf("Error: failed to add string to head!\n"); - return -1; - } - /* delete string from tail */ - if (cirbuf_del_buf_tail(&cb, sizeof(CIRBUF_STR_HEAD)) < 0) { - printf("Error: failed to delete string from tail!\n"); - return -1; - } - /* verify string was deleted */ - if (cirbuf_del_tail_safe(&cb) == 0) { - printf("Error: buffer should have been empty!\n"); - return -1; - } - /* clear tmp buffer */ - memset(tmp, 0, sizeof(tmp)); - - /* - * reinitialize circular buffer - */ - memset(buf, 0, sizeof(buf)); - if (cirbuf_init(&cb, buf, 0, sizeof(buf)) < 0) { - printf("Error: failed to reinitialize circular buffer!\n"); - return -1; - } - - /* add string to tail */ - if (cirbuf_add_buf_tail(&cb, CIRBUF_STR_TAIL, sizeof(CIRBUF_STR_TAIL)) - != (sizeof(CIRBUF_STR_TAIL))) { - printf("Error: failed to add string to tail!\n"); - return -1; - } - /* delete string from head */ - if (cirbuf_del_buf_head(&cb, sizeof(CIRBUF_STR_TAIL)) < 0) { - printf("Error: failed to delete string from head!\n"); - return -1; - } - /* verify string was deleted */ - if (cirbuf_del_head_safe(&cb) == 0) { - printf("Error: buffer should have been empty!\n"); - return -1; - } - - return 0; -} - -/* try to write more than available */ -static int -test_cirbuf_string_add_boundaries(void) -{ - struct cirbuf cb; - char buf[CMDLINE_TEST_BUFSIZE]; - unsigned i; - - /* initialize buffers */ - memset(buf, 0, sizeof(buf)); - - /* - * initialize circular buffer - */ - if (cirbuf_init(&cb, buf, 0, sizeof(buf)) < 0) { - printf("Error: failed to initialize circular buffer!\n"); - return -1; - } - - /* fill the buffer from tail */ - for (i = 0; i < CMDLINE_TEST_BUFSIZE - sizeof(CIRBUF_STR_TAIL) + 1; i++) - cirbuf_add_tail_safe(&cb, 't'); - - /* try adding a string to tail */ - if (cirbuf_add_buf_tail(&cb, CIRBUF_STR_TAIL, sizeof(CIRBUF_STR_TAIL)) - > 0) { - printf("Error: buffer should have been full!\n"); - return -1; - } - /* try adding a string to head */ - if (cirbuf_add_buf_head(&cb, CIRBUF_STR_TAIL, sizeof(CIRBUF_STR_TAIL)) - > 0) { - printf("Error: buffer should have been full!\n"); - return -1; - } - - /* - * reinitialize circular buffer - */ - memset(buf, 0, sizeof(buf)); - if (cirbuf_init(&cb, buf, 0, sizeof(buf)) < 0) { - printf("Error: failed to reinitialize circular buffer!\n"); - return -1; - } - - /* fill the buffer from head */ - for (i = 0; i < CMDLINE_TEST_BUFSIZE - sizeof(CIRBUF_STR_HEAD) + 1; i++) - cirbuf_add_head_safe(&cb, 'h'); - - /* try adding a string to head */ - if (cirbuf_add_buf_head(&cb, CIRBUF_STR_HEAD, sizeof(CIRBUF_STR_HEAD)) - > 0) { - printf("Error: buffer should have been full!\n"); - return -1; - } - /* try adding a string to tail */ - if (cirbuf_add_buf_tail(&cb, CIRBUF_STR_HEAD, sizeof(CIRBUF_STR_HEAD)) - > 0) { - printf("Error: buffer should have been full!\n"); - return -1; - } - - return 0; -} - -/* try to read/delete more than written */ -static int -test_cirbuf_string_get_del_boundaries(void) -{ - struct cirbuf cb; - char buf[CMDLINE_TEST_BUFSIZE]; - char tmp[CMDLINE_TEST_BUFSIZE]; - - /* initialize buffers */ - memset(buf, 0, sizeof(buf)); - memset(tmp, 0, sizeof(tmp)); - - /* - * initialize circular buffer - */ - if (cirbuf_init(&cb, buf, 0, sizeof(buf)) < 0) { - printf("Error: failed to initialize circular buffer!\n"); - return -1; - } - - - /* add string to head */ - if (cirbuf_add_buf_head(&cb, CIRBUF_STR_HEAD, sizeof(CIRBUF_STR_HEAD)) - != (sizeof(CIRBUF_STR_HEAD))) { - printf("Error: failed to add string to head!\n"); - return -1; - } - /* read more than written (head) */ - if (cirbuf_get_buf_head(&cb, tmp, sizeof(CIRBUF_STR_HEAD) + 1) - != sizeof(CIRBUF_STR_HEAD)) { - printf("Error: unexpected result when reading too much data!\n"); - return -1; - } - /* read more than written (tail) */ - if (cirbuf_get_buf_tail(&cb, tmp, sizeof(CIRBUF_STR_HEAD) + 1) - != sizeof(CIRBUF_STR_HEAD)) { - printf("Error: unexpected result when reading too much data!\n"); - return -1; - } - /* delete more than written (head) */ - if (cirbuf_del_buf_head(&cb, sizeof(CIRBUF_STR_HEAD) + 1) == 0) { - printf("Error: unexpected result when deleting too much data!\n"); - return -1; - } - /* delete more than written (tail) */ - if (cirbuf_del_buf_tail(&cb, sizeof(CIRBUF_STR_HEAD) + 1) == 0) { - printf("Error: unexpected result when deleting too much data!\n"); - return -1; - } - - /* - * reinitialize circular buffer - */ - memset(buf, 0, sizeof(buf)); - if (cirbuf_init(&cb, buf, 0, sizeof(buf)) < 0) { - printf("Error: failed to reinitialize circular buffer!\n"); - return -1; - } - - /* add string to tail */ - if (cirbuf_add_buf_tail(&cb, CIRBUF_STR_TAIL, sizeof(CIRBUF_STR_TAIL)) - != (sizeof(CIRBUF_STR_TAIL))) { - printf("Error: failed to add string to tail!\n"); - return -1; - } - /* read more than written (tail) */ - if (cirbuf_get_buf_tail(&cb, tmp, sizeof(CIRBUF_STR_TAIL) + 1) - != sizeof(CIRBUF_STR_TAIL)) { - printf("Error: unexpected result when reading too much data!\n"); - return -1; - } - /* read more than written (head) */ - if (cirbuf_get_buf_head(&cb, tmp, sizeof(CIRBUF_STR_TAIL) + 1) - != sizeof(CIRBUF_STR_TAIL)) { - printf("Error: unexpected result when reading too much data!\n"); - return -1; - } - /* delete more than written (tail) */ - if (cirbuf_del_buf_tail(&cb, sizeof(CIRBUF_STR_TAIL) + 1) == 0) { - printf("Error: unexpected result when deleting too much data!\n"); - return -1; - } - /* delete more than written (head) */ - if (cirbuf_del_buf_tail(&cb, sizeof(CIRBUF_STR_TAIL) + 1) == 0) { - printf("Error: unexpected result when deleting too much data!\n"); - return -1; - } - - return 0; -} - -/* try to read/delete less than written */ -static int -test_cirbuf_string_get_del_partial(void) -{ - struct cirbuf cb; - char buf[CMDLINE_TEST_BUFSIZE]; - char tmp[CMDLINE_TEST_BUFSIZE]; - char tmp2[CMDLINE_TEST_BUFSIZE]; - - /* initialize buffers */ - memset(buf, 0, sizeof(buf)); - memset(tmp, 0, sizeof(tmp)); - memset(tmp2, 0, sizeof(tmp)); - - snprintf(tmp2, sizeof(tmp2), "%s", CIRBUF_STR_HEAD); - - /* - * initialize circular buffer - */ - if (cirbuf_init(&cb, buf, 0, sizeof(buf)) < 0) { - printf("Error: failed to initialize circular buffer!\n"); - return -1; - } - - /* add string to head */ - if (cirbuf_add_buf_head(&cb, CIRBUF_STR_HEAD, sizeof(CIRBUF_STR_HEAD)) - != (sizeof(CIRBUF_STR_HEAD))) { - printf("Error: failed to add string to head!\n"); - return -1; - } - /* read less than written (head) */ - if (cirbuf_get_buf_head(&cb, tmp, sizeof(CIRBUF_STR_HEAD) - 1) - != sizeof(CIRBUF_STR_HEAD) - 1) { - printf("Error: unexpected result when reading from head!\n"); - return -1; - } - /* verify string */ - if (strncmp(tmp, tmp2, sizeof(CIRBUF_STR_HEAD) - 1) != 0) { - printf("Error: strings mismatch!\n"); - return -1; - } - memset(tmp, 0, sizeof(tmp)); - /* read less than written (tail) */ - if (cirbuf_get_buf_tail(&cb, tmp, sizeof(CIRBUF_STR_HEAD) - 1) - != sizeof(CIRBUF_STR_HEAD) - 1) { - printf("Error: unexpected result when reading from tail!\n"); - return -1; - } - /* verify string */ - if (strncmp(tmp, &tmp2[1], sizeof(CIRBUF_STR_HEAD) - 1) != 0) { - printf("Error: strings mismatch!\n"); - return -1; - } - - /* - * verify correct deletion - */ - - /* clear buffer */ - memset(tmp, 0, sizeof(tmp)); - - /* delete less than written (head) */ - if (cirbuf_del_buf_head(&cb, 1) != 0) { - printf("Error: delete from head failed!\n"); - return -1; - } - /* read from head */ - if (cirbuf_get_buf_head(&cb, tmp, sizeof(CIRBUF_STR_HEAD) - 1) - != sizeof(CIRBUF_STR_HEAD) - 1) { - printf("Error: unexpected result when reading from head!\n"); - return -1; - } - /* since we deleted from head, first char should be deleted */ - if (strncmp(tmp, &tmp2[1], sizeof(CIRBUF_STR_HEAD) - 1) != 0) { - printf("Error: strings mismatch!\n"); - return -1; - } - /* clear buffer */ - memset(tmp, 0, sizeof(tmp)); - - /* delete less than written (tail) */ - if (cirbuf_del_buf_tail(&cb, 1) != 0) { - printf("Error: delete from tail failed!\n"); - return -1; - } - /* read from tail */ - if (cirbuf_get_buf_tail(&cb, tmp, sizeof(CIRBUF_STR_HEAD) - 2) - != sizeof(CIRBUF_STR_HEAD) - 2) { - printf("Error: unexpected result when reading from head!\n"); - return -1; - } - /* since we deleted from tail, last char should be deleted */ - if (strncmp(tmp, &tmp2[1], sizeof(CIRBUF_STR_HEAD) - 2) != 0) { - printf("Error: strings mismatch!\n"); - return -1; - } - - return 0; -} - -/* test cmdline_cirbuf char add/del functions */ -static int -test_cirbuf_char_add_del(void) -{ - struct cirbuf cb; - char buf[CMDLINE_TEST_BUFSIZE]; - char tmp[CMDLINE_TEST_BUFSIZE]; - - /* clear buffer */ - memset(buf, 0, sizeof(buf)); - memset(tmp, 0, sizeof(tmp)); - - /* - * initialize circular buffer - */ - if (cirbuf_init(&cb, buf, 0, sizeof(buf)) < 0) { - printf("Error: failed to initialize circular buffer!\n"); - return -1; - } - - /* - * try to delete something from cirbuf. since it's empty, - * these should fail. - */ - if (cirbuf_del_head_safe(&cb) == 0) { - printf("Error: deleting from empty cirbuf head succeeded!\n"); - return -1; - } - if (cirbuf_del_tail_safe(&cb) == 0) { - printf("Error: deleting from empty cirbuf tail succeeded!\n"); - return -1; - } - - /* - * add, verify and delete. these should pass. - */ - if (cirbuf_add_head_safe(&cb,'h') < 0) { - printf("Error: adding to cirbuf head failed!\n"); - return -1; - } - if (cirbuf_get_head(&cb) != 'h') { - printf("Error: wrong head content!\n"); - return -1; - } - if (cirbuf_del_head_safe(&cb) < 0) { - printf("Error: deleting from cirbuf head failed!\n"); - return -1; - } - if (cirbuf_add_tail_safe(&cb,'t') < 0) { - printf("Error: adding to cirbuf tail failed!\n"); - return -1; - } - if (cirbuf_get_tail(&cb) != 't') { - printf("Error: wrong tail content!\n"); - return -1; - } - if (cirbuf_del_tail_safe(&cb) < 0) { - printf("Error: deleting from cirbuf tail failed!\n"); - return -1; - } - /* do the same for unsafe versions. those are void. */ - cirbuf_add_head(&cb,'h'); - if (cirbuf_get_head(&cb) != 'h') { - printf("Error: wrong head content!\n"); - return -1; - } - cirbuf_del_head(&cb); - - /* test if char has been deleted. we can't call cirbuf_get_head - * because it's unsafe, but we can call cirbuf_get_buf_head. - */ - if (cirbuf_get_buf_head(&cb, tmp, 1) > 0) { - printf("Error: buffer should have been empty!\n"); - return -1; - } - - cirbuf_add_tail(&cb,'t'); - if (cirbuf_get_tail(&cb) != 't') { - printf("Error: wrong tail content!\n"); - return -1; - } - cirbuf_del_tail(&cb); - - /* test if char has been deleted. we can't call cirbuf_get_tail - * because it's unsafe, but we can call cirbuf_get_buf_tail. - */ - if (cirbuf_get_buf_tail(&cb, tmp, 1) > 0) { - printf("Error: buffer should have been empty!\n"); - return -1; - } - - return 0; -} - -/* test filling up buffer with chars */ -static int -test_cirbuf_char_fill(void) -{ - struct cirbuf cb; - char buf[CMDLINE_TEST_BUFSIZE]; - unsigned i; - - /* clear buffer */ - memset(buf, 0, sizeof(buf)); - - /* - * initialize circular buffer - */ - if (cirbuf_init(&cb, buf, 0, sizeof(buf)) < 0) { - printf("Error: failed to initialize circular buffer!\n"); - return -1; - } - - /* - * fill the buffer from head or tail, verify contents, test boundaries - * and clear the buffer - */ - - /* fill the buffer from tail */ - for (i = 0; i < CMDLINE_TEST_BUFSIZE; i++) - cirbuf_add_tail_safe(&cb, 't'); - /* verify that contents of the buffer are what they are supposed to be */ - for (i = 0; i < sizeof(buf); i++) { - if (buf[i] != 't') { - printf("Error: wrong content in buffer!\n"); - return -1; - } - } - /* try to add to a full buffer from tail */ - if (cirbuf_add_tail_safe(&cb, 't') == 0) { - printf("Error: buffer should have been full!\n"); - return -1; - } - /* try to add to a full buffer from head */ - if (cirbuf_add_head_safe(&cb, 'h') == 0) { - printf("Error: buffer should have been full!\n"); - return -1; - } - /* delete buffer from tail */ - for(i = 0; i < CMDLINE_TEST_BUFSIZE; i++) - cirbuf_del_tail_safe(&cb); - /* try to delete from an empty buffer */ - if (cirbuf_del_tail_safe(&cb) >= 0) { - printf("Error: buffer should have been empty!\n"); - return -1; - } - - /* fill the buffer from head */ - for (i = 0; i < CMDLINE_TEST_BUFSIZE; i++) - cirbuf_add_head_safe(&cb, 'h'); - /* verify that contents of the buffer are what they are supposed to be */ - for (i = 0; i < sizeof(buf); i++) { - if (buf[i] != 'h') { - printf("Error: wrong content in buffer!\n"); - return -1; - } - } - /* try to add to a full buffer from head */ - if (cirbuf_add_head_safe(&cb,'h') >= 0) { - printf("Error: buffer should have been full!\n"); - return -1; - } - /* try to add to a full buffer from tail */ - if (cirbuf_add_tail_safe(&cb, 't') == 0) { - printf("Error: buffer should have been full!\n"); - return -1; - } - /* delete buffer from head */ - for(i = 0; i < CMDLINE_TEST_BUFSIZE; i++) - cirbuf_del_head_safe(&cb); - /* try to delete from an empty buffer */ - if (cirbuf_del_head_safe(&cb) >= 0) { - printf("Error: buffer should have been empty!\n"); - return -1; - } - - /* - * fill the buffer from both head and tail, with alternating characters, - * verify contents and clear the buffer - */ - - /* fill half of buffer from tail */ - for (i = 0; i < CMDLINE_TEST_BUFSIZE / 2; i++) - cirbuf_add_tail_safe(&cb, (char) (i % 2 ? 't' : 'T')); - /* fill other half of the buffer from head */ - for (i = 0; i < CMDLINE_TEST_BUFSIZE / 2; i++) - cirbuf_add_head_safe(&cb, (char) (i % 2 ? 'H' : 'h')); /* added in reverse */ - - /* verify that contents of the buffer are what they are supposed to be */ - for (i = 0; i < sizeof(buf) / 2; i++) { - if (buf[i] != (char) (i % 2 ? 't' : 'T')) { - printf("Error: wrong content in buffer at %u!\n", i); - return -1; - } - } - for (i = sizeof(buf) / 2; i < sizeof(buf); i++) { - if (buf[i] != (char) (i % 2 ? 'h' : 'H')) { - printf("Error: wrong content in buffer %u!\n", i); - return -1; - } - } - - return 0; -} - -/* test left alignment */ -static int -test_cirbuf_align_left(void) -{ -#define HALF_OFFSET CMDLINE_TEST_BUFSIZE / 2 -#define SMALL_OFFSET HALF_OFFSET / 2 -/* resulting buffer lengths for each of the test cases */ -#define LEN1 HALF_OFFSET - SMALL_OFFSET - 1 -#define LEN2 HALF_OFFSET + SMALL_OFFSET + 2 -#define LEN3 HALF_OFFSET - SMALL_OFFSET -#define LEN4 HALF_OFFSET + SMALL_OFFSET - 1 - - struct cirbuf cb; - char buf[CMDLINE_TEST_BUFSIZE]; - char tmp[CMDLINE_TEST_BUFSIZE]; - unsigned i; - - /* - * align left when start < end and start in left half - */ - - /* - * initialize circular buffer - */ - memset(buf, 0, sizeof(buf)); - if (cirbuf_init(&cb, buf, 0, sizeof(buf)) < 0) { - printf("Error: failed to initialize circular buffer!\n"); - return -1; - } - - /* push end into left half */ - for (i = 0; i < HALF_OFFSET - 1; i++) - cirbuf_add_tail_safe(&cb, 't'); - - /* push start into left half < end */ - for (i = 0; i < SMALL_OFFSET; i++) - cirbuf_del_head_safe(&cb); - - /* align */ - if (cirbuf_align_left(&cb) < 0) { - printf("Error: alignment failed!\n"); - return -1; - } - - /* verify result */ - if (cb.start != 0 || cb.len != LEN1 || cb.end != cb.len - 1) { - printf("Error: buffer alignment is wrong!\n"); - return -1; - } - - /* - * align left when start > end and start in left half - */ - - /* - * reinitialize circular buffer - */ - memset(buf, 0, sizeof(buf)); - if (cirbuf_init(&cb, buf, 0, sizeof(buf)) < 0) { - printf("Error: failed to reinitialize circular buffer!\n"); - return -1; - } - - /* push start into left half */ - for (i = 0; i < HALF_OFFSET + 2; i++) - cirbuf_add_head_safe(&cb, 'h'); - - /* push end into left half > start */ - for (i = 0; i < SMALL_OFFSET; i++) - cirbuf_add_tail_safe(&cb, 't'); - - /* align */ - if (cirbuf_align_left(&cb) < 0) { - printf("Error: alignment failed!\n"); - return -1; - } - - /* verify result */ - if (cb.start != 0 || cb.len != LEN2 || cb.end != cb.len - 1) { - printf("Error: buffer alignment is wrong!"); - return -1; - } - - /* - * align left when start < end and start in right half - */ - - /* - * reinitialize circular buffer - */ - memset(buf, 0, sizeof(buf)); - if (cirbuf_init(&cb, buf, 0, sizeof(buf)) < 0) { - printf("Error: failed to reinitialize circular buffer!\n"); - return -1; - } - - /* push start into the right half */ - for (i = 0; i < HALF_OFFSET; i++) - cirbuf_add_head_safe(&cb, 'h'); - - /* push end into left half > start */ - for (i = 0; i < SMALL_OFFSET; i++) - cirbuf_del_tail_safe(&cb); - - /* align */ - if (cirbuf_align_left(&cb) < 0) { - printf("Error: alignment failed!\n"); - return -1; - } - - /* verify result */ - if (cb.start != 0 || cb.len != LEN3 || cb.end != cb.len - 1) { - printf("Error: buffer alignment is wrong!"); - return -1; - } - - /* - * align left when start > end and start in right half - */ - - /* - * reinitialize circular buffer - */ - memset(buf, 0, sizeof(buf)); - if (cirbuf_init(&cb, buf, 0, sizeof(buf)) < 0) { - printf("Error: failed to reinitialize circular buffer!\n"); - return -1; - } - - /* push start into the right half */ - for (i = 0; i < HALF_OFFSET - 1; i++) - cirbuf_add_head_safe(&cb, 'h'); - - /* push end into left half < start */ - for (i = 0; i < SMALL_OFFSET; i++) - cirbuf_add_tail_safe(&cb, 't'); - - /* align */ - if (cirbuf_align_left(&cb) < 0) { - printf("Error: alignment failed!\n"); - return -1; - } - - /* verify result */ - if (cb.start != 0 || cb.len != LEN4 || - cb.end != cb.len - 1) { - printf("Error: buffer alignment is wrong!"); - return -1; - } - - /* - * Verify that alignment doesn't corrupt data - */ - - /* - * reinitialize circular buffer - */ - memset(buf, 0, sizeof(buf)); - if (cirbuf_init(&cb, buf, 0, sizeof(buf)) < 0) { - printf("Error: failed to reinitialize circular buffer!\n"); - return -1; - } - - /* add string to tail and head */ - if (cirbuf_add_buf_head(&cb, CIRBUF_STR_HEAD, - sizeof(CIRBUF_STR_HEAD)) < 0 || cirbuf_add_buf_tail(&cb, - CIRBUF_STR_TAIL, sizeof(CIRBUF_STR_TAIL)) < 0) { - printf("Error: failed to add strings!\n"); - return -1; - } - - /* align */ - if (cirbuf_align_left(&cb) < 0) { - printf("Error: alignment failed!\n"); - return -1; - } - - /* get string from head */ - if (cirbuf_get_buf_head(&cb, tmp, - sizeof(CIRBUF_STR_HEAD) + sizeof(CIRBUF_STR_TAIL)) < 0) { - printf("Error: failed to read string from head!\n"); - return -1; - } - - /* verify string */ - if (strncmp(tmp, CIRBUF_STR_HEAD "\0" CIRBUF_STR_TAIL, - sizeof(CIRBUF_STR_HEAD) + sizeof(CIRBUF_STR_TAIL)) != 0) { - printf("Error: strings mismatch!\n"); - return -1; - } - - /* reset tmp buffer */ - memset(tmp, 0, sizeof(tmp)); - - /* get string from tail */ - if (cirbuf_get_buf_tail(&cb, tmp, - sizeof(CIRBUF_STR_HEAD) + sizeof(CIRBUF_STR_TAIL)) < 0) { - printf("Error: failed to read string from head!\n"); - return -1; - } - - /* verify string */ - if (strncmp(tmp, CIRBUF_STR_HEAD "\0" CIRBUF_STR_TAIL, - sizeof(CIRBUF_STR_HEAD) + sizeof(CIRBUF_STR_TAIL)) != 0) { - printf("Error: strings mismatch!\n"); - return -1; - } - - return 0; -} - -/* test right alignment */ -static int -test_cirbuf_align_right(void) -{ -#define END_OFFSET CMDLINE_TEST_BUFSIZE - 1 - struct cirbuf cb; - char buf[CMDLINE_TEST_BUFSIZE]; - char tmp[CMDLINE_TEST_BUFSIZE]; - unsigned i; - - - /* - * align right when start < end and start in left half - */ - - /* - * initialize circular buffer - */ - memset(buf, 0, sizeof(buf)); - if (cirbuf_init(&cb, buf, 0, sizeof(buf)) < 0) { - printf("Error: failed to initialize circular buffer!\n"); - return -1; - } - - /* push end into left half */ - for (i = 0; i < HALF_OFFSET - 1; i++) - cirbuf_add_tail_safe(&cb, 't'); - - /* push start into left half < end */ - for (i = 0; i < SMALL_OFFSET; i++) - cirbuf_del_head_safe(&cb); - - /* align */ - cirbuf_align_right(&cb); - - /* verify result */ - if (cb.start != END_OFFSET || cb.len != LEN1 || cb.end != cb.len - 2) { - printf("Error: buffer alignment is wrong!\n"); - return -1; - } - - /* - * align right when start > end and start in left half - */ - - /* - * reinitialize circular buffer - */ - memset(buf, 0, sizeof(buf)); - if (cirbuf_init(&cb, buf, 0, sizeof(buf)) < 0) { - printf("Error: failed to reinitialize circular buffer!\n"); - return -1; - } - - /* push start into left half */ - for (i = 0; i < HALF_OFFSET + 2; i++) - cirbuf_add_head_safe(&cb, 'h'); - - /* push end into left half > start */ - for (i = 0; i < SMALL_OFFSET; i++) - cirbuf_add_tail_safe(&cb, 't'); - - /* align */ - cirbuf_align_right(&cb); - - /* verify result */ - if (cb.start != END_OFFSET || cb.len != LEN2 || cb.end != cb.len - 2) { - printf("Error: buffer alignment is wrong!"); - return -1; - } - - /* - * align right when start < end and start in right half - */ - - /* - * reinitialize circular buffer - */ - memset(buf, 0, sizeof(buf)); - if (cirbuf_init(&cb, buf, 0, sizeof(buf)) < 0) { - printf("Error: failed to reinitialize circular buffer!\n"); - return -1; - } - - /* push start into the right half */ - for (i = 0; i < HALF_OFFSET; i++) - cirbuf_add_head_safe(&cb, 'h'); - - /* push end into left half > start */ - for (i = 0; i < SMALL_OFFSET; i++) - cirbuf_del_tail_safe(&cb); - - /* align */ - cirbuf_align_right(&cb); - - /* verify result */ - if (cb.end != END_OFFSET || cb.len != LEN3 || cb.start != cb.end - cb.len + 1) { - printf("Error: buffer alignment is wrong!"); - return -1; - } - - /* - * align right when start > end and start in right half - */ - - /* - * reinitialize circular buffer - */ - memset(buf, 0, sizeof(buf)); - if (cirbuf_init(&cb, buf, 0, sizeof(buf)) < 0) { - printf("Error: failed to reinitialize circular buffer!\n"); - return -1; - } - - /* push start into the right half */ - for (i = 0; i < HALF_OFFSET - 1; i++) - cirbuf_add_head_safe(&cb, 'h'); - - /* push end into left half < start */ - for (i = 0; i < SMALL_OFFSET; i++) - cirbuf_add_tail_safe(&cb, 't'); - - /* align */ - cirbuf_align_right(&cb); - - /* verify result */ - if (cb.end != END_OFFSET || cb.len != LEN4 || cb.start != cb.end - cb.len + 1) { - printf("Error: buffer alignment is wrong!"); - return -1; - } - - /* - * Verify that alignment doesn't corrupt data - */ - - /* - * reinitialize circular buffer - */ - memset(buf, 0, sizeof(buf)); - if (cirbuf_init(&cb, buf, 0, sizeof(buf)) < 0) { - printf("Error: failed to reinitialize circular buffer!\n"); - return -1; - } - - /* add string to tail and head */ - if (cirbuf_add_buf_tail(&cb, CIRBUF_STR_TAIL, - sizeof(CIRBUF_STR_TAIL)) < 0 || cirbuf_add_buf_head(&cb, - CIRBUF_STR_HEAD, sizeof(CIRBUF_STR_HEAD)) < 0) { - printf("Error: failed to add strings!\n"); - return -1; - } - - /* align */ - if (cirbuf_align_right(&cb) < 0) { - printf("Error: alignment failed!\n"); - return -1; - } - - /* get string from head */ - if (cirbuf_get_buf_head(&cb, tmp, - sizeof(CIRBUF_STR_HEAD) + sizeof(CIRBUF_STR_TAIL)) < 0) { - printf("Error: failed to read string from head!\n"); - return -1; - } - - /* verify string */ - if (strncmp(tmp, CIRBUF_STR_HEAD "\0" CIRBUF_STR_TAIL, - sizeof(CIRBUF_STR_HEAD) + sizeof(CIRBUF_STR_TAIL)) != 0) { - printf("Error: strings mismatch!\n"); - return -1; - } - - /* reset tmp buffer */ - memset(tmp, 0, sizeof(tmp)); - - /* get string from tail */ - if (cirbuf_get_buf_tail(&cb, tmp, - sizeof(CIRBUF_STR_HEAD) + sizeof(CIRBUF_STR_TAIL)) < 0) { - printf("Error: failed to read string from head!\n"); - return -1; - } - /* verify string */ - if (strncmp(tmp, CIRBUF_STR_HEAD "\0" CIRBUF_STR_TAIL, - sizeof(CIRBUF_STR_HEAD) + sizeof(CIRBUF_STR_TAIL)) != 0) { - printf("Error: strings mismatch!\n"); - return -1; - } - - return 0; -} - -/* call functions with invalid parameters */ -int -test_cirbuf_invalid_param(void) -{ - struct cirbuf cb; - char buf[CMDLINE_TEST_BUFSIZE]; - - /* null cirbuf */ - if (cirbuf_init(0, buf, 0, sizeof(buf)) == 0) - return -1; - /* null buffer */ - if (cirbuf_init(&cb, 0, 0, sizeof(buf)) == 0) - return -1; - /* null cirbuf */ - if (cirbuf_add_head_safe(0, 'h') == 0) - return -1; - if (cirbuf_add_tail_safe(0, 't') == 0) - return -1; - if (cirbuf_del_head_safe(0) == 0) - return -1; - if (cirbuf_del_tail_safe(0) == 0) - return -1; - /* null buffer */ - if (cirbuf_add_buf_head(&cb, 0, 0) == 0) - return -1; - if (cirbuf_add_buf_tail(&cb, 0, 0) == 0) - return -1; - /* null cirbuf */ - if (cirbuf_add_buf_head(0, buf, 0) == 0) - return -1; - if (cirbuf_add_buf_tail(0, buf, 0) == 0) - return -1; - /* null size */ - if (cirbuf_add_buf_head(&cb, buf, 0) == 0) - return -1; - if (cirbuf_add_buf_tail(&cb, buf, 0) == 0) - return -1; - /* null cirbuf */ - if (cirbuf_del_buf_head(0, 0) == 0) - return -1; - if (cirbuf_del_buf_tail(0, 0) == 0) - return -1; - /* null size */ - if (cirbuf_del_buf_head(&cb, 0) == 0) - return -1; - if (cirbuf_del_buf_tail(&cb, 0) == 0) - return -1; - /* null cirbuf */ - if (cirbuf_get_buf_head(0, 0, 0) == 0) - return -1; - if (cirbuf_get_buf_tail(0, 0, 0) == 0) - return -1; - /* null buffer */ - if (cirbuf_get_buf_head(&cb, 0, 0) == 0) - return -1; - if (cirbuf_get_buf_tail(&cb, 0, 0) == 0) - return -1; - /* null size, this is valid but should return 0 */ - if (cirbuf_get_buf_head(&cb, buf, 0) != 0) - return -1; - if (cirbuf_get_buf_tail(&cb, buf, 0) != 0) - return -1; - /* null cirbuf */ - if (cirbuf_align_left(0) == 0) - return -1; - if (cirbuf_align_right(0) == 0) - return -1; - - return 0; -} - -/* test cmdline_cirbuf char functions */ -int -test_cirbuf_char(void) -{ - int ret; - - ret = test_cirbuf_char_add_del(); - if (ret < 0) - return -1; - - ret = test_cirbuf_char_fill(); - if (ret < 0) - return -1; - - return 0; -} - -/* test cmdline_cirbuf string functions */ -int -test_cirbuf_string(void) -{ - if (test_cirbuf_string_add_del() < 0) - return -1; - - if (test_cirbuf_string_add_del_reverse() < 0) - return -1; - - if (test_cirbuf_string_add_boundaries() < 0) - return -1; - - if (test_cirbuf_string_get_del_boundaries() < 0) - return -1; - - if (test_cirbuf_string_get_del_partial() < 0) - return -1; - - if (test_cirbuf_string_misc() < 0) - return -1; - - return 0; -} - -/* test cmdline_cirbuf align functions */ -int -test_cirbuf_align(void) -{ - if (test_cirbuf_align_left() < 0) - return -1; - if (test_cirbuf_align_right() < 0) - return -1; - return 0; -} diff --git a/test/test/test_cmdline_lib.c b/test/test/test_cmdline_lib.c index 65b823a..93a80d0 100644 --- a/test/test/test_cmdline_lib.c +++ b/test/test/test_cmdline_lib.c @@ -41,8 +41,6 @@ #include <ctype.h> #include <sys/queue.h> -#include <cmdline_vt100.h> -#include <cmdline_rdline.h> #include <cmdline_parse.h> #include <cmdline_socket.h> #include <cmdline.h> @@ -50,113 +48,41 @@ #include "test_cmdline.h" /****************************************************************/ -/* static functions required for some tests */ -static void -valid_buffer(__attribute__((unused))struct rdline *rdl, - __attribute__((unused))const char *buf, - __attribute__((unused)) unsigned int size) -{ -} - -static int -complete_buffer(__attribute__((unused)) struct rdline *rdl, - __attribute__((unused)) const char *buf, - __attribute__((unused)) char *dstbuf, - __attribute__((unused)) unsigned int dstsize, - __attribute__((unused)) int *state) -{ - return 0; -} - -/****************************************************************/ static int test_cmdline_parse_fns(void) { - struct cmdline cl; + struct cmdline *cl; int i = 0; char dst[CMDLINE_TEST_BUFSIZE]; + cl = cmdline_new(NULL, "prompt", 0, 1); + if (!cl) + goto error; if (cmdline_parse(NULL, "buffer") >= 0) goto error; - if (cmdline_parse(&cl, NULL) >= 0) + if (cmdline_parse(cl, NULL) >= 0) goto error; if (cmdline_complete(NULL, "buffer", &i, dst, sizeof(dst)) >= 0) goto error; - if (cmdline_complete(&cl, NULL, &i, dst, sizeof(dst)) >= 0) + if (cmdline_complete(cl, NULL, &i, dst, sizeof(dst)) >= 0) goto error; - if (cmdline_complete(&cl, "buffer", NULL, dst, sizeof(dst)) >= 0) + if (cmdline_complete(cl, "buffer", NULL, dst, sizeof(dst)) >= 0) goto error; - if (cmdline_complete(&cl, "buffer", &i, NULL, sizeof(dst)) >= 0) + if (cmdline_complete(cl, "buffer", &i, NULL, sizeof(dst)) >= 0) goto error; return 0; error: + if (cl) + cmdline_free(cl); printf("Error: function accepted null parameter!\n"); return -1; } static int -test_cmdline_rdline_fns(void) -{ - struct rdline rdl; - rdline_write_char_t *wc = &cmdline_write_char; - rdline_validate_t *v = &valid_buffer; - rdline_complete_t *c = &complete_buffer; - - if (rdline_init(NULL, wc, v, c) >= 0) - goto error; - if (rdline_init(&rdl, NULL, v, c) >= 0) - goto error; - if (rdline_init(&rdl, wc, NULL, c) >= 0) - goto error; - if (rdline_init(&rdl, wc, v, NULL) >= 0) - goto error; - if (rdline_char_in(NULL, 0) >= 0) - goto error; - if (rdline_get_buffer(NULL) != NULL) - goto error; - if (rdline_add_history(NULL, "history") >= 0) - goto error; - if (rdline_add_history(&rdl, NULL) >= 0) - goto error; - if (rdline_get_history_item(NULL, 0) != NULL) - goto error; - - /* void functions */ - rdline_newline(NULL, "prompt"); - rdline_newline(&rdl, NULL); - rdline_stop(NULL); - rdline_quit(NULL); - rdline_restart(NULL); - rdline_redisplay(NULL); - rdline_reset(NULL); - rdline_clear_history(NULL); - - return 0; - -error: - printf("Error: function accepted null parameter!\n"); - return -1; -} - -static int -test_cmdline_vt100_fns(void) -{ - if (vt100_parser(NULL, 0) >= 0) { - printf("Error: function accepted null parameter!\n"); - return -1; - } - - /* void functions */ - vt100_init(NULL); - - return 0; -} - -static int test_cmdline_socket_fns(void) { cmdline_parse_ctx_t ctx; @@ -193,7 +119,7 @@ static int test_cmdline_fns(void) { cmdline_parse_ctx_t ctx; - struct cmdline cl, *tmp; + struct cmdline *tmp; memset(&ctx, 0, sizeof(ctx)); tmp = cmdline_new(&ctx, "test", -1, -1); @@ -206,10 +132,6 @@ test_cmdline_fns(void) goto error; if (cmdline_in(NULL, "buffer", CMDLINE_TEST_BUFSIZE) >= 0) goto error; - if (cmdline_in(&cl, NULL, CMDLINE_TEST_BUFSIZE) >= 0) - goto error; - if (cmdline_write_char(NULL, 0) >= 0) - goto error; /* void functions */ cmdline_set_prompt(NULL, "prompt"); @@ -220,16 +142,6 @@ test_cmdline_fns(void) cmdline_interact(NULL); cmdline_quit(NULL); - /* check if void calls change anything when they should fail */ - cl = *tmp; - - cmdline_printf(&cl, NULL); - if (memcmp(&cl, tmp, sizeof(cl))) goto mismatch; - cmdline_set_prompt(&cl, NULL); - if (memcmp(&cl, tmp, sizeof(cl))) goto mismatch; - cmdline_in(&cl, NULL, CMDLINE_TEST_BUFSIZE); - if (memcmp(&cl, tmp, sizeof(cl))) goto mismatch; - cmdline_free(tmp); return 0; @@ -237,9 +149,6 @@ test_cmdline_fns(void) error: printf("Error: function accepted null parameter!\n"); return -1; -mismatch: - printf("Error: data changed!\n"); - return -1; } /* test library functions. the point of these tests is not so much to test @@ -251,10 +160,6 @@ test_cmdline_lib(void) { if (test_cmdline_parse_fns() < 0) return -1; - if (test_cmdline_rdline_fns() < 0) - return -1; - if (test_cmdline_vt100_fns() < 0) - return -1; if (test_cmdline_socket_fns() < 0) return -1; if (test_cmdline_fns() < 0) -- 2.1.4 ^ permalink raw reply [flat|nested] 18+ messages in thread
* Re: [dpdk-dev] [RFC] cmdline: rework as a wrapper to libedit 2017-11-09 13:43 [dpdk-dev] [RFC] cmdline: rework as a wrapper to libedit Adrien Mazarguil @ 2017-11-15 4:12 ` Wiles, Keith 2017-11-15 8:04 ` Olivier MATZ 2017-11-16 9:23 ` Adrien Mazarguil 2017-11-16 16:53 ` Jim Thompson 2018-04-17 15:21 ` [dpdk-dev] [PATCH v1] " Adrien Mazarguil 2 siblings, 2 replies; 18+ messages in thread From: Wiles, Keith @ 2017-11-15 4:12 UTC (permalink / raw) To: Adrien Mazarguil Cc: Olivier Matz, Wu, Jingjing, dev, Thomas Monjalon, Yigit, Ferruh > On Nov 9, 2017, at 5:43 AM, Adrien Mazarguil <adrien.mazarguil@6wind.com> wrote: > > This patch removes all code associated with symbols not internally relied > on by other DPDK components, makes struct cmdline opaque and then proceeds > to re-implement the remaining functionality as a wrapper to the editline > library (also known as libedit) [1]. > > Besides adding a new external dependency to its users, its large impact on > librte_cmdline's API/ABI also warrants a major version number bump. > > While librte_cmdline served DPDK well all these years as a small, easy to > use and self-sufficient interactive command-line handler, it started to > show its limits with testpmd's flow (rte_flow) command, which required > support for dynamic tokens and very long commands. > > This is the main motivation behind this rework. Long commands often need to > be displayed on multiple lines, which are not properly supported by > librte_cmdline's limited terminal handling capabilities, resulting in a > rather frustrating user experience. > > Testpmd being one of the main tools used by PMD developers and given flow > command lines won't get any shorter, this issue had to be addressed. > > Three options were considered: > > - Fixing and enhancing librte_cmdline. > > The amount of work necessary to add support for edition on multiple lines > was deemed significant and the result would still have lacked in some > areas, such as working backspace/delete keys in all terminals (i.e. full > termcap support). > > - Making testpmd directly rely on a more capable library. > > All testpmd commands rely on the cmdline_parse interface provided by > librte_cmdline. This approach would have required either a complete > rewrite or importing the missing bits from librte_cmdline to wrap them > around the new library, which naturally led to... > > - Converting librte_cmdline as a wrapper to a more capable library. > > Let's be honest, interactive command line handling isn't what makes DPDK > shine. It's also far removed from its core functionality, but is still > necessary in order to easily implement test and example programs; the > cmdline_parse interface is particularly good at this. > > DPDK actually only relies on cmdline_parse. By removing all the other > unused interfaces, implementing what remains on top of a different > terminal-handling library would be quick and easy. > > This last approach was chosen for the stated reasons. Libedit is > well-known, BSD-licensed, widely available [2], used by many projects, does > everything needed and more [3]. > > This rework results in the following changes: > > - Removed circular buffer management interface for command history > (cmdline_cirbuf.c), command history being handled by libedit. > - Removed raw command-line interpreter (cmdline_rdline.c). > - Removed raw terminal handler (cmdline_vt100.c). > - Removed all test/example code for the above. > - Re-implemented high level interactive and non-interactive command-line > handlers (cmdline.c and cmdline_socket.c) on top of libedit using its > native interface, not its readline compatibility layer. > - Made struct cmdline opaque so that applications relying on librte_cmdline > do not need to include any libedit headers. > - The only visible change for most applications besides being linked to > libedit is they do not have to include cmdline_rdline.h anymore. > > As an added bonus, terminal resizing is now automatically handled. > > In the future, cmdline_parse could use libedit's advanced tokenizer as > well to interpret quoted strings and escape sequences. > I do agree that cmdline is getting pretty old and using libedit is one solution around the long commands, but it has a lot more problems IMO. I do not agree it has severed DPDK well, just look at test-pmd and the hoops people have to jump thru to get a new command or variation of an existing command integrated into test-pmd it is very difficult. Also if you look at the command sets in test-pmd they are very odd in that similar commands can some times be set up completely different as cmdline is too rigid and difficult to use. I had decided to not use the circular buffer code in cmdline as it did have a few problems for what I wanted and decided to write a standard gap buffer scheme used in most editors for lines. I had looked at libedit at one point decided I did not want another dependence for DPDK. I expect even my version does not solve the long line problem, but we can convert to libedit. (and toss my pretty code :-) Fixing the long line problem is a very minor issue compared to everything else wrong with cmdline. I would suggest we look at CLI and improve it instead. We can add libedit to CLI and then finish testing the CLI with test-pmd. The first time I converted test-pmd I did remove and simplify the commands, but I was afraid that would cause a lot of problems for testing and scripts that people have written, but it is possible to fix these problems too. I do not think fixing cmdline is the best answer and working to convert over to CLI is the better answer here. Regards, Keith ^ permalink raw reply [flat|nested] 18+ messages in thread
* Re: [dpdk-dev] [RFC] cmdline: rework as a wrapper to libedit 2017-11-15 4:12 ` Wiles, Keith @ 2017-11-15 8:04 ` Olivier MATZ 2017-11-15 16:31 ` Wiles, Keith 2017-11-16 9:23 ` Adrien Mazarguil 1 sibling, 1 reply; 18+ messages in thread From: Olivier MATZ @ 2017-11-15 8:04 UTC (permalink / raw) To: Wiles, Keith Cc: Adrien Mazarguil, Wu, Jingjing, dev, Thomas Monjalon, Yigit, Ferruh Hi, On Wed, Nov 15, 2017 at 04:12:07AM +0000, Wiles, Keith wrote: > > > > On Nov 9, 2017, at 5:43 AM, Adrien Mazarguil <adrien.mazarguil@6wind.com> wrote: > > > > This patch removes all code associated with symbols not internally relied > > on by other DPDK components, makes struct cmdline opaque and then proceeds > > to re-implement the remaining functionality as a wrapper to the editline > > library (also known as libedit) [1]. > > > > Besides adding a new external dependency to its users, its large impact on > > librte_cmdline's API/ABI also warrants a major version number bump. > > > > While librte_cmdline served DPDK well all these years as a small, easy to > > use and self-sufficient interactive command-line handler, it started to > > show its limits with testpmd's flow (rte_flow) command, which required > > support for dynamic tokens and very long commands. > > > > This is the main motivation behind this rework. Long commands often need to > > be displayed on multiple lines, which are not properly supported by > > librte_cmdline's limited terminal handling capabilities, resulting in a > > rather frustrating user experience. > > > > Testpmd being one of the main tools used by PMD developers and given flow > > command lines won't get any shorter, this issue had to be addressed. > > > > Three options were considered: > > > > - Fixing and enhancing librte_cmdline. > > > > The amount of work necessary to add support for edition on multiple lines > > was deemed significant and the result would still have lacked in some > > areas, such as working backspace/delete keys in all terminals (i.e. full > > termcap support). > > > > - Making testpmd directly rely on a more capable library. > > > > All testpmd commands rely on the cmdline_parse interface provided by > > librte_cmdline. This approach would have required either a complete > > rewrite or importing the missing bits from librte_cmdline to wrap them > > around the new library, which naturally led to... > > > > - Converting librte_cmdline as a wrapper to a more capable library. > > > > Let's be honest, interactive command line handling isn't what makes DPDK > > shine. It's also far removed from its core functionality, but is still > > necessary in order to easily implement test and example programs; the > > cmdline_parse interface is particularly good at this. > > > > DPDK actually only relies on cmdline_parse. By removing all the other > > unused interfaces, implementing what remains on top of a different > > terminal-handling library would be quick and easy. > > > > This last approach was chosen for the stated reasons. Libedit is > > well-known, BSD-licensed, widely available [2], used by many projects, does > > everything needed and more [3]. > > > > This rework results in the following changes: > > > > - Removed circular buffer management interface for command history > > (cmdline_cirbuf.c), command history being handled by libedit. > > - Removed raw command-line interpreter (cmdline_rdline.c). > > - Removed raw terminal handler (cmdline_vt100.c). > > - Removed all test/example code for the above. > > - Re-implemented high level interactive and non-interactive command-line > > handlers (cmdline.c and cmdline_socket.c) on top of libedit using its > > native interface, not its readline compatibility layer. > > - Made struct cmdline opaque so that applications relying on librte_cmdline > > do not need to include any libedit headers. > > - The only visible change for most applications besides being linked to > > libedit is they do not have to include cmdline_rdline.h anymore. > > > > As an added bonus, terminal resizing is now automatically handled. > > > > In the future, cmdline_parse could use libedit's advanced tokenizer as > > well to interpret quoted strings and escape sequences. > > > > I do agree that cmdline is getting pretty old and using libedit is one solution around the long commands, but it has a lot more problems IMO. > > I do not agree it has severed DPDK well, just look at test-pmd and the hoops people have to jump thru to get a new command or variation of an existing command integrated into test-pmd it is very difficult. Also if you look at the command sets in test-pmd they are very odd in that similar commands can some times be set up completely different as cmdline is too rigid and difficult to use. > > I had decided to not use the circular buffer code in cmdline as it did have a few problems for what I wanted and decided to write a standard gap buffer scheme used in most editors for lines. I had looked at libedit at one point decided I did not want another dependence for DPDK. I expect even my version does not solve the long line problem, but we can convert to libedit. (and toss my pretty code :-) > > Fixing the long line problem is a very minor issue compared to everything else wrong with cmdline. I would suggest we look at CLI and improve it instead. We can add libedit to CLI and then finish testing the CLI with test-pmd. The first time I converted test-pmd I did remove and simplify the commands, but I was afraid that would cause a lot of problems for testing and scripts that people have written, but it is possible to fix these problems too. > > > I do not think fixing cmdline is the best answer and working to convert over to CLI is the better answer here. On my side, I think this patch goes in the correct direction: - it solves an issue of the command line library - it replaces a specific dpdk code by a well-known library which is widely used Olivier ^ permalink raw reply [flat|nested] 18+ messages in thread
* Re: [dpdk-dev] [RFC] cmdline: rework as a wrapper to libedit 2017-11-15 8:04 ` Olivier MATZ @ 2017-11-15 16:31 ` Wiles, Keith 0 siblings, 0 replies; 18+ messages in thread From: Wiles, Keith @ 2017-11-15 16:31 UTC (permalink / raw) To: Olivier MATZ Cc: Adrien Mazarguil, Wu, Jingjing, dev, Thomas Monjalon, Yigit, Ferruh > On Nov 15, 2017, at 12:04 AM, Olivier MATZ <olivier.matz@6wind.com> wrote: > > Hi, > > On Wed, Nov 15, 2017 at 04:12:07AM +0000, Wiles, Keith wrote: >> >> >>> On Nov 9, 2017, at 5:43 AM, Adrien Mazarguil <adrien.mazarguil@6wind.com> wrote: >>> >>> This patch removes all code associated with symbols not internally relied >>> on by other DPDK components, makes struct cmdline opaque and then proceeds >>> to re-implement the remaining functionality as a wrapper to the editline >>> library (also known as libedit) [1]. >>> >>> Besides adding a new external dependency to its users, its large impact on >>> librte_cmdline's API/ABI also warrants a major version number bump. >>> >>> While librte_cmdline served DPDK well all these years as a small, easy to >>> use and self-sufficient interactive command-line handler, it started to >>> show its limits with testpmd's flow (rte_flow) command, which required >>> support for dynamic tokens and very long commands. >>> >>> This is the main motivation behind this rework. Long commands often need to >>> be displayed on multiple lines, which are not properly supported by >>> librte_cmdline's limited terminal handling capabilities, resulting in a >>> rather frustrating user experience. >>> >>> Testpmd being one of the main tools used by PMD developers and given flow >>> command lines won't get any shorter, this issue had to be addressed. >>> >>> Three options were considered: >>> >>> - Fixing and enhancing librte_cmdline. >>> >>> The amount of work necessary to add support for edition on multiple lines >>> was deemed significant and the result would still have lacked in some >>> areas, such as working backspace/delete keys in all terminals (i.e. full >>> termcap support). >>> >>> - Making testpmd directly rely on a more capable library. >>> >>> All testpmd commands rely on the cmdline_parse interface provided by >>> librte_cmdline. This approach would have required either a complete >>> rewrite or importing the missing bits from librte_cmdline to wrap them >>> around the new library, which naturally led to... >>> >>> - Converting librte_cmdline as a wrapper to a more capable library. >>> >>> Let's be honest, interactive command line handling isn't what makes DPDK >>> shine. It's also far removed from its core functionality, but is still >>> necessary in order to easily implement test and example programs; the >>> cmdline_parse interface is particularly good at this. >>> >>> DPDK actually only relies on cmdline_parse. By removing all the other >>> unused interfaces, implementing what remains on top of a different >>> terminal-handling library would be quick and easy. >>> >>> This last approach was chosen for the stated reasons. Libedit is >>> well-known, BSD-licensed, widely available [2], used by many projects, does >>> everything needed and more [3]. >>> >>> This rework results in the following changes: >>> >>> - Removed circular buffer management interface for command history >>> (cmdline_cirbuf.c), command history being handled by libedit. >>> - Removed raw command-line interpreter (cmdline_rdline.c). >>> - Removed raw terminal handler (cmdline_vt100.c). >>> - Removed all test/example code for the above. >>> - Re-implemented high level interactive and non-interactive command-line >>> handlers (cmdline.c and cmdline_socket.c) on top of libedit using its >>> native interface, not its readline compatibility layer. >>> - Made struct cmdline opaque so that applications relying on librte_cmdline >>> do not need to include any libedit headers. >>> - The only visible change for most applications besides being linked to >>> libedit is they do not have to include cmdline_rdline.h anymore. >>> >>> As an added bonus, terminal resizing is now automatically handled. >>> >>> In the future, cmdline_parse could use libedit's advanced tokenizer as >>> well to interpret quoted strings and escape sequences. >>> >> >> I do agree that cmdline is getting pretty old and using libedit is one solution around the long commands, but it has a lot more problems IMO. >> >> I do not agree it has severed DPDK well, just look at test-pmd and the hoops people have to jump thru to get a new command or variation of an existing command integrated into test-pmd it is very difficult. Also if you look at the command sets in test-pmd they are very odd in that similar commands can some times be set up completely different as cmdline is too rigid and difficult to use. >> >> I had decided to not use the circular buffer code in cmdline as it did have a few problems for what I wanted and decided to write a standard gap buffer scheme used in most editors for lines. I had looked at libedit at one point decided I did not want another dependence for DPDK. I expect even my version does not solve the long line problem, but we can convert to libedit. (and toss my pretty code :-) >> >> Fixing the long line problem is a very minor issue compared to everything else wrong with cmdline. I would suggest we look at CLI and improve it instead. We can add libedit to CLI and then finish testing the CLI with test-pmd. The first time I converted test-pmd I did remove and simplify the commands, but I was afraid that would cause a lot of problems for testing and scripts that people have written, but it is possible to fix these problems too. >> >> >> I do not think fixing cmdline is the best answer and working to convert over to CLI is the better answer here. > > On my side, I think this patch goes in the correct direction: > - it solves an issue of the command line library > - it replaces a specific dpdk code by a well-known library which is widely used We are ignoring the fact we are trying to patch something that is difficult to use and does not create a clean/simple design for the developer. Just patching this with libedit now adds two more dependencies to the DPDK libedit and now ncurses. If we moved to CLI then we can fix the one thing we need fixed is the long command line and not require more dependencies to DPDK. Adding more dependencies to DPDK is going ti cause problems with the distro’s but I assume these are around. In Ubuntu 17.04 I had to pull in libedit and ncurses to use libedit. > > Olivier Regards, Keith ^ permalink raw reply [flat|nested] 18+ messages in thread
* Re: [dpdk-dev] [RFC] cmdline: rework as a wrapper to libedit 2017-11-15 4:12 ` Wiles, Keith 2017-11-15 8:04 ` Olivier MATZ @ 2017-11-16 9:23 ` Adrien Mazarguil 2017-11-16 16:48 ` Wiles, Keith 2017-11-16 17:06 ` Ferruh Yigit 1 sibling, 2 replies; 18+ messages in thread From: Adrien Mazarguil @ 2017-11-16 9:23 UTC (permalink / raw) To: Wiles, Keith Cc: Olivier Matz, Wu, Jingjing, dev, Thomas Monjalon, Yigit, Ferruh Hi Keith, On Wed, Nov 15, 2017 at 04:12:07AM +0000, Wiles, Keith wrote: > > > > On Nov 9, 2017, at 5:43 AM, Adrien Mazarguil <adrien.mazarguil@6wind.com> wrote: > > > > This patch removes all code associated with symbols not internally relied > > on by other DPDK components, makes struct cmdline opaque and then proceeds > > to re-implement the remaining functionality as a wrapper to the editline > > library (also known as libedit) [1]. > > > > Besides adding a new external dependency to its users, its large impact on > > librte_cmdline's API/ABI also warrants a major version number bump. > > > > While librte_cmdline served DPDK well all these years as a small, easy to > > use and self-sufficient interactive command-line handler, it started to > > show its limits with testpmd's flow (rte_flow) command, which required > > support for dynamic tokens and very long commands. > > > > This is the main motivation behind this rework. Long commands often need to > > be displayed on multiple lines, which are not properly supported by > > librte_cmdline's limited terminal handling capabilities, resulting in a > > rather frustrating user experience. > > > > Testpmd being one of the main tools used by PMD developers and given flow > > command lines won't get any shorter, this issue had to be addressed. > > > > Three options were considered: > > > > - Fixing and enhancing librte_cmdline. > > > > The amount of work necessary to add support for edition on multiple lines > > was deemed significant and the result would still have lacked in some > > areas, such as working backspace/delete keys in all terminals (i.e. full > > termcap support). > > > > - Making testpmd directly rely on a more capable library. > > > > All testpmd commands rely on the cmdline_parse interface provided by > > librte_cmdline. This approach would have required either a complete > > rewrite or importing the missing bits from librte_cmdline to wrap them > > around the new library, which naturally led to... > > > > - Converting librte_cmdline as a wrapper to a more capable library. > > > > Let's be honest, interactive command line handling isn't what makes DPDK > > shine. It's also far removed from its core functionality, but is still > > necessary in order to easily implement test and example programs; the > > cmdline_parse interface is particularly good at this. > > > > DPDK actually only relies on cmdline_parse. By removing all the other > > unused interfaces, implementing what remains on top of a different > > terminal-handling library would be quick and easy. > > > > This last approach was chosen for the stated reasons. Libedit is > > well-known, BSD-licensed, widely available [2], used by many projects, does > > everything needed and more [3]. > > > > This rework results in the following changes: > > > > - Removed circular buffer management interface for command history > > (cmdline_cirbuf.c), command history being handled by libedit. > > - Removed raw command-line interpreter (cmdline_rdline.c). > > - Removed raw terminal handler (cmdline_vt100.c). > > - Removed all test/example code for the above. > > - Re-implemented high level interactive and non-interactive command-line > > handlers (cmdline.c and cmdline_socket.c) on top of libedit using its > > native interface, not its readline compatibility layer. > > - Made struct cmdline opaque so that applications relying on librte_cmdline > > do not need to include any libedit headers. > > - The only visible change for most applications besides being linked to > > libedit is they do not have to include cmdline_rdline.h anymore. > > > > As an added bonus, terminal resizing is now automatically handled. > > > > In the future, cmdline_parse could use libedit's advanced tokenizer as > > well to interpret quoted strings and escape sequences. > > > > I do agree that cmdline is getting pretty old and using libedit is one solution around the long commands, but it has a lot more problems IMO. Before going further, I'd like to put emphasis on the fact this RFC is not pushing to retain librte_cmdline over your librte_cli proposal. Rather, it removes about 30% of its code and shifts the blame to an external library without modifying user applications. It started some time ago as a quick hack to improve user experience with the flow command in testpmd using the least amount of time and effort, which I only recently reformatted as a proper RFC in order to get feedback from the community. > I do not agree it has severed DPDK well, just look at test-pmd and the hoops people have to jump thru to get a new command or variation of an existing command integrated into test-pmd it is very difficult. Also if you look at the command sets in test-pmd they are very odd in that similar commands can some times be set up completely different as cmdline is too rigid and difficult to use. Testpmd is indeed messy, but this is not librte_cmdline's fundamental fault in my opinion, more likely the result of using a copy/paste approach to new commands due to lack of time or interest in making things nicer than the bare minimum to validate features. There's no design direction for it hence the lack of uniformity in the command hierarchy. > I had decided to not use the circular buffer code in cmdline as it did have a few problems for what I wanted and decided to write a standard gap buffer scheme used in most editors for lines. I had looked at libedit at one point decided I did not want another dependence for DPDK. I expect even my version does not solve the long line problem, but we can convert to libedit. (and toss my pretty code :-) I'm not sure adding dependencies to DPDK is an issue anymore. Not in the sense "there's so many of them already, no one will notice" but more with the need to focus community efforts a bit more on what DPDK brings that doesn't exist elsewhere. How many DPDK contributors are experts in termcap handling and would care to invest time in this area, compared to say, squeezing the last drop of performance out of their employer's HW? I understand you've invested a lot of effort in this but I think that even if DPDK moves to librte_cli, the switch to libedit will be unavoidable. Keep in mind every time some feature will be requested, someone will raise the question "why not move to libedit instead?" > Fixing the long line problem is a very minor issue compared to everything > else wrong with cmdline. I beg to differ on this point, however the reason may not be obvious if you are not familiar with the flow command (the main reason behind this RFC). You should try it. It basically uses dynamic cmdline_parse tokens and help strings which enables flexible arguments with contextual help (without printing it for hundreds of unrelated commands) and more or less infinite command lines. That was the only sane approach to interface rte_flow. My point is there's already a case today for long lines support, it's not minor given rte_flow is bound to replace a lot of the legacy APIs and associated testpmd commands (flow_director_* to name a few). > I would suggest we look at CLI and improve it instead. We can add libedit to CLI and then finish testing the CLI with test-pmd. The first time I converted test-pmd I did remove and simplify the commands, but I was afraid that would cause a lot of problems for testing and scripts that people have written, but it is possible to fix these problems too. > > I do not think fixing cmdline is the best answer and working to convert over to CLI is the better answer here. In truth I didn't do my homework. Before your reply I completely forgot about the librte_cli proposal and related dpdk-draft-cli tree. It didn't cross my mind to check it out before working on this RFC. I'm now aware of how much effort you put in this and what it takes to reorder and reimplement all testpmd commands. That's huge. It seems like we're fighting unrelated battles though. To summarize: - You don't like librte_cmdline for various reasons and provide librte_cli as an alternative along a testpmd implementation. I assume the goal is to remove librte_cmdline once every application has switched. - I don't mind librte_cmdline, but I don't expect it to grow nor to be used by applications outside test programs in DPDK itself, hence I choose to strip its unused parts and make the rest a wrapper to libedit without modifying applications. Both are not incompatible, and since I think libedit will be unavoidable for librte_cli, my approach can be seen as temporary until something replaces librte_cmdline. In the meantime, users still benefit from much better command line handling at no extra cost. -- Adrien Mazarguil 6WIND ^ permalink raw reply [flat|nested] 18+ messages in thread
* Re: [dpdk-dev] [RFC] cmdline: rework as a wrapper to libedit 2017-11-16 9:23 ` Adrien Mazarguil @ 2017-11-16 16:48 ` Wiles, Keith 2017-11-16 18:07 ` Thomas Monjalon 2017-11-16 17:06 ` Ferruh Yigit 1 sibling, 1 reply; 18+ messages in thread From: Wiles, Keith @ 2017-11-16 16:48 UTC (permalink / raw) To: Adrien Mazarguil Cc: Olivier Matz, Wu, Jingjing, dev, Thomas Monjalon, Yigit, Ferruh > On Nov 16, 2017, at 1:23 AM, Adrien Mazarguil <adrien.mazarguil@6wind.com> wrote: > > Hi Keith, > > On Wed, Nov 15, 2017 at 04:12:07AM +0000, Wiles, Keith wrote: >> >> >>> On Nov 9, 2017, at 5:43 AM, Adrien Mazarguil <adrien.mazarguil@6wind.com> wrote: >>> >>> This patch removes all code associated with symbols not internally relied >>> on by other DPDK components, makes struct cmdline opaque and then proceeds >>> to re-implement the remaining functionality as a wrapper to the editline >>> library (also known as libedit) [1]. >>> >>> Besides adding a new external dependency to its users, its large impact on >>> librte_cmdline's API/ABI also warrants a major version number bump. >>> >>> While librte_cmdline served DPDK well all these years as a small, easy to >>> use and self-sufficient interactive command-line handler, it started to >>> show its limits with testpmd's flow (rte_flow) command, which required >>> support for dynamic tokens and very long commands. >>> >>> This is the main motivation behind this rework. Long commands often need to >>> be displayed on multiple lines, which are not properly supported by >>> librte_cmdline's limited terminal handling capabilities, resulting in a >>> rather frustrating user experience. >>> >>> Testpmd being one of the main tools used by PMD developers and given flow >>> command lines won't get any shorter, this issue had to be addressed. >>> >>> Three options were considered: >>> >>> - Fixing and enhancing librte_cmdline. >>> >>> The amount of work necessary to add support for edition on multiple lines >>> was deemed significant and the result would still have lacked in some >>> areas, such as working backspace/delete keys in all terminals (i.e. full >>> termcap support). >>> >>> - Making testpmd directly rely on a more capable library. >>> >>> All testpmd commands rely on the cmdline_parse interface provided by >>> librte_cmdline. This approach would have required either a complete >>> rewrite or importing the missing bits from librte_cmdline to wrap them >>> around the new library, which naturally led to... >>> >>> - Converting librte_cmdline as a wrapper to a more capable library. >>> >>> Let's be honest, interactive command line handling isn't what makes DPDK >>> shine. It's also far removed from its core functionality, but is still >>> necessary in order to easily implement test and example programs; the >>> cmdline_parse interface is particularly good at this. >>> >>> DPDK actually only relies on cmdline_parse. By removing all the other >>> unused interfaces, implementing what remains on top of a different >>> terminal-handling library would be quick and easy. >>> >>> This last approach was chosen for the stated reasons. Libedit is >>> well-known, BSD-licensed, widely available [2], used by many projects, does >>> everything needed and more [3]. >>> >>> This rework results in the following changes: >>> >>> - Removed circular buffer management interface for command history >>> (cmdline_cirbuf.c), command history being handled by libedit. >>> - Removed raw command-line interpreter (cmdline_rdline.c). >>> - Removed raw terminal handler (cmdline_vt100.c). >>> - Removed all test/example code for the above. >>> - Re-implemented high level interactive and non-interactive command-line >>> handlers (cmdline.c and cmdline_socket.c) on top of libedit using its >>> native interface, not its readline compatibility layer. >>> - Made struct cmdline opaque so that applications relying on librte_cmdline >>> do not need to include any libedit headers. >>> - The only visible change for most applications besides being linked to >>> libedit is they do not have to include cmdline_rdline.h anymore. >>> >>> As an added bonus, terminal resizing is now automatically handled. >>> >>> In the future, cmdline_parse could use libedit's advanced tokenizer as >>> well to interpret quoted strings and escape sequences. >>> >> >> I do agree that cmdline is getting pretty old and using libedit is one solution around the long commands, but it has a lot more problems IMO. > > Before going further, I'd like to put emphasis on the fact this RFC is not > pushing to retain librte_cmdline over your librte_cli proposal. Rather, it > removes about 30% of its code and shifts the blame to an external library > without modifying user applications. > > It started some time ago as a quick hack to improve user experience with the > flow command in testpmd using the least amount of time and effort, which I > only recently reformatted as a proper RFC in order to get feedback from the > community. > >> I do not agree it has severed DPDK well, just look at test-pmd and the hoops people have to jump thru to get a new command or variation of an existing command integrated into test-pmd it is very difficult. Also if you look at the command sets in test-pmd they are very odd in that similar commands can some times be set up completely different as cmdline is too rigid and difficult to use. > > Testpmd is indeed messy, but this is not librte_cmdline's fundamental fault > in my opinion, more likely the result of using a copy/paste approach to new > commands due to lack of time or interest in making things nicer than the > bare minimum to validate features. There's no design direction for it hence > the lack of uniformity in the command hierarchy. > >> I had decided to not use the circular buffer code in cmdline as it did have a few problems for what I wanted and decided to write a standard gap buffer scheme used in most editors for lines. I had looked at libedit at one point decided I did not want another dependence for DPDK. I expect even my version does not solve the long line problem, but we can convert to libedit. (and toss my pretty code :-) > > I'm not sure adding dependencies to DPDK is an issue anymore. Not in the > sense "there's so many of them already, no one will notice" but more with > the need to focus community efforts a bit more on what DPDK brings that > doesn't exist elsewhere. > > How many DPDK contributors are experts in termcap handling and would care to > invest time in this area, compared to say, squeezing the last drop of > performance out of their employer's HW? > > I understand you've invested a lot of effort in this but I think that even > if DPDK moves to librte_cli, the switch to libedit will be unavoidable. > > Keep in mind every time some feature will be requested, someone will raise > the question "why not move to libedit instead?" > >> Fixing the long line problem is a very minor issue compared to everything >> else wrong with cmdline. > > I beg to differ on this point, however the reason may not be obvious if > you are not familiar with the flow command (the main reason behind this > RFC). > > You should try it. It basically uses dynamic cmdline_parse tokens and help > strings which enables flexible arguments with contextual help (without > printing it for hundreds of unrelated commands) and more or less infinite > command lines. That was the only sane approach to interface rte_flow. > > My point is there's already a case today for long lines support, it's not > minor given rte_flow is bound to replace a lot of the legacy APIs and > associated testpmd commands (flow_director_* to name a few). > >> I would suggest we look at CLI and improve it instead. We can add libedit to CLI and then finish testing the CLI with test-pmd. The first time I converted test-pmd I did remove and simplify the commands, but I was afraid that would cause a lot of problems for testing and scripts that people have written, but it is possible to fix these problems too. >> >> I do not think fixing cmdline is the best answer and working to convert over to CLI is the better answer here. > > In truth I didn't do my homework. Before your reply I completely forgot > about the librte_cli proposal and related dpdk-draft-cli tree. It didn't > cross my mind to check it out before working on this RFC. > > I'm now aware of how much effort you put in this and what it takes to > reorder and reimplement all testpmd commands. That's huge. It seems like > we're fighting unrelated battles though. > > To summarize: > > - You don't like librte_cmdline for various reasons and provide librte_cli > as an alternative along a testpmd implementation. I assume the goal is to > remove librte_cmdline once every application has switched. > > - I don't mind librte_cmdline, but I don't expect it to grow nor to be used > by applications outside test programs in DPDK itself, hence I choose to > strip its unused parts and make the rest a wrapper to libedit without > modifying applications. > > Both are not incompatible, and since I think libedit will be unavoidable for > librte_cli, my approach can be seen as temporary until something replaces > librte_cmdline. In the meantime, users still benefit from much better > command line handling at no extra cost. OK, I understand your points and not to state your work was in vain, but it would have been better if we had applied the effort to the CLI. I do not agree per-say that libedit is required for CLI as the only feature we need is to handle long lines and their are easier ways to do then using libedit. I was looking at the problem and I think we can handle long lines without libedit, I will try to put together an example soon. For now we can accept your patch for cmdline as it does add the support without much effort. > > -- > Adrien Mazarguil > 6WIND Regards, Keith ^ permalink raw reply [flat|nested] 18+ messages in thread
* Re: [dpdk-dev] [RFC] cmdline: rework as a wrapper to libedit 2017-11-16 16:48 ` Wiles, Keith @ 2017-11-16 18:07 ` Thomas Monjalon 0 siblings, 0 replies; 18+ messages in thread From: Thomas Monjalon @ 2017-11-16 18:07 UTC (permalink / raw) To: Wiles, Keith Cc: Adrien Mazarguil, Olivier Matz, Wu, Jingjing, dev, Yigit, Ferruh 16/11/2017 17:48, Wiles, Keith: > For now we can accept your patch for cmdline as it does add the support without much effort. I agree. ^ permalink raw reply [flat|nested] 18+ messages in thread
* Re: [dpdk-dev] [RFC] cmdline: rework as a wrapper to libedit 2017-11-16 9:23 ` Adrien Mazarguil 2017-11-16 16:48 ` Wiles, Keith @ 2017-11-16 17:06 ` Ferruh Yigit 2017-11-16 17:27 ` Wiles, Keith 1 sibling, 1 reply; 18+ messages in thread From: Ferruh Yigit @ 2017-11-16 17:06 UTC (permalink / raw) To: Adrien Mazarguil, Wiles, Keith Cc: Olivier Matz, Wu, Jingjing, dev, Thomas Monjalon On 11/16/2017 1:23 AM, Adrien Mazarguil wrote: <...> >> I do not agree it has severed DPDK well, just look at test-pmd and the hoops people have to jump thru to get a new command or variation of an existing command integrated into test-pmd it is very difficult. Also if you look at the command sets in test-pmd they are very odd in that similar commands can some times be set up completely different as cmdline is too rigid and difficult to use. > > Testpmd is indeed messy, but this is not librte_cmdline's fundamental fault > in my opinion, more likely the result of using a copy/paste approach to new > commands due to lack of time or interest in making things nicer than the > bare minimum to validate features. There's no design direction for it hence > the lack of uniformity in the command hierarchy. Unrelated to cmdline discussion +1 for this paragraph. ^ permalink raw reply [flat|nested] 18+ messages in thread
* Re: [dpdk-dev] [RFC] cmdline: rework as a wrapper to libedit 2017-11-16 17:06 ` Ferruh Yigit @ 2017-11-16 17:27 ` Wiles, Keith 2017-11-16 18:05 ` Thomas Monjalon 0 siblings, 1 reply; 18+ messages in thread From: Wiles, Keith @ 2017-11-16 17:27 UTC (permalink / raw) To: Yigit, Ferruh Cc: Adrien Mazarguil, Olivier Matz, Wu, Jingjing, dev, Thomas Monjalon > On Nov 16, 2017, at 9:06 AM, Yigit, Ferruh <ferruh.yigit@intel.com> wrote: > > On 11/16/2017 1:23 AM, Adrien Mazarguil wrote: > <...> > >>> I do not agree it has severed DPDK well, just look at test-pmd and the hoops people have to jump thru to get a new command or variation of an existing command integrated into test-pmd it is very difficult. Also if you look at the command sets in test-pmd they are very odd in that similar commands can some times be set up completely different as cmdline is too rigid and difficult to use. >> >> Testpmd is indeed messy, but this is not librte_cmdline's fundamental fault >> in my opinion, more likely the result of using a copy/paste approach to new >> commands due to lack of time or interest in making things nicer than the >> bare minimum to validate features. There's no design direction for it hence >> the lack of uniformity in the command hierarchy. > > Unrelated to cmdline discussion +1 for this paragraph. As a side note should CLI change the test-pmd commands to be more reasonable or maintain the current commands to not break testing. I would like to fix these commands with CLI, but as I have both built into test-pmd currently we can could keep the old cmdline commands and if you use the new CLI then it would be the new cleaner commands. Regards, Keith ^ permalink raw reply [flat|nested] 18+ messages in thread
* Re: [dpdk-dev] [RFC] cmdline: rework as a wrapper to libedit 2017-11-16 17:27 ` Wiles, Keith @ 2017-11-16 18:05 ` Thomas Monjalon 0 siblings, 0 replies; 18+ messages in thread From: Thomas Monjalon @ 2017-11-16 18:05 UTC (permalink / raw) To: Wiles, Keith Cc: Yigit, Ferruh, Adrien Mazarguil, Olivier Matz, Wu, Jingjing, dev 16/11/2017 18:27, Wiles, Keith: > > > On Nov 16, 2017, at 9:06 AM, Yigit, Ferruh <ferruh.yigit@intel.com> wrote: > > > > On 11/16/2017 1:23 AM, Adrien Mazarguil wrote: > > <...> > > > >>> I do not agree it has severed DPDK well, just look at test-pmd and the hoops people have to jump thru to get a new command or variation of an existing command integrated into test-pmd it is very difficult. Also if you look at the command sets in test-pmd they are very odd in that similar commands can some times be set up completely different as cmdline is too rigid and difficult to use. > >> > >> Testpmd is indeed messy, but this is not librte_cmdline's fundamental fault > >> in my opinion, more likely the result of using a copy/paste approach to new > >> commands due to lack of time or interest in making things nicer than the > >> bare minimum to validate features. There's no design direction for it hence > >> the lack of uniformity in the command hierarchy. > > > > Unrelated to cmdline discussion +1 for this paragraph. > > As a side note should CLI change the test-pmd commands to be more reasonable or maintain the current commands to not break testing. I would like to fix these commands with CLI, but as I have both built into test-pmd currently we can could keep the old cmdline commands and if you use the new CLI then it would be the new cleaner commands. I think we must keep the existing testpmd commands for a while to not disturb people using it integrated in their testing tools. If we introduce a new set of commands, we can define a deadline for removal of old commands. ^ permalink raw reply [flat|nested] 18+ messages in thread
* Re: [dpdk-dev] [RFC] cmdline: rework as a wrapper to libedit 2017-11-09 13:43 [dpdk-dev] [RFC] cmdline: rework as a wrapper to libedit Adrien Mazarguil 2017-11-15 4:12 ` Wiles, Keith @ 2017-11-16 16:53 ` Jim Thompson 2018-04-17 15:21 ` [dpdk-dev] [PATCH v1] " Adrien Mazarguil 2 siblings, 0 replies; 18+ messages in thread From: Jim Thompson @ 2017-11-16 16:53 UTC (permalink / raw) To: Adrien Mazarguil Cc: Olivier Matz, Jingjing Wu, dev, Thomas Monjalon, Ferruh Yigit How does this fit with all the work that Keith Wiles just discussed at DPDK Summit? https://dpdk17.sched.com/event/Cqv3/new-command-line-interface-for-dpdk <https://dpdk17.sched.com/event/Cqv3/new-command-line-interface-for-dpdk> Jim > On Nov 9, 2017, at 7:43 AM, Adrien Mazarguil <adrien.mazarguil@6wind.com> wrote: > > This patch removes all code associated with symbols not internally relied > on by other DPDK components, makes struct cmdline opaque and then proceeds > to re-implement the remaining functionality as a wrapper to the editline > library (also known as libedit) [1]. > > Besides adding a new external dependency to its users, its large impact on > librte_cmdline's API/ABI also warrants a major version number bump. > > While librte_cmdline served DPDK well all these years as a small, easy to > use and self-sufficient interactive command-line handler, it started to > show its limits with testpmd's flow (rte_flow) command, which required > support for dynamic tokens and very long commands. > > This is the main motivation behind this rework. Long commands often need to > be displayed on multiple lines, which are not properly supported by > librte_cmdline's limited terminal handling capabilities, resulting in a > rather frustrating user experience. > > Testpmd being one of the main tools used by PMD developers and given flow > command lines won't get any shorter, this issue had to be addressed. > > Three options were considered: > > - Fixing and enhancing librte_cmdline. > > The amount of work necessary to add support for edition on multiple lines > was deemed significant and the result would still have lacked in some > areas, such as working backspace/delete keys in all terminals (i.e. full > termcap support). > > - Making testpmd directly rely on a more capable library. > > All testpmd commands rely on the cmdline_parse interface provided by > librte_cmdline. This approach would have required either a complete > rewrite or importing the missing bits from librte_cmdline to wrap them > around the new library, which naturally led to... > > - Converting librte_cmdline as a wrapper to a more capable library. > > Let's be honest, interactive command line handling isn't what makes DPDK > shine. It's also far removed from its core functionality, but is still > necessary in order to easily implement test and example programs; the > cmdline_parse interface is particularly good at this. > > DPDK actually only relies on cmdline_parse. By removing all the other > unused interfaces, implementing what remains on top of a different > terminal-handling library would be quick and easy. > > This last approach was chosen for the stated reasons. Libedit is > well-known, BSD-licensed, widely available [2], used by many projects, does > everything needed and more [3]. > > This rework results in the following changes: > > - Removed circular buffer management interface for command history > (cmdline_cirbuf.c), command history being handled by libedit. > - Removed raw command-line interpreter (cmdline_rdline.c). > - Removed raw terminal handler (cmdline_vt100.c). > - Removed all test/example code for the above. > - Re-implemented high level interactive and non-interactive command-line > handlers (cmdline.c and cmdline_socket.c) on top of libedit using its > native interface, not its readline compatibility layer. > - Made struct cmdline opaque so that applications relying on librte_cmdline > do not need to include any libedit headers. > - The only visible change for most applications besides being linked to > libedit is they do not have to include cmdline_rdline.h anymore. > > As an added bonus, terminal resizing is now automatically handled. > > In the future, cmdline_parse could use libedit's advanced tokenizer as > well to interpret quoted strings and escape sequences. > > [1] http://thrysoee.dk/editline/ > [2] It usually goes by the name "libedit" in Linux distributions. > [3] http://netbsd.gw.com/cgi-bin/man-cgi?editline++NetBSD-current > > Signed-off-by: Adrien Mazarguil <adrien.mazarguil@6wind.com> > --- > app/test-pmd/cmdline.c | 1 - > examples/bond/main.c | 1 - > examples/cmdline/commands.c | 1 - > examples/cmdline/main.c | 1 - > .../ip_pipeline/pipeline/pipeline_common_fe.c | 1 - > .../ip_pipeline/pipeline/pipeline_firewall.c | 1 - > .../pipeline/pipeline_flow_actions.c | 1 - > .../pipeline/pipeline_flow_classification.c | 1 - > examples/ip_pipeline/thread_fe.c | 1 - > examples/multi_process/simple_mp/main.c | 1 - > examples/multi_process/simple_mp/mp_commands.c | 1 - > examples/qos_sched/cmdline.c | 1 - > examples/quota_watermark/qwctl/commands.c | 1 - > examples/quota_watermark/qwctl/qwctl.c | 1 - > .../guest_cli/vm_power_cli_guest.c | 1 - > examples/vm_power_manager/vm_power_cli.c | 1 - > lib/librte_cmdline/Makefile | 10 +- > lib/librte_cmdline/cmdline.c | 385 +++-- > lib/librte_cmdline/cmdline.h | 22 +- > lib/librte_cmdline/cmdline_cirbuf.c | 466 ------ > lib/librte_cmdline/cmdline_cirbuf.h | 245 ---- > lib/librte_cmdline/cmdline_parse.c | 7 +- > lib/librte_cmdline/cmdline_rdline.c | 697 --------- > lib/librte_cmdline/cmdline_rdline.h | 255 ---- > lib/librte_cmdline/cmdline_socket.c | 36 +- > lib/librte_cmdline/cmdline_vt100.c | 185 --- > lib/librte_cmdline/cmdline_vt100.h | 153 -- > lib/librte_cmdline/rte_cmdline_version.map | 41 +- > mk/rte.app.mk | 2 + > test/cmdline_test/cmdline_test.c | 1 - > test/cmdline_test/commands.c | 69 - > test/test/Makefile | 1 - > test/test/commands.c | 1 - > test/test/test.c | 1 - > test/test/test_cmdline.c | 9 - > test/test/test_cmdline.h | 6 - > test/test/test_cmdline_cirbuf.c | 1330 ------------------ > test/test/test_cmdline_lib.c | 117 +- > 38 files changed, 293 insertions(+), 3762 deletions(-) > > diff --git a/app/test-pmd/cmdline.c b/app/test-pmd/cmdline.c > index f71d963..9fe625c 100644 > --- a/app/test-pmd/cmdline.c > +++ b/app/test-pmd/cmdline.c > @@ -77,7 +77,6 @@ > #include <rte_flow.h> > #include <rte_gro.h> > > -#include <cmdline_rdline.h> > #include <cmdline_parse.h> > #include <cmdline_parse_num.h> > #include <cmdline_parse_string.h> > diff --git a/examples/bond/main.c b/examples/bond/main.c > index 8e3b1f3..d903314 100644 > --- a/examples/bond/main.c > +++ b/examples/bond/main.c > @@ -71,7 +71,6 @@ > #include <rte_arp.h> > #include <rte_spinlock.h> > > -#include <cmdline_rdline.h> > #include <cmdline_parse.h> > #include <cmdline_parse_num.h> > #include <cmdline_parse_string.h> > diff --git a/examples/cmdline/commands.c b/examples/cmdline/commands.c > index f3ba247..e8fa7f0 100644 > --- a/examples/cmdline/commands.c > +++ b/examples/cmdline/commands.c > @@ -74,7 +74,6 @@ > #endif > #endif > > -#include <cmdline_rdline.h> > #include <cmdline_parse.h> > #include <cmdline_parse_ipaddr.h> > #include <cmdline_parse_num.h> > diff --git a/examples/cmdline/main.c b/examples/cmdline/main.c > index c6de944..c229f50 100644 > --- a/examples/cmdline/main.c > +++ b/examples/cmdline/main.c > @@ -65,7 +65,6 @@ > #include <termios.h> > #include <sys/queue.h> > > -#include <cmdline_rdline.h> > #include <cmdline_parse.h> > #include <cmdline_socket.h> > #include <cmdline.h> > diff --git a/examples/ip_pipeline/pipeline/pipeline_common_fe.c b/examples/ip_pipeline/pipeline/pipeline_common_fe.c > index 7521187..f1df197 100644 > --- a/examples/ip_pipeline/pipeline/pipeline_common_fe.c > +++ b/examples/ip_pipeline/pipeline/pipeline_common_fe.c > @@ -37,7 +37,6 @@ > > #include <rte_common.h> > #include <rte_malloc.h> > -#include <cmdline_rdline.h> > #include <cmdline_parse.h> > #include <cmdline_parse_num.h> > #include <cmdline_parse_string.h> > diff --git a/examples/ip_pipeline/pipeline/pipeline_firewall.c b/examples/ip_pipeline/pipeline/pipeline_firewall.c > index a82e552..e49d9ca 100644 > --- a/examples/ip_pipeline/pipeline/pipeline_firewall.c > +++ b/examples/ip_pipeline/pipeline/pipeline_firewall.c > @@ -41,7 +41,6 @@ > #include <rte_common.h> > #include <rte_hexdump.h> > #include <rte_malloc.h> > -#include <cmdline_rdline.h> > #include <cmdline_parse.h> > #include <cmdline_parse_num.h> > #include <cmdline_parse_string.h> > diff --git a/examples/ip_pipeline/pipeline/pipeline_flow_actions.c b/examples/ip_pipeline/pipeline/pipeline_flow_actions.c > index 349db6b..0f680db 100644 > --- a/examples/ip_pipeline/pipeline/pipeline_flow_actions.c > +++ b/examples/ip_pipeline/pipeline/pipeline_flow_actions.c > @@ -40,7 +40,6 @@ > #include <rte_common.h> > #include <rte_hexdump.h> > #include <rte_malloc.h> > -#include <cmdline_rdline.h> > #include <cmdline_parse.h> > #include <cmdline_parse_num.h> > #include <cmdline_parse_string.h> > diff --git a/examples/ip_pipeline/pipeline/pipeline_flow_classification.c b/examples/ip_pipeline/pipeline/pipeline_flow_classification.c > index 70b1938..b9e4ed5 100644 > --- a/examples/ip_pipeline/pipeline/pipeline_flow_classification.c > +++ b/examples/ip_pipeline/pipeline/pipeline_flow_classification.c > @@ -40,7 +40,6 @@ > #include <rte_common.h> > #include <rte_hexdump.h> > #include <rte_malloc.h> > -#include <cmdline_rdline.h> > #include <cmdline_parse.h> > #include <cmdline_parse_num.h> > #include <cmdline_parse_string.h> > diff --git a/examples/ip_pipeline/thread_fe.c b/examples/ip_pipeline/thread_fe.c > index 4590c2b..4f54094 100644 > --- a/examples/ip_pipeline/thread_fe.c > +++ b/examples/ip_pipeline/thread_fe.c > @@ -1,7 +1,6 @@ > #include <rte_common.h> > #include <rte_ring.h> > #include <rte_malloc.h> > -#include <cmdline_rdline.h> > #include <cmdline_parse.h> > #include <cmdline_parse_num.h> > #include <cmdline_parse_string.h> > diff --git a/examples/multi_process/simple_mp/main.c b/examples/multi_process/simple_mp/main.c > index 62537b0..c0fc6ea 100644 > --- a/examples/multi_process/simple_mp/main.c > +++ b/examples/multi_process/simple_mp/main.c > @@ -64,7 +64,6 @@ > #include <rte_ring.h> > #include <rte_log.h> > #include <rte_mempool.h> > -#include <cmdline_rdline.h> > #include <cmdline_parse.h> > #include <cmdline_parse_string.h> > #include <cmdline_socket.h> > diff --git a/examples/multi_process/simple_mp/mp_commands.c b/examples/multi_process/simple_mp/mp_commands.c > index ef6dc58..264dea2 100644 > --- a/examples/multi_process/simple_mp/mp_commands.c > +++ b/examples/multi_process/simple_mp/mp_commands.c > @@ -54,7 +54,6 @@ > #include <rte_mempool.h> > #include <rte_string_fns.h> > > -#include <cmdline_rdline.h> > #include <cmdline_parse.h> > #include <cmdline_parse_string.h> > #include <cmdline_socket.h> > diff --git a/examples/qos_sched/cmdline.c b/examples/qos_sched/cmdline.c > index b62d165..c2a4f6b 100644 > --- a/examples/qos_sched/cmdline.c > +++ b/examples/qos_sched/cmdline.c > @@ -36,7 +36,6 @@ > #include <inttypes.h> > #include <string.h> > > -#include <cmdline_rdline.h> > #include <cmdline_parse.h> > #include <cmdline_parse_num.h> > #include <cmdline_parse_string.h> > diff --git a/examples/quota_watermark/qwctl/commands.c b/examples/quota_watermark/qwctl/commands.c > index 5cac0e1..a30a35c 100644 > --- a/examples/quota_watermark/qwctl/commands.c > +++ b/examples/quota_watermark/qwctl/commands.c > @@ -36,7 +36,6 @@ > #include <string.h> > #include <termios.h> > > -#include <cmdline_rdline.h> > #include <cmdline_parse.h> > #include <cmdline_parse_num.h> > #include <cmdline_parse_string.h> > diff --git a/examples/quota_watermark/qwctl/qwctl.c b/examples/quota_watermark/qwctl/qwctl.c > index 18ec17a..2831667 100644 > --- a/examples/quota_watermark/qwctl/qwctl.c > +++ b/examples/quota_watermark/qwctl/qwctl.c > @@ -42,7 +42,6 @@ > #include <rte_log.h> > #include <rte_memzone.h> > > -#include <cmdline_rdline.h> > #include <cmdline_parse.h> > #include <cmdline_socket.h> > #include <cmdline.h> > diff --git a/examples/vm_power_manager/guest_cli/vm_power_cli_guest.c b/examples/vm_power_manager/guest_cli/vm_power_cli_guest.c > index 63f711e..83cd215 100644 > --- a/examples/vm_power_manager/guest_cli/vm_power_cli_guest.c > +++ b/examples/vm_power_manager/guest_cli/vm_power_cli_guest.c > @@ -37,7 +37,6 @@ > #include <stdio.h> > #include <termios.h> > > -#include <cmdline_rdline.h> > #include <cmdline_parse.h> > #include <cmdline_parse_string.h> > #include <cmdline_parse_num.h> > diff --git a/examples/vm_power_manager/vm_power_cli.c b/examples/vm_power_manager/vm_power_cli.c > index 6f234fb..d013715 100644 > --- a/examples/vm_power_manager/vm_power_cli.c > +++ b/examples/vm_power_manager/vm_power_cli.c > @@ -39,7 +39,6 @@ > #include <termios.h> > #include <errno.h> > > -#include <cmdline_rdline.h> > #include <cmdline_parse.h> > #include <cmdline_parse_string.h> > #include <cmdline_parse_num.h> > diff --git a/lib/librte_cmdline/Makefile b/lib/librte_cmdline/Makefile > index 2c48e62..35c8972 100644 > --- a/lib/librte_cmdline/Makefile > +++ b/lib/librte_cmdline/Makefile > @@ -38,28 +38,24 @@ CFLAGS += $(WERROR_FLAGS) -I$(SRCDIR) -O3 > > EXPORT_MAP := rte_cmdline_version.map > > -LIBABIVER := 2 > +LIBABIVER := 3 > > # all source are stored in SRCS-y > SRCS-$(CONFIG_RTE_LIBRTE_CMDLINE) := cmdline.c > -SRCS-$(CONFIG_RTE_LIBRTE_CMDLINE) += cmdline_cirbuf.c > SRCS-$(CONFIG_RTE_LIBRTE_CMDLINE) += cmdline_parse.c > SRCS-$(CONFIG_RTE_LIBRTE_CMDLINE) += cmdline_parse_etheraddr.c > SRCS-$(CONFIG_RTE_LIBRTE_CMDLINE) += cmdline_parse_ipaddr.c > SRCS-$(CONFIG_RTE_LIBRTE_CMDLINE) += cmdline_parse_num.c > SRCS-$(CONFIG_RTE_LIBRTE_CMDLINE) += cmdline_parse_string.c > -SRCS-$(CONFIG_RTE_LIBRTE_CMDLINE) += cmdline_rdline.c > -SRCS-$(CONFIG_RTE_LIBRTE_CMDLINE) += cmdline_vt100.c > SRCS-$(CONFIG_RTE_LIBRTE_CMDLINE) += cmdline_socket.c > SRCS-$(CONFIG_RTE_LIBRTE_CMDLINE) += cmdline_parse_portlist.c > > -CFLAGS += -D_GNU_SOURCE > LDLIBS += -lrte_eal > > # install includes > INCS := cmdline.h cmdline_parse.h cmdline_parse_num.h cmdline_parse_ipaddr.h > -INCS += cmdline_parse_etheraddr.h cmdline_parse_string.h cmdline_rdline.h > -INCS += cmdline_vt100.h cmdline_socket.h cmdline_cirbuf.h cmdline_parse_portlist.h > +INCS += cmdline_parse_etheraddr.h cmdline_parse_string.h > +INCS += cmdline_socket.h cmdline_parse_portlist.h > SYMLINK-$(CONFIG_RTE_LIBRTE_CMDLINE)-include := $(INCS) > > include $(RTE_SDK)/mk/rte.lib.mk > diff --git a/lib/librte_cmdline/cmdline.c b/lib/librte_cmdline/cmdline.c > index d749165..1c19546 100644 > --- a/lib/librte_cmdline/cmdline.c > +++ b/lib/librte_cmdline/cmdline.c > @@ -58,79 +58,181 @@ > * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. > */ > > +#include <ctype.h> > +#include <histedit.h> > +#include <stdint.h> > #include <stdio.h> > #include <string.h> > #include <unistd.h> > #include <stdlib.h> > #include <stdarg.h> > -#include <inttypes.h> > #include <fcntl.h> > #include <poll.h> > #include <errno.h> > -#include <termios.h> > -#include <netinet/in.h> > - > -#include <rte_string_fns.h> > > #include "cmdline_parse.h" > -#include "cmdline_rdline.h" > #include "cmdline.h" > > -static void > -cmdline_valid_buffer(struct rdline *rdl, const char *buf, > - __attribute__((unused)) unsigned int size) > +struct cmdline { > + char *line; > + FILE *f_in; > + FILE *f_out; > + cmdline_parse_ctx_t *ctx; > + EditLine *el; > + History *hist; > + HistEvent histev; > + uint32_t eof:1; > + uint32_t error:1; > + char prompt[RDLINE_PROMPT_SIZE]; > +}; > + > +void > +cmdline_set_prompt(struct cmdline *cl, const char *prompt) > { > - struct cmdline *cl = rdl->opaque; > - int ret; > - ret = cmdline_parse(cl, buf); > - if (ret == CMDLINE_PARSE_AMBIGUOUS) > - cmdline_printf(cl, "Ambiguous command\n"); > - else if (ret == CMDLINE_PARSE_NOMATCH) > - cmdline_printf(cl, "Command not found\n"); > - else if (ret == CMDLINE_PARSE_BAD_ARGS) > - cmdline_printf(cl, "Bad arguments\n"); > + if (!cl || !prompt) > + return; > + snprintf(cl->prompt, sizeof(cl->prompt), "%s", prompt); > } > > -static int > -cmdline_complete_buffer(struct rdline *rdl, const char *buf, > - char *dstbuf, unsigned int dstsize, > - int *state) > +void * > +cmdline_ctx_get(struct cmdline *cl) > { > - struct cmdline *cl = rdl->opaque; > - return cmdline_complete(cl, buf, state, dstbuf, dstsize); > + if (!cl) > + return NULL; > + return cl->ctx; > } > > -int > -cmdline_write_char(struct rdline *rdl, char c) > +static char * > +cmdline_el_prompt(EditLine *el) > { > - int ret = -1; > struct cmdline *cl; > > - if (!rdl) > - return -1; > - > - cl = rdl->opaque; > + if (el_get(el, EL_CLIENTDATA, &cl)) > + return NULL; > + return cl->prompt; > +} > > - if (cl->s_out >= 0) > - ret = write(cl->s_out, &c, 1); > +static unsigned char > +cmdline_el_execute(EditLine *el, int c) > +{ > + const LineInfo *li = el_line(el); > + size_t len = li->lastchar - li->buffer; > + char *line; > + struct cmdline *cl; > + int ret; > > - return ret; > + (void)c; > + if (el_get(el, EL_CLIENTDATA, &cl)) > + return CC_FATAL; > + line = realloc(cl->line, len + 2); > + if (!line) { > + cl->error = 1; > + return CC_FATAL; > + } > + cl->line = line; > + memcpy(line, li->buffer, len); > + line[len] = '\n'; > + line[len + 1] = '\0'; > + fputs("\r\n", cl->f_out); > + ret = cmdline_parse(cl, line); > + if (ret == CMDLINE_PARSE_AMBIGUOUS) > + fprintf(cl->f_out, "Ambiguous command\r\n"); > + else if (ret == CMDLINE_PARSE_NOMATCH) > + fprintf(cl->f_out, "Command not found\r\n"); > + else if (ret == CMDLINE_PARSE_BAD_ARGS) > + fprintf(cl->f_out, "Bad arguments\r\n"); > + if (cl->error) > + return CC_FATAL; > + if (cl->eof) > + return CC_EOF; > + if (len) { > + line[len] = '\0'; > + history(cl->hist, &cl->histev, H_ENTER, line); > + } > + return CC_NEWLINE; > } > > +static unsigned char > +cmdline_el_complete(EditLine *el, int c) > +{ > + const LineInfo *li = el_line(el); > + size_t pos = li->cursor - li->buffer; > + char *line; > + struct cmdline *cl; > + char complete_buf[RDLINE_COMPLETE_SIZE]; > + int complete_state; > + int ret; > > -void > -cmdline_set_prompt(struct cmdline *cl, const char *prompt) > + if (el_get(el, EL_CLIENTDATA, &cl)) > + return CC_FATAL; > + line = realloc(cl->line, pos + 1); > + if (!line) { > + cl->error = 1; > + return CC_FATAL; > + } > + cl->line = line; > + memcpy(line, li->buffer, pos); > + line[pos] = '\0'; > + if (c == '\t') > + complete_state = 0; > + else > + complete_state = -1; > + /* see in parse.h for help on complete() */ > + ret = cmdline_complete(cl, line, &complete_state, > + complete_buf, sizeof(complete_buf)); > + /* no completion or error */ > + if (ret <= 0) > + return CC_ARGHACK; > + /* string must be NUL-terminated */ > + if (strnlen(complete_buf, sizeof(complete_buf)) == sizeof(complete_buf)) > + return CC_ERROR; > + /* add chars */ > + if (ret == CMDLINE_PARSE_COMPLETED_BUFFER) { > + /* if in the middle of a token, remove its suffix first */ > + for (pos = 0; li->cursor + pos != li->lastchar; pos++) > + if (isblank(li->cursor[pos])) > + break; > + el_cursor(el, pos); > + el_deletestr(el, pos); > + if (el_insertstr(el, complete_buf)) > + return CC_ERROR; > + return CC_REFRESH; > + } > + /* choice */ > + fputs("\r\n", cl->f_out); > + while (ret) { > + fputc(' ', cl->f_out); > + fputs(complete_buf, cl->f_out); > + fputs("\r\n", cl->f_out); > + ret = cmdline_complete(cl, line, &complete_state, > + complete_buf, sizeof(complete_buf)); > + } > + el_set(el, EL_REFRESH); > + return CC_REDISPLAY; > +} > + > +static unsigned char > +cmdline_el_delete_next_char_or_eof(EditLine *el, int c) > { > - if (!cl || !prompt) > - return; > - snprintf(cl->prompt, sizeof(cl->prompt), "%s", prompt); > + const LineInfo *li = el_line(el); > + struct cmdline *cl; > + > + (void)c; > + if (el_get(el, EL_CLIENTDATA, &cl)) > + return CC_FATAL; > + if (li->buffer == li->lastchar) { > + cl->eof = 1; > + return CC_EOF; > + } > + el_cursor(el, 1); > + el_deletestr(el, 1); > + return CC_REFRESH; > } > > struct cmdline * > cmdline_new(cmdline_parse_ctx_t *ctx, const char *prompt, int s_in, int s_out) > { > struct cmdline *cl; > - int ret; > > if (!ctx || !prompt) > return NULL; > @@ -139,36 +241,89 @@ cmdline_new(cmdline_parse_ctx_t *ctx, const char *prompt, int s_in, int s_out) > if (cl == NULL) > return NULL; > memset(cl, 0, sizeof(struct cmdline)); > - cl->s_in = s_in; > - cl->s_out = s_out; > + cl->line = NULL; > + s_in = dup(s_in); > + s_out = s_out != -1 ? dup(s_out) : open("/dev/null", O_WRONLY); > + if (s_in == -1 || s_out == -1) > + goto error; > + cl->f_in = fdopen(s_in, "rb"); > + cl->f_out = fdopen(s_out, "wb"); > + if (!cl->f_in || !cl->f_out) > + goto error; > cl->ctx = ctx; > - > - ret = rdline_init(&cl->rdl, cmdline_write_char, cmdline_valid_buffer, > - cmdline_complete_buffer); > - if (ret != 0) { > - free(cl); > - return NULL; > - } > - > - cl->rdl.opaque = cl; > + cl->el = el_init("dpdk", cl->f_in, cl->f_out, stderr); > + if (!cl->el) > + goto error; > + if (el_set(cl->el, EL_CLIENTDATA, cl)) > + goto error; > cmdline_set_prompt(cl, prompt); > - rdline_newline(&cl->rdl, cl->prompt); > - > + if (el_set(cl->el, EL_PROMPT, cmdline_el_prompt)) > + goto error; > + if (el_set(cl->el, EL_EDITOR, "emacs")) > + goto error; > + if (el_set(cl->el, EL_SIGNAL, 1)) > + goto error; > + cl->hist = history_init(); > + if (!cl->hist) > + goto error; > + if (history(cl->hist, &cl->histev, H_SETSIZE, > + RDLINE_HISTORY_MAX_LINE) < 0) > + goto error; > + if (history(cl->hist, &cl->histev, H_SETUNIQUE, 1)) > + goto error; > + if (el_set(cl->el, EL_HIST, history, cl->hist)) > + goto error; > + if (el_set(cl->el, EL_ADDFN, "ed-execute", "Execute command", > + cmdline_el_execute)) > + goto error; > + if (el_set(cl->el, EL_BIND, "^J", "ed-execute", NULL)) > + goto error; > + if (el_set(cl->el, EL_BIND, "^M", "ed-execute", NULL)) > + goto error; > + if (el_set(cl->el, EL_ADDFN, "ed-complete", "Complete argument", > + cmdline_el_complete)) > + goto error; > + if (el_set(cl->el, EL_BIND, "^I", "ed-complete", NULL)) > + goto error; > + if (el_set(cl->el, EL_BIND, "?", "ed-complete", NULL)) > + goto error; > + if (el_set(cl->el, EL_ADDFN, "ed-delete-next-char-or-eof", > + "Delete next character or assume EOF", > + cmdline_el_delete_next_char_or_eof)) > + goto error; > + if (el_set(cl->el, EL_BIND, "^D", > + "ed-delete-next-char-or-eof", NULL)) > + goto error; > + if (el_set(cl->el, EL_BIND, "^W", "ed-delete-prev-word", NULL)) > + goto error; > return cl; > +error: > + if (cl->hist) > + history_end(cl->hist); > + if (cl->el) > + el_end(cl->el); > + if (cl->f_out) > + fclose(cl->f_out); > + else if (s_out != -1) > + close(s_out); > + if (cl->f_in) > + fclose(cl->f_in); > + else if (s_in != -1) > + close(s_in); > + free(cl); > + return NULL; > } > > void > cmdline_free(struct cmdline *cl) > { > - dprintf("called\n"); > - > if (!cl) > return; > - > - if (cl->s_in > 2) > - close(cl->s_in); > - if (cl->s_out != cl->s_in && cl->s_out > 2) > - close(cl->s_out); > + history_end(cl->hist); > + el_end(cl->el); > + fclose(cl->f_out); > + fclose(cl->f_in); > + free(cl->line); > free(cl); > } > > @@ -180,70 +335,23 @@ cmdline_printf(const struct cmdline *cl, const char *fmt, ...) > if (!cl || !fmt) > return; > > -#ifdef _GNU_SOURCE > - if (cl->s_out < 0) > - return; > - va_start(ap, fmt); > - vdprintf(cl->s_out, fmt, ap); > - va_end(ap); > -#else > - int ret; > - char *buf; > - > - if (cl->s_out < 0) > - return; > - > - buf = malloc(BUFSIZ); > - if (buf == NULL) > - return; > va_start(ap, fmt); > - ret = vsnprintf(buf, BUFSIZ, fmt, ap); > + vfprintf(cl->f_out, fmt, ap); > va_end(ap); > - if (ret < 0) { > - free(buf); > - return; > - } > - if (ret >= BUFSIZ) > - ret = BUFSIZ - 1; > - ret = write(cl->s_out, buf, ret); > - (void)ret; > - free(buf); > -#endif > } > > int > cmdline_in(struct cmdline *cl, const char *buf, int size) > { > - const char *history, *buffer; > - size_t histlen, buflen; > - int ret = 0; > - int i, same; > + int i; > > if (!cl || !buf) > return -1; > > for (i=0; i<size; i++) { > - ret = rdline_char_in(&cl->rdl, buf[i]); > - > - if (ret == RDLINE_RES_VALIDATED) { > - buffer = rdline_get_buffer(&cl->rdl); > - history = rdline_get_history_item(&cl->rdl, 0); > - if (history) { > - histlen = strnlen(history, RDLINE_BUF_SIZE); > - same = !memcmp(buffer, history, histlen) && > - buffer[histlen] == '\n'; > - } > - else > - same = 0; > - buflen = strnlen(buffer, RDLINE_BUF_SIZE); > - if (buflen > 1 && !same) > - rdline_add_history(&cl->rdl, buffer); > - rdline_newline(&cl->rdl, cl->prompt); > - } > - else if (ret == RDLINE_RES_EOF) > - return -1; > - else if (ret == RDLINE_RES_EXITED) > - return -1; > + char tmp[2] = { buf[i], '\0' }; > + > + el_push(cl->el, tmp); > } > return i; > } > @@ -253,7 +361,7 @@ cmdline_quit(struct cmdline *cl) > { > if (!cl) > return; > - rdline_quit(&cl->rdl); > + cl->eof = 1; > } > > int > @@ -261,48 +369,49 @@ cmdline_poll(struct cmdline *cl) > { > struct pollfd pfd; > int status; > - ssize_t read_status; > - char c; > + int read_status; > + int flags; > > if (!cl) > return -EINVAL; > - else if (cl->rdl.status == RDLINE_EXITED) > + else if (cl->error) > + return RDLINE_ERROR; > + else if (cl->eof) > return RDLINE_EXITED; > > - pfd.fd = cl->s_in; > + pfd.fd = fileno(cl->f_in); > pfd.events = POLLIN; > pfd.revents = 0; > > status = poll(&pfd, 1, 0); > if (status < 0) > - return status; > - else if (status > 0) { > - c = -1; > - read_status = read(cl->s_in, &c, 1); > - if (read_status < 0) > - return read_status; > - > - status = cmdline_in(cl, &c, 1); > - if (status < 0 && cl->rdl.status != RDLINE_EXITED) > - return status; > - } > - > - return cl->rdl.status; > + return RDLINE_ERROR; > + if (!status) > + return RDLINE_RUNNING; > + flags = fcntl(pfd.fd, F_GETFL); > + if (!(flags & O_NONBLOCK)) > + fcntl(pfd.fd, F_SETFL, flags | O_NONBLOCK); > + if (!el_gets(cl->el, &read_status) && read_status == -1) > + cl->error = 1; > + if (!(flags & O_NONBLOCK)) > + fcntl(pfd.fd, F_SETFL, flags); > + return cl->error ? RDLINE_ERROR : > + cl->eof ? RDLINE_EXITED : > + RDLINE_RUNNING; > } > > void > cmdline_interact(struct cmdline *cl) > { > - char c; > - > if (!cl) > return; > > - c = -1; > - while (1) { > - if (read(cl->s_in, &c, 1) <= 0) > - break; > - if (cmdline_in(cl, &c, 1) < 0) > - break; > + while (!cl->error && !cl->eof) { > + int read_status; > + > + if (el_gets(cl->el, &read_status)) > + continue; > + if (read_status == -1) > + cl->error = 1; > } > } > diff --git a/lib/librte_cmdline/cmdline.h b/lib/librte_cmdline/cmdline.h > index 65d73b0..4507268 100644 > --- a/lib/librte_cmdline/cmdline.h > +++ b/lib/librte_cmdline/cmdline.h > @@ -61,8 +61,6 @@ > #ifndef _CMDLINE_H_ > #define _CMDLINE_H_ > > -#include <termios.h> > -#include <cmdline_rdline.h> > #include <cmdline_parse.h> > > /** > @@ -75,22 +73,26 @@ > extern "C" { > #endif > > -struct cmdline { > - int s_in; > - int s_out; > - cmdline_parse_ctx_t *ctx; > - struct rdline rdl; > - char prompt[RDLINE_PROMPT_SIZE]; > - struct termios oldterm; > +#define RDLINE_PROMPT_SIZE 32 > +#define RDLINE_HISTORY_MAX_LINE 64 > +#define RDLINE_COMPLETE_SIZE 128 > + > +enum rdline_status { > + RDLINE_ERROR = -1, > + RDLINE_INIT, > + RDLINE_RUNNING, > + RDLINE_EXITED, > }; > > +struct cmdline; > + > +void *cmdline_ctx_get(struct cmdline *cl); > struct cmdline *cmdline_new(cmdline_parse_ctx_t *ctx, const char *prompt, int s_in, int s_out); > void cmdline_set_prompt(struct cmdline *cl, const char *prompt); > void cmdline_free(struct cmdline *cl); > void cmdline_printf(const struct cmdline *cl, const char *fmt, ...) > __attribute__((format(printf,2,3))); > int cmdline_in(struct cmdline *cl, const char *buf, int size); > -int cmdline_write_char(struct rdline *rdl, char c); > > /** > * This function is nonblocking equivalent of ``cmdline_interact()``. It polls > diff --git a/lib/librte_cmdline/cmdline_cirbuf.c b/lib/librte_cmdline/cmdline_cirbuf.c > deleted file mode 100644 > index f506f88..0000000 > --- a/lib/librte_cmdline/cmdline_cirbuf.c > +++ /dev/null > @@ -1,466 +0,0 @@ > -/*- > - * BSD LICENSE > - * > - * Copyright(c) 2010-2014 Intel Corporation. All rights reserved. > - * 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 <zer0@droids-corp.org> > - * 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 the University of California, Berkeley 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 REGENTS 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 REGENTS AND 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. > - */ > - > -#include <string.h> > -#include <errno.h> > -#include <stdio.h> > - > -#include "cmdline_cirbuf.h" > - > - > -int > -cirbuf_init(struct cirbuf *cbuf, char *buf, unsigned int start, unsigned int maxlen) > -{ > - if (!cbuf || !buf) > - return -EINVAL; > - cbuf->maxlen = maxlen; > - cbuf->len = 0; > - cbuf->start = start; > - cbuf->end = start; > - cbuf->buf = buf; > - return 0; > -} > - > -/* multiple add */ > - > -int > -cirbuf_add_buf_head(struct cirbuf *cbuf, const char *c, unsigned int n) > -{ > - unsigned int e; > - > - if (!cbuf || !c || !n || n > CIRBUF_GET_FREELEN(cbuf)) > - return -EINVAL; > - > - e = CIRBUF_IS_EMPTY(cbuf) ? 1 : 0; > - > - if (n < cbuf->start + e) { > - dprintf("s[%d] -> d[%d] (%d)\n", 0, cbuf->start - n + e, n); > - memcpy(cbuf->buf + cbuf->start - n + e, c, n); > - } > - else { > - dprintf("s[%d] -> d[%d] (%d)\n", + n - (cbuf->start + e), 0, > - cbuf->start + e); > - dprintf("s[%d] -> d[%d] (%d)\n", cbuf->maxlen - n + > - (cbuf->start + e), 0, n - (cbuf->start + e)); > - memcpy(cbuf->buf, c + n - (cbuf->start + e) , cbuf->start + e); > - memcpy(cbuf->buf + cbuf->maxlen - n + (cbuf->start + e), c, > - n - (cbuf->start + e)); > - } > - cbuf->len += n; > - cbuf->start += (cbuf->maxlen - n + e); > - cbuf->start %= cbuf->maxlen; > - return n; > -} > - > -/* multiple add */ > - > -int > -cirbuf_add_buf_tail(struct cirbuf *cbuf, const char *c, unsigned int n) > -{ > - unsigned int e; > - > - if (!cbuf || !c || !n || n > CIRBUF_GET_FREELEN(cbuf)) > - return -EINVAL; > - > - e = CIRBUF_IS_EMPTY(cbuf) ? 1 : 0; > - > - if (n < cbuf->maxlen - cbuf->end - 1 + e) { > - dprintf("s[%d] -> d[%d] (%d)\n", 0, cbuf->end + !e, n); > - memcpy(cbuf->buf + cbuf->end + !e, c, n); > - } > - else { > - dprintf("s[%d] -> d[%d] (%d)\n", cbuf->end + !e, 0, > - cbuf->maxlen - cbuf->end - 1 + e); > - dprintf("s[%d] -> d[%d] (%d)\n", cbuf->maxlen - cbuf->end - 1 + > - e, 0, n - cbuf->maxlen + cbuf->end + 1 - e); > - memcpy(cbuf->buf + cbuf->end + !e, c, cbuf->maxlen - > - cbuf->end - 1 + e); > - memcpy(cbuf->buf, c + cbuf->maxlen - cbuf->end - 1 + e, > - n - cbuf->maxlen + cbuf->end + 1 - e); > - } > - cbuf->len += n; > - cbuf->end += n - e; > - cbuf->end %= cbuf->maxlen; > - return n; > -} > - > -/* add at head */ > - > -static inline void > -__cirbuf_add_head(struct cirbuf * cbuf, char c) > -{ > - if (!CIRBUF_IS_EMPTY(cbuf)) { > - cbuf->start += (cbuf->maxlen - 1); > - cbuf->start %= cbuf->maxlen; > - } > - cbuf->buf[cbuf->start] = c; > - cbuf->len ++; > -} > - > -int > -cirbuf_add_head_safe(struct cirbuf * cbuf, char c) > -{ > - if (cbuf && !CIRBUF_IS_FULL(cbuf)) { > - __cirbuf_add_head(cbuf, c); > - return 0; > - } > - return -EINVAL; > -} > - > -void > -cirbuf_add_head(struct cirbuf * cbuf, char c) > -{ > - __cirbuf_add_head(cbuf, c); > -} > - > -/* add at tail */ > - > -static inline void > -__cirbuf_add_tail(struct cirbuf * cbuf, char c) > -{ > - if (!CIRBUF_IS_EMPTY(cbuf)) { > - cbuf->end ++; > - cbuf->end %= cbuf->maxlen; > - } > - cbuf->buf[cbuf->end] = c; > - cbuf->len ++; > -} > - > -int > -cirbuf_add_tail_safe(struct cirbuf * cbuf, char c) > -{ > - if (cbuf && !CIRBUF_IS_FULL(cbuf)) { > - __cirbuf_add_tail(cbuf, c); > - return 0; > - } > - return -EINVAL; > -} > - > -void > -cirbuf_add_tail(struct cirbuf * cbuf, char c) > -{ > - __cirbuf_add_tail(cbuf, c); > -} > - > - > -static inline void > -__cirbuf_shift_left(struct cirbuf *cbuf) > -{ > - unsigned int i; > - char tmp = cbuf->buf[cbuf->start]; > - > - for (i=0 ; i<cbuf->len ; i++) { > - cbuf->buf[(cbuf->start+i)%cbuf->maxlen] = > - cbuf->buf[(cbuf->start+i+1)%cbuf->maxlen]; > - } > - cbuf->buf[(cbuf->start-1+cbuf->maxlen)%cbuf->maxlen] = tmp; > - cbuf->start += (cbuf->maxlen - 1); > - cbuf->start %= cbuf->maxlen; > - cbuf->end += (cbuf->maxlen - 1); > - cbuf->end %= cbuf->maxlen; > -} > - > -static inline void > -__cirbuf_shift_right(struct cirbuf *cbuf) > -{ > - unsigned int i; > - char tmp = cbuf->buf[cbuf->end]; > - > - for (i=0 ; i<cbuf->len ; i++) { > - cbuf->buf[(cbuf->end+cbuf->maxlen-i)%cbuf->maxlen] = > - cbuf->buf[(cbuf->end+cbuf->maxlen-i-1)%cbuf->maxlen]; > - } > - cbuf->buf[(cbuf->end+1)%cbuf->maxlen] = tmp; > - cbuf->start += 1; > - cbuf->start %= cbuf->maxlen; > - cbuf->end += 1; > - cbuf->end %= cbuf->maxlen; > -} > - > -/* XXX we could do a better algorithm here... */ > -int > -cirbuf_align_left(struct cirbuf * cbuf) > -{ > - if (!cbuf) > - return -EINVAL; > - > - if (cbuf->start < cbuf->maxlen/2) { > - while (cbuf->start != 0) { > - __cirbuf_shift_left(cbuf); > - } > - } > - else { > - while (cbuf->start != 0) { > - __cirbuf_shift_right(cbuf); > - } > - } > - > - return 0; > -} > - > -/* XXX we could do a better algorithm here... */ > -int > -cirbuf_align_right(struct cirbuf * cbuf) > -{ > - if (!cbuf) > - return -EINVAL; > - > - if (cbuf->start >= cbuf->maxlen/2) { > - while (cbuf->end != cbuf->maxlen-1) { > - __cirbuf_shift_left(cbuf); > - } > - } > - else { > - while (cbuf->start != cbuf->maxlen-1) { > - __cirbuf_shift_right(cbuf); > - } > - } > - > - return 0; > -} > - > -/* buffer del */ > - > -int > -cirbuf_del_buf_head(struct cirbuf *cbuf, unsigned int size) > -{ > - if (!cbuf || !size || size > CIRBUF_GET_LEN(cbuf)) > - return -EINVAL; > - > - cbuf->len -= size; > - if (CIRBUF_IS_EMPTY(cbuf)) { > - cbuf->start += size - 1; > - cbuf->start %= cbuf->maxlen; > - } > - else { > - cbuf->start += size; > - cbuf->start %= cbuf->maxlen; > - } > - return 0; > -} > - > -/* buffer del */ > - > -int > -cirbuf_del_buf_tail(struct cirbuf *cbuf, unsigned int size) > -{ > - if (!cbuf || !size || size > CIRBUF_GET_LEN(cbuf)) > - return -EINVAL; > - > - cbuf->len -= size; > - if (CIRBUF_IS_EMPTY(cbuf)) { > - cbuf->end += (cbuf->maxlen - size + 1); > - cbuf->end %= cbuf->maxlen; > - } > - else { > - cbuf->end += (cbuf->maxlen - size); > - cbuf->end %= cbuf->maxlen; > - } > - return 0; > -} > - > -/* del at head */ > - > -static inline void > -__cirbuf_del_head(struct cirbuf * cbuf) > -{ > - cbuf->len --; > - if (!CIRBUF_IS_EMPTY(cbuf)) { > - cbuf->start ++; > - cbuf->start %= cbuf->maxlen; > - } > -} > - > -int > -cirbuf_del_head_safe(struct cirbuf * cbuf) > -{ > - if (cbuf && !CIRBUF_IS_EMPTY(cbuf)) { > - __cirbuf_del_head(cbuf); > - return 0; > - } > - return -EINVAL; > -} > - > -void > -cirbuf_del_head(struct cirbuf * cbuf) > -{ > - __cirbuf_del_head(cbuf); > -} > - > -/* del at tail */ > - > -static inline void > -__cirbuf_del_tail(struct cirbuf * cbuf) > -{ > - cbuf->len --; > - if (!CIRBUF_IS_EMPTY(cbuf)) { > - cbuf->end += (cbuf->maxlen - 1); > - cbuf->end %= cbuf->maxlen; > - } > -} > - > -int > -cirbuf_del_tail_safe(struct cirbuf * cbuf) > -{ > - if (cbuf && !CIRBUF_IS_EMPTY(cbuf)) { > - __cirbuf_del_tail(cbuf); > - return 0; > - } > - return -EINVAL; > -} > - > -void > -cirbuf_del_tail(struct cirbuf * cbuf) > -{ > - __cirbuf_del_tail(cbuf); > -} > - > -/* convert to buffer */ > - > -int > -cirbuf_get_buf_head(struct cirbuf *cbuf, char *c, unsigned int size) > -{ > - unsigned int n; > - > - if (!cbuf || !c) > - return -EINVAL; > - > - n = (size < CIRBUF_GET_LEN(cbuf)) ? size : CIRBUF_GET_LEN(cbuf); > - > - if (!n) > - return 0; > - > - if (cbuf->start <= cbuf->end) { > - dprintf("s[%d] -> d[%d] (%d)\n", cbuf->start, 0, n); > - memcpy(c, cbuf->buf + cbuf->start , n); > - } > - else { > - /* check if we need to go from end to the beginning */ > - if (n <= cbuf->maxlen - cbuf->start) { > - dprintf("s[%d] -> d[%d] (%d)\n", 0, cbuf->start, n); > - memcpy(c, cbuf->buf + cbuf->start , n); > - } > - else { > - dprintf("s[%d] -> d[%d] (%d)\n", cbuf->start, 0, > - cbuf->maxlen - cbuf->start); > - dprintf("s[%d] -> d[%d] (%d)\n", 0, cbuf->maxlen - cbuf->start, > - n - cbuf->maxlen + cbuf->start); > - memcpy(c, cbuf->buf + cbuf->start , cbuf->maxlen - cbuf->start); > - memcpy(c + cbuf->maxlen - cbuf->start, cbuf->buf, > - n - cbuf->maxlen + cbuf->start); > - } > - } > - return n; > -} > - > -/* convert to buffer */ > - > -int > -cirbuf_get_buf_tail(struct cirbuf *cbuf, char *c, unsigned int size) > -{ > - unsigned int n; > - > - if (!cbuf || !c) > - return -EINVAL; > - > - n = (size < CIRBUF_GET_LEN(cbuf)) ? size : CIRBUF_GET_LEN(cbuf); > - > - if (!n) > - return 0; > - > - if (cbuf->start <= cbuf->end) { > - dprintf("s[%d] -> d[%d] (%d)\n", cbuf->end - n + 1, 0, n); > - memcpy(c, cbuf->buf + cbuf->end - n + 1, n); > - } > - else { > - /* check if we need to go from end to the beginning */ > - if (n <= cbuf->end + 1) { > - dprintf("s[%d] -> d[%d] (%d)\n", 0, cbuf->end - n + 1, n); > - memcpy(c, cbuf->buf + cbuf->end - n + 1, n); > - } > - else { > - dprintf("s[%d] -> d[%d] (%d)\n", 0, > - cbuf->maxlen - cbuf->start, cbuf->end + 1); > - dprintf("s[%d] -> d[%d] (%d)\n", > - cbuf->maxlen - n + cbuf->end + 1, 0, n - cbuf->end - 1); > - memcpy(c + cbuf->maxlen - cbuf->start, > - cbuf->buf, cbuf->end + 1); > - memcpy(c, cbuf->buf + cbuf->maxlen - n + cbuf->end +1, > - n - cbuf->end - 1); > - } > - } > - return n; > -} > - > -/* get head or get tail */ > - > -char > -cirbuf_get_head(struct cirbuf * cbuf) > -{ > - return cbuf->buf[cbuf->start]; > -} > - > -/* get head or get tail */ > - > -char > -cirbuf_get_tail(struct cirbuf * cbuf) > -{ > - return cbuf->buf[cbuf->end]; > -} > diff --git a/lib/librte_cmdline/cmdline_cirbuf.h b/lib/librte_cmdline/cmdline_cirbuf.h > deleted file mode 100644 > index 6321dec..0000000 > --- a/lib/librte_cmdline/cmdline_cirbuf.h > +++ /dev/null > @@ -1,245 +0,0 @@ > -/*- > - * BSD LICENSE > - * > - * Copyright(c) 2010-2014 Intel Corporation. All rights reserved. > - * 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 <zer0@droids-corp.org> > - * 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 the University of California, Berkeley 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 REGENTS 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 REGENTS AND 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. > - */ > - > -#ifndef _CIRBUF_H_ > -#define _CIRBUF_H_ > - > -#ifdef __cplusplus > -extern "C" { > -#endif > - > -/** > - * This structure is the header of a cirbuf type. > - */ > -struct cirbuf { > - unsigned int maxlen; /**< total len of the fifo (number of elements) */ > - unsigned int start; /**< indice of the first elt */ > - unsigned int end; /**< indice of the last elt */ > - unsigned int len; /**< current len of fifo */ > - char *buf; > -}; > - > -#ifdef RTE_LIBRTE_CMDLINE_DEBUG > -#define dprintf_(fmt, ...) printf("line %3.3d - " fmt "%.0s", __LINE__, __VA_ARGS__) > -#define dprintf(...) dprintf_(__VA_ARGS__, "dummy") > -#else > -#define dprintf(...) (void)0 > -#endif > - > - > -/** > - * Init the circular buffer > - */ > -int cirbuf_init(struct cirbuf *cbuf, char *buf, unsigned int start, unsigned int maxlen); > - > - > -/** > - * Return 1 if the circular buffer is full > - */ > -#define CIRBUF_IS_FULL(cirbuf) ((cirbuf)->maxlen == (cirbuf)->len) > - > -/** > - * Return 1 if the circular buffer is empty > - */ > -#define CIRBUF_IS_EMPTY(cirbuf) ((cirbuf)->len == 0) > - > -/** > - * return current size of the circular buffer (number of used elements) > - */ > -#define CIRBUF_GET_LEN(cirbuf) ((cirbuf)->len) > - > -/** > - * return size of the circular buffer (used + free elements) > - */ > -#define CIRBUF_GET_MAXLEN(cirbuf) ((cirbuf)->maxlen) > - > -/** > - * return the number of free elts > - */ > -#define CIRBUF_GET_FREELEN(cirbuf) ((cirbuf)->maxlen - (cirbuf)->len) > - > -/** > - * Iterator for a circular buffer > - * c: struct cirbuf pointer > - * i: an integer type internally used in the macro > - * e: char that takes the value for each iteration > - */ > -#define CIRBUF_FOREACH(c, i, e) \ > - for ( i=0, e=(c)->buf[(c)->start] ; \ > - i<((c)->len) ; \ > - i ++, e=(c)->buf[((c)->start+i)%((c)->maxlen)]) > - > - > -/** > - * Add a character at head of the circular buffer. Return 0 on success, or > - * a negative value on error. > - */ > -int cirbuf_add_head_safe(struct cirbuf *cbuf, char c); > - > -/** > - * Add a character at head of the circular buffer. You _must_ check that you > - * have enough free space in the buffer before calling this func. > - */ > -void cirbuf_add_head(struct cirbuf *cbuf, char c); > - > -/** > - * Add a character at tail of the circular buffer. Return 0 on success, or > - * a negative value on error. > - */ > -int cirbuf_add_tail_safe(struct cirbuf *cbuf, char c); > - > -/** > - * Add a character at tail of the circular buffer. You _must_ check that you > - * have enough free space in the buffer before calling this func. > - */ > -void cirbuf_add_tail(struct cirbuf *cbuf, char c); > - > -/** > - * Remove a char at the head of the circular buffer. Return 0 on > - * success, or a negative value on error. > - */ > -int cirbuf_del_head_safe(struct cirbuf *cbuf); > - > -/** > - * Remove a char at the head of the circular buffer. You _must_ check > - * that buffer is not empty before calling the function. > - */ > -void cirbuf_del_head(struct cirbuf *cbuf); > - > -/** > - * Remove a char at the tail of the circular buffer. Return 0 on > - * success, or a negative value on error. > - */ > -int cirbuf_del_tail_safe(struct cirbuf *cbuf); > - > -/** > - * Remove a char at the tail of the circular buffer. You _must_ check > - * that buffer is not empty before calling the function. > - */ > -void cirbuf_del_tail(struct cirbuf *cbuf); > - > -/** > - * Return the head of the circular buffer. You _must_ check that > - * buffer is not empty before calling the function. > - */ > -char cirbuf_get_head(struct cirbuf *cbuf); > - > -/** > - * Return the tail of the circular buffer. You _must_ check that > - * buffer is not empty before calling the function. > - */ > -char cirbuf_get_tail(struct cirbuf *cbuf); > - > -/** > - * Add a buffer at head of the circular buffer. 'c' is a pointer to a > - * buffer, and n is the number of char to add. Return the number of > - * copied bytes on success, or a negative value on error. > - */ > -int cirbuf_add_buf_head(struct cirbuf *cbuf, const char *c, unsigned int n); > - > -/** > - * Add a buffer at tail of the circular buffer. 'c' is a pointer to a > - * buffer, and n is the number of char to add. Return the number of > - * copied bytes on success, or a negative value on error. > - */ > -int cirbuf_add_buf_tail(struct cirbuf *cbuf, const char *c, unsigned int n); > - > -/** > - * Remove chars at the head of the circular buffer. Return 0 on > - * success, or a negative value on error. > - */ > -int cirbuf_del_buf_head(struct cirbuf *cbuf, unsigned int size); > - > -/** > - * Remove chars at the tail of the circular buffer. Return 0 on > - * success, or a negative value on error. > - */ > -int cirbuf_del_buf_tail(struct cirbuf *cbuf, unsigned int size); > - > -/** > - * Copy a maximum of 'size' characters from the head of the circular > - * buffer to a flat one pointed by 'c'. Return the number of copied > - * chars. > - */ > -int cirbuf_get_buf_head(struct cirbuf *cbuf, char *c, unsigned int size); > - > -/** > - * Copy a maximum of 'size' characters from the tail of the circular > - * buffer to a flat one pointed by 'c'. Return the number of copied > - * chars. > - */ > -int cirbuf_get_buf_tail(struct cirbuf *cbuf, char *c, unsigned int size); > - > - > -/** > - * Set the start of the data to the index 0 of the internal buffer. > - */ > -int cirbuf_align_left(struct cirbuf *cbuf); > - > -/** > - * Set the end of the data to the last index of the internal buffer. > - */ > -int cirbuf_align_right(struct cirbuf *cbuf); > - > -#ifdef __cplusplus > -} > -#endif > - > -#endif /* _CIRBUF_H_ */ > diff --git a/lib/librte_cmdline/cmdline_parse.c b/lib/librte_cmdline/cmdline_parse.c > index 3e12ee5..0cc0b57 100644 > --- a/lib/librte_cmdline/cmdline_parse.c > +++ b/lib/librte_cmdline/cmdline_parse.c > @@ -70,7 +70,6 @@ > > #include <rte_string_fns.h> > > -#include "cmdline_rdline.h" > #include "cmdline_parse.h" > #include "cmdline.h" > > @@ -267,7 +266,7 @@ cmdline_parse(struct cmdline *cl, const char * buf) > if (!cl || !buf) > return CMDLINE_PARSE_BAD_ARGS; > > - ctx = cl->ctx; > + ctx = cmdline_ctx_get(cl); > > /* > * - look if the buffer contains at least one line > @@ -386,7 +385,7 @@ cmdline_complete(struct cmdline *cl, const char *buf, int *state, > if (!cl || !buf || !state || !dst) > return -1; > > - ctx = cl->ctx; > + ctx = cmdline_ctx_get(cl); > > debug_printf("%s called\n", __func__); > memset(&token_hdr, 0, sizeof(token_hdr)); > @@ -398,7 +397,7 @@ cmdline_complete(struct cmdline *cl, const char *buf, int *state, > if (isblank2(buf[i]) && !isblank2(buf[i+1])) > partial_tok = buf+i+1; > } > - partial_tok_len = strnlen(partial_tok, RDLINE_BUF_SIZE); > + partial_tok_len = strlen(partial_tok); > > /* first call -> do a first pass */ > if (*state <= 0) { > diff --git a/lib/librte_cmdline/cmdline_rdline.c b/lib/librte_cmdline/cmdline_rdline.c > deleted file mode 100644 > index 1ef2258..0000000 > --- a/lib/librte_cmdline/cmdline_rdline.c > +++ /dev/null > @@ -1,697 +0,0 @@ > -/*- > - * BSD LICENSE > - * > - * Copyright(c) 2010-2014 Intel Corporation. All rights reserved. > - * 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 <zer0@droids-corp.org> > - * 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 the University of California, Berkeley 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 REGENTS 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 REGENTS AND 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. > - */ > - > -#include <stdlib.h> > -#include <stdio.h> > -#include <stdint.h> > -#include <string.h> > -#include <stdarg.h> > -#include <errno.h> > -#include <ctype.h> > - > -#include "cmdline_cirbuf.h" > -#include "cmdline_rdline.h" > - > -static void rdline_puts(struct rdline *rdl, const char *buf); > -static void rdline_miniprintf(struct rdline *rdl, > - const char *buf, unsigned int val); > - > -static void rdline_remove_old_history_item(struct rdline *rdl); > -static void rdline_remove_first_history_item(struct rdline *rdl); > -static unsigned int rdline_get_history_size(struct rdline *rdl); > - > - > -/* isblank() needs _XOPEN_SOURCE >= 600 || _ISOC99_SOURCE, so use our > - * own. */ > -static int > -isblank2(char c) > -{ > - if (c == ' ' || > - c == '\t' ) > - return 1; > - return 0; > -} > - > -int > -rdline_init(struct rdline *rdl, > - rdline_write_char_t *write_char, > - rdline_validate_t *validate, > - rdline_complete_t *complete) > -{ > - if (!rdl || !write_char || !validate || !complete) > - return -EINVAL; > - memset(rdl, 0, sizeof(*rdl)); > - rdl->validate = validate; > - rdl->complete = complete; > - rdl->write_char = write_char; > - rdl->status = RDLINE_INIT; > - return cirbuf_init(&rdl->history, rdl->history_buf, 0, RDLINE_HISTORY_BUF_SIZE); > -} > - > -void > -rdline_newline(struct rdline *rdl, const char *prompt) > -{ > - unsigned int i; > - > - if (!rdl || !prompt) > - return; > - > - vt100_init(&rdl->vt100); > - cirbuf_init(&rdl->left, rdl->left_buf, 0, RDLINE_BUF_SIZE); > - cirbuf_init(&rdl->right, rdl->right_buf, 0, RDLINE_BUF_SIZE); > - > - rdl->prompt_size = strnlen(prompt, RDLINE_PROMPT_SIZE-1); > - if (prompt != rdl->prompt) > - memcpy(rdl->prompt, prompt, rdl->prompt_size); > - rdl->prompt[RDLINE_PROMPT_SIZE-1] = '\0'; > - > - for (i=0 ; i<rdl->prompt_size ; i++) > - rdl->write_char(rdl, rdl->prompt[i]); > - rdl->status = RDLINE_RUNNING; > - > - rdl->history_cur_line = -1; > -} > - > -void > -rdline_stop(struct rdline *rdl) > -{ > - if (!rdl) > - return; > - rdl->status = RDLINE_INIT; > -} > - > -void > -rdline_quit(struct rdline *rdl) > -{ > - if (!rdl) > - return; > - rdl->status = RDLINE_EXITED; > -} > - > -void > -rdline_restart(struct rdline *rdl) > -{ > - if (!rdl) > - return; > - rdl->status = RDLINE_RUNNING; > -} > - > -void > -rdline_reset(struct rdline *rdl) > -{ > - if (!rdl) > - return; > - vt100_init(&rdl->vt100); > - cirbuf_init(&rdl->left, rdl->left_buf, 0, RDLINE_BUF_SIZE); > - cirbuf_init(&rdl->right, rdl->right_buf, 0, RDLINE_BUF_SIZE); > - > - rdl->status = RDLINE_RUNNING; > - > - rdl->history_cur_line = -1; > -} > - > -const char * > -rdline_get_buffer(struct rdline *rdl) > -{ > - if (!rdl) > - return NULL; > - unsigned int len_l, len_r; > - cirbuf_align_left(&rdl->left); > - cirbuf_align_left(&rdl->right); > - > - len_l = CIRBUF_GET_LEN(&rdl->left); > - len_r = CIRBUF_GET_LEN(&rdl->right); > - memcpy(rdl->left_buf+len_l, rdl->right_buf, len_r); > - > - rdl->left_buf[len_l + len_r] = '\n'; > - rdl->left_buf[len_l + len_r + 1] = '\0'; > - return rdl->left_buf; > -} > - > -static void > -display_right_buffer(struct rdline *rdl, int force) > -{ > - unsigned int i; > - char tmp; > - > - if (!force && CIRBUF_IS_EMPTY(&rdl->right)) > - return; > - > - rdline_puts(rdl, vt100_clear_right); > - CIRBUF_FOREACH(&rdl->right, i, tmp) { > - rdl->write_char(rdl, tmp); > - } > - if (!CIRBUF_IS_EMPTY(&rdl->right)) > - rdline_miniprintf(rdl, vt100_multi_left, > - CIRBUF_GET_LEN(&rdl->right)); > -} > - > -void > -rdline_redisplay(struct rdline *rdl) > -{ > - unsigned int i; > - char tmp; > - > - if (!rdl) > - return; > - > - rdline_puts(rdl, vt100_home); > - for (i=0 ; i<rdl->prompt_size ; i++) > - rdl->write_char(rdl, rdl->prompt[i]); > - CIRBUF_FOREACH(&rdl->left, i, tmp) { > - rdl->write_char(rdl, tmp); > - } > - display_right_buffer(rdl, 1); > -} > - > -int > -rdline_char_in(struct rdline *rdl, char c) > -{ > - unsigned int i; > - int cmd; > - char tmp; > - char *buf; > - > - if (!rdl) > - return -EINVAL; > - > - if (rdl->status == RDLINE_EXITED) > - return RDLINE_RES_EXITED; > - if (rdl->status != RDLINE_RUNNING) > - return RDLINE_RES_NOT_RUNNING; > - > - cmd = vt100_parser(&rdl->vt100, c); > - if (cmd == -2) > - return RDLINE_RES_SUCCESS; > - > - if (cmd >= 0) { > - switch (cmd) { > - /* move caret 1 char to the left */ > - case CMDLINE_KEY_CTRL_B: > - case CMDLINE_KEY_LEFT_ARR: > - if (CIRBUF_IS_EMPTY(&rdl->left)) > - break; > - tmp = cirbuf_get_tail(&rdl->left); > - cirbuf_del_tail(&rdl->left); > - cirbuf_add_head(&rdl->right, tmp); > - rdline_puts(rdl, vt100_left_arr); > - break; > - > - /* move caret 1 char to the right */ > - case CMDLINE_KEY_CTRL_F: > - case CMDLINE_KEY_RIGHT_ARR: > - if (CIRBUF_IS_EMPTY(&rdl->right)) > - break; > - tmp = cirbuf_get_head(&rdl->right); > - cirbuf_del_head(&rdl->right); > - cirbuf_add_tail(&rdl->left, tmp); > - rdline_puts(rdl, vt100_right_arr); > - break; > - > - /* move caret 1 word to the left */ > - /* keyboard equivalent: Alt+B */ > - case CMDLINE_KEY_WLEFT: > - while (! CIRBUF_IS_EMPTY(&rdl->left) && > - (tmp = cirbuf_get_tail(&rdl->left)) && > - isblank2(tmp)) { > - rdline_puts(rdl, vt100_left_arr); > - cirbuf_del_tail(&rdl->left); > - cirbuf_add_head(&rdl->right, tmp); > - } > - while (! CIRBUF_IS_EMPTY(&rdl->left) && > - (tmp = cirbuf_get_tail(&rdl->left)) && > - !isblank2(tmp)) { > - rdline_puts(rdl, vt100_left_arr); > - cirbuf_del_tail(&rdl->left); > - cirbuf_add_head(&rdl->right, tmp); > - } > - break; > - > - /* move caret 1 word to the right */ > - /* keyboard equivalent: Alt+F */ > - case CMDLINE_KEY_WRIGHT: > - while (! CIRBUF_IS_EMPTY(&rdl->right) && > - (tmp = cirbuf_get_head(&rdl->right)) && > - isblank2(tmp)) { > - rdline_puts(rdl, vt100_right_arr); > - cirbuf_del_head(&rdl->right); > - cirbuf_add_tail(&rdl->left, tmp); > - } > - while (! CIRBUF_IS_EMPTY(&rdl->right) && > - (tmp = cirbuf_get_head(&rdl->right)) && > - !isblank2(tmp)) { > - rdline_puts(rdl, vt100_right_arr); > - cirbuf_del_head(&rdl->right); > - cirbuf_add_tail(&rdl->left, tmp); > - } > - break; > - > - /* move caret to the left */ > - case CMDLINE_KEY_CTRL_A: > - if (CIRBUF_IS_EMPTY(&rdl->left)) > - break; > - rdline_miniprintf(rdl, vt100_multi_left, > - CIRBUF_GET_LEN(&rdl->left)); > - while (! CIRBUF_IS_EMPTY(&rdl->left)) { > - tmp = cirbuf_get_tail(&rdl->left); > - cirbuf_del_tail(&rdl->left); > - cirbuf_add_head(&rdl->right, tmp); > - } > - break; > - > - /* move caret to the right */ > - case CMDLINE_KEY_CTRL_E: > - if (CIRBUF_IS_EMPTY(&rdl->right)) > - break; > - rdline_miniprintf(rdl, vt100_multi_right, > - CIRBUF_GET_LEN(&rdl->right)); > - while (! CIRBUF_IS_EMPTY(&rdl->right)) { > - tmp = cirbuf_get_head(&rdl->right); > - cirbuf_del_head(&rdl->right); > - cirbuf_add_tail(&rdl->left, tmp); > - } > - break; > - > - /* delete 1 char from the left */ > - case CMDLINE_KEY_BKSPACE: > - if(!cirbuf_del_tail_safe(&rdl->left)) { > - rdline_puts(rdl, vt100_bs); > - display_right_buffer(rdl, 1); > - } > - break; > - > - /* delete 1 char from the right */ > - case CMDLINE_KEY_SUPPR: > - case CMDLINE_KEY_CTRL_D: > - if (cmd == CMDLINE_KEY_CTRL_D && > - CIRBUF_IS_EMPTY(&rdl->left) && > - CIRBUF_IS_EMPTY(&rdl->right)) { > - return RDLINE_RES_EOF; > - } > - if (!cirbuf_del_head_safe(&rdl->right)) { > - display_right_buffer(rdl, 1); > - } > - break; > - > - /* delete 1 word from the left */ > - case CMDLINE_KEY_META_BKSPACE: > - case CMDLINE_KEY_CTRL_W: > - while (! CIRBUF_IS_EMPTY(&rdl->left) && isblank2(cirbuf_get_tail(&rdl->left))) { > - rdline_puts(rdl, vt100_bs); > - cirbuf_del_tail(&rdl->left); > - } > - while (! CIRBUF_IS_EMPTY(&rdl->left) && !isblank2(cirbuf_get_tail(&rdl->left))) { > - rdline_puts(rdl, vt100_bs); > - cirbuf_del_tail(&rdl->left); > - } > - display_right_buffer(rdl, 1); > - break; > - > - /* delete 1 word from the right */ > - case CMDLINE_KEY_META_D: > - while (! CIRBUF_IS_EMPTY(&rdl->right) && isblank2(cirbuf_get_head(&rdl->right))) > - cirbuf_del_head(&rdl->right); > - while (! CIRBUF_IS_EMPTY(&rdl->right) && !isblank2(cirbuf_get_head(&rdl->right))) > - cirbuf_del_head(&rdl->right); > - display_right_buffer(rdl, 1); > - break; > - > - /* set kill buffer to contents on the right side of caret */ > - case CMDLINE_KEY_CTRL_K: > - cirbuf_get_buf_head(&rdl->right, rdl->kill_buf, RDLINE_BUF_SIZE); > - rdl->kill_size = CIRBUF_GET_LEN(&rdl->right); > - cirbuf_del_buf_head(&rdl->right, rdl->kill_size); > - rdline_puts(rdl, vt100_clear_right); > - break; > - > - /* paste contents of kill buffer to the left side of caret */ > - case CMDLINE_KEY_CTRL_Y: > - i=0; > - while(CIRBUF_GET_LEN(&rdl->right) + CIRBUF_GET_LEN(&rdl->left) < > - RDLINE_BUF_SIZE && > - i < rdl->kill_size) { > - cirbuf_add_tail(&rdl->left, rdl->kill_buf[i]); > - rdl->write_char(rdl, rdl->kill_buf[i]); > - i++; > - } > - display_right_buffer(rdl, 0); > - break; > - > - /* clear and newline */ > - case CMDLINE_KEY_CTRL_C: > - rdline_puts(rdl, "\r\n"); > - rdline_newline(rdl, rdl->prompt); > - break; > - > - /* redisplay (helps when prompt is lost in other output) */ > - case CMDLINE_KEY_CTRL_L: > - rdline_redisplay(rdl); > - break; > - > - /* autocomplete */ > - case CMDLINE_KEY_TAB: > - case CMDLINE_KEY_HELP: > - cirbuf_align_left(&rdl->left); > - rdl->left_buf[CIRBUF_GET_LEN(&rdl->left)] = '\0'; > - if (rdl->complete) { > - char tmp_buf[BUFSIZ]; > - int complete_state; > - int ret; > - unsigned int tmp_size; > - > - if (cmd == CMDLINE_KEY_TAB) > - complete_state = 0; > - else > - complete_state = -1; > - > - /* see in parse.h for help on complete() */ > - ret = rdl->complete(rdl, rdl->left_buf, > - tmp_buf, sizeof(tmp_buf), > - &complete_state); > - /* no completion or error */ > - if (ret <= 0) { > - return RDLINE_RES_COMPLETE; > - } > - > - tmp_size = strnlen(tmp_buf, sizeof(tmp_buf)); > - /* add chars */ > - if (ret == RDLINE_RES_COMPLETE) { > - i=0; > - while(CIRBUF_GET_LEN(&rdl->right) + CIRBUF_GET_LEN(&rdl->left) < > - RDLINE_BUF_SIZE && > - i < tmp_size) { > - cirbuf_add_tail(&rdl->left, tmp_buf[i]); > - rdl->write_char(rdl, tmp_buf[i]); > - i++; > - } > - display_right_buffer(rdl, 1); > - return RDLINE_RES_COMPLETE; /* ?? */ > - } > - > - /* choice */ > - rdline_puts(rdl, "\r\n"); > - while (ret) { > - rdl->write_char(rdl, ' '); > - for (i=0 ; tmp_buf[i] ; i++) > - rdl->write_char(rdl, tmp_buf[i]); > - rdline_puts(rdl, "\r\n"); > - ret = rdl->complete(rdl, rdl->left_buf, > - tmp_buf, sizeof(tmp_buf), > - &complete_state); > - } > - > - rdline_redisplay(rdl); > - } > - return RDLINE_RES_COMPLETE; > - > - /* complete buffer */ > - case CMDLINE_KEY_RETURN: > - case CMDLINE_KEY_RETURN2: > - rdline_get_buffer(rdl); > - rdl->status = RDLINE_INIT; > - rdline_puts(rdl, "\r\n"); > - if (rdl->history_cur_line != -1) > - rdline_remove_first_history_item(rdl); > - > - if (rdl->validate) > - rdl->validate(rdl, rdl->left_buf, CIRBUF_GET_LEN(&rdl->left)+2); > - /* user may have stopped rdline */ > - if (rdl->status == RDLINE_EXITED) > - return RDLINE_RES_EXITED; > - return RDLINE_RES_VALIDATED; > - > - /* previous element in history */ > - case CMDLINE_KEY_UP_ARR: > - case CMDLINE_KEY_CTRL_P: > - if (rdl->history_cur_line == 0) { > - rdline_remove_first_history_item(rdl); > - } > - if (rdl->history_cur_line <= 0) { > - rdline_add_history(rdl, rdline_get_buffer(rdl)); > - rdl->history_cur_line = 0; > - } > - > - buf = rdline_get_history_item(rdl, rdl->history_cur_line + 1); > - if (!buf) > - break; > - > - rdl->history_cur_line ++; > - vt100_init(&rdl->vt100); > - cirbuf_init(&rdl->left, rdl->left_buf, 0, RDLINE_BUF_SIZE); > - cirbuf_init(&rdl->right, rdl->right_buf, 0, RDLINE_BUF_SIZE); > - cirbuf_add_buf_tail(&rdl->left, buf, strnlen(buf, RDLINE_BUF_SIZE)); > - rdline_redisplay(rdl); > - break; > - > - /* next element in history */ > - case CMDLINE_KEY_DOWN_ARR: > - case CMDLINE_KEY_CTRL_N: > - if (rdl->history_cur_line - 1 < 0) > - break; > - > - rdl->history_cur_line --; > - buf = rdline_get_history_item(rdl, rdl->history_cur_line); > - if (!buf) > - break; > - vt100_init(&rdl->vt100); > - cirbuf_init(&rdl->left, rdl->left_buf, 0, RDLINE_BUF_SIZE); > - cirbuf_init(&rdl->right, rdl->right_buf, 0, RDLINE_BUF_SIZE); > - cirbuf_add_buf_tail(&rdl->left, buf, strnlen(buf, RDLINE_BUF_SIZE)); > - rdline_redisplay(rdl); > - > - break; > - > - > - default: > - break; > - } > - > - return RDLINE_RES_SUCCESS; > - } > - > - if (!isprint((int)c)) > - return RDLINE_RES_SUCCESS; > - > - /* standard chars */ > - if (CIRBUF_GET_LEN(&rdl->left) + CIRBUF_GET_LEN(&rdl->right) >= RDLINE_BUF_SIZE) > - return RDLINE_RES_SUCCESS; > - > - if (cirbuf_add_tail_safe(&rdl->left, c)) > - return RDLINE_RES_SUCCESS; > - > - rdl->write_char(rdl, c); > - display_right_buffer(rdl, 0); > - > - return RDLINE_RES_SUCCESS; > -} > - > - > -/* HISTORY */ > - > -static void > -rdline_remove_old_history_item(struct rdline * rdl) > -{ > - char tmp; > - > - while (! CIRBUF_IS_EMPTY(&rdl->history) ) { > - tmp = cirbuf_get_head(&rdl->history); > - cirbuf_del_head(&rdl->history); > - if (!tmp) > - break; > - } > -} > - > -static void > -rdline_remove_first_history_item(struct rdline * rdl) > -{ > - char tmp; > - > - if ( CIRBUF_IS_EMPTY(&rdl->history) ) { > - return; > - } > - else { > - cirbuf_del_tail(&rdl->history); > - } > - > - while (! CIRBUF_IS_EMPTY(&rdl->history) ) { > - tmp = cirbuf_get_tail(&rdl->history); > - if (!tmp) > - break; > - cirbuf_del_tail(&rdl->history); > - } > -} > - > -static unsigned int > -rdline_get_history_size(struct rdline * rdl) > -{ > - unsigned int i, tmp, ret=0; > - > - CIRBUF_FOREACH(&rdl->history, i, tmp) { > - if (tmp == 0) > - ret ++; > - } > - > - return ret; > -} > - > -char * > -rdline_get_history_item(struct rdline * rdl, unsigned int idx) > -{ > - unsigned int len, i, tmp; > - > - if (!rdl) > - return NULL; > - > - len = rdline_get_history_size(rdl); > - if ( idx >= len ) { > - return NULL; > - } > - > - cirbuf_align_left(&rdl->history); > - > - CIRBUF_FOREACH(&rdl->history, i, tmp) { > - if ( idx == len - 1) { > - return rdl->history_buf + i; > - } > - if (tmp == 0) > - len --; > - } > - > - return NULL; > -} > - > -int > -rdline_add_history(struct rdline * rdl, const char * buf) > -{ > - unsigned int len, i; > - > - if (!rdl || !buf) > - return -EINVAL; > - > - len = strnlen(buf, RDLINE_BUF_SIZE); > - for (i=0; i<len ; i++) { > - if (buf[i] == '\n') { > - len = i; > - break; > - } > - } > - > - if ( len >= RDLINE_HISTORY_BUF_SIZE ) > - return -1; > - > - while ( len >= CIRBUF_GET_FREELEN(&rdl->history) ) { > - rdline_remove_old_history_item(rdl); > - } > - > - cirbuf_add_buf_tail(&rdl->history, buf, len); > - cirbuf_add_tail(&rdl->history, 0); > - > - return 0; > -} > - > -void > -rdline_clear_history(struct rdline * rdl) > -{ > - if (!rdl) > - return; > - cirbuf_init(&rdl->history, rdl->history_buf, 0, RDLINE_HISTORY_BUF_SIZE); > -} > - > - > -/* STATIC USEFUL FUNCS */ > - > -static void > -rdline_puts(struct rdline * rdl, const char * buf) > -{ > - char c; > - while ( (c = *(buf++)) != '\0' ) { > - rdl->write_char(rdl, c); > - } > -} > - > -/* a very very basic printf with one arg and one format 'u' */ > -static void > -rdline_miniprintf(struct rdline *rdl, const char * buf, unsigned int val) > -{ > - char c, started=0, div=100; > - > - while ( (c=*(buf++)) ) { > - if (c != '%') { > - rdl->write_char(rdl, c); > - continue; > - } > - c = *(buf++); > - if (c != 'u') { > - rdl->write_char(rdl, '%'); > - rdl->write_char(rdl, c); > - continue; > - } > - /* val is never more than 255 */ > - while (div) { > - c = (char)(val / div); > - if (c || started) { > - rdl->write_char(rdl, (char)(c+'0')); > - started = 1; > - } > - val %= div; > - div /= 10; > - } > - } > -} > diff --git a/lib/librte_cmdline/cmdline_rdline.h b/lib/librte_cmdline/cmdline_rdline.h > deleted file mode 100644 > index 72e2dad..0000000 > --- a/lib/librte_cmdline/cmdline_rdline.h > +++ /dev/null > @@ -1,255 +0,0 @@ > -/*- > - * BSD LICENSE > - * > - * Copyright(c) 2010-2014 Intel Corporation. All rights reserved. > - * 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 <zer0@droids-corp.org> > - * 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 the University of California, Berkeley 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 REGENTS 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 REGENTS AND 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. > - */ > - > -#ifndef _RDLINE_H_ > -#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. > - * > - * Obviously, it does not support as many things as the GNU readline, > - * but at least it supports some interesting 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. > - */ > - > -#include <stdio.h> > -#include <cmdline_cirbuf.h> > -#include <cmdline_vt100.h> > - > -#ifdef __cplusplus > -extern "C" { > -#endif > - > -/* configuration */ > -#define RDLINE_BUF_SIZE 512 > -#define RDLINE_PROMPT_SIZE 32 > -#define RDLINE_VT100_BUF_SIZE 8 > -#define RDLINE_HISTORY_BUF_SIZE BUFSIZ > -#define RDLINE_HISTORY_MAX_LINE 64 > - > -enum rdline_status { > - RDLINE_INIT, > - RDLINE_RUNNING, > - RDLINE_EXITED > -}; > - > -struct rdline; > - > -typedef int (rdline_write_char_t)(struct rdline *rdl, char); > -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); > - > -struct rdline { > - enum rdline_status status; > - /* rdline bufs */ > - struct cirbuf left; > - struct cirbuf right; > - char left_buf[RDLINE_BUF_SIZE+2]; /* reserve 2 chars for the \n\0 */ > - char right_buf[RDLINE_BUF_SIZE]; > - > - char prompt[RDLINE_PROMPT_SIZE]; > - unsigned int prompt_size; > - > - char kill_buf[RDLINE_BUF_SIZE]; > - unsigned int kill_size; > - > - /* history */ > - struct cirbuf history; > - char history_buf[RDLINE_HISTORY_BUF_SIZE]; > - int history_cur_line; > - > - /* callbacks and func pointers */ > - rdline_write_char_t *write_char; > - rdline_validate_t *validate; > - rdline_complete_t *complete; > - > - /* vt100 parser */ > - struct cmdline_vt100 vt100; > - > - /* opaque pointer */ > - void *opaque; > -}; > - > -/** > - * 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. > - */ > -int rdline_init(struct rdline *rdl, > - rdline_write_char_t *write_char, > - rdline_validate_t *validate, > - rdline_complete_t *complete); > - > - > -/** > - * Init the current buffer, and display a prompt. > - * \param rdl A pointer to a 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 > - */ > -void rdline_stop(struct rdline *rdl); > - > -/** > - * Same than rdline_stop() except that next calls to rdline_char_in() > - * will return RDLINE_RES_EXITED. > - * \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 > - */ > -void rdline_redisplay(struct rdline *rdl); > - > -/** > - * Reset the current buffer and setup for a new line. > - * \param rdl A pointer to a struct rdline > - */ > -void rdline_reset(struct rdline *rdl); > - > - > -/* return status for rdline_char_in() */ > -#define RDLINE_RES_SUCCESS 0 > -#define RDLINE_RES_VALIDATED 1 > -#define RDLINE_RES_COMPLETE 2 > -#define RDLINE_RES_NOT_RUNNING -1 > -#define RDLINE_RES_EOF -2 > -#define RDLINE_RES_EXITED -3 > - > -/** > - * append a char to the readline buffer. > - * Return RDLINE_RES_VALIDATE when the line has been validated. > - * Return RDLINE_RES_COMPLETE when the user asked to complete the buffer. > - * Return RDLINE_RES_NOT_RUNNING if it is not running. > - * Return RDLINE_RES_EOF if EOF (ctrl-d on an empty line). > - * Else return RDLINE_RES_SUCCESS. > - * XXX error case when the buffer is full ? > - * > - * \param rdl A pointer to a struct rdline > - * \param c The character to append > - */ > -int rdline_char_in(struct rdline *rdl, char c); > - > -/** > - * Return the current buffer, terminated by '\0'. > - * \param rdl A pointer to a struct rdline > - */ > -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' > - */ > -int rdline_add_history(struct rdline *rdl, const char *buf); > - > -/** > - * Clear current history > - * \param rdl A pointer to a struct rdline > - */ > -void rdline_clear_history(struct rdline *rdl); > - > -/** > - * Get the i-th history item > - */ > -char *rdline_get_history_item(struct rdline *rdl, unsigned int i); > - > -#ifdef __cplusplus > -} > -#endif > - > -#endif /* _RDLINE_H_ */ > diff --git a/lib/librte_cmdline/cmdline_socket.c b/lib/librte_cmdline/cmdline_socket.c > index 3fc243b..11524b5 100644 > --- a/lib/librte_cmdline/cmdline_socket.c > +++ b/lib/librte_cmdline/cmdline_socket.c > @@ -58,23 +58,18 @@ > * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. > */ > > -#include <stdio.h> > -#include <string.h> > +#include <stddef.h> > #include <unistd.h> > -#include <stdlib.h> > -#include <stdarg.h> > -#include <inttypes.h> > #include <fcntl.h> > -#include <termios.h> > > #include "cmdline_parse.h" > -#include "cmdline_rdline.h" > #include "cmdline_socket.h" > #include "cmdline.h" > > struct cmdline * > cmdline_file_new(cmdline_parse_ctx_t *ctx, const char *prompt, const char *path) > { > + struct cmdline *cl; > int fd; > > /* everything else is checked in cmdline_new() */ > @@ -83,37 +78,22 @@ cmdline_file_new(cmdline_parse_ctx_t *ctx, const char *prompt, const char *path) > > fd = open(path, O_RDONLY, 0); > if (fd < 0) { > - dprintf("open() failed\n"); > return NULL; > } > - return cmdline_new(ctx, prompt, fd, -1); > + cl = cmdline_new(ctx, prompt, fd, -1); > + /* cmdline_new() duplicates fd */ > + close(fd); > + return cl; > } > > struct cmdline * > cmdline_stdin_new(cmdline_parse_ctx_t *ctx, const char *prompt) > { > - struct cmdline *cl; > - struct termios oldterm, term; > - > - tcgetattr(0, &oldterm); > - memcpy(&term, &oldterm, sizeof(term)); > - term.c_lflag &= ~(ICANON | ECHO | ISIG); > - tcsetattr(0, TCSANOW, &term); > - setbuf(stdin, NULL); > - > - cl = cmdline_new(ctx, prompt, 0, 1); > - > - if (cl) > - memcpy(&cl->oldterm, &oldterm, sizeof(term)); > - > - return cl; > + return cmdline_new(ctx, prompt, 0, 1); > } > > void > cmdline_stdin_exit(struct cmdline *cl) > { > - if (!cl) > - return; > - > - tcsetattr(fileno(stdin), TCSANOW, &cl->oldterm); > + cmdline_free(cl); > } > diff --git a/lib/librte_cmdline/cmdline_vt100.c b/lib/librte_cmdline/cmdline_vt100.c > deleted file mode 100644 > index a253e8b..0000000 > --- a/lib/librte_cmdline/cmdline_vt100.c > +++ /dev/null > @@ -1,185 +0,0 @@ > -/*- > - * BSD LICENSE > - * > - * Copyright(c) 2010-2014 Intel Corporation. All rights reserved. > - * 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 <zer0@droids-corp.org> > - * 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 the University of California, Berkeley 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 REGENTS 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 REGENTS AND 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. > - */ > - > -#include <stdlib.h> > -#include <stdint.h> > -#include <stdio.h> > -#include <string.h> > -#include <stdarg.h> > -#include <ctype.h> > -#include <termios.h> > - > -#include "cmdline_vt100.h" > - > -const char *cmdline_vt100_commands[] = { > - vt100_up_arr, > - vt100_down_arr, > - vt100_right_arr, > - vt100_left_arr, > - "\177", > - "\n", > - "\001", > - "\005", > - "\013", > - "\031", > - "\003", > - "\006", > - "\002", > - vt100_suppr, > - vt100_tab, > - "\004", > - "\014", > - "\r", > - "\033\177", > - vt100_word_left, > - vt100_word_right, > - "?", > - "\027", > - "\020", > - "\016", > - "\033\144", > -}; > - > -void > -vt100_init(struct cmdline_vt100 *vt) > -{ > - if (!vt) > - return; > - vt->state = CMDLINE_VT100_INIT; > -} > - > - > -static int > -match_command(char *buf, unsigned int size) > -{ > - const char *cmd; > - size_t cmdlen; > - unsigned int i = 0; > - > - for (i=0 ; i<sizeof(cmdline_vt100_commands)/sizeof(const char *) ; i++) { > - cmd = *(cmdline_vt100_commands + i); > - > - cmdlen = strnlen(cmd, CMDLINE_VT100_BUF_SIZE); > - if (size == cmdlen && > - !strncmp(buf, cmd, cmdlen)) { > - return i; > - } > - } > - > - return -1; > -} > - > -int > -vt100_parser(struct cmdline_vt100 *vt, char ch) > -{ > - unsigned int size; > - uint8_t c = (uint8_t) ch; > - > - if (!vt) > - return -1; > - > - if (vt->bufpos >= CMDLINE_VT100_BUF_SIZE) { > - vt->state = CMDLINE_VT100_INIT; > - vt->bufpos = 0; > - } > - > - vt->buf[vt->bufpos++] = c; > - size = vt->bufpos; > - > - switch (vt->state) { > - case CMDLINE_VT100_INIT: > - if (c == 033) { > - vt->state = CMDLINE_VT100_ESCAPE; > - } > - else { > - vt->bufpos = 0; > - goto match_command; > - } > - break; > - > - case CMDLINE_VT100_ESCAPE: > - if (c == 0133) { > - vt->state = CMDLINE_VT100_ESCAPE_CSI; > - } > - else if (c >= 060 && c <= 0177) { /* XXX 0177 ? */ > - vt->bufpos = 0; > - vt->state = CMDLINE_VT100_INIT; > - goto match_command; > - } > - break; > - > - case CMDLINE_VT100_ESCAPE_CSI: > - if (c >= 0100 && c <= 0176) { > - vt->bufpos = 0; > - vt->state = CMDLINE_VT100_INIT; > - goto match_command; > - } > - break; > - > - default: > - vt->bufpos = 0; > - break; > - } > - > - return -2; > - > - match_command: > - return match_command(vt->buf, size); > -} > diff --git a/lib/librte_cmdline/cmdline_vt100.h b/lib/librte_cmdline/cmdline_vt100.h > deleted file mode 100644 > index 963add8..0000000 > --- a/lib/librte_cmdline/cmdline_vt100.h > +++ /dev/null > @@ -1,153 +0,0 @@ > -/*- > - * BSD LICENSE > - * > - * Copyright(c) 2010-2014 Intel Corporation. All rights reserved. > - * 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 <zer0@droids-corp.org> > - * 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 the University of California, Berkeley 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 REGENTS 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 REGENTS AND 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. > - */ > - > -#ifndef _CMDLINE_VT100_H_ > -#define _CMDLINE_VT100_H_ > - > -#include <stdint.h> > - > -#ifdef __cplusplus > -extern "C" { > -#endif > - > -#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" > - > -/* Result of parsing : it must be synchronized with > - * cmdline_vt100_commands[] in vt100.c */ > -#define CMDLINE_KEY_UP_ARR 0 > -#define CMDLINE_KEY_DOWN_ARR 1 > -#define CMDLINE_KEY_RIGHT_ARR 2 > -#define CMDLINE_KEY_LEFT_ARR 3 > -#define CMDLINE_KEY_BKSPACE 4 > -#define CMDLINE_KEY_RETURN 5 > -#define CMDLINE_KEY_CTRL_A 6 > -#define CMDLINE_KEY_CTRL_E 7 > -#define CMDLINE_KEY_CTRL_K 8 > -#define CMDLINE_KEY_CTRL_Y 9 > -#define CMDLINE_KEY_CTRL_C 10 > -#define CMDLINE_KEY_CTRL_F 11 > -#define CMDLINE_KEY_CTRL_B 12 > -#define CMDLINE_KEY_SUPPR 13 > -#define CMDLINE_KEY_TAB 14 > -#define CMDLINE_KEY_CTRL_D 15 > -#define CMDLINE_KEY_CTRL_L 16 > -#define CMDLINE_KEY_RETURN2 17 > -#define CMDLINE_KEY_META_BKSPACE 18 > -#define CMDLINE_KEY_WLEFT 19 > -#define CMDLINE_KEY_WRIGHT 20 > -#define CMDLINE_KEY_HELP 21 > -#define CMDLINE_KEY_CTRL_W 22 > -#define CMDLINE_KEY_CTRL_P 23 > -#define CMDLINE_KEY_CTRL_N 24 > -#define CMDLINE_KEY_META_D 25 > - > -extern const char *cmdline_vt100_commands[]; > - > -enum cmdline_vt100_parser_state { > - CMDLINE_VT100_INIT, > - CMDLINE_VT100_ESCAPE, > - CMDLINE_VT100_ESCAPE_CSI > -}; > - > -#define CMDLINE_VT100_BUF_SIZE 8 > -struct cmdline_vt100 { > - uint8_t bufpos; > - char buf[CMDLINE_VT100_BUF_SIZE]; > - enum cmdline_vt100_parser_state state; > -}; > - > -/** > - * Init > - */ > -void vt100_init(struct cmdline_vt100 *vt); > - > -/** > - * Input a new character. > - * Return -1 if the character is not part of a control sequence > - * Return -2 if c is not the last char of a control sequence > - * Else return the index in vt100_commands[] > - */ > -int vt100_parser(struct cmdline_vt100 *vt, char c); > - > -#ifdef __cplusplus > -} > -#endif > - > -#endif > diff --git a/lib/librte_cmdline/rte_cmdline_version.map b/lib/librte_cmdline/rte_cmdline_version.map > index 04bcb38..3133199 100644 > --- a/lib/librte_cmdline/rte_cmdline_version.map > +++ b/lib/librte_cmdline/rte_cmdline_version.map > @@ -1,25 +1,6 @@ > DPDK_2.0 { > global: > > - cirbuf_add_buf_head; > - cirbuf_add_buf_tail; > - cirbuf_add_head; > - cirbuf_add_head_safe; > - cirbuf_add_tail; > - cirbuf_add_tail_safe; > - cirbuf_align_left; > - cirbuf_align_right; > - cirbuf_del_buf_head; > - cirbuf_del_buf_tail; > - cirbuf_del_head; > - cirbuf_del_head_safe; > - cirbuf_del_tail; > - cirbuf_del_tail_safe; > - cirbuf_get_buf_head; > - cirbuf_get_buf_tail; > - cirbuf_get_head; > - cirbuf_get_tail; > - cirbuf_init; > cmdline_complete; > cmdline_complete_get_elt_string; > cmdline_complete_get_nb_string; > @@ -50,21 +31,6 @@ DPDK_2.0 { > cmdline_token_num_ops; > cmdline_token_portlist_ops; > cmdline_token_string_ops; > - cmdline_write_char; > - rdline_add_history; > - rdline_char_in; > - rdline_clear_history; > - rdline_get_buffer; > - rdline_get_history_item; > - rdline_init; > - rdline_newline; > - rdline_quit; > - rdline_redisplay; > - rdline_reset; > - rdline_restart; > - rdline_stop; > - vt100_init; > - vt100_parser; > > local: *; > }; > @@ -75,3 +41,10 @@ DPDK_2.1 { > cmdline_poll; > > } DPDK_2.0; > + > +DPDK_18.02 { > + global: > + > + cmdline_ctx_get; > + > +} DPDK_2.1; > diff --git a/mk/rte.app.mk b/mk/rte.app.mk > index 6a6a745..504bb4e 100644 > --- a/mk/rte.app.mk > +++ b/mk/rte.app.mk > @@ -102,6 +102,8 @@ _LDLIBS-$(CONFIG_RTE_LIBRTE_RING) += -lrte_ring > _LDLIBS-$(CONFIG_RTE_LIBRTE_PCI) += -lrte_pci > _LDLIBS-$(CONFIG_RTE_LIBRTE_EAL) += -lrte_eal > _LDLIBS-$(CONFIG_RTE_LIBRTE_CMDLINE) += -lrte_cmdline > + > +_LDLIBS-$(CONFIG_RTE_LIBRTE_CMDLINE) += $(shell pkg-config --libs libedit) > _LDLIBS-$(CONFIG_RTE_LIBRTE_REORDER) += -lrte_reorder > _LDLIBS-$(CONFIG_RTE_LIBRTE_SCHED) += -lrte_sched > > diff --git a/test/cmdline_test/cmdline_test.c b/test/cmdline_test/cmdline_test.c > index 716b5f1..595efa5 100644 > --- a/test/cmdline_test/cmdline_test.c > +++ b/test/cmdline_test/cmdline_test.c > @@ -41,7 +41,6 @@ > #include <ctype.h> > #include <sys/queue.h> > > -#include <cmdline_rdline.h> > #include <cmdline_parse.h> > #include <cmdline_socket.h> > #include <cmdline.h> > diff --git a/test/cmdline_test/commands.c b/test/cmdline_test/commands.c > index 404f51a..8481af9 100644 > --- a/test/cmdline_test/commands.c > +++ b/test/cmdline_test/commands.c > @@ -36,7 +36,6 @@ > #include <termios.h> > #include <inttypes.h> > > -#include <cmdline_rdline.h> > #include <cmdline_parse.h> > #include <cmdline_parse_string.h> > #include <cmdline_parse_num.h> > @@ -306,72 +305,6 @@ cmdline_parse_inst_t cmd_ambig_2 = { > > > > -/*** get_history_bufsize ***/ > -/* command that displays total space in history buffer > - * this will be useful for testing history (to fill it up just enough to > - * remove the last entry, we need to know how big it is). > - */ > - > -struct cmd_get_history_bufsize_result { > - cmdline_fixed_string_t str; > -}; > - > -static void > -cmd_get_history_bufsize_parsed(__attribute__((unused)) void *parsed_result, > - struct cmdline *cl, > - __attribute__((unused)) void *data) > -{ > - cmdline_printf(cl, "History buffer size: %zu\n", > - sizeof(cl->rdl.history_buf)); > -} > - > -cmdline_parse_token_string_t cmd_get_history_bufsize_tok = > - TOKEN_STRING_INITIALIZER(struct cmd_get_history_bufsize_result, str, > - "get_history_bufsize"); > - > -cmdline_parse_inst_t cmd_get_history_bufsize = { > - .f = cmd_get_history_bufsize_parsed, /* function to call */ > - .data = NULL, /* 2nd arg of func */ > - .help_str = "command that displays total space in history buffer", > - .tokens = { /* token list, NULL terminated */ > - (void *)&cmd_get_history_bufsize_tok, > - NULL, > - }, > -}; > - > - > - > -/*** clear_history ***/ > -/* clears history buffer */ > - > -struct cmd_clear_history_result { > - cmdline_fixed_string_t str; > -}; > - > -static void > -cmd_clear_history_parsed(__attribute__((unused)) void *parsed_result, > - struct cmdline *cl, > - __attribute__((unused)) void *data) > -{ > - rdline_clear_history(&cl->rdl); > -} > - > -cmdline_parse_token_string_t cmd_clear_history_tok = > - TOKEN_STRING_INITIALIZER(struct cmd_clear_history_result, str, > - "clear_history"); > - > -cmdline_parse_inst_t cmd_clear_history = { > - .f = cmd_clear_history_parsed, /* function to call */ > - .data = NULL, /* 2nd arg of func */ > - .help_str = "clear command history", > - .tokens = { /* token list, NULL terminated */ > - (void *)&cmd_clear_history_tok, > - NULL, > - }, > -}; > - > - > - > /****************/ > > cmdline_parse_ctx_t main_ctx[] = { > @@ -381,8 +314,6 @@ cmdline_parse_ctx_t main_ctx[] = { > (cmdline_parse_inst_t *)&cmd_single, > (cmdline_parse_inst_t *)&cmd_single_long, > (cmdline_parse_inst_t *)&cmd_num, > - (cmdline_parse_inst_t *)&cmd_get_history_bufsize, > - (cmdline_parse_inst_t *)&cmd_clear_history, > (cmdline_parse_inst_t *)&cmd_autocomplete_1, > (cmdline_parse_inst_t *)&cmd_autocomplete_2, > NULL, > diff --git a/test/test/Makefile b/test/test/Makefile > index bb54c98..49e907c 100644 > --- a/test/test/Makefile > +++ b/test/test/Makefile > @@ -164,7 +164,6 @@ SRCS-$(CONFIG_RTE_LIBRTE_CMDLINE) += test_cmdline_num.c > SRCS-$(CONFIG_RTE_LIBRTE_CMDLINE) += test_cmdline_etheraddr.c > SRCS-$(CONFIG_RTE_LIBRTE_CMDLINE) += test_cmdline_portlist.c > SRCS-$(CONFIG_RTE_LIBRTE_CMDLINE) += test_cmdline_ipaddr.c > -SRCS-$(CONFIG_RTE_LIBRTE_CMDLINE) += test_cmdline_cirbuf.c > SRCS-$(CONFIG_RTE_LIBRTE_CMDLINE) += test_cmdline_string.c > SRCS-$(CONFIG_RTE_LIBRTE_CMDLINE) += test_cmdline_lib.c > > diff --git a/test/test/commands.c b/test/test/commands.c > index 4097a33..21a4a06 100644 > --- a/test/test/commands.c > +++ b/test/test/commands.c > @@ -66,7 +66,6 @@ > #include <rte_mbuf.h> > #include <rte_devargs.h> > > -#include <cmdline_rdline.h> > #include <cmdline_parse.h> > #include <cmdline_parse_ipaddr.h> > #include <cmdline_parse_num.h> > diff --git a/test/test/test.c b/test/test/test.c > index 0e6ff7c..6f48892 100644 > --- a/test/test/test.c > +++ b/test/test/test.c > @@ -42,7 +42,6 @@ > #include <sys/queue.h> > > #ifdef RTE_LIBRTE_CMDLINE > -#include <cmdline_rdline.h> > #include <cmdline_parse.h> > #include <cmdline_socket.h> > #include <cmdline.h> > diff --git a/test/test/test_cmdline.c b/test/test/test_cmdline.c > index 38c7256..056b569 100644 > --- a/test/test/test_cmdline.c > +++ b/test/test/test_cmdline.c > @@ -74,15 +74,6 @@ test_cmdline(void) > return -1; > if (test_parse_string_invalid_param() < 0) > return -1; > - printf("Testing circular buffer...\n"); > - if (test_cirbuf_char() < 0) > - return -1; > - if (test_cirbuf_string() < 0) > - return -1; > - if (test_cirbuf_align() < 0) > - return -1; > - if (test_cirbuf_invalid_param() < 0) > - return -1; > printf("Testing library functions...\n"); > if (test_cmdline_lib() < 0) > return -1; > diff --git a/test/test/test_cmdline.h b/test/test/test_cmdline.h > index 0ee91c1..b55caa9 100644 > --- a/test/test/test_cmdline.h > +++ b/test/test/test_cmdline.h > @@ -61,12 +61,6 @@ int test_parse_string_valid(void); > int test_parse_string_invalid_data(void); > int test_parse_string_invalid_param(void); > > -/* cmdline_cirbuf tests */ > -int test_cirbuf_invalid_param(void); > -int test_cirbuf_char(void); > -int test_cirbuf_string(void); > -int test_cirbuf_align(void); > - > /* test the rest of the library */ > int test_cmdline_lib(void); > > diff --git a/test/test/test_cmdline_cirbuf.c b/test/test/test_cmdline_cirbuf.c > deleted file mode 100644 > index 2c32145..0000000 > --- a/test/test/test_cmdline_cirbuf.c > +++ /dev/null > @@ -1,1330 +0,0 @@ > -/*- > - * BSD LICENSE > - * > - * Copyright(c) 2010-2014 Intel Corporation. All rights reserved. > - * 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. > - */ > - > -#include <stdio.h> > -#include <stdlib.h> > -#include <string.h> > - > -#include <rte_string_fns.h> > - > -#include <cmdline_cirbuf.h> > - > -#include "test_cmdline.h" > - > -/* different length strings */ > -#define CIRBUF_STR_HEAD " HEAD" > -#define CIRBUF_STR_TAIL "TAIL" > - > -/* miscellaneous tests - they make bullseye happy */ > -static int > -test_cirbuf_string_misc(void) > -{ > - struct cirbuf cb; > - char buf[CMDLINE_TEST_BUFSIZE]; > - char tmp[CMDLINE_TEST_BUFSIZE]; > - > - /* initialize buffers */ > - memset(buf, 0, sizeof(buf)); > - memset(tmp, 0, sizeof(tmp)); > - > - /* > - * initialize circular buffer > - */ > - if (cirbuf_init(&cb, buf, 0, sizeof(buf)) < 0) { > - printf("Error: failed to initialize circular buffer!\n"); > - return -1; > - } > - > - /* > - * add strings to head and tail, but read only tail > - * this results in read operation that does not transcend > - * from buffer end to buffer beginning (in other words, > - * strlen <= cb->maxlen - cb->end) > - */ > - > - /* add string to head */ > - if (cirbuf_add_buf_head(&cb, CIRBUF_STR_HEAD, sizeof(CIRBUF_STR_HEAD)) > - != (sizeof(CIRBUF_STR_HEAD))) { > - printf("Error: failed to add string to head!\n"); > - return -1; > - } > - /* add string to tail */ > - if (cirbuf_add_buf_tail(&cb, CIRBUF_STR_TAIL, sizeof(CIRBUF_STR_TAIL)) > - != (sizeof(CIRBUF_STR_TAIL))) { > - printf("Error: failed to add string to head!\n"); > - return -1; > - } > - /* read string from tail */ > - if (cirbuf_get_buf_tail(&cb, tmp, sizeof(CIRBUF_STR_TAIL)) > - != (sizeof(CIRBUF_STR_TAIL))) { > - printf("Error: failed to get string from tail!\n"); > - return -1; > - } > - /* verify string */ > - if (strncmp(tmp, CIRBUF_STR_TAIL, sizeof(CIRBUF_STR_TAIL)) != 0) { > - printf("Error: tail strings do not match!\n"); > - return -1; > - } > - /* clear buffers */ > - memset(tmp, 0, sizeof(tmp)); > - memset(buf, 0, sizeof(buf)); > - > - > - > - /* > - * add a string to buffer when start/end is at end of buffer > - */ > - > - /* > - * reinitialize circular buffer with start at the end of cirbuf > - */ > - if (cirbuf_init(&cb, buf, CMDLINE_TEST_BUFSIZE - 2, sizeof(buf)) < 0) { > - printf("Error: failed to reinitialize circular buffer!\n"); > - return -1; > - } > - > - > - /* add string to tail */ > - if (cirbuf_add_buf_tail(&cb, CIRBUF_STR_TAIL, sizeof(CIRBUF_STR_TAIL)) > - != (sizeof(CIRBUF_STR_TAIL))) { > - printf("Error: failed to add string to tail!\n"); > - return -1; > - } > - /* read string from tail */ > - if (cirbuf_get_buf_tail(&cb, tmp, sizeof(CIRBUF_STR_TAIL)) > - != (sizeof(CIRBUF_STR_TAIL))) { > - printf("Error: failed to get string from tail!\n"); > - return -1; > - } > - /* verify string */ > - if (strncmp(tmp, CIRBUF_STR_TAIL, sizeof(CIRBUF_STR_TAIL)) != 0) { > - printf("Error: tail strings do not match!\n"); > - return -1; > - } > - /* clear tmp buffer */ > - memset(tmp, 0, sizeof(tmp)); > - > - > - /* add string to head */ > - if (cirbuf_add_buf_head(&cb, CIRBUF_STR_HEAD, sizeof(CIRBUF_STR_HEAD)) > - != (sizeof(CIRBUF_STR_HEAD))) { > - printf("Error: failed to add string to head!\n"); > - return -1; > - } > - /* read string from tail */ > - if (cirbuf_get_buf_head(&cb, tmp, sizeof(CIRBUF_STR_HEAD)) > - != (sizeof(CIRBUF_STR_HEAD))) { > - printf("Error: failed to get string from head!\n"); > - return -1; > - } > - /* verify string */ > - if (strncmp(tmp, CIRBUF_STR_HEAD, sizeof(CIRBUF_STR_HEAD)) != 0) { > - printf("Error: headstrings do not match!\n"); > - return -1; > - } > - > - return 0; > -} > - > -/* test adding and deleting strings */ > -static int > -test_cirbuf_string_add_del(void) > -{ > - struct cirbuf cb; > - char buf[CMDLINE_TEST_BUFSIZE]; > - char tmp[CMDLINE_TEST_BUFSIZE]; > - > - /* initialize buffers */ > - memset(buf, 0, sizeof(buf)); > - memset(tmp, 0, sizeof(tmp)); > - > - /* > - * initialize circular buffer > - */ > - if (cirbuf_init(&cb, buf, 0, sizeof(buf)) < 0) { > - printf("Error: failed to initialize circular buffer!\n"); > - return -1; > - } > - > - /* add string to head */ > - if (cirbuf_add_buf_head(&cb, CIRBUF_STR_HEAD, sizeof(CIRBUF_STR_HEAD)) > - != (sizeof(CIRBUF_STR_HEAD))) { > - printf("Error: failed to add string to head!\n"); > - return -1; > - } > - /* read string from head */ > - if (cirbuf_get_buf_head(&cb, tmp, sizeof(CIRBUF_STR_HEAD)) > - != (sizeof(CIRBUF_STR_HEAD))) { > - printf("Error: failed to get string from head!\n"); > - return -1; > - } > - /* verify string */ > - if (strncmp(tmp, CIRBUF_STR_HEAD, sizeof(CIRBUF_STR_HEAD)) != 0) { > - printf("Error: head strings do not match!\n"); > - return -1; > - } > - /* clear tmp buffer */ > - memset(tmp, 0, sizeof(tmp)); > - /* read string from tail */ > - if (cirbuf_get_buf_tail(&cb, tmp, sizeof(CIRBUF_STR_HEAD)) > - != (sizeof(CIRBUF_STR_HEAD))) { > - printf("Error: failed to get string from head!\n"); > - return -1; > - } > - /* verify string */ > - if (strncmp(tmp, CIRBUF_STR_HEAD, sizeof(CIRBUF_STR_HEAD)) != 0) { > - printf("Error: head strings do not match!\n"); > - return -1; > - } > - /* delete string from head*/ > - if (cirbuf_del_buf_head(&cb, sizeof(CIRBUF_STR_HEAD)) < 0) { > - printf("Error: failed to delete string from head!\n"); > - return -1; > - } > - /* verify string was deleted */ > - if (cirbuf_del_head_safe(&cb) == 0) { > - printf("Error: buffer should have been empty!\n"); > - return -1; > - } > - /* clear tmp buffer */ > - memset(tmp, 0, sizeof(tmp)); > - > - > - > - /* > - * reinitialize circular buffer > - */ > - memset(buf, 0, sizeof(buf)); > - if (cirbuf_init(&cb, buf, 0, sizeof(buf)) < 0) { > - printf("Error: failed to reinitialize circular buffer!\n"); > - return -1; > - } > - > - /* add string to tail */ > - if (cirbuf_add_buf_tail(&cb, CIRBUF_STR_TAIL, sizeof(CIRBUF_STR_TAIL)) > - != (sizeof(CIRBUF_STR_TAIL))) { > - printf("Error: failed to add string to tail!\n"); > - return -1; > - } > - /* get string from tail */ > - if (cirbuf_get_buf_tail(&cb, tmp, sizeof(CIRBUF_STR_TAIL)) > - != (sizeof(CIRBUF_STR_TAIL))) { > - printf("Error: failed to get string from tail!\n"); > - return -1; > - } > - /* verify string */ > - if (strncmp(tmp, CIRBUF_STR_TAIL, sizeof(CIRBUF_STR_TAIL)) != 0) { > - printf("Error: tail strings do not match!\n"); > - return -1; > - } > - /* clear tmp buffer */ > - memset(tmp, 0, sizeof(tmp)); > - /* get string from head */ > - if (cirbuf_get_buf_head(&cb, tmp, sizeof(CIRBUF_STR_TAIL)) > - != (sizeof(CIRBUF_STR_TAIL))) { > - printf("Error: failed to get string from tail!\n"); > - return -1; > - } > - /* verify string */ > - if (strncmp(tmp, CIRBUF_STR_TAIL, sizeof(CIRBUF_STR_TAIL)) != 0) { > - printf("Error: tail strings do not match!\n"); > - return -1; > - } > - /* delete string from tail */ > - if (cirbuf_del_buf_tail(&cb, sizeof(CIRBUF_STR_TAIL)) < 0) { > - printf("Error: failed to delete string from tail!\n"); > - return -1; > - } > - /* verify string was deleted */ > - if (cirbuf_del_tail_safe(&cb) == 0) { > - printf("Error: buffer should have been empty!\n"); > - return -1; > - } > - > - return 0; > -} > - > -/* test adding from head and deleting from tail, and vice versa */ > -static int > -test_cirbuf_string_add_del_reverse(void) > -{ > - struct cirbuf cb; > - char buf[CMDLINE_TEST_BUFSIZE]; > - char tmp[CMDLINE_TEST_BUFSIZE]; > - > - /* initialize buffers */ > - memset(buf, 0, sizeof(buf)); > - memset(tmp, 0, sizeof(tmp)); > - > - /* > - * initialize circular buffer > - */ > - if (cirbuf_init(&cb, buf, 0, sizeof(buf)) < 0) { > - printf("Error: failed to initialize circular buffer!\n"); > - return -1; > - } > - > - /* add string to head */ > - if (cirbuf_add_buf_head(&cb, CIRBUF_STR_HEAD, sizeof(CIRBUF_STR_HEAD)) > - != (sizeof(CIRBUF_STR_HEAD))) { > - printf("Error: failed to add string to head!\n"); > - return -1; > - } > - /* delete string from tail */ > - if (cirbuf_del_buf_tail(&cb, sizeof(CIRBUF_STR_HEAD)) < 0) { > - printf("Error: failed to delete string from tail!\n"); > - return -1; > - } > - /* verify string was deleted */ > - if (cirbuf_del_tail_safe(&cb) == 0) { > - printf("Error: buffer should have been empty!\n"); > - return -1; > - } > - /* clear tmp buffer */ > - memset(tmp, 0, sizeof(tmp)); > - > - /* > - * reinitialize circular buffer > - */ > - memset(buf, 0, sizeof(buf)); > - if (cirbuf_init(&cb, buf, 0, sizeof(buf)) < 0) { > - printf("Error: failed to reinitialize circular buffer!\n"); > - return -1; > - } > - > - /* add string to tail */ > - if (cirbuf_add_buf_tail(&cb, CIRBUF_STR_TAIL, sizeof(CIRBUF_STR_TAIL)) > - != (sizeof(CIRBUF_STR_TAIL))) { > - printf("Error: failed to add string to tail!\n"); > - return -1; > - } > - /* delete string from head */ > - if (cirbuf_del_buf_head(&cb, sizeof(CIRBUF_STR_TAIL)) < 0) { > - printf("Error: failed to delete string from head!\n"); > - return -1; > - } > - /* verify string was deleted */ > - if (cirbuf_del_head_safe(&cb) == 0) { > - printf("Error: buffer should have been empty!\n"); > - return -1; > - } > - > - return 0; > -} > - > -/* try to write more than available */ > -static int > -test_cirbuf_string_add_boundaries(void) > -{ > - struct cirbuf cb; > - char buf[CMDLINE_TEST_BUFSIZE]; > - unsigned i; > - > - /* initialize buffers */ > - memset(buf, 0, sizeof(buf)); > - > - /* > - * initialize circular buffer > - */ > - if (cirbuf_init(&cb, buf, 0, sizeof(buf)) < 0) { > - printf("Error: failed to initialize circular buffer!\n"); > - return -1; > - } > - > - /* fill the buffer from tail */ > - for (i = 0; i < CMDLINE_TEST_BUFSIZE - sizeof(CIRBUF_STR_TAIL) + 1; i++) > - cirbuf_add_tail_safe(&cb, 't'); > - > - /* try adding a string to tail */ > - if (cirbuf_add_buf_tail(&cb, CIRBUF_STR_TAIL, sizeof(CIRBUF_STR_TAIL)) > - > 0) { > - printf("Error: buffer should have been full!\n"); > - return -1; > - } > - /* try adding a string to head */ > - if (cirbuf_add_buf_head(&cb, CIRBUF_STR_TAIL, sizeof(CIRBUF_STR_TAIL)) > - > 0) { > - printf("Error: buffer should have been full!\n"); > - return -1; > - } > - > - /* > - * reinitialize circular buffer > - */ > - memset(buf, 0, sizeof(buf)); > - if (cirbuf_init(&cb, buf, 0, sizeof(buf)) < 0) { > - printf("Error: failed to reinitialize circular buffer!\n"); > - return -1; > - } > - > - /* fill the buffer from head */ > - for (i = 0; i < CMDLINE_TEST_BUFSIZE - sizeof(CIRBUF_STR_HEAD) + 1; i++) > - cirbuf_add_head_safe(&cb, 'h'); > - > - /* try adding a string to head */ > - if (cirbuf_add_buf_head(&cb, CIRBUF_STR_HEAD, sizeof(CIRBUF_STR_HEAD)) > - > 0) { > - printf("Error: buffer should have been full!\n"); > - return -1; > - } > - /* try adding a string to tail */ > - if (cirbuf_add_buf_tail(&cb, CIRBUF_STR_HEAD, sizeof(CIRBUF_STR_HEAD)) > - > 0) { > - printf("Error: buffer should have been full!\n"); > - return -1; > - } > - > - return 0; > -} > - > -/* try to read/delete more than written */ > -static int > -test_cirbuf_string_get_del_boundaries(void) > -{ > - struct cirbuf cb; > - char buf[CMDLINE_TEST_BUFSIZE]; > - char tmp[CMDLINE_TEST_BUFSIZE]; > - > - /* initialize buffers */ > - memset(buf, 0, sizeof(buf)); > - memset(tmp, 0, sizeof(tmp)); > - > - /* > - * initialize circular buffer > - */ > - if (cirbuf_init(&cb, buf, 0, sizeof(buf)) < 0) { > - printf("Error: failed to initialize circular buffer!\n"); > - return -1; > - } > - > - > - /* add string to head */ > - if (cirbuf_add_buf_head(&cb, CIRBUF_STR_HEAD, sizeof(CIRBUF_STR_HEAD)) > - != (sizeof(CIRBUF_STR_HEAD))) { > - printf("Error: failed to add string to head!\n"); > - return -1; > - } > - /* read more than written (head) */ > - if (cirbuf_get_buf_head(&cb, tmp, sizeof(CIRBUF_STR_HEAD) + 1) > - != sizeof(CIRBUF_STR_HEAD)) { > - printf("Error: unexpected result when reading too much data!\n"); > - return -1; > - } > - /* read more than written (tail) */ > - if (cirbuf_get_buf_tail(&cb, tmp, sizeof(CIRBUF_STR_HEAD) + 1) > - != sizeof(CIRBUF_STR_HEAD)) { > - printf("Error: unexpected result when reading too much data!\n"); > - return -1; > - } > - /* delete more than written (head) */ > - if (cirbuf_del_buf_head(&cb, sizeof(CIRBUF_STR_HEAD) + 1) == 0) { > - printf("Error: unexpected result when deleting too much data!\n"); > - return -1; > - } > - /* delete more than written (tail) */ > - if (cirbuf_del_buf_tail(&cb, sizeof(CIRBUF_STR_HEAD) + 1) == 0) { > - printf("Error: unexpected result when deleting too much data!\n"); > - return -1; > - } > - > - /* > - * reinitialize circular buffer > - */ > - memset(buf, 0, sizeof(buf)); > - if (cirbuf_init(&cb, buf, 0, sizeof(buf)) < 0) { > - printf("Error: failed to reinitialize circular buffer!\n"); > - return -1; > - } > - > - /* add string to tail */ > - if (cirbuf_add_buf_tail(&cb, CIRBUF_STR_TAIL, sizeof(CIRBUF_STR_TAIL)) > - != (sizeof(CIRBUF_STR_TAIL))) { > - printf("Error: failed to add string to tail!\n"); > - return -1; > - } > - /* read more than written (tail) */ > - if (cirbuf_get_buf_tail(&cb, tmp, sizeof(CIRBUF_STR_TAIL) + 1) > - != sizeof(CIRBUF_STR_TAIL)) { > - printf("Error: unexpected result when reading too much data!\n"); > - return -1; > - } > - /* read more than written (head) */ > - if (cirbuf_get_buf_head(&cb, tmp, sizeof(CIRBUF_STR_TAIL) + 1) > - != sizeof(CIRBUF_STR_TAIL)) { > - printf("Error: unexpected result when reading too much data!\n"); > - return -1; > - } > - /* delete more than written (tail) */ > - if (cirbuf_del_buf_tail(&cb, sizeof(CIRBUF_STR_TAIL) + 1) == 0) { > - printf("Error: unexpected result when deleting too much data!\n"); > - return -1; > - } > - /* delete more than written (head) */ > - if (cirbuf_del_buf_tail(&cb, sizeof(CIRBUF_STR_TAIL) + 1) == 0) { > - printf("Error: unexpected result when deleting too much data!\n"); > - return -1; > - } > - > - return 0; > -} > - > -/* try to read/delete less than written */ > -static int > -test_cirbuf_string_get_del_partial(void) > -{ > - struct cirbuf cb; > - char buf[CMDLINE_TEST_BUFSIZE]; > - char tmp[CMDLINE_TEST_BUFSIZE]; > - char tmp2[CMDLINE_TEST_BUFSIZE]; > - > - /* initialize buffers */ > - memset(buf, 0, sizeof(buf)); > - memset(tmp, 0, sizeof(tmp)); > - memset(tmp2, 0, sizeof(tmp)); > - > - snprintf(tmp2, sizeof(tmp2), "%s", CIRBUF_STR_HEAD); > - > - /* > - * initialize circular buffer > - */ > - if (cirbuf_init(&cb, buf, 0, sizeof(buf)) < 0) { > - printf("Error: failed to initialize circular buffer!\n"); > - return -1; > - } > - > - /* add string to head */ > - if (cirbuf_add_buf_head(&cb, CIRBUF_STR_HEAD, sizeof(CIRBUF_STR_HEAD)) > - != (sizeof(CIRBUF_STR_HEAD))) { > - printf("Error: failed to add string to head!\n"); > - return -1; > - } > - /* read less than written (head) */ > - if (cirbuf_get_buf_head(&cb, tmp, sizeof(CIRBUF_STR_HEAD) - 1) > - != sizeof(CIRBUF_STR_HEAD) - 1) { > - printf("Error: unexpected result when reading from head!\n"); > - return -1; > - } > - /* verify string */ > - if (strncmp(tmp, tmp2, sizeof(CIRBUF_STR_HEAD) - 1) != 0) { > - printf("Error: strings mismatch!\n"); > - return -1; > - } > - memset(tmp, 0, sizeof(tmp)); > - /* read less than written (tail) */ > - if (cirbuf_get_buf_tail(&cb, tmp, sizeof(CIRBUF_STR_HEAD) - 1) > - != sizeof(CIRBUF_STR_HEAD) - 1) { > - printf("Error: unexpected result when reading from tail!\n"); > - return -1; > - } > - /* verify string */ > - if (strncmp(tmp, &tmp2[1], sizeof(CIRBUF_STR_HEAD) - 1) != 0) { > - printf("Error: strings mismatch!\n"); > - return -1; > - } > - > - /* > - * verify correct deletion > - */ > - > - /* clear buffer */ > - memset(tmp, 0, sizeof(tmp)); > - > - /* delete less than written (head) */ > - if (cirbuf_del_buf_head(&cb, 1) != 0) { > - printf("Error: delete from head failed!\n"); > - return -1; > - } > - /* read from head */ > - if (cirbuf_get_buf_head(&cb, tmp, sizeof(CIRBUF_STR_HEAD) - 1) > - != sizeof(CIRBUF_STR_HEAD) - 1) { > - printf("Error: unexpected result when reading from head!\n"); > - return -1; > - } > - /* since we deleted from head, first char should be deleted */ > - if (strncmp(tmp, &tmp2[1], sizeof(CIRBUF_STR_HEAD) - 1) != 0) { > - printf("Error: strings mismatch!\n"); > - return -1; > - } > - /* clear buffer */ > - memset(tmp, 0, sizeof(tmp)); > - > - /* delete less than written (tail) */ > - if (cirbuf_del_buf_tail(&cb, 1) != 0) { > - printf("Error: delete from tail failed!\n"); > - return -1; > - } > - /* read from tail */ > - if (cirbuf_get_buf_tail(&cb, tmp, sizeof(CIRBUF_STR_HEAD) - 2) > - != sizeof(CIRBUF_STR_HEAD) - 2) { > - printf("Error: unexpected result when reading from head!\n"); > - return -1; > - } > - /* since we deleted from tail, last char should be deleted */ > - if (strncmp(tmp, &tmp2[1], sizeof(CIRBUF_STR_HEAD) - 2) != 0) { > - printf("Error: strings mismatch!\n"); > - return -1; > - } > - > - return 0; > -} > - > -/* test cmdline_cirbuf char add/del functions */ > -static int > -test_cirbuf_char_add_del(void) > -{ > - struct cirbuf cb; > - char buf[CMDLINE_TEST_BUFSIZE]; > - char tmp[CMDLINE_TEST_BUFSIZE]; > - > - /* clear buffer */ > - memset(buf, 0, sizeof(buf)); > - memset(tmp, 0, sizeof(tmp)); > - > - /* > - * initialize circular buffer > - */ > - if (cirbuf_init(&cb, buf, 0, sizeof(buf)) < 0) { > - printf("Error: failed to initialize circular buffer!\n"); > - return -1; > - } > - > - /* > - * try to delete something from cirbuf. since it's empty, > - * these should fail. > - */ > - if (cirbuf_del_head_safe(&cb) == 0) { > - printf("Error: deleting from empty cirbuf head succeeded!\n"); > - return -1; > - } > - if (cirbuf_del_tail_safe(&cb) == 0) { > - printf("Error: deleting from empty cirbuf tail succeeded!\n"); > - return -1; > - } > - > - /* > - * add, verify and delete. these should pass. > - */ > - if (cirbuf_add_head_safe(&cb,'h') < 0) { > - printf("Error: adding to cirbuf head failed!\n"); > - return -1; > - } > - if (cirbuf_get_head(&cb) != 'h') { > - printf("Error: wrong head content!\n"); > - return -1; > - } > - if (cirbuf_del_head_safe(&cb) < 0) { > - printf("Error: deleting from cirbuf head failed!\n"); > - return -1; > - } > - if (cirbuf_add_tail_safe(&cb,'t') < 0) { > - printf("Error: adding to cirbuf tail failed!\n"); > - return -1; > - } > - if (cirbuf_get_tail(&cb) != 't') { > - printf("Error: wrong tail content!\n"); > - return -1; > - } > - if (cirbuf_del_tail_safe(&cb) < 0) { > - printf("Error: deleting from cirbuf tail failed!\n"); > - return -1; > - } > - /* do the same for unsafe versions. those are void. */ > - cirbuf_add_head(&cb,'h'); > - if (cirbuf_get_head(&cb) != 'h') { > - printf("Error: wrong head content!\n"); > - return -1; > - } > - cirbuf_del_head(&cb); > - > - /* test if char has been deleted. we can't call cirbuf_get_head > - * because it's unsafe, but we can call cirbuf_get_buf_head. > - */ > - if (cirbuf_get_buf_head(&cb, tmp, 1) > 0) { > - printf("Error: buffer should have been empty!\n"); > - return -1; > - } > - > - cirbuf_add_tail(&cb,'t'); > - if (cirbuf_get_tail(&cb) != 't') { > - printf("Error: wrong tail content!\n"); > - return -1; > - } > - cirbuf_del_tail(&cb); > - > - /* test if char has been deleted. we can't call cirbuf_get_tail > - * because it's unsafe, but we can call cirbuf_get_buf_tail. > - */ > - if (cirbuf_get_buf_tail(&cb, tmp, 1) > 0) { > - printf("Error: buffer should have been empty!\n"); > - return -1; > - } > - > - return 0; > -} > - > -/* test filling up buffer with chars */ > -static int > -test_cirbuf_char_fill(void) > -{ > - struct cirbuf cb; > - char buf[CMDLINE_TEST_BUFSIZE]; > - unsigned i; > - > - /* clear buffer */ > - memset(buf, 0, sizeof(buf)); > - > - /* > - * initialize circular buffer > - */ > - if (cirbuf_init(&cb, buf, 0, sizeof(buf)) < 0) { > - printf("Error: failed to initialize circular buffer!\n"); > - return -1; > - } > - > - /* > - * fill the buffer from head or tail, verify contents, test boundaries > - * and clear the buffer > - */ > - > - /* fill the buffer from tail */ > - for (i = 0; i < CMDLINE_TEST_BUFSIZE; i++) > - cirbuf_add_tail_safe(&cb, 't'); > - /* verify that contents of the buffer are what they are supposed to be */ > - for (i = 0; i < sizeof(buf); i++) { > - if (buf[i] != 't') { > - printf("Error: wrong content in buffer!\n"); > - return -1; > - } > - } > - /* try to add to a full buffer from tail */ > - if (cirbuf_add_tail_safe(&cb, 't') == 0) { > - printf("Error: buffer should have been full!\n"); > - return -1; > - } > - /* try to add to a full buffer from head */ > - if (cirbuf_add_head_safe(&cb, 'h') == 0) { > - printf("Error: buffer should have been full!\n"); > - return -1; > - } > - /* delete buffer from tail */ > - for(i = 0; i < CMDLINE_TEST_BUFSIZE; i++) > - cirbuf_del_tail_safe(&cb); > - /* try to delete from an empty buffer */ > - if (cirbuf_del_tail_safe(&cb) >= 0) { > - printf("Error: buffer should have been empty!\n"); > - return -1; > - } > - > - /* fill the buffer from head */ > - for (i = 0; i < CMDLINE_TEST_BUFSIZE; i++) > - cirbuf_add_head_safe(&cb, 'h'); > - /* verify that contents of the buffer are what they are supposed to be */ > - for (i = 0; i < sizeof(buf); i++) { > - if (buf[i] != 'h') { > - printf("Error: wrong content in buffer!\n"); > - return -1; > - } > - } > - /* try to add to a full buffer from head */ > - if (cirbuf_add_head_safe(&cb,'h') >= 0) { > - printf("Error: buffer should have been full!\n"); > - return -1; > - } > - /* try to add to a full buffer from tail */ > - if (cirbuf_add_tail_safe(&cb, 't') == 0) { > - printf("Error: buffer should have been full!\n"); > - return -1; > - } > - /* delete buffer from head */ > - for(i = 0; i < CMDLINE_TEST_BUFSIZE; i++) > - cirbuf_del_head_safe(&cb); > - /* try to delete from an empty buffer */ > - if (cirbuf_del_head_safe(&cb) >= 0) { > - printf("Error: buffer should have been empty!\n"); > - return -1; > - } > - > - /* > - * fill the buffer from both head and tail, with alternating characters, > - * verify contents and clear the buffer > - */ > - > - /* fill half of buffer from tail */ > - for (i = 0; i < CMDLINE_TEST_BUFSIZE / 2; i++) > - cirbuf_add_tail_safe(&cb, (char) (i % 2 ? 't' : 'T')); > - /* fill other half of the buffer from head */ > - for (i = 0; i < CMDLINE_TEST_BUFSIZE / 2; i++) > - cirbuf_add_head_safe(&cb, (char) (i % 2 ? 'H' : 'h')); /* added in reverse */ > - > - /* verify that contents of the buffer are what they are supposed to be */ > - for (i = 0; i < sizeof(buf) / 2; i++) { > - if (buf[i] != (char) (i % 2 ? 't' : 'T')) { > - printf("Error: wrong content in buffer at %u!\n", i); > - return -1; > - } > - } > - for (i = sizeof(buf) / 2; i < sizeof(buf); i++) { > - if (buf[i] != (char) (i % 2 ? 'h' : 'H')) { > - printf("Error: wrong content in buffer %u!\n", i); > - return -1; > - } > - } > - > - return 0; > -} > - > -/* test left alignment */ > -static int > -test_cirbuf_align_left(void) > -{ > -#define HALF_OFFSET CMDLINE_TEST_BUFSIZE / 2 > -#define SMALL_OFFSET HALF_OFFSET / 2 > -/* resulting buffer lengths for each of the test cases */ > -#define LEN1 HALF_OFFSET - SMALL_OFFSET - 1 > -#define LEN2 HALF_OFFSET + SMALL_OFFSET + 2 > -#define LEN3 HALF_OFFSET - SMALL_OFFSET > -#define LEN4 HALF_OFFSET + SMALL_OFFSET - 1 > - > - struct cirbuf cb; > - char buf[CMDLINE_TEST_BUFSIZE]; > - char tmp[CMDLINE_TEST_BUFSIZE]; > - unsigned i; > - > - /* > - * align left when start < end and start in left half > - */ > - > - /* > - * initialize circular buffer > - */ > - memset(buf, 0, sizeof(buf)); > - if (cirbuf_init(&cb, buf, 0, sizeof(buf)) < 0) { > - printf("Error: failed to initialize circular buffer!\n"); > - return -1; > - } > - > - /* push end into left half */ > - for (i = 0; i < HALF_OFFSET - 1; i++) > - cirbuf_add_tail_safe(&cb, 't'); > - > - /* push start into left half < end */ > - for (i = 0; i < SMALL_OFFSET; i++) > - cirbuf_del_head_safe(&cb); > - > - /* align */ > - if (cirbuf_align_left(&cb) < 0) { > - printf("Error: alignment failed!\n"); > - return -1; > - } > - > - /* verify result */ > - if (cb.start != 0 || cb.len != LEN1 || cb.end != cb.len - 1) { > - printf("Error: buffer alignment is wrong!\n"); > - return -1; > - } > - > - /* > - * align left when start > end and start in left half > - */ > - > - /* > - * reinitialize circular buffer > - */ > - memset(buf, 0, sizeof(buf)); > - if (cirbuf_init(&cb, buf, 0, sizeof(buf)) < 0) { > - printf("Error: failed to reinitialize circular buffer!\n"); > - return -1; > - } > - > - /* push start into left half */ > - for (i = 0; i < HALF_OFFSET + 2; i++) > - cirbuf_add_head_safe(&cb, 'h'); > - > - /* push end into left half > start */ > - for (i = 0; i < SMALL_OFFSET; i++) > - cirbuf_add_tail_safe(&cb, 't'); > - > - /* align */ > - if (cirbuf_align_left(&cb) < 0) { > - printf("Error: alignment failed!\n"); > - return -1; > - } > - > - /* verify result */ > - if (cb.start != 0 || cb.len != LEN2 || cb.end != cb.len - 1) { > - printf("Error: buffer alignment is wrong!"); > - return -1; > - } > - > - /* > - * align left when start < end and start in right half > - */ > - > - /* > - * reinitialize circular buffer > - */ > - memset(buf, 0, sizeof(buf)); > - if (cirbuf_init(&cb, buf, 0, sizeof(buf)) < 0) { > - printf("Error: failed to reinitialize circular buffer!\n"); > - return -1; > - } > - > - /* push start into the right half */ > - for (i = 0; i < HALF_OFFSET; i++) > - cirbuf_add_head_safe(&cb, 'h'); > - > - /* push end into left half > start */ > - for (i = 0; i < SMALL_OFFSET; i++) > - cirbuf_del_tail_safe(&cb); > - > - /* align */ > - if (cirbuf_align_left(&cb) < 0) { > - printf("Error: alignment failed!\n"); > - return -1; > - } > - > - /* verify result */ > - if (cb.start != 0 || cb.len != LEN3 || cb.end != cb.len - 1) { > - printf("Error: buffer alignment is wrong!"); > - return -1; > - } > - > - /* > - * align left when start > end and start in right half > - */ > - > - /* > - * reinitialize circular buffer > - */ > - memset(buf, 0, sizeof(buf)); > - if (cirbuf_init(&cb, buf, 0, sizeof(buf)) < 0) { > - printf("Error: failed to reinitialize circular buffer!\n"); > - return -1; > - } > - > - /* push start into the right half */ > - for (i = 0; i < HALF_OFFSET - 1; i++) > - cirbuf_add_head_safe(&cb, 'h'); > - > - /* push end into left half < start */ > - for (i = 0; i < SMALL_OFFSET; i++) > - cirbuf_add_tail_safe(&cb, 't'); > - > - /* align */ > - if (cirbuf_align_left(&cb) < 0) { > - printf("Error: alignment failed!\n"); > - return -1; > - } > - > - /* verify result */ > - if (cb.start != 0 || cb.len != LEN4 || > - cb.end != cb.len - 1) { > - printf("Error: buffer alignment is wrong!"); > - return -1; > - } > - > - /* > - * Verify that alignment doesn't corrupt data > - */ > - > - /* > - * reinitialize circular buffer > - */ > - memset(buf, 0, sizeof(buf)); > - if (cirbuf_init(&cb, buf, 0, sizeof(buf)) < 0) { > - printf("Error: failed to reinitialize circular buffer!\n"); > - return -1; > - } > - > - /* add string to tail and head */ > - if (cirbuf_add_buf_head(&cb, CIRBUF_STR_HEAD, > - sizeof(CIRBUF_STR_HEAD)) < 0 || cirbuf_add_buf_tail(&cb, > - CIRBUF_STR_TAIL, sizeof(CIRBUF_STR_TAIL)) < 0) { > - printf("Error: failed to add strings!\n"); > - return -1; > - } > - > - /* align */ > - if (cirbuf_align_left(&cb) < 0) { > - printf("Error: alignment failed!\n"); > - return -1; > - } > - > - /* get string from head */ > - if (cirbuf_get_buf_head(&cb, tmp, > - sizeof(CIRBUF_STR_HEAD) + sizeof(CIRBUF_STR_TAIL)) < 0) { > - printf("Error: failed to read string from head!\n"); > - return -1; > - } > - > - /* verify string */ > - if (strncmp(tmp, CIRBUF_STR_HEAD "\0" CIRBUF_STR_TAIL, > - sizeof(CIRBUF_STR_HEAD) + sizeof(CIRBUF_STR_TAIL)) != 0) { > - printf("Error: strings mismatch!\n"); > - return -1; > - } > - > - /* reset tmp buffer */ > - memset(tmp, 0, sizeof(tmp)); > - > - /* get string from tail */ > - if (cirbuf_get_buf_tail(&cb, tmp, > - sizeof(CIRBUF_STR_HEAD) + sizeof(CIRBUF_STR_TAIL)) < 0) { > - printf("Error: failed to read string from head!\n"); > - return -1; > - } > - > - /* verify string */ > - if (strncmp(tmp, CIRBUF_STR_HEAD "\0" CIRBUF_STR_TAIL, > - sizeof(CIRBUF_STR_HEAD) + sizeof(CIRBUF_STR_TAIL)) != 0) { > - printf("Error: strings mismatch!\n"); > - return -1; > - } > - > - return 0; > -} > - > -/* test right alignment */ > -static int > -test_cirbuf_align_right(void) > -{ > -#define END_OFFSET CMDLINE_TEST_BUFSIZE - 1 > - struct cirbuf cb; > - char buf[CMDLINE_TEST_BUFSIZE]; > - char tmp[CMDLINE_TEST_BUFSIZE]; > - unsigned i; > - > - > - /* > - * align right when start < end and start in left half > - */ > - > - /* > - * initialize circular buffer > - */ > - memset(buf, 0, sizeof(buf)); > - if (cirbuf_init(&cb, buf, 0, sizeof(buf)) < 0) { > - printf("Error: failed to initialize circular buffer!\n"); > - return -1; > - } > - > - /* push end into left half */ > - for (i = 0; i < HALF_OFFSET - 1; i++) > - cirbuf_add_tail_safe(&cb, 't'); > - > - /* push start into left half < end */ > - for (i = 0; i < SMALL_OFFSET; i++) > - cirbuf_del_head_safe(&cb); > - > - /* align */ > - cirbuf_align_right(&cb); > - > - /* verify result */ > - if (cb.start != END_OFFSET || cb.len != LEN1 || cb.end != cb.len - 2) { > - printf("Error: buffer alignment is wrong!\n"); > - return -1; > - } > - > - /* > - * align right when start > end and start in left half > - */ > - > - /* > - * reinitialize circular buffer > - */ > - memset(buf, 0, sizeof(buf)); > - if (cirbuf_init(&cb, buf, 0, sizeof(buf)) < 0) { > - printf("Error: failed to reinitialize circular buffer!\n"); > - return -1; > - } > - > - /* push start into left half */ > - for (i = 0; i < HALF_OFFSET + 2; i++) > - cirbuf_add_head_safe(&cb, 'h'); > - > - /* push end into left half > start */ > - for (i = 0; i < SMALL_OFFSET; i++) > - cirbuf_add_tail_safe(&cb, 't'); > - > - /* align */ > - cirbuf_align_right(&cb); > - > - /* verify result */ > - if (cb.start != END_OFFSET || cb.len != LEN2 || cb.end != cb.len - 2) { > - printf("Error: buffer alignment is wrong!"); > - return -1; > - } > - > - /* > - * align right when start < end and start in right half > - */ > - > - /* > - * reinitialize circular buffer > - */ > - memset(buf, 0, sizeof(buf)); > - if (cirbuf_init(&cb, buf, 0, sizeof(buf)) < 0) { > - printf("Error: failed to reinitialize circular buffer!\n"); > - return -1; > - } > - > - /* push start into the right half */ > - for (i = 0; i < HALF_OFFSET; i++) > - cirbuf_add_head_safe(&cb, 'h'); > - > - /* push end into left half > start */ > - for (i = 0; i < SMALL_OFFSET; i++) > - cirbuf_del_tail_safe(&cb); > - > - /* align */ > - cirbuf_align_right(&cb); > - > - /* verify result */ > - if (cb.end != END_OFFSET || cb.len != LEN3 || cb.start != cb.end - cb.len + 1) { > - printf("Error: buffer alignment is wrong!"); > - return -1; > - } > - > - /* > - * align right when start > end and start in right half > - */ > - > - /* > - * reinitialize circular buffer > - */ > - memset(buf, 0, sizeof(buf)); > - if (cirbuf_init(&cb, buf, 0, sizeof(buf)) < 0) { > - printf("Error: failed to reinitialize circular buffer!\n"); > - return -1; > - } > - > - /* push start into the right half */ > - for (i = 0; i < HALF_OFFSET - 1; i++) > - cirbuf_add_head_safe(&cb, 'h'); > - > - /* push end into left half < start */ > - for (i = 0; i < SMALL_OFFSET; i++) > - cirbuf_add_tail_safe(&cb, 't'); > - > - /* align */ > - cirbuf_align_right(&cb); > - > - /* verify result */ > - if (cb.end != END_OFFSET || cb.len != LEN4 || cb.start != cb.end - cb.len + 1) { > - printf("Error: buffer alignment is wrong!"); > - return -1; > - } > - > - /* > - * Verify that alignment doesn't corrupt data > - */ > - > - /* > - * reinitialize circular buffer > - */ > - memset(buf, 0, sizeof(buf)); > - if (cirbuf_init(&cb, buf, 0, sizeof(buf)) < 0) { > - printf("Error: failed to reinitialize circular buffer!\n"); > - return -1; > - } > - > - /* add string to tail and head */ > - if (cirbuf_add_buf_tail(&cb, CIRBUF_STR_TAIL, > - sizeof(CIRBUF_STR_TAIL)) < 0 || cirbuf_add_buf_head(&cb, > - CIRBUF_STR_HEAD, sizeof(CIRBUF_STR_HEAD)) < 0) { > - printf("Error: failed to add strings!\n"); > - return -1; > - } > - > - /* align */ > - if (cirbuf_align_right(&cb) < 0) { > - printf("Error: alignment failed!\n"); > - return -1; > - } > - > - /* get string from head */ > - if (cirbuf_get_buf_head(&cb, tmp, > - sizeof(CIRBUF_STR_HEAD) + sizeof(CIRBUF_STR_TAIL)) < 0) { > - printf("Error: failed to read string from head!\n"); > - return -1; > - } > - > - /* verify string */ > - if (strncmp(tmp, CIRBUF_STR_HEAD "\0" CIRBUF_STR_TAIL, > - sizeof(CIRBUF_STR_HEAD) + sizeof(CIRBUF_STR_TAIL)) != 0) { > - printf("Error: strings mismatch!\n"); > - return -1; > - } > - > - /* reset tmp buffer */ > - memset(tmp, 0, sizeof(tmp)); > - > - /* get string from tail */ > - if (cirbuf_get_buf_tail(&cb, tmp, > - sizeof(CIRBUF_STR_HEAD) + sizeof(CIRBUF_STR_TAIL)) < 0) { > - printf("Error: failed to read string from head!\n"); > - return -1; > - } > - /* verify string */ > - if (strncmp(tmp, CIRBUF_STR_HEAD "\0" CIRBUF_STR_TAIL, > - sizeof(CIRBUF_STR_HEAD) + sizeof(CIRBUF_STR_TAIL)) != 0) { > - printf("Error: strings mismatch!\n"); > - return -1; > - } > - > - return 0; > -} > - > -/* call functions with invalid parameters */ > -int > -test_cirbuf_invalid_param(void) > -{ > - struct cirbuf cb; > - char buf[CMDLINE_TEST_BUFSIZE]; > - > - /* null cirbuf */ > - if (cirbuf_init(0, buf, 0, sizeof(buf)) == 0) > - return -1; > - /* null buffer */ > - if (cirbuf_init(&cb, 0, 0, sizeof(buf)) == 0) > - return -1; > - /* null cirbuf */ > - if (cirbuf_add_head_safe(0, 'h') == 0) > - return -1; > - if (cirbuf_add_tail_safe(0, 't') == 0) > - return -1; > - if (cirbuf_del_head_safe(0) == 0) > - return -1; > - if (cirbuf_del_tail_safe(0) == 0) > - return -1; > - /* null buffer */ > - if (cirbuf_add_buf_head(&cb, 0, 0) == 0) > - return -1; > - if (cirbuf_add_buf_tail(&cb, 0, 0) == 0) > - return -1; > - /* null cirbuf */ > - if (cirbuf_add_buf_head(0, buf, 0) == 0) > - return -1; > - if (cirbuf_add_buf_tail(0, buf, 0) == 0) > - return -1; > - /* null size */ > - if (cirbuf_add_buf_head(&cb, buf, 0) == 0) > - return -1; > - if (cirbuf_add_buf_tail(&cb, buf, 0) == 0) > - return -1; > - /* null cirbuf */ > - if (cirbuf_del_buf_head(0, 0) == 0) > - return -1; > - if (cirbuf_del_buf_tail(0, 0) == 0) > - return -1; > - /* null size */ > - if (cirbuf_del_buf_head(&cb, 0) == 0) > - return -1; > - if (cirbuf_del_buf_tail(&cb, 0) == 0) > - return -1; > - /* null cirbuf */ > - if (cirbuf_get_buf_head(0, 0, 0) == 0) > - return -1; > - if (cirbuf_get_buf_tail(0, 0, 0) == 0) > - return -1; > - /* null buffer */ > - if (cirbuf_get_buf_head(&cb, 0, 0) == 0) > - return -1; > - if (cirbuf_get_buf_tail(&cb, 0, 0) == 0) > - return -1; > - /* null size, this is valid but should return 0 */ > - if (cirbuf_get_buf_head(&cb, buf, 0) != 0) > - return -1; > - if (cirbuf_get_buf_tail(&cb, buf, 0) != 0) > - return -1; > - /* null cirbuf */ > - if (cirbuf_align_left(0) == 0) > - return -1; > - if (cirbuf_align_right(0) == 0) > - return -1; > - > - return 0; > -} > - > -/* test cmdline_cirbuf char functions */ > -int > -test_cirbuf_char(void) > -{ > - int ret; > - > - ret = test_cirbuf_char_add_del(); > - if (ret < 0) > - return -1; > - > - ret = test_cirbuf_char_fill(); > - if (ret < 0) > - return -1; > - > - return 0; > -} > - > -/* test cmdline_cirbuf string functions */ > -int > -test_cirbuf_string(void) > -{ > - if (test_cirbuf_string_add_del() < 0) > - return -1; > - > - if (test_cirbuf_string_add_del_reverse() < 0) > - return -1; > - > - if (test_cirbuf_string_add_boundaries() < 0) > - return -1; > - > - if (test_cirbuf_string_get_del_boundaries() < 0) > - return -1; > - > - if (test_cirbuf_string_get_del_partial() < 0) > - return -1; > - > - if (test_cirbuf_string_misc() < 0) > - return -1; > - > - return 0; > -} > - > -/* test cmdline_cirbuf align functions */ > -int > -test_cirbuf_align(void) > -{ > - if (test_cirbuf_align_left() < 0) > - return -1; > - if (test_cirbuf_align_right() < 0) > - return -1; > - return 0; > -} > diff --git a/test/test/test_cmdline_lib.c b/test/test/test_cmdline_lib.c > index 65b823a..93a80d0 100644 > --- a/test/test/test_cmdline_lib.c > +++ b/test/test/test_cmdline_lib.c > @@ -41,8 +41,6 @@ > #include <ctype.h> > #include <sys/queue.h> > > -#include <cmdline_vt100.h> > -#include <cmdline_rdline.h> > #include <cmdline_parse.h> > #include <cmdline_socket.h> > #include <cmdline.h> > @@ -50,113 +48,41 @@ > #include "test_cmdline.h" > > /****************************************************************/ > -/* static functions required for some tests */ > -static void > -valid_buffer(__attribute__((unused))struct rdline *rdl, > - __attribute__((unused))const char *buf, > - __attribute__((unused)) unsigned int size) > -{ > -} > - > -static int > -complete_buffer(__attribute__((unused)) struct rdline *rdl, > - __attribute__((unused)) const char *buf, > - __attribute__((unused)) char *dstbuf, > - __attribute__((unused)) unsigned int dstsize, > - __attribute__((unused)) int *state) > -{ > - return 0; > -} > - > -/****************************************************************/ > > static int > test_cmdline_parse_fns(void) > { > - struct cmdline cl; > + struct cmdline *cl; > int i = 0; > char dst[CMDLINE_TEST_BUFSIZE]; > > + cl = cmdline_new(NULL, "prompt", 0, 1); > + if (!cl) > + goto error; > if (cmdline_parse(NULL, "buffer") >= 0) > goto error; > - if (cmdline_parse(&cl, NULL) >= 0) > + if (cmdline_parse(cl, NULL) >= 0) > goto error; > > if (cmdline_complete(NULL, "buffer", &i, dst, sizeof(dst)) >= 0) > goto error; > - if (cmdline_complete(&cl, NULL, &i, dst, sizeof(dst)) >= 0) > + if (cmdline_complete(cl, NULL, &i, dst, sizeof(dst)) >= 0) > goto error; > - if (cmdline_complete(&cl, "buffer", NULL, dst, sizeof(dst)) >= 0) > + if (cmdline_complete(cl, "buffer", NULL, dst, sizeof(dst)) >= 0) > goto error; > - if (cmdline_complete(&cl, "buffer", &i, NULL, sizeof(dst)) >= 0) > + if (cmdline_complete(cl, "buffer", &i, NULL, sizeof(dst)) >= 0) > goto error; > > return 0; > > error: > + if (cl) > + cmdline_free(cl); > printf("Error: function accepted null parameter!\n"); > return -1; > } > > static int > -test_cmdline_rdline_fns(void) > -{ > - struct rdline rdl; > - rdline_write_char_t *wc = &cmdline_write_char; > - rdline_validate_t *v = &valid_buffer; > - rdline_complete_t *c = &complete_buffer; > - > - if (rdline_init(NULL, wc, v, c) >= 0) > - goto error; > - if (rdline_init(&rdl, NULL, v, c) >= 0) > - goto error; > - if (rdline_init(&rdl, wc, NULL, c) >= 0) > - goto error; > - if (rdline_init(&rdl, wc, v, NULL) >= 0) > - goto error; > - if (rdline_char_in(NULL, 0) >= 0) > - goto error; > - if (rdline_get_buffer(NULL) != NULL) > - goto error; > - if (rdline_add_history(NULL, "history") >= 0) > - goto error; > - if (rdline_add_history(&rdl, NULL) >= 0) > - goto error; > - if (rdline_get_history_item(NULL, 0) != NULL) > - goto error; > - > - /* void functions */ > - rdline_newline(NULL, "prompt"); > - rdline_newline(&rdl, NULL); > - rdline_stop(NULL); > - rdline_quit(NULL); > - rdline_restart(NULL); > - rdline_redisplay(NULL); > - rdline_reset(NULL); > - rdline_clear_history(NULL); > - > - return 0; > - > -error: > - printf("Error: function accepted null parameter!\n"); > - return -1; > -} > - > -static int > -test_cmdline_vt100_fns(void) > -{ > - if (vt100_parser(NULL, 0) >= 0) { > - printf("Error: function accepted null parameter!\n"); > - return -1; > - } > - > - /* void functions */ > - vt100_init(NULL); > - > - return 0; > -} > - > -static int > test_cmdline_socket_fns(void) > { > cmdline_parse_ctx_t ctx; > @@ -193,7 +119,7 @@ static int > test_cmdline_fns(void) > { > cmdline_parse_ctx_t ctx; > - struct cmdline cl, *tmp; > + struct cmdline *tmp; > > memset(&ctx, 0, sizeof(ctx)); > tmp = cmdline_new(&ctx, "test", -1, -1); > @@ -206,10 +132,6 @@ test_cmdline_fns(void) > goto error; > if (cmdline_in(NULL, "buffer", CMDLINE_TEST_BUFSIZE) >= 0) > goto error; > - if (cmdline_in(&cl, NULL, CMDLINE_TEST_BUFSIZE) >= 0) > - goto error; > - if (cmdline_write_char(NULL, 0) >= 0) > - goto error; > > /* void functions */ > cmdline_set_prompt(NULL, "prompt"); > @@ -220,16 +142,6 @@ test_cmdline_fns(void) > cmdline_interact(NULL); > cmdline_quit(NULL); > > - /* check if void calls change anything when they should fail */ > - cl = *tmp; > - > - cmdline_printf(&cl, NULL); > - if (memcmp(&cl, tmp, sizeof(cl))) goto mismatch; > - cmdline_set_prompt(&cl, NULL); > - if (memcmp(&cl, tmp, sizeof(cl))) goto mismatch; > - cmdline_in(&cl, NULL, CMDLINE_TEST_BUFSIZE); > - if (memcmp(&cl, tmp, sizeof(cl))) goto mismatch; > - > cmdline_free(tmp); > > return 0; > @@ -237,9 +149,6 @@ test_cmdline_fns(void) > error: > printf("Error: function accepted null parameter!\n"); > return -1; > -mismatch: > - printf("Error: data changed!\n"); > - return -1; > } > > /* test library functions. the point of these tests is not so much to test > @@ -251,10 +160,6 @@ test_cmdline_lib(void) > { > if (test_cmdline_parse_fns() < 0) > return -1; > - if (test_cmdline_rdline_fns() < 0) > - return -1; > - if (test_cmdline_vt100_fns() < 0) > - return -1; > if (test_cmdline_socket_fns() < 0) > return -1; > if (test_cmdline_fns() < 0) > -- > 2.1.4 ^ permalink raw reply [flat|nested] 18+ messages in thread
* [dpdk-dev] [PATCH v1] cmdline: rework as a wrapper to libedit 2017-11-09 13:43 [dpdk-dev] [RFC] cmdline: rework as a wrapper to libedit Adrien Mazarguil 2017-11-15 4:12 ` Wiles, Keith 2017-11-16 16:53 ` Jim Thompson @ 2018-04-17 15:21 ` Adrien Mazarguil 2018-04-17 15:59 ` Burakov, Anatoly 2018-04-19 15:13 ` [dpdk-dev] [PATCH v2] " Adrien Mazarguil 2 siblings, 2 replies; 18+ messages in thread From: Adrien Mazarguil @ 2018-04-17 15:21 UTC (permalink / raw) To: Olivier Matz Cc: dev, Keith Wiles, Jingjing Wu, Thomas Monjalon, Ferruh Yigit, Jim Thompson Disclaimer: this patch must not be confused with the CLI library [1] (work in progress) that will eventually supersede librte_cmdline itself with a different API. Rather, it modifies librte_cmdline to delegate all the heavy lifting (terminal and history handling), strips unused features and re-implements what remains of its public API as a wrapper to the editline library (also known as libedit) [2], a well-known, BSD-licensed and widely available library used by many projects which does everything needed and more [3]. This approach was chosen because converting librte_cmdline as a wrapper to a more capable library was easier and faster than addressing its shortcomings and results in much less code to maintain in DPDK. It also provides a drop-in solution for applications that rely on librte_cmdline. They benefit from greatly improved command line handling without a meaningful impact on their code base. The main motivation behind this patch is testpmd's flow (rte_flow) command, which requires support for dynamic tokens and very long lines that must be broken down when displayed. This is not supported by librte_cmdline's limited terminal handling capabilities, resulting in a rather frustrating user experience. It had to be addressed given the importance of testpmd as one of the primary tool used by PMD developers. This rework results in the following changes: - Removed circular buffer management interface for command history (cmdline_cirbuf.c), command history being handled by libedit. - Removed raw command-line interpreter (cmdline_rdline.c). - Removed raw terminal handler (cmdline_vt100.c). - Removed all test/example code for the above. - Re-implemented high level interactive and non-interactive command-line handlers (cmdline.c and cmdline_socket.c) on top of libedit using its native interface, not its readline compatibility layer. - Made struct cmdline opaque so that applications relying on librte_cmdline do not need to include any libedit headers. - Applications do not need to include cmdline_rdline.h anymore. - Terminal resizing is now automatically handled. - New external dependency for applications relying on librte_cmdline. - Major version bump due to the ABI impact of these changes. [1] http://dpdk.org/browse/draft/dpdk-draft-cli/ [2] http://thrysoee.dk/editline/ [3] http://netbsd.gw.com/cgi-bin/man-cgi?editline++NetBSD-current Signed-off-by: Adrien Mazarguil <adrien.mazarguil@6wind.com> Cc: Olivier Matz <olivier.matz@6wind.com> Cc: Keith Wiles <keith.wiles@intel.com> Cc: Jingjing Wu <jingjing.wu@intel.com> Cc: Thomas Monjalon <thomas@monjalon.net> Cc: Ferruh Yigit <ferruh.yigit@intel.com> Cc: Jim Thompson <jim@netgate.com> -- No fundamental change since the original RFC [4], except it's been rebased several times and Meson build support was added in the meantime. Commit log was also shortened a bit. I'm re-sending this because I think it's useful, at least to me (duh). As the maintainer of rte_flow, I spend most of my time typing flow commands in testpmd and libedit makes that a pleasant experience. Try it out! And don't hesitate to send your acked-by line to get this in time for 18.05 :) [4] http://dpdk.org/ml/archives/dev/2017-November/081605.html --- app/test-pmd/cmdline.c | 1 - examples/bond/main.c | 1 - examples/cmdline/commands.c | 1 - examples/cmdline/main.c | 1 - examples/multi_process/simple_mp/main.c | 1 - examples/multi_process/simple_mp/mp_commands.c | 1 - examples/qos_sched/cmdline.c | 1 - examples/quota_watermark/qwctl/commands.c | 1 - examples/quota_watermark/qwctl/qwctl.c | 1 - .../guest_cli/vm_power_cli_guest.c | 1 - examples/vm_power_manager/vm_power_cli.c | 1 - lib/librte_cmdline/Makefile | 10 +- lib/librte_cmdline/cmdline.c | 385 ++++-- lib/librte_cmdline/cmdline.h | 22 +- lib/librte_cmdline/cmdline_cirbuf.c | 412 ------ lib/librte_cmdline/cmdline_cirbuf.h | 193 --- lib/librte_cmdline/cmdline_parse.c | 7 +- lib/librte_cmdline/cmdline_rdline.c | 644 --------- lib/librte_cmdline/cmdline_rdline.h | 201 --- lib/librte_cmdline/cmdline_socket.c | 36 +- lib/librte_cmdline/cmdline_vt100.c | 132 -- lib/librte_cmdline/cmdline_vt100.h | 100 -- lib/librte_cmdline/meson.build | 18 +- lib/librte_cmdline/rte_cmdline_version.map | 41 +- mk/rte.app.mk | 2 + test/cmdline_test/cmdline_test.c | 1 - test/cmdline_test/commands.c | 69 - test/test/Makefile | 1 - test/test/commands.c | 1 - test/test/meson.build | 1 - test/test/test.c | 1 - test/test/test_cmdline.c | 9 - test/test/test_cmdline.h | 6 - test/test/test_cmdline_cirbuf.c | 1301 ------------------ test/test/test_cmdline_lib.c | 117 +- 35 files changed, 303 insertions(+), 3418 deletions(-) diff --git a/app/test-pmd/cmdline.c b/app/test-pmd/cmdline.c index 512e3b55e..140e6480c 100644 --- a/app/test-pmd/cmdline.c +++ b/app/test-pmd/cmdline.c @@ -48,7 +48,6 @@ #include <rte_flow.h> #include <rte_gro.h> -#include <cmdline_rdline.h> #include <cmdline_parse.h> #include <cmdline_parse_num.h> #include <cmdline_parse_string.h> diff --git a/examples/bond/main.c b/examples/bond/main.c index 455f108ee..3a832079e 100644 --- a/examples/bond/main.c +++ b/examples/bond/main.c @@ -42,7 +42,6 @@ #include <rte_arp.h> #include <rte_spinlock.h> -#include <cmdline_rdline.h> #include <cmdline_parse.h> #include <cmdline_parse_num.h> #include <cmdline_parse_string.h> diff --git a/examples/cmdline/commands.c b/examples/cmdline/commands.c index 06916d783..3e9d84d46 100644 --- a/examples/cmdline/commands.c +++ b/examples/cmdline/commands.c @@ -20,7 +20,6 @@ #endif #endif -#include <cmdline_rdline.h> #include <cmdline_parse.h> #include <cmdline_parse_ipaddr.h> #include <cmdline_parse_num.h> diff --git a/examples/cmdline/main.c b/examples/cmdline/main.c index f2f2e5a2f..9fe0fdef7 100644 --- a/examples/cmdline/main.c +++ b/examples/cmdline/main.c @@ -11,7 +11,6 @@ #include <termios.h> #include <sys/queue.h> -#include <cmdline_rdline.h> #include <cmdline_parse.h> #include <cmdline_socket.h> #include <cmdline.h> diff --git a/examples/multi_process/simple_mp/main.c b/examples/multi_process/simple_mp/main.c index e6c69d6a3..49d6ed169 100644 --- a/examples/multi_process/simple_mp/main.c +++ b/examples/multi_process/simple_mp/main.c @@ -35,7 +35,6 @@ #include <rte_ring.h> #include <rte_log.h> #include <rte_mempool.h> -#include <cmdline_rdline.h> #include <cmdline_parse.h> #include <cmdline_parse_string.h> #include <cmdline_socket.h> diff --git a/examples/multi_process/simple_mp/mp_commands.c b/examples/multi_process/simple_mp/mp_commands.c index e4df6ff01..a9eb8bb44 100644 --- a/examples/multi_process/simple_mp/mp_commands.c +++ b/examples/multi_process/simple_mp/mp_commands.c @@ -25,7 +25,6 @@ #include <rte_mempool.h> #include <rte_string_fns.h> -#include <cmdline_rdline.h> #include <cmdline_parse.h> #include <cmdline_parse_string.h> #include <cmdline_socket.h> diff --git a/examples/qos_sched/cmdline.c b/examples/qos_sched/cmdline.c index 15f51830c..679819a25 100644 --- a/examples/qos_sched/cmdline.c +++ b/examples/qos_sched/cmdline.c @@ -7,7 +7,6 @@ #include <inttypes.h> #include <string.h> -#include <cmdline_rdline.h> #include <cmdline_parse.h> #include <cmdline_parse_num.h> #include <cmdline_parse_string.h> diff --git a/examples/quota_watermark/qwctl/commands.c b/examples/quota_watermark/qwctl/commands.c index a1c646b9f..33fce2063 100644 --- a/examples/quota_watermark/qwctl/commands.c +++ b/examples/quota_watermark/qwctl/commands.c @@ -7,7 +7,6 @@ #include <string.h> #include <termios.h> -#include <cmdline_rdline.h> #include <cmdline_parse.h> #include <cmdline_parse_num.h> #include <cmdline_parse_string.h> diff --git a/examples/quota_watermark/qwctl/qwctl.c b/examples/quota_watermark/qwctl/qwctl.c index 2f7914c80..9f41a684a 100644 --- a/examples/quota_watermark/qwctl/qwctl.c +++ b/examples/quota_watermark/qwctl/qwctl.c @@ -13,7 +13,6 @@ #include <rte_log.h> #include <rte_memzone.h> -#include <cmdline_rdline.h> #include <cmdline_parse.h> #include <cmdline_socket.h> #include <cmdline.h> diff --git a/examples/vm_power_manager/guest_cli/vm_power_cli_guest.c b/examples/vm_power_manager/guest_cli/vm_power_cli_guest.c index 43bdeacef..218ed192e 100644 --- a/examples/vm_power_manager/guest_cli/vm_power_cli_guest.c +++ b/examples/vm_power_manager/guest_cli/vm_power_cli_guest.c @@ -8,7 +8,6 @@ #include <stdio.h> #include <termios.h> -#include <cmdline_rdline.h> #include <cmdline_parse.h> #include <cmdline_parse_string.h> #include <cmdline_parse_num.h> diff --git a/examples/vm_power_manager/vm_power_cli.c b/examples/vm_power_manager/vm_power_cli.c index d588d38aa..99757420a 100644 --- a/examples/vm_power_manager/vm_power_cli.c +++ b/examples/vm_power_manager/vm_power_cli.c @@ -10,7 +10,6 @@ #include <termios.h> #include <errno.h> -#include <cmdline_rdline.h> #include <cmdline_parse.h> #include <cmdline_parse_string.h> #include <cmdline_parse_num.h> diff --git a/lib/librte_cmdline/Makefile b/lib/librte_cmdline/Makefile index ddae1cfde..feb1f1bca 100644 --- a/lib/librte_cmdline/Makefile +++ b/lib/librte_cmdline/Makefile @@ -10,28 +10,24 @@ CFLAGS += $(WERROR_FLAGS) -I$(SRCDIR) -O3 EXPORT_MAP := rte_cmdline_version.map -LIBABIVER := 2 +LIBABIVER := 3 # all source are stored in SRCS-y SRCS-$(CONFIG_RTE_LIBRTE_CMDLINE) := cmdline.c -SRCS-$(CONFIG_RTE_LIBRTE_CMDLINE) += cmdline_cirbuf.c SRCS-$(CONFIG_RTE_LIBRTE_CMDLINE) += cmdline_parse.c SRCS-$(CONFIG_RTE_LIBRTE_CMDLINE) += cmdline_parse_etheraddr.c SRCS-$(CONFIG_RTE_LIBRTE_CMDLINE) += cmdline_parse_ipaddr.c SRCS-$(CONFIG_RTE_LIBRTE_CMDLINE) += cmdline_parse_num.c SRCS-$(CONFIG_RTE_LIBRTE_CMDLINE) += cmdline_parse_string.c -SRCS-$(CONFIG_RTE_LIBRTE_CMDLINE) += cmdline_rdline.c -SRCS-$(CONFIG_RTE_LIBRTE_CMDLINE) += cmdline_vt100.c SRCS-$(CONFIG_RTE_LIBRTE_CMDLINE) += cmdline_socket.c SRCS-$(CONFIG_RTE_LIBRTE_CMDLINE) += cmdline_parse_portlist.c -CFLAGS += -D_GNU_SOURCE LDLIBS += -lrte_eal # install includes INCS := cmdline.h cmdline_parse.h cmdline_parse_num.h cmdline_parse_ipaddr.h -INCS += cmdline_parse_etheraddr.h cmdline_parse_string.h cmdline_rdline.h -INCS += cmdline_vt100.h cmdline_socket.h cmdline_cirbuf.h cmdline_parse_portlist.h +INCS += cmdline_parse_etheraddr.h cmdline_parse_string.h +INCS += cmdline_socket.h cmdline_parse_portlist.h SYMLINK-$(CONFIG_RTE_LIBRTE_CMDLINE)-include := $(INCS) include $(RTE_SDK)/mk/rte.lib.mk diff --git a/lib/librte_cmdline/cmdline.c b/lib/librte_cmdline/cmdline.c index 591b78b0f..d160854e6 100644 --- a/lib/librte_cmdline/cmdline.c +++ b/lib/librte_cmdline/cmdline.c @@ -4,79 +4,181 @@ * All rights reserved. */ +#include <ctype.h> +#include <histedit.h> +#include <stdint.h> #include <stdio.h> #include <string.h> #include <unistd.h> #include <stdlib.h> #include <stdarg.h> -#include <inttypes.h> #include <fcntl.h> #include <poll.h> #include <errno.h> -#include <termios.h> -#include <netinet/in.h> - -#include <rte_string_fns.h> #include "cmdline_parse.h" -#include "cmdline_rdline.h" #include "cmdline.h" -static void -cmdline_valid_buffer(struct rdline *rdl, const char *buf, - __attribute__((unused)) unsigned int size) +struct cmdline { + char *line; + FILE *f_in; + FILE *f_out; + cmdline_parse_ctx_t *ctx; + EditLine *el; + History *hist; + HistEvent histev; + uint32_t eof:1; + uint32_t error:1; + char prompt[RDLINE_PROMPT_SIZE]; +}; + +void +cmdline_set_prompt(struct cmdline *cl, const char *prompt) { - struct cmdline *cl = rdl->opaque; - int ret; - ret = cmdline_parse(cl, buf); - if (ret == CMDLINE_PARSE_AMBIGUOUS) - cmdline_printf(cl, "Ambiguous command\n"); - else if (ret == CMDLINE_PARSE_NOMATCH) - cmdline_printf(cl, "Command not found\n"); - else if (ret == CMDLINE_PARSE_BAD_ARGS) - cmdline_printf(cl, "Bad arguments\n"); + if (!cl || !prompt) + return; + snprintf(cl->prompt, sizeof(cl->prompt), "%s", prompt); } -static int -cmdline_complete_buffer(struct rdline *rdl, const char *buf, - char *dstbuf, unsigned int dstsize, - int *state) +void * +cmdline_ctx_get(struct cmdline *cl) { - struct cmdline *cl = rdl->opaque; - return cmdline_complete(cl, buf, state, dstbuf, dstsize); + if (!cl) + return NULL; + return cl->ctx; } -int -cmdline_write_char(struct rdline *rdl, char c) +static char * +cmdline_el_prompt(EditLine *el) { - int ret = -1; struct cmdline *cl; - if (!rdl) - return -1; - - cl = rdl->opaque; + if (el_get(el, EL_CLIENTDATA, &cl)) + return NULL; + return cl->prompt; +} - if (cl->s_out >= 0) - ret = write(cl->s_out, &c, 1); +static unsigned char +cmdline_el_execute(EditLine *el, int c) +{ + const LineInfo *li = el_line(el); + size_t len = li->lastchar - li->buffer; + char *line; + struct cmdline *cl; + int ret; - return ret; + (void)c; + if (el_get(el, EL_CLIENTDATA, &cl)) + return CC_FATAL; + line = realloc(cl->line, len + 2); + if (!line) { + cl->error = 1; + return CC_FATAL; + } + cl->line = line; + memcpy(line, li->buffer, len); + line[len] = '\n'; + line[len + 1] = '\0'; + fputs("\r\n", cl->f_out); + ret = cmdline_parse(cl, line); + if (ret == CMDLINE_PARSE_AMBIGUOUS) + fprintf(cl->f_out, "Ambiguous command\r\n"); + else if (ret == CMDLINE_PARSE_NOMATCH) + fprintf(cl->f_out, "Command not found\r\n"); + else if (ret == CMDLINE_PARSE_BAD_ARGS) + fprintf(cl->f_out, "Bad arguments\r\n"); + if (cl->error) + return CC_FATAL; + if (cl->eof) + return CC_EOF; + if (len) { + line[len] = '\0'; + history(cl->hist, &cl->histev, H_ENTER, line); + } + return CC_NEWLINE; } +static unsigned char +cmdline_el_complete(EditLine *el, int c) +{ + const LineInfo *li = el_line(el); + size_t pos = li->cursor - li->buffer; + char *line; + struct cmdline *cl; + char complete_buf[RDLINE_COMPLETE_SIZE]; + int complete_state; + int ret; -void -cmdline_set_prompt(struct cmdline *cl, const char *prompt) + if (el_get(el, EL_CLIENTDATA, &cl)) + return CC_FATAL; + line = realloc(cl->line, pos + 1); + if (!line) { + cl->error = 1; + return CC_FATAL; + } + cl->line = line; + memcpy(line, li->buffer, pos); + line[pos] = '\0'; + if (c == '\t') + complete_state = 0; + else + complete_state = -1; + /* see in parse.h for help on complete() */ + ret = cmdline_complete(cl, line, &complete_state, + complete_buf, sizeof(complete_buf)); + /* no completion or error */ + if (ret <= 0) + return CC_ARGHACK; + /* string must be NUL-terminated */ + if (strnlen(complete_buf, sizeof(complete_buf)) == sizeof(complete_buf)) + return CC_ERROR; + /* add chars */ + if (ret == CMDLINE_PARSE_COMPLETED_BUFFER) { + /* if in the middle of a token, remove its suffix first */ + for (pos = 0; li->cursor + pos != li->lastchar; pos++) + if (isblank(li->cursor[pos])) + break; + el_cursor(el, pos); + el_deletestr(el, pos); + if (el_insertstr(el, complete_buf)) + return CC_ERROR; + return CC_REFRESH; + } + /* choice */ + fputs("\r\n", cl->f_out); + while (ret) { + fputc(' ', cl->f_out); + fputs(complete_buf, cl->f_out); + fputs("\r\n", cl->f_out); + ret = cmdline_complete(cl, line, &complete_state, + complete_buf, sizeof(complete_buf)); + } + el_set(el, EL_REFRESH); + return CC_REDISPLAY; +} + +static unsigned char +cmdline_el_delete_next_char_or_eof(EditLine *el, int c) { - if (!cl || !prompt) - return; - snprintf(cl->prompt, sizeof(cl->prompt), "%s", prompt); + const LineInfo *li = el_line(el); + struct cmdline *cl; + + (void)c; + if (el_get(el, EL_CLIENTDATA, &cl)) + return CC_FATAL; + if (li->buffer == li->lastchar) { + cl->eof = 1; + return CC_EOF; + } + el_cursor(el, 1); + el_deletestr(el, 1); + return CC_REFRESH; } struct cmdline * cmdline_new(cmdline_parse_ctx_t *ctx, const char *prompt, int s_in, int s_out) { struct cmdline *cl; - int ret; if (!ctx || !prompt) return NULL; @@ -85,36 +187,89 @@ cmdline_new(cmdline_parse_ctx_t *ctx, const char *prompt, int s_in, int s_out) if (cl == NULL) return NULL; memset(cl, 0, sizeof(struct cmdline)); - cl->s_in = s_in; - cl->s_out = s_out; + cl->line = NULL; + s_in = dup(s_in); + s_out = s_out != -1 ? dup(s_out) : open("/dev/null", O_WRONLY); + if (s_in == -1 || s_out == -1) + goto error; + cl->f_in = fdopen(s_in, "rb"); + cl->f_out = fdopen(s_out, "wb"); + if (!cl->f_in || !cl->f_out) + goto error; cl->ctx = ctx; - - ret = rdline_init(&cl->rdl, cmdline_write_char, cmdline_valid_buffer, - cmdline_complete_buffer); - if (ret != 0) { - free(cl); - return NULL; - } - - cl->rdl.opaque = cl; + cl->el = el_init("dpdk", cl->f_in, cl->f_out, stderr); + if (!cl->el) + goto error; + if (el_set(cl->el, EL_CLIENTDATA, cl)) + goto error; cmdline_set_prompt(cl, prompt); - rdline_newline(&cl->rdl, cl->prompt); - + if (el_set(cl->el, EL_PROMPT, cmdline_el_prompt)) + goto error; + if (el_set(cl->el, EL_EDITOR, "emacs")) + goto error; + if (el_set(cl->el, EL_SIGNAL, 1)) + goto error; + cl->hist = history_init(); + if (!cl->hist) + goto error; + if (history(cl->hist, &cl->histev, H_SETSIZE, + RDLINE_HISTORY_MAX_LINE) < 0) + goto error; + if (history(cl->hist, &cl->histev, H_SETUNIQUE, 1)) + goto error; + if (el_set(cl->el, EL_HIST, history, cl->hist)) + goto error; + if (el_set(cl->el, EL_ADDFN, "ed-execute", "Execute command", + cmdline_el_execute)) + goto error; + if (el_set(cl->el, EL_BIND, "^J", "ed-execute", NULL)) + goto error; + if (el_set(cl->el, EL_BIND, "^M", "ed-execute", NULL)) + goto error; + if (el_set(cl->el, EL_ADDFN, "ed-complete", "Complete argument", + cmdline_el_complete)) + goto error; + if (el_set(cl->el, EL_BIND, "^I", "ed-complete", NULL)) + goto error; + if (el_set(cl->el, EL_BIND, "?", "ed-complete", NULL)) + goto error; + if (el_set(cl->el, EL_ADDFN, "ed-delete-next-char-or-eof", + "Delete next character or assume EOF", + cmdline_el_delete_next_char_or_eof)) + goto error; + if (el_set(cl->el, EL_BIND, "^D", + "ed-delete-next-char-or-eof", NULL)) + goto error; + if (el_set(cl->el, EL_BIND, "^W", "ed-delete-prev-word", NULL)) + goto error; return cl; +error: + if (cl->hist) + history_end(cl->hist); + if (cl->el) + el_end(cl->el); + if (cl->f_out) + fclose(cl->f_out); + else if (s_out != -1) + close(s_out); + if (cl->f_in) + fclose(cl->f_in); + else if (s_in != -1) + close(s_in); + free(cl); + return NULL; } void cmdline_free(struct cmdline *cl) { - dprintf("called\n"); - if (!cl) return; - - if (cl->s_in > 2) - close(cl->s_in); - if (cl->s_out != cl->s_in && cl->s_out > 2) - close(cl->s_out); + history_end(cl->hist); + el_end(cl->el); + fclose(cl->f_out); + fclose(cl->f_in); + free(cl->line); free(cl); } @@ -126,70 +281,23 @@ cmdline_printf(const struct cmdline *cl, const char *fmt, ...) if (!cl || !fmt) return; -#ifdef _GNU_SOURCE - if (cl->s_out < 0) - return; - va_start(ap, fmt); - vdprintf(cl->s_out, fmt, ap); - va_end(ap); -#else - int ret; - char *buf; - - if (cl->s_out < 0) - return; - - buf = malloc(BUFSIZ); - if (buf == NULL) - return; va_start(ap, fmt); - ret = vsnprintf(buf, BUFSIZ, fmt, ap); + vfprintf(cl->f_out, fmt, ap); va_end(ap); - if (ret < 0) { - free(buf); - return; - } - if (ret >= BUFSIZ) - ret = BUFSIZ - 1; - ret = write(cl->s_out, buf, ret); - (void)ret; - free(buf); -#endif } int cmdline_in(struct cmdline *cl, const char *buf, int size) { - const char *history, *buffer; - size_t histlen, buflen; - int ret = 0; - int i, same; + int i; if (!cl || !buf) return -1; for (i=0; i<size; i++) { - ret = rdline_char_in(&cl->rdl, buf[i]); - - if (ret == RDLINE_RES_VALIDATED) { - buffer = rdline_get_buffer(&cl->rdl); - history = rdline_get_history_item(&cl->rdl, 0); - if (history) { - histlen = strnlen(history, RDLINE_BUF_SIZE); - same = !memcmp(buffer, history, histlen) && - buffer[histlen] == '\n'; - } - else - same = 0; - buflen = strnlen(buffer, RDLINE_BUF_SIZE); - if (buflen > 1 && !same) - rdline_add_history(&cl->rdl, buffer); - rdline_newline(&cl->rdl, cl->prompt); - } - else if (ret == RDLINE_RES_EOF) - return -1; - else if (ret == RDLINE_RES_EXITED) - return -1; + char tmp[2] = { buf[i], '\0' }; + + el_push(cl->el, tmp); } return i; } @@ -199,7 +307,7 @@ cmdline_quit(struct cmdline *cl) { if (!cl) return; - rdline_quit(&cl->rdl); + cl->eof = 1; } int @@ -207,48 +315,49 @@ cmdline_poll(struct cmdline *cl) { struct pollfd pfd; int status; - ssize_t read_status; - char c; + int read_status; + int flags; if (!cl) return -EINVAL; - else if (cl->rdl.status == RDLINE_EXITED) + else if (cl->error) + return RDLINE_ERROR; + else if (cl->eof) return RDLINE_EXITED; - pfd.fd = cl->s_in; + pfd.fd = fileno(cl->f_in); pfd.events = POLLIN; pfd.revents = 0; status = poll(&pfd, 1, 0); if (status < 0) - return status; - else if (status > 0) { - c = -1; - read_status = read(cl->s_in, &c, 1); - if (read_status < 0) - return read_status; - - status = cmdline_in(cl, &c, 1); - if (status < 0 && cl->rdl.status != RDLINE_EXITED) - return status; - } - - return cl->rdl.status; + return RDLINE_ERROR; + if (!status) + return RDLINE_RUNNING; + flags = fcntl(pfd.fd, F_GETFL); + if (!(flags & O_NONBLOCK)) + fcntl(pfd.fd, F_SETFL, flags | O_NONBLOCK); + if (!el_gets(cl->el, &read_status) && read_status == -1) + cl->error = 1; + if (!(flags & O_NONBLOCK)) + fcntl(pfd.fd, F_SETFL, flags); + return cl->error ? RDLINE_ERROR : + cl->eof ? RDLINE_EXITED : + RDLINE_RUNNING; } void cmdline_interact(struct cmdline *cl) { - char c; - if (!cl) return; - c = -1; - while (1) { - if (read(cl->s_in, &c, 1) <= 0) - break; - if (cmdline_in(cl, &c, 1) < 0) - break; + while (!cl->error && !cl->eof) { + int read_status; + + if (el_gets(cl->el, &read_status)) + continue; + if (read_status == -1) + cl->error = 1; } } diff --git a/lib/librte_cmdline/cmdline.h b/lib/librte_cmdline/cmdline.h index 27d2effdf..1f443be60 100644 --- a/lib/librte_cmdline/cmdline.h +++ b/lib/librte_cmdline/cmdline.h @@ -7,8 +7,6 @@ #ifndef _CMDLINE_H_ #define _CMDLINE_H_ -#include <termios.h> -#include <cmdline_rdline.h> #include <cmdline_parse.h> /** @@ -21,22 +19,26 @@ extern "C" { #endif -struct cmdline { - int s_in; - int s_out; - cmdline_parse_ctx_t *ctx; - struct rdline rdl; - char prompt[RDLINE_PROMPT_SIZE]; - struct termios oldterm; +#define RDLINE_PROMPT_SIZE 32 +#define RDLINE_HISTORY_MAX_LINE 64 +#define RDLINE_COMPLETE_SIZE 128 + +enum rdline_status { + RDLINE_ERROR = -1, + RDLINE_INIT, + RDLINE_RUNNING, + RDLINE_EXITED, }; +struct cmdline; + +void *cmdline_ctx_get(struct cmdline *cl); struct cmdline *cmdline_new(cmdline_parse_ctx_t *ctx, const char *prompt, int s_in, int s_out); void cmdline_set_prompt(struct cmdline *cl, const char *prompt); void cmdline_free(struct cmdline *cl); void cmdline_printf(const struct cmdline *cl, const char *fmt, ...) __attribute__((format(printf,2,3))); int cmdline_in(struct cmdline *cl, const char *buf, int size); -int cmdline_write_char(struct rdline *rdl, char c); /** * This function is nonblocking equivalent of ``cmdline_interact()``. It polls diff --git a/lib/librte_cmdline/cmdline_cirbuf.c b/lib/librte_cmdline/cmdline_cirbuf.c deleted file mode 100644 index 829a8af56..000000000 --- a/lib/librte_cmdline/cmdline_cirbuf.c +++ /dev/null @@ -1,412 +0,0 @@ -/* SPDX-License-Identifier: BSD-3-Clause - * Copyright(c) 2010-2014 Intel Corporation. - * Copyright (c) 2009, Olivier MATZ <zer0@droids-corp.org> - * All rights reserved. - */ - -#include <string.h> -#include <errno.h> -#include <stdio.h> - -#include "cmdline_cirbuf.h" - - -int -cirbuf_init(struct cirbuf *cbuf, char *buf, unsigned int start, unsigned int maxlen) -{ - if (!cbuf || !buf) - return -EINVAL; - cbuf->maxlen = maxlen; - cbuf->len = 0; - cbuf->start = start; - cbuf->end = start; - cbuf->buf = buf; - return 0; -} - -/* multiple add */ - -int -cirbuf_add_buf_head(struct cirbuf *cbuf, const char *c, unsigned int n) -{ - unsigned int e; - - if (!cbuf || !c || !n || n > CIRBUF_GET_FREELEN(cbuf)) - return -EINVAL; - - e = CIRBUF_IS_EMPTY(cbuf) ? 1 : 0; - - if (n < cbuf->start + e) { - dprintf("s[%d] -> d[%d] (%d)\n", 0, cbuf->start - n + e, n); - memcpy(cbuf->buf + cbuf->start - n + e, c, n); - } - else { - dprintf("s[%d] -> d[%d] (%d)\n", + n - (cbuf->start + e), 0, - cbuf->start + e); - dprintf("s[%d] -> d[%d] (%d)\n", cbuf->maxlen - n + - (cbuf->start + e), 0, n - (cbuf->start + e)); - memcpy(cbuf->buf, c + n - (cbuf->start + e) , cbuf->start + e); - memcpy(cbuf->buf + cbuf->maxlen - n + (cbuf->start + e), c, - n - (cbuf->start + e)); - } - cbuf->len += n; - cbuf->start += (cbuf->maxlen - n + e); - cbuf->start %= cbuf->maxlen; - return n; -} - -/* multiple add */ - -int -cirbuf_add_buf_tail(struct cirbuf *cbuf, const char *c, unsigned int n) -{ - unsigned int e; - - if (!cbuf || !c || !n || n > CIRBUF_GET_FREELEN(cbuf)) - return -EINVAL; - - e = CIRBUF_IS_EMPTY(cbuf) ? 1 : 0; - - if (n < cbuf->maxlen - cbuf->end - 1 + e) { - dprintf("s[%d] -> d[%d] (%d)\n", 0, cbuf->end + !e, n); - memcpy(cbuf->buf + cbuf->end + !e, c, n); - } - else { - dprintf("s[%d] -> d[%d] (%d)\n", cbuf->end + !e, 0, - cbuf->maxlen - cbuf->end - 1 + e); - dprintf("s[%d] -> d[%d] (%d)\n", cbuf->maxlen - cbuf->end - 1 + - e, 0, n - cbuf->maxlen + cbuf->end + 1 - e); - memcpy(cbuf->buf + cbuf->end + !e, c, cbuf->maxlen - - cbuf->end - 1 + e); - memcpy(cbuf->buf, c + cbuf->maxlen - cbuf->end - 1 + e, - n - cbuf->maxlen + cbuf->end + 1 - e); - } - cbuf->len += n; - cbuf->end += n - e; - cbuf->end %= cbuf->maxlen; - return n; -} - -/* add at head */ - -static inline void -__cirbuf_add_head(struct cirbuf * cbuf, char c) -{ - if (!CIRBUF_IS_EMPTY(cbuf)) { - cbuf->start += (cbuf->maxlen - 1); - cbuf->start %= cbuf->maxlen; - } - cbuf->buf[cbuf->start] = c; - cbuf->len ++; -} - -int -cirbuf_add_head_safe(struct cirbuf * cbuf, char c) -{ - if (cbuf && !CIRBUF_IS_FULL(cbuf)) { - __cirbuf_add_head(cbuf, c); - return 0; - } - return -EINVAL; -} - -void -cirbuf_add_head(struct cirbuf * cbuf, char c) -{ - __cirbuf_add_head(cbuf, c); -} - -/* add at tail */ - -static inline void -__cirbuf_add_tail(struct cirbuf * cbuf, char c) -{ - if (!CIRBUF_IS_EMPTY(cbuf)) { - cbuf->end ++; - cbuf->end %= cbuf->maxlen; - } - cbuf->buf[cbuf->end] = c; - cbuf->len ++; -} - -int -cirbuf_add_tail_safe(struct cirbuf * cbuf, char c) -{ - if (cbuf && !CIRBUF_IS_FULL(cbuf)) { - __cirbuf_add_tail(cbuf, c); - return 0; - } - return -EINVAL; -} - -void -cirbuf_add_tail(struct cirbuf * cbuf, char c) -{ - __cirbuf_add_tail(cbuf, c); -} - - -static inline void -__cirbuf_shift_left(struct cirbuf *cbuf) -{ - unsigned int i; - char tmp = cbuf->buf[cbuf->start]; - - for (i=0 ; i<cbuf->len ; i++) { - cbuf->buf[(cbuf->start+i)%cbuf->maxlen] = - cbuf->buf[(cbuf->start+i+1)%cbuf->maxlen]; - } - cbuf->buf[(cbuf->start-1+cbuf->maxlen)%cbuf->maxlen] = tmp; - cbuf->start += (cbuf->maxlen - 1); - cbuf->start %= cbuf->maxlen; - cbuf->end += (cbuf->maxlen - 1); - cbuf->end %= cbuf->maxlen; -} - -static inline void -__cirbuf_shift_right(struct cirbuf *cbuf) -{ - unsigned int i; - char tmp = cbuf->buf[cbuf->end]; - - for (i=0 ; i<cbuf->len ; i++) { - cbuf->buf[(cbuf->end+cbuf->maxlen-i)%cbuf->maxlen] = - cbuf->buf[(cbuf->end+cbuf->maxlen-i-1)%cbuf->maxlen]; - } - cbuf->buf[(cbuf->end+1)%cbuf->maxlen] = tmp; - cbuf->start += 1; - cbuf->start %= cbuf->maxlen; - cbuf->end += 1; - cbuf->end %= cbuf->maxlen; -} - -/* XXX we could do a better algorithm here... */ -int -cirbuf_align_left(struct cirbuf * cbuf) -{ - if (!cbuf) - return -EINVAL; - - if (cbuf->start < cbuf->maxlen/2) { - while (cbuf->start != 0) { - __cirbuf_shift_left(cbuf); - } - } - else { - while (cbuf->start != 0) { - __cirbuf_shift_right(cbuf); - } - } - - return 0; -} - -/* XXX we could do a better algorithm here... */ -int -cirbuf_align_right(struct cirbuf * cbuf) -{ - if (!cbuf) - return -EINVAL; - - if (cbuf->start >= cbuf->maxlen/2) { - while (cbuf->end != cbuf->maxlen-1) { - __cirbuf_shift_left(cbuf); - } - } - else { - while (cbuf->start != cbuf->maxlen-1) { - __cirbuf_shift_right(cbuf); - } - } - - return 0; -} - -/* buffer del */ - -int -cirbuf_del_buf_head(struct cirbuf *cbuf, unsigned int size) -{ - if (!cbuf || !size || size > CIRBUF_GET_LEN(cbuf)) - return -EINVAL; - - cbuf->len -= size; - if (CIRBUF_IS_EMPTY(cbuf)) { - cbuf->start += size - 1; - cbuf->start %= cbuf->maxlen; - } - else { - cbuf->start += size; - cbuf->start %= cbuf->maxlen; - } - return 0; -} - -/* buffer del */ - -int -cirbuf_del_buf_tail(struct cirbuf *cbuf, unsigned int size) -{ - if (!cbuf || !size || size > CIRBUF_GET_LEN(cbuf)) - return -EINVAL; - - cbuf->len -= size; - if (CIRBUF_IS_EMPTY(cbuf)) { - cbuf->end += (cbuf->maxlen - size + 1); - cbuf->end %= cbuf->maxlen; - } - else { - cbuf->end += (cbuf->maxlen - size); - cbuf->end %= cbuf->maxlen; - } - return 0; -} - -/* del at head */ - -static inline void -__cirbuf_del_head(struct cirbuf * cbuf) -{ - cbuf->len --; - if (!CIRBUF_IS_EMPTY(cbuf)) { - cbuf->start ++; - cbuf->start %= cbuf->maxlen; - } -} - -int -cirbuf_del_head_safe(struct cirbuf * cbuf) -{ - if (cbuf && !CIRBUF_IS_EMPTY(cbuf)) { - __cirbuf_del_head(cbuf); - return 0; - } - return -EINVAL; -} - -void -cirbuf_del_head(struct cirbuf * cbuf) -{ - __cirbuf_del_head(cbuf); -} - -/* del at tail */ - -static inline void -__cirbuf_del_tail(struct cirbuf * cbuf) -{ - cbuf->len --; - if (!CIRBUF_IS_EMPTY(cbuf)) { - cbuf->end += (cbuf->maxlen - 1); - cbuf->end %= cbuf->maxlen; - } -} - -int -cirbuf_del_tail_safe(struct cirbuf * cbuf) -{ - if (cbuf && !CIRBUF_IS_EMPTY(cbuf)) { - __cirbuf_del_tail(cbuf); - return 0; - } - return -EINVAL; -} - -void -cirbuf_del_tail(struct cirbuf * cbuf) -{ - __cirbuf_del_tail(cbuf); -} - -/* convert to buffer */ - -int -cirbuf_get_buf_head(struct cirbuf *cbuf, char *c, unsigned int size) -{ - unsigned int n; - - if (!cbuf || !c) - return -EINVAL; - - n = (size < CIRBUF_GET_LEN(cbuf)) ? size : CIRBUF_GET_LEN(cbuf); - - if (!n) - return 0; - - if (cbuf->start <= cbuf->end) { - dprintf("s[%d] -> d[%d] (%d)\n", cbuf->start, 0, n); - memcpy(c, cbuf->buf + cbuf->start , n); - } - else { - /* check if we need to go from end to the beginning */ - if (n <= cbuf->maxlen - cbuf->start) { - dprintf("s[%d] -> d[%d] (%d)\n", 0, cbuf->start, n); - memcpy(c, cbuf->buf + cbuf->start , n); - } - else { - dprintf("s[%d] -> d[%d] (%d)\n", cbuf->start, 0, - cbuf->maxlen - cbuf->start); - dprintf("s[%d] -> d[%d] (%d)\n", 0, cbuf->maxlen - cbuf->start, - n - cbuf->maxlen + cbuf->start); - memcpy(c, cbuf->buf + cbuf->start , cbuf->maxlen - cbuf->start); - memcpy(c + cbuf->maxlen - cbuf->start, cbuf->buf, - n - cbuf->maxlen + cbuf->start); - } - } - return n; -} - -/* convert to buffer */ - -int -cirbuf_get_buf_tail(struct cirbuf *cbuf, char *c, unsigned int size) -{ - unsigned int n; - - if (!cbuf || !c) - return -EINVAL; - - n = (size < CIRBUF_GET_LEN(cbuf)) ? size : CIRBUF_GET_LEN(cbuf); - - if (!n) - return 0; - - if (cbuf->start <= cbuf->end) { - dprintf("s[%d] -> d[%d] (%d)\n", cbuf->end - n + 1, 0, n); - memcpy(c, cbuf->buf + cbuf->end - n + 1, n); - } - else { - /* check if we need to go from end to the beginning */ - if (n <= cbuf->end + 1) { - dprintf("s[%d] -> d[%d] (%d)\n", 0, cbuf->end - n + 1, n); - memcpy(c, cbuf->buf + cbuf->end - n + 1, n); - } - else { - dprintf("s[%d] -> d[%d] (%d)\n", 0, - cbuf->maxlen - cbuf->start, cbuf->end + 1); - dprintf("s[%d] -> d[%d] (%d)\n", - cbuf->maxlen - n + cbuf->end + 1, 0, n - cbuf->end - 1); - memcpy(c + cbuf->maxlen - cbuf->start, - cbuf->buf, cbuf->end + 1); - memcpy(c, cbuf->buf + cbuf->maxlen - n + cbuf->end +1, - n - cbuf->end - 1); - } - } - return n; -} - -/* get head or get tail */ - -char -cirbuf_get_head(struct cirbuf * cbuf) -{ - return cbuf->buf[cbuf->start]; -} - -/* get head or get tail */ - -char -cirbuf_get_tail(struct cirbuf * cbuf) -{ - return cbuf->buf[cbuf->end]; -} diff --git a/lib/librte_cmdline/cmdline_cirbuf.h b/lib/librte_cmdline/cmdline_cirbuf.h deleted file mode 100644 index c23b211ad..000000000 --- a/lib/librte_cmdline/cmdline_cirbuf.h +++ /dev/null @@ -1,193 +0,0 @@ -/* SPDX-License-Identifier: BSD-3-Clause - * Copyright(c) 2010-2014 Intel Corporation. - * Copyright (c) 2009, Olivier MATZ <zer0@droids-corp.org> - * All rights reserved. - */ - -#ifndef _CIRBUF_H_ -#define _CIRBUF_H_ - -#include <rte_config.h> - -#ifdef __cplusplus -extern "C" { -#endif - -/** - * This structure is the header of a cirbuf type. - */ -struct cirbuf { - unsigned int maxlen; /**< total len of the fifo (number of elements) */ - unsigned int start; /**< indice of the first elt */ - unsigned int end; /**< indice of the last elt */ - unsigned int len; /**< current len of fifo */ - char *buf; -}; - -#ifdef RTE_LIBRTE_CMDLINE_DEBUG -#define dprintf_(fmt, ...) printf("line %3.3d - " fmt "%.0s", __LINE__, __VA_ARGS__) -#define dprintf(...) dprintf_(__VA_ARGS__, "dummy") -#else -#define dprintf(...) (void)0 -#endif - - -/** - * Init the circular buffer - */ -int cirbuf_init(struct cirbuf *cbuf, char *buf, unsigned int start, unsigned int maxlen); - - -/** - * Return 1 if the circular buffer is full - */ -#define CIRBUF_IS_FULL(cirbuf) ((cirbuf)->maxlen == (cirbuf)->len) - -/** - * Return 1 if the circular buffer is empty - */ -#define CIRBUF_IS_EMPTY(cirbuf) ((cirbuf)->len == 0) - -/** - * return current size of the circular buffer (number of used elements) - */ -#define CIRBUF_GET_LEN(cirbuf) ((cirbuf)->len) - -/** - * return size of the circular buffer (used + free elements) - */ -#define CIRBUF_GET_MAXLEN(cirbuf) ((cirbuf)->maxlen) - -/** - * return the number of free elts - */ -#define CIRBUF_GET_FREELEN(cirbuf) ((cirbuf)->maxlen - (cirbuf)->len) - -/** - * Iterator for a circular buffer - * c: struct cirbuf pointer - * i: an integer type internally used in the macro - * e: char that takes the value for each iteration - */ -#define CIRBUF_FOREACH(c, i, e) \ - for ( i=0, e=(c)->buf[(c)->start] ; \ - i<((c)->len) ; \ - i ++, e=(c)->buf[((c)->start+i)%((c)->maxlen)]) - - -/** - * Add a character at head of the circular buffer. Return 0 on success, or - * a negative value on error. - */ -int cirbuf_add_head_safe(struct cirbuf *cbuf, char c); - -/** - * Add a character at head of the circular buffer. You _must_ check that you - * have enough free space in the buffer before calling this func. - */ -void cirbuf_add_head(struct cirbuf *cbuf, char c); - -/** - * Add a character at tail of the circular buffer. Return 0 on success, or - * a negative value on error. - */ -int cirbuf_add_tail_safe(struct cirbuf *cbuf, char c); - -/** - * Add a character at tail of the circular buffer. You _must_ check that you - * have enough free space in the buffer before calling this func. - */ -void cirbuf_add_tail(struct cirbuf *cbuf, char c); - -/** - * Remove a char at the head of the circular buffer. Return 0 on - * success, or a negative value on error. - */ -int cirbuf_del_head_safe(struct cirbuf *cbuf); - -/** - * Remove a char at the head of the circular buffer. You _must_ check - * that buffer is not empty before calling the function. - */ -void cirbuf_del_head(struct cirbuf *cbuf); - -/** - * Remove a char at the tail of the circular buffer. Return 0 on - * success, or a negative value on error. - */ -int cirbuf_del_tail_safe(struct cirbuf *cbuf); - -/** - * Remove a char at the tail of the circular buffer. You _must_ check - * that buffer is not empty before calling the function. - */ -void cirbuf_del_tail(struct cirbuf *cbuf); - -/** - * Return the head of the circular buffer. You _must_ check that - * buffer is not empty before calling the function. - */ -char cirbuf_get_head(struct cirbuf *cbuf); - -/** - * Return the tail of the circular buffer. You _must_ check that - * buffer is not empty before calling the function. - */ -char cirbuf_get_tail(struct cirbuf *cbuf); - -/** - * Add a buffer at head of the circular buffer. 'c' is a pointer to a - * buffer, and n is the number of char to add. Return the number of - * copied bytes on success, or a negative value on error. - */ -int cirbuf_add_buf_head(struct cirbuf *cbuf, const char *c, unsigned int n); - -/** - * Add a buffer at tail of the circular buffer. 'c' is a pointer to a - * buffer, and n is the number of char to add. Return the number of - * copied bytes on success, or a negative value on error. - */ -int cirbuf_add_buf_tail(struct cirbuf *cbuf, const char *c, unsigned int n); - -/** - * Remove chars at the head of the circular buffer. Return 0 on - * success, or a negative value on error. - */ -int cirbuf_del_buf_head(struct cirbuf *cbuf, unsigned int size); - -/** - * Remove chars at the tail of the circular buffer. Return 0 on - * success, or a negative value on error. - */ -int cirbuf_del_buf_tail(struct cirbuf *cbuf, unsigned int size); - -/** - * Copy a maximum of 'size' characters from the head of the circular - * buffer to a flat one pointed by 'c'. Return the number of copied - * chars. - */ -int cirbuf_get_buf_head(struct cirbuf *cbuf, char *c, unsigned int size); - -/** - * Copy a maximum of 'size' characters from the tail of the circular - * buffer to a flat one pointed by 'c'. Return the number of copied - * chars. - */ -int cirbuf_get_buf_tail(struct cirbuf *cbuf, char *c, unsigned int size); - - -/** - * Set the start of the data to the index 0 of the internal buffer. - */ -int cirbuf_align_left(struct cirbuf *cbuf); - -/** - * Set the end of the data to the last index of the internal buffer. - */ -int cirbuf_align_right(struct cirbuf *cbuf); - -#ifdef __cplusplus -} -#endif - -#endif /* _CIRBUF_H_ */ diff --git a/lib/librte_cmdline/cmdline_parse.c b/lib/librte_cmdline/cmdline_parse.c index 961f9befd..f75870b5b 100644 --- a/lib/librte_cmdline/cmdline_parse.c +++ b/lib/librte_cmdline/cmdline_parse.c @@ -16,7 +16,6 @@ #include <rte_string_fns.h> -#include "cmdline_rdline.h" #include "cmdline_parse.h" #include "cmdline.h" @@ -216,7 +215,7 @@ cmdline_parse(struct cmdline *cl, const char * buf) if (!cl || !buf) return CMDLINE_PARSE_BAD_ARGS; - ctx = cl->ctx; + ctx = cmdline_ctx_get(cl); /* * - look if the buffer contains at least one line @@ -334,7 +333,7 @@ cmdline_complete(struct cmdline *cl, const char *buf, int *state, if (!cl || !buf || !state || !dst) return -1; - ctx = cl->ctx; + ctx = cmdline_ctx_get(cl); debug_printf("%s called\n", __func__); memset(&token_hdr, 0, sizeof(token_hdr)); @@ -346,7 +345,7 @@ cmdline_complete(struct cmdline *cl, const char *buf, int *state, if (isblank2(buf[i]) && !isblank2(buf[i+1])) partial_tok = buf+i+1; } - partial_tok_len = strnlen(partial_tok, RDLINE_BUF_SIZE); + partial_tok_len = strlen(partial_tok); /* first call -> do a first pass */ if (*state <= 0) { diff --git a/lib/librte_cmdline/cmdline_rdline.c b/lib/librte_cmdline/cmdline_rdline.c deleted file mode 100644 index 2cb53e38f..000000000 --- a/lib/librte_cmdline/cmdline_rdline.c +++ /dev/null @@ -1,644 +0,0 @@ -/* SPDX-License-Identifier: BSD-3-Clause - * Copyright(c) 2010-2014 Intel Corporation. - * Copyright (c) 2009, Olivier MATZ <zer0@droids-corp.org> - * All rights reserved. - */ - -#include <stdlib.h> -#include <stdio.h> -#include <stdint.h> -#include <string.h> -#include <stdarg.h> -#include <errno.h> -#include <ctype.h> - -#include "cmdline_cirbuf.h" -#include "cmdline_rdline.h" - -static void rdline_puts(struct rdline *rdl, const char *buf); -static void rdline_miniprintf(struct rdline *rdl, - const char *buf, unsigned int val); - -static void rdline_remove_old_history_item(struct rdline *rdl); -static void rdline_remove_first_history_item(struct rdline *rdl); -static unsigned int rdline_get_history_size(struct rdline *rdl); - - -/* isblank() needs _XOPEN_SOURCE >= 600 || _ISOC99_SOURCE, so use our - * own. */ -static int -isblank2(char c) -{ - if (c == ' ' || - c == '\t' ) - return 1; - return 0; -} - -int -rdline_init(struct rdline *rdl, - rdline_write_char_t *write_char, - rdline_validate_t *validate, - rdline_complete_t *complete) -{ - if (!rdl || !write_char || !validate || !complete) - return -EINVAL; - memset(rdl, 0, sizeof(*rdl)); - rdl->validate = validate; - rdl->complete = complete; - rdl->write_char = write_char; - rdl->status = RDLINE_INIT; - return cirbuf_init(&rdl->history, rdl->history_buf, 0, RDLINE_HISTORY_BUF_SIZE); -} - -void -rdline_newline(struct rdline *rdl, const char *prompt) -{ - unsigned int i; - - if (!rdl || !prompt) - return; - - vt100_init(&rdl->vt100); - cirbuf_init(&rdl->left, rdl->left_buf, 0, RDLINE_BUF_SIZE); - cirbuf_init(&rdl->right, rdl->right_buf, 0, RDLINE_BUF_SIZE); - - rdl->prompt_size = strnlen(prompt, RDLINE_PROMPT_SIZE-1); - if (prompt != rdl->prompt) - memcpy(rdl->prompt, prompt, rdl->prompt_size); - rdl->prompt[RDLINE_PROMPT_SIZE-1] = '\0'; - - for (i=0 ; i<rdl->prompt_size ; i++) - rdl->write_char(rdl, rdl->prompt[i]); - rdl->status = RDLINE_RUNNING; - - rdl->history_cur_line = -1; -} - -void -rdline_stop(struct rdline *rdl) -{ - if (!rdl) - return; - rdl->status = RDLINE_INIT; -} - -void -rdline_quit(struct rdline *rdl) -{ - if (!rdl) - return; - rdl->status = RDLINE_EXITED; -} - -void -rdline_restart(struct rdline *rdl) -{ - if (!rdl) - return; - rdl->status = RDLINE_RUNNING; -} - -void -rdline_reset(struct rdline *rdl) -{ - if (!rdl) - return; - vt100_init(&rdl->vt100); - cirbuf_init(&rdl->left, rdl->left_buf, 0, RDLINE_BUF_SIZE); - cirbuf_init(&rdl->right, rdl->right_buf, 0, RDLINE_BUF_SIZE); - - rdl->status = RDLINE_RUNNING; - - rdl->history_cur_line = -1; -} - -const char * -rdline_get_buffer(struct rdline *rdl) -{ - if (!rdl) - return NULL; - unsigned int len_l, len_r; - cirbuf_align_left(&rdl->left); - cirbuf_align_left(&rdl->right); - - len_l = CIRBUF_GET_LEN(&rdl->left); - len_r = CIRBUF_GET_LEN(&rdl->right); - memcpy(rdl->left_buf+len_l, rdl->right_buf, len_r); - - rdl->left_buf[len_l + len_r] = '\n'; - rdl->left_buf[len_l + len_r + 1] = '\0'; - return rdl->left_buf; -} - -static void -display_right_buffer(struct rdline *rdl, int force) -{ - unsigned int i; - char tmp; - - if (!force && CIRBUF_IS_EMPTY(&rdl->right)) - return; - - rdline_puts(rdl, vt100_clear_right); - CIRBUF_FOREACH(&rdl->right, i, tmp) { - rdl->write_char(rdl, tmp); - } - if (!CIRBUF_IS_EMPTY(&rdl->right)) - rdline_miniprintf(rdl, vt100_multi_left, - CIRBUF_GET_LEN(&rdl->right)); -} - -void -rdline_redisplay(struct rdline *rdl) -{ - unsigned int i; - char tmp; - - if (!rdl) - return; - - rdline_puts(rdl, vt100_home); - for (i=0 ; i<rdl->prompt_size ; i++) - rdl->write_char(rdl, rdl->prompt[i]); - CIRBUF_FOREACH(&rdl->left, i, tmp) { - rdl->write_char(rdl, tmp); - } - display_right_buffer(rdl, 1); -} - -int -rdline_char_in(struct rdline *rdl, char c) -{ - unsigned int i; - int cmd; - char tmp; - char *buf; - - if (!rdl) - return -EINVAL; - - if (rdl->status == RDLINE_EXITED) - return RDLINE_RES_EXITED; - if (rdl->status != RDLINE_RUNNING) - return RDLINE_RES_NOT_RUNNING; - - cmd = vt100_parser(&rdl->vt100, c); - if (cmd == -2) - return RDLINE_RES_SUCCESS; - - if (cmd >= 0) { - switch (cmd) { - /* move caret 1 char to the left */ - case CMDLINE_KEY_CTRL_B: - case CMDLINE_KEY_LEFT_ARR: - if (CIRBUF_IS_EMPTY(&rdl->left)) - break; - tmp = cirbuf_get_tail(&rdl->left); - cirbuf_del_tail(&rdl->left); - cirbuf_add_head(&rdl->right, tmp); - rdline_puts(rdl, vt100_left_arr); - break; - - /* move caret 1 char to the right */ - case CMDLINE_KEY_CTRL_F: - case CMDLINE_KEY_RIGHT_ARR: - if (CIRBUF_IS_EMPTY(&rdl->right)) - break; - tmp = cirbuf_get_head(&rdl->right); - cirbuf_del_head(&rdl->right); - cirbuf_add_tail(&rdl->left, tmp); - rdline_puts(rdl, vt100_right_arr); - break; - - /* move caret 1 word to the left */ - /* keyboard equivalent: Alt+B */ - case CMDLINE_KEY_WLEFT: - while (! CIRBUF_IS_EMPTY(&rdl->left) && - (tmp = cirbuf_get_tail(&rdl->left)) && - isblank2(tmp)) { - rdline_puts(rdl, vt100_left_arr); - cirbuf_del_tail(&rdl->left); - cirbuf_add_head(&rdl->right, tmp); - } - while (! CIRBUF_IS_EMPTY(&rdl->left) && - (tmp = cirbuf_get_tail(&rdl->left)) && - !isblank2(tmp)) { - rdline_puts(rdl, vt100_left_arr); - cirbuf_del_tail(&rdl->left); - cirbuf_add_head(&rdl->right, tmp); - } - break; - - /* move caret 1 word to the right */ - /* keyboard equivalent: Alt+F */ - case CMDLINE_KEY_WRIGHT: - while (! CIRBUF_IS_EMPTY(&rdl->right) && - (tmp = cirbuf_get_head(&rdl->right)) && - isblank2(tmp)) { - rdline_puts(rdl, vt100_right_arr); - cirbuf_del_head(&rdl->right); - cirbuf_add_tail(&rdl->left, tmp); - } - while (! CIRBUF_IS_EMPTY(&rdl->right) && - (tmp = cirbuf_get_head(&rdl->right)) && - !isblank2(tmp)) { - rdline_puts(rdl, vt100_right_arr); - cirbuf_del_head(&rdl->right); - cirbuf_add_tail(&rdl->left, tmp); - } - break; - - /* move caret to the left */ - case CMDLINE_KEY_CTRL_A: - if (CIRBUF_IS_EMPTY(&rdl->left)) - break; - rdline_miniprintf(rdl, vt100_multi_left, - CIRBUF_GET_LEN(&rdl->left)); - while (! CIRBUF_IS_EMPTY(&rdl->left)) { - tmp = cirbuf_get_tail(&rdl->left); - cirbuf_del_tail(&rdl->left); - cirbuf_add_head(&rdl->right, tmp); - } - break; - - /* move caret to the right */ - case CMDLINE_KEY_CTRL_E: - if (CIRBUF_IS_EMPTY(&rdl->right)) - break; - rdline_miniprintf(rdl, vt100_multi_right, - CIRBUF_GET_LEN(&rdl->right)); - while (! CIRBUF_IS_EMPTY(&rdl->right)) { - tmp = cirbuf_get_head(&rdl->right); - cirbuf_del_head(&rdl->right); - cirbuf_add_tail(&rdl->left, tmp); - } - break; - - /* delete 1 char from the left */ - case CMDLINE_KEY_BKSPACE: - case CMDLINE_KEY_BKSPACE2: - if(!cirbuf_del_tail_safe(&rdl->left)) { - rdline_puts(rdl, vt100_bs); - display_right_buffer(rdl, 1); - } - break; - - /* delete 1 char from the right */ - case CMDLINE_KEY_SUPPR: - case CMDLINE_KEY_CTRL_D: - if (cmd == CMDLINE_KEY_CTRL_D && - CIRBUF_IS_EMPTY(&rdl->left) && - CIRBUF_IS_EMPTY(&rdl->right)) { - return RDLINE_RES_EOF; - } - if (!cirbuf_del_head_safe(&rdl->right)) { - display_right_buffer(rdl, 1); - } - break; - - /* delete 1 word from the left */ - case CMDLINE_KEY_META_BKSPACE: - case CMDLINE_KEY_CTRL_W: - while (! CIRBUF_IS_EMPTY(&rdl->left) && isblank2(cirbuf_get_tail(&rdl->left))) { - rdline_puts(rdl, vt100_bs); - cirbuf_del_tail(&rdl->left); - } - while (! CIRBUF_IS_EMPTY(&rdl->left) && !isblank2(cirbuf_get_tail(&rdl->left))) { - rdline_puts(rdl, vt100_bs); - cirbuf_del_tail(&rdl->left); - } - display_right_buffer(rdl, 1); - break; - - /* delete 1 word from the right */ - case CMDLINE_KEY_META_D: - while (! CIRBUF_IS_EMPTY(&rdl->right) && isblank2(cirbuf_get_head(&rdl->right))) - cirbuf_del_head(&rdl->right); - while (! CIRBUF_IS_EMPTY(&rdl->right) && !isblank2(cirbuf_get_head(&rdl->right))) - cirbuf_del_head(&rdl->right); - display_right_buffer(rdl, 1); - break; - - /* set kill buffer to contents on the right side of caret */ - case CMDLINE_KEY_CTRL_K: - cirbuf_get_buf_head(&rdl->right, rdl->kill_buf, RDLINE_BUF_SIZE); - rdl->kill_size = CIRBUF_GET_LEN(&rdl->right); - cirbuf_del_buf_head(&rdl->right, rdl->kill_size); - rdline_puts(rdl, vt100_clear_right); - break; - - /* paste contents of kill buffer to the left side of caret */ - case CMDLINE_KEY_CTRL_Y: - i=0; - while(CIRBUF_GET_LEN(&rdl->right) + CIRBUF_GET_LEN(&rdl->left) < - RDLINE_BUF_SIZE && - i < rdl->kill_size) { - cirbuf_add_tail(&rdl->left, rdl->kill_buf[i]); - rdl->write_char(rdl, rdl->kill_buf[i]); - i++; - } - display_right_buffer(rdl, 0); - break; - - /* clear and newline */ - case CMDLINE_KEY_CTRL_C: - rdline_puts(rdl, "\r\n"); - rdline_newline(rdl, rdl->prompt); - break; - - /* redisplay (helps when prompt is lost in other output) */ - case CMDLINE_KEY_CTRL_L: - rdline_redisplay(rdl); - break; - - /* autocomplete */ - case CMDLINE_KEY_TAB: - case CMDLINE_KEY_HELP: - cirbuf_align_left(&rdl->left); - rdl->left_buf[CIRBUF_GET_LEN(&rdl->left)] = '\0'; - if (rdl->complete) { - char tmp_buf[BUFSIZ]; - int complete_state; - int ret; - unsigned int tmp_size; - - if (cmd == CMDLINE_KEY_TAB) - complete_state = 0; - else - complete_state = -1; - - /* see in parse.h for help on complete() */ - ret = rdl->complete(rdl, rdl->left_buf, - tmp_buf, sizeof(tmp_buf), - &complete_state); - /* no completion or error */ - if (ret <= 0) { - return RDLINE_RES_COMPLETE; - } - - tmp_size = strnlen(tmp_buf, sizeof(tmp_buf)); - /* add chars */ - if (ret == RDLINE_RES_COMPLETE) { - i=0; - while(CIRBUF_GET_LEN(&rdl->right) + CIRBUF_GET_LEN(&rdl->left) < - RDLINE_BUF_SIZE && - i < tmp_size) { - cirbuf_add_tail(&rdl->left, tmp_buf[i]); - rdl->write_char(rdl, tmp_buf[i]); - i++; - } - display_right_buffer(rdl, 1); - return RDLINE_RES_COMPLETE; /* ?? */ - } - - /* choice */ - rdline_puts(rdl, "\r\n"); - while (ret) { - rdl->write_char(rdl, ' '); - for (i=0 ; tmp_buf[i] ; i++) - rdl->write_char(rdl, tmp_buf[i]); - rdline_puts(rdl, "\r\n"); - ret = rdl->complete(rdl, rdl->left_buf, - tmp_buf, sizeof(tmp_buf), - &complete_state); - } - - rdline_redisplay(rdl); - } - return RDLINE_RES_COMPLETE; - - /* complete buffer */ - case CMDLINE_KEY_RETURN: - case CMDLINE_KEY_RETURN2: - rdline_get_buffer(rdl); - rdl->status = RDLINE_INIT; - rdline_puts(rdl, "\r\n"); - if (rdl->history_cur_line != -1) - rdline_remove_first_history_item(rdl); - - if (rdl->validate) - rdl->validate(rdl, rdl->left_buf, CIRBUF_GET_LEN(&rdl->left)+2); - /* user may have stopped rdline */ - if (rdl->status == RDLINE_EXITED) - return RDLINE_RES_EXITED; - return RDLINE_RES_VALIDATED; - - /* previous element in history */ - case CMDLINE_KEY_UP_ARR: - case CMDLINE_KEY_CTRL_P: - if (rdl->history_cur_line == 0) { - rdline_remove_first_history_item(rdl); - } - if (rdl->history_cur_line <= 0) { - rdline_add_history(rdl, rdline_get_buffer(rdl)); - rdl->history_cur_line = 0; - } - - buf = rdline_get_history_item(rdl, rdl->history_cur_line + 1); - if (!buf) - break; - - rdl->history_cur_line ++; - vt100_init(&rdl->vt100); - cirbuf_init(&rdl->left, rdl->left_buf, 0, RDLINE_BUF_SIZE); - cirbuf_init(&rdl->right, rdl->right_buf, 0, RDLINE_BUF_SIZE); - cirbuf_add_buf_tail(&rdl->left, buf, strnlen(buf, RDLINE_BUF_SIZE)); - rdline_redisplay(rdl); - break; - - /* next element in history */ - case CMDLINE_KEY_DOWN_ARR: - case CMDLINE_KEY_CTRL_N: - if (rdl->history_cur_line - 1 < 0) - break; - - rdl->history_cur_line --; - buf = rdline_get_history_item(rdl, rdl->history_cur_line); - if (!buf) - break; - vt100_init(&rdl->vt100); - cirbuf_init(&rdl->left, rdl->left_buf, 0, RDLINE_BUF_SIZE); - cirbuf_init(&rdl->right, rdl->right_buf, 0, RDLINE_BUF_SIZE); - cirbuf_add_buf_tail(&rdl->left, buf, strnlen(buf, RDLINE_BUF_SIZE)); - rdline_redisplay(rdl); - - break; - - - default: - break; - } - - return RDLINE_RES_SUCCESS; - } - - if (!isprint((int)c)) - return RDLINE_RES_SUCCESS; - - /* standard chars */ - if (CIRBUF_GET_LEN(&rdl->left) + CIRBUF_GET_LEN(&rdl->right) >= RDLINE_BUF_SIZE) - return RDLINE_RES_SUCCESS; - - if (cirbuf_add_tail_safe(&rdl->left, c)) - return RDLINE_RES_SUCCESS; - - rdl->write_char(rdl, c); - display_right_buffer(rdl, 0); - - return RDLINE_RES_SUCCESS; -} - - -/* HISTORY */ - -static void -rdline_remove_old_history_item(struct rdline * rdl) -{ - char tmp; - - while (! CIRBUF_IS_EMPTY(&rdl->history) ) { - tmp = cirbuf_get_head(&rdl->history); - cirbuf_del_head(&rdl->history); - if (!tmp) - break; - } -} - -static void -rdline_remove_first_history_item(struct rdline * rdl) -{ - char tmp; - - if ( CIRBUF_IS_EMPTY(&rdl->history) ) { - return; - } - else { - cirbuf_del_tail(&rdl->history); - } - - while (! CIRBUF_IS_EMPTY(&rdl->history) ) { - tmp = cirbuf_get_tail(&rdl->history); - if (!tmp) - break; - cirbuf_del_tail(&rdl->history); - } -} - -static unsigned int -rdline_get_history_size(struct rdline * rdl) -{ - unsigned int i, tmp, ret=0; - - CIRBUF_FOREACH(&rdl->history, i, tmp) { - if (tmp == 0) - ret ++; - } - - return ret; -} - -char * -rdline_get_history_item(struct rdline * rdl, unsigned int idx) -{ - unsigned int len, i, tmp; - - if (!rdl) - return NULL; - - len = rdline_get_history_size(rdl); - if ( idx >= len ) { - return NULL; - } - - cirbuf_align_left(&rdl->history); - - CIRBUF_FOREACH(&rdl->history, i, tmp) { - if ( idx == len - 1) { - return rdl->history_buf + i; - } - if (tmp == 0) - len --; - } - - return NULL; -} - -int -rdline_add_history(struct rdline * rdl, const char * buf) -{ - unsigned int len, i; - - if (!rdl || !buf) - return -EINVAL; - - len = strnlen(buf, RDLINE_BUF_SIZE); - for (i=0; i<len ; i++) { - if (buf[i] == '\n') { - len = i; - break; - } - } - - if ( len >= RDLINE_HISTORY_BUF_SIZE ) - return -1; - - while ( len >= CIRBUF_GET_FREELEN(&rdl->history) ) { - rdline_remove_old_history_item(rdl); - } - - cirbuf_add_buf_tail(&rdl->history, buf, len); - cirbuf_add_tail(&rdl->history, 0); - - return 0; -} - -void -rdline_clear_history(struct rdline * rdl) -{ - if (!rdl) - return; - cirbuf_init(&rdl->history, rdl->history_buf, 0, RDLINE_HISTORY_BUF_SIZE); -} - - -/* STATIC USEFUL FUNCS */ - -static void -rdline_puts(struct rdline * rdl, const char * buf) -{ - char c; - while ( (c = *(buf++)) != '\0' ) { - rdl->write_char(rdl, c); - } -} - -/* a very very basic printf with one arg and one format 'u' */ -static void -rdline_miniprintf(struct rdline *rdl, const char * buf, unsigned int val) -{ - char c, started=0, div=100; - - while ( (c=*(buf++)) ) { - if (c != '%') { - rdl->write_char(rdl, c); - continue; - } - c = *(buf++); - if (c != 'u') { - rdl->write_char(rdl, '%'); - rdl->write_char(rdl, c); - continue; - } - /* val is never more than 255 */ - while (div) { - c = (char)(val / div); - if (c || started) { - rdl->write_char(rdl, (char)(c+'0')); - started = 1; - } - val %= div; - div /= 10; - } - } -} diff --git a/lib/librte_cmdline/cmdline_rdline.h b/lib/librte_cmdline/cmdline_rdline.h deleted file mode 100644 index d2170293d..000000000 --- a/lib/librte_cmdline/cmdline_rdline.h +++ /dev/null @@ -1,201 +0,0 @@ -/* SPDX-License-Identifier: BSD-3-Clause - * Copyright(c) 2010-2014 Intel Corporation. - * Copyright (c) 2009, Olivier MATZ <zer0@droids-corp.org> - * All rights reserved. - */ - -#ifndef _RDLINE_H_ -#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. - * - * Obviously, it does not support as many things as the GNU readline, - * but at least it supports some interesting 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. - */ - -#include <stdio.h> -#include <cmdline_cirbuf.h> -#include <cmdline_vt100.h> - -#ifdef __cplusplus -extern "C" { -#endif - -/* configuration */ -#define RDLINE_BUF_SIZE 512 -#define RDLINE_PROMPT_SIZE 32 -#define RDLINE_VT100_BUF_SIZE 8 -#define RDLINE_HISTORY_BUF_SIZE BUFSIZ -#define RDLINE_HISTORY_MAX_LINE 64 - -enum rdline_status { - RDLINE_INIT, - RDLINE_RUNNING, - RDLINE_EXITED -}; - -struct rdline; - -typedef int (rdline_write_char_t)(struct rdline *rdl, char); -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); - -struct rdline { - enum rdline_status status; - /* rdline bufs */ - struct cirbuf left; - struct cirbuf right; - char left_buf[RDLINE_BUF_SIZE+2]; /* reserve 2 chars for the \n\0 */ - char right_buf[RDLINE_BUF_SIZE]; - - char prompt[RDLINE_PROMPT_SIZE]; - unsigned int prompt_size; - - char kill_buf[RDLINE_BUF_SIZE]; - unsigned int kill_size; - - /* history */ - struct cirbuf history; - char history_buf[RDLINE_HISTORY_BUF_SIZE]; - int history_cur_line; - - /* callbacks and func pointers */ - rdline_write_char_t *write_char; - rdline_validate_t *validate; - rdline_complete_t *complete; - - /* vt100 parser */ - struct cmdline_vt100 vt100; - - /* opaque pointer */ - void *opaque; -}; - -/** - * 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. - */ -int rdline_init(struct rdline *rdl, - rdline_write_char_t *write_char, - rdline_validate_t *validate, - rdline_complete_t *complete); - - -/** - * Init the current buffer, and display a prompt. - * \param rdl A pointer to a 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 - */ -void rdline_stop(struct rdline *rdl); - -/** - * Same than rdline_stop() except that next calls to rdline_char_in() - * will return RDLINE_RES_EXITED. - * \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 - */ -void rdline_redisplay(struct rdline *rdl); - -/** - * Reset the current buffer and setup for a new line. - * \param rdl A pointer to a struct rdline - */ -void rdline_reset(struct rdline *rdl); - - -/* return status for rdline_char_in() */ -#define RDLINE_RES_SUCCESS 0 -#define RDLINE_RES_VALIDATED 1 -#define RDLINE_RES_COMPLETE 2 -#define RDLINE_RES_NOT_RUNNING -1 -#define RDLINE_RES_EOF -2 -#define RDLINE_RES_EXITED -3 - -/** - * append a char to the readline buffer. - * Return RDLINE_RES_VALIDATE when the line has been validated. - * Return RDLINE_RES_COMPLETE when the user asked to complete the buffer. - * Return RDLINE_RES_NOT_RUNNING if it is not running. - * Return RDLINE_RES_EOF if EOF (ctrl-d on an empty line). - * Else return RDLINE_RES_SUCCESS. - * XXX error case when the buffer is full ? - * - * \param rdl A pointer to a struct rdline - * \param c The character to append - */ -int rdline_char_in(struct rdline *rdl, char c); - -/** - * Return the current buffer, terminated by '\0'. - * \param rdl A pointer to a struct rdline - */ -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' - */ -int rdline_add_history(struct rdline *rdl, const char *buf); - -/** - * Clear current history - * \param rdl A pointer to a struct rdline - */ -void rdline_clear_history(struct rdline *rdl); - -/** - * Get the i-th history item - */ -char *rdline_get_history_item(struct rdline *rdl, unsigned int i); - -#ifdef __cplusplus -} -#endif - -#endif /* _RDLINE_H_ */ diff --git a/lib/librte_cmdline/cmdline_socket.c b/lib/librte_cmdline/cmdline_socket.c index ecb3d82b6..f639c61cb 100644 --- a/lib/librte_cmdline/cmdline_socket.c +++ b/lib/librte_cmdline/cmdline_socket.c @@ -4,23 +4,18 @@ * All rights reserved. */ -#include <stdio.h> -#include <string.h> +#include <stddef.h> #include <unistd.h> -#include <stdlib.h> -#include <stdarg.h> -#include <inttypes.h> #include <fcntl.h> -#include <termios.h> #include "cmdline_parse.h" -#include "cmdline_rdline.h" #include "cmdline_socket.h" #include "cmdline.h" struct cmdline * cmdline_file_new(cmdline_parse_ctx_t *ctx, const char *prompt, const char *path) { + struct cmdline *cl; int fd; /* everything else is checked in cmdline_new() */ @@ -29,37 +24,22 @@ cmdline_file_new(cmdline_parse_ctx_t *ctx, const char *prompt, const char *path) fd = open(path, O_RDONLY, 0); if (fd < 0) { - dprintf("open() failed\n"); return NULL; } - return cmdline_new(ctx, prompt, fd, -1); + cl = cmdline_new(ctx, prompt, fd, -1); + /* cmdline_new() duplicates fd */ + close(fd); + return cl; } struct cmdline * cmdline_stdin_new(cmdline_parse_ctx_t *ctx, const char *prompt) { - struct cmdline *cl; - struct termios oldterm, term; - - tcgetattr(0, &oldterm); - memcpy(&term, &oldterm, sizeof(term)); - term.c_lflag &= ~(ICANON | ECHO | ISIG); - tcsetattr(0, TCSANOW, &term); - setbuf(stdin, NULL); - - cl = cmdline_new(ctx, prompt, 0, 1); - - if (cl) - memcpy(&cl->oldterm, &oldterm, sizeof(term)); - - return cl; + return cmdline_new(ctx, prompt, 0, 1); } void cmdline_stdin_exit(struct cmdline *cl) { - if (!cl) - return; - - tcsetattr(fileno(stdin), TCSANOW, &cl->oldterm); + cmdline_free(cl); } diff --git a/lib/librte_cmdline/cmdline_vt100.c b/lib/librte_cmdline/cmdline_vt100.c deleted file mode 100644 index 662fc7345..000000000 --- a/lib/librte_cmdline/cmdline_vt100.c +++ /dev/null @@ -1,132 +0,0 @@ -/* SPDX-License-Identifier: BSD-3-Clause - * Copyright(c) 2010-2014 Intel Corporation. - * Copyright (c) 2009, Olivier MATZ <zer0@droids-corp.org> - * All rights reserved. - */ - -#include <stdlib.h> -#include <stdint.h> -#include <stdio.h> -#include <string.h> -#include <stdarg.h> -#include <ctype.h> -#include <termios.h> - -#include "cmdline_vt100.h" - -const char *cmdline_vt100_commands[] = { - vt100_up_arr, - vt100_down_arr, - vt100_right_arr, - vt100_left_arr, - "\177", - "\n", - "\001", - "\005", - "\013", - "\031", - "\003", - "\006", - "\002", - vt100_suppr, - vt100_tab, - "\004", - "\014", - "\r", - "\033\177", - vt100_word_left, - vt100_word_right, - "?", - "\027", - "\020", - "\016", - "\033\144", - vt100_bs, -}; - -void -vt100_init(struct cmdline_vt100 *vt) -{ - if (!vt) - return; - vt->state = CMDLINE_VT100_INIT; -} - - -static int -match_command(char *buf, unsigned int size) -{ - const char *cmd; - size_t cmdlen; - unsigned int i = 0; - - for (i=0 ; i<sizeof(cmdline_vt100_commands)/sizeof(const char *) ; i++) { - cmd = *(cmdline_vt100_commands + i); - - cmdlen = strnlen(cmd, CMDLINE_VT100_BUF_SIZE); - if (size == cmdlen && - !strncmp(buf, cmd, cmdlen)) { - return i; - } - } - - return -1; -} - -int -vt100_parser(struct cmdline_vt100 *vt, char ch) -{ - unsigned int size; - uint8_t c = (uint8_t) ch; - - if (!vt) - return -1; - - if (vt->bufpos >= CMDLINE_VT100_BUF_SIZE) { - vt->state = CMDLINE_VT100_INIT; - vt->bufpos = 0; - } - - vt->buf[vt->bufpos++] = c; - size = vt->bufpos; - - switch (vt->state) { - case CMDLINE_VT100_INIT: - if (c == 033) { - vt->state = CMDLINE_VT100_ESCAPE; - } - else { - vt->bufpos = 0; - goto match_command; - } - break; - - case CMDLINE_VT100_ESCAPE: - if (c == 0133) { - vt->state = CMDLINE_VT100_ESCAPE_CSI; - } - else if (c >= 060 && c <= 0177) { /* XXX 0177 ? */ - vt->bufpos = 0; - vt->state = CMDLINE_VT100_INIT; - goto match_command; - } - break; - - case CMDLINE_VT100_ESCAPE_CSI: - if (c >= 0100 && c <= 0176) { - vt->bufpos = 0; - vt->state = CMDLINE_VT100_INIT; - goto match_command; - } - break; - - default: - vt->bufpos = 0; - break; - } - - return -2; - - match_command: - return match_command(vt->buf, size); -} diff --git a/lib/librte_cmdline/cmdline_vt100.h b/lib/librte_cmdline/cmdline_vt100.h deleted file mode 100644 index e33e67ed8..000000000 --- a/lib/librte_cmdline/cmdline_vt100.h +++ /dev/null @@ -1,100 +0,0 @@ -/* SPDX-License-Identifier: BSD-3-Clause - * Copyright(c) 2010-2014 Intel Corporation. - * Copyright (c) 2009, Olivier MATZ <zer0@droids-corp.org> - * All rights reserved. - */ - -#ifndef _CMDLINE_VT100_H_ -#define _CMDLINE_VT100_H_ - -#include <stdint.h> - -#ifdef __cplusplus -extern "C" { -#endif - -#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" - -/* Result of parsing : it must be synchronized with - * cmdline_vt100_commands[] in vt100.c */ -#define CMDLINE_KEY_UP_ARR 0 -#define CMDLINE_KEY_DOWN_ARR 1 -#define CMDLINE_KEY_RIGHT_ARR 2 -#define CMDLINE_KEY_LEFT_ARR 3 -#define CMDLINE_KEY_BKSPACE 4 -#define CMDLINE_KEY_RETURN 5 -#define CMDLINE_KEY_CTRL_A 6 -#define CMDLINE_KEY_CTRL_E 7 -#define CMDLINE_KEY_CTRL_K 8 -#define CMDLINE_KEY_CTRL_Y 9 -#define CMDLINE_KEY_CTRL_C 10 -#define CMDLINE_KEY_CTRL_F 11 -#define CMDLINE_KEY_CTRL_B 12 -#define CMDLINE_KEY_SUPPR 13 -#define CMDLINE_KEY_TAB 14 -#define CMDLINE_KEY_CTRL_D 15 -#define CMDLINE_KEY_CTRL_L 16 -#define CMDLINE_KEY_RETURN2 17 -#define CMDLINE_KEY_META_BKSPACE 18 -#define CMDLINE_KEY_WLEFT 19 -#define CMDLINE_KEY_WRIGHT 20 -#define CMDLINE_KEY_HELP 21 -#define CMDLINE_KEY_CTRL_W 22 -#define CMDLINE_KEY_CTRL_P 23 -#define CMDLINE_KEY_CTRL_N 24 -#define CMDLINE_KEY_META_D 25 -#define CMDLINE_KEY_BKSPACE2 26 - -extern const char *cmdline_vt100_commands[]; - -enum cmdline_vt100_parser_state { - CMDLINE_VT100_INIT, - CMDLINE_VT100_ESCAPE, - CMDLINE_VT100_ESCAPE_CSI -}; - -#define CMDLINE_VT100_BUF_SIZE 8 -struct cmdline_vt100 { - uint8_t bufpos; - char buf[CMDLINE_VT100_BUF_SIZE]; - enum cmdline_vt100_parser_state state; -}; - -/** - * Init - */ -void vt100_init(struct cmdline_vt100 *vt); - -/** - * Input a new character. - * Return -1 if the character is not part of a control sequence - * Return -2 if c is not the last char of a control sequence - * Else return the index in vt100_commands[] - */ -int vt100_parser(struct cmdline_vt100 *vt, char c); - -#ifdef __cplusplus -} -#endif - -#endif diff --git a/lib/librte_cmdline/meson.build b/lib/librte_cmdline/meson.build index 5741817ac..1735737c7 100644 --- a/lib/librte_cmdline/meson.build +++ b/lib/librte_cmdline/meson.build @@ -1,18 +1,15 @@ # SPDX-License-Identifier: BSD-3-Clause # Copyright(c) 2017 Intel Corporation -version = 2 +version = 3 sources = files('cmdline.c', - 'cmdline_cirbuf.c', 'cmdline_parse.c', 'cmdline_parse_etheraddr.c', 'cmdline_parse_ipaddr.c', 'cmdline_parse_num.c', 'cmdline_parse_portlist.c', 'cmdline_parse_string.c', - 'cmdline_rdline.c', - 'cmdline_socket.c', - 'cmdline_vt100.c') + 'cmdline_socket.c') headers = files('cmdline.h', 'cmdline_parse.h', @@ -20,8 +17,13 @@ headers = files('cmdline.h', 'cmdline_parse_ipaddr.h', 'cmdline_parse_etheraddr.h', 'cmdline_parse_string.h', - 'cmdline_rdline.h', - 'cmdline_vt100.h', 'cmdline_socket.h', - 'cmdline_cirbuf.h', 'cmdline_parse_portlist.h') + +cmdline_dep = dependency('libedit', required: false) +if cmdline_dep.found() + ext_deps += cmdline_dep + dpdk_extra_ldflags += '-ledit' +else + build = false +endif diff --git a/lib/librte_cmdline/rte_cmdline_version.map b/lib/librte_cmdline/rte_cmdline_version.map index 04bcb387f..31331995b 100644 --- a/lib/librte_cmdline/rte_cmdline_version.map +++ b/lib/librte_cmdline/rte_cmdline_version.map @@ -1,25 +1,6 @@ DPDK_2.0 { global: - cirbuf_add_buf_head; - cirbuf_add_buf_tail; - cirbuf_add_head; - cirbuf_add_head_safe; - cirbuf_add_tail; - cirbuf_add_tail_safe; - cirbuf_align_left; - cirbuf_align_right; - cirbuf_del_buf_head; - cirbuf_del_buf_tail; - cirbuf_del_head; - cirbuf_del_head_safe; - cirbuf_del_tail; - cirbuf_del_tail_safe; - cirbuf_get_buf_head; - cirbuf_get_buf_tail; - cirbuf_get_head; - cirbuf_get_tail; - cirbuf_init; cmdline_complete; cmdline_complete_get_elt_string; cmdline_complete_get_nb_string; @@ -50,21 +31,6 @@ DPDK_2.0 { cmdline_token_num_ops; cmdline_token_portlist_ops; cmdline_token_string_ops; - cmdline_write_char; - rdline_add_history; - rdline_char_in; - rdline_clear_history; - rdline_get_buffer; - rdline_get_history_item; - rdline_init; - rdline_newline; - rdline_quit; - rdline_redisplay; - rdline_reset; - rdline_restart; - rdline_stop; - vt100_init; - vt100_parser; local: *; }; @@ -75,3 +41,10 @@ DPDK_2.1 { cmdline_poll; } DPDK_2.0; + +DPDK_18.02 { + global: + + cmdline_ctx_get; + +} DPDK_2.1; diff --git a/mk/rte.app.mk b/mk/rte.app.mk index 8bab901fc..f66411eba 100644 --- a/mk/rte.app.mk +++ b/mk/rte.app.mk @@ -104,6 +104,8 @@ _LDLIBS-$(CONFIG_RTE_LIBRTE_RING) += -lrte_ring _LDLIBS-$(CONFIG_RTE_LIBRTE_PCI) += -lrte_pci _LDLIBS-$(CONFIG_RTE_LIBRTE_EAL) += -lrte_eal _LDLIBS-$(CONFIG_RTE_LIBRTE_CMDLINE) += -lrte_cmdline + +_LDLIBS-$(CONFIG_RTE_LIBRTE_CMDLINE) += $(shell pkg-config --libs libedit) _LDLIBS-$(CONFIG_RTE_LIBRTE_REORDER) += -lrte_reorder _LDLIBS-$(CONFIG_RTE_LIBRTE_SCHED) += -lrte_sched diff --git a/test/cmdline_test/cmdline_test.c b/test/cmdline_test/cmdline_test.c index 3e406331a..e46b66d0c 100644 --- a/test/cmdline_test/cmdline_test.c +++ b/test/cmdline_test/cmdline_test.c @@ -12,7 +12,6 @@ #include <ctype.h> #include <sys/queue.h> -#include <cmdline_rdline.h> #include <cmdline_parse.h> #include <cmdline_socket.h> #include <cmdline.h> diff --git a/test/cmdline_test/commands.c b/test/cmdline_test/commands.c index d81da9665..2bf0262f6 100644 --- a/test/cmdline_test/commands.c +++ b/test/cmdline_test/commands.c @@ -7,7 +7,6 @@ #include <termios.h> #include <inttypes.h> -#include <cmdline_rdline.h> #include <cmdline_parse.h> #include <cmdline_parse_string.h> #include <cmdline_parse_num.h> @@ -277,72 +276,6 @@ cmdline_parse_inst_t cmd_ambig_2 = { -/*** get_history_bufsize ***/ -/* command that displays total space in history buffer - * this will be useful for testing history (to fill it up just enough to - * remove the last entry, we need to know how big it is). - */ - -struct cmd_get_history_bufsize_result { - cmdline_fixed_string_t str; -}; - -static void -cmd_get_history_bufsize_parsed(__attribute__((unused)) void *parsed_result, - struct cmdline *cl, - __attribute__((unused)) void *data) -{ - cmdline_printf(cl, "History buffer size: %zu\n", - sizeof(cl->rdl.history_buf)); -} - -cmdline_parse_token_string_t cmd_get_history_bufsize_tok = - TOKEN_STRING_INITIALIZER(struct cmd_get_history_bufsize_result, str, - "get_history_bufsize"); - -cmdline_parse_inst_t cmd_get_history_bufsize = { - .f = cmd_get_history_bufsize_parsed, /* function to call */ - .data = NULL, /* 2nd arg of func */ - .help_str = "command that displays total space in history buffer", - .tokens = { /* token list, NULL terminated */ - (void *)&cmd_get_history_bufsize_tok, - NULL, - }, -}; - - - -/*** clear_history ***/ -/* clears history buffer */ - -struct cmd_clear_history_result { - cmdline_fixed_string_t str; -}; - -static void -cmd_clear_history_parsed(__attribute__((unused)) void *parsed_result, - struct cmdline *cl, - __attribute__((unused)) void *data) -{ - rdline_clear_history(&cl->rdl); -} - -cmdline_parse_token_string_t cmd_clear_history_tok = - TOKEN_STRING_INITIALIZER(struct cmd_clear_history_result, str, - "clear_history"); - -cmdline_parse_inst_t cmd_clear_history = { - .f = cmd_clear_history_parsed, /* function to call */ - .data = NULL, /* 2nd arg of func */ - .help_str = "clear command history", - .tokens = { /* token list, NULL terminated */ - (void *)&cmd_clear_history_tok, - NULL, - }, -}; - - - /****************/ cmdline_parse_ctx_t main_ctx[] = { @@ -352,8 +285,6 @@ cmdline_parse_ctx_t main_ctx[] = { (cmdline_parse_inst_t *)&cmd_single, (cmdline_parse_inst_t *)&cmd_single_long, (cmdline_parse_inst_t *)&cmd_num, - (cmdline_parse_inst_t *)&cmd_get_history_bufsize, - (cmdline_parse_inst_t *)&cmd_clear_history, (cmdline_parse_inst_t *)&cmd_autocomplete_1, (cmdline_parse_inst_t *)&cmd_autocomplete_2, NULL, diff --git a/test/test/Makefile b/test/test/Makefile index c9c007c9b..08cc04277 100644 --- a/test/test/Makefile +++ b/test/test/Makefile @@ -139,7 +139,6 @@ SRCS-$(CONFIG_RTE_LIBRTE_CMDLINE) += test_cmdline_num.c SRCS-$(CONFIG_RTE_LIBRTE_CMDLINE) += test_cmdline_etheraddr.c SRCS-$(CONFIG_RTE_LIBRTE_CMDLINE) += test_cmdline_portlist.c SRCS-$(CONFIG_RTE_LIBRTE_CMDLINE) += test_cmdline_ipaddr.c -SRCS-$(CONFIG_RTE_LIBRTE_CMDLINE) += test_cmdline_cirbuf.c SRCS-$(CONFIG_RTE_LIBRTE_CMDLINE) += test_cmdline_string.c SRCS-$(CONFIG_RTE_LIBRTE_CMDLINE) += test_cmdline_lib.c diff --git a/test/test/commands.c b/test/test/commands.c index 6bfdc0272..7e5357b93 100644 --- a/test/test/commands.c +++ b/test/test/commands.c @@ -38,7 +38,6 @@ #include <rte_mbuf.h> #include <rte_devargs.h> -#include <cmdline_rdline.h> #include <cmdline_parse.h> #include <cmdline_parse_ipaddr.h> #include <cmdline_parse_num.h> diff --git a/test/test/meson.build b/test/test/meson.build index eb3d87a4d..d5bfdccf3 100644 --- a/test/test/meson.build +++ b/test/test/meson.build @@ -10,7 +10,6 @@ test_sources = files('commands.c', 'test_barrier.c', 'test_byteorder.c', 'test_cmdline.c', - 'test_cmdline_cirbuf.c', 'test_cmdline_etheraddr.c', 'test_cmdline_ipaddr.c', 'test_cmdline_lib.c', diff --git a/test/test/test.c b/test/test/test.c index 44dfe20ef..802e8079b 100644 --- a/test/test/test.c +++ b/test/test/test.c @@ -13,7 +13,6 @@ #include <sys/queue.h> #ifdef RTE_LIBRTE_CMDLINE -#include <cmdline_rdline.h> #include <cmdline_parse.h> #include <cmdline_socket.h> #include <cmdline.h> diff --git a/test/test/test_cmdline.c b/test/test/test_cmdline.c index 115bee966..eef219a93 100644 --- a/test/test/test_cmdline.c +++ b/test/test/test_cmdline.c @@ -45,15 +45,6 @@ test_cmdline(void) return -1; if (test_parse_string_invalid_param() < 0) return -1; - printf("Testing circular buffer...\n"); - if (test_cirbuf_char() < 0) - return -1; - if (test_cirbuf_string() < 0) - return -1; - if (test_cirbuf_align() < 0) - return -1; - if (test_cirbuf_invalid_param() < 0) - return -1; printf("Testing library functions...\n"); if (test_cmdline_lib() < 0) return -1; diff --git a/test/test/test_cmdline.h b/test/test/test_cmdline.h index 1854caf8f..2fb45b3d4 100644 --- a/test/test/test_cmdline.h +++ b/test/test/test_cmdline.h @@ -32,12 +32,6 @@ int test_parse_string_valid(void); int test_parse_string_invalid_data(void); int test_parse_string_invalid_param(void); -/* cmdline_cirbuf tests */ -int test_cirbuf_invalid_param(void); -int test_cirbuf_char(void); -int test_cirbuf_string(void); -int test_cirbuf_align(void); - /* test the rest of the library */ int test_cmdline_lib(void); diff --git a/test/test/test_cmdline_cirbuf.c b/test/test/test_cmdline_cirbuf.c deleted file mode 100644 index 8ac326cb0..000000000 --- a/test/test/test_cmdline_cirbuf.c +++ /dev/null @@ -1,1301 +0,0 @@ -/* SPDX-License-Identifier: BSD-3-Clause - * Copyright(c) 2010-2014 Intel Corporation - */ - -#include <stdio.h> -#include <stdlib.h> -#include <string.h> - -#include <rte_string_fns.h> - -#include <cmdline_cirbuf.h> - -#include "test_cmdline.h" - -/* different length strings */ -#define CIRBUF_STR_HEAD " HEAD" -#define CIRBUF_STR_TAIL "TAIL" - -/* miscellaneous tests - they make bullseye happy */ -static int -test_cirbuf_string_misc(void) -{ - struct cirbuf cb; - char buf[CMDLINE_TEST_BUFSIZE]; - char tmp[CMDLINE_TEST_BUFSIZE]; - - /* initialize buffers */ - memset(buf, 0, sizeof(buf)); - memset(tmp, 0, sizeof(tmp)); - - /* - * initialize circular buffer - */ - if (cirbuf_init(&cb, buf, 0, sizeof(buf)) < 0) { - printf("Error: failed to initialize circular buffer!\n"); - return -1; - } - - /* - * add strings to head and tail, but read only tail - * this results in read operation that does not transcend - * from buffer end to buffer beginning (in other words, - * strlen <= cb->maxlen - cb->end) - */ - - /* add string to head */ - if (cirbuf_add_buf_head(&cb, CIRBUF_STR_HEAD, sizeof(CIRBUF_STR_HEAD)) - != (sizeof(CIRBUF_STR_HEAD))) { - printf("Error: failed to add string to head!\n"); - return -1; - } - /* add string to tail */ - if (cirbuf_add_buf_tail(&cb, CIRBUF_STR_TAIL, sizeof(CIRBUF_STR_TAIL)) - != (sizeof(CIRBUF_STR_TAIL))) { - printf("Error: failed to add string to head!\n"); - return -1; - } - /* read string from tail */ - if (cirbuf_get_buf_tail(&cb, tmp, sizeof(CIRBUF_STR_TAIL)) - != (sizeof(CIRBUF_STR_TAIL))) { - printf("Error: failed to get string from tail!\n"); - return -1; - } - /* verify string */ - if (strncmp(tmp, CIRBUF_STR_TAIL, sizeof(CIRBUF_STR_TAIL)) != 0) { - printf("Error: tail strings do not match!\n"); - return -1; - } - /* clear buffers */ - memset(tmp, 0, sizeof(tmp)); - memset(buf, 0, sizeof(buf)); - - - - /* - * add a string to buffer when start/end is at end of buffer - */ - - /* - * reinitialize circular buffer with start at the end of cirbuf - */ - if (cirbuf_init(&cb, buf, CMDLINE_TEST_BUFSIZE - 2, sizeof(buf)) < 0) { - printf("Error: failed to reinitialize circular buffer!\n"); - return -1; - } - - - /* add string to tail */ - if (cirbuf_add_buf_tail(&cb, CIRBUF_STR_TAIL, sizeof(CIRBUF_STR_TAIL)) - != (sizeof(CIRBUF_STR_TAIL))) { - printf("Error: failed to add string to tail!\n"); - return -1; - } - /* read string from tail */ - if (cirbuf_get_buf_tail(&cb, tmp, sizeof(CIRBUF_STR_TAIL)) - != (sizeof(CIRBUF_STR_TAIL))) { - printf("Error: failed to get string from tail!\n"); - return -1; - } - /* verify string */ - if (strncmp(tmp, CIRBUF_STR_TAIL, sizeof(CIRBUF_STR_TAIL)) != 0) { - printf("Error: tail strings do not match!\n"); - return -1; - } - /* clear tmp buffer */ - memset(tmp, 0, sizeof(tmp)); - - - /* add string to head */ - if (cirbuf_add_buf_head(&cb, CIRBUF_STR_HEAD, sizeof(CIRBUF_STR_HEAD)) - != (sizeof(CIRBUF_STR_HEAD))) { - printf("Error: failed to add string to head!\n"); - return -1; - } - /* read string from tail */ - if (cirbuf_get_buf_head(&cb, tmp, sizeof(CIRBUF_STR_HEAD)) - != (sizeof(CIRBUF_STR_HEAD))) { - printf("Error: failed to get string from head!\n"); - return -1; - } - /* verify string */ - if (strncmp(tmp, CIRBUF_STR_HEAD, sizeof(CIRBUF_STR_HEAD)) != 0) { - printf("Error: headstrings do not match!\n"); - return -1; - } - - return 0; -} - -/* test adding and deleting strings */ -static int -test_cirbuf_string_add_del(void) -{ - struct cirbuf cb; - char buf[CMDLINE_TEST_BUFSIZE]; - char tmp[CMDLINE_TEST_BUFSIZE]; - - /* initialize buffers */ - memset(buf, 0, sizeof(buf)); - memset(tmp, 0, sizeof(tmp)); - - /* - * initialize circular buffer - */ - if (cirbuf_init(&cb, buf, 0, sizeof(buf)) < 0) { - printf("Error: failed to initialize circular buffer!\n"); - return -1; - } - - /* add string to head */ - if (cirbuf_add_buf_head(&cb, CIRBUF_STR_HEAD, sizeof(CIRBUF_STR_HEAD)) - != (sizeof(CIRBUF_STR_HEAD))) { - printf("Error: failed to add string to head!\n"); - return -1; - } - /* read string from head */ - if (cirbuf_get_buf_head(&cb, tmp, sizeof(CIRBUF_STR_HEAD)) - != (sizeof(CIRBUF_STR_HEAD))) { - printf("Error: failed to get string from head!\n"); - return -1; - } - /* verify string */ - if (strncmp(tmp, CIRBUF_STR_HEAD, sizeof(CIRBUF_STR_HEAD)) != 0) { - printf("Error: head strings do not match!\n"); - return -1; - } - /* clear tmp buffer */ - memset(tmp, 0, sizeof(tmp)); - /* read string from tail */ - if (cirbuf_get_buf_tail(&cb, tmp, sizeof(CIRBUF_STR_HEAD)) - != (sizeof(CIRBUF_STR_HEAD))) { - printf("Error: failed to get string from head!\n"); - return -1; - } - /* verify string */ - if (strncmp(tmp, CIRBUF_STR_HEAD, sizeof(CIRBUF_STR_HEAD)) != 0) { - printf("Error: head strings do not match!\n"); - return -1; - } - /* delete string from head*/ - if (cirbuf_del_buf_head(&cb, sizeof(CIRBUF_STR_HEAD)) < 0) { - printf("Error: failed to delete string from head!\n"); - return -1; - } - /* verify string was deleted */ - if (cirbuf_del_head_safe(&cb) == 0) { - printf("Error: buffer should have been empty!\n"); - return -1; - } - /* clear tmp buffer */ - memset(tmp, 0, sizeof(tmp)); - - - - /* - * reinitialize circular buffer - */ - memset(buf, 0, sizeof(buf)); - if (cirbuf_init(&cb, buf, 0, sizeof(buf)) < 0) { - printf("Error: failed to reinitialize circular buffer!\n"); - return -1; - } - - /* add string to tail */ - if (cirbuf_add_buf_tail(&cb, CIRBUF_STR_TAIL, sizeof(CIRBUF_STR_TAIL)) - != (sizeof(CIRBUF_STR_TAIL))) { - printf("Error: failed to add string to tail!\n"); - return -1; - } - /* get string from tail */ - if (cirbuf_get_buf_tail(&cb, tmp, sizeof(CIRBUF_STR_TAIL)) - != (sizeof(CIRBUF_STR_TAIL))) { - printf("Error: failed to get string from tail!\n"); - return -1; - } - /* verify string */ - if (strncmp(tmp, CIRBUF_STR_TAIL, sizeof(CIRBUF_STR_TAIL)) != 0) { - printf("Error: tail strings do not match!\n"); - return -1; - } - /* clear tmp buffer */ - memset(tmp, 0, sizeof(tmp)); - /* get string from head */ - if (cirbuf_get_buf_head(&cb, tmp, sizeof(CIRBUF_STR_TAIL)) - != (sizeof(CIRBUF_STR_TAIL))) { - printf("Error: failed to get string from tail!\n"); - return -1; - } - /* verify string */ - if (strncmp(tmp, CIRBUF_STR_TAIL, sizeof(CIRBUF_STR_TAIL)) != 0) { - printf("Error: tail strings do not match!\n"); - return -1; - } - /* delete string from tail */ - if (cirbuf_del_buf_tail(&cb, sizeof(CIRBUF_STR_TAIL)) < 0) { - printf("Error: failed to delete string from tail!\n"); - return -1; - } - /* verify string was deleted */ - if (cirbuf_del_tail_safe(&cb) == 0) { - printf("Error: buffer should have been empty!\n"); - return -1; - } - - return 0; -} - -/* test adding from head and deleting from tail, and vice versa */ -static int -test_cirbuf_string_add_del_reverse(void) -{ - struct cirbuf cb; - char buf[CMDLINE_TEST_BUFSIZE]; - char tmp[CMDLINE_TEST_BUFSIZE]; - - /* initialize buffers */ - memset(buf, 0, sizeof(buf)); - memset(tmp, 0, sizeof(tmp)); - - /* - * initialize circular buffer - */ - if (cirbuf_init(&cb, buf, 0, sizeof(buf)) < 0) { - printf("Error: failed to initialize circular buffer!\n"); - return -1; - } - - /* add string to head */ - if (cirbuf_add_buf_head(&cb, CIRBUF_STR_HEAD, sizeof(CIRBUF_STR_HEAD)) - != (sizeof(CIRBUF_STR_HEAD))) { - printf("Error: failed to add string to head!\n"); - return -1; - } - /* delete string from tail */ - if (cirbuf_del_buf_tail(&cb, sizeof(CIRBUF_STR_HEAD)) < 0) { - printf("Error: failed to delete string from tail!\n"); - return -1; - } - /* verify string was deleted */ - if (cirbuf_del_tail_safe(&cb) == 0) { - printf("Error: buffer should have been empty!\n"); - return -1; - } - /* clear tmp buffer */ - memset(tmp, 0, sizeof(tmp)); - - /* - * reinitialize circular buffer - */ - memset(buf, 0, sizeof(buf)); - if (cirbuf_init(&cb, buf, 0, sizeof(buf)) < 0) { - printf("Error: failed to reinitialize circular buffer!\n"); - return -1; - } - - /* add string to tail */ - if (cirbuf_add_buf_tail(&cb, CIRBUF_STR_TAIL, sizeof(CIRBUF_STR_TAIL)) - != (sizeof(CIRBUF_STR_TAIL))) { - printf("Error: failed to add string to tail!\n"); - return -1; - } - /* delete string from head */ - if (cirbuf_del_buf_head(&cb, sizeof(CIRBUF_STR_TAIL)) < 0) { - printf("Error: failed to delete string from head!\n"); - return -1; - } - /* verify string was deleted */ - if (cirbuf_del_head_safe(&cb) == 0) { - printf("Error: buffer should have been empty!\n"); - return -1; - } - - return 0; -} - -/* try to write more than available */ -static int -test_cirbuf_string_add_boundaries(void) -{ - struct cirbuf cb; - char buf[CMDLINE_TEST_BUFSIZE]; - unsigned i; - - /* initialize buffers */ - memset(buf, 0, sizeof(buf)); - - /* - * initialize circular buffer - */ - if (cirbuf_init(&cb, buf, 0, sizeof(buf)) < 0) { - printf("Error: failed to initialize circular buffer!\n"); - return -1; - } - - /* fill the buffer from tail */ - for (i = 0; i < CMDLINE_TEST_BUFSIZE - sizeof(CIRBUF_STR_TAIL) + 1; i++) - cirbuf_add_tail_safe(&cb, 't'); - - /* try adding a string to tail */ - if (cirbuf_add_buf_tail(&cb, CIRBUF_STR_TAIL, sizeof(CIRBUF_STR_TAIL)) - > 0) { - printf("Error: buffer should have been full!\n"); - return -1; - } - /* try adding a string to head */ - if (cirbuf_add_buf_head(&cb, CIRBUF_STR_TAIL, sizeof(CIRBUF_STR_TAIL)) - > 0) { - printf("Error: buffer should have been full!\n"); - return -1; - } - - /* - * reinitialize circular buffer - */ - memset(buf, 0, sizeof(buf)); - if (cirbuf_init(&cb, buf, 0, sizeof(buf)) < 0) { - printf("Error: failed to reinitialize circular buffer!\n"); - return -1; - } - - /* fill the buffer from head */ - for (i = 0; i < CMDLINE_TEST_BUFSIZE - sizeof(CIRBUF_STR_HEAD) + 1; i++) - cirbuf_add_head_safe(&cb, 'h'); - - /* try adding a string to head */ - if (cirbuf_add_buf_head(&cb, CIRBUF_STR_HEAD, sizeof(CIRBUF_STR_HEAD)) - > 0) { - printf("Error: buffer should have been full!\n"); - return -1; - } - /* try adding a string to tail */ - if (cirbuf_add_buf_tail(&cb, CIRBUF_STR_HEAD, sizeof(CIRBUF_STR_HEAD)) - > 0) { - printf("Error: buffer should have been full!\n"); - return -1; - } - - return 0; -} - -/* try to read/delete more than written */ -static int -test_cirbuf_string_get_del_boundaries(void) -{ - struct cirbuf cb; - char buf[CMDLINE_TEST_BUFSIZE]; - char tmp[CMDLINE_TEST_BUFSIZE]; - - /* initialize buffers */ - memset(buf, 0, sizeof(buf)); - memset(tmp, 0, sizeof(tmp)); - - /* - * initialize circular buffer - */ - if (cirbuf_init(&cb, buf, 0, sizeof(buf)) < 0) { - printf("Error: failed to initialize circular buffer!\n"); - return -1; - } - - - /* add string to head */ - if (cirbuf_add_buf_head(&cb, CIRBUF_STR_HEAD, sizeof(CIRBUF_STR_HEAD)) - != (sizeof(CIRBUF_STR_HEAD))) { - printf("Error: failed to add string to head!\n"); - return -1; - } - /* read more than written (head) */ - if (cirbuf_get_buf_head(&cb, tmp, sizeof(CIRBUF_STR_HEAD) + 1) - != sizeof(CIRBUF_STR_HEAD)) { - printf("Error: unexpected result when reading too much data!\n"); - return -1; - } - /* read more than written (tail) */ - if (cirbuf_get_buf_tail(&cb, tmp, sizeof(CIRBUF_STR_HEAD) + 1) - != sizeof(CIRBUF_STR_HEAD)) { - printf("Error: unexpected result when reading too much data!\n"); - return -1; - } - /* delete more than written (head) */ - if (cirbuf_del_buf_head(&cb, sizeof(CIRBUF_STR_HEAD) + 1) == 0) { - printf("Error: unexpected result when deleting too much data!\n"); - return -1; - } - /* delete more than written (tail) */ - if (cirbuf_del_buf_tail(&cb, sizeof(CIRBUF_STR_HEAD) + 1) == 0) { - printf("Error: unexpected result when deleting too much data!\n"); - return -1; - } - - /* - * reinitialize circular buffer - */ - memset(buf, 0, sizeof(buf)); - if (cirbuf_init(&cb, buf, 0, sizeof(buf)) < 0) { - printf("Error: failed to reinitialize circular buffer!\n"); - return -1; - } - - /* add string to tail */ - if (cirbuf_add_buf_tail(&cb, CIRBUF_STR_TAIL, sizeof(CIRBUF_STR_TAIL)) - != (sizeof(CIRBUF_STR_TAIL))) { - printf("Error: failed to add string to tail!\n"); - return -1; - } - /* read more than written (tail) */ - if (cirbuf_get_buf_tail(&cb, tmp, sizeof(CIRBUF_STR_TAIL) + 1) - != sizeof(CIRBUF_STR_TAIL)) { - printf("Error: unexpected result when reading too much data!\n"); - return -1; - } - /* read more than written (head) */ - if (cirbuf_get_buf_head(&cb, tmp, sizeof(CIRBUF_STR_TAIL) + 1) - != sizeof(CIRBUF_STR_TAIL)) { - printf("Error: unexpected result when reading too much data!\n"); - return -1; - } - /* delete more than written (tail) */ - if (cirbuf_del_buf_tail(&cb, sizeof(CIRBUF_STR_TAIL) + 1) == 0) { - printf("Error: unexpected result when deleting too much data!\n"); - return -1; - } - /* delete more than written (head) */ - if (cirbuf_del_buf_tail(&cb, sizeof(CIRBUF_STR_TAIL) + 1) == 0) { - printf("Error: unexpected result when deleting too much data!\n"); - return -1; - } - - return 0; -} - -/* try to read/delete less than written */ -static int -test_cirbuf_string_get_del_partial(void) -{ - struct cirbuf cb; - char buf[CMDLINE_TEST_BUFSIZE]; - char tmp[CMDLINE_TEST_BUFSIZE]; - char tmp2[CMDLINE_TEST_BUFSIZE]; - - /* initialize buffers */ - memset(buf, 0, sizeof(buf)); - memset(tmp, 0, sizeof(tmp)); - memset(tmp2, 0, sizeof(tmp)); - - strlcpy(tmp2, CIRBUF_STR_HEAD, sizeof(tmp2)); - - /* - * initialize circular buffer - */ - if (cirbuf_init(&cb, buf, 0, sizeof(buf)) < 0) { - printf("Error: failed to initialize circular buffer!\n"); - return -1; - } - - /* add string to head */ - if (cirbuf_add_buf_head(&cb, CIRBUF_STR_HEAD, sizeof(CIRBUF_STR_HEAD)) - != (sizeof(CIRBUF_STR_HEAD))) { - printf("Error: failed to add string to head!\n"); - return -1; - } - /* read less than written (head) */ - if (cirbuf_get_buf_head(&cb, tmp, sizeof(CIRBUF_STR_HEAD) - 1) - != sizeof(CIRBUF_STR_HEAD) - 1) { - printf("Error: unexpected result when reading from head!\n"); - return -1; - } - /* verify string */ - if (strncmp(tmp, tmp2, sizeof(CIRBUF_STR_HEAD) - 1) != 0) { - printf("Error: strings mismatch!\n"); - return -1; - } - memset(tmp, 0, sizeof(tmp)); - /* read less than written (tail) */ - if (cirbuf_get_buf_tail(&cb, tmp, sizeof(CIRBUF_STR_HEAD) - 1) - != sizeof(CIRBUF_STR_HEAD) - 1) { - printf("Error: unexpected result when reading from tail!\n"); - return -1; - } - /* verify string */ - if (strncmp(tmp, &tmp2[1], sizeof(CIRBUF_STR_HEAD) - 1) != 0) { - printf("Error: strings mismatch!\n"); - return -1; - } - - /* - * verify correct deletion - */ - - /* clear buffer */ - memset(tmp, 0, sizeof(tmp)); - - /* delete less than written (head) */ - if (cirbuf_del_buf_head(&cb, 1) != 0) { - printf("Error: delete from head failed!\n"); - return -1; - } - /* read from head */ - if (cirbuf_get_buf_head(&cb, tmp, sizeof(CIRBUF_STR_HEAD) - 1) - != sizeof(CIRBUF_STR_HEAD) - 1) { - printf("Error: unexpected result when reading from head!\n"); - return -1; - } - /* since we deleted from head, first char should be deleted */ - if (strncmp(tmp, &tmp2[1], sizeof(CIRBUF_STR_HEAD) - 1) != 0) { - printf("Error: strings mismatch!\n"); - return -1; - } - /* clear buffer */ - memset(tmp, 0, sizeof(tmp)); - - /* delete less than written (tail) */ - if (cirbuf_del_buf_tail(&cb, 1) != 0) { - printf("Error: delete from tail failed!\n"); - return -1; - } - /* read from tail */ - if (cirbuf_get_buf_tail(&cb, tmp, sizeof(CIRBUF_STR_HEAD) - 2) - != sizeof(CIRBUF_STR_HEAD) - 2) { - printf("Error: unexpected result when reading from head!\n"); - return -1; - } - /* since we deleted from tail, last char should be deleted */ - if (strncmp(tmp, &tmp2[1], sizeof(CIRBUF_STR_HEAD) - 2) != 0) { - printf("Error: strings mismatch!\n"); - return -1; - } - - return 0; -} - -/* test cmdline_cirbuf char add/del functions */ -static int -test_cirbuf_char_add_del(void) -{ - struct cirbuf cb; - char buf[CMDLINE_TEST_BUFSIZE]; - char tmp[CMDLINE_TEST_BUFSIZE]; - - /* clear buffer */ - memset(buf, 0, sizeof(buf)); - memset(tmp, 0, sizeof(tmp)); - - /* - * initialize circular buffer - */ - if (cirbuf_init(&cb, buf, 0, sizeof(buf)) < 0) { - printf("Error: failed to initialize circular buffer!\n"); - return -1; - } - - /* - * try to delete something from cirbuf. since it's empty, - * these should fail. - */ - if (cirbuf_del_head_safe(&cb) == 0) { - printf("Error: deleting from empty cirbuf head succeeded!\n"); - return -1; - } - if (cirbuf_del_tail_safe(&cb) == 0) { - printf("Error: deleting from empty cirbuf tail succeeded!\n"); - return -1; - } - - /* - * add, verify and delete. these should pass. - */ - if (cirbuf_add_head_safe(&cb,'h') < 0) { - printf("Error: adding to cirbuf head failed!\n"); - return -1; - } - if (cirbuf_get_head(&cb) != 'h') { - printf("Error: wrong head content!\n"); - return -1; - } - if (cirbuf_del_head_safe(&cb) < 0) { - printf("Error: deleting from cirbuf head failed!\n"); - return -1; - } - if (cirbuf_add_tail_safe(&cb,'t') < 0) { - printf("Error: adding to cirbuf tail failed!\n"); - return -1; - } - if (cirbuf_get_tail(&cb) != 't') { - printf("Error: wrong tail content!\n"); - return -1; - } - if (cirbuf_del_tail_safe(&cb) < 0) { - printf("Error: deleting from cirbuf tail failed!\n"); - return -1; - } - /* do the same for unsafe versions. those are void. */ - cirbuf_add_head(&cb,'h'); - if (cirbuf_get_head(&cb) != 'h') { - printf("Error: wrong head content!\n"); - return -1; - } - cirbuf_del_head(&cb); - - /* test if char has been deleted. we can't call cirbuf_get_head - * because it's unsafe, but we can call cirbuf_get_buf_head. - */ - if (cirbuf_get_buf_head(&cb, tmp, 1) > 0) { - printf("Error: buffer should have been empty!\n"); - return -1; - } - - cirbuf_add_tail(&cb,'t'); - if (cirbuf_get_tail(&cb) != 't') { - printf("Error: wrong tail content!\n"); - return -1; - } - cirbuf_del_tail(&cb); - - /* test if char has been deleted. we can't call cirbuf_get_tail - * because it's unsafe, but we can call cirbuf_get_buf_tail. - */ - if (cirbuf_get_buf_tail(&cb, tmp, 1) > 0) { - printf("Error: buffer should have been empty!\n"); - return -1; - } - - return 0; -} - -/* test filling up buffer with chars */ -static int -test_cirbuf_char_fill(void) -{ - struct cirbuf cb; - char buf[CMDLINE_TEST_BUFSIZE]; - unsigned i; - - /* clear buffer */ - memset(buf, 0, sizeof(buf)); - - /* - * initialize circular buffer - */ - if (cirbuf_init(&cb, buf, 0, sizeof(buf)) < 0) { - printf("Error: failed to initialize circular buffer!\n"); - return -1; - } - - /* - * fill the buffer from head or tail, verify contents, test boundaries - * and clear the buffer - */ - - /* fill the buffer from tail */ - for (i = 0; i < CMDLINE_TEST_BUFSIZE; i++) - cirbuf_add_tail_safe(&cb, 't'); - /* verify that contents of the buffer are what they are supposed to be */ - for (i = 0; i < sizeof(buf); i++) { - if (buf[i] != 't') { - printf("Error: wrong content in buffer!\n"); - return -1; - } - } - /* try to add to a full buffer from tail */ - if (cirbuf_add_tail_safe(&cb, 't') == 0) { - printf("Error: buffer should have been full!\n"); - return -1; - } - /* try to add to a full buffer from head */ - if (cirbuf_add_head_safe(&cb, 'h') == 0) { - printf("Error: buffer should have been full!\n"); - return -1; - } - /* delete buffer from tail */ - for(i = 0; i < CMDLINE_TEST_BUFSIZE; i++) - cirbuf_del_tail_safe(&cb); - /* try to delete from an empty buffer */ - if (cirbuf_del_tail_safe(&cb) >= 0) { - printf("Error: buffer should have been empty!\n"); - return -1; - } - - /* fill the buffer from head */ - for (i = 0; i < CMDLINE_TEST_BUFSIZE; i++) - cirbuf_add_head_safe(&cb, 'h'); - /* verify that contents of the buffer are what they are supposed to be */ - for (i = 0; i < sizeof(buf); i++) { - if (buf[i] != 'h') { - printf("Error: wrong content in buffer!\n"); - return -1; - } - } - /* try to add to a full buffer from head */ - if (cirbuf_add_head_safe(&cb,'h') >= 0) { - printf("Error: buffer should have been full!\n"); - return -1; - } - /* try to add to a full buffer from tail */ - if (cirbuf_add_tail_safe(&cb, 't') == 0) { - printf("Error: buffer should have been full!\n"); - return -1; - } - /* delete buffer from head */ - for(i = 0; i < CMDLINE_TEST_BUFSIZE; i++) - cirbuf_del_head_safe(&cb); - /* try to delete from an empty buffer */ - if (cirbuf_del_head_safe(&cb) >= 0) { - printf("Error: buffer should have been empty!\n"); - return -1; - } - - /* - * fill the buffer from both head and tail, with alternating characters, - * verify contents and clear the buffer - */ - - /* fill half of buffer from tail */ - for (i = 0; i < CMDLINE_TEST_BUFSIZE / 2; i++) - cirbuf_add_tail_safe(&cb, (char) (i % 2 ? 't' : 'T')); - /* fill other half of the buffer from head */ - for (i = 0; i < CMDLINE_TEST_BUFSIZE / 2; i++) - cirbuf_add_head_safe(&cb, (char) (i % 2 ? 'H' : 'h')); /* added in reverse */ - - /* verify that contents of the buffer are what they are supposed to be */ - for (i = 0; i < sizeof(buf) / 2; i++) { - if (buf[i] != (char) (i % 2 ? 't' : 'T')) { - printf("Error: wrong content in buffer at %u!\n", i); - return -1; - } - } - for (i = sizeof(buf) / 2; i < sizeof(buf); i++) { - if (buf[i] != (char) (i % 2 ? 'h' : 'H')) { - printf("Error: wrong content in buffer %u!\n", i); - return -1; - } - } - - return 0; -} - -/* test left alignment */ -static int -test_cirbuf_align_left(void) -{ -#define HALF_OFFSET CMDLINE_TEST_BUFSIZE / 2 -#define SMALL_OFFSET HALF_OFFSET / 2 -/* resulting buffer lengths for each of the test cases */ -#define LEN1 HALF_OFFSET - SMALL_OFFSET - 1 -#define LEN2 HALF_OFFSET + SMALL_OFFSET + 2 -#define LEN3 HALF_OFFSET - SMALL_OFFSET -#define LEN4 HALF_OFFSET + SMALL_OFFSET - 1 - - struct cirbuf cb; - char buf[CMDLINE_TEST_BUFSIZE]; - char tmp[CMDLINE_TEST_BUFSIZE]; - unsigned i; - - /* - * align left when start < end and start in left half - */ - - /* - * initialize circular buffer - */ - memset(buf, 0, sizeof(buf)); - if (cirbuf_init(&cb, buf, 0, sizeof(buf)) < 0) { - printf("Error: failed to initialize circular buffer!\n"); - return -1; - } - - /* push end into left half */ - for (i = 0; i < HALF_OFFSET - 1; i++) - cirbuf_add_tail_safe(&cb, 't'); - - /* push start into left half < end */ - for (i = 0; i < SMALL_OFFSET; i++) - cirbuf_del_head_safe(&cb); - - /* align */ - if (cirbuf_align_left(&cb) < 0) { - printf("Error: alignment failed!\n"); - return -1; - } - - /* verify result */ - if (cb.start != 0 || cb.len != LEN1 || cb.end != cb.len - 1) { - printf("Error: buffer alignment is wrong!\n"); - return -1; - } - - /* - * align left when start > end and start in left half - */ - - /* - * reinitialize circular buffer - */ - memset(buf, 0, sizeof(buf)); - if (cirbuf_init(&cb, buf, 0, sizeof(buf)) < 0) { - printf("Error: failed to reinitialize circular buffer!\n"); - return -1; - } - - /* push start into left half */ - for (i = 0; i < HALF_OFFSET + 2; i++) - cirbuf_add_head_safe(&cb, 'h'); - - /* push end into left half > start */ - for (i = 0; i < SMALL_OFFSET; i++) - cirbuf_add_tail_safe(&cb, 't'); - - /* align */ - if (cirbuf_align_left(&cb) < 0) { - printf("Error: alignment failed!\n"); - return -1; - } - - /* verify result */ - if (cb.start != 0 || cb.len != LEN2 || cb.end != cb.len - 1) { - printf("Error: buffer alignment is wrong!"); - return -1; - } - - /* - * align left when start < end and start in right half - */ - - /* - * reinitialize circular buffer - */ - memset(buf, 0, sizeof(buf)); - if (cirbuf_init(&cb, buf, 0, sizeof(buf)) < 0) { - printf("Error: failed to reinitialize circular buffer!\n"); - return -1; - } - - /* push start into the right half */ - for (i = 0; i < HALF_OFFSET; i++) - cirbuf_add_head_safe(&cb, 'h'); - - /* push end into left half > start */ - for (i = 0; i < SMALL_OFFSET; i++) - cirbuf_del_tail_safe(&cb); - - /* align */ - if (cirbuf_align_left(&cb) < 0) { - printf("Error: alignment failed!\n"); - return -1; - } - - /* verify result */ - if (cb.start != 0 || cb.len != LEN3 || cb.end != cb.len - 1) { - printf("Error: buffer alignment is wrong!"); - return -1; - } - - /* - * align left when start > end and start in right half - */ - - /* - * reinitialize circular buffer - */ - memset(buf, 0, sizeof(buf)); - if (cirbuf_init(&cb, buf, 0, sizeof(buf)) < 0) { - printf("Error: failed to reinitialize circular buffer!\n"); - return -1; - } - - /* push start into the right half */ - for (i = 0; i < HALF_OFFSET - 1; i++) - cirbuf_add_head_safe(&cb, 'h'); - - /* push end into left half < start */ - for (i = 0; i < SMALL_OFFSET; i++) - cirbuf_add_tail_safe(&cb, 't'); - - /* align */ - if (cirbuf_align_left(&cb) < 0) { - printf("Error: alignment failed!\n"); - return -1; - } - - /* verify result */ - if (cb.start != 0 || cb.len != LEN4 || - cb.end != cb.len - 1) { - printf("Error: buffer alignment is wrong!"); - return -1; - } - - /* - * Verify that alignment doesn't corrupt data - */ - - /* - * reinitialize circular buffer - */ - memset(buf, 0, sizeof(buf)); - if (cirbuf_init(&cb, buf, 0, sizeof(buf)) < 0) { - printf("Error: failed to reinitialize circular buffer!\n"); - return -1; - } - - /* add string to tail and head */ - if (cirbuf_add_buf_head(&cb, CIRBUF_STR_HEAD, - sizeof(CIRBUF_STR_HEAD)) < 0 || cirbuf_add_buf_tail(&cb, - CIRBUF_STR_TAIL, sizeof(CIRBUF_STR_TAIL)) < 0) { - printf("Error: failed to add strings!\n"); - return -1; - } - - /* align */ - if (cirbuf_align_left(&cb) < 0) { - printf("Error: alignment failed!\n"); - return -1; - } - - /* get string from head */ - if (cirbuf_get_buf_head(&cb, tmp, - sizeof(CIRBUF_STR_HEAD) + sizeof(CIRBUF_STR_TAIL)) < 0) { - printf("Error: failed to read string from head!\n"); - return -1; - } - - /* verify string */ - if (strncmp(tmp, CIRBUF_STR_HEAD "\0" CIRBUF_STR_TAIL, - sizeof(CIRBUF_STR_HEAD) + sizeof(CIRBUF_STR_TAIL)) != 0) { - printf("Error: strings mismatch!\n"); - return -1; - } - - /* reset tmp buffer */ - memset(tmp, 0, sizeof(tmp)); - - /* get string from tail */ - if (cirbuf_get_buf_tail(&cb, tmp, - sizeof(CIRBUF_STR_HEAD) + sizeof(CIRBUF_STR_TAIL)) < 0) { - printf("Error: failed to read string from head!\n"); - return -1; - } - - /* verify string */ - if (strncmp(tmp, CIRBUF_STR_HEAD "\0" CIRBUF_STR_TAIL, - sizeof(CIRBUF_STR_HEAD) + sizeof(CIRBUF_STR_TAIL)) != 0) { - printf("Error: strings mismatch!\n"); - return -1; - } - - return 0; -} - -/* test right alignment */ -static int -test_cirbuf_align_right(void) -{ -#define END_OFFSET CMDLINE_TEST_BUFSIZE - 1 - struct cirbuf cb; - char buf[CMDLINE_TEST_BUFSIZE]; - char tmp[CMDLINE_TEST_BUFSIZE]; - unsigned i; - - - /* - * align right when start < end and start in left half - */ - - /* - * initialize circular buffer - */ - memset(buf, 0, sizeof(buf)); - if (cirbuf_init(&cb, buf, 0, sizeof(buf)) < 0) { - printf("Error: failed to initialize circular buffer!\n"); - return -1; - } - - /* push end into left half */ - for (i = 0; i < HALF_OFFSET - 1; i++) - cirbuf_add_tail_safe(&cb, 't'); - - /* push start into left half < end */ - for (i = 0; i < SMALL_OFFSET; i++) - cirbuf_del_head_safe(&cb); - - /* align */ - cirbuf_align_right(&cb); - - /* verify result */ - if (cb.start != END_OFFSET || cb.len != LEN1 || cb.end != cb.len - 2) { - printf("Error: buffer alignment is wrong!\n"); - return -1; - } - - /* - * align right when start > end and start in left half - */ - - /* - * reinitialize circular buffer - */ - memset(buf, 0, sizeof(buf)); - if (cirbuf_init(&cb, buf, 0, sizeof(buf)) < 0) { - printf("Error: failed to reinitialize circular buffer!\n"); - return -1; - } - - /* push start into left half */ - for (i = 0; i < HALF_OFFSET + 2; i++) - cirbuf_add_head_safe(&cb, 'h'); - - /* push end into left half > start */ - for (i = 0; i < SMALL_OFFSET; i++) - cirbuf_add_tail_safe(&cb, 't'); - - /* align */ - cirbuf_align_right(&cb); - - /* verify result */ - if (cb.start != END_OFFSET || cb.len != LEN2 || cb.end != cb.len - 2) { - printf("Error: buffer alignment is wrong!"); - return -1; - } - - /* - * align right when start < end and start in right half - */ - - /* - * reinitialize circular buffer - */ - memset(buf, 0, sizeof(buf)); - if (cirbuf_init(&cb, buf, 0, sizeof(buf)) < 0) { - printf("Error: failed to reinitialize circular buffer!\n"); - return -1; - } - - /* push start into the right half */ - for (i = 0; i < HALF_OFFSET; i++) - cirbuf_add_head_safe(&cb, 'h'); - - /* push end into left half > start */ - for (i = 0; i < SMALL_OFFSET; i++) - cirbuf_del_tail_safe(&cb); - - /* align */ - cirbuf_align_right(&cb); - - /* verify result */ - if (cb.end != END_OFFSET || cb.len != LEN3 || cb.start != cb.end - cb.len + 1) { - printf("Error: buffer alignment is wrong!"); - return -1; - } - - /* - * align right when start > end and start in right half - */ - - /* - * reinitialize circular buffer - */ - memset(buf, 0, sizeof(buf)); - if (cirbuf_init(&cb, buf, 0, sizeof(buf)) < 0) { - printf("Error: failed to reinitialize circular buffer!\n"); - return -1; - } - - /* push start into the right half */ - for (i = 0; i < HALF_OFFSET - 1; i++) - cirbuf_add_head_safe(&cb, 'h'); - - /* push end into left half < start */ - for (i = 0; i < SMALL_OFFSET; i++) - cirbuf_add_tail_safe(&cb, 't'); - - /* align */ - cirbuf_align_right(&cb); - - /* verify result */ - if (cb.end != END_OFFSET || cb.len != LEN4 || cb.start != cb.end - cb.len + 1) { - printf("Error: buffer alignment is wrong!"); - return -1; - } - - /* - * Verify that alignment doesn't corrupt data - */ - - /* - * reinitialize circular buffer - */ - memset(buf, 0, sizeof(buf)); - if (cirbuf_init(&cb, buf, 0, sizeof(buf)) < 0) { - printf("Error: failed to reinitialize circular buffer!\n"); - return -1; - } - - /* add string to tail and head */ - if (cirbuf_add_buf_tail(&cb, CIRBUF_STR_TAIL, - sizeof(CIRBUF_STR_TAIL)) < 0 || cirbuf_add_buf_head(&cb, - CIRBUF_STR_HEAD, sizeof(CIRBUF_STR_HEAD)) < 0) { - printf("Error: failed to add strings!\n"); - return -1; - } - - /* align */ - if (cirbuf_align_right(&cb) < 0) { - printf("Error: alignment failed!\n"); - return -1; - } - - /* get string from head */ - if (cirbuf_get_buf_head(&cb, tmp, - sizeof(CIRBUF_STR_HEAD) + sizeof(CIRBUF_STR_TAIL)) < 0) { - printf("Error: failed to read string from head!\n"); - return -1; - } - - /* verify string */ - if (strncmp(tmp, CIRBUF_STR_HEAD "\0" CIRBUF_STR_TAIL, - sizeof(CIRBUF_STR_HEAD) + sizeof(CIRBUF_STR_TAIL)) != 0) { - printf("Error: strings mismatch!\n"); - return -1; - } - - /* reset tmp buffer */ - memset(tmp, 0, sizeof(tmp)); - - /* get string from tail */ - if (cirbuf_get_buf_tail(&cb, tmp, - sizeof(CIRBUF_STR_HEAD) + sizeof(CIRBUF_STR_TAIL)) < 0) { - printf("Error: failed to read string from head!\n"); - return -1; - } - /* verify string */ - if (strncmp(tmp, CIRBUF_STR_HEAD "\0" CIRBUF_STR_TAIL, - sizeof(CIRBUF_STR_HEAD) + sizeof(CIRBUF_STR_TAIL)) != 0) { - printf("Error: strings mismatch!\n"); - return -1; - } - - return 0; -} - -/* call functions with invalid parameters */ -int -test_cirbuf_invalid_param(void) -{ - struct cirbuf cb; - char buf[CMDLINE_TEST_BUFSIZE]; - - /* null cirbuf */ - if (cirbuf_init(0, buf, 0, sizeof(buf)) == 0) - return -1; - /* null buffer */ - if (cirbuf_init(&cb, 0, 0, sizeof(buf)) == 0) - return -1; - /* null cirbuf */ - if (cirbuf_add_head_safe(0, 'h') == 0) - return -1; - if (cirbuf_add_tail_safe(0, 't') == 0) - return -1; - if (cirbuf_del_head_safe(0) == 0) - return -1; - if (cirbuf_del_tail_safe(0) == 0) - return -1; - /* null buffer */ - if (cirbuf_add_buf_head(&cb, 0, 0) == 0) - return -1; - if (cirbuf_add_buf_tail(&cb, 0, 0) == 0) - return -1; - /* null cirbuf */ - if (cirbuf_add_buf_head(0, buf, 0) == 0) - return -1; - if (cirbuf_add_buf_tail(0, buf, 0) == 0) - return -1; - /* null size */ - if (cirbuf_add_buf_head(&cb, buf, 0) == 0) - return -1; - if (cirbuf_add_buf_tail(&cb, buf, 0) == 0) - return -1; - /* null cirbuf */ - if (cirbuf_del_buf_head(0, 0) == 0) - return -1; - if (cirbuf_del_buf_tail(0, 0) == 0) - return -1; - /* null size */ - if (cirbuf_del_buf_head(&cb, 0) == 0) - return -1; - if (cirbuf_del_buf_tail(&cb, 0) == 0) - return -1; - /* null cirbuf */ - if (cirbuf_get_buf_head(0, 0, 0) == 0) - return -1; - if (cirbuf_get_buf_tail(0, 0, 0) == 0) - return -1; - /* null buffer */ - if (cirbuf_get_buf_head(&cb, 0, 0) == 0) - return -1; - if (cirbuf_get_buf_tail(&cb, 0, 0) == 0) - return -1; - /* null size, this is valid but should return 0 */ - if (cirbuf_get_buf_head(&cb, buf, 0) != 0) - return -1; - if (cirbuf_get_buf_tail(&cb, buf, 0) != 0) - return -1; - /* null cirbuf */ - if (cirbuf_align_left(0) == 0) - return -1; - if (cirbuf_align_right(0) == 0) - return -1; - - return 0; -} - -/* test cmdline_cirbuf char functions */ -int -test_cirbuf_char(void) -{ - int ret; - - ret = test_cirbuf_char_add_del(); - if (ret < 0) - return -1; - - ret = test_cirbuf_char_fill(); - if (ret < 0) - return -1; - - return 0; -} - -/* test cmdline_cirbuf string functions */ -int -test_cirbuf_string(void) -{ - if (test_cirbuf_string_add_del() < 0) - return -1; - - if (test_cirbuf_string_add_del_reverse() < 0) - return -1; - - if (test_cirbuf_string_add_boundaries() < 0) - return -1; - - if (test_cirbuf_string_get_del_boundaries() < 0) - return -1; - - if (test_cirbuf_string_get_del_partial() < 0) - return -1; - - if (test_cirbuf_string_misc() < 0) - return -1; - - return 0; -} - -/* test cmdline_cirbuf align functions */ -int -test_cirbuf_align(void) -{ - if (test_cirbuf_align_left() < 0) - return -1; - if (test_cirbuf_align_right() < 0) - return -1; - return 0; -} diff --git a/test/test/test_cmdline_lib.c b/test/test/test_cmdline_lib.c index a856a9713..2821d4bbf 100644 --- a/test/test/test_cmdline_lib.c +++ b/test/test/test_cmdline_lib.c @@ -12,8 +12,6 @@ #include <ctype.h> #include <sys/queue.h> -#include <cmdline_vt100.h> -#include <cmdline_rdline.h> #include <cmdline_parse.h> #include <cmdline_socket.h> #include <cmdline.h> @@ -21,113 +19,41 @@ #include "test_cmdline.h" /****************************************************************/ -/* static functions required for some tests */ -static void -valid_buffer(__attribute__((unused))struct rdline *rdl, - __attribute__((unused))const char *buf, - __attribute__((unused)) unsigned int size) -{ -} - -static int -complete_buffer(__attribute__((unused)) struct rdline *rdl, - __attribute__((unused)) const char *buf, - __attribute__((unused)) char *dstbuf, - __attribute__((unused)) unsigned int dstsize, - __attribute__((unused)) int *state) -{ - return 0; -} - -/****************************************************************/ static int test_cmdline_parse_fns(void) { - struct cmdline cl; + struct cmdline *cl; int i = 0; char dst[CMDLINE_TEST_BUFSIZE]; + cl = cmdline_new(NULL, "prompt", 0, 1); + if (!cl) + goto error; if (cmdline_parse(NULL, "buffer") >= 0) goto error; - if (cmdline_parse(&cl, NULL) >= 0) + if (cmdline_parse(cl, NULL) >= 0) goto error; if (cmdline_complete(NULL, "buffer", &i, dst, sizeof(dst)) >= 0) goto error; - if (cmdline_complete(&cl, NULL, &i, dst, sizeof(dst)) >= 0) + if (cmdline_complete(cl, NULL, &i, dst, sizeof(dst)) >= 0) goto error; - if (cmdline_complete(&cl, "buffer", NULL, dst, sizeof(dst)) >= 0) + if (cmdline_complete(cl, "buffer", NULL, dst, sizeof(dst)) >= 0) goto error; - if (cmdline_complete(&cl, "buffer", &i, NULL, sizeof(dst)) >= 0) + if (cmdline_complete(cl, "buffer", &i, NULL, sizeof(dst)) >= 0) goto error; return 0; error: + if (cl) + cmdline_free(cl); printf("Error: function accepted null parameter!\n"); return -1; } static int -test_cmdline_rdline_fns(void) -{ - struct rdline rdl; - rdline_write_char_t *wc = &cmdline_write_char; - rdline_validate_t *v = &valid_buffer; - rdline_complete_t *c = &complete_buffer; - - if (rdline_init(NULL, wc, v, c) >= 0) - goto error; - if (rdline_init(&rdl, NULL, v, c) >= 0) - goto error; - if (rdline_init(&rdl, wc, NULL, c) >= 0) - goto error; - if (rdline_init(&rdl, wc, v, NULL) >= 0) - goto error; - if (rdline_char_in(NULL, 0) >= 0) - goto error; - if (rdline_get_buffer(NULL) != NULL) - goto error; - if (rdline_add_history(NULL, "history") >= 0) - goto error; - if (rdline_add_history(&rdl, NULL) >= 0) - goto error; - if (rdline_get_history_item(NULL, 0) != NULL) - goto error; - - /* void functions */ - rdline_newline(NULL, "prompt"); - rdline_newline(&rdl, NULL); - rdline_stop(NULL); - rdline_quit(NULL); - rdline_restart(NULL); - rdline_redisplay(NULL); - rdline_reset(NULL); - rdline_clear_history(NULL); - - return 0; - -error: - printf("Error: function accepted null parameter!\n"); - return -1; -} - -static int -test_cmdline_vt100_fns(void) -{ - if (vt100_parser(NULL, 0) >= 0) { - printf("Error: function accepted null parameter!\n"); - return -1; - } - - /* void functions */ - vt100_init(NULL); - - return 0; -} - -static int test_cmdline_socket_fns(void) { cmdline_parse_ctx_t ctx; @@ -164,7 +90,7 @@ static int test_cmdline_fns(void) { cmdline_parse_ctx_t ctx; - struct cmdline cl, *tmp; + struct cmdline *tmp; memset(&ctx, 0, sizeof(ctx)); tmp = cmdline_new(&ctx, "test", -1, -1); @@ -177,10 +103,6 @@ test_cmdline_fns(void) goto error; if (cmdline_in(NULL, "buffer", CMDLINE_TEST_BUFSIZE) >= 0) goto error; - if (cmdline_in(&cl, NULL, CMDLINE_TEST_BUFSIZE) >= 0) - goto error; - if (cmdline_write_char(NULL, 0) >= 0) - goto error; /* void functions */ cmdline_set_prompt(NULL, "prompt"); @@ -191,16 +113,6 @@ test_cmdline_fns(void) cmdline_interact(NULL); cmdline_quit(NULL); - /* check if void calls change anything when they should fail */ - cl = *tmp; - - cmdline_printf(&cl, NULL); - if (memcmp(&cl, tmp, sizeof(cl))) goto mismatch; - cmdline_set_prompt(&cl, NULL); - if (memcmp(&cl, tmp, sizeof(cl))) goto mismatch; - cmdline_in(&cl, NULL, CMDLINE_TEST_BUFSIZE); - if (memcmp(&cl, tmp, sizeof(cl))) goto mismatch; - cmdline_free(tmp); return 0; @@ -208,9 +120,6 @@ test_cmdline_fns(void) error: printf("Error: function accepted null parameter!\n"); return -1; -mismatch: - printf("Error: data changed!\n"); - return -1; } /* test library functions. the point of these tests is not so much to test @@ -222,10 +131,6 @@ test_cmdline_lib(void) { if (test_cmdline_parse_fns() < 0) return -1; - if (test_cmdline_rdline_fns() < 0) - return -1; - if (test_cmdline_vt100_fns() < 0) - return -1; if (test_cmdline_socket_fns() < 0) return -1; if (test_cmdline_fns() < 0) -- 2.11.0 ^ permalink raw reply [flat|nested] 18+ messages in thread
* Re: [dpdk-dev] [PATCH v1] cmdline: rework as a wrapper to libedit 2018-04-17 15:21 ` [dpdk-dev] [PATCH v1] " Adrien Mazarguil @ 2018-04-17 15:59 ` Burakov, Anatoly 2018-04-19 15:13 ` [dpdk-dev] [PATCH v2] " Adrien Mazarguil 1 sibling, 0 replies; 18+ messages in thread From: Burakov, Anatoly @ 2018-04-17 15:59 UTC (permalink / raw) To: Adrien Mazarguil, Olivier Matz Cc: dev, Keith Wiles, Jingjing Wu, Thomas Monjalon, Ferruh Yigit, Jim Thompson On 17-Apr-18 4:21 PM, Adrien Mazarguil wrote: > Disclaimer: this patch must not be confused with the CLI library [1] > (work in progress) that will eventually supersede librte_cmdline itself > with a different API. > > Rather, it modifies librte_cmdline to delegate all the heavy lifting > (terminal and history handling), strips unused features and re-implements > what remains of its public API as a wrapper to the editline library (also > known as libedit) [2], a well-known, BSD-licensed and widely available > library used by many projects which does everything needed and more [3]. > > This approach was chosen because converting librte_cmdline as a wrapper to > a more capable library was easier and faster than addressing its > shortcomings and results in much less code to maintain in DPDK. > > It also provides a drop-in solution for applications that rely on > librte_cmdline. They benefit from greatly improved command line handling > without a meaningful impact on their code base. > > The main motivation behind this patch is testpmd's flow (rte_flow) command, > which requires support for dynamic tokens and very long lines that must be > broken down when displayed. This is not supported by librte_cmdline's > limited terminal handling capabilities, resulting in a rather frustrating > user experience. > > It had to be addressed given the importance of testpmd as one of the > primary tool used by PMD developers. > > This rework results in the following changes: > > - Removed circular buffer management interface for command history > (cmdline_cirbuf.c), command history being handled by libedit. > - Removed raw command-line interpreter (cmdline_rdline.c). > - Removed raw terminal handler (cmdline_vt100.c). > - Removed all test/example code for the above. > - Re-implemented high level interactive and non-interactive command-line > handlers (cmdline.c and cmdline_socket.c) on top of libedit using its > native interface, not its readline compatibility layer. > - Made struct cmdline opaque so that applications relying on librte_cmdline > do not need to include any libedit headers. > - Applications do not need to include cmdline_rdline.h anymore. > - Terminal resizing is now automatically handled. > - New external dependency for applications relying on librte_cmdline. > - Major version bump due to the ABI impact of these changes. > > [1] http://dpdk.org/browse/draft/dpdk-draft-cli/ > [2] http://thrysoee.dk/editline/ > [3] http://netbsd.gw.com/cgi-bin/man-cgi?editline++NetBSD-current > > Signed-off-by: Adrien Mazarguil <adrien.mazarguil@6wind.com> > Cc: Olivier Matz <olivier.matz@6wind.com> > Cc: Keith Wiles <keith.wiles@intel.com> > Cc: Jingjing Wu <jingjing.wu@intel.com> > Cc: Thomas Monjalon <thomas@monjalon.net> > Cc: Ferruh Yigit <ferruh.yigit@intel.com> > Cc: Jim Thompson <jim@netgate.com> > > -- > > No fundamental change since the original RFC [4], except it's been rebased > several times and Meson build support was added in the meantime. Commit log > was also shortened a bit. > > I'm re-sending this because I think it's useful, at least to me (duh). As > the maintainer of rte_flow, I spend most of my time typing flow commands in > testpmd and libedit makes that a pleasant experience. > > Try it out! And don't hesitate to send your acked-by line to get this in > time for 18.05 :) > > [4] http://dpdk.org/ml/archives/dev/2017-November/081605.html > --- <...> > + uint32_t error:1; > + char prompt[RDLINE_PROMPT_SIZE]; > +}; > + > +void > +cmdline_set_prompt(struct cmdline *cl, const char *prompt) > { > - struct cmdline *cl = rdl->opaque; > - int ret; > - ret = cmdline_parse(cl, buf); > - if (ret == CMDLINE_PARSE_AMBIGUOUS) > - cmdline_printf(cl, "Ambiguous command\n"); > - else if (ret == CMDLINE_PARSE_NOMATCH) > - cmdline_printf(cl, "Command not found\n"); > - else if (ret == CMDLINE_PARSE_BAD_ARGS) > - cmdline_printf(cl, "Bad arguments\n"); > + if (!cl || !prompt) > + return; > + snprintf(cl->prompt, sizeof(cl->prompt), "%s", prompt); Didn't look through the entire patch yet, but this stood out - please use strlcpy() :) -- Thanks, Anatoly ^ permalink raw reply [flat|nested] 18+ messages in thread
* [dpdk-dev] [PATCH v2] cmdline: rework as a wrapper to libedit 2018-04-17 15:21 ` [dpdk-dev] [PATCH v1] " Adrien Mazarguil 2018-04-17 15:59 ` Burakov, Anatoly @ 2018-04-19 15:13 ` Adrien Mazarguil 2018-06-26 13:21 ` Olivier Matz 1 sibling, 1 reply; 18+ messages in thread From: Adrien Mazarguil @ 2018-04-19 15:13 UTC (permalink / raw) To: Olivier Matz Cc: dev, Keith Wiles, Jingjing Wu, Thomas Monjalon, Ferruh Yigit, Jim Thompson, Anatoly Burakov Disclaimer: this patch must not be confused with the CLI library [1] (work in progress) that will eventually supersede librte_cmdline itself with a different API. Rather, it modifies librte_cmdline to delegate all the heavy lifting (terminal and history handling), strips unused features and re-implements what remains of its public API as a wrapper to the editline library (also known as libedit) [2], a well-known, BSD-licensed and widely available library used by many projects which does everything needed and more [3]. This approach was chosen because converting librte_cmdline as a wrapper to a more capable library was easier and faster than addressing its shortcomings and results in much less code to maintain in DPDK. It also provides a drop-in solution for applications that rely on librte_cmdline. They benefit from greatly improved command line handling without a meaningful impact on their code base. The main motivation behind this patch is testpmd's flow (rte_flow) command, which requires support for dynamic tokens and very long lines that must be broken down when displayed. This is not supported by librte_cmdline's limited terminal handling capabilities, resulting in a rather frustrating user experience. It had to be addressed given the importance of testpmd as one of the primary tool used by PMD developers. This rework results in the following changes: - Removed circular buffer management interface for command history (cmdline_cirbuf.c), command history being handled by libedit. - Removed raw command-line interpreter (cmdline_rdline.c). - Removed raw terminal handler (cmdline_vt100.c). - Removed all test/example code for the above. - Re-implemented high level interactive and non-interactive command-line handlers (cmdline.c and cmdline_socket.c) on top of libedit using its native interface, not its readline compatibility layer. - Made struct cmdline opaque so that applications relying on librte_cmdline do not need to include any libedit headers. - Applications do not need to include cmdline_rdline.h anymore. - Terminal resizing is now automatically handled. - New external dependency for applications relying on librte_cmdline. - Major version bump due to the ABI impact of these changes. [1] http://dpdk.org/browse/draft/dpdk-draft-cli/ [2] http://thrysoee.dk/editline/ [3] http://netbsd.gw.com/cgi-bin/man-cgi?editline++NetBSD-current Signed-off-by: Adrien Mazarguil <adrien.mazarguil@6wind.com> Cc: Olivier Matz <olivier.matz@6wind.com> Cc: Keith Wiles <keith.wiles@intel.com> Cc: Jingjing Wu <jingjing.wu@intel.com> Cc: Thomas Monjalon <thomas@monjalon.net> Cc: Ferruh Yigit <ferruh.yigit@intel.com> Cc: Jim Thompson <jim@netgate.com> Cc: Anatoly Burakov <anatoly.burakov@intel.com> -- v2 changes: - Replaced an instance of snprintf() with rte_strlcpy() [5]. - Rebased patch. [5] http://dpdk.org/ml/archives/dev/2018-April/097721.html v1 changes: No fundamental change since the original RFC [4], except it's been rebased several times and Meson build support was added in the meantime. Commit log was also shortened a bit. I'm re-sending this because I think it's useful, at least to me (duh). As the maintainer of rte_flow, I spend most of my time typing flow commands in testpmd and libedit makes that a pleasant experience. Try it out! And don't hesitate to send your acked-by line to get this in time for 18.05 :) [4] http://dpdk.org/ml/archives/dev/2017-November/081605.html --- app/test-pmd/cmdline.c | 1 - examples/bond/main.c | 1 - examples/cmdline/commands.c | 1 - examples/cmdline/main.c | 1 - examples/multi_process/simple_mp/main.c | 1 - examples/multi_process/simple_mp/mp_commands.c | 1 - examples/qos_sched/cmdline.c | 1 - examples/quota_watermark/qwctl/commands.c | 1 - examples/quota_watermark/qwctl/qwctl.c | 1 - .../guest_cli/vm_power_cli_guest.c | 1 - examples/vm_power_manager/vm_power_cli.c | 1 - lib/librte_cmdline/Makefile | 10 +- lib/librte_cmdline/cmdline.c | 383 ++++-- lib/librte_cmdline/cmdline.h | 22 +- lib/librte_cmdline/cmdline_cirbuf.c | 412 ------ lib/librte_cmdline/cmdline_cirbuf.h | 193 --- lib/librte_cmdline/cmdline_parse.c | 7 +- lib/librte_cmdline/cmdline_rdline.c | 644 --------- lib/librte_cmdline/cmdline_rdline.h | 201 --- lib/librte_cmdline/cmdline_socket.c | 36 +- lib/librte_cmdline/cmdline_vt100.c | 132 -- lib/librte_cmdline/cmdline_vt100.h | 100 -- lib/librte_cmdline/meson.build | 18 +- lib/librte_cmdline/rte_cmdline_version.map | 41 +- mk/rte.app.mk | 2 + test/cmdline_test/cmdline_test.c | 1 - test/cmdline_test/commands.c | 69 - test/test/Makefile | 1 - test/test/commands.c | 1 - test/test/meson.build | 1 - test/test/test.c | 1 - test/test/test_cmdline.c | 9 - test/test/test_cmdline.h | 6 - test/test/test_cmdline_cirbuf.c | 1301 ------------------ test/test/test_cmdline_lib.c | 117 +- 35 files changed, 303 insertions(+), 3416 deletions(-) diff --git a/app/test-pmd/cmdline.c b/app/test-pmd/cmdline.c index 0b442c3a6..6b4d9dbfd 100644 --- a/app/test-pmd/cmdline.c +++ b/app/test-pmd/cmdline.c @@ -48,7 +48,6 @@ #include <rte_flow.h> #include <rte_gro.h> -#include <cmdline_rdline.h> #include <cmdline_parse.h> #include <cmdline_parse_num.h> #include <cmdline_parse_string.h> diff --git a/examples/bond/main.c b/examples/bond/main.c index d8edc642b..cd9da146f 100644 --- a/examples/bond/main.c +++ b/examples/bond/main.c @@ -42,7 +42,6 @@ #include <rte_arp.h> #include <rte_spinlock.h> -#include <cmdline_rdline.h> #include <cmdline_parse.h> #include <cmdline_parse_num.h> #include <cmdline_parse_string.h> diff --git a/examples/cmdline/commands.c b/examples/cmdline/commands.c index 06916d783..3e9d84d46 100644 --- a/examples/cmdline/commands.c +++ b/examples/cmdline/commands.c @@ -20,7 +20,6 @@ #endif #endif -#include <cmdline_rdline.h> #include <cmdline_parse.h> #include <cmdline_parse_ipaddr.h> #include <cmdline_parse_num.h> diff --git a/examples/cmdline/main.c b/examples/cmdline/main.c index f2f2e5a2f..9fe0fdef7 100644 --- a/examples/cmdline/main.c +++ b/examples/cmdline/main.c @@ -11,7 +11,6 @@ #include <termios.h> #include <sys/queue.h> -#include <cmdline_rdline.h> #include <cmdline_parse.h> #include <cmdline_socket.h> #include <cmdline.h> diff --git a/examples/multi_process/simple_mp/main.c b/examples/multi_process/simple_mp/main.c index e6c69d6a3..49d6ed169 100644 --- a/examples/multi_process/simple_mp/main.c +++ b/examples/multi_process/simple_mp/main.c @@ -35,7 +35,6 @@ #include <rte_ring.h> #include <rte_log.h> #include <rte_mempool.h> -#include <cmdline_rdline.h> #include <cmdline_parse.h> #include <cmdline_parse_string.h> #include <cmdline_socket.h> diff --git a/examples/multi_process/simple_mp/mp_commands.c b/examples/multi_process/simple_mp/mp_commands.c index e4df6ff01..a9eb8bb44 100644 --- a/examples/multi_process/simple_mp/mp_commands.c +++ b/examples/multi_process/simple_mp/mp_commands.c @@ -25,7 +25,6 @@ #include <rte_mempool.h> #include <rte_string_fns.h> -#include <cmdline_rdline.h> #include <cmdline_parse.h> #include <cmdline_parse_string.h> #include <cmdline_socket.h> diff --git a/examples/qos_sched/cmdline.c b/examples/qos_sched/cmdline.c index 15f51830c..679819a25 100644 --- a/examples/qos_sched/cmdline.c +++ b/examples/qos_sched/cmdline.c @@ -7,7 +7,6 @@ #include <inttypes.h> #include <string.h> -#include <cmdline_rdline.h> #include <cmdline_parse.h> #include <cmdline_parse_num.h> #include <cmdline_parse_string.h> diff --git a/examples/quota_watermark/qwctl/commands.c b/examples/quota_watermark/qwctl/commands.c index a1c646b9f..33fce2063 100644 --- a/examples/quota_watermark/qwctl/commands.c +++ b/examples/quota_watermark/qwctl/commands.c @@ -7,7 +7,6 @@ #include <string.h> #include <termios.h> -#include <cmdline_rdline.h> #include <cmdline_parse.h> #include <cmdline_parse_num.h> #include <cmdline_parse_string.h> diff --git a/examples/quota_watermark/qwctl/qwctl.c b/examples/quota_watermark/qwctl/qwctl.c index 2f7914c80..9f41a684a 100644 --- a/examples/quota_watermark/qwctl/qwctl.c +++ b/examples/quota_watermark/qwctl/qwctl.c @@ -13,7 +13,6 @@ #include <rte_log.h> #include <rte_memzone.h> -#include <cmdline_rdline.h> #include <cmdline_parse.h> #include <cmdline_socket.h> #include <cmdline.h> diff --git a/examples/vm_power_manager/guest_cli/vm_power_cli_guest.c b/examples/vm_power_manager/guest_cli/vm_power_cli_guest.c index 43bdeacef..218ed192e 100644 --- a/examples/vm_power_manager/guest_cli/vm_power_cli_guest.c +++ b/examples/vm_power_manager/guest_cli/vm_power_cli_guest.c @@ -8,7 +8,6 @@ #include <stdio.h> #include <termios.h> -#include <cmdline_rdline.h> #include <cmdline_parse.h> #include <cmdline_parse_string.h> #include <cmdline_parse_num.h> diff --git a/examples/vm_power_manager/vm_power_cli.c b/examples/vm_power_manager/vm_power_cli.c index d588d38aa..99757420a 100644 --- a/examples/vm_power_manager/vm_power_cli.c +++ b/examples/vm_power_manager/vm_power_cli.c @@ -10,7 +10,6 @@ #include <termios.h> #include <errno.h> -#include <cmdline_rdline.h> #include <cmdline_parse.h> #include <cmdline_parse_string.h> #include <cmdline_parse_num.h> diff --git a/lib/librte_cmdline/Makefile b/lib/librte_cmdline/Makefile index ddae1cfde..feb1f1bca 100644 --- a/lib/librte_cmdline/Makefile +++ b/lib/librte_cmdline/Makefile @@ -10,28 +10,24 @@ CFLAGS += $(WERROR_FLAGS) -I$(SRCDIR) -O3 EXPORT_MAP := rte_cmdline_version.map -LIBABIVER := 2 +LIBABIVER := 3 # all source are stored in SRCS-y SRCS-$(CONFIG_RTE_LIBRTE_CMDLINE) := cmdline.c -SRCS-$(CONFIG_RTE_LIBRTE_CMDLINE) += cmdline_cirbuf.c SRCS-$(CONFIG_RTE_LIBRTE_CMDLINE) += cmdline_parse.c SRCS-$(CONFIG_RTE_LIBRTE_CMDLINE) += cmdline_parse_etheraddr.c SRCS-$(CONFIG_RTE_LIBRTE_CMDLINE) += cmdline_parse_ipaddr.c SRCS-$(CONFIG_RTE_LIBRTE_CMDLINE) += cmdline_parse_num.c SRCS-$(CONFIG_RTE_LIBRTE_CMDLINE) += cmdline_parse_string.c -SRCS-$(CONFIG_RTE_LIBRTE_CMDLINE) += cmdline_rdline.c -SRCS-$(CONFIG_RTE_LIBRTE_CMDLINE) += cmdline_vt100.c SRCS-$(CONFIG_RTE_LIBRTE_CMDLINE) += cmdline_socket.c SRCS-$(CONFIG_RTE_LIBRTE_CMDLINE) += cmdline_parse_portlist.c -CFLAGS += -D_GNU_SOURCE LDLIBS += -lrte_eal # install includes INCS := cmdline.h cmdline_parse.h cmdline_parse_num.h cmdline_parse_ipaddr.h -INCS += cmdline_parse_etheraddr.h cmdline_parse_string.h cmdline_rdline.h -INCS += cmdline_vt100.h cmdline_socket.h cmdline_cirbuf.h cmdline_parse_portlist.h +INCS += cmdline_parse_etheraddr.h cmdline_parse_string.h +INCS += cmdline_socket.h cmdline_parse_portlist.h SYMLINK-$(CONFIG_RTE_LIBRTE_CMDLINE)-include := $(INCS) include $(RTE_SDK)/mk/rte.lib.mk diff --git a/lib/librte_cmdline/cmdline.c b/lib/librte_cmdline/cmdline.c index 591b78b0f..1c45cd9ff 100644 --- a/lib/librte_cmdline/cmdline.c +++ b/lib/librte_cmdline/cmdline.c @@ -4,79 +4,183 @@ * All rights reserved. */ +#include <ctype.h> +#include <histedit.h> +#include <stdint.h> #include <stdio.h> #include <string.h> #include <unistd.h> #include <stdlib.h> #include <stdarg.h> -#include <inttypes.h> #include <fcntl.h> #include <poll.h> #include <errno.h> -#include <termios.h> -#include <netinet/in.h> #include <rte_string_fns.h> #include "cmdline_parse.h" -#include "cmdline_rdline.h" #include "cmdline.h" -static void -cmdline_valid_buffer(struct rdline *rdl, const char *buf, - __attribute__((unused)) unsigned int size) +struct cmdline { + char *line; + FILE *f_in; + FILE *f_out; + cmdline_parse_ctx_t *ctx; + EditLine *el; + History *hist; + HistEvent histev; + uint32_t eof:1; + uint32_t error:1; + char prompt[RDLINE_PROMPT_SIZE]; +}; + +void +cmdline_set_prompt(struct cmdline *cl, const char *prompt) { - struct cmdline *cl = rdl->opaque; - int ret; - ret = cmdline_parse(cl, buf); - if (ret == CMDLINE_PARSE_AMBIGUOUS) - cmdline_printf(cl, "Ambiguous command\n"); - else if (ret == CMDLINE_PARSE_NOMATCH) - cmdline_printf(cl, "Command not found\n"); - else if (ret == CMDLINE_PARSE_BAD_ARGS) - cmdline_printf(cl, "Bad arguments\n"); + if (!cl || !prompt) + return; + rte_strlcpy(cl->prompt, prompt, sizeof(cl->prompt)); } -static int -cmdline_complete_buffer(struct rdline *rdl, const char *buf, - char *dstbuf, unsigned int dstsize, - int *state) +void * +cmdline_ctx_get(struct cmdline *cl) { - struct cmdline *cl = rdl->opaque; - return cmdline_complete(cl, buf, state, dstbuf, dstsize); + if (!cl) + return NULL; + return cl->ctx; } -int -cmdline_write_char(struct rdline *rdl, char c) +static char * +cmdline_el_prompt(EditLine *el) { - int ret = -1; struct cmdline *cl; - if (!rdl) - return -1; - - cl = rdl->opaque; + if (el_get(el, EL_CLIENTDATA, &cl)) + return NULL; + return cl->prompt; +} - if (cl->s_out >= 0) - ret = write(cl->s_out, &c, 1); +static unsigned char +cmdline_el_execute(EditLine *el, int c) +{ + const LineInfo *li = el_line(el); + size_t len = li->lastchar - li->buffer; + char *line; + struct cmdline *cl; + int ret; - return ret; + (void)c; + if (el_get(el, EL_CLIENTDATA, &cl)) + return CC_FATAL; + line = realloc(cl->line, len + 2); + if (!line) { + cl->error = 1; + return CC_FATAL; + } + cl->line = line; + memcpy(line, li->buffer, len); + line[len] = '\n'; + line[len + 1] = '\0'; + fputs("\r\n", cl->f_out); + ret = cmdline_parse(cl, line); + if (ret == CMDLINE_PARSE_AMBIGUOUS) + fprintf(cl->f_out, "Ambiguous command\r\n"); + else if (ret == CMDLINE_PARSE_NOMATCH) + fprintf(cl->f_out, "Command not found\r\n"); + else if (ret == CMDLINE_PARSE_BAD_ARGS) + fprintf(cl->f_out, "Bad arguments\r\n"); + if (cl->error) + return CC_FATAL; + if (cl->eof) + return CC_EOF; + if (len) { + line[len] = '\0'; + history(cl->hist, &cl->histev, H_ENTER, line); + } + return CC_NEWLINE; } +static unsigned char +cmdline_el_complete(EditLine *el, int c) +{ + const LineInfo *li = el_line(el); + size_t pos = li->cursor - li->buffer; + char *line; + struct cmdline *cl; + char complete_buf[RDLINE_COMPLETE_SIZE]; + int complete_state; + int ret; -void -cmdline_set_prompt(struct cmdline *cl, const char *prompt) + if (el_get(el, EL_CLIENTDATA, &cl)) + return CC_FATAL; + line = realloc(cl->line, pos + 1); + if (!line) { + cl->error = 1; + return CC_FATAL; + } + cl->line = line; + memcpy(line, li->buffer, pos); + line[pos] = '\0'; + if (c == '\t') + complete_state = 0; + else + complete_state = -1; + /* see in parse.h for help on complete() */ + ret = cmdline_complete(cl, line, &complete_state, + complete_buf, sizeof(complete_buf)); + /* no completion or error */ + if (ret <= 0) + return CC_ARGHACK; + /* string must be NUL-terminated */ + if (strnlen(complete_buf, sizeof(complete_buf)) == sizeof(complete_buf)) + return CC_ERROR; + /* add chars */ + if (ret == CMDLINE_PARSE_COMPLETED_BUFFER) { + /* if in the middle of a token, remove its suffix first */ + for (pos = 0; li->cursor + pos != li->lastchar; pos++) + if (isblank(li->cursor[pos])) + break; + el_cursor(el, pos); + el_deletestr(el, pos); + if (el_insertstr(el, complete_buf)) + return CC_ERROR; + return CC_REFRESH; + } + /* choice */ + fputs("\r\n", cl->f_out); + while (ret) { + fputc(' ', cl->f_out); + fputs(complete_buf, cl->f_out); + fputs("\r\n", cl->f_out); + ret = cmdline_complete(cl, line, &complete_state, + complete_buf, sizeof(complete_buf)); + } + el_set(el, EL_REFRESH); + return CC_REDISPLAY; +} + +static unsigned char +cmdline_el_delete_next_char_or_eof(EditLine *el, int c) { - if (!cl || !prompt) - return; - snprintf(cl->prompt, sizeof(cl->prompt), "%s", prompt); + const LineInfo *li = el_line(el); + struct cmdline *cl; + + (void)c; + if (el_get(el, EL_CLIENTDATA, &cl)) + return CC_FATAL; + if (li->buffer == li->lastchar) { + cl->eof = 1; + return CC_EOF; + } + el_cursor(el, 1); + el_deletestr(el, 1); + return CC_REFRESH; } struct cmdline * cmdline_new(cmdline_parse_ctx_t *ctx, const char *prompt, int s_in, int s_out) { struct cmdline *cl; - int ret; if (!ctx || !prompt) return NULL; @@ -85,36 +189,89 @@ cmdline_new(cmdline_parse_ctx_t *ctx, const char *prompt, int s_in, int s_out) if (cl == NULL) return NULL; memset(cl, 0, sizeof(struct cmdline)); - cl->s_in = s_in; - cl->s_out = s_out; + cl->line = NULL; + s_in = dup(s_in); + s_out = s_out != -1 ? dup(s_out) : open("/dev/null", O_WRONLY); + if (s_in == -1 || s_out == -1) + goto error; + cl->f_in = fdopen(s_in, "rb"); + cl->f_out = fdopen(s_out, "wb"); + if (!cl->f_in || !cl->f_out) + goto error; cl->ctx = ctx; - - ret = rdline_init(&cl->rdl, cmdline_write_char, cmdline_valid_buffer, - cmdline_complete_buffer); - if (ret != 0) { - free(cl); - return NULL; - } - - cl->rdl.opaque = cl; + cl->el = el_init("dpdk", cl->f_in, cl->f_out, stderr); + if (!cl->el) + goto error; + if (el_set(cl->el, EL_CLIENTDATA, cl)) + goto error; cmdline_set_prompt(cl, prompt); - rdline_newline(&cl->rdl, cl->prompt); - + if (el_set(cl->el, EL_PROMPT, cmdline_el_prompt)) + goto error; + if (el_set(cl->el, EL_EDITOR, "emacs")) + goto error; + if (el_set(cl->el, EL_SIGNAL, 1)) + goto error; + cl->hist = history_init(); + if (!cl->hist) + goto error; + if (history(cl->hist, &cl->histev, H_SETSIZE, + RDLINE_HISTORY_MAX_LINE) < 0) + goto error; + if (history(cl->hist, &cl->histev, H_SETUNIQUE, 1)) + goto error; + if (el_set(cl->el, EL_HIST, history, cl->hist)) + goto error; + if (el_set(cl->el, EL_ADDFN, "ed-execute", "Execute command", + cmdline_el_execute)) + goto error; + if (el_set(cl->el, EL_BIND, "^J", "ed-execute", NULL)) + goto error; + if (el_set(cl->el, EL_BIND, "^M", "ed-execute", NULL)) + goto error; + if (el_set(cl->el, EL_ADDFN, "ed-complete", "Complete argument", + cmdline_el_complete)) + goto error; + if (el_set(cl->el, EL_BIND, "^I", "ed-complete", NULL)) + goto error; + if (el_set(cl->el, EL_BIND, "?", "ed-complete", NULL)) + goto error; + if (el_set(cl->el, EL_ADDFN, "ed-delete-next-char-or-eof", + "Delete next character or assume EOF", + cmdline_el_delete_next_char_or_eof)) + goto error; + if (el_set(cl->el, EL_BIND, "^D", + "ed-delete-next-char-or-eof", NULL)) + goto error; + if (el_set(cl->el, EL_BIND, "^W", "ed-delete-prev-word", NULL)) + goto error; return cl; +error: + if (cl->hist) + history_end(cl->hist); + if (cl->el) + el_end(cl->el); + if (cl->f_out) + fclose(cl->f_out); + else if (s_out != -1) + close(s_out); + if (cl->f_in) + fclose(cl->f_in); + else if (s_in != -1) + close(s_in); + free(cl); + return NULL; } void cmdline_free(struct cmdline *cl) { - dprintf("called\n"); - if (!cl) return; - - if (cl->s_in > 2) - close(cl->s_in); - if (cl->s_out != cl->s_in && cl->s_out > 2) - close(cl->s_out); + history_end(cl->hist); + el_end(cl->el); + fclose(cl->f_out); + fclose(cl->f_in); + free(cl->line); free(cl); } @@ -126,70 +283,23 @@ cmdline_printf(const struct cmdline *cl, const char *fmt, ...) if (!cl || !fmt) return; -#ifdef _GNU_SOURCE - if (cl->s_out < 0) - return; - va_start(ap, fmt); - vdprintf(cl->s_out, fmt, ap); - va_end(ap); -#else - int ret; - char *buf; - - if (cl->s_out < 0) - return; - - buf = malloc(BUFSIZ); - if (buf == NULL) - return; va_start(ap, fmt); - ret = vsnprintf(buf, BUFSIZ, fmt, ap); + vfprintf(cl->f_out, fmt, ap); va_end(ap); - if (ret < 0) { - free(buf); - return; - } - if (ret >= BUFSIZ) - ret = BUFSIZ - 1; - ret = write(cl->s_out, buf, ret); - (void)ret; - free(buf); -#endif } int cmdline_in(struct cmdline *cl, const char *buf, int size) { - const char *history, *buffer; - size_t histlen, buflen; - int ret = 0; - int i, same; + int i; if (!cl || !buf) return -1; for (i=0; i<size; i++) { - ret = rdline_char_in(&cl->rdl, buf[i]); - - if (ret == RDLINE_RES_VALIDATED) { - buffer = rdline_get_buffer(&cl->rdl); - history = rdline_get_history_item(&cl->rdl, 0); - if (history) { - histlen = strnlen(history, RDLINE_BUF_SIZE); - same = !memcmp(buffer, history, histlen) && - buffer[histlen] == '\n'; - } - else - same = 0; - buflen = strnlen(buffer, RDLINE_BUF_SIZE); - if (buflen > 1 && !same) - rdline_add_history(&cl->rdl, buffer); - rdline_newline(&cl->rdl, cl->prompt); - } - else if (ret == RDLINE_RES_EOF) - return -1; - else if (ret == RDLINE_RES_EXITED) - return -1; + char tmp[2] = { buf[i], '\0' }; + + el_push(cl->el, tmp); } return i; } @@ -199,7 +309,7 @@ cmdline_quit(struct cmdline *cl) { if (!cl) return; - rdline_quit(&cl->rdl); + cl->eof = 1; } int @@ -207,48 +317,49 @@ cmdline_poll(struct cmdline *cl) { struct pollfd pfd; int status; - ssize_t read_status; - char c; + int read_status; + int flags; if (!cl) return -EINVAL; - else if (cl->rdl.status == RDLINE_EXITED) + else if (cl->error) + return RDLINE_ERROR; + else if (cl->eof) return RDLINE_EXITED; - pfd.fd = cl->s_in; + pfd.fd = fileno(cl->f_in); pfd.events = POLLIN; pfd.revents = 0; status = poll(&pfd, 1, 0); if (status < 0) - return status; - else if (status > 0) { - c = -1; - read_status = read(cl->s_in, &c, 1); - if (read_status < 0) - return read_status; - - status = cmdline_in(cl, &c, 1); - if (status < 0 && cl->rdl.status != RDLINE_EXITED) - return status; - } - - return cl->rdl.status; + return RDLINE_ERROR; + if (!status) + return RDLINE_RUNNING; + flags = fcntl(pfd.fd, F_GETFL); + if (!(flags & O_NONBLOCK)) + fcntl(pfd.fd, F_SETFL, flags | O_NONBLOCK); + if (!el_gets(cl->el, &read_status) && read_status == -1) + cl->error = 1; + if (!(flags & O_NONBLOCK)) + fcntl(pfd.fd, F_SETFL, flags); + return cl->error ? RDLINE_ERROR : + cl->eof ? RDLINE_EXITED : + RDLINE_RUNNING; } void cmdline_interact(struct cmdline *cl) { - char c; - if (!cl) return; - c = -1; - while (1) { - if (read(cl->s_in, &c, 1) <= 0) - break; - if (cmdline_in(cl, &c, 1) < 0) - break; + while (!cl->error && !cl->eof) { + int read_status; + + if (el_gets(cl->el, &read_status)) + continue; + if (read_status == -1) + cl->error = 1; } } diff --git a/lib/librte_cmdline/cmdline.h b/lib/librte_cmdline/cmdline.h index 27d2effdf..1f443be60 100644 --- a/lib/librte_cmdline/cmdline.h +++ b/lib/librte_cmdline/cmdline.h @@ -7,8 +7,6 @@ #ifndef _CMDLINE_H_ #define _CMDLINE_H_ -#include <termios.h> -#include <cmdline_rdline.h> #include <cmdline_parse.h> /** @@ -21,22 +19,26 @@ extern "C" { #endif -struct cmdline { - int s_in; - int s_out; - cmdline_parse_ctx_t *ctx; - struct rdline rdl; - char prompt[RDLINE_PROMPT_SIZE]; - struct termios oldterm; +#define RDLINE_PROMPT_SIZE 32 +#define RDLINE_HISTORY_MAX_LINE 64 +#define RDLINE_COMPLETE_SIZE 128 + +enum rdline_status { + RDLINE_ERROR = -1, + RDLINE_INIT, + RDLINE_RUNNING, + RDLINE_EXITED, }; +struct cmdline; + +void *cmdline_ctx_get(struct cmdline *cl); struct cmdline *cmdline_new(cmdline_parse_ctx_t *ctx, const char *prompt, int s_in, int s_out); void cmdline_set_prompt(struct cmdline *cl, const char *prompt); void cmdline_free(struct cmdline *cl); void cmdline_printf(const struct cmdline *cl, const char *fmt, ...) __attribute__((format(printf,2,3))); int cmdline_in(struct cmdline *cl, const char *buf, int size); -int cmdline_write_char(struct rdline *rdl, char c); /** * This function is nonblocking equivalent of ``cmdline_interact()``. It polls diff --git a/lib/librte_cmdline/cmdline_cirbuf.c b/lib/librte_cmdline/cmdline_cirbuf.c deleted file mode 100644 index 829a8af56..000000000 --- a/lib/librte_cmdline/cmdline_cirbuf.c +++ /dev/null @@ -1,412 +0,0 @@ -/* SPDX-License-Identifier: BSD-3-Clause - * Copyright(c) 2010-2014 Intel Corporation. - * Copyright (c) 2009, Olivier MATZ <zer0@droids-corp.org> - * All rights reserved. - */ - -#include <string.h> -#include <errno.h> -#include <stdio.h> - -#include "cmdline_cirbuf.h" - - -int -cirbuf_init(struct cirbuf *cbuf, char *buf, unsigned int start, unsigned int maxlen) -{ - if (!cbuf || !buf) - return -EINVAL; - cbuf->maxlen = maxlen; - cbuf->len = 0; - cbuf->start = start; - cbuf->end = start; - cbuf->buf = buf; - return 0; -} - -/* multiple add */ - -int -cirbuf_add_buf_head(struct cirbuf *cbuf, const char *c, unsigned int n) -{ - unsigned int e; - - if (!cbuf || !c || !n || n > CIRBUF_GET_FREELEN(cbuf)) - return -EINVAL; - - e = CIRBUF_IS_EMPTY(cbuf) ? 1 : 0; - - if (n < cbuf->start + e) { - dprintf("s[%d] -> d[%d] (%d)\n", 0, cbuf->start - n + e, n); - memcpy(cbuf->buf + cbuf->start - n + e, c, n); - } - else { - dprintf("s[%d] -> d[%d] (%d)\n", + n - (cbuf->start + e), 0, - cbuf->start + e); - dprintf("s[%d] -> d[%d] (%d)\n", cbuf->maxlen - n + - (cbuf->start + e), 0, n - (cbuf->start + e)); - memcpy(cbuf->buf, c + n - (cbuf->start + e) , cbuf->start + e); - memcpy(cbuf->buf + cbuf->maxlen - n + (cbuf->start + e), c, - n - (cbuf->start + e)); - } - cbuf->len += n; - cbuf->start += (cbuf->maxlen - n + e); - cbuf->start %= cbuf->maxlen; - return n; -} - -/* multiple add */ - -int -cirbuf_add_buf_tail(struct cirbuf *cbuf, const char *c, unsigned int n) -{ - unsigned int e; - - if (!cbuf || !c || !n || n > CIRBUF_GET_FREELEN(cbuf)) - return -EINVAL; - - e = CIRBUF_IS_EMPTY(cbuf) ? 1 : 0; - - if (n < cbuf->maxlen - cbuf->end - 1 + e) { - dprintf("s[%d] -> d[%d] (%d)\n", 0, cbuf->end + !e, n); - memcpy(cbuf->buf + cbuf->end + !e, c, n); - } - else { - dprintf("s[%d] -> d[%d] (%d)\n", cbuf->end + !e, 0, - cbuf->maxlen - cbuf->end - 1 + e); - dprintf("s[%d] -> d[%d] (%d)\n", cbuf->maxlen - cbuf->end - 1 + - e, 0, n - cbuf->maxlen + cbuf->end + 1 - e); - memcpy(cbuf->buf + cbuf->end + !e, c, cbuf->maxlen - - cbuf->end - 1 + e); - memcpy(cbuf->buf, c + cbuf->maxlen - cbuf->end - 1 + e, - n - cbuf->maxlen + cbuf->end + 1 - e); - } - cbuf->len += n; - cbuf->end += n - e; - cbuf->end %= cbuf->maxlen; - return n; -} - -/* add at head */ - -static inline void -__cirbuf_add_head(struct cirbuf * cbuf, char c) -{ - if (!CIRBUF_IS_EMPTY(cbuf)) { - cbuf->start += (cbuf->maxlen - 1); - cbuf->start %= cbuf->maxlen; - } - cbuf->buf[cbuf->start] = c; - cbuf->len ++; -} - -int -cirbuf_add_head_safe(struct cirbuf * cbuf, char c) -{ - if (cbuf && !CIRBUF_IS_FULL(cbuf)) { - __cirbuf_add_head(cbuf, c); - return 0; - } - return -EINVAL; -} - -void -cirbuf_add_head(struct cirbuf * cbuf, char c) -{ - __cirbuf_add_head(cbuf, c); -} - -/* add at tail */ - -static inline void -__cirbuf_add_tail(struct cirbuf * cbuf, char c) -{ - if (!CIRBUF_IS_EMPTY(cbuf)) { - cbuf->end ++; - cbuf->end %= cbuf->maxlen; - } - cbuf->buf[cbuf->end] = c; - cbuf->len ++; -} - -int -cirbuf_add_tail_safe(struct cirbuf * cbuf, char c) -{ - if (cbuf && !CIRBUF_IS_FULL(cbuf)) { - __cirbuf_add_tail(cbuf, c); - return 0; - } - return -EINVAL; -} - -void -cirbuf_add_tail(struct cirbuf * cbuf, char c) -{ - __cirbuf_add_tail(cbuf, c); -} - - -static inline void -__cirbuf_shift_left(struct cirbuf *cbuf) -{ - unsigned int i; - char tmp = cbuf->buf[cbuf->start]; - - for (i=0 ; i<cbuf->len ; i++) { - cbuf->buf[(cbuf->start+i)%cbuf->maxlen] = - cbuf->buf[(cbuf->start+i+1)%cbuf->maxlen]; - } - cbuf->buf[(cbuf->start-1+cbuf->maxlen)%cbuf->maxlen] = tmp; - cbuf->start += (cbuf->maxlen - 1); - cbuf->start %= cbuf->maxlen; - cbuf->end += (cbuf->maxlen - 1); - cbuf->end %= cbuf->maxlen; -} - -static inline void -__cirbuf_shift_right(struct cirbuf *cbuf) -{ - unsigned int i; - char tmp = cbuf->buf[cbuf->end]; - - for (i=0 ; i<cbuf->len ; i++) { - cbuf->buf[(cbuf->end+cbuf->maxlen-i)%cbuf->maxlen] = - cbuf->buf[(cbuf->end+cbuf->maxlen-i-1)%cbuf->maxlen]; - } - cbuf->buf[(cbuf->end+1)%cbuf->maxlen] = tmp; - cbuf->start += 1; - cbuf->start %= cbuf->maxlen; - cbuf->end += 1; - cbuf->end %= cbuf->maxlen; -} - -/* XXX we could do a better algorithm here... */ -int -cirbuf_align_left(struct cirbuf * cbuf) -{ - if (!cbuf) - return -EINVAL; - - if (cbuf->start < cbuf->maxlen/2) { - while (cbuf->start != 0) { - __cirbuf_shift_left(cbuf); - } - } - else { - while (cbuf->start != 0) { - __cirbuf_shift_right(cbuf); - } - } - - return 0; -} - -/* XXX we could do a better algorithm here... */ -int -cirbuf_align_right(struct cirbuf * cbuf) -{ - if (!cbuf) - return -EINVAL; - - if (cbuf->start >= cbuf->maxlen/2) { - while (cbuf->end != cbuf->maxlen-1) { - __cirbuf_shift_left(cbuf); - } - } - else { - while (cbuf->start != cbuf->maxlen-1) { - __cirbuf_shift_right(cbuf); - } - } - - return 0; -} - -/* buffer del */ - -int -cirbuf_del_buf_head(struct cirbuf *cbuf, unsigned int size) -{ - if (!cbuf || !size || size > CIRBUF_GET_LEN(cbuf)) - return -EINVAL; - - cbuf->len -= size; - if (CIRBUF_IS_EMPTY(cbuf)) { - cbuf->start += size - 1; - cbuf->start %= cbuf->maxlen; - } - else { - cbuf->start += size; - cbuf->start %= cbuf->maxlen; - } - return 0; -} - -/* buffer del */ - -int -cirbuf_del_buf_tail(struct cirbuf *cbuf, unsigned int size) -{ - if (!cbuf || !size || size > CIRBUF_GET_LEN(cbuf)) - return -EINVAL; - - cbuf->len -= size; - if (CIRBUF_IS_EMPTY(cbuf)) { - cbuf->end += (cbuf->maxlen - size + 1); - cbuf->end %= cbuf->maxlen; - } - else { - cbuf->end += (cbuf->maxlen - size); - cbuf->end %= cbuf->maxlen; - } - return 0; -} - -/* del at head */ - -static inline void -__cirbuf_del_head(struct cirbuf * cbuf) -{ - cbuf->len --; - if (!CIRBUF_IS_EMPTY(cbuf)) { - cbuf->start ++; - cbuf->start %= cbuf->maxlen; - } -} - -int -cirbuf_del_head_safe(struct cirbuf * cbuf) -{ - if (cbuf && !CIRBUF_IS_EMPTY(cbuf)) { - __cirbuf_del_head(cbuf); - return 0; - } - return -EINVAL; -} - -void -cirbuf_del_head(struct cirbuf * cbuf) -{ - __cirbuf_del_head(cbuf); -} - -/* del at tail */ - -static inline void -__cirbuf_del_tail(struct cirbuf * cbuf) -{ - cbuf->len --; - if (!CIRBUF_IS_EMPTY(cbuf)) { - cbuf->end += (cbuf->maxlen - 1); - cbuf->end %= cbuf->maxlen; - } -} - -int -cirbuf_del_tail_safe(struct cirbuf * cbuf) -{ - if (cbuf && !CIRBUF_IS_EMPTY(cbuf)) { - __cirbuf_del_tail(cbuf); - return 0; - } - return -EINVAL; -} - -void -cirbuf_del_tail(struct cirbuf * cbuf) -{ - __cirbuf_del_tail(cbuf); -} - -/* convert to buffer */ - -int -cirbuf_get_buf_head(struct cirbuf *cbuf, char *c, unsigned int size) -{ - unsigned int n; - - if (!cbuf || !c) - return -EINVAL; - - n = (size < CIRBUF_GET_LEN(cbuf)) ? size : CIRBUF_GET_LEN(cbuf); - - if (!n) - return 0; - - if (cbuf->start <= cbuf->end) { - dprintf("s[%d] -> d[%d] (%d)\n", cbuf->start, 0, n); - memcpy(c, cbuf->buf + cbuf->start , n); - } - else { - /* check if we need to go from end to the beginning */ - if (n <= cbuf->maxlen - cbuf->start) { - dprintf("s[%d] -> d[%d] (%d)\n", 0, cbuf->start, n); - memcpy(c, cbuf->buf + cbuf->start , n); - } - else { - dprintf("s[%d] -> d[%d] (%d)\n", cbuf->start, 0, - cbuf->maxlen - cbuf->start); - dprintf("s[%d] -> d[%d] (%d)\n", 0, cbuf->maxlen - cbuf->start, - n - cbuf->maxlen + cbuf->start); - memcpy(c, cbuf->buf + cbuf->start , cbuf->maxlen - cbuf->start); - memcpy(c + cbuf->maxlen - cbuf->start, cbuf->buf, - n - cbuf->maxlen + cbuf->start); - } - } - return n; -} - -/* convert to buffer */ - -int -cirbuf_get_buf_tail(struct cirbuf *cbuf, char *c, unsigned int size) -{ - unsigned int n; - - if (!cbuf || !c) - return -EINVAL; - - n = (size < CIRBUF_GET_LEN(cbuf)) ? size : CIRBUF_GET_LEN(cbuf); - - if (!n) - return 0; - - if (cbuf->start <= cbuf->end) { - dprintf("s[%d] -> d[%d] (%d)\n", cbuf->end - n + 1, 0, n); - memcpy(c, cbuf->buf + cbuf->end - n + 1, n); - } - else { - /* check if we need to go from end to the beginning */ - if (n <= cbuf->end + 1) { - dprintf("s[%d] -> d[%d] (%d)\n", 0, cbuf->end - n + 1, n); - memcpy(c, cbuf->buf + cbuf->end - n + 1, n); - } - else { - dprintf("s[%d] -> d[%d] (%d)\n", 0, - cbuf->maxlen - cbuf->start, cbuf->end + 1); - dprintf("s[%d] -> d[%d] (%d)\n", - cbuf->maxlen - n + cbuf->end + 1, 0, n - cbuf->end - 1); - memcpy(c + cbuf->maxlen - cbuf->start, - cbuf->buf, cbuf->end + 1); - memcpy(c, cbuf->buf + cbuf->maxlen - n + cbuf->end +1, - n - cbuf->end - 1); - } - } - return n; -} - -/* get head or get tail */ - -char -cirbuf_get_head(struct cirbuf * cbuf) -{ - return cbuf->buf[cbuf->start]; -} - -/* get head or get tail */ - -char -cirbuf_get_tail(struct cirbuf * cbuf) -{ - return cbuf->buf[cbuf->end]; -} diff --git a/lib/librte_cmdline/cmdline_cirbuf.h b/lib/librte_cmdline/cmdline_cirbuf.h deleted file mode 100644 index c23b211ad..000000000 --- a/lib/librte_cmdline/cmdline_cirbuf.h +++ /dev/null @@ -1,193 +0,0 @@ -/* SPDX-License-Identifier: BSD-3-Clause - * Copyright(c) 2010-2014 Intel Corporation. - * Copyright (c) 2009, Olivier MATZ <zer0@droids-corp.org> - * All rights reserved. - */ - -#ifndef _CIRBUF_H_ -#define _CIRBUF_H_ - -#include <rte_config.h> - -#ifdef __cplusplus -extern "C" { -#endif - -/** - * This structure is the header of a cirbuf type. - */ -struct cirbuf { - unsigned int maxlen; /**< total len of the fifo (number of elements) */ - unsigned int start; /**< indice of the first elt */ - unsigned int end; /**< indice of the last elt */ - unsigned int len; /**< current len of fifo */ - char *buf; -}; - -#ifdef RTE_LIBRTE_CMDLINE_DEBUG -#define dprintf_(fmt, ...) printf("line %3.3d - " fmt "%.0s", __LINE__, __VA_ARGS__) -#define dprintf(...) dprintf_(__VA_ARGS__, "dummy") -#else -#define dprintf(...) (void)0 -#endif - - -/** - * Init the circular buffer - */ -int cirbuf_init(struct cirbuf *cbuf, char *buf, unsigned int start, unsigned int maxlen); - - -/** - * Return 1 if the circular buffer is full - */ -#define CIRBUF_IS_FULL(cirbuf) ((cirbuf)->maxlen == (cirbuf)->len) - -/** - * Return 1 if the circular buffer is empty - */ -#define CIRBUF_IS_EMPTY(cirbuf) ((cirbuf)->len == 0) - -/** - * return current size of the circular buffer (number of used elements) - */ -#define CIRBUF_GET_LEN(cirbuf) ((cirbuf)->len) - -/** - * return size of the circular buffer (used + free elements) - */ -#define CIRBUF_GET_MAXLEN(cirbuf) ((cirbuf)->maxlen) - -/** - * return the number of free elts - */ -#define CIRBUF_GET_FREELEN(cirbuf) ((cirbuf)->maxlen - (cirbuf)->len) - -/** - * Iterator for a circular buffer - * c: struct cirbuf pointer - * i: an integer type internally used in the macro - * e: char that takes the value for each iteration - */ -#define CIRBUF_FOREACH(c, i, e) \ - for ( i=0, e=(c)->buf[(c)->start] ; \ - i<((c)->len) ; \ - i ++, e=(c)->buf[((c)->start+i)%((c)->maxlen)]) - - -/** - * Add a character at head of the circular buffer. Return 0 on success, or - * a negative value on error. - */ -int cirbuf_add_head_safe(struct cirbuf *cbuf, char c); - -/** - * Add a character at head of the circular buffer. You _must_ check that you - * have enough free space in the buffer before calling this func. - */ -void cirbuf_add_head(struct cirbuf *cbuf, char c); - -/** - * Add a character at tail of the circular buffer. Return 0 on success, or - * a negative value on error. - */ -int cirbuf_add_tail_safe(struct cirbuf *cbuf, char c); - -/** - * Add a character at tail of the circular buffer. You _must_ check that you - * have enough free space in the buffer before calling this func. - */ -void cirbuf_add_tail(struct cirbuf *cbuf, char c); - -/** - * Remove a char at the head of the circular buffer. Return 0 on - * success, or a negative value on error. - */ -int cirbuf_del_head_safe(struct cirbuf *cbuf); - -/** - * Remove a char at the head of the circular buffer. You _must_ check - * that buffer is not empty before calling the function. - */ -void cirbuf_del_head(struct cirbuf *cbuf); - -/** - * Remove a char at the tail of the circular buffer. Return 0 on - * success, or a negative value on error. - */ -int cirbuf_del_tail_safe(struct cirbuf *cbuf); - -/** - * Remove a char at the tail of the circular buffer. You _must_ check - * that buffer is not empty before calling the function. - */ -void cirbuf_del_tail(struct cirbuf *cbuf); - -/** - * Return the head of the circular buffer. You _must_ check that - * buffer is not empty before calling the function. - */ -char cirbuf_get_head(struct cirbuf *cbuf); - -/** - * Return the tail of the circular buffer. You _must_ check that - * buffer is not empty before calling the function. - */ -char cirbuf_get_tail(struct cirbuf *cbuf); - -/** - * Add a buffer at head of the circular buffer. 'c' is a pointer to a - * buffer, and n is the number of char to add. Return the number of - * copied bytes on success, or a negative value on error. - */ -int cirbuf_add_buf_head(struct cirbuf *cbuf, const char *c, unsigned int n); - -/** - * Add a buffer at tail of the circular buffer. 'c' is a pointer to a - * buffer, and n is the number of char to add. Return the number of - * copied bytes on success, or a negative value on error. - */ -int cirbuf_add_buf_tail(struct cirbuf *cbuf, const char *c, unsigned int n); - -/** - * Remove chars at the head of the circular buffer. Return 0 on - * success, or a negative value on error. - */ -int cirbuf_del_buf_head(struct cirbuf *cbuf, unsigned int size); - -/** - * Remove chars at the tail of the circular buffer. Return 0 on - * success, or a negative value on error. - */ -int cirbuf_del_buf_tail(struct cirbuf *cbuf, unsigned int size); - -/** - * Copy a maximum of 'size' characters from the head of the circular - * buffer to a flat one pointed by 'c'. Return the number of copied - * chars. - */ -int cirbuf_get_buf_head(struct cirbuf *cbuf, char *c, unsigned int size); - -/** - * Copy a maximum of 'size' characters from the tail of the circular - * buffer to a flat one pointed by 'c'. Return the number of copied - * chars. - */ -int cirbuf_get_buf_tail(struct cirbuf *cbuf, char *c, unsigned int size); - - -/** - * Set the start of the data to the index 0 of the internal buffer. - */ -int cirbuf_align_left(struct cirbuf *cbuf); - -/** - * Set the end of the data to the last index of the internal buffer. - */ -int cirbuf_align_right(struct cirbuf *cbuf); - -#ifdef __cplusplus -} -#endif - -#endif /* _CIRBUF_H_ */ diff --git a/lib/librte_cmdline/cmdline_parse.c b/lib/librte_cmdline/cmdline_parse.c index 961f9befd..f75870b5b 100644 --- a/lib/librte_cmdline/cmdline_parse.c +++ b/lib/librte_cmdline/cmdline_parse.c @@ -16,7 +16,6 @@ #include <rte_string_fns.h> -#include "cmdline_rdline.h" #include "cmdline_parse.h" #include "cmdline.h" @@ -216,7 +215,7 @@ cmdline_parse(struct cmdline *cl, const char * buf) if (!cl || !buf) return CMDLINE_PARSE_BAD_ARGS; - ctx = cl->ctx; + ctx = cmdline_ctx_get(cl); /* * - look if the buffer contains at least one line @@ -334,7 +333,7 @@ cmdline_complete(struct cmdline *cl, const char *buf, int *state, if (!cl || !buf || !state || !dst) return -1; - ctx = cl->ctx; + ctx = cmdline_ctx_get(cl); debug_printf("%s called\n", __func__); memset(&token_hdr, 0, sizeof(token_hdr)); @@ -346,7 +345,7 @@ cmdline_complete(struct cmdline *cl, const char *buf, int *state, if (isblank2(buf[i]) && !isblank2(buf[i+1])) partial_tok = buf+i+1; } - partial_tok_len = strnlen(partial_tok, RDLINE_BUF_SIZE); + partial_tok_len = strlen(partial_tok); /* first call -> do a first pass */ if (*state <= 0) { diff --git a/lib/librte_cmdline/cmdline_rdline.c b/lib/librte_cmdline/cmdline_rdline.c deleted file mode 100644 index 2cb53e38f..000000000 --- a/lib/librte_cmdline/cmdline_rdline.c +++ /dev/null @@ -1,644 +0,0 @@ -/* SPDX-License-Identifier: BSD-3-Clause - * Copyright(c) 2010-2014 Intel Corporation. - * Copyright (c) 2009, Olivier MATZ <zer0@droids-corp.org> - * All rights reserved. - */ - -#include <stdlib.h> -#include <stdio.h> -#include <stdint.h> -#include <string.h> -#include <stdarg.h> -#include <errno.h> -#include <ctype.h> - -#include "cmdline_cirbuf.h" -#include "cmdline_rdline.h" - -static void rdline_puts(struct rdline *rdl, const char *buf); -static void rdline_miniprintf(struct rdline *rdl, - const char *buf, unsigned int val); - -static void rdline_remove_old_history_item(struct rdline *rdl); -static void rdline_remove_first_history_item(struct rdline *rdl); -static unsigned int rdline_get_history_size(struct rdline *rdl); - - -/* isblank() needs _XOPEN_SOURCE >= 600 || _ISOC99_SOURCE, so use our - * own. */ -static int -isblank2(char c) -{ - if (c == ' ' || - c == '\t' ) - return 1; - return 0; -} - -int -rdline_init(struct rdline *rdl, - rdline_write_char_t *write_char, - rdline_validate_t *validate, - rdline_complete_t *complete) -{ - if (!rdl || !write_char || !validate || !complete) - return -EINVAL; - memset(rdl, 0, sizeof(*rdl)); - rdl->validate = validate; - rdl->complete = complete; - rdl->write_char = write_char; - rdl->status = RDLINE_INIT; - return cirbuf_init(&rdl->history, rdl->history_buf, 0, RDLINE_HISTORY_BUF_SIZE); -} - -void -rdline_newline(struct rdline *rdl, const char *prompt) -{ - unsigned int i; - - if (!rdl || !prompt) - return; - - vt100_init(&rdl->vt100); - cirbuf_init(&rdl->left, rdl->left_buf, 0, RDLINE_BUF_SIZE); - cirbuf_init(&rdl->right, rdl->right_buf, 0, RDLINE_BUF_SIZE); - - rdl->prompt_size = strnlen(prompt, RDLINE_PROMPT_SIZE-1); - if (prompt != rdl->prompt) - memcpy(rdl->prompt, prompt, rdl->prompt_size); - rdl->prompt[RDLINE_PROMPT_SIZE-1] = '\0'; - - for (i=0 ; i<rdl->prompt_size ; i++) - rdl->write_char(rdl, rdl->prompt[i]); - rdl->status = RDLINE_RUNNING; - - rdl->history_cur_line = -1; -} - -void -rdline_stop(struct rdline *rdl) -{ - if (!rdl) - return; - rdl->status = RDLINE_INIT; -} - -void -rdline_quit(struct rdline *rdl) -{ - if (!rdl) - return; - rdl->status = RDLINE_EXITED; -} - -void -rdline_restart(struct rdline *rdl) -{ - if (!rdl) - return; - rdl->status = RDLINE_RUNNING; -} - -void -rdline_reset(struct rdline *rdl) -{ - if (!rdl) - return; - vt100_init(&rdl->vt100); - cirbuf_init(&rdl->left, rdl->left_buf, 0, RDLINE_BUF_SIZE); - cirbuf_init(&rdl->right, rdl->right_buf, 0, RDLINE_BUF_SIZE); - - rdl->status = RDLINE_RUNNING; - - rdl->history_cur_line = -1; -} - -const char * -rdline_get_buffer(struct rdline *rdl) -{ - if (!rdl) - return NULL; - unsigned int len_l, len_r; - cirbuf_align_left(&rdl->left); - cirbuf_align_left(&rdl->right); - - len_l = CIRBUF_GET_LEN(&rdl->left); - len_r = CIRBUF_GET_LEN(&rdl->right); - memcpy(rdl->left_buf+len_l, rdl->right_buf, len_r); - - rdl->left_buf[len_l + len_r] = '\n'; - rdl->left_buf[len_l + len_r + 1] = '\0'; - return rdl->left_buf; -} - -static void -display_right_buffer(struct rdline *rdl, int force) -{ - unsigned int i; - char tmp; - - if (!force && CIRBUF_IS_EMPTY(&rdl->right)) - return; - - rdline_puts(rdl, vt100_clear_right); - CIRBUF_FOREACH(&rdl->right, i, tmp) { - rdl->write_char(rdl, tmp); - } - if (!CIRBUF_IS_EMPTY(&rdl->right)) - rdline_miniprintf(rdl, vt100_multi_left, - CIRBUF_GET_LEN(&rdl->right)); -} - -void -rdline_redisplay(struct rdline *rdl) -{ - unsigned int i; - char tmp; - - if (!rdl) - return; - - rdline_puts(rdl, vt100_home); - for (i=0 ; i<rdl->prompt_size ; i++) - rdl->write_char(rdl, rdl->prompt[i]); - CIRBUF_FOREACH(&rdl->left, i, tmp) { - rdl->write_char(rdl, tmp); - } - display_right_buffer(rdl, 1); -} - -int -rdline_char_in(struct rdline *rdl, char c) -{ - unsigned int i; - int cmd; - char tmp; - char *buf; - - if (!rdl) - return -EINVAL; - - if (rdl->status == RDLINE_EXITED) - return RDLINE_RES_EXITED; - if (rdl->status != RDLINE_RUNNING) - return RDLINE_RES_NOT_RUNNING; - - cmd = vt100_parser(&rdl->vt100, c); - if (cmd == -2) - return RDLINE_RES_SUCCESS; - - if (cmd >= 0) { - switch (cmd) { - /* move caret 1 char to the left */ - case CMDLINE_KEY_CTRL_B: - case CMDLINE_KEY_LEFT_ARR: - if (CIRBUF_IS_EMPTY(&rdl->left)) - break; - tmp = cirbuf_get_tail(&rdl->left); - cirbuf_del_tail(&rdl->left); - cirbuf_add_head(&rdl->right, tmp); - rdline_puts(rdl, vt100_left_arr); - break; - - /* move caret 1 char to the right */ - case CMDLINE_KEY_CTRL_F: - case CMDLINE_KEY_RIGHT_ARR: - if (CIRBUF_IS_EMPTY(&rdl->right)) - break; - tmp = cirbuf_get_head(&rdl->right); - cirbuf_del_head(&rdl->right); - cirbuf_add_tail(&rdl->left, tmp); - rdline_puts(rdl, vt100_right_arr); - break; - - /* move caret 1 word to the left */ - /* keyboard equivalent: Alt+B */ - case CMDLINE_KEY_WLEFT: - while (! CIRBUF_IS_EMPTY(&rdl->left) && - (tmp = cirbuf_get_tail(&rdl->left)) && - isblank2(tmp)) { - rdline_puts(rdl, vt100_left_arr); - cirbuf_del_tail(&rdl->left); - cirbuf_add_head(&rdl->right, tmp); - } - while (! CIRBUF_IS_EMPTY(&rdl->left) && - (tmp = cirbuf_get_tail(&rdl->left)) && - !isblank2(tmp)) { - rdline_puts(rdl, vt100_left_arr); - cirbuf_del_tail(&rdl->left); - cirbuf_add_head(&rdl->right, tmp); - } - break; - - /* move caret 1 word to the right */ - /* keyboard equivalent: Alt+F */ - case CMDLINE_KEY_WRIGHT: - while (! CIRBUF_IS_EMPTY(&rdl->right) && - (tmp = cirbuf_get_head(&rdl->right)) && - isblank2(tmp)) { - rdline_puts(rdl, vt100_right_arr); - cirbuf_del_head(&rdl->right); - cirbuf_add_tail(&rdl->left, tmp); - } - while (! CIRBUF_IS_EMPTY(&rdl->right) && - (tmp = cirbuf_get_head(&rdl->right)) && - !isblank2(tmp)) { - rdline_puts(rdl, vt100_right_arr); - cirbuf_del_head(&rdl->right); - cirbuf_add_tail(&rdl->left, tmp); - } - break; - - /* move caret to the left */ - case CMDLINE_KEY_CTRL_A: - if (CIRBUF_IS_EMPTY(&rdl->left)) - break; - rdline_miniprintf(rdl, vt100_multi_left, - CIRBUF_GET_LEN(&rdl->left)); - while (! CIRBUF_IS_EMPTY(&rdl->left)) { - tmp = cirbuf_get_tail(&rdl->left); - cirbuf_del_tail(&rdl->left); - cirbuf_add_head(&rdl->right, tmp); - } - break; - - /* move caret to the right */ - case CMDLINE_KEY_CTRL_E: - if (CIRBUF_IS_EMPTY(&rdl->right)) - break; - rdline_miniprintf(rdl, vt100_multi_right, - CIRBUF_GET_LEN(&rdl->right)); - while (! CIRBUF_IS_EMPTY(&rdl->right)) { - tmp = cirbuf_get_head(&rdl->right); - cirbuf_del_head(&rdl->right); - cirbuf_add_tail(&rdl->left, tmp); - } - break; - - /* delete 1 char from the left */ - case CMDLINE_KEY_BKSPACE: - case CMDLINE_KEY_BKSPACE2: - if(!cirbuf_del_tail_safe(&rdl->left)) { - rdline_puts(rdl, vt100_bs); - display_right_buffer(rdl, 1); - } - break; - - /* delete 1 char from the right */ - case CMDLINE_KEY_SUPPR: - case CMDLINE_KEY_CTRL_D: - if (cmd == CMDLINE_KEY_CTRL_D && - CIRBUF_IS_EMPTY(&rdl->left) && - CIRBUF_IS_EMPTY(&rdl->right)) { - return RDLINE_RES_EOF; - } - if (!cirbuf_del_head_safe(&rdl->right)) { - display_right_buffer(rdl, 1); - } - break; - - /* delete 1 word from the left */ - case CMDLINE_KEY_META_BKSPACE: - case CMDLINE_KEY_CTRL_W: - while (! CIRBUF_IS_EMPTY(&rdl->left) && isblank2(cirbuf_get_tail(&rdl->left))) { - rdline_puts(rdl, vt100_bs); - cirbuf_del_tail(&rdl->left); - } - while (! CIRBUF_IS_EMPTY(&rdl->left) && !isblank2(cirbuf_get_tail(&rdl->left))) { - rdline_puts(rdl, vt100_bs); - cirbuf_del_tail(&rdl->left); - } - display_right_buffer(rdl, 1); - break; - - /* delete 1 word from the right */ - case CMDLINE_KEY_META_D: - while (! CIRBUF_IS_EMPTY(&rdl->right) && isblank2(cirbuf_get_head(&rdl->right))) - cirbuf_del_head(&rdl->right); - while (! CIRBUF_IS_EMPTY(&rdl->right) && !isblank2(cirbuf_get_head(&rdl->right))) - cirbuf_del_head(&rdl->right); - display_right_buffer(rdl, 1); - break; - - /* set kill buffer to contents on the right side of caret */ - case CMDLINE_KEY_CTRL_K: - cirbuf_get_buf_head(&rdl->right, rdl->kill_buf, RDLINE_BUF_SIZE); - rdl->kill_size = CIRBUF_GET_LEN(&rdl->right); - cirbuf_del_buf_head(&rdl->right, rdl->kill_size); - rdline_puts(rdl, vt100_clear_right); - break; - - /* paste contents of kill buffer to the left side of caret */ - case CMDLINE_KEY_CTRL_Y: - i=0; - while(CIRBUF_GET_LEN(&rdl->right) + CIRBUF_GET_LEN(&rdl->left) < - RDLINE_BUF_SIZE && - i < rdl->kill_size) { - cirbuf_add_tail(&rdl->left, rdl->kill_buf[i]); - rdl->write_char(rdl, rdl->kill_buf[i]); - i++; - } - display_right_buffer(rdl, 0); - break; - - /* clear and newline */ - case CMDLINE_KEY_CTRL_C: - rdline_puts(rdl, "\r\n"); - rdline_newline(rdl, rdl->prompt); - break; - - /* redisplay (helps when prompt is lost in other output) */ - case CMDLINE_KEY_CTRL_L: - rdline_redisplay(rdl); - break; - - /* autocomplete */ - case CMDLINE_KEY_TAB: - case CMDLINE_KEY_HELP: - cirbuf_align_left(&rdl->left); - rdl->left_buf[CIRBUF_GET_LEN(&rdl->left)] = '\0'; - if (rdl->complete) { - char tmp_buf[BUFSIZ]; - int complete_state; - int ret; - unsigned int tmp_size; - - if (cmd == CMDLINE_KEY_TAB) - complete_state = 0; - else - complete_state = -1; - - /* see in parse.h for help on complete() */ - ret = rdl->complete(rdl, rdl->left_buf, - tmp_buf, sizeof(tmp_buf), - &complete_state); - /* no completion or error */ - if (ret <= 0) { - return RDLINE_RES_COMPLETE; - } - - tmp_size = strnlen(tmp_buf, sizeof(tmp_buf)); - /* add chars */ - if (ret == RDLINE_RES_COMPLETE) { - i=0; - while(CIRBUF_GET_LEN(&rdl->right) + CIRBUF_GET_LEN(&rdl->left) < - RDLINE_BUF_SIZE && - i < tmp_size) { - cirbuf_add_tail(&rdl->left, tmp_buf[i]); - rdl->write_char(rdl, tmp_buf[i]); - i++; - } - display_right_buffer(rdl, 1); - return RDLINE_RES_COMPLETE; /* ?? */ - } - - /* choice */ - rdline_puts(rdl, "\r\n"); - while (ret) { - rdl->write_char(rdl, ' '); - for (i=0 ; tmp_buf[i] ; i++) - rdl->write_char(rdl, tmp_buf[i]); - rdline_puts(rdl, "\r\n"); - ret = rdl->complete(rdl, rdl->left_buf, - tmp_buf, sizeof(tmp_buf), - &complete_state); - } - - rdline_redisplay(rdl); - } - return RDLINE_RES_COMPLETE; - - /* complete buffer */ - case CMDLINE_KEY_RETURN: - case CMDLINE_KEY_RETURN2: - rdline_get_buffer(rdl); - rdl->status = RDLINE_INIT; - rdline_puts(rdl, "\r\n"); - if (rdl->history_cur_line != -1) - rdline_remove_first_history_item(rdl); - - if (rdl->validate) - rdl->validate(rdl, rdl->left_buf, CIRBUF_GET_LEN(&rdl->left)+2); - /* user may have stopped rdline */ - if (rdl->status == RDLINE_EXITED) - return RDLINE_RES_EXITED; - return RDLINE_RES_VALIDATED; - - /* previous element in history */ - case CMDLINE_KEY_UP_ARR: - case CMDLINE_KEY_CTRL_P: - if (rdl->history_cur_line == 0) { - rdline_remove_first_history_item(rdl); - } - if (rdl->history_cur_line <= 0) { - rdline_add_history(rdl, rdline_get_buffer(rdl)); - rdl->history_cur_line = 0; - } - - buf = rdline_get_history_item(rdl, rdl->history_cur_line + 1); - if (!buf) - break; - - rdl->history_cur_line ++; - vt100_init(&rdl->vt100); - cirbuf_init(&rdl->left, rdl->left_buf, 0, RDLINE_BUF_SIZE); - cirbuf_init(&rdl->right, rdl->right_buf, 0, RDLINE_BUF_SIZE); - cirbuf_add_buf_tail(&rdl->left, buf, strnlen(buf, RDLINE_BUF_SIZE)); - rdline_redisplay(rdl); - break; - - /* next element in history */ - case CMDLINE_KEY_DOWN_ARR: - case CMDLINE_KEY_CTRL_N: - if (rdl->history_cur_line - 1 < 0) - break; - - rdl->history_cur_line --; - buf = rdline_get_history_item(rdl, rdl->history_cur_line); - if (!buf) - break; - vt100_init(&rdl->vt100); - cirbuf_init(&rdl->left, rdl->left_buf, 0, RDLINE_BUF_SIZE); - cirbuf_init(&rdl->right, rdl->right_buf, 0, RDLINE_BUF_SIZE); - cirbuf_add_buf_tail(&rdl->left, buf, strnlen(buf, RDLINE_BUF_SIZE)); - rdline_redisplay(rdl); - - break; - - - default: - break; - } - - return RDLINE_RES_SUCCESS; - } - - if (!isprint((int)c)) - return RDLINE_RES_SUCCESS; - - /* standard chars */ - if (CIRBUF_GET_LEN(&rdl->left) + CIRBUF_GET_LEN(&rdl->right) >= RDLINE_BUF_SIZE) - return RDLINE_RES_SUCCESS; - - if (cirbuf_add_tail_safe(&rdl->left, c)) - return RDLINE_RES_SUCCESS; - - rdl->write_char(rdl, c); - display_right_buffer(rdl, 0); - - return RDLINE_RES_SUCCESS; -} - - -/* HISTORY */ - -static void -rdline_remove_old_history_item(struct rdline * rdl) -{ - char tmp; - - while (! CIRBUF_IS_EMPTY(&rdl->history) ) { - tmp = cirbuf_get_head(&rdl->history); - cirbuf_del_head(&rdl->history); - if (!tmp) - break; - } -} - -static void -rdline_remove_first_history_item(struct rdline * rdl) -{ - char tmp; - - if ( CIRBUF_IS_EMPTY(&rdl->history) ) { - return; - } - else { - cirbuf_del_tail(&rdl->history); - } - - while (! CIRBUF_IS_EMPTY(&rdl->history) ) { - tmp = cirbuf_get_tail(&rdl->history); - if (!tmp) - break; - cirbuf_del_tail(&rdl->history); - } -} - -static unsigned int -rdline_get_history_size(struct rdline * rdl) -{ - unsigned int i, tmp, ret=0; - - CIRBUF_FOREACH(&rdl->history, i, tmp) { - if (tmp == 0) - ret ++; - } - - return ret; -} - -char * -rdline_get_history_item(struct rdline * rdl, unsigned int idx) -{ - unsigned int len, i, tmp; - - if (!rdl) - return NULL; - - len = rdline_get_history_size(rdl); - if ( idx >= len ) { - return NULL; - } - - cirbuf_align_left(&rdl->history); - - CIRBUF_FOREACH(&rdl->history, i, tmp) { - if ( idx == len - 1) { - return rdl->history_buf + i; - } - if (tmp == 0) - len --; - } - - return NULL; -} - -int -rdline_add_history(struct rdline * rdl, const char * buf) -{ - unsigned int len, i; - - if (!rdl || !buf) - return -EINVAL; - - len = strnlen(buf, RDLINE_BUF_SIZE); - for (i=0; i<len ; i++) { - if (buf[i] == '\n') { - len = i; - break; - } - } - - if ( len >= RDLINE_HISTORY_BUF_SIZE ) - return -1; - - while ( len >= CIRBUF_GET_FREELEN(&rdl->history) ) { - rdline_remove_old_history_item(rdl); - } - - cirbuf_add_buf_tail(&rdl->history, buf, len); - cirbuf_add_tail(&rdl->history, 0); - - return 0; -} - -void -rdline_clear_history(struct rdline * rdl) -{ - if (!rdl) - return; - cirbuf_init(&rdl->history, rdl->history_buf, 0, RDLINE_HISTORY_BUF_SIZE); -} - - -/* STATIC USEFUL FUNCS */ - -static void -rdline_puts(struct rdline * rdl, const char * buf) -{ - char c; - while ( (c = *(buf++)) != '\0' ) { - rdl->write_char(rdl, c); - } -} - -/* a very very basic printf with one arg and one format 'u' */ -static void -rdline_miniprintf(struct rdline *rdl, const char * buf, unsigned int val) -{ - char c, started=0, div=100; - - while ( (c=*(buf++)) ) { - if (c != '%') { - rdl->write_char(rdl, c); - continue; - } - c = *(buf++); - if (c != 'u') { - rdl->write_char(rdl, '%'); - rdl->write_char(rdl, c); - continue; - } - /* val is never more than 255 */ - while (div) { - c = (char)(val / div); - if (c || started) { - rdl->write_char(rdl, (char)(c+'0')); - started = 1; - } - val %= div; - div /= 10; - } - } -} diff --git a/lib/librte_cmdline/cmdline_rdline.h b/lib/librte_cmdline/cmdline_rdline.h deleted file mode 100644 index d2170293d..000000000 --- a/lib/librte_cmdline/cmdline_rdline.h +++ /dev/null @@ -1,201 +0,0 @@ -/* SPDX-License-Identifier: BSD-3-Clause - * Copyright(c) 2010-2014 Intel Corporation. - * Copyright (c) 2009, Olivier MATZ <zer0@droids-corp.org> - * All rights reserved. - */ - -#ifndef _RDLINE_H_ -#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. - * - * Obviously, it does not support as many things as the GNU readline, - * but at least it supports some interesting 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. - */ - -#include <stdio.h> -#include <cmdline_cirbuf.h> -#include <cmdline_vt100.h> - -#ifdef __cplusplus -extern "C" { -#endif - -/* configuration */ -#define RDLINE_BUF_SIZE 512 -#define RDLINE_PROMPT_SIZE 32 -#define RDLINE_VT100_BUF_SIZE 8 -#define RDLINE_HISTORY_BUF_SIZE BUFSIZ -#define RDLINE_HISTORY_MAX_LINE 64 - -enum rdline_status { - RDLINE_INIT, - RDLINE_RUNNING, - RDLINE_EXITED -}; - -struct rdline; - -typedef int (rdline_write_char_t)(struct rdline *rdl, char); -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); - -struct rdline { - enum rdline_status status; - /* rdline bufs */ - struct cirbuf left; - struct cirbuf right; - char left_buf[RDLINE_BUF_SIZE+2]; /* reserve 2 chars for the \n\0 */ - char right_buf[RDLINE_BUF_SIZE]; - - char prompt[RDLINE_PROMPT_SIZE]; - unsigned int prompt_size; - - char kill_buf[RDLINE_BUF_SIZE]; - unsigned int kill_size; - - /* history */ - struct cirbuf history; - char history_buf[RDLINE_HISTORY_BUF_SIZE]; - int history_cur_line; - - /* callbacks and func pointers */ - rdline_write_char_t *write_char; - rdline_validate_t *validate; - rdline_complete_t *complete; - - /* vt100 parser */ - struct cmdline_vt100 vt100; - - /* opaque pointer */ - void *opaque; -}; - -/** - * 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. - */ -int rdline_init(struct rdline *rdl, - rdline_write_char_t *write_char, - rdline_validate_t *validate, - rdline_complete_t *complete); - - -/** - * Init the current buffer, and display a prompt. - * \param rdl A pointer to a 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 - */ -void rdline_stop(struct rdline *rdl); - -/** - * Same than rdline_stop() except that next calls to rdline_char_in() - * will return RDLINE_RES_EXITED. - * \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 - */ -void rdline_redisplay(struct rdline *rdl); - -/** - * Reset the current buffer and setup for a new line. - * \param rdl A pointer to a struct rdline - */ -void rdline_reset(struct rdline *rdl); - - -/* return status for rdline_char_in() */ -#define RDLINE_RES_SUCCESS 0 -#define RDLINE_RES_VALIDATED 1 -#define RDLINE_RES_COMPLETE 2 -#define RDLINE_RES_NOT_RUNNING -1 -#define RDLINE_RES_EOF -2 -#define RDLINE_RES_EXITED -3 - -/** - * append a char to the readline buffer. - * Return RDLINE_RES_VALIDATE when the line has been validated. - * Return RDLINE_RES_COMPLETE when the user asked to complete the buffer. - * Return RDLINE_RES_NOT_RUNNING if it is not running. - * Return RDLINE_RES_EOF if EOF (ctrl-d on an empty line). - * Else return RDLINE_RES_SUCCESS. - * XXX error case when the buffer is full ? - * - * \param rdl A pointer to a struct rdline - * \param c The character to append - */ -int rdline_char_in(struct rdline *rdl, char c); - -/** - * Return the current buffer, terminated by '\0'. - * \param rdl A pointer to a struct rdline - */ -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' - */ -int rdline_add_history(struct rdline *rdl, const char *buf); - -/** - * Clear current history - * \param rdl A pointer to a struct rdline - */ -void rdline_clear_history(struct rdline *rdl); - -/** - * Get the i-th history item - */ -char *rdline_get_history_item(struct rdline *rdl, unsigned int i); - -#ifdef __cplusplus -} -#endif - -#endif /* _RDLINE_H_ */ diff --git a/lib/librte_cmdline/cmdline_socket.c b/lib/librte_cmdline/cmdline_socket.c index ecb3d82b6..f639c61cb 100644 --- a/lib/librte_cmdline/cmdline_socket.c +++ b/lib/librte_cmdline/cmdline_socket.c @@ -4,23 +4,18 @@ * All rights reserved. */ -#include <stdio.h> -#include <string.h> +#include <stddef.h> #include <unistd.h> -#include <stdlib.h> -#include <stdarg.h> -#include <inttypes.h> #include <fcntl.h> -#include <termios.h> #include "cmdline_parse.h" -#include "cmdline_rdline.h" #include "cmdline_socket.h" #include "cmdline.h" struct cmdline * cmdline_file_new(cmdline_parse_ctx_t *ctx, const char *prompt, const char *path) { + struct cmdline *cl; int fd; /* everything else is checked in cmdline_new() */ @@ -29,37 +24,22 @@ cmdline_file_new(cmdline_parse_ctx_t *ctx, const char *prompt, const char *path) fd = open(path, O_RDONLY, 0); if (fd < 0) { - dprintf("open() failed\n"); return NULL; } - return cmdline_new(ctx, prompt, fd, -1); + cl = cmdline_new(ctx, prompt, fd, -1); + /* cmdline_new() duplicates fd */ + close(fd); + return cl; } struct cmdline * cmdline_stdin_new(cmdline_parse_ctx_t *ctx, const char *prompt) { - struct cmdline *cl; - struct termios oldterm, term; - - tcgetattr(0, &oldterm); - memcpy(&term, &oldterm, sizeof(term)); - term.c_lflag &= ~(ICANON | ECHO | ISIG); - tcsetattr(0, TCSANOW, &term); - setbuf(stdin, NULL); - - cl = cmdline_new(ctx, prompt, 0, 1); - - if (cl) - memcpy(&cl->oldterm, &oldterm, sizeof(term)); - - return cl; + return cmdline_new(ctx, prompt, 0, 1); } void cmdline_stdin_exit(struct cmdline *cl) { - if (!cl) - return; - - tcsetattr(fileno(stdin), TCSANOW, &cl->oldterm); + cmdline_free(cl); } diff --git a/lib/librte_cmdline/cmdline_vt100.c b/lib/librte_cmdline/cmdline_vt100.c deleted file mode 100644 index 662fc7345..000000000 --- a/lib/librte_cmdline/cmdline_vt100.c +++ /dev/null @@ -1,132 +0,0 @@ -/* SPDX-License-Identifier: BSD-3-Clause - * Copyright(c) 2010-2014 Intel Corporation. - * Copyright (c) 2009, Olivier MATZ <zer0@droids-corp.org> - * All rights reserved. - */ - -#include <stdlib.h> -#include <stdint.h> -#include <stdio.h> -#include <string.h> -#include <stdarg.h> -#include <ctype.h> -#include <termios.h> - -#include "cmdline_vt100.h" - -const char *cmdline_vt100_commands[] = { - vt100_up_arr, - vt100_down_arr, - vt100_right_arr, - vt100_left_arr, - "\177", - "\n", - "\001", - "\005", - "\013", - "\031", - "\003", - "\006", - "\002", - vt100_suppr, - vt100_tab, - "\004", - "\014", - "\r", - "\033\177", - vt100_word_left, - vt100_word_right, - "?", - "\027", - "\020", - "\016", - "\033\144", - vt100_bs, -}; - -void -vt100_init(struct cmdline_vt100 *vt) -{ - if (!vt) - return; - vt->state = CMDLINE_VT100_INIT; -} - - -static int -match_command(char *buf, unsigned int size) -{ - const char *cmd; - size_t cmdlen; - unsigned int i = 0; - - for (i=0 ; i<sizeof(cmdline_vt100_commands)/sizeof(const char *) ; i++) { - cmd = *(cmdline_vt100_commands + i); - - cmdlen = strnlen(cmd, CMDLINE_VT100_BUF_SIZE); - if (size == cmdlen && - !strncmp(buf, cmd, cmdlen)) { - return i; - } - } - - return -1; -} - -int -vt100_parser(struct cmdline_vt100 *vt, char ch) -{ - unsigned int size; - uint8_t c = (uint8_t) ch; - - if (!vt) - return -1; - - if (vt->bufpos >= CMDLINE_VT100_BUF_SIZE) { - vt->state = CMDLINE_VT100_INIT; - vt->bufpos = 0; - } - - vt->buf[vt->bufpos++] = c; - size = vt->bufpos; - - switch (vt->state) { - case CMDLINE_VT100_INIT: - if (c == 033) { - vt->state = CMDLINE_VT100_ESCAPE; - } - else { - vt->bufpos = 0; - goto match_command; - } - break; - - case CMDLINE_VT100_ESCAPE: - if (c == 0133) { - vt->state = CMDLINE_VT100_ESCAPE_CSI; - } - else if (c >= 060 && c <= 0177) { /* XXX 0177 ? */ - vt->bufpos = 0; - vt->state = CMDLINE_VT100_INIT; - goto match_command; - } - break; - - case CMDLINE_VT100_ESCAPE_CSI: - if (c >= 0100 && c <= 0176) { - vt->bufpos = 0; - vt->state = CMDLINE_VT100_INIT; - goto match_command; - } - break; - - default: - vt->bufpos = 0; - break; - } - - return -2; - - match_command: - return match_command(vt->buf, size); -} diff --git a/lib/librte_cmdline/cmdline_vt100.h b/lib/librte_cmdline/cmdline_vt100.h deleted file mode 100644 index e33e67ed8..000000000 --- a/lib/librte_cmdline/cmdline_vt100.h +++ /dev/null @@ -1,100 +0,0 @@ -/* SPDX-License-Identifier: BSD-3-Clause - * Copyright(c) 2010-2014 Intel Corporation. - * Copyright (c) 2009, Olivier MATZ <zer0@droids-corp.org> - * All rights reserved. - */ - -#ifndef _CMDLINE_VT100_H_ -#define _CMDLINE_VT100_H_ - -#include <stdint.h> - -#ifdef __cplusplus -extern "C" { -#endif - -#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" - -/* Result of parsing : it must be synchronized with - * cmdline_vt100_commands[] in vt100.c */ -#define CMDLINE_KEY_UP_ARR 0 -#define CMDLINE_KEY_DOWN_ARR 1 -#define CMDLINE_KEY_RIGHT_ARR 2 -#define CMDLINE_KEY_LEFT_ARR 3 -#define CMDLINE_KEY_BKSPACE 4 -#define CMDLINE_KEY_RETURN 5 -#define CMDLINE_KEY_CTRL_A 6 -#define CMDLINE_KEY_CTRL_E 7 -#define CMDLINE_KEY_CTRL_K 8 -#define CMDLINE_KEY_CTRL_Y 9 -#define CMDLINE_KEY_CTRL_C 10 -#define CMDLINE_KEY_CTRL_F 11 -#define CMDLINE_KEY_CTRL_B 12 -#define CMDLINE_KEY_SUPPR 13 -#define CMDLINE_KEY_TAB 14 -#define CMDLINE_KEY_CTRL_D 15 -#define CMDLINE_KEY_CTRL_L 16 -#define CMDLINE_KEY_RETURN2 17 -#define CMDLINE_KEY_META_BKSPACE 18 -#define CMDLINE_KEY_WLEFT 19 -#define CMDLINE_KEY_WRIGHT 20 -#define CMDLINE_KEY_HELP 21 -#define CMDLINE_KEY_CTRL_W 22 -#define CMDLINE_KEY_CTRL_P 23 -#define CMDLINE_KEY_CTRL_N 24 -#define CMDLINE_KEY_META_D 25 -#define CMDLINE_KEY_BKSPACE2 26 - -extern const char *cmdline_vt100_commands[]; - -enum cmdline_vt100_parser_state { - CMDLINE_VT100_INIT, - CMDLINE_VT100_ESCAPE, - CMDLINE_VT100_ESCAPE_CSI -}; - -#define CMDLINE_VT100_BUF_SIZE 8 -struct cmdline_vt100 { - uint8_t bufpos; - char buf[CMDLINE_VT100_BUF_SIZE]; - enum cmdline_vt100_parser_state state; -}; - -/** - * Init - */ -void vt100_init(struct cmdline_vt100 *vt); - -/** - * Input a new character. - * Return -1 if the character is not part of a control sequence - * Return -2 if c is not the last char of a control sequence - * Else return the index in vt100_commands[] - */ -int vt100_parser(struct cmdline_vt100 *vt, char c); - -#ifdef __cplusplus -} -#endif - -#endif diff --git a/lib/librte_cmdline/meson.build b/lib/librte_cmdline/meson.build index 5741817ac..1735737c7 100644 --- a/lib/librte_cmdline/meson.build +++ b/lib/librte_cmdline/meson.build @@ -1,18 +1,15 @@ # SPDX-License-Identifier: BSD-3-Clause # Copyright(c) 2017 Intel Corporation -version = 2 +version = 3 sources = files('cmdline.c', - 'cmdline_cirbuf.c', 'cmdline_parse.c', 'cmdline_parse_etheraddr.c', 'cmdline_parse_ipaddr.c', 'cmdline_parse_num.c', 'cmdline_parse_portlist.c', 'cmdline_parse_string.c', - 'cmdline_rdline.c', - 'cmdline_socket.c', - 'cmdline_vt100.c') + 'cmdline_socket.c') headers = files('cmdline.h', 'cmdline_parse.h', @@ -20,8 +17,13 @@ headers = files('cmdline.h', 'cmdline_parse_ipaddr.h', 'cmdline_parse_etheraddr.h', 'cmdline_parse_string.h', - 'cmdline_rdline.h', - 'cmdline_vt100.h', 'cmdline_socket.h', - 'cmdline_cirbuf.h', 'cmdline_parse_portlist.h') + +cmdline_dep = dependency('libedit', required: false) +if cmdline_dep.found() + ext_deps += cmdline_dep + dpdk_extra_ldflags += '-ledit' +else + build = false +endif diff --git a/lib/librte_cmdline/rte_cmdline_version.map b/lib/librte_cmdline/rte_cmdline_version.map index 04bcb387f..31331995b 100644 --- a/lib/librte_cmdline/rte_cmdline_version.map +++ b/lib/librte_cmdline/rte_cmdline_version.map @@ -1,25 +1,6 @@ DPDK_2.0 { global: - cirbuf_add_buf_head; - cirbuf_add_buf_tail; - cirbuf_add_head; - cirbuf_add_head_safe; - cirbuf_add_tail; - cirbuf_add_tail_safe; - cirbuf_align_left; - cirbuf_align_right; - cirbuf_del_buf_head; - cirbuf_del_buf_tail; - cirbuf_del_head; - cirbuf_del_head_safe; - cirbuf_del_tail; - cirbuf_del_tail_safe; - cirbuf_get_buf_head; - cirbuf_get_buf_tail; - cirbuf_get_head; - cirbuf_get_tail; - cirbuf_init; cmdline_complete; cmdline_complete_get_elt_string; cmdline_complete_get_nb_string; @@ -50,21 +31,6 @@ DPDK_2.0 { cmdline_token_num_ops; cmdline_token_portlist_ops; cmdline_token_string_ops; - cmdline_write_char; - rdline_add_history; - rdline_char_in; - rdline_clear_history; - rdline_get_buffer; - rdline_get_history_item; - rdline_init; - rdline_newline; - rdline_quit; - rdline_redisplay; - rdline_reset; - rdline_restart; - rdline_stop; - vt100_init; - vt100_parser; local: *; }; @@ -75,3 +41,10 @@ DPDK_2.1 { cmdline_poll; } DPDK_2.0; + +DPDK_18.02 { + global: + + cmdline_ctx_get; + +} DPDK_2.1; diff --git a/mk/rte.app.mk b/mk/rte.app.mk index 8bab901fc..f66411eba 100644 --- a/mk/rte.app.mk +++ b/mk/rte.app.mk @@ -104,6 +104,8 @@ _LDLIBS-$(CONFIG_RTE_LIBRTE_RING) += -lrte_ring _LDLIBS-$(CONFIG_RTE_LIBRTE_PCI) += -lrte_pci _LDLIBS-$(CONFIG_RTE_LIBRTE_EAL) += -lrte_eal _LDLIBS-$(CONFIG_RTE_LIBRTE_CMDLINE) += -lrte_cmdline + +_LDLIBS-$(CONFIG_RTE_LIBRTE_CMDLINE) += $(shell pkg-config --libs libedit) _LDLIBS-$(CONFIG_RTE_LIBRTE_REORDER) += -lrte_reorder _LDLIBS-$(CONFIG_RTE_LIBRTE_SCHED) += -lrte_sched diff --git a/test/cmdline_test/cmdline_test.c b/test/cmdline_test/cmdline_test.c index 3e406331a..e46b66d0c 100644 --- a/test/cmdline_test/cmdline_test.c +++ b/test/cmdline_test/cmdline_test.c @@ -12,7 +12,6 @@ #include <ctype.h> #include <sys/queue.h> -#include <cmdline_rdline.h> #include <cmdline_parse.h> #include <cmdline_socket.h> #include <cmdline.h> diff --git a/test/cmdline_test/commands.c b/test/cmdline_test/commands.c index d81da9665..2bf0262f6 100644 --- a/test/cmdline_test/commands.c +++ b/test/cmdline_test/commands.c @@ -7,7 +7,6 @@ #include <termios.h> #include <inttypes.h> -#include <cmdline_rdline.h> #include <cmdline_parse.h> #include <cmdline_parse_string.h> #include <cmdline_parse_num.h> @@ -277,72 +276,6 @@ cmdline_parse_inst_t cmd_ambig_2 = { -/*** get_history_bufsize ***/ -/* command that displays total space in history buffer - * this will be useful for testing history (to fill it up just enough to - * remove the last entry, we need to know how big it is). - */ - -struct cmd_get_history_bufsize_result { - cmdline_fixed_string_t str; -}; - -static void -cmd_get_history_bufsize_parsed(__attribute__((unused)) void *parsed_result, - struct cmdline *cl, - __attribute__((unused)) void *data) -{ - cmdline_printf(cl, "History buffer size: %zu\n", - sizeof(cl->rdl.history_buf)); -} - -cmdline_parse_token_string_t cmd_get_history_bufsize_tok = - TOKEN_STRING_INITIALIZER(struct cmd_get_history_bufsize_result, str, - "get_history_bufsize"); - -cmdline_parse_inst_t cmd_get_history_bufsize = { - .f = cmd_get_history_bufsize_parsed, /* function to call */ - .data = NULL, /* 2nd arg of func */ - .help_str = "command that displays total space in history buffer", - .tokens = { /* token list, NULL terminated */ - (void *)&cmd_get_history_bufsize_tok, - NULL, - }, -}; - - - -/*** clear_history ***/ -/* clears history buffer */ - -struct cmd_clear_history_result { - cmdline_fixed_string_t str; -}; - -static void -cmd_clear_history_parsed(__attribute__((unused)) void *parsed_result, - struct cmdline *cl, - __attribute__((unused)) void *data) -{ - rdline_clear_history(&cl->rdl); -} - -cmdline_parse_token_string_t cmd_clear_history_tok = - TOKEN_STRING_INITIALIZER(struct cmd_clear_history_result, str, - "clear_history"); - -cmdline_parse_inst_t cmd_clear_history = { - .f = cmd_clear_history_parsed, /* function to call */ - .data = NULL, /* 2nd arg of func */ - .help_str = "clear command history", - .tokens = { /* token list, NULL terminated */ - (void *)&cmd_clear_history_tok, - NULL, - }, -}; - - - /****************/ cmdline_parse_ctx_t main_ctx[] = { @@ -352,8 +285,6 @@ cmdline_parse_ctx_t main_ctx[] = { (cmdline_parse_inst_t *)&cmd_single, (cmdline_parse_inst_t *)&cmd_single_long, (cmdline_parse_inst_t *)&cmd_num, - (cmdline_parse_inst_t *)&cmd_get_history_bufsize, - (cmdline_parse_inst_t *)&cmd_clear_history, (cmdline_parse_inst_t *)&cmd_autocomplete_1, (cmdline_parse_inst_t *)&cmd_autocomplete_2, NULL, diff --git a/test/test/Makefile b/test/test/Makefile index c9c007c9b..08cc04277 100644 --- a/test/test/Makefile +++ b/test/test/Makefile @@ -139,7 +139,6 @@ SRCS-$(CONFIG_RTE_LIBRTE_CMDLINE) += test_cmdline_num.c SRCS-$(CONFIG_RTE_LIBRTE_CMDLINE) += test_cmdline_etheraddr.c SRCS-$(CONFIG_RTE_LIBRTE_CMDLINE) += test_cmdline_portlist.c SRCS-$(CONFIG_RTE_LIBRTE_CMDLINE) += test_cmdline_ipaddr.c -SRCS-$(CONFIG_RTE_LIBRTE_CMDLINE) += test_cmdline_cirbuf.c SRCS-$(CONFIG_RTE_LIBRTE_CMDLINE) += test_cmdline_string.c SRCS-$(CONFIG_RTE_LIBRTE_CMDLINE) += test_cmdline_lib.c diff --git a/test/test/commands.c b/test/test/commands.c index 6bfdc0272..7e5357b93 100644 --- a/test/test/commands.c +++ b/test/test/commands.c @@ -38,7 +38,6 @@ #include <rte_mbuf.h> #include <rte_devargs.h> -#include <cmdline_rdline.h> #include <cmdline_parse.h> #include <cmdline_parse_ipaddr.h> #include <cmdline_parse_num.h> diff --git a/test/test/meson.build b/test/test/meson.build index eb3d87a4d..d5bfdccf3 100644 --- a/test/test/meson.build +++ b/test/test/meson.build @@ -10,7 +10,6 @@ test_sources = files('commands.c', 'test_barrier.c', 'test_byteorder.c', 'test_cmdline.c', - 'test_cmdline_cirbuf.c', 'test_cmdline_etheraddr.c', 'test_cmdline_ipaddr.c', 'test_cmdline_lib.c', diff --git a/test/test/test.c b/test/test/test.c index 44dfe20ef..802e8079b 100644 --- a/test/test/test.c +++ b/test/test/test.c @@ -13,7 +13,6 @@ #include <sys/queue.h> #ifdef RTE_LIBRTE_CMDLINE -#include <cmdline_rdline.h> #include <cmdline_parse.h> #include <cmdline_socket.h> #include <cmdline.h> diff --git a/test/test/test_cmdline.c b/test/test/test_cmdline.c index 115bee966..eef219a93 100644 --- a/test/test/test_cmdline.c +++ b/test/test/test_cmdline.c @@ -45,15 +45,6 @@ test_cmdline(void) return -1; if (test_parse_string_invalid_param() < 0) return -1; - printf("Testing circular buffer...\n"); - if (test_cirbuf_char() < 0) - return -1; - if (test_cirbuf_string() < 0) - return -1; - if (test_cirbuf_align() < 0) - return -1; - if (test_cirbuf_invalid_param() < 0) - return -1; printf("Testing library functions...\n"); if (test_cmdline_lib() < 0) return -1; diff --git a/test/test/test_cmdline.h b/test/test/test_cmdline.h index 1854caf8f..2fb45b3d4 100644 --- a/test/test/test_cmdline.h +++ b/test/test/test_cmdline.h @@ -32,12 +32,6 @@ int test_parse_string_valid(void); int test_parse_string_invalid_data(void); int test_parse_string_invalid_param(void); -/* cmdline_cirbuf tests */ -int test_cirbuf_invalid_param(void); -int test_cirbuf_char(void); -int test_cirbuf_string(void); -int test_cirbuf_align(void); - /* test the rest of the library */ int test_cmdline_lib(void); diff --git a/test/test/test_cmdline_cirbuf.c b/test/test/test_cmdline_cirbuf.c deleted file mode 100644 index 8ac326cb0..000000000 --- a/test/test/test_cmdline_cirbuf.c +++ /dev/null @@ -1,1301 +0,0 @@ -/* SPDX-License-Identifier: BSD-3-Clause - * Copyright(c) 2010-2014 Intel Corporation - */ - -#include <stdio.h> -#include <stdlib.h> -#include <string.h> - -#include <rte_string_fns.h> - -#include <cmdline_cirbuf.h> - -#include "test_cmdline.h" - -/* different length strings */ -#define CIRBUF_STR_HEAD " HEAD" -#define CIRBUF_STR_TAIL "TAIL" - -/* miscellaneous tests - they make bullseye happy */ -static int -test_cirbuf_string_misc(void) -{ - struct cirbuf cb; - char buf[CMDLINE_TEST_BUFSIZE]; - char tmp[CMDLINE_TEST_BUFSIZE]; - - /* initialize buffers */ - memset(buf, 0, sizeof(buf)); - memset(tmp, 0, sizeof(tmp)); - - /* - * initialize circular buffer - */ - if (cirbuf_init(&cb, buf, 0, sizeof(buf)) < 0) { - printf("Error: failed to initialize circular buffer!\n"); - return -1; - } - - /* - * add strings to head and tail, but read only tail - * this results in read operation that does not transcend - * from buffer end to buffer beginning (in other words, - * strlen <= cb->maxlen - cb->end) - */ - - /* add string to head */ - if (cirbuf_add_buf_head(&cb, CIRBUF_STR_HEAD, sizeof(CIRBUF_STR_HEAD)) - != (sizeof(CIRBUF_STR_HEAD))) { - printf("Error: failed to add string to head!\n"); - return -1; - } - /* add string to tail */ - if (cirbuf_add_buf_tail(&cb, CIRBUF_STR_TAIL, sizeof(CIRBUF_STR_TAIL)) - != (sizeof(CIRBUF_STR_TAIL))) { - printf("Error: failed to add string to head!\n"); - return -1; - } - /* read string from tail */ - if (cirbuf_get_buf_tail(&cb, tmp, sizeof(CIRBUF_STR_TAIL)) - != (sizeof(CIRBUF_STR_TAIL))) { - printf("Error: failed to get string from tail!\n"); - return -1; - } - /* verify string */ - if (strncmp(tmp, CIRBUF_STR_TAIL, sizeof(CIRBUF_STR_TAIL)) != 0) { - printf("Error: tail strings do not match!\n"); - return -1; - } - /* clear buffers */ - memset(tmp, 0, sizeof(tmp)); - memset(buf, 0, sizeof(buf)); - - - - /* - * add a string to buffer when start/end is at end of buffer - */ - - /* - * reinitialize circular buffer with start at the end of cirbuf - */ - if (cirbuf_init(&cb, buf, CMDLINE_TEST_BUFSIZE - 2, sizeof(buf)) < 0) { - printf("Error: failed to reinitialize circular buffer!\n"); - return -1; - } - - - /* add string to tail */ - if (cirbuf_add_buf_tail(&cb, CIRBUF_STR_TAIL, sizeof(CIRBUF_STR_TAIL)) - != (sizeof(CIRBUF_STR_TAIL))) { - printf("Error: failed to add string to tail!\n"); - return -1; - } - /* read string from tail */ - if (cirbuf_get_buf_tail(&cb, tmp, sizeof(CIRBUF_STR_TAIL)) - != (sizeof(CIRBUF_STR_TAIL))) { - printf("Error: failed to get string from tail!\n"); - return -1; - } - /* verify string */ - if (strncmp(tmp, CIRBUF_STR_TAIL, sizeof(CIRBUF_STR_TAIL)) != 0) { - printf("Error: tail strings do not match!\n"); - return -1; - } - /* clear tmp buffer */ - memset(tmp, 0, sizeof(tmp)); - - - /* add string to head */ - if (cirbuf_add_buf_head(&cb, CIRBUF_STR_HEAD, sizeof(CIRBUF_STR_HEAD)) - != (sizeof(CIRBUF_STR_HEAD))) { - printf("Error: failed to add string to head!\n"); - return -1; - } - /* read string from tail */ - if (cirbuf_get_buf_head(&cb, tmp, sizeof(CIRBUF_STR_HEAD)) - != (sizeof(CIRBUF_STR_HEAD))) { - printf("Error: failed to get string from head!\n"); - return -1; - } - /* verify string */ - if (strncmp(tmp, CIRBUF_STR_HEAD, sizeof(CIRBUF_STR_HEAD)) != 0) { - printf("Error: headstrings do not match!\n"); - return -1; - } - - return 0; -} - -/* test adding and deleting strings */ -static int -test_cirbuf_string_add_del(void) -{ - struct cirbuf cb; - char buf[CMDLINE_TEST_BUFSIZE]; - char tmp[CMDLINE_TEST_BUFSIZE]; - - /* initialize buffers */ - memset(buf, 0, sizeof(buf)); - memset(tmp, 0, sizeof(tmp)); - - /* - * initialize circular buffer - */ - if (cirbuf_init(&cb, buf, 0, sizeof(buf)) < 0) { - printf("Error: failed to initialize circular buffer!\n"); - return -1; - } - - /* add string to head */ - if (cirbuf_add_buf_head(&cb, CIRBUF_STR_HEAD, sizeof(CIRBUF_STR_HEAD)) - != (sizeof(CIRBUF_STR_HEAD))) { - printf("Error: failed to add string to head!\n"); - return -1; - } - /* read string from head */ - if (cirbuf_get_buf_head(&cb, tmp, sizeof(CIRBUF_STR_HEAD)) - != (sizeof(CIRBUF_STR_HEAD))) { - printf("Error: failed to get string from head!\n"); - return -1; - } - /* verify string */ - if (strncmp(tmp, CIRBUF_STR_HEAD, sizeof(CIRBUF_STR_HEAD)) != 0) { - printf("Error: head strings do not match!\n"); - return -1; - } - /* clear tmp buffer */ - memset(tmp, 0, sizeof(tmp)); - /* read string from tail */ - if (cirbuf_get_buf_tail(&cb, tmp, sizeof(CIRBUF_STR_HEAD)) - != (sizeof(CIRBUF_STR_HEAD))) { - printf("Error: failed to get string from head!\n"); - return -1; - } - /* verify string */ - if (strncmp(tmp, CIRBUF_STR_HEAD, sizeof(CIRBUF_STR_HEAD)) != 0) { - printf("Error: head strings do not match!\n"); - return -1; - } - /* delete string from head*/ - if (cirbuf_del_buf_head(&cb, sizeof(CIRBUF_STR_HEAD)) < 0) { - printf("Error: failed to delete string from head!\n"); - return -1; - } - /* verify string was deleted */ - if (cirbuf_del_head_safe(&cb) == 0) { - printf("Error: buffer should have been empty!\n"); - return -1; - } - /* clear tmp buffer */ - memset(tmp, 0, sizeof(tmp)); - - - - /* - * reinitialize circular buffer - */ - memset(buf, 0, sizeof(buf)); - if (cirbuf_init(&cb, buf, 0, sizeof(buf)) < 0) { - printf("Error: failed to reinitialize circular buffer!\n"); - return -1; - } - - /* add string to tail */ - if (cirbuf_add_buf_tail(&cb, CIRBUF_STR_TAIL, sizeof(CIRBUF_STR_TAIL)) - != (sizeof(CIRBUF_STR_TAIL))) { - printf("Error: failed to add string to tail!\n"); - return -1; - } - /* get string from tail */ - if (cirbuf_get_buf_tail(&cb, tmp, sizeof(CIRBUF_STR_TAIL)) - != (sizeof(CIRBUF_STR_TAIL))) { - printf("Error: failed to get string from tail!\n"); - return -1; - } - /* verify string */ - if (strncmp(tmp, CIRBUF_STR_TAIL, sizeof(CIRBUF_STR_TAIL)) != 0) { - printf("Error: tail strings do not match!\n"); - return -1; - } - /* clear tmp buffer */ - memset(tmp, 0, sizeof(tmp)); - /* get string from head */ - if (cirbuf_get_buf_head(&cb, tmp, sizeof(CIRBUF_STR_TAIL)) - != (sizeof(CIRBUF_STR_TAIL))) { - printf("Error: failed to get string from tail!\n"); - return -1; - } - /* verify string */ - if (strncmp(tmp, CIRBUF_STR_TAIL, sizeof(CIRBUF_STR_TAIL)) != 0) { - printf("Error: tail strings do not match!\n"); - return -1; - } - /* delete string from tail */ - if (cirbuf_del_buf_tail(&cb, sizeof(CIRBUF_STR_TAIL)) < 0) { - printf("Error: failed to delete string from tail!\n"); - return -1; - } - /* verify string was deleted */ - if (cirbuf_del_tail_safe(&cb) == 0) { - printf("Error: buffer should have been empty!\n"); - return -1; - } - - return 0; -} - -/* test adding from head and deleting from tail, and vice versa */ -static int -test_cirbuf_string_add_del_reverse(void) -{ - struct cirbuf cb; - char buf[CMDLINE_TEST_BUFSIZE]; - char tmp[CMDLINE_TEST_BUFSIZE]; - - /* initialize buffers */ - memset(buf, 0, sizeof(buf)); - memset(tmp, 0, sizeof(tmp)); - - /* - * initialize circular buffer - */ - if (cirbuf_init(&cb, buf, 0, sizeof(buf)) < 0) { - printf("Error: failed to initialize circular buffer!\n"); - return -1; - } - - /* add string to head */ - if (cirbuf_add_buf_head(&cb, CIRBUF_STR_HEAD, sizeof(CIRBUF_STR_HEAD)) - != (sizeof(CIRBUF_STR_HEAD))) { - printf("Error: failed to add string to head!\n"); - return -1; - } - /* delete string from tail */ - if (cirbuf_del_buf_tail(&cb, sizeof(CIRBUF_STR_HEAD)) < 0) { - printf("Error: failed to delete string from tail!\n"); - return -1; - } - /* verify string was deleted */ - if (cirbuf_del_tail_safe(&cb) == 0) { - printf("Error: buffer should have been empty!\n"); - return -1; - } - /* clear tmp buffer */ - memset(tmp, 0, sizeof(tmp)); - - /* - * reinitialize circular buffer - */ - memset(buf, 0, sizeof(buf)); - if (cirbuf_init(&cb, buf, 0, sizeof(buf)) < 0) { - printf("Error: failed to reinitialize circular buffer!\n"); - return -1; - } - - /* add string to tail */ - if (cirbuf_add_buf_tail(&cb, CIRBUF_STR_TAIL, sizeof(CIRBUF_STR_TAIL)) - != (sizeof(CIRBUF_STR_TAIL))) { - printf("Error: failed to add string to tail!\n"); - return -1; - } - /* delete string from head */ - if (cirbuf_del_buf_head(&cb, sizeof(CIRBUF_STR_TAIL)) < 0) { - printf("Error: failed to delete string from head!\n"); - return -1; - } - /* verify string was deleted */ - if (cirbuf_del_head_safe(&cb) == 0) { - printf("Error: buffer should have been empty!\n"); - return -1; - } - - return 0; -} - -/* try to write more than available */ -static int -test_cirbuf_string_add_boundaries(void) -{ - struct cirbuf cb; - char buf[CMDLINE_TEST_BUFSIZE]; - unsigned i; - - /* initialize buffers */ - memset(buf, 0, sizeof(buf)); - - /* - * initialize circular buffer - */ - if (cirbuf_init(&cb, buf, 0, sizeof(buf)) < 0) { - printf("Error: failed to initialize circular buffer!\n"); - return -1; - } - - /* fill the buffer from tail */ - for (i = 0; i < CMDLINE_TEST_BUFSIZE - sizeof(CIRBUF_STR_TAIL) + 1; i++) - cirbuf_add_tail_safe(&cb, 't'); - - /* try adding a string to tail */ - if (cirbuf_add_buf_tail(&cb, CIRBUF_STR_TAIL, sizeof(CIRBUF_STR_TAIL)) - > 0) { - printf("Error: buffer should have been full!\n"); - return -1; - } - /* try adding a string to head */ - if (cirbuf_add_buf_head(&cb, CIRBUF_STR_TAIL, sizeof(CIRBUF_STR_TAIL)) - > 0) { - printf("Error: buffer should have been full!\n"); - return -1; - } - - /* - * reinitialize circular buffer - */ - memset(buf, 0, sizeof(buf)); - if (cirbuf_init(&cb, buf, 0, sizeof(buf)) < 0) { - printf("Error: failed to reinitialize circular buffer!\n"); - return -1; - } - - /* fill the buffer from head */ - for (i = 0; i < CMDLINE_TEST_BUFSIZE - sizeof(CIRBUF_STR_HEAD) + 1; i++) - cirbuf_add_head_safe(&cb, 'h'); - - /* try adding a string to head */ - if (cirbuf_add_buf_head(&cb, CIRBUF_STR_HEAD, sizeof(CIRBUF_STR_HEAD)) - > 0) { - printf("Error: buffer should have been full!\n"); - return -1; - } - /* try adding a string to tail */ - if (cirbuf_add_buf_tail(&cb, CIRBUF_STR_HEAD, sizeof(CIRBUF_STR_HEAD)) - > 0) { - printf("Error: buffer should have been full!\n"); - return -1; - } - - return 0; -} - -/* try to read/delete more than written */ -static int -test_cirbuf_string_get_del_boundaries(void) -{ - struct cirbuf cb; - char buf[CMDLINE_TEST_BUFSIZE]; - char tmp[CMDLINE_TEST_BUFSIZE]; - - /* initialize buffers */ - memset(buf, 0, sizeof(buf)); - memset(tmp, 0, sizeof(tmp)); - - /* - * initialize circular buffer - */ - if (cirbuf_init(&cb, buf, 0, sizeof(buf)) < 0) { - printf("Error: failed to initialize circular buffer!\n"); - return -1; - } - - - /* add string to head */ - if (cirbuf_add_buf_head(&cb, CIRBUF_STR_HEAD, sizeof(CIRBUF_STR_HEAD)) - != (sizeof(CIRBUF_STR_HEAD))) { - printf("Error: failed to add string to head!\n"); - return -1; - } - /* read more than written (head) */ - if (cirbuf_get_buf_head(&cb, tmp, sizeof(CIRBUF_STR_HEAD) + 1) - != sizeof(CIRBUF_STR_HEAD)) { - printf("Error: unexpected result when reading too much data!\n"); - return -1; - } - /* read more than written (tail) */ - if (cirbuf_get_buf_tail(&cb, tmp, sizeof(CIRBUF_STR_HEAD) + 1) - != sizeof(CIRBUF_STR_HEAD)) { - printf("Error: unexpected result when reading too much data!\n"); - return -1; - } - /* delete more than written (head) */ - if (cirbuf_del_buf_head(&cb, sizeof(CIRBUF_STR_HEAD) + 1) == 0) { - printf("Error: unexpected result when deleting too much data!\n"); - return -1; - } - /* delete more than written (tail) */ - if (cirbuf_del_buf_tail(&cb, sizeof(CIRBUF_STR_HEAD) + 1) == 0) { - printf("Error: unexpected result when deleting too much data!\n"); - return -1; - } - - /* - * reinitialize circular buffer - */ - memset(buf, 0, sizeof(buf)); - if (cirbuf_init(&cb, buf, 0, sizeof(buf)) < 0) { - printf("Error: failed to reinitialize circular buffer!\n"); - return -1; - } - - /* add string to tail */ - if (cirbuf_add_buf_tail(&cb, CIRBUF_STR_TAIL, sizeof(CIRBUF_STR_TAIL)) - != (sizeof(CIRBUF_STR_TAIL))) { - printf("Error: failed to add string to tail!\n"); - return -1; - } - /* read more than written (tail) */ - if (cirbuf_get_buf_tail(&cb, tmp, sizeof(CIRBUF_STR_TAIL) + 1) - != sizeof(CIRBUF_STR_TAIL)) { - printf("Error: unexpected result when reading too much data!\n"); - return -1; - } - /* read more than written (head) */ - if (cirbuf_get_buf_head(&cb, tmp, sizeof(CIRBUF_STR_TAIL) + 1) - != sizeof(CIRBUF_STR_TAIL)) { - printf("Error: unexpected result when reading too much data!\n"); - return -1; - } - /* delete more than written (tail) */ - if (cirbuf_del_buf_tail(&cb, sizeof(CIRBUF_STR_TAIL) + 1) == 0) { - printf("Error: unexpected result when deleting too much data!\n"); - return -1; - } - /* delete more than written (head) */ - if (cirbuf_del_buf_tail(&cb, sizeof(CIRBUF_STR_TAIL) + 1) == 0) { - printf("Error: unexpected result when deleting too much data!\n"); - return -1; - } - - return 0; -} - -/* try to read/delete less than written */ -static int -test_cirbuf_string_get_del_partial(void) -{ - struct cirbuf cb; - char buf[CMDLINE_TEST_BUFSIZE]; - char tmp[CMDLINE_TEST_BUFSIZE]; - char tmp2[CMDLINE_TEST_BUFSIZE]; - - /* initialize buffers */ - memset(buf, 0, sizeof(buf)); - memset(tmp, 0, sizeof(tmp)); - memset(tmp2, 0, sizeof(tmp)); - - strlcpy(tmp2, CIRBUF_STR_HEAD, sizeof(tmp2)); - - /* - * initialize circular buffer - */ - if (cirbuf_init(&cb, buf, 0, sizeof(buf)) < 0) { - printf("Error: failed to initialize circular buffer!\n"); - return -1; - } - - /* add string to head */ - if (cirbuf_add_buf_head(&cb, CIRBUF_STR_HEAD, sizeof(CIRBUF_STR_HEAD)) - != (sizeof(CIRBUF_STR_HEAD))) { - printf("Error: failed to add string to head!\n"); - return -1; - } - /* read less than written (head) */ - if (cirbuf_get_buf_head(&cb, tmp, sizeof(CIRBUF_STR_HEAD) - 1) - != sizeof(CIRBUF_STR_HEAD) - 1) { - printf("Error: unexpected result when reading from head!\n"); - return -1; - } - /* verify string */ - if (strncmp(tmp, tmp2, sizeof(CIRBUF_STR_HEAD) - 1) != 0) { - printf("Error: strings mismatch!\n"); - return -1; - } - memset(tmp, 0, sizeof(tmp)); - /* read less than written (tail) */ - if (cirbuf_get_buf_tail(&cb, tmp, sizeof(CIRBUF_STR_HEAD) - 1) - != sizeof(CIRBUF_STR_HEAD) - 1) { - printf("Error: unexpected result when reading from tail!\n"); - return -1; - } - /* verify string */ - if (strncmp(tmp, &tmp2[1], sizeof(CIRBUF_STR_HEAD) - 1) != 0) { - printf("Error: strings mismatch!\n"); - return -1; - } - - /* - * verify correct deletion - */ - - /* clear buffer */ - memset(tmp, 0, sizeof(tmp)); - - /* delete less than written (head) */ - if (cirbuf_del_buf_head(&cb, 1) != 0) { - printf("Error: delete from head failed!\n"); - return -1; - } - /* read from head */ - if (cirbuf_get_buf_head(&cb, tmp, sizeof(CIRBUF_STR_HEAD) - 1) - != sizeof(CIRBUF_STR_HEAD) - 1) { - printf("Error: unexpected result when reading from head!\n"); - return -1; - } - /* since we deleted from head, first char should be deleted */ - if (strncmp(tmp, &tmp2[1], sizeof(CIRBUF_STR_HEAD) - 1) != 0) { - printf("Error: strings mismatch!\n"); - return -1; - } - /* clear buffer */ - memset(tmp, 0, sizeof(tmp)); - - /* delete less than written (tail) */ - if (cirbuf_del_buf_tail(&cb, 1) != 0) { - printf("Error: delete from tail failed!\n"); - return -1; - } - /* read from tail */ - if (cirbuf_get_buf_tail(&cb, tmp, sizeof(CIRBUF_STR_HEAD) - 2) - != sizeof(CIRBUF_STR_HEAD) - 2) { - printf("Error: unexpected result when reading from head!\n"); - return -1; - } - /* since we deleted from tail, last char should be deleted */ - if (strncmp(tmp, &tmp2[1], sizeof(CIRBUF_STR_HEAD) - 2) != 0) { - printf("Error: strings mismatch!\n"); - return -1; - } - - return 0; -} - -/* test cmdline_cirbuf char add/del functions */ -static int -test_cirbuf_char_add_del(void) -{ - struct cirbuf cb; - char buf[CMDLINE_TEST_BUFSIZE]; - char tmp[CMDLINE_TEST_BUFSIZE]; - - /* clear buffer */ - memset(buf, 0, sizeof(buf)); - memset(tmp, 0, sizeof(tmp)); - - /* - * initialize circular buffer - */ - if (cirbuf_init(&cb, buf, 0, sizeof(buf)) < 0) { - printf("Error: failed to initialize circular buffer!\n"); - return -1; - } - - /* - * try to delete something from cirbuf. since it's empty, - * these should fail. - */ - if (cirbuf_del_head_safe(&cb) == 0) { - printf("Error: deleting from empty cirbuf head succeeded!\n"); - return -1; - } - if (cirbuf_del_tail_safe(&cb) == 0) { - printf("Error: deleting from empty cirbuf tail succeeded!\n"); - return -1; - } - - /* - * add, verify and delete. these should pass. - */ - if (cirbuf_add_head_safe(&cb,'h') < 0) { - printf("Error: adding to cirbuf head failed!\n"); - return -1; - } - if (cirbuf_get_head(&cb) != 'h') { - printf("Error: wrong head content!\n"); - return -1; - } - if (cirbuf_del_head_safe(&cb) < 0) { - printf("Error: deleting from cirbuf head failed!\n"); - return -1; - } - if (cirbuf_add_tail_safe(&cb,'t') < 0) { - printf("Error: adding to cirbuf tail failed!\n"); - return -1; - } - if (cirbuf_get_tail(&cb) != 't') { - printf("Error: wrong tail content!\n"); - return -1; - } - if (cirbuf_del_tail_safe(&cb) < 0) { - printf("Error: deleting from cirbuf tail failed!\n"); - return -1; - } - /* do the same for unsafe versions. those are void. */ - cirbuf_add_head(&cb,'h'); - if (cirbuf_get_head(&cb) != 'h') { - printf("Error: wrong head content!\n"); - return -1; - } - cirbuf_del_head(&cb); - - /* test if char has been deleted. we can't call cirbuf_get_head - * because it's unsafe, but we can call cirbuf_get_buf_head. - */ - if (cirbuf_get_buf_head(&cb, tmp, 1) > 0) { - printf("Error: buffer should have been empty!\n"); - return -1; - } - - cirbuf_add_tail(&cb,'t'); - if (cirbuf_get_tail(&cb) != 't') { - printf("Error: wrong tail content!\n"); - return -1; - } - cirbuf_del_tail(&cb); - - /* test if char has been deleted. we can't call cirbuf_get_tail - * because it's unsafe, but we can call cirbuf_get_buf_tail. - */ - if (cirbuf_get_buf_tail(&cb, tmp, 1) > 0) { - printf("Error: buffer should have been empty!\n"); - return -1; - } - - return 0; -} - -/* test filling up buffer with chars */ -static int -test_cirbuf_char_fill(void) -{ - struct cirbuf cb; - char buf[CMDLINE_TEST_BUFSIZE]; - unsigned i; - - /* clear buffer */ - memset(buf, 0, sizeof(buf)); - - /* - * initialize circular buffer - */ - if (cirbuf_init(&cb, buf, 0, sizeof(buf)) < 0) { - printf("Error: failed to initialize circular buffer!\n"); - return -1; - } - - /* - * fill the buffer from head or tail, verify contents, test boundaries - * and clear the buffer - */ - - /* fill the buffer from tail */ - for (i = 0; i < CMDLINE_TEST_BUFSIZE; i++) - cirbuf_add_tail_safe(&cb, 't'); - /* verify that contents of the buffer are what they are supposed to be */ - for (i = 0; i < sizeof(buf); i++) { - if (buf[i] != 't') { - printf("Error: wrong content in buffer!\n"); - return -1; - } - } - /* try to add to a full buffer from tail */ - if (cirbuf_add_tail_safe(&cb, 't') == 0) { - printf("Error: buffer should have been full!\n"); - return -1; - } - /* try to add to a full buffer from head */ - if (cirbuf_add_head_safe(&cb, 'h') == 0) { - printf("Error: buffer should have been full!\n"); - return -1; - } - /* delete buffer from tail */ - for(i = 0; i < CMDLINE_TEST_BUFSIZE; i++) - cirbuf_del_tail_safe(&cb); - /* try to delete from an empty buffer */ - if (cirbuf_del_tail_safe(&cb) >= 0) { - printf("Error: buffer should have been empty!\n"); - return -1; - } - - /* fill the buffer from head */ - for (i = 0; i < CMDLINE_TEST_BUFSIZE; i++) - cirbuf_add_head_safe(&cb, 'h'); - /* verify that contents of the buffer are what they are supposed to be */ - for (i = 0; i < sizeof(buf); i++) { - if (buf[i] != 'h') { - printf("Error: wrong content in buffer!\n"); - return -1; - } - } - /* try to add to a full buffer from head */ - if (cirbuf_add_head_safe(&cb,'h') >= 0) { - printf("Error: buffer should have been full!\n"); - return -1; - } - /* try to add to a full buffer from tail */ - if (cirbuf_add_tail_safe(&cb, 't') == 0) { - printf("Error: buffer should have been full!\n"); - return -1; - } - /* delete buffer from head */ - for(i = 0; i < CMDLINE_TEST_BUFSIZE; i++) - cirbuf_del_head_safe(&cb); - /* try to delete from an empty buffer */ - if (cirbuf_del_head_safe(&cb) >= 0) { - printf("Error: buffer should have been empty!\n"); - return -1; - } - - /* - * fill the buffer from both head and tail, with alternating characters, - * verify contents and clear the buffer - */ - - /* fill half of buffer from tail */ - for (i = 0; i < CMDLINE_TEST_BUFSIZE / 2; i++) - cirbuf_add_tail_safe(&cb, (char) (i % 2 ? 't' : 'T')); - /* fill other half of the buffer from head */ - for (i = 0; i < CMDLINE_TEST_BUFSIZE / 2; i++) - cirbuf_add_head_safe(&cb, (char) (i % 2 ? 'H' : 'h')); /* added in reverse */ - - /* verify that contents of the buffer are what they are supposed to be */ - for (i = 0; i < sizeof(buf) / 2; i++) { - if (buf[i] != (char) (i % 2 ? 't' : 'T')) { - printf("Error: wrong content in buffer at %u!\n", i); - return -1; - } - } - for (i = sizeof(buf) / 2; i < sizeof(buf); i++) { - if (buf[i] != (char) (i % 2 ? 'h' : 'H')) { - printf("Error: wrong content in buffer %u!\n", i); - return -1; - } - } - - return 0; -} - -/* test left alignment */ -static int -test_cirbuf_align_left(void) -{ -#define HALF_OFFSET CMDLINE_TEST_BUFSIZE / 2 -#define SMALL_OFFSET HALF_OFFSET / 2 -/* resulting buffer lengths for each of the test cases */ -#define LEN1 HALF_OFFSET - SMALL_OFFSET - 1 -#define LEN2 HALF_OFFSET + SMALL_OFFSET + 2 -#define LEN3 HALF_OFFSET - SMALL_OFFSET -#define LEN4 HALF_OFFSET + SMALL_OFFSET - 1 - - struct cirbuf cb; - char buf[CMDLINE_TEST_BUFSIZE]; - char tmp[CMDLINE_TEST_BUFSIZE]; - unsigned i; - - /* - * align left when start < end and start in left half - */ - - /* - * initialize circular buffer - */ - memset(buf, 0, sizeof(buf)); - if (cirbuf_init(&cb, buf, 0, sizeof(buf)) < 0) { - printf("Error: failed to initialize circular buffer!\n"); - return -1; - } - - /* push end into left half */ - for (i = 0; i < HALF_OFFSET - 1; i++) - cirbuf_add_tail_safe(&cb, 't'); - - /* push start into left half < end */ - for (i = 0; i < SMALL_OFFSET; i++) - cirbuf_del_head_safe(&cb); - - /* align */ - if (cirbuf_align_left(&cb) < 0) { - printf("Error: alignment failed!\n"); - return -1; - } - - /* verify result */ - if (cb.start != 0 || cb.len != LEN1 || cb.end != cb.len - 1) { - printf("Error: buffer alignment is wrong!\n"); - return -1; - } - - /* - * align left when start > end and start in left half - */ - - /* - * reinitialize circular buffer - */ - memset(buf, 0, sizeof(buf)); - if (cirbuf_init(&cb, buf, 0, sizeof(buf)) < 0) { - printf("Error: failed to reinitialize circular buffer!\n"); - return -1; - } - - /* push start into left half */ - for (i = 0; i < HALF_OFFSET + 2; i++) - cirbuf_add_head_safe(&cb, 'h'); - - /* push end into left half > start */ - for (i = 0; i < SMALL_OFFSET; i++) - cirbuf_add_tail_safe(&cb, 't'); - - /* align */ - if (cirbuf_align_left(&cb) < 0) { - printf("Error: alignment failed!\n"); - return -1; - } - - /* verify result */ - if (cb.start != 0 || cb.len != LEN2 || cb.end != cb.len - 1) { - printf("Error: buffer alignment is wrong!"); - return -1; - } - - /* - * align left when start < end and start in right half - */ - - /* - * reinitialize circular buffer - */ - memset(buf, 0, sizeof(buf)); - if (cirbuf_init(&cb, buf, 0, sizeof(buf)) < 0) { - printf("Error: failed to reinitialize circular buffer!\n"); - return -1; - } - - /* push start into the right half */ - for (i = 0; i < HALF_OFFSET; i++) - cirbuf_add_head_safe(&cb, 'h'); - - /* push end into left half > start */ - for (i = 0; i < SMALL_OFFSET; i++) - cirbuf_del_tail_safe(&cb); - - /* align */ - if (cirbuf_align_left(&cb) < 0) { - printf("Error: alignment failed!\n"); - return -1; - } - - /* verify result */ - if (cb.start != 0 || cb.len != LEN3 || cb.end != cb.len - 1) { - printf("Error: buffer alignment is wrong!"); - return -1; - } - - /* - * align left when start > end and start in right half - */ - - /* - * reinitialize circular buffer - */ - memset(buf, 0, sizeof(buf)); - if (cirbuf_init(&cb, buf, 0, sizeof(buf)) < 0) { - printf("Error: failed to reinitialize circular buffer!\n"); - return -1; - } - - /* push start into the right half */ - for (i = 0; i < HALF_OFFSET - 1; i++) - cirbuf_add_head_safe(&cb, 'h'); - - /* push end into left half < start */ - for (i = 0; i < SMALL_OFFSET; i++) - cirbuf_add_tail_safe(&cb, 't'); - - /* align */ - if (cirbuf_align_left(&cb) < 0) { - printf("Error: alignment failed!\n"); - return -1; - } - - /* verify result */ - if (cb.start != 0 || cb.len != LEN4 || - cb.end != cb.len - 1) { - printf("Error: buffer alignment is wrong!"); - return -1; - } - - /* - * Verify that alignment doesn't corrupt data - */ - - /* - * reinitialize circular buffer - */ - memset(buf, 0, sizeof(buf)); - if (cirbuf_init(&cb, buf, 0, sizeof(buf)) < 0) { - printf("Error: failed to reinitialize circular buffer!\n"); - return -1; - } - - /* add string to tail and head */ - if (cirbuf_add_buf_head(&cb, CIRBUF_STR_HEAD, - sizeof(CIRBUF_STR_HEAD)) < 0 || cirbuf_add_buf_tail(&cb, - CIRBUF_STR_TAIL, sizeof(CIRBUF_STR_TAIL)) < 0) { - printf("Error: failed to add strings!\n"); - return -1; - } - - /* align */ - if (cirbuf_align_left(&cb) < 0) { - printf("Error: alignment failed!\n"); - return -1; - } - - /* get string from head */ - if (cirbuf_get_buf_head(&cb, tmp, - sizeof(CIRBUF_STR_HEAD) + sizeof(CIRBUF_STR_TAIL)) < 0) { - printf("Error: failed to read string from head!\n"); - return -1; - } - - /* verify string */ - if (strncmp(tmp, CIRBUF_STR_HEAD "\0" CIRBUF_STR_TAIL, - sizeof(CIRBUF_STR_HEAD) + sizeof(CIRBUF_STR_TAIL)) != 0) { - printf("Error: strings mismatch!\n"); - return -1; - } - - /* reset tmp buffer */ - memset(tmp, 0, sizeof(tmp)); - - /* get string from tail */ - if (cirbuf_get_buf_tail(&cb, tmp, - sizeof(CIRBUF_STR_HEAD) + sizeof(CIRBUF_STR_TAIL)) < 0) { - printf("Error: failed to read string from head!\n"); - return -1; - } - - /* verify string */ - if (strncmp(tmp, CIRBUF_STR_HEAD "\0" CIRBUF_STR_TAIL, - sizeof(CIRBUF_STR_HEAD) + sizeof(CIRBUF_STR_TAIL)) != 0) { - printf("Error: strings mismatch!\n"); - return -1; - } - - return 0; -} - -/* test right alignment */ -static int -test_cirbuf_align_right(void) -{ -#define END_OFFSET CMDLINE_TEST_BUFSIZE - 1 - struct cirbuf cb; - char buf[CMDLINE_TEST_BUFSIZE]; - char tmp[CMDLINE_TEST_BUFSIZE]; - unsigned i; - - - /* - * align right when start < end and start in left half - */ - - /* - * initialize circular buffer - */ - memset(buf, 0, sizeof(buf)); - if (cirbuf_init(&cb, buf, 0, sizeof(buf)) < 0) { - printf("Error: failed to initialize circular buffer!\n"); - return -1; - } - - /* push end into left half */ - for (i = 0; i < HALF_OFFSET - 1; i++) - cirbuf_add_tail_safe(&cb, 't'); - - /* push start into left half < end */ - for (i = 0; i < SMALL_OFFSET; i++) - cirbuf_del_head_safe(&cb); - - /* align */ - cirbuf_align_right(&cb); - - /* verify result */ - if (cb.start != END_OFFSET || cb.len != LEN1 || cb.end != cb.len - 2) { - printf("Error: buffer alignment is wrong!\n"); - return -1; - } - - /* - * align right when start > end and start in left half - */ - - /* - * reinitialize circular buffer - */ - memset(buf, 0, sizeof(buf)); - if (cirbuf_init(&cb, buf, 0, sizeof(buf)) < 0) { - printf("Error: failed to reinitialize circular buffer!\n"); - return -1; - } - - /* push start into left half */ - for (i = 0; i < HALF_OFFSET + 2; i++) - cirbuf_add_head_safe(&cb, 'h'); - - /* push end into left half > start */ - for (i = 0; i < SMALL_OFFSET; i++) - cirbuf_add_tail_safe(&cb, 't'); - - /* align */ - cirbuf_align_right(&cb); - - /* verify result */ - if (cb.start != END_OFFSET || cb.len != LEN2 || cb.end != cb.len - 2) { - printf("Error: buffer alignment is wrong!"); - return -1; - } - - /* - * align right when start < end and start in right half - */ - - /* - * reinitialize circular buffer - */ - memset(buf, 0, sizeof(buf)); - if (cirbuf_init(&cb, buf, 0, sizeof(buf)) < 0) { - printf("Error: failed to reinitialize circular buffer!\n"); - return -1; - } - - /* push start into the right half */ - for (i = 0; i < HALF_OFFSET; i++) - cirbuf_add_head_safe(&cb, 'h'); - - /* push end into left half > start */ - for (i = 0; i < SMALL_OFFSET; i++) - cirbuf_del_tail_safe(&cb); - - /* align */ - cirbuf_align_right(&cb); - - /* verify result */ - if (cb.end != END_OFFSET || cb.len != LEN3 || cb.start != cb.end - cb.len + 1) { - printf("Error: buffer alignment is wrong!"); - return -1; - } - - /* - * align right when start > end and start in right half - */ - - /* - * reinitialize circular buffer - */ - memset(buf, 0, sizeof(buf)); - if (cirbuf_init(&cb, buf, 0, sizeof(buf)) < 0) { - printf("Error: failed to reinitialize circular buffer!\n"); - return -1; - } - - /* push start into the right half */ - for (i = 0; i < HALF_OFFSET - 1; i++) - cirbuf_add_head_safe(&cb, 'h'); - - /* push end into left half < start */ - for (i = 0; i < SMALL_OFFSET; i++) - cirbuf_add_tail_safe(&cb, 't'); - - /* align */ - cirbuf_align_right(&cb); - - /* verify result */ - if (cb.end != END_OFFSET || cb.len != LEN4 || cb.start != cb.end - cb.len + 1) { - printf("Error: buffer alignment is wrong!"); - return -1; - } - - /* - * Verify that alignment doesn't corrupt data - */ - - /* - * reinitialize circular buffer - */ - memset(buf, 0, sizeof(buf)); - if (cirbuf_init(&cb, buf, 0, sizeof(buf)) < 0) { - printf("Error: failed to reinitialize circular buffer!\n"); - return -1; - } - - /* add string to tail and head */ - if (cirbuf_add_buf_tail(&cb, CIRBUF_STR_TAIL, - sizeof(CIRBUF_STR_TAIL)) < 0 || cirbuf_add_buf_head(&cb, - CIRBUF_STR_HEAD, sizeof(CIRBUF_STR_HEAD)) < 0) { - printf("Error: failed to add strings!\n"); - return -1; - } - - /* align */ - if (cirbuf_align_right(&cb) < 0) { - printf("Error: alignment failed!\n"); - return -1; - } - - /* get string from head */ - if (cirbuf_get_buf_head(&cb, tmp, - sizeof(CIRBUF_STR_HEAD) + sizeof(CIRBUF_STR_TAIL)) < 0) { - printf("Error: failed to read string from head!\n"); - return -1; - } - - /* verify string */ - if (strncmp(tmp, CIRBUF_STR_HEAD "\0" CIRBUF_STR_TAIL, - sizeof(CIRBUF_STR_HEAD) + sizeof(CIRBUF_STR_TAIL)) != 0) { - printf("Error: strings mismatch!\n"); - return -1; - } - - /* reset tmp buffer */ - memset(tmp, 0, sizeof(tmp)); - - /* get string from tail */ - if (cirbuf_get_buf_tail(&cb, tmp, - sizeof(CIRBUF_STR_HEAD) + sizeof(CIRBUF_STR_TAIL)) < 0) { - printf("Error: failed to read string from head!\n"); - return -1; - } - /* verify string */ - if (strncmp(tmp, CIRBUF_STR_HEAD "\0" CIRBUF_STR_TAIL, - sizeof(CIRBUF_STR_HEAD) + sizeof(CIRBUF_STR_TAIL)) != 0) { - printf("Error: strings mismatch!\n"); - return -1; - } - - return 0; -} - -/* call functions with invalid parameters */ -int -test_cirbuf_invalid_param(void) -{ - struct cirbuf cb; - char buf[CMDLINE_TEST_BUFSIZE]; - - /* null cirbuf */ - if (cirbuf_init(0, buf, 0, sizeof(buf)) == 0) - return -1; - /* null buffer */ - if (cirbuf_init(&cb, 0, 0, sizeof(buf)) == 0) - return -1; - /* null cirbuf */ - if (cirbuf_add_head_safe(0, 'h') == 0) - return -1; - if (cirbuf_add_tail_safe(0, 't') == 0) - return -1; - if (cirbuf_del_head_safe(0) == 0) - return -1; - if (cirbuf_del_tail_safe(0) == 0) - return -1; - /* null buffer */ - if (cirbuf_add_buf_head(&cb, 0, 0) == 0) - return -1; - if (cirbuf_add_buf_tail(&cb, 0, 0) == 0) - return -1; - /* null cirbuf */ - if (cirbuf_add_buf_head(0, buf, 0) == 0) - return -1; - if (cirbuf_add_buf_tail(0, buf, 0) == 0) - return -1; - /* null size */ - if (cirbuf_add_buf_head(&cb, buf, 0) == 0) - return -1; - if (cirbuf_add_buf_tail(&cb, buf, 0) == 0) - return -1; - /* null cirbuf */ - if (cirbuf_del_buf_head(0, 0) == 0) - return -1; - if (cirbuf_del_buf_tail(0, 0) == 0) - return -1; - /* null size */ - if (cirbuf_del_buf_head(&cb, 0) == 0) - return -1; - if (cirbuf_del_buf_tail(&cb, 0) == 0) - return -1; - /* null cirbuf */ - if (cirbuf_get_buf_head(0, 0, 0) == 0) - return -1; - if (cirbuf_get_buf_tail(0, 0, 0) == 0) - return -1; - /* null buffer */ - if (cirbuf_get_buf_head(&cb, 0, 0) == 0) - return -1; - if (cirbuf_get_buf_tail(&cb, 0, 0) == 0) - return -1; - /* null size, this is valid but should return 0 */ - if (cirbuf_get_buf_head(&cb, buf, 0) != 0) - return -1; - if (cirbuf_get_buf_tail(&cb, buf, 0) != 0) - return -1; - /* null cirbuf */ - if (cirbuf_align_left(0) == 0) - return -1; - if (cirbuf_align_right(0) == 0) - return -1; - - return 0; -} - -/* test cmdline_cirbuf char functions */ -int -test_cirbuf_char(void) -{ - int ret; - - ret = test_cirbuf_char_add_del(); - if (ret < 0) - return -1; - - ret = test_cirbuf_char_fill(); - if (ret < 0) - return -1; - - return 0; -} - -/* test cmdline_cirbuf string functions */ -int -test_cirbuf_string(void) -{ - if (test_cirbuf_string_add_del() < 0) - return -1; - - if (test_cirbuf_string_add_del_reverse() < 0) - return -1; - - if (test_cirbuf_string_add_boundaries() < 0) - return -1; - - if (test_cirbuf_string_get_del_boundaries() < 0) - return -1; - - if (test_cirbuf_string_get_del_partial() < 0) - return -1; - - if (test_cirbuf_string_misc() < 0) - return -1; - - return 0; -} - -/* test cmdline_cirbuf align functions */ -int -test_cirbuf_align(void) -{ - if (test_cirbuf_align_left() < 0) - return -1; - if (test_cirbuf_align_right() < 0) - return -1; - return 0; -} diff --git a/test/test/test_cmdline_lib.c b/test/test/test_cmdline_lib.c index a856a9713..2821d4bbf 100644 --- a/test/test/test_cmdline_lib.c +++ b/test/test/test_cmdline_lib.c @@ -12,8 +12,6 @@ #include <ctype.h> #include <sys/queue.h> -#include <cmdline_vt100.h> -#include <cmdline_rdline.h> #include <cmdline_parse.h> #include <cmdline_socket.h> #include <cmdline.h> @@ -21,113 +19,41 @@ #include "test_cmdline.h" /****************************************************************/ -/* static functions required for some tests */ -static void -valid_buffer(__attribute__((unused))struct rdline *rdl, - __attribute__((unused))const char *buf, - __attribute__((unused)) unsigned int size) -{ -} - -static int -complete_buffer(__attribute__((unused)) struct rdline *rdl, - __attribute__((unused)) const char *buf, - __attribute__((unused)) char *dstbuf, - __attribute__((unused)) unsigned int dstsize, - __attribute__((unused)) int *state) -{ - return 0; -} - -/****************************************************************/ static int test_cmdline_parse_fns(void) { - struct cmdline cl; + struct cmdline *cl; int i = 0; char dst[CMDLINE_TEST_BUFSIZE]; + cl = cmdline_new(NULL, "prompt", 0, 1); + if (!cl) + goto error; if (cmdline_parse(NULL, "buffer") >= 0) goto error; - if (cmdline_parse(&cl, NULL) >= 0) + if (cmdline_parse(cl, NULL) >= 0) goto error; if (cmdline_complete(NULL, "buffer", &i, dst, sizeof(dst)) >= 0) goto error; - if (cmdline_complete(&cl, NULL, &i, dst, sizeof(dst)) >= 0) + if (cmdline_complete(cl, NULL, &i, dst, sizeof(dst)) >= 0) goto error; - if (cmdline_complete(&cl, "buffer", NULL, dst, sizeof(dst)) >= 0) + if (cmdline_complete(cl, "buffer", NULL, dst, sizeof(dst)) >= 0) goto error; - if (cmdline_complete(&cl, "buffer", &i, NULL, sizeof(dst)) >= 0) + if (cmdline_complete(cl, "buffer", &i, NULL, sizeof(dst)) >= 0) goto error; return 0; error: + if (cl) + cmdline_free(cl); printf("Error: function accepted null parameter!\n"); return -1; } static int -test_cmdline_rdline_fns(void) -{ - struct rdline rdl; - rdline_write_char_t *wc = &cmdline_write_char; - rdline_validate_t *v = &valid_buffer; - rdline_complete_t *c = &complete_buffer; - - if (rdline_init(NULL, wc, v, c) >= 0) - goto error; - if (rdline_init(&rdl, NULL, v, c) >= 0) - goto error; - if (rdline_init(&rdl, wc, NULL, c) >= 0) - goto error; - if (rdline_init(&rdl, wc, v, NULL) >= 0) - goto error; - if (rdline_char_in(NULL, 0) >= 0) - goto error; - if (rdline_get_buffer(NULL) != NULL) - goto error; - if (rdline_add_history(NULL, "history") >= 0) - goto error; - if (rdline_add_history(&rdl, NULL) >= 0) - goto error; - if (rdline_get_history_item(NULL, 0) != NULL) - goto error; - - /* void functions */ - rdline_newline(NULL, "prompt"); - rdline_newline(&rdl, NULL); - rdline_stop(NULL); - rdline_quit(NULL); - rdline_restart(NULL); - rdline_redisplay(NULL); - rdline_reset(NULL); - rdline_clear_history(NULL); - - return 0; - -error: - printf("Error: function accepted null parameter!\n"); - return -1; -} - -static int -test_cmdline_vt100_fns(void) -{ - if (vt100_parser(NULL, 0) >= 0) { - printf("Error: function accepted null parameter!\n"); - return -1; - } - - /* void functions */ - vt100_init(NULL); - - return 0; -} - -static int test_cmdline_socket_fns(void) { cmdline_parse_ctx_t ctx; @@ -164,7 +90,7 @@ static int test_cmdline_fns(void) { cmdline_parse_ctx_t ctx; - struct cmdline cl, *tmp; + struct cmdline *tmp; memset(&ctx, 0, sizeof(ctx)); tmp = cmdline_new(&ctx, "test", -1, -1); @@ -177,10 +103,6 @@ test_cmdline_fns(void) goto error; if (cmdline_in(NULL, "buffer", CMDLINE_TEST_BUFSIZE) >= 0) goto error; - if (cmdline_in(&cl, NULL, CMDLINE_TEST_BUFSIZE) >= 0) - goto error; - if (cmdline_write_char(NULL, 0) >= 0) - goto error; /* void functions */ cmdline_set_prompt(NULL, "prompt"); @@ -191,16 +113,6 @@ test_cmdline_fns(void) cmdline_interact(NULL); cmdline_quit(NULL); - /* check if void calls change anything when they should fail */ - cl = *tmp; - - cmdline_printf(&cl, NULL); - if (memcmp(&cl, tmp, sizeof(cl))) goto mismatch; - cmdline_set_prompt(&cl, NULL); - if (memcmp(&cl, tmp, sizeof(cl))) goto mismatch; - cmdline_in(&cl, NULL, CMDLINE_TEST_BUFSIZE); - if (memcmp(&cl, tmp, sizeof(cl))) goto mismatch; - cmdline_free(tmp); return 0; @@ -208,9 +120,6 @@ test_cmdline_fns(void) error: printf("Error: function accepted null parameter!\n"); return -1; -mismatch: - printf("Error: data changed!\n"); - return -1; } /* test library functions. the point of these tests is not so much to test @@ -222,10 +131,6 @@ test_cmdline_lib(void) { if (test_cmdline_parse_fns() < 0) return -1; - if (test_cmdline_rdline_fns() < 0) - return -1; - if (test_cmdline_vt100_fns() < 0) - return -1; if (test_cmdline_socket_fns() < 0) return -1; if (test_cmdline_fns() < 0) -- 2.11.0 ^ permalink raw reply [flat|nested] 18+ messages in thread
* Re: [dpdk-dev] [PATCH v2] cmdline: rework as a wrapper to libedit 2018-04-19 15:13 ` [dpdk-dev] [PATCH v2] " Adrien Mazarguil @ 2018-06-26 13:21 ` Olivier Matz 2018-06-26 13:33 ` Olivier Matz 2018-06-27 10:36 ` Bruce Richardson 0 siblings, 2 replies; 18+ messages in thread From: Olivier Matz @ 2018-06-26 13:21 UTC (permalink / raw) To: Adrien Mazarguil Cc: dev, Keith Wiles, Jingjing Wu, Thomas Monjalon, Ferruh Yigit, Jim Thompson, Anatoly Burakov Hi Adrien, Better late than never, please find below some comments about your patch. On Thu, Apr 19, 2018 at 05:13:53PM +0200, Adrien Mazarguil wrote: > Disclaimer: this patch must not be confused with the CLI library [1] > (work in progress) that will eventually supersede librte_cmdline itself > with a different API. > > Rather, it modifies librte_cmdline to delegate all the heavy lifting > (terminal and history handling), strips unused features and re-implements > what remains of its public API as a wrapper to the editline library (also > known as libedit) [2], a well-known, BSD-licensed and widely available > library used by many projects which does everything needed and more [3]. > > This approach was chosen because converting librte_cmdline as a wrapper to > a more capable library was easier and faster than addressing its > shortcomings and results in much less code to maintain in DPDK. > > It also provides a drop-in solution for applications that rely on > librte_cmdline. They benefit from greatly improved command line handling > without a meaningful impact on their code base. > > The main motivation behind this patch is testpmd's flow (rte_flow) command, > which requires support for dynamic tokens and very long lines that must be > broken down when displayed. This is not supported by librte_cmdline's > limited terminal handling capabilities, resulting in a rather frustrating > user experience. > > It had to be addressed given the importance of testpmd as one of the > primary tool used by PMD developers. > > This rework results in the following changes: > > - Removed circular buffer management interface for command history > (cmdline_cirbuf.c), command history being handled by libedit. > - Removed raw command-line interpreter (cmdline_rdline.c). > - Removed raw terminal handler (cmdline_vt100.c). > - Removed all test/example code for the above. > - Re-implemented high level interactive and non-interactive command-line > handlers (cmdline.c and cmdline_socket.c) on top of libedit using its > native interface, not its readline compatibility layer. > - Made struct cmdline opaque so that applications relying on librte_cmdline > do not need to include any libedit headers. > - Applications do not need to include cmdline_rdline.h anymore. > - Terminal resizing is now automatically handled. > - New external dependency for applications relying on librte_cmdline. > - Major version bump due to the ABI impact of these changes. > > [1] http://dpdk.org/browse/draft/dpdk-draft-cli/ > [2] http://thrysoee.dk/editline/ > [3] http://netbsd.gw.com/cgi-bin/man-cgi?editline++NetBSD-current > > Signed-off-by: Adrien Mazarguil <adrien.mazarguil@6wind.com> > Cc: Olivier Matz <olivier.matz@6wind.com> > Cc: Keith Wiles <keith.wiles@intel.com> > Cc: Jingjing Wu <jingjing.wu@intel.com> > Cc: Thomas Monjalon <thomas@monjalon.net> > Cc: Ferruh Yigit <ferruh.yigit@intel.com> > Cc: Jim Thompson <jim@netgate.com> > Cc: Anatoly Burakov <anatoly.burakov@intel.com> > > -- > > v2 changes: > > - Replaced an instance of snprintf() with rte_strlcpy() [5]. > - Rebased patch. > > [5] http://dpdk.org/ml/archives/dev/2018-April/097721.html > > v1 changes: > > No fundamental change since the original RFC [4], except it's been rebased > several times and Meson build support was added in the meantime. Commit log > was also shortened a bit. > > I'm re-sending this because I think it's useful, at least to me (duh). As > the maintainer of rte_flow, I spend most of my time typing flow commands in > testpmd and libedit makes that a pleasant experience. > > Try it out! And don't hesitate to send your acked-by line to get this in > time for 18.05 :) > > [4] http://dpdk.org/ml/archives/dev/2017-November/081605.html Re-saying what I said the first time: I think this is a very good improvement, removing lots of dpdk code that is better implemented in well-known libraries. The compilation with shared libraries fail. Please try for instance: ./devtools/test-build.sh -j4 x86_64-native-linuxapp-clang+shared+debug I suggest to add in lib/librte_cmdline/Makefile: LDLIBS += $(shell pkg-config --libs libedit) I also think something should be added in /doc/guides/linux_gsg/sys_reqs.rst to highlight the new build dependency. I noticed a bad behavior change (in addition to many good ones): ctrl-c now quits the application, and this was not the case before. I often use ctrl-c to delete the line I'm currently editing. Please see at the end a proposition to restore this feature. Finally, the patch removes some functions, so it should be announced with a deprecation notice. [...] > diff --git a/app/test-pmd/cmdline.c b/app/test-pmd/cmdline.c > index 0b442c3a6..6b4d9dbfd 100644 > --- a/app/test-pmd/cmdline.c > +++ b/app/test-pmd/cmdline.c > @@ -48,7 +48,6 @@ > #include <rte_flow.h> > #include <rte_gro.h> > > -#include <cmdline_rdline.h> > #include <cmdline_parse.h> > #include <cmdline_parse_num.h> > #include <cmdline_parse_string.h> FYI, after rebase, same hunk is also required in examples/vhost_crypto/main.c [...] > diff --git a/lib/librte_cmdline/cmdline.c b/lib/librte_cmdline/cmdline.c > index 591b78b0f..1c45cd9ff 100644 > --- a/lib/librte_cmdline/cmdline.c > +++ b/lib/librte_cmdline/cmdline.c > @@ -4,79 +4,183 @@ > * All rights reserved. > */ > > +#include <ctype.h> > +#include <histedit.h> histedit.h would be better after system includes. [...] > @@ -207,48 +317,49 @@ cmdline_poll(struct cmdline *cl) > { > struct pollfd pfd; > int status; > - ssize_t read_status; > - char c; > + int read_status; > + int flags; > > if (!cl) > return -EINVAL; > - else if (cl->rdl.status == RDLINE_EXITED) > + else if (cl->error) > + return RDLINE_ERROR; > + else if (cl->eof) > return RDLINE_EXITED; > > - pfd.fd = cl->s_in; > + pfd.fd = fileno(cl->f_in); > pfd.events = POLLIN; > pfd.revents = 0; > > status = poll(&pfd, 1, 0); > if (status < 0) > - return status; > - else if (status > 0) { > - c = -1; > - read_status = read(cl->s_in, &c, 1); > - if (read_status < 0) > - return read_status; > - > - status = cmdline_in(cl, &c, 1); > - if (status < 0 && cl->rdl.status != RDLINE_EXITED) > - return status; > - } > - > - return cl->rdl.status; > + return RDLINE_ERROR; > + if (!status) > + return RDLINE_RUNNING; > + flags = fcntl(pfd.fd, F_GETFL); > + if (!(flags & O_NONBLOCK)) > + fcntl(pfd.fd, F_SETFL, flags | O_NONBLOCK); We just checked that fd is readable, what is the purpose of adding the O_NONBLOCK flag? > + if (!el_gets(cl->el, &read_status) && read_status == -1) > + cl->error = 1; Either from documentation or libedit code, I don't think it is possible that read_status is set to -1. Am I missing something? > + if (!(flags & O_NONBLOCK)) > + fcntl(pfd.fd, F_SETFL, flags); > + return cl->error ? RDLINE_ERROR : > + cl->eof ? RDLINE_EXITED : > + RDLINE_RUNNING; > } > > void > cmdline_interact(struct cmdline *cl) > { > - char c; > - > if (!cl) > return; > > - c = -1; > - while (1) { > - if (read(cl->s_in, &c, 1) <= 0) > - break; > - if (cmdline_in(cl, &c, 1) < 0) > - break; > + while (!cl->error && !cl->eof) { > + int read_status; > + > + if (el_gets(cl->el, &read_status)) > + continue; > + if (read_status == -1) > + cl->error = 1; Same comment here about read_status. Thanks Olivier ^ permalink raw reply [flat|nested] 18+ messages in thread
* Re: [dpdk-dev] [PATCH v2] cmdline: rework as a wrapper to libedit 2018-06-26 13:21 ` Olivier Matz @ 2018-06-26 13:33 ` Olivier Matz 2018-06-27 10:36 ` Bruce Richardson 1 sibling, 0 replies; 18+ messages in thread From: Olivier Matz @ 2018-06-26 13:33 UTC (permalink / raw) To: Adrien Mazarguil Cc: dev, Keith Wiles, Jingjing Wu, Thomas Monjalon, Ferruh Yigit, Jim Thompson, Anatoly Burakov > I noticed a bad behavior change (in addition to many good ones): > ctrl-c now quits the application, and this was not the case before. > I often use ctrl-c to delete the line I'm currently editing. Please > see at the end a proposition to restore this feature. And now, ladies and gentlemen, the proposition I was talking about :) diff --git a/examples/vhost_crypto/main.c b/examples/vhost_crypto/main.c index f334d7123..860457dc6 100644 --- a/examples/vhost_crypto/main.c +++ b/examples/vhost_crypto/main.c @@ -15,7 +15,6 @@ #include <rte_cryptodev.h> #include <rte_vhost_crypto.h> -#include <cmdline_rdline.h> #include <cmdline_parse.h> #include <cmdline_parse_string.h> #include <cmdline.h> diff --git a/lib/librte_cmdline/Makefile b/lib/librte_cmdline/Makefile index feb1f1bca..052934b69 100644 --- a/lib/librte_cmdline/Makefile +++ b/lib/librte_cmdline/Makefile @@ -23,6 +23,7 @@ SRCS-$(CONFIG_RTE_LIBRTE_CMDLINE) += cmdline_socket.c SRCS-$(CONFIG_RTE_LIBRTE_CMDLINE) += cmdline_parse_portlist.c LDLIBS += -lrte_eal +LDLIBS += $(shell pkg-config --libs libedit) # install includes INCS := cmdline.h cmdline_parse.h cmdline_parse_num.h cmdline_parse_ipaddr.h diff --git a/lib/librte_cmdline/cmdline.c b/lib/librte_cmdline/cmdline.c index 1c45cd9ff..af72f394f 100644 --- a/lib/librte_cmdline/cmdline.c +++ b/lib/librte_cmdline/cmdline.c @@ -4,8 +4,9 @@ * All rights reserved. */ +#include <sys/types.h> #include <ctype.h> -#include <histedit.h> +#include <signal.h> #include <stdint.h> #include <stdio.h> #include <string.h> @@ -16,6 +17,8 @@ #include <poll.h> #include <errno.h> +#include <histedit.h> + #include <rte_string_fns.h> #include "cmdline_parse.h" @@ -60,6 +63,32 @@ cmdline_el_prompt(EditLine *el) return cl->prompt; } +static int +editline_break(EditLine *el, int c) +{ + struct cmdline *cl; + + (void)c; + + if (el_get(el, EL_CLIENTDATA, &cl)) + return CC_FATAL; + + fprintf(cl->f_out, "\n"); + + return CC_NEWLINE; +} + +static int +editline_suspend(EditLine *editline, int c) +{ + (void)editline; + (void)c; + + kill(getpid(), SIGSTOP); + + return CC_NORM; +} + static unsigned char cmdline_el_execute(EditLine *el, int c) { @@ -224,6 +253,20 @@ cmdline_new(cmdline_parse_ctx_t *ctx, const char *prompt, int s_in, int s_out) if (el_set(cl->el, EL_ADDFN, "ed-execute", "Execute command", cmdline_el_execute)) goto error; + if (el_set(cl->el, EL_SETTY, "-d", "-isig", NULL)) + goto error; + if (el_set(cl->el, EL_ADDFN, "ed-break", + "Break and flush the buffer", + editline_break)) + goto error; + if (el_set(cl->el, EL_BIND, "^C", "ed-break", NULL)) + goto error; + if (el_set(cl->el, EL_ADDFN, "ed-suspend", + "Suspend the terminal", + editline_suspend)) + goto error; + if (el_set(cl->el, EL_BIND, "^Z", "ed-suspend", NULL)) + goto error; if (el_set(cl->el, EL_BIND, "^J", "ed-execute", NULL)) goto error; if (el_set(cl->el, EL_BIND, "^M", "ed-execute", NULL)) diff --git a/mk/rte.app.mk b/mk/rte.app.mk index e5caefb08..f7d9f6f2c 100644 --- a/mk/rte.app.mk +++ b/mk/rte.app.mk @@ -81,8 +81,6 @@ _LDLIBS-$(CONFIG_RTE_LIBRTE_RING) += -lrte_ring _LDLIBS-$(CONFIG_RTE_LIBRTE_PCI) += -lrte_pci _LDLIBS-$(CONFIG_RTE_LIBRTE_EAL) += -lrte_eal _LDLIBS-$(CONFIG_RTE_LIBRTE_CMDLINE) += -lrte_cmdline - -_LDLIBS-$(CONFIG_RTE_LIBRTE_CMDLINE) += $(shell pkg-config --libs libedit) _LDLIBS-$(CONFIG_RTE_LIBRTE_REORDER) += -lrte_reorder _LDLIBS-$(CONFIG_RTE_LIBRTE_SCHED) += -lrte_sched @@ -267,6 +265,7 @@ ifeq ($(CONFIG_RTE_LIBRTE_VHOST_NUMA),y) _LDLIBS-$(CONFIG_RTE_LIBRTE_VHOST) += -lnuma endif _LDLIBS-$(CONFIG_RTE_PORT_PCAP) += -lpcap +_LDLIBS-$(CONFIG_RTE_LIBRTE_CMDLINE) += $(shell pkg-config --libs libedit) endif # !CONFIG_RTE_BUILD_SHARED_LIBS _LDLIBS-y += $(EXECENV_LDLIBS) ^ permalink raw reply [flat|nested] 18+ messages in thread
* Re: [dpdk-dev] [PATCH v2] cmdline: rework as a wrapper to libedit 2018-06-26 13:21 ` Olivier Matz 2018-06-26 13:33 ` Olivier Matz @ 2018-06-27 10:36 ` Bruce Richardson 2018-06-27 11:35 ` Olivier Matz 1 sibling, 1 reply; 18+ messages in thread From: Bruce Richardson @ 2018-06-27 10:36 UTC (permalink / raw) To: Olivier Matz Cc: Adrien Mazarguil, dev, Keith Wiles, Jingjing Wu, Thomas Monjalon, Ferruh Yigit, Jim Thompson, Anatoly Burakov On Tue, Jun 26, 2018 at 03:21:21PM +0200, Olivier Matz wrote: > Hi Adrien, > > Better late than never, please find below some comments > about your patch. > > On Thu, Apr 19, 2018 at 05:13:53PM +0200, Adrien Mazarguil wrote: > > Disclaimer: this patch must not be confused with the CLI library [1] > > (work in progress) that will eventually supersede librte_cmdline itself > > with a different API. > > > > Rather, it modifies librte_cmdline to delegate all the heavy lifting > > (terminal and history handling), strips unused features and re-implements > > what remains of its public API as a wrapper to the editline library (also > > known as libedit) [2], a well-known, BSD-licensed and widely available > > library used by many projects which does everything needed and more [3]. > > > > This approach was chosen because converting librte_cmdline as a wrapper to > > a more capable library was easier and faster than addressing its > > shortcomings and results in much less code to maintain in DPDK. > > > > It also provides a drop-in solution for applications that rely on > > librte_cmdline. They benefit from greatly improved command line handling > > without a meaningful impact on their code base. > > > > The main motivation behind this patch is testpmd's flow (rte_flow) command, > > which requires support for dynamic tokens and very long lines that must be > > broken down when displayed. This is not supported by librte_cmdline's > > limited terminal handling capabilities, resulting in a rather frustrating > > user experience. > > > > It had to be addressed given the importance of testpmd as one of the > > primary tool used by PMD developers. > > > > This rework results in the following changes: > > > > - Removed circular buffer management interface for command history > > (cmdline_cirbuf.c), command history being handled by libedit. > > - Removed raw command-line interpreter (cmdline_rdline.c). > > - Removed raw terminal handler (cmdline_vt100.c). > > - Removed all test/example code for the above. > > - Re-implemented high level interactive and non-interactive command-line > > handlers (cmdline.c and cmdline_socket.c) on top of libedit using its > > native interface, not its readline compatibility layer. > > - Made struct cmdline opaque so that applications relying on librte_cmdline > > do not need to include any libedit headers. > > - Applications do not need to include cmdline_rdline.h anymore. > > - Terminal resizing is now automatically handled. > > - New external dependency for applications relying on librte_cmdline. > > - Major version bump due to the ABI impact of these changes. > > > > [1] http://dpdk.org/browse/draft/dpdk-draft-cli/ > > [2] http://thrysoee.dk/editline/ > > [3] http://netbsd.gw.com/cgi-bin/man-cgi?editline++NetBSD-current > > > > Signed-off-by: Adrien Mazarguil <adrien.mazarguil@6wind.com> > > Cc: Olivier Matz <olivier.matz@6wind.com> > > Cc: Keith Wiles <keith.wiles@intel.com> > > Cc: Jingjing Wu <jingjing.wu@intel.com> > > Cc: Thomas Monjalon <thomas@monjalon.net> > > Cc: Ferruh Yigit <ferruh.yigit@intel.com> > > Cc: Jim Thompson <jim@netgate.com> > > Cc: Anatoly Burakov <anatoly.burakov@intel.com> > > > > -- > > > > v2 changes: > > > > - Replaced an instance of snprintf() with rte_strlcpy() [5]. > > - Rebased patch. > > > > [5] http://dpdk.org/ml/archives/dev/2018-April/097721.html > > > > v1 changes: > > > > No fundamental change since the original RFC [4], except it's been rebased > > several times and Meson build support was added in the meantime. Commit log > > was also shortened a bit. > > > > I'm re-sending this because I think it's useful, at least to me (duh). As > > the maintainer of rte_flow, I spend most of my time typing flow commands in > > testpmd and libedit makes that a pleasant experience. > > > > Try it out! And don't hesitate to send your acked-by line to get this in > > time for 18.05 :) > > > > [4] http://dpdk.org/ml/archives/dev/2017-November/081605.html > > Re-saying what I said the first time: I think this is a very good > improvement, removing lots of dpdk code that is better implemented in > well-known libraries. > > > The compilation with shared libraries fail. Please try for instance: > ./devtools/test-build.sh -j4 x86_64-native-linuxapp-clang+shared+debug > > I suggest to add in lib/librte_cmdline/Makefile: > > LDLIBS += $(shell pkg-config --libs libedit) > > > I also think something should be added in > /doc/guides/linux_gsg/sys_reqs.rst to highlight the new build > dependency. > > > I noticed a bad behavior change (in addition to many good ones): > ctrl-c now quits the application, and this was not the case before. > I often use ctrl-c to delete the line I'm currently editing. Please > see at the end a proposition to restore this feature. > I 100% disagree, please set things up that "ctrl-c" quits the application. Having our DPDK testpmd and auto-test apps fail to close on ctrl-c is just awful from a usability perspective IMHO! If there is ever a problem with the app and you need to kill it quickly, e.g. you want to stop one of those long-running autotests, the lack of ctrl-c is a pain. For me, the only valid use-case for a command-line app to catch the signal from ctrl-c is to allow the app to do some cleanup before it quits. /Bruce ^ permalink raw reply [flat|nested] 18+ messages in thread
* Re: [dpdk-dev] [PATCH v2] cmdline: rework as a wrapper to libedit 2018-06-27 10:36 ` Bruce Richardson @ 2018-06-27 11:35 ` Olivier Matz 0 siblings, 0 replies; 18+ messages in thread From: Olivier Matz @ 2018-06-27 11:35 UTC (permalink / raw) To: Bruce Richardson Cc: Adrien Mazarguil, dev, Keith Wiles, Jingjing Wu, Thomas Monjalon, Ferruh Yigit, Jim Thompson, Anatoly Burakov On Wed, Jun 27, 2018 at 11:36:28AM +0100, Bruce Richardson wrote: > On Tue, Jun 26, 2018 at 03:21:21PM +0200, Olivier Matz wrote: > > Hi Adrien, > > > > Better late than never, please find below some comments > > about your patch. > > > > On Thu, Apr 19, 2018 at 05:13:53PM +0200, Adrien Mazarguil wrote: > > > Disclaimer: this patch must not be confused with the CLI library [1] > > > (work in progress) that will eventually supersede librte_cmdline itself > > > with a different API. > > > > > > Rather, it modifies librte_cmdline to delegate all the heavy lifting > > > (terminal and history handling), strips unused features and re-implements > > > what remains of its public API as a wrapper to the editline library (also > > > known as libedit) [2], a well-known, BSD-licensed and widely available > > > library used by many projects which does everything needed and more [3]. > > > > > > This approach was chosen because converting librte_cmdline as a wrapper to > > > a more capable library was easier and faster than addressing its > > > shortcomings and results in much less code to maintain in DPDK. > > > > > > It also provides a drop-in solution for applications that rely on > > > librte_cmdline. They benefit from greatly improved command line handling > > > without a meaningful impact on their code base. > > > > > > The main motivation behind this patch is testpmd's flow (rte_flow) command, > > > which requires support for dynamic tokens and very long lines that must be > > > broken down when displayed. This is not supported by librte_cmdline's > > > limited terminal handling capabilities, resulting in a rather frustrating > > > user experience. > > > > > > It had to be addressed given the importance of testpmd as one of the > > > primary tool used by PMD developers. > > > > > > This rework results in the following changes: > > > > > > - Removed circular buffer management interface for command history > > > (cmdline_cirbuf.c), command history being handled by libedit. > > > - Removed raw command-line interpreter (cmdline_rdline.c). > > > - Removed raw terminal handler (cmdline_vt100.c). > > > - Removed all test/example code for the above. > > > - Re-implemented high level interactive and non-interactive command-line > > > handlers (cmdline.c and cmdline_socket.c) on top of libedit using its > > > native interface, not its readline compatibility layer. > > > - Made struct cmdline opaque so that applications relying on librte_cmdline > > > do not need to include any libedit headers. > > > - Applications do not need to include cmdline_rdline.h anymore. > > > - Terminal resizing is now automatically handled. > > > - New external dependency for applications relying on librte_cmdline. > > > - Major version bump due to the ABI impact of these changes. > > > > > > [1] http://dpdk.org/browse/draft/dpdk-draft-cli/ > > > [2] http://thrysoee.dk/editline/ > > > [3] http://netbsd.gw.com/cgi-bin/man-cgi?editline++NetBSD-current > > > > > > Signed-off-by: Adrien Mazarguil <adrien.mazarguil@6wind.com> > > > Cc: Olivier Matz <olivier.matz@6wind.com> > > > Cc: Keith Wiles <keith.wiles@intel.com> > > > Cc: Jingjing Wu <jingjing.wu@intel.com> > > > Cc: Thomas Monjalon <thomas@monjalon.net> > > > Cc: Ferruh Yigit <ferruh.yigit@intel.com> > > > Cc: Jim Thompson <jim@netgate.com> > > > Cc: Anatoly Burakov <anatoly.burakov@intel.com> > > > > > > -- > > > > > > v2 changes: > > > > > > - Replaced an instance of snprintf() with rte_strlcpy() [5]. > > > - Rebased patch. > > > > > > [5] http://dpdk.org/ml/archives/dev/2018-April/097721.html > > > > > > v1 changes: > > > > > > No fundamental change since the original RFC [4], except it's been rebased > > > several times and Meson build support was added in the meantime. Commit log > > > was also shortened a bit. > > > > > > I'm re-sending this because I think it's useful, at least to me (duh). As > > > the maintainer of rte_flow, I spend most of my time typing flow commands in > > > testpmd and libedit makes that a pleasant experience. > > > > > > Try it out! And don't hesitate to send your acked-by line to get this in > > > time for 18.05 :) > > > > > > [4] http://dpdk.org/ml/archives/dev/2017-November/081605.html > > > > Re-saying what I said the first time: I think this is a very good > > improvement, removing lots of dpdk code that is better implemented in > > well-known libraries. > > > > > > The compilation with shared libraries fail. Please try for instance: > > ./devtools/test-build.sh -j4 x86_64-native-linuxapp-clang+shared+debug > > > > I suggest to add in lib/librte_cmdline/Makefile: > > > > LDLIBS += $(shell pkg-config --libs libedit) > > > > > > I also think something should be added in > > /doc/guides/linux_gsg/sys_reqs.rst to highlight the new build > > dependency. > > > > > > I noticed a bad behavior change (in addition to many good ones): > > ctrl-c now quits the application, and this was not the case before. > > I often use ctrl-c to delete the line I'm currently editing. Please > > see at the end a proposition to restore this feature. > > > > I 100% disagree, please set things up that "ctrl-c" quits the application. > > Having our DPDK testpmd and auto-test apps fail to close on ctrl-c is just > awful from a usability perspective IMHO! If there is ever a problem with > the app and you need to kill it quickly, e.g. you want to stop one of those > long-running autotests, the lack of ctrl-c is a pain. Well, this is a good argument. It looks that ctrl-u can do the job, so I may just need to change my habits :) Olivier ^ permalink raw reply [flat|nested] 18+ messages in thread
end of thread, other threads:[~2018-06-27 11:35 UTC | newest] Thread overview: 18+ messages (download: mbox.gz / follow: Atom feed) -- links below jump to the message on this page -- 2017-11-09 13:43 [dpdk-dev] [RFC] cmdline: rework as a wrapper to libedit Adrien Mazarguil 2017-11-15 4:12 ` Wiles, Keith 2017-11-15 8:04 ` Olivier MATZ 2017-11-15 16:31 ` Wiles, Keith 2017-11-16 9:23 ` Adrien Mazarguil 2017-11-16 16:48 ` Wiles, Keith 2017-11-16 18:07 ` Thomas Monjalon 2017-11-16 17:06 ` Ferruh Yigit 2017-11-16 17:27 ` Wiles, Keith 2017-11-16 18:05 ` Thomas Monjalon 2017-11-16 16:53 ` Jim Thompson 2018-04-17 15:21 ` [dpdk-dev] [PATCH v1] " Adrien Mazarguil 2018-04-17 15:59 ` Burakov, Anatoly 2018-04-19 15:13 ` [dpdk-dev] [PATCH v2] " Adrien Mazarguil 2018-06-26 13:21 ` Olivier Matz 2018-06-26 13:33 ` Olivier Matz 2018-06-27 10:36 ` Bruce Richardson 2018-06-27 11:35 ` Olivier Matz
This is a public inbox, see mirroring instructions for how to clone and mirror all data and code used for this inbox; as well as URLs for NNTP newsgroup(s).