summaryrefslogtreecommitdiff
path: root/cmd-line-utils/libedit/readline.c
diff options
context:
space:
mode:
Diffstat (limited to 'cmd-line-utils/libedit/readline.c')
-rw-r--r--cmd-line-utils/libedit/readline.c843
1 files changed, 320 insertions, 523 deletions
diff --git a/cmd-line-utils/libedit/readline.c b/cmd-line-utils/libedit/readline.c
index 004fcf7d183..ca8796fbd37 100644
--- a/cmd-line-utils/libedit/readline.c
+++ b/cmd-line-utils/libedit/readline.c
@@ -1,4 +1,4 @@
-/* $NetBSD: readline.c,v 1.49 2005/03/10 19:34:46 christos Exp $ */
+/* $NetBSD: readline.c,v 1.78 2009/02/05 19:15:26 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
@@ -36,25 +29,9 @@
* POSSIBILITY OF SUCH DAMAGE.
*/
-/* AIX requires this to be the first thing in the file. */
-#if defined (_AIX) && !defined (__GNUC__)
- #pragma alloca
-#endif
-
-#include <config.h>
-
-#ifdef __GNUC__
-# undef alloca
-# define alloca(n) __builtin_alloca (n)
-#else
-# ifdef HAVE_ALLOCA_H
-# include <alloca.h>
-# else
-# ifndef _AIX
-extern char *alloca ();
-# endif
-# endif
-#endif
+#include "config.h"
+#if !defined(lint) && !defined(SCCSID)
+#endif /* not lint && not SCCSID */
#include <sys/types.h>
#include <sys/stat.h>
@@ -68,12 +45,23 @@ extern char *alloca ();
#include <limits.h>
#include <errno.h>
#include <fcntl.h>
+#include <setjmp.h>
+#ifdef HAVE_VIS_H
#include <vis.h>
-
-#include "readline/readline.h"
+#else
+#include "np/vis.h"
+#endif
+#ifdef HAVE_ALLOCA_H
+#include <alloca.h>
+#endif
#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'
@@ -94,9 +82,12 @@ FILE *rl_outstream = NULL;
int rl_point = 0;
int rl_end = 0;
char *rl_line_buffer = NULL;
-VFunction *rl_linefunc = 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;
@@ -112,21 +103,23 @@ int rl_attempted_completion_over = 0;
char *rl_basic_word_break_characters = break_chars;
char *rl_completer_word_break_characters = NULL;
char *rl_completer_quote_characters = NULL;
-CPFunction *rl_completion_entry_function = NULL;
+Function *rl_completion_entry_function = NULL;
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.
@@ -150,7 +143,7 @@ int rl_completion_query_items = 100;
* in the parsed text when it is passed to the completion function.
* Shell uses this to help determine what kind of completing to do.
*/
-char *rl_special_prefixes = (char *)NULL;
+char *rl_special_prefixes = NULL;
/*
* This is the character appended to the completed words if at the end of
@@ -160,25 +153,21 @@ int rl_completion_append_character = ' ';
/* stuff below is used internally by libedit for readline emulation */
-/* if not zero, non-unique completions always show list of possible matches */
-static int _rl_complete_show_all = 0;
-
static History *h = NULL;
static EditLine *e = NULL;
static Function *map[256];
-static int el_rl_complete_cmdnum = 0;
+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 **);
static char *_rl_compat_sub(const char *, const char *,
const char *, int);
-static int _rl_complete_internal(int);
-static int _rl_qsort_string_compare(const void *, const void *);
static int _rl_event_read_char(EditLine *, char *);
static void _rl_update_pos(void);
@@ -205,17 +194,50 @@ _move_history(int op)
return (HIST_ENTRY *) NULL;
rl_he.line = ev.str;
- rl_he.data = (histdata_t) &(ev.num);
+ rl_he.data = NULL;
return (&rl_he);
}
/*
+ * 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)
+{
+ if (!prompt)
+ prompt = "";
+ if (rl_prompt != NULL && strcmp(rl_prompt, prompt) == 0)
+ return 0;
+ if (rl_prompt)
+ free(rl_prompt);
+ rl_prompt = strdup(prompt);
+ return rl_prompt == NULL ? -1 : 0;
+}
+
+/*
* initialize rl compat stuff
*/
int
@@ -223,7 +245,6 @@ rl_initialize(void)
{
HistEvent ev;
const LineInfo *li;
- int i;
int editmode = 1;
struct termios t;
@@ -257,9 +278,12 @@ 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;
@@ -291,17 +315,6 @@ rl_initialize(void)
"ReadLine compatible suspend function",
_el_rl_tstp);
el_set(e, EL_BIND, "^Z", "rl_tstp", NULL);
-
- /*
- * Find out where the rl_complete function was added; this is
- * used later to detect that lastcmd was also rl_complete.
- */
- for(i=EL_NUM_FCNS; i < e->el_map.nfunc; i++) {
- if (e->el_map.func[i] == _el_rl_complete) {
- el_rl_complete_cmdnum = i;
- break;
- }
- }
/* read settings from configuration file */
el_source(e, NULL);
@@ -327,9 +340,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;
@@ -340,15 +354,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);
@@ -446,7 +456,7 @@ _rl_compat_sub(const char *str, const char *what, const char *with,
} else
*r++ = *s++;
}
- *r = 0;
+ *r = '\0';
return(result);
}
@@ -467,7 +477,7 @@ get_history_event(const char *cmd, int *cindex, int qchar)
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;
@@ -689,7 +699,7 @@ _history_expand_command(const char *command, size_t offs, size_t cmdlen,
if (aptr)
free(aptr);
- if (*cmd == 0 || (cmd - (command + offs) >= cmdlen)) {
+ if (*cmd == '\0' || ((size_t)(cmd - (command + offs)) >= cmdlen)) {
*result = tmp;
return(1);
}
@@ -699,7 +709,7 @@ _history_expand_command(const char *command, size_t offs, size_t cmdlen,
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);
@@ -708,7 +718,7 @@ _history_expand_command(const char *command, size_t offs, size_t cmdlen,
}
} 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);
@@ -732,6 +742,7 @@ _history_expand_command(const char *command, size_t offs, size_t cmdlen,
what = realloc(from, size);
if (what == NULL) {
free(from);
+ free(tmp);
return 0;
}
len = 0;
@@ -744,6 +755,7 @@ _history_expand_command(const char *command, size_t offs, size_t cmdlen,
(size <<= 1));
if (nwhat == NULL) {
free(what);
+ free(tmp);
return 0;
}
what = nwhat;
@@ -756,10 +768,13 @@ _history_expand_command(const char *command, size_t offs, size_t cmdlen,
free(what);
if (search) {
from = strdup(search);
- if (from == NULL)
+ if (from == NULL) {
+ free(tmp);
return 0;
+ }
} else {
from = NULL;
+ free(tmp);
return (-1);
}
}
@@ -771,6 +786,7 @@ _history_expand_command(const char *command, size_t offs, size_t cmdlen,
with = realloc(to, size);
if (with == NULL) {
free(to);
+ free(tmp);
return -1;
}
len = 0;
@@ -782,6 +798,7 @@ _history_expand_command(const char *command, size_t offs, size_t cmdlen,
nwith = realloc(with, size);
if (nwith == NULL) {
free(with);
+ free(tmp);
return -1;
}
with = nwith;
@@ -850,12 +867,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; \
@@ -867,6 +886,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;
@@ -904,13 +924,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
@@ -920,8 +938,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;
}
@@ -973,23 +994,23 @@ history_arg_extract(int start, int end, const char *str)
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]);
@@ -1152,7 +1173,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;
@@ -1185,6 +1206,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
@@ -1377,172 +1423,18 @@ history_search_pos(const char *str,
/********************************/
/* completion functions */
-/*
- * does tilde expansion of strings of type ``~user/foo''
- * if ``user'' isn't valid user name or ``txt'' doesn't start
- * w/ '~', returns pointer to strdup()ed copy of ``txt''
- *
- * it's callers's responsibility to free() returned string
- */
char *
-tilde_expand(char *txt)
+tilde_expand(char *name)
{
- struct passwd *pass;
- char *temp;
- size_t len = 0;
-
- if (txt[0] != '~')
- return (strdup(txt));
-
- temp = strchr(txt + 1, '/');
- if (temp == NULL) {
- temp = strdup(txt + 1);
- if (temp == NULL)
- return NULL;
- } else {
- len = temp - txt + 1; /* text until string after slash */
- temp = malloc(len);
- if (temp == NULL)
- return NULL;
- (void)strncpy(temp, txt + 1, len - 2);
- temp[len - 2] = '\0';
- }
- pass = getpwnam(temp);
- free(temp); /* value no more needed */
- if (pass == NULL)
- return (strdup(txt));
-
- /* update pointer txt to point at string immedially following */
- /* first slash */
- txt += len;
-
- temp = malloc(strlen(pass->pw_dir) + 1 + strlen(txt) + 1);
- if (temp == NULL)
- return NULL;
- (void)sprintf(temp, "%s/%s", pass->pw_dir, txt);
-
- return (temp);
+ return fn_tilde_expand(name);
}
-
-/*
- * return first found file name starting by the ``text'' or NULL if no
- * such file can be found
- * value of ``state'' is ignored
- *
- * it's caller's responsibility to free returned string
- */
char *
-filename_completion_function(const char *text, int state)
+filename_completion_function(const char *name, int state)
{
- static DIR *dir = NULL;
- static char *filename = NULL, *dirname = NULL;
- static size_t filename_len = 0;
- struct dirent *entry;
- char *temp;
- size_t len;
-
- if (state == 0 || dir == NULL) {
- temp = strrchr(text, '/');
- if (temp) {
- char *nptr;
- temp++;
- nptr = realloc(filename, strlen(temp) + 1);
- if (nptr == NULL) {
- free(filename);
- return NULL;
- }
- filename = nptr;
- (void)strcpy(filename, temp);
- len = temp - text; /* including last slash */
- nptr = realloc(dirname, len + 1);
- if (nptr == NULL) {
- free(filename);
- return NULL;
- }
- dirname = nptr;
- (void)strncpy(dirname, text, len);
- dirname[len] = '\0';
- } else {
- if (*text == 0)
- filename = NULL;
- else {
- filename = strdup(text);
- if (filename == NULL)
- return NULL;
- }
- dirname = NULL;
- }
-
- /* support for ``~user'' syntax */
- if (dirname && *dirname == '~') {
- char *nptr;
- temp = tilde_expand(dirname);
- if (temp == NULL)
- return NULL;
- nptr = realloc(dirname, strlen(temp) + 1);
- if (nptr == NULL) {
- free(dirname);
- return NULL;
- }
- dirname = nptr;
- (void)strcpy(dirname, temp); /* safe */
- free(temp); /* no longer needed */
- }
- /* will be used in cycle */
- filename_len = filename ? strlen(filename) : 0;
-
- if (dir != NULL) {
- (void)closedir(dir);
- dir = NULL;
- }
- dir = opendir(dirname ? dirname : ".");
- if (!dir)
- return (NULL); /* cannot open the directory */
- }
- /* find the match */
- while ((entry = readdir(dir)) != NULL) {
- /* skip . and .. */
- if (entry->d_name[0] == '.' && (!entry->d_name[1]
- || (entry->d_name[1] == '.' && !entry->d_name[2])))
- continue;
- if (filename_len == 0)
- break;
- /* otherwise, get first entry where first */
- /* filename_len characters are equal */
- if (entry->d_name[0] == filename[0]
- /* Some dirents have d_namlen, but it is not portable. */
- && strlen(entry->d_name) >= filename_len
- && strncmp(entry->d_name, filename,
- filename_len) == 0)
- break;
- }
-
- if (entry) { /* match found */
-
- struct stat stbuf;
- /* Some dirents have d_namlen, but it is not portable. */
- len = strlen(entry->d_name) +
- ((dirname) ? strlen(dirname) : 0) + 1 + 1;
- temp = malloc(len);
- if (temp == NULL)
- return NULL;
- (void)sprintf(temp, "%s%s",
- dirname ? dirname : "", entry->d_name); /* safe */
-
- /* test, if it's directory */
- if (stat(temp, &stbuf) == 0 && S_ISDIR(stbuf.st_mode))
- strcat(temp, "/"); /* safe */
- } else {
- (void)closedir(dir);
- dir = NULL;
- temp = NULL;
- }
-
- return (temp);
+ return fn_filename_completion_function(name, state);
}
-
/*
* a completion generator for usernames; returns _first_ username
* which starts with supplied text
@@ -1564,6 +1456,7 @@ username_completion_function(const char *text, int state)
if (state == 0)
setpwent();
+ /* XXXMYSQL: just use non-_r functions for now */
while ((pwd = getpwent()) && text[0] == pwd->pw_name[0]
&& strcmp(text, pwd->pw_name) == 0);
@@ -1576,16 +1469,6 @@ username_completion_function(const char *text, int state)
/*
- * el-compatible wrapper around rl_complete; needed for key binding
- */
-/* ARGSUSED */
-static unsigned char
-_el_rl_complete(EditLine *el __attribute__((__unused__)), int ch)
-{
- return (unsigned char) rl_complete(0, ch);
-}
-
-/*
* el-compatible wrapper to send TSTP on ^Z
*/
/* ARGSUSED */
@@ -1597,272 +1480,35 @@ _el_rl_tstp(EditLine *el __attribute__((__unused__)), int ch __attribute__((__un
}
/*
- * returns list of completions for text given
- */
-char **
-completion_matches(const char *text, CPFunction *genfunc)
-{
- char **match_list = NULL, *retstr, *prevstr;
- size_t match_list_len, max_equal, which, i;
- size_t matches;
-
- if (h == NULL || e == NULL)
- rl_initialize();
-
- matches = 0;
- match_list_len = 1;
- while ((retstr = (*genfunc) (text, (int)matches)) != NULL) {
- /* allow for list terminator here */
- if (matches + 3 >= match_list_len) {
- char **nmatch_list;
- while (matches + 3 >= match_list_len)
- match_list_len <<= 1;
- nmatch_list = realloc(match_list,
- match_list_len * sizeof(char *));
- if (nmatch_list == NULL) {
- free(match_list);
- return NULL;
- }
- match_list = nmatch_list;
-
- }
- match_list[++matches] = retstr;
- }
-
- if (!match_list)
- return NULL; /* nothing found */
-
- /* find least denominator and insert it to match_list[0] */
- which = 2;
- prevstr = match_list[1];
- max_equal = strlen(prevstr);
- for (; which <= matches; which++) {
- for (i = 0; i < max_equal &&
- prevstr[i] == match_list[which][i]; i++)
- continue;
- max_equal = i;
- }
-
- retstr = malloc(max_equal + 1);
- if (retstr == NULL) {
- free(match_list);
- return NULL;
- }
- (void)strncpy(retstr, match_list[1], max_equal);
- retstr[max_equal] = '\0';
- match_list[0] = retstr;
-
- /* add NULL as last pointer to the array */
- match_list[matches + 1] = (char *) NULL;
-
- return (match_list);
-}
-
-/*
- * Sort function for qsort(). Just wrapper around strcasecmp().
- */
-static int
-_rl_qsort_string_compare(i1, i2)
- const void *i1, *i2;
-{
- const char *s1 = ((const char * const *)i1)[0];
- const char *s2 = ((const char * const *)i2)[0];
-
- return strcasecmp(s1, s2);
-}
-
-/*
* Display list of strings in columnar format on readline's output stream.
* 'matches' is list of strings, 'len' is number of strings in 'matches',
* 'max' is maximum length of string in 'matches'.
*/
void
-rl_display_match_list (matches, len, max)
- char **matches;
- int len, max;
+rl_display_match_list(char **matches, int len, int max)
{
- int i, idx, limit, count;
- int screenwidth = e->el_term.t_size.h;
- /*
- * Find out how many entries can be put on one line, count
- * with two spaces between strings.
- */
- limit = screenwidth / (max + 2);
- if (limit == 0)
- limit = 1;
-
- /* how many lines of output */
- count = len / limit;
- if (count * limit < len)
- count++;
-
- /* Sort the items if they are not already sorted. */
- qsort(&matches[1], (size_t)(len - 1), sizeof(char *),
- _rl_qsort_string_compare);
-
- idx = 1;
- for(; count > 0; count--) {
- for(i = 0; i < limit && matches[idx]; i++, idx++)
- (void)fprintf(e->el_outfile, "%-*s ", max,
- matches[idx]);
- (void)fprintf(e->el_outfile, "\n");
- }
+ fn_display_match_list(e, matches, len, max);
}
-/*
- * Complete the word at or before point, called by rl_complete()
- * 'what_to_do' says what to do with the completion.
- * `?' means list the possible completions.
- * TAB means do standard completion.
- * `*' means insert all of the possible completions.
- * `!' means to do standard completion, and list all possible completions if
- * there is more than one.
- *
- * Note: '*' support is not implemented
- */
-static int
-_rl_complete_internal(int what_to_do)
+static const char *
+/*ARGSUSED*/
+_rl_completion_append_character_function(const char *dummy
+ __attribute__((__unused__)))
{
- CPFunction *complet_func;
- const LineInfo *li;
- char *temp, **matches;
- const char *ctemp;
- size_t len;
-
- rl_completion_type = what_to_do;
-
- if (h == NULL || e == NULL)
- rl_initialize();
-
- complet_func = rl_completion_entry_function;
- if (!complet_func)
- complet_func = filename_completion_function;
-
- /* We now look backwards for the start of a filename/variable word */
- li = el_line(e);
- ctemp = (const char *) li->cursor;
- while (ctemp > li->buffer
- && !strchr(rl_basic_word_break_characters, ctemp[-1])
- && (!rl_special_prefixes
- || !strchr(rl_special_prefixes, ctemp[-1]) ) )
- ctemp--;
-
- len = li->cursor - ctemp;
- temp = alloca(len + 1);
- (void)strncpy(temp, ctemp, len);
- temp[len] = '\0';
-
- /* these can be used by function called in completion_matches() */
- /* or (*rl_attempted_completion_function)() */
- _rl_update_pos();
-
- if (rl_attempted_completion_function) {
- int end = li->cursor - li->buffer;
- matches = (*rl_attempted_completion_function) (temp, (int)
- (end - len), end);
- } else
- matches = 0;
- if (!rl_attempted_completion_function || !matches)
- matches = completion_matches(temp, complet_func);
-
- if (matches) {
- int i, retval = CC_REFRESH;
- int matches_num, maxlen, match_len, match_display=1;
-
- /*
- * Only replace the completed string with common part of
- * possible matches if there is possible completion.
- */
- if (matches[0][0] != '\0') {
- el_deletestr(e, (int) len);
- el_insertstr(e, matches[0]);
- }
-
- if (what_to_do == '?')
- goto display_matches;
-
- if (matches[2] == NULL && strcmp(matches[0], matches[1]) == 0) {
- /*
- * We found exact match. Add a space after
- * it, unless we do filename completion and the
- * object is a directory.
- */
- size_t alen = strlen(matches[0]);
- if ((complet_func != filename_completion_function
- || (alen > 0 && (matches[0])[alen - 1] != '/'))
- && rl_completion_append_character) {
- char buf[2];
- buf[0] = rl_completion_append_character;
- buf[1] = '\0';
- el_insertstr(e, buf);
- }
- } else if (what_to_do == '!') {
- display_matches:
- /*
- * More than one match and requested to list possible
- * matches.
- */
-
- for(i=1, maxlen=0; matches[i]; i++) {
- match_len = strlen(matches[i]);
- if (match_len > maxlen)
- maxlen = match_len;
- }
- matches_num = i - 1;
-
- /* newline to get on next line from command line */
- (void)fprintf(e->el_outfile, "\n");
-
- /*
- * If there are too many items, ask user for display
- * confirmation.
- */
- if (matches_num > rl_completion_query_items) {
- (void)fprintf(e->el_outfile,
- "Display all %d possibilities? (y or n) ",
- matches_num);
- (void)fflush(e->el_outfile);
- if (getc(stdin) != 'y')
- match_display = 0;
- (void)fprintf(e->el_outfile, "\n");
- }
-
- if (match_display)
- rl_display_match_list(matches, matches_num,
- maxlen);
- retval = CC_REDISPLAY;
- } else if (matches[0][0]) {
- /*
- * There was some common match, but the name was
- * not complete enough. Next tab will print possible
- * completions.
- */
- el_beep(e);
- } else {
- /* lcd is not a valid object - further specification */
- /* is needed */
- el_beep(e);
- retval = CC_NORM;
- }
-
- /* free elements of array and the array itself */
- for (i = 0; matches[i]; i++)
- free(matches[i]);
- free(matches), matches = NULL;
-
- return (retval);
- }
- return (CC_NORM);
+ static char buf[2];
+ buf[0] = rl_completion_append_character;
+ buf[1] = '\0';
+ return buf;
}
/*
* complete word at current point
*/
+/* ARGSUSED */
int
-/*ARGSUSED*/
-rl_complete(int ignore, int invoking_key)
+rl_complete(int ignore __attribute__((__unused__)), int invoking_key)
{
if (h == NULL || e == NULL)
rl_initialize();
@@ -1873,15 +1519,26 @@ rl_complete(int ignore, int invoking_key)
arr[1] = '\0';
el_insertstr(e, arr);
return (CC_REFRESH);
- } else if (e->el_state.lastcmd == el_rl_complete_cmdnum)
- return _rl_complete_internal('?');
- else if (_rl_complete_show_all)
- return _rl_complete_internal('!');
- else
- return _rl_complete_internal(TAB);
+ }
+
+ /* Just look at how many global variables modify this operation! */
+ return fn_complete(e,
+ (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_type, &rl_attempted_completion_over,
+ &rl_point, &rl_end);
}
+/* ARGSUSED */
+static unsigned char
+_el_rl_complete(EditLine *el __attribute__((__unused__)), int ch)
+{
+ return (unsigned char)rl_complete(0, ch);
+}
+
/*
* misc other functions
*/
@@ -1989,7 +1646,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);
@@ -2007,11 +1664,7 @@ rl_callback_read_char()
if (buf == NULL || count-- <= 0)
return;
-#ifdef CTRL2 /* _AIX */
- if (count == 0 && buf[0] == CTRL2('d'))
-#else
- if (count == 0 && buf[0] == CTRL('d'))
-#endif
+ 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;
@@ -2029,14 +1682,12 @@ rl_callback_read_char()
}
void
-rl_callback_handler_install (const char *prompt, VFunction *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);
}
@@ -2045,17 +1696,14 @@ void
rl_callback_handler_remove(void)
{
el_set(e, EL_UNBUFFERED, 0);
+ rl_linefunc = NULL;
}
void
rl_redisplay(void)
{
char a[2];
-#ifdef CTRL2 /* _AIX */
- a[0] = CTRL2('r');
-#else
- a[0] = CTRL('r');
-#endif
+ a[0] = e->el_tty.t_c[TS_IO][C_REPRINT];
a[1] = '\0';
el_push(e, a);
}
@@ -2079,7 +1727,7 @@ rl_prep_terminal(int meta_flag)
}
void
-rl_deprep_terminal()
+rl_deprep_terminal(void)
{
el_set(e, EL_PREP_TERM, 0);
}
@@ -2104,6 +1752,16 @@ rl_parse_and_bind(const char *line)
return (argc ? 1 : 0);
}
+int
+rl_variable_bind(const char *var, const char *value)
+{
+ /*
+ * The proper return value is undocument, but this is what the
+ * readline source seems to do.
+ */
+ return ((el_set(e, EL_BIND, "", var, value) == -1) ? 1 : 0);
+}
+
void
rl_stuff_char(int c)
{
@@ -2119,7 +1777,7 @@ _rl_event_read_char(EditLine *el, char *cp)
{
int n, num_read = 0;
- *cp = 0;
+ *cp = '\0';
while (rl_event_hook) {
(*rl_event_hook)();
@@ -2164,3 +1822,142 @@ _rl_update_pos(void)
rl_point = li->cursor - li->buffer;
rl_end = 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) {
+ if (len == max) {
+ char **nl;
+ max += 10;
+ if ((nl = realloc(list, max * sizeof(*nl))) == NULL)
+ goto out;
+ list = nl;
+ }
+ list[len++] = match;
+ }
+ 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;
+}