Please note that diffs are not public domain; they are subject to the copyright notices on the relevant files. =================================================================== RCS file: /ftp/cvs/cvsroot/src/lib/libedit/readline.c,v rcsdiff: /ftp/cvs/cvsroot/src/lib/libedit/readline.c,v: warning: Unknown phrases like `commitid ...;' are present. retrieving revision 1.123 retrieving revision 1.136.2.1 diff -u -p -r1.123 -r1.136.2.1 --- src/lib/libedit/readline.c 2016/02/16 15:53:48 1.123 +++ src/lib/libedit/readline.c 2016/11/04 14:48:53 1.136.2.1 @@ -1,4 +1,4 @@ -/* $NetBSD: readline.c,v 1.123 2016/02/16 15:53:48 christos Exp $ */ +/* $NetBSD: readline.c,v 1.136.2.1 2016/11/04 14:48:53 pgoyette Exp $ */ /*- * Copyright (c) 1997 The NetBSD Foundation, Inc. @@ -31,28 +31,28 @@ #include "config.h" #if !defined(lint) && !defined(SCCSID) -__RCSID("$NetBSD: readline.c,v 1.123 2016/02/16 15:53:48 christos Exp $"); +__RCSID("$NetBSD: readline.c,v 1.136.2.1 2016/11/04 14:48:53 pgoyette Exp $"); #endif /* not lint && not SCCSID */ #include #include -#include -#include -#include -#include -#include #include -#include -#include -#include +#include #include #include +#include +#include #include +#include +#include +#include +#include +#include #include #include "readline/readline.h" #include "el.h" -#include "fcns.h" /* for EL_NUM_FCNS */ +#include "fcns.h" #include "filecomplete.h" void rl_prep_terminal(int); @@ -156,6 +156,14 @@ char *rl_special_prefixes = NULL; */ int rl_completion_append_character = ' '; +/* + * When the history cursor is on the newest element and next_history() + * is called, GNU readline moves the cursor beyond the newest element. + * The editline library does not provide data structures to express + * that state, so we need a local flag. + */ +static int current_history_valid = 1; + /* stuff below is used internally by libedit for readline emulation */ static History *h = NULL; @@ -167,13 +175,13 @@ static jmp_buf topbuf; static unsigned char _el_rl_complete(EditLine *, int); static unsigned char _el_rl_tstp(EditLine *, int); static char *_get_prompt(EditLine *); -static int _getc_function(EditLine *, char *); +static int _getc_function(EditLine *, wchar_t *); static HIST_ENTRY *_move_history(int); static int _history_expand_command(const char *, size_t, size_t, char **); static char *_rl_compat_sub(const char *, const char *, const char *, int); -static int _rl_event_read_char(EditLine *, char *); +static int _rl_event_read_char(EditLine *, wchar_t *); static void _rl_update_pos(void); @@ -210,14 +218,14 @@ _move_history(int op) */ static int /*ARGSUSED*/ -_getc_function(EditLine *el __attribute__((__unused__)), char *c) +_getc_function(EditLine *el __attribute__((__unused__)), wchar_t *c) { int i; - i = (*rl_getc_function)(NULL); + i = (*rl_getc_function)(rl_instream); if (i == -1) return 0; - *c = (char)i; + *c = (wchar_t)i; return 1; } @@ -267,7 +275,7 @@ rl_set_prompt(const char *prompt) if (!prompt) prompt = ""; - if (rl_prompt != NULL && strcmp(rl_prompt, prompt) == 0) + if (rl_prompt != NULL && strcmp(rl_prompt, prompt) == 0) return 0; if (rl_prompt) el_free(rl_prompt); @@ -291,6 +299,8 @@ rl_initialize(void) int editmode = 1; struct termios t; + current_history_valid = 1; + if (e != NULL) el_end(e); if (h != NULL) @@ -361,7 +371,7 @@ rl_initialize(void) "ReadLine compatible suspend function", _el_rl_tstp); el_set(e, EL_BIND, "^Z", "rl_tstp", NULL); - + /* * Set some readline compatible key-bindings. */ @@ -1168,12 +1178,22 @@ void stifle_history(int max) { HistEvent ev; + HIST_ENTRY *he; if (h == NULL || e == NULL) rl_initialize(); - if (history(h, &ev, H_SETSIZE, max) == 0) + if (history(h, &ev, H_SETSIZE, max) == 0) { max_input_history = max; + if (history_length > max) + history_base = history_length - max; + while (history_length > max) { + he = remove_history(0); + el_free(he->data); + el_free((void *)(unsigned long)he->line); + el_free(he); + } + } } @@ -1388,25 +1408,37 @@ history_get(int num) if (h == NULL || e == NULL) rl_initialize(); + if (num < history_base) + return NULL; + /* save current position */ if (history(h, &ev, H_CURR) != 0) return NULL; curr_num = ev.num; - /* start from the oldest */ - if (history(h, &ev, H_LAST) != 0) - return NULL; /* error */ - - /* look forwards for event matching specified offset */ - if (history(h, &ev, H_NEXT_EVDATA, num, &she.data)) - return NULL; + /* + * use H_DELDATA to set to nth history (without delete) by passing + * (void **)-1 -- as in history_set_pos + */ + if (history(h, &ev, H_DELDATA, num - history_base, (void **)-1) != 0) + goto out; + /* get current entry */ + if (history(h, &ev, H_CURR) != 0) + goto out; + if (history(h, &ev, H_NEXT_EVDATA, ev.num, &she.data) != 0) + goto out; she.line = ev.str; /* restore pointer to where it was */ (void)history(h, &ev, H_SET, curr_num); return &she; + +out: + /* restore pointer to where it was */ + (void)history(h, &ev, H_SET, curr_num); + return NULL; } @@ -1418,17 +1450,19 @@ add_history(const char *line) { HistEvent ev; - if (line == NULL) - return 0; - if (h == NULL || e == NULL) rl_initialize(); - (void)history(h, &ev, H_ENTER, line); - if (history(h, &ev, H_GETSIZE) == 0) - history_length = ev.num; + if (history(h, &ev, H_ENTER, line) == -1) + return 0; - return !(history_length > 0); /* return 0 if all is okay */ + (void)history(h, &ev, H_GETSIZE); + if (ev.num == history_length) + history_base++; + else + history_length = ev.num; + current_history_valid = 1; + return 0; } @@ -1519,6 +1553,7 @@ clear_history(void) (void)history(h, &ev, H_CLEAR); history_length = 0; + current_history_valid = 1; } @@ -1535,9 +1570,12 @@ where_history(void) return 0; curr_num = ev.num; - (void)history(h, &ev, H_FIRST); - off = 1; - while (ev.num != curr_num && history(h, &ev, H_NEXT) == 0) + /* start from the oldest */ + (void)history(h, &ev, H_LAST); + + /* position is zero-based */ + off = 0; + while (ev.num != curr_num && history(h, &ev, H_PREV) == 0) off++; return off; @@ -1551,7 +1589,7 @@ HIST_ENTRY * current_history(void) { - return _move_history(H_CURR); + return current_history_valid ? _move_history(H_CURR) : NULL; } @@ -1592,10 +1630,11 @@ history_set_pos(int pos) int curr_num; if (pos >= history_length || pos < 0) - return -1; + return 0; (void)history(h, &ev, H_CURR); curr_num = ev.num; + current_history_valid = 1; /* * use H_DELDATA to set to nth history (without delete) by passing @@ -1603,20 +1642,25 @@ history_set_pos(int pos) */ if (history(h, &ev, H_DELDATA, pos, (void **)-1)) { (void)history(h, &ev, H_SET, curr_num); - return -1; + return 0; } - return 0; + return 1; } /* * returns previous event in history and shifts pointer accordingly + * Note that readline and editline define directions in opposite ways. */ HIST_ENTRY * previous_history(void) { - return _move_history(H_PREV); + if (current_history_valid == 0) { + current_history_valid = 1; + return _move_history(H_CURR); + } + return _move_history(H_NEXT); } @@ -1626,8 +1670,12 @@ previous_history(void) HIST_ENTRY * next_history(void) { + HIST_ENTRY *he; - return _move_history(H_NEXT); + he = _move_history(H_PREV); + if (he == NULL) + current_history_valid = 0; + return he; } @@ -1688,7 +1736,7 @@ history_search_pos(const char *str, return -1; curr_num = ev.num; - if (history_set_pos(off) != 0 || history(h, &ev, H_CURR) != 0) + if (!history_set_pos(off) || history(h, &ev, H_CURR) != 0) return -1; for (;;) { @@ -1806,9 +1854,7 @@ _rl_completion_append_character_function int rl_complete(int ignore __attribute__((__unused__)), int invoking_key) { -#ifdef WIDECHAR static ct_buffer_t wbreak_conv, sprefix_conv; -#endif char *breakchars; if (h == NULL || e == NULL) @@ -2008,7 +2054,7 @@ rl_callback_read_char(void) } } -void +void rl_callback_handler_install(const char *prompt, rl_vcpfunc_t *linefunc) { if (e == NULL) { @@ -2017,9 +2063,9 @@ rl_callback_handler_install(const char * (void)rl_set_prompt(prompt); rl_linefunc = linefunc; el_set(e, EL_UNBUFFERED, 1); -} +} -void +void rl_callback_handler_remove(void) { el_set(e, EL_UNBUFFERED, 0); @@ -2100,12 +2146,14 @@ rl_stuff_char(int c) } static int -_rl_event_read_char(EditLine *el, char *cp) +_rl_event_read_char(EditLine *el, wchar_t *wc) { + char ch; int n; ssize_t num_read = 0; - *cp = '\0'; + ch = '\0'; + *wc = L'\0'; while (rl_event_hook) { (*rl_event_hook)(); @@ -2114,7 +2162,7 @@ _rl_event_read_char(EditLine *el, char * if (ioctl(el->el_infd, FIONREAD, &n) < 0) return -1; if (n) - num_read = read(el->el_infd, cp, (size_t)1); + num_read = read(el->el_infd, &ch, (size_t)1); else num_read = 0; #elif defined(F_SETFL) && defined(O_NDELAY) @@ -2122,12 +2170,12 @@ _rl_event_read_char(EditLine *el, char * return -1; if (fcntl(el->el_infd, F_SETFL, n|O_NDELAY) < 0) return -1; - num_read = read(el->el_infd, cp, 1); + num_read = read(el->el_infd, &ch, 1); if (fcntl(el->el_infd, F_SETFL, n)) return -1; #else /* not non-blocking, but what you gonna do? */ - num_read = read(el->el_infd, cp, 1); + num_read = read(el->el_infd, &ch, 1); return -1; #endif @@ -2139,6 +2187,7 @@ _rl_event_read_char(EditLine *el, char * } if (!rl_event_hook) el_set(el, EL_GETCFN, EL_BUILTIN_GETCFN); + *wc = (wchar_t)ch; return (int)num_read; } @@ -2219,7 +2268,7 @@ rl_completion_matches(const char *str, r list[0][min] = '\0'; } return list; - + out: el_free(list); return NULL;