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.56 retrieving revision 1.83 diff -u -p -r1.56 -r1.83 --- src/lib/libedit/readline.c 2005/06/10 20:21:00 1.56 +++ src/lib/libedit/readline.c 2009/04/08 21:31:31 1.83 @@ -1,4 +1,4 @@ -/* $NetBSD: readline.c,v 1.56 2005/06/10 20:21:00 christos Exp $ */ +/* $NetBSD: readline.c,v 1.83 2009/04/08 21:31:31 christos Exp $ */ /*- * Copyright (c) 1997 The NetBSD Foundation, Inc. @@ -15,13 +15,6 @@ * 2. 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. - * 3. All advertising materials mentioning features or use of this software - * must display the following acknowledgement: - * This product includes software developed by the NetBSD - * Foundation, Inc. and its contributors. - * 4. Neither the name of The NetBSD Foundation 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 NETBSD FOUNDATION, INC. AND CONTRIBUTORS * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED @@ -38,7 +31,7 @@ #include "config.h" #if !defined(lint) && !defined(SCCSID) -__RCSID("$NetBSD: readline.c,v 1.56 2005/06/10 20:21:00 christos Exp $"); +__RCSID("$NetBSD: readline.c,v 1.83 2009/04/08 21:31:31 christos Exp $"); #endif /* not lint && not SCCSID */ #include @@ -53,20 +46,21 @@ __RCSID("$NetBSD: readline.c,v 1.56 2005 #include #include #include +#include #ifdef HAVE_VIS_H #include #else #include "np/vis.h" #endif -#ifdef HAVE_ALLOCA_H -#include -#endif +#include "readline/readline.h" #include "el.h" #include "fcns.h" /* for EL_NUM_FCNS */ #include "histedit.h" -#include "readline/readline.h" #include "filecomplete.h" +void rl_prep_terminal(int); +void rl_deprep_terminal(void); + /* for rl_complete() */ #define TAB '\r' @@ -89,6 +83,9 @@ char *rl_line_buffer = NULL; VCPFunction *rl_linefunc = NULL; int rl_done = 0; VFunction *rl_event_hook = NULL; +KEYMAP_ENTRY_ARRAY emacs_standard_keymap, + emacs_meta_keymap, + emacs_ctlx_keymap; int history_base = 1; /* probably never subject to change */ int history_length = 0; @@ -108,17 +105,19 @@ Function *rl_completion_entry_function = CPPFunction *rl_attempted_completion_function = NULL; Function *rl_pre_input_hook = NULL; Function *rl_startup1_hook = NULL; -Function *rl_getc_function = NULL; +int (*rl_getc_function)(FILE *) = NULL; char *rl_terminal_name = NULL; int rl_already_prompted = 0; int rl_filename_completion_desired = 0; int rl_ignore_completion_duplicates = 0; int rl_catch_signals = 1; +int readline_echoing_p = 1; +int _rl_print_completions_horizontally = 0; VFunction *rl_redisplay_function = NULL; Function *rl_startup_hook = NULL; VFunction *rl_completion_display_matches_hook = NULL; -VFunction *rl_prep_term_function = NULL; -VFunction *rl_deprep_term_function = NULL; +VFunction *rl_prep_term_function = (VFunction *)rl_prep_terminal; +VFunction *rl_deprep_term_function = (VFunction *)rl_deprep_terminal; /* * The current prompt string. @@ -155,11 +154,13 @@ int rl_completion_append_character = ' ' static History *h = NULL; static EditLine *e = NULL; static Function *map[256]; +static jmp_buf topbuf; /* internal functions */ 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 HIST_ENTRY *_move_history(int); static int _history_expand_command(const char *, size_t, size_t, char **); @@ -198,10 +199,51 @@ _move_history(int op) /* + * read one key from user defined input function + */ +static int +/*ARGSUSED*/ +_getc_function(EditLine *el, char *c) +{ + int i; + + i = (*rl_getc_function)(NULL); + if (i == -1) + return 0; + *c = i; + return 1; +} + + +/* * READLINE compatibility stuff */ /* + * Set the prompt + */ +int +rl_set_prompt(const char *prompt) +{ + char *p; + + if (!prompt) + prompt = ""; + if (rl_prompt != NULL && strcmp(rl_prompt, prompt) == 0) + return 0; + if (rl_prompt) + free(rl_prompt); + rl_prompt = strdup(prompt); + if (rl_prompt == NULL) + return -1; + + while ((p = strchr(rl_prompt, RL_PROMPT_END_IGNORE)) != NULL) + *p = RL_PROMPT_START_IGNORE; + + return 0; +} + +/* * initialize rl compat stuff */ int @@ -242,14 +284,17 @@ rl_initialize(void) max_input_history = INT_MAX; el_set(e, EL_HIST, history, h); + /* setup getc function if valid */ + if (rl_getc_function) + el_set(e, EL_GETCFN, _getc_function); + /* for proper prompt printing in readline() */ - rl_prompt = strdup(""); - if (rl_prompt == NULL) { + if (rl_set_prompt("") == -1) { history_end(h); el_end(e); return -1; } - el_set(e, EL_PROMPT, _get_prompt); + el_set(e, EL_PROMPT, _get_prompt, RL_PROMPT_START_IGNORE); el_set(e, EL_SIGNAL, rl_catch_signals); /* set default mode to "emacs"-style and read setting afterwards */ @@ -301,9 +346,10 @@ rl_initialize(void) * trailing newline (if there is any) */ char * -readline(const char *prompt) +readline(const char *p) { HistEvent ev; + const char * volatile prompt = p; int count; const char *ret; char *buf; @@ -314,15 +360,11 @@ readline(const char *prompt) rl_done = 0; + (void)setjmp(topbuf); + /* update prompt accordingly to what has been passed */ - if (!prompt) - prompt = ""; - if (strcmp(rl_prompt, prompt) != 0) { - free(rl_prompt); - rl_prompt = strdup(prompt); - if (rl_prompt == NULL) - return NULL; - } + if (rl_set_prompt(prompt) == -1) + return NULL; if (rl_pre_input_hook) (*rl_pre_input_hook)(NULL, 0); @@ -420,7 +462,7 @@ _rl_compat_sub(const char *str, const ch } else *r++ = *s++; } - *r = 0; + *r = '\0'; return(result); } @@ -441,7 +483,7 @@ get_history_event(const char *cmd, int * return(NULL); /* find out which event to take */ - if (cmd[idx] == history_expansion_char || cmd[idx] == 0) { + if (cmd[idx] == history_expansion_char || cmd[idx] == '\0') { if (history(h, &ev, H_FIRST) != 0) return(NULL); *cindex = cmd[idx]? (idx + 1):idx; @@ -663,7 +705,7 @@ _history_expand_command(const char *comm if (aptr) free(aptr); - if (*cmd == 0 || (cmd - (command + offs) >= cmdlen)) { + if (*cmd == '\0' || ((size_t)(cmd - (command + offs)) >= cmdlen)) { *result = tmp; return(1); } @@ -673,7 +715,7 @@ _history_expand_command(const char *comm continue; else if (*cmd == 'h') { /* remove trailing path */ if ((aptr = strrchr(tmp, '/')) != NULL) - *aptr = 0; + *aptr = '\0'; } else if (*cmd == 't') { /* remove leading path */ if ((aptr = strrchr(tmp, '/')) != NULL) { aptr = strdup(aptr + 1); @@ -682,7 +724,7 @@ _history_expand_command(const char *comm } } else if (*cmd == 'r') { /* remove trailing suffix */ if ((aptr = strrchr(tmp, '.')) != NULL) - *aptr = 0; + *aptr = '\0'; } else if (*cmd == 'e') { /* remove all but suffix */ if ((aptr = strrchr(tmp, '.')) != NULL) { aptr = strdup(aptr); @@ -706,6 +748,7 @@ _history_expand_command(const char *comm what = realloc(from, size); if (what == NULL) { free(from); + free(tmp); return 0; } len = 0; @@ -718,6 +761,7 @@ _history_expand_command(const char *comm (size <<= 1)); if (nwhat == NULL) { free(what); + free(tmp); return 0; } what = nwhat; @@ -730,10 +774,13 @@ _history_expand_command(const char *comm free(what); if (search) { from = strdup(search); - if (from == NULL) + if (from == NULL) { + free(tmp); return 0; + } } else { from = NULL; + free(tmp); return (-1); } } @@ -745,6 +792,7 @@ _history_expand_command(const char *comm with = realloc(to, size); if (with == NULL) { free(to); + free(tmp); return -1; } len = 0; @@ -756,6 +804,7 @@ _history_expand_command(const char *comm nwith = realloc(with, size); if (nwith == NULL) { free(with); + free(tmp); return -1; } with = nwith; @@ -824,12 +873,14 @@ history_expand(char *str, char **output) return 0; } -#define ADD_STRING(what, len) \ +#define ADD_STRING(what, len, fr) \ { \ if (idx + len + 1 > size) { \ char *nresult = realloc(result, (size += len + 1));\ if (nresult == NULL) { \ free(*output); \ + if (/*CONSTCOND*/fr) \ + free(tmp); \ return 0; \ } \ result = nresult; \ @@ -841,6 +892,7 @@ history_expand(char *str, char **output) result = NULL; size = idx = 0; + tmp = NULL; for (i = 0; str[i];) { int qchar, loop_again; size_t len, start, j; @@ -878,13 +930,11 @@ loop: goto loop; } len = i - start; - tmp = &str[start]; - ADD_STRING(tmp, len); + ADD_STRING(&str[start], len, 0); if (str[i] == '\0' || str[i] != history_expansion_char) { len = j - i; - tmp = &str[i]; - ADD_STRING(tmp, len); + ADD_STRING(&str[i], len, 0); if (start == 0) ret = 0; else @@ -894,8 +944,11 @@ loop: ret = _history_expand_command (str, i, (j - i), &tmp); if (ret > 0 && tmp) { len = strlen(tmp); - ADD_STRING(tmp, len); + ADD_STRING(tmp, len, 1); + } + if (tmp) { free(tmp); + tmp = NULL; } i = j; } @@ -939,31 +992,31 @@ history_arg_extract(int start, int end, max--; if (start == '$') - start = max; + start = (int)max; if (end == '$') - end = max; + end = (int)max; if (end < 0) - end = max + end + 1; + end = (int)max + end + 1; if (start < 0) start = end; - if (start < 0 || end < 0 || start > max || end > max || start > end) + if (start < 0 || end < 0 || (size_t)start > max || (size_t)end > max || start > end) return(NULL); - for (i = start, len = 0; i <= end; i++) + for (i = start, len = 0; i <= (size_t)end; i++) len += strlen(arr[i]) + 1; len++; result = malloc(len); if (result == NULL) return NULL; - for (i = start, len = 0; i <= end; i++) { + for (i = start, len = 0; i <= (size_t)end; i++) { (void)strcpy(result + len, arr[i]); len += strlen(arr[i]); - if (i < end) + if (i < (size_t)end) result[len++] = ' '; } - result[len] = 0; + result[len] = '\0'; for (i = 0; arr[i]; i++) free(arr[i]); @@ -1083,7 +1136,7 @@ read_history(const char *filename) if (h == NULL || e == NULL) rl_initialize(); - return (history(h, &ev, H_LOAD, filename)); + return (history(h, &ev, H_LOAD, filename) == -1); } @@ -1097,7 +1150,7 @@ write_history(const char *filename) if (h == NULL || e == NULL) rl_initialize(); - return (history(h, &ev, H_SAVE, filename)); + return (history(h, &ev, H_SAVE, filename) == -1); } @@ -1126,7 +1179,7 @@ history_get(int num) return (NULL); /* error */ /* look backwards for event matching specified offset */ - if (history(h, &ev, H_NEXT_EVENT, num)) + if (history(h, &ev, H_NEXT_EVENT, num + 1)) return (NULL); she.line = ev.str; @@ -1159,6 +1212,31 @@ add_history(const char *line) /* + * remove the specified entry from the history list and return it. + */ +HIST_ENTRY * +remove_history(int num) +{ + HIST_ENTRY *she; + HistEvent ev; + + if (h == NULL || e == NULL) + rl_initialize(); + + if (history(h, &ev, H_DEL, num) != 0) + return NULL; + + if ((she = malloc(sizeof(*she))) == NULL) + return NULL; + + she->line = ev.str; + she->data = NULL; + + return she; +} + + +/* * clear the history list - delete all entries */ void @@ -1210,7 +1288,8 @@ int history_total_bytes(void) { HistEvent ev; - int curr_num, size; + int curr_num; + size_t size; if (history(h, &ev, H_CURR) != 0) return (-1); @@ -1225,7 +1304,7 @@ history_total_bytes(void) /* get to the same position as before */ history(h, &ev, H_PREV_EVENT, curr_num); - return (size); + return (int)(size); } @@ -1351,6 +1430,18 @@ history_search_pos(const char *str, /********************************/ /* completion functions */ +char * +tilde_expand(char *name) +{ + return fn_tilde_expand(name); +} + +char * +filename_completion_function(const char *name, int state) +{ + return fn_filename_completion_function(name, state); +} + /* * a completion generator for usernames; returns _first_ username * which starts with supplied text @@ -1405,7 +1496,7 @@ void rl_display_match_list(char **matches, int len, int max) { - fn_display_match_list(e, matches, len, max); + fn_display_match_list(e, matches, (size_t)len, (size_t)max); } static const char * @@ -1414,7 +1505,8 @@ _rl_completion_append_character_function __attribute__((__unused__))) { static char buf[2]; - buf[1] = rl_completion_append_character; + buf[0] = rl_completion_append_character; + buf[1] = '\0'; return buf; } @@ -1442,7 +1534,8 @@ rl_complete(int ignore __attribute__((__ (CPFunction *)rl_completion_entry_function, rl_attempted_completion_function, rl_basic_word_break_characters, rl_special_prefixes, - _rl_completion_append_character_function, rl_completion_query_items, + _rl_completion_append_character_function, + (size_t)rl_completion_query_items, &rl_completion_type, &rl_attempted_completion_over, &rl_point, &rl_end); } @@ -1562,7 +1655,7 @@ int rl_add_defun(const char *name, Function *fun, int c) { char dest[8]; - if (c >= sizeof(map) / sizeof(map[0]) || c < 0) + if ((size_t)c >= sizeof(map) / sizeof(map[0]) || c < 0) return -1; map[(unsigned char)c] = fun; el_set(e, EL_ADDFN, name, name, rl_bind_wrapper); @@ -1580,7 +1673,7 @@ rl_callback_read_char() if (buf == NULL || count-- <= 0) return; - if (count == 0 && buf[0] == CTRL('d')) + if (count == 0 && buf[0] == e->el_tty.t_c[TS_IO][C_EOF]) done = 1; if (buf[count] == '\n' || buf[count] == '\r') done = 2; @@ -1598,14 +1691,12 @@ rl_callback_read_char() } void -rl_callback_handler_install (const char *prompt, VCPFunction *linefunc) +rl_callback_handler_install(const char *prompt, VCPFunction *linefunc) { if (e == NULL) { rl_initialize(); } - if (rl_prompt) - free(rl_prompt); - rl_prompt = prompt ? strdup(strchr(prompt, *prompt)) : NULL; + (void)rl_set_prompt(prompt); rl_linefunc = linefunc; el_set(e, EL_UNBUFFERED, 1); } @@ -1614,13 +1705,14 @@ void rl_callback_handler_remove(void) { el_set(e, EL_UNBUFFERED, 0); + rl_linefunc = NULL; } void rl_redisplay(void) { char a[2]; - a[0] = CTRL('r'); + a[0] = e->el_tty.t_c[TS_IO][C_REPRINT]; a[1] = '\0'; el_push(e, a); } @@ -1644,7 +1736,7 @@ rl_prep_terminal(int meta_flag) } void -rl_deprep_terminal() +rl_deprep_terminal(void) { el_set(e, EL_PREP_TERM, 0); } @@ -1692,9 +1784,10 @@ rl_stuff_char(int c) static int _rl_event_read_char(EditLine *el, char *cp) { - int n, num_read = 0; + int n; + ssize_t num_read = 0; - *cp = 0; + *cp = '\0'; while (rl_event_hook) { (*rl_event_hook)(); @@ -1728,7 +1821,7 @@ _rl_event_read_char(EditLine *el, char * } if (!rl_event_hook) el_set(el, EL_GETCFN, EL_BUILTIN_GETCFN); - return(num_read); + return (int)num_read; } static void @@ -1736,6 +1829,145 @@ _rl_update_pos(void) { const LineInfo *li = el_line(e); - rl_point = li->cursor - li->buffer; - rl_end = li->lastchar - li->buffer; + rl_point = (int)(li->cursor - li->buffer); + rl_end = (int)(li->lastchar - li->buffer); +} + +void +rl_get_screen_size(int *rows, int *cols) +{ + if (rows) + el_get(e, EL_GETTC, "li", rows); + if (cols) + el_get(e, EL_GETTC, "co", cols); +} + +void +rl_set_screen_size(int rows, int cols) +{ + char buf[64]; + (void)snprintf(buf, sizeof(buf), "%d", rows); + el_set(e, EL_SETTC, "li", buf); + (void)snprintf(buf, sizeof(buf), "%d", cols); + el_set(e, EL_SETTC, "co", buf); +} + +char ** +rl_completion_matches(const char *str, rl_compentry_func_t *fun) +{ + size_t len, max, i, j, min; + char **list, *match, *a, *b; + + len = 1; + max = 10; + if ((list = malloc(max * sizeof(*list))) == NULL) + return NULL; + + while ((match = (*fun)(str, (int)(len - 1))) != NULL) { + list[len++] = match; + if (len == max) { + char **nl; + max += 10; + if ((nl = realloc(list, max * sizeof(*nl))) == NULL) + goto out; + list = nl; + } + } + if (len == 1) + goto out; + list[len] = NULL; + if (len == 2) { + if ((list[0] = strdup(list[1])) == NULL) + goto out; + return list; + } + qsort(&list[1], len - 1, sizeof(*list), + (int (*)(const void *, const void *)) strcmp); + min = SIZE_T_MAX; + for (i = 1, a = list[i]; i < len - 1; i++, a = b) { + b = list[i + 1]; + for (j = 0; a[j] && a[j] == b[j]; j++) + continue; + if (min > j) + min = j; + } + if (min == 0 && *str) { + if ((list[0] = strdup(str)) == NULL) + goto out; + } else { + if ((list[0] = malloc(min + 1)) == NULL) + goto out; + (void)memcpy(list[0], list[1], min); + list[0][min] = '\0'; + } + return list; + +out: + free(list); + return NULL; +} + +char * +rl_filename_completion_function (const char *text, int state) +{ + return fn_filename_completion_function(text, state); +} + +void +rl_forced_update_display(void) +{ + el_set(e, EL_REFRESH); +} + +int +_rl_abort_internal(void) +{ + el_beep(e); + longjmp(topbuf, 1); + /*NOTREACHED*/ +} + +int +_rl_qsort_string_compare(char **s1, char **s2) +{ + return strcoll(*s1, *s2); +} + +int +/*ARGSUSED*/ +rl_kill_text(int from, int to) +{ + return 0; +} + +Keymap +rl_make_bare_keymap(void) +{ + return NULL; +} + +Keymap +rl_get_keymap(void) +{ + return NULL; +} + +void +/*ARGSUSED*/ +rl_set_keymap(Keymap k) +{ +} + +int +/*ARGSUSED*/ +rl_generic_bind(int type, const char * keyseq, const char * data, Keymap k) +{ + return 0; +} + +int +/*ARGSUSED*/ +rl_bind_key_in_map(int key, Function *fun, Keymap k) +{ + return 0; }