version 1.69, 2006/08/21 12:45:30 |
version 1.83, 2009/04/08 21:31:31 |
|
|
* 2. Redistributions in binary form must reproduce the above copyright |
* 2. Redistributions in binary form must reproduce the above copyright |
* notice, this list of conditions and the following disclaimer in the |
* notice, this list of conditions and the following disclaimer in the |
* documentation and/or other materials provided with the distribution. |
* documentation and/or other materials provided with the distribution. |
* 3. 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 |
* THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS |
* ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED |
* ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED |
Line 49 __RCSID("$NetBSD$"); |
|
Line 46 __RCSID("$NetBSD$"); |
|
#include <limits.h> |
#include <limits.h> |
#include <errno.h> |
#include <errno.h> |
#include <fcntl.h> |
#include <fcntl.h> |
|
#include <setjmp.h> |
#ifdef HAVE_VIS_H |
#ifdef HAVE_VIS_H |
#include <vis.h> |
#include <vis.h> |
#else |
#else |
#include "np/vis.h" |
#include "np/vis.h" |
#endif |
#endif |
#ifdef HAVE_ALLOCA_H |
#include "readline/readline.h" |
#include <alloca.h> |
|
#endif |
|
#include "el.h" |
#include "el.h" |
#include "fcns.h" /* for EL_NUM_FCNS */ |
#include "fcns.h" /* for EL_NUM_FCNS */ |
#include "histedit.h" |
#include "histedit.h" |
#include "readline/readline.h" |
|
#include "filecomplete.h" |
#include "filecomplete.h" |
|
|
void rl_prep_terminal(int); |
void rl_prep_terminal(int); |
Line 88 char *rl_line_buffer = NULL; |
|
Line 83 char *rl_line_buffer = NULL; |
|
VCPFunction *rl_linefunc = NULL; |
VCPFunction *rl_linefunc = NULL; |
int rl_done = 0; |
int rl_done = 0; |
VFunction *rl_event_hook = NULL; |
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_base = 1; /* probably never subject to change */ |
int history_length = 0; |
int history_length = 0; |
Line 107 Function *rl_completion_entry_function = |
|
Line 105 Function *rl_completion_entry_function = |
|
CPPFunction *rl_attempted_completion_function = NULL; |
CPPFunction *rl_attempted_completion_function = NULL; |
Function *rl_pre_input_hook = NULL; |
Function *rl_pre_input_hook = NULL; |
Function *rl_startup1_hook = NULL; |
Function *rl_startup1_hook = NULL; |
Function *rl_getc_function = NULL; |
int (*rl_getc_function)(FILE *) = NULL; |
char *rl_terminal_name = NULL; |
char *rl_terminal_name = NULL; |
int rl_already_prompted = 0; |
int rl_already_prompted = 0; |
int rl_filename_completion_desired = 0; |
int rl_filename_completion_desired = 0; |
int rl_ignore_completion_duplicates = 0; |
int rl_ignore_completion_duplicates = 0; |
int rl_catch_signals = 1; |
int rl_catch_signals = 1; |
|
int readline_echoing_p = 1; |
|
int _rl_print_completions_horizontally = 0; |
VFunction *rl_redisplay_function = NULL; |
VFunction *rl_redisplay_function = NULL; |
Function *rl_startup_hook = NULL; |
Function *rl_startup_hook = NULL; |
VFunction *rl_completion_display_matches_hook = NULL; |
VFunction *rl_completion_display_matches_hook = NULL; |
Line 154 int rl_completion_append_character = ' ' |
|
Line 154 int rl_completion_append_character = ' ' |
|
static History *h = NULL; |
static History *h = NULL; |
static EditLine *e = NULL; |
static EditLine *e = NULL; |
static Function *map[256]; |
static Function *map[256]; |
|
static jmp_buf topbuf; |
|
|
/* internal functions */ |
/* internal functions */ |
static unsigned char _el_rl_complete(EditLine *, int); |
static unsigned char _el_rl_complete(EditLine *, int); |
Line 206 _getc_function(EditLine *el, char *c) |
|
Line 207 _getc_function(EditLine *el, char *c) |
|
{ |
{ |
int i; |
int i; |
|
|
i = (*rl_getc_function)(NULL, 0); |
i = (*rl_getc_function)(NULL); |
if (i == -1) |
if (i == -1) |
return 0; |
return 0; |
*c = i; |
*c = i; |
Line 219 _getc_function(EditLine *el, char *c) |
|
Line 220 _getc_function(EditLine *el, char *c) |
|
*/ |
*/ |
|
|
/* |
/* |
|
* 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 |
* initialize rl compat stuff |
*/ |
*/ |
int |
int |
Line 264 rl_initialize(void) |
|
Line 289 rl_initialize(void) |
|
el_set(e, EL_GETCFN, _getc_function); |
el_set(e, EL_GETCFN, _getc_function); |
|
|
/* for proper prompt printing in readline() */ |
/* for proper prompt printing in readline() */ |
rl_prompt = strdup(""); |
if (rl_set_prompt("") == -1) { |
if (rl_prompt == NULL) { |
|
history_end(h); |
history_end(h); |
el_end(e); |
el_end(e); |
return -1; |
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); |
el_set(e, EL_SIGNAL, rl_catch_signals); |
|
|
/* set default mode to "emacs"-style and read setting afterwards */ |
/* set default mode to "emacs"-style and read setting afterwards */ |
Line 322 rl_initialize(void) |
|
Line 346 rl_initialize(void) |
|
* trailing newline (if there is any) |
* trailing newline (if there is any) |
*/ |
*/ |
char * |
char * |
readline(const char *prompt) |
readline(const char *p) |
{ |
{ |
HistEvent ev; |
HistEvent ev; |
|
const char * volatile prompt = p; |
int count; |
int count; |
const char *ret; |
const char *ret; |
char *buf; |
char *buf; |
Line 335 readline(const char *prompt) |
|
Line 360 readline(const char *prompt) |
|
|
|
rl_done = 0; |
rl_done = 0; |
|
|
|
(void)setjmp(topbuf); |
|
|
/* update prompt accordingly to what has been passed */ |
/* update prompt accordingly to what has been passed */ |
if (!prompt) |
if (rl_set_prompt(prompt) == -1) |
prompt = ""; |
return NULL; |
if (strcmp(rl_prompt, prompt) != 0) { |
|
free(rl_prompt); |
|
rl_prompt = strdup(prompt); |
|
if (rl_prompt == NULL) |
|
return NULL; |
|
} |
|
|
|
if (rl_pre_input_hook) |
if (rl_pre_input_hook) |
(*rl_pre_input_hook)(NULL, 0); |
(*rl_pre_input_hook)(NULL, 0); |
Line 441 _rl_compat_sub(const char *str, const ch |
|
Line 462 _rl_compat_sub(const char *str, const ch |
|
} else |
} else |
*r++ = *s++; |
*r++ = *s++; |
} |
} |
*r = 0; |
*r = '\0'; |
return(result); |
return(result); |
} |
} |
|
|
Line 462 get_history_event(const char *cmd, int * |
|
Line 483 get_history_event(const char *cmd, int * |
|
return(NULL); |
return(NULL); |
|
|
/* find out which event to take */ |
/* 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) |
if (history(h, &ev, H_FIRST) != 0) |
return(NULL); |
return(NULL); |
*cindex = cmd[idx]? (idx + 1):idx; |
*cindex = cmd[idx]? (idx + 1):idx; |
Line 684 _history_expand_command(const char *comm |
|
Line 705 _history_expand_command(const char *comm |
|
if (aptr) |
if (aptr) |
free(aptr); |
free(aptr); |
|
|
if (*cmd == 0 || (cmd - (command + offs) >= cmdlen)) { |
if (*cmd == '\0' || ((size_t)(cmd - (command + offs)) >= cmdlen)) { |
*result = tmp; |
*result = tmp; |
return(1); |
return(1); |
} |
} |
Line 694 _history_expand_command(const char *comm |
|
Line 715 _history_expand_command(const char *comm |
|
continue; |
continue; |
else if (*cmd == 'h') { /* remove trailing path */ |
else if (*cmd == 'h') { /* remove trailing path */ |
if ((aptr = strrchr(tmp, '/')) != NULL) |
if ((aptr = strrchr(tmp, '/')) != NULL) |
*aptr = 0; |
*aptr = '\0'; |
} else if (*cmd == 't') { /* remove leading path */ |
} else if (*cmd == 't') { /* remove leading path */ |
if ((aptr = strrchr(tmp, '/')) != NULL) { |
if ((aptr = strrchr(tmp, '/')) != NULL) { |
aptr = strdup(aptr + 1); |
aptr = strdup(aptr + 1); |
Line 703 _history_expand_command(const char *comm |
|
Line 724 _history_expand_command(const char *comm |
|
} |
} |
} else if (*cmd == 'r') { /* remove trailing suffix */ |
} else if (*cmd == 'r') { /* remove trailing suffix */ |
if ((aptr = strrchr(tmp, '.')) != NULL) |
if ((aptr = strrchr(tmp, '.')) != NULL) |
*aptr = 0; |
*aptr = '\0'; |
} else if (*cmd == 'e') { /* remove all but suffix */ |
} else if (*cmd == 'e') { /* remove all but suffix */ |
if ((aptr = strrchr(tmp, '.')) != NULL) { |
if ((aptr = strrchr(tmp, '.')) != NULL) { |
aptr = strdup(aptr); |
aptr = strdup(aptr); |
Line 971 history_arg_extract(int start, int end, |
|
Line 992 history_arg_extract(int start, int end, |
|
max--; |
max--; |
|
|
if (start == '$') |
if (start == '$') |
start = max; |
start = (int)max; |
if (end == '$') |
if (end == '$') |
end = max; |
end = (int)max; |
if (end < 0) |
if (end < 0) |
end = max + end + 1; |
end = (int)max + end + 1; |
if (start < 0) |
if (start < 0) |
start = end; |
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); |
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 += strlen(arr[i]) + 1; |
len++; |
len++; |
result = malloc(len); |
result = malloc(len); |
if (result == NULL) |
if (result == NULL) |
return 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]); |
(void)strcpy(result + len, arr[i]); |
len += strlen(arr[i]); |
len += strlen(arr[i]); |
if (i < end) |
if (i < (size_t)end) |
result[len++] = ' '; |
result[len++] = ' '; |
} |
} |
result[len] = 0; |
result[len] = '\0'; |
|
|
for (i = 0; arr[i]; i++) |
for (i = 0; arr[i]; i++) |
free(arr[i]); |
free(arr[i]); |
Line 1158 history_get(int num) |
|
Line 1179 history_get(int num) |
|
return (NULL); /* error */ |
return (NULL); /* error */ |
|
|
/* look backwards for event matching specified offset */ |
/* 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); |
return (NULL); |
|
|
she.line = ev.str; |
she.line = ev.str; |
Line 1196 add_history(const char *line) |
|
Line 1217 add_history(const char *line) |
|
HIST_ENTRY * |
HIST_ENTRY * |
remove_history(int num) |
remove_history(int num) |
{ |
{ |
static HIST_ENTRY she; |
HIST_ENTRY *she; |
HistEvent ev; |
HistEvent ev; |
|
|
if (h == NULL || e == NULL) |
if (h == NULL || e == NULL) |
Line 1205 remove_history(int num) |
|
Line 1226 remove_history(int num) |
|
if (history(h, &ev, H_DEL, num) != 0) |
if (history(h, &ev, H_DEL, num) != 0) |
return NULL; |
return NULL; |
|
|
she.line = ev.str; |
if ((she = malloc(sizeof(*she))) == NULL) |
she.data = NULL; |
return NULL; |
|
|
return &she; |
she->line = ev.str; |
|
she->data = NULL; |
|
|
|
return she; |
} |
} |
|
|
|
|
|
|
history_total_bytes(void) |
history_total_bytes(void) |
{ |
{ |
HistEvent ev; |
HistEvent ev; |
int curr_num, size; |
int curr_num; |
|
size_t size; |
|
|
if (history(h, &ev, H_CURR) != 0) |
if (history(h, &ev, H_CURR) != 0) |
return (-1); |
return (-1); |
Line 1279 history_total_bytes(void) |
|
Line 1304 history_total_bytes(void) |
|
/* get to the same position as before */ |
/* get to the same position as before */ |
history(h, &ev, H_PREV_EVENT, curr_num); |
history(h, &ev, H_PREV_EVENT, curr_num); |
|
|
return (size); |
return (int)(size); |
} |
} |
|
|
|
|
|
|
rl_display_match_list(char **matches, int len, int max) |
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 * |
static const char * |
Line 1480 _rl_completion_append_character_function |
|
Line 1505 _rl_completion_append_character_function |
|
__attribute__((__unused__))) |
__attribute__((__unused__))) |
{ |
{ |
static char buf[2]; |
static char buf[2]; |
buf[1] = rl_completion_append_character; |
buf[0] = rl_completion_append_character; |
|
buf[1] = '\0'; |
return buf; |
return buf; |
} |
} |
|
|
Line 1508 rl_complete(int ignore __attribute__((__ |
|
Line 1534 rl_complete(int ignore __attribute__((__ |
|
(CPFunction *)rl_completion_entry_function, |
(CPFunction *)rl_completion_entry_function, |
rl_attempted_completion_function, |
rl_attempted_completion_function, |
rl_basic_word_break_characters, rl_special_prefixes, |
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_completion_type, &rl_attempted_completion_over, |
&rl_point, &rl_end); |
&rl_point, &rl_end); |
} |
} |
|
|
rl_add_defun(const char *name, Function *fun, int c) |
rl_add_defun(const char *name, Function *fun, int c) |
{ |
{ |
char dest[8]; |
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; |
return -1; |
map[(unsigned char)c] = fun; |
map[(unsigned char)c] = fun; |
el_set(e, EL_ADDFN, name, name, rl_bind_wrapper); |
el_set(e, EL_ADDFN, name, name, rl_bind_wrapper); |
Line 1664 rl_callback_read_char() |
|
Line 1691 rl_callback_read_char() |
|
} |
} |
|
|
void |
void |
rl_callback_handler_install (const char *prompt, VCPFunction *linefunc) |
rl_callback_handler_install(const char *prompt, VCPFunction *linefunc) |
{ |
{ |
if (e == NULL) { |
if (e == NULL) { |
rl_initialize(); |
rl_initialize(); |
} |
} |
if (rl_prompt) |
(void)rl_set_prompt(prompt); |
free(rl_prompt); |
|
rl_prompt = prompt ? strdup(strchr(prompt, *prompt)) : NULL; |
|
rl_linefunc = linefunc; |
rl_linefunc = linefunc; |
el_set(e, EL_UNBUFFERED, 1); |
el_set(e, EL_UNBUFFERED, 1); |
} |
} |
|
|
rl_callback_handler_remove(void) |
rl_callback_handler_remove(void) |
{ |
{ |
el_set(e, EL_UNBUFFERED, 0); |
el_set(e, EL_UNBUFFERED, 0); |
|
rl_linefunc = NULL; |
} |
} |
|
|
void |
void |
Line 1758 rl_stuff_char(int c) |
|
Line 1784 rl_stuff_char(int c) |
|
static int |
static int |
_rl_event_read_char(EditLine *el, char *cp) |
_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) { |
while (rl_event_hook) { |
|
|
(*rl_event_hook)(); |
(*rl_event_hook)(); |
Line 1794 _rl_event_read_char(EditLine *el, char * |
|
Line 1821 _rl_event_read_char(EditLine *el, char * |
|
} |
} |
if (!rl_event_hook) |
if (!rl_event_hook) |
el_set(el, EL_GETCFN, EL_BUILTIN_GETCFN); |
el_set(el, EL_GETCFN, EL_BUILTIN_GETCFN); |
return(num_read); |
return (int)num_read; |
} |
} |
|
|
static void |
static void |
Line 1802 _rl_update_pos(void) |
|
Line 1829 _rl_update_pos(void) |
|
{ |
{ |
const LineInfo *li = el_line(e); |
const LineInfo *li = el_line(e); |
|
|
rl_point = li->cursor - li->buffer; |
rl_point = (int)(li->cursor - li->buffer); |
rl_end = li->lastchar - 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; |
} |
} |